docs: BIZ-PACKAGE-BASED-SYSTEM v4 — comprehensive side-effect discovery
44 NEW side effects discovered across 6 layers (total: 92 changes): Side Effects — CMS Domain (3): Side Effects — CMS Application (10): - ChargeMagicWalletCommandHandler: global MagicWalletMaxDeposit (1B) - VerifyMagicWalletChargeCommandHandler: global multiplier ×2.5 - UserOrderService EXIT/ENTRY: global caps → user trapped/ejected wrong - 3 FluentValidation validators: hardcoded 1B ceiling - GetAllFeatureIds(): ALL features granted regardless of package - JWT: no PackageId/CanRepurchase, just boolean HasPurchased - WalletGrpcService.GetMagicWalletStatus: global caps to frontend - 4 Notifications: no PackageId in interface Side Effects — Background (3): - ClubMembershipCycleSeedService: seeds with hardcoded amounts - DayaLoanStatusCheckWorker: global DayaLoanAmount - ChatikaAccountActivationWorker: no package filter Side Effects — FrontOffice (9): - Contract text '56M toman' = LEGAL LIABILITY - Magic wallet ×2.5 and deposit cap hardcoded (6 places + C# code) - 'پکیج طلایی' hardcoded (5+ places) — wrong name - PackageId=1 hardcoded in activation flow Side Effects — BackOffice (8): - ManualActivationDialog: 56M hardcoded + disabled + no package selector - SystemConfigurationPage: global settings need per-package - CSV exports (3 places): no package column Impact: 48 core changes + 44 side effects = 92 total Timeline: v3 17 days → v4 22 days critical path (+5 days)
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
|
||||
> **وضعیت:** تاییدشده — آماده پیادهسازی
|
||||
> **تاریخ بروزرسانی:** ۶ اسفند ۱۴۰۴
|
||||
> **نسخه:** v3 (تکمیل تحلیل پورسانت per-package + گزارشدهی + SystemConstants کامل)
|
||||
> **تاثیرگذاری:** زیاد — ۵۵+ فایل در ۶ لایه
|
||||
> **نسخه:** v4 (تحلیل جامع سایدافکتها — ۴۴ مورد جدید)
|
||||
> **تاثیرگذاری:** زیاد — **۹۰+** تغییر در ۶ لایه (۴۸ اصلی + ۴۴ سایدافکت)
|
||||
|
||||
---
|
||||
|
||||
@@ -588,6 +588,228 @@ flowchart LR
|
||||
|
||||
---
|
||||
|
||||
## ۷٫۵ تحلیل جامع Side Effectها (v4 — کشف جدید)
|
||||
|
||||
> ⚠️ **این بخش سایدافکتهایی را مستند میکند که در تحلیلهای v1–v3 کشف نشده بودند.**
|
||||
> هر آیتم با بررسی عمیق کدبیس CMS، FrontOffice و BackOffice شناسایی شده.
|
||||
|
||||
### ۷٫۵٫۱ Entity — WalletChangeLog بدون PackageId
|
||||
|
||||
> 🔴 **بحرانی — ۲۱ محل ساخت WalletChangeLog**
|
||||
|
||||
Entity فعلی `UserWalletChangeLog` **هیچ فیلد PackageId ندارد**. در سیستم چندپکیجی نمیتوان ردیابی کرد کدام پکیج باعث تغییر کیفپول شده.
|
||||
|
||||
**محلهای ساخت WalletChangeLog (۲۱ مورد):**
|
||||
|
||||
| # | فایل | کانتکست |
|
||||
|---|------|---------|
|
||||
| 1-2 | `UserOrderService.cs` | خرید فروشگاه + لغو مشتری |
|
||||
| 3-4 | `VerifyPackagePurchaseCommandHandler` | Balance + DiscountBalance |
|
||||
| 5 | `VerifyBasePackagePaymentCommandHandler` | Balance |
|
||||
| 6-7 | `VerifyGoldenPackagePurchaseCommandHandler` | Balance + Discount |
|
||||
| 8 | `VerifyMagicWalletChargeCommandHandler` | شارژ جادویی |
|
||||
| 9-10 | `CheckAndProcessDayaLoansCommandHandler` | Balance + Discount |
|
||||
| 11-12 | `CreateManualPaymentCommandHandler` | Balance + Discount |
|
||||
| 13-18 | `ChargeUserWalletsCommandHandler` | ۶ شاخه switch |
|
||||
| 19 | `CancelOrderByAdminCommandHandler` | ریفاند ادمین |
|
||||
| 20 | `SpCommissionCalculationStrategy` | پرداخت پورسانت |
|
||||
| 21 | `OrmCommissionCalculationStrategy` | پرداخت پورسانت |
|
||||
|
||||
**اقدام لازم:**
|
||||
```csharp
|
||||
// اضافه به UserWalletChangeLog entity:
|
||||
public long? PackageId { get; set; }
|
||||
public virtual Package Package { get; set; }
|
||||
```
|
||||
+ Migration + بروزرسانی ۲۱ محل
|
||||
|
||||
---
|
||||
|
||||
### ۷٫۵٫۲ Validator — سقف hardcoded 1B
|
||||
|
||||
> 🟡 **متوسط — ۳ Validator**
|
||||
|
||||
| Validator | فایل | قانون | مشکل |
|
||||
|-----------|------|-------|------|
|
||||
| `ChargeMagicWalletCommandValidator` | FluentValidation | `.LessThanOrEqualTo(1_000_000_000)` | سقف global — پکیج نقرهای ممکنه ۱۰۰M باشه |
|
||||
| `ChargeDiscountWalletCommandValidator` | FluentValidation | `.LessThanOrEqualTo(1_000_000_000)` | سقف global |
|
||||
| `CreateManualPaymentCommandValidator` | FluentValidation | `.LessThanOrEqualTo(1_000_000_000)` | سقف global |
|
||||
|
||||
**اقدام:** Validator باید PackageId بگیره و از `Package.MagicWalletMaxDeposit` بخونه، یا حداکثر بین همه پکیجها.
|
||||
|
||||
---
|
||||
|
||||
### ۷٫۵٫۳ Magic Wallet — ۶ Side Effect
|
||||
|
||||
> 🔴 **بحرانی — چرخه حیات Magic Wallet کامل global است**
|
||||
|
||||
| # | فایل | مشکل | شدت |
|
||||
|---|------|------|------|
|
||||
| **MW1** | `ChargeMagicWalletCommandHandler` | `remainingDeposit = SystemConstants.MagicWalletMaxDeposit - wallet.MagicTotalDeposited` ← global 1B | 🔴 |
|
||||
| **MW2** | `VerifyMagicWalletChargeCommandHandler` | `creditAmount = depositAmount * SystemConstants.MagicWalletMultiplier` ← global ×2.5 | 🔴 |
|
||||
| **MW3** | `UserOrderService.cs` L347 | EXIT trigger: `wallet.MagicTotalDeposited >= SystemConstants.MagicWalletMaxDeposit` ← global 1B | 🔴 |
|
||||
| **MW4** | `UserOrderService.cs` L363 | ENTRY trigger: فقط `PackagePurchaseMethod != None` — چک نمیکنه **کدام** پکیج | 🟡 |
|
||||
| **MW5** | `WalletGrpcService` | `GetMagicWalletStatus` → سقف و باقیمانده global به FrontOffice ارسال | 🟡 |
|
||||
| **MW6** | `ActivateClubMembershipCommandHandler` | Guard: `WalletMode == Magic → throw` — مدت Magic وابسته به سقف per-package | 🟡 |
|
||||
|
||||
**فلوی مشکلدار:**
|
||||
```
|
||||
پکیج نقرهای (MaxDeposit=100M):
|
||||
کاربر ۱۰۰M شارژ کرد → باید EXIT شه
|
||||
❌ EXIT نمیشه! چون سیستم ۱B (global) چک میکنه
|
||||
❌ کاربر تا ابد در Magic Mode گیر میافته!
|
||||
|
||||
پکیج طلایی (MaxDeposit=2B):
|
||||
کاربر ۱B شارژ کرد → EXIT اشتباه!
|
||||
❌ سیستم فکر میکنه سقف رسیده
|
||||
❌ کاربر زودتر از موعد از Magic خارج میشه!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ۷٫۵٫۴ JWT Claims — بدون PackageId
|
||||
|
||||
> 🟡 **بالا — اطلاعات ناکافی JWT**
|
||||
|
||||
| Claim فعلی | نوع | مشکل |
|
||||
|------------|-----|------|
|
||||
| `HasPurchasedGoldenPackage` | `bool` | فقط boolean — نمیگه **کدام** پکیج |
|
||||
| `PackagePurchaseMethod` | missing | در JWT نیست — فقط در DB |
|
||||
| `CanRepurchase` | **وجود ندارد** | هیچجا تعریف نشده — UI نمیتونه دکمه خرید مجدد نشون بده |
|
||||
| `PackageId` | **وجود ندارد** | فرانت نمیدونه کاربر کدام پکیج رو داره |
|
||||
| `PackageTitle` | **وجود ندارد** | نام پکیج در JWT نیست |
|
||||
|
||||
**اقدام — Claims جدید:**
|
||||
```csharp
|
||||
claims.Add("PackageId", membership.PackageId?.ToString() ?? "");
|
||||
claims.Add("PackageTitle", package?.Title ?? "");
|
||||
claims.Add("CanRepurchase", HasCompletedMagicCycle(membership).ToString());
|
||||
// حذف HasPurchasedGoldenPackage → جایگزین با PackageId > 0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ۷٫۵٫۵ Club Features — تخصیص global
|
||||
|
||||
> 🔴 **بحرانی — همه فیچرها به همه کاربران**
|
||||
|
||||
```csharp
|
||||
// ActivateClubMembershipCommandHandler.cs + AcceptClubMembershipContractCommandHandler.cs:
|
||||
var featureIds = ClubFeatureTypeExtensions.GetAllFeatureIds();
|
||||
// ↑ همیشه همه فیچرها (Chatika, Bime, Trip, Learn) — صرفنظر از پکیج!
|
||||
```
|
||||
|
||||
**مشکل:** پکیج نقرهای ممکنه فقط ۲ فیچر داشته باشه ولی سیستم فعلی **همه ۴ فیچر** رو فعال میکنه.
|
||||
|
||||
**اقدام:**
|
||||
```csharp
|
||||
// باید بشه:
|
||||
var featureIds = await _context.PackageFeatures
|
||||
.Where(pf => pf.PackageId == package.Id && pf.IsIncluded)
|
||||
.Select(pf => pf.ClubFeatureId)
|
||||
.ToListAsync();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ۷٫۵٫۶ Notification — بدون PackageId
|
||||
|
||||
> 🟡 **متوسط — ۴ Notification**
|
||||
|
||||
| # | Notification | مشکل |
|
||||
|---|-------------|------|
|
||||
| N1 | `CommissionDepositedNotification` | پیام: "پورسانت X ریال واریز شد" — نمیگه از **کدام پکیج** |
|
||||
| N2 | `ClubActivatedNotification` | پیام: "عضویت فعال شد" — نمیگه **کدام پکیج** فعال شد |
|
||||
| N3 | `CommissionPayoutFailedNotification` | بدون PackageId |
|
||||
| N4 | Daya SMS | "وام دایا تایید شد" — نمیگه برای کدام پکیج |
|
||||
|
||||
**اقدام:** Interface `INotification` باید `PackageId` + `PackageTitle` بگیره.
|
||||
|
||||
---
|
||||
|
||||
### ۷٫۵٫۷ Background Services — ۳ سرویس
|
||||
|
||||
> 🟡 **متوسط**
|
||||
|
||||
| # | سرویس | مشکل |
|
||||
|---|--------|------|
|
||||
| BG1 | `ClubMembershipCycleSeedService` | چرخهها را با `PurchaseAmount=0` seed میکنه — PackageId ندارد |
|
||||
| BG2 | `DayaLoanStatusCheckWorker` | `DayaLoanAmount` global — بدون PackageId |
|
||||
| BG3 | `ChatikaAccountActivationWorker` | همه اعضا — بدون فیلتر پکیج (Chatika ممکنه فقط پکیج پایه) |
|
||||
|
||||
---
|
||||
|
||||
### ۷٫۵٫۸ Commission Reports — بدون PackageId
|
||||
|
||||
> 🟡 **متوسط**
|
||||
|
||||
| # | فایل | مشکل |
|
||||
|---|------|------|
|
||||
| CR1 | `CommissionWithdrawalReportService` | گزارش برداشت global — بدون فیلتر پکیج |
|
||||
| CR2 | `WorkerExecutionLog` | لاگ اجرای Hangfire — نمیگه کدام پکیج محاسبه شد |
|
||||
| CR3 | Admin manual trigger endpoint | `EnqueueCommissionCalculation` بدون پارامتر PackageId |
|
||||
|
||||
---
|
||||
|
||||
### ۷٫۵٫۹ FrontOffice — متنهای hardcoded
|
||||
|
||||
> 🔴 **بحرانی — مسئولیت حقوقی قرارداد**
|
||||
|
||||
| # | فایل | مشکل | شدت |
|
||||
|---|------|------|------|
|
||||
| FO1 | `ClubMembershipContractDialog.razor` | **"۵۶ میلیون تومان (پکیج پایه)"** در متن قرارداد حقوقی — اگه نقرهای بخره اشتباهه! | 🔴 حقوقی |
|
||||
| FO2 | `PackagePurchaseBottomSheet.razor` | **"خرید پکیج پایه ۵۶ میلیون تومان"** hardcoded | 🔴 |
|
||||
| FO3 | `ActivationSection.razor` | `56_000_000` hardcoded در محاسبه هزینه | 🔴 |
|
||||
| FO4 | `MagicWalletChargePage.razor` | "×۲.۵" و "سقف واریز: ۱۰۰ میلیون" hardcoded در ۶ جا | 🟡 |
|
||||
| FO5 | `MagicWalletChargePage.razor` L112 | `_chargeAmount * 2.5m` hardcoded در **C# code** | 🔴 |
|
||||
| FO6 | صفحات متعدد | **"پکیج طلایی"** hardcoded (حداقل ۵ جا) — نام اشتباه! | 🟡 |
|
||||
| FO7 | Activation flow | `PackageId = 1` hardcoded | 🔴 |
|
||||
| FO8 | `HasPurchasedPackage` claim | `bool` — UI نمیتونه multi-package نشون بده | 🟡 |
|
||||
| FO9 | Network tree | بدون نمایش پکیج هر نود | 🟢 |
|
||||
|
||||
---
|
||||
|
||||
### ۷٫۵٫۱۰ BackOffice — ۸ Side Effect
|
||||
|
||||
> 🟡 **بالا**
|
||||
|
||||
| # | فایل | مشکل | شدت |
|
||||
|---|------|------|------|
|
||||
| BO-S1 | `ManualActivationDialog.razor` | مبلغ `56_000_000` hardcoded + `Disabled` + **بدون package selector** | 🔴 |
|
||||
| BO-S2 | `SystemConfigurationPage.razor` | تنظیمات global — MaxWithdrawal, MaxTreeDepth, CommissionPercent باید per-package بشن | 🔴 |
|
||||
| BO-S3 | Commission Dashboard | یک Pool واحد نشون میده — بدون per-package | 🟡 |
|
||||
| BO-S4 | User detail page | `HasPurchasedGoldenPackage` boolean — نمیگه کدام پکیج | 🟡 |
|
||||
| BO-S5 | Package CRUD grid | فقط Title + Price — فیلدهای v3 ندارد | 🟡 |
|
||||
| BO-S6 | Club members grid | ستون PackageTitle ✅ اما فیلتر ❌ | 🟢 |
|
||||
| BO-S7 | CSV exports (۳ جا) | بدون ستون پکیج | 🟡 |
|
||||
| BO-S8 | Network tree viewer | بدون پکیج هر نود + `MaxNetworkDepth` global | 🟡 |
|
||||
|
||||
---
|
||||
|
||||
### ۷٫۵٫۱۱ خلاصه آماری Side Effectها
|
||||
|
||||
```
|
||||
═══════════════════════════════════════════════════════════════
|
||||
لایه 🔴 بحرانی 🟡 بالا/متوسط 🟢 کم جمع
|
||||
═══════════════════════════════════════════════════════════════
|
||||
CMS Domain ۲ ۱ ۰ ۳
|
||||
CMS Application ۶ ۴ ۰ ۱۰
|
||||
CMS Infrastructure ۱ ۳ ۰ ۴
|
||||
CMS Validators ۰ ۳ ۰ ۳
|
||||
FrontOffice ۵ ۳ ۱ ۹
|
||||
BackOffice ۲ ۵ ۱ ۸
|
||||
Notifications ۰ ۴ ۰ ۴
|
||||
Background Jobs ۰ ۳ ۰ ۳
|
||||
─────────────────────────────────────────────────────────────
|
||||
جمع کل ۱۶ ۲۶ ۲ ۴۴
|
||||
═══════════════════════════════════════════════════════════════
|
||||
```
|
||||
|
||||
> **مجموع سایدافکتهای کشفشده v4: ۴۴ مورد** (نسبت به ۴۸ تغییر اصلی v3)
|
||||
> **بیشتری تغییرات لازم از سایدافکتها ناشی میشوند!**
|
||||
|
||||
---
|
||||
|
||||
## ۸. Seed Data
|
||||
|
||||
```sql
|
||||
@@ -688,7 +910,9 @@ SELECT 'Balances', COUNT(*) FROM "CMS"."NetworkWeeklyBalances" WHERE "PackageId"
|
||||
|
||||
---
|
||||
|
||||
## ۱۰. Impact Analysis — ۴۸+ تغییر در ۶ لایه (v3)
|
||||
## ۱۱. Impact Analysis — ۹۰+ تغییر در ۶ لایه (v4)
|
||||
|
||||
> ۴۸ تغییر اصلی (بخش ۱۰) + ۴۴ سایدافکت (بخش ۷.۵) = **۹۲ تغییر کل**
|
||||
|
||||
### ۱۰.۱ لایه Domain (۱۰ تغییر)
|
||||
|
||||
@@ -704,6 +928,7 @@ SELECT 'Balances', COUNT(*) FROM "CMS"."NetworkWeeklyBalances" WHERE "PackageId"
|
||||
| D8 | EF Migration + Seed | schema + data migration | 🔴 | |
|
||||
| **D9** | **`NetworkWeeklyBalance.cs`** | **اضافه `PackageId` + Unique(UserId,WeekId,PackageId)** | **🔴** | **🆕** |
|
||||
| **D10** | **Data volume impact** | **رکوردهای تعادل ×N (تعداد پکیج)** | **🟡** | **🆕** |
|
||||
| **D11** | **`UserWalletChangeLog.cs`** | **اضافه `PackageId` — ۲۱ محل ساخت باید بروزرسانی شوند** | **🔴** | **🆕 v4** |
|
||||
|
||||
### ۱۰.۲ لایه Application (۱۲ تغییر)
|
||||
|
||||
@@ -721,6 +946,14 @@ SELECT 'Balances', COUNT(*) FROM "CMS"."NetworkWeeklyBalances" WHERE "PackageId"
|
||||
| A10 | `AcceptClubMembershipContractCommandHandler` | اجازه re-contract بعد چرخه | 🟡 |
|
||||
| A11 | `UserOrderService` (EXIT Magic) | ریست PackagePurchaseMethod + Deactivate | 🔴 |
|
||||
| A12 | Package CRUD handlers | فیلدهای جدید + PackageFeature CRUD | 🟡 |
|
||||
| **A13** | **`ChargeMagicWalletCommandHandler`** | **`MagicWalletMaxDeposit` از Package بخوند (نه global)** | **🔴 v4** |
|
||||
| **A14** | **`VerifyMagicWalletChargeCommandHandler`** | **`MagicWalletMultiplier` از Package بخوند (نه ×2.5 global)** | **🔴 v4** |
|
||||
| **A15** | **`UserOrderService.cs` EXIT/ENTRY** | **EXIT: سقف از Package + ENTRY: چک کدام پکیج** | **🔴 v4** |
|
||||
| **A16** | **Validators (۳ فایل)** | **`1_000_000_000` hardcoded → داینامیک per-package** | **🟡 v4** |
|
||||
| **A17** | **`GetAllFeatureIds()` (۲ handler)** | **همه فیچرها global → per-package از PackageFeature** | **🔴 v4** |
|
||||
| **A18** | **JWT Token Generation** | **اضافه PackageId + PackageTitle + CanRepurchase** | **🟡 v4** |
|
||||
| **A19** | **`WalletGrpcService.GetMagicWalletStatus`** | **سقف و باقیمانده per-package (نه global)** | **🟡 v4** |
|
||||
| **A20** | **Notifications (۴ مورد)** | **اضافه PackageId + PackageTitle به interface** | **🟡 v4** |
|
||||
|
||||
### ۱۰.۳ لایه Infrastructure (۶ تغییر)
|
||||
|
||||
@@ -756,6 +989,10 @@ SELECT 'Balances', COUNT(*) FROM "CMS"."NetworkWeeklyBalances" WHERE "PackageId"
|
||||
| F6 | `PackageService.cs` | فیکس stub GetPurchaseHistory | 🟡 | |
|
||||
| **F7** | **`CommissionDashboardPage.razor`** | **خلاصه پاداش per-package (کارتهای جداگانه هر پکیج)** | **🔴** | **🆕** |
|
||||
| **F8** | **`WeeklyBalancePage.razor`** | **تعادلها per-package (تیم اول/دوم بر اساس پکیج)** | **🟡** | **🆕** |
|
||||
| **F9** | **`ClubMembershipContractDialog.razor`** | **متن حقوقی "۵۶ میلیون تومان" — مسئولیت حقوقی!** | **🔴** | **🆕 v4** |
|
||||
| **F10** | **`MagicWalletChargePage.razor`** | **×۲.۵ و سقف واریز hardcoded در ۶ جا (متن + کد C#)** | **🔴** | **🆕 v4** |
|
||||
| **F11** | **صفحات متعدد** | **"پکیج طلایی" hardcoded (۵+ جا) — نام اشتباه** | **🟡** | **🆕 v4** |
|
||||
| **F12** | **Activation flow** | **`PackageId = 1` hardcoded** | **🔴** | **🆕 v4** |
|
||||
|
||||
### ۱۰.۶ لایه BackOffice (۸ تغییر)
|
||||
|
||||
@@ -769,6 +1006,9 @@ SELECT 'Balances', COUNT(*) FROM "CMS"."NetworkWeeklyBalances" WHERE "PackageId"
|
||||
| **BO6** | **`WeeklyReportsPage.razor`** | **فیلتر پکیج + CSV export per-package** | **🟡** | **🆕** |
|
||||
| **BO7** | **`BalancesReportPage.razor`** | **فیلتر پکیج + ستون پکیج در جدول تعادلها** | **🟡** | **🆕** |
|
||||
| **BO8** | **`UserPayoutsPage.razor`** | **ستون پکیج در لیست پرداختها + فیلتر** | **🟡** | **🆕** |
|
||||
| **BO9** | **`ManualActivationDialog.razor`** | **مبلغ ۵۶M hardcoded + Disabled + بدون package selector** | **🔴** | **🆕 v4** |
|
||||
| **BO10** | **`SystemConfigurationPage.razor`** | **تنظیمات global — باید per-package بشن** | **🔴** | **🆕 v4** |
|
||||
| **BO11** | **CSV exports (۳ جا)** | **بدون ستون پکیج** | **🟡** | **🆕 v4** |
|
||||
|
||||
---
|
||||
|
||||
@@ -799,21 +1039,28 @@ SELECT 'Balances', COUNT(*) FROM "CMS"."NetworkWeeklyBalances" WHERE "PackageId"
|
||||
| **T1.10** | بروزرسانی Protoها (package + clubmembership + commission) | 🔄 |
|
||||
| **T1.11** | **اضافه `PackageId` به `NetworkWeeklyBalance` + Unique(UserId,WeekId,PackageId)** | **🆕** |
|
||||
| **T1.12** | **Data Migration: `NetworkWeeklyBalance` موجود → PackageId = پکیج پایه** | **🆕** |
|
||||
| **T1.13** | **اضافه `PackageId` به `UserWalletChangeLog` + Migration داده** | **🆕 v4** |
|
||||
|
||||
### فاز ۲ — منطق کسبوکار ≈ ۴ روز
|
||||
### فاز ۲ — منطق کسبوکار ≈ ۵ روز (v4: +۱)
|
||||
|
||||
| تسک | شرح |
|
||||
|-----|------|
|
||||
| **T2.1** | ادغام Verify handlers → Generic (DiscountMultiplier + UserPackagePurchase) |
|
||||
| **T2.2** | ادغام Purchase handlers → Generic (حذف "طلایی"، حذف ID=4) |
|
||||
| **T2.3** | بروزرسانی `ActivateClubMembership` — فیچر از PackageFeature |
|
||||
| **T2.4** | بروزرسانی `ActivateClubMembership` — ActivationFee از Package |
|
||||
| **T2.5** | اجازه re-purchase در Guards (G1–G3) |
|
||||
| **T2.6** | ریست وضعیت در EXIT Magic Mode |
|
||||
| **T2.7** | اجازه re-contract (G5) + بروزرسانی JWT (G7) |
|
||||
| **T2.8** | بروزرسانی `CreateManualPayment` + `DayaLoan` |
|
||||
| **T2.9** | PackageFeature CRUD |
|
||||
| **T2.10** | Event: PackageCreated → ساخت Pool خالی |
|
||||
| تسک | شرح | v4? |
|
||||
|-----|----- |-----|
|
||||
| **T2.1** | ادغام Verify handlers → Generic (DiscountMultiplier + UserPackagePurchase) | |
|
||||
| **T2.2** | ادغام Purchase handlers → Generic (حذف "طلایی"، حذف ID=4) | |
|
||||
| **T2.3** | بروزرسانی `ActivateClubMembership` — فیچر از PackageFeature | |
|
||||
| **T2.4** | بروزرسانی `ActivateClubMembership` — ActivationFee از Package | |
|
||||
| **T2.5** | اجازه re-purchase در Guards (G1–G3) | |
|
||||
| **T2.6** | ریست وضعیت در EXIT Magic Mode | |
|
||||
| **T2.7** | اجازه re-contract (G5) + بروزرسانی JWT (G7) | |
|
||||
| **T2.8** | بروزرسانی `CreateManualPayment` + `DayaLoan` | |
|
||||
| **T2.9** | PackageFeature CRUD | |
|
||||
| **T2.10** | Event: PackageCreated → ساخت Pool خالی | |
|
||||
| **T2.11** | **Magic Wallet: `ChargeMagicWallet` + `VerifyMagicWalletCharge` + `UserOrderService` EXIT/ENTRY → خواندن سقف/ضریب از Package** | **🆕 v4** |
|
||||
| **T2.12** | **Validators (۳ فایل): حذف hardcoded 1B → داینامیک** | **🆕 v4** |
|
||||
| **T2.13** | **JWT Claims: اضافه PackageId + PackageTitle + CanRepurchase، حذف HasPurchasedGoldenPackage** | **🆕 v4** |
|
||||
| **T2.14** | **`WalletGrpcService.GetMagicWalletStatus`: سقف per-package** | **🆕 v4** |
|
||||
| **T2.15** | **Notifications (۴ مورد): اضافه PackageId به interface + پیام** | **🆕 v4** |
|
||||
| **T2.16** | **بروزرسانی ۲۱ محل ساخت WalletChangeLog با PackageId** | **🆕 v4** |
|
||||
|
||||
### فاز ۳ — محاسبه پورسانت ≈ ۴ روز (موازی با فاز ۲)
|
||||
|
||||
@@ -844,6 +1091,11 @@ SELECT 'Balances', COUNT(*) FROM "CMS"."NetworkWeeklyBalances" WHERE "PackageId"
|
||||
| **T4.11** | **BackOffice: Weekly Reports + CSV export — ستون پکیج + فیلتر** | **🆕** |
|
||||
| **T4.12** | **BackOffice: BalancesReport + UserPayouts — ستون پکیج + فیلتر** | **🆕** |
|
||||
| **T4.13** | **BackOffice: Package Create/Edit — Quick Access فیچرها (checkbox inline)** | **🆕** |
|
||||
| **T4.14** | **FrontOffice: MagicWalletChargePage — حذف ×۲.۵ و سقف hardcoded (۶ جا) → خواندن از API** | **🆕 v4** |
|
||||
| **T4.15** | **FrontOffice: حذف "پکیج طلایی" hardcoded (۵+ جا) + حذف PackageId=1** | **🆕 v4** |
|
||||
| **T4.16** | **FrontOffice: قرارداد حقوقی — مبلغ + نام پکیج داینامیک (مسئولیت حقوقی!)** | **🆕 v4** |
|
||||
| **T4.17** | **BackOffice: ManualActivationDialog — حذف 56M hardcoded + اضافه package selector** | **🆕 v4** |
|
||||
| **T4.18** | **BackOffice: SystemConfiguration — تفکیک تنظیمات global/per-package** | **🆕 v4** |
|
||||
|
||||
### فاز ۵ — تست و استقرار ≈ ۳ روز
|
||||
|
||||
@@ -856,11 +1108,15 @@ SELECT 'Balances', COUNT(*) FROM "CMS"."NetworkWeeklyBalances" WHERE "PackageId"
|
||||
| **T5.5** | **تست تعادل per-package: carryover مجزا، MaxBalancesPerLeg متفاوت** | **🆕** |
|
||||
| **T5.6** | **تست گزارش FO per-package: مشتری breakdown صحیح میبیند** | **🆕** |
|
||||
| **T5.7** | **تست گزارش BO per-package: فیلتر پکیج + CSV** | **🆕** |
|
||||
| **T5.8** | Deploy staging → production |
|
||||
| **T5.8** | **تست Magic Wallet: سقف متفاوت per-package (پایه=1B, نقرهای=100M) — EXIT صحیح** | **🆕 v4** |
|
||||
| **T5.9** | **تست ضریب جادویی: پکیج A ×2.5 vs پکیج B ×2.0 — اعتبار صحیح** | **🆕 v4** |
|
||||
| **T5.10** | **تست قرارداد حقوقی: مبلغ و نام پکیج صحیح در متن** | **🆕 v4** |
|
||||
| **T5.11** | **تست WalletChangeLog: رکوردها PackageId دارند** | **🆕 v4** |
|
||||
| **T5.12** | Deploy staging → production |
|
||||
|
||||
---
|
||||
|
||||
## ۱۲. ریسکها
|
||||
## ۱۲. ریسکها (v4)
|
||||
|
||||
| ریسک | احتمال | شدت | راهحل |
|
||||
|------|--------|-----|--------|
|
||||
@@ -869,20 +1125,24 @@ SELECT 'Balances', COUNT(*) FROM "CMS"."NetworkWeeklyBalances" WHERE "PackageId"
|
||||
| ادغام handlers → رگرسیون | متوسط | زیاد | E2E test |
|
||||
| خرید مجدد بدون تکمیل چرخه | کم | زیاد | Validation: چرخه قبلی MagicCompletedAt |
|
||||
| Proto breaking change | قطعی | کم | backward compatible fields |
|
||||
| **Magic Wallet EXIT اشتباه — کاربر گیر میافته** | **زیاد** | **بحرانی** | **اولویت P0 — سقف از Package خوانده شود** |
|
||||
| **قرارداد حقوقی با مبلغ اشتباه** | **زیاد** | **بحرانی** | **متن قرارداد داینامیک از Package** |
|
||||
| **۲۱ WalletChangeLog بدون ردیابی** | **قطعی** | **متوسط** | **اضافه PackageId به entity** |
|
||||
|
||||
---
|
||||
|
||||
## ۱۳. تخمین زمانی (v3)
|
||||
## ۱۳. تخمین زمانی (v4)
|
||||
|
||||
| فاز | مدت | وابستگی | v3 تغییر |
|
||||
| فاز | مدت | وابستگی | v4 تغییر |
|
||||
|-----|------|---------|----------|
|
||||
| فاز ۰ — فیکس باگها | ۱ روز | — | |
|
||||
| فاز ۱ — زیرساخت | ۴ روز | فاز ۰ | +۱ روز (NetworkWeeklyBalance + Unique) |
|
||||
| فاز ۲ — منطق | ۴ روز | فاز ۱ | |
|
||||
| فاز ۳ — پورسانت | **۴ روز** | فاز ۱ | **+۱ روز** (SP params + carryover per-package) |
|
||||
| فاز ۴ — UI | **۵ روز** | فاز ۲ | **+۱ روز** (FO/BO گزارش per-package) |
|
||||
| فاز ۵ — تست | **۳ روز** | فاز ۳, ۴ | **+۱ روز** (تست carryover + گزارش) |
|
||||
| **مجموع** | **~۲۱ روز** | | |
|
||||
| فاز ۱ — زیرساخت | **۵ روز** | فاز ۰ | +۱ (WalletChangeLog PackageId + ۲۱ محل) |
|
||||
| فاز ۲ — منطق | **۵ روز** | فاز ۱ | +۱ (Magic Wallet + Validators + JWT + Notifications) |
|
||||
| فاز ۳ — پورسانت | ۴ روز | فاز ۱ | |
|
||||
| فاز ۴ — UI | **۷ روز** | فاز ۲ | +۲ (Magic Wallet UI + قرارداد + ManualActivation + SystemConfig) |
|
||||
| فاز ۵ — تست | **۴ روز** | فاز ۳, ۴ | +۱ (تست Magic per-package + قرارداد + WalletLog) |
|
||||
| **مجموع** | **~۲۶ روز** | | |
|
||||
|
||||
> فاز ۲ و ۳ **موازی** → مسیر بحرانی: ۰→۱→۲→۴→۵ = **~۱۷ روز**
|
||||
> نسبت به v2 (**۱۴ روز**): +۳ روز بخاطر per-package commission + گزارشدهی + carryover
|
||||
> فاز ۲ و ۳ **موازی** → مسیر بحرانی: ۰→۱→۲→۴→۵ = **~۲۲ روز**
|
||||
> نسبت به v3 (**۱۷ روز**): **+۵ روز** بخاطر ۴۴ سایدافکت کشفشده
|
||||
> نسبت به v2 (**۱۴ روز**): **+۸ روز** — بزرگترین سهم: Magic Wallet + WalletChangeLog + قرارداد حقوقی
|
||||
|
||||
Reference in New Issue
Block a user