Laravel Vapor - Enhancement to prevent customer from underpay when a payment transaction include storage invoice(s)

This commit is contained in:
Dillon Ngo
2024-11-15 18:34:08 +08:00
parent 141f1ed9d5
commit 54e6041fe5
7 changed files with 156 additions and 31 deletions
@@ -208,10 +208,10 @@
successHandler(response){
const totalAmount = response.payload.data.reduce((total, item) => {
const topLevelAmount = item.amount || 0;
const storagesAmount = item.storages.reduce((sum, storage) => {
const storagesAmount = item.storages ? item.storages.reduce((sum, storage) => {
const storageInvoiceAmount = storage.storageInvoice?.amount || 0;
return sum + storageInvoiceAmount;
}, 0);
}, 0) : 0;
return total + topLevelAmount + storagesAmount;
@@ -191,9 +191,20 @@
</div>
<div class="row m-t-20" v-if="item.outstanding - item.floating > 0.009 && !paymentPending">
<div class="col">
<div class="btn btn-sm all-caps b-rad-none btn-success btn-block requestModal" data-type="makePayment">Make Payment</div>
<div class="btn btn-sm all-caps b-rad-none btn-success btn-block requestModal" @click="handleMakePaymentClick" data-type="makePayment">Make Payment</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="makePayment">
<payment-form-component :data="item" :section="section"></payment-form-component>
<div class="d-flex justify-content-center align-items-center" v-if="!showPaymentProceedModal && !showPaymentOutdatedModal">
<i class="fa fa-spinner fa-spin"></i>
</div>
<payment-form-component :data="item" :section="section" v-on:isPaymentOutdated="paymentOutdated($event)" v-if="showPaymentProceedModal"></payment-form-component>
<reload-confirmation-form-component
contentText="Some information has been updated, click 'Yes' to reload page"
buttonText="Yes"
class="text-center"
:section="section"
v-if="showPaymentOutdatedModal"
>
</reload-confirmation-form-component>
</modal-component>
</div>
</div>
@@ -236,6 +247,8 @@
transaction_details: [],
},
expanded: true,
showPaymentProceedModal: false,
showPaymentOutdatedModal: false,
}
},
computed: {
@@ -265,9 +278,43 @@
this.parameters.packing_list_id = this.data.id;
},
methods: {
successHandler(response){
this.item = response.payload.data;
// this.$forceUpdate();
handleMakePaymentClick(event) {
let selectedShippingInvoicesOnlyIds = [];
this.showPaymentProceedModal = false;
this.showPaymentOutdatedModal = false;
selectedShippingInvoicesOnlyIds.push(this.item.id);
this.submit(this.route('api.transaction.verify.transactions', JSON.stringify(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 ? item.storages.reduce((sum, storage) => {
const storageInvoiceAmount = storage.storageInvoice?.amount || 0;
return sum + storageInvoiceAmount;
}, 0) : 0;
return total + topLevelAmount + storagesAmount;
}, 0);
const epsilon = 0.0001;
if(Math.abs(this.item.outstanding - totalAmount) < epsilon){
this.showPaymentProceedModal = true;
}
else{
this.showPaymentOutdatedModal = true;
}
}
else{
this.item = response.payload.data;
// this.$forceUpdate();
}
},
paymentOutdated(){
this.showPaymentProceedModal = false;
this.showPaymentOutdatedModal = true;
}
},
mixins: [componentHandler]
@@ -399,10 +399,10 @@
{
const totalAmount = response.payload.data.reduce((total, item) => {
const topLevelAmount = item.amount || 0;
const storagesAmount = item.storages.reduce((sum, storage) => {
const storagesAmount = item.storages ? item.storages.reduce((sum, storage) => {
const storageInvoiceAmount = storage.storageInvoice?.amount || 0;
return sum + storageInvoiceAmount;
}, 0);
}, 0) : 0;
return total + topLevelAmount + storagesAmount;
@@ -309,10 +309,10 @@
{
const totalAmount = response.payload.data.reduce((total, item) => {
const topLevelAmount = item.amount || 0;
const storagesAmount = item.storages.reduce((sum, storage) => {
const storagesAmount = item.storages ? item.storages.reduce((sum, storage) => {
const storageInvoiceAmount = storage.storageInvoice?.amount || 0;
return sum + storageInvoiceAmount;
}, 0);
}, 0) : 0;
return total + topLevelAmount + storagesAmount;
@@ -263,13 +263,24 @@
</div>
<div class="row m-t-20" v-if="item.shipping_transaction.outstanding > 0">
<div class="col">
<div class="btn btn-sm all-caps b-rad-none btn-success btn-block requestModal" data-type="makePayment">Make Payment</div>
<div class="btn btn-sm all-caps b-rad-none btn-success btn-block requestModal" @click="handleMakePaymentClick" data-type="makePayment">Make Payment</div>
</div>
</div>
</div>
</div>
<modal-component class="animate__animated animate__fast animate__fadeIn" styleType="fill-in" type="makePayment">
<payment-form-component :data="item.shipping_transaction" :section="section"></payment-form-component>
<div class="d-flex justify-content-center align-items-center" v-if="!showPaymentProceedModal && !showPaymentOutdatedModal">
<i class="fa fa-spinner fa-spin"></i>
</div>
<payment-form-component :data="item.shipping_transaction" :section="section" v-on:isPaymentOutdated="paymentOutdated($event)" v-if="showPaymentProceedModal"></payment-form-component>
<reload-confirmation-form-component
contentText="Some information has been updated, click 'Yes' to reload page"
buttonText="Yes"
class="text-center"
:section="section"
v-if="showPaymentOutdatedModal"
>
</reload-confirmation-form-component>
</modal-component>
</div>
</div>
@@ -298,6 +309,8 @@
transaction_details: [],
},
expanded: false,
showPaymentProceedModal: false,
showPaymentOutdatedModal: false,
}
},
computed: {
@@ -315,9 +328,43 @@
generateInvoice() {
this.submit(this.route('api.transaction.invoice.create'), 'post', this.section, true, true);
},
successHandler(response){
this.item = response.payload.data;
this.updateList();
handleMakePaymentClick(event) {
let selectedShippingInvoicesOnlyIds = [];
this.showPaymentProceedModal = false;
this.showPaymentOutdatedModal = false;
selectedShippingInvoicesOnlyIds.push(this.item.shipping_transaction.id);
this.submit(this.route('api.transaction.verify.transactions', JSON.stringify(selectedShippingInvoicesOnlyIds)), 'get', 'verifyPaymentForPendingPaymentSection', false, false);
},
successHandler(response, section){
if(section === "verifyPaymentForPendingPaymentSection")
{
const totalAmount = response.payload.data.reduce((total, item) => {
const topLevelAmount = item.amount || 0;
const storagesAmount = item.storages ? item.storages.reduce((sum, storage) => {
const storageInvoiceAmount = storage.storageInvoice?.amount || 0;
return sum + storageInvoiceAmount;
}, 0) : 0;
return total + topLevelAmount + storagesAmount;
}, 0);
const epsilon = 0.0001;
if(Math.abs(this.item.shipping_transaction.outstanding - totalAmount) < epsilon){
this.showPaymentProceedModal = true;
}
else{
this.showPaymentOutdatedModal = true;
}
}
else{
this.item = response.payload.data;
this.updateList();
}
},
paymentOutdated(){
this.showPaymentProceedModal = false;
this.showPaymentOutdatedModal = true;
}
},
mixins: [componentHandler]
@@ -227,15 +227,17 @@
if(section === 'verifyPendingPaymentInvoice'){
const totalAmount = response.payload.data.reduce((total, item) => {
const topLevelAmount = item.amount || 0;
const storagesAmount = item.storages.reduce((sum, storage) => {
const storagesAmount = item.storages ? item.storages.reduce((sum, storage) => {
const storageInvoiceAmount = storage.storageInvoice?.amount || 0;
return sum + storageInvoiceAmount;
}, 0);
}, 0) : 0;
return total + topLevelAmount + storagesAmount;
}, 0).toFixed(2);
if(this.sumAmount == totalAmount){
const epsilon = 0.0001;
if(Math.abs(this.sumAmount - totalAmount) < epsilon){
this.submitForm();
}
else{
@@ -97,7 +97,7 @@
<div class="btn btn-sm all-caps b-rad-none btn-default bg-master-lighter btn-block" @click="expandPayment = false" data-dismiss="modal">Cancel</div>
</div>
<div class="col-8 p-l-0">
<div class="btn btn-sm all-caps b-rad-none btn-default bg-success btn-block text-white" @click="submitForm()" :class="[{'hide': paymentMethod.name === ''}]">Proceed</div>
<div class="btn btn-sm all-caps b-rad-none btn-default bg-success btn-block text-white" @click="handleProceedClick" :class="[{'hide': paymentMethod.name === ''}]">Proceed</div>
</div>
</div>
</div>
@@ -146,21 +146,50 @@
}
this.error = '';
},
successHandler(response){
if (response.payload) {
if (response.payload.data.payment_method === 5) {
window.location.href = this.route('billplz.bill', response.payload.data.payment_reference) + '?auto_submit=true';
handleProceedClick(event) {
let selectedShippingInvoicesOnlyIds = [];
this.showPaymentProceedModal = false;
this.showPaymentOutdatedModal = false;
selectedShippingInvoicesOnlyIds.push(this.data.id);
this.submit(this.route('api.transaction.verify.transactions', JSON.stringify(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 ? item.storages.reduce((sum, storage) => {
const storageInvoiceAmount = storage.storageInvoice?.amount || 0;
return sum + storageInvoiceAmount;
}, 0) : 0;
return total + topLevelAmount + storagesAmount;
}, 0).toFixed(2);
const epsilon = 0.0001;
if(Math.abs(this.parameters.amount - totalAmount) < epsilon){
this.submitForm();
}
else{
this.$emit('isPaymentOutdated', true);
}
}
if(response.payload.data && response.payload.data.message){
this.error = response.payload.data.message;
}
else{
this.closeModal();
this.updateList();
if (response.payload) {
if (response.payload.data.payment_method === 5) {
window.location.href = this.route('billplz.bill', response.payload.data.payment_reference) + '?auto_submit=true';
}
}
if(response.payload.data && response.payload.data.message){
this.error = response.payload.data.message;
}
else{
this.closeModal();
this.updateList();
}
}
}
},
},
mixins: [formHandler]
}