Skip to content

feat(events): QR code check-in #246

@danielhe4rt

Description

@danielhe4rt

Parent

#237

What to build

Implement QR code check-in: system generates a unique QR token per enrollment on confirmation, organizer scans it to check participant in. Token is reusable across event days.

QR Token generation:

  • When enrollment transitions to confirmed: automatically generate a unique token in events_qr_tokens
  • Token format: URL-safe random string (32+ chars), unique across all tokens
  • Optional expires_at (nullable — if null, valid for event lifetime)
  • One token per enrollment (created once, reused per day)

Extend CheckInAction (qr_code path):

  • Input: token string + event_date (date derived from scan time)
  • Validates: token exists and belongs to an enrollment in this event
  • Validates: enrollment status is confirmed or checked_in
  • Validates: token not expired (expires_at IS NULL OR expires_at > now())
  • Validates: no check-in for this enrollment + date yet
  • Creates check-in record with method=qr_code, payload={token: "..."}
  • Same status transition logic as other methods
  • Dispatches ParticipantCheckedIn

Admin panel — Scan interface:

  • "Scan QR" page/action accessible from Event resource
  • Input field for token (simulates scan — actual camera integration is frontend concern)
  • Shows participant name + status on successful scan
  • Error display for invalid/expired tokens

App panel — QR display:

  • "My QR Code" section on enrollment detail (visible when status=confirmed or checked_in)
  • Renders QR code image from token (using a QR library or inline SVG generation)
  • Shows "Present this QR to the organizer" instruction

Token lifecycle:

  • Generated on confirmed transition
  • NOT regenerated on subsequent transitions (e.g., checked_in → stays same token)
  • If enrollment is cancelled: token can be soft-invalidated (or just check enrollment status on scan)

Acceptance criteria

  • QR token is auto-generated when enrollment reaches confirmed status
  • Token is unique and URL-safe
  • Organizer can scan/input token and check participant in
  • Same token works across multiple event days (creates new check-in per day)
  • Expired token is rejected
  • Duplicate scan on same day is rejected
  • Cancelled enrollment's token is rejected on scan (status check)
  • Participant sees their QR code in App panel
  • Check-in record stores method=qr_code with token in payload
  • ParticipantCheckedIn domain event dispatched
  • Feature tests: generate token, valid scan, expired token, duplicate scan, cancelled enrollment scan, multi-day reuse
  • Pint passes

Blocked by

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions