feat(domain): RubroConProductosActivosException + guard en DeactivateRubro (closes #41) #44

Merged
dmolinari merged 4 commits from fix/issue-41-rubro-deactivation-guard into main 2026-04-19 20:09:38 +00:00
Owner

Summary

  • Nueva RubroConProductosActivosException(rubroId, productosActivosCount) en Domain → HTTP 409 con error code rubro_con_productos_activos
  • IProductQueryRepository extendido con CountActiveByRubroAsync(rubroId, ct) — impl real Dapper
  • DeactivateRubroCommandHandler injecta IProductQueryRepository y ejecuta el guard después del check de hijos activos (orden: NotFound → ActiveChildren → ActiveProducts → deactivate)
  • Cierra el gap detectado en PRD-002 donde desactivar un Rubro con Products activos referenciándolo los dejaba huérfanos

Test plan

  • Domain: RubroConProductosActivosExceptionTests (2 tests)
  • Application unit: DeactivateRubroCommandHandlerTests extendido con 3 tests (throws con Products activos, OK con 0, order of checks — ActiveChildren antes que Products)
  • Infrastructure integration: ProductQueryRepository.CountActiveByRubroAsync con 3 tests (active count correcto, inactive excluidos, otros rubros excluidos)
  • Api e2e: DELETE /api/v1/admin/rubros/{id} con fake IProductQueryRepository via CreateClientWithOverrides → 409 + error code
  • 1744 total tests green (1021 Application + 289 Api + 434 frontend, +10 vs baseline 1734)

Gotcha resuelto

AlwaysInUseProductQueryRepository fake en ProductTypesControllerTests tuvo que stubear el nuevo método de interfaz (return 0). Inserts de integration tests en Product usan nombres únicos por UQ filtered.

Closes

Closes #41

Artifacts

  • Issue #41 — PRD-002 Rubro deactivation guard (diferido por scope discipline en proposal)
  • Archive-report PRD-002 (engram sdd/prd-002-product-crud/archive-report)
## Summary - Nueva `RubroConProductosActivosException(rubroId, productosActivosCount)` en Domain → HTTP 409 con error code `rubro_con_productos_activos` - `IProductQueryRepository` extendido con `CountActiveByRubroAsync(rubroId, ct)` — impl real Dapper - `DeactivateRubroCommandHandler` injecta `IProductQueryRepository` y ejecuta el guard después del check de hijos activos (orden: NotFound → ActiveChildren → ActiveProducts → deactivate) - Cierra el gap detectado en PRD-002 donde desactivar un Rubro con Products activos referenciándolo los dejaba huérfanos ## Test plan - [x] Domain: `RubroConProductosActivosExceptionTests` (2 tests) - [x] Application unit: `DeactivateRubroCommandHandlerTests` extendido con 3 tests (throws con Products activos, OK con 0, order of checks — ActiveChildren antes que Products) - [x] Infrastructure integration: `ProductQueryRepository.CountActiveByRubroAsync` con 3 tests (active count correcto, inactive excluidos, otros rubros excluidos) - [x] Api e2e: DELETE `/api/v1/admin/rubros/{id}` con fake IProductQueryRepository via `CreateClientWithOverrides` → 409 + error code - [x] **1744 total tests green** (1021 Application + 289 Api + 434 frontend, +10 vs baseline 1734) ## Gotcha resuelto `AlwaysInUseProductQueryRepository` fake en `ProductTypesControllerTests` tuvo que stubear el nuevo método de interfaz (return 0). Inserts de integration tests en Product usan nombres únicos por UQ filtered. ## Closes Closes #41 ## Artifacts - Issue #41 — PRD-002 Rubro deactivation guard (diferido por scope discipline en proposal) - Archive-report PRD-002 (engram `sdd/prd-002-product-crud/archive-report`)
dmolinari added 4 commits 2026-04-19 20:09:34 +00:00
Co-authored-by: fix/issue-41-rubro-deactivation-guard
Extiende IProductQueryRepository con CountActiveByRubroAsync, inyecta
el repositorio en el handler e intercala el chequeo después del guard
de hijos activos. Tests de unidad cubren: throw, success con 0 productos,
y estabilidad del orden de guardas (hijos primero).
Implementa SELECT COUNT(1) FROM dbo.Product WHERE RubroId = @RubroId AND IsActive = 1.
Tests de integración verifican: 0 sin productos, count correcto con mix
activos/inactivos/otro rubro, y solo inactivos retorna 0.
Mapea RubroConProductosActivosException → HTTP 409 con error code
rubro_con_productos_activos. Test e2e usa DI override (patrón issue #36)
para stub IProductQueryRepository sin sembrar Products reales en DB.
dmolinari merged commit e735afb5b4 into main 2026-04-19 20:09:38 +00:00
dmolinari deleted branch fix/issue-41-rubro-deactivation-guard 2026-04-19 20:09:38 +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#44