# Dominio Ticket ## Propósito Genera, valida, consulta y exporta entradas asociadas a compras pagadas de productos o variantes ticketables. ## Modelo - `Ticket`: pertenece a tenant y usuario, y conserva referencias al ítem de compra que lo generó, producto, variante y usuario escáner. La compra se obtiene a través de su ítem. - El nombre y la descripción se calculan dinámicamente desde el producto y la variante; los tickets no persisten una copia de esos textos. - `ValidityTime`: define ventanas absolutas o relativas de vigencia para fechas de evento y opciones de atributos. - `ValidityTimeType`: enum de estrategias de vigencia. `TicketValidityResolver` deriva la vigencia desde la variante asociada. Las alternativas de un mismo atributo se combinan con OR y las dimensiones diferentes se combinan con AND. El modelo calcula si un ticket está vigente, vencido o usado, y resuelve sus fechas efectivas de inicio y fin sin persistir vigencias en el ticket. ## Flujo de generación 1. `Purchase` emite `PurchasePaid` al confirmarse el pago. 2. `GenerateTicketsForPaidPurchase` atiende el evento. 3. `TicketGeneratorService` crea los tickets requeridos según ítems, cantidades y vigencia. 4. `Notification` envía la confirmación de compra después de la generación y adjunta los tickets cuando existen. ## Datos descartables para pruebas de carga En ambientes `local`, `testing`, `staging`, `homo` u `homologation`, el comando siguiente crea tickets válidos, identidades scanner con tokens Sanctum y un dataset JSON importable por Postman: ```bash php artisan load-test:tickets:prepare loadtest-evento \ --tickets=40000 \ --scanners=100 \ --owners=1000 \ --catalog-item=123 \ --run=evento-001 ``` El tenant debe existir y se recomienda que sea exclusivo para carga. Si no se indica `--catalog-item`, se usa el primer producto estándar del tenant con tickets habilitados. `--variant` es opcional; al indicarlo, su configuración de vigencia debe estar activa y ser resoluble. Sin variante, los tickets tienen vigencia irrestricta. El archivo se escribe por defecto en `storage/app/private/load-tests/` y contiene tokens secretos, por lo que no debe versionarse. Para limpiar el tenant después de la ejecución: ```bash php artisan tenants:reset-transactions loadtest-evento --dry-run php artisan tenants:reset-transactions loadtest-evento ``` ## Endpoints Bajo `/tenants/{tenant:codigo}`, protegidos por `auth:sanctum`: - `GET /tickets`. - `POST /tickets/pdf`. Bajo `/v1/adminapp/tenant`, protegido por `auth:sanctum`, `adminapp.tenant` y el menú `adminapp.tickets`: - `GET /tickets`, paginado y con búsqueda opcional mediante `q`. La respuesta incluye `scanned_tickets` y `total_tickets` para el tenant autenticado. `TicketPdfService` genera la descarga y `TicketResource`/`ValidityTimeResource` definen las respuestas. ## Dependencias y reglas Depende de `Purchase`, `Catalog`, `Tenant` y `Auth`. La generación debe ser idempotente ante reintentos del evento. `TicketNotAvailableException` y `TicketGenerationException` separan indisponibilidad de errores de generación.