# RegiTicket — Cursor AI Agent Guide

> **Product**: RegiTicket — SaaS profesional de venta de entradas y gestión de eventos (Puerto Rico y LATAM)
> **Stack**: Laravel 11 · PHP 8.2+ · MySQL · Blade · Bootstrap 5 · Vite · Alpine.js · Stripe · PayPal
> **Estado actual**: ~35% completado. Meta de entrega: 50% funcional.
> **Fecha de referencia**: Mayo 2026

---

## 1. PROPÓSITO Y CONTEXTO DE NEGOCIO

RegiTicket es una plataforma SaaS multi-tenant para creación, venta y gestión de eventos de cualquier tipo:
- Carreras atléticas / running (timing, chips, bibs)
- Conciertos y música
- Eventos corporativos y conferencias
- Festivales y experiencias

### Competencia directa (estudiarla para superarla):
- https://www.eventrid.com.pr/organizador — referencia principal de UX para organizadores
- https://micarrerapr.com/events — especializado en running/atletismo
- https://tiempodellegadapr.com/ — timing para carreras

### Diferenciadores de RegiTicket:
1. **Carga manual de asistentes** — los organizadores pueden registrar participantes sin pago (gap crítico que la competencia no tiene)
2. **Payout automático** a PayPal o Stripe cuando se completa cada orden
3. **Check-in QR profesional** con panel en tiempo real
4. **Multi-pago** sin lock-in a un solo gateway
5. **Precios transparentes**: la plataforma retiene **$2.99 USD + 5% por venta**

### Modelo de comisión (REGLA DE NEGOCIO CRÍTICA):
```
Si ticket = $25.00
  platform_fee = $2.99 + ($25.00 × 0.05) = $2.99 + $1.25 = $4.24
  net_organizer = $25.00 - $4.24 = $20.76
```
El remanente se envía automáticamente al PayPal o Stripe del organizador al completarse la orden.

---

## 2. ARQUITECTURA DEL SISTEMA

### Estructura de directorios clave:
```
app/
  Console/Commands/           ← Artisan commands
  Http/
    Controllers/
      Dashboard/              ← Controladores del panel admin/organizador
      Auth/                   ← Auth controllers (Laravel UI)
    Middleware/               ← AuditHttpActivity, etc.
    Requests/                 ← Form Requests con validación
  Models/                     ← Eloquent models
  Policies/                   ← Autorización
  Services/                   ← Lógica de negocio (AuditLogger, etc.)
  Enums/                      ← Tipos tipados (EventStatus, OrderStatus, etc.)
database/
  migrations/                 ← Schema completo
  seeders/                    ← DemoFullEventSeeder, DatabaseSeeder
resources/views/
  layouts/
    dashboard.blade.php       ← Layout del panel (sidebar nav)
    landing.blade.php         ← Layout público
    auth.blade.php            ← Layout de autenticación
  dashboard/
    events/                   ← CRUD de eventos
    audit-logs/               ← Trazabilidad
  landing/                    ← Páginas públicas
routes/
  web.php                     ← Todas las rutas web
tests/
  Feature/                    ← Tests de integración (usar RefreshDatabase + SQLite)
  Support/                    ← Payloads y helpers de test
```

### Roles en base de datos (NO modificar slugs):
| slug          | Descripción                                      |
|---------------|--------------------------------------------------|
| super_admin   | Acceso total. Ve todo, puede hacer todo.          |
| administrador | Admin de plataforma. Ve todos los eventos.        |
| organizador   | Crea y gestiona sus propios eventos y asistentes. |
| cliente       | Comprador/asistente. Solo ve sus órdenes.         |

### Guards y autorización:
- Middleware `auth` para todo el dashboard
- `AuditHttpActivity` en todo `/dashboard*`
- Políticas en `app/Policies/` (EventPolicy, etc.)
- Helper de rol: `$user->role->slug === 'organizador'`

---

## 3. MODELOS Y RELACIONES

```
User → Role (BelongsTo)
User → Organizer (HasOne)
User → Orders (HasMany)

Organizer → Events (HasMany)
Event → TicketTypes (HasMany)
Event → Venue (BelongsTo)
Event → Category (BelongsTo)

TicketType → CustomFields (HasMany, ordered by sort_order)
TicketType → Attendees (HasMany)

Order → Attendees (HasMany)
Order → Transactions (HasMany)

Attendee → TicketType (BelongsTo)
Attendee → Order (BelongsTo)
```

