From dc225ac31b323da8e205aa51ac242abd6f8c7ffd Mon Sep 17 00:00:00 2001 From: puriphatt Date: Mon, 24 Feb 2025 16:20:56 +0700 Subject: [PATCH] feat: enhance credit note functionality and improve task order handling --- .../09_task-order/SelectReadyRequestWork.vue | 21 ++- src/pages/11_credit-note/FormPage.vue | 126 ++++++++++++++---- src/pages/11_credit-note/MainPage.vue | 14 +- 3 files changed, 125 insertions(+), 36 deletions(-) diff --git a/src/pages/09_task-order/SelectReadyRequestWork.vue b/src/pages/09_task-order/SelectReadyRequestWork.vue index b294763e..34d9dd22 100644 --- a/src/pages/09_task-order/SelectReadyRequestWork.vue +++ b/src/pages/09_task-order/SelectReadyRequestWork.vue @@ -23,7 +23,9 @@ const emit = defineEmits<{ const props = defineProps<{ taskListGroup?: { - product: RequestWork['productService']['product']; + product: + | RequestWork['productService']['product'] + | RequestWork['productService']; list: (RequestWork & { _template?: { id: string; @@ -135,6 +137,7 @@ async function getList() { } function getStep(requestWork: RequestWork) { + if (!requestWork.stepStatus) return 0; const target = requestWork.stepStatus.find( (v) => v.workStatus === RequestWorkStatus.Ready || @@ -166,7 +169,7 @@ function submit() { requestWorkStep?: Task; }[] = []; selectedEmployee.value.forEach((v, i) => { - if (v.stepStatus.length === 0) { + if (!v.stepStatus || v.stepStatus.length === 0) { selected.push({ step: 0, requestWorkId: v.id || '', @@ -224,7 +227,7 @@ function close() { function onDialogOpen() { // assign selected to group - !props.creditNote && assignTempGroup(); + assignTempGroup(); // match group to check selectedEmployee.value = []; @@ -232,7 +235,7 @@ function onDialogOpen() { const matchingItems = tempGroupEdit.value .flatMap((g) => g.list) .filter((l) => { - if (l.stepStatus.length === 0) { + if (!l.stepStatus || l.stepStatus.length === 0) { return taskList.value.some( (t) => t.requestWorkStep?.requestWork.id === l.id, ); @@ -248,8 +251,12 @@ function onDialogOpen() { function assignTempGroup() { if (!props.taskListGroup) return; props.taskListGroup.forEach((newGroup) => { + const productId = props.creditNote + ? (newGroup.product as RequestWork['productService']).productId + : (newGroup.product as RequestWork['productService']['product']).id; + const existingGroup = tempGroupEdit.value.find( - (g) => g.product.id === newGroup.product.id, + (g) => g.product.id === productId, ); if (existingGroup) { @@ -260,7 +267,9 @@ function assignTempGroup() { }); } else { tempGroupEdit.value.push({ - ...newGroup, + product: props.creditNote + ? (newGroup.product as RequestWork['productService']).product + : (newGroup.product as RequestWork['productService']['product']), list: [...newGroup.list], // Ensure a new reference }); } diff --git a/src/pages/11_credit-note/FormPage.vue b/src/pages/11_credit-note/FormPage.vue index 14f40fcc..b8847e14 100644 --- a/src/pages/11_credit-note/FormPage.vue +++ b/src/pages/11_credit-note/FormPage.vue @@ -24,7 +24,13 @@ import SelectReadyRequestWork from '../09_task-order/SelectReadyRequestWork.vue' import RefundInformation from './RefundInformation.vue'; import QuotationFormReceipt from '../05_quotation/QuotationFormReceipt.vue'; import DialogViewFile from 'src/components/dialog/DialogViewFile.vue'; -import { MainButton, SaveButton } from 'src/components/button'; +import { + MainButton, + SaveButton, + CancelButton, + EditButton, + UndoButton, +} from 'src/components/button'; import { RequestWork } from 'src/stores/request-list/types'; import { storeToRefs } from 'pinia'; import useOptionStore from 'src/stores/options'; @@ -76,15 +82,16 @@ const statusTabForm = ref< }[] >([]); -const readonly = computed( - () => - creditNoteData.value?.creditNoteStatus === CreditNoteStatus.Pending || - creditNoteData.value?.creditNoteStatus === CreditNoteStatus.Success, -); +// const readonly = computed( +// () => +// creditNoteData.value?.creditNoteStatus === CreditNoteStatus.Pending || +// creditNoteData.value?.creditNoteStatus === CreditNoteStatus.Success, +// ); const pageState = reactive({ productDialog: false, fileDialog: false, + mode: 'view' as 'view' | 'edit' | 'info', }); const defaultRemark = '#[quotation-labor]

#[quotation-payment]'; @@ -161,9 +168,11 @@ async function initStatus() { { title: 'Pending', status: creditNoteData.value?.id - ? creditNoteData.value.creditNoteStatus === CreditNoteStatus.Success - ? 'done' - : 'doing' + ? creditNoteData.value.creditNoteStatus === CreditNoteStatus.Waiting + ? 'waiting' + : creditNoteData.value.creditNoteStatus === CreditNoteStatus.Success + ? 'done' + : 'doing' : 'waiting', active: () => view.value === CreditNoteStatus.Pending, handler: async () => { @@ -253,8 +262,9 @@ function assignFormData() { requestWorkStep: { requestWork: { ...v, + stepStatus: v.stepStatus || [], request: { ...v.request, quotation: current.quotation }, - }, + } as RequestWork, }, })); } @@ -285,12 +295,24 @@ async function getQuotation() { async function submit() { const payload = formData.value; + payload.requestWorkId = formTaskList.value.map((v) => v.requestWorkId); payload.quotationId = - typeof route.query['quotationId'] === 'string' - ? route.query['quotationId'] - : ''; - const res = await creditNote.createCreditNote(payload); + (pageState.mode === 'edit' + ? creditNoteData.value?.quotationId + : typeof route.query['quotationId'] === 'string' + ? route.query['quotationId'] + : '') || ''; + + const res = + pageState.mode === 'edit' + ? await creditNote.updateCreditNote( + creditNoteData.value?.id || '', + payload, + ) + : creditNoteData.value + ? await creditNote.acceptCreditNote(creditNoteData.value.id) + : await creditNote.createCreditNote(payload); if (res) { await router.push(`/credit-note/${res.id}`); @@ -302,6 +324,7 @@ async function submit() { } initStatus(); + pageState.mode = 'info'; } } @@ -526,13 +549,31 @@ function storeDataLocal() { window.open(url, '_blank'); } +function closeTab() { + dialogWarningClose(t, { + message: t('dialog.message.close'), + action: () => { + window.close(); + }, + cancel: () => {}, + }); +} + +function undo() { + assignFormData(); + pageState.mode = 'info'; +} + onMounted(async () => { initTheme(); initLang(); await useConfigStore().getConfig(); await getCreditNote(); await getQuotation(); - creditNoteData.value && (await getFileList(creditNoteData.value.id, true)); + if (creditNoteData.value) { + pageState.mode = 'info'; + await getFileList(creditNoteData.value.id, true); + } initStatus(); }); @@ -587,7 +628,7 @@ onMounted(async () => { :key="i.title" :label=" $t( - `creditNote${i.title === 'title' ? '' : '.stats'}.${i.title}`, + `creditNote${i.title === 'title' ? '' : '.status'}.${i.title}`, ) " :status-active="i.active?.()" @@ -616,7 +657,7 @@ onMounted(async () => { > @@ -625,7 +666,7 @@ onMounted(async () => { { { v-model:remark="formData.remark" :default-remark="defaultRemark" :items="[]" - :readonly + :readonly="pageState.mode === 'info'" >