From adabb2c6900be32c6a805818beb46fdf5754280b Mon Sep 17 00:00:00 2001 From: Nyan Lin Paing <117423022+LinPaing21@users.noreply.github.com> Date: Thu, 3 Sep 2026 10:56:55 +0700 Subject: [PATCH] Revert "Make MarkBookingRefunded synchronous so refunds cancel instantly" This reverts commit 825320a1173876fc8d2f4c5fb32a4093d4d6b29b. --- .../payment/src/Listeners/MarkBookingRefunded.php | 13 ++++++------- .../tests/Feature/MarkBookingRefundedTest.php | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app-modules/payment/src/Listeners/MarkBookingRefunded.php b/app-modules/payment/src/Listeners/MarkBookingRefunded.php index 27a73b8..e58ecf1 100644 --- a/app-modules/payment/src/Listeners/MarkBookingRefunded.php +++ b/app-modules/payment/src/Listeners/MarkBookingRefunded.php @@ -2,6 +2,7 @@ namespace Modules\Payment\Listeners; +use Illuminate\Contracts\Queue\ShouldQueue; use Modules\Booking\Enums\BookingStatus; use Modules\Payment\Events\RefundProcessed; @@ -10,14 +11,8 @@ use Modules\Payment\Events\RefundProcessed; * completes (domain.md ยง5). Guarded the same way as MarkBookingPaid โ€” only * ever moves a still-confirmed booking, never clobbers one that moved on * for another reason. - * - * Deliberately synchronous, unlike MarkBookingPaid โ€” a refund is always - * initiated from a request that's already waiting on it (the Filament - * action or the API endpoint), and staff expect the booking's status to - * read Cancelled the instant that request completes, not once a queue - * worker gets to it. */ -class MarkBookingRefunded +class MarkBookingRefunded implements ShouldQueue { public function handle(RefundProcessed $event): void { @@ -27,6 +22,10 @@ class MarkBookingRefunded // pre-redesign rows where booking_id wasn't yet recorded. $booking = $event->refund->booking ?? $event->refund->payment->booking; + // Booking uses SoftDeletes โ€” normally unreachable here (a confirmed + // booking is never deletable, BookingPolicy::delete), but this + // listener is queued, so it's worth guarding against a booking that + // vanished between dispatch and execution regardless. if ($booking === null) { return; } diff --git a/app-modules/payment/tests/Feature/MarkBookingRefundedTest.php b/app-modules/payment/tests/Feature/MarkBookingRefundedTest.php index 2942a37..bebab92 100644 --- a/app-modules/payment/tests/Feature/MarkBookingRefundedTest.php +++ b/app-modules/payment/tests/Feature/MarkBookingRefundedTest.php @@ -29,7 +29,7 @@ test('does not touch a booking that already moved on for another reason', functi expect($booking->refresh()->status)->toBe(BookingStatus::Cancelled); }); -test('does not crash if the booking was soft-deleted before this listener ran', function () { +test('does not crash if the booking was soft-deleted before this queued listener ran', function () { $booking = Booking::factory()->create(['status' => BookingStatus::Confirmed]); $payment = Payment::factory()->completed()->create(['booking_id' => $booking->id, 'gateway' => PaymentMethod::KbzMiniApp]); $refund = Refund::factory()->create(['payment_id' => $payment->id, 'status' => RefundStatus::Completed]);