diff --git a/CHANGELOG.md b/CHANGELOG.md index 69f9f63b6..29d270a3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,19 +5,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2346.01] - 2023-11-16 + +### Added +### Changed +### Fixed + + ## [2342.01] - 2023-11-02 ### Added - (Usuarios -> Foto) Se muestra la foto del trabajador -### Changed ### Fixed - (Usuarios -> Historial) Abre el descriptor del usuario correctamente -## [2340.01] - 2023-10-05 -### Added -### Changed -### Fixed +## [2340.01] - 2023-10-05 ## [2338.01] - 2023-09-21 @@ -28,17 +31,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - (Trabajadores -> Calendario) Icono de check arreglado cuando pulsas un tipo de dia -### Fixed - ## [2336.01] - 2023-09-07 -### Added - -### Changed - -### Fixed - - ## [2334.01] - 2023-08-24 ### Added diff --git a/db/.archive/225201/00-invoiceOut_new.sql b/db/.archive/225201/00-invoiceOut_new.sql index 4c60b50bc..8e23fb43b 100644 --- a/db/.archive/225201/00-invoiceOut_new.sql +++ b/db/.archive/225201/00-invoiceOut_new.sql @@ -74,7 +74,7 @@ BEGIN clientFk, dued, companyFk, - cplusInvoiceType477Fk + siiTypeInvoiceOutFk ) SELECT 1, diff --git a/db/.archive/231001/02-invoiceOut_new.sql b/db/.archive/231001/02-invoiceOut_new.sql index d2b96eff7..d570dfb72 100644 --- a/db/.archive/231001/02-invoiceOut_new.sql +++ b/db/.archive/231001/02-invoiceOut_new.sql @@ -96,7 +96,7 @@ BEGIN clientFk, dued, companyFk, - cplusInvoiceType477Fk + siiTypeInvoiceOutFk ) SELECT 1, diff --git a/db/changes/231201/00-ACL.sql b/db/.archive/231201/00-ACL.sql similarity index 100% rename from db/changes/231201/00-ACL.sql rename to db/.archive/231201/00-ACL.sql diff --git a/db/changes/231201/00-chatRefactor.sql b/db/.archive/231201/00-chatRefactor.sql similarity index 100% rename from db/changes/231201/00-chatRefactor.sql rename to db/.archive/231201/00-chatRefactor.sql diff --git a/db/changes/231201/00-invoiceInSerial.sql b/db/.archive/231201/00-invoiceInSerial.sql similarity index 100% rename from db/changes/231201/00-invoiceInSerial.sql rename to db/.archive/231201/00-invoiceInSerial.sql diff --git a/db/changes/231201/00-itemType_isFragile.sql b/db/.archive/231201/00-itemType_isFragile.sql similarity index 100% rename from db/changes/231201/00-itemType_isFragile.sql rename to db/.archive/231201/00-itemType_isFragile.sql diff --git a/db/changes/231201/00-mailACL.sql b/db/.archive/231201/00-mailACL.sql similarity index 100% rename from db/changes/231201/00-mailACL.sql rename to db/.archive/231201/00-mailACL.sql diff --git a/db/changes/231201/00-operator.sql b/db/.archive/231201/00-operator.sql similarity index 100% rename from db/changes/231201/00-operator.sql rename to db/.archive/231201/00-operator.sql diff --git a/db/changes/231201/00-supplierAccount_deleteTriggers.sql b/db/.archive/231201/00-supplierAccount_deleteTriggers.sql similarity index 100% rename from db/changes/231201/00-supplierAccount_deleteTriggers.sql rename to db/.archive/231201/00-supplierAccount_deleteTriggers.sql diff --git a/db/changes/231201/00-ticket_getWarnings.sql b/db/.archive/231201/00-ticket_getWarnings.sql similarity index 100% rename from db/changes/231201/00-ticket_getWarnings.sql rename to db/.archive/231201/00-ticket_getWarnings.sql diff --git a/db/changes/231201/00-wagon.sql b/db/.archive/231201/00-wagon.sql similarity index 100% rename from db/changes/231201/00-wagon.sql rename to db/.archive/231201/00-wagon.sql diff --git a/db/changes/231202/00-delivery.sql b/db/.archive/231202/00-delivery.sql similarity index 100% rename from db/changes/231202/00-delivery.sql rename to db/.archive/231202/00-delivery.sql diff --git a/db/changes/231203/00-delivery.sql b/db/.archive/231203/00-delivery.sql similarity index 100% rename from db/changes/231203/00-delivery.sql rename to db/.archive/231203/00-delivery.sql diff --git a/db/changes/231204/00-rollbackDelivery.sql b/db/.archive/231204/00-rollbackDelivery.sql similarity index 100% rename from db/changes/231204/00-rollbackDelivery.sql rename to db/.archive/231204/00-rollbackDelivery.sql diff --git a/db/changes/231205/00-printQueueArgs.sql b/db/.archive/231205/00-printQueueArgs.sql similarity index 100% rename from db/changes/231205/00-printQueueArgs.sql rename to db/.archive/231205/00-printQueueArgs.sql diff --git a/db/changes/231401/00-claimBeginningAfterInsert.sql b/db/.archive/231401/00-claimBeginningAfterInsert.sql similarity index 100% rename from db/changes/231401/00-claimBeginningAfterInsert.sql rename to db/.archive/231401/00-claimBeginningAfterInsert.sql diff --git a/db/changes/231401/00-clientBeforeUpdate.sql b/db/.archive/231401/00-clientBeforeUpdate.sql similarity index 100% rename from db/changes/231401/00-clientBeforeUpdate.sql rename to db/.archive/231401/00-clientBeforeUpdate.sql diff --git a/db/changes/231401/00-hotfixDelivery.sql b/db/.archive/231401/00-hotfixDelivery.sql similarity index 100% rename from db/changes/231401/00-hotfixDelivery.sql rename to db/.archive/231401/00-hotfixDelivery.sql diff --git a/db/changes/231401/00-invoiceOutAfterInsert.sql b/db/.archive/231401/00-invoiceOutAfterInsert.sql similarity index 100% rename from db/changes/231401/00-invoiceOutAfterInsert.sql rename to db/.archive/231401/00-invoiceOutAfterInsert.sql diff --git a/db/changes/231401/00-negativeBases.sql b/db/.archive/231401/00-negativeBases.sql similarity index 100% rename from db/changes/231401/00-negativeBases.sql rename to db/.archive/231401/00-negativeBases.sql diff --git a/db/changes/231401/00-workerNotes.sql b/db/.archive/231401/00-workerNotes.sql similarity index 100% rename from db/changes/231401/00-workerNotes.sql rename to db/.archive/231401/00-workerNotes.sql diff --git a/db/changes/231402/00-negativeBases.sql b/db/.archive/231402/00-negativeBases.sql similarity index 100% rename from db/changes/231402/00-negativeBases.sql rename to db/.archive/231402/00-negativeBases.sql diff --git a/db/changes/231801/00-aclClientInforma.sql b/db/.archive/231801/00-aclClientInforma.sql similarity index 100% rename from db/changes/231801/00-aclClientInforma.sql rename to db/.archive/231801/00-aclClientInforma.sql diff --git a/db/changes/231801/00-acl_receiptEmail.sql b/db/.archive/231801/00-acl_receiptEmail.sql similarity index 100% rename from db/changes/231801/00-acl_receiptEmail.sql rename to db/.archive/231801/00-acl_receiptEmail.sql diff --git a/db/changes/231801/00-clientInforma.sql b/db/.archive/231801/00-clientInforma.sql similarity index 100% rename from db/changes/231801/00-clientInforma.sql rename to db/.archive/231801/00-clientInforma.sql diff --git a/db/changes/231801/00-client_setRatingAcl.sql b/db/.archive/231801/00-client_setRatingAcl.sql similarity index 100% rename from db/changes/231801/00-client_setRatingAcl.sql rename to db/.archive/231801/00-client_setRatingAcl.sql diff --git a/db/changes/231801/00-deleteProcs_refund.sql b/db/.archive/231801/00-deleteProcs_refund.sql similarity index 100% rename from db/changes/231801/00-deleteProcs_refund.sql rename to db/.archive/231801/00-deleteProcs_refund.sql diff --git a/db/changes/231801/00-deviceProduction.sql b/db/.archive/231801/00-deviceProduction.sql similarity index 100% rename from db/changes/231801/00-deviceProduction.sql rename to db/.archive/231801/00-deviceProduction.sql diff --git a/db/changes/231801/00-kkearEntryNotes.sql b/db/.archive/231801/00-kkearEntryNotes.sql similarity index 100% rename from db/changes/231801/00-kkearEntryNotes.sql rename to db/.archive/231801/00-kkearEntryNotes.sql diff --git a/db/changes/231801/00-newCompanyI18n.sql b/db/.archive/231801/00-newCompanyI18n.sql similarity index 100% rename from db/changes/231801/00-newCompanyI18n.sql rename to db/.archive/231801/00-newCompanyI18n.sql diff --git a/db/changes/231801/00-newTableWeb.sql b/db/.archive/231801/00-newTableWeb.sql similarity index 100% rename from db/changes/231801/00-newTableWeb.sql rename to db/.archive/231801/00-newTableWeb.sql diff --git a/db/changes/231801/00-observationEmailACL.sql b/db/.archive/231801/00-observationEmailACL.sql similarity index 100% rename from db/changes/231801/00-observationEmailACL.sql rename to db/.archive/231801/00-observationEmailACL.sql diff --git a/db/changes/231801/00-optimiceZoneEstimatedDelivery.sql b/db/.archive/231801/00-optimiceZoneEstimatedDelivery.sql similarity index 100% rename from db/changes/231801/00-optimiceZoneEstimatedDelivery.sql rename to db/.archive/231801/00-optimiceZoneEstimatedDelivery.sql diff --git a/db/changes/231801/00-saleTracking.sql b/db/.archive/231801/00-saleTracking.sql similarity index 100% rename from db/changes/231801/00-saleTracking.sql rename to db/.archive/231801/00-saleTracking.sql diff --git a/db/changes/231801/00-ticketConfig.sql b/db/.archive/231801/00-ticketConfig.sql similarity index 100% rename from db/changes/231801/00-ticketConfig.sql rename to db/.archive/231801/00-ticketConfig.sql diff --git a/db/changes/231801/00-updateIsVies.sql b/db/.archive/231801/00-updateIsVies.sql similarity index 100% rename from db/changes/231801/00-updateIsVies.sql rename to db/.archive/231801/00-updateIsVies.sql diff --git a/db/changes/231801/00-updateisViesClient.sql b/db/.archive/231801/00-updateisViesClient.sql similarity index 100% rename from db/changes/231801/00-updateisViesClient.sql rename to db/.archive/231801/00-updateisViesClient.sql diff --git a/db/changes/231801/00-userAcl.sql b/db/.archive/231801/00-userAcl.sql similarity index 100% rename from db/changes/231801/00-userAcl.sql rename to db/.archive/231801/00-userAcl.sql diff --git a/db/changes/231801/00-userRoleLog.sql b/db/.archive/231801/00-userRoleLog.sql similarity index 100% rename from db/changes/231801/00-userRoleLog.sql rename to db/.archive/231801/00-userRoleLog.sql diff --git a/db/changes/231801/01-viewCompany10L.sql b/db/.archive/231801/01-viewCompany10L.sql similarity index 100% rename from db/changes/231801/01-viewCompany10L.sql rename to db/.archive/231801/01-viewCompany10L.sql diff --git a/db/changes/232001/00-clientWorkerName.sql b/db/.archive/232001/00-clientWorkerName.sql similarity index 100% rename from db/changes/232001/00-clientWorkerName.sql rename to db/.archive/232001/00-clientWorkerName.sql diff --git a/db/changes/232001/00-createWorker.sql b/db/.archive/232001/00-createWorker.sql similarity index 100% rename from db/changes/232001/00-createWorker.sql rename to db/.archive/232001/00-createWorker.sql diff --git a/db/changes/232001/00-invoiceOut_new.sql b/db/.archive/232001/00-invoiceOut_new.sql similarity index 99% rename from db/changes/232001/00-invoiceOut_new.sql rename to db/.archive/232001/00-invoiceOut_new.sql index b4fc5c824..b497dffda 100644 --- a/db/changes/232001/00-invoiceOut_new.sql +++ b/db/.archive/232001/00-invoiceOut_new.sql @@ -96,7 +96,7 @@ BEGIN clientFk, dued, companyFk, - cplusInvoiceType477Fk + siiTypeInvoiceOutFk ) SELECT 1, diff --git a/db/changes/232001/00-wagon.sql b/db/.archive/232001/00-wagon.sql similarity index 100% rename from db/changes/232001/00-wagon.sql rename to db/.archive/232001/00-wagon.sql diff --git a/db/changes/232201/00-defaulterView.sql b/db/.archive/232201/00-defaulterView.sql similarity index 100% rename from db/changes/232201/00-defaulterView.sql rename to db/.archive/232201/00-defaulterView.sql diff --git a/db/changes/232201/00-procedurecanAdvance.sql b/db/.archive/232201/00-procedurecanAdvance.sql similarity index 100% rename from db/changes/232201/00-procedurecanAdvance.sql rename to db/.archive/232201/00-procedurecanAdvance.sql diff --git a/db/changes/232201/00-procedurecanbePostponed.sql b/db/.archive/232201/00-procedurecanbePostponed.sql similarity index 100% rename from db/changes/232201/00-procedurecanbePostponed.sql rename to db/.archive/232201/00-procedurecanbePostponed.sql diff --git a/db/changes/232201/00-workerConfigPayMethod.sql b/db/.archive/232201/00-workerConfigPayMethod.sql similarity index 100% rename from db/changes/232201/00-workerConfigPayMethod.sql rename to db/.archive/232201/00-workerConfigPayMethod.sql diff --git a/db/changes/232202/00-procedurecanAdvance.sql b/db/.archive/232202/00-procedurecanAdvance.sql similarity index 100% rename from db/changes/232202/00-procedurecanAdvance.sql rename to db/.archive/232202/00-procedurecanAdvance.sql diff --git a/db/changes/232202/00-procedurecanbePostponed.sql b/db/.archive/232202/00-procedurecanbePostponed.sql similarity index 100% rename from db/changes/232202/00-procedurecanbePostponed.sql rename to db/.archive/232202/00-procedurecanbePostponed.sql diff --git a/db/changes/232401/.gitkeep b/db/.archive/232401/.gitkeep similarity index 100% rename from db/changes/232401/.gitkeep rename to db/.archive/232401/.gitkeep diff --git a/db/changes/232401/00-buyConfig_travelConfig.sql b/db/.archive/232401/00-buyConfig_travelConfig.sql similarity index 100% rename from db/changes/232401/00-buyConfig_travelConfig.sql rename to db/.archive/232401/00-buyConfig_travelConfig.sql diff --git a/db/changes/232401/00-printer.sql b/db/.archive/232401/00-printer.sql similarity index 100% rename from db/changes/232401/00-printer.sql rename to db/.archive/232401/00-printer.sql diff --git a/db/changes/232401/00-ticket_warehouse.sql b/db/.archive/232401/00-ticket_warehouse.sql similarity index 100% rename from db/changes/232401/00-ticket_warehouse.sql rename to db/.archive/232401/00-ticket_warehouse.sql diff --git a/db/changes/232401/00-userPassExpired.sql b/db/.archive/232401/00-userPassExpired.sql similarity index 100% rename from db/changes/232401/00-userPassExpired.sql rename to db/.archive/232401/00-userPassExpired.sql diff --git a/db/changes/232402/00-hotFix_travelConfig.sql b/db/.archive/232402/00-hotFix_travelConfig.sql similarity index 100% rename from db/changes/232402/00-hotFix_travelConfig.sql rename to db/.archive/232402/00-hotFix_travelConfig.sql diff --git a/db/changes/232601/00-aclAccount.sql b/db/.archive/232601/00-aclAccount.sql similarity index 100% rename from db/changes/232601/00-aclAccount.sql rename to db/.archive/232601/00-aclAccount.sql diff --git a/db/changes/232601/00-aclInvoiceTickets.sql b/db/.archive/232601/00-aclInvoiceTickets.sql similarity index 100% rename from db/changes/232601/00-aclInvoiceTickets.sql rename to db/.archive/232601/00-aclInvoiceTickets.sql diff --git a/db/changes/232601/00-aclMailAliasAccount.sql b/db/.archive/232601/00-aclMailAliasAccount.sql similarity index 100% rename from db/changes/232601/00-aclMailAliasAccount.sql rename to db/.archive/232601/00-aclMailAliasAccount.sql diff --git a/db/changes/232601/00-aclMailForward.sql b/db/.archive/232601/00-aclMailForward.sql similarity index 100% rename from db/changes/232601/00-aclMailForward.sql rename to db/.archive/232601/00-aclMailForward.sql diff --git a/db/changes/232601/00-aclRole.sql b/db/.archive/232601/00-aclRole.sql similarity index 100% rename from db/changes/232601/00-aclRole.sql rename to db/.archive/232601/00-aclRole.sql diff --git a/db/changes/232601/00-aclVnUser.sql b/db/.archive/232601/00-aclVnUser.sql similarity index 100% rename from db/changes/232601/00-aclVnUser.sql rename to db/.archive/232601/00-aclVnUser.sql diff --git a/db/changes/232601/00-aclVnUser_renewToken.sql b/db/.archive/232601/00-aclVnUser_renewToken.sql similarity index 100% rename from db/changes/232601/00-aclVnUser_renewToken.sql rename to db/.archive/232601/00-aclVnUser_renewToken.sql diff --git a/db/changes/232601/00-entry_updateComission.sql b/db/.archive/232601/00-entry_updateComission.sql similarity index 100% rename from db/changes/232601/00-entry_updateComission.sql rename to db/.archive/232601/00-entry_updateComission.sql diff --git a/db/changes/232601/00-packingSiteAdvanced.sql b/db/.archive/232601/00-packingSiteAdvanced.sql similarity index 100% rename from db/changes/232601/00-packingSiteAdvanced.sql rename to db/.archive/232601/00-packingSiteAdvanced.sql diff --git a/db/changes/232601/00-salix.sql b/db/.archive/232601/00-salix.sql similarity index 100% rename from db/changes/232601/00-salix.sql rename to db/.archive/232601/00-salix.sql diff --git a/db/changes/232601/00-useSpecificsAcls.sql b/db/.archive/232601/00-useSpecificsAcls.sql similarity index 100% rename from db/changes/232601/00-useSpecificsAcls.sql rename to db/.archive/232601/00-useSpecificsAcls.sql diff --git a/db/changes/232601/01-invoiceOutPdf.sql b/db/.archive/232601/01-invoiceOutPdf.sql similarity index 100% rename from db/changes/232601/01-invoiceOutPdf.sql rename to db/.archive/232601/01-invoiceOutPdf.sql diff --git a/db/changes/232602/01-aclAddAlias.sql b/db/.archive/232602/01-aclAddAlias.sql similarity index 100% rename from db/changes/232602/01-aclAddAlias.sql rename to db/.archive/232602/01-aclAddAlias.sql diff --git a/db/changes/232801/00-authCode.sql b/db/.archive/232801/00-authCode.sql similarity index 100% rename from db/changes/232801/00-authCode.sql rename to db/.archive/232801/00-authCode.sql diff --git a/db/changes/232801/00-client_create.sql b/db/.archive/232801/00-client_create.sql similarity index 100% rename from db/changes/232801/00-client_create.sql rename to db/.archive/232801/00-client_create.sql diff --git a/db/changes/232801/00-client_create2.sql b/db/.archive/232801/00-client_create2.sql similarity index 100% rename from db/changes/232801/00-client_create2.sql rename to db/.archive/232801/00-client_create2.sql diff --git a/db/changes/232801/00-department.sql b/db/.archive/232801/00-department.sql similarity index 100% rename from db/changes/232801/00-department.sql rename to db/.archive/232801/00-department.sql diff --git a/db/changes/232801/00-fix_editCredit.sql b/db/.archive/232801/00-fix_editCredit.sql similarity index 100% rename from db/changes/232801/00-fix_editCredit.sql rename to db/.archive/232801/00-fix_editCredit.sql diff --git a/db/changes/232801/00-user.sql b/db/.archive/232801/00-user.sql similarity index 100% rename from db/changes/232801/00-user.sql rename to db/.archive/232801/00-user.sql diff --git a/db/changes/232802/01-aclWorkerDisable.sql b/db/.archive/232802/01-aclWorkerDisable.sql similarity index 100% rename from db/changes/232802/01-aclWorkerDisable.sql rename to db/.archive/232802/01-aclWorkerDisable.sql diff --git a/db/changes/234201/00-packagingFkviews.sql b/db/changes/234201/00-packagingFkviews.sql index abc7dc004..49d41c26c 100644 --- a/db/changes/234201/00-packagingFkviews.sql +++ b/db/changes/234201/00-packagingFkviews.sql @@ -1,3 +1,5 @@ +CREATE SCHEMA IF NOT EXISTS `vn2008`; + CREATE OR REPLACE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vn`.`awbVolume` diff --git a/db/changes/234601/.gitkeep b/db/changes/234601/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/db/changes/234601/00-ACLticketTrackingState.sql b/db/changes/234601/00-ACLticketTrackingState.sql new file mode 100644 index 000000000..ca6dce0c9 --- /dev/null +++ b/db/changes/234601/00-ACLticketTrackingState.sql @@ -0,0 +1,4 @@ +UPDATE `salix`.`ACL` + SET `property` = 'state', + `model` = 'Ticket' + WHERE `property` = 'changeState'; diff --git a/db/changes/234601/00-addressShortage.sql b/db/changes/234601/00-addressShortage.sql new file mode 100644 index 000000000..57c07d480 --- /dev/null +++ b/db/changes/234601/00-addressShortage.sql @@ -0,0 +1,98 @@ + +-- Place your SQL code here + +ALTER TABLE `vn`.`productionConfig` ADD shortageAddressFk int(11) COMMENT 'Consignatario por defecto para añadir un item de alta'; +ALTER TABLE `vn`.`productionConfig` ADD CONSTRAINT productionConfig_FK FOREIGN KEY (shortageAddressFk) REFERENCES vn.address(id) ON DELETE RESTRICT ON UPDATE CASCADE; + +ALTER TABLE `vn`.`sale` MODIFY COLUMN originalQuantity double(9,1) DEFAULT NULL NULL COMMENT 'Se utiliza para notificar a través de rocket los cambios de quantity'; + +INSERT INTO `salix`.`ACL` ( model, property, accessType, permission, principalType, principalId) VALUES( 'AddressShortage', '*', 'READ', 'ALLOW', 'ROLE', 'production'); + +-- vn.addressShortage definition + +CREATE TABLE `vn`.`addressShortage` ( + `addressFk` int(11) NOT NULL, + PRIMARY KEY (`addressFk`), + CONSTRAINT `addressShortage_FK` FOREIGN KEY (`addressFk`) REFERENCES `address` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci; + + +DELIMITER $$ + +CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_setVisibleDiscard`( + vItemFk INT, + vWarehouseFk INT, + vQuantity INT, + vAddressFk INT) +BEGIN +/** + * Procedimiento para dar dar de baja/alta un item, si vAddressFk es NULL se entiende que se da de alta y se toma el addressFk de la configuración + * + * @param vItemFk Identificador del ítem + * @param vWarehouseFk id del warehouse + * @param vQuantity a dar de alta/baja + * @param vAddressFk id address + */ + DECLARE vTicketFk INT; + DECLARE vClientFk INT; + DECLARE vDefaultCompanyFk INT; + DECLARE vCalc INT; + DECLARE vAddressShortage INT; + + SELECT barcodeToItem(vItemFk) INTO vItemFk; + + SELECT DEFAULT(companyFk) INTO vDefaultCompanyFk + FROM vn.ticket LIMIT 1; + + IF vAddressFk IS NULL THEN + SELECT pc.shortageAddressFk INTO vAddressShortage + FROM productionConfig pc ; + ELSE + SET vAddressShortage = vAddressFk; + END IF; + + SELECT a.clientFk INTO vClientFk + FROM address a + WHERE a.id = vAddressFk; + + SELECT t.id INTO vTicketFk + FROM ticket t + JOIN address a ON a.id = t.addressFk + JOIN ticketState ts ON ts.ticketFk = t.id + WHERE t.warehouseFk = vWarehouseFk + AND a.id = vAddressShortage + AND DATE(t.shipped) = util.VN_CURDATE() + AND ts.code = 'DELIVERED' + LIMIT 1; + + CALL cache.visible_refresh(vCalc, TRUE, vWarehouseFk); + + IF vTicketFk IS NULL THEN + CALL ticket_add( + vClientFk, + util.VN_CURDATE(), + vWarehouseFk, + vDefaultCompanyFk, + vAddressFk, + NULL, + NULL, + util.VN_CURDATE(), + account.myUser_getId(), + FALSE, + vTicketFk); + END IF; + + INSERT INTO sale(ticketFk, itemFk, concept, quantity) + SELECT vTicketFk, + vItemFk, + CONCAT(longName,' ', worker_getCode(), ' ', LEFT(CAST(util.VN_NOW() AS TIME),5)), + vQuantity + FROM item + WHERE id = vItemFk; + + UPDATE cache.visible + SET visible = visible - vQuantity + WHERE calc_id = vCalc + AND item_id = vItemFk; +END$$ +DELIMITER ; diff --git a/db/changes/233601/00-createClaimReader.sql b/db/changes/234601/00-claimViewerAcl.sql similarity index 86% rename from db/changes/233601/00-createClaimReader.sql rename to db/changes/234601/00-claimViewerAcl.sql index e913c0ed9..17d8d4ce0 100644 --- a/db/changes/233601/00-createClaimReader.sql +++ b/db/changes/234601/00-claimViewerAcl.sql @@ -21,11 +21,11 @@ DELETE FROM `salix`.`ACL` 'getSummary' ); -INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalid`) +INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`) VALUES ('Claim','filter','READ','ALLOW','ROLE','claimViewer'); -INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalid`) +INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`) VALUES ('Claim','find','READ','ALLOW','ROLE','claimViewer'); -INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalid`) +INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`) VALUES ('Claim','findById','READ','ALLOW','ROLE','claimViewer'); -INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalid`) - VALUES ('Claim','getSummary','READ','ALLOW','ROLE','claimViewer'); \ No newline at end of file +INSERT INTO `salix`.`ACL` (`model`,`property`,`accessType`,`permission`,`principalType`,`principalId`) + VALUES ('Claim','getSummary','READ','ALLOW','ROLE','claimViewer'); diff --git a/db/changes/234601/00-clientAfterUpdate.sql b/db/changes/234601/00-clientAfterUpdate.sql new file mode 100644 index 000000000..c6483813f --- /dev/null +++ b/db/changes/234601/00-clientAfterUpdate.sql @@ -0,0 +1,95 @@ +ALTER TABLE `vn`.`client` MODIFY COLUMN `credit` decimal(10,2) unsigned DEFAULT 0.00 NOT NULL; + +DELETE FROM `salix`.`ACL` WHERE `model` = 'Client' AND `property` = 'create'; + +DELIMITER $$ +CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`client_beforeUpdate` + BEFORE UPDATE ON `client` + FOR EACH ROW +BEGIN + DECLARE vText VARCHAR(255) DEFAULT NULL; + DECLARE vPayMethodFk INT; + + SET NEW.editorFk = account.myUser_getId(); + + IF NOT(NEW.credit <=> OLD.credit) THEN + INSERT INTO clientCredit + SET clientFk = NEW.id, + amount = NEW.credit, + workerFk = NEW.editorFk; + END IF; + -- Comprueba que el formato de los teléfonos es válido + + IF !(NEW.phone <=> OLD.phone) AND (NEW.phone <> '') THEN + CALL pbx.phone_isValid(NEW.phone); + END IF; + + IF !(NEW.mobile <=> OLD.mobile) AND (NEW.mobile <> '')THEN + CALL pbx.phone_isValid(NEW.mobile); + END IF; + + SELECT id INTO vPayMethodFk + FROM vn.payMethod + WHERE code = 'bankDraft'; + + IF NEW.payMethodFk = vPayMethodFk AND NEW.dueDay = 0 THEN + SET NEW.dueDay = 5; + END IF; + + -- Avisar al comercial si ha llegado la documentación sepa/core + + IF NEW.hasSepaVnl AND !OLD.hasSepaVnl THEN + SET vText = 'Sepa de VNL'; + END IF; + + IF NEW.hasCoreVnl AND !OLD.hasCoreVnl THEN + SET vText = 'Core de VNL'; + END IF; + + IF vText IS NOT NULL + THEN + INSERT INTO mail(receiver, replyTo, `subject`, body) + SELECT + CONCAT(IF(ac.id,u.name, 'jgallego'), '@verdnatura.es'), + 'administracion@verdnatura.es', + CONCAT('Cliente ', NEW.id), + CONCAT('Recibida la documentación: ', vText) + FROM worker w + LEFT JOIN account.user u ON w.id = u.id AND u.active + LEFT JOIN account.account ac ON ac.id = u.id + WHERE w.id = NEW.salesPersonFk; + END IF; + + IF NEW.salespersonFk IS NULL AND OLD.salespersonFk IS NOT NULL THEN + IF (SELECT COUNT(clientFk) + FROM clientProtected + WHERE clientFk = NEW.id + ) > 0 THEN + CALL util.throw("HAS_CLIENT_PROTECTED"); + END IF; + END IF; + + IF !(NEW.salesPersonFk <=> OLD.salesPersonFk) THEN + SET NEW.lastSalesPersonFk = IFNULL(NEW.salesPersonFk, OLD.salesPersonFk); + END IF; + + IF !(NEW.businessTypeFk <=> OLD.businessTypeFk) AND (NEW.businessTypeFk = 'individual' OR OLD.businessTypeFk = 'individual') THEN + SET NEW.isTaxDataChecked = 0; + END IF; +END$$ +DELIMITER ; + +DELIMITER $$ +CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`client_AfterInsert` + AFTER INSERT ON `client` + FOR EACH ROW +BEGIN + IF NEW.credit IS NOT NULL AND NEW.credit THEN + INSERT INTO clientCredit + SET clientFk = NEW.id, + workerFk = NEW.editorFk, + amount = NEW.credit; + END IF; +END$$ +DELIMITER ; + diff --git a/db/changes/234601/00-expeditionStateBeforeInsert.sql b/db/changes/234601/00-expeditionStateBeforeInsert.sql new file mode 100644 index 000000000..565b3ded3 --- /dev/null +++ b/db/changes/234601/00-expeditionStateBeforeInsert.sql @@ -0,0 +1,13 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`root`@`localhost` TRIGGER `vn`.`expeditionState_BeforeInsert` + BEFORE INSERT ON `expeditionState` + FOR EACH ROW +BEGIN + + SET NEW.userFk = IFNULL(NEW.userFk, account.myUser_getId()); + +END$$ +DELIMITER ; + + + diff --git a/db/changes/234601/00-ticketSetStateRefactor.sql b/db/changes/234601/00-ticketSetStateRefactor.sql new file mode 100644 index 000000000..9078ffb0e --- /dev/null +++ b/db/changes/234601/00-ticketSetStateRefactor.sql @@ -0,0 +1,55 @@ +DELIMITER $$ +CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_setState`( + vSelf INT, + vStateCode VARCHAR(255) COLLATE utf8_general_ci +) +BEGIN +/** + * Modifica el estado de un ticket si se cumplen las condiciones necesarias. + * + * @param vSelf el id del ticket + * @param vStateCode estado a modificar del ticket + */ + DECLARE vticketAlertLevel INT; + DECLARE vTicketStateCode VARCHAR(255); + DECLARE vCanChangeState BOOL; + DECLARE vPackedAlertLevel INT; + DECLARE vZoneFk INT; + + SELECT s.alertLevel, s.`code`, t.zoneFk + INTO vticketAlertLevel, vTicketStateCode, vZoneFk + FROM state s + JOIN ticketTracking tt ON tt.stateFk = s.id + JOIN ticket t ON t.id = tt.ticketFk + WHERE tt.ticketFk = vSelf + ORDER BY tt.created DESC + LIMIT 1; + + SELECT id INTO vPackedAlertLevel FROM alertLevel WHERE code = 'PACKED'; + + IF vStateCode = 'OK' AND vZoneFk IS NULL THEN + CALL util.throw('ASSIGN_ZONE_FIRST'); + END IF; + + SET vCanChangeState = ( + vStateCode <> 'ON_CHECKING' OR + vticketAlertLevel < vPackedAlertLevel + )AND NOT ( + vTicketStateCode IN ('CHECKED', 'CHECKING') + AND vStateCode IN ('PREPARED', 'ON_PREPARATION') + ); + + IF vCanChangeState THEN + INSERT INTO ticketTracking (stateFk, ticketFk, workerFk) + SELECT id, vSelf, account.myUser_getId() + FROM state + WHERE `code` = vStateCode COLLATE utf8_unicode_ci; + + IF vStateCode = 'PACKED' THEN + CALL ticket_doCmr(vSelf); + END IF; + ELSE + CALL util.throw('INCORRECT_TICKET_STATE'); + END IF; +END$$ +DELIMITER ; diff --git a/db/changes/234601/00-transferInvoice.sql b/db/changes/234601/00-transferInvoice.sql new file mode 100644 index 000000000..d9ae39464 --- /dev/null +++ b/db/changes/234601/00-transferInvoice.sql @@ -0,0 +1,6 @@ +INSERT INTO `salix`.`ACL` (model, property, accessType, permission, principalType, principalId) + VALUES + ('CplusRectificationType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('SiiTypeInvoiceOut', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('InvoiceCorrectionType', '*', 'READ', 'ALLOW', 'ROLE', 'administrative'), + ('InvoiceOut', 'transferInvoice', 'WRITE', 'ALLOW', 'ROLE', 'administrative'); diff --git a/db/changes/234602/00-roleSync.sql b/db/changes/234602/00-roleSync.sql new file mode 100644 index 000000000..7ce277748 --- /dev/null +++ b/db/changes/234602/00-roleSync.sql @@ -0,0 +1 @@ +CALL `account`.`role_sync`(); diff --git a/db/changes/234603/00-createSignInLogTable.sql b/db/changes/234603/00-createSignInLogTable.sql new file mode 100644 index 000000000..977de4646 --- /dev/null +++ b/db/changes/234603/00-createSignInLogTable.sql @@ -0,0 +1,19 @@ + + +-- +-- Table structure for table `signInLog` +-- + +DROP TABLE IF EXISTS `account`.`signInLog`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `account`.`signInLog` ( + `id` varchar(10) NOT NULL , + `userFk` int(10) unsigned DEFAULT NULL, + `creationDate` timestamp NULL DEFAULT current_timestamp(), + `ip` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL, + PRIMARY KEY (`id`), + KEY `userFk` (`userFk`), + CONSTRAINT `signInLog_ibfk_1` FOREIGN KEY (`userFk`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +); + diff --git a/db/dump/dumpedFixtures.sql b/db/dump/dumpedFixtures.sql index 2e1511b59..43eba7f24 100644 --- a/db/dump/dumpedFixtures.sql +++ b/db/dump/dumpedFixtures.sql @@ -275,13 +275,13 @@ INSERT INTO `cplusInvoiceType472` VALUES (1,'F1 - Factura'),(2,'F2 - Factura sim UNLOCK TABLES; -- --- Dumping data for table `cplusInvoiceType477` +-- Dumping data for table `siiTypeInvoiceOut` -- -LOCK TABLES `cplusInvoiceType477` WRITE; -/*!40000 ALTER TABLE `cplusInvoiceType477` DISABLE KEYS */; -INSERT INTO `cplusInvoiceType477` VALUES (1,'F1 - Factura'),(2,'F2 - Factura simplificada (ticket)'),(3,'F3 - Factura emitida en sustitución de facturas simplificadas facturadas y declaradas'),(4,'F4 - Asiento resumen de facturas'),(5,'R1 - Factura rectificativa (Art. 80.1, 80.2 y error fundado en derecho)'),(6,'R2 - Factura rectificativa (Art. 80.3)'),(7,'R3 - Factura rectificativa (Art. 80.4)'),(8,'R4 - Factura rectificativa (Resto)'),(9,'R5 - Factura rectificativa en facturas simplificadas'); -/*!40000 ALTER TABLE `cplusInvoiceType477` ENABLE KEYS */; +LOCK TABLES `siiTypeInvoiceOut` WRITE; +/*!40000 ALTER TABLE `siiTypeInvoiceOut` DISABLE KEYS */; +INSERT INTO `siiTypeInvoiceOut` VALUES (1,'F1 - Factura'),(2,'F2 - Factura simplificada (ticket)'),(3,'F3 - Factura emitida en sustitución de facturas simplificadas facturadas y declaradas'),(4,'F4 - Asiento resumen de facturas'),(5,'R1 - Factura rectificativa (Art. 80.1, 80.2 y error fundado en derecho)'),(6,'R2 - Factura rectificativa (Art. 80.3)'),(7,'R3 - Factura rectificativa (Art. 80.4)'),(8,'R4 - Factura rectificativa (Resto)'),(9,'R5 - Factura rectificativa en facturas simplificadas'); +/*!40000 ALTER TABLE `siiTypeInvoiceOut` ENABLE KEYS */; UNLOCK TABLES; -- diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index eeaa0fe7a..ae47a1eef 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -470,22 +470,22 @@ CREATE TEMPORARY TABLE tmp.address WHERE `defaultAddressFk` IS NULL; DROP TEMPORARY TABLE tmp.address; -INSERT INTO `vn`.`clientCredit`(`id`, `clientFk`, `workerFk`, `amount`, `created`) +INSERT INTO `vn`.`clientCredit`(`clientFk`, `workerFk`, `amount`, `created`) VALUES - (1 , 1101, 5, 300, DATE_ADD(util.VN_CURDATE(), INTERVAL -11 MONTH)), - (2 , 1101, 5, 900, DATE_ADD(util.VN_CURDATE(), INTERVAL -10 MONTH)), - (3 , 1101, 5, 800, DATE_ADD(util.VN_CURDATE(), INTERVAL -9 MONTH)), - (4 , 1101, 5, 700, DATE_ADD(util.VN_CURDATE(), INTERVAL -8 MONTH)), - (5 , 1101, 5, 600, DATE_ADD(util.VN_CURDATE(), INTERVAL -7 MONTH)), - (6 , 1101, 5, 500, DATE_ADD(util.VN_CURDATE(), INTERVAL -6 MONTH)), - (7 , 1101, 5, 400, DATE_ADD(util.VN_CURDATE(), INTERVAL -5 MONTH)), - (8 , 1101, 9, 300, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH)), - (9 , 1101, 9, 200, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH)), - (10, 1101, 9, 100, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH)), - (11, 1101, 9, 50 , DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH)), - (12, 1102, 9, 800, util.VN_CURDATE()), - (14, 1104, 9, 90 , util.VN_CURDATE()), - (15, 1105, 9, 90 , util.VN_CURDATE()); + (1101, 5, 300, DATE_ADD(util.VN_CURDATE(), INTERVAL -11 MONTH)), + (1101, 5, 900, DATE_ADD(util.VN_CURDATE(), INTERVAL -10 MONTH)), + (1101, 5, 800, DATE_ADD(util.VN_CURDATE(), INTERVAL -9 MONTH)), + (1101, 5, 700, DATE_ADD(util.VN_CURDATE(), INTERVAL -8 MONTH)), + (1101, 5, 600, DATE_ADD(util.VN_CURDATE(), INTERVAL -7 MONTH)), + (1101, 5, 500, DATE_ADD(util.VN_CURDATE(), INTERVAL -6 MONTH)), + (1101, 5, 400, DATE_ADD(util.VN_CURDATE(), INTERVAL -5 MONTH)), + (1101, 9, 300, DATE_ADD(util.VN_CURDATE(), INTERVAL -4 MONTH)), + (1101, 9, 200, DATE_ADD(util.VN_CURDATE(), INTERVAL -3 MONTH)), + (1101, 9, 100, DATE_ADD(util.VN_CURDATE(), INTERVAL -2 MONTH)), + (1101, 9, 50 , DATE_ADD(util.VN_CURDATE(), INTERVAL -1 MONTH)), + (1102, 9, 800, util.VN_CURDATE()), + (1104, 9, 90 , util.VN_CURDATE()), + (1105, 9, 90 , util.VN_CURDATE()); INSERT INTO `vn`.`clientCreditLimit`(`id`, `maxAmount`, `roleFk`) VALUES @@ -604,7 +604,7 @@ INSERT INTO `vn`.`invoiceOutSerial` (`code`, `description`, `isTaxed`, `taxAreaF INSERT INTO `vn`.`invoiceOut`(`id`, `serial`, `amount`, `issued`,`clientFk`, `created`, `companyFk`, `dued`, `booked`, `bankFk`, `hasPdf`) VALUES - (1, 'T', 1014.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), + (1, 'T', 1026.24, util.VN_CURDATE(), 1101, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (2, 'T', 121.36, util.VN_CURDATE(), 1102, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (3, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), (4, 'T', 8.88, util.VN_CURDATE(), 1103, util.VN_CURDATE(), 442, util.VN_CURDATE(), util.VN_CURDATE(), 1, 0), @@ -2758,7 +2758,7 @@ INSERT INTO `vn`.`sectorCollectionSaleGroup` (`sectorCollectionFk`, `saleGroupFk VALUES (1, 1); -INSERT INTO `vn`.`workerTimeControlConfig` (`id`, `dayBreak`, `dayBreakDriver`, `shortWeekBreak`, `longWeekBreak`, `weekScope`, `mailPass`, `mailHost`, `mailSuccessFolder`, `mailErrorFolder`, `mailUser`, `minHoursToBreak`, `breakHours`, `hoursCompleteWeek`, `startNightlyHours`, `endNightlyHours`, `maxTimePerDay`, `breakTime`, `timeToBreakTime`, `dayMaxTime`, `shortWeekDays`, `longWeekDays`, `teleworkingStart`, `teleworkingStartBreakTime`, `maxTimeToBreak`, `maxWorkShortCycle`, `maxWorkLongCycle`) +INSERT INTO `vn`.`workerTimeControlConfig` (`id`, `dayBreak`, `dayBreakDriver`, `shortWeekBreak`, `longWeekBreak`, `weekScope`, `mailPass`, `mailHost`, `mailSuccessFolder`, `mailErrorFolder`, `mailUser`, `minHoursToBreak`, `breakHours`, `hoursCompleteWeek`, `startNightlyHours`, `endNightlyHours`, `maxTimePerDay`, `breakTime`, `timeToBreakTime`, `dayMaxTime`, `shortWeekDays`, `longWeekDays`, `teleworkingStart`, `teleworkingStartBreakTime`, `maxTimeToBreak`, `maxWorkShortCycle`, `maxWorkLongCycle`) VALUES (1, 43200, 32400, 129600, 259200, 1080000, '', 'imap.verdnatura.es', 'Leidos.exito', 'Leidos.error', 'timeControl', 5.00, 0.33, 40, '22:00:00', '06:00:00', 72000, 1200, 18000, 72000, 6, 13, 28800, 32400, 3600, 561600, 950400); @@ -2981,3 +2981,9 @@ INSERT INTO vn.XDiario (id, ASIEN, FECHA, SUBCTA, CONTRA, CONCEPTO, EURODEBE, EU INSERT INTO `vn`.`mistakeType` (`id`, `description`) VALUES (1, 'Incorrect quantity'); + +INSERT INTO `vn`.`invoiceCorrectionType` (`id`, `description`) + VALUES + (1, 'Error in VAT calculation'), + (2, 'Error in sales details'), + (3, 'Error in customer data'); diff --git a/db/dump/structure.sql b/db/dump/structure.sql index b242821fc..3dab0c5a4 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -25993,13 +25993,13 @@ CREATE TABLE `cplusInvoiceType472` ( /*!40101 SET character_set_client = @saved_cs_client */; -- --- Table structure for table `cplusInvoiceType477` +-- Table structure for table `siiTypeInvoiceOut` -- -DROP TABLE IF EXISTS `cplusInvoiceType477`; +DROP TABLE IF EXISTS `siiTypeInvoiceOut`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; -CREATE TABLE `cplusInvoiceType477` ( +CREATE TABLE `siiTypeInvoiceOut` ( `id` int(10) unsigned NOT NULL, `description` varchar(255) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL, PRIMARY KEY (`id`) @@ -29450,16 +29450,16 @@ CREATE TABLE `invoiceCorrection` ( `correctingFk` int(10) unsigned NOT NULL COMMENT 'Factura rectificativa', `correctedFk` int(10) unsigned NOT NULL COMMENT 'Factura rectificada', `cplusRectificationTypeFk` int(10) unsigned NOT NULL, - `cplusInvoiceType477Fk` int(10) unsigned NOT NULL, + `siiTypeInvoiceOutFk` int(10) unsigned NOT NULL, `invoiceCorrectionTypeFk` int(11) NOT NULL DEFAULT 3, PRIMARY KEY (`correctingFk`), KEY `correctedFk_idx` (`correctedFk`), KEY `invoiceCorrection_ibfk_1_idx` (`cplusRectificationTypeFk`), - KEY `cplusInvoiceTyoeFk_idx` (`cplusInvoiceType477Fk`), + KEY `cplusInvoiceTyoeFk_idx` (`siiTypeInvoiceOutFk`), KEY `invoiceCorrectionTypeFk_idx` (`invoiceCorrectionTypeFk`), CONSTRAINT `corrected_fk` FOREIGN KEY (`correctedFk`) REFERENCES `invoiceOut` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `correcting_fk` FOREIGN KEY (`correctingFk`) REFERENCES `invoiceOut` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - CONSTRAINT `cplusInvoiceTyoeFk` FOREIGN KEY (`cplusInvoiceType477Fk`) REFERENCES `cplusInvoiceType477` (`id`) ON UPDATE CASCADE, + CONSTRAINT `cplusInvoiceTyoeFk` FOREIGN KEY (`siiTypeInvoiceOutFk`) REFERENCES `siiTypeInvoiceOut` (`id`) ON UPDATE CASCADE, CONSTRAINT `invoiceCorrectionType_Fk33` FOREIGN KEY (`invoiceCorrectionTypeFk`) REFERENCES `invoiceCorrectionType` (`id`) ON UPDATE CASCADE, CONSTRAINT `invoiceCorrection_ibfk_1` FOREIGN KEY (`cplusRectificationTypeFk`) REFERENCES `cplusRectificationType` (`id`) ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='Relacion entre las facturas rectificativas y las rectificadas.'; @@ -30130,7 +30130,7 @@ CREATE TABLE `invoiceOut` ( `companyFk` int(10) unsigned NOT NULL DEFAULT 442, `hasPdf` tinyint(3) unsigned NOT NULL DEFAULT 0, `booked` date DEFAULT NULL, - `cplusInvoiceType477Fk` int(10) unsigned NOT NULL DEFAULT 1, + `siiTypeInvoiceOutFk` int(10) unsigned NOT NULL DEFAULT 1, `cplusTaxBreakFk` int(10) unsigned NOT NULL DEFAULT 1, `cplusSubjectOpFk` int(10) unsigned NOT NULL DEFAULT 1, `cplusTrascendency477Fk` int(10) unsigned NOT NULL DEFAULT 1, @@ -30140,13 +30140,13 @@ CREATE TABLE `invoiceOut` ( KEY `Id_Cliente` (`clientFk`), KEY `empresa_id` (`companyFk`), KEY `Fecha` (`issued`), - KEY `Facturas_ibfk_2_idx` (`cplusInvoiceType477Fk`), + KEY `Facturas_ibfk_2_idx` (`siiTypeInvoiceOutFk`), KEY `Facturas_ibfk_3_idx` (`cplusSubjectOpFk`), KEY `Facturas_ibfk_4_idx` (`cplusTaxBreakFk`), KEY `Facturas_ibfk_5_idx` (`cplusTrascendency477Fk`), KEY `Facturas_idx_Vencimiento` (`dued`), KEY `invoiceOut_serial` (`serial`), - CONSTRAINT `invoiceOut_ibfk_2` FOREIGN KEY (`cplusInvoiceType477Fk`) REFERENCES `cplusInvoiceType477` (`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_serial` FOREIGN KEY (`serial`) REFERENCES `invoiceOutSerial` (`code`), @@ -30308,7 +30308,7 @@ CREATE TABLE `invoiceOutSerial` ( `isTaxed` tinyint(1) NOT NULL DEFAULT 1, `taxAreaFk` varchar(15) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT 'NATIONAL', `isCEE` tinyint(1) NOT NULL DEFAULT 0, - `cplusInvoiceType477Fk` int(10) unsigned DEFAULT 1, + `siiTypeInvoiceOutFk` int(10) unsigned DEFAULT 1, `footNotes` longtext DEFAULT NULL, `isRefEditable` tinyint(4) NOT NULL DEFAULT 0, `type` enum('global','quick') DEFAULT NULL, @@ -58288,7 +58288,7 @@ BEGIN io.cplusTrascendency477Fk AS TIPOCLAVE, io.cplusTaxBreakFk AS TIPOEXENCI, io.cplusSubjectOpFk AS TIPONOSUJE, - io.cplusInvoiceType477Fk AS TIPOFACT, + io.siiTypeInvoiceOutFk AS TIPOFACT, ic.cplusRectificationTypeFk AS TIPORECTIF, io.companyFk, RIGHT(io.ref, LENGTH(io.ref) - 1) AS invoiceNum, @@ -58868,7 +58868,7 @@ BEGIN clientFk, dued, companyFk, - cplusInvoiceType477Fk + siiTypeInvoiceOutFk ) SELECT 1, diff --git a/db/export-data.sh b/db/export-data.sh index 7d346b235..a516992d3 100755 --- a/db/export-data.sh +++ b/db/export-data.sh @@ -46,7 +46,7 @@ TABLES=( bookingPlanner businessType cplusInvoiceType472 - cplusInvoiceType477 + siiTypeInvoiceOut cplusRectificationType cplusSubjectOp cplusTaxBreak diff --git a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js index 23983a9c8..5e82306cc 100644 --- a/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js +++ b/e2e/paths/05-ticket/01-sale/02_edit_sale.spec.js @@ -212,7 +212,7 @@ describe('Ticket Edit sale path', () => { it('should log in as salesAssistant and navigate to ticket sales', async() => { await page.loginAndModule('salesAssistant', 'ticket'); - await page.accessToSearchResult('17'); + await page.accessToSearchResult('15'); await page.accessToSection('ticket.card.sale'); }); @@ -316,7 +316,7 @@ describe('Ticket Edit sale path', () => { }); it('should confirm the transfered quantity is the correct one', async() => { - const result = await page.waitToGetProperty(selectors.ticketSales.secondSaleQuantityCell, 'innerText'); + const result = await page.waitToGetProperty(selectors.ticketSales.firstSaleQuantityCell, 'innerText'); expect(result).toContain('20'); }); @@ -370,7 +370,7 @@ describe('Ticket Edit sale path', () => { await page.waitToClick(selectors.ticketSales.moveToNewTicketButton); const message = await page.waitForSnackbar(); - expect(message.text).toContain(`You can't create a ticket for a inactive client`); + expect(message.text).toContain(`You can't create a ticket for an inactive client`); await page.closePopup(); }); diff --git a/loopback/locale/en.json b/loopback/locale/en.json index 8dfed66f6..9f9961f57 100644 --- a/loopback/locale/en.json +++ b/loopback/locale/en.json @@ -23,7 +23,7 @@ "Agency cannot be blank": "Agency cannot be blank", "The IBAN does not have the correct format": "The IBAN does not have the correct format", "You can't make changes on the basic data of an confirmed order or with rows": "You can't make changes on the basic data of an confirmed order or with rows", - "You can't create a ticket for a inactive client": "You can't create a ticket for a inactive client", + "You can't create a ticket for an inactive client": "You can't create a ticket for an inactive client", "Worker cannot be blank": "Worker cannot be blank", "You must delete the claim id %d first": "You must delete the claim id %d first", "You don't have enough privileges": "You don't have enough privileges", @@ -188,7 +188,14 @@ "The ticket doesn't exist.": "The ticket doesn't exist.", "The sales do not exists": "The sales do not exists", "Ticket without Route": "Ticket without route", + "Select a different client": "Select a different client", + "Fill all the fields": "Fill all the fields", + "Error while generating PDF": "Error while generating PDF", + "Can't invoice to future": "Can't invoice to future", + "This ticket is already invoiced": "This ticket is already invoiced", + "Negative basis of tickets: 23": "Negative basis of tickets: 23", "Booking completed": "Booking complete", "The ticket is in preparation": "The ticket [{{ticketId}}]({{{ticketUrl}}}) of the sales person {{salesPersonId}} is in preparation", - "You can only add negative amounts in refund tickets": "You can only add negative amounts in refund tickets" -} + "You can only add negative amounts in refund tickets": "You can only add negative amounts in refund tickets", + "Try again": "Try again" +} \ No newline at end of file diff --git a/loopback/locale/es.json b/loopback/locale/es.json index 99f07fc05..239faff34 100644 --- a/loopback/locale/es.json +++ b/loopback/locale/es.json @@ -5,10 +5,10 @@ "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 invalido", + "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": "Is invalid", + "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", @@ -55,17 +55,17 @@ "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 basicos 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 esta permitido el uso de la letra ñ", + "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 a inactive client": "No puedes crear un ticket para un cliente inactivo", + "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": "Cuidad 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", @@ -102,8 +102,8 @@ "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": "This postal code is not valid", - "is invalid": "is invalid", + "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", @@ -112,8 +112,8 @@ "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 fín", - "Start date should be lower than end date": "La fecha de inicio debe ser menor que la fecha de fín", + "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", @@ -144,15 +144,15 @@ "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": "ORDER_ALREADY_CONFIRMED", + "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": "Role already assigned", - "Invalid role name": "Invalid role name", - "Role name must be written in camelCase": "Role name must be written in camelCase", - "Email already exists": "Email already exists", - "User already exists": "User already exists", - "Absence change notification on the labour calendar": "Notificacion de cambio de ausencia en el calendario laboral", + "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}}.", @@ -317,11 +317,14 @@ "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", - "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" + "quantityLessThanMin": "La cantidad no puede ser menor que la cantidad mínima" } diff --git a/modules/client/back/model-config.json b/modules/client/back/model-config.json index 296b5e6a7..0cc5df9a2 100644 --- a/modules/client/back/model-config.json +++ b/modules/client/back/model-config.json @@ -5,6 +5,9 @@ "AddressObservation": { "dataSource": "vn" }, + "AddressShortage": { + "dataSource": "vn" + }, "BankEntity": { "dataSource": "vn" }, diff --git a/modules/client/back/models/addressShortage.json b/modules/client/back/models/addressShortage.json new file mode 100644 index 000000000..1ae8d986c --- /dev/null +++ b/modules/client/back/models/addressShortage.json @@ -0,0 +1,22 @@ +{ + "name": "AddressShortage", + "base": "VnModel", + "options": { + "mysql": { + "table": "addressShortage" + } + }, + "properties": { + "addressFk": { + "type": "number", + "id": true + } + }, + "relations": { + "address": { + "type": "belongsTo", + "model": "Address", + "foreignKey": "addressFk" + } + } +} \ No newline at end of file diff --git a/modules/client/back/models/client-config.json b/modules/client/back/models/client-config.json index 90d47333d..6c5eae7d7 100644 --- a/modules/client/back/models/client-config.json +++ b/modules/client/back/models/client-config.json @@ -17,6 +17,9 @@ }, "maxCreditRows": { "type": "number" + }, + "defaultCredit": { + "type": "number" } } } \ No newline at end of file diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index e16e884cc..72b702779 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -450,14 +450,14 @@ module.exports = Self => { if (lastCredit && lastCredit.amount == 0) { const zeroCreditEditor = - await models.ACL.checkAccessAcl(accessToken, 'Client', 'zeroCreditEditor', 'WRITE'); + await models.ACL.checkAccessAcl(accessToken, 'Client', 'zeroCreditEditor', 'WRITE'); const lastCreditIsNotEditable = - await models.ACL.checkAccessAcl( - {req: {accessToken: {userId: lastCredit.workerFk}}}, - 'Client', - 'zeroCreditEditor', - 'WRITE' - ); + await models.ACL.checkAccessAcl( + {req: {accessToken: {userId: lastCredit.workerFk}}}, + 'Client', + 'zeroCreditEditor', + 'WRITE' + ); if (lastCreditIsNotEditable && !zeroCreditEditor) throw new UserError(`You can't change the credit set to zero from a financialBoss`); @@ -483,12 +483,6 @@ module.exports = Self => { if (userRequiredRoles <= 0) throw new UserError(`You don't have enough privileges to set this credit amount`); } - - await models.ClientCredit.create({ - amount: changes.credit, - clientFk: finalState.id, - workerFk: userId - }, ctx.options); }; Self.changeCreditManagement = async function changeCreditManagement(ctx, finalState, changes) { diff --git a/modules/client/back/models/specs/client.spec.js b/modules/client/back/models/specs/client.spec.js index 201d14bb4..bf134fbf9 100644 --- a/modules/client/back/models/specs/client.spec.js +++ b/modules/client/back/models/specs/client.spec.js @@ -62,13 +62,13 @@ describe('Client Model', () => { const options = {transaction: tx}; const ctx = {options}; - // Set credit to zero by a financialBoss const financialBoss = await models.VnUser.findOne({ where: {name: 'financialBoss'} }, options); ctx.options.accessToken = {userId: financialBoss.id}; - await models.Client.changeCredit(ctx, instance, {credit: 0}); + const testClient = await models.Client.findById(instance.id, options); + await testClient.updateAttributes({credit: 0}, ctx.options); const salesAssistant = await models.VnUser.findOne({ where: {name: 'salesAssistant'} diff --git a/modules/invoiceOut/back/methods/invoiceOut/makePdfAndNotify.js b/modules/invoiceOut/back/methods/invoiceOut/makePdfAndNotify.js index 1de15b666..4bba2498f 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/makePdfAndNotify.js +++ b/modules/invoiceOut/back/methods/invoiceOut/makePdfAndNotify.js @@ -23,7 +23,7 @@ module.exports = Self => { } }); - Self.makePdfAndNotify = async function(ctx, id, printerFk) { + Self.makePdfAndNotify = async function(ctx, id, printerFk, options) { const models = Self.app.models; options = typeof options == 'object' diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/refund.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/refund.spec.js index 6ecfe6015..22891f161 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/specs/refund.spec.js +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/refund.spec.js @@ -3,7 +3,7 @@ const LoopBackContext = require('loopback-context'); describe('InvoiceOut refund()', () => { const userId = 5; - const ctx = {req: {accessToken: userId}}; + const ctx = {req: {accessToken: userId}, args: {}}; const withWarehouse = true; const activeCtx = { accessToken: {userId: userId}, diff --git a/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js b/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js new file mode 100644 index 000000000..800a4ea83 --- /dev/null +++ b/modules/invoiceOut/back/methods/invoiceOut/specs/transferinvoice.spec.js @@ -0,0 +1,68 @@ + +const models = require('vn-loopback/server/server').models; +const LoopBackContext = require('loopback-context'); + +describe('InvoiceOut tranferInvoice()', () => { + const activeCtx = { + accessToken: {userId: 5}, + http: { + req: { + headers: {origin: 'http://localhost'} + } + } + }; + const ctx = {req: activeCtx}; + + beforeEach(() => { + spyOn(LoopBackContext, 'getCurrentContext').and.returnValue({ + active: activeCtx + }); + }); + + it('should return the id of the created issued invoice', async() => { + const tx = await models.InvoiceOut.beginTransaction({}); + const options = {transaction: tx}; + const args = { + id: '1', + ref: 'T4444444', + newClientFk: 1, + cplusRectificationId: 1, + siiTypeInvoiceOutId: 1, + invoiceCorrectionTypeId: 1 + }; + ctx.args = args; + try { + const result = await models.InvoiceOut.transferInvoice( + ctx, + options); + + expect(result).toBeDefined(); + await tx.rollback(); + } catch (e) { + await tx.rollback(); + throw e; + } + }); + + it('should throw an UserError when it is the same client', async() => { + const tx = await models.InvoiceOut.beginTransaction({}); + const options = {transaction: tx}; + const args = { + id: '1', + ref: 'T1111111', + newClientFk: 1101, + cplusRectificationId: 1, + siiTypeInvoiceOutId: 1, + invoiceCorrectionTypeId: 1 + }; + ctx.args = args; + try { + await models.InvoiceOut.transferInvoice( + ctx, + options); + } catch (e) { + expect(e.message).toBe(`Select a different client`); + await tx.rollback(); + } + }); +}); diff --git a/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js b/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js new file mode 100644 index 000000000..dde535c99 --- /dev/null +++ b/modules/invoiceOut/back/methods/invoiceOut/transferInvoice.js @@ -0,0 +1,111 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethodCtx('transferInvoice', { + description: 'Transfer an issued invoice to another client', + accessType: 'WRITE', + accepts: [ + { + arg: 'id', + type: 'number', + required: true, + description: 'Issued invoice id' + }, + { + arg: 'ref', + type: 'string', + required: true + }, + { + arg: 'newClientFk', + type: 'number', + required: true + }, + { + arg: 'cplusRectificationId', + type: 'number', + required: true + }, + { + arg: 'siiTypeInvoiceOutId', + type: 'number', + required: true + }, + { + arg: 'invoiceCorrectionTypeId', + type: 'number', + required: true + }, + ], + returns: { + type: 'boolean', + root: true + }, + http: { + path: '/transferInvoice', + verb: 'post' + } + }); + + Self.transferInvoice = async(ctx, options) => { + const models = Self.app.models; + const myOptions = {userId: ctx.req.accessToken.userId}; + const args = ctx.args; + let tx; + if (typeof options == 'object') + Object.assign(myOptions, options); + + const {clientFk} = await models.InvoiceOut.findById(args.id); + + if (clientFk == args.newClientFk) + throw new UserError(`Select a different client`); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + try { + const filterRef = {where: {refFk: args.ref}}; + const tickets = await models.Ticket.find(filterRef, myOptions); + const ticketsIds = tickets.map(ticket => ticket.id); + await models.Ticket.refund(ctx, ticketsIds, null, myOptions); + + const filterTicket = {where: {ticketFk: {inq: ticketsIds}}}; + + const services = await models.TicketService.find(filterTicket, myOptions); + const servicesIds = services.map(service => service.id); + + const sales = await models.Sale.find(filterTicket, myOptions); + const salesIds = sales.map(sale => sale.id); + + const clonedTickets = await models.Sale.clone(ctx, salesIds, servicesIds, null, false, false, myOptions); + const clonedTicketIds = []; + + for (const clonedTicket of clonedTickets) { + await clonedTicket.updateAttribute('clientFk', args.newClientFk, myOptions); + clonedTicketIds.push(clonedTicket.id); + } + + const invoiceIds = await models.Ticket.invoiceTickets(ctx, clonedTicketIds, myOptions); + const [invoiceId] = invoiceIds; + + await models.InvoiceCorrection.create({ + correctingFk: invoiceId, + correctedFk: args.id, + cplusRectificationTypeFk: args.cplusRectificationId, + siiTypeInvoiceOutFk: args.siiTypeInvoiceOutId, + invoiceCorrectionTypeFk: args.invoiceCorrectionTypeId + }, myOptions); + + if (tx) { + await tx.commit(); + await models.InvoiceOut.makePdfAndNotify(ctx, invoiceId, null); + } + + return invoiceId; + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + }; +}; diff --git a/modules/invoiceOut/back/model-config.json b/modules/invoiceOut/back/model-config.json index 9e8b119ab..9c7512429 100644 --- a/modules/invoiceOut/back/model-config.json +++ b/modules/invoiceOut/back/model-config.json @@ -31,5 +31,17 @@ }, "ZipConfig": { "dataSource": "vn" + }, + "CplusRectificationType": { + "dataSource": "vn" + }, + "InvoiceCorrectionType": { + "dataSource": "vn" + }, + "InvoiceCorrection": { + "dataSource": "vn" + }, + "SiiTypeInvoiceOut": { + "dataSource": "vn" } } diff --git a/modules/invoiceOut/back/models/cplus-invoice-type-477.json b/modules/invoiceOut/back/models/cplus-invoice-type-477.json new file mode 100644 index 000000000..17b312617 --- /dev/null +++ b/modules/invoiceOut/back/models/cplus-invoice-type-477.json @@ -0,0 +1,19 @@ +{ + "name": "SiiTypeInvoiceOut", + "base": "VnModel", + "options": { + "mysql": { + "table": "siiTypeInvoiceOut" + } + }, + "properties": { + "id": { + "id": true, + "type": "number", + "description": "Identifier" + }, + "description": { + "type": "string" + } + } +} diff --git a/modules/invoiceOut/back/models/cplus-rectification-type.json b/modules/invoiceOut/back/models/cplus-rectification-type.json new file mode 100644 index 000000000..e7bfb957f --- /dev/null +++ b/modules/invoiceOut/back/models/cplus-rectification-type.json @@ -0,0 +1,19 @@ +{ + "name": "CplusRectificationType", + "base": "VnModel", + "options": { + "mysql": { + "table": "cplusRectificationType" + } + }, + "properties": { + "id": { + "id": true, + "type": "number", + "description": "Identifier" + }, + "description": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/modules/invoiceOut/back/models/invoice-correction-type.json b/modules/invoiceOut/back/models/invoice-correction-type.json new file mode 100644 index 000000000..ad3f034ea --- /dev/null +++ b/modules/invoiceOut/back/models/invoice-correction-type.json @@ -0,0 +1,19 @@ +{ + "name": "InvoiceCorrectionType", + "base": "VnModel", + "options": { + "mysql": { + "table": "invoiceCorrectionType" + } + }, + "properties": { + "id": { + "id": true, + "type": "number", + "description": "Identifier" + }, + "description": { + "type": "string" + } + } +} \ No newline at end of file diff --git a/modules/invoiceOut/back/models/invoice-correction.json b/modules/invoiceOut/back/models/invoice-correction.json new file mode 100644 index 000000000..43e4f07ef --- /dev/null +++ b/modules/invoiceOut/back/models/invoice-correction.json @@ -0,0 +1,28 @@ +{ + "name": "InvoiceCorrection", + "base": "VnModel", + "options": { + "mysql": { + "table": "invoiceCorrection" + } + }, + "properties": { + "correctingFk": { + "id": true, + "type": "number", + "description": "Identifier" + }, + "correctedFk": { + "type": "number" + }, + "cplusRectificationTypeFk": { + "type": "number" + }, + "siiTypeInvoiceOutFk": { + "type": "number" + }, + "invoiceCorrectionTypeFk": { + "type": "number" + } + } +} diff --git a/modules/invoiceOut/back/models/invoice-out.js b/modules/invoiceOut/back/models/invoice-out.js index d3aaf3b3d..ca77c856f 100644 --- a/modules/invoiceOut/back/models/invoice-out.js +++ b/modules/invoiceOut/back/models/invoice-out.js @@ -23,6 +23,7 @@ module.exports = Self => { require('../methods/invoiceOut/getInvoiceDate')(Self); require('../methods/invoiceOut/negativeBases')(Self); require('../methods/invoiceOut/negativeBasesCsv')(Self); + require('../methods/invoiceOut/transferInvoice')(Self); Self.filePath = async function(id, options) { const fields = ['ref', 'issued']; diff --git a/modules/invoiceOut/front/descriptor-menu/index.html b/modules/invoiceOut/front/descriptor-menu/index.html index 106f8e3cc..0052f0c03 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.html +++ b/modules/invoiceOut/front/descriptor-menu/index.html @@ -1,3 +1,19 @@ + + + + + + + + Transfer invoice to... + Confirm + + + +
+ + + + #{{id}} - {{::name}} + + + + + {{::description}} + + + + + + + + + +
+
+ + + +
diff --git a/modules/invoiceOut/front/descriptor-menu/index.js b/modules/invoiceOut/front/descriptor-menu/index.js index 38c3c9434..d3862a753 100644 --- a/modules/invoiceOut/front/descriptor-menu/index.js +++ b/modules/invoiceOut/front/descriptor-menu/index.js @@ -125,6 +125,22 @@ class Controller extends Section { this.$state.go('ticket.card.sale', {id: refundTicket.id}); }); } + + transferInvoice() { + const params = { + id: this.invoiceOut.id, + ref: this.invoiceOut.ref, + newClientFk: this.invoiceOut.client.id, + cplusRectificationId: this.cplusRectificationType, + siiTypeInvoiceOutId: this.siiTypeInvoiceOut, + invoiceCorrectionTypeId: this.invoiceCorrectionType + }; + this.$http.post(`InvoiceOuts/transferInvoice`, params).then(res => { + const invoiceId = res.data; + this.vnApp.showSuccess(this.$t('Invoice trasfered!')); + this.$state.go('invoiceOut.card.summary', {id: invoiceId}); + }); + } } Controller.$inject = ['$element', '$scope', 'vnReport', 'vnEmail']; diff --git a/modules/invoiceOut/front/descriptor-menu/locale/en.yml b/modules/invoiceOut/front/descriptor-menu/locale/en.yml index d299155d7..8fad5f25e 100644 --- a/modules/invoiceOut/front/descriptor-menu/locale/en.yml +++ b/modules/invoiceOut/front/descriptor-menu/locale/en.yml @@ -1 +1,3 @@ The following refund tickets have been created: "The following refund tickets have been created: {{ticketIds}}" +Transfer invoice to...: Transfer invoice to... +Cplus Type: Cplus Type \ No newline at end of file diff --git a/modules/invoiceOut/front/descriptor-menu/locale/es.yml b/modules/invoiceOut/front/descriptor-menu/locale/es.yml index 393efd58c..0f74b5fec 100644 --- a/modules/invoiceOut/front/descriptor-menu/locale/es.yml +++ b/modules/invoiceOut/front/descriptor-menu/locale/es.yml @@ -21,3 +21,5 @@ The invoice PDF document has been regenerated: El documento PDF de la factura ha The email can't be empty: El correo no puede estar vacío The following refund tickets have been created: "Se han creado los siguientes tickets de abono: {{ticketIds}}" Refund...: Abono... +Transfer invoice to...: Transferir factura a... +Cplus Type: Cplus Tipo diff --git a/modules/invoiceOut/front/descriptor-menu/style.scss b/modules/invoiceOut/front/descriptor-menu/style.scss index b68301961..9e4cf4297 100644 --- a/modules/invoiceOut/front/descriptor-menu/style.scss +++ b/modules/invoiceOut/front/descriptor-menu/style.scss @@ -21,4 +21,10 @@ vn-invoice-out-descriptor-menu { font-size: 1.75rem; } } -} \ No newline at end of file + +} +@media screen and (min-width: 1000px) { + .transferInvoice { + min-width: $width-md; + } +} diff --git a/modules/item/back/methods/item/setVisibleDiscard.js b/modules/item/back/methods/item/setVisibleDiscard.js index 08cc507c3..16cef6baf 100644 --- a/modules/item/back/methods/item/setVisibleDiscard.js +++ b/modules/item/back/methods/item/setVisibleDiscard.js @@ -20,8 +20,7 @@ module.exports = Self => { }, { arg: 'addressFk', - type: 'Number', - required: true, + type: 'Any', description: 'The address id' }], http: { diff --git a/modules/ticket/back/locale/sale-group/en.yml b/modules/ticket/back/locale/sale-group/en.yml new file mode 100644 index 000000000..d88231647 --- /dev/null +++ b/modules/ticket/back/locale/sale-group/en.yml @@ -0,0 +1,10 @@ +name: saleGroup +columns: + id: id + created: created + userFk: user + parkingFk: parking + sectorFk: sector + ticketFk: ticket + editorFk: editor + diff --git a/modules/ticket/back/locale/sale-group/es.yml b/modules/ticket/back/locale/sale-group/es.yml new file mode 100644 index 000000000..9efbe7148 --- /dev/null +++ b/modules/ticket/back/locale/sale-group/es.yml @@ -0,0 +1,10 @@ +name: saleGroup +columns: + id: id + created: creado + userFk: usuario + parkingFk: parking + sectorFk: sector + ticketFk: ticket + editorFk: editor + diff --git a/modules/ticket/back/methods/expedition-state/addExpeditionState.js b/modules/ticket/back/methods/expedition-state/addExpeditionState.js index f1199f188..8eab1a838 100644 --- a/modules/ticket/back/methods/expedition-state/addExpeditionState.js +++ b/modules/ticket/back/methods/expedition-state/addExpeditionState.js @@ -1,7 +1,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { - Self.remoteMethod('addExpeditionState', { + Self.remoteMethodCtx('addExpeditionState', { description: 'Update an expedition state', accessType: 'WRITE', accepts: [ @@ -12,18 +12,15 @@ module.exports = Self => { description: 'Array of objects containing expeditionFk and stateCode' } ], - returns: { - type: 'boolean', - root: true - }, http: { path: `/addExpeditionState`, verb: 'post' } }); - Self.addExpeditionState = async(expeditions, options) => { + Self.addExpeditionState = async(ctx, expeditions, options) => { const models = Self.app.models; + const userId = ctx.req.accessToken.userId; let tx; const myOptions = {}; if (typeof options == 'object') @@ -51,6 +48,7 @@ module.exports = Self => { await models.ExpeditionState.create({ expeditionFk: expedition.expeditionFk, typeFk, + userFk: userId, }, myOptions); } diff --git a/modules/ticket/back/methods/expedition-state/specs/addExpeditionState.spec.js b/modules/ticket/back/methods/expedition-state/specs/addExpeditionState.spec.js index 819a43a60..6c7739006 100644 --- a/modules/ticket/back/methods/expedition-state/specs/addExpeditionState.spec.js +++ b/modules/ticket/back/methods/expedition-state/specs/addExpeditionState.spec.js @@ -1,9 +1,9 @@ const models = require('vn-loopback/server/server').models; describe('expeditionState addExpeditionState()', () => { + const ctx = {req: {accessToken: {userId: 9}}}; it('should update the expedition states', async() => { const tx = await models.ExpeditionState.beginTransaction({}); - try { const options = {transaction: tx}; const payload = [ @@ -13,7 +13,7 @@ describe('expeditionState addExpeditionState()', () => { }, ]; - await models.ExpeditionState.addExpeditionState(payload, options); + await models.ExpeditionState.addExpeditionState(ctx, payload, options); const expeditionState = await models.ExpeditionState.findOne({ where: {id: 5} @@ -39,7 +39,7 @@ describe('expeditionState addExpeditionState()', () => { stateCode: 'DUMMY' } ]; - await models.ExpeditionState.addExpeditionState(payload, options); + await models.ExpeditionState.addExpeditionState(ctx, payload, options); await tx.rollback(); } catch (e) { @@ -62,7 +62,7 @@ describe('expeditionState addExpeditionState()', () => { } ]; - await models.ExpeditionState.addExpeditionState(payload, options); + await models.ExpeditionState.addExpeditionState(ctx, payload, options); await tx.rollback(); } catch (e) { diff --git a/modules/ticket/back/methods/sale/clone.js b/modules/ticket/back/methods/sale/clone.js new file mode 100644 index 000000000..a5ccb6de4 --- /dev/null +++ b/modules/ticket/back/methods/sale/clone.js @@ -0,0 +1,122 @@ +module.exports = Self => { + Self.clone = async(ctx, salesIds, servicesIds, withWarehouse, group, negative, options) => { + const models = Self.app.models; + const myOptions = {}; + let tx; + const newTickets = []; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + const salesFilter = { + where: {id: {inq: salesIds}}, + include: { + relation: 'components', + scope: { + fields: ['saleFk', 'componentFk', 'value'] + } + } + }; + const sales = await models.Sale.find(salesFilter, myOptions); + let ticketsIds = [...new Set(sales.map(sale => sale.ticketFk))]; + + const mappedTickets = new Map(); + + if (group) ticketsIds = [ticketsIds[0]]; + + for (let ticketId of ticketsIds) { + const newTicket = await createTicket( + ctx, + ticketId, + withWarehouse, + negative, + myOptions + ); + newTickets.push(newTicket); + mappedTickets.set(ticketId, newTicket.id); + } + + for (const sale of sales) { + const newTicketId = mappedTickets.get(sale.ticketFk); + + const createdSale = await models.Sale.create({ + ticketFk: newTicketId, + itemFk: sale.itemFk, + quantity: negative ? - sale.quantity : sale.quantity, + concept: sale.concept, + price: sale.price, + discount: sale.discount, + }, myOptions); + + const components = sale.components(); + for (const component of components) + component.saleFk = createdSale.id; + + await models.SaleComponent.create(components, myOptions); + } + + if (servicesIds && servicesIds.length) { + const servicesFilter = { + where: {id: {inq: servicesIds}} + }; + const services = await models.TicketService.find(servicesFilter, myOptions); + + for (const service of services) { + const newTicketId = mappedTickets.get(service.ticketFk); + + await models.TicketService.create({ + description: service.description, + quantity: negative ? - service.quantity : service.quantity, + price: service.price, + taxClassFk: service.taxClassFk, + ticketFk: newTicketId, + ticketServiceTypeFk: service.ticketServiceTypeFk, + }, myOptions); + } + } + + if (tx) await tx.commit(); + + return newTickets; + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + + async function createTicket( + ctx, + ticketId, + withWarehouse, + negative, + myOptions + ) { + const models = Self.app.models; + const now = Date.vnNew(); + + const ticket = await models.Ticket.findById(ticketId, null, myOptions); + ctx.args.clientId = ticket.clientFk; + ctx.args.shipped = now; + ctx.args.landed = now; + ctx.args.warehouseId = withWarehouse ? ticket.warehouseFk : null; + ctx.args.companyId = ticket.companyFk; + ctx.args.addressId = ticket.addressFk; + + const newTicket = await models.Ticket.new(ctx, myOptions); + + if (negative) { + await models.TicketRefund.create({ + originalTicketFk: ticketId, + refundTicketFk: newTicket.id + }, myOptions); + } + + return newTicket; + } + }; +}; diff --git a/modules/ticket/back/methods/sale/refund.js b/modules/ticket/back/methods/sale/refund.js index 03302550e..17b70f12b 100644 --- a/modules/ticket/back/methods/sale/refund.js +++ b/modules/ticket/back/methods/sale/refund.js @@ -5,7 +5,8 @@ module.exports = Self => { accepts: [ { arg: 'salesIds', - type: ['number'] + type: ['number'], + required: true }, { arg: 'servicesIds', @@ -40,122 +41,23 @@ module.exports = Self => { myOptions.transaction = tx; } - let refundTicket = null; try { - const refundAgencyMode = await models.AgencyMode.findOne({ - include: { - relation: 'zones', - scope: { - limit: 1, - field: ['id', 'name'] - } - }, - where: {code: 'refund'} - }, myOptions); - - const refoundZoneId = refundAgencyMode.zones()[0].id; - - if (salesIds.length) { - const salesFilter = { - where: {id: {inq: salesIds}}, - include: { - relation: 'components', - scope: { - fields: ['saleFk', 'componentFk', 'value'] - } - } - }; - const sales = await models.Sale.find(salesFilter, myOptions); - const ticketsIds = [...new Set(sales.map(sale => sale.ticketFk))]; - - const now = Date.vnNew(); - const [firstTicketId] = ticketsIds; - - // eslint-disable-next-line max-len - refundTicket = await createTicketRefund(firstTicketId, now, refundAgencyMode, refoundZoneId, withWarehouse, myOptions); - - for (const sale of sales) { - const createdSale = await models.Sale.create({ - ticketFk: refundTicket.id, - itemFk: sale.itemFk, - quantity: - sale.quantity, - concept: sale.concept, - price: sale.price, - discount: sale.discount, - }, myOptions); - - const components = sale.components(); - for (const component of components) - component.saleFk = createdSale.id; - - await models.SaleComponent.create(components, myOptions); - } - } - if (!refundTicket) { - const servicesFilter = { - where: {id: {inq: servicesIds}} - }; - const services = await models.TicketService.find(servicesFilter, myOptions); - const firstTicketId = services[0].ticketFk; - - const now = Date.vnNew(); - - // eslint-disable-next-line max-len - refundTicket = await createTicketRefund(firstTicketId, now, refundAgencyMode, refoundZoneId, withWarehouse, myOptions); - } - - if (servicesIds && servicesIds.length > 0) { - const servicesFilter = { - where: {id: {inq: servicesIds}} - }; - const services = await models.TicketService.find(servicesFilter, myOptions); - for (const service of services) { - await models.TicketService.create({ - description: service.description, - quantity: - service.quantity, - price: service.price, - taxClassFk: service.taxClassFk, - ticketFk: refundTicket.id, - ticketServiceTypeFk: service.ticketServiceTypeFk, - }, myOptions); - } - } - - const query = `CALL vn.ticket_recalc(?, NULL)`; - await Self.rawSql(query, [refundTicket.id], myOptions); + const refundsTicket = await models.Sale.clone( + ctx, + salesIds, + servicesIds, + withWarehouse, + false, + true, + myOptions + ); if (tx) await tx.commit(); - return refundTicket; + return refundsTicket[0]; } catch (e) { if (tx) await tx.rollback(); throw e; } }; - - async function createTicketRefund(ticketId, now, refundAgencyMode, refoundZoneId, withWarehouse, myOptions) { - const models = Self.app.models; - - const filter = {include: {relation: 'address'}}; - const ticket = await models.Ticket.findById(ticketId, filter, myOptions); - - const refundTicket = await models.Ticket.create({ - clientFk: ticket.clientFk, - shipped: now, - addressFk: ticket.address().id, - agencyModeFk: refundAgencyMode.id, - nickname: ticket.address().nickname, - warehouseFk: withWarehouse ? ticket.warehouseFk : null, - companyFk: ticket.companyFk, - landed: now, - zoneFk: refoundZoneId - }, myOptions); - - await models.TicketRefund.create({ - refundTicketFk: refundTicket.id, - originalTicketFk: ticket.id, - }, myOptions); - - return refundTicket; - } }; diff --git a/modules/ticket/back/methods/sale/specs/refund.spec.js b/modules/ticket/back/methods/sale/specs/refund.spec.js index b81f7f84d..08eb1fabd 100644 --- a/modules/ticket/back/methods/sale/specs/refund.spec.js +++ b/modules/ticket/back/methods/sale/specs/refund.spec.js @@ -3,7 +3,7 @@ const LoopBackContext = require('loopback-context'); describe('Sale refund()', () => { const userId = 5; - const ctx = {req: {accessToken: userId}}; + const ctx = {req: {accessToken: userId}, args: {}}; const activeCtx = { accessToken: {userId}, }; @@ -40,6 +40,7 @@ describe('Sale refund()', () => { try { const options = {transaction: tx}; + const ticketsBefore = await models.Ticket.find({}, options); const ticket = await models.Sale.refund(ctx, salesIds, servicesIds, withWarehouse, options); @@ -61,12 +62,13 @@ describe('Sale refund()', () => { } ] }, options); - + const ticketsAfter = await models.Ticket.find({}, options); const salesLength = refundedTicket.ticketSales().length; const componentsLength = refundedTicket.ticketSales()[0].components().length; expect(refundedTicket).toBeDefined(); - expect(salesLength).toEqual(2); + expect(salesLength).toEqual(1); + expect(ticketsBefore.length).toEqual(ticketsAfter.length - 2); expect(componentsLength).toEqual(4); await tx.rollback(); diff --git a/modules/ticket/back/methods/ticket-tracking/setDelivered.js b/modules/ticket/back/methods/ticket-tracking/setDelivered.js index df482fd01..d3cdb192f 100644 --- a/modules/ticket/back/methods/ticket-tracking/setDelivered.js +++ b/modules/ticket/back/methods/ticket-tracking/setDelivered.js @@ -47,7 +47,7 @@ module.exports = Self => { const promises = []; for (const id of ticketIds) { - const promise = models.TicketTracking.changeState(ctx, { + const promise = await models.Ticket.state(ctx, { stateFk: state.id, workerFk: worker.id, ticketFk: id diff --git a/modules/ticket/back/methods/ticket/invoiceTickets.js b/modules/ticket/back/methods/ticket/invoiceTickets.js index ca1bf15fb..fa3ee93af 100644 --- a/modules/ticket/back/methods/ticket/invoiceTickets.js +++ b/modules/ticket/back/methods/ticket/invoiceTickets.js @@ -77,9 +77,10 @@ module.exports = function(Self) { if (tx) await tx.rollback(); throw e; } - - for (const invoiceId of invoicesIds) - await models.InvoiceOut.makePdfAndNotify(ctx, invoiceId, null); + if (tx) { + for (const invoiceId of invoicesIds) + await models.InvoiceOut.makePdfAndNotify(ctx, invoiceId, null); + } return invoicesIds; }; diff --git a/modules/ticket/back/methods/ticket/new.js b/modules/ticket/back/methods/ticket/new.js index 0f5c323ed..288d38d77 100644 --- a/modules/ticket/back/methods/ticket/new.js +++ b/modules/ticket/back/methods/ticket/new.js @@ -96,7 +96,7 @@ module.exports = Self => { if (address.client().type().code === 'normal' && (!agencyMode || agencyMode.code != 'refund')) { const canCreateTicket = await models.Client.canCreateTicket(args.clientId, myOptions); if (!canCreateTicket) - throw new UserError(`You can't create a ticket for a inactive client`); + throw new UserError(`You can't create a ticket for an inactive client`); } if (!args.shipped && args.landed) { diff --git a/modules/ticket/back/methods/ticket/refund.js b/modules/ticket/back/methods/ticket/refund.js index c99b6aa83..758384ae2 100644 --- a/modules/ticket/back/methods/ticket/refund.js +++ b/modules/ticket/back/methods/ticket/refund.js @@ -39,7 +39,6 @@ module.exports = Self => { try { const filter = {where: {ticketFk: {inq: ticketsIds}}}; - const sales = await models.Sale.find(filter, myOptions); const salesIds = sales.map(sale => sale.id); diff --git a/modules/ticket/back/methods/ticket/specs/new.spec.js b/modules/ticket/back/methods/ticket/specs/new.spec.js index 0a2f93bc4..9aa073a7b 100644 --- a/modules/ticket/back/methods/ticket/specs/new.spec.js +++ b/modules/ticket/back/methods/ticket/specs/new.spec.js @@ -30,7 +30,7 @@ describe('ticket new()', () => { await tx.rollback(); } - expect(error).toEqual(new UserError(`You can't create a ticket for a inactive client`)); + expect(error).toEqual(new UserError(`You can't create a ticket for an inactive client`)); }); it('should throw an error if the address doesnt exist', async() => { diff --git a/modules/ticket/back/methods/ticket-tracking/specs/changeState.spec.js b/modules/ticket/back/methods/ticket/specs/state.spec.js similarity index 87% rename from modules/ticket/back/methods/ticket-tracking/specs/changeState.spec.js rename to modules/ticket/back/methods/ticket/specs/state.spec.js index 175bc4e4b..9b5e80165 100644 --- a/modules/ticket/back/methods/ticket-tracking/specs/changeState.spec.js +++ b/modules/ticket/back/methods/ticket/specs/state.spec.js @@ -1,7 +1,7 @@ const models = require('vn-loopback/server/server').models; const LoopBackContext = require('loopback-context'); -describe('ticket changeState()', () => { +describe('ticket state()', () => { const salesPersonId = 18; const employeeId = 1; const productionId = 49; @@ -47,7 +47,7 @@ describe('ticket changeState()', () => { activeCtx.accessToken.userId = salesPersonId; const params = {ticketFk: 2, stateFk: 3}; - await models.TicketTracking.changeState(ctx, params, options); + await models.Ticket.state(ctx, params, options); await tx.rollback(); } catch (e) { @@ -69,7 +69,7 @@ describe('ticket changeState()', () => { activeCtx.accessToken.userId = employeeId; const params = {ticketFk: 11, stateFk: 13}; - await models.TicketTracking.changeState(ctx, params, options); + await models.Ticket.state(ctx, params, options); await tx.rollback(); } catch (e) { @@ -80,7 +80,8 @@ describe('ticket changeState()', () => { expect(error.code).toBe('ACCESS_DENIED'); }); - it('should be able to create a ticket tracking line for a not editable ticket if the user has the production role', async() => { + it('should be able to create a ticket tracking line for a not' + + ' editable ticket if the user has the production role', async() => { const tx = await models.TicketTracking.beginTransaction({}); try { @@ -91,7 +92,7 @@ describe('ticket changeState()', () => { activeCtx.accessToken.userId = productionId; const params = {ticketFk: ticket.id, stateFk: 3}; - const ticketTracking = await models.TicketTracking.changeState(ctx, params, options); + const ticketTracking = await models.Ticket.state(ctx, params, options); expect(ticketTracking.__data.ticketFk).toBe(params.ticketFk); expect(ticketTracking.__data.stateFk).toBe(params.stateFk); @@ -105,7 +106,8 @@ describe('ticket changeState()', () => { } }); - it('should update the ticket tracking line when the user is salesperson, uses the state assigned and a valid worker id', async() => { + it('should update the ticket tracking line when the user is salesperson,' + + ' uses the state assigned and a valid worker id', async() => { const tx = await models.TicketTracking.beginTransaction({}); try { @@ -115,7 +117,7 @@ describe('ticket changeState()', () => { const ctx = {req: {accessToken: {userId: 18}}}; const assignedState = await models.State.findOne({where: {code: 'PICKER_DESIGNED'}}, options); const params = {ticketFk: ticket.id, stateFk: assignedState.id, workerFk: 1}; - const res = await models.TicketTracking.changeState(ctx, params, options); + const res = await models.Ticket.state(ctx, params, options); expect(res.__data.ticketFk).toBe(params.ticketFk); expect(res.__data.stateFk).toBe(params.stateFk); diff --git a/modules/ticket/back/methods/ticket-tracking/changeState.js b/modules/ticket/back/methods/ticket/state.js similarity index 94% rename from modules/ticket/back/methods/ticket-tracking/changeState.js rename to modules/ticket/back/methods/ticket/state.js index dbef8762e..01bfbba20 100644 --- a/modules/ticket/back/methods/ticket-tracking/changeState.js +++ b/modules/ticket/back/methods/ticket/state.js @@ -1,7 +1,7 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { - Self.remoteMethodCtx('changeState', { + Self.remoteMethodCtx('state', { description: 'Change the state of a ticket', accessType: 'WRITE', accepts: [ @@ -18,12 +18,12 @@ module.exports = Self => { root: true }, http: { - path: `/changeState`, + path: `/state`, verb: 'POST' } }); - Self.changeState = async(ctx, params, options) => { + Self.state = async(ctx, params, options) => { const models = Self.app.models; const myOptions = {}; let tx; diff --git a/modules/ticket/back/methods/ticket/transferSales.js b/modules/ticket/back/methods/ticket/transferSales.js index a2e92d524..54306510c 100644 --- a/modules/ticket/back/methods/ticket/transferSales.js +++ b/modules/ticket/back/methods/ticket/transferSales.js @@ -66,7 +66,7 @@ module.exports = Self => { const ticket = await models.Ticket.findById(id); const canCreateTicket = await models.Client.canCreateTicket(ticket.clientFk); if (!canCreateTicket) - throw new UserError(`You can't create a ticket for a inactive client`); + throw new UserError(`You can't create a ticket for an inactive client`); ticketId = await cloneTicket(originalTicket, myOptions); } diff --git a/modules/ticket/back/models/expeditionScan.json b/modules/ticket/back/models/expeditionScan.json index 1db2c1238..7b95eff1e 100644 --- a/modules/ticket/back/models/expeditionScan.json +++ b/modules/ticket/back/models/expeditionScan.json @@ -8,17 +8,16 @@ "properties": { "id": { "type": "number", - "description": "Identifier" + "description": "Identifier", + "id": true }, "expeditionFk": { "type": "number", - "description": "Identifier", - "id": true + "description": "Identifier" }, "palletFk": { "type": "number", - "description": "Identifier", - "id": true + "description": "Identifier" }, "scanned": { "type": "date", diff --git a/modules/ticket/back/models/sale.js b/modules/ticket/back/models/sale.js index 99cfeeeea..3589eac4b 100644 --- a/modules/ticket/back/models/sale.js +++ b/modules/ticket/back/models/sale.js @@ -12,6 +12,7 @@ module.exports = Self => { require('../methods/sale/refund')(Self); require('../methods/sale/canEdit')(Self); require('../methods/sale/usesMana')(Self); + require('../methods/sale/clone')(Self); Self.validatesPresenceOf('concept', { message: `Concept cannot be blank` diff --git a/modules/ticket/back/models/ticket-tracking.js b/modules/ticket/back/models/ticket-tracking.js index 2e6d3403e..92e046d3e 100644 --- a/modules/ticket/back/models/ticket-tracking.js +++ b/modules/ticket/back/models/ticket-tracking.js @@ -1,5 +1,4 @@ module.exports = function(Self) { - require('../methods/ticket-tracking/changeState')(Self); require('../methods/ticket-tracking/setDelivered')(Self); Self.validatesPresenceOf('stateFk', {message: 'State cannot be blank'}); diff --git a/modules/ticket/back/models/ticket.js b/modules/ticket/back/models/ticket.js index ea068ef8a..1930765fb 100644 --- a/modules/ticket/back/models/ticket.js +++ b/modules/ticket/back/models/ticket.js @@ -1,4 +1,4 @@ module.exports = Self => { - // Methods require('./ticket-methods')(Self); + require('../methods/ticket/state')(Self); }; diff --git a/modules/ticket/front/sale/index.html b/modules/ticket/front/sale/index.html index 729822764..262395d16 100644 --- a/modules/ticket/front/sale/index.html +++ b/modules/ticket/front/sale/index.html @@ -15,7 +15,7 @@ + on-change="$ctrl.state(value)"> { + return this.$http.post('Tickets/state', params).then(() => { this.vnApp.showSuccess(this.$t('Data saved!')); this.card.reload(); }).finally(() => this.resetChanges()); diff --git a/modules/ticket/front/sale/index.spec.js b/modules/ticket/front/sale/index.spec.js index b36e78893..70781eb58 100644 --- a/modules/ticket/front/sale/index.spec.js +++ b/modules/ticket/front/sale/index.spec.js @@ -228,15 +228,16 @@ describe('Ticket', () => { }); }); - describe('changeState()', () => { - it('should make an HTTP post query, then call the showSuccess(), reload() and resetChanges() methods', () => { + describe('state()', () => { + it('should make an HTTP post query, then call the showSuccess(),' + + ' reload() and resetChanges() methods', () => { jest.spyOn(controller.card, 'reload').mockReturnThis(); jest.spyOn(controller.vnApp, 'showSuccess').mockReturnThis(); jest.spyOn(controller, 'resetChanges').mockReturnThis(); const expectedParams = {ticketFk: 1, code: 'OK'}; - $httpBackend.expect('POST', `TicketTrackings/changeState`, expectedParams).respond(200); - controller.changeState('OK'); + $httpBackend.expect('POST', `Tickets/state`, expectedParams).respond(200); + controller.state('OK'); $httpBackend.flush(); expect(controller.card.reload).toHaveBeenCalledWith(); @@ -246,7 +247,8 @@ describe('Ticket', () => { }); describe('removeSales()', () => { - it('should make an HTTP post query, then call the showSuccess(), removeSelectedSales() and resetChanges() methods', () => { + it('should make an HTTP post query, then call the showSuccess(),' + + ' removeSelectedSales() and resetChanges() methods', () => { jest.spyOn(controller.vnApp, 'showSuccess').mockReturnThis(); jest.spyOn(controller, 'removeSelectedSales').mockReturnThis(); jest.spyOn(controller, 'resetChanges').mockReturnThis(); @@ -352,7 +354,8 @@ describe('Ticket', () => { }); describe('updatePrice()', () => { - it('should make an HTTP POST query, update the sale price and then call to the resetChanges() method', () => { + it('should make an HTTP POST query, update the sale price ' + + 'and then call to the resetChanges() method', () => { jest.spyOn(controller.vnApp, 'showSuccess').mockReturnThis(); jest.spyOn(controller, 'resetChanges').mockReturnThis(); @@ -418,7 +421,8 @@ describe('Ticket', () => { expect(controller.$.editDiscount.hide).toHaveBeenCalledWith(); }); - it('should not call to the updateDiscount() method and then to the editDiscountDialog hide() method', () => { + it('should not call to the updateDiscount() method and then' + + ' to the editDiscountDialog hide() method', () => { jest.spyOn(controller, 'updateDiscount').mockReturnThis(); const firstSelectedSale = controller.sales[0]; @@ -444,7 +448,8 @@ describe('Ticket', () => { }); describe('updateDiscount()', () => { - it('should make an HTTP POST query, update the sales discount and then call to the resetChanges() method', () => { + it('should make an HTTP POST query, update the sales discount ' + + 'and then call to the resetChanges() method', () => { jest.spyOn(controller, 'resetChanges').mockReturnThis(); jest.spyOn(controller.vnApp, 'showSuccess').mockReturnThis(); diff --git a/modules/ticket/front/summary/index.html b/modules/ticket/front/summary/index.html index 3c60352a7..025078d36 100644 --- a/modules/ticket/front/summary/index.html +++ b/modules/ticket/front/summary/index.html @@ -18,7 +18,7 @@ value-field="code" fields="['id', 'name', 'alertLevel', 'code']" url="States/editableStates" - on-change="$ctrl.changeState(value)"> + on-change="$ctrl.state(value)"> {{::sale.quantity}}
- {{::sale.item.name}} + {{::sale.concept}}

