This commit is contained in:
Pau 2023-02-03 13:56:34 +01:00
parent 53b11dfca0
commit e10ee70d4a
9 changed files with 393 additions and 4918 deletions

View File

@ -1,14 +1,12 @@
import moment from 'moment'; import moment from 'moment';
import * as vnUtils from './utils.js'; import * as vnUtils from './utils.js';
import cliProgress from 'cli-progress'; //import cliProgress from 'cli-progress';
import dotenv from 'dotenv'; import dotenv from 'dotenv';
dotenv.config(); dotenv.config();
import { models } from './models/index.js'; import { models } from './models/index.js';
import suppliers from './suppliersGln.js';
console.log = function () { console.log = function () {
let args = Array.prototype.slice.call(arguments); let args = Array.prototype.slice.call(arguments);
args.unshift(new moment().format('HH:mm:ss') + ' -'); args.unshift(new moment().format('HH:mm:ss') + ' -');
@ -17,48 +15,22 @@ console.log = function () {
let tokenExpirationDate = await vnUtils.getClientToken(models); 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 { 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 // eslint-disable-next-line no-constant-condition
while (true) { while (true) {
try{ try{
console.log('Querying the API to check for new data...'); console.log('Querying the API to check for new data...');
console.log('Current token expiration date: ', tokenExpirationDate); console.log('Current token expiration date: ', tokenExpirationDate);
await vnUtils.getStock();
if (moment().isAfter(tokenExpirationDate)) { if (moment().isAfter(tokenExpirationDate)) {
console.log('Token expired, getting a new one...'); console.log('Token expired, getting a new one...');
tokenExpirationDate = await vnUtils.getClientToken(models); tokenExpirationDate = await vnUtils.getClientToken(models);
} }
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }

View File

@ -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;
};

View File

@ -4,24 +4,36 @@ dotenv.config();
let sequelize = createConnection(); 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 botanicalNames from './tradeItem/botanicalNames.js';
import countryOfOriginIsoCodes from './tradeItem/countryOfOriginIsoCodes.js'; import countryOfOriginIsoCodes from './tradeItem/countryOfOriginIsoCodes.js';
import packageModel from './tradeItem/package.js'; import packageModel from './tradeItem/package.js';
import packingConfigurations from './tradeItem/packingConfigurations.js'; import packingConfigurations from './tradeItem/packingConfigurations.js';
import photos from './tradeItem/photos.js'; import photos from './tradeItem/photos.js';
import seasonalPeriod from './tradeItem/seasonalPeriod.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 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. * Contains all the models that are related to the application.
* *
* @example * @example
* models.tradeItem.findAll(); * models.@modelName@.findAll();
* *
* @example * @example
* models.tradeItem.findAll().then((data) => { * models.tradeItem.findAll().then((data) => {
@ -38,6 +50,7 @@ import suppliers from './supplier/suppliers.js';
* @type {Object.<string, Sequelize.Model>} * @type {Object.<string, Sequelize.Model>}
*/ */
let models = { let models = {
sequelize: sequelize,
tradeItem: tradeItem(sequelize), tradeItem: tradeItem(sequelize),
packingConfigurations: packingConfigurations(sequelize), packingConfigurations: packingConfigurations(sequelize),
photos: photos(sequelize), photos: photos(sequelize),
@ -50,6 +63,8 @@ let models = {
supplyLines: supplyLine(sequelize), supplyLines: supplyLine(sequelize),
volumePrices: volumePrices(sequelize), volumePrices: volumePrices(sequelize),
suppliers: suppliers(sequelize), suppliers: suppliers(sequelize),
sequenceNumber: sequenceNumber(sequelize),
connections: connections(sequelize),
}; };
models.characteristics.belongsTo(models.tradeItem, { models.characteristics.belongsTo(models.tradeItem, {
@ -125,9 +140,12 @@ models.supplyLines.belongsTo(models.tradeItem, {
targetKey: 'tradeItemId', targetKey: 'tradeItemId',
}); });
if (process.env.FORCE_SYNC) { if (process.env.FORCE_SYNC == true) {
console.log('Syncing the models...'); console.log('Forcing the models...');
await sequelize.sync({ force: true }); await sequelize.sync({ force: true });
} else {
console.log('Altering the models...');
await sequelize.sync({ alter: true });
} }
if (process.env.SECRETS) { if (process.env.SECRETS) {

View File

@ -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;
};

View File

@ -1,16 +1,56 @@
import { Sequelize } from 'sequelize'; import { Sequelize } from 'sequelize';
const suppliers = { const suppliers = {
id: { isConnected: {
type: Sequelize.INTEGER, type: Sequelize.BOOLEAN,
primaryKey: true, defaultValue: false,
autoIncrement: true,
}, },
supplierId: { commercialName: {
type: Sequelize.STRING, 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, type: Sequelize.STRING,
}, },
}; };

View File

@ -7,7 +7,7 @@
"dev-sync": "FORCE_SYNC=true node --max-old-space-size=4096 index.js", "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-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-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": { "dependencies": {
"cli-progress": "^3.11.2", "cli-progress": "^3.11.2",

File diff suppressed because it is too large Load Diff

29
test.json Normal file
View File

@ -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
View File

@ -2,8 +2,9 @@ import moment from 'moment';
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import dotenv from 'dotenv'; import dotenv from 'dotenv';
import { models } from './models/index.js'; import { models } from './models/index.js';
import { v4 as uuidv4 } from 'uuid'; //import { v4 as uuidv4 } from 'uuid';
import cliProgress from 'cli-progress'; //import cliProgress from 'cli-progress';
import suppliersGln from './suppliersGln.js';
dotenv.config(); dotenv.config();
/** /**
@ -86,6 +87,7 @@ async function updateClientConfig(clientId, clientSecret, accessToken, tokenExpi
clientSecret: clientSecret, clientSecret: clientSecret,
currentToken: accessToken, currentToken: accessToken,
tokenExpiration: tokenExpirationDate, tokenExpiration: tokenExpirationDate,
requestLimit : 500
}, },
{ {
where: { 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 * 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 // 4. Execute the run function while the concurrency is greater than 0
// 5. Return the results // 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 {Number} current - current sequence number
* * @param {String} model - model name
* @param {*} organizationGln * @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 = { for (let i = 0; i < mockModels.length; i++) {
'Content-Type': 'application/json', const element = mockModels[i];
'Authorization': 'Bearer ' + await getJWT(), console.log('Syncing sequence for: ', element);
'X-Api-Key': process.env.API_KEY, await syncSequence(0, element);
};
// 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();
} }
} catch (error) { } else {
console.log('There was an error while saving the data to the database, trying again in 5 seconds...');
await sleep(5000); let tx = await models.sequelize.transaction();
await getTradeitems(organizationGln);
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);
}
} }
} }
/** async function syncSuppliers(){
* Gets a single tradeitem from the API and inserts it into the database
*
* @param {*} tradeItemId
*/
async function getTradeItem(tradeItemId) {
try { let headers = {
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 = {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'Authorization': `Bearer ${await getJWT()}`, '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 { let dataConnections = await responseConnections.json();
stockRequest = await fetch(stockUrl, {
method: 'GET', for(let connection of dataConnections){
headers: headers, 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) { let query = `${BASE_CUSTOMER_URL}organizations/gln/${producer}`;
return;
}
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); if (response.status === 200) {
bar.start(stockResponse.length, 0); 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: { where: {
supplyLineId: supplyLine.supplyLineId, companyGln: producer,
isConnected: false
} }
}); });
if (alreadyExists) { await models.suppliers.findOrCreate({
return; where : where,
} defaults: defaults
});
try { } else {
let where = {
await models.supplyLines.upsert({ companyGln: producer,
supplyLineId: supplyLine.supplyLineId, isConnected: isConnected
status: supplyLine.status, };
supplierOrganizationId: await vnUuid(supplyLine.supplierOrganizationId), let defaults = {
pricePerPiece: supplyLine.pricePerPiece, isConnected: isConnected,
numberOfPieces: supplyLine.numberOfPieces, commercialName: data.commercialName,
deliveryPeriod: supplyLine.deliveryPeriod, email: data.email,
orderPeriod: supplyLine.orderPeriod, phone: data.phone,
warehouseId: await vnUuid(supplyLine.warehouseId), website: data.website,
sequenceNumber: supplyLine.sequenceNumber, mailingAddress: data.mailingAddress,
type: supplyLine.type, physicalAddress: data.physicalAddress,
isDeleted: supplyLine.isDeleted, pythosanitaryNumber: data.phytosanitaryNumber,
salesUnit: supplyLine.salesUnit, sequenceNumber: data.sequenceNumber,
agreementReferenceCode: supplyLine.agreementReference.code, organizationId: data.organizationId,
agreementReferenceDescription: supplyLine.agreementReference.description, companyGln: producer,
isLimited: supplyLine.isLimited, name: data.name,
isCustomerSpecific: supplyLine.isCustomerSpecific, endDate: data.endDate,
tradeItemFk: await vnUuid(supplyLine.tradeItemId), rfhRelationId: data.rfhRelationId,
}); organizationType: data.organizationType,
paymentProviders: JSON.stringify(data.paymentProviders),
supplyLine.volumePrices.forEach(async (volumePrice) => { };
await models.volumePrices.upsert({ await models.suppliers.destroy({
supplyLineFk: supplyLine.supplyLineId, where: {
unit: volumePrice.unit, companyGln: producer,
pricePerPiece: volumePrice.pricePerPiece, isConnected: true
});
});
} 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
});
}
}); console.log(`DATA FOR SUPPLIER: ${data.name} OK`);
bar.stop(); } 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 };