feat: CAT-002 Regla de Oro Rama vs Hoja + validaciones #35

Merged
dmolinari merged 9 commits from feature/CAT-002 into main 2026-04-19 11:56:32 +00:00
Owner

Summary

  • Regla de Oro enforced en Application layer (Create/Move guards + GetTree tieneAvisos)
  • IAvisoQueryRepository con NullAvisoQueryRepository stub (PRD-002 reemplaza binding)
  • 2 nuevas domain exceptions → 409 Conflict (RubroPadreEsHojaConAvisosException activa; RubroEsRamaConHijosActivosException definida/mapeada, consumidor en PRD-002)
  • Frontend: tieneAvisos?: boolean en RubroTreeNode + disable "Agregar subrubro" con tooltip cuando === true
  • 1450 tests green (+31 vs baseline 1419), 0 regresiones

Test plan

  • Backend Application: dotnet test tests/SIGCM2.Application.Tests/844/844
  • Backend Api: dotnet test tests/SIGCM2.Api.Tests/254/254 (sequential per #29)
  • Frontend: cd src/web && npx vitest run352/352
  • Smoke manual post-merge: crear rubro hijo bajo hoja (hoy OK; cuando Aviso exista, 409)

Warnings resueltos (tracking)

  • W1 — e2e 409 gap por RSA singleton sealed en TestWebApplicationFactory: abierto como follow-up #36 (label followup). Prioridad antes de PRD-002. Cobertura actual compositiva (handler unit + ExceptionFilter unit + DI wiring test en /arbol).
  • W2 — título tooltip divergente de spec: resuelto en commit a0a1874 — test aprieta match exacto del literal de impl ("El rubro contiene avisos asignados. Muévalos antes de agregar sub-rubros.").
  • W3 — commit c3 duplicado en mensaje: cosmetic, sin acción (requeriría rebase destructivo).
  • W4 — NullAvisoQueryRepository.CountAvisosBatchAsync devuelve {} vs spec {1:0,...}: design-intentional, todos los consumers usan GetValueOrDefault(id, 0). Cerrado.

Follow-ups

  • #36[CAT-002 / Infra] TestWebApplicationFactory: desacoplar RSA singleton (bloquea e2e override en PRD-002 y otros)

Siguiente

  • Mergear este PR
  • PRD-002 reemplaza binding DI IAvisoQueryRepository → implementación real + activa RubroEsRamaConHijosActivosException en CreateAvisoCommandHandler
  • Considerar RepeatableRead o constraint DB para TOCTOU cuando exista dbo.Aviso

Artifacts SDD (engram)

  • sdd/cat-002-regla-oro-rama-vs-hoja/explore
  • sdd/cat-002-regla-oro-rama-vs-hoja/proposal
  • sdd/cat-002-regla-oro-rama-vs-hoja/spec
  • sdd/cat-002-regla-oro-rama-vs-hoja/design
  • sdd/cat-002-regla-oro-rama-vs-hoja/tasks
  • sdd/cat-002-regla-oro-rama-vs-hoja/apply-progress
  • sdd/cat-002-regla-oro-rama-vs-hoja/verify-report
  • sdd/cat-002-regla-oro-rama-vs-hoja/archive-report
## Summary - Regla de Oro enforced en Application layer (Create/Move guards + GetTree tieneAvisos) - `IAvisoQueryRepository` con `NullAvisoQueryRepository` stub (PRD-002 reemplaza binding) - 2 nuevas domain exceptions → 409 Conflict (`RubroPadreEsHojaConAvisosException` activa; `RubroEsRamaConHijosActivosException` definida/mapeada, consumidor en PRD-002) - Frontend: `tieneAvisos?: boolean` en `RubroTreeNode` + disable "Agregar subrubro" con tooltip cuando `=== true` - **1450 tests green (+31 vs baseline 1419), 0 regresiones** ## Test plan - [x] Backend Application: `dotnet test tests/SIGCM2.Application.Tests/` → **844/844** - [x] Backend Api: `dotnet test tests/SIGCM2.Api.Tests/` → **254/254** (sequential per #29) - [x] Frontend: `cd src/web && npx vitest run` → **352/352** - [x] Smoke manual post-merge: crear rubro hijo bajo hoja (hoy OK; cuando Aviso exista, 409) ## Warnings resueltos (tracking) - **W1 — e2e 409 gap por RSA singleton sealed en TestWebApplicationFactory**: abierto como follow-up #36 (label `followup`). Prioridad antes de PRD-002. Cobertura actual compositiva (handler unit + ExceptionFilter unit + DI wiring test en `/arbol`). - **W2 — título tooltip divergente de spec**: resuelto en commit `a0a1874` — test aprieta match exacto del literal de impl ("El rubro contiene avisos asignados. Muévalos antes de agregar sub-rubros."). - **W3 — commit c3 duplicado en mensaje**: cosmetic, sin acción (requeriría rebase destructivo). - **W4 — `NullAvisoQueryRepository.CountAvisosBatchAsync` devuelve `{}` vs spec `{1:0,...}`**: design-intentional, todos los consumers usan `GetValueOrDefault(id, 0)`. Cerrado. ## Follow-ups - #36 — `[CAT-002 / Infra] TestWebApplicationFactory: desacoplar RSA singleton` (bloquea e2e override en PRD-002 y otros) ## Siguiente - Mergear este PR - PRD-002 reemplaza binding DI `IAvisoQueryRepository` → implementación real + activa `RubroEsRamaConHijosActivosException` en `CreateAvisoCommandHandler` - Considerar `RepeatableRead` o constraint DB para TOCTOU cuando exista `dbo.Aviso` ## Artifacts SDD (engram) - `sdd/cat-002-regla-oro-rama-vs-hoja/explore` - `sdd/cat-002-regla-oro-rama-vs-hoja/proposal` - `sdd/cat-002-regla-oro-rama-vs-hoja/spec` - `sdd/cat-002-regla-oro-rama-vs-hoja/design` - `sdd/cat-002-regla-oro-rama-vs-hoja/tasks` - `sdd/cat-002-regla-oro-rama-vs-hoja/apply-progress` - `sdd/cat-002-regla-oro-rama-vs-hoja/verify-report` - `sdd/cat-002-regla-oro-rama-vs-hoja/archive-report`
dmolinari added 8 commits 2026-04-19 11:41:45 +00:00
dmolinari added 1 commit 2026-04-19 11:52:39 +00:00
dmolinari merged commit d8d1da8ea4 into main 2026-04-19 11:56:32 +00:00
dmolinari deleted branch feature/CAT-002 2026-04-19 11:56:32 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dmolinari/SIG-CM2.0#35