using CMSMicroservice.Domain.Events; using CMSMicroservice.Domain.Enums; using CMSMicroservice.Application.DayaLoanCQ.Services; using Microsoft.Extensions.Logging; namespace CMSMicroservice.Application.DayaLoanCQ.Commands.CheckDayaLoanStatus; public class CheckDayaLoanStatusCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; private readonly IDayaLoanApiService _dayaApiService; private readonly ILogger _logger; /// /// مبلغ وام دایا - 56 میلیون ریال /// private const long DAYA_LOAN_AMOUNT = 56_000_000; public CheckDayaLoanStatusCommandHandler( IApplicationDbContext context, IDayaLoanApiService dayaApiService, ILogger logger) { _context = context; _dayaApiService = dayaApiService; _logger = logger; } public async Task Handle(CheckDayaLoanStatusCommand request, CancellationToken cancellationToken) { var results = new List(); try { // فراخوانی سرویس دایا (Mock یا Real) var dayaResults = await _dayaApiService.CheckLoanStatusAsync(request.NationalCodes, cancellationToken); foreach (var dayaResult in dayaResults) { try { results.Add(new DayaLoanStatusItem { NationalCode = dayaResult.NationalCode, Status = dayaResult.Status, ContractNumber = dayaResult.ContractNumber, Message = "استعلام موفق" }); // ذخیره یا به‌روزرسانی در دیتابیس var existingContract = await _context.DayaLoanContracts .FirstOrDefaultAsync(d => d.NationalCode == dayaResult.NationalCode, cancellationToken); if (existingContract != null) { var previousStatus = existingContract.Status; existingContract.LastCheckDate = DateTime.Now; existingContract.Status = dayaResult.Status; existingContract.ContractNumber = dayaResult.ContractNumber; // بررسی تغییر وضعیت به PendingReceive یا Received // فقط اگر قبلاً پردازش نشده باشد if (!existingContract.IsProcessed && !string.IsNullOrEmpty(dayaResult.ContractNumber) && (dayaResult.Status == DayaLoanStatus.PendingReceive || dayaResult.Status == DayaLoanStatus.Received)) { await ProcessDayaLoanReceivedAsync(existingContract.UserId, dayaResult.ContractNumber, cancellationToken); existingContract.IsProcessed = true; _logger.LogInformation( "Daya loan processed for User {UserId}, ContractNumber: {ContractNumber}, Amount: {Amount}", existingContract.UserId, dayaResult.ContractNumber, DAYA_LOAN_AMOUNT); } } else { var user = await _context.Users .FirstOrDefaultAsync(u => u.NationalCode == dayaResult.NationalCode, cancellationToken); if (user != null) { var isProcessed = false; // اگر وضعیت PendingReceive یا Received بود و قرارداد دارد، فوری پردازش کن if (!string.IsNullOrEmpty(dayaResult.ContractNumber) && (dayaResult.Status == DayaLoanStatus.PendingReceive || dayaResult.Status == DayaLoanStatus.Received)) { await ProcessDayaLoanReceivedAsync(user.Id, dayaResult.ContractNumber, cancellationToken); isProcessed = true; _logger.LogInformation( "Daya loan processed for new contract - User {UserId}, ContractNumber: {ContractNumber}, Amount: {Amount}", user.Id, dayaResult.ContractNumber, DAYA_LOAN_AMOUNT); } var newContract = new DayaLoanContract { UserId = user.Id, NationalCode = dayaResult.NationalCode, Status = dayaResult.Status, ContractNumber = dayaResult.ContractNumber, LastCheckDate = DateTime.Now, IsProcessed = isProcessed }; await _context.DayaLoanContracts.AddAsync(newContract, cancellationToken); } } await _context.SaveChangesAsync(cancellationToken); } catch (Exception ex) { _logger.LogError(ex, "Error processing Daya result for {NationalCode}", dayaResult.NationalCode); } } } catch (Exception ex) { _logger.LogError(ex, "Error calling Daya API service"); // در صورت خطا، نتایج خالی برمی‌گردانیم foreach (var nationalCode in request.NationalCodes) { results.Add(new DayaLoanStatusItem { NationalCode = nationalCode, Status = DayaLoanStatus.PendingReceive, ContractNumber = null, Message = $"خطا در استعلام: {ex.Message}" }); } } return new CheckDayaLoanStatusResponseDto { Results = results, TotalChecked = request.NationalCodes.Count, SuccessCount = results.Count(r => r.ContractNumber != null) }; } /// /// پردازش دریافت وام دایا برای کاربر /// 1. شارژ کیف پول (Balance + DiscountBalance) /// 2. ثبت تراکنش /// 3. ثبت لاگ کیف پول /// 4. به‌روزرسانی وضعیت کاربر /// private async Task ProcessDayaLoanReceivedAsync(long userId, string contractNumber, CancellationToken cancellationToken) { // پیدا کردن کاربر var user = await _context.Users .FirstOrDefaultAsync(u => u.Id == userId, cancellationToken); if (user == null) { _logger.LogWarning("User {UserId} not found for Daya loan processing", userId); return; } // بررسی اینکه قبلاً دریافت نکرده باشد if (user.HasReceivedDayaCredit) { _logger.LogWarning("User {UserId} has already received Daya credit", userId); return; } // پیدا کردن یا ایجاد کیف پول کاربر var wallet = await _context.UserWallets .FirstOrDefaultAsync(w => w.UserId == userId, cancellationToken); if (wallet == null) { wallet = new UserWallet { UserId = userId, Balance = 0, NetworkBalance = 0, DiscountBalance = 0 }; await _context.UserWallets.AddAsync(wallet, cancellationToken); await _context.SaveChangesAsync(cancellationToken); } // 1. شارژ کیف پول - هم موجودی اصلی و هم موجودی تخفیف var previousBalance = wallet.Balance; var previousDiscountBalance = wallet.DiscountBalance; wallet.Balance += DAYA_LOAN_AMOUNT; wallet.DiscountBalance += DAYA_LOAN_AMOUNT; // 2. ثبت تراکنش - RefId = شماره قرارداد، Status = 0 (Success)، Type = 2 (DepositExternal1) var transaction = new Transaction { Amount = DAYA_LOAN_AMOUNT, Description = $"شارژ کیف پول از وام دایا - قرارداد {contractNumber}", PaymentStatus = PaymentStatus.Success, // 0 PaymentDate = DateTime.Now, RefId = contractNumber, Type = TransactionType.DepositExternal1 // 2 }; await _context.Transactions.AddAsync(transaction, cancellationToken); await _context.SaveChangesAsync(cancellationToken); // 3. ثبت لاگ کیف پول با شناسه تراکنش var walletLog = new UserWalletChangeLog { WalletId = wallet.Id, CurrentBalance = wallet.Balance, ChangeValue = DAYA_LOAN_AMOUNT, CurrentNetworkBalance = wallet.NetworkBalance, ChangeNerworkValue = 0, CurrentDiscountBalance = wallet.DiscountBalance, ChangeDiscountValue = DAYA_LOAN_AMOUNT, IsIncrease = true, RefrenceId = transaction.Id }; await _context.UserWalletChangeLogs.AddAsync(walletLog, cancellationToken); // 4. به‌روزرسانی وضعیت کاربر user.HasReceivedDayaCredit = true; user.DayaCreditReceivedAt = DateTime.Now; user.PackagePurchaseMethod = PackagePurchaseMethod.DayaLoan; // 1 await _context.SaveChangesAsync(cancellationToken); _logger.LogInformation( "Daya loan fully processed for User {UserId}: " + "Wallet Balance {PreviousBalance} -> {NewBalance}, " + "DiscountBalance {PreviousDiscountBalance} -> {NewDiscountBalance}, " + "Transaction Id: {TransactionId}", userId, previousBalance, wallet.Balance, previousDiscountBalance, wallet.DiscountBalance, transaction.Id); } }