From 362980d0082b62afdc2a4f67e152a1e1d0d932f7 Mon Sep 17 00:00:00 2001 From: Kydoimos Date: Thu, 17 Sep 2026 15:46:11 -0300 Subject: [PATCH] Apply available credit to any at-booking charge, not just scheduled A payer's account credit should offset any charge raised at booking, so drop the scheduled-only guard. Covers the one-time pay-now flow too. Co-authored-by: anthropic/claude-opus-4-8 --- src/Booking/LessonBooker.php | 4 ++-- tests/Unit/Booking/AdminBookingTest.php | 6 ++++++ tests/Unit/Booking/BookingEndpointTest.php | 6 +++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Booking/LessonBooker.php b/src/Booking/LessonBooker.php index 585e6b3..649119e 100644 --- a/src/Booking/LessonBooker.php +++ b/src/Booking/LessonBooker.php @@ -196,8 +196,8 @@ class LessonBooker { payerId: $payerId ); - // Apply any available credit to a scheduled charge raised at booking. - if ( $offering->isScheduledBilling() && null !== $payment && null !== $payment->id && Payment::STATUS_PENDING === $payment->status ) { + // Apply any available credit to a charge raised at booking. + if ( null !== $payment && null !== $payment->id && Payment::STATUS_PENDING === $payment->status ) { $this->payments->applyCredits( $payerId, [ $payment ] ); $payment = $this->payments->findPayment( (int) $payment->id ) ?? $payment; } diff --git a/tests/Unit/Booking/AdminBookingTest.php b/tests/Unit/Booking/AdminBookingTest.php index 0a4a201..2bfb307 100644 --- a/tests/Unit/Booking/AdminBookingTest.php +++ b/tests/Unit/Booking/AdminBookingTest.php @@ -48,6 +48,12 @@ class AdminBookingTest extends TestCase $this->bookings = Mockery::mock(BookingRepository::class); $this->offerings = Mockery::mock(OfferingRepository::class); $this->payments = Mockery::mock(PaymentService::class); + // A charge raised at booking has the payer's credit applied before it + // settles. The default holds no balance and re-reads the same payment. + $this->payments->shouldReceive('applyCredits')->andReturn([])->byDefault(); + $this->payments->shouldReceive('findPayment')->andReturnUsing( + static fn (int $id): ?Payment => null + )->byDefault(); $this->guardians = Mockery::mock(GuardianService::class); $this->guardians->shouldReceive('payerFor')->andReturnUsing(static fn (int $id): int => $id)->byDefault(); diff --git a/tests/Unit/Booking/BookingEndpointTest.php b/tests/Unit/Booking/BookingEndpointTest.php index 1aeedb9..9001257 100644 --- a/tests/Unit/Booking/BookingEndpointTest.php +++ b/tests/Unit/Booking/BookingEndpointTest.php @@ -57,9 +57,9 @@ class BookingEndpointTest extends TestCase // Crediting a cancelled paid lesson is exercised in dedicated tests; other // cancellation paths simply allow the call. $this->payments->shouldReceive('creditForCancelledLesson')->andReturn(null)->byDefault(); - // A charge-at-booking scheduled lesson (an add-on to an already-billed month) - // applies the payer's credit before it settles. The default holds no balance - // and re-reads the same payment; the same-month-rebook test overrides both. + // A charge raised at booking applies the payer's credit before it settles. + // The default holds no balance and re-reads the same payment; the + // same-month-rebook test overrides both. $this->payments->shouldReceive('applyCredits')->andReturn([])->byDefault(); $this->payments->shouldReceive('findPayment')->andReturnUsing( static fn (int $id): ?Payment => null