diff --git a/src/api/SIGCM2.Domain/Exceptions/RubroEsRamaConHijosActivosException.cs b/src/api/SIGCM2.Domain/Exceptions/RubroEsRamaConHijosActivosException.cs new file mode 100644 index 0000000..84bfda6 --- /dev/null +++ b/src/api/SIGCM2.Domain/Exceptions/RubroEsRamaConHijosActivosException.cs @@ -0,0 +1,19 @@ +namespace SIGCM2.Domain.Exceptions; + +/// +/// Thrown when attempting to assign an aviso to a rubro that has active children. +/// Invariante: un nodo con hijos activos es RAMA — no puede recibir avisos directos. → HTTP 409 +/// NOTE: no handler launches this in CAT-002. Consumer: PRD-002 CreateAvisoCommandHandler. +/// +public sealed class RubroEsRamaConHijosActivosException : DomainException +{ + public int RubroId { get; } + public int CantidadHijos { get; } + + public RubroEsRamaConHijosActivosException(int rubroId, int cantidadHijos) + : base($"El destino tiene sub-rubros. No puede contener avisos directos.") + { + RubroId = rubroId; + CantidadHijos = cantidadHijos; + } +} diff --git a/src/api/SIGCM2.Domain/Exceptions/RubroPadreEsHojaConAvisosException.cs b/src/api/SIGCM2.Domain/Exceptions/RubroPadreEsHojaConAvisosException.cs new file mode 100644 index 0000000..143e785 --- /dev/null +++ b/src/api/SIGCM2.Domain/Exceptions/RubroPadreEsHojaConAvisosException.cs @@ -0,0 +1,18 @@ +namespace SIGCM2.Domain.Exceptions; + +/// +/// Thrown when attempting to create or move a child into a rubro that already has avisos assigned. +/// Invariante: un nodo con avisos es HOJA — no puede tener hijos. → HTTP 409 +/// +public sealed class RubroPadreEsHojaConAvisosException : DomainException +{ + public int ParentId { get; } + public int CantidadAvisos { get; } + + public RubroPadreEsHojaConAvisosException(int parentId, int cantidadAvisos) + : base($"El rubro padre contiene {cantidadAvisos} avisos. Muévalos antes de crear sub-rubros.") + { + ParentId = parentId; + CantidadAvisos = cantidadAvisos; + } +} diff --git a/tests/SIGCM2.Application.Tests/Domain/Rubros/RubroReglaDeOroExceptionsTests.cs b/tests/SIGCM2.Application.Tests/Domain/Rubros/RubroReglaDeOroExceptionsTests.cs new file mode 100644 index 0000000..6327d5b --- /dev/null +++ b/tests/SIGCM2.Application.Tests/Domain/Rubros/RubroReglaDeOroExceptionsTests.cs @@ -0,0 +1,61 @@ +using FluentAssertions; +using SIGCM2.Domain.Exceptions; + +namespace SIGCM2.Application.Tests.Domain.Rubros; + +public class RubroReglaDeOroExceptionsTests +{ + // ── RubroPadreEsHojaConAvisosException ────────────────────────────────── + + [Fact] + public void RubroPadreEsHojaConAvisosException_Constructor_SetsMessage() + { + var ex = new RubroPadreEsHojaConAvisosException(parentId: 42, cantidadAvisos: 3); + + ex.Message.Should().Be("El rubro padre contiene 3 avisos. Muévalos antes de crear sub-rubros."); + } + + [Fact] + public void RubroPadreEsHojaConAvisosException_Constructor_SetsParentId_Y_CantidadAvisos() + { + var ex = new RubroPadreEsHojaConAvisosException(parentId: 42, cantidadAvisos: 3); + + ex.ParentId.Should().Be(42); + ex.CantidadAvisos.Should().Be(3); + } + + [Fact] + public void RubroPadreEsHojaConAvisosException_IsA_DomainException() + { + var ex = new RubroPadreEsHojaConAvisosException(parentId: 1, cantidadAvisos: 1); + + ex.Should().BeAssignableTo(); + } + + // ── RubroEsRamaConHijosActivosException ───────────────────────────────── + + [Fact] + public void RubroEsRamaConHijosActivosException_Constructor_SetsMessage() + { + var ex = new RubroEsRamaConHijosActivosException(rubroId: 7, cantidadHijos: 2); + + ex.Message.Should().Be("El destino tiene sub-rubros. No puede contener avisos directos."); + } + + [Fact] + public void RubroEsRamaConHijosActivosException_Constructor_SetsRubroId_Y_CantidadHijos() + { + var ex = new RubroEsRamaConHijosActivosException(rubroId: 7, cantidadHijos: 2); + + ex.RubroId.Should().Be(7); + ex.CantidadHijos.Should().Be(2); + } + + [Fact] + public void RubroEsRamaConHijosActivosException_IsA_DomainException() + { + var ex = new RubroEsRamaConHijosActivosException(rubroId: 1, cantidadHijos: 1); + + ex.Should().BeAssignableTo(); + } +}