## Supuestos adoptados en F4

| Decisión | Supuesto adoptado | Alternativa descartada | Quién debe validar |
|---|---|---|---|
| Textos de los emails | Redactados en alemán en `lang/de/emails.php`, tono formal ("Sehr geehrte(r)"), coherente con el resto del portal (F3, alemán exclusivo). **[PENDIENTE Verena]**: el contenido es una redacción razonable, no un texto oficial acordado. | Esperar a F9 sin implementar nada — descartado porque el plan pide construir las plantillas ya en F4 y dejar el texto marcado como pendiente. | Verena — validar literalmente cada texto en F9. |
| Recipientes | Cada email usa `Therapeut->email` (la dirección principal) o `Berater->email`, no las direcciones adicionales de Therapeut (`email_2`, `email_3`, `email_fachkreis`, añadidas en F3.5). | Enviar a las 4 direcciones de Therapeut — descartado porque no se confirmó con Verena el propósito de cada una (ver docs/supuestos-F3.5.md); enviar a todas sin saber su uso podría filtrar información al destinatario equivocado. | Verena — confirmar qué dirección(es) deben recibir qué tipo de email. |
| Momento del aviso de límite no-socio | Se envía **exactamente** al crear la cita que iguala `Einstellung.limite_citas_no_socio` (ej. la 2ª, con el valor por defecto 2) — ni antes ni en citas posteriores. Implementado como comparación `===`, no `>=`, para que solo dispare una vez. | Enviarlo en cada cita a partir del límite (`>=`) — descartado por ruido; el plan pregunta explícitamente "¿se envía al crear la 2ª cita, o al intentar crear la 3ª?" y se optó por la primera lectura (aviso proactivo, no bloqueo reactivo, que ya existe como validación síncrona en F2B/F3). | Verena — confirmar si el momento es correcto. |
| Días de antelación de la agenda del asesor | Configurable **por asesor** (`Berater.agenda_dias_antes`, default 1 día), no un valor fijo global — el plan pregunta explícitamente "¿es configurable por asesor?". | Un valor fijo global (ej. 2 días para todos) — descartado porque el plan ya apunta a que debería ser configurable por asesor. | Verena — confirmar el valor por defecto correcto por asesor. |
| Recordatorio 24h antes | Implementado como Job diario a las 08:00 que busca citas de "mañana" (`status='pendiente'`), marcando `recordatorio_enviado_at` para idempotencia (no reenviar si el Scheduler corre más de una vez el mismo día). | No marcar idempotencia y confiar en que el Scheduler solo corre una vez — descartado por ser una garantía débil en producción real (reinicios, colas atascadas, etc.). | — (decisión técnica, no requiere validación de negocio). |
| `AppointmentCreated` dentro de una transacción | Se añadió `'after_commit' => true` a la conexión `redis` de `config/queue.php` para que los listeners encolados (`SendBookingConfirmation`, `SendNonMemberWarning`) no se procesen antes de que la transacción de `TerminBookingService::book()` haga commit (que incluye locks de fila para reservas concurrentes, ver F2B). Sin esto, un listener podría no encontrar el Termin o verlo con datos no confirmados. | Dejar `after_commit` en `false` (por defecto) — descartado por ser una condición de carrera real, no hipotética, dado que F2B ya usa transacciones con locks explícitamente para esto mismo. | — (hallazgo técnico, no requiere validación de negocio). |
| Registro de listeners | Ninguno — se apoya en el auto-discovery de eventos de Laravel 11 (Laravel escanea `app/Listeners` y liga automáticamente cualquier `handle()` cuyo parámetro tipe un evento). **Se probó registrar manualmente vía `Event::listen()` en `AppServiceProvider::boot()` y causó doble envío de cada email** (auto-discovery + registro manual): se detectó con un test que contaba los mails encolados y se corrigió eliminando el registro manual. | Mantener el registro manual explícito — descartado tras confirmar que duplicaba los envíos; además añade código redundante que Laravel ya cubre por defecto. | — (bug real encontrado y corregido durante esta misma fase, cubierto por test de regresión). |
| Informe mensual (`GenerateMonthlyReportJob`) | El Job genera y almacena el XLSX del mes anterior en el disco privado `local` (`informes/termine-YYYY-MM.xlsx`), reutilizando `TerminExport` de F5. **No se envía por email a nadie todavía** — el destinatario sigue sin confirmar (ver docs/supuestos-F5.md). | Enviarlo a una dirección adivinada (ej. la del admin actual) — descartado explícitamente para no mandar datos con 78 columnas de citas a una dirección no confirmada por el cliente. | Verena — **crítico, bloqueante** antes de activar el envío real del informe mensual. |
| Formato de los Mailables | Se usó el sistema de Markdown Mail de Laravel (`->markdown()` + componentes `<x-mail::message>`/`<x-mail::table>`) en vez de vistas Blade HTML a medida. | Construir HTML propio desde cero — descartado por reinventar lo que el framework ya resuelve (responsive, dark mode, estructura accesible), consistente con el principio de no añadir abstracciones innecesarias. | — (decisión técnica). |
| Idioma de los emails | Solo alemán (`lang/de/emails.php`), sin equivalente en `lang/es/`. | Traducir también al español — descartado: los destinatarios reales (terapeutas y asesores DACH) son germanohablantes; la regla de F6 de traducción íntegra aplica al panel admin, no a comunicaciones externas a terceros (mismo criterio ya aplicado al portal público de F3, que es alemán exclusivo). | — (decisión ya establecida en F3/F6, reconfirmada aquí). |

Este archivo se revisa con Verena antes del UAT (F9). Los puntos de **recipientes** (qué dirección de email usar) y **destinatario del informe mensual** son los más urgentes de confirmar antes de activar el envío real en producción.
