# Feature Specification: Event Management App

**Feature Branch**: `001-event-management-app`

**Created**: 2026-05-30

**Status**: Draft

**Input**: User description: "Build an event management application. Each event is a single, unique occasion with a cover image and a description. Events support registrations with multiple ticket categories (e.g., student discounts, corporate partnerships). As the event date approaches, the system must allow ticket sales to transition between different batches. Each purchase must generate a checkout page displaying the relevant payment details. The system requires a backend administrative panel to manage each event and process manual ticket sales. Upon payment confirmation, a confirmation ticket must be generated and sent to the attendee, which is triggered via a manual approval action in the backend."

## Clarifications

### Session 2026-05-30
- Q: Should the system integrate with the local MLX Server for LLM operations? → A: No, remove the local MLX component from the app entirely.
- Q: Should manual payment instructions be configured globally or per-event? → A: Globally (Option A).
- Q: How should we ensure the 10s SLA for sending confirmation tickets? → A: Implement a background queue worker task (Option B).

### Session 2026-06-26
- Q: How should we consolidate the duplicated checkout requirements in spec.md? → A: Keep only ASAAS (Pix & Credit Card) and the event-specific Direct PIX configuration, and prune the outdated manual/offline global fallback section.
- Q: How should the webhook verify that the payment notifications are authentically sent by ASAAS? → A: Validação de Token de Cabeçalho (ASAAS Access Token) contra uma chave armazenada no ambiente.
- Q: Should the extended registration form fields (Nationality, Phone, Country, State, City, OAB) be mandatory or optional? → A: Confirmação de E-mail e CPF obrigatórios; os demais campos estendidos (Nacionalidade, Telefone Celular, País, Estado, Cidade, OAB) são opcionais.

## User Scenarios & Testing *(mandatory)*

### User Story 1 - Attendee Event Registration & Checkout (Priority: P1)
An attendee discovers an event, selects their ticket category and batch, and completes registration choosing between Pix or Credit Card.

**Acceptance Scenarios**:
1. **Given** an active event, **When** the attendee selects a ticket, enters their CPF and selects Pix, **Then** the system creates an order, communicates with ASAAS, and displays the Pix QR Code and Copy-Paste string.
2. **Given** an active event, **When** the attendee selects a ticket, enters their CPF and selects Credit Card, **Then** the system redirects the user to the ASAAS secure hosted checkout page.

### User Story 2 - Automated Payment Approval via Webhook (Priority: P1)
The system receives an asynchronous notification from ASAAS confirming payment, updates the order, and automatically issues the ticket.

**Acceptance Scenarios**:
1. **Given** a pending order awaiting Pix or Credit Card payment, **When** the ASAAS webhook POSTs a payment confirmation to the system, **Then** the order status changes to approved and a confirmation ticket is emailed to the attendee.

### User Story 3 - Admin Event Management (Priority: P2)
An administrator creates a new event, configures the cover image, and sets up ticket categories and date-based batches.

**Acceptance Scenarios**:
1. **Given** admin access, **When** the admin creates an event with a "Student" category and an "Early Bird" batch ending tomorrow, **Then** the event is successfully saved and available publicly.

### User Story 4 - Admin Manual Ticket Sales (Priority: P3)
An administrator manually processes a ticket sale directly from the backend for attendees paying in person (bypassing ASAAS).

**Acceptance Scenarios**:
1. **Given** a walk-in attendee, **When** the administrator enters their details into the manual sale form, **Then** an approved order is created and the ticket is generated immediately.

### Edge Cases
- What happens when a user tries to register exactly as a ticket batch expires?
- How does the system handle an administrator approving an order that was already cancelled by the user?

## Requirements *(mandatory)*

