Files
docs/CHANGELOG-2025-12-27.md
T
masoodafar-web 6220049161 feat: Enhance CMS Microservice with SystemConstants and SmsTemplates
- Added SystemConstants class to centralize hardcoded values for club configuration, commission configuration, and package amounts.
- Introduced SmsTemplates class to manage SMS message templates for various user notifications.
- Implemented automatic SMS sending for Daya Loan approval notifications.
- Updated BackOffice UI to include App Version management features.
- Fixed mapping issues in Mapster profiles for improved data handling.
- Updated changelog and documentation to reflect recent changes and configurations.
2025-12-27 05:07:33 +03:30

11 KiB
Raw Blame History

📝 Changelog - ۷ دی ۱۴۰۴ (27 December 2025)

Session: بهینه‌سازی‌های Mapping + SystemConstants + SMS Templates + AppVersion UI


🎯 خلاصه Session

این session شامل موارد زیر بود:

  1. SystemConstants - انتقال مقادیر ثابت از hardcode به کلاس مرکزی
  2. SMS Templates - متمرکز کردن همه قالب‌های پیامک
  3. SMS for Daya Loan - ارسال پیامک هنگام تأیید وام دایا
  4. AppVersion UI - تکمیل صفحه مدیریت نسخه در BackOffice
  5. Mapping Fixes - رفع مشکلات Mapster

تغییرات

1. 💰 SystemConstants - مقادیر ثابت

فایل: CMSMicroservice.Domain/Common/SystemConstants.cs

public static class SystemConstants
{
    // Club Configuration
    public const decimal ClubJoiningPercentage = 0.35m;    // 35% کمیسیون پیوستن به باشگاه
    public const decimal ClubActivationThreshold = 0.5m;   // 50% آستانه فعال‌سازی
    
    // Commission Configuration
    public const int MaxCalculationAttempts = 3;           // حداکثر تلاش محاسبه
    public const int DefaultCommissionPoolDays = 7;        // روزهای استخر کمیسیون
    
    // Package Amounts
    public const long GoldenPackageAmount = 56_000_000;    // 56 میلیون - پکیج طلایی
    public const long DayaLoanAmount = 56_000_000;         // 56 میلیون - وام دایا
}

Handlers آپدیت شده:

Handler تغییر
ProcessDayaLoanApprovalCommandHandler استفاده از SystemConstants.DayaLoanAmount
ValidateGoldenPackagePurchaseQueryHandler استفاده از SystemConstants.GoldenPackageAmount
سایر handlers با 56_000_000 همه به ثابت تبدیل شدند

2. 📱 SmsTemplates - قالب‌های متمرکز پیامک

فایل جدید: CMSMicroservice.Domain/Common/SmsTemplates.cs

public static class SmsTemplates
{
    private static string GetUserName(string? firstName) 
        => string.IsNullOrWhiteSpace(firstName) ? "کاربر" : firstName;

    public static string DayaLoanReceived(string? firstName, long amount)
        => $"{GetUserName(firstName)} عزیز، مبلغ {amount:N0} ریال وام دایا به کیف پول شما واریز شد. کارابازار";

    public static string ClubActivated(string? firstName)
        => $"{GetUserName(firstName)} عزیز، حساب باشگاه شما فعال شد. کارابازار";

    public static string PackagePurchased(string? firstName, string packageName)
        => $"{GetUserName(firstName)} عزیز، پکیج {packageName} با موفقیت خریداری شد. کارابازار";

    public static string CommissionDeposited(string? firstName, long amount)
        => $"{GetUserName(firstName)} عزیز، مبلغ {amount:N0} ریال کمیسیون به کیف پول شما واریز شد. کارابازار";

    public static string WithdrawalSuccess(string? firstName, long amount)
        => $"{GetUserName(firstName)} عزیز، درخواست برداشت {amount:N0} ریال با موفقیت انجام شد. کارابازار";

    public static string NetworkJoined(string? firstName, string referrerName)
        => $"{GetUserName(firstName)} عزیز، به شبکه {referrerName} پیوستید. کارابازار";

    public static string NewDownline(string? firstName, string newMemberName)
        => $"{GetUserName(firstName)} عزیز، {newMemberName} به زیرمجموعه شما اضافه شد. کارابازار";

    public static string OtpCode(string code)
        => $"کد تأیید شما: {code}\nکارابازار";

    public static string Welcome(string? firstName)
        => $"{GetUserName(firstName)} عزیز، به کارابازار خوش آمدید!";
}

3. 📲 ارسال SMS هنگام تأیید وام دایا

فایل: CMSMicroservice.Application/FinancialCQ/Commands/ProcessDayaLoanApproval/ProcessDayaLoanApprovalCommandHandler.cs

تغییرات:

public class ProcessDayaLoanApprovalCommandHandler : IRequestHandler<ProcessDayaLoanApprovalCommand, Unit>
{
    private readonly IKavenegarService _smsService;  // جدید
    private readonly ILogger<ProcessDayaLoanApprovalCommandHandler> _logger;  // جدید

    // بعد از واریز موفق به کیف پول
    private async Task SendDayaLoanSmsAsync(User user)
    {
        try
        {
            var message = SmsTemplates.DayaLoanReceived(
                user.FirstName, 
                SystemConstants.DayaLoanAmount);
            
            await _smsService.SendAsync(user.PhoneNumber, message);
            _logger.LogInformation("Daya loan SMS sent to user {UserId}", user.Id);
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to send Daya loan SMS to user {UserId}", user.Id);
            // خطای SMS مانع عملیات اصلی نمی‌شود
        }
    }
}

4. 🖥️ BackOffice - صفحه مدیریت نسخه اپلیکیشن

4.1 اضافه شدن به منو

فایل: BackOffice/Shared/NavMenu.razor

@if (CanViewSettings)
{
    <MudNavLink Match="NavLinkMatch.Prefix"
                Href="/settings/app-versions"
                Icon="@Icons.Material.Filled.PhoneAndroid">
        نسخه اپلیکیشن‌ها
    </MudNavLink>
}

Permission: settings.view

4.2 دکمه افزودن نسخه جدید

فایل: BackOffice/Pages/Settings/AppVersions.razor

<MudButton Variant="Variant.Filled" 
           Color="Color.Primary" 
           StartIcon="@Icons.Material.Filled.Add"
           OnClick="@OpenCreateDialog">
    افزودن نسخه جدید
</MudButton>

4.3 Dialog با حالت جدید/ویرایش

فایل: BackOffice/Pages/Settings/Components/AppVersionEditDialog.razor

[Parameter]
public bool IsNew { get; set; } = false;

@if (IsNew)
{
    <MudSelect @bind-Value="Model.AppName"
               Label="نام اپلیکیشن"
               Required="true">
        <MudSelectItem Value="@("KaraBazarApp")">کارابازار</MudSelectItem>
        <MudSelectItem Value="@("KaraBazarAdminApp")">ادمین کارابازار</MudSelectItem>
    </MudSelect>
}
else
{
    <MudTextField @bind-Value="Model.AppName" 
                  ReadOnly="true" Disabled="true" />
}

4.4 آیکون و رنگ اپلیکیشن‌ها

private string GetAppIcon(string appName) => appName switch
{
    "KaraBazarApp" => Icons.Material.Filled.ShoppingCart,
    "KaraBazarAdminApp" => Icons.Material.Filled.AdminPanelSettings,
    _ => Icons.Material.Filled.PhoneAndroid
};

private Color GetAppColor(string appName) => appName switch
{
    "KaraBazarApp" => Color.Primary,
    "KaraBazarAdminApp" => Color.Secondary,
    _ => Color.Default
};

5. 🔧 Mapping Fixes

5.1 CMS - AppVersionProfile

فایل جدید: CMSMicroservice.WebApi/Common/Mappings/AppVersionProfile.cs

