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 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
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) {
|
||||||
|
|
|
@ -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';
|
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,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -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",
|
||||||
|
|
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 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 };
|
Loading…
Reference in New Issue