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'; dotenv.config(); /** * The Endpoint where the Access Token is requested */ const _accessTokenEndpoint = 'https://idm.staging.floriday.io/oauth2/ausmw6b47z1BnlHkw0h7/v1/token'; /** * Gets the Access Token from the client config table * * @param {sequelize.models} models * @returns {Date} tokenExpirationDate formated as YYYY-MM-DD HH:mm:ss */ async function getClientToken() { const clientConfigData = await models.clientConfig.findAll(); const now = moment().format('YYYY-MM-DD HH:mm:ss'); const tokenExpirationDate = clientConfigData[0].tokenExpiration; if (clientConfigData[0].tokenExpiration == null || moment(now).isAfter(tokenExpirationDate)) { let clientId = clientConfigData[0].clientId; let clientSecret = clientConfigData[0].clientSecret; const tokenRequest = await fetch(_accessTokenEndpoint, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: `grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}&scope=role:app catalog:read supply:read organization:read network:read`, }); const tokenResponse = await tokenRequest.json(); if (tokenRequest.status === 200) { console.log('Token request successful'); } else { throw new Error( `Token request failed with status ${tokenRequest.status}` ); } const accessToken = tokenResponse.access_token; let now = moment().format('YYYY-MM-DD HH:mm:ss'); let tokenExpirationDate = moment(now) .add(tokenResponse.expires_in, 's') .format('YYYY-MM-DD HH:mm:ss'); await updateClientConfig( clientId, clientSecret, accessToken, tokenExpirationDate ); return tokenExpirationDate; } else { console.log('Using the current token...'); return tokenExpirationDate; } } /** * Updates the Access Token in the client config table * * @param {sequelize.models} models * @param {String} clientId * @param {String} clientSecret * @param {String} accessToken * @param {String} tokenExpirationDate */ async function updateClientConfig(clientId, clientSecret, accessToken, tokenExpirationDate) { try { console.log('Updating the client config with the new token...'); await models.clientConfig.update( { clientId: clientId, clientSecret: clientSecret, currentToken: accessToken, tokenExpiration: tokenExpirationDate, }, { where: { id: 1, }, } ); console.log('Client config updated, new Token set'); console.log('New token expiration date: ', tokenExpirationDate); } catch (error) { console.log('There was a error while updating the client config'); console.log(error); } } /** * returns the current Access Token * * @returns */ async function getJWT() { const clientConfigData = await models.clientConfig.findAll(); return clientConfigData[0].currentToken; } /** * pauses the execution of the script for the given amount of milliseconds * * @param {integer} ms * @returns A promise that resolves after ms milliseconds. */ async function sleep(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } /** * * returns every tradeitem from the organization * * @param {*} organizationGln */ async function getTradeitems(organizationGln) { const headers = { 'Content-Type': 'application/json', 'Authorization': 'Bearer ' + await getJWT(), 'X-Api-Key': process.env.API_KEY, }; const BASE_CUSTOMER_URL = 'https://api.staging.floriday.io/customers-api/2022v2/'; // 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; // 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 at least one tradeitem, save it in the database //console.log(tradeitemsResponse[0]); try { if (tradeitemsResponse.length > 0 && tradeitemsResponse != null) { console.log(`Tradeitems for the organization ${organizationGln} : `, tradeitemsResponse.length); await tradeitemsResponse.forEach(async item => { try { item.tradeItemId = 'Vn-' + item.tradeItemId; await models.tradeItem.upsert({ tradeItemId: item.tradeItemId, supplierOrganizationId: organizationGln, 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, }); try { await item.characteristics.forEach((characteristic) => { models.characteristics.upsert({ tradeItemFk: item.tradeItemId, vbnCode: characteristic.vbnCode, vbnValueCode: characteristic.vbnValueCode, }); }); } catch (error) { console.log('There was a error while saving the characteristics for the tradeitem: ', item.tradeItemId); } try { await item.seasonalPeriods.forEach((seasonalPeriod) => { models.seasonalPeriod.upsert({ tradeItemFk: item.tradeItemId, startWeek: seasonalPeriod.startWeek, endWeek: seasonalPeriod.endWeek, }); }); } catch (error) { console.log('There was a error while saving the seasonalPeriods for the tradeitem: ', item.tradeItemId); } try { await item.photos.forEach((photo) => { photo.id = 'Vn-' + photo.id; models.photos.upsert({ tradeItemFk: item.tradeItemId, photoId: photo.id, url: photo.url, seasonalPeriodFk: photo.seasonalPeriod, type: photo.type, primary: photo.primary, }); }); } catch (error) { console.log('There was a error while saving the photos for the tradeitem: ', item.tradeItemId); } try { await item.packingConfigurations.forEach(async (packagingConfiguration) => { let uuid = uuidv4(); uuid = 'Vn-' + 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, }); await models.package.upsert({ packingConfigurationsFk: uuid, vbnPackageCode: packagingConfiguration.package.vbnPackageCode, vbnPackageValueCode: packagingConfiguration.package.vbnPackageValueCode, }); await models.additionalPricePerPiece.upsert({ packingConfigurationsFk: uuid, currency: packagingConfiguration.additionalPricePerPiece.currency, value: packagingConfiguration.additionalPricePerPiece.value, }); }); } catch (error) { console.log('There was a error while saving the packingConfigurations for the tradeitem: ', item.tradeItemId); } try { await item.botanicalNames.forEach((botanicalName) => { models.botanicalNames.upsert({ tradeItemFk: item.tradeItemId, name: botanicalName, }); }); } catch (error) { console.log('There was a error while saving the botanicalNames for the tradeitem: ', item.tradeItemId); } try { await item.countryOfOriginIsoCodes.forEach((countryOfOriginIsoCode) => { models.countryOfOriginIsoCodes.upsert({ tradeItemFk: item.tradeItemId, isoCode: countryOfOriginIsoCode, }); }); } catch (error) { console.log('There was a error while saving the countryOfOriginIsoCodes for the tradeitem: ', item.tradeItemId); } } catch (error) { console.log('There was an error while saving the data to the database'); console.log(error); } }); } else { console.log('There are no tradeitems for the organization: ', organizationGln); } } catch (error) { console.log('There was an error while saving the data to the database'); throw new Error(error); } } export { getClientToken, updateClientConfig, getJWT, getTradeitems ,sleep };