Apply account credit on same-month rebook; show total credit on student page #202

Merged
thatguygriff merged 6 commits from feature/student-credit-display-and-rebook-fix into main 2026-09-17 18:50:44 +00:00
Member

Summary

Two changes to the credit system:

  1. Bug fix — credits not applied when rebooking a cancelled lesson within the same month.
  2. Feature — show a student's total account credit on their detail page when they hold a balance.

Bug: same-month rebook charged twice

LessonBooker::settle() charges a scheduled (monthly/weekly) lesson at booking time when it is added to a month whose billing date has already passed — exactly the case of rebooking a cancelled lesson within the same month. That charge bypasses the daily billing scan (ScheduledBillingRunner::sendNotices), which was the only place applyCredits() ran. So the cancellation credit sat unused while the family was charged full price for the replacement slot — billed twice for the same lesson.

Fix: after creating the charge-at-booking payment for a scheduled offering, settle() now applies the payer's account credit to it, mirroring the daily scan. A payment fully covered by credit is settled and its lesson confirmed. applyCredits is a no-op when the payer holds no balance, and the one-time pay-now flow is deliberately left unchanged. Added PaymentService::findPayment() so settle() can re-read the row after applyCredits writes to it (the Payment object is immutable).

Feature: total credit on the student detail page

Added a prominent banner at the top of the student detail page, shown only when the student/family has a positive credit balance. Uses the already-available $creditBalance/$creditCurrency (no controller change), and notes when the balance is held on a guardian's account. The full "Account credit" breakdown remains lower on the page.

Tests

  • Added testMonthlyRebookInBilledMonthAppliesAccountCredit proving credit is applied and the lesson confirms when fully covered.
  • Added default mock expectations so existing charge-at-booking tests keep passing.

composer test (1015 tests), composer lint (PHPStan level 10), and composer cs all pass. No schema change, so no version bump required.

## Summary Two changes to the credit system: 1. **Bug fix — credits not applied when rebooking a cancelled lesson within the same month.** 2. **Feature — show a student's total account credit on their detail page when they hold a balance.** ## Bug: same-month rebook charged twice `LessonBooker::settle()` charges a scheduled (monthly/weekly) lesson *at booking time* when it is added to a month whose billing date has already passed — exactly the case of rebooking a cancelled lesson within the same month. That charge bypasses the daily billing scan (`ScheduledBillingRunner::sendNotices`), which was the **only** place `applyCredits()` ran. So the cancellation credit sat unused while the family was charged full price for the replacement slot — billed twice for the same lesson. **Fix:** after creating the charge-at-booking payment for a scheduled offering, `settle()` now applies the payer's account credit to it, mirroring the daily scan. A payment fully covered by credit is settled and its lesson confirmed. `applyCredits` is a no-op when the payer holds no balance, and the one-time pay-now flow is deliberately left unchanged. Added `PaymentService::findPayment()` so `settle()` can re-read the row after `applyCredits` writes to it (the `Payment` object is immutable). ## Feature: total credit on the student detail page Added a prominent banner at the top of the student detail page, shown only when the student/family has a positive credit balance. Uses the already-available `$creditBalance`/`$creditCurrency` (no controller change), and notes when the balance is held on a guardian's account. The full "Account credit" breakdown remains lower on the page. ## Tests - Added `testMonthlyRebookInBilledMonthAppliesAccountCredit` proving credit is applied and the lesson confirms when fully covered. - Added default mock expectations so existing charge-at-booking tests keep passing. `composer test` (1015 tests), `composer lint` (PHPStan level 10), and `composer cs` all pass. No schema change, so no version bump required.
Kydoimos added 1 commit 2026-09-17 18:40:09 +00:00
Apply account credit on same-month rebook, surface credit on student page
CI / Coding Standards (pull_request) Successful in 27s
CI / Tests (PHP 8.2) (pull_request) Successful in 28s
CI / No Debug Code (pull_request) Successful in 9s
CI / Tests (PHP 8.5) (pull_request) Successful in 35s
CI / Tests (PHP 8.1) (pull_request) Successful in 37s
CI / Tests (PHP 8.3) (pull_request) Successful in 43s
CI / Static Analysis (pull_request) Successful in 51s
CI / Build Plugin Zip (pull_request) Skipped
e7de627752
A monthly/weekly lesson booked into a month whose billing date has
already passed is charged at booking time by LessonBooker::settle,
bypassing the daily scan where account credit is otherwise applied. So
rebooking a cancelled paid lesson within the same month charged the
family in full while their cancellation credit sat unused — billed twice
for the same slot.

