diff --git a/CHANGELOG.md b/CHANGELOG.md index 67ffe9f12..5aabb9305 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,49 @@ +# Version 25.04 - 2025-01-28 + +### Added 🆕 + +- feat: refs #7202 added new field by:Jon +- feat: refs #7343 delete sending to user by:ivanm +- feat: refs #7569 refs#7569 sendEmailNotification by:sergiodt +- feat: refs #7569 refs#7569 sendMail by:sergiodt +- feat: refs #7584 changes request by:robert +- feat: refs #7584 workerTimeControl_afterDelete by:robert +- feat: refs #7832 implement refund ticket restrictions and add unit tests for ticket service updates by:jgallego +- feat: refs #7882 Added coords to create a address by:guillermo +- feat: refs #8073 change names and primary key by:ivanm +- feat: refs #8073 new comment message by:ivanm +- feat: refs #8073 #refs 8073 create vn.productionCountryVolume by:ivanm +- feat: refs #8117 add worker first and last name to item type query by:jtubau +- feat: refs #8247 added new acl for VnUser model by:Jon +- feat: refs #8258 added uppercase validation on supplier create (origin/8258-uppercaseInputs) by:provira +- feat: refs #8298 add priceOptimum and packagesDiscountFactor to zone and client tables by:jgallego +- feat: refs #8298 add priceOptimum column to zoneEvent and update zone fixture data by:jgallego +- feat: refs #8298 update price calculation logic and add packagesDiscountFactor column to client table by:jgallego +- feat: refs #8357 Agregados triggers para manejar exclusiones de trabajadores en la tabla workerMana by:guillermo +- feat: refs #8361 add hasToDownloadRate field to currency model and update exchange rate logic by:jgallego +- feat: refs #8381 add initial and final temperature fields to entry model and queries by:jgallego + +### Changed 📦 + +- refactor: order by id by:alexm +- refactor: refs #7202 modified new invoice procedure and incoterms sql by:Jon +- refactor: refs #7202 modified procedure to include customsAgent field when creating an invoice by:Jon +- refactor: refs #8378 deprecate bi.f_tvc by:ivanm + +### Fixed 🛠️ + +- feat: refs #8298 add priceOptimum column to zoneEvent and update zone fixture data by:jgallego +- fix: prevent slow update (HEAD -> 8452-testToMaster, origin/test, origin/8452-testToMaster, test) by:alexm +- fix: refs #7202 fixed back test by:Jon +- fix: refs #7202 fixed sql by:Jon +- fix: refs #7569 refs·6861 ticketOrderReserve by:sergiodt +- fix: refs #7569 refs·6861 ticketOrderReserve (origin/7569-sendEmailOrderTicket) by:sergiodt +- fix: refs #7569 refs#8188 add IfNotExists by:sergiodt +- fix: refs #7832 update ticketService model test suite to correct describe block by:jgallego +- fix: refs #8298 remove duplicate entry in English locale file by:jgallego +- fix: refs #8361 streamline transaction handling in exchangeRateUpdate by:jgallego +- test: refs #8448 fix e2e by:alexm + # Version 25.00 - 2025-01-14 ### Added 🆕 diff --git a/back/methods/collection/getTickets.js b/back/methods/collection/getTickets.js index 85d1111df..dfe86c94c 100644 --- a/back/methods/collection/getTickets.js +++ b/back/methods/collection/getTickets.js @@ -65,7 +65,8 @@ module.exports = Self => { iss.id itemShelvingSaleFk, iss.isPicked, iss.itemShelvingFk, - st.code stateCode + st.code stateCode, + ac.username FROM ticketCollection tc LEFT JOIN collection c ON c.id = tc.collectionFk JOIN sale s ON s.ticketFk = tc.ticketFk @@ -80,6 +81,7 @@ module.exports = Self => { LEFT JOIN itemColor ic ON ic.itemFk = s.itemFk LEFT JOIN origin o ON o.id = i.originFk LEFT JOIN state st ON st.id = sg.stateFk + LEFT JOIN account.user ac ON ac.id = iss.userFk WHERE tc.collectionFk = ? GROUP BY s.id, ish.id, p.code, p2.code UNION ALL @@ -109,7 +111,8 @@ module.exports = Self => { iss.id itemShelvingSaleFk, iss.isPicked, iss.itemShelvingFk, - st.code stateCode + st.code stateCode, + ac.username FROM sectorCollection sc JOIN sectorCollectionSaleGroup ss ON ss.sectorCollectionFk = sc.id JOIN saleGroup sg ON sg.id = ss.saleGroupFk @@ -124,6 +127,7 @@ module.exports = Self => { LEFT JOIN itemColor ic ON ic.itemFk = s.itemFk LEFT JOIN origin o ON o.id = i.originFk LEFT JOIN state st ON st.id = sg.stateFk + LEFT JOIN account.user ac ON ac.id = sg.userFk WHERE sc.id = ? AND sgd.saleGroupFk GROUP BY s.id, ish.id, p.code, p2.code`, [id, id], myOptions); diff --git a/back/models/payment.json b/back/models/payment.json index ed354969e..2bc665503 100644 --- a/back/models/payment.json +++ b/back/models/payment.json @@ -52,7 +52,7 @@ }, "payMethod": { "type": "belongsTo", - "model": "PayMethodFk", + "model": "PayMethod", "foreignKey": "payMethodFk" }, "company": { @@ -61,4 +61,4 @@ "foreignKey": "companyFk" } } -} \ No newline at end of file +} diff --git a/db/dump/.dump/data.sql b/db/dump/.dump/data.sql index b95890b0d..7fa281197 100644 --- a/db/dump/.dump/data.sql +++ b/db/dump/.dump/data.sql @@ -4,7 +4,7 @@ USE `util`; /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -INSERT INTO `version` VALUES ('vn-database','11391','43edb1f82e88dcc44eedc8501b93c1fac66d71e9','2025-01-14 07:32:09','11407'); +INSERT INTO `version` VALUES ('vn-database','11410','7a02af9a3acae14a658de1557baa44542c24d480','2025-01-28 07:44:02','11423'); INSERT INTO `versionLog` VALUES ('vn-database','10107','00-firstScript.sql','jenkins@10.0.2.69','2022-04-23 10:53:53',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','10112','00-firstScript.sql','jenkins@10.0.2.69','2022-05-09 09:14:53',NULL,NULL); @@ -1041,6 +1041,7 @@ INSERT INTO `versionLog` VALUES ('vn-database','11261','00-firstScript.sql','jen INSERT INTO `versionLog` VALUES ('vn-database','11262','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2024-10-03 07:47:43',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11263','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2024-09-27 12:05:32',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11264','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-12 08:00:15',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11269','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:43:58',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11271','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-12 08:00:15',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11272','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2024-11-12 08:00:15',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11273','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2024-10-03 10:50:51',NULL,NULL); @@ -1140,9 +1141,24 @@ INSERT INTO `versionLog` VALUES ('vn-database','11379','00-firstScript.sql','jen INSERT INTO `versionLog` VALUES ('vn-database','11379','01-secScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:32',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11384','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:32',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11385','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-07 07:46:33',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11387','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:43:58',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11390','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-14 07:32:08',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11391','00-itemAlter.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-14 07:32:08',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11396','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:43:58',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11398','00-zoneEventPriceOptimum.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:43:59',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11398','00-zonePriceOptimum.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:43:59',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11398','01-zoneUpdate.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:43:59',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11398','02-clientAlter.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:43:59',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11398','03-clientConfig.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:43:59',NULL,NULL); INSERT INTO `versionLog` VALUES ('vn-database','11400','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-09 09:55:24',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11405','00-entryAlter.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:44:00',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11406','00-currrencyAlter.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:44:00',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11406','01-currrencyUpdate.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:44:00',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11407','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:44:00',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11410','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-28 07:44:00',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11415','00-firstScript.sql','jenkins@db-proxy1.servers.dc.verdnatura.es','2025-01-20 08:12:38',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11418','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-21 11:03:27',NULL,NULL); +INSERT INTO `versionLog` VALUES ('vn-database','11423','00-firstScript.sql','jenkins@db-proxy2.servers.dc.verdnatura.es','2025-01-23 15:19:32',NULL,NULL); /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; @@ -1241,6 +1257,7 @@ INSERT INTO `role` VALUES (127,'timeControl','Tablet para fichar',1,'2024-01-09 INSERT INTO `role` VALUES (129,'buyerAssistant','Comprador que tienes mas permisos para ayudar al buyerBoss en algunas tareas',1,'2024-02-06 06:59:12','2024-02-06 06:59:12',783); INSERT INTO `role` VALUES (130,'reviewer','Revisor de producción',1,'2024-06-11 00:00:00','2024-06-11 00:00:00',10578); INSERT INTO `role` VALUES (131,'supplier','Privilegios básicos de un proveedor',1,'2024-07-05 10:18:58','2024-07-05 10:18:58',19295); +INSERT INTO `role` VALUES (132,'salesPersonClaim','Departamento de ventas con funciones de reclamaciones',1,'2025-01-17 07:07:40','2025-01-17 07:07:40',19295); INSERT INTO `roleInherit` VALUES (1,1,2,NULL); INSERT INTO `roleInherit` VALUES (2,1,3,NULL); @@ -1252,7 +1269,6 @@ INSERT INTO `roleInherit` VALUES (8,5,33,NULL); INSERT INTO `roleInherit` VALUES (10,11,6,NULL); INSERT INTO `roleInherit` VALUES (11,13,1,NULL); INSERT INTO `roleInherit` VALUES (12,15,35,NULL); -INSERT INTO `roleInherit` VALUES (16,17,20,NULL); INSERT INTO `roleInherit` VALUES (17,17,37,NULL); INSERT INTO `roleInherit` VALUES (18,17,39,NULL); INSERT INTO `roleInherit` VALUES (19,17,64,NULL); @@ -1327,7 +1343,6 @@ INSERT INTO `roleInherit` VALUES (105,72,18,NULL); INSERT INTO `roleInherit` VALUES (106,73,5,NULL); INSERT INTO `roleInherit` VALUES (107,73,64,NULL); INSERT INTO `roleInherit` VALUES (108,73,19,NULL); -INSERT INTO `roleInherit` VALUES (109,59,50,NULL); INSERT INTO `roleInherit` VALUES (115,39,76,NULL); INSERT INTO `roleInherit` VALUES (117,65,76,NULL); INSERT INTO `roleInherit` VALUES (118,30,76,NULL); @@ -1520,6 +1535,9 @@ INSERT INTO `roleInherit` VALUES (379,103,121,19294); INSERT INTO `roleInherit` VALUES (381,119,123,19295); INSERT INTO `roleInherit` VALUES (382,48,72,783); INSERT INTO `roleInherit` VALUES (383,114,111,19295); +INSERT INTO `roleInherit` VALUES (384,132,18,19295); +INSERT INTO `roleInherit` VALUES (385,132,72,19295); +INSERT INTO `roleInherit` VALUES (386,109,132,19295); INSERT INTO `userPassword` VALUES (1,7,1,0,2,1); @@ -2389,6 +2407,7 @@ INSERT INTO `ACL` VALUES (1012,'OsrmConfig','optimize','READ','ALLOW','ROLE','em INSERT INTO `ACL` VALUES (1013,'Route','optimizePriority','*','ALLOW','ROLE','employee',10578); INSERT INTO `ACL` VALUES (1014,'Worker','canModifyAbsenceInPast','WRITE','ALLOW','ROLE','hr',10578); INSERT INTO `ACL` VALUES (1015,'Worker','__get__sip','READ','ALLOW','ROLE','employee',19294); +INSERT INTO `ACL` VALUES (1016,'VnUser','adminUser','WRITE','ALLOW','ROLE','sysadmin',10578); INSERT INTO `fieldAcl` VALUES (1,'Client','name','update','employee'); INSERT INTO `fieldAcl` VALUES (2,'Client','contact','update','employee'); @@ -2687,71 +2706,72 @@ INSERT INTO `continent` VALUES (3,'África','AF'); INSERT INTO `continent` VALUES (4,'Europa','EU'); INSERT INTO `continent` VALUES (5,'Oceanía','OC'); -INSERT INTO `department` VALUES (1,'VN','VERDNATURA',1,130,763,0,0,0,0,26,NULL,'/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (1,'VN','VERDNATURA',1,132,763,0,0,0,0,26,NULL,'/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (22,'shopping','COMPRAS',2,5,NULL,72,0,0,1,1,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (23,'CMA','CAMARA',15,16,NULL,72,1,1,2,0,37,'/1/37/',NULL,0,NULL,0,1,1,1,NULL,NULL,NULL,'PREVIOUS'); INSERT INTO `department` VALUES (31,'it','INFORMATICA',6,7,NULL,72,0,0,1,0,1,'/1/','informatica-cau',1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (34,'accounting','CONTABILIDAD',8,9,NULL,0,0,0,1,0,1,'/1/',NULL,1,NULL,1,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (35,'finance','FINANZAS',10,11,NULL,0,0,0,1,0,1,'/1/',NULL,1,'begonya@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (36,'labor','LABORAL',12,13,NULL,0,0,0,1,0,1,'/1/',NULL,1,NULL,1,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (37,'PROD','PRODUCCION',14,37,NULL,72,1,1,1,11,1,'/1/',NULL,0,NULL,0,1,1,1,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (37,'PROD','PRODUCCION',14,39,NULL,72,1,1,1,12,1,'/1/',NULL,0,NULL,0,1,1,1,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (38,'picking','SACADO',17,18,NULL,72,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,1,0,1,NULL,NULL,NULL,'ON_PREPARATION'); INSERT INTO `department` VALUES (39,'packing','ENCAJADO',19,20,NULL,72,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,0,0,1,NULL,NULL,NULL,'PACKING'); -INSERT INTO `department` VALUES (41,'administration','ADMINISTRACION',38,39,NULL,72,0,0,1,0,1,'/1/',NULL,1,NULL,1,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (43,'VT','VENTAS',40,89,NULL,0,0,0,1,24,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (44,'management','GERENCIA',90,91,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (45,'logistic','LOGISTICA',92,93,NULL,72,0,0,1,0,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (46,'delivery','REPARTO',94,95,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,1,0,0,NULL,NULL,NULL,'DELIVERY'); -INSERT INTO `department` VALUES (48,'storage','ALMACENAJE',96,97,NULL,0,1,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,'STORAGE'); -INSERT INTO `department` VALUES (49,NULL,'PROPIEDAD',98,99,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (52,NULL,'CARGA AEREA',100,101,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (53,'marketing','MARKETING Y COMUNICACIÓN',41,42,NULL,72,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (54,NULL,'ORNAMENTALES',102,103,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (41,'administration','ADMINISTRACION',40,41,NULL,72,0,0,1,0,1,'/1/',NULL,1,NULL,1,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (43,'VT','VENTAS',42,91,NULL,0,0,0,1,24,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (44,'management','GERENCIA',92,93,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (45,'logistic','LOGISTICA',94,95,NULL,72,0,0,1,0,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (46,'delivery','REPARTO',96,97,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,1,0,0,NULL,NULL,NULL,'DELIVERY'); +INSERT INTO `department` VALUES (48,'storage','ALMACENAJE',98,99,NULL,0,1,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,'STORAGE'); +INSERT INTO `department` VALUES (49,NULL,'PROPIEDAD',100,101,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (52,NULL,'CARGA AEREA',102,103,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (53,'marketing','MARKETING Y COMUNICACIÓN',43,44,NULL,72,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (54,NULL,'ORNAMENTALES',104,105,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (55,NULL,'TALLER NATURAL',21,22,14548,72,0,0,2,0,37,'/1/37/',NULL,0,NULL,0,1,1,0,1118,NULL,NULL,NULL); INSERT INTO `department` VALUES (56,NULL,'TALLER ARTIFICIAL',23,24,8470,72,0,0,2,0,37,'/1/37/',NULL,0,NULL,0,1,1,0,1927,NULL,NULL,NULL); -INSERT INTO `department` VALUES (58,'CMP','CAMPOS',104,107,NULL,72,0,0,1,1,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,'FIELD'); -INSERT INTO `department` VALUES (59,'maintenance','MANTENIMIENTO',108,109,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,1,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (60,'claims','RECLAMACIONES',43,44,NULL,72,0,0,2,0,43,'/1/43/',NULL,0,NULL,0,1,0,0,NULL,NULL,NULL,'CLAIM'); -INSERT INTO `department` VALUES (61,NULL,'VNH',110,113,NULL,73,0,0,1,1,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (66,NULL,'VERDNAMADRID',114,115,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (58,'CMP','CAMPOS',106,109,NULL,72,0,0,1,1,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,'FIELD'); +INSERT INTO `department` VALUES (59,'maintenance','MANTENIMIENTO',110,111,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,1,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (60,'claims','RECLAMACIONES',45,46,NULL,72,0,0,2,0,43,'/1/43/',NULL,0,NULL,0,1,0,0,NULL,NULL,NULL,'CLAIM'); +INSERT INTO `department` VALUES (61,NULL,'VNH',112,115,NULL,73,0,0,1,1,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (66,NULL,'VERDNAMADRID',116,117,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (68,NULL,'COMPLEMENTOS',25,26,NULL,72,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,1,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (69,NULL,'VERDNABARNA',116,117,NULL,74,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (80,'spainTeam5','EQUIPO ESPAÑA 5',45,46,4250,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (86,NULL,'LIMPIEZA',118,119,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (89,NULL,'COORDINACION',120,121,NULL,0,1,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (90,NULL,'TRAILER',111,112,NULL,0,0,0,2,0,61,'/1/61/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (69,NULL,'VERDNABARNA',118,119,NULL,74,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (80,'spainTeam5','EQUIPO ESPAÑA 5',47,48,4250,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (86,NULL,'LIMPIEZA',120,121,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (89,NULL,'COORDINACION',122,123,NULL,0,1,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (90,NULL,'TRAILER',113,114,NULL,0,0,0,2,0,61,'/1/61/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (91,'artificial','ARTIFICIAL',27,28,NULL,0,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,'PREVIOUS'); -INSERT INTO `department` VALUES (92,NULL,'EQUIPO SILVERIO',47,48,1203,0,0,0,2,0,43,'/1/43/','sdc_equipo',0,'gestioncomercial@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (94,'spainTeam2','EQUIPO ESPAÑA 2',49,50,3797,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (95,'spainTeam1','EQUIPO ESPAÑA 1',51,52,24065,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (96,NULL,'EQUIPO C LOPEZ',53,54,4661,0,0,0,2,0,43,'/1/43/','cla_equipo',0,'gestioncomercial@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (115,NULL,'EQUIPO CLAUDI',55,56,3810,0,0,0,2,0,43,'/1/43/','csr_equipo',0,'gestioncomercial@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (123,NULL,'EQUIPO ELENA BASCUÑANA',57,58,7102,0,0,0,2,0,43,'/1/43/','ebt_equipo',0,'gestioncomercial@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (124,NULL,'CONTROL INTERNO',122,123,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (125,'spainTeam3','EQUIPO ESPAÑA 3',59,60,1118,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (92,NULL,'EQUIPO SILVERIO',49,50,1203,0,0,0,2,0,43,'/1/43/','sdc_equipo',0,'gestioncomercial@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (94,'spainTeam2','EQUIPO ESPAÑA 2',51,52,3797,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (95,'spainTeam1','EQUIPO ESPAÑA 1',53,54,24065,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (96,NULL,'EQUIPO C LOPEZ',55,56,4661,0,0,0,2,0,43,'/1/43/','cla_equipo',0,'gestioncomercial@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (115,NULL,'EQUIPO CLAUDI',57,58,3810,0,0,0,2,0,43,'/1/43/','csr_equipo',0,'gestioncomercial@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (123,NULL,'EQUIPO ELENA BASCUÑANA',59,60,7102,0,0,0,2,0,43,'/1/43/','ebt_equipo',0,'gestioncomercial@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (124,NULL,'CONTROL INTERNO',124,125,NULL,72,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (125,'spainTeam3','EQUIPO ESPAÑA 3',61,62,1118,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (126,NULL,'PRESERVADO',29,30,NULL,0,0,0,2,0,37,'/1/37/',NULL,0,NULL,0,1,1,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (128,NULL,'PALETIZADO',31,32,NULL,0,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,'PALLETIZING'); INSERT INTO `department` VALUES (130,'reviewers','REVISION',33,34,NULL,0,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,0,0,1,NULL,NULL,NULL,'ON_CHECKING'); -INSERT INTO `department` VALUES (131,'greenhouse','INVERNADERO',105,106,NULL,0,0,0,2,0,58,'/1/58/',NULL,0,NULL,0,1,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (132,NULL,'EQUIPO DC',61,62,1731,0,0,0,2,0,43,'/1/43/','dc_equipo',1,'gestioncomercial@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (133,'franceTeamManagement','EQUIPO GESTIÓN FRANCIA',63,64,9751,72,0,0,2,0,43,'/1/43/','fr_equipo',1,'gestionfrancia@verdnatura.es',0,0,0,0,NULL,NULL,'3300',NULL); -INSERT INTO `department` VALUES (134,'portugalTeam','EQUIPO PORTUGAL',65,66,8964,0,0,0,2,0,43,'/1/43/','pt_equipo',1,'portugal@verdnatura.es',0,0,0,0,NULL,NULL,'3500',NULL); -INSERT INTO `department` VALUES (135,'routers','ENRUTADORES',124,125,NULL,0,0,0,1,0,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (136,'heavyVehicles','VEHICULOS PESADOS',126,127,NULL,0,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (137,'sorter','SORTER',128,129,NULL,0,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (139,'spainTeam4','EQUIPO ESPAÑA 4',67,68,3803,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (140,'internationalTeam','EQUIPO INTERNACIONAL',69,70,24065,0,0,0,2,0,43,'/1/43/','int_equipo',1,'international@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (131,'greenhouse','INVERNADERO',107,108,NULL,0,0,0,2,0,58,'/1/58/',NULL,0,NULL,0,1,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (132,NULL,'EQUIPO DC',63,64,1731,0,0,0,2,0,43,'/1/43/','dc_equipo',1,'gestioncomercial@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (133,'franceTeamManagement','EQUIPO GESTIÓN FRANCIA',65,66,9751,72,0,0,2,0,43,'/1/43/','fr_equipo',1,'gestionfrancia@verdnatura.es',0,0,0,0,NULL,NULL,'3300',NULL); +INSERT INTO `department` VALUES (134,'portugalTeam','EQUIPO PORTUGAL',67,68,8964,0,0,0,2,0,43,'/1/43/','pt_equipo',1,'portugal@verdnatura.es',0,0,0,0,NULL,NULL,'3500',NULL); +INSERT INTO `department` VALUES (135,'routers','ENRUTADORES',126,127,NULL,0,0,0,1,0,1,'/1/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (136,'heavyVehicles','VEHICULOS PESADOS',128,129,NULL,0,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (137,'sorter','SORTER',130,131,NULL,0,0,0,1,0,1,'/1/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (139,'spainTeam4','EQUIPO ESPAÑA 4',69,70,3803,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,NULL,NULL); +INSERT INTO `department` VALUES (140,'internationalTeam','EQUIPO INTERNACIONAL',71,72,24065,0,0,0,2,0,43,'/1/43/','int_equipo',1,'international@verdnatura.es',0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `department` VALUES (141,NULL,'PREVIA',35,36,NULL,0,1,0,2,0,37,'/1/37/',NULL,0,NULL,0,0,0,1,NULL,NULL,NULL,'PREVIOUS'); INSERT INTO `department` VALUES (146,NULL,'VERDNACOLOMBIA',3,4,NULL,72,0,0,2,0,22,'/1/22/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); -INSERT INTO `department` VALUES (147,'spainTeamAsia','EQUIPO ESPAÑA ASIA',71,72,40214,0,0,0,2,0,43,'/1/43/','esA_equipo',1,'esA@verdnatura.es',0,0,0,0,NULL,NULL,'5500',NULL); -INSERT INTO `department` VALUES (148,'franceTeamCatchment','EQUIPO CAPTACIÓN FRANCIA',73,74,25178,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,'6000',NULL); -INSERT INTO `department` VALUES (149,'spainTeamCatchment','EQUIPO ESPAÑA CAPTACIÓN',75,76,1203,0,0,0,2,0,43,'/1/43/','es_captacion_equipo',1,'es_captacion@verdnatura.es',0,0,0,0,NULL,NULL,'5700',NULL); -INSERT INTO `department` VALUES (150,'spainTeamLevanteIslands','EQUIPO ESPAÑA LEVANTE',77,78,1118,0,0,0,2,0,43,'/1/43/','es_levante_equipo',1,'es_levante@verdnatura.es',0,0,0,0,NULL,NULL,'5000',NULL); -INSERT INTO `department` VALUES (151,'spainTeamNorthwest','EQUIPO ESPAÑA NOROESTE',79,80,7102,0,0,0,2,0,43,'/1/43/','es_noroeste_equipo',1,'es_noroeste@verdnatura.es',0,0,0,0,NULL,NULL,'5300',NULL); -INSERT INTO `department` VALUES (152,'spainTeamNortheast','EQUIPO ESPAÑA NORESTE',81,82,1118,0,0,0,2,0,43,'/1/43/','es_noreste_equipo',1,'es_noreste@verdnatura.es',0,0,0,0,NULL,NULL,'5200',NULL); -INSERT INTO `department` VALUES (153,'spainTeamSouth','EQUIPO ESPAÑA SUR',83,84,36578,0,0,0,2,0,43,'/1/43/','es_sur_equipo',1,'es_sur@verdnatura.es',0,0,0,0,NULL,NULL,'5400',NULL); -INSERT INTO `department` VALUES (154,'spainTeamCenter','EQUIPO ESPAÑA CENTRO',85,86,4661,0,0,0,2,0,43,'/1/43/','es_centro_equipo',1,'es_centro@verdnatura.es',0,0,0,0,NULL,NULL,'5100',NULL); -INSERT INTO `department` VALUES (155,'spainTeamVip','EQUIPO ESPAÑA VIP',87,88,5432,0,0,0,2,0,43,'/1/43/','es_vip_equipo',1,'es_vip@verdnatura.es',0,0,0,0,NULL,NULL,'5600',NULL); +INSERT INTO `department` VALUES (147,'spainTeamAsia','EQUIPO ESPAÑA ASIA',73,74,40214,0,0,0,2,0,43,'/1/43/','esA_equipo',1,'esA@verdnatura.es',0,0,0,0,NULL,NULL,'5500',NULL); +INSERT INTO `department` VALUES (148,'franceTeamCatchment','EQUIPO CAPTACIÓN FRANCIA',75,76,25178,0,0,0,2,0,43,'/1/43/',NULL,1,NULL,0,0,0,0,NULL,NULL,'6000',NULL); +INSERT INTO `department` VALUES (149,'spainTeamCatchment','EQUIPO ESPAÑA CAPTACIÓN',77,78,1203,0,0,0,2,0,43,'/1/43/','es_captacion_equipo',1,'es_captacion@verdnatura.es',0,0,0,0,NULL,NULL,'5700',NULL); +INSERT INTO `department` VALUES (150,'spainTeamLevanteIslands','EQUIPO ESPAÑA LEVANTE',79,80,1118,0,0,0,2,0,43,'/1/43/','es_levante_equipo',1,'es_levante@verdnatura.es',0,0,0,0,NULL,NULL,'5000',NULL); +INSERT INTO `department` VALUES (151,'spainTeamNorthwest','EQUIPO ESPAÑA NOROESTE',81,82,7102,0,0,0,2,0,43,'/1/43/','es_noroeste_equipo',1,'es_noroeste@verdnatura.es',0,0,0,0,NULL,NULL,'5300',NULL); +INSERT INTO `department` VALUES (152,'spainTeamNortheast','EQUIPO ESPAÑA NORESTE',83,84,1118,0,0,0,2,0,43,'/1/43/','es_noreste_equipo',1,'es_noreste@verdnatura.es',0,0,0,0,NULL,NULL,'5200',NULL); +INSERT INTO `department` VALUES (153,'spainTeamSouth','EQUIPO ESPAÑA SUR',85,86,36578,0,0,0,2,0,43,'/1/43/','es_sur_equipo',1,'es_sur@verdnatura.es',0,0,0,0,NULL,NULL,'5400',NULL); +INSERT INTO `department` VALUES (154,'spainTeamCenter','EQUIPO ESPAÑA CENTRO',87,88,4661,0,0,0,2,0,43,'/1/43/','es_centro_equipo',1,'es_centro@verdnatura.es',0,0,0,0,NULL,NULL,'5100',NULL); +INSERT INTO `department` VALUES (155,'spainTeamVip','EQUIPO ESPAÑA VIP',89,90,5432,0,0,0,2,0,43,'/1/43/','es_vip_equipo',1,'es_vip@verdnatura.es',0,0,0,0,NULL,NULL,'5600',NULL); +INSERT INTO `department` VALUES (156,NULL,'COCINA',37,38,NULL,0,0,0,2,0,37,'/1/37/',NULL,0,NULL,0,0,0,0,NULL,NULL,NULL,NULL); INSERT INTO `docuware` VALUES (1,'deliveryNote','Albaranes cliente','find','find','N__ALBAR_N',NULL); INSERT INTO `docuware` VALUES (2,'deliveryNote','Albaranes cliente','store','Archivar','N__ALBAR_N',NULL); diff --git a/db/dump/.dump/privileges.sql b/db/dump/.dump/privileges.sql index 598bfdf75..1d4fce189 100644 --- a/db/dump/.dump/privileges.sql +++ b/db/dump/.dump/privileges.sql @@ -602,7 +602,7 @@ INSERT IGNORE INTO `tables_priv` VALUES ('','vn','administrative','projectState' INSERT IGNORE INTO `tables_priv` VALUES ('','vn','employee','entrySplit__','alexm@%','0000-00-00 00:00:00','Select,Insert,Update,Delete',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','employee','entryType','alexm@%','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','administrative','projectNotes','alexm@%','0000-00-00 00:00:00','Select',''); -INSERT IGNORE INTO `tables_priv` VALUES ('','vn','administrative','project','juan@10.5.1.1','0000-00-00 00:00:00','Select,Update',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','administrative','project','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select,Insert,Update',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','employee','productionConfig','alexm@%','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','manager','productionConfig','alexm@%','0000-00-00 00:00:00','Update',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','creditInsurance','juan@db-proxy2.static.verdnatura.es','0000-00-00 00:00:00','Select',''); @@ -1498,6 +1498,13 @@ INSERT IGNORE INTO `tables_priv` VALUES ('','vn','employee','zoneGeo','guillermo INSERT IGNORE INTO `tables_priv` VALUES ('','vn','buyer','itemCampaign','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','itemCampaign','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); INSERT IGNORE INTO `tables_priv` VALUES ('','vn','buyer','campaign','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','awb','guillermo@db-proxy2.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','awbComponent','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','grafana','awbComponentType','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','logisticAssist','itemSoldOutTag','jenkins@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select,Insert,Update,Delete',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','logisticAssist','itemDurationTag','jenkins@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select,Insert,Update,Delete',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','logisticAssist','itemGrowingTag','jenkins@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Select,Insert,Update,Delete',''); +INSERT IGNORE INTO `tables_priv` VALUES ('','vn','adminBoss','receipt','guillermo@db-proxy1.servers.dc.verdnatura.es','0000-00-00 00:00:00','Update,Delete',''); /*!40000 ALTER TABLE `tables_priv` ENABLE KEYS */; /*!40000 ALTER TABLE `columns_priv` DISABLE KEYS */; @@ -2142,6 +2149,7 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','srt','delivery','buffer_settypebynam INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','expedition_getstate','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','srt','delivery','expedition_scan','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','itemshelving_get','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); +INSERT IGNORE INTO `procs_priv` VALUES ('','vn','financial','remittance_calc','PROCEDURE','jgallego@db-proxy2.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','itemshelving_add','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','itemshelving_getsaledate','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','delivery','itemshelving_filterbuyer','PROCEDURE','guillermo@db-proxy1.static.verdnatura.es','Execute','0000-00-00 00:00:00'); @@ -2204,7 +2212,6 @@ INSERT IGNORE INTO `procs_priv` VALUES ('','vn','claimManager','entry_getTransfe INSERT IGNORE INTO `procs_priv` VALUES ('','vn','buyer','entry_getTransfer','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','administrative','intrastat_estimateNet','FUNCTION','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','artificialBoss','confection_controlSource','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); -INSERT IGNORE INTO `procs_priv` VALUES ('','vn','financial','remittance_calc','PROCEDURE','alexm@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','util','developer','connection_kill','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','vn','financial','client_getRisk','PROCEDURE','jenkins@db-proxy1.servers.dc.verdnatura.es','Execute','0000-00-00 00:00:00'); INSERT IGNORE INTO `procs_priv` VALUES ('','account','developer','user_hasRole','FUNCTION','root@localhost','Execute','0000-00-00 00:00:00'); @@ -2312,6 +2319,7 @@ INSERT IGNORE INTO `global_priv` VALUES ('','root','{\"access\": 549755781119, \ INSERT IGNORE INTO `global_priv` VALUES ('','salesAssistant','{\"access\":0,\"version_id\":101106,\"is_role\":true}'); INSERT IGNORE INTO `global_priv` VALUES ('','salesBoss','{\"access\":0,\"version_id\":101106,\"is_role\":true}'); INSERT IGNORE INTO `global_priv` VALUES ('','salesPerson','{\"access\": 0, \"is_role\": true,\"version_id\":101106}'); +INSERT IGNORE INTO `global_priv` VALUES ('','salesPersonClaim','{\"access\":0,\"version_id\":101106,\"is_role\":true}'); INSERT IGNORE INTO `global_priv` VALUES ('','salesTeamBoss','{\"access\":0,\"version_id\":100707,\"is_role\":true}'); INSERT IGNORE INTO `global_priv` VALUES ('','salix','{\"access\":33555456,\"version_id\":100707,\"is_role\":true}'); INSERT IGNORE INTO `global_priv` VALUES ('','sysadmin','{\"access\": 201326592, \"is_role\": true, \"version_id\": 100707}'); diff --git a/db/dump/.dump/structure.sql b/db/dump/.dump/structure.sql index 58f1e7591..97f7bc512 100644 --- a/db/dump/.dump/structure.sql +++ b/db/dump/.dump/structure.sql @@ -2543,17 +2543,17 @@ CREATE TABLE `defaulting` ( /*!40101 SET character_set_client = @saved_cs_client */; -- --- Table structure for table `f_tvc` +-- Table structure for table `f_tvc__` -- -DROP TABLE IF EXISTS `f_tvc`; +DROP TABLE IF EXISTS `f_tvc__`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE `f_tvc` ( +CREATE TABLE `f_tvc__` ( `Id_Ticket` int(11) NOT NULL, PRIMARY KEY (`Id_Ticket`), CONSTRAINT `id_ticket_to_comisionantes` FOREIGN KEY (`Id_Ticket`) REFERENCES `vn`.`ticket` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Almacenamos la lista de tickets para agilizar la consulta. Corresponde a los clientes REAL y en los almacenes COMISIONANTES'; +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='@deprecated 2025-01-15'; /*!40101 SET character_set_client = @saved_cs_client */; -- @@ -25878,7 +25878,7 @@ CREATE TABLE `address` ( `isActive` tinyint(4) NOT NULL DEFAULT 1, `longitude` decimal(11,7) DEFAULT NULL COMMENT 'Indica la última longitud proporcionada por tabla delivery', `latitude` decimal(11,7) DEFAULT NULL COMMENT 'Indica la última latitud proporcionada por tabla delivery', - `isEqualizated` tinyint(1) NOT NULL DEFAULT 0, + `isEqualizated` tinyint(1) DEFAULT NULL, `customsAgentFk` int(11) DEFAULT NULL, `incotermsFk` varchar(3) DEFAULT NULL, `isLogifloraAllowed` tinyint(4) NOT NULL DEFAULT 0, @@ -27725,6 +27725,7 @@ CREATE TABLE `client` ( `hasDailyInvoice` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Indica si el cliente requiere facturación diaria por defecto se copiará lo que tenga country.hasDailyInvoice', `geoFk` int(11) DEFAULT NULL, `editorFk` int(10) unsigned DEFAULT NULL, + `packagesDiscountFactor` decimal(4,3) NOT NULL DEFAULT 1.000 COMMENT 'Porcentaje de ajuste entre el numero de bultos medio del cliente, y el número medio óptimo para las zonas en las que compra', PRIMARY KEY (`id`), UNIQUE KEY `IF` (`fi`), KEY `Id_Trabajador` (`salesPersonFk`), @@ -27804,6 +27805,8 @@ CREATE TABLE `clientConfig` ( `defaultHasCoreVnl` tinyint(1) DEFAULT NULL, `defaultMandateTypeFk` smallint(5) DEFAULT NULL, `monthsToDisableUser` int(10) unsigned DEFAULT NULL, + `packagesOptimum` int(10) unsigned NOT NULL DEFAULT 20 COMMENT 'Numero de bultos por cliente/dia para conseguir el precio optimo', + `monthsToCalcOptimumPrice` tinyint(3) unsigned NOT NULL DEFAULT 3 COMMENT 'Número de meses a usar para el cálculo de client.packagesDiscountFactor', PRIMARY KEY (`id`), KEY `clientNewConfigPayMethod_FK` (`defaultPayMethodFk`), KEY `clientNewConfigMandateType_FK` (`defaultMandateTypeFk`), @@ -29061,6 +29064,7 @@ CREATE TABLE `currency` ( `code` varchar(3) NOT NULL, `name` varchar(45) DEFAULT NULL, `ratio` double NOT NULL DEFAULT 1, + `hasToDownloadRate` tinyint(1) NOT NULL DEFAULT 0 COMMENT 'Si se guarda el tipo de cambio diariamente en referenceRate', PRIMARY KEY (`id`), UNIQUE KEY `Moneda_UNIQUE` (`code`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; @@ -29972,6 +29976,8 @@ CREATE TABLE `entry` ( `editorFk` int(10) unsigned DEFAULT NULL, `lockerUserFk` int(10) unsigned DEFAULT NULL, `locked` datetime DEFAULT current_timestamp(), + `initialTemperature` decimal(10,2) DEFAULT NULL COMMENT 'Temperatura de como lo recibimos del proveedor ej. en colombia', + `finalTemperature` decimal(10,2) DEFAULT NULL COMMENT 'Temperatura final de como llega a nuestras instalaciones', PRIMARY KEY (`id`), KEY `Id_Proveedor` (`supplierFk`), KEY `Fecha` (`dated`), @@ -31774,6 +31780,8 @@ CREATE TABLE `invoiceOut` ( `cplusTaxBreakFk` int(10) unsigned NOT NULL DEFAULT 1, `cplusSubjectOpFk` int(10) unsigned NOT NULL DEFAULT 1, `siiTrascendencyInvoiceOutFk` int(10) unsigned NOT NULL DEFAULT 1, + `customsAgentFk` int(11) DEFAULT NULL, + `incotermsFk` varchar(3) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `invoiceOut_unique` (`ref`), KEY `Id_Banco` (`bankFk`), @@ -31786,9 +31794,13 @@ CREATE TABLE `invoiceOut` ( KEY `Facturas_ibfk_5_idx` (`siiTrascendencyInvoiceOutFk`), KEY `Facturas_idx_Vencimiento` (`dued`), KEY `invoiceOut_serial` (`serial`), + KEY `invoiceOut_customsAgentFk` (`customsAgentFk`), + KEY `invoiceOut_incotermsFk` (`incotermsFk`), + CONSTRAINT `invoiceOut_customsAgentFk` FOREIGN KEY (`customsAgentFk`) REFERENCES `customsAgent` (`id`) ON UPDATE CASCADE, CONSTRAINT `invoiceOut_ibfk_2` FOREIGN KEY (`siiTypeInvoiceOutFk`) REFERENCES `siiTypeInvoiceOut` (`id`) ON UPDATE CASCADE, CONSTRAINT `invoiceOut_ibfk_3` FOREIGN KEY (`cplusSubjectOpFk`) REFERENCES `cplusSubjectOp` (`id`) ON UPDATE CASCADE, CONSTRAINT `invoiceOut_ibfk_4` FOREIGN KEY (`cplusTaxBreakFk`) REFERENCES `cplusTaxBreak` (`id`) ON UPDATE CASCADE, + CONSTRAINT `invoiceOut_incotermsFk` FOREIGN KEY (`incotermsFk`) REFERENCES `incoterms` (`code`) ON UPDATE CASCADE, CONSTRAINT `invoiceOut_serial` FOREIGN KEY (`serial`) REFERENCES `invoiceOutSerial` (`code`), CONSTRAINT `invoice_bank_id` FOREIGN KEY (`bankFk`) REFERENCES `accounting` (`id`) ON UPDATE CASCADE, CONSTRAINT `invoice_customer_id` FOREIGN KEY (`clientFk`) REFERENCES `client` (`id`) ON UPDATE CASCADE @@ -32259,6 +32271,21 @@ CREATE TABLE `itemCost` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Almacena los valores de rotacion en los ultimos 365 dias'; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `itemDurationTag` +-- + +DROP TABLE IF EXISTS `itemDurationTag`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `itemDurationTag` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name_UNIQUE` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Temporary table structure for view `itemEntryIn` -- @@ -32323,6 +32350,21 @@ CREATE TABLE `itemFarmingTag` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `itemGrowingTag` +-- + +DROP TABLE IF EXISTS `itemGrowingTag`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `itemGrowingTag` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name_UNIQUE` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `itemImageQueue` -- @@ -32871,6 +32913,21 @@ SET character_set_client = utf8; 1 AS `removed` */; SET character_set_client = @saved_cs_client; +-- +-- Table structure for table `itemSoldOutTag` +-- + +DROP TABLE IF EXISTS `itemSoldOutTag`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `itemSoldOutTag` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `name_UNIQUE` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `itemStateTag` -- @@ -35460,6 +35517,21 @@ CREATE TABLE `productionConfigLog` ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; /*!40101 SET character_set_client = @saved_cs_client */; +-- +-- Table structure for table `productionCountry` +-- + +DROP TABLE IF EXISTS `productionCountry`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `productionCountry` ( + `countryFk` mediumint(8) unsigned NOT NULL, + `volumeGrowthEstimatePercent` decimal(6,2) DEFAULT NULL COMMENT 'Porcentaje estimado de crecimiento del volumen', + PRIMARY KEY (`countryFk`), + CONSTRAINT `productionCountryVolume_countryFK` FOREIGN KEY (`countryFk`) REFERENCES `country` (`id`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Datos de producción por país'; +/*!40101 SET character_set_client = @saved_cs_client */; + -- -- Table structure for table `productionError` -- @@ -37992,7 +38064,7 @@ CREATE TABLE `supplier` ( `payDay` tinyint(4) unsigned DEFAULT NULL, `payDemFk` tinyint(3) unsigned NOT NULL DEFAULT 7, `created` timestamp NOT NULL DEFAULT current_timestamp(), - `isReal` tinyint(1) unsigned NOT NULL DEFAULT 0, + `isReal` tinyint(1) unsigned NOT NULL DEFAULT 1, `note` text CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT NULL, `postcodeFk` int(11) unsigned DEFAULT NULL, `postCode` char(8) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci DEFAULT NULL, @@ -38585,6 +38657,7 @@ CREATE TABLE `ticket` ( KEY `tickets_zone_fk_idx` (`zoneFk`), KEY `ticket_fk_editor` (`editorFk`), KEY `ticket_cmrFk` (`cmrFk`), + KEY `ticket_landed_IDX` (`landed`) USING BTREE, CONSTRAINT `ticketCompany_Fk` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON UPDATE CASCADE, CONSTRAINT `ticket_cmrFk` FOREIGN KEY (`cmrFk`) REFERENCES `cmr` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `ticket_customer_id` FOREIGN KEY (`clientFk`) REFERENCES `client` (`id`) ON UPDATE CASCADE, @@ -41261,6 +41334,7 @@ CREATE TABLE `zone` ( `agencyModeFk` int(11) NOT NULL, `travelingDays` int(11) NOT NULL DEFAULT 1, `price` decimal(10,2) DEFAULT NULL, + `priceOptimum` decimal(10,2) NOT NULL COMMENT 'Precio mínimo que puede pagar un bulto', `bonus` double NOT NULL DEFAULT 0, `isVolumetric` tinyint(1) NOT NULL DEFAULT 0, `inflation` decimal(5,2) NOT NULL DEFAULT 1.00, @@ -41277,7 +41351,8 @@ CREATE TABLE `zone` ( KEY `zone_address_FK` (`addressFk`), CONSTRAINT `fk_zone_2` FOREIGN KEY (`agencyModeFk`) REFERENCES `agencyMode` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `zone_address_FK` FOREIGN KEY (`addressFk`) REFERENCES `address` (`id`) ON UPDATE CASCADE, - CONSTRAINT `zone_fk_editor` FOREIGN KEY (`editorFk`) REFERENCES `account`.`user` (`id`) + CONSTRAINT `zone_fk_editor` FOREIGN KEY (`editorFk`) REFERENCES `account`.`user` (`id`), + CONSTRAINT `ck_zone_priceOptimum` CHECK (`priceOptimum` <= `price`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; @@ -41370,6 +41445,7 @@ CREATE TABLE `zoneEvent` ( `hour` datetime DEFAULT NULL, `travelingDays` int(11) DEFAULT NULL, `price` decimal(10,2) DEFAULT NULL, + `priceOptimum` decimal(10,2) DEFAULT NULL COMMENT 'Precio mínimo que puede pagar un bulto', `bonus` decimal(10,2) DEFAULT NULL, `m3Max` decimal(10,2) unsigned DEFAULT NULL, `editorFk` int(10) unsigned DEFAULT NULL, @@ -41377,7 +41453,8 @@ CREATE TABLE `zoneEvent` ( UNIQUE KEY `zoneFk` (`zoneFk`,`type`,`dated`), KEY `zoneEvent_fk_editor` (`editorFk`), CONSTRAINT `zoneEvent_fk_editor` FOREIGN KEY (`editorFk`) REFERENCES `account`.`user` (`id`), - CONSTRAINT `zoneEvent_ibfk_1` FOREIGN KEY (`zoneFk`) REFERENCES `zone` (`id`) ON DELETE CASCADE ON UPDATE CASCADE + CONSTRAINT `zoneEvent_ibfk_1` FOREIGN KEY (`zoneFk`) REFERENCES `zone` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `ck_zoneEvent_priceOptimum` CHECK (`priceOptimum` <= `price`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci; /*!40101 SET character_set_client = @saved_cs_client */; @@ -41611,6 +41688,24 @@ END */ ;; /*!50003 SET character_set_client = @saved_cs_client */ ;; /*!50003 SET character_set_results = @saved_cs_results */ ;; /*!50003 SET collation_connection = @saved_col_connection */ ;; +/*!50106 DROP EVENT IF EXISTS `client_setPackagesDiscountFactor` */;; +DELIMITER ;; +/*!50003 SET @saved_cs_client = @@character_set_client */ ;; +/*!50003 SET @saved_cs_results = @@character_set_results */ ;; +/*!50003 SET @saved_col_connection = @@collation_connection */ ;; +/*!50003 SET character_set_client = utf8mb4 */ ;; +/*!50003 SET character_set_results = utf8mb4 */ ;; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ;; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ;; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ;; +/*!50003 SET @saved_time_zone = @@time_zone */ ;; +/*!50003 SET time_zone = 'SYSTEM' */ ;; +/*!50106 CREATE*/ /*!50117 DEFINER=`vn`@`localhost`*/ /*!50106 EVENT `client_setPackagesDiscountFactor` ON SCHEDULE EVERY 1 DAY STARTS '2024-10-18 03:00:00' ON COMPLETION PRESERVE ENABLE DO CALL client_setPackagesDiscountFactor() */ ;; +/*!50003 SET time_zone = @saved_time_zone */ ;; +/*!50003 SET sql_mode = @saved_sql_mode */ ;; +/*!50003 SET character_set_client = @saved_cs_client */ ;; +/*!50003 SET character_set_results = @saved_cs_results */ ;; +/*!50003 SET collation_connection = @saved_col_connection */ ;; /*!50106 DROP EVENT IF EXISTS `client_unassignSalesPerson` */;; DELIMITER ;; /*!50003 SET @saved_cs_client = @@character_set_client */ ;; @@ -49234,7 +49329,19 @@ BEGIN SELECT tcc.warehouseFK, tcc.itemFk, c2.id, - z.inflation * ROUND(ic.cm3delivery * (IFNULL(zo.price,5000) - IFNULL(zo.bonus,0)) / (1000 * vc.standardFlowerBox) , 4) cost + z.inflation + * ROUND( + ic.cm3delivery + * ( + ( + zo.priceOptimum + (( zo.price - zo.priceOptimum) * 2 * ( 1 - c.packagesDiscountFactor)) + ) + - IFNULL(zo.bonus, 0) + ) + / (1000 * vc.standardFlowerBox), + 4 + ) cost + FROM tmp.ticketComponentCalculate tcc JOIN item i ON i.id = tcc.itemFk JOIN tmp.zoneOption zo ON zo.zoneFk = vZoneFk @@ -49242,6 +49349,7 @@ BEGIN JOIN agencyMode am ON am.id = z.agencyModeFk JOIN vn.volumeConfig vc JOIN vn.component c2 ON c2.code = 'delivery' + JOIN `client` c on c.id = vClientFk LEFT JOIN itemCost ic ON ic.warehouseFk = tcc.warehouseFk AND ic.itemFk = tcc.itemFk HAVING cost <> 0; @@ -50944,6 +51052,41 @@ BEGIN ORDER BY clientFk; +END ;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +/*!50003 DROP PROCEDURE IF EXISTS `client_setPackagesDiscountFactor` */; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +DELIMITER ;; +CREATE DEFINER=`vn`@`localhost` PROCEDURE `client_setPackagesDiscountFactor`() +BEGIN + /** + * Set the discount factor for the packages of the clients. + */ + UPDATE client c + JOIN ( + SELECT t.clientFk, + LEAST(( + SUM(t.packages) / COUNT(DISTINCT DATE(t.shipped)) + ) / cc.packagesOptimum, 1) discountFactor + FROM ticket t + JOIN clientConfig cc ON TRUE + WHERE t.shipped > util.VN_CURDATE() - INTERVAL cc.monthsToCalcOptimumPrice MONTH + AND t.packages + GROUP BY t.clientFk + ) ca ON c.id = ca.clientFk + SET c.packagesDiscountFactor = ca.discountFactor; + END ;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -58737,6 +58880,7 @@ BEGIN DECLARE vMaxShipped DATE; DECLARE vDone BOOL; DECLARE vTicketFk INT; + DECLARE vAddressFk INT; DECLARE vCursor CURSOR FOR SELECT id FROM tmp.ticketToInvoice; @@ -58751,11 +58895,13 @@ BEGIN DATE(vInvoiceDate) >= invoiceOut_getMaxIssued( vSerial, t.companyFk, - YEAR(vInvoiceDate)) + YEAR(vInvoiceDate)), + t.addressFk INTO vClientFk, vCompanyFk, vMaxShipped, - vIsCorrectInvoiceDate + vIsCorrectInvoiceDate, + vAddressFk FROM tmp.ticketToInvoice tt JOIN ticket t ON t.id = tt.id; @@ -58808,7 +58954,9 @@ BEGIN clientFk, dued, companyFk, - siiTypeInvoiceOutFk + siiTypeInvoiceOutFk, + customsAgentFk, + incotermsFk ) SELECT 1, @@ -58821,9 +58969,12 @@ BEGIN vCplusCorrectingInvoiceTypeFk, IF(vSerial = vSimplifiedSerial, vCplusSimplifiedInvoiceTypeFk, - vCplusStandardInvoiceTypeFk)) - FROM client - WHERE id = vClientFk; + vCplusStandardInvoiceTypeFk)), + a.customsAgentFk, + a.incotermsFk + FROM client c + JOIN address a ON a.id = vAddressFk + WHERE c.id = vClientFk; SET vNewInvoiceId = LAST_INSERT_ID(); @@ -67491,14 +67642,14 @@ DELIMITER ; /*!50003 SET character_set_results = @saved_cs_results */ ; /*!50003 SET collation_connection = @saved_col_connection */ ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; -/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +/*!50003 SET sql_mode = 'NO_ENGINE_SUBSTITUTION' */ ; /*!50003 DROP PROCEDURE IF EXISTS `remittance_calc` */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; /*!50003 SET @saved_cs_results = @@character_set_results */ ; /*!50003 SET @saved_col_connection = @@collation_connection */ ; /*!50003 SET character_set_client = utf8mb4 */ ; /*!50003 SET character_set_results = utf8mb4 */ ; -/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +/*!50003 SET collation_connection = utf8mb4_general_ci */ ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `remittance_calc`( vDated DATE @@ -67562,7 +67713,7 @@ BEGIN ) risk ON risk.clientFk = c.id GROUP BY risk.companyFk, c.id - HAVING receipt > 10 + HAVING receipt > 1 ) sub ON sub.id = c.id JOIN supplier s ON s.id = sub.companyFk JOIN company co ON co.id = sub.companyFk @@ -74504,9 +74655,6 @@ BEGIN IFNULL(sat.supplierFk, su.id) supplierFk, t.landed FROM ticket t - JOIN ticketState ts ON ts.ticketFk = t.id - JOIN `state` s ON s.id = ts.stateFk - JOIN alertLevel al ON al.id = s.alertLevel JOIN client c ON c.id = t.clientFk JOIN `address` a ON a.id = t.addressFk JOIN province p ON p.id = a.provinceFk @@ -74523,8 +74671,7 @@ BEGIN LEFT JOIN agency ag ON ag.id = am.agencyFk LEFT JOIN supplierAgencyTerm sat ON sat.agencyFk = ag.id AND wo.isFreelance - WHERE al.code IN ('PACKED', 'DELIVERED') - AND co.code <> 'ES' + WHERE co.code <> 'ES' AND am.name <> 'ABONO' AND w.code = 'ALG' AND t.id = vSelf @@ -81591,26 +81738,27 @@ DELIMITER ; DELIMITER ;; CREATE DEFINER=`vn`@`localhost` PROCEDURE `zone_getAddresses`( vSelf INT, - vShipped DATE, + vLanded DATE, vDepartmentFk INT ) BEGIN /** * Devuelve un listado de todos los clientes activos * con consignatarios a los que se les puede - * vender producto para esa zona. + * entregar producto para esa zona. * * @param vSelf Id de zona - * @param vShipped Fecha de envio - * @param vDepartmentFk Id de departamento + * @param vLanded Fecha de entrega + * @param vDepartmentFk Id de departamento | NULL para mostrar todos * @return Un select */ CALL zone_getPostalCode(vSelf); WITH clientWithTicket AS ( - SELECT clientFk + SELECT DISTINCT clientFk FROM vn.ticket - WHERE shipped BETWEEN vShipped AND util.dayEnd(vShipped) + WHERE landed BETWEEN vLanded AND util.dayEnd(vLanded) + AND NOT isDeleted ) SELECT c.id, c.name, @@ -81620,7 +81768,7 @@ BEGIN u.name username, aai.invoiced, cnb.lastShipped, - cwt.clientFk + IF(cwt.clientFk, TRUE, FALSE) hasTicket FROM vn.client c JOIN vn.worker w ON w.id = c.salesPersonFk JOIN vn.workerDepartment wd ON wd.workerFk = w.id @@ -81640,7 +81788,7 @@ BEGIN AND c.isActive AND ct.code = 'normal' AND bt.code <> 'worker' - AND (d.id = vDepartmentFk OR NOT vDepartmentFk) + AND (d.id = vDepartmentFk OR vDepartmentFk IS NULL) GROUP BY c.id; DROP TEMPORARY TABLE tmp.zoneNodes; @@ -82332,7 +82480,7 @@ BEGIN * @return tmp.zoneOption(zoneFk, hour, travelingDays, price, bonus, specificity) The computed options */ DECLARE vHour TIME DEFAULT TIME(util.VN_NOW()); - + DROP TEMPORARY TABLE IF EXISTS tLandings; CREATE TEMPORARY TABLE tLandings (INDEX (eventFk)) @@ -82353,6 +82501,7 @@ BEGIN TIME(IFNULL(e.`hour`, z.`hour`)) `hour`, l.travelingDays, IFNULL(e.price, z.price) price, + IFNULL(e.priceOptimum, z.priceOptimum) priceOptimum, IFNULL(e.bonus, z.bonus) bonus, l.landed, vShipped shipped @@ -90893,4 +91042,4 @@ USE `vn2008`; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2025-01-14 6:39:04 +-- Dump completed on 2025-01-28 7:08:42 diff --git a/db/dump/.dump/triggers.sql b/db/dump/.dump/triggers.sql index fb72e9899..4f7bab43b 100644 --- a/db/dump/.dump/triggers.sql +++ b/db/dump/.dump/triggers.sql @@ -6804,6 +6804,30 @@ DELIMITER ;; FOR EACH ROW BEGIN SET NEW.editorFk = account.myUser_getId(); + + IF NOT(NEW.`countryFk` <=> OLD.`countryFk`) OR NOT(NEW.`itemFk` <=> OLD.`itemFk`) THEN + CALL util.throw('Only the VAT can be modified'); + END IF; +END */;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +/*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`itemTaxCountry_beforeDelete` + BEFORE DELETE ON `itemTaxCountry` + FOR EACH ROW +BEGIN + CALL util.throw('Records in this table cannot be deleted'); END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -11019,6 +11043,92 @@ DELIMITER ; /*!50003 SET @saved_sql_mode = @@sql_mode */ ; /*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; DELIMITER ;; +/*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`workerMana_beforeInsert` + BEFORE INSERT ON `workerMana` + FOR EACH ROW +BEGIN + IF (SELECT EXISTS(SELECT TRUE FROM workerManaExcluded WHERE workerFk = NEW.workerFk)) THEN + CALL util.throw('Worker is excluded from mana'); + END IF; +END */;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +/*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`workerMana_beforeUpdate` + BEFORE UPDATE ON `workerMana` + FOR EACH ROW +BEGIN + IF (SELECT EXISTS(SELECT TRUE FROM workerManaExcluded WHERE workerFk = NEW.workerFk)) THEN + CALL util.throw('Worker is excluded from mana'); + END IF; +END */;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +/*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`workerManaExcluded_beforeInsert` + BEFORE INSERT ON `workerManaExcluded` + FOR EACH ROW +BEGIN + DELETE FROM workerMana + WHERE workerFk = NEW.workerFk; +END */;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; +/*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`workerManaExcluded_beforeUpdate` + BEFORE UPDATE ON `workerManaExcluded` + FOR EACH ROW +BEGIN + DELETE FROM workerMana + WHERE workerFk = NEW.workerFk; +END */;; +DELIMITER ; +/*!50003 SET sql_mode = @saved_sql_mode */ ; +/*!50003 SET character_set_client = @saved_cs_client */ ; +/*!50003 SET character_set_results = @saved_cs_results */ ; +/*!50003 SET collation_connection = @saved_col_connection */ ; +/*!50003 SET @saved_cs_client = @@character_set_client */ ; +/*!50003 SET @saved_cs_results = @@character_set_results */ ; +/*!50003 SET @saved_col_connection = @@collation_connection */ ; +/*!50003 SET character_set_client = utf8mb4 */ ; +/*!50003 SET character_set_results = utf8mb4 */ ; +/*!50003 SET collation_connection = utf8mb4_unicode_ci */ ; +/*!50003 SET @saved_sql_mode = @@sql_mode */ ; +/*!50003 SET sql_mode = 'IGNORE_SPACE,NO_ENGINE_SUBSTITUTION' */ ; +DELIMITER ;; /*!50003 CREATE*/ /*!50017 DEFINER=`vn`@`localhost`*/ /*!50003 TRIGGER `vn`.`workerTimeControl_beforeInsert` BEFORE INSERT ON `workerTimeControl` FOR EACH ROW @@ -11085,11 +11195,13 @@ DELIMITER ;; AFTER DELETE ON `workerTimeControl` FOR EACH ROW BEGIN - INSERT INTO workerLog - SET `action` = 'delete', - `changedModel` = 'WorkerTimeControl', - `changedModelId` = OLD.id, - `userFk` = account.myUser_getId(); + IF account.myUser_getId() IS NOT NULL THEN + INSERT INTO workerLog + SET `action` = 'delete', + `changedModel` = 'WorkerTimeControl', + `changedModelId` = OLD.id, + `userFk` = account.myUser_getId(); + END IF; END */;; DELIMITER ; /*!50003 SET sql_mode = @saved_sql_mode */ ; @@ -11499,4 +11611,4 @@ USE `vn2008`; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; --- Dump completed on 2025-01-14 6:39:25 +-- Dump completed on 2025-01-28 7:09:01 diff --git a/db/dump/fixtures.before.sql b/db/dump/fixtures.before.sql index 590fe34b6..df18fbb43 100644 --- a/db/dump/fixtures.before.sql +++ b/db/dump/fixtures.before.sql @@ -321,6 +321,11 @@ UPDATE `vn`.`agencyMode` SET `web` = 1, `reportMail` = 'no-reply@gothamcity.com' UPDATE `vn`.`agencyMode` SET `code` = 'refund' WHERE `id` = 23; +INSERT INTO `vn`.`agencyIncoming`(`agencyModeFk`) + VALUES + (1), + (2); + INSERT INTO `vn`.`payMethod`(`id`,`code`, `name`, `graceDays`, `outstandingDebt`, `isIbanRequiredForClients`, `isIbanRequiredForSuppliers`, `hasVerified`) VALUES (1, NULL, 'PayMethod one', 0, 001, 0, 0, 0), @@ -745,15 +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', 56, 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()); + (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 @@ -1085,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'), @@ -1101,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 @@ -1940,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 @@ -2634,9 +2639,9 @@ REPLACE INTO `vn`.`invoiceIn`(`id`, `serialNumber`,`serial`, `supplierFk`, `issu (9, 1009, 'R', 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1242, 0, 442, 1,util.VN_CURDATE()), (10, 1010, 'R', 2, DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH), 1243, 0, 442, 1,util.VN_CURDATE()); -INSERT INTO `vn`.`invoiceInConfig` (`id`, `retentionRate`, `retentionName`, `sageFarmerWithholdingFk`, `daysAgo`) +INSERT INTO `vn`.`invoiceInConfig` (`id`, `retentionRate`, `retentionName`, `sageFarmerWithholdingFk`, `daysAgo`, `balanceStartingDate`) VALUES - (1, -2, '2% retention', 2, 45); + (1, -2, '2% retention', 2, 45, '2000-01-01'); INSERT INTO `vn`.`invoiceInDueDay`(`invoiceInFk`, `dueDated`, `bankFk`, `amount`) VALUES @@ -2749,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), @@ -2919,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`) @@ -2933,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`) @@ -3200,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 @@ -4045,6 +4052,9 @@ INSERT IGNORE INTO vn.saySimpleConfig (url, defaultChannel) INSERT INTO vn.workerIrpf (workerFk,spouseNif, geographicMobilityDate) VALUES (1106,'26493101E','2019-09-20'); +INSERT INTO vn.payment (received, supplierFk, amount, currencyFk, divisa, bankFk, payMethodFk, bankingFees, concept, companyFk, created, isConciliated, dueDated, workerFk) VALUES + (util.VN_CURDATE(), 1, 1000.00, 1, NULL, 1, 1, 0.0, 'n/pago', 442, util.VN_CURDATE(), 1, util.VN_CURDATE(), 9); + INSERT INTO vn.referenceRate (currencyFk, dated, value) VALUES (2, '2000-12-01', 1.0495), (2, '2001-01-01', 1.0531), @@ -4056,3 +4066,8 @@ INSERT IGNORE INTO vn.osrmConfig (id,url,tolerance) INSERT IGNORE INTO vn.inventoryConfig SET id = 1, supplierFk = 4; + +UPDATE vn.worker + SET isFreelance=1 + WHERE firstName='deliveryFreelancer'; + diff --git a/db/routines/bs/procedures/inventoryDiscrepancyDetail_replace.sql b/db/routines/bs/procedures/inventoryDiscrepancyDetail_replace.sql index b698f0e3e..6894b2928 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/bs/procedures/ventas_contables_add.sql b/db/routines/bs/procedures/ventas_contables_add.sql index 72b0c0fee..c82cb96d9 100644 --- a/db/routines/bs/procedures/ventas_contables_add.sql +++ b/db/routines/bs/procedures/ventas_contables_add.sql @@ -15,7 +15,7 @@ BEGIN DELETE FROM bs.ventas_contables WHERE year = vYear - AND month = vMonth; + AND month = vMonth; DROP TEMPORARY TABLE IF EXISTS tmp.ticket_list; CREATE TEMPORARY TABLE tmp.ticket_list diff --git a/db/routines/cache/procedures/available_refresh.sql b/db/routines/cache/procedures/available_refresh.sql index 87c003648..0e42a62cd 100644 --- a/db/routines/cache/procedures/available_refresh.sql +++ b/db/routines/cache/procedures/available_refresh.sql @@ -3,7 +3,7 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `cache`.`available_refres OUT `vCalc` INT, `vRefresh` INT, `vWarehouse` INT, - `vDated` DATE + `vAvailabled` DATETIME ) proc: BEGIN DECLARE vStartDate DATE; @@ -12,6 +12,7 @@ proc: BEGIN DECLARE vInventoryDate DATE; DECLARE vLifeScope DATE; DECLARE vWarehouseFkInventory INT; + DECLARE vDated DATE; DECLARE EXIT HANDLER FOR SQLEXCEPTION BEGIN @@ -19,13 +20,17 @@ proc: BEGIN RESIGNAL; END; - IF vDated < util.VN_CURDATE() THEN + IF vAvailabled < util.VN_CURDATE() THEN LEAVE proc; END IF; + SET vDated = DATE(vAvailabled); + + SET vAvailabled = vDated + INTERVAL HOUR(vAvailabled) HOUR; + CALL vn.item_getStock(vWarehouse, vDated, NULL); - SET vParams = CONCAT_WS('/', vWarehouse, vDated); + SET vParams = CONCAT_WS('/', vWarehouse, vAvailabled); CALL cache_calc_start (vCalc, vRefresh, 'available', vParams); IF !vRefresh THEN @@ -87,11 +92,10 @@ proc: BEGIN SELECT i.itemFk, i.landed, i.quantity FROM vn.itemEntryIn i JOIN itemRange ir ON ir.itemFk = i.itemFk - LEFT JOIN edi.warehouseFloramondo wf ON wf.entryFk = i.entryFk WHERE i.landed >= vStartDate + AND IFNULL(i.availabled, i.landed) <= vAvailabled AND (ir.ended IS NULL OR i.landed <= ir.ended) AND i.warehouseInFk = vWarehouse - AND ISNULL(wf.entryFk) UNION ALL SELECT i.itemFk, i.shipped, i.quantity FROM vn.itemEntryOut i diff --git a/db/routines/sage/procedures/accountingMovements_add.sql b/db/routines/sage/procedures/accountingMovements_add.sql index 8c129beb2..060d89a3f 100644 --- a/db/routines/sage/procedures/accountingMovements_add.sql +++ b/db/routines/sage/procedures/accountingMovements_add.sql @@ -1,11 +1,11 @@ DELIMITER $$ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `sage`.`accountingMovements_add`( - vYear INT, + vYear INT, vCompanyFk INT ) BEGIN /** - * Traslada la info de contabilidad generada en base a vn.XDiario a la tabla sage.movConta + * Traslada la info de contabilidad generada en base a vn.XDiario a la tabla sage.movConta * para poder ejecutar posteriormente el proceso de importación de datos de SQL Server * Solo traladará los asientos marcados con el campo vn.XDiario.enlazadoSage = FALSE * @vYear Año contable del que se quiere trasladar la información @@ -23,6 +23,7 @@ BEGIN DECLARE vInvoiceTypeInformativeCode VARCHAR(1); DECLARE vCountryCanariasCode, vCountryCeutaMelillaCode VARCHAR(2); DECLARE vCompanyCode INT; + DECLARE vHasErrorTax BOOL DEFAULT FALSE; SELECT SiglaNacion INTO vCountryCanariasCode FROM Naciones @@ -44,12 +45,12 @@ BEGIN FROM taxType WHERE code = 'import4'; - SELECT shipmentTransactionTypeFk, - definitiveExportTransactionTypeFk, + SELECT shipmentTransactionTypeFk, + definitiveExportTransactionTypeFk, pendingServiceTransactionTypeFk, company_getCode(vCompanyFk) INTO vTransactionExportTaxFreeFk, - vTransactionExportFk, + vTransactionExportFk, vDuaTransactionFk, vCompanyCode FROM config; @@ -66,6 +67,24 @@ BEGIN WHERE enlazadoSage = FALSE AND Asiento <> 1 ; + SELECT EXISTS ( + SELECT TRUE + FROM vn.XDiario x + JOIN vn.invoiceIn ii ON ii.id = x.CLAVE + JOIN vn.invoiceInTax it ON it.invoiceInFk = ii.id + LEFT JOIN TiposIva ti ON ti.CodigoIva = it.taxTypeSageFk + LEFT JOIN taxType tt ON tt.id = it.taxTypeSageFk + WHERE x.FECHA BETWEEN vDatedFrom AND vDatedTo + AND NOT x.enlazadoSage + AND x.empresa_id = vCompanyFk + AND it.taxTypeSageFk + AND (ti.CodigoIva IS NULL OR tt.id IS NULL) + ) INTO vHasErrorTax; + + IF vHasErrorTax tHEN + CALL util.throw ('Error in tables for received invoices tax'); + END IF; + CALL invoiceOut_manager(vYear, vCompanyFk); CALL invoiceIn_manager(vYear, vCompanyFk); @@ -306,8 +325,8 @@ BEGIN mci.FechaFacturaOriginal = x.FECHA_EX, mci.SuFacturaNo = x.FACTURAEX, mci.FechaOperacion = x.FECHA_OP, - mci.ImporteFactura = mci.ImporteFactura + - x.BASEEURO + + mci.ImporteFactura = mci.ImporteFactura + + x.BASEEURO + CAST((x.IVA / 100) * x.BASEEURO AS DECIMAL(10, 2)) WHERE pm.description = 'HP Iva pendiente' AND mci.enlazadoSage = FALSE @@ -326,7 +345,7 @@ BEGIN mci.CodigoIva2 = vTaxImportFk, mci.IvaDeducible2 = TRUE, mci.ImporteFactura = mci.ImporteFactura + - x.BASEEURO + + x.BASEEURO + CAST((x.IVA / 100) * x.BASEEURO AS DECIMAL(10, 2)) WHERE pm.description = 'HP Iva pendiente' AND mci.enlazadoSage = FALSE @@ -344,8 +363,8 @@ BEGIN mci.CodigoTransaccion3 = vDuaTransactionFk , mci.CodigoIva3 = vTaxImportSuperReducedFk, mci.IvaDeducible3 = TRUE, - mci.ImporteFactura = mci.ImporteFactura + - x.BASEEURO + + mci.ImporteFactura = mci.ImporteFactura + + x.BASEEURO + CAST((x.IVA / 100) * x.BASEEURO AS DECIMAL(10, 2)) WHERE pm.description = 'HP Iva pendiente' AND mci.enlazadoSage = FALSE @@ -379,14 +398,14 @@ BEGIN OR CodigoTransaccion2 = vTransactionExportFk OR CodigoTransaccion3 = vTransactionExportFk OR CodigoTransaccion4 = vTransactionExportFk) - AND SiglaNacion IN (vCountryCanariasCode COLLATE utf8mb3_unicode_ci, + AND SiglaNacion IN (vCountryCanariasCode COLLATE utf8mb3_unicode_ci, vCountryCeutaMelillaCode COLLATE utf8mb3_unicode_ci); UPDATE movConta mc SET CodigoDivisa = 'USD', FactorCambio = TRUE, - ImporteCambio = ABS( CAST( IF( ImporteDivisa <> 0 AND ImporteCambio = 0, - ImporteAsiento / ImporteDivisa, + ImporteCambio = ABS( CAST( IF( ImporteDivisa <> 0 AND ImporteCambio = 0, + ImporteAsiento / ImporteDivisa, ImporteCambio) AS DECIMAL( 10, 2))) WHERE enlazadoSage = FALSE AND (ImporteCambio <> 0 OR ImporteDivisa <> 0 OR FactorCambio); @@ -403,20 +422,20 @@ BEGIN WITH client AS( SELECT DISTINCT c.id FROM sage.movConta mc - JOIN vn.client c ON c.accountingAccount = mc.CodigoCuenta - WHERE NOT enlazadoSage - ),supplier AS( + JOIN vn.client c ON c.accountingAccount = mc.CodigoCuenta + WHERE NOT enlazadoSage + ),supplier AS( SELECT DISTINCT s.id FROM sage.movConta mc - JOIN vn.supplier s ON s.account = mc.CodigoCuenta - WHERE NOT enlazadoSage + JOIN vn.supplier s ON s.account = mc.CodigoCuenta + WHERE NOT enlazadoSage ),clientSupplierSync AS( SELECT idClientSupplier, `type` - FROM sage.clientSupplier cs - WHERE isSync + FROM sage.clientSupplier cs + WHERE isSync ) SELECT idClientSupplier, `type` - FROM sage.clientSupplier cs + FROM sage.clientSupplier cs WHERE NOT isSync UNION SELECT id, 'C' @@ -424,7 +443,7 @@ BEGIN LEFT JOIN clientSupplierSync cs ON cs.idClientSupplier = c.id AND cs.Type ='C' WHERE cs.idClientSupplier IS NULL - UNION + UNION SELECT id, 'P' FROM supplier s LEFT JOIN clientSupplierSync cs ON cs.idClientSupplier = s.id @@ -436,7 +455,7 @@ BEGIN INSERT IGNORE INTO sage.clientSupplier (companyFk, `type`, idClientSupplier, isSync) SELECT vCompanyCode, `type`, idClientSupplier, FALSE FROM tmp.clientSupplier; - + DROP TEMPORARY TABLE tmp.clientSupplier; CALL pgc_add(vCompanyFk); diff --git a/db/routines/vn/functions/getTimeBetweenRoadmapAddresses.sql b/db/routines/vn/functions/getTimeBetweenRoadmapAddresses.sql new file mode 100644 index 000000000..354aeb835 --- /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_clone.sql b/db/routines/vn/procedures/entry_clone.sql index a0ed39c29..511ff4837 100644 --- a/db/routines/vn/procedures/entry_clone.sql +++ b/db/routines/vn/procedures/entry_clone.sql @@ -1,20 +1,31 @@ DELIMITER $$ -CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`entry_clone`(vSelf INT) +CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`entry_clone`( + vSelf INT, + OUT vOutputEntryFk INT +) BEGIN /** * clones an entry. * * @param vSelf The entry id + * @param vOutputEntryFk The new entry id */ DECLARE vNewEntryFk INT; - START TRANSACTION; + DECLARE vIsRequiredTx BOOL DEFAULT NOT @@in_transaction; + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + CALL util.tx_rollback(vIsRequiredTx); + RESIGNAL; + END; + + CALL util.tx_start(vIsRequiredTx); CALL entry_cloneHeader(vSelf, vNewEntryFk, NULL); CALL entry_copyBuys(vSelf, vNewEntryFk); - COMMIT; + CALL util.tx_commit(vIsRequiredTx); + SET vOutputEntryFk = vNewEntryFk; - SELECT vNewEntryFk; END$$ DELIMITER ; diff --git a/db/routines/vn/procedures/entry_splitByShelving.sql b/db/routines/vn/procedures/entry_splitByShelving.sql index f5de36098..019abe6cb 100644 --- a/db/routines/vn/procedures/entry_splitByShelving.sql +++ b/db/routines/vn/procedures/entry_splitByShelving.sql @@ -39,14 +39,14 @@ BEGIN read_loop: LOOP SET vDone = FALSE; - + FETCH cur INTO vBuyFk, vIshStickers, vBuyStickers; IF vDone THEN LEAVE read_loop; END IF; - IF vIshStickers = vBuyStickers THEN + IF vIshStickers = vBuyStickers THEN UPDATE buy SET entryFk = vToEntryFk WHERE id = vBuyFk; diff --git a/db/routines/vn/procedures/entry_transfer.sql b/db/routines/vn/procedures/entry_transfer.sql new file mode 100644 index 000000000..c02365092 --- /dev/null +++ b/db/routines/vn/procedures/entry_transfer.sql @@ -0,0 +1,158 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`entry_transfer`( + vOriginalEntry INT, + OUT vNewEntryFk INT + ) +BEGIN +/** + * Adelanta a mañana la mercancia de una entrada a partir de lo que hay ubicado en el almacén + * + * @param vOriginalEntry entrada que se quiera adelantar + * @param vNewEntry nueva entrada creada + */ + DECLARE vTravelFk INT; + DECLARE vWarehouseFk INT; + DECLARE vWarehouseInFk INT; + DECLARE vWarehouseOutFk INT; + DECLARE vRef INT; + DECLARE vIsReceived INT; + DECLARE vAgencyModeFk INT; + DECLARE vTomorrow DATETIME DEFAULT util.tomorrow(); + DECLARE vCurDate DATE DEFAULT util.VN_CURDATE(); + + DECLARE vIsRequiredTx BOOL DEFAULT NOT @@in_transaction; + DECLARE EXIT HANDLER FOR SQLEXCEPTION + BEGIN + CALL util.tx_rollback(vIsRequiredTx); + RESIGNAL; + END; + + -- Clonar la entrada + CALL entry_clone(vOriginalEntry, vNewEntryFk); + + CALL util.tx_start(vIsRequiredTx); + + /* Hay que crear un nuevo travel, con salida hoy y llegada mañana y + asignar la entrada nueva al nuevo travel.*/ + SELECT t.warehouseInFk, t.warehouseOutFk, t.`ref`, t.isReceived, t.agencyModeFk + INTO vWarehouseInFk, vWarehouseOutFk, vRef, vIsReceived, vAgencyModeFk + FROM travel t + JOIN entry e ON e.travelFk = t.id + WHERE e.id = vOriginalEntry; + + SELECT id INTO vTravelFk + FROM travel t + WHERE shipped = vCurDate + AND landed = vTomorrow + AND warehouseInFk = vWarehouseInFk + AND warehouseOutFk = vWarehouseOutFk + AND `ref` = vRef + AND isReceived =vIsReceived + AND agencyModeFk = vAgencyModeFk; + + IF vTravelFk IS NULL THEN + INSERT INTO travel( + shipped, + landed, + warehouseInFk, + warehouseOutFk, + `ref`, + isReceived, + agencyModeFk) + SELECT vCurDate, + vTomorrow, + t.warehouseInFk, + t.warehouseOutFk, + t.`ref`, + t.isReceived, + t.agencyModeFk + FROM travel t + JOIN entry e ON e.travelFk = t.id + WHERE e.id = vOriginalEntry; + + SET vTravelFk = LAST_INSERT_ID(); + END IF; + + UPDATE entry + SET travelFk = vTravelFk, + evaNotes = vOriginalEntry + WHERE id = vNewEntryFk; + + -- Poner a 0 las cantidades + UPDATE buy b + SET b.quantity = 0, b.stickers = 0 + WHERE b.entryFk = vNewEntryFk; + + -- Eliminar duplicados + DELETE b + FROM buy b + LEFT JOIN (SELECT b.id, b.itemFk + FROM buy b + WHERE b.entryFk = vNewEntryFk + GROUP BY b.itemFk) tBuy ON tBuy.id = b.id + WHERE b.entryFk = vNewEntryFk + AND tBuy.id IS NULL; + + SELECT t.warehouseInFk INTO vWarehouseFk + FROM travel t + JOIN entry e ON e.travelFk = t.id + WHERE e.id = vOriginalEntry; + + /* Actualizar nueva entrada con lo que no está ubicado HOY, + descontando lo vendido HOY de esas ubicaciones*/ + CREATE OR REPLACE TEMPORARY TABLE buys + WITH tBuy AS ( + SELECT b.itemFk, SUM(b.quantity) totalQuantity + FROM vn.buy b + WHERE b.entryFk = vOriginalEntry + GROUP BY b.itemFk + ), + itemShelvings AS ( + SELECT ish.itemFk, SUM(ish.visible) visible + FROM vn.itemShelving ish + JOIN vn.shelving sh ON sh.id = ish.shelvingFk + JOIN vn.parking p ON p.id = sh.parkingFk + JOIN vn.sector s ON s.id = p.sectorFk + JOIN vn.buy b ON b.id = ish.buyFk + JOIN vn.entry e ON e.id = b.entryFk + JOIN tBuy t ON t.itemFk = ish.itemFk + WHERE s.warehouseFk = vWarehouseFk + AND sh.parked >= vCurDate + GROUP BY ish.itemFk + ), + sales AS ( + SELECT s.itemFk, SUM(s.quantity) sold + FROM vn.ticket t + JOIN vn.sale s ON s.ticketFk = t.id + JOIN vn.itemShelvingSale iss ON iss.saleFk = s.id + JOIN vn.itemShelving is2 ON is2.id = iss.itemShelvingFk + JOIN vn.shelving s2 ON s2.id = is2.shelvingFk + JOIN tBuy t ON t.itemFk = s.itemFk + WHERE t.shipped BETWEEN vCurDate AND util.dayend(vCurDate) + AND s2.parked >= vCurDate + GROUP BY s.itemFk + ) + SELECT tmp.itemFk, + IFNULL(iss.visible, 0) visible, + tmp.totalQuantity, + IFNULL(s.sold, 0) sold + FROM tBuy tmp + LEFT JOIN itemShelvings iss ON tmp.itemFk = iss.itemFk + LEFT JOIN sales s ON s.itemFk = tmp.itemFk + WHERE visible < tmp.totalQuantity + OR iss.itemFk IS NULL; + + UPDATE buy b + JOIN buys tmp ON tmp.itemFk = b.itemFk + SET b.quantity = tmp.totalQuantity - tmp.visible - tmp.sold + WHERE b.entryFk = vNewEntryFk; + + -- Limpia la nueva entrada + DELETE FROM buy WHERE entryFk = vNewEntryFk AND quantity = 0; + + CALL util.tx_commit(vIsRequiredTx); + + CALL cache.visible_refresh(@c,TRUE,vWarehouseFk); + CALL cache.available_refresh(@c, TRUE, vWarehouseFk, vCurDate); +END$$ +DELIMITER ; diff --git a/db/routines/vn/procedures/itemShelvingRadar.sql b/db/routines/vn/procedures/itemShelvingRadar.sql deleted file mode 100644 index 4bdd0873e..000000000 --- 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 9ae96c7a8..b2179f4f8 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/item_getStock.sql b/db/routines/vn/procedures/item_getStock.sql index 8c0eea251..cd5bc4bdc 100644 --- a/db/routines/vn/procedures/item_getStock.sql +++ b/db/routines/vn/procedures/item_getStock.sql @@ -15,8 +15,6 @@ BEGIN * * @return tmp.itemList(itemFk, stock, visible, available) */ - DECLARE vIsLogifloraDay BOOL DEFAULT vn.isLogifloraDay(vDated, vWarehouseFk); - SET vDated = TIMESTAMP(vDated, '00:00:00'); CREATE OR REPLACE TEMPORARY TABLE tmp.itemList @@ -36,14 +34,11 @@ BEGIN UNION ALL SELECT iei.itemFk, iei.quantity FROM itemEntryIn iei - LEFT JOIN edi.warehouseFloramondo wf ON wf.entryFk = iei.entryFk JOIN item i ON i.id = iei.itemFk WHERE iei.landed >= util.VN_CURDATE() AND iei.landed < vDated AND iei.warehouseInFk = vWarehouseFk AND (vItemFk IS NULL OR iei.itemFk = vItemFk) - AND (wf.entryFk IS NULL OR vIsLogifloraDay) - AND NOT (iei.landed > util.VN_CURDATE() AND i.isFloramondo) UNION ALL SELECT ieo.itemFk, ieo.quantity FROM itemEntryOut ieo @@ -52,7 +47,6 @@ BEGIN AND ieo.shipped < vDated AND ieo.warehouseOutFk = vWarehouseFk AND (vItemFk IS NULL OR ieo.itemFk = vItemFk) - AND NOT (ieo.shipped > util.VN_CURDATE() AND i.isFloramondo) ) sub GROUP BY itemFk HAVING stock; diff --git a/db/routines/vn/procedures/prepareTicketList.sql b/db/routines/vn/procedures/prepareTicketList.sql index 7c44bb994..cfe9492ee 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 813c65ab2..605c06dba 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 000000000..8c3803947 --- /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 e016f3ab4..ca81660b8 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 ff419989d..fdfd5c8bc 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/supplier_statementWithEntries.sql b/db/routines/vn/procedures/supplier_statementWithEntries.sql index c0014f8e5..ad80e2c9f 100644 --- a/db/routines/vn/procedures/supplier_statementWithEntries.sql +++ b/db/routines/vn/procedures/supplier_statementWithEntries.sql @@ -41,6 +41,7 @@ BEGIN ) currencyBalance FROM ( SELECT NULL bankFk, + NULL bank, ii.companyFk, ii.serial, ii.id, @@ -74,6 +75,7 @@ BEGIN GROUP BY iid.id, ii.id UNION ALL SELECT p.bankFk, + a.bank, p.companyFk, NULL, p.id, @@ -109,6 +111,7 @@ BEGIN AND (vIsConciliated = p.isConciliated OR NOT vIsConciliated) UNION ALL SELECT NULL, + NULL bankFk, companyFk, NULL, se.id, @@ -136,6 +139,7 @@ BEGIN AND (vIsConciliated = se.isConciliated OR NOT vIsConciliated) UNION ALL SELECT NULL bankFk, + NULL, e.companyFk, 'E' serial, e.invoiceNumber id, @@ -154,7 +158,7 @@ BEGIN JOIN travel tr ON tr.id = e.travelFk JOIN currency c ON c.id = e.currencyFk WHERE e.supplierFk = vSupplierFk - AND tr.landed >= CURDATE() + AND tr.landed >= util.VN_CURDATE() AND e.invoiceInFk IS NULL AND vHasEntries ORDER BY (dated IS NULL AND NOT isBooked), diff --git a/db/routines/vn/procedures/ticket_DelayTruck.sql b/db/routines/vn/procedures/ticket_DelayTruck.sql deleted file mode 100644 index ebd0e5baf..000000000 --- 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 3d22207f3..000000000 --- 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 ce90551db..d0737f00f 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_doCmr.sql b/db/routines/vn/procedures/ticket_doCmr.sql index ba64944f8..59bb3e070 100644 --- a/db/routines/vn/procedures/ticket_doCmr.sql +++ b/db/routines/vn/procedures/ticket_doCmr.sql @@ -21,9 +21,6 @@ BEGIN IFNULL(sat.supplierFk, su.id) supplierFk, t.landed FROM ticket t - JOIN ticketState ts ON ts.ticketFk = t.id - JOIN `state` s ON s.id = ts.stateFk - JOIN alertLevel al ON al.id = s.alertLevel JOIN client c ON c.id = t.clientFk JOIN `address` a ON a.id = t.addressFk JOIN province p ON p.id = a.provinceFk @@ -40,8 +37,7 @@ BEGIN LEFT JOIN agency ag ON ag.id = am.agencyFk LEFT JOIN supplierAgencyTerm sat ON sat.agencyFk = ag.id AND wo.isFreelance - WHERE al.code IN ('PACKED', 'DELIVERED') - AND co.code <> 'ES' + WHERE co.code <> 'ES' AND am.name <> 'ABONO' AND w.code = 'ALG' AND t.id = vSelf diff --git a/db/routines/vn/procedures/ticket_getProblems.sql b/db/routines/vn/procedures/ticket_getProblems.sql index 1851bce47..a65413f5f 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 cbbcbec63..b7444cac8 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 24246329b..c67d44f6f 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 000000000..f0faeb8be --- /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 d71942fea..012702f3e 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 c3cbf2597..c3142c8ac 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 000000000..7fcc31d92 --- /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 2f9481140..4dd9e686c 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 a2a02e96a..4f355915b 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/travel_beforeInsert.sql b/db/routines/vn/triggers/travel_beforeInsert.sql index 5356ed537..2cae96cd9 100644 --- a/db/routines/vn/triggers/travel_beforeInsert.sql +++ b/db/routines/vn/triggers/travel_beforeInsert.sql @@ -16,5 +16,9 @@ BEGIN IF NEW.awbFk IS NOT NULL THEN CALL travel_throwAwb(NEW.id); END IF; + + IF NEW.availabled < NEW.landed THEN + CALL util.throw('The travel availabled cannot be earlier than landed'); + END IF; END$$ DELIMITER ; diff --git a/db/routines/vn/triggers/travel_beforeUpdate.sql b/db/routines/vn/triggers/travel_beforeUpdate.sql index 5a27b43b4..093dee082 100644 --- a/db/routines/vn/triggers/travel_beforeUpdate.sql +++ b/db/routines/vn/triggers/travel_beforeUpdate.sql @@ -40,5 +40,9 @@ BEGIN IF (NOT(NEW.awbFk <=> OLD.awbFk)) AND NEW.awbFk IS NOT NULL THEN CALL travel_throwAwb(NEW.id); END IF; + + IF NEW.availabled < NEW.landed THEN + CALL util.throw('The travel availabled cannot be earlier than landed'); + END IF; END$$ DELIMITER ; diff --git a/db/routines/vn/triggers/zoneIncluded_afterDelete.sql b/db/routines/vn/triggers/zoneIncluded_afterDelete.sql index 2990626ca..d3caedb13 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/vn/views/agencyModeIncoming.sql b/db/routines/vn/views/agencyModeIncoming.sql new file mode 100644 index 000000000..f7f6e595d --- /dev/null +++ b/db/routines/vn/views/agencyModeIncoming.sql @@ -0,0 +1,9 @@ +CREATE OR REPLACE DEFINER=`vn`@`localhost` +SQL SECURITY DEFINER +VIEW `vn`.`agencyModeIncoming` AS + SELECT + am.id, + am.name + FROM `vn`.`agencyMode` AS am + JOIN `vn`.`agencyIncoming` AS ai + ON am.id = ai.agencyModeFk; diff --git a/db/routines/vn/views/itemEntryIn.sql b/db/routines/vn/views/itemEntryIn.sql index 60af585f2..5be558a43 100644 --- a/db/routines/vn/views/itemEntryIn.sql +++ b/db/routines/vn/views/itemEntryIn.sql @@ -7,7 +7,8 @@ AS SELECT `t`.`warehouseInFk` AS `warehouseInFk`, `b`.`quantity` AS `quantity`, `t`.`isReceived` AS `isReceived`, `t`.`isRaid` AS `isVirtualStock`, - `e`.`id` AS `entryFk` + `e`.`id` AS `entryFk`, + `t`.`availabled` FROM ( ( `vn`.`buy` `b` diff --git a/db/routines/vn2008/views/Cubos.sql b/db/routines/vn2008/views/Cubos.sql index 1b23af4fc..7ca82e66e 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 010596288..a32571888 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 000000000..75fdc0c56 --- /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 000000000..c49ad71ed --- /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/11269-wheatBirch/00-firstScript.sql b/db/versions/11269-wheatBirch/00-firstScript.sql index 9432d131b..9552fe6cd 100644 --- a/db/versions/11269-wheatBirch/00-firstScript.sql +++ b/db/versions/11269-wheatBirch/00-firstScript.sql @@ -7,9 +7,9 @@ ALTER TABLE vn.invoiceOut ADD CONSTRAINT invoiceOut_customsAgentFk FOREIGN KEY ( ALTER TABLE vn.invoiceOut ADD CONSTRAINT invoiceOut_incotermsFk FOREIGN KEY (incotermsFk) REFERENCES vn.incoterms (`code`) ON DELETE RESTRICT ON UPDATE CASCADE; -UPDATE vn.invoiceOut io - JOIN vn.client c ON c.id = io.clientFk - JOIN vn.ticket t ON t.clientFk = c.id - JOIN vn.address a ON a.id = t.addressFk - SET io.customsAgentFk = a.customsAgentFk, - io.incotermsFk = a.incotermsFk; \ No newline at end of file +-- UPDATE vn.invoiceOut io +-- JOIN vn.client c ON c.id = io.clientFk +-- JOIN vn.ticket t ON t.clientFk = c.id +-- JOIN vn.address a ON a.id = t.addressFk +-- SET io.customsAgentFk = a.customsAgentFk, +-- io.incotermsFk = a.incotermsFk; diff --git a/db/versions/11306-greenMonstera/00-firstScript.sql b/db/versions/11306-greenMonstera/00-firstScript.sql new file mode 100644 index 000000000..c9edc6bfb --- /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 000000000..5eb107694 --- /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/11383-maroonChico/00-town.sql b/db/versions/11383-maroonChico/00-town.sql new file mode 100644 index 000000000..8fdd8c7b0 --- /dev/null +++ b/db/versions/11383-maroonChico/00-town.sql @@ -0,0 +1,10 @@ +UPDATE vn.town t + LEFT JOIN vn.zoneGeo zg ON zg.id = t.geoFk + SET t.geoFk = NULL + WHERE zg.id IS NULL; + +ALTER TABLE vn.town + ADD CONSTRAINT town_zoneGeo_FK FOREIGN KEY (geoFk) + REFERENCES vn.zoneGeo(id) + ON DELETE RESTRICT + ON UPDATE CASCADE; diff --git a/db/versions/11383-maroonChico/01-postCode.sql b/db/versions/11383-maroonChico/01-postCode.sql new file mode 100644 index 000000000..668cf69cb --- /dev/null +++ b/db/versions/11383-maroonChico/01-postCode.sql @@ -0,0 +1,10 @@ +UPDATE vn.postCode pc + LEFT JOIN vn.zoneGeo zg ON zg.id = pc.geoFk + SET pc.geoFk = NULL + WHERE zg.id IS NULL; + +ALTER TABLE vn.postCode + ADD CONSTRAINT postCode_zoneGeo_FK FOREIGN KEY (geoFk) + REFERENCES vn.zoneGeo(id) + ON DELETE RESTRICT + ON UPDATE CASCADE; diff --git a/db/versions/11383-maroonChico/02-province.sql b/db/versions/11383-maroonChico/02-province.sql new file mode 100644 index 000000000..c16d33cd8 --- /dev/null +++ b/db/versions/11383-maroonChico/02-province.sql @@ -0,0 +1,10 @@ +UPDATE vn.province p + LEFT JOIN vn.zoneGeo zg ON zg.id = p.geoFk + SET p.geoFk = NULL + WHERE zg.id IS NULL; + +ALTER TABLE vn.province + ADD CONSTRAINT province_zoneGeo_FK FOREIGN KEY (geoFk) + REFERENCES vn.zoneGeo(id) + ON DELETE RESTRICT + ON UPDATE CASCADE; diff --git a/db/versions/11393-redCamellia/00-firstScript.sql b/db/versions/11393-redCamellia/00-firstScript.sql new file mode 100644 index 000000000..19ea2a9ef --- /dev/null +++ b/db/versions/11393-redCamellia/00-firstScript.sql @@ -0,0 +1,19 @@ +INSERT INTO account.`role` (name,description,hasLogin) + VALUES ('deliveryFreelancer','Repartidor autónomo',1); + +INSERT INTO salix.ACL (model, property, accessType, permission, principalType, principalId) + VALUES + ('Route', 'getTickets', 'READ', 'ALLOW', 'ROLE', 'deliveryFreelancer'), + ('AgencyTerm', 'filter', 'READ', 'ALLOW', 'ROLE', 'deliveryFreelancer'), + ('Route', 'summary', 'READ', 'ALLOW', 'ROLE', 'deliveryFreelancer'), + ('Route', 'getRouteByAgency', 'WRITE', 'ALLOW', 'ROLE', 'deliveryFreelancer'), + ('Route','filter','READ','ALLOW','ROLE','deliveryFreelancer'), + ('UserConfig','getUserConfig','*','ALLOW','ROLE','deliveryFreelancer'), + ('Route', 'getTickets', 'READ', 'ALLOW', 'ROLE', 'deliveryFreelancer'), + ('Route','guessPriority','WRITE','ALLOW','ROLE','deliveryFreelancer'), + ('Route','getDeliveryPoint','READ','ALLOW','ROLE','deliveryFreelancer'), + ('Route', 'findById', 'READ', 'ALLOW', 'ROLE', 'deliveryFreelancer'), + ('Route','sendSms','WRITE','ALLOW','ROLE','deliveryFreelancer'), + ('Ticket','updateAttributes','WRITE','ALLOW','ROLE','deliveryFreelancer'), + ('Client','findById','READ','ALLOW','ROLE','deliveryFreelancer'); +; diff --git a/db/versions/11411-turquoiseEucalyptus/00-agencyIncomingForeign.sql b/db/versions/11411-turquoiseEucalyptus/00-agencyIncomingForeign.sql new file mode 100644 index 000000000..d2c46e9ca --- /dev/null +++ b/db/versions/11411-turquoiseEucalyptus/00-agencyIncomingForeign.sql @@ -0,0 +1,13 @@ +use `vn`; +DELETE ai from + `vn`.`agencyIncoming` ai + LEFT JOIN `vn`.`agencyMode` am ON + am.id = ai.agencyModeFk + WHERE am.id IS null; + +ALTER TABLE `vn`.`agencyIncoming` + ADD CONSTRAINT `fk_agencyIncoming_agencyMode` + FOREIGN KEY (`agencyModeFk`) + REFERENCES `agencyMode`(`id`) + ON DELETE CASCADE + ON UPDATE CASCADE; diff --git a/db/versions/11411-turquoiseEucalyptus/01-travelThermographAlter.sql b/db/versions/11411-turquoiseEucalyptus/01-travelThermographAlter.sql new file mode 100644 index 000000000..3838f59d7 --- /dev/null +++ b/db/versions/11411-turquoiseEucalyptus/01-travelThermographAlter.sql @@ -0,0 +1,7 @@ +ALTER TABLE `vn`.`travelThermograph` + ADD COLUMN `agencyModeFk` INT(11) NULL AFTER `editorFk`, + ADD CONSTRAINT `travelThermograph_agencyIncoming_fk` + FOREIGN KEY (`agencyModeFk`) + REFERENCES `agencyIncoming`(`agencyModeFk`) + ON DELETE RESTRICT + ON UPDATE CASCADE; diff --git a/db/versions/11416-goldenTulip/00-firstScript.sql b/db/versions/11416-goldenTulip/00-firstScript.sql new file mode 100644 index 000000000..aa410c52f --- /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 000000000..565bf0f55 --- /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 000000000..c729c3de2 --- /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 000000000..4df73139a --- /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 000000000..89833fe8b --- /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 000000000..588810ded --- /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 000000000..82de52c67 --- /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 000000000..13cb9df89 --- /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 000000000..a7fdd5b86 --- /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 000000000..5e61de07a --- /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/11419-orangeSalal/00-firstScript.sql b/db/versions/11419-orangeSalal/00-firstScript.sql new file mode 100644 index 000000000..432ed70aa --- /dev/null +++ b/db/versions/11419-orangeSalal/00-firstScript.sql @@ -0,0 +1,2 @@ +ALTER TABLE `vn`.`tag` +ADD COLUMN IF NOT EXISTS `validationRegex` varchar(50) DEFAULT NULL; diff --git a/db/versions/11423-maroonMonstera/00-firstScript.sql b/db/versions/11423-maroonMonstera/00-firstScript.sql new file mode 100644 index 000000000..cf21473d8 --- /dev/null +++ b/db/versions/11423-maroonMonstera/00-firstScript.sql @@ -0,0 +1 @@ +ALTER TABLE vn.address MODIFY COLUMN isEqualizated tinyint(1) NULL; diff --git a/db/versions/11424-navyRose/00-travel.sql b/db/versions/11424-navyRose/00-travel.sql new file mode 100644 index 000000000..eabd83d5e --- /dev/null +++ b/db/versions/11424-navyRose/00-travel.sql @@ -0,0 +1,3 @@ +-- Place your SQL code here +ALTER TABLE vn.travel ADD IF NOT EXISTS availabled DATETIME NULL +COMMENT 'Indicates the moment in time when the goods become available for picking'; diff --git a/db/versions/11425-aquaCordyline/00-firstScript.sql b/db/versions/11425-aquaCordyline/00-firstScript.sql new file mode 100644 index 000000000..f8b194e8a --- /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 000000000..34a8c8d14 --- /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 000000000..4e9aecafa --- /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 000000000..726856e76 --- /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 000000000..65f8fa43b --- /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/e2e/paths/02-client/21_defaulter.spec.js b/e2e/paths/02-client/21_defaulter.spec.js deleted file mode 100644 index 01f394bc8..000000000 --- a/e2e/paths/02-client/21_defaulter.spec.js +++ /dev/null @@ -1,65 +0,0 @@ -import selectors from '../../helpers/selectors.js'; -import getBrowser from '../../helpers/puppeteer'; - -describe('Client defaulter path', () => { - let browser; - let page; - - beforeAll(async() => { - browser = await getBrowser(); - page = browser.page; - await page.loginAndModule('insurance', 'client'); - await page.accessToSection('client.defaulter'); - }); - - afterAll(async() => { - await browser.close(); - }); - - it('should count the amount of clients in the turns section', async() => { - const result = await page.countElement(selectors.clientDefaulter.anyClient); - - expect(result).toEqual(6); - }); - - it('should check contain expected client', async() => { - const clientName = - await page.waitToGetProperty(selectors.clientDefaulter.firstClientName, 'innerText'); - const salesPersonName = - await page.waitToGetProperty(selectors.clientDefaulter.firstSalesPersonName, 'innerText'); - - expect(clientName).toEqual('Ororo Munroe'); - expect(salesPersonName).toEqual('salesperson'); - }); - - it('should first observation not changed', async() => { - const expectedObservation = 'Madness, as you know, is like gravity, all it takes is a little push'; - const result = await page.waitToGetProperty(selectors.clientDefaulter.firstObservation, 'value'); - - expect(result).toContain(expectedObservation); - }); - - it('should not add empty observation', async() => { - await page.waitToClick(selectors.clientDefaulter.allDefaulterCheckbox); - - await page.waitToClick(selectors.clientDefaulter.addObservationButton); - await page.write(selectors.clientDefaulter.observation, ''); - await page.waitToClick(selectors.clientDefaulter.saveButton); - const message = await page.waitForSnackbar(); - - expect(message.text).toContain(`The message can't be empty`); - }); - - it('should checked all defaulters', async() => { - await page.loginAndModule('insurance', 'client'); - await page.accessToSection('client.defaulter'); - - await page.waitToClick(selectors.clientDefaulter.allDefaulterCheckbox); - }); - - it('should add observation for all clients', async() => { - await page.waitToClick(selectors.clientDefaulter.addObservationButton); - await page.write(selectors.clientDefaulter.observation, 'My new observation'); - await page.waitToClick(selectors.clientDefaulter.saveButton); - }); -}); diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 06428475f..eeb32f545 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 abd2f79a0..dca19e4a6 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" -} \ No newline at end of file + "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 d7d5b7710..378b0d267 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 d1ac2ef23..35fe3d4f1 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 b7974ad23..8b56f3a1c 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 25414d1db..75caf278e 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 3dc9261c3..41c064c75 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/extendedListFilter.js b/modules/client/back/methods/client/extendedListFilter.js index 174970a2f..0097795e6 100644 --- a/modules/client/back/methods/client/extendedListFilter.js +++ b/modules/client/back/methods/client/extendedListFilter.js @@ -43,6 +43,14 @@ module.exports = Self => { arg: 'postcode', type: 'string', }, + { + arg: 'sageTransactionTypeFk', + type: 'number', + }, + { + arg: 'sageTaxTypeFk', + type: 'number', + }, { arg: 'provinceFk', type: 'number', @@ -79,6 +87,10 @@ module.exports = Self => { return /^\d+$/.test(value) ? {'c.id': {inq: value}} : {'c.name': {like: `%${value}%`}}; + case 'sageTaxTypeFk': + return {'sti.CodigoIva': value}; + case 'sageTransactionTypeFk': + return {'stt.CodigoTransaccion': value}; case 'name': case 'salesPersonFk': case 'fi': diff --git a/modules/client/back/methods/client/filter.js b/modules/client/back/methods/client/filter.js index 7df973f19..c217b2a86 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/methods/client/specs/updateAddress.spec.js b/modules/client/back/methods/client/specs/updateAddress.spec.js index 0453332d7..233ab9ccb 100644 --- a/modules/client/back/methods/client/specs/updateAddress.spec.js +++ b/modules/client/back/methods/client/specs/updateAddress.spec.js @@ -157,4 +157,52 @@ describe('Address updateAddress', () => { throw e; } }); + + it('should update ticket observations when updateObservations is true', async() => { + const tx = await models.Client.beginTransaction({}); + const client = 1103; + const address = 123; + const ticket = 31; + const observationType = 3; + + const salesAssistantId = 21; + const addressObservation = 'nuevo texto'; + const ticketObservation = 'texto a modificar'; + + try { + const options = {transaction: tx}; + ctx.req.accessToken.userId = salesAssistantId; + ctx.args = { + updateObservations: true, + incotermsFk: incotermsId, + provinceFk: provinceId, + customsAgentFk: customAgentOneId + }; + + await models.AddressObservation.create({ + addressFk: address, + observationTypeFk: observationType, + description: addressObservation + }, options); + + await models.TicketObservation.create({ + ticketFk: ticket, + observationTypeFk: observationType, + description: ticketObservation + }, options); + + await models.Client.updateAddress(ctx, client, address, options); + + const updatedObservation = await models.TicketObservation.findOne({ + where: {ticketFk: ticket, observationTypeFk: observationType} + }, options); + + expect(updatedObservation.description).toEqual(addressObservation); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); }); diff --git a/modules/client/back/methods/client/updateAddress.js b/modules/client/back/methods/client/updateAddress.js index efef83d6b..e6e5adb45 100644 --- a/modules/client/back/methods/client/updateAddress.js +++ b/modules/client/back/methods/client/updateAddress.js @@ -80,6 +80,10 @@ module.exports = function(Self) { { arg: 'latitude', type: 'any', + }, + { + arg: 'updateObservations', + type: 'boolean' } ], returns: { @@ -135,6 +139,17 @@ module.exports = function(Self) { delete args.ctx; // Remove unwanted properties const updatedAddress = await address.updateAttributes(ctx.args, myOptions); + if (args.updateObservations) { + const ticket = await Self.rawSql(` + UPDATE ticketObservation to2 + JOIN ticket t ON t.id = to2.ticketFk + JOIN address a ON a.id = t.addressFk + JOIN addressObservation ao ON ao.addressFk = a.id + SET to2.description = ao.description + WHERE ao.observationTypeFk = to2.observationTypeFk + AND a.id = ? + AND t.shipped >= util.VN_CURDATE()`, [addressId], myOptions); + } return updatedAddress; }; diff --git a/modules/client/back/methods/defaulter/filter.js b/modules/client/back/methods/defaulter/filter.js index cf8bd855a..e00048cf5 100644 --- a/modules/client/back/methods/defaulter/filter.js +++ b/modules/client/back/methods/defaulter/filter.js @@ -21,7 +21,7 @@ module.exports = Self => { } ], returns: { - type: ['object'], + type: 'object', root: true }, http: { @@ -41,23 +41,28 @@ module.exports = Self => { switch (param) { case 'search': return {or: [ - {'d.clientFk': value}, - {'d.clientName': {like: `%${value}%`}} + {'c.id': value}, + {'c.name': {like: `%${value}%`}} ]}; } }); - filter = mergeFilters(ctx.args.filter, {where}); + const date = Date.vnNew(); + date.setHours(0, 0, 0, 0); + + filter = mergeFilters({where: {'d.created': date, 'd.amount': {gt: 0}}}, ctx.args.filter); + filter = mergeFilters(filter, {where}); const stmts = []; - const date = Date.vnNew(); - date.setHours(0, 0, 0, 0); - const stmt = new ParameterizedSQL( - `SELECT * - FROM ( - SELECT - DISTINCT c.id clientFk, + let stmt = new ParameterizedSQL( + `CREATE OR REPLACE TEMPORARY TABLE tmp.defaulters + WITH clientObservations AS + (SELECT clientFk,text, created, workerFk + FROM vn.clientObservation + GROUP BY clientFk + ORDER BY created DESC + )SELECT c.id clientFk, c.name clientName, c.salesPersonFk, c.businessTypeFk = 'worker' isWorker, @@ -80,36 +85,43 @@ module.exports = Self => { JOIN client c ON c.id = d.clientFk JOIN country cn ON cn.id = c.countryFk JOIN payMethod pm ON pm.id = c.payMethodFk - LEFT JOIN clientObservation co ON co.clientFk = c.id + LEFT JOIN clientObservations co ON co.clientFk = c.id LEFT JOIN account.user u ON u.id = c.salesPersonFk LEFT JOIN account.user uw ON uw.id = co.workerFk LEFT JOIN ( - SELECT r1.started, r1.clientFk, r1.finished + SELECT r1.started, r1.clientFk, r1.finished FROM recovery r1 JOIN ( - SELECT MAX(started) AS maxStarted, clientFk + SELECT MAX(started) maxStarted, clientFk FROM recovery GROUP BY clientFk ) r2 ON r1.clientFk = r2.clientFk AND r1.started = r2.maxStarted + WHERE r1.finished + GROUP BY r1.clientFk ) r ON r.clientFk = c.id LEFT JOIN workerDepartment wd ON wd.workerFk = u.id - LEFT JOIN department dp ON dp.id = wd.departmentFk - WHERE - d.created = ? - AND d.amount > 0 - ORDER BY co.created DESC) d` - , [date]); + LEFT JOIN department dp ON dp.id = wd.departmentFk`); stmt.merge(conn.makeWhere(filter.where)); - stmt.merge(`GROUP BY d.clientFk`); + stmts.push(stmt); + + stmt = new ParameterizedSQL(` + SELECT SUM(amount) amount + FROM tmp.defaulters + `); + stmts.push(stmt); + + stmt = new ParameterizedSQL(` + SELECT * + FROM tmp.defaulters + `); stmt.merge(conn.makeOrderBy(filter.order)); - stmt.merge(conn.makeLimit(filter)); const itemsIndex = stmts.push(stmt) - 1; const sql = ParameterizedSQL.join(stmts, ';'); const result = await conn.executeStmt(sql, myOptions); - return itemsIndex === 0 ? result : result[itemsIndex]; + return {defaulters: result[itemsIndex], amount: result[itemsIndex - 1][0].amount}; }; }; diff --git a/modules/client/back/methods/defaulter/specs/filter.spec.js b/modules/client/back/methods/defaulter/specs/filter.spec.js index 0a970823e..ca7a6b4ff 100644 --- a/modules/client/back/methods/defaulter/specs/filter.spec.js +++ b/modules/client/back/methods/defaulter/specs/filter.spec.js @@ -11,10 +11,10 @@ describe('defaulter filter()', () => { const ctx = {req: {accessToken: {userId: authUserId}}, args: {filter: filter}}; const result = await models.Defaulter.filter(ctx, null, options); - const firstRow = result[0]; + const firstRow = result.defaulters[0]; expect(firstRow.clientFk).toEqual(1101); - expect(result.length).toEqual(5); + expect(result.defaulters.length).toEqual(5); await tx.rollback(); } catch (e) { @@ -31,7 +31,7 @@ describe('defaulter filter()', () => { const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 1101}}; const result = await models.Defaulter.filter(ctx, null, options); - const firstRow = result[0]; + const firstRow = result.defaulters[0]; expect(firstRow.clientFk).toEqual(1101); @@ -50,7 +50,7 @@ describe('defaulter filter()', () => { const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 'Petter Parker'}}; const result = await models.Defaulter.filter(ctx, null, options); - const firstRow = result[0]; + const firstRow = result.defaulters[0]; expect(firstRow.clientName).toEqual('Petter Parker'); @@ -60,4 +60,23 @@ describe('defaulter filter()', () => { throw e; } }); + + it('should return the defaulter the sum of every defaulters', async() => { + const tx = await models.Defaulter.beginTransaction({}); + + try { + const options = {transaction: tx}; + const ctx = {req: {accessToken: {userId: authUserId}}, args: {search: 1101}}; + const {defaulters, amount} = await models.Defaulter.filter(ctx, null, options); + + const total = defaulters.reduce((total, row) => total + row.amount, 0); + + expect(total).toEqual(amount); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); }); diff --git a/modules/client/back/model-config.json b/modules/client/back/model-config.json index e6690ee5f..67a61b8b5 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 000000000..54a632bea --- /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 416845842..dc6cd0bcd 100644 --- a/modules/client/back/models/business.json +++ b/modules/client/back/models/business.json @@ -14,9 +14,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": { "worker": { @@ -28,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 000000000..742aaed94 --- /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 000000000..e40eaf2fe --- /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 000000000..ca3431ba9 --- /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 000000000..5f812a704 --- /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 000000000..bd62b2aa3 --- /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 000000000..648ce3fd2 --- /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/client/front/defaulter/index.html b/modules/client/front/defaulter/index.html index 440f34d3d..7fb3b870e 100644 --- a/modules/client/front/defaulter/index.html +++ b/modules/client/front/defaulter/index.html @@ -1,200 +1,2 @@ - - - - - - - - -
-
-
Total
- - -
-
-
- - -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - Client - - Es trabajador - - Comercial - - Country - - P.Method - - Balance D. - - Author - - Last observation - - L. O. Date - - Credit I. - - From -
- - - - - {{::defaulter.clientName}} - - - - - - - {{::defaulter.salesPersonName | dashIfEmpty}} - - - {{::defaulter.country}} - - {{::defaulter.payMethod}} - {{::defaulter.amount | currency: 'EUR': 2}} - - {{::defaulter.workerName | dashIfEmpty}} - - - - - - - {{::defaulter.created | date: 'dd/MM/yyyy'}} - - {{::defaulter.creditInsurance | currency: 'EUR': 2}}{{::defaulter.defaulterSinced | date: 'dd/MM/yyyy'}}
-
-
- - - - - - - - - - - - -
-
{{$ctrl.$t('Add observation to all selected clients', {total: $ctrl.checked.length})}}
- - - - -
-
- - - - -
diff --git a/modules/client/front/defaulter/index.js b/modules/client/front/defaulter/index.js index 2ec53d380..9df546a85 100644 --- a/modules/client/front/defaulter/index.js +++ b/modules/client/front/defaulter/index.js @@ -1,199 +1,13 @@ import ngModule from '../module'; import Section from 'salix/components/section'; -import UserError from 'core/lib/user-error'; export default class Controller extends Section { constructor($element, $) { super($element, $); - this.defaulter = {}; - this.defaulters = []; - this.checkedDefaulers = []; - - this.smartTableOptions = { - activeButtons: { - search: true - }, - columns: [ - { - field: 'clientFk', - autocomplete: { - url: 'Clients', - showField: 'name', - valueField: 'id' - } - }, { - field: 'salesPersonFk', - autocomplete: { - url: 'Workers/activeWithInheritedRole', - where: `{role: 'salesPerson'}`, - searchFunction: '{firstName: $search}', - showField: 'name', - valueField: 'id', - } - }, { - field: 'countryFk', - autocomplete: { - url: 'Countries', - showField: 'country', - valueField: 'id' - } - }, { - field: 'payMethodFk', - autocomplete: { - showField: 'name', - valueField: 'id' - } - }, - { - field: 'workerFk', - autocomplete: { - url: 'Workers/activeWithInheritedRole', - searchFunction: '{firstName: $search}', - showField: 'name', - valueField: 'id', - } - }, - { - field: 'observation', - searchable: false - }, - { - field: 'isWorker', - checkbox: true, - - }, - { - field: 'created', - datepicker: true - }, - { - field: 'defaulterSinced', - datepicker: true - } - ] - }; - - this.getBalanceDueTotal(); } - - set defaulters(value) { - if (!value || !value.length) return; - this._defaulters = value; - } - - get defaulters() { - return this._defaulters; - } - - get checked() { - const clients = this.$.model.data || []; - const checkedLines = []; - for (let defaulter of clients) { - if (defaulter.checked) - checkedLines.push(defaulter); - } - - return checkedLines; - } - - saveChecked(clientId) { - this.checkedDefaulers = this.checkedDefaulers.includes(clientId) ? - this.checkedDefaulers.filter(id => id !== clientId) : [...this.checkedDefaulers, clientId]; - } - - reCheck() { - if (!this.$.model.data || !this.checkedDefaulers.length) return; - - this.$.model.data.forEach(defaulter => { - defaulter.checked = this.checkedDefaulers.includes(defaulter.clientFk); - }); - } - - getBalanceDueTotal() { - this.$http.get('Defaulters/filter') - .then(res => { - if (!res.data) return 0; - - this.balanceDueTotal = res.data.reduce( - (accumulator, currentValue) => { - return accumulator + (currentValue['amount'] || 0); - }, 0); - }); - } - - chipColor(date) { - const day = 24 * 60 * 60 * 1000; - const today = Date.vnNew(); - today.setHours(0, 0, 0, 0); - - const observationShipped = new Date(date); - observationShipped.setHours(0, 0, 0, 0); - - const difference = today - observationShipped; - - if (difference > (day * 20)) - return 'alert'; - if (difference > (day * 10)) - return 'warning'; - } - - onResponse() { - if (!this.defaulter.observation) - throw new UserError(`The message can't be empty`); - - const params = []; - for (let defaulter of this.checked) { - params.push({ - text: this.defaulter.observation, - clientFk: defaulter.clientFk - }); - } - - this.$http.post(`ClientObservations`, params) .then(() => { - this.vnApp.showSuccess(this.$t('Observation saved!')); - this.sendMail(); - this.$state.reload(); - }); - } - - sendMail() { - const params = { - defaulters: this.checked, - observation: this.defaulter.observation, - }; - this.$http.post(`Defaulters/observationEmail`, params); - } - - exprBuilder(param, value) { - switch (param) { - case 'isWorker': - return {isWorker: value}; - case 'creditInsurance': - case 'amount': - case 'clientFk': - case 'workerFk': - case 'countryFk': - case 'payMethod': - case 'salesPersonFk': - return {[`d.${param}`]: value}; - case 'created': - return {'d.created': { - between: this.dateRange(value)} - }; - case 'defaulterSinced': - return {'d.defaulterSinced': { - between: this.dateRange(value)} - }; - } - } - - dateRange(value) { - const minHour = new Date(value); - minHour.setHours(0, 0, 0, 0); - const maxHour = new Date(value); - maxHour.setHours(23, 59, 59, 59); - - return [minHour, maxHour]; + async $onInit() { + this.$state.go('customer.defaulter', {id: this.$params.id}); + window.location.href = await this.vnApp.getUrl(`customer/defaulter`); } } diff --git a/modules/client/front/defaulter/index.spec.js b/modules/client/front/defaulter/index.spec.js deleted file mode 100644 index b4a9df184..000000000 --- a/modules/client/front/defaulter/index.spec.js +++ /dev/null @@ -1,179 +0,0 @@ -import './index'; -import crudModel from 'core/mocks/crud-model'; - -describe('client defaulter', () => { - describe('Component vnClientDefaulter', () => { - let controller; - let $httpBackend; - - beforeEach(ngModule('client')); - - beforeEach(inject(($componentController, _$httpBackend_) => { - $httpBackend = _$httpBackend_; - const $element = angular.element(''); - controller = $componentController('vnClientDefaulter', {$element}); - controller.$.model = crudModel; - controller.$.model.data = [ - {clientFk: 1101, amount: 125}, - {clientFk: 1102, amount: 500}, - {clientFk: 1103, amount: 250} - ]; - })); - - describe('checked() getter', () => { - it('should return the checked lines', () => { - const data = controller.$.model.data; - data[1].checked = true; - data[2].checked = true; - - const checkedRows = controller.checked; - - const firstCheckedRow = checkedRows[0]; - const secondCheckedRow = checkedRows[1]; - - expect(firstCheckedRow.clientFk).toEqual(1102); - expect(secondCheckedRow.clientFk).toEqual(1103); - }); - }); - - describe('chipColor()', () => { - it('should return undefined when the date is the present', () => { - let today = Date.vnNew(); - let result = controller.chipColor(today); - - expect(result).toEqual(undefined); - }); - - it('should return warning when the date is 10 days in the past', () => { - let pastDate = Date.vnNew(); - pastDate = pastDate.setDate(pastDate.getDate() - 11); - let result = controller.chipColor(pastDate); - - expect(result).toEqual('warning'); - }); - - it('should return alert when the date is 20 days in the past', () => { - let pastDate = Date.vnNew(); - pastDate = pastDate.setDate(pastDate.getDate() - 21); - let result = controller.chipColor(pastDate); - - expect(result).toEqual('alert'); - }); - }); - - describe('onResponse()', () => { - it('should return error for empty message', () => { - let error; - try { - controller.onResponse(); - } catch (e) { - error = e; - } - - expect(error).toBeDefined(); - expect(error.message).toBe(`The message can't be empty`); - }); - - it('should return saved message', () => { - const data = controller.$.model.data; - data[1].checked = true; - controller.defaulter = {observation: 'My new observation'}; - - const params = [{text: controller.defaulter.observation, clientFk: data[1].clientFk}]; - - jest.spyOn(controller.vnApp, 'showSuccess'); - $httpBackend.expect('GET', `Defaulters/filter`).respond(200); - $httpBackend.expect('POST', `ClientObservations`, params).respond(200, params); - $httpBackend.expect('POST', `Defaulters/observationEmail`).respond(200); - - controller.onResponse(); - $httpBackend.flush(); - - expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Observation saved!'); - }); - }); - - describe('exprBuilder()', () => { - it('should search by sales person', () => { - const expr = controller.exprBuilder('salesPersonFk', '5'); - - expect(expr).toEqual({'d.salesPersonFk': '5'}); - }); - - it('should search by client', () => { - const expr = controller.exprBuilder('clientFk', '5'); - - expect(expr).toEqual({'d.clientFk': '5'}); - }); - }); - - describe('getBalanceDueTotal()', () => { - it('should return balance due total', () => { - const defaulters = controller.$.model.data; - $httpBackend.when('GET', `Defaulters/filter`).respond(defaulters); - - controller.getBalanceDueTotal(); - $httpBackend.flush(); - - expect(controller.balanceDueTotal).toEqual(875); - }); - }); - - describe('dateRange()', () => { - it('should return two dates with the hours at the start and end of the given date', () => { - const now = Date.vnNew(); - - const today = now.getDate(); - - const dateRange = controller.dateRange(now); - const start = dateRange[0].toString(); - const end = dateRange[1].toString(); - - expect(start).toContain(today); - expect(start).toContain('00:00:00'); - - expect(end).toContain(today); - expect(end).toContain('23:59:59'); - }); - }); - - describe('reCheck()', () => { - it(`should recheck buys`, () => { - controller.$.model.data = [ - {checked: false, clientFk: 1}, - {checked: false, clientFk: 2}, - {checked: false, clientFk: 3}, - {checked: false, clientFk: 4}, - ]; - controller.checkedDefaulers = [1, 2]; - - controller.reCheck(); - - expect(controller.$.model.data[0].checked).toEqual(true); - expect(controller.$.model.data[1].checked).toEqual(true); - expect(controller.$.model.data[2].checked).toEqual(false); - expect(controller.$.model.data[3].checked).toEqual(false); - }); - }); - - describe('saveChecked()', () => { - it(`should check buy`, () => { - const buyCheck = 3; - controller.checkedDefaulers = [1, 2]; - - controller.saveChecked(buyCheck); - - expect(controller.checkedDefaulers[2]).toEqual(buyCheck); - }); - - it(`should uncheck buy`, () => { - const buyUncheck = 3; - controller.checkedDefaulers = [1, 2, 3]; - - controller.saveChecked(buyUncheck); - - expect(controller.checkedDefaulers[2]).toEqual(undefined); - }); - }); - }); -}); diff --git a/modules/client/front/defaulter/locale/es.yml b/modules/client/front/defaulter/locale/es.yml deleted file mode 100644 index 7d93d4fe2..000000000 --- a/modules/client/front/defaulter/locale/es.yml +++ /dev/null @@ -1,14 +0,0 @@ -Add observation: Añadir observación -Add observation to all selected clients: Añadir observación a {{total}} cliente(s) seleccionado(s) -Balance D.: Saldo V. -Credit I.: Crédito A. -Last observation: Última observación -L. O. Date: Fecha Ú. O. -Last observation date: Fecha última observación -Search client: Buscar clientes -Worker who made the last observation: Trabajador que ha realizado la última observación -Email sended!: Email enviado! -Observation saved!: Observación añadida! -P.Method: F.Pago -Pay Method: Forma de Pago -Country: Pais \ No newline at end of file diff --git a/modules/entry/back/methods/entry/specs/transfer.spec.js b/modules/entry/back/methods/entry/specs/transfer.spec.js new file mode 100644 index 000000000..bf0b2b974 --- /dev/null +++ b/modules/entry/back/methods/entry/specs/transfer.spec.js @@ -0,0 +1,43 @@ +const models = require('vn-loopback/server/server').models; + +describe('Transfer merchandise from one entry to the next day()', () => { + it('should Transfer buys not located', async() => { + const tx = await models.ItemShelving.beginTransaction({}); + const options = {transaction: tx}; + + try { + const id = 3; + const item = 8; + const buy = 6; + const originalEntry = 4; + const ctx = {req: {accessToken: {userId: 48}}}; + + const currentItemShelving = await models.ItemShelving.findOne({where: {id}}, options); + await currentItemShelving.updateAttributes({itemFk: item, buyFk: buy}, options); + + const {newEntryFk} = await models.Entry.transfer(ctx, originalEntry, options); + const originalEntrybuys = await models.Buy.find({where: {entryFk: originalEntry}}, options); + + const newEntrybuys = await models.Buy.find({where: {entryFk: newEntryFk}}, options); + + const itemShelvingsWithBuys = await models.Buy.find({ + include: { + relation: 'itemShelving', + scope: { + fields: ['id'], + }, + }, + where: {entryFk: originalEntry}, + }, options); + + const hasItemShelving = await itemShelvingsWithBuys.filter(buy => buy.itemShelving().length); + + expect(newEntrybuys.length).toEqual(originalEntrybuys.length - hasItemShelving.length); + + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); +}); diff --git a/modules/entry/back/methods/entry/transfer.js b/modules/entry/back/methods/entry/transfer.js new file mode 100644 index 000000000..fc1c4808a --- /dev/null +++ b/modules/entry/back/methods/entry/transfer.js @@ -0,0 +1,46 @@ +module.exports = Self => { + Self.remoteMethodCtx('transfer', { + description: 'Transfer merchandise from one entry to the next day', + accessType: 'WRITE', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + http: {source: 'path'} + } + ], + http: { + path: '/:id/transfer', + verb: 'POST' + }, + returns: { + arg: 'newEntryFk', + type: 'number' + } + }); + + Self.transfer = async(ctx, id, options) => { + const myOptions = {userId: ctx.req.accessToken.userId}; + let tx; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + await Self.rawSql('CALL vn.entry_transfer(?, @vNewEntry)', [id], myOptions); + const [newEntryFk] = await Self.rawSql('SELECT @vNewEntry newEntryFk', null, myOptions); + + if (tx) await tx.commit(); + return newEntryFk; + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/entry/back/models/buy.json b/modules/entry/back/models/buy.json index 14cafde06..cd1e54de7 100644 --- a/modules/entry/back/models/buy.json +++ b/modules/entry/back/models/buy.json @@ -114,6 +114,11 @@ "type": "belongsTo", "model": "Delivery", "foreignKey": "deliveryFk" - } + }, + "itemShelving": { + "type": "hasMany", + "model": "ItemShelving", + "foreignKey": "buyFk" + } } } diff --git a/modules/entry/back/models/entry.js b/modules/entry/back/models/entry.js index 55a23bb0a..03cbd6e7f 100644 --- a/modules/entry/back/models/entry.js +++ b/modules/entry/back/models/entry.js @@ -12,6 +12,7 @@ module.exports = Self => { require('../methods/entry/addFromPackaging')(Self); require('../methods/entry/addFromBuy')(Self); require('../methods/entry/buyLabel')(Self); + require('../methods/entry/transfer')(Self); require('../methods/entry/labelSupplier')(Self); require('../methods/entry/buyLabelSupplier')(Self); diff --git a/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/createManualInvoice.js index a06128848..c4e336818 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 7a960a8c8..715456511 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/item/back/models/item-shelving.json b/modules/item/back/models/item-shelving.json index 483d6bf3d..5c31e9e4e 100644 --- a/modules/item/back/models/item-shelving.json +++ b/modules/item/back/models/item-shelving.json @@ -61,6 +61,11 @@ "type": "belongsTo", "model": "Shelving", "foreignKey": "shelvingFk" - } + }, + "buy": { + "type": "belongsTo", + "model": "Buy", + "foreignKey": "buyFk" + } } -} \ No newline at end of file +} diff --git a/modules/item/back/models/item-tag.js b/modules/item/back/models/item-tag.js index 5b7163913..2cd2e5f9b 100644 --- a/modules/item/back/models/item-tag.js +++ b/modules/item/back/models/item-tag.js @@ -10,4 +10,27 @@ module.exports = Self => { return new UserError(`Tag value cannot be blank`); return err; }); + + Self.observe('before save', async ctx => { + let tagFk; + let value; + + if (ctx.isNewInstance) { + tagFk = ctx.instance.tagFk; + value = ctx.instance.value; + } else { + tagFk = ctx.currentInstance.tagFk; + value = ctx.data.value; + } + const models = Self.app.models; + const validTag = await models.Tag.findById(tagFk); + + if (validTag.validationRegex) { + const regexString = validTag.validationRegex.replace(/\\\\/g, '\\'); + const validExpresion = new RegExp(regexString); + + if (value && !validExpresion.test(value)) + throw new UserError('The value must be a number or a range of numbers'); + } + }); }; diff --git a/modules/item/back/models/tag.json b/modules/item/back/models/tag.json index 6c5f5c0ba..5269b849f 100644 --- a/modules/item/back/models/tag.json +++ b/modules/item/back/models/tag.json @@ -30,6 +30,9 @@ "mysql": { "columnName": "isQuantitatif" } + }, + "validationRegex": { + "type": "string" } }, "acls": [ diff --git a/modules/mdb/back/methods/mdbVersion/upload.js b/modules/mdb/back/methods/mdbVersion/upload.js index 64de72679..ee67e35d0 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 4947edeaf..ce50fec6a 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 738af5219..1b4616de7 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/roadmap/specs/clone.spec.js b/modules/route/back/methods/roadmap/specs/clone.spec.js deleted file mode 100644 index 41e696157..000000000 --- a/modules/route/back/methods/roadmap/specs/clone.spec.js +++ /dev/null @@ -1,109 +0,0 @@ -const app = require('vn-loopback/server/server'); -const models = require('vn-loopback/server/server').models; - -describe('AgencyTerm filter()', () => { - const authUserId = 9; - const today = Date.vnNew(); - today.setHours(2, 0, 0, 0); - - it('should return all results matching the filter', async() => { - const tx = await models.AgencyTerm.beginTransaction({}); - - try { - const options = {transaction: tx}; - const filter = {}; - const ctx = {req: {accessToken: {userId: authUserId}}}; - - const agencyTerms = await models.AgencyTerm.filter(ctx, filter, options); - const firstAgencyTerm = agencyTerms[0]; - - expect(firstAgencyTerm.routeFk).toEqual(1); - expect(agencyTerms.length).toEqual(5); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); - - it('should return results matching "search" searching by integer', async() => { - let ctx = { - args: { - search: 1, - } - }; - - let result = await app.models.AgencyTerm.filter(ctx); - - expect(result.length).toEqual(1); - expect(result[0].routeFk).toEqual(1); - }); - - it('should return results matching "search" searching by string', async() => { - let ctx = { - args: { - search: 'Plants SL', - } - }; - - let result = await app.models.AgencyTerm.filter(ctx); - - expect(result.length).toEqual(2); - }); - - it('should return results matching "from" and "to"', async() => { - const tx = await models.Buy.beginTransaction({}); - const options = {transaction: tx}; - - try { - const from = Date.vnNew(); - from.setHours(0, 0, 0, 0); - - const to = Date.vnNew(); - to.setHours(23, 59, 59, 999); - - const ctx = { - args: { - from: from, - to: to - } - }; - - const results = await models.AgencyTerm.filter(ctx, options); - - expect(results.length).toBe(5); - - await tx.rollback(); - } catch (e) { - await tx.rollback(); - throw e; - } - }); - - it('should return results matching "agencyModeFk"', async() => { - let ctx = { - args: { - agencyModeFk: 1, - } - }; - - let result = await app.models.AgencyTerm.filter(ctx); - - expect(result.length).toEqual(1); - expect(result[0].routeFk).toEqual(1); - }); - - it('should return results matching "agencyFk"', async() => { - let ctx = { - args: { - agencyFk: 2, - } - }; - - let result = await app.models.AgencyTerm.filter(ctx); - - expect(result.length).toEqual(1); - expect(result[0].routeFk).toEqual(2); - }); -}); diff --git a/modules/route/back/methods/route/filter.js b/modules/route/back/methods/route/filter.js index 70bf7ba67..d4e127a92 100644 --- a/modules/route/back/methods/route/filter.js +++ b/modules/route/back/methods/route/filter.js @@ -87,6 +87,8 @@ module.exports = Self => { Self.filter = async(ctx, filter) => { let conn = Self.dataSource.connector; + const userId = ctx.req.accessToken.userId; + const models = Self.app.models; let where = buildFilter(ctx.args, (param, value) => { switch (param) { @@ -110,6 +112,13 @@ module.exports = Self => { filter = mergeFilters(filter, {where}); + const worker = await models.Worker.findById(userId, {fields: ['isFreelance']}); + const getMyRoute = await models.ACL.checkAccessAcl(ctx, 'Route', 'getRouteByAgency', 'WRITE'); + + if (userId && getMyRoute && worker.isFreelance) { + if (!filter.where) filter.where = {}; + filter.where[`workerFk`] = userId; + } let stmts = []; let stmt; diff --git a/modules/route/back/methods/route/specs/filter.spec.js b/modules/route/back/methods/route/specs/filter.spec.js index 18c0ca04f..ddc2fe893 100644 --- a/modules/route/back/methods/route/specs/filter.spec.js +++ b/modules/route/back/methods/route/specs/filter.spec.js @@ -8,14 +8,32 @@ describe('Route filter()', () => { it('should return the routes matching "search"', async() => { const ctx = { args: { - search: 1, + search: 5, + }, + req: { + accessToken: { + userId: 9 + } + } + }; + const result = await app.models.Route.filter(ctx); + + expect(result.length).toEqual(1); + expect(result[0].id).toEqual(5); + }); + + it('should return all results matching the filter', async() => { + const ctx = { + req: { + accessToken: { + userId: 133 + } } }; const result = await app.models.Route.filter(ctx); - expect(result.length).toEqual(1); - expect(result[0].id).toEqual(1); + expect(result.length).toEqual(3); }); it('should return results matching "from" and "to"', async() => { @@ -32,9 +50,13 @@ describe('Route filter()', () => { args: { from: from, to: to + }, + req: { + accessToken: { + userId: 9 + } } }; - const results = await models.Route.filter(ctx, options); expect(results.length).toBe(7); @@ -50,6 +72,11 @@ describe('Route filter()', () => { const ctx = { args: { m3: 0.1, + }, + req: { + accessToken: { + userId: 9 + } } }; @@ -62,6 +89,11 @@ describe('Route filter()', () => { const ctx = { args: { description: 'third route', + }, + req: { + accessToken: { + userId: 9 + } } }; @@ -74,18 +106,27 @@ describe('Route filter()', () => { const ctx = { args: { workerFk: 56, + }, + req: { + accessToken: { + userId: 9 + } } }; - const result = await app.models.Route.filter(ctx); - expect(result.length).toEqual(5); + expect(result.length).toEqual(2); }); it('should return the routes matching "warehouseFk"', async() => { const ctx = { args: { warehouseFk: 1, + }, + req: { + accessToken: { + userId: 9 + } } }; @@ -104,9 +145,13 @@ describe('Route filter()', () => { const ctx = { args: { vehicleFk: 2, + }, + req: { + accessToken: { + userId: 9 + } } }; - const result = await app.models.Route.filter(ctx); expect(result.length).toEqual(1); @@ -116,6 +161,11 @@ describe('Route filter()', () => { const ctx = { args: { agencyModeFk: 7, + }, + req: { + accessToken: { + userId: 9 + } } }; diff --git a/modules/route/back/methods/route/specs/optimizePriority.spec.js b/modules/route/back/methods/route/specs/optimizePriority.spec.js index c1c2dc45e..94072fd88 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/methods/route/specs/summary.spec.js b/modules/route/back/methods/route/specs/summary.spec.js index a9516f7c5..2ef052c7e 100644 --- a/modules/route/back/methods/route/specs/summary.spec.js +++ b/modules/route/back/methods/route/specs/summary.spec.js @@ -22,7 +22,7 @@ describe('route summary()', () => { }); it(`should return a summary object containing it's worker`, async() => { - const result = await app.models.Route.summary(1); + const result = await app.models.Route.summary(2); const worker = result.route.worker().user(); expect(worker.name).toEqual('delivery'); diff --git a/modules/route/back/models/route.json b/modules/route/back/models/route.json index 8f4eab761..948352571 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/supplier/back/methods/supplier/receipts.js b/modules/supplier/back/methods/supplier/receipts.js new file mode 100644 index 000000000..cc7b03a42 --- /dev/null +++ b/modules/supplier/back/methods/supplier/receipts.js @@ -0,0 +1,100 @@ + +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; +const {buildFilter, mergeFilters} = require('vn-loopback/util/filter'); +module.exports = Self => { + Self.remoteMethodCtx('receipts', { + description: 'Find all suppliers matched by the filter', + accessType: 'READ', + accepts: [ + { + arg: 'filter', + type: 'object', + description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string', + http: {source: 'query'} + }, { + arg: 'supplierId', + type: 'number', + description: 'The supplier id', + }, + { + arg: 'companyId', + type: 'number', + description: 'The company id', + }, + { + arg: 'currencyFk', + type: 'number', + description: 'The currency', + default: 1, + }, + { + arg: 'bankFk', + type: 'number', + description: 'The bank', + default: 1, + }, + { + arg: 'orderBy', + type: 'string', + description: 'The supplier fiscal id', + enum: ['issued', ' bookEntried', ' booked', ' dueDate'], + }, + { + arg: 'isConciliated', + default: false, + type: 'boolean', + }, + ], + returns: { + type: ['object'], + root: true + }, + http: { + path: `/receipts`, + verb: 'GET' + } + }); + + Self.receipts = async(ctx, filter, options) => { + const conn = Self.dataSource.connector; + const myOptions = {userId: ctx.req.accessToken.userId}; + const args = ctx.args; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const where = buildFilter(ctx.args, (param, value) => { + switch (param) { + case 'bankFk': + return {[param]: value}; + } + }); + + let stmts = []; + + stmts.push(new ParameterizedSQL('CALL vn.supplier_statementWithEntries(?,?,?,?,?,?)', [ + args.supplierId, + args.currencyFk, + args.companyId, + args.orderBy ?? 'issued', + args.isConciliated ?? false, + false + ])); + + const stmt = new ParameterizedSQL(` + SELECT * + FROM tmp.supplierStatement`); + + filter = mergeFilters(args.filter, {where}); + + stmt.merge(conn.makeSuffix(filter)); + stmts.push(stmt); + stmts.push(`DROP TEMPORARY TABLE tmp.supplierStatement`); + + const sql = ParameterizedSQL.join(stmts, ';'); + const results = await conn.executeStmt(sql); + const resultsIndex = stmts.length - 2; + const result = results[resultsIndex]; + return result; + }; +}; diff --git a/modules/supplier/back/models/supplier.js b/modules/supplier/back/models/supplier.js index 7e6908d57..63bd65fbd 100644 --- a/modules/supplier/back/models/supplier.js +++ b/modules/supplier/back/models/supplier.js @@ -8,6 +8,7 @@ module.exports = Self => { require('../methods/supplier/updateFiscalData')(Self); require('../methods/supplier/consumption')(Self); require('../methods/supplier/freeAgencies')(Self); + require('../methods/supplier/receipts')(Self); require('../methods/supplier/campaignMetricsPdf')(Self); require('../methods/supplier/campaignMetricsEmail')(Self); require('../methods/supplier/newSupplier')(Self); diff --git a/modules/ticket/back/locale/sale/es.yml b/modules/ticket/back/locale/sale/es.yml index e6a984a5d..eefd05d83 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 c51781f59..cb10bdb0e 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 ec246c61f..696183827 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 2e1ce0c19..0c4024bbc 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 f125ac586..87556810b 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 5b2288d31..3b5ee21a6 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 000000000..351e07b67 --- /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 247924591..88f40bc3e 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/priceDifference.js b/modules/ticket/back/methods/ticket/priceDifference.js index 7db03e268..7e4fe8283 100644 --- a/modules/ticket/back/methods/ticket/priceDifference.js +++ b/modules/ticket/back/methods/ticket/priceDifference.js @@ -108,7 +108,10 @@ module.exports = Self => { // Get items movable const ticketOrigin = await models.Ticket.findById(args.id, null, myOptions); - const differenceShipped = ticketOrigin.shipped.getTime() > args.shipped.getTime(); + let shipped = ticketOrigin.shipped ?? ticketOrigin.updated; + + const differenceShipped = shipped.getTime() > args.shipped.getTime(); + const differenceWarehouse = ticketOrigin.warehouseFk != args.warehouseId; salesObj.haveDifferences = differenceShipped || differenceWarehouse; diff --git a/modules/ticket/back/methods/ticket/saveSign.js b/modules/ticket/back/methods/ticket/saveSign.js index f99311c39..d619e2037 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 d0edb24e3..cbd799431 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 7c0a67d45..f0a99b90b 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 000000000..f46c27e4d --- /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 3b426c2cf..092ff95fd 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/methods/ticket/specs/transferClient.spec.js b/modules/ticket/back/methods/ticket/specs/transferClient.spec.js index d3ac3c6aa..063433680 100644 --- a/modules/ticket/back/methods/ticket/specs/transferClient.spec.js +++ b/modules/ticket/back/methods/ticket/specs/transferClient.spec.js @@ -22,14 +22,16 @@ describe('Ticket transferClient()', () => { it('should throw an error as the ticket is not editable', async() => { try { const ticketId = 4; - await models.Ticket.transferClient(ctx, ticketId, clientId, options); + const addressFk = null; + await models.Ticket.transferClient(ctx, ticketId, clientId, addressFk, options); } catch (e) { expect(e.message).toEqual('This ticket is locked'); } }); it('should be assigned a different clientFk and nickname in the original ticket', async() => { - await models.Ticket.transferClient(ctx, 2, clientId, options); + const addressFk = null; + await models.Ticket.transferClient(ctx, 2, clientId, addressFk, options); const afterTransfer = await models.Ticket.findById(2, null, options); const client = await models.Client.findById(clientId, {fields: ['defaultAddressFk']}, options); const address = await models.Address.findById(client.defaultAddressFk, {fields: ['nickname']}, options); @@ -39,7 +41,8 @@ describe('Ticket transferClient()', () => { }); it('should be assigned a different clientFk and nickname in the original and refund ticket and claim', async() => { - await models.Ticket.transferClient(ctx, originalTicketId, clientId, options); + const addressFk = null; + await models.Ticket.transferClient(ctx, originalTicketId, clientId, addressFk, options); const [originalTicket, refundTicket] = await models.Ticket.find({ where: {id: {inq: [originalTicketId, refundTicketId]}} @@ -59,4 +62,39 @@ describe('Ticket transferClient()', () => { expect(originalTicket.nickname).toEqual(address.nickname); expect(refundTicket.nickname).toEqual(address.nickname); }); + + it('should be assigned a different addressFk and nickname in the original and refund ticket', async() => { + const addressFk = 131; + await models.Ticket.transferClient(ctx, originalTicketId, clientId, addressFk, options); + + const [originalTicket, refundTicket] = await models.Ticket.find({ + where: {id: {inq: [originalTicketId, refundTicketId]}} + }, options); + + const claim = await models.Claim.findOne({ + where: {ticketFk: originalTicketId} + }, options); + + const address = await models.Address.findById(addressFk, {fields: ['id', 'nickname', 'clientFk']}, options); + + expect(originalTicket.clientFk).toEqual(clientId); + expect(originalTicket.clientFk).toEqual(address.clientFk); + expect(refundTicket.clientFk).toEqual(clientId); + expect(refundTicket.clientFk).toEqual(address.clientFk); + expect(claim.clientFk).toEqual(clientId); + expect(claim.clientFk).toEqual(address.clientFk); + + expect(originalTicket.nickname).toEqual(address.nickname); + expect(refundTicket.nickname).toEqual(address.nickname); + }); + + it('should be thrown an error if the new address is not belong to the client', async() => { + const addressFk = 1; + try { + await models.Ticket.transferClient(ctx, originalTicketId, clientId, addressFk, options); + fail('Expected an error to be thrown, but none was thrown.'); + } catch (e) { + expect(e.message).toEqual('The address does not belong to the client'); + } + }); }); diff --git a/modules/ticket/back/methods/ticket/summary.js b/modules/ticket/back/methods/ticket/summary.js index 6bfa478ec..88894cef7 100644 --- a/modules/ticket/back/methods/ticket/summary.js +++ b/modules/ticket/back/methods/ticket/summary.js @@ -72,7 +72,8 @@ module.exports = Self => { }, { relation: 'address', scope: { - fields: ['street', 'city', 'provinceFk', 'phone', 'mobile', 'postalCode', 'isEqualizated'], + fields: ['street', 'city', 'provinceFk', 'phone', 'mobile', + 'postalCode', 'isEqualizated', 'nickname'], include: { relation: 'province', scope: { diff --git a/modules/ticket/back/methods/ticket/transferClient.js b/modules/ticket/back/methods/ticket/transferClient.js index 95bee008d..2e845144e 100644 --- a/modules/ticket/back/methods/ticket/transferClient.js +++ b/modules/ticket/back/methods/ticket/transferClient.js @@ -1,3 +1,4 @@ +const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('transferClient', { description: 'Transferring ticket to another client', @@ -12,6 +13,10 @@ module.exports = Self => { arg: 'clientFk', type: 'number', required: true, + }, { + arg: 'addressFk', + type: 'number', + required: false, }], http: { path: `/:id/transferClient`, @@ -19,7 +24,7 @@ module.exports = Self => { } }); - Self.transferClient = async(ctx, id, clientFk, options) => { + Self.transferClient = async(ctx, id, clientFk, addressFk, options) => { const models = Self.app.models; const myOptions = {}; let tx; @@ -43,10 +48,12 @@ module.exports = Self => { const client = await models.Client.findById(clientFk, {fields: ['id', 'defaultAddressFk']}, myOptions); - const address = await models.Address.findById(client.defaultAddressFk, - {fields: ['id', 'nickname']}, myOptions); + const address = await models.Address.findById(addressFk ? addressFk : client.defaultAddressFk, + {fields: ['id', 'nickname', 'clientFk']}, myOptions); - const attributes = {clientFk, addressFk: client.defaultAddressFk, nickname: address.nickname}; + if (address.clientFk !== clientFk) throw new UserError('The address does not belong to the client'); + + const attributes = {clientFk, addressFk: address.id, nickname: address.nickname}; const tickets = []; const ticketIds = []; diff --git a/modules/ticket/back/models/ticket-methods.js b/modules/ticket/back/models/ticket-methods.js index 620b3e184..995fa2da3 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/travel/back/methods/travel/saveThermograph.js b/modules/travel/back/methods/travel/saveThermograph.js index 6f7e1c8bf..2517b0b8c 100644 --- a/modules/travel/back/methods/travel/saveThermograph.js +++ b/modules/travel/back/methods/travel/saveThermograph.js @@ -57,6 +57,10 @@ module.exports = Self => { arg: 'hasFileAttached', type: 'Boolean', description: 'True if has an attached file' + }, { + arg: 'agencyModeFk', + type: 'Number', + description: 'Carrier' }], returns: {type: 'object', root: true}, http: {path: `/:id/saveThermograph`, verb: 'POST'} @@ -76,6 +80,7 @@ module.exports = Self => { reference, description, hasFileAttached, + agencyModeFk, options ) => { const models = Self.app.models; @@ -119,6 +124,7 @@ module.exports = Self => { minTemperature, temperatureFk, warehouseFk: warehouseId, + agencyModeFk, }, myOptions); if (tx) await tx.commit(); diff --git a/modules/travel/back/methods/travel/specs/saveThermograph.spec.js b/modules/travel/back/methods/travel/specs/saveThermograph.spec.js index c2da4234e..0f5f248bf 100644 --- a/modules/travel/back/methods/travel/specs/saveThermograph.spec.js +++ b/modules/travel/back/methods/travel/specs/saveThermograph.spec.js @@ -9,6 +9,7 @@ describe('Thermograph saveThermograph()', () => { const maxTemperature = 30; const minTemperature = 10; const temperatureFk = 'COOL'; + const agencyModeFk = 1; let tx; let options; @@ -46,13 +47,16 @@ describe('Thermograph saveThermograph()', () => { null, null, null, - null, options + null, + agencyModeFk, + options ); expect(updatedThermograph.result).toEqual(state); expect(updatedThermograph.maxTemperature).toEqual(maxTemperature); expect(updatedThermograph.minTemperature).toEqual(minTemperature); expect(updatedThermograph.temperatureFk).toEqual(temperatureFk); + expect(updatedThermograph.agencyModeFk).toEqual(agencyModeFk); expect(updatedThermograph.dmsFk).toEqual(dmsFk); }); diff --git a/modules/travel/back/model-config.json b/modules/travel/back/model-config.json index 952ce0d20..e7a644180 100644 --- a/modules/travel/back/model-config.json +++ b/modules/travel/back/model-config.json @@ -22,5 +22,8 @@ }, "Temperature": { "dataSource": "vn" + }, + "AgencyModeIncoming": { + "dataSource": "vn" } -} \ No newline at end of file +} diff --git a/modules/travel/back/models/agency-mode-incoming.json b/modules/travel/back/models/agency-mode-incoming.json new file mode 100644 index 000000000..efefaf872 --- /dev/null +++ b/modules/travel/back/models/agency-mode-incoming.json @@ -0,0 +1,27 @@ +{ + "name": "AgencyModeIncoming", + "base": "VnModel", + "options": { + "mysql": { + "table": "agencyModeIncoming" + } + }, + "properties": { + "id": { + "type": "number", + "id": true, + "description": "Identifier" + }, + "name": { + "type": "string" + } + }, + "acls": [ + { + "accessType": "READ", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } + ] +} diff --git a/modules/travel/back/models/travel-thermograph.json b/modules/travel/back/models/travel-thermograph.json index cb0a9b4f8..79b692507 100644 --- a/modules/travel/back/models/travel-thermograph.json +++ b/modules/travel/back/models/travel-thermograph.json @@ -58,6 +58,11 @@ "type": "belongsTo", "model": "Thermograph", "foreignKey": "thermographFk" + }, + "agencyMode": { + "type": "belongsTo", + "model": "AgencyMode", + "foreignKey": "agencyModeFk" } } } diff --git a/modules/worker/back/methods/worker/filter.js b/modules/worker/back/methods/worker/filter.js index 087f080bd..da12dceca 100644 --- a/modules/worker/back/methods/worker/filter.js +++ b/modules/worker/back/methods/worker/filter.js @@ -166,12 +166,11 @@ module.exports = Self => { LEFT JOIN account.emailUser eu ON eu.userFk = u.id` ); - stmt.merge(conn.makeWhere(filter.where)); - stmts.push(stmt); + stmt.merge(conn.makeSuffix(filter)); + let itemsIndex = stmts.push(stmt) - 1; - const itemsIndex = stmts.push(stmt) - 1; - const sql = ParameterizedSQL.join(stmts, ';'); - const result = await conn.executeStmt(sql, myOptions); - return result[itemsIndex]; + let sql = ParameterizedSQL.join(stmts, ';'); + let result = await conn.executeStmt(sql); + return itemsIndex === 0 ? result : result[itemsIndex]; }; }; diff --git a/modules/worker/back/models/worker.js b/modules/worker/back/models/worker.js index 97e6a283c..4895a6107 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 fbba4c227..2715c233b 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", @@ -264,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": { @@ -317,7 +364,8 @@ "educationLevelFk", "originCountryFk", "maritalStatus", - "SSN" + "SSN", + "businessFk" ], "include": [ { @@ -328,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 72f8e2d1b..7f2025552 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 000000000..4b4bb7086 --- /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 000000000..b16d9bd50 --- /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 000000000..fbb1c74f1 --- /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 000000000..0c8f155d6 --- /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 000000000..129960ba6 --- /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 000000000..ad68ae0b6 --- /dev/null +++ b/print/templates/email/misallocation-warehouse/misallocation-warehouse.html @@ -0,0 +1,9 @@ + +
+
+

{{ $t('title') }}

+

{{$t('body')}}

+

{{action}}

+
+
+
diff --git a/print/templates/email/misallocation-warehouse/misallocation-warehouse.js b/print/templates/email/misallocation-warehouse/misallocation-warehouse.js new file mode 100755 index 000000000..f61cef819 --- /dev/null +++ b/print/templates/email/misallocation-warehouse/misallocation-warehouse.js @@ -0,0 +1,15 @@ +const Component = require(`vn-print/core/component`); +const emailBody = new Component('email-body'); + +module.exports = { + name: 'misallocation-warehouse', + components: { + 'email-body': emailBody.build(), + }, + props: { + action: { + type: String, + required: true + } + } +}; diff --git a/print/templates/reports/driver-route/driver-route.html b/print/templates/reports/driver-route/driver-route.html index e3a206656..8e69d6c65 100644 --- a/print/templates/reports/driver-route/driver-route.html +++ b/print/templates/reports/driver-route/driver-route.html @@ -90,8 +90,7 @@ {{ticket.id}} {{ticket.clientFk}} {{ticket.addressName}} - {{ticket.addressFk.toString().substr(0, ticket.addressFk.toString().length - 3)}} - {{ticket.addressFk.toString().substr(-3, 3)}} + {{ticket.addressFk.toString()}} {{ticket.packages}} {{ticket.itemPackingTypes}} diff --git a/print/templates/reports/invoice-incoterms/sql/incoterms.sql b/print/templates/reports/invoice-incoterms/sql/incoterms.sql index 535451674..77a7daad1 100644 --- a/print/templates/reports/invoice-incoterms/sql/incoterms.sql +++ b/print/templates/reports/invoice-incoterms/sql/incoterms.sql @@ -1,9 +1,9 @@ WITH tickets AS( -SELECT id, addressFk, packages, refFk +SELECT id, addressFk, packages, refFk, weight FROM vn.ticket WHERE refFk = ? ), volume AS( -SELECT SUM(volume) volume, MAX(weight)weight +SELECT SUM(sv.volume) volume, MAX(t.weight)weight FROM tickets t JOIN vn.saleVolume sv ON sv.ticketFk = t.id ), intrastat AS(