mirror of
https://github.com/crater-invoice/crater.git
synced 2025-10-28 04:01:10 -04:00
v6 update
This commit is contained in:
460
resources/scripts/admin/stores/recurring-invoice.js
Normal file
460
resources/scripts/admin/stores/recurring-invoice.js
Normal file
@ -0,0 +1,460 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import axios from 'axios'
|
||||
import recurringInvoiceStub from '@/scripts/admin/stub/recurring-invoice'
|
||||
import recurringInvoiceItemStub from '@/scripts/admin/stub/recurring-invoice-item'
|
||||
import TaxStub from '../stub/tax'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useCompanyStore } from './company'
|
||||
import { useItemStore } from './item'
|
||||
import { useTaxTypeStore } from './tax-type'
|
||||
import { useCustomerStore } from './customer'
|
||||
import Guid from 'guid'
|
||||
import { handleError } from '@/scripts/helpers/error-handling'
|
||||
import moment from 'moment'
|
||||
import _ from 'lodash'
|
||||
import { useInvoiceStore } from './invoice'
|
||||
import { useNotificationStore } from '@/scripts/stores/notification'
|
||||
|
||||
export const useRecurringInvoiceStore = (useWindow = false) => {
|
||||
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
|
||||
const { global } = window.i18n
|
||||
|
||||
return defineStoreFunc({
|
||||
id: 'recurring-invoice',
|
||||
|
||||
state: () => ({
|
||||
templates: [],
|
||||
recurringInvoices: [],
|
||||
selectedRecurringInvoices: [],
|
||||
totalRecurringInvoices: 0,
|
||||
isFetchingInitialSettings: false,
|
||||
isFetchingViewData: false,
|
||||
showExchangeRate: false,
|
||||
selectAllField: false,
|
||||
newRecurringInvoice: {
|
||||
...recurringInvoiceStub(),
|
||||
},
|
||||
|
||||
frequencies: [
|
||||
{ label: 'Every Minute', value: '* * * * *' },
|
||||
{ label: 'Every 30 Minute', value: '*/30 * * * *' },
|
||||
{ label: 'Every Hour', value: '0 * * * *' },
|
||||
{ label: 'Every 2 Hour', value: '0 */2 * * *' },
|
||||
{ label: 'Twice A Day', value: '0 13-15 * * *' },
|
||||
{ label: 'Every Week', value: '0 0 * * 0' },
|
||||
{ label: 'Every 15 Days', value: '0 5 */15 * *' },
|
||||
{ label: 'First Day Of Month', value: '0 0 1 * *' },
|
||||
{ label: 'Every 6 Month', value: '0 0 1 */6 *' },
|
||||
{ label: 'Every Year', value: '0 0 1 1 *' },
|
||||
{ label: 'Custom', value: 'CUSTOM' },
|
||||
],
|
||||
}),
|
||||
|
||||
getters: {
|
||||
getSubTotal() {
|
||||
return (
|
||||
this.newRecurringInvoice?.items.reduce(function (a, b) {
|
||||
return a + b['total']
|
||||
}, 0) || 0
|
||||
)
|
||||
},
|
||||
|
||||
getTotalSimpleTax() {
|
||||
return _.sumBy(this.newRecurringInvoice.taxes, function (tax) {
|
||||
if (!tax.compound_tax) {
|
||||
return tax.amount
|
||||
}
|
||||
return 0
|
||||
})
|
||||
},
|
||||
|
||||
getTotalCompoundTax() {
|
||||
return _.sumBy(this.newRecurringInvoice.taxes, function (tax) {
|
||||
if (tax.compound_tax) {
|
||||
return tax.amount
|
||||
}
|
||||
return 0
|
||||
})
|
||||
},
|
||||
|
||||
getTotalTax() {
|
||||
if (
|
||||
this.newRecurringInvoice.tax_per_item === 'NO' ||
|
||||
this.newRecurringInvoice.tax_per_item === null
|
||||
) {
|
||||
return this.getTotalSimpleTax + this.getTotalCompoundTax
|
||||
}
|
||||
return _.sumBy(this.newRecurringInvoice.items, function (tax) {
|
||||
return tax.tax
|
||||
})
|
||||
},
|
||||
|
||||
getSubtotalWithDiscount() {
|
||||
return this.getSubTotal - this.newRecurringInvoice.discount_val
|
||||
},
|
||||
|
||||
getTotal() {
|
||||
return this.getSubtotalWithDiscount + this.getTotalTax
|
||||
},
|
||||
},
|
||||
|
||||
actions: {
|
||||
resetCurrentRecurringInvoice() {
|
||||
this.newRecurringInvoice = {
|
||||
...recurringInvoiceStub(),
|
||||
}
|
||||
},
|
||||
|
||||
deselectItem(index) {
|
||||
this.newRecurringInvoice.items[index] = {
|
||||
...recurringInvoiceItemStub,
|
||||
id: Guid.raw(),
|
||||
taxes: [{ ...TaxStub, id: Guid.raw() }],
|
||||
}
|
||||
},
|
||||
|
||||
addRecurringInvoice(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.post('/api/v1/recurring-invoices', data)
|
||||
.then((response) => {
|
||||
this.recurringInvoices = [
|
||||
...this.recurringInvoices,
|
||||
response.data.recurringInvoice,
|
||||
]
|
||||
const notificationStore = useNotificationStore()
|
||||
|
||||
notificationStore.showNotification({
|
||||
type: 'success',
|
||||
message: global.t('recurring_invoices.created_message'),
|
||||
})
|
||||
resolve(response)
|
||||
})
|
||||
.catch((err) => {
|
||||
handleError(err)
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
fetchRecurringInvoice(id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.isFetchingViewData = true
|
||||
axios
|
||||
.get(`/api/v1/recurring-invoices/${id}`)
|
||||
.then((response) => {
|
||||
Object.assign(this.newRecurringInvoice, response.data.data)
|
||||
this.newRecurringInvoice.invoices =
|
||||
response.data.data.invoices || []
|
||||
this.setSelectedFrequency()
|
||||
this.isFetchingViewData = false
|
||||
resolve(response)
|
||||
})
|
||||
.catch((err) => {
|
||||
this.isFetchingViewData = false
|
||||
handleError(err)
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
updateRecurringInvoice(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.put(`/api/v1/recurring-invoices/${data.id}`, data)
|
||||
.then((response) => {
|
||||
resolve(response)
|
||||
|
||||
const notificationStore = useNotificationStore()
|
||||
|
||||
notificationStore.showNotification({
|
||||
type: 'success',
|
||||
message: global.t('recurring_invoices.updated_message'),
|
||||
})
|
||||
|
||||
let pos = this.recurringInvoices.findIndex(
|
||||
(invoice) => invoice.id === response.data.data.id
|
||||
)
|
||||
|
||||
this.recurringInvoices[pos] = response.data.data
|
||||
})
|
||||
.catch((err) => {
|
||||
handleError(err)
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
selectCustomer(id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.get(`/api/v1/customers/${id}`)
|
||||
.then((response) => {
|
||||
this.newRecurringInvoice.customer = response.data.data
|
||||
this.newRecurringInvoice.customer_id = response.data.data.id
|
||||
resolve(response)
|
||||
})
|
||||
.catch((err) => {
|
||||
handleError(err)
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
searchRecurringInvoice(data) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.get(`/api/v1/recurring-invoices?${data}`)
|
||||
.then((response) => {
|
||||
resolve(response)
|
||||
})
|
||||
.catch((err) => {
|
||||
handleError(err)
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
fetchRecurringInvoices(params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.get(`/api/v1/recurring-invoices`, { params })
|
||||
.then((response) => {
|
||||
this.recurringInvoices = response.data.data
|
||||
this.totalRecurringInvoices =
|
||||
response.data.meta.recurring_invoice_total_count
|
||||
|
||||
resolve(response)
|
||||
})
|
||||
.catch((err) => {
|
||||
handleError(err)
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
deleteRecurringInvoice(id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.post(`/api/v1/recurring-invoices/delete`, id)
|
||||
.then((response) => {
|
||||
let index = this.recurringInvoices.findIndex(
|
||||
(invoice) => invoice.id === id
|
||||
)
|
||||
this.recurringInvoices.splice(index, 1)
|
||||
resolve(response)
|
||||
})
|
||||
.catch((err) => {
|
||||
handleError(err)
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
deleteMultipleRecurringInvoices(id) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let ids = this.selectedRecurringInvoices
|
||||
if (id) {
|
||||
ids = [id]
|
||||
}
|
||||
axios
|
||||
.post(`/api/v1/recurring-invoices/delete`, {
|
||||
ids: ids,
|
||||
})
|
||||
.then((response) => {
|
||||
this.selectedRecurringInvoices.forEach((invoice) => {
|
||||
let index = this.recurringInvoices.findIndex(
|
||||
(_inv) => _inv.id === invoice.id
|
||||
)
|
||||
this.recurringInvoices.splice(index, 1)
|
||||
})
|
||||
this.selectedRecurringInvoices = []
|
||||
resolve(response)
|
||||
})
|
||||
.catch((err) => {
|
||||
handleError(err)
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
resetSelectedCustomer() {
|
||||
this.newRecurringInvoice.customer = null
|
||||
this.newRecurringInvoice.customer_id = ''
|
||||
},
|
||||
|
||||
selectRecurringInvoice(data) {
|
||||
this.selectedRecurringInvoices = data
|
||||
if (
|
||||
this.selectedRecurringInvoices.length ===
|
||||
this.recurringInvoices.length
|
||||
) {
|
||||
this.selectAllField = true
|
||||
} else {
|
||||
this.selectAllField = false
|
||||
}
|
||||
},
|
||||
|
||||
selectAllRecurringInvoices() {
|
||||
if (
|
||||
this.selectedRecurringInvoices.length ===
|
||||
this.recurringInvoices.length
|
||||
) {
|
||||
this.selectedRecurringInvoices = []
|
||||
this.selectAllField = false
|
||||
} else {
|
||||
let allInvoiceIds = this.recurringInvoices.map(
|
||||
(invoice) => invoice.id
|
||||
)
|
||||
this.selectedRecurringInvoices = allInvoiceIds
|
||||
this.selectAllField = true
|
||||
}
|
||||
},
|
||||
|
||||
addItem() {
|
||||
this.newRecurringInvoice.items.push({
|
||||
...recurringInvoiceItemStub,
|
||||
id: Guid.raw(),
|
||||
taxes: [{ ...TaxStub, id: Guid.raw() }],
|
||||
})
|
||||
},
|
||||
|
||||
removeItem(index) {
|
||||
this.newRecurringInvoice.items.splice(index, 1)
|
||||
},
|
||||
|
||||
updateItem(data) {
|
||||
Object.assign(this.newRecurringInvoice.items[data.index], { ...data })
|
||||
},
|
||||
|
||||
async fetchRecurringInvoiceInitialSettings(isEdit) {
|
||||
const companyStore = useCompanyStore()
|
||||
const customerStore = useCustomerStore()
|
||||
const itemStore = useItemStore()
|
||||
const invoiceStore = useInvoiceStore()
|
||||
const taxTypeStore = useTaxTypeStore()
|
||||
const route = useRoute()
|
||||
|
||||
this.isFetchingInitialSettings = true
|
||||
this.newRecurringInvoice.currency = companyStore.selectedCompanyCurrency
|
||||
|
||||
if (route.query.customer) {
|
||||
let response = await customerStore.fetchCustomer(route.query.customer)
|
||||
this.newRecurringInvoice.customer = response.data.data
|
||||
this.selectCustomer(response.data.data.id)
|
||||
}
|
||||
|
||||
let editActions = []
|
||||
|
||||
// on create
|
||||
if (!isEdit) {
|
||||
this.newRecurringInvoice.tax_per_item =
|
||||
companyStore.selectedCompanySettings.tax_per_item
|
||||
this.newRecurringInvoice.discount_per_item =
|
||||
companyStore.selectedCompanySettings.discount_per_item
|
||||
this.newRecurringInvoice.sales_tax_type = companyStore.selectedCompanySettings.sales_tax_type
|
||||
this.newRecurringInvoice.sales_tax_address_type = companyStore.selectedCompanySettings.sales_tax_address_type
|
||||
this.newRecurringInvoice.starts_at = moment().format('YYYY-MM-DD')
|
||||
this.newRecurringInvoice.next_invoice_date = moment()
|
||||
.add(7, 'days')
|
||||
.format('YYYY-MM-DD')
|
||||
} else {
|
||||
editActions = [this.fetchRecurringInvoice(route.params.id)]
|
||||
}
|
||||
|
||||
Promise.all([
|
||||
itemStore.fetchItems({
|
||||
filter: {},
|
||||
orderByField: '',
|
||||
orderBy: '',
|
||||
}),
|
||||
this.resetSelectedNote(),
|
||||
invoiceStore.fetchInvoiceTemplates(),
|
||||
taxTypeStore.fetchTaxTypes({ limit: 'all' }),
|
||||
...editActions,
|
||||
])
|
||||
.then(async ([res1, res2, res3, res4, res5]) => {
|
||||
if (res3.data) {
|
||||
this.templates = invoiceStore.templates
|
||||
}
|
||||
|
||||
if (!isEdit) {
|
||||
this.setTemplate(this.templates[0].name)
|
||||
}
|
||||
|
||||
if (isEdit && res5?.data) {
|
||||
let data = {
|
||||
...res5.data.data,
|
||||
}
|
||||
|
||||
this.setTemplate(res5?.data?.data?.template_name)
|
||||
}
|
||||
if (isEdit) {
|
||||
this.addSalesTaxUs()
|
||||
}
|
||||
this.isFetchingInitialSettings = false
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
handleError(err)
|
||||
})
|
||||
},
|
||||
|
||||
addSalesTaxUs() {
|
||||
const taxTypeStore = useTaxTypeStore()
|
||||
let salesTax = { ...TaxStub }
|
||||
let found = this.newRecurringInvoice.taxes.find((_t) => _t.name === 'Sales Tax' && _t.type === 'MODULE')
|
||||
if (found) {
|
||||
for (const key in found) {
|
||||
if (Object.prototype.hasOwnProperty.call(salesTax, key)) {
|
||||
salesTax[key] = found[key]
|
||||
}
|
||||
}
|
||||
salesTax.id = found.tax_type_id
|
||||
taxTypeStore.taxTypes.push(salesTax)
|
||||
}
|
||||
},
|
||||
|
||||
setTemplate(data) {
|
||||
this.newRecurringInvoice.template_name = data
|
||||
},
|
||||
|
||||
setSelectedFrequency() {
|
||||
let data = this.frequencies.find(
|
||||
(frequency) => {
|
||||
return frequency.value === this.newRecurringInvoice.frequency
|
||||
}
|
||||
)
|
||||
data ? this.newRecurringInvoice.selectedFrequency = data
|
||||
: this.newRecurringInvoice.selectedFrequency = { label: 'Custom', value: 'CUSTOM' }
|
||||
|
||||
},
|
||||
|
||||
resetSelectedNote() {
|
||||
this.newRecurringInvoice.selectedNote = null
|
||||
},
|
||||
|
||||
fetchRecurringInvoiceFrequencyDate(params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios
|
||||
.get('/api/v1/recurring-invoice-frequency', { params })
|
||||
.then((response) => {
|
||||
this.newRecurringInvoice.next_invoice_at =
|
||||
response.data.next_invoice_at
|
||||
|
||||
resolve(response)
|
||||
})
|
||||
.catch((err) => {
|
||||
const notificationStore = useNotificationStore()
|
||||
|
||||
notificationStore.showNotification({
|
||||
type: 'error',
|
||||
message: global.t('errors.enter_valid_cron_format'),
|
||||
})
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
},
|
||||
})()
|
||||
}
|
||||
Reference in New Issue
Block a user