diff --git a/src/api/SIGCM2.Api/Filters/ExceptionFilter.cs b/src/api/SIGCM2.Api/Filters/ExceptionFilter.cs
index bf0f054..f43eac9 100644
--- a/src/api/SIGCM2.Api/Filters/ExceptionFilter.cs
+++ b/src/api/SIGCM2.Api/Filters/ExceptionFilter.cs
@@ -169,6 +169,79 @@ public sealed class ExceptionFilter : IExceptionFilter
context.ExceptionHandled = true;
break;
+ // CAT-001: Rubro exceptions
+ case RubroNotFoundException rubroNotFoundEx:
+ context.Result = new ObjectResult(new
+ {
+ error = "rubro_not_found",
+ message = rubroNotFoundEx.Message
+ })
+ {
+ StatusCode = StatusCodes.Status404NotFound
+ };
+ context.ExceptionHandled = true;
+ break;
+
+ case RubroNombreDuplicadoEnPadreException rubroDupEx:
+ context.Result = new ObjectResult(new
+ {
+ error = "rubro_nombre_duplicado",
+ message = rubroDupEx.Message
+ })
+ {
+ StatusCode = StatusCodes.Status409Conflict
+ };
+ context.ExceptionHandled = true;
+ break;
+
+ case RubroTieneHijosActivosException rubroHijosEx:
+ context.Result = new ObjectResult(new
+ {
+ error = "rubro_tiene_hijos_activos",
+ message = rubroHijosEx.Message
+ })
+ {
+ StatusCode = StatusCodes.Status409Conflict
+ };
+ context.ExceptionHandled = true;
+ break;
+
+ case RubroPadreInactivoException rubroPadreEx:
+ context.Result = new ObjectResult(new
+ {
+ error = "rubro_padre_inactivo",
+ message = rubroPadreEx.Message
+ })
+ {
+ StatusCode = StatusCodes.Status400BadRequest
+ };
+ context.ExceptionHandled = true;
+ break;
+
+ case RubroMaxDepthExceededException rubroDepthEx:
+ context.Result = new ObjectResult(new
+ {
+ error = "rubro_max_depth_exceeded",
+ message = rubroDepthEx.Message
+ })
+ {
+ StatusCode = StatusCodes.Status422UnprocessableEntity
+ };
+ context.ExceptionHandled = true;
+ break;
+
+ case RubroCycleDetectedException rubroCycleEx:
+ context.Result = new ObjectResult(new
+ {
+ error = "rubro_cycle_detected",
+ message = rubroCycleEx.Message
+ })
+ {
+ StatusCode = StatusCodes.Status400BadRequest
+ };
+ context.ExceptionHandled = true;
+ break;
+
// ADM-001: Medio exceptions
case MedioCodigoDuplicadoException medioCodDupEx:
context.Result = new ObjectResult(new
diff --git a/src/api/SIGCM2.Domain/Entities/Rubro.cs b/src/api/SIGCM2.Domain/Entities/Rubro.cs
new file mode 100644
index 0000000..582a7a0
--- /dev/null
+++ b/src/api/SIGCM2.Domain/Entities/Rubro.cs
@@ -0,0 +1,139 @@
+namespace SIGCM2.Domain.Entities;
+
+///
+/// Immutable N-ary tree node for the commercial catalog taxonomy.
+/// Follows the same sealed-class + factory + with-methods pattern as Medio.cs.
+///
+public sealed class Rubro
+{
+ private const int NombreMaxLength = 200;
+
+ public int Id { get; }
+ public int? ParentId { get; }
+ public string Nombre { get; }
+ public int Orden { get; }
+ public bool Activo { get; }
+ public int? TarifarioBaseId { get; }
+ public DateTime FechaCreacion { get; }
+ public DateTime? FechaModificacion { get; }
+
+ ///
+ /// Full hydration constructor — used by the repository to reconstruct from DB rows.
+ ///
+ public Rubro(
+ int id,
+ int? parentId,
+ string nombre,
+ int orden,
+ bool activo,
+ int? tarifarioBaseId,
+ DateTime fechaCreacion,
+ DateTime? fechaModificacion)
+ {
+ Id = id;
+ ParentId = parentId;
+ Nombre = nombre;
+ Orden = orden;
+ Activo = activo;
+ TarifarioBaseId = tarifarioBaseId;
+ FechaCreacion = fechaCreacion;
+ FechaModificacion = fechaModificacion;
+ }
+
+ ///
+ /// Factory for creating a new Rubro.
+ /// Id=0 — DB assigns via IDENTITY.
+ /// Activo=true, FechaModificacion=null by default.
+ /// FechaCreacion is set from TimeProvider so it is testable.
+ ///
+ public static Rubro ForCreation(
+ string nombre,
+ int? parentId,
+ int orden,
+ int? tarifarioBaseId,
+ TimeProvider timeProvider)
+ {
+ ValidateNombre(nombre);
+
+ if (parentId.HasValue && parentId.Value <= 0)
+ throw new ArgumentException("parentId debe ser un entero positivo cuando no es nulo.", nameof(parentId));
+
+ if (tarifarioBaseId.HasValue && tarifarioBaseId.Value < 0)
+ throw new ArgumentException("tarifarioBaseId no puede ser negativo.", nameof(tarifarioBaseId));
+
+ return new Rubro(
+ id: 0,
+ parentId: parentId,
+ nombre: nombre,
+ orden: orden,
+ activo: true,
+ tarifarioBaseId: tarifarioBaseId,
+ fechaCreacion: timeProvider.GetUtcNow().UtcDateTime,
+ fechaModificacion: null);
+ }
+
+ ///
+ /// Returns a new Rubro instance with an updated Nombre and FechaModificacion.
+ /// Does NOT mutate the current instance.
+ ///
+ public Rubro WithRenamed(string nuevoNombre, TimeProvider timeProvider)
+ {
+ ValidateNombre(nuevoNombre);
+
+ return new Rubro(
+ id: Id,
+ parentId: ParentId,
+ nombre: nuevoNombre,
+ orden: Orden,
+ activo: Activo,
+ tarifarioBaseId: TarifarioBaseId,
+ fechaCreacion: FechaCreacion,
+ fechaModificacion: timeProvider.GetUtcNow().UtcDateTime);
+ }
+
+ ///
+ /// Returns a new Rubro instance with updated ParentId and Orden.
+ /// Does NOT mutate the current instance.
+ ///
+ public Rubro WithMoved(int? nuevoParentId, int nuevoOrden, TimeProvider timeProvider)
+ {
+ return new Rubro(
+ id: Id,
+ parentId: nuevoParentId,
+ nombre: Nombre,
+ orden: nuevoOrden,
+ activo: Activo,
+ tarifarioBaseId: TarifarioBaseId,
+ fechaCreacion: FechaCreacion,
+ fechaModificacion: timeProvider.GetUtcNow().UtcDateTime);
+ }
+
+ ///
+ /// Returns a new Rubro instance with updated Activo flag.
+ /// Use Deactivate (false) or Reactivate (true).
+ /// Does NOT mutate the current instance.
+ ///
+ public Rubro WithActivo(bool activo, TimeProvider timeProvider)
+ {
+ return new Rubro(
+ id: Id,
+ parentId: ParentId,
+ nombre: Nombre,
+ orden: Orden,
+ activo: activo,
+ tarifarioBaseId: TarifarioBaseId,
+ fechaCreacion: FechaCreacion,
+ fechaModificacion: timeProvider.GetUtcNow().UtcDateTime);
+ }
+
+ private static void ValidateNombre(string nombre)
+ {
+ if (string.IsNullOrWhiteSpace(nombre))
+ throw new ArgumentException("El nombre del rubro no puede estar vacío o ser solo espacios.", nameof(nombre));
+
+ if (nombre.Length > NombreMaxLength)
+ throw new ArgumentException(
+ $"El nombre del rubro no puede superar los {NombreMaxLength} caracteres.",
+ nameof(nombre));
+ }
+}
diff --git a/src/api/SIGCM2.Domain/Exceptions/RubroCycleDetectedException.cs b/src/api/SIGCM2.Domain/Exceptions/RubroCycleDetectedException.cs
new file mode 100644
index 0000000..c86a387
--- /dev/null
+++ b/src/api/SIGCM2.Domain/Exceptions/RubroCycleDetectedException.cs
@@ -0,0 +1,17 @@
+namespace SIGCM2.Domain.Exceptions;
+
+///
+/// Thrown when moving a Rubro to one of its own descendants would create a cycle. → HTTP 400
+///
+public sealed class RubroCycleDetectedException : DomainException
+{
+ public int RubroId { get; }
+ public int NuevoParentId { get; }
+
+ public RubroCycleDetectedException(int rubroId, int nuevoParentId)
+ : base($"Mover el rubro '{rubroId}' al padre '{nuevoParentId}' crearía un ciclo en el árbol.")
+ {
+ RubroId = rubroId;
+ NuevoParentId = nuevoParentId;
+ }
+}
diff --git a/src/api/SIGCM2.Domain/Exceptions/RubroMaxDepthExceededException.cs b/src/api/SIGCM2.Domain/Exceptions/RubroMaxDepthExceededException.cs
new file mode 100644
index 0000000..d993955
--- /dev/null
+++ b/src/api/SIGCM2.Domain/Exceptions/RubroMaxDepthExceededException.cs
@@ -0,0 +1,17 @@
+namespace SIGCM2.Domain.Exceptions;
+
+///
+/// Thrown when creating or moving a Rubro would exceed the configured maximum tree depth. → HTTP 422
+///
+public sealed class RubroMaxDepthExceededException : DomainException
+{
+ public int Intentada { get; }
+ public int Max { get; }
+
+ public RubroMaxDepthExceededException(int intentada, int max)
+ : base($"La profundidad intentada ({intentada}) excede el máximo permitido ({max}).")
+ {
+ Intentada = intentada;
+ Max = max;
+ }
+}
diff --git a/src/api/SIGCM2.Domain/Exceptions/RubroNombreDuplicadoEnPadreException.cs b/src/api/SIGCM2.Domain/Exceptions/RubroNombreDuplicadoEnPadreException.cs
new file mode 100644
index 0000000..1b0b284
--- /dev/null
+++ b/src/api/SIGCM2.Domain/Exceptions/RubroNombreDuplicadoEnPadreException.cs
@@ -0,0 +1,19 @@
+namespace SIGCM2.Domain.Exceptions;
+
+///
+/// Thrown when a Rubro with the same Nombre (CI) already exists under the same parent. → HTTP 409
+///
+public sealed class RubroNombreDuplicadoEnPadreException : DomainException
+{
+ public string Nombre { get; }
+ public int? ParentId { get; }
+
+ public RubroNombreDuplicadoEnPadreException(string nombre, int? parentId)
+ : base(parentId.HasValue
+ ? $"Ya existe un rubro con el nombre '{nombre}' bajo el padre con id '{parentId}'."
+ : $"Ya existe un rubro raíz con el nombre '{nombre}'.")
+ {
+ Nombre = nombre;
+ ParentId = parentId;
+ }
+}
diff --git a/src/api/SIGCM2.Domain/Exceptions/RubroNotFoundException.cs b/src/api/SIGCM2.Domain/Exceptions/RubroNotFoundException.cs
new file mode 100644
index 0000000..c1b4f28
--- /dev/null
+++ b/src/api/SIGCM2.Domain/Exceptions/RubroNotFoundException.cs
@@ -0,0 +1,15 @@
+namespace SIGCM2.Domain.Exceptions;
+
+///
+/// Thrown when a requested Rubro does not exist in the system. → HTTP 404
+///
+public sealed class RubroNotFoundException : DomainException
+{
+ public int Id { get; }
+
+ public RubroNotFoundException(int id)
+ : base($"El rubro con id '{id}' no existe.")
+ {
+ Id = id;
+ }
+}
diff --git a/src/api/SIGCM2.Domain/Exceptions/RubroPadreInactivoException.cs b/src/api/SIGCM2.Domain/Exceptions/RubroPadreInactivoException.cs
new file mode 100644
index 0000000..08bf642
--- /dev/null
+++ b/src/api/SIGCM2.Domain/Exceptions/RubroPadreInactivoException.cs
@@ -0,0 +1,15 @@
+namespace SIGCM2.Domain.Exceptions;
+
+///
+/// Thrown when attempting to create or move a Rubro under an inactive parent. → HTTP 400
+///
+public sealed class RubroPadreInactivoException : DomainException
+{
+ public int ParentId { get; }
+
+ public RubroPadreInactivoException(int parentId)
+ : base($"El padre con id '{parentId}' está inactivo y no puede tener hijos.")
+ {
+ ParentId = parentId;
+ }
+}
diff --git a/src/api/SIGCM2.Domain/Exceptions/RubroTieneHijosActivosException.cs b/src/api/SIGCM2.Domain/Exceptions/RubroTieneHijosActivosException.cs
new file mode 100644
index 0000000..4df437f
--- /dev/null
+++ b/src/api/SIGCM2.Domain/Exceptions/RubroTieneHijosActivosException.cs
@@ -0,0 +1,17 @@
+namespace SIGCM2.Domain.Exceptions;
+
+///
+/// Thrown when attempting to soft-delete a Rubro that still has active children. → HTTP 409
+///
+public sealed class RubroTieneHijosActivosException : DomainException
+{
+ public int Id { get; }
+ public int Count { get; }
+
+ public RubroTieneHijosActivosException(int id, int count)
+ : base($"El rubro con id '{id}' tiene {count} subrubros activos.")
+ {
+ Id = id;
+ Count = count;
+ }
+}
diff --git a/tests/SIGCM2.Application.Tests/Domain/Rubros/RubroExceptionsTests.cs b/tests/SIGCM2.Application.Tests/Domain/Rubros/RubroExceptionsTests.cs
new file mode 100644
index 0000000..e55a283
--- /dev/null
+++ b/tests/SIGCM2.Application.Tests/Domain/Rubros/RubroExceptionsTests.cs
@@ -0,0 +1,137 @@
+using FluentAssertions;
+using SIGCM2.Domain.Exceptions;
+
+namespace SIGCM2.Application.Tests.Domain.Rubros;
+
+public class RubroExceptionsTests
+{
+ // ── RubroNotFoundException ───────────────────────────────────────────────
+
+ [Fact]
+ public void RubroNotFoundException_ContainsId()
+ {
+ var ex = new RubroNotFoundException(42);
+
+ ex.Id.Should().Be(42);
+ ex.Message.Should().Contain("42");
+ }
+
+ [Fact]
+ public void RubroNotFoundException_InheritsFromDomainException()
+ {
+ var ex = new RubroNotFoundException(1);
+
+ ex.Should().BeAssignableTo();
+ }
+
+ // ── RubroNombreDuplicadoEnPadreException ─────────────────────────────────
+
+ [Fact]
+ public void RubroNombreDuplicadoEnPadreException_ContainsNombreAndParentId()
+ {
+ var ex = new RubroNombreDuplicadoEnPadreException("Autos", parentId: 5);
+
+ ex.Nombre.Should().Be("Autos");
+ ex.ParentId.Should().Be(5);
+ ex.Message.Should().Contain("Autos");
+ }
+
+ [Fact]
+ public void RubroNombreDuplicadoEnPadreException_WithNullParent_IsValid()
+ {
+ var ex = new RubroNombreDuplicadoEnPadreException("Autos", parentId: null);
+
+ ex.Nombre.Should().Be("Autos");
+ ex.ParentId.Should().BeNull();
+ }
+
+ [Fact]
+ public void RubroNombreDuplicadoEnPadreException_InheritsFromDomainException()
+ {
+ var ex = new RubroNombreDuplicadoEnPadreException("x", null);
+
+ ex.Should().BeAssignableTo();
+ }
+
+ // ── RubroMaxDepthExceededException ───────────────────────────────────────
+
+ [Fact]
+ public void RubroMaxDepthExceededException_ContainsDepthInfo()
+ {
+ var ex = new RubroMaxDepthExceededException(intentada: 11, max: 10);
+
+ ex.Intentada.Should().Be(11);
+ ex.Max.Should().Be(10);
+ ex.Message.Should().Contain("11");
+ ex.Message.Should().Contain("10");
+ }
+
+ [Fact]
+ public void RubroMaxDepthExceededException_InheritsFromDomainException()
+ {
+ var ex = new RubroMaxDepthExceededException(11, 10);
+
+ ex.Should().BeAssignableTo();
+ }
+
+ // ── RubroCycleDetectedException ──────────────────────────────────────────
+
+ [Fact]
+ public void RubroCycleDetectedException_ContainsRubroIdAndIntendedParentId()
+ {
+ var ex = new RubroCycleDetectedException(rubroId: 5, nuevoParentId: 10);
+
+ ex.RubroId.Should().Be(5);
+ ex.NuevoParentId.Should().Be(10);
+ ex.Message.Should().Contain("5");
+ ex.Message.Should().Contain("10");
+ }
+
+ [Fact]
+ public void RubroCycleDetectedException_InheritsFromDomainException()
+ {
+ var ex = new RubroCycleDetectedException(1, 2);
+
+ ex.Should().BeAssignableTo();
+ }
+
+ // ── RubroTieneHijosActivosException ─────────────────────────────────────
+
+ [Fact]
+ public void RubroTieneHijosActivosException_ContainsIdAndCount()
+ {
+ var ex = new RubroTieneHijosActivosException(id: 7, count: 3);
+
+ ex.Id.Should().Be(7);
+ ex.Count.Should().Be(3);
+ ex.Message.Should().Contain("3");
+ ex.Message.Should().Contain("subrubros");
+ }
+
+ [Fact]
+ public void RubroTieneHijosActivosException_InheritsFromDomainException()
+ {
+ var ex = new RubroTieneHijosActivosException(1, 2);
+
+ ex.Should().BeAssignableTo();
+ }
+
+ // ── RubroPadreInactivoException ──────────────────────────────────────────
+
+ [Fact]
+ public void RubroPadreInactivoException_ContainsParentId()
+ {
+ var ex = new RubroPadreInactivoException(parentId: 9);
+
+ ex.ParentId.Should().Be(9);
+ ex.Message.Should().Contain("9");
+ }
+
+ [Fact]
+ public void RubroPadreInactivoException_InheritsFromDomainException()
+ {
+ var ex = new RubroPadreInactivoException(1);
+
+ ex.Should().BeAssignableTo();
+ }
+}
diff --git a/tests/SIGCM2.Application.Tests/Domain/Rubros/RubroTests.cs b/tests/SIGCM2.Application.Tests/Domain/Rubros/RubroTests.cs
new file mode 100644
index 0000000..2688bfd
--- /dev/null
+++ b/tests/SIGCM2.Application.Tests/Domain/Rubros/RubroTests.cs
@@ -0,0 +1,171 @@
+using FluentAssertions;
+using Microsoft.Extensions.Time.Testing;
+using SIGCM2.Domain.Entities;
+
+namespace SIGCM2.Application.Tests.Domain.Rubros;
+
+public class RubroTests
+{
+ private static readonly FakeTimeProvider FakeTime = new(new DateTimeOffset(2026, 4, 18, 12, 0, 0, TimeSpan.Zero));
+
+ // ── ForCreation: happy path ──────────────────────────────────────────────
+
+ [Fact]
+ public void Create_con_datos_validos_crea_rubro_activo_con_orden_cero_como_default()
+ {
+ var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime);
+
+ rubro.Nombre.Should().Be("Autos");
+ rubro.ParentId.Should().BeNull();
+ rubro.Orden.Should().Be(0);
+ rubro.Activo.Should().BeTrue();
+ rubro.TarifarioBaseId.Should().BeNull();
+ rubro.Id.Should().Be(0);
+ rubro.FechaCreacion.Should().Be(FakeTime.GetUtcNow().UtcDateTime);
+ rubro.FechaModificacion.Should().BeNull();
+ }
+
+ [Fact]
+ public void Create_root_con_parentId_null_es_valido()
+ {
+ var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime);
+
+ rubro.ParentId.Should().BeNull();
+ }
+
+ // ── ForCreation: validations ─────────────────────────────────────────────
+
+ [Fact]
+ public void Create_con_nombre_vacio_lanza_ArgumentException()
+ {
+ var act = () => Rubro.ForCreation("", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime);
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public void Create_con_nombre_solo_whitespace_lanza_ArgumentException()
+ {
+ var act = () => Rubro.ForCreation(" ", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime);
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public void Create_con_nombre_excediendo_200_chars_lanza_ArgumentException()
+ {
+ var nombre = new string('A', 201);
+
+ var act = () => Rubro.ForCreation(nombre, parentId: null, orden: 0, tarifarioBaseId: null, FakeTime);
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public void Create_con_parentId_menor_o_igual_a_cero_lanza_ArgumentException()
+ {
+ var act = () => Rubro.ForCreation("Autos", parentId: 0, orden: 0, tarifarioBaseId: null, FakeTime);
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public void Create_con_tarifarioBaseId_menor_a_cero_lanza_ArgumentException()
+ {
+ var act = () => Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: -1, FakeTime);
+
+ act.Should().Throw();
+ }
+
+ // ── WithRenamed ──────────────────────────────────────────────────────────
+
+ [Fact]
+ public void Rename_con_nombre_valido_devuelve_nueva_instancia_con_FechaModificacion()
+ {
+ var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime);
+ var laterTime = new FakeTimeProvider(new DateTimeOffset(2026, 4, 18, 14, 0, 0, TimeSpan.Zero));
+
+ var renamed = rubro.WithRenamed("Vehiculos", laterTime);
+
+ renamed.Nombre.Should().Be("Vehiculos");
+ renamed.FechaModificacion.Should().Be(laterTime.GetUtcNow().UtcDateTime);
+ }
+
+ [Fact]
+ public void Rename_con_nombre_invalido_lanza_ArgumentException()
+ {
+ var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime);
+
+ var act = () => rubro.WithRenamed("", FakeTime);
+
+ act.Should().Throw();
+ }
+
+ [Fact]
+ public void Rename_no_muta_la_instancia_original()
+ {
+ var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime);
+
+ rubro.WithRenamed("Vehiculos", FakeTime);
+
+ rubro.Nombre.Should().Be("Autos");
+ }
+
+ // ── WithMoved ────────────────────────────────────────────────────────────
+
+ [Fact]
+ public void Move_a_nuevo_parent_devuelve_nueva_instancia_con_parentId_actualizado()
+ {
+ var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime);
+
+ var moved = rubro.WithMoved(nuevoParentId: 5, nuevoOrden: 2, FakeTime);
+
+ moved.ParentId.Should().Be(5);
+ moved.Orden.Should().Be(2);
+ }
+
+ [Fact]
+ public void Move_a_root_permite_parentId_null()
+ {
+ var rubro = Rubro.ForCreation("Autos", parentId: 3, orden: 0, tarifarioBaseId: null, FakeTime);
+
+ var moved = rubro.WithMoved(nuevoParentId: null, nuevoOrden: 0, FakeTime);
+
+ moved.ParentId.Should().BeNull();
+ }
+
+ [Fact]
+ public void Move_no_muta_la_instancia_original()
+ {
+ var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime);
+
+ rubro.WithMoved(nuevoParentId: 5, nuevoOrden: 1, FakeTime);
+
+ rubro.ParentId.Should().BeNull();
+ rubro.Orden.Should().Be(0);
+ }
+
+ // ── WithActivo (Deactivate / Reactivate) ────────────────────────────────
+
+ [Fact]
+ public void Deactivate_flip_Activo_a_false()
+ {
+ var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime);
+
+ var deactivated = rubro.WithActivo(false, FakeTime);
+
+ deactivated.Activo.Should().BeFalse();
+ deactivated.FechaModificacion.Should().Be(FakeTime.GetUtcNow().UtcDateTime);
+ }
+
+ [Fact]
+ public void Reactivate_flip_Activo_a_true()
+ {
+ var rubro = Rubro.ForCreation("Autos", parentId: null, orden: 0, tarifarioBaseId: null, FakeTime);
+ var deactivated = rubro.WithActivo(false, FakeTime);
+
+ var reactivated = deactivated.WithActivo(true, FakeTime);
+
+ reactivated.Activo.Should().BeTrue();
+ }
+}