Resumen ejecutivo

El proyecto se divide en 11 fases. Las fases 2A, 2B, 3 y 6 se ejecutan en paralelo, que es donde se concentra el mayor ahorro de tiempo. El testing no es una fase final: cada fase entrega sus propios tests unitarios e de integración. Los tests de rendimiento y aceptación se concentran en las semanas 8–9.

10
Semanas totales
~6
Semanas sin paralelo
4
Tracks en paralelo
61
Productos en catálogo
17
Preguntas pendientes
5
Tipos de test
Prerequisito bloqueante

Las 17 preguntas pendientes con Verena Heufler (documentadas en la especificación técnica) deben resolverse antes de la Fase 2B y Fase 3. En particular: rol de Betreuer, textos de emails, lógica de límite de 2 citas, y visibilidad entre asesores.

Diagrama Gantt — 10 semanas

Las filas de color idéntico pueden ejecutarse en paralelo. La fila de i18n (verde) es transversal a todo el proyecto.

S1
S2
S3
S4
S5
S6
S7
S8
S9
S10
F0 · Infra
Setup
F1 · Modelos
Modelos + Auth
F2A · Admin gestión
Filament: Gestión
F2B · Admin citas
Filament: Citas
F3 · Portal público
Livewire: Portal
F6 · i18n (transv.)
Multiidioma — transversal
F4 · Emails
Mail + Queues
F5 · Estadísticas
Stats + Export
F7 · HubSpot arch.
Eventos
F8 · Testing
Test avanzado
F9 · UAT
UAT
F10 · Lanzamiento
Go live
Semanas con mayor paralelismo (S3–S5)

Durante las semanas 3 a 5 pueden trabajar simultáneamente cuatro tracks independientes: F2A (panel admin - módulos de gestión), F2B (panel admin - citas), F3 (portal público) y F6 (multiidioma). Esto requiere al menos dos desarrolladores. Con un único desarrollador, F2A y F2B se fusionan y F3 se desplaza a S5–S7.

Principios de desarrollo

Estrategia de testing

Unit — lógica aislada, sin BD ni red
Integration — módulos + BD real en memoria
Functional — flujos completos de usuario (Dusk/Pest)
Performance — carga, concurrencia, tiempos de respuesta
Acceptance — validación con Verena en staging
TipoHerramientaCuándo se escribeCriterio de paso
UnitPest + PHPUnitJunto a cada clase/servicio100% en lógica de negocio crítica (slots, tokens, reglas de reserva)
IntegrationPest + SQLite in-memoryAl completar cada móduloTodos los flujos DB verificados; sin queries N+1
FunctionalLaravel DuskAl completar F3 (portal) y F2 (admin)Flujo de reserva completo, login, post-consulta funcionan en browser
Performancek6 o ArtilleryFase 8Calendar load <300ms · 50 usuarios simultáneos sin degradación
AcceptanceManual con Verena en stagingFase 9Las 17 preguntas pendientes validadas; flujo completo aprobado

F0Infra

Infraestructura y configuración del proyecto

📅 Semana 1 🔒 Bloqueante para todo lo demás

Entornos

  • Crear repositorio Git con estrategia de branching (main / develop / feature branches)
  • Provisionar servidor de producción y staging (Hetzner/DigitalOcean) con Laravel Forge
  • Configurar Nginx + PHP 8.3-FPM + MySQL 8.0 + Redis en ambos entornos
  • Configurar almacenamiento S3 o MinIO para documentos clínicos
  • Configurar cuenta de email transaccional (Mailgun o Postmark) con dominio verificado

Proyecto base

  • Instalar Laravel 11 + Filament 3 + Livewire 3
  • Instalar paquetes core: Spatie Permission, Spatie Media Library, Spatie Translatable, Laravel Excel, mcamara/laravel-localization, pragmarx/google2fa, Laravel Fortify
  • Configurar Laravel Pint (code style) + PHPStan nivel 6
  • Configurar Pest como framework de tests
  • Configurar pipeline CI/CD (GitHub Actions): lint → tests → deploy staging en merge a develop
Unit: configuración inicial del pipeline
F1Datos

Modelos de datos, migraciones y autenticación

📅 Semanas 1–2 🔒 Bloqueante para F2A, F2B, F3

