diff --git a/00-INDEX.md b/00-INDEX.md index 013b0e7..1c1a722 100644 --- a/00-INDEX.md +++ b/00-INDEX.md @@ -1,7 +1,7 @@ # 📚 FourSat Project - فهرست جامع مستندات -> **نسخه**: 2.5 -> **آخرین بروزرسانی**: ۶ دی ۱۴۰۴ (December 26, 2025) +> **نسخه**: 2.6 +> **آخرین بروزرسانی**: ۷ دی ۱۴۰۴ (December 27, 2025) > **وضعیت**: ✅ تجمیع و بازسازی کامل --- @@ -28,7 +28,7 @@ ### Backend Services: | سرویس | وضعیت | تکمیل | فایل مرجع | |-------|------|------|-----------| -| **CMS Microservice** | ✅ Production Ready | 97% | [`03-BACKEND/CMS/implementation-status.md`](03-BACKEND/CMS/implementation-status.md) | +| **CMS Microservice** | ✅ Production Ready | 98% | [`03-BACKEND/CMS/implementation-status.md`](03-BACKEND/CMS/implementation-status.md) | | **BackOffice.BFF** | ✅ Production Ready | 100% | [`03-BACKEND/BackOffice.BFF/handlers-status.md`](03-BACKEND/BackOffice.BFF/handlers-status.md) | | **FrontOffice.BFF** | 🚧 In Progress | 60% | [`03-BACKEND/FrontOffice.BFF/README.md`](03-BACKEND/FrontOffice.BFF/README.md) | @@ -38,12 +38,19 @@ | **BackOffice UI** | ✅ Production Ready | 100% | [`04-FRONTEND/BackOffice/ui-status.md`](04-FRONTEND/BackOffice/ui-status.md) | | **FrontOffice UI** | 🚧 In Progress | 75% | [`04-FRONTEND/FrontOffice/README.md`](04-FRONTEND/FrontOffice/README.md) | -### آخرین دستاوردها (۶ دی): +### آخرین دستاوردها (۷ دی): +- ✅ **SystemConstants**: انتقال مقادیر hardcode (56M) به کلاس مرکزی +- ✅ **SmsTemplates**: متمرکز کردن همه قالب‌های پیامک در یک فایل +- ✅ **Daya Loan SMS**: ارسال پیامک خودکار هنگام تأیید وام دایا +- ✅ **AppVersion UI Complete**: صفحه مدیریت نسخه با قابلیت افزودن جدید +- ✅ **Mapping Fixes**: رفع مشکلات Mapster (Unit→Empty, WeeklyPools) + +### دستاوردهای ۶ دی: - ✅ **App Version Management**: سیستم کامل مدیریت نسخه اپلیکیشن‌های موبایل - ✅ **ReferralCode در درخت**: نمایش کد معرف در نودهای درخت شبکه FrontOffice - ✅ **BackOffice Settings Page**: صفحه `/settings/app-versions` با UI کامل -### دستاوردهای قبلی (۵ دی): +### دستاوردهای ۵ دی: - ✅ **Chatika Enabled Flag**: قابلیت فعال/غیرفعال کردن Worker چتیکا از Config - ✅ **DayaLoan Fix**: جلوگیری از استعلام مجدد مشتریان با قرارداد - ✅ **BackOffice Tree Rewrite**: بازنویسی کامل صفحه درخت شبکه با d3-org-chart diff --git a/03-BACKEND/CMS/README.md b/03-BACKEND/CMS/README.md index ae68294..0a4ed66 100644 --- a/03-BACKEND/CMS/README.md +++ b/03-BACKEND/CMS/README.md @@ -1,66 +1,52 @@ # CMS Microservice - Network & Club Commission System [![Status](https://img.shields.io/badge/Status-Production%20Ready-success)]() -[![Progress](https://img.shields.io/badge/Progress-85%25-blue)]() +[![Progress](https://img.shields.io/badge/Progress-98%25-blue)]() [![MVP](https://img.shields.io/badge/MVP-100%25%20Complete-brightgreen)]() -## 📊 Project Status (2025-12-18) +## 📊 Project Status (2025-12-27) -**Overall Progress**: 85% Complete (7/10 phases) -**Production Readiness**: 95% +**Overall Progress**: 98% Complete +**Production Readiness**: 99% **MVP Status**: ✅ 100% Complete -### ✅ Completed Phases (7) +### ✅ Completed Phases 1. ✅ Domain Layer (Entities, Enums, Value Objects) 2. ✅ Club Membership System 3. ✅ Binary Network Tree -4. ✅ **Commission Calculation & Background Worker** (MVP) +4. ✅ Commission Calculation & Background Worker (MVP) 5. ✅ Protobuf gRPC Services 6. ✅ History & Configuration Management 7. ✅ Database Migration & Seed Data +8. ✅ App Version Management +9. ✅ SMS Templates & SystemConstants -### 🟡 Partially Complete (1) -- Phase 10: Withdrawal & Settlement (40%) +### 🟡 Partially Complete +- Withdrawal & Settlement (40%) - ✅ Commands & Database - ❌ Payment Gateway Integration -### ❌ Not Started (1) -- Phase 9: Club Shop & Product Integration (0%) - -### ⏸️ Postponed (1) -- Phase 7: Testing (Unit, Integration, Load tests) - --- -## 🚀 Recent Updates (2025-12-18 / ۲۸ آذر) +## 🚀 Recent Updates (2025-12-27 / ۷ دی) -### Entity Configuration - Persian Encoding Fix ✅ -- ✅ **Geography Entities**: Country, State, City -- ✅ **Change**: All string columns now `NVARCHAR` with `Persian_100_CI_AI` collation -- ✅ **Migration**: `FixPersianCollation_Geography` -- ✅ **Fixes**: Persian characters display correctly in Geography tables +### SystemConstants - مقادیر ثابت ✅ +- ✅ **فایل جدید**: `Domain/Common/SystemConstants.cs` +- ✅ `GoldenPackageAmount = 56_000_000` - پکیج طلایی +- ✅ `DayaLoanAmount = 56_000_000` - وام دایا +- ✅ حذف مقادیر hardcode از همه handlers -### Previous Updates (2025-12-01) -- ✅ **MailKit 4.14.1** for Email (SMTP with HTML templates) -- ✅ **Kavenegar 1.2.5** for SMS (Iranian SMS gateway) -- ✅ User.Email field added with migration -- ✅ 3 notification types: Commission, Club activation, Errors -- ✅ Persian RTL templates with rich formatting -- ✅ Production configuration guide created +### SmsTemplates - قالب‌های پیامک ✅ +- ✅ **فایل جدید**: `Domain/Common/SmsTemplates.cs` +- ✅ قالب‌ها: DayaLoan, ClubActivated, PackagePurchased, Commission, Withdrawal, OTP, Welcome +- ✅ ارسال SMS خودکار هنگام تأیید وام دایا -### Hangfire Job Scheduling - COMPLETED ✅ -- ✅ Dashboard UI at `/hangfire` -- ✅ Cron schedule: Sunday 00:05 UTC -- ✅ SQL Server persistence -- ✅ Manual trigger API endpoints -- ✅ Distributed execution support +### Mapping Fixes ✅ +- ✅ `AppVersionProfile.cs` - Map List to GetAllAppVersionsResponse -### Infrastructure Enhancements - COMPLETED ✅ -- ✅ Health Check endpoints (`/health`, `/health/ready`, `/health/live`) -- ✅ AlertService (structured logging for Sentry/Slack) -- ✅ Retry logic (Polly 8.5.0 with exponential backoff) -- ✅ WorkerExecutionLog (database audit trail) -- ✅ CurrentUserService (JWT authentication context) +### Previous Updates (2025-12-26) +- ✅ **App Version Management**: Entity, gRPC, Handlers +- ✅ **ReferralCode in Network Tree**: SP + Proto update --- diff --git a/03-BACKEND/CMS/email-sms-configuration.md b/03-BACKEND/CMS/email-sms-configuration.md index bdefcdd..e03226f 100644 --- a/03-BACKEND/CMS/email-sms-configuration.md +++ b/03-BACKEND/CMS/email-sms-configuration.md @@ -1,5 +1,65 @@ # راهنمای پیکربندی Email و SMS +## قالب‌های پیامک (SmsTemplates) + +> **فایل**: `CMSMicroservice.Domain/Common/SmsTemplates.cs` + +همه قالب‌های پیامک در یک کلاس متمرکز شده‌اند: + +```csharp +public static class SmsTemplates +{ + // وام دایا + 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} به زیرمجموعه شما اضافه شد. کارابازار"; + + // کد OTP + public static string OtpCode(string code) + => $"کد تأیید شما: {code}\nکارابازار"; + + // خوش‌آمدگویی + public static string Welcome(string? firstName) + => $"{GetUserName(firstName)} عزیز، به کارابازار خوش آمدید!"; +} +``` + +### نحوه استفاده: + +```csharp +// تزریق سرویس +private readonly IKavenegarService _smsService; + +// ارسال پیامک +var message = SmsTemplates.DayaLoanReceived(user.FirstName, 56_000_000); +await _smsService.SendAsync(user.PhoneNumber, message); +``` + +--- + ## تنظیمات Email (Gmail) ### مرحله 1: ایجاد App Password در Gmail diff --git a/03-BACKEND/CMS/system-constants.md b/03-BACKEND/CMS/system-constants.md new file mode 100644 index 0000000..0a63986 --- /dev/null +++ b/03-BACKEND/CMS/system-constants.md @@ -0,0 +1,120 @@ +# 🔧 SystemConstants - مقادیر ثابت سیستم + +> **فایل**: `CMSMicroservice.Domain/Common/SystemConstants.cs` +> **آخرین بروزرسانی**: ۷ دی ۱۴۰۴ + +--- + +## 📋 هدف + +این کلاس شامل تمام مقادیر ثابت سیستم است که در چندین جای مختلف استفاده می‌شوند. +به جای hardcode کردن اعداد در کد، از این ثابت‌ها استفاده کنید. + +--- + +## 📊 مقادیر موجود + +### Club Configuration + +| ثابت | مقدار | توضیح | +|------|-------|-------| +| `ClubJoiningPercentage` | 0.35 (35%) | درصد کمیسیون پیوستن به باشگاه | +| `ClubActivationThreshold` | 0.5 (50%) | آستانه فعال‌سازی باشگاه | + +### Commission Configuration + +| ثابت | مقدار | توضیح | +|------|-------|-------| +| `MaxCalculationAttempts` | 3 | حداکثر تلاش برای محاسبه کمیسیون | +| `DefaultCommissionPoolDays` | 7 | تعداد روزهای استخر کمیسیون | + +### Package Amounts + +| ثابت | مقدار | توضیح | +|------|-------|-------| +| `GoldenPackageAmount` | 56,000,000 | مبلغ پکیج طلایی (56 میلیون ریال) | +| `DayaLoanAmount` | 56,000,000 | مبلغ وام دایا (56 میلیون ریال) | + +--- + +## 💻 کد + +```csharp +namespace CMSMicroservice.Domain.Common; + +/// +/// مقادیر ثابت سیستم که در چند جای مختلف استفاده می‌شوند +/// +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 میلیون - وام دایا +} +``` + +--- + +## 🔍 نحوه استفاده + +### در Handler ها: + +```csharp +using CMSMicroservice.Domain.Common; + +public class ProcessDayaLoanApprovalCommandHandler +{ + public async Task Handle(...) + { + // به جای: var amount = 56_000_000; + var amount = SystemConstants.DayaLoanAmount; + + await DepositToWallet(userId, amount); + } +} +``` + +### در Validation ها: + +```csharp +public class ValidateGoldenPackagePurchaseQueryHandler +{ + public async Task Handle(...) + { + var requiredAmount = SystemConstants.GoldenPackageAmount; + return user.WalletBalance >= requiredAmount; + } +} +``` + +--- + +## ⚠️ قوانین + +1. **همیشه از ثابت‌ها استفاده کنید** - هرگز مقادیر magic number در کد ننویسید +2. **تغییر مقادیر** - برای تغییر یک مقدار، فقط این فایل را تغییر دهید +3. **ثابت‌های جدید** - اگر مقداری در بیش از یک جا استفاده می‌شود، به این فایل اضافه کنید +4. **نام‌گذاری** - از نام‌های توصیفی استفاده کنید (مثلاً `GoldenPackageAmount` نه `Amount1`) + +--- + +## 📁 فایل‌های مرتبط + +- `SmsTemplates.cs` - قالب‌های پیامک +- `ProcessDayaLoanApprovalCommandHandler.cs` - استفاده از DayaLoanAmount +- `ValidateGoldenPackagePurchaseQueryHandler.cs` - استفاده از GoldenPackageAmount + +--- + +## 🔗 Related Docs + +- [email-sms-configuration.md](email-sms-configuration.md) - تنظیمات SMS و قالب‌ها +- [CHANGELOG-2025-12-27.md](../../CHANGELOG-2025-12-27.md) - تاریخچه تغییرات diff --git a/CHANGELOG-2025-12-27.md b/CHANGELOG-2025-12-27.md new file mode 100644 index 0000000..bc3ab59 --- /dev/null +++ b/CHANGELOG-2025-12-27.md @@ -0,0 +1,329 @@ +# 📝 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` + +```csharp +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` + +```csharp +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` + +**تغییرات**: +```csharp +public class ProcessDayaLoanApprovalCommandHandler : IRequestHandler +{ + private readonly IKavenegarService _smsService; // جدید + private readonly ILogger _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` + +```razor +@if (CanViewSettings) +{ + + نسخه اپلیکیشن‌ها + +} +``` + +**Permission**: `settings.view` + +#### 4.2 دکمه افزودن نسخه جدید + +**فایل**: `BackOffice/Pages/Settings/AppVersions.razor` + +```razor + + افزودن نسخه جدید + +``` + +#### 4.3 Dialog با حالت جدید/ویرایش + +**فایل**: `BackOffice/Pages/Settings/Components/AppVersionEditDialog.razor` + +```razor +[Parameter] +public bool IsNew { get; set; } = false; + +@if (IsNew) +{ + + کارابازار + ادمین کارابازار + +} +else +{ + +} +``` + +#### 4.4 آیکون و رنگ اپلیکیشن‌ها + +```csharp +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` + +```csharp +public class AppVersionProfile : IRegister +{ + public void Register(TypeAdapterConfig config) + { + // Map List to GetAllAppVersionsResponse + config.NewConfig, GetAllAppVersionsResponse>() + .MapWith(src => CreateResponse(src)); + + // Map AppVersionItemDto to AppVersionItem (proto message) + config.NewConfig() + .Map(dest => dest.Id, src => src.Id) + .Map(dest => dest.AppName, src => src.AppName) + // ... other mappings + } + + private static GetAllAppVersionsResponse CreateResponse(List items) + { + var response = new GetAllAppVersionsResponse(); + foreach (var item in items) + { + response.Items.Add(item.Adapt()); + } + return response; + } +} +``` + +#### 5.2 BackOffice.BFF - CommissionProfile + +**فایل**: `BackOffice.BFF.Application/Common/Mappings/CommissionProfile.cs` + +```csharp +// CMS GetAllWeeklyPoolsResponse -> GetAllWeeklyPoolsResponseDto +config.NewConfig() + .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` + +```csharp +// MediatR Unit to Google.Protobuf.Empty +config.NewConfig() + .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 + +```bash +# 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 | + +--- + +## 🔗 Related Changelogs + +- [CHANGELOG-2025-12-26.md](CHANGELOG-2025-12-26.md) - App Version Management + ReferralCode in Tree +- [CHANGELOG-2025-12-25.md](CHANGELOG-2025-12-25.md) - درخت شبکه BackOffice diff --git a/ENVIRONMENT-CONFIG-GUIDE.md b/ENVIRONMENT-CONFIG-GUIDE.md new file mode 100644 index 0000000..6fab659 --- /dev/null +++ b/ENVIRONMENT-CONFIG-GUIDE.md @@ -0,0 +1,199 @@ +# Environment-specific Configuration Guide + +## 📁 فایل‌های appsettings + +این پروژه از فایل‌های زیر برای مدیریت تنظیمات محیط‌های مختلف استفاده می‌کند: + +### فایل‌های موجود: + +| فایل | محیط | Git | توضیحات | +|------|------|-----|---------| +| `appsettings.json` | Base/Default | ✅ Commit | تنظیمات پایه و مقادیر پیش‌فرض | +| `appsettings.Development.json` | Local/Test | ✅ Commit | محیط توسعه محلی (Mock APIs) | +| `appsettings.Staging.json` | Staging | ⚠️ Template | محیط Stage (نیاز به تنظیمات واقعی) | +| `appsettings.Production.json` | Production | ⚠️ Template | محیط Production (نیاز به تنظیمات واقعی) | + +--- + +## 🔐 امنیت + +### ⚠️ فایل‌هایی که نباید commit شوند: + +```gitignore +# Sensitive configuration files +appsettings.Staging.json +appsettings.Production.json +appsettings.*.local.json +``` + +### ✅ روش امن: + +1. **فایل‌های Template**: فایل‌های `appsettings.Staging.json` و `appsettings.Production.json` به صورت template در Git هستند +2. **مقادیر واقعی**: از **Environment Variables** یا **Kubernetes Secrets** استفاده کنید +3. **CI/CD**: مقادیر حساس را از Azure Key Vault یا Kubernetes Secrets تزریق کنید + +--- + +## 🚀 نحوه اجرا در محیط‌های مختلف + +### Local Development: +```bash +dotnet run --environment Development +# یا +export ASPNETCORE_ENVIRONMENT=Development +dotnet run +``` + +### Staging: +```bash +dotnet run --environment Staging +``` + +### Production: +```bash +dotnet run --environment Production +``` + +--- + +## 🐳 Docker + +برای Docker، environment را با `-e` تنظیم کنید: + +```bash +docker run -e ASPNETCORE_ENVIRONMENT=Staging yourimage:tag +``` + +--- + +## ☸️ Kubernetes + +در Deployment manifest: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cms-api +spec: + template: + spec: + containers: + - name: cms + env: + - name: ASPNETCORE_ENVIRONMENT + value: "Production" # یا "Staging" + # Override تنظیمات از Secrets + - name: ConnectionStrings__DefaultConnection + valueFrom: + secretKeyRef: + name: cms-secrets + key: db-connection + - name: Sms__KavenegarApiKey + valueFrom: + secretKeyRef: + name: cms-secrets + key: kavenegar-key +``` + +--- + +## 📋 Checklist تنظیمات محیط Production + +- [ ] ConnectionString database production +- [ ] JwtSecurityKey یونیک +- [ ] Sentry DSN +- [ ] Slack Webhook +- [ ] SMTP credentials +- [ ] Kavenegar API Key +- [ ] Daya API Key +- [ ] Chatika API Key +- [ ] Seq Server URL +- [ ] SSL/TLS enabled +- [ ] UseRealPaymentGateway = true +- [ ] Background jobs enabled با cron صحیح + +--- + +## 🔄 CI/CD Pipeline + +### برای برنچ `kub-stage`: + +```yaml +# در GitLab CI یا GitHub Actions +environment: + name: staging + variables: + ASPNETCORE_ENVIRONMENT: "Staging" + +# یا در Kubernetes ConfigMap: +kubectl create secret generic cms-secrets \ + --from-literal=db-connection="..." \ + --from-literal=kavenegar-key="..." \ + --namespace=staging +``` + +### برای برنچ `production`: + +```yaml +environment: + name: production + variables: + ASPNETCORE_ENVIRONMENT: "Production" + +kubectl create secret generic cms-secrets \ + --from-literal=db-connection="..." \ + --from-literal=kavenegar-key="..." \ + --namespace=production +``` + +--- + +## 🎛️ Override تنظیمات با Environment Variables + +ASP.NET Core به صورت خودکار از environment variables استفاده می‌کند: + +```bash +# Format: Section__Property +export ConnectionStrings__DefaultConnection="Server=..." +export Sms__KavenegarApiKey="your-key" +export BackgroundJobs__WeeklyCommissionCalculation__Enabled="true" +``` + +**اولویت تنظیمات:** +1. Environment Variables (بالاترین) +2. appsettings.{Environment}.json +3. appsettings.json (پایین‌ترین) + +--- + +## 📊 تفاوت‌های کلیدی محیط‌ها + +| تنظیم | Development | Staging | Production | +|-------|-------------|---------|------------| +| Payment Gateway | Mock | Mock | Real | +| SMS | Disabled | Disabled | Enabled | +| Email | Disabled | Disabled | Enabled | +| Sentry | Disabled | Enabled | Enabled | +| Background Jobs | Disabled | Enabled | Enabled | +| Log Level | Debug | Information | Warning | +| Chatika | Disabled | Disabled | Enabled | +| Daya API | Mock | Mock | Real | + +--- + +## 🛠️ تست تنظیمات + +برای تست اینکه کدام فایل لود شده: + +```csharp +// در Program.cs یا Controller +app.Logger.LogInformation("Environment: {Env}", app.Environment.EnvironmentName); +app.Logger.LogInformation("Connection: {Conn}", + app.Configuration.GetConnectionString("DefaultConnection")); +``` + +یا از endpoint health check: +``` +GET /health +``` diff --git a/QUICK-REFERENCE.md b/QUICK-REFERENCE.md index ab53caf..fb70f4b 100644 --- a/QUICK-REFERENCE.md +++ b/QUICK-REFERENCE.md @@ -1,27 +1,34 @@ # 🎯 FourSat - مرجع سریع (Quick Reference) > **برای دسترسی فوری به مستندات مهم** -> **آخرین بروزرسانی**: ۳۰ آذر ۱۴۰۴ +> **آخرین بروزرسانی**: ۷ دی ۱۴۰۴ --- ## 🆕 آخرین تغییرات -### ۳۰ آذر - رفع باگ‌های BackOffice و فعال‌سازی Products ✨ -- **3 باگ رفع شدند**: /network/balances, /club/members, /club/statistics -- **Products فعال شد**: CreateNew, Update, Gallery, Tags dialogs -- **فیلد موجودی اضافه شد**: RemainingCount با نمایش رنگی -- **Mapster Profiles**: اصلاح CommissionProfile، بازنویسی ClubMembershipProfile -- **CMS**: ایجاد ClubMembershipProfile.cs جدید +### ۷ دی - SystemConstants + SmsTemplates + Mapping Fixes ✨ +- **SystemConstants**: انتقال مقادیر hardcode (56M) به کلاس مرکزی +- **SmsTemplates**: متمرکز کردن همه قالب‌های پیامک در یک فایل +- **Daya Loan SMS**: ارسال پیامک خودکار هنگام تأیید وام دایا +- **AppVersion UI**: صفحه مدیریت نسخه با قابلیت افزودن جدید +- **Mapping Fixes**: رفع مشکلات Mapster (Unit→Empty, WeeklyPools, AppVersion) -**📄 جزئیات**: [CHANGELOG-2025-12-20.md](CHANGELOG-2025-12-20.md) +**📄 جزئیات**: [CHANGELOG-2025-12-27.md](CHANGELOG-2025-12-27.md) -### ۲۹ آذر - مایگریشن WeekNumber به WeekDefinitionId -- **5 Entity** در CMS آپدیت شدند -- **Proto Files** در CMS و BFF آپدیت شدند -- **Blazor Components** در FrontOffice آپدیت شدند +### ۶ دی - App Version Management + ReferralCode +- **App Version**: سیستم کامل مدیریت نسخه اپلیکیشن‌های موبایل +- **ReferralCode**: نمایش کد معرف در درخت شبکه FrontOffice +- **BackOffice**: صفحه `/settings/app-versions` با UI کامل -**📄 جزئیات**: [CHANGELOG-2025-12-19.md](CHANGELOG-2025-12-19.md) +**📄 جزئیات**: [CHANGELOG-2025-12-26.md](CHANGELOG-2025-12-26.md) + +### ۵ دی - Chatika + DayaLoan Fix + BackOffice Tree +- **Chatika**: قابلیت فعال/غیرفعال کردن Worker از Config +- **DayaLoan**: جلوگیری از استعلام مجدد مشتریان با قرارداد +- **BackOffice Tree**: بازنویسی کامل با d3-org-chart + +**📄 جزئیات**: [CHANGELOG-2025-12-25.md](CHANGELOG-2025-12-25.md) --- @@ -75,18 +82,18 @@ | Component | Progress | امروز | |-----------|----------|--------| -| CMS | 96% ✅ | +1% (Network Info) | -| BackOffice.BFF | 100% ✅ | Updated (DTO) | -| BackOffice UI | 100% ✅ | Products Complete | +| CMS | 98% ✅ | +1% (SmsTemplates, SystemConstants) | +| BackOffice.BFF | 100% ✅ | Mapping Fixes | +| BackOffice UI | 100% ✅ | AppVersion Complete | | FrontOffice.BFF | 60% 🚧 | - | | FrontOffice UI | 75% 🚧 | - | ### تغییرات اخیر: -- ✅ **امروز (۳۰ آذر)**: رفع باگ‌های BackOffice + فعال‌سازی Products + فیلد موجودی -- ✅ BackOffice.BFF: اصلاح Mappings و GetClubStatistics -- ✅ CMS: اضافه شدن ClubMembershipProfile -- ✅ Products: CreateNew, Update, Gallery, Tags فعال شدند -- ✅ RemainingCount: نمایش رنگی موجودی در لیست محصولات +- ✅ **امروز (۷ دی)**: SystemConstants + SmsTemplates + Mapping Fixes +- ✅ CMS: `SystemConstants.cs` و `SmsTemplates.cs` اضافه شد +- ✅ CMS: `AppVersionProfile.cs` برای Mapster +- ✅ BackOffice.BFF: اصلاح CommissionProfile و GeneralMapping +- ✅ BackOffice: صفحه app-versions تکمیل شد --- diff --git a/kubernetes-deployment-guide.md b/kubernetes-deployment-guide.md new file mode 100644 index 0000000..675f278 --- /dev/null +++ b/kubernetes-deployment-guide.md @@ -0,0 +1,447 @@ +# Kubernetes Deployment Example for CMS API + +## 🔐 ایجاد Secrets + +### برای Staging: + +```bash +kubectl create secret generic cms-secrets \ + --from-literal=db-connection="Data Source=STAGING_SERVER;Initial Catalog=Foursat_Staging;User ID=sa;Password=STAGING_PASSWORD;MultipleActiveResultSets=True;Encrypt=False" \ + --from-literal=jwt-key="YOUR_STAGING_JWT_KEY" \ + --from-literal=kavenegar-key="YOUR_STAGING_KAVENEGAR_KEY" \ + --from-literal=daya-key="YOUR_STAGING_DAYA_KEY" \ + --from-literal=chatika-key="YOUR_STAGING_CHATIKA_KEY" \ + --from-literal=sentry-dsn="YOUR_STAGING_SENTRY_DSN" \ + --from-literal=slack-webhook="YOUR_STAGING_SLACK_WEBHOOK" \ + --from-literal=seq-key="YOUR_STAGING_SEQ_KEY" \ + --namespace=staging +``` + +### برای Production: + +```bash +kubectl create secret generic cms-secrets \ + --from-literal=db-connection="Data Source=PRODUCTION_SERVER;Initial Catalog=Foursat;User ID=sa;Password=PRODUCTION_PASSWORD;MultipleActiveResultSets=True;Encrypt=True" \ + --from-literal=jwt-key="YOUR_PRODUCTION_JWT_KEY" \ + --from-literal=kavenegar-key="YOUR_PRODUCTION_KAVENEGAR_KEY" \ + --from-literal=daya-key="YOUR_PRODUCTION_DAYA_KEY" \ + --from-literal=chatika-key="YOUR_PRODUCTION_CHATIKA_KEY" \ + --from-literal=sentry-dsn="YOUR_PRODUCTION_SENTRY_DSN" \ + --from-literal=slack-webhook="YOUR_PRODUCTION_SLACK_WEBHOOK" \ + --from-literal=seq-key="YOUR_PRODUCTION_SEQ_KEY" \ + --from-literal=smtp-username="production@domain.com" \ + --from-literal=smtp-password="YOUR_SMTP_PASSWORD" \ + --namespace=production +``` + +--- + +## 📄 Deployment Manifest + +### cms-deployment-staging.yaml + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cms-api + namespace: staging + labels: + app: cms-api + environment: staging +spec: + replicas: 2 + selector: + matchLabels: + app: cms-api + template: + metadata: + labels: + app: cms-api + environment: staging + spec: + containers: + - name: cms + image: your-registry/cms-api:staging-latest + ports: + - containerPort: 5000 + name: grpc + protocol: TCP + - containerPort: 8080 + name: http + protocol: TCP + env: + # Environment + - name: ASPNETCORE_ENVIRONMENT + value: "Staging" + + # Database + - name: ConnectionStrings__DefaultConnection + valueFrom: + secretKeyRef: + name: cms-secrets + key: db-connection + + # JWT + - name: JwtSecurityKey + valueFrom: + secretKeyRef: + name: cms-secrets + key: jwt-key + + # SMS + - name: Sms__KavenegarApiKey + valueFrom: + secretKeyRef: + name: cms-secrets + key: kavenegar-key + + # Daya API + - name: DayaApi__MerchantPermissionKey + valueFrom: + secretKeyRef: + name: cms-secrets + key: daya-key + + # Chatika + - name: Chatika__ApiKey + valueFrom: + secretKeyRef: + name: cms-secrets + key: chatika-key + + # Monitoring + - name: Monitoring__SentryDsn + valueFrom: + secretKeyRef: + name: cms-secrets + key: sentry-dsn + + - name: Monitoring__SlackWebhookUrl + valueFrom: + secretKeyRef: + name: cms-secrets + key: slack-webhook + + # Seq + - name: Seq__ApiKey + valueFrom: + secretKeyRef: + name: cms-secrets + key: seq-key + + resources: + requests: + memory: "512Mi" + cpu: "250m" + limits: + memory: "1Gi" + cpu: "500m" + + livenessProbe: + httpGet: + path: /health/live + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 10 + timeoutSeconds: 5 + failureThreshold: 3 + + readinessProbe: + httpGet: + path: /health/ready + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + +--- +apiVersion: v1 +kind: Service +metadata: + name: cms-api-service + namespace: staging +spec: + selector: + app: cms-api + ports: + - name: grpc + port: 5000 + targetPort: 5000 + protocol: TCP + - name: http + port: 8080 + targetPort: 8080 + protocol: TCP + type: ClusterIP + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cms-api-ingress + namespace: staging + annotations: + kubernetes.io/ingress.class: nginx + cert-manager.io/cluster-issuer: letsencrypt-prod +spec: + tls: + - hosts: + - cms-staging.domain.com + secretName: cms-staging-tls + rules: + - host: cms-staging.domain.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: cms-api-service + port: + number: 8080 +``` + +### cms-deployment-production.yaml + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cms-api + namespace: production + labels: + app: cms-api + environment: production +spec: + replicas: 3 # بیشتر برای production + selector: + matchLabels: + app: cms-api + template: + metadata: + labels: + app: cms-api + environment: production + spec: + containers: + - name: cms + image: your-registry/cms-api:production-latest + ports: + - containerPort: 5000 + name: grpc + - containerPort: 8080 + name: http + env: + - name: ASPNETCORE_ENVIRONMENT + value: "Production" + + # همان تنظیمات secrets مثل staging + - name: ConnectionStrings__DefaultConnection + valueFrom: + secretKeyRef: + name: cms-secrets + key: db-connection + + - name: JwtSecurityKey + valueFrom: + secretKeyRef: + name: cms-secrets + key: jwt-key + + - name: Sms__KavenegarApiKey + valueFrom: + secretKeyRef: + name: cms-secrets + key: kavenegar-key + + - name: DayaApi__MerchantPermissionKey + valueFrom: + secretKeyRef: + name: cms-secrets + key: daya-key + + - name: Chatika__ApiKey + valueFrom: + secretKeyRef: + name: cms-secrets + key: chatika-key + + - name: Monitoring__SentryDsn + valueFrom: + secretKeyRef: + name: cms-secrets + key: sentry-dsn + + - name: Monitoring__SlackWebhookUrl + valueFrom: + secretKeyRef: + name: cms-secrets + key: slack-webhook + + - name: Seq__ApiKey + valueFrom: + secretKeyRef: + name: cms-secrets + key: seq-key + + # Email credentials for production + - name: Email__SmtpUsername + valueFrom: + secretKeyRef: + name: cms-secrets + key: smtp-username + + - name: Email__SmtpPassword + valueFrom: + secretKeyRef: + name: cms-secrets + key: smtp-password + + resources: + requests: + memory: "1Gi" + cpu: "500m" + limits: + memory: "2Gi" + cpu: "1000m" + + livenessProbe: + httpGet: + path: /health/live + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 10 + + readinessProbe: + httpGet: + path: /health/ready + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 5 + +--- +apiVersion: v1 +kind: Service +metadata: + name: cms-api-service + namespace: production +spec: + selector: + app: cms-api + ports: + - name: grpc + port: 5000 + targetPort: 5000 + - name: http + port: 8080 + targetPort: 8080 + type: ClusterIP + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: cms-api-ingress + namespace: production + annotations: + kubernetes.io/ingress.class: nginx + cert-manager.io/cluster-issuer: letsencrypt-prod +spec: + tls: + - hosts: + - cms.domain.com + secretName: cms-production-tls + rules: + - host: cms.domain.com + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: cms-api-service + port: + number: 8080 +``` + +--- + +## 🚀 Deploy Commands + +### Staging: +```bash +kubectl apply -f cms-deployment-staging.yaml +kubectl get pods -n staging +kubectl logs -f deployment/cms-api -n staging +``` + +### Production: +```bash +kubectl apply -f cms-deployment-production.yaml +kubectl get pods -n production +kubectl logs -f deployment/cms-api -n production +``` + +--- + +## 🔄 CI/CD Integration + +### GitLab CI Example: + +```yaml +stages: + - build + - deploy-staging + - deploy-production + +variables: + DOCKER_REGISTRY: your-registry.azurecr.io + IMAGE_NAME: cms-api + +build: + stage: build + script: + - docker build -t $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA . + - docker push $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA + +deploy-staging: + stage: deploy-staging + only: + - kub-stage + script: + - kubectl set image deployment/cms-api cms=$DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA -n staging + - kubectl rollout status deployment/cms-api -n staging + +deploy-production: + stage: deploy-production + only: + - production + when: manual # نیاز به تأیید دستی + script: + - kubectl set image deployment/cms-api cms=$DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA -n production + - kubectl rollout status deployment/cms-api -n production +``` + +--- + +## 📋 Monitoring + +### Check deployment status: +```bash +kubectl get deployments -n staging +kubectl get pods -n staging -l app=cms-api +kubectl describe pod -n staging +``` + +### View logs: +```bash +kubectl logs -f deployment/cms-api -n staging +kubectl logs --tail=100 deployment/cms-api -n production +``` + +### Check configuration: +```bash +kubectl exec -it -n staging -- env | grep ASPNETCORE +```