## Supuestos adoptados en F5

| Decisión | Supuesto adoptado | Alternativa descartada | Quién debe validar |
|---|---|---|---|
| `actual_ends_at` (duración real de la llamada) | CLAUDE.md/spec ya afirmaban desde F1 que "el CSV muestra duración real de llamada, no del slot", pero ningún campo lo capturaba — solo existía el par fijo `starts_at`/`ends_at` de 30 min. Se añadió `termins.actual_ends_at` (nullable, `datetime`), fijado automáticamente a `now()` cuando el Berater pulsa "Completar" en `TerminResource`. Sin formulario nuevo — mínimo alcance. Si es null (cita aún no completada, o completada antes de F5), el export usa `ends_at` como fallback. | Añadir un campo editable en el panel para que el Berater introduzca manualmente la hora de fin real. Se descartó por ampliar alcance sin que el plan lo pida explícitamente; "ahora mismo" al completar es una aproximación razonable y automática. | Verena — confirmar si "duración real" debe poder ajustarse manualmente (ej. la llamada terminó antes y se completó el registro más tarde). |
| Exclusión de citas canceladas en las estadísticas | `TerminStatsService` excluye `status = 'cancelada'` de todos los recuentos (total, desgloses, ratio socios/no-socios, top productos), igual que ya hacen F2B (límite de 2 citas/día) y F3 (límite de no-socio). El plan no lo dice explícitamente para F5, pero mezclar citas canceladas en "total de citas" produciría cifras que no reflejan actividad real. | Contar todas las citas sin filtrar por estado. | Verena — si el informe mensual debe distinguir "citas gestionadas" de "citas efectivamente realizadas", podría necesitarse un desglose adicional por estado en vez de una exclusión silenciosa. |
| Cálculo de desgloses en PHP, no en SQL agregado | `Hauptthema` es un atributo `Spatie\Translatable` (columna JSON). Agrupar por su valor traducido con SQL crudo (`GROUP BY JSON_EXTRACT(...)`) no es portable entre MySQL (producción) y SQLite in-memory (`.env.testing`). Se optó por cargar los `Termin` del periodo con `with()` y agrupar con `Collection::groupBy()` en PHP. Coste aceptable dado el volumen esperado (informes mensuales/trimestrales, no consultas en caliente de alto tráfico). | Agregación SQL nativa por rendimiento. Se descartó por el problema de portabilidad de tests y porque F5 no tiene requisito de rendimiento en tiempo real (a diferencia de F2B, que sí es síncrono). | Dev — decisión técnica; revisar si el volumen de citas crece lo suficiente como para justificar agregación SQL. |
| Acceso al dashboard: solo `admin` | El plan tiene una tensión interna: la sección "Fuera de alcance" de F5 dice explícitamente "Dashboard accesible por rol berater", pero en otro punto lista como "supuesto a documentar" la misma pregunta (si berater debería verlo, aunque sea con datos limitados a sus propias citas). Se adoptó la interpretación literal de "Fuera de alcance" como autoritativa: `Statistiken::canAccess()` restringe a `admin`, igual que `EinstellungenPage` y los Resources de F2A. | Dar acceso a `berater` con las métricas filtradas a sus propias citas. Se descartó porque el plan lo marca explícitamente como fuera de alcance de F5, aunque la ambigüedad interna del documento queda señalada aquí. | Verena — resolver la ambigüedad del plan antes de F9; si berater debe ver sus propias métricas, es una fase/ticket aparte. |
| Exportación XLSX manual desde el dashboard | Se añadió una acción "Exportar a XLSX" en `Statistiken` que reutiliza `App\Exports\TerminExport` (ya construido y testeado con las 78 columnas exactas del CSV de producción) filtrado por el rango de fechas seleccionado en el filtro de periodo. Restringida a `admin` por heredar `canAccess()` de la página. | Construir un exportador separado solo para el dashboard. Se descartó por duplicar lo ya validado contra el CSV real de producción. | — (decisión técnica, no requiere validación de negocio). |
| Destinatario del informe mensual automático | **No implementado en F5** — el plan menciona un envío periódico de estadísticas, pero no especifica destinatario fijo ni configurable, ni el disparador (cron/job). F5 se limita al dashboard interactivo y la exportación manual bajo demanda; el envío automático se deja pendiente para cuando se resuelva junto con F4 (colas/emails), del cual depende técnicamente (mismo mecanismo de Jobs/Mail). | Implementar ya un Job programado con un destinatario hardcodeado. Se descartó por violar la regla de CLAUDE.md de no implementar fuera del alcance de la fase activa, y porque F4 (colas) es un prerrequisito técnico no resuelto todavía. | Verena — destinatario(s) del informe periódico y periodicidad exacta. |

Este archivo se revisa con Verena antes del UAT (F9). Si algún supuesto está mal, se corrige antes de F9.
