Merge pull request '#7346 manualInvoice' (!793) from 7346-manualInvoice into dev
gitea/salix-front/pipeline/head This commit looks good Details

Reviewed-on: #793
Reviewed-by: Javier Segarra <jsegarra@verdnatura.es>
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
This commit is contained in:
Javi Gallego 2024-11-19 07:10:06 +00:00
commit 9c271eee08
15 changed files with 282 additions and 335 deletions

View File

@ -1,155 +0,0 @@
<script setup>
import { reactive, ref, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import FetchData from 'components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue';
import FormModelPopup from './FormModelPopup.vue';
import VnInputDate from './common/VnInputDate.vue';
const emit = defineEmits(['onDataSaved']);
const { t } = useI18n();
const router = useRouter();
const manualInvoiceFormData = reactive({
maxShipped: Date.vnNew(),
});
const formModelPopupRef = ref();
const invoiceOutSerialsOptions = ref([]);
const taxAreasOptions = ref([]);
const ticketsOptions = ref([]);
const clientsOptions = ref([]);
const isLoading = computed(() => formModelPopupRef.value?.isLoading);
const onDataSaved = async (formData, requestResponse) => {
emit('onDataSaved', formData, requestResponse);
if (requestResponse && requestResponse.id)
router.push({ name: 'InvoiceOutSummary', params: { id: requestResponse.id } });
};
</script>
<template>
<FetchData
url="InvoiceOutSerials"
:filter="{ where: { code: { neq: 'R' } }, order: ['code'] }"
@on-fetch="(data) => (invoiceOutSerialsOptions = data)"
auto-load
/>
<FetchData
url="TaxAreas"
:filter="{ order: ['code'] }"
@on-fetch="(data) => (taxAreasOptions = data)"
auto-load
/>
<FormModelPopup
ref="formModelPopupRef"
:title="t('Create manual invoice')"
url-create="InvoiceOuts/createManualInvoice"
model="invoiceOut"
:form-initial-data="manualInvoiceFormData"
@on-data-saved="onDataSaved"
>
<template #form-inputs="{ data }">
<span v-if="isLoading" class="text-primary invoicing-text">
<QIcon name="warning" class="fill-icon q-mr-sm" size="md" />
{{ t('Invoicing in progress...') }}
</span>
<VnRow>
<VnSelect
:label="t('Ticket')"
:options="ticketsOptions"
hide-selected
option-label="id"
option-value="id"
v-model="data.ticketFk"
@update:model-value="data.clientFk = null"
url="Tickets"
:where="{ refFk: null }"
:fields="['id', 'nickname']"
:filter-options="{ order: 'shipped DESC' }"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel> #{{ scope.opt?.id }} </QItemLabel>
<QItemLabel caption>{{ scope.opt?.nickname }}</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
<span class="row items-center" style="max-width: max-content">{{
t('Or')
}}</span>
<VnSelect
:label="t('Client')"
:options="clientsOptions"
hide-selected
option-label="name"
option-value="id"
v-model="data.clientFk"
@update:model-value="data.ticketFk = null"
url="Clients"
:fields="['id', 'name']"
:filter-options="{ order: 'name ASC' }"
/>
<VnInputDate :label="t('Max date')" v-model="data.maxShipped" />
</VnRow>
<VnRow>
<VnSelect
:label="t('Serial')"
:options="invoiceOutSerialsOptions"
hide-selected
option-label="description"
option-value="code"
v-model="data.serial"
/>
<VnSelect
:label="t('Area')"
:options="taxAreasOptions"
hide-selected
option-label="code"
option-value="code"
v-model="data.taxArea"
/>
</VnRow>
<VnRow>
<VnInput
:label="t('Reference')"
type="textarea"
v-model="data.reference"
fill-input
autogrow
/>
</VnRow>
</template>
</FormModelPopup>
</template>
<style lang="scss" scoped>
.invoicing-text {
display: flex;
justify-content: center;
align-items: center;
color: $primary;
font-size: 24px;
margin-bottom: 8px;
}
</style>
<i18n>
es:
Create manual invoice: Crear factura manual
Ticket: Ticket
Client: Cliente
Max date: Fecha límite
Serial: Serie
Area: Area
Reference: Referencia
Or: O
Invoicing in progress...: Facturación en progreso...
</i18n>

View File

@ -162,9 +162,7 @@ onMounted(() => {
: $props.defaultMode; : $props.defaultMode;
stateStore.rightDrawer = quasar.screen.gt.xs; stateStore.rightDrawer = quasar.screen.gt.xs;
columnsVisibilitySkipped.value = [ columnsVisibilitySkipped.value = [
...splittedColumns.value.columns ...splittedColumns.value.columns.filter((c) => !c.visible).map((c) => c.name),
.filter((c) => c.visible == false)
.map((c) => c.name),
...['tableActions'], ...['tableActions'],
]; ];
createForm.value = $props.create; createForm.value = $props.create;
@ -237,7 +235,7 @@ function splitColumns(columns) {
if (col.create) splittedColumns.value.create.push(col); if (col.create) splittedColumns.value.create.push(col);
if (col.cardVisible) splittedColumns.value.cardVisible.push(col); if (col.cardVisible) splittedColumns.value.cardVisible.push(col);
if ($props.isEditable && col.disable == null) col.disable = false; if ($props.isEditable && col.disable == null) col.disable = false;
if ($props.useModel && col.columnFilter != false) if ($props.useModel && col.columnFilter !== false)
col.columnFilter = { inWhere: true, ...col.columnFilter }; col.columnFilter = { inWhere: true, ...col.columnFilter };
splittedColumns.value.columns.push(col); splittedColumns.value.columns.push(col);
} }

View File

@ -1,8 +1,7 @@
<script setup> <script setup>
import { onMounted, watch, computed, ref } from 'vue'; import { onMounted, watch, computed, ref, useAttrs } from 'vue';
import { date } from 'quasar'; import { date } from 'quasar';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useAttrs } from 'vue';
import VnDate from './VnDate.vue'; import VnDate from './VnDate.vue';
import { useRequired } from 'src/composables/useRequired'; import { useRequired } from 'src/composables/useRequired';

View File

@ -2,5 +2,12 @@
const model = defineModel({ type: Boolean, required: true }); const model = defineModel({ type: Boolean, required: true });
</script> </script>
<template> <template>
<QRadio v-model="model" v-bind="$attrs" dense :dark="true" class="q-mr-sm" /> <QRadio
v-model="model"
v-bind="$attrs"
dense
:dark="true"
class="q-mr-sm"
size="xs"
/>
</template> </template>

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="vn-row q-gutter-md q-mb-md"> <div class="vn-row q-gutter-md">
<slot /> <slot />
</div> </div>
</template> </template>
@ -18,6 +18,9 @@
&:not(.wrap) { &:not(.wrap) {
flex-direction: column; flex-direction: column;
} }
&[fixed] {
flex-direction: row;
}
} }
} }
</style> </style>

