Passes
Purpose
A pass is a pre-paid product a company sells to its customers: “10 yoga sessions valid 30 days”, “monthly unlimited”, “a 5-class punch card with a free towel”. A customer who buys one gets entitlements that the booking layer consumes — instead of paying-per-booking, the booking debits one entry from a covering pass.
The context has two tiers:
- Template tier — the offer the company defines: Pass + Pass entitlement template (which activities and how many sessions each) + Pass entitlement covered extra (bundled extras) + Pass price (per-currency price tiers).
- Customer tier — what a specific customer holds: Customer pass (their purchased instance) + Customer entitlement (their per-activity remaining counters).
The customer tier is snapshotted at purchase from the template tier — later edits to the template don’t retroactively change what customers already have.
Boundaries
- In: pass templates, price tiers, customer-held passes and their per-activity counters.
- Out:
Entities
| ID | Entity | Tier | Role |
|---|---|---|---|
| ENT-029 | Pass | Template | The offer — name, validity, pricing config |
| ENT-031 | Pass entitlement template | Template | ”Activity X: N sessions” — one row per included activity |
| ENT-030 | Pass entitlement covered extra | Template | Extras included with each entitlement (e.g. a free towel) |
| ENT-032 | Pass price | Template | Per-currency price tier of a pass |
| ENT-028 | Customer pass | Customer | A specific customer’s purchased instance — status, period, remaining |
| ENT-027 | Customer entitlement | Customer | ”This customer has K bookings left for activity X” — snapshot from template |
Backend implementation
- Module:
libs/features/passes/ - Surface routing:
passes-client.module.ts(customer view of own passes) +passes-admin.module.ts(company manages templates, issues passes, adjusts). - Drizzle schema:
libs/shared/data-access-db/src/lib/schema/passes.schema.ts(pgSchema('passes')).
Cross-context relationships
- This context owns the
passes.*Postgres schema. - This context references:
- This context is referenced by:
- Bookings —
booking.customer_entitlement_id(ON DELETE SET NULL).
- Bookings —
Open questions
- The template/customer split means a pass redesign does not retroactively change existing customer instances. Validate that snapshot logic on edit is complete.
- ON DELETE RESTRICT throughout the template-tier FK graph: a pass with active customer instances cannot be deleted, and an activity included in any entitlement template cannot be deleted.
- OPEN:
pass_entitlement_template (pass_id, activity_id)lacks UNIQUE at the DB level — see Pass entitlement template.