Skip to content

PRD 10 — Check-in & Outlet Access

Status: draft · Priority tier: P1 · Size: M · Depends on: PRD 01 (locations, staff, roles), pricing plans PRD (memberships/packages), class/appointment/course PRDs (their check-in settings), PRD 15 (smart lock, later)

1. Summary

Lets staff confirm that a customer showed up: scan the customer's QR at a chosen location, record manual entries, and automatically check customers in to classes, appointments and courses within a configurable window. Also controls walk-in "outlet access" (gym-style entry): which membership/package plans open which location, an access log, and rules such as outside-hours access. A printable per-location QR sheet supports self-service signage.

2. Problem & goals

Problem: front desk needs a fast, auditable way to know who entered and whether they were entitled to. Goals:

  • Scan-to-result in ≤3 taps after first setup (default location remembered), and result shown in < 2 s.
  • 100% of access attempts (granted, denied, manual) leave a log row.
  • Check-in window and auto-check-in configurable per service type. Non-goals: hardware door control (Later), face recognition, payroll attendance, customer-facing QR in the member app (covered by the customer account PRD; this PRD defines the QR payload only).

3. Users & roles

  • Front desk / staff: scan, manual entry, view logs.
  • Manager/owner: configure outlet access, settings, windows.
  • Customer: shows QR (own account), or scans the location QR.

4. Scope