public class AppVersionProfile : IRegister
{
    public void Register(TypeAdapterConfig config)
    {
        // Map List<AppVersionItemDto> to GetAllAppVersionsResponse
        config.NewConfig<List<AppVersionItemDto>, GetAllAppVersionsResponse>()
            .MapWith(src => CreateResponse(src));

        // Map AppVersionItemDto to AppVersionItem (proto message)
        config.NewConfig<AppVersionItemDto, AppVersionItem>()
            .Map(dest => dest.Id, src => src.Id)
            .Map(dest => dest.AppName, src => src.AppName)
            // ... other mappings
    }

    private static GetAllAppVersionsResponse CreateResponse(List<AppVersionItemDto> items)
    {
        var response = new GetAllAppVersionsResponse();
        foreach (var item in items)
        {
            response.Items.Add(item.Adapt<AppVersionItem>());
        }
        return response;
    }
}

5.2 BackOffice.BFF - CommissionProfile

فایل: BackOffice.BFF.Application/Common/Mappings/CommissionProfile.cs

// CMS GetAllWeeklyPoolsResponse -> GetAllWeeklyPoolsResponseDto
config.NewConfig<GetAllWeeklyPoolsResponse, GetAllWeeklyPoolsResponseDto>()
    .MapWith(src => new GetAllWeeklyPoolsResponseDto
    {
        MetaData = new MetaDataDto
        {
            TotalCount = (int)src.MetaData.TotalCount,
            PageSize = (int)src.MetaData.PageSize,
            CurrentPage = (int)src.MetaData.CurrentPage,
            TotalPages = (int)src.MetaData.TotalPage
        },
        Models = src.Models.Select(m => new WeeklyCommissionPoolDto
        {
            Id = m.Id,
            WeekDefinitionId = m.WeekDefinitionId,
            // ... other mappings
        }).ToList()
    });

5.3 BackOffice.BFF - GeneralMapping (Unit to Empty)

فایل: BackOffice.BFF.WebApi/Common/Mappings/GeneralMapping.cs

// MediatR Unit to Google.Protobuf.Empty
config.NewConfig<MediatR.Unit, Google.Protobuf.WellKnownTypes.Empty>()
    .MapWith(_ => new Google.Protobuf.WellKnownTypes.Empty());

📦 فایل‌های تغییر یافته

CMS

فایل نوع تغییر
Domain/Common/SystemConstants.cs Modified - اضافه شدن GoldenPackageAmount, DayaLoanAmount
Domain/Common/SmsTemplates.cs New - قالب‌های پیامک
Application/.../ProcessDayaLoanApprovalCommandHandler.cs Modified - اضافه شدن SMS
WebApi/Common/Mappings/AppVersionProfile.cs New - Mapster profile

BackOffice.BFF

فایل نوع تغییر
Application/Common/Mappings/CommissionProfile.cs Modified - اضافه شدن GetAllWeeklyPools mapping
WebApi/Common/Mappings/GeneralMapping.cs Modified - اضافه شدن Unit to Empty

BackOffice

فایل نوع تغییر
Shared/NavMenu.razor Modified - اضافه شدن لینک app-versions
Pages/Settings/AppVersions.razor Modified - دکمه افزودن + OpenCreateDialog
Pages/Settings/Components/AppVersionEditDialog.razor Modified - پارامتر IsNew + Select

Build Status

# CMS
dotnet build CMSMicroservice.WebApi/CMSMicroservice.WebApi.csproj
# Build succeeded. 0 Error(s)

# BackOffice.BFF
dotnet build BackOffice.BFF.WebApi/BackOffice.BFF.WebApi.csproj
# Build succeeded. 0 Error(s)

# BackOffice
dotnet build BackOffice/BackOffice.csproj
# Build succeeded. 0 Error(s)

📊 آمار Session

متریک مقدار
فایل‌های جدید 2
فایل‌های تغییر یافته 8
خطوط کد اضافه شده ~300
باگ‌های Mapping رفع شده 3