namespace WalletService.API.Application.Commands; using MediatR; using WalletService.Domain.AggregatesModel.WalletAggregate; using WalletService.Domain.Exceptions; using WalletService.Domain.SeedWork; /// /// EN: Handler for ExchangeCommand. /// VI: Handler cho ExchangeCommand. /// public class ExchangeCommandHandler : IRequestHandler { private readonly IWalletRepository _walletRepository; private readonly ILogger _logger; public ExchangeCommandHandler( IWalletRepository walletRepository, ILogger logger) { _walletRepository = walletRepository; _logger = logger; } public async Task Handle( ExchangeCommand request, CancellationToken cancellationToken) { // EN: Get wallet by user ID // VI: Lấy ví theo user ID var wallet = await _walletRepository.GetByUserIdAsync(request.UserId) ?? throw new WalletDomainException($"Wallet not found for user {request.UserId}"); // EN: Parse currency types from IDs // VI: Parse loại tiền tệ từ IDs var fromCurrency = Enumeration.FromValue(request.FromCurrencyTypeId); var toCurrency = Enumeration.FromValue(request.ToCurrencyTypeId); // EN: Calculate actual rate // VI: Tính tỷ giá thực tế var rate = request.CustomRate ?? fromCurrency.GetExchangeRateTo(toCurrency); // EN: Perform exchange (atomic operation within aggregate) // VI: Thực hiện quy đổi (thao tác atomic trong aggregate) var receivedAmount = wallet.Exchange(request.FromAmount, fromCurrency, toCurrency, request.CustomRate); _walletRepository.Update(wallet); await _walletRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); _logger.LogInformation( "Exchanged {FromAmount} {FromCurrency} to {ToAmount} {ToCurrency} in wallet {WalletId}", request.FromAmount, fromCurrency.Name, receivedAmount, toCurrency.Name, wallet.Id); return new ExchangeResult( wallet.Id, request.FromAmount, fromCurrency.Name, receivedAmount, toCurrency.Name, rate, DateTime.UtcNow ); } }