import { defineStore } from 'pinia'; import { useUserConfig } from 'src/composables/useUserConfig'; import invoiceOutService from 'src/services/invoiceOut.service'; 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; }, }, });