Migraciones y modelos Eloquent

  • Migraciones: termins, therapeuts, beraters, betreuer, medikaments, kategorien, feiertags, users
  • Modelos Eloquent con relaciones, casts, fillable y reglas de validación
  • Spatie Translatable en: Kategorie.nombre, Medikament.nombre_display, plantillas de email
  • Spatie Media Library: colección befunde en modelo Termin

Autenticación y roles

  • Laravel Fortify: login, logout, contraseñas
  • TOTP 2FA con pragmarx/google2fa (activable por usuario)
  • Spatie Permission: roles admin, berater, betreuer (pendiente confirmar con Verena)
  • Middleware de autorización por rol en rutas admin

Seeders de datos de referencia

  • Seeder de categorías completo (14 Hauptthemen + subcategorías extraídas del CSV)
  • Seeder de los 61 productos del catálogo con código y serie
  • Seeder de los 3 asesores con horarios reales
  • Seeder de festivos base para DE/AT/CH (año en curso)
Unit: relaciones entre modelos Unit: roles y permisos Unit: login + 2FA flow Integration: seeders producen estado consistente
F2AAdmin

Panel admin — Módulos de gestión

📅 Semanas 2–4
⇌ Paralelo con F2B · F3 · F6

Filament Resources para todos los catálogos y entidades de configuración. No requieren la lógica de negocio de citas.

Resources Filament

  • TherapeutResource: tabla filtrable, badge membresía, contador de usos sin socio, campo HubSpot ID
  • BeraterResource: CRUD completo, gestión de horarios de slots (configuración semanal), días de antelación de agenda, periodos de vacaciones y asignación de sustituto
  • BetreuerResource: CRUD básico (pendiente confirmar si tiene login o solo es catálogo)
  • MedikamentResource: CRUD con campo serie y orden de visualización en formularios. Soporte translatable.
  • KategorieResource: árbol jerárquico Hauptthema → Unterkategorie. Soporte translatable.
  • FeiertageResource: CRUD por país (DE/AT/CH/ALL) con selector de fecha
  • EinstellungenPage: página de configuración global (límite no-socios, parámetros generales)

Autorización

  • Policies Filament: solo rol admin accede a estos módulos
  • Navegación Filament condicional por rol
Unit: validaciones CRUD Unit: lógica de sustituciones de asesor Integration: solo admin accede, berater es redirigido Integration: translatable guarda/recupera por locale
F2BAdmin

Panel admin — Módulo de citas

📅 Semanas 2–4
⇌ Paralelo con F2A · F3 · F6

TerminResource — Vista admin

  • Tabla principal con todas las columnas del CSV: fecha, terapeuta, asesor, betreuer, tema, estado, FAX-code, Fallnummer
  • Filtros: por asesor, por Hauptthema, por periodo, por estado (completada/pendiente), por membresía del terapeuta
  • Indicador visual para terapeutas sin membresía
  • Acción de creación manual de cita (admin puede reservar por teléfono/email)
  • Acción de marcar como completada, cancelar
  • Campo interner_kommentar visible solo para admin y berater

Vista del asesor (Berater)

  • Vista filtrada: solo las citas asignadas al asesor logueado (o a su sustituto si aplica)
  • Página de detalle de cita: anamnesis completa, documentos adjuntos descargables, datos del paciente
  • Formulario post-consulta: cuadrícula de checkboxes de productos (61), checkboxes de formaciones recomendadas, campo de texto libre adicional, comentario interno
  • Acción de marcar cita como completada

Servicio de slots

  • SlotAvailabilityService: calcula franjas libres de 30 min para un asesor en una fecha dada, excluyendo festivos, vacaciones y citas ya reservadas
  • Validación: máximo 2 citas por terapeuta por día de consulta
  • Generación automática de Fallnummer y FAX-Code al crear cita
Unit: SlotAvailabilityService (festivos, vacaciones, límite 2) Unit: generación de Fallnummer y FAX-Code (unicidad) Unit: berater solo ve sus citas Integration: formulario post-consulta persiste correctamente Integration: creación manual dispara eventos de dominio
F3Portal

Portal público de reserva (Livewire)

📅 Semanas 3–5 🔗 Depende de F1 (SlotService disponible desde F2B)
⇌ Paralelo con F2A · F2B · F6

Aplicación Livewire embebible como iframe en megemit.org. Sin login tradicional — identifica al terapeuta mediante token firmado.

