Notify instructors on new bookings and enrolments
CI / Coding Standards (pull_request) Successful in 27s
CI / Tests (PHP 8.1) (pull_request) Successful in 37s
CI / No Debug Code (pull_request) Successful in 9s
CI / Tests (PHP 8.3) (pull_request) Successful in 36s
CI / Tests (PHP 8.5) (pull_request) Successful in 40s
CI / Tests (PHP 8.2) (pull_request) Successful in 42s
CI / Static Analysis (pull_request) Successful in 48s
CI / Build Plugin Zip (pull_request) Skipped
CI / Coding Standards (pull_request) Successful in 27s
CI / Tests (PHP 8.1) (pull_request) Successful in 37s
CI / No Debug Code (pull_request) Successful in 9s
CI / Tests (PHP 8.3) (pull_request) Successful in 36s
CI / Tests (PHP 8.5) (pull_request) Successful in 40s
CI / Tests (PHP 8.2) (pull_request) Successful in 42s
CI / Static Analysis (pull_request) Successful in 48s
CI / Build Plugin Zip (pull_request) Skipped
Add an opt-in, per-instructor email notice sent when someone books one of their lessons or enrols in one of their group classes. Off by default and set from My Availability → Notifications; covers both the student/guardian REST flows and the studio's wp-admin "book/add for a student" forms. The opt-in check lives in InstructorNotificationMailer so no booking path can drift on who is mailed; lessons fire from LessonBooker::settle (the one step both booking paths reach), enrolments from EnrollmentEndpoint::enroll and GroupClassController::addDirect. The notice is a courtesy and never fails a booking or enrolment that otherwise succeeded. Co-authored-by: anthropic/claude-opus-4-8
This commit is contained in:
co-authored by
anthropic/claude-opus-4-8
parent
56fc0bd57d
commit
12765d8f13
@@ -0,0 +1,84 @@
|
||||
# Feature: Instructor Booking Notifications
|
||||
|
||||
## Overview
|
||||
An instructor can ask to be emailed whenever someone books one of their private
|
||||
lessons or enrols in one of their group classes. It is **off by default** and set
|
||||
per instructor — the people it emails decide whether they want it.
|
||||
|
||||
The notice fires whichever way the booking or enrolment was made: a student
|
||||
(or a guardian for their child) doing it themselves through the front-end, or the
|
||||
studio doing it on their behalf from wp-admin. There is no separate "the studio
|
||||
booked it" case to forget — every path funnels through one place per registration
|
||||
type, and the opt-in check lives in the mailer, not at each call site, so no path
|
||||
can drift on who gets mailed.
|
||||
|
||||
## Preference `us_notify_on_booking` (user meta)
|
||||
`'1'` or `'0'`, stored against the instructor's WordPress user. Absent — the
|
||||
default for every account — reads as off. Stored as `'0'` rather than deleted when
|
||||
an instructor turns it off, so a deliberate "no" is told apart from never having
|
||||
chosen.
|
||||
|
||||
Default off because the notification is a new capability: turning it on for every
|
||||
instructor on an existing site the day it ships would mail people who never asked.
|
||||
|
||||
## Admin Interface
|
||||
**My Availability → Notifications** (`manage_availability` — every instructor sees
|
||||
their own availability page):
|
||||
|
||||
- **Email me when someone books a lesson or enrols in one of my group classes** —
|
||||
a single checkbox, off by default, saved on its own form (`usc_action=save_notify`).
|
||||
|
||||
The page an instructor sets availability on is the one they already visit to shape
|
||||
their teaching schedule, so the preference about that schedule lives beside it.
|
||||
|
||||
## What triggers a notice
|
||||
| Registration | Path | Where the notice fires |
|
||||
|---|---|---|
|
||||
| Private lesson | student/guardian REST **and** studio wp-admin form | `Booking\LessonBooker::settle()` — the single step both paths reach once a slot is claimed |
|
||||
| Group class | student/guardian REST | `GroupClass\EnrollmentEndpoint::enroll()`, after the roster row is written |
|
||||
| Group class | studio "Add students directly" (wp-admin) | `GroupClass\GroupClassController::addDirect()`, per student added |
|
||||
|
||||
A weekly lesson reservation reports the number of occurrences claimed, so a single
|
||||
booking and a term booked at once each read correctly.
|
||||
|
||||
The notice is an opt-in courtesy, never a step a booking or enrolment depends on:
|
||||
a missing or failed send can never fail a booking that otherwise succeeded, and
|
||||
the mailer returns false (without sending) when the instructor has not opted in,
|
||||
their account is gone, or it carries no email.
|
||||
|
||||
## Implementation
|
||||
- `Unsupervised\Schedular\Auth\InstructorNotificationPref` — the per-instructor
|
||||
user-meta preference (`wants()` / `set()`), default off
|
||||
- `Unsupervised\Schedular\Auth\InstructorNotificationMailer` — `notifyLessonBooked()`
|
||||
and `notifyEnrollment()`; the opt-in check and recipient resolution live here
|
||||
- `Unsupervised\Schedular\Booking\LessonBooker::settle()` — fires the lesson notice
|
||||
for both booking paths
|
||||
- `Unsupervised\Schedular\GroupClass\EnrollmentEndpoint::enroll()` — student/guardian
|
||||
enrolment notice
|
||||
- `Unsupervised\Schedular\GroupClass\GroupClassController::addDirect()` — studio
|
||||
enrolment notice
|
||||
- `Unsupervised\Schedular\Availability\AvailabilityController` — reads the preference
|
||||
for the page and saves the toggle (`save_notify`)
|
||||
- `templates/admin/availability.php` — the Notifications checkbox
|
||||
|
||||
All three consumers take the mailer (and the controller its preference) as a
|
||||
constructor dependency defaulting to a fresh instance, so existing wiring in
|
||||
`Plugin`, `RestRegistrar` and `AdminMenu` is unchanged.
|
||||
|
||||
## Tests
|
||||
- `tests/Unit/Auth/InstructorNotificationPrefTest.php` — default-off, opt-in read,
|
||||
string-boolean write, non-user guards
|
||||
- `tests/Unit/Auth/InstructorNotificationMailerTest.php` — sends to an opted-in
|
||||
instructor, weekly occurrence count, and sends nothing when opted out / account
|
||||
gone / no email
|
||||
- `tests/Unit/GroupClass/EnrollmentEndpointTest.php` — a successful enrolment
|
||||
notifies the class instructor
|
||||
- `tests/Unit/Availability/AvailabilityControllerTest.php` — the toggle saves an
|
||||
opt-in and an opt-out
|
||||
- The booking-path tests (`BookingEndpointTest`, `AdminBookingTest`) inject a mock
|
||||
mailer, keeping them about booking
|
||||
|
||||
## Related
|
||||
- `lesson-booking.md` — the booking core the lesson notice hangs off
|
||||
- `group-classes.md` — the enrolment paths the class notice hangs off
|
||||
- `user-roles.md` — the instructor role and `manage_availability` capability
|
||||
Reference in New Issue
Block a user