### Enums críticos:
- `EventStatus`: draft, pending, published, cancelled
- `OrderStatus`: pending, completed, refunded
- `TicketCapacityStrategy`: unlimited, per_ticket, shared_pool
- `TicketIac`: none, optional, required (individual attendee collection)
- `TransactionGateway`: stripe, paypal

---

## 4. CONVENCIONES DE DESARROLLO

### PHP / Laravel:
- PHP 8.2+ — usar tipos declarados, enums nativos, readonly properties donde aplique
- Eloquent sobre SQL crudo salvo queries complejas
- Form Requests para toda validación de entrada
- Policies para toda autorización de recursos
- Services en `app/Services/` para lógica de negocio compleja
- Traits en `app/Concerns/` o `app/Http/Concerns/`
- **NUNCA** poner lógica de negocio en controladores — delegar a Services
- Auditar toda acción significativa con `AuditLogger`
- Usar `DB::transaction()` para operaciones multi-tabla

### Blade / Frontend:
- Bootstrap 5 para layout y componentes UI
- Alpine.js para interactividad reactiva ligera (preferido sobre JS vanilla)
- Vite como build tool (ya configurado)
- NO agregar Vue.js ni React — mantener Blade + Alpine
- Tailwind CSS disponible pero usar con moderación (Bootstrap es el sistema principal)
- Iconos: Bootstrap Icons (`bi-*`)
- Tablas: Bootstrap Table (ya integrado en dashboard)

### CSS / Estilos:
- `public/css/dashboard-sb-admin-overrides.css` — overrides del dashboard
- `public/css/landing.css` — estilos del landing público
- Variables CSS en `:root` para colores de marca

### JavaScript:
- `public/js/dashboard-event-tickets.js` — lógica dinámica del formulario de tickets
- `public/js/dashboard-event-form-widgets.js` — widgets del formulario de eventos
- Siempre verificar si un módulo JS ya existe antes de crear uno nuevo

### Naming conventions:
- Controladores: `NombreAccionController` (ej: `OrganizerApprovalController`)
- Rutas nombradas: `dashboard.recurso.accion` (ej: `dashboard.organizers.index`)
- Views: `dashboard/recurso/accion.blade.php`
- Migrations: `YYYY_MM_DD_HHMMSS_descripcion_tabla.php`
- Tests: `NombreModuleTest.php` con métodos `test_accion_resultado()`

---

## 5. BASE DE DATOS — SCHEMA ACTUAL

### Tablas existentes:
- `users` — usuarios con `role_id`
- `roles` — 4 roles pre-seeded
- `organizers` — perfil extendido del organizador (Stripe account, etc.)
- `categories` — categorías jerárquicas de eventos
- `venues` — lugares/ubicaciones con geolocalización
- `events` — eventos con UUID, slug único, metadata JSON
- `ticket_types` — tipos de entrada con estrategias de capacidad
- `custom_fields` — preguntas dinámicas por tipo de entrada
- `orders` — órdenes de compra
- `transactions` — pagos (Stripe/PayPal)
- `attendees` — asistentes con QR security_code único
- `audit_logs` — trazabilidad completa

### Columnas JSON estratégicas:
- `events.metadata` — datos extendidos del evento
- `attendees.registration_data` — respuestas a custom fields
- `transactions.payload` — respuesta completa del gateway
- `venues.metadata` — datos extendidos del venue

---

## 6. FEATURES PRIORITARIAS (META 50% FUNCIONAL)

Desarrollar en este orden de prioridad:

### PRIORIDAD 1 — Onboarding de Organizadores (CRÍTICO)
**Objetivo**: Un organizador puede registrarse, ser aprobado y empezar a crear eventos.

- [ ] Página de registro dedicada para organizadores (`/registro-organizador`)
  - Campos: nombre, email, password, nombre de organización, teléfono, tipo de eventos
  - Al registrar: `users.role_id = organizador`, `account_status = awaiting_review`
- [ ] Dashboard de aprobación para super_admin/administrador
  - Lista de organizadores pendientes
  - Aprobar / Rechazar con razón opcional
  - Email automático al aprobar/rechazar
- [ ] Bloqueo de acceso al dashboard si `account_status != approved`
- [ ] Perfil del organizador: editar datos, configurar PayPal email y/o Stripe

### PRIORIDAD 2 — Carga Manual de Asistentes (DIFERENCIADOR CLAVE)
**Objetivo**: El organizador puede registrar asistentes SIN que hayan pagado.

- [ ] Formulario de carga individual: nombre, email, ticket_type, datos personalizados
- [ ] Carga masiva por CSV (template descargable)
  - Columnas mínimas: first_name, last_name, email, ticket_type_name, [custom_fields...]
  - Validación de errores fila por fila, preview antes de importar
