The payments schema and model define a refunded status (us_payments.status, Payment::STATUS_REFUNDED), but nothing in the plugin can ever set it — STATUS_REFUNDED has no other reference in src/. docs/features/lesson-booking.md documents the gap:
A paid payment is never touched — refunds are a manual, admin-side decision.
Today that manual decision has no tooling: the admin refunds in Stripe (or by e-transfer) out-of-band and the ledger still says paid, which also skews the monthly payment reports.
Proposal
Studio-admin action (manage_billing) to mark a paid payment refunded — e.g. PATCH /payments/{id} extension plus a button on the payments queue / student payment history.
For card payments, optionally issue the refund via the Stripe API (StripeGateway) rather than only recording it; handle the charge.refunded webhook.
Decide the effect on the linked registration (cancel the lesson/enrolment or leave it), and how refunded rows appear in payment-reporting totals/CSV.
## What
The payments schema and model define a `refunded` status (`us_payments.status`, `Payment::STATUS_REFUNDED`), but nothing in the plugin can ever set it — `STATUS_REFUNDED` has no other reference in `src/`. `docs/features/lesson-booking.md` documents the gap:
> A `paid` payment is never touched — refunds are a manual, admin-side decision.
Today that manual decision has no tooling: the admin refunds in Stripe (or by e-transfer) out-of-band and the ledger still says `paid`, which also skews the monthly payment reports.
## Proposal
- Studio-admin action (`manage_billing`) to mark a `paid` payment `refunded` — e.g. `PATCH /payments/{id}` extension plus a button on the payments queue / student payment history.
- For card payments, optionally issue the refund via the Stripe API (`StripeGateway`) rather than only recording it; handle the `charge.refunded` webhook.
- Decide the effect on the linked registration (cancel the lesson/enrolment or leave it), and how `refunded` rows appear in `payment-reporting` totals/CSV.
## Where
- `src/Payment/` (`PaymentRepository`, `PaymentEndpoint`, `StripeGateway`, `PaymentController`)
- Specs: `docs/features/payments.md`, `docs/features/payment-reporting.md`
- Tests under `tests/Unit/Payment/`
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What
The payments schema and model define a
refundedstatus (us_payments.status,Payment::STATUS_REFUNDED), but nothing in the plugin can ever set it —STATUS_REFUNDEDhas no other reference insrc/.docs/features/lesson-booking.mddocuments the gap:Today that manual decision has no tooling: the admin refunds in Stripe (or by e-transfer) out-of-band and the ledger still says
paid, which also skews the monthly payment reports.Proposal
manage_billing) to mark apaidpaymentrefunded— e.g.PATCH /payments/{id}extension plus a button on the payments queue / student payment history.StripeGateway) rather than only recording it; handle thecharge.refundedwebhook.refundedrows appear inpayment-reportingtotals/CSV.Where
src/Payment/(PaymentRepository,PaymentEndpoint,StripeGateway,PaymentController)docs/features/payments.md,docs/features/payment-reporting.mdtests/Unit/Payment/