Skip to content

PRD 02 — Classes (catalogue, settings, bookings)

Status: draft · Priority tier: P0 · Size: L · Depends on: Foundation (auth/roles/business, existing), Locations & Facilities, Pricing Plans (packages/memberships), Customers, Schedule (PRD 03)

1. Summary

The class catalogue: categories and sub-categories, a 4-step class wizard (with draft save), difficulty levels, studio-wide class rules (timetable window, slots-left display, booking window, check-in, late cancel, penalty strikes, refund-credit validity) and the class bookings list with a per-booking drawer. A class is the reusable template; dated sessions live in PRD 03. Without it nothing can be scheduled or sold.

2. Problem & goals

Studio owners need to define what they teach once, set how customers may book and cancel it, and see who is booked. Goals:

  • Create and publish a class in <= 8 clicks plus typing (original: ~8).
  • Every booking rule has one studio-wide default and can be overridden per session (PRD 03) — no rule is hard-coded.
  • Bookings list answers "who is booked today / this week" in <= 2 filter changes. Non-goals: third-party class marketplace (ClassPass) bookings; session scheduling (PRD 03); package/membership authoring (Pricing Plans PRD); public storefront pages (Storefront PRD).

3. Users & roles

  • Owner/admin: full catalogue, settings, bookings.
  • Manager/front desk: manage classes and bookings; settings depends on role permission.
  • Instructor/staff: view their own sessions' bookings; no catalogue edit (guess).
  • Customer: indirect — sees the published class, slots-left, and is bound by booking/cancel rules.

4. Scope

In (v1)

  • must: category CRUD + reorder, sub-category; class list grouped by category with status/category filters and search.
  • must: 4-step class wizard (details, images, what to bring, pricing options); draft, edit, duplicate, set inactive, delete.
  • must: pricing: free or paid; direct price per pricing group; accepted memberships and packages; refund method.
  • must: class settings (timetable weeks/start, slots-left display, booking window, late-cancel hours, refund-credit validity).
  • must: class bookings list (filters) and booking drawer (No show, Cancel booking, event log).
  • should: levels CRUD; penalty strike; auto check-in + window; SEO fields + slug; 4:3 image crop; video URL; custom cancellation policy; show reviews toggle; session roster actions (email/SMS class, download list, audit trail).
  • could: refund-credit validity; rich-text description toolbar beyond basics. Later (v2+)

  • should: waitlist (original timetable legend shows "Waitlisted"; config not observed). Out

  • ClassPass integration (third-party, no clean-room API need).

  • Plan-count limits on classes (billing tie-in; pricing tier: TBD).

5. User stories

  • US-02-01 As an owner, I want to group classes into categories and sub-categories so that the catalogue and storefront stay organised.
  • US-02-02 As an owner, I want a guided wizard that blocks Next until required data is valid so that I never publish an incomplete class.
  • US-02-03 As an owner, I want to save a half-finished class as a draft so that I can continue later.
  • US-02-04 As an owner, I want to set a free class, a direct-payment price, or credit-based access (membership/package) so that customers can pay in the way I sell.
  • US-02-05 As an owner, I want studio-wide rules (booking window, late cancel, slots-left display) so that I do not configure every session.
  • US-02-06 As a front desk user, I want to find a booking by customer/date/class/status so that I can help at the door.
  • US-02-07 As a front desk user, I want to mark a no-show or cancel one booking from a drawer so that attendance and credits stay accurate.
  • US-02-08 As an owner, I want to define difficulty levels so that customers can filter classes.

6. Functional requirements

