From 0610cbc32e64386c6bf8ec94dfa4d5cf56daff8c Mon Sep 17 00:00:00 2001 From: guillermo Date: Fri, 23 Aug 2024 13:12:11 +0200 Subject: [PATCH 01/18] 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 000000000..edaf9a25a --- /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 cb9ee4fdb..37a9ff9f7 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 000000000..f2f36d0db --- /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 000000000..a78fb01ed --- /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 000000000..637ed31b7 --- /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 02/18] 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 edaf9a25a..5806a36ea 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 03/18] 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 5806a36ea..d71de9edd 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 000000000..af0cafcb3 --- /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 f2f36d0db..c2773fa0b 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 04/18] 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 af0cafcb3..933536eb1 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 05/18] 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 d71de9edd..179cad28e 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 933536eb1..cb5eef93e 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 a78fb01ed..4213699a9 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 637ed31b7..7c4a476c5 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 06/18] 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 179cad28e..ac434213d 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 8fedfbd090fa3dce0e9b309dfbd8e1f0361a3a47 Mon Sep 17 00:00:00 2001 From: jorgep Date: Mon, 16 Sep 2024 13:32:14 +0200 Subject: [PATCH 07/18] fix: refs #7524 getAmountPaid wip --- modules/client/front/balance/create/index.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/client/front/balance/create/index.js b/modules/client/front/balance/create/index.js index f1474e10c..c0bc11c0b 100644 --- a/modules/client/front/balance/create/index.js +++ b/modules/client/front/balance/create/index.js @@ -7,6 +7,10 @@ class Controller extends Dialog { this.vnReport = vnReport; this.vnEmail = vnEmail; this.receipt = {}; + + this.$.$watch(() => this.clientFk, (newVal, oldVal) => { + if (!this.receipt.amountPaid && newVal != oldVal) this.getAmountPaid(); + }); } set payed(value) { @@ -51,7 +55,6 @@ class Controller extends Dialog { set companyFk(value) { this.receipt.companyFk = value; - this.getAmountPaid(); } set description(value) { From 9896ac2361374dcc39055c4dcc050c173adbda59 Mon Sep 17 00:00:00 2001 From: pablone Date: Tue, 17 Sep 2024 08:21:29 +0200 Subject: [PATCH 08/18] fix: refs #7760 remove throw on ticket split --- db/routines/vn/procedures/ticket_splitItemPackingType.sql | 4 ---- 1 file changed, 4 deletions(-) diff --git a/db/routines/vn/procedures/ticket_splitItemPackingType.sql b/db/routines/vn/procedures/ticket_splitItemPackingType.sql index 6a974ea39..ec630d545 100644 --- a/db/routines/vn/procedures/ticket_splitItemPackingType.sql +++ b/db/routines/vn/procedures/ticket_splitItemPackingType.sql @@ -30,10 +30,6 @@ BEGIN WHERE t.id = vSelf AND i.itemPackingTypeFk = vOriginalItemPackingTypeFk; - IF NOT vHasItemPackingType THEN - CALL util.throw('The ticket has not sales with the itemPackingType'); - END IF; - CREATE OR REPLACE TEMPORARY TABLE tSalesToMove ( ticketFk INT, saleFk INT, From 3fe1724e84055c3634abd38d1bb17e2575203ce6 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 17 Sep 2024 09:12:25 +0200 Subject: [PATCH 09/18] fix: refs #7760 ticket_splitItemPackingType --- .../ticket_splitItemPackingType.sql | 154 +++++++++++------- 1 file changed, 99 insertions(+), 55 deletions(-) diff --git a/db/routines/vn/procedures/ticket_splitItemPackingType.sql b/db/routines/vn/procedures/ticket_splitItemPackingType.sql index ec630d545..0ee865af5 100644 --- a/db/routines/vn/procedures/ticket_splitItemPackingType.sql +++ b/db/routines/vn/procedures/ticket_splitItemPackingType.sql @@ -5,78 +5,122 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_splitItemPacki ) BEGIN /** - * Clona y reparte las líneas de ventas de un ticket en funcion del tipo de empaquetado. - * Respeta el id de ticket inicial para el tipo de empaquetado propuesto. + * Clona y reparte las ventas de un ticket en funcion del tipo de empaquetado. + * Respeta el id inicial para el tipo propuesto. * * @param vSelf Id ticket - * @param vOriginalItemPackingTypeFk Tipo empaquetado al que se mantiene el ticket original + * @param vOriginalItemPackingTypeFk Tipo para el que se reserva el número de ticket original * @return table tmp.ticketIPT(ticketFk, itemPackingTypeFk) */ - DECLARE vDone INT DEFAULT FALSE; - DECLARE vHasItemPackingType BOOL; - DECLARE vItemPackingTypeFk INT; + DECLARE vItemPackingTypeFk VARCHAR(1) DEFAULT 'H'; DECLARE vNewTicketFk INT; + DECLARE vPackingTypesToSplit INT; + DECLARE vDone INT DEFAULT FALSE; - DECLARE vItemPackingTypes CURSOR FOR - SELECT DISTINCT itemPackingTypeFk - FROM tSalesToMove; + DECLARE vSaleGroup CURSOR FOR + SELECT itemPackingTypeFk + FROM tSaleGroup + WHERE itemPackingTypeFk IS NOT NULL + ORDER BY (itemPackingTypeFk = vOriginalItemPackingTypeFk) DESC; DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; - SELECT COUNT(*) INTO vHasItemPackingType - FROM ticket t - JOIN sale s ON s.ticketFk = t.id - JOIN item i ON i.id = s.itemFk - WHERE t.id = vSelf - AND i.itemPackingTypeFk = vOriginalItemPackingTypeFk; + START TRANSACTION; - CREATE OR REPLACE TEMPORARY TABLE tSalesToMove ( - ticketFk INT, - saleFk INT, - itemPackingTypeFk INT - ) ENGINE=MEMORY; + SELECT id + FROM sale + WHERE ticketFk = vSelf + AND NOT quantity + FOR UPDATE; - INSERT INTO tSalesToMove (saleFk, itemPackingTypeFk) - SELECT s.id, i.itemPackingTypeFk - FROM ticket t - JOIN sale s ON s.ticketFk = t.id - JOIN item i ON i.id = s.itemFk - WHERE t.id = vSelf - AND i.itemPackingTypeFk <> vOriginalItemPackingTypeFk; + DELETE FROM sale + WHERE NOT quantity + AND ticketFk = vSelf; - OPEN vItemPackingTypes; + CREATE OR REPLACE TEMPORARY TABLE tSale + (PRIMARY KEY (id)) + ENGINE = MEMORY + SELECT s.id, i.itemPackingTypeFk, IFNULL(sv.litros, 0) litros + FROM sale s + JOIN item i ON i.id = s.itemFk + LEFT JOIN saleVolume sv ON sv.saleFk = s.id + WHERE s.ticketFk = vSelf; - l: LOOP - SET vDone = FALSE; - FETCH vItemPackingTypes INTO vItemPackingTypeFk; + CREATE OR REPLACE TEMPORARY TABLE tSaleGroup + ENGINE = MEMORY + SELECT itemPackingTypeFk, SUM(litros) totalLitros + FROM tSale + GROUP BY itemPackingTypeFk; - IF vDone THEN - LEAVE l; - END IF; - - CALL ticket_Clone(vSelf, vNewTicketFk); - - UPDATE tSalesToMove - SET ticketFk = vNewTicketFk - WHERE itemPackingTypeFk = vItemPackingTypeFk; - - END LOOP; - - CLOSE vItemPackingTypes; - - UPDATE sale s - JOIN tSalesToMove stm ON stm.saleFk = s.id - SET s.ticketFk = stm.ticketFk - WHERE stm.ticketFk; + SELECT COUNT(*) INTO vPackingTypesToSplit + FROM tSaleGroup + WHERE itemPackingTypeFk IS NOT NULL; CREATE OR REPLACE TEMPORARY TABLE tmp.ticketIPT( ticketFk INT, itemPackingTypeFk VARCHAR(1) - ) ENGINE=MEMORY - SELECT ticketFk, itemPackingTypeFk - FROM tSalesToMove - GROUP BY ticketFk; + ) ENGINE = MEMORY; - DROP TEMPORARY TABLE tSalesToMove; + CASE vPackingTypesToSplit + WHEN 0 THEN + INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) + VALUES(vSelf, vItemPackingTypeFk); + WHEN 1 THEN + INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) + SELECT vSelf, itemPackingTypeFk + FROM tSaleGroup + WHERE itemPackingTypeFk IS NOT NULL; + ELSE + OPEN vSaleGroup; + FETCH vSaleGroup INTO vItemPackingTypeFk; + + INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) + VALUES(vSelf, vItemPackingTypeFk); + + l: LOOP + SET vDone = FALSE; + FETCH vSaleGroup INTO vItemPackingTypeFk; + + IF vDone THEN + LEAVE l; + END IF; + + CALL ticket_Clone(vSelf, vNewTicketFk); + + INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk) + VALUES(vNewTicketFk, vItemPackingTypeFk); + END LOOP; + + CLOSE vSaleGroup; + + SELECT s.id + FROM sale s + JOIN tSale ts ON ts.id = s.id + JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = ts.itemPackingTypeFk + FOR UPDATE; + + UPDATE sale s + JOIN tSale ts ON ts.id = s.id + JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = ts.itemPackingTypeFk + SET s.ticketFk = t.ticketFk; + + SELECT itemPackingTypeFk INTO vItemPackingTypeFk + FROM tSaleGroup sg + WHERE sg.itemPackingTypeFk IS NOT NULL + ORDER BY sg.itemPackingTypeFk + LIMIT 1; + + UPDATE sale s + JOIN tSale ts ON ts.id = s.id + JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = vItemPackingTypeFk + SET s.ticketFk = t.ticketFk + WHERE ts.itemPackingTypeFk IS NULL; + END CASE; + + COMMIT; + + DROP TEMPORARY TABLE + tSale, + tSaleGroup; END$$ -DELIMITER ; \ No newline at end of file +DELIMITER ; From 267ce3167c1fbf42b9c22826c736bc36f8aea32e Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 17 Sep 2024 09:30:40 +0200 Subject: [PATCH 10/18] fix: refs #7760 collection_new --- db/routines/vn/procedures/collection_new.sql | 313 ++++++++++-------- .../vn/procedures/ticket_mergeSales.sql | 40 +-- 2 files changed, 189 insertions(+), 164 deletions(-) diff --git a/db/routines/vn/procedures/collection_new.sql b/db/routines/vn/procedures/collection_new.sql index 53f5500a0..545320081 100644 --- a/db/routines/vn/procedures/collection_new.sql +++ b/db/routines/vn/procedures/collection_new.sql @@ -1,8 +1,5 @@ DELIMITER $$ -CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`collection_new`( - vUserFk INT, - OUT vCollectionFk INT -) +CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`collection_new`(vUserFk INT, OUT vCollectionFk INT) BEGIN /** * Genera colecciones de tickets sin asignar trabajador. @@ -15,29 +12,28 @@ BEGIN DECLARE vLinesLimit INT; DECLARE vTicketLines INT; DECLARE vVolumeLimit DECIMAL; - DECLARE vSizeLimit INT; DECLARE vTicketVolume DECIMAL; + DECLARE vSizeLimit INT; DECLARE vMaxTickets INT; - DECLARE vStateCode VARCHAR(45); + DECLARE vStateFk VARCHAR(45); DECLARE vFirstTicketFk INT; + DECLARE vHour INT; + DECLARE vMinute INT; DECLARE vWorkerCode VARCHAR(3); - DECLARE vWagonCounter INT DEFAULT 1; + DECLARE vWagonCounter INT DEFAULT 0; DECLARE vTicketFk INT; DECLARE vItemPackingTypeFk VARCHAR(1); - DECLARE vHasAssignedTickets BOOL; + DECLARE vHasAssignedTickets BOOLEAN; DECLARE vHasUniqueCollectionTime BOOL; - DECLARE vHeight INT; - DECLARE vVolume INT; - DECLARE vLiters INT; - DECLARE vLines INT; - DECLARE vTotalLines INT DEFAULT 0; - DECLARE vTotalVolume INT DEFAULT 0; - DECLARE vFreeWagonFk INT; DECLARE vDone INT DEFAULT FALSE; + DECLARE vLockName VARCHAR(215); + DECLARE vLockTime INT DEFAULT 30; + DECLARE vFreeWagonFk INT; - DECLARE vTickets CURSOR FOR + DECLARE c1 CURSOR FOR SELECT ticketFk, `lines`, m3 FROM tmp.productionBuffer + WHERE ticketFk <> vFirstTicketFk ORDER BY HH, mm, productionOrder DESC, @@ -50,6 +46,14 @@ BEGIN DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + IF vLockName IS NOT NULL THEN + DO RELEASE_LOCK(vLockName); + END IF; + RESIGNAL; + END; + SELECT pc.ticketTrolleyMax * o.numberOfWagons, pc.hasUniqueCollectionTime, w.code, @@ -60,26 +64,36 @@ BEGIN o.trainFk, o.linesLimit, o.volumeLimit, - o.sizeLimit + o.sizeLimit, + pc.collection_new_lockname INTO vMaxTickets, - vHasUniqueCollectionTime, - vWorkerCode, - vWarehouseFk, - vItemPackingTypeFk, - vStateCode, - vWagons, - vTrainFk, - vLinesLimit, - vVolumeLimit, - vSizeLimit - FROM worker w - JOIN operator o ON o.workerFk = w.id + vHasUniqueCollectionTime, + vWorkerCode, + vWarehouseFk, + vItemPackingTypeFk, + vStateFk, + vWagons, + vTrainFk, + vLinesLimit, + vVolumeLimit, + vSizeLimit, + vLockName + FROM productionConfig pc + JOIN worker w ON w.id = vUserFk JOIN state st ON st.`code` = 'ON_PREPARATION' - JOIN productionConfig pc - WHERE w.id = vUserFk; + JOIN operator o ON o.workerFk = vUserFk; + + SET vLockName = CONCAT_WS('/', + vLockName, + vWarehouseFk, + vItemPackingTypeFk + ); + + IF NOT GET_LOCK(vLockName, vLockTime) THEN + CALL util.throw(CONCAT('Cannot get lock: ', vLockName)); + END IF; -- Se prepara el tren, con tantos vagones como sea necesario. - CREATE OR REPLACE TEMPORARY TABLE tTrain (wagon INT, shelve INT, @@ -90,58 +104,59 @@ BEGIN PRIMARY KEY(wagon, shelve)) ENGINE = MEMORY; - INSERT INTO tTrain (wagon, shelve, liters, `lines`, height) - WITH RECURSIVE wagonSequence AS ( - SELECT vWagonCounter wagon - UNION ALL - SELECT wagon + 1 wagon - FROM wagonSequence - WHERE wagon < vWagonCounter + vWagons -1 - ) - SELECT ws.wagon, cv.`level`, cv.liters, cv.`lines`, cv.height - FROM wagonSequence ws - JOIN vn.collectionVolumetry cv ON cv.trainFk = vTrainFk + WHILE vWagons > vWagonCounter DO + SET vWagonCounter = vWagonCounter + 1; + + INSERT INTO tTrain(wagon, shelve, liters, `lines`, height) + SELECT vWagonCounter, cv.`level` , cv.liters , cv.`lines` , cv.height + FROM collectionVolumetry cv + WHERE cv.trainFk = vTrainFk AND cv.itemPackingTypeFk = vItemPackingTypeFk; + END WHILE; -- Esto desaparecerá cuando tengamos la table cache.ticket - CALL productionControl(vWarehouseFk, 0); ALTER TABLE tmp.productionBuffer ADD COLUMN liters INT, ADD COLUMN height INT; + -- Se obtiene nº de colección. + INSERT INTO collection + SET itemPackingTypeFk = vItemPackingTypeFk, + trainFk = vTrainFk, + wagons = vWagons, + warehouseFk = vWarehouseFk; + + SELECT LAST_INSERT_ID() INTO vCollectionFk; + -- Los tickets de recogida en Algemesí sólo se sacan si están asignados. -- Los pedidos con riesgo no se sacan aunque se asignen. - - DELETE pb + DELETE pb.* FROM tmp.productionBuffer pb JOIN state s ON s.id = pb.state WHERE (pb.agency = 'REC_ALGEMESI' AND s.code <> 'PICKER_DESIGNED') OR pb.problem LIKE '%RIESGO%'; - -- Si hay tickets asignados, nos centramos exclusivamente en esos tickets - -- y los sacamos independientemente de problemas o tamaños - - SELECT EXISTS ( - SELECT TRUE - FROM tmp.productionBuffer pb - JOIN state s ON s.id = pb.state - WHERE s.code = 'PICKER_DESIGNED' - AND pb.workerCode = vWorkerCode - ) INTO vHasAssignedTickets; + -- Comprobamos si hay tickets asignados. En ese caso, nos centramos + -- exclusivamente en esos tickets y los sacamos independientemente + -- de problemas o tamaños + SELECT COUNT(*) INTO vHasAssignedTickets + FROM tmp.productionBuffer pb + JOIN state s ON s.id = pb.state + WHERE s.code = 'PICKER_DESIGNED' + AND pb.workerCode = vWorkerCode; -- Se dejan en la tabla tmp.productionBuffer sólo aquellos tickets adecuados - IF vHasAssignedTickets THEN - DELETE pb + DELETE pb.* FROM tmp.productionBuffer pb JOIN state s ON s.id = pb.state WHERE s.code <> 'PICKER_DESIGNED' OR pb.workerCode <> vWorkerCode; ELSE - DELETE pb + DELETE pb.* FROM tmp.productionBuffer pb JOIN state s ON s.id = pb.state JOIN agencyMode am ON am.id = pb.agencyModeFk @@ -164,66 +179,72 @@ BEGIN OR (NOT pb.H AND pb.V > 0 AND vItemPackingTypeFk = 'H') OR (NOT pb.V AND vItemPackingTypeFk = 'V') OR (pc.isPreviousPreparationRequired AND pb.previousWithoutParking) - OR LENGTH(pb.problem) - OR pb.lines > vLinesLimit - OR pb.m3 > vVolumeLimit - OR sub.maxSize > vSizeLimit - OR pb.hasPlantTray; + OR LENGTH(pb.problem) > 0 + OR (pb.lines > vLinesLimit AND vLinesLimit IS NOT NULL) + OR (pb.m3 > vVolumeLimit AND vVolumeLimit IS NOT NULL) + OR ((sub.maxSize > vSizeLimit OR sub.maxSize IS NOT NULL) AND vSizeLimit IS NOT NULL); END IF; + -- Es importante que el primer ticket se coja en todos los casos + SELECT ticketFk, + HH, + mm, + `lines`, + m3 + INTO vFirstTicketFk, + vHour, + vMinute, + vTicketLines, + vTicketVolume + FROM tmp.productionBuffer + ORDER BY HH, + mm, + productionOrder DESC, + m3 DESC, + agency, + zona, + routeFk, + ticketFk + LIMIT 1; + -- Hay que excluir aquellos que no tengan la misma hora de preparacion, si procede IF vHasUniqueCollectionTime THEN - - SELECT ticketFk INTO vFirstTicketFk - FROM tmp.productionBuffer - ORDER BY HH, - mm, - productionOrder DESC, - m3 DESC, - agency, - zona, - routeFk, - ticketFk - LIMIT 1; - - DELETE pb - FROM tmp.productionBuffer pb - JOIN tmp.productionBuffer pb2 ON pb2.ticketFk = vFirstTicketFk - AND (pb.HH <> pb2.HH OR pb.mm <> pb2.mm); - + DELETE FROM tmp.productionBuffer + WHERE HH <> vHour + OR mm <> vMinute; END IF; - OPEN vTickets; - l: LOOP - SET vDone = FALSE; - FETCH vTickets INTO vTicketFk, vTicketLines, vTicketVolume; + SET vTicketFk = vFirstTicketFk; + SET @lines = 0; + SET @volume = 0; - IF vDone THEN - LEAVE l; - END IF; + OPEN c1; + read_loop: LOOP + SET vDone = FALSE; -- Buscamos un ticket que cumpla con los requisitos en el listado - - IF (vLinesLimit IS NULL OR (vTotalLines + vTicketLines) <= vLinesLimit) - AND (vVolumeLimit IS NULL OR (vTotalVolume + vTicketVolume) <= vVolumeLimit) THEN + IF ((vTicketLines + @lines) <= vLinesLimit OR vLinesLimit IS NULL) + AND ((vTicketVolume + @volume) <= vVolumeLimit OR vVolumeLimit IS NULL) THEN CALL ticket_splitItemPackingType(vTicketFk, vItemPackingTypeFk); DROP TEMPORARY TABLE tmp.ticketIPT; - SELECT COUNT(*), SUM(litros), MAX(i.`size`), SUM(sv.volume) - INTO vLines, vLiters, vHeight, vVolume - FROM saleVolume sv - JOIN sale s ON s.id = sv.saleFk - JOIN item i ON i.id = s.itemFk - WHERE sv.ticketFk = vTicketFk; - - SET vTotalVolume = vTotalVolume + vVolume, - vTotalLines = vTotalLines + vLines; - UPDATE tmp.productionBuffer pb - SET pb.liters = vLiters, - pb.`lines` = vLines, - pb.height = vHeight + JOIN ( + SELECT SUM(litros) liters, + @lines:= COUNT(*) + @lines, + COUNT(*) `lines`, + MAX(i.`size`) height, + @volume := SUM(sv.volume) + @volume, + SUM(sv.volume) volume + FROM saleVolume sv + JOIN sale s ON s.id = sv.saleFk + JOIN item i ON i.id = s.itemFk + WHERE sv.ticketFk = vTicketFk + ) sub + SET pb.liters = sub.liters, + pb.`lines` = sub.`lines`, + pb.height = sub.height WHERE pb.ticketFk = vTicketFk; UPDATE tTrain tt @@ -240,13 +261,17 @@ BEGIN tt.height LIMIT 1; - -- Si no le encuentra una balda, intentamos darle un carro entero libre - + -- Si no le encuentra una balda adecuada, intentamos darle un carro entero si queda alguno libre IF NOT (SELECT COUNT(*) FROM tTrain WHERE ticketFk) THEN - SELECT wagon INTO vFreeWagonFk - FROM tTrain - GROUP BY wagon - HAVING SUM(IFNULL(ticketFk, 0)) = 0 + SELECT tt.wagon + INTO vFreeWagonFk + FROM tTrain tt + LEFT JOIN ( + SELECT DISTINCT wagon + FROM tTrain + WHERE ticketFk IS NOT NULL + ) nn ON nn.wagon = tt.wagon + WHERE nn.wagon IS NULL ORDER BY wagon LIMIT 1; @@ -255,35 +280,38 @@ BEGIN SET ticketFk = vFirstTicketFk WHERE wagon = vFreeWagonFk; - -- Se anulan el resto de carros libres, - -- máximo un carro con pedido excesivo - - DELETE tt + -- Se anulan el resto de carros libres para que sólo uno lleve un pedido excesivo + DELETE tt.* FROM tTrain tt - JOIN (SELECT wagon - FROM tTrain - GROUP BY wagon - HAVING SUM(IFNULL(ticketFk, 0)) = 0 - ) sub ON sub.wagon = tt.wagon; + LEFT JOIN ( + SELECT DISTINCT wagon + FROM tTrain + WHERE ticketFk IS NOT NULL + ) nn ON nn.wagon = tt.wagon + WHERE nn.wagon IS NULL; END IF; - END IF; + END IF; + + FETCH c1 INTO vTicketFk, vTicketLines, vTicketVolume; + IF vDone OR NOT (SELECT COUNT(*) FROM tTrain WHERE ticketFk IS NULL) THEN + LEAVE read_loop; + END IF; + ELSE + FETCH c1 INTO vTicketFk, vTicketLines, vTicketVolume; + IF vDone THEN + LEAVE read_loop; + END IF; END IF; END LOOP; - CLOSE vTickets; + CLOSE c1; IF (SELECT COUNT(*) FROM tTrain WHERE ticketFk) THEN - -- Se obtiene nº de colección - - INSERT INTO collection - SET itemPackingTypeFk = vItemPackingTypeFk, - trainFk = vTrainFk, - wagons = vWagons, - warehouseFk = vWarehouseFk; - - SELECT LAST_INSERT_ID() INTO vCollectionFk; + UPDATE collection c + JOIN state st ON st.code = 'ON_PREPARATION' + SET c.stateFk = st.id + WHERE c.id = vCollectionFk; -- Asigna las bandejas - INSERT IGNORE INTO ticketCollection(ticketFk, collectionFk, `level`, wagon, liters) SELECT tt.ticketFk, vCollectionFk, tt.shelve, tt.wagon, tt.liters FROM tTrain tt @@ -291,34 +319,37 @@ BEGIN ORDER BY tt.wagon, tt.shelve; -- Actualiza el estado de los tickets - - CALL collection_setState(vCollectionFk, vStateCode); + CALL collection_setState(vCollectionFk, vStateFk); -- Aviso para la preparacion previa - INSERT INTO ticketDown(ticketFk, collectionFk) SELECT tc.ticketFk, tc.collectionFk FROM ticketCollection tc WHERE tc.collectionFk = vCollectionFk; - CALL collection_mergeSales(vCollectionFk); + CALL sales_mergeByCollection(vCollectionFk); UPDATE `collection` c - JOIN( + JOIN ( SELECT COUNT(*) saleTotalCount, SUM(s.isPicked <> 0) salePickedCount FROM ticketCollection tc JOIN sale s ON s.ticketFk = tc.ticketFk - WHERE tc.collectionFk = vCollectionFk - AND s.quantity > 0 - )sub + WHERE tc.collectionFk = vCollectionFk + AND s.quantity > 0 + ) sub SET c.saleTotalCount = sub.saleTotalCount, c.salePickedCount = sub.salePickedCount WHERE c.id = vCollectionFk; + ELSE - SET vCollectionFk = NULL; + DELETE FROM `collection` + WHERE id = vCollectionFk; + SET vCollectionFk = NULL; END IF; + DO RELEASE_LOCK(vLockName); + DROP TEMPORARY TABLE tTrain, tmp.productionBuffer; diff --git a/db/routines/vn/procedures/ticket_mergeSales.sql b/db/routines/vn/procedures/ticket_mergeSales.sql index 2dc3a39da..674587bb4 100644 --- a/db/routines/vn/procedures/ticket_mergeSales.sql +++ b/db/routines/vn/procedures/ticket_mergeSales.sql @@ -3,47 +3,41 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_mergeSales`( vSelf INT ) BEGIN - DECLARE vHasSalesToMerge BOOL; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN ROLLBACK; RESIGNAL; END; - START TRANSACTION; - - SELECT id INTO vSelf - FROM ticket - WHERE id = vSelf FOR UPDATE; - CREATE OR REPLACE TEMPORARY TABLE tSalesToPreserve (PRIMARY KEY (id)) ENGINE = MEMORY - SELECT s.id, s.itemFk, SUM(s.quantity) newQuantity + SELECT s.id, s.itemFk, SUM(s.quantity) newQuantity FROM sale s JOIN item i ON i.id = s.itemFk JOIN itemType it ON it.id = i.typeFk - WHERE s.ticketFk = vSelf + WHERE s.ticketFk = vTicketFk AND it.isMergeable - GROUP BY s.itemFk, s.price, s.discount - HAVING COUNT(*) > 1; + GROUP BY s.itemFk, s.price, s.discount; - SELECT COUNT(*) INTO vHasSalesToMerge - FROM tSalesToPreserve; + START TRANSACTION; - IF vHasSalesToMerge THEN - UPDATE sale s - JOIN tSalesToPreserve stp ON stp.id = s.id - SET s.quantity = newQuantity; + UPDATE sale s + JOIN tSalesToPreserve stp ON stp.id = s.id + SET s.quantity = newQuantity + WHERE s.ticketFk = vTicketFk; - DELETE s - FROM sale s - JOIN tSalesToPreserve stp ON stp.itemFk = s.itemFk - WHERE s.ticketFk = vSelf - AND s.id <> stp.id; - END IF; + DELETE s.* + FROM sale s + LEFT JOIN tSalesToPreserve stp ON stp.id = s.id + JOIN item i ON i.id = s.itemFk + JOIN itemType it ON it.id = i.typeFk + WHERE s.ticketFk = vTicketFk + AND stp.id IS NULL + AND it.isMergeable; COMMIT; + DROP TEMPORARY TABLE tSalesToPreserve; END$$ DELIMITER ; From 55df91907696a20c1e30718849b6da95d349fe86 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 17 Sep 2024 09:37:25 +0200 Subject: [PATCH 11/18] fix: refs #7760 collection_new --- db/routines/vn/procedures/ticket_mergeSales.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/db/routines/vn/procedures/ticket_mergeSales.sql b/db/routines/vn/procedures/ticket_mergeSales.sql index 674587bb4..28b2dc1c0 100644 --- a/db/routines/vn/procedures/ticket_mergeSales.sql +++ b/db/routines/vn/procedures/ticket_mergeSales.sql @@ -16,7 +16,7 @@ BEGIN FROM sale s JOIN item i ON i.id = s.itemFk JOIN itemType it ON it.id = i.typeFk - WHERE s.ticketFk = vTicketFk + WHERE s.ticketFk = vSelf AND it.isMergeable GROUP BY s.itemFk, s.price, s.discount; @@ -25,14 +25,14 @@ BEGIN UPDATE sale s JOIN tSalesToPreserve stp ON stp.id = s.id SET s.quantity = newQuantity - WHERE s.ticketFk = vTicketFk; + WHERE s.ticketFk = vSelf; DELETE s.* FROM sale s LEFT JOIN tSalesToPreserve stp ON stp.id = s.id JOIN item i ON i.id = s.itemFk JOIN itemType it ON it.id = i.typeFk - WHERE s.ticketFk = vTicketFk + WHERE s.ticketFk = vSelf AND stp.id IS NULL AND it.isMergeable; From 019d855fbf112e266f700c961ef2fd8b2082f5ad Mon Sep 17 00:00:00 2001 From: Pako Date: Tue, 17 Sep 2024 11:22:07 +0200 Subject: [PATCH 12/18] fix: refs #7969 new plantTray restriction --- db/dump/fixtures.before.sql | 2 +- db/routines/vn/procedures/productionControl.sql | 5 ++--- db/versions/11239-goldenBirch/00-firstScript.sql | 2 ++ 3 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 db/versions/11239-goldenBirch/00-firstScript.sql diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index ea689c609..6992dd6f8 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -3180,7 +3180,7 @@ UPDATE vn.department SET workerFk = null; INSERT INTO vn.packaging - VALUES('--', 2745600.00, 100.00, 120.00, 220.00, 0.00, 1, '2001-01-01 00:00:00.000', NULL, NULL, NULL, 0.00, 16, 0.00, 0, NULL, 0.00, NULL, NULL, 0, NULL, 0, 0); + VALUES('--', 2745600.00, 100.00, 120.00, 220.00, 0.00, 1, '2001-01-01 00:00:00.000', NULL, NULL, NULL, 0.00, 16, 0.00, 0, NULL, 0.00, NULL, NULL, 0, NULL, 0, 0,0); INSERT IGNORE INTO vn.intrastat diff --git a/db/routines/vn/procedures/productionControl.sql b/db/routines/vn/procedures/productionControl.sql index 5d97e3f55..ba8764c77 100644 --- a/db/routines/vn/procedures/productionControl.sql +++ b/db/routines/vn/procedures/productionControl.sql @@ -274,9 +274,8 @@ proc: BEGIN JOIN buy b ON b.id = lb.buy_id JOIN packaging p ON p.id = b.packagingFk JOIN productionConfig pc - SET hasPlantTray = TRUE - WHERE ic.code = 'plant' - AND p.`depth` >= pc.minPlantTrayLength + SET pb.hasPlantTray = TRUE + WHERE p.isPlantTray AND pb.isOwn; DROP TEMPORARY TABLE diff --git a/db/versions/11239-goldenBirch/00-firstScript.sql b/db/versions/11239-goldenBirch/00-firstScript.sql new file mode 100644 index 000000000..559982081 --- /dev/null +++ b/db/versions/11239-goldenBirch/00-firstScript.sql @@ -0,0 +1,2 @@ +-- Place your SQL code here +ALTER TABLE vn.packaging ADD IF NOT EXISTS isPlantTray BOOL DEFAULT FALSE NOT NULL COMMENT 'The container is a plant tray. Used to restrict the picking of full plant trays, to make previous picking.'; From 4332fccfcccd76774f3cdc6be54dde7cdce6d5ae Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 17 Sep 2024 11:43:34 +0200 Subject: [PATCH 13/18] chore: refs #7524 rollback --- modules/client/front/balance/create/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/client/front/balance/create/index.js b/modules/client/front/balance/create/index.js index c0bc11c0b..f1474e10c 100644 --- a/modules/client/front/balance/create/index.js +++ b/modules/client/front/balance/create/index.js @@ -7,10 +7,6 @@ class Controller extends Dialog { this.vnReport = vnReport; this.vnEmail = vnEmail; this.receipt = {}; - - this.$.$watch(() => this.clientFk, (newVal, oldVal) => { - if (!this.receipt.amountPaid && newVal != oldVal) this.getAmountPaid(); - }); } set payed(value) { @@ -55,6 +51,7 @@ class Controller extends Dialog { set companyFk(value) { this.receipt.companyFk = value; + this.getAmountPaid(); } set description(value) { From 529be86d8430176d54070ce8d2d6bf68e8a37bb8 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 17 Sep 2024 11:44:09 +0200 Subject: [PATCH 14/18] fix: refs #7524 too records error --- modules/ticket/front/descriptor-menu/index.html | 7 ------- 1 file changed, 7 deletions(-) diff --git a/modules/ticket/front/descriptor-menu/index.html b/modules/ticket/front/descriptor-menu/index.html index 82094d7b8..b861b0c0e 100644 --- a/modules/ticket/front/descriptor-menu/index.html +++ b/modules/ticket/front/descriptor-menu/index.html @@ -349,13 +349,6 @@ message="Recalculate components"> - - - - Date: Tue, 17 Sep 2024 11:57:00 +0200 Subject: [PATCH 15/18] feat(collection_new): refs #7969 new restriction hasPlantTray for pickers Refs: #7969 --- db/routines/vn/procedures/collection_new.sql | 23 ++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/db/routines/vn/procedures/collection_new.sql b/db/routines/vn/procedures/collection_new.sql index 545320081..dc1280373 100644 --- a/db/routines/vn/procedures/collection_new.sql +++ b/db/routines/vn/procedures/collection_new.sql @@ -29,6 +29,8 @@ BEGIN DECLARE vLockName VARCHAR(215); DECLARE vLockTime INT DEFAULT 30; DECLARE vFreeWagonFk INT; + DECLARE vErrorNumber INT; + DECLARE vErrorMsg TEXT; DECLARE c1 CURSOR FOR SELECT ticketFk, `lines`, m3 @@ -48,6 +50,18 @@ BEGIN DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN + GET DIAGNOSTICS CONDITION 1 + vErrorNumber = MYSQL_ERRNO, + vErrorMsg = MESSAGE_TEXT; + + CALL util.debugAdd('collection_new', JSON_OBJECT( + 'errorNumber', vErrorNumber, + 'errorMsg', vErrorMsg, + 'lockName', vLockName, + 'userFk', vUserFk, + 'ticketFk', vTicketFk + )); -- Tmp + IF vLockName IS NOT NULL THEN DO RELEASE_LOCK(vLockName); END IF; @@ -180,9 +194,10 @@ BEGIN OR (NOT pb.V AND vItemPackingTypeFk = 'V') OR (pc.isPreviousPreparationRequired AND pb.previousWithoutParking) OR LENGTH(pb.problem) > 0 - OR (pb.lines > vLinesLimit AND vLinesLimit IS NOT NULL) - OR (pb.m3 > vVolumeLimit AND vVolumeLimit IS NOT NULL) - OR ((sub.maxSize > vSizeLimit OR sub.maxSize IS NOT NULL) AND vSizeLimit IS NOT NULL); + OR pb.lines > vLinesLimit + OR pb.m3 > vVolumeLimit + OR sub.maxSize > vSizeLimit + OR pb.hasPlantTray; END IF; -- Es importante que el primer ticket se coja en todos los casos @@ -354,4 +369,4 @@ BEGIN tTrain, tmp.productionBuffer; END$$ -DELIMITER ; +DELIMITER ; \ No newline at end of file From 4a102d315d4abe9e4f406d27a25700c5ac090c71 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 17 Sep 2024 12:10:47 +0200 Subject: [PATCH 16/18] fix: refs #7564 Ticket volume item cost --- .../vn/procedures/ticket_setVolume.sql | 2 +- .../procedures/ticket_setVolumeItemCost.sql | 32 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/db/routines/vn/procedures/ticket_setVolume.sql b/db/routines/vn/procedures/ticket_setVolume.sql index 060a6fa57..d0fe9740c 100644 --- a/db/routines/vn/procedures/ticket_setVolume.sql +++ b/db/routines/vn/procedures/ticket_setVolume.sql @@ -4,7 +4,7 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_setVolume`( ) BEGIN /** - * Update the volume ticket + * Update the volume ticket. * * @param vSelf Ticket id */ diff --git a/db/routines/vn/procedures/ticket_setVolumeItemCost.sql b/db/routines/vn/procedures/ticket_setVolumeItemCost.sql index f266cd769..d7fb4473d 100644 --- a/db/routines/vn/procedures/ticket_setVolumeItemCost.sql +++ b/db/routines/vn/procedures/ticket_setVolumeItemCost.sql @@ -4,26 +4,36 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_setVolumeIte ) BEGIN /** - * Update the volume tickets of item + * Update the volume of tickets containing the item. * - * @param vSelf Ticket id + * @param vItemFk Item id */ - CREATE OR REPLACE TEMPORARY TABLE tTicket - (PRIMARY KEY (id)) - ENGINE = MEMORY - SELECT t.id, SUM(s.quantity * ic.cm3delivery / 1000000) volume + DECLARE vTicket INT; + DECLARE vDone BOOL; + + DECLARE vTickets CURSOR FOR + SELECT DISTINCT t.id FROM sale s JOIN ticket t ON t.id = s.ticketFk JOIN itemCost ic ON ic.itemFk = s.itemFk AND ic.warehouseFk = t.warehouseFk WHERE s.itemFk = vItemFk AND t.shipped >= util.VN_CURDATE() - GROUP BY t.id; + AND t.refFk IS NULL; - UPDATE ticket t - JOIN tTicket tt ON tt.id = t.id - SET t.volume = tt.volume; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; - DROP TEMPORARY TABLE tTicket; + OPEN vTickets; + l: LOOP + FETCH vTickets INTO vTicket; + + IF vDone THEN + LEAVE l; + END IF; + + CALL ticket_setVolume(vTicket); + + END LOOP l; + CLOSE vTickets; END$$ DELIMITER ; From 974827443c4c52c6fcf66ec0493d0231bab751bb Mon Sep 17 00:00:00 2001 From: sergiodt Date: Tue, 17 Sep 2024 13:11:27 +0200 Subject: [PATCH 17/18] fix: refs #6861 itemShelvingSale transaction --- .../procedures/itemShelvingSale_addBySale.sql | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/db/routines/vn/procedures/itemShelvingSale_addBySale.sql b/db/routines/vn/procedures/itemShelvingSale_addBySale.sql index aa50f0ed8..6625e89b8 100644 --- a/db/routines/vn/procedures/itemShelvingSale_addBySale.sql +++ b/db/routines/vn/procedures/itemShelvingSale_addBySale.sql @@ -48,6 +48,13 @@ proc: BEGIN RESIGNAL; END; + START TRANSACTION; + + SELECT id INTO vSaleFk + FROM sale + WHERE id = vSaleFk + FOR UPDATE; + SELECT MAX(p.pickingOrder), s.quantity - SUM(IFNULL(iss.quantity, 0)), s.quantity INTO vLastPickingOrder, vOutStanding, vSaleQuantity FROM sale s @@ -57,7 +64,8 @@ proc: BEGIN LEFT JOIN parking p ON p.id = sh.parkingFk WHERE s.id = vSaleFk; - IF vOutStanding <= 0 THEN + IF vOutStanding <= 0 THEN + COMMIT; LEAVE proc; END IF; @@ -84,10 +92,8 @@ proc: BEGIN END IF; LEAVE l; END IF; - - START TRANSACTION; - - SELECT id INTO vItemShelvingFk + + SELECT id INTO vItemShelvingFk FROM itemShelving WHERE id = vItemShelvingFk FOR UPDATE; @@ -115,9 +121,8 @@ proc: BEGIN WHERE id = vItemShelvingFk; END IF; - - COMMIT; END LOOP; CLOSE vItemShelvingAvailable; + COMMIT; END$$ DELIMITER ; \ No newline at end of file From 871d5457d041e0362e95c190e5600da3c90d56ea Mon Sep 17 00:00:00 2001 From: guillermo Date: Wed, 18 Sep 2024 07:14:52 +0200 Subject: [PATCH 18/18] 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 ac434213d..760d622b6 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 7c4a476c5..e05225204 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';