jws-frontend/src/stores/quotations/index.ts

241 lines
5.5 KiB
TypeScript
Raw Normal View History

2024-09-30 12:04:58 +07:00
import { ref } from 'vue';
import { defineStore } from 'pinia';
import { api } from 'src/boot/axios';
2024-10-07 16:58:45 +07:00
import {
Quotation,
QuotationFull,
QuotationPayload,
2024-10-16 17:21:30 +07:00
QuotationPaymentData,
2024-10-07 16:58:45 +07:00
QuotationStats,
2024-10-21 15:17:27 +07:00
PaymentPayload,
2024-10-28 08:57:41 +07:00
QuotationStatus,
QuotationAddWorkerPayload,
2024-10-07 16:58:45 +07:00
} from './types';
2024-09-30 12:04:58 +07:00
import { PaginationResult } from 'src/types';
2024-10-21 15:17:27 +07:00
2024-10-24 13:57:22 +07:00
import { manageAttachment } from '../utils';
2024-09-30 12:04:58 +07:00
2024-09-30 14:16:16 +07:00
export const useQuotationStore = defineStore('quotation-store', () => {
2024-09-30 12:04:58 +07:00
const data = ref<Quotation[]>([]);
const page = ref<number>(1);
const pageMax = ref<number>(1);
2024-09-30 15:03:36 +07:00
const pageSize = ref<number>(30);
2024-10-07 16:58:45 +07:00
const stats = ref<QuotationStats>({
2024-11-07 14:22:13 +07:00
issued: 0,
accepted: 0,
expired: 0,
paymentInProcess: 0,
paymentSuccess: 0,
processComplete: 0,
2024-12-26 12:00:25 +07:00
canceled: 0,
2024-10-07 16:58:45 +07:00
});
async function getQuotationStats(params?: {
startDate: string | Date;
endDate: string | Date;
}) {
const res = await api.get<QuotationStats>('/quotation/stats', { params });
2024-10-07 16:58:45 +07:00
if (res.status < 400) {
return res.data;
}
return null;
}
2024-09-30 12:04:58 +07:00
async function getQuotation(id: string) {
const res = await api.get<QuotationFull>(`/quotation/${id}`);
if (res.status < 400) {
return res.data;
}
return null;
}
async function getQuotationList(params?: {
2024-09-30 15:03:36 +07:00
page?: number;
pageSize?: number;
2024-10-29 10:19:47 +07:00
payCondition?:
| 'Full'
| 'Split'
| 'SplitCustom'
| 'BillFull'
| 'BillSplit'
| 'BillSplitCustom';
2024-11-07 12:51:15 +07:00
status?:
| 'Issued'
| 'Accepted'
| 'Expired'
2024-11-07 12:51:15 +07:00
| 'PaymentPending'
| 'PaymentInProcess'
| 'PaymentSuccess'
| 'ProcessComplete'
| 'Canceled';
urgentFirst?: boolean;
2024-10-21 13:33:36 +07:00
query?: string;
feat: credit note (#171) * feat: add main page credit note * feat: enable credit note route and update menu item states * refactor: add i18n * refactor: edit i18n status * feat: add action column * feat: add empty form page * feat: add get data * feat: add type credit note status * refactor: add type name en * refactor: add type credit note status in type credit note * feat: add hsla colors * refactor: add slot grid * refactor: handle hide kebab edit show only tab tssued * feat: show grid card * feat: i18n * feat: add credit note form and dialog * refactor: add props hide kebab deelete * refactor: hide kebab * style: update color segments to indigo theme * feat: i18n * fix: update labels for credit note fields * refactor: add type * feat: new select quotation * refactor: use new select quotation * feat: navigate to * refactor: function trigger and navigate to * feat: i18n bank * feat: add payment expansion component and integrate into credit note form * refactor: bind i18n pay condition * refactor: navigate to get quotation id * feat: i18n * fix: update label for createdBy field in credit note form * feat: add credit note information expansion component * feat: add Credit Note expansion component and update form layout * refactor: bind quotation id and send * refactor: deelete duplicate type * refactor: show state button * refactor: handle show status * feat: add function update payback status * feat: add return and canceled reasons to credit note translations * feat: enhance SelectReadyRequestWork component with credit note handling and fetch parameters * feat: type * feat: add status handling and optional display for employee table * refactor: rename selectedQuotationId to quotationId in FormCredit component * feat: set default opened state for CreditNoteExpansion and add reason options * feat: update PaymentExpansion to handle payback type selection and clear fields for cash payments * feat: enhance ProductExpansion to support credit note handling and adjust price calculations * feat: implement product handling and price calculation in CreditNote form * feat: add manage attachment function to store * refactor: bind delete credit note * feat: add credit note status and reference fields to types * refactor: update task step handling and simplify request work structure in credit note form * feat: add navigation to quotation from credit note form * feat: enhance upload section layout based on file data * feat: add readonly functionality to credit note form and related components * refactor: remove console log * feat: update i18n * style: add rounded corners to complete view container in quotation form * feat: add RefundInformation component and update credit note form status handling * feat: i18n * feat: update payback status endpoint and add paybackStatus to CreditNote type * feat: enhance QuotationFormReceipt component with optional props and slot support * feat: integrate payback status handling in RefundInformation and FormPage components * feat: add external file group * feat: update API endpoint paths for credit note operations * feat: improve layout and styling in UploadFile components * feat: implement file upload and management in Credit Note * refactor: update upload to check if it is redirect or not * feat: upload file slips * feat: add payback date dispaly * refactor: change module no * fix: icon link to main page instead * feat: add file dialog with image download functionality * fix: view slip * feat: add download button to image viewer * feat: handle after submit * feat: conditionally render bank transfer information * feat: handle upload file on create * feat: handle change payback status * feat: payback type in credit note form * fix: correct reference to quotation data in goToQuotation function --------- Co-authored-by: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Co-authored-by: puriphatt <puriphat@frappet.com> Co-authored-by: Thanaphon Frappet <thanaphon@frappet.com>
2025-01-14 09:08:31 +07:00
hasCancel?: boolean;
includeRegisteredBranch?: boolean;
2025-01-30 16:40:35 +07:00
forDebitNote?: boolean;
cancelIncludeDebitNote?: boolean;
2024-09-30 15:03:36 +07:00
}) {
const res = await api.get<PaginationResult<Quotation>>('/quotation', {
params,
});
2024-09-30 12:04:58 +07:00
if (res.status < 400) {
return res.data;
}
return null;
}
2024-10-07 17:04:12 +07:00
async function createQuotation(data: QuotationPayload) {
const { _count, quotationStatus, ...payload } = data;
2024-10-07 17:04:12 +07:00
2024-10-03 14:57:14 +07:00
const res = await api.post('/quotation', {
...payload,
paySplit: data.paySplit.map((v) => ({
2024-10-31 13:40:12 +07:00
name: v.name,
amount: v.amount,
})),
2024-10-07 17:04:12 +07:00
productServiceList: data.productServiceList.map((v) => ({
2024-10-03 14:57:14 +07:00
vat: v.vat,
amount: v.amount,
pricePerUnit: v.pricePerUnit,
discount: v.discount,
productId: v.product.id,
workId: v.work?.id,
serviceId: v.service?.id,
2024-10-29 18:00:59 +07:00
installmentNo: v.installmentNo,
2024-10-08 10:05:46 +07:00
workerIndex: v.workerIndex,
2024-10-03 14:57:14 +07:00
})),
});
2024-09-30 12:04:58 +07:00
if (res.status < 400) {
return res.data;
}
return null;
}
2024-10-28 08:57:41 +07:00
async function changeStatus(quotationId: string, status: QuotationStatus) {
const res = await api.put(`/quotation/${quotationId}`, {
quotationStatus: status,
});
if (res.status < 400) {
return res.data;
}
return null;
}
2024-10-10 13:34:27 +07:00
async function editQuotation(data: QuotationPayload & { id: string }) {
2025-01-30 14:05:20 +07:00
const { _count, agentPrice, ...payload } = data;
2024-10-10 13:34:27 +07:00
const res = await api.put(`/quotation/${data.id}`, {
2024-09-30 12:04:58 +07:00
...payload,
2024-11-01 14:31:10 +07:00
quotationStatus:
payload.quotationStatus !== 'Accepted' ? undefined : 'Accepted',
paySplit: data.paySplit.map((v) => ({
2024-10-31 13:40:12 +07:00
name: v.name,
amount: v.amount,
})),
2024-10-03 14:57:14 +07:00
productServiceList: payload.productServiceList.map((v) => ({
vat: v.vat,
amount: v.amount,
pricePerUnit: v.pricePerUnit,
discount: v.discount,
productId: v.product.id,
workId: v.work?.id,
serviceId: v.service?.id,
2024-10-10 17:53:12 +07:00
workerIndex: v.workerIndex,
2024-10-31 13:40:12 +07:00
installmentNo: v.installmentNo,
2024-10-03 14:57:14 +07:00
})),
2024-09-30 12:04:58 +07:00
id: undefined,
});
if (res.status < 400) {
return res.data;
}
return null;
}
2024-10-24 13:57:22 +07:00
async function deleteQuotation(id: string) {
2024-09-30 12:04:58 +07:00
const res = await api.delete(`/quotation/${id}`);
if (res.status < 400) {
return res.data;
}
return null;
}
/** This is meant to be use after quotation was accepted */
async function addQuotationWorker(
id: string,
payload: QuotationAddWorkerPayload,
) {
const res = await api.post(`/quotation/${id}/add-worker`, payload);
if (res.status < 400) {
return res.data;
}
return null;
}
const fileManager = manageAttachment(api, 'quotation');
2024-09-30 12:04:58 +07:00
return {
data,
page,
2024-09-30 15:03:36 +07:00
pageSize,
2024-09-30 12:04:58 +07:00
pageMax,
2024-10-07 16:58:45 +07:00
stats,
getQuotationStats,
2024-09-30 12:04:58 +07:00
getQuotation,
getQuotationList,
createQuotation,
editQuotation,
2024-10-24 13:57:22 +07:00
deleteQuotation,
2024-10-28 08:57:41 +07:00
changeStatus,
addQuotationWorker,
...fileManager,
2024-09-30 12:04:58 +07:00
};
});
2024-10-16 17:21:30 +07:00
2024-10-30 10:46:45 +07:00
/**
* @deprecated Please use payment store instead.
*/
2024-10-16 17:21:30 +07:00
export const useQuotationPayment = defineStore('quotation-payment', () => {
feat: debit note (#172) * feat: new file * feat: function api debit * feat: add route debit * feat: new form page * refactor: show menu debit * refactor: add type debit note status * feat: add i18n * feat: add constants * feat: add stores * feat: layout * feat: add function * refactor: change name value * feat: form select quotation * refactor: change name url * refactor: use form debit * refactor: change src import * refactor: move file form debit * refactor: add i18n * feat: add type debit note * refactor: add columns * refactor: bind value columns * refactor: change name Table * refactor: edit type * refactor: bind type debit note * refactor: bind value debit * refactor: chame name function * fix: calculate page * refactor: delete table * refactor: change name get list * refactor: change i18n * refactor: change name value * refactor: bind navigate and trigger delete * refactor: format number deciml * refactor: add i18n * feat: new page * refactor: add color debit * feat: Debit tab #178 * feat: TableRequest * refactor: edit type pay condition * refactor: add i18n btn submit * refactor: use type enum * feat: edit layout product expansion * refactor: bind function * refactor: show code * feat: add input search and select status * feat: paymentform * refactor: edit type * refactor: add manage file and edit end point * feat: add form.ts * refactor: send mode * refactor: edit v-model of due date * feat: submit create debit * fix: status * refactor: handle data not allow * fix: call updateDebitNote in edit mode and simplify payload handling * refactor: hide edit * refactor: handle pay condition only full * refactor: delete pay split * refactor: add query * refactor: handle is debit note * refactor: handle is quotation * refactor: add props hide * refactor: tap payment and receipt * refactor: add i18n * feat: view document * refactor: handle btn view doc * refactor: use my remark --------- Co-authored-by: Thanaphon Frappet <thanaphon@frappet.com> Co-authored-by: nwpptrs <jay02499@gmail.com> Co-authored-by: aif912752 <siripak@chamomind.com>
2025-01-27 09:04:08 +07:00
async function getQuotationPayment(params: {
quotationId?: string;
debitNoteId?: string;
debitNoteOnly?: boolean;
quotationOnly?: boolean;
}) {
2024-10-28 16:44:14 +07:00
const res = await api.get<PaginationResult<QuotationPaymentData>>(
'/payment',
feat: debit note (#172) * feat: new file * feat: function api debit * feat: add route debit * feat: new form page * refactor: show menu debit * refactor: add type debit note status * feat: add i18n * feat: add constants * feat: add stores * feat: layout * feat: add function * refactor: change name value * feat: form select quotation * refactor: change name url * refactor: use form debit * refactor: change src import * refactor: move file form debit * refactor: add i18n * feat: add type debit note * refactor: add columns * refactor: bind value columns * refactor: change name Table * refactor: edit type * refactor: bind type debit note * refactor: bind value debit * refactor: chame name function * fix: calculate page * refactor: delete table * refactor: change name get list * refactor: change i18n * refactor: change name value * refactor: bind navigate and trigger delete * refactor: format number deciml * refactor: add i18n * feat: new page * refactor: add color debit * feat: Debit tab #178 * feat: TableRequest * refactor: edit type pay condition * refactor: add i18n btn submit * refactor: use type enum * feat: edit layout product expansion * refactor: bind function * refactor: show code * feat: add input search and select status * feat: paymentform * refactor: edit type * refactor: add manage file and edit end point * feat: add form.ts * refactor: send mode * refactor: edit v-model of due date * feat: submit create debit * fix: status * refactor: handle data not allow * fix: call updateDebitNote in edit mode and simplify payload handling * refactor: hide edit * refactor: handle pay condition only full * refactor: delete pay split * refactor: add query * refactor: handle is debit note * refactor: handle is quotation * refactor: add props hide * refactor: tap payment and receipt * refactor: add i18n * feat: view document * refactor: handle btn view doc * refactor: use my remark --------- Co-authored-by: Thanaphon Frappet <thanaphon@frappet.com> Co-authored-by: nwpptrs <jay02499@gmail.com> Co-authored-by: aif912752 <siripak@chamomind.com>
2025-01-27 09:04:08 +07:00
{ params },
2024-10-28 16:44:14 +07:00
);
2024-10-16 17:21:30 +07:00
if (res.status < 400) {
return res.data;
}
return null;
}
2024-10-21 15:17:27 +07:00
async function updateQuotationPayment(
paymentId: string,
payload: PaymentPayload,
) {
const res = await api.put<PaymentPayload & { id: string }>(
2024-10-28 16:44:14 +07:00
`/payment/${paymentId}`,
2024-10-21 15:17:27 +07:00
payload,
);
if (res.status < 400) {
return res.data;
}
return null;
}
const fileManager = manageAttachment(api, 'payment');
2024-10-21 15:17:27 +07:00
2024-10-16 17:21:30 +07:00
return {
getQuotationPayment,
2024-10-21 15:17:27 +07:00
updateQuotationPayment,
2024-10-28 16:44:14 +07:00
...fileManager,
2024-10-16 17:21:30 +07:00
};
});
export * from './types.ts';