forked from verdnatura/salix-front
form integration and view content
This commit is contained in:
parent
505052d84d
commit
c3b9f013f6
|
@ -0,0 +1,15 @@
|
||||||
|
import { Notify } from 'quasar';
|
||||||
|
import { i18n } from 'src/boot/i18n';
|
||||||
|
|
||||||
|
export default function useNotify() {
|
||||||
|
const notify = (message, type) => {
|
||||||
|
Notify.create({
|
||||||
|
message: i18n.global.t(message),
|
||||||
|
type: type,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
notify,
|
||||||
|
};
|
||||||
|
}
|
|
@ -390,6 +390,18 @@ export default {
|
||||||
shipped: 'Shipped',
|
shipped: 'Shipped',
|
||||||
totalWithVat: 'Amount',
|
totalWithVat: 'Amount',
|
||||||
},
|
},
|
||||||
|
globalInvoices: {
|
||||||
|
errors: {
|
||||||
|
chooseValidClient: 'Choose a valid client',
|
||||||
|
chooseValidCompany: 'Choose a valid company',
|
||||||
|
chooseValidPrinter: 'Choose a valid printer',
|
||||||
|
fillDates: 'Invoice date and the max date should be filled',
|
||||||
|
invoiceDateLessThanMaxDate: "Invoice date can't be less than max date",
|
||||||
|
invoiceWithFutureDate: 'Exists an invoice with a future date',
|
||||||
|
noTicketsToInvoice: "There aren't clients to invoice",
|
||||||
|
criticalInvoiceError: 'Critical invoicing error, process stopped',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
worker: {
|
worker: {
|
||||||
pageTitles: {
|
pageTitles: {
|
||||||
|
|
|
@ -390,6 +390,20 @@ export default {
|
||||||
shipped: 'F. envío',
|
shipped: 'F. envío',
|
||||||
totalWithVat: 'Importe',
|
totalWithVat: 'Importe',
|
||||||
},
|
},
|
||||||
|
globalInvoices: {
|
||||||
|
errors: {
|
||||||
|
chooseValidClient: 'Selecciona un cliente válido',
|
||||||
|
chooseValidCompany: 'Selecciona una empresa válida',
|
||||||
|
chooseValidPrinter: 'Selecciona una impresora válida',
|
||||||
|
fillDates:
|
||||||
|
'La fecha de la factura y la fecha máxima deben estar completas',
|
||||||
|
invoiceDateLessThanMaxDate:
|
||||||
|
'La fecha de la factura no puede ser menor que la fecha máxima',
|
||||||
|
invoiceWithFutureDate: 'Existe una factura con una fecha futura',
|
||||||
|
noTicketsToInvoice: 'No hay clientes para facturar',
|
||||||
|
criticalInvoiceError: 'Error crítico en la facturación, proceso detenido',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
worker: {
|
worker: {
|
||||||
pageTitles: {
|
pageTitles: {
|
||||||
|
|
|
@ -1,17 +1,95 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, onUnmounted } from 'vue';
|
import { onMounted, onUnmounted, computed, ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter } from 'vue-router';
|
|
||||||
import { useQuasar } from 'quasar';
|
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
|
||||||
import InvoiceOutGlobalForm from './InvoiceOutGlobalForm.vue';
|
import InvoiceOutGlobalForm from './InvoiceOutGlobalForm.vue';
|
||||||
|
import { useInvoiceOutGlobalStore } from 'src/stores/invoiceOutGlobal.js';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
import { QBadge, QBtn } from 'quasar';
|
||||||
|
import CustomerDescriptor from 'src/pages/Customer/Card/CustomerDescriptor.vue';
|
||||||
|
|
||||||
const stateStore = useStateStore();
|
const stateStore = useStateStore();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const invoiceOutGlobalStore = useInvoiceOutGlobalStore();
|
||||||
|
|
||||||
|
// invoiceOutGlobalStore state and getters
|
||||||
|
const {
|
||||||
|
status,
|
||||||
|
getPercentage,
|
||||||
|
getAddressNumber,
|
||||||
|
getNAddresses,
|
||||||
|
nPdfs,
|
||||||
|
totalPdfs,
|
||||||
|
errors,
|
||||||
|
} = storeToRefs(invoiceOutGlobalStore);
|
||||||
|
|
||||||
|
const selectedCustomerId = ref(null);
|
||||||
|
|
||||||
|
const tableColumnComponents = {
|
||||||
|
clientId: {
|
||||||
|
component: QBtn,
|
||||||
|
props: { flat: true, color: 'blue' },
|
||||||
|
event: (prop) => selectCustomerId(prop.value),
|
||||||
|
},
|
||||||
|
clientName: {
|
||||||
|
component: 'span',
|
||||||
|
props: {},
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
component: 'span',
|
||||||
|
props: {},
|
||||||
|
},
|
||||||
|
nickname: {
|
||||||
|
component: 'span',
|
||||||
|
props: {},
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
component: QBadge,
|
||||||
|
props: { color: 'red' },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = ref([
|
||||||
|
{ label: 'Id', field: 'clientId', name: 'clientId', align: 'left' },
|
||||||
|
{ label: 'Cliente', field: 'clientName', name: 'clientName', align: 'left' },
|
||||||
|
{ label: 'Id dirección', field: 'id', name: 'id', align: 'left' },
|
||||||
|
{ label: 'Dirección fiscal', field: 'nickname', name: 'nickname', align: 'left' },
|
||||||
|
{ label: 'Error', field: 'message', name: 'message', align: 'left' },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const cardStatusText = computed(() => {
|
||||||
|
return t(`status.${status.value}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
const percentageStatusText = computed(() => {
|
||||||
|
return `${getPercentage.value}% (${getAddressNumber.value} ${t('of')} ${
|
||||||
|
getNAddresses.value
|
||||||
|
})`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const pdfStatusText = computed(() => {
|
||||||
|
return `${nPdfs.value} ${t('of')} ${totalPdfs.value} PDFs`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const rows = computed(() => {
|
||||||
|
if (!errors && !errors.length > 0) return [];
|
||||||
|
return errors.value.map((row) => {
|
||||||
|
return {
|
||||||
|
...row.client,
|
||||||
|
message: row.message,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const selectCustomerId = (id) => {
|
||||||
|
selectedCustomerId.value = id;
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(() => (stateStore.rightDrawer = true));
|
onMounted(() => (stateStore.rightDrawer = true));
|
||||||
onUnmounted(() => (stateStore.rightDrawer = false));
|
onUnmounted(() => {
|
||||||
|
stateStore.rightDrawer = false;
|
||||||
|
invoiceOutGlobalStore.$reset();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -20,13 +98,96 @@ onUnmounted(() => (stateStore.rightDrawer = false));
|
||||||
<InvoiceOutGlobalForm />
|
<InvoiceOutGlobalForm />
|
||||||
</QScrollArea>
|
</QScrollArea>
|
||||||
</QDrawer>
|
</QDrawer>
|
||||||
<QPage class="column items-center q-pa-md"> Aca iria una tabla </QPage>
|
|
||||||
|
<QPage class="column items-center q-pa-md">
|
||||||
|
<QCard v-if="status" class="card">
|
||||||
|
<QCardSection class="card-section">
|
||||||
|
<span class="status-text">{{ cardStatusText }}</span>
|
||||||
|
<span class="text">{{ percentageStatusText }}</span>
|
||||||
|
<span class="text">{{ pdfStatusText }}</span>
|
||||||
|
</QCardSection>
|
||||||
|
</QCard>
|
||||||
|
|
||||||
|
<QTable
|
||||||
|
v-if="rows.length > 0"
|
||||||
|
:rows="rows"
|
||||||
|
:columns="columns"
|
||||||
|
hide-bottom
|
||||||
|
row-key="id"
|
||||||
|
class="full-width q-mt-md"
|
||||||
|
>
|
||||||
|
<template #body-cell="props">
|
||||||
|
<QTd :props="props">
|
||||||
|
<component
|
||||||
|
:is="tableColumnComponents[props.col.name].component"
|
||||||
|
v-bind="tableColumnComponents[props.col.name].props"
|
||||||
|
@click="tableColumnComponents[props.col.name].event(props)"
|
||||||
|
class="col-content"
|
||||||
|
>
|
||||||
|
{{ props.value }}
|
||||||
|
<QPopupProxy>
|
||||||
|
<CustomerDescriptor
|
||||||
|
v-if="selectedCustomerId === props.value"
|
||||||
|
:id="selectedCustomerId"
|
||||||
|
/>
|
||||||
|
</QPopupProxy>
|
||||||
|
</component>
|
||||||
|
</QTd>
|
||||||
|
</template>
|
||||||
|
</QTable>
|
||||||
|
</QPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped>
|
||||||
|
.card {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #292929;
|
||||||
|
padding: 16px;
|
||||||
|
|
||||||
<!-- <i18n>
|
.card-section {
|
||||||
es:
|
display: flex;
|
||||||
Search invoice: Buscar factura emitida
|
flex-direction: column;
|
||||||
You can search by invoice reference: Puedes buscar por referencia de la factura
|
padding: 0px;
|
||||||
</i18n> -->
|
}
|
||||||
|
|
||||||
|
.status-text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #eeeeee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #aaaaaa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.col-content {
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 6px 6px 6px 6px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<i18n>
|
||||||
|
{
|
||||||
|
"en": {
|
||||||
|
"status": {
|
||||||
|
"packageInvoicing": "Build packaging tickets",
|
||||||
|
"invoicing": "Invoicing client",
|
||||||
|
"stopping": "Stopping process",
|
||||||
|
"done": "Ended process"
|
||||||
|
},
|
||||||
|
"of": "of"
|
||||||
|
},
|
||||||
|
"es": {
|
||||||
|
"status":{
|
||||||
|
"packageInvoicing": "Generación de tickets de empaque",
|
||||||
|
"invoicing": "Facturando a cliente",
|
||||||
|
"stopping": "Deteniendo proceso",
|
||||||
|
"done": "Proceso detenido",
|
||||||
|
},
|
||||||
|
"of": "de"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</i18n>
|
||||||
|
|
|
@ -1,100 +1,60 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref } from 'vue';
|
import { onMounted, ref, computed } from 'vue';
|
||||||
import invoiceOutService from 'src/services/InvoiceOut.service.js';
|
|
||||||
import { useUserConfig } from 'src/composables/useUserConfig';
|
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useInvoiceOutGlobalStore } from 'src/stores/invoiceOutGlobal.js';
|
||||||
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
const invoiceOutGlobalStore = useInvoiceOutGlobalStore();
|
||||||
|
|
||||||
|
// invoiceOutGlobalStore state and getters
|
||||||
|
const {
|
||||||
|
initialDataLoading,
|
||||||
|
formInitialData,
|
||||||
|
clientsOptions,
|
||||||
|
companiesOptions,
|
||||||
|
printersOptions,
|
||||||
|
invoicing,
|
||||||
|
printer,
|
||||||
|
status,
|
||||||
|
} = storeToRefs(invoiceOutGlobalStore);
|
||||||
|
|
||||||
|
// invoiceOutGlobalStore actions
|
||||||
|
const { makeInvoice, setPrinterValue, setStatusValue } = invoiceOutGlobalStore;
|
||||||
|
|
||||||
const formData = ref({
|
const formData = ref({
|
||||||
companyFk: null,
|
companyFk: null,
|
||||||
invoiceDate: null,
|
invoiceDate: null,
|
||||||
maxShipped: null,
|
maxShipped: null,
|
||||||
clientId: null,
|
clientId: null,
|
||||||
printer: null,
|
|
||||||
});
|
});
|
||||||
const parallelismVal = ref();
|
|
||||||
const clients = ref('all');
|
const getPrinter = computed({
|
||||||
const initialLoading = ref(true);
|
get() {
|
||||||
const companiesOptions = ref([]);
|
return printer.value;
|
||||||
const printersOptions = ref([]);
|
},
|
||||||
const clientsOptions = ref([]);
|
set(value) {
|
||||||
|
setPrinterValue(value.value);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const getStatus = computed({
|
||||||
|
get() {
|
||||||
|
return status.value;
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
setStatusValue(value.value);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const clientsToInvoice = ref('all');
|
||||||
const filteredClientsOptions = ref([]);
|
const filteredClientsOptions = ref([]);
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const date = Date.vnNew();
|
await invoiceOutGlobalStore.init();
|
||||||
const userInfo = await useUserConfig().fetch();
|
formData.value = { ...formInitialData.value };
|
||||||
formData.value.maxShipped = new Date(date.getFullYear(), date.getMonth(), 0)
|
|
||||||
.toISOString()
|
|
||||||
.substring(0, 10);
|
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
fetchClients(),
|
|
||||||
fetchParallelism(),
|
|
||||||
fetchCompanies(userInfo.companyFk),
|
|
||||||
fetchPrinters(),
|
|
||||||
fetchInvoiceOutConfig(userInfo.companyFk),
|
|
||||||
]);
|
|
||||||
|
|
||||||
initialLoading.value = false;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Estos methods de fetch idealmente deberían ir en un store
|
|
||||||
|
|
||||||
const fetchClients = async () => {
|
|
||||||
const clientsFilter = { fields: ['id', 'name'], order: 'id', limit: 30 };
|
|
||||||
const clientsResponse = await invoiceOutService.getClients(clientsFilter);
|
|
||||||
clientsOptions.value = clientsResponse.map((client) => {
|
|
||||||
return { value: client.id, label: client.name };
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchCompanies = async (companyFk) => {
|
|
||||||
const companiesFilters = { order: ['code'] };
|
|
||||||
const companiesResponse = await invoiceOutService.getCompanies(companiesFilters);
|
|
||||||
companiesOptions.value = companiesResponse.map((company) => {
|
|
||||||
return { value: company.id, label: company.code };
|
|
||||||
});
|
|
||||||
|
|
||||||
formData.value.companyFk = companiesOptions.value.find(
|
|
||||||
(company) => companyFk === company.value
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchPrinters = async () => {
|
|
||||||
const printersFilters = {
|
|
||||||
fields: ['id', 'name'],
|
|
||||||
where: { isLabeler: false },
|
|
||||||
order: 'name ASC',
|
|
||||||
limit: 30,
|
|
||||||
};
|
|
||||||
const printersResponse = await invoiceOutService.getPrinters(printersFilters);
|
|
||||||
printersOptions.value = printersResponse.map((printer) => {
|
|
||||||
return { value: printer.id, label: printer.name };
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchInvoiceOutConfig = async (companyFk) => {
|
|
||||||
const params = { companyFk: companyFk };
|
|
||||||
const { issued } = await invoiceOutService.getInvoiceOutConfig(
|
|
||||||
'InvoiceOuts/getInvoiceDate',
|
|
||||||
params
|
|
||||||
);
|
|
||||||
formData.value.invoiceDate = issued
|
|
||||||
? new Date(issued).toISOString().substring(0, 10)
|
|
||||||
: null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const fetchParallelism = async () => {
|
|
||||||
const filter = { fields: ['parallelism'] };
|
|
||||||
const { parallelism } = await invoiceOutService.getInvoiceOutConfig(
|
|
||||||
'InvoiceOutConfigs/findOne',
|
|
||||||
filter
|
|
||||||
);
|
|
||||||
parallelismVal.value = parallelism;
|
|
||||||
console.log('parallelism.value:: ', parallelismVal.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const inputSelectfilter = (val, update) => {
|
const inputSelectfilter = (val, update) => {
|
||||||
if (val === '') {
|
if (val === '') {
|
||||||
update(() => {
|
update(() => {
|
||||||
|
@ -112,29 +72,31 @@ const inputSelectfilter = (val, update) => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const makeInvoice = () => {};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<QForm v-if="!initialLoading" @submit="makeInvoice()" class="q-pa-md text-white">
|
<QForm
|
||||||
|
v-if="!initialDataLoading"
|
||||||
|
@submit="makeInvoice(formData, clientsToInvoice)"
|
||||||
|
class="q-pa-md text-white"
|
||||||
|
>
|
||||||
<div class="q-gutter-md">
|
<div class="q-gutter-md">
|
||||||
<QRadio
|
<QRadio
|
||||||
v-model="clients"
|
v-model="clientsToInvoice"
|
||||||
dense
|
dense
|
||||||
val="all"
|
val="all"
|
||||||
:label="t('allClients')"
|
:label="t('allClients')"
|
||||||
:dark="true"
|
:dark="true"
|
||||||
/>
|
/>
|
||||||
<QRadio
|
<QRadio
|
||||||
v-model="clients"
|
v-model="clientsToInvoice"
|
||||||
dense
|
dense
|
||||||
val="one"
|
val="one"
|
||||||
:label="t('oneClient')"
|
:label="t('oneClient')"
|
||||||
:dark="true"
|
:dark="true"
|
||||||
/>
|
/>
|
||||||
<QSelect
|
<QSelect
|
||||||
v-if="clients === 'one'"
|
v-if="clientsToInvoice === 'one'"
|
||||||
:options="filteredClientsOptions"
|
:options="filteredClientsOptions"
|
||||||
v-model="formData.clientId"
|
v-model="formData.clientId"
|
||||||
filled
|
filled
|
||||||
|
@ -169,13 +131,14 @@ const makeInvoice = () => {};
|
||||||
<QSelect
|
<QSelect
|
||||||
filled
|
filled
|
||||||
:options="printersOptions"
|
:options="printersOptions"
|
||||||
v-model="formData.printer"
|
v-model="getPrinter"
|
||||||
:label="t('printer')"
|
:label="t('printer')"
|
||||||
transition-show="jump-up"
|
transition-show="jump-up"
|
||||||
transition-hide="jump-up"
|
transition-hide="jump-up"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<QBtn
|
<QBtn
|
||||||
|
v-if="!invoicing"
|
||||||
:label="t('invoiceOut')"
|
:label="t('invoiceOut')"
|
||||||
type="submit"
|
type="submit"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
@ -184,6 +147,16 @@ const makeInvoice = () => {};
|
||||||
rounded
|
rounded
|
||||||
dense
|
dense
|
||||||
/>
|
/>
|
||||||
|
<QBtn
|
||||||
|
v-if="invoicing"
|
||||||
|
:label="t('stop')"
|
||||||
|
color="primary"
|
||||||
|
class="full-width q-mt-md"
|
||||||
|
unelevated
|
||||||
|
rounded
|
||||||
|
dense
|
||||||
|
@click="getStatus = 'stopping'"
|
||||||
|
/>
|
||||||
</QForm>
|
</QForm>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -197,7 +170,8 @@ const makeInvoice = () => {};
|
||||||
"company": "Company",
|
"company": "Company",
|
||||||
"printer": "Printer",
|
"printer": "Printer",
|
||||||
"invoiceOut": "Invoice out",
|
"invoiceOut": "Invoice out",
|
||||||
"client": "Client"
|
"client": "Client",
|
||||||
|
"stop": "Stop"
|
||||||
},
|
},
|
||||||
"es": {
|
"es": {
|
||||||
"invoiceDate": "Fecha de factura",
|
"invoiceDate": "Fecha de factura",
|
||||||
|
@ -207,8 +181,8 @@ const makeInvoice = () => {};
|
||||||
"company": "Empresa",
|
"company": "Empresa",
|
||||||
"printer": "Impresora",
|
"printer": "Impresora",
|
||||||
"invoiceOut": "Facturar",
|
"invoiceOut": "Facturar",
|
||||||
"client": "Cliente"
|
"client": "Cliente",
|
||||||
|
"stop": "Parar"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</i18n>
|
</i18n>
|
||||||
|
|
|
@ -1,52 +1,52 @@
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
const invoiceOutService = {
|
const request = async (method, url, params = {}) => {
|
||||||
getInvoiceOutConfig: async (path = '', params) => {
|
try {
|
||||||
try {
|
let response;
|
||||||
const { data } = await axios.get(path, {
|
|
||||||
params,
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
if (method === 'GET') {
|
||||||
} catch (err) {
|
response = await axios.get(url, { params });
|
||||||
console.error('Error fetching invoice date');
|
} else if (method === 'POST') {
|
||||||
|
response = await axios.post(url, params);
|
||||||
}
|
}
|
||||||
|
return response.data;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Error with ${method} request to ${url}`, err);
|
||||||
|
return err.response;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const invoiceOutService = {
|
||||||
|
getInvoiceDate: async (params) => {
|
||||||
|
return await request('GET', 'InvoiceOuts/getInvoiceDate', params);
|
||||||
|
},
|
||||||
|
|
||||||
|
getFindOne: async (params) => {
|
||||||
|
return await request('GET', 'InvoiceOutConfigs/findOne', params);
|
||||||
},
|
},
|
||||||
|
|
||||||
getCompanies: async (filter) => {
|
getCompanies: async (filter) => {
|
||||||
try {
|
return await request('GET', 'Companies', { filter });
|
||||||
const { data } = await axios.get('Companies', {
|
|
||||||
filter,
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error fetching companies');
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getPrinters: async (filter) => {
|
getPrinters: async (filter) => {
|
||||||
try {
|
return await request('GET', 'Printers', { filter });
|
||||||
const { data } = await axios.get('Printers', {
|
|
||||||
filter,
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Error fetching printers');
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getClients: async (filter) => {
|
getClients: async (filter) => {
|
||||||
try {
|
return await request('GET', 'Clients', { filter });
|
||||||
const { data } = await axios.get('Clients', {
|
},
|
||||||
filter,
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
getClientsToInvoice: async (params) => {
|
||||||
} catch (err) {
|
return await request('POST', 'InvoiceOuts/clientsToInvoice', params);
|
||||||
console.error('Error fetching clients');
|
},
|
||||||
}
|
|
||||||
|
invoiceClient: async (params) => {
|
||||||
|
return await request('POST', 'InvoiceOuts/invoiceClient', params);
|
||||||
|
},
|
||||||
|
|
||||||
|
makePdfAndNotify: async (invoiceId, params) => {
|
||||||
|
return await request('POST', `InvoiceOuts/${invoiceId}/makePdfAndNotify`, params);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,286 @@
|
||||||
|
import { defineStore } from 'pinia';
|
||||||
|
import { useUserConfig } from 'src/composables/useUserConfig';
|
||||||
|
import invoiceOutService from 'src/services/InvoiceOut.service.js';
|
||||||
|
import useNotify from 'src/composables/useNotify.js';
|
||||||
|
|
||||||
|
const { notify } = useNotify();
|
||||||
|
|
||||||
|
export const useInvoiceOutGlobalStore = defineStore({
|
||||||
|
id: 'invoiceOutGlobal',
|
||||||
|
|
||||||
|
state: () => ({
|
||||||
|
initialDataLoading: true,
|
||||||
|
formInitialData: {
|
||||||
|
companyFk: null,
|
||||||
|
invoiceDate: null,
|
||||||
|
maxShipped: null,
|
||||||
|
clientId: null,
|
||||||
|
},
|
||||||
|
clientsOptions: [],
|
||||||
|
companiesOptions: [],
|
||||||
|
printersOptions: [],
|
||||||
|
addresses: [],
|
||||||
|
minInvoicingDate: null,
|
||||||
|
parallelism: null,
|
||||||
|
invoicing: false,
|
||||||
|
isInvoicing: false,
|
||||||
|
status: null,
|
||||||
|
addressIndex: 0,
|
||||||
|
printer: null,
|
||||||
|
errors: [],
|
||||||
|
nRequests: 0,
|
||||||
|
nPdfs: 0,
|
||||||
|
totalPdfs: 0,
|
||||||
|
}),
|
||||||
|
actions: {
|
||||||
|
async init() {
|
||||||
|
await this.fetchAllData();
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchAllData() {
|
||||||
|
try {
|
||||||
|
const userInfo = await useUserConfig().fetch();
|
||||||
|
const date = Date.vnNew();
|
||||||
|
this.formInitialData.maxShipped = new Date(
|
||||||
|
date.getFullYear(),
|
||||||
|
date.getMonth(),
|
||||||
|
0
|
||||||
|
)
|
||||||
|
.toISOString()
|
||||||
|
.substring(0, 10);
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
this.fetchClients(),
|
||||||
|
this.fetchParallelism(),
|
||||||
|
this.fetchCompanies(userInfo.companyFk),
|
||||||
|
this.fetchPrinters(),
|
||||||
|
this.fetchInvoiceOutConfig(userInfo.companyFk),
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.initialDataLoading = false;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error fetching invoice out global initial data');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchClients() {
|
||||||
|
const clientsFilter = { fields: ['id', 'name'], order: 'id', limit: 30 };
|
||||||
|
const clientsResponse = await invoiceOutService.getClients(clientsFilter);
|
||||||
|
this.clientsOptions = clientsResponse.map((client) => {
|
||||||
|
return { value: client.id, label: client.name };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchCompanies(companyFk) {
|
||||||
|
const companiesFilters = { order: ['code'] };
|
||||||
|
const companiesResponse = await invoiceOutService.getCompanies(
|
||||||
|
companiesFilters
|
||||||
|
);
|
||||||
|
this.companiesOptions = companiesResponse.map((company) => {
|
||||||
|
return { value: company.id, label: company.code };
|
||||||
|
});
|
||||||
|
|
||||||
|
this.formInitialData.companyFk = this.companiesOptions.find(
|
||||||
|
(company) => companyFk === company.value
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchPrinters() {
|
||||||
|
const printersFilters = {
|
||||||
|
fields: ['id', 'name'],
|
||||||
|
where: { isLabeler: false },
|
||||||
|
order: 'name ASC',
|
||||||
|
limit: 30,
|
||||||
|
};
|
||||||
|
const printersResponse = await invoiceOutService.getPrinters(printersFilters);
|
||||||
|
this.printersOptions = printersResponse.map((printer) => {
|
||||||
|
return { value: printer.id, label: printer.name };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchInvoiceOutConfig(companyFk) {
|
||||||
|
const params = { companyFk: companyFk };
|
||||||
|
const { issued } = await invoiceOutService.getInvoiceDate(params);
|
||||||
|
|
||||||
|
const stringDate = issued.substring(0, 10);
|
||||||
|
this.minInvoicingDate = stringDate;
|
||||||
|
this.formInitialData.invoiceDate = stringDate;
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchParallelism() {
|
||||||
|
const filter = { fields: ['parallelism'] };
|
||||||
|
const { parallelism } = await invoiceOutService.getFindOne(filter);
|
||||||
|
this.parallelism = parallelism;
|
||||||
|
},
|
||||||
|
|
||||||
|
async makeInvoice(formData, clientsToInvoice) {
|
||||||
|
this.invoicing = true;
|
||||||
|
this.status = 'packageInvoicing';
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
invoiceDate: new Date(formData.invoiceDate),
|
||||||
|
maxShipped: new Date(formData.maxShipped),
|
||||||
|
clientId: formData.clientId ? formData.clientId.value : null,
|
||||||
|
companyFk: formData.companyFk.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.validateMakeInvoceParams(params, clientsToInvoice);
|
||||||
|
|
||||||
|
if (clientsToInvoice == 'all') params.clientId = undefined;
|
||||||
|
|
||||||
|
const addressesResponse = await invoiceOutService.getClientsToInvoice(
|
||||||
|
params
|
||||||
|
);
|
||||||
|
|
||||||
|
this.addresses = addressesResponse;
|
||||||
|
|
||||||
|
if (!this.addresses || !this.addresses.length > 0) {
|
||||||
|
notify(
|
||||||
|
'invoiceOut.globalInvoices.errors.noTicketsToInvoice',
|
||||||
|
'negative'
|
||||||
|
);
|
||||||
|
throw new Error("There aren't addresses to invoice");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addresses.forEach(async (address) => {
|
||||||
|
await this.invoiceClient(address, formData);
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
this.handleError(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
validateMakeInvoceParams(params, clientsToInvoice) {
|
||||||
|
if (clientsToInvoice === 'one' && !params.clientId) {
|
||||||
|
notify('invoiceOut.globalInvoices.errors.chooseValidClient', 'negative');
|
||||||
|
throw new Error('Invalid client');
|
||||||
|
}
|
||||||
|
if (!params.invoiceDate || !params.maxShipped) {
|
||||||
|
notify('invoiceOut.globalInvoices.errors.fillDates', 'negative');
|
||||||
|
throw new Error('Missing dates');
|
||||||
|
}
|
||||||
|
if (params.invoiceDate < params.maxShipped) {
|
||||||
|
notify(
|
||||||
|
'invoiceOut.globalInvoices.errors.invoiceDateLessThanMaxDate',
|
||||||
|
'negative'
|
||||||
|
);
|
||||||
|
throw new Error('Invalid date range');
|
||||||
|
}
|
||||||
|
|
||||||
|
const invoiceDateTime = new Date(params.invoiceDate).getTime();
|
||||||
|
const minInvoiceDateTime = new Date(this.minInvoicingDate).getTime();
|
||||||
|
|
||||||
|
if (this.minInvoicingDate && invoiceDateTime < minInvoiceDateTime) {
|
||||||
|
notify(
|
||||||
|
'invoiceOut.globalInvoices.errors.invoiceWithFutureDate',
|
||||||
|
'negative'
|
||||||
|
);
|
||||||
|
throw new Error('Invoice date in the future');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!params.companyFk) {
|
||||||
|
notify('invoiceOut.globalInvoices.errors.chooseValidCompany', 'negative');
|
||||||
|
throw new Error('Invalid company');
|
||||||
|
}
|
||||||
|
if (!this.printer) {
|
||||||
|
notify('invoiceOut.globalInvoices.errors.chooseValidPrinter', 'negative');
|
||||||
|
throw new Error('Invalid printer');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async invoiceClient(address, formData) {
|
||||||
|
if (this.nRequests === this.parallelism || this.isInvoicing) return;
|
||||||
|
|
||||||
|
if (this.status === 'stopping') {
|
||||||
|
if (this.nRequests) return;
|
||||||
|
this.invoicing = false;
|
||||||
|
this.status = 'done';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
clientId: address.clientId,
|
||||||
|
addressId: address.id,
|
||||||
|
invoiceDate: new Date(formData.invoiceDate),
|
||||||
|
maxShipped: new Date(formData.maxShipped),
|
||||||
|
companyFk: formData.companyFk.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.status = 'invoicing';
|
||||||
|
this.invoicing = true;
|
||||||
|
|
||||||
|
const invoiceResponse = await invoiceOutService.invoiceClient(params);
|
||||||
|
|
||||||
|
if (invoiceResponse.data.error) {
|
||||||
|
if (invoiceResponse.status >= 400 && invoiceResponse.status < 500) {
|
||||||
|
this.invoiceClientError(address, invoiceResponse);
|
||||||
|
this.addressIndex++;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.invoicing = false;
|
||||||
|
this.status = 'done';
|
||||||
|
notify(
|
||||||
|
'invoiceOut.globalInvoices.errors.criticalInvoiceError',
|
||||||
|
'negative'
|
||||||
|
);
|
||||||
|
throw new Error('Critical invoicing error, process stopped');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.isInvoicing = false;
|
||||||
|
if (invoiceResponse.data) {
|
||||||
|
this.makePdfAndNotify(invoiceResponse.data, address);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async makePdfAndNotify(invoiceId, client) {
|
||||||
|
try {
|
||||||
|
this.nRequests++;
|
||||||
|
this.totalPdfs++;
|
||||||
|
const params = { printerFk: this.printer.value };
|
||||||
|
await invoiceOutService.makePdfAndNotify(invoiceId, params);
|
||||||
|
this.nPdfs++;
|
||||||
|
this.nRequests--;
|
||||||
|
} catch (err) {
|
||||||
|
this.invoiceClientError(client, err, true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
invoiceClientError(client, response, isWarning) {
|
||||||
|
const message = response.data?.error?.message || response.message;
|
||||||
|
this.errors.unshift({ client, message, isWarning });
|
||||||
|
},
|
||||||
|
|
||||||
|
handleError(err) {
|
||||||
|
this.invoicing = false;
|
||||||
|
this.status = null;
|
||||||
|
throw err;
|
||||||
|
},
|
||||||
|
|
||||||
|
// State mutations actions
|
||||||
|
|
||||||
|
setPrinterValue(printer) {
|
||||||
|
this.printer = printer;
|
||||||
|
},
|
||||||
|
|
||||||
|
setStatusValue(status) {
|
||||||
|
this.status = status;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
getters: {
|
||||||
|
getNAddresses(state) {
|
||||||
|
return state.addresses.length;
|
||||||
|
},
|
||||||
|
getPercentage(state) {
|
||||||
|
if (this.getNAdresses <= 0 || !state.addressIndex) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
let porcentaje = (state.addressIndex / this.getNAddresses) * 100;
|
||||||
|
return porcentaje;
|
||||||
|
},
|
||||||
|
getAddressNumber(state) {
|
||||||
|
return state.addressIndex;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
Loading…
Reference in New Issue