Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 7119-createVehicle
gitea/salix/pipeline/pr-dev This commit looks good Details

This commit is contained in:
Jorge Penadés 2025-02-06 10:20:22 +01:00
commit 9ba517b648
97 changed files with 1897 additions and 1245 deletions

View File

@ -750,17 +750,15 @@ INSERT INTO `vn`.`zoneClosure` (`zoneFk`, `dated`, `hour`)
INSERT INTO `vn`.`zoneConfig` (`id`, `scope`) VALUES (1, '1');
INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`, `zoneFk`, `dated`)
INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`, `dated`)
VALUES
(1, '1899-12-30 12:15:00', 133, util.VN_CURDATE(), 1, 1, 'first route', 1.8, 10, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1, util.VN_CURDATE()),
(2, '1899-12-30 13:20:00', 56, util.VN_CURDATE(), 1, 2, 'second route', 0.2, 20, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 9, util.VN_CURDATE()),
(3, '1899-12-30 14:30:00', 56, util.VN_CURDATE(), 2, 3, 'third route', 0.5, 30, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 10, util.VN_CURDATE()),
(4, '1899-12-30 15:45:00', 56, util.VN_CURDATE(), 3, 4, 'fourth route', 0, 40, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 12, util.VN_CURDATE()),
(5, '1899-12-30 16:00:00', 56, util.VN_CURDATE(), 4, 5, 'fifth route', 0.1, 50, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 13, util.VN_CURDATE()),
(6, NULL, 57, util.VN_CURDATE(), 5, 7, 'sixth route', 1.7, 60, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 3, util.VN_CURDATE()),
(7, NULL, 57, util.VN_CURDATE(), 6, 8, 'seventh route', 0, 70, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 5, util.VN_CURDATE()),
(8, NULL, 133, util.VN_CURDATE(), 1, 1, 'eighth route', 1.8, 10.0, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1, util.VN_CURDATE()),
(9, NULL, 133, util.VN_CURDATE(), 1, 2, 'ninth route', 0.2, 20.0, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 9, util.VN_CURDATE());
(1, '1899-12-30 12:15:00', 133, util.VN_CURDATE(), 1, 1, 'first route', 1.8, 10, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), util.VN_CURDATE()),
(2, '1899-12-30 13:20:00', 56, util.VN_CURDATE(), 1, 2, 'second route', 0.2, 20, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), util.VN_CURDATE()),
(3, '1899-12-30 14:30:00', 133, util.VN_CURDATE(), 2, 3, 'third route', 0.5, 30, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), util.VN_CURDATE()),
(4, '1899-12-30 15:45:00', 56, util.VN_CURDATE(), 3, 4, 'fourth route', 0, 40, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), util.VN_CURDATE()),
(5, '1899-12-30 16:00:00', 133, util.VN_CURDATE(), 4, 5, 'fifth route', 0.1, 50, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), util.VN_CURDATE()),
(6, NULL, 57, util.VN_CURDATE(), 5, 7, 'sixth route', 1.7, 60, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), util.VN_CURDATE()),
(7, NULL, 57, util.VN_CURDATE(), 6, 8, 'seventh route', 0, 70, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), util.VN_CURDATE());
INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `zonePrice`, `zoneBonus`, `created`, `weight`, `cmrFk`, `problem`, `risk`)
VALUES
@ -1093,12 +1091,12 @@ INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `pric
(5, 1, 2, 'Ranged weapon longbow 200cm', 1, 110.33, 0, 0, 0, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 'hasComponentLack'),
(6, 1, 3, 'Ranged weapon longbow 200cm', 1, 110.33, 0, 0, 0, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH), 'hasComponentLack'),
(7, 2, 11, 'Melee weapon combat fist 15cm', 15, 7.74, 0, 0, 0, util.VN_CURDATE(), NULL),
(8, 4, 11, 'Melee weapon heavy shield 100cm', 10, 1.79, 0, 0, 0, util.VN_CURDATE(), NULL),
(8, 4, 11, 'Melee weapon heavy shield 100cm', 10, 1.79, 0, 0, 0, util.VN_CURDATE(), 'hasItemLost,hasRounding'),
(9, 1, 16, 'Ranged weapon longbow 200cm', 1, 103.49, 0, 0, 0, util.VN_CURDATE(), NULL),
(10, 2, 16, 'Melee weapon combat fist 15cm', 10, 7.09, 0, 0, 0, util.VN_CURDATE(), NULL),
(11, 1, 16, 'Ranged weapon longbow 200cm', 1, 103.49, 0, 0, 0, util.VN_CURDATE(), NULL),
(12, 4, 16, 'Melee weapon heavy shield 100cm', 20, 1.71, 0, 0, 0, util.VN_CURDATE(), NULL),
(13, 2, 8, 'Melee weapon combat fist 15cm', 10, 7.08, 0, 0, 0, util.VN_CURDATE(), NULL),
(13, 2, 8, 'Melee weapon combat fist 15cm', 10, 7.08, 0, 0, 0, util.VN_CURDATE(), 'hasItemLost'),
(14, 1, 8, 'Ranged weapon longbow 200cm', 2, 103.49, 0, 0, 0, util.VN_CURDATE(), NULL),
(15, 1, 19, 'Ranged weapon longbow 200cm', 1, 103.49, 0, 0, 0, util.VN_CURDATE(), NULL),
(16, 2, 20, 'Melee weapon combat fist 15cm', 20, 7.07, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
@ -1109,25 +1107,25 @@ INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `pric
(21, 1, 6, 'Ranged weapon longbow 200cm', 1, 8.07, 0, 0, 0, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 'hasComponentLack'),
(22, 1, 7, 'Ranged weapon longbow 200cm', 1, 8.07, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(23, 1, 9, 'Ranged weapon longbow 200cm', 1, 8.07, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(24, 1, 10, 'Ranged weapon longbow 200cm', 1, 8.07, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(25, 4, 12, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(26, 4, 13, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(27, 4, 14, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(28, 4, 15, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(29, 4, 17, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(30, 4, 18, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(31, 2, 23, 'Melee weapon combat fist 15cm', -5, 7.08, 0, 0, 0, util.VN_CURDATE(), NULL),
(24, 1, 10, 'Ranged weapon longbow 200cm', 1, 8.07, 0, 0, 0, util.VN_CURDATE(), 'hasItemShortage,hasComponentLack'),
(25, 4, 12, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack,hasItemLost'),
(26, 4, 13, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack,hasItemLost'),
(27, 4, 14, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasItemShortage,hasComponentLack,hasItemLost'),
(28, 4, 15, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack,hasItemLost'),
(29, 4, 17, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasItemShortage,hasComponentLack'),
(30, 4, 18, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasItemShortage,hasComponentLack'),
(31, 2, 23, 'Melee weapon combat fist 15cm', -5, 7.08, 0, 0, 0, util.VN_CURDATE(), 'hasRounding'),
(32, 1, 24, 'Ranged weapon longbow 200cm', -1, 8.07, 0, 0, 0, util.VN_CURDATE(), NULL),
(33, 5, 14, 'Ranged weapon pistol 9mm', 50, 1.79, 0, 0, 0, util.VN_CURDATE(), NULL),
(34, 4, 28, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(35, 4, 29, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(34, 4, 28, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack,hasItemLost'),
(35, 4, 29, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack,hasItemLost'),
(37, 4, 31, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), NULL),
(36, 4, 30, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(36, 4, 30, 'Melee weapon heavy shield 100cm', 20, 1.72, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack,hasItemLost'),
(38, 2, 32, 'Melee weapon combat fist 15cm', 30, 7.07, 0, 0, 0, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH), 'hasComponentLack'),
(39, 1, 32, 'Ranged weapon longbow 200cm', 2, 103.49, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(40, 2, 34, 'Melee weapon combat fist 15cm', 10.00, 3.91, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(41, 2, 35, 'Melee weapon combat fist 15cm', 8.00, 3.01, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack'),
(42, 2, 36, 'Melee weapon combat fist 15cm', 6.00, 2.50, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack');
(40, 2, 34, 'Melee weapon combat fist 15cm', 10.00, 3.91, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack,hasItemLost'),
(41, 2, 35, 'Melee weapon combat fist 15cm', 8.00, 3.01, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack,hasRounding,hasItemLost'),
(42, 2, 36, 'Melee weapon combat fist 15cm', 6.00, 2.50, 0, 0, 0, util.VN_CURDATE(), 'hasComponentLack,hasRounding,hasItemLost');
INSERT INTO `vn`.`saleComponent`(`saleFk`, `componentFk`, `value`)
VALUES
@ -1948,9 +1946,9 @@ INSERT INTO `vn`.`claimEnd`(`id`, `saleFk`, `claimFk`, `workerFk`, `claimDestina
(1, 31, 4, 21, 2),
(2, 32, 3, 21, 3);
INSERT INTO `vn`.`claimConfig`(`id`, `maxResponsibility`, `monthsToRefund`, `minShipped`)
INSERT INTO `vn`.`claimConfig`(`id`, `maxResponsibility`, `monthsToRefund`, `minShipped`,`daysToClaim`)
VALUES
(1, 5, 4, '2016-10-01');
(1, 5, 4, '2016-10-01', 7);
INSERT INTO `vn`.`claimRatio`(`clientFk`, `yearSale`, `claimAmount`, `claimingRate`, `priceIncreasing`, `packingRate`)
VALUES
@ -2757,13 +2755,13 @@ INSERT INTO `vn`.`roadmapAddress` (`addressFk`)
(3),
(4);
INSERT INTO `vn`.`roadmap` (`id`, `name`, `tractorPlate`, `trailerPlate`, `phone`, `supplierFk`, `etd`, `observations`, `userFk`, `price`, `driverName`)
INSERT INTO `vn`.`roadmap` (`id`, `name`, `tractorPlate`, `trailerPlate`, `phone`, `supplierFk`, `etd`, `eta`, `observations`, `editorFk`, `price`, `driverName`)
VALUES
(1, 'val-algemesi', '1234-BCD', '9876-BCD', '111111111', 1, util.VN_NOW(), 'this is test observation', 1, 15, 'Batman'),
(2, 'alg-valencia', '2345-CDF', '8765-BCD', '111111111', 1, util.VN_NOW(), 'test observation', 1, 20, 'Robin'),
(3, 'alz-algemesi', '3456-DFG', '7654-BCD', '222222222', 2, DATE_ADD(util.VN_NOW(), INTERVAL 2 DAY), 'observations...', 2, 25, 'Driverman');
(1, 'val-algemesi', '1234-BCD', '9876-BCD', '111111111', 1, util.VN_NOW(), DATE_ADD(util.VN_NOW(), INTERVAL 2 DAY), 'this is test observation', 1, 15, 'Batman'),
(2, 'alg-valencia', '2345-CDF', '8765-BCD', '111111111', 1, util.VN_NOW(), DATE_ADD(util.VN_NOW(), INTERVAL 5 DAY), 'test observation', 1, 20, 'Robin'),
(3, 'alz-algemesi', '3456-DFG', '7654-BCD', '222222222', 2, DATE_ADD(util.VN_NOW(), INTERVAL 3 DAY), DATE_ADD(util.VN_NOW(), INTERVAL 6 DAY), 'observations...', 2, 25, 'Driverman');
INSERT INTO `vn`.`roadmapStop` (`id`, `roadmapFk`, `addressFk`, `eta`, `description`, `userFk`)
INSERT INTO `vn`.`roadmapStop` (`id`, `roadmapFk`, `roadmapAddressFk`, `eta`, `description`, `editorFk`)
VALUES
(1, 1, 1, DATE_ADD(util.VN_NOW(), INTERVAL 1 DAY), 'Best truck in fleet', 1),
(2, 1, 2, DATE_ADD(util.VN_NOW(), INTERVAL '1 2' DAY_HOUR), 'Second truck in fleet', 1),
@ -2927,7 +2925,8 @@ INSERT INTO `util`.`notification` (`id`, `name`, `description`)
(7, 'zone-included','An email to notify zoneCollisions'),
(8, 'backup-printer-selected','A backup printer has been selected'),
(9, 'mrw-deadline','The MRW deadline has passed'),
(10,'invoice-ticket-closure','Tickets not invoiced during the nightly closure ticket process');
(10,'invoice-ticket-closure','Tickets not invoiced during the nightly closure ticket process'),
(11,'misallocation-warehouse','Misallocation of items in the warehouse.');
TRUNCATE `util`.`notificationAcl`;
INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`)
@ -2941,7 +2940,8 @@ INSERT INTO `util`.`notificationAcl` (`notificationFk`, `roleFk`)
(6, 9),
(7, 9),
(8, 66),
(9, 56);
(9, 56),
(11, 9);
TRUNCATE `util`.`notificationQueue`;
INSERT INTO `util`.`notificationQueue` (`id`, `notificationFk`, `params`, `authorFk`, `status`, `created`)
@ -3208,7 +3208,7 @@ UPDATE vn.department
SET workerFk = null;
INSERT INTO vn.packaging
VALUES('--', 2745600.00, 100.00, 120.00, 220.00, 0.00, 1, '2001-01-01 00:00:00.000', NULL, NULL, NULL, 0.00, 16, 0.00, 0, NULL, 0.00, NULL, NULL, 0, NULL, 0, 0,0,1);
VALUES('--', 2745600.00, 100.00, 120.00, 220.00, 0.00, 1, '2001-01-01 00:00:00.000', NULL, NULL, NULL, 0.00, 16, 0.00, 0, NULL, 0.00, NULL, NULL, 0, NULL, 0, 0,0,1,0);
INSERT IGNORE INTO vn.intrastat

View File

@ -65,7 +65,7 @@ BEGIN
JOIN vn.ticketState ts ON ts.ticketFk = t.id
JOIN vn.alertLevel al ON al.id = ts.alertLevel
WHERE t.shipped BETWEEN util.VN_CURDATE() AND util.dayend(util.VN_CURDATE())
AND s.isPicked = FALSE
AND NOT s.isPicked
AND al.code = 'FREE'
AND t.warehouseFk = vWarehouseFk
GROUP BY s.itemFk
@ -73,7 +73,6 @@ BEGIN
) s ON s.itemFk = v.item_id
WHERE v.calc_id = vCalc
AND NOT v.visible <=> tv.totalVisible;
END LOOP;
CLOSE cWarehouses;

View File

@ -0,0 +1,62 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` FUNCTION `vn`.`getTimeBetweenRoadmapAddresses`(
vRoadmapAddressFrom INT,
vRoadmapAddressTo INT
)
RETURNS int(11)
DETERMINISTIC
BEGIN
/**
* Retorna el tiempo en segundos que se suele tardar en ir
* de un punto de distribución a otro en una ruta troncal.
*
* @param vRoadmapAddressFrom Punto de distribución de origen
* @param vRoadmapAddressTo Punto de distribución de destino
* @return Tiempo en segundos
*/
DECLARE vSeconds INT;
WITH wRoadmapStop AS (
SELECT ROW_NUMBER() OVER(PARTITION BY roadmapFk ORDER BY eta) `sequence`,
roadmapFk,
roadmapAddressFk,
eta
FROM vn.roadmapStop
WHERE roadmapFk IS NOT NULL
AND roadmapAddressFk IS NOT NULL
AND eta IS NOT NULL
)
SELECT AVG(TIME_TO_SEC(TIMEDIFF(rsTo.eta, rsFrom.eta))) INTO vSeconds
FROM wRoadmapStop rsFrom
JOIN wRoadmapStop rsTo ON rsTo.roadmapFk = rsFrom.roadmapFk
WHERE rsFrom.roadmapAddressFk = vRoadmapAddressFrom
AND rsTo.roadmapAddressFk = vRoadmapAddressTo
AND rsFrom.`sequence` + 1 = rsTo.`sequence`;
IF NOT IFNULL(vSeconds, 0) THEN
WITH wRoadmap AS (
SELECT id,
roadmapAddressFk,
etd
FROM vn.roadmap
WHERE roadmapAddressFk = vRoadmapAddressFrom
AND etd IS NOT NULL
), wRoadmapStop AS (
SELECT ROW_NUMBER() OVER(PARTITION BY roadmapFk ORDER BY eta) `sequence`,
roadmapFk,
roadmapAddressFk,
eta
FROM vn.roadmapStop
WHERE roadmapFk IS NOT NULL
AND roadmapAddressFk = vRoadmapAddressTo
AND eta IS NOT NULL
)
SELECT AVG(TIME_TO_SEC(TIMEDIFF(rsTo.eta, rFrom.etd))) INTO vSeconds
FROM wRoadmap rFrom
JOIN wRoadmapStop rsTo ON rsTo.roadmapFk = rFrom.id
AND rsTo.`sequence` = 1;
END IF;
RETURN vSeconds;
END$$
DELIMITER ;

View File

@ -1,207 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`itemShelvingRadar`(
vSectorFk INT
)
BEGIN
/**
* Calcula la información detallada respecto un sector.
*
* @param vSectorFk Id de sector
*/
DECLARE vCalcVisibleFk INT;
DECLARE vCalcAvailableFk INT;
DECLARE hasFatherSector BOOLEAN;
DECLARE vBuyerFk INT DEFAULT 0;
DECLARE vWarehouseFk INT DEFAULT 0;
DECLARE vSonSectorFk INT;
DECLARE vWorkerFk INT;
SELECT s.workerFk INTO vWorkerFk
FROM sector s
WHERE s.id = vSectorFk;
SELECT COUNT(*) INTO hasFatherSector
FROM sector
WHERE sonFk = vSectorFk;
SELECT warehouseFk, sonFk INTO vWarehouseFk, vSonSectorFk
FROM sector
WHERE id = vSectorFk;
CALL cache.visible_refresh(vCalcVisibleFk, TRUE, vWarehouseFk);
CALL cache.available_refresh(vCalcAvailableFk, FALSE, vWarehouseFk, util.VN_CURDATE());
IF hasFatherSector THEN
CREATE OR REPLACE TEMPORARY TABLE tItemShelvingRadar
(PRIMARY KEY (itemFk))
ENGINE = MEMORY
SELECT *
FROM (
SELECT iss.itemFk,
i.longName,
i.size,
i.subName producer,
IFNULL(a.available, 0) available,
SUM(IF(s.sonFk = vSectorFk, IFNULL(iss.visible, 0), 0)) upstairs,
SUM(IF(iss.sectorFk = vSectorFk, IFNULL(iss.visible, 0), 0)) downstairs,
IF(it.isPackaging, NULL, IFNULL(v.visible, 0)) visible,
vSectorFk sectorFk,
ish.isChecked,
sub.isAllChecked
FROM itemShelvingStock iss
JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
LEFT JOIN (
SELECT itemFk,
IF(
COUNT(*) = SUM(IF(isChecked >= 0, 1, 0)),
TRUE,
FALSE
) isAllChecked
FROM itemShelving is2
GROUP BY itemFk
) sub ON sub.itemFk = ish.itemFk
JOIN sector s ON s.id = iss.sectorFk
JOIN item i ON i.id = iss.itemFk
JOIN itemType it ON it.id = i.typeFk
LEFT JOIN cache.available a ON a.item_id = iss.itemFk
AND a.calc_id = vCalcAvailableFk
LEFT JOIN cache.visible v ON v.item_id = iss.itemFk
AND v.calc_id = vCalcVisibleFk
WHERE vSectorFk IN (iss.sectorFk, s.sonFk)
GROUP BY iss.itemFk
UNION ALL
SELECT v.item_id,
i.longName,
i.size,
i.subName,
IFNULL(a.available, 0),
0,
0,
IF(it.isPackaging, NULL, v.visible),
vSectorFk,
NULL,
NULL
FROM cache.visible v
JOIN item i ON i.id = v.item_id
JOIN itemType it ON it.id = i.typeFk
LEFT JOIN itemShelvingStock iss ON iss.itemFk = v.item_id
AND iss.warehouseFk = vWarehouseFk
LEFT JOIN cache.available a ON a.item_id = v.item_id
AND a.calc_id = vCalcAvailableFk
WHERE v.calc_id = vCalcVisibleFk
AND iss.itemFk IS NULL
AND it.isInventory
) sub
GROUP BY itemFk;
SELECT ishr.*,
CAST(visible - upstairs - downstairs AS DECIMAL(10, 0)) nicho,
CAST(downstairs - IFNULL(notPickedYed, 0) AS DECIMAL(10, 0)) pendiente
FROM tItemShelvingRadar ishr
JOIN item i ON i.id = ishr.itemFk
LEFT JOIN (
SELECT s.itemFk, SUM(s.quantity) notPickedYed
FROM ticket t
JOIN ticketStateToday tst ON tst.ticketFk = t.id
JOIN alertLevel al ON al.id = tst.alertLevel
JOIN sale s ON s.ticketFk = t.id
WHERE t.warehouseFk = vWarehouseFk
AND al.code = 'FREE'
GROUP BY s.itemFk
) sub ON sub.itemFk = ishr.itemFk
ORDER BY i.typeFk, i.longName;
ELSE
CREATE OR REPLACE TEMPORARY TABLE tItemShelvingRadar
(PRIMARY KEY (itemFk))
ENGINE = MEMORY
SELECT iss.itemFk,
0 `hour`,
0 `minute`,
'--' itemPlacementCode,
i.longName,
i.size,
i.subName producer,
i.upToDown,
IFNULL(a.available, 0) available,
IFNULL(v.visible - iss.visible, 0) dayEndVisible,
IFNULL(v.visible - iss.visible, 0) firstNegative,
IFNULL(v.visible - iss.visible, 0) itemPlacementVisible,
IFNULL(i.minimum * b.packing, 0) itemPlacementSize,
ips.onTheWay,
iss.visible itemShelvingStock,
IFNULL(v.visible, 0) visible,
b.isPickedOff,
iss.sectorFk
FROM itemShelvingStock iss
JOIN item i ON i.id = iss.itemFk
LEFT JOIN cache.last_buy lb ON lb.item_id = iss.itemFk
AND lb.warehouse_id = vWarehouseFk
LEFT JOIN buy b ON b.id = lb.buy_id
LEFT JOIN cache.available a ON a.item_id = iss.itemFk
AND a.calc_id = vCalcAvailableFk
LEFT JOIN cache.visible v ON v.item_id = iss.itemFk
AND v.calc_id = vCalcVisibleFk
LEFT JOIN (
SELECT itemFk, SUM(saldo) onTheWay
FROM itemPlacementSupplyList
WHERE saldo > 0
GROUP BY itemFk
) ips ON ips.itemFk = i.id
WHERE iss.sectorFk = vSectorFk
OR iss.sectorFk IS NULL;
CREATE OR REPLACE TEMPORARY TABLE tmp.itemOutTime
SELECT *, SUM(amount) quantity
FROM (
SELECT io.itemFk,
io.quantity amount,
IF(HOUR(t.shipped), HOUR(t.shipped), HOUR(z.`hour`)) `hours`,
IF(MINUTE(t.shipped), MINUTE(t.shipped), MINUTE(z.`hour`)) `minutes`
FROM itemTicketOut `io`
JOIN tItemShelvingRadar isr ON isr.itemFk = io.itemFk
JOIN ticket t ON t.id= io.ticketFk
JOIN ticketState ts ON ts.ticketFk = io.ticketFk
JOIN `state` s ON s.id = ts.stateFk
LEFT JOIN `zone` z ON z.id = t.zoneFk
LEFT JOIN (
SELECT DISTINCT saleFk
FROM saleTracking st
WHERE st.created > util.VN_CURDATE()
AND st.isChecked
) stPrevious ON stPrevious.saleFk = io.saleFk
WHERE t.warehouseFk = vWarehouseFk
AND NOT s.isPicked
AND NOT io.reserved
AND stPrevious.saleFk IS NULL
AND io.shipped >= util.VN_CURDATE()
AND io.shipped < util.VN_CURDATE() + INTERVAL 1 DAY
) sub
GROUP BY itemFk, `hours`, `minutes`;
INSERT INTO tItemShelvingRadar (itemFk)
SELECT itemFk FROM tmp.itemOutTime
ON DUPLICATE KEY UPDATE dayEndVisible = dayEndVisible + quantity,
firstNegative = IF(firstNegative < 0, firstNegative, firstNegative + quantity),
`hour` = IFNULL(IF(firstNegative > 0 , `hour`, `hours`), 0),
`minute` = IFNULL(IF(firstNegative > 0, `minute`, `minutes`), 0);
UPDATE tItemShelvingRadar isr
JOIN (
SELECT s.itemFk, SUM(s.quantity) amount
FROM sale s
JOIN ticket t ON t.id = s.ticketFk
JOIN ticketState ts ON ts.ticketFk = t.id
WHERE t.shipped BETWEEN util.VN_CURDATE() AND util.dayend(util.VN_CURDATE())
AND ts.code = 'COOLER_PREPARATION'
GROUP BY s.itemFk
) sub ON sub.itemFk = isr.itemFk
SET isr.dayEndVisible = dayEndVisible + sub.amount,
firstNegative = firstNegative + sub.amount;
SELECT * FROM tItemShelvingRadar;
END IF;
DROP TEMPORARY TABLE tItemShelvingRadar;
END$$
DELIMITER ;

View File

@ -24,7 +24,7 @@ BEGIN
SELECT ish.id,
p.pickingOrder,
p.code parking,
ish.shelvingFk,
sh.code,
ish.itemFk,
i.longName,
ish.visible,

View File

@ -1,16 +1,18 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`prepareTicketList`(vStartingDate DATETIME, vEndingDate DATETIME)
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`prepareTicketList`(
vStartingDate DATETIME,
vEndingDate DATETIME
)
BEGIN
DROP TEMPORARY TABLE IF EXISTS tmp.productionTicket;
CREATE TEMPORARY TABLE tmp.productionTicket
(PRIMARY KEY (ticketFk))
ENGINE = MEMORY
SELECT t.id ticketFk, t.clientFk
SELECT t.id ticketFk
FROM ticket t
JOIN alertLevel al ON al.code = 'DELIVERED'
LEFT JOIN ticketState ts ON ts.ticketFk = t.id
JOIN client c ON c.id = t.clientFk
WHERE c.typeFk IN ('normal','handMaking','internalUse')
AND (
t.shipped BETWEEN util.VN_CURDATE() AND vEndingDate

View File

@ -24,24 +24,31 @@ proc: BEGIN
CALL prepareTicketList(util.yesterday(), vEndingDate);
CREATE OR REPLACE TEMPORARY TABLE tmp.ticket
SELECT * FROM tmp.productionTicket;
CALL prepareClientList();
CREATE OR REPLACE TEMPORARY TABLE tmp.sale_getProblems
(INDEX (ticketFk))
ENGINE = MEMORY
SELECT tt.ticketFk, tt.clientFk, t.warehouseFk, t.shipped
FROM tmp.productionTicket tt
JOIN ticket t ON t.id = tt.ticketFk;
SELECT ticketFk
FROM tmp.productionTicket;
CALL ticket_getProblems(vIsTodayRelative);
CREATE OR REPLACE TEMPORARY TABLE tmp.productionBuffer
(PRIMARY KEY(ticketFk), previaParking VARCHAR(255))
ENGINE = MEMORY
WITH saleProblemsDescription AS(
SELECT s.ticketFk,
LEFT(CONCAT('F: ', GROUP_CONCAT(CONCAT(i.id, ' ', i.longName) SEPARATOR ', ')), 250) itemShortage,
LEFT(CONCAT('R: ', GROUP_CONCAT(CONCAT(i2.id, ' ', i2.longName) SEPARATOR ', ')), 250) itemDelay,
LEFT(CONCAT('I: ', GROUP_CONCAT(CONCAT(i3.id, ' ', i3.longName) SEPARATOR ', ')), 250) itemLost
FROM tmp.saleProblems sp
JOIN vn.sale s ON s.id = sp.saleFk
LEFT JOIN vn.item i ON i.id = s.itemFk AND sp.hasItemShortage
LEFT JOIN vn.item i2 ON i2.id = s.itemFk AND sp.hasItemDelay
LEFT JOIN vn.item i3 ON i3.id = s.itemFk AND sp.hasItemLost
WHERE hasItemShortage OR hasItemDelay OR hasItemLost
GROUP BY s.ticketFk
)
SELECT tt.ticketFk,
tt.clientFk,
t.clientFk,
t.warehouseFk,
t.nickname,
t.packages,
@ -59,7 +66,17 @@ proc: BEGIN
0 `lines`,
CAST( 0 AS DECIMAL(5,2)) m3,
CAST( 0 AS DECIMAL(5,2)) preparationRate,
"" problem,
TRIM(CAST(CONCAT( IFNULL(sp.itemShortage, ''),
IFNULL(sp.itemDelay, ''),
IFNULL(sp.itemLost, ''),
IF(tpr.isFreezed, ' CONGELADO',''),
IF(tpr.hasHighRisk, ' RIESGO',''),
IF(tpr.hasTicketRequest, ' COD 100',''),
IF(tpr.isTaxDataChecked, '',' FICHA INCOMPLETA'),
IF(tpr.hasComponentLack, ' COMPONENTES', ''),
IF(HOUR(util.VN_NOW()) < IF(HOUR(t.shipped), HOUR(t.shipped), COALESCE(HOUR(zc.hour),HOUR(z.hour)))
AND tpr.isTooLittle, ' PEQUEÑO', '')
) AS char(255))) problem,
IFNULL(tls.state,2) state,
w.code workerCode,
DATE(t.shipped) shipped,
@ -79,26 +96,28 @@ proc: BEGIN
ag.isOwn,
rm.bufferFk
FROM tmp.productionTicket tt
JOIN ticket t ON tt.ticketFk = t.id
JOIN alertLevel al ON al.code = 'FREE'
LEFT JOIN ticketStateToday tst ON tst.ticketFk = t.id
LEFT JOIN `state` st ON st.id = tst.state
LEFT JOIN client c ON c.id = t.clientFk
LEFT JOIN worker wk ON wk.id = c.salesPersonFk
JOIN address a ON a.id = t.addressFk
LEFT JOIN province p ON p.id = a.provinceFk
JOIN agencyMode am ON am.id = t.agencyModeFk
JOIN deliveryMethod dm ON dm.id = am.deliveryMethodFk
JOIN agency ag ON ag.id = am.agencyFk
LEFT JOIN ticketState tls ON tls.ticketFk = tt.ticketFk
LEFT JOIN ticketLastUpdated tlu ON tlu.ticketFk = tt.ticketFk
LEFT JOIN worker w ON w.id = tls.userFk
LEFT JOIN routesMonitor rm ON rm.routeFk = t.routeFk
LEFT JOIN `zone` z ON z.id = t.zoneFk
LEFT JOIN zoneClosure zc ON zc.zoneFk = t.zoneFk
JOIN vn.ticket t ON tt.ticketFk = t.id
JOIN vn.alertLevel al ON al.code = 'FREE'
LEFT JOIN vn.ticketStateToday tst ON tst.ticketFk = t.id
LEFT JOIN vn.`state` st ON st.id = tst.state
LEFT JOIN vn.client c ON c.id = t.clientFk
LEFT JOIN vn.worker wk ON wk.id = c.salesPersonFk
JOIN vn.address a ON a.id = t.addressFk
LEFT JOIN vn.province p ON p.id = a.provinceFk
JOIN vn.agencyMode am ON am.id = t.agencyModeFk
JOIN vn.deliveryMethod dm ON dm.id = am.deliveryMethodFk
JOIN vn.agency ag ON ag.id = am.agencyFk
LEFT JOIN vn.ticketState tls ON tls.ticketFk = tt.ticketFk
LEFT JOIN vn.ticketLastUpdated tlu ON tlu.ticketFk = tt.ticketFk
LEFT JOIN vn.worker w ON w.id = tls.userFk
LEFT JOIN vn.routesMonitor rm ON rm.routeFk = t.routeFk
LEFT JOIN vn.`zone` z ON z.id = t.zoneFk
LEFT JOIN vn.zoneClosure zc ON zc.zoneFk = t.zoneFk
AND DATE(t.shipped) = zc.dated
LEFT JOIN ticketParking tp ON tp.ticketFk = t.id
LEFT JOIN parking pk ON pk.id = tp.parkingFk
LEFT JOIN vn.ticketParking tp ON tp.ticketFk = t.id
LEFT JOIN vn.parking pk ON pk.id = tp.parkingFk
LEFT JOIN tmp.ticketProblems tpr ON tpr.ticketFk = tt.ticketFk
LEFT JOIN saleProblemsDescription sp ON sp.ticketFk = tt.ticketFk
WHERE t.warehouseFk = vWarehouseFk
AND dm.code IN ('AGENCY', 'DELIVERY', 'PICKUP');
@ -121,19 +140,6 @@ proc: BEGIN
ADD COLUMN `collectionV` INT,
ADD COLUMN `collectionN` INT;
UPDATE tmp.productionBuffer pb
JOIN tmp.ticket_problems tp ON tp.ticketFk = pb.ticketFk
SET pb.problem = TRIM(CAST(CONCAT( IFNULL(tp.itemShortage, ''),
IFNULL(tp.itemDelay, ''),
IFNULL(tp.itemLost, ''),
IF(tp.isFreezed, ' CONGELADO',''),
IF(tp.hasHighRisk, ' RIESGO',''),
IF(tp.hasTicketRequest, ' COD 100',''),
IF(tp.isTaxDataChecked, '',' FICHA INCOMPLETA'),
IF(tp.hasComponentLack, ' COMPONENTES', ''),
IF(HOUR(util.VN_NOW()) < pb.HH AND tp.isTooLittle, ' PEQUEÑO', '')
) AS char(255)));
-- Clientes Nuevos o Recuperados
UPDATE tmp.productionBuffer pb
LEFT JOIN bs.clientNewBorn cnb ON cnb.clientFk = pb.clientFk
@ -278,7 +284,8 @@ proc: BEGIN
DROP TEMPORARY TABLE
tmp.productionTicket,
tmp.ticket,
tmp.ticket_problems,
tmp.ticketProblems,
tmp.saleProblems,
tmp.ticketWithPrevia,
tItemShelvingStock,
tItemPackingType;

View File

@ -0,0 +1,72 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`roadmap_cloneDay`(
vDateToCopy DATE,
vDateToPaste DATE
)
BEGIN
/**
* Clona roadmaps de un día a otro, incluyendo las paradas y sin algunos
* campos de la tabla principal, como matrículas, conductores...
*
* @param vDateToCopy Fecha para copiar
* @param vDateToPaste Fecha para pegar
*/
DECLARE vDaysDiff INT;
DECLARE vRoadmapFk INT;
DECLARE vNewRoadmapFk INT;
DECLARE vDone BOOL DEFAULT FALSE;
DECLARE vRoadmaps CURSOR FOR
SELECT id
FROM roadmap
WHERE etd BETWEEN vDateToCopy AND util.dayEnd(vDateToCopy);
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
SET vDaysDiff = DATEDIFF(vDateToPaste, vDateToCopy);
IF vDaysDiff IS NULL THEN
CALL util.throw("No valid dates");
END IF;
START TRANSACTION;
OPEN vRoadmaps;
l: LOOP
SET vDone = FALSE;
FETCH vRoadmaps INTO vRoadmapFk;
IF vDone THEN
LEAVE l;
END IF;
INSERT INTO roadmap (`name`, roadmapAddressFk, etd, eta, observations, price)
SELECT `name`,
roadmapAddressFk,
etd + INTERVAL vDaysDiff DAY,
eta + INTERVAL vDaysDiff DAY,
observations,
price
FROM roadmap
WHERE id = vRoadmapFk;
SET vNewRoadmapFk = LAST_INSERT_ID();
INSERT INTO roadmapStop (roadmapFk, roadmapAddressFk, eta, `description`, bufferFk)
SELECT vNewRoadmapFk,
roadmapAddressFk,
eta + INTERVAL vDaysDiff DAY,
`description`,
bufferFk
FROM roadmapStop
WHERE roadmapFk = vRoadmapFk;
END LOOP;
CLOSE vRoadmaps;
COMMIT;
END$$
DELIMITER ;

View File

@ -1,14 +1,14 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`sale_getProblems`(
vIsTodayRelative tinyint(1)
vIsTodayRelative TINYINT(1)
)
BEGIN
/**
* Calcula los problemas de cada venta para un conjunto de tickets.
* Calcula los problemas para un conjunto de sale
*
* @param vIsTodayRelative Indica si se calcula el disponible como si todo saliera hoy
* @table tmp.sale_getProblems(ticketFk, clientFk, warehouseFk, shipped) Tickets a calcular
* @return tmp.sale_problems
* @table tmp.sale(saleFk) Identificadores de los sale a calcular
* @return tmp.saleProblems
*/
DECLARE vWarehouseFk INT;
DECLARE vDate DATE;
@ -16,71 +16,27 @@ BEGIN
DECLARE vVisibleCache INT;
DECLARE vDone BOOL;
DECLARE vCursor CURSOR FOR
SELECT DISTINCT warehouseFk, IF(vIsTodayRelative, util.VN_CURDATE(), DATE(shipped))
FROM tmp.sale_getProblems
WHERE shipped BETWEEN util.VN_CURDATE()
AND util.dayEnd(util.VN_CURDATE() + INTERVAL IF(vIsTodayRelative, 9.9, 1.9) DAY);
SELECT t.warehouseFk, IF(vIsTodayRelative, util.VN_CURDATE(), DATE(t.shipped)) dated
FROM tmp.sale ts
JOIN sale s ON s.id = ts.saleFk
JOIN ticket t ON t.id = s.ticketFk
WHERE t.shipped BETWEEN util.VN_CURDATE()
AND util.dayEnd(util.VN_CURDATE() + INTERVAL IF(vIsTodayRelative, 9.9, 1.9) DAY)
GROUP BY warehouseFk, dated;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
CREATE OR REPLACE TEMPORARY TABLE tmp.sale_problems (
ticketFk INT(11),
CREATE OR REPLACE TEMPORARY TABLE tmp.saleProblems(
saleFk INT(11),
isFreezed INTEGER(1) DEFAULT 0,
risk DECIMAL(10,1) DEFAULT 0,
hasRisk TINYINT(1) DEFAULT 0,
hasHighRisk TINYINT(1) DEFAULT 0,
hasTicketRequest INTEGER(1) DEFAULT 0,
itemShortage VARCHAR(255),
isTaxDataChecked INTEGER(1) DEFAULT 1,
itemDelay VARCHAR(255),
itemLost VARCHAR(255),
hasComponentLack INTEGER(1),
hasRounding VARCHAR(255),
isTooLittle BOOL DEFAULT FALSE,
isVip BOOL DEFAULT FALSE,
PRIMARY KEY (ticketFk, saleFk)
); -- No memory
hasItemShortage BOOL DEFAULT FALSE,
hasItemLost BOOL DEFAULT FALSE,
hasComponentLack BOOL DEFAULT FALSE,
hasItemDelay BOOL DEFAULT FALSE,
hasRounding BOOL DEFAULT FALSE,
PRIMARY KEY (saleFk)
) ENGINE = MEMORY;
INSERT INTO tmp.sale_problems(ticketFk,
saleFk,
isFreezed,
risk,
hasRisk,
hasHighRisk,
hasTicketRequest,
isTaxDataChecked,
hasComponentLack,
isTooLittle)
SELECT sgp.ticketFk,
s.id,
IF(FIND_IN_SET('isFreezed', t.problem), TRUE, FALSE) isFreezed,
t.risk,
IF(FIND_IN_SET('hasRisk', t.problem), TRUE, FALSE) hasRisk,
IF(FIND_IN_SET('hasHighRisk', t.problem), TRUE, FALSE) hasHighRisk,
IF(FIND_IN_SET('hasTicketRequest', t.problem), TRUE, FALSE) hasTicketRequest,
IF(FIND_IN_SET('isTaxDataChecked', t.problem), FALSE, TRUE) isTaxDataChecked,
IF(FIND_IN_SET('hasComponentLack', s.problem), TRUE, FALSE) hasComponentLack,
IF(FIND_IN_SET('isTooLittle', t.problem)
AND util.VN_NOW() < (util.VN_CURDATE() + INTERVAL HOUR(zc.`hour`) HOUR) + INTERVAL MINUTE(zc.`hour`) MINUTE,
TRUE, FALSE) isTooLittle
FROM tmp.sale_getProblems sgp
JOIN ticket t ON t.id = sgp.ticketFk
LEFT JOIN sale s ON s.ticketFk = t.id
LEFT JOIN item i ON i.id = s.itemFk
LEFT JOIN zoneClosure zc ON zc.zoneFk = t.zoneFk
AND zc.dated = util.VN_CURDATE()
WHERE s.problem <> '' OR t.problem <> '' OR t.risk
GROUP BY t.id, s.id;
INSERT INTO tmp.sale_problems(ticketFk, isVip)
SELECT sgp.ticketFk, TRUE
FROM tmp.sale_getProblems sgp
JOIN client c ON c.id = sgp.clientFk
WHERE c.businessTypeFk = 'VIP'
ON DUPLICATE KEY UPDATE isVIP = TRUE;
CREATE OR REPLACE TEMPORARY TABLE tItemShelvingStock_byWarehouse
CREATE OR REPLACE TEMPORARY TABLE tItemShelving
(INDEX (itemFk, warehouseFk))
ENGINE = MEMORY
SELECT ish.itemFk itemFk,
@ -92,6 +48,14 @@ BEGIN
JOIN sector s ON s.id = p.sectorFk
GROUP BY ish.itemFk, s.warehouseFk;
-- Componentes: Algún componente obligatorio no se ha calcualdo
INSERT INTO tmp.saleProblems(saleFk, hasComponentLack)
SELECT s.id, TRUE
FROM tmp.sale ts
JOIN sale s ON s.id = ts.saleFk
WHERE FIND_IN_SET('hasComponentLack', s.problem)
GROUP BY s.id;
-- Disponible, faltas, inventario y retrasos
OPEN vCursor;
l: LOOP
@ -108,15 +72,11 @@ BEGIN
-- Faltas: visible, disponible y ubicado son menores que la cantidad vendida
CALL cache.visible_refresh(vVisibleCache, FALSE, vWarehouseFk);
INSERT INTO tmp.sale_problems(ticketFk, itemShortage, saleFk)
SELECT ticketFk, problem, saleFk
FROM (
SELECT sgp.ticketFk,
LEFT(CONCAT('F: ', GROUP_CONCAT(i.id, ' ', i.longName, ' ')), 250) problem,
s.id saleFk
FROM tmp.sale_getProblems sgp
JOIN ticket t ON t.id = sgp.ticketFk
JOIN sale s ON s.ticketFk = t.id
INSERT INTO tmp.saleProblems(saleFk, hasItemShortage)
SELECT s.id, TRUE
FROM tmp.sale ts
JOIN sale s ON s.id = ts.saleFk
JOIN ticket t ON t.id = s.ticketFk
JOIN item i ON i.id = s.itemFk
JOIN itemType it ON it.id = i.typeFk
JOIN itemCategory ic ON ic.id = it.categoryFk
@ -124,11 +84,11 @@ BEGIN
AND v.calc_id = vVisibleCache
LEFT JOIN cache.available av ON av.item_id = i.id
AND av.calc_id = vAvailableCache
LEFT JOIN tItemShelvingStock_byWarehouse issw ON issw.itemFk = i.id
AND issw.warehouseFk = t.warehouseFk
WHERE IFNULL(v.visible, 0) < s.quantity
AND IFNULL(av.available, 0) < 0
AND IFNULL(issw.visible, 0) < s.quantity
LEFT JOIN tItemShelving tis ON tis.itemFk = i.id
AND tis.warehouseFk = t.warehouseFk
WHERE (s.quantity > v.visible OR (s.quantity > 0 AND v.visible IS NULL))
AND (av.available < 0 OR av.available IS NULL)
AND (s.quantity > tis.visible OR tis.visible IS NULL)
AND NOT s.isPicked
AND NOT s.reserved
AND ic.merchandise
@ -136,28 +96,24 @@ BEGIN
AND NOT i.generic
AND util.VN_CURDATE() = vDate
AND t.warehouseFk = vWarehouseFk
GROUP BY sgp.ticketFk) sub
ON DUPLICATE KEY UPDATE itemShortage = sub.problem, saleFk = sub.saleFk;
GROUP BY s.id
ON DUPLICATE KEY UPDATE hasItemShortage = TRUE;
-- Inventario: Visible suficiente, pero ubicado menor a la cantidad vendida
INSERT INTO tmp.sale_problems(ticketFk, itemLost, saleFk)
SELECT ticketFk, problem, saleFk
FROM (
SELECT sgp.ticketFk,
LEFT(GROUP_CONCAT('I: ', i.id, ' ', i.longName, ' '), 250) problem,
s.id saleFk
FROM tmp.sale_getProblems sgp
JOIN ticket t ON t.id = sgp.ticketFk
JOIN sale s ON s.ticketFk = t.id
INSERT INTO tmp.saleProblems(saleFk, hasItemLost)
SELECT s.id, TRUE
FROM tmp.sale ts
JOIN sale s ON s.id = ts.saleFk
JOIN ticket t ON t.id = s.ticketFk
JOIN item i ON i.id = s.itemFk
JOIN itemType it ON it.id = i.typeFk
JOIN itemCategory ic ON ic.id = it.categoryFk
LEFT JOIN cache.visible v ON v.item_id = s.itemFk
AND v.calc_id = vVisibleCache
LEFT JOIN tItemShelvingStock_byWarehouse issw ON issw.itemFk = i.id
AND issw.warehouseFk = t.warehouseFk
WHERE IFNULL(v.visible, 0) >= s.quantity
AND IFNULL(issw.visible, 0) < s.quantity
LEFT JOIN tItemShelving tis ON tis.itemFk = i.id
AND tis.warehouseFk = t.warehouseFk
WHERE (v.visible >= s.quantity OR v.visible IS NULL)
AND (s.quantity > tis.visible AND tis.visible IS NOT NULL)
AND s.quantity > 0
AND NOT s.isPicked
AND NOT s.reserved
@ -166,20 +122,15 @@ BEGIN
AND NOT i.generic
AND util.VN_CURDATE() = vDate
AND t.warehouseFk = vWarehouseFk
GROUP BY sgp.ticketFk
) sub
ON DUPLICATE KEY UPDATE itemLost = sub.problem, saleFk = sub.saleFk;
GROUP BY s.id
ON DUPLICATE KEY UPDATE hasItemLost = TRUE;
-- Retraso: Disponible suficiente, pero no visible ni ubicado
INSERT INTO tmp.sale_problems(ticketFk, itemDelay, saleFk)
SELECT ticketFk, problem, saleFk
FROM (
SELECT sgp.ticketFk,
LEFT(GROUP_CONCAT('R: ', i.id, ' ', i.longName, ' '), 250) problem,
s.id saleFk
FROM tmp.sale_getProblems sgp
JOIN ticket t ON t.id = sgp.ticketFk
JOIN sale s ON s.ticketFk = t.id
INSERT INTO tmp.saleProblems(saleFk, hasItemDelay)
SELECT s.id, TRUE
FROM tmp.sale ts
JOIN sale s ON s.id = ts.saleFk
JOIN ticket t ON t.id = s.ticketFk
JOIN item i ON i.id = s.itemFk
JOIN itemType it ON it.id = i.typeFk
JOIN itemCategory ic ON ic.id = it.categoryFk
@ -187,11 +138,11 @@ BEGIN
AND v.calc_id = vVisibleCache
LEFT JOIN cache.available av ON av.item_id = i.id
AND av.calc_id = vAvailableCache
LEFT JOIN tItemShelvingStock_byWarehouse issw ON issw.itemFk = i.id
AND issw.warehouseFk = t.warehouseFk
WHERE IFNULL(v.visible, 0) < s.quantity
AND IFNULL(av.available, 0) >= 0
AND IFNULL(issw.visible, 0) < s.quantity
LEFT JOIN tItemShelving tis ON tis.itemFk = i.id
AND tis.warehouseFk = t.warehouseFk
WHERE (s.quantity > v.visible AND v.visible IS NULL)
AND (av.available >= 0 OR av.available IS NULL)
AND (s.quantity > tis.visible AND tis.visible IS NOT NULL)
AND s.quantity > 0
AND NOT s.isPicked
AND NOT s.reserved
@ -200,34 +151,29 @@ BEGIN
AND NOT i.generic
AND util.VN_CURDATE() = vDate
AND t.warehouseFk = vWarehouseFk
GROUP BY sgp.ticketFk
) sub
ON DUPLICATE KEY UPDATE itemDelay = sub.problem, saleFk = sub.saleFk;
GROUP BY s.id
ON DUPLICATE KEY UPDATE hasItemDelay = TRUE;
-- Redondeo: cantidad incorrecta con respecto al grouping
CALL buy_getUltimate(NULL, vWarehouseFk, vDate);
INSERT INTO tmp.sale_problems(ticketFk, hasRounding, saleFk)
SELECT ticketFk, problem, saleFk
FROM (
SELECT sgp.ticketFk,
s.id saleFk,
LEFT(GROUP_CONCAT('RE: ',i.id, ' ', IFNULL(i.longName,'') SEPARATOR ', '), 250) problem
FROM tmp.sale_getProblems sgp
JOIN ticket t ON t.id = sgp.ticketFk
INSERT INTO tmp.saleProblems(saleFk, hasRounding)
SELECT s.id, TRUE
FROM tmp.sale ts
JOIN sale s ON s.id = ts.saleFk
JOIN ticket t ON t.id = s.ticketFk
AND t.warehouseFk = vWarehouseFk
JOIN sale s ON s.ticketFk = sgp.ticketFk
JOIN item i ON i.id = s.itemFk
JOIN tmp.buyUltimate bu ON bu.itemFk = s.itemFk
JOIN buy b ON b.id = bu.buyFk
WHERE MOD(s.quantity, b.`grouping`)
GROUP BY sgp.ticketFk
)sub
ON DUPLICATE KEY UPDATE hasRounding = sub.problem, saleFk = sub.saleFk;
GROUP BY s.id
ON DUPLICATE KEY UPDATE hasRounding = TRUE;
DROP TEMPORARY TABLE tmp.buyUltimate;
END LOOP;
CLOSE vCursor;
DROP TEMPORARY TABLE tItemShelvingStock_byWarehouse;
DROP TEMPORARY TABLE tItemShelving;
END$$
DELIMITER ;

View File

@ -1,25 +1,25 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`sale_getProblemsByTicket`(IN vTicketFk INT, IN vIsTodayRelative TINYINT(1))
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`sale_getProblemsByTicket`(
IN vTicketFk INT,
IN vIsTodayRelative TINYINT(1)
)
BEGIN
/**
* Calcula los problemas de cada venta
* para un conjunto de tickets.
* Calcula los problemas de cada venta para un tickets.
*
* @return Problems result
*/
CREATE OR REPLACE TEMPORARY TABLE tmp.sale_getProblems
(INDEX (ticketFk))
CREATE OR REPLACE TEMPORARY TABLE tmp.sale
(INDEX (saleFk))
ENGINE = MEMORY
SELECT t.id ticketFk, t.clientFk, t.warehouseFk, t.shipped
FROM ticket t
WHERE t.id = vTicketFk;
SELECT id saleFk FROM sale WHERE ticketFk = vTicketFk;
CALL sale_getProblems(vIsTodayRelative);
SELECT * FROM tmp.sale_problems;
SELECT * FROM tmp.saleProblems;
DROP TEMPORARY TABLE
tmp.sale_getProblems,
tmp.sale_problems;
tmp.saleProblems,
tmp.sale;
END$$
DELIMITER ;

View File

@ -1,36 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_DelayTruck`(vWarehouserFk INT, vHour INT, vMinute INT)
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE vTicketFk INT;
DECLARE cur1 CURSOR FOR SELECT ticketFk FROM tTicket;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
CALL vn.productionControl(vWarehouserFk,0) ;
DROP TEMPORARY TABLE IF EXISTS tTicket;
CREATE TEMPORARY TABLE tTicket
SELECT ticketFk
FROM tmp.productionBuffer
JOIN alertLevel al ON al.code = 'FREE'
WHERE shipped = util.VN_CURDATE()
AND problem LIKE '%I:%'
AND (HH <= vHour OR HH = vHour AND mm < vMinute)
AND alertLevel = al.id;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO vTicketFk;
IF done THEN
LEAVE read_loop;
END IF;
CALL vn.ticket_DelayTruckSplit(vTicketFk);
END LOOP;
CLOSE cur1;
DROP TEMPORARY TABLE tTicket, tmp.productionBuffer;
END$$
DELIMITER ;

View File

@ -1,59 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_DelayTruckSplit`(
vTicketFk INT
)
BEGIN
/**
* Splita las lineas de ticket que no estan ubicadas
*
* @param vTicketFk Id ticket
*/
DECLARE vNewTicketFk INT;
DECLARE vTotalLines INT;
DECLARE vLinesToSplit INT;
DROP TEMPORARY TABLE IF EXISTS tmp.SalesToSplit;
SELECT COUNT(*) INTO vTotalLines
FROM sale
WHERE ticketFk = vTicketFk;
CREATE TEMPORARY TABLE tmp.SalesToSplit
SELECT s.id saleFk
FROM ticket t
JOIN sale s ON t.id = s.ticketFk
LEFT JOIN (
SELECT ish.itemFk itemFk,
SUM(ish.visible) visible,
s.warehouseFk warehouseFk
FROM itemShelving ish
JOIN shelving sh ON sh.id = ish.shelvingFk
JOIN parking p ON p.id = sh.parkingFk
JOIN sector s ON s.id = p.sectorFk
GROUP BY ish.itemFk,
s.warehouseFk
) issw ON issw.itemFk = s.itemFk
AND issw.warehouseFk = t.warehouseFk
WHERE s.quantity > IFNULL(issw.visible, 0)
AND s.quantity > 0
AND NOT s.isPicked
AND NOT s.reserved
AND t.id = vTicketFk;
SELECT COUNT(*) INTO vLinesToSplit
FROM tmp.SalesToSplit;
IF vLinesToSplit = vTotalLines AND vLinesToSplit > 0 THEN
SET vNewTicketFk = vTicketFk;
ELSE
CALL ticket_Clone(vTicketFk, vNewTicketFk);
UPDATE sale s
JOIN tmp.SalesToSplit sts ON sts.saleFk = s.id
SET s.ticketFk = vNewTicketFk;
END IF;
CALL ticket_setState(vNewTicketFk, 'FIXING');
DROP TEMPORARY TABLE tmp.SalesToSplit;
END$$
DELIMITER ;

View File

@ -1,53 +1,109 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_getProblems`(
vIsTodayRelative tinyint(1)
vIsTodayRelative TINYINT(1)
)
BEGIN
/**
* Calcula los problemas para un conjunto de tickets.
* Agrupados por ticket
*
* @table tmp.sale_getProblems(ticketFk, clientFk, warehouseFk, shipped) Identificadores de los tickets a calcular
* @return tmp.ticket_problems
* @param vIsTodayRelative Indica si se calcula el disponible como si todo saliera hoy
* @table tmp.ticket(ticketFk) Identificadores de los tickets a calcular
* @return tmp.ticketProblems, tmp.saleProblems
*/
CREATE OR REPLACE TEMPORARY TABLE tmp.sale (
saleFk INT(11),
PRIMARY KEY (saleFk)
) ENGINE = MEMORY
SELECT DISTINCT s.id saleFk
FROM tmp.ticket tt
JOIN ticket t ON t.id = tt.ticketFk
JOIN sale s ON s.ticketFk = t.id
GROUP BY s.id;
CALL sale_getProblems(vIsTodayRelative);
CREATE OR REPLACE TEMPORARY TABLE tmp.ticket_problems
(PRIMARY KEY (ticketFk))
ENGINE = MEMORY
SELECT ticketFk,
MAX(isFreezed) isFreezed,
MAX(risk) risk,
MAX(hasRisk) hasRisk,
MAX(hasHighRisk) hasHighRisk,
MAX(hasTicketRequest) hasTicketRequest,
MAX(itemShortage) itemShortage,
MIN(isTaxDataChecked) isTaxDataChecked,
MAX(hasComponentLack) hasComponentLack,
MAX(isTooLittle) isTooLittle,
MAX(itemDelay) itemDelay,
MAX(hasRounding) hasRounding,
MAX(itemLost) itemLost,
MAX(isVip) isVip,
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketProblems (
ticketFk INT(11),
isFreezed BOOL DEFAULT FALSE,
risk DECIMAL(10,1) DEFAULT 0,
hasRisk BOOL DEFAULT FALSE,
hasHighRisk BOOL DEFAULT FALSE,
hasTicketRequest BOOL DEFAULT FALSE,
isTaxDataChecked BOOL DEFAULT FALSE,
isTooLittle BOOL DEFAULT FALSE,
isVip BOOL DEFAULT FALSE,
hasItemShortage BOOL DEFAULT FALSE,
hasItemDelay BOOL DEFAULT FALSE,
hasItemLost BOOL DEFAULT FALSE,
hasComponentLack BOOL DEFAULT FALSE,
hasRounding BOOL DEFAULT FALSE,
PRIMARY KEY (ticketFk)
) ENGINE = MEMORY
WITH hasItemShortage AS(
SELECT s.ticketFk
FROM tmp.saleProblems sp
JOIN vn.sale s ON s.id = sp.saleFk
WHERE sp.hasItemShortage
GROUP BY s.ticketFk
),hasItemLost AS(
SELECT s.ticketFk
FROM tmp.saleProblems sp
JOIN vn.sale s ON s.id = sp.saleFk
WHERE sp.hasItemLost
GROUP BY s.ticketFk
),hasRounding AS(
SELECT s.ticketFk
FROM tmp.saleProblems sp
JOIN vn.sale s ON s.id = sp.saleFk
WHERE sp.hasRounding
GROUP BY s.ticketFk
), hasItemDelay AS(
SELECT s.ticketFk
FROM tmp.saleProblems sp
JOIN vn.sale s ON s.id = sp.saleFk
WHERE sp.hasItemDelay
GROUP BY s.ticketFk
), hasComponentLack AS(
SELECT s.ticketFk
FROM tmp.saleProblems sp
JOIN vn.sale s ON s.id = sp.saleFk
WHERE sp.hasComponentLack
GROUP BY s.ticketFk
)SELECT tt.ticketFk,
FIND_IN_SET('isFreezed', t.problem) > 0 isFreezed,
t.risk,
FIND_IN_SET('hasRisk', t.problem) > 0 hasRisk,
FIND_IN_SET('hasHighRisk', t.problem) > 0 hasHighRisk,
FIND_IN_SET('hasTicketRequest', t.problem) > 0 hasTicketRequest,
FIND_IN_SET('isTaxDataChecked', t.problem) > 0 isTaxDataChecked,
FIND_IN_SET('isTooLittle', t.problem) > 0
AND util.VN_NOW() < (util.VN_CURDATE() +
INTERVAL HOUR(zc.`hour`) HOUR) +
INTERVAL MINUTE(zc.`hour`) MINUTE isTooLittle,
c.businessTypeFk = 'VIP' isVip,
NOT (his.ticketFk IS NULL) hasItemShortage,
NOT (hid.ticketFk IS NULL) hasItemDelay,
NOT (hil.ticketFk IS NULL) hasItemLost,
NOT (hcl.ticketFk IS NULL) hasComponentLack,
NOT (hr.ticketFk IS NULL) hasRounding,
0 totalProblems
FROM tmp.sale_problems
GROUP BY ticketFk;
FROM tmp.ticket tt
JOIN vn.ticket t ON t.id = tt.ticketFk
JOIN vn.client c ON c.id = t.clientFk
LEFT JOIN hasItemShortage his ON his.ticketFk = t.id
LEFT JOIN hasItemLost hil ON hil.ticketFk = t.id
LEFT JOIN hasRounding hr ON hr.ticketFk = t.id
LEFT JOIN hasItemDelay hid ON hid.ticketFk = t.id
LEFT JOIN hasComponentLack hcl ON hcl.ticketFk = t.id
LEFT JOIN vn.zoneClosure zc ON zc.zoneFk = t.zoneFk
AND zc.dated = util.VN_CURDATE()
GROUP BY t.id;
UPDATE tmp.ticket_problems
SET totalProblems = (
(isFreezed) +
(hasHighRisk) +
(hasTicketRequest) +
(!isTaxDataChecked) +
(hasComponentLack) +
(itemDelay IS NOT NULL) +
(isTooLittle) +
(itemLost IS NOT NULL) +
(hasRounding IS NOT NULL) +
(itemShortage IS NOT NULL) +
(isVip)
);
UPDATE tmp.ticketProblems
SET totalProblems = isFreezed + hasHighRisk + hasTicketRequest +
isTaxDataChecked + hasComponentLack + hasItemDelay +
isTooLittle + hasItemLost + hasRounding + hasItemShortage + isVip;
DROP TEMPORARY TABLE tmp.sale_problems;
DROP TEMPORARY TABLE tmp.sale;
END$$
DELIMITER ;

View File

@ -1,14 +1,21 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`vehicle_checkNumberPlate`(vNumberPlate VARCHAR(10), vCountryCodeFk VARCHAR(2))
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`vehicle_checkNumberPlate`(
vNumberPlate VARCHAR(10),
vCountryCodeFk VARCHAR(2)
)
BEGIN
/**
* Comprueba si la matricula pasada tiene el formato correcto dependiendo del pais del vehiculo
* Comprueba si la matricula pasada tiene el formato
* correcto dependiendo del pais del vehiculo.
*
* @param vNumberPlate Número de matricula
* @param vCountryCodeFk Código de pais
*/
DECLARE vRegex VARCHAR(45);
SELECT vp.regex INTO vRegex
FROM vehiclePlateRegex vp
WHERE vp.countryCodeFk = vCountryCodeFk;
SELECT regex INTO vRegex
FROM vehiclePlateRegex
WHERE countryCodeFk = vCountryCodeFk;
IF NOT vNumberPlate REGEXP BINARY (vRegex)THEN
CALL util.throw(CONCAT('Error: la matricula ', vNumberPlate, ' no es valida para ',vCountryCodeFk));

View File

@ -20,6 +20,7 @@ trig:BEGIN
THEN
CALL entry_isEditable(OLD.entryFk);
CALL entry_isEditable(NEW.entryFk);
END IF;
SET NEW.editorFk = account.myUser_getId();

View File

@ -0,0 +1,26 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`roadmapStop_beforeDelete`
BEFORE DELETE ON `roadmapStop`
FOR EACH ROW
BEGIN
DECLARE vMaxEta DATETIME;
DECLARE vRoadmapEta DATETIME;
IF OLD.roadmapFk IS NOT NULL THEN
SELECT MAX(eta) INTO vMaxEta
FROM roadmapStop
WHERE roadmapFk = OLD.roadmapFk
AND id <> OLD.id;
SELECT eta INTO vRoadmapEta
FROM roadmap
WHERE id = OLD.roadmapFk;
IF vMaxEta <> vRoadmapEta OR vMaxEta IS NULL THEN
UPDATE roadmap
SET eta = vMaxEta
WHERE id = OLD.roadmapFk;
END IF;
END IF;
END$$
DELIMITER ;

View File

@ -3,8 +3,30 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`roadmapStop_beforeInser
BEFORE INSERT ON `roadmapStop`
FOR EACH ROW
BEGIN
DECLARE vRoadmapEta DATETIME;
SET NEW.editorFk = account.myUser_getId();
IF NEW.description IS NOT NULL THEN
SET NEW.description = UCASE(NEW.description);
END IF;
IF NEW.roadmapFk IS NOT NULL THEN
IF NEW.eta < (SELECT etd FROM roadmap WHERE id = NEW.roadmapFk) THEN
CALL util.throw('Departure time can not be after arrival time');
END IF;
END IF;
IF NEW.roadmapFk IS NOT NULL AND NEW.eta IS NOT NULL THEN
SELECT eta INTO vRoadmapEta
FROM roadmap
WHERE id = NEW.roadmapFk;
IF vRoadmapEta < NEW.eta OR vRoadmapEta IS NULL THEN
UPDATE roadmap
SET eta = NEW.eta
WHERE id = NEW.roadmapFk;
END IF;
END IF;
END$$
DELIMITER ;

View File

@ -3,8 +3,40 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`roadmapStop_beforeUpdat
BEFORE UPDATE ON `roadmapStop`
FOR EACH ROW
BEGIN
DECLARE vMaxEta DATETIME;
DECLARE vCurrentEta DATETIME;
SET NEW.editorFk = account.myUser_getId();
IF NOT (NEW.description <=> OLD.description) THEN
SET NEW.description = UCASE(NEW.description);
END IF;
IF (NOT (NEW.roadmapFk <=> OLD.roadmapFk) AND NEW.roadmapFk IS NOT NULL)
OR (NOT (NEW.eta <=> OLD.eta)) THEN
IF NEW.eta < (SELECT etd FROM roadmap WHERE id = NEW.roadmapFk) THEN
CALL util.throw('Departure time can not be after arrival time');
END IF;
SELECT MAX(eta) INTO vMaxEta
FROM roadmapStop
WHERE roadmapFk = NEW.roadmapFk
AND id <> OLD.id;
IF vMaxEta < NEW.eta OR vMaxEta IS NULL THEN
SET vMaxEta = NEW.eta;
END IF;
SELECT eta INTO vCurrentEta
FROM roadmap
WHERE id = NEW.roadmapFk;
IF (vMaxEta <> vCurrentEta OR vMaxEta IS NULL) OR vMaxEta IS NOT NULL THEN
UPDATE roadmap
SET eta = vMaxEta
WHERE id = NEW.roadmapFk;
END IF;
END IF;
END$$
DELIMITER ;

View File

@ -0,0 +1,17 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`roadmap_afterUpdate`
AFTER UPDATE ON `roadmap`
FOR EACH ROW
BEGIN
DECLARE vSeconds INT;
IF NOT (NEW.etd <=> OLD.etd) THEN
SET vSeconds = TIME_TO_SEC(TIMEDIFF(NEW.etd, OLD.etd));
IF vSeconds IS NOT NULL AND vSeconds <> 0 THEN
UPDATE roadmapStop
SET eta = eta + INTERVAL vSeconds SECOND
WHERE roadmapFk = NEW.id;
END IF;
END IF;
END$$
DELIMITER ;

View File

@ -3,10 +3,31 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`roadmap_beforeInsert`
BEFORE INSERT ON `roadmap`
FOR EACH ROW
BEGIN
SET NEW.editorFk = account.myUser_getId();
IF NEW.name IS NOT NULL THEN
SET NEW.name = UCASE(NEW.name);
END IF;
IF NEW.trailerPlate IS NOT NULL OR NEW.tugPlate IS NOT NULL THEN
SET NEW.m3 = (SELECT SUM(m3) FROM vehicle WHERE numberPlate IN (NEW.trailerPlate, NEW.tugPlate));
END IF;
IF NEW.driver1Fk IS NOT NULL THEN
SET NEW.driverName = (SELECT firstName FROM worker WHERE id = NEW.driver1Fk);
ELSE
SET NEW.driverName = NULL;
SET NEW.driverName = (SELECT CONCAT(w.firstName, ' ', w.lastName)
FROM worker w
WHERE w.id = NEW.driver1Fk);
SET NEW.phone = (SELECT COALESCE(w.phone, c.mobile, c.phone, c.mobile)
FROM worker w
LEFT JOIN client c ON c.id = w.id
WHERE w.id = NEW.driver1Fk);
END IF;
IF NEW.driverChangeFk IS NOT NULL THEN
SET NEW.driverChangeName = (SELECT CONCAT(w.firstName, ' ', w.lastName)
FROM worker w
WHERE w.id = NEW.driverChangeFk);
END IF;
END$$
DELIMITER ;

View File

@ -3,10 +3,39 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` TRIGGER `vn`.`roadmap_beforeUpdate`
BEFORE UPDATE ON `roadmap`
FOR EACH ROW
BEGIN
IF NEW.driver1Fk IS NOT NULL THEN
SET NEW.driverName = (SELECT firstName FROM worker WHERE id = NEW.driver1Fk);
ELSE
SET NEW.driverName = NULL;
SET NEW.editorFk = account.myUser_getId();
IF NOT (NEW.name <=> OLD.name) THEN
SET NEW.name = UCASE(NEW.name);
END IF;
IF NOT (NEW.trailerPlate <=> OLD.trailerPlate) OR NOT (NEW.tugPlate <=> OLD.tugPlate) THEN
SET NEW.m3 = (SELECT SUM(m3) FROM vehicle WHERE numberPlate IN (NEW.trailerPlate, NEW.tugPlate));
END IF;
IF NOT (NEW.driverName <=> OLD.driverName) THEN
SET NEW.driver1Fk = NULL;
END IF;
IF NOT (NEW.driver1Fk <=> OLD.driver1Fk) AND NEW.driver1Fk IS NOT NULL THEN
SET NEW.driverName = (SELECT CONCAT(w.firstName, ' ', w.lastName)
FROM worker w
WHERE w.id = NEW.driver1Fk);
SET NEW.phone = (SELECT COALESCE(w.phone, c.mobile, c.phone, c.mobile)
FROM worker w
LEFT JOIN client c ON c.id = w.id
WHERE w.id = NEW.driver1Fk);
END IF;
IF NOT (NEW.driverChangeName <=> OLD.driverChangeName) THEN
SET NEW.driverChangeFk = NULL;
END IF;
IF NOT (NEW.driverChangeFk <=> OLD.driverChangeFk) AND NEW.driverChangeFk IS NOT NULL THEN
SET NEW.driverChangeName = (SELECT CONCAT(w.firstName, ' ', w.lastName)
FROM worker w
WHERE w.id = NEW.driverChangeFk);
END IF;
END$$
DELIMITER ;

View File

@ -6,8 +6,7 @@ BEGIN
INSERT INTO zoneLog
SET `action` = 'delete',
`changedModel` = 'zoneIncluded',
`changedModelId` = OLD.zoneFk,
`changedModelId` = OLD.id,
`userFk` = account.myUser_getId();
END$$
DELIMITER ;

View File

@ -18,5 +18,6 @@ AS SELECT `p`.`id` AS `Id_Cubo`,
`p`.`base` AS `Base`,
`p`.`isBox` AS `box`,
`p`.`returnCost` AS `costeRetorno`,
`p`.`isActive` AS `isActive`
`p`.`isActive` AS `isActive`,
`p`.`flippingCost` AS `flippingCost`
FROM `vn`.`packaging` `p`

View File

@ -29,5 +29,6 @@ AS SELECT `a`.`id` AS `id`,
`a`.`invoiceInPaletizedFk` AS `invoiceInPaletizedFk`,
`a`.`observation` AS `observation`,
`a`.`hasFreightPrepaid` AS `hasFreightPrepaid`,
`a`.`propertyNumber` AS `propertyNumber`
`a`.`propertyNumber` AS `propertyNumber`,
`a`.`costPerKg` AS `costPerKg`
FROM `vn`.`awb` `a`

View File

@ -0,0 +1,27 @@
ALTER TABLE vn.business
ADD CONSTRAINT `business_companyCodeFk` FOREIGN KEY (`companyCodeFk`) REFERENCES `company` (`code`) ON DELETE CASCADE ON UPDATE CASCADE;
-- Auto-generated SQL script. Actual values for binary/complex data types may differ - what you see is the default string representation of values.
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('BusinessReasonEnd','find','*','ALLOW','ROLE','hr');
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('CalendarType','find','*','ALLOW','ROLE','hr');
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('OccupationCode','find','*','ALLOW','ROLE','hr');
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('BusinessReasonEnd','find','*','ALLOW','ROLE','hr');
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('WorkerBusinessProfessionalCategory','find','*','ALLOW','ROLE','hr');
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('WorkerBusinessAgreement','find','*','ALLOW','ROLE','hr');
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('WorkerBusinessType','find','*','ALLOW','ROLE','hr');
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('PayrollCategory','find','*','ALLOW','ROLE','hr');
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('Worker','__get__business','*','ALLOW','ROLE','hr');
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('Worker','__create__business','*','ALLOW','ROLE','hr');
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('Business','crud','*','ALLOW','ROLE','hr');

View File

@ -0,0 +1,14 @@
UPDATE vn.state
SET alertLevel = 1 -- ON_PREVIOUS
WHERE id IN (
36, -- Previa Revisando
37, -- Previa Revisado
26, -- Prep Previa
28, -- Previa OK
29, -- Previa Impreso
31, -- Polizon Impreso
32, -- Polizon OK
20, -- Asignado
23, -- URGENTE
33 -- Auto_Impreso
);

View File

@ -0,0 +1,3 @@
-- Place your SQL code here
INSERT INTO salix.ACL (model,property,accessType,permission,principalType,principalId)
VALUES ('Ticket','getTicketProblems','READ','ALLOW','ROLE','employee');

View File

@ -0,0 +1,2 @@
-- Place your SQL code here
ALTER TABLE vn.claimConfig ADD IF NOT EXISTS daysToClaim int(11) NOT NULL DEFAULT 7 COMMENT 'Dias para reclamar';

View File

@ -0,0 +1,6 @@
INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
VALUES
('WorkerDms', 'hasHighPrivs', 'READ', 'ALLOW', 'ROLE', 'hr'),
('Business', 'updateAttributes', 'WRITE', 'ALLOW', 'ROLE', 'hr'),
('Worker', '__get__business', 'READ', 'ALLOW', 'ROLE', 'hr')
;

View File

@ -0,0 +1,4 @@
ALTER TABLE vn.roadmap
DROP FOREIGN KEY roadmap_worker_FK_2,
DROP FOREIGN KEY roadmap_worker_FK,
DROP FOREIGN KEY roadmap_ibfk_2;

View File

@ -0,0 +1,20 @@
ALTER TABLE vn.roadmap
COMMENT='Rutas troncales (trailers)',
MODIFY COLUMN m3 int(10) unsigned DEFAULT NULL NULL COMMENT 'Capacidad máxima del remolque',
MODIFY COLUMN trailerPlate varchar(10) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT NULL NULL,
MODIFY COLUMN etd datetime NOT NULL COMMENT 'Tiempo estimado de salida',
MODIFY COLUMN `name` varchar(45) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL,
MODIFY COLUMN driver1Fk int(10) unsigned DEFAULT NULL NULL AFTER driverName,
MODIFY COLUMN driver2Fk int(10) unsigned DEFAULT NULL NULL AFTER driver1Fk,
ADD eta datetime DEFAULT NULL NULL COMMENT 'Tiempo estimado de llegada' AFTER etd,
ADD roadmapAddressFk int(11) DEFAULT NULL NULL AFTER `name`,
ADD dollyPlate varchar(10) DEFAULT NULL AFTER trailerPlate,
ADD tugPlate varchar(10) DEFAULT NULL AFTER dollyPlate,
ADD driverChangeName varchar(45) DEFAULT NULL AFTER driver2Fk,
ADD driverChangeFk int(10) unsigned DEFAULT NULL NULL AFTER driverChangeName;
-- Separamos los CHANGE por que si no arriba no se aplican
ALTER TABLE vn.roadmap
CHANGE userFk editorFk int(10) unsigned DEFAULT NULL NULL AFTER m3;
CREATE INDEX roadmap_etd_IDX USING BTREE ON vn.roadmap (etd);

View File

@ -0,0 +1,15 @@
UPDATE vn.roadmap
SET roadmapAddressFk = (SELECT MIN(addressFk) FROM vn.roadmapAddress),
eta = etd + INTERVAL 1 DAY;
ALTER TABLE vn.roadmap
ADD CONSTRAINT roadmap_roadmapAddress_FK FOREIGN KEY (roadmapAddressFk)
REFERENCES vn.roadmapAddress(addressFk) ON DELETE RESTRICT ON UPDATE CASCADE,
ADD CONSTRAINT roadmap_driver_FK FOREIGN KEY (driver1Fk)
REFERENCES vn.worker(id) ON DELETE RESTRICT ON UPDATE CASCADE,
ADD CONSTRAINT roadmap_driver_FK2 FOREIGN KEY (driver2Fk)
REFERENCES vn.worker(id) ON DELETE RESTRICT ON UPDATE CASCADE,
ADD CONSTRAINT roadmap_driverChange_FK FOREIGN KEY (driverChangeFk)
REFERENCES vn.worker(id) ON DELETE RESTRICT ON UPDATE CASCADE,
ADD CONSTRAINT roadmap_user_Fk FOREIGN KEY (editorFk)
REFERENCES account.user(id) ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -0,0 +1,7 @@
ALTER TABLE vn.roadmapStop
CHANGE userFk editorFk int(10) unsigned DEFAULT NULL NULL,
CHANGE addressFk roadmapAddressFk int(11) DEFAULT NULL NULL,
DROP FOREIGN KEY expeditionTruck_FK_2;
ALTER TABLE vn.roadmapStop ADD CONSTRAINT roadmapStop_roadmap_FK
FOREIGN KEY (roadmapFk) REFERENCES vn.roadmap(id) ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -0,0 +1,4 @@
ALTER TABLE vn.route
ADD roadmapStopFk int(11) NULL,
ADD CONSTRAINT route_roadmapStop_FK FOREIGN KEY (roadmapStopFk) REFERENCES vn.roadmapStop(id) ON DELETE RESTRICT ON UPDATE CASCADE,
CHANGE editorFk editorFk int(10) unsigned DEFAULT NULL NULL AFTER roadmapStopFk;

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.roadmapAddress
COMMENT='Direcciones de los troncales o también llamados puntos de distribución';

View File

@ -0,0 +1,11 @@
GRANT SELECT ON TABLE vn.roadmap TO 'delivery';
GRANT SELECT ON TABLE vn.roadmapStop TO 'delivery';
GRANT SELECT ON TABLE vn.roadmapAddress TO 'delivery';
GRANT DELETE, UPDATE, INSERT ON TABLE vn.roadmap TO 'deliveryBoss';
GRANT DELETE, UPDATE, INSERT ON TABLE vn.roadmapStop TO 'deliveryBoss';
GRANT DELETE, UPDATE, INSERT ON TABLE vn.roadmapAddress TO 'deliveryBoss';
-- Comentado debido a que da error porque ejecuta primero el script de la versión
-- GRANT EXECUTE ON PROCEDURE vn.roadmap_cloneDay TO 'deliveryBoss';
-- GRANT EXECUTE ON FUNCTION vn.getTimeBetweenRoadmapAddresses TO 'deliveryBoss';

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.route DROP FOREIGN KEY fk_route_1;
ALTER TABLE vn.route DROP COLUMN zoneFk;

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.vehicle
ADD typeFk enum('car','van','truck','trailer','tug', 'tugDolly','dolly') DEFAULT 'van' NOT NULL;

View File

@ -0,0 +1 @@
CREATE INDEX route_dated_IDX USING BTREE ON vn.route (dated);

View File

@ -0,0 +1,2 @@
ALTER TABLE vn.packaging
ADD COLUMN flippingCost decimal(10, 2) NOT NULL DEFAULT 0.00

View File

@ -0,0 +1 @@
ALTER TABLE vn.travel CHANGE appointment appointment__ datetime DEFAULT NULL COMMENT '@deprecated 2025-01-28';

View File

@ -0,0 +1,2 @@
ALTER TABLE `vn`.`awb`
ADD COLUMN `costPerKg` DECIMAL(10, 2) UNSIGNED DEFAULT NULL COMMENT 'Tarifa que indica a cuanto cuesta el kilo en ese vuelo';

View File

@ -0,0 +1,5 @@
INSERT IGNORE INTO util.notification
SET name = 'misallocation-warehouse',
description = 'Misallocation in warehouse';

View File

@ -253,5 +253,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."
"Ticket has been delivered out of order": "The ticket {{ticket}} of route {{{fullUrl}}} has been delivered out of order."
}

View File

@ -395,6 +395,7 @@
"All tickets have a route order": "Todos los tickets tienen orden de ruta",
"There are tickets to be invoiced": "La zona tiene tickets por facturar",
"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.",
"Ticket has been delivered out of order": "El ticket {{ticket}} {{{fullUrl}}} no ha sido entregado en su orden.",
"Price cannot be blank": "El precio no puede estar en blanco"
}

View File

@ -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."
"Ticket has been delivered out of order": "Le ticket {{ticket}} de la route {{{fullUrl}}} a été livré hors service."
}

View File

@ -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."
"Ticket has been delivered out of order": "O ticket {{ticket}} da rota {{{fullUrl}}} foi entregue fora de ordem."
}

View File

@ -4,7 +4,7 @@ const LoopBackContext = require('loopback-context');
describe('ClaimBeginning model()', () => {
const claimFk = 1;
const activeCtx = {
accessToken: {userId: 18},
accessToken: {userId: 72},
headers: {origin: 'localhost:5000'},
__: () => {}
};

View File

@ -3,22 +3,18 @@ const LoopBackContext = require('loopback-context');
describe('Claim createFromSales()', () => {
const ticketId = 23;
const newSale = [{
id: 31,
instance: 0,
quantity: 10
}];
const activeCtx = {
accessToken: {userId: 1},
const newSale = [{id: 31, instance: 0, quantity: 10}];
let activeCtx;
let ctx;
beforeEach(() => {
activeCtx = {
accessToken: {userId: 72},
headers: {origin: 'localhost:5000'},
__: () => {}
};
ctx = {req: activeCtx};
const ctx = {
req: activeCtx
};
beforeEach(() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});

View File

@ -1,6 +1,7 @@
const UserError = require('vn-loopback/util/user-error');
const LoopBackContext = require('loopback-context');
const moment = require('moment');
module.exports = Self => {
require('../methods/claim-beginning/importToNewRefundTicket')(Self);
@ -13,10 +14,51 @@ module.exports = Self => {
const options = ctx.options;
const models = Self.app.models;
const saleFk = ctx?.currentInstance?.saleFk || ctx?.instance?.saleFk;
const claimFk = ctx?.instance?.claimFk || ctx?.currentInstance?.claimFk;
const myOptions = {};
const accessToken = ctx?.options?.accessToken || LoopBackContext.getCurrentContext().active.accessToken;
const ctxToken = {req: {accessToken}};
if (typeof options == 'object')
Object.assign(myOptions, options);
const sale = await models.Sale.findById(saleFk, {fields: ['ticketFk', 'quantity']}, options);
const canCreateClaimAfterDeadline = models.ACL.checkAccessAcl(
ctxToken,
'Claim',
'createAfterDeadline',
myOptions
);
const canUpdateClaim = models.ACL.checkAccessAcl(
ctxToken,
'Claim',
'updateClaim',
myOptions
);
if (!canUpdateClaim && !canCreateClaimAfterDeadline)
throw new UserError(`You don't have permission to modify this claim`);
if (canUpdateClaim) {
const query = `
SELECT daysToClaim
FROM vn.claimConfig`;
const res = await Self.rawSql(query);
const daysToClaim = res[0]?.daysToClaim;
const claim = await models.Claim.findById(claimFk, {fields: ['created']}, options);
const claimDate = moment.utc(claim.created);
const currentDate = moment.utc();
const daysSinceSale = currentDate.diff(claimDate, 'days');
if (daysSinceSale > daysToClaim && !canCreateClaimAfterDeadline)
throw new UserError(`You can't modify this claim because the deadline has already passed`);
}
if (ctx.isNewInstance) {
const claim = await models.Claim.findById(ctx.instance.claimFk, {fields: ['ticketFk']}, options);
const claim = await models.Claim.findById(claimFk, {fields: ['ticketFk']}, options);
if (sale.ticketFk != claim.ticketFk)
throw new UserError(`Cannot create a new claimBeginning from a different ticket`);
}
@ -41,7 +83,7 @@ module.exports = Self => {
if (ctx.options && ctx.options.transaction)
myOptions.transaction = ctx.options.transaction;
const claimBeginning = ctx.instance ?? await Self.findById(ctx.where.id);
const claimBeginning = ctx.instance ?? await Self.findById(ctx?.where?.id);
const filter = {
where: {id: claimBeginning.claimFk},

View File

@ -158,10 +158,12 @@ module.exports = Self => {
a.provinceFk AS provinceAddressFk,
p.name AS province,
u.id AS salesPersonFk,
u.name AS salesPerson
u.name AS salesPerson,
co.name AS country
FROM client c
LEFT JOIN account.user u ON u.id = c.salesPersonFk
LEFT JOIN province p ON p.id = c.provinceFk
LEFT JOIN country co ON co.id = c.countryFk
JOIN address a ON a.clientFk = c.id
`
);

View File

@ -139,5 +139,23 @@
},
"Xdiario": {
"dataSource": "vn"
},
"BusinessReasonEnd": {
"dataSource": "vn"
},
"OccupationCode": {
"dataSource": "vn"
},
"WorkerBusinessProfessionalCategory": {
"dataSource": "vn"
},
"CalendarType": {
"dataSource": "vn"
},
"WorkerBusinessType": {
"dataSource": "vn"
},
"PayrollCategory": {
"dataSource": "vn"
}
}

View File

@ -0,0 +1,17 @@
{
"name": "BusinessReasonEnd",
"base": "VnModel",
"options": {
"mysql": {
"table": "businessReasonEnd"
}
},
"properties": {
"id": {
"type": "number"
},
"reason": {
"type": "string"
}
}
}

View File

@ -13,6 +13,63 @@
},
"workcenterFk" : {
"type": "number"
},
"companyCodeFk" : {
"type": "string"
},
"started" : {
"type": "date"
},
"ended" : {
"type": "date"
},
"workerBusiness" : {
"type": "string"
},
"reasonEndFk" : {
"type": "number"
},
"payedHolidays" : {
"type": "number"
},
"occupationCodeFk" : {
"type": "string"
},
"workerFk" : {
"type": "number"
},
"notes" : {
"type": "string"
},
"departmentFk": {
"type": "string"
},
"workerBusinessProfessionalCategoryFk": {
"type": "number"
},
"calendarTypeFk": {
"type": "string"
},
"isHourlyLabor": {
"type": "boolean"
},
"rate": {
"type": "number"
},
"workerBusinessCategoryFk": {
"type": "number"
},
"workerBusinessTypeFk": {
"type": "number"
},
"amount": {
"type": "number"
},
"workerBusinessAgreementFk": {
"type": "number"
},
"basicSalary": {
"type": "number"
}
},
"relations": {
@ -25,6 +82,59 @@
"type": "belongsTo",
"model": "Department",
"foreignKey": "departmentFk"
},
"workCenter": {
"type": "belongsTo",
"model": "WorkCenter",
"foreignKey": "workcenterFk"
},
"companyCode": {
"type": "belongsTo",
"model": "Company",
"foreignKey": "companyCodeFk",
"primaryKey": "code"
},
"reasonEnd": {
"type": "belongsTo",
"model": "BusinessReasonEnd",
"foreignKey": "reasonEndFk"
},
"occupationCode": {
"type": "belongsTo",
"model": "OccupationCode",
"foreignKey":"occupationCodeFk",
"primaryKey": "code"
},
"payrollCategory": {
"type": "belongsTo",
"model": "PayrollCategory",
"foreignKey":"workerBusinessCategoryFk"
},
"workerBusinessProfessionalCategory": {
"type": "belongsTo",
"model": "WorkerBusinessProfessionalCategory",
"foreignKey": "workerBusinessProfessionalCategoryFk"
},
"calendarType": {
"type": "belongsTo",
"model": "CalendarType",
"foreignKey": "calendarTypeFk"
},
"workerBusinessCategory": {
"type": "belongsTo",
"model": "WorkerBusinessCategory",
"foreignKey": "workerBusinessCategoryFk"
},
"workerBusinessType": {
"type": "belongsTo",
"model": "WorkerBusinessType",
"foreignKey": "workerBusinessTypeFk"
},
"workerBusinessAgreement": {
"type": "belongsTo",
"model": "WorkerBusinessAgreement",
"foreignKey": "workerBusinessAgreementFk"
}
}
}

View File

@ -0,0 +1,21 @@
{
"name": "CalendarType",
"base": "VnModel",
"options": {
"mysql": {
"table": "calendarType"
}
},
"properties": {
"id": {
"type": "number"
},
"description": {
"type": "string"
},
"hoursWeek": {
"type": "number"
},
"isPartial": "number"
}
}

View File

@ -0,0 +1,18 @@
{
"name": "OccupationCode",
"base": "VnModel",
"options": {
"mysql": {
"table": "occupationCode"
}
},
"properties": {
"code": {
"type": "string",
"id": true
},
"name": {
"type": "string"
}
}
}

View File

@ -0,0 +1,20 @@
{
"name": "PayrollCategory",
"base": "VnModel",
"options": {
"mysql": {
"table": "payrollCategories"
}
},
"properties": {
"id": {
"type": "number"
},
"description": {
"type": "string"
},
"rate": {
"type": "number"
}
}
}

View File

@ -0,0 +1,20 @@
{
"name": "WorkerBusinessProfessionalCategory",
"base": "VnModel",
"options": {
"mysql": {
"table": "professionalCategory"
}
},
"properties": {
"id": {
"type": "number"
},
"description": {
"type": "string"
},
"code": {
"type": "string"
}
}
}

View File

@ -0,0 +1,29 @@
{
"name": "WorkerBusinessAgreement",
"base": "VnModel",
"options": {
"mysql": {
"table": "workerBusinessAgreement"
}
},
"properties": {
"id": {
"type": "number"
},
"name": {
"type": "string"
},
"monthHolidays": {
"type": "number"
},
"yearsHours": {
"type": "number"
},
"started": {
"type": "date"
},
"ended": {
"type": "date"
}
}
}

View File

@ -0,0 +1,27 @@
{
"name": "WorkerBusinessType",
"base": "VnModel",
"options": {
"mysql": {
"table": "workerBusinessType"
}
},
"properties": {
"id": {
"type": "number",
"id": true
},
"name": {
"type": "string"
},
"isFullTime": {
"type": "number"
},
"isPermanent": {
"type": "number"
},
"hasHolidayEntitlement": {
"type": "number"
}
}
}

View File

@ -109,7 +109,8 @@ module.exports = Self => {
where: {
clientFk: clientFk,
shipped: {lte: maxShipped}
}
},
order: 'shipped DESC'
}, myOptions);
companyFk = company.companyFk;
}

View File

@ -52,7 +52,9 @@ module.exports = Self => {
JOIN vn.shelving sh ON sh.id = is2.shelvingFk
LEFT JOIN vn.parking p ON p.id = sh.parkingFk
LEFT JOIN vn.sector s ON s.id = p.sectorFk
WHERE sh.code = ? AND (? IS NULL OR is2.itemFk = ?)
WHERE sh.code = ?
AND (? IS NULL OR is2.itemFk = ?)
AND is2.visible > 0
),
itemShelvings AS (
SELECT is2.itemFk, is2.created, sh.code, p.pickingOrder, p.code AS parkingFk
@ -61,6 +63,7 @@ module.exports = Self => {
JOIN vn.shelving sh ON sh.id = is2.shelvingFk AND ai.code <> sh.code
JOIN vn.parking p ON p.id = sh.parkingFk
JOIN vn.sector s ON s.id = p.sectorFk
WHERE is2.visible > 0
),
parkingDestiny AS (
SELECT ? AS pickingOrder

View File

@ -146,7 +146,7 @@ module.exports = Self => {
await fs.symlink(rootRelative, destinationRoot);
}
}
if (description) {
if (description && branch == 'master') {
let formatDesc;
const mainBranches = new Set(['master', 'test', 'dev']);
if (mainBranches.has(branch))

View File

@ -258,10 +258,10 @@ module.exports = Self => {
stmts.push(`SET SESSION optimizer_search_depth = @_optimizer_search_depth`);
stmt = new ParameterizedSQL(`
CREATE OR REPLACE TEMPORARY TABLE tmp.sale_getProblems
CREATE OR REPLACE TEMPORARY TABLE tmp.ticket
(INDEX (ticketFk))
ENGINE = MEMORY
SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped
SELECT f.id ticketFk
FROM tmp.filter f
LEFT JOIN alertLevel al ON al.id = f.alertLevel
WHERE (al.code = 'FREE' OR f.alertLevel IS NULL)
@ -282,7 +282,7 @@ module.exports = Self => {
stmts.push('CALL ticket_getWarnings()');
stmt = new ParameterizedSQL(`
UPDATE tmp.ticket_problems
UPDATE tmp.ticketProblems
SET risk = IF(hasRisk, risk, 0)
`);
stmts.push(stmt);
@ -290,7 +290,7 @@ module.exports = Self => {
stmt = new ParameterizedSQL(`
SELECT *
FROM tmp.filter f
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id
LEFT JOIN tmp.ticketProblems tp ON tp.ticketFk = f.id
LEFT JOIN tmp.ticket_warnings tw ON tw.ticketFk = f.id
`);
stmts.push(stmt);
@ -307,8 +307,8 @@ module.exports = Self => {
{'tp.hasRisk': true},
{'tp.hasTicketRequest': true},
{'tp.hasComponentLack': true},
{'tp.isTaxDataChecked': false},
{'tp.itemShortage': {neq: null}},
{'tp.isTaxDataChecked': true},
{'tp.hasItemShortage': true},
{'tp.isTooLittle': true}
]};
} else if (hasProblems === false) {
@ -317,8 +317,8 @@ module.exports = Self => {
{'tp.hasRisk': false},
{'tp.hasTicketRequest': false},
{'tp.hasComponentLack': false},
{'tp.isTaxDataChecked': true},
{'tp.itemShortage': null},
{'tp.isTaxDataChecked': false},
{'tp.hasItemShortage': false},
{'tp.isTooLittle': false}
]};
}
@ -392,9 +392,9 @@ module.exports = Self => {
stmts.push(`
DROP TEMPORARY TABLE
tmp.ticket,
tmp.filter,
tmp.ticket_problems,
tmp.sale_getProblems,
tmp.ticketProblems,
tmp.sale_getWarnings,
tmp.ticket_warnings
`);

View File

@ -68,7 +68,7 @@ describe('SalesMonitor salesFilter()', () => {
const filter = {};
const result = await models.SalesMonitor.salesFilter(ctx, filter, options);
expect(result.length).toEqual(4);
expect(result.length).toEqual(5);
await tx.rollback();
} catch (e) {

View File

@ -18,7 +18,7 @@ describe('AgencyTerm filter()', () => {
const firstAgencyTerm = agencyTerms[0];
expect(firstAgencyTerm.routeFk).toEqual(1);
expect(agencyTerms.length).toEqual(7);
expect(agencyTerms.length).toEqual(5);
await tx.rollback();
} catch (e) {
@ -49,7 +49,7 @@ describe('AgencyTerm filter()', () => {
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(4);
expect(result.length).toEqual(2);
});
it('should return results matching "from" and "to"', async() => {
@ -72,7 +72,7 @@ describe('AgencyTerm filter()', () => {
const results = await models.AgencyTerm.filter(ctx, options);
expect(results.length).toBe(7);
expect(results.length).toBe(5);
await tx.rollback();
} catch (e) {
@ -90,7 +90,7 @@ describe('AgencyTerm filter()', () => {
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(2);
expect(result.length).toEqual(1);
expect(result[0].routeFk).toEqual(1);
});
@ -103,7 +103,7 @@ describe('AgencyTerm filter()', () => {
let result = await app.models.AgencyTerm.filter(ctx);
expect(result.length).toEqual(2);
expect(result.length).toEqual(1);
expect(result[0].routeFk).toEqual(2);
});
});

View File

@ -59,7 +59,7 @@ describe('Route filter()', () => {
};
const results = await models.Route.filter(ctx, options);
expect(results.length).toBe(9);
expect(results.length).toBe(7);
await tx.rollback();
} catch (e) {
@ -115,7 +115,7 @@ describe('Route filter()', () => {
};
const result = await app.models.Route.filter(ctx);
expect(result.length).toEqual(4);
expect(result.length).toEqual(2);
});
it('should return the routes matching "warehouseFk"', async() => {
@ -132,7 +132,7 @@ describe('Route filter()', () => {
let result = await app.models.Route.filter(ctx);
expect(result.length).toEqual(9);
expect(result.length).toEqual(7);
ctx.args.warehouseFk = 2;

View File

@ -1,7 +1,16 @@
const models = require('vn-loopback/server/server').models;
const routeId = 1;
describe('route optimizePriority())', function() {
describe('route optimizePriority()', function() {
beforeEach(() => {
spyOn(models.OsrmConfig, 'optimize').and.returnValue(
Promise.resolve([
{addressId: 1, position: 0},
{addressId: 2, position: 1}
])
);
});
it('should execute without throwing errors', async function() {
const tx = await models.Route.beginTransaction({});
let error;
@ -20,9 +29,10 @@ describe('route optimizePriority())', function() {
}
expect(error).toBeUndefined();
expect(models.OsrmConfig.optimize).toHaveBeenCalled();
});
it('should execute with error', async function() {
it('should execute with error when all tickets have a route order', async function() {
let error;
try {
await models.Route.optimizePriority(routeId);

View File

@ -75,11 +75,6 @@
"type": "hasMany",
"model": "Ticket",
"foreignKey": "routeFk"
},
"zone": {
"type": "belongsTo",
"model": "Zone",
"foreignKey": "zoneFk"
}
}
}

View File

@ -15,4 +15,4 @@ columns:
priceFixed: precio fijado
isPriceFixed: tiene precio fijado
isAdded: añadida
total: total
total: importe

View File

@ -30,7 +30,6 @@ module.exports = Self => {
SELECT
s.id AS saleFk,
t.id AS ticketFk,
t.landed,
s.concept,
s.itemFk,
s.quantity,
@ -41,11 +40,10 @@ module.exports = Self => {
INNER JOIN vn.sale s ON s.ticketFk = t.id
LEFT JOIN vn.claimBeginning cb ON cb.saleFk = s.id
WHERE (t.landed) >= TIMESTAMPADD(DAY, -7, ?)
AND t.id = ? AND cb.id IS NULL
ORDER BY t.landed DESC, t.id DESC`;
WHERE t.id = ?
AND cb.id IS NULL`;
const claimableSales = await Self.rawSql(query, [date, ticketFk], myOptions);
const claimableSales = await Self.rawSql(query, [ticketFk], myOptions);
return claimableSales;
};

View File

@ -34,8 +34,8 @@ module.exports = Self => {
state.code == 'PICKER_DESIGNED' || state.code == 'PRINTED'
)
);
const isAllowed = isAllEditable || isSomeEditable || state.alertLevel == 0;
const alertLevel = await models.AlertLevel.findOne({where: {code: 'FREE'}}, myOptions);
const isAllowed = isAllEditable || isSomeEditable || state.alertLevel == alertLevel.id;
return isAllowed;
};
};

View File

@ -35,9 +35,9 @@ describe('ticket editableStates()', () => {
const editableStates = await models.State.editableStates(ctx, filter, options);
const pickerDesignedState = editableStates.some(state => state.code == 'PICKER_DESIGNED');
const okState = editableStates.some(state => state.code == 'OK');
expect(pickerDesignedState).toBeTruthy();
expect(okState).toBeTruthy();
await tx.rollback();
} catch (e) {
@ -54,11 +54,11 @@ describe('ticket editableStates()', () => {
const employeeRole = 1;
const ctx = {req: {accessToken: {userId: employeeRole}}};
const filter = {where: {name: {like: '%Previa OK%'}}};
const filter = {where: {name: {like: '%Bloqueado%'}}};
const [editableStates] = await models.State.editableStates(ctx, filter, options);
expect(editableStates.name).toBe('Previa OK');
expect(editableStates.name).toBe('Bloqueado');
await tx.rollback();
} catch (e) {

View File

@ -288,21 +288,17 @@ module.exports = Self => {
stmts.push(stmt);
stmt = new ParameterizedSQL(`
CREATE OR REPLACE TEMPORARY TABLE tmp.sale_getProblems
CREATE OR REPLACE TEMPORARY TABLE tmp.ticket
(INDEX (ticketFk))
ENGINE = MEMORY
SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped
FROM tmp.filter f
LEFT JOIN alertLevel al ON al.id = f.alertLevel
WHERE (al.code = 'FREE' OR f.alertLevel IS NULL)
AND f.shipped >= ?
`, [date]);
SELECT f.id ticketFk
FROM tmp.filter f`);
stmts.push(stmt);
stmts.push('CALL ticket_getProblems(FALSE)');
stmt = new ParameterizedSQL(`
UPDATE tmp.ticket_problems
UPDATE tmp.ticketProblems
SET risk = IF(hasRisk, risk, 0)
`);
stmts.push(stmt);
@ -310,43 +306,19 @@ module.exports = Self => {
stmt = new ParameterizedSQL(`
SELECT f.*, tp.*
FROM tmp.filter f
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id
LEFT JOIN tmp.ticketProblems tp ON tp.ticketFk = f.id
`);
if (args.problems != undefined && (!args.from && !args.to))
throw new UserError('Choose a date range or days forward');
let condition;
let hasProblem;
let range;
let hasWhere;
switch (args.problems) {
case true:
condition = `or`;
hasProblem = true;
range = {neq: null};
hasWhere = true;
break;
case false:
condition = `and`;
hasProblem = null;
range = null;
hasWhere = true;
break;
if (typeof args.problems == 'boolean') {
let condition = 0;
if (args.problems)
condition = {neq: condition};
stmt.merge(conn.makeWhere({'tp.totalProblems': condition}));
}
const problems = {[condition]: [
{'tp.isFreezed': hasProblem},
{'tp.hasRisk': hasProblem},
{'tp.hasTicketRequest': hasProblem},
{'tp.itemShortage': range},
{'tp.hasRounding': hasProblem}
]};
if (hasWhere)
stmt.merge(conn.makeWhere(problems));
if (filter.order) {
if (typeof filter.order == 'string') filter.order = [filter.order];
const index = filter.order.findIndex(o => o.includes('stateFk'));
@ -365,8 +337,9 @@ module.exports = Self => {
stmts.push(
`DROP TEMPORARY TABLE
tmp.ticket,
tmp.filter,
tmp.ticket_problems`);
tmp.ticketProblems`);
const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql, myOptions);

View File

@ -98,14 +98,9 @@ module.exports = Self => {
for (let sale of sales) {
const problems = saleProblems.get(sale.id);
const itemStock = itemAvailable.get(sale.itemFk);
sale.available = itemStock.available;
sale.visible = itemStock.visible;
sale.claim = claimedSales.get(sale.id);
if (problems) {
sale.itemShortage = problems.itemShortage;
sale.hasTicketRequest = problems.hasTicketRequest;
sale.hasComponentLack = problems.hasComponentLack;
for (const problem in problems)
sale[problem] = problems[problem];
}
if (salesWithLogs.includes(sale.id))
sale.$hasLogs = true;

View File

@ -0,0 +1,83 @@
const {buildFilter} = require('vn-loopback/util/filter');
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
module.exports = Self => {
Self.remoteMethodCtx('getTicketProblems', {
description: 'Get problems for a ticket',
accessType: 'READ',
accepts: [{
arg: 'id',
type: 'number',
required: true,
description: 'The ticket id',
http: {source: 'path'}
}],
returns: {
type: ['object'],
root: true
},
http: {
path: `/:id/getTicketProblems`,
verb: 'get'
}
});
Self.getTicketProblems = async(ctx, id, options) => {
const myOptions = {};
const stmts = [];
const conn = Self.dataSource.connector;
let stmt;
const ticketId = id;
const where = buildFilter(ctx.args, param => {
switch (param) {
case 'id':
return {'t.id': ticketId};
}
});
if (typeof options == 'object')
Object.assign(myOptions, options);
stmt = new ParameterizedSQL(`
CREATE OR REPLACE TEMPORARY TABLE tmp.filter
(INDEX (id))
ENGINE = MEMORY
SELECT t.id
FROM ticket t
`);
stmt.merge(conn.makeWhere(where));
stmts.push(stmt);
stmt = new ParameterizedSQL(`
CREATE OR REPLACE TEMPORARY TABLE tmp.ticket
(INDEX (ticketFk))
ENGINE = MEMORY
SELECT f.id AS ticketFk
FROM tmp.filter f
`);
stmts.push(stmt);
stmts.push('CALL ticket_getProblems(FALSE)');
stmt = new ParameterizedSQL(`
SELECT f.*, tp.*
FROM tmp.filter f
LEFT JOIN tmp.ticketProblems tp ON tp.ticketFk = f.id
`);
const ticketsIndex = stmts.push(stmt) - 1;
stmts.push(`
DROP TEMPORARY TABLE IF EXISTS
tmp.filter,
tmp.ticket,
tmp.ticketProblems
`);
const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql, myOptions);
return result[ticketsIndex];
};
};

View File

@ -146,10 +146,10 @@ module.exports = Self => {
stmts.push(stmt);
stmt = new ParameterizedSQL(`
CREATE OR REPLACE TEMPORARY TABLE tmp.sale_getProblems
CREATE OR REPLACE TEMPORARY TABLE tmp.ticket
(INDEX (ticketFk))
ENGINE = MEMORY
SELECT f.id ticketFk, f.clientFk, f.warehouseFk, f.shipped, f.lines, f.liters
SELECT f.id ticketFk
FROM tmp.filter f
LEFT JOIN alertLevel al ON al.id = f.alertLevel
WHERE (al.code = 'FREE' OR f.alertLevel IS NULL)
@ -159,7 +159,7 @@ module.exports = Self => {
stmts.push('CALL ticket_getProblems(FALSE)');
stmt = new ParameterizedSQL(`
UPDATE tmp.ticket_problems
UPDATE tmp.ticketProblems
SET risk = IF(hasRisk, risk, 0)
`);
stmts.push(stmt);
@ -167,7 +167,7 @@ module.exports = Self => {
stmt = new ParameterizedSQL(`
SELECT f.*, tp.*
FROM tmp.filter f
LEFT JOIN tmp.ticket_problems tp ON tp.ticketFk = f.id
LEFT JOIN tmp.ticketProblems tp ON tp.ticketFk = f.id
`);
if (args.problems != undefined && (!args.originScopeDays && !args.futureScopeDays))
@ -175,20 +175,17 @@ module.exports = Self => {
let condition;
let hasProblem;
let range;
let hasWhere;
switch (args.problems) {
case true:
condition = `or`;
hasProblem = true;
range = {neq: null};
hasWhere = true;
break;
case false:
condition = `and`;
hasProblem = null;
range = null;
hasWhere = true;
break;
}
@ -198,7 +195,7 @@ module.exports = Self => {
{'tp.isFreezed': hasProblem},
{'tp.hasRisk': hasProblem},
{'tp.hasTicketRequest': hasProblem},
{'tp.itemShortage': range},
{'tp.hasItemShortage': hasProblem},
{'tp.hasComponentLack': hasProblem},
{'tp.isTooLittle': hasProblem},
{'tp.hasRounding': hasProblem}
@ -216,8 +213,9 @@ module.exports = Self => {
stmts.push(
`DROP TEMPORARY TABLE
tmp.ticket,
tmp.filter,
tmp.ticket_problems`);
tmp.ticketProblems`);
const sql = ParameterizedSQL.join(stmts, ';');
const result = await conn.executeStmt(sql, myOptions);

View File

@ -1,4 +1,5 @@
const UserError = require('vn-loopback/util/user-error');
const smtp = require('vn-print/core/smtp');
module.exports = Self => {
Self.remoteMethodCtx('saveSign', {
@ -31,6 +32,7 @@ module.exports = Self => {
Self.saveSign = async(ctx, tickets, location, signedTime, options) => {
const models = Self.app.models;
const myOptions = {userId: ctx.req.accessToken.userId};
const url = await Self.app.models.Url.getUrl('lilium');
let tx;
let ticket;
let dms;
@ -159,23 +161,24 @@ module.exports = Self => {
if (stateCode == 'DELIVERED' && ticket.priority) {
const orderState = await models.State.findOne({
where: {code: 'DELIVERED'},
fields: ['id']
fields: ['order']
}, myOptions);
const ticketIncorrect = 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
SELECT tls.ticketFk
FROM ticketLastState tls
JOIN ticketTracking tt ON tt.id = tls.ticketTrackingFk
JOIN ticket t ON t.id = tt.ticketFk
JOIN state s ON s.id = tt.stateFk
WHERE t.routeFk = ?
AND s.\`order\` < ?
AND priority <(SELECT t.priority
FROM ticket t
WHERE t.id = ?)`
, [ticket.routeFk, orderState.id, ticket.id], myOptions);
AND priority < (SELECT priority
FROM ticket
WHERE id = ?)
`, [ticket.routeFk, orderState.order, ticket.id], myOptions);
if (ticketIncorrect?.length > 0)
await sendMail(ctx, ticket.routeFk, ticket.id, ticket.zone().name);
await sendMail(ticket.routeFk, ticket.id, ticket.zone().name);
}
if (ticket?.address()?.province()?.country()?.code != 'ES' && ticket.$cmrFk) {
@ -189,26 +192,21 @@ module.exports = Self => {
throw e;
}
await models.Ticket.sendCmrEmail(ctx, externalTickets);
};
async function sendMail(ctx, route, ticket, zoneName) {
async function sendMail(route, ticket, zoneName) {
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', {
const fullUrl = `<a href="${url}route/${route}/summary">${route}</a>`;
await smtp.send({
to: 'repartos@verdnatura.es',
subject: $t('Incorrect delivery order alert on route', {
route,
zone: zoneName
});
const emailBody = $t('Ticket has been delivered out of order', {
}),
html: $t('Ticket has been delivered out of order', {
ticket,
fullUrl
});
await Self.app.models.Mail.create({
receiver: sendTo,
subject: emailSubject,
body: emailBody
})
});
}
};
};

View File

@ -42,11 +42,11 @@ describe('ticket filter()', () => {
const result = await models.Ticket.filter(ctx, filter, options);
const hasProblemTicket = result.some(ticket =>
ticket.isFreezed === true ||
ticket.hasRisk === true ||
ticket.hasTicketRequest === true ||
(typeof ticket.hasRounding === 'string' && ticket.hasRounding.trim().length > 0) ||
(typeof ticket.itemShortage === 'string' && ticket.itemShortage.trim().length > 0)
ticket.isFreezed == true ||
ticket.hasRisk == true ||
ticket.hasTicketRequest == true ||
ticket.hasRounding == true ||
ticket.hasItemShortage == true
);
expect(hasProblemTicket).toBe(true);
@ -80,11 +80,11 @@ describe('ticket filter()', () => {
const result = await models.Ticket.filter(ctx, filter, options);
result.forEach(ticket => {
expect(ticket.isFreezed).toEqual(null);
expect(ticket.hasRisk).toEqual(null);
expect(ticket.hasTicketRequest).toEqual(null);
expect(ticket.itemShortage).toEqual(null);
expect(ticket.hasRounding).toEqual(null);
expect(ticket.isFreezed).toEqual(0);
expect(ticket.hasRisk).toEqual(0);
expect(ticket.hasTicketRequest).toEqual(0);
expect(ticket.hasItemShortage).toEqual(0);
expect(ticket.hasRounding).toEqual(0);
});
await tx.rollback();

View File

@ -15,7 +15,6 @@ describe('ticket getSales()', () => {
expect(sales[1].item).toBeDefined();
expect(sales[2].item).toBeDefined();
expect(sales[3].item).toBeDefined();
expect(sales[0].claim).toBeDefined();
await tx.rollback();
} catch (e) {

View File

@ -0,0 +1,21 @@
const models = require('vn-loopback/server/server').models;
describe('ticket getTicketProblems()', () => {
const ctx = {req: {accessToken: 9}};
it('should return the problems of a ticket', async() => {
const tx = await models.Ticket.beginTransaction({});
try {
const options = {transaction: tx};
const problems = await models.Ticket.getTicketProblems(ctx, 11, options);
expect(problems[7].totalProblems).toEqual(3);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
});

View File

@ -6,7 +6,7 @@ describe('Ticket saveSign()', () => {
getLocale: () => {
return 'en';
},
__: () => {},
__: t => t,
accessToken: {userId: 9}
}
};

View File

@ -46,4 +46,5 @@ module.exports = function(Self) {
require('../methods/ticket/docuwareDownload')(Self);
require('../methods/ticket/myLastModified')(Self);
require('../methods/ticket/setWeight')(Self);
require('../methods/ticket/getTicketProblems')(Self);
};

View File

@ -1,5 +1,6 @@
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
const {mergeFilters, mergeWhere} = require('vn-loopback/util/filter');
const UserError = require('vn-loopback/util/user-error');
module.exports = Self => {
Self.remoteMethodCtx('filter', {
@ -33,7 +34,10 @@ module.exports = Self => {
const conn = Self.dataSource.connector;
const userId = ctx.req.accessToken.userId;
const models = Self.app.models;
const hasPrivs = await models.ACL.checkAccessAcl(ctx, 'WorkerDms', 'hasHighPrivs', '*');
if (!hasPrivs && userId !== id)
throw new UserError('You don\'t have enough privileges');
// Get ids alloweds
const account = await models.VnUser.findById(userId);

View File

@ -1,5 +1,4 @@
module.exports = Self => {
const validateTin = require('vn-loopback/util/validateTin');
require('../methods/worker/filter')(Self);
require('../methods/worker/mySubordinates')(Self);
require('../methods/worker/isSubordinate')(Self);
@ -23,26 +22,10 @@ module.exports = Self => {
require('../methods/worker/getAvailablePda')(Self);
require('../methods/worker/myTeam')(Self);
Self.validateAsync('fi', tinIsValid, {
message: 'Invalid TIN'
});
Self.canModifyAbsenceInPast = async(ctx, time) => {
const hasPrivs = await Self.app.models.ACL.checkAccessAcl(ctx, 'Worker', 'canModifyAbsenceInPast', 'WRITE');
const today = Date.vnNew();
today.setHours(0, 0, 0, 0);
return hasPrivs || today.getTime() < time;
};
async function tinIsValid(err, done) {
const country = await Self.app.models.Country.findOne({
fields: ['code'],
where: {id: this.originCountryFk}
});
const code = country ? country.code.toLowerCase() : null;
if (!this.fi || !validateTin(this.fi, code))
err();
done();
}
};

View File

@ -75,6 +75,9 @@
},
"isSsDiscounted": {
"type": "boolean"
},
"businessFk": {
"type": "number"
}
},
"relations": {
@ -103,6 +106,11 @@
"model": "WorkerDepartment",
"foreignKey": "id"
},
"currentBusiness": {
"type": "belongsTo",
"model": "Business",
"foreignKey": "businessFk"
},
"collegues": {
"type": "hasMany",
"model": "WorkerTeamCollegues",
@ -113,6 +121,11 @@
"model": "Locker",
"foreignKey": "workerFk"
},
"business": {
"type": "hasMany",
"model": "Business",
"foreignKey": "workerFk"
},
"medicalReview": {
"type": "hasMany",
"model": "MedicalReview",
@ -142,6 +155,11 @@
"type": "hasMany",
"model": "WorkerRelative",
"foreignKey": "workerFK"
},
"business": {
"type": "hasMany",
"model": "Business",
"foreignKey": "workerFk"
}
},
"acls": [
@ -259,12 +277,46 @@
"relation": "department",
"scope": {
"fields": [
"id",
"name"
]
}
}
}
},
{
"relation": "business",
"scope": {
"fields": [
"id",
"started",
"ended",
"reasonEndFk",
"departmentFk",
"workerBusinessProfessionalCategoryFk"
],
"include":[
{
"relation": "department",
"scope": {
"fields": ["id", "name"]
}
},
{
"relation": "reasonEnd",
"scope": {
"fields": ["id", "reason"]
}
},
{
"relation": "workerBusinessProfessionalCategory",
"scope": {
"fields": ["id", "description"]
}
}
]
}
},
{
"relation": "boss",
"scope": {
@ -312,7 +364,8 @@
"educationLevelFk",
"originCountryFk",
"maritalStatus",
"SSN"
"SSN",
"businessFk"
],
"include": [
{
@ -323,6 +376,48 @@
"phone"
]
}
},
{
"relation": "currentBusiness",
"scope": {
"fields": [
"id",
"started",
"ended",
"reasonEndFk",
"departmentFk",
"workerBusinessProfessionalCategoryFk"
],
"include": [
{
"relation": "reasonEnd",
"scope": {
"fields": [
"id",
"reason"
]
}
},
{
"relation": "department",
"scope": {
"fields": [
"id",
"name"
]
}
},
{
"relation": "workerBusinessProfessionalCategory",
"scope": {
"fields": [
"id",
"description"
]
}
}
]
}
}
]
}

View File

@ -1,6 +1,6 @@
{
"name": "salix-back",
"version": "25.06.0",
"version": "25.08.0",
"author": "Verdnatura Levante SL",
"description": "Salix backend",
"license": "GPL-3.0",

View File

@ -0,0 +1,11 @@
const Stylesheet = require(`vn-print/core/stylesheet`);
const path = require('path');
const vnPrintPath = path.resolve('print');
module.exports = new Stylesheet([
`${vnPrintPath}/common/css/spacing.css`,
`${vnPrintPath}/common/css/misc.css`,
`${vnPrintPath}/common/css/layout.css`,
`${vnPrintPath}/common/css/email.css`])
.mergeStyles();

View File

@ -0,0 +1,3 @@
subject: Misallocation of articles
title: Misallocation of articles
body: Misallocated articles have been placed in the warehouse that do not correspond to the entry location.

View File

@ -0,0 +1,3 @@
subject: Artículos mal ubicados
title: Artículos mal ubicados
body: Artículos mal ubicados han sido colocados en el almacén que no corresponden a la ubicación de la entrada.

View File

@ -0,0 +1,3 @@
subject: Artículos mal placés
title: Artículos mal placés
body: Artículos mal placés ont été stockés dans lentrepôt qui ne correspond pas à lemplacement de lentrée.

View File

@ -0,0 +1,3 @@
subject: Artículos mal colocados
title: Artículos mal colocados
body: Artículos mal colocados foram armazenados no armazém que não corresponde à localização da entrada.

View File

@ -0,0 +1,9 @@
<email-body>
<div class="grid-row">
<div class="grid-block vn-pa-ml">
<h1>{{ $t('title') }}</h1>
<p>{{$t('body')}}</p>
<p>{{action}}</p>
</div>
</div>
</email-body>

View File

@ -0,0 +1,15 @@
const Component = require(`vn-print/core/component`);
const emailBody = new Component('email-body');
module.exports = {
name: 'misallocation-warehouse',
components: {
'email-body': emailBody.build(),
},
props: {
action: {
type: String,
required: true
}
}
};

View File

@ -90,8 +90,7 @@
<td class="number">{{ticket.id}}</td>
<td width="50%">{{ticket.clientFk}} {{ticket.addressName}}</td>
<td v-if="ticket.addressFk" class="number">
{{ticket.addressFk.toString().substr(0, ticket.addressFk.toString().length - 3)}}
<span class="black-container"> {{ticket.addressFk.toString().substr(-3, 3)}} </span>
<span class="black-container"> {{ticket.addressFk.toString()}} </span>
</td>
<td class="number">{{ticket.packages}}</td>
<td>{{ticket.itemPackingTypes}}</td>

View File

@ -1,9 +1,9 @@
WITH tickets AS(
SELECT id, addressFk, packages, refFk
SELECT id, addressFk, packages, refFk, weight
FROM vn.ticket
WHERE refFk = ?
), volume AS(
SELECT SUM(volume) volume, MAX(weight)weight
SELECT SUM(sv.volume) volume, MAX(t.weight)weight
FROM tickets t
JOIN vn.saleVolume sv ON sv.ticketFk = t.id
), intrastat AS(