diff --git a/CHANGELOG.md b/CHANGELOG.md index 58b68b7fa..10b7c73f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,41 @@ +# Version 25.08 - 2025-03-04 + +### Added 🆕 + +- feat: add order for table (origin/8681_ticketAdvance_updates) by:Javier Segarra +- feat: detect when is descriptor proxy by:Javier Segarra +- feat: refs #7356 update CrudModel by:Javier Segarra +- feat: refs #8242 remove teleport by:Javier Segarra +- feat: refs #8242 use stateStore by:Javier Segarra +- fix: fixed negative bases style by:Jon +- fix: fixed style when clicking on icons by:Jon +- refactor: refs #6897 remove debug logs and unused style (origin/6897-fixSomeCaus) by:pablone +- style: refs #7356 eslint format by:Javier Segarra + +### Changed 📦 + +- perf: refs #7356 minor changes (origin/7356_ticketService) by:Javier Segarra +- refactor: refs #6897 remove debug logs and unused style (origin/6897-fixSomeCaus) by:pablone +- refactor: refs #6897 update component props and attributes for consistency and improved functionality (origin/6897-fixMinorIssues) by:pablone +- refactor: refs #6897 update component props and improve UI handling in Entry pages by:pablone +- refactor: refs #6897 update VnTable components for improved value handling and UI adjustments (origin/6897-minorFixes) by:pablone +- refactor: refs #8697 simplify date handling in ItemDiary component by:pablone + +### Fixed 🛠️ + +- fix: add datakey by:Javier Segarra +- fix: fixed account descriptor menu and created e2e by:Jon +- fix: fixed negative bases style by:Jon +- fix: fixed style when clicking on icons by:Jon +- fix: refs #6553 workerBusiness (origin/6553-fixWorkerBusinessV2) by:carlossa +- fix: refs #6553 workerBusiness v3 by:carlossa +- fix: refs #6897 prevent default event behavior in autocompleteExpense function by:pablone +- fix: refs #7356 chaining params by:Javier Segarra +- fix: refs #7356 ticketService by:Javier Segarra +- fix: refs #8242 workerDepartmentTree bug (origin/8242_leftMenu_responsive) by:Javier Segarra +- fix: workerBasicData by:carlossa +- Revert "revert 1015acefb7e400be2d8b5958dba69b4d98276b34" (origin/fix_revert_revert, fix_revert_revert) by:alexm + # Version 25.06 - 2025-02-18 ### Added 🆕 diff --git a/src/components/TicketProblems.vue b/src/components/TicketProblems.vue index 783f2556f..a537174c3 100644 --- a/src/components/TicketProblems.vue +++ b/src/components/TicketProblems.vue @@ -17,6 +17,17 @@ 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?.risk" name="vn:risk" diff --git a/src/components/ui/VnNotes.vue b/src/components/ui/VnNotes.vue index ec6289a67..6740934d4 100644 --- a/src/components/ui/VnNotes.vue +++ b/src/components/ui/VnNotes.vue @@ -26,12 +26,13 @@ const $attrs = computed(() => { }); const isRequired = computed(() => { - return Object.keys($attrs).includes('required') + return Object.keys($attrs).includes('required'); }); const $props = defineProps({ url: { type: String, default: null }, - saveUrl: {type: String, default: null}, + saveUrl: { type: String, default: null }, + userFilter: { type: Object, default: () => {} }, filter: { type: Object, default: () => {} }, body: { type: Object, default: () => {} }, addNote: { type: Boolean, default: false }, @@ -65,7 +66,7 @@ async function insert() { } function confirmAndUpdate() { - if(!newNote.text && originalText) + if (!newNote.text && originalText) quasar .dialog({ component: VnConfirm, @@ -88,11 +89,17 @@ async function update() { ...body, ...{ notes: newNote.text }, }; - await axios.patch(`${$props.saveUrl ?? `${$props.url}/${$props.body.workerFk}`}`, newBody); + await axios.patch( + `${$props.saveUrl ?? `${$props.url}/${$props.body.workerFk}`}`, + newBody, + ); } onBeforeRouteLeave((to, from, next) => { - if ((newNote.text && !$props.justInput) || (newNote.text !== originalText) && $props.justInput) + if ( + (newNote.text && !$props.justInput) || + (newNote.text !== originalText && $props.justInput) + ) quasar.dialog({ component: VnConfirm, componentProps: { @@ -104,12 +111,11 @@ onBeforeRouteLeave((to, from, next) => { else next(); }); -function fetchData([ data ]) { +function fetchData([data]) { newNote.text = data?.notes; originalText = data?.notes; emit('onFetch', data); } - </script> <template> <FetchData @@ -126,8 +132,8 @@ function fetchData([ data ]) { @on-fetch="fetchData" auto-load /> - <QCard - class="q-pa-xs q-mb-lg full-width" + <QCard + class="q-pa-xs q-mb-lg full-width" :class="{ 'just-input': $props.justInput }" v-if="$props.addNote || $props.justInput" > @@ -179,7 +185,8 @@ function fetchData([ data ]) { :url="$props.url" order="created DESC" :limit="0" - :user-filter="$props.filter" + :user-filter="userFilter" + :filter="filter" auto-load ref="vnPaginateRef" class="show" @@ -218,7 +225,7 @@ function fetchData([ data ]) { > {{ observationTypes.find( - (ot) => ot.id === note.observationTypeFk + (ot) => ot.id === note.observationTypeFk, )?.description }} </QBadge> diff --git a/src/pages/Claim/Card/ClaimNotes.vue b/src/pages/Claim/Card/ClaimNotes.vue index cc6e33779..68cb220ee 100644 --- a/src/pages/Claim/Card/ClaimNotes.vue +++ b/src/pages/Claim/Card/ClaimNotes.vue @@ -1,5 +1,5 @@ <script setup> -import { computed, useAttrs } from 'vue'; +import { computed } from 'vue'; import { useRoute } from 'vue-router'; import { useState } from 'src/composables/useState'; import VnNotes from 'src/components/ui/VnNotes.vue'; @@ -7,7 +7,6 @@ import VnNotes from 'src/components/ui/VnNotes.vue'; const route = useRoute(); const state = useState(); const user = state.getUser(); -const $attrs = useAttrs(); const $props = defineProps({ id: { type: [Number, String], default: null }, @@ -15,24 +14,21 @@ const $props = defineProps({ }); const claimId = computed(() => $props.id || route.params.id); -const claimFilter = computed(() => { - return { - where: { claimFk: claimId.value }, - fields: ['id', 'created', 'workerFk', 'text'], - include: { - relation: 'worker', - scope: { - fields: ['id', 'firstName', 'lastName'], - include: { - relation: 'user', - scope: { - fields: ['id', 'nickname', 'name'], - }, +const claimFilter = { + fields: ['id', 'created', 'workerFk', 'text'], + include: { + relation: 'worker', + scope: { + fields: ['id', 'firstName', 'lastName'], + include: { + relation: 'user', + scope: { + fields: ['id', 'nickname', 'name'], }, }, }, - }; -}); + }, +}; const body = { claimFk: claimId.value, @@ -43,7 +39,8 @@ const body = { <VnNotes url="claimObservations" :add-note="$props.addNote" - :filter="claimFilter" + :user-filter="claimFilter" + :filter="{ where: { claimFk: claimId } }" :body="body" v-bind="$attrs" style="overflow-y: auto" diff --git a/src/pages/Customer/Card/CustomerNotes.vue b/src/pages/Customer/Card/CustomerNotes.vue index 189b59904..5a078b0cb 100644 --- a/src/pages/Customer/Card/CustomerNotes.vue +++ b/src/pages/Customer/Card/CustomerNotes.vue @@ -1,28 +1,15 @@ <script setup> -import { computed } from 'vue'; -import { useRoute } from 'vue-router'; import VnNotes from 'src/components/ui/VnNotes.vue'; - -const route = useRoute(); - -const noteFilter = computed(() => { - return { - order: 'created DESC', - where: { - clientFk: `${route.params.id}`, - }, - }; -}); </script> - <template> <VnNotes url="clientObservations" :add-note="true" - :filter="noteFilter" - :body="{ clientFk: route.params.id }" + :filter="{ where: { clientFk: $route.params.id } }" + :body="{ clientFk: $route.params.id }" style="overflow-y: auto" :select-type="true" required + order="created DESC" /> </template> diff --git a/src/pages/Worker/Card/WorkerNotes.vue b/src/pages/Worker/Card/WorkerNotes.vue index 4f123206b..da274f3fa 100644 --- a/src/pages/Worker/Card/WorkerNotes.vue +++ b/src/pages/Worker/Card/WorkerNotes.vue @@ -5,9 +5,9 @@ import VnNotes from 'src/components/ui/VnNotes.vue'; const route = useRoute(); -const filter = { +const userFilter = { order: 'created DESC', - where: { workerFk: route.params.id }, + include: { relation: 'worker', scope: { @@ -22,11 +22,15 @@ const filter = { }, }; -const body = { - workerFk: route.params.id, -}; +const body = { workerFk: route.params.id }; </script> <template> - <VnNotes :add-note="true" url="WorkerObservations" :filter="filter" :body="body" /> + <VnNotes + :add-note="true" + url="WorkerObservations" + :user-filter="userFilter" + :filter="{ where: { workerFk: $route.params.id } }" + :body="body" + /> </template> diff --git a/test/cypress/integration/ticket/ticketFilter.spec.js b/test/cypress/integration/ticket/ticketFilter.spec.js index 659a9f83c..2e5a3f3ce 100644 --- a/test/cypress/integration/ticket/ticketFilter.spec.js +++ b/test/cypress/integration/ticket/ticketFilter.spec.js @@ -8,43 +8,8 @@ describe('TicketFilter', () => { it('use search button', function () { cy.waitForElement('.q-page'); - cy.intercept('GET', /\/api\/Tickets\/filter/).as('ticketFilter'); + cy.get('[data-cy="Customer ID_input"]').type('1105'); cy.searchBtnFilterPanel(); - cy.waitRequest('@ticketFilter', ({ request }) => { - const { query } = request; - expect(query).to.have.property('from'); - expect(query).to.have.property('to'); - }); - cy.on('uncaught:exception', () => { - return false; - }); - cy.get('.q-field__control-container > [data-cy="From_date"]') - .type(`${today()} `) - .type('{enter}'); - cy.get('.q-notification').should( - 'contain', - `The date range must have both 'from' and 'to'`, - ); - - cy.get('.q-field__control-container > [data-cy="To_date"]').type( - `${today()}{enter}`, - ); - cy.intercept('GET', /\/api\/Tickets\/filter/).as('ticketFilter'); - cy.searchBtnFilterPanel(); - cy.wait('@ticketFilter').then(({ request }) => { - const { query } = request; - expect(query).to.have.property('from'); - expect(query).to.have.property('to'); - }); - cy.location('href').should('contain', '#/ticket/999999'); + cy.location('href').should('contain', '#/ticket/15/summary'); }); }); -function today(date) { - // return new Date().toISOString().split('T')[0]; - - return new Intl.DateTimeFormat('es-ES', { - day: '2-digit', - month: '2-digit', - year: 'numeric', - }).format(date ?? new Date()); -} diff --git a/test/cypress/integration/ticket/ticketList.spec.js b/test/cypress/integration/ticket/ticketList.spec.js index 6a6dc24af..c9b3092a8 100644 --- a/test/cypress/integration/ticket/ticketList.spec.js +++ b/test/cypress/integration/ticket/ticketList.spec.js @@ -11,12 +11,12 @@ describe('TicketList', () => { const searchResults = (search) => { if (search) cy.typeSearchbar().type(search); cy.dataCy('vn-searchbar').find('input').type('{enter}'); - cy.dataCy('ticketListTable').should('exist'); + // cy.dataCy('ticketListTable').should('exist'); cy.get(firstRow).should('exist'); }; it('should search results', () => { - cy.dataCy('ticketListTable').should('not.exist'); + // cy.dataCy('ticketListTable').should('not.exist'); cy.get('.q-field__control').should('exist'); searchResults(); }); @@ -40,21 +40,11 @@ describe('TicketList', () => { it('filter client and create ticket', () => { cy.intercept('GET', /\/api\/Tickets\/filter/).as('ticketSearchbar'); searchResults(); - cy.wait('@ticketSearchbar').then(({ request }) => { - const { query } = request; - expect(query).to.have.property('from'); - expect(query).to.have.property('to'); - expect(query).to.not.have.property('clientFk'); - }); + cy.intercept('GET', /\/api\/Tickets\/filter/).as('ticketFilter'); cy.dataCy('Customer ID_input').clear('1'); cy.dataCy('Customer ID_input').type('1101{enter}'); - cy.wait('@ticketFilter').then(({ request }) => { - const { query } = request; - expect(query).to.not.have.property('from'); - expect(query).to.not.have.property('to'); - expect(query).to.have.property('clientFk'); - }); + cy.get('[data-cy="vnTableCreateBtn"] > .q-btn__content > .q-icon').click(); cy.dataCy('Customer_select').should('have.value', 'Bruce Wayne'); cy.dataCy('Address_select').click(); diff --git a/test/cypress/integration/ticket/ticketSale.spec.js b/test/cypress/integration/ticket/ticketSale.spec.js index b59765ca6..b8a0c83b5 100644 --- a/test/cypress/integration/ticket/ticketSale.spec.js +++ b/test/cypress/integration/ticket/ticketSale.spec.js @@ -6,6 +6,7 @@ describe('TicketSale', () => { cy.login('developer'); cy.viewport(1920, 1080); cy.visit('/#/ticket/31/sale'); + cy.domContentLoad(); }); const firstRow = 'tbody > :nth-child(1)'; @@ -112,7 +113,6 @@ describe('TicketSale', () => { cy.dataCy('ticketSaleTransferBtn').click(); cy.dataCy('ticketTransferPopup').should('exist'); cy.dataCy('ticketTransferNewTicketBtn').click(); - //check the new ticket has been created succesfully cy.get('.q-item > .q-item__label').should('not.have.text', ' #32'); }); @@ -138,7 +138,7 @@ describe('TicketSale', () => { it('update price', () => { const price = Number((Math.random() * 99 + 1).toFixed(2)); cy.waitForElement(firstRow); - cy.get(':nth-child(10) > .q-btn').click(); + cy.get('[data-col-field="price"]').find('.q-btn').click(); cy.waitForElement('[data-cy="ticketEditManaProxy"]'); cy.dataCy('ticketEditManaProxy').should('exist'); cy.waitForElement('[data-cy="Price_input"]'); @@ -147,15 +147,14 @@ describe('TicketSale', () => { cy.dataCy('saveManaBtn').click(); handleVnConfirm(); - cy.get(':nth-child(10) > .q-btn > .q-btn__content').should( - 'have.text', - `€${price}`, - ); + cy.get('[data-col-field="price"]') + .find('.q-btn > .q-btn__content') + .should('have.text', `€${price}`); }); - it('update dicount', () => { + it('update discount', () => { const discount = Math.floor(Math.random() * 100) + 1; selectFirstRow(); - cy.get(':nth-child(11) > .q-btn').click(); + cy.get('[data-col-field="discount"]').find('.q-btn').click(); cy.waitForElement('[data-cy="ticketEditManaProxy"]'); cy.dataCy('ticketEditManaProxy').should('exist'); cy.waitForElement('[data-cy="Disc_input"]'); @@ -164,26 +163,24 @@ describe('TicketSale', () => { cy.dataCy('saveManaBtn').click(); handleVnConfirm(); - cy.get(':nth-child(11) > .q-btn > .q-btn__content').should( - 'have.text', - `${discount}.00%`, - ); + cy.get('[data-col-field="discount"]') + .find('.q-btn > .q-btn__content') + .should('have.text', `${discount}.00%`); }); it('change concept', () => { - const quantity = Math.floor(Math.random() * 100) + 1; + const concept = Math.floor(Math.random() * 100) + 1; cy.waitForElement(firstRow); - cy.get(':nth-child(8) > .row').click(); - cy.get( - '.q-menu > [data-v-ca3f07a4=""] > .q-field > .q-field__inner > .q-field__control > .q-field__control-container > [data-cy="undefined_input"]', - ) - .type(quantity) + cy.get('[data-col-field="item"]').click(); + cy.get('.q-menu') + .find('[data-cy="undefined_input"]') + .type(concept) .type('{enter}'); handleVnConfirm(); - cy.get(':nth-child(8) >.row').should('contain.text', `${quantity}`); + cy.get('[data-col-field="item"]').should('contain.text', `${concept}`); }); - it('changequantity ', () => { + it('change quantity ', () => { const quantity = Math.floor(Math.random() * 100) + 1; cy.waitForElement(firstRow); cy.dataCy('ticketSaleQuantityInput').clear(); @@ -200,7 +197,7 @@ describe('TicketSale', () => { }); function handleVnConfirm() { - cy.get('[data-cy="VnConfirm_confirm"] > .q-btn__content > .block').click(); + cy.get('[data-cy="VnConfirm_confirm"]').click(); cy.waitForElement('.q-notification__message'); cy.get('.q-notification__message').should('be.visible');