{{::sale.item.subName}}

diff --git a/modules/ticket/front/summary/index.js b/modules/ticket/front/summary/index.js index 60394b5b3..9d161f63e 100644 --- a/modules/ticket/front/summary/index.js +++ b/modules/ticket/front/summary/index.js @@ -59,13 +59,12 @@ class Controller extends Summary { this.$.invoiceOutDescriptor.show(event.target, this.summary.invoiceOut.id); } - changeState(value) { + state(value) { const params = { ticketFk: 'id' in this.ticket ? this.ticket.id : this.$params.id, code: value }; - - this.$http.post(`TicketTrackings/changeState`, params) + this.$http.post(`Tickets/state`, params) .then(() => { if ('id' in this.$params) this.reload(); }) diff --git a/modules/ticket/front/summary/index.spec.js b/modules/ticket/front/summary/index.spec.js index 599da73ae..6837bfd54 100644 --- a/modules/ticket/front/summary/index.spec.js +++ b/modules/ticket/front/summary/index.spec.js @@ -43,15 +43,15 @@ describe('Ticket', () => { }); }); - describe('changeState()', () => { + describe('state()', () => { it('should change the state', () => { jest.spyOn(controller.vnApp, 'showSuccess'); const value = 'myTicketState'; let res = {id: 1, nickname: 'myNickname'}; $httpBackend.when('GET', `Tickets/1/summary`).respond(200, res); - $httpBackend.expectPOST(`TicketTrackings/changeState`).respond(200, 'ok'); - controller.changeState(value); + $httpBackend.expectPOST(`Tickets/state`).respond(200, 'ok'); + controller.state(value); $httpBackend.flush(); expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!'); diff --git a/modules/ticket/front/tracking/edit/index.html b/modules/ticket/front/tracking/edit/index.html index bff8e71b1..47f367007 100644 --- a/modules/ticket/front/tracking/edit/index.html +++ b/modules/ticket/front/tracking/edit/index.html @@ -1,4 +1,4 @@ - + { + this.$http.post(`Tickets/state`, this.params).then(() => { this.$.watcher.updateOriginalData(); this.card.reload(); this.vnApp.showSuccess(this.$t('Data saved!')); diff --git a/modules/ticket/front/tracking/edit/index.spec.js b/modules/ticket/front/tracking/edit/index.spec.js index 1ba5912b5..9d9aa7983 100644 --- a/modules/ticket/front/tracking/edit/index.spec.js +++ b/modules/ticket/front/tracking/edit/index.spec.js @@ -61,7 +61,7 @@ describe('Ticket', () => { jest.spyOn(controller.vnApp, 'showSuccess'); jest.spyOn(controller.$state, 'go'); - $httpBackend.expectPOST(`TicketTrackings/changeState`, controller.params).respond({}); + $httpBackend.expectPOST(`Tickets/state`, controller.params).respond({}); controller.onSubmit(); $httpBackend.flush(); diff --git a/modules/worker/back/models/operator.json b/modules/worker/back/models/operator.json index 2417078e1..6da3945fc 100644 --- a/modules/worker/back/models/operator.json +++ b/modules/worker/back/models/operator.json @@ -33,6 +33,16 @@ "type": "belongsTo", "model": "Sector", "foreignKey": "sectorFk" + }, + "train": { + "type": "belongsTo", + "model": "Train", + "foreignKey": "trainFk" + }, + "printer": { + "type": "belongsTo", + "model": "Printer", + "foreignKey": "labelerFk" } } } diff --git a/modules/worker/front/time-control/index.js b/modules/worker/front/time-control/index.js index a60c71589..0a955c586 100644 --- a/modules/worker/front/time-control/index.js +++ b/modules/worker/front/time-control/index.js @@ -404,7 +404,7 @@ class Controller extends Section { }); } - changeState(state, reason) { + state(state, reason) { this.state = state; this.reason = reason; this.repaint(); diff --git a/package-lock.json b/package-lock.json index c3f88bc2c..5bf7a2cb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "salix-back", - "version": "23.42.01", + "version": "23.46.01", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "salix-back", - "version": "23.42.01", + "version": "23.46.01", "license": "GPL-3.0", "dependencies": { "axios": "^1.2.2", diff --git a/package.json b/package.json index 3320705f5..b1539f9a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "23.42.01", + "version": "23.46.01", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0", diff --git a/print/templates/reports/invoice/invoice.js b/print/templates/reports/invoice/invoice.js index 1c9965d3b..b26472b08 100755 --- a/print/templates/reports/invoice/invoice.js +++ b/print/templates/reports/invoice/invoice.js @@ -7,6 +7,7 @@ module.exports = { mixins: [vnReport], async serverPrefetch() { this.invoice = await this.findOneFromDef('invoice', [this.reference]); + this.checkMainEntity(this.invoice); this.client = await this.findOneFromDef('client', [this.reference]); this.taxes = await this.rawSqlFromDef(`taxes`, [this.reference]);