From 87364ff8e6dd446c7b9a2be9af8e9be13c08b68d Mon Sep 17 00:00:00 2001 From: dmolinari Date: Fri, 17 Apr 2026 17:49:46 -0300 Subject: [PATCH] test(adm-009): IngresosBrutos entity tests (Red) --- .../Domain/Fiscal/IngresosBrutosTests.cs | 242 ++++++++++++++++++ 1 file changed, 242 insertions(+) create mode 100644 tests/SIGCM2.Application.Tests/Domain/Fiscal/IngresosBrutosTests.cs diff --git a/tests/SIGCM2.Application.Tests/Domain/Fiscal/IngresosBrutosTests.cs b/tests/SIGCM2.Application.Tests/Domain/Fiscal/IngresosBrutosTests.cs new file mode 100644 index 0000000..4a98d78 --- /dev/null +++ b/tests/SIGCM2.Application.Tests/Domain/Fiscal/IngresosBrutosTests.cs @@ -0,0 +1,242 @@ +using System.Reflection; +using FluentAssertions; +using SIGCM2.Domain.Entities; +using SIGCM2.Domain.Fiscal; + +namespace SIGCM2.Application.Tests.Domain.Fiscal; + +public class IngresosBrutosTests +{ + private static readonly DateOnly Desde2020 = new(2020, 1, 1); + private static readonly DateOnly Desde2026 = new(2026, 6, 1); + + private static IngresosBrutos MakeIIBB( + int id = 1, + ProvinciaArgentina provincia = ProvinciaArgentina.BuenosAires, + string descripcion = "IIBB Buenos Aires", + decimal alicuota = 3.5m, + bool activo = true, + DateOnly? vigenciaDesde = null, + DateOnly? vigenciaHasta = null, + int? predecesorId = null) + => IngresosBrutos.FromDb( + id: id, + provincia: provincia, + descripcion: descripcion, + alicuota: alicuota, + activo: activo, + vigenciaDesde: vigenciaDesde ?? Desde2020, + vigenciaHasta: vigenciaHasta, + predecesorId: predecesorId, + fechaCreacion: DateTime.UtcNow, + fechaModificacion: null); + + // ── T200.20: ForCreation validations ────────────────────────────────────── + + [Fact] + public void ForCreation_ValidArgs_ReturnsEntity() + { + var iibb = IngresosBrutos.ForCreation(ProvinciaArgentina.Cordoba, "IIBB Córdoba", 2.5m, Desde2020); + + iibb.Provincia.Should().Be(ProvinciaArgentina.Cordoba); + iibb.Descripcion.Should().Be("IIBB Córdoba"); + iibb.Alicuota.Should().Be(2.5m); + iibb.Activo.Should().BeTrue(); + iibb.Id.Should().Be(0); + iibb.PredecesorId.Should().BeNull(); + iibb.VigenciaHasta.Should().BeNull(); + } + + [Fact] + public void ForCreation_AlicuotaNegativa_ThrowsArgumentException() + { + var act = () => IngresosBrutos.ForCreation(ProvinciaArgentina.BuenosAires, "desc", -1m, Desde2020); + + act.Should().Throw() + .WithParameterName("alicuota"); + } + + [Fact] + public void ForCreation_AlicuotaMayorA100_ThrowsArgumentException() + { + var act = () => IngresosBrutos.ForCreation(ProvinciaArgentina.BuenosAires, "desc", 101m, Desde2020); + + act.Should().Throw() + .WithParameterName("alicuota"); + } + + [Theory] + [InlineData(0)] + [InlineData(2.5)] + [InlineData(100)] + public void ForCreation_AlicuotaEnRango_NoLanza(double alicuota) + { + var act = () => IngresosBrutos.ForCreation(ProvinciaArgentina.Salta, "desc", (decimal)alicuota, Desde2020); + + act.Should().NotThrow(); + } + + [Fact] + public void ForCreation_VigenciaHastaMenorQueDesde_ThrowsArgumentException() + { + var desde = new DateOnly(2026, 6, 1); + var hasta = new DateOnly(2026, 1, 1); + + var act = () => IngresosBrutos.ForCreation(ProvinciaArgentina.SantaFe, "desc", 3m, desde, hasta); + + act.Should().Throw() + .WithParameterName("vigenciaHasta"); + } + + // ── T200.22: With* methods ──────────────────────────────────────────────── + + [Fact] + public void WithDescripcion_ReturnsNewInstanceWithUpdatedDescripcion() + { + var original = MakeIIBB(descripcion: "Original"); + + var updated = original.WithDescripcion("Actualizado"); + + updated.Should().NotBeSameAs(original); + updated.Descripcion.Should().Be("Actualizado"); + updated.Alicuota.Should().Be(original.Alicuota, "Alicuota es inmutable"); + } + + [Fact] + public void Deactivate_ReturnsNewInstanceWithActivoFalse() + { + var original = MakeIIBB(activo: true); + + var deactivated = original.Deactivate(); + + deactivated.Activo.Should().BeFalse(); + deactivated.Alicuota.Should().Be(original.Alicuota); + deactivated.Id.Should().Be(original.Id); + } + + [Fact] + public void Reactivate_ReturnsNewInstanceWithActivoTrue() + { + var original = MakeIIBB(activo: false); + + var reactivated = original.Reactivate(); + + reactivated.Activo.Should().BeTrue(); + } + + [Fact] + public void CerrarVigencia_SetsVigenciaHasta() + { + var original = MakeIIBB(vigenciaHasta: null); + var hasta = new DateOnly(2026, 5, 31); + + var cerrado = original.CerrarVigencia(hasta); + + cerrado.VigenciaHasta.Should().Be(hasta); + cerrado.Alicuota.Should().Be(original.Alicuota); + } + + // ── T200.24: NuevaVersion tuple ─────────────────────────────────────────── + + [Fact] + public void NuevaVersion_ReturnsPredecesoraCerradaYNuevaVersion() + { + var predecesora = MakeIIBB(id: 5, alicuota: 2.5m, vigenciaDesde: Desde2020, vigenciaHasta: null); + + var (cerrada, nueva) = predecesora.NuevaVersion(3.0m, Desde2026); + + cerrada.Id.Should().Be(5); + cerrada.VigenciaHasta.Should().Be(Desde2026.AddDays(-1)); + cerrada.Alicuota.Should().Be(2.5m, "alicuota predecesora no cambia"); + + nueva.Id.Should().Be(0); + nueva.PredecesorId.Should().Be(5); + nueva.Alicuota.Should().Be(3.0m); + nueva.VigenciaDesde.Should().Be(Desde2026); + nueva.VigenciaHasta.Should().BeNull(); + nueva.Provincia.Should().Be(predecesora.Provincia, "hereda la provincia"); + nueva.Descripcion.Should().Be(predecesora.Descripcion, "hereda la descripción"); + nueva.Activo.Should().BeTrue(); + } + + [Fact] + public void NuevaVersion_PredecesoraConVigenciaHasta_ThrowsInvalidOperationException() + { + var predecesora = MakeIIBB( + vigenciaDesde: Desde2020, + vigenciaHasta: new DateOnly(2025, 12, 31)); + + var act = () => predecesora.NuevaVersion(4.0m, Desde2026); + + act.Should().Throw(); + } + + [Fact] + public void NuevaVersion_VigenciaDesdeIgualAPredecesora_ThrowsArgumentException() + { + var predecesora = MakeIIBB(vigenciaDesde: Desde2020, vigenciaHasta: null); + + var act = () => predecesora.NuevaVersion(4.0m, Desde2020); + + act.Should().Throw() + .WithParameterName("vigenciaDesde"); + } + + [Fact] + public void NuevaVersion_NuevaAlicuotaNegativa_ThrowsArgumentException() + { + var predecesora = MakeIIBB(vigenciaDesde: Desde2020, vigenciaHasta: null); + + var act = () => predecesora.NuevaVersion(-1m, Desde2026); + + act.Should().Throw() + .WithParameterName("nuevaAlicuota"); + } + + [Fact] + public void NuevaVersion_NuevaAlicuotaMayorA100_ThrowsArgumentException() + { + var predecesora = MakeIIBB(vigenciaDesde: Desde2020, vigenciaHasta: null); + + var act = () => predecesora.NuevaVersion(101m, Desde2026); + + act.Should().Throw() + .WithParameterName("nuevaAlicuota"); + } + + // ── T200.25: reflection — NO debe existir WithAlicuota ni WithProvincia ─── + + [Fact] + public void IngresosBrutos_No_Debe_Exponer_WithAlicuota() + { + var method = typeof(IngresosBrutos).GetMethod("WithAlicuota", BindingFlags.Public | BindingFlags.Instance); + + method.Should().BeNull("Alicuota es inmutable — usar NuevaVersion"); + } + + [Fact] + public void IngresosBrutos_No_Debe_Exponer_WithProvincia() + { + var method = typeof(IngresosBrutos).GetMethod("WithProvincia", BindingFlags.Public | BindingFlags.Instance); + + method.Should().BeNull("Provincia es inmutable en IngresosBrutos"); + } + + // ── FromDb sets all properties ──────────────────────────────────────────── + + [Fact] + public void FromDb_SetsAllProperties() + { + var fechaCreacion = DateTime.UtcNow; + var iibb = IngresosBrutos.FromDb( + id: 10, provincia: ProvinciaArgentina.Tucuman, descripcion: "IIBB Tucuman", + alicuota: 1.5m, activo: true, + vigenciaDesde: Desde2020, vigenciaHasta: null, + predecesorId: null, fechaCreacion: fechaCreacion, fechaModificacion: null); + + iibb.Id.Should().Be(10); + iibb.Provincia.Should().Be(ProvinciaArgentina.Tucuman); + iibb.Alicuota.Should().Be(1.5m); + iibb.FechaCreacion.Should().Be(fechaCreacion); + } +}