salix-front/src/pages/InvoiceIn/Card/InvoiceInBasicData.vue

588 lines
21 KiB
Vue

<script setup>
import { ref, computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import axios from 'axios';
import { useArrayData } from 'src/composables/useArrayData';
import { downloadFile } from 'src/composables/downloadFile';
import FormModel from 'components/FormModel.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import FetchData from 'src/components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnInput from 'src/components/common/VnInput.vue';
const quasar = useQuasar();
const { t } = useI18n();
const dms = ref({});
const route = useRoute();
const editDownloadDisabled = ref(false);
const invoiceIn = computed(() => useArrayData(route.meta.moduleName).store.data);
const userConfig = ref(null);
const invoiceId = computed(() => +route.params.id);
const expenses = ref([]);
const currencies = ref([]);
const currenciesRef = ref();
const companies = ref([]);
const companiesRef = ref();
const dmsTypes = ref([]);
const dmsTypesRef = ref();
const warehouses = ref([]);
const warehousesRef = ref();
const allowTypesRef = ref();
const allowedContentTypes = ref([]);
const sageWithholdings = ref([]);
const inputFileRef = ref();
const editDmsRef = ref();
const createDmsRef = ref();
async function checkFileExists(dmsId) {
if (!dmsId) return;
try {
await axios.get(`Dms/${dmsId}`, { fields: ['id'] });
editDownloadDisabled.value = false;
} catch (e) {
editDownloadDisabled.value = true;
}
}
async function setEditDms(dmsId) {
const { data } = await axios.get(`Dms/${dmsId}`);
dms.value = {
warehouseId: data.warehouseFk,
companyId: data.companyFk,
dmsTypeId: data.dmsTypeFk,
...data,
};
if (!allowedContentTypes.value.length) await allowTypesRef.value.fetch();
editDmsRef.value.show();
}
async function setCreateDms() {
const { data } = await axios.get('DmsTypes/findOne', {
where: { code: 'invoiceIn' },
});
dms.value = {
reference: invoiceIn.value.supplierRef,
warehouseId: userConfig.value.warehouseFk,
companyId: userConfig.value.companyFk,
dmsTypeId: data.id,
description: invoiceIn.value.supplier.name,
hasFile: true,
hasFileAttached: true,
files: null,
};
createDmsRef.value.show();
}
async function upsert() {
try {
const isEdit = !!dms.value.id;
const errors = {
companyId: `The company can't be empty`,
warehouseId: `The warehouse can't be empty`,
dmsTypeId: `The DMS Type can't be empty`,
description: `The description can't be empty`,
};
Object.keys(errors).forEach((key) => {
if (!dms.value[key]) throw Error(t(errors[key]));
});
if (!isEdit && !dms.value.files) throw Error(t(`The files can't be empty`));
const formData = new FormData();
if (dms.value.files) {
for (let i = 0; i < dms.value.files.length; i++)
formData.append(dms.value.files[i].name, dms.value.files[i]);
dms.value.hasFileAttached = true;
}
const url = isEdit ? `dms/${dms.value.id}/updateFile` : 'Dms/uploadFile';
const { data } = await axios.post(url, formData, {
params: dms.value,
});
if (data.length) invoiceIn.value.dmsFk = data[0].id;
if (!isEdit) {
createDmsRef.value.hide();
} else {
editDmsRef.value.hide();
}
quasar.notify({
message: t('globals.dataSaved'),
type: 'positive',
});
} catch (error) {
quasar.notify({
message: t(`${error.message}`),
type: 'negative',
});
}
}
</script>
<template>
<FetchData
ref="currenciesRef"
url="Currencies"
:filter="{ fields: ['id', 'code'] }"
sort-by="code"
@on-fetch="(data) => (currencies = data)"
auto-load
/>
<FetchData
ref="companiesRef"
url="Companies"
:filter="{ fields: ['id', 'code'] }"
sort-by="code"
@on-fetch="(data) => (companies = data)"
auto-load
/>
<FetchData
ref="dmsTypesRef"
url="DmsTypes"
:filter="{ fields: ['id', 'name'] }"
sort-by="name"
@on-fetch="(data) => (dmsTypes = data)"
auto-load
/>
<FetchData
ref="warehousesRef"
url="Warehouses"
:filter="{ fields: ['id', 'name'] }"
sort-by="name"
@on-fetch="(data) => (warehouses = data)"
auto-load
/>
<FetchData
ref="allowTypesRef"
url="DmsContainers/allowedContentTypes"
@on-fetch="(data) => (allowedContentTypes = data)"
auto-load
/>
<FetchData
url="UserConfigs/getUserConfig"
@on-fetch="(data) => (userConfig = data)"
auto-load
/>
<FetchData url="Expenses" auto-load @on-fetch="(data) => (expenses = data)" />
<FetchData
url="SageWithholdings"
auto-load
@on-fetch="(data) => (sageWithholdings = data)"
/>
<FormModel
model="InvoiceIn"
:go-to="`/invoice-in/${invoiceId}/vat`"
auto-load
:url-update="`InvoiceIns/${invoiceId}/updateInvoiceIn`"
>
<template #form="{ data }">
<VnRow>
<VnSelect
:label="t('supplierFk')"
v-model="data.supplierFk"
option-value="id"
option-label="nickname"
url="Suppliers"
:fields="['id', 'nickname']"
sort-by="nickname"
:is-clearable="false"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{
`${scope.opt.id} - ${scope.opt.nickname}`
}}</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnInput
clearable
clear-icon="close"
:label="t('Supplier ref')"
v-model="data.supplierRef"
/>
</VnRow>
<VnRow>
<VnInputDate :label="t('Expedition date')" v-model="data.issued" />
<VnInputDate
:label="t('Operation date')"
v-model="data.operated"
autofocus
/>
</VnRow>
<VnRow>
<VnSelect
:label="t('Undeductible VAT')"
v-model="data.deductibleExpenseFk"
:options="expenses"
option-value="id"
option-label="id"
:filter-options="['id', 'name']"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
{{ `${scope.opt.id}: ${scope.opt.name}` }}
</QItem>
</template>
</VnSelect>
<VnInput
:label="t('Document')"
v-model="data.dmsFk"
clearable
clear-icon="close"
@update:model-value="checkFileExists(data.dmsFk)"
>
<template #prepend>
<QBtn
v-if="data.dmsFk"
:class="{
'no-pointer-events': editDownloadDisabled,
}"
:disable="editDownloadDisabled"
icon="cloud_download"
:title="t('Download file')"
padding="xs"
round
@click="downloadFile(data.dmsFk)"
/>
</template>
<template #append>
<QBtn
:class="{
'no-pointer-events': editDownloadDisabled,
}"
:disable="editDownloadDisabled"
v-if="data.dmsFk"
icon="edit"
round
padding="xs"
@click="setEditDms(data.dmsFk)"
>
<QTooltip>{{ t('Edit document') }}</QTooltip>
</QBtn>
<QBtn
v-else
icon="add_circle"
round
padding="xs"
@click="setCreateDms()"
>
<QTooltip>{{ t('Create document') }}</QTooltip>
</QBtn>
</template>
</VnInput>
</VnRow>
<VnRow>
<VnInputDate :label="t('Entry date')" v-model="data.bookEntried" />
<VnInputDate :label="t('Accounted date')" v-model="data.booked" />
</VnRow>
<VnRow>
<VnSelect
:label="t('Currency')"
v-model="data.currencyFk"
:options="currencies"
option-value="id"
option-label="code"
/>
<VnSelect
v-if="companiesRef"
:label="t('Company')"
v-model="data.companyFk"
:options="companies"
option-value="id"
option-label="code"
/>
</VnRow>
<VnRow>
<VnSelect
:label="t('invoiceIn.summary.sage')"
v-model="data.withholdingSageFk"
:options="sageWithholdings"
option-value="id"
option-label="withholding"
/>
</VnRow>
</template>
</FormModel>
<QDialog ref="editDmsRef">
<QCard>
<QCardSection class="q-pb-none">
<QItem class="q-px-none">
<span class="text-primary text-h6 full-width">
<QIcon name="edit" class="q-mr-xs" />
{{ t('Edit document') }}
</span>
<QBtn icon="close" flat round dense v-close-popup />
</QItem>
</QCardSection>
<QCardSection class="q-py-none">
<QItem>
<VnInput
class="full-width q-pa-xs"
:label="t('Reference')"
v-model="dms.reference"
clearable
clear-icon="close"
/>
<VnSelect
class="full-width q-pa-xs"
:label="t('Company')"
v-model="dms.companyId"
:options="companies"
option-value="id"
option-label="code"
:required="true"
/>
</QItem>
<QItem>
<VnSelect
class="full-width q-pa-xs"
:label="t('Warehouse')"
v-model="dms.warehouseId"
:options="warehouses"
option-value="id"
option-label="name"
:required="true"
/>
<VnSelect
class="full-width q-pa-xs"
:label="t('Type')"
v-model="dms.dmsTypeId"
:options="dmsTypes"
option-value="id"
option-label="name"
:required="true"
/>
</QItem>
<QItem>
<VnInput
:label="t('Description')"
v-model="dms.description"
:required="true"
type="textarea"
class="full-width q-pa-xs"
size="lg"
autogrow
clearable
clear-icon="close"
/>
</QItem>
<QItem>
<QFile
ref="inputFileRef"
class="full-width q-pa-xs"
:label="t('File')"
v-model="dms.files"
multiple
:accept="allowedContentTypes.join(',')"
clearable
clear-icon="close"
>
<template #append>
<QBtn
icon="attach_file_add"
flat
round
padding="xs"
@click="inputFileRef.pickFiles()"
>
<QTooltip>
{{ t('globals.selectFile') }}
</QTooltip>
</QBtn>
<QBtn icon="info" flat round padding="xs">
<QTooltip max-width="30rem">
{{
`${t(
'Allowed content types'
)}: ${allowedContentTypes.join(', ')}`
}}
</QTooltip>
</QBtn>
</template>
</QFile>
</QItem>
<QItem>
<QCheckbox
:label="t('Generate identifier for original file')"
v-model="dms.hasFile"
/>
</QItem>
</QCardSection>
<QCardActions class="justify-end">
<QBtn flat :label="t('globals.close')" color="primary" v-close-popup />
<QBtn :label="t('globals.save')" color="primary" @click="upsert" />
</QCardActions>
</QCard>
</QDialog>
<QDialog ref="createDmsRef">
<QCard>
<QCardSection class="q-pb-none">
<QItem>
<span class="text-primary text-h6 full-width">
<QIcon name="edit" class="q-mr-xs" />
{{ t('Create document') }}
</span>
<QBtn icon="close" flat round dense v-close-popup align="right" />
</QItem>
</QCardSection>
<QCardSection class="q-pb-none">
<QItem>
<VnInput
class="full-width q-pa-xs"
:label="t('Reference')"
v-model="dms.reference"
/>
<VnSelect
class="full-width q-pa-xs"
:label="`${t('Company')}*`"
v-model="dms.companyId"
:options="companies"
option-value="id"
option-label="code"
:required="true"
/>
</QItem>
<QItem>
<VnSelect
class="full-width q-pa-xs"
:label="`${t('Warehouse')}*`"
v-model="dms.warehouseId"
:options="warehouses"
option-value="id"
option-label="name"
:required="true"
/>
<VnSelect
class="full-width q-pa-xs"
:label="`${t('Type')}*`"
v-model="dms.dmsTypeId"
:options="dmsTypes"
option-value="id"
option-label="name"
:required="true"
/>
</QItem>
<QItem>
<VnInput
class="full-width q-pa-xs"
type="textarea"
size="lg"
autogrow
:label="`${t('Description')}*`"
v-model="dms.description"
clearable
clear-icon="close"
:rules="[(val) => val.length || t('Required field')]"
/>
</QItem>
<QItem>
<QFile
ref="inputFileRef"
class="full-width q-pa-xs"
:label="t('File')"
v-model="dms.files"
multiple
:accept="allowedContentTypes.join(',')"
clearable
clear-icon="close"
>
<template #append>
<QBtn
icon="attach_file_add"
flat
round
padding="xs"
@click="inputFileRef.pickFiles()"
>
<QTooltip>
{{ t('globals.selectFile') }}
</QTooltip>
</QBtn>
<QBtn icon="info" flat round padding="xs">
<QTooltip max-width="30rem">
{{
`${t(
'Allowed content types'
)}: ${allowedContentTypes.join(', ')}`
}}
</QTooltip>
</QBtn>
</template>
</QFile>
</QItem>
<QItem>
<QCheckbox
:label="t('Generate identifier for original file')"
v-model="dms.hasFile"
/>
</QItem>
</QCardSection>
<QCardActions align="right">
<QBtn flat :label="t('globals.close')" color="primary" v-close-popup />
<QBtn :label="t('globals.save')" color="primary" @click="upsert" />
</QCardActions>
</QCard>
</QDialog>
</template>
<style lang="scss" scoped>
@media (max-width: $breakpoint-xs) {
.column {
.row:not(:last-child) {
flex-direction: column;
}
}
.q-dialog {
.q-card {
&__section:not(:first-child) {
.q-item {
flex-direction: column;
}
}
}
}
}
</style>
<i18n>
en:
supplierFk: Supplier
es:
supplierFk: Proveedor
Supplier ref: Ref. proveedor
Expedition date: Fecha expedición
Operation date: Fecha operación
Undeductible VAT: Iva no deducible
Document: Documento
Download file: Descargar archivo
Entry date: Fecha asiento
Accounted date: Fecha contable
Currency: Moneda
Company: Empresa
Edit document: Editar documento
Reference: Referencia
Type: Tipo
Description: Descripción
Generate identifier for original file: Generar identificador para archivo original
File: Fichero
Create document: Crear documento
Allowed content types: Tipos de archivo permitidos
The company can't be empty: La empresa no puede estar vacía
The warehouse can't be empty: El almacén no puede estar vacío
The DMS Type can't be empty: El dms no puede estar vacío
The description can't be empty: La descripción no puede estar vacía
The files can't be empty: Los archivos no pueden estar vacíos
</i18n>