# Sprint 1.4 · Criterios de Aceptación

> **Para vos, Ricci.** Esta es la checklist al cierre. Es el sprint más grande, así que la validación es más larga.

⚠️ **Tomate 1-2 horas tranquilo para esto.** No te apures.

---

## ✅ Bloque 1 · Técnico (Claude Code lo confirma)

- [ ] `app/Core/Storage.php` existe y conecta a R2 sin error
- [ ] `app/Core/Validator.php` existe con todas las reglas (incluye RUT chileno)
- [ ] `app/Core/Upload.php` existe con validaciones
- [ ] Permissions nuevos sembrados (`admin.acceso`, `*.gestionar`, etc.)
- [ ] Mapping de `tenant_admin` y `gerente` actualizado
- [ ] 5 controllers admin existen en `app/Controllers/Admin/`
- [ ] Layout `app/Views/layouts/admin.php` existe
- [ ] Componentes en `app/Views/components/` existen
- [ ] Rutas `/admin/*` registradas en `public/index.php`
- [ ] Tests pasan: ~120+ totales (85 anteriores + ~35 nuevos), 100% verde
- [ ] No hay warnings de PHP en logs

---

## ✅ Bloque 2 · Acceso y permisos

### 2.1 · Login con cada rol

Probá login con cada usuario y verificá:

- [ ] `superadmin@demo.cl` → puede acceder a `/admin/*`
- [ ] `admin@demo.cl` (tenant_admin) → puede acceder a `/admin/*`
- [ ] `gerente@demo.cl` → puede acceder a `/admin/*` PERO modo solo lectura (sin botones de crear/editar)
- [ ] `vendedor@demo.cl` → 403 al intentar `/admin/categorias`
- [ ] `operativo@demo.cl` → 403
- [ ] `contador@demo.cl` → 403

### 2.2 · Sidebar dinámico

Estando logueado:

- [ ] Sidebar muestra sección "ADMINISTRACIÓN" solo si tenés permiso `admin.acceso`
- [ ] Item activo se resalta (background purple, barra lateral, texto purple)
- [ ] Click en otro item navega correctamente

---

## ✅ Bloque 3 · CRUD de Categorías

URL: **http://demo.innovium.test:8000/admin/categorias**

### Crear

- [ ] Click "+ Nueva categoría" → abre modal
- [ ] Validación inline: si dejás nombre vacío y guardás, error inline
- [ ] Validación inline: slug con caracteres inválidos (espacios, mayúsculas) → error
- [ ] Validación inline: slug duplicado → "Ya existe una categoría con este slug"
- [ ] Crear "Urnas" con slug "urnas" → toast verde "Categoría creada"
- [ ] La fila aparece en la tabla
- [ ] Audit log registra `categoria.creada`

### Editar

- [ ] Click en fila o "⋮ → Editar" → abre modal con datos cargados
- [ ] Cambiar nombre → toast verde
- [ ] Cancelar → no guarda

### Eliminar

- [ ] Click "⋮ → Eliminar" → modal de confirmación
- [ ] Confirmar → soft delete (eliminado_en se setea)
- [ ] La fila desaparece de la tabla
- [ ] Audit log registra `categoria.eliminada`

### Listado

- [ ] Búsqueda funciona (filtra por nombre)
- [ ] Estado vacío con mensaje claro

---

## ✅ Bloque 4 · CRUD de Niveles

URL: **/admin/niveles**

Mismo patrón que Categorías:

- [ ] Crear "Austero", "Tradicional", "Premium" en demo
- [ ] Editar nombre funciona
- [ ] Soft delete funciona
- [ ] Audit log registra acciones

---

## ✅ Bloque 5 · Configuración del Tenant

URL: **/admin/configuracion**

### Tab Monetario

- [ ] Muestra valor UF actual: 38500
- [ ] Cambiar a 39000 → toast verde
- [ ] Refresh página → muestra 39000
- [ ] Audit log registra `tenant_config.actualizada` con clave `valor_uf_actual`

