243 lines
8.3 KiB
C#
243 lines
8.3 KiB
C#
using System.Reflection;
|
|
using FluentAssertions;
|
|
using SIGCM2.Domain.Fiscal;
|
|
using IibbDomain = SIGCM2.Domain.Entities.IngresosBrutos;
|
|
|
|
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 IibbDomain 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)
|
|
=> IibbDomain.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 = IibbDomain.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 = () => IibbDomain.ForCreation(ProvinciaArgentina.BuenosAires, "desc", -1m, Desde2020);
|
|
|
|
act.Should().Throw<ArgumentException>()
|
|
.WithParameterName("alicuota");
|
|
}
|
|
|
|
[Fact]
|
|
public void ForCreation_AlicuotaMayorA100_ThrowsArgumentException()
|
|
{
|
|
var act = () => IibbDomain.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 = () => IibbDomain.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 = () => IibbDomain.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(IibbDomain).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(IibbDomain).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 = IibbDomain.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);
|
|
}
|
|
}
|