From 0610cbc32e64386c6bf8ec94dfa4d5cf56daff8c Mon Sep 17 00:00:00 2001 From: guillermo Date: Fri, 23 Aug 2024 13:12:11 +0200 Subject: [PATCH 1/7] feat: refs #7882 Added model and method --- .../quadminds-api-config/sendOrders.js | 70 +++++++++++++++++++ back/model-config.json | 3 + back/models/quadminds-api-config.js | 3 + back/models/quadminds-api-config.json | 22 ++++++ .../11196-blackCymbidium/00-firstScript.sql | 1 + 5 files changed, 99 insertions(+) create mode 100644 back/methods/quadminds-api-config/sendOrders.js create mode 100644 back/models/quadminds-api-config.js create mode 100644 back/models/quadminds-api-config.json create mode 100644 db/versions/11196-blackCymbidium/00-firstScript.sql diff --git a/back/methods/quadminds-api-config/sendOrders.js b/back/methods/quadminds-api-config/sendOrders.js new file mode 100644 index 0000000000..edaf9a25a1 --- /dev/null +++ b/back/methods/quadminds-api-config/sendOrders.js @@ -0,0 +1,70 @@ +const axios = require('axios'); +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethod('sendOrders', { + description: 'Sends a set of orders/tickets', + accessType: 'WRITE', + accepts: [{ + arg: 'orders', + type: ['number'], + required: true + } + ], + returns: { + type: 'string', + root: true + }, + http: { + path: `/sendOrders`, + verb: 'POST' + } + }); + Self.sendOrders = async orders => { + const config = await Self.app.models.QuadmindsApiConfig.findOne(); + if (!config) throw new UserError('Config params not set'); + + let pois = await Self.rawSql(` + WITH deliveryNotes AS ( + SELECT t.id, t.routeFk, tn.description + FROM ticket t + JOIN ticketObservation tn ON tn.ticketFk = t.id + JOIN observationType ot ON ot.id = tn.observationTypeFk + WHERE ot.code = 'delivery' + ) + SELECT a.id code, + c.name, + CONCAT_WS(', ', IFNULL(a.street, ''), IFNULL(a.city, ''), IFNULL(p.name, '')) longAddress, + CONCAT(IFNULL(a.mobile, c.mobile)) phoneNumber, + dn.description poiDeliveryComments, + c.email email + FROM route r + JOIN ticket t ON t.routeFk = r.id + JOIN address a ON a.id = t.addressFk + JOIN province p ON p.id = a.provinceFk + JOIN country co ON co.id = p.countryFk + JOIN client c ON c.id = t.clientFk + LEFT JOIN deliveryNotes dn ON dn.id = t.id + WHERE t.id IN (?) + GROUP BY t.id + `, [orders]); + + // Transformo code en string ya que lo obtenermos como integer + pois = pois.map(poi => { + return { + ...poi, + code: poi.code.toString(), + poiDeliveryComments: poi.poiDeliveryComments || undefined, + phoneNumber: poi.phoneNumber || undefined + }; + }); + + await axios.post(`${config.url}pois`, pois, { + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'X-Saas-Apikey': config.key + } + }); + }; +}; diff --git a/back/model-config.json b/back/model-config.json index cb9ee4fdb8..37a9ff9f79 100644 --- a/back/model-config.json +++ b/back/model-config.json @@ -124,6 +124,9 @@ "Province": { "dataSource": "vn" }, + "QuadmindsApiConfig": { + "dataSource": "vn" + }, "Autonomy": { "dataSource": "vn" }, diff --git a/back/models/quadminds-api-config.js b/back/models/quadminds-api-config.js new file mode 100644 index 0000000000..f2f36d0db8 --- /dev/null +++ b/back/models/quadminds-api-config.js @@ -0,0 +1,3 @@ +module.exports = Self => { + require('../methods/quadminds-api-config/sendOrders')(Self); +}; diff --git a/back/models/quadminds-api-config.json b/back/models/quadminds-api-config.json new file mode 100644 index 0000000000..a78fb01edf --- /dev/null +++ b/back/models/quadminds-api-config.json @@ -0,0 +1,22 @@ +{ + "name": "QuadmindsApiConfig", + "base": "VnModel", + "options": { + "mysql": { + "table": "quadmindsApiConfig" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "required": true + }, + "url": { + "type": "string" + }, + "key": { + "type": "string" + } + } +} diff --git a/db/versions/11196-blackCymbidium/00-firstScript.sql b/db/versions/11196-blackCymbidium/00-firstScript.sql new file mode 100644 index 0000000000..637ed31b73 --- /dev/null +++ b/db/versions/11196-blackCymbidium/00-firstScript.sql @@ -0,0 +1 @@ +RENAME TABLE vn.quadMindsApiConfig TO vn.quadmindsApiConfig; From e4477ca1098041f5b91e1178e17be6a39f2853a3 Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 29 Aug 2024 13:21:59 +0200 Subject: [PATCH 2/7] fix: refs #7882 Stable version --- back/methods/quadminds-api-config/sendOrders.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/back/methods/quadminds-api-config/sendOrders.js b/back/methods/quadminds-api-config/sendOrders.js index edaf9a25a1..5806a36ea3 100644 --- a/back/methods/quadminds-api-config/sendOrders.js +++ b/back/methods/quadminds-api-config/sendOrders.js @@ -33,13 +33,12 @@ module.exports = Self => { WHERE ot.code = 'delivery' ) SELECT a.id code, - c.name, + c.socialName name, CONCAT_WS(', ', IFNULL(a.street, ''), IFNULL(a.city, ''), IFNULL(p.name, '')) longAddress, CONCAT(IFNULL(a.mobile, c.mobile)) phoneNumber, dn.description poiDeliveryComments, c.email email - FROM route r - JOIN ticket t ON t.routeFk = r.id + FROM ticket t JOIN address a ON a.id = t.addressFk JOIN province p ON p.id = a.provinceFk JOIN country co ON co.id = p.countryFk From a25e61903688c89be4b4a2bb8cf74bf161e5ab99 Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 29 Aug 2024 14:48:21 +0200 Subject: [PATCH 3/7] fix: refs #7882 Added send orders method --- .../quadminds-api-config/sendOrders.js | 57 +++++++-------- back/methods/quadminds-api-config/sendPois.js | 70 +++++++++++++++++++ back/models/quadminds-api-config.js | 1 + 3 files changed, 100 insertions(+), 28 deletions(-) create mode 100644 back/methods/quadminds-api-config/sendPois.js diff --git a/back/methods/quadminds-api-config/sendOrders.js b/back/methods/quadminds-api-config/sendOrders.js index 5806a36ea3..d71de9edda 100644 --- a/back/methods/quadminds-api-config/sendOrders.js +++ b/back/methods/quadminds-api-config/sendOrders.js @@ -1,12 +1,13 @@ const axios = require('axios'); const UserError = require('vn-loopback/util/user-error'); +const moment = require('moment'); module.exports = Self => { Self.remoteMethod('sendOrders', { - description: 'Sends a set of orders/tickets', + description: 'Sends a set of orders', accessType: 'WRITE', accepts: [{ - arg: 'orders', + arg: 'tickets', type: ['number'], required: true } @@ -20,45 +21,45 @@ module.exports = Self => { verb: 'POST' } }); - Self.sendOrders = async orders => { + Self.sendOrders = async tickets => { const config = await Self.app.models.QuadmindsApiConfig.findOne(); if (!config) throw new UserError('Config params not set'); - let pois = await Self.rawSql(` - WITH deliveryNotes AS ( - SELECT t.id, t.routeFk, tn.description - FROM ticket t - JOIN ticketObservation tn ON tn.ticketFk = t.id - JOIN observationType ot ON ot.id = tn.observationTypeFk - WHERE ot.code = 'delivery' - ) - SELECT a.id code, - c.socialName name, - CONCAT_WS(', ', IFNULL(a.street, ''), IFNULL(a.city, ''), IFNULL(p.name, '')) longAddress, - CONCAT(IFNULL(a.mobile, c.mobile)) phoneNumber, - dn.description poiDeliveryComments, - c.email email + const pois = await axios.get(`${config.url}pois/search?limit=10000&offset=0`, { + headers: { + 'Accept': 'application/json', + 'X-Saas-Apikey': config.key + } + }); + + const poiMap = new Map(pois.data.data.map(poi => [poi.code, poi._id])); + + let orders = await Self.rawSql(` + SELECT a.id poiCode, + t.id code, + t.shipped date, + 'PEDIDO' operation, + t.totalWithVat totalAmount, + t.totalWithoutVat totalAmountWithoutTaxes FROM ticket t JOIN address a ON a.id = t.addressFk - JOIN province p ON p.id = a.provinceFk - JOIN country co ON co.id = p.countryFk - JOIN client c ON c.id = t.clientFk - LEFT JOIN deliveryNotes dn ON dn.id = t.id WHERE t.id IN (?) GROUP BY t.id - `, [orders]); + `, [tickets]); // Transformo code en string ya que lo obtenermos como integer - pois = pois.map(poi => { + orders = orders.map(order => { return { - ...poi, - code: poi.code.toString(), - poiDeliveryComments: poi.poiDeliveryComments || undefined, - phoneNumber: poi.phoneNumber || undefined + ...order, + poiId: poiMap.get(order.poiCode.toString()) || undefined, + code: order.code.toString(), + date: moment(order.date).format('YYYY-MM-DD'), + totalAmount: order.totalAmount || undefined, + totalAmountWithoutTaxes: order.totalAmountWithoutTaxes || undefined }; }); - await axios.post(`${config.url}pois`, pois, { + await axios.post(`${config.url}orders`, orders, { headers: { 'Accept': 'application/json', 'Content-Type': 'application/json', diff --git a/back/methods/quadminds-api-config/sendPois.js b/back/methods/quadminds-api-config/sendPois.js new file mode 100644 index 0000000000..af0cafcb35 --- /dev/null +++ b/back/methods/quadminds-api-config/sendPois.js @@ -0,0 +1,70 @@ +const axios = require('axios'); +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethod('sendPois', { + description: 'Sends a set of pois', + accessType: 'WRITE', + accepts: [{ + arg: 'tickets', + type: ['number'], + required: true + } + ], + returns: { + type: 'string', + root: true + }, + http: { + path: `/sendPois`, + verb: 'POST' + } + }); + Self.sendPois = async tickets => { + const config = await Self.app.models.QuadmindsApiConfig.findOne(); + if (!config) throw new UserError('Config params not set'); + + let pois = await Self.rawSql(` + WITH deliveryNotes AS ( + SELECT t.id, t.routeFk, tn.description + FROM ticket t + JOIN ticketObservation tn ON tn.ticketFk = t.id + JOIN observationType ot ON ot.id = tn.observationTypeFk + WHERE ot.code = 'delivery' + ) + SELECT a.id code, + c.socialName name, + CONCAT_WS(', ', IFNULL(a.street, ''), IFNULL(a.city, ''), IFNULL(p.name, '')) longAddress, + CONCAT(IFNULL(a.mobile, c.mobile)) phoneNumber, + dn.description poiDeliveryComments, + c.email email + FROM ticket t + JOIN address a ON a.id = t.addressFk + JOIN province p ON p.id = a.provinceFk + JOIN country co ON co.id = p.countryFk + JOIN client c ON c.id = t.clientFk + LEFT JOIN deliveryNotes dn ON dn.id = t.id + WHERE t.id IN (?) + GROUP BY t.id + `, [tickets]); + + // Transformo code en string ya que lo obtenermos como integer + pois = pois.map(poi => { + return { + ...poi, + code: poi.code.toString(), + poiDeliveryComments: poi.poiDeliveryComments || undefined, + phoneNumber: poi.phoneNumber || undefined, + email: poi.email || undefined + }; + }); + + await axios.post(`${config.url}pois`, pois, { + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json', + 'X-Saas-Apikey': config.key + } + }); + }; +}; diff --git a/back/models/quadminds-api-config.js b/back/models/quadminds-api-config.js index f2f36d0db8..c2773fa0bc 100644 --- a/back/models/quadminds-api-config.js +++ b/back/models/quadminds-api-config.js @@ -1,3 +1,4 @@ module.exports = Self => { + require('../methods/quadminds-api-config/sendPois')(Self); require('../methods/quadminds-api-config/sendOrders')(Self); }; From 8165830934bb0985019daaba54873c9cb65a4652 Mon Sep 17 00:00:00 2001 From: guillermo Date: Fri, 30 Aug 2024 12:30:40 +0200 Subject: [PATCH 4/7] feat: refs #7882 Now supports coords, address and long address --- back/methods/quadminds-api-config/sendPois.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/back/methods/quadminds-api-config/sendPois.js b/back/methods/quadminds-api-config/sendPois.js index af0cafcb35..933536eb1a 100644 --- a/back/methods/quadminds-api-config/sendPois.js +++ b/back/methods/quadminds-api-config/sendPois.js @@ -34,6 +34,12 @@ module.exports = Self => { ) SELECT a.id code, c.socialName name, + IF(ABS(a.latitude - ROUND(a.latitude)) < 0.000001, NULL, a.latitude) latitude, + IF(ABS(a.longitude - ROUND(a.longitude)) < 0.000001, NULL, a.longitude) longitude, + a.street, + a.city locality, + p.name state, + co.name country, CONCAT_WS(', ', IFNULL(a.street, ''), IFNULL(a.city, ''), IFNULL(p.name, '')) longAddress, CONCAT(IFNULL(a.mobile, c.mobile)) phoneNumber, dn.description poiDeliveryComments, @@ -53,6 +59,14 @@ module.exports = Self => { return { ...poi, code: poi.code.toString(), + latitude: poi.latitude || undefined, + longitude: poi.longitude || undefined, + address: { + street: poi.street || undefined, + locality: poi.locality || undefined, + state: poi.state || undefined, + country: poi.country || undefined + }, poiDeliveryComments: poi.poiDeliveryComments || undefined, phoneNumber: poi.phoneNumber || undefined, email: poi.email || undefined From b40ecf9e19f8577fad9b1e2d546f251f5695eee6 Mon Sep 17 00:00:00 2001 From: guillermo Date: Mon, 2 Sep 2024 11:48:32 +0200 Subject: [PATCH 5/7] feat: refs #7882 Improved sendOrders and added more config params --- .../quadminds-api-config/sendOrders.js | 22 +++++++++++++------ back/methods/quadminds-api-config/sendPois.js | 3 +++ back/models/quadminds-api-config.json | 6 +++++ .../11196-blackCymbidium/00-firstScript.sql | 4 ++++ 4 files changed, 28 insertions(+), 7 deletions(-) diff --git a/back/methods/quadminds-api-config/sendOrders.js b/back/methods/quadminds-api-config/sendOrders.js index d71de9edda..179cad28e5 100644 --- a/back/methods/quadminds-api-config/sendOrders.js +++ b/back/methods/quadminds-api-config/sendOrders.js @@ -25,14 +25,22 @@ module.exports = Self => { const config = await Self.app.models.QuadmindsApiConfig.findOne(); if (!config) throw new UserError('Config params not set'); - const pois = await axios.get(`${config.url}pois/search?limit=10000&offset=0`, { - headers: { - 'Accept': 'application/json', - 'X-Saas-Apikey': config.key - } - }); + if (tickets.length > config.maxObjects) + throw new UserError(`Quadminds does not support more than ${config.maxObjects} tickets`); - const poiMap = new Map(pois.data.data.map(poi => [poi.code, poi._id])); + let poisData = []; + let isOk; + for (let offset = 0; !isOk; offset = offset + config.limit) { + const pois = await axios.get(`${config.url}pois/search?limit=${config.limit}&offset=${offset}`, { + headers: { + 'Accept': 'application/json', + 'X-Saas-Apikey': config.key + } + }); + pois.data.data.length ? poisData.push(...pois.data.data) : isOk = true; + } + + const poiMap = new Map(poisData.map(poi => [poi.code, poi._id])); let orders = await Self.rawSql(` SELECT a.id poiCode, diff --git a/back/methods/quadminds-api-config/sendPois.js b/back/methods/quadminds-api-config/sendPois.js index 933536eb1a..cb5eef93e4 100644 --- a/back/methods/quadminds-api-config/sendPois.js +++ b/back/methods/quadminds-api-config/sendPois.js @@ -24,6 +24,9 @@ module.exports = Self => { const config = await Self.app.models.QuadmindsApiConfig.findOne(); if (!config) throw new UserError('Config params not set'); + if (tickets.length > config.maxObjects) + throw new UserError(`Quadminds does not support more than ${config.maxObjects} tickets`); + let pois = await Self.rawSql(` WITH deliveryNotes AS ( SELECT t.id, t.routeFk, tn.description diff --git a/back/models/quadminds-api-config.json b/back/models/quadminds-api-config.json index a78fb01edf..4213699a9d 100644 --- a/back/models/quadminds-api-config.json +++ b/back/models/quadminds-api-config.json @@ -17,6 +17,12 @@ }, "key": { "type": "string" + }, + "maxObjects": { + "type": "number" + }, + "limit": { + "type": "number" } } } diff --git a/db/versions/11196-blackCymbidium/00-firstScript.sql b/db/versions/11196-blackCymbidium/00-firstScript.sql index 637ed31b73..7c4a476c56 100644 --- a/db/versions/11196-blackCymbidium/00-firstScript.sql +++ b/db/versions/11196-blackCymbidium/00-firstScript.sql @@ -1 +1,5 @@ RENAME TABLE vn.quadMindsApiConfig TO vn.quadmindsApiConfig; + +ALTER TABLE vn.quadmindsApiConfig + ADD maxObjects INT NULL COMMENT 'Número máximo de objetos en el array por petición', + ADD `limit` INT NULL COMMENT 'Limite de objetos solicitados por petición'; From ef4ea588ca19a650d69e84f2177af39173dece74 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 10 Sep 2024 07:43:11 +0200 Subject: [PATCH 6/7] feat: refs #7882 Added volume and timeWindow --- back/methods/quadminds-api-config/sendOrders.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/back/methods/quadminds-api-config/sendOrders.js b/back/methods/quadminds-api-config/sendOrders.js index 179cad28e5..ac434213d9 100644 --- a/back/methods/quadminds-api-config/sendOrders.js +++ b/back/methods/quadminds-api-config/sendOrders.js @@ -48,9 +48,11 @@ module.exports = Self => { t.shipped date, 'PEDIDO' operation, t.totalWithVat totalAmount, - t.totalWithoutVat totalAmountWithoutTaxes + t.totalWithoutVat totalAmountWithoutTaxes, + SUM(sv.volume) volume FROM ticket t JOIN address a ON a.id = t.addressFk + JOIN saleVolume sv ON sv.ticketFk = t.id WHERE t.id IN (?) GROUP BY t.id `, [tickets]); @@ -63,7 +65,15 @@ module.exports = Self => { code: order.code.toString(), date: moment(order.date).format('YYYY-MM-DD'), totalAmount: order.totalAmount || undefined, - totalAmountWithoutTaxes: order.totalAmountWithoutTaxes || undefined + totalAmountWithoutTaxes: order.totalAmountWithoutTaxes || undefined, + timeWindow: [{ + from: '07:00', + to: '20:00' + }], + orderMeasures: [{ + constraintId: 3, // Volumen + value: order.volume + }] }; }); From 871d5457d041e0362e95c190e5600da3c90d56ea Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 18 Sep 2024 07:14:52 +0200 Subject: [PATCH 7/7] refactor: refs #7882 Requested changes --- back/methods/quadminds-api-config/sendOrders.js | 4 ++-- db/versions/11196-blackCymbidium/00-firstScript.sql | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/back/methods/quadminds-api-config/sendOrders.js b/back/methods/quadminds-api-config/sendOrders.js index ac434213d9..760d622b6e 100644 --- a/back/methods/quadminds-api-config/sendOrders.js +++ b/back/methods/quadminds-api-config/sendOrders.js @@ -67,8 +67,8 @@ module.exports = Self => { totalAmount: order.totalAmount || undefined, totalAmountWithoutTaxes: order.totalAmountWithoutTaxes || undefined, timeWindow: [{ - from: '07:00', - to: '20:00' + from: config.orderTimeFrom, + to: config.orderTimeTo }], orderMeasures: [{ constraintId: 3, // Volumen diff --git a/db/versions/11196-blackCymbidium/00-firstScript.sql b/db/versions/11196-blackCymbidium/00-firstScript.sql index 7c4a476c56..e05225204f 100644 --- a/db/versions/11196-blackCymbidium/00-firstScript.sql +++ b/db/versions/11196-blackCymbidium/00-firstScript.sql @@ -2,4 +2,6 @@ RENAME TABLE vn.quadMindsApiConfig TO vn.quadmindsApiConfig; ALTER TABLE vn.quadmindsApiConfig ADD maxObjects INT NULL COMMENT 'Número máximo de objetos en el array por petición', - ADD `limit` INT NULL COMMENT 'Limite de objetos solicitados por petición'; + ADD `limit` INT NULL COMMENT 'Limite de objetos solicitados por petición', + ADD `orderTimeFrom` VARCHAR(5) NULL COMMENT 'Inicio de ventana horaria de pedido', + ADD `orderTimeTo` VARCHAR(5) NULL COMMENT 'Fin de ventana horaria de pedido';