Catalog
Purpose
The largest context (12 entities). The Activity is the aggregate root: a bookable offering — show, movie, gym class, service — published by a company.
Around it sit:
- Scheduling: Session (a concrete occurrence customers book) and Time slot (a recurrence rule from which sessions are materialised).
- Taxonomy: Category (companies’ or platform-level) under one Sphere.
- People: Contributor (a company-member credited on an activity in one or more roles — coach, host, speaker, actor, director).
- Presentation: Activity extra, Activity partner, Activity link, Location.
- Engagement: User activity favorite, Time slot attendee.
- Reputation: Contributor review (client 1–5 star rating + text for a contributor, gated on a confirmed booking).
Boundaries
- In: everything needed to describe what’s bookable and where/when.
- Out:
- The reservation itself is in Bookings — a Booking points back at a Session here.
- Pass entitlements that cover an activity are in Passes —
pass_entitlement_template.activity_idreferences back here. - The actor: bookings are made by Company customer, not a raw User.
Entities
| ID | Entity | Role |
|---|---|---|
| ENT-005 | Activity | The bookable offering — aggregate root |
| ENT-012 | Session | A concrete occurrence at a date+time — what customers book |
| ENT-013 | Time slot | Recurrence rule that materialises sessions |
| ENT-009 | Category | Taxonomy node, company-scoped or platform-wide |
| ENT-010 | Contributor | Company-member credited on an activity (multi-role) |
| ENT-011 | Location | Physical venue — embedded only, no top-level resource |
| ENT-014 | Time slot attendee | Customer expected at a slot occurrence (post-fact billable) |
| ENT-015 | User activity favorite | Per-user pin on an activity |
| ENT-006 | Activity extra | Add-on bought with a booking (towel, equipment, etc.) |
| ENT-007 | Activity link | External link from an activity (trailer, webpage) |
| ENT-008 | Activity partner | Co-presenter / co-organiser on the activity |
| ENT-043 | Contributor review | Client’s 1–5 star rating for a contributor, gated on a confirmed booking |
Backend implementation
- Module:
libs/features/activities/— single feature lib covering all 11 entities. - Surface routing:
activities-client.module.ts,activities-admin.module.ts. No super-admin surface. - Drizzle schema:
libs/shared/data-access-db/src/lib/schema/activities.schema.ts(pgSchema('activities')).
Cross-context relationships
- This context owns the
activities.*Postgres schema (minus spheres and audit log, which logically belong to Spheres even though they share the file). - This context references:
- Spheres via
activity.sphere_id(FK, intra-schema, NOT NULL). - Companies via
activity.company_id,location.company_id,category.company_id— cross-schema, no FK (see ADR). - Companies via
contributor.member_id→company_member(cross-schema, no FK; ADR applies). - Identity via
user_activity_favorite.user_id. - Identity via
contributor_review.target_user_idandcontributor_review.reviewer_user_id(cross-schema soft refs, no FK; ADR applies). - Bookings via
contributor_review.booking_id(cross-schema soft ref, no FK; ADR applies).
- Spheres via
- This context is referenced by:
Open questions
- OPEN (assertion to add): when an activity is linked to a category, the service must check
category.companyId IS NULL OR category.companyId = activity.companyId— currently nothing enforces this. See Activity Known gotchas. - Bookings’ feature library is co-located here (no separate
libs/features/bookings/) — see Bookings.