From beb66cce1f6be159a0f265c364d9df31f60d045b Mon Sep 17 00:00:00 2001 From: Pako Date: Wed, 25 Sep 2024 07:43:29 +0200 Subject: [PATCH 1/8] feat(components): refs #8030 new component bonus With table vn.priceDelta, buyers set a range of items to be affected for a price increasing Refs: #8030 --- .../procedures/catalog_componentCalculate.sql | 58 +++++++++++++++---- .../11263-brownAnthurium/00-firstScript.sql | 32 ++++++++++ 2 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 db/versions/11263-brownAnthurium/00-firstScript.sql diff --git a/db/routines/vn/procedures/catalog_componentCalculate.sql b/db/routines/vn/procedures/catalog_componentCalculate.sql index 7ac383e8f..d4ce88ca7 100644 --- a/db/routines/vn/procedures/catalog_componentCalculate.sql +++ b/db/routines/vn/procedures/catalog_componentCalculate.sql @@ -7,7 +7,7 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`catalog_componentCalc ) BEGIN /** - * Calcula los componentes de los articulos de tmp.ticketLot + * Calcula los componentes de los articulos de la tabla tmp.ticketLot * * @param vZoneFk para calcular el transporte * @param vAddressFk Consignatario @@ -25,18 +25,38 @@ BEGIN FROM address WHERE id = vAddressFk; - CREATE OR REPLACE TEMPORARY TABLE tSpecialPrice + CREATE OR REPLACE TEMPORARY TABLE tPriceDelta (INDEX (itemFk)) - ENGINE = MEMORY - SELECT * FROM ( + ENGINE = MEMORY + SELECT i.id itemFk, + SUM(IFNULL(pd.absIncreasing,0)) absIncreasing, + SUM(IFNULL(pd.ratIncreasing,0)) ratIncreasing, + pd.warehouseFk + FROM item i + JOIN priceDelta pd + ON pd.itemTypeFk = i.typeFk + AND (pd.minSize IS NULL OR pd.minSize <= i.`size`) + AND (pd.maxSize IS NULL OR pd.maxSize >= i.`size`) + AND (pd.inkFk IS NULL OR pd.inkFk = i.inkFk) + AND (pd.originFk IS NULL OR pd.originFk = i.originFk) + AND (pd.producerFk IS NULL OR pd.producerFk = i.producerFk) + AND (pd.warehouseFk IS NULL OR pd.warehouseFk = vWarehouseFk) + WHERE (pd.fromDated IS NULL OR pd.fromDated <= vShipped) + AND (pd.toDated IS NULL OR pd.toDated >= vShipped) + GROUP BY i.id; + + CREATE OR REPLACE TEMPORARY TABLE tSpecialPrice + (INDEX (itemFk)) + ENGINE = MEMORY + SELECT * FROM ( SELECT * - FROM specialPrice - WHERE (clientFk = vClientFk OR clientFk IS NULL) - AND started <= vShipped - AND (ended >= vShipped OR ended IS NULL) - ORDER BY (clientFk = vClientFk) DESC, id DESC - LIMIT 10000000000000000000) t - GROUP BY itemFk; + FROM specialPrice + WHERE (clientFk = vClientFk OR clientFk IS NULL) + AND started <= vShipped + AND (ended >= vShipped OR ended IS NULL) + ORDER BY (clientFk = vClientFk) DESC, id DESC + LIMIT 10000000000000000000) t + GROUP BY itemFk; CREATE OR REPLACE TEMPORARY TABLE tmp.ticketComponentCalculate (PRIMARY KEY (itemFk, warehouseFk)) @@ -108,6 +128,19 @@ BEGIN JOIN tmp.ticketComponentCalculate tcc ON tcc.itemFk = tc.itemFk AND tcc.warehouseFk = tc.warehouseFk GROUP BY tc.itemFk, warehouseFk; + -- Bonus del comprador a un rango de productos + INSERT INTO tmp.ticketComponent(warehouseFk, itemFk, componentFk, cost) + SELECT + tcb.warehouseFk, + tcb.itemFk, + c.id, + IFNULL(tcb.base * tpd.ratIncreasing / 100,0) + IFNULL(tpd.absIncreasing,0) + FROM tmp.ticketComponentBase tcb + JOIN component c ON c.code = 'bonus' + JOIN tPriceDelta tpd + ON tpd.itemFk = tcb.itemFk + AND tpd.warehouseFk = tcb.warehouseFk; + -- RECOBRO INSERT INTO tmp.ticketComponent(warehouseFk, itemFk, componentFk, cost) SELECT tcb.warehouseFk, tcb.itemFk, c2.id, @@ -303,6 +336,7 @@ BEGIN tmp.ticketComponentBase, tmp.ticketComponentRate, tmp.ticketComponentCopy, - tSpecialPrice; + tPriceDelta, + tSpecialPrice; END$$ DELIMITER ; diff --git a/db/versions/11263-brownAnthurium/00-firstScript.sql b/db/versions/11263-brownAnthurium/00-firstScript.sql new file mode 100644 index 000000000..0824ea5f7 --- /dev/null +++ b/db/versions/11263-brownAnthurium/00-firstScript.sql @@ -0,0 +1,32 @@ +-- Place your SQL code here +-- vn.priceDelta definition + +CREATE OR REPLACE TABLE vn.priceDelta ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `itemTypeFk` smallint(5) unsigned NOT NULL, + `minSize` int(10) unsigned DEFAULT NULL COMMENT 'Minimum item.size', + `maxSize` int(10) unsigned DEFAULT NULL COMMENT 'Maximum item.size', + `inkFk` varchar(3) DEFAULT NULL, + `originFk` tinyint(2) unsigned DEFAULT NULL, + `producerFk` mediumint(3) unsigned DEFAULT NULL, + `fromDated` date DEFAULT NULL, + `toDated` date DEFAULT NULL, + `absIncreasing` decimal(10,3) DEFAULT NULL COMMENT 'Absolute increasing of final price', + `ratIncreasing` int(11) DEFAULT NULL COMMENT 'Increasing ratio for the cost price', + `warehouseFk` smallint(6) unsigned NOT NULL, + `created` timestamp NOT NULL DEFAULT current_timestamp(), + `editorFk` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `priceDelta_itemType_FK` (`itemTypeFk`), + KEY `priceDelta_ink_FK` (`inkFk`), + KEY `priceDelta_producer_FK` (`producerFk`), + KEY `priceDelta_warehouse_FK` (`warehouseFk`), + KEY `priceDelta_worker_FK` (`editorFk`), + CONSTRAINT `priceDelta_ink_FK` FOREIGN KEY (`inkFk`) REFERENCES `ink` (`id`) ON UPDATE CASCADE, + CONSTRAINT `priceDelta_itemType_FK` FOREIGN KEY (`itemTypeFk`) REFERENCES `itemType` (`id`) ON UPDATE CASCADE, + CONSTRAINT `priceDelta_producer_FK` FOREIGN KEY (`producerFk`) REFERENCES `producer` (`id`) ON UPDATE CASCADE, + CONSTRAINT `priceDelta_warehouse_FK` FOREIGN KEY (`warehouseFk`) REFERENCES `warehouse` (`id`) ON UPDATE CASCADE, + CONSTRAINT `priceDelta_worker_FK` FOREIGN KEY (`editorFk`) REFERENCES `worker` (`id`) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Defines the increasing o decreasing for ranges of items'; + +GRANT INSERT, SELECT, UPDATE, DELETE ON TABLE vn.priceDelta TO buyer; \ No newline at end of file From 8f63118550998f48acd324a1d8103a29a56941db Mon Sep 17 00:00:00 2001 From: sergiodt Date: Wed, 25 Sep 2024 12:24:00 +0200 Subject: [PATCH 2/8] fix: refs #6861 updateAvailable --- modules/item/back/methods/item-shelving/updateFromSale.js | 6 +++++- modules/ticket/back/methods/sale-tracking/setPicked.js | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/modules/item/back/methods/item-shelving/updateFromSale.js b/modules/item/back/methods/item-shelving/updateFromSale.js index 167509074..47ca2a010 100644 --- a/modules/item/back/methods/item-shelving/updateFromSale.js +++ b/modules/item/back/methods/item-shelving/updateFromSale.js @@ -38,9 +38,13 @@ module.exports = Self => { const itemShelving = itemShelvingSale.itemShelving(); const quantity = itemShelving.visible + itemShelvingSale.quantity; + const available = itemShelving.available + itemShelvingSale.quantity; await itemShelving.updateAttributes( - {visible: quantity}, + { + visible: quantity, + available: available + }, myOptions ); if (tx) await tx.commit(); diff --git a/modules/ticket/back/methods/sale-tracking/setPicked.js b/modules/ticket/back/methods/sale-tracking/setPicked.js index ed3656cf4..b63a0474f 100644 --- a/modules/ticket/back/methods/sale-tracking/setPicked.js +++ b/modules/ticket/back/methods/sale-tracking/setPicked.js @@ -75,7 +75,11 @@ module.exports = Self => { const itemShelving = await models.ItemShelving.findById(itemShelvingFk, null, myOptions); - await itemShelving.updateAttributes({visible: itemShelving.visible - quantity}, myOptions); + await itemShelving.updateAttributes( + { + visible: itemShelving.visible - quantity, + available: itemShelving.available - quantity + }, myOptions); await Self.updateAll( {saleFk}, From 08cb1241bf4fb0c529dcde98ef434aec0e713b2e Mon Sep 17 00:00:00 2001 From: sergiodt Date: Thu, 26 Sep 2024 11:53:33 +0200 Subject: [PATCH 3/8] fix: refs #5890 recovery ItemShelving_afterInsert --- .../vn/triggers/itemShelving_afterInsert.sql | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 db/routines/vn/triggers/itemShelving_afterInsert.sql diff --git a/db/routines/vn/triggers/itemShelving_afterInsert.sql b/db/routines/vn/triggers/itemShelving_afterInsert.sql new file mode 100644 index 000000000..92243ca03 --- /dev/null +++ b/db/routines/vn/triggers/itemShelving_afterInsert.sql @@ -0,0 +1,18 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`itemShelving_afterInsert` + AFTER INSERT ON `itemShelving` + FOR EACH ROW +BEGIN + INSERT INTO itemShelvingLog + SET itemShelvingFk = NEW.id, + workerFk = account.myUser_getId(), + accion = 'CREA REGISTRO', + itemFk = NEW.itemFk, + shelvingFk = NEW.shelvingFk, + visible = NEW.visible, + `grouping` = NEW.`grouping`, + packing = NEW.packing, + available = NEW.available; + +END$$ +DELIMITER ; From 989589afd7e17c25d20f8851a8a812d7ab5aa554 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Thu, 26 Sep 2024 11:18:05 +0000 Subject: [PATCH 4/8] feat(salix): use params.q as table filter in lilium --- front/core/services/app.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/front/core/services/app.js b/front/core/services/app.js index cec7bea7f..17381dba8 100644 --- a/front/core/services/app.js +++ b/front/core/services/app.js @@ -66,6 +66,9 @@ export default class App { ]} }; + if (this.logger.$params.q) + newRoute = newRoute.concat(`list?table=${this.logger.$params.q}`); + return this.logger.$http.get('Urls/findOne', {filter}) .then(res => { if (res && res.data) From c83f44a4553935a180692a3d5e9f2af98ae00410 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Thu, 26 Sep 2024 12:12:33 +0000 Subject: [PATCH 5/8] perf(salix): use params.q as table filter in lilium --- front/core/services/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/front/core/services/app.js b/front/core/services/app.js index 17381dba8..a26d6def5 100644 --- a/front/core/services/app.js +++ b/front/core/services/app.js @@ -67,7 +67,8 @@ export default class App { }; if (this.logger.$params.q) - newRoute = newRoute.concat(`list?table=${this.logger.$params.q}`); + this.logger.$params.table = this.logger.$params.q; + return this.logger.$http.get('Urls/findOne', {filter}) .then(res => { From 4f16df523e23e4c63acaadfa807eb311ac293b60 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Thu, 26 Sep 2024 12:14:02 +0000 Subject: [PATCH 6/8] perf(salix): use params.q as table filter in lilium --- front/core/services/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/front/core/services/app.js b/front/core/services/app.js index a26d6def5..65d70e216 100644 --- a/front/core/services/app.js +++ b/front/core/services/app.js @@ -66,8 +66,9 @@ export default class App { ]} }; + if (this.logger.$params.q) - this.logger.$params.table = this.logger.$params.q; + newRoute = newRoute.concat(`?table=${this.logger.$params.q}`); return this.logger.$http.get('Urls/findOne', {filter}) From 640d9ad9f7ab5187743679c0f0feb34db46cf9c3 Mon Sep 17 00:00:00 2001 From: Javier Segarra Date: Thu, 26 Sep 2024 12:38:27 +0000 Subject: [PATCH 7/8] fix(salix): use params.sq --- front/core/services/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front/core/services/app.js b/front/core/services/app.js index 65d70e216..b8fcc43e1 100644 --- a/front/core/services/app.js +++ b/front/core/services/app.js @@ -57,7 +57,7 @@ export default class App { getUrl(route, appName = 'lilium') { const index = window.location.hash.indexOf(route.toLowerCase()); - const newRoute = index < 0 ? route : window.location.hash.substring(index); + let newRoute = index < 0 ? route : window.location.hash.substring(index); const env = process.env.NODE_ENV; const filter = { where: {and: [ From dbbd2c7947c7e81f3e828a382972166b892354ba Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 30 Sep 2024 08:04:01 +0200 Subject: [PATCH 8/8] feat(ClaimBeginning): throw error when quantity claimed is greater than quantity of line --- loopback/locale/en.json | 4 +- loopback/locale/es.json | 3 +- loopback/locale/fr.json | 4 +- loopback/locale/pt.json | 3 +- .../specs/claim-beginning.spec.js | 55 +++++++++++++++++++ modules/claim/back/models/claim-beginning.js | 17 ++++-- 6 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 modules/claim/back/methods/claim-beginning/specs/claim-beginning.spec.js diff --git a/loopback/locale/en.json b/loopback/locale/en.json index d9d9c8511..f0b7d6eca 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -236,6 +236,6 @@ "Cannot send mail": "Cannot send mail", "CONSTRAINT `chkParkingCodeFormat` failed for `vn`.`parking`": "CONSTRAINT `chkParkingCodeFormat` failed for `vn`.`parking`", "This postcode already exists": "This postcode already exists", - "Original invoice not found": "Original invoice not found" - + "Original invoice not found": "Original invoice not found", + "The quantity claimed cannot be greater than the quantity of the line": "The quantity claimed cannot be greater than the quantity of the line" } diff --git a/loopback/locale/es.json b/loopback/locale/es.json index b9933f596..84722ea5d 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -372,5 +372,6 @@ "The entry not have stickers": "La entrada no tiene etiquetas", "Too many records": "Demasiados registros", "Original invoice not found": "Factura original no encontrada", - "The entry has no lines or does not exist": "La entrada no tiene lineas o no existe" + "The entry has no lines or does not exist": "La entrada no tiene lineas o no existe", + "The quantity claimed cannot be greater than the quantity of the line": "La cantidad reclamada no puede ser mayor que la cantidad de la línea" } diff --git a/loopback/locale/fr.json b/loopback/locale/fr.json index 601fe35f5..a6648b186 100644 --- a/loopback/locale/fr.json +++ b/loopback/locale/fr.json @@ -361,6 +361,6 @@ "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" - + "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" } diff --git a/loopback/locale/pt.json b/loopback/locale/pt.json index a6a65710f..a43f0e780 100644 --- a/loopback/locale/pt.json +++ b/loopback/locale/pt.json @@ -361,5 +361,6 @@ "The invoices have been created but the PDFs could not be generated": "Foi faturado, mas o PDF não pôde ser gerado", "It has been invoiced but the PDF of refund not be generated": "Foi faturado mas não foi gerado o PDF do reembolso", "Original invoice not found": "Fatura original não encontrada", - "Cannot send mail": "Não é possível enviar o email" + "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" } diff --git a/modules/claim/back/methods/claim-beginning/specs/claim-beginning.spec.js b/modules/claim/back/methods/claim-beginning/specs/claim-beginning.spec.js new file mode 100644 index 000000000..b7974ad23 --- /dev/null +++ b/modules/claim/back/methods/claim-beginning/specs/claim-beginning.spec.js @@ -0,0 +1,55 @@ +const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); + +describe('ClaimBeginning model()', () => { + const claimFk = 1; + const activeCtx = { + accessToken: {userId: 18}, + headers: {origin: 'localhost:5000'}, + __: () => {} + }; + + beforeEach(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + + it('should change quantity claimed', async() => { + const tx = await models.ClaimBeginning.beginTransaction({}); + + let error; + try { + const options = {transaction: tx}; + const claim = await models.ClaimBeginning.findOne({where: {claimFk}}, options); + const sale = await models.Sale.findById(claim.saleFk, {}, options); + await claim.updateAttribute('quantity', sale.quantity - 1, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error).toBeUndefined(); + }); + + it('should throw error when quantity claimed is greater than quantity of the sale', async() => { + const tx = await models.ClaimBeginning.beginTransaction({}); + + let error; + try { + const options = {transaction: tx}; + const claim = await models.ClaimBeginning.findOne({where: {claimFk}}, options); + const sale = await models.Sale.findById(claim.saleFk, {}, options); + await claim.updateAttribute('quantity', sale.quantity + 1, options); + + await tx.rollback(); + } catch (e) { + error = e; + await tx.rollback(); + } + + expect(error.toString()).toContain('The quantity claimed cannot be greater than the quantity of the line'); + }); +}); diff --git a/modules/claim/back/models/claim-beginning.js b/modules/claim/back/models/claim-beginning.js index d269b2285..3dc9261c3 100644 --- a/modules/claim/back/models/claim-beginning.js +++ b/modules/claim/back/models/claim-beginning.js @@ -10,16 +10,21 @@ module.exports = Self => { }); Self.observe('before save', async ctx => { + const options = ctx.options; + const models = Self.app.models; + const saleFk = ctx?.currentInstance?.saleFk || ctx?.instance?.saleFk; + const sale = await models.Sale.findById(saleFk, {fields: ['ticketFk', 'quantity']}, options); + if (ctx.isNewInstance) { - const models = Self.app.models; - const options = ctx.options; - const instance = ctx.instance; - const ticket = await models.Sale.findById(instance.saleFk, {fields: ['ticketFk']}, options); - const claim = await models.Claim.findById(instance.claimFk, {fields: ['ticketFk']}, options); - if (ticket.ticketFk != claim.ticketFk) + const claim = await models.Claim.findById(ctx.instance.claimFk, {fields: ['ticketFk']}, options); + if (sale.ticketFk != claim.ticketFk) throw new UserError(`Cannot create a new claimBeginning from a different ticket`); } + await claimIsEditable(ctx); + + if (sale?.quantity && ctx.data?.quantity && ctx.data.quantity > sale?.quantity) + throw new UserError('The quantity claimed cannot be greater than the quantity of the line'); }); Self.observe('before delete', async ctx => {