- [ ] Al cargar manualmente: `order.status = completed`, `transaction = null`, `platform_fee = 0`
- [ ] Interfaz de gestión de asistentes por evento (lista, buscar, editar, eliminar)
- [ ] Exportar lista de asistentes (CSV/Excel)

### PRIORIDAD 3 — Checkout Público (Compra de Entradas)
**Objetivo**: Un visitante puede comprar entradas y recibir confirmación.

- [ ] Página de detalle del evento pública (`/eventos/{slug}`)
  - Ya existe parcialmente en `LandingController@eventShow`
- [ ] Flujo de checkout (wizard):
  1. Seleccionar tickets y cantidades
  2. Capturar datos de asistentes (si `iac = required`)
  3. Responder custom fields
  4. Pago (Stripe Elements o PayPal JS SDK)
  5. Confirmación con QR code
- [ ] Cálculo automático de `platform_fee = $2.99 + (subtotal × 0.05)` por orden
- [ ] Email de confirmación con entradas en PDF o HTML
- [ ] Generación del `security_code` UUID por asistente (ya en schema)

### PRIORIDAD 4 — Check-in QR
**Objetivo**: El organizador puede escanear QR en el evento para validar entrada.

- [ ] Panel de check-in por evento (`/dashboard/events/{event}/checkin`)
  - Interfaz limpia para móvil (fullscreen)
  - Input de QR (teclado o cámara con HTML5)
  - Validación: `attendee.security_code` → mostrar datos del asistente
  - Marcar `checked_in_at` y `checkin_by`
- [ ] Lista de asistentes con estado de check-in en tiempo real
- [ ] Estadísticas: total vendido, checked-in, pendientes, ingresos

### PRIORIDAD 5 — Reportes y Payouts
**Objetivo**: Transparencia financiera para organizador y admin.

- [ ] Resumen financiero por evento:
  - Total recaudado, platform_fee retenido, neto del organizador
- [ ] Historial de payouts (registro cuando se envía dinero al organizador)
- [ ] Panel de administración de plataforma:
  - Ingresos totales de plataforma (suma de platform_fees)
  - Lista de todas las órdenes
  - Gestión de reembolsos

---

## 7. ESTÁNDARES DE UX/UI

### Principios:
1. **Intuitivo primero** — si necesita manual, rediseñar
2. **Mobile-first** — el check-in se hace desde teléfono
3. **Profesional** — comparar con Eventbrite, no con webs locales amateur
4. **Velocidad** — forms rápidos, feedback inmediato, sin page reloads innecesarios

### Patrones UI establecidos:
- Dashboard: sidebar fija + contenido principal con padding
- Cards con sombra sutil para bloques de información
- Status badges con colores semánticos (Bootstrap: success/warning/danger/info)
- Tablas con Bootstrap Table (sorting, search, pagination built-in)
- Modales para confirmaciones destructivas
- Toast notifications para feedback de acciones (éxito/error)
- Formularios en steps/wizard para flujos complejos (checkout, registro)

### Paleta de colores (mantener consistencia):
- Primary: `#3490dc` (azul)
- Success: `#38c172` (verde)
- Warning: `#f6993f` (naranja)
- Danger: `#e3342f` (rojo)
- Dark sidebar: `#2d3748`

---

## 8. TESTING

### Reglas:
- **NUNCA** usar mocks de base de datos — usar SQLite in-memory con `RefreshDatabase`
- Todo feature crítico tiene al menos un test de integración
- Los tests de organizer deben probar el flujo completo: registro → aprobación → crear evento → vender → check-in
- Usar factories para crear datos: `User::factory()->organizer()->create()`
- Usar `DemoCatalogSeeder` para pre-poblar venues y categorías en tests

### Estructura de tests:
```php
// test_[rol]_puede_[accion]_[resultado]
test_organizador_puede_cargar_asistentes_sin_pago()
test_checkout_calcula_platform_fee_correctamente()
test_checkin_rechaza_codigo_duplicado()
```

---

## 9. SEGURIDAD

- Sanitizar TODA entrada de usuario antes de persistir
- Usar `$request->validated()` siempre, nunca `$request->all()`
- Los organizadores SOLO ven sus propios datos (Policy enforcement)
- El `security_code` del attendee se genera con `Str::uuid()` y NUNCA se acepta del cliente
- CSV imports: validar MIME type, tamaño máximo 5MB, encodings UTF-8
- Rate limiting en endpoints de checkout y check-in
- CSRF en todos los forms (Laravel default, no desactivar)

