diff --git a/CHANGELOG.md b/CHANGELOG.md index 725ce31a2..bf8cfd17c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,19 +9,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - (Rutas) Al descargar varias facturas se comprime en un zip -- (Trabajadores -> Nuevo trabajador) Nueva sección +- (Trabajadores -> Nuevo trabajador) Nueva sección +- (Tickets -> Adelantar tickets) Añadidos campos "líneas" y "litros" al ticket origen +- (Tickets -> Adelantar tickets) Nuevo icono muestra cuando las agencias de los tickets origen/destino son distintas ### Changed - (Entradas -> Compras) Cambiados los campos "Precio Grouping/Packing" por "PVP" y "Precio" por "Coste" - (Artículos -> Últimas entradas) Cambiados los campos "P.P.U." y "P.P.P." por "PVP" - (Rutas -> Sumario/Tickets) Actualizados campos de los tickets - (Proveedores -> Crear/Editar) Permite añadir Proveedores con la misma razón social pero con países distintos +- (Tickets -> Adelantar tickets) Cambiados selectores de estado por checks "Pendiente origen/destino" +- (Tickets -> Adelantar tickets) Cambiado stock de destino a origen. ### Fixed - (Artículos -> Etiquetas) Permite intercambiar la relevancia entre dos etiquetas. - (Cliente -> Datos Fiscales) No se permite seleccionar 'Notificar vía e-mail' a los clientes sin e-mail - (Tickets -> Datos básicos) Permite guardar la hora de envío - (Tickets -> Añadir pago) Eliminado "null" en las referencias +- (Tickets -> Adelantar tickets) Permite ordenar por importe +- (Tickets -> Adelantar tickets) El filtrado por encajado muestra también los tickets sin tipo de encajado ## [2302.01] - 2023-01-26 diff --git a/db/changes/230401/00-ticket_canAdvance.sql b/db/changes/230401/00-ticket_canAdvance.sql new file mode 100644 index 000000000..fd9d451bf --- /dev/null +++ b/db/changes/230401/00-ticket_canAdvance.sql @@ -0,0 +1,110 @@ +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 s.ticketFk futureId, + t2.ticketFk id, + count(DISTINCT s.id) saleCount, + t2.state, + t2.isNotValidated, + st.name futureState, + st.isNotValidated futureIsNotValidated, + 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))) hasStock + FROM vn.ticket t + JOIN vn.ticketState ts ON ts.ticketFk = t.id + JOIN vn.state st ON st.id = ts.stateFk + JOIN vn.saleVolume sv ON t.id = sv.ticketFk + JOIN (SELECT + t2.id ticketFk, + t2.addressFk, + st.isNotValidated, + 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.saleVolume sv ON t2.id = sv.ticketFk + JOIN vn.sale s ON s.ticketFk = t2.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 + GROUP BY t2.id) t2 ON t2.addressFk = t.addressFk + JOIN vn.sale s ON s.ticketFk = t.id + JOIN vn.item i ON i.id = s.itemFk + 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 + WHERE t.shipped BETWEEN vDateFuture AND util.dayend(vDateFuture) + AND t.warehouseFk = vWarehouseFk + GROUP BY t.id; + + DROP TEMPORARY TABLE tmp.stock; +END$$ +DELIMITER ; diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 986c6547b..32f1de99f 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -778,8 +778,8 @@ 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"]', + futureState: 'vn-check[label="Pending Origin"]', + state: 'vn-check[label="Pending Destination"]', 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..3a6234fe9 100644 --- a/e2e/paths/05-ticket/22_advance.spec.js +++ b/e2e/paths/05-ticket/22_advance.spec.js @@ -50,7 +50,7 @@ describe('Ticket Advance path', () => { 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, 0); + await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.clearInput(selectors.ticketAdvance.ipt); @@ -62,7 +62,7 @@ describe('Ticket Advance path', () => { 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, 0); + await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); await page.clearInput(selectors.ticketAdvance.futureIpt); @@ -70,26 +70,36 @@ describe('Ticket Advance path', () => { await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); }); - it('should search with the origin grouped state', async() => { + it('should search with the origin pending state', async() => { await page.waitToClick(selectors.ticketAdvance.openAdvancedSearchButton); - await page.autocompleteSearch(selectors.ticketAdvance.futureState, 'Free'); + await page.waitToClick(selectors.ticketAdvance.futureState); 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.futureState); + 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.autocompleteSearch(selectors.ticketAdvance.state, 'Free'); + 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.clearInput(selectors.ticketAdvance.state); + 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); }); @@ -116,42 +126,7 @@ describe('Ticket Advance path', () => { await page.waitForNumberOfElements(selectors.ticketAdvance.table, 1); }); - it('should search in smart-table with stock', async() => { - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.write(selectors.ticketAdvance.tableStock, '5'); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 2); - - 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 especified Lines', async() => { - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.write(selectors.ticketAdvance.tableLines, '0'); - await page.keyboard.press('Enter'); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 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 especified Liters', async() => { - await page.waitToClick(selectors.ticketAdvance.tableButtonSearch); - await page.write(selectors.ticketAdvance.tableLiters, '0'); - await page.keyboard.press('Enter'); - await page.waitForNumberOfElements(selectors.ticketAdvance.table, 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 three last tickets and move to the future', async() => { + it('should check the one ticket and move to the present', async() => { await page.waitToClick(selectors.ticketAdvance.multiCheck); await page.waitToClick(selectors.ticketAdvance.moveButton); await page.waitToClick(selectors.ticketAdvance.acceptButton); diff --git a/modules/ticket/back/methods/ticket/getTicketsAdvance.js b/modules/ticket/back/methods/ticket/getTicketsAdvance.js index 19571bb51..1e1646cba 100644 --- a/modules/ticket/back/methods/ticket/getTicketsAdvance.js +++ b/modules/ticket/back/methods/ticket/getTicketsAdvance.js @@ -50,14 +50,14 @@ module.exports = Self => { required: false }, { - arg: 'state', - type: 'string', + arg: 'isNotValidated', + type: 'boolean', description: 'Origin state', required: false }, { - arg: 'futureState', - type: 'string', + arg: 'futureIsNotValidated', + type: 'boolean', description: 'Destination state', required: false }, @@ -92,13 +92,23 @@ 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 'isNotValidated': + return {'f.isNotValidated': value}; + case 'futureIsNotValidated': + return {'f.futureIsNotValidated': 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..7d3bc174d 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 grouped state', async() => { + it('should return the tickets matching the origin pending state', async() => { const tx = await models.Ticket.beginTransaction({}); try { @@ -39,7 +39,7 @@ describe('TicketFuture getTicketsAdvance()', () => { dateFuture: tomorrow, dateToAdvance: today, warehouseFk: 1, - state: 'OK' + futureIsNotValidated: 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 destination pending state', async() => { const tx = await models.Ticket.beginTransaction({}); try { @@ -64,13 +64,13 @@ describe('TicketFuture getTicketsAdvance()', () => { dateFuture: tomorrow, dateToAdvance: today, warehouseFk: 1, - futureState: 'FREE' + isNotValidated: true }; 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) { @@ -89,7 +89,7 @@ describe('TicketFuture getTicketsAdvance()', () => { dateFuture: tomorrow, dateToAdvance: today, warehouseFk: 1, - ipt: 'Vertical' + ipt: 'V' }; const ctx = {req: {accessToken: {userId: 9}}, args}; @@ -114,7 +114,7 @@ describe('TicketFuture getTicketsAdvance()', () => { dateFuture: tomorrow, dateToAdvance: today, warehouseFk: 1, - tfIpt: 'Vertical' + tfIpt: 'V' }; 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 e8d5dc60d..dfe1f6b08 100644 --- a/modules/ticket/front/advance-search-panel/index.html +++ b/modules/ticket/front/advance-search-panel/index.html @@ -39,26 +39,18 @@ - - - {{name}} - - - - - {{name}} - - + + + + { - for (let state of res.data) { - groupedStates.push({ - id: state.id, - code: state.code, - name: this.$t(state.code) - }); - } - this.groupedStates = groupedStates; - }); - } - getItemPackingTypes() { let itemPackingTypes = []; const filter = { diff --git a/modules/ticket/front/advance-search-panel/locale/es.yml b/modules/ticket/front/advance-search-panel/locale/es.yml index 3dce7dae5..4ea2fc737 100644 --- a/modules/ticket/front/advance-search-panel/locale/es.yml +++ b/modules/ticket/front/advance-search-panel/locale/es.yml @@ -1 +1,3 @@ Advance tickets: Adelantar tickets +Pending Origin: Pendiente origen +Pending Destination: Pendiente destino diff --git a/modules/ticket/front/advance/index.html b/modules/ticket/front/advance/index.html index f63c0fbf7..3dd52b909 100644 --- a/modules/ticket/front/advance/index.html +++ b/modules/ticket/front/advance/index.html @@ -32,8 +32,8 @@ - Origin - Destination + Origin + Destination @@ -43,19 +43,30 @@ check-field="checked"> + + ID Date - + IPT State - + + Liters + + + Stock + + + Lines + + Import @@ -64,7 +75,7 @@ Date - + IPT @@ -73,13 +84,10 @@ Liters - - Stock - Lines - + Import @@ -92,6 +100,13 @@ vn-click-stop> + + + + + {{::ticket.futureLiters | dashIfEmpty}} + {{::ticket.hasStock | dashIfEmpty}} + {{::ticket.futureLines | dashIfEmpty}} {{::(ticket.futureTotalWithVat ? ticket.futureTotalWithVat : 0) | currency: 'EUR': 2}} @@ -136,7 +154,6 @@ {{::ticket.liters | dashIfEmpty}} - {{::ticket.hasStock | dashIfEmpty}} {{::ticket.lines | dashIfEmpty}} diff --git a/modules/ticket/front/advance/index.js b/modules/ticket/front/advance/index.js index b770440f1..a29d2db97 100644 --- a/modules/ticket/front/advance/index.js +++ b/modules/ticket/front/advance/index.js @@ -1,5 +1,6 @@ import ngModule from '../module'; import Section from 'salix/components/section'; +import './style.scss'; export default class Controller extends Section { constructor($element, $) { @@ -128,6 +129,11 @@ export default class Controller extends Section { }); } + agencies(futureAgency, agency) { + return this.$t(`Origin agency`, {agency: futureAgency}) + + '
' + this.$t(`Destination agency`, {agency: agency}); + } + moveTicketsAdvance() { let ticketsToMove = []; this.checked.forEach(ticket => { @@ -157,6 +163,10 @@ export default class Controller extends Section { return {'liters': value}; case 'lines': return {'lines': value}; + case 'futureLiters': + return {'futureLiters': value}; + case 'futureLines': + return {'futureLines': value}; case 'ipt': return {'ipt': value}; case 'futureIpt': diff --git a/modules/ticket/front/advance/locale/es.yml b/modules/ticket/front/advance/locale/es.yml index b444fbdd3..da22cd433 100644 --- a/modules/ticket/front/advance/locale/es.yml +++ b/modules/ticket/front/advance/locale/es.yml @@ -4,3 +4,6 @@ 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}}" diff --git a/modules/ticket/front/advance/style.scss b/modules/ticket/front/advance/style.scss new file mode 100644 index 000000000..8fa9de438 --- /dev/null +++ b/modules/ticket/front/advance/style.scss @@ -0,0 +1,7 @@ +@import "variables"; + +vn-ticket-advance{ + vn-icon { + color: #f7931e + } +}