# Feature: Offerings ## Overview An offering is anything a student can register for: a private-lesson type (30 or 60 minutes, single or weekly) or a group class. Offerings carry pricing, billing mode, and the intake questions a registrant must answer. They are the catalog the booking calendar and group-class pages are built from. ## Data Model — `{prefix}us_offerings` | Column | Type | Notes | |--------------------|------------------|-------------------------------------------------------------| | `id` | BIGINT UNSIGNED | Primary key | | `instructor_id` | BIGINT UNSIGNED | WordPress user ID of the owning instructor | | `kind` | VARCHAR(20) | `private_lesson` or `group_class` | | `title` | VARCHAR(191) | Display name | | `description` | TEXT | Optional longer description | | `duration_minutes` | SMALLINT | Private lessons only (e.g. 30, 60); NULL for group classes | | `price` | DECIMAL(10,2) | Price in dollars | | `currency` | VARCHAR(3) | ISO 4217, e.g. `CAD` | | `billing_mode` | VARCHAR(20) | `one_time` (single booking) or `full_term` (weekly / group) | | `allow_weekly` | TINYINT(1) | Private only — may be reserved weekly for the term | | `capacity` | SMALLINT | Group only — max enrolments; NULL for private | | `term_start` | DATE | Group / term offerings — first day; NULL otherwise | | `term_end` | DATE | Group / term offerings — last day; NULL otherwise | | `schedule_note` | VARCHAR(191) | Group only — human-readable schedule, e.g. "Tuesdays 4:00pm"| | `is_active` | TINYINT(1) | 0 = hidden from registration, 1 = bookable | | `created_at` | DATETIME | Insertion time | ## Billing Mode - `one_time` — charged once at booking (a single private lesson). - `full_term` — charged in full upfront at registration (a weekly private reservation or a year-long group class). See `payments.md`. ## Admin Interface Studio admin and instructors manage offerings under **Offerings** in wp-admin. - Studio admin (`manage_offerings`) manages offerings for any instructor. - Instructor (`manage_offerings`) manages only their own. - Each offering's intake questions are edited from the offering screen (see `registration-questions.md`). ## REST API | Method | Endpoint | Permission | |----------|---------------------------------------------|----------------------------------| | `GET` | `/wp-json/us-scheduler/v1/offerings` | Public (active offerings only) | | `POST` | `/wp-json/us-scheduler/v1/offerings` | `manage_offerings` | | `PATCH` | `/wp-json/us-scheduler/v1/offerings/{id}` | `manage_offerings` + owner | | `DELETE` | `/wp-json/us-scheduler/v1/offerings/{id}` | `manage_offerings` + owner | `GET` supports query params: `instructor_id`, `kind`. ## Implementation - Repository: `Unsupervised\Schedular\Offering\OfferingRepository` - Model: `Unsupervised\Schedular\Offering\Offering` - Admin controller: `Unsupervised\Schedular\Offering\OfferingController` - REST endpoint: `Unsupervised\Schedular\Offering\OfferingEndpoint` ## Tests - `tests/Unit/Offering/OfferingRepositoryTest.php` - `tests/Unit/Offering/OfferingTest.php`