### Tab Funeraria (placeholder OK si no hay tablas todavía)

- [ ] Tab existe y carga
- [ ] Si los campos no están en backend, mostrar "Próximamente" en cada uno

### Tab Branding

- [ ] Upload de logo funciona
- [ ] El logo aparece en el sidebar (o muestra "Próximamente" si no se integró aún en sidebar)

---

## ✅ Bloque 6 · CRUD de Productos (el más complejo)

URL: **/admin/productos**

### Crear producto sin imágenes

- [ ] Modal abre
- [ ] Selectores de Categoría y Nivel se llenan con las opciones del tenant
- [ ] Crear "Urna Olmo" con datos válidos → toast verde
- [ ] Aparece en la tabla con thumbnail placeholder
- [ ] Audit log registra `producto.creado`

### Crear producto con imágenes

- [ ] Drag & drop de 1 imagen → preview inmediato
- [ ] Subir → toast "imagen subida"
- [ ] Drag & drop de 3 imágenes a la vez → todas suben
- [ ] Cada imagen aparece como thumbnail
- [ ] Click en thumbnail la marca como principal (estrella)
- [ ] Eliminar thumbnail → desaparece
- [ ] Guardar producto → asocia las imágenes correctamente
- [ ] En la tabla, el thumbnail es la imagen principal

### Validaciones de imágenes

- [ ] Subir un PDF → error "Tipo no permitido"
- [ ] Subir imagen 6MB → error "Excede 5MB"
- [ ] Subir imagen 200x200 → error "Dimensiones mínimas 400x400"

### Filtros y búsqueda

- [ ] Filtrar por categoría
- [ ] Filtrar por nivel
- [ ] Filtrar por activo/inactivo
- [ ] Buscar por nombre

### Editar y eliminar

- [ ] Editar funciona
- [ ] Soft delete funciona
- [ ] Las imágenes quedan en R2 (no se borran físicamente al soft delete)

---

## ✅ Bloque 7 · CRUD de Planes (el más rico)

URL: **/admin/planes**

### Crear plan simple

- [ ] Modal abre
- [ ] Datos básicos: nombre "Plan NF Básico", tipo: plan, disponible_para: NF, moneda: UF, precio: 80
- [ ] Sin líneas todavía → guardar → ¿es válido o requiere mínimo 1 línea? (decisión: mínimo 1 línea obligatoria, sino error)
- [ ] Toast verde

### Agregar línea fija

- [ ] Click "+ Agregar línea fija" → modal interno
- [ ] Selector de producto: search funciona
- [ ] Cantidad: 1
- [ ] Toggle obligatorio: ON
- [ ] Agregar → la línea aparece en la lista del plan padre

### Agregar línea de elección

- [ ] Click "+ Agregar línea elección"
- [ ] Selector de categoría: muestra solo las activas del tenant
- [ ] Selector de nivel (opcional): muestra los del tenant
- [ ] Cantidad: 3
- [ ] Agregar → línea visible

### Plan completo

Ejemplo: crear "Plan NF Tradicional Familiar":
- 1× Urna Olmo (línea fija obligatoria)
- 3× Relicarios cualquier nivel (línea elección)
- 1× Capilla Velatoria 24hs (línea fija opcional)

- [ ] Las 3 líneas aparecen ordenadas
- [ ] Reordenar drag & drop funciona (si se implementó; si no, dejar nota)
- [ ] Editar línea funciona
- [ ] Eliminar línea funciona
- [ ] Guardar plan → toast verde
- [ ] Refrescar → todas las líneas persisten

### Editar plan existente

- [ ] Modificar precio → guarda
- [ ] Agregar línea adicional → guarda
- [ ] Eliminar línea → guarda

---

## ✅ Bloque 8 · Storage R2 funcionando