View File

@ -96,7 +96,7 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
Object.assign(params, userParams); Object.assign(params, userParams);
params.filter.skip = store.skip; params.filter.skip = store.skip;
if (store.order && store.order.length) params.filter.order = store.order; if (store.order?.length) params.filter.order = store.order;
else delete params.filter.order; else delete params.filter.order;
params.filter = JSON.stringify(params.filter); params.filter = JSON.stringify(params.filter);

View File

@ -506,6 +506,7 @@ invoiceOut:
invoiceWithFutureDate: Exists an invoice with a future date invoiceWithFutureDate: Exists an invoice with a future date
noTicketsToInvoice: There are not tickets to invoice noTicketsToInvoice: There are not tickets to invoice
criticalInvoiceError: 'Critical invoicing error, process stopped' criticalInvoiceError: 'Critical invoicing error, process stopped'
invalidSerialTypeForAll: The serial type must be global when invoicing all clients
table: table:
addressId: Address id addressId: Address id
streetAddress: Street streetAddress: Street
@ -857,6 +858,7 @@ components:
downloadFile: Download file downloadFile: Download file
openCard: View openCard: View
openSummary: Summary openSummary: Summary
viewSummary: Summary
cardDescriptor: cardDescriptor:
mainList: Main list mainList: Main list
summary: Summary summary: Summary

