diff --git a/CHANGELOG.md b/CHANGELOG.md index ea4725448..aa63ad637 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +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). +## [2308.01] - 2023-03-09 + +### Added +- + +### Changed +- + +### Fixed +- + ## [2306.01] - 2023-02-23 ### Added - (Tickets -> Datos Básicos) Mensaje de confirmación al intentar generar tickets con negativos +- (Artículos) El visible y disponible se calcula a partir de un almacén diferente dependiendo de la sección en la que te encuentres. Se ha añadido un icono que informa sobre a partir de que almacén se esta calculando. ### Changed - (General -> Inicio) Ahora permite recuperar la contraseña tanto con el correo de recuperación como el usuario @@ -16,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - (Monitor de tickets) Cuando ordenas por columna, ya no se queda deshabilitado el botón de 'Actualizar' - (Zone -> Días de entrega) Al hacer click en un día, muestra correctamente las zonas +- (Artículos) El disponible en la vista previa se muestra correctamente ## [2304.01] - 2023-02-09 diff --git a/back/models/company.json b/back/models/company.json index a36b43b69..f16c5762f 100644 --- a/back/models/company.json +++ b/back/models/company.json @@ -20,10 +20,9 @@ "type": "date" } }, - "scope": { "where" :{ "expired": null } } -} \ No newline at end of file +} diff --git a/db/changes/230201/00-validPriorities_ItemConfig.sql b/db/changes/230201/00-validPriorities_ItemConfig.sql index a793997d0..0b32d5de8 100644 --- a/db/changes/230201/00-validPriorities_ItemConfig.sql +++ b/db/changes/230201/00-validPriorities_ItemConfig.sql @@ -3,7 +3,3 @@ ALTER TABLE `vn`.`itemConfig` ADD CONSTRAINT itemConfig_FK FOREIGN KEY (defaultT ALTER TABLE `vn`.`itemConfig` ADD validPriorities varchar(50) DEFAULT '[1,2,3]' NOT NULL; ALTER TABLE `vn`.`itemConfig` ADD defaultPriority INT DEFAULT 2 NOT NULL; ALTER TABLE `vn`.`item` MODIFY COLUMN relevancy tinyint(1) DEFAULT 0 NOT NULL COMMENT 'La web ordena de forma descendiente por este campo para mostrar los artículos'; - -INSERT INTO `salix`.`ACL` -(model, property, accessType, permission, principalType, principalId) -VALUES('ItemConfig', '*', 'READ', 'ALLOW', 'ROLE', 'buyer'); diff --git a/db/changes/230202/00-itemConfig.sql b/db/changes/230202/00-itemConfig.sql index a793997d0..0b32d5de8 100644 --- a/db/changes/230202/00-itemConfig.sql +++ b/db/changes/230202/00-itemConfig.sql @@ -3,7 +3,3 @@ ALTER TABLE `vn`.`itemConfig` ADD CONSTRAINT itemConfig_FK FOREIGN KEY (defaultT ALTER TABLE `vn`.`itemConfig` ADD validPriorities varchar(50) DEFAULT '[1,2,3]' NOT NULL; ALTER TABLE `vn`.`itemConfig` ADD defaultPriority INT DEFAULT 2 NOT NULL; ALTER TABLE `vn`.`item` MODIFY COLUMN relevancy tinyint(1) DEFAULT 0 NOT NULL COMMENT 'La web ordena de forma descendiente por este campo para mostrar los artículos'; - -INSERT INTO `salix`.`ACL` -(model, property, accessType, permission, principalType, principalId) -VALUES('ItemConfig', '*', 'READ', 'ALLOW', 'ROLE', 'buyer'); diff --git a/db/changes/230402/00-invoiceOut_getWeight.sql b/db/changes/230402/00-invoiceOut_getWeight.sql new file mode 100644 index 000000000..4ca284857 --- /dev/null +++ b/db/changes/230402/00-invoiceOut_getWeight.sql @@ -0,0 +1,30 @@ +DROP FUNCTION IF EXISTS `vn`.`invoiceOut_getWeight`; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` FUNCTION `vn`.`invoiceOut_getWeight`(vInvoice VARCHAR(15)) RETURNS decimal(10,2) + READS SQL DATA +BEGIN +/** + * Calcula el peso de una factura emitida + * + * @param vInvoice Id de la factura + * @return vTotalWeight peso de la factura + */ + DECLARE vTotalWeight DECIMAL(10,2); + + SELECT SUM(CAST(IFNULL(i.stems, 1) + * s.quantity + * IF(ic.grams, ic.grams, IFNULL(i.weightByPiece, 0)) / 1000 AS DECIMAL(10,2))) + INTO vTotalWeight + FROM ticket t + JOIN sale s ON s.ticketFk = t.id + JOIN item i ON i.id = s.itemFk + JOIN itemCost ic ON ic.itemFk = i.id + AND ic.warehouseFk = t.warehouseFk + WHERE t.refFk = vInvoice + AND i.intrastatFk; + + RETURN vTotalWeight; +END$$ +DELIMITER ; diff --git a/db/changes/230403/00-clienteCompensado.sql b/db/changes/230403/00-clienteCompensado.sql new file mode 100644 index 000000000..ff1982b93 --- /dev/null +++ b/db/changes/230403/00-clienteCompensado.sql @@ -0,0 +1,3 @@ +INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`) + VALUES + ('Client', 'getClientOrSupplierReference', 'READ', 'ALLOW', 'ROLE', 'employee'); diff --git a/db/changes/230404/00-ticket_canAdvance.sql b/db/changes/230404/00-ticket_canAdvance.sql new file mode 100644 index 000000000..d7386e9d1 --- /dev/null +++ b/db/changes/230404/00-ticket_canAdvance.sql @@ -0,0 +1,127 @@ +DROP PROCEDURE IF EXISTS `vn`.`ticket_canAdvance`; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_canAdvance`(vDateFuture DATE, vDateToAdvance DATE, vWarehouseFk INT) +BEGIN +/** + * Devuelve los tickets y la cantidad de lineas de venta que se pueden adelantar. + * + * @param vDateFuture Fecha de los tickets que se quieren adelantar. + * @param vDateToAdvance Fecha a cuando se quiere adelantar. + * @param vWarehouseFk Almacén + */ + + DECLARE vDateInventory DATE; + + SELECT inventoried INTO vDateInventory FROM config; + + DROP TEMPORARY TABLE IF EXISTS tmp.stock; + CREATE TEMPORARY TABLE tmp.stock + (itemFk INT PRIMARY KEY, + amount INT) + ENGINE = MEMORY; + + INSERT INTO tmp.stock(itemFk, amount) + SELECT itemFk, SUM(quantity) amount FROM + ( + SELECT itemFk, quantity + FROM itemTicketOut + WHERE shipped >= vDateInventory + AND shipped < vDateFuture + AND warehouseFk = vWarehouseFk + UNION ALL + SELECT itemFk, quantity + FROM itemEntryIn + WHERE landed >= vDateInventory + AND landed < vDateFuture + AND isVirtualStock = FALSE + AND warehouseInFk = vWarehouseFk + UNION ALL + SELECT itemFk, quantity + FROM itemEntryOut + WHERE shipped >= vDateInventory + AND shipped < vDateFuture + AND warehouseOutFk = vWarehouseFk + ) t + GROUP BY itemFk HAVING amount != 0; + + DROP TEMPORARY TABLE IF EXISTS tmp.filter; + CREATE TEMPORARY TABLE tmp.filter + (INDEX (id)) + + SELECT + origin.ticketFk futureId, + dest.ticketFk id, + dest.state, + origin.futureState, + origin.futureIpt, + dest.ipt, + origin.workerFk, + origin.futureLiters, + origin.futureLines, + dest.shipped, + origin.shipped futureShipped, + dest.totalWithVat, + origin.totalWithVat futureTotalWithVat, + dest.agency, + origin.futureAgency, + dest.lines, + dest.liters, + origin.futureLines - origin.hasStock AS notMovableLines, + (origin.futureLines = origin.hasStock) AS isFullMovable + FROM ( + SELECT + s.ticketFk, + t.workerFk, + t.shipped, + t.totalWithVat, + st.name futureState, + t.addressFk, + am.name futureAgency, + count(s.id) futureLines, + GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) futureIpt, + CAST(SUM(litros) AS DECIMAL(10,0)) futureLiters, + SUM((s.quantity <= IFNULL(st.amount,0))) hasStock + FROM ticket t + JOIN sale s ON s.ticketFk = t.id + JOIN saleVolume sv ON sv.saleFk = s.id + JOIN item i ON i.id = s.itemFk + JOIN ticketState ts ON ts.ticketFk = t.id + JOIN state st ON st.id = ts.stateFk + JOIN agencyMode am ON t.agencyModeFk = am.id + LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk + LEFT JOIN tmp.stock st ON st.itemFk = i.id + WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture) + AND t.warehouseFk = vWarehouseFk + GROUP BY t.id + ) origin + JOIN ( + SELECT + t.id ticketFk, + t.addressFk, + st.name state, + GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) ipt, + t.shipped, + t.totalWithVat, + am.name agency, + CAST(SUM(litros) AS DECIMAL(10,0)) liters, + CAST(COUNT(*) AS DECIMAL(10,0)) `lines` + FROM ticket t + JOIN sale s ON s.ticketFk = t.id + JOIN saleVolume sv ON sv.saleFk = s.id + JOIN item i ON i.id = s.itemFk + JOIN ticketState ts ON ts.ticketFk = t.id + JOIN state st ON st.id = ts.stateFk + JOIN agencyMode am ON t.agencyModeFk = am.id + LEFT JOIN itemPackingType ipt ON ipt.code = i.itemPackingTypeFk + WHERE t.shipped BETWEEN vDateToAdvance AND util.dayend(vDateToAdvance) + AND t.warehouseFk = vWarehouseFk + AND st.order <= 5 + GROUP BY t.id + ) dest ON dest.addressFk = origin.addressFk + WHERE origin.hasStock != 0; + + DROP TEMPORARY TABLE tmp.stock; +END$$ +DELIMITER ; diff --git a/db/changes/230401/00-acl_notifications.sql b/db/changes/230601/00-acl_notifications.sql similarity index 100% rename from db/changes/230401/00-acl_notifications.sql rename to db/changes/230601/00-acl_notifications.sql diff --git a/db/changes/230601/00-itemConfig_warehouseFk.sql b/db/changes/230601/00-itemConfig_warehouseFk.sql new file mode 100644 index 000000000..c860986d6 --- /dev/null +++ b/db/changes/230601/00-itemConfig_warehouseFk.sql @@ -0,0 +1,4 @@ +ALTER TABLE `vn`.`itemConfig` ADD warehouseFk smallint(6) unsigned NULL; +UPDATE `vn`.`itemConfig` + SET warehouseFk=60 +WHERE id=0; diff --git a/db/changes/230401/00-uniqueKeyNotificationSubscription.sql b/db/changes/230601/00-uniqueKeyNotificationSubscription.sql similarity index 100% rename from db/changes/230401/00-uniqueKeyNotificationSubscription.sql rename to db/changes/230601/00-uniqueKeyNotificationSubscription.sql diff --git a/db/changes/230401/01-alter_notSubs.sql b/db/changes/230601/01-alter_notSubs.sql similarity index 100% rename from db/changes/230401/01-alter_notSubs.sql rename to db/changes/230601/01-alter_notSubs.sql diff --git a/db/changes/230601/.gitkeep b/db/changes/230801/.gitkeep similarity index 100% rename from db/changes/230601/.gitkeep rename to db/changes/230801/.gitkeep diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index 5c7bbf192..6f766f8ad 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -717,7 +717,8 @@ INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeF (28, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()), (29, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()), (30, 1, 8, 1, 1, util.VN_CURDATE(), DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()), - (31, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()); + (31, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()), + (32, 1, 8, 1, 1, DATE_ADD(util.VN_CURDATE(), INTERVAL + 1 DAY), DATE_ADD(util.VN_CURDATE(), INTERVAL + 2 DAY), 1103, 'Phone Box', 123, NULL, 0, 1, 5, 1, util.VN_CURDATE()); INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`) VALUES @@ -1019,7 +1020,9 @@ INSERT INTO `vn`.`sale`(`id`, `itemFk`, `ticketFk`, `concept`, `quantity`, `pric (34, 4, 28, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()), (35, 4, 29, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()), (36, 4, 30, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()), - (37, 4, 31, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()); + (37, 4, 31, 'Melee weapon heavy shield 1x0.5m', 20, 1.72, 0, 0, 0, util.VN_CURDATE()), + (38, 2, 32, 'Melee weapon combat fist 15cm', 30, 7.07, 0, 0, 0, DATE_ADD(util.VN_CURDATE(), INTERVAL +1 MONTH)), + (39, 1, 32, 'Ranged weapon longbow 2m', 2, 103.49, 0, 0, 0, util.VN_CURDATE()); INSERT INTO `vn`.`saleChecked`(`saleFk`, `isChecked`) VALUES @@ -2744,9 +2747,9 @@ INSERT INTO `vn`.`collection` (`id`, `created`, `workerFk`, `stateFk`, `itemPack VALUES (3, util.VN_NOW(), 1107, 5, NULL, 0, 0, 1, NULL, NULL); -INSERT INTO `vn`.`itemConfig` (`id`, `isItemTagTriggerDisabled`, `monthToDeactivate`, `wasteRecipients`, `validPriorities`, `defaultPriority`, `defaultTag`) +INSERT INTO `vn`.`itemConfig` (`id`, `isItemTagTriggerDisabled`, `monthToDeactivate`, `wasteRecipients`, `validPriorities`, `defaultPriority`, `defaultTag`, `warehouseFk`) VALUES - (0, 0, 24, '', '[1,2,3]', 2, 56); + (0, 0, 24, '', '[1,2,3]', 2, 56, 60); INSERT INTO `vn`.`ticketCollection` (`ticketFk`, `collectionFk`, `created`, `level`, `wagon`, `smartTagFk`, `usedShelves`, `itemCount`, `liters`) VALUES diff --git a/db/dump/structure.sql b/db/dump/structure.sql index 4626279e4..3186fa01f 100644 --- a/db/dump/structure.sql +++ b/db/dump/structure.sql @@ -26286,6 +26286,7 @@ CREATE TABLE `entry` ( `typeFk` varchar(100) COLLATE utf8mb3_unicode_ci DEFAULT NULL COMMENT 'Tipo de entrada', `reference` varchar(50) COLLATE utf8mb3_unicode_ci DEFAULT NULL COMMENT 'Referencia para eti', `ref` varchar(50) GENERATED ALWAYS AS (`invoiceNumber`) VIRTUAL COMMENT 'Columna virtual provisional para Salix', + `observationEditorFk` INT(10) unsigned NULL COMMENT 'Último usuario que ha modificado el campo evaNotes', PRIMARY KEY (`id`), KEY `Id_Proveedor` (`supplierFk`), KEY `Fecha` (`dated`), @@ -26300,7 +26301,8 @@ CREATE TABLE `entry` ( CONSTRAINT `entry_FK_1` FOREIGN KEY (`typeFk`) REFERENCES `entryType` (`code`) ON UPDATE CASCADE, CONSTRAINT `entry_ibfk_1` FOREIGN KEY (`supplierFk`) REFERENCES `supplier` (`id`) ON UPDATE CASCADE, CONSTRAINT `entry_ibfk_6` FOREIGN KEY (`travelFk`) REFERENCES `travel` (`id`) ON UPDATE CASCADE, - CONSTRAINT `entry_ibfk_7` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON UPDATE CASCADE + CONSTRAINT `entry_ibfk_7` FOREIGN KEY (`companyFk`) REFERENCES `company` (`id`) ON UPDATE CASCADE, + CONSTRAINT `entry_observationEditorFk` FOREIGN KEY (`observationEditorFk`) REFERENCES `account`.`user`(`id`) ON UPDATE CASCADE ) ENGINE=InnoDBDEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci COMMENT='InnoDB free: 88064 kB; (`Id_Proveedor`) REFER `vn2008/Provee'; /*!40101 SET character_set_client = @saved_cs_client */; /*!50003 SET @saved_cs_client = @@character_set_client */ ; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 8f9fcda57..efaa13ee3 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -778,18 +778,16 @@ export default { ipt: 'vn-autocomplete[label="Destination IPT"]', tableIpt: 'vn-autocomplete[name="ipt"]', tableFutureIpt: 'vn-autocomplete[name="futureIpt"]', - futureState: 'vn-check[label="Pending Origin"]', - state: 'vn-check[label="Pending Destination"]', + isFullMovable: 'vn-check[ng-model="filter.isFullMovable"]', warehouseFk: 'vn-autocomplete[label="Warehouse"]', tableButtonSearch: 'vn-button[vn-tooltip="Search"]', moveButton: 'vn-button[vn-tooltip="Advance tickets"]', acceptButton: '.vn-confirm.shown button[response="accept"]', - multiCheck: 'vn-multi-check', + firstCheck: 'tbody > tr:nth-child(1) > td > vn-check', tableId: 'vn-textfield[name="id"]', tableFutureId: 'vn-textfield[name="futureId"]', tableLiters: 'vn-textfield[name="liters"]', tableLines: 'vn-textfield[name="lines"]', - tableStock: 'vn-textfield[name="hasStock"]', submit: 'vn-submit[label="Search"]', table: 'tbody > tr:not(.empty-rows)' }, diff --git a/e2e/paths/05-ticket/16_summary.spec.js b/e2e/paths/05-ticket/16_summary.spec.js index 960998c7d..a6017e454 100644 --- a/e2e/paths/05-ticket/16_summary.spec.js +++ b/e2e/paths/05-ticket/16_summary.spec.js @@ -55,7 +55,7 @@ describe('Ticket Summary path', () => { let result = await page .waitToGetProperty(selectors.ticketSummary.firstSaleItemId, 'innerText'); - expect(result).toContain('000002'); + expect(result).toContain('2'); }); it(`should click on the first sale ID to make the item descriptor visible`, async() => { diff --git a/e2e/paths/05-ticket/22_advance.spec.js b/e2e/paths/05-ticket/22_advance.spec.js index 3a6234fe9..c92cd7a20 100644 --- a/e2e/paths/05-ticket/22_advance.spec.js +++ b/e2e/paths/05-ticket/22_advance.spec.js @@ -4,12 +4,17 @@ import getBrowser from '../../helpers/puppeteer'; describe('Ticket Advance path', () => { let browser; let page; + const httpRequests = []; beforeAll(async() => { browser = await getBrowser(); page = browser.page; await page.loginAndModule('employee', 'ticket'); await page.accessToSection('ticket.advance'); + page.on('request', req => { + if (req.url().includes(`Tickets/getTicketsAdvance`)) + httpRequests.push(req.url()); + }); }); afterAll(async() => { @@ -43,91 +48,74 @@ describe('Ticket Advance path', () => { it('should search with the required data', async() => { await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); + + expect(httpRequests.length).toBeGreaterThan(0); }); it('should search with the origin IPT', async() => { - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal'); - await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); - - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.clearInput(selectors.ticketAdvance.ipt); - await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); - }); - - it('should search with the destination IPT', async() => { await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.autocompleteSearch(selectors.ticketAdvance.futureIpt, 'Horizontal'); await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); + + const request = httpRequests.find(req => req.includes(('futureIpt=H'))); + + expect(request).toBeDefined(); + + httpRequests.splice(httpRequests.indexOf(request), 1); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.clearInput(selectors.ticketAdvance.futureIpt); await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); }); - it('should search with the origin pending state', async() => { + it('should search with the destination IPT', async() => { await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketAdvance.futureState); + await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal'); await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); + + const request = httpRequests.find(req => req.includes(('ipt=H'))); + + expect(request).toBeDefined(); + + httpRequests.splice(httpRequests.indexOf(request), 1); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketAdvance.futureState); + await page.clearInput(selectors.ticketAdvance.ipt); await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 0); - - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketAdvance.futureState); - await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); - }); - - it('should search with the destination grouped state', async() => { - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketAdvance.state); - await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 0); - - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketAdvance.state); - await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); - - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.waitToClick(selectors.ticketAdvance.state); - await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); }); it('should search in smart-table with an IPT Origin', async() => { await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'Vertical'); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); + + const request = httpRequests.find(req => req.includes(('futureIpt'))); + + expect(request).toBeDefined(); + + httpRequests.splice(httpRequests.indexOf(request), 1); await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); }); it('should search in smart-table with an IPT Destination', async() => { await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'Vertical'); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); + + const request = httpRequests.find(req => req.includes(('ipt'))); + + expect(request).toBeDefined(); + + httpRequests.splice(httpRequests.indexOf(request), 1); await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); }); - it('should check the one ticket and move to the present', async() => { - await page.waitToClick(selectors.ticketAdvance.multiCheck); + it('should check the first ticket and move to the present', async() => { + await page.waitToClick(selectors.ticketAdvance.firstCheck); await page.waitToClick(selectors.ticketAdvance.moveButton); await page.waitToClick(selectors.ticketAdvance.acceptButton); const message = await page.waitForSnackbar(); diff --git a/e2e/paths/06-claim/05_summary.spec.js b/e2e/paths/06-claim/05_summary.spec.js index 00b021f88..758dc2ee3 100644 --- a/e2e/paths/06-claim/05_summary.spec.js +++ b/e2e/paths/06-claim/05_summary.spec.js @@ -45,7 +45,7 @@ describe('Claim summary path', () => { it('should display the claimed line(s)', async() => { const result = await page.waitToGetProperty(selectors.claimSummary.firstSaleItemId, 'innerText'); - expect(result).toContain('000002'); + expect(result).toContain('2'); }); it(`should click on the first sale ID making the item descriptor visible`, async() => { diff --git a/front/core/filters/index.js b/front/core/filters/index.js index 2c3f77ebe..6097a18a1 100644 --- a/front/core/filters/index.js +++ b/front/core/filters/index.js @@ -3,5 +3,4 @@ import './ucwords'; import './dash-if-empty'; import './percentage'; import './currency'; -import './zero-fill'; import './id'; diff --git a/front/core/filters/specs/zero-fill.spec.js b/front/core/filters/specs/zero-fill.spec.js deleted file mode 100644 index 97f04c655..000000000 --- a/front/core/filters/specs/zero-fill.spec.js +++ /dev/null @@ -1,25 +0,0 @@ -describe('ZeroFill filter', () => { - let zeroFillFilter; - - beforeEach(ngModule('vnCore')); - - beforeEach(inject(_zeroFillFilter_ => { - zeroFillFilter = _zeroFillFilter_; - })); - - it('should return null for a input null', () => { - expect(zeroFillFilter(null, null)).toBeNull(); - }); - - it('should return a positive number pads a number with five zeros', () => { - expect(zeroFillFilter(1, 5)).toBe('00001'); - }); - - it('should return negative number pads a number with five zeros', () => { - expect(zeroFillFilter(-1, 5)).toBe('-00001'); - }); - - it('should return zero number with zero zeros', () => { - expect(zeroFillFilter(0, 1)).toBe('0'); - }); -}); diff --git a/front/core/filters/zero-fill.js b/front/core/filters/zero-fill.js deleted file mode 100644 index c4d76b96f..000000000 --- a/front/core/filters/zero-fill.js +++ /dev/null @@ -1,17 +0,0 @@ -import ngModule from '../module'; - -/** - * Pads a number with zeros. - * - * @param {Number} input The number to pad - * @param {Number} padLength The resulting number of digits - * @return {String} The zero-filled number - */ -export default function zeroFill() { - return function(input, padLength) { - if (input == null) return input; - let sign = Math.sign(input) === -1 ? '-' : ''; - return sign + new Array(padLength).concat([Math.abs(input)]).join('0').slice(-padLength); - }; -} -ngModule.filter('zeroFill', zeroFill); diff --git a/loopback/common/methods/application/post.js b/loopback/common/methods/application/post.js new file mode 100644 index 000000000..9ea9a7f71 --- /dev/null +++ b/loopback/common/methods/application/post.js @@ -0,0 +1,17 @@ +module.exports = Self => { + Self.remoteMethodCtx('post', { + description: 'Returns the sent parameters', + returns: { + type: 'object', + root: true + }, + http: { + path: `/post`, + verb: 'POST' + } + }); + + Self.post = async ctx => { + return ctx.req.body; + }; +}; diff --git a/loopback/common/models/application.js b/loopback/common/models/application.js index ff7599fac..5e767fdc1 100644 --- a/loopback/common/models/application.js +++ b/loopback/common/models/application.js @@ -1,4 +1,5 @@ module.exports = function(Self) { require('../methods/application/status')(Self); + require('../methods/application/post')(Self); }; diff --git a/loopback/common/models/application.json b/loopback/common/models/application.json index 0bb489720..bc72df315 100644 --- a/loopback/common/models/application.json +++ b/loopback/common/models/application.json @@ -7,6 +7,12 @@ "principalType": "ROLE", "principalId": "$everyone", "permission": "ALLOW" - } + }, + { + "property": "post", + "principalType": "ROLE", + "principalId": "$everyone", + "permission": "ALLOW" + } ] } diff --git a/modules/claim/front/action/index.html b/modules/claim/front/action/index.html index 35e788290..81b14d3a7 100644 --- a/modules/claim/front/action/index.html +++ b/modules/claim/front/action/index.html @@ -101,7 +101,7 @@ - {{::saleClaimed.itemFk | zeroFill:6}} + {{::saleClaimed.itemFk}} diff --git a/modules/claim/front/summary/index.html b/modules/claim/front/summary/index.html index 6adbfd684..3115cb451 100644 --- a/modules/claim/front/summary/index.html +++ b/modules/claim/front/summary/index.html @@ -115,7 +115,7 @@ - {{::saleClaimed.sale.itemFk | zeroFill:6}} + {{::saleClaimed.sale.itemFk}} {{::saleClaimed.sale.ticket.landed | date: 'dd/MM/yyyy'}} @@ -241,7 +241,7 @@ - {{::action.sale.itemFk | zeroFill:6}} + {{::action.sale.itemFk}} diff --git a/modules/client/back/methods/client/createReceipt.js b/modules/client/back/methods/client/createReceipt.js index 74fe2211e..cb032270a 100644 --- a/modules/client/back/methods/client/createReceipt.js +++ b/modules/client/back/methods/client/createReceipt.js @@ -67,7 +67,7 @@ module.exports = function(Self) { try { delete args.ctx; // Remove unwanted properties - const newReceipt = await models.Receipt.create(args, myOptions); + const originalClient = await models.Client.findById(args.clientFk, null, myOptions); const bank = await models.Bank.findById(args.bankFk, null, myOptions); const accountingType = await models.AccountingType.findById(bank.accountingTypeFk, null, myOptions); @@ -76,23 +76,8 @@ module.exports = function(Self) { if (!args.compensationAccount) throw new UserError('Compensation account is empty'); - const supplierCompensation = await models.Supplier.findOne({ - where: { - account: args.compensationAccount - } - }, myOptions); - - let clientCompensation = {}; - - if (!supplierCompensation) { - clientCompensation = await models.Client.findOne({ - where: { - accountingAccount: args.compensationAccount - } - }, myOptions); - } - if (!supplierCompensation && !clientCompensation) - throw new UserError('Invalid account'); + // Check compensation account exists + await models.Client.getClientOrSupplierReference(args.compensationAccount, myOptions); await Self.rawSql( `CALL vn.ledger_doCompensation(?, ?, ?, ?, ?, ?, ?)`, @@ -151,7 +136,7 @@ module.exports = function(Self) { myOptions ); } - + const newReceipt = await models.Receipt.create(args, myOptions); if (tx) await tx.commit(); return newReceipt; diff --git a/modules/client/back/methods/client/getClientOrSupplierReference.js b/modules/client/back/methods/client/getClientOrSupplierReference.js new file mode 100644 index 000000000..4c7201ee3 --- /dev/null +++ b/modules/client/back/methods/client/getClientOrSupplierReference.js @@ -0,0 +1,57 @@ +const UserError = require('vn-loopback/util/user-error'); + +module.exports = Self => { + Self.remoteMethod('getClientOrSupplierReference', { + description: 'Returns the reference of a compensation providing a bank account', + accessType: 'READ', + accepts: { + arg: 'bankAccount', + type: 'number', + required: true, + description: 'The bank account of a client or a supplier' + }, + returns: { + type: 'string', + root: true + }, + http: { + path: `/getClientOrSupplierReference`, + verb: 'GET' + } + }); + + Self.getClientOrSupplierReference = async(bankAccount, options) => { + const models = Self.app.models; + const myOptions = {}; + let reference = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + const supplierCompensation = await models.Supplier.findOne({ + where: { + account: bankAccount + } + }, myOptions); + + reference.supplierId = supplierCompensation?.id; + reference.supplierName = supplierCompensation?.name; + + let clientCompensation = {}; + + if (!supplierCompensation) { + clientCompensation = await models.Client.findOne({ + where: { + accountingAccount: bankAccount + } + }, myOptions); + reference.clientId = clientCompensation?.id; + reference.clientName = clientCompensation?.name; + } + + if (!supplierCompensation && !clientCompensation) + throw new UserError('Invalid account'); + + return reference; + }; +}; diff --git a/modules/client/back/models/client-methods.js b/modules/client/back/models/client-methods.js index 4b20a822c..9241d80cf 100644 --- a/modules/client/back/models/client-methods.js +++ b/modules/client/back/models/client-methods.js @@ -47,4 +47,5 @@ module.exports = Self => { require('../methods/client/incotermsAuthorizationEmail')(Self); require('../methods/client/consumptionSendQueued')(Self); require('../methods/client/filter')(Self); + require('../methods/client/getClientOrSupplierReference')(Self); }; diff --git a/modules/client/front/balance/create/index.html b/modules/client/front/balance/create/index.html index 56e505463..b76c09356 100644 --- a/modules/client/front/balance/create/index.html +++ b/modules/client/front/balance/create/index.html @@ -11,7 +11,7 @@ @@ -48,6 +48,14 @@ max="$ctrl.maxAmount"> + +
Compensation
+ + +
- -
Compensation
- - -
- @@ -89,4 +89,4 @@ - \ No newline at end of file + diff --git a/modules/client/front/balance/create/index.js b/modules/client/front/balance/create/index.js index 4d2b4c792..ef22c968a 100644 --- a/modules/client/front/balance/create/index.js +++ b/modules/client/front/balance/create/index.js @@ -61,12 +61,15 @@ class Controller extends Dialog { this.receipt.description = []; this.viewReceipt = accountingType.code == 'cash'; - if (accountingType.receiptDescription != null && accountingType.receiptDescription != '') - this.receipt.description.push(accountingType.receiptDescription); - if (this.originalDescription) - this.receipt.description.push(this.originalDescription); - this.receipt.description.join(', '); - + if (accountingType.code == 'compensation') + this.receipt.description = ''; + else { + if (accountingType.receiptDescription != null && accountingType.receiptDescription != '') + this.receipt.description.push(accountingType.receiptDescription); + if (this.originalDescription) + this.receipt.description.push(this.originalDescription); + this.receipt.description.join(', '); + } this.maxAmount = accountingType && accountingType.maxAmount; this.receipt.payed = Date.vnNew(); @@ -112,7 +115,25 @@ class Controller extends Dialog { } accountShortToStandard(value) { - this.receipt.compensationAccount = value.replace('.', '0'.repeat(11 - value.length)); + if (value) { + this.receipt.compensationAccount = value.replace('.', '0'.repeat(11 - value.length)); + const params = {bankAccount: this.receipt.compensationAccount}; + this.$http.get(`Clients/getClientOrSupplierReference`, {params}) + .then(res => { + if (res.data.clientId) { + this.receipt.description = this.$t('Client Compensation Reference', { + clientId: res.data.clientId, + clientName: res.data.clientName + }); + } else { + this.receipt.description = this.$t('Supplier Compensation Reference', { + supplierId: res.data.supplierId, + supplierName: res.data.supplierName + }); + } + }); + } else + this.receipt.description = ''; } getAmountPaid() { diff --git a/modules/client/front/balance/create/locale/es.yml b/modules/client/front/balance/create/locale/es.yml index 056590966..8c407708a 100644 --- a/modules/client/front/balance/create/locale/es.yml +++ b/modules/client/front/balance/create/locale/es.yml @@ -1,2 +1,4 @@ View receipt: Ver recibo -Amount exceeded: Según ley contra el fraude no se puede recibir cobros por importe igual o superior a {{maxAmount}} \ No newline at end of file +Amount exceeded: Según ley contra el fraude no se puede recibir cobros por importe igual o superior a {{maxAmount}} +Client Compensation Reference: "({{clientId}}) Ntro Cliente: {{clientName}}" +Supplier Compensation Reference: "({{supplierId}}) Ntro Proveedor: {{supplierName}}" diff --git a/modules/entry/back/models/entry.js b/modules/entry/back/models/entry.js index 4854bc3d3..1980f964c 100644 --- a/modules/entry/back/models/entry.js +++ b/modules/entry/back/models/entry.js @@ -1,3 +1,4 @@ +const LoopBackContext = require('loopback-context'); module.exports = Self => { require('../methods/entry/filter')(Self); require('../methods/entry/getEntry')(Self); @@ -7,4 +8,41 @@ module.exports = Self => { require('../methods/entry/importBuysPreview')(Self); require('../methods/entry/lastItemBuys')(Self); require('../methods/entry/entryOrderPdf')(Self); + + Self.observe('before save', async function(ctx, options) { + if (ctx.isNewInstance) return; + + const changes = ctx.data || ctx.instance; + const orgData = ctx.currentInstance; + + const observation = changes.observation || orgData.observation; + const hasChanges = orgData && changes; + const observationChanged = hasChanges + && orgData.observation != observation; + + if (observationChanged) { + let tx; + const myOptions = {}; + + if (typeof options == 'object') + Object.assign(myOptions, options); + + if (!myOptions.transaction) { + tx = await Self.beginTransaction({}); + myOptions.transaction = tx; + } + + try { + const loopbackContext = LoopBackContext.getCurrentContext(); + const userId = loopbackContext.active.accessToken.userId; + const id = changes.id || orgData.id; + const entry = await Self.app.models.Entry.findById(id, null, myOptions); + await entry.updateAttribute('observationEditorFk', userId, myOptions); + if (tx) await tx.commit(); + } catch (e) { + if (tx) await tx.rollback(); + throw e; + } + } + }); }; diff --git a/modules/entry/back/models/entry.json b/modules/entry/back/models/entry.json index d9b7c52df..6c5e1b7d3 100644 --- a/modules/entry/back/models/entry.json +++ b/modules/entry/back/models/entry.json @@ -77,6 +77,9 @@ "companyFk": { "type": "number", "required": true + }, + "observationEditorFk": { + "type": "number" } }, "relations": { @@ -99,6 +102,11 @@ "type": "belongsTo", "model": "Currency", "foreignKey": "currencyFk" + }, + "observationEditor": { + "type": "belongsTo", + "model": "Account", + "foreignKey": "observationEditorFk" } } } diff --git a/modules/entry/front/buy/index/index.html b/modules/entry/front/buy/index/index.html index ae67e208b..de784198c 100644 --- a/modules/entry/front/buy/index/index.html +++ b/modules/entry/front/buy/index/index.html @@ -60,7 +60,7 @@ ng-if="buy.id" ng-click="itemDescriptor.show($event, buy.item.id)" class="link"> - {{::buy.item.id | zeroFill:6}} + {{::buy.item.id}} - {{::line.item.id | zeroFill:6}} + {{::line.item.id}} diff --git a/modules/invoiceIn/front/intrastat/index.html b/modules/invoiceIn/front/intrastat/index.html index cb447132d..fc0139303 100644 --- a/modules/invoiceIn/front/intrastat/index.html +++ b/modules/invoiceIn/front/intrastat/index.html @@ -47,7 +47,7 @@ show-field="description" rule vn-focus> - {{id | zeroFill:8}}: {{description}} + {{id}}: {{description}} - {{::intrastat.intrastatFk | zeroFill:8}}: {{::intrastat.intrastat.description}} + {{::intrastat.intrastatFk}}: {{::intrastat.intrastat.description}} {{::intrastat.amount | currency: 'EUR':2}} {{::intrastat.net}} {{::intrastat.stems}} diff --git a/modules/item/back/methods/item/getSummary.js b/modules/item/back/methods/item/getSummary.js index 738976e60..6cd9d9511 100644 --- a/modules/item/back/methods/item/getSummary.js +++ b/modules/item/back/methods/item/getSummary.js @@ -98,9 +98,8 @@ module.exports = Self => { summary.tags = res[1]; [summary.botanical] = res[2]; - const userConfig = await models.UserConfig.getUserConfig(ctx, myOptions); - - res = await models.Item.getVisibleAvailable(summary.item.id, userConfig.warehouseFk, null, myOptions); + const itemConfig = await models.ItemConfig.findOne(null, myOptions); + res = await models.Item.getVisibleAvailable(summary.item.id, itemConfig.warehouseFk, undefined, myOptions); summary.available = res.available; summary.visible = res.visible; diff --git a/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js b/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js index 13b2417d7..61bf6b3e7 100644 --- a/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js +++ b/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js @@ -12,7 +12,7 @@ describe('item getVisibleAvailable()', () => { const result = await models.Item.getVisibleAvailable(itemFk, warehouseFk, dated, options); - expect(result.available).toEqual(187); + expect(result.available).toEqual(185); expect(result.visible).toEqual(92); await tx.rollback(); diff --git a/modules/item/back/models/item-config.json b/modules/item/back/models/item-config.json index 36d25e0bb..c7a0b2644 100644 --- a/modules/item/back/models/item-config.json +++ b/modules/item/back/models/item-config.json @@ -25,6 +25,9 @@ }, "defaultTag": { "type": "int" + }, + "warehouseFk": { + "type": "int" } }, "relations": { diff --git a/modules/item/front/card/index.html b/modules/item/front/card/index.html index e92e1696d..330d274c0 100644 --- a/modules/item/front/card/index.html +++ b/modules/item/front/card/index.html @@ -1,6 +1,6 @@ - diff --git a/modules/item/front/descriptor/index.html b/modules/item/front/descriptor/index.html index 321545b38..8e85e043f 100644 --- a/modules/item/front/descriptor/index.html +++ b/modules/item/front/descriptor/index.html @@ -19,7 +19,7 @@
Available

{{$ctrl.available | dashIfEmpty}}

+ +

+ + +

+
- {{$ctrl.item.itemType.worker.user.name}} @@ -50,22 +60,22 @@
@@ -112,7 +122,7 @@ question="Do you want to clone this item?" message="All it's properties will be copied"> - @@ -120,7 +130,7 @@ - - \ No newline at end of file + diff --git a/modules/item/front/descriptor/index.js b/modules/item/front/descriptor/index.js index b88f24456..972c89ae0 100644 --- a/modules/item/front/descriptor/index.js +++ b/modules/item/front/descriptor/index.js @@ -30,7 +30,10 @@ class Controller extends Descriptor { set warehouseFk(value) { this._warehouseFk = value; - if (value) this.updateStock(); + if (value) { + this.updateStock(); + this.getWarehouseName(value); + } } loadData() { @@ -89,6 +92,22 @@ class Controller extends Descriptor { this.$.photo.setAttribute('src', newSrc); this.$.photo.setAttribute('zoom-image', newZoomSrc); } + + getWarehouseName(warehouseFk) { + this.showIcon = false; + + const filter = { + where: {id: warehouseFk} + }; + this.$http.get('Warehouses/findOne', {filter}) + .then(res => { + this.warehouseText = this.$t('WarehouseFk', { + warehouseName: res.data.name + }); + + this.showIcon = true; + }); + } } Controller.$inject = ['$element', '$scope', '$rootScope']; @@ -100,6 +119,6 @@ ngModule.vnComponent('vnItemDescriptor', { item: '<', dated: '<', cardReload: '&', - warehouseFk: ' { controller = $componentController('vnItemDiary', {$element, $scope}); controller.$.model = crudModel; controller.$params = {id: 1}; + controller.card = {}; })); describe('set item()', () => { diff --git a/modules/item/front/last-entries/index.html b/modules/item/front/last-entries/index.html index 1c2db10a5..f6cdf8343 100644 --- a/modules/item/front/last-entries/index.html +++ b/modules/item/front/last-entries/index.html @@ -11,6 +11,8 @@ @@ -35,7 +37,7 @@ Warehouse Landed Entry - PVP + PVP Label Packing Grouping @@ -64,7 +66,7 @@ {{::entry.entryFk | dashIfEmpty}} - + {{::entry.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::entry.price3 | currency: 'EUR':2 | dashIfEmpty}} {{entry.stickers | dashIfEmpty}} diff --git a/modules/item/front/summary/index.html b/modules/item/front/summary/index.html index e6746eedf..c604f5c8f 100644 --- a/modules/item/front/summary/index.html +++ b/modules/item/front/summary/index.html @@ -11,7 +11,7 @@ @@ -22,44 +22,54 @@

Available

{{$ctrl.summary.available}}

+ +

+ + +

+

- Basic data

Basic data

- - - - - - - {{$ctrl.summary.item.itemType.worker.user.name}} @@ -102,45 +112,45 @@

- Other data

Other data

- - - - - -

- Tags

-

Tags @@ -153,14 +163,14 @@

- Description

Description

@@ -170,13 +180,13 @@

- Tax

-

Tax @@ -188,33 +198,33 @@

- Botanical

-

Botanical

- -

- Barcode

-

Barcode @@ -225,6 +235,6 @@ - - \ No newline at end of file + diff --git a/modules/item/front/summary/index.js b/modules/item/front/summary/index.js index 52753ff65..e17a6a8c4 100644 --- a/modules/item/front/summary/index.js +++ b/modules/item/front/summary/index.js @@ -7,6 +7,24 @@ class Controller extends Summary { this.$http.get(`Items/${this.item.id}/getSummary`).then(response => { this.summary = response.data; }); + + this.$http.get('ItemConfigs/findOne') + .then(res => { + if (this.card) this.card.warehouseFk = res.data.warehouseFk; + this.getWarehouseName(res.data.warehouseFk); + }); + } + + getWarehouseName(warehouseFk) { + const filter = { + where: {id: warehouseFk} + }; + this.$http.get('Warehouses/findOne', {filter}) + .then(res => { + this.warehouseText = this.$t('WarehouseFk', { + warehouseName: res.data.name + }); + }); } $onChanges() { @@ -37,4 +55,7 @@ ngModule.vnComponent('vnItemSummary', { bindings: { item: '<', }, + require: { + card: '?^vnItemCard' + } }); diff --git a/modules/item/front/summary/index.spec.js b/modules/item/front/summary/index.spec.js index 0b349194c..d7821bea0 100644 --- a/modules/item/front/summary/index.spec.js +++ b/modules/item/front/summary/index.spec.js @@ -14,12 +14,15 @@ describe('Item', () => { const $element = angular.element(''); controller = $componentController('vnItemSummary', {$element, $scope}); controller.item = {id: 1}; + controller.card = {}; })); describe('getSummary()', () => { it('should perform a query to set summary', () => { let data = {id: 1, name: 'Gem of mind'}; $httpBackend.expect('GET', `Items/1/getSummary`).respond(200, data); + $httpBackend.expect('GET', `ItemConfigs/findOne`).respond({}); + $httpBackend.expect('GET', `Warehouses/findOne`).respond({}); controller.getSummary(); $httpBackend.flush(); diff --git a/modules/item/front/summary/locale/en.yml b/modules/item/front/summary/locale/en.yml new file mode 100644 index 000000000..0ec208720 --- /dev/null +++ b/modules/item/front/summary/locale/en.yml @@ -0,0 +1 @@ +WarehouseFk: Calculated on the warehouse of {{ warehouseName }} diff --git a/modules/item/front/summary/locale/es.yml b/modules/item/front/summary/locale/es.yml index a87a04857..2e78841ae 100644 --- a/modules/item/front/summary/locale/es.yml +++ b/modules/item/front/summary/locale/es.yml @@ -1,3 +1,4 @@ Barcode: Códigos de barras Other data: Otros datos -Go to the item: Ir al artículo \ No newline at end of file +Go to the item: Ir al artículo +WarehouseFk: Calculado sobre el almacén de {{ warehouseName }} diff --git a/modules/item/front/summary/style.scss b/modules/item/front/summary/style.scss index 7d5e3b609..d047f3e36 100644 --- a/modules/item/front/summary/style.scss +++ b/modules/item/front/summary/style.scss @@ -29,7 +29,11 @@ vn-item-summary { padding: 0; &:nth-child(1) { - border-right: 1px solid white; + border-right: 1px solid white; + } + + &:nth-child(2) { + border-right: 1px solid white; } } -} \ No newline at end of file +} diff --git a/modules/item/front/tags/index.js b/modules/item/front/tags/index.js index bfa1f3f46..2c3b39d45 100644 --- a/modules/item/front/tags/index.js +++ b/modules/item/front/tags/index.js @@ -40,6 +40,7 @@ class Controller extends Section { this.$.model.refresh(); this.$.watcher.notifySaved(); this.$.watcher.updateOriginalData(); + this.card.reload(); }); } } diff --git a/modules/order/front/line/index.html b/modules/order/front/line/index.html index f0a2f2bdf..7be5a00af 100644 --- a/modules/order/front/line/index.html +++ b/modules/order/front/line/index.html @@ -39,7 +39,7 @@ - {{::row.itemFk | zeroFill:6}} + {{::row.itemFk}} diff --git a/modules/order/front/summary/index.html b/modules/order/front/summary/index.html index 2813aeb9b..3622ae932 100644 --- a/modules/order/front/summary/index.html +++ b/modules/order/front/summary/index.html @@ -95,7 +95,7 @@ - {{::row.itemFk | zeroFill:6}} + {{::row.itemFk}} diff --git a/modules/ticket/back/methods/ticket/getTicketsAdvance.js b/modules/ticket/back/methods/ticket/getTicketsAdvance.js index 1e1646cba..ec9314db2 100644 --- a/modules/ticket/back/methods/ticket/getTicketsAdvance.js +++ b/modules/ticket/back/methods/ticket/getTicketsAdvance.js @@ -50,15 +50,9 @@ module.exports = Self => { required: false }, { - arg: 'isNotValidated', + arg: 'isFullMovable', type: 'boolean', - description: 'Origin state', - required: false - }, - { - arg: 'futureIsNotValidated', - type: 'boolean', - description: 'Destination state', + description: 'True when lines and stock of origin are equal', required: false }, { @@ -93,22 +87,20 @@ module.exports = Self => { return {'f.futureId': value}; case 'ipt': return {or: - [ - {'f.ipt': {like: `%${value}%`}}, - {'f.ipt': null} - ] + [ + {'f.ipt': {like: `%${value}%`}}, + {'f.ipt': null} + ] }; case 'futureIpt': return {or: - [ - {'f.futureIpt': {like: `%${value}%`}}, - {'f.futureIpt': null} - ] + [ + {'f.futureIpt': {like: `%${value}%`}}, + {'f.futureIpt': null} + ] }; - case 'isNotValidated': - return {'f.isNotValidated': value}; - case 'futureIsNotValidated': - return {'f.futureIsNotValidated': value}; + case 'isFullMovable': + return {'f.isFullMovable': value}; } }); diff --git a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js index 11571bede..5a3209a6d 100644 --- a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js +++ b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js @@ -29,7 +29,7 @@ describe('TicketFuture getTicketsAdvance()', () => { } }); - it('should return the tickets matching the origin pending state', async() => { + it('should return the tickets matching the fullMovable true', async() => { const tx = await models.Ticket.beginTransaction({}); try { @@ -39,7 +39,7 @@ describe('TicketFuture getTicketsAdvance()', () => { dateFuture: tomorrow, dateToAdvance: today, warehouseFk: 1, - futureIsNotValidated: true + isFullMovable: true }; const ctx = {req: {accessToken: {userId: 9}}, args}; @@ -54,7 +54,7 @@ describe('TicketFuture getTicketsAdvance()', () => { } }); - it('should return the tickets matching the destination pending state', async() => { + it('should return the tickets matching the fullMovable false', async() => { const tx = await models.Ticket.beginTransaction({}); try { @@ -64,7 +64,7 @@ describe('TicketFuture getTicketsAdvance()', () => { dateFuture: tomorrow, dateToAdvance: today, warehouseFk: 1, - isNotValidated: true + isFullMovable: false }; const ctx = {req: {accessToken: {userId: 9}}, args}; @@ -95,7 +95,7 @@ describe('TicketFuture getTicketsAdvance()', () => { const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsAdvance(ctx, options); - expect(result.length).toBeLessThan(5); + expect(result.length).toBeGreaterThan(5); await tx.rollback(); } catch (e) { @@ -120,7 +120,7 @@ describe('TicketFuture getTicketsAdvance()', () => { const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsAdvance(ctx, options); - expect(result.length).toBeLessThan(5); + expect(result.length).toBeGreaterThan(5); await tx.rollback(); } catch (e) { diff --git a/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js b/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js index 1db1b6eaa..cc54353ef 100644 --- a/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js +++ b/modules/ticket/back/methods/ticket/specs/priceDifference.spec.js @@ -86,7 +86,7 @@ describe('sale priceDifference()', () => { const firstItem = result.items[0]; const secondtItem = result.items[1]; - expect(firstItem.movable).toEqual(410); + expect(firstItem.movable).toEqual(380); expect(secondtItem.movable).toEqual(1790); await tx.rollback(); diff --git a/modules/ticket/front/advance-search-panel/index.html b/modules/ticket/front/advance-search-panel/index.html index dfe1f6b08..ee18c26f9 100644 --- a/modules/ticket/front/advance-search-panel/index.html +++ b/modules/ticket/front/advance-search-panel/index.html @@ -41,18 +41,10 @@ - - - - - Origin Destination + Origin @@ -45,31 +45,7 @@ - - ID - - - Date - - - IPT - - - State - - - Liters - - - Stock - - - Lines - - - Import - - + ID @@ -90,6 +66,30 @@ Import + + ID + + + Date + + + IPT + + + State + + + Liters + + + Not Movable + + + Lines + + + Import + @@ -104,36 +104,9 @@ + title="{{$ctrl.agencies(ticket.futureAgency, ticket.agency)}}"> - - - {{::ticket.futureId | dashIfEmpty}} - - - - - {{::ticket.futureShipped | date: 'dd/MM/yyyy'}} - - - {{::ticket.futureIpt | dashIfEmpty}} - - - {{::ticket.futureState | dashIfEmpty}} - - - {{::ticket.futureLiters | dashIfEmpty}} - {{::ticket.hasStock | dashIfEmpty}} - {{::ticket.futureLines | dashIfEmpty}} - - - {{::(ticket.futureTotalWithVat ? ticket.futureTotalWithVat : 0) | currency: 'EUR': 2}} - - {{::ticket.liters | dashIfEmpty}} {{::ticket.lines | dashIfEmpty}} - + {{::(ticket.totalWithVat ? ticket.totalWithVat : 0) | currency: 'EUR': 2}} + + + {{::ticket.futureId | dashIfEmpty}} + + + + + {{::ticket.futureShipped | date: 'dd/MM/yyyy'}} + + + {{::ticket.futureIpt | dashIfEmpty}} + + + {{::ticket.futureState | dashIfEmpty}} + + + {{::ticket.futureLiters | dashIfEmpty}} + {{::ticket.notMovableLines | dashIfEmpty}} + {{::ticket.futureLines | dashIfEmpty}} + + + {{::(ticket.futureTotalWithVat ? ticket.futureTotalWithVat : 0) | currency: 'EUR': 2}} + + + diff --git a/modules/ticket/front/advance/index.js b/modules/ticket/front/advance/index.js index 1b9272bcc..7b8008426 100644 --- a/modules/ticket/front/advance/index.js +++ b/modules/ticket/front/advance/index.js @@ -119,9 +119,15 @@ export default class Controller extends Section { } totalPriceColor(totalWithVat) { - const total = parseInt(totalWithVat); - if (total > 0 && total < 50) - return 'warning'; + return this.isLessThan50(totalWithVat) ? 'warning' : ''; + } + + totalPriceTitle(totalWithVat) { + return this.isLessThan50(totalWithVat) ? 'Less than 50€' : ''; + } + + isLessThan50(totalWithVat) { + return (parseInt(totalWithVat) > 0 && parseInt(totalWithVat) < 50); } get confirmationMessage() { @@ -134,7 +140,7 @@ export default class Controller extends Section { agencies(futureAgency, agency) { return this.$t(`Origin agency`, {agency: futureAgency}) + - '
' + this.$t(`Destination agency`, {agency: agency}); + '\n' + this.$t(`Destination agency`, {agency: agency}); } moveTicketsAdvance() { @@ -171,15 +177,25 @@ export default class Controller extends Section { case 'futureLines': return {'futureLines': value}; case 'ipt': - return {'ipt': value}; + return {or: + [ + {'ipt': {like: `%${value}%`}}, + {'ipt': null} + ] + }; case 'futureIpt': - return {'futureIpt': value}; + return {or: + [ + {'futureIpt': {like: `%${value}%`}}, + {'futureIpt': null} + ] + }; case 'totalWithVat': return {'totalWithVat': value}; case 'futureTotalWithVat': return {'futureTotalWithVat': value}; - case 'hasStock': - return {'hasStock': value}; + case 'notMovableLines': + return {'notMovableLines': value}; } } } diff --git a/modules/ticket/front/advance/locale/es.yml b/modules/ticket/front/advance/locale/es.yml index da22cd433..3111d9afd 100644 --- a/modules/ticket/front/advance/locale/es.yml +++ b/modules/ticket/front/advance/locale/es.yml @@ -7,3 +7,5 @@ Liters: Litros Item Packing Type: Encajado Origin agency: "Agencia origen: {{agency}}" Destination agency: "Agencia destino: {{agency}}" +Less than 50€: Menor a 50€ +Not Movable: No movibles diff --git a/modules/ticket/front/basic-data/step-two/index.html b/modules/ticket/front/basic-data/step-two/index.html index ad0c49dbb..fc57a354a 100644 --- a/modules/ticket/front/basic-data/step-two/index.html +++ b/modules/ticket/front/basic-data/step-two/index.html @@ -23,7 +23,7 @@ title="{{::sale.item.name}}" vn-click-stop="itemDescriptor.show($event, sale.itemFk, sale.id)" class="link"> - {{::sale.itemFk | zeroFill:6}} + {{::sale.itemFk}}
diff --git a/modules/ticket/front/component/index.html b/modules/ticket/front/component/index.html index 1236059ae..39b54b461 100644 --- a/modules/ticket/front/component/index.html +++ b/modules/ticket/front/component/index.html @@ -27,7 +27,7 @@ - {{sale.itemFk | zeroFill:6}} + {{sale.itemFk}} diff --git a/modules/ticket/front/expedition/index.html b/modules/ticket/front/expedition/index.html index ec6dc7ee2..447411f3a 100644 --- a/modules/ticket/front/expedition/index.html +++ b/modules/ticket/front/expedition/index.html @@ -55,7 +55,7 @@ ng-model="expedition.checked"> - {{expedition.id | zeroFill:6}} + {{expedition.id}} {{::ticket.liters}} {{::ticket.lines}} - + diff --git a/modules/ticket/front/future/index.js b/modules/ticket/front/future/index.js index b588f1e49..8cb7f16aa 100644 --- a/modules/ticket/front/future/index.js +++ b/modules/ticket/front/future/index.js @@ -149,9 +149,19 @@ export default class Controller extends Section { case 'lines': return {'lines': value}; case 'ipt': - return {'ipt': value}; + return {or: + [ + {'ipt': {like: `%${value}%`}}, + {'ipt': null} + ] + }; case 'futureIpt': - return {'futureIpt': value}; + return {or: + [ + {'futureIpt': {like: `%${value}%`}}, + {'futureIpt': null} + ] + }; } } } diff --git a/modules/ticket/front/request/index/index.html b/modules/ticket/front/request/index/index.html index 054f0c76a..510c09974 100644 --- a/modules/ticket/front/request/index/index.html +++ b/modules/ticket/front/request/index/index.html @@ -75,7 +75,7 @@ ng-show="::request.saleFk" ng-click="itemDescriptor.show($event, request.sale.itemFk, request.sale.id)" class="link"> - {{::request.saleFk | zeroFill:6}} + {{::request.saleFk}} + ng-click="itemDescriptor.show($event, sale.itemFk, sale.id, $ctrl.ticket.shipped)"> {{sale.itemFk}} - {{::sale.itemFk | zeroFill:6}} + {{::sale.itemFk}} {{::sale.concept}} diff --git a/modules/ticket/front/summary/index.html b/modules/ticket/front/summary/index.html index a7441dcf1..97055208b 100644 --- a/modules/ticket/front/summary/index.html +++ b/modules/ticket/front/summary/index.html @@ -177,7 +177,7 @@ - {{sale.itemFk | zeroFill:6}} + {{sale.itemFk}} @@ -312,7 +312,7 @@ ng-show="::request.saleFk" ng-click="itemDescriptor.show($event, request.sale.itemFk, request.sale.id)" class="link"> - {{request.sale.itemFk | zeroFill:6}} + {{request.sale.itemFk}} diff --git a/modules/ticket/front/volume/index.html b/modules/ticket/front/volume/index.html index 8f17a9475..f5dd18033 100644 --- a/modules/ticket/front/volume/index.html +++ b/modules/ticket/front/volume/index.html @@ -35,7 +35,7 @@ - {{sale.itemFk | zeroFill:6}} + {{sale.itemFk}} diff --git a/package.json b/package.json index 89bd1a3e8..4cf53911c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-back", - "version": "23.06.01", + "version": "23.08.01", "author": "Verdnatura Levante SL", "description": "Salix backend", "license": "GPL-3.0", diff --git a/print/core/filters/index.js b/print/core/filters/index.js index efc398508..bfd99c504 100644 --- a/print/core/filters/index.js +++ b/print/core/filters/index.js @@ -4,5 +4,4 @@ require('./uppercase'); require('./currency'); require('./percentage'); require('./number'); -require('./zerofill'); diff --git a/print/core/filters/specs/zerofill.spec.js b/print/core/filters/specs/zerofill.spec.js deleted file mode 100644 index 1c00ff4a7..000000000 --- a/print/core/filters/specs/zerofill.spec.js +++ /dev/null @@ -1,9 +0,0 @@ -import zerofill from '../zerofill.js'; - -describe('zerofill filter', () => { - const superDuperNumber = 1984; - - it('should filter the number filling it with zeros up to 6 characters length', () => { - expect(zerofill(superDuperNumber, '000000')).toEqual('001984'); - }); -}); diff --git a/print/core/filters/zerofill.js b/print/core/filters/zerofill.js deleted file mode 100644 index c3d18079b..000000000 --- a/print/core/filters/zerofill.js +++ /dev/null @@ -1,10 +0,0 @@ -const Vue = require('vue'); - -const zerofill = function(value, pad) { - const valueStr = String(value); - return pad.substring(0, pad.length - valueStr.length) + valueStr; -}; - -Vue.filter('zerofill', zerofill); - -module.exports = zerofill; diff --git a/print/templates/reports/balance-compensation/balance-compensation.html b/print/templates/reports/balance-compensation/balance-compensation.html index 1e9aa5661..d1a2788ed 100644 --- a/print/templates/reports/balance-compensation/balance-compensation.html +++ b/print/templates/reports/balance-compensation/balance-compensation.html @@ -17,8 +17,8 @@

{{$t('Agree') | uppercase}}

- {{$t('Date')}} {{formatDate(client.payed, '%d-%m-%Y')}} {{$t('Compensate')}} {{client.amountPaid}} € - {{$t('From client')}} {{client.name}} {{$t('Toclient')}} {{company.name}}. + {{$t('Date')}} {{client.payed | date('%d-%m-%Y')}} {{$t('Compensate')}} {{client.amountPaid}} € + {{$t('From client')}} {{client.name}} {{$t('Against the balance of')}}: {{client.invoiceFk}}.

{{$t('Reception')}} administracion@verdnatura.es diff --git a/print/templates/reports/balance-compensation/locale/es.yml b/print/templates/reports/balance-compensation/locale/es.yml index 546e55f06..1c76274ae 100644 --- a/print/templates/reports/balance-compensation/locale/es.yml +++ b/print/templates/reports/balance-compensation/locale/es.yml @@ -4,13 +4,13 @@ Compensation: Compensación de saldos deudores y acreedores In one hand: De una parte CIF: con CIF NIF: con NIF -Home: y domicilio sito en +Home: y domicilio sito en In other hand: De la otra Sr: Don/Doña Agree: Acuerdan Date: En fecha de -Compensate: se ha compensado el saldo de +Compensate: se ha compensado el saldo de From client: del cliente/proveedor -To client: con el cliente/proveedor +Against the balance of: contra el saldo de Reception: Por favor, rogamos confirmen la recepción de esta compensación al email -Greetings: Saludos cordiales, \ No newline at end of file +Greetings: Saludos cordiales, diff --git a/print/templates/reports/balance-compensation/sql/client.sql b/print/templates/reports/balance-compensation/sql/client.sql index b4463be23..c3679b68a 100644 --- a/print/templates/reports/balance-compensation/sql/client.sql +++ b/print/templates/reports/balance-compensation/sql/client.sql @@ -4,6 +4,7 @@ SELECT c.street, c.fi, c.city, + r.invoiceFk, r.amountPaid, r.payed FROM client c diff --git a/print/templates/reports/campaign-metrics/campaign-metrics.html b/print/templates/reports/campaign-metrics/campaign-metrics.html index 57d616a29..ad60c511c 100644 --- a/print/templates/reports/campaign-metrics/campaign-metrics.html +++ b/print/templates/reports/campaign-metrics/campaign-metrics.html @@ -45,7 +45,7 @@ - {{sale.itemFk | zerofill('000000')}} + {{sale.itemFk}} {{Math.trunc(sale.subtotal)}} {{sale.concept}} diff --git a/print/templates/reports/client-debt-statement/client-debt-statement.html b/print/templates/reports/client-debt-statement/client-debt-statement.html index fb7bfd625..30fbbe003 100644 --- a/print/templates/reports/client-debt-statement/client-debt-statement.html +++ b/print/templates/reports/client-debt-statement/client-debt-statement.html @@ -13,7 +13,7 @@ {{$t('date')}} - {{formatDate(new Date(), '%d-%m-%Y');}} + {{formatDate(new Date(), '%d-%m-%Y')}} @@ -44,7 +44,7 @@ - {{formatDate(sale.issued, '%d-%m-%Y');}} + {{formatDate(sale.issued, '%d-%m-%Y')}} {{sale.ref}} {{sale.debtOut}} {{sale.debtIn}} diff --git a/print/templates/reports/collection-label/collection-label.html b/print/templates/reports/collection-label/collection-label.html index 2fd77079f..a699d4ac5 100644 --- a/print/templates/reports/collection-label/collection-label.html +++ b/print/templates/reports/collection-label/collection-label.html @@ -21,7 +21,7 @@ {{labelData.code == 'V' ? (labelData.size || 0) + 'cm' : (labelData.volume || 0) + 'm³'}} -

{{labelData.agencyDescription ? labelData.agencyDescription.toUpperCase() : '---'}}
+
{{getAgencyDescripton(labelData)}}
{{labelData.lineCount || 0}} diff --git a/print/templates/reports/collection-label/collection-label.js b/print/templates/reports/collection-label/collection-label.js index 74024bb56..656dde082 100644 --- a/print/templates/reports/collection-label/collection-label.js +++ b/print/templates/reports/collection-label/collection-label.js @@ -59,5 +59,17 @@ module.exports = { return value; }, + getAgencyDescripton(labelData) { + let value; + if (labelData.agencyDescription) + value = labelData.agencyDescription.toUpperCase().substring(0, 11); + else + value = '---'; + + if (labelData.routeFk) + value = `${value} [${labelData.routeFk.toString().substring(0, 3)}]`; + + return value; + }, }, }; diff --git a/print/templates/reports/collection-label/sql/labelsData.sql b/print/templates/reports/collection-label/sql/labelsData.sql index 1846c6893..fef692272 100644 --- a/print/templates/reports/collection-label/sql/labelsData.sql +++ b/print/templates/reports/collection-label/sql/labelsData.sql @@ -1,37 +1,38 @@ SELECT c.itemPackingTypeFk code, - tc.collectionFk, - SUBSTRING('ABCDEFGH', tc.wagon, 1) wagon, - tc.`level`, - t.id ticketFk, - COALESCE(et.description, zo.name, am.name) agencyDescription, - cc.code color, - t.clientFk, - CAST(SUM(sv.volume) AS DECIMAL(5, 2)) volume, - MAX(i.`size`) `size`, - w.code workerCode, - TIME_FORMAT(t.shipped, '%H:%i') shippedHour, - TIME_FORMAT(zo.`hour`, '%H:%i') zoneHour, - DATE_FORMAT(t.shipped, '%d/%m/%y') shipped, - tt.labelCount, - t.nickName, - COUNT(*) lineCount - FROM vn.ticket t - JOIN vn.ticketCollection tc ON tc.ticketFk = t.id - JOIN vn.collection c ON c.id = tc.collectionFk - LEFT JOIN vn.collectionColors cc ON cc.shelve = tc.`level` - AND cc.wagon = tc.wagon - AND cc.trainFk = c.trainFk - JOIN vn.sale s ON s.ticketFk = t.id - LEFT JOIN vn.saleVolume sv ON sv.saleFk = s.id - JOIN vn.item i ON i.id = s.itemFk - JOIN vn.itemType it ON it.id = i.typeFk - JOIN vn.itemCategory ic ON ic.id = it.categoryFk - JOIN vn.worker w ON w.id = c.workerFk - JOIN vn.agencyMode am ON am.id = t.agencyModeFk - LEFT JOIN vn.ticketTrolley tt ON tt.ticket = t.id - LEFT JOIN vn.`zone` zo ON t.zoneFk = zo.id - LEFT JOIN vn.routesMonitor rm ON rm.routeFk = t.routeFk - LEFT JOIN vn.expeditionTruck et ON et.id = rm.expeditionTruckFk - WHERE t.id IN (?) - GROUP BY t.id - ORDER BY cc.`code`; \ No newline at end of file + tc.collectionFk, + SUBSTRING('ABCDEFGH', tc.wagon, 1) wagon, + tc.`level`, + t.id ticketFk, + COALESCE(et.description, zo.name, am.name) agencyDescription, + cc.code color, + t.clientFk, + CAST(SUM(sv.volume) AS DECIMAL(5, 2)) volume, + MAX(i.`size`) `size`, + w.code workerCode, + TIME_FORMAT(t.shipped, '%H:%i') shippedHour, + TIME_FORMAT(zo.`hour`, '%H:%i') zoneHour, + DATE_FORMAT(t.shipped, '%d/%m/%y') shipped, + tt.labelCount, + t.nickName, + COUNT(*) lineCount, + rm.routeFk + FROM vn.ticket t + JOIN vn.ticketCollection tc ON tc.ticketFk = t.id + JOIN vn.collection c ON c.id = tc.collectionFk + LEFT JOIN vn.collectionColors cc ON cc.shelve = tc.`level` + AND cc.wagon = tc.wagon + AND cc.trainFk = c.trainFk + JOIN vn.sale s ON s.ticketFk = t.id + LEFT JOIN vn.saleVolume sv ON sv.saleFk = s.id + JOIN vn.item i ON i.id = s.itemFk + JOIN vn.itemType it ON it.id = i.typeFk + JOIN vn.itemCategory ic ON ic.id = it.categoryFk + JOIN vn.worker w ON w.id = c.workerFk + JOIN vn.agencyMode am ON am.id = t.agencyModeFk + LEFT JOIN vn.ticketTrolley tt ON tt.ticket = t.id + LEFT JOIN vn.`zone` zo ON t.zoneFk = zo.id + LEFT JOIN vn.routesMonitor rm ON rm.routeFk = t.routeFk + LEFT JOIN vn.expeditionTruck et ON et.id = rm.expeditionTruckFk + WHERE t.id IN (?) + GROUP BY t.id + ORDER BY cc.`code`; \ No newline at end of file diff --git a/print/templates/reports/delivery-note/delivery-note.html b/print/templates/reports/delivery-note/delivery-note.html index 9f217ba22..eb133c0cd 100644 --- a/print/templates/reports/delivery-note/delivery-note.html +++ b/print/templates/reports/delivery-note/delivery-note.html @@ -66,7 +66,7 @@ - {{sale.itemFk | zerofill('000000')}} + {{sale.itemFk}} {{sale.quantity}} {{sale.concept}} {{sale.price | currency('EUR', $i18n.locale)}} @@ -145,7 +145,7 @@ - {{packaging.itemFk | zerofill('000000')}} + {{packaging.itemFk}} {{packaging.quantity}} {{packaging.name}} diff --git a/print/templates/reports/delivery-note/delivery-note.js b/print/templates/reports/delivery-note/delivery-note.js index d9544a58c..50d5720ad 100755 --- a/print/templates/reports/delivery-note/delivery-note.js +++ b/print/templates/reports/delivery-note/delivery-note.js @@ -13,7 +13,7 @@ module.exports = { this.sales = await this.rawSqlFromDef('sales', [this.id]); this.address = await this.findOneFromDef(`address`, [this.id]); this.services = await this.rawSqlFromDef('services', [this.id]); - this.taxes = await this.rawSqlFromDef('taxes', [this.id]); + this.taxes = await this.findOneFromDef('taxes', [this.id]); this.packagings = await this.rawSqlFromDef('packagings', [this.id]); this.signature = await this.findOneFromDef('signature', [this.id]); }, diff --git a/print/templates/reports/invoice/invoice.html b/print/templates/reports/invoice/invoice.html index 60d06d528..2d180878a 100644 --- a/print/templates/reports/invoice/invoice.html +++ b/print/templates/reports/invoice/invoice.html @@ -96,7 +96,7 @@ - {{sale.itemFk | zerofill('000000')}} + {{sale.itemFk}} {{sale.quantity}} {{sale.concept}} {{sale.price | currency('EUR', $i18n.locale)}} @@ -203,7 +203,7 @@

-
+

{{$t('intrastat')}}

diff --git a/print/templates/reports/invoice/invoice.js b/print/templates/reports/invoice/invoice.js index 7b572d970..eaf17527d 100755 --- a/print/templates/reports/invoice/invoice.js +++ b/print/templates/reports/invoice/invoice.js @@ -10,7 +10,8 @@ module.exports = { this.checkMainEntity(this.invoice); this.client = await this.findOneFromDef('client', [this.reference]); this.taxes = await this.rawSqlFromDef(`taxes`, [this.reference]); - this.intrastat = await this.rawSqlFromDef(`intrastat`, [this.reference, this.reference, this.reference]); + this.hasIntrastat = await this.findValueFromDef(`hasIntrastat`, [this.reference]); + this.intrastat = await this.rawSqlFromDef(`intrastat`, [this.reference, this.reference, this.reference, this.reference]); this.rectified = await this.rawSqlFromDef(`rectified`, [this.reference]); this.hasIncoterms = await this.findValueFromDef(`hasIncoterms`, [this.reference]); diff --git a/print/templates/reports/invoice/sql/hasIntrastat.sql b/print/templates/reports/invoice/sql/hasIntrastat.sql new file mode 100644 index 000000000..09eda94c2 --- /dev/null +++ b/print/templates/reports/invoice/sql/hasIntrastat.sql @@ -0,0 +1,4 @@ +SELECT taxAreaFk != 'NATIONAL' + FROM vn.invoiceOutSerial ios + JOIN vn.invoiceOut io ON io.serial = ios.code + WHERE io.ref = ?; diff --git a/print/templates/reports/invoice/sql/intrastat.sql b/print/templates/reports/invoice/sql/intrastat.sql index f986a9564..211ebfe71 100644 --- a/print/templates/reports/invoice/sql/intrastat.sql +++ b/print/templates/reports/invoice/sql/intrastat.sql @@ -1,26 +1,36 @@ SELECT * - FROM invoiceOut io - JOIN invoiceOutSerial ios ON io.serial = ios.code - JOIN( - SELECT ir.id code, - ir.description, - iii.stems, - iii.net netKg, - iii.amount subtotal - FROM vn.invoiceInIntrastat iii - LEFT JOIN vn.invoiceIn ii ON ii.id = iii.invoiceInFk - LEFT JOIN vn.invoiceOut io ON io.ref = ii.supplierRef - LEFT JOIN vn.intrastat ir ON ir.id = iii.intrastatFk - WHERE io.`ref` = ? - UNION ALL - SELECT NULL code, - 'Servicios' description, - 0 stems, - 0 netKg, - IF(CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), 0) subtotal - FROM vn.ticketService ts - JOIN vn.ticket t ON ts.ticketFk = t.id - WHERE t.refFk = ? - ) sub - WHERE io.ref = ? AND ios.isCEE - ORDER BY sub.code; + FROM ( + SELECT i.intrastatFk code, + it.description, + CAST(SUM(ROUND((s.quantity * s.price * (100 - s.discount) / 100 ) , 2))AS DECIMAL(10, 2)) subtotal, + SUM(IFNULL(i.stems, 1) * s.quantity) stems, + CAST(SUM(IFNULL(i.stems, 1) + * s.quantity + * IF(ic.grams, ic.grams, IFNULL(i.weightByPiece, 0)) / 1000) + * IF(sub.totalWeight, sub.totalWeight / vn.invoiceOut_getWeight(?), 1) + AS DECIMAL(10,2)) netKg + FROM sale s + JOIN ticket t ON s.ticketFk = t.id + JOIN supplier su ON su.id = t.companyFk + JOIN item i ON i.id = s.itemFk + JOIN intrastat it ON it.id = i.intrastatFk + LEFT JOIN itemCost ic ON ic.itemFk = i.id AND ic.warehouseFk = t.warehouseFk + LEFT JOIN ( + SELECT SUM(weight)totalWeight + FROM vn.ticket + WHERE refFk = ? + AND weight + ) sub ON TRUE + WHERE t.refFk =? + GROUP BY i.intrastatFk + UNION ALL + SELECT NULL , + IF((SUM((ts.quantity * ts.price))), 'Servicios', NULL), + IFNULL(CAST(SUM((ts.quantity * ts.price)) AS DECIMAL(10,2)), 0), + 0 , + 0 + FROM vn.ticketService ts + JOIN vn.ticket t ON ts.ticketFk = t.id + WHERE t.refFk = ? + ) sub2 + WHERE `description` IS NOT NULL;