diff --git a/.eslintrc.yml b/.eslintrc.yml index 3b82d0a90..247319137 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -31,4 +31,3 @@ rules: curly: [error, multi-or-nest] indent: [error, 4] arrow-parens: [error, as-needed] - jasmine/no-focused-tests: 0 \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index 65aae2300..4ccc54b46 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -131,6 +131,7 @@ pipeline { stage('Database') { when { anyOf { branch 'test' + branch 'master' }} steps { configFileProvider([ diff --git a/db/changes/10002-lent/00-ACL.sql b/db/changes/10002-lent/00-ACL.sql new file mode 100644 index 000000000..6ca46845d --- /dev/null +++ b/db/changes/10002-lent/00-ACL.sql @@ -0,0 +1 @@ +INSERT INTO `salix`.`ACL` (`id`, `model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) VALUES ('160', 'TicketServiceType', '*', 'READ', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/changes/10002-lent/00-clientGetSalesPerson.sql b/db/changes/10002-lent/00-clientGetSalesPerson.sql new file mode 100644 index 000000000..f93e528a2 --- /dev/null +++ b/db/changes/10002-lent/00-clientGetSalesPerson.sql @@ -0,0 +1,76 @@ + +DROP function IF EXISTS `vn`.`clientGetSalesPerson`; +DELIMITER $$ +CREATE DEFINER=`root`@`%` FUNCTION `vn`.`clientGetSalesPerson`(vClientFk INT, vDated DATE) RETURNS int(11) + DETERMINISTIC +BEGIN +/** + * Dado un id cliente y una fecha, devuelve su comercial para ese dia, teniendo + * en cuenta la jerarquía de las tablas: 1º la de sharingClient, 2º la de + * sharingCart y tercero la de clientes. + * + * @param vClientFk El id del cliente + * @param vDated Fecha a comprobar + * @return El id del comercial para la fecha dada + **/ + DECLARE vSalesperson INT DEFAULT NULL; + DECLARE vSubstitute INT DEFAULT NULL; + DECLARE vLoop BOOLEAN; + + -- Obtiene el comercial original y el de sharingClient + + SELECT c.salesPersonFk, s.workerFk + INTO vSalesperson, vSubstitute + FROM client c + LEFT JOIN sharingClient s + ON c.id = s.clientFk + AND vDated BETWEEN s.started AND s.ended + WHERE c.id = vClientFk + ORDER BY s.id + LIMIT 1; + + -- Si no hay ninguno en sharingClient busca en sharingCart + + IF vSubstitute IS NOT NULL + THEN + SET vSalesperson = vSubstitute; + ELSEIF vSalesperson IS NOT NULL + THEN + DROP TEMPORARY TABLE IF EXISTS tmp.stack; + CREATE TEMPORARY TABLE tmp.stack + (INDEX (substitute)) + ENGINE = MEMORY + SELECT vSalesperson substitute; + + l: LOOP + SELECT workerSubstitute INTO vSubstitute + FROM sharingCart + WHERE vDated BETWEEN started AND ended + AND workerFk = vSalesperson + ORDER BY id + LIMIT 1; + + IF vSubstitute IS NULL THEN + LEAVE l; + END IF; + + SELECT COUNT(*) > 0 INTO vLoop + FROM tmp.stack WHERE substitute = vSubstitute; + + IF vLoop THEN + LEAVE l; + END IF; + + INSERT INTO tmp.stack SET + substitute = vSubstitute; + + SET vSalesperson = vSubstitute; + END LOOP; + + DROP TEMPORARY TABLE tmp.stack; + END IF; + + RETURN vSalesperson; +END$$ + +DELIMITER ; \ No newline at end of file diff --git a/db/changes/10002-lent/00-greugesShipped.sql b/db/changes/10002-lent/00-greugesShipped.sql new file mode 100644 index 000000000..25cb4df2f --- /dev/null +++ b/db/changes/10002-lent/00-greugesShipped.sql @@ -0,0 +1 @@ +ALTER TABLE `vn2008`.`Greuges` CHANGE COLUMN `Fecha` `Fecha` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ; \ No newline at end of file diff --git a/db/changes/10002-lent/00-invoiceOut.sql b/db/changes/10002-lent/00-invoiceOut.sql new file mode 100644 index 000000000..ed58227ac --- /dev/null +++ b/db/changes/10002-lent/00-invoiceOut.sql @@ -0,0 +1,9 @@ +ALTER TABLE `vn2008`.`Facturas` +DROP FOREIGN KEY `invoice_bank_id`; +ALTER TABLE `vn2008`.`Facturas` +CHANGE COLUMN `Id_Banco` `Id_Banco` INT(11) NULL DEFAULT NULL ; +ALTER TABLE `vn2008`.`Facturas` +ADD CONSTRAINT `invoice_bank_id` + FOREIGN KEY (`Id_Banco`) + REFERENCES `vn2008`.`Bancos` (`Id_Banco`) + ON UPDATE CASCADE; diff --git a/db/changes/10002-lent/00-printQueue.sql b/db/changes/10002-lent/00-printQueue.sql new file mode 100644 index 000000000..d2493458b --- /dev/null +++ b/db/changes/10002-lent/00-printQueue.sql @@ -0,0 +1,17 @@ +ALTER TABLE `vn2008`.`Colas` +DROP FOREIGN KEY `Colas_ibfk_1`, +DROP FOREIGN KEY `Colas_ibfk_2`, +DROP FOREIGN KEY `Colas_ibfk_3`, +DROP FOREIGN KEY `Colas_ibfk_5`; +ALTER TABLE `vn2008`.`Colas` +CHANGE COLUMN `Id_Impresora` `Id_Impresora` TINYINT(3) UNSIGNED NULL DEFAULT NULL , +CHANGE COLUMN `Id_Prioridad` `Id_Prioridad` TINYINT(3) UNSIGNED NULL DEFAULT NULL ; +ALTER TABLE `vn2008`.`Colas` +ADD CONSTRAINT `Colas_ibfk_4` + FOREIGN KEY (`Id_Impresora`) + REFERENCES `vn2008`.`Impresoras` (`Id_Impresora`) + ON UPDATE CASCADE, +ADD CONSTRAINT `Colas_ibfk_3` + FOREIGN KEY (`Id_Prioridad`) + REFERENCES `vn2008`.`Prioridades` (`Id_Prioridad`) + ON UPDATE CASCADE; diff --git a/db/changes/10002-lent/00-sharingCart.sql b/db/changes/10002-lent/00-sharingCart.sql new file mode 100644 index 000000000..1267cd044 --- /dev/null +++ b/db/changes/10002-lent/00-sharingCart.sql @@ -0,0 +1,14 @@ +CREATE + ALGORITHM = UNDEFINED + DEFINER = `root`@`%` + SQL SECURITY DEFINER +VIEW `vn`.`sharingCart` AS + SELECT + `s`.`id` AS `id`, + `s`.`Id_Trabajador` AS `workerFk`, + `s`.`datSTART` AS `started`, + `s`.`datEND` AS `ended`, + `s`.`Id_Suplente` AS `workerSubstitute`, + `s`.`odbc_date` AS `created` + FROM + `vn2008`.`sharingcart` `s` \ No newline at end of file diff --git a/db/changes/10002-lent/00-sharingclient.sql b/db/changes/10002-lent/00-sharingclient.sql new file mode 100644 index 000000000..ab76ec6c5 --- /dev/null +++ b/db/changes/10002-lent/00-sharingclient.sql @@ -0,0 +1,13 @@ +CREATE + OR REPLACE ALGORITHM = UNDEFINED + DEFINER = `root`@`%` + SQL SECURITY DEFINER +VIEW `vn`.`sharingClient` AS + SELECT + `s`.`id` AS `id`, + `s`.`Id_Trabajador` AS `workerFk`, + `s`.`datSTART` AS `started`, + `s`.`datEND` AS `ended`, + `s`.`Id_Cliente` AS `clientFk` + FROM + `vn2008`.`sharingclient` `s`; diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index aec4a3a3a..ccc722c44 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -440,9 +440,12 @@ INSERT INTO `vn`.`ticket`(`id`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`) VALUES - ( 1, 1 , 1, 'ready' ), - ( 2, 2 , 2, 'do it fast please'), - ( 3, 3 , 3, ''); + (1, 1 , 1, 'ready' ), + (2, 2 , 2, 'do it fast please'), + (3, 3 , 3, 'Faster faster fasteeeeeer!!!'), + (4, 4 , 3, 'Deliver before 8am'), + (5, 13 , 3, 'You can run from the disappointments you are trying to forget. But its only when you embrace your past that you truly move forward. Maybe I never get to go home again, but I found my way there. And I am glad I did.'), + (6, 14, 3, 'Careful, armed warhead'); INSERT INTO `vn`.`ticketTracking`(`id`, `ticketFk`, `stateFk`, `workerFk`, `created`) VALUES @@ -973,6 +976,14 @@ INSERT INTO `vn2008`.`tblContadores`(`id`,`FechaInventario`) VALUES (1,DATE_ADD(CURDATE(),INTERVAL -1 MONTH)); +INSERT INTO `vn2008`.`Estados` (`Id_Estado`, `Estado`) + VALUES + ('1', 'En Espera'); + +INSERT INTO `vn2008`.`Informes` (`Id_Informe`, `Informe`) + VALUES + ('30', 'Generar factura PDF'); + INSERT INTO `vn`.`deliveryMethod`(`id`, `code`, `description`) VALUES ( 1, 'AGENCY', 'Agencia'), @@ -1317,3 +1328,11 @@ INSERT INTO `vn`.`smsConfig` (`id`, `uri`, `user`, `password`, `title`) VALUES ('1', 'https://websms.xtratelecom.es/api_php/server.wsdl', 'VERDINATURA', '182wbOKu', 'Verdnatura'); +INSERT INTO `vn`.`sharingClient`(`id`, `workerFk`, `started`, `ended`, `clientFk`) + VALUES + (1, 19, DATE_ADD(CURDATE(), INTERVAL -5 DAY), DATE_ADD(CURDATE(), INTERVAL +15 DAY), 101), + (2, 18, DATE_ADD(CURDATE(), INTERVAL -5 DAY), DATE_ADD(CURDATE(), INTERVAL +15 DAY), 106); + +INSERT INTO `vn`.`sharingCart`(`id`, `workerFk`, `started`, `ended`, `workerSubstitute`, `created`) + VALUES + (1, 18, DATE_ADD(CURDATE(), INTERVAL -5 DAY), DATE_ADD(CURDATE(), INTERVAL +15 DAY), 19, DATE_ADD(CURDATE(), INTERVAL -5 DAY)); \ No newline at end of file diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index c7663af4d..a8c3d44dc 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -455,7 +455,7 @@ export default { }, ticketService: { addServiceButton: 'vn-ticket-service > form > vn-card > div > vn-one:nth-child(3) > vn-icon-button > button > vn-icon', - firstDescriptionInput: 'vn-ticket-service vn-autocomplete[label="Documentos"]', + firstDescriptionAutocomplete: 'vn-ticket-service vn-autocomplete[field="service.description"]', firstQuantityInput: 'vn-ticket-service vn-input-number[label="Quantity"] input', firstPriceInput: 'vn-ticket-service vn-input-number[label="Price"] input', firstVatTypeAutocomplete: 'vn-ticket-service vn-autocomplete[label="Tax class"]', diff --git a/e2e/paths/02-worker-module/01_pbx.spec.js b/e2e/paths/03-worker-module/01_pbx.spec.js similarity index 100% rename from e2e/paths/02-worker-module/01_pbx.spec.js rename to e2e/paths/03-worker-module/01_pbx.spec.js diff --git a/e2e/paths/03-item-module/01_summary.spec.js b/e2e/paths/04-item-module/01_summary.spec.js similarity index 100% rename from e2e/paths/03-item-module/01_summary.spec.js rename to e2e/paths/04-item-module/01_summary.spec.js diff --git a/e2e/paths/03-item-module/02_basic_data.spec.js b/e2e/paths/04-item-module/02_basic_data.spec.js similarity index 100% rename from e2e/paths/03-item-module/02_basic_data.spec.js rename to e2e/paths/04-item-module/02_basic_data.spec.js diff --git a/e2e/paths/03-item-module/03_tax.spec.js b/e2e/paths/04-item-module/03_tax.spec.js similarity index 100% rename from e2e/paths/03-item-module/03_tax.spec.js rename to e2e/paths/04-item-module/03_tax.spec.js diff --git a/e2e/paths/03-item-module/04_tags.spec.js b/e2e/paths/04-item-module/04_tags.spec.js similarity index 100% rename from e2e/paths/03-item-module/04_tags.spec.js rename to e2e/paths/04-item-module/04_tags.spec.js diff --git a/e2e/paths/03-item-module/05_niche.spec.js b/e2e/paths/04-item-module/05_niche.spec.js similarity index 100% rename from e2e/paths/03-item-module/05_niche.spec.js rename to e2e/paths/04-item-module/05_niche.spec.js diff --git a/e2e/paths/03-item-module/06_botanical.spec.js b/e2e/paths/04-item-module/06_botanical.spec.js similarity index 100% rename from e2e/paths/03-item-module/06_botanical.spec.js rename to e2e/paths/04-item-module/06_botanical.spec.js diff --git a/e2e/paths/03-item-module/07_barcode.spec.js b/e2e/paths/04-item-module/07_barcode.spec.js similarity index 100% rename from e2e/paths/03-item-module/07_barcode.spec.js rename to e2e/paths/04-item-module/07_barcode.spec.js diff --git a/e2e/paths/03-item-module/08_create_and_clone.spec.js b/e2e/paths/04-item-module/08_create_and_clone.spec.js similarity index 100% rename from e2e/paths/03-item-module/08_create_and_clone.spec.js rename to e2e/paths/04-item-module/08_create_and_clone.spec.js diff --git a/e2e/paths/03-item-module/09_regularize.spec.js b/e2e/paths/04-item-module/09_regularize.spec.js similarity index 100% rename from e2e/paths/03-item-module/09_regularize.spec.js rename to e2e/paths/04-item-module/09_regularize.spec.js diff --git a/e2e/paths/03-item-module/10_item_index.spec.js b/e2e/paths/04-item-module/10_item_index.spec.js similarity index 100% rename from e2e/paths/03-item-module/10_item_index.spec.js rename to e2e/paths/04-item-module/10_item_index.spec.js diff --git a/e2e/paths/03-item-module/11_item_log.spec.js b/e2e/paths/04-item-module/11_item_log.spec.js similarity index 100% rename from e2e/paths/03-item-module/11_item_log.spec.js rename to e2e/paths/04-item-module/11_item_log.spec.js diff --git a/e2e/paths/03-item-module/12_descriptor.spec.js b/e2e/paths/04-item-module/12_descriptor.spec.js similarity index 100% rename from e2e/paths/03-item-module/12_descriptor.spec.js rename to e2e/paths/04-item-module/12_descriptor.spec.js diff --git a/e2e/paths/04-ticket-module/01_create_ticket_observations.spec.js b/e2e/paths/05-ticket-module/01_create_ticket_observations.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/01_create_ticket_observations.spec.js rename to e2e/paths/05-ticket-module/01_create_ticket_observations.spec.js diff --git a/e2e/paths/04-ticket-module/02_ticket_expeditions_and_log.spec.js b/e2e/paths/05-ticket-module/02_ticket_expeditions_and_log.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/02_ticket_expeditions_and_log.spec.js rename to e2e/paths/05-ticket-module/02_ticket_expeditions_and_log.spec.js diff --git a/e2e/paths/04-ticket-module/03_list_sale.spec.js b/e2e/paths/05-ticket-module/03_list_sale.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/03_list_sale.spec.js rename to e2e/paths/05-ticket-module/03_list_sale.spec.js diff --git a/e2e/paths/04-ticket-module/04_create_ticket_packages.spec.js b/e2e/paths/05-ticket-module/04_create_ticket_packages.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/04_create_ticket_packages.spec.js rename to e2e/paths/05-ticket-module/04_create_ticket_packages.spec.js diff --git a/e2e/paths/04-ticket-module/05_create_new_tracking_state.spec.js b/e2e/paths/05-ticket-module/05_create_new_tracking_state.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/05_create_new_tracking_state.spec.js rename to e2e/paths/05-ticket-module/05_create_new_tracking_state.spec.js diff --git a/e2e/paths/04-ticket-module/06_edit_basic_data_steps.spec.js b/e2e/paths/05-ticket-module/06_edit_basic_data_steps.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/06_edit_basic_data_steps.spec.js rename to e2e/paths/05-ticket-module/06_edit_basic_data_steps.spec.js diff --git a/e2e/paths/04-ticket-module/07_edit_sale.spec.js b/e2e/paths/05-ticket-module/07_edit_sale.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/07_edit_sale.spec.js rename to e2e/paths/05-ticket-module/07_edit_sale.spec.js diff --git a/e2e/paths/04-ticket-module/08_list_components.spec.js b/e2e/paths/05-ticket-module/08_list_components.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/08_list_components.spec.js rename to e2e/paths/05-ticket-module/08_list_components.spec.js diff --git a/e2e/paths/04-ticket-module/09_ticket_weekly.spec.js b/e2e/paths/05-ticket-module/09_ticket_weekly.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/09_ticket_weekly.spec.js rename to e2e/paths/05-ticket-module/09_ticket_weekly.spec.js diff --git a/e2e/paths/04-ticket-module/10_ticket_request.spec.js b/e2e/paths/05-ticket-module/10_ticket_request.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/10_ticket_request.spec.js rename to e2e/paths/05-ticket-module/10_ticket_request.spec.js diff --git a/e2e/paths/04-ticket-module/11_ticket_diary.spec.js b/e2e/paths/05-ticket-module/11_ticket_diary.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/11_ticket_diary.spec.js rename to e2e/paths/05-ticket-module/11_ticket_diary.spec.js diff --git a/e2e/paths/04-ticket-module/12_descriptor.spec.js b/e2e/paths/05-ticket-module/12_descriptor.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/12_descriptor.spec.js rename to e2e/paths/05-ticket-module/12_descriptor.spec.js diff --git a/e2e/paths/04-ticket-module/13_create_ticket_services.spec.js b/e2e/paths/05-ticket-module/13_create_ticket_services.spec.js similarity index 88% rename from e2e/paths/04-ticket-module/13_create_ticket_services.spec.js rename to e2e/paths/05-ticket-module/13_create_ticket_services.spec.js index 34bd22a6c..5a35ba337 100644 --- a/e2e/paths/04-ticket-module/13_create_ticket_services.spec.js +++ b/e2e/paths/05-ticket-module/13_create_ticket_services.spec.js @@ -13,8 +13,7 @@ describe('Ticket services path', () => { it('should edit the first service', async() => { const result = await nightmare - .clearInput(selectors.ticketService.firstDescriptionInput) - .write(selectors.ticketService.firstDescriptionInput, 'my service') + .autocompleteSearch(selectors.ticketService.firstDescriptionAutocomplete, 'Documentos') .clearInput(selectors.ticketService.firstQuantityInput) .write(selectors.ticketService.firstQuantityInput, 99) .clearInput(selectors.ticketService.firstPriceInput) @@ -29,9 +28,9 @@ describe('Ticket services path', () => { it('should confirm the service description was edited correctly', async() => { const result = await nightmare .reloadSection('ticket.card.service') - .waitToGetProperty(selectors.ticketService.firstDescriptionInput, 'value'); + .waitToGetProperty(`${selectors.ticketService.firstDescriptionAutocomplete} input`, 'value'); - expect(result).toEqual('my service'); + expect(result).toEqual('Documentos'); }); it('should confirm the service quantity was edited correctly', async() => { @@ -55,7 +54,7 @@ describe('Ticket services path', () => { expect(result).toEqual('General VAT'); }); - fit('should delete the service', async() => { + it('should delete the service', async() => { const result = await nightmare .waitToClick(selectors.ticketService.fistDeleteServiceButton) .waitForNumberOfElements(selectors.ticketService.serviceLine, 0) diff --git a/e2e/paths/04-ticket-module/14_create_ticket.spec.js b/e2e/paths/05-ticket-module/14_create_ticket.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/14_create_ticket.spec.js rename to e2e/paths/05-ticket-module/14_create_ticket.spec.js diff --git a/e2e/paths/04-ticket-module/15_create_ticket_from_client.spec.js b/e2e/paths/05-ticket-module/15_create_ticket_from_client.spec.js similarity index 100% rename from e2e/paths/04-ticket-module/15_create_ticket_from_client.spec.js rename to e2e/paths/05-ticket-module/15_create_ticket_from_client.spec.js diff --git a/e2e/paths/05-claim-module/01_edit_basic_data.spec.js b/e2e/paths/06-claim-module/01_edit_basic_data.spec.js similarity index 100% rename from e2e/paths/05-claim-module/01_edit_basic_data.spec.js rename to e2e/paths/06-claim-module/01_edit_basic_data.spec.js diff --git a/e2e/paths/05-claim-module/02_create_development.spec.js b/e2e/paths/06-claim-module/02_create_development.spec.js similarity index 100% rename from e2e/paths/05-claim-module/02_create_development.spec.js rename to e2e/paths/06-claim-module/02_create_development.spec.js diff --git a/e2e/paths/05-claim-module/03_detail.spec.js b/e2e/paths/06-claim-module/03_detail.spec.js similarity index 100% rename from e2e/paths/05-claim-module/03_detail.spec.js rename to e2e/paths/06-claim-module/03_detail.spec.js diff --git a/e2e/paths/05-claim-module/04_claim_action.spec.js b/e2e/paths/06-claim-module/04_claim_action.spec.js similarity index 100% rename from e2e/paths/05-claim-module/04_claim_action.spec.js rename to e2e/paths/06-claim-module/04_claim_action.spec.js diff --git a/e2e/paths/06-order-module/01_edit_basic_data.spec.js b/e2e/paths/07-order-module/01_edit_basic_data.spec.js similarity index 100% rename from e2e/paths/06-order-module/01_edit_basic_data.spec.js rename to e2e/paths/07-order-module/01_edit_basic_data.spec.js diff --git a/e2e/paths/06-order-module/02_lines.spec.js b/e2e/paths/07-order-module/02_lines.spec.js similarity index 100% rename from e2e/paths/06-order-module/02_lines.spec.js rename to e2e/paths/07-order-module/02_lines.spec.js diff --git a/e2e/paths/07-route-module/01_create.spec.js b/e2e/paths/08-route-module/01_create.spec.js similarity index 100% rename from e2e/paths/07-route-module/01_create.spec.js rename to e2e/paths/08-route-module/01_create.spec.js diff --git a/e2e/paths/07-route-module/02_basic_data.spec.js b/e2e/paths/08-route-module/02_basic_data.spec.js similarity index 100% rename from e2e/paths/07-route-module/02_basic_data.spec.js rename to e2e/paths/08-route-module/02_basic_data.spec.js diff --git a/e2e/paths/07-route-module/03_tickets.spec.js b/e2e/paths/08-route-module/03_tickets.spec.js similarity index 100% rename from e2e/paths/07-route-module/03_tickets.spec.js rename to e2e/paths/08-route-module/03_tickets.spec.js diff --git a/front/core/components/drop-down/style.scss b/front/core/components/drop-down/style.scss index 43be76492..3fceb0212 100755 --- a/front/core/components/drop-down/style.scss +++ b/front/core/components/drop-down/style.scss @@ -48,7 +48,7 @@ vn-drop-down { } } & > .list { - max-height: 12.8em; + max-height: 20em; overflow: auto; ul { diff --git a/front/core/components/input-number/index.js b/front/core/components/input-number/index.js index 2e4e73c29..19c28a63d 100644 --- a/front/core/components/input-number/index.js +++ b/front/core/components/input-number/index.js @@ -44,11 +44,12 @@ export default class InputNumber extends Input { * @param {Number} value - Value */ set value(value) { - if (!this.hasOwnProperty('_value') && value) + this.hasValue = !(value === null || value === undefined || value === ''); + + if (!this.hasOwnProperty('_value') && this.hasValue) this.input.value = value; this._value = value; - this.hasValue = !(value === null || value === undefined || value === ''); if (this.hasValue) this.element.classList.add('not-empty'); diff --git a/front/core/components/popover/popover.js b/front/core/components/popover/popover.js index f6f2dcb96..10fdf3c31 100644 --- a/front/core/components/popover/popover.js +++ b/front/core/components/popover/popover.js @@ -120,7 +120,6 @@ export default class Popover extends Component { if (!(this.parent && this._shown)) return; let margin = 10; - let scrollbarSize = 10; let style = this.popover.style; style.width = ''; @@ -135,11 +134,12 @@ export default class Popover extends Component { let arrowRect = this.arrow.getBoundingClientRect(); let clamp = (value, min, max) => Math.min(Math.max(value, min), max); - let arrowHeight = Math.sqrt(Math.pow(arrowRect.height, 2) * 2) / 2; + let arrowHeight = Math.floor(arrowRect.height / 2); + let arrowOffset = arrowHeight + margin / 2; - let endMargin = margin + scrollbarSize; - let maxRight = window.innerWidth - endMargin; - let maxBottom = window.innerHeight - endMargin; + let docEl = document.documentElement; + let maxRight = Math.min(window.innerWidth, docEl.clientWidth) - margin; + let maxBottom = Math.min(window.innerHeight, docEl.clientHeight) - margin; let maxWith = maxRight - margin; let maxHeight = maxBottom - margin - arrowHeight; @@ -149,9 +149,9 @@ export default class Popover extends Component { let left = parentRect.left + parentRect.width / 2 - width / 2; left = clamp(left, margin, maxRight - width); - let top = parentRect.top + parentRect.height + arrowHeight; + let top = parentRect.top + parentRect.height + arrowOffset; let showTop = top + height > maxBottom; - if (showTop) top = parentRect.top - height - arrowHeight; + if (showTop) top = parentRect.top - height - arrowOffset; top = Math.max(top, margin); if (showTop) diff --git a/front/core/components/searchbar/searchbar.html b/front/core/components/searchbar/searchbar.html index 61132d5c0..d06c4247d 100644 --- a/front/core/components/searchbar/searchbar.html +++ b/front/core/components/searchbar/searchbar.html @@ -8,8 +8,14 @@ pointer> - - + + + this.onStateChange()); @@ -218,7 +219,8 @@ ngModule.component('vnSearchbar', { model: ' diff --git a/modules/agency/front/locale/es.yml b/modules/agency/front/locale/es.yml index 7f70ca50a..d34ab1f70 100644 --- a/modules/agency/front/locale/es.yml +++ b/modules/agency/front/locale/es.yml @@ -9,4 +9,5 @@ Are you sure you want to delete this zone?: ¿Estás seguro de querer eliminar e Zones: Zonas New zone: Nueva zona Volumetric: Volumétrico -Clone: Clonar \ No newline at end of file +Clone: Clonar +Search zone by id or name: Buscar zonas por identificador o nombre \ No newline at end of file diff --git a/modules/agency/front/search-panel/index.html b/modules/agency/front/search-panel/index.html index 9621f8b56..fd0a0158b 100644 --- a/modules/agency/front/search-panel/index.html +++ b/modules/agency/front/search-panel/index.html @@ -5,6 +5,7 @@ vn-one label="General search" model="filter.search" + info="Search zone by id or name" vn-focus> diff --git a/modules/claim/back/methods/claim/filter.js b/modules/claim/back/methods/claim/filter.js new file mode 100644 index 000000000..7a8f3c40c --- /dev/null +++ b/modules/claim/back/methods/claim/filter.js @@ -0,0 +1,118 @@ + +const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; +const buildFilter = require('vn-loopback/util/filter').buildFilter; +const mergeFilters = require('vn-loopback/util/filter').mergeFilters; + +module.exports = Self => { + Self.remoteMethodCtx('filter', { + description: 'Find all instances of the model matched by filter from the data source.', + accessType: 'READ', + accepts: [ + { + arg: 'filter', + type: 'Object', + description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string', + http: {source: 'query'} + }, { + arg: 'tags', + type: ['Object'], + description: 'List of tags to filter with', + http: {source: 'query'} + }, { + arg: 'search', + type: 'String', + description: `If it's and integer searchs by id, otherwise it searchs by client name`, + http: {source: 'query'} + }, { + arg: 'client', + type: 'String', + description: 'The worker name', + http: {source: 'query'} + }, { + arg: 'id', + type: 'Integer', + description: 'The claim id', + http: {source: 'query'} + }, { + arg: 'clientFk', + type: 'Integer', + description: 'The client id', + http: {source: 'query'} + }, { + arg: 'claimStateFk', + type: 'Integer', + description: 'The claim state id', + http: {source: 'query'} + }, { + arg: 'workerFk', + type: 'Integer', + description: 'The worker id', + http: {source: 'query'} + }, { + arg: 'created', + type: 'Date', + description: 'The to date filter', + http: {source: 'query'} + } + ], + returns: { + type: ['Object'], + root: true + }, + http: { + path: `/filter`, + verb: 'GET' + } + }); + + Self.filter = async(ctx, filter) => { + let conn = Self.dataSource.connector; + + let where = buildFilter(ctx.args, (param, value) => { + switch (param) { + case 'search': + return /^\d+$/.test(value) + ? {'cl.id': value} + : { + or: [ + {'c.name': {like: `%${value}%`}} + ] + }; + case 'client': + return {'c.name': {like: `%${value}%`}}; + case 'id': + return {'cl.id': value}; + case 'clientFk': + return {'c.id': value}; + case 'claimStateFk': + return {'cl.claimStateFk': value}; + case 'workerFk': + return {'cl.workerFk': value}; + case 'created': + return {'cl.created': value}; + } + }); + + filter = mergeFilters(ctx.args.filter, {where}); + + let stmts = []; + let stmt; + + stmt = new ParameterizedSQL( + `SELECT cl.id, c.name, u.nickName, cs.description, cl.created + FROM claim cl + LEFT JOIN client c ON c.id = cl.clientFk + LEFT JOIN worker w ON w.id = cl.workerFk + LEFT JOIN account.user u ON u.id = w.userFk + LEFT JOIN claimState cs ON cs.id = cl.claimStateFk` + ); + + + stmt.merge(conn.makeSuffix(filter)); + let itemsIndex = stmts.push(stmt) - 1; + + let sql = ParameterizedSQL.join(stmts, ';'); + let result = await conn.executeStmt(sql); + return itemsIndex === 0 ? result : result[itemsIndex]; + }; +}; diff --git a/modules/claim/back/methods/claim/specs/filter.spec.js b/modules/claim/back/methods/claim/specs/filter.spec.js new file mode 100644 index 000000000..187fffaa4 --- /dev/null +++ b/modules/claim/back/methods/claim/specs/filter.spec.js @@ -0,0 +1,27 @@ +const app = require('vn-loopback/server/server'); + +describe('claim filter()', () => { + it('should return 1 result filtering by id', async() => { + let result = await app.models.Claim.filter({args: {filter: {}, search: 1}}); + + expect(result.length).toEqual(1); + expect(result[0].id).toEqual(1); + }); + + it('should return 1 result filtering by string', async() => { + let result = await app.models.Claim.filter({args: {filter: {}, search: 'Tony Stark'}}); + + expect(result.length).toEqual(1); + expect(result[0].id).toEqual(4); + }); + + it('should return 4 results filtering by worker id', async() => { + let result = await app.models.Claim.filter({args: {filter: {}, workerFk: 18}}); + + expect(result.length).toEqual(4); + expect(result[0].id).toEqual(1); + expect(result[1].id).toEqual(2); + expect(result[2].id).toEqual(3); + expect(result[3].id).toEqual(4); + }); +}); diff --git a/modules/claim/back/methods/claim/updateClaim.js b/modules/claim/back/methods/claim/updateClaim.js index d177ac050..66b409d09 100644 --- a/modules/claim/back/methods/claim/updateClaim.js +++ b/modules/claim/back/methods/claim/updateClaim.js @@ -41,7 +41,7 @@ module.exports = Self => { let notModifiable = ['id', 'responsibility', 'isChargedToMana']; let changedFields = diff(oldClaim, params); let changedFieldsPicked = pick(changedFields, notModifiable); - let statesViables = ['Gestionado', 'Pendiente', 'Anulado']; + let statesViables = ['Gestionado', 'Pendiente', 'Anulado', 'Mana']; let oldState = await models.ClaimState.findOne({where: {id: oldClaim.claimStateFk}}); let newState = await models.ClaimState.findOne({where: {id: params.claimStateFk}}); let canChangeState = statesViables.includes(oldState.description) diff --git a/modules/claim/back/models/claim.js b/modules/claim/back/models/claim.js index dc07ebea7..415b6f0e9 100644 --- a/modules/claim/back/models/claim.js +++ b/modules/claim/back/models/claim.js @@ -3,4 +3,5 @@ module.exports = Self => { require('../methods/claim/createFromSales')(Self); require('../methods/claim/updateClaim')(Self); require('../methods/claim/regularizeClaim')(Self); + require('../methods/claim/filter')(Self); }; diff --git a/modules/claim/back/models/claim.json b/modules/claim/back/models/claim.json index 38d508725..1462c4222 100644 --- a/modules/claim/back/models/claim.json +++ b/modules/claim/back/models/claim.json @@ -34,9 +34,6 @@ "claimStateFk": { "type": "Number" }, - "clientFk": { - "type": "Number" - }, "workerFk": { "type": "Number" } diff --git a/modules/claim/front/action/index.html b/modules/claim/front/action/index.html index 7bace5a0e..44f9bb68c 100644 --- a/modules/claim/front/action/index.html +++ b/modules/claim/front/action/index.html @@ -30,7 +30,7 @@ vn-one label="Responsability" value="$ctrl.claim.responsibility" - max="5" + max="$ctrl.maxResponsibility" min="1" step="1" vn-acl="salesAssistant" @@ -191,4 +191,10 @@ - \ No newline at end of file + + + \ No newline at end of file diff --git a/modules/claim/front/action/index.js b/modules/claim/front/action/index.js index ec93f2ae1..0b12a54d0 100644 --- a/modules/claim/front/action/index.js +++ b/modules/claim/front/action/index.js @@ -23,6 +23,7 @@ class Controller { ] }; this.resolvedState = 3; + this.maxResponsibility = 5; } openAddSalesDialog() { @@ -135,9 +136,29 @@ class Controller { this.$http.post(query, data).then(() => { this.card.reload(); this.vnApp.showSuccess(this.$translate.instant('Data saved!')); + if (this.claim.responsibility >= Math.ceil(this.maxResponsibility) / 2) + this.$.updateGreuge.show(); }); } + onUpdateGreugeResponse(response) { + if (response !== 'ACCEPT') + return; + let greugeTypeFreight = 7; + let query = `claim/api/Greuges/`; + let data = { + clientFk: this.claim.clientFk, + description: `claim: ${this.claim.id}`, + amount: 11, + greugeTypeFk: greugeTypeFreight, + ticketFk: this.claim.ticketFk + }; + + this.$http.post(query, data).then(() => { + this.card.reload(); + this.vnApp.showSuccess(this.$translate.instant('Greuge inserted!')); + }); + } // Item Descriptor showDescriptor(event, itemFk) { this.quicklinks = { diff --git a/modules/claim/front/action/index.spec.js b/modules/claim/front/action/index.spec.js index 22f3f321b..9842bf646 100644 --- a/modules/claim/front/action/index.spec.js +++ b/modules/claim/front/action/index.spec.js @@ -158,5 +158,37 @@ describe('claim', () => { expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!'); }); }); + + describe('onUpdateGreugeResponse()', () => { + it('should do nothing', () => { + spyOn(controller.card, 'reload'); + spyOn(controller.vnApp, 'showSuccess'); + + controller.onUpdateGreugeResponse('CANCEL'); + + expect(controller.card.reload).not.toHaveBeenCalledWith(); + expect(controller.vnApp.showSuccess).not.toHaveBeenCalledWith('Greuge inserted!'); + }); + + it('should perform a insert into greuges', () => { + spyOn(controller.card, 'reload'); + spyOn(controller.vnApp, 'showSuccess'); + controller.claim.clientFk = 101; + controller.claim.id = 11; + let data = { + clientFk: 101, + description: `claim: ${controller.claim.id}`, + amount: 11, + greugeTypeFk: 7, + ticketFk: controller.claim.ticketFk + }; + $httpBackend.expect('POST', `claim/api/Greuges/`, data).respond(); + controller.onUpdateGreugeResponse('ACCEPT'); + $httpBackend.flush(); + + expect(controller.card.reload).toHaveBeenCalledWith(); + expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Greuge inserted!'); + }); + }); }); }); diff --git a/modules/claim/front/action/locale/es.yml b/modules/claim/front/action/locale/es.yml index 8112d3c89..3950ec06a 100644 --- a/modules/claim/front/action/locale/es.yml +++ b/modules/claim/front/action/locale/es.yml @@ -5,4 +5,7 @@ Import claim: Importar reclamacion Imports claim details: Importa detalles de la reclamacion Import ticket: Importar ticket Imports ticket lines: Importa las lineas de un ticket -Regularize: Regularizar \ No newline at end of file +Regularize: Regularizar +Do you want to insert greuges?: Desea insertar greuges? +Insert greuges on client card: Insertar greuges en la ficha del cliente +Greuge inserted: Greuge insertado \ No newline at end of file diff --git a/modules/claim/front/index/index.html b/modules/claim/front/index/index.html index a486eac3b..f6945e834 100644 --- a/modules/claim/front/index/index.html +++ b/modules/claim/front/index/index.html @@ -1,19 +1,17 @@ + order="claimStateFk ASC, created DESC">
@@ -38,7 +36,7 @@ {{::claim.id}} - {{::claim.client.name}} + {{::claim.name}} {{::claim.created | dateTime:'dd/MM/yyyy'}} @@ -46,12 +44,12 @@ - {{::claim.worker.user.nickname}} + {{::claim.nickName}} - {{::claim.claimState.description}} + {{::claim.description}} diff --git a/modules/claim/front/index/index.js b/modules/claim/front/index/index.js index ec9624845..c8462bc48 100644 --- a/modules/claim/front/index/index.js +++ b/modules/claim/front/index/index.js @@ -4,58 +4,10 @@ export default class Controller { constructor($scope) { this.$ = $scope; this.ticketSelected = null; - - this.filter = { - include: [ - { - relation: 'client', - scope: { - fields: ['name'] - } - }, - { - relation: 'worker', - scope: { - fields: ['userFk'], - include: { - relation: 'user', - scope: { - fields: ['nickname'] - } - } - } - }, - { - relation: 'claimState', - scope: { - fields: ['description'] - } - } - ], - order: 'claimStateFk ASC, created DESC' - }; - } - - exprBuilder(param, value) { - switch (param) { - case 'search': - return /^\d+$/.test(value) - ? {id: value} - : {client: {like: `%${value}%`}}; - case 'client': - return {[param]: {like: `%${value}%`}}; - case 'created': - return {created: {between: [value, value]}}; - case 'id': - case 'clientFk': - case 'workerFk': - case 'claimStateFk': - return {[param]: value}; - } } stateColor(claim) { - switch (claim.claimState.description) { + switch (claim.description) { case 'Pendiente': return 'warning'; case 'Gestionado': @@ -91,6 +43,13 @@ export default class Controller { onDescriptorLoad() { this.$.popover.relocate(); } + + onSearch(params) { + if (params) + this.$.model.applyFilter(null, params); + else + this.$.model.clear(); + } } Controller.$inject = ['$scope']; diff --git a/modules/claim/front/locale/es.yml b/modules/claim/front/locale/es.yml index 307494dcd..6c33a779f 100644 --- a/modules/claim/front/locale/es.yml +++ b/modules/claim/front/locale/es.yml @@ -10,4 +10,5 @@ Claim Id: Id reclamación Created: Creado Send Pickup order: Enviar orden de recogida Show Pickup order: Ver orden de recogida +Search claim by id or client name: Buscar reclamaciones por identificador o nombre de cliente diff --git a/modules/claim/front/search-panel/index.html b/modules/claim/front/search-panel/index.html index 2ce6b704a..580c96eda 100644 --- a/modules/claim/front/search-panel/index.html +++ b/modules/claim/front/search-panel/index.html @@ -5,6 +5,7 @@ vn-one label="General search" model="filter.search" + info="Search claim by id or client name" vn-focus> diff --git a/modules/client/back/methods/sms/send.js b/modules/client/back/methods/sms/send.js index 539b6e546..d11b722f5 100644 --- a/modules/client/back/methods/sms/send.js +++ b/modules/client/back/methods/sms/send.js @@ -6,11 +6,11 @@ module.exports = Self => { Self.remoteMethodCtx('send', { description: 'Sends SMS to a destination phone', accepts: [{ - arg: 'recipientFk', + arg: 'destinationFk', type: 'Integer' }, { - arg: 'recipient', + arg: 'destination', type: 'String', required: true, }, @@ -20,7 +20,7 @@ module.exports = Self => { required: true, }], returns: { - type: 'boolean', + type: 'Object', root: true }, http: { @@ -29,7 +29,7 @@ module.exports = Self => { } }); - Self.send = async(ctx, recipientFk, recipient, message) => { + Self.send = async(ctx, destinationFk, destination, message) => { const userId = ctx.req.accessToken.userId; const smsConfig = await Self.app.models.SmsConfig.findOne(); const soapClient = await soap.createClientAsync(smsConfig.uri); @@ -37,7 +37,7 @@ module.exports = Self => { user: smsConfig.user, pass: smsConfig.password, src: smsConfig.title, - dst: recipient, + dst: destination, msg: message }; @@ -61,18 +61,21 @@ module.exports = Self => { console.error(e); } + const statusCode = status.codigo[0]; + const statusDescription = status.descripcion[0]; + const newSms = { senderFk: userId, - destinationFk: recipientFk || null, - destination: recipient, + destinationFk: destinationFk || null, + destination: destination, message: message, - statusCode: status.codigo, - status: status.descripcion + statusCode: statusCode, + status: statusDescription }; - const sms = Self.create(newSms); + const sms = await Self.create(newSms); - if (status.codigo != 200) + if (statusCode != 200) throw new UserError(`We weren't able to send this SMS`); return sms; diff --git a/modules/client/back/methods/sms/specs/send.spec.js b/modules/client/back/methods/sms/specs/send.spec.js index 0045b148a..475e9fc1c 100644 --- a/modules/client/back/methods/sms/specs/send.spec.js +++ b/modules/client/back/methods/sms/specs/send.spec.js @@ -8,7 +8,7 @@ const app = require('vn-loopback/server/server'); describe('sms send()', () => { it('should should return the expected message and status code', async() => { let ctx = {req: {accessToken: {userId: 1}}}; - let result = await app.models.Sms.send(ctx, null, 'Invalid', 'My SMS Body'); + let result = await app.models.Sms.send(ctx, 101, 'Invalid', 'My SMS Body'); expect(result.statusCode).toEqual(200); expect(result.status).toEqual('Envio en procesamiento'); diff --git a/modules/client/back/models/sms.json b/modules/client/back/models/sms.json index ec458e73d..aa9737478 100644 --- a/modules/client/back/models/sms.json +++ b/modules/client/back/models/sms.json @@ -1,7 +1,11 @@ { "name": "Sms", "description": "Sms sent to client", - "base": "VnModel", + "base": "Loggable", + "log": { + "model":"ClientLog", + "relation": "recipient" + }, "options": { "mysql": { "table": "sms" diff --git a/modules/client/front/index/index.html b/modules/client/front/index/index.html index da718f952..8873e10ae 100644 --- a/modules/client/front/index/index.html +++ b/modules/client/front/index/index.html @@ -13,6 +13,7 @@ panel="vn-client-search-panel" model="model" expr-builder="$ctrl.exprBuilder(param, value)" + info="Search client by id or name" vn-focus> diff --git a/modules/client/front/locale/es.yml b/modules/client/front/locale/es.yml index ed38dfe0d..8c154bbf4 100644 --- a/modules/client/front/locale/es.yml +++ b/modules/client/front/locale/es.yml @@ -27,6 +27,7 @@ Client inactive: Cliente inactivo Client not checked: Cliente no comprobado Credit insurance: Crédito asegurado Web Account inactive: Sin acceso Web +Search client by id or name: Buscar clientes por identificador o nombre # Sections diff --git a/modules/client/front/search-panel/index.html b/modules/client/front/search-panel/index.html index 9fb1aaf3e..b33d9d7c9 100644 --- a/modules/client/front/search-panel/index.html +++ b/modules/client/front/search-panel/index.html @@ -5,6 +5,7 @@ vn-one label="General search" model="filter.search" + info="Search client by id or name" vn-focus> diff --git a/modules/client/front/sms/index.html b/modules/client/front/sms/index.html index 30bf2dcc8..9d907e5c2 100644 --- a/modules/client/front/sms/index.html +++ b/modules/client/front/sms/index.html @@ -5,8 +5,8 @@
Send SMS
+ label="Destination" + model="$ctrl.sms.destination"> diff --git a/modules/client/front/sms/index.js b/modules/client/front/sms/index.js index 03bafdec0..19d9ab3ea 100644 --- a/modules/client/front/sms/index.js +++ b/modules/client/front/sms/index.js @@ -18,11 +18,7 @@ class Controller extends Component { onResponse(response) { if (response === 'ACCEPT') { - let params = { - recipient: this.sms.recipient, - message: this.sms.message - }; - this.$http.post(`/client/api/Sms/send`, params).then(res => { + this.$http.post(`/client/api/Sms/send`, this.sms).then(res => { this.vnApp.showMessage(this.$translate.instant('SMS sent!')); if (res.data) this.emit('send', {response: res.data}); diff --git a/modules/client/front/sms/index.spec.js b/modules/client/front/sms/index.spec.js index e8f530025..a1f18c23f 100644 --- a/modules/client/front/sms/index.spec.js +++ b/modules/client/front/sms/index.spec.js @@ -17,8 +17,8 @@ describe('Client', () => { describe('onResponse()', () => { it('should perform a POST query and show a success snackbar', () => { - let params = {recipient: 111111111, message: 'My SMS'}; - controller.sms = {recipient: 111111111, message: 'My SMS'}; + let params = {destinationFk: 101, destination: 111111111, message: 'My SMS'}; + controller.sms = {destinationFk: 101, destination: 111111111, message: 'My SMS'}; spyOn(controller.vnApp, 'showMessage'); $httpBackend.when('POST', `/client/api/Sms/send`, params).respond(200, params); diff --git a/modules/client/front/sms/locale/es.yml b/modules/client/front/sms/locale/es.yml index 28933f774..10247b926 100644 --- a/modules/client/front/sms/locale/es.yml +++ b/modules/client/front/sms/locale/es.yml @@ -1,4 +1,4 @@ Send SMS: Enviar SMS -Recipient: Destinatario +Destination: Destinatario Message: Mensaje SMS sent!: ¡SMS enviado! \ No newline at end of file diff --git a/modules/invoiceOut/front/index/index.html b/modules/invoiceOut/front/index/index.html index 79c075777..98c286dbc 100644 --- a/modules/invoiceOut/front/index/index.html +++ b/modules/invoiceOut/front/index/index.html @@ -15,6 +15,7 @@ model="model" expr-builder="$ctrl.exprBuilder(param, value)" auto-load="true" + info="Search invoices by reference" vn-focus> diff --git a/modules/invoiceOut/front/locale/es.yml b/modules/invoiceOut/front/locale/es.yml index 4981025e8..87de48f56 100644 --- a/modules/invoiceOut/front/locale/es.yml +++ b/modules/invoiceOut/front/locale/es.yml @@ -1 +1,2 @@ -Invoice out: Facturas \ No newline at end of file +Invoice out: Facturas +Search invoices by reference: Buscar facturas por referencia \ No newline at end of file diff --git a/modules/invoiceOut/front/search-panel/index.html b/modules/invoiceOut/front/search-panel/index.html index 40bd57736..1abded45a 100644 --- a/modules/invoiceOut/front/search-panel/index.html +++ b/modules/invoiceOut/front/search-panel/index.html @@ -5,6 +5,7 @@ vn-one label="General search" model="filter.search" + info="Search invoices by reference" vn-focus> diff --git a/modules/item/front/index/index.html b/modules/item/front/index/index.html index 1157c40c9..6fb0fdfb5 100644 --- a/modules/item/front/index/index.html +++ b/modules/item/front/index/index.html @@ -14,6 +14,7 @@ vn-three panel="vn-item-search-panel" on-search="$ctrl.onSearch($params)" + info="Search items by id, name or barcode" vn-focus> diff --git a/modules/order/front/index/index.html b/modules/order/front/index/index.html index 705fb5c7a..c5d29c292 100644 --- a/modules/order/front/index/index.html +++ b/modules/order/front/index/index.html @@ -11,6 +11,7 @@ diff --git a/modules/order/front/locale/es.yml b/modules/order/front/locale/es.yml index 8fa991bc7..cd32325eb 100644 --- a/modules/order/front/locale/es.yml +++ b/modules/order/front/locale/es.yml @@ -19,4 +19,5 @@ Order: Orden Price: Precio Ascendant: Ascendente Descendant: Descendente -Created from: Creado desde \ No newline at end of file +Created from: Creado desde +Search orders by id: Buscar en la cesta por identificador \ No newline at end of file diff --git a/modules/order/front/search-panel/index.html b/modules/order/front/search-panel/index.html index 0af885a53..2a6f33b8c 100644 --- a/modules/order/front/search-panel/index.html +++ b/modules/order/front/search-panel/index.html @@ -5,6 +5,7 @@ vn-one label="General search" model="filter.search" + info="Search orders by id" vn-focus> diff --git a/modules/route/front/descriptor/index.html b/modules/route/front/descriptor/index.html index 9ccd7444b..2a2600177 100644 --- a/modules/route/front/descriptor/index.html +++ b/modules/route/front/descriptor/index.html @@ -6,6 +6,15 @@ + +
diff --git a/modules/route/front/descriptor/index.js b/modules/route/front/descriptor/index.js index 5c47c864f..ca2a3de0c 100644 --- a/modules/route/front/descriptor/index.js +++ b/modules/route/front/descriptor/index.js @@ -1,6 +1,16 @@ import ngModule from '../module'; class Controller { + constructor($, $http, vnApp, $translate) { + this.$http = $http; + this.vnApp = vnApp; + this.$translate = $translate; + this.$ = $; + this.moreOptions = [ + {callback: this.showRouteReport, name: 'Show route report'}, + {callback: this.sendRouteReport, name: 'Send route report'} + ]; + } set quicklinks(value = {}) { this._quicklinks = Object.assign(value, this._quicklinks); } @@ -8,9 +18,25 @@ class Controller { get quicklinks() { return this._quicklinks; } + + onMoreChange(callback) { + callback.call(this); + } + + showRouteReport() { + let url = `/api/report/rpt-route?routeFk=${this.route.id}`; + window.open(url); + } + + sendRouteReport() { + let url = `/api/email/driver-route?routeFk=${this.route.id}`; + this.$http.post(url).then(() => { + this.vnApp.showSuccess(this.$translate.instant('Report sent')); + }); + } } -Controller.$inject = ['$http', '$state']; +Controller.$inject = ['$scope', '$http', 'vnApp', '$translate']; ngModule.component('vnRouteDescriptor', { template: require('./index.html'), diff --git a/modules/route/front/descriptor/locale/es.yml b/modules/route/front/descriptor/locale/es.yml index 3f7596ae0..3fd58aed6 100644 --- a/modules/route/front/descriptor/locale/es.yml +++ b/modules/route/front/descriptor/locale/es.yml @@ -1,2 +1,4 @@ Volume exceded: Volumen excedido -Volume: Volumen \ No newline at end of file +Volume: Volumen +Send route report: Enviar informe de ruta +Show route report: Ver informe de ruta \ No newline at end of file diff --git a/modules/route/front/index/index.html b/modules/route/front/index/index.html index 62bfee7f9..43238fd4d 100644 --- a/modules/route/front/index/index.html +++ b/modules/route/front/index/index.html @@ -14,6 +14,7 @@ model="model" expr-builder="$ctrl.exprBuilder(param, value)" auto-load="true" + info="Search routes by id" vn-focus> diff --git a/modules/route/front/locale/es.yml b/modules/route/front/locale/es.yml index 5c60e1724..0b6c1f2b3 100644 --- a/modules/route/front/locale/es.yml +++ b/modules/route/front/locale/es.yml @@ -1 +1,2 @@ -Routes: Rutas \ No newline at end of file +Routes: Rutas +Search routes by id: Buscar rutas por identificador \ No newline at end of file diff --git a/modules/route/front/search-panel/index.html b/modules/route/front/search-panel/index.html index 337d96121..5be281981 100644 --- a/modules/route/front/search-panel/index.html +++ b/modules/route/front/search-panel/index.html @@ -5,6 +5,7 @@ vn-one label="General search" model="filter.search" + info="Search routes by id" vn-focus> diff --git a/modules/ticket/back/methods/ticket-request/confirm.js b/modules/ticket/back/methods/ticket-request/confirm.js index 6bef90b4c..f9888f9e0 100644 --- a/modules/ticket/back/methods/ticket-request/confirm.js +++ b/modules/ticket/back/methods/ticket-request/confirm.js @@ -31,15 +31,16 @@ module.exports = Self => { }); Self.confirm = async ctx => { + const models = Self.app.models; let transaction = await Self.beginTransaction({}); let options = {transaction: transaction}; try { - let item = await Self.app.models.Item.findById(ctx.args.itemFk); + let item = await models.Item.findById(ctx.args.itemFk); if (!item) throw new UserError(`That item doesn't exists`); - let request = await Self.app.models.TicketRequest.findById(ctx.args.id, { + let request = await models.TicketRequest.findById(ctx.args.id, { include: {relation: 'ticket'} }); @@ -60,15 +61,19 @@ module.exports = Self => { if (request.saleFk) { - let sale = await Self.app.models.Sale.findById(request.saleFk); - sale.updateAttributes({itemFk: ctx.args.itemFk, quantity: ctx.args.quantity, description: item.description}, options); + let sale = await models.Sale.findById(request.saleFk); + sale.updateAttributes({ + itemFk: ctx.args.itemFk, + quantity: ctx.args.quantity, + description: item.description + }, options); } else { params = { ticketFk: request.ticketFk, itemFk: ctx.args.itemFk, quantity: ctx.args.quantity }; - sale = await Self.app.models.Sale.create(params, options); + sale = await models.Sale.create(params, options); request.updateAttributes({saleFk: sale.id, itemFk: sale.itemFk}, options); } @@ -76,6 +81,14 @@ module.exports = Self => { params = [sale.id]; await Self.rawSql(query, params, options); + const message = `Se ha comprado ${params.quantity} unidades de "${item.description}" (#${params.itemFk}) ` + + `para el ticket #${params.ticketFk}`; + + await models.Message.send(ctx, { + recipientFk: request.requesterFk, + message: message + }, options); + await transaction.commit(); } catch (error) { await transaction.rollback(); diff --git a/modules/ticket/back/methods/ticket/makeInvoice.js b/modules/ticket/back/methods/ticket/makeInvoice.js index b472cfa81..1bc514990 100644 --- a/modules/ticket/back/methods/ticket/makeInvoice.js +++ b/modules/ticket/back/methods/ticket/makeInvoice.js @@ -2,14 +2,14 @@ const UserError = require('vn-loopback/util/user-error'); module.exports = function(Self) { Self.remoteMethodCtx('makeInvoice', { - description: 'Change property isEqualizated in all client addresses', + description: 'Make out an invoice from a ticket id', accessType: 'WRITE', accepts: [ { arg: 'id', type: 'string', required: true, - description: 'Client id', + description: 'Ticket id', http: {source: 'path'} } ], @@ -53,7 +53,7 @@ module.exports = function(Self) { query = `CALL vn.invoiceOutMake(?, ?, @invoiceId); SELECT @invoiceId AS invoiceId;`; result = await Self.rawSql(query, [serial, null], options); - let invoice = result[1].invoiceId; + let invoice = result[1][0].invoiceId; if (serial != 'R' && invoice) { query = `CALL vn.invoiceOutBooking(?)`; @@ -62,9 +62,11 @@ module.exports = function(Self) { let user = await Self.app.models.Worker.findOne({where: {userFk: userId}}); - query = `INSERT INTO vn2008.Colas(Id_Informe,Cola,Id_Trabajador) VALUES (?, ?, ?)`; + query = `INSERT INTO printServerQueue(reportFk, param1, workerFk) VALUES (?, ?, ?)`; await Self.rawSql(query, [3, invoice, user.id], options); await options.transaction.commit(); + + return {invoiceFk: invoice, serial}; } catch (e) { options.transaction.rollback(); throw e; diff --git a/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js new file mode 100644 index 000000000..b33b92e13 --- /dev/null +++ b/modules/ticket/back/methods/ticket/specs/makeInvoice.spec.js @@ -0,0 +1,39 @@ +const app = require('vn-loopback/server/server'); + +describe('ticket makeInvoice()', () => { + let invoice; + + afterAll(async done => { + let ticket = await app.models.Ticket.findById(11); + ticket.updateAttributes({refFk: null}); + + let ticketTracking = await app.models.TicketTracking.findOne({order: 'id DESC', limit: 1}); + ticketTracking.destroy(); + + let invoiceOut = await app.models.InvoiceOut.findById(invoice.invoiceFk); + invoiceOut.destroy(); + + done(); + }); + + it('should invoice a ticket', async() => { + let ctx = {req: {accessToken: {userId: 9}}}; + let ticketFk = 11; + invoice = await app.models.Ticket.makeInvoice(ctx, ticketFk); + + expect(invoice.invoiceFk).not.toBeNaN(); + expect(invoice.serial).toEqual('T'); + }); + + it('should not invoice an already invoiced ticket', async() => { + let ctx = {req: {accessToken: {userId: 9}}}; + let ticketFk = 11; + let error; + + await app.models.Ticket.makeInvoice(ctx, ticketFk).catch(e => { + error = e; + }).finally(() => { + expect(error.message).toEqual(`This ticket can't be invoiced`); + }); + }); +}); diff --git a/modules/ticket/front/descriptor/index.html b/modules/ticket/front/descriptor/index.html index dbe8f8c89..779ce7e53 100644 --- a/modules/ticket/front/descriptor/index.html +++ b/modules/ticket/front/descriptor/index.html @@ -179,6 +179,15 @@ + + + + + \ No newline at end of file diff --git a/modules/ticket/front/descriptor/index.js b/modules/ticket/front/descriptor/index.js index 5c7d81ab9..0e153b8fc 100644 --- a/modules/ticket/front/descriptor/index.js +++ b/modules/ticket/front/descriptor/index.js @@ -1,21 +1,23 @@ import ngModule from '../module'; class Controller { - constructor($state, $scope, $http, vnApp, $translate) { + constructor($state, $scope, $http, vnApp, $translate, aclService) { this.$scope = $scope; this.$state = $state; this.$http = $http; this.vnApp = vnApp; this.$translate = $translate; + this.aclService = aclService; this.moreOptions = [ - {callback: this.showAddTurnDialog, name: 'Add turn', show: true}, + {callback: this.showAddTurnDialog, name: 'Add turn'}, {callback: this.showAddStowaway, name: 'Add stowaway', show: () => this.isTicketModule()}, {callback: this.showRemoveStowaway, name: 'Remove stowaway', show: () => this.shouldShowRemoveStowaway()}, - {callback: this.showDeliveryNote, name: 'Show Delivery Note', show: true}, - {callback: this.showDeleteTicketDialog, name: 'Delete ticket', show: true}, - {callback: this.showChangeShipped, name: 'Change shipped hour', show: true}, - {callback: this.showSMSDialog, name: 'Send SMS', show: true}, - {callback: this.openRptRoute, name: 'Show pallet report', show: true} + {callback: this.showInvoiceOutMakeDialog, name: 'Make invoice', acl: 'invoicing'}, + {callback: this.showDeliveryNote, name: 'Show Delivery Note'}, + {callback: this.showDeleteTicketDialog, name: 'Delete ticket'}, + {callback: this.showChangeShipped, name: 'Change shipped hour'}, + {callback: this.showSMSDialog, name: 'Send SMS'}, + {callback: this.openRptRoute, name: 'Show pallet report'} ]; } @@ -63,8 +65,13 @@ class Controller { } onMoreOpen() { - let options = this.moreOptions.filter(o => { - return o.show === true || typeof o.show === 'function' && o.show(); + let options = this.moreOptions.filter(option => { + const hasShowProperty = Object.hasOwnProperty.call(option, 'show'); + const hasAclProperty = Object.hasOwnProperty.call(option, 'acl'); + const hasAcl = !hasAclProperty || (hasAclProperty && this.aclService.hasAny([option.acl])); + + return (!hasShowProperty || option.show === true || + typeof option.show === 'function' && option.show()) && hasAcl; }); this.$scope.moreButton.data = options; } @@ -175,14 +182,38 @@ class Controller { showSMSDialog() { const address = this.ticket.address; this.newSMS = { - recipient: address.mobile || null, + destinationFk: this.ticket.clientFk, + destination: address.mobile || null, message: this.$translate.instant('SMSPayment') }; this.$scope.sms.open(); } + + /** + * Shows an invoice confirmation + */ + showInvoiceOutMakeDialog() { + this.$scope.invoiceMakeConfirmation.show(); + } + + /** + * Makes an invoice + * from current ticket + * + * @param {String} response - Response result + */ + invoiceMakeOut(response) { + if (response === 'ACCEPT') { + const query = `/ticket/api/Tickets/${this.ticket.id}/makeInvoice`; + this.$http.post(query).then(() => { + this.vnApp.showSuccess(this.$translate.instant('Ticket invoiced')); + this.$state.reload(); + }); + } + } } -Controller.$inject = ['$state', '$scope', '$http', 'vnApp', '$translate']; +Controller.$inject = ['$state', '$scope', '$http', 'vnApp', '$translate', 'aclService']; ngModule.component('vnTicketDescriptor', { template: require('./index.html'), diff --git a/modules/ticket/front/descriptor/index.spec.js b/modules/ticket/front/descriptor/index.spec.js index 2c2359299..8e5a43f71 100644 --- a/modules/ticket/front/descriptor/index.spec.js +++ b/modules/ticket/front/descriptor/index.spec.js @@ -77,5 +77,20 @@ describe('Ticket Component vnTicketDescriptor', () => { expect(window.open).toHaveBeenCalledWith(expectedPath); }); }); + + describe('invoiceMakeOut(response)', () => { + it('should make a query and call $state.reload() method if the response is ACCEPT', () => { + spyOn(controller.$state, 'reload'); + spyOn(controller.vnApp, 'showSuccess'); + + $httpBackend.when('POST', `/ticket/api/Tickets/2/makeInvoice`).respond(); + $httpBackend.expect('POST', `/ticket/api/Tickets/2/makeInvoice`).respond(); + controller.invoiceMakeOut('ACCEPT'); + $httpBackend.flush(); + + expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Ticket invoiced'); + expect(controller.$state.reload).toHaveBeenCalledWith(); + }); + }); }); diff --git a/modules/ticket/front/descriptor/locale/es.yml b/modules/ticket/front/descriptor/locale/es.yml index 3ce9905cb..0e0d0bdd6 100644 --- a/modules/ticket/front/descriptor/locale/es.yml +++ b/modules/ticket/front/descriptor/locale/es.yml @@ -6,11 +6,15 @@ Stowaways to add: Polizones a añadir Stowaways of the ticket: Polizones del ticket Add stowaway: Añadir polizón Remove stowaway: Borrar polizón -Are you sure you want to delete this stowaway?: ¿Estas seguro de que quieres borrar este polizón? +Are you sure you want to delete this stowaway?: ¿Seguro que quieres borrar este polizón? Show Delivery Note: Ver albarán Show pallet report: Mostrar hoja de pallet Change shipped hour: Cambiar hora de envío Shipped hour: Hora de envío SMSPayment: >- Verdnatura le comunica: Su pedido está pendiente de pago. - Por favor, entre en la página web y efectue el pago con tarjeta. Muchas gracias. \ No newline at end of file + Por favor, entre en la página web y efectue el pago con tarjeta. Muchas gracias. +Ticket invoiced: Ticket facturado +Make invoice: Facturar +You are going to invoice this ticket: Vas a facturar este ticket +Are you sure you want to invoice this ticket?: ¿Seguro que quieres facturar este ticket? \ No newline at end of file diff --git a/modules/ticket/front/index/index.html b/modules/ticket/front/index/index.html index 70aabd729..9a494b6a8 100644 --- a/modules/ticket/front/index/index.html +++ b/modules/ticket/front/index/index.html @@ -15,6 +15,7 @@ style="width: 100%" panel="vn-ticket-search-panel" on-search="$ctrl.onSearch($params)" + info="Search ticket by id or alias" vn-focus> diff --git a/modules/ticket/front/sale/index.js b/modules/ticket/front/sale/index.js index 492dd831c..16b668c4e 100644 --- a/modules/ticket/front/sale/index.js +++ b/modules/ticket/front/sale/index.js @@ -331,7 +331,8 @@ class Controller { notAvailables }; this.newSMS = { - recipient: address.mobile || null, + destinationFk: this.ticket.clientFk, + destination: address.mobile || null, message: this.$translate.instant('SMSAvailability', params) }; this.$scope.sms.open(); diff --git a/modules/ticket/front/sale/index.spec.js b/modules/ticket/front/sale/index.spec.js index 113e29c80..23bc4b809 100644 --- a/modules/ticket/front/sale/index.spec.js +++ b/modules/ticket/front/sale/index.spec.js @@ -180,7 +180,7 @@ describe('Ticket', () => { controller.showSMSDialog(); expect(controller.$scope.sms.open).toHaveBeenCalledWith(); - expect(controller.newSMS.recipient).toEqual(111111111); + expect(controller.newSMS.destination).toEqual(111111111); expect(controller.newSMS.message).not.toEqual(''); }); }); diff --git a/modules/ticket/front/search-panel/index.html b/modules/ticket/front/search-panel/index.html index 35802bc7c..7e3267f45 100644 --- a/modules/ticket/front/search-panel/index.html +++ b/modules/ticket/front/search-panel/index.html @@ -5,6 +5,7 @@ vn-one label="General search" model="filter.search" + info="Search ticket by id or alias" vn-focus> diff --git a/modules/travel/front/index/index.html b/modules/travel/front/index/index.html index c649d24fb..9b5d4c829 100644 --- a/modules/travel/front/index/index.html +++ b/modules/travel/front/index/index.html @@ -13,6 +13,7 @@ panel="vn-travel-search-panel" model="model" expr-builder="$ctrl.exprBuilder(param, value)" + info="Search travels by id" vn-focus> diff --git a/modules/travel/front/locale/es.yml b/modules/travel/front/locale/es.yml index b2eb3297c..d474130ae 100644 --- a/modules/travel/front/locale/es.yml +++ b/modules/travel/front/locale/es.yml @@ -7,6 +7,7 @@ Landed: F. llegada Delivered: Enviado Received: Recibido Travel id: Id envío +Search travels by id: Buscar envios por identificador # Sections Travels: Envíos \ No newline at end of file diff --git a/modules/travel/front/search-panel/index.html b/modules/travel/front/search-panel/index.html index c6662836c..2a763767e 100644 --- a/modules/travel/front/search-panel/index.html +++ b/modules/travel/front/search-panel/index.html @@ -5,6 +5,7 @@ vn-one label="General search" model="filter.search" + info="Search travels by id" vn-focus> diff --git a/modules/worker/front/index/index.html b/modules/worker/front/index/index.html index d6e42ddd1..70c3b806f 100644 --- a/modules/worker/front/index/index.html +++ b/modules/worker/front/index/index.html @@ -1,6 +1,6 @@ @@ -13,6 +13,7 @@ style="width: 100%" panel="vn-worker-search-panel" on-search="$ctrl.onSearch($params)" + info="Search workers by id, firstName, lastName or user name" vn-focus> diff --git a/print/common/css/layout.css b/print/common/css/layout.css index 560309a0d..3e302d675 100644 --- a/print/common/css/layout.css +++ b/print/common/css/layout.css @@ -99,6 +99,11 @@ width: 35.4px } +.field.rectangle span { + height: 2em; + width: 8em +} + .pull-left { float: left !important } diff --git a/print/common/css/misc.css b/print/common/css/misc.css index a31279ee2..16a37b6c3 100644 --- a/print/common/css/misc.css +++ b/print/common/css/misc.css @@ -10,6 +10,14 @@ text-align: center } +.align-right { + text-align: right +} + +.align-left { + text-align: left +} + .number { text-align: right } @@ -28,4 +36,8 @@ .font.bold { font-weight: bold +} + +.non-page-break { + page-break-inside: avoid; } \ No newline at end of file diff --git a/print/config/routes.json b/print/config/routes.json index 95e881f0a..69b94a6e4 100644 --- a/print/config/routes.json +++ b/print/config/routes.json @@ -6,12 +6,13 @@ {"type": "email", "name": "letter-debtor-nd"}, {"type": "email", "name": "claim-pickup-order"}, {"type": "email", "name": "sepa-core"}, + {"type": "email", "name": "driver-route"}, {"type": "report", "name": "rpt-delivery-note"}, - {"type": "report", "name": "rpt-invoice"}, {"type": "report", "name": "rpt-claim-pickup-order"}, {"type": "report", "name": "rpt-letter-debtor"}, {"type": "report", "name": "rpt-sepa-core"}, {"type": "report", "name": "rpt-receipt"}, + {"type": "report", "name": "rpt-zone"}, {"type": "report", "name": "rpt-route"}, {"type": "static", "name": "email-header"}, {"type": "static", "name": "email-footer"}, diff --git a/print/report/driver-route/assets/css/index.js b/print/report/driver-route/assets/css/index.js new file mode 100644 index 000000000..321c632dc --- /dev/null +++ b/print/report/driver-route/assets/css/index.js @@ -0,0 +1,7 @@ +const CssReader = require(`${appPath}/lib/cssReader`); + +module.exports = new CssReader([ + `${appPath}/common/css/layout.css`, + `${appPath}/common/css/email.css`, + `${appPath}/common/css/misc.css`]) + .mergeStyles(); diff --git a/print/report/driver-route/index.html b/print/report/driver-route/index.html new file mode 100644 index 000000000..45dbd3e1f --- /dev/null +++ b/print/report/driver-route/index.html @@ -0,0 +1,24 @@ + + + + {{ $t('subject') }} + + +
+ + + +
+ +
+

{{ $t('title') }}

+
+ +

{{$t('description.instructions')}}

+
+ + + +
+ + \ No newline at end of file diff --git a/print/report/driver-route/index.js b/print/report/driver-route/index.js new file mode 100755 index 000000000..2a142856f --- /dev/null +++ b/print/report/driver-route/index.js @@ -0,0 +1,54 @@ +const UserException = require(`${appPath}/lib/exceptions/userException`); +const reportEngine = require(`${appPath}/lib/reportEngine`); +const database = require(`${appPath}/lib/database`); +const emailHeader = require('../email-header'); +const emailFooter = require('../email-footer'); + + +module.exports = { + name: 'driver-route', + async asyncData(ctx, params) { + const promises = []; + const data = { + isPreview: ctx.method === 'GET', + }; + + if (!params.routeFk) + throw new UserException('No route id specified'); + + promises.push(reportEngine.toPdf('rpt-route', ctx)); + promises.push(this.methods.fetchRoute(params.routeFk)); + + return Promise.all(promises).then(result => { + const stream = result[0]; + const [[route]] = result[1]; + + Object.assign(data, route); + Object.assign(data, {attachments: [{filename: 'driver-route.pdf', content: stream}]}); + + return data; + }); + }, + created() { + if (this.locale) + this.$i18n.locale = this.locale; + }, + methods: { + fetchRoute(routeFk) { + return database.pool.query(` + SELECT + u.id, + u.lang AS locale, + mu.email AS recipient + FROM route r + LEFT JOIN worker w ON w.id = r.workerFk + LEFT JOIN account.user u ON u.id = w.userFk + LEFT JOIN account.emailUser mu ON mu.userFk = u.id + WHERE r.id = ?`, [routeFk]); + }, + }, + components: { + emailHeader, + emailFooter, + }, +}; diff --git a/print/report/driver-route/locale.js b/print/report/driver-route/locale.js new file mode 100644 index 000000000..9255f8f97 --- /dev/null +++ b/print/report/driver-route/locale.js @@ -0,0 +1,11 @@ +module.exports = { + messages: { + es: { + subject: 'Hoja de ruta', + title: 'Hoja de ruta', + description: { + instructions: 'Adjuntamos tu hoja de ruta.' + }, + }, + }, +}; diff --git a/print/report/rpt-route/assets/css/index.js b/print/report/rpt-route/assets/css/index.js index 06417fcee..515dea750 100644 --- a/print/report/rpt-route/assets/css/index.js +++ b/print/report/rpt-route/assets/css/index.js @@ -3,5 +3,6 @@ const CssReader = require(`${appPath}/lib/cssReader`); module.exports = new CssReader([ `${appPath}/common/css/layout.css`, `${appPath}/common/css/report.css`, + `${appPath}/common/css/misc.css`, `${__dirname}/style.css`]) .mergeStyles(); diff --git a/print/report/rpt-route/assets/css/style.css b/print/report/rpt-route/assets/css/style.css index 82e5c33f1..2e7ec4dab 100644 --- a/print/report/rpt-route/assets/css/style.css +++ b/print/report/rpt-route/assets/css/style.css @@ -1,9 +1,49 @@ -section .text { - font-family: Tahoma; - font-weight: bold; - color: white; - font-size: 7.5em; +h1 { text-align: center; +} + +th.align-right { + padding-right: 1em; +} + +.gap { + width: 3em; +} + +.contained { + padding-top: 20px; +} + +.middle { + margin: auto; +} + +p.small { + width: 8em; +} + +.black-container { + padding-top: 0.19em; + padding-right: 0.2em; + padding-left: 0.2em; background-color: black; - margin-bottom: 0.2em -} \ No newline at end of file + color: white; + font-size: 1.3em; +} + +table.repeatable { + margin-top: 1em; + margin-bottom: 1em; +} + +table.repeatable > tbody > tr > td { + padding-top: 0.5em; +} + +section.text-area { + margin-top: 1em; + padding: 0.19em; + padding-left: 1em; + padding-right: 1em; + background-color: #e5e5e5; +} diff --git a/print/report/rpt-route/index.html b/print/report/rpt-route/index.html index 727088c82..e3b814c50 100644 --- a/print/report/rpt-route/index.html +++ b/print/report/rpt-route/index.html @@ -2,14 +2,155 @@
+ + +
- -
{{route.agencyName}}
-
{{route.id}}
-
{{route.plateNumber}} {{routeTime(route.time)}}
-
- +

{{$t('Title')}}

+
+
{{$t('Information')}}
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{$t('Route')}}{{route.id}}{{$t('Driver')}}{{route.userNickName}}
{{$t('Date')}}{{date(route.created)}}{{$t('Vehicle')}}{{route.vehicleTradeMark}} {{route.vehicleModel}}
{{$t('Time')}}{{time(route.time)}}{{route.plateNumber}}
{{$t('Volume')}}{{route.m3}}{{$t('Agency')}}{{route.agencyName}}
+
+ + + + + + + + + + + + + + + +
+

Hora inicio

+
+

Hora fin

+
+

Km inicio

+
+

Km fin

+
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + +
{{$t('Order')}}{{$t('Ticket')}}{{$t('Client')}}{{$t('Address')}}{{$t('Packages')}}
{{ticket.priority}}{{ticket.id}}{{ticket.clientFk}} {{ticket.addressName}} + {{ticket.addressFk.toString().substr(0, ticket.addressFk.toString().length - 3)}} + + {{ticket.addressFk.toString().substr(-3, 3)}} + + {{ticket.packages}}
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{$t('Street')}}{{ticket.street}}{{$t('Postcode')}}{{ticket.postalCode}}
{{$t('City')}}{{ticket.city}}{{$t('Agency')}}{{ticket.ticketAgency}}
{{$t('Mobile')}}{{ticket.mobile}}{{$t('Phone')}}{{ticket.phone}}
{{$t('Warehouse')}}{{ticket.warehouseName}}{{$t('salesPerson')}}{{ticket.salesPersonName}}
{{$t('Import')}}{{ticket.import}}
+
+

{{ticket.description}}

+

{{$t('stowaway')}}: {{ticket.shipFk}}

+
+
+
+
+ + + + - \ No newline at end of file + diff --git a/print/report/rpt-route/index.js b/print/report/rpt-route/index.js index 7048acc2a..989a27254 100755 --- a/print/report/rpt-route/index.js +++ b/print/report/rpt-route/index.js @@ -5,32 +5,90 @@ const UserException = require(`${appPath}/lib/exceptions/userException`); module.exports = { name: 'rpt-route', async asyncData(ctx, params) { - if (!params.routeFk) - throw new UserException('No route id specified'); + Object.assign(this, this.methods); - let [[route]] = await this.methods.fetchRoute(params.routeFk); + const [[route]] = await this.fetchRoute(params.routeFk); + const [tickets] = await this.fetchTickets(params.routeFk); if (!route) - throw new UserException('Route not ready'); + throw new UserException('No route data found'); - return {route}; + if (!tickets) + throw new UserException('No ticket data found'); + + return {route, tickets}; }, methods: { fetchRoute(routeFk) { return database.pool.query( - `SELECT + `SELECT r.id, + r.m3, + r.created, r.time, - am.name agencyName, - v.numberPlate plateNumber + u.nickName userNickName, + u.lang AS locale, + v.tradeMark vehicleTradeMark, + v.model vehicleModel, + v.numberPlate plateNumber, + am.name agencyName FROM route r - JOIN agencyMode am ON am.id = r.agencyModeFk - JOIN vehicle v ON v.id = r.vehicleFk + LEFT JOIN ticket t ON t.routeFk = r.id + LEFT JOIN sale s ON s.ticketFk = t.id + LEFT JOIN cache.last_buy lb ON lb.item_id = s.itemFk + LEFT JOIN vehicle v ON v.id = r.vehicleFk + LEFT JOIN worker w ON w.id = r.workerFk + LEFT JOIN account.user u ON u.id = w.userFk + LEFT JOIN agencyMode am ON am.id = r.agencyModeFk WHERE r.id = ?`, [routeFk]); }, - routeTime: routeTime => { - if (routeTime) - return strftime('%H:%M', routeTime); + fetchTickets(routeFk) { + return database.pool.query( + `SELECT + t.nickname addressName, + t.packages, + t.priority, + t.id, + t.clientFk, + t.companyFk, + if(a.phone, a.phone, c.phone) AS phone, + if(a.mobile, a.mobile, c.mobile) AS mobile, + wh.name warehouseName, + a.city, + a.street, + a.postalCode, + LPAD(a.id, 5, '0') AS addressFk, + p.name province, + vn.ticketGetTotal(t.id) AS import, + am.name ticketAgency, + tob.description, + s.shipFk, + u.nickName salesPersonName + FROM route r + LEFT JOIN ticket t ON t.routeFk = r.id + LEFT JOIN address a ON a.id = t.addressFk + LEFT JOIN client c ON c.id = t.clientFk + LEFT JOIN worker w ON w.id = vn2008.Averiguar_ComercialCliente_Id(t.clientFk, CURDATE()) + LEFT JOIN account.user u ON u.id = w.userFk + LEFT JOIN ticketObservation tob ON tob.ticketFk = t.id AND tob.observationTypeFk = 3 + LEFT JOIN province p ON a.provinceFk = p.id + LEFT JOIN warehouse wh ON wh.id = t.warehouseFk + LEFT JOIN agencyMode am ON am.id = t.agencyModeFk + LEFT JOIN stowaway s ON s.id = t.id + WHERE r.id = ? + ORDER BY t.priority, t.id`, [routeFk]); + }, + date(date) { + if (date) + return strftime('%d-%m-%Y', date); + }, + time: time => { + if (time) + return strftime('%H:%M', time); }, }, + components: { + 'report-header': require('../report-header'), + 'report-footer': require('../report-footer'), + }, }; diff --git a/print/report/rpt-route/locale.js b/print/report/rpt-route/locale.js index e69de29bb..ef835b20f 100644 --- a/print/report/rpt-route/locale.js +++ b/print/report/rpt-route/locale.js @@ -0,0 +1,29 @@ +module.exports = { + messages: { + es: { + Title: 'Hoja de ruta', + Information: 'Información', + Route: 'Ruta', + Date: 'Fecha', + Time: 'Hora', + Volume: 'Cubicaje', + Driver: 'Conductor', + Vehicle: 'Vehículo', + Agency: 'Agencia', + Order: 'Orden', + Client: 'Cliente', + Address: 'Consignatario', + Packages: 'Bultos', + Street: 'Dirección', + Postcode: 'Código Postal', + City: 'Ciudad', + Mobile: 'Móvil', + Phone: 'Teléfono', + Warehouse: 'Almacén', + salesPerson: 'Comercial', + Import: 'Importe', + stowaway: 'Encajado dentro del ticket', + route: 'Ruta {0}' + } + }, +}; diff --git a/print/report/rpt-zone/assets/css/index.js b/print/report/rpt-zone/assets/css/index.js new file mode 100644 index 000000000..06417fcee --- /dev/null +++ b/print/report/rpt-zone/assets/css/index.js @@ -0,0 +1,7 @@ +const CssReader = require(`${appPath}/lib/cssReader`); + +module.exports = new CssReader([ + `${appPath}/common/css/layout.css`, + `${appPath}/common/css/report.css`, + `${__dirname}/style.css`]) + .mergeStyles(); diff --git a/print/report/rpt-zone/assets/css/style.css b/print/report/rpt-zone/assets/css/style.css new file mode 100644 index 000000000..82e5c33f1 --- /dev/null +++ b/print/report/rpt-zone/assets/css/style.css @@ -0,0 +1,9 @@ +section .text { + font-family: Tahoma; + font-weight: bold; + color: white; + font-size: 7.5em; + text-align: center; + background-color: black; + margin-bottom: 0.2em +} \ No newline at end of file diff --git a/print/report/rpt-zone/index.html b/print/report/rpt-zone/index.html new file mode 100644 index 000000000..5e64da73c --- /dev/null +++ b/print/report/rpt-zone/index.html @@ -0,0 +1,15 @@ + + + +
+
+ +
{{zone.agencyName}}
+
{{zone.id}}
+
{{zone.plateNumber}} {{zoneTime(zone.time)}}
+
+ +
+
+ + \ No newline at end of file diff --git a/print/report/rpt-zone/index.js b/print/report/rpt-zone/index.js new file mode 100755 index 000000000..c6b0a245c --- /dev/null +++ b/print/report/rpt-zone/index.js @@ -0,0 +1,36 @@ +const strftime = require('strftime'); +const database = require(`${appPath}/lib/database`); +const UserException = require(`${appPath}/lib/exceptions/userException`); + +module.exports = { + name: 'rpt-zone', + async asyncData(ctx, params) { + if (!params.routeFk) + throw new UserException('No route id specified'); + + let [[zone]] = await this.methods.fetchRoute(params.routeFk); + + if (!zone) + throw new UserException('Route not ready'); + + return {zone}; + }, + methods: { + fetchRoute(routeFk) { + return database.pool.query( + `SELECT + r.id, + r.time, + am.name agencyName, + v.numberPlate plateNumber + FROM route r + JOIN agencyMode am ON am.id = r.agencyModeFk + JOIN vehicle v ON v.id = r.vehicleFk + WHERE r.id = ?`, [routeFk]); + }, + zoneTime: zoneTime => { + if (zoneTime) + return strftime('%H:%M', zoneTime); + }, + }, +}; diff --git a/print/report/rpt-zone/locale.js b/print/report/rpt-zone/locale.js new file mode 100644 index 000000000..e69de29bb