using System.Transactions; using SIGCM2.Application.Abstractions; using SIGCM2.Application.Abstractions.Persistence; using SIGCM2.Application.Audit; using SIGCM2.Domain.Entities; using SIGCM2.Domain.Exceptions; namespace SIGCM2.Application.Rubros.Update; public sealed class UpdateRubroCommandHandler : ICommandHandler { private readonly IRubroRepository _repo; private readonly IAuditLogger _audit; private readonly TimeProvider _timeProvider; public UpdateRubroCommandHandler( IRubroRepository repo, IAuditLogger audit, TimeProvider timeProvider) { _repo = repo; _audit = audit; _timeProvider = timeProvider; } public async Task Handle(UpdateRubroCommand command) { var target = await _repo.GetByIdAsync(command.Id) ?? throw new RubroNotFoundException(command.Id); // Duplicate name check (CI, excluding self) var exists = await _repo.ExistsByNombreUnderParentAsync(target.ParentId, command.Nombre, excludeId: command.Id); if (exists) throw new RubroNombreDuplicadoEnPadreException(command.Nombre, target.ParentId); var updated = target.WithRenamed(command.Nombre, _timeProvider); using var tx = new TransactionScope( TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }, TransactionScopeAsyncFlowOption.Enabled); await _repo.UpdateAsync(updated); await _audit.LogAsync( action: "rubro.updated", targetType: "Rubro", targetId: command.Id.ToString(), metadata: new { before = new { target.Nombre }, after = new { updated.Nombre }, }); tx.Complete(); return new RubroUpdatedDto( Id: updated.Id, Nombre: updated.Nombre, ParentId: updated.ParentId, Orden: updated.Orden, Activo: updated.Activo, TarifarioBaseId: updated.TarifarioBaseId); } }