feat(application): DeactivateRubroCommandHandler guard contra Products activos
Extiende IProductQueryRepository con CountActiveByRubroAsync, inyecta el repositorio en el handler e intercala el chequeo después del guard de hijos activos. Tests de unidad cubren: throw, success con 0 productos, y estabilidad del orden de guardas (hijos primero).
This commit is contained in:
@@ -12,4 +12,10 @@ public interface IProductQueryRepository
|
||||
/// Used by DeactivateProductTypeCommandHandler to guard against orphaning active products.
|
||||
/// </summary>
|
||||
Task<bool> ExistsActiveByProductTypeAsync(int productTypeId, CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the count of active Products where RubroId = rubroId.
|
||||
/// Used by DeactivateRubroCommandHandler to guard against orphaning active products. (issue #41)
|
||||
/// </summary>
|
||||
Task<int> CountActiveByRubroAsync(int rubroId, CancellationToken ct = default);
|
||||
}
|
||||
|
||||
@@ -10,15 +10,18 @@ public sealed class DeactivateRubroCommandHandler : ICommandHandler<DeactivateRu
|
||||
{
|
||||
private readonly IRubroRepository _repo;
|
||||
private readonly IAuditLogger _audit;
|
||||
private readonly IProductQueryRepository _productQuery;
|
||||
private readonly TimeProvider _timeProvider;
|
||||
|
||||
public DeactivateRubroCommandHandler(
|
||||
IRubroRepository repo,
|
||||
IAuditLogger audit,
|
||||
IProductQueryRepository productQuery,
|
||||
TimeProvider timeProvider)
|
||||
{
|
||||
_repo = repo;
|
||||
_audit = audit;
|
||||
_productQuery = productQuery;
|
||||
_timeProvider = timeProvider;
|
||||
}
|
||||
|
||||
@@ -31,6 +34,10 @@ public sealed class DeactivateRubroCommandHandler : ICommandHandler<DeactivateRu
|
||||
if (activeChildren > 0)
|
||||
throw new RubroTieneHijosActivosException(command.Id, activeChildren);
|
||||
|
||||
var productosActivos = await _productQuery.CountActiveByRubroAsync(command.Id);
|
||||
if (productosActivos > 0)
|
||||
throw new RubroConProductosActivosException(command.Id, productosActivos);
|
||||
|
||||
var deactivated = target.WithActivo(false, _timeProvider);
|
||||
|
||||
using var tx = new TransactionScope(
|
||||
|
||||
Reference in New Issue
Block a user