diff --git a/index.js b/index.js index 6987fb1..36e3103 100644 --- a/index.js +++ b/index.js @@ -9,6 +9,12 @@ 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') + ' -'); + console.info.apply(console, args); +}; + let tokenExpirationDate = await vnUtils.getClientToken(models); try { @@ -43,16 +49,20 @@ try { // eslint-disable-next-line no-constant-condition while (true) { - - console.log('Querying the API to check for new data...'); - console.log('Current token expiration date: ', tokenExpirationDate); + try{ + console.log('Querying the API to check for new data...'); + console.log('Current token expiration date: ', tokenExpirationDate); - await vnUtils.getStock(); + await vnUtils.getStock(); - if (moment().isAfter(tokenExpirationDate)) { - console.log('Token expired, getting a new one...'); - tokenExpirationDate = await vnUtils.getClientToken(models); + if (moment().isAfter(tokenExpirationDate)) { + console.log('Token expired, getting a new one...'); + tokenExpirationDate = await vnUtils.getClientToken(models); + } + } catch (error) { + console.error(error); } + if (process.env.STATUS == 'development') { await vnUtils.sleep(15000); } else { @@ -62,10 +72,4 @@ try { } catch (error) { console.error('Unable to connect to the database:', error); -} - -console.log = function () { - let args = Array.prototype.slice.call(arguments); - args.unshift(new moment().format('HH:mm:ss') + ' -'); - console.info.apply(console, args); -}; \ No newline at end of file +} \ No newline at end of file diff --git a/utils.js b/utils.js index d3c50ae..e0f2d03 100644 --- a/utils.js +++ b/utils.js @@ -169,7 +169,7 @@ async function asyncQueue(fnArray, concurrency = 1) { } await Promise.all(promises); // 5 - + return results; } @@ -349,6 +349,128 @@ async function getTradeitems(organizationGln) { } } +/** + * Gets a single tradeitem from the API and inserts it into the database + * + * @param {*} tradeItemId + */ +async function getTradeItem(tradeItemId) { + + 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); + } + +} + async function getStock() { const suppliers = await models.suppliers.findAll(); @@ -360,7 +482,7 @@ async function getStock() { }); await asyncQueue(supplierQueue); - + } async function getStockBySupplier(supplierId) { @@ -375,10 +497,17 @@ async function getStockBySupplier(supplierId) { const stockUrl = `${BASE_CUSTOMER_URL}supply-lines?supplierOrganizationId=${supplierId}`; - const stockRequest = await fetch(stockUrl, { - method: 'GET', - headers: headers, - }); + let stockRequest; + + try { + stockRequest = await fetch(stockUrl, { + method: 'GET', + headers: headers, + }); + } catch (error) { + console.log(error.message); + return; + } const stockResponse = await stockRequest.json(); @@ -387,18 +516,28 @@ async function getStockBySupplier(supplierId) { } try { - + if (stockResponse.length > 0 && stockResponse != null) { - + let bar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_grey); bar.start(stockResponse.length, 0); - + await stockResponse.forEach(async supplyLine => { - + bar.increment(); - + + let alreadyExists = await models.supplyLines.findOne({ + where: { + supplyLineId: supplyLine.supplyLineId, + } + }); + + if (alreadyExists) { + return; + } + try { - + await models.supplyLines.upsert({ supplyLineId: supplyLine.supplyLineId, status: supplyLine.status, @@ -424,15 +563,17 @@ async function getStockBySupplier(supplierId) { price: supplyLine.volumePrices.price, supplyLineFk: await vnUuid(supplyLine.supplyLineId), }); - - } catch (error) { + + } 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; } - bar.stop(); - return; } - + }); bar.stop(); } @@ -440,7 +581,7 @@ async function getStockBySupplier(supplierId) { console.log('There was an error while saving the data to the database, trying again in 5 seconds...'); await sleep(5000); await getStockBySupplier(supplierId); - } + } }