```bash
mysql -u root -e "SELECT COUNT(*) AS imagenes FROM innovium_demo.producto_imagenes WHERE eliminado_en IS NULL"
```

- [ ] Las imágenes que subiste están registradas

Verificá en R2 (panel de Cloudflare):

- [ ] Bucket `innovium-storage` tiene archivos en `tenants/demo/productos/`
- [ ] Las URLs firmadas funcionan (copiá una URL de la página de productos en otra pestaña)
- [ ] La URL caduca a la hora (probá esperar y refrescar)

---

## ✅ Bloque 9 · Aislamiento (CRÍTICO)

### 9.1 · Productos aislados entre tenants

- [ ] Crear categorías y productos en `demo.innovium.test:8000/admin/...`
- [ ] Loguearse en `infinia.innovium.test:8000` → `/admin/categorias` debe estar vacío
- [ ] Loguearse en `infinia.innovium.test:8000` → `/admin/productos` debe estar vacío

### 9.2 · Imágenes aisladas en R2

```bash
# Ver paths en R2 desde mysql
mysql -u root -e "SELECT r2_path FROM innovium_demo.producto_imagenes LIMIT 5"
mysql -u root -e "SELECT r2_path FROM innovium_infinia.producto_imagenes LIMIT 5"
```

- [ ] Demo tiene paths `tenants/demo/productos/...`
- [ ] Infinia tiene paths `tenants/infinia/productos/...`
- [ ] Nunca se cruzan

---

## ✅ Bloque 10 · Visual y UX

### 10.1 · Estética coherente

- [ ] Las 5 pantallas se ven igual de profesionales que el dashboard del Sprint 1.1
- [ ] Tipografía Georgia en titulares
- [ ] Paleta correcta (purple primario, accents)
- [ ] Sin Bootstrap, sin componentes prefabricados
- [ ] Responsive: todo funciona en tablet 1024×768

### 10.2 · Mobile

Estrechá ventana a <768px:

- [ ] Sidebar se oculta, hamburger button aparece
- [ ] Tablas se transforman en cards verticales
- [ ] Modales son full-screen
- [ ] Buttons full-width en mobile

### 10.3 · Microinteracciones

- [ ] Hover en filas: sutil
- [ ] Botones: scale 0.98 al click
- [ ] Toasts aparecen y desaparecen suaves
- [ ] Modales con backdrop blur
- [ ] Loading states (skeleton o spinner inline en buttons)

---

## ✅ Bloque 11 · Tests

```bash
cd /c/proyectos/innovium && vendor/bin/phpunit
```

- [ ] **Todos** los tests pasan (no falla ni 1)
- [ ] Tests cubren: Validator (incluye RUT), Storage mockeado, Upload, controllers admin, RBAC

---

## Lo que NO esperar (para que no te frustres)

- 🚫 Visor 360° de productos → Sprint 2.x
- 🚫 Generación automática de thumbnails → Sprint 2.x
- 🚫 Dashboard admin con KPIs → Sprint 2.x
- 🚫 Importar/exportar Excel → Sprint 3.x+
- 🚫 Notificaciones email → Sprint 2.x
- 🚫 Historial de cambios visible (existe en audit_log pero sin pantalla) → Sprint 2.x

---

## Cierre del sprint

Cuando todos los checks de arriba estén ✅:

1. Tomá **screenshots de las 5 pantallas** funcionando con datos cargados
2. Pegámelos acá
3. Confirmo "Sprint 1.4 cerrado, vamos al 1.5"
4. Hacés commit final: `chore: sprint 1.4 cerrado - panel admin completo`

---

## Si algo falla

No improvises. Volvé al chat con Vene y contale:
- En qué bloque estás
- Qué pantalla
- Qué esperabas
- Qué pasó (mensaje exacto / screenshot)
- Cualquier error en consola del navegador (F12)

Te ayudo a debuguear con Claude Code.
