docs: BIZ-PACKAGE-BASED-SYSTEM v3 — per-package commission deep analysis
Major v3 changes: - Q12-Q18: MaxWeeklyBalancesPerLeg, MaxNetworkLevel, MagicWalletMaxDeposit, MagicWalletMaxCredit all become per-package (not global SystemConstants) - NetworkWeeklyBalance gets PackageId + Unique(UserId,WeekId,PackageId) - SP changes: @MaxBalancesPerLeg and @MaxNetworkLevel as dynamic params (removing hardcoded 300/15) - SpCommissionCalculationStrategy: pass package settings to SPs - Carryover per-package: week-shifting only for same PackageId records - commission.proto: package_id+package_title in 4 message types, new CustomerCommissionPackageSummary message, package filter in requests - FrontOffice: commission dashboard with per-package summary cards - BackOffice: package filter dropdown in all commission reports + CSV - Package Create/Edit: Quick Access checkboxes for features inline - Seed data: silver MaxBalancesPerLeg=30, MagicWalletMax=100M/250M - Migration: NetworkWeeklyBalances existing records get base PackageId - Impact Analysis: 39 -> 48+ changes across 6 layers - Timeline: 14 -> 17 days critical path (+3 days for per-package work) Updated docs: - business/BIZ-PACKAGE-BASED-SYSTEM.md (v2 -> v3) - roadmap/PACKAGE-TRANSFORMATION-TASKS.md (synced with v3)
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
|
||||
> **وضعیت:** تاییدشده — آماده پیادهسازی
|
||||
> **تاریخ بروزرسانی:** ۶ اسفند ۱۴۰۴
|
||||
> **نسخه:** v2 (بازنویسی کامل بعد از تحلیل عمیق کدبیس)
|
||||
> **تاثیرگذاری:** زیاد — ۳۹ فایل در ۶ لایه
|
||||
> **نسخه:** v3 (تکمیل تحلیل پورسانت per-package + گزارشدهی + SystemConstants کامل)
|
||||
> **تاثیرگذاری:** زیاد — ۵۵+ فایل در ۶ لایه
|
||||
|
||||
---
|
||||
|
||||
@@ -30,6 +30,13 @@
|
||||
| Q9 | MagicWallet Multiplier | ✅ **داینامیک** بهازای هر پکیج (فعلاً همه ×2.5) |
|
||||
| Q10 | کاربران دایا | ✅ **پکیج پایه** گرفتن — "طلایی" اشتباه نامگذاری بوده |
|
||||
| Q11 | فیچرها | ✅ **داینامیک** — ادمین مدیریت میکند |
|
||||
| Q12 | MaxWeeklyBalancesPerLeg (300) | ✅ **per-package** — پکیج نقرهای ۳۰، پکیج پایه ۳۰۰ |
|
||||
| Q13 | MaxNetworkLevel (15) | ✅ **per-package** — ادمین تنظیم کند |
|
||||
| Q14 | MagicWalletMaxDeposit (1B) | ✅ **per-package** — سقف شارژ بر اساس پکیج |
|
||||
| Q15 | MagicWalletMaxCredit (2.5B) | ✅ **per-package** — سقف اعتبار بر اساس پکیج |
|
||||
| Q16 | NetworkWeeklyBalance + PackageId | ✅ **هر رکورد تعادل = per-package** — carryover هم جداگانه |
|
||||
| Q17 | گزارش پورسانت FO | ✅ **breakdown per-package** — مشتری ببیند از هر پکیج چقدر |
|
||||
| Q18 | گزارش پورسانت BO | ✅ **فیلتر بر اساس پکیج** — ادمین بر اساس پکیج فیلتر کند |
|
||||
|
||||
---
|
||||
|
||||
@@ -132,6 +139,14 @@ public class Package : BaseAuditableEntity
|
||||
public decimal DiscountMultiplier { get; set; } = 2.0m; // ضریب شارژ DiscountBalance
|
||||
public decimal MagicWalletMultiplier { get; set; } = 2.5m; // ضریب کیفپول جادویی
|
||||
|
||||
// === تنظیمات پورسانت (v3 — انتقال از SystemConstants) ===
|
||||
public int MaxBalancesPerLeg { get; set; } = 300; // سقف تعادل هر پا (نقرهای=۳۰)
|
||||
public int MaxNetworkLevel { get; set; } = 15; // عمق شبکه برای محاسبه
|
||||
|
||||
// === تنظیمات کیفپول جادویی (v3) ===
|
||||
public long MagicWalletMaxDeposit { get; set; } = 1_000_000_000; // سقف شارژ
|
||||
public long MagicWalletMaxCredit { get; set; } = 2_500_000_000; // سقف اعتبار
|
||||
|
||||
// === Navigation ===
|
||||
public virtual ICollection<PackageFeature> PackageFeatures { get; set; }
|
||||
public virtual ICollection<UserPackagePurchase> Purchases { get; set; }
|
||||
@@ -167,8 +182,14 @@ public class PackageFeature : BaseAuditableEntity
|
||||
| `ClubMembershipCycle` | `long PackageId` + FK | پکیج این چرخه |
|
||||
| `WeeklyCommissionPool` | `long PackageId` + FK | Pool جداگانه هر پکیج |
|
||||
| `UserCommissionPayout` | `long PackageId` + FK | از کدام Pool |
|
||||
| **`NetworkWeeklyBalance`** | **`long PackageId` + FK** ← v3 | **هر رکورد تعادل = per-package** |
|
||||
|
||||
**Constraint جدید:** `WeeklyCommissionPool` → Unique(`WeekDefinitionId`, `PackageId`)
|
||||
**Constraintهای جدید:**
|
||||
- `WeeklyCommissionPool` → Unique(`WeekDefinitionId`, `PackageId`)
|
||||
- `NetworkWeeklyBalance` → Unique(`UserId`, `WeekDefinitionId`, `PackageId`) ← v3
|
||||
- `UserCommissionPayout` → Unique(`UserId`, `WeekDefinitionId`, `PackageId`) ← v3
|
||||
|
||||
> ⚠️ **تاثیر حجم داده:** رکوردهای `NetworkWeeklyBalance` ضربدر تعداد پکیجهای فعال میشوند. مثلاً ۱۰۰۰ کاربر × ۲ پکیج = ۲۰۰۰ رکورد تعادل هفتگی (بجای ۱۰۰۰).
|
||||
|
||||
### ۴.۴ حذف/تغییر SystemConstants
|
||||
|
||||
@@ -179,9 +200,19 @@ public class PackageFeature : BaseAuditableEntity
|
||||
| `BasePackageAmount` | ❌ حذف | `Package.Price` |
|
||||
| `DayaLoanAmount` | ❌ حذف | `Package.Price` (base) |
|
||||
| `MagicWalletMultiplier` | ❌ حذف | `Package.MagicWalletMultiplier` |
|
||||
| `CommissionMaxWeeklyBalancesPerLeg` | ✅ حفظ | عمومی |
|
||||
| `CommissionMaxNetworkLevel` | ✅ حفظ | عمومی |
|
||||
| `CommissionMaxWeeklyBalancesPerLeg` | ❌ **حذف** ← تغییر از v2 | `Package.MaxBalancesPerLeg` (نقرهای=۳۰، پایه=۳۰۰) |
|
||||
| `CommissionMaxNetworkLevel` | ❌ **حذف** ← تغییر از v2 | `Package.MaxNetworkLevel` (قابل تنظیم ادمین) |
|
||||
| `MagicWalletMaxDeposit` | ❌ **حذف** ← جدید v3 | `Package.MagicWalletMaxDeposit` (سقف شارژ) |
|
||||
| `MagicWalletMaxCredit` | ❌ **حذف** ← جدید v3 | `Package.MagicWalletMaxCredit` (سقف اعتبار) |
|
||||
| `ShopVAT` | ✅ حفظ | عمومی |
|
||||
| `CommissionCalculationStrategy` | ✅ حفظ | عمومی (ORM or SP) |
|
||||
| `AllowDeletingParentsWithChildren` | ✅ حفظ | عمومی |
|
||||
| `MaxDirectChildrenPerLeg` | ✅ حفظ | عمومی |
|
||||
| `IsCommissionWithdrawalEnabled` | ✅ حفظ | عمومی |
|
||||
| `CommissionMinWithdrawalAmount` | ✅ حفظ | عمومی |
|
||||
| `IsMaintenanceMode` | ✅ حفظ | عمومی |
|
||||
| `IsAuditLogEnabled` | ✅ حفظ | عمومی |
|
||||
| `IsVATEnabled` | ✅ حفظ | عمومی |
|
||||
|
||||
### ۴.۵ فرمول مالی
|
||||
|
||||
@@ -276,14 +307,142 @@ Commission:
|
||||
Reza → پاداش از Pool_پایه
|
||||
```
|
||||
|
||||
### ۶.۳ تغییرات SP
|
||||
### ۶.۳ فلوی کامل چرخه خرید مجدد و تاثیر بر پورسانت (v3)
|
||||
|
||||
| SP | تغییر |
|
||||
|----|-------|
|
||||
| `sp_CalculateWeeklyBalances` | پارامتر `@PackageId` — فیلتر کاربران بر اساس PackageId |
|
||||
| `sp_CalculateWeeklyCommissionPool` | پارامتر `@PackageId` — Pool مخصوص آن پکیج |
|
||||
```
|
||||
چرخه ۱ — کاربر "علی" پکیج پایه میخرد (۵۶M):
|
||||
────────────────────────────────────────────────
|
||||
✅ Balance += 56M
|
||||
✅ DiscountBalance += 112M (×2)
|
||||
✅ ActivationFee → Pool_پایه هفته جاری
|
||||
✅ فیچرهای پکیج پایه فعال
|
||||
✅ NetworkWeeklyBalance ساخته میشود (PackageId=پایه)
|
||||
✅ بالاسریها: تعادلها بر اساس MaxBalancesPerLeg=300 + MaxNetworkLevel=15
|
||||
✅ پورسانت بالاسریها از Pool_پایه
|
||||
|
||||
### ۶.۴ تغییرات Service
|
||||
... خرید از فروشگاه → Balance صفر شد → Magic Mode فعال ...
|
||||
... خرید جادویی → MagicBalance صفر + Deposit ≥ MaxDeposit → EXIT Magic ...
|
||||
|
||||
چرخه ۲ — کاربر "علی" دوباره پکیج پایه میخرد:
|
||||
──────────────────────────────────────────────
|
||||
✅ ریست وضعیت: PackagePurchaseMethod=None, membership.IsActive=false
|
||||
✅ Balance += 56M (مجدد شارژ)
|
||||
✅ DiscountBalance += 112M (مجدد شارژ)
|
||||
✅ ActivationFee → Pool_پایه هفته جاری
|
||||
✅ فیچرهای پکیج پایه فعال (مجدد)
|
||||
✅ NetworkWeeklyBalance جدید (PackageId=پایه, WeekId=هفته جاری)
|
||||
✅ carryover از هفته قبل: فقط carryover پکیج پایه (نه نقرهای!)
|
||||
✅ بالاسریها: محاسبه مجدد از Pool_پایه
|
||||
|
||||
... همان چرخه Magic Wallet تکرار ...
|
||||
|
||||
چرخه ۵ — کاربر "علی" پکیج نقرهای میخرد (۵.۶M):
|
||||
────────────────────────────────────────────────────
|
||||
✅ Balance += 5.6M
|
||||
✅ DiscountBalance += 11.2M (×2)
|
||||
✅ ActivationFee → Pool_نقرهای هفته جاری (۲,۵۲۰,۰۰۰)
|
||||
✅ فیچرهای پکیج نقرهای فعال (ممکنه کمتر از پایه باشه!)
|
||||
✅ NetworkWeeklyBalance جدید (PackageId=نقرهای, WeekId=هفته جاری)
|
||||
✅ تعادلها: MaxBalancesPerLeg=30 (نه 300!) + MaxNetworkLevel=15 (از پکیج)
|
||||
✅ carryover: فقط carryover نقرهای (جداگانه از پایه)
|
||||
✅ بالاسریها: محاسبه از Pool_نقرهای → ValuePerBalance کمتر
|
||||
✅ پاداش بالاسری: ~۲,۵۲۰,۰۰۰ ÷ TotalBalances_نقرهای × BalancesEarned
|
||||
```
|
||||
|
||||
### ۶.۴ تعادلها (NetworkWeeklyBalance) — per-package (v3)
|
||||
|
||||
> ⚠️ **تغییر اساسی:** هر کاربر **بهازای هر پکیج فعال** یک رکورد تعادل جداگانه دارد.
|
||||
|
||||
```
|
||||
قبل (تکپکیج):
|
||||
NetworkWeeklyBalance: [UserId, WeekId] → یک رکورد
|
||||
|
||||
بعد (چندپکیج):
|
||||
NetworkWeeklyBalance: [UserId, WeekId, PackageId] → N رکورد (N = تعداد پکیج)
|
||||
```
|
||||
|
||||
**الگوریتم محاسبه تعادل per-package:**
|
||||
|
||||
```
|
||||
برای هر پکیج فعال:
|
||||
1. واکشی کاربرانی که این پکیج را دارند (PackageId = X)
|
||||
2. carryover از هفته قبل: فقط رکوردهای PackageId = X
|
||||
3. اعضای جدید: فقط کسانی که PackageId = X خریدند + JoinedAt در بازه هفته
|
||||
4. LeftLegTotal = NewLeft + CarryoverLeft
|
||||
5. RightLegTotal = NewRight + CarryoverRight
|
||||
6. TotalBalances = MIN(Left, Right) → cap at Package.MaxBalancesPerLeg
|
||||
7. Remainder → carryover هفته بعد (فقط برای PackageId = X)
|
||||
8. SubordinateBalances: مجموع TotalBalances زیرمجموعه (تا Package.MaxNetworkLevel)
|
||||
```
|
||||
|
||||
**مثال عملی:**
|
||||
|
||||
```
|
||||
هفته ۱۰:
|
||||
علی (پکیج پایه):
|
||||
تعادل_پایه: Left=45, Right=52, Min=45 (cap 300) → OK
|
||||
تعادل_نقرهای: Left=0, Right=0 (علی پکیج نقرهای نداره)
|
||||
|
||||
سارا (پکیج نقرهای):
|
||||
تعادل_پایه: Left=0, Right=0
|
||||
تعادل_نقرهای: Left=12, Right=8, Min=8 (cap 30) → OK
|
||||
|
||||
رضا (پکیج پایه + قبلاً نقرهای داشته):
|
||||
تعادل_پایه: Left=30, Right=25, Min=25 (cap 300) → OK
|
||||
تعادل_نقرهای: Left=2 (carryover), Right=0 (carryover) → Min=0
|
||||
|
||||
هفته ۱۱ (Shift):
|
||||
علی: carryover_پایه = {Left: surplus_left, Right: surplus_right}
|
||||
سارا: carryover_نقرهای = {Left: surplus_left, Right: surplus_right}
|
||||
رضا: carryover_پایه = {...}, carryover_نقرهای = {Left:2, Right:0}
|
||||
```
|
||||
|
||||
### ۶.۵ تغییرات SP (v3 — بروزرسانی)
|
||||
|
||||
| SP | تغییرات v2 | تغییرات اضافی v3 |
|
||||
|----|------------|------------------|
|
||||
| `sp_CalculateWeeklyBalances` | پارامتر `@PackageId` | `@MaxBalancesPerLeg` و `@MaxNetworkLevel` هم **پارامتر** شوند (نه hardcoded) |
|
||||
| `sp_CalculateWeeklyCommissionPool` | پارامتر `@PackageId` | Pool فقط از تعادلهای همان PackageId |
|
||||
|
||||
**sp_CalculateWeeklyBalances — تغییرات ساختاری:**
|
||||
|
||||
```sql
|
||||
-- قبل (v2 — فقط PackageId فیلتر):
|
||||
CREATE PROCEDURE sp_CalculateWeeklyBalances
|
||||
@WeekDefinitionId BIGINT,
|
||||
@PackageId BIGINT,
|
||||
@MaxBalancesPerLeg INT = 300, -- ← hardcoded!
|
||||
@MaxNetworkLevel INT = 15 -- ← hardcoded!
|
||||
|
||||
-- بعد (v3 — همه داینامیک):
|
||||
CREATE PROCEDURE sp_CalculateWeeklyBalances
|
||||
@WeekDefinitionId BIGINT,
|
||||
@PackageId BIGINT,
|
||||
@MaxBalancesPerLeg INT, -- ← از Package entity خوانده میشود
|
||||
@MaxNetworkLevel INT, -- ← از Package entity خوانده میشود
|
||||
@ForceRecalculate BIT = 0,
|
||||
@RowCount INT OUTPUT
|
||||
```
|
||||
|
||||
**StoredProcedureCommissionCalculationStrategy — تغییرات:**
|
||||
|
||||
```csharp
|
||||
// قبل: فقط WeekDefinitionId پاس میداد
|
||||
await connection.ExecuteAsync("CMS.sp_CalculateWeeklyBalances",
|
||||
new { WeekDefinitionId = weekId, ForceRecalculate = true });
|
||||
|
||||
// بعد (v3): پکیج + تنظیمات داینامیک
|
||||
await connection.ExecuteAsync("CMS.sp_CalculateWeeklyBalances",
|
||||
new {
|
||||
WeekDefinitionId = weekId,
|
||||
PackageId = package.Id,
|
||||
MaxBalancesPerLeg = package.MaxBalancesPerLeg,
|
||||
MaxNetworkLevel = package.MaxNetworkLevel,
|
||||
ForceRecalculate = true
|
||||
});
|
||||
```
|
||||
|
||||
### ۶.۶ تغییرات Service (v3)
|
||||
|
||||
```csharp
|
||||
// WeeklyCommissionCalculationService — Loop روی پکیجها:
|
||||
@@ -293,11 +452,118 @@ var activePackages = await _context.Packages
|
||||
|
||||
foreach (var package in activePackages)
|
||||
{
|
||||
await strategy.CalculateWeeklyBalancesAsync(weekId, package.Id);
|
||||
_logger.LogInformation(
|
||||
"Calculating commission for package {Id}: {Title} " +
|
||||
"(MaxBalances={Max}, MaxLevel={Level})",
|
||||
package.Id, package.Title,
|
||||
package.MaxBalancesPerLeg, package.MaxNetworkLevel);
|
||||
|
||||
// محاسبه تعادلها — هر پکیج با تنظیمات خودش
|
||||
await strategy.CalculateWeeklyBalancesAsync(
|
||||
weekId, package.Id,
|
||||
package.MaxBalancesPerLeg, package.MaxNetworkLevel);
|
||||
|
||||
// محاسبه Pool — هر پکیج جداگانه
|
||||
await strategy.CalculateWeeklyPoolAsync(weekId, package.Id);
|
||||
}
|
||||
```
|
||||
|
||||
### ۶.۷ گزارشدهی پورسانت per-package (v3 — جدید)
|
||||
|
||||
> ⚠️ **فعلاً `package_id` در هیچکدام از پیامهای commission.proto وجود ندارد!**
|
||||
|
||||
#### تغییرات Proto (commission.proto):
|
||||
|
||||
```diff
|
||||
message UserWeeklyBalanceModel {
|
||||
// ... فیلدهای فعلی ...
|
||||
+ int64 package_id = 17;
|
||||
+ string package_title = 18;
|
||||
}
|
||||
|
||||
message UserCommissionPayoutModel {
|
||||
// ... فیلدهای فعلی ...
|
||||
+ int64 package_id = 16;
|
||||
+ string package_title = 17;
|
||||
}
|
||||
|
||||
message CustomerCommissionPayoutModel {
|
||||
// ... فیلدهای فعلی ...
|
||||
+ int64 package_id = 10;
|
||||
+ string package_title = 11;
|
||||
}
|
||||
|
||||
message CustomerWeeklyBalanceModel {
|
||||
// ... فیلدهای فعلی ...
|
||||
+ int64 package_id = 15;
|
||||
+ string package_title = 16;
|
||||
}
|
||||
|
||||
+ // مدل خلاصه پورسانت per-package برای مشتری
|
||||
+ message CustomerCommissionPackageSummary {
|
||||
+ int64 package_id = 1;
|
||||
+ string package_title = 2;
|
||||
+ int32 downline_count = 3; // تعداد زیرمجموعه با این پکیج
|
||||
+ int32 left_leg_members = 4;
|
||||
+ int32 right_leg_members = 5;
|
||||
+ int32 total_balances = 6;
|
||||
+ int64 commission_earned = 7; // پورسانت کسبشده از این پکیج
|
||||
+ string commission_formatted = 8;
|
||||
+ }
|
||||
|
||||
// Request فیلتر بر اساس پکیج
|
||||
message GetAllWeeklyBalancesByFilterRequest {
|
||||
// ... فیلدهای فعلی ...
|
||||
+ Int64Value package_id = 7; // فیلتر اختیاری
|
||||
}
|
||||
|
||||
message GetUserCommissionPayoutsRequest {
|
||||
// ... فیلدهای فعلی ...
|
||||
+ Int64Value package_id = 7; // فیلتر اختیاری
|
||||
}
|
||||
```
|
||||
|
||||
#### FrontOffice — گزارش پورسانت per-package (صفحه جدید/بهبود):
|
||||
|
||||
```
|
||||
┌─── پاداشهای من — هفته ۱۰ ────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ 📊 خلاصه بر اساس پکیج: │
|
||||
│ │
|
||||
│ ┌── پکیج پایه ─────────────────┐ ┌── پکیج نقرهای ───────────────┐ │
|
||||
│ │ زیرمجموعه: ۱۲ نفر │ │ زیرمجموعه: ۵ نفر │ │
|
||||
│ │ تیم اول: ۷ │ تیم دوم: ۵ │ │ تیم اول: ۳ │ تیم دوم: ۲ │ │
|
||||
│ │ تعادل: ۵ │ │ تعادل: ۲ │ │
|
||||
│ │ 💰 پاداش: ۱,۲۵۰,۰۰۰ تومان │ │ 💰 پاداش: ۱۸۰,۰۰۰ تومان │ │
|
||||
│ └───────────────────────────────┘ └──────────────────────────────┘ │
|
||||
│ │
|
||||
│ 📦 مجموع پاداش هفته: ۱,۴۳۰,۰۰۰ تومان │
|
||||
│ ├── از پکیج پایه: ۱,۲۵۰,۰۰۰ │
|
||||
│ └── از پکیج نقرهای: ۱۸۰,۰۰۰ │
|
||||
└─────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### BackOffice — گزارش ادمین با فیلتر پکیج:
|
||||
|
||||
```
|
||||
┌─── گزارش تعادلها — هفته ۱۰ ───────────────────────────────────────┐
|
||||
│ │
|
||||
│ فیلتر: [▼ پکیج: همه ▼] [کاربر: ___] [هفته: ▼ هفته ۱۰ ▼] [جستجو]│
|
||||
│ ├── همه │
|
||||
│ ├── پکیج پایه │
|
||||
│ └── پکیج نقرهای │
|
||||
│ │
|
||||
│ # │ کاربر │ پکیج │ تیم اول │ تیم دوم │ تعادل │ سهم استخر │
|
||||
│ ──┼──────────┼─────────┼─────────┼─────────┼───────┼────────────────│
|
||||
│ 1 │ علی │ پایه │ ۴۵ │ ۵۲ │ ۴۵ │ ۲,۲۵۰,۰۰۰ │
|
||||
│ 2 │ سارا │ نقرهای │ ۱۲ │ ۸ │ ۸ │ ۱۴۴,۰۰۰ │
|
||||
│ 3 │ رضا │ پایه │ ۳۰ │ ۲۵ │ ۲۵ │ ۱,۲۵۰,۰۰۰ │
|
||||
│ 4 │ رضا │ نقرهای │ ۲ │ ۰ │ ۰ │ ۰ │
|
||||
│ │
|
||||
│ خلاصه: پکیج پایه: ۷۰ تعادل | پکیج نقرهای: ۸ تعادل │
|
||||
└──────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۷. Event-Driven Side Effects
|
||||
@@ -330,12 +596,16 @@ INSERT INTO "CMS"."Packages" (
|
||||
"Title", "Description", "Price", "IsActive", "IsBasePackage",
|
||||
"SupportsDayaPurchase", "SupportsDirectPurchase",
|
||||
"ActivationFee", "DiscountMultiplier", "MagicWalletMultiplier",
|
||||
"MaxBalancesPerLeg", "MaxNetworkLevel",
|
||||
"MagicWalletMaxDeposit", "MagicWalletMaxCredit",
|
||||
"SortOrder", "ImagePath"
|
||||
) VALUES (
|
||||
'پکیج پایه', 'پکیج اصلی باشگاه مشتریان کارا بازار سلامت',
|
||||
56000000, true, true,
|
||||
true, true,
|
||||
25200000, 2.0, 2.5,
|
||||
300, 15,
|
||||
1000000000, 2500000000,
|
||||
2, ''
|
||||
);
|
||||
|
||||
@@ -344,12 +614,16 @@ INSERT INTO "CMS"."Packages" (
|
||||
"Title", "Description", "Price", "IsActive", "IsBasePackage",
|
||||
"SupportsDayaPurchase", "SupportsDirectPurchase",
|
||||
"ActivationFee", "DiscountMultiplier", "MagicWalletMultiplier",
|
||||
"MaxBalancesPerLeg", "MaxNetworkLevel",
|
||||
"MagicWalletMaxDeposit", "MagicWalletMaxCredit",
|
||||
"SortOrder", "ImagePath"
|
||||
) VALUES (
|
||||
'پکیج نقرهای', 'پکیج سطح نقرهای باشگاه مشتریان',
|
||||
5600000, true, false,
|
||||
false, true,
|
||||
2520000, 2.0, 2.5,
|
||||
30, 15,
|
||||
100000000, 250000000,
|
||||
1, ''
|
||||
);
|
||||
|
||||
@@ -393,35 +667,43 @@ BEGIN
|
||||
UPDATE "CMS"."UserCommissionPayouts"
|
||||
SET "PackageId" = base_pkg_id WHERE "PackageId" IS NULL;
|
||||
|
||||
-- STEP 6: NetworkWeeklyBalance (v3 — جدید)
|
||||
UPDATE "CMS"."NetworkWeeklyBalances"
|
||||
SET "PackageId" = base_pkg_id WHERE "PackageId" IS NULL;
|
||||
|
||||
RAISE NOTICE 'Migration completed for PackageId=%', base_pkg_id;
|
||||
END $$;
|
||||
|
||||
-- STEP 6: Verify — همه باید 0 باشند
|
||||
-- STEP 7: Verify — همه باید 0 باشند
|
||||
SELECT 'ClubMemberships' AS tbl, COUNT(*) FROM "CMS"."ClubMemberships" WHERE "PackageId" IS NULL
|
||||
UNION ALL
|
||||
SELECT 'Cycles', COUNT(*) FROM "CMS"."ClubMembershipCycles" WHERE "PackageId" IS NULL
|
||||
UNION ALL
|
||||
SELECT 'Pools', COUNT(*) FROM "CMS"."WeeklyCommissionPools" WHERE "PackageId" IS NULL
|
||||
UNION ALL
|
||||
SELECT 'Payouts', COUNT(*) FROM "CMS"."UserCommissionPayouts" WHERE "PackageId" IS NULL;
|
||||
SELECT 'Payouts', COUNT(*) FROM "CMS"."UserCommissionPayouts" WHERE "PackageId" IS NULL
|
||||
UNION ALL
|
||||
SELECT 'Balances', COUNT(*) FROM "CMS"."NetworkWeeklyBalances" WHERE "PackageId" IS NULL;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۱۰. Impact Analysis — ۳۹ تغییر در ۶ لایه
|
||||
## ۱۰. Impact Analysis — ۴۸+ تغییر در ۶ لایه (v3)
|
||||
|
||||
### ۱۰.۱ لایه Domain (۸ تغییر)
|
||||
### ۱۰.۱ لایه Domain (۱۰ تغییر)
|
||||
|
||||
| # | فایل | نوع | شدت |
|
||||
|---|------|-----|------|
|
||||
| D1 | `Package.cs` | اضافه ۷ فیلد جدید | 🟡 |
|
||||
| D2 | `PackageFeature.cs` | Entity جدید + EF Config | 🔴 |
|
||||
| D3 | `ClubMembership.cs` | اضافه `PackageId` | 🟡 |
|
||||
| D4 | `ClubMembershipCycle.cs` | اضافه `PackageId` | 🟡 |
|
||||
| D5 | `WeeklyCommissionPool.cs` | اضافه `PackageId` + Unique | 🔴 |
|
||||
| D6 | `UserCommissionPayout.cs` | اضافه `PackageId` | 🟡 |
|
||||
| D7 | `SystemConstants.cs` | حذف ۵ ثابت، حفظ بقیه | 🟡 |
|
||||
| D8 | EF Migration + Seed | schema + data migration | 🔴 |
|
||||
| # | فایل | نوع | شدت | v3? |
|
||||
|---|------|-----|------|-----|
|
||||
| D1 | `Package.cs` | اضافه **۱۱ فیلد** جدید (v2: ۷ + v3: ۴) | 🟡 | 🔄 |
|
||||
| D2 | `PackageFeature.cs` | Entity جدید + EF Config | 🔴 | |
|
||||
| D3 | `ClubMembership.cs` | اضافه `PackageId` | 🟡 | |
|
||||
| D4 | `ClubMembershipCycle.cs` | اضافه `PackageId` | 🟡 | |
|
||||
| D5 | `WeeklyCommissionPool.cs` | اضافه `PackageId` + Unique | 🔴 | |
|
||||
| D6 | `UserCommissionPayout.cs` | اضافه `PackageId` + Unique(UserId,WeekId,PackageId) | 🟡 | 🔄 |
|
||||
| D7 | `SystemConstants.cs` | حذف **۷ ثابت** (v2: ۵ + v3: ۲)، حفظ ۱۱ | 🟡 | 🔄 |
|
||||
| D8 | EF Migration + Seed | schema + data migration | 🔴 | |
|
||||
| **D9** | **`NetworkWeeklyBalance.cs`** | **اضافه `PackageId` + Unique(UserId,WeekId,PackageId)** | **🔴** | **🆕** |
|
||||
| **D10** | **Data volume impact** | **رکوردهای تعادل ×N (تعداد پکیج)** | **🟡** | **🆕** |
|
||||
|
||||
### ۱۰.۲ لایه Application (۱۲ تغییر)
|
||||
|
||||
@@ -440,44 +722,53 @@ SELECT 'Payouts', COUNT(*) FROM "CMS"."UserCommissionPayouts" WHERE "PackageId"
|
||||
| A11 | `UserOrderService` (EXIT Magic) | ریست PackagePurchaseMethod + Deactivate | 🔴 |
|
||||
| A12 | Package CRUD handlers | فیلدهای جدید + PackageFeature CRUD | 🟡 |
|
||||
|
||||
### ۱۰.۳ لایه Infrastructure (۵ تغییر)
|
||||
### ۱۰.۳ لایه Infrastructure (۶ تغییر)
|
||||
|
||||
| # | فایل | نوع | شدت |
|
||||
|---|------|-----|------|
|
||||
| I1 | `sp_CalculateWeeklyBalances` | پارامتر `@PackageId` | 🔴 |
|
||||
| I2 | `sp_CalculateWeeklyCommissionPool` | پارامتر `@PackageId` | 🔴 |
|
||||
| I3 | `WeeklyCommissionCalculationService` | Loop روی پکیجها | 🟡 |
|
||||
| I4 | `OrmCommissionCalculationStrategy` | فیلتر PackageId | 🔴 |
|
||||
| I5 | `SpCommissionCalculationStrategy` | پاس دادن PackageId | 🟡 |
|
||||
| # | فایل | نوع | شدت | v3? |
|
||||
|---|------|-----|------|-----|
|
||||
| I1 | `sp_CalculateWeeklyBalances` | پارامتر `@PackageId` + **`@MaxBalancesPerLeg`** + **`@MaxNetworkLevel`** (حذف hardcode) | 🔴 | 🔄 |
|
||||
| I2 | `sp_CalculateWeeklyCommissionPool` | پارامتر `@PackageId` + فیلتر تعادلهای همان پکیج | 🔴 | 🔄 |
|
||||
| I3 | `WeeklyCommissionCalculationService` | Loop روی پکیجها + ارسال تنظیمات هر پکیج | 🟡 | 🔄 |
|
||||
| I4 | `OrmCommissionCalculationStrategy` | فیلتر PackageId + خواندن MaxBalancesPerLeg/MaxNetworkLevel از Package | 🔴 | 🔄 |
|
||||
| I5 | `SpCommissionCalculationStrategy` | پاس دادن PackageId + MaxBalancesPerLeg + MaxNetworkLevel | 🟡 | 🔄 |
|
||||
| **I6** | **Carryover logic** | **Week-shifting per-package: carryover فقط رکوردهای همان PackageId** | **🔴** | **🆕** |
|
||||
|
||||
### ۱۰.۴ لایه Proto/gRPC (۴ تغییر)
|
||||
### ۱۰.۴ لایه Proto/gRPC (۶ تغییر)
|
||||
|
||||
| # | فایل | نوع | شدت |
|
||||
|---|------|-----|------|
|
||||
| P1 | `package.proto` | فیلدهای جدید Package | 🟡 |
|
||||
| P2 | `clubmembership.proto` | `package_id` در request/response | 🟡 |
|
||||
| P3 | `commission.proto` | `package_id` در pool/payout | 🟡 |
|
||||
| P4 | `PackageGrpcService.cs` | Generic purchase + CRUD | 🟡 |
|
||||
| # | فایل | نوع | شدت | v3? |
|
||||
|---|------|-----|------|-----|
|
||||
| P1 | `package.proto` | فیلدهای جدید Package (۱۱ فیلد) | 🟡 | 🔄 |
|
||||
| P2 | `clubmembership.proto` | `package_id` در request/response | 🟡 | |
|
||||
| P3 | `commission.proto` | **`package_id` + `package_title`** در ۴ message: UserWeeklyBalance, UserCommissionPayout, CustomerCommissionPayout, CustomerWeeklyBalance | **🔴** | **🔄** |
|
||||
| P4 | `PackageGrpcService.cs` | Generic purchase + CRUD | 🟡 | |
|
||||
| **P5** | **`commission.proto`** | **Message جدید: `CustomerCommissionPackageSummary`** (خلاصه per-package) | **🟡** | **🆕** |
|
||||
| **P6** | **`commission.proto`** | **فیلتر اختیاری `package_id` در Requestهای** GetWeeklyBalances + GetPayouts | **🟡** | **🆕** |
|
||||
|
||||
### ۱۰.۵ لایه FrontOffice (۶ تغییر)
|
||||
### ۱۰.۵ لایه FrontOffice (۸ تغییر)
|
||||
|
||||
| # | فایل | نوع | شدت |
|
||||
|---|------|-----|------|
|
||||
| F1 | `Packages.razor` | کاشیهای پکیج از API | 🔴 |
|
||||
| F2 | `PackageDetail.razor` | فیچرها از PackageFeature | 🟡 |
|
||||
| F3 | `ActivationSection.razor` | حذف hardcoded 56M | 🟡 |
|
||||
| F4 | `ClubMembershipContractDialog.razor` | متن قرارداد داینامیک | 🟡 |
|
||||
| F5 | `MyPackages.razor` | نمایش نوع پکیج + re-purchase | 🟡 |
|
||||
| F6 | `PackageService.cs` | فیکس stub GetPurchaseHistory | 🟡 |
|
||||
| # | فایل | نوع | شدت | v3? |
|
||||
|---|------|-----|------|-----|
|
||||
| F1 | `Packages.razor` | کاشیهای پکیج از API | 🔴 | |
|
||||
| F2 | `PackageDetail.razor` | فیچرها از PackageFeature | 🟡 | |
|
||||
| F3 | `ActivationSection.razor` | حذف hardcoded 56M | 🟡 | |
|
||||
| F4 | `ClubMembershipContractDialog.razor` | متن قرارداد داینامیک | 🟡 | |
|
||||
| F5 | `MyPackages.razor` | نمایش نوع پکیج + re-purchase | 🟡 | |
|
||||
| F6 | `PackageService.cs` | فیکس stub GetPurchaseHistory | 🟡 | |
|
||||
| **F7** | **`CommissionDashboardPage.razor`** | **خلاصه پاداش per-package (کارتهای جداگانه هر پکیج)** | **🔴** | **🆕** |
|
||||
| **F8** | **`WeeklyBalancePage.razor`** | **تعادلها per-package (تیم اول/دوم بر اساس پکیج)** | **🟡** | **🆕** |
|
||||
|
||||
### ۱۰.۶ لایه BackOffice (۴ تغییر)
|
||||
### ۱۰.۶ لایه BackOffice (۸ تغییر)
|
||||
|
||||
| # | فایل | نوع | شدت |
|
||||
|---|------|-----|------|
|
||||
| BO1 | `PackageCreateDialog.razor` | فیلدهای جدید | 🟡 |
|
||||
| BO2 | `PackageEditDialog.razor` | فیلدهای جدید | 🟡 |
|
||||
| BO3 | `PackageFeatureMatrixPage` — **جدید** | ماتریس پکیج×فیچر | 🔴 |
|
||||
| BO4 | `ActivateClubDialog.razor` | dropdown انتخاب پکیج | 🟡 |
|
||||
| # | فایل | نوع | شدت | v3? |
|
||||
|---|------|-----|------|-----|
|
||||
| BO1 | `PackageCreateDialog.razor` | فیلدهای جدید (**۱۱ فیلد** شامل MaxBalancesPerLeg, MaxNetworkLevel, MagicWallet limits) | 🟡 | 🔄 |
|
||||
| BO2 | `PackageEditDialog.razor` | فیلدهای جدید + **Quick Access فیچرها** (checkbox فیچرها در همان فرم) | 🟡 | 🔄 |
|
||||
| BO3 | `PackageFeatureMatrixPage` — **جدید** | ماتریس پکیج×فیچر | 🔴 | |
|
||||
| BO4 | `ActivateClubDialog.razor` | dropdown انتخاب پکیج | 🟡 | |
|
||||
| **BO5** | **`Dashboard.razor` (Commission)** | **فیلتر dropdown پکیج + خلاصه per-package** | **🟡** | **🆕** |
|
||||
| **BO6** | **`WeeklyReportsPage.razor`** | **فیلتر پکیج + CSV export per-package** | **🟡** | **🆕** |
|
||||
| **BO7** | **`BalancesReportPage.razor`** | **فیلتر پکیج + ستون پکیج در جدول تعادلها** | **🟡** | **🆕** |
|
||||
| **BO8** | **`UserPayoutsPage.razor`** | **ستون پکیج در لیست پرداختها + فیلتر** | **🟡** | **🆕** |
|
||||
|
||||
---
|
||||
|
||||
@@ -494,18 +785,20 @@ SELECT 'Payouts', COUNT(*) FROM "CMS"."UserCommissionPayouts" WHERE "PackageId"
|
||||
|
||||
### فاز ۱ — زیرساخت (Domain + DB) ≈ ۳ روز
|
||||
|
||||
| تسک | شرح |
|
||||
|-----|------|
|
||||
| **T1.1** | بروزرسانی `Package` entity (۷ فیلد جدید) |
|
||||
| **T1.2** | ایجاد `PackageFeature` entity + EF Config |
|
||||
| **T1.3** | اضافه `PackageId` به `ClubMembership` |
|
||||
| **T1.4** | اضافه `PackageId` به `ClubMembershipCycle` |
|
||||
| **T1.5** | اضافه `PackageId` به `WeeklyCommissionPool` + Unique |
|
||||
| **T1.6** | اضافه `PackageId` به `UserCommissionPayout` |
|
||||
| **T1.7** | حذف ۵ ثابت از `SystemConstants` |
|
||||
| **T1.8** | Database Migration + Seed Data (۲ پکیج + فیچرها) |
|
||||
| **T1.9** | Data Migration: کاربران فعلی → PackageId = پکیج پایه |
|
||||
| **T1.10** | بروزرسانی Protoها |
|
||||
| تسک | شرح | v3? |
|
||||
|-----|----- |-----|
|
||||
| **T1.1** | بروزرسانی `Package` entity (**۱۱ فیلد** جدید: v2 ۷ + v3 ۴ شامل MaxBalancesPerLeg, MaxNetworkLevel, MagicWalletMaxDeposit, MagicWalletMaxCredit) | 🔄 |
|
||||
| **T1.2** | ایجاد `PackageFeature` entity + EF Config | |
|
||||
| **T1.3** | اضافه `PackageId` به `ClubMembership` | |
|
||||
| **T1.4** | اضافه `PackageId` به `ClubMembershipCycle` | |
|
||||
| **T1.5** | اضافه `PackageId` به `WeeklyCommissionPool` + Unique(WeekId,PackageId) | |
|
||||
| **T1.6** | اضافه `PackageId` به `UserCommissionPayout` + Unique(UserId,WeekId,PackageId) | 🔄 |
|
||||
| **T1.7** | حذف **۷ ثابت** از `SystemConstants` (v2: ۵ + v3: MaxWeeklyBalancesPerLeg, MaxNetworkLevel) | 🔄 |
|
||||
| **T1.8** | Database Migration + Seed Data (۲ پکیج + فیچرها) | |
|
||||
| **T1.9** | Data Migration: کاربران فعلی → PackageId = پکیج پایه | |
|
||||
| **T1.10** | بروزرسانی Protoها (package + clubmembership + commission) | 🔄 |
|
||||
| **T1.11** | **اضافه `PackageId` به `NetworkWeeklyBalance` + Unique(UserId,WeekId,PackageId)** | **🆕** |
|
||||
| **T1.12** | **Data Migration: `NetworkWeeklyBalance` موجود → PackageId = پکیج پایه** | **🆕** |
|
||||
|
||||
### فاز ۲ — منطق کسبوکار ≈ ۴ روز
|
||||
|
||||
@@ -522,37 +815,48 @@ SELECT 'Payouts', COUNT(*) FROM "CMS"."UserCommissionPayouts" WHERE "PackageId"
|
||||
| **T2.9** | PackageFeature CRUD |
|
||||
| **T2.10** | Event: PackageCreated → ساخت Pool خالی |
|
||||
|
||||
### فاز ۳ — محاسبه پورسانت ≈ ۳ روز (موازی با فاز ۲)
|
||||
### فاز ۳ — محاسبه پورسانت ≈ ۴ روز (موازی با فاز ۲)
|
||||
|
||||
| تسک | شرح |
|
||||
|-----|------|
|
||||
| **T3.1** | بروزرسانی `sp_CalculateWeeklyBalances` — `@PackageId` |
|
||||
| **T3.2** | بروزرسانی `sp_CalculateWeeklyCommissionPool` — `@PackageId` |
|
||||
| **T3.3** | بروزرسانی `WeeklyCommissionCalculationService` — Loop |
|
||||
| **T3.4** | بروزرسانی `OrmCommissionCalculationStrategy` — فیلتر |
|
||||
| **T3.5** | تست محاسبات با داده واقعی |
|
||||
| تسک | شرح | v3? |
|
||||
|-----|----- |-----|
|
||||
| **T3.1** | بروزرسانی `sp_CalculateWeeklyBalances` — `@PackageId` + **`@MaxBalancesPerLeg`** + **`@MaxNetworkLevel`** (حذف hardcode ۳۰۰/۱۵) | 🔄 |
|
||||
| **T3.2** | بروزرسانی `sp_CalculateWeeklyCommissionPool` — `@PackageId` + فیلتر تعادلهای همان پکیج | 🔄 |
|
||||
| **T3.3** | بروزرسانی `WeeklyCommissionCalculationService` — Loop روی پکیجها + ارسال تنظیمات | 🔄 |
|
||||
| **T3.4** | بروزرسانی `OrmCommissionCalculationStrategy` — فیلتر PackageId + خواندن Max از Package | 🔄 |
|
||||
| **T3.5** | **بروزرسانی `SpCommissionCalculationStrategy` — پاس دادن PackageId + MaxBalancesPerLeg + MaxNetworkLevel** | **🆕** |
|
||||
| **T3.6** | **Carryover per-package: week-shifting فقط رکوردهای همان PackageId** | **🆕** |
|
||||
| **T3.7** | تست محاسبات با داده واقعی (۲ پکیج موازی، carryover مجزا) | 🔄 |
|
||||
|
||||
### فاز ۴ — UI ≈ ۴ روز
|
||||
### فاز ۴ — UI ≈ ۵ روز
|
||||
|
||||
| تسک | شرح |
|
||||
|-----|------|
|
||||
| **T4.1** | FrontOffice: کاشیهای پکیج (داینامیک) |
|
||||
| **T4.2** | FrontOffice: مدال پرداخت (دایا+مستقیم / فقط مستقیم) |
|
||||
| **T4.3** | FrontOffice: MyPackages — re-purchase |
|
||||
| **T4.4** | FrontOffice: ActivationSection + Contract — داینامیک |
|
||||
| **T4.5** | BackOffice: CRUD پکیج — فیلدهای جدید |
|
||||
| **T4.6** | BackOffice: ماتریس PackageFeature |
|
||||
| **T4.7** | BackOffice: ActivateClubDialog — dropdown |
|
||||
| تسک | شرح | v3? |
|
||||
|-----|----- |-----|
|
||||
| **T4.1** | FrontOffice: کاشیهای پکیج (داینامیک) | |
|
||||
| **T4.2** | FrontOffice: مدال پرداخت (دایا+مستقیم / فقط مستقیم) | |
|
||||
| **T4.3** | FrontOffice: MyPackages — re-purchase | |
|
||||
| **T4.4** | FrontOffice: ActivationSection + Contract — داینامیک | |
|
||||
| **T4.5** | BackOffice: CRUD پکیج — فیلدهای جدید (۱۱ فیلد) | 🔄 |
|
||||
| **T4.6** | BackOffice: ماتریس PackageFeature | |
|
||||
| **T4.7** | BackOffice: ActivateClubDialog — dropdown | |
|
||||
| **T4.8** | **FrontOffice: CommissionDashboard — کارتهای خلاصه per-package + مجموع پاداش** | **🆕** |
|
||||
| **T4.9** | **FrontOffice: WeeklyBalance — تعادل تیم اول/دوم per-package** | **🆕** |
|
||||
| **T4.10** | **BackOffice: Commission Dashboard — فیلتر dropdown پکیج** | **🆕** |
|
||||
| **T4.11** | **BackOffice: Weekly Reports + CSV export — ستون پکیج + فیلتر** | **🆕** |
|
||||
| **T4.12** | **BackOffice: BalancesReport + UserPayouts — ستون پکیج + فیلتر** | **🆕** |
|
||||
| **T4.13** | **BackOffice: Package Create/Edit — Quick Access فیچرها (checkbox inline)** | **🆕** |
|
||||
|
||||
### فاز ۵ — تست و استقرار ≈ ۲ روز
|
||||
### فاز ۵ — تست و استقرار ≈ ۳ روز
|
||||
|
||||
| تسک | شرح |
|
||||
|-----|------|
|
||||
| **T5.1** | تست خرید هر پکیج |
|
||||
| **T5.2** | تست re-purchase بعد تکمیل چرخه |
|
||||
| **T5.3** | تست Commission Pool جداگانه |
|
||||
| **T5.4** | تست Migration |
|
||||
| **T5.5** | Deploy staging → production |
|
||||
| تسک | شرح | v3? |
|
||||
|-----|----- |-----|
|
||||
| **T5.1** | تست خرید هر پکیج | |
|
||||
| **T5.2** | تست re-purchase بعد تکمیل چرخه | |
|
||||
| **T5.3** | تست Commission Pool جداگانه | |
|
||||
| **T5.4** | تست Migration | |
|
||||
| **T5.5** | **تست تعادل per-package: carryover مجزا، MaxBalancesPerLeg متفاوت** | **🆕** |
|
||||
| **T5.6** | **تست گزارش FO per-package: مشتری breakdown صحیح میبیند** | **🆕** |
|
||||
| **T5.7** | **تست گزارش BO per-package: فیلتر پکیج + CSV** | **🆕** |
|
||||
| **T5.8** | Deploy staging → production |
|
||||
|
||||
---
|
||||
|
||||
@@ -568,16 +872,17 @@ SELECT 'Payouts', COUNT(*) FROM "CMS"."UserCommissionPayouts" WHERE "PackageId"
|
||||
|
||||
---
|
||||
|
||||
## ۱۳. تخمین زمانی
|
||||
## ۱۳. تخمین زمانی (v3)
|
||||
|
||||
| فاز | مدت | وابستگی |
|
||||
|-----|------|---------|
|
||||
| فاز ۰ — فیکس باگها | ۱ روز | — |
|
||||
| فاز ۱ — زیرساخت | ۳ روز | فاز ۰ |
|
||||
| فاز ۲ — منطق | ۴ روز | فاز ۱ |
|
||||
| فاز ۳ — پورسانت | ۳ روز | فاز ۱ |
|
||||
| فاز ۴ — UI | ۴ روز | فاز ۲ |
|
||||
| فاز ۵ — تست | ۲ روز | فاز ۳, ۴ |
|
||||
| **مجموع** | **~۱۷ روز** | |
|
||||
| فاز | مدت | وابستگی | v3 تغییر |
|
||||
|-----|------|---------|----------|
|
||||
| فاز ۰ — فیکس باگها | ۱ روز | — | |
|
||||
| فاز ۱ — زیرساخت | ۴ روز | فاز ۰ | +۱ روز (NetworkWeeklyBalance + Unique) |
|
||||
| فاز ۲ — منطق | ۴ روز | فاز ۱ | |
|
||||
| فاز ۳ — پورسانت | **۴ روز** | فاز ۱ | **+۱ روز** (SP params + carryover per-package) |
|
||||
| فاز ۴ — UI | **۵ روز** | فاز ۲ | **+۱ روز** (FO/BO گزارش per-package) |
|
||||
| فاز ۵ — تست | **۳ روز** | فاز ۳, ۴ | **+۱ روز** (تست carryover + گزارش) |
|
||||
| **مجموع** | **~۲۱ روز** | | |
|
||||
|
||||
> فاز ۲ و ۳ **موازی** → مسیر بحرانی: ۰→۱→۲→۴→۵ = **~۱۴ روز**
|
||||
> فاز ۲ و ۳ **موازی** → مسیر بحرانی: ۰→۱→۲→۴→۵ = **~۱۷ روز**
|
||||
> نسبت به v2 (**۱۴ روز**): +۳ روز بخاطر per-package commission + گزارشدهی + carryover
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
|
||||
> **وضعیت:** تاییدشده — آماده شروع
|
||||
> **تاریخ:** ۱۴۰۴/۱۲/۰۶
|
||||
> **پیشنیاز:** [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) v2
|
||||
> **هدف:** شکستن ۳۹ تغییر به تسکهای اتمیک با ترتیب اجرا و وابستگیها
|
||||
> **پیشنیاز:** [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) **v3** (تکمیل پورسانت per-package)
|
||||
> **هدف:** شکستن **۴۸+ تغییر** به تسکهای اتمیک با ترتیب اجرا و وابستگیها
|
||||
|
||||
> ⚠️ **تغییرات v3:** پورسانت per-package، carryover مجزا، SP parameters داینامیک، گزارشدهی FO/BO per-package
|
||||
|
||||
---
|
||||
|
||||
@@ -11,14 +13,13 @@
|
||||
|
||||
```
|
||||
مرحله ۰: فیکس باگ فوری (۱ روز)
|
||||
└─→ مرحله ۱: زیرساخت Domain + DB (۳ روز)
|
||||
└─→ مرحله ۱: زیرساخت Domain + DB (۴ روز) ← +۱ روز (v3: NetworkWeeklyBalance)
|
||||
├─→ مرحله ۲: منطق کسبوکار (۴ روز) ← موازی
|
||||
│ └─→ مرحله ۴: FrontOffice UI (۳ روز)
|
||||
└─→ مرحله ۳: پورسانت (۳ روز) ← موازی
|
||||
└─→ مرحله ۵: BackOffice UI (۳ روز)
|
||||
└─→ مرحله ۶: تست + استقرار (۲ روز)
|
||||
│ └─→ مرحله ۴: UI (۵ روز) ← +۲ (v3: FO/BO گزارش per-package)
|
||||
└─→ مرحله ۳: پورسانت (۴ روز) ← +۱ (v3: SP params + carryover)
|
||||
└─→ مرحله ۵: تست + استقرار (۳ روز) ← +۱
|
||||
|
||||
مسیر بحرانی: ۰→۱→۲→۴→۶ = ~۱۳ روز
|
||||
مسیر بحرانی: ۰→۱→۲→۴→۵ = ~۱۷ روز (v2: ۱۳ روز)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -69,7 +70,7 @@
|
||||
|
||||
> ⏱️ ۳ روز | وابستگی: مرحله ۰ | ریسک: متوسط (migration)
|
||||
|
||||
### T1.1 — بروزرسانی Package Entity
|
||||
### T1.1 — بروزرسانی Package Entity (۱۱ فیلد جدید — v3)
|
||||
|
||||
**فایل:** `CMS/src/CMSMicroservice.Domain/Entities/Package.cs`
|
||||
|
||||
@@ -82,6 +83,13 @@
|
||||
+ public long ActivationFee { get; set; }
|
||||
+ public decimal DiscountMultiplier { get; set; } = 2.0m;
|
||||
+ public decimal MagicWalletMultiplier { get; set; } = 2.5m;
|
||||
+ // === v3: تنظیمات پورسانت per-package ===
|
||||
+ public int MaxBalancesPerLeg { get; set; } = 300; // نقرهای=۳۰
|
||||
+ public int MaxNetworkLevel { get; set; } = 15;
|
||||
+ // === v3: سقف کیفپول جادویی per-package ===
|
||||
+ public long MagicWalletMaxDeposit { get; set; } = 1_000_000_000;
|
||||
+ public long MagicWalletMaxCredit { get; set; } = 2_500_000_000;
|
||||
+
|
||||
+ public virtual ICollection<PackageFeature> PackageFeatures { get; set; }
|
||||
```
|
||||
|
||||
@@ -106,14 +114,15 @@ public class PackageFeature : BaseAuditableEntity
|
||||
|
||||
### T1.3-T1.6 — اضافه PackageId به entityها
|
||||
|
||||
| Entity | فیلد | Required? | توضیح |
|
||||
|--------|------|-----------|-------|
|
||||
| ClubMembership | `long? PackageId` | nullable (بعد migration → required) | آخرین پکیج |
|
||||
| ClubMembershipCycle | `long PackageId` | required | پکیج این چرخه |
|
||||
| WeeklyCommissionPool | `long PackageId` | required + Unique(WeekDefId, PkgId) | Pool هر پکیج |
|
||||
| UserCommissionPayout | `long? PackageId` | nullable | ردیابی |
|
||||
| Entity | فیلد | Required? | توضیح | v3? |
|
||||
|--------|------|-----------|-------|-----|
|
||||
| ClubMembership | `long? PackageId` | nullable (بعد migration → required) | آخرین پکیج | |
|
||||
| ClubMembershipCycle | `long PackageId` | required | پکیج این چرخه | |
|
||||
| WeeklyCommissionPool | `long PackageId` | required + Unique(WeekDefId, PkgId) | Pool هر پکیج | |
|
||||
| UserCommissionPayout | `long? PackageId` | nullable + **Unique(UserId, WeekId, PkgId)** | ردیابی | 🔄 |
|
||||
| **NetworkWeeklyBalance** | **`long PackageId`** | **required + Unique(UserId, WeekId, PkgId)** | **تعادل per-package** | **🆕** |
|
||||
|
||||
### T1.7 — حذف SystemConstants
|
||||
### T1.7 — حذف SystemConstants (v3: ۷ ثابت)
|
||||
|
||||
**فایل:** `CMS/src/CMSMicroservice.Domain/Common/SystemConstants.cs`
|
||||
|
||||
@@ -122,10 +131,14 @@ public class PackageFeature : BaseAuditableEntity
|
||||
- public const long DayaLoanAmount = 56_000_000;
|
||||
- public const long ClubActivationFee = 25_200_000;
|
||||
- public const long ClubMembershipGiftValue = 25_200_000;
|
||||
- public const decimal MagicWalletMultiplier = 2.5m; // اگر وجود داشت
|
||||
- public const decimal MagicWalletMultiplier = 2.5m;
|
||||
- // === v3: انتقال به Package entity ===
|
||||
- public const int CommissionMaxWeeklyBalancesPerLeg = 300;
|
||||
- public const int CommissionMaxNetworkLevel = 15;
|
||||
```
|
||||
|
||||
> ⚠️ **قبل از حذف:** grep تمام مصرفکنندهها → جایگزین با `Package.Property`
|
||||
> ⚠️ **قبل از حذف:** grep تمام مصرفکنندهها → جایگزین با `Package.Property`
|
||||
> ⚠️ **v3:** `CommissionMaxWeeklyBalancesPerLeg` و `CommissionMaxNetworkLevel` هم باید per-package شوند
|
||||
|
||||
### T1.8 — Database Migration
|
||||
|
||||
@@ -151,7 +164,12 @@ UPDATE "CMS"."Packages" SET
|
||||
"SupportsDirectPurchase" = true,
|
||||
"ActivationFee" = 25200000,
|
||||
"DiscountMultiplier" = 2.0,
|
||||
"MagicWalletMultiplier" = 2.5
|
||||
"MagicWalletMultiplier" = 2.5,
|
||||
-- v3: تنظیمات پورسانت
|
||||
"MaxBalancesPerLeg" = 300,
|
||||
"MaxNetworkLevel" = 15,
|
||||
"MagicWalletMaxDeposit" = 1000000000,
|
||||
"MagicWalletMaxCredit" = 2500000000
|
||||
WHERE "Id" = 4;
|
||||
|
||||
-- 2. Link existing data to base package
|
||||
@@ -159,18 +177,50 @@ UPDATE "CMS"."ClubMemberships" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
|
||||
UPDATE "CMS"."ClubMembershipCycles" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
|
||||
UPDATE "CMS"."WeeklyCommissionPools" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
|
||||
UPDATE "CMS"."UserCommissionPayouts" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
|
||||
-- v3: NetworkWeeklyBalance هم PackageId میگیره
|
||||
UPDATE "CMS"."NetworkWeeklyBalances" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
|
||||
|
||||
-- 3. Seed Silver package
|
||||
INSERT INTO "CMS"."Packages" (...) VALUES ('پکیج نقرهای', 5600000, ...);
|
||||
-- 3. Seed Silver package (شامل فیلدهای v3)
|
||||
INSERT INTO "CMS"."Packages" (..., "MaxBalancesPerLeg", "MaxNetworkLevel",
|
||||
"MagicWalletMaxDeposit", "MagicWalletMaxCredit", ...)
|
||||
VALUES ('پکیج نقرهای', 5600000, ..., 30, 15, 100000000, 250000000, ...);
|
||||
```
|
||||
|
||||
### T1.10 — بروزرسانی Protoها
|
||||
|
||||
| Proto File | تغییر |
|
||||
|-----------|-------|
|
||||
| package.proto | فیلدهای جدید Package message |
|
||||
| clubmembership.proto | package_id در request/response |
|
||||
| commission.proto | package_id در pool/payout messages |
|
||||
| Proto File | تغیر | v3? |
|
||||
|-----------|-------|-----|
|
||||
| package.proto | فیلدهای جدید Package message (۱۱ فیلد) | 🔄 |
|
||||
| clubmembership.proto | package_id در request/response | |
|
||||
| commission.proto | **`package_id` + `package_title`** در ۴ message | **🆕** |
|
||||
| commission.proto | **Message جدید: `CustomerCommissionPackageSummary`** | **🆕** |
|
||||
| commission.proto | **فیلتر `package_id` در Requestها** | **🆕** |
|
||||
|
||||
### T1.11 — اضافه PackageId به NetworkWeeklyBalance (🆕 v3)
|
||||
|
||||
**فایل:** `CMS/src/CMSMicroservice.Domain/Entities/NetworkWeeklyBalance.cs`
|
||||
|
||||
```diff
|
||||
+ public long PackageId { get; set; }
|
||||
+ public virtual Package Package { get; set; }
|
||||
```
|
||||
|
||||
**EF Config:** اضافه Unique Index:
|
||||
```csharp
|
||||
builder.HasIndex(e => new { e.UserId, e.WeekDefinitionId, e.PackageId }).IsUnique();
|
||||
builder.HasOne(e => e.Package).WithMany().HasForeignKey(e => e.PackageId);
|
||||
```
|
||||
|
||||
> ⚠️ **تاثیر حجم:** رکوردهای تعادل ×N (تعداد پکیج). مثلاً ۱۰۰۰ کاربر × ۲ پکیج = ۲۰۰۰ رکورد هفتگی
|
||||
|
||||
### T1.12 — Data Migration: NetworkWeeklyBalance (🆕 v3)
|
||||
|
||||
```sql
|
||||
-- رکوردهای موجود → پکیج پایه
|
||||
UPDATE "CMS"."NetworkWeeklyBalances"
|
||||
SET "PackageId" = (SELECT "Id" FROM "CMS"."Packages" WHERE "IsBasePackage" = true LIMIT 1)
|
||||
WHERE "PackageId" IS NULL;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -256,29 +306,33 @@ INSERT INTO "CMS"."Packages" (...) VALUES ('پکیج نقرهای', 5600000,
|
||||
|
||||
## مرحله ۳ — محاسبه پورسانت (موازی با مرحله ۲)
|
||||
|
||||
> ⏱️ ۳ روز | وابستگی: مرحله ۱ | ریسک: بحرانی (مالی)
|
||||
> ⏱️ **۴ روز** (v3: +۱) | وابستگی: مرحله ۱ | ریسک: بحرانی (مالی)
|
||||
|
||||
### T3.1-T3.2 — SPs + PackageId
|
||||
### T3.1-T3.2 — SPs + PackageId + پارامترهای داینامیک (🔄 v3)
|
||||
|
||||
```sql
|
||||
-- sp_CalculateWeeklyBalances:
|
||||
-- sp_CalculateWeeklyBalances — v3: حذف hardcode
|
||||
ALTER PROCEDURE sp_CalculateWeeklyBalances
|
||||
@WeekDefinitionId BIGINT,
|
||||
@PackageId BIGINT -- ← جدید
|
||||
@PackageId BIGINT,
|
||||
@MaxBalancesPerLeg INT, -- v3: از Package entity (نه ۳۰۰ hardcode!)
|
||||
@MaxNetworkLevel INT -- v3: از Package entity (نه ۱۵ hardcode!)
|
||||
AS
|
||||
BEGIN
|
||||
-- فیلتر بالانسها فقط کاربرانی که این پکیج را دارند
|
||||
INSERT INTO "CMS"."WeeklyBalances" (...)
|
||||
SELECT ...
|
||||
-- فیلتر: فقط کاربرانی که این پکیج را دارند
|
||||
-- carryover: فقط رکوردهای PackageId = @PackageId
|
||||
-- cap: از @MaxBalancesPerLeg (نه ۳۰۰)
|
||||
-- depth: CTE تا @MaxNetworkLevel (نه ۱۵)
|
||||
INSERT INTO "CMS"."NetworkWeeklyBalances" ("PackageId", ...)
|
||||
SELECT @PackageId, ...
|
||||
FROM "CMS"."UserWallets" w
|
||||
INNER JOIN "CMS"."ClubMemberships" m ON m."UserId" = w."UserId"
|
||||
WHERE m."PackageId" = @PackageId -- ← فیلتر
|
||||
AND m."IsActive" = true
|
||||
AND w."WalletMode" = 0; -- Normal only
|
||||
WHERE m."PackageId" = @PackageId
|
||||
AND m."IsActive" = true;
|
||||
END;
|
||||
```
|
||||
|
||||
### T3.3 — Loop Service
|
||||
### T3.3 — Loop Service (🔄 v3: ارسال تنظیمات پکیج)
|
||||
|
||||
```csharp
|
||||
// WeeklyCommissionCalculationService.cs
|
||||
@@ -288,14 +342,71 @@ var activePackages = await _context.Packages
|
||||
|
||||
foreach (var package in activePackages)
|
||||
{
|
||||
_logger.LogInformation("Calculating commission for package {Id}: {Title}",
|
||||
package.Id, package.Title);
|
||||
_logger.LogInformation(
|
||||
"Calculating commission for package {Id}: {Title} " +
|
||||
"(MaxBalances={Max}, MaxLevel={Level})",
|
||||
package.Id, package.Title,
|
||||
package.MaxBalancesPerLeg, package.MaxNetworkLevel);
|
||||
|
||||
// v3: پاس دادن تنظیمات پکیج
|
||||
await strategy.CalculateWeeklyBalancesAsync(
|
||||
weekId, package.Id,
|
||||
package.MaxBalancesPerLeg, package.MaxNetworkLevel);
|
||||
|
||||
await strategy.CalculateWeeklyBalancesAsync(weekId, package.Id);
|
||||
await strategy.CalculateWeeklyPoolAsync(weekId, package.Id);
|
||||
}
|
||||
```
|
||||
|
||||
### T3.4 — OrmCommissionCalculationStrategy (🔄 v3)
|
||||
|
||||
**تغییرات:**
|
||||
```diff
|
||||
- var maxBalances = SystemConstants.CommissionMaxWeeklyBalancesPerLeg; // 300
|
||||
- var maxLevel = SystemConstants.CommissionMaxNetworkLevel; // 15
|
||||
+ // پارامتر از بیرون — per-package
|
||||
+ int maxBalances = maxBalancesPerLeg; // e.g., نقرهای=30, پایه=300
|
||||
+ int maxLevel = maxNetworkLevel;
|
||||
|
||||
- // فیلتر کاربران
|
||||
+ // فیلتر کاربران بر اساس پکیج
|
||||
+ .Where(m => m.PackageId == packageId && m.IsActive)
|
||||
|
||||
- // carryover
|
||||
+ // carryover: فقط رکوردهای همان PackageId
|
||||
+ .Where(b => b.PackageId == packageId && b.WeekDefinitionId == prevWeekId)
|
||||
```
|
||||
|
||||
### T3.5 — SpCommissionCalculationStrategy (🆕 v3)
|
||||
|
||||
```csharp
|
||||
// قبل: فقط WeekDefinitionId
|
||||
await connection.ExecuteAsync("CMS.sp_CalculateWeeklyBalances",
|
||||
new { WeekDefinitionId = weekId, ForceRecalculate = true });
|
||||
|
||||
// بعد (v3): پکیج + تنظیمات داینامیک
|
||||
await connection.ExecuteAsync("CMS.sp_CalculateWeeklyBalances",
|
||||
new {
|
||||
WeekDefinitionId = weekId,
|
||||
PackageId = package.Id,
|
||||
MaxBalancesPerLeg = package.MaxBalancesPerLeg,
|
||||
MaxNetworkLevel = package.MaxNetworkLevel,
|
||||
ForceRecalculate = true
|
||||
});
|
||||
```
|
||||
|
||||
### T3.6 — Carryover per-package (🆕 v3)
|
||||
|
||||
> ⚠️ **بحرانی:** week-shifting باید فقط رکوردهای همان PackageId را shift کند
|
||||
|
||||
```
|
||||
هفته ۱۰ → هفته ۱۱:
|
||||
علی: carryover_پایه = {Left: surplus, Right: surplus} ← جداگانه
|
||||
علی: carryover_نقرهای = {Left: 0, Right: 0} ← جداگانه
|
||||
|
||||
✖ اشتباه: قاطی کردن carryover پایه و نقرهای!
|
||||
✔ صحیح: هر PackageId فقط carryover خودش را میبینه
|
||||
```
|
||||
|
||||
### ⚠️ نکته بحرانی
|
||||
|
||||
> پورسانت = پول واقعی. **هر تغییر در SPs باید:**
|
||||
@@ -306,9 +417,9 @@ foreach (var package in activePackages)
|
||||
|
||||
---
|
||||
|
||||
## مرحله ۴ — FrontOffice UI
|
||||
## مرحله ۴ — UI (FrontOffice + BackOffice)
|
||||
|
||||
> ⏱️ ۳ روز | وابستگی: مرحله ۲ | ریسک: متوسط
|
||||
> ⏱️ **۵ روز** (v3: +۲) | وابستگی: مرحله ۲ + ۳ | ریسک: متوسط
|
||||
|
||||
### T4.1 — کاشیهای پکیج داینامیک
|
||||
|
||||
@@ -355,52 +466,118 @@ else
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
### T4.8 — FrontOffice: CommissionDashboard per-package (🆕 v3)
|
||||
|
||||
## مرحله ۵ — BackOffice UI
|
||||
**فایل:** `FrontOffice/src/.../Pages/Commission/CommissionDashboardPage.razor`
|
||||
|
||||
> ⏱️ ۳ روز | وابستگی: مرحله ۳ | ریسک: کم
|
||||
```razor
|
||||
@* v3: کارتهای خلاصه بر اساس پکیج *@
|
||||
<MudGrid>
|
||||
@foreach (var summary in _packageSummaries)
|
||||
{
|
||||
<MudItem xs="12" md="6">
|
||||
<MudCard>
|
||||
<MudCardHeader>@summary.PackageTitle</MudCardHeader>
|
||||
<MudCardContent>
|
||||
<p>زیرمجموعه: @summary.DownlineCount نفر</p>
|
||||
<p>تیم اول: @summary.LeftLegMembers | تیم دوم: @summary.RightLegMembers</p>
|
||||
<p>تعادل: @summary.TotalBalances</p>
|
||||
<p>💰 پاداش: @summary.CommissionFormatted</p>
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
</MudItem>
|
||||
}
|
||||
</MudGrid>
|
||||
<MudAlert>📦 مجموع پاداش هفته: @_totalCommission</MudAlert>
|
||||
```
|
||||
|
||||
_(تسکها در PACKAGE-TRANSFORMATION-UX.md بخش ۳ مستند شده)_
|
||||
### T4.9 — FrontOffice: WeeklyBalance per-package (🆕 v3)
|
||||
|
||||
> تعادل تیم اول/دوم به تفکیک هر پکیج نمایش داده شود
|
||||
|
||||
### T4.10-T4.12 — BackOffice: گزارشهای پورسانت per-package (🆕 v3)
|
||||
|
||||
**تغییرات مشترک:**
|
||||
- اضافه dropdown فیلتر پکیج (همه / پایه / نقرهای / ...)
|
||||
- اضافه ستون پکیج در جدولها
|
||||
- CSV export شامل ستون پکیج
|
||||
|
||||
| صفحه | تغییر |
|
||||
|------|-------|
|
||||
| Commission Dashboard | فیلتر + خلاصه per-package |
|
||||
| Weekly Reports | فیلتر + CSV per-package |
|
||||
| Balances Report | فیلتر + ستون پکیج |
|
||||
| User Payouts | ستون پکیج + فیلتر |
|
||||
|
||||
### T4.13 — BackOffice: Package CRUD + Quick Access فیچرها (🆕 v3)
|
||||
|
||||
> ادمین موقع ساخت/ویرایش پکیج، فیچرها را با checkbox در همان فرم تعیین کند
|
||||
|
||||
```razor
|
||||
@* در PackageCreateDialog / PackageEditDialog: *@
|
||||
<MudText Typo="Typo.h6">فیچرهای پکیج</MudText>
|
||||
@foreach (var feature in _allFeatures)
|
||||
{
|
||||
<MudCheckBox @bind-Checked="feature.IsIncluded" Label="@feature.Title" />
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## مرحله ۶ — تست و استقرار
|
||||
## مرحله ۵ — تست و استقرار
|
||||
|
||||
> ⏱️ ۲ روز | وابستگی: مرحله ۴ و ۵
|
||||
> ⏱️ **۳ روز** (v3: +۱) | وابستگی: مرحله ۴
|
||||
|
||||
### Checklist تست
|
||||
|
||||
**خرید + فعالسازی:**
|
||||
- [ ] خرید پکیج نقرهای (ZarinPal)
|
||||
- [ ] خرید پکیج پایه (ZarinPal)
|
||||
- [ ] خرید پکیج پایه (Daya Loan)
|
||||
- [ ] خرید پکیج پایه (Manual Payment)
|
||||
- [ ] فعالسازی باشگاه با پکیج نقرهای → فیچرهای محدود
|
||||
- [ ] فعالسازی باشگاه با پکیج پایه → همه فیچرها
|
||||
|
||||
**چرخه Magic + خرید مجدد:**
|
||||
- [ ] تکمیل چرخه Magic → ریست وضعیت
|
||||
- [ ] خرید مجدد بعد تکمیل چرخه
|
||||
- [ ] خرید مجدد بعد تکمیل چرخه (همان پکیج)
|
||||
- [ ] خرید مجدد با پکیج متفاوت (پایه → نقرهای)
|
||||
|
||||
**پورسانت per-package (v3):**
|
||||
- [ ] Commission Pool جداگانه هر پکیج
|
||||
- [ ] Data Migration — PackageId در رکوردهای قبلی
|
||||
- [ ] تعادل per-package: MaxBalancesPerLeg متفاوت (پایه=۳۰۰, نقرهای=۳۰)
|
||||
- [ ] Carryover مجزا: shift فقط رکوردهای همان PackageId
|
||||
- [ ] SP پارامترها صحیح: @MaxBalancesPerLeg و @MaxNetworkLevel از Package
|
||||
- [ ] NetworkWeeklyBalance رکوردها: ۲ پکیج = ۲× رکورد
|
||||
|
||||
**گزارش per-package (v3):**
|
||||
- [ ] FO: مشتری کارتهای خلاصه per-package را میبیند
|
||||
- [ ] FO: مجموع پاداش = جمع همه پکیجها
|
||||
- [ ] BO: فیلتر dropdown پکیج کار میکند
|
||||
- [ ] BO: CSV export شامل ستون پکیج
|
||||
|
||||
**Migration + سایر:**
|
||||
- [ ] Data Migration — PackageId در رکوردهای قبلی (شامل NetworkWeeklyBalance)
|
||||
- [ ] JWT claims جدید (CanRepurchase, PackageId)
|
||||
- [ ] UI: کاشیهای داینامیک FrontOffice
|
||||
- [ ] UI: ماتریس فیچر BackOffice
|
||||
- [ ] UI: ماتریس فیچر + Quick Access BackOffice
|
||||
- [ ] Rollback: بدون data loss
|
||||
|
||||
---
|
||||
|
||||
## 📅 تقویم پیشنهادی
|
||||
## 📅 تقویم پیشنهادی (v3)
|
||||
|
||||
| هفته | روز | تسک |
|
||||
|------|-----|------|
|
||||
| هفته ۱ | روز ۱ | مرحله ۰: فیکس ۴ باگ |
|
||||
| | روز ۲-۳ | مرحله ۱: Package entity + PackageFeature |
|
||||
| | روز ۴ | مرحله ۱: FKها + Migration |
|
||||
| هفته ۲ | روز ۵-۶ | مرحله ۲: Generic handlers + re-purchase |
|
||||
| | روز ۵-۶ | مرحله ۳: SP + Loop (موازی) |
|
||||
| | روز ۷-۸ | مرحله ۲: Guards + JWT + Manual |
|
||||
| هفته ۳ | روز ۹-۱۰ | مرحله ۴: FrontOffice UI |
|
||||
| | روز ۱۱ | مرحله ۵: BackOffice UI |
|
||||
| | روز ۱۲-۱۳ | مرحله ۶: تست + deploy |
|
||||
| | روز ۲-۳ | مرحله ۱: Package entity (۱۱ فیلد) + PackageFeature |
|
||||
| | روز ۴-۵ | مرحله ۱: FKها + NetworkWeeklyBalance + Migration |
|
||||
| هفته ۲ | روز ۶-۷ | مرحله ۲: Generic handlers + re-purchase |
|
||||
| | روز ۶-۸ | مرحله ۳: SP params + carryover per-package (موازی) |
|
||||
| | روز ۸-۱۰ | مرحله ۲: Guards + JWT + Manual |
|
||||
| هفته ۳ | روز ۱۱-۱۲ | مرحله ۴: FrontOffice UI + گزارش per-package |
|
||||
| | روز ۱۳-۱۴ | مرحله ۴: BackOffice UI + گزارش per-package |
|
||||
| | روز ۱۵-۱۷ | مرحله ۵: تست + deploy |
|
||||
|
||||
---
|
||||
|
||||
@@ -408,11 +585,11 @@ _(تسکها در PACKAGE-TRANSFORMATION-UX.md بخش ۳ مستند شده)_
|
||||
|
||||
| مستند | محتوا |
|
||||
|-------|-------|
|
||||
| [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) | طراحی فنی — ۳۹ تغییر + باگها |
|
||||
| [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) | طراحی فنی — **۴۸+ تغییر** (v3) + باگها |
|
||||
| [PACKAGE-TRANSFORMATION-UX.md](PACKAGE-TRANSFORMATION-UX.md) | تاثیر UX بر فرانتها |
|
||||
| [FEATURE-BACKLOG.md](FEATURE-BACKLOG.md) | بکلاگ ۱۲ RPC آماده |
|
||||
| [GRPC-SERVICES-AUDIT.md](../cms/GRPC-SERVICES-AUDIT.md) | آدیت ۳۴۲ RPC |
|
||||
|
||||
---
|
||||
|
||||
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۰۶*
|
||||
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۰۶ — v3 (پورسانت per-package + گزارشدهی + carryover)*
|
||||
|
||||
Reference in New Issue
Block a user