diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue index d0e10aae3..a6e3be291 100644 --- a/src/components/VnTable/VnTable.vue +++ b/src/components/VnTable/VnTable.vue @@ -501,7 +501,7 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) { { + let wrapper; + let vm; + let state; + + beforeEach(() => { + wrapper = createWrapper(UserPanel, {}); + state = useState(); + state.setUser({ + id: 115, + name: 'itmanagement', + nickname: 'itManagementNick', + lang: 'en', + darkMode: false, + companyFk: 442, + warehouseFk: 1, + }); + wrapper = wrapper.wrapper; + vm = wrapper.vm; + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it('should fetch warehouses data on mounted', async () => { + const fetchData = wrapper.findComponent({ name: 'FetchData' }); + expect(fetchData.props('url')).toBe('Warehouses'); + expect(fetchData.props('autoLoad')).toBe(true); + }); + + it('should toggle dark mode correctly and update preferences', async () => { + await vm.saveDarkMode(true); + expect(axios.patch).toHaveBeenCalledWith('/UserConfigs/115', { darkMode: true }); + expect(vm.user.darkMode).toBe(true); + vm.updatePreferences(); + expect(vm.darkMode).toBe(true); + }); + + it('should change user language and update preferences', async () => { + const userLanguage = 'es'; + await vm.saveLanguage(userLanguage); + expect(axios.patch).toHaveBeenCalledWith('/VnUsers/115', { lang: userLanguage }); + expect(vm.user.lang).toBe(userLanguage); + vm.updatePreferences(); + expect(vm.locale).toBe(userLanguage); + }); + + it('should update user data', async () => { + const key = 'name'; + const value = 'itboss'; + await vm.saveUserData(key, value); + expect(axios.post).toHaveBeenCalledWith('UserConfigs/setUserConfig', { [key]: value }); + }); +}); diff --git a/src/components/ui/VnPaginate.vue b/src/components/ui/VnPaginate.vue index 7bb81591f..b067381f6 100644 --- a/src/components/ui/VnPaginate.vue +++ b/src/components/ui/VnPaginate.vue @@ -123,7 +123,7 @@ watch( () => props.data, () => { store.data = props.data; - } + }, ); watch( @@ -132,12 +132,12 @@ watch( if (!mounted.value) return; emit('onChange', data); }, - { immediate: true } + { immediate: true }, ); watch( () => [props.url, props.filter], - ([url, filter]) => mounted.value && fetch({ url, filter }) + ([url, filter]) => mounted.value && fetch({ url, filter }), ); const addFilter = async (filter, params) => { await arrayData.addFilter({ filter, params }); @@ -198,7 +198,7 @@ function endPagination() { async function onLoad(index, done) { if (!store.data || !mounted.value) return done(); - if (store.data.length === 0 || !props.url) return done(false); + if (store.data.length === 0 || !arrayData.store.url) return done(false); pagination.value.page = pagination.value.page + 1; diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml index db5d89f0b..3b6bf34f5 100644 --- a/src/i18n/locale/en.yml +++ b/src/i18n/locale/en.yml @@ -380,7 +380,7 @@ login: loginError: Invalid username or password fieldRequired: This field is required twoFactorRequired: Two-factor verification required -twoFactorRequired: +twoFactor: validate: Validate insert: Enter the verification code explanation: >- @@ -459,48 +459,6 @@ ticket: consigneeStreet: Street create: address: Address -invoiceOut: - card: - issued: Issued - customerCard: Customer card - ticketList: Ticket List - summary: - issued: Issued - dued: Due - booked: Booked - taxBreakdown: Tax breakdown - taxableBase: Taxable base - rate: Rate - fee: Fee - tickets: Tickets - totalWithVat: Amount - globalInvoices: - errors: - chooseValidClient: Choose a valid client - chooseValidCompany: Choose a valid company - chooseValidPrinter: Choose a valid printer - chooseValidSerialType: Choose a serial type - fillDates: Invoice date and the max date should be filled - invoiceDateLessThanMaxDate: Invoice date can not be less than max date - invoiceWithFutureDate: Exists an invoice with a future date - noTicketsToInvoice: There are not tickets to invoice - criticalInvoiceError: 'Critical invoicing error, process stopped' - invalidSerialTypeForAll: The serial type must be global when invoicing all clients - table: - addressId: Address id - streetAddress: Street - statusCard: - percentageText: '{getPercentage}% {getAddressNumber} of {getNAddresses}' - pdfsNumberText: '{nPdfs} of {totalPdfs} PDFs' - negativeBases: - clientId: Client Id - base: Base - active: Active - hasToInvoice: Has to Invoice - verifiedData: Verified Data - comercial: Comercial - errors: - downloadCsvFailed: CSV download failed department: chat: Chat bossDepartment: Boss Department diff --git a/src/pages/Customer/composables/getAddresses.js b/src/pages/Customer/composables/getAddresses.js index eecc0150b..e65e64455 100644 --- a/src/pages/Customer/composables/getAddresses.js +++ b/src/pages/Customer/composables/getAddresses.js @@ -1,8 +1,9 @@ import axios from 'axios'; -export async function getAddresses(clientId) { +export async function getAddresses(clientId, _filter = {}) { if (!clientId) return; const filter = { + ..._filter, fields: ['nickname', 'street', 'city', 'id'], where: { isActive: true }, order: 'nickname ASC', diff --git a/src/pages/Customer/composables/getClient.js b/src/pages/Customer/composables/getClient.js index ecacc67c0..3b9e811de 100644 --- a/src/pages/Customer/composables/getClient.js +++ b/src/pages/Customer/composables/getClient.js @@ -1,7 +1,8 @@ import axios from 'axios'; -export async function getClient(clientId) { +export async function getClient(clientId, _filter = {}) { const filter = { + ..._filter, include: { relation: 'defaultAddress', scope: { diff --git a/src/pages/Entry/EntryBuysTableDialog.vue b/src/pages/Entry/EntryBuysTableDialog.vue index a2d8c9117..86a9b018f 100644 --- a/src/pages/Entry/EntryBuysTableDialog.vue +++ b/src/pages/Entry/EntryBuysTableDialog.vue @@ -134,6 +134,7 @@ function downloadCSV(rows) { @click=" openReport(`Entries/${entityId}/labelSupplier`) " + data-cy="printLabelsBtn" /> diff --git a/src/pages/Order/Card/OrderCatalog.vue b/src/pages/Order/Card/OrderCatalog.vue index d7efdb726..4b3992f21 100644 --- a/src/pages/Order/Card/OrderCatalog.vue +++ b/src/pages/Order/Card/OrderCatalog.vue @@ -22,7 +22,6 @@ const catalogParams = { }; const arrayData = useArrayData(dataKey, { url: 'Orders/CatalogFilter', - limit: 50, userParams: catalogParams, }); const store = arrayData.store; @@ -66,7 +65,7 @@ function extractValueTags(items) { .filter((k) => /^value\d+$/.test(k)) .map((v) => x[v]) .filter((v) => v) - .sort() + .sort(), ); tagValue.value = resultValueTags; } @@ -76,7 +75,7 @@ watch( (val) => { extractTags(val); }, - { immediate: true } + { immediate: true }, ); diff --git a/src/pages/Route/Agency/composables/__tests__/getAgencies.spec.js b/src/pages/Route/Agency/composables/__tests__/getAgencies.spec.js index 9897173f1..ccf7872cb 100644 --- a/src/pages/Route/Agency/composables/__tests__/getAgencies.spec.js +++ b/src/pages/Route/Agency/composables/__tests__/getAgencies.spec.js @@ -3,14 +3,17 @@ import axios from 'axios'; import { getAgencies } from 'src/pages/Route/Agency/composables/getAgencies'; vi.mock('axios'); +const response = { data: [{ agencyModeFk: 'Agency1' }, { agencyModeFk: 'Agency2' }] }; +axios.get.mockResolvedValue(response); describe('getAgencies', () => { afterEach(() => { vi.clearAllMocks(); }); - const generateParams = (formData) => ({ + const generateParams = (formData, filter = {}) => ({ params: { + filter: JSON.stringify(filter), warehouseFk: formData.warehouseId, addressFk: formData.addressId, landed: formData.landed, @@ -23,10 +26,15 @@ describe('getAgencies', () => { addressId: '456', landed: 'true', }; + const filter = { + fields: ['nickname', 'street', 'city', 'id'], + where: { isActive: true }, + order: 'nickname ASC', + }; - await getAgencies(formData); + await getAgencies(formData, null, filter); - expect(axios.get).toHaveBeenCalledWith('Agencies/getAgenciesWithWarehouse', generateParams(formData)); + expect(axios.get).toHaveBeenCalledWith('Agencies/getAgenciesWithWarehouse', generateParams(formData, filter)); }); it('should not call API when formData is missing required landed field', async () => { @@ -52,4 +60,23 @@ describe('getAgencies', () => { expect(axios.get).not.toHaveBeenCalled(); }); + + it('should return options and agency when default agency is found', async () => { + const formData = { warehouseId: '123', addressId: '456', landed: 'true' }; + const client = { defaultAddress: { agencyModeFk: 'Agency1' } }; + + const { options, agency } = await getAgencies(formData, client); + + expect(options).toEqual(response.data); + expect(agency).toEqual(response.data[0]); + }); + + it('should return options and agency when client is not provided', async () => { + const formData = { warehouseId: '123', addressId: '456', landed: 'true' }; + + const { options, agency } = await getAgencies(formData); + + expect(options).toEqual(response.data); + expect(agency).toBeNull(); + }); }); diff --git a/src/pages/Route/Agency/composables/getAgencies.js b/src/pages/Route/Agency/composables/getAgencies.js index 7299d7e23..850f87456 100644 --- a/src/pages/Route/Agency/composables/getAgencies.js +++ b/src/pages/Route/Agency/composables/getAgencies.js @@ -1,12 +1,26 @@ import axios from 'axios'; +import agency from 'src/router/modules/agency'; -export async function getAgencies(formData) { +export async function getAgencies(formData, client, _filter = {}) { if (!formData.warehouseId || !formData.addressId || !formData.landed) return; + + const filter = { + ..._filter + }; + + let defaultAgency = null; let params = { + filter: JSON.stringify(filter), warehouseFk: formData.warehouseId, addressFk: formData.addressId, landed: formData.landed, }; - return await axios.get('Agencies/getAgenciesWithWarehouse', { params }); + const { data } = await axios.get('Agencies/getAgenciesWithWarehouse', { params }); + + if(data && client) { + defaultAgency = data.find((agency) => agency.agencyModeFk === client.defaultAddress.agencyModeFk ); + }; + + return {options: data, agency: defaultAgency} } diff --git a/src/pages/Ticket/Card/TicketDescriptorMenu.vue b/src/pages/Ticket/Card/TicketDescriptorMenu.vue index 89f7015d7..63e45c8ab 100644 --- a/src/pages/Ticket/Card/TicketDescriptorMenu.vue +++ b/src/pages/Ticket/Card/TicketDescriptorMenu.vue @@ -69,14 +69,16 @@ const onAddressSelected = (addressId) => { } const fetchClient = async () => { - const { data } = await getClient(client.value) - const [retrievedClient] = data; + const response = await getClient(client.value) + if (!response) return; + const [retrievedClient] = response.data; selectedClient.value = retrievedClient; }; const fetchAddresses = async () => { - const { data } = await getAddresses(client.value); - addressesOptions.value = data; + const response = await getAddresses(client.value); + if (!response) return; + addressesOptions.value = response.data; const { defaultAddress } = selectedClient.value; address.value = defaultAddress.id; diff --git a/src/pages/Ticket/TicketCreate.vue b/src/pages/Ticket/TicketCreate.vue index 4c32448e4..96d200547 100644 --- a/src/pages/Ticket/TicketCreate.vue +++ b/src/pages/Ticket/TicketCreate.vue @@ -38,35 +38,43 @@ onBeforeMount(async () => { await onClientSelected(initialFormState); }); +function resetAgenciesSelector(formData) { + agenciesOptions.value = []; + formData.agencyModeId = null; +} + const fetchClient = async (formData) => { - const { data } = await getClient(formData.clientId); - const [client] = data; + const response = await getClient(formData.clientId); + if (!response) return; + const [client] = response.data; selectedClient.value = client; }; const fetchAddresses = async (formData) => { - const { data } = await getAddresses(formData.clientId); - addressesOptions.value = data; + const response = await getAddresses(formData.clientId); + if (!response) return; + addressesOptions.value = response.data; const { defaultAddress } = selectedClient.value; formData.addressId = defaultAddress.id; }; const onClientSelected = async (formData) => { + resetAgenciesSelector(formData); await fetchClient(formData); await fetchAddresses(formData); }; const fetchAvailableAgencies = async (formData) => { - const { data } = await getAgencies(formData); - agenciesOptions.value = data; - - const defaultAgency = agenciesOptions.value.find( - (agency) => - agency.agencyModeFk === selectedClient.value.defaultAddress.agencyModeFk - ); - - if (defaultAgency) formData.agencyModeId = defaultAgency.agencyModeFk; + resetAgenciesSelector(formData); + const response= await getAgencies(formData, selectedClient.value); + if (!response) return; + + const { options, agency } = response + if(options) + agenciesOptions.value = options; + if(agency) + formData.agencyModeId = agency; }; const redirectToTicketList = (_, { id }) => { diff --git a/src/pages/Ticket/TicketCreateDialog.vue b/src/pages/Ticket/TicketCreateDialog.vue index c8b126d7d..2245c5c81 100644 --- a/src/pages/Ticket/TicketCreateDialog.vue +++ b/src/pages/Ticket/TicketCreateDialog.vue @@ -38,35 +38,43 @@ onBeforeMount(async () => { await onClientSelected(initialFormState); }); +function resetAgenciesSelector(formData) { + agenciesOptions.value = []; + if(formData) formData.agencyModeId = null; +} + const fetchClient = async (formData) => { - const { data } = await getClient(formData.clientId); - const [client] = data; + const response = await getClient(formData.clientId); + if (!response) return; + const [client] = response.data; selectedClient.value = client; }; const fetchAddresses = async (formData) => { - const { data } = await getAddresses(formData.clientId); - addressesOptions.value = data; + const response = await getAddresses(formData.clientId); + if (!response) return; + addressesOptions.value = response.data; const { defaultAddress } = selectedClient.value; formData.addressId = defaultAddress.id; }; const onClientSelected = async (formData) => { + resetAgenciesSelector(formData); await fetchClient(formData); await fetchAddresses(formData); }; const fetchAvailableAgencies = async (formData) => { - const { data } = await getAgencies(formData); - agenciesOptions.value = data; - - const defaultAgency = agenciesOptions.value.find( - (agency) => - agency.agencyModeFk === selectedClient.value.defaultAddress.agencyModeFk - ); - - if (defaultAgency) formData.agencyModeId = defaultAgency.agencyModeFk; + resetAgenciesSelector(formData); + const response= await getAgencies(formData, selectedClient.value); + if (!response) return; + + const { options, agency } = response + if(options) + agenciesOptions.value = options; + if(agency) + formData.agencyModeId = agency; }; const redirectToTicketList = (_, { id }) => { diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue index 8cf1184eb..8df19c0d9 100644 --- a/src/pages/Ticket/TicketList.vue +++ b/src/pages/Ticket/TicketList.vue @@ -229,37 +229,46 @@ const columns = computed(() => [ ], }, ]); + +function resetAgenciesSelector(formData) { + agenciesOptions.value = []; + if(formData) formData.agencyModeId = null; +} + function redirectToLines(id) { const url = `#/ticket/${id}/sale`; window.open(url, '_blank'); } -const onClientSelected = async (formData) => { +const onClientSelected = async (formData) => { + resetAgenciesSelector(formData); await fetchClient(formData); await fetchAddresses(formData); }; const fetchAvailableAgencies = async (formData) => { - const { data } = await getAgencies(formData); - agenciesOptions.value = data; - - const defaultAgency = agenciesOptions.value.find( - (agency) => - agency.agencyModeFk === selectedClient.value.defaultAddress.agencyModeFk - ); - - if (defaultAgency) formData.agencyModeId = defaultAgency.agencyModeFk; + resetAgenciesSelector(formData); + const response= await getAgencies(formData, selectedClient.value); + if (!response) return; + + const { options, agency } = response + if(options) + agenciesOptions.value = options; + if(agency) + formData.agencyModeId = agency; }; const fetchClient = async (formData) => { - const { data } = await getClient(formData.clientId); - const [client] = data; + const response = await getClient(formData.clientId); + if (!response) return; + const [client] = response.data; selectedClient.value = client; }; const fetchAddresses = async (formData) => { - const { data } = await getAddresses(formData.clientId); - addressesOptions.value = data; + const response = await getAddresses(formData.clientId); + if (!response) return; + addressesOptions.value = response.data; const { defaultAddress } = selectedClient.value; formData.addressId = defaultAddress.id; diff --git a/test/cypress/integration/entry/myEntry.spec.js b/test/cypress/integration/entry/myEntry.spec.js index c25476419..492e1b491 100644 --- a/test/cypress/integration/entry/myEntry.spec.js +++ b/test/cypress/integration/entry/myEntry.spec.js @@ -8,12 +8,12 @@ describe('EntryMy when is supplier', () => { }, }); }); - // https://redmine.verdnatura.es/issues/8418 - it.skip('should open buyLabel when is supplier', () => { + + it('should open buyLabel when is supplier', () => { cy.get( '[to="/null/3"] > .q-card > .column > .q-btn > .q-btn__content > .q-icon' ).click(); - cy.get('.q-card__actions > .q-btn').click(); + cy.dataCy('printLabelsBtn').click(); cy.window().its('open').should('be.called'); }); });