using CMSMicroservice.Application.Common; using CMSMicroservice.Application.Common.Exceptions; using CMSMicroservice.Application.Common.Interfaces; using CMSMicroservice.Domain.Entities; using CMSMicroservice.Domain.Enums; using MediatR; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; namespace CMSMicroservice.Application.WalletCQ.Commands.AdminManualCreditCharge; public class AdminManualCreditChargeCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; private readonly ILogger _logger; private readonly IUserPaymentLock _paymentLock; public AdminManualCreditChargeCommandHandler( IApplicationDbContext context, ILogger logger, IUserPaymentLock paymentLock) { _context = context; _logger = logger; _paymentLock = paymentLock; } public Task Handle( AdminManualCreditChargeCommand request, CancellationToken cancellationToken) => _paymentLock.ExecuteAsync( PaymentLockScopes.Initiate(request.UserId), PaymentLockStrategy.FailFast, ct => HandleCore(request, ct), cancellationToken); private async Task HandleCore( AdminManualCreditChargeCommand request, CancellationToken cancellationToken) { var user = await _context.Users .FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken) ?? throw new NotFoundException(nameof(User), request.UserId); var wallet = await _context.UserWallets .FirstOrDefaultAsync(w => w.UserId == user.Id, cancellationToken) ?? throw new NotFoundException($"کیف پول کاربر با شناسه {request.UserId} یافت نشد"); var oldBalance = wallet.Balance; wallet.Balance += request.Amount; var refId = $"MANUAL-{Guid.NewGuid():N}"; var notePart = string.IsNullOrWhiteSpace(request.Note) ? string.Empty : $" — {request.Note.Trim()}"; var adminPart = string.IsNullOrWhiteSpace(request.PerformedByAdminId) ? string.Empty : $" (ادمین: {request.PerformedByAdminId})"; var transaction = new Transaction { Amount = request.Amount, Description = $"شارژ دستی کیف پول اصلی - کاربر {user.Id}{notePart}{adminPart}", PaymentStatus = PaymentStatus.Success, PaymentDate = DateTime.Now, RefId = refId, Type = TransactionType.ManualCreditWalletCharge }; _context.Transactions.Add(transaction); await _context.SaveChangesAsync(cancellationToken); _context.UserWalletHistories.Add(new UserWalletHistory { WalletId = wallet.Id, CurrentBalance = wallet.Balance, ChangeValue = request.Amount, CurrentNetworkBalance = wallet.NetworkBalance, ChangeNerworkValue = 0, CurrentDiscountBalance = wallet.DiscountBalance, ChangeDiscountValue = 0, IsIncrease = true, RefrenceId = transaction.Id }); await _context.SaveChangesAsync(cancellationToken); _logger.LogInformation( "Manual credit charge: UserId={UserId}, Amount={Amount}, OldBalance={Old}, NewBalance={New}, TxId={TxId}, Admin={Admin}", user.Id, request.Amount, oldBalance, wallet.Balance, transaction.Id, request.PerformedByAdminId); return new AdminManualCreditChargeResult { Success = true, Message = "شارژ دستی کیف پول اصلی با موفقیت انجام شد", TransactionId = transaction.Id, NewBalance = wallet.Balance }; } }