Require an offering on every lesson booking, with a student-facing picker
CI / Tests (PHP 8.1) (pull_request) Successful in 41s
CI / Tests (PHP 8.2) (pull_request) Successful in 45s
CI / No Debug Code (pull_request) Successful in 2s
CI / Tests (PHP 8.3) (pull_request) Successful in 1m40s
CI / PHPStan (pull_request) Successful in 2m24s
CI / Coding Standards (pull_request) Successful in 2m49s
CI / Build Plugin Zip (pull_request) Has been skipped
CI / Tests (PHP 8.1) (pull_request) Successful in 41s
CI / Tests (PHP 8.2) (pull_request) Successful in 45s
CI / No Debug Code (pull_request) Successful in 2s
CI / Tests (PHP 8.3) (pull_request) Successful in 1m40s
CI / PHPStan (pull_request) Successful in 2m24s
CI / Coding Standards (pull_request) Successful in 2m49s
CI / Build Plugin Zip (pull_request) Has been skipped
Generic slots (no tied offering) were bookable with no offering at all: free, instantly confirmed, and with no intake questions. POST /bookings now rejects offering-less bookings (400 offering_required), and a student-chosen offering must be an active private-lesson type owned by the slot's instructor whose duration matches the slot. The registration form gains a Lesson type field: locked to the slot's tied offering (title, duration, price) so the student sees what they are booking, or a required picker of fitting offerings for generic slots, with intake questions following the selection. Fixes #55 Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
@@ -21,12 +21,12 @@ Students register for a private lesson by choosing an offering, picking a time (
|
||||
|
||||
## Registration Flow
|
||||
1. Student opens the page with the `[us_booking]` shortcode and browses open slots as an agenda list or a weekly calendar (view toggle with previous/next-week navigation; times shown in 12-hour AM/PM form).
|
||||
2. Student picks an **offering** (a 30 or 60-minute private-lesson type) and a slot.
|
||||
2. Student picks a slot and an **offering** (a 30 or 60-minute private-lesson type). When the slot is tied to an offering the form shows it locked (the student sees exactly what they are booking); otherwise the form presents the instructor's active private-lesson offerings whose duration fits the slot. Every booking requires an offering — a generic slot with no fitting offering cannot be booked online.
|
||||
3. For a `weekly` reservation, the same weekday/time is held for the rest of the offering's term.
|
||||
4. Student answers the offering's questions (`GET /offerings/{id}/questions`).
|
||||
5. Student accepts the current published policy versions (`GET /policies`) — required to continue.
|
||||
6. Payment is taken per the student's billing method (card by default; `pending` for e-transfer; skipped for comp). See `payments.md`.
|
||||
7. `POST /bookings` creates the lesson row(s) (`status = pending`), records answers and policy acceptances, marks `us_availability.is_booked = 1`, and links the payment. A booking with nothing owed (no offering, or a free offering) creates no payment and is `confirmed` immediately.
|
||||
7. `POST /bookings` creates the lesson row(s) (`status = pending`), records answers and policy acceptances, marks `us_availability.is_booked = 1`, and links the payment. A booking with nothing owed (a free offering) creates no payment and is `confirmed` immediately.
|
||||
8. On successful payment (or comp) the lesson is `confirmed` and a receipt is emailed.
|
||||
9. Instructor sees the booking under **My Lessons** and may update status via `PATCH /bookings/{id}/status`.
|
||||
10. The booking page also shows the student their upcoming lessons (`GET /bookings`) with a per-lesson status badge (pending payment / confirmed) and a **Cancel** button.
|
||||
@@ -61,6 +61,11 @@ offering).
|
||||
`status`, and `payment` — a `{id, method, status}` summary, or `null` when
|
||||
nothing is owed (the front end then skips the payment step).
|
||||
|
||||
An offering is always required (`400 offering_required` otherwise): a slot tied
|
||||
to an offering uses that offering regardless of the request, while a generic
|
||||
slot uses the student's `offering_id`, which must be one of the instructor's
|
||||
active `private_lesson` offerings whose `duration_minutes` matches the slot.
|
||||
|
||||
`GET /bookings` returns the caller's upcoming, non-cancelled lessons (their own
|
||||
for students; the instructor's for callers with `manage_availability`), each
|
||||
with the slot's `start_dt`/`end_dt`.
|
||||
|
||||
Reference in New Issue
Block a user