diff --git a/README.md b/README.md new file mode 100644 index 0000000..81ce1e2 --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +# Unsupervised Scheduler + +A WordPress plugin for instructor/student lesson scheduling — private lessons and +group classes — with offerings, intake questions, versioned policies, account +registration, and (coming) online payments. + +**Version:** 1.0.0-rc.1 · **Requires:** WordPress 6.0+, PHP 8.1+ · **License:** GPL-2.0-or-later + +> Pre-release. The booking platform is being built feature-by-feature; see +> [Implementation status](#implementation-status) below. + +## Overview + +The plugin is organised **package-by-domain** under `src/` (PSR-4 +`Unsupervised\Schedular\`). Each domain owns its value objects, repositories, +REST endpoints, and admin/front-end controllers. All data access goes through +repository classes against custom `{prefix}us_*` tables; permissions are enforced +with WordPress **capabilities**, never role-name checks. There is no front-end +build step (vanilla JS/CSS in `assets/`). + +Every feature has a spec in [`docs/features/`](docs/features/) describing its data +model, REST API, classes, and tests. For contributor/architecture guidance see +[`CLAUDE.md`](CLAUDE.md). + +## Implementation status + +| Feature | Spec | Status | +|---|---|---| +| User roles & capabilities (studio admin / instructor / student) | [user-roles.md](docs/features/user-roles.md) | ✅ Implemented | +| Offerings (private-lesson types & group classes) | [offerings.md](docs/features/offerings.md) | ✅ Implemented | +| Availability (durations, weekly recurrence, calendar) | [availability-management.md](docs/features/availability-management.md) | ✅ Implemented | +| Registration questions (per-offering intake) | [registration-questions.md](docs/features/registration-questions.md) | ✅ Implemented | +| Policies (drafting, versioning, tracked acceptance) | [policies.md](docs/features/policies.md) | ✅ Implemented | +| Account registration (invite-only, signup policy acceptance) | [account-registration.md](docs/features/account-registration.md) | ✅ Implemented | +| Lesson booking (offering → questions → policies) | [lesson-booking.md](docs/features/lesson-booking.md) | ✅ Implemented | +| Group classes (capacity-enforced enrolment) | [group-classes.md](docs/features/group-classes.md) | ✅ Implemented | +| Student administration (studio-admin view) | [student-administration.md](docs/features/student-administration.md) | 🟡 Planned | +| Payments (Stripe, e-transfer/comp, receipts) | [payments.md](docs/features/payments.md) | 🟡 Planned | +| Payment reporting (monthly per-instructor + CSV) | [payment-reporting.md](docs/features/payment-reporting.md) | 🟡 Planned | + +> Payments are deliberately deferred to the end: booking and enrolment ship with a +> clean seam (a lesson lands `pending`, an enrolment `active`, with `payment_id` +> null) into which the pay→confirm + receipt step plugs later. + +## Shortcodes + +| Shortcode | Purpose | +|---|---| +| `[us_booking]` | Student calendar + private-lesson registration flow | +| `[us_group_classes]` | Browse and enrol in group classes | +| `[us_student_login]` | Front-end student login | +| `[us_student_register]` | Invite-based account registration (accepts signup policies) | + +## REST API + +All endpoints live under `/wp-json/us-scheduler/v1/` (e.g. `/offerings`, +`/availability`, `/bookings`, `/enrollments`, `/policies`, `/questions`). +Permissions are enforced via `permission_callback` capability checks. See each +feature doc for the routes and required capabilities. + +## Roles & capabilities + +Three custom roles — **Studio Admin** (`us_studio_admin`), **Instructor** +(`us_instructor`), and **Student** (`us_student`) — plus a `user_has_cap` filter +that grants every studio-admin capability to WordPress administrators, so the site +owner runs the studio without a separate role. Full capability matrix in +[user-roles.md](docs/features/user-roles.md). + +## Installation + +1. Build a distributable zip (see [Development](#development)): + ```bash + composer build # -> dist/unsupervised-schedular-.zip + ``` +2. In wp-admin: **Plugins → Add New → Upload Plugin**, choose the zip, install, and activate. + +Activation creates the `us_*` database tables and registers the roles. CI also +publishes an installable zip artifact on every merge to `main`. + +## Development + +```bash +composer install # install dependencies +composer test # PHPUnit (run after every change) +composer lint # PHPStan (level 6) +composer cs # PHPCS (WordPress coding standards) +composer cs:fix # auto-fix coding standards +composer build # build the plugin zip into dist/ + +# a single test file / single test +./vendor/bin/phpunit tests/Unit/Offering/OfferingRepositoryTest.php +./vendor/bin/phpunit --filter testInsertReturnsId +``` + +Tests use [Brain\Monkey](https://brain-wp.github.io/BrainMonkey/) and Mockery to +stub WordPress and `$wpdb` without a full WP install. To run the plugin in a real +WordPress without Docker, `wp-now` works well: `npx @wp-now/cli@latest start`. + +## CI + +Gitea Actions (`.gitea/workflows/ci.yml`) runs on every push and pull request: +**lint** (PHPCS), **static-analysis** (PHPStan), **test** (PHPUnit on PHP +8.1/8.2/8.3), and **no-debug** (rejects debug statements in `src/`). On merge to +`main` a **build** job publishes the installable plugin zip as an artifact. + +## License + +GPL-2.0-or-later. diff --git a/docs/features/student-administration.md b/docs/features/student-administration.md new file mode 100644 index 0000000..19ad5f5 --- /dev/null +++ b/docs/features/student-administration.md @@ -0,0 +1,46 @@ +# Feature: Student Administration + +## Overview +A read-only studio-admin area to browse students and drill into one student's +history and upcoming activity — lessons and group-class enrolments — without +digging through individual records. (Status: planned — issue #22.) + +## 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`. + +## 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. + - *(Later)* policy-acceptance history, intake answers, and payment history once + Payments lands. + +Read-only in this iteration; cancel/edit actions are a possible follow-up. + +## 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`, + `Availability\AvailabilityRepository::findById`, + `Offering\OfferingRepository::findById`, + `GroupClass\EnrollmentRepository::findByStudent` +- 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)