refs #4823 Added methods.yml and more
This commit is contained in:
parent
5aa27e45bd
commit
79c3582bb4
19
floriday.js
19
floriday.js
|
@ -1,8 +1,11 @@
|
||||||
import { checkCon, closeCon } from './models/sequelize.js';
|
import { checkCon, closeCon } from './models/sequelize.js';
|
||||||
import * as utils from './utils.js';
|
import * as utils from './utils.js';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
import yml from 'js-yaml';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
const env = process.env;
|
const env = process.env;
|
||||||
|
const flModels = yml.load(fs.readFileSync('./models/models.yml', 'utf8'));
|
||||||
|
|
||||||
class Floriday {
|
class Floriday {
|
||||||
async start() {
|
async start() {
|
||||||
|
@ -46,20 +49,14 @@ class Floriday {
|
||||||
|
|
||||||
async trunk() {
|
async trunk() {
|
||||||
try{
|
try{
|
||||||
const models = [
|
for (let model of flModels)
|
||||||
'organization',
|
|
||||||
'warehouse',
|
|
||||||
'tradeItem',
|
|
||||||
'supplyLine',
|
|
||||||
'clockPresaleSupply',
|
|
||||||
];
|
|
||||||
for (let model of models)
|
|
||||||
await utils.syncModel(model);
|
await utils.syncModel(model);
|
||||||
|
|
||||||
// await utils.syncConnections();
|
await utils.checkConnections();
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.name === 'SequelizeConnectionRefusedError') throw err;
|
if (['SequelizeConnectionRefusedError', 'SequelizeConnectionError'].includes(err.name))
|
||||||
|
throw err;
|
||||||
|
|
||||||
utils.criticalError(err);
|
utils.criticalError(err);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
connections:
|
||||||
|
base:
|
||||||
|
url: /connections/
|
||||||
|
sync:
|
||||||
|
url: /connections/sync/
|
||||||
|
maxSeq:
|
||||||
|
url: /connections/current-max-sequence
|
||||||
|
organizations:
|
||||||
|
base:
|
||||||
|
url: /organizations/
|
||||||
|
sync:
|
||||||
|
url: /organizations/sync/
|
||||||
|
params:
|
||||||
|
organizationType: SUPPLIER
|
||||||
|
maxSeq:
|
||||||
|
url: /organizations/current-max-sequence
|
||||||
|
warehouses:
|
||||||
|
base:
|
||||||
|
url: /warehouses/
|
||||||
|
sync:
|
||||||
|
url: /warehouses/sync/
|
||||||
|
maxSeq:
|
||||||
|
url: /warehouses/current-max-sequence
|
||||||
|
tradeItems:
|
||||||
|
base:
|
||||||
|
url: /trade-items/
|
||||||
|
sync:
|
||||||
|
url: /trade-items/sync/
|
||||||
|
params:
|
||||||
|
postFilterSelectedTradeItems: false
|
||||||
|
postFilterSelectedTradeItemPackingConfigurations: false
|
||||||
|
maxSeq:
|
||||||
|
url: /trade-items/current-max-sequence
|
||||||
|
supplyLines:
|
||||||
|
base:
|
||||||
|
url: /supply-lines/
|
||||||
|
sync:
|
||||||
|
url: /supply-lines/sync/
|
||||||
|
params:
|
||||||
|
postFilterSelectedTradeItems: false
|
||||||
|
maxSeq:
|
||||||
|
url: /supply-lines/current-max-sequence
|
||||||
|
clockPresalesSupply:
|
||||||
|
base:
|
||||||
|
url: /auction/clock-presales-supply/
|
||||||
|
sync:
|
||||||
|
url: /auction/clock-presales-supply/sync/
|
||||||
|
maxSeq:
|
||||||
|
url: /auction/clock-presales-supply/max-sequence-number
|
|
@ -0,0 +1,5 @@
|
||||||
|
- organizations
|
||||||
|
- warehouses
|
||||||
|
- tradeItems
|
||||||
|
- supplyLines
|
||||||
|
- clockPresalesSupply
|
File diff suppressed because it is too large
Load Diff
|
@ -18,6 +18,7 @@
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"chalk": "^5.2.0",
|
"chalk": "^5.2.0",
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
"mariadb": "^3.1.2",
|
"mariadb": "^3.1.2",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"ora": "^6.3.0",
|
"ora": "^6.3.0",
|
||||||
|
|
202
utils.js
202
utils.js
|
@ -1,12 +1,15 @@
|
||||||
import { models } from './models/sequelize.js';
|
import { models } from './models/sequelize.js';
|
||||||
import { Op } from 'sequelize';
|
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import ora from 'ora';
|
import ora from 'ora';
|
||||||
|
import yml from 'js-yaml';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
const env = process.env;
|
const env = process.env;
|
||||||
|
const methods = yml.load(fs.readFileSync('./methods.yml', 'utf8'));
|
||||||
|
const flModels = yml.load(fs.readFileSync('./models/models.yml', 'utf8'));
|
||||||
let spinner;
|
let spinner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,7 +18,7 @@ let spinner;
|
||||||
* @param {Boolean} isForce Force to request new token
|
* @param {Boolean} isForce Force to request new token
|
||||||
*/
|
*/
|
||||||
export async function requestToken(isForce = false) {
|
export async function requestToken(isForce = false) {
|
||||||
await startSpin(`Requesting new token...`, true);
|
await startSpin(`Checking token...`, true);
|
||||||
let optionalMsg;
|
let optionalMsg;
|
||||||
try {
|
try {
|
||||||
const clientConfigData = await models.config.findOne();
|
const clientConfigData = await models.config.findOne();
|
||||||
|
@ -27,6 +30,7 @@ export async function requestToken(isForce = false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isForce || !token || !tokenExpiration || moment().isAfter(tokenExpiration)) {
|
if (isForce || !token || !tokenExpiration || moment().isAfter(tokenExpiration)) {
|
||||||
|
await txtSpin(`Requesting new token...`, false);
|
||||||
const clientId = JSON.parse(env.USE_SECRETS_DB) ? clientConfigData.clientId || env.CLIENT_ID : env.CLIENT_ID;
|
const clientId = JSON.parse(env.USE_SECRETS_DB) ? clientConfigData.clientId || env.CLIENT_ID : env.CLIENT_ID;
|
||||||
const clientSecret = JSON.parse(env.USE_SECRETS_DB) ? clientConfigData.clientSecret || env.CLIENT_SECRET : env.CLIENT_SECRET;
|
const clientSecret = JSON.parse(env.USE_SECRETS_DB) ? clientConfigData.clientSecret || env.CLIENT_SECRET : env.CLIENT_SECRET;
|
||||||
|
|
||||||
|
@ -51,7 +55,6 @@ export async function requestToken(isForce = false) {
|
||||||
});
|
});
|
||||||
} else
|
} else
|
||||||
optionalMsg = 'Using stored token...';
|
optionalMsg = 'Using stored token...';
|
||||||
|
|
||||||
await okSpin(optionalMsg, true);
|
await okSpin(optionalMsg, true);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await failSpin(err, true);
|
await failSpin(err, true);
|
||||||
|
@ -127,7 +130,7 @@ export async function sleep(ms) {
|
||||||
/**
|
/**
|
||||||
* Sync a model.
|
* Sync a model.
|
||||||
*
|
*
|
||||||
* @param {String} model Supported models (organization | warehouse | tradeItem | supplyLine | clockPresaleSupply)
|
* @param {String} model Supported models (./models/methods.yml)
|
||||||
*/
|
*/
|
||||||
export async function syncModel(model) {
|
export async function syncModel(model) {
|
||||||
await startSpin(`Syncing ${model}...`, true);
|
await startSpin(`Syncing ${model}...`, true);
|
||||||
|
@ -136,72 +139,27 @@ export async function syncModel(model) {
|
||||||
const dbSeqNum = await models.sequenceNumber.findOne({ where: { model } })
|
const dbSeqNum = await models.sequenceNumber.findOne({ where: { model } })
|
||||||
let curSeqNum = dbSeqNum?.maxSequenceNumber ?? 0;
|
let curSeqNum = dbSeqNum?.maxSequenceNumber ?? 0;
|
||||||
|
|
||||||
let maxSeqUrl, syncUrl;
|
if (!flModels.includes(model))
|
||||||
switch (model) {
|
|
||||||
case 'organization':
|
|
||||||
maxSeqUrl = `${env.API_URL}/organizations/current-max-sequence`;
|
|
||||||
syncUrl = `${env.API_URL}/organizations/sync/`;
|
|
||||||
break;
|
|
||||||
case 'warehouse':
|
|
||||||
maxSeqUrl = `${env.API_URL}/warehouses/current-max-sequence`;
|
|
||||||
syncUrl = `${env.API_URL}/warehouses/sync/`;
|
|
||||||
break;
|
|
||||||
case 'tradeItem':
|
|
||||||
maxSeqUrl = `${env.API_URL}/trade-items/current-max-sequence`;
|
|
||||||
syncUrl = `${env.API_URL}/trade-items/sync/`;
|
|
||||||
break;
|
|
||||||
case 'supplyLine':
|
|
||||||
maxSeqUrl = `${env.API_URL}/supply-lines/current-max-sequence`;
|
|
||||||
syncUrl = `${env.API_URL}/supply-lines/sync/`;
|
|
||||||
break;
|
|
||||||
case 'clockPresaleSupply':
|
|
||||||
maxSeqUrl = `${env.API_URL}/auction/clock-presales-supply/max-sequence-number`;
|
|
||||||
syncUrl = `${env.API_URL}/auction/clock-presales-supply/sync/`;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error('Unsupported model');
|
throw new Error('Unsupported model');
|
||||||
}
|
|
||||||
|
|
||||||
const maxSeqNum = (await vnRequest('GET', maxSeqUrl)).data;
|
const maxSeqNum = (await vnRequest('GET', `${env.API_URL}${methods[model].maxSeq.url}`)).data;
|
||||||
for (curSeqNum; curSeqNum < maxSeqNum; curSeqNum++) {
|
for (curSeqNum; curSeqNum < maxSeqNum; curSeqNum++) {
|
||||||
let params, misSeqNum;
|
let params, misSeqNum;
|
||||||
if (model === 'organization')
|
|
||||||
params = new URLSearchParams({ organizationType: 'SUPPLIER'} ).toString();
|
|
||||||
else if (model === 'supplyLine' )
|
|
||||||
params = new URLSearchParams({ postFilterSelectedTradeItems: false }).toString();
|
|
||||||
else if (model === 'tradeItem')
|
|
||||||
params = new URLSearchParams({
|
|
||||||
postFilterSelectedTradeItems: false,
|
|
||||||
postFilterSelectedTradeItemPackingConfigurations: false,
|
|
||||||
}).toString();
|
|
||||||
|
|
||||||
const res = (await vnRequest('GET', `${syncUrl}${curSeqNum}${params ? `?${params}` : ''}`)).data;
|
if (methods[model].sync.params) {
|
||||||
curSeqNum = res.maximumSequenceNumber;
|
params = new URLSearchParams();
|
||||||
const objects = res.results;
|
for (const key in methods[model].sync.params) {
|
||||||
misSeqNum = maxSeqNum - curSeqNum;
|
params.append(key, methods[model].sync.params[key]);
|
||||||
txtSpin(`Syncing ${i} ${model}, ${misSeqNum} missing...`);
|
}
|
||||||
switch (model) {
|
params = params.toString();
|
||||||
case 'organization':
|
|
||||||
await insertOrganizations(objects);
|
|
||||||
break;
|
|
||||||
case 'warehouse':
|
|
||||||
await insertWarehouses(objects);
|
|
||||||
break;
|
|
||||||
case 'tradeItem':
|
|
||||||
await insertTradeItems(objects);
|
|
||||||
break;
|
|
||||||
case 'supplyLine':
|
|
||||||
await insertSupplyLines(objects);
|
|
||||||
break;
|
|
||||||
case 'clockPresaleSupply':
|
|
||||||
await insertClockPresalesSupply(objects);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new Error('Unsupported model');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
txtSpin(`Syncing ${i = i + objects.length} ${model}, ${misSeqNum} missing...`);
|
const res = (await vnRequest('GET', `${env.API_URL}${methods[model].sync.url}${curSeqNum}${params ? `?${params}` : ''}`)).data;
|
||||||
|
const data = res.results;
|
||||||
|
curSeqNum = res.maximumSequenceNumber;
|
||||||
|
misSeqNum = maxSeqNum - curSeqNum;
|
||||||
|
await insertModel(model, data)
|
||||||
|
txtSpin(`Syncing ${i = i + data.length} ${model}, ${misSeqNum} missing...`);
|
||||||
await insertSequenceNumber(model, curSeqNum);
|
await insertSequenceNumber(model, curSeqNum);
|
||||||
}
|
}
|
||||||
await insertSequenceNumber(model, maxSeqNum);
|
await insertSequenceNumber(model, maxSeqNum);
|
||||||
|
@ -214,47 +172,39 @@ export async function syncModel(model) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert a model.
|
||||||
|
*/
|
||||||
|
export async function insertModel(model, data) {
|
||||||
|
switch (model) {
|
||||||
|
case 'organizations':
|
||||||
|
await insertOrganizations(data);
|
||||||
|
break;
|
||||||
|
case 'warehouses':
|
||||||
|
await insertWarehouses(data);
|
||||||
|
break;
|
||||||
|
case 'tradeItems':
|
||||||
|
await insertTradeItems(data);
|
||||||
|
break;
|
||||||
|
case 'supplyLines':
|
||||||
|
await insertSupplyLines(data);
|
||||||
|
break;
|
||||||
|
case 'clockPresalesSupply':
|
||||||
|
await insertClockPresalesSupply(data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('Unsupported model');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the connections in Floriday.
|
* Check (create and/or remove) the connections in Floriday.
|
||||||
*/
|
*/
|
||||||
export async function syncConnections(){
|
export async function checkConnections(){
|
||||||
await deleteConnections();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let connectionsInDb = await models.organization.findAll({
|
startSpin('Checking connections...', true);
|
||||||
where: {
|
await createConnections();
|
||||||
isConnected: true,
|
await deleteConnections();
|
||||||
companyGln: {
|
|
||||||
[Op.ne]: null
|
|
||||||
},
|
|
||||||
rfhRelationId: {
|
|
||||||
[Op.ne]: null
|
|
||||||
},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const connectionsInFloriday = (await vnRequest('GET', `${env.API_URL}/connections`)).data;
|
|
||||||
|
|
||||||
let isExists = false, connectionsToPut = [];
|
|
||||||
for (let connectionInDb of connectionsInDb) {
|
|
||||||
for (let connectionInFloriday of connectionsInFloriday)
|
|
||||||
if (connectionInFloriday == connectionInDb.organizationId) {
|
|
||||||
isExists = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!isExists) connectionsToPut.push(connectionInDb.organizationId)
|
|
||||||
isExists = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (connectionsToPut.length)
|
|
||||||
await startSpin(`Creating connections in Floriday...`, true);
|
|
||||||
|
|
||||||
let i = 1;
|
|
||||||
for (let connection of connectionsToPut) {
|
|
||||||
txtSpin(`Creating ${i++} of ${connectionsToPut.length} connections in Floriday...`);
|
|
||||||
await vnRequest('PUT', `${env.API_URL}/connections/${connection}`);
|
|
||||||
}
|
|
||||||
await okSpin(null, true);
|
await okSpin(null, true);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await failSpin(err, true);
|
await failSpin(err, true);
|
||||||
|
@ -695,37 +645,52 @@ export async function insertSupplyLines(supplyLines) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the connections in Floriday of the connected organizations.
|
||||||
|
**/
|
||||||
|
export async function createConnections() {
|
||||||
|
try {
|
||||||
|
const flConnections = (await vnRequest('GET', `${env.API_URL}${methods.connections.base.url}`)).data;
|
||||||
|
const dbConnections = await models.organization.findAll({
|
||||||
|
where: { isConnected: true }
|
||||||
|
});
|
||||||
|
|
||||||
|
let connectionsToPut = [], i = 1;
|
||||||
|
dbConnections.forEach(valor => {
|
||||||
|
if (!flConnections.includes(valor.organizationId))
|
||||||
|
connectionsToPut.push(valor.organizationId);
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let connection of connectionsToPut) {
|
||||||
|
await vnRequest('PUT', `${env.API_URL}${methods.connections.base.url}${connection}`);
|
||||||
|
txtSpin(`Creating ${i++} connections, ${connectionsToPut.length - i} missing...`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes Floriday connections that we don't have in the database.
|
* Removes Floriday connections that we don't have in the database.
|
||||||
**/
|
**/
|
||||||
export async function deleteConnections() {
|
export async function deleteConnections() {
|
||||||
try {
|
try {
|
||||||
let i = 1;
|
const flConnections = (await vnRequest('GET', `${env.API_URL}/connections`)).data;
|
||||||
const connectionsInFloriday = (await vnRequest('GET', `${env.API_URL}/connections`)).data;
|
const dbConnections = await models.organization.findAll({
|
||||||
const connectionsInDb = await models.organization.findAll({
|
|
||||||
attributes: ['organizationId'],
|
attributes: ['organizationId'],
|
||||||
where: { isConnected: true }
|
where: { isConnected: true }
|
||||||
});
|
});
|
||||||
|
|
||||||
let isExists = false, ghostConnections = [];
|
let ghostConnections = [], i = 1;
|
||||||
for (let connectionInFloriday of connectionsInFloriday) {
|
flConnections.forEach(valor => {
|
||||||
for (let connectionInDb of connectionsInDb)
|
if (!dbConnections.includes(valor))
|
||||||
if (connectionInFloriday == connectionInDb.organizationId) {
|
ghostConnections.push(valor);
|
||||||
isExists = true;
|
});
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!isExists) ghostConnections.push(connectionInFloriday)
|
|
||||||
isExists = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ghostConnections.length)
|
|
||||||
await startSpin(`Deleting connections that aren't in the db...`, true);
|
|
||||||
|
|
||||||
for (let connection of ghostConnections) {
|
for (let connection of ghostConnections) {
|
||||||
await vnRequest('DELETE', `${env.API_URL}/connections/${connection}`);
|
await vnRequest('DELETE', `${env.API_URL}/connections/${connection}`);
|
||||||
txtSpin(`Deleting ${i++} of ${ghostConnections.length} connections that aren't in the db...`);
|
txtSpin(`Deleting ${i++} connections, ${ghostConnections.length - i} missing...`);
|
||||||
}
|
}
|
||||||
await okSpin(null, true);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
await criticalSpin(err);
|
await criticalSpin(err);
|
||||||
}
|
}
|
||||||
|
@ -818,7 +783,6 @@ export async function startSpin(msg, isNew) {
|
||||||
? spinner.start()
|
? spinner.start()
|
||||||
: spinner = ora({
|
: spinner = ora({
|
||||||
text: msg,
|
text: msg,
|
||||||
indent: 1,
|
|
||||||
spinner: 'arc',
|
spinner: 'arc',
|
||||||
interval: 40,
|
interval: 40,
|
||||||
color: 'white',
|
color: 'white',
|
||||||
|
|
Loading…
Reference in New Issue