From 764d9bab3f5f19b5a69bea1663249f0c968b2115 Mon Sep 17 00:00:00 2001 From: Thanaphon Frappet Date: Fri, 22 Aug 2025 14:03:48 +0700 Subject: [PATCH 01/35] fix: get contact number and name --- src/components/05_quotation/FormAbout.vue | 7 +++++++ src/pages/05_quotation/QuotationForm.vue | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/components/05_quotation/FormAbout.vue b/src/components/05_quotation/FormAbout.vue index 1fec0148..54f19f90 100644 --- a/src/components/05_quotation/FormAbout.vue +++ b/src/components/05_quotation/FormAbout.vue @@ -1,4 +1,6 @@ diff --git a/src/pages/03_customer-management/form.ts b/src/pages/03_customer-management/form.ts index 3abefdaa..fe875a3c 100644 --- a/src/pages/03_customer-management/form.ts +++ b/src/pages/03_customer-management/form.ts @@ -30,6 +30,8 @@ export const useCustomerForm = defineStore('form-customer', () => { const registerAbleBranchOption = ref<{ id: string; name: string }[]>(); + const currentBranchRootId = ref(''); + const tabFieldRequired = ref<{ [key: string]: (keyof CustomerBranchCreate)[]; }>({ @@ -160,6 +162,7 @@ export const useCustomerForm = defineStore('form-customer', () => { state.value.editCustomerCode = data.code; state.value.customerImageUrl = `${baseUrl}/customer/${id}/image/${data.selectedImage}`; state.value.defaultCustomerImageUrl = `${baseUrl}/customer/${id}/image/${data.selectedImage}`; + currentBranchRootId.value = data.branch[0].id || ''; resetFormData.registeredBranchId = data.registeredBranchId; resetFormData.status = data.status; @@ -500,6 +503,8 @@ export const useCustomerForm = defineStore('form-customer', () => { state, resetFormData, currentFormData, + currentBranchRootId, + isFormDataDifferent, resetForm, assignFormData, @@ -1663,6 +1668,7 @@ export const useEmployeeForm = defineStore('form-employee', () => { state, currentFromDataEmployee, resetEmployeeData, + addPassport, addVisa, addCheckup, diff --git a/src/pages/05_quotation/MainPage.vue b/src/pages/05_quotation/MainPage.vue index b9b57354..3551a047 100644 --- a/src/pages/05_quotation/MainPage.vue +++ b/src/pages/05_quotation/MainPage.vue @@ -60,7 +60,6 @@ const flowStore = useFlowStore(); const userBranch = useMyBranch(); const navigatorStore = useNavigator(); const customerStore = useCustomerStore(); - const { fetchListOfOptionBranch, customerFormUndo, @@ -76,6 +75,7 @@ const { const { state: customerFormState, currentFormData: customerFormData, + currentBranchRootId, registerAbleBranchOption, tabFieldRequired, } = storeToRefs(customerFormStore); @@ -89,6 +89,8 @@ const fieldSelectedOption = computed(() => { value: v.name, })); }); + +const keyAddDialog = ref(0); const special = ref(false); const branchId = ref(''); const agentPrice = ref(false); @@ -865,6 +867,7 @@ async function filterBySellerId() { @@ -999,6 +1002,7 @@ async function filterBySellerId() { () => { customerFormState.dialogModal = false; onCreateImageList = { selectedImage: '', list: [] }; + keyAddDialog++; } " > @@ -1190,7 +1194,7 @@ async function filterBySellerId() { customerFormData.customerBranch[0].legalPersonNo " v-model:business-type=" - customerFormData.customerBranch[0].businessType + customerFormData.customerBranch[0].businessTypeId " v-model:job-position=" customerFormData.customerBranch[0].jobPosition @@ -1271,7 +1275,6 @@ async function filterBySellerId() { res = await customerStore.createBranch({ ...customerFormData.customerBranch[idx], customerId: customerFormState.editCustomerId || '', - id: undefined, }); } if (res) { From 09b51d601ea27a942fb702951d9bb375cd8ffc6d Mon Sep 17 00:00:00 2001 From: net Date: Thu, 11 Sep 2025 13:37:03 +0700 Subject: [PATCH 05/35] refactor: can create new type --- .../shared/select/SelectBusinessType.vue | 33 +++++++++++++ src/pages/03_customer-management/MainPage.vue | 2 +- .../employer/EmployerFormBusiness.vue | 49 ++++++++++++++++++- 3 files changed, 82 insertions(+), 2 deletions(-) diff --git a/src/components/shared/select/SelectBusinessType.vue b/src/components/shared/select/SelectBusinessType.vue index 211ed07e..12b6172e 100644 --- a/src/components/shared/select/SelectBusinessType.vue +++ b/src/components/shared/select/SelectBusinessType.vue @@ -158,6 +158,39 @@ function setDefaultValue() { + + From ef4c84341c947260622e4b03d67fb384741c6f43 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 11 Sep 2025 13:43:35 +0700 Subject: [PATCH 06/35] fix: price calc --- src/components/05_quotation/ProductItem.vue | 40 ++++++---- src/pages/05_quotation/QuotationForm.vue | 31 +++----- src/pages/05_quotation/QuotationFormInfo.vue | 4 +- src/pages/05_quotation/preview/ViewForm.vue | 77 ++++++-------------- 4 files changed, 63 insertions(+), 89 deletions(-) diff --git a/src/components/05_quotation/ProductItem.vue b/src/components/05_quotation/ProductItem.vue index b1996d03..cfa2ad8e 100644 --- a/src/components/05_quotation/ProductItem.vue +++ b/src/components/05_quotation/ProductItem.vue @@ -58,16 +58,15 @@ const currentBtnOpen = ref<{ title: string; opened: boolean[] }[]>([ function calcPrice(c: (typeof rows.value)[number]) { const originalPrice = c.pricePerUnit; - const finalPriceWithVat = precisionRound( - originalPrice + originalPrice * (config.value?.vat || 0.07), + const finalPricePerUnit = precisionRound( + originalPrice + + (c.product[props.agentPrice ? 'agentPriceCalcVat' : 'calcVat'] + ? originalPrice * (config.value?.vat || 0.07) + : 0), ); - const finalPriceNoVat = finalPriceWithVat / (1 + (config.value?.vat || 0.07)); + const price = finalPricePerUnit * c.amount - c.discount; - const price = finalPriceNoVat * c.amount - c.discount; - const vat = c.product[props.agentPrice ? 'agentPriceCalcVat' : 'calcVat'] - ? (finalPriceNoVat * c.amount - c.discount) * (config.value?.vat || 0.07) - : 0; - return precisionRound(price + vat); + return precisionRound(price); } const discount4Show = ref([]); @@ -435,8 +434,20 @@ watch( {{ formatNumberDecimal( - props.row.pricePerUnit * props.row.amount - - props.row.discount, + props.row.product[ + agentPrice ? 'agentPriceCalcVat' : 'calcVat' + ] + ? precisionRound( + (props.row.pricePerUnit * + (1 + (config?.vat || 0.07)) * + props.row.amount - + props.row.discount) / + (1 + (config?.vat || 0.07)), + ) + : precisionRound( + props.row.pricePerUnit * props.row.amount - + props.row.discount, + ), 2, ) }} @@ -448,9 +459,12 @@ watch( agentPrice ? 'agentPriceCalcVat' : 'calcVat' ] ? precisionRound( - (props.row.pricePerUnit * props.row.amount - - props.row.discount) * - (config?.vat || 0.07), + ((props.row.pricePerUnit * + (1 + (config?.vat || 0.07)) * + props.row.amount - + props.row.discount) / + (1 + (config?.vat || 0.07))) * + 0.07, ) : 0, 2, diff --git a/src/pages/05_quotation/QuotationForm.vue b/src/pages/05_quotation/QuotationForm.vue index dd5b5aeb..e46f911f 100644 --- a/src/pages/05_quotation/QuotationForm.vue +++ b/src/pages/05_quotation/QuotationForm.vue @@ -248,32 +248,23 @@ function getPrice( return a; } - const originalPrice = c.pricePerUnit; - const finalPriceWithVat = precisionRound( - originalPrice * (1 + (config.value?.vat || 0.07)), - ); - const finalPriceNoVat = - finalPriceWithVat / (1 + (config.value?.vat || 0.07)); - - const price = finalPriceNoVat * c.amount; - const vat = - (finalPriceNoVat * c.amount - c.discount) * (config.value?.vat || 0.07); - const calcVat = c.product[agentPrice.value ? 'agentPriceCalcVat' : 'calcVat']; + const vatFactor = calcVat ? (config.value?.vat ?? 0.07) : 0; - a.totalPrice = precisionRound(a.totalPrice + price); - a.totalDiscount = precisionRound(a.totalDiscount + Number(c.discount)); - a.vat = calcVat ? precisionRound(a.vat + vat) : a.vat; + const price = precisionRound( + (c.pricePerUnit * c.amount * (1 + vatFactor) - c.discount) / + (1 + vatFactor), + ); + const vat = price * vatFactor; + + a.totalPrice = precisionRound(a.totalPrice + price + c.discount); + a.totalDiscount = precisionRound(a.totalDiscount + c.discount); + a.vat = precisionRound(a.vat + vat); a.vatExcluded = calcVat ? a.vatExcluded : precisionRound(a.vatExcluded + price); - a.finalPrice = precisionRound( - a.totalPrice - - a.totalDiscount + - a.vat - - Number(quotationFormData.value.discount || 0), - ); + a.finalPrice = precisionRound(a.totalPrice - a.totalDiscount + a.vat); return a; }, diff --git a/src/pages/05_quotation/QuotationFormInfo.vue b/src/pages/05_quotation/QuotationFormInfo.vue index 5f9f45b3..c0324392 100644 --- a/src/pages/05_quotation/QuotationFormInfo.vue +++ b/src/pages/05_quotation/QuotationFormInfo.vue @@ -446,7 +446,9 @@ watch( {{ formatNumberDecimal( - summaryPrice.totalPrice - summaryPrice.totalDiscount, + summaryPrice.totalPrice - + summaryPrice.totalDiscount - + summaryPrice.vatExcluded, 2, ) }} diff --git a/src/pages/05_quotation/preview/ViewForm.vue b/src/pages/05_quotation/preview/ViewForm.vue index 8b00ca70..62a30faa 100644 --- a/src/pages/05_quotation/preview/ViewForm.vue +++ b/src/pages/05_quotation/preview/ViewForm.vue @@ -1,6 +1,6 @@ @@ -109,7 +107,6 @@ const agentUserId = defineModel('agentUserId'); /> - Date: Fri, 12 Sep 2025 14:29:42 +0700 Subject: [PATCH 13/35] fix: type error --- src/stores/quotations/types.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/stores/quotations/types.ts b/src/stores/quotations/types.ts index ac3740de..e260bd52 100644 --- a/src/stores/quotations/types.ts +++ b/src/stores/quotations/types.ts @@ -44,7 +44,12 @@ export type CustomerBranchRelation = { payDate: string; jobDescription: string; jobPosition: string; - businessType: string; + businessTypeId: string; + businessType?: { + id: string; + name: string; + nameEN: string; + }; contactName: string; officeTel: string; contactTel: string; @@ -80,7 +85,6 @@ export type CustomerBranchRelation = { namePrefix: string; telephoneNo: string; codeCustomer: string; - customerName: string; updatedByUserId: string; createdByUserId: string; code: string; From 763ac07be70349b4a38c5f28b030e4394fe4567c Mon Sep 17 00:00:00 2001 From: puriphatt Date: Fri, 12 Sep 2025 17:59:03 +0700 Subject: [PATCH 14/35] refactor: customer & employee --- .../03_customer-management/TableEmpoloyee.vue | 11 +- src/pages/03_customer-management/MainPage.vue | 5968 ++--------------- .../03_customer-management/TabCustomer.vue | 2001 ++++++ .../03_customer-management/TabEmployee.vue | 3704 ++++++++++ src/pages/03_customer-management/form.ts | 5 + 5 files changed, 6154 insertions(+), 5535 deletions(-) create mode 100644 src/pages/03_customer-management/TabCustomer.vue create mode 100644 src/pages/03_customer-management/TabEmployee.vue diff --git a/src/components/03_customer-management/TableEmpoloyee.vue b/src/components/03_customer-management/TableEmpoloyee.vue index d93c6085..000c701a 100644 --- a/src/components/03_customer-management/TableEmpoloyee.vue +++ b/src/components/03_customer-management/TableEmpoloyee.vue @@ -141,8 +141,9 @@ defineEmits<{ router.push('/customer-management'), - }, - ]; - - gridView.value = $q.screen.lt.md ? true : false; - - if (route.query.tab === 'customer') { - currentTab.value = 'employer'; - if (route.query.id) openSpecificCustomer(route.query.id as string); - } else if (route.query.tab === 'employee') { - currentTab.value = 'employee'; - if (route.query.id) openSpecificEmployee(route.query.id as string); - } - - if (route.name === 'CustomerManagement') await fetchListCustomer(true); - - if ( - route.name === 'CustomerBranchManagement' && - typeof route.params.customerId === 'string' - ) { - const _data = await customerStore.fetchById(route.params.customerId); - - if (_data) { - currentCustomer.value = _data; - navigatorStore.current.path.push({ - text: `${ - _data.customerType === 'CORP' - ? _data.branch[0].registerName - : locale.value === 'eng' - ? _data.branch[0].firstNameEN + ' ' + _data.branch[0].lastNameEN - : _data.branch[0].firstName + ' ' + _data.branch[0].lastName - }`, - i18n: false, - }); - } else { - router.push('/customer-management'); - } - } - flowStore.rotate(); -} -onMounted(init); +const refTabCustomer = ref>(); +const refTabEmployee = ref>(); // NOTE: Page Data const currentCustomer = ref(); -const listCustomer = ref<(Customer & { branch: CustomerBranch[] })[]>([]); -const listEmployee = ref([]); +// const listCustomer = ref<(Customer & { branch: CustomerBranch[] })[]>([]); +// const listEmployee = ref([]); const hideStats = ref(false); const statsCustomerType = ref({ CORP: 0, @@ -201,68 +158,31 @@ const customerTypeSelected = ref<{ value: 'all', }); -const customerNameInfo = computed(() => { - if (customerFormData.value.customerBranch === undefined) return; +// const customerNameInfo = computed(() => { +// if (customerFormData.value.customerBranch === undefined) return; - const name = - locale.value === 'eng' - ? `${customerFormData.value.customerBranch[0]?.firstNameEN} ${customerFormData.value.customerBranch[0]?.lastNameEN}` - : `${customerFormData.value.customerBranch[0]?.firstName} ${customerFormData.value.customerBranch[0]?.lastName}`; - return name || '-'; -}); -const currentBtnOpen = ref([]); +// const name = +// locale.value === 'eng' +// ? `${customerFormData.value.customerBranch[0]?.firstNameEN} ${customerFormData.value.customerBranch[0]?.lastNameEN}` +// : `${customerFormData.value.customerBranch[0]?.firstName} ${customerFormData.value.customerBranch[0]?.lastName}`; +// return name || '-'; +// }); +// const currentBtnOpen = ref([]); const employeeStats = ref(0); const gridView = ref(false); -const splitPercent = computed(() => ($q.screen.lt.md ? 0 : 15)); +// const splitPercent = computed(() => ($q.screen.lt.md ? 0 : 15)); -const currentPageCustomer = ref(1); -const maxPageCustomer = ref(1); -const currentPageEmployee = ref(1); -const maxPageEmployee = ref(1); -const pageSize = ref(30); -const dialogCustomerImageUpload = ref>(); -const dialogEmployeeImageUpload = ref>(); +// const currentPageCustomer = ref(1); +// const maxPageCustomer = ref(1); +// const currentPageEmployee = ref(1); +// const maxPageEmployee = ref(1); +// const pageSize = ref(30); +// const dialogCustomerImageUpload = ref>(); +// const dialogEmployeeImageUpload = ref>(); // image const imageList = ref<{ selectedImage: string; list: string[] }>(); -watch(() => route.name, init); -watch( - [ - currentTab, - currentStatus, - inputSearch, - customerTypeSelected, - pageSize, - searchDate, - ], - async ([tabName], [oldTabName]) => { - // if (tabName !== oldTabName) searchDate.value = []; - if (tabName === 'employer') { - currentPageCustomer.value = 1; - currentBtnOpen.value = []; - listCustomer.value = []; - await fetchListCustomer(true); - } - if (tabName === 'employee') { - currentPageEmployee.value = 1; - listEmployee.value = []; - await fetchListEmployee({ fetchStats: true }); - } - - customerFormState.value.currentCustomerId = undefined; - flowStore.rotate(); - }, -); -watch(locale, () => { - customerTypeSelected.value = { - label: `${customerTypeSelected.value.label}`, - value: customerTypeSelected.value?.value, - }; -}); -watch( - () => $q.screen.lt.md, - () => $q.screen.lt.md && (gridView.value = true), -); +const branch = ref(); const fieldDisplayCustomer = ref< { @@ -274,7 +194,6 @@ const fieldDisplayCustomer = ref< .filter((v) => v.name !== 'action') .map((v) => ({ label: v.label, value: v.name })), ); - const fieldDisplayEmployee = ref< { label: string; @@ -285,7 +204,6 @@ const fieldDisplayEmployee = ref< .filter((v) => v.name !== 'action') .map((v) => ({ label: v.label, value: v.name })), ); - const fieldSelected = ref( [ ...columnsEmployee.map((v) => v.name), @@ -293,110 +211,16 @@ const fieldSelected = ref( ].filter((v, index, self) => self.indexOf(v) === index), ); -const branch = ref(); - const customerStats = [ { id: 1, count: 2, name: 'CORP' }, { id: 2, count: 3, name: 'PERS' }, ]; - const fieldCustomer = [ 'all', 'customerLegalEntity', 'customerNaturalPerson', ] as const; -const employeeHistoryDialog = ref(false); -const employeeHistory = ref(); - -async function fetchListCustomer(fetchStats = false, mobileFetch?: boolean) { - const total = statsCustomerType.value.PERS + statsCustomerType.value.CORP; - - const resultList = await customerStore.fetchList({ - includeBranch: true, - page: mobileFetch ? 1 : currentPageCustomer.value, - pageSize: mobileFetch - ? listCustomer.value.length + - (total === listCustomer.value.length ? 1 : 0) - : pageSize.value, - status: - currentStatus.value === 'All' - ? undefined - : currentStatus.value === 'ACTIVE' - ? 'ACTIVE' - : 'INACTIVE', - query: inputSearch.value, - startDate: searchDate.value[0], - endDate: searchDate.value[1], - customerType: ( - { - all: undefined, - customerLegalEntity: CustomerType.Corporate, - customerNaturalPerson: CustomerType.Person, - } as const - )[customerTypeSelected.value.value], - }); - - if (resultList) { - // currentPageCustomer.value = resultList.page; - maxPageCustomer.value = Math.ceil(resultList.total / pageSize.value); - $q.screen.xs && !mobileFetch - ? listCustomer.value.push(...resultList.result) - : (listCustomer.value = resultList.result); - } - - if (fetchStats) { - statsCustomerType.value = await customerStore - .getStatsCustomer() - .then((value) => (value ? value : { CORP: 0, PERS: 0 })); - } -} - -async function fetchListEmployee(opt?: { - fetchStats?: boolean; - page?: number; - pageSize?: number; - customerId?: string; - mobileFetch?: boolean; -}) { - const resultListEmployee = await employeeStore.fetchList({ - customerId: opt?.customerId, - page: opt - ? opt.mobileFetch - ? 1 - : opt.page || currentPageEmployee.value - : currentPageEmployee.value, - pageSize: opt - ? opt.mobileFetch - ? listEmployee.value.length + - (employeeStats.value === listEmployee.value.length ? 1 : 0) - : opt.pageSize || pageSize.value - : pageSize.value, - status: - currentStatus.value === 'All' - ? undefined - : currentStatus.value === 'ACTIVE' - ? 'ACTIVE' - : 'INACTIVE', - query: inputSearch.value, - passport: true, - visa: true, - startDate: searchDate.value[0], - endDate: searchDate.value[1], - }); - if (resultListEmployee) { - maxPageEmployee.value = Math.ceil( - resultListEmployee.total / pageSize.value, - ); - $q.screen.xs && !(opt && opt.mobileFetch) - ? listEmployee.value.push(...resultListEmployee.result) - : (listEmployee.value = resultListEmployee.result); - } - - if (opt && opt.fetchStats) - employeeStats.value = await employeeStore.getStatsEmployee(); -} - async function triggerChangeStatus( id: string, status: string, @@ -416,15 +240,17 @@ async function triggerChangeStatus( : t('dialog.message.confirmChangeStatusOn'), action: async () => { if (currentTab.value === 'employee') { - await toggleStatusEmployee( - id, - status === 'INACTIVE' ? false : true, - employeeName, - ) + await refTabEmployee.value + ?.toggleStatusEmployee( + id, + status === 'INACTIVE' ? false : true, + employeeName, + ) .then(resolve) .catch(reject); } else { - await toggleStatusCustomer(id, status === 'INACTIVE' ? false : true) + await refTabCustomer.value + ?.toggleStatusCustomer(id, status === 'INACTIVE' ? false : true) .then(resolve) .catch(reject); } @@ -434,65 +260,6 @@ async function triggerChangeStatus( }); } -async function toggleStatusEmployee( - id: string, - status: boolean, - employeeName: string, -) { - const res = await employeeStore.editById(id, { - status: !status ? 'ACTIVE' : 'INACTIVE', - firstNameEN: employeeName, - }); - if (res && employeeFormState.value.drawerModal) - currentFromDataEmployee.value.status = res.status; - - await fetchListEmployee({ mobileFetch: $q.screen.xs }); - flowStore.rotate(); -} - -async function toggleStatusCustomer(id: string, status: boolean) { - const res = await customerStore.editById(id, { - status: !status ? 'ACTIVE' : 'INACTIVE', - }); - if (res && customerFormState.value.drawerModal) - customerFormData.value.status = res.status; - - await fetchListCustomer(false, $q.screen.xs); - flowStore.rotate(); -} -async function openHistory(id: string) { - const res = await employeeStore.getEditHistory(id); - employeeHistory.value = res.reverse(); - employeeHistoryDialog.value = true; -} - -async function editCustomerForm(id: string) { - await customerFormStore.assignFormData(id); - await fetchListOfOptionBranch(); - await fetchImageList( - id, - customerFormData.value.selectedImage || '', - 'customer', - ); - customerFormState.value.branchIndex = -1; - customerFormState.value.dialogType = 'edit'; - customerFormState.value.drawerModal = true; - customerFormState.value.editCustomerId = id; -} - -async function editEmployeeFormPersonal(id: string) { - await employeeFormStore.assignFormDataEmployee(id); - await fetchImageList( - id, - currentFromDataEmployee.value.selectedImage || '', - 'employee', - ); - - employeeFormState.value.isEmployeeEdit = true; - employeeFormState.value.dialogType = 'edit'; - employeeFormState.value.drawerModal = true; -} - async function createCustomerForm(customerType: 'CORP' | 'PERS') { customerFormState.value.dialogModal = true; customerFormState.value.dialogType = 'create'; @@ -524,30 +291,6 @@ async function fetchImageList( return res; } -async function openSpecificCustomer(id: string) { - await customerFormStore.assignFormData(id); - await fetchImageList( - id, - customerFormData.value.selectedImage || '', - 'customer', - ); - customerFormState.value.branchIndex = -1; - customerFormState.value.drawerModal = true; - customerFormState.value.editCustomerId = id; - customerFormState.value.dialogType = 'info'; -} - -async function openSpecificEmployee(id: string) { - await employeeFormStore.assignFormDataEmployee(id); - await fetchImageList( - id, - currentFromDataEmployee.value.selectedImage || '', - 'employee', - ); - employeeFormState.value.dialogType = 'info'; - employeeFormState.value.drawerModal = true; -} - async function triggerExport() { switch (currentTab.value) { case 'employer': @@ -561,131 +304,388 @@ async function triggerExport() { } } +async function init() { + navigatorStore.current.title = 'menu.customer'; + navigatorStore.current.path = [ + { + text: 'menu.customerCaption', + i18n: true, + handler: () => router.push('/customer-management'), + }, + ]; + + gridView.value = $q.screen.lt.md ? true : false; + + if (route.query.tab === 'customer') { + currentTab.value = 'employer'; + if (route.query.id) + refTabCustomer.value?.openSpecificCustomer(route.query.id as string); + } else if (route.query.tab === 'employee') { + currentTab.value = 'employee'; + if (route.query.id) + refTabEmployee.value?.openSpecificEmployee(route.query.id as string); + } + + if ( + route.name === 'CustomerBranchManagement' && + typeof route.params.customerId === 'string' + ) { + const _data = await customerStore.fetchById(route.params.customerId); + + if (_data) { + currentCustomer.value = _data; + navigatorStore.current.path.push({ + text: `${ + _data.customerType === 'CORP' + ? _data.branch[0].registerName + : locale.value === 'eng' + ? _data.branch[0].firstNameEN + ' ' + _data.branch[0].lastNameEN + : _data.branch[0].firstName + ' ' + _data.branch[0].lastName + }`, + i18n: false, + }); + } else { + router.push('/customer-management'); + } + } + + flowStore.rotate(); +} + +watch(() => route.name, init); + +// watch( +// [currentTab, currentStatus, inputSearch, searchDate], +// async ([tabName], [oldTabName]) => { +// if (tabName !== oldTabName) searchDate.value = []; +// if (tabName === 'employer') { +// currentPageCustomer.value = 1; +// currentBtnOpen.value = []; +// listCustomer.value = []; +// await fetchListCustomer(true); +// } +// if (tabName === 'employee') { +// currentPageEmployee.value = 1; +// listEmployee.value = []; +// await fetchListEmployee({ fetchStats: true }); +// } + +// customerFormState.value.currentCustomerId = undefined; +// flowStore.rotate(); +// }, +// ); + +watch(locale, () => { + customerTypeSelected.value = { + label: `${customerTypeSelected.value.label}`, + value: customerTypeSelected.value?.value, + }; +}); + +watch( + () => $q.screen.lt.md, + () => $q.screen.lt.md && (gridView.value = true), +); + +onMounted(async () => await init()); +// const employeeHistoryDialog = ref(false); +// const employeeHistory = ref(); + +// async function fetchListCustomer(fetchStats = false, mobileFetch?: boolean) { +// const total = statsCustomerType.value.PERS + statsCustomerType.value.CORP; + +// const resultList = await customerStore.fetchList({ +// includeBranch: true, +// page: mobileFetch ? 1 : currentPageCustomer.value, +// pageSize: mobileFetch +// ? listCustomer.value.length + +// (total === listCustomer.value.length ? 1 : 0) +// : pageSize.value, +// status: +// currentStatus.value === 'All' +// ? undefined +// : currentStatus.value === 'ACTIVE' +// ? 'ACTIVE' +// : 'INACTIVE', +// query: inputSearch.value, +// startDate: searchDate.value[0], +// endDate: searchDate.value[1], +// customerType: ( +// { +// all: undefined, +// customerLegalEntity: CustomerType.Corporate, +// customerNaturalPerson: CustomerType.Person, +// } as const +// )[customerTypeSelected.value.value], +// }); + +// if (resultList) { +// maxPageCustomer.value = Math.ceil(resultList.total / pageSize.value); +// $q.screen.xs && !mobileFetch +// ? listCustomer.value.push(...resultList.result) +// : (listCustomer.value = resultList.result); +// } + +// if (fetchStats) { +// statsCustomerType.value = await customerStore +// .getStatsCustomer() +// .then((value) => (value ? value : { CORP: 0, PERS: 0 })); +// } +// } + +// async function fetchListEmployee(opt?: { +// fetchStats?: boolean; +// page?: number; +// pageSize?: number; +// customerId?: string; +// mobileFetch?: boolean; +// }) { +// const resultListEmployee = await employeeStore.fetchList({ +// customerId: opt?.customerId, +// page: opt +// ? opt.mobileFetch +// ? 1 +// : opt.page || currentPageEmployee.value +// : currentPageEmployee.value, +// pageSize: opt +// ? opt.mobileFetch +// ? listEmployee.value.length + +// (employeeStats.value === listEmployee.value.length ? 1 : 0) +// : opt.pageSize || pageSize.value +// : pageSize.value, +// status: +// currentStatus.value === 'All' +// ? undefined +// : currentStatus.value === 'ACTIVE' +// ? 'ACTIVE' +// : 'INACTIVE', +// query: inputSearch.value, +// passport: true, +// visa: true, +// startDate: searchDate.value[0], +// endDate: searchDate.value[1], +// }); +// if (resultListEmployee) { +// maxPageEmployee.value = Math.ceil( +// resultListEmployee.total / pageSize.value, +// ); +// $q.screen.xs && !(opt && opt.mobileFetch) +// ? listEmployee.value.push(...resultListEmployee.result) +// : (listEmployee.value = resultListEmployee.result); +// } + +// if (opt && opt.fetchStats) +// employeeStats.value = await employeeStore.getStatsEmployee(); +// } + +// async function toggleStatusEmployee( +// id: string, +// status: boolean, +// employeeName: string, +// ) { +// const res = await employeeStore.editById(id, { +// status: !status ? 'ACTIVE' : 'INACTIVE', +// firstNameEN: employeeName, +// }); +// if (res && employeeFormState.value.drawerModal) +// currentFromDataEmployee.value.status = res.status; + +// await fetchListEmployee({ mobileFetch: $q.screen.xs }); +// flowStore.rotate(); +// } + +// async function toggleStatusCustomer(id: string, status: boolean) { +// const res = await customerStore.editById(id, { +// status: !status ? 'ACTIVE' : 'INACTIVE', +// }); +// if (res && customerFormState.value.drawerModal) +// customerFormData.value.status = res.status; + +// await fetchListCustomer(false, $q.screen.xs); +// flowStore.rotate(); +// } +// async function openHistory(id: string) { +// const res = await employeeStore.getEditHistory(id); +// employeeHistory.value = res.reverse(); +// employeeHistoryDialog.value = true; +// } + +// async function editCustomerForm(id: string) { +// await customerFormStore.assignFormData(id); +// await fetchListOfOptionBranch(); +// await fetchImageList( +// id, +// customerFormData.value.selectedImage || '', +// 'customer', +// ); +// customerFormState.value.branchIndex = -1; +// customerFormState.value.dialogType = 'edit'; +// customerFormState.value.drawerModal = true; +// customerFormState.value.editCustomerId = id; +// } + +// async function editEmployeeFormPersonal(id: string) { +// await employeeFormStore.assignFormDataEmployee(id); +// await fetchImageList( +// id, +// currentFromDataEmployee.value.selectedImage || '', +// 'employee', +// ); + +// employeeFormState.value.isEmployeeEdit = true; +// employeeFormState.value.dialogType = 'edit'; +// employeeFormState.value.drawerModal = true; +// } + +// async function openSpecificCustomer(id: string) { +// await customerFormStore.assignFormData(id); +// await fetchImageList( +// id, +// customerFormData.value.selectedImage || '', +// 'customer', +// ); +// customerFormState.value.branchIndex = -1; +// customerFormState.value.drawerModal = true; +// customerFormState.value.editCustomerId = id; +// customerFormState.value.dialogType = 'info'; +// } + +// async function openSpecificEmployee(id: string) { +// await employeeFormStore.assignFormDataEmployee(id); +// await fetchImageList( +// id, +// currentFromDataEmployee.value.selectedImage || '', +// 'employee', +// ); +// employeeFormState.value.dialogType = 'info'; +// employeeFormState.value.drawerModal = true; +// } + // TODO: When in employee form, if select address same as customer then auto fill -watch( - () => employeeFormState.value.currentCustomerBranch, - (e) => { - if (!e) return; - if (employeeFormState.value.formDataEmployeeSameAddr) { - currentFromDataEmployee.value.address = e.address; - currentFromDataEmployee.value.addressEN = e.addressEN; - currentFromDataEmployee.value.provinceId = e.provinceId; - currentFromDataEmployee.value.districtId = e.districtId; - currentFromDataEmployee.value.subDistrictId = e.subDistrictId; - } - currentFromDataEmployee.value.customerBranchId = e.id; - }, -); +// watch( +// () => employeeFormState.value.currentCustomerBranch, +// (e) => { +// if (!e) return; +// if (employeeFormState.value.formDataEmployeeSameAddr) { +// currentFromDataEmployee.value.address = e.address; +// currentFromDataEmployee.value.addressEN = e.addressEN; +// currentFromDataEmployee.value.provinceId = e.provinceId; +// currentFromDataEmployee.value.districtId = e.districtId; +// currentFromDataEmployee.value.subDistrictId = e.subDistrictId; +// } +// currentFromDataEmployee.value.customerBranchId = e.id; +// }, +// ); -watch( - () => employeeFormState.value.formDataEmployeeSameAddr, - (isSame) => { - if (!employeeFormState.value.currentCustomerBranch) return; - if (isSame) { - currentFromDataEmployee.value.address = - employeeFormState.value.currentCustomerBranch.address; - currentFromDataEmployee.value.addressEN = - employeeFormState.value.currentCustomerBranch.addressEN; - currentFromDataEmployee.value.provinceId = - employeeFormState.value.currentCustomerBranch.provinceId; - currentFromDataEmployee.value.districtId = - employeeFormState.value.currentCustomerBranch.districtId; - currentFromDataEmployee.value.subDistrictId = - employeeFormState.value.currentCustomerBranch.subDistrictId; - } - currentFromDataEmployee.value.customerBranchId = - employeeFormState.value.currentCustomerBranch.id; - }, -); +// watch( +// () => employeeFormState.value.formDataEmployeeSameAddr, +// (isSame) => { +// if (!employeeFormState.value.currentCustomerBranch) return; +// if (isSame) { +// currentFromDataEmployee.value.address = +// employeeFormState.value.currentCustomerBranch.address; +// currentFromDataEmployee.value.addressEN = +// employeeFormState.value.currentCustomerBranch.addressEN; +// currentFromDataEmployee.value.provinceId = +// employeeFormState.value.currentCustomerBranch.provinceId; +// currentFromDataEmployee.value.districtId = +// employeeFormState.value.currentCustomerBranch.districtId; +// currentFromDataEmployee.value.subDistrictId = +// employeeFormState.value.currentCustomerBranch.subDistrictId; +// } +// currentFromDataEmployee.value.customerBranchId = +// employeeFormState.value.currentCustomerBranch.id; +// }, +// ); -watch( - () => employeeFormState.value.currentTab, - () => { - employeeFormState.value.isEmployeeEdit = false; - }, -); +// watch( +// () => employeeFormState.value.currentTab, +// () => { +// employeeFormState.value.isEmployeeEdit = false; +// }, +// ); -watch( - () => currentFromDataEmployee.value.dateOfBirth, - (v) => { - const isEdit = - employeeFormState.value.drawerModal && - employeeFormState.value.isEmployeeEdit; - let currentFormDate = v && toISOStringWithTimezone(new Date(v)); - let currentDate: string = ''; +// watch( +// () => currentFromDataEmployee.value.dateOfBirth, +// (v) => { +// const isEdit = +// employeeFormState.value.drawerModal && +// employeeFormState.value.isEmployeeEdit; +// let currentFormDate = v && toISOStringWithTimezone(new Date(v)); +// let currentDate: string = ''; - if (isEdit && employeeFormState.value.currentEmployee) { - currentDate = toISOStringWithTimezone( - new Date(employeeFormState.value.currentEmployee.dateOfBirth), - ); - } +// if (isEdit && employeeFormState.value.currentEmployee) { +// currentDate = toISOStringWithTimezone( +// new Date(employeeFormState.value.currentEmployee.dateOfBirth), +// ); +// } - if ( - employeeFormState.value.dialogModal || - (isEdit && currentFormDate !== currentDate) - ) { - const age = calculateAge( - currentFromDataEmployee.value.dateOfBirth, - 'year', - ); - if (currentFromDataEmployee.value.dateOfBirth && Number(age) < 15) { - dialog({ - color: 'warning', - icon: 'mdi-alert', - title: t('dialog.title.youngWorker15'), - cancelText: t('general.edit'), - persistent: true, - message: t('dialog.message.youngWorker15'), +// if ( +// employeeFormState.value.dialogModal || +// (isEdit && currentFormDate !== currentDate) +// ) { +// const age = calculateAge( +// currentFromDataEmployee.value.dateOfBirth, +// 'year', +// ); +// if (currentFromDataEmployee.value.dateOfBirth && Number(age) < 15) { +// dialog({ +// color: 'warning', +// icon: 'mdi-alert', +// title: t('dialog.title.youngWorker15'), +// cancelText: t('general.edit'), +// persistent: true, +// message: t('dialog.message.youngWorker15'), - cancel: async () => { - currentFromDataEmployee.value.dateOfBirth = null; - return; - }, - }); - } +// cancel: async () => { +// currentFromDataEmployee.value.dateOfBirth = null; +// return; +// }, +// }); +// } - if ( - currentFromDataEmployee.value.dateOfBirth && - Number(age) > 15 && - Number(age) <= 18 - ) { - dialog({ - color: 'warning', - icon: 'mdi-alert', - title: t('dialog.title.youngWorker18'), - cancelText: t('general.cancel'), - actionText: t('general.confirm'), - persistent: true, - message: t('dialog.message.youngWorker18'), - action: () => {}, - cancel: async () => { - currentFromDataEmployee.value.dateOfBirth = null; - return; - }, - }); - } - } - }, -); +// if ( +// currentFromDataEmployee.value.dateOfBirth && +// Number(age) > 15 && +// Number(age) <= 18 +// ) { +// dialog({ +// color: 'warning', +// icon: 'mdi-alert', +// title: t('dialog.title.youngWorker18'), +// cancelText: t('general.cancel'), +// actionText: t('general.confirm'), +// persistent: true, +// message: t('dialog.message.youngWorker18'), +// action: () => {}, +// cancel: async () => { +// currentFromDataEmployee.value.dateOfBirth = null; +// return; +// }, +// }); +// } +// } +// }, +// ); -watch( - () => customerFormData.value.image, - () => { - if (customerFormData.value.image !== null) - customerFormState.value.isImageEdit = true; - }, -); +// watch( +// () => customerFormData.value.image, +// () => { +// if (customerFormData.value.image !== null) +// customerFormState.value.isImageEdit = true; +// }, +// ); -watch( - () => currentFromDataEmployee.value.image, - () => { - if (currentFromDataEmployee.value.image !== null) - employeeFormState.value.isImageEdit = true; - }, -); +// watch( +// () => currentFromDataEmployee.value.image, +// () => { +// if (currentFromDataEmployee.value.image !== null) +// employeeFormState.value.isImageEdit = true; +// }, +// ); -const emptyCreateDialog = ref(false); +// const emptyCreateDialog = ref(false); diff --git a/src/pages/03_customer-management/TabEmployee.vue b/src/pages/03_customer-management/TabEmployee.vue new file mode 100644 index 00000000..c7fcc8d9 --- /dev/null +++ b/src/pages/03_customer-management/TabEmployee.vue @@ -0,0 +1,3704 @@ + + + + diff --git a/src/pages/03_customer-management/form.ts b/src/pages/03_customer-management/form.ts index fe875a3c..2de3415d 100644 --- a/src/pages/03_customer-management/form.ts +++ b/src/pages/03_customer-management/form.ts @@ -22,6 +22,10 @@ import { useRoute } from 'vue-router'; export const useCustomerForm = defineStore('form-customer', () => { const customerStore = useCustomerStore(); + const onCreateImageList = ref<{ + selectedImage: string; + list: { url: string; imgFile: File | null; name: string }[]; + }>({ selectedImage: '', list: [] }); const { t } = useI18n(); const flowStore = useFlowStore(); @@ -498,6 +502,7 @@ export const useCustomerForm = defineStore('form-customer', () => { } return { + onCreateImageList, tabFieldRequired, registerAbleBranchOption, state, From 67cde37e342180425134bb958fe519df08f70202 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 12 Sep 2025 14:29:54 +0700 Subject: [PATCH 15/35] fix: price calc on update installments --- src/pages/05_quotation/QuotationForm.vue | 46 +++++++++--------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/src/pages/05_quotation/QuotationForm.vue b/src/pages/05_quotation/QuotationForm.vue index c373c964..fa018fb5 100644 --- a/src/pages/05_quotation/QuotationForm.vue +++ b/src/pages/05_quotation/QuotationForm.vue @@ -715,19 +715,13 @@ function handleUpdateProductTable( // handleChangePayType(quotationFormData.value.payCondition); // calc price const calc = (c: QuotationPayload['productServiceList'][number]) => { - const originalPrice = c.pricePerUnit || 0; - const finalPriceWithVat = precisionRound( - originalPrice * (1 + (config.value?.vat || 0.07)), - ); - const finalPriceNoVat = - finalPriceWithVat / (1 + (config.value?.vat || 0.07)); - - const price = finalPriceNoVat * c.amount; - const vat = c.product.calcVat - ? (finalPriceNoVat * c.amount - (c.discount || 0)) * - (config.value?.vat || 0.07) - : 0; - return precisionRound(price + vat); + const calcVat = + c.product[agentPrice.value ? 'agentPriceCalcVat' : 'calcVat']; + const vatFactor = calcVat ? (config.value?.vat ?? 0.07) : 0; + const pricePerUnit = + precisionRound(c.pricePerUnit * (1 + vatFactor)) / (1 + vatFactor); + const price = pricePerUnit * c.amount * (1 + vatFactor) - c.discount; + return precisionRound(price); }; // installment @@ -780,21 +774,16 @@ function toggleDeleteProduct(index: number) { // cal curr amount if (currPaySplit && currTempPaySplit) { - const price = agentPrice.value - ? currProduct.product.agentPrice - : currProduct.product.price; - const pricePerUnit = currProduct.product.vatIncluded - ? price / (1 + (config.value?.vat || 0.07)) - : price; - const vat = - (pricePerUnit * currProduct.amount - currProduct.discount) * - (config.value?.vat || 0.07); - const finalPrice = - pricePerUnit * currProduct.amount + - vat - - Number(currProduct.discount || 0); + const calcVat = + currProduct.product[agentPrice.value ? 'agentPriceCalcVat' : 'calcVat']; + const vatFactor = calcVat ? (config.value?.vat ?? 0.07) : 0; - currTempPaySplit.amount = currPaySplit.amount - finalPrice; + const price = precisionRound( + currProduct.pricePerUnit * currProduct.amount * (1 + vatFactor) - + currProduct.discount, + ); + + currTempPaySplit.amount = currPaySplit.amount - price; currPaySplit.amount = currTempPaySplit.amount; } @@ -849,8 +838,7 @@ function convertToTable(nodes: Node[]) { tempTableProduct.value = JSON.parse(JSON.stringify(list)); if (nodes.length > 0) { - quotationFormData.value.paySplit = Array.apply( - null, + quotationFormData.value.paySplit = Array.from( new Array(quotationFormData.value.paySplitCount), ).map((_, i) => ({ no: i + 1, From e6f8870cdf67076fefd1009bfca19505e661c7db Mon Sep 17 00:00:00 2001 From: puriphatt Date: Mon, 15 Sep 2025 14:53:40 +0700 Subject: [PATCH 16/35] refactor: drawer employee --- .../03_customer-management/DrawerEmployee.vue | 1670 +++++++++++++++++ src/pages/03_customer-management/MainPage.vue | 441 +---- .../03_customer-management/TabCustomer.vue | 21 +- .../03_customer-management/TabEmployee.vue | 1595 +--------------- 4 files changed, 1702 insertions(+), 2025 deletions(-) create mode 100644 src/components/03_customer-management/DrawerEmployee.vue diff --git a/src/components/03_customer-management/DrawerEmployee.vue b/src/components/03_customer-management/DrawerEmployee.vue new file mode 100644 index 00000000..c7155931 --- /dev/null +++ b/src/components/03_customer-management/DrawerEmployee.vue @@ -0,0 +1,1670 @@ + + + diff --git a/src/pages/03_customer-management/MainPage.vue b/src/pages/03_customer-management/MainPage.vue index 6152ad1b..7ed8d550 100644 --- a/src/pages/03_customer-management/MainPage.vue +++ b/src/pages/03_customer-management/MainPage.vue @@ -3,21 +3,11 @@ import { ref, watch, onMounted, computed } from 'vue'; import { useI18n } from 'vue-i18n'; import { useQuasar } from 'quasar'; import { useRoute, useRouter } from 'vue-router'; -import { getUserId, getRole } from 'src/services/keycloak'; -import { baseUrl, setPrefixName, waitAll } from 'src/stores/utils'; -import { dateFormat } from 'src/utils/datetime'; -import { dialogCheckData, canAccess } from 'stores/utils'; +import { canAccess } from 'stores/utils'; -import useOcrStore from 'stores/ocr'; import useCustomerStore from 'stores/customer'; import useEmployeeStore from 'stores/employee'; -import useMyBranchStore from 'stores/my-branch'; -import { - dialog, - notify, - resetScrollBar, - capitalizeFirstLetter, -} from 'stores/utils'; +import { dialog } from 'stores/utils'; import { useNavigator } from 'src/stores/navigator'; import useFlowStore from 'stores/flow'; import { Status } from 'stores/types'; @@ -25,68 +15,21 @@ import { CustomerStats, Customer, CustomerBranch, - CustomerBranchCreate, CustomerType, } from 'stores/customer/types'; import { Employee, EmployeeHistory } from 'stores/employee/types'; -import { - EditButton, - DeleteButton, - SaveButton, - UndoButton, -} from 'components/button'; +import { SaveButton } from 'components/button'; import TabCustomer from './TabCustomer.vue'; -import ExpirationDate from 'components/03_customer-management/ExpirationDate.vue'; -import { AddressForm } from 'components/form'; -import BranchCard from 'src/components/01_branch-management/BranchCard.vue'; -import ItemCard from 'src/components/ItemCard.vue'; -import DrawerInfo from 'components/DrawerInfo.vue'; import FloatingActionButton from 'components/FloatingActionButton.vue'; import StatCardComponent from 'components/StatCardComponent.vue'; -import TooltipComponent from 'components/TooltipComponent.vue'; -import EmptyAddButton from 'components/AddButton.vue'; -import NoData from 'components/NoData.vue'; -import PaginationComponent from 'components/PaginationComponent.vue'; -import BasicInformation from 'components/03_customer-management/employee/BasicInformation.vue'; -import FormPerson from 'components/02_personnel-management/FormPerson.vue'; -import { EmployerFormBasicInfo, EmployerFormBranch } from './components'; import BranchPage from './BranchPage.vue'; -import FormEmployeePassport from 'components/03_customer-management/FormEmployeePassport.vue'; -import DialogForm from 'components/DialogForm.vue'; -import SideMenu from 'components/SideMenu.vue'; -import TableEmpoloyee from 'src/components/03_customer-management/TableEmpoloyee.vue'; -import HistoryEditComponent from 'src/components/03_customer-management/HistoryEditComponent.vue'; -import { calculateAge, toISOStringWithTimezone } from 'src/utils/datetime'; -import { runOcr, parseResultMRZ } from 'src/utils/ocr'; -import { formatAddress } from 'src/utils/address'; -import { - UploadFileGroup, - FormTm6, - NoticeJobEmployment, -} from 'components/upload-file'; -import { - columnsCustomer, - columnsEmployee, - uploadFileListEmployee, - columnsAttachment, - dialogCreateCustomerItem, -} from './constant'; +import { columnsCustomer, columnsEmployee } from './constant'; import { useCustomerForm, useEmployeeForm } from './form'; import { storeToRefs } from 'pinia'; -import ProfileBanner from 'components/ProfileBanner.vue'; -import ImageUploadDialog from 'components/ImageUploadDialog.vue'; -import FormEmployeeHealthCheck from 'components/03_customer-management/FormEmployeeHealthCheck.vue'; -import FormEmployeeWorkHistory from 'components/03_customer-management/FormEmployeeWorkHistory.vue'; -import FormEmployeeOther from 'components/03_customer-management/FormEmployeeOther.vue'; -import useOptionStore from 'stores/options'; -import { DialogContainer, DialogHeader } from 'components/dialog'; -import KebabAction from 'src/components/shared/KebabAction.vue'; + import { nextTick } from 'vue'; -import FormEmployeeVisa from 'components/03_customer-management/FormEmployeeVisa.vue'; -import PaginationPageSize from 'src/components/PaginationPageSize.vue'; -import { AddButton } from 'components/button'; import AdvanceSearch from 'src/components/shared/AdvanceSearch.vue'; import TabEmployee from './TabEmployee.vue'; @@ -97,48 +40,20 @@ const router = useRouter(); const flowStore = useFlowStore(); const navigatorStore = useNavigator(); const customerStore = useCustomerStore(); -const userBranchStore = useMyBranchStore(); const employeeStore = useEmployeeStore(); const customerFormStore = useCustomerForm(); const employeeFormStore = useEmployeeForm(); -const optionStore = useOptionStore(); -const ocrStore = useOcrStore(); -const mrz = ref>>(); - -const { - fetchListOfOptionBranch, - customerFormUndo, - customerConfirmUnsave, - deleteCustomerById, - validateTabField, - deleteCustomerBranchById, -} = customerFormStore; - -const { employeeFormUndo, employeeConfirmUnsave, deleteEmployeeById } = - employeeFormStore; - -const { - state: customerFormState, - currentFormData: customerFormData, - registerAbleBranchOption, - tabFieldRequired, -} = storeToRefs(customerFormStore); -const { - state: employeeFormState, - currentFromDataEmployee, - onCreateImageList, - statusEmployeeCreate, - refreshImageState, -} = storeToRefs(employeeFormStore); +const { state: customerFormState, currentFormData: customerFormData } = + storeToRefs(customerFormStore); +const { state: employeeFormState, statusEmployeeCreate } = + storeToRefs(employeeFormStore); const refTabCustomer = ref>(); const refTabEmployee = ref>(); // NOTE: Page Data const currentCustomer = ref(); -// const listCustomer = ref<(Customer & { branch: CustomerBranch[] })[]>([]); -// const listEmployee = ref([]); const hideStats = ref(false); const statsCustomerType = ref({ CORP: 0, @@ -158,27 +73,8 @@ const customerTypeSelected = ref<{ value: 'all', }); -// const customerNameInfo = computed(() => { -// if (customerFormData.value.customerBranch === undefined) return; - -// const name = -// locale.value === 'eng' -// ? `${customerFormData.value.customerBranch[0]?.firstNameEN} ${customerFormData.value.customerBranch[0]?.lastNameEN}` -// : `${customerFormData.value.customerBranch[0]?.firstName} ${customerFormData.value.customerBranch[0]?.lastName}`; -// return name || '-'; -// }); -// const currentBtnOpen = ref([]); const employeeStats = ref(0); const gridView = ref(false); -// const splitPercent = computed(() => ($q.screen.lt.md ? 0 : 15)); - -// const currentPageCustomer = ref(1); -// const maxPageCustomer = ref(1); -// const currentPageEmployee = ref(1); -// const maxPageEmployee = ref(1); -// const pageSize = ref(30); -// const dialogCustomerImageUpload = ref>(); -// const dialogEmployeeImageUpload = ref>(); // image const imageList = ref<{ selectedImage: string; list: string[] }>(); @@ -354,27 +250,6 @@ async function init() { watch(() => route.name, init); -// watch( -// [currentTab, currentStatus, inputSearch, searchDate], -// async ([tabName], [oldTabName]) => { -// if (tabName !== oldTabName) searchDate.value = []; -// if (tabName === 'employer') { -// currentPageCustomer.value = 1; -// currentBtnOpen.value = []; -// listCustomer.value = []; -// await fetchListCustomer(true); -// } -// if (tabName === 'employee') { -// currentPageEmployee.value = 1; -// listEmployee.value = []; -// await fetchListEmployee({ fetchStats: true }); -// } - -// customerFormState.value.currentCustomerId = undefined; -// flowStore.rotate(); -// }, -// ); - watch(locale, () => { customerTypeSelected.value = { label: `${customerTypeSelected.value.label}`, @@ -388,304 +263,6 @@ watch( ); onMounted(async () => await init()); -// const employeeHistoryDialog = ref(false); -// const employeeHistory = ref(); - -// async function fetchListCustomer(fetchStats = false, mobileFetch?: boolean) { -// const total = statsCustomerType.value.PERS + statsCustomerType.value.CORP; - -// const resultList = await customerStore.fetchList({ -// includeBranch: true, -// page: mobileFetch ? 1 : currentPageCustomer.value, -// pageSize: mobileFetch -// ? listCustomer.value.length + -// (total === listCustomer.value.length ? 1 : 0) -// : pageSize.value, -// status: -// currentStatus.value === 'All' -// ? undefined -// : currentStatus.value === 'ACTIVE' -// ? 'ACTIVE' -// : 'INACTIVE', -// query: inputSearch.value, -// startDate: searchDate.value[0], -// endDate: searchDate.value[1], -// customerType: ( -// { -// all: undefined, -// customerLegalEntity: CustomerType.Corporate, -// customerNaturalPerson: CustomerType.Person, -// } as const -// )[customerTypeSelected.value.value], -// }); - -// if (resultList) { -// maxPageCustomer.value = Math.ceil(resultList.total / pageSize.value); -// $q.screen.xs && !mobileFetch -// ? listCustomer.value.push(...resultList.result) -// : (listCustomer.value = resultList.result); -// } - -// if (fetchStats) { -// statsCustomerType.value = await customerStore -// .getStatsCustomer() -// .then((value) => (value ? value : { CORP: 0, PERS: 0 })); -// } -// } - -// async function fetchListEmployee(opt?: { -// fetchStats?: boolean; -// page?: number; -// pageSize?: number; -// customerId?: string; -// mobileFetch?: boolean; -// }) { -// const resultListEmployee = await employeeStore.fetchList({ -// customerId: opt?.customerId, -// page: opt -// ? opt.mobileFetch -// ? 1 -// : opt.page || currentPageEmployee.value -// : currentPageEmployee.value, -// pageSize: opt -// ? opt.mobileFetch -// ? listEmployee.value.length + -// (employeeStats.value === listEmployee.value.length ? 1 : 0) -// : opt.pageSize || pageSize.value -// : pageSize.value, -// status: -// currentStatus.value === 'All' -// ? undefined -// : currentStatus.value === 'ACTIVE' -// ? 'ACTIVE' -// : 'INACTIVE', -// query: inputSearch.value, -// passport: true, -// visa: true, -// startDate: searchDate.value[0], -// endDate: searchDate.value[1], -// }); -// if (resultListEmployee) { -// maxPageEmployee.value = Math.ceil( -// resultListEmployee.total / pageSize.value, -// ); -// $q.screen.xs && !(opt && opt.mobileFetch) -// ? listEmployee.value.push(...resultListEmployee.result) -// : (listEmployee.value = resultListEmployee.result); -// } - -// if (opt && opt.fetchStats) -// employeeStats.value = await employeeStore.getStatsEmployee(); -// } - -// async function toggleStatusEmployee( -// id: string, -// status: boolean, -// employeeName: string, -// ) { -// const res = await employeeStore.editById(id, { -// status: !status ? 'ACTIVE' : 'INACTIVE', -// firstNameEN: employeeName, -// }); -// if (res && employeeFormState.value.drawerModal) -// currentFromDataEmployee.value.status = res.status; - -// await fetchListEmployee({ mobileFetch: $q.screen.xs }); -// flowStore.rotate(); -// } - -// async function toggleStatusCustomer(id: string, status: boolean) { -// const res = await customerStore.editById(id, { -// status: !status ? 'ACTIVE' : 'INACTIVE', -// }); -// if (res && customerFormState.value.drawerModal) -// customerFormData.value.status = res.status; - -// await fetchListCustomer(false, $q.screen.xs); -// flowStore.rotate(); -// } -// async function openHistory(id: string) { -// const res = await employeeStore.getEditHistory(id); -// employeeHistory.value = res.reverse(); -// employeeHistoryDialog.value = true; -// } - -// async function editCustomerForm(id: string) { -// await customerFormStore.assignFormData(id); -// await fetchListOfOptionBranch(); -// await fetchImageList( -// id, -// customerFormData.value.selectedImage || '', -// 'customer', -// ); -// customerFormState.value.branchIndex = -1; -// customerFormState.value.dialogType = 'edit'; -// customerFormState.value.drawerModal = true; -// customerFormState.value.editCustomerId = id; -// } - -// async function editEmployeeFormPersonal(id: string) { -// await employeeFormStore.assignFormDataEmployee(id); -// await fetchImageList( -// id, -// currentFromDataEmployee.value.selectedImage || '', -// 'employee', -// ); - -// employeeFormState.value.isEmployeeEdit = true; -// employeeFormState.value.dialogType = 'edit'; -// employeeFormState.value.drawerModal = true; -// } - -// async function openSpecificCustomer(id: string) { -// await customerFormStore.assignFormData(id); -// await fetchImageList( -// id, -// customerFormData.value.selectedImage || '', -// 'customer', -// ); -// customerFormState.value.branchIndex = -1; -// customerFormState.value.drawerModal = true; -// customerFormState.value.editCustomerId = id; -// customerFormState.value.dialogType = 'info'; -// } - -// async function openSpecificEmployee(id: string) { -// await employeeFormStore.assignFormDataEmployee(id); -// await fetchImageList( -// id, -// currentFromDataEmployee.value.selectedImage || '', -// 'employee', -// ); -// employeeFormState.value.dialogType = 'info'; -// employeeFormState.value.drawerModal = true; -// } - -// TODO: When in employee form, if select address same as customer then auto fill - -// watch( -// () => employeeFormState.value.currentCustomerBranch, -// (e) => { -// if (!e) return; -// if (employeeFormState.value.formDataEmployeeSameAddr) { -// currentFromDataEmployee.value.address = e.address; -// currentFromDataEmployee.value.addressEN = e.addressEN; -// currentFromDataEmployee.value.provinceId = e.provinceId; -// currentFromDataEmployee.value.districtId = e.districtId; -// currentFromDataEmployee.value.subDistrictId = e.subDistrictId; -// } -// currentFromDataEmployee.value.customerBranchId = e.id; -// }, -// ); - -// watch( -// () => employeeFormState.value.formDataEmployeeSameAddr, -// (isSame) => { -// if (!employeeFormState.value.currentCustomerBranch) return; -// if (isSame) { -// currentFromDataEmployee.value.address = -// employeeFormState.value.currentCustomerBranch.address; -// currentFromDataEmployee.value.addressEN = -// employeeFormState.value.currentCustomerBranch.addressEN; -// currentFromDataEmployee.value.provinceId = -// employeeFormState.value.currentCustomerBranch.provinceId; -// currentFromDataEmployee.value.districtId = -// employeeFormState.value.currentCustomerBranch.districtId; -// currentFromDataEmployee.value.subDistrictId = -// employeeFormState.value.currentCustomerBranch.subDistrictId; -// } -// currentFromDataEmployee.value.customerBranchId = -// employeeFormState.value.currentCustomerBranch.id; -// }, -// ); - -// watch( -// () => employeeFormState.value.currentTab, -// () => { -// employeeFormState.value.isEmployeeEdit = false; -// }, -// ); - -// watch( -// () => currentFromDataEmployee.value.dateOfBirth, -// (v) => { -// const isEdit = -// employeeFormState.value.drawerModal && -// employeeFormState.value.isEmployeeEdit; -// let currentFormDate = v && toISOStringWithTimezone(new Date(v)); -// let currentDate: string = ''; - -// if (isEdit && employeeFormState.value.currentEmployee) { -// currentDate = toISOStringWithTimezone( -// new Date(employeeFormState.value.currentEmployee.dateOfBirth), -// ); -// } - -// if ( -// employeeFormState.value.dialogModal || -// (isEdit && currentFormDate !== currentDate) -// ) { -// const age = calculateAge( -// currentFromDataEmployee.value.dateOfBirth, -// 'year', -// ); -// if (currentFromDataEmployee.value.dateOfBirth && Number(age) < 15) { -// dialog({ -// color: 'warning', -// icon: 'mdi-alert', -// title: t('dialog.title.youngWorker15'), -// cancelText: t('general.edit'), -// persistent: true, -// message: t('dialog.message.youngWorker15'), - -// cancel: async () => { -// currentFromDataEmployee.value.dateOfBirth = null; -// return; -// }, -// }); -// } - -// if ( -// currentFromDataEmployee.value.dateOfBirth && -// Number(age) > 15 && -// Number(age) <= 18 -// ) { -// dialog({ -// color: 'warning', -// icon: 'mdi-alert', -// title: t('dialog.title.youngWorker18'), -// cancelText: t('general.cancel'), -// actionText: t('general.confirm'), -// persistent: true, -// message: t('dialog.message.youngWorker18'), -// action: () => {}, -// cancel: async () => { -// currentFromDataEmployee.value.dateOfBirth = null; -// return; -// }, -// }); -// } -// } -// }, -// ); - -// watch( -// () => customerFormData.value.image, -// () => { -// if (customerFormData.value.image !== null) -// customerFormState.value.isImageEdit = true; -// }, -// ); - -// watch( -// () => currentFromDataEmployee.value.image, -// () => { -// if (currentFromDataEmployee.value.image !== null) -// employeeFormState.value.isImageEdit = true; -// }, -// ); - -// const emptyCreateDialog = ref(false); + +