# مستندات سیستم کمیسیون (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" } ```