Backend: POST /api/events/checkin — body { "code": "<ticket/check-in code>", "eventId": "<optional>" }. Code-based (looks up by checkInCode or displayTicketCode); there is no /:id/check-in route. Guard: EVENTS:EDIT:registrations (ADMIN / EVENT_MANAGER). Validations: returns 402 if the linked invoice is unpaid; 409 if already checked in. ⚠️ The old "same-day only" restriction was removed (#342) — admins can now check attendees in regardless of the event date.
Frontend: /admin/events/check-in (event selector) → /admin/events/:eventId/check-in (pages/AdminEventCheckInPage.tsx → EventCheckInPanel: QR camera + manual code entry + stats + recent check-ins).
Prerequisites
Login as events@demo.membervu.com / Events123! (EVENT_MANAGER) or admin@rcme.membervu.com / Admin123!.
An event dated today with registered attendees. The seed always creates RCME Check-in Test Event (free, today) — register a member for it first (TC-EVT-002) so there's a ticket code to scan. (The former same-day-only rule was removed in #342 — a past/future event can now be checked into as well.)
Test Cases
TC-CHK-01: Select Event for Check-In
Step
Action
Expected Result
1
Go to /admin/events/check-in (sidebar Events → Check-in).
An event selector appears (search/list of events).
2
Pick today's event (e.g. RCME Check-in Test Event).
Navigates to /admin/events/:eventId/check-in: event header + check-in panel (QR scanner, manual entry, stats: Total Registered / Checked-In, recent list).
TC-CHK-02: Manual Check-In (Valid Code)
Step
Action
Expected Result
1
Get a valid code: register a member for the event (TC-EVT-002), open their My Ticket — note the ticket/check-in code.
Code available.
2
In the manual-entry field, type the code → Check In.
POST /api/events/checkin with {code, eventId}. Success toast + attendee name; checked-in count increments; registration status → CHECKED_IN.
3
Enter the same code again.
409 — "Already checked in" warning.
TC-CHK-03: QR Scan Check-In
Step
Action
Expected Result
1
Allow camera access; point the scanner at a member's ticket QR.
Scanner reads the code and auto-submits to /api/events/checkin.
2
Observe.
"Checked In" confirmation; panel resets for the next scan.
TC-CHK-04: Invalid / Wrong-Event Code
Step
Action
Expected Result
1
Enter a random string, or a valid code from a different event.
Error — code not found / not valid for this event.
TC-CHK-05: Unpaid Attendee (Paid Event)
Step
Action
Expected Result
1
For a paid event today, attempt to check in an attendee whose invoice is unpaid.
402 — payment required; check-in is blocked until the invoice is paid. (Live payment is parked — use a free event for the happy path.)
TC-CHK-06: No Same-Day Restriction (#342 — corrected)
✅ Behavior changed (#342): the same-day-only check-in restriction was removed. This TC now asserts the absence of that restriction — do not file a bug expecting a past/future check-in to be rejected.
Step
Action
Expected Result
1
Select a past or future event with a valid ticket code and check the attendee in.
Check-in succeeds (status → CHECKED_IN); there is no date-based rejection. Only the unpaid-invoice (402) and already-checked-in (409) guards apply.
TC-CHK-07: Permission
Step
Action
Expected Result
1
As a plain MEMBER, call POST /api/events/checkin.
403 (lacks EVENTS:EDIT:registrations); the Check-in page is not in the member sidebar.
Manual attendance (no code)
An admin can also mark attendance directly from the attendance report without a code: POST /api/events/admin/attendance/:registrationId/mark (and /undo, /bulk-mark). See TC-EVT-007 (Reporting/Attendance).