using System.Transactions; using SIGCM2.Application.Abstractions; using SIGCM2.Application.Abstractions.Persistence; using SIGCM2.Application.Audit; namespace SIGCM2.Application.Pricing.ChargeableChars.Create; /// /// PRC-001 — Handler for CreateChargeableCharConfigCommand. /// Flow: opens TransactionScope → InsertWithCloseAsync (SP) → IAuditLogger.LogAsync (fail-closed) → tx.Complete(). /// public sealed class CreateChargeableCharConfigCommandHandler : ICommandHandler { private readonly IChargeableCharConfigRepository _repo; private readonly IAuditLogger _audit; private readonly TimeProvider _timeProvider; public CreateChargeableCharConfigCommandHandler( IChargeableCharConfigRepository repo, IAuditLogger audit, TimeProvider timeProvider) { _repo = repo; _audit = audit; _timeProvider = timeProvider; } public async Task Handle(CreateChargeableCharConfigCommand command) { long newId; using (var tx = new TransactionScope( TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }, TransactionScopeAsyncFlowOption.Enabled)) { newId = await _repo.InsertWithCloseAsync( command.MedioId, command.Symbol, command.Category, command.PricePerUnit, command.ValidFrom); await _audit.LogAsync( action: "tasacion.chargeable_char.create", targetType: "ChargeableCharConfig", targetId: newId.ToString(), metadata: new { after = new { command.MedioId, command.Symbol, command.Category, command.PricePerUnit, validFrom = command.ValidFrom.ToString("yyyy-MM-dd"), } }); tx.Complete(); } return new CreateChargeableCharConfigResponse( newId, command.Symbol, command.PricePerUnit, command.ValidFrom); } }