""" Ticket admin blueprint — check-in interface and ticket management. Routes: GET /admin/tickets/ — Ticket dashboard (scan + list) GET /admin/tickets/entry// — Tickets for a specific entry POST /admin/tickets//checkin — Check in a ticket GET /admin/tickets// — Ticket admin detail """ from __future__ import annotations import logging from quart import ( Blueprint, g, request, make_response, ) from sqlalchemy import select from sqlalchemy.orm import selectinload from models.calendars import CalendarEntry from shared.browser.app.authz import require_admin from shared.browser.app.redis_cacher import clear_cache from shared.sx.helpers import sx_response from ..tickets.services.tickets import ( get_ticket_by_code, get_tickets_for_entry, checkin_ticket, ) logger = logging.getLogger(__name__) def register() -> Blueprint: bp = Blueprint("ticket_admin", __name__, url_prefix="/admin/tickets") @bp.get("/entry//") @require_admin async def entry_tickets(entry_id: int): """List all tickets for a specific calendar entry.""" from shared.browser.app.utils.htmx import is_htmx_request entry = await g.s.scalar( select(CalendarEntry) .where( CalendarEntry.id == entry_id, CalendarEntry.deleted_at.is_(None), ) .options(selectinload(CalendarEntry.calendar)) ) if not entry: return await make_response("Entry not found", 404) tickets = await get_tickets_for_entry(g.s, entry_id) from sxc.pages.tickets import render_entry_tickets_admin html = render_entry_tickets_admin(entry, tickets) return sx_response(html) @bp.get("/lookup/") @require_admin async def lookup(): """Look up a ticket by code (used by scanner).""" code = request.args.get("code", "").strip() if not code: return await make_response( '
Enter a ticket code
', 200, ) ticket = await get_ticket_by_code(g.s, code) from sxc.pages.tickets import render_lookup_result if not ticket: return sx_response(render_lookup_result(None, "Ticket not found")) return sx_response(render_lookup_result(ticket, None)) @bp.post("//checkin/") @require_admin @clear_cache(tag="calendars", tag_scope="all") async def do_checkin(code: str): """Check in a ticket by its code.""" success, error = await checkin_ticket(g.s, code) from sxc.pages.tickets import render_checkin_result if not success: return sx_response(render_checkin_result(False, error, None)) ticket = await get_ticket_by_code(g.s, code) return sx_response(render_checkin_result(True, None, ticket)) return bp