### Functional Requirements
- **FR-001**: System MUST allow administrators to create single-occasion events with a title, cover image, and description.
- **FR-002**: System MUST allow administrators to define multiple ticket categories (e.g., Student, Corporate) for an event.
- **FR-003**: System MUST allow administrators to define pricing batches tied to specific date ranges, linked to ticket categories.
- **FR-004**: System MUST automatically transition active ticket batches based on the current date, hiding expired batches and showing active ones.
- **FR-005**: System MUST provide a public registration page where attendees can select active tickets and submit their details. Nome, E-mail, Confirmar E-mail, and CPF are mandatory; Nationality, Phone, Country, State, City, and OAB are optional.
- **FR-006**: System MUST allow configuring a Direct PIX option per event with custom payment instructions, creating pending orders for manual approval.
- **FR-007**: System MUST provide a backend administrative panel to view and manage pending orders.
- **FR-008**: System MUST allow administrators to manually approve pending orders.
- **FR-009**: System MUST generate a confirmation ticket and send it to the attendee (via email) immediately upon manual order approval.
- **FR-010**: System MUST allow administrators to manually record and approve a ticket sale entirely from the backend interface.
- **FR-011**: System MUST be fully localized in Brazilian Portuguese (pt-BR) across all frontend and backend interfaces.
- **FR-012**: System MUST integrate with the ASAAS API to create or retrieve customers using the attendee's email and CPF/CNPJ.
- **FR-013**: System MUST allow attendees to select Pix or Credit Card during checkout.
- **FR-014**: For Pix, system MUST generate the charge in ASAAS, fetch the QR Code image and Copy-Paste string, and display them on a transparent checkout page.
- **FR-015**: For Credit Card, system MUST generate the charge and redirect the user to the `invoice_url` provided by ASAAS (Hosted Checkout).
- **FR-016**: System MUST expose a secure, public-facing Webhook endpoint (`POST /webhooks/asaas`) to receive asynchronous payment status updates, validating each request using a pre-configured ASAAS access token sent in the headers.
- **FR-017**: Upon receiving a successful payment payload via webhook, system MUST automatically change order status to APPROVED and dispatch the ticket email.
- **FR-018**: System MUST allow administrators to manually approve orders or record offline sales as a fallback.

### User Story 5 - Attendee Ticket Check-In via QR Code (Priority: P1)
An event receptionist scans the QR code from the attendee's ticket (or inputs the ticket code manually) to verify its validity and check them in.

**Acceptance Scenarios**:
1. **Given** a valid confirmed ticket, **When** the receptionist scans the QR code, **Then** the screen displays the attendee's details, the event name, ticket category, and status.
2. **Given** a ticket displayed on the check-in screen, **When** the receptionist clicks "Confirmar Check-in", **Then** the ticket's check-in timestamp (`checked_in_at`) is recorded, and a success message is shown.
3. **Given** a ticket that has already been checked in, **When** the receptionist scans the QR code, **Then** the system displays a prominent warning indicating the check-in date/time and prevents duplicate check-ins.

### User Story 6 - Receptionist Access Control (Priority: P2)
A user with the role of `recepcao` (receptionist) logs into the admin panel and can only access the check-in page, being restricted from any other admin dashboards, user management, or event configurations.

**Acceptance Scenarios**:
1. **Given** a user logged in with the `recepcao` role, **When** they access `/admin` or `/admin/`, **Then** the system automatically redirects them to `/admin/checkin`.
2. **Given** a user logged in with the `recepcao` role, **When** they try to access restricted paths like `/admin/events`, `/admin/users`, or `/admin/configuracoes`, **Then** the system returns a 403 Forbidden page.
3. **Given** a user logged in with `superadmin`, `administrador`, or `financeiro`, **When** they access `/admin/checkin`, **Then** they are allowed access to verify tickets and perform check-ins.

### User Story 7 - Participant Check-In Report (Priority: P2)
An administrator views a report of participants for an event, showing total registrations, check-in status, and has the ability to export the list as a CSV file.

**Acceptance Scenarios**:
1. **Given** an admin logged in with `superadmin`, `administrador`, or `financeiro` role, **When** they view the report for an event, **Then** they see total registrations, total check-ins, the check-in rate (%), and a detailed list of attendees with their check-in timestamps.
2. **Given** the report page, **When** the admin clicks "Exportar CSV", **Then** the system generates and downloads a CSV file containing participant names, emails, documents, categories, batches, and check-in statuses/timestamps.

### User Story 8 - Participant Badge Printing (Priority: P2)
An administrator or receptionist verifies a participant during check-in, and the system automatically generates a PDF badge to print on a custom-sized label (default 8x4 cm) containing only the attendee's name.

**Acceptance Scenarios**:
1. **Given** a successful check-in, **When** the check-in is confirmed, **Then** the system generates a PDF badge according to the event's configured dimensions and automatically triggers the print dialog.
2. **Given** a checked-in ticket, **When** the user accesses the badge print URL, **Then** the system returns a PDF file containing the attendee's name centered.

## Edge Cases
- What happens when a user tries to register exactly as a ticket batch expires?
- How does the system handle an administrator approving an order that was already cancelled by the user?
- What happens if the receptionist scans a ticket code that does not exist in the database?
- What happens if a ticket is scanned but the order status is not APPROVED? (Note: Tickets should only exist for approved orders, but validation should fail gracefully).

## Requirements *(mandatory)*

