Files
SIG-CM2.0/tests/SIGCM2.Application.Tests/Domain/Fiscal/IngresosBrutosTests.cs

243 lines
8.3 KiB
C#
Raw Normal View History

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<ArgumentException>()
.WithParameterName("alicuota");
}
[Fact]
public void ForCreation_AlicuotaMayorA100_ThrowsArgumentException()
{
var act = () => IngresosBrutos.ForCreation(ProvinciaArgentina.BuenosAires, "desc", 101m, Desde2020);
act.Should().Throw<ArgumentException>()
.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<ArgumentException>()
.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<InvalidOperationException>();
}
[Fact]
public void NuevaVersion_VigenciaDesdeIgualAPredecesora_ThrowsArgumentException()
{
var predecesora = MakeIIBB(vigenciaDesde: Desde2020, vigenciaHasta: null);
var act = () => predecesora.NuevaVersion(4.0m, Desde2020);
act.Should().Throw<ArgumentException>()
.WithParameterName("vigenciaDesde");
}
[Fact]
public void NuevaVersion_NuevaAlicuotaNegativa_ThrowsArgumentException()
{
var predecesora = MakeIIBB(vigenciaDesde: Desde2020, vigenciaHasta: null);
var act = () => predecesora.NuevaVersion(-1m, Desde2026);
act.Should().Throw<ArgumentException>()
.WithParameterName("nuevaAlicuota");
}
[Fact]
public void NuevaVersion_NuevaAlicuotaMayorA100_ThrowsArgumentException()
{
var predecesora = MakeIIBB(vigenciaDesde: Desde2020, vigenciaHasta: null);
var act = () => predecesora.NuevaVersion(101m, Desde2026);
act.Should().Throw<ArgumentException>()
.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);
}
}