2023-01-09 11:58:34 +00:00
|
|
|
import moment from 'moment';
|
|
|
|
import fetch from 'node-fetch';
|
2023-01-10 12:24:43 +00:00
|
|
|
import dotenv from 'dotenv';
|
2023-01-11 12:13:22 +00:00
|
|
|
import { models } from './models/index.js';
|
|
|
|
import { v4 as uuidv4 } from 'uuid';
|
2023-01-12 13:54:05 +00:00
|
|
|
import cliProgress from 'cli-progress';
|
2023-01-10 12:24:43 +00:00
|
|
|
dotenv.config();
|
2023-01-11 13:37:46 +00:00
|
|
|
|
2023-01-09 12:35:05 +00:00
|
|
|
/**
|
|
|
|
* The Endpoint where the Access Token is requested
|
|
|
|
*/
|
|
|
|
const _accessTokenEndpoint = 'https://idm.staging.floriday.io/oauth2/ausmw6b47z1BnlHkw0h7/v1/token';
|
2023-01-09 11:58:34 +00:00
|
|
|
|
2023-01-09 12:35:05 +00:00
|
|
|
/**
|
|
|
|
* Gets the Access Token from the client config table
|
|
|
|
*
|
|
|
|
* @param {sequelize.models} models
|
|
|
|
* @returns {Date} tokenExpirationDate formated as YYYY-MM-DD HH:mm:ss
|
|
|
|
*/
|
2023-01-10 12:24:43 +00:00
|
|
|
async function getClientToken() {
|
2023-01-09 11:58:34 +00:00
|
|
|
const clientConfigData = await models.clientConfig.findAll();
|
|
|
|
|
|
|
|
const now = moment().format('YYYY-MM-DD HH:mm:ss');
|
|
|
|
const tokenExpirationDate = clientConfigData[0].tokenExpiration;
|
|
|
|
|
2023-01-09 12:35:05 +00:00
|
|
|
if (clientConfigData[0].tokenExpiration == null || moment(now).isAfter(tokenExpirationDate)) {
|
2023-01-09 11:58:34 +00:00
|
|
|
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');
|
|
|
|
|
2023-01-10 12:24:43 +00:00
|
|
|
await updateClientConfig(
|
2023-01-09 11:58:34 +00:00
|
|
|
clientId,
|
|
|
|
clientSecret,
|
|
|
|
accessToken,
|
|
|
|
tokenExpirationDate
|
|
|
|
);
|
|
|
|
|
2023-01-09 12:35:05 +00:00
|
|
|
return tokenExpirationDate;
|
2023-01-09 11:58:34 +00:00
|
|
|
} else {
|
|
|
|
console.log('Using the current token...');
|
2023-01-09 12:35:05 +00:00
|
|
|
return tokenExpirationDate;
|
2023-01-09 11:58:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-09 12:35:05 +00:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
*/
|
2023-01-10 12:24:43 +00:00
|
|
|
async function updateClientConfig(clientId, clientSecret, accessToken, tokenExpirationDate) {
|
2023-01-09 11:58:34 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-10 12:24:43 +00:00
|
|
|
/**
|
|
|
|
* returns the current Access Token
|
|
|
|
*
|
|
|
|
* @returns
|
|
|
|
*/
|
|
|
|
async function getJWT() {
|
|
|
|
const clientConfigData = await models.clientConfig.findAll();
|
|
|
|
return clientConfigData[0].currentToken;
|
|
|
|
}
|
|
|
|
|
2023-01-11 12:13:22 +00:00
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
2023-01-11 13:37:46 +00:00
|
|
|
* Inserts every tradeitem from the organization into the DB
|
2023-01-11 12:13:22 +00:00
|
|
|
*
|
|
|
|
* @param {*} organizationGln
|
|
|
|
*/
|
2023-01-10 12:24:43 +00:00
|
|
|
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,
|
|
|
|
});
|
2023-01-11 12:13:22 +00:00
|
|
|
|
2023-01-10 12:24:43 +00:00
|
|
|
const tradeitemsResponse = await tradeitemsRequest.json();
|
|
|
|
|
2023-01-12 13:54:05 +00:00
|
|
|
// If there is no tradeitems
|
|
|
|
if (tradeitemsResponse.length == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-11 12:13:22 +00:00
|
|
|
// if there is at least one tradeitem, save it in the database
|
2023-01-10 12:24:43 +00:00
|
|
|
|
2023-01-11 12:13:22 +00:00
|
|
|
//console.log(tradeitemsResponse[0]);
|
2023-01-10 12:24:43 +00:00
|
|
|
|
2023-01-11 12:13:22 +00:00
|
|
|
try {
|
2023-01-10 12:24:43 +00:00
|
|
|
|
2023-01-11 12:13:22 +00:00
|
|
|
if (tradeitemsResponse.length > 0 && tradeitemsResponse != null) {
|
2023-01-10 12:24:43 +00:00
|
|
|
|
2023-01-12 13:54:05 +00:00
|
|
|
let bar = new cliProgress.SingleBar({}, cliProgress.Presets.shades_grey);
|
|
|
|
bar.start(tradeitemsResponse.length, 0);
|
2023-01-10 12:24:43 +00:00
|
|
|
|
2023-01-11 12:13:22 +00:00
|
|
|
await tradeitemsResponse.forEach(async item => {
|
2023-01-12 13:54:05 +00:00
|
|
|
|
|
|
|
bar.increment();
|
|
|
|
|
2023-01-11 12:13:22 +00:00
|
|
|
try {
|
2023-01-10 12:24:43 +00:00
|
|
|
|
2023-01-11 12:13:22 +00:00
|
|
|
item.tradeItemId = 'Vn-' + item.tradeItemId;
|
2023-01-10 12:24:43 +00:00
|
|
|
|
2023-01-11 12:13:22 +00:00
|
|
|
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,
|
|
|
|
});
|
2023-01-10 12:24:43 +00:00
|
|
|
|
2023-01-12 13:54:05 +00:00
|
|
|
await item.characteristics.forEach((characteristic) => {
|
|
|
|
models.characteristics.upsert({
|
|
|
|
tradeItemFk: item.tradeItemId,
|
|
|
|
vbnCode: characteristic.vbnCode,
|
|
|
|
vbnValueCode: characteristic.vbnValueCode,
|
2023-01-11 12:13:22 +00:00
|
|
|
});
|
2023-01-12 13:54:05 +00:00
|
|
|
});
|
2023-01-11 12:13:22 +00:00
|
|
|
|
2023-01-12 13:54:05 +00:00
|
|
|
await item.seasonalPeriods.forEach((seasonalPeriod) => {
|
|
|
|
models.seasonalPeriod.upsert({
|
|
|
|
tradeItemFk: item.tradeItemId,
|
|
|
|
startWeek: seasonalPeriod.startWeek,
|
|
|
|
endWeek: seasonalPeriod.endWeek,
|
2023-01-11 12:13:22 +00:00
|
|
|
});
|
|
|
|
|
2023-01-12 13:54:05 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
await item.photos.forEach((photo) => {
|
|
|
|
|
|
|
|
photo.id = 'Vn-' + 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,
|
2023-01-11 12:13:22 +00:00
|
|
|
});
|
2023-01-12 13:54:05 +00:00
|
|
|
});
|
2023-01-11 12:13:22 +00:00
|
|
|
|
2023-01-12 13:54:05 +00:00
|
|
|
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,
|
|
|
|
additionalPricePerPiece: JSON.stringify(packagingConfiguration.additionalPricePerPiece),
|
|
|
|
});
|
2023-01-11 12:13:22 +00:00
|
|
|
|
2023-01-12 13:54:05 +00:00
|
|
|
await models.package.upsert({
|
|
|
|
packingConfigurationsId: uuid,
|
|
|
|
vbnPackageCode: packagingConfiguration.package.vbnPackageCode,
|
|
|
|
vbnPackageValueCode: packagingConfiguration.package.vbnPackageValueCode,
|
2023-01-11 12:13:22 +00:00
|
|
|
});
|
2023-01-12 13:54:05 +00:00
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
await item.botanicalNames.forEach((botanicalName) => {
|
|
|
|
models.botanicalNames.upsert({
|
|
|
|
tradeItemFk: item.tradeItemId,
|
|
|
|
name: botanicalName,
|
2023-01-11 12:13:22 +00:00
|
|
|
});
|
2023-01-12 13:54:05 +00:00
|
|
|
});
|
2023-01-11 12:13:22 +00:00
|
|
|
|
2023-01-12 13:54:05 +00:00
|
|
|
await item.countryOfOriginIsoCodes.forEach((countryOfOriginIsoCode) => {
|
|
|
|
models.countryOfOriginIsoCodes.upsert({
|
|
|
|
tradeItemFk: item.tradeItemId,
|
|
|
|
isoCode: countryOfOriginIsoCode,
|
|
|
|
});
|
|
|
|
});
|
2023-01-11 12:13:22 +00:00
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
console.log('There was an error while saving the data to the database');
|
|
|
|
}
|
2023-01-12 13:54:05 +00:00
|
|
|
|
2023-01-10 12:24:43 +00:00
|
|
|
});
|
2023-01-12 13:54:05 +00:00
|
|
|
bar.stop();
|
2023-01-10 12:24:43 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 12:13:22 +00:00
|
|
|
} catch (error) {
|
|
|
|
console.log('There was an error while saving the data to the database');
|
|
|
|
throw new Error(error);
|
|
|
|
}
|
2023-01-10 12:24:43 +00:00
|
|
|
}
|
|
|
|
|
2023-01-12 13:54:05 +00:00
|
|
|
export { getClientToken, updateClientConfig, getJWT, getTradeitems, sleep };
|