From 91a7230b9edf687f314d073133e0a897934a0333 Mon Sep 17 00:00:00 2001 From: Dillon Ngo Date: Sun, 19 Apr 2026 03:07:13 +0800 Subject: [PATCH] Prevention fix -> wallet double refund issue reported by Sin Yee on 20260416 --- ...UpdateRefundTransactionStatusProcessor.php | 15 ++++++++ ...d_process_status_to_transactions_table.php | 36 +++++++++++++++++++ ...ocess_status_to_transaction_logs_table.php | 36 +++++++++++++++++++ .../elements/PaymentHistoryComponent.vue | 2 +- 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 database/migrations/2026_04_19_012052_add_process_status_to_transactions_table.php create mode 100644 database/migrations/2026_04_19_015052_add_process_status_to_transaction_logs_table.php diff --git a/app/Classes/Modules/Transactions/Processors/UpdateRefundTransactionStatusProcessor.php b/app/Classes/Modules/Transactions/Processors/UpdateRefundTransactionStatusProcessor.php index f0aeb939..3a0b8d91 100644 --- a/app/Classes/Modules/Transactions/Processors/UpdateRefundTransactionStatusProcessor.php +++ b/app/Classes/Modules/Transactions/Processors/UpdateRefundTransactionStatusProcessor.php @@ -13,8 +13,11 @@ use App\Classes\Modules\Wallets\Processors\CreditWalletProcessor; use App\Classes\Modules\Bookings\Services\CalculatesBookingPayableAmount; use App\Classes\Modules\Bookings\Services\CalculatesBookingRefundAmount; use App\Classes\Modules\Transactions\Standards\Rules\CanUpdateRefundTransactionStatus; +use App\Classes\ValueObjects\Constants\KVPKey; use App\Classes\ValueObjects\Constants\RemarkRefundReason; use App\Classes\ValueObjects\Constants\TransactionType; +use App\Models\Transaction; +use ErrorException; use Illuminate\Support\Facades\Log; class UpdateRefundTransactionStatusProcessor @@ -107,6 +110,14 @@ class UpdateRefundTransactionStatusProcessor $paidAmount = $paymentTransaction->original_amount - $refundAmount; + $claimed = Transaction::where('id', $refundTransaction->id) + ->where('process_status', null) + ->update(['process_status' => ApprovalStatus::PENDING_VERIFICATION]); + + if (!$claimed) { + throw new ErrorException("This refund transaction has already been processed"); + } + if ($refundTransaction->status == ApprovalStatus::APPROVED) { $this->creditWalletProcessor->execute($booking->company, $refundTransaction->type, $refundTransaction->amount, $reference, $refundTransaction); @@ -140,5 +151,9 @@ class UpdateRefundTransactionStatusProcessor 'bookingOriginalStatus' => $booking->status ]); } + + Transaction::where('id', $refundTransaction->id) + ->where('process_status', ApprovalStatus::PENDING_VERIFICATION) + ->update(['process_status' => ApprovalStatus::APPROVED]); } } diff --git a/database/migrations/2026_04_19_012052_add_process_status_to_transactions_table.php b/database/migrations/2026_04_19_012052_add_process_status_to_transactions_table.php new file mode 100644 index 00000000..e4ba8a35 --- /dev/null +++ b/database/migrations/2026_04_19_012052_add_process_status_to_transactions_table.php @@ -0,0 +1,36 @@ +unsignedTinyInteger('process_status') + ->nullable() + ->default(null) + ->after('status') + ->index(); + }); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('transactions', function (Blueprint $table) { + Schema::table('transactions', function (Blueprint $table) { + $table->dropColumn('process_status'); + }); + }); + } +}; diff --git a/database/migrations/2026_04_19_015052_add_process_status_to_transaction_logs_table.php b/database/migrations/2026_04_19_015052_add_process_status_to_transaction_logs_table.php new file mode 100644 index 00000000..cfc0df68 --- /dev/null +++ b/database/migrations/2026_04_19_015052_add_process_status_to_transaction_logs_table.php @@ -0,0 +1,36 @@ +unsignedTinyInteger('process_status') + ->nullable() + ->default(null) + ->after('status') + ->index(); + }); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('transaction_logs', function (Blueprint $table) { + Schema::table('transaction_logs', function (Blueprint $table) { + $table->dropColumn('process_status'); + }); + }); + } +}; diff --git a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue index df5fb8e3..0f690114 100644 --- a/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue +++ b/resources/assets/vue/components/bookings/elements/PaymentHistoryComponent.vue @@ -475,7 +475,7 @@ - +