---

## 10. INTEGRACIONES DE PAGO

### Stripe:
- Usar Stripe Connect para split payments (organizador recibe directo)
- `stripe_account_id` ya en tabla `organizers`
- Stripe Elements para captura de tarjeta (nunca raw card numbers)
- Webhooks para confirmar pagos y triggers de payout

### PayPal:
- PayPal JS SDK para checkout
- Guardar email de PayPal del organizador en su perfil
- Payouts via PayPal Payouts API

### Cálculo de fees (implementar en `App\Services\FeeCalculator`):
```php
class FeeCalculator
{
    const FIXED_FEE = 2.99;
    const PERCENTAGE_FEE = 0.05;

    public static function calculate(float $subtotal): array
    {
        $platformFee = self::FIXED_FEE + ($subtotal * self::PERCENTAGE_FEE);
        return [
            'subtotal' => round($subtotal, 2),
            'platform_fee' => round($platformFee, 2),
            'net_organizer' => round($subtotal - $platformFee, 2),
        ];
    }
}
```

---

## 11. COMANDOS ARTISAN FRECUENTES

```bash
# Correr tests
php artisan test

# Correr solo tests de un módulo
php artisan test --filter=OrganizerTest

# Refresh de base de datos con seeders
php artisan migrate:fresh --seed

# Crear un controller
php artisan make:controller Dashboard/OrganizerController --resource

# Crear un Form Request
php artisan make:request SaveOrganizerRequest

# Crear una Policy
php artisan make:policy OrganizerPolicy --model=Organizer

# Crear migration
php artisan make:migration add_account_status_to_users_table

# Build assets
npm run dev
npm run build
```

---

## 12. REFERENCIA DEL PLUGIN WORDPRESS HEREDADO

El plugin `rt-checkin` (WordPress) contiene la lógica legacy que estamos migrando. Consultar para:
- Lógica de aprobación de organizadores (`account_status`: awaiting_admin_review → approved/rejected)
- Endpoints de check-in y validación de QR
- Estructura de reportes de eventos
- Integración con PayPal para payouts

**Ruta**: `/Volumes/yzamora_ext/Desarrollo/Personales/regiticket_dev/wp-content/plugins/rt-checkin`

---

## 13. LO QUE NO HACER

- NO agregar Vue.js, React o cualquier SPA framework — Blade + Alpine.js es suficiente
- NO crear helpers/abstracciones para casos de un solo uso
- NO poner lógica de negocio en controladores — usar Services
- NO hacer mocks de DB en tests — siempre SQLite real con RefreshDatabase
- NO agregar comentarios obvios al código — solo donde la lógica no sea evidente
- NO ignorar las políticas de autorización — siempre validar en Policy
- NO aceptar `$request->all()` en validación — siempre `$request->validated()`
- NO crear archivos README ni documentación adicional salvo que se pida explícitamente
- NO cambiar los slugs de roles (`super_admin`, `administrador`, `organizador`, `cliente`)
- NO usar `dd()` o `dump()` en código que se va a commitear
- NO añadir features extras no pedidas — implementar exactamente lo solicitado

---

## 14. ESTADO DE FEATURES (TRACKING)

| Feature                              | Estado       | Prioridad |
|--------------------------------------|-------------|-----------|
| Auth (login/register)                | Completo    | —         |
| CRUD de eventos                      | Completo    | —         |
| Tipos de entrada dinámicos           | Completo    | —         |
| Custom fields por ticket             | Completo    | —         |
| Audit logging                        | Completo    | —         |
| Landing pública de eventos           | Parcial     | —         |
| Registro de organizadores            | Pendiente   | P1        |
| Aprobación de organizadores          | Pendiente   | P1        |
| Perfil de organizador (PayPal/Stripe)| Pendiente   | P1        |
| Carga manual de asistentes           | Pendiente   | P2        |
| Import CSV de asistentes             | Pendiente   | P2        |
| Gestión de asistentes por evento     | Pendiente   | P2        |
| Checkout público (compra)            | Pendiente   | P3        |
| Pago con Stripe                      | Pendiente   | P3        |
| Pago con PayPal                      | Pendiente   | P3        |
| Email de confirmación + QR           | Pendiente   | P3        |
| Panel de check-in QR                 | Pendiente   | P4        |
| Reportes financieros                 | Pendiente   | P5        |
| Historial de payouts                 | Pendiente   | P5        |
| Panel admin de plataforma            | Pendiente   | P5        |
