Implements #3 (Lesson booking) — the registration flow tying offerings, intake questions, and booking-scoped policy acceptance together. (Group classes #4 follow as the next PR, reusing the gate.)
BookingRepository::insertSeries() builds a weekly series sharing a series_id; AvailabilityRepository::findUnbookedInGroup() reserves the recurring group.
RegistrationGate (src/Registration/): validate() + record() for required intake answers and booking-scoped policy acceptances — shared with group enrolment (#4).
BookingEndpoint::book(): accepts offering_id, recurrence, answers, accepted_policy_version_ids; books a single lesson or a weekly series; records answers + acceptances (type lesson).
GET /policies?scope=booking filter.
Front end
booking.js: slot → load offering questions + booking policies → form (questions, required policy checkboxes, optional weekly) → POST /bookings.
Payment seam
Payment is deferred to #7. A booking lands status = pending, payment_id = null; the instructor confirms via PATCH /bookings/{id}/status. The pay→confirm + receipt step plugs into this seam later.
Tests
Lesson, BookingRepository (incl. weekly series), and RegistrationGate (validate/record).
A test-only WP_Error stub added to tests/bootstrap.php (the gate returns WP_Error).
composer test (110 tests), composer cs, PHPStan level 6, and no-debug all pass.
Implements #3: students register for a private lesson by picking a slot,
answering the offering's intake questions, and accepting booking-scoped
policies. Payment is a clean seam for #7 (lessons land pending; payment_id
null; instructor confirms via PATCH /bookings/{id}/status).
- Schema: us_lessons += offering_id, recurrence, series_id, payment_id.
- Lesson: new fields + recurrence constants.
- BookingRepository::insertSeries() builds a weekly series sharing a
series_id; AvailabilityRepository::findUnbookedInGroup() reserves a group.
- RegistrationGate (src/Registration/): validate + record intake answers and
booking-scoped policy acceptances. Reused by group enrolment (#4).
- BookingEndpoint::book(): offering_id, recurrence, answers,
accepted_policy_version_ids; single or weekly; records answers/acceptances
(type lesson).
- GET /policies?scope=booking filter.
- Front-end booking.js: slot -> questions + policies -> submit.
- Wiring: RegistrationGate built in Plugin, passed via RestRegistrar.
- Test-only WP_Error stub in tests/bootstrap.php for gate testing.
Refs #3
Co-Authored-By: Claude Opus 4.8 <[email protected]>
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.
Implements #3 (Lesson booking) — the registration flow tying offerings, intake questions, and booking-scoped policy acceptance together. (Group classes #4 follow as the next PR, reusing the gate.)
Backend
us_lessons+=offering_id,recurrence,series_id,payment_id.Lesson: new fields +RECURRENCE_SINGLE/WEEKLY.BookingRepository::insertSeries()builds a weekly series sharing aseries_id;AvailabilityRepository::findUnbookedInGroup()reserves the recurring group.RegistrationGate(src/Registration/):validate()+record()for required intake answers and booking-scoped policy acceptances — shared with group enrolment (#4).BookingEndpoint::book(): acceptsoffering_id,recurrence,answers,accepted_policy_version_ids; books a single lesson or a weekly series; records answers + acceptances (typelesson).GET /policies?scope=bookingfilter.Front end
booking.js: slot → load offering questions + booking policies → form (questions, required policy checkboxes, optional weekly) →POST /bookings.Payment seam
Payment is deferred to #7. A booking lands
status = pending,payment_id = null; the instructor confirms viaPATCH /bookings/{id}/status. The pay→confirm + receipt step plugs into this seam later.Tests
Lesson,BookingRepository(incl. weekly series), andRegistrationGate(validate/record).WP_Errorstub added totests/bootstrap.php(the gate returnsWP_Error).composer test(110 tests),composer cs, PHPStan level 6, and no-debug all pass.Refs #3
🤖 Generated with Claude Code