From fa5c1643a4d1716f246f22c7761e42d8c2cdbaa7 Mon Sep 17 00:00:00 2001 From: jtubau <jtubau@verdnatura.es> Date: Tue, 4 Mar 2025 12:32:21 +0100 Subject: [PATCH 01/65] test: refs #8717 add integration test for agencyModes --- .../integration/route/agency/agencyModes.spec.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 test/cypress/integration/route/agency/agencyModes.spec.js diff --git a/test/cypress/integration/route/agency/agencyModes.spec.js b/test/cypress/integration/route/agency/agencyModes.spec.js new file mode 100644 index 000000000..3f5784997 --- /dev/null +++ b/test/cypress/integration/route/agency/agencyModes.spec.js @@ -0,0 +1,15 @@ +describe('Agency modes', () => { + const name = 'inhouse pickup'; + + beforeEach(() => { + cy.viewport(1920, 1080); + cy.login('developer'); + cy.visit(`/#/route/agency/1/modes`); + }); + + it('should display the agency modes page', () => { + cy.get('.flex > .title').should('have.text', name); + cy.get('.flex > .q-chip > .q-chip__content').should('have.text', 'ID: 1'); + cy.get('.list-items > :nth-child(1) > .value').should('have.text', name); + }); +}); From 1a0df60e06878c3695a7011016ec705a3b19dbaa Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Fri, 14 Mar 2025 14:21:26 +0100 Subject: [PATCH 02/65] fix: remove reserved ticket functionality from TicketProblems and TicketSaleMoreActions components --- src/components/TicketProblems.vue | 11 ------ .../Ticket/Card/TicketSaleMoreActions.vue | 35 ------------------- 2 files changed, 46 deletions(-) diff --git a/src/components/TicketProblems.vue b/src/components/TicketProblems.vue index c11cc2e7b..aee132fe0 100644 --- a/src/components/TicketProblems.vue +++ b/src/components/TicketProblems.vue @@ -17,17 +17,6 @@ defineProps({ row: { type: Object, required: true } }); </QTooltip> </QIcon> </router-link> - <QIcon - v-if="row?.reserved" - color="primary" - name="vn:reserva" - size="xs" - data-cy="ticketSaleReservedIcon" - > - <QTooltip> - {{ t('ticketSale.reserved') }} - </QTooltip> - </QIcon> <QIcon v-if="row?.isDeleted" color="primary" diff --git a/src/pages/Ticket/Card/TicketSaleMoreActions.vue b/src/pages/Ticket/Card/TicketSaleMoreActions.vue index 840b62507..a1eaba53f 100644 --- a/src/pages/Ticket/Card/TicketSaleMoreActions.vue +++ b/src/pages/Ticket/Card/TicketSaleMoreActions.vue @@ -62,7 +62,6 @@ const isClaimable = computed(() => { } return false; }); -const hasReserves = computed(() => props.sales.some((sale) => sale.reserved == true)); const sendSms = async (params) => { await axios.post(`Tickets/${ticket.value.id}/sendSms`, params); @@ -144,14 +143,6 @@ const onCreateClaimAccepted = async () => { push({ name: 'ClaimBasicData', params: { id: data.id } }); }; -const setReserved = async (reserved) => { - const params = { ticketId: ticket.value.id, sales: props.sales, reserved: reserved }; - await axios.post(`Sales/reserve`, params); - props.sales.forEach((sale) => { - sale.reserved = reserved; - }); -}; - const createRefund = async (withWarehouse) => { if (!props.ticket) return; @@ -240,30 +231,6 @@ const createRefund = async (withWarehouse) => { <QItemLabel>{{ t('Add claim') }}</QItemLabel> </QItemSection> </QItem> - <QItem - v-if="isTicketEditable" - clickable - v-close-popup - v-ripple - @click="setReserved(true)" - data-cy="markAsReservedItem" - > - <QItemSection> - <QItemLabel>{{ t('Mark as reserved') }}</QItemLabel> - </QItemSection> - </QItem> - <QItem - v-if="isTicketEditable && hasReserves" - clickable - v-close-popup - v-ripple - @click="setReserved(false)" - data-cy="unmarkAsReservedItem" - > - <QItemSection> - <QItemLabel>{{ t('Unmark as reserved') }}</QItemLabel> - </QItemSection> - </QItem> <QItem clickable v-ripple data-cy="ticketSaleRefundItem"> <QItemSection> <QItemLabel>{{ t('Refund') }}</QItemLabel> @@ -309,8 +276,6 @@ es: Recalculate price: Recalcular precio Update discount: Actualizar descuento Add claim: Crear reclamación - Mark as reserved: Marcar como reservado - Unmark as reserved: Desmarcar como reservado Refund: Abono with warehouse: con almacén without warehouse: sin almacén From 5f48c9b887a799bf0ada9e7cc36ae6c86393ca9b Mon Sep 17 00:00:00 2001 From: jtubau <jtubau@verdnatura.es> Date: Mon, 24 Mar 2025 08:13:06 +0100 Subject: [PATCH 03/65] refactor: refs #8717 eliminate warnings and add component on children routes --- src/components/VnTable/VnColumn.vue | 14 ++++++++------ src/router/modules/route.js | 6 ++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/components/VnTable/VnColumn.vue b/src/components/VnTable/VnColumn.vue index d0e245388..3ce62c5de 100644 --- a/src/components/VnTable/VnColumn.vue +++ b/src/components/VnTable/VnColumn.vue @@ -55,6 +55,8 @@ const $props = defineProps({ }, }); +const label = $props.showLabel && $props.column.label ? $props.column.label : ''; + const defaultSelect = { attrs: { row: $props.row, @@ -62,7 +64,7 @@ const defaultSelect = { class: 'fit', }, forceAttrs: { - label: $props.showLabel && $props.column.label, + label, }, }; @@ -74,7 +76,7 @@ const defaultComponents = { class: 'fit', }, forceAttrs: { - label: $props.showLabel && $props.column.label, + label, }, }, number: { @@ -84,7 +86,7 @@ const defaultComponents = { class: 'fit', }, forceAttrs: { - label: $props.showLabel && $props.column.label, + label, }, }, date: { @@ -96,7 +98,7 @@ const defaultComponents = { class: 'fit', }, forceAttrs: { - label: $props.showLabel && $props.column.label, + label, }, }, time: { @@ -105,7 +107,7 @@ const defaultComponents = { disable: !$props.isEditable, }, forceAttrs: { - label: $props.showLabel && $props.column.label, + label, }, }, checkbox: { @@ -125,7 +127,7 @@ const defaultComponents = { return defaultAttrs; }, forceAttrs: { - label: $props.showLabel && $props.column.label, + label, autofocus: true, }, events: { diff --git a/src/router/modules/route.js b/src/router/modules/route.js index 62765a49c..0bf3a6eff 100644 --- a/src/router/modules/route.js +++ b/src/router/modules/route.js @@ -229,6 +229,7 @@ export default { title: 'list', icon: 'view_list', }, + component: () => import('src/pages/Route/RouteList.vue'), }, routeCard, ], @@ -277,6 +278,7 @@ export default { title: 'list', icon: 'view_list', }, + component: () => import('src/pages/Route/RouteRoadmap.vue'), }, roadmapCard, ], @@ -307,6 +309,8 @@ export default { title: 'list', icon: 'view_list', }, + component: () => + import('src/pages/Route/Agency/AgencyList.vue'), }, agencyCard, ], @@ -328,6 +332,8 @@ export default { title: 'vehicleList', icon: 'directions_car', }, + component: () => + import('src/pages/Route/Vehicle/VehicleList.vue'), }, vehicleCard, ], From 26f20440972b8fd42d032e49c580c58bc8b3edb0 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Mon, 24 Mar 2025 09:08:18 +0100 Subject: [PATCH 04/65] test: update order creation test and remove reserved ticket tests --- test/cypress/integration/order/orderList.spec.js | 2 +- .../integration/ticket/ticketSale.spec.js | 16 ---------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/test/cypress/integration/order/orderList.spec.js b/test/cypress/integration/order/orderList.spec.js index 1c954622f..024517bbf 100644 --- a/test/cypress/integration/order/orderList.spec.js +++ b/test/cypress/integration/order/orderList.spec.js @@ -6,7 +6,7 @@ describe('OrderList', () => { cy.visit('/#/order/list'); }); - it('create order', () => { + it.only('create order', () => { cy.get('[data-cy="vnTableCreateBtn"]').click(); cy.get('[data-cy="Client_select"]').type('1101'); cy.get('.q-menu').contains('Bruce Wayne').click(); diff --git a/test/cypress/integration/ticket/ticketSale.spec.js b/test/cypress/integration/ticket/ticketSale.spec.js index 61ba9fe4f..514c50281 100644 --- a/test/cypress/integration/ticket/ticketSale.spec.js +++ b/test/cypress/integration/ticket/ticketSale.spec.js @@ -152,22 +152,6 @@ describe('TicketSale', () => { cy.checkNotification('Future ticket date not allowed'); }); - it('marks row as reserved', () => { - selectFirstRow(); - cy.dataCy('ticketSaleMoreActionsDropdown').click(); - cy.waitForElement('[data-cy="markAsReservedItem"]'); - cy.dataCy('markAsReservedItem').click(); - cy.dataCy('ticketSaleReservedIcon').should('exist'); - }); - - it('unmarks row as reserved', () => { - selectFirstRow(); - cy.dataCy('ticketSaleMoreActionsDropdown').click(); - cy.waitForElement('[data-cy="unmarkAsReservedItem"]'); - cy.dataCy('unmarkAsReservedItem').click(); - cy.dataCy('ticketSaleReservedIcon').should('not.exist'); - }); - it('refunds row with warehouse', () => { selectFirstRow(); cy.dataCy('ticketSaleMoreActionsDropdown').click(); From 17b784e4d107711f329a84324be5706b406b0d11 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Mon, 24 Mar 2025 09:46:10 +0100 Subject: [PATCH 05/65] test: rename account descriptor test and enable claim notes test --- .../integration/account/accountDescriptorMenu.spec.js | 5 ++++- test/cypress/integration/claim/claimNotes.spec.js | 2 +- test/cypress/integration/ticket/ticketSale.spec.js | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/cypress/integration/account/accountDescriptorMenu.spec.js b/test/cypress/integration/account/accountDescriptorMenu.spec.js index 67a7d8ef6..04fc57040 100644 --- a/test/cypress/integration/account/accountDescriptorMenu.spec.js +++ b/test/cypress/integration/account/accountDescriptorMenu.spec.js @@ -1,4 +1,4 @@ -describe('ClaimNotes', () => { +describe('Account descriptor', () => { const descriptorOptions = '[data-cy="descriptor-more-opts-menu"] > .q-list'; const url = '/#/account/1/summary'; @@ -7,6 +7,9 @@ describe('ClaimNotes', () => { cy.visit(url); cy.dataCy('descriptor-more-opts').click(); cy.get(descriptorOptions) + .should('exist') + .should('be.visible') + .find('.q-item') .its('length') .then((count) => { diff --git a/test/cypress/integration/claim/claimNotes.spec.js b/test/cypress/integration/claim/claimNotes.spec.js index ae8b4186c..fa4a214a1 100644 --- a/test/cypress/integration/claim/claimNotes.spec.js +++ b/test/cypress/integration/claim/claimNotes.spec.js @@ -1,4 +1,4 @@ -describe.skip('ClaimNotes', () => { +describe('ClaimNotes', () => { const saveBtn = '.q-field__append > .q-btn > .q-btn__content > .q-icon'; const firstNote = '.q-infinite-scroll :nth-child(1) > .q-card__section--vert'; beforeEach(() => { diff --git a/test/cypress/integration/ticket/ticketSale.spec.js b/test/cypress/integration/ticket/ticketSale.spec.js index 514c50281..6d84f214c 100644 --- a/test/cypress/integration/ticket/ticketSale.spec.js +++ b/test/cypress/integration/ticket/ticketSale.spec.js @@ -23,7 +23,7 @@ describe('TicketSale', () => { cy.get('[data-col-field="price"]') .find('.q-btn > .q-btn__content') - .should('have.text', `€${price}`); + .should('contain.text', `€${price}`); }); it('update discount', () => { const discount = Math.floor(Math.random() * 100) + 1; From fb00824ee38a257669f297b7a9bafdfe0b628ddd Mon Sep 17 00:00:00 2001 From: jtubau <jtubau@verdnatura.es> Date: Mon, 24 Mar 2025 09:55:03 +0100 Subject: [PATCH 06/65] refactor: refs #8717 change toModule prop type from String to Object --- src/components/ui/VnDescriptor.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ui/VnDescriptor.vue b/src/components/ui/VnDescriptor.vue index 47da98d74..878adcadc 100644 --- a/src/components/ui/VnDescriptor.vue +++ b/src/components/ui/VnDescriptor.vue @@ -30,7 +30,7 @@ const $props = defineProps({ default: null, }, toModule: { - type: String, + type: Object, default: null, }, }); From feabf9c7be8793f881fd0b7abba8426ce0fe62dd Mon Sep 17 00:00:00 2001 From: jtubau <jtubau@verdnatura.es> Date: Mon, 24 Mar 2025 11:19:26 +0100 Subject: [PATCH 07/65] refactor: refs #8717 use markRaw for cardDescriptor in VnCard component --- src/components/common/VnCard.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/common/VnCard.vue b/src/components/common/VnCard.vue index 21cdc9df5..50b041060 100644 --- a/src/components/common/VnCard.vue +++ b/src/components/common/VnCard.vue @@ -1,5 +1,5 @@ <script setup> -import { onBeforeMount, computed } from 'vue'; +import { onBeforeMount, computed, markRaw } from 'vue'; import { useRoute, useRouter, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router'; import { useArrayData } from 'src/composables/useArrayData'; import { useStateStore } from 'stores/useStateStore'; @@ -37,7 +37,7 @@ onBeforeRouteLeave(() => { }); onBeforeMount(async () => { - stateStore.cardDescriptorChangeValue(props.descriptor); + stateStore.cardDescriptorChangeValue(markRaw(props.descriptor)); const route = router.currentRoute.value; try { From 9a2c7c8012b586803437c4ed3e3654c56556ee19 Mon Sep 17 00:00:00 2001 From: jtubau <jtubau@verdnatura.es> Date: Tue, 25 Mar 2025 14:02:13 +0100 Subject: [PATCH 08/65] fix: refs #8717 streamline field filling logic in tests --- .../integration/route/routeExtendedList.spec.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/test/cypress/integration/route/routeExtendedList.spec.js b/test/cypress/integration/route/routeExtendedList.spec.js index a183c08cb..fce4753f1 100644 --- a/test/cypress/integration/route/routeExtendedList.spec.js +++ b/test/cypress/integration/route/routeExtendedList.spec.js @@ -53,17 +53,20 @@ describe('Route extended list', () => { function fillField(selector, type, value) { switch (type) { case 'select': - cy.get(selector).should('be.visible').click(); - cy.dataCy('null_select').clear().type(value); + cy.get(selector).should('be.visible').click().clear().type(value); cy.get('.q-item').contains(value).click(); break; case 'input': - cy.get(selector).should('be.visible').click(); - cy.dataCy('null_input').clear().type(`${value}`); + cy.get(selector) + .should('be.visible') + .click() + .type(`{selectall}{backspace}${value}`); break; case 'date': - cy.get(selector).should('be.visible').click(); - cy.dataCy('null_inputDate').clear().type(`${value}`); + cy.get(selector) + .should('be.visible') + .click() + .type(`{selectall}{backspace}${value}`); break; case 'checkbox': cy.get(selector).should('be.visible').click().click(); @@ -177,7 +180,7 @@ describe('Route extended list', () => { const [month, day, year] = value.split('/'); value = `${day}/${month}/${year}`; } - cy.validateContent(selector, value); + cy.get(selector).should('contain', value); }); }); From c5a05917c0a990d71470d5e33bce6c74424d0087 Mon Sep 17 00:00:00 2001 From: jtubau <jtubau@verdnatura.es> Date: Wed, 26 Mar 2025 08:50:25 +0100 Subject: [PATCH 09/65] fix: refs #8717 enable RouteAutonomous tests and adjust notification check in RouteExtendedList --- test/cypress/integration/route/routeAutonomous.spec.js | 4 ++-- test/cypress/integration/route/routeExtendedList.spec.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/cypress/integration/route/routeAutonomous.spec.js b/test/cypress/integration/route/routeAutonomous.spec.js index 08fd7d7ea..72562259a 100644 --- a/test/cypress/integration/route/routeAutonomous.spec.js +++ b/test/cypress/integration/route/routeAutonomous.spec.js @@ -1,4 +1,4 @@ -describe.skip('RouteAutonomous', () => { +describe('RouteAutonomous', () => { const getLinkSelector = (colField) => `tr:first-child > [data-col-field="${colField}"] > .no-padding > .link`; @@ -49,12 +49,12 @@ describe.skip('RouteAutonomous', () => { cy.get(selectors.firstRowCheckbox).click(); cy.get(selectors.createInvoiceBtn).click(); cy.dataCy(selectors.reference).type(data.reference); + cy.dataCy('attachFile').click(); cy.get('.q-file').selectFile('test/cypress/fixtures/image.jpg', { force: true, }); cy.dataCy(selectors.saveFormBtn).click(); cy.checkNotification(dataSaved); - cy.typeSearchbar('{enter}'); }); it('Should display the total price of the selected rows', () => { diff --git a/test/cypress/integration/route/routeExtendedList.spec.js b/test/cypress/integration/route/routeExtendedList.spec.js index fce4753f1..e6c873d5e 100644 --- a/test/cypress/integration/route/routeExtendedList.spec.js +++ b/test/cypress/integration/route/routeExtendedList.spec.js @@ -106,8 +106,8 @@ describe('Route extended list', () => { cy.fillInForm(data); cy.dataCy(selectors.saveFormBtn).click(); - cy.checkNotification(dataCreated); cy.url().should('include', '/summary'); + cy.checkNotification(dataCreated); }); it('Should reset changed values when click reset button', () => { @@ -143,7 +143,7 @@ describe('Route extended list', () => { const downloadsFolder = Cypress.config('downloadsFolder'); cy.get(selectors.lastRowSelectCheckBox).click(); cy.get(selectors.downloadBtn).click(); - cy.wait(5000); + cy.wait(3000); const fileName = 'download.zip'; cy.readFile(`${downloadsFolder}/${fileName}`).should('exist'); From 3783cdeed4313fe907d48842d90841f89c8348bd Mon Sep 17 00:00:00 2001 From: Jon <jon@verdnatura.es> Date: Wed, 26 Mar 2025 12:03:46 +0100 Subject: [PATCH 10/65] fix: fixed buttons disabled when there are no changes --- src/pages/Customer/components/CustomerAddressEdit.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Customer/components/CustomerAddressEdit.vue b/src/pages/Customer/components/CustomerAddressEdit.vue index f852c160a..88abcaa77 100644 --- a/src/pages/Customer/components/CustomerAddressEdit.vue +++ b/src/pages/Customer/components/CustomerAddressEdit.vue @@ -180,7 +180,7 @@ function handleLocation(data, location) { <FetchData @on-fetch="getData" auto-load url="ObservationTypes" /> <FormModel - :observe-form-changes="false" + observe-form-changes :url-update="urlUpdate" :url="`Addresses/${route.params.addressId}`" :save-fn="handleDialog" From ae9cc49addbf7617e33ff8fd664e8b9c67e0bb48 Mon Sep 17 00:00:00 2001 From: Jon <jon@verdnatura.es> Date: Wed, 26 Mar 2025 12:32:22 +0100 Subject: [PATCH 11/65] refactor: manage every nullable option --- .../Customer/components/CustomerAddressEdit.vue | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/pages/Customer/components/CustomerAddressEdit.vue b/src/pages/Customer/components/CustomerAddressEdit.vue index 88abcaa77..1f7b4c1e8 100644 --- a/src/pages/Customer/components/CustomerAddressEdit.vue +++ b/src/pages/Customer/components/CustomerAddressEdit.vue @@ -93,10 +93,20 @@ const updateAddressTicket = async () => { }; const updateObservations = async (payload) => { + if (isPayloadEmpty(payload)) return; await axios.post('AddressObservations/crud', payload); notes.value = []; deletes.value = []; }; + +function isPayloadEmpty(payload) { + return ['creates', 'deletes', 'updates'].every( + (prop) => + !payload[prop] || + payload[prop].length === 0 || + payload[prop].every((item) => item === undefined || item === null), + ); +} async function updateAll({ data, payload }) { await updateObservations(payload); await updateAddress(data); @@ -180,7 +190,7 @@ function handleLocation(data, location) { <FetchData @on-fetch="getData" auto-load url="ObservationTypes" /> <FormModel - observe-form-changes + :observe-form-changes="false" :url-update="urlUpdate" :url="`Addresses/${route.params.addressId}`" :save-fn="handleDialog" From a3b109595205b0bfc556ac8c5b1621c1e966ad79 Mon Sep 17 00:00:00 2001 From: Jon <jon@verdnatura.es> Date: Wed, 26 Mar 2025 13:51:03 +0100 Subject: [PATCH 12/65] refactor: clean payload --- .../components/CustomerAddressEdit.vue | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/pages/Customer/components/CustomerAddressEdit.vue b/src/pages/Customer/components/CustomerAddressEdit.vue index 1f7b4c1e8..c89e7e2e9 100644 --- a/src/pages/Customer/components/CustomerAddressEdit.vue +++ b/src/pages/Customer/components/CustomerAddressEdit.vue @@ -93,20 +93,28 @@ const updateAddressTicket = async () => { }; const updateObservations = async (payload) => { - if (isPayloadEmpty(payload)) return; + cleanPayload(payload); await axios.post('AddressObservations/crud', payload); notes.value = []; deletes.value = []; }; -function isPayloadEmpty(payload) { - return ['creates', 'deletes', 'updates'].every( - (prop) => - !payload[prop] || - payload[prop].length === 0 || - payload[prop].every((item) => item === undefined || item === null), - ); +function cleanPayload(payload) { + ['creates', 'deletes', 'updates'].forEach((prop) => { + if (prop === 'creates' || prop === 'updates') { + payload[prop] = payload[prop].filter( + (item) => item.description !== '' && item.observationTypeFk !== '', + ); + } + if (prop === 'deletes') { + payload[prop] = payload[prop].filter( + (item) => item !== null && item !== undefined, + ); + } + return payload[prop]; + }); } + async function updateAll({ data, payload }) { await updateObservations(payload); await updateAddress(data); From e353f7916af14d781fc5eb23bead0a231bba20e9 Mon Sep 17 00:00:00 2001 From: Jon <jon@verdnatura.es> Date: Wed, 26 Mar 2025 14:15:01 +0100 Subject: [PATCH 13/65] perf: clean payload --- src/pages/Customer/components/CustomerAddressEdit.vue | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/Customer/components/CustomerAddressEdit.vue b/src/pages/Customer/components/CustomerAddressEdit.vue index c89e7e2e9..31a930341 100644 --- a/src/pages/Customer/components/CustomerAddressEdit.vue +++ b/src/pages/Customer/components/CustomerAddressEdit.vue @@ -105,8 +105,7 @@ function cleanPayload(payload) { payload[prop] = payload[prop].filter( (item) => item.description !== '' && item.observationTypeFk !== '', ); - } - if (prop === 'deletes') { + } else { payload[prop] = payload[prop].filter( (item) => item !== null && item !== undefined, ); From dd4e872fcca53e22418a9dbf7b3bbec2daea65d7 Mon Sep 17 00:00:00 2001 From: jorgep <jorgep@verdnatura.es> Date: Wed, 26 Mar 2025 16:00:50 +0100 Subject: [PATCH 14/65] refactor: refs #8718 simplify VnAccountNumber component and remove obsolete tests --- src/components/common/VnAccountNumber.vue | 25 +------------ .../vnComponent/VnAccountNumber.spec.js | 37 ------------------- 2 files changed, 2 insertions(+), 60 deletions(-) delete mode 100644 test/cypress/integration/vnComponent/VnAccountNumber.spec.js diff --git a/src/components/common/VnAccountNumber.vue b/src/components/common/VnAccountNumber.vue index 56add7329..8bff3e261 100644 --- a/src/components/common/VnAccountNumber.vue +++ b/src/components/common/VnAccountNumber.vue @@ -1,35 +1,14 @@ <script setup> -import { nextTick, ref } from 'vue'; import VnInput from './VnInput.vue'; import { useAccountShortToStandard } from 'src/composables/useAccountShortToStandard'; -const $props = defineProps({ - insertable: { - type: Boolean, - default: false, - }, -}); - -const emit = defineEmits(['update:modelValue', 'accountShortToStandard']); const model = defineModel({ prop: 'modelValue' }); -const inputRef = ref(false); - -function setCursorPosition(pos) { - const input = inputRef.value.vnInputRef.$el.querySelector('input'); - input.focus(); - input.setSelectionRange(pos, pos); -} - -async function handleUpdateModel(val) { - model.value = val?.at(-1) === '.' ? useAccountShortToStandard(val) : val; - await nextTick(() => setCursorPosition(0)); -} </script> <template> <VnInput v-model="model" ref="inputRef" - :insertable - @update:model-value="handleUpdateModel" + @keydown.tab="model = useAccountShortToStandard($event.target.value) ?? model" + @input="model = $event.target.value.replace(/[^\d.]/g, '')" /> </template> diff --git a/test/cypress/integration/vnComponent/VnAccountNumber.spec.js b/test/cypress/integration/vnComponent/VnAccountNumber.spec.js deleted file mode 100644 index 053902f35..000000000 --- a/test/cypress/integration/vnComponent/VnAccountNumber.spec.js +++ /dev/null @@ -1,37 +0,0 @@ -describe('VnAccountNumber', () => { - const accountInput = 'input[data-cy="supplierFiscalDataAccount_input"]'; - beforeEach(() => { - cy.login('developer'); - cy.viewport(1920, 1080); - cy.visit('/#/supplier/1/fiscal-data'); - }); - - describe('VnInput handleInsertMode()', () => { - it('should replace character at cursor position in insert mode', () => { - cy.get(accountInput).type('{selectall}4100000001'); - cy.get(accountInput).type('{movetostart}'); - cy.get(accountInput).type('999'); - cy.get(accountInput).should('have.value', '9990000001'); - }); - - it('should replace character at cursor position in insert mode', () => { - cy.get(accountInput).clear(); - cy.get(accountInput).type('4100000001'); - cy.get(accountInput).type('{movetostart}'); - cy.get(accountInput).type('999'); - cy.get(accountInput).should('have.value', '9990000001'); - }); - - it('should respect maxlength prop', () => { - cy.get(accountInput).clear(); - cy.get(accountInput).type('123456789012345'); - cy.get(accountInput).should('have.value', '1234567890'); - }); - }); - - it('should convert short account number to standard format', () => { - cy.get(accountInput).clear(); - cy.get(accountInput).type('123.'); - cy.get(accountInput).should('have.value', '1230000000'); - }); -}); From 67e0791f3480ff279d82c76fa8553bda73cec391 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Thu, 27 Mar 2025 09:03:40 +0100 Subject: [PATCH 15/65] fix: update order list tests to remove only and skip modifiers --- test/cypress/integration/order/orderList.spec.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/cypress/integration/order/orderList.spec.js b/test/cypress/integration/order/orderList.spec.js index 0f04d256b..ee011ea05 100644 --- a/test/cypress/integration/order/orderList.spec.js +++ b/test/cypress/integration/order/orderList.spec.js @@ -10,7 +10,7 @@ describe('OrderList', () => { cy.visit('/#/order/list'); }); - it.only('create order', () => { + it('create order', () => { cy.get('[data-cy="vnTableCreateBtn"]').click(); cy.selectOption(clientCreateSelect, 1101); cy.get(addressCreateSelect).click(); @@ -30,9 +30,11 @@ describe('OrderList', () => { cy.url().should('include', `/order`); }); - it.skip('filter list and create order', () => { + it('filter list and create order', () => { cy.dataCy('Customer ID_input').type('1101{enter}'); + cy.intercept('GET', /\/api\/Clients/).as('clientFilter'); cy.dataCy('vnTableCreateBtn').click(); + cy.wait('@clientFilter'); cy.dataCy('landedDate').find('input').type('06/01/2001'); cy.selectOption(agencyCreateSelect, 1); From 446b679bca32599d2c09ad8ceda096f7afe56ba9 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Thu, 27 Mar 2025 10:23:55 +0100 Subject: [PATCH 16/65] chore: update Cypress parallel test execution to use 2 instances --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 05ef34791..7f4144a54 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -126,7 +126,7 @@ pipeline { sh "docker-compose ${env.COMPOSE_PARAMS} up -d" image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") { - sh 'sh test/cypress/cypressParallel.sh 1' + sh 'sh test/cypress/cypressParallel.sh 2' } } } From d94dafd6671c885ca663b1ac86c17448922c7225 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Thu, 27 Mar 2025 11:43:00 +0100 Subject: [PATCH 17/65] chore: update Cypress parallel test execution to use 3 instances --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 7f4144a54..73c700f19 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -126,7 +126,7 @@ pipeline { sh "docker-compose ${env.COMPOSE_PARAMS} up -d" image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") { - sh 'sh test/cypress/cypressParallel.sh 2' + sh 'sh test/cypress/cypressParallel.sh 3' } } } From 696dbd4149c6e05046bfa8450bd955f31e49b73d Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Thu, 27 Mar 2025 12:27:47 +0100 Subject: [PATCH 18/65] chore: update Cypress parallel test execution to use 4 instances --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 73c700f19..0c209bdef 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -126,7 +126,7 @@ pipeline { sh "docker-compose ${env.COMPOSE_PARAMS} up -d" image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") { - sh 'sh test/cypress/cypressParallel.sh 3' + sh 'sh test/cypress/cypressParallel.sh 4' } } } From 71c6741cf290bf0ca58b4be97c2e0709f1ab087a Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Thu, 27 Mar 2025 12:28:11 +0100 Subject: [PATCH 19/65] chore: update Cypress parallel test execution to use 6 instances --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 0c209bdef..2a4e80e4f 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -126,7 +126,7 @@ pipeline { sh "docker-compose ${env.COMPOSE_PARAMS} up -d" image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") { - sh 'sh test/cypress/cypressParallel.sh 4' + sh 'sh test/cypress/cypressParallel.sh 6' } } } From a91a0146fe294d01717a394380e94a9bc9362a35 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Thu, 27 Mar 2025 13:03:21 +0100 Subject: [PATCH 20/65] fix: hasChanges --- src/pages/Ticket/Card/TicketSale.vue | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue index 2fb305cc3..666b5fefe 100644 --- a/src/pages/Ticket/Card/TicketSale.vue +++ b/src/pages/Ticket/Card/TicketSale.vue @@ -187,7 +187,9 @@ const getRowUpdateInputEvents = (sale) => { const resetChanges = async () => { arrayData.fetch({ append: false }); + tableRef.value.CrudModelRef.hasChanges = false; tableRef.value.reload(); + selectedRows.value = []; }; const changeQuantity = async (sale) => { @@ -390,7 +392,7 @@ const changeTicketState = async (val) => { const params = { ticketFk: route.params.id, code: val }; await axios.post('Tickets/state', params); notify('globals.dataSaved', 'positive'); - await resetChanges(); + resetChanges(); }; const removeSelectedSales = () => { From 6e84341aeade6662684dcbb3292d5bcf3fab8b3e Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Thu, 27 Mar 2025 13:06:29 +0100 Subject: [PATCH 21/65] perf: add await --- src/pages/Ticket/Card/TicketSale.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue index 666b5fefe..96a2dc43f 100644 --- a/src/pages/Ticket/Card/TicketSale.vue +++ b/src/pages/Ticket/Card/TicketSale.vue @@ -188,7 +188,7 @@ const getRowUpdateInputEvents = (sale) => { const resetChanges = async () => { arrayData.fetch({ append: false }); tableRef.value.CrudModelRef.hasChanges = false; - tableRef.value.reload(); + await tableRef.value.reload(); selectedRows.value = []; }; From ea314073d2b78f3d5c2df2031c9af8176e5f5d08 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Thu, 27 Mar 2025 13:26:42 +0100 Subject: [PATCH 22/65] chore: update Cypress parallel test execution to use 2 instances --- Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index 2a4e80e4f..7f4144a54 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -126,7 +126,7 @@ pipeline { sh "docker-compose ${env.COMPOSE_PARAMS} up -d" image.inside("--network ${env.COMPOSE_PROJECT}_default -e CI -e TZ --init") { - sh 'sh test/cypress/cypressParallel.sh 6' + sh 'sh test/cypress/cypressParallel.sh 2' } } } From c4ab00ffd21bbffdd3b99ae1b579fd47ae18bf82 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Thu, 27 Mar 2025 14:56:22 +0100 Subject: [PATCH 23/65] fix: update filter in TravelCard to include route parameter --- src/pages/Travel/Card/TravelCard.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Travel/Card/TravelCard.vue b/src/pages/Travel/Card/TravelCard.vue index 479b47fb9..d452f5287 100644 --- a/src/pages/Travel/Card/TravelCard.vue +++ b/src/pages/Travel/Card/TravelCard.vue @@ -8,6 +8,6 @@ import filter from './TravelFilter.js'; data-key="Travel" url="Travels" :descriptor="TravelDescriptor" - :filter="filter" + :filter="{ ...filter, where: { id: $route.params.id } }" /> </template> From 60899ef2d255f6bf9443121de25ece33fdc64316 Mon Sep 17 00:00:00 2001 From: Jon <jon@verdnatura.es> Date: Thu, 27 Mar 2025 15:03:11 +0100 Subject: [PATCH 24/65] perf: clean payload --- src/pages/Customer/components/CustomerAddressEdit.vue | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/pages/Customer/components/CustomerAddressEdit.vue b/src/pages/Customer/components/CustomerAddressEdit.vue index 31a930341..bc76f5985 100644 --- a/src/pages/Customer/components/CustomerAddressEdit.vue +++ b/src/pages/Customer/components/CustomerAddressEdit.vue @@ -93,8 +93,7 @@ const updateAddressTicket = async () => { }; const updateObservations = async (payload) => { - cleanPayload(payload); - await axios.post('AddressObservations/crud', payload); + await axios.post('AddressObservations/crud', cleanPayload(payload)); notes.value = []; deletes.value = []; }; @@ -110,8 +109,8 @@ function cleanPayload(payload) { (item) => item !== null && item !== undefined, ); } - return payload[prop]; }); + return payload; } async function updateAll({ data, payload }) { From 34c18d2baaf2f74db5d6fdb990bf2308471f3460 Mon Sep 17 00:00:00 2001 From: jtubau <jtubau@verdnatura.es> Date: Thu, 27 Mar 2025 15:31:55 +0100 Subject: [PATCH 25/65] test: refs #8717 update invoice creation test to ensure save button visibility --- test/cypress/integration/route/routeAutonomous.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cypress/integration/route/routeAutonomous.spec.js b/test/cypress/integration/route/routeAutonomous.spec.js index 72562259a..11d591bdd 100644 --- a/test/cypress/integration/route/routeAutonomous.spec.js +++ b/test/cypress/integration/route/routeAutonomous.spec.js @@ -53,7 +53,7 @@ describe('RouteAutonomous', () => { cy.get('.q-file').selectFile('test/cypress/fixtures/image.jpg', { force: true, }); - cy.dataCy(selectors.saveFormBtn).click(); + cy.dataCy(selectors.saveFormBtn).should('be.visible').click(); cy.checkNotification(dataSaved); }); From 0aa4c1c527d0bc63ed38e810ce97d3b0fcc8764f Mon Sep 17 00:00:00 2001 From: jtubau <jtubau@verdnatura.es> Date: Thu, 27 Mar 2025 16:12:03 +0100 Subject: [PATCH 26/65] test: refs #8717 skip RouteAutonomous test suite --- test/cypress/integration/route/routeAutonomous.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cypress/integration/route/routeAutonomous.spec.js b/test/cypress/integration/route/routeAutonomous.spec.js index 11d591bdd..d77584c04 100644 --- a/test/cypress/integration/route/routeAutonomous.spec.js +++ b/test/cypress/integration/route/routeAutonomous.spec.js @@ -1,4 +1,4 @@ -describe('RouteAutonomous', () => { +describe.skip('RouteAutonomous', () => { const getLinkSelector = (colField) => `tr:first-child > [data-col-field="${colField}"] > .no-padding > .link`; From 2a3e072b1bd95c2484099b04e7e7c24b0bb6d9ab Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Fri, 28 Mar 2025 01:25:38 +0100 Subject: [PATCH 27/65] feat: add departmentFk to user data and filter clients by department --- src/composables/useRole.js | 1 + src/pages/Monitor/MonitorClients.vue | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/composables/useRole.js b/src/composables/useRole.js index ff54b409c..e700b1f2e 100644 --- a/src/composables/useRole.js +++ b/src/composables/useRole.js @@ -13,6 +13,7 @@ export function useRole() { name: data.user.name, nickname: data.user.nickname, lang: data.user.lang || 'es', + departmentFk: data.user.worker.department.departmentFk, }; state.setUser(userData); state.setRoles(roles); diff --git a/src/pages/Monitor/MonitorClients.vue b/src/pages/Monitor/MonitorClients.vue index c814d623e..99110df16 100644 --- a/src/pages/Monitor/MonitorClients.vue +++ b/src/pages/Monitor/MonitorClients.vue @@ -9,12 +9,14 @@ import VnInputDate from 'src/components/common/VnInputDate.vue'; import VnRow from 'src/components/ui/VnRow.vue'; import { dateRange } from 'src/filters'; import useOpenURL from 'src/composables/useOpenURL'; +import { useState } from 'src/composables/useState'; const { t } = useI18n(); const dates = dateRange(Date.vnNew()); const from = ref(dates[0]); const to = ref(dates[1]); +const state = useState(); const filter = computed(() => { const obj = {}; const formatFrom = setHours(from.value, 'from'); @@ -25,7 +27,9 @@ const filter = computed(() => { else if (formatFrom && !formatTo) stamp = { gte: formatFrom }; else if (formatFrom && formatTo) stamp = { between: [formatFrom, formatTo] }; - return Object.assign(obj, { where: { 'v.stamp': stamp } }); + return Object.assign(obj, { + where: { 'v.stamp': stamp, departmentFk: state.getUser().departmentFk }, + }); }); function exprBuilder(param, value) { From c03a56f69fb774c3399f8147bf8e5521da9769ea Mon Sep 17 00:00:00 2001 From: Jon <jon@verdnatura.es> Date: Fri, 28 Mar 2025 09:28:24 +0100 Subject: [PATCH 28/65] feat: refs #7995 added hasAcl to check only one acl --- src/composables/useAcl.js | 11 +++++++++++ src/pages/Account/Card/AccountDescriptorMenu.vue | 10 +++------- src/pages/Customer/Card/CustomerBalance.vue | 6 ++---- .../Ticket/Card/BasicData/TicketBasicDataForm.vue | 4 +--- src/pages/Ticket/Card/TicketSaleMoreActions.vue | 4 +--- src/pages/Travel/Card/TravelDescriptorMenuItems.vue | 2 +- src/pages/Worker/Card/WorkerCalendar.vue | 4 +--- src/pages/Worker/Card/WorkerLocker.vue | 8 ++------ src/pages/Worker/Card/WorkerTimeControl.vue | 8 ++------ 9 files changed, 24 insertions(+), 33 deletions(-) diff --git a/src/composables/useAcl.js b/src/composables/useAcl.js index ede359186..581e553aa 100644 --- a/src/composables/useAcl.js +++ b/src/composables/useAcl.js @@ -30,9 +30,20 @@ export function useAcl() { return false; } + function hasAcl(model, props, accessType) { + const modelAcl = state.getAcls().value[model]; + const access = modelAcl[props]; + if (!modelAcl || !access) return false; + if (access[accessType] || access['*']) { + return true; + } + return false; + } + return { fetch, hasAny, state, + hasAcl, }; } diff --git a/src/pages/Account/Card/AccountDescriptorMenu.vue b/src/pages/Account/Card/AccountDescriptorMenu.vue index eafd62df6..f3eabb531 100644 --- a/src/pages/Account/Card/AccountDescriptorMenu.vue +++ b/src/pages/Account/Card/AccountDescriptorMenu.vue @@ -100,12 +100,8 @@ const onChangePass = (oldPass) => { }; onMounted(() => { - hasitManagementAccess.value = useAcl().hasAny([ - { model: 'VnUser', props: 'higherPrivileges', accessType: 'WRITE' }, - ]); - hasSysadminAccess.value = useAcl().hasAny([ - { model: 'VnUser', props: 'adminUser', accessType: 'WRITE' }, - ]); + hasitManagementAccess.value = useAcl().hasAcl('VnUser', 'higherPrivileges', 'WRITE'); + hasSysadminAccess.value = useAcl().hasAcl('VnUser', 'adminUser', 'WRITE'); }); </script> <template> @@ -227,7 +223,7 @@ onMounted(() => { <QItemSection>{{ t('account.card.actions.deactivateUser.name') }}</QItemSection> </QItem> <QItem - v-if="useAcl().hasAny([{ model: 'VnRole', props: '*', accessType: 'WRITE' }])" + v-if="useAcl().hasAcl('VnRole', '*', 'WRITE')" v-ripple clickable @click="showSyncDialog = true" diff --git a/src/pages/Customer/Card/CustomerBalance.vue b/src/pages/Customer/Card/CustomerBalance.vue index 11db92eab..eea532de6 100644 --- a/src/pages/Customer/Card/CustomerBalance.vue +++ b/src/pages/Customer/Card/CustomerBalance.vue @@ -24,7 +24,7 @@ import InvoiceOutDescriptorProxy from 'src/pages/InvoiceOut/Card/InvoiceOutDescr const { openConfirmationModal } = useVnConfirm(); const { sendEmail, openReport } = usePrintService(); const { t } = useI18n(); -const { hasAny } = useAcl(); +const { hasAcl } = useAcl(); const quasar = useQuasar(); const route = useRoute(); @@ -276,9 +276,7 @@ const showBalancePdf = ({ id }) => { > <VnInput v-model="scope.value" - :disable=" - !hasAny([{ model: 'Receipt', props: '*', accessType: 'WRITE' }]) - " + :disable="!hasAcl('Receipt', '*', 'WRITE')" @keypress.enter="scope.set" autofocus /> diff --git a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue index 9d70fea38..61932468c 100644 --- a/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue +++ b/src/pages/Ticket/Card/BasicData/TicketBasicDataForm.vue @@ -25,9 +25,7 @@ const { validate } = useValidator(); const { notify } = useNotify(); const router = useRouter(); const { t } = useI18n(); -const canEditZone = useAcl().hasAny([ - { model: 'Ticket', props: 'editZone', accessType: 'WRITE' }, -]); +const canEditZone = useAcl().hasAcl('Ticket', 'editZone', 'WRITE'); const agencyFetchRef = ref(); const warehousesOptions = ref([]); diff --git a/src/pages/Ticket/Card/TicketSaleMoreActions.vue b/src/pages/Ticket/Card/TicketSaleMoreActions.vue index 773b0807f..864bfd03f 100644 --- a/src/pages/Ticket/Card/TicketSaleMoreActions.vue +++ b/src/pages/Ticket/Card/TicketSaleMoreActions.vue @@ -55,9 +55,7 @@ const isClaimable = computed(() => { if (ticket.value) { const landedPlusWeek = new Date(ticket.value.landed); landedPlusWeek.setDate(landedPlusWeek.getDate() + 7); - const createAfterDeadline = acl.hasAny([ - { model: 'Claim', props: 'createAfterDeadline', accessType: 'WRITE' }, - ]); + const createAfterDeadline = acl.hasAcl('Claim', 'createAfterDeadline', 'WRITE'); return landedPlusWeek >= Date.vnNew() || createAfterDeadline; } return false; diff --git a/src/pages/Travel/Card/TravelDescriptorMenuItems.vue b/src/pages/Travel/Card/TravelDescriptorMenuItems.vue index 14d824b86..f8828bffe 100644 --- a/src/pages/Travel/Card/TravelDescriptorMenuItems.vue +++ b/src/pages/Travel/Card/TravelDescriptorMenuItems.vue @@ -37,7 +37,7 @@ const cloneTravelWithEntries = async () => { router.push({ name: 'TravelBasicData', params: { id: data.id } }); }; -const canDelete = computed(() => useAcl().hasAny('Travel', '*', 'WRITE')); +const canDelete = computed(() => useAcl().hasAcl('Travel', '*', 'WRITE')); const openDeleteEntryDialog = (id) => { quasar diff --git a/src/pages/Worker/Card/WorkerCalendar.vue b/src/pages/Worker/Card/WorkerCalendar.vue index df4616011..05ebb4687 100644 --- a/src/pages/Worker/Card/WorkerCalendar.vue +++ b/src/pages/Worker/Card/WorkerCalendar.vue @@ -18,9 +18,7 @@ const router = useRouter(); const route = useRoute(); const { t } = useI18n(); const acl = useAcl(); -const canSeeNotes = computed(() => - acl.hasAny([{ model: 'Worker', props: '__get__business', accessType: 'READ' }]), -); +const canSeeNotes = computed(() => acl.hasAcl('Worker', '__get__business', 'READ')); const workerIsFreelance = ref(); const WorkerFreelanceRef = ref(); const workerCalendarFilterRef = ref(null); diff --git a/src/pages/Worker/Card/WorkerLocker.vue b/src/pages/Worker/Card/WorkerLocker.vue index 015bced35..62891070d 100644 --- a/src/pages/Worker/Card/WorkerLocker.vue +++ b/src/pages/Worker/Card/WorkerLocker.vue @@ -9,7 +9,7 @@ import VnSelect from 'src/components/common/VnSelect.vue'; import { useArrayData } from 'src/composables/useArrayData'; import FetchData from 'components/FetchData.vue'; -const { hasAny } = useAcl(); +const { hasAcl } = useAcl(); const { t } = useI18n(); const fetchData = ref(); const originaLockerId = ref(); @@ -58,11 +58,7 @@ const init = async (data) => { option-label="code" option-value="id" hide-selected - :readonly=" - !hasAny([ - { model: 'Worker', props: '__get__locker', accessType: 'READ' }, - ]) - " + :readonly="!hasAcl('Worker', '__get__locker', 'READ')" /> </template> </FormModel> diff --git a/src/pages/Worker/Card/WorkerTimeControl.vue b/src/pages/Worker/Card/WorkerTimeControl.vue index 9c0fa6758..b64166c7d 100644 --- a/src/pages/Worker/Card/WorkerTimeControl.vue +++ b/src/pages/Worker/Card/WorkerTimeControl.vue @@ -68,13 +68,9 @@ const arrayData = useArrayData('Worker'); const acl = useAcl(); const selectedDateYear = computed(() => moment(selectedDate.value).isoWeekYear()); const worker = computed(() => arrayData.store?.data); -const canSend = computed(() => - acl.hasAny([{ model: 'WorkerTimeControl', props: 'sendMail', accessType: 'WRITE' }]), -); +const canSend = computed(() => acl.hasAcl('WorkerTimeControl', 'sendMail', 'WRITE')); const canUpdate = computed(() => - acl.hasAny([ - { model: 'WorkerTimeControl', props: 'updateMailState', accessType: 'WRITE' }, - ]), + acl.hasAcl('WorkerTimeControl', 'updateMailState', 'WRITE'), ); const isHimself = computed(() => user.value.id === Number(route.params.id)); From a49c8891a743d0e73162e1dbea0e05a385eb91cc Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Fri, 28 Mar 2025 10:22:08 +0100 Subject: [PATCH 29/65] fix: params.departmentFk i18n and ticketFilter.groupedStates --- src/pages/Claim/ClaimFilter.vue | 2 ++ src/pages/Customer/CustomerFilter.vue | 2 ++ .../Defaulter/CustomerDefaulterFilter.vue | 2 ++ src/pages/Order/Card/OrderFilter.vue | 2 ++ src/pages/Ticket/TicketFilter.vue | 29 +++++-------------- src/pages/Worker/WorkerFilter.vue | 3 ++ 6 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/pages/Claim/ClaimFilter.vue b/src/pages/Claim/ClaimFilter.vue index 37146865c..d86a233b5 100644 --- a/src/pages/Claim/ClaimFilter.vue +++ b/src/pages/Claim/ClaimFilter.vue @@ -122,6 +122,7 @@ const props = defineProps({ <i18n> en: params: + departmentFk: Department search: Contains clientFk: Customer clientName: Customer @@ -134,6 +135,7 @@ en: zoneFk: Zone es: params: + departmentFk: Departamento search: Contiene clientFk: Cliente clientName: Cliente diff --git a/src/pages/Customer/CustomerFilter.vue b/src/pages/Customer/CustomerFilter.vue index 2ace6dd02..6231036c0 100644 --- a/src/pages/Customer/CustomerFilter.vue +++ b/src/pages/Customer/CustomerFilter.vue @@ -163,6 +163,7 @@ en: email: Email isToBeMailed: Mailed isEqualizated: Equailized + departmentFk: Department businessTypeFk: Business type sageTaxTypeFk: Sage Tax Type sageTransactionTypeFk: Sage Tax Type @@ -173,6 +174,7 @@ en: postcode: Postcode es: params: + departmentFk: Departamento search: Contiene fi: NIF isActive: Activo diff --git a/src/pages/Customer/Defaulter/CustomerDefaulterFilter.vue b/src/pages/Customer/Defaulter/CustomerDefaulterFilter.vue index 0eab7b7c5..c391e4c64 100644 --- a/src/pages/Customer/Defaulter/CustomerDefaulterFilter.vue +++ b/src/pages/Customer/Defaulter/CustomerDefaulterFilter.vue @@ -196,8 +196,10 @@ en: date: L. O. Date credit: Credit I. defaulterSinced: From + departmentFk: Department es: params: + departmentFk: Departamento clientFk: Cliente countryFk: País paymentMethod: F. Pago diff --git a/src/pages/Order/Card/OrderFilter.vue b/src/pages/Order/Card/OrderFilter.vue index 42578423f..362afd044 100644 --- a/src/pages/Order/Card/OrderFilter.vue +++ b/src/pages/Order/Card/OrderFilter.vue @@ -141,8 +141,10 @@ en: myTeam: My Team isConfirmed: Order Confirmed showEmpty: Show Empty + departmentFk: Department es: params: + departmentFk: Departamento search: Búsqueda clientFk: Cliente agencyModeFk: Agencia diff --git a/src/pages/Ticket/TicketFilter.vue b/src/pages/Ticket/TicketFilter.vue index f959157f6..318b27b13 100644 --- a/src/pages/Ticket/TicketFilter.vue +++ b/src/pages/Ticket/TicketFilter.vue @@ -22,16 +22,6 @@ const states = ref([]); const agencies = ref([]); const warehouses = ref([]); const groupedStates = ref([]); - -const getGroupedStates = (data) => { - for (const state of data) { - groupedStates.value.push({ - id: state.id, - name: t(`${state.code}`), - code: state.code, - }); - } -}; </script> <template> @@ -39,12 +29,11 @@ const getGroupedStates = (data) => { <FetchData url="States" @on-fetch="(data) => (states = data)" auto-load /> <FetchData url="AlertLevels" - @on-fetch=" - (data) => { - getGroupedStates(data); - } - " auto-load + @on-fetch=" + (data) => + (groupedStates = data.map((x) => Object.assign(x, { code: t(x.code) }))) + " /> <FetchData url="AgencyModes" @@ -136,19 +125,17 @@ const getGroupedStates = (data) => { </QItemSection> <QItemSection v-if="groupedStates"> <VnSelect - :label="t('Grouped state')" + :label="t('params.groupedStates')" v-model="params.groupedStates" @update:model-value="searchFn()" :options="groupedStates" - option-value="id" - option-label="name" + option-label="code" emit-value map-options use-input dense outlined rounded - sort-by="name ASC" /> </QItemSection> </QItem> @@ -326,7 +313,7 @@ en: ON_PREPARATION: On preparation PACKED: Packed DELIVERED: Delivered - ON_PREVIOUS: ON_PREVIOUS + ON_PREVIOUS: On previous es: params: search: Contiene @@ -371,7 +358,7 @@ es: ON_PREPARATION: En preparación PACKED: Encajado DELIVERED: Servido - ON_PREVIOUS: ON_PREVIOUS + ON_PREVIOUS: En previa Collection: Colección Nickname: Nombre mostrado </i18n> diff --git a/src/pages/Worker/WorkerFilter.vue b/src/pages/Worker/WorkerFilter.vue index 8210ba0e3..adddacd28 100644 --- a/src/pages/Worker/WorkerFilter.vue +++ b/src/pages/Worker/WorkerFilter.vue @@ -119,8 +119,11 @@ en: lastName: Last name userName: User extension: Extension + departmentFk: Department es: + params: + departmentFk: Departamento search: Contiene firstName: Nombre lastName: Apellidos From 50fb8a31a68c83e6adfa0b16e59eb8bdf88e5d20 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Fri, 28 Mar 2025 12:03:15 +0100 Subject: [PATCH 30/65] test: fix test --- src/composables/__tests__/useRole.spec.js | 7 ++++--- src/composables/__tests__/useSession.spec.js | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/composables/__tests__/useRole.spec.js b/src/composables/__tests__/useRole.spec.js index d0bca5342..54d983a13 100644 --- a/src/composables/__tests__/useRole.spec.js +++ b/src/composables/__tests__/useRole.spec.js @@ -23,18 +23,19 @@ describe('useRole', () => { name: `T'Challa`, nickname: 'Black Panther', lang: 'en', + worker: { department: { departmentFk: 155 } }, }; const expectedUser = { id: 999, name: `T'Challa`, nickname: 'Black Panther', lang: 'en', + departmentFk: 155, }; const expectedRoles = ['salesPerson', 'admin']; - vi.spyOn(axios, 'get') - .mockResolvedValueOnce({ + vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: { roles: rolesData, user: fetchedUser }, - }) + }); vi.spyOn(role.state, 'setUser'); vi.spyOn(role.state, 'setRoles'); diff --git a/src/composables/__tests__/useSession.spec.js b/src/composables/__tests__/useSession.spec.js index 789b149ec..cae33f893 100644 --- a/src/composables/__tests__/useSession.spec.js +++ b/src/composables/__tests__/useSession.spec.js @@ -75,6 +75,7 @@ describe('session', () => { userConfig: { darkMode: false, }, + worker: { department: { departmentFk: 155 } }, }; const rolesData = [ { @@ -143,7 +144,7 @@ describe('session', () => { await session.destroy(); // this clears token and user for any other test }); }, - {} + {}, ); describe('RenewToken', () => { @@ -175,7 +176,7 @@ describe('session', () => { await session.checkValidity(); expect(sessionStorage.getItem('token')).toEqual(expectedToken); expect(sessionStorage.getItem('tokenMultimedia')).toEqual( - expectedTokenMultimedia + expectedTokenMultimedia, ); }); it('Should renewToken', async () => { @@ -204,7 +205,7 @@ describe('session', () => { await session.checkValidity(); expect(sessionStorage.getItem('token')).not.toEqual(expectedToken); expect(sessionStorage.getItem('tokenMultimedia')).not.toEqual( - expectedTokenMultimedia + expectedTokenMultimedia, ); }); }); From 4fbcb822347040044e28a92ec7e55bf3fc391cc6 Mon Sep 17 00:00:00 2001 From: jtubau <jtubau@verdnatura.es> Date: Fri, 28 Mar 2025 13:20:02 +0100 Subject: [PATCH 31/65] fix: refs #8717 update AgencyCard to include filter by agency ID and correct locale key casing --- src/pages/Route/Agency/Card/AgencyCard.vue | 2 +- src/pages/Route/locale/en.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/Route/Agency/Card/AgencyCard.vue b/src/pages/Route/Agency/Card/AgencyCard.vue index c21298470..9fd3fe5e5 100644 --- a/src/pages/Route/Agency/Card/AgencyCard.vue +++ b/src/pages/Route/Agency/Card/AgencyCard.vue @@ -3,5 +3,5 @@ import AgencyDescriptor from 'pages/Route/Agency/Card/AgencyDescriptor.vue'; import VnCard from 'src/components/common/VnCard.vue'; </script> <template> - <VnCard data-key="Agency" url="Agencies" :descriptor="AgencyDescriptor" /> + <VnCard data-key="Agency" url="Agencies" :descriptor="AgencyDescriptor" :filter="{ where: { id: $route.params.id } }" /> </template> diff --git a/src/pages/Route/locale/en.yml b/src/pages/Route/locale/en.yml index 283b61855..e7e2d691e 100644 --- a/src/pages/Route/locale/en.yml +++ b/src/pages/Route/locale/en.yml @@ -50,7 +50,7 @@ route: agencyAgreement: Agency agreement agencyModeName: Agency route isOwn: Own - isAnyVolumeallowed: Any volume allowed + isAnyVolumeAllowed: Any volume allowed Worker: Worker Agency: Agency Vehicle: Vehicle From d60d7da33c756b36c0dc1bdb2390c20eca5f0b84 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Fri, 28 Mar 2025 14:31:11 +0100 Subject: [PATCH 32/65] fix: improve monitorClient.department --- src/pages/Monitor/MonitorClients.vue | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/pages/Monitor/MonitorClients.vue b/src/pages/Monitor/MonitorClients.vue index 99110df16..2ba5f4c0b 100644 --- a/src/pages/Monitor/MonitorClients.vue +++ b/src/pages/Monitor/MonitorClients.vue @@ -26,9 +26,11 @@ const filter = computed(() => { if (!formatFrom && formatTo) stamp = { lte: formatTo }; else if (formatFrom && !formatTo) stamp = { gte: formatFrom }; else if (formatFrom && formatTo) stamp = { between: [formatFrom, formatTo] }; - return Object.assign(obj, { - where: { 'v.stamp': stamp, departmentFk: state.getUser().departmentFk }, + where: { + 'v.stamp': stamp, + 'c.departmentFk': state.getUser().value.departmentFk, + }, }); }); @@ -36,8 +38,6 @@ function exprBuilder(param, value) { switch (param) { case 'clientFk': return { [`c.id`]: value }; - case 'departmentFk': - return { [`c.${param}`]: value }; } } @@ -70,9 +70,13 @@ const columns = computed(() => [ align: 'left', name: 'departmentFk', label: t('customer.summary.team'), - component: 'select', - attrs: { - url: 'Departments', + columnFilter: { + component: 'select', + attrs: { + url: 'Departments', + }, + alias: 'c', + inWhere: true, }, columnField: { component: null, From 36f142800f04b6549b599ebc6633cc1dad5a8165 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Mon, 31 Mar 2025 09:51:36 +0200 Subject: [PATCH 33/65] refactor: simplify data fetching logic in VnCard.vue --- src/components/common/VnCard.vue | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/components/common/VnCard.vue b/src/components/common/VnCard.vue index 21cdc9df5..569fdfe87 100644 --- a/src/components/common/VnCard.vue +++ b/src/components/common/VnCard.vue @@ -26,11 +26,7 @@ const route = useRoute(); const stateStore = useStateStore(); const router = useRouter(); const entityId = computed(() => props.id || route?.params?.id); -const arrayData = useArrayData(props.dataKey, { - url: props.url, - userFilter: props.filter, - oneRecord: true, -}); +let arrayData = getArrayData(); onBeforeRouteLeave(() => { stateStore.cardDescriptorChangeValue(null); @@ -61,16 +57,31 @@ onBeforeRouteUpdate(async (to, from) => { }); async function fetch(id, append = false) { - const regex = /\/(\d+)/; if (props.idInWhere) arrayData.store.filter.where = { id }; - else if (!regex.test(props.url)) arrayData.store.url = `${props.url}/${id}`; - else arrayData.store.url = props.url.replace(regex, `/${id}`); + else { + arrayData = getArrayData(); + } await arrayData.fetch({ append, updateRouter: false }); emit('onFetch', arrayData.store.data); } function hasRouteParam(params, valueToCheck = ':addressId') { return Object.values(params).includes(valueToCheck); } + +function formatUrl(id) { + const newId = id || entityId.value; + const regex = /\/(\d+)/; + if (!regex.test(props.url)) return `${props.url}/${newId}`; + return props.url.replace(regex, `/${newId}`); +} + +function getArrayData() { + return useArrayData(props.dataKey, { + url: formatUrl(), + userFilter: props.filter, + oneRecord: true, + }); +} </script> <template> <template v-if="visual"> From f8cc7b95abe28463859b7e02e7daf705330f38e5 Mon Sep 17 00:00:00 2001 From: Jon <jon@verdnatura.es> Date: Mon, 31 Mar 2025 09:51:40 +0200 Subject: [PATCH 34/65] refactor: refs #7995 modified hasAcl function --- src/composables/useAcl.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/composables/useAcl.js b/src/composables/useAcl.js index 581e553aa..4033ee9a6 100644 --- a/src/composables/useAcl.js +++ b/src/composables/useAcl.js @@ -32,12 +32,13 @@ export function useAcl() { function hasAcl(model, props, accessType) { const modelAcl = state.getAcls().value[model]; - const access = modelAcl[props]; - if (!modelAcl || !access) return false; - if (access[accessType] || access['*']) { - return true; - } - return false; + const propAcl = modelAcl[props] || {}; + return !!( + propAcl[accessType] || + modelAcl['*']?.[accessType] || + propAcl['*'] || + modelAcl['*']?.['*'] + ); } return { From ba2084e90686d6467438ea97992b5d8efbea38db Mon Sep 17 00:00:00 2001 From: pablone <pablone@verdnatura.es> Date: Mon, 31 Mar 2025 12:30:16 +0200 Subject: [PATCH 35/65] refactor: update TravelSummary and TravelList components for improved data fetching and summary view --- src/pages/Travel/Card/TravelSummary.vue | 29 ++++++++++--------------- src/pages/Travel/TravelList.vue | 2 +- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/pages/Travel/Card/TravelSummary.vue b/src/pages/Travel/Card/TravelSummary.vue index 5a824ddc3..dbb997ccb 100644 --- a/src/pages/Travel/Card/TravelSummary.vue +++ b/src/pages/Travel/Card/TravelSummary.vue @@ -268,13 +268,6 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`; </script> <template> - <FetchData - url="Warehouses" - :filter="{ fields: ['id', 'name'] }" - order="name" - @on-fetch="(data) => (warehouses = data)" - auto-load - /> <CardSummary ref="summaryRef" :url="`Travels/${entityId}/getTravel`" @@ -414,18 +407,18 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`; </template> </QTable> </QCard> - <QCard class="full-width" v-if="thermographs.length > 0"> - <RouterLink - class="header header-link" - :to="{ - name: 'TravelThermographsIndex', - params: { id: travel.id }, - }" - > - {{ t('travel.summary.thermographs') }} - <QIcon name="open_in_new" /> - </RouterLink> + <FetchData + url="Warehouses" + :filter="{ fields: ['id', 'name'] }" + order="name" + @on-fetch="(data) => (warehouses = data)" + auto-load + /> + <VnTitle + :url="getLink('thermographs')" + :text="t('travel.summary.thermographs')" + /> <QTable :rows="thermographs" :columns="thermographsTableColumns" diff --git a/src/pages/Travel/TravelList.vue b/src/pages/Travel/TravelList.vue index b227afcb2..32ddc639a 100644 --- a/src/pages/Travel/TravelList.vue +++ b/src/pages/Travel/TravelList.vue @@ -201,7 +201,7 @@ const columns = computed(() => [ { title: t('components.smartCard.viewSummary'), icon: 'preview', - action: (row) => viewSummary(row.id, TravelSummary), + action: (row) => viewSummary(row.id, TravelSummary, 'lg-width'), isPrimary: true, }, ], From 95950b748540e0d8cf074e95c3c735819e386681 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Mon, 31 Mar 2025 13:27:28 +0200 Subject: [PATCH 36/65] refactor(VnCard): use prop.url when init --- src/components/common/VnCard.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/common/VnCard.vue b/src/components/common/VnCard.vue index 569fdfe87..39c0b2e00 100644 --- a/src/components/common/VnCard.vue +++ b/src/components/common/VnCard.vue @@ -26,7 +26,7 @@ const route = useRoute(); const stateStore = useStateStore(); const router = useRouter(); const entityId = computed(() => props.id || route?.params?.id); -let arrayData = getArrayData(); +let arrayData = getArrayData(props.url); onBeforeRouteLeave(() => { stateStore.cardDescriptorChangeValue(null); @@ -75,9 +75,9 @@ function formatUrl(id) { return props.url.replace(regex, `/${newId}`); } -function getArrayData() { +function getArrayData(url = formatUrl()) { return useArrayData(props.dataKey, { - url: formatUrl(), + url, userFilter: props.filter, oneRecord: true, }); From 5ade9fd13332fe89388d6c3206c6cea86fb25f9e Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Mon, 31 Mar 2025 14:43:00 +0200 Subject: [PATCH 37/65] fix: add trycatch to handle notifications --- src/pages/Ticket/Card/TicketSale.vue | 148 +++++++++++++++------------ 1 file changed, 84 insertions(+), 64 deletions(-) diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue index 96a2dc43f..abcc2196d 100644 --- a/src/pages/Ticket/Card/TicketSale.vue +++ b/src/pages/Ticket/Card/TicketSale.vue @@ -1,5 +1,5 @@ <script setup> -import { onMounted, ref, computed, watch } from 'vue'; +import { onMounted, ref, computed, watch, inject } from 'vue'; import { useI18n } from 'vue-i18n'; import { useRouter, useRoute } from 'vue-router'; import { useQuasar } from 'quasar'; @@ -25,7 +25,7 @@ import VnTable from 'src/components/VnTable/VnTable.vue'; import VnConfirm from 'src/components/ui/VnConfirm.vue'; import TicketProblems from 'src/components/TicketProblems.vue'; import RightMenu from 'src/components/common/RightMenu.vue'; - +const app = inject('app'); const route = useRoute(); const router = useRouter(); const { t } = useI18n(); @@ -196,13 +196,17 @@ const changeQuantity = async (sale) => { if (!sale.itemFk || sale.quantity == null || sale?.originalQuantity === sale.quantity) return; else sale.originalQuantity = sale.quantity; - if (!sale.id) return addSale(sale); + try { + if (!sale.id) await addSale(sale); + } catch (e) { + app.config.errorHandler(e); + return; + } if (await isSalePrepared(sale)) { await confirmUpdate(() => updateQuantity(sale)); } else await updateQuantity(sale); }; - const updateQuantity = async (sale) => { try { let { quantity, id } = sale; @@ -215,7 +219,7 @@ const updateQuantity = async (sale) => { (s) => s.id === sale.id, ); sale.quantity = quantity; - throw e; + app.config.errorHandler(e); } }; @@ -224,24 +228,27 @@ const addSale = async (sale) => { barcode: sale.itemFk, quantity: sale.quantity, }; + try { + const { data } = await axios.post(`tickets/${route.params.id}/addSale`, params); - const { data } = await axios.post(`tickets/${route.params.id}/addSale`, params); + if (!data) return; - if (!data) return; + const newSale = data; + sale.id = newSale.id; + sale.image = newSale.item.image; + sale.subName = newSale.item.subName; + sale.concept = newSale.concept; + sale.quantity = newSale.quantity; + sale.discount = newSale.discount; + sale.price = newSale.price; + sale.item = newSale.item; - const newSale = data; - sale.id = newSale.id; - sale.image = newSale.item.image; - sale.subName = newSale.item.subName; - sale.concept = newSale.concept; - sale.quantity = newSale.quantity; - sale.discount = newSale.discount; - sale.price = newSale.price; - sale.item = newSale.item; - - notify('globals.dataSaved', 'positive'); - sale.isNew = false; - resetChanges(); + notify('globals.dataSaved', 'positive'); + sale.isNew = false; + resetChanges(); + } catch (e) { + app.config.errorHandler(e); + } }; const changeConcept = async (sale) => { if (await isSalePrepared(sale)) { @@ -250,10 +257,14 @@ const changeConcept = async (sale) => { }; const updateConcept = async (sale) => { - const data = { newConcept: sale.concept }; - await axios.post(`Sales/${sale.id}/updateConcept`, data); - notify('globals.dataSaved', 'positive'); - resetChanges(); + try { + const data = { newConcept: sale.concept }; + await axios.post(`Sales/${sale.id}/updateConcept`, data); + notify('globals.dataSaved', 'positive'); + resetChanges(); + } catch (e) { + app.config.errorHandler(e); + } }; const DEFAULT_EDIT = { @@ -264,18 +275,6 @@ const DEFAULT_EDIT = { oldQuantity: null, }; const edit = ref({ ...DEFAULT_EDIT }); -const usesMana = ref(null); - -const getUsesMana = async () => { - const { data } = await axios.get('Sales/usesMana'); - usesMana.value = data; -}; - -const getMana = async () => { - const { data } = await axios.get(`Tickets/${route.params.id}/getDepartmentMana`); - mana.value = data; - await getUsesMana(); -}; const selectedValidSales = computed(() => { if (!sales.value) return; @@ -312,11 +311,15 @@ const changePrice = async (sale) => { } }; const updatePrice = async (sale, newPrice) => { - await axios.post(`Sales/${sale.id}/updatePrice`, { newPrice }); - sale.price = newPrice; - edit.value = { ...DEFAULT_EDIT }; - notify('globals.dataSaved', 'positive'); - resetChanges(); + try { + await axios.post(`Sales/${sale.id}/updatePrice`, { newPrice }); + sale.price = newPrice; + edit.value = { ...DEFAULT_EDIT }; + notify('globals.dataSaved', 'positive'); + resetChanges(); + } catch (e) { + app.config.errorHandler(e); + } }; const changeDiscount = async (sale) => { @@ -339,15 +342,20 @@ const updateDiscounts = async (sales, newDiscount) => { }; const updateDiscount = async (sales, newDiscount = 0) => { - const salesIds = sales.map(({ id }) => id); - const params = { - salesIds, - newDiscount, - manaCode: manaCode.value, - }; - await axios.post(`Tickets/${route.params.id}/updateDiscount`, params); - notify('globals.dataSaved', 'positive'); - resetChanges(); + try { + const salesIds = sales.map(({ id }) => id); + const params = { + salesIds, + newDiscount, + manaCode: manaCode.value, + }; + await axios.post(`Tickets/${route.params.id}/updateDiscount`, params); + notify('globals.dataSaved', 'positive'); + resetChanges(); + } catch (e) { + app.config.errorHandler(e); + return; + } }; const getNewPrice = computed(() => { @@ -369,11 +377,15 @@ const getNewPrice = computed(() => { }); const newOrderFromTicket = async () => { - const { data } = await axios.post(`Orders/newFromTicket`, { - ticketFk: Number(route.params.id), - }); - const routeData = router.resolve({ name: 'OrderCatalog', params: { id: data } }); - window.open(routeData.href, '_blank'); + try { + const { data } = await axios.post(`Orders/newFromTicket`, { + ticketFk: Number(route.params.id), + }); + const routeData = router.resolve({ name: 'OrderCatalog', params: { id: data } }); + window.open(routeData.href, '_blank'); + } catch (e) { + app.config.errorHandler(e); + } }; const goToLog = (saleId) => { @@ -388,11 +400,15 @@ const goToLog = (saleId) => { }; const changeTicketState = async (val) => { - stateBtnDropdownRef.value.hide(); - const params = { ticketFk: route.params.id, code: val }; - await axios.post('Tickets/state', params); - notify('globals.dataSaved', 'positive'); - resetChanges(); + try { + stateBtnDropdownRef.value.hide(); + const params = { ticketFk: route.params.id, code: val }; + await axios.post('Tickets/state', params); + notify('globals.dataSaved', 'positive'); + resetChanges(); + } catch (e) { + app.config.errorHandler(e); + } }; const removeSelectedSales = () => { @@ -412,10 +428,14 @@ const removeSales = async () => { .forEach((sale) => tableRef.value.CrudModelRef.formData.splice(sale.$index, 1)); if (params.sales.length == 0) return; - await axios.post('Sales/deleteSales', params); - removeSelectedSales(); - notify('globals.dataSaved', 'positive'); - resetChanges(); + try { + await axios.post('Sales/deleteSales', params); + removeSelectedSales(); + notify('globals.dataSaved', 'positive'); + resetChanges(); + } catch (e) { + app.config.errorHandler(e); + } }; const setTransferParams = async () => { From a81f8fcdafe7dd3aab520716c11f10515b9e0d66 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Mon, 31 Mar 2025 14:43:15 +0200 Subject: [PATCH 38/65] feat: add noOne --- src/pages/Customer/CustomerFilter.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/Customer/CustomerFilter.vue b/src/pages/Customer/CustomerFilter.vue index 2ace6dd02..58bc18344 100644 --- a/src/pages/Customer/CustomerFilter.vue +++ b/src/pages/Customer/CustomerFilter.vue @@ -73,6 +73,7 @@ const exprBuilder = (param, value) => { option-value="id" option-label="name" url="Departments" + no-one="true" /> </QItemSection> </QItem> From f3925026738af32b0bc00a20e62d4e203d6274df Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Mon, 31 Mar 2025 15:02:37 +0200 Subject: [PATCH 39/65] fix: workerSummary --- src/pages/Worker/Card/WorkerSummary.vue | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue index 40787613c..26c84fe09 100644 --- a/src/pages/Worker/Card/WorkerSummary.vue +++ b/src/pages/Worker/Card/WorkerSummary.vue @@ -73,21 +73,18 @@ onBeforeMount(async () => { /> </template> </VnLv> - <VnLv :value="worker.mobileExtension"> - <template #label> - {{ t('worker.summary.phoneExtension') }} + <VnLv :label="t('worker.summary.phoneExtension')"> + <template #value> <VnLinkPhone :phone-number="worker.mobileExtension" /> </template> </VnLv> - <VnLv :value="worker.phone"> - <template #label> - {{ t('worker.summary.entPhone') }} + <VnLv :label="t('worker.summary.entPhone')"> + <template #value> <VnLinkPhone :phone-number="worker.phone" /> </template> </VnLv> - <VnLv :value="advancedSummary?.client?.phone"> - <template #label> - {{ t('worker.summary.personalPhone') }} + <VnLv :label="t('worker.summary.personalPhone')"> + <template #value> <VnLinkPhone :phone-number="advancedSummary?.client?.phone" /> @@ -147,9 +144,8 @@ onBeforeMount(async () => { </span> </template> </VnLv> - <VnLv :value="worker?.sip?.extension"> - <template #label> - {{ t('worker.summary.sipExtension') }} + <VnLv :label="t('worker.summary.sipExtension')"> + <template #value> <VnLinkPhone :phone-number="worker?.sip?.extension" /> </template> </VnLv> From 0208debdbefee208764c9ec27ade547d2f88ea5b Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Mon, 31 Mar 2025 15:15:07 +0200 Subject: [PATCH 40/65] feat: worker vnLinkPhone --- src/pages/Worker/Card/WorkerDescriptor.vue | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue index 060520e84..0f09c0a97 100644 --- a/src/pages/Worker/Card/WorkerDescriptor.vue +++ b/src/pages/Worker/Card/WorkerDescriptor.vue @@ -128,15 +128,13 @@ const handlePhotoUpdated = (evt = false) => { </template> </VnLv> - <VnLv :value="entity.phone"> - <template #label> - {{ t('globals.phone') }} + <VnLv :label="t('globals.phone')"> + <template #value> <VnLinkPhone :phone-number="entity.phone" /> </template> </VnLv> - <VnLv :value="entity?.sip?.extension"> - <template #label> - {{ t('worker.summary.sipExtension') }} + <VnLv :label="t('worker.summary.sipExtension')"> + <template #value> <VnLinkPhone :phone-number="entity?.sip?.extension" /> </template> </VnLv> From dd739b11650802e6090f63d3578ef647cd8fdc21 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Mon, 31 Mar 2025 15:15:17 +0200 Subject: [PATCH 41/65] fix: customer vnLinkPhone --- src/pages/Customer/Card/CustomerSummary.vue | 33 +++++++++++---------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue index 7d5d691a3..04246c39c 100644 --- a/src/pages/Customer/Card/CustomerSummary.vue +++ b/src/pages/Customer/Card/CustomerSummary.vue @@ -84,27 +84,28 @@ const sumRisk = ({ clientRisks }) => { <VnLv :label="t('customer.summary.customerId')" :value="entity.id" /> <VnLv :label="t('globals.name')" :value="entity.name" /> <VnLv :label="t('customer.summary.contact')" :value="entity.contact" /> - <VnLv :value="entity.phone"> - <template #label> - {{ t('customer.extendedList.tableVisibleColumns.phone') }} + <VnLv :label="t('customer.extendedList.tableVisibleColumns.phone')"> + <template #value> <VnLinkPhone :phone-number="entity.phone" /> </template> </VnLv> - <VnLv :value="entity.mobile"> - <template #label> - {{ t('customer.summary.mobile') }} - <VnLinkPhone :phone-number="entity.mobile" /> - <VnLinkPhone - say-simple - :phone-number="entity.mobile" - :channel="entity.country?.saySimpleCountry?.channel" - class="q-ml-xs" - /> + <VnLv :label="t('customer.summary.mobile')"> + <template #value> + <div class="col"> + <VnLinkPhone :phone-number="entity.mobile" /> + </div> + <div class="col"> + <VnLinkPhone + say-simple + :phone-number="entity.mobile" + :channel="entity.country?.saySimpleCountry?.channel" + class="q-ml-xs" + /> + </div> </template> </VnLv> - <VnLv :value="entity.email" copy - ><template #label> - {{ t('globals.params.email') }} + <VnLv :label="t('globals.params.email')" + ><template #value> <VnLinkMail email="entity.email"></VnLinkMail> </template ></VnLv> <VnLv :label="t('globals.department')"> From 19121fbeb988a83951bce220f02447d655e5f1e8 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Mon, 31 Mar 2025 15:15:29 +0200 Subject: [PATCH 42/65] fix: roadmap --- src/pages/Route/Roadmap/RoadmapSummary.vue | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/pages/Route/Roadmap/RoadmapSummary.vue b/src/pages/Route/Roadmap/RoadmapSummary.vue index 0c1c2b903..dcd02d98e 100644 --- a/src/pages/Route/Roadmap/RoadmapSummary.vue +++ b/src/pages/Route/Roadmap/RoadmapSummary.vue @@ -112,12 +112,9 @@ const filter = { :label="t('Trailer Plate')" :value="dashIfEmpty(entity?.trailerPlate)" /> - <VnLv :label="t('Phone')" :value="dashIfEmpty(entity?.phone)"> + <VnLv :label="t('Phone')"> <template #value> - <span> - {{ dashIfEmpty(entity?.phone) }} - <VnLinkPhone :phone-number="entity?.phone" /> - </span> + <VnLinkPhone :phone-number="entity?.phone" /> </template> </VnLv> <VnLv From d71029c7e9ebb9222096e6d8c2539ab8881c4826 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Mon, 31 Mar 2025 15:15:37 +0200 Subject: [PATCH 43/65] feat: dashIfEmpty --- src/components/ui/VnLinkPhone.vue | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/ui/VnLinkPhone.vue b/src/components/ui/VnLinkPhone.vue index 4174e4ae6..94b4b9d1c 100644 --- a/src/components/ui/VnLinkPhone.vue +++ b/src/components/ui/VnLinkPhone.vue @@ -1,7 +1,7 @@ <script setup> import { ref, reactive, useAttrs, onBeforeMount, capitalize } from 'vue'; import axios from 'axios'; -import { parsePhone } from 'src/filters'; +import { dashIfEmpty, parsePhone } from 'src/filters'; import useOpenURL from 'src/composables/useOpenURL'; const props = defineProps({ @@ -31,9 +31,8 @@ onBeforeMount(async () => { if (!channel) channel = defaultChannel; phone.value = await parsePhone(props.phoneNumber, props.country?.toLowerCase()); - config[ - type - ].url = `${url}?customerIdentity=%2B${phone.value}&channelId=${channel}`; + config[type].url = + `${url}?customerIdentity=%2B${phone.value}&channelId=${channel}`; } }); @@ -57,5 +56,6 @@ function handleClick() { {{ capitalize(type).replace('-', '') }} </QTooltip> </QBtn> - {{ phoneNumber }} + + <span>{{ dashIfEmpty(phone) }}</span> </template> From 044c60740598262ff5df383b53a63415d18bb401 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Tue, 1 Apr 2025 08:32:58 +0200 Subject: [PATCH 44/65] chore: update version to 25.16.0 in package.json --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 017412ef2..366e4bd36 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-front", - "version": "25.14.0", + "version": "25.16.0", "description": "Salix frontend", "productName": "Salix", "author": "Verdnatura", @@ -76,4 +76,4 @@ "vite": "^6.0.11", "vitest": "^0.31.1" } -} \ No newline at end of file +} From b00d89a4bee022b8810ff7b308332e8691cce30f Mon Sep 17 00:00:00 2001 From: Jon <jon@verdnatura.es> Date: Tue, 1 Apr 2025 09:34:38 +0200 Subject: [PATCH 45/65] perf: refs #7995 has acl function --- src/composables/useAcl.js | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/composables/useAcl.js b/src/composables/useAcl.js index 4033ee9a6..52704fee9 100644 --- a/src/composables/useAcl.js +++ b/src/composables/useAcl.js @@ -30,15 +30,10 @@ export function useAcl() { return false; } - function hasAcl(model, props, accessType) { + function hasAcl(model, prop, accessType) { const modelAcl = state.getAcls().value[model]; - const propAcl = modelAcl[props] || {}; - return !!( - propAcl[accessType] || - modelAcl['*']?.[accessType] || - propAcl['*'] || - modelAcl['*']?.['*'] - ); + const propAcl = modelAcl?.[prop] || modelAcl?.['*']; + return !!(propAcl?.[accessType] || propAcl?.['*']); } return { From 79fdaffbc8bd03740fbcf70178daea87671cc496 Mon Sep 17 00:00:00 2001 From: PAU ROVIRA ROSALENY <provira@verdnatura.es> Date: Tue, 1 Apr 2025 07:42:30 +0000 Subject: [PATCH 46/65] fix: fixed CustomerTicket table order --- src/pages/Customer/components/CustomerSummaryTable.vue | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/Customer/components/CustomerSummaryTable.vue b/src/pages/Customer/components/CustomerSummaryTable.vue index 09c7e714c..8d921ae69 100644 --- a/src/pages/Customer/components/CustomerSummaryTable.vue +++ b/src/pages/Customer/components/CustomerSummaryTable.vue @@ -49,7 +49,6 @@ const filter = { }, ], where: { clientFk: $props.id ?? route.params.id }, - order: ['shipped DESC', 'id'], limit: 30, }; @@ -191,7 +190,7 @@ const getItemPackagingType = (ticketSales) => { :without-header="true" auto-load :row-click="rowClick" - order="shipped DESC, id" + order="shipped DESC, id DESC" :disable-option="{ card: true, table: true }" class="full-width" :disable-infinite-scroll="true" From 35886999e465e124c8cbffbfb16e9167c846f419 Mon Sep 17 00:00:00 2001 From: PAU ROVIRA ROSALENY <provira@verdnatura.es> Date: Tue, 1 Apr 2025 07:54:41 +0000 Subject: [PATCH 47/65] fix: rollback --- src/pages/Customer/components/CustomerSummaryTable.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/Customer/components/CustomerSummaryTable.vue b/src/pages/Customer/components/CustomerSummaryTable.vue index 8d921ae69..feb137065 100644 --- a/src/pages/Customer/components/CustomerSummaryTable.vue +++ b/src/pages/Customer/components/CustomerSummaryTable.vue @@ -49,6 +49,7 @@ const filter = { }, ], where: { clientFk: $props.id ?? route.params.id }, + order: ['shipped DESC', 'id'], limit: 30, }; From 246e4429bde5b8e41d3996b0a400e8403bbde14e Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Tue, 1 Apr 2025 11:04:36 +0200 Subject: [PATCH 48/65] refactor: update getArrayData function to accept entityId for improved data fetching --- src/components/common/VnCard.vue | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/common/VnCard.vue b/src/components/common/VnCard.vue index 390906ab6..0b9cc2cce 100644 --- a/src/components/common/VnCard.vue +++ b/src/components/common/VnCard.vue @@ -26,7 +26,7 @@ const route = useRoute(); const stateStore = useStateStore(); const router = useRouter(); const entityId = computed(() => props.id || route?.params?.id); -let arrayData = getArrayData(props.url); +let arrayData = getArrayData(entityId.value, props.url); onBeforeRouteLeave(() => { stateStore.cardDescriptorChangeValue(null); @@ -59,7 +59,7 @@ onBeforeRouteUpdate(async (to, from) => { async function fetch(id, append = false) { if (props.idInWhere) arrayData.store.filter.where = { id }; else { - arrayData = getArrayData(); + arrayData = getArrayData(id); } await arrayData.fetch({ append, updateRouter: false }); emit('onFetch', arrayData.store.data); @@ -75,9 +75,9 @@ function formatUrl(id) { return props.url.replace(regex, `/${newId}`); } -function getArrayData(url = formatUrl()) { +function getArrayData(id, url) { return useArrayData(props.dataKey, { - url, + url: url ?? formatUrl(id), userFilter: props.filter, oneRecord: true, }); From da148c54352a7f8284e73cd628f2b2e47ae5469d Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Tue, 1 Apr 2025 11:56:05 +0200 Subject: [PATCH 49/65] test: skip invoice deletion test and add spinner waits in VnShortcuts --- test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js | 2 +- test/cypress/integration/vnComponent/VnShortcut.spec.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js b/test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js index 7058e154c..fdaa01876 100644 --- a/test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js +++ b/test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js @@ -13,7 +13,7 @@ describe('InvoiceInDescriptor', () => { cy.validateCheckbox(checkbox, false); }); - it('should delete the invoice properly', () => { + it.skip('should delete the invoice properly', () => { cy.visit('/#/invoice-in/2/summary'); cy.selectDescriptorOption(2); cy.clickConfirm(); diff --git a/test/cypress/integration/vnComponent/VnShortcut.spec.js b/test/cypress/integration/vnComponent/VnShortcut.spec.js index e08c44635..fa05e2e3d 100644 --- a/test/cypress/integration/vnComponent/VnShortcut.spec.js +++ b/test/cypress/integration/vnComponent/VnShortcut.spec.js @@ -27,12 +27,15 @@ describe('VnShortcuts', () => { code: `Key${shortcut.toUpperCase()}`, }); + cy.waitSpinner(); cy.url().should('include', module); if (['monitor', 'claim'].includes(module)) { return; } cy.waitForElement('.q-page').should('exist'); cy.dataCy('vnTableCreateBtn').should('exist'); + cy.waitSpinner(); + cy.get('.q-page').trigger('keydown', { ctrlKey: true, altKey: true, From 590afaba93afe428ab754552b8ac860083097d20 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Tue, 1 Apr 2025 12:39:26 +0200 Subject: [PATCH 50/65] fix: update condition for rendering QChip in VnOrder component --- src/components/VnTable/VnOrder.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/VnTable/VnOrder.vue b/src/components/VnTable/VnOrder.vue index d39fc8641..fe071a57f 100644 --- a/src/components/VnTable/VnOrder.vue +++ b/src/components/VnTable/VnOrder.vue @@ -70,7 +70,7 @@ function textAlignToFlex(textAlign) { :style="textAlignToFlex(align)" > <span :title="label">{{ label }}</span> - <div v-if="name"> + <div v-if="name && (model?.index || vertical)"> <QChip :label="!vertical ? model?.index : ''" :icon=" From 06e5188146b31b383314f28b626c9e5cc98e73e7 Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Tue, 1 Apr 2025 13:02:49 +0200 Subject: [PATCH 51/65] refactor: remove keepData property from components and update related logic --- src/components/common/VnSection.vue | 5 ----- src/components/ui/VnPaginate.vue | 2 +- src/composables/useArrayData.js | 3 +-- src/pages/Supplier/Card/SupplierDescriptor.vue | 2 +- src/pages/Travel/Card/TravelDescriptor.vue | 2 +- src/stores/useArrayDataStore.js | 1 - 6 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/components/common/VnSection.vue b/src/components/common/VnSection.vue index 4bd17124f..34eb14601 100644 --- a/src/components/common/VnSection.vue +++ b/src/components/common/VnSection.vue @@ -40,10 +40,6 @@ const $props = defineProps({ type: Boolean, default: true, }, - keepData: { - type: Boolean, - default: true, - }, }); const route = useRoute(); @@ -61,7 +57,6 @@ onBeforeMount(() => { if ($props.dataKey) arrayData = useArrayData($props.dataKey, { searchUrl: 'table', - keepData: $props.keepData, ...$props.arrayDataProps, navigate: $props.redirect, }); diff --git a/src/components/ui/VnPaginate.vue b/src/components/ui/VnPaginate.vue index 7facb7916..8fbfb067f 100644 --- a/src/components/ui/VnPaginate.vue +++ b/src/components/ui/VnPaginate.vue @@ -115,7 +115,7 @@ onMounted(async () => { }); onBeforeUnmount(() => { - if (!store.keepData) arrayData.reset(['data']); + arrayData.reset(['data']); arrayData.resetPagination(); }); diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js index 363580148..a17730754 100644 --- a/src/composables/useArrayData.js +++ b/src/composables/useArrayData.js @@ -56,7 +56,6 @@ export function useArrayData(key, userOptions) { 'searchUrl', 'navigate', 'mapKey', - 'keepData', 'oneRecord', ]; if (typeof userOptions === 'object') { @@ -108,7 +107,7 @@ export function useArrayData(key, userOptions) { store.hasMoreData = limit && response.data.length >= limit; if (!append && !isDialogOpened() && updateRouter) { - if (updateStateParams(response.data)?.redirect && !store.keepData) return; + if (updateStateParams(response.data)?.redirect) return; } store.isLoading = false; canceller = null; diff --git a/src/pages/Supplier/Card/SupplierDescriptor.vue b/src/pages/Supplier/Card/SupplierDescriptor.vue index 2863784ab..2511edf11 100644 --- a/src/pages/Supplier/Card/SupplierDescriptor.vue +++ b/src/pages/Supplier/Card/SupplierDescriptor.vue @@ -106,7 +106,7 @@ const getEntryQueryParams = (supplier) => { <QBtn :to="{ name: 'EntryList', - query: { params: JSON.stringify(getEntryQueryParams(entity)) }, + query: { table: JSON.stringify(getEntryQueryParams(entity)) }, }" size="md" icon="vn:entry" diff --git a/src/pages/Travel/Card/TravelDescriptor.vue b/src/pages/Travel/Card/TravelDescriptor.vue index d4903f794..d57046bae 100644 --- a/src/pages/Travel/Card/TravelDescriptor.vue +++ b/src/pages/Travel/Card/TravelDescriptor.vue @@ -66,7 +66,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.ref, entity. :to="{ name: 'TravelList', query: { - params: JSON.stringify({ + table: JSON.stringify({ agencyModeFk: entity.agencyModeFk, }), }, diff --git a/src/stores/useArrayDataStore.js b/src/stores/useArrayDataStore.js index b3996d1e3..569ff1c7e 100644 --- a/src/stores/useArrayDataStore.js +++ b/src/stores/useArrayDataStore.js @@ -18,7 +18,6 @@ export const useArrayDataStore = defineStore('arrayDataStore', () => { navigate: null, page: 1, mapKey: 'id', - keepData: false, oneRecord: false, }; From 588876952a5e5531b89f82d5087f2ebb91840a06 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Tue, 1 Apr 2025 14:51:24 +0200 Subject: [PATCH 52/65] fix: customerSummary --- src/pages/Customer/Card/CustomerSummary.vue | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue index 04246c39c..3e88cd5da 100644 --- a/src/pages/Customer/Card/CustomerSummary.vue +++ b/src/pages/Customer/Card/CustomerSummary.vue @@ -96,17 +96,20 @@ const sumRisk = ({ clientRisks }) => { </div> <div class="col"> <VnLinkPhone + sip say-simple :phone-number="entity.mobile" :channel="entity.country?.saySimpleCountry?.channel" - class="q-ml-xs" /> </div> </template> </VnLv> - <VnLv :label="t('globals.params.email')" - ><template #value> - <VnLinkMail email="entity.email"></VnLinkMail> </template + <VnLv + :label="t('globals.params.email')" + :value="entity.email" + class="ellipsis" + copy + ><template #value> <VnLinkMail :email="entity.email" /> </template ></VnLv> <VnLv :label="t('globals.department')"> <template #value> From 02a78c662bee2b3c7bf5545b805e4a926aee63d4 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Tue, 1 Apr 2025 14:51:49 +0200 Subject: [PATCH 53/65] perf: handle VnLinkMail and VnEmail --- src/components/ui/VnLinkMail.vue | 4 ++ src/components/ui/VnLinkPhone.vue | 69 +++++++++++++++++++------------ 2 files changed, 46 insertions(+), 27 deletions(-) diff --git a/src/components/ui/VnLinkMail.vue b/src/components/ui/VnLinkMail.vue index a54f463f5..6c5129a9b 100644 --- a/src/components/ui/VnLinkMail.vue +++ b/src/components/ui/VnLinkMail.vue @@ -1,8 +1,11 @@ <script setup> +import { dashIfEmpty } from 'src/filters'; + defineProps({ email: { type: [String], default: null } }); </script> <template> <QBtn + class="q-pr-xs" v-if="email" flat round @@ -13,4 +16,5 @@ defineProps({ email: { type: [String], default: null } }); :href="`mailto:${email}`" @click.stop /> + <span>{{ dashIfEmpty(email) }}</span> </template> diff --git a/src/components/ui/VnLinkPhone.vue b/src/components/ui/VnLinkPhone.vue index 94b4b9d1c..e34a70011 100644 --- a/src/components/ui/VnLinkPhone.vue +++ b/src/components/ui/VnLinkPhone.vue @@ -12,50 +12,65 @@ const props = defineProps({ const phone = ref(props.phoneNumber); const config = reactive({ - sip: { icon: 'phone', href: `sip:${props.phoneNumber}` }, 'say-simple': { icon: 'vn:saysimple', url: null, channel: props.channel, }, + sip: { icon: 'phone', href: `sip:${props.phoneNumber}` }, }); -const type = Object.keys(config).find((key) => key in useAttrs()) || 'sip'; + +const attrs = useAttrs(); +const types = Object.keys(config) + .filter((key) => key in attrs) + .sort(); +const activeTypes = types.length ? types : ['sip']; onBeforeMount(async () => { if (!phone.value) return; - let { channel } = config[type]; - if (type === 'say-simple') { - const { url, defaultChannel } = (await axios.get('SaySimpleConfigs/findOne')) - .data; - if (!channel) channel = defaultChannel; + for (const type of activeTypes) { + if (type === 'say-simple') { + let { channel } = config[type]; + const { url, defaultChannel } = (await axios.get('SaySimpleConfigs/findOne')) + .data; + if (!channel) channel = defaultChannel; - phone.value = await parsePhone(props.phoneNumber, props.country?.toLowerCase()); - config[type].url = - `${url}?customerIdentity=%2B${phone.value}&channelId=${channel}`; + phone.value = await parsePhone( + props.phoneNumber, + props.country?.toLowerCase(), + ); + config[type].url = + `${url}?customerIdentity=%2B${phone.value}&channelId=${channel}`; + } } }); -function handleClick() { +function handleClick(type) { if (config[type].url) useOpenURL(config[type].url); else if (config[type].href) window.location.href = config[type].href; } </script> -<template> - <QBtn - v-if="phone" - flat - round - :icon="config[type].icon" - size="sm" - color="primary" - padding="none" - @click.stop="handleClick" - > - <QTooltip> - {{ capitalize(type).replace('-', '') }} - </QTooltip> - </QBtn> - <span>{{ dashIfEmpty(phone) }}</span> +<template> + <div class="flex items-center gap-2"> + <template v-for="type in activeTypes"> + <QBtn + :key="type" + v-if="phone" + flat + round + :icon="config[type].icon" + size="sm" + color="primary" + padding="none" + @click.stop="() => handleClick(type)" + > + <QTooltip> + {{ capitalize(type).replace('-', '') }} + </QTooltip> + </QBtn></template + > + <span>{{ dashIfEmpty(phone) }}</span> + </div> </template> From 40cfe2a5cc8d3d92919d2340ba49db7d144a23fe Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Tue, 1 Apr 2025 14:52:05 +0200 Subject: [PATCH 54/65] style: add ellipsis class to CardSummary --- src/components/ui/CardSummary.vue | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/ui/CardSummary.vue b/src/components/ui/CardSummary.vue index 2ec6bea78..7ea91edca 100644 --- a/src/components/ui/CardSummary.vue +++ b/src/components/ui/CardSummary.vue @@ -159,6 +159,7 @@ async function fetch() { display: flex; flex-direction: row; margin-top: 2px; + align-items: start; .label { color: var(--vn-label-color); width: 9em; @@ -169,6 +170,10 @@ async function fetch() { flex-grow: 0; flex-shrink: 0; } + &.ellipsis > .value { + text-overflow: ellipsis; + white-space: pre; + } .value { color: var(--vn-text-color); overflow: hidden; From f02fa732ee7dad015868f2543893f353333ef0a9 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Tue, 1 Apr 2025 15:10:49 +0200 Subject: [PATCH 55/65] feat: remove unused vnLinkPhone --- src/pages/Customer/Card/CustomerSummary.vue | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue index 3e88cd5da..342643ec3 100644 --- a/src/pages/Customer/Card/CustomerSummary.vue +++ b/src/pages/Customer/Card/CustomerSummary.vue @@ -91,17 +91,12 @@ const sumRisk = ({ clientRisks }) => { </VnLv> <VnLv :label="t('customer.summary.mobile')"> <template #value> - <div class="col"> - <VnLinkPhone :phone-number="entity.mobile" /> - </div> - <div class="col"> - <VnLinkPhone - sip - say-simple - :phone-number="entity.mobile" - :channel="entity.country?.saySimpleCountry?.channel" - /> - </div> + <VnLinkPhone + sip + say-simple + :phone-number="entity.mobile" + :channel="entity.country?.saySimpleCountry?.channel" + /> </template> </VnLv> <VnLv From 2e6963d505e14a1c6fb3886439022cfb4ecaba6f Mon Sep 17 00:00:00 2001 From: jorgep <jorgep@verdnatura.es> Date: Wed, 2 Apr 2025 11:38:44 +0200 Subject: [PATCH 56/65] refactor: refs #8326 conditionally render vn-card-content based on advancedSummary --- src/pages/Worker/Card/WorkerSummary.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue index 40787613c..1da2b7d11 100644 --- a/src/pages/Worker/Card/WorkerSummary.vue +++ b/src/pages/Worker/Card/WorkerSummary.vue @@ -94,7 +94,7 @@ onBeforeMount(async () => { </template> </VnLv> </div> - <div class="vn-card-content"> + <div class="vn-card-content" v-if="advancedSummary"> <VnLv :label="t('worker.summary.fiDueDate')" :value="toDate(advancedSummary.fiDueDate)" From 87e56d9ff1a669a9bbf6243e121f1e3e040e0fe8 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Wed, 2 Apr 2025 11:39:02 +0200 Subject: [PATCH 57/65] fix: customer missing i18n --- src/pages/Customer/CustomerFilter.vue | 2 ++ src/pages/Customer/Notifications/CustomerNotifications.vue | 1 + 2 files changed, 3 insertions(+) diff --git a/src/pages/Customer/CustomerFilter.vue b/src/pages/Customer/CustomerFilter.vue index 58bc18344..4c8624102 100644 --- a/src/pages/Customer/CustomerFilter.vue +++ b/src/pages/Customer/CustomerFilter.vue @@ -162,6 +162,7 @@ en: city: City phone: Phone email: Email + departmentFk: Department isToBeMailed: Mailed isEqualizated: Equailized businessTypeFk: Business type @@ -177,6 +178,7 @@ es: search: Contiene fi: NIF isActive: Activo + departmentFk: Departamento isToBeMailed: A enviar isEqualizated: Recargo de equivalencia businessTypeFk: Tipo de negocio diff --git a/src/pages/Customer/Notifications/CustomerNotifications.vue b/src/pages/Customer/Notifications/CustomerNotifications.vue index b30ed6f76..cbbd6d205 100644 --- a/src/pages/Customer/Notifications/CustomerNotifications.vue +++ b/src/pages/Customer/Notifications/CustomerNotifications.vue @@ -127,6 +127,7 @@ es: Identifier: Identificador Social name: Razón social Phone: Teléfono + Postcode: Código postal City: Población Email: Email Campaign consumption: Consumo campaña From 74033a7bdf1532e737f35aa450d0d7dfd1ae5cb8 Mon Sep 17 00:00:00 2001 From: pablone <pablone@verdnatura.es> Date: Wed, 2 Apr 2025 11:51:03 +0200 Subject: [PATCH 58/65] refactor: improve layout and styling in ExtraCommunity.vue --- src/pages/Travel/ExtraCommunity.vue | 32 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/pages/Travel/ExtraCommunity.vue b/src/pages/Travel/ExtraCommunity.vue index ec898719d..849eeee5b 100644 --- a/src/pages/Travel/ExtraCommunity.vue +++ b/src/pages/Travel/ExtraCommunity.vue @@ -505,7 +505,6 @@ watch(route, () => { :props="props" @click="stopEventPropagation($event, col)" :style="col.style" - style="padding-left: 5px" > <component :is="tableColumnComponents[col.name].component" @@ -581,19 +580,20 @@ watch(route, () => { <QBtn dense flat class="link">{{ entry.id }} </QBtn> <EntryDescriptorProxy :id="entry.id" /> </QTd> - <QTd> - <QBtn flat class="link" dense>{{ entry.supplierName }}</QBtn> - <SupplierDescriptorProxy :id="entry.supplierFk" /> - </QTd> - <QTd class="text-center"> - <QIcon - v-if="entry.isCustomInspectionRequired" - name="warning" - color="negative" - size="md" - :title="t('extraCommunity.requiresInspection')" - > - </QIcon> + <QTd :colspan="2"> + <div style="display: flex"> + <span class="link"> + {{ entry.supplierName }} + <SupplierDescriptorProxy :id="entry.supplierFk" /> + </span> + <QIcon + v-if="entry.isCustomInspectionRequired" + name="warning" + color="negative" + size="md" + :title="t('extraCommunity.requiresInspection')" + /> + </div> </QTd> <QTd class="text-right"> <span>{{ toCurrency(entry.invoiceAmount) }}</span> @@ -639,9 +639,7 @@ watch(route, () => { &:nth-child(1) { max-width: 65px; } - &:nth-child(4) { - padding: 0; - } + padding: 0 5px 0; } thead > tr > th { padding: 3px; From 1e1715df1aadef727528bfa4a41e7e811a8f2b0d Mon Sep 17 00:00:00 2001 From: jorgep <jorgep@verdnatura.es> Date: Wed, 2 Apr 2025 12:37:16 +0200 Subject: [PATCH 59/65] test: refs #8441 enable invoice deletion test in invoiceInDescriptor.spec.js --- test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js b/test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js index fdaa01876..7058e154c 100644 --- a/test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js +++ b/test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js @@ -13,7 +13,7 @@ describe('InvoiceInDescriptor', () => { cy.validateCheckbox(checkbox, false); }); - it.skip('should delete the invoice properly', () => { + it('should delete the invoice properly', () => { cy.visit('/#/invoice-in/2/summary'); cy.selectDescriptorOption(2); cy.clickConfirm(); From 6debb64b2bb00c62b97177aa359a8f84080bdca5 Mon Sep 17 00:00:00 2001 From: pablone <pablone@verdnatura.es> Date: Wed, 2 Apr 2025 12:52:51 +0200 Subject: [PATCH 60/65] test: skip VnShortcuts and WorkerList test suites --- test/cypress/integration/vnComponent/VnShortcut.spec.js | 4 ++-- test/cypress/integration/worker/workerList.spec.js | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/test/cypress/integration/vnComponent/VnShortcut.spec.js b/test/cypress/integration/vnComponent/VnShortcut.spec.js index fa05e2e3d..cc5cacbe4 100644 --- a/test/cypress/integration/vnComponent/VnShortcut.spec.js +++ b/test/cypress/integration/vnComponent/VnShortcut.spec.js @@ -1,6 +1,6 @@ /// <reference types="cypress" /> - -describe('VnShortcuts', () => { +// https://redmine.verdnatura.es/issues/8848 +describe.skip('VnShortcuts', () => { const modules = { item: 'a', customer: 'c', diff --git a/test/cypress/integration/worker/workerList.spec.js b/test/cypress/integration/worker/workerList.spec.js index 0a45441c1..d964c3dc8 100644 --- a/test/cypress/integration/worker/workerList.spec.js +++ b/test/cypress/integration/worker/workerList.spec.js @@ -1,4 +1,5 @@ -describe('WorkerList', () => { +// https://redmine.verdnatura.es/issues/8848 +describe.skip('WorkerList', () => { const inputName = '.q-drawer .q-form input[aria-label="First Name"]'; const searchBtn = '.q-drawer button:nth-child(3)'; const descriptorTitle = '.descriptor .title span'; @@ -13,7 +14,7 @@ describe('WorkerList', () => { cy.intercept('GET', /\/api\/Workers\/summary+/).as('worker'); cy.get(searchBtn).click(); cy.wait('@worker').then(() => - cy.get(descriptorTitle).should('include.text', 'Jessica') + cy.get(descriptorTitle).should('include.text', 'Jessica'), ); }); }); From 6fd01a4d099b9432518cb2f376baa33e38413eee Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Wed, 2 Apr 2025 14:20:58 +0200 Subject: [PATCH 61/65] fix: remove duplicate departmentFk entries in CustomerFilter.vue --- src/pages/Customer/CustomerFilter.vue | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/Customer/CustomerFilter.vue b/src/pages/Customer/CustomerFilter.vue index 03033fd8e..c30b11528 100644 --- a/src/pages/Customer/CustomerFilter.vue +++ b/src/pages/Customer/CustomerFilter.vue @@ -158,7 +158,6 @@ en: departmentFk: Department isToBeMailed: Mailed isEqualizated: Equailized - departmentFk: Department businessTypeFk: Business type sageTaxTypeFk: Sage Tax Type sageTransactionTypeFk: Sage Tax Type @@ -173,7 +172,6 @@ es: search: Contiene fi: NIF isActive: Activo - departmentFk: Departamento isToBeMailed: A enviar isEqualizated: Recargo de equivalencia businessTypeFk: Tipo de negocio From a780786a2c30dfd6452089bda677e1a8188fc4b4 Mon Sep 17 00:00:00 2001 From: Javier Segarra <jsegarra@verdnatura.es> Date: Wed, 2 Apr 2025 14:27:07 +0200 Subject: [PATCH 62/65] style: select needs filled --- src/pages/Monitor/Ticket/MonitorTicketFilter.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Monitor/Ticket/MonitorTicketFilter.vue b/src/pages/Monitor/Ticket/MonitorTicketFilter.vue index aea47aa08..1cadd4cb4 100644 --- a/src/pages/Monitor/Ticket/MonitorTicketFilter.vue +++ b/src/pages/Monitor/Ticket/MonitorTicketFilter.vue @@ -198,7 +198,7 @@ const getLocale = (label) => { <QItemSection> <VnSelect dense - rounded + filled :label="t('globals.params.packing')" v-model="params.packing" url="ItemPackingTypes" From 00ed955577b7daeb8f801b86053b307be05bfa2a Mon Sep 17 00:00:00 2001 From: alexm <alexm@verdnatura.es> Date: Wed, 2 Apr 2025 14:39:23 +0200 Subject: [PATCH 63/65] fix: refs #8449 reset pagination in VnLog and bind all attributes in AccountDescriptorProxy --- src/components/common/VnLog.vue | 1 + src/pages/Account/Card/AccountDescriptorProxy.vue | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/common/VnLog.vue b/src/components/common/VnLog.vue index 0f5a162e3..e2f18866a 100644 --- a/src/components/common/VnLog.vue +++ b/src/components/common/VnLog.vue @@ -219,6 +219,7 @@ function filterByRecord(modelLog) { } async function applyFilter(params = {}) { + paginate.value.arrayData.resetPagination(); paginate.value.arrayData.applyFilter({ filter: {}, params: { originFk: route.params.id, ...params }, diff --git a/src/pages/Account/Card/AccountDescriptorProxy.vue b/src/pages/Account/Card/AccountDescriptorProxy.vue index de3220fea..6a4b3e267 100644 --- a/src/pages/Account/Card/AccountDescriptorProxy.vue +++ b/src/pages/Account/Card/AccountDescriptorProxy.vue @@ -6,7 +6,7 @@ import AccountSummary from './AccountSummary.vue'; <QPopupProxy style="max-width: 10px"> <AccountDescriptor v-if="$attrs.id" - v-bind="$attrs.id" + v-bind="$attrs" :summary="AccountSummary" :proxy-render="true" /> From 832646638be001f67ad2f1e1b9bd669825ac3d05 Mon Sep 17 00:00:00 2001 From: jorgep <jorgep@verdnatura.es> Date: Wed, 2 Apr 2025 14:50:17 +0200 Subject: [PATCH 64/65] fix: refs #5835 update ticket references to invoices in InvoiceInDescriptor and localization files --- src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue | 8 ++++---- src/pages/InvoiceIn/locale/en.yml | 1 + src/pages/InvoiceIn/locale/es.yml | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue index 3843f5bf7..a097d9610 100644 --- a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue +++ b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue @@ -26,7 +26,7 @@ const routes = reactive({ getSupplier: (id) => { return { name: 'SupplierCard', params: { id } }; }, - getTickets: (id) => { + getInvoices: (id) => { return { name: 'InvoiceInList', query: { @@ -135,11 +135,11 @@ async function setInvoiceCorrection(id) { </QBtn> <QBtn size="md" - icon="vn:ticket" + icon="vn:invoice" color="primary" - :to="routes.getTickets(entity.supplierFk)" + :to="routes.getInvoices(entity.supplierFk)" > - <QTooltip>{{ t('globals.ticketList') }}</QTooltip> + <QTooltip>{{ t('invoiceIn.descriptor.invoices') }}</QTooltip> </QBtn> <QBtn v-if=" diff --git a/src/pages/InvoiceIn/locale/en.yml b/src/pages/InvoiceIn/locale/en.yml index 548e6c201..0ab12e14c 100644 --- a/src/pages/InvoiceIn/locale/en.yml +++ b/src/pages/InvoiceIn/locale/en.yml @@ -14,6 +14,7 @@ invoiceIn: amount: Amount descriptor: ticketList: Ticket list + invoices: Supplier invoices descriptorMenu: book: Book unbook: Unbook diff --git a/src/pages/InvoiceIn/locale/es.yml b/src/pages/InvoiceIn/locale/es.yml index 142d95f92..e91f00a60 100644 --- a/src/pages/InvoiceIn/locale/es.yml +++ b/src/pages/InvoiceIn/locale/es.yml @@ -13,7 +13,7 @@ invoiceIn: awb: AWB amount: Importe descriptor: - ticketList: Listado de tickets + invoices: Facturas de proveedor descriptorMenu: book: Contabilizar unbook: Descontabilizar From b2ce75d2f6cd1c79bf72d9055be860c4db1c1896 Mon Sep 17 00:00:00 2001 From: jorgep <jorgep@verdnatura.es> Date: Wed, 2 Apr 2025 15:54:55 +0200 Subject: [PATCH 65/65] fix: refs #5835 update icon for invoice button in InvoiceInDescriptor --- src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue index a097d9610..a6a8f922d 100644 --- a/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue +++ b/src/pages/InvoiceIn/Card/InvoiceInDescriptor.vue @@ -135,7 +135,7 @@ async function setInvoiceCorrection(id) { </QBtn> <QBtn size="md" - icon="vn:invoice" + icon="vn:invoice-in" color="primary" :to="routes.getInvoices(entity.supplierFk)" >