From 7087df23ef23c240f752eb8f234105f478d22460 Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Sat, 27 Dec 2025 06:40:30 +0330 Subject: [PATCH] feat: remove CheckDayaLoanStatusCommandHandler and ProcessDayaLoanApprovalCommandHandler - Deleted unused command handlers to streamline codebase --- .../CheckDayaLoanStatusCommandHandler.cs | 121 ----------- .../ProcessDayaLoanApprovalCommandHandler.cs | 202 ------------------ .../Services/ConfigurationService.cs | 162 ++++++++++++++ 3 files changed, 162 insertions(+), 323 deletions(-) delete mode 100644 src/CMSMicroservice.Application/DayaLoanCQ/Commands/CheckDayaLoanStatus/CheckDayaLoanStatusCommandHandler.cs delete mode 100644 src/CMSMicroservice.Application/DayaLoanCQ/Commands/ProcessDayaLoanApproval/ProcessDayaLoanApprovalCommandHandler.cs create mode 100644 src/CMSMicroservice.WebApi/Services/ConfigurationService.cs diff --git a/src/CMSMicroservice.Application/DayaLoanCQ/Commands/CheckDayaLoanStatus/CheckDayaLoanStatusCommandHandler.cs b/src/CMSMicroservice.Application/DayaLoanCQ/Commands/CheckDayaLoanStatus/CheckDayaLoanStatusCommandHandler.cs deleted file mode 100644 index e25975c..0000000 --- a/src/CMSMicroservice.Application/DayaLoanCQ/Commands/CheckDayaLoanStatus/CheckDayaLoanStatusCommandHandler.cs +++ /dev/null @@ -1,121 +0,0 @@ -using CMSMicroservice.Domain.Enums; -using CMSMicroservice.Application.DayaLoanCQ.Services; -using Microsoft.Extensions.Logging; - -namespace CMSMicroservice.Application.DayaLoanCQ.Commands.CheckDayaLoanStatus; - -/// -/// این Handler فقط وظیفه استعلام از API دایا و به‌روزرسانی DayaLoanContracts را دارد. -/// پردازش مالی (شارژ کیف پول، ثبت Order و...) توسط Worker و ProcessDayaLoanApprovalCommand انجام می‌شود. -/// -public class CheckDayaLoanStatusCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - private readonly IDayaLoanApiService _dayaApiService; - private readonly ILogger _logger; - - 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) - { - // به‌روزرسانی قرارداد موجود - existingContract.LastCheckDate = DateTime.Now; - existingContract.Status = dayaResult.Status; - existingContract.ContractNumber = dayaResult.ContractNumber; - - _logger.LogDebug( - "Updated DayaLoanContract for NationalCode {NationalCode}, Status: {Status}", - dayaResult.NationalCode, dayaResult.Status); - } - else - { - // ایجاد رکورد جدید قرارداد - var user = await _context.Users - .FirstOrDefaultAsync(u => u.NationalCode == dayaResult.NationalCode, cancellationToken); - - if (user != null) - { - var newContract = new DayaLoanContract - { - UserId = user.Id, - NationalCode = dayaResult.NationalCode, - Status = dayaResult.Status, - ContractNumber = dayaResult.ContractNumber, - LastCheckDate = DateTime.Now, - IsProcessed = false // پردازش مالی توسط Worker انجام می‌شود - }; - - await _context.DayaLoanContracts.AddAsync(newContract, cancellationToken); - - _logger.LogInformation( - "Created new DayaLoanContract for User {UserId}, NationalCode: {NationalCode}, Status: {Status}", - user.Id, dayaResult.NationalCode, dayaResult.Status); - } - } - - 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) - }; - } -} diff --git a/src/CMSMicroservice.Application/DayaLoanCQ/Commands/ProcessDayaLoanApproval/ProcessDayaLoanApprovalCommandHandler.cs b/src/CMSMicroservice.Application/DayaLoanCQ/Commands/ProcessDayaLoanApproval/ProcessDayaLoanApprovalCommandHandler.cs deleted file mode 100644 index 6d9651b..0000000 --- a/src/CMSMicroservice.Application/DayaLoanCQ/Commands/ProcessDayaLoanApproval/ProcessDayaLoanApprovalCommandHandler.cs +++ /dev/null @@ -1,202 +0,0 @@ -using CMSMicroservice.Domain.Events; -using CMSMicroservice.Domain.Enums; -using CMSMicroservice.Domain.Common; -using CMSMicroservice.Application.Common.Interfaces; -using Microsoft.Extensions.Logging; - -namespace CMSMicroservice.Application.DayaLoanCQ.Commands.ProcessDayaLoanApproval; - -public class ProcessDayaLoanApprovalCommandHandler : IRequestHandler -{ - private readonly IApplicationDbContext _context; - private readonly IKavenegarService _smsService; - private readonly ILogger _logger; - - public ProcessDayaLoanApprovalCommandHandler( - IApplicationDbContext context, - IKavenegarService smsService, - ILogger logger) - { - _context = context; - _smsService = smsService; - _logger = logger; - } - - public async Task Handle(ProcessDayaLoanApprovalCommand request, CancellationToken cancellationToken) - { - // پیدا کردن کاربر - var user = await _context.Users - .Include(u => u.UserWallets) - .FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken); - - if (user == null) - { - throw new NotFoundException(nameof(User), request.UserId); - } - - // چک کردن که قبلاً دریافت نکرده باشد - if (user.HasReceivedDayaCredit) - { - throw new InvalidOperationException($"کاربر {request.UserId} قبلاً اعتبار دایا را دریافت کرده است"); - } - - // ایجاد تراکنش با RefId = شماره قرارداد دایا - var transaction = new Transaction - { - Amount = request.WalletAmount , // 168 میلیون - Description = $"دریافت اعتبار دایا - قرارداد {request.ContractNumber}", - PaymentStatus = PaymentStatus.Success, - PaymentDate = DateTime.Now, - RefId = request.ContractNumber, // شماره قرارداد دایا - Type = TransactionType.DepositExternal1 - }; - - await _context.Transactions.AddAsync(transaction, cancellationToken); - await _context.SaveChangesAsync(cancellationToken); - - // یافتن یا ایجاد کیف پول کاربر - var wallet = user.UserWallets.FirstOrDefault(); - if (wallet == null) - { - wallet = new UserWallet - { - UserId = request.UserId, - Balance = 0, - NetworkBalance = 0, - DiscountBalance = 0 - }; - await _context.UserWallets.AddAsync(wallet, cancellationToken); - await _context.SaveChangesAsync(cancellationToken); - } - - // شارژ کیف پول عادی (56 میلیون) - var balanceBeforeMain = wallet.Balance; - wallet.Balance += request.WalletAmount; - - // لاگ کیف پول عادی - var mainLog = new UserWalletChangeLog - { - WalletId = wallet.Id, - CurrentBalance = wallet.Balance, - ChangeValue = request.WalletAmount, - CurrentNetworkBalance = wallet.NetworkBalance, - ChangeNerworkValue = 0, - IsIncrease = true, - RefrenceId = transaction.Id - }; - await _context.UserWalletChangeLogs.AddAsync(mainLog, cancellationToken); - - - - // شارژ کیف پول تخفیف (56 میلیون) - var balanceBeforeDiscount = wallet.DiscountBalance; - wallet.DiscountBalance += request.DiscountWalletAmount; - - // لاگ کیف پول تخفیف - var discountLog = new UserWalletChangeLog - { - WalletId = wallet.Id, - CurrentBalance = wallet.Balance, - ChangeValue = 0, - CurrentNetworkBalance = wallet.NetworkBalance, - ChangeNerworkValue = 0, - CurrentDiscountBalance = wallet.DiscountBalance, - ChangeDiscountValue = request.DiscountWalletAmount, - IsIncrease = true, - RefrenceId = transaction.Id - }; - await _context.UserWalletChangeLogs.AddAsync(discountLog, cancellationToken); - - // به‌روزرسانی وضعیت کاربر - user.HasReceivedDayaCredit = true; - user.DayaCreditReceivedAt = DateTime.Now; - - // تنظیم نحوه خرید پکیج به DayaLoan - user.PackagePurchaseMethod = PackagePurchaseMethod.DayaLoan; - - // ثبت سفارش پکیج (فعلاً پکیج پایه) - var goldenPackage = await _context.Packages - .FirstOrDefaultAsync(p => p.Id==4, cancellationToken); - - if (goldenPackage != null) - { - // پیدا کردن آدرس پیش‌فرض کاربر - var defaultAddress = await _context.UserAddresses - .Where(a => a.UserId == request.UserId) - .OrderByDescending(a => a.Created) - .FirstOrDefaultAsync(cancellationToken); - - if (defaultAddress != null) - { - var packageOrder = new UserOrder - { - UserId = request.UserId, - PackageId = goldenPackage.Id, - Amount = request.WalletAmount, // 56 میلیون - PaymentStatus = PaymentStatus.Success, - PaymentDate = DateTime.Now, - DeliveryStatus = DeliveryStatus.None, - UserAddressId = defaultAddress.Id, - TransactionId = transaction.Id, - PaymentMethod = PaymentMethod.IPG - }; - - await _context.UserOrders.AddAsync(packageOrder, cancellationToken); - } - } - - // ثبت Event - user.AddDomainEvent(new DayaLoanApprovedEvent(user, transaction, request.ContractNumber)); - - // به‌روزرسانی DayaLoanContract.IsProcessed - var dayaContract = await _context.DayaLoanContracts - .FirstOrDefaultAsync(d => d.UserId == request.UserId || d.ContractNumber == request.ContractNumber, cancellationToken); - - if (dayaContract != null) - { - dayaContract.IsProcessed = true; - _logger.LogInformation("Marked DayaLoanContract as processed for User {UserId}", request.UserId); - } - - await _context.SaveChangesAsync(cancellationToken); - - // ارسال SMS به کاربر - await SendDayaLoanSmsAsync(user); - - return new ProcessDayaLoanApprovalResponseDto - { - UserId = user.Id, - TransactionId = transaction.Id, - ContractNumber = request.ContractNumber, - MainWalletBalance = wallet.Balance, - LockedWalletBalance = wallet.NetworkBalance, - DiscountWalletBalance = wallet.DiscountBalance, - Message = "اعتبار دایا با موفقیت دریافت شد" - }; - } - - /// - /// ارسال SMS اطلاع‌رسانی دریافت اعتبار دایا - /// - private async Task SendDayaLoanSmsAsync(User user) - { - try - { - var userName = SmsTemplates.GetUserName(user.FirstName); - var message = SmsTemplates.DayaLoanReceived(userName); - - await _smsService.SendAsync(user.Mobile, message); - - _logger.LogInformation( - "Daya loan SMS sent to User {UserId}, Mobile: {Mobile}", - user.Id, user.Mobile); - } - catch (Exception ex) - { - // خطای SMS نباید فرایند اصلی رو متوقف کنه - _logger.LogError(ex, - "Failed to send Daya loan SMS to User {UserId}, Mobile: {Mobile}", - user.Id, user.Mobile); - } - } -} diff --git a/src/CMSMicroservice.WebApi/Services/ConfigurationService.cs b/src/CMSMicroservice.WebApi/Services/ConfigurationService.cs new file mode 100644 index 0000000..fa0fda6 --- /dev/null +++ b/src/CMSMicroservice.WebApi/Services/ConfigurationService.cs @@ -0,0 +1,162 @@ +using CMSMicroservice.Domain.Common; +using CMSMicroservice.Protobuf.Protos.Configuration; +using Google.Protobuf.WellKnownTypes; +using Grpc.Core; +using Microsoft.Extensions.Logging; + +namespace CMSMicroservice.WebApi.Services; + +/// +/// سرویس تنظیمات سیستم - خواندن از SystemConstants +/// +public class ConfigurationService : ConfigurationContract.ConfigurationContractBase +{ + private readonly ILogger _logger; + + public ConfigurationService(ILogger logger) + { + _logger = logger; + } + + /// + /// دریافت تنظیمات با کلید خاص + /// + public override Task GetConfigurationByKey(GetConfigurationByKeyRequest request, ServerCallContext context) + { + var response = new GetConfigurationByKeyResponse + { + Key = request.Key, + Scope = request.Scope, + IsActive = true, + Created = Timestamp.FromDateTime(DateTime.UtcNow), + LastModified = Timestamp.FromDateTime(DateTime.UtcNow) + }; + + // خواندن مقدار از SystemConstants بر اساس کلید + response.Value = GetConfigurationValue(request.Key); + response.Description = GetConfigurationDescription(request.Key); + + _logger.LogDebug("Configuration requested: Key={Key}, Value={Value}", request.Key, response.Value); + + return Task.FromResult(response); + } + + /// + /// دریافت تمام تنظیمات + /// + public override Task GetAllConfigurations(GetAllConfigurationsRequest request, ServerCallContext context) + { + var response = new GetAllConfigurationsResponse(); + + // Club Settings + response.Models.Add(CreateConfigModel("Club.ActivationFee", SystemConstants.ClubActivationFee.ToString(), "هزینه فعال‌سازی عضویت باشگاه", 2)); + response.Models.Add(CreateConfigModel("Club.MembershipGiftValue", SystemConstants.ClubMembershipGiftValue.ToString(), "مبلغ هدیه حق عضویت باشگاه", 2)); + + // Commission Settings + response.Models.Add(CreateConfigModel("Commission.MinWithdrawalAmount", SystemConstants.CommissionMinWithdrawalAmount.ToString(), "حداقل مبلغ برداشت", 3)); + response.Models.Add(CreateConfigModel("Commission.MaxWeeklyBalancesPerLeg", SystemConstants.CommissionMaxWeeklyBalancesPerLeg.ToString(), "سقف تعادل هفتگی برای هر دست", 3)); + response.Models.Add(CreateConfigModel("Commission.MaxNetworkLevel", SystemConstants.CommissionMaxNetworkLevel.ToString(), "حداکثر عمق شبکه برای محاسبه کمیسیون", 3)); + response.Models.Add(CreateConfigModel("Commission.CashWithdrawalEnabled", SystemConstants.CommissionCashWithdrawalEnabled.ToString(), "امکان برداشت نقدی", 3)); + response.Models.Add(CreateConfigModel("Commission.CalculationStrategy", SystemConstants.CommissionCalculationStrategy, "روش محاسبه کمیسیون", 3)); + + // Network Settings + response.Models.Add(CreateConfigModel("Network.AllowOrphanNodes", SystemConstants.NetworkAllowOrphanNodes.ToString(), "اجازه حذف والدین با فرزند", 1)); + response.Models.Add(CreateConfigModel("Network.MaxChildrenPerLeg", SystemConstants.NetworkMaxChildrenPerLeg.ToString(), "حداکثر تعداد فرزند مستقیم در هر پا", 1)); + + // Package Settings + response.Models.Add(CreateConfigModel("Package.BasePackageAmount", SystemConstants.BasePackageAmount.ToString(), "مبلغ پکیج پایه", 0)); + response.Models.Add(CreateConfigModel("Package.DayaLoanAmount", SystemConstants.DayaLoanAmount.ToString(), "مبلغ وام دایا", 0)); + + // System Settings + response.Models.Add(CreateConfigModel("System.MaintenanceMode", SystemConstants.SystemMaintenanceMode.ToString(), "حالت تعمیر و نگهداری", 0)); + response.Models.Add(CreateConfigModel("System.EnableAuditLog", SystemConstants.SystemEnableAuditLog.ToString(), "فعال‌سازی لاگ تغییرات", 0)); + + // Shop Settings + response.Models.Add(CreateConfigModel("Shop.VAT", SystemConstants.ShopVAT.ToString(), "مالیات بر ارزش افزوده", 0)); + + return Task.FromResult(response); + } + + /// + /// سایر عملیات‌ها که فعلاً پیاده‌سازی نشده‌اند (چون از constant استفاده می‌کنیم) + /// + public override Task CreateOrUpdateConfiguration(CreateOrUpdateConfigurationRequest request, ServerCallContext context) + { + _logger.LogWarning("CreateOrUpdateConfiguration called but SystemConstants are read-only"); + throw new RpcException(new Status(StatusCode.Unimplemented, "تنظیمات سیستم فقط خواندنی هستند")); + } + + public override Task DeactivateConfiguration(DeactivateConfigurationRequest request, ServerCallContext context) + { + _logger.LogWarning("DeactivateConfiguration called but SystemConstants are read-only"); + throw new RpcException(new Status(StatusCode.Unimplemented, "تنظیمات سیستم فقط خواندنی هستند")); + } + + public override Task GetConfigurationHistory(GetConfigurationHistoryRequest request, ServerCallContext context) + { + // چون constant هستند، تاریخچه‌ای وجود نداره + return Task.FromResult(new GetConfigurationHistoryResponse()); + } + + #region Private Helpers + + private static string GetConfigurationValue(string key) + { + return key switch + { + "Club.ActivationFee" => SystemConstants.ClubActivationFee.ToString(), + "Club.MembershipGiftValue" => SystemConstants.ClubMembershipGiftValue.ToString(), + "Commission.MinWithdrawalAmount" => SystemConstants.CommissionMinWithdrawalAmount.ToString(), + "Commission.MaxWeeklyBalancesPerLeg" => SystemConstants.CommissionMaxWeeklyBalancesPerLeg.ToString(), + "Commission.MaxNetworkLevel" => SystemConstants.CommissionMaxNetworkLevel.ToString(), + "Commission.CashWithdrawalEnabled" => SystemConstants.CommissionCashWithdrawalEnabled.ToString(), + "Commission.CalculationStrategy" => SystemConstants.CommissionCalculationStrategy, + "Network.AllowOrphanNodes" => SystemConstants.NetworkAllowOrphanNodes.ToString(), + "Network.MaxChildrenPerLeg" => SystemConstants.NetworkMaxChildrenPerLeg.ToString(), + "Package.BasePackageAmount" => SystemConstants.BasePackageAmount.ToString(), + "Package.DayaLoanAmount" => SystemConstants.DayaLoanAmount.ToString(), + "System.MaintenanceMode" => SystemConstants.SystemMaintenanceMode.ToString(), + "System.EnableAuditLog" => SystemConstants.SystemEnableAuditLog.ToString(), + "Shop.VAT" => SystemConstants.ShopVAT.ToString(), + _ => string.Empty + }; + } + + private static string GetConfigurationDescription(string key) + { + return key switch + { + "Club.ActivationFee" => "هزینه فعال‌سازی عضویت باشگاه (ریال)", + "Club.MembershipGiftValue" => "مبلغ هدیه حق عضویت باشگاه (ریال)", + "Commission.MinWithdrawalAmount" => "حداقل مبلغ برداشت (ریال)", + "Commission.MaxWeeklyBalancesPerLeg" => "سقف تعادل هفتگی برای هر دست", + "Commission.MaxNetworkLevel" => "حداکثر عمق شبکه برای محاسبه کمیسیون", + "Commission.CashWithdrawalEnabled" => "امکان برداشت نقدی", + "Commission.CalculationStrategy" => "روش محاسبه کمیسیون", + "Network.AllowOrphanNodes" => "اجازه حذف والدین با فرزند", + "Network.MaxChildrenPerLeg" => "حداکثر تعداد فرزند مستقیم در هر پا", + "Package.BasePackageAmount" => "مبلغ پکیج پایه (ریال)", + "Package.DayaLoanAmount" => "مبلغ وام دایا (ریال)", + "System.MaintenanceMode" => "حالت تعمیر و نگهداری سیستم", + "System.EnableAuditLog" => "فعال‌سازی لاگ تغییرات", + "Shop.VAT" => "مالیات بر ارزش افزوده", + _ => string.Empty + }; + } + + private static ConfigurationModel CreateConfigModel(string key, string value, string description, int scope) + { + return new ConfigurationModel + { + Id = key.GetHashCode(), + Key = key, + Value = value, + Description = description, + Scope = scope, + IsActive = true, + Created = Timestamp.FromDateTime(DateTime.UtcNow) + }; + } + + #endregion +}