0
0
Fork 0

Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into feature/ItemsList

This commit is contained in:
William Buezas 2024-04-10 08:46:00 -03:00
commit eceb60f6e4
17 changed files with 171 additions and 66 deletions

View File

@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
### Fixed
- (General) => Se vuelven a mostrar los parámetros en la url al aplicar un filtro
## [2414.01] - 2024-04-04 ## [2414.01] - 2024-04-04
### Added ### Added

View File

@ -3,6 +3,7 @@ const { defineConfig } = require('cypress');
module.exports = defineConfig({ module.exports = defineConfig({
e2e: { e2e: {
baseUrl: 'http://localhost:9000/', baseUrl: 'http://localhost:9000/',
experimentalStudio: true,
fixturesFolder: 'test/cypress/fixtures', fixturesFolder: 'test/cypress/fixtures',
screenshotsFolder: 'test/cypress/screenshots', screenshotsFolder: 'test/cypress/screenshots',
supportFile: 'test/cypress/support/index.js', supportFile: 'test/cypress/support/index.js',

View File

@ -28,8 +28,23 @@ const countriesOptions = ref([]);
const provincesOptions = ref([]); const provincesOptions = ref([]);
const townsLocationOptions = ref([]); const townsLocationOptions = ref([]);
const onDataSaved = (dataSaved) => { const onDataSaved = (formData) => {
emit('onDataSaved', dataSaved); const newPostcode = {
...formData
};
const townObject = townsLocationOptions.value.find(
({id}) => id === formData.townFk
);
newPostcode.town = townObject?.name;
const provinceObject = provincesOptions.value.find(
({id}) => id === formData.provinceFk
);
newPostcode.province = provinceObject?.name;
const countryObject = countriesOptions.value.find(
({id}) => id === formData.countryFk
);
newPostcode.country = countryObject?.country;
emit('onDataSaved', newPostcode);
}; };
const onCityCreated = async ({ name, provinceFk }, formData) => { const onCityCreated = async ({ name, provinceFk }, formData) => {
@ -73,7 +88,7 @@ const onProvinceCreated = async ({ name }, formData) => {
:title="t('New postcode')" :title="t('New postcode')"
:subtitle="t('Please, ensure you put the correct data!')" :subtitle="t('Please, ensure you put the correct data!')"
:form-initial-data="postcodeFormData" :form-initial-data="postcodeFormData"
@on-data-saved="onDataSaved($event)" @on-data-saved="onDataSaved"
> >
<template #form-inputs="{ data, validate }"> <template #form-inputs="{ data, validate }">
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">

View File

@ -101,16 +101,16 @@ onMounted(async () => {
}); });
onBeforeRouteLeave((to, from, next) => { onBeforeRouteLeave((to, from, next) => {
if (!hasChanges.value) next(); if (hasChanges.value)
quasar.dialog({
quasar.dialog({ component: VnConfirm,
component: VnConfirm, componentProps: {
componentProps: { title: t('Unsaved changes will be lost'),
title: t('Unsaved changes will be lost'), message: t('Are you sure exit without saving?'),
message: t('Are you sure exit without saving?'), promise: () => next(),
promise: () => next(), },
}, });
}); else next();
}); });
onUnmounted(() => { onUnmounted(() => {
@ -132,12 +132,12 @@ const formUrl = computed(() => $props.url);
const defaultButtons = computed(() => ({ const defaultButtons = computed(() => ({
save: { save: {
color: 'primary', color: 'primary',
icon: 'restart_alt', icon: 'save',
label: 'globals.save', label: 'globals.save',
}, },
reset: { reset: {
color: 'primary', color: 'primary',
icon: 'save', icon: 'restart_alt',
label: 'globals.reset', label: 'globals.reset',
}, },
...$props.defaultButtons, ...$props.defaultButtons,

View File

@ -5,7 +5,7 @@ import { useCapitalize } from 'src/composables/useCapitalize';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
const props = defineProps({ const props = defineProps({
modelValue: { type: String, default: '' }, modelValue: { type: [String, Number], default: '' },
}); });
const { t } = useI18n(); const { t } = useI18n();

View File

@ -88,6 +88,10 @@ function locationFilter(search = '') {
function handleFetch(data) { function handleFetch(data) {
postcodesOptions.value = data; postcodesOptions.value = data;
} }
function onDataSaved(newPostcode) {
postcodesOptions.value.push(newPostcode);
value.value = newPostcode.code;
}
</script> </script>
<template> <template>
<FetchData <FetchData
@ -111,11 +115,13 @@ function handleFetch(data) {
clearable clearable
> >
<template #form> <template #form>
<CreateNewPostcode @on-data-saved="locationFilter()" /> <CreateNewPostcode
@on-data-saved="onDataSaved"
/>
</template> </template>
<template #option="{ itemProps, opt }"> <template #option="{ itemProps, opt }">
<QItem v-bind="itemProps"> <QItem v-bind="itemProps">
<QItemSection v-if="opt"> <QItemSection v-if="opt.code">
<QItemLabel>{{ opt.code }}</QItemLabel> <QItemLabel>{{ opt.code }}</QItemLabel>
<QItemLabel caption>{{ showLabel(opt) }}</QItemLabel> <QItemLabel caption>{{ showLabel(opt) }}</QItemLabel>
</QItemSection> </QItemSection>

View File

@ -1030,7 +1030,7 @@ en:
ticketCreated: Created ticketCreated: Created
created: Created created: Created
isChargedToMana: Charged to mana isChargedToMana: Charged to mana
hasToPickUp: Has to pick Up pickup: Type of pickup
dmsFk: Document ID dmsFk: Document ID
text: Description text: Description
claimStateFk: Claim State claimStateFk: Claim State
@ -1069,7 +1069,7 @@ es:
ticketCreated: Creado ticketCreated: Creado
created: Creado created: Creado
isChargedToMana: Cargado a maná isChargedToMana: Cargado a maná
hasToPickUp: Se debe recoger pickup: Se debe recoger
dmsFk: ID documento dmsFk: ID documento
text: Descripción text: Descripción
claimStateFk: Estado de la reclamación claimStateFk: Estado de la reclamación

View File

@ -1,5 +1,5 @@
import { onMounted, ref, computed } from 'vue'; import { onMounted, ref, computed } from 'vue';
import { useRouter, useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import axios from 'axios'; import axios from 'axios';
import { useArrayDataStore } from 'stores/useArrayDataStore'; import { useArrayDataStore } from 'stores/useArrayDataStore';
import { buildFilter } from 'filters/filterPanel'; import { buildFilter } from 'filters/filterPanel';
@ -15,7 +15,6 @@ export function useArrayData(key, userOptions) {
const store = arrayDataStore.get(key); const store = arrayDataStore.get(key);
const hasMoreData = ref(false); const hasMoreData = ref(false);
const router = useRouter();
const route = useRoute(); const route = useRoute();
let canceller = null; let canceller = null;
@ -105,7 +104,7 @@ export function useArrayData(key, userOptions) {
for (const row of response.data) store.data.push(row); for (const row of response.data) store.data.push(row);
} else { } else {
store.data = response.data; store.data = response.data;
if (!document.querySelectorAll('[role="dialog"]')) if (!document.querySelectorAll('[role="dialog"]').length)
updateRouter && updateStateParams(); updateRouter && updateStateParams();
} }
@ -190,11 +189,15 @@ export function useArrayData(key, userOptions) {
if (store.userParams && Object.keys(store.userParams).length !== 0) if (store.userParams && Object.keys(store.userParams).length !== 0)
query.params = JSON.stringify(store.userParams); query.params = JSON.stringify(store.userParams);
if (router) const url = new URL(window.location.href);
router.replace({ const { hash: currentHash } = url;
path: route.path, const [currentRoute] = currentHash.split('?');
query: query,
}); const params = new URLSearchParams();
for (const param in query) params.append(param, query[param]);
url.hash = currentRoute + '?' + params.toString();
window.history.pushState({}, '', url.hash);
} }
const totalRows = computed(() => (store.data && store.data.length) || 0); const totalRows = computed(() => (store.data && store.data.length) || 0);

View File

@ -544,6 +544,7 @@ export default {
assignedTo: 'Assigned', assignedTo: 'Assigned',
attendedBy: 'Attended by', attendedBy: 'Attended by',
created: 'Created', created: 'Created',
pickup: 'Pickup',
state: 'State', state: 'State',
details: 'Details', details: 'Details',
item: 'Item', item: 'Item',
@ -565,13 +566,19 @@ export default {
responsible: 'Responsible', responsible: 'Responsible',
worker: 'Worker', worker: 'Worker',
redelivery: 'Redelivery', redelivery: 'Redelivery',
null: 'No',
agency: 'Agency',
delivery: 'Delivery',
}, },
basicData: { basicData: {
customer: 'Customer', customer: 'Customer',
assignedTo: 'Assigned', assignedTo: 'Assigned',
created: 'Created', created: 'Created',
state: 'State', state: 'State',
picked: 'Picked', pickup: 'Pickup',
null: 'No',
agency: 'Agency',
delivery: 'Delivery',
}, },
photo: { photo: {
fileDescription: 'Claim id {claimId} from client {clientName} id {clientId}', fileDescription: 'Claim id {claimId} from client {clientName} id {clientId}',

View File

@ -543,6 +543,7 @@ export default {
assignedTo: 'Asignada a', assignedTo: 'Asignada a',
attendedBy: 'Atendida por', attendedBy: 'Atendida por',
created: 'Creada', created: 'Creada',
pickup: 'Recogida',
state: 'Estado', state: 'Estado',
details: 'Detalles', details: 'Detalles',
item: 'Artículo', item: 'Artículo',
@ -564,13 +565,19 @@ export default {
responsible: 'Responsable', responsible: 'Responsable',
worker: 'Trabajador', worker: 'Trabajador',
redelivery: 'Devolución', redelivery: 'Devolución',
null: 'No',
agency: 'Agencia',
delivery: 'Reparto',
}, },
basicData: { basicData: {
customer: 'Cliente', customer: 'Cliente',
assignedTo: 'Asignada a', assignedTo: 'Asignada a',
created: 'Creada', created: 'Creada',
state: 'Estado', state: 'Estado',
picked: 'Recogida', pickup: 'Recogida',
null: 'No',
agency: 'Agencia',
delivery: 'Reparto',
}, },
photo: { photo: {
fileDescription: fileDescription:

View File

@ -9,6 +9,7 @@ import VnRow from 'components/ui/VnRow.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
import VnInputDate from 'components/common/VnInputDate.vue'; import VnInputDate from 'components/common/VnInputDate.vue';
import axios from 'axios';
import { useSession } from 'src/composables/useSession'; import { useSession } from 'src/composables/useSession';
const route = useRoute(); const route = useRoute();
@ -24,7 +25,7 @@ const claimFilter = {
'workerFk', 'workerFk',
'claimStateFk', 'claimStateFk',
'packages', 'packages',
'hasToPickUp', 'pickup',
], ],
include: [ include: [
{ {
@ -50,6 +51,20 @@ function setClaimStates(data) {
claimStates.value = data; claimStates.value = data;
claimStatesCopy.value = data; claimStatesCopy.value = data;
} }
let optionsList;
async function getEnumValues() {
optionsList = [{ id: null, description: t('claim.basicData.null') }];
const { data } = await axios.get(`Applications/get-enum-values`, {
params: {
schema: 'vn',
table: 'claim',
column: 'pickup',
},
});
for (let value of data)
optionsList.push({ id: value, description: t(`claim.basicData.${value}`) });
}
getEnumValues();
const workerFilter = { const workerFilter = {
options: workers, options: workers,
@ -168,13 +183,19 @@ const statesFilter = {
type="number" type="number"
/> />
</div> </div>
</VnRow>
<VnRow class="row q-gutter-md q-mb-md">
<div class="col"> <div class="col">
<QCheckbox <QSelect
v-model="data.hasToPickUp" v-model="data.pickup"
:label="t('claim.basicData.picked')" :options="optionsList"
/> option-value="id"
option-label="description"
emit-value
:label="t('claim.basicData.pickup')"
map-options
use-input
:input-debounce="0"
>
</QSelect>
</div> </div>
</VnRow> </VnRow>
</template> </template>

View File

@ -220,10 +220,9 @@ function openDialog(dmsId) {
/> />
</template> </template>
</VnLv> </VnLv>
<QCheckbox <VnLv
:label="t('claim.basicData.picked')" :label="t('claim.summary.pickup')"
v-model="claim.hasToPickUp" :value="t(`claim.summary.${claim.pickup}`)"
:disable="true"
/> />
</QCard> </QCard>
<QCard class="vn-three"> <QCard class="vn-three">

View File

@ -32,6 +32,13 @@ const invoiceInFormRef = ref();
const expensesRef = ref(); const expensesRef = ref();
const newExpenseRef = ref(); const newExpenseRef = ref();
defineProps({
actionIcon: {
type: String,
default: 'add',
},
});
const columns = computed(() => [ const columns = computed(() => [
{ {
name: 'expense', name: 'expense',
@ -207,17 +214,16 @@ async function addExpense() {
@click.stop="value = null" @click.stop="value = null"
class="cursor-pointer" class="cursor-pointer"
/> />
<QBtn <QIcon
padding="xs" @click.stop.prevent="newExpenseRef.show()"
round :name="actionIcon"
flat size="xs"
icon="add_circle" class="default-icon"
@click.stop="newExpenseRef.show()"
> >
<QTooltip> <QTooltip>
{{ t('Create expense') }} {{ t('Create expense') }}
</QTooltip> </QTooltip>
</QBtn> </QIcon>
</template> </template>
</VnSelectFilter> </VnSelectFilter>
</QTd> </QTd>
@ -470,6 +476,11 @@ async function addExpense() {
.q-item { .q-item {
min-height: 0; min-height: 0;
} }
.default-icon {
cursor: pointer;
border-radius: 50px;
background-color: $primary;
}
</style> </style>
<i18n> <i18n>
es: es:

View File

@ -8,41 +8,41 @@ describe('VnLocation', () => {
cy.visit('/#/worker/create'); cy.visit('/#/worker/create');
cy.waitForElement('.q-card'); cy.waitForElement('.q-card');
}); });
it('Show all options', function() {
it('Show all options', function() { cy.get(inputLocation).click();
cy.get(inputLocation).click(); cy.get(locationOptions).should('have.length.at.least',5);
cy.get(locationOptions).should('have.length',5);
}); });
it('input filter location as "al"', function() {
it('input filter location as "al"', function() {
cy.get(inputLocation).click(); cy.get(inputLocation).click();
cy.get(inputLocation).clear(); cy.get(inputLocation).clear();
cy.get(inputLocation).type('al'); cy.get(inputLocation).type('al');
cy.get(locationOptions).should('have.length',3); cy.get(locationOptions).should('have.length.at.least',3);
}); });
it('input filter location as "ecuador"', function() { it('input filter location as "ecuador"', function() {
cy.get(inputLocation).click(); cy.get(inputLocation).click();
cy.get(inputLocation).clear(); cy.get(inputLocation).clear();
cy.get(inputLocation).type('ecuador'); cy.get(inputLocation).type('ecuador');
cy.get(locationOptions).should('have.length',1); cy.get(locationOptions).should('have.length.at.least',1);
cy.get(`${locationOptions}:nth-child(1)`).click(); cy.get(`${locationOptions}:nth-child(1)`).click();
cy.get(':nth-child(3) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control > :nth-child(2) > .q-icon').click(); cy.get(':nth-child(3) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control > :nth-child(2) > .q-icon').click();
}); });
}); });
describe('Fiscal-data',()=>{ describe('Fiscal-data',()=>{
const inputLocation = ':nth-child(6) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control';
beforeEach(() => { beforeEach(() => {
cy.viewport(1280, 720); cy.viewport(1280, 720);
cy.login('developer'); cy.login('developer');
cy.visit('/#/supplier/567/fiscal-data', {timeout: 2000}); cy.visit('/#/supplier/567/fiscal-data', {timeout: 2000});
cy.waitForElement('.q-card'); cy.waitForElement('.q-card');
}); });
it('Create postCode', function() {
it('Show locations options', function() { cy.get(':nth-child(6) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control > :nth-child(3) > .q-icon').click();
cy.get(inputLocation).click(); cy.get(' .q-card > h1').should('have.text', 'New postcode');
cy.get(locationOptions).should('have.length', 5); cy.get('.q-card > :nth-child(4) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control > :nth-child(1) > input').clear('12');
cy.get('.q-card > :nth-child(4) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control > :nth-child(1) > input').type('1234453');
cy.selectOption('.q-dialog__inner > .column > #formModel > .q-card > :nth-child(4) > :nth-child(2) > .q-field > .q-field__inner > .q-field__control ', 'Valencia');
cy.selectOption('.q-dialog__inner > .column > #formModel > .q-card > :nth-child(5) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control ', 'Province one');
cy.selectOption('.q-dialog__inner > .column > #formModel > .q-card > :nth-child(5) > :nth-child(2) > .q-field > .q-field__inner > .q-field__control ', 'España');
cy.get('.q-mt-lg > .q-btn--standard').click();
}); });
}); });
}) })

View File

@ -36,7 +36,7 @@ describe('VnSearchBar', () => {
const checkCardListAndUrl = (expectedLength) => { const checkCardListAndUrl = (expectedLength) => {
cy.get(cardList).then(($cardList) => { cy.get(cardList).then(($cardList) => {
expect($cardList.find('.q-card').length).to.equal(expectedLength); expect($cardList.find('.q-card').length).to.equal(expectedLength);
cy.url().then((currentUrl) => expect(currentUrl).to.equal(url)); cy.url().then((currentUrl) => expect(currentUrl).to.contain(url));
}); });
}; };
}); });

View File

@ -38,10 +38,10 @@ describe('VnLog', () => {
action: 'update', action: 'update',
changedModel: 'Claim', changedModel: 'Claim',
oldInstance: { oldInstance: {
hasToPickUp: false, pickup: null,
}, },
newInstance: { newInstance: {
hasToPickUp: true, pickup: 'agency',
}, },
creationDate: '2023-09-18T12:25:34.000Z', creationDate: '2023-09-18T12:25:34.000Z',
changedModelId: '1', changedModelId: '1',

View File

@ -0,0 +1,31 @@
import { describe, expect, it, beforeAll } from 'vitest';
import { axios } from 'app/test/vitest/helper';
import { useArrayData } from 'composables/useArrayData';
describe('useArrayData', () => {
let arrayData;
beforeAll(() => {
axios.get.mockResolvedValue({ data: [] });
arrayData = useArrayData('InvoiceIn', { url: 'invoice-in/list' });
Object.defineProperty(window.location, 'href', {
writable: true,
value: 'localhost:9000/invoice-in/list',
});
// Mock the window.history.pushState method within useArrayData
window.history.pushState = (data, title, url) => (window.location.href = url);
// Mock the URL constructor within useArrayData
global.URL = class URL {
constructor(url) {
this.hash = url.split('localhost:9000/')[1];
}
};
});
it('should add the params to the url', async () => {
arrayData.store.userParams = { supplierFk: 2 };
arrayData.updateStateParams();
expect(window.location.href).contain('params=%7B%22supplierFk%22%3A2%7D');
});
});