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.
This commit is contained in:
+12
-5
@@ -1,7 +1,7 @@
|
|||||||
# 📚 FourSat Project - فهرست جامع مستندات
|
# 📚 FourSat Project - فهرست جامع مستندات
|
||||||
|
|
||||||
> **نسخه**: 2.5
|
> **نسخه**: 2.6
|
||||||
> **آخرین بروزرسانی**: ۶ دی ۱۴۰۴ (December 26, 2025)
|
> **آخرین بروزرسانی**: ۷ دی ۱۴۰۴ (December 27, 2025)
|
||||||
> **وضعیت**: ✅ تجمیع و بازسازی کامل
|
> **وضعیت**: ✅ تجمیع و بازسازی کامل
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
### Backend Services:
|
### 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) |
|
| **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) |
|
| **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) |
|
| **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) |
|
| **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**: سیستم کامل مدیریت نسخه اپلیکیشنهای موبایل
|
- ✅ **App Version Management**: سیستم کامل مدیریت نسخه اپلیکیشنهای موبایل
|
||||||
- ✅ **ReferralCode در درخت**: نمایش کد معرف در نودهای درخت شبکه FrontOffice
|
- ✅ **ReferralCode در درخت**: نمایش کد معرف در نودهای درخت شبکه FrontOffice
|
||||||
- ✅ **BackOffice Settings Page**: صفحه `/settings/app-versions` با UI کامل
|
- ✅ **BackOffice Settings Page**: صفحه `/settings/app-versions` با UI کامل
|
||||||
|
|
||||||
### دستاوردهای قبلی (۵ دی):
|
### دستاوردهای ۵ دی:
|
||||||
- ✅ **Chatika Enabled Flag**: قابلیت فعال/غیرفعال کردن Worker چتیکا از Config
|
- ✅ **Chatika Enabled Flag**: قابلیت فعال/غیرفعال کردن Worker چتیکا از Config
|
||||||
- ✅ **DayaLoan Fix**: جلوگیری از استعلام مجدد مشتریان با قرارداد
|
- ✅ **DayaLoan Fix**: جلوگیری از استعلام مجدد مشتریان با قرارداد
|
||||||
- ✅ **BackOffice Tree Rewrite**: بازنویسی کامل صفحه درخت شبکه با d3-org-chart
|
- ✅ **BackOffice Tree Rewrite**: بازنویسی کامل صفحه درخت شبکه با d3-org-chart
|
||||||
|
|||||||
+25
-39
@@ -1,66 +1,52 @@
|
|||||||
# CMS Microservice - Network & Club Commission System
|
# CMS Microservice - Network & Club Commission System
|
||||||
|
|
||||||
[]()
|
[]()
|
||||||
[]()
|
[]()
|
||||||
[]()
|
[]()
|
||||||
|
|
||||||
## 📊 Project Status (2025-12-18)
|
## 📊 Project Status (2025-12-27)
|
||||||
|
|
||||||
**Overall Progress**: 85% Complete (7/10 phases)
|
**Overall Progress**: 98% Complete
|
||||||
**Production Readiness**: 95%
|
**Production Readiness**: 99%
|
||||||
**MVP Status**: ✅ 100% Complete
|
**MVP Status**: ✅ 100% Complete
|
||||||
|
|
||||||
### ✅ Completed Phases (7)
|
### ✅ Completed Phases
|
||||||
1. ✅ Domain Layer (Entities, Enums, Value Objects)
|
1. ✅ Domain Layer (Entities, Enums, Value Objects)
|
||||||
2. ✅ Club Membership System
|
2. ✅ Club Membership System
|
||||||
3. ✅ Binary Network Tree
|
3. ✅ Binary Network Tree
|
||||||
4. ✅ **Commission Calculation & Background Worker** (MVP)
|
4. ✅ Commission Calculation & Background Worker (MVP)
|
||||||
5. ✅ Protobuf gRPC Services
|
5. ✅ Protobuf gRPC Services
|
||||||
6. ✅ History & Configuration Management
|
6. ✅ History & Configuration Management
|
||||||
7. ✅ Database Migration & Seed Data
|
7. ✅ Database Migration & Seed Data
|
||||||
|
8. ✅ App Version Management
|
||||||
|
9. ✅ SMS Templates & SystemConstants
|
||||||
|
|
||||||
### 🟡 Partially Complete (1)
|
### 🟡 Partially Complete
|
||||||
- Phase 10: Withdrawal & Settlement (40%)
|
- Withdrawal & Settlement (40%)
|
||||||
- ✅ Commands & Database
|
- ✅ Commands & Database
|
||||||
- ❌ Payment Gateway Integration
|
- ❌ 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 ✅
|
### SystemConstants - مقادیر ثابت ✅
|
||||||
- ✅ **Geography Entities**: Country, State, City
|
- ✅ **فایل جدید**: `Domain/Common/SystemConstants.cs`
|
||||||
- ✅ **Change**: All string columns now `NVARCHAR` with `Persian_100_CI_AI` collation
|
- ✅ `GoldenPackageAmount = 56_000_000` - پکیج طلایی
|
||||||
- ✅ **Migration**: `FixPersianCollation_Geography`
|
- ✅ `DayaLoanAmount = 56_000_000` - وام دایا
|
||||||
- ✅ **Fixes**: Persian characters display correctly in Geography tables
|
- ✅ حذف مقادیر hardcode از همه handlers
|
||||||
|
|
||||||
### Previous Updates (2025-12-01)
|
### SmsTemplates - قالبهای پیامک ✅
|
||||||
- ✅ **MailKit 4.14.1** for Email (SMTP with HTML templates)
|
- ✅ **فایل جدید**: `Domain/Common/SmsTemplates.cs`
|
||||||
- ✅ **Kavenegar 1.2.5** for SMS (Iranian SMS gateway)
|
- ✅ قالبها: DayaLoan, ClubActivated, PackagePurchased, Commission, Withdrawal, OTP, Welcome
|
||||||
- ✅ User.Email field added with migration
|
- ✅ ارسال SMS خودکار هنگام تأیید وام دایا
|
||||||
- ✅ 3 notification types: Commission, Club activation, Errors
|
|
||||||
- ✅ Persian RTL templates with rich formatting
|
|
||||||
- ✅ Production configuration guide created
|
|
||||||
|
|
||||||
### Hangfire Job Scheduling - COMPLETED ✅
|
### Mapping Fixes ✅
|
||||||
- ✅ Dashboard UI at `/hangfire`
|
- ✅ `AppVersionProfile.cs` - Map List to GetAllAppVersionsResponse
|
||||||
- ✅ Cron schedule: Sunday 00:05 UTC
|
|
||||||
- ✅ SQL Server persistence
|
|
||||||
- ✅ Manual trigger API endpoints
|
|
||||||
- ✅ Distributed execution support
|
|
||||||
|
|
||||||
### Infrastructure Enhancements - COMPLETED ✅
|
### Previous Updates (2025-12-26)
|
||||||
- ✅ Health Check endpoints (`/health`, `/health/ready`, `/health/live`)
|
- ✅ **App Version Management**: Entity, gRPC, Handlers
|
||||||
- ✅ AlertService (structured logging for Sentry/Slack)
|
- ✅ **ReferralCode in Network Tree**: SP + Proto update
|
||||||
- ✅ Retry logic (Polly 8.5.0 with exponential backoff)
|
|
||||||
- ✅ WorkerExecutionLog (database audit trail)
|
|
||||||
- ✅ CurrentUserService (JWT authentication context)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,65 @@
|
|||||||
# راهنمای پیکربندی Email و SMS
|
# راهنمای پیکربندی 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)
|
## تنظیمات Email (Gmail)
|
||||||
|
|
||||||
### مرحله 1: ایجاد App Password در Gmail
|
### مرحله 1: ایجاد App Password در Gmail
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// مقادیر ثابت سیستم که در چند جای مختلف استفاده میشوند
|
||||||
|
/// </summary>
|
||||||
|
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<Unit> Handle(...)
|
||||||
|
{
|
||||||
|
// به جای: var amount = 56_000_000;
|
||||||
|
var amount = SystemConstants.DayaLoanAmount;
|
||||||
|
|
||||||
|
await DepositToWallet(userId, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### در Validation ها:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class ValidateGoldenPackagePurchaseQueryHandler
|
||||||
|
{
|
||||||
|
public async Task<bool> 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) - تاریخچه تغییرات
|
||||||
@@ -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<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`
|
||||||
|
|
||||||
|
```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`
|
||||||
|
|
||||||
|
```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`
|
||||||
|
|
||||||
|
```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 آیکون و رنگ اپلیکیشنها
|
||||||
|
|
||||||
|
```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<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`
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 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`
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// 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
|
||||||
|
|
||||||
|
```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
|
||||||
@@ -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
|
||||||
|
```
|
||||||
+28
-21
@@ -1,27 +1,34 @@
|
|||||||
# 🎯 FourSat - مرجع سریع (Quick Reference)
|
# 🎯 FourSat - مرجع سریع (Quick Reference)
|
||||||
|
|
||||||
> **برای دسترسی فوری به مستندات مهم**
|
> **برای دسترسی فوری به مستندات مهم**
|
||||||
> **آخرین بروزرسانی**: ۳۰ آذر ۱۴۰۴
|
> **آخرین بروزرسانی**: ۷ دی ۱۴۰۴
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🆕 آخرین تغییرات
|
## 🆕 آخرین تغییرات
|
||||||
|
|
||||||
### ۳۰ آذر - رفع باگهای BackOffice و فعالسازی Products ✨
|
### ۷ دی - SystemConstants + SmsTemplates + Mapping Fixes ✨
|
||||||
- **3 باگ رفع شدند**: /network/balances, /club/members, /club/statistics
|
- **SystemConstants**: انتقال مقادیر hardcode (56M) به کلاس مرکزی
|
||||||
- **Products فعال شد**: CreateNew, Update, Gallery, Tags dialogs
|
- **SmsTemplates**: متمرکز کردن همه قالبهای پیامک در یک فایل
|
||||||
- **فیلد موجودی اضافه شد**: RemainingCount با نمایش رنگی
|
- **Daya Loan SMS**: ارسال پیامک خودکار هنگام تأیید وام دایا
|
||||||
- **Mapster Profiles**: اصلاح CommissionProfile، بازنویسی ClubMembershipProfile
|
- **AppVersion UI**: صفحه مدیریت نسخه با قابلیت افزودن جدید
|
||||||
- **CMS**: ایجاد ClubMembershipProfile.cs جدید
|
- **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
|
### ۶ دی - App Version Management + ReferralCode
|
||||||
- **5 Entity** در CMS آپدیت شدند
|
- **App Version**: سیستم کامل مدیریت نسخه اپلیکیشنهای موبایل
|
||||||
- **Proto Files** در CMS و BFF آپدیت شدند
|
- **ReferralCode**: نمایش کد معرف در درخت شبکه FrontOffice
|
||||||
- **Blazor Components** در 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 | امروز |
|
| Component | Progress | امروز |
|
||||||
|-----------|----------|--------|
|
|-----------|----------|--------|
|
||||||
| CMS | 96% ✅ | +1% (Network Info) |
|
| CMS | 98% ✅ | +1% (SmsTemplates, SystemConstants) |
|
||||||
| BackOffice.BFF | 100% ✅ | Updated (DTO) |
|
| BackOffice.BFF | 100% ✅ | Mapping Fixes |
|
||||||
| BackOffice UI | 100% ✅ | Products Complete |
|
| BackOffice UI | 100% ✅ | AppVersion Complete |
|
||||||
| FrontOffice.BFF | 60% 🚧 | - |
|
| FrontOffice.BFF | 60% 🚧 | - |
|
||||||
| FrontOffice UI | 75% 🚧 | - |
|
| FrontOffice UI | 75% 🚧 | - |
|
||||||
|
|
||||||
### تغییرات اخیر:
|
### تغییرات اخیر:
|
||||||
- ✅ **امروز (۳۰ آذر)**: رفع باگهای BackOffice + فعالسازی Products + فیلد موجودی
|
- ✅ **امروز (۷ دی)**: SystemConstants + SmsTemplates + Mapping Fixes
|
||||||
- ✅ BackOffice.BFF: اصلاح Mappings و GetClubStatistics
|
- ✅ CMS: `SystemConstants.cs` و `SmsTemplates.cs` اضافه شد
|
||||||
- ✅ CMS: اضافه شدن ClubMembershipProfile
|
- ✅ CMS: `AppVersionProfile.cs` برای Mapster
|
||||||
- ✅ Products: CreateNew, Update, Gallery, Tags فعال شدند
|
- ✅ BackOffice.BFF: اصلاح CommissionProfile و GeneralMapping
|
||||||
- ✅ RemainingCount: نمایش رنگی موجودی در لیست محصولات
|
- ✅ BackOffice: صفحه app-versions تکمیل شد
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -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 <pod-name> -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 <pod-name> -n staging -- env | grep ASPNETCORE
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user