From 61d7ad22e7c40c024307ff5d763b73d9c7204749 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Thu, 14 Nov 2024 14:03:29 +0800 Subject: [PATCH] Laravel Vapor - Enhancement to prevent customer from underpay when a transaction also invoice storage invoices --- .../VerifyTransactionsLogic.php | 7 -- .../CustomerPaymentBillingInnerComponent.vue | 51 ++++++++++- .../forms/ReloadConfirmationFormComponent.vue | 48 ++++++++++ ...merPaymentsBillingWithStorageComponent.vue | 57 ++++++++++-- .../forms/GroupPaymentFormComponent.vue | 90 ++++++++++++------- 5 files changed, 208 insertions(+), 45 deletions(-) create mode 100644 resources/assets/vue/components/general/forms/ReloadConfirmationFormComponent.vue diff --git a/app/Classes/Modules/Transactions/ControllersLogic/VerifyTransactionsLogic.php b/app/Classes/Modules/Transactions/ControllersLogic/VerifyTransactionsLogic.php index 317af93b..f38a3c2d 100644 --- a/app/Classes/Modules/Transactions/ControllersLogic/VerifyTransactionsLogic.php +++ b/app/Classes/Modules/Transactions/ControllersLogic/VerifyTransactionsLogic.php @@ -4,16 +4,9 @@ namespace App\Classes\Modules\Transactions\ControllersLogic; use App\Classes\General\Abstracts\AbstractControllerLogic; -use App\Classes\Modules\Transactions\Services\FetchesTransaction; -use App\Classes\Modules\Transactions\Services\GeneratesTransactionBillNumber; -use App\Classes\Modules\Companies\Services\FetchesCompanyModule; -use App\Classes\Modules\Transactions\Processors\CreatePaymentTransactionProcessor; -use App\Classes\Modules\Groups\Services\CreatesGroup; use App\Models\Transaction; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use App\Classes\Modules\Wallets\Processors\CreateWalletTopUpTransactionProcessor; -use App\Classes\Modules\Transactions\Processors\ReleaseGoodsToCustomerProcessor; use App\Classes\Modules\Transactions\Processors\CheckStorageInvoiceTransactionProcessor; use App\Http\Resources\TransactionVerifyResource; diff --git a/resources/assets/vue/components/companies/elements/CustomerPaymentBillingInnerComponent.vue b/resources/assets/vue/components/companies/elements/CustomerPaymentBillingInnerComponent.vue index 048c63b1..e41aa9fa 100644 --- a/resources/assets/vue/components/companies/elements/CustomerPaymentBillingInnerComponent.vue +++ b/resources/assets/vue/components/companies/elements/CustomerPaymentBillingInnerComponent.vue @@ -63,12 +63,23 @@
-
Make Payment
+
Make Payment
Generate Summary Invoice
- +
+ +
+ + +
@@ -108,6 +119,9 @@ selectedPaidInvoice: [], selectedUnpaidInvoice: [], selectAllInvoice: false, + showPaymentProceedModal: false, + showPaymentOutdatedModal: false, + selectedShippingInvoicesOnlyIds: [], } }, computed: { @@ -119,7 +133,8 @@ var total = Object.keys(new_object).reduce(function(total, key) { return total + new_object[key].amount; }, 0).toFixed(2); - return Math.round(total * 100) / 100; + total = (Math.round(total * 100) / 100).toFixed(2); + return total; }, selectedIds () { return this.selectedInvoice.map(s=>s.id); @@ -183,6 +198,36 @@ ...(shippingInvoice ? [shippingInvoice] : []) ]; return mergedArray; + }, + handleMakePaymentClick(event) { + this.showPaymentProceedModal = false; + this.showPaymentOutdatedModal = false; + this.selectedShippingInvoicesOnlyIds = this.selectedInvoice.filter(invoice => invoice.type === 1).map(s=>s.id); + this.submit(this.route('api.transaction.verify.transactions', JSON.stringify(this.selectedShippingInvoicesOnlyIds)), 'get', this.section, false, false); + }, + successHandler(response){ + const totalAmount = response.payload.data.reduce((total, item) => { + const topLevelAmount = item.amount || 0; + const storagesAmount = item.storages.reduce((sum, storage) => { + const storageInvoiceAmount = storage.storageInvoice?.amount || 0; + return sum + storageInvoiceAmount; + }, 0); + + return total + topLevelAmount + storagesAmount; + + }, 0).toFixed(2); + + const epsilon = 0.0001; + if(Math.abs(this.sumAmount - totalAmount) < epsilon){ + this.showPaymentProceedModal = true; + } + else{ + this.showPaymentOutdatedModal = true; + } + }, + paymentOutdated(){ + this.showPaymentProceedModal = false; + this.showPaymentOutdatedModal = true; } } } diff --git a/resources/assets/vue/components/general/forms/ReloadConfirmationFormComponent.vue b/resources/assets/vue/components/general/forms/ReloadConfirmationFormComponent.vue new file mode 100644 index 00000000..dd9e7521 --- /dev/null +++ b/resources/assets/vue/components/general/forms/ReloadConfirmationFormComponent.vue @@ -0,0 +1,48 @@ + + diff --git a/resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingWithStorageComponent.vue b/resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingWithStorageComponent.vue index 178f2597..86563d3a 100644 --- a/resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingWithStorageComponent.vue +++ b/resources/assets/vue/components/paymentsBilling/elements/CustomerPaymentsBillingWithStorageComponent.vue @@ -279,9 +279,20 @@
-
Make Payment
+
Make Payment
- +
+ +
+ + +
@@ -321,6 +332,9 @@ transaction_details: [], }, expanded: true, + showPaymentProceedModal: false, + showPaymentOutdatedModal: false, + selectedShippingInvoicesOnlyIds: [], } }, watch: { @@ -365,9 +379,6 @@ let questions = item.remarks; return questions.slice().reverse()[0]; }, - successHandler(response){ - this.item = response.payload.data; - }, groupTransactionsExist(items, groups) { return groups.some(group => group.payment_transaction && @@ -376,6 +387,42 @@ items.some(item => item.id === transaction.transaction_id) ) ); + }, + handleMakePaymentClick(event) { + this.showPaymentProceedModal = false; + this.showPaymentOutdatedModal = false; + this.selectedShippingInvoicesOnlyIds = this.items.filter(invoice => invoice.type === 1).map(s=>s.id); + this.submit(this.route('api.transaction.verify.transactions', JSON.stringify(this.selectedShippingInvoicesOnlyIds)), 'get', 'verifyPaymentForOrderProfileV2Section', false, false); + }, + successHandler(response, section){ + if(section === "verifyPaymentForOrderProfileV2Section") + { + const totalAmount = response.payload.data.reduce((total, item) => { + const topLevelAmount = item.amount || 0; + const storagesAmount = item.storages.reduce((sum, storage) => { + const storageInvoiceAmount = storage.storageInvoice?.amount || 0; + return sum + storageInvoiceAmount; + }, 0); + + return total + topLevelAmount + storagesAmount; + + }, 0); + + const epsilon = 0.0001; + if(Math.abs(this.totalOutstanding - totalAmount) < epsilon){ + this.showPaymentProceedModal = true; + } + else{ + this.showPaymentOutdatedModal = true; + } + } + else{ + this.item = response.payload.data; + } + }, + paymentOutdated(){ + this.showPaymentProceedModal = false; + this.showPaymentOutdatedModal = true; } } } diff --git a/resources/assets/vue/components/paymentsBilling/forms/GroupPaymentFormComponent.vue b/resources/assets/vue/components/paymentsBilling/forms/GroupPaymentFormComponent.vue index be721bdd..d1a6cea8 100644 --- a/resources/assets/vue/components/paymentsBilling/forms/GroupPaymentFormComponent.vue +++ b/resources/assets/vue/components/paymentsBilling/forms/GroupPaymentFormComponent.vue @@ -138,7 +138,7 @@
Cancel
-
Proceed
+
Proceed
@@ -174,11 +174,15 @@ type: Boolean, default: false }, + selectedShippingInvoicesOnlyIds: { + type: Array, + required: true, + }, }, data(){ return { parameters : { - amount: this.sumAmount, + amount: this.sumAmount.toFixed(2), // transaction_ids: this.data.id, payment_method: '', }, @@ -214,39 +218,65 @@ } this.error = ''; }, - successHandler(response){ - // todo-new: when using the page reload, the section reload will auto refresh with new data and refresh again - // however if dont use the page reload, then the section will refresh with old data - // if (response.payload) { - // if (response.payload.data.payment_method === 5) { - // window.location.href = this.route('billplz.bill', response.payload.data.reference) + '?auto_submit=true'; - // } else { - // location.reload(); - // } - // } + handleProceedClick(event) { + this.showPaymentProceedModal = false; + this.showPaymentOutdatedModal = false; + this.submit(this.route('api.transaction.verify.transactions', JSON.stringify(this.selectedShippingInvoicesOnlyIds)), 'get', 'verifyPendingPaymentInvoice', false, false); + }, + successHandler(response, section){ + if(section === 'verifyPendingPaymentInvoice'){ + const totalAmount = response.payload.data.reduce((total, item) => { + const topLevelAmount = item.amount || 0; + const storagesAmount = item.storages.reduce((sum, storage) => { + const storageInvoiceAmount = storage.storageInvoice?.amount || 0; + return sum + storageInvoiceAmount; + }, 0); - let isClearToUpdateList = true; - if(response.payload.data && response.payload.data.message){ - this.error = response.payload.data.message; - isClearToUpdateList = false; + return total + topLevelAmount + storagesAmount; + + }, 0).toFixed(2); + if(this.sumAmount == totalAmount){ + this.submitForm(); + } + else{ + this.$emit('isPaymentOutdated', true); + } } - else if (response.payload.length == 0) { - setTimeout(function() { - location.reload(); - }, 2000); - } - else if (response.payload) { - if (response.payload.data.payment_method === 5) { - window.location.href = this.route('billplz.bill', response.payload.data.reference) + '?auto_submit=true'; - } else { - location.reload(); + else{ + // todo-new: when using the page reload, the section reload will auto refresh with new data and refresh again + // however if dont use the page reload, then the section will refresh with old data + // if (response.payload) { + // if (response.payload.data.payment_method === 5) { + // window.location.href = this.route('billplz.bill', response.payload.data.reference) + '?auto_submit=true'; + // } else { + // location.reload(); + // } + // } + + let isClearToUpdateList = true; + if(response.payload.data && response.payload.data.message){ + this.error = response.payload.data.message; + isClearToUpdateList = false; + } + else if (response.payload.length == 0) { + setTimeout(function() { + location.reload(); + }, 2000); + } + else if (response.payload) { + if (response.payload.data.payment_method === 5) { + window.location.href = this.route('billplz.bill', response.payload.data.reference) + '?auto_submit=true'; + } else { + location.reload(); + } + } + + if(isClearToUpdateList){ + this.updateList(); } } - if(isClearToUpdateList){ - this.updateList(); - } - } + }, }, mixins: [formHandler] }