In (v1)

  • must: Scan Customer screen (select location, camera scanner, result card).
  • must: Check-in on a booking (manual button and auto), with window setting for class, appointment, course.
  • should: Outlet access: plan-to-location mapping, access log list with filters and stat tiles, manual entry, access settings (outside hours, guest contact).
  • should: Download location QR PDF (all locations).
  • could: Bulk import of access entries, audit trail view, default scan location preference. Later (v2+)

  • Smart-lock / door hardware integration (see PRD 15; official API only).

  • Self-service scan of location QR by customer (the original's PDF implies it; behaviour after scan was not observed).
  • Location capacity limit ("access size limit" section existed with no control observed). Out

  • Anything relying on the original's proprietary QR format or its mobile app internals.

5. User stories

  • US-10-01 As front desk, I want to scan a customer's QR, so that I check them in without typing.
  • US-10-02 As front desk, I want to pick my scan location once and have it remembered, so that I do not choose it each time.
  • US-10-03 As a customer, I want to be checked in automatically when I arrive in the window, so that I need no staff action.
  • US-10-04 As a manager, I want to choose which membership and package plans grant entry at each location, so that only paying members get in.
  • US-10-05 As a manager, I want an access log with granted/denied/manual counts, so that I can audit entry.
  • US-10-06 As front desk, I want to add a manual entry for a customer, so that I can record a walk-in or an override.
  • US-10-07 As a manager, I want to allow or block access outside opening hours, so that 24h members can train.
  • US-10-08 As an owner, I want a printable QR sheet per location, so that I can post it at the door.

6. Functional requirements

ID requirement priority evidence
FR-10-01 "Scan Customer" action in the sidebar opens a location picker modal (radio list of locations, "remember my choice" checkbox) must S18, F08
FR-10-02 Scanner screen shows "Scanning for {location}", Change Location, close; uses device camera; shows readable error and manual-code fallback when camera is unavailable must S18; fallback is our addition
FR-10-03 Picker with zero locations shows empty state linking to location creation; Select disabled until a choice is made, with a visible hint must S18 (original did nothing silently)
FR-10-04 Default scan location stored per user; changeable from scanner and profile settings should S18
FR-10-05 Result card after scan: customer name, photo if any, outcome (checked in / access granted / denied + reason), next booking, and a one-tap undo for 10 s must not observed in recon
FR-10-06 Scan resolves customer's QR token to: (a) an upcoming booking at that location within its check-in window, else (b) outlet access entitlement, else denied must S18, S36
FR-10-07 Customer QR is a signed, rotating token (no personal data in the payload) must security; not observed
FR-10-08 Class settings: check-in mode manual or auto; earliest check-in = anytime or N hours before start should S24, class settings
FR-10-09 Appointment settings: segmented manual/auto; earliest check-in anytime or N minutes before should S33
FR-10-10 Course settings (and course option "enable check-in"): auto check-in toggle; window anytime or N hours before should S44
FR-10-11 Per-session override of check-in window in the session's advanced options could 01_core S08 advanced
FR-10-12 Auto check-in marks the booking checked-in when the customer is scanned/arrives inside the window; without a scan it never marks attendance silently (see rule 10.3) must our interpretation; open question
FR-10-13 Manual check-in button on booking rows (class roster, appointment list) respects the same window unless the user has override permission should S12, 08 gapfill
FR-10-14 Outlet access list: per location, assigned pricing plans (membership/package tag), search, location filter should S37, S37b
FR-10-15 Add plans to a location: pick location, search, select all, plans grouped by category, Add should S38, F17
FR-10-16 Access log list: columns customer, location, method (booking/membership/manual), status (granted/denied/cancelled), time; search by name/email, date, location, method, status filters should S36
FR-10-17 Stat tiles over the filtered range: granted, denied, manually added should S36
FR-10-18 Manual entry: choose existing customer or create new, location, note; logged as manual with the staff user should S36b, F16
FR-10-19 Audit trail of a log row (who/when/what changed) could S36c
FR-10-20 Bulk import of access entries via CSV with downloadable template could S36c
FR-10-21 Access setting "allow membership access outside opening hours" (default off); when off, outside-hours scans are denied with reason should S39, F16
FR-10-22 Access setting "collect guest contact details" (name, mobile, email) when a guest is added could S39
FR-10-23 Downloadable PDF with one QR page per location (location name + QR); button shows downloaded state should S19
FR-10-24 Hardware settings button links to PRD 15 hardware integration could S39, S39b

7. Screens

  • Scan modal + scanner (S18): states picker-empty, picker-filled, scanning, camera-error, result (success/denied).
  • Access logs (S36) and add entry (S36b): empty, filtered, filled, error.
  • Outlet access list (S37) and add plans (S38).
  • Access settings (S39).
  • Check-in sections inside class, appointment, course settings (S24, S33, S44) — owned by their PRDs; this PRD owns the fields' semantics.
  • Locations page "Download QR" button (S19), owned by PRD 01 UI.

8. Flows

Scan: sidebar Scan -> (location modal skipped if remembered) -> scanner -> scan -> result. Original 3 clicks; target 1-2 after first time. Plan mapping: Access > Outlet access > Add plans > location > tick > Add (about 5 clicks). Manual entry: Access logs > Manual entry > customer > Save. Edge cases: expired/invalid QR; customer with no entitlement; scanning for the wrong location (deny with the right location suggested); duplicate scan within 60 s (idempotent, shows "already checked in"); offline camera; booking cancelled; customer suspended.

9. Data model

  • AccessLog: id, customer_id, location_id, method (booking|membership|manual), status (granted|denied|cancelled), reason, booking_id?, created_by (staff, for manual), at.
  • OutletAccessPlan: location_id, pricing_plan_id (membership|package).
  • AccessSettings (per business): allow_outside_hours, collect_guest_details.
  • Check-in config fields (owned by class/appointment/course settings): auto_check_in bool, earliest_minutes (null = anytime).
  • Booking.checked_in_at, checked_in_by (staff|auto|customer).
  • UserPreference: default_scan_location_id.
  • CustomerQrToken: customer_id, secret/rotation (guess).

10. Business rules & edge cases

10.1 Entitlement order: matching booking in window first, then outlet access plan, else denied. 10.2 A plan grants access only if active, not expired and has credits (for packages). 10.3 Auto check-in never records attendance without an event (scan, geofence or customer tap); "auto" means the window opens automatically and a scan is accepted without staff confirmation. Alternative reading (time-based auto mark) is an open question. 10.4 Outside opening hours (location hours and holidays from PRD 01): denied unless setting FR-10-21 is on and the plan is a membership. 10.5 Check-in earlier than window start: rejected with the time it opens. 10.6 Denied attempts are always logged. 10.7 Manual entries are flagged and attributed to the staff member.

11. Permissions

  • Scan, manual check-in: Schedule/Bookings edit or "Access logs" edit.
  • Access logs view: Services > Access > Access logs view; manual entry/import: edit.
  • Outlet access + settings: Services > Access > Outlet access/Settings edit.
  • "Override restricted plan" permission allows admitting without entitlement (reason required).
  • QR PDF download: Settings > Locations view.
  • Check-in window settings: edit on the owning service settings.

12. Acceptance criteria

  • AC-01: Given a valid customer QR with a booking starting in 20 min and window 30 min, when scanned at the booking's location, then the booking is checked in and a granted log row exists.
  • AC-02: Given the same booking and window 10 min, then the scan is rejected with "opens in 10 min" and a denied log row exists.
  • AC-03: Given a membership mapped to location L, when scanned at L inside opening hours, then access is granted; at other location, denied.
  • AC-04: Given outside-hours off, when a member scans after closing, then denied with reason "outside opening hours".
  • AC-05: Given remember-location was ticked, when I open Scan again, then the scanner starts directly at that location.
  • AC-06: Given a camera error, then a message and manual code entry are shown.
  • AC-07: Given 3 granted, 1 denied, 2 manual rows in range, then tiles show 3 / 1 / 2.
  • AC-08: Given a user without Access edit, then manual entry returns 403.
  • AC-09: Given two locations, the PDF has two QR pages with the matching location names.

13. Dependencies & open questions

Depends on PRD 01, pricing plans, services PRDs. Open:

  • Result UI after scan was not observable (headless, no camera): our result card is a design guess.
  • What happens when a customer scans the printed location QR was not observed.
  • Meaning of "auto check-in" (see 10.3).
  • "Location access size limit" section had no controls; capacity logic is Later.
  • Access log columns were not observed (empty data); columns are inferred.
  • Whether access consumes package credits per entry.
  • Camera library choice (web) and fallback on desktop.

14. Evidence

See evidence/evidence.md.