d3a2767976
CI / Coding Standards (push) Successful in 2m23s
CI / PHPStan (push) Successful in 59s
CI / Tests (PHP 8.1) (push) Successful in 50s
CI / Tests (PHP 8.2) (push) Successful in 51s
CI / Tests (PHP 8.3) (push) Successful in 48s
CI / No Debug Code (push) Successful in 3s
Update availability, lesson-booking, and user-roles docs and add specs for offerings, group classes, registration questions, versioned policies, Stripe payments (with e-transfer/comp overrides and receipts), and monthly per-instructor payment reporting. Tracked in issues #1-#9. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
64 lines
4.2 KiB
Markdown
64 lines
4.2 KiB
Markdown
# Feature: Registration Questions
|
|
|
|
## Overview
|
|
Each offering can carry a set of intake questions the registrant must answer when booking. Questions are authored per offering by the studio admin or the owning instructor, and answers are stored against the resulting lesson or group enrolment.
|
|
|
|
## Data Model — `{prefix}us_questions`
|
|
|
|
| Column | Type | Notes |
|
|
|---------------|------------------|-------------------------------------------------------------|
|
|
| `id` | BIGINT UNSIGNED | Primary key |
|
|
| `offering_id` | BIGINT UNSIGNED | FK → `us_offerings.id` — questions are scoped per offering |
|
|
| `label` | VARCHAR(255) | The question text shown to the registrant |
|
|
| `field_type` | VARCHAR(20) | `text` / `textarea` / `select` / `checkbox` |
|
|
| `options` | TEXT | JSON array of choices (for `select`); NULL otherwise |
|
|
| `is_required` | TINYINT(1) | 1 = registrant must answer to continue |
|
|
| `sort_order` | INT | Display order within the offering |
|
|
| `is_active` | TINYINT(1) | 0 = retired, 1 = shown on the form |
|
|
| `created_at` | DATETIME | Insertion time |
|
|
|
|
## Data Model — `{prefix}us_question_answers`
|
|
|
|
| Column | Type | Notes |
|
|
|---------------------|------------------|--------------------------------------------------------|
|
|
| `id` | BIGINT UNSIGNED | Primary key |
|
|
| `question_id` | BIGINT UNSIGNED | FK → `us_questions.id` |
|
|
| `registration_type` | VARCHAR(20) | `lesson` or `enrollment` |
|
|
| `registration_id` | BIGINT UNSIGNED | FK → `us_lessons.id` or `us_group_enrollments.id` |
|
|
| `student_id` | BIGINT UNSIGNED | WordPress user ID (denormalised for fast lookup) |
|
|
| `answer_value` | TEXT | The submitted answer (checkbox stored as `0`/`1`) |
|
|
| `created_at` | DATETIME | Insertion time |
|
|
|
|
The `registration_type` + `registration_id` pair is a polymorphic reference shared
|
|
with `us_policy_acceptances` (see `policies.md`), letting answers attach to either a
|
|
private lesson or a group enrolment.
|
|
|
|
## Flow
|
|
1. On the registration form, the front-end calls `GET /offerings/{id}/questions`.
|
|
2. Required questions block submission until answered.
|
|
3. Answers are sent in the `answers[]` array on `POST /bookings` or `POST /enrollments` and written to `us_question_answers` alongside the new registration row.
|
|
|
|
## Admin Interface
|
|
Questions are edited from each offering's screen (**Offerings → Questions**).
|
|
- Studio admin (`manage_questions`) edits questions on any offering.
|
|
- Instructor (`manage_questions`) edits questions only on their own offerings.
|
|
|
|
## REST API
|
|
| Method | Endpoint | Permission |
|
|
|----------|---------------------------------------------------|----------------------|
|
|
| `GET` | `/wp-json/us-scheduler/v1/offerings/{id}/questions`| Public |
|
|
| `POST` | `/wp-json/us-scheduler/v1/questions` | `manage_questions` |
|
|
| `PATCH` | `/wp-json/us-scheduler/v1/questions/{id}` | `manage_questions` + owner |
|
|
| `DELETE` | `/wp-json/us-scheduler/v1/questions/{id}` | `manage_questions` + owner |
|
|
|
|
## Implementation
|
|
- Repositories: `Unsupervised\Schedular\Registration\QuestionRepository`, `Unsupervised\Schedular\Registration\AnswerRepository`
|
|
- Models: `Unsupervised\Schedular\Registration\Question`, `Unsupervised\Schedular\Registration\Answer`
|
|
- Admin controller: `Unsupervised\Schedular\Registration\QuestionController`
|
|
- REST endpoint: `Unsupervised\Schedular\Registration\QuestionEndpoint`
|
|
|
|
## Tests
|
|
- `tests/Unit/Registration/QuestionRepositoryTest.php`
|
|
- `tests/Unit/Registration/AnswerRepositoryTest.php`
|
|
- `tests/Unit/Registration/QuestionTest.php`
|