Identificación del terapeuta

  • Servicio TherapistTokenService: genera y verifica tokens firmados HMAC con email + timestamp + expiración configurable
  • Middleware que verifica el token en cada request del portal
  • Comprobación de límite no-socio (contador de usos)

Componentes Livewire

  • BookingCalendar: selector de asesor + calendario de fechas disponibles. Llama a SlotAvailabilityService. Actualización reactiva sin recarga.
  • AnamnesisForm: todos los campos del formulario (Betreff, Hauptthema, Unterkategorie dependiente, Weitere Angaben, Geschlecht, Alter, Gewicht, Größe, PLZ)
  • FileUpload: subida múltiple de documentos (Spatie Media Library). Validación de formatos (PDF, JPEG, EPS, DOC/DOCX). Aviso visible de anonimización obligatoria.
  • BookingConfirmation: muestra Fallnummer y FAX-Code. Checkbox de protección de datos.
  • AppointmentManagement: listado de citas activas del terapeuta, opción de modificar o cancelar.

Integración iframe

  • Ruta pública con prefijo de locale: /{locale}/buchen
  • Headers X-Frame-Options: ALLOW-FROM megemit.org + Content-Security-Policy: frame-ancestors
  • Responsive: funciona en las dimensiones del iframe de megemit.org
Unit: TherapistTokenService (generación, verificación, expiración) Unit: validación de anonimización (campos prohibidos) Unit: límite 2 citas/día se bloquea en portal Integration: flujo reserva completo crea Termin con todos los campos Integration: cancelación libera el slot Functional (Dusk): flujo completo de reserva en browser Functional (Dusk): subida de fichero y confirmación con Fallnummer
F4Email

Emails automáticos, colas y Scheduler

📅 Semanas 5–6 🔗 Depende de F2B y F3 (eventos de dominio)

Plantillas de email (Blade + alemán)

  • Confirmación de reserva: Fallnummer, FAX-Code, datos de la cita, instrucciones para modificar/cancelar
  • Recordatorio 24h antes: detalles de la cita + aviso para subir documentos si no lo ha hecho
  • Agenda del asesor: listado de citas del día con enlace directo a cada caso. Enviado X días antes (configurable por asesor).
  • Email a no-socios: enviado al superar el límite de 2 usos. Información sobre membresía MeGeMIT.
  • Todas las plantillas en alemán inicialmente; estructura multiidioma desde el primer día (lang/de/emails.php)

Jobs y Scheduler

  • SendBookingConfirmationJob: disparado por evento AppointmentCreated
  • SendReminderJob: Scheduler diario, busca citas de mañana y encola recordatorios
  • SendAdvisorAgendaJob: Scheduler diario, envía agenda a los asesores que correspondan según su configuración de días
  • CheckNonMemberLimitJob: disparado al crear cita; si supera límite, envía email y bloquea
  • GenerateMonthlyReportJob: Scheduler el día 1 de cada mes, genera XLSX con todas las citas del mes anterior y lo envía por email a la administración
Unit: contenido de cada plantilla de email Unit: Scheduler dispara los jobs en el momento correcto Unit: email se envía en el locale del terapeuta Integration: confirmación se encola al crear cita Integration: email de no-socio se envía al superar límite Integration: agenda incluye las citas correctas del asesor
F5Stats

Estadísticas e informes

📅 Semanas 6–7 🔗 Depende de F2B (modelo Termin completo)
⇌ Paralelo con F7

Dashboard de estadísticas (Filament)

  • Filtro de periodo: mensual, trimestral, semestral, anual + rango personalizado
  • Métricas: total de citas, desglose por asesor, por país (DE/AT/CH), por Hauptthema
  • Ranking de productos más recomendados (top 10)
  • Terapeutas con mayor frecuencia de uso
  • Ratio socios/no-socios

Exportación XLSX

  • Exportación manual desde el panel (Laravel Excel)
  • Formato exacto del CSV de producción: 78 columnas en el orden documentado (Termin, Land, PLZ … RANTES 27CH)
  • Exportación mensual automática via GenerateMonthlyReportJob (implementado en F4)
Unit: cálculo correcto de métricas por periodo Integration: exportación XLSX contiene las 78 columnas en orden exacto Functional: descarga del informe desde el panel admin
F6i18n

Multiidioma

📅 Semanas 2–7
⟳ Transversal — se construye junto a cada módulo

No es una fase independiente sino una disciplina que acompaña a cada fase. Cada módulo entregado incluye sus claves de traducción en lang/de/.

