- Entry page shows tickets sold count, remaining, and "in basket" count
- Replace numeric input + Buy button with add-to-basket / +/- controls
- New POST /tickets/adjust/ route creates/cancels tickets to target count
- Keep buy form active after adding (no confirmation replacement)
- New service functions: get_sold_ticket_count, get_user_reserved_count,
cancel_latest_reserved_ticket
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1-3 of decoupling:
- path_setup.py adds project root to sys.path
- Events-owned models in events/models/ (calendars with all related models)
- All imports updated: shared.infrastructure, shared.db, shared.browser, etc.
- Calendar uses container_type/container_id instead of post_id FK
- CalendarEntryPost uses content_type/content_id (generic content refs)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ticket purchase:
- tickets blueprint with routes for my tickets list, ticket detail with QR
- Buy tickets form on entry detail page (HTMX-powered)
- Ticket services: create, query, availability checking
Admin check-in:
- ticket_admin blueprint with dashboard, lookup, and check-in routes
- QR scanner/lookup interface with real-time search
- Per-entry ticket list view
- Check-in transitions ticket state to checked_in
Internal API:
- GET /internal/events/tickets endpoint for cross-app queries
- POST /internal/events/tickets/<code>/checkin for programmatic check-in
Template fixes:
- All templates updated: blog.post.calendars.* → calendars.*
- Removed slug=post.slug parameters (standalone events service)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>