View File

@ -509,6 +509,7 @@ invoiceOut:
invoiceWithFutureDate: Existe una factura con una fecha futura invoiceWithFutureDate: Existe una factura con una fecha futura
noTicketsToInvoice: No existen tickets para facturar noTicketsToInvoice: No existen tickets para facturar
criticalInvoiceError: Error crítico en la facturación proceso detenido criticalInvoiceError: Error crítico en la facturación proceso detenido
invalidSerialTypeForAll: El tipo de serie debe ser global cuando se facturan todos los clientes
table: table:
addressId: Id dirección addressId: Id dirección
streetAddress: Dirección fiscal streetAddress: Dirección fiscal

View File

@ -183,7 +183,7 @@ onMounted(async () => {
<i18n> <i18n>
en: en:
invoiceDate: Invoice date invoiceDate: Invoice date
maxShipped: Max date maxShipped: Max date ticket
allClients: All clients allClients: All clients
oneClient: One client oneClient: One client
company: Company company: Company
@ -195,7 +195,7 @@ en:
es: es:
invoiceDate: Fecha de factura invoiceDate: Fecha de factura
maxShipped: Fecha límite maxShipped: Fecha límite ticket
allClients: Todos los clientes allClients: Todos los clientes
oneClient: Un solo cliente oneClient: Un solo cliente
company: Empresa company: Empresa

View File

@ -6,15 +6,19 @@ import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue'; import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { usePrintService } from 'composables/usePrintService'; import { usePrintService } from 'src/composables/usePrintService';
import VnTable from 'components/VnTable/VnTable.vue'; import VnTable from 'src/components/VnTable/VnTable.vue';
import InvoiceOutSummary from './Card/InvoiceOutSummary.vue'; import InvoiceOutSummary from './Card/InvoiceOutSummary.vue';
import { toCurrency, toDate } from 'src/filters/index'; import { toCurrency, toDate } from 'src/filters/index';
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
import { QBtn } from 'quasar'; import { QBtn } from 'quasar';
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue'; import axios from 'axios';
import RightMenu from 'src/components/common/RightMenu.vue'; import RightMenu from 'src/components/common/RightMenu.vue';
import InvoiceOutFilter from './InvoiceOutFilter.vue'; import InvoiceOutFilter from './InvoiceOutFilter.vue';
import VnRow from 'src/components/ui/VnRow.vue';
import VnRadio from 'src/components/common/VnRadio.vue';
import VnInput from 'src/components/common/VnInput.vue';
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
const { t } = useI18n(); const { t } = useI18n();
const stateStore = useStateStore(); const stateStore = useStateStore();
@ -26,99 +30,86 @@ const selectedRows = ref([]);
const hasSelectedCards = computed(() => selectedRows.value.length > 0); const hasSelectedCards = computed(() => selectedRows.value.length > 0);
const MODEL = 'InvoiceOuts'; const MODEL = 'InvoiceOuts';
const { openReport } = usePrintService(); const { openReport } = usePrintService();
const addressOptions = ref([]);
const selectedOption = ref('ticket');
async function fetchClientAddress(id) {
const { data } = await axios.get(
`Clients/${id}/addresses?filter[order]=isActive DESC`
);
addressOptions.value = data;
}
const exprBuilder = (_, value) => {
return {
or: [{ code: value }, { description: { like: `%${value}%` } }],
};
};
const columns = computed(() => [ const columns = computed(() => [
{ {
align: 'center', align: 'center',
name: 'id', name: 'id',
label: t('invoiceOutList.tableVisibleColumns.id'), label: t('invoiceOutList.tableVisibleColumns.id'),
chip: { chip: { condition: () => true },
condition: () => true,
},
isId: true, isId: true,
columnFilter: { columnFilter: { name: 'search' },
name: 'search',
},
}, },
{ {
align: 'left', align: 'left',
name: 'ref', name: 'ref',
label: t('invoiceOutList.tableVisibleColumns.ref'), label: t('globals.reference'),
isTitle: true, isTitle: true,
component: 'select', component: 'select',
attrs: { attrs: { url: MODEL, optionLabel: 'ref', optionValue: 'id' },
url: MODEL, columnField: { component: null },
optionLabel: 'ref',
optionValue: 'id',
},
columnField: {
component: null,
},
}, },
{ {
align: 'left', align: 'left',
name: 'Issued', name: 'issued',
label: t('invoiceOutList.tableVisibleColumns.issued'), label: t('invoiceOut.summary.issued'),
component: 'date', component: 'date',
format: (row) => toDate(row.issued), format: (row) => toDate(row.issued),
columnField: { columnField: { component: null },
component: null,
},
}, },
{ {
align: 'left', align: 'left',
name: 'clientFk', name: 'clientFk',
label: t('invoiceOutModule.customer'), label: t('globals.client'),
cardVisible: true, cardVisible: true,
component: 'select', component: 'select',
attrs: { attrs: { url: 'Clients', fields: ['id', 'name'] },
url: 'Clients', columnField: { component: null },
fields: ['id', 'name'],
},
columnField: {
component: null,
},
}, },
{ {
align: 'left', align: 'left',
name: 'companyCode', name: 'companyCode',
label: t('invoiceOutModule.company'), label: t('globals.company'),
cardVisible: true, cardVisible: true,
component: 'select', component: 'select',
attrs: { attrs: { url: 'Companies', optionLabel: 'code', optionValue: 'id' },
url: 'Companies', columnField: { component: null },
optionLabel: 'code',
optionValue: 'id',
},
columnField: {
component: null,
},
}, },
{ {
align: 'left', align: 'left',
name: 'amount', name: 'amount',
label: t('invoiceOutModule.amount'), label: t('globals.amount'),
cardVisible: true, cardVisible: true,
format: (row) => toCurrency(row.amount), format: (row) => toCurrency(row.amount),
}, },
{ {
align: 'left', align: 'left',
name: 'created', name: 'created',
label: t('invoiceOutList.tableVisibleColumns.created'), label: t('globals.created'),
component: 'date', component: 'date',
columnField: { columnField: { component: null },
component: null,
},
format: (row) => toDate(row.created), format: (row) => toDate(row.created),
}, },
{ {
align: 'left', align: 'left',
name: 'dued', name: 'dued',
label: t('invoiceOutList.tableVisibleColumns.dueDate'), label: t('invoiceOut.summary.dued'),
component: 'date', component: 'date',
columnField: { columnField: { component: null },
component: null,
},
format: (row) => toDate(row.dued), format: (row) => toDate(row.dued),
}, },
{ {
@ -128,11 +119,12 @@ const columns = computed(() => [
{ {
title: t('components.smartCard.viewSummary'), title: t('components.smartCard.viewSummary'),
icon: 'preview', icon: 'preview',
isPrimary: true,
action: (row) => viewSummary(row.id, InvoiceOutSummary), action: (row) => viewSummary(row.id, InvoiceOutSummary),
}, },
{ {
title: t('DownloadPdf'), title: t('globals.downloadPdf'),
icon: 'vn:ticket', icon: 'cloud_download',
isPrimary: true, isPrimary: true,
action: (row) => openPdf(row.id), action: (row) => openPdf(row.id),
}, },
@ -181,7 +173,7 @@ watchEffect(selectedRows);
<template> <template>
<VnSearchbar <VnSearchbar
:info="t('youCanSearchByInvoiceReference')" :info="t('youCanSearchByInvoiceReference')"
:label="t('searchInvoice')" :label="t('Search invoice')"
data-key="invoiceOutList" data-key="invoiceOutList"
/> />
<RightMenu> <RightMenu>
@ -197,7 +189,7 @@ watchEffect(selectedRows);
@click="downloadPdf()" @click="downloadPdf()"
:disable="!hasSelectedCards" :disable="!hasSelectedCards"
> >
<QTooltip>{{ t('globals.downloadPdf') }}</QTooltip> <QTooltip>{{ t('downloadPdf') }}</QTooltip>
</QBtn> </QBtn>
</template> </template>
</VnSubToolbar> </VnSubToolbar>
@ -207,11 +199,9 @@ watchEffect(selectedRows);
:url="`${MODEL}/filter`" :url="`${MODEL}/filter`"
:create="{ :create="{
urlCreate: 'InvoiceOuts/createManualInvoice', urlCreate: 'InvoiceOuts/createManualInvoice',
title: t('Create manual invoice'), title: t('createManualInvoice'),
onDataSaved: ({ id }) => tableRef.redirect(id), onDataSaved: ({ id }) => tableRef.redirect(id),
formInitialData: { formInitialData: { active: true },
active: true,
},
}" }"
:right-search="false" :right-search="false"
v-model:selected="selectedRows" v-model:selected="selectedRows"
@ -231,45 +221,158 @@ watchEffect(selectedRows);
</span> </span>
</template> </template>
<template #more-create-dialog="{ data }"> <template #more-create-dialog="{ data }">
<div class="flex no-wrap flex-center"> <div class="row q-col-gutter-xs">
<VnSelect <div class="col-12">
url="Tickets" <div class="q-col-gutter-xs">
<VnRow fixed>
<VnRadio
v-model="selectedOption"
val="ticket"
:label="t('globals.ticket')"
class="q-my-none q-mr-md"
/>
<VnInput
v-show="selectedOption === 'ticket'"
v-model="data.ticketFk" v-model="data.ticketFk"
:label="t('invoiceOutList.tableVisibleColumns.ticket')" :label="t('globals.ticket')"
option-label="id" style="flex: 1"
/>
<div
class="row q-col-gutter-xs q-ml-none"
v-show="selectedOption !== 'ticket'"
>
<div class="col">
<VnSelect
v-model="data.clientFk"
:label="t('globals.client')"
url="Clients"
:options="customerOptions"
option-label="name"
option-value="id" option-value="id"
@update:model-value="fetchClientAddress"
> >
<template #option="scope"> <template #option="scope">
<QItem v-bind="scope.itemProps"> <QItem
v-bind="scope.itemProps"
@click="selectedClient(scope.opt)"
>
<QItemSection> <QItemSection>
<QItemLabel> #{{ scope.opt?.id }} </QItemLabel> <QItemLabel>
<QItemLabel caption>{{ scope.opt?.nickname }}</QItemLabel> #{{ scope.opt?.id }} -
{{ scope.opt?.name }}
</QItemLabel>
</QItemSection> </QItemSection>
</QItem> </QItem>
</template> </template>
</VnSelect> </VnSelect>
<span class="q-ml-md">O</span>
</div> </div>
<div class="col">
<VnSelect <VnSelect
url="Clients" v-model="data.addressFk"
v-model="data.clientFk" :label="t('ticket.summary.consignee')"
:label="t('invoiceOutModule.customer')" :options="addressOptions"
:options="customerOptions" option-label="nickname"
option-label="name"
option-value="id" option-value="id"
v-if="
data.clientFk &&
selectedOption === 'consignatario'
"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel
:class="{
'color-vn-label':
!scope.opt?.isActive,
}"
>
{{
`${
!scope.opt?.isActive
? t('inactive')
: ''
} `
}}
<span>
{{
scope.opt?.nickname
}}</span
>
<span
v-if="
scope.opt?.province ||
scope.opt?.city ||
scope.opt?.street
"
>, {{ scope.opt?.street }},
{{ scope.opt?.city }},
{{
scope.opt?.province?.name
}}
-
{{
scope.opt?.agencyMode
?.name
}}</span
>
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</div>
</div>
</VnRow>
<VnRow fixed>
<VnRadio
v-model="selectedOption"
val="cliente"
:label="t('globals.client')"
class="q-my-none q-mr-md"
/> />
</VnRow>
<VnRow fixed>
<VnRadio
v-model="selectedOption"
val="consignatario"
:label="t('ticket.summary.consignee')"
class="q-my-none q-mr-md"
/>
</VnRow>
</div>
</div>
<div class="full-width">
<VnRow class="row q-col-gutter-xs">
<VnSelect <VnSelect
url="InvoiceOutSerials" url="InvoiceOutSerials"
v-model="data.serial" v-model="data.serial"
:label="t('invoiceOutList.tableVisibleColumns.invoiceOutSerial')" :label="t('invoiceIn.serial')"
:options="invoiceOutSerialsOptions" :options="invoiceOutSerialsOptions"
option-label="description" option-label="description"
option-value="code" option-value="code"
/> option-filter
:expr-builder="exprBuilder"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>
{{ scope.opt?.code }} -
{{ scope.opt?.description }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnInputDate <VnInputDate
:label="t('invoiceOutList.tableVisibleColumns.dueDate')" :label="t('invoiceOut.summary.dued')"
v-model="data.maxShipped" v-model="data.maxShipped"
/> />
</VnRow>
<VnRow class="row q-col-gutter-xs">
<VnSelect <VnSelect
url="TaxAreas" url="TaxAreas"
v-model="data.taxArea" v-model="data.taxArea"
@ -278,27 +381,43 @@ watchEffect(selectedRows);
option-label="code" option-label="code"
option-value="code" option-value="code"
/> />
<QInput <VnInput
v-model="data.reference" v-model="data.reference"
:label="t('invoiceOutList.tableVisibleColumns.ref')" :label="t('globals.reference')"
/> />
</VnRow>
</div>
</div>
</template> </template>
</VnTable> </VnTable>
</template> </template>
<style lang="scss" scoped>
#formModel .vn-row {
min-height: 45px;
.q-radio {
align-self: flex-end;
flex: 0.3;
}
> .q-input,
> .q-select {
flex: 0.75;
}
}
</style>
<i18n> <i18n>
en: en:
searchInvoice: Search issued invoice invoiceId: Invoice ID
fileDenied: Browser denied file download...
fileAllowed: Successful download of CSV file
youCanSearchByInvoiceReference: You can search by invoice reference youCanSearchByInvoiceReference: You can search by invoice reference
createInvoice: Make invoice createManualInvoice: Create Manual Invoice
Create manual invoice: Create manual invoice inactive: (Inactive)
es:
searchInvoice: Buscar factura emitida es:
fileDenied: El navegador denegó la descarga de archivos... invoiceId: ID de factura
fileAllowed: Descarga exitosa de archivo CSV
youCanSearchByInvoiceReference: Puedes buscar por referencia de la factura youCanSearchByInvoiceReference: Puedes buscar por referencia de la factura
createInvoice: Crear factura createManualInvoice: Crear factura manual
Create manual invoice: Crear factura manual inactive: (Inactivo)
</i18n> </i18n>

View File

@ -2,6 +2,7 @@ invoiceOutModule:
customer: Client customer: Client
amount: Amount amount: Amount
company: Company company: Company
address: Address
invoiceOutList: invoiceOutList:
tableVisibleColumns: tableVisibleColumns:
id: ID id: ID

View File

@ -4,6 +4,7 @@ invoiceOutModule:
customer: Cliente customer: Cliente
amount: Importe amount: Importe
company: Empresa company: Empresa
address: Consignatario
invoiceOutList: invoiceOutList:
tableVisibleColumns: tableVisibleColumns:
id: ID id: ID

View File

@ -1,6 +1,6 @@
<script setup> <script setup>
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { onMounted, ref } from 'vue'; import { reactive, onMounted, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import axios from 'axios'; import axios from 'axios';
import { useState } from 'composables/useState'; import { useState } from 'composables/useState';
@ -9,7 +9,6 @@ import VnRow from 'components/ui/VnRow.vue';
import VnSelect from 'components/common/VnSelect.vue'; import VnSelect from 'components/common/VnSelect.vue';
import VnInputDate from 'components/common/VnInputDate.vue'; import VnInputDate from 'components/common/VnInputDate.vue';
import { useDialogPluginComponent } from 'quasar'; import { useDialogPluginComponent } from 'quasar';
import { reactive } from 'vue';
const { t } = useI18n(); const { t } = useI18n();
const state = useState(); const state = useState();
@ -58,10 +57,6 @@ const fetchAgencyList = async (landed, addressFk) => {
} }
}; };
// const fetchOrderDetails = (order) => {
// fetchAddressList(order?.addressFk);
// fetchAgencyList(order?.landed, order?.addressFk);
// };
const $props = defineProps({ const $props = defineProps({
clientFk: { clientFk: {
type: Number, type: Number,
@ -73,39 +68,6 @@ const initialFormState = reactive({
addressId: null, addressId: null,
clientFk: $props.clientFk, clientFk: $props.clientFk,
}); });
// const orderMapper = (order) => {
// return {
// addressId: order.addressFk,
// agencyModeId: order.agencyModeFk,
// landed: new Date(order.landed).toISOString(),
// };
// };
// const orderFilter = {
// include: [
// { relation: 'agencyMode', scope: { fields: ['name'] } },
// {
// relation: 'address',
// scope: { fields: ['nickname'] },
// },
// { relation: 'rows', scope: { fields: ['id'] } },
// {
// relation: 'client',
// scope: {
// fields: [
// 'salesPersonFk',
// 'name',
// 'isActive',
// 'isFreezed',
// 'isTaxDataChecked',
// ],
// include: {
// relation: 'salesPersonUser',
// scope: { fields: ['id', 'name'] },
// },
// },
// },
// ],
// };
const onClientChange = async (clientId = $props.clientFk) => { const onClientChange = async (clientId = $props.clientFk) => {
try { try {

View File

@ -113,7 +113,7 @@ export default {
name: 'SupplierAccounts', name: 'SupplierAccounts',
meta: { meta: {
title: 'accounts', title: 'accounts',
icon: 'vn:account', icon: 'vn:credit',
}, },
component: () => component: () =>
import('src/pages/Supplier/Card/SupplierAccounts.vue'), import('src/pages/Supplier/Card/SupplierAccounts.vue'),

View File

@ -162,6 +162,15 @@ export const useInvoiceOutGlobalStore = defineStore({
); );
throw new Error('Invalid Serial Type'); throw new Error('Invalid Serial Type');
} }
if (clientsToInvoice === 'all' && params.serialType !== 'global') {
notify(
'invoiceOut.globalInvoices.errors.invalidSerialTypeForAll',
'negative'
);
throw new Error('For "all" clients, the serialType must be "global"');
}
if (!params.companyFk) { if (!params.companyFk) {
notify('invoiceOut.globalInvoices.errors.chooseValidCompany', 'negative'); notify('invoiceOut.globalInvoices.errors.chooseValidCompany', 'negative');
throw new Error('Invalid company'); throw new Error('Invalid company');