refs #4823 ESModule-to-CommonJS

This commit is contained in:
Guillermo Bonet 2023-03-14 13:30:54 +01:00
parent c57916815d
commit ad38daebe9
23 changed files with 406 additions and 328 deletions

18
.env_template Normal file
View File

@ -0,0 +1,18 @@
# FLORIDAY SERVICE CONFIG
clientId = floriday-client_id
clientSecret = floriday-client_secret
environment = production_or_development
# SEQUELIZE CONFIG
dbHost = localhost
dbPort = 3306
dbSchema = floriday
dbUser = root
dbPwd = root
dbDialect = mariadb
forceCreateSchema = false
forceSync = false
putSecrets = false
syncSequence = true
syncSuplier = true
syncTradeItem = true

View File

@ -7,7 +7,7 @@ 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.
This is done using the [Sequelize](https://sequelize.org/) ORM.
2. Query the Floriday API and store the data in the database.
This is done using the [node-fetch](https://www.npmjs.com/package/node-fetch) package.
This is done using the [axios](https://www.npmjs.com/package/axios) package.
2.1. The data is requested every minute, but only the data that has changed is stored in the database.
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.
@ -59,7 +59,6 @@ import foo from "./foo";
let models = {
bar: foo(sequelize),
};
```
To install dependencies:
@ -71,23 +70,9 @@ npm install
To run:
```bash
npm start # run the service
npm dev-sync # run and create the db structure
node main # Run the service
```
### .env file
## Config 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
```
Rename '.env_emplate' → '.env'

View File

@ -1,51 +0,0 @@
import moment from 'moment';
import * as vnUtils from './utils.js';
//import cliProgress from 'cli-progress';
import dotenv from 'dotenv';
dotenv.config();
import { models } from './models/index.js';
console.log = function () {
let args = Array.prototype.slice.call(arguments);
args.unshift(new moment().format('HH:mm:ss') + ' -');
console.info.apply(console, args);
};
let tokenExpirationDate = await vnUtils.getClientToken(models);
process.env.SYNC_SEQUENCE ? await vnUtils.syncSequence() : null;
process.env.SYNC_SUPPLIER ? await vnUtils.syncSuppliers() : null;
await vnUtils.syncConnections();
process.env.SYNC_TRADEITEM ? await vnUtils.syncTradeItems() : null;
console.log('Synced trade items');
try {
// eslint-disable-next-line no-constant-condition
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);
}
await vnUtils.syncSupplyLines();
} catch (error) {
console.error(error);
}
if (process.env.STATUS == 'development') {
await vnUtils.sleep(120000);
} else {
await vnUtils.sleep(300000);
}
}
} catch (error) {
console.error('Unable to connect to the database:', error);
}

51
main.js Normal file
View File

