Event finance
- Finance tab on the event page: P&L summary with a revenue-to-result
waterfall, costs and other income in one ledger, and the partner split
with payouts. Lifecycle stepper (Selling, Adding costs, Ready to close,
Finalized) with what is left to do; closing the books goes through a
checklist dialog that freezes the numbers.
- Expense modal shows only the fields each calculation type needs, a live
preview with the event's real counts, and a category suggested from the
description. Date inputs follow the UI language.
- Global Finance page: profit per event with outliers clipped and labelled,
and a "Ready to close" list of past events whose books are still open.
- Calculation service (integer PYG, basis points) with pinned regression
scenarios; PYG formatting centralised in lib/money with locale-aware
separators.
Event team permissions
- Per-event members with role presets and requireEventPermission; the
header stat "Confirmed" is relabelled "Not checked in yet", which is
what it counts.
Public sales state
- One sales state (online, door, sold out, ended, external, cancelled) for
the event page, listings and JSON-LD, with the door price and tenders
shown only while people can still pay at the door.
Frontend unit tests run with vitest (npm test in frontend/).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Events gain nullable presale_closure_enabled / presale_close_minutes_before
overrides; null inherits the new site_settings defaults (enabled, 120 min).
A shared resolver computes the effective cutoff, which the public event API
exposes as presaleClosesAt and the public booking endpoint enforces. Door and
admin ticket creation are not gated.
Admin: toggle + duration picker in the event modal (pre-filled from the site
default) and a matching default card on Settings › General. Public: the event
page shows "Registration Closed" after the cutoff and the checkout page
redirects back.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- Add in-memory email queue with rate limiting (MAX_EMAILS_PER_HOUR)
- Bulk send to event attendees now queues and returns immediately
- Frontend shows 'Emails are being sent in the background'
- Legal pages, settings, and placeholders updates
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add featured_event_id to site_settings (schema + migration)
- Backend: featured event logic in /events/next/upcoming with auto-unset when event ends
- Site settings: PUT supports featuredEventId, add PUT /featured-event for admin
- Admin events: Set as featured checkbox in editor, star toggle in list, featured badge
- Admin settings: Featured Event section with current event and remove/change links
- API: siteSettingsApi.setFeaturedEvent(), Event.isFeatured, SiteSettings.featuredEventId
- Homepage/linktree unchanged: still use getNextUpcoming (now returns featured or fallback)
- Add ticket validation and check-in API endpoints
- Add PDF ticket generation with QR codes (pdfkit)
- Add admin QR scanner page with camera support
- Add admin site settings page
- Update email templates with PDF ticket download link
- Add checked_in_by_admin_id field for audit tracking
- Update booking success page with ticket download
- Various UI improvements to events and booking pages