Files
azionelab/docs/domain-model.md

6.2 KiB

Domain Model

This document describes the core domain concepts for AzioneLab's theatre website and booking system.

Show

A show is a theatrical production presented by the company.

Suggested fields:

  • id: internal identifier;
  • title: public show title;
  • slug: stable public URL identifier;
  • summary: short public description;
  • description: full public description;
  • poster_image: optional public image;
  • is_published: controls public visibility;
  • created_at: creation timestamp;
  • updated_at: last update timestamp.

Relationships:

  • one show can have many performances.

Rules:

  • unpublished shows are not listed publicly;
  • a public show detail page may include only published upcoming performances.

Venue

A venue is the place where a performance happens.

Suggested fields:

  • id: internal identifier;
  • name: public venue name;
  • slug: stable public URL identifier;
  • address: public address;
  • city: venue city;
  • notes: optional public or internal venue notes;
  • created_at: creation timestamp;
  • updated_at: last update timestamp.

Relationships:

  • one venue can host many performances.

Performance

A performance is a scheduled presentation of one show at one venue.

Suggested fields:

  • id: internal identifier;
  • show: required reference to Show;
  • venue: required reference to Venue;
  • starts_at: performance date and time;
  • room_capacity: configured total room capacity;
  • manually_occupied_seats: seats unavailable because they are reserved outside the public booking system;
  • additional_seats: optional extra seats made available during booking;
  • is_booking_enabled: controls whether public booking is open;
  • created_at: creation timestamp;
  • updated_at: last update timestamp.

Relationships:

  • each performance belongs to one show;
  • each performance belongs to one venue;
  • one performance can have many reservations.

Availability formula:

available seats =
  room capacity
  + additional seats
  - manually occupied seats
  - confirmed reservations

Rules:

  • capacity values must not be negative;
  • manually_occupied_seats must not exceed room_capacity + additional_seats;
  • only confirmed reservations reduce public availability;
  • pending reservations do not guarantee a seat until confirmation;
  • final capacity validation must happen server-side when confirming a reservation;
  • changes to capacity configuration must preserve existing confirmed reservations.

Reservation

A reservation is a booking request for a specific performance.

Suggested fields:

  • id: internal identifier;
  • performance: required reference to Performance;
  • status: explicit status such as pending, confirmed, cancelled, or expired;
  • name: reservation contact name;
  • email: reservation contact email;
  • phone: optional reservation contact phone;
  • party_size: number of requested seats;
  • notes: optional visitor note;
  • confirmed_at: timestamp set when the reservation is confirmed;
  • qr_code_generated_at: timestamp set when the QR code is generated;
  • created_at: creation timestamp;
  • updated_at: last update timestamp.

Relationships:

  • each reservation belongs to one performance;
  • one reservation can have one or more reservation tokens for different purposes;
  • one confirmed reservation can have at most one successful check-in.

Rules:

  • a new reservation starts as pending;
  • a reservation becomes confirmed only through a valid confirmation token;
  • a confirmed reservation receives a QR code;
  • party_size must be positive;
  • the backend must reject confirmation if the requested seats would exceed availability;
  • personal data must never be stored in QR codes.

ReservationToken

A reservation token is an opaque token used for confirmation or QR verification.

Suggested fields:

  • id: internal identifier;
  • reservation: required reference to Reservation;
  • purpose: token purpose, such as confirmation or check_in;
  • token_hash: server-side hash of the opaque token;
  • expires_at: optional expiration timestamp;
  • used_at: timestamp set when a one-time token is consumed;
  • created_at: creation timestamp.

Relationships:

  • each token belongs to one reservation.

Rules:

  • raw tokens must be random, non-guessable, and generated with a cryptographically secure generator;
  • store only a hash of the token when practical;
  • confirmation tokens should be single use;
  • QR tokens may remain valid until the performance check-in window closes;
  • tokens must not encode personal data.

CheckIn

A check-in records entrance validation for a confirmed reservation.

Suggested fields:

  • id: internal identifier;
  • reservation: required unique reference to Reservation;
  • checked_in_at: timestamp of successful check-in;
  • checked_in_by: required authenticated staff user reference for successful check-in;
  • source: optional source such as qr_scan or manual;
  • created_at: creation timestamp;
  • updated_at: last update timestamp.

Relationships:

  • each check-in belongs to one reservation;
  • a reservation can have at most one successful check-in.

Rules:

  • check-in is performed only by authenticated staff or admin users;
  • staff use a mobile-friendly web page to scan the QR code or enter the token manually;
  • the QR code contains only an opaque verification token or URL;
  • the backend validates the token server-side;
  • only confirmed reservations can be checked in;
  • a reservation cannot be checked in twice;
  • successful check-in creates a CheckIn record, or updates an existing incomplete check-in record for the same reservation;
  • successful check-in records must include checked_in_at and checked_in_by;
  • failed check-in attempts should return a clear status without changing successful check-in state;
  • check-in must not expose unnecessary personal data to scanning clients.

Anti-Overbooking Rule

The backend must enforce capacity inside a transaction when confirming reservations.

Recommended approach:

  • lock the relevant Performance row during confirmation;
  • count confirmed seats for that performance;
  • compare requested seats with available seats;
  • confirm only if enough seats remain;
  • otherwise leave the reservation pending or mark it as expired/rejected according to the future product decision.