Files
recordalexia/docs/adr/adr-002-catalogo-rutinas-reutilizable.md

4.1 KiB
Raw Permalink Blame History

ADR-002: Normalización de las rutinas de tarde (catálogo + asignación)

Metadata Valor
Estado Aceptado (implementado)
Fecha 2026-07-12
Autor(es) Jaume Garriga Maestre
Supersede —

Contexto

El modelo original de AfternoonRoutine mezclaba en una fila la definición de la rutina (labelEs/labelCa, emoji, color, monedas) y su asignación (niño, día, orden). Para tener "Merendar" de lunes a viernes había que crear la misma rutina cinco veces, y editar el emoji exigía tocar cinco filas. El usuario lo detectó como fricción real de uso.

Las mañanas ya estaban bien normalizadas: Activity (catálogo por familia) + WeeklyTemplateEntry (asignación niño+día+orden+override de monedas). Las tardes eran la anomalía.

Opciones Consideradas

Opción A: Mantener el modelo y duplicar en la UI ("crear en varios días")

Pros Contras
Sin migración de datos La duplicación persiste en BD: editar sigue costando N filas
Cambio solo de frontend La asimetría mañana/tarde se consolida

Opción B: Reutilizar Activity también para las tardes

Pros Contras
Una sola entidad de catálogo Semántica forzada: Activity arrastra material del cole (N:M) que la rutina no necesita
Menos código Acopla dos conceptos de dominio distintos

Opción C: Nueva entidad RoutineTask gemela de Activity (elegida)

Pros Contras
Simetría total mañana/tarde: mismo patrón mental y de código Migración de datos con deduplicación
Definir una vez, asignar a N días y N niños Una entidad y un CRUD más
Monedas con cascada: override por día → catálogo → niño

Decisión

Opción C. RoutineTask = catálogo por familia (labels, emoji, color, monedas por defecto). AfternoonRoutine queda como pura asignación (child + dayOfWeek + routineTask + orderIndex + coinsReward como override). La migración Liquibase (changeset 003) consolida los duplicados existentes por clave natural (familia + labels + emoji + color) sin pérdida; el changeset 004 añade ON DELETE CASCADE para que borrar del catálogo arrastre las asignaciones (el modelo mental del padre).

erDiagram
    FAMILY ||--o{ ROUTINE_TASK : "define una vez"
    ROUTINE_TASK ||--o{ AFTERNOON_ROUTINE : "se asigna a N dias/niños"
    CHILD ||--o{ AFTERNOON_ROUTINE : ""
    FAMILY ||--o{ ACTIVITY : "(patrón gemelo de mañanas)"
    ACTIVITY ||--o{ WEEKLY_TEMPLATE_ENTRY : ""
    CHILD ||--o{ WEEKLY_TEMPLATE_ENTRY : ""

Trade-offs

Optimizamos para:

  • Coste de edición del padre: cambiar una rutina se hace UNA vez y se propaga.
  • Consistencia del dominio: un solo patrón (catálogo+asignación) para todo el día.

Sacrificamos:

  • Simplicidad de una tabla única: aceptable; el patrón ya existía en mañanas.
  • Riesgo puntual de migración: mitigado con rollback explícito por changeset y verificación contra Postgres real (Testcontainers, MigrationIT).

Asunciones que podrían invalidar esta decisión:

  • Si apareciera la necesidad de rutinas con material asociado (como Activity), reconsiderar la unificación con Activity (Opción B) en lugar de duplicar N:M.

Consecuencias

  • (+) Alta multi-día en una llamada (POST /routines con lista de días).
  • (+) Cascada de monedas expresiva: día > catálogo > coinsPerTask del niño.
  • (−) Lección aprendida en la migración: H2 no detecta el tipado estricto de Postgres (CAST(NULL AS INTEGER)); por eso existe MigrationIT con Testcontainers.

Criterios de Éxito

  • Una rutina definida una vez y asignada a varios días/niños (tests verdes).
  • Migración sin pérdida verificada contra Postgres 16 real.
  • Borrar del catálogo arrastra asignaciones sin error 500 (test de cascade).

Referencias

  • backend/.../domain/RoutineTask.java, domain/AfternoonRoutine.java
  • backend/src/main/resources/db/changelog/changes/003-routine-catalog.yaml, 004-routine-task-cascade.yaml
  • Artefactos SDD en engram: sdd/rutinas-reutilizables/{proposal,spec,design,tasks,verify-report}