Apply the payer's credit to that charge-at-booking payment for scheduled
offerings, mirroring the daily scan: a payment fully covered by credit
settles and confirms its lesson. Add PaymentService::findPayment so
settle can re-read the row after applyCredits writes to it.

Also surface the student's total account credit at the top of their
detail page when they hold a balance, so the studio sees it at a glance.

Co-authored-by: anthropic/claude-opus-4-8
Kydoimos added 1 commit 2026-09-17 18:42:41 +00:00
Drop stale comment about not applying credit at booking
CI / Coding Standards (pull_request) Successful in 29s
CI / Tests (PHP 8.1) (pull_request) Successful in 36s
CI / No Debug Code (pull_request) Successful in 11s
CI / Tests (PHP 8.5) (pull_request) Successful in 36s
CI / Static Analysis (pull_request) Successful in 41s
CI / Tests (PHP 8.2) (pull_request) Successful in 43s
CI / Tests (PHP 8.3) (pull_request) Successful in 43s
CI / Build Plugin Zip (pull_request) Skipped
67017409d7
This change applies credit at booking for scheduled rebooks, so the note
saying the pay-now flow deliberately does not was contradictory.

Co-authored-by: anthropic/claude-opus-4-8
Kydoimos added 1 commit 2026-09-17 18:43:59 +00:00
Trim credit-at-booking comment to one line
CI / Coding Standards (pull_request) Successful in 23s
CI / No Debug Code (pull_request) Successful in 9s
CI / Tests (PHP 8.2) (pull_request) Successful in 33s
CI / Tests (PHP 8.5) (pull_request) Successful in 34s
CI / Static Analysis (pull_request) Successful in 39s
CI / Tests (PHP 8.3) (pull_request) Successful in 38s
CI / Tests (PHP 8.1) (pull_request) Successful in 46s
CI / Build Plugin Zip (pull_request) Skipped
1758c253a1
Co-authored-by: anthropic/claude-opus-4-8
Kydoimos added 1 commit 2026-09-17 18:44:44 +00:00
Clarify credit-at-booking comment scopes to scheduled charges
CI / Coding Standards (pull_request) Successful in 30s
CI / Tests (PHP 8.2) (pull_request) Successful in 32s
CI / Tests (PHP 8.3) (pull_request) Successful in 37s
CI / Static Analysis (pull_request) Successful in 38s
CI / No Debug Code (pull_request) Successful in 9s
CI / Tests (PHP 8.1) (pull_request) Successful in 46s
CI / Tests (PHP 8.5) (pull_request) Successful in 45s
CI / Build Plugin Zip (pull_request) Skipped
e3ab7973d6
Co-authored-by: anthropic/claude-opus-4-8
Kydoimos added 1 commit 2026-09-17 18:46:13 +00:00
Apply available credit to any at-booking charge, not just scheduled
CI / Coding Standards (pull_request) Successful in 31s
CI / Tests (PHP 8.2) (pull_request) Successful in 30s
CI / Tests (PHP 8.3) (pull_request) Successful in 31s
CI / No Debug Code (pull_request) Successful in 5s
CI / Tests (PHP 8.1) (pull_request) Successful in 43s
CI / Tests (PHP 8.5) (pull_request) Successful in 42s
CI / Static Analysis (pull_request) Successful in 56s
CI / Build Plugin Zip (pull_request) Skipped
362980d008
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
thatguygriff approved these changes 2026-09-17 18:48:13 +00:00
Dismissed
Kydoimos added 1 commit 2026-09-17 18:49:18 +00:00
Add changelog entries for the credit fix and student-page display
CI / Coding Standards (pull_request) Successful in 30s
CI / Tests (PHP 8.2) (pull_request) Successful in 33s
CI / Tests (PHP 8.5) (pull_request) Successful in 33s
CI / Static Analysis (pull_request) Successful in 38s
CI / No Debug Code (pull_request) Successful in 9s
CI / Tests (PHP 8.1) (pull_request) Successful in 42s
CI / Tests (PHP 8.3) (pull_request) Successful in 41s
CI / Build Plugin Zip (pull_request) Skipped
1a166eb4e3
Recorded under the current 1.5.8 section; no version bump.

Co-authored-by: anthropic/claude-opus-4-8
Kydoimos dismissed thatguygriff's review 2026-09-17 18:49:19 +00:00
Reason:

New commits pushed, approval review dismissed automatically according to repository settings

thatguygriff merged commit ad4e4ae357 into main 2026-09-17 18:50:44 +00:00
thatguygriff deleted branch feature/student-credit-display-and-rebook-fix 2026-09-17 18:50:44 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Unsupervised/unsupervised-scheduler#202