0
0
Fork 0

fix: refs #6942 wip: formModel

This commit is contained in:
Jorge Penadés 2024-05-22 11:22:46 +02:00
parent 467531d029
commit 5bddc6e04d
8 changed files with 179 additions and 226 deletions

View File

@ -11,6 +11,7 @@ import useNotify from 'src/composables/useNotify.js';
import SkeletonForm from 'components/ui/SkeletonForm.vue'; import SkeletonForm from 'components/ui/SkeletonForm.vue';
import VnConfirm from './ui/VnConfirm.vue'; import VnConfirm from './ui/VnConfirm.vue';
import { tMobile } from 'src/composables/tMobile'; import { tMobile } from 'src/composables/tMobile';
import { useArrayData } from 'src/composables/useArrayData';
const { push } = useRouter(); const { push } = useRouter();
const quasar = useQuasar(); const quasar = useQuasar();
@ -85,28 +86,66 @@ const $props = defineProps({
const emit = defineEmits(['onFetch', 'onDataSaved']); const emit = defineEmits(['onFetch', 'onDataSaved']);
const componentIsRendered = ref(false); const componentIsRendered = ref(false);
const arrayData = useArrayData($props.model);
const isLoading = ref(false);
// Si elegimos observar los cambios del form significa que inicialmente las actions estaran deshabilitadas
const isResetting = ref(false);
const hasChanges = ref(!$props.observeFormChanges);
const originalData = ref({});
const formData = computed(() => state.get($props.model));
const formUrl = computed(() => $props.url);
const defaultButtons = computed(() => ({
save: {
color: 'primary',
icon: 'save',
label: 'globals.save',
},
reset: {
color: 'primary',
icon: 'restart_alt',
label: 'globals.reset',
},
...$props.defaultButtons,
}));
onMounted(async () => { onMounted(async () => {
originalData.value = $props.formInitialData; originalData.value = $props.formInitialData;
nextTick(() => {
componentIsRendered.value = true; nextTick(() => (componentIsRendered.value = true));
});
// Podemos enviarle al form la estructura de data inicial sin necesidad de fetchearla // Podemos enviarle al form la estructura de data inicial sin necesidad de fetchearla
state.set($props.model, $props.formInitialData); state.set($props.model, $props.formInitialData);
if ($props.autoLoad && !$props.formInitialData) { if ($props.autoLoad && !$props.formInitialData && $props.url) await fetch();
await fetch(); else if (arrayData.store.data) {
state.set($props.model, arrayData.store.data);
emit('onFetch', state.get($props.model));
} }
// Si así se desea disparamos el watcher del form después de 100ms, asi darle tiempo de que se haya cargado la data inicial
// para evitar que detecte cambios cuando es data inicial default
if ($props.observeFormChanges) { if ($props.observeFormChanges) {
setTimeout(() => { watch(
startFormWatcher(); () => formData.value,
}, 100); (val) => {
hasChanges.value = !isResetting.value && val;
isResetting.value = false;
},
{ deep: true }
);
} }
}); });
if (!$props.url)
watch(
() => arrayData.store.data,
(val) => updateAndEmit(val, 'onFetch')
);
watch(formUrl, async () => {
originalData.value = null;
reset();
fetch();
});
onBeforeRouteLeave((to, from, next) => { onBeforeRouteLeave((to, from, next) => {
if (hasChanges.value && $props.observeFormChanges) if (hasChanges.value && $props.observeFormChanges)
quasar.dialog({ quasar.dialog({
@ -129,49 +168,14 @@ onUnmounted(() => {
if ($props.clearStoreOnUnmount) state.unset($props.model); if ($props.clearStoreOnUnmount) state.unset($props.model);
}); });
const isLoading = ref(false);
// Si elegimos observar los cambios del form significa que inicialmente las actions estaran deshabilitadas
const isResetting = ref(false);
const hasChanges = ref(!$props.observeFormChanges);
const originalData = ref({});
const formData = computed(() => state.get($props.model));
const formUrl = computed(() => $props.url);
const defaultButtons = computed(() => ({
save: {
color: 'primary',
icon: 'save',
label: 'globals.save',
},
reset: {
color: 'primary',
icon: 'restart_alt',
label: 'globals.reset',
},
...$props.defaultButtons,
}));
const startFormWatcher = () => {
watch(
() => formData.value,
(val) => {
hasChanges.value = !isResetting.value && val;
isResetting.value = false;
},
{ deep: true }
);
};
async function fetch() { async function fetch() {
try { try {
let { data } = await axios.get($props.url, { let { data } = await axios.get($props.url, {
params: { filter: JSON.stringify($props.filter) }, params: { filter: JSON.stringify($props.filter) },
}); });
if (Array.isArray(data)) data = data[0] ?? {}; if (Array.isArray(data)) data = data[0] ?? {};
state.set($props.model, data); updateAndEmit(data, 'onFetch');
originalData.value = data && JSON.parse(JSON.stringify(data));
emit('onFetch', state.get($props.model));
} catch (error) { } catch (error) {
state.set($props.model, {}); state.set($props.model, {});
originalData.value = {}; originalData.value = {};
@ -179,32 +183,31 @@ async function fetch() {
} }
async function save() { async function save() {
if ($props.observeFormChanges && !hasChanges.value) { if ($props.observeFormChanges && !hasChanges.value)
notify('globals.noChanges', 'negative'); return notify('globals.noChanges', 'negative');
return;
}
isLoading.value = true;
isLoading.value = true;
try { try {
const body = $props.mapper ? $props.mapper(formData.value) : formData.value; const body = $props.mapper ? $props.mapper(formData.value) : formData.value;
const method = $props.urlCreate ? 'post' : 'patch';
const url =
$props.urlCreate || $props.urlUpdate || $props.url || arrayData.store.url;
let response; let response;
if ($props.saveFn) response = await $props.saveFn(body); if ($props.saveFn) response = await $props.saveFn(body);
else else response = await axios[method](url, body);
response = await axios[$props.urlCreate ? 'post' : 'patch'](
$props.urlCreate || $props.urlUpdate || $props.url,
body
);
if ($props.urlCreate) notify('globals.dataCreated', 'positive'); if ($props.urlCreate) notify('globals.dataCreated', 'positive');
emit('onDataSaved', formData.value, response?.data); updateAndEmit(response?.data, 'onDataSaved');
originalData.value = JSON.parse(JSON.stringify(formData.value));
hasChanges.value = false; hasChanges.value = false;
} catch (err) { } catch (err) {
console.error(err); console.error(err);
notify('errors.writeRequest', 'negative'); notify('errors.writeRequest', 'negative');
} } finally {
isLoading.value = false; isLoading.value = false;
} }
}
async function saveAndGo() { async function saveAndGo() {
await save(); await save();
@ -212,10 +215,7 @@ async function saveAndGo() {
} }
function reset() { function reset() {
state.set($props.model, originalData.value); updateAndEmit(originalData.value, 'onFetch');
originalData.value = JSON.parse(JSON.stringify(originalData.value));
emit('onFetch', state.get($props.model));
if ($props.observeFormChanges) { if ($props.observeFormChanges) {
hasChanges.value = false; hasChanges.value = false;
isResetting.value = true; isResetting.value = true;
@ -237,17 +237,15 @@ function filter(value, update, filterOptions) {
); );
} }
watch(formUrl, async () => { function updateAndEmit(val, evt) {
originalData.value = null; state.set($props.model, val);
reset(); originalData.value = val && JSON.parse(JSON.stringify(val));
fetch(); if (!$props.url) arrayData.store.data = val;
});
defineExpose({ emit(evt, state.get($props.model));
save, }
isLoading,
hasChanges, defineExpose({ save, isLoading, hasChanges });
});
</script> </script>
<template> <template>
<div class="column items-center full-width"> <div class="column items-center full-width">

View File

@ -49,12 +49,13 @@ const { store } = arrayData;
const entity = computed(() => (Array.isArray(store.data) ? store.data[0] : store.data)); const entity = computed(() => (Array.isArray(store.data) ? store.data[0] : store.data));
const isLoading = ref(false); const isLoading = ref(false);
defineExpose({ defineExpose({ getData });
getData,
});
onBeforeMount(async () => { onBeforeMount(async () => {
await getData(); await getData();
watch($props, async () => await getData()); watch(
() => [$props.url, $props.filter],
async () => await getData()
);
}); });
async function getData() { async function getData() {

View File

@ -24,6 +24,7 @@ globals:
create: Create create: Create
edit: Edit edit: Edit
save: Save save: Save
saveAndContinue: Save and continue
remove: Remove remove: Remove
reset: Reset reset: Reset
close: Close close: Close

View File

@ -24,6 +24,7 @@ globals:
create: Crear create: Crear
edit: Modificar edit: Modificar
save: Guardar save: Guardar
saveAndContinue: Guardar y continuar
remove: Eliminar remove: Eliminar
reset: Restaurar reset: Restaurar
close: Cerrar close: Cerrar

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import { ref, computed } from 'vue'; import { ref, computed } from 'vue';
import { useRouter } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
import axios from 'axios'; import axios from 'axios';
@ -14,15 +14,13 @@ import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
const quasar = useQuasar(); const quasar = useQuasar();
const { currentRoute } = useRouter();
const { t } = useI18n(); const { t } = useI18n();
const dms = ref({}); const dms = ref({});
const editDownloadDisabled = ref(false); const editDownloadDisabled = ref(false);
const arrayData = useArrayData('InvoiceIn'); const invoiceIn = computed(() => useArrayData('InvoiceIn').store.data);
const invoiceIn = computed(() => arrayData.store.data);
const userConfig = ref(null); const userConfig = ref(null);
const invoiceId = currentRoute.value.params.id; const invoiceId = computed(() => +useRoute().params.id);
const expenses = ref([]); const expenses = ref([]);
const currencies = ref([]); const currencies = ref([]);
@ -180,13 +178,7 @@ async function upsert() {
auto-load auto-load
@on-fetch="(data) => (sageWithholdings = data)" @on-fetch="(data) => (sageWithholdings = data)"
/> />
<FormModel <FormModel model="InvoiceIn" :go-to="`/invoice-in/${invoiceId}/vat`" auto-load>
v-if="invoiceIn"
:url="`InvoiceIns/${invoiceId}`"
model="InvoiceIn"
:go-to="`/invoice-in/${invoiceId}/vat`"
auto-load
>
<template #form="{ data }"> <template #form="{ data }">
<VnRow> <VnRow>
<VnSelect <VnSelect

View File

@ -6,7 +6,6 @@ import { useQuasar } from 'quasar';
import axios from 'axios'; import axios from 'axios';
import { toCurrency, toDate } from 'src/filters'; import { toCurrency, toDate } from 'src/filters';
import { useRole } from 'src/composables/useRole'; import { useRole } from 'src/composables/useRole';
import useCardDescription from 'src/composables/useCardDescription';
import { downloadFile } from 'src/composables/downloadFile'; import { downloadFile } from 'src/composables/downloadFile';
import { useArrayData } from 'src/composables/useArrayData'; import { useArrayData } from 'src/composables/useArrayData';
import { usePrintService } from 'composables/usePrintService'; import { usePrintService } from 'composables/usePrintService';
@ -20,9 +19,7 @@ import { useCapitalize } from 'src/composables/useCapitalize';
import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue'; import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorProxy.vue';
import InvoiceInToBook from '../InvoiceInToBook.vue'; import InvoiceInToBook from '../InvoiceInToBook.vue';
const $props = defineProps({ const $props = defineProps({ id: { type: Number, default: null } });
id: { type: Number, default: null },
});
const { push, currentRoute } = useRouter(); const { push, currentRoute } = useRouter();
@ -33,7 +30,6 @@ const { openReport, sendEmail } = usePrintService();
const { store } = useArrayData('InvoiceIn'); const { store } = useArrayData('InvoiceIn');
const invoiceIn = computed(() => store.data); const invoiceIn = computed(() => store.data);
const isBooked = ref();
const cardDescriptorRef = ref(); const cardDescriptorRef = ref();
const correctionDialogRef = ref(); const correctionDialogRef = ref();
const entityId = computed(() => $props.id || +currentRoute.value.params.id); const entityId = computed(() => $props.id || +currentRoute.value.params.id);
@ -92,11 +88,7 @@ const filter = {
}, },
], ],
}; };
const data = ref(useCardDescription()); const invoiceInCorrection = reactive({ correcting: [], corrected: null });
const invoiceInCorrection = reactive({
correcting: [],
corrected: null,
});
const routes = reactive({ const routes = reactive({
getSupplier: (id) => { getSupplier: (id) => {
return { name: 'SupplierCard', params: { id } }; return { name: 'SupplierCard', params: { id } };
@ -177,16 +169,9 @@ async function setInvoiceCorrection(id) {
); );
} }
async function setData(entity) { async function setTotals() {
data.value = useCardDescription(entity.supplierRef, entity.id);
isBooked.value = entity.isBooked;
const { totalDueDay } = await getTotals();
totalAmount.value = totalDueDay;
}
async function getTotals() {
const { data } = await axios.get(`InvoiceIns/${entityId.value}/getTotals`); const { data } = await axios.get(`InvoiceIns/${entityId.value}/getTotals`);
return data; totalAmount.value = data.totalDueDay;
} }
function openDialog() { function openDialog() {
@ -303,16 +288,17 @@ const createInvoiceInCorrection = async () => {
auto-load auto-load
/> />
<CardDescriptor <CardDescriptor
v-if="invoiceIn"
ref="cardDescriptorRef" ref="cardDescriptorRef"
module="InvoiceIn" module="InvoiceIn"
:url="`InvoiceIns/${entityId}`" :url="`InvoiceIns/${entityId}`"
:filter="filter" :filter="filter"
:title="data.title" :title="invoiceIn.supplierRef"
:subtitle="data.subtitle" :subtitle="invoiceIn.id"
@on-fetch="setData" data-key="InvoiceIn"
data-key="invoiceInData" @on-fetch="setTotals"
> >
<template #menu="{ entity }"> <template #menu>
<InvoiceInToBook> <InvoiceInToBook>
<template #content="{ book }"> <template #content="{ book }">
<QItem <QItem
@ -378,17 +364,20 @@ const createInvoiceInCorrection = async () => {
<QItemSection>{{ t('Create rectificative invoice') }}...</QItemSection> <QItemSection>{{ t('Create rectificative invoice') }}...</QItemSection>
</QItem> </QItem>
<QItem <QItem
v-if="entity.dmsFk" v-if="invoiceIn.dmsFk"
v-ripple v-ripple
clickable clickable
@click="downloadFile(entity.dmsFk)" @click="downloadFile(invoiceIn.dmsFk)"
> >
<QItemSection>{{ t('components.smartCard.downloadFile') }}</QItemSection> <QItemSection>{{ t('components.smartCard.downloadFile') }}</QItemSection>
</QItem> </QItem>
</template> </template>
<template #body="{ entity }"> <template #body>
<VnLv :label="t('invoiceIn.card.issued')" :value="toDate(entity.issued)" /> <VnLv :label="t('invoiceIn.card.issued')" :value="toDate(invoiceIn.issued)" />
<VnLv :label="t('invoiceIn.summary.booked')" :value="toDate(entity.booked)" /> <VnLv
:label="t('invoiceIn.summary.booked')"
:value="toDate(invoiceIn.booked)"
/>
<VnLv :label="t('invoiceIn.card.amount')" :value="toCurrency(totalAmount)" /> <VnLv :label="t('invoiceIn.card.amount')" :value="toCurrency(totalAmount)" />
<VnLv :label="t('invoiceIn.summary.supplier')"> <VnLv :label="t('invoiceIn.summary.supplier')">
<template #value> <template #value>
@ -399,13 +388,13 @@ const createInvoiceInCorrection = async () => {
</template> </template>
</VnLv> </VnLv>
</template> </template>
<template #actions="{ entity }"> <template #action>
<QCardActions> <QCardActions>
<QBtn <QBtn
size="md" size="md"
icon="vn:supplier" icon="vn:supplier"
color="primary" color="primary"
:to="routes.getSupplier(entity.supplierFk)" :to="routes.getSupplier(invoiceIn.supplierFk)"
> >
<QTooltip>{{ t('invoiceIn.list.supplier') }}</QTooltip> <QTooltip>{{ t('invoiceIn.list.supplier') }}</QTooltip>
</QBtn> </QBtn>
@ -413,7 +402,7 @@ const createInvoiceInCorrection = async () => {
size="md" size="md"
icon="vn:entry" icon="vn:entry"
color="primary" color="primary"
:to="routes.getEntry(entity.entryFk)" :to="routes.getEntry(invoiceIn.entryFk)"
> >
<QTooltip>{{ t('Entry') }}</QTooltip> <QTooltip>{{ t('Entry') }}</QTooltip>
</QBtn> </QBtn>
@ -421,7 +410,7 @@ const createInvoiceInCorrection = async () => {
size="md" size="md"
icon="vn:ticket" icon="vn:ticket"
color="primary" color="primary"
:to="routes.getTickets(entity.supplierFk)" :to="routes.getTickets(invoiceIn.supplierFk)"
> >
<QTooltip>{{ t('invoiceOut.card.ticketList') }}</QTooltip> <QTooltip>{{ t('invoiceOut.card.ticketList') }}</QTooltip>
</QBtn> </QBtn>

View File

@ -11,7 +11,7 @@ import SupplierDescriptorProxy from 'src/pages/Supplier/Card/SupplierDescriptorP
import InvoiceIntoBook from '../InvoiceInToBook.vue'; import InvoiceIntoBook from '../InvoiceInToBook.vue';
import VnTitle from 'src/components/common/VnTitle.vue'; import VnTitle from 'src/components/common/VnTitle.vue';
const props = defineProps({ id: { type: Number, default: 0 } }); const props = defineProps({ id: { type: [Number, String], default: 0 } });
const { t } = useI18n(); const { t } = useI18n();
const entityId = computed(() => props.id || useRoute().params.id); const entityId = computed(() => props.id || useRoute().params.id);
@ -20,7 +20,6 @@ const invoiceIn = computed(() => useArrayData('InvoiceIn').store.data);
const invoiceInUrl = ref(); const invoiceInUrl = ref();
const amountsNotMatch = ref(null); const amountsNotMatch = ref(null);
const intrastatTotals = ref({ amount: 0, net: 0, stems: 0 }); const intrastatTotals = ref({ amount: 0, net: 0, stems: 0 });
const isBooked = ref();
const vatColumns = ref([ const vatColumns = ref([
{ {
@ -156,37 +155,26 @@ onMounted(async () => {
invoiceInUrl.value = `${await getUrl('')}invoiceIn/${entityId.value}/`; invoiceInUrl.value = `${await getUrl('')}invoiceIn/${entityId.value}/`;
}); });
function getAmountNotMatch(totals) {
return (
totals.totalDueDay != totals.totalTaxableBase &&
totals.totalDueDay != totals.totalVat
);
}
function getTaxTotal(tax) {
return tax.reduce(
(acc, cur) => acc + taxRate(cur.taxableBase, cur.taxTypeSage?.rate),
0
);
}
const init = (data) => { const init = (data) => {
if (!data) return; if (!data) return;
isBooked.value = data.isBooked; const { totals, invoiceInIntrastat } = data;
amountsNotMatch.value = getAmountNotMatch(data.totals); amountsNotMatch.value =
totals.totalDueDay != totals.totalTaxableBase &&
totals.totalDueDay != totals.totalVat;
if (data.invoiceInIntrastat.length) { invoiceInIntrastat.forEach((val) => {
data.invoiceInIntrastat.forEach((val) => {
intrastatTotals.value.amount += val.amount; intrastatTotals.value.amount += val.amount;
intrastatTotals.value.net += val.net; intrastatTotals.value.net += val.net;
intrastatTotals.value.stems += val.stems; intrastatTotals.value.stems += val.stems;
}); });
}
}; };
const taxRate = (taxableBase = 0, rate = 0) => (rate / 100) * taxableBase; const taxRate = (taxableBase = 0, rate = 0) => (rate / 100) * taxableBase;
const getTotalTax = (tax) =>
tax.reduce((acc, cur) => acc + taxRate(cur.taxableBase, cur.taxTypeSage?.rate), 0);
const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`; const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
</script> </script>
@ -199,7 +187,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
<template #header="{ entity }"> <template #header="{ entity }">
<div>{{ entity.id }} - {{ entity.supplier?.name }}</div> <div>{{ entity.id }} - {{ entity.supplier?.name }}</div>
</template> </template>
<template #header-right v-if="!isBooked"> <template #header-right v-if="!invoiceIn?.isBooked">
<InvoiceIntoBook> <InvoiceIntoBook>
<template #content="{ book }"> <template #content="{ book }">
<QBtn <QBtn
@ -288,11 +276,9 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
:label="t('invoiceIn.summary.company')" :label="t('invoiceIn.summary.company')"
:value="entity.company?.code" :value="entity.company?.code"
/> />
<QCheckbox <VnLv
v-if="invoiceIn"
:label="t('invoiceIn.summary.booked')" :label="t('invoiceIn.summary.booked')"
v-model="invoiceIn.isBooked" :value="invoiceIn.isBooked"
:disable="true"
/> />
</QCard> </QCard>
<QCard class="vn-one"> <QCard class="vn-one">
@ -352,7 +338,7 @@ const getLink = (param) => `#/invoice-in/${entityId.value}/${param}`;
<QTd>{{ toCurrency(entity.totals.totalTaxableBase) }}</QTd> <QTd>{{ toCurrency(entity.totals.totalTaxableBase) }}</QTd>
<QTd></QTd> <QTd></QTd>
<QTd></QTd> <QTd></QTd>
<QTd>{{ toCurrency(getTaxTotal(entity.invoiceInTax)) }}</QTd> <QTd>{{ toCurrency(getTotalTax(entity.invoiceInTax)) }}</QTd>
<QTd></QTd> <QTd></QTd>
</QTr> </QTr>
</template> </template>

View File

@ -4,33 +4,17 @@ import { useI18n } from 'vue-i18n';
import VnSelect from 'components/common/VnSelect.vue'; import VnSelect from 'components/common/VnSelect.vue';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue'; import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import FetchData from 'components/FetchData.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 VnCurrency from 'src/components/common/VnCurrency.vue'; import VnCurrency from 'src/components/common/VnCurrency.vue';
const { t } = useI18n(); const { t } = useI18n();
const props = defineProps({ defineProps({ dataKey: { type: String, required: true } });
dataKey: {
type: String,
required: true,
},
});
const suppliers = ref([]); const suppliers = ref([]);
const suppliersRef = ref();
</script> </script>
<template> <template>
<FetchData <VnFilterPanel :data-key="dataKey" :search-button="true">
ref="suppliersRef"
url="Suppliers"
:filter="{ fields: ['id', 'nickname'] }"
order="nickname"
limit="30"
@on-fetch="(data) => (suppliers = data)"
auto-load
/>
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
<template #tags="{ tag, formatFn }"> <template #tags="{ tag, formatFn }">
<div class="q-gutter-x-xs"> <div class="q-gutter-x-xs">
<strong>{{ t(`params.${tag.label}`) }}: </strong> <strong>{{ t(`params.${tag.label}`) }}: </strong>
@ -38,22 +22,6 @@ const suppliersRef = ref();
</div> </div>
</template> </template>
<template #body="{ params, searchFn }"> <template #body="{ params, searchFn }">
<QItem>
<QItemSection>
<VnSelect
:label="t('params.supplierFk')"
v-model="params.supplierFk"
:options="suppliers"
option-value="id"
option-label="nickname"
@input-value="suppliersRef.fetch()"
dense
outlined
rounded
>
</VnSelect>
</QItemSection>
</QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInput <VnInput
@ -68,21 +36,11 @@ const suppliersRef = ref();
</VnInput> </VnInput>
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem>
<QItemSection>
<VnInputDate :label="t('From')" v-model="params.from" is-outlined />
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInputDate :label="t('To')" v-model="params.to" is-outlined />
</QItemSection>
</QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInput <VnInput
:label="t('params.serial')" :label="t('params.fi')"
v-model="params.serial" v-model="params.fi"
is-outlined is-outlined
lazy-rules lazy-rules
> >
@ -92,11 +50,61 @@ const suppliersRef = ref();
</VnInput> </VnInput>
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem>
<QItemSection>
<VnSelect
v-model="params.supplierFk"
url="Suppliers"
:fields="['id', 'nickname']"
:label="t('params.supplierFk')"
option-value="id"
option-label="nickname"
:options="suppliers"
dense
outlined
rounded
>
</VnSelect>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInput
:label="t('params.account')"
v-model="params.account"
is-outlined
lazy-rules
>
<template #prepend>
<QIcon name="person" size="sm" />
</template>
</VnInput>
</QItemSection>
</QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnCurrency v-model="params.amount" is-outlined /> <VnCurrency v-model="params.amount" is-outlined />
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem>
<QItemSection>
<VnInputDate :label="t('From')" v-model="params.from" is-outlined />
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInputDate :label="t('To')" v-model="params.to" is-outlined />
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInputDate
:label="t('Issued')"
v-model="params.issued"
is-outlined
/>
</QItemSection>
</QItem>
<QItem class="q-mb-md"> <QItem class="q-mb-md">
<QItemSection> <QItemSection>
<QCheckbox <QCheckbox
@ -111,8 +119,8 @@ const suppliersRef = ref();
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInput <VnInput
:label="t('params.fi')" :label="t('params.serialNumber')"
v-model="params.fi" v-model="params.serialNumber"
is-outlined is-outlined
lazy-rules lazy-rules
> >
@ -125,8 +133,8 @@ const suppliersRef = ref();
<QItem> <QItem>
<QItemSection> <QItemSection>
<VnInput <VnInput
:label="t('params.serialNumber')" :label="t('params.serial')"
v-model="params.serialNumber" v-model="params.serial"
is-outlined is-outlined
lazy-rules lazy-rules
> >
@ -150,29 +158,6 @@ const suppliersRef = ref();
</VnInput> </VnInput>
</QItemSection> </QItemSection>
</QItem> </QItem>
<QItem>
<QItemSection>
<VnInput
:label="t('params.account')"
v-model="params.account"
is-outlined
lazy-rules
>
<template #prepend>
<QIcon name="person" size="sm" />
</template>
</VnInput>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<VnInputDate
:label="t('Issued')"
v-model="params.issued"
is-outlined
/>
</QItemSection>
</QItem>
</QExpansionItem> </QExpansionItem>
</template> </template>
</VnFilterPanel> </VnFilterPanel>