changes
This commit is contained in:
parent
53b11dfca0
commit
e10ee70d4a
40
index.js
40
index.js
|
@ -1,14 +1,12 @@
|
|||
import moment from 'moment';
|
||||
import * as vnUtils from './utils.js';
|
||||
import cliProgress from 'cli-progress';
|
||||
//import cliProgress from 'cli-progress';
|
||||
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config();
|
||||
|
||||
import { models } from './models/index.js';
|
||||
|
||||
import suppliers from './suppliersGln.js';
|
||||
|
||||
console.log = function () {
|
||||
let args = Array.prototype.slice.call(arguments);
|
||||
args.unshift(new moment().format('HH:mm:ss') + ' -');
|
||||
|
@ -17,48 +15,22 @@ console.log = function () {
|
|||
|
||||
let tokenExpirationDate = await vnUtils.getClientToken(models);
|
||||
|
||||
process.env.SYNC_SEQUENCE ? await vnUtils.syncSequence() : null;
|
||||
process.env.SYNC_SUPPLIER ? await vnUtils.syncSuppliers() : null;
|
||||
process.env.SYNC_TRADEITEM ? await vnUtils.syncTradeItems() : null;
|
||||
|
||||
try {
|
||||
|
||||
if (process.env.QUERYSUPPLIERS) {
|
||||
|
||||
process.env.HowManySuppliers ??= suppliers.suppliers.length;
|
||||
|
||||
console.log('Querying suppliers...');
|
||||
console.log(process.env.HowManySuppliers + ' suppliers will be queried.');
|
||||
|
||||
const bar1 = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
|
||||
bar1.start(process.env.HowManySuppliers, 0);
|
||||
|
||||
let functionQueue = [];
|
||||
|
||||
// vnUtils.getTradeitems(suppliers.suppliers[i].SupplierGLN)
|
||||
for (let i = 0; i < process.env.HowManySuppliers; i++) {
|
||||
functionQueue.push(async () => {
|
||||
await vnUtils.getTradeitems(suppliers.suppliers[i].SupplierGLN);
|
||||
bar1.increment();
|
||||
});
|
||||
}
|
||||
|
||||
await vnUtils.asyncQueue(functionQueue, 10);
|
||||
|
||||
bar1.stop();
|
||||
|
||||
console.log('Done querying trade items.');
|
||||
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-constant-condition
|
||||
while (true) {
|
||||
try{
|
||||
console.log('Querying the API to check for new data...');
|
||||
console.log('Current token expiration date: ', tokenExpirationDate);
|
||||
|
||||
await vnUtils.getStock();
|
||||
|
||||
if (moment().isAfter(tokenExpirationDate)) {
|
||||
console.log('Token expired, getting a new one...');
|
||||
tokenExpirationDate = await vnUtils.getClientToken(models);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import { Sequelize } from 'sequelize';
|
||||
|
||||
const sequenceNumber = {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
},
|
||||
sequenceNumber: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
maximumSequenceNumber: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
defaultValue: 0,
|
||||
},
|
||||
model: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
};
|
||||
|
||||
export default (sequelize) => {
|
||||
const sequenceNumbers = sequelize.define(
|
||||
'FDsequenceNumber',
|
||||
sequenceNumber,
|
||||
{
|
||||
timestamps: false,
|
||||
freezeTableName: true,
|
||||
}
|
||||
);
|
||||
return sequenceNumbers;
|
||||
};
|
|
@ -4,24 +4,36 @@ dotenv.config();
|
|||
|
||||
let sequelize = createConnection();
|
||||
|
||||
// Supply Line Models
|
||||
import supplyLine from './supplyLine/supplyLine.js';
|
||||
import volumePrices from './supplyLine/volumePrices.js';
|
||||
|
||||
// Conf Models
|
||||
import clientConfig from './conf/clientConfig.js';
|
||||
import sequenceNumber from './conf/sequenceNumber.js';
|
||||
|
||||
// Supplier Models
|
||||
import suppliers from './supplier/suppliers.js';
|
||||
import connections from './supplier/connections.js';
|
||||
|
||||
// TradeItem Models
|
||||
import tradeItem from './tradeItem/tradeItem.js';
|
||||
import botanicalNames from './tradeItem/botanicalNames.js';
|
||||
import countryOfOriginIsoCodes from './tradeItem/countryOfOriginIsoCodes.js';
|
||||
import packageModel from './tradeItem/package.js';
|
||||
import packingConfigurations from './tradeItem/packingConfigurations.js';
|
||||
import photos from './tradeItem/photos.js';
|
||||
import seasonalPeriod from './tradeItem/seasonalPeriod.js';
|
||||
import tradeItem from './tradeItem/tradeItem.js';
|
||||
import clientConfig from './conf/clientConfig.js';
|
||||
import characteristics from './tradeItem/characteristics.js';
|
||||
import supplyLine from './supplyLine/supplyLine.js';
|
||||
import volumePrices from './supplyLine/volumePrices.js';
|
||||
import suppliers from './supplier/suppliers.js';
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Contains all the models that are related to the application.
|
||||
*
|
||||
* @example
|
||||
* models.tradeItem.findAll();
|
||||
* models.@modelName@.findAll();
|
||||
*
|
||||
* @example
|
||||
* models.tradeItem.findAll().then((data) => {
|
||||
|
@ -38,6 +50,7 @@ import suppliers from './supplier/suppliers.js';
|
|||
* @type {Object.<string, Sequelize.Model>}
|
||||
*/
|
||||
let models = {
|
||||
sequelize: sequelize,
|
||||
tradeItem: tradeItem(sequelize),
|
||||
packingConfigurations: packingConfigurations(sequelize),
|
||||
photos: photos(sequelize),
|
||||
|
@ -50,6 +63,8 @@ let models = {
|
|||
supplyLines: supplyLine(sequelize),
|
||||
volumePrices: volumePrices(sequelize),
|
||||
suppliers: suppliers(sequelize),
|
||||
sequenceNumber: sequenceNumber(sequelize),
|
||||
connections: connections(sequelize),
|
||||
};
|
||||
|
||||
models.characteristics.belongsTo(models.tradeItem, {
|
||||
|
@ -125,9 +140,12 @@ models.supplyLines.belongsTo(models.tradeItem, {
|
|||
targetKey: 'tradeItemId',
|
||||
});
|
||||
|
||||
if (process.env.FORCE_SYNC) {
|
||||
console.log('Syncing the models...');
|
||||
if (process.env.FORCE_SYNC == true) {
|
||||
console.log('Forcing the models...');
|
||||
await sequelize.sync({ force: true });
|
||||
} else {
|
||||
console.log('Altering the models...');
|
||||
await sequelize.sync({ alter: true });
|
||||
}
|
||||
|
||||
if (process.env.SECRETS) {
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import { Sequelize } from 'sequelize';
|
||||
|
||||
const connections = {
|
||||
organizationId: {
|
||||
type: Sequelize.STRING,
|
||||
primaryKey: true,
|
||||
allowNull: false,
|
||||
},
|
||||
connect: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false,
|
||||
},
|
||||
};
|
||||
|
||||
export default (sequelize) => {
|
||||
const connection = sequelize.define(
|
||||
'FDconnections',
|
||||
connections,
|
||||
{
|
||||
timestamps: false,
|
||||
freezeTableName: true,
|
||||
}
|
||||
);
|
||||
return connection;
|
||||
};
|
|
@ -1,16 +1,56 @@
|
|||
import { Sequelize } from 'sequelize';
|
||||
|
||||
const suppliers = {
|
||||
id: {
|
||||
type: Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true,
|
||||
isConnected: {
|
||||
type: Sequelize.BOOLEAN,
|
||||
defaultValue: false,
|
||||
},
|
||||
supplierId: {
|
||||
commercialName: {
|
||||
type: Sequelize.STRING,
|
||||
unique: true,
|
||||
allowNull: false,
|
||||
},
|
||||
supplierGln: {
|
||||
email: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
phone: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
website: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
mailingAddress: {
|
||||
type: Sequelize.JSON,
|
||||
},
|
||||
physicalAddress: {
|
||||
type: Sequelize.JSON,
|
||||
},
|
||||
pythosanitaryNumber: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
sequenceNumber: {
|
||||
type: Sequelize.INTEGER,
|
||||
allowNull: false,
|
||||
},
|
||||
organizationId: {
|
||||
type: Sequelize.STRING,
|
||||
primaryKey: true,
|
||||
},
|
||||
companyGln: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
name: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
endDate: {
|
||||
type: Sequelize.DATE,
|
||||
},
|
||||
rfhRelationId: {
|
||||
type: Sequelize.INTEGER,
|
||||
},
|
||||
organizationType: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
paymentProviders: {
|
||||
type: Sequelize.STRING,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"dev-sync": "FORCE_SYNC=true node --max-old-space-size=4096 index.js",
|
||||
"dev-secrets": "SECRETS=true node --max-old-space-size=4096 index.js",
|
||||
"dev-both": "FORCE_SYNC=true SECRETS=true node --max-old-space-size=4096 index.js",
|
||||
"dev-query": "QUERYSUPPLIERS=true FORCE_SYNC=true SECRETS=true node --max-old-space-size=4096 index.js"
|
||||
"dev-query": "QUERYSUPPLIERS=true SECRETS=true node --max-old-space-size=4096 index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"cli-progress": "^3.11.2",
|
||||
|
|
4467
suppliersGln.js
4467
suppliersGln.js
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"commercialName": "Viveros Las Cunas",
|
||||
"email": null,
|
||||
"phone": null,
|
||||
"website": null,
|
||||
"mailingAddress": {
|
||||
"addressLine": "Carretera 0A-352",
|
||||
"city": "Vera - Almeria",
|
||||
"countryCode": "ES",
|
||||
"postalCode": "04620",
|
||||
"stateOrProvince": null
|
||||
},
|
||||
"physicalAddress": {
|
||||
"addressLine": "Carretera 0A-352",
|
||||
"city": "Vera - Almeria",
|
||||
"countryCode": "ES",
|
||||
"postalCode": "04620",
|
||||
"stateOrProvince": null
|
||||
},
|
||||
"phytosanitaryNumber": null,
|
||||
"sequenceNumber": 195803,
|
||||
"organizationId": "ebc1894a-c3be-3a19-9de2-40b2e691cc9f",
|
||||
"companyGln": "8718288089847",
|
||||
"name": "Viveros Las Cunas",
|
||||
"endDate": null,
|
||||
"rfhRelationId": 0,
|
||||
"organizationType": "SUPPLIER",
|
||||
"paymentProviders": []
|
||||
}
|
626
utils.js
626
utils.js
|
@ -2,8 +2,9 @@ import moment from 'moment';
|
|||
import fetch from 'node-fetch';
|
||||
import dotenv from 'dotenv';
|
||||
import { models } from './models/index.js';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import cliProgress from 'cli-progress';
|
||||
//import { v4 as uuidv4 } from 'uuid';
|
||||
//import cliProgress from 'cli-progress';
|
||||
import suppliersGln from './suppliersGln.js';
|
||||
dotenv.config();
|
||||
|
||||
/**
|
||||
|
@ -86,6 +87,7 @@ async function updateClientConfig(clientId, clientSecret, accessToken, tokenExpi
|
|||
clientSecret: clientSecret,
|
||||
currentToken: accessToken,
|
||||
tokenExpiration: tokenExpirationDate,
|
||||
requestLimit : 500
|
||||
},
|
||||
{
|
||||
where: {
|
||||
|
@ -123,25 +125,6 @@ async function sleep(ms) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the uuidv4 string with the prefix 'Vn-'
|
||||
*
|
||||
* @param {string} uuidv4 - uuidv4 string
|
||||
* @returns
|
||||
*/
|
||||
async function vnUuid(uuidv4) {
|
||||
return 'Vn-' + uuidv4;
|
||||
}
|
||||
/**
|
||||
* Returns the uuidv4 string without the prefix 'Vn-'
|
||||
*
|
||||
* @param {string} uuidv4 - uuidv4 string with prefix 'Vn-'
|
||||
* @returns
|
||||
*/
|
||||
async function removeVnPrefix(uuidv4) {
|
||||
return uuidv4.replace('Vn-', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Recieves an array of functions and executes them in a queue with the given concurrency
|
||||
*
|
||||
|
@ -179,425 +162,252 @@ async function asyncQueue(fnArray, concurrency = 1) {
|
|||
// 4. Execute the run function while the concurrency is greater than 0
|
||||
// 5. Return the results
|
||||
|
||||
|
||||
/**
|
||||
* Syncs the sequence number for the given model
|
||||
* if no params are given it will reset all the sequence number to 0
|
||||
*
|
||||
* Inserts every tradeitem from the organization into the DB
|
||||
*
|
||||
* @param {*} organizationGln
|
||||
* @param {Number} current - current sequence number
|
||||
* @param {String} model - model name
|
||||
* @param {Number} maximumSequenceNumber - maximum sequence number
|
||||
* @returns
|
||||
*/
|
||||
async function getTradeitems(organizationGln) {
|
||||
async function syncSequence(current = 0, model = null ,maximumSequenceNumber = 0){
|
||||
if (model == null && current == 0){
|
||||
|
||||
let mockModels = ['suppliers','tradeItems','supplyLines',];
|
||||
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + await getJWT(),
|
||||
'X-Api-Key': process.env.API_KEY,
|
||||
};
|
||||
|
||||
// Get the organization id from the organizationGln
|
||||
|
||||
const organizationsUrl = `${BASE_CUSTOMER_URL}organizations/gln/${organizationGln}`;
|
||||
const organizationsRequest = await fetch(organizationsUrl, {
|
||||
method: 'GET',
|
||||
headers: headers,
|
||||
});
|
||||
|
||||
const organizationsResponse = await organizationsRequest.json();
|
||||
|
||||
const organizationId = organizationsResponse.organizationId;
|
||||
console.log('Organization ID: ', organizationId);
|
||||
|
||||
// Get the tradeitems from the organization
|
||||
|
||||
const tradeitemsUrl = `${BASE_CUSTOMER_URL}trade-items?supplierOrganizationId=${organizationId}`;
|
||||
const tradeitemsRequest = await fetch(tradeitemsUrl, {
|
||||
method: 'GET',
|
||||
headers: headers,
|
||||
});
|
||||
|
||||
const tradeitemsResponse = await tradeitemsRequest.json();
|
||||
|
||||
// If there is no tradeitems
|
||||
if (tradeitemsResponse.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if there is at least one tradeitem, save it in the database
|
||||
|
||||
//console.log(tradeitemsResponse[0]);
|
||||
|
||||
try {
|
||||
|
||||
if (tradeitemsResponse.length > 0 && tradeitemsResponse != null) {
|
||||
|
||||
let bar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_grey);
|
||||
bar.start(tradeitemsResponse.length, 0);
|
||||
|
||||
await tradeitemsResponse.forEach(async item => {
|
||||
|
||||
bar.increment();
|
||||
|
||||
try {
|
||||
|
||||
item.tradeItemId = await vnUuid(item.tradeItemId);
|
||||
|
||||
await models.suppliers.upsert({
|
||||
supplierId: await vnUuid(organizationId),
|
||||
supplierGln: organizationGln,
|
||||
});
|
||||
|
||||
await models.tradeItem.upsert({
|
||||
tradeItemId: item.tradeItemId,
|
||||
supplierOrganizationId: organizationGln,
|
||||
supplierOrganizationUuid: await vnUuid(organizationId),
|
||||
code: item.code,
|
||||
gtin: item.gtin,
|
||||
vbnProductCode: item.vbnProductCode,
|
||||
name: item.name,
|
||||
isDeleted: item.isDeleted,
|
||||
sequenceNumber: item.sequenceNumber,
|
||||
tradeItemVersion: item.tradeItemVersion,
|
||||
isCustomerSpecific: item.isCustomerSpecific,
|
||||
isHiddenInCatalog: item.isHiddenInCatalog,
|
||||
});
|
||||
|
||||
await item.characteristics.forEach((characteristic) => {
|
||||
models.characteristics.upsert({
|
||||
tradeItemFk: item.tradeItemId,
|
||||
vbnCode: characteristic.vbnCode,
|
||||
vbnValueCode: characteristic.vbnValueCode,
|
||||
});
|
||||
});
|
||||
|
||||
await item.seasonalPeriods.forEach((seasonalPeriod) => {
|
||||
models.seasonalPeriod.upsert({
|
||||
tradeItemFk: item.tradeItemId,
|
||||
startWeek: seasonalPeriod.startWeek,
|
||||
endWeek: seasonalPeriod.endWeek,
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
await item.photos.forEach(async (photo) => {
|
||||
|
||||
photo.id = await vnUuid(photo.id);
|
||||
|
||||
models.photos.upsert({
|
||||
tradeItemFk: item.tradeItemId,
|
||||
photoId: photo.id,
|
||||
url: photo.url,
|
||||
seasonalPeriodFk: JSON.stringify(photo.seasonalPeriod),
|
||||
type: photo.type,
|
||||
primary: photo.primary,
|
||||
});
|
||||
});
|
||||
|
||||
await item.packingConfigurations.forEach(async (packagingConfiguration) => {
|
||||
|
||||
let uuid = uuidv4();
|
||||
uuid = await vnUuid(uuid);
|
||||
|
||||
await models.packingConfigurations.upsert({
|
||||
tradeItemFk: item.tradeItemId,
|
||||
packingConfigurationId: uuid,
|
||||
piecesPerPackage: packagingConfiguration.piecesPerPackage,
|
||||
bunchesPerPackage: packagingConfiguration.bunchesPerPackage,
|
||||
photoUrl: packagingConfiguration.photoUrl,
|
||||
packagesPerLayer: packagingConfiguration.packagesPerLayer,
|
||||
layersPerLoadCarrier: packagingConfiguration.layersPerLoadCarrier,
|
||||
transportHeightInCm: packagingConfiguration.transportHeightInCm,
|
||||
loadCarrierType: packagingConfiguration.loadCarrierType,
|
||||
isPrimary: packagingConfiguration.isPrimary,
|
||||
additionalPricePerPiece: JSON.stringify(packagingConfiguration.additionalPricePerPiece),
|
||||
});
|
||||
|
||||
await models.package.upsert({
|
||||
packingConfigurationsId: uuid,
|
||||
vbnPackageCode: packagingConfiguration.package.vbnPackageCode,
|
||||
vbnPackageValueCode: packagingConfiguration.package.vbnPackageValueCode,
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
await item.botanicalNames.forEach((botanicalName) => {
|
||||
models.botanicalNames.upsert({
|
||||
tradeItemFk: item.tradeItemId,
|
||||
name: botanicalName,
|
||||
});
|
||||
});
|
||||
|
||||
await item.countryOfOriginIsoCodes.forEach((countryOfOriginIsoCode) => {
|
||||
models.countryOfOriginIsoCodes.upsert({
|
||||
tradeItemFk: item.tradeItemId,
|
||||
isoCode: countryOfOriginIsoCode,
|
||||
});
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.log('Missing data for the tradeitem: ' + item.tradeItemId);
|
||||
bar.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
});
|
||||
bar.stop();
|
||||
for (let i = 0; i < mockModels.length; i++) {
|
||||
const element = mockModels[i];
|
||||
console.log('Syncing sequence for: ', element);
|
||||
await syncSequence(0, element);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log('There was an error while saving the data to the database, trying again in 5 seconds...');
|
||||
await sleep(5000);
|
||||
await getTradeitems(organizationGln);
|
||||
} else {
|
||||
|
||||
let tx = await models.sequelize.transaction();
|
||||
|
||||
try {
|
||||
|
||||
await models.sequenceNumber.upsert({
|
||||
model: model,
|
||||
sequenceNumber: current,
|
||||
maximumSequenceNumber: maximumSequenceNumber
|
||||
},{ transaction: tx });
|
||||
|
||||
await tx.commit();
|
||||
|
||||
} catch (error) {
|
||||
await tx.rollback();
|
||||
console.log('Error while syncing sequence number for: ', model);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a single tradeitem from the API and inserts it into the database
|
||||
*
|
||||
* @param {*} tradeItemId
|
||||
*/
|
||||
async function getTradeItem(tradeItemId) {
|
||||
async function syncSuppliers(){
|
||||
|
||||
try {
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${await getJWT()}`,
|
||||
'X-Api-Key': process.env.API_KEY,
|
||||
};
|
||||
|
||||
const tradeitemUrl = `${BASE_CUSTOMER_URL}trade-items/${tradeItemId}`;
|
||||
|
||||
const tradeitemRequest = await fetch(tradeitemUrl, {
|
||||
method: 'GET',
|
||||
headers: headers,
|
||||
});
|
||||
|
||||
const tradeitemResponse = await tradeitemRequest.json();
|
||||
|
||||
tradeitemResponse.tradeItemId = await vnUuid(tradeitemResponse.tradeItemId);
|
||||
|
||||
await models.tradeItem.upsert({
|
||||
tradeItemId: tradeitemResponse.tradeItemId,
|
||||
supplierOrganizationId: tradeitemResponse.supplierOrganizationGln,
|
||||
supplierOrganizationUuid: await vnUuid(tradeitemResponse.supplierOrganizationId),
|
||||
code: tradeitemResponse.code,
|
||||
gtin: tradeitemResponse.gtin,
|
||||
vbnProductCode: tradeitemResponse.vbnProductCode,
|
||||
name: tradeitemResponse.name,
|
||||
isDeleted: tradeitemResponse.isDeleted,
|
||||
sequenceNumber: tradeitemResponse.sequenceNumber,
|
||||
tradeItemVersion: tradeitemResponse.tradeItemVersion,
|
||||
isCustomerSpecific: tradeitemResponse.isCustomerSpecific,
|
||||
isHiddenInCatalog: tradeitemResponse.isHiddenInCatalog,
|
||||
});
|
||||
|
||||
await tradeitemResponse.characteristics.forEach((characteristic) => {
|
||||
models.characteristics.upsert({
|
||||
tradeItemFk: tradeitemResponse.tradeItemId,
|
||||
vbnCode: characteristic.vbnCode,
|
||||
vbnValueCode: characteristic.vbnValueCode,
|
||||
});
|
||||
});
|
||||
|
||||
await tradeitemResponse.seasonalPeriods.forEach((seasonalPeriod) => {
|
||||
models.seasonalPeriod.upsert({
|
||||
tradeItemFk: tradeitemResponse.tradeItemId,
|
||||
startWeek: seasonalPeriod.startWeek,
|
||||
endWeek: seasonalPeriod.endWeek,
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
await tradeitemResponse.photos.forEach(async (photo) => {
|
||||
|
||||
photo.id = await vnUuid(photo.id);
|
||||
|
||||
models.photos.upsert({
|
||||
tradeItemFk: tradeitemResponse.tradeItemId,
|
||||
photoId: photo.id,
|
||||
url: photo.url,
|
||||
seasonalPeriodFk: JSON.stringify(photo.seasonalPeriod),
|
||||
type: photo.type,
|
||||
primary: photo.primary,
|
||||
});
|
||||
});
|
||||
|
||||
await tradeitemResponse.packingConfigurations.forEach(async (packagingConfiguration) => {
|
||||
|
||||
let uuid = uuidv4();
|
||||
uuid = await vnUuid(uuid);
|
||||
|
||||
await models.packingConfigurations.upsert({
|
||||
tradeItemFk: tradeitemResponse.tradeItemId,
|
||||
packingConfigurationId: uuid,
|
||||
piecesPerPackage: packagingConfiguration.piecesPerPackage,
|
||||
bunchesPerPackage: packagingConfiguration.bunchesPerPackage,
|
||||
photoUrl: packagingConfiguration.photoUrl,
|
||||
packagesPerLayer: packagingConfiguration.packagesPerLayer,
|
||||
layersPerLoadCarrier: packagingConfiguration.layersPerLoadCarrier,
|
||||
transportHeightInCm: packagingConfiguration.transportHeightInCm,
|
||||
loadCarrierType: packagingConfiguration.loadCarrierType,
|
||||
isPrimary: packagingConfiguration.isPrimary,
|
||||
additionalPricePerPiece: JSON.stringify(packagingConfiguration.additionalPricePerPiece),
|
||||
});
|
||||
|
||||
await models.package.upsert({
|
||||
packingConfigurationsId: uuid,
|
||||
vbnPackageCode: packagingConfiguration.package.vbnPackageCode,
|
||||
vbnPackageValueCode: packagingConfiguration.package.vbnPackageValueCode,
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
await tradeitemResponse.botanicalNames.forEach((botanicalName) => {
|
||||
models.botanicalNames.upsert({
|
||||
tradeItemFk: tradeitemResponse.tradeItemId,
|
||||
name: botanicalName,
|
||||
});
|
||||
});
|
||||
|
||||
await tradeitemResponse.countryOfOriginIsoCodes.forEach((countryOfOriginIsoCode) => {
|
||||
models.countryOfOriginIsoCodes.upsert({
|
||||
tradeItemFk: tradeitemResponse.tradeItemId,
|
||||
isoCode: countryOfOriginIsoCode,
|
||||
});
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log('There was an error while saving the data to the database, trying again in 5 seconds...');
|
||||
console.log(error.message);
|
||||
await sleep(5000);
|
||||
await getTradeItem(tradeItemId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stock for all suppliers
|
||||
*
|
||||
* Does this by getting all suppliers and then calling the getStockBySupplier function for each supplier
|
||||
*/
|
||||
async function getStock() {
|
||||
|
||||
const suppliers = await models.suppliers.findAll();
|
||||
|
||||
const supplierQueue = [];
|
||||
|
||||
suppliers.forEach(async (supplier) => {
|
||||
supplierQueue.push(await getStockBySupplier(supplier.supplierId));
|
||||
});
|
||||
|
||||
await asyncQueue(supplierQueue);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the stock for a given supplier
|
||||
*
|
||||
* @param {*} supplierId
|
||||
* @returns void - inserts the stock into the database
|
||||
*/
|
||||
async function getStockBySupplier(supplierId) {
|
||||
|
||||
supplierId = await removeVnPrefix(supplierId);
|
||||
|
||||
const headers = {
|
||||
let headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${await getJWT()}`,
|
||||
'X-Api-Key': process.env.API_KEY,
|
||||
'X-Api-Key': process.env.API_KEY
|
||||
};
|
||||
|
||||
let rFloraHolland = suppliersGln.floraholland;
|
||||
|
||||
const stockUrl = `${BASE_CUSTOMER_URL}supply-lines?supplierOrganizationId=${supplierId}`;
|
||||
let queryConnections = `${BASE_CUSTOMER_URL}connections`;
|
||||
|
||||
let stockRequest;
|
||||
let responseConnections = await fetch(queryConnections, {
|
||||
method: 'GET',
|
||||
headers: headers
|
||||
});
|
||||
|
||||
try {
|
||||
stockRequest = await fetch(stockUrl, {
|
||||
method: 'GET',
|
||||
headers: headers,
|
||||
let dataConnections = await responseConnections.json();
|
||||
|
||||
for(let connection of dataConnections){
|
||||
await models.connections.findOrCreate({
|
||||
where: {
|
||||
organizationId: connection
|
||||
},
|
||||
defaults: {
|
||||
organizationId: connection,
|
||||
connect : true
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error.message);
|
||||
return;
|
||||
}
|
||||
|
||||
const stockResponse = await stockRequest.json();
|
||||
for(let producer of rFloraHolland){
|
||||
|
||||
if (stockResponse.length == 0) {
|
||||
return;
|
||||
}
|
||||
let query = `${BASE_CUSTOMER_URL}organizations/gln/${producer}`;
|
||||
|
||||
try {
|
||||
let response = await fetch(query, {
|
||||
method: 'GET',
|
||||
headers: headers
|
||||
});
|
||||
|
||||
if (stockResponse.length > 0 && stockResponse != null) {
|
||||
let data = await response.json();
|
||||
|
||||
let bar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_grey);
|
||||
bar.start(stockResponse.length, 0);
|
||||
if (response.status === 200) {
|
||||
console.log('Supplier request successful');
|
||||
|
||||
await stockResponse.forEach(async supplyLine => {
|
||||
let connection = await models.connections.findOne({
|
||||
where: {
|
||||
organizationId: data.organizationId,
|
||||
connect: true
|
||||
}
|
||||
});
|
||||
|
||||
bar.increment();
|
||||
let isConnected = false;
|
||||
|
||||
let alreadyExists = await models.supplyLines.findOne({
|
||||
|
||||
|
||||
|
||||
if (connection != null) {
|
||||
isConnected = true;
|
||||
|
||||
let where = {
|
||||
companyGln: producer,
|
||||
isConnected: isConnected
|
||||
};
|
||||
let defaults = {
|
||||
isConnected: isConnected,
|
||||
commercialName: data.commercialName,
|
||||
email: data.email,
|
||||
phone: data.phone,
|
||||
website: data.website,
|
||||
mailingAddress: data.mailingAddress,
|
||||
physicalAddress: data.physicalAddress,
|
||||
pythosanitaryNumber: data.phytosanitaryNumber,
|
||||
sequenceNumber: data.sequenceNumber,
|
||||
organizationId: data.organizationId,
|
||||
companyGln: producer,
|
||||
name: data.name,
|
||||
endDate: data.endDate,
|
||||
rfhRelationId: data.rfhRelationId,
|
||||
organizationType: data.organizationType,
|
||||
paymentProviders: JSON.stringify(data.paymentProviders),
|
||||
};
|
||||
|
||||
await models.suppliers.destroy({
|
||||
where: {
|
||||
supplyLineId: supplyLine.supplyLineId,
|
||||
companyGln: producer,
|
||||
isConnected: false
|
||||
}
|
||||
});
|
||||
|
||||
if (alreadyExists) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
await models.supplyLines.upsert({
|
||||
supplyLineId: supplyLine.supplyLineId,
|
||||
status: supplyLine.status,
|
||||
supplierOrganizationId: await vnUuid(supplyLine.supplierOrganizationId),
|
||||
pricePerPiece: supplyLine.pricePerPiece,
|
||||
numberOfPieces: supplyLine.numberOfPieces,
|
||||
deliveryPeriod: supplyLine.deliveryPeriod,
|
||||
orderPeriod: supplyLine.orderPeriod,
|
||||
warehouseId: await vnUuid(supplyLine.warehouseId),
|
||||
sequenceNumber: supplyLine.sequenceNumber,
|
||||
type: supplyLine.type,
|
||||
isDeleted: supplyLine.isDeleted,
|
||||
salesUnit: supplyLine.salesUnit,
|
||||
agreementReferenceCode: supplyLine.agreementReference.code,
|
||||
agreementReferenceDescription: supplyLine.agreementReference.description,
|
||||
isLimited: supplyLine.isLimited,
|
||||
isCustomerSpecific: supplyLine.isCustomerSpecific,
|
||||
tradeItemFk: await vnUuid(supplyLine.tradeItemId),
|
||||
});
|
||||
|
||||
supplyLine.volumePrices.forEach(async (volumePrice) => {
|
||||
await models.volumePrices.upsert({
|
||||
supplyLineFk: supplyLine.supplyLineId,
|
||||
unit: volumePrice.unit,
|
||||
pricePerPiece: volumePrice.pricePerPiece,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
} catch (error) {
|
||||
if (error.name == 'SequelizeForeignKeyConstraintError') {
|
||||
bar.stop();
|
||||
console.log('Missing data for the tradeitem: ' + supplyLine.tradeItemId);
|
||||
console.log('Trying to get the tradeitem data...');
|
||||
await getTradeItem(supplyLine.tradeItemId);
|
||||
return;
|
||||
|
||||
await models.suppliers.findOrCreate({
|
||||
where : where,
|
||||
defaults: defaults
|
||||
});
|
||||
} else {
|
||||
let where = {
|
||||
companyGln: producer,
|
||||
isConnected: isConnected
|
||||
};
|
||||
let defaults = {
|
||||
isConnected: isConnected,
|
||||
commercialName: data.commercialName,
|
||||
email: data.email,
|
||||
phone: data.phone,
|
||||
website: data.website,
|
||||
mailingAddress: data.mailingAddress,
|
||||
physicalAddress: data.physicalAddress,
|
||||
pythosanitaryNumber: data.phytosanitaryNumber,
|
||||
sequenceNumber: data.sequenceNumber,
|
||||
organizationId: data.organizationId,
|
||||
companyGln: producer,
|
||||
name: data.name,
|
||||
endDate: data.endDate,
|
||||
rfhRelationId: data.rfhRelationId,
|
||||
organizationType: data.organizationType,
|
||||
paymentProviders: JSON.stringify(data.paymentProviders),
|
||||
};
|
||||
await models.suppliers.destroy({
|
||||
where: {
|
||||
companyGln: producer,
|
||||
isConnected: true
|
||||
}
|
||||
}
|
||||
});
|
||||
await models.suppliers.findOrCreate({
|
||||
where: where,
|
||||
defaults: defaults
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
bar.stop();
|
||||
console.log(`DATA FOR SUPPLIER: ${data.name} OK`);
|
||||
} else {
|
||||
console.log('Supplier request failed with status ', response.status);
|
||||
console.log('Supplier: ', data);
|
||||
console.log('response: ', response);
|
||||
console.log('query: ', query);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('There was an error while saving the data to the database, trying again in 5 seconds...');
|
||||
await sleep(5000);
|
||||
await getStockBySupplier(supplierId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export { getClientToken, updateClientConfig, getJWT, getTradeitems, sleep, asyncQueue, getStock };
|
||||
async function syncTradeItems(){
|
||||
|
||||
let suppliers = await models.suppliers.findAll({
|
||||
where: {
|
||||
isConnected: true
|
||||
}
|
||||
});
|
||||
|
||||
let headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${await getJWT()}`,
|
||||
'X-Api-Key': process.env.API_KEY
|
||||
};
|
||||
|
||||
for (let i = 0; i < suppliers.length; i++) {
|
||||
|
||||
let queryMaxSequence = `${BASE_CUSTOMER_URL}trade-items/current-max-sequence`;
|
||||
|
||||
let responseMaxSequence = await fetch(queryMaxSequence, {
|
||||
method: 'GET',
|
||||
headers: headers
|
||||
});
|
||||
|
||||
let maximumSequenceNumber = await responseMaxSequence.json();
|
||||
|
||||
await syncSequence(0, 'tradeItems', maximumSequenceNumber);
|
||||
|
||||
let currentSequence = await models.sequenceNumber.findOne({
|
||||
where: {
|
||||
model: 'tradeItems'
|
||||
}
|
||||
});
|
||||
|
||||
currentSequence = currentSequence.sequenceNumber;
|
||||
|
||||
let estimatedIterations = Math.ceil(maximumSequenceNumber / 1000);
|
||||
|
||||
let supplier = suppliers[i];
|
||||
|
||||
console.log('Syncing trade items for: ', supplier.name);
|
||||
console.log('Supplier Id: ', supplier.organizationId);
|
||||
console.log('Current sequence number: ', currentSequence);
|
||||
console.log('Maximum sequence number: ', maximumSequenceNumber);
|
||||
console.log('Estimated iterations: ', estimatedIterations);
|
||||
|
||||
for (let j = 0; j < estimatedIterations; j++) {
|
||||
|
||||
let query = `${BASE_CUSTOMER_URL}trade-items/sync/${currentSequence}?supplierOrganizationId=${supplier.organizationId}&limit=1000`;
|
||||
|
||||
let request = await fetch(query, {
|
||||
method: 'GET',
|
||||
headers: headers
|
||||
});
|
||||
|
||||
let data = await request.json();
|
||||
|
||||
let results = data.results;
|
||||
|
||||
if (results.length == 0) {
|
||||
console.log('No more trade items to sync');
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { getClientToken, updateClientConfig, getJWT, sleep, asyncQueue, syncSequence, syncSuppliers, syncTradeItems };
|
Loading…
Reference in New Issue