using CMSMicroservice.Domain.Events; using CMSMicroservice.Domain.Enums; using CMSMicroservice.Domain.Common; using CMSMicroservice.Application.DayaLoanCQ.Services; using CMSMicroservice.Application.Common.Interfaces; using Microsoft.Extensions.Logging; namespace CMSMicroservice.Application.DayaLoanCQ.Commands.CheckAndProcessDayaLoans; /// /// Handler یکپارچه برای استعلام و پردازش وام دایا /// 1. استعلام از API دایا /// 2. ذخیره/به‌روزرسانی DayaLoanContract /// 3. شارژ کیف پول برای وام‌های تأیید شده /// 4. ثبت Order پکیج طلایی /// 5. ارسال SMS /// public class CheckAndProcessDayaLoansCommandHandler : IRequestHandler { private readonly IApplicationDbContext _context; private readonly IDayaLoanApiService _dayaApiService; private readonly IKavenegarService _smsService; private readonly ILogger _logger; public CheckAndProcessDayaLoansCommandHandler( IApplicationDbContext context, IDayaLoanApiService dayaApiService, IKavenegarService smsService, ILogger logger) { _context = context; _dayaApiService = dayaApiService; _smsService = smsService; _logger = logger; } public async Task Handle(CheckAndProcessDayaLoansCommand request, CancellationToken cancellationToken) { var results = new List(); var processedCount = 0; try { // 1. استعلام از سرویس دایا _logger.LogInformation("Checking Daya loan status for {Count} national codes", request.NationalCodes.Count); var dayaResults = await _dayaApiService.CheckLoanStatusAsync(request.NationalCodes, cancellationToken); foreach (var dayaResult in dayaResults) { var result = new DayaLoanProcessResult { NationalCode = dayaResult.NationalCode, Status = dayaResult.Status, ContractNumber = dayaResult.ContractNumber, WasProcessed = false, Message = "استعلام موفق" }; try { // 2. پیدا کردن کاربر var user = await _context.Users .Include(u => u.UserWallets) .FirstOrDefaultAsync(u => u.NationalCode == dayaResult.NationalCode, cancellationToken); if (user == null) { result.Message = "کاربر یافت نشد"; results.Add(result); continue; } result.UserId = user.Id; // 3. ذخیره/به‌روزرسانی DayaLoanContract var contract = await _context.DayaLoanContracts .FirstOrDefaultAsync(d => d.NationalCode == dayaResult.NationalCode, cancellationToken); if (contract == null) { contract = new DayaLoanContract { UserId = user.Id, NationalCode = dayaResult.NationalCode, Status = dayaResult.Status, ContractNumber = dayaResult.ContractNumber, LastCheckDate = DateTime.Now, IsProcessed = false }; await _context.DayaLoanContracts.AddAsync(contract, cancellationToken); } else { contract.Status = dayaResult.Status; contract.ContractNumber = dayaResult.ContractNumber; contract.LastCheckDate = DateTime.Now; } // 4. آیا باید پردازش مالی انجام شود؟ var shouldProcess = !contract.IsProcessed && !user.HasReceivedDayaCredit && !string.IsNullOrEmpty(dayaResult.ContractNumber) && (dayaResult.Status == DayaLoanStatus.PendingReceive || dayaResult.Status == DayaLoanStatus.Received); if (shouldProcess) { // 5. پردازش مالی var processResult = await ProcessDayaLoanAsync(user, dayaResult.ContractNumber!, cancellationToken); contract.IsProcessed = true; result.WasProcessed = true; result.NewWalletBalance = processResult.NewBalance; result.Message = "وام پردازش و کیف پول شارژ شد"; processedCount++; _logger.LogInformation( "Daya loan processed for User {UserId}, Contract: {ContractNumber}, NewBalance: {Balance}", user.Id, dayaResult.ContractNumber, processResult.NewBalance); } else if (contract.IsProcessed || user.HasReceivedDayaCredit) { result.Message = "قبلاً پردازش شده"; } else if (string.IsNullOrEmpty(dayaResult.ContractNumber)) { result.Message = "هنوز قرارداد ندارد"; } await _context.SaveChangesAsync(cancellationToken); } catch (Exception ex) { _logger.LogError(ex, "Error processing Daya loan for NationalCode {NationalCode}", dayaResult.NationalCode); result.Message = $"خطا: {ex.Message}"; } results.Add(result); } } catch (Exception ex) { _logger.LogError(ex, "Error calling Daya API service"); // در صورت خطا در API foreach (var nationalCode in request.NationalCodes) { if (!results.Any(r => r.NationalCode == nationalCode)) { results.Add(new DayaLoanProcessResult { NationalCode = nationalCode, Status = DayaLoanStatus.PendingReceive, WasProcessed = false, Message = $"خطا در استعلام: {ex.Message}" }); } } } return new CheckAndProcessDayaLoansResponseDto { Results = results, TotalChecked = request.NationalCodes.Count, WithContractCount = results.Count(r => !string.IsNullOrEmpty(r.ContractNumber)), ProcessedCount = processedCount }; } /// /// پردازش مالی وام دایا /// private async Task<(long NewBalance, long TransactionId)> ProcessDayaLoanAsync( User user, string contractNumber, CancellationToken cancellationToken) { // 1. ایجاد تراکنش var transaction = new Transaction { Amount = SystemConstants.DayaLoanAmount, Description = $"دریافت اعتبار دایا - قرارداد {contractNumber}", PaymentStatus = PaymentStatus.Success, PaymentDate = DateTime.Now, RefId = contractNumber, Type = TransactionType.DepositExternal1 }; await _context.Transactions.AddAsync(transaction, cancellationToken); await _context.SaveChangesAsync(cancellationToken); // 2. یافتن یا ایجاد کیف پول var wallet = user.UserWallets.FirstOrDefault(); if (wallet == null) { wallet = new UserWallet { UserId = user.Id, Balance = 0, NetworkBalance = 0, DiscountBalance = 0 }; await _context.UserWallets.AddAsync(wallet, cancellationToken); await _context.SaveChangesAsync(cancellationToken); } // 3. شارژ کیف پول عادی wallet.Balance += SystemConstants.DayaLoanAmount; var mainLog = new UserWalletChangeLog { WalletId = wallet.Id, CurrentBalance = 0, ChangeValue = SystemConstants.DayaLoanAmount, CurrentNetworkBalance = wallet.NetworkBalance, ChangeNerworkValue = 0, IsIncrease = true, RefrenceId = transaction.Id }; await _context.UserWalletChangeLogs.AddAsync(mainLog, cancellationToken); // 4. شارژ کیف پول تخفیف (دو برابر) var discountAmount = SystemConstants.DayaLoanAmount * 2; wallet.DiscountBalance += discountAmount; var discountLog = new UserWalletChangeLog { WalletId = wallet.Id, CurrentBalance = wallet.Balance, ChangeValue = 0, CurrentNetworkBalance = wallet.NetworkBalance, ChangeNerworkValue = 0, CurrentDiscountBalance = 0, ChangeDiscountValue = discountAmount, IsIncrease = true, RefrenceId = transaction.Id }; await _context.UserWalletChangeLogs.AddAsync(discountLog, cancellationToken); // 5. به‌روزرسانی کاربر user.HasReceivedDayaCredit = true; user.DayaCreditReceivedAt = DateTime.Now; user.PackagePurchaseMethod = PackagePurchaseMethod.DayaLoan; // 6. ثبت Order پکیج پایه var goldenPackage = await _context.Packages .FirstOrDefaultAsync(p => p.Id == 4, cancellationToken); if (goldenPackage != null) { // 6. ثبت UserPackagePurchase برای پکیج پایه var goldenPackageId =goldenPackage.Id; var packagePurchase = new UserPackagePurchase { UserId = user.Id, PackageId = goldenPackageId, PurchaseMethod = PackagePurchaseMethod.DayaLoan, PurchasedAt = DateTime.Now, Amount = SystemConstants.DayaLoanAmount, TransactionId = transaction.Id }; await _context.UserPackagePurchases.AddAsync(packagePurchase, cancellationToken); } // 7. Domain Event user.AddDomainEvent(new DayaLoanApprovedEvent(user, transaction, contractNumber)); await _context.SaveChangesAsync(cancellationToken); // 8. ارسال SMS await SendDayaLoanSmsAsync(user); return (wallet.Balance, transaction.Id); } /// /// ارسال SMS اطلاع‌رسانی /// private async Task SendDayaLoanSmsAsync(User user) { try { var userName = SmsTemplates.GetUserName(user.FirstName+" "+user.LastName); var message = SmsTemplates.DayaLoanReceived(userName); await _smsService.SendAsync(user.Mobile, message); // ارسال SMS به ادمین برای اطلاع var adminMessage = $"وام دایا دریافت شد\nکاربر: {user.FirstName} {user.LastName}\nموبایل: {user.Mobile}\nکدملی: {user.NationalCode}"; await _smsService.SendAsync("09199877503", adminMessage); _logger.LogInformation("Daya loan SMS sent to User {UserId}", user.Id); } catch (Exception ex) { _logger.LogError(ex, "Failed to send Daya loan SMS to User {UserId}", user.Id); } } }