Files
unsupervised-scheduler/docs/features/student-administration.md
T
thatguygriffandClaude Opus 5 76caf178f0
CI / Tests (PHP 8.1) (pull_request) Successful in 41s
CI / Tests (PHP 8.2) (pull_request) Successful in 40s
CI / No Debug Code (pull_request) Successful in 2s
CI / Coding Standards (pull_request) Successful in 2m55s
CI / PHPStan (pull_request) Successful in 3m1s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m43s
CI / Build Plugin Zip (pull_request) Skipped
Say "student" and "profile" in the UI, not "child" and "family"
Sweep the translatable strings across the frontend templates, the admin
screens, the editor previews and the block inserter entry. Nothing else
moves: the database columns, request parameters, form field names, CSS
classes, the us_family shortcode and the us-scheduler/family block name are
contracts with existing installs and with post content people have already
saved, so renaming them would break sites for no user-visible gain.

Two strings are reworded rather than swapped, because the direct
substitution reads wrong:

- The students list said "Child of Jane" and now says "Managed by Jane".
  "Student of Jane" would read as a teacher's pupil, which is exactly the
  wrong idea in a music studio.
- A managed account is now "a managed student account" rather than "a
  student account", which would not distinguish it from the account holder.

The guardian feature doc gains a short section on the split, so the next
person to work on it does not read the mismatch as drift and "fix" it.

Closes #144

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-07-29 20:34:55 -03:00

5.1 KiB

Feature: Student Administration

Overview

A studio-admin area to browse students, drill into one student's history and upcoming activity — lessons and group-class enrolments — and act on their behalf: cancel a lesson, withdraw them from a group class, or fix their account details.

Data Model

No new tables. The views are composed from existing data:

  • Students are WordPress users with the us_student role (get_users, get_userdata).
  • Lessons come from {prefix}us_lessons (with {prefix}us_availability for slot times).
  • Group-class enrolments come from {prefix}us_group_enrollments.
  • Policy acceptances come from {prefix}us_policy_acceptances (with the policy and version tables for titles/numbers).
  • Intake answers come from {prefix}us_question_answers (with {prefix}us_questions for labels).
  • Payments come from {prefix}us_payments.

Admin Interface

Students in wp-admin (manage_students, studio admin only):

  • List — every us_student user: display name, email, registered date, and quick counts (upcoming lessons, active group enrolments). Each row links to the detail view.
  • Detail (?student_id=):
    • Account — display name, email, registered date.
    • Upcoming lessons and Past lessons — split by the linked availability slot's start_dt; each shows date/time, offering, instructor, and status.
    • Group-class enrolments — active/past, with offering title and status.
    • Policy acceptances — every acceptance the student has recorded, newest first: policy title, version, context (account signup / lesson / enrolment), and when it was accepted.
    • Intake answers — every registration-question answer, newest first: question label, answer, and the registration it was given for.
    • Account credit (manage_billing only) — the student's available credit balance plus every credit (date, reason, amount, remaining, status). Credit comes from cancelled paid lessons and is applied automatically to upcoming scheduled billing. See credits.md.
    • Payment history (manage_billing only) — every payment, newest first: date, context, method, status, subtotal, HST, total, and receipt number.

Admin actions (detail view)

All actions are nonce-protected POSTs handled on the detail page:

  • Edit account — display name and email. The email must be valid and not in use by another account.
  • Cancel lesson — on any non-cancelled upcoming lesson. Uses the same path as student-initiated cancellation: the lesson is marked cancelled, the availability slot is freed for rebooking, and a still-pending payment is voided. A paid lesson is credited back to the student's account (see credits.md) rather than refunded.
  • Withdraw — on an active group-class enrolment: marked cancelled (freeing its capacity seat), with the same pending-payment voiding.

Capabilities

  • manage_students — studio admin (administrators inherit it via the user_has_cap filter). No new capabilities or tables.

Implementation

  • Admin controller: Unsupervised\Schedular\Auth\StudentController (list + detail)
  • Templates: templates/admin/students.php, templates/admin/student-detail.php
  • Reuses Booking\BookingRepository::findByStudent + countUpcomingForStudent, Availability\AvailabilityRepository::findById, Offering\OfferingRepository::findById, GroupClass\EnrollmentRepository::findByStudent + countActiveForStudent
  • History sections: Auth\StudentHistory builds the display rows from Policy\AcceptanceRepository::findByStudent, Registration\AnswerRepository::findByStudent, and Payment\PaymentRepository::findByStudent, resolving policy/version titles and question labels (unit-tested with mocked repositories).
  • Actions: Auth\StudentActions — cancel lesson / withdraw enrolment (both refuse records that don't belong to the student, and reuse Payment\PaymentService::voidPending) and account updates via wp_update_user (unit-tested with mocked repositories).
  • Upcoming/past split: Auth\StudentSchedule::partition() (pure, unit-tested)
  • The upcoming/past split is extracted into a small pure helper so it is unit-testable (the controller itself follows the repo convention of not being unit-tested).

Tests

  • tests/Unit/Auth/StudentScheduleTest.php (the pure upcoming/past split helper)
  • tests/Unit/Auth/StudentHistoryTest.php (history display rows + fallbacks)
  • tests/Unit/Auth/StudentActionsTest.php (cancel/withdraw guards + side effects, account validation)
  • findByStudent coverage in tests/Unit/Policy/AcceptanceRepositoryTest.php, tests/Unit/Registration/AnswerRepositoryTest.php, and tests/Unit/Payment/PaymentRepositoryTest.php

Family Relationships

The students list gains a Profile column — a child links to their guardian, a guardian lists their children — and the student screen a Profile panel. A child's listed email is their guardian's, since a child's own address is an undeliverable placeholder, and the credit balance shown is the payer's, labelled with whose account holds it. See parent-guardian-accounts.md.