Infraestructura i18n (semana 2, junto con F1)

  • Configurar mcamara/laravel-localization: routing con prefijo /{locale}/
  • Configurar Filament para leer el locale del perfil de usuario
  • Configurar middleware que establece el locale en cada request

Ficheros de traducción (se completan por fase)

  • lang/de/auth.php, validation.php, pagination.php — junto con F0/F1
  • lang/de/booking.php, lang/de/anamnesis.php — junto con F3
  • lang/de/emails.php — junto con F4
  • lang/de/admin.php, lang/de/stats.php — junto con F2 y F5
  • Contenido traducible en BD (categorías, productos, plantillas): admin lo introduce desde Filament

Criterio de completitud

  • Ningún texto hardcodeado en Blade o Livewire: todo pasa por __() o trans()
  • Añadir un nuevo idioma no requiere modificar código — solo crear lang/{locale}/ y traducir BD
Unit: ninguna cadena hardcodeada en vistas (script de auditoría) Integration: cambiar locale cambia todos los textos de la UI
F7HubSpot

Arquitectura de integración HubSpot

📅 Semana 7 ⚠️ Solo arquitectura — sin implementación del adaptador
⇌ Paralelo con F5

Se construye el esqueleto de integración completo. El adaptador HubSpot real se implementará en una fase posterior cuando se defina el mapping de propiedades con el cliente.

Eventos de dominio

  • AppointmentCompleted: disparado al marcar una cita como erledigt
  • TherapistCreated: disparado al crear un nuevo terapeuta
  • TherapistMembershipChanged: disparado al cambiar el estado de membresía

Capa de abstracción

  • Interface CrmAdapterInterface: métodos syncContact(), recordActivity()
  • NullCrmAdapter: implementación vacía (no-op) activa por defecto — no falla, no hace nada
  • HubSpotCrmAdapter: clase esqueleto preparada; se implementa en fase posterior
  • SyncToCrmJob: Job en cola que consume los eventos y llama al adapter activo
  • Variable de entorno CRM_ADAPTER=null|hubspot para activar el adaptador
Unit: eventos se disparan en las acciones correctas Unit: NullAdapter no lanza excepciones Integration: cambiar CRM_ADAPTER=hubspot llama al adaptador correcto
F8Testing

Testing avanzado — rendimiento y seguridad

📅 Semanas 7–8 🔗 Requiere F2, F3, F4, F5 completos en staging

Tests de rendimiento (k6 / Artillery)

  • Carga del calendario de slots: <300ms con 50 usuarios simultáneos
  • Subida de ficheros: 10 uploads simultáneos sin timeout
  • Login en panel admin: <200ms
  • Generación del XLSX mensual con 200+ citas: <30s
  • Test de concurrencia en reserva: dos terapeutas intentando reservar el mismo slot simultáneamente — solo uno triunfa

Tests funcionales completos (Dusk)

  • Flujo completo: reserva → recordatorio → consulta → post-consulta → exportación XLSX
  • Flujo de cancelación: terapeuta cancela → slot liberado → aparece disponible
  • Flujo de sustitución: asesor en vacaciones → sustituto ve sus citas
  • Portal embebido: test de renderizado correcto dentro de iframe

Revisión de seguridad

  • Verificar que comentarios internos no son accesibles vía API por el terapeuta
  • Verificar CSRF en todos los formularios
  • Verificar que documentos clínicos requieren autenticación para descargarse
  • Verificar que un berater no puede acceder a citas de otro berater manipulando la URL
  • Revisar headers de seguridad (CSP, X-Frame-Options en el portal embebido)
Performance: slots, uploads, XLSX, concurrencia Functional: flujos E2E completos en browser
F9UAT

Pruebas de aceptación con Verena Heufler

📅 Semana 9 🔗 Staging debe estar completo y estable

Verena valida el sistema completo en el entorno de staging con datos reales de prueba. Las 17 preguntas pendientes documentadas en la especificación deben haberse respondido antes de esta fase.

Checklist de aceptación

  • Reserva de cita desde el portal (simular un terapeuta real)
  • Vista del asesor: revisión de caso, rellenar recomendaciones, marcar como completada
  • Administración: crear cita manual, gestionar festivos, modificar catálogo de productos
  • Verificar emails recibidos: confirmación, recordatorio y agenda del asesor
  • Generar y descargar el informe mensual XLSX; comparar con el CSV de referencia
  • Verificar que el portal se renderiza correctamente embebido en megemit.org (staging)
  • Validar textos de emails en alemán con Verena

