From 036f5e10a0205890bdefbbd67fd8f10b0d8bfaa4 Mon Sep 17 00:00:00 2001 From: puriphatt Date: Fri, 4 Oct 2024 15:16:28 +0700 Subject: [PATCH] refactor: bind quotationFormInfo & cal installment --- src/pages/05_quotation/QuotationForm.vue | 99 +++++++++------ src/pages/05_quotation/QuotationFormInfo.vue | 125 ++++++++++++++----- 2 files changed, 153 insertions(+), 71 deletions(-) diff --git a/src/pages/05_quotation/QuotationForm.vue b/src/pages/05_quotation/QuotationForm.vue index c8e4bc52..29868d02 100644 --- a/src/pages/05_quotation/QuotationForm.vue +++ b/src/pages/05_quotation/QuotationForm.vue @@ -73,16 +73,21 @@ const preSelectedWorker = ref([]); const selectedWorker = ref([]); const workerList = ref([]); -const documentReceivePoint = ref(''); -const paySplitCount = ref(1); +const agentPrice = ref(false); +const summaryPrice = ref<{ + totalPrice: number; + totalDiscount: number; + vat: number; + finalPrice: number; +}>({ + totalPrice: 0, + totalDiscount: 0, + vat: 0, + finalPrice: 0, +}); + const quotationNo = ref(''); -const workName = ref(''); -const contactor = ref(''); -const telephone = ref(''); -const dueDate = ref(''); -const payType = ref(''); const payBank = ref(''); -const actor = ref(''); const pageState = reactive({ hideStat: false, @@ -153,7 +158,6 @@ async function triggerSelectEmployeeDialog() { function triggerProductServiceDialog() { pageState.productServiceModal = true; - // TODO: form and state controll } function toggleDeleteProduct(index: number) { @@ -206,29 +210,7 @@ function changeMode(mode: string) { } onMounted(async () => { - const ret = await productServiceStore.fetchListProductService({ - page: 1, - pageSize: 9999, - }); - if (ret) productGroup.value = ret.result; - - const urlParams = new URLSearchParams(window.location.search); - const queryDate = urlParams.get('date'); - date.value = queryDate && new Date(Number(queryDate)); - branchId.value = urlParams.get('branchId') || ''; - quotationFormData.value.customerBranchId = - urlParams.get('customerBranchId') || ''; - - const resultOption = await fetch('/option/option.json'); - const rawOption = await resultOption.json(); - if (locale.value === 'eng') optionStore.globalOption = rawOption.eng; - if (locale.value === 'tha') optionStore.globalOption = rawOption.tha; - - const retEmp = await customerStore.fetchBranchEmployee( - quotationFormData.value.customerBranchId, - ); - if (retEmp) workerList.value = retEmp.data.result; - + // get language const getCurLang = localStorage.getItem('currentLanguage'); if (getCurLang === 'English') { locale.value = 'eng'; @@ -239,6 +221,7 @@ onMounted(async () => { setLocale('th'); } + // get theme const getCurTheme = localStorage.getItem('currentTheme'); if ( getCurTheme === 'light' || @@ -249,6 +232,35 @@ onMounted(async () => { } else { changeMode('light'); } + + // get query string + const urlParams = new URLSearchParams(window.location.search); + branchId.value = urlParams.get('branchId') || ''; + + const price = urlParams.get('agentPrice'); + agentPrice.value = price === 'true' ? true : false; + + date.value = Date.now(); + + quotationFormData.value.customerBranchId = + urlParams.get('customerBranchId') || ''; + + // fetch option + const resultOption = await fetch('/option/option.json'); + const rawOption = await resultOption.json(); + if (locale.value === 'eng') optionStore.globalOption = rawOption.eng; + if (locale.value === 'tha') optionStore.globalOption = rawOption.tha; + + const ret = await productServiceStore.fetchListProductService({ + page: 1, + pageSize: 9999, + }); + if (ret) productGroup.value = ret.result; + + const retEmp = await customerStore.fetchBranchEmployee( + quotationFormData.value.customerBranchId, + ); + if (retEmp) workerList.value = retEmp.data.result; }); @@ -388,8 +400,10 @@ onMounted(async () => {
@@ -450,17 +464,22 @@ onMounted(async () => { }" > diff --git a/src/pages/05_quotation/QuotationFormInfo.vue b/src/pages/05_quotation/QuotationFormInfo.vue index a435fff5..11ac889d 100644 --- a/src/pages/05_quotation/QuotationFormInfo.vue +++ b/src/pages/05_quotation/QuotationFormInfo.vue @@ -5,6 +5,8 @@ import { selectFilterOptionRefMod } from 'src/stores/utils'; import { onMounted, ref, watch } from 'vue'; import { useI18n } from 'vue-i18n'; +import { formatNumberDecimal } from 'stores/utils'; + import AppBox from 'components/app/AppBox.vue'; import DatePicker from 'src/components/shared/DatePicker.vue'; import SelectInput from 'src/components/shared/SelectInput.vue'; @@ -24,6 +26,10 @@ defineProps<{ const { t } = useI18n(); +const urgent = defineModel('urgent', { + required: true, + default: false, +}); const quotationNo = defineModel('quotationNo', { required: true }); const actor = defineModel('actor', { required: true }); const workName = defineModel('workName', { required: true }); @@ -32,35 +38,50 @@ const telephone = defineModel('telephone', { required: true }); const documentReceivePoint = defineModel('documentReceivePoint', { required: true, }); -const dueDate = defineModel('dueDate', { required: true }); -const payType = defineModel('payType', { required: true }); -const paySplitCount = defineModel('paySplitCount', { - required: true, +const dueDate = defineModel('dueDate', { required: true }); +const payType = defineModel<'Full' | 'Split' | 'BillFull' | 'BillSplit'>( + 'payType', + { required: true }, +); +const paySplitCount = defineModel('paySplitCount', { default: 1, }); const payBank = defineModel('payBank', { required: true }); +const paySplit = defineModel< + { no: number; date: string | Date | null; amount: number }[] +>('paySplit', { required: true }); +const summaryPrice = defineModel<{ + totalPrice: number; + totalDiscount: number; + vat: number; + finalPrice: number; +}>('summaryPrice', { + required: true, + default: { + totalPrice: 0, + totalDiscount: 0, + vat: 0, + finalPrice: 0, + }, +}); const optionStore = useOptionStore(); -// fullAmountCash -// installmentsCash -// fullAmountBill -// installmentsBill const payTypeOpion = ref([ { - value: 'fullAmountCash', + value: 'Full', label: t('quotation.type.fullAmountCash'), }, { - value: 'installmentsCash', + value: 'Split', label: t('quotation.type.installmentsCash'), }, { - value: 'fullAmountBill', + value: 'BillFull', label: t('quotation.type.fullAmountBill'), }, { - value: 'installmentsBill', + value: 'BillSplit', label: t('quotation.type.installmentsBill'), }, ]); @@ -91,6 +112,50 @@ watch( ); }, ); + +watch( + () => payType.value, + (v) => { + if (v === 'Split' || v === 'BillSplit') { + paySplitCount.value = 1; + } else { + paySplitCount.value = 0; + } + }, +); + +watch( + () => paySplitCount.value, + (newCount, oldCount) => { + if (newCount !== null && oldCount !== null) { + const totalAmount = summaryPrice.value.finalPrice; + + if (newCount > oldCount) { + const installmentAmount = totalAmount / newCount; + + paySplit.value.forEach((payment, index) => { + payment.amount = installmentAmount; + }); + + for (let i = oldCount; i < newCount; i++) { + paySplit.value.push({ + no: i + 1, + date: null, + amount: installmentAmount, + }); + } + } else if (newCount < oldCount) { + paySplit.value.splice(newCount, oldCount - newCount); + + const installmentAmount = totalAmount / newCount; + paySplit.value.forEach((payment) => { + payment.amount = installmentAmount; + }); + } + } + }, + { deep: true }, +);