From 6fbc5a1a544e3feff1e9a6feb05785db15eda975 Mon Sep 17 00:00:00 2001 From: Jon Date: Mon, 30 Sep 2024 09:17:27 +0200 Subject: [PATCH 01/39] feat: refs #7202 added new field --- db/dump/fixtures.before.sql | 98 +++++++++---------- .../11269-wheatBirch/00-firstScript.sql | 9 ++ .../back/methods/invoiceOut/filter.js | 14 ++- .../invoiceOut/back/models/invoice-out.json | 5 + 4 files changed, 75 insertions(+), 51 deletions(-) create mode 100644 db/versions/11269-wheatBirch/00-firstScript.sql diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index ffbc6a864..33090d7a6 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -425,50 +425,50 @@ INSERT INTO `vn`.`clientConfig`(`id`, `riskTolerance`, `maxCreditRows`, `maxPric (1, 200, 10, 0.25, 2, 4, 5, 300.00, 1, 1, 2); -INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`, `isDefaultAddress`) +INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `phone`, `mobile`, `isActive`, `clientFk`, `agencyModeFk`, `longitude`, `latitude`, `isEqualizated`, `isDefaultAddress`, `customsAgentFk`) VALUES - (1, 'Bruce Wayne', '1007 Mountain Drive, Gotham', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, NULL, NULL, 0, 1), - (2, 'Petter Parker', '20 Ingram Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, NULL, NULL, 0, 1), - (3, 'Clark Kent', '344 Clinton Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, NULL, NULL, 0, 1), - (4, 'Tony Stark', '10880 Malibu Point', 'Gotham', 46460, 1, 1111111111, 222222222, 1 , 1104, 2, NULL, NULL, 0, 1), - (5, 'Max Eisenhardt', 'Unknown Whereabouts', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 1), - (6, 'DavidCharlesHaller', 'Evil hideout', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 1), - (7, 'Hank Pym', 'Anthill', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 1), - (8, 'Charles Xavier', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Gotham', 46460, 5, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 1), - (9, 'Bruce Banner', 'Somewhere in New York', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 1), - (10, 'Jessica Jones', 'NYCC 2015 Poster', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 1), - (11, 'Missing', 'The space', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1111, 10, NULL, NULL, 0, 1), - (12, 'Trash', 'New York city', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1112, 10, NULL, NULL, 0, 1), - (101, 'Somewhere in Thailand', 'address 01', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (102, 'Somewhere in Poland', 'address 02', 'Gotham', 46460, 1, 3333333333, 444444444, 1, 1109, 2, NULL, NULL, 0, 0), - (103, 'Somewhere in Japan', 'address 03', 'Gotham', 46460, 1, 3333333333, 444444444, 1, 1109, 2, NULL, NULL, 0, 0), - (104, 'Somewhere in Spain', 'address 04', 'Gotham', 46460, 1, 3333333333, 444444444, 1, 1109, 2, NULL, NULL, 0, 0), - (105, 'Somewhere in Potugal', 'address 05', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0), - (106, 'Somewhere in UK', 'address 06', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0), - (107, 'Somewhere in Valencia', 'address 07', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0), - (108, 'Somewhere in Gotham', 'address 08', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0), - (109, 'Somewhere in London', 'address 09', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (110, 'Somewhere in Algemesi', 'address 10', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (111, 'Somewhere in Carlet', 'address 11', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (112, 'Somewhere in Campanar', 'address 12', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (113, 'Somewhere in Malilla', 'address 13', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (114, 'Somewhere in France', 'address 14', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (115, 'Somewhere in Birmingham', 'address 15', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (116, 'Somewhere in Scotland', 'address 16', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (117, 'Somewhere in nowhere', 'address 17', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (118, 'Somewhere over the rainbow', 'address 18', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (119, 'Somewhere in Alberic', 'address 19', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (120, 'Somewhere in Montortal', 'address 20', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0), - (121, 'the bat cave', 'address 21', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, NULL, NULL, 0, 0), - (122, 'NY roofs', 'address 22', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, NULL, NULL, 0, 0), - (123, 'The phone box', 'address 23', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, NULL, NULL, 0, 0), - (124, 'Stark tower Gotham', 'address 24', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1104, 2, NULL, NULL, 0, 0), - (125, 'The plastic cell', 'address 25', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 0), - (126, 'Many places', 'address 26', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 0), - (127, 'Your pocket', 'address 27', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 0), - (128, 'Cerebro', 'address 28', 'Gotham', 46460, 5, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 0), - (129, 'Luke Cages Bar', 'address 29', 'Gotham', 'EC170150', 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 0), - (130, 'Non valid address', 'address 30', 'Gotham', 46460, 1, 1111111111, 222222222, 0, 1101, 2, NULL, NULL, 0, 0); + (1, 'Bruce Wayne', '1007 Mountain Drive, Gotham', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, NULL, NULL, 0, 1, 1), + (2, 'Petter Parker', '20 Ingram Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, NULL, NULL, 0, 1, NULL), + (3, 'Clark Kent', '344 Clinton Street', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, NULL, NULL, 0, 1, NULL), + (4, 'Tony Stark', '10880 Malibu Point', 'Gotham', 46460, 1, 1111111111, 222222222, 1 , 1104, 2, NULL, NULL, 0, 1, NULL), + (5, 'Max Eisenhardt', 'Unknown Whereabouts', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 1, NULL), + (6, 'DavidCharlesHaller', 'Evil hideout', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 1, NULL), + (7, 'Hank Pym', 'Anthill', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 1, NULL), + (8, 'Charles Xavier', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Gotham', 46460, 5, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 1, NULL), + (9, 'Bruce Banner', 'Somewhere in New York', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 1, NULL), + (10, 'Jessica Jones', 'NYCC 2015 Poster', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 1, NULL), + (11, 'Missing', 'The space', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1111, 10, NULL, NULL, 0, 1, NULL), + (12, 'Trash', 'New York city', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1112, 10, NULL, NULL, 0, 1, NULL), + (101, 'Somewhere in Thailand', 'address 01', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (102, 'Somewhere in Poland', 'address 02', 'Gotham', 46460, 1, 3333333333, 444444444, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (103, 'Somewhere in Japan', 'address 03', 'Gotham', 46460, 1, 3333333333, 444444444, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (104, 'Somewhere in Spain', 'address 04', 'Gotham', 46460, 1, 3333333333, 444444444, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (105, 'Somewhere in Potugal', 'address 05', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (106, 'Somewhere in UK', 'address 06', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (107, 'Somewhere in Valencia', 'address 07', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (108, 'Somewhere in Gotham', 'address 08', 'Gotham', 46460, 1, 5555555555, 666666666, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (109, 'Somewhere in London', 'address 09', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (110, 'Somewhere in Algemesi', 'address 10', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (111, 'Somewhere in Carlet', 'address 11', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (112, 'Somewhere in Campanar', 'address 12', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (113, 'Somewhere in Malilla', 'address 13', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (114, 'Somewhere in France', 'address 14', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (115, 'Somewhere in Birmingham', 'address 15', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (116, 'Somewhere in Scotland', 'address 16', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (117, 'Somewhere in nowhere', 'address 17', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (118, 'Somewhere over the rainbow', 'address 18', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (119, 'Somewhere in Alberic', 'address 19', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (120, 'Somewhere in Montortal', 'address 20', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1109, 2, NULL, NULL, 0, 0, NULL), + (121, 'the bat cave', 'address 21', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1101, 2, NULL, NULL, 0, 0, NULL), + (122, 'NY roofs', 'address 22', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1102, 2, NULL, NULL, 0, 0, NULL), + (123, 'The phone box', 'address 23', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1103, 2, NULL, NULL, 0, 0, NULL), + (124, 'Stark tower Gotham', 'address 24', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1104, 2, NULL, NULL, 0, 0, NULL), + (125, 'The plastic cell', 'address 25', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1105, 2, NULL, NULL, 0, 0, NULL), + (126, 'Many places', 'address 26', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1106, 2, NULL, NULL, 0, 0, NULL), + (127, 'Your pocket', 'address 27', 'Gotham', 46460, 1, 1111111111, 222222222, 1, 1107, 2, NULL, NULL, 0, 0, NULL), + (128, 'Cerebro', 'address 28', 'Gotham', 46460, 5, 1111111111, 222222222, 1, 1108, 2, NULL, NULL, 0, 0, NULL), + (129, 'Luke Cages Bar', 'address 29', 'Gotham', 'EC170150', 1, 1111111111, 222222222, 1, 1110, 2, NULL, NULL, 0, 0, NULL), + (130, 'Non valid address', 'address 30', 'Gotham', 46460, 1, 1111111111, 222222222, 0, 1101, 2, NULL, NULL, 0, 0, NULL); INSERT INTO `vn`.`address`( `nickname`, `street`, `city`, `postalCode`, `provinceFk`, `isActive`, `clientFk`, `agencyModeFk`, `isDefaultAddress`) SELECT name, CONCAT(name, 'Street'), 'GOTHAM', 46460, 1, 1, id, 2, 1 @@ -639,13 +639,13 @@ INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaF ('R', 'Rectificativa', 1, 'NATIONAL', 0, NULL), ('E', 'Exportación rápida', 0, 'WORLD', 0, 'quick'); -INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`) +INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`, `customsAgentFk`) VALUES - (1, 'T', 1026.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), - (2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), - (3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), - (4, 'T', 8.88, util.VN_CURDATE(), 1104, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), - (5, 'A', 8.88, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1103, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 442, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 0); + (1, 'T', 1026.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, 1), + (2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, NULL), + (3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, NULL), + (4, 'T', 8.88, util.VN_CURDATE(), 1104, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, NULL), + (5, 'A', 8.88, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1103, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 442, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 0, NULL); UPDATE `vn`.`invoiceOut` SET ref = 'T1111111' WHERE id = 1; UPDATE `vn`.`invoiceOut` SET ref = 'T2222222' WHERE id = 2; diff --git a/db/versions/11269-wheatBirch/00-firstScript.sql b/db/versions/11269-wheatBirch/00-firstScript.sql new file mode 100644 index 000000000..b2f113167 --- /dev/null +++ b/db/versions/11269-wheatBirch/00-firstScript.sql @@ -0,0 +1,9 @@ +ALTER TABLE vn.invoiceOut ADD COLUMN IF NOT EXISTS customsAgentFk INT(11) DEFAULT NULL AFTER siiTrascendencyInvoiceOutFk; + +ALTER TABLE vn.invoiceOut ADD CONSTRAINT invoiceOut_customsAgentFk FOREIGN KEY (customsAgentFk) + REFERENCES vn.customsAgent (id) ON DELETE RESTRICT ON UPDATE CASCADE; + +UPDATE vn.invoiceOut i + JOIN vn.client c ON c.id = io.clientFk + JOIN vn.address a ON a.id = c.defaultAddressFk + SET i.customsAgentFk = a.customsAgentFk; \ No newline at end of file diff --git a/modules/invoiceOut/back/methods/invoiceOut/filter.js b/modules/invoiceOut/back/methods/invoiceOut/filter.js index 99a80c169..3b6aa4d82 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/filter.js +++ b/modules/invoiceOut/back/methods/invoiceOut/filter.js @@ -73,6 +73,12 @@ module.exports = Self => { type: 'date', description: 'The due date filter', http: {source: 'query'} + }, + { + arg: 'customsAgentFk', + type: 'integer', + description: 'The customsAgent id', + http: {source: 'query'} } ], returns: { @@ -112,6 +118,7 @@ module.exports = Self => { case 'companyFk': case 'issued': case 'dued': + case 'customsAgentFk': param = `i.${param}`; return {[param]: value}; } @@ -131,11 +138,14 @@ module.exports = Self => { i.dued, i.clientFk, i.hasPdf, + i.customsAgentFk, c.socialName AS clientSocialName, - co.code AS companyCode + co.code AS companyCode, + ca.fiscalName AS customsAgentName FROM invoiceOut i LEFT JOIN client c ON c.id = i.clientFk - LEFT JOIN company co ON co.id = i.companyFk` + LEFT JOIN company co ON co.id = i.companyFk + LEFT JOIN customsAgent ca ON ca.id = i.customsAgentFk` ); stmt.merge(conn.makeSuffix(filter)); diff --git a/modules/invoiceOut/back/models/invoice-out.json b/modules/invoiceOut/back/models/invoice-out.json index 1ee36accb..2ad13fe3f 100644 --- a/modules/invoiceOut/back/models/invoice-out.json +++ b/modules/invoiceOut/back/models/invoice-out.json @@ -66,6 +66,11 @@ "model": "Ticket", "foreignKey": "refFk", "primaryKey": "ref" + }, + "customsAgentFk": { + "type": "belongsTo", + "model": "CustomsAgent", + "foreignKey": "customsAgentFk" } } } -- 2.40.1 From da749a5dcbe9cbc648ec16281d80a96493acda4b Mon Sep 17 00:00:00 2001 From: Jon Date: Mon, 30 Sep 2024 09:21:05 +0200 Subject: [PATCH 02/39] fix: refs #7202 fixed sql --- db/versions/11269-wheatBirch/00-firstScript.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/versions/11269-wheatBirch/00-firstScript.sql b/db/versions/11269-wheatBirch/00-firstScript.sql index b2f113167..6a50e5232 100644 --- a/db/versions/11269-wheatBirch/00-firstScript.sql +++ b/db/versions/11269-wheatBirch/00-firstScript.sql @@ -3,7 +3,7 @@ ALTER TABLE vn.invoiceOut ADD COLUMN IF NOT EXISTS customsAgentFk INT(11) DEFAUL ALTER TABLE vn.invoiceOut ADD CONSTRAINT invoiceOut_customsAgentFk FOREIGN KEY (customsAgentFk) REFERENCES vn.customsAgent (id) ON DELETE RESTRICT ON UPDATE CASCADE; -UPDATE vn.invoiceOut i +UPDATE vn.invoiceOut io JOIN vn.client c ON c.id = io.clientFk JOIN vn.address a ON a.id = c.defaultAddressFk - SET i.customsAgentFk = a.customsAgentFk; \ No newline at end of file + SET io.customsAgentFk = a.customsAgentFk; \ No newline at end of file -- 2.40.1 From 451e3bebefaad230d5eb30222aa07afff29d6e3b Mon Sep 17 00:00:00 2001 From: Jon Date: Mon, 30 Sep 2024 09:45:55 +0200 Subject: [PATCH 03/39] fix: refs #7202 fixed back test --- .../client/back/methods/client/specs/updateAddress.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/client/back/methods/client/specs/updateAddress.spec.js b/modules/client/back/methods/client/specs/updateAddress.spec.js index 68981f8b7..0453332d7 100644 --- a/modules/client/back/methods/client/specs/updateAddress.spec.js +++ b/modules/client/back/methods/client/specs/updateAddress.spec.js @@ -1,7 +1,7 @@ const models = require('vn-loopback/server/server').models; describe('Address updateAddress', () => { - const clientId = 1101; - const addressId = 1; + const clientId = 1102; + const addressId = 2; const provinceId = 5; const incotermsId = 'FAS'; const customAgentOneId = 1; -- 2.40.1 From a6799cba0ff74c1740220430b18ad38fea1f5a79 Mon Sep 17 00:00:00 2001 From: Jon Date: Tue, 1 Oct 2024 10:39:57 +0200 Subject: [PATCH 04/39] refactor: refs #7202 modified procedure to include customsAgent field when creating an invoice --- db/routines/vn/procedures/invoiceOut_new.sql | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/db/routines/vn/procedures/invoiceOut_new.sql b/db/routines/vn/procedures/invoiceOut_new.sql index 723f33df5..6f2f7f8ff 100644 --- a/db/routines/vn/procedures/invoiceOut_new.sql +++ b/db/routines/vn/procedures/invoiceOut_new.sql @@ -105,7 +105,8 @@ BEGIN clientFk, dued, companyFk, - siiTypeInvoiceOutFk + siiTypeInvoiceOutFk, + customsAgentFk ) SELECT 1, @@ -118,9 +119,11 @@ BEGIN vCplusCorrectingInvoiceTypeFk, IF(vSerial = vSimplifiedSerial, vCplusSimplifiedInvoiceTypeFk, - vCplusStandardInvoiceTypeFk)) - FROM client - WHERE id = vClientFk; + vCplusStandardInvoiceTypeFk)), + a.customsAgentFk + FROM client c + JOIN address a ON a.id = c.defaultAddressFk + WHERE c.id = vClientFk; SET vNewInvoiceId = LAST_INSERT_ID(); -- 2.40.1 From 2ec0d7f186526d774a79ca07f80da9d9f6efc793 Mon Sep 17 00:00:00 2001 From: Jon Date: Wed, 23 Oct 2024 08:10:00 +0200 Subject: [PATCH 05/39] refactor: refs #7202 modified new invoice procedure and incoterms sql --- db/dump/fixtures.before.sql | 12 ++++----- db/routines/vn/procedures/invoiceOut_new.sql | 15 +++++++---- .../11269-wheatBirch/00-firstScript.sql | 12 ++++++--- .../invoice-incoterms/sql/incoterms.sql | 27 +++++++++++-------- 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index e48fb36b0..a418876b0 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -639,13 +639,13 @@ INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaF ('R', 'Rectificativa', 1, 'NATIONAL', 0, NULL), ('E', 'Exportación rápida', 0, 'WORLD', 0, 'quick'); -INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`, `customsAgentFk`) +INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`, `customsAgentFk`, `incotermsFk`) VALUES - (1, 'T', 1026.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, 1), - (2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, NULL), - (3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, NULL), - (4, 'T', 8.88, util.VN_CURDATE(), 1104, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, NULL), - (5, 'A', 8.88, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1103, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 442, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 0, NULL); + (1, 'E', 1026.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, 1, 'FAS'), + (2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, NULL, NULL), + (3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, NULL, NULL), + (4, 'T', 8.88, util.VN_CURDATE(), 1104, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0, NULL, NULL), + (5, 'A', 8.88, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1103, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 442, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1, 0, NULL, NULL); UPDATE `vn`.`invoiceOut` SET ref = 'T1111111' WHERE id = 1; UPDATE `vn`.`invoiceOut` SET ref = 'T2222222' WHERE id = 2; diff --git a/db/routines/vn/procedures/invoiceOut_new.sql b/db/routines/vn/procedures/invoiceOut_new.sql index 6f2f7f8ff..1f20fb5fc 100644 --- a/db/routines/vn/procedures/invoiceOut_new.sql +++ b/db/routines/vn/procedures/invoiceOut_new.sql @@ -34,6 +34,7 @@ BEGIN DECLARE vMaxShipped DATE; DECLARE vDone BOOL; DECLARE vTicketFk INT; + DECLARE vAddressFk INT; DECLARE vCursor CURSOR FOR SELECT id FROM tmp.ticketToInvoice; @@ -48,11 +49,13 @@ BEGIN DATE(vInvoiceDate) >= invoiceOut_getMaxIssued( vSerial, t.companyFk, - YEAR(vInvoiceDate)) + YEAR(vInvoiceDate)), + t.addressFk INTO vClientFk, vCompanyFk, vMaxShipped, - vIsCorrectInvoiceDate + vIsCorrectInvoiceDate, + vAddressFk FROM tmp.ticketToInvoice tt JOIN ticket t ON t.id = tt.id; @@ -106,7 +109,8 @@ BEGIN dued, companyFk, siiTypeInvoiceOutFk, - customsAgentFk + customsAgentFk, + incotermsFk ) SELECT 1, @@ -120,9 +124,10 @@ BEGIN IF(vSerial = vSimplifiedSerial, vCplusSimplifiedInvoiceTypeFk, vCplusStandardInvoiceTypeFk)), - a.customsAgentFk + a.customsAgentFk, + a.incotermsFk FROM client c - JOIN address a ON a.id = c.defaultAddressFk + JOIN address a ON a.id = vAddressFk WHERE c.id = vClientFk; SET vNewInvoiceId = LAST_INSERT_ID(); diff --git a/db/versions/11269-wheatBirch/00-firstScript.sql b/db/versions/11269-wheatBirch/00-firstScript.sql index 6a50e5232..9432d131b 100644 --- a/db/versions/11269-wheatBirch/00-firstScript.sql +++ b/db/versions/11269-wheatBirch/00-firstScript.sql @@ -1,9 +1,15 @@ ALTER TABLE vn.invoiceOut ADD COLUMN IF NOT EXISTS customsAgentFk INT(11) DEFAULT NULL AFTER siiTrascendencyInvoiceOutFk; +ALTER TABLE vn.invoiceOut ADD COLUMN IF NOT EXISTS incotermsFk varchar(3) DEFAULT NULL AFTER customsAgentFk; ALTER TABLE vn.invoiceOut ADD CONSTRAINT invoiceOut_customsAgentFk FOREIGN KEY (customsAgentFk) REFERENCES vn.customsAgent (id) ON DELETE RESTRICT ON UPDATE CASCADE; +ALTER TABLE vn.invoiceOut ADD CONSTRAINT invoiceOut_incotermsFk FOREIGN KEY (incotermsFk) + REFERENCES vn.incoterms (`code`) ON DELETE RESTRICT ON UPDATE CASCADE; + UPDATE vn.invoiceOut io - JOIN vn.client c ON c.id = io.clientFk - JOIN vn.address a ON a.id = c.defaultAddressFk - SET io.customsAgentFk = a.customsAgentFk; \ No newline at end of file + JOIN vn.client c ON c.id = io.clientFk + JOIN vn.ticket t ON t.clientFk = c.id + JOIN vn.address a ON a.id = t.addressFk + SET io.customsAgentFk = a.customsAgentFk, + io.incotermsFk = a.incotermsFk; \ No newline at end of file diff --git a/print/templates/reports/invoice-incoterms/sql/incoterms.sql b/print/templates/reports/invoice-incoterms/sql/incoterms.sql index 016a8342e..535451674 100644 --- a/print/templates/reports/invoice-incoterms/sql/incoterms.sql +++ b/print/templates/reports/invoice-incoterms/sql/incoterms.sql @@ -1,9 +1,9 @@ WITH tickets AS( -SELECT id, packages, addressFk, weight - FROM ticket - WHERE refFk= ? +SELECT id, addressFk, packages, refFk + FROM vn.ticket + WHERE refFk = ? ), volume AS( -SELECT SUM(volume) volume +SELECT SUM(volume) volume, MAX(weight)weight FROM tickets t JOIN vn.saleVolume sv ON sv.ticketFk = t.id ), intrastat AS( @@ -12,10 +12,14 @@ SELECT GROUP_CONCAT(DISTINCT ir.description ORDER BY ir.description SEPARATOR ' JOIN vn.sale s ON t.id = s.ticketFk JOIN vn.item i ON i.id = s.itemFk JOIN vn.intrastat ir ON ir.id = i.intrastatFk -)SELECT SUM(t.packages) packages, - a.incotermsFk, +), totalPackages AS( +SELECT SUM(packages)packages + FROM tickets s +) +SELECT tp.packages, + io.incotermsFk, ic.name incotermsName, - MAX(t.weight) weight, + v.weight weight, ca.fiscalName customsAgentName, ca.street customsAgentStreet, ca.nif customsAgentNif, @@ -23,9 +27,10 @@ SELECT GROUP_CONCAT(DISTINCT ir.description ORDER BY ir.description SEPARATOR ' ca.email customsAgentEmail, CAST(v.volume AS DECIMAL (10,2)) volume, i.intrastat - FROM tickets t - JOIN vn.address a ON a.id = t.addressFk - JOIN vn.incoterms ic ON ic.code = a.incotermsFk - LEFT JOIN vn.customsAgent ca ON ca.id = a.customsAgentFk + FROM vn.invoiceOut io + JOIN vn.incoterms ic ON ic.code = io.incotermsFk + LEFT JOIN vn.customsAgent ca ON ca.id = io.customsAgentFk JOIN volume v JOIN intrastat i + JOIN totalPackages tp + WHERE `ref` = (SELECT DISTINCT refFk FROM tickets) \ No newline at end of file -- 2.40.1 From 31a6db5da0cc02f9062e17bb2a07f59632e1abbb Mon Sep 17 00:00:00 2001 From: sergiodt Date: Thu, 12 Dec 2024 20:30:38 +0100 Subject: [PATCH 06/39] feat: refs #7569 refs#7569 sendMail --- loopback/locale/en.json | 8 +-- loopback/locale/es.json | 13 ++--- loopback/locale/fr.json | 12 +++-- loopback/locale/pt.json | 6 ++- .../ticket/back/methods/ticket/saveSign.js | 52 ++++++++++++++++++- .../methods/ticket/specs/saveSign.spec.js | 42 +++++++++++++++ 6 files changed, 116 insertions(+), 17 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 7372ac9a6..f5c27726b 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -246,6 +246,8 @@ "ticketLostExpedition": "The ticket [{{ticketId}}]({{{ticketUrl}}}) has the following lost expedition:{{ expeditionId }}", "The raid information is not correct": "The raid information is not correct", "Payment method is required": "Payment method is required", - "Sales already moved": "Sales already moved", - "Holidays to past days not available": "Holidays to past days not available" -} + "Sales already moved": "Sales already moved", + "Holidays to past days not available": "Holidays to past days not available", + "Incorrect delivery order alert on route": "Incorrect delivery order alert on route: {{ route }} zone: {{ zone }}", + "Ticket has been delivered out of order": "The ticket {{ ticket }} ({{ fullUrl }}) has been delivered out of order. Tickets that have not been delivered in their route are: {{ ticketsToMail }}" +} \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 0dc8e53a8..2a93407fc 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -388,10 +388,11 @@ "You do not have permission to modify the booked field": "No tienes permisos para modificar el campo contabilizada", "ticketLostExpedition": "El ticket [{{ticketId}}]({{{ticketUrl}}}) tiene la siguiente expedición perdida:{{ expeditionId }}", "The web user's email already exists": "El correo del usuario web ya existe", - "Sales already moved": "Ya han sido transferidas", - "The raid information is not correct": "La información de la redada no es correcta", - "There are tickets to be invoiced": "Hay tickets para esta zona, borralos primero", + "Sales already moved": "Ya han sido transferidas", + "The raid information is not correct": "La información de la redada no es correcta", + "There are tickets to be invoiced": "Hay tickets para esta zona, borralos primero", "An item type with the same code already exists": "Un tipo con el mismo código ya existe", - "Holidays to past days not available": "Las vacaciones a días pasados no están disponibles" -} - + "Holidays to past days not available": "Las vacaciones a días pasados no están disponibles", + "Incorrect delivery order alert on route": "Alerta de orden de entrega incorrecta en ruta: {{ route }} zona: {{ zone }}", + "Ticket has been delivered out of order": "El ticket {{ ticket }} ({{ fullUrl }}) no ha sigo entregado en su orden. Los tickets de la ruta que no han sido entregados en su orden son: {{ ticketsToMail }}" +} \ No newline at end of file diff --git a/loopback/locale/fr.json b/loopback/locale/fr.json index 9941358be..719cbf99c 100644 --- a/loopback/locale/fr.json +++ b/loopback/locale/fr.json @@ -362,9 +362,11 @@ "The invoices have been created but the PDFs could not be generated": "La facture a été émise mais le PDF n'a pas pu être généré", "It has been invoiced but the PDF of refund not be generated": "Il a été facturé mais le PDF de remboursement n'a pas été généré", "Cannot send mail": "Impossible d'envoyer le mail", - "Original invoice not found": "Facture originale introuvable", - "The quantity claimed cannot be greater than the quantity of the line": "Le montant réclamé ne peut pas être supérieur au montant de la ligne", - "You do not have permission to modify the booked field": "Vous n'avez pas la permission de modifier le champ comptabilisé", + "Original invoice not found": "Facture originale introuvable", + "The quantity claimed cannot be greater than the quantity of the line": "Le montant réclamé ne peut pas être supérieur au montant de la ligne", + "You do not have permission to modify the booked field": "Vous n'avez pas la permission de modifier le champ comptabilisé", "ticketLostExpedition": "Le ticket [{{ticketId}}]({{{ticketUrl}}}) a l'expédition perdue suivante : {{expeditionId}}", - "The web user's email already exists": "L'email de l'internaute existe déjà" -} + "The web user's email already exists": "L'email de l'internaute existe déjà", + "Incorrect delivery order alert on route": "Alerte de bon de livraison incorrect sur l'itinéraire: {{ route }} zone : {{ zone }}", + "Ticket has been delivered out of order": "Le ticket {{ticket}} ({{fullUrl}}) a été livré hors ordre. Les tickets qui n'ont pas été livrés dans leur itinéraire sont : {{ticketsToMail}}" +} \ No newline at end of file diff --git a/loopback/locale/pt.json b/loopback/locale/pt.json index e84b30f3d..5dfad3725 100644 --- a/loopback/locale/pt.json +++ b/loopback/locale/pt.json @@ -365,5 +365,7 @@ "Cannot send mail": "Não é possível enviar o email", "The quantity claimed cannot be greater than the quantity of the line": "O valor reclamado não pode ser superior ao valor da linha", "ticketLostExpedition": "O ticket [{{ticketId}}]({{{ticketUrl}}}) tem a seguinte expedição perdida: {{expeditionId}}", - "The web user's email already exists": "O e-mail do utilizador da web já existe." -} + "The web user's email already exists": "O e-mail do utilizador da web já existe.", + "Incorrect delivery order alert on route": "Alerta de ordem de entrega incorreta na rota: {{ route }} zona: {{ zone }}", + "Ticket has been delivered out of order": "O ticket {{ ticket }} ({{ fullUrl }}) foi entregue fora de ordem. Os tickets que não foram entregues na sua rota são: {{ ticketsToMail }}" +} \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index ac2a7bc66..eeb753614 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -28,7 +28,6 @@ module.exports = Self => { verb: 'POST' } }); - Self.saveSign = async(ctx, tickets, location, signedTime, options) => { const models = Self.app.models; const myOptions = {userId: ctx.req.accessToken.userId}; @@ -111,6 +110,12 @@ module.exports = Self => { scope: { fields: ['id'] } + }, + { + relation: 'zone', + scope: { + fields: ['id', 'zoneFk,', 'name'] + } }] }, myOptions); @@ -151,6 +156,29 @@ module.exports = Self => { await Self.rawSql(`CALL vn.ticket_setState(?, ?)`, [ticketId, stateCode], myOptions); + if (stateCode == 'DELIVERED' && ticket.priority) { + const orderState = await models.State.findOne({ + where: {code: 'DELIVERED'}, + fields: ['id'] + }, myOptions); + + const ticketsToMail = await Self.rawSql(` + SELECT t.id + FROM ticket t + JOIN ticketState ts ON ts.ticketFk = t.id + JOIN state s ON s.code = ts.code + WHERE t.routeFk = ? + AND s.\`order\` < ? + AND priority <(SELECT t.priority + FROM ticket t + WHERE t.id = ?)` + , [ticket.routeFk, orderState.id, ticket.id], myOptions); + const ticketIds = ticketsToMail.map(row => row.id); + + if (ticketsToMail) + await sendMail(ctx, ticket.routeFk, ticket.id, ticket.zone().name, ticketIds); + } + if (ticket?.address()?.province()?.country()?.code != 'ES' && ticket.$cmrFk) { await models.Ticket.saveCmr(ctx, [ticketId], myOptions); externalTickets.push(ticketId); @@ -163,4 +191,26 @@ module.exports = Self => { } await models.Ticket.sendCmrEmail(ctx, externalTickets); }; + + async function sendMail(ctx, route, ticket, zoneName, ticketsToMail) { + const $t = ctx.req.__; + const url = await Self.app.models.Url.getUrl(); + const sendTo = 'repartos@verdnatura.es'; + const fullUrl = `${url}route/${route}/summary`; + const emailSubject = $t('Incorrect delivery order alert on route', { + route: route, + zone: zoneName + }); + const emailBody = $t('Ticket has been delivered out of order', { + ticket: ticket, + fullUrl: fullUrl, + ticketsToMail: ticketsToMail, + }, {escape: false}); + + await Self.app.models.Mail.create({ + receiver: sendTo, + subject: emailSubject, + body: emailBody + }); + } }; diff --git a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js index e93408973..559c413e5 100644 --- a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js +++ b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js @@ -51,4 +51,46 @@ describe('Ticket saveSign()', () => { expect(ticketTrackingAfter.name).toBe('Entregado en parte'); }); + + fit('should send an email to notify that the delivery order is not correct', async() => { + const tx = await models.Ticket.beginTransaction({}); + const ticketFk = 8; + const priority = 5; + const stateFk = 10; + const stateTicketFk = 2; + const expeditionFk = 11; + const expeditionStateFK = 2; + + let mailCountBefore; + let mailCountAfter; + spyOn(models.Dms, 'uploadFile').and.returnValue([{id: 1}]); + + const options = {transaction: tx}; + const tickets = [ticketFk]; + + const expedition = await models.Expedition.findById(expeditionFk, null, options); + expedition.updateAttribute('stateTypeFk', expeditionStateFK, options); + + const ticket = await models.Ticket.findById(ticketFk, null, options); + ticket.updateAttribute('priority', priority, options); + + const filter = {where: { + ticketFk: ticketFk, + stateFk: stateTicketFk} + }; + try { + const ticketTracking = await models.TicketTracking.findOne(filter, options); + ticketTracking.updateAttribute('stateFk', stateFk, options); + mailCountBefore = await models.Mail.count(options); + await models.Ticket.saveSign(ctx, tickets, null, null, options); + mailCountAfter = await models.Mail.count(options); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + + expect(mailCountAfter).toBeGreaterThan(mailCountBefore); + }); }); -- 2.40.1 From 2c672951c6428f27958ee850f11093db08748c5e Mon Sep 17 00:00:00 2001 From: sergiodt Date: Thu, 12 Dec 2024 20:33:00 +0100 Subject: [PATCH 07/39] fix: refs #7569 refs#8188 add IfNotExists --- modules/ticket/back/methods/ticket/saveSign.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index eeb753614..6dc90e330 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -205,7 +205,7 @@ module.exports = Self => { ticket: ticket, fullUrl: fullUrl, ticketsToMail: ticketsToMail, - }, {escape: false}); + }); await Self.app.models.Mail.create({ receiver: sendTo, -- 2.40.1 From 1d7e69cb25f809ca2d26c1fa2e90facff815cbc4 Mon Sep 17 00:00:00 2001 From: robert Date: Mon, 16 Dec 2024 07:40:49 +0100 Subject: [PATCH 08/39] feat: refs #7584 workerTimeControl_afterDelete --- .../vn/triggers/workerTimeControl_afterDelete.sql | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/db/routines/vn/triggers/workerTimeControl_afterDelete.sql b/db/routines/vn/triggers/workerTimeControl_afterDelete.sql index 27432fccb..762754591 100644 --- a/db/routines/vn/triggers/workerTimeControl_afterDelete.sql +++ b/db/routines/vn/triggers/workerTimeControl_afterDelete.sql @@ -3,10 +3,12 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerTimeControl_after AFTER DELETE ON `workerTimeControl` FOR EACH ROW BEGIN - INSERT INTO workerLog - SET `action` = 'delete', - `changedModel` = 'WorkerTimeControl', - `changedModelId` = OLD.id, - `userFk` = account.myUser_getId(); + IF account.myUser_getId() THEN + INSERT INTO workerLog + SET `action` = 'delete', + `changedModel` = 'WorkerTimeControl', + `changedModelId` = OLD.id, + `userFk` = account.myUser_getId(); + END IF; END$$ DELIMITER ; -- 2.40.1 From 1ba23ad45057893a6612a62e1844025c0b353657 Mon Sep 17 00:00:00 2001 From: ivanm Date: Wed, 18 Dec 2024 13:27:43 +0100 Subject: [PATCH 09/39] feat: refs #8073 #refs 8073 create vn.productionCountryVolume --- db/versions/11387-whiteDendro/00-firstScript.sql | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 db/versions/11387-whiteDendro/00-firstScript.sql diff --git a/db/versions/11387-whiteDendro/00-firstScript.sql b/db/versions/11387-whiteDendro/00-firstScript.sql new file mode 100644 index 000000000..4461b945d --- /dev/null +++ b/db/versions/11387-whiteDendro/00-firstScript.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS vn.productionCountryVolume( + id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, + countryFk MEDIUMINT(8) UNSIGNED NOT NULL, + estimate DECIMAL(6, 2), + PRIMARY KEY (id), + CONSTRAINT productionCountryVolume_countryFK + FOREIGN KEY (countryFk) REFERENCES vn.country (id) + ON DELETE RESTRICT ON UPDATE CASCADE +) COMMENT = 'Estimación del crecimiento por país' \ No newline at end of file -- 2.40.1 From 148ab57b1a1cf0bc4d42f999a039951ace7c41a8 Mon Sep 17 00:00:00 2001 From: ivanm Date: Wed, 18 Dec 2024 15:06:49 +0100 Subject: [PATCH 10/39] feat: refs #8073 change names and primary key --- db/versions/11387-whiteDendro/00-firstScript.sql | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/db/versions/11387-whiteDendro/00-firstScript.sql b/db/versions/11387-whiteDendro/00-firstScript.sql index 4461b945d..3226dfc42 100644 --- a/db/versions/11387-whiteDendro/00-firstScript.sql +++ b/db/versions/11387-whiteDendro/00-firstScript.sql @@ -1,8 +1,7 @@ -CREATE TABLE IF NOT EXISTS vn.productionCountryVolume( - id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, +CREATE TABLE IF NOT EXISTS vn.productionCountry( countryFk MEDIUMINT(8) UNSIGNED NOT NULL, - estimate DECIMAL(6, 2), - PRIMARY KEY (id), + volumeGrowthEstimatePercent DECIMAL(6, 2), + PRIMARY KEY (countryFk), CONSTRAINT productionCountryVolume_countryFK FOREIGN KEY (countryFk) REFERENCES vn.country (id) ON DELETE RESTRICT ON UPDATE CASCADE -- 2.40.1 From c59cae9f74fbe65d14badde2fc40e82660573a1c Mon Sep 17 00:00:00 2001 From: ivanm Date: Thu, 19 Dec 2024 14:38:28 +0100 Subject: [PATCH 11/39] feat: refs #8073 new comment message --- db/versions/11387-whiteDendro/00-firstScript.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/db/versions/11387-whiteDendro/00-firstScript.sql b/db/versions/11387-whiteDendro/00-firstScript.sql index 3226dfc42..4e9f1d217 100644 --- a/db/versions/11387-whiteDendro/00-firstScript.sql +++ b/db/versions/11387-whiteDendro/00-firstScript.sql @@ -1,8 +1,8 @@ CREATE TABLE IF NOT EXISTS vn.productionCountry( countryFk MEDIUMINT(8) UNSIGNED NOT NULL, - volumeGrowthEstimatePercent DECIMAL(6, 2), + volumeGrowthEstimatePercent DECIMAL(6, 2) COMMENT 'Porcentaje estimado de crecimiento del volumen', PRIMARY KEY (countryFk), CONSTRAINT productionCountryVolume_countryFK FOREIGN KEY (countryFk) REFERENCES vn.country (id) ON DELETE RESTRICT ON UPDATE CASCADE -) COMMENT = 'Estimación del crecimiento por país' \ No newline at end of file +) COMMENT = 'Datos de producción por país' \ No newline at end of file -- 2.40.1 From 48d2d1d3271eb6d92ef8cda0979e38daed999e30 Mon Sep 17 00:00:00 2001 From: jtubau Date: Thu, 26 Dec 2024 10:41:20 +0100 Subject: [PATCH 12/39] feat: refs #8117 add worker first and last name to item type query --- modules/ticket/back/methods/ticket-request/getItemTypeWorker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js b/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js index f160cfaac..2f2a85abb 100644 --- a/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js +++ b/modules/ticket/back/methods/ticket-request/getItemTypeWorker.js @@ -30,7 +30,7 @@ module.exports = Self => { Object.assign(myOptions, options); const query = - `SELECT DISTINCT u.id, u.nickname + `SELECT DISTINCT u.id, u.nickname, w.firstName, w.lastName FROM itemType it JOIN worker w ON w.id = it.workerFk JOIN account.user u ON u.id = w.id`; -- 2.40.1 From 1f23ebf6d5a3d5528acb535dac45c87a783c352b Mon Sep 17 00:00:00 2001 From: jgallego Date: Tue, 31 Dec 2024 11:46:32 +0100 Subject: [PATCH 13/39] feat: refs #7832 implement refund ticket restrictions and add unit tests for ticket service updates --- .../back/models/specs/ticket-service.spec.js | 65 +++++++++++++++++++ modules/ticket/back/models/ticket-service.js | 11 +++- 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 modules/ticket/back/models/specs/ticket-service.spec.js diff --git a/modules/ticket/back/models/specs/ticket-service.spec.js b/modules/ticket/back/models/specs/ticket-service.spec.js new file mode 100644 index 000000000..0edd296c6 --- /dev/null +++ b/modules/ticket/back/models/specs/ticket-service.spec.js @@ -0,0 +1,65 @@ +/* eslint max-len: ["error", { "code": 150 }]*/ +const {models} = require('vn-loopback/server/server'); + +fdescribe('ticketService model ', () => { + const originalTicketFk = 1; + const refundTicketFk = 11; + + let tx; + let opts; + let ticketService; + + beforeEach(async() => { + tx = await models.Sale.beginTransaction({}); + opts = {transaction: tx}; + + ticketService = await models.TicketService.create({ + ticketFk: refundTicketFk, + description: 'test', + quantity: 1, + price: 100, + taxClassFk: 1, + ticketServiceTypeFk: 1 + }, opts); + }); + + afterEach(async() => { + await tx.rollback(); + }); + + describe('TicketService', () => { + it('should allow updating description and quantity for non-refund tickets', async() => { + await ticketService.updateAttributes({ + ticketServiceTypeFk: 2, + quantity: 5 + }, opts); + + const updated = await models.TicketService.findById(ticketService.id, null, opts); + + expect(updated.description).not.toBe('test'); + expect(updated.quantity).toBe(5); + }); + + it('should only allow updating description for refund tickets', async() => { + await models.TicketRefund.create({ + refundTicketFk, + originalTicketFk + }, opts); + + await ticketService.updateAttributes({ + ticketServiceTypeFk: 2 + }, opts); + + try { + await ticketService.updateAttributes({ + ticketServiceTypeFk: 3, + quantity: 5 + }, opts); + + fail('Should have thrown error'); + } catch (e) { + expect(e.message).toBe('Only description can be modified in refund tickets'); + } + }); + }); +}); diff --git a/modules/ticket/back/models/ticket-service.js b/modules/ticket/back/models/ticket-service.js index 209727ee4..77479498a 100644 --- a/modules/ticket/back/models/ticket-service.js +++ b/modules/ticket/back/models/ticket-service.js @@ -10,9 +10,18 @@ module.exports = Self => { const isLocked = await models.Ticket.isLocked(ticketId); if (isLocked) throw new UserError(`The current ticket can't be modified`); + + const isRefund = await models.TicketRefund.findOne({ + where: {refundTicketFk: ticketId} + }, { + transaction: ctx.options.transaction + }); + + if (isRefund && ctx.data && Object.keys(ctx.data).some(field => field !== 'ticketServiceTypeFk')) + throw new UserError('Only description can be modified in refund tickets'); } - if (changes && changes.ticketServiceTypeFk) { + if (changes?.ticketServiceTypeFk) { const ticketServiceType = await models.TicketServiceType.findById(changes.ticketServiceTypeFk); changes.description = ticketServiceType.name; } -- 2.40.1 From 0ad26b336d7a08a4a885b1d0b04947c968684a56 Mon Sep 17 00:00:00 2001 From: jgallego Date: Tue, 31 Dec 2024 11:48:05 +0100 Subject: [PATCH 14/39] fix: refs #7832 update ticketService model test suite to correct describe block --- modules/ticket/back/models/specs/ticket-service.spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/ticket/back/models/specs/ticket-service.spec.js b/modules/ticket/back/models/specs/ticket-service.spec.js index 0edd296c6..2691123eb 100644 --- a/modules/ticket/back/models/specs/ticket-service.spec.js +++ b/modules/ticket/back/models/specs/ticket-service.spec.js @@ -1,7 +1,6 @@ -/* eslint max-len: ["error", { "code": 150 }]*/ const {models} = require('vn-loopback/server/server'); -fdescribe('ticketService model ', () => { +describe('ticketService model ', () => { const originalTicketFk = 1; const refundTicketFk = 11; -- 2.40.1 From 8822fde7fb194c93f284db3b9e5b7b38374a4c4a Mon Sep 17 00:00:00 2001 From: ivanm Date: Thu, 2 Jan 2025 18:04:53 +0100 Subject: [PATCH 15/39] feat: refs #7343 delete sending to user --- .../back/methods/route/driverRouteEmail.js | 21 ++++--------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/modules/route/back/methods/route/driverRouteEmail.js b/modules/route/back/methods/route/driverRouteEmail.js index bbac2b0e8..78069683d 100644 --- a/modules/route/back/methods/route/driverRouteEmail.js +++ b/modules/route/back/methods/route/driverRouteEmail.js @@ -8,7 +8,7 @@ module.exports = Self => { arg: 'id', type: 'number', required: true, - description: 'The client id', + description: 'The route id', http: {source: 'path'} }, { arg: 'replyTo', @@ -31,26 +31,13 @@ module.exports = Self => { }); Self.driverRouteEmail = async(ctx, id) => { - const models = Self.app.models; - const {workerFk, agencyMode} = await Self.findById(id, { - fields: ['workerFk', 'agencyModeFk'], + const {agencyMode} = await Self.findById(id, { + fields: ['agencyModeFk'], include: {relation: 'agencyMode'} }); const {reportMail} = agencyMode(); - let user; - let account; - - if (workerFk) { - user = await models.VnUser.findById(workerFk, { - fields: ['active', 'id'], - include: {relation: 'emailUser'} - }); - account = await models.Account.findById(workerFk); - } - - if (user?.active && account) ctx.args.recipient = user.emailUser().email; - else ctx.args.recipient = reportMail; + ctx.args.recipient = reportMail; if (!ctx.args.recipient) throw new UserError('An email is necessary'); return Self.sendTemplate(ctx, 'driver-route'); }; -- 2.40.1 From 1d8dcdf63f70534afc1c3529ef85244d9e08a608 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 7 Jan 2025 09:44:50 +0100 Subject: [PATCH 16/39] build: add new version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a843ac9c5..e4cbf1406 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "25.02.0", + "version": "25.04.0", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0", -- 2.40.1 From 73d5d508cef2567ccbcfbf7796e45ad77fcd6c8d Mon Sep 17 00:00:00 2001 From: jgallego Date: Tue, 7 Jan 2025 10:45:51 +0100 Subject: [PATCH 17/39] test: refs #8361 enhance exchangeRateUpdate specs with additional scenarios --- .../methods/invoice-in/exchangeRateUpdate.js | 134 +++++++++++----- .../specs/exchangeRateUpdate.spec.js | 148 ++++++++++++++---- 2 files changed, 217 insertions(+), 65 deletions(-) diff --git a/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js b/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js index 989b1d4a2..b5a081fc6 100644 --- a/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js +++ b/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js @@ -13,66 +13,126 @@ module.exports = Self => { } }); - Self.exchangeRateUpdate = async() => { - const response = await axios.get('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml'); - const xmlData = response.data; - - const doc = new DOMParser({errorHandler: {warning: () => {}}})?.parseFromString(xmlData, 'text/xml'); - const cubes = doc?.getElementsByTagName('Cube'); - if (!cubes || cubes.length === 0) - throw new UserError('No cubes found. Exiting the method.'); - + Self.exchangeRateUpdate = async(options = {}) => { const models = Self.app.models; + const myOptions = {}; + Object.assign(myOptions, options); - const maxDateRecord = await models.ReferenceRate.findOne({order: 'dated DESC'}); + let createdTx = false; + if (!myOptions.transaction) { + myOptions.transaction = await Self.beginTransaction({}); + createdTx = true; + } - const maxDate = maxDateRecord?.dated ? new Date(maxDateRecord.dated) : null; + try { + const response = await axios.get('http://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml'); + const xmlData = response.data; - for (const cube of Array.from(cubes)) { - if (cube.nodeType === doc.ELEMENT_NODE && cube.attributes.getNamedItem('time')) { - const xmlDate = new Date(cube.getAttribute('time')); - const xmlDateWithoutTime = new Date(xmlDate.getFullYear(), xmlDate.getMonth(), xmlDate.getDate()); - if (!maxDate || maxDate < xmlDateWithoutTime) { + const doc = new DOMParser({errorHandler: {warning: () => {}}}) + .parseFromString(xmlData, 'text/xml'); + const cubes = doc?.getElementsByTagName('Cube'); + if (!cubes || cubes.length === 0) + throw new UserError('No cubes found. Exiting the method.'); + + const maxDateRecord = await models.ReferenceRate.findOne({order: 'dated DESC'}, myOptions); + const maxDate = maxDateRecord?.dated ? new Date(maxDateRecord.dated) : null; + let lastProcessedDate = maxDate; + + for (const cube of Array.from(cubes)) { + if (cube.nodeType === doc.ELEMENT_NODE && cube.attributes.getNamedItem('time')) { + const xmlDate = new Date(cube.getAttribute('time')); + const xmlDateWithoutTime = new Date( + xmlDate.getFullYear(), + xmlDate.getMonth(), + xmlDate.getDate() + ); + + if (!maxDate || xmlDateWithoutTime > maxDate) { + if (lastProcessedDate && xmlDateWithoutTime > lastProcessedDate) { + for (const code of ['USD', 'CNY', 'GBP']) { + const currency = await models.Currency.findOne( + {where: {code}}, + myOptions + ); + if (!currency) + throw new UserError(`Currency not found for code: ${code}`); + + await fillMissingDates( + models, currency, lastProcessedDate, xmlDateWithoutTime, myOptions + ); + } + } + } for (const rateCube of Array.from(cube.childNodes)) { if (rateCube.nodeType === doc.ELEMENT_NODE) { const currencyCode = rateCube.getAttribute('currency'); const rate = rateCube.getAttribute('rate'); if (['USD', 'CNY', 'GBP'].includes(currencyCode)) { - const currency = await models.Currency.findOne({where: {code: currencyCode}}); - if (!currency) throw new UserError(`Currency not found for code: ${currencyCode}`); + const currency = await models.Currency.findOne( + {where: {code: currencyCode}}, + myOptions + ); + if (!currency) + throw new UserError(`Currency not found for code: ${currencyCode}`); + const existingRate = await models.ReferenceRate.findOne({ - where: {currencyFk: currency.id, dated: xmlDate} - }); + where: {currencyFk: currency.id, dated: xmlDateWithoutTime} + }, myOptions); if (existingRate) { if (existingRate.value !== rate) - await existingRate.updateAttributes({value: rate}); + await existingRate.updateAttributes({value: rate}, myOptions); } else { await models.ReferenceRate.create({ currencyFk: currency.id, - dated: xmlDate, + dated: xmlDateWithoutTime, value: rate - }); - } - const monday = 1; - if (xmlDateWithoutTime.getDay() === monday) { - const saturday = new Date(xmlDateWithoutTime); - saturday.setDate(xmlDateWithoutTime.getDate() - 2); - const sunday = new Date(xmlDateWithoutTime); - sunday.setDate(xmlDateWithoutTime.getDate() - 1); - - for (const date of [saturday, sunday]) { - await models.ReferenceRate.upsertWithWhere( - {currencyFk: currency.id, dated: date}, - {currencyFk: currency.id, dated: date, value: rate} - ); - } + }, myOptions); } } } } + + lastProcessedDate = xmlDateWithoutTime; } } + + if (createdTx) + await myOptions.transaction.commit(); + } catch (error) { + if (createdTx) + await myOptions.transaction.rollback(); + + throw error; } }; + + async function getLastValidRate(models, currencyId, date, myOptions) { + return models.ReferenceRate.findOne({ + where: {currencyFk: currencyId, dated: {lt: date}}, + order: 'dated DESC' + }, myOptions); + } + + async function fillMissingDates(models, currency, startDate, endDate, myOptions) { + const cursor = new Date(startDate); + cursor.setDate(cursor.getDate() + 1); + while (cursor < endDate) { + const existingRate = await models.ReferenceRate.findOne({ + where: {currencyFk: currency.id, dated: cursor} + }, myOptions); + + if (!existingRate) { + const lastValid = await getLastValidRate(models, currency.id, cursor, myOptions); + if (lastValid) { + await models.ReferenceRate.create({ + currencyFk: currency.id, + dated: new Date(cursor), + value: lastValid.value + }, myOptions); + } + } + cursor.setDate(cursor.getDate() + 1); + } + } }; diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js index 0fd7ea165..70e7dbad7 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js @@ -1,52 +1,144 @@ describe('exchangeRateUpdate functionality', function() { const axios = require('axios'); const models = require('vn-loopback/server/server').models; + let tx; let options; - beforeEach(function() { - spyOn(axios, 'get').and.returnValue(Promise.resolve({ - data: ` - - - - - ` - })); + function formatYmd(d) { + const mm = (d.getMonth() + 1).toString().padStart(2, '0'); + const dd = d.getDate().toString().padStart(2, '0'); + return `${d.getFullYear()}-${mm}-${dd}`; + } + + afterEach(async() => { + await tx.rollback(); }); - it('should process XML data and update or create rates in the database', async function() { + beforeEach(async() => { + tx = await models.Sale.beginTransaction({}); + options = {transaction: tx}; + spyOn(axios, 'get').and.returnValue(Promise.resolve({data: ''})); + }); + + it('should process XML data and create rates', async function() { + const d1 = Date.vnNew(); + const d4 = Date.vnNew(); + d4.setDate(d4.getDate() + 1); + const xml = ` + + + + + + + + `; + axios.get.and.returnValue(Promise.resolve({data: xml})); spyOn(models.ReferenceRate, 'findOne').and.returnValue(Promise.resolve(null)); spyOn(models.ReferenceRate, 'create').and.returnValue(Promise.resolve()); + await models.InvoiceIn.exchangeRateUpdate(options); - await models.InvoiceIn.exchangeRateUpdate(); - - expect(models.ReferenceRate.create).toHaveBeenCalledTimes(2); + expect(models.ReferenceRate.create).toHaveBeenCalledTimes(3); }); - it('should not create or update rates when no XML data is available', async function() { + it('should handle no data', async function() { axios.get.and.returnValue(Promise.resolve({})); spyOn(models.ReferenceRate, 'create'); - - let thrownError = null; + let e; try { - await models.InvoiceIn.exchangeRateUpdate(); - } catch (error) { - thrownError = error; + await models.InvoiceIn.exchangeRateUpdate(options); + } catch (err) { + e = err; } - expect(thrownError.message).toBe('No cubes found. Exiting the method.'); + expect(e.message).toBe('No cubes found. Exiting the method.'); + expect(models.ReferenceRate.create).not.toHaveBeenCalled(); }); - it('should handle errors gracefully', async function() { + it('should handle errors', async function() { axios.get.and.returnValue(Promise.reject(new Error('Network error'))); - let error; - + let e; try { - await models.InvoiceIn.exchangeRateUpdate(); - } catch (e) { - error = e; + await models.InvoiceIn.exchangeRateUpdate(options); + } catch (err) { + e = err; } - expect(error).toBeDefined(); - expect(error.message).toBe('Network error'); + expect(e).toBeDefined(); + expect(e.message).toBe('Network error'); + }); + + it('should update existing rate', async function() { + const existingRate = await models.ReferenceRate.findOne({ + order: 'id DESC' + }, options); + + if (!existingRate) return fail('No ReferenceRate records in DB'); + + const currency = await models.Currency.findById(existingRate.currencyFk, null, options); + + const xml = ` + + + + `; + + axios.get.and.returnValue(Promise.resolve({data: xml})); + + await models.InvoiceIn.exchangeRateUpdate(options); + + const updatedRate = await models.ReferenceRate.findById(existingRate.id, null, options); + + expect(updatedRate.value).toBeCloseTo('2.22'); + }); + + it('should not update if same rate', async function() { + const existingRate = await models.ReferenceRate.findOne({order: 'id DESC'}, options); + if (!existingRate) return fail('No existing ReferenceRate in DB'); + + const currency = await models.Currency.findById(existingRate.currencyFk, null, options); + + const oldValue = existingRate.value; + const xml = ` + + + + `; + + axios.get.and.returnValue(Promise.resolve({data: xml})); + + await models.InvoiceIn.exchangeRateUpdate(options); + + const updatedRate = await models.ReferenceRate.findById(existingRate.id, null, options); + + expect(updatedRate.value).toBe(oldValue); + }); + + it('should backfill missing dates', async function() { + const lastRate = await models.ReferenceRate.findOne({order: 'dated DESC'}, options); + if (!lastRate) return fail('No existing ReferenceRate data in DB'); + + const currency = await models.Currency.findById(lastRate.currencyFk, null, options); + + const d1 = new Date(lastRate.dated); + d1.setDate(d1.getDate() + 1); + const d4 = new Date(lastRate.dated); + d4.setDate(d4.getDate() + 4); + + const xml = ` + + + + + + + `; + + axios.get.and.returnValue(Promise.resolve({data: xml})); + + const beforeCount = await models.ReferenceRate.count({}, options); + await models.InvoiceIn.exchangeRateUpdate(options); + const afterCount = await models.ReferenceRate.count({}, options); + + expect(afterCount - beforeCount).toBe(4); }); }); -- 2.40.1 From 786f1fe661a40204831fb8942a7f1734d9e86322 Mon Sep 17 00:00:00 2001 From: jgallego Date: Tue, 7 Jan 2025 11:06:09 +0100 Subject: [PATCH 18/39] test: refs #8361 enhance exchangeRateUpdate specs to validate day1 and day2 entries without backfilling day3 --- .../specs/exchangeRateUpdate.spec.js | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js index 70e7dbad7..4b53f65c6 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js @@ -141,4 +141,50 @@ describe('exchangeRateUpdate functionality', function() { expect(afterCount - beforeCount).toBe(4); }); + + fit('should create entries for day1 and day2 from the feed, and not backfill day3', async function() { + const lastRate = await models.ReferenceRate.findOne({order: 'dated DESC'}, options); + if (!lastRate) return fail('No existing ReferenceRate data in DB'); + + const currency = await models.Currency.findById(lastRate.currencyFk, null, options); + if (!currency) return fail(`No currency for ID ${lastRate.currencyFk}`); + + const day1 = new Date(lastRate.dated); + day1.setDate(day1.getDate() + 1); + + const day2 = new Date(lastRate.dated); + day2.setDate(day2.getDate() + 2); + + const day3 = new Date(lastRate.dated); + day3.setDate(day3.getDate() + 3); + + const xml = ` + + + + + + + `; + + axios.get.and.returnValue(Promise.resolve({data: xml})); + + await models.InvoiceIn.exchangeRateUpdate(options); + + const day3Record = await models.ReferenceRate.findOne({ + where: {currencyFk: currency.id, dated: day3} + }, options); + + expect(day3Record).toBeNull(); + + const day1Record = await models.ReferenceRate.findOne({ + where: {currencyFk: currency.id, dated: day1} + }, options); + const day2Record = await models.ReferenceRate.findOne({ + where: {currencyFk: currency.id, dated: day2} + }, options); + + expect(day1Record.value).toBeCloseTo('1.1'); + expect(day2Record.value).toBeCloseTo('2.2'); + }); }); -- 2.40.1 From 065f13557b9265d1e0903560c05be40d91b18039 Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 7 Jan 2025 11:58:36 +0100 Subject: [PATCH 19/39] feat: refs #8357 Agregados triggers para manejar exclusiones de trabajadores en la tabla workerMana --- .../vn/triggers/workerManaExcluded_beforeInsert.sql | 9 +++++++++ .../vn/triggers/workerManaExcluded_beforeUpdate.sql | 9 +++++++++ db/routines/vn/triggers/workerMana_beforeInsert.sql | 10 ++++++++++ db/routines/vn/triggers/workerMana_beforeUpdate.sql | 10 ++++++++++ db/versions/11396-blueErica/00-firstScript.sql | 5 +++++ 5 files changed, 43 insertions(+) create mode 100644 db/routines/vn/triggers/workerManaExcluded_beforeInsert.sql create mode 100644 db/routines/vn/triggers/workerManaExcluded_beforeUpdate.sql create mode 100644 db/routines/vn/triggers/workerMana_beforeInsert.sql create mode 100644 db/routines/vn/triggers/workerMana_beforeUpdate.sql create mode 100644 db/versions/11396-blueErica/00-firstScript.sql diff --git a/db/routines/vn/triggers/workerManaExcluded_beforeInsert.sql b/db/routines/vn/triggers/workerManaExcluded_beforeInsert.sql new file mode 100644 index 000000000..824f0982b --- /dev/null +++ b/db/routines/vn/triggers/workerManaExcluded_beforeInsert.sql @@ -0,0 +1,9 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerManaExcluded_beforeInsert` + BEFORE INSERT ON `workerManaExcluded` + FOR EACH ROW +BEGIN + DELETE FROM workerMana + WHERE workerFk = NEW.workerFk; +END$$ +DELIMITER ; diff --git a/db/routines/vn/triggers/workerManaExcluded_beforeUpdate.sql b/db/routines/vn/triggers/workerManaExcluded_beforeUpdate.sql new file mode 100644 index 000000000..83d73e131 --- /dev/null +++ b/db/routines/vn/triggers/workerManaExcluded_beforeUpdate.sql @@ -0,0 +1,9 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerManaExcluded_beforeUpdate` + BEFORE UPDATE ON `workerManaExcluded` + FOR EACH ROW +BEGIN + DELETE FROM workerMana + WHERE workerFk = NEW.workerFk; +END$$ +DELIMITER ; diff --git a/db/routines/vn/triggers/workerMana_beforeInsert.sql b/db/routines/vn/triggers/workerMana_beforeInsert.sql new file mode 100644 index 000000000..2d27004e3 --- /dev/null +++ b/db/routines/vn/triggers/workerMana_beforeInsert.sql @@ -0,0 +1,10 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerMana_beforeInsert` + BEFORE INSERT ON `workerMana` + FOR EACH ROW +BEGIN + IF (SELECT EXISTS(SELECT TRUE FROM workerManaExcluded WHERE workerFk = NEW.workerFk)) THEN + CALL util.throw('Worker is excluded from mana'); + END IF; +END$$ +DELIMITER ; diff --git a/db/routines/vn/triggers/workerMana_beforeUpdate.sql b/db/routines/vn/triggers/workerMana_beforeUpdate.sql new file mode 100644 index 000000000..6916733cb --- /dev/null +++ b/db/routines/vn/triggers/workerMana_beforeUpdate.sql @@ -0,0 +1,10 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerMana_beforeUpdate` + BEFORE UPDATE ON `workerMana` + FOR EACH ROW +BEGIN + IF (SELECT EXISTS(SELECT TRUE FROM workerManaExcluded WHERE workerFk = NEW.workerFk)) THEN + CALL util.throw('Worker is excluded from mana'); + END IF; +END$$ +DELIMITER ; diff --git a/db/versions/11396-blueErica/00-firstScript.sql b/db/versions/11396-blueErica/00-firstScript.sql new file mode 100644 index 000000000..b21965fe8 --- /dev/null +++ b/db/versions/11396-blueErica/00-firstScript.sql @@ -0,0 +1,5 @@ +DELETE FROM vn.workerMana + WHERE workerFk IN ( + SELECT workerFk + FROM vn.workerManaExcluded + ); -- 2.40.1 From dbd8d816c06a6a0dc066b14baea4333f712e9a81 Mon Sep 17 00:00:00 2001 From: jgallego Date: Tue, 7 Jan 2025 14:53:26 +0100 Subject: [PATCH 20/39] fix: refs #8361 streamline transaction handling in exchangeRateUpdate --- .../methods/invoice-in/exchangeRateUpdate.js | 17 ++++++++--------- .../invoice-in/specs/exchangeRateUpdate.spec.js | 2 +- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js b/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js index b5a081fc6..a6bad405f 100644 --- a/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js +++ b/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js @@ -16,12 +16,14 @@ module.exports = Self => { Self.exchangeRateUpdate = async(options = {}) => { const models = Self.app.models; const myOptions = {}; - Object.assign(myOptions, options); + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); - let createdTx = false; if (!myOptions.transaction) { - myOptions.transaction = await Self.beginTransaction({}); - createdTx = true; + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; } try { @@ -97,12 +99,9 @@ module.exports = Self => { } } - if (createdTx) - await myOptions.transaction.commit(); + if (tx) await tx.commit(); } catch (error) { - if (createdTx) - await myOptions.transaction.rollback(); - + if (tx) await tx.rollback(); throw error; } }; diff --git a/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js b/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js index 4b53f65c6..c3dcca5ae 100644 --- a/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js +++ b/modules/invoiceIn/back/methods/invoice-in/specs/exchangeRateUpdate.spec.js @@ -142,7 +142,7 @@ describe('exchangeRateUpdate functionality', function() { expect(afterCount - beforeCount).toBe(4); }); - fit('should create entries for day1 and day2 from the feed, and not backfill day3', async function() { + it('should create entries for day1 and day2 from the feed, and not backfill day3', async function() { const lastRate = await models.ReferenceRate.findOne({order: 'dated DESC'}, options); if (!lastRate) return fail('No existing ReferenceRate data in DB'); -- 2.40.1 From 1816b6de678ff5a9254483ae33ac0c855bb9e797 Mon Sep 17 00:00:00 2001 From: jgallego Date: Wed, 8 Jan 2025 10:24:18 +0100 Subject: [PATCH 21/39] feat: refs #8298 add priceOptimum and packagesDiscountFactor to zone and client tables --- .../client_setPackagesDiscountFactor.sql | 8 ++++++ .../procedures/catalog_componentCalculate.sql | 19 +++++++++++++- .../client_setPackagesDiscountFactor.sql | 25 +++++++++++++++++++ .../procedures/zone_getOptionsForShipment.sql | 3 ++- .../00-zoneEventPriceOptimum.sql | 5 ++++ .../11398-orangeRose/00-zonePriceOptimum.sql | 5 ++++ .../11398-orangeRose/01-zoneUpdate.sql | 2 ++ .../11398-orangeRose/02-clientAlter.sql | 3 +++ .../11398-orangeRose/03-clientConfig.sql | 3 +++ loopback/locale/en.json | 3 ++- modules/zone/back/models/zone-event.json | 3 +++ modules/zone/back/models/zone.json | 3 +++ 12 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 db/routines/vn/events/client_setPackagesDiscountFactor.sql create mode 100644 db/routines/vn/procedures/client_setPackagesDiscountFactor.sql create mode 100644 db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql create mode 100644 db/versions/11398-orangeRose/00-zonePriceOptimum.sql create mode 100644 db/versions/11398-orangeRose/01-zoneUpdate.sql create mode 100644 db/versions/11398-orangeRose/02-clientAlter.sql create mode 100644 db/versions/11398-orangeRose/03-clientConfig.sql diff --git a/db/routines/vn/events/client_setPackagesDiscountFactor.sql b/db/routines/vn/events/client_setPackagesDiscountFactor.sql new file mode 100644 index 000000000..a0dc33cac --- /dev/null +++ b/db/routines/vn/events/client_setPackagesDiscountFactor.sql @@ -0,0 +1,8 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` EVENT `vn`.`client_setPackagesDiscountFactor` + ON SCHEDULE EVERY 1 DAY + STARTS '2024-10-18 03:00:00.000' + ON COMPLETION PRESERVE + ENABLE +DO CALL client_setPackagesDiscountFactor()$$ +DELIMITER ; diff --git a/db/routines/vn/procedures/catalog_componentCalculate.sql b/db/routines/vn/procedures/catalog_componentCalculate.sql index e29e13a8c..991ff412f 100644 --- a/db/routines/vn/procedures/catalog_componentCalculate.sql +++ b/db/routines/vn/procedures/catalog_componentCalculate.sql @@ -231,7 +231,23 @@ BEGIN SELECT tcc.warehouseFK, tcc.itemFk, c2.id, - z.inflation * ROUND(ic.cm3delivery * (IFNULL(zo.price,5000) - IFNULL(zo.bonus,0)) / (1000 * vc.standardFlowerBox) , 4) cost + z.inflation + * ROUND( + ic.cm3delivery + * ( + ( + zo.price + - ( + (zo.price - zo.priceOptimum) + * c.packagesDiscountFactor + ) + ) + - IFNULL(zo.bonus, 0) + ) + / (1000 * vc.standardFlowerBox), + 4 + ) cost + FROM tmp.ticketComponentCalculate tcc JOIN item i ON i.id = tcc.itemFk JOIN tmp.zoneOption zo ON zo.zoneFk = vZoneFk @@ -239,6 +255,7 @@ BEGIN JOIN agencyMode am ON am.id = z.agencyModeFk JOIN vn.volumeConfig vc JOIN vn.component c2 ON c2.code = 'delivery' + JOIN `client` c on c.id = vClientFk LEFT JOIN itemCost ic ON ic.warehouseFk = tcc.warehouseFk AND ic.itemFk = tcc.itemFk HAVING cost <> 0; diff --git a/db/routines/vn/procedures/client_setPackagesDiscountFactor.sql b/db/routines/vn/procedures/client_setPackagesDiscountFactor.sql new file mode 100644 index 000000000..f6068ca37 --- /dev/null +++ b/db/routines/vn/procedures/client_setPackagesDiscountFactor.sql @@ -0,0 +1,25 @@ +DELIMITER $$ + +CREATE OR REPLACE DEFINER=`vn`@`localhost` +PROCEDURE `vn`.`client_setPackagesDiscountFactor`() +BEGIN + /** + * Set the discount factor for the packages of the clients. + */ + UPDATE client c + JOIN ( + SELECT t.clientFk, + LEAST(( + SUM(t.packages) / COUNT(DISTINCT DATE(t.shipped)) + ) / cc.packagesOptimum, 1) discountFactor + FROM ticket t + JOIN clientConfig cc ON TRUE + WHERE t.shipped > util.VN_CURDATE() - INTERVAL cc.monthsToCalcOptimumPrice MONTH + AND t.packages + GROUP BY t.clientFk + ) ca ON c.id = ca.clientFk + SET c.packagesDiscountFactor = ca.discountFactor; + +END$$ + +DELIMITER ; diff --git a/db/routines/vn/procedures/zone_getOptionsForShipment.sql b/db/routines/vn/procedures/zone_getOptionsForShipment.sql index fa48b0b0f..17d1b3d11 100644 --- a/db/routines/vn/procedures/zone_getOptionsForShipment.sql +++ b/db/routines/vn/procedures/zone_getOptionsForShipment.sql @@ -9,7 +9,7 @@ BEGIN * @return tmp.zoneOption(zoneFk, hour, travelingDays, price, bonus, specificity) The computed options */ DECLARE vHour TIME DEFAULT TIME(util.VN_NOW()); - + DROP TEMPORARY TABLE IF EXISTS tLandings; CREATE TEMPORARY TABLE tLandings (INDEX (eventFk)) @@ -30,6 +30,7 @@ BEGIN TIME(IFNULL(e.`hour`, z.`hour`)) `hour`, l.travelingDays, IFNULL(e.price, z.price) price, + IFNULL(e.priceOptimum, z.priceOptimum) priceOptimum, IFNULL(e.bonus, z.bonus) bonus, l.landed, vShipped shipped diff --git a/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql b/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql new file mode 100644 index 000000000..8f08eb3e7 --- /dev/null +++ b/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql @@ -0,0 +1,5 @@ +ALTER TABLE `vn`.`zoneEvent` + ADD COLUMN `priceOptimum` DECIMAL(10,2) NOT NULL COMMENT 'Precio mínimo que puede pagar un bulto' + AFTER `price`, + ADD CONSTRAINT `ck_zoneEvent_priceOptimum` + CHECK (priceOptimum <= price) diff --git a/db/versions/11398-orangeRose/00-zonePriceOptimum.sql b/db/versions/11398-orangeRose/00-zonePriceOptimum.sql new file mode 100644 index 000000000..82b2001cd --- /dev/null +++ b/db/versions/11398-orangeRose/00-zonePriceOptimum.sql @@ -0,0 +1,5 @@ +ALTER TABLE `vn`.`zone` + ADD COLUMN `priceOptimum` DECIMAL(10,2) NOT NULL COMMENT 'Precio mínimo que puede pagar un bulto' + AFTER `price`, + ADD CONSTRAINT `ck_zone_priceOptimum` + CHECK (priceOptimum <= price) diff --git a/db/versions/11398-orangeRose/01-zoneUpdate.sql b/db/versions/11398-orangeRose/01-zoneUpdate.sql new file mode 100644 index 000000000..042f2a92b --- /dev/null +++ b/db/versions/11398-orangeRose/01-zoneUpdate.sql @@ -0,0 +1,2 @@ +UPDATE `vn`.`zone` + SET `priceOptimum` = `price`; diff --git a/db/versions/11398-orangeRose/02-clientAlter.sql b/db/versions/11398-orangeRose/02-clientAlter.sql new file mode 100644 index 000000000..4119f05ff --- /dev/null +++ b/db/versions/11398-orangeRose/02-clientAlter.sql @@ -0,0 +1,3 @@ +ALTER TABLE `vn`.`client` + ADD COLUMN `packagesDiscountFactor` DECIMAL(4,3) NOT NULL DEFAULT 1.000 + COMMENT 'Factor (1-0) que pondera el precio final entre priceOptimum (mejor) y price (peor)'; diff --git a/db/versions/11398-orangeRose/03-clientConfig.sql b/db/versions/11398-orangeRose/03-clientConfig.sql new file mode 100644 index 000000000..2869f26a2 --- /dev/null +++ b/db/versions/11398-orangeRose/03-clientConfig.sql @@ -0,0 +1,3 @@ +ALTER TABLE `vn`.`clientConfig` + ADD COLUMN `packagesOptimum` INT UNSIGNED NOT NULL DEFAULT 20 COMMENT 'Numero de bultos por cliente/dia para conseguir el precio optimo', + ADD COLUMN `monthsToCalcOptimumPrice` TINYINT UNSIGNED NOT NULL DEFAULT 3 COMMENT 'Número de meses a usar para el cálculo de client.packagesDiscountFactor'; diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 80da13ae5..72346a364 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -250,5 +250,6 @@ "Holidays to past days not available": "Holidays to past days not available", "Price cannot be blank": "Price cannot be blank", "There are tickets to be invoiced": "There are tickets to be invoiced", - "The address of the customer must have information about Incoterms and Customs Agent": "The address of the customer must have information about Incoterms and Customs Agent" + "The address of the customer must have information about Incoterms and Customs Agent": "The address of the customer must have information about Incoterms and Customs Agent", + "CONSTRAINT `ck_zoneEvent_priceOptimum` failed for `vn`.`zoneEvent`": "CONSTRAINT `ck_zoneEvent_priceOptimum` failed for `vn`.`zoneEvent`" } \ No newline at end of file diff --git a/modules/zone/back/models/zone-event.json b/modules/zone/back/models/zone-event.json index 366bdec9d..cf5045a8c 100644 --- a/modules/zone/back/models/zone-event.json +++ b/modules/zone/back/models/zone-event.json @@ -42,6 +42,9 @@ "price": { "type": "number" }, + "priceOptimum": { + "type": "number" + }, "bonus": { "type": "number" }, diff --git a/modules/zone/back/models/zone.json b/modules/zone/back/models/zone.json index 141b28750..4f963568f 100644 --- a/modules/zone/back/models/zone.json +++ b/modules/zone/back/models/zone.json @@ -28,6 +28,9 @@ "price": { "type": "number" }, + "priceOptimum": { + "type": "number" + }, "bonus": { "type": "number" }, -- 2.40.1 From 0d822d03c929094e6f685a4fb05cee51ead9db79 Mon Sep 17 00:00:00 2001 From: jgallego Date: Wed, 8 Jan 2025 10:30:47 +0100 Subject: [PATCH 22/39] fix: refs #8298 remove duplicate entry in English locale file --- loopback/locale/en.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 72346a364..2e25408c6 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -250,6 +250,5 @@ "Holidays to past days not available": "Holidays to past days not available", "Price cannot be blank": "Price cannot be blank", "There are tickets to be invoiced": "There are tickets to be invoiced", - "The address of the customer must have information about Incoterms and Customs Agent": "The address of the customer must have information about Incoterms and Customs Agent", - "CONSTRAINT `ck_zoneEvent_priceOptimum` failed for `vn`.`zoneEvent`": "CONSTRAINT `ck_zoneEvent_priceOptimum` failed for `vn`.`zoneEvent`" -} \ No newline at end of file + "The address of the customer must have information about Incoterms and Customs Agent": "The address of the customer must have information about Incoterms and Customs Agent" +} -- 2.40.1 From be5631370649bc90bf6c4b059bc1082f403494e9 Mon Sep 17 00:00:00 2001 From: jgallego Date: Wed, 8 Jan 2025 11:58:50 +0100 Subject: [PATCH 23/39] feat: refs #8298 add priceOptimum column to zoneEvent and update zone fixture data --- db/dump/fixtures.before.sql | 32 +++++++++---------- .../00-zoneEventPriceOptimum.sql | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index ff896b84d..9e46e3c2e 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -694,22 +694,22 @@ INSERT INTO `vn`.`invoiceOutExpense`(`id`, `invoiceOutFk`, `amount`, `expenseFk` (6, 4, 8.07, 2000000000, util.VN_CURDATE()), (7, 5, 8.07, 2000000000, util.VN_CURDATE()); -INSERT INTO `vn`.`zone` (`id`, `name`, `hour`, `agencyModeFk`, `travelingDays`, `price`, `bonus`, `itemMaxSize`) - VALUES - (1, 'Zone pickup A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100), - (2, 'Zone pickup B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100), - (3, 'Zone 247 A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 7, 1, 2, 0, 100), - (4, 'Zone 247 B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 7, 1, 2, 0, 100), - (5, 'Zone expensive A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 8, 1, 1000, 0, 100), - (6, 'Zone expensive B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 8, 1, 1000, 0, 100), - (7, 'Zone refund', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 23, 0, 1, 0, 100), - (8, 'Zone others', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 10, 0, 1, 0, 100), - (9, 'Zone superMan', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 2, 0, 1, 0, 100), - (10, 'Zone teleportation', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 3, 0, 1, 0, 100), - (11, 'Zone pickup C', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100), - (12, 'Zone entanglement', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 4, 0, 1, 0, 100), - (13, 'Zone quantum break', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 5, 0, 1, 0, 100); - +INSERT INTO `vn`.`zone` + (`id`, `name`, `hour`, `agencyModeFk`, `travelingDays`, `price`, `bonus`, `itemMaxSize`, `priceOptimum`) +VALUES + (1, 'Zone pickup A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100, 1), + (2, 'Zone pickup B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100, 1), + (3, 'Zone 247 A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 7, 1, 2, 0, 100, 1), + (4, 'Zone 247 B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 7, 1, 2, 0, 100, 1), + (5, 'Zone expensive A', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 8, 1, 1000, 0, 100, 500), + (6, 'Zone expensive B', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 8, 1, 1000, 0, 100, 500), + (7, 'Zone refund', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 23, 0, 1, 0, 100, 0.5), + (8, 'Zone others', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 10, 0, 1, 0, 100, 0.5), + (9, 'Zone superMan', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 2, 0, 1, 0, 100, 0.5), + (10, 'Zone teleportation', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 3, 0, 1, 0, 100, 0.5), + (11, 'Zone pickup C', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 1, 0, 1, 0, 100, 0.5), + (12, 'Zone entanglement', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 4, 0, 1, 0, 100, 0.5), + (13, 'Zone quantum break', CONCAT(util.VN_CURDATE(), ' ', TIME('23:59')), 5, 0, 1, 0, 100, 0.5); INSERT INTO `vn`.`zoneWarehouse` (`id`, `zoneFk`, `warehouseFk`) VALUES diff --git a/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql b/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql index 8f08eb3e7..0440714e4 100644 --- a/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql +++ b/db/versions/11398-orangeRose/00-zoneEventPriceOptimum.sql @@ -1,5 +1,5 @@ ALTER TABLE `vn`.`zoneEvent` - ADD COLUMN `priceOptimum` DECIMAL(10,2) NOT NULL COMMENT 'Precio mínimo que puede pagar un bulto' + ADD COLUMN `priceOptimum` DECIMAL(10,2) NULL COMMENT 'Precio mínimo que puede pagar un bulto' AFTER `price`, ADD CONSTRAINT `ck_zoneEvent_priceOptimum` CHECK (priceOptimum <= price) -- 2.40.1 From 12fa87a93cbb53f7ce95b9cc257f522ff010fdbf Mon Sep 17 00:00:00 2001 From: sergiodt Date: Thu, 9 Jan 2025 16:15:29 +0100 Subject: [PATCH 24/39] =?UTF-8?q?fix:=20refs=20#7569=20refs=C2=B76861=20ti?= =?UTF-8?q?cketOrderReserve?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- loopback/locale/en.json | 2 +- loopback/locale/es.json | 2 +- loopback/locale/fr.json | 2 +- modules/ticket/back/methods/ticket/saveSign.js | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index f5c27726b..0f53cf572 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -249,5 +249,5 @@ "Sales already moved": "Sales already moved", "Holidays to past days not available": "Holidays to past days not available", "Incorrect delivery order alert on route": "Incorrect delivery order alert on route: {{ route }} zone: {{ zone }}", - "Ticket has been delivered out of order": "The ticket {{ ticket }} ({{ fullUrl }}) has been delivered out of order. Tickets that have not been delivered in their route are: {{ ticketsToMail }}" + "Ticket has been delivered out of order": "The ticket {{ticket}} {{{fullUrl}}} has been delivered out of order. Tickets that have not been delivered in their route are: {{ ticketsToMail }}" } \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 2a93407fc..163fbaa71 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -394,5 +394,5 @@ "An item type with the same code already exists": "Un tipo con el mismo código ya existe", "Holidays to past days not available": "Las vacaciones a días pasados no están disponibles", "Incorrect delivery order alert on route": "Alerta de orden de entrega incorrecta en ruta: {{ route }} zona: {{ zone }}", - "Ticket has been delivered out of order": "El ticket {{ ticket }} ({{ fullUrl }}) no ha sigo entregado en su orden. Los tickets de la ruta que no han sido entregados en su orden son: {{ ticketsToMail }}" + "Ticket has been delivered out of order": "El ticket {{ticket}} {{{fullUrl}}} no ha sigo entregado en su orden. Los tickets de la ruta que no han sido entregados en su orden son: {{ ticketsToMail }}" } \ No newline at end of file diff --git a/loopback/locale/fr.json b/loopback/locale/fr.json index 719cbf99c..082aedd2b 100644 --- a/loopback/locale/fr.json +++ b/loopback/locale/fr.json @@ -368,5 +368,5 @@ "ticketLostExpedition": "Le ticket [{{ticketId}}]({{{ticketUrl}}}) a l'expédition perdue suivante : {{expeditionId}}", "The web user's email already exists": "L'email de l'internaute existe déjà", "Incorrect delivery order alert on route": "Alerte de bon de livraison incorrect sur l'itinéraire: {{ route }} zone : {{ zone }}", - "Ticket has been delivered out of order": "Le ticket {{ticket}} ({{fullUrl}}) a été livré hors ordre. Les tickets qui n'ont pas été livrés dans leur itinéraire sont : {{ticketsToMail}}" + "Ticket has been delivered out of order": "Le ticket {{ticket}} {{{fullUrl}}} a été livré hors ordre. Les tickets qui n'ont pas été livrés dans leur itinéraire sont : {{ticketsToMail}}" } \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 6dc90e330..443b2c1c7 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -198,13 +198,13 @@ module.exports = Self => { const sendTo = 'repartos@verdnatura.es'; const fullUrl = `${url}route/${route}/summary`; const emailSubject = $t('Incorrect delivery order alert on route', { - route: route, + route, zone: zoneName }); const emailBody = $t('Ticket has been delivered out of order', { - ticket: ticket, - fullUrl: fullUrl, - ticketsToMail: ticketsToMail, + ticket, + fullUrl, + ticketsToMail, }); await Self.app.models.Mail.create({ -- 2.40.1 From a1e1d4fa72fd906a65659fbfb3425fd683c25652 Mon Sep 17 00:00:00 2001 From: sergiodt Date: Fri, 10 Jan 2025 07:20:24 +0100 Subject: [PATCH 25/39] =?UTF-8?q?fix:=20refs=20#7569=20refs=C2=B76861=20ti?= =?UTF-8?q?cketOrderReserve?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- loopback/locale/pt.json | 2 +- modules/ticket/back/methods/ticket/specs/saveSign.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/loopback/locale/pt.json b/loopback/locale/pt.json index 5dfad3725..1fa16074f 100644 --- a/loopback/locale/pt.json +++ b/loopback/locale/pt.json @@ -367,5 +367,5 @@ "ticketLostExpedition": "O ticket [{{ticketId}}]({{{ticketUrl}}}) tem a seguinte expedição perdida: {{expeditionId}}", "The web user's email already exists": "O e-mail do utilizador da web já existe.", "Incorrect delivery order alert on route": "Alerta de ordem de entrega incorreta na rota: {{ route }} zona: {{ zone }}", - "Ticket has been delivered out of order": "O ticket {{ ticket }} ({{ fullUrl }}) foi entregue fora de ordem. Os tickets que não foram entregues na sua rota são: {{ ticketsToMail }}" + "Ticket has been delivered out of order": "O ticket {{ticket}} {{{fullUrl}}} foi entregue fora de ordem. Os tickets que não foram entregues na sua rota são: {{ ticketsToMail }}" } \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js index 559c413e5..ed802e311 100644 --- a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js +++ b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js @@ -52,7 +52,7 @@ describe('Ticket saveSign()', () => { expect(ticketTrackingAfter.name).toBe('Entregado en parte'); }); - fit('should send an email to notify that the delivery order is not correct', async() => { + it('should send an email to notify that the delivery order is not correct', async() => { const tx = await models.Ticket.beginTransaction({}); const ticketFk = 8; const priority = 5; -- 2.40.1 From bdaaffbbd76247d2eaf64635c58fbd8e707bff2b Mon Sep 17 00:00:00 2001 From: robert Date: Fri, 10 Jan 2025 10:33:19 +0100 Subject: [PATCH 26/39] feat: refs #7584 changes request --- db/routines/vn/triggers/workerTimeControl_afterDelete.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/routines/vn/triggers/workerTimeControl_afterDelete.sql b/db/routines/vn/triggers/workerTimeControl_afterDelete.sql index 762754591..96db381b5 100644 --- a/db/routines/vn/triggers/workerTimeControl_afterDelete.sql +++ b/db/routines/vn/triggers/workerTimeControl_afterDelete.sql @@ -3,7 +3,7 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`workerTimeControl_after AFTER DELETE ON `workerTimeControl` FOR EACH ROW BEGIN - IF account.myUser_getId() THEN + IF account.myUser_getId() IS NOT NULL THEN INSERT INTO workerLog SET `action` = 'delete', `changedModel` = 'WorkerTimeControl', -- 2.40.1 From c15a3bfe501f46159e3868ddfb8a90ac7c493527 Mon Sep 17 00:00:00 2001 From: jgallego Date: Mon, 13 Jan 2025 11:28:30 +0100 Subject: [PATCH 27/39] feat: refs #8381 add initial and final temperature fields to entry model and queries --- db/versions/11405-blackMoss/00-entryAlter.sql | 3 +++ modules/entry/back/methods/entry/filter.js | 16 ++++++++++++++++ modules/entry/back/models/entry.json | 6 ++++++ modules/travel/back/methods/travel/getEntries.js | 4 +++- 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 db/versions/11405-blackMoss/00-entryAlter.sql diff --git a/db/versions/11405-blackMoss/00-entryAlter.sql b/db/versions/11405-blackMoss/00-entryAlter.sql new file mode 100644 index 000000000..3320b9dd3 --- /dev/null +++ b/db/versions/11405-blackMoss/00-entryAlter.sql @@ -0,0 +1,3 @@ +ALTER TABLE `vn`.`entry` + ADD COLUMN `initialTemperature` decimal(10,2) DEFAULT NULL COMMENT 'Temperatura de como lo recibimos del proveedor ej. en colombia', + ADD COLUMN `finalTemperature` decimal(10,2) DEFAULT NULL COMMENT 'Temperatura final de como llega a nuestras instalaciones'; diff --git a/modules/entry/back/methods/entry/filter.js b/modules/entry/back/methods/entry/filter.js index d7740dd4e..e5eae85fd 100644 --- a/modules/entry/back/methods/entry/filter.js +++ b/modules/entry/back/methods/entry/filter.js @@ -119,6 +119,16 @@ module.exports = Self => { arg: 'invoiceAmount', type: 'number', description: `The invoice amount` + }, + { + arg: 'initialTemperature', + type: 'number', + description: 'Initial temperature value' + }, + { + arg: 'finalTemperature', + type: 'number', + description: 'Final temperature value' } ], returns: { @@ -170,6 +180,10 @@ module.exports = Self => { case 'invoiceInFk': param = `e.${param}`; return {[param]: value}; + case 'initialTemperature': + return {'e.initialTemperature': {lte: value}}; + case 'finalTemperature': + return {'e.finalTemperature': {gte: value}}; } }); filter = mergeFilters(ctx.args.filter, {where}); @@ -204,6 +218,8 @@ module.exports = Self => { e.gestDocFk, e.invoiceInFk, e.invoiceAmount, + e.initialTemperature, + e.finalTemperature, t.landed, s.name supplierName, s.nickname supplierAlias, diff --git a/modules/entry/back/models/entry.json b/modules/entry/back/models/entry.json index 4a09c7d6a..1ff062119 100644 --- a/modules/entry/back/models/entry.json +++ b/modules/entry/back/models/entry.json @@ -68,6 +68,12 @@ }, "invoiceAmount": { "type": "number" + }, + "initialTemperature": { + "type": "number" + }, + "finalTemperature": { + "type": "number" } }, "relations": { diff --git a/modules/travel/back/methods/travel/getEntries.js b/modules/travel/back/methods/travel/getEntries.js index 50088ccfa..2399f8bc4 100644 --- a/modules/travel/back/methods/travel/getEntries.js +++ b/modules/travel/back/methods/travel/getEntries.js @@ -41,7 +41,9 @@ module.exports = Self => { * b.stickers)/1000000) AS DECIMAL(10,2)) m3, TRUNCATE(SUM(b.stickers)/(COUNT( b.id) / COUNT( DISTINCT b.id)),0) hb, CAST(SUM(b.freightValue*b.quantity) AS DECIMAL(10,2)) freightValue, - CAST(SUM(b.packageValue*b.quantity) AS DECIMAL(10,2)) packageValue + CAST(SUM(b.packageValue*b.quantity) AS DECIMAL(10,2)) packageValue, + e.initialTemperature, + e.finalTemperature FROM vn.travel t LEFT JOIN vn.entry e ON t.id = e.travelFk LEFT JOIN vn.buy b ON b.entryFk = e.id -- 2.40.1 From 29e6a999836f42bd626dce912451aaa1293223fe Mon Sep 17 00:00:00 2001 From: Jon Date: Tue, 14 Jan 2025 07:36:23 +0100 Subject: [PATCH 28/39] feat: refs #8247 added new acl for VnUser model --- db/versions/11407-turquoiseTulip/00-firstScript.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 db/versions/11407-turquoiseTulip/00-firstScript.sql diff --git a/db/versions/11407-turquoiseTulip/00-firstScript.sql b/db/versions/11407-turquoiseTulip/00-firstScript.sql new file mode 100644 index 000000000..72d29061d --- /dev/null +++ b/db/versions/11407-turquoiseTulip/00-firstScript.sql @@ -0,0 +1,2 @@ +INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId) + VALUES ('VnUser','adminUser','WRITE','ALLOW','ROLE','sysadmin'); \ No newline at end of file -- 2.40.1 From 44765b5a64dc00913c59b83776c1c7fbd10df7a7 Mon Sep 17 00:00:00 2001 From: jgallego Date: Tue, 14 Jan 2025 09:07:00 +0100 Subject: [PATCH 29/39] feat: refs #8361 add hasToDownloadRate field to currency model and update exchange rate logic --- db/dump/fixtures.before.sql | 12 +++++------ .../11406-bronzeMoss/00-currrencyAlter.sql | 2 ++ .../11406-bronzeMoss/01-currrencyUpdate.sql | 3 +++ .../methods/invoice-in/exchangeRateUpdate.js | 21 +++++-------------- modules/travel/back/models/currency.json | 3 +++ 5 files changed, 19 insertions(+), 22 deletions(-) create mode 100644 db/versions/11406-bronzeMoss/00-currrencyAlter.sql create mode 100644 db/versions/11406-bronzeMoss/01-currrencyUpdate.sql diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index ff896b84d..788854b4e 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -158,13 +158,13 @@ INSERT INTO `account`.`mailForward`(`account`, `forwardTo`) -INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`) +INSERT INTO `vn`.`currency`(`id`, `code`, `name`, `ratio`, `hasToDownloadRate`) VALUES - (1, 'EUR', 'Euro', 1), - (2, 'USD', 'Dollar USA', 1.4), - (3, 'GBP', 'Libra', 1), - (4, 'JPY', 'Yen Japones', 1), - (5, 'CNY', 'Yuan Chino', 1.2); + (1, 'EUR', 'Euro', 1, FALSE), + (2, 'USD', 'Dollar USA', 1.4, TRUE), + (3, 'GBP', 'Libra', 1, TRUE), + (4, 'JPY', 'Yen Japones', 1, FALSE), + (5, 'CNY', 'Yuan Chino', 1.2, TRUE); INSERT INTO `vn`.`country`(`id`, `name`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`, `continentFk`, `hasDailyInvoice`, `CEE`) VALUES diff --git a/db/versions/11406-bronzeMoss/00-currrencyAlter.sql b/db/versions/11406-bronzeMoss/00-currrencyAlter.sql new file mode 100644 index 000000000..86465545e --- /dev/null +++ b/db/versions/11406-bronzeMoss/00-currrencyAlter.sql @@ -0,0 +1,2 @@ +ALTER TABLE `vn`.`currency` +ADD COLUMN `hasToDownloadRate` TINYINT(1) NOT NULL DEFAULT 0 comment 'Si se guarda el tipo de cambio diariamente en referenceRate'; diff --git a/db/versions/11406-bronzeMoss/01-currrencyUpdate.sql b/db/versions/11406-bronzeMoss/01-currrencyUpdate.sql new file mode 100644 index 000000000..5e0882de2 --- /dev/null +++ b/db/versions/11406-bronzeMoss/01-currrencyUpdate.sql @@ -0,0 +1,3 @@ +UPDATE `vn`.`currency` + SET `hasToDownloadRate` = TRUE + WHERE `code` IN ('USD', 'CNY', 'GBP'); diff --git a/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js b/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js index a6bad405f..99ff4cd79 100644 --- a/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js +++ b/modules/invoiceIn/back/methods/invoice-in/exchangeRateUpdate.js @@ -36,6 +36,7 @@ module.exports = Self => { if (!cubes || cubes.length === 0) throw new UserError('No cubes found. Exiting the method.'); + const currencies = await models.Currency.find({where: {hasToDownloadRate: true}}, myOptions); const maxDateRecord = await models.ReferenceRate.findOne({order: 'dated DESC'}, myOptions); const maxDate = maxDateRecord?.dated ? new Date(maxDateRecord.dated) : null; let lastProcessedDate = maxDate; @@ -51,32 +52,20 @@ module.exports = Self => { if (!maxDate || xmlDateWithoutTime > maxDate) { if (lastProcessedDate && xmlDateWithoutTime > lastProcessedDate) { - for (const code of ['USD', 'CNY', 'GBP']) { - const currency = await models.Currency.findOne( - {where: {code}}, - myOptions - ); - if (!currency) - throw new UserError(`Currency not found for code: ${code}`); - + for (const currency of currencies) { await fillMissingDates( models, currency, lastProcessedDate, xmlDateWithoutTime, myOptions ); } } } + for (const rateCube of Array.from(cube.childNodes)) { if (rateCube.nodeType === doc.ELEMENT_NODE) { const currencyCode = rateCube.getAttribute('currency'); const rate = rateCube.getAttribute('rate'); - if (['USD', 'CNY', 'GBP'].includes(currencyCode)) { - const currency = await models.Currency.findOne( - {where: {code: currencyCode}}, - myOptions - ); - if (!currency) - throw new UserError(`Currency not found for code: ${currencyCode}`); - + const currency = currencies.find(c => c.code === currencyCode); + if (currency) { const existingRate = await models.ReferenceRate.findOne({ where: {currencyFk: currency.id, dated: xmlDateWithoutTime} }, myOptions); diff --git a/modules/travel/back/models/currency.json b/modules/travel/back/models/currency.json index f3241fad1..427a18e31 100644 --- a/modules/travel/back/models/currency.json +++ b/modules/travel/back/models/currency.json @@ -20,6 +20,9 @@ }, "ratio": { "type": "number" + }, + "hasToDownloadRate": { + "type": "boolean" } }, "acls": [ -- 2.40.1 From 416e6c81f152850a3d4da974e4f2e8df8252b677 Mon Sep 17 00:00:00 2001 From: ivanm Date: Wed, 15 Jan 2025 15:22:48 +0100 Subject: [PATCH 30/39] refactor: refs #8378 deprecate bi.f_tvc --- db/versions/11410-blackTulip/00-firstScript.sql | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 db/versions/11410-blackTulip/00-firstScript.sql diff --git a/db/versions/11410-blackTulip/00-firstScript.sql b/db/versions/11410-blackTulip/00-firstScript.sql new file mode 100644 index 000000000..e300c4b7c --- /dev/null +++ b/db/versions/11410-blackTulip/00-firstScript.sql @@ -0,0 +1,2 @@ +RENAME TABLE bi.f_tvc TO bi.f_tvc__; +ALTER TABLE bi.f_tvc__ COMMENT='@deprecated 2025-01-15'; \ No newline at end of file -- 2.40.1 From 4d98c340d210635d1546e15ea7e74dc620c05b00 Mon Sep 17 00:00:00 2001 From: guillermo Date: Thu, 16 Jan 2025 09:34:18 +0100 Subject: [PATCH 31/39] feat: refs #7882 Added coords to create a address --- modules/client/back/methods/client/createAddress.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/client/back/methods/client/createAddress.js b/modules/client/back/methods/client/createAddress.js index 2709632cb..6bd4a26c1 100644 --- a/modules/client/back/methods/client/createAddress.js +++ b/modules/client/back/methods/client/createAddress.js @@ -52,6 +52,14 @@ module.exports = function(Self) { arg: 'customsAgentFk', type: 'number' }, + { + arg: 'longitude', + type: 'number' + }, + { + arg: 'latitude', + type: 'number' + }, { arg: 'isActive', type: 'boolean' -- 2.40.1 From 125b7730e736b2e8421e4226c624a80d4d109230 Mon Sep 17 00:00:00 2001 From: jgallego Date: Thu, 16 Jan 2025 12:56:04 +0100 Subject: [PATCH 32/39] feat: refs #8298 update price calculation logic and add packagesDiscountFactor column to client table --- db/routines/vn/procedures/catalog_componentCalculate.sql | 6 +----- db/versions/11398-orangeRose/02-clientAlter.sql | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/db/routines/vn/procedures/catalog_componentCalculate.sql b/db/routines/vn/procedures/catalog_componentCalculate.sql index 991ff412f..aaf2db408 100644 --- a/db/routines/vn/procedures/catalog_componentCalculate.sql +++ b/db/routines/vn/procedures/catalog_componentCalculate.sql @@ -236,11 +236,7 @@ BEGIN ic.cm3delivery * ( ( - zo.price - - ( - (zo.price - zo.priceOptimum) - * c.packagesDiscountFactor - ) + zo.priceOptimum + (( zo.price - zo.priceOptimum) * 2 * ( 1 - c.packagesDiscountFactor)) ) - IFNULL(zo.bonus, 0) ) diff --git a/db/versions/11398-orangeRose/02-clientAlter.sql b/db/versions/11398-orangeRose/02-clientAlter.sql index 4119f05ff..b5275a301 100644 --- a/db/versions/11398-orangeRose/02-clientAlter.sql +++ b/db/versions/11398-orangeRose/02-clientAlter.sql @@ -1,3 +1,3 @@ ALTER TABLE `vn`.`client` ADD COLUMN `packagesDiscountFactor` DECIMAL(4,3) NOT NULL DEFAULT 1.000 - COMMENT 'Factor (1-0) que pondera el precio final entre priceOptimum (mejor) y price (peor)'; + COMMENT 'Porcentaje de ajuste entre el numero de bultos medio del cliente, y el número medio óptimo para las zonas en las que compra'; -- 2.40.1 From 1cdeadb59de1288857e0df6ed058e08aa1375413 Mon Sep 17 00:00:00 2001 From: provira Date: Fri, 17 Jan 2025 13:20:45 +0100 Subject: [PATCH 33/39] feat: refs #8258 added uppercase validation on supplier create --- loopback/locale/es.json | 5 +++-- modules/supplier/back/methods/supplier/newSupplier.js | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index cde81e0cb..3183a9697 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -398,5 +398,6 @@ "Holidays to past days not available": "Las vacaciones a días pasados no están disponibles", "All tickets have a route order": "Todos los tickets tienen orden de ruta", "Price cannot be blank": "Price cannot be blank", - "There are tickets to be invoiced": "La zona tiene tickets por facturar" -} + "There are tickets to be invoiced": "La zona tiene tickets por facturar", + "Social name should be uppercase": "La razón social debe ir en mayúscula" +} \ No newline at end of file diff --git a/modules/supplier/back/methods/supplier/newSupplier.js b/modules/supplier/back/methods/supplier/newSupplier.js index 3cca4195f..eb941ed69 100644 --- a/modules/supplier/back/methods/supplier/newSupplier.js +++ b/modules/supplier/back/methods/supplier/newSupplier.js @@ -28,6 +28,7 @@ module.exports = Self => { delete args.ctx; if (!args.name) throw new UserError('The social name cannot be empty'); + if (args.name !== args.name.toUpperCase()) throw new UserError('Social name should be uppercase'); const data = {...args, ...{nickname: args.name}}; const supplier = await models.Supplier.create(data, myOptions); -- 2.40.1 From 0340612645ab456997ba034775c0de3cab70aff1 Mon Sep 17 00:00:00 2001 From: sergiodt Date: Mon, 20 Jan 2025 12:35:55 +0100 Subject: [PATCH 34/39] feat: refs #7569 refs#7569 sendEmailNotification --- loopback/locale/en.json | 2 +- loopback/locale/es.json | 3 ++- loopback/locale/fr.json | 2 +- loopback/locale/pt.json | 2 +- modules/ticket/back/methods/ticket/saveSign.js | 12 +++++------- .../back/methods/ticket/specs/saveSign.spec.js | 16 ++++++++++++---- 6 files changed, 22 insertions(+), 15 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 0f53cf572..d39b1bac5 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -249,5 +249,5 @@ "Sales already moved": "Sales already moved", "Holidays to past days not available": "Holidays to past days not available", "Incorrect delivery order alert on route": "Incorrect delivery order alert on route: {{ route }} zone: {{ zone }}", - "Ticket has been delivered out of order": "The ticket {{ticket}} {{{fullUrl}}} has been delivered out of order. Tickets that have not been delivered in their route are: {{ ticketsToMail }}" + "Ticket has been delivered out of order": "The ticket {{ticket}} {{{fullUrl}}} has been delivered out of order." } \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 163fbaa71..b9207d9cf 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -394,5 +394,6 @@ "An item type with the same code already exists": "Un tipo con el mismo código ya existe", "Holidays to past days not available": "Las vacaciones a días pasados no están disponibles", "Incorrect delivery order alert on route": "Alerta de orden de entrega incorrecta en ruta: {{ route }} zona: {{ zone }}", - "Ticket has been delivered out of order": "El ticket {{ticket}} {{{fullUrl}}} no ha sigo entregado en su orden. Los tickets de la ruta que no han sido entregados en su orden son: {{ ticketsToMail }}" + "Ticket has been delivered out of order": "El ticket {{ticket}} {{{fullUrl}}} no ha sigo entregado en su orden.", + "Price cannot be blank": "Price cannot be blank" } \ No newline at end of file diff --git a/loopback/locale/fr.json b/loopback/locale/fr.json index 082aedd2b..66098bac5 100644 --- a/loopback/locale/fr.json +++ b/loopback/locale/fr.json @@ -368,5 +368,5 @@ "ticketLostExpedition": "Le ticket [{{ticketId}}]({{{ticketUrl}}}) a l'expédition perdue suivante : {{expeditionId}}", "The web user's email already exists": "L'email de l'internaute existe déjà", "Incorrect delivery order alert on route": "Alerte de bon de livraison incorrect sur l'itinéraire: {{ route }} zone : {{ zone }}", - "Ticket has been delivered out of order": "Le ticket {{ticket}} {{{fullUrl}}} a été livré hors ordre. Les tickets qui n'ont pas été livrés dans leur itinéraire sont : {{ticketsToMail}}" + "Ticket has been delivered out of order": "Le ticket {{ticket}} {{{fullUrl}}} a été livré hors ordre." } \ No newline at end of file diff --git a/loopback/locale/pt.json b/loopback/locale/pt.json index 1fa16074f..240d239d6 100644 --- a/loopback/locale/pt.json +++ b/loopback/locale/pt.json @@ -367,5 +367,5 @@ "ticketLostExpedition": "O ticket [{{ticketId}}]({{{ticketUrl}}}) tem a seguinte expedição perdida: {{expeditionId}}", "The web user's email already exists": "O e-mail do utilizador da web já existe.", "Incorrect delivery order alert on route": "Alerta de ordem de entrega incorreta na rota: {{ route }} zona: {{ zone }}", - "Ticket has been delivered out of order": "O ticket {{ticket}} {{{fullUrl}}} foi entregue fora de ordem. Os tickets que não foram entregues na sua rota são: {{ ticketsToMail }}" + "Ticket has been delivered out of order": "O ticket {{ticket}} {{{fullUrl}}} foi entregue fora de ordem." } \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 443b2c1c7..9c33797b6 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -162,7 +162,7 @@ module.exports = Self => { fields: ['id'] }, myOptions); - const ticketsToMail = await Self.rawSql(` + const ticketIncorrect = await Self.rawSql(` SELECT t.id FROM ticket t JOIN ticketState ts ON ts.ticketFk = t.id @@ -173,10 +173,9 @@ module.exports = Self => { FROM ticket t WHERE t.id = ?)` , [ticket.routeFk, orderState.id, ticket.id], myOptions); - const ticketIds = ticketsToMail.map(row => row.id); - if (ticketsToMail) - await sendMail(ctx, ticket.routeFk, ticket.id, ticket.zone().name, ticketIds); + if (ticketIncorrect && ticketIncorrect.length > 0) + await sendMail(ctx, ticket.routeFk, ticket.id, ticket.zone().name); } if (ticket?.address()?.province()?.country()?.code != 'ES' && ticket.$cmrFk) { @@ -192,7 +191,7 @@ module.exports = Self => { await models.Ticket.sendCmrEmail(ctx, externalTickets); }; - async function sendMail(ctx, route, ticket, zoneName, ticketsToMail) { + async function sendMail(ctx, route, ticket, zoneName) { const $t = ctx.req.__; const url = await Self.app.models.Url.getUrl(); const sendTo = 'repartos@verdnatura.es'; @@ -203,8 +202,7 @@ module.exports = Self => { }); const emailBody = $t('Ticket has been delivered out of order', { ticket, - fullUrl, - ticketsToMail, + fullUrl }); await Self.app.models.Mail.create({ diff --git a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js index ed802e311..7098ee1fc 100644 --- a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js +++ b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js @@ -1,14 +1,22 @@ const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); describe('Ticket saveSign()', () => { let ctx = {req: { getLocale: () => { return 'en'; }, + __: () => {}, accessToken: {userId: 9} - }}; + } + }; + beforeEach(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: ctx + }); + }); - it(`should throw error if the ticket's alert level is lower than 2`, async() => { + fit(`should throw error if the ticket's alert level is lower than 2`, async() => { const tx = await models.TicketDms.beginTransaction({}); const ticketWithOkState = 12; let error; @@ -27,7 +35,7 @@ describe('Ticket saveSign()', () => { expect(error).toBeDefined(); }); - it('should change state for ticket', async() => { + fit('should change state for ticket', async() => { const tx = await models.Ticket.beginTransaction({}); const ticketWithPackedState = 7; spyOn(models.Dms, 'uploadFile').and.returnValue([{id: 1}]); @@ -52,7 +60,7 @@ describe('Ticket saveSign()', () => { expect(ticketTrackingAfter.name).toBe('Entregado en parte'); }); - it('should send an email to notify that the delivery order is not correct', async() => { + fit('should send an email to notify that the delivery order is not correct', async() => { const tx = await models.Ticket.beginTransaction({}); const ticketFk = 8; const priority = 5; -- 2.40.1 From b5e27707a73f339e2d4d5fbe27d76b3765ca9041 Mon Sep 17 00:00:00 2001 From: sergiodt Date: Mon, 20 Jan 2025 12:36:31 +0100 Subject: [PATCH 35/39] feat: refs #7569 refs#7569 sendEmailNotification --- modules/ticket/back/methods/ticket/specs/saveSign.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js index 7098ee1fc..9cc262ea0 100644 --- a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js +++ b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js @@ -16,7 +16,7 @@ describe('Ticket saveSign()', () => { }); }); - fit(`should throw error if the ticket's alert level is lower than 2`, async() => { + it(`should throw error if the ticket's alert level is lower than 2`, async() => { const tx = await models.TicketDms.beginTransaction({}); const ticketWithOkState = 12; let error; @@ -35,7 +35,7 @@ describe('Ticket saveSign()', () => { expect(error).toBeDefined(); }); - fit('should change state for ticket', async() => { + it('should change state for ticket', async() => { const tx = await models.Ticket.beginTransaction({}); const ticketWithPackedState = 7; spyOn(models.Dms, 'uploadFile').and.returnValue([{id: 1}]); -- 2.40.1 From ef68884fe0b5f656540cfeddf1d3a6f711bd6259 Mon Sep 17 00:00:00 2001 From: sergiodt Date: Mon, 20 Jan 2025 16:27:35 +0100 Subject: [PATCH 36/39] feat: refs #7569 refs#7569 sendEmailNotification --- loopback/locale/es.json | 2 +- modules/ticket/back/methods/ticket/saveSign.js | 2 +- modules/ticket/back/methods/ticket/specs/saveSign.spec.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/loopback/locale/es.json b/loopback/locale/es.json index b9207d9cf..eff238150 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -395,5 +395,5 @@ "Holidays to past days not available": "Las vacaciones a días pasados no están disponibles", "Incorrect delivery order alert on route": "Alerta de orden de entrega incorrecta en ruta: {{ route }} zona: {{ zone }}", "Ticket has been delivered out of order": "El ticket {{ticket}} {{{fullUrl}}} no ha sigo entregado en su orden.", - "Price cannot be blank": "Price cannot be blank" + "Price cannot be blank": "El precio no puede estar en blanco" } \ No newline at end of file diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index 9c33797b6..f99311c39 100644 --- a/modules/ticket/back/methods/ticket/saveSign.js +++ b/modules/ticket/back/methods/ticket/saveSign.js @@ -174,7 +174,7 @@ module.exports = Self => { WHERE t.id = ?)` , [ticket.routeFk, orderState.id, ticket.id], myOptions); - if (ticketIncorrect && ticketIncorrect.length > 0) + if (ticketIncorrect?.length > 0) await sendMail(ctx, ticket.routeFk, ticket.id, ticket.zone().name); } diff --git a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js index 9cc262ea0..3b426c2cf 100644 --- a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js +++ b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js @@ -60,7 +60,7 @@ describe('Ticket saveSign()', () => { expect(ticketTrackingAfter.name).toBe('Entregado en parte'); }); - fit('should send an email to notify that the delivery order is not correct', async() => { + it('should send an email to notify that the delivery order is not correct', async() => { const tx = await models.Ticket.beginTransaction({}); const ticketFk = 8; const priority = 5; -- 2.40.1 From eee73f001de867f11a0e68f863a9f40bb0bc0b7e Mon Sep 17 00:00:00 2001 From: sergiodt Date: Tue, 21 Jan 2025 07:00:02 +0100 Subject: [PATCH 37/39] Merge branch 'dev' of https: refs #7569//gitea.verdnatura.es/verdnatura/salix into 7569-sendEmailOrderTicket --- loopback/locale/en.json | 2 -- loopback/locale/es.json | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 4f6374a8f..2c180e204 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -247,8 +247,6 @@ "ticketLostExpedition": "The ticket [{{ticketId}}]({{{ticketUrl}}}) has the following lost expedition:{{ expeditionId }}", "The raid information is not correct": "The raid information is not correct", "Payment method is required": "Payment method is required", - "Sales already moved": "Sales already moved", - "Holidays to past days not available": "Holidays to past days not available", "Price cannot be blank": "Price cannot be blank", "There are tickets to be invoiced": "There are tickets to be invoiced", "The address of the customer must have information about Incoterms and Customs Agent": "The address of the customer must have information about Incoterms and Customs Agent""Sales already moved": "Sales already moved", diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 0203a3bc1..abd2f79a0 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -390,13 +390,11 @@ "The web user's email already exists": "El correo del usuario web ya existe", "Sales already moved": "Ya han sido transferidas", "The raid information is not correct": "La información de la redada no es correcta", - "There are tickets to be invoiced": "Hay tickets para esta zona, borralos primero", "An item type with the same code already exists": "Un tipo con el mismo código ya existe", "Holidays to past days not available": "Las vacaciones a días pasados no están disponibles", "All tickets have a route order": "Todos los tickets tienen orden de ruta", - "Price cannot be blank": "Price cannot be blank", "There are tickets to be invoiced": "La zona tiene tickets por facturar", - "Social name should be uppercase": "La razón social debe ir en mayúscula""Incorrect delivery order alert on route": "Alerta de orden de entrega incorrecta en ruta: {{ route }} zona: {{ zone }}", + "Incorrect delivery order alert on route": "Alerta de orden de entrega incorrecta en ruta: {{ route }} zona: {{ zone }}", "Ticket has been delivered out of order": "El ticket {{ticket}} {{{fullUrl}}} no ha sigo entregado en su orden.", "Price cannot be blank": "El precio no puede estar en blanco" } \ No newline at end of file -- 2.40.1 From c50ff6a43aa27323c9973b976c29da509920f4a6 Mon Sep 17 00:00:00 2001 From: sergiodt Date: Tue, 21 Jan 2025 07:05:42 +0100 Subject: [PATCH 38/39] feat: refs #7569 refs#7569 sendEmailNotification --- loopback/locale/en.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 2c180e204..06428475f 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -249,7 +249,8 @@ "Payment method is required": "Payment method is required", "Price cannot be blank": "Price cannot be blank", "There are tickets to be invoiced": "There are tickets to be invoiced", - "The address of the customer must have information about Incoterms and Customs Agent": "The address of the customer must have information about Incoterms and Customs Agent""Sales already moved": "Sales already moved", + "The address of the customer must have information about Incoterms and Customs Agent": "The address of the customer must have information about Incoterms and Customs Agent", + "Sales already moved": "Sales already moved", "Holidays to past days not available": "Holidays to past days not available", "Incorrect delivery order alert on route": "Incorrect delivery order alert on route: {{ route }} zone: {{ zone }}", "Ticket has been delivered out of order": "The ticket {{ticket}} {{{fullUrl}}} has been delivered out of order." -- 2.40.1 From 05b383ecb01ad4fc5606aa73bdff2cc2c9f1b1d6 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 21 Jan 2025 10:57:40 +0100 Subject: [PATCH 39/39] test: refs #8448 fix e2e --- e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js | 16 +--------------- e2e/paths/05-ticket/06_basic_data_steps.spec.js | 2 +- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js index d9689e31a..af1dc56bc 100644 --- a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js +++ b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js @@ -238,25 +238,11 @@ describe('Ticket Edit sale path', () => { await page.waitToClick(selectors.globalItems.cancelButton); }); - it('should select the third sale and create a claim of it', async() => { - await page.accessToSearchResult('16'); - await page.accessToSection('ticket.card.sale'); - await page.waitToClick(selectors.ticketSales.thirdSaleCheckbox); - await page.waitToClick(selectors.ticketSales.moreMenu); - await page.waitToClick(selectors.ticketSales.moreMenuCreateClaim); - await page.waitToClick(selectors.globalItems.acceptButton); - await page.waitForNavigation(); - }); - - it('should search for a ticket then access to the sales section', async() => { - await page.goBack(); - await page.goBack(); + it('should select the third sale and delete it', async() => { await page.loginAndModule('salesPerson', 'ticket'); await page.accessToSearchResult('16'); await page.accessToSection('ticket.card.sale'); - }); - it('should select the third sale and delete it', async() => { await page.waitToClick(selectors.ticketSales.thirdSaleCheckbox); await page.waitToClick(selectors.ticketSales.deleteSaleButton); await page.waitToClick(selectors.globalItems.acceptButton); diff --git a/e2e/paths/05-ticket/06_basic_data_steps.spec.js b/e2e/paths/05-ticket/06_basic_data_steps.spec.js index 77f0e0459..0a3ae4edc 100644 --- a/e2e/paths/05-ticket/06_basic_data_steps.spec.js +++ b/e2e/paths/05-ticket/06_basic_data_steps.spec.js @@ -75,7 +75,7 @@ describe('Ticket Edit basic data path', () => { const result = await page .waitToGetProperty(selectors.ticketBasicData.stepTwoTotalPriceDif, 'innerText'); - expect(result).toContain('-€228.25'); + expect(result).toContain('-€111.75'); }); it(`should select a new reason for the changes made then click on finalize`, async() => { -- 2.40.1