* 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>
301 lines
7.2 KiB
TypeScript
301 lines
7.2 KiB
TypeScript
import { defineStore } from 'pinia';
|
|
import { ref } from 'vue';
|
|
import {
|
|
RequestData,
|
|
RequestDataStatus,
|
|
RequestWork,
|
|
RequestWorkStatus,
|
|
Step,
|
|
} from './types';
|
|
import { api } from 'src/boot/axios';
|
|
import { PaginationResult } from 'src/types';
|
|
import {
|
|
EmployeePassportPayload,
|
|
EmployeeVisaPayload,
|
|
} from 'stores/employee/types';
|
|
|
|
import { manageAttachment, manageFile, manageMeta } from '../utils';
|
|
|
|
export const useRequestList = defineStore('request-list', () => {
|
|
const data = ref<RequestData[]>([]);
|
|
const page = ref<number>(1);
|
|
const pageMax = ref<number>(1);
|
|
const pageSize = ref<number>(30);
|
|
const stats = ref<Record<RequestDataStatus, number>>({
|
|
[RequestDataStatus.Pending]: 0,
|
|
[RequestDataStatus.InProgress]: 0,
|
|
[RequestDataStatus.Completed]: 0,
|
|
[RequestDataStatus.Canceled]: 0,
|
|
});
|
|
|
|
type TypeFile =
|
|
| 'passport'
|
|
| 'visa'
|
|
| 'citizen'
|
|
| 'house-registration'
|
|
| 'commercial-registration'
|
|
| 'vat-registration'
|
|
| 'power-of-attorney';
|
|
|
|
async function uploadAttachmentRequest(opt: {
|
|
id: string;
|
|
type: 'customer' | 'employee';
|
|
group: string;
|
|
file: File;
|
|
form?: EmployeePassportPayload | EmployeeVisaPayload;
|
|
name?: string;
|
|
}) {
|
|
const base = { customer: 'customer-branch', employee: 'employee' }[
|
|
opt.type
|
|
];
|
|
const attachmentManag = manageAttachment(api, base);
|
|
const metaManager = manageMeta<TypeFile>(api, base);
|
|
|
|
let res;
|
|
const group = [
|
|
'passport',
|
|
'visa',
|
|
'citizen',
|
|
'house-registration',
|
|
'commercial-registration',
|
|
'vat-registration',
|
|
'power-of-attorney',
|
|
];
|
|
|
|
console.log(opt.group);
|
|
|
|
if (group.includes(opt.group)) {
|
|
res = await metaManager.postMeta({
|
|
group: opt.group as TypeFile,
|
|
parentId: opt.id,
|
|
meta: opt.form,
|
|
file: opt.file,
|
|
});
|
|
} else {
|
|
res = await attachmentManag.putAttachment({
|
|
parentId: opt.id,
|
|
name: opt.name || '',
|
|
file: opt.file,
|
|
});
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
async function viewAttachmentRequest(opt: {
|
|
id: string;
|
|
name: string;
|
|
type: 'customer' | 'employee';
|
|
group: string;
|
|
download?: boolean;
|
|
}) {
|
|
const base = { customer: 'customer-branch', employee: 'employee' }[
|
|
opt.type
|
|
];
|
|
const attachmentManag = manageAttachment(api, base);
|
|
const fileManager = manageFile<TypeFile>(api, base);
|
|
|
|
let res;
|
|
const group = [
|
|
'passport',
|
|
'visa',
|
|
'citizen',
|
|
'house-registration',
|
|
'commercial-registration',
|
|
'vat-registration',
|
|
'power-of-attorney',
|
|
];
|
|
|
|
if (group.includes(opt.group)) {
|
|
res = await fileManager.getFile({
|
|
parentId: opt.id,
|
|
group: opt.group as TypeFile,
|
|
fileId: opt.name,
|
|
download: opt.download,
|
|
});
|
|
}
|
|
|
|
if (!group.includes(opt.group)) {
|
|
res = await attachmentManag.getAttachment({
|
|
parentId: opt.id,
|
|
name: opt.name,
|
|
download: opt.download,
|
|
});
|
|
}
|
|
|
|
if (res) return res;
|
|
}
|
|
|
|
async function getAttachmentRequest(
|
|
id: string,
|
|
type: 'customer' | 'employee',
|
|
) {
|
|
const base = { customer: 'customer-branch', employee: 'employee' }[type];
|
|
|
|
const attachmentManag = manageAttachment(api, base);
|
|
const fileManager = manageFile<TypeFile>(api, base);
|
|
|
|
const resFiles: Partial<Record<string, any>> = {};
|
|
|
|
if (type === 'employee') {
|
|
const resPassport = await fileManager.listFile({
|
|
group: 'passport',
|
|
parentId: id,
|
|
});
|
|
|
|
const resVisa = await fileManager.listFile({
|
|
group: 'visa',
|
|
parentId: id,
|
|
});
|
|
|
|
resFiles['passport'] = { ...resPassport };
|
|
resFiles['visa'] = { ...resVisa };
|
|
} else if (type === 'customer') {
|
|
const groups = [
|
|
'citizen',
|
|
'house-registration',
|
|
'commercial-registration',
|
|
'vat-registration',
|
|
'power-of-attorney',
|
|
] as const;
|
|
|
|
for (const group of groups) {
|
|
const res = await fileManager.listFile({
|
|
group,
|
|
parentId: id,
|
|
});
|
|
resFiles[group] = { ...res };
|
|
}
|
|
}
|
|
|
|
const resAttachment = await attachmentManag.listAttachment({
|
|
parentId: id,
|
|
});
|
|
|
|
if (resAttachment)
|
|
for (const item of resAttachment) {
|
|
const [key] = item.split('-').map((s) => s.trim());
|
|
if (key) {
|
|
if (!resFiles[key]) {
|
|
resFiles[key] = [];
|
|
}
|
|
|
|
if (!resFiles[key].includes(item)) {
|
|
resFiles[key].push(item);
|
|
}
|
|
}
|
|
}
|
|
|
|
return resFiles;
|
|
}
|
|
|
|
async function getRequestDataStats() {
|
|
const res = await api.get<typeof stats.value>('/request-data/stats');
|
|
if (res.status < 400) return res.data;
|
|
return null;
|
|
}
|
|
|
|
async function getRequestData(id: string) {
|
|
const res = await api.get<RequestData>(`/request-data/${id}`);
|
|
if (res.status < 400) return res.data;
|
|
return null;
|
|
}
|
|
|
|
async function getRequestDataList(params?: {
|
|
query?: string;
|
|
page?: number;
|
|
pageSize?: number;
|
|
requestDataStatus?: RequestDataStatus;
|
|
responsibleOnly?: boolean;
|
|
quotationId?: string;
|
|
}) {
|
|
const res = await api.get<PaginationResult<RequestData>>('/request-data', {
|
|
params,
|
|
});
|
|
if (res.status < 400) return res.data;
|
|
return null;
|
|
}
|
|
|
|
async function getRequestWorkList(params?: {
|
|
requestDataId?: string;
|
|
query?: string;
|
|
page?: number;
|
|
pageSize?: number;
|
|
workStatus?: RequestWorkStatus;
|
|
readyToTask?: boolean;
|
|
quotationId?: string;
|
|
cancelOnly?: boolean;
|
|
}) {
|
|
const res = await api.get<PaginationResult<RequestWork>>('/request-work', {
|
|
params,
|
|
});
|
|
if (res.status < 400) return res.data;
|
|
return null;
|
|
}
|
|
|
|
async function editRequestWork(body: Partial<RequestWork>) {
|
|
const res = await api.put(`/request-work/${body.id}`, {
|
|
...body,
|
|
id: undefined,
|
|
});
|
|
|
|
if (res.status < 400) return res.data;
|
|
return null;
|
|
}
|
|
|
|
async function editStatusRequestWork(body: Step, successAll?: boolean) {
|
|
const res = await api.put<Step>(
|
|
`/request-work/${body.requestWorkId}/step-status/${body.step}`,
|
|
{
|
|
customerDuty: body.customerDuty,
|
|
customerDutyCost: body.customerDutyCost,
|
|
companyDuty: body.companyDuty,
|
|
companyDutyCost: body.companyDutyCost,
|
|
individualDuty: body.individualDuty,
|
|
individualDutyCost: body.individualDutyCost,
|
|
responsibleUserLocal: body.responsibleUserLocal,
|
|
responsibleUserId: body.responsibleUserId,
|
|
attributes: body.attributes,
|
|
workStatus: body.workStatus,
|
|
requestWorkId: undefined,
|
|
step: undefined,
|
|
},
|
|
{ params: { successAll } },
|
|
);
|
|
|
|
if (res.status < 400) return res.data;
|
|
return null;
|
|
}
|
|
|
|
async function cancelRequest(id: string) {
|
|
const res = await api.post(`/request-data/${id}/cancel`);
|
|
|
|
if (res.status < 400) return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
return {
|
|
data,
|
|
page,
|
|
pageMax,
|
|
pageSize,
|
|
stats,
|
|
|
|
viewAttachmentRequest,
|
|
getAttachmentRequest,
|
|
uploadAttachmentRequest,
|
|
|
|
getRequestDataStats,
|
|
getRequestData,
|
|
getRequestDataList,
|
|
getRequestWorkList,
|
|
|
|
editRequestWork,
|
|
editStatusRequestWork,
|
|
|
|
cancelRequest,
|
|
};
|
|
});
|
|
|
|
export * from './types.ts';
|