floriday/utils.js

337 lines
10 KiB
JavaScript
Raw Normal View History

import moment from 'moment';
import fetch from 'node-fetch';
import dotenv from 'dotenv';
2023-01-11 12:13:22 +00:00
import { models } from './models/index.js';
2023-02-03 12:56:34 +00:00
//import { v4 as uuidv4 } from 'uuid';
//import cliProgress from 'cli-progress';
import suppliersGln from './suppliersGln.js';
dotenv.config();
2023-01-11 13:37:46 +00:00
/**
* The Endpoint where the Access Token is requested
*/
const _accessTokenEndpoint = 'https://idm.staging.floriday.io/oauth2/ausmw6b47z1BnlHkw0h7/v1/token';
2023-01-16 13:52:08 +00:00
const BASE_CUSTOMER_URL = 'https://api.staging.floriday.io/customers-api/2022v2/';
/**
* 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',
},
2023-02-01 12:23:06 +00:00
body: `grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}&scope=role:app catalog:read supply:read organization:read network:write 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...');
2023-02-07 08:45:04 +00:00
await models.clientConfig.upsert({
id: 1,
clientId: clientId,
clientSecret: clientSecret,
currentToken: accessToken,
tokenExpiration: tokenExpirationDate,
requestLimit: 500,
2023-02-07 06:50:05 +00:00
});
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;
}
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-16 13:52:08 +00:00
/**
* Recieves an array of functions and executes them in a queue with the given concurrency
*
* @param {Array} fnArray
* @param {Number} concurrency
* @returns
*/
async function asyncQueue(fnArray, concurrency = 1) {
const results = []; // 1
const queue = fnArray.map((fn, index) => () => fn().then((result) => results[index] = result));
const run = async () => { // 2
const fn = queue.shift();
if (fn) {
await fn();
await run();
}
};
const promises = []; // 3
while (concurrency--) { // 4
promises.push(run());
}
await Promise.all(promises); // 5
2023-01-24 12:51:44 +00:00
2023-01-16 13:52:08 +00:00
return results;
}
// 1. Create an array of functions that will be executed in a queue
// 2. Create a function that will execute the functions in the queue
// 3. Create an array of promises that will execute the run function
// 4. Execute the run function while the concurrency is greater than 0
// 5. Return the results
2023-01-11 12:13:22 +00:00
/**
2023-02-03 12:56:34 +00:00
* Syncs the sequence number for the given model
* if no params are given it will reset all the sequence number to 0
2023-01-11 12:13:22 +00:00
*
2023-02-03 12:56:34 +00:00
* @param {Number} current - current sequence number
* @param {String} model - model name
* @param {Number} maximumSequenceNumber - maximum sequence number
* @returns
2023-01-11 12:13:22 +00:00
*/
2023-02-03 12:56:34 +00:00
async function syncSequence(current = 0, model = null ,maximumSequenceNumber = 0){
if (model == null && current == 0){
let mockModels = ['suppliers','tradeItems','supplyLines',];
for (let i = 0; i < mockModels.length; i++) {
const element = mockModels[i];
console.log('Syncing sequence for: ', element);
await syncSequence(0, element);
}
2023-02-03 12:56:34 +00:00
} else {
2023-02-03 12:56:34 +00:00
let tx = await models.sequelize.transaction();
try {
2023-02-07 08:41:54 +00:00
let sequence = await models.sequenceNumber.findOrCreate({
where: {
model: model
},
defaults: {
model: model,
sequenceNumber: current,
maximumSequenceNumber: maximumSequenceNumber
},
transaction: tx
});
if (sequence[1] == false){
await models.sequenceNumber.update({
sequenceNumber: current,
maximumSequenceNumber: maximumSequenceNumber
}, {
where: {
model: model
},
transaction: tx
});
}
2023-02-03 12:56:34 +00:00
await tx.commit();
2023-02-03 12:56:34 +00:00
} catch (error) {
await tx.rollback();
console.log('Error while syncing sequence number for: ', model);
}
2023-01-11 12:13:22 +00:00
}
}
2023-02-03 12:56:34 +00:00
async function syncSuppliers(){
2023-01-24 12:51:44 +00:00
2023-02-03 12:56:34 +00:00
let headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${await getJWT()}`,
'X-Api-Key': process.env.API_KEY
};
2023-01-24 12:51:44 +00:00
let maximumSequenceNumber = 500;
2023-01-24 12:51:44 +00:00
for (let i = 0; i < maximumSequenceNumber; i++) {
2023-01-24 12:51:44 +00:00
let query = `${BASE_CUSTOMER_URL}organizations/sync/${i}?organizationType=SUPPLIER&limit=500`;
let response = await fetch(query, {
method: 'GET',
headers: headers
});
2023-01-24 12:51:44 +00:00
let data = await response.json();
maximumSequenceNumber = data.maximumSequenceNumber;
let suppliers = data.results;
for (let supplier of suppliers) {
i = supplier.sequenceNumber;
await models.suppliers.upsert({
isConnected: false,
commercialName: supplier.commercialName,
email: supplier.email,
phone: supplier.phone,
website: supplier.website,
mailingAddress: supplier.mailingAddress,
physicalAddress: supplier.physicalAddress,
pythosanitaryNumber: supplier.pythosanitaryNumber,
sequenceNumber: supplier.sequenceNumber,
organizationId: supplier.organizationId,
companyGln: supplier.companyGln,
name: supplier.name,
endDate: supplier.endDate,
rfhRelationId: supplier.rfhRelationId,
organizationType: supplier.organizationType,
paymentProviders: `${supplier.paymentProviders}`,
});
console.log('INSERTED:\t', supplier.commercialName, '\nsequenceNumber:\t', supplier.sequenceNumber);
}
await syncSequence(i, 'suppliers', maximumSequenceNumber);
console.log(data.maximumSequenceNumber);
console.log(data.results.length);
console.log(i);
}
2023-01-24 12:51:44 +00:00
}
2023-02-03 12:56:34 +00:00
async function syncTradeItems(){
2023-01-16 13:52:08 +00:00
2023-02-03 12:56:34 +00:00
let suppliers = await models.suppliers.findAll({
where: {
isConnected: true
}
2023-01-16 13:52:08 +00:00
});
2023-02-03 12:56:34 +00:00
let headers = {
2023-01-16 13:52:08 +00:00
'Content-Type': 'application/json',
'Authorization': `Bearer ${await getJWT()}`,
2023-02-03 12:56:34 +00:00
'X-Api-Key': process.env.API_KEY
2023-01-16 13:52:08 +00:00
};
2023-02-03 12:56:34 +00:00
for (let i = 0; i < suppliers.length; i++) {
let queryMaxSequence = `${BASE_CUSTOMER_URL}trade-items/current-max-sequence`;
let responseMaxSequence = await fetch(queryMaxSequence, {
2023-01-24 12:51:44 +00:00
method: 'GET',
2023-02-03 12:56:34 +00:00
headers: headers
2023-01-24 12:51:44 +00:00
});
2023-02-03 12:56:34 +00:00
let maximumSequenceNumber = await responseMaxSequence.json();
2023-01-24 12:51:44 +00:00
2023-02-03 12:56:34 +00:00
await syncSequence(0, 'tradeItems', maximumSequenceNumber);
let currentSequence = await models.sequenceNumber.findOne({
where: {
model: 'tradeItems'
}
});
2023-01-24 12:51:44 +00:00
2023-02-03 12:56:34 +00:00
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
});
2023-01-24 12:51:44 +00:00
2023-02-07 06:50:05 +00:00
let itemdata = await request.json();
2023-01-24 12:51:44 +00:00
2023-02-07 06:50:05 +00:00
let results = itemdata.results;
2023-01-24 12:51:44 +00:00
2023-02-03 12:56:34 +00:00
if (results.length == 0) {
console.log('No more trade items to sync');
break;
}
2023-01-24 12:51:44 +00:00
2023-01-16 13:52:08 +00:00
}
2023-01-24 12:51:44 +00:00
}
2023-01-16 13:52:08 +00:00
}
2023-02-03 12:56:34 +00:00
export { getClientToken, updateClientConfig, getJWT, sleep, asyncQueue, syncSequence, syncSuppliers, syncTradeItems };