@ -0,0 +1,51 @@
const moment = require('moment');
const { models } = require('./models/index.js');
const vnUtils = require('./utils.js');
require('dotenv').config()
// const cliProgress = require('cli-progress');
async function main() {
console.log = function () {
let args = Array.prototype.slice.call(arguments);
args.unshift(new moment().format('HH:mm:ss') + ' -');
console.info.apply(console, args);
};
let tokenExpirationDate = vnUtils.getClientToken(models);
process.env.syncSequence ? await vnUtils.syncSequence() : null;
process.env.syncSupplier ? await vnUtils.syncSuppliers() : null;
await vnUtils.syncConnections();
process.env.syncTradeItem ? await vnUtils.syncTradeItems() : null;
console.log('Synced trade items');
try {
// eslint-disable-next-line no-constant-condition
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);
}
await vnUtils.syncSupplyLines();
} catch (error) {
console.error(error);
}
if (process.env.environment == 'development') {
await vnUtils.sleep(120000);
} else {
await vnUtils.sleep(300000);
}
}
} catch (error) {
console.error('Unable to connect to the database:', error);
}
}
main();

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const clientConfig = {
id: {
@ -23,7 +23,7 @@ const clientConfig = {
},
};
export default (sequelize) => {
module.exports = function (sequelize) {
const ClientConfig = sequelize.define(
'FDClientConfig',
clientConfig,

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const sequenceNumber = {
id: {
@ -21,7 +21,7 @@ const sequenceNumber = {
},
};
export default (sequelize) => {
module.exports = function (sequelize) {
const sequenceNumbers = sequelize.define(
'FDsequenceNumber',
sequenceNumber,
@ -31,4 +31,4 @@ export default (sequelize) => {
}
);
return sequenceNumbers;
};
};

View File

@ -1,33 +1,35 @@
import { Sequelize } from 'sequelize';
import dotenv from 'dotenv';
dotenv.config();
const { Sequelize } = require ('sequelize');
const colors = require('colors');
require('dotenv').config()
console.clear();
const decoration = '△▽'.repeat(10);
const appName = colors.bold.green('Floriday Service');
console.log(`${decoration} ${appName} ${decoration}`);
let sequelize = createConnection();
// Supply Line Models
import supplyLine from './supplyLine/supplyLine.js';
import volumePrices from './supplyLine/volumePrices.js';
main();
// Conf Models
import clientConfig from './conf/clientConfig.js';
import sequenceNumber from './conf/sequenceNumber.js';
const clientConfig = require('./conf/clientConfig.js');
const sequenceNumber = require('./conf/sequenceNumber.js');
// Supply Line Models
const supplyLine = require('./supplyLine/supplyLine.js');
const volumePrices = require('./supplyLine/volumePrices.js');
// Supplier Models
import suppliers from './supplier/suppliers.js';
import connections from './supplier/connections.js';
const suppliers = require('./supplier/suppliers.js');
const connections = require('./supplier/connections.js');
// TradeItem Models
import tradeItem from './tradeItem/tradeItem.js';
import botanicalNames from './tradeItem/botanicalNames.js';
import countryOfOriginIsoCodes from './tradeItem/countryOfOriginIsoCodes.js';
import packageModel from './tradeItem/package.js';
import packingConfigurations from './tradeItem/packingConfigurations.js';
import photos from './tradeItem/photos.js';
import seasonalPeriod from './tradeItem/seasonalPeriod.js';
import characteristics from './tradeItem/characteristics.js';
const tradeItem = require('./tradeItem/tradeItem.js');
const botanicalNames = require('./tradeItem/botanicalNames.js');
const countryOfOriginIsoCodes = require('./tradeItem/countryOfOriginIsoCodes.js');
const packageModel = require('./tradeItem/package.js');
const packingConfigurations = require('./tradeItem/packingConfigurations.js');
const photos = require('./tradeItem/photos.js');
const seasonalPeriod = require('./tradeItem/seasonalPeriod.js');
const characteristics = require('./tradeItem/characteristics.js');
/**
* Contains all the models that are related to the application.
@ -46,7 +48,6 @@ import characteristics from './tradeItem/characteristics.js';
* foo: 'bar',
* });
*
*
* @type {Object.<string, Sequelize.Model>}
*/
let models = {
@ -80,86 +81,85 @@ models.characteristic.belongsTo(models.tradeItem, {
as: 'tradeItem_Fk',
targetKey: 'tradeItemId',
});
models.seasonalPeriod.belongsTo(models.tradeItem, {
foreignKey: 'tradeItemFk',
as: 'tradeItem_Fk',
targetKey: 'tradeItemId',
});
models.photo.belongsTo(models.tradeItem, {
foreignKey: 'tradeItemFk',
as: 'tradeItem_Fk',
targetKey: 'tradeItemId',
});
models.packingConfiguration.belongsTo(models.tradeItem, {
foreignKey: 'tradeItemFk',
as: 'tradeItem_Fk',
targetKey: 'tradeItemId',
});
models.packingConfiguration.hasMany(models.package, {
foreignKey: 'packingConfigurationFk',
as: 'package_Fk',
targetKey: 'packingConfigurationId',
});
models.package.belongsTo(models.packingConfiguration, {
foreignKey: 'packingConfigurationFk',
as: 'packingConfiguration_Fk',
targetKey: 'packingConfigurationId',
});
models.botanicalName.belongsTo(models.tradeItem, {
foreignKey: 'tradeItemFk',
as: 'tradeItem_Fk',
targetKey: 'tradeItemId',
});
models.countryOfOriginIsoCode.belongsTo(models.tradeItem, {
foreignKey: 'tradeItemFk',
as: 'tradeItem_Fk',
targetKey: 'tradeItemId',
});
models.volumePrice.belongsTo(models.supplyLine, {
foreignKey: 'supplyLineFk',
as: 'supplyLine_Fk',
targetKey: 'supplyLineId',
});
models.supplyLine.belongsTo(models.tradeItem, {
foreignKey: 'tradeItemFk',
as: 'tradeItem_Fk',
targetKey: 'tradeItemId',
});
models.tradeItem.belongsTo(models.supplier, {
foreignKey: 'supplierOrganizationId',
as: 'supplierOrganization_Id',
targetKey: 'organizationId',
});
if (process.env.FORCE_SYNC === 'true') {
console.log('Forcing the models...');
await sequelize.sync({ force: true });
} else {
console.log('Altering the models...');
await sequelize.sync({ alter: true });
}
async function main() {
const conf = process.env;
try {
if (conf.forceCreateSchema == 'true')
await sequelize.createSchema(conf.dbSchema, { ifNotExists: true });
if (process.env.SECRETS) {
await models.clientConfig.findOrCreate({
where: {
id: 1,
},
defaults: {
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
},
});
if (conf.forceSync === 'true') {
console.log('Forcing the models...');
await sequelize.sync({ force: true });
} else {
console.log('Altering the models...');
await sequelize.sync({ alter: true });
}
} catch (err) {
sendError(err.original.text)
}
if (conf.putSecrets === 'true') {
await models.clientConfig.findOrCreate({
where: {
id: 1,
},
defaults: {
clientId: conf.clientId,
clientSecret: conf.clientSecret,
},
});
}
}
/**
@ -171,10 +171,13 @@ if (process.env.SECRETS) {
* @returns {Sequelize} Sequelize instance with the connection to the database.
*/
function createConnection() {
console.log('Creating the connection...');
return new Sequelize(process.env.DB_SCHEMA, process.env.DB_USER, process.env.DB_PWD, {
host: process.env.DB_HOST,
dialect: process.env.DB_DIALECT,
const conf = process.env;
console.log('Creating the connection...'.green.bold);
try {
return new Sequelize(conf.dbSchema, conf.dbUser, conf.dbPwd, {
host: conf.dbHost,
dialect: conf.dbDialect,
port: conf.dbPort,
logging: false,
pool: {
max: 40,
@ -183,6 +186,16 @@ function createConnection() {
idle: 10000,
},
});
} catch (err) {
sendError(err);
}
}
export { models } ;
/**
* Error message
*/
function sendError(msg) {
throw colors.red.bold(msg)
}
module.exports = { models };

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const connections = {
organizationId: {
@ -12,7 +12,7 @@ const connections = {
},
};
export default (sequelize) => {
module.exports = function (sequelize) {
const connection = sequelize.define(
'FDconnections',
connections,
@ -22,4 +22,4 @@ export default (sequelize) => {
}
);
return connection;
};
};

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const suppliers = {
isConnected: {
@ -55,10 +55,14 @@ const suppliers = {
},
};
export default (sequelize) => {
const Suppliers = sequelize.define('FDsuppliers', suppliers, {
timestamps: false,
freezeTableName: true,
});
module.exports = function (sequelize) {
const Suppliers = sequelize.define(
'FDsuppliers',
suppliers,
{
timestamps: false,
freezeTableName: true,
}
);
return Suppliers;
};

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const supplyLine = {
supplyLineId: {
@ -52,12 +52,14 @@ const supplyLine = {
}
};
export default (sequelize) => {
const SupplyLine = sequelize.define('FDsupplyLine', supplyLine, {
timestamps: false,
freezeTableName: true,
});
module.exports = function (sequelize) {
const SupplyLine = sequelize.define(
'FDsupplyLine',
supplyLine,
{
timestamps: false,
freezeTableName: true,
}
);
return SupplyLine;
};

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const volumePrices = {
id: {
@ -14,10 +14,14 @@ const volumePrices = {
},
};
export default (sequelize) => {
const VolumePrices = sequelize.define('FDvolumePrices', volumePrices, {
timestamps: false,
freezeTableName: true,
});
module.exports = function (sequelize) {
const VolumePrices = sequelize.define(
'FDvolumePrices',
volumePrices,
{
timestamps: false,
freezeTableName: true,
}
);
return VolumePrices;
};

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const botanicalNames = {
name: {
@ -6,10 +6,14 @@ const botanicalNames = {
},
};
export default (sequelize) => {
const BotanicalNames = sequelize.define('FDbotanicalNames', botanicalNames, {
timestamps: false,
freezeTableName: true,
});
module.exports = function (sequelize) {
const BotanicalNames = sequelize.define(
'FDbotanicalNames',
botanicalNames,
{
timestamps: false,
freezeTableName: true,
}
);
return BotanicalNames;
};
};

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const characteristics = {
vbnCode: {
@ -9,7 +9,7 @@ const characteristics = {
},
};
export default (sequelize) => {
module.exports = function (sequelize) {
const Characteristics = sequelize.define(
'FDcharacteristics',
characteristics,
@ -19,4 +19,4 @@ export default (sequelize) => {
}
);
return Characteristics;
};
};

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const countryOfOriginIsoCodes = {
isoCode: {
@ -6,7 +6,7 @@ const countryOfOriginIsoCodes = {
},
};
export default (sequelize) => {
module.exports = function (sequelize) {
const CountryOfOriginIsoCodes = sequelize.define(
'FDcountryOfOriginIsoCodes',
countryOfOriginIsoCodes,

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const PackageModel = {
vbnPackageCode: {
@ -9,10 +9,14 @@ const PackageModel = {
},
};
export default (sequelize) => {
const Package = sequelize.define('FDpackage', PackageModel, {
timestamps: false,
freezeTableName: true,
});
module.exports = function (sequelize) {
const Package = sequelize.define(
'FDpackage',
PackageModel,
{
timestamps: false,
freezeTableName: true,
}
);
return Package;
};
};

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const packingConfigurations = {
packingConfigurationId: {
@ -34,7 +34,7 @@ const packingConfigurations = {
},
};
export default (sequelize) => {
module.exports = function (sequelize) {
const PackingConfigurations = sequelize.define(
'FDpackingConfigurations',
packingConfigurations,
@ -44,4 +44,4 @@ export default (sequelize) => {
}
);
return PackingConfigurations;
};
};

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const photos = {
id: {
@ -16,10 +16,14 @@ const photos = {
},
};
export default (sequelize) => {
const Photos = sequelize.define('FDphotos', photos, {
timestamps: false,
freezeTableName: true,
});
module.exports = function (sequelize) {
const Photos = sequelize.define(
'FDphotos',
photos,
{
timestamps: false,
freezeTableName: true,
}
);
return Photos;
};
};

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const seasonalPeriod = {
id: {
@ -14,10 +14,14 @@ const seasonalPeriod = {
},
};
export default (sequelize) => {
const SeasonalPeriod = sequelize.define('FDseasonalPeriod', seasonalPeriod, {
timestamps: false,
freezeTableName: true,
});
module.exports = function (sequelize) {
const SeasonalPeriod = sequelize.define(
'FDseasonalPeriod',
seasonalPeriod,
{
timestamps: false,
freezeTableName: true,
}
);
return SeasonalPeriod;
};

View File

@ -1,4 +1,4 @@
import { Sequelize } from 'sequelize';
const { Sequelize } = require('sequelize');
const tradeItem = {
tradeItemId: {
@ -37,10 +37,14 @@ const tradeItem = {
}
};
export default (sequelize) => {
const TradeItem = sequelize.define('FDtradeItem', tradeItem, {
timestamps: false,
freezeTableName: true,
});
module.exports = function (sequelize) {
const TradeItem = sequelize.define(
'FDtradeItem',
tradeItem,
{
timestamps: false,
freezeTableName: true,
}
);
return TradeItem;
};

172
package-lock.json generated
View File

@ -1,22 +1,28 @@
{
"name": "floriday",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "floriday",
"version": "1.0.0",
"dependencies": {
"axios": "^1.3.4",
"cli-progress": "^3.11.2",
"colors": "^1.4.0",
"dotenv": "^16.0.3",
"mariadb": "^3.0.2",
"moment": "^2.29.4",
"node-fetch": "^3.3.0",
"sequelize": "^6.26.0",
"uuid": "^9.0.0"
},
"devDependencies": {
"eslint": "^8.31.0"
},
"engines": {
"node": ">=15",
"npm": ">=8"
}
},
"node_modules/@eslint/eslintrc": {
@ -204,6 +210,21 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/axios": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -282,6 +303,17 @@
"node": ">=0.1.90"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -302,14 +334,6 @@
"node": ">= 8"
}
},
"node_modules/data-uri-to-buffer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz",
"integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==",
"engines": {
"node": ">= 12"
}
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -332,6 +356,14 @@
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
@ -573,28 +605,6 @@
"reusify": "^1.0.4"
}
},
"node_modules/fetch-blob": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "paypal",
"url": "https://paypal.me/jimmywarting"
}
],
"dependencies": {
"node-domexception": "^1.0.0",
"web-streams-polyfill": "^3.0.3"
},
"engines": {
"node": "^12.20 || >= 14.13"
}
},
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@ -642,15 +652,36 @@
"integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
"dev": true
},
"node_modules/formdata-polyfill": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
"node_modules/follow-redirects": {
"version": "1.15.2",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"fetch-blob": "^3.1.2"
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">=12.20.0"
"node": ">= 6"
}
},
"node_modules/fs.realpath": {
@ -931,6 +962,25 @@
"node": ">= 12"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@ -973,41 +1023,6 @@
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
"node_modules/node-domexception": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/jimmywarting"
},
{
"type": "github",
"url": "https://paypal.me/jimmywarting"
}
],
"engines": {
"node": ">=10.5.0"
}
},
"node_modules/node-fetch": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz",
"integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==",
"dependencies": {
"data-uri-to-buffer": "^4.0.0",
"fetch-blob": "^3.1.4",
"formdata-polyfill": "^4.0.10"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/node-fetch"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@ -1117,6 +1132,11 @@
"node": ">= 0.8.0"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
@ -1456,14 +1476,6 @@
"node": ">= 0.10"
}
},
"node_modules/web-streams-polyfill": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
"integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
"engines": {
"node": ">= 8"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -1,25 +1,23 @@
{
"name": "floriday",
"module": "index.ts",
"type": "module",
"scripts": {
"start": "node index.js",
"dev-sync": "FORCE_SYNC=true node --max-old-space-size=4096 index.js",
"dev-secrets": "SECRETS=true node --max-old-space-size=4096 index.js",
"dev-both": "FORCE_SYNC=true SECRETS=true node --max-old-space-size=4096 index.js",
"dev-query": "QUERYSUPPLIERS=true SECRETS=true node --max-old-space-size=4096 index.js"
},
"version": "1.0.0",
"author": "Verdnatura Levante SL",
"description": "Floriday Service",
"dependencies": {
"axios": "^1.3.4",
"cli-progress": "^3.11.2",
"colors": "^1.4.0",
"dotenv": "^16.0.3",
"mariadb": "^3.0.2",
"moment": "^2.29.4",
"node-fetch": "^3.3.0",
"sequelize": "^6.26.0",
"uuid": "^9.0.0"
},
"devDependencies": {
"eslint": "^8.31.0"
},
"engines": {
"node": ">=15",
"npm": ">=8"
}
}

View File

@ -6,4 +6,4 @@ let floraholland = [
8718288004970,
];
export default {floraholland};
module.exports = {floraholland};

106
utils.js
View File

@ -1,17 +1,15 @@
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';
import colors from 'colors';
//import cliProgress from 'cli-progress';
dotenv.config();
const moment = require('moment');
const axios = require('axios');
const { models } = require('./models/index.js');
const { v4: uuidv4 } = require('uuid');
const colors = require('colors');
require('dotenv').config()
// const cliProgress = require('cli-progress');
/**
* The Endpoint where the Access Token is requested
*/
const _accessTokenEndpoint = 'https://idm.staging.floriday.io/oauth2/ausmw6b47z1BnlHkw0h7/v1/token';
const BASE_CUSTOMER_URL = 'https://api.staging.floriday.io/customers-api/2022v2/';
/**
@ -32,13 +30,18 @@ async function getClientToken() {
if (clientConfigData[0].tokenExpiration == null || moment(now).isAfter(tokenExpirationDate)) {
let clientId = clientConfigData[0].clientId;
let clientSecret = clientConfigData[0].clientSecret;
let myBody = `grant_type=client_credentials&client_id=${clientId}
&client_secret=${clientSecret}
&scope=role:app catalog:read
supply:read organization:read
network:write network:read`
const tokenRequest = await fetch(_accessTokenEndpoint, {
const tokenRequest = await axios(_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:write network:read`,
body: myBody,
});
const tokenResponse = await tokenRequest.json();
@ -101,7 +104,7 @@ async function updateClientConfig(clientId, clientSecret, accessToken, tokenExpi
}
/**
* returns the current Access Token
* Returns the current Access Token.
*
* @returns
*/
@ -111,7 +114,7 @@ async function getJWT() {
}
/**
* pauses the execution of the script for the given amount of milliseconds
* Pauses the execution of the script for the given amount of milliseconds.
*
* @param {integer} ms
* @returns A promise that resolves after ms milliseconds.
@ -133,7 +136,9 @@ async function asyncQueue(fnArray, concurrency = 1) {
const results = []; // 1
const queue = fnArray.map((fn, index) => () => fn().then((result) => results[index] = result));
const queue = fnArray.map(
(fn, index) => () => fn().then((result) => results[index] = result)
);
const run = async () => { // 2
const fn = queue.shift();
@ -168,21 +173,17 @@ async function asyncQueue(fnArray, concurrency = 1) {
* @param {Number} maximumSequenceNumber - maximum sequence number
* @returns
*/
async function syncSequence(current = 0, model = null ,maximumSequenceNumber = 0){
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];
for (let mockModel in mockModels) {
const element = mockModels[mockModel];
console.log('Syncing sequence for: ', element);
await syncSequence(0, element);
}
} else {
let tx = await models.sequelize.transaction();
try {
let sequence = await models.sequenceNumber.findOrCreate({
@ -208,9 +209,8 @@ async function syncSequence(current = 0, model = null ,maximumSequenceNumber = 0
transaction: tx
});
}
await tx.commit();
} catch (error) {
await tx.rollback();
console.log('Error while syncing sequence number for: ', model);
@ -226,19 +226,20 @@ async function syncSuppliers(){
'X-Api-Key': process.env.API_KEY
};
let maximumSequenceNumber = await fetch(`${BASE_CUSTOMER_URL}organizations/current-max-sequence`, {
const curMaxSeqUrl = `${BASE_CUSTOMER_URL}organizations/current-max-sequence`;
let maximumSequenceNumber = await axios(curMaxSeqUrl, {
method: 'GET',
headers: headers
});
maximumSequenceNumber = await maximumSequenceNumber.json();
console.log('Maximum sequence number: ', maximumSequenceNumber);
for (let i = 0; i < maximumSequenceNumber; i++) {
let query = `${BASE_CUSTOMER_URL}organizations/sync/${i}?organizationType=SUPPLIER&limit=1000`;
let response = await fetch(query, {
let response = await axios(query, {
method: 'GET',
headers: headers
});
@ -267,7 +268,10 @@ async function syncSuppliers(){
organizationType: supplier.organizationType,
paymentProviders: `${supplier.paymentProviders}`,
});
console.log('INSERTED:\t', supplier.commercialName, '\nsequenceNumber:\t', supplier.sequenceNumber);
console.log(
'INSERTED:\t', supplier.commercialName,
'\nsequenceNumber:\t', supplier.sequenceNumber
);
}
await syncSequence(i, 'suppliers', maximumSequenceNumber);
}
@ -282,7 +286,7 @@ async function syncConnections(){
'X-Api-Key': process.env.API_KEY
};
let remoteConnections = await fetch(`${BASE_CUSTOMER_URL}connections`, {
let remoteConnections = await axios(`${BASE_CUSTOMER_URL}connections`, {
method: 'GET',
headers: headers
});
@ -293,12 +297,14 @@ async function syncConnections(){
if (connection.isConnected == false){
continue;
}
let remoteConnection = remoteConnections.find(remoteConnection => remoteConnection == connection.organizationId);
let remoteConnection = remoteConnections.find(
remoteConnection => remoteConnection == connection.organizationId
);
if (remoteConnection == undefined){
console.log('Connection: ', connection, 'does not exist in the remote server');
console.log('Creating remote connection');
await fetch(`${BASE_CUSTOMER_URL}connections/${connection.organizationId}`, {
await axios(`${BASE_CUSTOMER_URL}connections/${connection.organizationId}`, {
method: 'PUT',
headers: headers
});
@ -354,7 +360,7 @@ async function syncTradeItems(){
try {
let request = await fetch(query, {
let request = await axios(query, {
method: 'GET',
headers: headers
});
@ -424,10 +430,13 @@ async function syncSupplyLines(){
// eslint-disable-next-line no-async-promise-executor
let promise = new Promise(async (resolve) => {
try {
let url = `${BASE_CUSTOMER_URL}supply-lines/sync/0?
supplierOrganizationId=${supplier.organizationId}
&tradeItemId=${tradeItem.tradeItemId}
&limit=100
&postFilterSelectedTradeItems=false`;
let url = `${BASE_CUSTOMER_URL}supply-lines/sync/0?supplierOrganizationId=${supplier.organizationId}&tradeItemId=${tradeItem.tradeItemId}&limit=100&postFilterSelectedTradeItems=false`;
let request = await fetch(url, {
let request = await axios(url, {
method: 'GET',
headers: headers
});
@ -435,7 +444,10 @@ async function syncSupplyLines(){
let supplyLines = await request.json();
if (supplyLines.length == 0) {
console.log('No supply lines for supplier: ', supplier.commercialName, ' - ' , tradeItem.name);
console.log(
'No supply lines for supplier: ', supplier.commercialName,
' - ' , tradeItem.name
);
resolve([]);
return;
}
@ -443,7 +455,10 @@ async function syncSupplyLines(){
resolve(supplyLines);
} catch (error) {
console.log('Error while syncing supply lines for: ', supplier.commercialName, ' - ' , tradeItem.name);
console.log(
'Error while syncing supply lines for: ', supplier.commercialName,
' - ' , tradeItem.name
);
console.log(error);
resolve([]);
}
@ -474,7 +489,7 @@ async function syncSupplyLines(){
let urlTradeItem = `${BASE_CUSTOMER_URL}trade-items?tradeItemIds=${line.tradeItemId}`;
let queryTradeItem = await fetch(urlTradeItem, {
let queryTradeItem = await axios(urlTradeItem, {
method: 'GET',
headers: headers
});
@ -550,9 +565,7 @@ async function insertItem(tradeItem, supplier) {
console.log('Syncing trade item: ', tradeItem.name);
try {
// Temporal connection to all suppliers that have trade items
let currentSupp = await models.supplier.findOne({
where: {
organizationId: tradeItem.supplierOrganizationId
@ -569,7 +582,6 @@ async function insertItem(tradeItem, supplier) {
}, {transaction: tx});
// -----
await models.tradeItem.upsert({
tradeItemId: tradeItem.tradeItemId,
supplierOrganizationId: tradeItem.supplierOrganizationId,
@ -674,5 +686,15 @@ async function insertItem(tradeItem, supplier) {
}
export { getClientToken, updateClientConfig, getJWT, sleep, asyncQueue, syncSequence, syncSuppliers, syncTradeItems, syncConnections, syncSupplyLines };
module.exports = {
getClientToken,
updateClientConfig,
getJWT,
sleep,
asyncQueue,
syncSequence,
syncSuppliers,
syncTradeItems,
syncConnections,
syncSupplyLines
};