feat: implement Kavenegar SMS service and refactor system configurations to use static constants
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 1m38s

This commit is contained in:
masoodafar-web
2025-12-26 09:04:27 +03:30
parent 9d2b5ad2d4
commit 02e2f8111f
51 changed files with 4064 additions and 1388 deletions
@@ -1,4 +1,5 @@
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Common;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
@@ -13,13 +14,6 @@ public class CommissionCalculationStrategyFactory : ICommissionCalculationStrate
private readonly IWeekDefinitionRepository _weekRepository;
private readonly IServiceProvider _serviceProvider;
/// <summary>
/// کلید Config برای انتخاب استراتژی
/// مقدار: "ORM" یا "SP"
/// پیش‌فرض: "ORM"
/// </summary>
private const string ConfigKey = "Commission.CalculationStrategy";
public CommissionCalculationStrategyFactory(
IApplicationDbContext context,
IWeekDefinitionRepository weekRepository,
@@ -31,13 +25,10 @@ public class CommissionCalculationStrategyFactory : ICommissionCalculationStrate
}
/// <inheritdoc />
public async Task<ICommissionCalculationStrategy> CreateStrategyAsync(CancellationToken cancellationToken = default)
public Task<ICommissionCalculationStrategy> CreateStrategyAsync(CancellationToken cancellationToken = default)
{
// خواندن Config از دیتابیس
var config = await _context.SystemConfigurations
.FirstOrDefaultAsync(x => x.Key == ConfigKey && x.IsActive, cancellationToken);
var strategyValue = config?.Value?.ToUpperInvariant() ?? "ORM";
// خواندن Config از SystemConstants (استاتیک)
var strategyValue = SystemConstants.CommissionCalculationStrategy.ToUpperInvariant();
var strategyType = strategyValue switch
{
@@ -45,7 +36,7 @@ public class CommissionCalculationStrategyFactory : ICommissionCalculationStrate
_ => CommissionCalculationStrategyType.Orm
};
return CreateStrategy(strategyType);
return Task.FromResult(CreateStrategy(strategyType));
}
/// <inheritdoc />
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Domain.Common;
using CMSMicroservice.Domain.Entities.Club;
using CMSMicroservice.Domain.Entities.Commission;
using CMSMicroservice.Domain.Entities.Network;
@@ -87,15 +88,9 @@ public class OrmCommissionCalculationStrategy : ICommissionCalculationStrategy
var balancesList = new List<NetworkWeeklyBalance>();
var calculatedAt = DateTime.Now;
// خواندن یکباره Configuration ها
var configs = await _context.SystemConfigurations
.Where(x => x.IsActive && (
x.Key == "Commission.MaxWeeklyBalancesPerLeg" ||
x.Key == "Commission.MaxNetworkLevel"))
.ToDictionaryAsync(x => x.Key, x => x.Value, cancellationToken);
var maxBalancesPerLeg = int.Parse(configs.GetValueOrDefault("Commission.MaxWeeklyBalancesPerLeg", "300"));
var maxNetworkLevel = int.Parse(configs.GetValueOrDefault("Commission.MaxNetworkLevel", "15"));
// استفاده از SystemConstants به جای دیتابیس
var maxBalancesPerLeg = SystemConstants.CommissionMaxWeeklyBalancesPerLeg;
var maxNetworkLevel = SystemConstants.CommissionMaxNetworkLevel;
foreach (var user in usersInNetwork.OrderBy(o => o.Id))
{
@@ -0,0 +1,109 @@
using CMSMicroservice.Application.Common.Interfaces;
using CMSMicroservice.Infrastructure.Configuration;
using Kavenegar;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace CMSMicroservice.Infrastructure.Services;
/// <summary>
/// پیاده‌سازی سرویس ارسال SMS با کاوه‌نگار
/// </summary>
public class KavenegarService : IKavenegarService
{
private readonly KavenegarApi? _kavenegarApi;
private readonly SmsSettings _smsSettings;
private readonly ILogger<KavenegarService> _logger;
public KavenegarService(
IOptions<SmsSettings> smsSettings,
ILogger<KavenegarService> logger)
{
_smsSettings = smsSettings.Value;
_logger = logger;
// Initialize Kavenegar API
if (_smsSettings.Enabled && !string.IsNullOrEmpty(_smsSettings.KavenegarApiKey))
{
try
{
_kavenegarApi = new KavenegarApi(_smsSettings.KavenegarApiKey);
}
catch (Exception ex)
{
_logger.LogError(ex, "❌ Failed to initialize Kavenegar API");
}
}
}
/// <inheritdoc />
public async Task SendAsync(string mobile, string message)
{
if (!_smsSettings.Enabled)
{
_logger.LogInformation("SMS is disabled. Skipping send to {Mobile}", mobile);
return;
}
if (_kavenegarApi == null)
{
_logger.LogWarning("⚠️ Kavenegar API not initialized, cannot send SMS");
return;
}
try
{
// Kavenegar Send is synchronous
await Task.Run(() =>
{
var result = _kavenegarApi.Send(
sender: _smsSettings.Sender,
receptor: mobile,
message: message);
_logger.LogInformation("📱 SMS sent successfully to {Mobile}, MessageId: {MessageId}", mobile, result.Messageid);
});
}
catch (Exception ex)
{
_logger.LogError(ex, "❌ Kavenegar error sending SMS to {Mobile}: {Message}", mobile, ex.Message);
throw;
}
}
/// <inheritdoc />
public async Task VerifyLookupAsync(string mobile, string token, string template = "Afrino")
{
if (!_smsSettings.Enabled)
{
_logger.LogInformation("SMS is disabled. Skipping VerifyLookup to {Mobile}", mobile);
return;
}
if (_kavenegarApi == null)
{
_logger.LogWarning("⚠️ Kavenegar API not initialized, cannot send VerifyLookup");
return;
}
try
{
// Kavenegar VerifyLookup is synchronous
await Task.Run(() =>
{
var result = _kavenegarApi.VerifyLookup(
receptor: mobile,
token: token,
template: template);
_logger.LogInformation("📱 VerifyLookup SMS sent successfully to {Mobile} with template {Template}, MessageId: {MessageId}",
mobile, template, result.Messageid);
});
}
catch (Exception ex)
{
_logger.LogError(ex, "❌ Kavenegar error sending VerifyLookup to {Mobile}: {Message}", mobile, ex.Message);
throw;
}
}
}