feat: yoyaku_checkin: scan a ticket QR at the door to mark attendance
Adds the yoyaku_checkin submodule: an operator scans a ticket's signed QR token and each confirmed booking it names is completed through the engine's existing complete(), so marking attendance needs no new booking state.
Closes #3611639.
Two ways to scan, one code
A ticket's QR now encodes a short, opaque check-in URL carrying the token in its path (/yykchkn/<token>), so it stays small and does not expose the administration path.
- Native camera - any phone's normal camera opens the URL and admits the holder on the spot (for staff signed in with the permission).
- Kiosk scanner page (
/yykchkn, Administration › Booking › Check in) - the in-page camera reads the same QR over AJAX and extracts the token back out of the URL; a manual field is the fallback for a damaged QR or no camera.
Feedback
Each scan gives tri-state feedback plus the order summary:
- Green banner + clean chime: checked in.
- Red banner + loud alert: already used, naming who used it and when.
- Yellow banner + soft tone: refused (invalid, expired, gone, not confirmed, or scanned outside the event's day(s)).
Check-in is allowed only on the event's calendar day(s); the token's own expiry remains the hard cap. Every completion is logged (booking, operator, time) so a re-scan can report who admitted the code. A dedicated check in tickets permission gates the page and URL.
Layering
yoyaku_ticket gains a hook_yoyaku_ticket_qr_payload_alter seam (documented in its .api.php) so it stays unaware of check-in: with the submodule absent, the QR keeps encoding the bare token.
Tests
Kernel coverage for the tri-state outcomes, the wrong-day block, invalid/not-found tokens, and the QR-payload seam.