diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql
index d929c63ba8..20ed6d3f96 100644
--- a/db/dump/fixtures.before.sql
+++ b/db/dump/fixtures.before.sql
@@ -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
@@ -1092,12 +1090,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),
+ (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(), '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'),
@@ -1108,25 +1106,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
@@ -1947,9 +1945,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
@@ -2756,13 +2754,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),
@@ -2926,7 +2924,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`)
@@ -2940,7 +2939,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`)
@@ -3207,7 +3207,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
diff --git a/db/routines/bs/procedures/inventoryDiscrepancyDetail_replace.sql b/db/routines/bs/procedures/inventoryDiscrepancyDetail_replace.sql
index b698f0e3ea..6894b29289 100644
--- a/db/routines/bs/procedures/inventoryDiscrepancyDetail_replace.sql
+++ b/db/routines/bs/procedures/inventoryDiscrepancyDetail_replace.sql
@@ -9,7 +9,7 @@ BEGIN
DECLARE vCalc INT;
DECLARE vWarehouseFk INT;
- DECLARE cWarehouses CURSOR FOR
+ DECLARE cWarehouses CURSOR FOR
SELECT id
FROM vn.warehouse
WHERE isInventory;
@@ -22,13 +22,13 @@ BEGIN
read_loop: LOOP
SET vDone = FALSE;
FETCH cWarehouses INTO vWarehouseFk;
-
+
IF vDone THEN
LEAVE read_loop;
END IF;
-
+
CALL cache.visible_refresh(vCalc, FALSE, vWarehouseFk);
-
+
CREATE OR REPLACE TEMPORARY TABLE tVisible
SELECT itemFk, SUM(visible) totalVisible
FROM vn.itemShelving ish
@@ -37,7 +37,7 @@ BEGIN
JOIN vn.sector sc ON sc.id = p.sectorFk
WHERE sc.warehouseFk = vWarehouseFk
GROUP BY itemFk;
-
+
INSERT INTO inventoryDiscrepancyDetail(
warehouseFk,
itemFk,
@@ -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;
diff --git a/db/routines/vn/functions/getTimeBetweenRoadmapAddresses.sql b/db/routines/vn/functions/getTimeBetweenRoadmapAddresses.sql
new file mode 100644
index 0000000000..354aeb835f
--- /dev/null
+++ b/db/routines/vn/functions/getTimeBetweenRoadmapAddresses.sql
@@ -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 ;
diff --git a/db/routines/vn/procedures/entry_transfer.sql b/db/routines/vn/procedures/entry_transfer.sql
index 5b83ae5321..c02365092b 100644
--- a/db/routines/vn/procedures/entry_transfer.sql
+++ b/db/routines/vn/procedures/entry_transfer.sql
@@ -1,5 +1,5 @@
DELIMITER $$
-CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`entry_transfer`(
+CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`entry_transfer`(
vOriginalEntry INT,
OUT vNewEntryFk INT
)
diff --git a/db/routines/vn/procedures/itemShelvingRadar.sql b/db/routines/vn/procedures/itemShelvingRadar.sql
deleted file mode 100644
index 4bdd0873eb..0000000000
--- a/db/routines/vn/procedures/itemShelvingRadar.sql
+++ /dev/null
@@ -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 ;
diff --git a/db/routines/vn/procedures/itemShelving_inventory.sql b/db/routines/vn/procedures/itemShelving_inventory.sql
index 9ae96c7a89..b2179f4f84 100644
--- a/db/routines/vn/procedures/itemShelving_inventory.sql
+++ b/db/routines/vn/procedures/itemShelving_inventory.sql
@@ -24,7 +24,7 @@ BEGIN
SELECT ish.id,
p.pickingOrder,
p.code parking,
- ish.shelvingFk,
+ sh.code,
ish.itemFk,
i.longName,
ish.visible,
diff --git a/db/routines/vn/procedures/prepareTicketList.sql b/db/routines/vn/procedures/prepareTicketList.sql
index 7c44bb9946..cfe9492ee0 100644
--- a/db/routines/vn/procedures/prepareTicketList.sql
+++ b/db/routines/vn/procedures/prepareTicketList.sql
@@ -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
diff --git a/db/routines/vn/procedures/productionControl.sql b/db/routines/vn/procedures/productionControl.sql
index 813c65ab2c..605c06dba7 100644
--- a/db/routines/vn/procedures/productionControl.sql
+++ b/db/routines/vn/procedures/productionControl.sql
@@ -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,29 +96,31 @@ 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');
-
+
UPDATE tmp.productionBuffer pb
JOIN (
SELECT pb.ticketFk, GROUP_CONCAT(p.code) previaParking
@@ -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
@@ -266,19 +272,20 @@ proc: BEGIN
UPDATE tmp.productionBuffer pb
JOIN sale s ON s.ticketFk = pb.ticketFk
JOIN item i ON i.id = s.itemFk
- JOIN cache.last_buy lb ON lb.warehouse_id = vWarehouseFk
+ JOIN cache.last_buy lb ON lb.warehouse_id = vWarehouseFk
AND lb.item_id = s.itemFk
JOIN buy b ON b.id = lb.buy_id
JOIN packaging p ON p.id = b.packagingFk
SET pb.hasPlantTray = TRUE
WHERE p.isPlantTray
AND s.quantity >= b.packing
- AND pb.isOwn;
+ AND pb.isOwn;
DROP TEMPORARY TABLE
tmp.productionTicket,
tmp.ticket,
- tmp.ticket_problems,
+ tmp.ticketProblems,
+ tmp.saleProblems,
tmp.ticketWithPrevia,
tItemShelvingStock,
tItemPackingType;
diff --git a/db/routines/vn/procedures/roadmap_cloneDay.sql b/db/routines/vn/procedures/roadmap_cloneDay.sql
new file mode 100644
index 0000000000..8c38039473
--- /dev/null
+++ b/db/routines/vn/procedures/roadmap_cloneDay.sql
@@ -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 ;
diff --git a/db/routines/vn/procedures/sale_getProblems.sql b/db/routines/vn/procedures/sale_getProblems.sql
index e016f3ab4e..ca81660b8d 100644
--- a/db/routines/vn/procedures/sale_getProblems.sql
+++ b/db/routines/vn/procedures/sale_getProblems.sql
@@ -1,86 +1,42 @@
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 vWarehouseFk INT;
DECLARE vDate DATE;
- DECLARE vAvailableCache INT;
+ DECLARE vAvailableCache INT;
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);
+ DECLARE vCursor CURSOR FOR
+ 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
@@ -104,130 +68,112 @@ BEGIN
-- Disponible: no va a haber suficiente producto para preparar todos los pedidos
CALL cache.available_refresh(vAvailableCache, FALSE, vWarehouseFk, vDate);
-
- -- Faltas: visible, disponible y ubicado son menores que la cantidad vendida
+
+ -- 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
- 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 = i.id
- 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
- AND NOT s.isPicked
- AND NOT s.reserved
- AND ic.merchandise
- AND IF(vIsTodayRelative, TRUE, DATE(t.shipped) = vDate)
- 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;
-
- -- 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
- 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
- AND s.quantity > 0
- AND NOT s.isPicked
- AND NOT s.reserved
- AND ic.merchandise
- AND IF(vIsTodayRelative, TRUE, DATE(t.shipped) = vDate)
- 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;
-
- -- 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
- 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 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
- AND s.quantity > 0
- AND NOT s.isPicked
- AND NOT s.reserved
- AND ic.merchandise
- AND IF(vIsTodayRelative, TRUE, DATE(t.shipped) = vDate)
- 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;
+ 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
+ LEFT JOIN cache.visible v ON v.item_id = i.id
+ AND v.calc_id = vVisibleCache
+ LEFT JOIN cache.available av ON av.item_id = i.id
+ AND av.calc_id = vAvailableCache
+ 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
+ AND IF(vIsTodayRelative, TRUE, DATE(t.shipped) = vDate)
+ AND NOT i.generic
+ AND util.VN_CURDATE() = vDate
+ AND t.warehouseFk = vWarehouseFk
+ GROUP BY s.id
+ ON DUPLICATE KEY UPDATE hasItemShortage = TRUE;
- -- Redondeo: cantidad incorrecta con respecto al grouping
+ -- Inventario: Visible suficiente, pero ubicado menor a la cantidad vendida
+ 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 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
+ AND ic.merchandise
+ AND IF(vIsTodayRelative, TRUE, DATE(t.shipped) = vDate)
+ AND NOT i.generic
+ AND util.VN_CURDATE() = vDate
+ AND t.warehouseFk = vWarehouseFk
+ GROUP BY s.id
+ ON DUPLICATE KEY UPDATE hasItemLost = TRUE;
+
+ -- Retraso: Disponible suficiente, pero no visible ni ubicado
+ 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
+ LEFT JOIN cache.visible v ON v.item_id = s.itemFk
+ AND v.calc_id = vVisibleCache
+ LEFT JOIN cache.available av ON av.item_id = i.id
+ AND av.calc_id = vAvailableCache
+ 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
+ AND ic.merchandise
+ AND IF(vIsTodayRelative, TRUE, DATE(t.shipped) = vDate)
+ AND NOT i.generic
+ AND util.VN_CURDATE() = vDate
+ AND t.warehouseFk = vWarehouseFk
+ 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
- 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;
+
+ 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 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 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 ;
diff --git a/db/routines/vn/procedures/sale_getProblemsByTicket.sql b/db/routines/vn/procedures/sale_getProblemsByTicket.sql
index ff419989d4..fdfd5c8bc8 100644
--- a/db/routines/vn/procedures/sale_getProblemsByTicket.sql
+++ b/db/routines/vn/procedures/sale_getProblemsByTicket.sql
@@ -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))
- ENGINE = MEMORY
- SELECT t.id ticketFk, t.clientFk, t.warehouseFk, t.shipped
- FROM ticket t
- WHERE t.id = vTicketFk;
+ CREATE OR REPLACE TEMPORARY TABLE tmp.sale
+ (INDEX (saleFk))
+ ENGINE = MEMORY
+ SELECT id saleFk FROM sale WHERE ticketFk = vTicketFk;
- CALL sale_getProblems(vIsTodayRelative);
+ CALL sale_getProblems(vIsTodayRelative);
- SELECT * FROM tmp.sale_problems;
+ SELECT * FROM tmp.saleProblems;
- DROP TEMPORARY TABLE
- tmp.sale_getProblems,
- tmp.sale_problems;
+ DROP TEMPORARY TABLE
+ tmp.saleProblems,
+ tmp.sale;
END$$
DELIMITER ;
diff --git a/db/routines/vn/procedures/ticket_DelayTruck.sql b/db/routines/vn/procedures/ticket_DelayTruck.sql
deleted file mode 100644
index ebd0e5bafb..0000000000
--- a/db/routines/vn/procedures/ticket_DelayTruck.sql
+++ /dev/null
@@ -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 ;
diff --git a/db/routines/vn/procedures/ticket_DelayTruckSplit.sql b/db/routines/vn/procedures/ticket_DelayTruckSplit.sql
deleted file mode 100644
index 3d22207f3c..0000000000
--- a/db/routines/vn/procedures/ticket_DelayTruckSplit.sql
+++ /dev/null
@@ -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 ;
diff --git a/db/routines/vn/procedures/ticket_canMerge.sql b/db/routines/vn/procedures/ticket_canMerge.sql
index ce90551db1..d0737f00fc 100644
--- a/db/routines/vn/procedures/ticket_canMerge.sql
+++ b/db/routines/vn/procedures/ticket_canMerge.sql
@@ -3,7 +3,7 @@ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_canMerge`(vDat
BEGIN
/**
* Devuelve un listado de tickets susceptibles de fusionarse con otros tickets en el futuro
- *
+ *
* @param vDated Fecha en cuestión
* @param vScopeDays Dias en el futuro a sondear
* @param vLitersMax Volumen máximo de los tickets a catapultar
diff --git a/db/routines/vn/procedures/ticket_getProblems.sql b/db/routines/vn/procedures/ticket_getProblems.sql
index 1851bce47f..a65413f5f8 100644
--- a/db/routines/vn/procedures/ticket_getProblems.sql
+++ b/db/routines/vn/procedures/ticket_getProblems.sql
@@ -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 ;
diff --git a/db/routines/vn/procedures/vehicle_checkNumberPlate.sql b/db/routines/vn/procedures/vehicle_checkNumberPlate.sql
index cbbcbec639..b7444cac89 100644
--- a/db/routines/vn/procedures/vehicle_checkNumberPlate.sql
+++ b/db/routines/vn/procedures/vehicle_checkNumberPlate.sql
@@ -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));
diff --git a/db/routines/vn/triggers/buy_beforeUpdate.sql b/db/routines/vn/triggers/buy_beforeUpdate.sql
index 24246329bc..c67d44f6f3 100644
--- a/db/routines/vn/triggers/buy_beforeUpdate.sql
+++ b/db/routines/vn/triggers/buy_beforeUpdate.sql
@@ -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();
@@ -88,11 +89,11 @@ trig:BEGIN
SET NEW.buyerFk = vBuyerFk;
END IF;
- IF NOT (NEW.itemFk <=> OLD.itemFk) OR
- NOT (OLD.entryFk <=> NEW.entryFk) THEN
+ IF NOT (NEW.itemFk <=> OLD.itemFk) OR
+ NOT (OLD.entryFk <=> NEW.entryFk) THEN
CREATE OR REPLACE TEMPORARY TABLE tmp.buysToCheck
SELECT NEW.id;
- CALL buy_checkItem();
+ CALL buy_checkItem();
END IF;
END$$
DELIMITER ;
diff --git a/db/routines/vn/triggers/roadmapStop_beforeDelete.sql b/db/routines/vn/triggers/roadmapStop_beforeDelete.sql
new file mode 100644
index 0000000000..f0faeb8bef
--- /dev/null
+++ b/db/routines/vn/triggers/roadmapStop_beforeDelete.sql
@@ -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 ;
\ No newline at end of file
diff --git a/db/routines/vn/triggers/roadmapStop_beforeInsert.sql b/db/routines/vn/triggers/roadmapStop_beforeInsert.sql
index d71942feab..012702f3ed 100644
--- a/db/routines/vn/triggers/roadmapStop_beforeInsert.sql
+++ b/db/routines/vn/triggers/roadmapStop_beforeInsert.sql
@@ -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.description = UCASE(NEW.description);
+ 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 ;
+DELIMITER ;
\ No newline at end of file
diff --git a/db/routines/vn/triggers/roadmapStop_beforeUpdate.sql b/db/routines/vn/triggers/roadmapStop_beforeUpdate.sql
index c3cbf25976..c3142c8acc 100644
--- a/db/routines/vn/triggers/roadmapStop_beforeUpdate.sql
+++ b/db/routines/vn/triggers/roadmapStop_beforeUpdate.sql
@@ -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.description = UCASE(NEW.description);
+ 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 ;
diff --git a/db/routines/vn/triggers/roadmap_afterUpdate.sql b/db/routines/vn/triggers/roadmap_afterUpdate.sql
new file mode 100644
index 0000000000..7fcc31d922
--- /dev/null
+++ b/db/routines/vn/triggers/roadmap_afterUpdate.sql
@@ -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 ;
\ No newline at end of file
diff --git a/db/routines/vn/triggers/roadmap_beforeInsert.sql b/db/routines/vn/triggers/roadmap_beforeInsert.sql
index 2f9481140a..4dd9e686ce 100644
--- a/db/routines/vn/triggers/roadmap_beforeInsert.sql
+++ b/db/routines/vn/triggers/roadmap_beforeInsert.sql
@@ -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 ;
\ No newline at end of file
diff --git a/db/routines/vn/triggers/roadmap_beforeUpdate.sql b/db/routines/vn/triggers/roadmap_beforeUpdate.sql
index a2a02e96a5..4f355915bc 100644
--- a/db/routines/vn/triggers/roadmap_beforeUpdate.sql
+++ b/db/routines/vn/triggers/roadmap_beforeUpdate.sql
@@ -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 ;
\ No newline at end of file
diff --git a/db/routines/vn/triggers/zoneIncluded_afterDelete.sql b/db/routines/vn/triggers/zoneIncluded_afterDelete.sql
index 2990626cad..d3caedb13f 100644
--- a/db/routines/vn/triggers/zoneIncluded_afterDelete.sql
+++ b/db/routines/vn/triggers/zoneIncluded_afterDelete.sql
@@ -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 ;
diff --git a/db/routines/vn2008/views/Cubos.sql b/db/routines/vn2008/views/Cubos.sql
index 1b23af4fc9..7ca82e66e8 100644
--- a/db/routines/vn2008/views/Cubos.sql
+++ b/db/routines/vn2008/views/Cubos.sql
@@ -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`
diff --git a/db/routines/vn2008/views/awb.sql b/db/routines/vn2008/views/awb.sql
index 0105962880..a325718888 100644
--- a/db/routines/vn2008/views/awb.sql
+++ b/db/routines/vn2008/views/awb.sql
@@ -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`
diff --git a/db/versions/11076-blueChico/00-firstScript.sql b/db/versions/11076-blueChico/00-firstScript.sql
new file mode 100644
index 0000000000..75fdc0c56f
--- /dev/null
+++ b/db/versions/11076-blueChico/00-firstScript.sql
@@ -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');
+
diff --git a/db/versions/11202-limeRuscus/01-updateStateAlertLevel.sql b/db/versions/11202-limeRuscus/01-updateStateAlertLevel.sql
new file mode 100644
index 0000000000..c49ad71ed8
--- /dev/null
+++ b/db/versions/11202-limeRuscus/01-updateStateAlertLevel.sql
@@ -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
+ );
diff --git a/db/versions/11306-greenMonstera/00-firstScript.sql b/db/versions/11306-greenMonstera/00-firstScript.sql
new file mode 100644
index 0000000000..c9edc6bfb9
--- /dev/null
+++ b/db/versions/11306-greenMonstera/00-firstScript.sql
@@ -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');
diff --git a/db/versions/11334-grayRoebelini/00-firstScript.sql b/db/versions/11334-grayRoebelini/00-firstScript.sql
new file mode 100644
index 0000000000..5eb1076947
--- /dev/null
+++ b/db/versions/11334-grayRoebelini/00-firstScript.sql
@@ -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';
diff --git a/db/versions/11404-azureAnthurium/00-firstScript.sql b/db/versions/11404-azureAnthurium/00-firstScript.sql
new file mode 100644
index 0000000000..58e74cbfb6
--- /dev/null
+++ b/db/versions/11404-azureAnthurium/00-firstScript.sql
@@ -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')
+ ;
\ No newline at end of file
diff --git a/db/versions/11416-goldenTulip/00-firstScript.sql b/db/versions/11416-goldenTulip/00-firstScript.sql
new file mode 100644
index 0000000000..aa410c52f9
--- /dev/null
+++ b/db/versions/11416-goldenTulip/00-firstScript.sql
@@ -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;
diff --git a/db/versions/11416-goldenTulip/01-firstScript.sql b/db/versions/11416-goldenTulip/01-firstScript.sql
new file mode 100644
index 0000000000..565bf0f555
--- /dev/null
+++ b/db/versions/11416-goldenTulip/01-firstScript.sql
@@ -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);
diff --git a/db/versions/11416-goldenTulip/02-firstScript.sql b/db/versions/11416-goldenTulip/02-firstScript.sql
new file mode 100644
index 0000000000..c729c3de2f
--- /dev/null
+++ b/db/versions/11416-goldenTulip/02-firstScript.sql
@@ -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;
diff --git a/db/versions/11416-goldenTulip/03-firstScript.sql b/db/versions/11416-goldenTulip/03-firstScript.sql
new file mode 100644
index 0000000000..4df73139a6
--- /dev/null
+++ b/db/versions/11416-goldenTulip/03-firstScript.sql
@@ -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;
diff --git a/db/versions/11416-goldenTulip/04-firstScript.sql b/db/versions/11416-goldenTulip/04-firstScript.sql
new file mode 100644
index 0000000000..89833fe8b4
--- /dev/null
+++ b/db/versions/11416-goldenTulip/04-firstScript.sql
@@ -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;
diff --git a/db/versions/11416-goldenTulip/05-firstScript.sql b/db/versions/11416-goldenTulip/05-firstScript.sql
new file mode 100644
index 0000000000..588810ded9
--- /dev/null
+++ b/db/versions/11416-goldenTulip/05-firstScript.sql
@@ -0,0 +1,2 @@
+ALTER TABLE vn.roadmapAddress
+ COMMENT='Direcciones de los troncales o también llamados puntos de distribución';
diff --git a/db/versions/11416-goldenTulip/06-firstScript.sql b/db/versions/11416-goldenTulip/06-firstScript.sql
new file mode 100644
index 0000000000..82de52c674
--- /dev/null
+++ b/db/versions/11416-goldenTulip/06-firstScript.sql
@@ -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';
diff --git a/db/versions/11416-goldenTulip/07-firstScript.sql b/db/versions/11416-goldenTulip/07-firstScript.sql
new file mode 100644
index 0000000000..13cb9df894
--- /dev/null
+++ b/db/versions/11416-goldenTulip/07-firstScript.sql
@@ -0,0 +1,2 @@
+ALTER TABLE vn.route DROP FOREIGN KEY fk_route_1;
+ALTER TABLE vn.route DROP COLUMN zoneFk;
diff --git a/db/versions/11416-goldenTulip/08-firstScript.sql b/db/versions/11416-goldenTulip/08-firstScript.sql
new file mode 100644
index 0000000000..a7fdd5b86e
--- /dev/null
+++ b/db/versions/11416-goldenTulip/08-firstScript.sql
@@ -0,0 +1,2 @@
+ALTER TABLE vn.vehicle
+ ADD typeFk enum('car','van','truck','trailer','tug', 'tugDolly','dolly') DEFAULT 'van' NOT NULL;
diff --git a/db/versions/11416-goldenTulip/09-firstScript.sql b/db/versions/11416-goldenTulip/09-firstScript.sql
new file mode 100644
index 0000000000..5e61de07a7
--- /dev/null
+++ b/db/versions/11416-goldenTulip/09-firstScript.sql
@@ -0,0 +1 @@
+CREATE INDEX route_dated_IDX USING BTREE ON vn.route (dated);
diff --git a/db/versions/11425-aquaCordyline/00-firstScript.sql b/db/versions/11425-aquaCordyline/00-firstScript.sql
new file mode 100644
index 0000000000..f8b194e8a4
--- /dev/null
+++ b/db/versions/11425-aquaCordyline/00-firstScript.sql
@@ -0,0 +1,2 @@
+INSERT IGNORE INTO salix.ACL (model, property, accessType, permission, principalType, principalId)
+VALUES('Entry', 'transfer', 'WRITE', 'ALLOW', 'ROLE', 'coolerBoss');
diff --git a/db/versions/11427-azureChico/00-firstScript.sql b/db/versions/11427-azureChico/00-firstScript.sql
new file mode 100644
index 0000000000..34a8c8d14a
--- /dev/null
+++ b/db/versions/11427-azureChico/00-firstScript.sql
@@ -0,0 +1,2 @@
+ALTER TABLE vn.packaging
+ ADD COLUMN flippingCost decimal(10, 2) NOT NULL DEFAULT 0.00
\ No newline at end of file
diff --git a/db/versions/11428-blackArborvitae/00-firstScript.sql b/db/versions/11428-blackArborvitae/00-firstScript.sql
new file mode 100644
index 0000000000..4e9aecafa2
--- /dev/null
+++ b/db/versions/11428-blackArborvitae/00-firstScript.sql
@@ -0,0 +1 @@
+ALTER TABLE vn.travel CHANGE appointment appointment__ datetime DEFAULT NULL COMMENT '@deprecated 2025-01-28';
\ No newline at end of file
diff --git a/db/versions/11429-brownBamboo/00-firstScript.sql b/db/versions/11429-brownBamboo/00-firstScript.sql
new file mode 100644
index 0000000000..726856e767
--- /dev/null
+++ b/db/versions/11429-brownBamboo/00-firstScript.sql
@@ -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';
\ No newline at end of file
diff --git a/db/versions/11430-salmonRaphis/00-firstScript.sql b/db/versions/11430-salmonRaphis/00-firstScript.sql
new file mode 100644
index 0000000000..65f8fa43b1
--- /dev/null
+++ b/db/versions/11430-salmonRaphis/00-firstScript.sql
@@ -0,0 +1,5 @@
+
+
+INSERT IGNORE INTO util.notification
+ SET name = 'misallocation-warehouse',
+ description = 'Misallocation in warehouse';
diff --git a/loopback/locale/en.json b/loopback/locale/en.json
index 06428475fc..eeb32f545e 100644
--- a/loopback/locale/en.json
+++ b/loopback/locale/en.json
@@ -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."
}
\ No newline at end of file
diff --git a/loopback/locale/es.json b/loopback/locale/es.json
index f79dad236e..dca19e4a63 100644
--- a/loopback/locale/es.json
+++ b/loopback/locale/es.json
@@ -1,400 +1,401 @@
{
- "Phone format is invalid": "El formato del teléfono no es correcto",
- "You are not allowed to change the credit": "No tienes privilegios para modificar el crédito",
- "Unable to mark the equivalence surcharge": "No se puede marcar el recargo de equivalencia",
- "The default consignee can not be unchecked": "No se puede desmarcar el consignatario predeterminado",
- "Unable to default a disabled consignee": "No se puede poner predeterminado un consignatario desactivado",
- "Can't be blank": "No puede estar en blanco",
- "Invalid TIN": "NIF/CIF inválido",
- "TIN must be unique": "El NIF/CIF debe ser único",
- "A client with that Web User name already exists": "Ya existe un cliente con ese Usuario Web",
- "Is invalid": "Es inválido",
- "Quantity cannot be zero": "La cantidad no puede ser cero",
- "Enter an integer different to zero": "Introduce un entero distinto de cero",
- "Package cannot be blank": "El embalaje no puede estar en blanco",
- "The company name must be unique": "La razón social debe ser única",
- "Invalid email": "Correo electrónico inválido",
- "The IBAN does not have the correct format": "El IBAN no tiene el formato correcto",
- "That payment method requires an IBAN": "El método de pago seleccionado requiere un IBAN",
- "That payment method requires a BIC": "El método de pago seleccionado requiere un BIC",
- "State cannot be blank": "El estado no puede estar en blanco",
- "Worker cannot be blank": "El trabajador no puede estar en blanco",
- "Cannot change the payment method if no salesperson": "No se puede cambiar la forma de pago si no hay comercial asignado",
- "can't be blank": "El campo no puede estar vacío",
- "Observation type must be unique": "El tipo de observación no puede repetirse",
- "The credit must be an integer greater than or equal to zero": "The credit must be an integer greater than or equal to zero",
- "The grade must be similar to the last one": "El grade debe ser similar al último",
- "Only manager can change the credit": "Solo el gerente puede cambiar el credito de este cliente",
- "Name cannot be blank": "El nombre no puede estar en blanco",
- "Phone cannot be blank": "El teléfono no puede estar en blanco",
- "Period cannot be blank": "El periodo no puede estar en blanco",
- "Choose a company": "Selecciona una empresa",
- "Se debe rellenar el campo de texto": "Se debe rellenar el campo de texto",
- "Description should have maximum of 45 characters": "La descripción debe tener maximo 45 caracteres",
- "Cannot be blank": "El campo no puede estar en blanco",
- "The grade must be an integer greater than or equal to zero": "El grade debe ser un entero mayor o igual a cero",
- "Sample type cannot be blank": "El tipo de plantilla no puede quedar en blanco",
- "Description cannot be blank": "Se debe rellenar el campo de texto",
- "The price of the item changed": "El precio del artículo cambió",
- "The value should not be greater than 100%": "El valor no debe de ser mayor de 100%",
- "The value should be a number": "El valor debe ser un numero",
- "This order is not editable": "Esta orden no se puede modificar",
- "You can't create an order for a frozen client": "No puedes crear una orden para un cliente congelado",
- "You can't create an order for a client that has a debt": "No puedes crear una orden para un cliente con deuda",
- "is not a valid date": "No es una fecha valida",
- "Barcode must be unique": "El código de barras debe ser único",
- "The warehouse can't be repeated": "El almacén no puede repetirse",
- "The tag or priority can't be repeated for an item": "El tag o prioridad no puede repetirse para un item",
- "The observation type can't be repeated": "El tipo de observación no puede repetirse",
- "A claim with that sale already exists": "Ya existe una reclamación para esta línea",
- "You don't have enough privileges to change that field": "No tienes permisos para cambiar ese campo",
- "Warehouse cannot be blank": "El almacén no puede quedar en blanco",
- "Agency cannot be blank": "La agencia no puede quedar en blanco",
- "Not enough privileges to edit a client with verified data": "No tienes permisos para hacer cambios en un cliente con datos comprobados",
- "This address doesn't exist": "Este consignatario no existe",
- "You must delete the claim id %d first": "Antes debes borrar la reclamación %d",
- "You don't have enough privileges": "No tienes suficientes permisos",
- "Cannot check Equalization Tax in this NIF/CIF": "No se puede marcar RE en este NIF/CIF",
- "You can't make changes on the basic data of an confirmed order or with rows": "No puedes cambiar los datos básicos de una orden con artículos",
- "INVALID_USER_NAME": "El nombre de usuario solo debe contener letras minúsculas o, a partir del segundo carácter, números o subguiones, no está permitido el uso de la letra ñ",
- "You can't create a ticket for a frozen client": "No puedes crear un ticket para un cliente congelado",
- "You can't create a ticket for an inactive client": "No puedes crear un ticket para un cliente inactivo",
- "Tag value cannot be blank": "El valor del tag no puede quedar en blanco",
- "ORDER_EMPTY": "Cesta vacía",
- "You don't have enough privileges to do that": "No tienes permisos para cambiar esto",
- "NO SE PUEDE DESACTIVAR EL CONSIGNAT": "NO SE PUEDE DESACTIVAR EL CONSIGNAT",
- "Error. El NIF/CIF está repetido": "Error. El NIF/CIF está repetido",
- "Street cannot be empty": "Dirección no puede estar en blanco",
- "City cannot be empty": "Ciudad no puede estar en blanco",
- "Code cannot be blank": "Código no puede estar en blanco",
- "You cannot remove this department": "No puedes eliminar este departamento",
- "The extension must be unique": "La extensión debe ser unica",
- "The secret can't be blank": "La contraseña no puede estar en blanco",
- "We weren't able to send this SMS": "No hemos podido enviar el SMS",
- "This client can't be invoiced": "Este cliente no puede ser facturado",
- "You must provide the correction information to generate a corrective invoice": "Debes informar la información de corrección para generar una factura rectificativa",
- "This ticket can't be invoiced": "Este ticket no puede ser facturado",
- "You cannot add or modify services to an invoiced ticket": "No puedes añadir o modificar servicios a un ticket facturado",
- "This ticket can not be modified": "Este ticket no puede ser modificado",
- "The introduced hour already exists": "Esta hora ya ha sido introducida",
- "INFINITE_LOOP": "Existe una dependencia entre dos Jefes",
- "The sales of the receiver ticket can't be modified": "Las lineas del ticket al que envias no pueden ser modificadas",
- "NO_AGENCY_AVAILABLE": "No hay una zona de reparto disponible con estos parámetros",
- "ERROR_PAST_SHIPMENT": "No puedes seleccionar una fecha de envío en pasado",
- "The current ticket can't be modified": "El ticket actual no puede ser modificado",
- "The current claim can't be modified": "La reclamación actual no puede ser modificada",
- "The sales of this ticket can't be modified": "Las lineas de este ticket no pueden ser modificadas",
- "The sales do not exists": "La(s) línea(s) seleccionada(s) no existe(n)",
- "Please select at least one sale": "Por favor selecciona al menos una linea",
- "All sales must belong to the same ticket": "Todas las lineas deben pertenecer al mismo ticket",
- "NO_ZONE_FOR_THIS_PARAMETERS": "Para este día no hay ninguna zona configurada",
- "This item doesn't exists": "El artículo no existe",
- "NOT_ZONE_WITH_THIS_PARAMETERS": "Para este día no hay ninguna zona configurada",
- "Extension format is invalid": "El formato de la extensión es inválido",
- "Invalid parameters to create a new ticket": "Parámetros inválidos para crear un nuevo ticket",
- "This item is not available": "Este artículo no está disponible",
- "This postcode already exists": "Este código postal ya existe",
- "Concept cannot be blank": "El concepto no puede quedar en blanco",
- "File doesn't exists": "El archivo no existe",
- "You don't have privileges to change the zone": "No tienes permisos para cambiar la zona o para esos parámetros hay más de una opción de envío, hable con las agencias",
- "This ticket is already on weekly tickets": "Este ticket ya está en tickets programados",
- "Ticket id cannot be blank": "El id de ticket no puede quedar en blanco",
- "Weekday cannot be blank": "El día de la semana no puede quedar en blanco",
- "You can't delete a confirmed order": "No puedes borrar un pedido confirmado",
- "The social name has an invalid format": "El nombre fiscal tiene un formato incorrecto",
- "Invalid quantity": "Cantidad invalida",
- "This postal code is not valid": "Este código postal no es válido",
- "is invalid": "es inválido",
- "The postcode doesn't exist. Please enter a correct one": "El código postal no existe. Por favor, introduce uno correcto",
- "The department name can't be repeated": "El nombre del departamento no puede repetirse",
- "This phone already exists": "Este teléfono ya existe",
- "You cannot move a parent to its own sons": "No puedes mover un elemento padre a uno de sus hijos",
- "You can't create a claim for a removed ticket": "No puedes crear una reclamación para un ticket eliminado",
- "You cannot delete a ticket that part of it is being prepared": "No puedes eliminar un ticket en el que una parte que está siendo preparada",
- "You must delete all the buy requests first": "Debes eliminar todas las peticiones de compra primero",
- "You should specify a date": "Debes especificar una fecha",
- "You should specify at least a start or end date": "Debes especificar al menos una fecha de inicio o de fin",
- "Start date should be lower than end date": "La fecha de inicio debe ser menor que la fecha de fin",
- "You should mark at least one week day": "Debes marcar al menos un día de la semana",
- "Swift / BIC can't be empty": "Swift / BIC no puede estar vacío",
- "Customs agent is required for a non UEE member": "El agente de aduanas es requerido para los clientes extracomunitarios",
- "Incoterms is required for a non UEE member": "El incoterms es requerido para los clientes extracomunitarios",
- "Deleted sales from ticket": "He eliminado las siguientes lineas del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{deletions}}}",
- "Added sale to ticket": "He añadido la siguiente linea al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{addition}}}",
- "Changed sale discount": "He cambiado el descuento de las siguientes lineas al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
- "Created claim": "He creado la reclamación [{{claimId}}]({{{claimUrl}}}) de las siguientes lineas del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
- "Changed sale price": "He cambiado el precio de [{{itemId}} {{concept}}]({{{itemUrl}}}) ({{quantity}}) de {{oldPrice}}€ ➔ *{{newPrice}}€* del ticket [{{ticketId}}]({{{ticketUrl}}})",
- "Changed sale quantity": "He cambiado {{changes}} del ticket [{{ticketId}}]({{{ticketUrl}}})",
- "Changes in sales": "la cantidad de [{{itemId}} {{concept}}]({{{itemUrl}}}) de {{oldQuantity}} ➔ *{{newQuantity}}*",
- "State": "Estado",
- "regular": "normal",
- "reserved": "reservado",
- "Changed sale reserved state": "He cambiado el estado reservado de las siguientes lineas al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
- "Bought units from buy request": "Se ha comprado {{quantity}} unidades de [{{itemId}} {{concept}}]({{{urlItem}}}) para el ticket id [{{ticketId}}]({{{url}}})",
- "Deny buy request": "Se ha rechazado la petición de compra para el ticket id [{{ticketId}}]({{{url}}}). Motivo: {{observation}}",
- "MESSAGE_INSURANCE_CHANGE": "He cambiado el crédito asegurado del cliente [{{clientName}} ({{clientId}})]({{{url}}}) a *{{credit}} €*",
- "Changed client paymethod": "He cambiado la forma de pago del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
- "Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})",
- "Change quantity": "{{concept}} cambia de {{oldQuantity}} a {{newQuantity}}",
- "Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*, con el tipo de recogida *{{claimPickup}}*",
- "Claim state has changed to": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *{{newState}}*",
- "Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}",
- "ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto",
- "Distance must be lesser than 4000": "La distancia debe ser inferior a 4000",
- "This ticket is deleted": "Este ticket está eliminado",
- "Unable to clone this travel": "No ha sido posible clonar este travel",
- "This thermograph id already exists": "La id del termógrafo ya existe",
- "Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante",
- "ORDER_ALREADY_CONFIRMED": "ORDEN YA CONFIRMADA",
- "Invalid password": "Invalid password",
- "Password does not meet requirements": "La contraseña no cumple los requisitos",
- "Role already assigned": "Rol ya asignado",
- "Invalid role name": "Nombre de rol no válido",
- "Role name must be written in camelCase": "El nombre del rol debe escribirse en camelCase",
- "Email already exists": "El correo ya existe",
- "User already exists": "El/La usuario/a ya existe",
- "Absence change notification on the labour calendar": "Notificación de cambio de ausencia en el calendario laboral",
- "Record of hours week": "Registro de horas semana {{week}} año {{year}} ",
- "Created absence": "El empleado {{author}} ha añadido una ausencia de tipo '{{absenceType}}' a {{employee}} para el día {{dated}}.",
- "Deleted absence": "El empleado {{author}} ha eliminado una ausencia de tipo '{{absenceType}}' a {{employee}} del día {{dated}}.",
- "I have deleted the ticket id": "He eliminado el ticket id [{{id}}]({{{url}}})",
- "I have restored the ticket id": "He restaurado el ticket id [{{id}}]({{{url}}})",
- "You can only restore a ticket within the first hour after deletion": "Únicamente puedes restaurar el ticket dentro de la primera hora después de su eliminación",
- "Changed this data from the ticket": "He cambiado estos datos del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
- "agencyModeFk": "Agencia",
- "clientFk": "Cliente",
- "zoneFk": "Zona",
- "warehouseFk": "Almacén",
- "shipped": "F. envío",
- "landed": "F. entrega",
- "addressFk": "Consignatario",
- "companyFk": "Empresa",
- "agency": "Agencia",
- "delivery": "Reparto",
- "The social name cannot be empty": "La razón social no puede quedar en blanco",
- "The nif cannot be empty": "El NIF no puede quedar en blanco",
- "You need to fill sage information before you check verified data": "Debes rellenar la información de sage antes de marcar datos comprobados",
- "ASSIGN_ZONE_FIRST": "Asigna una zona primero",
- "Amount cannot be zero": "El importe no puede ser cero",
- "Company has to be official": "Empresa inválida",
- "You can not select this payment method without a registered bankery account": "No se puede utilizar este método de pago si no has registrado una cuenta bancaria",
- "Action not allowed on the test environment": "Esta acción no está permitida en el entorno de pruebas",
- "The selected ticket is not suitable for this route": "El ticket seleccionado no es apto para esta ruta",
- "New ticket request has been created with price": "Se ha creado una nueva petición de compra '{{description}}' para el día *{{shipped}}*, con una cantidad de *{{quantity}}* y un precio de *{{price}} €*",
- "New ticket request has been created": "Se ha creado una nueva petición de compra '{{description}}' para el día *{{shipped}}*, con una cantidad de *{{quantity}}*",
- "Swift / BIC cannot be empty": "Swift / BIC no puede estar vacío",
- "This BIC already exist.": "Este BIC ya existe.",
- "That item doesn't exists": "Ese artículo no existe",
- "There's a new urgent ticket:": "Hay un nuevo ticket urgente:",
- "Invalid account": "Cuenta inválida",
- "Compensation account is empty": "La cuenta para compensar está vacia",
- "This genus already exist": "Este genus ya existe",
- "This specie already exist": "Esta especie ya existe",
- "Client assignment has changed": "He cambiado el comercial ~*\"<{{previousWorkerName}}>\"*~ por *\"<{{currentWorkerName}}>\"* del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
- "None": "Ninguno",
- "The contract was not active during the selected date": "El contrato no estaba activo durante la fecha seleccionada",
- "Cannot add more than one '1/2 day vacation'": "No puedes añadir más de un 'Vacaciones 1/2 dia'",
- "This document already exists on this ticket": "Este documento ya existe en el ticket",
- "Some of the selected tickets are not billable": "Algunos de los tickets seleccionados no son facturables",
- "You can't invoice tickets from multiple clients": "No puedes facturar tickets de multiples clientes",
- "nickname": "nickname",
- "INACTIVE_PROVIDER": "Proveedor inactivo",
- "This client is not invoiceable": "Este cliente no es facturable",
- "serial non editable": "Esta serie no permite asignar la referencia",
- "Max shipped required": "La fecha límite es requerida",
- "Can't invoice to future": "No se puede facturar a futuro",
- "Can't invoice to past": "No se puede facturar a pasado",
- "This ticket is already invoiced": "Este ticket ya está facturado",
- "A ticket with an amount of zero can't be invoiced": "No se puede facturar un ticket con importe cero",
- "A ticket with a negative base can't be invoiced": "No se puede facturar un ticket con una base negativa",
- "Global invoicing failed": "[Facturación global] No se han podido facturar algunos clientes",
- "Wasn't able to invoice the following clients": "No se han podido facturar los siguientes clientes",
- "Can't verify data unless the client has a business type": "No se puede verificar datos de un cliente que no tiene tipo de negocio",
- "You don't have enough privileges to set this credit amount": "No tienes suficientes privilegios para establecer esta cantidad de crédito",
- "You can't change the credit set to zero from a financialBoss": "No puedes cambiar el cŕedito establecido a cero por un jefe de finanzas",
- "Amounts do not match": "Las cantidades no coinciden",
- "The PDF document does not exist": "El documento PDF no existe. Prueba a regenerarlo desde la opción 'Regenerar PDF factura'",
- "The type of business must be filled in basic data": "El tipo de negocio debe estar rellenado en datos básicos",
- "You can't create a claim from a ticket delivered more than seven days ago": "No puedes crear una reclamación de un ticket entregado hace más de siete días",
- "The worker has hours recorded that day": "El trabajador tiene horas fichadas ese día",
- "The worker has a marked absence that day": "El trabajador tiene marcada una ausencia ese día",
- "You can not modify is pay method checked": "No se puede modificar el campo método de pago validado",
- "The account size must be exactly 10 characters": "El tamaño de la cuenta debe ser exactamente de 10 caracteres",
- "Can't transfer claimed sales": "No puedes transferir lineas reclamadas",
- "You don't have privileges to create refund": "No tienes permisos para crear un abono",
- "The item is required": "El artículo es requerido",
- "The agency is already assigned to another autonomous": "La agencia ya está asignada a otro autónomo",
- "date in the future": "Fecha en el futuro",
- "reference duplicated": "Referencia duplicada",
- "This ticket is already a refund": "Este ticket ya es un abono",
- "isWithoutNegatives": "Sin negativos",
- "routeFk": "routeFk",
- "Can't change the password of another worker": "No se puede cambiar la contraseña de otro trabajador",
- "No hay un contrato en vigor": "No hay un contrato en vigor",
- "No se permite fichar a futuro": "No se permite fichar a futuro",
- "No está permitido trabajar": "No está permitido trabajar",
- "Fichadas impares": "Fichadas impares",
- "Descanso diario 12h.": "Descanso diario 12h.",
- "Descanso semanal 36h. / 72h.": "Descanso semanal 36h. / 72h.",
- "Dirección incorrecta": "Dirección incorrecta",
- "Modifiable user details only by an administrator": "Detalles de usuario modificables solo por un administrador",
- "Modifiable password only via recovery or by an administrator": "Contraseña modificable solo a través de la recuperación o por un administrador",
- "Not enough privileges to edit a client": "No tienes suficientes privilegios para editar un cliente",
- "This route does not exists": "Esta ruta no existe",
- "Claim pickup order sent": "Reclamación Orden de recogida enviada [{{claimId}}]({{{claimUrl}}}) al cliente *{{clientName}}*",
- "You don't have grant privilege": "No tienes privilegios para dar privilegios",
- "You don't own the role and you can't assign it to another user": "No eres el propietario del rol y no puedes asignarlo a otro usuario",
- "Ticket merged": "Ticket [{{originId}}]({{{originFullPath}}}) ({{{originDated}}}) fusionado con [{{destinationId}}]({{{destinationFullPath}}}) ({{{destinationDated}}})",
- "Already has this status": "Ya tiene este estado",
- "There aren't records for this week": "No existen registros para esta semana",
- "Empty data source": "Origen de datos vacio",
- "App locked": "Aplicación bloqueada por el usuario {{userId}}",
- "Email verify": "Correo de verificación",
- "Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment",
- "Receipt's bank was not found": "No se encontró el banco del recibo",
- "This receipt was not compensated": "Este recibo no ha sido compensado",
- "Client's email was not found": "No se encontró el email del cliente",
- "Negative basis": "Base negativa",
- "This worker code already exists": "Este codigo de trabajador ya existe",
- "This personal mail already exists": "Este correo personal ya existe",
- "This worker already exists": "Este trabajador ya existe",
- "App name does not exist": "El nombre de aplicación no es válido",
- "Try again": "Vuelve a intentarlo",
- "Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9",
- "Failed to upload delivery note": "Error al subir albarán {{id}}",
- "The DOCUWARE PDF document does not exists": "El documento PDF Docuware no existe",
- "It is not possible to modify tracked sales": "No es posible modificar líneas de pedido que se hayan empezado a preparar",
- "It is not possible to modify sales that their articles are from Floramondo": "No es posible modificar líneas de pedido cuyos artículos sean de Floramondo",
- "It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas",
- "A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país.",
- "There is no assigned email for this client": "No hay correo asignado para este cliente",
- "Exists an invoice with a future date": "Existe una factura con fecha posterior",
- "Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite",
- "Warehouse inventory not set": "El almacén inventario no está establecido",
- "This locker has already been assigned": "Esta taquilla ya ha sido asignada",
- "Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº %s",
- "Not exist this branch": "La rama no existe",
- "This ticket cannot be signed because it has not been boxed": "Este ticket no puede firmarse porque no ha sido encajado",
- "Collection does not exist": "La colección no existe",
- "Cannot obtain exclusive lock": "No se puede obtener un bloqueo exclusivo",
- "Insert a date range": "Inserte un rango de fechas",
- "Added observation": "{{user}} añadió esta observacion: {{text}} {{defaulterId}} ({{{defaulterUrl}}})",
- "Comment added to client": "Observación añadida al cliente {{clientFk}}",
- "Invalid auth code": "Código de verificación incorrecto",
- "Invalid or expired verification code": "Código de verificación incorrecto o expirado",
- "Cannot create a new claimBeginning from a different ticket": "No se puede crear una línea de reclamación de un ticket diferente al origen",
- "company": "Compañía",
- "country": "País",
- "clientId": "Id cliente",
- "clientSocialName": "Cliente",
- "amount": "Importe",
- "taxableBase": "Base",
- "ticketFk": "Id ticket",
- "isActive": "Activo",
- "hasToInvoice": "Facturar",
- "isTaxDataChecked": "Datos comprobados",
- "comercialId": "Id comercial",
- "comercialName": "Comercial",
- "Pass expired": "La contraseña ha caducado, cambiela desde Salix",
- "Invalid NIF for VIES": "Invalid NIF for VIES",
- "Ticket does not exist": "Este ticket no existe",
- "Ticket is already signed": "Este ticket ya ha sido firmado",
- "Authentication failed": "Autenticación fallida",
- "You can't use the same password": "No puedes usar la misma contraseña",
- "You can only add negative amounts in refund tickets": "Solo se puede añadir cantidades negativas en tickets abono",
- "Fecha fuera de rango": "Fecha fuera de rango",
- "Error while generating PDF": "Error al generar PDF",
- "Error when sending mail to client": "Error al enviar el correo al cliente",
- "Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico",
- "The renew period has not been exceeded": "El periodo de renovación no ha sido superado",
- "Valid priorities": "Prioridades válidas: %d",
- "hasAnyNegativeBase": "Base negativa para los tickets: {{ticketsIds}}",
- "hasAnyPositiveBase": "Base positivas para los tickets: {{ticketsIds}}",
- "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado",
- "This ticket cannot be left empty.": "Este ticket no se puede dejar vacío. %s",
- "The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias",
- "You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado",
- "This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado",
- "You don't have enough privileges.": "No tienes suficientes permisos.",
- "This ticket is locked": "Este ticket está bloqueado.",
- "This ticket is not editable.": "Este ticket no es editable.",
- "The ticket doesn't exist.": "No existe el ticket.",
- "Social name should be uppercase": "La razón social debe ir en mayúscula",
- "Street should be uppercase": "La dirección fiscal debe ir en mayúscula",
- "Ticket without Route": "Ticket sin ruta",
- "Select a different client": "Seleccione un cliente distinto",
- "Fill all the fields": "Rellene todos los campos",
- "The response is not a PDF": "La respuesta no es un PDF",
- "Booking completed": "Reserva completada",
- "The ticket is in preparation": "El ticket [{{ticketId}}]({{{ticketUrl}}}) del comercial {{salesPersonId}} está en preparación",
- "The notification subscription of this worker cant be modified": "La subscripción a la notificación de este trabajador no puede ser modificada",
- "User disabled": "Usuario desactivado",
- "The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima",
- "quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima",
- "Cannot past travels with entries": "No se pueden pasar envíos con entradas",
- "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}",
- "This claim has been updated": "La reclamación con Id: {{claimId}}, ha sido actualizada",
- "This user does not have an assigned tablet": "Este usuario no tiene tablet asignada",
- "Field are invalid": "El campo '{{tag}}' no es válido",
- "Incorrect pin": "Pin incorrecto.",
- "You already have the mailAlias": "Ya tienes este alias de correo",
- "The alias cant be modified": "Este alias de correo no puede ser modificado",
- "No tickets to invoice": "No hay tickets para facturar que cumplan los requisitos de facturación",
- "this warehouse has not dms": "El Almacén no acepta documentos",
- "This ticket already has a cmr saved": "Este ticket ya tiene un cmr guardado",
- "Name should be uppercase": "El nombre debe ir en mayúscula",
- "Bank entity must be specified": "La entidad bancaria es obligatoria",
- "An email is necessary": "Es necesario un email",
- "You cannot update these fields": "No puedes actualizar estos campos",
- "CountryFK cannot be empty": "El país no puede estar vacío",
- "Cmr file does not exist": "El archivo del cmr no existe",
- "You are not allowed to modify the alias": "No estás autorizado a modificar el alias",
- "The address of the customer must have information about Incoterms and Customs Agent": "El consignatario del cliente debe tener informado Incoterms y Agente de aduanas",
- "No invoice series found for these parameters": "No se encontró una serie para estos parámetros",
- "The line could not be marked": "La linea no puede ser marcada",
- "Through this procedure, it is not possible to modify the password of users with verified email": "Mediante este procedimiento, no es posible modificar la contraseña de usuarios con correo verificado",
- "They're not your subordinate": "No es tu subordinado/a.",
- "No results found": "No se han encontrado resultados",
- "InvoiceIn is already booked": "La factura recibida está contabilizada",
- "This workCenter is already assigned to this agency": "Este centro de trabajo ya está asignado a esta agencia",
- "Select ticket or client": "Elija un ticket o un client",
- "It was not able to create the invoice": "No se pudo crear la factura",
- "Incoterms and Customs agent are required for a non UEE member": "Se requieren Incoterms y agente de aduanas para un no miembro de la UEE",
- "You can not use the same password": "No puedes usar la misma contraseña",
- "This PDA is already assigned to another user": "Este PDA ya está asignado a otro usuario",
- "You can only have one PDA": "Solo puedes tener un PDA",
- "The invoices have been created but the PDFs could not be generated": "Se ha facturado pero no se ha podido generar el PDF",
- "It has been invoiced but the PDF of refund not be generated": "Se ha facturado pero no se ha podido generar el PDF del abono",
- "Payment method is required": "El método de pago es obligatorio",
- "Cannot send mail": "Não é possível enviar o email",
- "CONSTRAINT `supplierAccountTooShort` failed for `vn`.`supplier`": "La cuenta debe tener exactamente 10 dígitos",
- "The sale not exists in the item shelving": "La venta no existe en la estantería del artículo",
- "The entry not have stickers": "La entrada no tiene etiquetas",
- "Too many records": "Demasiados registros",
- "Original invoice not found": "Factura original no encontrada",
- "The entry has no lines or does not exist": "La entrada no tiene lineas o no existe",
- "Weight already set": "El peso ya está establecido",
- "This ticket is not allocated to your department": "Este ticket no está asignado a tu departamento",
- "There is already a tray with the same height": "Ya existe una bandeja con la misma altura",
- "The height must be greater than 50cm": "La altura debe ser superior a 50cm",
- "The maximum height of the wagon is 200cm": "La altura máxima es 200cm",
- "The entry does not have stickers": "La entrada no tiene etiquetas",
- "This buyer has already made a reservation for this date": "Este comprador ya ha hecho una reserva para esta fecha",
- "No valid travel thermograph found": "No se encontró un termógrafo válido",
- "The quantity claimed cannot be greater than the quantity of the line": "La cantidad reclamada no puede ser mayor que la cantidad de la línea",
- "type cannot be blank": "Se debe rellenar el tipo",
- "There are tickets for this area, delete them first": "Hay tickets para esta sección, borralos primero",
- "There is no company associated with that warehouse": "No hay ninguna empresa asociada a ese almacén",
- "You do not have permission to modify the booked field": "No tienes permisos para modificar el campo contabilizada",
- "ticketLostExpedition": "El ticket [{{ticketId}}]({{{ticketUrl}}}) tiene la siguiente expedición perdida:{{ expeditionId }}",
- "The web user's email already exists": "El correo del usuario web ya existe",
- "Sales already moved": "Ya han sido transferidas",
- "The raid information is not correct": "La información de la redada no es correcta",
- "An item type with the same code already exists": "Un tipo con el mismo código ya existe",
- "Holidays to past days not available": "Las vacaciones a días pasados no están disponibles",
- "All tickets have a route order": "Todos los tickets tienen orden de ruta",
- "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.",
- "Price cannot be blank": "El precio no puede estar en blanco"
+ "Phone format is invalid": "El formato del teléfono no es correcto",
+ "You are not allowed to change the credit": "No tienes privilegios para modificar el crédito",
+ "Unable to mark the equivalence surcharge": "No se puede marcar el recargo de equivalencia",
+ "The default consignee can not be unchecked": "No se puede desmarcar el consignatario predeterminado",
+ "Unable to default a disabled consignee": "No se puede poner predeterminado un consignatario desactivado",
+ "Can't be blank": "No puede estar en blanco",
+ "Invalid TIN": "NIF/CIF inválido",
+ "TIN must be unique": "El NIF/CIF debe ser único",
+ "A client with that Web User name already exists": "Ya existe un cliente con ese Usuario Web",
+ "Is invalid": "Es inválido",
+ "Quantity cannot be zero": "La cantidad no puede ser cero",
+ "Enter an integer different to zero": "Introduce un entero distinto de cero",
+ "Package cannot be blank": "El embalaje no puede estar en blanco",
+ "The company name must be unique": "La razón social debe ser única",
+ "Invalid email": "Correo electrónico inválido",
+ "The IBAN does not have the correct format": "El IBAN no tiene el formato correcto",
+ "That payment method requires an IBAN": "El método de pago seleccionado requiere un IBAN",
+ "That payment method requires a BIC": "El método de pago seleccionado requiere un BIC",
+ "State cannot be blank": "El estado no puede estar en blanco",
+ "Worker cannot be blank": "El trabajador no puede estar en blanco",
+ "Cannot change the payment method if no salesperson": "No se puede cambiar la forma de pago si no hay comercial asignado",
+ "can't be blank": "El campo no puede estar vacío",
+ "Observation type must be unique": "El tipo de observación no puede repetirse",
+ "The credit must be an integer greater than or equal to zero": "The credit must be an integer greater than or equal to zero",
+ "The grade must be similar to the last one": "El grade debe ser similar al último",
+ "Only manager can change the credit": "Solo el gerente puede cambiar el credito de este cliente",
+ "Name cannot be blank": "El nombre no puede estar en blanco",
+ "Phone cannot be blank": "El teléfono no puede estar en blanco",
+ "Period cannot be blank": "El periodo no puede estar en blanco",
+ "Choose a company": "Selecciona una empresa",
+ "Se debe rellenar el campo de texto": "Se debe rellenar el campo de texto",
+ "Description should have maximum of 45 characters": "La descripción debe tener maximo 45 caracteres",
+ "Cannot be blank": "El campo no puede estar en blanco",
+ "The grade must be an integer greater than or equal to zero": "El grade debe ser un entero mayor o igual a cero",
+ "Sample type cannot be blank": "El tipo de plantilla no puede quedar en blanco",
+ "Description cannot be blank": "Se debe rellenar el campo de texto",
+ "The price of the item changed": "El precio del artículo cambió",
+ "The value should not be greater than 100%": "El valor no debe de ser mayor de 100%",
+ "The value should be a number": "El valor debe ser un numero",
+ "This order is not editable": "Esta orden no se puede modificar",
+ "You can't create an order for a frozen client": "No puedes crear una orden para un cliente congelado",
+ "You can't create an order for a client that has a debt": "No puedes crear una orden para un cliente con deuda",
+ "is not a valid date": "No es una fecha valida",
+ "Barcode must be unique": "El código de barras debe ser único",
+ "The warehouse can't be repeated": "El almacén no puede repetirse",
+ "The tag or priority can't be repeated for an item": "El tag o prioridad no puede repetirse para un item",
+ "The observation type can't be repeated": "El tipo de observación no puede repetirse",
+ "A claim with that sale already exists": "Ya existe una reclamación para esta línea",
+ "You don't have enough privileges to change that field": "No tienes permisos para cambiar ese campo",
+ "Warehouse cannot be blank": "El almacén no puede quedar en blanco",
+ "Agency cannot be blank": "La agencia no puede quedar en blanco",
+ "Not enough privileges to edit a client with verified data": "No tienes permisos para hacer cambios en un cliente con datos comprobados",
+ "This address doesn't exist": "Este consignatario no existe",
+ "You must delete the claim id %d first": "Antes debes borrar la reclamación %d",
+ "You don't have enough privileges": "No tienes suficientes permisos",
+ "Cannot check Equalization Tax in this NIF/CIF": "No se puede marcar RE en este NIF/CIF",
+ "You can't make changes on the basic data of an confirmed order or with rows": "No puedes cambiar los datos básicos de una orden con artículos",
+ "INVALID_USER_NAME": "El nombre de usuario solo debe contener letras minúsculas o, a partir del segundo carácter, números o subguiones, no está permitido el uso de la letra ñ",
+ "You can't create a ticket for a frozen client": "No puedes crear un ticket para un cliente congelado",
+ "You can't create a ticket for an inactive client": "No puedes crear un ticket para un cliente inactivo",
+ "Tag value cannot be blank": "El valor del tag no puede quedar en blanco",
+ "ORDER_EMPTY": "Cesta vacía",
+ "You don't have enough privileges to do that": "No tienes permisos para cambiar esto",
+ "NO SE PUEDE DESACTIVAR EL CONSIGNAT": "NO SE PUEDE DESACTIVAR EL CONSIGNAT",
+ "Error. El NIF/CIF está repetido": "Error. El NIF/CIF está repetido",
+ "Street cannot be empty": "Dirección no puede estar en blanco",
+ "City cannot be empty": "Ciudad no puede estar en blanco",
+ "Code cannot be blank": "Código no puede estar en blanco",
+ "You cannot remove this department": "No puedes eliminar este departamento",
+ "The extension must be unique": "La extensión debe ser unica",
+ "The secret can't be blank": "La contraseña no puede estar en blanco",
+ "We weren't able to send this SMS": "No hemos podido enviar el SMS",
+ "This client can't be invoiced": "Este cliente no puede ser facturado",
+ "You must provide the correction information to generate a corrective invoice": "Debes informar la información de corrección para generar una factura rectificativa",
+ "This ticket can't be invoiced": "Este ticket no puede ser facturado",
+ "You cannot add or modify services to an invoiced ticket": "No puedes añadir o modificar servicios a un ticket facturado",
+ "This ticket can not be modified": "Este ticket no puede ser modificado",
+ "The introduced hour already exists": "Esta hora ya ha sido introducida",
+ "INFINITE_LOOP": "Existe una dependencia entre dos Jefes",
+ "The sales of the receiver ticket can't be modified": "Las lineas del ticket al que envias no pueden ser modificadas",
+ "NO_AGENCY_AVAILABLE": "No hay una zona de reparto disponible con estos parámetros",
+ "ERROR_PAST_SHIPMENT": "No puedes seleccionar una fecha de envío en pasado",
+ "The current ticket can't be modified": "El ticket actual no puede ser modificado",
+ "The current claim can't be modified": "La reclamación actual no puede ser modificada",
+ "The sales of this ticket can't be modified": "Las lineas de este ticket no pueden ser modificadas",
+ "The sales do not exists": "La(s) línea(s) seleccionada(s) no existe(n)",
+ "Please select at least one sale": "Por favor selecciona al menos una linea",
+ "All sales must belong to the same ticket": "Todas las lineas deben pertenecer al mismo ticket",
+ "NO_ZONE_FOR_THIS_PARAMETERS": "Para este día no hay ninguna zona configurada",
+ "This item doesn't exists": "El artículo no existe",
+ "NOT_ZONE_WITH_THIS_PARAMETERS": "Para este día no hay ninguna zona configurada",
+ "Extension format is invalid": "El formato de la extensión es inválido",
+ "Invalid parameters to create a new ticket": "Parámetros inválidos para crear un nuevo ticket",
+ "This item is not available": "Este artículo no está disponible",
+ "This postcode already exists": "Este código postal ya existe",
+ "Concept cannot be blank": "El concepto no puede quedar en blanco",
+ "File doesn't exists": "El archivo no existe",
+ "You don't have privileges to change the zone": "No tienes permisos para cambiar la zona o para esos parámetros hay más de una opción de envío, hable con las agencias",
+ "This ticket is already on weekly tickets": "Este ticket ya está en tickets programados",
+ "Ticket id cannot be blank": "El id de ticket no puede quedar en blanco",
+ "Weekday cannot be blank": "El día de la semana no puede quedar en blanco",
+ "You can't delete a confirmed order": "No puedes borrar un pedido confirmado",
+ "The social name has an invalid format": "El nombre fiscal tiene un formato incorrecto",
+ "Invalid quantity": "Cantidad invalida",
+ "This postal code is not valid": "Este código postal no es válido",
+ "is invalid": "es inválido",
+ "The postcode doesn't exist. Please enter a correct one": "El código postal no existe. Por favor, introduce uno correcto",
+ "The department name can't be repeated": "El nombre del departamento no puede repetirse",
+ "This phone already exists": "Este teléfono ya existe",
+ "You cannot move a parent to its own sons": "No puedes mover un elemento padre a uno de sus hijos",
+ "You can't create a claim for a removed ticket": "No puedes crear una reclamación para un ticket eliminado",
+ "You cannot delete a ticket that part of it is being prepared": "No puedes eliminar un ticket en el que una parte que está siendo preparada",
+ "You must delete all the buy requests first": "Debes eliminar todas las peticiones de compra primero",
+ "You should specify a date": "Debes especificar una fecha",
+ "You should specify at least a start or end date": "Debes especificar al menos una fecha de inicio o de fin",
+ "Start date should be lower than end date": "La fecha de inicio debe ser menor que la fecha de fin",
+ "You should mark at least one week day": "Debes marcar al menos un día de la semana",
+ "Swift / BIC can't be empty": "Swift / BIC no puede estar vacío",
+ "Customs agent is required for a non UEE member": "El agente de aduanas es requerido para los clientes extracomunitarios",
+ "Incoterms is required for a non UEE member": "El incoterms es requerido para los clientes extracomunitarios",
+ "Deleted sales from ticket": "He eliminado las siguientes lineas del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{deletions}}}",
+ "Added sale to ticket": "He añadido la siguiente linea al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{addition}}}",
+ "Changed sale discount": "He cambiado el descuento de las siguientes lineas al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
+ "Created claim": "He creado la reclamación [{{claimId}}]({{{claimUrl}}}) de las siguientes lineas del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
+ "Changed sale price": "He cambiado el precio de [{{itemId}} {{concept}}]({{{itemUrl}}}) ({{quantity}}) de {{oldPrice}}€ ➔ *{{newPrice}}€* del ticket [{{ticketId}}]({{{ticketUrl}}})",
+ "Changed sale quantity": "He cambiado {{changes}} del ticket [{{ticketId}}]({{{ticketUrl}}})",
+ "Changes in sales": "la cantidad de [{{itemId}} {{concept}}]({{{itemUrl}}}) de {{oldQuantity}} ➔ *{{newQuantity}}*",
+ "State": "Estado",
+ "regular": "normal",
+ "reserved": "reservado",
+ "Changed sale reserved state": "He cambiado el estado reservado de las siguientes lineas al ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
+ "Bought units from buy request": "Se ha comprado {{quantity}} unidades de [{{itemId}} {{concept}}]({{{urlItem}}}) para el ticket id [{{ticketId}}]({{{url}}})",
+ "Deny buy request": "Se ha rechazado la petición de compra para el ticket id [{{ticketId}}]({{{url}}}). Motivo: {{observation}}",
+ "MESSAGE_INSURANCE_CHANGE": "He cambiado el crédito asegurado del cliente [{{clientName}} ({{clientId}})]({{{url}}}) a *{{credit}} €*",
+ "Changed client paymethod": "He cambiado la forma de pago del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
+ "Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} ({{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [{{ticketId}}]({{{ticketUrl}}})",
+ "Change quantity": "{{concept}} cambia de {{oldQuantity}} a {{newQuantity}}",
+ "Claim will be picked": "Se recogerá el género de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}*, con el tipo de recogida *{{claimPickup}}*",
+ "Claim state has changed to": "Se ha cambiado el estado de la reclamación [({{claimId}})]({{{claimUrl}}}) del cliente *{{clientName}}* a *{{newState}}*",
+ "Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}",
+ "ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto",
+ "Distance must be lesser than 4000": "La distancia debe ser inferior a 4000",
+ "This ticket is deleted": "Este ticket está eliminado",
+ "Unable to clone this travel": "No ha sido posible clonar este travel",
+ "This thermograph id already exists": "La id del termógrafo ya existe",
+ "Choose a date range or days forward": "Selecciona un rango de fechas o días en adelante",
+ "ORDER_ALREADY_CONFIRMED": "ORDEN YA CONFIRMADA",
+ "Invalid password": "Invalid password",
+ "Password does not meet requirements": "La contraseña no cumple los requisitos",
+ "Role already assigned": "Rol ya asignado",
+ "Invalid role name": "Nombre de rol no válido",
+ "Role name must be written in camelCase": "El nombre del rol debe escribirse en camelCase",
+ "Email already exists": "El correo ya existe",
+ "User already exists": "El/La usuario/a ya existe",
+ "Absence change notification on the labour calendar": "Notificación de cambio de ausencia en el calendario laboral",
+ "Record of hours week": "Registro de horas semana {{week}} año {{year}} ",
+ "Created absence": "El empleado {{author}} ha añadido una ausencia de tipo '{{absenceType}}' a {{employee}} para el día {{dated}}.",
+ "Deleted absence": "El empleado {{author}} ha eliminado una ausencia de tipo '{{absenceType}}' a {{employee}} del día {{dated}}.",
+ "I have deleted the ticket id": "He eliminado el ticket id [{{id}}]({{{url}}})",
+ "I have restored the ticket id": "He restaurado el ticket id [{{id}}]({{{url}}})",
+ "You can only restore a ticket within the first hour after deletion": "Únicamente puedes restaurar el ticket dentro de la primera hora después de su eliminación",
+ "Changed this data from the ticket": "He cambiado estos datos del ticket [{{ticketId}}]({{{ticketUrl}}}): {{{changes}}}",
+ "agencyModeFk": "Agencia",
+ "clientFk": "Cliente",
+ "zoneFk": "Zona",
+ "warehouseFk": "Almacén",
+ "shipped": "F. envío",
+ "landed": "F. entrega",
+ "addressFk": "Consignatario",
+ "companyFk": "Empresa",
+ "agency": "Agencia",
+ "delivery": "Reparto",
+ "The social name cannot be empty": "La razón social no puede quedar en blanco",
+ "The nif cannot be empty": "El NIF no puede quedar en blanco",
+ "You need to fill sage information before you check verified data": "Debes rellenar la información de sage antes de marcar datos comprobados",
+ "ASSIGN_ZONE_FIRST": "Asigna una zona primero",
+ "Amount cannot be zero": "El importe no puede ser cero",
+ "Company has to be official": "Empresa inválida",
+ "You can not select this payment method without a registered bankery account": "No se puede utilizar este método de pago si no has registrado una cuenta bancaria",
+ "Action not allowed on the test environment": "Esta acción no está permitida en el entorno de pruebas",
+ "The selected ticket is not suitable for this route": "El ticket seleccionado no es apto para esta ruta",
+ "New ticket request has been created with price": "Se ha creado una nueva petición de compra '{{description}}' para el día *{{shipped}}*, con una cantidad de *{{quantity}}* y un precio de *{{price}} €*",
+ "New ticket request has been created": "Se ha creado una nueva petición de compra '{{description}}' para el día *{{shipped}}*, con una cantidad de *{{quantity}}*",
+ "Swift / BIC cannot be empty": "Swift / BIC no puede estar vacío",
+ "This BIC already exist.": "Este BIC ya existe.",
+ "That item doesn't exists": "Ese artículo no existe",
+ "There's a new urgent ticket:": "Hay un nuevo ticket urgente:",
+ "Invalid account": "Cuenta inválida",
+ "Compensation account is empty": "La cuenta para compensar está vacia",
+ "This genus already exist": "Este genus ya existe",
+ "This specie already exist": "Esta especie ya existe",
+ "Client assignment has changed": "He cambiado el comercial ~*\"<{{previousWorkerName}}>\"*~ por *\"<{{currentWorkerName}}>\"* del cliente [{{clientName}} ({{clientId}})]({{{url}}})",
+ "None": "Ninguno",
+ "The contract was not active during the selected date": "El contrato no estaba activo durante la fecha seleccionada",
+ "Cannot add more than one '1/2 day vacation'": "No puedes añadir más de un 'Vacaciones 1/2 dia'",
+ "This document already exists on this ticket": "Este documento ya existe en el ticket",
+ "Some of the selected tickets are not billable": "Algunos de los tickets seleccionados no son facturables",
+ "You can't invoice tickets from multiple clients": "No puedes facturar tickets de multiples clientes",
+ "nickname": "nickname",
+ "INACTIVE_PROVIDER": "Proveedor inactivo",
+ "This client is not invoiceable": "Este cliente no es facturable",
+ "serial non editable": "Esta serie no permite asignar la referencia",
+ "Max shipped required": "La fecha límite es requerida",
+ "Can't invoice to future": "No se puede facturar a futuro",
+ "Can't invoice to past": "No se puede facturar a pasado",
+ "This ticket is already invoiced": "Este ticket ya está facturado",
+ "A ticket with an amount of zero can't be invoiced": "No se puede facturar un ticket con importe cero",
+ "A ticket with a negative base can't be invoiced": "No se puede facturar un ticket con una base negativa",
+ "Global invoicing failed": "[Facturación global] No se han podido facturar algunos clientes",
+ "Wasn't able to invoice the following clients": "No se han podido facturar los siguientes clientes",
+ "Can't verify data unless the client has a business type": "No se puede verificar datos de un cliente que no tiene tipo de negocio",
+ "You don't have enough privileges to set this credit amount": "No tienes suficientes privilegios para establecer esta cantidad de crédito",
+ "You can't change the credit set to zero from a financialBoss": "No puedes cambiar el cŕedito establecido a cero por un jefe de finanzas",
+ "Amounts do not match": "Las cantidades no coinciden",
+ "The PDF document does not exist": "El documento PDF no existe. Prueba a regenerarlo desde la opción 'Regenerar PDF factura'",
+ "The type of business must be filled in basic data": "El tipo de negocio debe estar rellenado en datos básicos",
+ "You can't create a claim from a ticket delivered more than seven days ago": "No puedes crear una reclamación de un ticket entregado hace más de siete días",
+ "The worker has hours recorded that day": "El trabajador tiene horas fichadas ese día",
+ "The worker has a marked absence that day": "El trabajador tiene marcada una ausencia ese día",
+ "You can not modify is pay method checked": "No se puede modificar el campo método de pago validado",
+ "The account size must be exactly 10 characters": "El tamaño de la cuenta debe ser exactamente de 10 caracteres",
+ "Can't transfer claimed sales": "No puedes transferir lineas reclamadas",
+ "You don't have privileges to create refund": "No tienes permisos para crear un abono",
+ "The item is required": "El artículo es requerido",
+ "The agency is already assigned to another autonomous": "La agencia ya está asignada a otro autónomo",
+ "date in the future": "Fecha en el futuro",
+ "reference duplicated": "Referencia duplicada",
+ "This ticket is already a refund": "Este ticket ya es un abono",
+ "isWithoutNegatives": "Sin negativos",
+ "routeFk": "routeFk",
+ "Can't change the password of another worker": "No se puede cambiar la contraseña de otro trabajador",
+ "No hay un contrato en vigor": "No hay un contrato en vigor",
+ "No se permite fichar a futuro": "No se permite fichar a futuro",
+ "No está permitido trabajar": "No está permitido trabajar",
+ "Fichadas impares": "Fichadas impares",
+ "Descanso diario 12h.": "Descanso diario 12h.",
+ "Descanso semanal 36h. / 72h.": "Descanso semanal 36h. / 72h.",
+ "Dirección incorrecta": "Dirección incorrecta",
+ "Modifiable user details only by an administrator": "Detalles de usuario modificables solo por un administrador",
+ "Modifiable password only via recovery or by an administrator": "Contraseña modificable solo a través de la recuperación o por un administrador",
+ "Not enough privileges to edit a client": "No tienes suficientes privilegios para editar un cliente",
+ "This route does not exists": "Esta ruta no existe",
+ "Claim pickup order sent": "Reclamación Orden de recogida enviada [{{claimId}}]({{{claimUrl}}}) al cliente *{{clientName}}*",
+ "You don't have grant privilege": "No tienes privilegios para dar privilegios",
+ "You don't own the role and you can't assign it to another user": "No eres el propietario del rol y no puedes asignarlo a otro usuario",
+ "Ticket merged": "Ticket [{{originId}}]({{{originFullPath}}}) ({{{originDated}}}) fusionado con [{{destinationId}}]({{{destinationFullPath}}}) ({{{destinationDated}}})",
+ "Already has this status": "Ya tiene este estado",
+ "There aren't records for this week": "No existen registros para esta semana",
+ "Empty data source": "Origen de datos vacio",
+ "App locked": "Aplicación bloqueada por el usuario {{userId}}",
+ "Email verify": "Correo de verificación",
+ "Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment",
+ "Receipt's bank was not found": "No se encontró el banco del recibo",
+ "This receipt was not compensated": "Este recibo no ha sido compensado",
+ "Client's email was not found": "No se encontró el email del cliente",
+ "Negative basis": "Base negativa",
+ "This worker code already exists": "Este codigo de trabajador ya existe",
+ "This personal mail already exists": "Este correo personal ya existe",
+ "This worker already exists": "Este trabajador ya existe",
+ "App name does not exist": "El nombre de aplicación no es válido",
+ "Try again": "Vuelve a intentarlo",
+ "Aplicación bloqueada por el usuario 9": "Aplicación bloqueada por el usuario 9",
+ "Failed to upload delivery note": "Error al subir albarán {{id}}",
+ "The DOCUWARE PDF document does not exists": "El documento PDF Docuware no existe",
+ "It is not possible to modify tracked sales": "No es posible modificar líneas de pedido que se hayan empezado a preparar",
+ "It is not possible to modify sales that their articles are from Floramondo": "No es posible modificar líneas de pedido cuyos artículos sean de Floramondo",
+ "It is not possible to modify cloned sales": "No es posible modificar líneas de pedido clonadas",
+ "A supplier with the same name already exists. Change the country.": "Un proveedor con el mismo nombre ya existe. Cambie el país.",
+ "There is no assigned email for this client": "No hay correo asignado para este cliente",
+ "Exists an invoice with a future date": "Existe una factura con fecha posterior",
+ "Invoice date can't be less than max date": "La fecha de factura no puede ser inferior a la fecha límite",
+ "Warehouse inventory not set": "El almacén inventario no está establecido",
+ "This locker has already been assigned": "Esta taquilla ya ha sido asignada",
+ "Tickets with associated refunds": "No se pueden borrar tickets con abonos asociados. Este ticket está asociado al abono Nº %s",
+ "Not exist this branch": "La rama no existe",
+ "This ticket cannot be signed because it has not been boxed": "Este ticket no puede firmarse porque no ha sido encajado",
+ "Collection does not exist": "La colección no existe",
+ "Cannot obtain exclusive lock": "No se puede obtener un bloqueo exclusivo",
+ "Insert a date range": "Inserte un rango de fechas",
+ "Added observation": "{{user}} añadió esta observacion: {{text}} {{defaulterId}} ({{{defaulterUrl}}})",
+ "Comment added to client": "Observación añadida al cliente {{clientFk}}",
+ "Invalid auth code": "Código de verificación incorrecto",
+ "Invalid or expired verification code": "Código de verificación incorrecto o expirado",
+ "Cannot create a new claimBeginning from a different ticket": "No se puede crear una línea de reclamación de un ticket diferente al origen",
+ "company": "Compañía",
+ "country": "País",
+ "clientId": "Id cliente",
+ "clientSocialName": "Cliente",
+ "amount": "Importe",
+ "taxableBase": "Base",
+ "ticketFk": "Id ticket",
+ "isActive": "Activo",
+ "hasToInvoice": "Facturar",
+ "isTaxDataChecked": "Datos comprobados",
+ "comercialId": "Id comercial",
+ "comercialName": "Comercial",
+ "Pass expired": "La contraseña ha caducado, cambiela desde Salix",
+ "Invalid NIF for VIES": "Invalid NIF for VIES",
+ "Ticket does not exist": "Este ticket no existe",
+ "Ticket is already signed": "Este ticket ya ha sido firmado",
+ "Authentication failed": "Autenticación fallida",
+ "You can't use the same password": "No puedes usar la misma contraseña",
+ "You can only add negative amounts in refund tickets": "Solo se puede añadir cantidades negativas en tickets abono",
+ "Fecha fuera de rango": "Fecha fuera de rango",
+ "Error while generating PDF": "Error al generar PDF",
+ "Error when sending mail to client": "Error al enviar el correo al cliente",
+ "Mail not sent": "Se ha producido un fallo al enviar la factura al cliente [{{clientId}}]({{{clientUrl}}}), por favor revisa la dirección de correo electrónico",
+ "The renew period has not been exceeded": "El periodo de renovación no ha sido superado",
+ "Valid priorities": "Prioridades válidas: %d",
+ "hasAnyNegativeBase": "Base negativa para los tickets: {{ticketsIds}}",
+ "hasAnyPositiveBase": "Base positivas para los tickets: {{ticketsIds}}",
+ "You cannot assign an alias that you are not assigned to": "No puede asignar un alias que no tenga asignado",
+ "This ticket cannot be left empty.": "Este ticket no se puede dejar vacío. %s",
+ "The company has not informed the supplier account for bank transfers": "La empresa no tiene informado la cuenta de proveedor para transferencias bancarias",
+ "You cannot assign/remove an alias that you are not assigned to": "No puede asignar/eliminar un alias que no tenga asignado",
+ "This invoice has a linked vehicle.": "Esta factura tiene un vehiculo vinculado",
+ "You don't have enough privileges.": "No tienes suficientes permisos.",
+ "This ticket is locked": "Este ticket está bloqueado.",
+ "This ticket is not editable.": "Este ticket no es editable.",
+ "The ticket doesn't exist.": "No existe el ticket.",
+ "Social name should be uppercase": "La razón social debe ir en mayúscula",
+ "Street should be uppercase": "La dirección fiscal debe ir en mayúscula",
+ "Ticket without Route": "Ticket sin ruta",
+ "Select a different client": "Seleccione un cliente distinto",
+ "Fill all the fields": "Rellene todos los campos",
+ "The response is not a PDF": "La respuesta no es un PDF",
+ "Booking completed": "Reserva completada",
+ "The ticket is in preparation": "El ticket [{{ticketId}}]({{{ticketUrl}}}) del comercial {{salesPersonId}} está en preparación",
+ "The notification subscription of this worker cant be modified": "La subscripción a la notificación de este trabajador no puede ser modificada",
+ "User disabled": "Usuario desactivado",
+ "The amount cannot be less than the minimum": "La cantidad no puede ser menor que la cantidad mínima",
+ "quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima",
+ "Cannot past travels with entries": "No se pueden pasar envíos con entradas",
+ "It was not able to remove the next expeditions:": "No se pudo eliminar las siguientes expediciones: {{expeditions}}",
+ "This claim has been updated": "La reclamación con Id: {{claimId}}, ha sido actualizada",
+ "This user does not have an assigned tablet": "Este usuario no tiene tablet asignada",
+ "Field are invalid": "El campo '{{tag}}' no es válido",
+ "Incorrect pin": "Pin incorrecto.",
+ "You already have the mailAlias": "Ya tienes este alias de correo",
+ "The alias cant be modified": "Este alias de correo no puede ser modificado",
+ "No tickets to invoice": "No hay tickets para facturar que cumplan los requisitos de facturación",
+ "this warehouse has not dms": "El Almacén no acepta documentos",
+ "This ticket already has a cmr saved": "Este ticket ya tiene un cmr guardado",
+ "Name should be uppercase": "El nombre debe ir en mayúscula",
+ "Bank entity must be specified": "La entidad bancaria es obligatoria",
+ "An email is necessary": "Es necesario un email",
+ "You cannot update these fields": "No puedes actualizar estos campos",
+ "CountryFK cannot be empty": "El país no puede estar vacío",
+ "Cmr file does not exist": "El archivo del cmr no existe",
+ "You are not allowed to modify the alias": "No estás autorizado a modificar el alias",
+ "The address of the customer must have information about Incoterms and Customs Agent": "El consignatario del cliente debe tener informado Incoterms y Agente de aduanas",
+ "No invoice series found for these parameters": "No se encontró una serie para estos parámetros",
+ "The line could not be marked": "La linea no puede ser marcada",
+ "Through this procedure, it is not possible to modify the password of users with verified email": "Mediante este procedimiento, no es posible modificar la contraseña de usuarios con correo verificado",
+ "They're not your subordinate": "No es tu subordinado/a.",
+ "No results found": "No se han encontrado resultados",
+ "InvoiceIn is already booked": "La factura recibida está contabilizada",
+ "This workCenter is already assigned to this agency": "Este centro de trabajo ya está asignado a esta agencia",
+ "Select ticket or client": "Elija un ticket o un client",
+ "It was not able to create the invoice": "No se pudo crear la factura",
+ "Incoterms and Customs agent are required for a non UEE member": "Se requieren Incoterms y agente de aduanas para un no miembro de la UEE",
+ "You can not use the same password": "No puedes usar la misma contraseña",
+ "This PDA is already assigned to another user": "Este PDA ya está asignado a otro usuario",
+ "You can only have one PDA": "Solo puedes tener un PDA",
+ "The invoices have been created but the PDFs could not be generated": "Se ha facturado pero no se ha podido generar el PDF",
+ "It has been invoiced but the PDF of refund not be generated": "Se ha facturado pero no se ha podido generar el PDF del abono",
+ "Payment method is required": "El método de pago es obligatorio",
+ "Cannot send mail": "Não é possível enviar o email",
+ "CONSTRAINT `supplierAccountTooShort` failed for `vn`.`supplier`": "La cuenta debe tener exactamente 10 dígitos",
+ "The sale not exists in the item shelving": "La venta no existe en la estantería del artículo",
+ "The entry not have stickers": "La entrada no tiene etiquetas",
+ "Too many records": "Demasiados registros",
+ "Original invoice not found": "Factura original no encontrada",
+ "The entry has no lines or does not exist": "La entrada no tiene lineas o no existe",
+ "Weight already set": "El peso ya está establecido",
+ "This ticket is not allocated to your department": "Este ticket no está asignado a tu departamento",
+ "There is already a tray with the same height": "Ya existe una bandeja con la misma altura",
+ "The height must be greater than 50cm": "La altura debe ser superior a 50cm",
+ "The maximum height of the wagon is 200cm": "La altura máxima es 200cm",
+ "The entry does not have stickers": "La entrada no tiene etiquetas",
+ "This buyer has already made a reservation for this date": "Este comprador ya ha hecho una reserva para esta fecha",
+ "No valid travel thermograph found": "No se encontró un termógrafo válido",
+ "The quantity claimed cannot be greater than the quantity of the line": "La cantidad reclamada no puede ser mayor que la cantidad de la línea",
+ "type cannot be blank": "Se debe rellenar el tipo",
+ "There are tickets for this area, delete them first": "Hay tickets para esta sección, borralos primero",
+ "There is no company associated with that warehouse": "No hay ninguna empresa asociada a ese almacén",
+ "You do not have permission to modify the booked field": "No tienes permisos para modificar el campo contabilizada",
+ "ticketLostExpedition": "El ticket [{{ticketId}}]({{{ticketUrl}}}) tiene la siguiente expedición perdida:{{ expeditionId }}",
+ "The web user's email already exists": "El correo del usuario web ya existe",
+ "Sales already moved": "Ya han sido transferidas",
+ "The raid information is not correct": "La información de la redada no es correcta",
+ "An item type with the same code already exists": "Un tipo con el mismo código ya existe",
+ "Holidays to past days not available": "Las vacaciones a días pasados no están disponibles",
+ "All tickets have a route order": "Todos los tickets tienen orden de ruta",
+ "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 sido entregado en su orden.",
+ "Price cannot be blank": "El precio no puede estar en blanco"
+
}
diff --git a/loopback/locale/fr.json b/loopback/locale/fr.json
index d7d5b7710e..378b0d2671 100644
--- a/loopback/locale/fr.json
+++ b/loopback/locale/fr.json
@@ -368,5 +368,5 @@
"ticketLostExpedition": "Le ticket [{{ticketId}}]({{{ticketUrl}}}) a l'expédition perdue suivante : {{expeditionId}}",
"The web user's email already exists": "L'email de l'internaute existe déjà",
"Incorrect delivery order alert on route": "Alerte de bon de livraison incorrect sur l'itinéraire: {{ route }} zone : {{ zone }}",
- "Ticket has been delivered out of order": "Le ticket {{ticket}} {{{fullUrl}}} a été livré hors ordre."
+ "Ticket has been delivered out of order": "Le ticket {{ticket}} de la route {{{fullUrl}}} a été livré hors service."
}
\ No newline at end of file
diff --git a/loopback/locale/pt.json b/loopback/locale/pt.json
index d1ac2ef236..35fe3d4f17 100644
--- a/loopback/locale/pt.json
+++ b/loopback/locale/pt.json
@@ -367,5 +367,5 @@
"ticketLostExpedition": "O ticket [{{ticketId}}]({{{ticketUrl}}}) tem a seguinte expedição perdida: {{expeditionId}}",
"The web user's email already exists": "O e-mail do utilizador da web já existe.",
"Incorrect delivery order alert on route": "Alerta de ordem de entrega incorreta na rota: {{ route }} zona: {{ zone }}",
- "Ticket has been delivered out of order": "O ticket {{ticket}} {{{fullUrl}}} foi entregue fora de ordem."
+ "Ticket has been delivered out of order": "O ticket {{ticket}} da rota {{{fullUrl}}} foi entregue fora de ordem."
}
\ No newline at end of file
diff --git a/modules/claim/back/methods/claim-beginning/specs/claim-beginning.spec.js b/modules/claim/back/methods/claim-beginning/specs/claim-beginning.spec.js
index b7974ad237..8b56f3a1c3 100644
--- a/modules/claim/back/methods/claim-beginning/specs/claim-beginning.spec.js
+++ b/modules/claim/back/methods/claim-beginning/specs/claim-beginning.spec.js
@@ -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'},
__: () => {}
};
diff --git a/modules/claim/back/methods/claim/specs/createFromSales.spec.js b/modules/claim/back/methods/claim/specs/createFromSales.spec.js
index 25414d1db7..75caf278ef 100644
--- a/modules/claim/back/methods/claim/specs/createFromSales.spec.js
+++ b/modules/claim/back/methods/claim/specs/createFromSales.spec.js
@@ -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},
- headers: {origin: 'localhost:5000'},
- __: () => {}
- };
-
- const ctx = {
- req: activeCtx
- };
+ const newSale = [{id: 31, instance: 0, quantity: 10}];
+ let activeCtx;
+ let ctx;
beforeEach(() => {
+ activeCtx = {
+ accessToken: {userId: 72},
+ headers: {origin: 'localhost:5000'},
+ __: () => {}
+ };
+ ctx = {req: activeCtx};
+
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({
active: activeCtx
});
diff --git a/modules/claim/back/models/claim-beginning.js b/modules/claim/back/models/claim-beginning.js
index 3dc9261c3d..41c064c751 100644
--- a/modules/claim/back/models/claim-beginning.js
+++ b/modules/claim/back/models/claim-beginning.js
@@ -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},
diff --git a/modules/client/back/methods/client/filter.js b/modules/client/back/methods/client/filter.js
index 7df973f193..c217b2a86c 100644
--- a/modules/client/back/methods/client/filter.js
+++ b/modules/client/back/methods/client/filter.js
@@ -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
`
);
diff --git a/modules/client/back/model-config.json b/modules/client/back/model-config.json
index e6690ee5f0..67a61b8b56 100644
--- a/modules/client/back/model-config.json
+++ b/modules/client/back/model-config.json
@@ -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"
}
}
diff --git a/modules/client/back/models/business-reason-end.json b/modules/client/back/models/business-reason-end.json
new file mode 100644
index 0000000000..54a632bea8
--- /dev/null
+++ b/modules/client/back/models/business-reason-end.json
@@ -0,0 +1,17 @@
+{
+ "name": "BusinessReasonEnd",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "businessReasonEnd"
+ }
+ },
+ "properties": {
+ "id": {
+ "type": "number"
+ },
+ "reason": {
+ "type": "string"
+ }
+ }
+}
diff --git a/modules/client/back/models/business.json b/modules/client/back/models/business.json
index 58e989ae08..dc6cd0bcd9 100644
--- a/modules/client/back/models/business.json
+++ b/modules/client/back/models/business.json
@@ -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"
}
+
}
}
diff --git a/modules/client/back/models/calendar-type.json b/modules/client/back/models/calendar-type.json
new file mode 100644
index 0000000000..742aaed94c
--- /dev/null
+++ b/modules/client/back/models/calendar-type.json
@@ -0,0 +1,21 @@
+{
+ "name": "CalendarType",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "calendarType"
+ }
+ },
+ "properties": {
+ "id": {
+ "type": "number"
+ },
+ "description": {
+ "type": "string"
+ },
+ "hoursWeek": {
+ "type": "number"
+ },
+ "isPartial": "number"
+ }
+}
diff --git a/modules/client/back/models/occupation-code.json b/modules/client/back/models/occupation-code.json
new file mode 100644
index 0000000000..e40eaf2fe1
--- /dev/null
+++ b/modules/client/back/models/occupation-code.json
@@ -0,0 +1,18 @@
+{
+ "name": "OccupationCode",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "occupationCode"
+ }
+ },
+ "properties": {
+ "code": {
+ "type": "string",
+ "id": true
+ },
+ "name": {
+ "type": "string"
+ }
+ }
+}
diff --git a/modules/client/back/models/payroll-categories.json b/modules/client/back/models/payroll-categories.json
new file mode 100644
index 0000000000..ca3431ba93
--- /dev/null
+++ b/modules/client/back/models/payroll-categories.json
@@ -0,0 +1,20 @@
+{
+ "name": "PayrollCategory",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "payrollCategories"
+ }
+ },
+ "properties": {
+ "id": {
+ "type": "number"
+ },
+ "description": {
+ "type": "string"
+ },
+ "rate": {
+ "type": "number"
+ }
+ }
+}
diff --git a/modules/client/back/models/professional-category.json b/modules/client/back/models/professional-category.json
new file mode 100644
index 0000000000..5f812a704f
--- /dev/null
+++ b/modules/client/back/models/professional-category.json
@@ -0,0 +1,20 @@
+{
+ "name": "WorkerBusinessProfessionalCategory",
+ "base": "VnModel",
+ "options": {
+ "mysql": {
+ "table": "professionalCategory"
+ }
+ },
+ "properties": {
+ "id": {
+ "type": "number"
+ },
+ "description": {
+ "type": "string"
+ },
+ "code": {
+ "type": "string"
+ }
+ }
+}
diff --git a/modules/client/back/models/worker-business-agreement.json b/modules/client/back/models/worker-business-agreement.json
new file mode 100644
index 0000000000..bd62b2aa39
--- /dev/null
+++ b/modules/client/back/models/worker-business-agreement.json
@@ -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"
+ }
+ }
+}
diff --git a/modules/client/back/models/worker-business-type.json b/modules/client/back/models/worker-business-type.json
new file mode 100644
index 0000000000..648ce3fd2a
--- /dev/null
+++ b/modules/client/back/models/worker-business-type.json
@@ -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"
+ }
+ }
+}
diff --git a/modules/entry/back/methods/entry/transfer.js b/modules/entry/back/methods/entry/transfer.js
index db68736633..fc1c4808af 100644
--- a/modules/entry/back/methods/entry/transfer.js
+++ b/modules/entry/back/methods/entry/transfer.js
@@ -1,6 +1,7 @@
module.exports = Self => {
Self.remoteMethodCtx('transfer', {
description: 'Transfer merchandise from one entry to the next day',
+ accessType: 'WRITE',
accepts: [
{
arg: 'id',
diff --git a/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js
index a06128848a..c4e336818a 100644
--- a/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js
+++ b/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js
@@ -109,7 +109,8 @@ module.exports = Self => {
where: {
clientFk: clientFk,
shipped: {lte: maxShipped}
- }
+ },
+ order: 'shipped DESC'
}, myOptions);
companyFk = company.companyFk;
}
diff --git a/modules/item/back/methods/item-shelving/getItemsByReviewOrder.js b/modules/item/back/methods/item-shelving/getItemsByReviewOrder.js
index 7a960a8c8f..7154565119 100644
--- a/modules/item/back/methods/item-shelving/getItemsByReviewOrder.js
+++ b/modules/item/back/methods/item-shelving/getItemsByReviewOrder.js
@@ -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,15 +63,16 @@ 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
)
SELECT ish.*,
- CASE
- WHEN ish.pickingOrder < d.pickingOrder AND aish.created < ish.created
+ CASE
+ WHEN ish.pickingOrder < d.pickingOrder AND aish.created < ish.created
AND ABS(TIMESTAMPDIFF(HOUR, aish.created, ish.created)) > ? THEN "old"
- WHEN ish.pickingOrder > d.pickingOrder AND aish.created > ish.created
+ WHEN ish.pickingOrder > d.pickingOrder AND aish.created > ish.created
AND ABS(TIMESTAMPDIFF(HOUR, aish.created, ish.created)) > ? THEN "new"
END AS itemCreated
FROM itemShelvings ish
@@ -77,8 +80,8 @@ module.exports = Self => {
JOIN currentItemShelving aish ON ish.itemFk = aish.itemFk
WHERE ABS(TIMESTAMPDIFF(HOUR, aish.created, ish.created)) > ?
AND (
- (ish.pickingOrder < d.pickingOrder AND aish.created < ish.created)
- OR
+ (ish.pickingOrder < d.pickingOrder AND aish.created < ish.created)
+ OR
(ish.pickingOrder > d.pickingOrder AND aish.created > ish.created)
);
`,
diff --git a/modules/mdb/back/methods/mdbVersion/upload.js b/modules/mdb/back/methods/mdbVersion/upload.js
index 64de726791..ee67e35d03 100644
--- a/modules/mdb/back/methods/mdbVersion/upload.js
+++ b/modules/mdb/back/methods/mdbVersion/upload.js
@@ -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))
diff --git a/modules/monitor/back/methods/sales-monitor/salesFilter.js b/modules/monitor/back/methods/sales-monitor/salesFilter.js
index 4947edeafb..ce50fec6aa 100644
--- a/modules/monitor/back/methods/sales-monitor/salesFilter.js
+++ b/modules/monitor/back/methods/sales-monitor/salesFilter.js
@@ -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
`);
diff --git a/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js b/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js
index 738af52199..1b4616de73 100644
--- a/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js
+++ b/modules/monitor/back/methods/sales-monitor/specs/salesFilter.spec.js
@@ -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) {
diff --git a/modules/route/back/methods/agency-term/specs/filter.spec.js b/modules/route/back/methods/agency-term/specs/filter.spec.js
index aa27438688..41e696157d 100644
--- a/modules/route/back/methods/agency-term/specs/filter.spec.js
+++ b/modules/route/back/methods/agency-term/specs/filter.spec.js
@@ -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);
});
});
diff --git a/modules/route/back/methods/route/specs/filter.spec.js b/modules/route/back/methods/route/specs/filter.spec.js
index 11bf0b7b0a..ddc2fe893d 100644
--- a/modules/route/back/methods/route/specs/filter.spec.js
+++ b/modules/route/back/methods/route/specs/filter.spec.js
@@ -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;
diff --git a/modules/route/back/methods/route/specs/optimizePriority.spec.js b/modules/route/back/methods/route/specs/optimizePriority.spec.js
index c1c2dc45e2..94072fd884 100644
--- a/modules/route/back/methods/route/specs/optimizePriority.spec.js
+++ b/modules/route/back/methods/route/specs/optimizePriority.spec.js
@@ -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);
diff --git a/modules/route/back/models/route.json b/modules/route/back/models/route.json
index 8f4eab7611..9483525718 100644
--- a/modules/route/back/models/route.json
+++ b/modules/route/back/models/route.json
@@ -75,11 +75,6 @@
"type": "hasMany",
"model": "Ticket",
"foreignKey": "routeFk"
- },
- "zone": {
- "type": "belongsTo",
- "model": "Zone",
- "foreignKey": "zoneFk"
- }
+ }
}
}
diff --git a/modules/ticket/back/locale/sale/es.yml b/modules/ticket/back/locale/sale/es.yml
index e6a984a5d6..eefd05d83d 100644
--- a/modules/ticket/back/locale/sale/es.yml
+++ b/modules/ticket/back/locale/sale/es.yml
@@ -15,4 +15,4 @@ columns:
priceFixed: precio fijado
isPriceFixed: tiene precio fijado
isAdded: añadida
- total: total
+ total: importe
diff --git a/modules/ticket/back/methods/sale/getClaimableFromTicket.js b/modules/ticket/back/methods/sale/getClaimableFromTicket.js
index c51781f595..cb10bdb0e0 100644
--- a/modules/ticket/back/methods/sale/getClaimableFromTicket.js
+++ b/modules/ticket/back/methods/sale/getClaimableFromTicket.js
@@ -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;
};
diff --git a/modules/ticket/back/methods/state/isEditable.js b/modules/ticket/back/methods/state/isEditable.js
index ec246c61f5..6961838278 100644
--- a/modules/ticket/back/methods/state/isEditable.js
+++ b/modules/ticket/back/methods/state/isEditable.js
@@ -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;
};
};
diff --git a/modules/ticket/back/methods/state/specs/editableState.spec.js b/modules/ticket/back/methods/state/specs/editableState.spec.js
index 2e1ce0c199..0c4024bbc0 100644
--- a/modules/ticket/back/methods/state/specs/editableState.spec.js
+++ b/modules/ticket/back/methods/state/specs/editableState.spec.js
@@ -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) {
diff --git a/modules/ticket/back/methods/ticket/filter.js b/modules/ticket/back/methods/ticket/filter.js
index f125ac586f..87556810b4 100644
--- a/modules/ticket/back/methods/ticket/filter.js
+++ b/modules/ticket/back/methods/ticket/filter.js
@@ -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);
diff --git a/modules/ticket/back/methods/ticket/getSales.js b/modules/ticket/back/methods/ticket/getSales.js
index 5b2288d317..3b5ee21a67 100644
--- a/modules/ticket/back/methods/ticket/getSales.js
+++ b/modules/ticket/back/methods/ticket/getSales.js
@@ -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;
diff --git a/modules/ticket/back/methods/ticket/getTicketProblems.js b/modules/ticket/back/methods/ticket/getTicketProblems.js
new file mode 100644
index 0000000000..351e07b679
--- /dev/null
+++ b/modules/ticket/back/methods/ticket/getTicketProblems.js
@@ -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];
+ };
+};
diff --git a/modules/ticket/back/methods/ticket/getTicketsFuture.js b/modules/ticket/back/methods/ticket/getTicketsFuture.js
index 2479245912..88f40bc3ef 100644
--- a/modules/ticket/back/methods/ticket/getTicketsFuture.js
+++ b/modules/ticket/back/methods/ticket/getTicketsFuture.js
@@ -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);
diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js
index f99311c392..d619e20379 100644
--- a/modules/ticket/back/methods/ticket/saveSign.js
+++ b/modules/ticket/back/methods/ticket/saveSign.js
@@ -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;
@@ -146,11 +148,11 @@ module.exports = Self => {
await ticket.updateAttribute('isSigned', true, myOptions);
const [{stateCode}] = await Self.rawSql(`
- SELECT
+ SELECT
IF((SUM(CASE WHEN est.code = 'DELIVERED' THEN 1 ELSE 0 END) = COUNT(*)),
'DELIVERED','PARTIAL_DELIVERED') stateCode
FROM vn.expedition e
- JOIN vn.expeditionStateType est ON est.id = e.stateTypeFk
+ JOIN vn.expeditionStateType est ON est.id = e.stateTypeFk
WHERE e.ticketFk = ?;
`, [ticketId], myOptions);
@@ -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
- WHERE t.routeFk = ?
- AND s.\`order\` < ?
- AND priority <(SELECT t.priority
- FROM ticket t
- WHERE t.id = ?)`
- , [ticket.routeFk, orderState.id, ticket.id], myOptions);
+ 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 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(route, ticket, zoneName) {
+ const $t = ctx.req.__;
+ const fullUrl = `${route}`;
+ await smtp.send({
+ to: 'repartos@verdnatura.es',
+ subject: $t('Incorrect delivery order alert on route', {
+ route,
+ zone: zoneName
+ }),
+ html: $t('Ticket has been delivered out of order', {
+ ticket,
+ fullUrl
+ })
+ });
+ }
};
-
- async function sendMail(ctx, 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', {
- route,
- zone: zoneName
- });
- const emailBody = $t('Ticket has been delivered out of order', {
- ticket,
- fullUrl
- });
-
- await Self.app.models.Mail.create({
- receiver: sendTo,
- subject: emailSubject,
- body: emailBody
- });
- }
};
diff --git a/modules/ticket/back/methods/ticket/specs/filter.spec.js b/modules/ticket/back/methods/ticket/specs/filter.spec.js
index d0edb24e39..cbd799431e 100644
--- a/modules/ticket/back/methods/ticket/specs/filter.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/filter.spec.js
@@ -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();
diff --git a/modules/ticket/back/methods/ticket/specs/getSales.spec.js b/modules/ticket/back/methods/ticket/specs/getSales.spec.js
index 7c0a67d451..f0a99b90b6 100644
--- a/modules/ticket/back/methods/ticket/specs/getSales.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/getSales.spec.js
@@ -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) {
diff --git a/modules/ticket/back/methods/ticket/specs/getTicketProblems.spec.js b/modules/ticket/back/methods/ticket/specs/getTicketProblems.spec.js
new file mode 100644
index 0000000000..f46c27e4dc
--- /dev/null
+++ b/modules/ticket/back/methods/ticket/specs/getTicketProblems.spec.js
@@ -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;
+ }
+ });
+});
diff --git a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js
index 3b426c2cf9..092ff95fdb 100644
--- a/modules/ticket/back/methods/ticket/specs/saveSign.spec.js
+++ b/modules/ticket/back/methods/ticket/specs/saveSign.spec.js
@@ -6,7 +6,7 @@ describe('Ticket saveSign()', () => {
getLocale: () => {
return 'en';
},
- __: () => {},
+ __: t => t,
accessToken: {userId: 9}
}
};
diff --git a/modules/ticket/back/models/ticket-methods.js b/modules/ticket/back/models/ticket-methods.js
index 620b3e1841..995fa2da3c 100644
--- a/modules/ticket/back/models/ticket-methods.js
+++ b/modules/ticket/back/models/ticket-methods.js
@@ -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);
};
diff --git a/modules/worker/back/methods/worker-dms/filter.js b/modules/worker/back/methods/worker-dms/filter.js
index 240a905d28..a6e5d67e76 100644
--- a/modules/worker/back/methods/worker-dms/filter.js
+++ b/modules/worker/back/methods/worker-dms/filter.js
@@ -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);
diff --git a/modules/worker/back/models/worker.js b/modules/worker/back/models/worker.js
index 97e6a283c3..4895a6107f 100644
--- a/modules/worker/back/models/worker.js
+++ b/modules/worker/back/models/worker.js
@@ -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();
- }
};
diff --git a/modules/worker/back/models/worker.json b/modules/worker/back/models/worker.json
index 705851963a..2715c233b1 100644
--- a/modules/worker/back/models/worker.json
+++ b/modules/worker/back/models/worker.json
@@ -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"
+ ]
+ }
+ }
+ ]
+ }
}
]
}
diff --git a/package.json b/package.json
index 72f8e2d1ba..7f2025552a 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/print/templates/email/misallocation-warehouse/assets/css/import.js b/print/templates/email/misallocation-warehouse/assets/css/import.js
new file mode 100644
index 0000000000..4b4bb70869
--- /dev/null
+++ b/print/templates/email/misallocation-warehouse/assets/css/import.js
@@ -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();
diff --git a/print/templates/email/misallocation-warehouse/locale/en.yml b/print/templates/email/misallocation-warehouse/locale/en.yml
new file mode 100644
index 0000000000..b16d9bd50a
--- /dev/null
+++ b/print/templates/email/misallocation-warehouse/locale/en.yml
@@ -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.
diff --git a/print/templates/email/misallocation-warehouse/locale/es.yml b/print/templates/email/misallocation-warehouse/locale/es.yml
new file mode 100644
index 0000000000..fbb1c74f16
--- /dev/null
+++ b/print/templates/email/misallocation-warehouse/locale/es.yml
@@ -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.
diff --git a/print/templates/email/misallocation-warehouse/locale/fr.yml b/print/templates/email/misallocation-warehouse/locale/fr.yml
new file mode 100644
index 0000000000..0c8f155d6b
--- /dev/null
+++ b/print/templates/email/misallocation-warehouse/locale/fr.yml
@@ -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 l’entrepôt qui ne correspond pas à l’emplacement de l’entrée.
diff --git a/print/templates/email/misallocation-warehouse/locale/pt.yml b/print/templates/email/misallocation-warehouse/locale/pt.yml
new file mode 100644
index 0000000000..129960ba69
--- /dev/null
+++ b/print/templates/email/misallocation-warehouse/locale/pt.yml
@@ -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.
diff --git a/print/templates/email/misallocation-warehouse/misallocation-warehouse.html b/print/templates/email/misallocation-warehouse/misallocation-warehouse.html
new file mode 100644
index 0000000000..ad68ae0b63
--- /dev/null
+++ b/print/templates/email/misallocation-warehouse/misallocation-warehouse.html
@@ -0,0 +1,9 @@
+ {{$t('body')}} {{action}}{{ $t('title') }}
+