Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 7642_createNewState
gitea/salix/pipeline/pr-dev There was a failure building this commit Details

This commit is contained in:
Sergio De la torre 2024-07-15 12:24:58 +02:00
commit 689a88b75e
50 changed files with 782 additions and 327 deletions

View File

@ -314,5 +314,4 @@ INSERT INTO mysql.roles_mapping (`User`, `Host`, `Role`, `Admin_option`)
SELECT SUBSTR(`User`, @prefixLen + 1), `Host`, `Role`, `Admin_option` SELECT SUBSTR(`User`, @prefixLen + 1), `Host`, `Role`, `Admin_option`
FROM mysql.roles_mapping FROM mysql.roles_mapping
WHERE `User` LIKE @prefixedLike AND `Host` = @genRoleHost; WHERE `User` LIKE @prefixedLike AND `Host` = @genRoleHost;
FLUSH PRIVILEGES; FLUSH PRIVILEGES;

View File

@ -115,10 +115,13 @@ INSERT INTO `hedera`.`tpvConfig`(`id`, `currency`, `terminal`, `transactionType`
VALUES VALUES
(1, 978, 1, 0, 2000, 9, 0); (1, 978, 1, 0, 2000, 9, 0);
INSERT INTO hedera.orderConfig (`id`, `employeeFk`, `defaultAgencyFk`, `guestMethod`, `guestAgencyFk`, `reserveTime`, `defaultCompanyFk`)
VALUES (1, 1, 2, 'PICKUP', 1, '00:20:00', 442);
INSERT INTO `account`.`user`(`id`,`name`,`nickname`, `password`,`role`,`active`,`email`,`lang`, `image`) INSERT INTO `account`.`user`(`id`,`name`,`nickname`, `password`,`role`,`active`,`email`,`lang`, `image`)
VALUES VALUES
(1101, 'brucewayne', 'Bruce Wayne', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'BruceWayne@mydomain.com', 'es','1101'), (1101, 'brucewayne', 'Bruce Wayne', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'BruceWayne@mydomain.com', 'es','1101'),
(1102, 'petterparker', 'Petter Parker', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'PetterParker@mydomain.com', 'en','1102'), (1102, 'petterparker', 'Petter Parker', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 131, 1, 'PetterParker@mydomain.com', 'en','1102'),
(1103, 'clarkkent', 'Clark Kent', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'ClarkKent@mydomain.com', 'fr','1103'), (1103, 'clarkkent', 'Clark Kent', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'ClarkKent@mydomain.com', 'fr','1103'),
(1104, 'tonystark', 'Tony Stark', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'TonyStark@mydomain.com', 'es','1104'), (1104, 'tonystark', 'Tony Stark', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'TonyStark@mydomain.com', 'es','1104'),
(1105, 'maxeisenhardt', 'Max Eisenhardt', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'MaxEisenhardt@mydomain.com', 'pt','1105'), (1105, 'maxeisenhardt', 'Max Eisenhardt', '$2b$10$UzQHth.9UUQ1T5aiQJ21lOU0oVlbxoqH4PFM9V8T90KNSAcg0eEL2', 2, 1, 'MaxEisenhardt@mydomain.com', 'pt','1105'),
@ -301,6 +304,17 @@ UPDATE `vn`.`agencyMode` SET `deliveryMethodFk` = 1 WHERE `id` = 8;
UPDATE `vn`.`agencyMode` SET `deliveryMethodFk` = 4 WHERE `id` = 23; UPDATE `vn`.`agencyMode` SET `deliveryMethodFk` = 4 WHERE `id` = 23;
UPDATE `vn`.`agencyMode` SET `deliveryMethodFk` = 1 WHERE `id` = 10; UPDATE `vn`.`agencyMode` SET `deliveryMethodFk` = 1 WHERE `id` = 10;
UPDATE `vn`.`agencyMode` SET `description` = 'inhouse pickup' WHERE `id` = 1;
UPDATE `vn`.`agencyMode` SET `description` = 'Super-Man delivery' WHERE `id` = 2;
UPDATE `vn`.`agencyMode` SET `description` = 'Teleportation device' WHERE `id` = 3;
UPDATE `vn`.`agencyMode` SET `description` = 'Entanglement' WHERE `id` = 4;
UPDATE `vn`.`agencyMode` SET `description` = 'Quantum break device' WHERE `id` = 5;
UPDATE `vn`.`agencyMode` SET `description` = 'Walking' WHERE `id` = 6;
UPDATE `vn`.`agencyMode` SET `description` = 'Gotham247' WHERE `id` = 7;
UPDATE `vn`.`agencyMode` SET `description` = 'Gotham247Expensive' WHERE `id` = 8;
UPDATE `vn`.`agencyMode` SET `description` = 'Other agency' WHERE `id` = 10;
UPDATE `vn`.`agencyMode` SET `description` = 'Refund' WHERE `id` = 23;
UPDATE `vn`.`agencyMode` SET `web` = 1, `reportMail` = 'no-reply@gothamcity.com'; UPDATE `vn`.`agencyMode` SET `web` = 1, `reportMail` = 'no-reply@gothamcity.com';
UPDATE `vn`.`agencyMode` SET `code` = 'refund' WHERE `id` = 23; UPDATE `vn`.`agencyMode` SET `code` = 'refund' WHERE `id` = 23;
@ -979,6 +993,14 @@ INSERT INTO `vn`.`priceFixed`(`id`, `itemFk`, `rate0`, `rate1`, `rate2`, `rate3`
(2, 3, 10, 10, 10, 10, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), 0, 1, util.VN_CURDATE()), (2, 3, 10, 10, 10, 10, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), 0, 1, util.VN_CURDATE()),
(3, 13, 8.5, 10, 7.5, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), 1, 2, util.VN_CURDATE()); (3, 13, 8.5, 10, 7.5, 6, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), 1, 2, util.VN_CURDATE());
INSERT INTO `vn`.`itemMinimumQuantity`(`itemFk`, `quantity`, `started`, `ended`, `warehouseFk`)
VALUES
(1, 5, util.VN_CURDATE() - INTERVAL 2 MONTH, util.VN_CURDATE() + INTERVAL 1 MONTH, 1),
(2, 10, util.VN_CURDATE() - INTERVAL 2 DAY, util.VN_CURDATE() - INTERVAL 1 DAY, 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),
(4, 8, util.VN_CURDATE() - INTERVAL 3 MONTH, NULL, NULL);
INSERT INTO `vn`.`expeditionBoxVol`(`boxFk`, `m3`, `ratio`) INSERT INTO `vn`.`expeditionBoxVol`(`boxFk`, `m3`, `ratio`)
VALUES VALUES
(71,0.141,1); (71,0.141,1);
@ -1478,7 +1500,8 @@ INSERT INTO `vn`.`travel`(`id`,`shipped`, `landed`, `warehouseInFk`, `warehouseO
(5, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 3, 1, 50.00, 500, 'fifth travel', 1, 1, 5), (5, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 3, 3, 1, 50.00, 500, 'fifth travel', 1, 1, 5),
(6, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 4, 4, 1, 50.00, 500, 'sixth travel', 1, 2, 6), (6, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 4, 4, 1, 50.00, 500, 'sixth travel', 1, 2, 6),
(7, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 4, 1, 50.00, 500, 'seventh travel', 2, 1, 7), (7, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 4, 1, 50.00, 500, 'seventh travel', 2, 1, 7),
(8, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 1, 1, 50.00, 500, 'eight travel', 1, 2, 10); (8, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 1, 1, 50.00, 500, 'eight travel', 1, 2, 10),
(10, DATE_ADD(util.VN_CURDATE(), INTERVAL + 5 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 5 DAY), 5, 1, 1, 50.00, 500, 'nineth travel', 1, 2, 10);
INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `isRaid`, `evaNotes`) INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed`, `companyFk`, `invoiceNumber`, `reference`, `isExcludedFromAvailable`, `isRaid`, `evaNotes`)
VALUES VALUES
@ -1489,7 +1512,9 @@ INSERT INTO `vn`.`entry`(`id`, `supplierFk`, `created`, `travelFk`, `isConfirmed
(5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 0, 'observation five'), (5, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 5, 0, 442, 'IN2005', 'Movement 5', 0, 0, 'observation five'),
(6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 0, 'observation six'), (6, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 6, 0, 442, 'IN2006', 'Movement 6', 0, 0, 'observation six'),
(7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 0, 'observation seven'), (7, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2007', 'Movement 7', 0, 0, 'observation seven'),
(8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, 1, ''); (8, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 7, 0, 442, 'IN2008', 'Movement 8', 1, 1, ''),
(9, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, 1, ''),
(10, 2, DATE_ADD(util.VN_CURDATE(), INTERVAL +2 DAY), 10, 0, 442, 'IN2009', 'Movement 9', 1, 1, '');
INSERT INTO `bs`.`waste`(`buyer`, `year`, `week`, `family`, `itemFk`, `itemTypeFk`, `saleTotal`, `saleWaste`, `rate`) INSERT INTO `bs`.`waste`(`buyer`, `year`, `week`, `family`, `itemFk`, `itemTypeFk`, `saleTotal`, `saleWaste`, `rate`)
VALUES VALUES

View File

@ -25,12 +25,7 @@ BEGIN
JOIN vn.warehouse w ON w.id = p.warehouseFk JOIN vn.warehouse w ON w.id = p.warehouseFk
ORDER BY warehouseFk, `grouping`; ORDER BY warehouseFk, `grouping`;
DROP TEMPORARY TABLE CALL vn.ticketCalculatePurge();
tmp.ticketCalculateItem, DROP TEMPORARY TABLE tmp.item;
tmp.ticketComponentPrice,
tmp.ticketComponent,
tmp.ticketLot,
tmp.zoneGetShipped,
tmp.item;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -56,11 +56,23 @@ BEGIN
CALL util.throw ('ORDER_ROW_UNAVAILABLE'); CALL util.throw ('ORDER_ROW_UNAVAILABLE');
END IF; END IF;
SELECT IFNULL(minQuantity, 0) INTO vMinQuantity WITH itemMinQuantityPriority AS (
FROM vn.item SELECT quantity,
WHERE id = vItem; ROW_NUMBER() OVER (
PARTITION BY itemFk
ORDER BY warehouseFk IS NULL
) priority
FROM vn.itemMinimumQuantity
WHERE itemFk = vItem
AND `started` <= vShipment
AND (`ended` >= vShipment OR `ended` IS NULL)
AND (warehouseFk = vWarehouse OR warehouseFk IS NULL)
)
SELECT quantity INTO vMinQuantity
FROM itemMinQuantityPriority
WHERE priority = 1;
IF vAmount < LEAST(vMinQuantity, vAvailable) THEN IF vAmount < LEAST(IFNULL(vMinQuantity, 0), vAvailable) THEN
CALL util.throw ('quantityLessThanMin'); CALL util.throw ('quantityLessThanMin');
END IF; END IF;

View File

@ -0,0 +1,25 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`address_updateCoordinates`(
vTicketFk INT,
vLongitude INT,
vLatitude INT)
BEGIN
/**
* Actualiza las coordenadas de una dirección.
*
* @param vTicketFk Id del ticket
* @param vLongitude Longitud de la dirección
* @param vLatitude Latitud de la dirección
*/
DECLARE vAddressFK INT;
SELECT addressFK INTO vAddressFK
FROM ticket
WHERE id = vTicketFk;
UPDATE address
SET longitude = vLongitude,
latitude = vLatitude
WHERE id = vAddressFK;
END$$
DELIMITER ;

View File

@ -45,8 +45,7 @@ BEGIN
CALL catalog_componentPrepare(); CALL catalog_componentPrepare();
DROP TEMPORARY TABLE IF EXISTS tmp.ticketCalculateItem; CREATE OR REPLACE TEMPORARY TABLE tmp.ticketCalculateItem(
CREATE TEMPORARY TABLE tmp.ticketCalculateItem(
itemFk INT(11) NOT NULL, itemFk INT(11) NOT NULL,
available INT(11), available INT(11),
producer VARCHAR(50), producer VARCHAR(50),
@ -60,11 +59,11 @@ BEGIN
price DECIMAL(10,2), price DECIMAL(10,2),
priceKg DECIMAL(10,2), priceKg DECIMAL(10,2),
`grouping` INT(10) UNSIGNED, `grouping` INT(10) UNSIGNED,
minQuantity INT(10) UNSIGNED,
PRIMARY KEY `itemFk` (`itemFk`) PRIMARY KEY `itemFk` (`itemFk`)
) ENGINE = MEMORY DEFAULT CHARSET=utf8; ) ENGINE = MEMORY DEFAULT CHARSET=utf8;
OPEN cTravelTree; OPEN cTravelTree;
l: LOOP l: LOOP
SET vDone = FALSE; SET vDone = FALSE;
FETCH cTravelTree INTO vZoneFk, vWarehouseFk, vShipped; FETCH cTravelTree INTO vZoneFk, vWarehouseFk, vShipped;
@ -136,7 +135,7 @@ BEGIN
CALL vn.catalog_componentCalculate(vZoneFk, vAddressFk, vShipped, vWarehouseFk); CALL vn.catalog_componentCalculate(vZoneFk, vAddressFk, vShipped, vWarehouseFk);
INSERT INTO tmp.ticketCalculateItem ( INSERT INTO tmp.ticketCalculateItem(
itemFk, itemFk,
available, available,
producer, producer,
@ -149,9 +148,9 @@ BEGIN
origin, origin,
price, price,
priceKg, priceKg,
`grouping`) `grouping`,
SELECT minQuantity)
tl.itemFk, SELECT tl.itemFk,
SUM(tl.available) available, SUM(tl.available) available,
p.name producer, p.name producer,
i.name item, i.name item,
@ -163,7 +162,8 @@ BEGIN
o.code origin, o.code origin,
bl.price, bl.price,
bl.priceKg, bl.priceKg,
bl.`grouping` bl.`grouping`,
mq.quantity
FROM tmp.ticketLot tl FROM tmp.ticketLot tl
JOIN item i ON tl.itemFk = i.id JOIN item i ON tl.itemFk = i.id
LEFT JOIN producer p ON p.id = i.producerFk AND p.isVisible LEFT JOIN producer p ON p.id = i.producerFk AND p.isVisible
@ -179,12 +179,28 @@ BEGIN
) sub ) sub
GROUP BY itemFk GROUP BY itemFk
) bl ON bl.itemFk = tl.itemFk ) bl ON bl.itemFk = tl.itemFk
WHERE tl.zoneFk = vZoneFk AND tl.warehouseFk = vWarehouseFk LEFT JOIN (
WITH itemMinQuantityPriority AS (
SELECT itemFk,
quantity,
ROW_NUMBER() OVER (
PARTITION BY itemFk
ORDER BY warehouseFk IS NULL
) priority
FROM vn.itemMinimumQuantity
WHERE `started` <= vShipped
AND (`ended` >= vShipped OR `ended` IS NULL)
AND (warehouseFk = vWarehouseFk OR warehouseFk IS NULL)
)
SELECT itemFk, quantity
FROM itemMinQuantityPriority
WHERE priority = 1
) mq ON mq.itemFk = tl.itemFk
WHERE tl.zoneFk = vZoneFk
AND tl.warehouseFk = vWarehouseFk
GROUP BY tl.itemFk GROUP BY tl.itemFk
ON DUPLICATE KEY UPDATE available = available + VALUES(available); ON DUPLICATE KEY UPDATE available = available + VALUES(available);
END LOOP; END LOOP;
CLOSE cTravelTree; CLOSE cTravelTree;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -1,15 +1,18 @@
DELIMITER $$ DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`collection_setParking`(IN `vCollectionFk` VARCHAR(8), IN `vParkingFk` INT) CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`collection_setParking`(
proc: BEGIN vSelf INT,
vParkingFk INT
)
BEGIN
/** /**
* Aparca una colección en un parking. * Aparca una colección en un parking.
* *
* @param vCollectionFk Id de la colección * @param vSelf Id colección
* @param vParkingFk Id del parking * @param vParkingFk Id parking
*/ */
REPLACE vn.ticketParking(ticketFk, parkingFk) REPLACE ticketParking(ticketFk, parkingFk)
SELECT tc.ticketFk, vParkingFk SELECT tc.ticketFk, vParkingFk
FROM vn.ticketCollection tc FROM ticketCollection tc
WHERE tc.collectionFk = vCollectionFk; WHERE tc.collectionFk = vSelf;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -2,94 +2,84 @@ DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_getBalance`( CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_getBalance`(
vItemFk INT, vItemFk INT,
vWarehouseFk INT, vWarehouseFk INT,
vDate DATETIME vDated DATETIME
) )
BEGIN BEGIN
/** /**
* @vItemFk item a buscar * Calcula el balance de un artículo.
* @vWarehouseFk almacen donde buscar *
* @vDate Si la fecha es null, muestra el histórico desde el inventario. * @vItemFk Id de artículo
* Si la fecha no es null, muestra histórico desde la fecha de vDate. * @vWarehouseFk Id de almacén
* @vDated Fecha a calcular, si es NULL muestra el histórico desde el inventario
*/ */
DECLARE vDateInventory DATETIME; DECLARE vDateInventory DATETIME
DEFAULT (
SELECT IF(vDated, uc.mockUtcTime, c.inventoried)
FROM config c
JOIN util.config uc
);
DECLARE vSupplierInventoryFk INT
DEFAULT (SELECT supplierFk FROM inventoryConfig);
IF vDate IS NULL THEN IF NOT vSupplierInventoryFk OR NOT vDateInventory THEN
SELECT inventoried INTO vDateInventory CALL util.throw('Config variables are not set');
FROM config;
ELSE
SELECT mockUtcTime INTO vDateInventory
FROM util.config;
END IF; END IF;
CREATE OR REPLACE TEMPORARY TABLE tItemDiary( CREATE OR REPLACE TEMPORARY TABLE tItemDiary
shipped DATE, ENGINE = MEMORY
`in` INT(11),
`out` INT(11),
alertLevel INT(11),
stateName VARCHAR(20),
`name` VARCHAR(50),
reference VARCHAR(50),
origin INT(11),
clientFk INT(11),
isPicked INT(11),
isTicket TINYINT(1),
lineFk INT(11),
`order` TINYINT(3) UNSIGNED,
clientType VARCHAR(20),
claimFk INT(10) UNSIGNED,
inventorySupplierFk INT(10)
);
INSERT INTO tItemDiary
WITH entriesIn AS ( WITH entriesIn AS (
SELECT tr.landed shipped, SELECT 'entry' originType,
e.id originId,
tr.landed shipped,
b.quantity `in`, b.quantity `in`,
NULL `out`, NULL `out`,
st.alertLevel , st.alertLevel ,
st.name stateName, st.name stateName,
s.name `name`,
e.invoiceNumber reference, e.invoiceNumber reference,
e.id origin, 'supplier' entityType,
s.id clientFk, s.id entityId,
s.name entityName,
IF(st.`code` = 'DELIVERED', TRUE, FALSE) isPicked, IF(st.`code` = 'DELIVERED', TRUE, FALSE) isPicked,
FALSE isTicket, FALSE isTicket,
b.id lineFk, b.id lineFk,
NULL `order`, NULL `order`,
NULL clientType, NULL clientType,
NULL claimFk, NULL claimFk,
ec.inventorySupplierFk vSupplierInventoryFk inventorySupplierFk
FROM vn.buy b FROM vn.buy b
JOIN vn.entry e ON e.id = b.entryFk JOIN vn.entry e ON e.id = b.entryFk
JOIN vn.travel tr ON tr.id = e.travelFk JOIN vn.travel tr ON tr.id = e.travelFk
JOIN vn.supplier s ON s.id = e.supplierFk JOIN vn.supplier s ON s.id = e.supplierFk
JOIN vn.state st ON st.`code` = IF( tr.landed < util.VN_CURDATE() JOIN vn.state st ON st.`code` = IF(tr.landed < util.VN_CURDATE()
OR (util.VN_CURDATE() AND tr.isReceived), OR (util.VN_CURDATE() AND tr.isReceived),
'DELIVERED', 'DELIVERED',
'FREE') 'FREE')
JOIN vn.entryConfig ec
WHERE tr.landed >= vDateInventory WHERE tr.landed >= vDateInventory
AND vWarehouseFk = tr.warehouseInFk AND tr.warehouseInFk = vWarehouseFk
AND (s.id <> ec.inventorySupplierFk OR vDate IS NULL) AND (s.id <> vSupplierInventoryFk OR vDated IS NULL)
AND b.itemFk = vItemFk AND b.itemFk = vItemFk
AND NOT e.isExcludedFromAvailable AND NOT e.isExcludedFromAvailable
AND NOT e.isRaid AND NOT e.isRaid
), entriesOut AS ( ),
SELECT tr.shipped, entriesOut AS (
SELECT 'entry',
e.id originType,
tr.shipped,
NULL, NULL,
b.quantity, b.quantity,
st.alertLevel, st.alertLevel,
st.name stateName, st.name stateName,
s.name ,
e.invoiceNumber, e.invoiceNumber,
e.id entryFk, 'supplier' entityType,
s.id supplierFk, s.id entityId,
s.name,
IF(st.`code` = 'DELIVERED' , TRUE, FALSE), IF(st.`code` = 'DELIVERED' , TRUE, FALSE),
FALSE isTicket, FALSE isTicket,
b.id, b.id,
NULL `order`, NULL `order`,
NULL clientType, NULL clientType,
NULL claimFk, NULL claimFk,
ec.inventorySupplierFk vSupplierInventoryFk
FROM vn.buy b FROM vn.buy b
JOIN vn.entry e ON e.id = b.entryFk JOIN vn.entry e ON e.id = b.entryFk
JOIN vn.travel tr ON tr.id = e.travelFk JOIN vn.travel tr ON tr.id = e.travelFk
@ -99,23 +89,25 @@ BEGIN
OR (tr.shipped = util.VN_CURDATE() AND tr.isReceived), OR (tr.shipped = util.VN_CURDATE() AND tr.isReceived),
'DELIVERED', 'DELIVERED',
'FREE') 'FREE')
JOIN vn.entryConfig ec
WHERE tr.shipped >= vDateInventory WHERE tr.shipped >= vDateInventory
AND vWarehouseFk = tr.warehouseOutFk AND tr.warehouseOutFk = vWarehouseFk
AND (s.id <> ec.inventorySupplierFk OR vDate IS NULL) AND (s.id <> vSupplierInventoryFk OR vDated IS NULL)
AND b.itemFk = vItemFk AND b.itemFk = vItemFk
AND NOT e.isExcludedFromAvailable AND NOT e.isExcludedFromAvailable
AND NOT w.isFeedStock AND NOT w.isFeedStock
AND NOT e.isRaid AND NOT e.isRaid
), sales AS ( ),
sales AS (
WITH itemSales AS (
SELECT DATE(t.shipped) shipped, SELECT DATE(t.shipped) shipped,
s.quantity, s.quantity,
st2.alertLevel, st2.alertLevel,
st2.name, st2.name,
t.nickname,
t.refFk, t.refFk,
t.id ticketFk, t.id ticketFk,
t.clientFk, 'client' entityType,
t.clientFk entityId,
t.nickname,
s.id saleFk, s.id saleFk,
st.`order`, st.`order`,
c.typeFk, c.typeFk,
@ -123,62 +115,82 @@ BEGIN
FROM vn.sale s FROM vn.sale s
JOIN vn.ticket t ON t.id = s.ticketFk JOIN vn.ticket t ON t.id = s.ticketFk
LEFT JOIN vn.ticketState ts ON ts.ticketFk = t.id LEFT JOIN vn.ticketState ts ON ts.ticketFk = t.id
LEFT JOIN vn.state st ON st.`code` = ts.`code` LEFT JOIN vn.state st ON st.code = ts.code
JOIN vn.client c ON c.id = t.clientFk JOIN vn.client c ON c.id = t.clientFk
JOIN vn.state st2 ON st2.`code` = IF(t.shipped < util.VN_CURDATE(), JOIN vn.state st2 ON st2.`code` = IF(t.shipped < util.VN_CURDATE(),
'DELIVERED', 'DELIVERED',
IF (t.shipped > util.dayEnd(util.VN_CURDATE()), IF (t.shipped > util.dayEnd(util.VN_CURDATE()),
'FREE', 'FREE',
IFNULL(ts.code, 'FREE'))) IFNULL(st.code, 'FREE')))
LEFT JOIN vn.claimBeginning cb ON s.id = cb.saleFk LEFT JOIN vn.claimBeginning cb ON cb.saleFk = s.id
WHERE t.shipped >= vDateInventory WHERE t.shipped >= vDateInventory
AND s.itemFk = vItemFk AND s.itemFk = vItemFk
AND vWarehouseFk = t.warehouseFk AND t.warehouseFk = vWarehouseFk
),sale AS ( )
SELECT s.shipped, SELECT 'ticket',
s.ticketFk,
s.shipped,
NULL `in`, NULL `in`,
s.quantity, s.quantity,
s.alertLevel, s.alertLevel,
s.name, s.name,
s.nickname,
s.refFk, s.refFk,
s.ticketFk, s.entityType,
s.clientFk, s.entityId,
IF(stk.saleFk, TRUE, NULL), s.nickname,
IF(stk.saleFk, TRUE, FALSE),
TRUE, TRUE,
s.saleFk, s.saleFk,
s.`order`, s.`order`,
s.typeFk, s.typeFk,
s.claimFk, s.claimFk,
NULL NULL
FROM sales s FROM itemSales s
LEFT JOIN vn.state stPrep ON stPrep.`code` = 'PREPARED' LEFT JOIN vn.state stPrep ON stPrep.`code` = 'PREPARED'
LEFT JOIN vn.saleTracking stk ON stk.saleFk = s.saleFk LEFT JOIN vn.saleTracking stk ON stk.saleFk = s.saleFk
AND stk.stateFk = stPrep.id AND stk.stateFk = stPrep.id
GROUP BY s.saleFk GROUP BY s.saleFk
) SELECT shipped, ),
`in`, orders AS (
`out`, SELECT 'order' originType,
alertLevel, o.id originId,
stateName, r.shipment,
`name`, NULL 'in',
reference, r.amount,
origin, NULL alertLevel,
clientFk, NULL stateName,
isPicked, NULL invoiceNumber,
isTicket, 'client' entityType,
lineFk, c.id,
`order`, c.name,
clientType, FALSE,
claimFk, FALSE isTicket,
inventorySupplierFk NULL buyFk,
FROM entriesIn NULL 'order',
c.typeFk,
NULL claimFk,
NULL
FROM hedera.orderRow r
JOIN hedera.`order` o ON o.id = r.orderFk
JOIN vn.client c ON c.id = o.customer_id
WHERE r.shipment >= vDateInventory
AND r.warehouseFk = vWarehouseFk
AND r.created >= (
SELECT SUBTIME(util.VN_NOW(), reserveTime)
FROM hedera.orderConfig
)
AND NOT o.confirmed
AND r.itemFk = vItemFk
)
SELECT * FROM entriesIn
UNION ALL UNION ALL
SELECT * FROM entriesOut SELECT * FROM entriesOut
UNION ALL UNION ALL
SELECT * FROM sale SELECT * FROM sales
UNION ALL
SELECT * FROM orders
ORDER BY shipped, ORDER BY shipped,
(inventorySupplierFk = clientFk) DESC, (inventorySupplierFk = entityId) DESC,
alertLevel DESC, alertLevel DESC,
isTicket, isTicket,
`order` DESC, `order` DESC,
@ -186,19 +198,20 @@ BEGIN
`in` DESC, `in` DESC,
`out` DESC; `out` DESC;
IF vDate IS NULL THEN IF vDated IS NULL THEN
SET @a := 0; SET @a := 0;
SET @currentLineFk := 0; SET @currentLineFk := 0;
SET @shipped := ''; SET @shipped := '';
SELECT DATE(@shipped:= t.shipped) shipped, SELECT t.originType,
t.originId,
DATE(@shipped:= t.shipped) shipped,
t.alertLevel, t.alertLevel,
t.stateName, t.stateName,
t.origin,
t.reference, t.reference,
t.clientFk, t.entityType,
t.name, t.entityId,
t.entityName,
t.`in` invalue, t.`in` invalue,
t.`out`, t.`out`,
@a := @a + IFNULL(t.`in`, 0) - IFNULL(t.`out`, 0) balance, @a := @a + IFNULL(t.`in`, 0) - IFNULL(t.`out`, 0) balance,
@ -214,37 +227,41 @@ BEGIN
t.`order` t.`order`
FROM tItemDiary t FROM tItemDiary t
LEFT JOIN alertLevel a ON a.id = t.alertLevel; LEFT JOIN alertLevel a ON a.id = t.alertLevel;
ELSE ELSE
SELECT IFNULL(SUM(IFNULL(`in`, 0)) - SUM(IFNULL(`out`, 0)), 0) INTO @a SELECT IFNULL(SUM(IFNULL(`in`, 0)) - SUM(IFNULL(`out`, 0)), 0) INTO @a
FROM tItemDiary FROM tItemDiary
WHERE shipped < vDate; WHERE shipped < vDated;
SELECT vDate shipped, SELECT NULL originType,
0 alertLevel, NULL originId,
0 stateName, vDated shipped,
0 origin, NULL alertLevel,
'' reference, NULL stateName,
0 clientFk, NULL reference,
NULL entityType,
NULL entityId,
'Inventario calculado', 'Inventario calculado',
@a invalue, @a invalue,
NULL `out`, NULL `out`,
@a balance, @a balance,
0 lastPreparedLineFk, NULL lastPreparedLineFk,
0 isTicket, NULL isTicket,
0 lineFk, NULL lineFk,
0 isPicked, NULL isPicked,
0 clientType, NULL clientType,
0 claimFk, NULL claimFk,
NULL `order` NULL `order`
UNION ALL UNION ALL
SELECT shipped, SELECT originType,
originId,
shipped,
alertlevel, alertlevel,
stateName, stateName,
origin,
reference, reference,
clientFk, entityType,
name, `in`, entityId,
entityName,
`in`,
`out`, `out`,
@a := @a + IFNULL(`in`, 0) - IFNULL(`out`, 0), @a := @a + IFNULL(`in`, 0) - IFNULL(`out`, 0),
0, 0,
@ -255,7 +272,7 @@ BEGIN
claimFk, claimFk,
`order` `order`
FROM tItemDiary FROM tItemDiary
WHERE shipped >= vDate; WHERE shipped >= vDated;
END IF; END IF;
DROP TEMPORARY TABLE tItemDiary; DROP TEMPORARY TABLE tItemDiary;

View File

@ -63,7 +63,7 @@ BEGIN
WHEN b.groupingMode = 'grouping' THEN b.grouping WHEN b.groupingMode = 'grouping' THEN b.grouping
WHEN b.groupingMode = 'packing' THEN b.packing WHEN b.groupingMode = 'packing' THEN b.packing
ELSE 1 ELSE 1
END AS minQuantity, END minQuantity,
v.visible located, v.visible located,
b.price2 b.price2
FROM vn.item i FROM vn.item i

View File

@ -1,17 +1,25 @@
DELIMITER $$ DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`saleGroup_setParking`(IN `vSaleGroupFk` VARCHAR(8), IN `vParkingFk` INT) CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`saleGroup_setParking`(
proc: BEGIN vSaleGroupFk VARCHAR(8),
vParkingFk INT
)
BEGIN
/** /**
* Aparca una preparación previa en un parking * Aparca una preparación previa en un parking.
* *
* @param vSaleGroupFk id de la preparación previa * @param vSaleGroupFk id de la preparación previa
* @param vParkingFk id del parking * @param vParkingFk id del parking
*/ */
UPDATE vn.saleGroup sg DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
RESIGNAL;
END;
UPDATE saleGroup sg
SET sg.parkingFk = vParkingFk SET sg.parkingFk = vParkingFk
WHERE sg.id = vSaleGroupFk WHERE sg.id = vSaleGroupFk
AND sg.created >= TIMESTAMPADD(WEEK,-1,util.VN_CURDATE()); AND sg.created >= util.VN_CURDATE() - INTERVAL 1 WEEK;
CALL vn.ticket_setNextState(vn.ticket_get(vSaleGroupFk)); CALL ticket_setNextState(ticket_get(vSaleGroupFk));
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -5,14 +5,32 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`sale_setProblem`(
BEGIN BEGIN
/** /**
* Update column sale.problem with a problem code * Update column sale.problem with a problem code
*
* @param vProblemCode Code to set or unset * @param vProblemCode Code to set or unset
* @table tmp.sale(saleFk, hasProblem) * @table tmp.sale(saleFk, hasProblem)
*/ */
UPDATE sale s DECLARE vSaleFk INT;
JOIN tmp.sale ts ON ts.saleFk = s.id DECLARE vHasProblem INT;
SET s.problem = CONCAT( DECLARE vDone BOOL;
IF(ts.hasProblem, DECLARE vSaleList CURSOR FOR SELECT saleFk, hasProblem FROM tmp.sale;
CONCAT(s.problem, ',', vProblemCode), DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
REPLACE(s.problem, vProblemCode , '')));
OPEN vSaleList;
l: LOOP
SET vDone = FALSE;
FETCH vSaleList INTO vSaleFk, vHasProblem;
IF vDone THEN
LEAVE l;
END IF;
UPDATE sale
SET problem = CONCAT(
IF(vHasProblem,
CONCAT(problem, ',', vProblemCode),
REPLACE(problem, vProblemCode , '')))
WHERE id = vSaleFk;
END LOOP;
CLOSE vSaleList;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -1,6 +1,9 @@
DELIMITER $$ DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`setParking`(IN `vParam` VARCHAR(8), IN `vParkingCode` VARCHAR(8)) CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`setParking`(
proc: BEGIN vParam VARCHAR(8),
vParkingCode VARCHAR(8)
)
BEGIN
/** /**
* Aparca una colección, un ticket, un saleGroup o un shelving en un parking * Aparca una colección, un ticket, un saleGroup o un shelving en un parking
* *
@ -8,56 +11,41 @@ proc: BEGIN
* @param vParkingCode código del parking * @param vParkingCode código del parking
*/ */
DECLARE vParkingFk INT; DECLARE vParkingFk INT;
DECLARE vIsSaleGroup BOOL; DECLARE vLastWeek DATE;
DECLARE vIsTicket BOOL;
DECLARE vIsCollection BOOL;
SET vParkingCode = replace(vParkingCode,' ',''); DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
SET vParkingCode = REPLACE(vParkingCode, ' ', '');
SELECT id INTO vParkingFk SELECT id INTO vParkingFk
FROM vn.parking FROM parking
WHERE code = vParkingCode COLLATE utf8_unicode_ci; WHERE code = vParkingCode COLLATE utf8_unicode_ci;
IF vParkingFk IS NULL THEN IF vParkingFk IS NULL THEN
CALL util.throw('parkingNotExist'); CALL util.throw('parkingNotExist');
LEAVE proc;
END IF; END IF;
IF vParam REGEXP '^[0-9]+$' THEN START TRANSACTION;
-- Se comprueba si es una preparación previa
SELECT COUNT(*) INTO vIsSaleGroup
FROM vn.saleGroup sg
WHERE sg.id = vParam;
IF vIsSaleGroup THEN SET vLastWeek = util.VN_CURDATE() - INTERVAL 1 WEEK;
CALL vn.saleGroup_setParking(vParam, vParkingFk);
LEAVE proc;
END IF;
-- Se comprueba si es un ticket -- Comprobamos si es una prep. previa, ticket, colección o shelving
SELECT COUNT(*) INTO vIsTicket IF (SELECT TRUE FROM saleGroup WHERE id = vParam) THEN
FROM vn.ticket t CALL saleGroup_setParking(vParam, vParkingFk);
WHERE t.id = vParam ELSEIF (SELECT TRUE FROM ticket WHERE id = vParam AND shipped >= vLastWeek) THEN
AND t.shipped >= TIMESTAMPADD(WEEK,-1,util.VN_CURDATE()); CALL ticket_setParking(vParam, vParkingFk);
ELSEIF (SELECT TRUE FROM `collection` WHERE id = vParam AND created >= vLastWeek) THEN
IF vIsTicket THEN CALL collection_setParking(vParam, vParkingFk);
CALL vn.ticket_setParking(vParam, vParkingFk); ELSEIF (SELECT TRUE FROM shelving WHERE code = vParam COLLATE utf8_unicode_ci) THEN
LEAVE proc; CALL shelving_setParking(vParam, vParkingFk);
END IF;
-- Se comprueba si es una coleccion de tickets
SELECT COUNT(*) INTO vIsCollection
FROM vn.collection c
WHERE c.id = vParam
AND c.created >= TIMESTAMPADD(WEEK,-1,util.VN_CURDATE());
IF vIsCollection THEN
CALL vn.collection_setParking(vParam, vParkingFk);
LEAVE proc;
END IF;
ELSE ELSE
-- Por descarte, se considera una matrícula CALL util.throw('paramNotExist');
CALL vn.shelving_setParking(vParam, vParkingFk);
END IF; END IF;
COMMIT;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -1,14 +1,21 @@
DELIMITER $$ DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_setNextState`(vSelf INT) CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_setNextState`(
vSelf INT
)
BEGIN BEGIN
/** /**
* Cambia el estado del ticket al siguiente estado según la tabla state * Cambia el estado del ticket al siguiente estado según la tabla state.
* *
* @param vSelf id dle ticket * @param vSelf Id ticket
*/ */
DECLARE vStateFk INT; DECLARE vStateFk INT;
DECLARE vNewStateFk INT; DECLARE vNewStateFk INT;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
RESIGNAL;
END;
SELECT stateFk INTO vStateFk SELECT stateFk INTO vStateFk
FROM ticketState FROM ticketState
WHERE ticketFk = vSelf; WHERE ticketFk = vSelf;
@ -17,6 +24,10 @@ BEGIN
FROM state FROM state
WHERE id = vStateFk; WHERE id = vStateFk;
IF vNewStateFk IS NULL THEN
CALL util.throw('The ticket not have next state');
END IF;
INSERT INTO ticketTracking(stateFk, ticketFk, userFk) INSERT INTO ticketTracking(stateFk, ticketFk, userFk)
VALUES (vNewStateFk, vSelf, account.myUser_getId()); VALUES (vNewStateFk, vSelf, account.myUser_getId());
END$$ END$$

View File

@ -1,11 +1,14 @@
DELIMITER $$ DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_setParking`(IN `vTicketFk` VARCHAR(8), IN `vParkingFk` INT) CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_setParking`(
proc: BEGIN vSelf INT,
vParkingFk INT
)
BEGIN
/** /**
* Aparca un ticket en un parking * Aparca un ticket en un parking.
* *
* @param vTicketFk id del ticket * @param vSelf Id ticket
* @param vParkingFk id del parking * @param vParkingFk Id parking
*/ */
DECLARE vDone INT DEFAULT FALSE; DECLARE vDone INT DEFAULT FALSE;
DECLARE vCollectionTicketFk INT; DECLARE vCollectionTicketFk INT;
@ -14,16 +17,21 @@ proc: BEGIN
FROM ticket t FROM ticket t
LEFT JOIN ticketCollection tc1 ON tc1.ticketFk = t.id LEFT JOIN ticketCollection tc1 ON tc1.ticketFk = t.id
LEFT JOIN ticketCollection tc2 ON tc2.collectionFk = tc1.collectionFk LEFT JOIN ticketCollection tc2 ON tc2.collectionFk = tc1.collectionFk
WHERE t.id = vTicketFk; WHERE t.id = vSelf;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
RESIGNAL;
END;
INSERT INTO vn.ticketParking(ticketFk, parkingFk) INSERT INTO vn.ticketParking(ticketFk, parkingFk)
SELECT IFNULL(tc2.ticketFk, t.id), vParkingFk SELECT IFNULL(tc2.ticketFk, t.id), vParkingFk
FROM ticket t FROM ticket t
LEFT JOIN ticketCollection tc1 ON tc1.ticketFk = t.id LEFT JOIN ticketCollection tc1 ON tc1.ticketFk = t.id
LEFT JOIN ticketCollection tc2 ON tc2.collectionFk = tc1.collectionFk LEFT JOIN ticketCollection tc2 ON tc2.collectionFk = tc1.collectionFk
WHERE t.id = vTicketFk WHERE t.id = vSelf
ON DUPLICATE KEY UPDATE parkingFk = vParkingFk; ON DUPLICATE KEY UPDATE parkingFk = vParkingFk;
OPEN vCursor; OPEN vCursor;

View File

@ -9,11 +9,28 @@ BEGIN
* @param vProblemCode Code to set or unset * @param vProblemCode Code to set or unset
* @table tmp.ticket(ticketFk, hasProblem) * @table tmp.ticket(ticketFk, hasProblem)
*/ */
UPDATE ticket t DECLARE vTicketFk INT;
JOIN tmp.ticket tt ON tt.ticketFk = t.id DECLARE vHasProblem INT;
SET t.problem = CONCAT( DECLARE vDone BOOL;
IF(tt.hasProblem, DECLARE vTicketList CURSOR FOR SELECT ticketFk, hasProblem FROM tmp.ticket;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
OPEN vTicketList;
l: LOOP
SET vDone = FALSE;
FETCH vTicketList INTO vTicketFk, vHasProblem;
IF vDone THEN
LEAVE l;
END IF;
UPDATE ticket
SET problem = CONCAT(
IF(vHasProblem,
CONCAT(problem, ',', vProblemCode), CONCAT(problem, ',', vProblemCode),
REPLACE(problem, vProblemCode , ''))); REPLACE(problem, vProblemCode , '')))
WHERE id = vTicketFk;
END LOOP;
CLOSE vTicketList;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -3,18 +3,11 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`delivery_beforeInsert
BEFORE INSERT ON `delivery` BEFORE INSERT ON `delivery`
FOR EACH ROW FOR EACH ROW
BEGIN BEGIN
IF (NEW.longitude IS NOT NULL
IF (NEW.longitude IS NOT NULL AND NEW.latitude IS NOT NULL AND NEW.ticketFK IS NOT NULL) AND NEW.latitude IS NOT NULL
AND NEW.ticketFK IS NOT NULL)
THEN THEN
UPDATE address CALL address_updateCoordinates(NEW.ticketFk, NEW.longitude, NEW.latitude);
SET longitude = NEW.longitude,
latitude = NEW.latitude
WHERE id IN (
SELECT addressFK
FROM ticket
WHERE id = NEW.ticketFk
);
END IF; END IF;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -3,18 +3,11 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`delivery_beforeUpdate
BEFORE UPDATE ON `delivery` BEFORE UPDATE ON `delivery`
FOR EACH ROW FOR EACH ROW
BEGIN BEGIN
IF (NEW.longitude IS NOT NULL
IF (NEW.longitude IS NOT NULL AND NEW.latitude IS NOT NULL AND NEW.ticketFK IS NOT NULL) AND NEW.latitude IS NOT NULL
AND NEW.ticketFK IS NOT NULL)
THEN THEN
UPDATE address CALL address_updateCoordinates(NEW.ticketFk, NEW.longitude, NEW.latitude);
SET longitude = NEW.longitude,
latitude = NEW.latitude
WHERE id IN (
SELECT addressFK
FROM ticket
WHERE id = NEW.ticketFk
);
END IF; END IF;
END$$ END$$
DELIMITER ; DELIMITER ;

View File

@ -0,0 +1,12 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`itemMinimumQuantity_afterDelete`
AFTER DELETE ON `itemMinimumQuantity`
FOR EACH ROW
BEGIN
INSERT INTO itemLog
SET `action` = 'delete',
`changedModel` = 'ItemMinimumQuantity',
`changedModelId` = OLD.id,
`userFk` = account.myUser_getId();
END$$
DELIMITER ;

View File

@ -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 ;

View File

@ -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 ;

View File

@ -1,5 +1,5 @@
DELIMITER $$ DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`itemShelving _afterDelete` CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`itemShelving_afterDelete`
AFTER DELETE ON `itemShelving` AFTER DELETE ON `itemShelving`
FOR EACH ROW FOR EACH ROW
BEGIN BEGIN

View File

@ -0,0 +1,12 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`productionConfig_afterDelete`
AFTER DELETE ON `productionConfig`
FOR EACH ROW
BEGIN
INSERT INTO productionConfig
SET `action` = 'delete',
`changedModel` = 'ProductionConfig',
`changedModelId` = OLD.id,
`userFk` = account.myUser_getId();
END$$
DELIMITER ;

View File

@ -0,0 +1,8 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`productionConfig_beforeInsert`
BEFORE INSERT ON `productionConfig`
FOR EACH ROW
BEGIN
SET NEW.editorFk = account.myUser_getId();
END$$
DELIMITER ;

View File

@ -0,0 +1,8 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`productionConfig_beforeUpdate`
BEFORE UPDATE ON `productionConfig`
FOR EACH ROW
BEGIN
SET NEW.editorFk = account.myUser_getId();
END$$
DELIMITER ;

View File

@ -54,8 +54,7 @@ AS SELECT `b`.`entryFk` AS `Id_Entrada`,
`i`.`packingOut` AS `packingOut`, `i`.`packingOut` AS `packingOut`,
`b`.`itemOriginalFk` AS `itemOriginalFk`, `b`.`itemOriginalFk` AS `itemOriginalFk`,
`io`.`longName` AS `itemOriginalName`, `io`.`longName` AS `itemOriginalName`,
`it`.`gramsMax` AS `gramsMax`, `it`.`gramsMax` AS `gramsMax`
`i`.`minQuantity` AS `minQuantity`
FROM ( FROM (
( (
( (

View File

@ -0,0 +1,23 @@
ALTER TABLE vn.productionConfig
ADD editorFk int(10) unsigned DEFAULT NULL NULL;
ALTER TABLE vn.productionConfig
ADD CONSTRAINT productionConfig_user_FK FOREIGN KEY (editorFk) REFERENCES account.`user`(id);
CREATE OR REPLACE TABLE `vn`.`productionConfigLog` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`originFk` int(11) DEFAULT NULL,
`userFk` int(10) unsigned DEFAULT NULL,
`action` set('insert','update','delete','select') NOT NULL,
`creationDate` timestamp NULL DEFAULT current_timestamp(),
`description` text CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL,
`changedModel` enum('ProductionConfig') NOT NULL DEFAULT 'ProductionConfig',
`oldInstance` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`oldInstance`)),
`newInstance` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`newInstance`)),
`changedModelId` int(11) NOT NULL,
`changedModelValue` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `productionConfigLog_userFk` (`userFk`),
KEY `productionConfigLog_changedModel` (`changedModel`,`changedModelId`,`creationDate`),
KEY `productionConfigLog_originFk` (`originFk`,`creationDate`),
CONSTRAINT `productionConfigUserFk` FOREIGN KEY (`userFk`) REFERENCES `account`.`user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;

View File

@ -0,0 +1 @@
CREATE INDEX travel_landed_IDX USING BTREE ON vn.travel (landed DESC,warehouseInFk,warehouseOutFk);

View File

@ -0,0 +1,30 @@
ALTER TABLE vn.item CHANGE minQuantity minQuantity__ int(10) unsigned DEFAULT
NULL NULL COMMENT '@deprecated 2024-07-11 refs #7704 Cantidad mínima para una línea de venta';
CREATE TABLE `vn`.`itemMinimumQuantity` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`itemFk` int(10) NOT NULL,
`quantity` int(10) NOT NULL,
`started` date NOT NULL,
`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;
GRANT SELECT, UPDATE, DELETE, INSERT ON TABLE vn.itemMinimumQuantity TO buyer;
GRANT EXECUTE ON PROCEDURE vn.ticketCalculatePurge TO guest;
ALTER TABLE vn.itemLog MODIFY COLUMN changedModel enum('Item','ItemBarcode','ItemBotanical','ItemNiche','ItemTag','ItemTaxCountry','ItemMinimumQuantity')
CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT 'Item' NOT NULL;

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.itemMinimumQuantity
ADD CONSTRAINT itemMinimumQuantity_check CHECK (quantity > 0);

View File

@ -1,4 +1,3 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const buildFilter = require('vn-loopback/util/filter').buildFilter; const buildFilter = require('vn-loopback/util/filter').buildFilter;
const mergeFilters = require('vn-loopback/util/filter').mergeFilters; const mergeFilters = require('vn-loopback/util/filter').mergeFilters;
@ -95,6 +94,11 @@ module.exports = Self => {
arg: 'to', arg: 'to',
type: 'date', type: 'date',
description: `The to date filter` description: `The to date filter`
},
{
arg: 'days',
type: 'number',
description: `N days interval`
} }
], ],
returns: { returns: {
@ -192,6 +196,15 @@ module.exports = Self => {
JOIN vn.currency cu ON cu.id = e.currencyFk` JOIN vn.currency cu ON cu.id = e.currencyFk`
); );
if (ctx.args.days) {
stmt.merge({
sql: `
AND t.shipped <= util.VN_CURDATE() + INTERVAL ? DAY
AND t.shipped >= util.VN_CURDATE()
`,
params: [ctx.args.days]
});
}
stmt.merge(conn.makeSuffix(filter)); stmt.merge(conn.makeSuffix(filter));
const itemsIndex = stmts.push(stmt) - 1; const itemsIndex = stmts.push(stmt) - 1;

View File

@ -39,7 +39,7 @@ describe('Entry filter()', () => {
const result = await models.Entry.filter(ctx, options); const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(9); expect(result.length).toEqual(11);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -55,13 +55,13 @@ describe('Entry filter()', () => {
try { try {
const ctx = { const ctx = {
args: {}, args: {days: 6},
req: {accessToken: {userId: 1102}} req: {accessToken: {userId: 1102}}
}; };
const result = await models.Entry.filter(ctx, options); const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(6); expect(result.length).toEqual(2);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -84,7 +84,7 @@ describe('Entry filter()', () => {
const result = await models.Entry.filter(ctx, options); const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(6); expect(result.length).toEqual(8);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -107,7 +107,7 @@ describe('Entry filter()', () => {
const result = await models.Entry.filter(ctx, options); const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(6); expect(result.length).toEqual(8);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -131,7 +131,7 @@ describe('Entry filter()', () => {
const result = await models.Entry.filter(ctx, options); const result = await models.Entry.filter(ctx, options);
expect(result.length).toEqual(8); expect(result.length).toEqual(10);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -61,7 +61,7 @@ describe('item getBalance()', () => {
const secondItemBalance = await models.Item.getBalance(ctx, secondFilter, options); const secondItemBalance = await models.Item.getBalance(ctx, secondFilter, options);
expect(firstItemBalance[9].claimFk).toEqual(null); expect(firstItemBalance[9].claimFk).toEqual(null);
expect(secondItemBalance[7].claimFk).toEqual(2); expect(secondItemBalance[7].claimFk).toEqual(1);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {

View File

@ -32,6 +32,9 @@
"ItemLog": { "ItemLog": {
"dataSource": "vn" "dataSource": "vn"
}, },
"ItemMinimumQuantity": {
"dataSource": "vn"
},
"ItemPackingType": { "ItemPackingType": {
"dataSource": "vn" "dataSource": "vn"
}, },

View File

@ -0,0 +1,63 @@
{
"name": "ItemMinimumQuantity",
"base": "VnModel",
"options": {
"mysql": {
"table": "itemMinimumQuantity"
}
},
"mixins": {
"Loggable": true
},
"properties": {
"id": {
"type": "number",
"id": true,
"description": "Id"
},
"itemFk": {
"type": "number",
"required": true
},
"quantity": {
"type": "number",
"required": true
},
"started": {
"type": "date",
"required": true
},
"ended": {
"type": "date"
},
"warehouseFk": {
"type": "number"
},
"created": {
"type": "date"
},
"editorFk": {
"type": "number"
}
},
"relations": {
"item": {
"type": "belongsTo",
"model": "Item",
"foreignKey": "itemFk"
},
"warehouse": {
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk"
}
},
"acls": [
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "buyer",
"permission": "ALLOW"
}
]
}

View File

@ -152,10 +152,6 @@
"columnName": "doPhoto" "columnName": "doPhoto"
} }
}, },
"minQuantity": {
"type": "number",
"description": "Min quantity"
},
"photoMotivation": { "photoMotivation": {
"type": "string" "type": "string"
} }

View File

@ -0,0 +1,101 @@
const {models} = require('vn-loopback/server/server');
describe('itemMinimumQuantity model', () => {
const itemFk = 5;
const warehouseFk = 60;
beforeAll(async() => {
await models.ItemMinimumQuantity.destroyAll({where: {itemFk: itemFk}});
});
describe('CRUD operations', () => {
it('should create a new itemMinimumQuantity record', async() => {
const newRecord = {
itemFk: itemFk,
quantity: 100,
started: Date.vnNew(),
ended: new Date(Date.vnNew().setFullYear(Date.vnNew().getFullYear() + 1)),
warehouseFk: warehouseFk
};
const createdRecord = await models.ItemMinimumQuantity.create(newRecord);
expect(createdRecord).toBeDefined();
expect(createdRecord.quantity).toEqual(newRecord.quantity);
});
it('should read an existing itemMinimumQuantity record', async() => {
const newRecord = {
itemFk: itemFk,
quantity: 100,
started: Date.vnNew(),
ended: new Date(Date.vnNew().setFullYear(Date.vnNew().getFullYear() + 2)),
warehouseFk: warehouseFk
};
await models.ItemMinimumQuantity.create(newRecord);
const existingRecord = await models.ItemMinimumQuantity.findOne({where: {itemFk: itemFk}});
expect(existingRecord).toBeDefined();
expect(existingRecord.itemFk).toEqual(itemFk);
});
it('should update an existing itemMinimumQuantity record', async() => {
const newRecord = {
itemFk: itemFk,
quantity: 100,
started: Date.vnNew(),
ended: new Date(Date.vnNew().setFullYear(Date.vnNew().getFullYear() + 3)),
warehouseFk: warehouseFk
};
await models.ItemMinimumQuantity.create(newRecord);
const newQuantity = 150;
const existingRecord = await models.ItemMinimumQuantity.findOne({where: {itemFk: itemFk}});
existingRecord.quantity = newQuantity;
await existingRecord.save();
const updatedRecord = await models.ItemMinimumQuantity.findOne({where: {itemFk: itemFk}});
expect(updatedRecord.quantity).toEqual(newQuantity);
});
});
describe('validation and constraints', () => {
it('should enforce unique constraint on itemFk, started, ended, and warehouseFk', async() => {
const newRecord = {
itemFk: itemFk,
quantity: 100,
started: Date.vnNew(),
ended: Date.vnNew().setFullYear(Date.vnNew().getFullYear() + 5),
warehouseFk: warehouseFk
};
try {
await models.ItemMinimumQuantity.create(newRecord);
await models.ItemMinimumQuantity.create(newRecord);
} catch (e) {
expect(e).toBeDefined();
expect(e.code).toContain('ER_DUP_ENTRY');
}
});
it('should allow null values for ended and warehouseFk', async() => {
const newRecord = {
itemFk: itemFk,
quantity: 100,
started: Date.vnNew(),
ended: null,
warehouseFk: null
};
const createdRecord = await models.ItemMinimumQuantity.create(newRecord);
expect(createdRecord).toBeDefined();
expect(createdRecord.ended).toBeNull();
expect(createdRecord.warehouseFk).toBeNull();
});
});
});

View File

@ -128,9 +128,6 @@
<vn-label-value label="Non recycled plastic" <vn-label-value label="Non recycled plastic"
value="{{$ctrl.summary.item.nonRecycledPlastic}}"> value="{{$ctrl.summary.item.nonRecycledPlastic}}">
</vn-label-value> </vn-label-value>
<vn-label-value label="Minimum sales quantity"
value="{{$ctrl.summary.item.minQuantity}}">
</vn-label-value>
</vn-one> </vn-one>
<vn-one name="tags"> <vn-one name="tags">
<h4 ng-show="$ctrl.isBuyer || $ctrl.isReplenisher"> <h4 ng-show="$ctrl.isBuyer || $ctrl.isReplenisher">

View File

@ -119,7 +119,7 @@ module.exports = Self => {
w.firstName, w.firstName,
tci.priceKg, tci.priceKg,
ink.hex, ink.hex,
i.minQuantity tci.minQuantity
FROM tmp.ticketCalculateItem tci FROM tmp.ticketCalculateItem tci
JOIN vn.item i ON i.id = tci.itemFk JOIN vn.item i ON i.id = tci.itemFk
JOIN vn.itemType it ON it.id = i.typeFk JOIN vn.itemType it ON it.id = i.typeFk
@ -158,21 +158,19 @@ module.exports = Self => {
// Apply item prices // Apply item prices
const pricesIndex = stmts.push( const pricesIndex = stmts.push(
`SELECT `SELECT tcp.itemFk,
tcp.itemFk,
tcp.grouping, tcp.grouping,
tcp.price, tcp.price,
tcp.rate, tcp.rate,
tcp.warehouseFk, tcp.warehouseFk,
tcp.priceKg, tcp.priceKg,
w.name AS warehouse w.name warehouse
FROM tmp.ticketComponentPrice tcp FROM tmp.ticketComponentPrice tcp
JOIN vn.warehouse w ON w.id = tcp.warehouseFk`) - 1; JOIN vn.warehouse w ON w.id = tcp.warehouseFk`) - 1;
// Get tags from all items // Get tags from all items
const itemTagsIndex = stmts.push( const itemTagsIndex = stmts.push(
`SELECT `SELECT t.id,
t.id,
t.name, t.name,
t.isFree, t.isFree,
t.sourceTable, t.sourceTable,

View File

@ -1,2 +1 @@
Order created: Orden creada Order created: Orden creada
Minimal quantity: Cantidad mínima

View File

@ -70,7 +70,7 @@ module.exports = Self => {
quantity: quantity quantity: quantity
}, myOptions); }, myOptions);
await Self.rawSql('CALL vn.sale_calculateComponent(?, NULL)', [newSale.id], myOptions); await Self.rawSql('CALL vn.sale_calculateComponent(?, ?)', [newSale.id, 'renewPrices'], myOptions);
await Self.rawSql('CALL vn.ticket_recalc(?, NULL)', [id], myOptions); await Self.rawSql('CALL vn.ticket_recalc(?, NULL)', [id], myOptions);
const sale = await models.Sale.findById(newSale.id, { const sale = await models.Sale.findById(newSale.id, {

View File

@ -65,7 +65,7 @@ module.exports = Self => {
throw new UserError('You can only add negative amounts in refund tickets'); throw new UserError('You can only add negative amounts in refund tickets');
const item = await models.Item.findOne({ const item = await models.Item.findOne({
fields: ['family', 'minQuantity'], fields: ['family'],
where: {id: itemId}, where: {id: itemId},
}, ctx.options); }, ctx.options);
if (item.family == 'EMB') return; if (item.family == 'EMB') return;
@ -88,7 +88,30 @@ module.exports = Self => {
if (await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*')) return; if (await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*')) return;
if (newQuantity < item.minQuantity && newQuantity != available) const itemMinimalQuantity = await models.ItemMinimumQuantity.find({
fields: ['quantity', 'warehouseFk'],
where: {
itemFk: itemId,
started: {lte: ticket.shipped},
or: [
{ended: {gte: ticket.shipped}},
{ended: null}
],
// eslint-disable-next-line no-dupe-keys
or: [
{warehouseFk: ticket.warehouseFk},
{warehouseFk: null}
]
},
}, ctx.options);
const minQuantity = itemMinimalQuantity.reduce((selected, item) => {
if (item.warehouseFk === ticket.warehouseFk) return item;
if (item.warehouseFk === null && !selected) return item;
return selected;
}, null);
if (newQuantity < minQuantity?.quantity && newQuantity != available)
throw new UserError('The amount cannot be less than the minimum'); throw new UserError('The amount cannot be less than the minimum');
if (ctx.isNewInstance || isReduction) return; if (ctx.isNewInstance || isReduction) return;
@ -114,4 +137,3 @@ module.exports = Self => {
throw new UserError('The price of the item changed'); throw new UserError('The price of the item changed');
}); });
}; };

View File

@ -112,14 +112,10 @@ describe('sale model ', () => {
it('should throw an error if the quantity is less than the minimum quantity of the item', async() => { it('should throw an error if the quantity is less than the minimum quantity of the item', async() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true)); spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true));
const itemId = 2;
const saleId = 17; const saleId = 17;
const minQuantity = 30; const newQuantity = 1;
const newQuantity = minQuantity - 1;
try { try {
const item = await models.Item.findById(itemId, null, opts);
await item.updateAttribute('minQuantity', minQuantity, opts);
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => { spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => {
if (sqlStatement.includes('catalog_calcFromItem')) { if (sqlStatement.includes('catalog_calcFromItem')) {
sqlStatement = `CREATE OR REPLACE TEMPORARY TABLE tmp.ticketCalculateItem ENGINE = MEMORY sqlStatement = `CREATE OR REPLACE TEMPORARY TABLE tmp.ticketCalculateItem ENGINE = MEMORY
@ -138,13 +134,8 @@ describe('sale model ', () => {
it('should change quantity if has minimum quantity and new quantity is equal than item available', async() => { it('should change quantity if has minimum quantity and new quantity is equal than item available', async() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true)); spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true));
const itemId = 2;
const saleId = 17; const saleId = 17;
const minQuantity = 30; const newQuantity = 8;
const newQuantity = minQuantity - 1;
const item = await models.Item.findById(itemId, null, opts);
await item.updateAttribute('minQuantity', minQuantity, opts);
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => { spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => {
if (sqlStatement.includes('catalog_calcFromItem')) { if (sqlStatement.includes('catalog_calcFromItem')) {
@ -162,13 +153,9 @@ describe('sale model ', () => {
it('should increase quantity if you have enough available and the new price is the same as the previous one', async() => { it('should increase quantity if you have enough available and the new price is the same as the previous one', async() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true)); spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true));
const itemId = 2;
const saleId = 17; const saleId = 17;
const minQuantity = 30;
const newQuantity = 31; const newQuantity = 31;
const item = await models.Item.findById(itemId, null, opts);
await item.updateAttribute('minQuantity', minQuantity, opts);
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => { spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => {
if (sqlStatement.includes('catalog_calcFromItem')) { if (sqlStatement.includes('catalog_calcFromItem')) {
sqlStatement = ` sqlStatement = `
@ -185,13 +172,9 @@ describe('sale model ', () => {
it('should increase quantity when the new price is lower than the previous one', async() => { it('should increase quantity when the new price is lower than the previous one', async() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true)); spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true));
const itemId = 2;
const saleId = 17; const saleId = 17;
const minQuantity = 30;
const newQuantity = 31; const newQuantity = 31;
const item = await models.Item.findById(itemId, null, opts);
await item.updateAttribute('minQuantity', minQuantity, opts);
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => { spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => {
if (sqlStatement.includes('catalog_calcFromItem')) { if (sqlStatement.includes('catalog_calcFromItem')) {
sqlStatement = ` sqlStatement = `
@ -208,14 +191,10 @@ describe('sale model ', () => {
it('should throw error when increase quantity and the new price is higher than the previous one', async() => { it('should throw error when increase quantity and the new price is higher than the previous one', async() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true)); spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true));
const itemId = 2;
const saleId = 17; const saleId = 17;
const minQuantity = 30;
const newQuantity = 31; const newQuantity = 31;
try { try {
const item = await models.Item.findById(itemId, null, opts);
await item.updateAttribute('minQuantity', minQuantity, opts);
spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => { spyOn(models.Sale, 'rawSql').and.callFake((sqlStatement, params, opts) => {
if (sqlStatement.includes('catalog_calcFromItem')) { if (sqlStatement.includes('catalog_calcFromItem')) {
sqlStatement = ` sqlStatement = `
@ -231,6 +210,48 @@ describe('sale model ', () => {
expect(e).toEqual(new Error('The price of the item changed')); expect(e).toEqual(new Error('The price of the item changed'));
} }
}); });
it('should throw an error if the quantity is lower than the minimum quantity of the item and is in 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'));
}
});
it('should update the quantity if the quantity is lower than the minimum quantity of the item and is out of the range', async() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getCtx(employeeId, true));
const saleId = 17;
const newQuantity = 8;
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);
});
}); });
}); });

View File

@ -79,7 +79,7 @@ describe('Travel extraCommunityFilter()', () => {
const result = await app.models.Travel.extraCommunityFilter(ctx, filter); const result = await app.models.Travel.extraCommunityFilter(ctx, filter);
expect(result.length).toEqual(8); expect(result.length).toEqual(9);
}); });
it('should return the travel matching "cargoSupplierFk"', async() => { it('should return the travel matching "cargoSupplierFk"', async() => {
@ -110,6 +110,6 @@ describe('Travel extraCommunityFilter()', () => {
const result = await app.models.Travel.extraCommunityFilter(ctx, filter); const result = await app.models.Travel.extraCommunityFilter(ctx, filter);
expect(result.length).toEqual(1); expect(result.length).toEqual(2);
}); });
}); });

View File

@ -50,7 +50,7 @@ describe('Travel filter()', () => {
const result = await app.models.Travel.filter(ctx); const result = await app.models.Travel.filter(ctx);
expect(result.length).toEqual(5); expect(result.length).toEqual(6);
}); });
it('should return the routes matching "shipped from" and "shipped to"', async() => { it('should return the routes matching "shipped from" and "shipped to"', async() => {
@ -80,6 +80,6 @@ describe('Travel filter()', () => {
const result = await app.models.Travel.filter(ctx); const result = await app.models.Travel.filter(ctx);
expect(result.length).toEqual(5); expect(result.length).toEqual(6);
}); });
}); });

View File

@ -19,7 +19,7 @@
<td id="outline" class="ellipsize">{{dashIfEmpty(labelData.workerCode)}}</td> <td id="outline" class="ellipsize">{{dashIfEmpty(labelData.workerCode)}}</td>
</tr> </tr>
<tr> <tr>
<td id="outline" class="ellipsize">{{labelData.labelCount || 0}}</td> <td id="outline" class="ellipsize">{{labelCount || labelData.labelCount || 0}}</td>
</tr> </tr>
<tr> <tr>
<td id="outline" class="ellipsize">{{labelData.code == 'V' ? (labelData.size || 0) + 'cm' : (labelData.volume || 0) + 'm³'}}</td> <td id="outline" class="ellipsize">{{labelData.code == 'V' ? (labelData.size || 0) + 'cm' : (labelData.volume || 0) + 'm³'}}</td>

View File

@ -104,7 +104,7 @@
<tr> <tr>
<td width="5%">{{sale.itemFk}}</td> <td width="5%">{{sale.itemFk}}</td>
<td class="number">{{sale.quantity}}</td> <td class="number">{{sale.quantity}}</td>
<td width="50%">{{sale.concept}}</td> <td width="50%">{{sale.concept}} <span class="font light-gray">{{sale.subName}}</span></td>
<td class="number">{{sale.price | currency('EUR', $i18n.locale)}}</td> <td class="number">{{sale.price | currency('EUR', $i18n.locale)}}</td>
<td class="centered" width="5%">{{(sale.discount / 100) | percentage}}</td> <td class="centered" width="5%">{{(sale.discount / 100) | percentage}}</td>
<td class="centered">{{sale.vatType}}</td> <td class="centered">{{sale.vatType}}</td>

View File

@ -35,3 +35,4 @@ observations: Observaciones
wireTransfer: "Forma de pago: Transferencia" wireTransfer: "Forma de pago: Transferencia"
accountNumber: "Número de cuenta: {0}" accountNumber: "Número de cuenta: {0}"
services: Servicios services: Servicios

View File

@ -8,7 +8,8 @@ SELECT
s.itemFk, s.itemFk,
s.concept, s.concept,
tc.code vatType, tc.code vatType,
it.isPackaging it.isPackaging,
i.subName
FROM vn.invoiceOut io FROM vn.invoiceOut io
JOIN vn.ticket t ON t.refFk = io.ref JOIN vn.ticket t ON t.refFk = io.ref
JOIN vn.supplier su ON su.id = io.companyFk JOIN vn.supplier su ON su.id = io.companyFk
@ -38,6 +39,7 @@ SELECT
NULL, NULL,
ts.description, ts.description,
tc.code, tc.code,
NULL,
NULL NULL
FROM vn.invoiceOut io FROM vn.invoiceOut io
JOIN vn.ticket t ON t.refFk = io.ref JOIN vn.ticket t ON t.refFk = io.ref