diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index be7a2fab5..d918007e7 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -995,10 +995,11 @@ INSERT INTO `vn`.`priceFixed`(`id`, `itemFk`, `rate0`, `rate1`, `rate2`, `rate3` INSERT INTO `vn`.`itemMinimumQuantity`(`itemFk`, `quantity`, `started`, `ended`, `warehouseFk`) VALUES - (1, 5, util.VN_CURDATE() - INTERVAL 4 DAY, util.VN_CURDATE() + INTERVAL 1 MONTH, 1), + (1, 5, util.VN_CURDATE() - INTERVAL 2 MONTH, util.VN_CURDATE() + INTERVAL 1 MONTH, 1), (2, 10, util.VN_CURDATE() - INTERVAL 2 DAY, NULL, 2), (3, 15, util.VN_CURDATE() + INTERVAL 3 DAY, util.VN_CURDATE() + INTERVAL 2 WEEK, 3), - (2, 10, util.VN_CURDATE() + INTERVAL 2 MONTH, NULL, 5); + (2, 10, util.VN_CURDATE() + INTERVAL 2 MONTH, NULL, 5), + (4, 8, util.VN_CURDATE() - INTERVAL 3 MONTH, NULL, NULL); INSERT INTO `vn`.`expeditionBoxVol`(`boxFk`, `m3`, `ratio`) VALUES diff --git a/db/routines/hedera/procedures/order_addItem.sql b/db/routines/hedera/procedures/order_addItem.sql index 782dfe5c0..50c2f3489 100644 --- a/db/routines/hedera/procedures/order_addItem.sql +++ b/db/routines/hedera/procedures/order_addItem.sql @@ -59,8 +59,8 @@ BEGIN SELECT quantity INTO vMinQuantity FROM vn.itemMinimumQuantity WHERE itemFk = vItem - AND `started` <= util.VN_CURDATE() - AND (`ended` >= util.VN_CURDATE() OR `ended` IS NULL) + AND `started` <= vShipment + AND (`ended` >= vShipment OR `ended` IS NULL) AND (warehouseFk = vWarehouse OR warehouseFk IS NULL) LIMIT 1; diff --git a/db/routines/vn/procedures/catalog_calculate.sql b/db/routines/vn/procedures/catalog_calculate.sql index 83d1dad03..e79f2da0b 100644 --- a/db/routines/vn/procedures/catalog_calculate.sql +++ b/db/routines/vn/procedures/catalog_calculate.sql @@ -59,12 +59,11 @@ BEGIN price DECIMAL(10,2), priceKg DECIMAL(10,2), `grouping` INT(10) UNSIGNED, - minQuantity INT(11), + minQuantity INT(10) UNSIGNED, PRIMARY KEY `itemFk` (`itemFk`) ) ENGINE = MEMORY DEFAULT CHARSET=utf8; OPEN cTravelTree; - l: LOOP SET vDone = FALSE; FETCH cTravelTree INTO vZoneFk, vWarehouseFk, vShipped; @@ -151,8 +150,7 @@ BEGIN priceKg, `grouping`, minQuantity) - SELECT - tl.itemFk, + SELECT tl.itemFk, SUM(tl.available) available, p.name producer, i.name item, @@ -183,9 +181,9 @@ BEGIN ) bl ON bl.itemFk = tl.itemFk LEFT JOIN ( SELECT itemFk, quantity, warehouseFk - FROM vn.itemMinimumQuantity - WHERE `started` <= util.VN_CURDATE() - AND (`ended` >= util.VN_CURDATE() OR `ended` IS NULL) + FROM itemMinimumQuantity + WHERE `started` <= vShipped + AND (`ended` >= vShipped OR `ended` IS NULL) GROUP BY itemFk, warehouseFk ORDER BY warehouseFk DESC ) mq ON mq.itemFk = tl.itemFk @@ -193,9 +191,7 @@ BEGIN WHERE tl.zoneFk = vZoneFk AND tl.warehouseFk = vWarehouseFk GROUP BY tl.itemFk ON DUPLICATE KEY UPDATE available = available + VALUES(available); - END LOOP; - CLOSE cTravelTree; END$$ DELIMITER ; diff --git a/db/routines/vn/triggers/itemMinimumQuantity_beforeInsert.sql b/db/routines/vn/triggers/itemMinimumQuantity_beforeInsert.sql new file mode 100644 index 000000000..8833ac968 --- /dev/null +++ b/db/routines/vn/triggers/itemMinimumQuantity_beforeInsert.sql @@ -0,0 +1,8 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`itemMinimumQuantity_beforeInsert` + BEFORE INSERT ON `itemMinimumQuantity` + FOR EACH ROW +BEGIN + SET NEW.editorFk = account.myUser_getId(); +END$$ +DELIMITER ; diff --git a/db/routines/vn/triggers/itemMinimumQuantity_beforeUpdate.sql b/db/routines/vn/triggers/itemMinimumQuantity_beforeUpdate.sql new file mode 100644 index 000000000..ef030f9f9 --- /dev/null +++ b/db/routines/vn/triggers/itemMinimumQuantity_beforeUpdate.sql @@ -0,0 +1,8 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`itemMinimumQuantity_beforeUpdate` + BEFORE UPDATE ON `itemMinimumQuantity` + FOR EACH ROW +BEGIN + SET NEW.editorFk = account.myUser_getId(); +END$$ +DELIMITER ; diff --git a/db/versions/11149-silverSalal/00-firstScript.sql b/db/versions/11149-silverSalal/00-firstScript.sql index 4bb0cdb47..a53911f37 100644 --- a/db/versions/11149-silverSalal/00-firstScript.sql +++ b/db/versions/11149-silverSalal/00-firstScript.sql @@ -9,14 +9,17 @@ CREATE TABLE `vn`.`itemMinimumQuantity` ( `ended` date DEFAULT NULL, `warehouseFk` smallint(5) unsigned DEFAULT NULL, `created` timestamp NOT NULL DEFAULT current_timestamp(), + `editorFk` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `itemMinimumQuantity_UNIQUE` (`itemFk`, `started`, `ended`, `warehouseFk`), KEY `itemFk` (`itemFk`), KEY `started` (`started`), KEY `ended` (`ended`), KEY `warehouseFk` (`warehouseFk`), + KEY `editorFk` (`editorFk`), CONSTRAINT `itemMinimumQuantity_ibfk_1` FOREIGN KEY (`itemFk`) REFERENCES `item` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `itemMinimumQuantity_ibfk_2` FOREIGN KEY (`warehouseFk`) REFERENCES `warehouse` (`id`) ON UPDATE CASCADE, + CONSTRAINT `itemMinimumQuantity_ibfk_3` FOREIGN KEY (`editorFk`) REFERENCES `account`.`user` (`id`), CONSTRAINT `itemMinimumQuantity_check_1` CHECK (`started` <= `ended`) ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; diff --git a/modules/item/back/models/item-minimum-quantity.json b/modules/item/back/models/item-minimum-quantity.json index 848b42a3f..7acbb5c6f 100644 --- a/modules/item/back/models/item-minimum-quantity.json +++ b/modules/item/back/models/item-minimum-quantity.json @@ -32,6 +32,9 @@ }, "created": { "type": "date" + }, + "editorFk": { + "type": "number" } }, "relations": { diff --git a/modules/ticket/back/models/sale.js b/modules/ticket/back/models/sale.js index 34668f4ab..12cb08c16 100644 --- a/modules/ticket/back/models/sale.js +++ b/modules/ticket/back/models/sale.js @@ -88,14 +88,13 @@ module.exports = Self => { if (await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*')) return; - const now = Date.vnNew(); const minQuantity = await models.ItemMinimumQuantity.findOne({ fields: ['quantity'], where: { itemFk: itemId, - started: {lte: now}, + started: {lte: ticket.shipped}, or: [ - {ended: {gte: now}}, + {ended: {gte: ticket.shipped}}, {ended: null} ], // eslint-disable-next-line no-dupe-keys diff --git a/modules/ticket/back/models/specs/sale.spec.js b/modules/ticket/back/models/specs/sale.spec.js index b599e1092..2cb087616 100644 --- a/modules/ticket/back/models/specs/sale.spec.js +++ b/modules/ticket/back/models/specs/sale.spec.js @@ -210,6 +210,29 @@ describe('sale model ', () => { expect(e).toEqual(new Error('The price of the item changed')); } }); + + it('should throw an error if the quantity is greater than the minimum quantity of the item but is out of range', async() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true)); + + const saleId = 25; + const newQuantity = 5; + + try { + spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => { + if (sqlStatement.includes('catalog_calcFromItem')) { + sqlStatement = ` + CREATE OR REPLACE TEMPORARY TABLE tmp.ticketCalculateItem ENGINE = MEMORY SELECT ${newQuantity} as available; + CREATE OR REPLACE TEMPORARY TABLE tmp.ticketComponentPrice ENGINE = MEMORY SELECT 1 as grouping, 100000 as price;`; + params = null; + } + return models.Ticket.rawSql(sqlStatement, params, opts); + }); + + await models.Sale.updateQuantity(ctx, saleId, newQuantity, opts); + } catch (e) { + expect(e).toEqual(new Error('The amount cannot be less than the minimum')); + } + }); }); });