ID requirement priority evidence
FR-02-01 Class list shows classes grouped into collapsible category rows (name, item count); card shows name, duration, mode tag (onsite/online), status badge (Active/Hidden/Draft), created date. must S21
FR-02-02 List filters: free-text search, Status (Active/Inactive/Draft), Category. must S21, S21h
FR-02-03 Category CRUD: add (inline name, persisted only once named), rename, delete, drag-reorder; sub-categories under a category. must S21, S21e, S21i, F12
FR-02-04 Deleting a category with classes is blocked or requires reassignment (assumption; original not observed). should F12
FR-02-05 Class card menu: Edit, Duplicate, Show/hide store listing, Set inactive, Delete; draft card: Continue, Delete. Card buttons: View Schedule (opens PRD 03 calendar filtered to class), View Pricing Plans (opens wizard step 4). must S21c, S21f, S21g
FR-02-06 Delete confirmation states the class cannot be recovered and that already-scheduled sessions are NOT cancelled. must S21d
FR-02-07 Wizard step 1 fields: name (<=100, required, unique per business, error on duplicate), short description (<=100), rich-text description (<=1000, required), category (required), sub-category, duration + unit (required, >0), level, mode onsite/online, "show on online store" toggle (default off), custom cancellation policy (collapsible). must S22, S22e, F10
FR-02-08 SEO block: page title (<=70), description (<=320), slug auto-derived from name and editable, with live preview of public URL. should S22c
FR-02-09 Step 2: at least one image (JPG/PNG/GIF, <10 MB), fixed 4:3 crop modal, first image is cover, extra images optional; optional video URL. must S22g, S22g2
FR-02-10 Step 3: "what to bring" yes/no; yes opens an add-items drawer; items reorderable. should S22h, S22h2
FR-02-11 Step 4: Free or Paid. Paid: optional direct-payment price per pricing group (+ "set as default option"), refund method (no refund / refund as credits / store-credit wallet), assign memberships, assign packages (search, select all, grouped by category). Free classes cannot be covered by package credits. must S22i, S22j, S22k, S22l, part 08
FR-02-12 Wizard chrome: step list with completion %, Back/Next (Next disabled until step valid), Preview, Save as draft, "saved N min ago"; final action "Add" publishes as Active. must S22, F10
FR-02-13 Edit uses the same wizard (Save & Exit); changes to a class do not rewrite past sessions/bookings (assumption). must S23
FR-02-14 Levels: list with add (drawer), delete, drag-reorder; seed defaults Beginner, Intermediate, Advanced, Open to all. Deleting an in-use level is blocked or clears the field on classes (open question). should S24, S24b
FR-02-15 Setting: timetable shows N weeks (default 2) of sessions; starts Today or on a chosen date. must S24
FR-02-16 Setting: show slots left on timetable and checkout; mode Always or only when <= N remain; optional "include total capacity" (e.g. 3/12). must S24
FR-02-17 Setting: show ratings/reviews on storefront (applies only if reviews exist; reviews feature is out of this PRD). could S24
FR-02-18 Setting: booking window — earliest: Anytime or N hours/days before start; latest: until start or N before start. must S24
FR-02-19 Setting: auto check-in toggle + earliest check-in window (Anytime or N hours before). should S24
FR-02-20 Setting: late-cancel window N hours before start; cancelling inside the window is a "late cancellation". must S24
FR-02-21 Setting: penalty strike — when ticked, a late cancel/no-show by a member on an unlimited-credit plan records a strike (strike consequences are defined by Memberships PRD). should S24
FR-02-22 Setting: validity of refunded credits (N + unit months/days) used when a session is cancelled and credits are returned. could S24
FR-02-23 Settings page: Save button disabled until a value changes; one settings record per business; session-level overrides in PRD 03 take precedence. must F11
FR-02-24 Class bookings list: search by customer, date-range presets (Today, Yesterday, Last 7/30/90 days, This/Last month, Last year, Till date, exact date, custom), filters Location, Staff, Status (Upcoming/In progress/Completed/Cancelled), Class; page size 50; empty state. must S20, S20b-d
FR-02-25 Session roster page: header (status, class, instructor, date/time, location/room), tabs Booked (n/capacity) and Cancelled, search, sort, status filter (Completed, No show), row = customer, payment option, booked-at, added-by, status. must S209i, S209k
FR-02-26 Roster Actions menu: email class, SMS class, edit class (session), cancel class, download list, view audit trail. should S209j
FR-02-27 Booking drawer: booking ref, customer link, payment card (status, option, transaction id), attendees, actions No show / Cancel booking, events log (emails sent, status changes with actor). must S209l
FR-02-28 Add booking to a session (customer, attendees/pax, internal note, notify staff) is reachable from the roster; spec lives in PRD 03. must S209g, S209h
FR-02-29 Class/booking changes emit notifications (payment confirmation, completed) via the Notifications PRD. should S209l

7. Screens

