Files
Kydoimosandanthropic/claude-opus-4-8 12765d8f13
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
Notify instructors on new bookings and enrolments
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
2026-09-18 16:18:43 -03:00

4.4 KiB

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\InstructorNotificationMailernotifyLessonBooked() 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
  • 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