using CMSMicroservice.Application.Common.Interfaces; using CMSMicroservice.Domain.Entities; using CMSMicroservice.Domain.Entities.Commission; using CMSMicroservice.Domain.Entities.History; using CMSMicroservice.Domain.Enums; using Microsoft.Extensions.Logging; namespace CMSMicroservice.Application.CommissionCQ.Commands.BulkCreditPayouts; public class BulkCreditPayoutsCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; private readonly ICurrentUserService _currentUser; private readonly ILogger _logger; public BulkCreditPayoutsCommandHandler( IApplicationDbContext context, ICurrentUserService currentUser, ILogger logger) { _context = context; _currentUser = currentUser; _logger = logger; } public async Task Handle(BulkCreditPayoutsCommand request, CancellationToken cancellationToken) { // بارگذاری همه پرداخت‌های Pending این هفته var pendingPayouts = await _context.UserCommissionPayouts .Where(p => p.WeekDefinitionId == request.WeekDefinitionId && p.Status == CommissionPayoutStatus.Pending && !p.IsDeleted) .ToListAsync(cancellationToken); if (!pendingPayouts.Any()) { return new BulkCreditPayoutsResult { CreditedCount = 0, TotalCredited = 0 }; } // بارگذاری کیف پول همه کاربران مربوطه (یک query) var userIds = pendingPayouts.Select(p => p.UserId).Distinct().ToList(); var wallets = await _context.UserWallets .Where(w => userIds.Contains(w.UserId) && !w.IsDeleted) .ToDictionaryAsync(w => w.UserId, cancellationToken); var performedBy = _currentUser.GetPerformedBy() ?? "System"; var now = DateTime.UtcNow; var walletHistories = new List(); var payoutHistories = new List(); var creditedCount = 0; long totalCredited = 0; foreach (var payout in pendingPayouts) { if (!wallets.TryGetValue(payout.UserId, out var wallet)) { _logger.LogWarning( "Wallet not found for UserId={UserId}, PayoutId={PayoutId} — skipping", payout.UserId, payout.Id); continue; } var oldBalance = wallet.Balance; // واریز مبلغ به کیف پول wallet.Balance += payout.TotalAmount; walletHistories.Add(new UserWalletHistory { WalletId = wallet.Id, CurrentBalance = wallet.Balance, CurrentNetworkBalance = wallet.NetworkBalance, CurrentDiscountBalance = wallet.DiscountBalance, ChangeValue = payout.TotalAmount, ChangeNerworkValue = 0, ChangeDiscountValue = 0, IsIncrease = true, RefrenceId = payout.Id }); // به‌روزرسانی وضعیت پرداخت payout.Status = CommissionPayoutStatus.Paid; payout.PaidAt = now; payout.LastModified = now; payoutHistories.Add(new CommissionPayoutHistory { UserCommissionPayoutId = payout.Id, UserId = payout.UserId, WeekDefinitionId = payout.WeekDefinitionId, AmountBefore = 0, AmountAfter = payout.TotalAmount, OldStatus = CommissionPayoutStatus.Pending, NewStatus = CommissionPayoutStatus.Paid, Action = CommissionPayoutAction.Paid, PerformedBy = performedBy, Reason = $"واریز دسته‌جمعی کمیسیون هفته {payout.WeekDefinitionId} توسط {performedBy}" }); creditedCount++; totalCredited += payout.TotalAmount; } await _context.UserWalletHistories.AddRangeAsync(walletHistories, cancellationToken); await _context.CommissionPayoutHistories.AddRangeAsync(payoutHistories, cancellationToken); await _context.SaveChangesAsync(cancellationToken); _logger.LogInformation( "BulkCreditPayouts completed: Week={WeekId}, Credited={Count}, TotalAmount={Total}, By={By}", request.WeekDefinitionId, creditedCount, totalCredited, performedBy); return new BulkCreditPayoutsResult { CreditedCount = creditedCount, TotalCredited = totalCredited }; } }