Our screen Modelled on States
Class list S21 empty (one default category, 0 items), loading skeleton, filled, filtered-empty, delete confirm, error/retry
Class wizard (create/edit) S22, S23 each step empty/invalid/valid, crop modal, add-items drawer, save error (duplicate name), saving
Class settings S24, S24b default, dirty, saved toast, add-level drawer
Class bookings list S20 empty, loading, filled, filters open
Session roster + booking drawer S209i, S209l empty ("no bookings"), filled, no-show confirm, cancel confirm

8. Flows

Create class: List > Add Class (2 clicks) > step 1 (name, desc, category, duration) > Next > image + crop > Next > bring Y/N > Next > Free/Paid (+ plans) > Add. Target <= 8 clicks + typing. Edges: duplicate name toast; draft cards omitted from session class-search; free class excludes package credits; navigating away offers Save as draft. Settings: open > change > Save (disabled until dirty). Mark no-show: bookings list > row > drawer > No show (<= 3 clicks).

9. Data model (guesses marked *)

  • ServiceCategory(id, type=class, name, sort, parent_id* for sub-category)
  • Class(id, name, slug, short_desc, description, category_id, subcategory_id, duration_min, level_id, mode, listing_visible, status draft|active|inactive, images[], video_url, bring_items[], cancel_policy, seo_title, seo_desc, pricing_type free|paid, direct_prices[{pricing_group, price}], refund_method, membership_ids[], package_ids[])
  • ClassLevel(id, name, sort)
  • ClassSettings(business_id, timetable_weeks, timetable_start, show_slots_left, slots_mode, slots_threshold, show_total_capacity, show_reviews, book_earliest, book_latest, auto_checkin, checkin_earliest, late_cancel_hours, penalty_strike, refund_credit_validity)
  • ClassBooking(ref, session_id, owner_customer_id, attendees[], payment_option, transaction_id, status booked|completed|no_show|cancelled, late_cancel*, added_by, events[]) Relations: Class 1-n Session (PRD 03); Session 1-n ClassBooking.

10. Business rules & edge cases

  • Class names unique per business (case-insensitive*).
  • Resolution order for booking/cancel/check-in rules: session override > class settings > none.
  • A class with status draft/inactive cannot receive new sessions or storefront listing; existing sessions are unaffected.
  • Price per pricing group falls back to the default group.
  • Late cancel: cancellation after (start - late_cancel_hours) is flagged; credit-return vs forfeit policy: see open questions.
  • Refunded credits expire after the configured validity.
  • Slots-left display never reveals capacity unless "include total" is on.
  • Deleting a class does not cancel its sessions; bookings stay visible.

11. Permissions

Action Owner Manager Front desk Instructor
Catalogue CRUD yes yes no no
Class settings yes yes* no no
View bookings all all all own sessions*
No-show / cancel booking yes yes yes no*
Role matrix to be driven by the existing/future Roles PRD; * = assumption.

12. Acceptance criteria

  • Given blank wizard step 1, when required fields are missing, then Next is disabled; when all valid, Next enables.
  • Given a class named "Yoga", when I create another "yoga", then save fails with a name-exists message and no record is created.
  • Given an uploaded image, when I confirm the 4:3 crop, then the cropped image is stored as cover.
  • Given step 4 Free, then package/membership assignment is not offered.
  • Given a published class with scheduled sessions, when I delete it, then the confirm text says sessions are not cancelled and sessions remain.
  • Given late_cancel_hours = 12, when a customer cancels 11h before start, then the booking is marked late cancelled.
  • Given slots mode "<= 3 remain" and 5 remaining, then the customer sees no count; at 3 remaining sees "3 left".
  • Given settings unchanged, then Save is disabled.
  • Given a Completed session, when I open a booking and choose No show, then status becomes No show and an event is logged with my name.
  • Given a draft class, then it does not appear in the session class picker.

13. Dependencies & open questions

Depends: PRD 03 (sessions), Pricing Plans, Locations, Customers, Notifications, Roles. Open questions

  1. Waitlist: enabled per class/session? Not observed (only a "Waitlisted" legend on storefront).
  2. Does late cancel return credits or forfeit them? Not observed; penalty-strike consequences not observed.
  3. Sub-category behaviour on storefront and deletion rules not observed.
  4. Online class: how is the meeting link delivered? Not observed (mode is only a tag).
  5. Do class edits propagate to future sessions? Not observed.
  6. Level delete when in use; instructor permissions not observed.
  7. Review feature scope (toggle exists, no reviews screens in recon).

14. Evidence

See evidence/evidence.md.