Gestión de incidencias

  • Incidencias bloqueantes: corrección inmediata, re-test el mismo día
  • Mejoras o ajustes menores: backlog priorizado para el sprint de lanzamiento
Acceptance: las 17 preguntas pendientes validadas Acceptance: flujo completo aprobado por Verena Acceptance: XLSX coincide con el formato de referencia
F10Launch

Lanzamiento a producción

📅 Semana 10 ✅ Requiere UAT aprobado sin incidencias bloqueantes

Cutover

  • Deploy a producción: main ← merge de develop tras UAT aprobado
  • Migrar datos históricos si los hay (acordar con Verena qué citas pasadas importar)
  • Cargar seeders de producción (categorías, productos, asesores, festivos)
  • Actualizar la URL del <iframe> en megemit.org apuntando al nuevo dominio
  • Verificar envío de emails desde producción (dominio verificado en Mailgun/Postmark)
  • Activar Redis queue workers en producción (Supervisor)
  • Verificar Laravel Scheduler activo (crontab en el servidor)

Post-lanzamiento

  • Sesión de formación con Verena: panel admin, gestión de citas, estadísticas
  • Monitorización activa durante 48h (logs, colas, emails)
  • Documento de handover: accesos, estructura del proyecto, cómo añadir un nuevo idioma, cómo añadir productos al catálogo
  • Mantener sistema Concloo activo en paralelo durante 2 semanas como fallback
Ventana de cutover recomendada

Realizar el cambio de iframe en megemit.org un miércoles por la tarde, después de que Gunter Schlegel haya terminado sus consultas. El siguiente día de consulta (jueves Dr. Bubendorfer) será el primer día real en el nuevo sistema.


Matriz de cobertura de tests

Módulo / Funcionalidad Unit Integration Functional Performance Acceptance
Login + 2FA✓✓✓
Roles y permisos✓✓
SlotAvailabilityService✓✓✓
Concurrencia en reserva✓✓
TherapistTokenService✓✓
Formulario de reserva (portal)✓✓✓✓
Upload de documentos✓✓✓
Generación Fallnummer + FAX-Code✓✓✓
Formulario post-consulta (asesor)✓✓✓✓
Visibilidad comentario interno✓✓✓
Email confirmación reserva✓✓✓
Email recordatorio 24h✓✓✓
Email agenda asesor✓✓✓
Email no-socio (límite 2 usos)✓✓✓
Exportación XLSX mensual✓✓✓✓✓
Dashboard estadísticas✓✓✓✓
Gestión festivos + vacaciones✓✓✓
Sustituciones de asesor✓✓✓✓
Multiidioma UI✓✓
Translatable en BD✓✓
Eventos de dominio (HubSpot arch.)✓✓
Portal embebido en iframe✓✓
Seguridad: acceso a documentos✓✓

Mapa de dependencias y paralelismo

Dependencias bloqueantes

F1requiere F0 completo
F2Arequiere F1 (modelos)paralelo con F2B · F3 · F6
F2Brequiere F1 (modelos + SlotService)paralelo con F2A · F3 · F6
F3requiere F1 + SlotService (puede mock hasta F2B)paralelo con F2A · F2B · F6
F4requiere F2B + F3 (eventos de dominio)
F5requiere F2B (modelo Termin)paralelo con F7
F6requiere F0 (infra i18n)transversal a F2A · F2B · F3 · F4 · F5
F7requiere F2B (eventos)paralelo con F5
F8requiere F2 · F3 · F4 · F5 en staging
F9requiere F8 sin bloqueantes
F10requiere F9 aprobado por Verena

Truco de paralelismo en F3

El portal público (F3) necesita SlotAvailabilityService que se implementa en F2B. Para no bloquear F3, el desarrollador puede arrancar con una implementación mock del servicio de slots y reemplazarla cuando F2B esté listo. Esto permite que F3 arranque en la semana 3 sin esperar a F2B.

Con un solo desarrollador

Si el proyecto lo ejecuta un único desarrollador, el orden recomendado es: F0 → F1 → F2A → F2B → F3 → F4 → F5 → F7 → F6 (integrar i18n en cada módulo al terminar). F8, F9 y F10 se mantienen igual. Tiempo estimado: 13–14 semanas.