refs #4823 Code refactor

This commit is contained in:
Guillermo Bonet 2023-04-04 20:14:20 +02:00
parent cdd2fa269f
commit ecf9ceb44b
4 changed files with 179 additions and 137 deletions

View File

@ -1,7 +1,5 @@
# Floriday
Requires [Node.js](https://nodejs.org/en/) v15.14.0 or higher.
The Floriday service project should perform the following tasks:
1. Create / mantain the table structure to allow the storage of the data provided by the Floriday API.
@ -12,13 +10,51 @@ The Floriday service project should perform the following tasks:
This is done using the [Sequelize](https://sequelize.org/) ORM and storing the data as it is received from the API,
so it can be compared with the previous data.
## Requeriments
* Git
* Nodejs (v15.14.0 or higher)
## Installation
Pull from repository.
Run this commands on project root directory to install Node dependencies.
```bash
npm i
```
### .env file template
```bash
#FLORIDAY DATA
CLIENT_ID = xxxxxxxxxx
CLIENT_SECRET = xxxxxxxxxx
API_KEY = xxxxxxxxxx
#SEQUELIZE CONFIG
DB_SCHEMA = schema
DB_USER = root
DB_PWD = root
DB_HOST = localhost
DB_DIALECT = mariadb
#GENERAL CONFIG
IS_PRODUCTION = false
SECRETS = true
FORCE_SYNC = true
SYNC_SEQUENCE = true
SYNC_SUPPLIER = true
SYNC_TRADEITEM = true
```
## Guidelines
- In case a new model is created, it should follow the following structure:
- /models
- index.js
- main.js
- foo.js
### Foo.js
@ -51,7 +87,7 @@ export default (sequelize) => {
};
```
### Index.js
### main.js
```javascript
import foo from "./foo";
@ -62,32 +98,7 @@ let models = {
```
To install dependencies:
## Built With
```bash
npm install
```
To run:
```bash
npm start # run the service
npm dev-sync # run and create the db structure
```
### .env file
```bash
# FLORIDAY SERVICE CONFIG
CLIENT_ID = floriday-client_id
CLIENT_SECRET = floriday-client_secret
STATUS = production_or_development
# SEQUELIZE CONFIG
DB_SCHEMA = edi
DB_USER = root
DB_PWD = root
DB_HOST = localhost
DB_DIALECT = mariadb
FORCE_SYNC = false
```
* [nodejs](https://nodejs.org/)
* [sequalize](https://sequelize.org/)

75
main.js
View File

@ -2,42 +2,59 @@ import * as vnUtils from './utils.js';
import { models } from './models/index.js';
import moment from 'moment';
console.log = (...args) => console.info(`${new moment().format('HH:mm:ss')} -`, ...args);
// Añade la hora a todos los console.log
// console.log = (...args) => console.info(`${new moment().format('HH:mm:ss')} -`, ...args);
async function main() {
let tokenExpirationDate = await vnUtils.getClientToken(models);
const env = process.env;
env.SYNC_SEQUENCE ? await vnUtils.syncSequence() : null;
env.SYNC_SUPPLIER ? await vnUtils.syncSuppliers() : null;
await vnUtils.syncConnections();
env.SYNC_TRADEITEM ? await vnUtils.syncTradeItems() : null;
console.log('Synced trade items');
try {
while (true) {
try{
console.log('Querying the API to check for new data...');
console.log('Current token expiration date: ', tokenExpirationDate);
if (moment().isAfter(tokenExpirationDate)) {
console.log('Token expired, getting a new one...');
tokenExpirationDate = await vnUtils.getClientToken(models);
const env = process.env;
let tokenExpirationDate = await vnUtils.getClientToken(models);
if (JSON.parse(env.SYNC_SEQUENCE)) await vnUtils.syncSequence()
if (JSON.parse(env.SYNC_SUPPLIER)) await vnUtils.syncSuppliers();
await vnUtils.syncConnections();
if (JSON.parse(env.SYNC_TRADEITEM)) await vnUtils.syncTradeItems();
console.log('Synced trade items');
try {
while (true) {
try{
console.log('Querying the API to check for new data...');
if (moment().isAfter(tokenExpirationDate)) {
console.log('Token expired, getting a new one...');
tokenExpirationDate = await vnUtils.getClientToken(models);
}
await vnUtils.syncSupplyLines();
} catch (err) {
console.error(err);
}
await vnUtils.syncSupplyLines();
} catch (error) {
console.error(error);
}
if (env.STATUS == 'development') {
await vnUtils.sleep(120000);
} else {
await vnUtils.sleep(300000);
if (JSON.parse(env.IS_PRODUCTION))
await vnUtils.sleep(300000);
else
await vnUtils.sleep(120000);
}
} catch (err) {
myErr(err);
}
} catch (error) {
console.error('Unable to connect to the database:', error);
} catch (err) {
myErr(err);
}
}
/**
* Creates the connection to the database.
*
* @param {err}
**/
function myErr(err) {
console.log(`[ERROR]`.red.bold, `${err.name}: ${err.message}`.red);
process.exit();
}
main()

View File

@ -16,7 +16,7 @@ console.log(
)
let sequelize = createConnection();
const conSpinner = ora('Creating the connection...').start();
const conSpinner = ora('Creating connection...').start();
try {
await sequelize.authenticate();
conSpinner.succeed();
@ -161,18 +161,18 @@ models.tradeItem.belongsTo(models.supplier, {
});
let action, force;
if (process.env.FORCE_SYNC === 'true') {
let action, isForce;
if (JSON.parse(process.env.FORCE_SYNC)) {
action = 'Forcing'
force = true
isForce = true
} else {
action = 'Altering'
force = false
isForce = false
}
const modSpinner = ora(`${action} the models...`).start();
const modSpinner = ora(`${action} models...`).start();
try {
await sequelize.sync({ force: force });
await sequelize.sync({ force: isForce });
if (process.env.SECRETS) {
await models.clientConfig.findOrCreate({
where: {

152
utils.js
View File

@ -24,6 +24,7 @@ async function getClientToken() {
throw colors.red.bold('No data found in the configuration table, ',
'if you have configured the .env file, declare the variable SECRET as true')
const spinner = ora(`Requesting token...`).start();
const now = moment().format('YYYY-MM-DD HH:mm:ss');
const tokenExpirationDate = clientConfigData[0].tokenExpiration;
@ -42,11 +43,11 @@ async function getClientToken() {
const tokenResponse = await tokenRequest.json();
if (tokenRequest.status === 200) {
console.log('Token request successful');
spinner.succeed();
} else {
throw new Error(
`Token request failed with status ${tokenRequest.status}`
);
spinner.fail();
throw new Error(`Token request failed with status: ${tokenRequest.status} - ${tokenRequest.statusText}`);
}
const accessToken = tokenResponse.access_token;
@ -65,7 +66,8 @@ async function getClientToken() {
return tokenExpirationDate;
} else {
console.log('Using the current token...');
spinner.text = 'Using stored token...'
spinner.succeed();
return tokenExpirationDate;
}
}
@ -81,7 +83,7 @@ async function getClientToken() {
*/
async function updateClientConfig(clientId, clientSecret, accessToken, tokenExpirationDate) {
try {
console.log('Updating the client config with the new token...');
const spinner = ora(`Updating config...`).start();
await models.clientConfig.upsert({
id: 1,
clientId: clientId,
@ -90,9 +92,9 @@ async function updateClientConfig(clientId, clientSecret, accessToken, tokenExpi
tokenExpiration: tokenExpirationDate,
requestLimit: 500,
});
console.log('Client config updated, new Token set');
console.log('New token expiration date: ', tokenExpirationDate);
spinner.succeed();
} catch (error) {
spinner.fail();
console.log('There was a error while updating the client config');
console.log(error);
}
@ -168,19 +170,23 @@ async function asyncQueue(fnArray, concurrency = 1) {
*/
async function syncSequence(current = 0, model = null , maximumSequenceNumber = 0){
if (model == null && current == 0){
let mockModels = [
'suppliers'.green,
'tradeItems'.blue,
'supplyLines'.yellow];
for (let mockModel in mockModels) {
const element = mockModels[mockModel];
console.log('Syncing sequence for:', element);
await syncSequence(0, element);
try {
let mockModels = [
'suppliers',
'tradeItems',
'supplyLines',
];
const spinner = ora(`Syncing sequence...`).start();
for (let mockModel in mockModels) {
const element = mockModels[mockModel];
await syncSequence(0, element);
}
spinner.succeed();
} catch (err) {
spinner.fail();
throw(err);
}
} else {
} else if (current) {
let tx = await models.sequelize.transaction();
@ -219,58 +225,69 @@ async function syncSequence(current = 0, model = null , maximumSequenceNumber =
}
async function syncSuppliers(){
let headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${await getJWT()}`,
'X-Api-Key': process.env.API_KEY
};
const response = await fetch(`${url}/organizations/current-max-sequence`, {
method: 'GET',
headers: headers
});
const maxSequenceNumber = await response.json();
let spinner;
for (let curSequenceNumber = 0; curSequenceNumber <= maxSequenceNumber; curSequenceNumber++) {
let query = `${url}/organizations/sync/${curSequenceNumber}?organizationType=SUPPLIER`;
let response = await fetch(query, {
try {
const spinner = ora('Preparing to load suppliers...').start();
let headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${await getJWT()}`,
'X-Api-Key': process.env.API_KEY
};
const response = await fetch(`${url}/organizations/current-max-sequence`, {
method: 'GET',
headers: headers
});
let data = await response.json();
let suppliers = data.results;
for (let supplier of suppliers) {
curSequenceNumber = supplier.sequenceNumber;
if (!spinner) {
spinner = ora('').start();
spinner.color = 'green';
}
spinner.text = `Loading suppliers ${curSequenceNumber} of ${maxSequenceNumber}`.green
await models.supplier.upsert({
sequenceNumber: supplier.sequenceNumber,
companyGln: supplier.companyGln,
name: supplier.name,
commercialName: supplier.commercialName,
email: supplier.email,
phone: supplier.phone,
website: supplier.website,
organizationId: supplier.organizationId,
rfhRelationId: supplier.rfhRelationId,
paymentProviders: `${supplier.paymentProviders}`,
endDate: supplier.endDate,
mailingAddress: supplier.mailingAddress,
physicalAddress: supplier.physicalAddress,
pythosanitaryNumber: supplier.pythosanitaryNumber,
organizationType: supplier.organizationType
const maxSequenceNumber = await response.json();
let timeFinish, timeToGoSec, timeToGoMin, timeLeft;
for (let curSequenceNumber = 0; curSequenceNumber <= maxSequenceNumber; curSequenceNumber++) {
let timeStart = new moment();
let query = `${url}/organizations/sync/${curSequenceNumber}?organizationType=SUPPLIER`;
let response = await fetch(query, {
method: 'GET',
headers: headers
});
let data = await response.json();
let suppliers = data.results;
for (let supplier of suppliers) {
curSequenceNumber = supplier.sequenceNumber;
spinner.text = `Loading suppliers, ${maxSequenceNumber - curSequenceNumber} are missing`
if (timeFinish)
spinner.text = spinner.text + ` (${timeLeft})`
await models.supplier.upsert({
sequenceNumber: supplier.sequenceNumber,
companyGln: supplier.companyGln,
name: supplier.name,
commercialName: supplier.commercialName,
email: supplier.email,
phone: supplier.phone,
website: supplier.website,
organizationId: supplier.organizationId,
rfhRelationId: supplier.rfhRelationId,
paymentProviders: `${supplier.paymentProviders}`,
endDate: supplier.endDate,
mailingAddress: supplier.mailingAddress,
physicalAddress: supplier.physicalAddress,
pythosanitaryNumber: supplier.pythosanitaryNumber,
organizationType: supplier.organizationType
});
}
await syncSequence(curSequenceNumber, 'suppliers', maxSequenceNumber);
timeFinish = new moment();
timeToGoSec = (timeFinish.diff(timeStart, 'seconds') * (maxSequenceNumber - curSequenceNumber) / 1000)
timeToGoMin = Math.trunc(timeToGoSec / 60)
if (!timeToGoMin)
timeLeft = `${Math.trunc(timeToGoSec)} sec`
else
timeLeft = `${timeToGoMin} min`
}
await syncSequence(curSequenceNumber, 'suppliers', maxSequenceNumber);
}
if (spinner)
spinner.succeed()
}
catch (err) {
spinner.fail();
throw(err);
}
}
async function syncConnections(){
@ -331,11 +348,8 @@ async function syncConnections(){
}
async function syncTradeItems(){
const suppliers = await models.supplier.findAll();
let i = 0;
console.log('Syncing trade items');
for (let supplier of suppliers) {
i++;