Files
crater/resources/scripts/admin/stores/estimate.js
2023-08-25 09:44:43 +05:30

579 lines
17 KiB
JavaScript

import axios from 'axios'
import moment from 'moment'
import Guid from 'guid'
import _ from 'lodash'
import { defineStore } from 'pinia'
import { useRoute } from 'vue-router'
import { useCompanyStore } from './company'
import { useCustomerStore } from './customer'
import { useNotificationStore } from '@/scripts/stores/notification'
import { useItemStore } from './item'
import { useTaxTypeStore } from './tax-type'
import { handleError } from '@/scripts/helpers/error-handling'
import estimateStub from '../stub/estimate'
import estimateItemStub from '../stub/estimate-item'
import taxStub from '../stub/tax'
import { useUserStore } from './user'
export const useEstimateStore = (useWindow = false) => {
const defineStoreFunc = useWindow ? window.pinia.defineStore : defineStore
const { global } = window.i18n
return defineStoreFunc({
id: 'estimate',
state: () => ({
templates: [],
estimates: [],
selectAllField: false,
selectedEstimates: [],
totalEstimateCount: 0,
isFetchingInitialSettings: false,
showExchangeRate: false,
newEstimate: {
...estimateStub(),
},
}),
getters: {
getSubTotal() {
return this.newEstimate.items.reduce(function (a, b) {
return a + b['total']
}, 0)
},
getTotalSimpleTax() {
return _.sumBy(this.newEstimate.taxes, function (tax) {
if (!tax.compound_tax) {
return tax.amount
}
return 0
})
},
getTotalCompoundTax() {
return _.sumBy(this.newEstimate.taxes, function (tax) {
if (tax.compound_tax) {
return tax.amount
}
return 0
})
},
getTotalTax() {
if (
this.newEstimate.tax_per_item === 'NO' ||
this.newEstimate.tax_per_item === null
) {
return this.getTotalSimpleTax + this.getTotalCompoundTax
}
return _.sumBy(this.newEstimate.items, function (tax) {
return tax.tax
})
},
getSubtotalWithDiscount() {
return this.getSubTotal - this.newEstimate.discount_val
},
getTotal() {
return this.getSubtotalWithDiscount + this.getTotalTax
},
isEdit: (state) => (state.newEstimate.id ? true : false),
},
actions: {
resetCurrentEstimate() {
this.newEstimate = {
...estimateStub(),
}
},
previewEstimate(params) {
return new Promise((resolve, reject) => {
axios
.get(`/api/v1/estimates/${params.id}/send/preview`, { params })
.then((response) => {
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
fetchEstimates(params) {
return new Promise((resolve, reject) => {
axios
.get(`/api/v1/estimates`, { params })
.then((response) => {
this.estimates = response.data.data
this.totalEstimateCount = response.data.meta.estimate_total_count
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
getNextNumber(params, setState = false) {
return new Promise((resolve, reject) => {
axios
.get(`/api/v1/next-number?key=estimate`, { params })
.then((response) => {
if (setState) {
this.newEstimate.estimate_number = response.data.nextNumber
}
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
fetchEstimate(id) {
return new Promise((resolve, reject) => {
axios
.get(`/api/v1/estimates/${id}`)
.then((response) => {
Object.assign(this.newEstimate, response.data.data)
if (this.newEstimate.discount_per_item === 'NO') {
this.newEstimate.items.forEach((_i, index) => {
if (_i.discount_type === 'fixed')
this.newEstimate.items[index].discount = _i.discount / 100
})
}
else {
if (this.newEstimate.discount_type === 'fixed')
this.newEstimate.discount = this.newEstimate.discount / 100
}
resolve(response)
})
.catch((err) => {
console.log(err);
handleError(err)
reject(err)
})
})
},
addSalesTaxUs() {
const taxTypeStore = useTaxTypeStore()
let salesTax = { ...taxStub }
let found = this.newEstimate.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
console.log(salesTax, 'salesTax');
taxTypeStore.taxTypes.push(salesTax)
console.log(taxTypeStore.taxTypes);
}
},
sendEstimate(data) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
.post(`/api/v1/estimates/${data.id}/send`, data)
.then((response) => {
if (!data.is_preview) {
notificationStore.showNotification({
type: 'success',
message: global.t('estimates.send_estimate_successfully'),
})
}
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
addEstimate(data) {
return new Promise((resolve, reject) => {
axios
.post('/api/v1/estimates', data)
.then((response) => {
this.estimates = [...this.estimates, response.data.estimate]
const notificationStore = useNotificationStore()
notificationStore.showNotification({
type: 'success',
message: global.t('estimates.created_message'),
})
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
deleteEstimate(id) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
.post(`/api/v1/estimates/delete`, id)
.then((response) => {
let index = this.estimates.findIndex(
(estimate) => estimate.id === id
)
this.estimates.splice(index, 1)
notificationStore.showNotification({
type: 'success',
message: global.t('estimates.deleted_message', 1),
})
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
deleteMultipleEstimates(id) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
.post(`/api/v1/estimates/delete`, { ids: this.selectedEstimates })
.then((response) => {
this.selectedEstimates.forEach((estimate) => {
let index = this.estimates.findIndex(
(_est) => _est.id === estimate.id
)
this.estimates.splice(index, 1)
})
this.selectedEstimates = []
notificationStore.showNotification({
type: 'success',
message: global.tc('estimates.deleted_message', 2),
})
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
updateEstimate(data) {
return new Promise((resolve, reject) => {
axios
.put(`/api/v1/estimates/${data.id}`, data)
.then((response) => {
let pos = this.estimates.findIndex(
(estimate) => estimate.id === response.data.data.id
)
this.estimates[pos] = response.data.data
const notificationStore = useNotificationStore()
notificationStore.showNotification({
type: 'success',
message: global.t('estimates.updated_message'),
})
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
markAsAccepted(data) {
return new Promise((resolve, reject) => {
axios
.post(`/api/v1/estimates/${data.id}/status`, data)
.then((response) => {
let pos = this.estimates.findIndex(
(estimate) => estimate.id === data.id
)
if (this.estimates[pos]) {
this.estimates[pos].status = 'ACCEPTED'
const notificationStore = useNotificationStore()
notificationStore.showNotification({
type: 'success',
message: global.t('estimates.marked_as_accepted_message'),
})
}
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
markAsRejected(data) {
return new Promise((resolve, reject) => {
axios
.post(`/api/v1/estimates/${data.id}/status`, data)
.then((response) => {
const notificationStore = useNotificationStore()
notificationStore.showNotification({
type: 'success',
message: global.t('estimates.marked_as_rejected_message'),
})
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
markAsSent(data) {
return new Promise((resolve, reject) => {
axios
.post(`/api/v1/estimates/${data.id}/status`, data)
.then((response) => {
let pos = this.estimates.findIndex(
(estimate) => estimate.id === data.id
)
if (this.estimates[pos]) {
this.estimates[pos].status = 'SENT'
const notificationStore = useNotificationStore()
notificationStore.showNotification({
type: 'success',
message: global.t('estimates.mark_as_sent_successfully'),
})
}
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
convertToInvoice(id) {
const notificationStore = useNotificationStore()
return new Promise((resolve, reject) => {
axios
.post(`/api/v1/estimates/${id}/convert-to-invoice`)
.then((response) => {
notificationStore.showNotification({
type: 'success',
message: global.t('estimates.conversion_message'),
})
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
searchEstimate(data) {
return new Promise((resolve, reject) => {
axios
.get(`/api/v1/estimates?${data}`)
.then((response) => {
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
selectEstimate(data) {
this.selectedEstimates = data
if (this.selectedEstimates.length === this.estimates.length) {
this.selectAllField = true
} else {
this.selectAllField = false
}
},
selectAllEstimates() {
if (this.selectedEstimates.length === this.estimates.length) {
this.selectedEstimates = []
this.selectAllField = false
} else {
let allEstimateIds = this.estimates.map((estimate) => estimate.id)
this.selectedEstimates = allEstimateIds
this.selectAllField = true
}
},
selectCustomer(id) {
return new Promise((resolve, reject) => {
axios
.get(`/api/v1/customers/${id}`)
.then((response) => {
this.newEstimate.customer = response.data.data
this.newEstimate.customer_id = response.data.data.id
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
fetchEstimateTemplates(params) {
return new Promise((resolve, reject) => {
axios
.get(`/api/v1/estimates/templates`, { params })
.then((response) => {
this.templates = response.data.estimateTemplates
resolve(response)
})
.catch((err) => {
handleError(err)
reject(err)
})
})
},
setTemplate(data) {
this.newEstimate.template_name = data
},
resetSelectedCustomer() {
this.newEstimate.customer = null
this.newEstimate.customer_id = ''
},
selectNote(data) {
this.newEstimate.selectedNote = null
this.newEstimate.selectedNote = data
},
resetSelectedNote() {
this.newEstimate.selectedNote = null
},
addItem() {
this.newEstimate.items.push({
...estimateItemStub,
id: Guid.raw(),
taxes: [{ ...taxStub, id: Guid.raw() }],
})
},
updateItem(data) {
Object.assign(this.newEstimate.items[data.index], { ...data })
},
removeItem(index) {
this.newEstimate.items.splice(index, 1)
},
deselectItem(index) {
this.newEstimate.items[index] = {
...estimateItemStub,
id: Guid.raw(),
taxes: [{ ...taxStub, id: Guid.raw() }],
}
},
async fetchEstimateInitialSettings(isEdit) {
const companyStore = useCompanyStore()
const customerStore = useCustomerStore()
const itemStore = useItemStore()
const taxTypeStore = useTaxTypeStore()
const route = useRoute()
const userStore = useUserStore()
this.isFetchingInitialSettings = true
this.newEstimate.selectedCurrency = companyStore.selectedCompanyCurrency
if (route.query.customer) {
let response = await customerStore.fetchCustomer(route.query.customer)
this.newEstimate.customer = response.data.data
this.newEstimate.customer_id = response.data.data.id
}
let editActions = []
if (!isEdit) {
this.newEstimate.tax_per_item =
companyStore.selectedCompanySettings.tax_per_item
this.newEstimate.sales_tax_type = companyStore.selectedCompanySettings.sales_tax_type
this.newEstimate.sales_tax_address_type = companyStore.selectedCompanySettings.sales_tax_address_type
this.newEstimate.discount_per_item =
companyStore.selectedCompanySettings.discount_per_item
this.newEstimate.estimate_date = moment().format('YYYY-MM-DD')
if (companyStore.selectedCompanySettings.estimate_set_expiry_date_automatically === 'YES') {
this.newEstimate.expiry_date = moment()
.add(companyStore.selectedCompanySettings.estimate_expiry_date_days, 'days')
.format('YYYY-MM-DD')
}
} else {
editActions = [this.fetchEstimate(route.params.id)]
}
Promise.all([
itemStore.fetchItems({
filter: {},
orderByField: '',
orderBy: '',
}),
this.resetSelectedNote(),
this.fetchEstimateTemplates(),
this.getNextNumber(),
taxTypeStore.fetchTaxTypes({ limit: 'all' }),
...editActions,
])
.then(async ([res1, res2, res3, res4, res5, res6, res7]) => {
// Create
if (!isEdit) {
if (res4.data) {
this.newEstimate.estimate_number = res4.data.nextNumber
}
this.setTemplate(this.templates[0].name)
this.newEstimate.template_name =
userStore.currentUserSettings.default_estimate_template ?
userStore.currentUserSettings.default_estimate_template : this.newEstimate.template_name
}
if (isEdit) {
this.addSalesTaxUs()
}
this.isFetchingInitialSettings = false
})
.catch((err) => {
handleError(err)
this.isFetchingInitialSettings = false
})
},
},
})()
}