Implement Persian Date Conversion and Enhance User Network Information Service
- Added PersianDateTimeService for converting Gregorian dates to Persian format in the BackOffice frontend. - Updated multiple frontend pages (Dashboard, UserPayouts, WorkerControl, UserNetworkInfo) to utilize the new Persian date service. - Enhanced GetUserNetworkPositionDto with 28+ new fields for comprehensive user network data. - Updated GetUserNetworkPositionQueryHandler to include new methods for calculating network statistics. - Modified Protobuf messages to accommodate the new fields, increasing from 14 to 42. - Refined week number calculation algorithm to ensure consistency across C# and SQL implementations. - Created new CSV and Excel files for binary plan calculations. - Ensured all changes are tested and validated for accuracy and performance.
This commit is contained in:
@@ -0,0 +1,310 @@
|
||||
# مستندات سیستم کمیسیون (Commission System)
|
||||
|
||||
> **آخرین بروزرسانی**: ۲۹ آذر ۱۴۰۴ (19 December 2025)
|
||||
|
||||
---
|
||||
|
||||
## 📋 خلاصه
|
||||
|
||||
سیستم کمیسیون مسئول محاسبه، ذخیره و پرداخت کمیسیونهای کاربران بر اساس ساختار شبکه بازاریابی است.
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ موجودیتها (Entities)
|
||||
|
||||
### WeekDefinition
|
||||
جدول مرجع برای تعریف هفتههای مالی:
|
||||
|
||||
```csharp
|
||||
public class WeekDefinition : BaseAuditableEntity
|
||||
{
|
||||
public int WeekOrder { get; set; } // شماره ترتیبی هفته
|
||||
public int Year { get; set; } // سال میلادی
|
||||
public int PersianYear { get; set; } // سال شمسی
|
||||
public DateTime StartDate { get; set; } // تاریخ شروع
|
||||
public DateTime EndDate { get; set; } // تاریخ پایان
|
||||
public string StartDatePersian { get; set; } // تاریخ شروع شمسی
|
||||
public string EndDatePersian { get; set; } // تاریخ پایان شمسی
|
||||
public bool IsActive { get; set; } // آیا هفته جاری است
|
||||
}
|
||||
```
|
||||
|
||||
### NetworkWeeklyBalance
|
||||
تعادل هفتگی شاخه چپ و راست کاربر:
|
||||
|
||||
```csharp
|
||||
public class NetworkWeeklyBalance : BaseAuditableEntity
|
||||
{
|
||||
public long UserId { get; set; }
|
||||
public long WeekDefinitionId { get; set; } // FK به WeekDefinition
|
||||
public long LeftBalance { get; set; } // امتیاز شاخه چپ
|
||||
public long RightBalance { get; set; } // امتیاز شاخه راست
|
||||
|
||||
// Navigation Properties
|
||||
public virtual User User { get; set; }
|
||||
public virtual WeekDefinition WeekDefinition { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
**Index**: `(UserId, WeekDefinitionId)` - Unique
|
||||
|
||||
### WeeklyCommissionPool
|
||||
استخر کمیسیون هفتگی:
|
||||
|
||||
```csharp
|
||||
public class WeeklyCommissionPool : BaseAuditableEntity
|
||||
{
|
||||
public long WeekDefinitionId { get; set; } // FK به WeekDefinition
|
||||
public long TotalPoolAmount { get; set; } // مجموع استخر
|
||||
public long DistributedAmount { get; set; } // مقدار توزیع شده
|
||||
public int TotalBalances { get; set; } // تعداد کل تعادلها
|
||||
public long PerBalanceAmount { get; set; } // مبلغ هر تعادل
|
||||
public bool IsFinalized { get; set; } // آیا نهایی شده
|
||||
|
||||
// Navigation Property
|
||||
public virtual WeekDefinition WeekDefinition { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
### UserCommissionPayout
|
||||
رکورد پرداخت کمیسیون به کاربر:
|
||||
|
||||
```csharp
|
||||
public class UserCommissionPayout : BaseAuditableEntity
|
||||
{
|
||||
public long UserId { get; set; }
|
||||
public long WeekDefinitionId { get; set; } // FK به WeekDefinition
|
||||
public int BalancesEarned { get; set; } // تعداد تعادلهای کسب شده
|
||||
public long Amount { get; set; } // مبلغ کمیسیون
|
||||
public CommissionPayoutStatus Status { get; set; } // وضعیت پرداخت
|
||||
public DateTime? PaidAt { get; set; } // تاریخ پرداخت
|
||||
|
||||
// Navigation Properties
|
||||
public virtual User User { get; set; }
|
||||
public virtual WeekDefinition WeekDefinition { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
**وضعیتها (Status)**:
|
||||
- `Created` - ایجاد شده
|
||||
- `Paid` - پرداخت به کیف پول
|
||||
- `WithdrawalRequested` - درخواست برداشت
|
||||
- `Withdrawn` - برداشت شده
|
||||
- `Cancelled` - لغو شده
|
||||
|
||||
### CommissionPayoutHistory
|
||||
تاریخچه تغییرات وضعیت پرداخت:
|
||||
|
||||
```csharp
|
||||
public class CommissionPayoutHistory : BaseAuditableEntity
|
||||
{
|
||||
public long UserCommissionPayoutId { get; set; }
|
||||
public long WeekDefinitionId { get; set; } // FK به WeekDefinition
|
||||
public CommissionPayoutStatus FromStatus { get; set; }
|
||||
public CommissionPayoutStatus ToStatus { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
|
||||
// Navigation Properties
|
||||
public virtual UserCommissionPayout UserCommissionPayout { get; set; }
|
||||
public virtual WeekDefinition WeekDefinition { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
### WorkerExecutionLog
|
||||
لاگ اجرای Worker های محاسبه کمیسیون:
|
||||
|
||||
```csharp
|
||||
public class WorkerExecutionLog : BaseAuditableEntity
|
||||
{
|
||||
public string WorkerName { get; set; } // نام Worker
|
||||
public long? WeekDefinitionId { get; set; } // FK به WeekDefinition (nullable)
|
||||
public DateTime StartedAt { get; set; } // زمان شروع
|
||||
public DateTime? CompletedAt { get; set; } // زمان پایان
|
||||
public bool IsSuccess { get; set; } // موفقیت
|
||||
public string? ErrorMessage { get; set; } // پیام خطا
|
||||
public int ProcessedCount { get; set; } // تعداد پردازش شده
|
||||
|
||||
// Navigation Property
|
||||
public virtual WeekDefinition? WeekDefinition { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔗 روابط (Relationships)
|
||||
|
||||
```
|
||||
WeekDefinition (1) ─────┬──── (*) NetworkWeeklyBalance
|
||||
├──── (*) WeeklyCommissionPool
|
||||
├──── (*) UserCommissionPayout
|
||||
├──── (*) CommissionPayoutHistory
|
||||
└──── (*) WorkerExecutionLog
|
||||
|
||||
User (1) ───────────────┬──── (*) NetworkWeeklyBalance
|
||||
└──── (*) UserCommissionPayout
|
||||
|
||||
UserCommissionPayout (1) ──── (*) CommissionPayoutHistory
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📡 Proto Models
|
||||
|
||||
### UserCommissionPayoutModel
|
||||
```protobuf
|
||||
message UserCommissionPayoutModel {
|
||||
int64 id = 1;
|
||||
int64 user_id = 2;
|
||||
string user_full_name = 3;
|
||||
int64 week_definition_id = 4; // شناسه هفته
|
||||
int32 balances_earned = 5; // تعداد تعادل
|
||||
int64 amount = 6; // مبلغ
|
||||
int32 status = 7; // وضعیت
|
||||
google.protobuf.Timestamp paid_at = 8;
|
||||
google.protobuf.Timestamp created = 9;
|
||||
string mobile = 10;
|
||||
string week_display_name = 11; // نام نمایشی هفته
|
||||
}
|
||||
```
|
||||
|
||||
### UserWeeklyBalanceModel
|
||||
```protobuf
|
||||
message UserWeeklyBalanceModel {
|
||||
int64 user_id = 1;
|
||||
int64 week_definition_id = 2; // شناسه هفته
|
||||
int64 left_balance = 3;
|
||||
int64 right_balance = 4;
|
||||
string start_date_persian = 5;
|
||||
string end_date_persian = 6;
|
||||
int32 year = 7;
|
||||
int32 week_order = 8;
|
||||
bool is_active = 9;
|
||||
string week_display_name = 10; // نام نمایشی هفته
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 نامگذاری فیلدها
|
||||
|
||||
### قبل از مایگریشن (Legacy)
|
||||
```
|
||||
WeekNumber: "2025-01" (string)
|
||||
GregorianWeekNumber: "2025-01" (string)
|
||||
PersianWeekNumber: "1403-40" (string)
|
||||
WeekLabel: "هفته 1 - 1403/10/01"
|
||||
```
|
||||
|
||||
### بعد از مایگریشن (Current)
|
||||
```
|
||||
WeekDefinitionId: 42 (long) // FK به جدول WeekDefinition
|
||||
WeekDisplayName: "هفته 1 - 1403/10/01" // ساخته شده از WeekDefinition
|
||||
```
|
||||
|
||||
**فرمول WeekDisplayName**:
|
||||
```csharp
|
||||
$"هفته {WeekDefinition.WeekOrder} - {WeekDefinition.StartDatePersian}"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Query Examples
|
||||
|
||||
### دریافت کمیسیونهای کاربر
|
||||
```csharp
|
||||
var payouts = await _context.UserCommissionPayouts
|
||||
.Include(p => p.WeekDefinition)
|
||||
.Where(p => p.UserId == userId)
|
||||
.OrderByDescending(p => p.WeekDefinition.WeekOrder)
|
||||
.Select(p => new {
|
||||
p.Id,
|
||||
p.WeekDefinitionId,
|
||||
WeekDisplayName = $"هفته {p.WeekDefinition.WeekOrder} - {p.WeekDefinition.StartDatePersian}",
|
||||
p.BalancesEarned,
|
||||
p.Amount,
|
||||
p.Status
|
||||
})
|
||||
.ToListAsync();
|
||||
```
|
||||
|
||||
### دریافت تعادل هفتگی
|
||||
```csharp
|
||||
var balance = await _context.NetworkWeeklyBalances
|
||||
.Include(b => b.WeekDefinition)
|
||||
.Where(b => b.UserId == userId && b.WeekDefinitionId == weekDefinitionId)
|
||||
.Select(b => new {
|
||||
b.WeekDefinitionId,
|
||||
WeekDisplayName = $"هفته {b.WeekDefinition.WeekOrder} - {b.WeekDefinition.StartDatePersian}",
|
||||
b.LeftBalance,
|
||||
b.RightBalance,
|
||||
b.WeekDefinition.StartDatePersian,
|
||||
b.WeekDefinition.EndDatePersian
|
||||
})
|
||||
.FirstOrDefaultAsync();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ ملاحظات مایگریشن
|
||||
|
||||
### EF Migration
|
||||
```bash
|
||||
# ایجاد migration
|
||||
dotnet ef migrations add MigrateWeekNumberToWeekDefinitionId \
|
||||
-p CMSMicroservice.Infrastructure \
|
||||
-s CMSMicroservice.WebApi
|
||||
|
||||
# اجرای migration
|
||||
dotnet ef database update \
|
||||
-p CMSMicroservice.Infrastructure \
|
||||
-s CMSMicroservice.WebApi
|
||||
```
|
||||
|
||||
### Data Migration Script
|
||||
```sql
|
||||
-- Step 1: Add new column
|
||||
ALTER TABLE NetworkWeeklyBalances ADD WeekDefinitionId BIGINT NULL;
|
||||
|
||||
-- Step 2: Populate from WeekDefinitions
|
||||
UPDATE nwb
|
||||
SET nwb.WeekDefinitionId = wd.Id
|
||||
FROM NetworkWeeklyBalances nwb
|
||||
INNER JOIN WeekDefinitions wd ON
|
||||
CONCAT(wd.Year, '-', RIGHT('0' + CAST(wd.WeekOrder AS VARCHAR), 2)) = nwb.WeekNumber;
|
||||
|
||||
-- Step 3: Add FK constraint
|
||||
ALTER TABLE NetworkWeeklyBalances
|
||||
ADD CONSTRAINT FK_NetworkWeeklyBalances_WeekDefinitions
|
||||
FOREIGN KEY (WeekDefinitionId) REFERENCES WeekDefinitions(Id);
|
||||
|
||||
-- Step 4: Drop old column (after verification)
|
||||
ALTER TABLE NetworkWeeklyBalances DROP COLUMN WeekNumber;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 تغییرات API
|
||||
|
||||
### Request Changes
|
||||
```
|
||||
// قبل
|
||||
GET /api/commission/payouts?weekNumber=2025-01
|
||||
|
||||
// بعد
|
||||
GET /api/commission/payouts?weekDefinitionId=42
|
||||
```
|
||||
|
||||
### Response Changes
|
||||
```json
|
||||
// قبل
|
||||
{
|
||||
"weekNumber": "2025-01",
|
||||
"weekLabel": "هفته 1 - 1403/10/01"
|
||||
}
|
||||
|
||||
// بعد
|
||||
{
|
||||
"weekDefinitionId": 42,
|
||||
"weekDisplayName": "هفته 1 - 1403/10/01"
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user