import { defineStore } from 'pinia'; import { useUserConfig } from 'src/composables/useUserConfig'; import { exportFile } from 'quasar'; import { useArrayData } from 'composables/useArrayData'; import useNotify from 'src/composables/useNotify.js'; import axios from 'axios'; const { notify } = useNotify(); export const useInvoiceOutGlobalStore = defineStore({ id: 'invoiceOutGlobal', state: () => ({ initialDataLoading: true, formInitialData: { companyFk: null, invoiceDate: null, maxShipped: null, clientId: null, printer: null, }, addresses: [], minInvoicingDate: null, parallelism: null, invoicing: false, isInvoicing: false, status: null, addressIndex: 0, errors: [], printer: null, 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.fetchParallelism(), this.fetchInvoiceOutConfig(userInfo.companyFk), ]); this.initialDataLoading = false; } catch (err) { console.error('Error fetching invoice out global initial data'); } }, async fetchInvoiceOutConfig(companyFk) { try { this.formInitialData.companyFk = companyFk; const params = { companyFk: companyFk }; const { data } = await axios.get('InvoiceOuts/getInvoiceDate', { params, }); const stringDate = data.issued.substring(0, 10); this.minInvoicingDate = stringDate; this.formInitialData.invoiceDate = stringDate; this.minInvoicingDate = new Date(data.issued); this.formInitialData.invoiceDate = this.minInvoicingDate; } catch (err) { console.error('Error fetching invoice out global initial data'); throw new Error(); } }, async fetchParallelism() { const filter = { fields: ['parallelism'] }; const { data } = await axios.get('InvoiceOutConfigs/findOne', { filter, }); this.parallelism = data.parallelism; }, async makeInvoice(formData, clientsToInvoice) { this.invoicing = true; this.status = 'packageInvoicing'; try { this.printer = formData.printer; const params = { invoiceDate: new Date(formData.invoiceDate), maxShipped: new Date(formData.maxShipped), clientId: formData.clientId ? formData.clientId : null, companyFk: formData.companyFk, }; this.validateMakeInvoceParams(params, clientsToInvoice); if (clientsToInvoice == 'all') params.clientId = undefined; const { data } = await axios.post('InvoiceOuts/clientsToInvoice', params); this.addresses = data; if (!this.addresses || !this.addresses.length > 0) { notify( 'invoiceOut.globalInvoices.errors.noTicketsToInvoice', 'negative' ); throw new Error("There aren't addresses to invoice"); } for (const address of this.addresses) { 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) { try { 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, }; this.status = 'invoicing'; this.invoicing = true; const { data } = await axios.post('InvoiceOuts/invoiceClient', params); if (data) { await this.makePdfAndNotify(data, address); } this.isInvoicing = false; } catch (err) { if ( err && err.response && err.response.status >= 400 && err.response.status < 500 ) { this.invoiceClientError(address, err.response?.data?.error?.message); this.addressIndex++; return; } else { this.invoicing = false; this.status = 'done'; notify( 'invoiceOut.globalInvoices.errors.criticalInvoiceError', 'negative' ); throw new Error('Critical invoicing error, process stopped'); } } }, async makePdfAndNotify(invoiceId, client) { try { this.nRequests++; this.totalPdfs++; const params = { printerFk: this.printer }; await axios.post(`InvoiceOuts/${invoiceId}/makePdfAndNotify`, params); this.nPdfs++; this.nRequests--; } catch (err) { this.invoiceClientError(client, err.response?.data?.error?.message, true); } }, invoiceClientError(client, message, isWarning) { this.errors.unshift({ client, message, isWarning }); }, handleError(err) { this.invoicing = false; this.status = null; throw err; }, async getNegativeBasesCsv() { try { const arrayData = useArrayData('InvoiceOutNegative'); const params = arrayData.store.currentFilter; const { data } = await axios.get('InvoiceOuts/negativeBasesCsv', { params, }); if (data.data && data.data.error) throw new Error(); const status = exportFile('negativeBases.csv', data, { encoding: 'windows-1252', mimeType: 'text/csv;charset=windows-1252;', }); if (status) { notify('globals.downloadCSVSuccess', 'positive'); } } catch (err) { notify('invoiceOut.negativeBases.errors.downloadCsvFailed', 'negative'); throw new Error(); } }, // State mutations actions 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; }, }, });