From 0529d56d4ec3947aa64b45a005501498b5862d96 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 9 Feb 2023 13:30:52 +0100 Subject: [PATCH 01/14] fix(delivery-note_report): fix taxes --- print/templates/reports/delivery-note/delivery-note.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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]); }, From 194069c0c2911472f3cf55e7869fca4ec1cee9a1 Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 10 Feb 2023 08:46:54 +0100 Subject: [PATCH 02/14] refs #5194 fixed stock, lines --- db/dump/fixtures.sql | 7 +- .../item/specs/getVisibleAvailable.spec.js | 2 +- modules/item/front/last-entries/index.html | 44 +++---- .../back/methods/ticket/getTicketsAdvance.js | 32 ++--- .../ticket/specs/getTicketsAdvance.spec.js | 16 +-- .../ticket/specs/priceDifference.spec.js | 2 +- .../front/advance-search-panel/index.html | 28 +---- .../front/advance-search-panel/locale/es.yml | 1 + modules/ticket/front/advance/index.html | 112 ++++++++++-------- modules/ticket/front/advance/index.js | 31 ++++- modules/ticket/front/advance/locale/es.yml | 4 + modules/ticket/front/future/index.html | 2 +- modules/ticket/front/future/index.js | 14 ++- 13 files changed, 165 insertions(+), 130 deletions(-) diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql index ece33f813..b62220a68 100644 --- a/db/dump/fixtures.sql +++ b/db/dump/fixtures.sql @@ -691,7 +691,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 @@ -993,7 +994,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 diff --git a/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js b/modules/item/back/methods/item/specs/getVisibleAvailable.spec.js index 8e4864ee8..e5f7bb81b 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/front/last-entries/index.html b/modules/item/front/last-entries/index.html index 0348d4f66..ba0552613 100644 --- a/modules/item/front/last-entries/index.html +++ b/modules/item/front/last-entries/index.html @@ -9,15 +9,15 @@ - + @@ -35,8 +35,7 @@ Warehouse Landed Entry - P.P.U - P.P.P + PVP Label Packing Grouping @@ -51,7 +50,7 @@ - @@ -65,26 +64,27 @@ {{::entry.entryFk | dashIfEmpty}} - {{::entry.price2 | dashIfEmpty}} - {{::entry.price3 | dashIfEmpty}} + + {{::entry.price2 | currency: 'EUR':2 | dashIfEmpty}} / {{::entry.price3 | currency: 'EUR':2 | dashIfEmpty}} + {{entry.stickers | dashIfEmpty}} - + {{::entry.packing | dashIfEmpty}} - + {{::entry.grouping | dashIfEmpty}} {{::entry.stems | dashIfEmpty}} {{::entry.quantity}} - @@ -113,24 +113,24 @@ ng-click="contextmenu.filterBySelection()"> Filter by selection - Exclude selection - Remove filter - Remove all filters - Copy value - \ No newline at end of file + diff --git a/modules/ticket/back/methods/ticket/getTicketsAdvance.js b/modules/ticket/back/methods/ticket/getTicketsAdvance.js index 19571bb51..86911a477 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: 'state', - type: 'string', - description: 'Origin state', - required: false - }, - { - arg: 'futureState', - type: 'string', - description: 'Destination state', + arg: 'fullMovable', + type: 'boolean', + description: 'True when lines and stock of origin are equal', required: false }, { @@ -92,13 +86,21 @@ module.exports = Self => { case 'futureId': return {'f.futureId': value}; case 'ipt': - return {'f.ipt': value}; + return {or: + [ + {'f.ipt': {like: `%${value}%`}}, + {'f.ipt': null} + ] + }; case 'futureIpt': - return {'f.futureIpt': value}; - case 'state': - return {'f.stateCode': {like: `%${value}%`}}; - case 'futureState': - return {'f.futureStateCode': {like: `%${value}%`}}; + return {or: + [ + {'f.futureIpt': {like: `%${value}%`}}, + {'f.futureIpt': null} + ] + }; + case 'fullMovable': + return {'f.fullMovable': value}; } }); diff --git a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js index aab053127..cb4762549 100644 --- a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js +++ b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js @@ -1,7 +1,7 @@ const models = require('vn-loopback/server/server').models; -describe('TicketFuture getTicketsAdvance()', () => { - const today = new Date(); +describe('ticket getTicketsAdvance()', () => { + const today = Date.vnNew(); today.setHours(0, 0, 0, 0); let tomorrow = new Date(); tomorrow.setDate(today.getDate() + 1); @@ -29,7 +29,7 @@ describe('TicketFuture getTicketsAdvance()', () => { } }); - it('should return the tickets matching the origin grouped 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, - state: 'OK' + fullMovable: true }; const ctx = {req: {accessToken: {userId: 9}}, args}; @@ -54,7 +54,7 @@ describe('TicketFuture getTicketsAdvance()', () => { } }); - it('should return the tickets matching the destination grouped 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, - futureState: 'FREE' + fullMovable: 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 5470382f9..e1e93af1e 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 e8d5dc60d..233d00127 100644 --- a/modules/ticket/front/advance-search-panel/index.html +++ b/modules/ticket/front/advance-search-panel/index.html @@ -39,28 +39,12 @@ - - - {{name}} - - - - - {{name}} - - - - + + - Origin - Destination + Destination + Origin @@ -43,7 +43,30 @@ check-field="checked"> - + + + + ID + + + Date + + + IPT + + + State + + + Liters + + + Lines + + + Import + + ID @@ -58,30 +81,6 @@ Import - - ID - - - Date - - - IPT - - - State - - - Liters - - - Stock - - - Lines - - - Import - @@ -93,28 +92,11 @@ - - {{::ticket.futureId | dashIfEmpty}} - - - - - {{::ticket.futureShipped | date: 'dd/MM/yyyy'}} - - - {{::ticket.futureIpt | dashIfEmpty}} - - - {{::ticket.futureState | dashIfEmpty}} - - - - - {{::(ticket.futureTotalWithVat ? ticket.futureTotalWithVat : 0) | currency: 'EUR': 2}} - + + {{::ticket.liters | dashIfEmpty}} - {{::ticket.hasStock | 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.futureTotalWithVat ? ticket.futureTotalWithVat : 0) | currency: 'EUR': 2}} + + + diff --git a/modules/ticket/front/advance/index.js b/modules/ticket/front/advance/index.js index b770440f1..0fb5119e3 100644 --- a/modules/ticket/front/advance/index.js +++ b/modules/ticket/front/advance/index.js @@ -115,9 +115,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() { @@ -128,6 +134,11 @@ export default class Controller extends Section { }); } + agencies(futureAgency, agency) { + return this.$t(`Origin agency`, {agency: futureAgency}) + + '\n' + this.$t(`Destination agency`, {agency: agency}); + } + moveTicketsAdvance() { let ticketsToMove = []; this.checked.forEach(ticket => { @@ -158,9 +169,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} + ] + }; case 'totalWithVat': return {'totalWithVat': value}; case 'futureTotalWithVat': diff --git a/modules/ticket/front/advance/locale/es.yml b/modules/ticket/front/advance/locale/es.yml index b444fbdd3..116a5d4f9 100644 --- a/modules/ticket/front/advance/locale/es.yml +++ b/modules/ticket/front/advance/locale/es.yml @@ -4,3 +4,7 @@ Advance confirmation: ¿Desea adelantar {{checked}} tickets? Success: Tickets movidos correctamente Lines: Líneas Liters: Litros +Item Packing Type: Encajado +Origin agency: "Agencia origen: {{agency}}" +Destination agency: "Agencia destino: {{agency}}" +Less than 50€: Menor a 50€ diff --git a/modules/ticket/front/future/index.html b/modules/ticket/front/future/index.html index c0e1decc2..8628bb34c 100644 --- a/modules/ticket/front/future/index.html +++ b/modules/ticket/front/future/index.html @@ -143,7 +143,7 @@ {{::ticket.liters}} {{::ticket.lines}} - + diff --git a/modules/ticket/front/future/index.js b/modules/ticket/front/future/index.js index 5fb2c8f82..5ca0f46a2 100644 --- a/modules/ticket/front/future/index.js +++ b/modules/ticket/front/future/index.js @@ -146,9 +146,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} + ] + }; } } } From 9dc07d88d691fde4913df62a0cd610e1a7b55896 Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 10 Feb 2023 08:56:30 +0100 Subject: [PATCH 03/14] fixing e2e --- db/changes/230601/00-ticket_canAdvance.sql | 114 ++++++++++++++++++ e2e/helpers/selectors.js | 2 - e2e/paths/05-ticket/22_advance.spec.js | 28 +---- .../ticket/specs/getTicketsAdvance.spec.js | 4 +- 4 files changed, 120 insertions(+), 28 deletions(-) create mode 100644 db/changes/230601/00-ticket_canAdvance.sql diff --git a/db/changes/230601/00-ticket_canAdvance.sql b/db/changes/230601/00-ticket_canAdvance.sql new file mode 100644 index 000000000..af1819c77 --- /dev/null +++ b/db/changes/230601/00-ticket_canAdvance.sql @@ -0,0 +1,114 @@ +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 vn.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 vn.itemTicketOut + WHERE shipped >= vDateInventory + AND shipped < vDateFuture + AND warehouseFk = vWarehouseFk + UNION ALL + SELECT itemFk, quantity + FROM vn.itemEntryIn + WHERE landed >= vDateInventory + AND landed < vDateFuture + AND isVirtualStock = FALSE + AND warehouseInFk = vWarehouseFk + UNION ALL + SELECT itemFk, quantity + FROM vn.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 + *, + CASE WHEN sub.futureLines = hasStock THEN '1' ELSE '0' END AS fullMovable + FROM (SELECT s.ticketFk futureId, + t2.ticketFk id, + count(DISTINCT s.id) saleCount, + t2.state, + st.name futureState, + GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) futureIpt, + t2.ipt, + t.workerFk, + CAST(SUM(litros) AS DECIMAL(10,0)) futureLiters, + CAST(COUNT(*) AS DECIMAL(10,0)) `futureLines`, + t2.shipped, + t.shipped futureShipped, + t2.totalWithVat, + t.totalWithVat futureTotalWithVat, + t2.agency, + am.name futureAgency, + t2.lines, + t2.liters, + SUM((s.quantity <= IFNULL(st.amount,0))) AS hasStock + FROM vn.ticket t + JOIN vn.sale s ON s.ticketFk = t.id + JOIN vn.saleVolume sv ON sv.saleFk = s.id + JOIN vn.item i ON i.id = s.itemFk + JOIN vn.ticketState ts ON ts.ticketFk = t.id + JOIN vn.state st ON st.id = ts.stateFk + JOIN vn.agencyMode am ON t.agencyModeFk = am.id + LEFT JOIN vn.itemPackingType ipt ON ipt.code = i.itemPackingTypeFk + LEFT JOIN tmp.stock st ON st.itemFk = s.itemFk + JOIN (SELECT + t2.id ticketFk, + t2.addressFk, + st.name state, + GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) ipt, + t2.shipped, + t2.totalWithVat, + am.name agency, + CAST(SUM(litros) AS DECIMAL(10,0)) liters, + CAST(COUNT(*) AS DECIMAL(10,0)) `lines` + FROM vn.ticket t2 + JOIN vn.sale s ON s.ticketFk = t2.id + JOIN vn.saleVolume sv ON sv.saleFk = s.id + JOIN vn.item i ON i.id = s.itemFk + JOIN vn.ticketState ts ON ts.ticketFk = t2.id + JOIN vn.state st ON st.id = ts.stateFk + JOIN vn.agencyMode am ON t2.agencyModeFk = am.id + LEFT JOIN vn.itemPackingType ipt ON ipt.code = i.itemPackingTypeFk + WHERE t2.shipped BETWEEN vDateToAdvance AND util.dayend(vDateToAdvance) + AND t2.warehouseFk = vWarehouseFk + AND st.order <= 5 + GROUP BY t2.id) t2 ON t2.addressFk = t.addressFk + WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture) + AND t.warehouseFk = vWarehouseFk + GROUP BY id, futureId + ) sub + WHERE hasStock != 0; + + DROP TEMPORARY TABLE tmp.stock; +END$$ +DELIMITER ; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index c0f10a506..c7afa8aab 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -776,8 +776,6 @@ export default { ipt: 'vn-autocomplete[label="Destination IPT"]', tableIpt: 'vn-autocomplete[name="ipt"]', tableFutureIpt: 'vn-autocomplete[name="futureIpt"]', - futureState: 'vn-autocomplete[label="Origin Grouped State"]', - state: 'vn-autocomplete[label="Destination Grouped State"]', warehouseFk: 'vn-autocomplete[label="Warehouse"]', tableButtonSearch: 'vn-button[vn-tooltip="Search"]', moveButton: 'vn-button[vn-tooltip="Advance tickets"]', diff --git a/e2e/paths/05-ticket/22_advance.spec.js b/e2e/paths/05-ticket/22_advance.spec.js index 6aaa81591..14ff11aa6 100644 --- a/e2e/paths/05-ticket/22_advance.spec.js +++ b/e2e/paths/05-ticket/22_advance.spec.js @@ -10,6 +10,10 @@ describe('Ticket Advance path', () => { 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() => { @@ -70,30 +74,6 @@ describe('Ticket Advance path', () => { await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); }); - it('should search with the origin grouped state', async() => { - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.ticketAdvance.futureState, 'Free'); - await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); - - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.clearInput(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.autocompleteSearch(selectors.ticketAdvance.state, 'Free'); - await page.waitToClick(selectors.ticketAdvance.submit); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 0); - - await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.clearInput(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'); diff --git a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js index cb4762549..685360115 100644 --- a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js +++ b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js @@ -1,7 +1,7 @@ const models = require('vn-loopback/server/server').models; describe('ticket getTicketsAdvance()', () => { - const today = Date.vnNew(); + const today = new Date(); today.setHours(0, 0, 0, 0); let tomorrow = new Date(); tomorrow.setDate(today.getDate() + 1); @@ -70,7 +70,7 @@ describe('ticket getTicketsAdvance()', () => { const ctx = {req: {accessToken: {userId: 9}}, args}; const result = await models.Ticket.getTicketsAdvance(ctx, options); - expect(result.length).toBeGreaterThan(0); + expect(result.length).toEqual(0); await tx.rollback(); } catch (e) { From 4787de3df5f58bec7b68673403080ea84a632c89 Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 10 Feb 2023 09:04:49 +0100 Subject: [PATCH 04/14] fixing merge --- modules/item/front/last-entries/index.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/item/front/last-entries/index.html b/modules/item/front/last-entries/index.html index f381ab63a..f6cdf8343 100644 --- a/modules/item/front/last-entries/index.html +++ b/modules/item/front/last-entries/index.html @@ -9,7 +9,6 @@ - @@ -55,7 +52,6 @@ - From d8acf45e0d9f2545062a055fa738dba7a5f970d9 Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 10 Feb 2023 09:34:42 +0100 Subject: [PATCH 05/14] fix(client-debt-statment): typo --- .../reports/client-debt-statement/client-debt-statement.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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}} From 6cb815faafa440cc66cdd58136ed631ea06a1624 Mon Sep 17 00:00:00 2001 From: alexandre Date: Fri, 10 Feb 2023 10:13:41 +0100 Subject: [PATCH 06/14] . --- db/changes/230601/00-ticket_canAdvance.sql | 4 +- e2e/paths/05-ticket/22_advance.spec.js | 56 ++++++++++++++-------- modules/ticket/front/advance/index.html | 10 ++-- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/db/changes/230601/00-ticket_canAdvance.sql b/db/changes/230601/00-ticket_canAdvance.sql index af1819c77..68942a286 100644 --- a/db/changes/230601/00-ticket_canAdvance.sql +++ b/db/changes/230601/00-ticket_canAdvance.sql @@ -80,7 +80,7 @@ BEGIN JOIN vn.state st ON st.id = ts.stateFk JOIN vn.agencyMode am ON t.agencyModeFk = am.id LEFT JOIN vn.itemPackingType ipt ON ipt.code = i.itemPackingTypeFk - LEFT JOIN tmp.stock st ON st.itemFk = s.itemFk + LEFT JOIN tmp.stock st ON st.itemFk = i.id JOIN (SELECT t2.id ticketFk, t2.addressFk, @@ -105,7 +105,7 @@ BEGIN GROUP BY t2.id) t2 ON t2.addressFk = t.addressFk WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture) AND t.warehouseFk = vWarehouseFk - GROUP BY id, futureId + GROUP BY t.id ) sub WHERE hasStock != 0; diff --git a/e2e/paths/05-ticket/22_advance.spec.js b/e2e/paths/05-ticket/22_advance.spec.js index e94600066..49ab5b0fc 100644 --- a/e2e/paths/05-ticket/22_advance.spec.js +++ b/e2e/paths/05-ticket/22_advance.spec.js @@ -4,6 +4,7 @@ import getBrowser from '../../helpers/puppeteer'; describe('Ticket Advance path', () => { let browser; let page; + const httpRequests = []; beforeAll(async() => { browser = await getBrowser(); @@ -47,53 +48,70 @@ 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 destination IPT', async() => { + await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); + await page.autocompleteSearch(selectors.ticketAdvance.ipt, 'Horizontal'); + await page.waitToClick(selectors.ticketAdvance.submit); + + 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.clearInput(selectors.ticketAdvance.ipt); + await page.waitToClick(selectors.ticketAdvance.submit); }); 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(('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 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(('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 check the one ticket and move to the present', async() => { diff --git a/modules/ticket/front/advance/index.html b/modules/ticket/front/advance/index.html index c700a1cc3..48023955e 100644 --- a/modules/ticket/front/advance/index.html +++ b/modules/ticket/front/advance/index.html @@ -100,13 +100,6 @@ vn-click-stop> - - - - + {{::ticket.futureLiters | dashIfEmpty}} + {{::ticket.hasStock | dashIfEmpty}} + {{::ticket.futureLines | dashIfEmpty}} Date: Fri, 10 Feb 2023 12:09:51 +0100 Subject: [PATCH 07/14] fix: actulizada sql intrastat y se muestra solamente cuando toca --- db/changes/230402/00-invoiceOut_getWeight.sql | 30 ++++++++++ print/templates/reports/invoice/invoice.html | 2 +- print/templates/reports/invoice/invoice.js | 3 +- .../reports/invoice/sql/hasIntrastat.sql | 4 ++ .../reports/invoice/sql/intrastat.sql | 60 +++++++++++-------- 5 files changed, 72 insertions(+), 27 deletions(-) create mode 100644 db/changes/230402/00-invoiceOut_getWeight.sql create mode 100644 print/templates/reports/invoice/sql/hasIntrastat.sql 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/print/templates/reports/invoice/invoice.html b/print/templates/reports/invoice/invoice.html index 60d06d528..ffa03af45 100644 --- a/print/templates/reports/invoice/invoice.html +++ b/print/templates/reports/invoice/invoice.html @@ -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; From 76ed4d2d4bcb0248249a7215e08d20b46a216530 Mon Sep 17 00:00:00 2001 From: alexandre Date: Mon, 13 Feb 2023 10:16:28 +0100 Subject: [PATCH 08/14] refs #5194 fixed tests --- db/changes/230402/00-ticket_canAdvance.sql | 127 ++++++++++++++++++ db/changes/230601/00-ticket_canAdvance.sql | 114 ---------------- e2e/helpers/selectors.js | 6 +- e2e/paths/05-ticket/22_advance.spec.js | 8 +- .../back/methods/ticket/getTicketsAdvance.js | 6 +- .../ticket/specs/getTicketsAdvance.spec.js | 4 +- .../front/advance-search-panel/index.html | 2 +- modules/ticket/front/advance/index.html | 6 +- modules/ticket/front/advance/index.js | 4 +- modules/ticket/front/advance/locale/es.yml | 1 + 10 files changed, 145 insertions(+), 133 deletions(-) create mode 100644 db/changes/230402/00-ticket_canAdvance.sql delete mode 100644 db/changes/230601/00-ticket_canAdvance.sql diff --git a/db/changes/230402/00-ticket_canAdvance.sql b/db/changes/230402/00-ticket_canAdvance.sql new file mode 100644 index 000000000..d7386e9d1 --- /dev/null +++ b/db/changes/230402/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/230601/00-ticket_canAdvance.sql b/db/changes/230601/00-ticket_canAdvance.sql deleted file mode 100644 index 68942a286..000000000 --- a/db/changes/230601/00-ticket_canAdvance.sql +++ /dev/null @@ -1,114 +0,0 @@ -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 vn.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 vn.itemTicketOut - WHERE shipped >= vDateInventory - AND shipped < vDateFuture - AND warehouseFk = vWarehouseFk - UNION ALL - SELECT itemFk, quantity - FROM vn.itemEntryIn - WHERE landed >= vDateInventory - AND landed < vDateFuture - AND isVirtualStock = FALSE - AND warehouseInFk = vWarehouseFk - UNION ALL - SELECT itemFk, quantity - FROM vn.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 - *, - CASE WHEN sub.futureLines = hasStock THEN '1' ELSE '0' END AS fullMovable - FROM (SELECT s.ticketFk futureId, - t2.ticketFk id, - count(DISTINCT s.id) saleCount, - t2.state, - st.name futureState, - GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) futureIpt, - t2.ipt, - t.workerFk, - CAST(SUM(litros) AS DECIMAL(10,0)) futureLiters, - CAST(COUNT(*) AS DECIMAL(10,0)) `futureLines`, - t2.shipped, - t.shipped futureShipped, - t2.totalWithVat, - t.totalWithVat futureTotalWithVat, - t2.agency, - am.name futureAgency, - t2.lines, - t2.liters, - SUM((s.quantity <= IFNULL(st.amount,0))) AS hasStock - FROM vn.ticket t - JOIN vn.sale s ON s.ticketFk = t.id - JOIN vn.saleVolume sv ON sv.saleFk = s.id - JOIN vn.item i ON i.id = s.itemFk - JOIN vn.ticketState ts ON ts.ticketFk = t.id - JOIN vn.state st ON st.id = ts.stateFk - JOIN vn.agencyMode am ON t.agencyModeFk = am.id - LEFT JOIN vn.itemPackingType ipt ON ipt.code = i.itemPackingTypeFk - LEFT JOIN tmp.stock st ON st.itemFk = i.id - JOIN (SELECT - t2.id ticketFk, - t2.addressFk, - st.name state, - GROUP_CONCAT(DISTINCT ipt.code ORDER BY ipt.code) ipt, - t2.shipped, - t2.totalWithVat, - am.name agency, - CAST(SUM(litros) AS DECIMAL(10,0)) liters, - CAST(COUNT(*) AS DECIMAL(10,0)) `lines` - FROM vn.ticket t2 - JOIN vn.sale s ON s.ticketFk = t2.id - JOIN vn.saleVolume sv ON sv.saleFk = s.id - JOIN vn.item i ON i.id = s.itemFk - JOIN vn.ticketState ts ON ts.ticketFk = t2.id - JOIN vn.state st ON st.id = ts.stateFk - JOIN vn.agencyMode am ON t2.agencyModeFk = am.id - LEFT JOIN vn.itemPackingType ipt ON ipt.code = i.itemPackingTypeFk - WHERE t2.shipped BETWEEN vDateToAdvance AND util.dayend(vDateToAdvance) - AND t2.warehouseFk = vWarehouseFk - AND st.order <= 5 - GROUP BY t2.id) t2 ON t2.addressFk = t.addressFk - WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture) - AND t.warehouseFk = vWarehouseFk - GROUP BY t.id - ) sub - WHERE hasStock != 0; - - DROP TEMPORARY TABLE tmp.stock; -END$$ -DELIMITER ; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 32f1de99f..e592bc123 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/22_advance.spec.js b/e2e/paths/05-ticket/22_advance.spec.js index 49ab5b0fc..c92cd7a20 100644 --- a/e2e/paths/05-ticket/22_advance.spec.js +++ b/e2e/paths/05-ticket/22_advance.spec.js @@ -88,7 +88,7 @@ describe('Ticket Advance path', () => { await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); await page.autocompleteSearch(selectors.ticketAdvance.tableFutureIpt, 'Vertical'); - const request = httpRequests.find(req => req.includes(('ipt'))); + const request = httpRequests.find(req => req.includes(('futureIpt'))); expect(request).toBeDefined(); @@ -103,7 +103,7 @@ describe('Ticket Advance path', () => { await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); await page.autocompleteSearch(selectors.ticketAdvance.tableIpt, 'Vertical'); - const request = httpRequests.find(req => req.includes(('futureIpt'))); + const request = httpRequests.find(req => req.includes(('ipt'))); expect(request).toBeDefined(); @@ -114,8 +114,8 @@ describe('Ticket Advance path', () => { await page.waitToClick(selectors.ticketAdvance.submit); }); - 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/modules/ticket/back/methods/ticket/getTicketsAdvance.js b/modules/ticket/back/methods/ticket/getTicketsAdvance.js index 86911a477..ec9314db2 100644 --- a/modules/ticket/back/methods/ticket/getTicketsAdvance.js +++ b/modules/ticket/back/methods/ticket/getTicketsAdvance.js @@ -50,7 +50,7 @@ module.exports = Self => { required: false }, { - arg: 'fullMovable', + arg: 'isFullMovable', type: 'boolean', description: 'True when lines and stock of origin are equal', required: false @@ -99,8 +99,8 @@ module.exports = Self => { {'f.futureIpt': null} ] }; - case 'fullMovable': - return {'f.fullMovable': 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 1d1681b09..126f6b1af 100644 --- a/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js +++ b/modules/ticket/back/methods/ticket/specs/getTicketsAdvance.spec.js @@ -39,7 +39,7 @@ describe('ticket getTicketsAdvance()', () => { dateFuture: tomorrow, dateToAdvance: today, warehouseFk: 1, - fullMovable: true + isFullMovable: true }; const ctx = {req: {accessToken: {userId: 9}}, args}; @@ -64,7 +64,7 @@ describe('ticket getTicketsAdvance()', () => { dateFuture: tomorrow, dateToAdvance: today, warehouseFk: 1, - fullMovable: false + isFullMovable: false }; const ctx = {req: {accessToken: {userId: 9}}, args}; diff --git a/modules/ticket/front/advance-search-panel/index.html b/modules/ticket/front/advance-search-panel/index.html index 233d00127..ee18c26f9 100644 --- a/modules/ticket/front/advance-search-panel/index.html +++ b/modules/ticket/front/advance-search-panel/index.html @@ -42,7 +42,7 @@ Liters - - +
- Stock + + Not Movable Lines @@ -155,7 +155,7 @@ {{::ticket.futureLiters | dashIfEmpty}}{{::ticket.hasStock | dashIfEmpty}}{{::ticket.notMovableLines | dashIfEmpty}} {{::ticket.futureLines | dashIfEmpty}} Date: Tue, 14 Feb 2023 12:41:36 +0100 Subject: [PATCH 09/14] refs #5223 changed ref and email text --- db/changes/230402/00-clienteCompensado.sql | 3 + .../back/methods/client/createReceipt.js | 23 ++------ .../client/getClientOrSupplierReference.js | 58 +++++++++++++++++++ modules/client/back/models/client-methods.js | 1 + .../client/front/balance/create/index.html | 24 ++++---- modules/client/front/balance/create/index.js | 33 +++++++++-- .../client/front/balance/create/locale/es.yml | 4 +- .../balance-compensation.html | 4 +- .../balance-compensation/locale/es.yml | 8 +-- .../balance-compensation/sql/client.sql | 1 + 10 files changed, 115 insertions(+), 44 deletions(-) create mode 100644 db/changes/230402/00-clienteCompensado.sql create mode 100644 modules/client/back/methods/client/getClientOrSupplierReference.js diff --git a/db/changes/230402/00-clienteCompensado.sql b/db/changes/230402/00-clienteCompensado.sql new file mode 100644 index 000000000..ff1982b93 --- /dev/null +++ b/db/changes/230402/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/modules/client/back/methods/client/createReceipt.js b/modules/client/back/methods/client/createReceipt.js index a75ee8844..b268aba35 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..afb427315 --- /dev/null +++ b/modules/client/back/methods/client/getClientOrSupplierReference.js @@ -0,0 +1,58 @@ +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', + http: {source: 'path'} + }, + returns: { + type: 'string', + root: true + }, + http: { + path: `/:bankAccount/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 ab97a7291..b22d15936 100644 --- a/modules/client/front/balance/create/index.js +++ b/modules/client/front/balance/create/index.js @@ -60,11 +60,15 @@ class Controller extends Dialog { const accountingType = value.accountingType; this.viewReceipt = accountingType.code == 'cash'; - if (accountingType.receiptDescription != null) { - this.receipt.description = accountingType.receiptDescription; - if (this.originalDescription) this.receipt.description += `, ${this.originalDescription}`; - } else if (this.originalDescription) - this.receipt.description = this.originalDescription; + if (accountingType.code == 'compensation') + this.receipt.description = ''; + else { + if (accountingType.receiptDescription != null) { + this.receipt.description = accountingType.receiptDescription; + if (this.originalDescription) this.receipt.description += `, ${this.originalDescription}`; + } else if (this.originalDescription) + this.receipt.description = this.originalDescription; + } this.maxAmount = accountingType && accountingType.maxAmount; this.receipt.payed = new Date(); @@ -110,7 +114,24 @@ 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)); + this.$http.get(`Clients/${this.receipt.compensationAccount}/getClientOrSupplierReference`) + .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/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 From e68afa316925d34e17e0e04f220604343a33638d Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 15 Feb 2023 12:59:19 +0100 Subject: [PATCH 10/14] refs #5223 moved sql --- db/changes/{230402 => 230403}/00-clienteCompensado.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/changes/{230402 => 230403}/00-clienteCompensado.sql (100%) diff --git a/db/changes/230402/00-clienteCompensado.sql b/db/changes/230403/00-clienteCompensado.sql similarity index 100% rename from db/changes/230402/00-clienteCompensado.sql rename to db/changes/230403/00-clienteCompensado.sql From dca5ae0f72e61720d491515ccf3f3e80894ded78 Mon Sep 17 00:00:00 2001 From: alexandre Date: Wed, 15 Feb 2023 13:14:52 +0100 Subject: [PATCH 11/14] refs #5223 added params --- .../back/methods/client/getClientOrSupplierReference.js | 5 ++--- modules/client/front/balance/create/index.js | 3 ++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/client/back/methods/client/getClientOrSupplierReference.js b/modules/client/back/methods/client/getClientOrSupplierReference.js index afb427315..4c7201ee3 100644 --- a/modules/client/back/methods/client/getClientOrSupplierReference.js +++ b/modules/client/back/methods/client/getClientOrSupplierReference.js @@ -8,15 +8,14 @@ module.exports = Self => { arg: 'bankAccount', type: 'number', required: true, - description: 'The bank account of a client or a supplier', - http: {source: 'path'} + description: 'The bank account of a client or a supplier' }, returns: { type: 'string', root: true }, http: { - path: `/:bankAccount/getClientOrSupplierReference`, + path: `/getClientOrSupplierReference`, verb: 'GET' } }); diff --git a/modules/client/front/balance/create/index.js b/modules/client/front/balance/create/index.js index b22d15936..6d6e99e29 100644 --- a/modules/client/front/balance/create/index.js +++ b/modules/client/front/balance/create/index.js @@ -116,7 +116,8 @@ class Controller extends Dialog { accountShortToStandard(value) { if (value) { this.receipt.compensationAccount = value.replace('.', '0'.repeat(11 - value.length)); - this.$http.get(`Clients/${this.receipt.compensationAccount}/getClientOrSupplierReference`) + 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', { From 457fd3f5f914005ad359cafcbf0c114f7d665b0e Mon Sep 17 00:00:00 2001 From: alexandre Date: Thu, 16 Feb 2023 14:35:03 +0100 Subject: [PATCH 12/14] refs #5194 sql moved to 230404 --- db/changes/{230402 => 230404}/00-ticket_canAdvance.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/changes/{230402 => 230404}/00-ticket_canAdvance.sql (100%) diff --git a/db/changes/230402/00-ticket_canAdvance.sql b/db/changes/230404/00-ticket_canAdvance.sql similarity index 100% rename from db/changes/230402/00-ticket_canAdvance.sql rename to db/changes/230404/00-ticket_canAdvance.sql From 4cae4448f6004cc398a1bafb655c32a040a67259 Mon Sep 17 00:00:00 2001 From: alexandre Date: Thu, 16 Feb 2023 14:45:11 +0100 Subject: [PATCH 13/14] refs #5194 moved invoiceOut to 230402 --- db/changes/{230404 => 230402}/00-invoiceOut_getWeight.sql | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename db/changes/{230404 => 230402}/00-invoiceOut_getWeight.sql (100%) diff --git a/db/changes/230404/00-invoiceOut_getWeight.sql b/db/changes/230402/00-invoiceOut_getWeight.sql similarity index 100% rename from db/changes/230404/00-invoiceOut_getWeight.sql rename to db/changes/230402/00-invoiceOut_getWeight.sql From 853e06f5236ebfd2ebee3f986bf5ce42e1165285 Mon Sep 17 00:00:00 2001 From: vicent Date: Fri, 17 Feb 2023 12:38:07 +0100 Subject: [PATCH 14/14] fix: card reload automatic --- modules/item/front/tags/index.js | 1 + 1 file changed, 1 insertion(+) 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(); }); } }