Merge branch '8647_fix_warnings' of https: refs #8647//gitea.verdnatura.es/verdnatura/salix-front into 8647_fix_warnings
gitea/salix-front/pipeline/pr-dev This commit is unstable Details

This commit is contained in:
Jorge Penadés 2025-03-06 11:18:26 +01:00
commit de0ce51f10
17 changed files with 51 additions and 693 deletions

View File

@ -26,7 +26,12 @@ function columnName(col) {
}
</script>
<template>
<VnFilterPanel v-bind="$attrs" :search-button="true" :data-key="$attrs['data-key']">
<VnFilterPanel
v-bind="$attrs"
:search-button="true"
:disable-submit-event="true"
:data-key="$attrs['data-key']"
>
<template #body="{ params, orders, searchFn }">
<div
class="container"

View File

@ -1,6 +1,5 @@
import { createWrapper, axios } from 'app/test/vitest/helper';
import CrudModel from 'components/CrudModel.vue';
import keyShortcut from 'src/boot/keyShortcut';
import { vi, afterEach, beforeEach, beforeAll, describe, expect, it } from 'vitest';
describe('CrudModel', () => {
@ -10,20 +9,10 @@ describe('CrudModel', () => {
beforeAll(() => {
wrapper = createWrapper(CrudModel, {
global: {
stubs: [
'vnPaginate',
'useState',
'arrayData',
'useStateStore',
'vue-i18n',
'RouterLink',
],
stubs: ['vnPaginate', 'vue-i18n'],
mocks: {
validate: vi.fn(),
},
directives: {
shortcut: keyShortcut,
},
},
propsData: {
dataRequired: {
@ -34,9 +23,6 @@ describe('CrudModel', () => {
url: 'crudModelUrl',
saveFn: '',
},
directives: {
shortcut: keyShortcut, // Registrar la directiva en los tests
},
});
wrapper = wrapper.wrapper;
vm = wrapper.vm;

View File

@ -4,11 +4,11 @@ import { vi, afterEach, beforeAll, describe, expect, it } from 'vitest';
describe('VnDmsList', () => {
let vm;
const dms = {
userFk: 1,
name: 'DMS 1'
const dms = {
userFk: 1,
name: 'DMS 1',
};
beforeAll(() => {
vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
vm = createWrapper(VnDmsList, {
@ -18,8 +18,8 @@ describe('VnDmsList', () => {
filter: 'wd.workerFk',
updateModel: 'Workers',
deleteModel: 'WorkerDms',
downloadModel: 'WorkerDms'
}
downloadModel: 'WorkerDms',
},
}).vm;
});
@ -29,46 +29,45 @@ describe('VnDmsList', () => {
describe('setData()', () => {
const data = [
{
userFk: 1,
{
userFk: 1,
name: 'Jessica',
lastName: 'Jones',
file: '4.jpg',
created: '2021-07-28 21:00:00'
created: '2021-07-28 21:00:00',
},
{
userFk: 2,
{
userFk: 2,
name: 'Bruce',
lastName: 'Banner',
created: '2022-07-28 21:00:00',
dms: {
userFk: 2,
userFk: 2,
name: 'Bruce',
lastName: 'BannerDMS',
created: '2022-07-28 21:00:00',
file: '4.jpg',
}
},
},
{
userFk: 3,
name: 'Natasha',
lastName: 'Romanoff',
file: '4.jpg',
created: '2021-10-28 21:00:00'
}
]
created: '2021-10-28 21:00:00',
},
];
it('Should replace objects that contain the "dms" property with the value of the same and sort by creation date', () => {
vm.setData(data);
expect([vm.rows][0][0].lastName).toEqual('BannerDMS');
expect([vm.rows][0][1].lastName).toEqual('Romanoff');
});
});
describe('parseDms()', () => {
const resultDms = { ...dms, userId:1};
const resultDms = { ...dms, userId: 1 };
it('Should add properties that end with "Fk" by changing the suffix to "Id"', () => {
const parsedDms = vm.parseDms(dms);
expect(parsedDms).toEqual(resultDms);
@ -76,12 +75,12 @@ describe('VnDmsList', () => {
});
describe('showFormDialog()', () => {
const resultDms = { ...dms, userId:1};
const resultDms = { ...dms, userId: 1 };
it('should call fn parseDms() and set show true if dms is defined', () => {
vm.showFormDialog(dms);
expect(vm.formDialog.show).toEqual(true);
expect(vm.formDialog.dms).toEqual(resultDms);
});
});
});
});

View File

@ -22,7 +22,6 @@ describe('CardSummary', () => {
beforeEach(() => {
wrapper = createWrapper(CardSummary, {
global: {
stubs: ['RouterLink'],
mocks: {
validate: vi.fn(),
},

View File

@ -11,8 +11,6 @@ describe('VnSearchbar', () => {
beforeEach(async () => {
wrapper = createWrapper(VnSearchbar, {
global: { stubs: ['RouterLink'] },
propsData: {
dataKey: 'testKey',
filter: null,

View File

@ -1,30 +0,0 @@
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
export function showResultsAsTable(dialog, results, key) {
const quasar = useQuasar();
const { t } = useI18n();
function openTable() {
quasar.notify({
message: t('negative.detail.modal.changeItem.success'),
color: 'positive',
actions: [
{
label: t('globals.ok'),
color: 'white',
handler: () => {
quasar.dialog({
component: dialog,
componentProps: {
results,
key,
},
});
},
},
],
});
}
return { openTable };
}

View File

@ -1,7 +1,6 @@
import { vi, describe, expect, it, beforeAll, beforeEach, afterEach } from 'vitest';
import { createWrapper, axios } from 'app/test/vitest/helper';
import ClaimLines from '/src/pages/Claim/Card/ClaimLines.vue';
import keyShortcut from 'src/boot/keyShortcut';
describe('ClaimLines', () => {
let vm;
@ -13,9 +12,6 @@ describe('ClaimLines', () => {
mocks: {
fetch: vi.fn(),
},
directives: {
shortcut: keyShortcut,
},
},
}).vm;
});

View File

@ -1,7 +1,6 @@
import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
import { createWrapper, axios } from 'app/test/vitest/helper';
import ClaimPhoto from 'pages/Claim/Card/ClaimPhoto.vue';
import keyShortcut from 'src/boot/keyShortcut';
describe('ClaimPhoto', () => {
let vm;
@ -26,9 +25,6 @@ describe('ClaimPhoto', () => {
mocks: {
fetch: vi.fn(),
},
directives: {
shortcut: keyShortcut,
},
},
}).vm;
});

View File

@ -1,7 +1,6 @@
import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
import { createWrapper, axios } from 'app/test/vitest/helper';
import CustomerPayments from 'src/pages/Customer/Payments/CustomerPayments.vue';
import keyShortcut from 'src/boot/keyShortcut';
describe('CustomerPayments', () => {
let vm;
@ -13,9 +12,6 @@ describe('CustomerPayments', () => {
mocks: {
fetch: vi.fn(),
},
directives: {
shortcut: keyShortcut,
},
},
}).vm;
});

View File

@ -5,7 +5,7 @@ import Login from 'pages/Login/LoginMain.vue';
describe('Login', () => {
let vm;
beforeAll(() => {
vm = createWrapper(Login, { global: { stubs: ['RouterLink'] } }).vm;
vm = createWrapper(Login).vm;
});
afterEach(() => {

View File

@ -58,10 +58,7 @@ function ticketFilter(ticket) {
<template #value>
<span class="link">
{{ entity.clientFk }}
<CustomerDescriptorProxy
v-if="entity.client?.id"
:id="entity.client.id"
/>
<CustomerDescriptorProxy :id="entity.client?.id" />
</span>
</template>
</VnLv>

View File

@ -40,7 +40,9 @@ const columns = computed(() => [
sortable: true,
cardVisible: true,
isId: true,
columnFilter: false,
columnFilter: {
component: 'date',
},
},
{
columnClass: 'shrink',
@ -50,7 +52,9 @@ const columns = computed(() => [
format: ({ timed }) => toHour(timed),
sortable: true,
cardVisible: true,
columnFilter: false,
columnFilter: {
component: 'time',
},
},
{
name: 'itemFk',
@ -62,7 +66,6 @@ const columns = computed(() => [
component: 'input',
type: 'number',
columnClass: 'shrink',
inWhere: false,
},
},
{
@ -91,12 +94,6 @@ const columns = computed(() => [
field: ({ inkFk }) => inkFk,
sortable: true,
cardVisible: true,
columnFilter: {
component: 'input',
inWhere: false,
columnClass: 'shrink',
},
},
{
name: 'size',
@ -108,8 +105,6 @@ const columns = computed(() => [
columnFilter: {
component: 'input',
type: 'number',
inWhere: false,
columnClass: 'shrink',
},
},

View File

@ -1,18 +1,9 @@
<script setup>
import { ref } from 'vue';
import axios from 'axios';
import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import VnSelect from 'src/components/common/VnSelect.vue';
import notifyResults from 'src/utils/notifyResults';
import { showResultsAsTable } from 'src/composables/showResultsTable';
import VnConfirm from 'src/components/ui/VnConfirm.vue';
import HandleSplitDialog from './HandleSplitDialog.vue';
const { openTable } = showResultsAsTable();
const emit = defineEmits(['update-item']);
const quasar = useQuasar();
const { t } = useI18n();
const showChangeItemDialog = ref(false);
const newItem = ref(null);
@ -26,17 +17,15 @@ const $props = defineProps({
const updateItem = async () => {
try {
showChangeItemDialog.value = true;
// const rowsToUpdate = $props.selectedRows.map(({ saleFk, quantity }) =>
// axios.post(`Sales/replaceItem`, {
// saleFk,
// substitutionFk: newItem.value,
// quantity,
// }),
// );
// const result = await Promise.allSettled(rowsToUpdate);
openTable(HandleSplitDialog, [], 'saleFk');
// notifyResults(result, 'saleFk');
const rowsToUpdate = $props.selectedRows.map(({ saleFk, quantity }) =>
axios.post(`Sales/replaceItem`, {
saleFk,
substitutionFk: newItem.value,
quantity,
}),
);
const result = await Promise.allSettled(rowsToUpdate);
notifyResults(result, 'saleFk');
emit('update-item', newItem.value);
} catch (err) {
console.error('Error updating item:', err);

View File

@ -1,281 +0,0 @@
<script setup>
import { computed, onMounted, ref, toRefs } from 'vue';
import { useI18n } from 'vue-i18n';
import axios from 'axios';
import { useDialogPluginComponent } from 'quasar';
import VnSelect from 'src/components/common/VnSelect.vue';
import FetchData from 'components/FetchData.vue';
import VnPaginate from 'src/components/ui/VnPaginate.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnInput from 'src/components/common/VnInput.vue';
const { t } = useI18n();
const showSplitDialog = ref(false);
const newState = ref(null);
const resultSplit = ref([]);
const { dialogRef, onDialogHide } = useDialogPluginComponent();
const $props = defineProps({
tickets: {
type: Array,
default: () => [],
},
});
const tickets = ref($props.tickets ?? []);
const rowBtnDisable = () =>
!(
formData.value?.agencyModeFk &&
formData.value?.date &&
rowsSelected.value.length > 0
);
const rowsSelected = ref([]);
const columns = computed(() => [
{
name: 'status',
label: t('negative.split.status'),
field: ({ status }) => status,
sortable: true,
},
{
name: 'ticket',
label: t('negative.split.ticket'),
field: ({ ticket }) => ticket,
sortable: true,
},
{
name: 'newTicket',
label: t('negative.split.newTicket'),
field: ({ newTicket }) => newTicket,
sortable: true,
},
{
name: 'message',
label: t('negative.split.message'),
field: ({ message }) => message,
sortable: true,
},
// {
// name: 'actions',
// align: 'center',
// label: t('negative.split.actions'),
// // style: 'padding-left: 100px',
// // headerStyle: 'padding-left: 100px',
// },
]);
const formData = ref({ agencies: [] });
const handleDateChanged = async () => {
const { data: agencyData } = await axios.get('Agencies/getLanded', {
params: {
addressFk: 123,
agencyModeFk: 8,
warehouseFk: 1,
shipped: '2001-02-08T23:00:00.000Z',
},
});
if (!agencyData) formData.value.agencies = [];
const { zoneFk } = agencyData;
const { data: zoneData } = await axios.get('Zones/Includingexpired', {
params: { filter: { fields: ['id', 'name'], where: { id: zoneFk } } },
});
formData.value.agencies = zoneData;
if (zoneData.length === 1) formData.value.agencyModeFk = zoneData[0];
// formData.value.dateChanged = false;
};
const ticketsSelected = ref([]);
onMounted(() => {
ticketsSelected.value = [...new Set($props.tickets.map(({ ticketFk }) => ticketFk))];
});
const updateState = async () => {
try {
showSplitDialog.value = true;
const rowsToUpdate = $props.tickets.map(({ ticketFk }) =>
axios.post(`Tickets/state`, {
ticketFk,
code: newState.value,
})
);
await Promise.all(rowsToUpdate);
} catch (err) {
return err;
} finally {
dialogRef.value.hide({ type: 'refresh', refresh: true });
}
};
function getIcon(value) {
const icons = {
split: {
name: 'check_circle',
color: 'secondary',
},
noSplit: {
name: 'warning',
color: 'primary',
},
error: {
name: 'close',
color: 'negative',
},
};
return icons[value];
}
const updateNewTickets = async () => {
tickets.value = $props.tickets.filter((ticket) => ticket.newTicket !== 1000005);
console.log('updateNewTickets');
rowsSelected.value = [];
};
</script>
<template>
<QDialog ref="dialogRef" @hide="onDialogHide" v-model="showSplitDialog">
<QCard class="q-pa-sm">
<QCardSection class="row items-center q-pb-none">
<QAvatar
:icon="icon"
color="primary"
text-color="white"
size="xl"
v-if="icon"
/>
<span class="text-h6 text-grey">{{
t('negative.detail.modal.handleSplited.title')
}}</span>
<QSpace />
<QBtn icon="close" flat round dense v-close-popup />
</QCardSection>
<QCardSection class="row items-center justify-center column items-stretch">
<Qform>
<VnRow class="row q-gutter-md q-mb-md">
<VnInputDate
:label="t('Max date')"
v-model="formData.date"
@update:model-value="(evt) => handleDateChanged()" />
<VnSelect
:disable="formData.agencies.length < 1"
:label="t('Agency')"
v-model="formData.agencyModeFk"
:options="formData.agencies"
option-label="name"
option-value="id" />
<QBtn
icon="save"
:disable="rowBtnDisable()"
color="primary"
flat
rounded
@click="updateNewTickets"
/></VnRow>
</Qform>
<VnPaginate data-key="splitLack" :data="tickets">
<template #body="{ rows }">
<QTable
:rows="rows"
:columns="columns"
selection="multiple"
row-key="newTicket"
v-model:selected="rowsSelected"
:no-data-label="t('globals.noResults')"
flat
dense
hide-bottom
auto-load
:rows-per-page-options="[0]"
hide-pagination
:pagination="{ rowsPerPage: null }"
>
<template #header="props">
<QTr :props="props">
<QTh></QTh>
<QTh
v-for="col in props.cols"
:key="col.name"
:props="props"
>
{{ t(col.label) }}
</QTh>
</QTr>
</template>
<template #body="props">
<QTr :props="props">
<Qtd>
<QCheckbox v-model="props.selected" />
</Qtd>
<QTd
v-for="col in props.cols"
:key="col.name"
:props="props"
>
<span
v-if="
![
'status',
'message',
'actions',
].includes(col.name)
"
>
{{ col.value }}
</span>
<span v-if="'status' === col.name">
<QIcon
:name="`${getIcon(col.value).name}`"
size="xs"
class="cursor-pointer"
:color="getIcon(col.value).color"
>
</QIcon>
</span>
<span v-if="'message' === col.name">message</span>
</QTd></QTr
></template
>
</QTable></template
>
</VnPaginate>
</QCardSection>
<QCardActions align="right">
<QBtn :label="t('globals.cancel')" color="primary" flat v-close-popup />
<QBtn
:label="t('globals.confirm')"
color="primary"
:disable="!newState"
@click="updateState"
unelevated
autofocus
/> </QCardActions
></QCard>
</QDialog>
</template>
<style lang="scss" scoped>
.splitRow {
border: 1px solid #ec8916;
border-width: 1px 0 1px 0;
}
.list {
max-height: 100%;
padding: 15px;
width: 100%;
}
.grid-style-transition {
transition: transform 0.28s, background-color 0.28s;
}
#true {
background-color: $positive;
}
#false {
background-color: $negative;
}
div.q-dialog__inner > div {
max-width: fit-content !important;
}
</style>

View File

@ -1,281 +0,0 @@
<script setup>
import { computed, onMounted, ref, toRefs } from 'vue';
import { useI18n } from 'vue-i18n';
import axios from 'axios';
import { useDialogPluginComponent } from 'quasar';
import VnSelect from 'src/components/common/VnSelect.vue';
import FetchData from 'components/FetchData.vue';
import VnPaginate from 'src/components/ui/VnPaginate.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnInput from 'src/components/common/VnInput.vue';
const { t } = useI18n();
const showSplitDialog = ref(false);
const newState = ref(null);
const resultSplit = ref([]);
const { dialogRef, onDialogHide } = useDialogPluginComponent();
const $props = defineProps({
tickets: {
type: Array,
default: () => [],
},
});
const tickets = ref($props.tickets ?? []);
const rowBtnDisable = () =>
!(
formData.value?.agencyModeFk &&
formData.value?.date &&
rowsSelected.value.length > 0
);
const rowsSelected = ref([]);
const columns = computed(() => [
{
name: 'status',
label: t('negative.split.status'),
field: ({ status }) => status,
sortable: true,
},
{
name: 'ticket',
label: t('negative.split.ticket'),
field: ({ ticket }) => ticket,
sortable: true,
},
{
name: 'newTicket',
label: t('negative.split.newTicket'),
field: ({ newTicket }) => newTicket,
sortable: true,
},
{
name: 'message',
label: t('negative.split.message'),
field: ({ message }) => message,
sortable: true,
},
// {
// name: 'actions',
// align: 'center',
// label: t('negative.split.actions'),
// // style: 'padding-left: 100px',
// // headerStyle: 'padding-left: 100px',
// },
]);
const formData = ref({ agencies: [] });
const handleDateChanged = async () => {
const { data: agencyData } = await axios.get('Agencies/getLanded', {
params: {
addressFk: 123,
agencyModeFk: 8,
warehouseFk: 1,
shipped: '2001-02-08T23:00:00.000Z',
},
});
if (!agencyData) formData.value.agencies = [];
const { zoneFk } = agencyData;
const { data: zoneData } = await axios.get('Zones/Includingexpired', {
params: { filter: { fields: ['id', 'name'], where: { id: zoneFk } } },
});
formData.value.agencies = zoneData;
if (zoneData.length === 1) formData.value.agencyModeFk = zoneData[0];
// formData.value.dateChanged = false;
};
const ticketsSelected = ref([]);
onMounted(() => {
ticketsSelected.value = [...new Set($props.tickets.map(({ ticketFk }) => ticketFk))];
});
const updateState = async () => {
try {
showSplitDialog.value = true;
const rowsToUpdate = $props.tickets.map(({ ticketFk }) =>
axios.post(`Tickets/state`, {
ticketFk,
code: newState.value,
})
);
await Promise.all(rowsToUpdate);
} catch (err) {
return err;
} finally {
dialogRef.value.hide({ type: 'refresh', refresh: true });
}
};
function getIcon(value) {
const icons = {
split: {
name: 'check_circle',
color: 'secondary',
},
noSplit: {
name: 'warning',
color: 'primary',
},
error: {
name: 'close',
color: 'negative',
},
};
return icons[value];
}
const updateNewTickets = async () => {
tickets.value = $props.tickets.filter((ticket) => ticket.newTicket !== 1000005);
console.log('updateNewTickets');
rowsSelected.value = [];
};
</script>
<template>
<QDialog ref="dialogRef" @hide="onDialogHide" v-model="showSplitDialog">
<QCard class="q-pa-sm">
<QCardSection class="row items-center q-pb-none">
<QAvatar
:icon="icon"
color="primary"
text-color="white"
size="xl"
v-if="icon"
/>
<span class="text-h6 text-grey">{{
t('negative.detail.modal.handleSplited.title')
}}</span>
<QSpace />
<QBtn icon="close" flat round dense v-close-popup />
</QCardSection>
<QCardSection class="row items-center justify-center column items-stretch">
<Qform>
<VnRow class="row q-gutter-md q-mb-md">
<VnInputDate
:label="t('Max date')"
v-model="formData.date"
@update:model-value="(evt) => handleDateChanged()" />
<VnSelect
:disable="formData.agencies.length < 1"
:label="t('Agency')"
v-model="formData.agencyModeFk"
:options="formData.agencies"
option-label="name"
option-value="id" />
<QBtn
icon="save"
:disable="rowBtnDisable()"
color="primary"
flat
rounded
@click="updateNewTickets"
/></VnRow>
</Qform>
<VnPaginate data-key="splitLack" :data="tickets">
<template #body="{ rows }">
<QTable
:rows="rows"
:columns="columns"
selection="multiple"
row-key="newTicket"
v-model:selected="rowsSelected"
:no-data-label="t('globals.noResults')"
flat
dense
hide-bottom
auto-load
:rows-per-page-options="[0]"
hide-pagination
:pagination="{ rowsPerPage: null }"
>
<template #header="props">
<QTr :props="props">
<QTh></QTh>
<QTh
v-for="col in props.cols"
:key="col.name"
:props="props"
>
{{ t(col.label) }}
</QTh>
</QTr>
</template>
<template #body="props">
<QTr :props="props">
<Qtd>
<QCheckbox v-model="props.selected" />
</Qtd>
<QTd
v-for="col in props.cols"
:key="col.name"
:props="props"
>
<span
v-if="
![
'status',
'message',
'actions',
].includes(col.name)
"
>
{{ col.value }}
</span>
<span v-if="'status' === col.name">
<QIcon
:name="`${getIcon(col.value).name}`"
size="xs"
class="cursor-pointer"
:color="getIcon(col.value).color"
>
</QIcon>
</span>
<span v-if="'message' === col.name">message</span>
</QTd></QTr
></template
>
</QTable></template
>
</VnPaginate>
</QCardSection>
<QCardActions align="right">
<QBtn :label="t('globals.cancel')" color="primary" flat v-close-popup />
<QBtn
:label="t('globals.confirm')"
color="primary"
:disable="!newState"
@click="updateState"
unelevated
autofocus
/> </QCardActions
></QCard>
</QDialog>
</template>
<style lang="scss" scoped>
.splitRow {
border: 1px solid #ec8916;
border-width: 1px 0 1px 0;
}
.list {
max-height: 100%;
padding: 15px;
width: 100%;
}
.grid-style-transition {
transition: transform 0.28s, background-color 0.28s;
}
#true {
background-color: $positive;
}
#false {
background-color: $negative;
}
div.q-dialog__inner > div {
max-width: fit-content !important;
}
</style>

View File

@ -18,10 +18,7 @@ describe('useStateQueryStore', () => {
beforeEach(() => {
stateQueryStore = useStateQueryStore();
({ add, isLoading, remove, reset } = useStateQueryStore());
reset();
// setActivePinia(createPinia());
expect(getQueries().size).toBeFalsy();
});

View File

@ -106,6 +106,7 @@ export function createWrapper(component, options) {
directives: {
shortcut: keyShortcut,
},
stubs: ['useState', 'arrayData', 'useStateStore', 'vue-i18n', 'RouterLink'],
},
mocks: {
t: (tKey) => tKey,
@ -113,15 +114,11 @@ export function createWrapper(component, options) {
},
};
const mountOptions = Object.assign({}, defaultOptions);
if (options instanceof Object) {
Object.assign(mountOptions, options);
if (options.global) {
mountOptions.global.plugins = defaultOptions.global.plugins;
}
}
const mountOptions = {
...defaultOptions,
...options,
global: { ...defaultOptions.global, ...options?.global },
};
const wrapper = mount(component, mountOptions);
const vm = wrapper.vm;