diff --git a/app-modules/payment/src/Listeners/MarkBookingRefunded.php b/app-modules/payment/src/Listeners/MarkBookingRefunded.php index e58ecf1..27a73b8 100644 --- a/app-modules/payment/src/Listeners/MarkBookingRefunded.php +++ b/app-modules/payment/src/Listeners/MarkBookingRefunded.php @@ -2,7 +2,6 @@ namespace Modules\Payment\Listeners; -use Illuminate\Contracts\Queue\ShouldQueue; use Modules\Booking\Enums\BookingStatus; use Modules\Payment\Events\RefundProcessed; @@ -11,8 +10,14 @@ 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 implements ShouldQueue +class MarkBookingRefunded { public function handle(RefundProcessed $event): void { @@ -22,10 +27,6 @@ class MarkBookingRefunded implements ShouldQueue // 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 bebab92..2942a37 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 queued listener ran', function () { +test('does not crash if the booking was soft-deleted before this 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]);