### Functional Requirements
- **FR-001**: System MUST allow administrators to create single-occasion events with a title, cover image, and description.
- **FR-002**: System MUST allow administrators to define multiple ticket categories (e.g., Student, Corporate) for an event.
- **FR-003**: System MUST allow administrators to define pricing batches tied to specific date ranges, linked to ticket categories.
- **FR-004**: System MUST automatically transition active ticket batches based on the current date, hiding expired batches and showing active ones.
- **FR-005**: System MUST provide a public registration page where attendees can select active tickets and submit their details. Nome, E-mail, Confirmar E-mail, and CPF are mandatory; Nationality, Phone, Country, State, City, and OAB are optional.
- **FR-006**: System MUST allow configuring a Direct PIX option per event with custom payment instructions, creating pending orders for manual approval.
- **FR-007**: System MUST provide a backend administrative panel to view and manage pending orders.
- **FR-008**: System MUST allow administrators to manually approve pending orders.
- **FR-009**: System MUST generate a confirmation ticket and send it to the attendee (via email) immediately upon manual order approval.
- **FR-010**: System MUST allow administrators to manually record and approve a ticket sale entirely from the backend interface.
- **FR-011**: System MUST be fully localized in Brazilian Portuguese (pt-BR) across all frontend and backend interfaces.
- **FR-012**: System MUST integrate with the ASAAS API to create or retrieve customers using the attendee's email and CPF/CNPJ.
- **FR-013**: System MUST allow attendees to select Pix or Credit Card during checkout.
- **FR-014**: For Pix, system MUST generate the charge in ASAAS, fetch the QR Code image and Copy-Paste string, and display them on a transparent checkout page.
- **FR-015**: For Credit Card, system MUST generate the charge and redirect the user to the `invoice_url` provided by ASAAS (Hosted Checkout).
- **FR-016**: System MUST expose a secure, public-facing Webhook endpoint (`POST /webhooks/asaas`) to receive asynchronous payment status updates, validating each request using a pre-configured ASAAS access token sent in the headers.
- **FR-017**: Upon receiving a successful payment payload via webhook, system MUST automatically change order status to APPROVED and dispatch the ticket email.
- **FR-018**: System MUST allow administrators to manually approve orders or record offline sales as a fallback.
- **FR-019**: System MUST generate a QR code for each confirmed ticket, representing its unique ticket code.
- **FR-020**: System MUST render the generated QR code on the printable ticket view.
- **FR-021**: System MUST provide a unified administrative check-in screen (`/admin/checkin`) that allows looking up ticket codes manually or scanning QR codes via webcam.
- **FR-022**: System MUST restrict users with the `recepcao` role to ONLY access `/admin/checkin` (and login/logout), redirecting `/admin` to `/admin/checkin` and returning 403 Forbidden for other routes.
- **FR-023**: System MUST record the date and time of check-in (`checked_in_at` field in tickets table) when a ticket is checked in.
- **FR-024**: System MUST provide an attendance report page (`/admin/events/{id}/report`) with a CSV export option, accessible by `superadmin`, `administrador`, and `financeiro`, but restricted for `recepcao`.
- **FR-025**: System MUST allow configuring the badge height and width in centimeters per event.
- **FR-026**: System MUST generate a PDF file containing ONLY the attendee's name centered horizontally and vertically for badge printing.
- **FR-027**: The generated badge PDF dimensions MUST dynamically scale to the configured width and height in points (where 1 cm = 28.346 points) based on the event's dimensions.
- **FR-028**: Upon successful check-in, the system MUST automatically launch the generated PDF badge in a browser print flow.

### Key Entities
- **Event**: Represents the unique occasion, containing the cover image and description.
- **Ticket Category**: Represents the type of attendee (e.g., Student, General).
- **Ticket Batch**: Represents a pricing tier linked to a category, bound by a start and end date.
- **Order/Registration**: Represents an attendee's intent to purchase, holding their details, selected batch, and payment status.
- **Ticket**: The final confirmed pass generated for the attendee, containing `ticket_code` and `checked_in_at` check-in timestamp.

## Success Criteria *(mandatory)*
- **SC-001**: Administrators can successfully create a multi-batch, multi-category event in under 5 minutes.
- **SC-002**: Attendees can complete the registration process and view the Pix QR code or be redirected to ASAAS in under 2 minutes.
- **SC-003**: System correctly transitions 100% of ticket batches exactly on their scheduled dates without manual intervention.
- **SC-004**: Confirmation tickets are sent to attendees within 10 seconds of the webhook confirming payment.
- **SC-005**: Receptionists can scan/verify a ticket and complete the attendee check-in in under 5 seconds.
- **SC-006**: Administrators can generate and download the attendee report in under 3 seconds.
- **SC-007**: System generates the custom badge PDF and triggers browser print setup in under 3 seconds after check-in confirmation.

## Assumptions
- **Payment Processing**: The system relies on the ASAAS API for automated billing (Pix and Credit Card). Manual approval remains only as a box-office fallback.
- **PCI Compliance**: Credit card data is never handled directly by the application frontend; it is deferred to the ASAAS hosted checkout page to ensure maximum security.

## Out of Scope
- **LLM/MLX Integration**: AI features (like auto-generating event descriptions via a local MLX server) have been explicitly removed from the application scope.

