302 lines
12 KiB
C#
302 lines
12 KiB
C#
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;
|
|
|
|
/// <summary>
|
|
/// Handler یکپارچه برای استعلام و پردازش وام دایا
|
|
/// 1. استعلام از API دایا
|
|
/// 2. ذخیره/بهروزرسانی DayaLoanContract
|
|
/// 3. شارژ کیف پول برای وامهای تأیید شده
|
|
/// 4. ثبت Order پکیج طلایی
|
|
/// 5. ارسال SMS
|
|
/// </summary>
|
|
public class CheckAndProcessDayaLoansCommandHandler : IRequestHandler<CheckAndProcessDayaLoansCommand, CheckAndProcessDayaLoansResponseDto>
|
|
{
|
|
private readonly IApplicationDbContext _context;
|
|
private readonly IDayaLoanApiService _dayaApiService;
|
|
private readonly IKavenegarService _smsService;
|
|
private readonly ILogger<CheckAndProcessDayaLoansCommandHandler> _logger;
|
|
|
|
public CheckAndProcessDayaLoansCommandHandler(
|
|
IApplicationDbContext context,
|
|
IDayaLoanApiService dayaApiService,
|
|
IKavenegarService smsService,
|
|
ILogger<CheckAndProcessDayaLoansCommandHandler> logger)
|
|
{
|
|
_context = context;
|
|
_dayaApiService = dayaApiService;
|
|
_smsService = smsService;
|
|
_logger = logger;
|
|
}
|
|
|
|
public async Task<CheckAndProcessDayaLoansResponseDto> Handle(CheckAndProcessDayaLoansCommand request, CancellationToken cancellationToken)
|
|
{
|
|
var results = new List<DayaLoanProcessResult>();
|
|
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
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// پردازش مالی وام دایا
|
|
/// </summary>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// ارسال SMS اطلاعرسانی
|
|
/// </summary>
|
|
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);
|
|
}
|
|
}
|
|
}
|