Compare commits
14 Commits
c78850f86e
...
df1affa46e
| Author | SHA1 | Date | |
|---|---|---|---|
| df1affa46e | |||
| 38aababc1a | |||
| e6d086b559 | |||
| a61a987b57 | |||
| d94b09878a | |||
| 0aa126af1c | |||
| 37330a3e45 | |||
| 977ef69e26 | |||
| 1885fcbd3b | |||
| 33d5ae9305 | |||
| 01244f426e | |||
| 3575e483b9 | |||
| 09b8b804d4 | |||
| dd5a2617cf |
@@ -0,0 +1,554 @@
|
||||
# 📦 سیستم مبتنی بر پکیج (Package-Based System)
|
||||
|
||||
> **وضعیت:** تحلیل و بررسی — منتظر تایید
|
||||
> **تاریخ:** اسفند ۱۴۰۴
|
||||
> **تاثیرگذاری:** زیاد — بخشهای متعدد سیستم تحت تاثیر قرار میگیرد
|
||||
|
||||
---
|
||||
|
||||
## ۱. خلاصه فیچر
|
||||
|
||||
**وضعیت فعلی:** سیستم فقط یک پکیج پایه (۵۶ میلیون تومان) دارد و همه چیز حول آن میچرخد.
|
||||
|
||||
**وضعیت هدف:** سیستم چندین پکیج با قیمتها و ویژگیهای متفاوت پشتیبانی میکند. هر پکیج روشهای پرداخت، محاسبه پورسانت، شارژ کیف پول و فیچرهای مختص خود را دارد.
|
||||
|
||||
```
|
||||
مثال پکیجها:
|
||||
┌──────────────┬──────────────┬──────────────┬──────────────┐
|
||||
│ 🥈 نقرهای │ 🥇 طلایی │ 💎 الماسی │ ⭐ ویژه │
|
||||
│ ۵.۶M تومان │ ۵۶M تومان │ ؟؟ تومان │ ؟؟ تومان │
|
||||
│ │ (پکیج پایه) │ │ │
|
||||
│ فقط مستقیم │ دایا+مستقیم │ فقط مستقیم │ فقط مستقیم │
|
||||
│ فیچر محدود │ همه فیچرها │ همه فیچرها │ همه+اختصاصی │
|
||||
└──────────────┴──────────────┴──────────────┴──────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۲. وضعیت فعلی سیستم (AS-IS)
|
||||
|
||||
### ۲.۱ فلوی فعلی فعالسازی
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["کاربر وارد سیستم میشود"] --> B{"روش پرداخت"}
|
||||
B -->|"خرید الماس دایا"| C["DayaLoan — ۵۶M"]
|
||||
B -->|"پرداخت مستقیم"| D["درگاه بانکی — ۵۶M"]
|
||||
C --> E["بررسی موفقیت پرداخت"]
|
||||
D --> E
|
||||
E --> F["شارژ کیف پول"]
|
||||
F --> G["مدال قرارداد باشگاه مشتریان"]
|
||||
G --> H["تایید OTP + امضا"]
|
||||
H --> I["فعالسازی عضویت باشگاه"]
|
||||
I --> J["اختصاص فیچرها"]
|
||||
I --> K["ایجاد Cycle"]
|
||||
I --> L["اضافه به Commission Pool"]
|
||||
J --> M["✅ کاربر فعال — لینک معرف"]
|
||||
```
|
||||
|
||||
### ۲.۲ جریان پول فعلی
|
||||
|
||||
```
|
||||
کاربر ۵۶M پرداخت میکند
|
||||
│
|
||||
├── Balance (کیف پول عادی) += ۵۶,۰۰۰,۰۰۰ ریال
|
||||
├── DiscountBalance (اعتباری) += ۱۱۲,۰۰۰,۰۰۰ ریال (×۲)
|
||||
│
|
||||
└── Club Activation:
|
||||
├── CommissionPool += ۲۵,۲۰۰,۰۰۰ ریال (ClubActivationFee)
|
||||
└── GiftValue = ۲۵,۲۰۰,۰۰۰ ریال (اطلاعرسانی)
|
||||
```
|
||||
|
||||
### ۲.۳ مقادیر Hardcoded فعلی (`SystemConstants.cs`)
|
||||
|
||||
| ثابت | مقدار | کاربرد |
|
||||
|------|-------|--------|
|
||||
| `BasePackageAmount` | ۵۶,۰۰۰,۰۰۰ | قیمت پکیج |
|
||||
| `DayaLoanAmount` | ۵۶,۰۰۰,۰۰۰ | مبلغ وام دایا |
|
||||
| `ClubActivationFee` | ۲۵,۲۰۰,۰۰۰ | سهم هفتگی Commission Pool |
|
||||
| `ClubMembershipGiftValue` | ۲۵,۲۰۰,۰۰۰ | ارزش هدیه حق عضویت |
|
||||
| `MagicWalletMultiplier` | ×۲.۵ | ضریب کیف پول جادویی |
|
||||
|
||||
### ۲.۴ مشکلات فعلی
|
||||
|
||||
| # | مشکل | فایل |
|
||||
|---|------|------|
|
||||
| ۱ | پکیج ID=4 **hardcoded** در `InitiateBasePackagePaymentCommandHandler` | Application/Commands |
|
||||
| ۲ | مبلغ ۵۶M **hardcoded** در `SystemConstants` و چندین handler | Domain/Common |
|
||||
| ۳ | فیچرها **همه یکجا** assign میشن (۴ فیچر ثابت: چتیکا، بیمه، تریپ، لرن) | ActivateClubMembershipHandler |
|
||||
| ۴ | Commission Pool فقط با `ClubActivationFee` ثابت پر میشه | ActivateClubMembershipHandler |
|
||||
| ۵ | `DiscountBalance = Amount × 2` — ضریب hardcoded | VerifyPayment handlers |
|
||||
| ۶ | فرانتاند فقط یک مسیر خرید نشون میده | FrontOffice pages |
|
||||
|
||||
---
|
||||
|
||||
## ۳. طراحی پیشنهادی (TO-BE)
|
||||
|
||||
### ۳.۱ فلوی جدید فعالسازی
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["کاربر وارد سیستم"] --> B["صفحه پکیجها<br/>(کاشیهای نقرهای/طلایی/الماسی/...)"]
|
||||
|
||||
B -->|"کلیک روی پکیج"| C{"نوع پکیج"}
|
||||
|
||||
C -->|"پکیج پایه (طلایی)"| D["مدال با دو گزینه:<br/>۱. خرید الماس دایا<br/>۲. پرداخت مستقیم"]
|
||||
C -->|"پکیجهای دیگر"| E["مدال با یک گزینه:<br/>فقط پرداخت مستقیم<br/>+ توضیحات + قیمت"]
|
||||
|
||||
D -->|"دایا"| F["فلوی دایا"]
|
||||
D -->|"مستقیم"| G["درگاه پرداخت"]
|
||||
E --> G
|
||||
|
||||
F --> H["پرداخت موفق"]
|
||||
G --> H
|
||||
|
||||
H --> I["شارژ کیف پول<br/>(متناسب با قیمت پکیج)"]
|
||||
I --> J["مدال قرارداد باشگاه"]
|
||||
J --> K["OTP + امضا"]
|
||||
K --> L["فعالسازی<br/>+ اختصاص فیچرهای پکیج"]
|
||||
L --> M["✅ کاربر فعال"]
|
||||
```
|
||||
|
||||
### ۳.۲ تغییرات Entity — Package
|
||||
|
||||
**فعلی:**
|
||||
```csharp
|
||||
public class Package : BaseAuditableEntity
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string ImagePath { get; set; }
|
||||
public long Price { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
**پیشنهادی:**
|
||||
```csharp
|
||||
public class Package : BaseAuditableEntity
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string ImagePath { get; set; }
|
||||
public long Price { get; set; } // قیمت پکیج (ریال)
|
||||
|
||||
// === فیلدهای جدید ===
|
||||
public int SortOrder { get; set; } // ترتیب نمایش
|
||||
public bool IsActive { get; set; } = true; // فعال/غیرفعال
|
||||
public bool IsBasePackage { get; set; } // آیا پکیج پایه است؟
|
||||
public bool SupportsDayaPurchase { get; set; } // پشتیبانی از خرید دایا
|
||||
public bool SupportsDirectPurchase { get; set; } = true; // پشتیبانی از پرداخت مستقیم
|
||||
|
||||
// === محاسبات مالی ===
|
||||
public long ActivationFee { get; set; } // سهم Commission Pool
|
||||
public long GiftValue { get; set; } // ارزش هدیه
|
||||
public decimal DiscountMultiplier { get; set; } = 2.0m; // ضریب شارژ DiscountBalance
|
||||
|
||||
// === Navigation ===
|
||||
public virtual ICollection<PackageFeature> PackageFeatures { get; set; }
|
||||
public virtual ICollection<UserPackagePurchase> Purchases { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
### ۳.۳ Entity جدید — PackageFeature (پل بین پکیج و فیچر)
|
||||
|
||||
```csharp
|
||||
/// <summary>
|
||||
/// مشخص میکند هر پکیج چه فیچرهایی را فعال میکند
|
||||
/// </summary>
|
||||
public class PackageFeature : BaseAuditableEntity
|
||||
{
|
||||
public long PackageId { get; set; }
|
||||
public virtual Package Package { get; set; }
|
||||
|
||||
public long ClubFeatureId { get; set; }
|
||||
public virtual ClubFeature ClubFeature { get; set; }
|
||||
|
||||
public bool IsIncluded { get; set; } = true; // آیا این فیچر در پکیج هست؟
|
||||
}
|
||||
```
|
||||
|
||||
### ۳.۴ تغییرات Entity — ClubMembership
|
||||
|
||||
```csharp
|
||||
public class ClubMembership : BaseAuditableEntity
|
||||
{
|
||||
// ... فیلدهای فعلی حفظ میشوند ...
|
||||
|
||||
// === فیلد جدید ===
|
||||
public long PackageId { get; set; } // کدام پکیج خریداری شده
|
||||
public virtual Package Package { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
### ۳.۵ تغییرات Entity — ClubMembershipCycle
|
||||
|
||||
```csharp
|
||||
public class ClubMembershipCycle : BaseAuditableEntity
|
||||
{
|
||||
// ... فیلدهای فعلی حفظ میشوند ...
|
||||
|
||||
// === فیلد جدید ===
|
||||
public long PackageId { get; set; } // پکیج این سایکل
|
||||
public virtual Package Package { get; set; }
|
||||
// PackageAmount قبلاً وجود دارد — از Package.Price پر میشود
|
||||
}
|
||||
```
|
||||
|
||||
### ۳.۶ تغییرات Entity — WeeklyCommissionPool
|
||||
|
||||
```csharp
|
||||
public class WeeklyCommissionPool : BaseAuditableEntity
|
||||
{
|
||||
// ... فیلدهای فعلی حفظ میشوند ...
|
||||
|
||||
// === فیلد جدید ===
|
||||
public long PackageId { get; set; } // Pool جداگانه برای هر پکیج
|
||||
public virtual Package Package { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
### ۳.۷ جریان پول جدید
|
||||
|
||||
```
|
||||
پکیج نقرهای (۵.۶M):
|
||||
├── Balance += ۵,۶۰۰,۰۰۰
|
||||
├── DiscountBalance += ۱۱,۲۰۰,۰۰۰ (×۲)
|
||||
└── CommissionPool += ActivationFee مخصوص نقرهای
|
||||
|
||||
پکیج طلایی/پایه (۵۶M):
|
||||
├── Balance += ۵۶,۰۰۰,۰۰۰
|
||||
├── DiscountBalance += ۱۱۲,۰۰۰,۰۰۰ (×۲)
|
||||
└── CommissionPool += ۲۵,۲۰۰,۰۰۰
|
||||
|
||||
پکیج الماسی (??M):
|
||||
├── Balance += ??
|
||||
├── DiscountBalance += ?? (×۲)
|
||||
└── CommissionPool += ActivationFee مخصوص الماسی
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۴. محاسبه پورسانت — تغییرات
|
||||
|
||||
### ۴.۱ وضعیت فعلی
|
||||
|
||||
```
|
||||
یک WeeklyCommissionPool برای کل هفته
|
||||
↓
|
||||
TotalAmount = مجموع ActivationFee همه فعالسازیها
|
||||
↓
|
||||
ValuePerBalance = TotalAmount ÷ مجموع Balanceها
|
||||
↓
|
||||
همه یکسان محاسبه میشوند
|
||||
```
|
||||
|
||||
### ۴.۲ وضعیت هدف
|
||||
|
||||
```
|
||||
برای هر پکیج، یک WeeklyCommissionPool جداگانه:
|
||||
|
||||
Pool_نقرهای:
|
||||
TotalAmount = مجموع ActivationFee خریداران نقرهای این هفته
|
||||
Balanceها = فقط از شبکه خریداران نقرهای
|
||||
ValuePerBalance = Pool_نقرهای ÷ Balance_نقرهای
|
||||
|
||||
Pool_طلایی:
|
||||
TotalAmount = مجموع ActivationFee خریداران طلایی این هفته
|
||||
Balanceها = فقط از شبکه خریداران طلایی
|
||||
ValuePerBalance = Pool_طلایی ÷ Balance_طلایی
|
||||
```
|
||||
|
||||
### ۴.۳ نکته مهم: ساختار شبکه یکی است
|
||||
|
||||
```
|
||||
[Ali]
|
||||
/ \
|
||||
[Sara] [Reza] ← شبکه باینری یکیست
|
||||
/ \ / \
|
||||
[M1] [M2] [M3] [M4]
|
||||
|
||||
ولی محاسبات جدا:
|
||||
- Ali با پکیج طلایی → پورسانت از Pool طلایی
|
||||
- Sara با پکیج نقرهای → پورسانت از Pool نقرهای
|
||||
- Reza با پکیج طلایی → پورسانت از Pool طلایی
|
||||
```
|
||||
|
||||
### ۴.۴ تغییرات Stored Procedure
|
||||
|
||||
**`sp_CalculateWeeklyBalances`** باید:
|
||||
- پارامتر `@PackageId` بگیرد
|
||||
- فقط کاربرانی که این پکیج را خریدهاند فیلتر کند
|
||||
- برای هر پکیج جداگانه اجرا شود
|
||||
|
||||
**`sp_CalculateWeeklyCommissionPool`** باید:
|
||||
- پارامتر `@PackageId` بگیرد
|
||||
- Pool مخصوص آن پکیج را بخواند
|
||||
- پرداختها فقط به خریداران آن پکیج اختصاص یابد
|
||||
|
||||
---
|
||||
|
||||
## ۵. فیچرهای باشگاه مشتریان بر اساس پکیج
|
||||
|
||||
### ۵.۱ وضعیت فعلی
|
||||
|
||||
وقتی کاربر فعال میشود، **همه ۴ فیچر** یکجا assign میشوند:
|
||||
```csharp
|
||||
// ActivateClubMembershipCommandHandler — خط ~350
|
||||
var allFeatureIds = ClubFeatureTypeExtensions.GetAllFeatureIds();
|
||||
foreach (var featureId in allFeatureIds)
|
||||
{
|
||||
userClubFeatures.Add(new UserClubFeature { ... });
|
||||
}
|
||||
```
|
||||
|
||||
### ۵.۲ وضعیت هدف
|
||||
|
||||
فیچرها بر اساس جدول `PackageFeature` تعیین میشوند:
|
||||
|
||||
| فیچر | نقرهای | طلایی (پایه) | الماسی |
|
||||
|------|---------|-------------|--------|
|
||||
| چتیکا | ❌ | ✅ | ✅ |
|
||||
| بیمه | ❌ | ✅ | ✅ |
|
||||
| تریپ | ✅ | ✅ | ✅ |
|
||||
| لرن | ✅ | ✅ | ✅ |
|
||||
| فیچر VIP | ❌ | ❌ | ✅ |
|
||||
|
||||
*مقادیر بالا نمونهای هستند — قابل تنظیم از BackOffice*
|
||||
|
||||
### ۵.۳ تغییر در ActivateClubMembershipHandler
|
||||
|
||||
```
|
||||
قبلی:
|
||||
GetAllFeatureIds() → assign all
|
||||
|
||||
جدید:
|
||||
Package.PackageFeatures
|
||||
.Where(pf => pf.IsIncluded)
|
||||
.Select(pf => pf.ClubFeatureId)
|
||||
→ assign only included features
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۶. تغییرات UI — FrontOffice
|
||||
|
||||
### ۶.۱ صفحه پکیجها (کاشیها)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ انتخاب پکیج باشگاه مشتریان │
|
||||
├─────────────┬──────────────┬──────────────┬─────────┤
|
||||
│ │ │ │ │
|
||||
│ 🥈 نقرهای │ 🥇 طلایی │ 💎 الماسی │ ⭐ ویژه │
|
||||
│ ۵.۶M │ ۵۶M │ ؟؟M │ ؟؟M │
|
||||
│ │ │ │ │
|
||||
│ ● لرن │ ● چتیکا │ ● همه │ ● همه │
|
||||
│ ● تریپ │ ● بیمه │ ● + VIP │ ● +... │
|
||||
│ │ ● تریپ │ │ │
|
||||
│ │ ● لرن │ │ │
|
||||
│ │ │ │ │
|
||||
│ [انتخاب] │ [انتخاب] │ [انتخاب] │[انتخاب]│
|
||||
└─────────────┴──────────────┴──────────────┴─────────┘
|
||||
```
|
||||
|
||||
### ۶.۲ مدال پرداخت — پکیج پایه (طلایی)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ خرید پکیج طلایی — ۵۶M تومان │
|
||||
│ │
|
||||
│ توضیحات: ... │
|
||||
│ │
|
||||
│ روشهای پرداخت: │
|
||||
│ ┌─────────────────────────────────┐ │
|
||||
│ │ 💎 خرید از طریق الماس دایا │ │
|
||||
│ └─────────────────────────────────┘ │
|
||||
│ ┌─────────────────────────────────┐ │
|
||||
│ │ 💳 پرداخت مستقیم (درگاه بانکی) │ │
|
||||
│ └─────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### ۶.۳ مدال پرداخت — پکیجهای دیگر (نقرهای و بالاتر)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ خرید پکیج نقرهای — ۵.۶M تومان │
|
||||
│ │
|
||||
│ توضیحات: ... │
|
||||
│ ویژگیها: لرن، تریپ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────┐ │
|
||||
│ │ 💳 پرداخت و فعالسازی │ │
|
||||
│ └─────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۷. بخشهای تحت تاثیر (Impact Analysis)
|
||||
|
||||
### ۷.۱ جدول تاثیرپذیری
|
||||
|
||||
| # | لایه | فایل/بخش | نوع تغییر | شدت |
|
||||
|---|------|----------|-----------|-----|
|
||||
| ۱ | **Domain** | `Package.cs` | اضافه فیلد | 🟡 متوسط |
|
||||
| ۲ | **Domain** | `PackageFeature.cs` — **جدید** | Entity جدید | 🔴 زیاد |
|
||||
| ۳ | **Domain** | `ClubMembership.cs` | اضافه `PackageId` | 🟡 متوسط |
|
||||
| ۴ | **Domain** | `ClubMembershipCycle.cs` | اضافه `PackageId` | 🟡 متوسط |
|
||||
| ۵ | **Domain** | `WeeklyCommissionPool.cs` | اضافه `PackageId` | 🔴 زیاد |
|
||||
| ۶ | **Domain** | `SystemConstants.cs` | حذف hardcodeها → خوانش از Package | 🟡 متوسط |
|
||||
| ۷ | **Application** | `ActivateClubMembershipCommandHandler` | فیچر بر اساس پکیج | 🔴 زیاد |
|
||||
| ۸ | **Application** | `InitiateBasePackagePaymentCommandHandler` | حذف ID=4 hardcoded | 🟡 متوسط |
|
||||
| ۹ | **Application** | `VerifyBasePackagePaymentCommandHandler` | شارژ متناسب با پکیج | 🔴 زیاد |
|
||||
| ۱۰ | **Application** | `VerifyPackagePurchasePaymentCommandHandler` | شارژ متناسب با پکیج | 🔴 زیاد |
|
||||
| ۱۱ | **Application** | `ManualPaymentCommandHandler` | شارژ متناسب با پکیج | 🟡 متوسط |
|
||||
| ۱۲ | **Application** | `CustomerPurchasePackageCommandHandler` | پشتیبانی روشهای پرداخت پکیج | 🟡 متوسط |
|
||||
| ۱۳ | **Infra** | `sp_CalculateWeeklyBalances` | پارامتر PackageId | 🔴 زیاد |
|
||||
| ۱۴ | **Infra** | `sp_CalculateWeeklyCommissionPool` | Pool جداگانه هر پکیج | 🔴 زیاد |
|
||||
| ۱۵ | **Infra** | `WeeklyCommissionCalculationService` | Loop روی پکیجها | 🟡 متوسط |
|
||||
| ۱۶ | **Infra** | EF Configurations | جدول جدید + FKها | 🟡 متوسط |
|
||||
| ۱۷ | **Infra** | Database Migration | schema changes | 🟡 متوسط |
|
||||
| ۱۸ | **Proto** | `package.proto` | فیلدهای جدید پکیج | 🟢 کم |
|
||||
| ۱۹ | **Proto** | `clubmembership.proto` | PackageId در response | 🟢 کم |
|
||||
| ۲۰ | **Proto** | `commission.proto` | PackageId در pool/payout | 🟢 کم |
|
||||
| ۲۱ | **FrontOffice** | صفحه انتخاب پکیج | UI جدید (کاشیها) | 🔴 زیاد |
|
||||
| ۲۲ | **FrontOffice** | مدال پرداخت | دو مدال متفاوت | 🔴 زیاد |
|
||||
| ۲۳ | **FrontOffice** | `MyPackages.razor` | نمایش نوع پکیج | 🟡 متوسط |
|
||||
| ۲۴ | **FrontOffice** | `ActivateClubDialog.razor` | ارتباط با پکیج | 🟡 متوسط |
|
||||
| ۲۵ | **BackOffice** | صفحه مدیریت پکیجها | CRUD فیلدهای جدید | 🟡 متوسط |
|
||||
| ۲۶ | **BackOffice** | صفحه فیچر پکیجها — **جدید** | ماتریس پکیج×فیچر | 🔴 زیاد |
|
||||
| ۲۷ | **BackOffice** | `ActivateClubDialog.razor` | انتخاب پکیج | 🟡 متوسط |
|
||||
|
||||
### ۷.۲ ریسکها
|
||||
|
||||
| ریسک | احتمال | شدت | راهحل |
|
||||
|------|--------|-----|--------|
|
||||
| دادههای فعلی — کاربران بدون PackageId | قطعی | زیاد | Migration: کاربران فعلی → PackageId = پکیج پایه |
|
||||
| Commission Pool فعلی بدون PackageId | قطعی | زیاد | Migration: Poolهای موجود → PackageId = پکیج پایه |
|
||||
| SP تغییر → محاسبات اشتباه | متوسط | بحرانی | تست جامع + محیط staging |
|
||||
| مبالغ hardcoded در جاهای پراکنده | زیاد | متوسط | Audit کامل کدبیس |
|
||||
| عدم سازگاری FrontOffice/BackOffice | متوسط | متوسط | تست end-to-end |
|
||||
|
||||
---
|
||||
|
||||
## ۸. فازبندی پیادهسازی
|
||||
|
||||
### فاز ۱ — زیرساخت (Domain + DB) ≈ ۳-۴ روز
|
||||
|
||||
| تسک | شرح |
|
||||
|-----|------|
|
||||
| T1.1 | بروزرسانی `Package` entity (فیلدهای جدید) |
|
||||
| T1.2 | ایجاد `PackageFeature` entity + EF Configuration |
|
||||
| T1.3 | اضافه کردن `PackageId` به `ClubMembership` |
|
||||
| T1.4 | اضافه کردن `PackageId` به `ClubMembershipCycle` |
|
||||
| T1.5 | اضافه کردن `PackageId` به `WeeklyCommissionPool` |
|
||||
| T1.6 | Database Migration + Seed data (پکیج پایه + فیچرها) |
|
||||
| T1.7 | Migration: کاربران/Poolهای فعلی → PackageId = پکیج پایه |
|
||||
| T1.8 | بروزرسانی Protoها |
|
||||
|
||||
### فاز ۲ — منطق کسبوکار (Application) ≈ ۴-۵ روز
|
||||
|
||||
| تسک | شرح |
|
||||
|-----|------|
|
||||
| T2.1 | بروزرسانی `ActivateClubMembershipCommandHandler` — فیچر بر اساس پکیج |
|
||||
| T2.2 | بروزرسانی Verify handlers — شارژ کیف پول متناسب با پکیج |
|
||||
| T2.3 | حذف مقادیر hardcoded از `SystemConstants` → خوانش از Package |
|
||||
| T2.4 | بروزرسانی `InitiateBasePackagePayment` → Generic `InitiatePackagePayment` |
|
||||
| T2.5 | بروزرسانی `ManualPaymentCommandHandler` — پشتیبانی پکیج متغیر |
|
||||
| T2.6 | CRUD پکیج با فیلدهای جدید (gRPC handlers) |
|
||||
| T2.7 | CRUD `PackageFeature` (ماتریس پکیج×فیچر) |
|
||||
|
||||
### فاز ۳ — محاسبه پورسانت ≈ ۳-۴ روز
|
||||
|
||||
| تسک | شرح |
|
||||
|-----|------|
|
||||
| T3.1 | بروزرسانی `sp_CalculateWeeklyBalances` — فیلتر بر اساس PackageId |
|
||||
| T3.2 | بروزرسانی `sp_CalculateWeeklyCommissionPool` — Pool جداگانه |
|
||||
| T3.3 | بروزرسانی `WeeklyCommissionCalculationService` — Loop روی پکیجها |
|
||||
| T3.4 | تست محاسبات با داده واقعی |
|
||||
|
||||
### فاز ۴ — UI (FrontOffice + BackOffice) ≈ ۴-۵ روز
|
||||
|
||||
| تسک | شرح |
|
||||
|-----|------|
|
||||
| T4.1 | صفحه کاشیهای پکیج (FrontOffice) |
|
||||
| T4.2 | مدال پرداخت پکیج پایه (دایا + مستقیم) |
|
||||
| T4.3 | مدال پرداخت پکیجهای دیگر (فقط مستقیم) |
|
||||
| T4.4 | بروزرسانی `MyPackages.razor` — نمایش نوع پکیج |
|
||||
| T4.5 | بروزرسانی `ActivateClubDialog.razor` — ارتباط با پکیج |
|
||||
| T4.6 | BackOffice: CRUD پکیج با فیلدهای جدید |
|
||||
| T4.7 | BackOffice: صفحه ماتریس فیچرهای پکیج |
|
||||
| T4.8 | BackOffice: `ActivateClubDialog` — انتخاب پکیج |
|
||||
|
||||
### فاز ۵ — تست و استقرار ≈ ۲-۳ روز
|
||||
|
||||
| تسک | شرح |
|
||||
|-----|------|
|
||||
| T5.1 | تست end-to-end فلوی خرید هر پکیج |
|
||||
| T5.2 | تست محاسبه پورسانت جداگانه |
|
||||
| T5.3 | تست migration دادههای فعلی |
|
||||
| T5.4 | Deploy به staging + تست |
|
||||
| T5.5 | Deploy به production |
|
||||
|
||||
---
|
||||
|
||||
## ۹. Seed Data — پکیجهای اولیه
|
||||
|
||||
```sql
|
||||
-- Migration: Seed packages
|
||||
INSERT INTO Packages (Title, Description, Price, IsActive, IsBasePackage,
|
||||
SupportsDayaPurchase, SupportsDirectPurchase, ActivationFee, GiftValue,
|
||||
DiscountMultiplier, SortOrder)
|
||||
VALUES
|
||||
('نقرهای', 'پکیج نقرهای باشگاه مشتریان', 5600000, 1, 0,
|
||||
0, 1, ???, ???, 2.0, 1),
|
||||
('طلایی', 'پکیج طلایی باشگاه مشتریان (پایه)', 56000000, 1, 1,
|
||||
1, 1, 25200000, 25200000, 2.0, 2);
|
||||
|
||||
-- Migration: ربط فیچرها به پکیجها
|
||||
INSERT INTO PackageFeatures (PackageId, ClubFeatureId, IsIncluded) VALUES
|
||||
-- نقرهای: فقط تریپ و لرن
|
||||
(@silverId, @tripId, 1),
|
||||
(@silverId, @learnId, 1),
|
||||
-- طلایی: همه فیچرها
|
||||
(@goldId, @chatikaId, 1),
|
||||
(@goldId, @bimeId, 1),
|
||||
(@goldId, @tripId, 1),
|
||||
(@goldId, @learnId, 1);
|
||||
|
||||
-- Migration: کاربران فعلی → پکیج پایه
|
||||
UPDATE ClubMemberships SET PackageId = @goldId WHERE PackageId IS NULL;
|
||||
UPDATE ClubMembershipCycles SET PackageId = @goldId WHERE PackageId IS NULL;
|
||||
UPDATE WeeklyCommissionPools SET PackageId = @goldId WHERE PackageId IS NULL;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۱۰. سوالات باز (نیاز به تصمیمگیری)
|
||||
|
||||
| # | سوال | گزینهها |
|
||||
|---|------|---------|
|
||||
| ۱ | `ActivationFee` و `GiftValue` پکیج نقرهای چقدر باشد؟ | نسبت به قیمت؟ مقدار ثابت؟ |
|
||||
| ۲ | آیا کاربر میتواند بعداً پکیج خود را ارتقا دهد (upgrade)؟ | بله → فقط مابهالتفاوت / خیر |
|
||||
| ۳ | `DiscountMultiplier` برای همه پکیجها ×۲ باشد؟ | یکسان / متفاوت به ازای هر پکیج |
|
||||
| ۴ | ضریب `MagicWallet` (×۲.۵) برای پکیجهای کوچکتر هم همان باشد؟ | بله / خیر |
|
||||
| ۵ | فیچرهای پکیج نقرهای دقیقاً کدامها هستند؟ | لرن+تریپ؟ فقط لرن؟ |
|
||||
| ۶ | آیا یک کاربر میتواند چند پکیج همزمان داشته باشد؟ | فقط یکی / امکان خرید چندتا |
|
||||
| ۷ | نام و تعداد دقیق پکیجها چیست؟ | نقرهای+طلایی؟ بیشتر؟ |
|
||||
| ۸ | کاربرانی که با دایا فعال شدن، چه پکیجی دارند؟ | طلایی (پایه) |
|
||||
|
||||
---
|
||||
|
||||
## ۱۱. تخمین زمانی
|
||||
|
||||
| فاز | مدت | وابستگی |
|
||||
|-----|------|---------|
|
||||
| فاز ۱ — زیرساخت | ۳-۴ روز | — |
|
||||
| فاز ۲ — منطق | ۴-۵ روز | فاز ۱ |
|
||||
| فاز ۳ — پورسانت | ۳-۴ روز | فاز ۱ |
|
||||
| فاز ۴ — UI | ۴-۵ روز | فاز ۲ |
|
||||
| فاز ۵ — تست | ۲-۳ روز | فاز ۳, ۴ |
|
||||
| **مجموع** | **~۱۶-۲۱ روز کاری** | |
|
||||
|
||||
> فازهای ۲ و ۳ قابل موازیسازی هستند.
|
||||
+1343
-429
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,219 @@
|
||||
# آدیت سرویسهای gRPC — CMS
|
||||
|
||||
> تاریخ: ۱۴۰۴/۰۴
|
||||
> آخرین بروزرسانی: ۱۴۰۴/۱۲/۰۶
|
||||
> هدف: شناسایی RPCهایی که از هیچکدام از فرانتها (FrontOffice مشتری + BackOffice ادمین) فراخوانی نمیشوند + تصمیمگیری نگهداری vs آرشیو
|
||||
|
||||
---
|
||||
|
||||
## 📊 خلاصه آمار
|
||||
|
||||
| متریک | تعداد |
|
||||
|--------|-------|
|
||||
| کل فایلهای proto | 43 (بدون google/) |
|
||||
| کل سرویسهای gRPC | 42 |
|
||||
| **کل RPC متدها** | **342** |
|
||||
| استفادهشده در FrontOffice | 92 |
|
||||
| استفادهشده در BackOffice | 159 |
|
||||
| **استفادهشده (مجموع یکتا)** | **217** |
|
||||
| **استفادهنشده از فرانتها** | **125** |
|
||||
| ↳ استفادهشده داخلی CMS | 101 |
|
||||
| ↳ **کد مُرده واقعی** | **24** |
|
||||
|
||||
---
|
||||
|
||||
## 🔴 بخش ۱ — تحلیل ۲۴ RPC مُرده: نگهداری vs آرشیو
|
||||
|
||||
### ✅ نگهداری (آیندهنگرانه — ۱۲ عدد)
|
||||
|
||||
> این RPCها پیادهسازی کامل دارند و در نقشهراه آینده محصول کاربرد دارند.
|
||||
|
||||
| # | RPC | فایل Proto | کیفیت کد | دلیل نگهداری |
|
||||
|---|-----|-----------|---------|-------------|
|
||||
| 1 | `CustomerReorderPreviousOrder` | userorder.proto | ✅ **کامل** — آیتمهای سفارش قبلی به سبد اضافه میشود | UX حیاتی: «تکرار سفارش قبلی» — فیچر رایج فروشگاهی، فقط نیاز به دکمه در FrontOffice |
|
||||
| 2 | `CustomerTrackOrder` | userorder.proto | ✅ **کامل** — وضعیت + TrackingCode + DeliveryInfo | UX حیاتی: «ردیابی سفارش» — وقتی ارسال پستی فعال شود ضروری است |
|
||||
| 3 | `CalculateOrderPV` | userorder.proto | ✅ **کامل** — PV هر آیتم + جمع کل | سیستم MLM: محاسبه PV (Point Value) سفارش — برای فاز بعدی کمیسیون بر اساس خرید |
|
||||
| 4 | `GetInventorySummary` | inventory.proto | ✅ **کامل** — آمار تعداد + ارزش کل | داشبورد ادمین: خلاصه موجودی انبار — نیاز به کارت در BackOffice Dashboard |
|
||||
| 5 | `GetStockValueReport` | inventory.proto | ✅ **کامل** — گزارش ارزش ریالی موجودی | گزارش مالی: ارزش دارایی انبار — برای حسابداری ضروری |
|
||||
| 6 | `BulkAddStock` | inventory.proto | ✅ **کامل** — loop با error handling | عملیات انبوه: افزودن موجودی دستهای — بعد از ورود کالای فیزیکی |
|
||||
| 7 | `BulkUpdateProductStock` | products.proto | ✅ **کامل** — Set/Add/Subtract با error handling | عملیات انبوه: بروزرسانی دستهای موجودی محصول |
|
||||
| 8 | `GetConfigurationByKey` | configuration.proto | ✅ **کامل** — خواندن از SystemConstants | API مفید: دریافت یک تنظیم خاص بدون بارگذاری همه — performance بهتر |
|
||||
| 9 | `UpdateCustomerSettings` | user.proto | ✅ **کامل** — Email/SMS/Push notifications | تنظیمات اعلانها: وقتی پنل تنظیمات مشتری ساخته شود |
|
||||
| 10 | `ChangeNetworkParent` | networkmembership.proto | ✅ **CQRS کامل** → MoveInNetworkCommand | مدیریت شبکه: جابجایی کاربر در درخت — ابزار ادمین ضروری |
|
||||
| 11 | `AssignFeatureToMembership` | clubmembership.proto | ✅ **CQRS کامل** → AssignClubFeatureCommand | مدیریت عضویت: اختصاص فیچر به عضویت — برای فاز بستهبندی پویا |
|
||||
| 12 | `GetLowStockProducts` | products.proto | ✅ **کامل** — فیلتر threshold + pagination | هشدار موجودی: مکمل GetLowStockItems — فیلتر ClubExclusive اضافه دارد |
|
||||
|
||||
### 🗑️ آرشیو (حذف امن — ۱۲ عدد)
|
||||
|
||||
> این RPCها یا stub خالی هستند، یا جایگزین بهتری دارند، یا هرگز ساخته نشدند.
|
||||
|
||||
| # | RPC | فایل Proto | وضعیت کد | دلیل آرشیو |
|
||||
|---|-----|-----------|---------|-----------|
|
||||
| 1 | `CreateNewFileInfo` | fms.proto | ❌ **۰ رفرنس** — هیچ Service/Handler ندارد | سرویس FMS هرگز طراحی نشد — فایلها از imageresolver استفاده میکنند |
|
||||
| 2 | `DeleteFileInfo` | fms.proto | ❌ **۰ رفرنس** — هیچ Service/Handler ندارد | همان — کل fms.proto حذفشدنی |
|
||||
| 3 | `BulkAdjustStock` | inventory.proto | ❌ **۰ رفرنس** — حتی Service method ندارد | هرگز پیادهسازی نشد — از AdjustStock تکی استفاده میشود |
|
||||
| 4 | `CreateNewOrderForCustomer` | userorder.proto | ❌ **Stub خالی** — `return new()` | مسیر سفارش مشتری از SubmitShopBuyOrder میگذرد — تکراری |
|
||||
| 5 | `SubmitOrderForCustomer` | userorder.proto | ❌ **Stub خالی** — `return new()` | مسیر سفارش مشتری از SubmitShopBuyOrder میگذرد — تکراری |
|
||||
| 6 | `DeactivateConfiguration` | configuration.proto | ❌ **throw میکند** — «تنظیمات فقط خواندنی هستند» | عمداً غیرفعال شده — SystemConstants ثابت هستند |
|
||||
| 7 | `GetConfigurationHistory` | configuration.proto | ❌ **خالی برمیگرداند** — `return new()` | SystemConstants تاریخچه ندارند — بیمعنی |
|
||||
| 8 | `DeleteCity` | City.proto | ✅ کامل ولی **بینیاز** | شهرها seed دیتا هستند — حذف شهر باعث خرابی آدرسها میشود |
|
||||
| 9 | `UpdateCity` | City.proto | ✅ کامل ولی **بینیاز** | شهرها از سرویس خارجی seed شدهاند — ویرایش دستی نیاز نیست |
|
||||
| 10 | `GetOrdersByDateRange` | userorder.proto | ✅ کامل ولی **تکراری** | `GetAllUserOrderByFilter` همین قابلیت + فیلترهای بیشتر دارد |
|
||||
| 11 | `GetServiceHealth` | health.proto | ✅ کامل ولی **تکراری** | `GetSystemHealth` کل سیستم را برمیگرداند — فیلتر client-side کافی است |
|
||||
| 12 | `GetCategoryByIdForCustomer` | category.proto | ✅ کامل ولی **تکراری** | `GetCategory` (admin) + `GetAllCategoriesForCustomer` کافی است |
|
||||
|
||||
---
|
||||
|
||||
## 🟡 بخش ۲ — استفاده داخلی CMS (Internal Only — ۱۰۱ عدد)
|
||||
|
||||
> این RPCها از فرانتها فراخوانی نمیشوند ولی **در کد بکند CMS فعال هستند** (background services, handlers, internal flows). **حذف نشوند!**
|
||||
|
||||
### B1. احراز هویت و کاربر (user.proto)
|
||||
|
||||
| RPC | رفرنس CMS | علت |
|
||||
|-----|-----------|-----|
|
||||
| `CreateNewUser` | 175 | ثبتنام کاربر — اصلیترین فلو |
|
||||
| `GetJwtToken` | 38 | صدور توکن JWT |
|
||||
| `AdminGetJwtToken` | 19 | لاگین ادمین |
|
||||
| `SetPasswordForUser` | 24 | تنظیم رمز عبور |
|
||||
| `ChangeCustomerPassword` | 5 | تغییر رمز مشتری |
|
||||
| `UploadCustomerAvatar` | 6 | آپلود آواتار |
|
||||
| `GetCustomerProfile` | 13 | پروفایل مشتری |
|
||||
| `GetCustomerReferrals` | 13 | لیست معرفیشدگان |
|
||||
| `GetCustomerSettings` | 13 | تنظیمات مشتری |
|
||||
|
||||
### B2. بستهها و پرداخت (package.proto / manualpayment.proto)
|
||||
|
||||
| RPC | رفرنس CMS | علت |
|
||||
|-----|-----------|-----|
|
||||
| `PurchaseGoldenPackage` | 21 | خرید بسته طلایی — فلو فعال |
|
||||
| `VerifyGoldenPackagePurchase` | 22 | تأیید خرید بسته طلایی |
|
||||
| `CustomerPurchasePackage` | 3 | خرید مشتری (proto-generated + service) |
|
||||
| `CustomerVerifyPackagePurchase` | 3 | تأیید خرید مشتری |
|
||||
| `GetCustomerPurchaseHistory` | 13 | تاریخچه خرید |
|
||||
| `ProcessManualMembershipPayment` | 20 | پرداخت دستی عضویت |
|
||||
|
||||
### B3. شبکه و عضویت (networkmembership.proto / clubmembership.proto)
|
||||
|
||||
| RPC | رفرنس CMS | علت |
|
||||
|-----|-----------|-----|
|
||||
| `JoinNetwork` | 14 | پیوستن به شبکه — فراخوانی خودکار |
|
||||
| `RemoveFromNetwork` | 14 | حذف از شبکه |
|
||||
|
||||
### B4. کمیسیون (commission.proto)
|
||||
|
||||
| RPC | رفرنس CMS | علت |
|
||||
|-----|-----------|-----|
|
||||
| `CalculateWeeklyBalances` | 26 | سرویس پسزمینه هفتگی |
|
||||
| `CalculateWeeklyCommissionPool` | 22 | سرویس پسزمینه هفتگی |
|
||||
| `ProcessUserPayouts` | 15 | پردازش پرداختها |
|
||||
| `GetCommissionPayoutHistory` | 20 | تاریخچه پرداخت کمیسیون |
|
||||
|
||||
### B5. انبارداری (inventory.proto)
|
||||
|
||||
| RPC | رفرنس CMS | علت |
|
||||
|-----|-----------|-----|
|
||||
| `ConfirmSale` | 10 | تأیید فروش — فلو سفارش |
|
||||
| `ReserveStock` | 12 | رزرو موجودی — فلو سفارش |
|
||||
| `ReleaseReservation` | 10 | آزادسازی رزرو |
|
||||
| `ProcessReturn` | 6 | پردازش مرجوعی |
|
||||
| `DeleteWarehouse` | 18 | حذف انبار |
|
||||
| `GetInventoryByProduct` | 26 | موجودی بر اساس محصول |
|
||||
| `GetInventoryItem` | 19 | آیتم انبار |
|
||||
| `GetWarehouse` | 18 | دریافت انبار |
|
||||
| `SetDefaultWarehouse` | 18 | تنظیم انبار پیشفرض |
|
||||
| `UpdateWarehouse` | 18 | بروزرسانی انبار |
|
||||
| `GetStockMovementsByInventoryItem` | 17 | حرکات موجودی |
|
||||
|
||||
### B6. تراکنشها (transactions.proto)
|
||||
|
||||
| RPC | رفرنس CMS | علت |
|
||||
|-----|-----------|-----|
|
||||
| `CreateNewTransactions` | 26 | ایجاد تراکنش — فلو پرداخت |
|
||||
| `DeleteTransactions` | 23 | حذف تراکنش |
|
||||
| `GetAllTransactionsByFilter` | 25 | لیست تراکنشها |
|
||||
| `CustomerPaymentVerification` | 3 | تأیید پرداخت مشتری |
|
||||
| `GetCustomerTransaction` | 27 | تراکنش مشتری |
|
||||
| `GetCustomerTransactionsByFilter` | 14 | فیلتر تراکنشها |
|
||||
| `RefundTransaction` | 31 | استرداد تراکنش |
|
||||
| `UpdateTransactions` | 23 | بروزرسانی تراکنش |
|
||||
| `VerifyTransaction` | 24 | تأیید تراکنش |
|
||||
|
||||
### B7. سایر CRUD داخلی (خلاصه)
|
||||
|
||||
> ۵۸ RPC در فایلهای contract, usercontract, factordetails, productcategory, productgalleries, productimages, userwallet, userwalletchangelog, otptoken, usercarts, discountproduct, public_messages, category, products, producttag, tag, City, useraddress, userorder — همه CRUD داخلی با ≥3 رفرنس در CMS.
|
||||
|
||||
---
|
||||
|
||||
## 🟢 بخش ۳ — سرویسهای کاملاً مورد استفاده
|
||||
|
||||
### فایلهای proto که تمام RPCهایشان استفاده میشود:
|
||||
|
||||
| فایل Proto | کل RPC | استفاده FO | استفاده BO |
|
||||
|-----------|--------|-----------|-----------|
|
||||
| appversion.proto | 3 | ✅ 1 | ✅ 3 |
|
||||
| blogcategory.proto | 6 | ✅ 2 | ✅ 6 |
|
||||
| blogpost.proto | 11 | ✅ 5 | ✅ 9 |
|
||||
| blogpostimage.proto | 4 | ✅ 0 | ✅ 4 |
|
||||
| discountcategory.proto | 4 | ✅ 1 | ✅ 4 |
|
||||
| discountorder.proto | 7 | ✅ 3 | ✅ 4 |
|
||||
| discountshoppingcart.proto | 5 | ✅ 5 | ✅ 0 |
|
||||
| manualpayment.proto | 5 | ✅ 0 | ✅ 4 |
|
||||
| public_messages.proto | 8 | ✅ 0 | ✅ 7 |
|
||||
| role.proto | 5 | ✅ 0 | ✅ 5 |
|
||||
| sitepage.proto | 10 | ✅ 2 | ✅ 10 |
|
||||
| sitepagesettings.proto | 5 | ✅ 1 | ✅ 5 |
|
||||
| tag.proto | 6 | ✅ 0 | ✅ 5 |
|
||||
| userrole.proto | 5 | ✅ 0 | ✅ 5 |
|
||||
|
||||
---
|
||||
|
||||
## 📋 بخش ۴ — خلاصه تصمیمات
|
||||
|
||||
### ماتریکس نهایی ۲۴ RPC مُرده
|
||||
|
||||
```
|
||||
✅ نگهداری (12): CustomerReorderPreviousOrder, CustomerTrackOrder,
|
||||
CalculateOrderPV, GetInventorySummary, GetStockValueReport,
|
||||
BulkAddStock, BulkUpdateProductStock, GetConfigurationByKey,
|
||||
UpdateCustomerSettings, ChangeNetworkParent,
|
||||
AssignFeatureToMembership, GetLowStockProducts
|
||||
|
||||
🗑️ آرشیو (12): CreateNewFileInfo, DeleteFileInfo, BulkAdjustStock,
|
||||
CreateNewOrderForCustomer, SubmitOrderForCustomer,
|
||||
DeactivateConfiguration, GetConfigurationHistory,
|
||||
DeleteCity, UpdateCity, GetOrdersByDateRange,
|
||||
GetServiceHealth, GetCategoryByIdForCustomer
|
||||
```
|
||||
|
||||
### فایلهای proto آرشیوشدنی (کامل)
|
||||
|
||||
| فایل | وضعیت | اقدام |
|
||||
|------|-------|-------|
|
||||
| **fms.proto** | کل فایل مُرده (2 RPC) | حذف از csproj — ساخته نشود |
|
||||
|
||||
### RPCهای آرشیوشدنی (جزئی — داخل فایلهای فعال)
|
||||
|
||||
| فایل Proto | RPCهای آرشیو | RPCهای فعال |
|
||||
|-----------|-------------|-------------|
|
||||
| inventory.proto | `BulkAdjustStock` (1) | 23 فعال |
|
||||
| userorder.proto | `CreateNewOrderForCustomer`, `SubmitOrderForCustomer` (2) | 18 فعال |
|
||||
| configuration.proto | `DeactivateConfiguration`, `GetConfigurationHistory` (2) | 5 فعال |
|
||||
| City.proto | `DeleteCity`, `UpdateCity` (2) | 6 فعال |
|
||||
| health.proto | `GetServiceHealth` (1) | 1 فعال |
|
||||
| category.proto | `GetCategoryByIdForCustomer` (1) | 7 فعال |
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ نکات مهم
|
||||
|
||||
1. **آرشیو ≠ حذف!** — RPCهای آرشیوشده با `[Obsolete]` + `#region [ARCHIVED]` علامتگذاری شدند (کامیت `13dd0f5`)
|
||||
2. RPCهای دسته B (Internal — ۱۰۱ عدد) **حیاتی** هستند — بدون آنها سیستم از کار میافتد
|
||||
3. RPCهای «نگهداری» (۱۲ عدد) کد **کامل و آماده** دارند — بکلاگ فیچر: [FEATURE-BACKLOG.md](../roadmap/FEATURE-BACKLOG.md)
|
||||
4. **fms.proto** از csproj اکسکلود شد (کامیت `13dd0f5`)
|
||||
5. نقشهراه تحول پکیجبیس: [PACKAGE-TRANSFORMATION-TASKS.md](../roadmap/PACKAGE-TRANSFORMATION-TASKS.md)
|
||||
6. قبل از هر تغییر، حتماً `grep -rn "RpcName" CMS/src/` بزنید تا مطمئن شوید
|
||||
|
||||
---
|
||||
|
||||
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۰۶*
|
||||
@@ -3,8 +3,8 @@
|
||||
> **فهرست کامل ۱۵ فایل مستند پروژه FourSat (کارا بازار سلامت)**
|
||||
> **تاریخ تجمیع:** اسفند ۱۴۰۴
|
||||
> **تعداد فایلهای مبدأ:** ۵۳ فایل (~۳۲,۰۰۰ خط)
|
||||
> **تعداد فایلهای نهایی:** ۱۷ فایل (۱۵ اصلی + ۲ roadmap)
|
||||
> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (فعالسازی درگاه + مرج Production + بهبود UI)
|
||||
> **تعداد فایلهای نهایی:** ۲۲ فایل (۱۵ اصلی + ۷ roadmap/business)
|
||||
> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (تحول پکیجبیس فاز ۰-۴ + فعالسازی درگاه + مرج Production)
|
||||
|
||||
---
|
||||
|
||||
@@ -35,7 +35,10 @@ totalDoc/
|
||||
│
|
||||
└── 📁 roadmap/ (فیچرهای جدید — در حال توسعه)
|
||||
├── MAGIC-WALLET-SPEC.md مشخصات کیفپول جادویی
|
||||
└── MAGIC-WALLET-PLAN.md پلن پیادهسازی + checklist
|
||||
├── MAGIC-WALLET-PLAN.md پلن پیادهسازی + checklist
|
||||
├── PACKAGE-TRANSFORMATION-TASKS.md تسکهای تحول پکیجبیس (فاز 0-5)
|
||||
├── PACKAGE-TRANSFORMATION-UX.md تاثیر بر UX فرانتها
|
||||
└── FEATURE-BACKLOG.md بکلاگ ۱۲ RPC آماده
|
||||
```
|
||||
|
||||
---
|
||||
@@ -77,7 +80,11 @@ totalDoc/
|
||||
| # | فایل | موضوع | خلاصه |
|
||||
|---|------|--------|--------|
|
||||
| R1 | [MAGIC-WALLET-SPEC](../roadmap/MAGIC-WALLET-SPEC.md) | کیفپول جادویی — مشخصات | State Machine، ضریب ×2.5، سقف 100M، قوانین، API، مدل داده |
|
||||
| R2 | [MAGIC-WALLET-PLAN](../roadmap/MAGIC-WALLET-PLAN.md) | کیفپول جادویی — پلن | ۶ فاز، **فاز 1-5 تکمیل ✅**، فاز 6 باقی |
|
||||
| R2 | [MAGIC-WALLET-PLAN](../roadmap/MAGIC-WALLET-PLAN.md) | کیفپول جادویی — پلن | ۶ فاز، **فاز 1-6 تکمیل ✅** |
|
||||
| R3 | [PACKAGE-TRANSFORMATION-TASKS](../roadmap/PACKAGE-TRANSFORMATION-TASKS.md) | تحول پکیجبیس — تسکها | ۵ فاز، **فاز 0-4 تکمیل ✅**، فاز 5-6 در انتظار |
|
||||
| R4 | [PACKAGE-TRANSFORMATION-UX](../roadmap/PACKAGE-TRANSFORMATION-UX.md) | تاثیر بر UX | تحلیل تاثیر بر FrontOffice + BackOffice |
|
||||
| R5 | [FEATURE-BACKLOG](../roadmap/FEATURE-BACKLOG.md) | بکلاگ فیچرها | ۱۲ RPC آماده بدون UI، اولویتبندیشده |
|
||||
| R6 | [BIZ-PACKAGE-BASED-SYSTEM](../business/BIZ-PACKAGE-BASED-SYSTEM.md) | طراحی سیستم پکیجبیس | v5، ۲۳ تصمیم + ۵۱ تغییر + ۴۴ سایدافکت |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 📜 تاریخچه کارهای انجامشده
|
||||
|
||||
> **همه فعالیتهای پروژه به صورت بولت با توضیح یکخطی و درصد تکمیل**
|
||||
> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (بروزرسانی: فعالسازی درگاه + مرج پروداکشن + بهبود UI ادمین)
|
||||
> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (بروزرسانی: فاز ۸e — Per-Package Commission Reports | NuGet v0.0.187)
|
||||
|
||||
---
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
|
||||
| حوزه | تعداد آیتم | تکمیلشده | درصد کل |
|
||||
|------|-----------|----------|---------|
|
||||
| **BackOffice** | 61 | 60 | **98%** |
|
||||
| **FrontOffice** | 40 | 38 | **95%** |
|
||||
| **CMS Core** | 58 | 56 | **97%** |
|
||||
| **BackOffice** | 61 | 61 | **100%** |
|
||||
| **FrontOffice** | 40 | 40 | **100%** |
|
||||
| **CMS Core** | 72 | 72 | **100%** |
|
||||
| **Package-Based System** | 35 | 35 | **100%** |
|
||||
| **Deployment** | 22 | 21 | **95%** |
|
||||
| **Migration** | 16 | 16 | **100%** |
|
||||
| **مجموع** | **197** | **191** | **97%** |
|
||||
| **مجموع** | **246** | **245** | **99%** |
|
||||
|
||||
---
|
||||
|
||||
@@ -66,6 +67,13 @@
|
||||
- ✅ فیلتر کاربر در صفحه ClubMembers — UserAutoComplete در تولبار جستجو
|
||||
- ✅ نمایش نام کاربر در WalletManagementPage — TemplateColumn با UserName + ID
|
||||
|
||||
### Phase 8b: CRUD پکیج کامل (اسفند ۱۴۰۴)
|
||||
- ✅ CreateDialog: اضافه ۱۲ فیلد جدید — SortOrder, ActivationFee, DiscountMultiplier, MagicWallet*, MaxBalancesPerLeg, MaxNetworkLevel, IsActive, IsBasePackage, SupportsDirectPurchase, SupportsDayaPurchase
|
||||
- ✅ UpdateDialog: همان ۱۲ فیلد جدید — ایجاد فرم کامل ادمین
|
||||
- ✅ PackageMainPage Grid: ۴ ستون جدید — قیمت (N0), ترتیب, وضعیت (فعال/غیرفعال chip), نوع (پایه/عادی chip)
|
||||
- ✅ فیکس `HasPurchasedGoldenPackage` → `HasPurchasedPackage` — UserNetworkInfo.razor
|
||||
- ✅ NuGet bump 0.0.184 → 0.0.186 + local feed source
|
||||
|
||||
---
|
||||
|
||||
## ۲. FrontOffice — فازها (95% کامل)
|
||||
@@ -97,6 +105,13 @@
|
||||
- ✅ دکمه پرداخت شارژ کیفپول اعتباری — ChargeDiscountWallet.razor فعال شد (حذف «بزودی»)
|
||||
- ✅ دکمه پرداخت شارژ کیفپول جادویی — MagicWallet.razor فعال شد (حذف «بزودی»)
|
||||
- ✅ دکمههای پرداخت مستقیم خرید پکیج — Index.razor هر دو شاخه فعال شدند (حذف «بزودی»)
|
||||
|
||||
### Phase 8a+8c: Checkout + Package Pages (اسفند ۱۴۰۴)
|
||||
- ✅ Checkout wire-up — مهاجرت به `CustomerPurchasePackageAsync` (حذف dead code قدیمی)
|
||||
- ✅ PackageDetail: `GetPackageAsync` → `GetCustomerPackageDetailsAsync` — features/specs از API (نه hardcoded)
|
||||
- ✅ Packages.razor: un-exclude از build + dynamic feature bullets از `CustomerPackageModel`
|
||||
- ✅ PackageService: `PackageDto` غنیشده با ۸ فیلد جدید + `GetUserPackageStatusAsync` متصل به RPC واقعی
|
||||
- ✅ NuGet bump 0.0.182 → 0.0.186 + local feed source
|
||||
- ✅ فیکس GwUrl پروداکشن — تصحیح از cms.kbs1.ir به cms.kbs2.ir
|
||||
|
||||
### محتوا و ناوبری
|
||||
@@ -217,7 +232,98 @@
|
||||
|
||||
---
|
||||
|
||||
## ۷. Timeline (جدول زمانی)
|
||||
## ۷. تحول سیستم پکیجبیس (Package-Based Transformation) — 90%
|
||||
|
||||
> 📦 تبدیل سیستم تکپکیجی hardcoded به معماری چندپکیجی داینامیک
|
||||
> مرجع: [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) | [PACKAGE-TRANSFORMATION-TASKS.md](../roadmap/PACKAGE-TRANSFORMATION-TASKS.md)
|
||||
|
||||
### Phase 0 — فیکس باگهای فوری ✅ (`8b9c317`, `fe3edd1`)
|
||||
- ✅ B1: DiscountBalance شارژ نمیشد در VerifyGoldenPackagePurchase — اضافه `DiscountBalance += Amount × 2` + WalletChangeLog
|
||||
- ✅ B2: UserPackagePurchase ساخته نمیشد در VerifyGoldenPackagePurchase — ساخت record بعد verify
|
||||
- ✅ B3: UserPackagePurchase ساخته نمیشد در VerifyPackagePurchase — ساخت record
|
||||
- ✅ B4: UserPackagePurchase ساخته نمیشد در VerifyBasePackagePayment — ساخت record
|
||||
- ✅ B6: EXIT Magic Mode — ریست PackagePurchaseMethod + بستن چرخه فعلی
|
||||
|
||||
### Phase 1 — زیرساخت Domain ✅ (`ae92ab8`)
|
||||
- ✅ T1.1: Package Entity — ۱۱ فیلد جدید (SortOrder, IsActive, IsBasePackage, DiscountMultiplier, MagicWalletMultiplier, ...)
|
||||
- ✅ T1.2: PackageFeature Entity — رابطه M:N بین Package و ClubFeature
|
||||
- ✅ T1.3: ClubMembership — ۴ فیلد First/Last Activation + PackageId
|
||||
- ✅ T1.4-T1.6: اضافه PackageId به ClubMembershipCycle, WeeklyCommissionPool, UserCommissionPayout, NetworkWeeklyBalance, UserWalletChangeLog
|
||||
- ✅ T1.7: علامتگذاری ۹ SystemConstants بهعنوان [Obsolete]
|
||||
- ✅ T1.8: EF Configurations — Index, Precision, FK relations
|
||||
|
||||
### Phase 1.5 — Migration + Data Seed ✅ (`a9cd2fd`)
|
||||
- ✅ EF Migration `AddPackageBasedSystem` — ستونها + جداول + ایندکسها
|
||||
- ✅ Golden Package Seed (Id=1) — Price=56M, ActivationFee=25.2M, DiscountMultiplier=2.0, MagicWalletMultiplier=2.5
|
||||
- ✅ Data Backfill — تمام رکوردهای موجود → PackageId=1
|
||||
- ✅ فیکس nullable DateTime/long در ClubMembership
|
||||
- ✅ فیکس Shadow FK PackageId1
|
||||
|
||||
### Phase 2 — منطق کسبوکار ✅ (`8e5c7c5`)
|
||||
- ✅ T2.1: ActivateClubMembership — ActivationFee از Package entity
|
||||
- ✅ T2.2: AcceptClubMembershipContract — Package features از DB
|
||||
- ✅ T2.3: CalculateWeeklyBalances — MaxBalancesPerLeg per-package
|
||||
- ✅ T2.4: ProcessUserPayouts — PackageId tracking
|
||||
- ✅ T2.5: DayaLoans — Package.Price بجای hardcoded
|
||||
- ✅ T2.6: ManualPayment — Package.Price بجای hardcoded
|
||||
- ✅ T2.7: InitiateBasePackage/VerifyBasePackage — Package-based
|
||||
- ✅ T2.8: ChargeMagicWallet/VerifyMagicWalletCharge — MagicWalletMultiplier per-package
|
||||
- ✅ T2.9: OrmCommissionCalculationStrategy — MaxBalancesPerLeg/MaxNetworkLevel per-package
|
||||
- ✅ T2.10: ConfigurationService/UserOrderService/UserWalletService — Package reads
|
||||
- ✅ **نتیجه:** صفر مصرف SystemConstants deprecated باقی مانده
|
||||
|
||||
### Phase 3 — بازسازی لایه Package ✅ (`ccb938e`)
|
||||
- ✅ Proto: ۱۱ فیلد جدید در ۵ message (CreateNewPackageRequest, UpdatePackageRequest, GetPackageResponse, ...)
|
||||
- ✅ GetUserPackageStatus — پیادهسازی (قبلاً NotImplementedException بود!)
|
||||
- ✅ CustomerVerifyPackagePurchase — شارژ کیفپول اضافه شد (قبلاً missing بود!)
|
||||
- ✅ VerifyGoldenPackagePurchase — `package.DiscountMultiplier` بجای hardcoded ×2
|
||||
- ✅ GetAllPackageByFilter — فیلتر IsDeleted
|
||||
- ✅ GetCustomerPackages — فیلتر IsDeleted + IncludeInactive + SortOrder
|
||||
- ✅ GetCustomerPackageDetails — PackageFeatures از DB
|
||||
- ✅ GetCustomerPurchaseHistory — Include Transaction
|
||||
- ✅ UpdatePackageCommand — ۱۲ فیلد جدید
|
||||
|
||||
### Phase 4 — تکمیل CRUD + Legacy Fixes ✅ (`0002a5a`)
|
||||
- ✅ CreateNewPackageCommand — ۱۲ فیلد جدید با defaultهای مناسب
|
||||
- ✅ GetPackageResponseDto — ۱۲ فیلد جدید (Mapster auto-map)
|
||||
- ✅ GetAllPackageByFilterResponseModel — ۱۲ فیلد جدید
|
||||
- ✅ PurchaseGoldenPackage — حذف Title string match شکننده (`"طلایی"/"golden"`) → `IsDeleted/IsActive/SupportsDirectPurchase`
|
||||
- ✅ VerifyPackagePurchase — حذف hardcoded `order.Amount × 2` → `package.DiscountMultiplier` از DB
|
||||
|
||||
### Phase 5 — پورسانت per-package + پاکسازی golden ✅ (`607f791`, `7176fe4`)
|
||||
- ✅ ORM Commission: per-user-package calculation via `ClubMembership.LastPackageId`
|
||||
- userPackageMap، per-user maxBalancesPerLeg/maxNetworkLevel
|
||||
- Carryover keyed by (UserId, PackageId) tuple
|
||||
- ✅ SP Commission: loop over packages، pass `@PackageId/@InputMaxBalancesPerLeg/@InputMaxNetworkLevel`
|
||||
- ✅ sp_CalculateWeeklyBalances: ۳ پارامتر جدید، فیلتر `cm.LastPackageId = @PackageId`، ستون PackageId در INSERT
|
||||
- ✅ Fix: `cm.PackageId` → `cm.LastPackageId` — match actual DB column name
|
||||
- ✅ Fix golden/طلایی string refs in user-facing messages (ActivateClubMembership)
|
||||
- ✅ Rename `HasPurchasedGoldenPackage` → `HasPurchasedPackage` (DTO + Handler + Proto + Mapping)
|
||||
|
||||
### Phase 6 — Deprecation cleanup + ConfigurationService ✅ (`d19c569`)
|
||||
- ✅ Mark `PurchaseGoldenPackage`/`VerifyGoldenPackagePurchase` RPCs as `deprecated = true`
|
||||
- ✅ Mark `InitiateBasePackagePayment`/`VerifyBasePackagePayment` RPCs as `deprecated = true`
|
||||
- ✅ Remove deprecated SystemConstants from `GetAllAsDict`/`GetAllWithDescriptions` helpers
|
||||
- ✅ Add MagicWallet per-package values to ConfigurationService (Multiplier, MaxDeposit, MaxCredit)
|
||||
- ✅ تأیید: صفر رفرنس فعال به ۹ SystemConstants منسوخ — dead code آماده حذف
|
||||
|
||||
### Phase 7 — UI ✅ (گزارش per-package)
|
||||
- ⬜ FrontOffice: کاشیهای داینامیک پکیج
|
||||
- ⬜ FrontOffice: MyPackages + re-purchase
|
||||
- ✅ FrontOffice: Commission Dashboard per-package — فیلتر dropdown پکیج + ستون پکیج + MudChip (دسکتاپ + موبایل)
|
||||
- ✅ FrontOffice: WeeklyBalance per-package — فیلتر MudSelect پکیج + MudChip اطلاعات هفته
|
||||
- ✅ BackOffice: فیلتر پکیج در گزارشها — PackageSelect component + UserPayouts + BalancesReport
|
||||
|
||||
### Phase 8e — Per-Package Commission Reports ✅ (CMS:`aaaf7fc` FO:`a956cb9` BO:`8be98ae`)
|
||||
- ✅ Proto: اضافه `package_id` فیلتر به ۴ request + `package_id`/`package_title` به ۴ response model
|
||||
- ✅ CMS: اضافه PackageId فیلتر به ۴ query + handler + ۳ DTO + CommissionProfile mapping
|
||||
- ✅ BO: کامپوننت PackageSelect + فیلتر و ستون پکیج در UserPayouts + BalancesReport
|
||||
- ✅ FO: فیلتر و ستون پکیج در CommissionDashboard + WeeklyBalance
|
||||
- ✅ NuGet: `0.0.186` → `0.0.187`
|
||||
|
||||
---
|
||||
|
||||
## ۸. Timeline (جدول زمانی)
|
||||
|
||||
| زمان | رویداد | درصد پروژه |
|
||||
|------|--------|-----------|
|
||||
@@ -232,3 +338,5 @@
|
||||
| اسفند ۱۴۰۳ (هفته ۴) | مستندات + نهاییسازی | 95% |
|
||||
| اسفند ۱۴۰۴ (هفته ۱-۲) | 🪄 کیفپول جادویی (فاز 1-6) + اصلاح VAT 10% | 96% |
|
||||
| اسفند ۱۴۰۴ (هفته ۳) | 🚀 فعالسازی درگاه + بهبود UI ادمین + مرج پروداکشن | 97% |
|
||||
| اسفند ۱۴۰۴ (هفته ۴) | 📦 تحول پکیجبیس فاز ۰-۶ (Domain → Migration → Business → Package → CRUD → Commission per-pkg → Deprecation) | 97% |
|
||||
| اسفند ۱۴۰۴ (هفته ۵) | 📦 فاز 8e: گزارشهای پورسانت per-package (Proto + CMS + BO + FO) | 98% |
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
# 🗺️ نقشه راه، ریسکها و کارهای باقیمانده
|
||||
|
||||
> **Roadmap + Risk Register + Dependencies + Priorities**
|
||||
> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (بروزرسانی: فعالسازی درگاه + مرج پروداکشن + بهبود UI)
|
||||
> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (بروزرسانی: تحول پکیجبیس فاز ۰-۶ + per-package commission + deprecation cleanup)
|
||||
|
||||
---
|
||||
|
||||
## ۱. وضعیت فعلی پروژه
|
||||
|
||||
```
|
||||
██████████████████████████████████████████████████ 97%
|
||||
██████████████████████████████████████████████████ 95%
|
||||
|
||||
Core Platform ████████████████████████████████████████████████ 98%
|
||||
Club System ████████████████████████████████████████████████ 98%
|
||||
E-Commerce ████████████████████████████████████████████████ 98%
|
||||
Payment ████████████████████████████████████████████████ 97%
|
||||
Magic Wallet ████████████████████████████████████████████████ 100%
|
||||
Package-Based ██████████████████████████████████████████████░░ 93%
|
||||
UI/UX █████████████████████████████████████████████░░░ 93%
|
||||
Deployment ██████████████████████████████████████████████░░ 95%
|
||||
Documentation ████████████████████████████████████████████████ 100%
|
||||
@@ -207,8 +208,10 @@ DONE (اسفند ۱۴۰۴):
|
||||
→ بهبود UI ادمین (UserAutoComplete + نام کاربر در کیفپول) ✅
|
||||
→ مرج پروداکشن هر ۳ ریپو (CMS + FO + BO) ✅
|
||||
→ اجرای Migration روی پروداکشن ✅
|
||||
→ 📦 تحول پکیجبیس فاز 0-6 ✅ (Domain → Migration → Business → Package → CRUD → Commission per-pkg → Deprecation)
|
||||
|
||||
NOW (این ماه):
|
||||
→ 📦 فاز 7: UI (کاشیهای داینامیک + فیلتر پکیج + MyPackages)
|
||||
→ EF Migration نهایی
|
||||
→ تست کامل پروداکشن
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
# 📋 فیچر بکلاگ — RPCهای آماده (بدون UI)
|
||||
|
||||
> تاریخ: ۱۴۰۴/۱۲/۱۰
|
||||
> منبع: آدیت gRPC (کامیت `3575e48`) → ۱۲ RPC کامل بدون فرانت
|
||||
> اولویتبندی: بر اساس ارزش کسبوکار + نیازمندی پکیجبیس
|
||||
|
||||
---
|
||||
|
||||
## 🎯 خلاصه
|
||||
|
||||
از ۲۴ RPC مُرده شناساییشده، **۱۲ عدد پیادهسازی کامل** دارند ولی هرگز از فرانتها وصل نشدند. اینها فیچرهای آماده هستند که فقط نیاز به UI دارند.
|
||||
|
||||
---
|
||||
|
||||
## 📊 ماتریس فیچر × اولویت
|
||||
|
||||
### 🔴 اولویت بالا — مرتبط با پکیجبیس کردن
|
||||
|
||||
| # | RPC | تارگت | صفحه | اقدام | تخمین |
|
||||
|---|-----|-------|------|-------|-------|
|
||||
| F1 | `AssignFeatureToMembership` | BackOffice | ClubFeaturesPage.razor | دکمه «اختصاص فیچر به عضو» + ماتریس PackageFeature | ۴ ساعت |
|
||||
| F2 | `ChangeNetworkParent` | BackOffice | UserNetworkInfo.razor | ✅ دکمه «تغییر والد» + مودال ChangeParentDialog | BO:`e020354` |
|
||||
| F3 | `CalculateOrderPV` | FrontOffice | Store/OrderDetail.razor | ✅ نمایش PV سفارش + PV هر محصول | FO:`3bffc13` |
|
||||
|
||||
### 🟡 اولویت متوسط — بهبود UX فروشگاه
|
||||
|
||||
| # | RPC | تارگت | صفحه | اقدام | تخمین |
|
||||
|---|-----|-------|------|-------|-------|
|
||||
| F4 | `CustomerReorderPreviousOrder` | FrontOffice | OrderHistory (Store/Discount) | دکمه «تکرار سفارش» در هر ردیف تاریخچه | ۳ ساعت |
|
||||
| F5 | `CustomerTrackOrder` | FrontOffice | OrderTracking.razor | وصل Tracking API → نمایش TrackingCode + وضعیت ارسال | ۴ ساعت |
|
||||
| F6 | `UpdateCustomerSettings` | FrontOffice | Profile/Settings.razor | فرم تنظیمات اعلان (Email/SMS/Push) + دکمه ذخیره | ۳ ساعت |
|
||||
| F7 | `GetLowStockProducts` | BackOffice | LowStockPage.razor | وصل API → فیلتر threshold + هشدار بصری | ۳ ساعت |
|
||||
|
||||
### 🟢 اولویت پایین — گزارشدهی و عملیات انبوه
|
||||
|
||||
| # | RPC | تارگت | صفحه | اقدام | تخمین |
|
||||
|---|-----|-------|------|-------|-------|
|
||||
| F8 | `GetInventorySummary` | BackOffice | InventoryMainPage.razor | کارت خلاصه بالای صفحه (تعداد کل + ارزش ریالی) | ۳ ساعت |
|
||||
| F9 | `GetStockValueReport` | BackOffice | InventoryMainPage.razor | تب «گزارش ارزش» + دانلود Excel | ۴ ساعت |
|
||||
| F10 | `BulkAddStock` | BackOffice | InventoryMainPage.razor | دکمه «افزودن دستهای» + آپلود CSV/فرم چندتایی | ۶ ساعت |
|
||||
| F11 | `BulkUpdateProductStock` | BackOffice | InventoryMainPage.razor | دکمه «بروزرسانی دستهای» (Set/Add/Subtract) | ۶ ساعت |
|
||||
| F12 | `GetConfigurationByKey` | Internal | — | بدون UI — استفاده داخلی بهینه بجای GetAll | ۰ |
|
||||
|
||||
---
|
||||
|
||||
## 📐 نقشه پیادهسازی
|
||||
|
||||
### فاز A — همراه پکیجبیس (فاز ۴ BIZ-PACKAGE-BASED-SYSTEM)
|
||||
|
||||
```
|
||||
F1 (AssignFeatureToMembership) → با T4.6 (ماتریس PackageFeature) ادغام
|
||||
F2 (ChangeNetworkParent) ✅ تکمیل → BO:`e020354`
|
||||
F3 (CalculateOrderPV) ✅ تکمیل → FO:`3bffc13`
|
||||
```
|
||||
|
||||
### فاز B — بعد از پکیجبیس (Sprint بعدی)
|
||||
|
||||
```
|
||||
F4 → F7: بهبود UX فروشگاه و مشتری
|
||||
تخمین: ۱۳ ساعت = ~۲ روز
|
||||
```
|
||||
|
||||
### فاز C — آینده (بدون فوریت)
|
||||
|
||||
```
|
||||
F8 → F12: گزارشدهی و عملیات انبوه
|
||||
تخمین: ۱۹ ساعت = ~۳ روز
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔗 ارجاعات
|
||||
|
||||
| مستند | محتوا |
|
||||
|-------|-------|
|
||||
| [GRPC-SERVICES-AUDIT.md](../cms/GRPC-SERVICES-AUDIT.md) | آدیت کامل ۳۴۲ RPC — ۱۲ نگهداری + ۱۲ آرشیو |
|
||||
| [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) | طراحی سیستم پکیجبیس — ۳۹ تغییر |
|
||||
|
||||
---
|
||||
|
||||
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۱۰ — F2+F3 تکمیل | باقیمانده فاز A: F1*
|
||||
@@ -0,0 +1,781 @@
|
||||
# 🔄 نقشهراه تحول پکیجبیس — تسکهای گامبهگام
|
||||
|
||||
> **وضعیت:** در حال اجرا — **فاز ۰-۸f (UI تکمیل) ✅** | NuGet v0.0.188 | تست باقیمانده
|
||||
> **تاریخ:** ۱۴۰۴/۱۲/۱۰
|
||||
> **پیشنیاز:** [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) **v3** (تکمیل پورسانت per-package)
|
||||
> **هدف:** شکستن **۴۸+ تغییر** به تسکهای اتمیک با ترتیب اجرا و وابستگیها
|
||||
> **کامیتها:**
|
||||
> CMS: `8b9c317`→`fe3edd1`→`ae92ab8`→`a9cd2fd`→`8e5c7c5`→`ccb938e`→`0002a5a`→`607f791`→`7176fe4`→`d19c569`→`469d97b`→`161f796`→`8446e0e`→`ce8e248`→`7554d70`→`aaaf7fc`→`dcd1135`
|
||||
> FrontOffice: `b82cac4`→`71f391a`→`0bbc11e`→`d71d463`→`40882c8`→`a956cb9`→`3bffc13`
|
||||
> BackOffice: `f1b0085`→`89f5241`→`c96377a`→`8be98ae`→`e020354`
|
||||
|
||||
> ⚠️ **تغییرات v3:** پورسانت per-package، carryover مجزا، SP parameters داینامیک، گزارشدهی FO/BO per-package
|
||||
|
||||
---
|
||||
|
||||
## 📊 نمای کلی
|
||||
|
||||
```
|
||||
مرحله ۰: فیکس باگ فوری (۱ روز) ✅ `8b9c317` + `fe3edd1`
|
||||
└─→ مرحله ۱: زیرساخت Domain + DB (۴ روز) ✅ `ae92ab8`
|
||||
└─→ مرحله ۱.۵: Migration + Seed ✅ `a9cd2fd`
|
||||
├─→ مرحله ۲: منطق کسبوکار (۴ روز) ✅ `8e5c7c5`
|
||||
│ └─→ مرحله ۳: بازسازی لایه Package ✅ `ccb938e`
|
||||
│ └─→ مرحله ۴: CRUD + Legacy Fixes ✅ `0002a5a`
|
||||
│ └─→ مرحله UI (۵ روز) ✅
|
||||
└─→ مرحله ۳: پورسانت (۴ روز) ✅ `607f791`+`7176fe4`
|
||||
└─→ مرحله ۶: Deprecation cleanup ✅ `d19c569`
|
||||
└─→ مرحله ۷: Migration + Cleanup ✅
|
||||
├─→ 7a: Cosmetic cleanup ✅ CMS:`469d97b` FO:`b82cac4` BO:`f1b0085`
|
||||
├─→ 7b: FO RPC migration ✅ CMS:`161f796` FO:`71f391a`
|
||||
└─→ 7c: Delete deprecated ✅ CMS:`8446e0e`
|
||||
└─→ مرحله ۸: FO/BO Completion
|
||||
├─→ 8a: Checkout wire-up ✅ FO:`0bbc11e`
|
||||
├─→ 8b: BO CRUD expansion ✅ CMS:`ce8e248` BO:`89f5241`
|
||||
├─→ 8c: FO Package pages ✅ FO:`d71d463`
|
||||
└─→ 8d: Proto cleanup ✅ CMS:`7554d70` FO:`40882c8` BO:`c96377a`
|
||||
└─→ 8e: Per-package reports ✅ CMS:`aaaf7fc` FO:`a956cb9` BO:`8be98ae`
|
||||
└─→ 8f: UI completion ✅ CMS:`dcd1135` FO:`3bffc13` BO:`e020354`
|
||||
└─→ مرحله ۵: تست + استقرار (۳ روز) ⬜
|
||||
|
||||
مسیر بحرانی: ۰→۱→۱.۵→۲→۳→۴→UI→۵ = ~۱۷ روز | انجامشده: ۰→8f (~۱۷ روز)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## مرحله ۰ — فیکس باگهای فوری ✅
|
||||
|
||||
> ✅ تکمیلشده | کامیت: `8b9c317` + `fe3edd1`
|
||||
|
||||
### ✅ وضعیت باگها (بررسی اولیه لازم)
|
||||
|
||||
| # | باگ | Handler | شرح فیکس |
|
||||
|---|------|---------|----------|
|
||||
| B1 | DiscountBalance شارژ نمیشود | `VerifyGoldenPackagePurchaseCommandHandler` | اضافه `DiscountBalance += Amount × 2` + WalletChangeLog |
|
||||
| B2 | UserPackagePurchase ساخته نمیشود | `VerifyGoldenPackagePurchaseCommandHandler` | ساخت record بعد verify موفق |
|
||||
| B3 | UserPackagePurchase ساخته نمیشود | `VerifyPackagePurchaseCommandHandler` | ساخت record بعد verify موفق |
|
||||
| B4 | UserPackagePurchase ساخته نمیشود | `VerifyBasePackagePaymentCommandHandler` | ساخت record بعد verify موفق |
|
||||
|
||||
#### دستور کار B1:
|
||||
```
|
||||
1. باز کردن VerifyGoldenPackagePurchaseCommandHandler.cs
|
||||
2. پیدا کردن جایی که Balance شارژ میشود
|
||||
3. اضافه کردن:
|
||||
wallet.DiscountBalance += command.Amount * 2;
|
||||
// + ساخت WalletChangeLog برای DiscountBalance
|
||||
4. تست: verify → چک DiscountBalance در DB
|
||||
```
|
||||
|
||||
#### دستور کار B2-B4 (الگوی مشترک):
|
||||
```
|
||||
1. بعد از verify موفق و شارژ wallet:
|
||||
var purchase = new UserPackagePurchase
|
||||
{
|
||||
UserId = userId,
|
||||
PackageId = packageId, // فعلاً BasePackageId = 4
|
||||
PurchaseDate = DateTime.UtcNow,
|
||||
Amount = amount,
|
||||
PurchaseMethod = purchaseMethod, // ZarinPal, BFF, etc.
|
||||
TransactionId = transactionId,
|
||||
IsVerified = true
|
||||
};
|
||||
_context.UserPackagePurchases.Add(purchase);
|
||||
2. تست: verify → چک UserPackagePurchases table
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## مرحله ۱ — زیرساخت (Domain + DB) ✅
|
||||
|
||||
> ✅ تکمیلشده | کامیت: `ae92ab8` (Phase 1) + `a9cd2fd` (Phase 1.5 Migration)
|
||||
|
||||
### T1.1 — بروزرسانی Package Entity (۱۱ فیلد جدید — v3)
|
||||
|
||||
**فایل:** `CMS/src/CMSMicroservice.Domain/Entities/Package.cs`
|
||||
|
||||
```diff
|
||||
+ public int SortOrder { get; set; }
|
||||
+ public bool IsActive { get; set; } = true;
|
||||
+ public bool IsBasePackage { get; set; }
|
||||
+ public bool SupportsDayaPurchase { get; set; }
|
||||
+ public bool SupportsDirectPurchase { get; set; } = true;
|
||||
+ 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; }
|
||||
```
|
||||
|
||||
**EF Config:** `PackageConfiguration.cs`
|
||||
- حداکثر یک `IsBasePackage = true` (Index filter)
|
||||
- Precision for decimal fields
|
||||
|
||||
### T1.2 — ایجاد PackageFeature Entity
|
||||
|
||||
**فایل جدید:** `CMS/src/CMSMicroservice.Domain/Entities/PackageFeature.cs`
|
||||
|
||||
```csharp
|
||||
public class PackageFeature : BaseAuditableEntity
|
||||
{
|
||||
public long PackageId { get; set; }
|
||||
public virtual Package Package { get; set; }
|
||||
public long ClubFeatureId { get; set; }
|
||||
public virtual ClubFeature ClubFeature { get; set; }
|
||||
public bool IsIncluded { get; set; } = true;
|
||||
}
|
||||
```
|
||||
|
||||
### T1.3-T1.6 — اضافه PackageId به entityها
|
||||
|
||||
| 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 (v3: ۷ ثابت)
|
||||
|
||||
**فایل:** `CMS/src/CMSMicroservice.Domain/Common/SystemConstants.cs`
|
||||
|
||||
```diff
|
||||
- public const long BasePackageAmount = 56_000_000;
|
||||
- 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;
|
||||
- // === v3: انتقال به Package entity ===
|
||||
- public const int CommissionMaxWeeklyBalancesPerLeg = 300;
|
||||
- public const int CommissionMaxNetworkLevel = 15;
|
||||
```
|
||||
|
||||
> ⚠️ **قبل از حذف:** grep تمام مصرفکنندهها → جایگزین با `Package.Property`
|
||||
> ⚠️ **v3:** `CommissionMaxWeeklyBalancesPerLeg` و `CommissionMaxNetworkLevel` هم باید per-package شوند
|
||||
|
||||
### T1.8 — Database Migration
|
||||
|
||||
```bash
|
||||
dotnet ef migrations add AddPackageBasedSystem
|
||||
```
|
||||
|
||||
**شامل:**
|
||||
- ستونهای جدید Package
|
||||
- جدول PackageFeatures
|
||||
- FKها در 4 entity
|
||||
- Unique constraint
|
||||
|
||||
### T1.9 — Data Migration Script
|
||||
|
||||
```sql
|
||||
-- 1. بروزرسانی پکیج فعلی (ID=4 → اضافه فیلدهای جدید)
|
||||
UPDATE "CMS"."Packages" SET
|
||||
"SortOrder" = 2,
|
||||
"IsActive" = true,
|
||||
"IsBasePackage" = true,
|
||||
"SupportsDayaPurchase" = true,
|
||||
"SupportsDirectPurchase" = true,
|
||||
"ActivationFee" = 25200000,
|
||||
"DiscountMultiplier" = 2.0,
|
||||
"MagicWalletMultiplier" = 2.5,
|
||||
-- v3: تنظیمات پورسانت
|
||||
"MaxBalancesPerLeg" = 300,
|
||||
"MaxNetworkLevel" = 15,
|
||||
"MagicWalletMaxDeposit" = 1000000000,
|
||||
"MagicWalletMaxCredit" = 2500000000
|
||||
WHERE "Id" = 4;
|
||||
|
||||
-- 2. Link existing data to base package
|
||||
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 (شامل فیلدهای v3)
|
||||
INSERT INTO "CMS"."Packages" (..., "MaxBalancesPerLeg", "MaxNetworkLevel",
|
||||
"MagicWalletMaxDeposit", "MagicWalletMaxCredit", ...)
|
||||
VALUES ('پکیج نقرهای', 5600000, ..., 30, 15, 100000000, 250000000, ...);
|
||||
```
|
||||
|
||||
### T1.10 — بروزرسانی Protoها
|
||||
|
||||
| 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;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## مرحله ۲ — منطق کسبوکار ✅
|
||||
|
||||
> ✅ تکمیلشده | کامیت: `8e5c7c5` (Phase 2) + `ccb938e` (Phase 3) + `0002a5a` (Phase 4)
|
||||
|
||||
### T2.1 — Generic Verify Handler
|
||||
|
||||
**هدف:** ادغام VerifyGolden + VerifyBase + VerifyGeneric → یک handler
|
||||
|
||||
**الگوریتم:**
|
||||
```
|
||||
1. دریافت TransactionId از request
|
||||
2. خواندن Transaction → PackageId → Package entity
|
||||
3. verify با درگاه (ZarinPal/BFF/...)
|
||||
4. اگر موفق:
|
||||
a. wallet.Balance += Package.Price
|
||||
b. wallet.DiscountBalance += Package.Price × Package.DiscountMultiplier
|
||||
c. ساخت WalletChangeLog (Balance)
|
||||
d. ساخت WalletChangeLog (DiscountBalance)
|
||||
e. ساخت UserPackagePurchase record
|
||||
f. اگر اولین خرید: JoinNetwork
|
||||
g. بروزرسانی ClubMembershipCycle.PackageId
|
||||
5. return success + receipt
|
||||
```
|
||||
|
||||
### T2.2 — Generic Purchase Handler
|
||||
|
||||
**هدف:** ادغام PurchaseGolden + PurchasePackage + InitiateBase → یک handler
|
||||
|
||||
**تغییرات:**
|
||||
- حذف فیلتر `Title.Contains("طلایی")`
|
||||
- حذف `BasePackageId = 4`
|
||||
- خواندن Package entity از DB بر اساس `request.PackageId`
|
||||
- Gateway URL + Amount از Package.Price
|
||||
|
||||
### T2.3-T2.4 — ActivateClubMembership بهبود
|
||||
|
||||
**تغییرات:**
|
||||
```diff
|
||||
- var features = await GetAllFeatureIds(); // همه فیچرها
|
||||
+ var features = await GetPackageFeatures(packageId); // فیچرهای پکیج
|
||||
|
||||
- membership.PackageAmount = SystemConstants.BasePackageAmount;
|
||||
+ membership.PackageAmount = package.Price;
|
||||
|
||||
- var activationFee = SystemConstants.ClubActivationFee;
|
||||
+ var activationFee = package.ActivationFee;
|
||||
```
|
||||
|
||||
### T2.5-T2.6 — Re-Purchase Logic
|
||||
|
||||
**EXIT Magic Mode — تغییرات:**
|
||||
```diff
|
||||
wallet.WalletMode = WalletMode.Normal;
|
||||
wallet.MagicCompletedAt = DateTime.UtcNow;
|
||||
cycle.MagicCompletedAt = DateTime.UtcNow;
|
||||
+ user.PackagePurchaseMethod = PackagePurchaseMethod.None;
|
||||
+ membership.IsActive = false;
|
||||
+ cycle.IsCurrentCycle = false;
|
||||
```
|
||||
|
||||
**Guard تغییرات:**
|
||||
```diff
|
||||
- if (user.PackagePurchaseMethod != PackagePurchaseMethod.None)
|
||||
- throw new RpcException("قبلاً پکیج خریداری شده");
|
||||
+ if (user.PackagePurchaseMethod != PackagePurchaseMethod.None
|
||||
+ && !HasCompletedMagicCycle(membership))
|
||||
+ throw new RpcException("چرخه جاری هنوز تکمیل نشده");
|
||||
```
|
||||
|
||||
### T2.7 — JWT Claims جدید
|
||||
|
||||
```diff
|
||||
claims.Add("HasPurchasedPackage", "true");
|
||||
+ claims.Add("CanRepurchase", HasCompletedMagicCycle(membership).ToString());
|
||||
+ claims.Add("PackageId", membership.PackageId?.ToString() ?? "");
|
||||
+ claims.Add("PackageTitle", package?.Title ?? "");
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## مرحله ۳ — محاسبه پورسانت (موازی با مرحله ۲) ✅
|
||||
|
||||
> ✅ تکمیلشده | کامیت: `607f791` + `7176fe4` | ⏱️ **۴ روز** | ریسک: بحرانی (مالی)
|
||||
|
||||
### T3.1-T3.2 — SPs + PackageId + پارامترهای داینامیک (🔄 v3)
|
||||
|
||||
```sql
|
||||
-- sp_CalculateWeeklyBalances — v3: حذف hardcode
|
||||
ALTER PROCEDURE sp_CalculateWeeklyBalances
|
||||
@WeekDefinitionId BIGINT,
|
||||
@PackageId BIGINT,
|
||||
@MaxBalancesPerLeg INT, -- v3: از Package entity (نه ۳۰۰ hardcode!)
|
||||
@MaxNetworkLevel INT -- v3: از Package entity (نه ۱۵ hardcode!)
|
||||
AS
|
||||
BEGIN
|
||||
-- فیلتر: فقط کاربرانی که این پکیج را دارند
|
||||
-- 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;
|
||||
END;
|
||||
```
|
||||
|
||||
### T3.3 — Loop Service (🔄 v3: ارسال تنظیمات پکیج)
|
||||
|
||||
```csharp
|
||||
// WeeklyCommissionCalculationService.cs
|
||||
var activePackages = await _context.Packages
|
||||
.Where(p => p.IsActive && !p.IsDeleted)
|
||||
.ToListAsync();
|
||||
|
||||
foreach (var package in activePackages)
|
||||
{
|
||||
_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.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 باید:**
|
||||
> 1. ابتدا در staging با داده واقعی تست شود
|
||||
> 2. نتایج قبل و بعد مقایسه شوند
|
||||
> 3. Rollback plan آماده باشد
|
||||
> 4. در production ابتدا read-only اجرا شود (بدون commit)
|
||||
|
||||
---
|
||||
|
||||
## مرحله ۷ — Migration + Cleanup (سهگانه) ✅
|
||||
|
||||
> ✅ تکمیلشده | ⏱️ **۱ روز** | ریسک: پایین
|
||||
|
||||
### فاز 7a — Cosmetic Cleanup ✅
|
||||
|
||||
> کامیت: CMS `469d97b` | FO `b82cac4` | BO `f1b0085`
|
||||
|
||||
**CMS:**
|
||||
- حذف orphaned `PurchasePackage` handler (۳ فایل، بدون caller)
|
||||
- فیکس doc-comments: `طلایی` → `پکیج` در ۶ فایل (enums, entities, handlers)
|
||||
|
||||
**FrontOffice:**
|
||||
- حذف hardcoded `پکیج طلایی` از `MyPackages.razor` و `Packages.razor`
|
||||
- اضافه `PackageTitle` property به `UserPackageStatusDto` record
|
||||
|
||||
**BackOffice:**
|
||||
- تغییر label `پکیج طلایی` → `خرید پکیج` در `UserNetworkInfo.razor`
|
||||
|
||||
### فاز 7b — FrontOffice RPC Migration ✅
|
||||
|
||||
> کامیت: CMS `161f796` | FO `71f391a`
|
||||
|
||||
**CMS:**
|
||||
- `CustomerPurchasePackage`: embed `orderId` در callback URL قبل از ارسال به درگاه
|
||||
- `$"{request.CallbackUrl}{separator}orderId={purchase.Id}"`
|
||||
|
||||
**FrontOffice:**
|
||||
- `Profile/Index.razor.cs`: مهاجرت `InitiateBasePackagePaymentAsync` → `CustomerPurchasePackageAsync`
|
||||
- `Profile/PaymentCallback.razor`: مهاجرت `VerifyBasePackagePaymentAsync` → `CustomerVerifyPackagePurchaseAsync`
|
||||
- پارامترهای جدید: `PackageId`, `CallbackUrl`, `PurchaseMethod`, `OrderId`, `Authority`, `Status`
|
||||
|
||||
### فاز 7c — Delete Deprecated Handlers ✅
|
||||
|
||||
> کامیت: CMS `8446e0e` (14 فایل، 1125 حذف)
|
||||
|
||||
**حذف ۴ handler CQRS (۱۲ فایل):**
|
||||
- `PurchaseGoldenPackage/` (Command, Handler, Validator)
|
||||
- `VerifyGoldenPackagePurchase/` (Command, Handler, Validator)
|
||||
- `InitiateBasePackagePayment/` (Command, Handler, Validator)
|
||||
- `VerifyBasePackagePayment/` (Command, Handler, Validator)
|
||||
|
||||
**Cleanup:**
|
||||
- `PackageService.cs`: حذف ۴ gRPC override method (proto RPCs حالا auto-throw `Unimplemented`)
|
||||
- `PackageProfile.cs`: حذف ۶ Mapster mapping block + ۴ using directive
|
||||
- Build: 0 Error ✅
|
||||
|
||||
---
|
||||
|
||||
## مرحله ۸ — FrontOffice Checkout + NuGet
|
||||
|
||||
> 🔄 در حال اجرا | فاز 8a تکمیل ✅
|
||||
|
||||
### فاز 8a — Checkout Wire-up ✅
|
||||
|
||||
> کامیت: FO `0bbc11e`
|
||||
|
||||
**Checkout.razor.cs:**
|
||||
- حذف dead code: `ProcessPayment()` از flow قدیمی `TransactionsContract + UserOrderContract` استفاده میکرد
|
||||
- Rewrite با `CustomerPurchasePackageAsync` (مثل Profile/Index.razor.cs)
|
||||
- Callback URL → `/profile/payment-callback` (از صفحه verify موجود استفاده مجدد)
|
||||
- حذف DI بلااستفاده: `UserOrderContract`, `TransactionContract`
|
||||
- حذف usings: `Transactions`, `UserOrder`, `WellKnownTypes`
|
||||
|
||||
**Profile/Index.razor.cs (cosmetic):**
|
||||
- Rename `basePackage` → `selectedPackage`, `tempCallbackUrl` → `callbackUrl`
|
||||
|
||||
### فاز 8b — BackOffice Package CRUD Expansion ✅
|
||||
|
||||
> کامیت: CMS `ce8e248` | BO `89f5241` (7 فایل، +138/-23)
|
||||
|
||||
**NuGet Rebuild:**
|
||||
- Proto version bump: `0.0.184` → `0.0.185`
|
||||
- Pack و deploy به local feed (`/nupkg`)
|
||||
- BackOffice NuGet.config: اضافه local feed source
|
||||
|
||||
**CreateDialog.razor (۱۲ فیلد جدید):**
|
||||
- `SortOrder` — MudNumericField<int> ترتیب نمایش
|
||||
- `ActivationFee` — MudNumericField<long> هزینه فعالسازی
|
||||
- `DiscountMultiplier` — MudNumericField<double> ضریب تخفیف
|
||||
- `MagicWalletMultiplier` — MudNumericField<double> ضریب کیف پول جادویی
|
||||
- `MagicWalletMaxDeposit` — MudNumericField<long> سقف واریز جادویی
|
||||
- `MagicWalletMaxCredit` — MudNumericField<long> سقف اعتبار جادویی
|
||||
- `MaxBalancesPerLeg` — MudNumericField<int> حداکثر تعادل هر پا
|
||||
- `MaxNetworkLevel` — MudNumericField<int> حداکثر سطح شبکه
|
||||
- `IsActive` — MudCheckBox فعال/غیرفعال
|
||||
- `IsBasePackage` — MudCheckBox پکیج پایه
|
||||
- `SupportsDirectPurchase` — MudCheckBox پرداخت مستقیم
|
||||
- `SupportsDayaPurchase` — MudCheckBox اعتبار دایا
|
||||
|
||||
**UpdateDialog.razor:** همان ۱۲ فیلد
|
||||
|
||||
**PackageMainPage Grid (۴ ستون جدید):**
|
||||
- `Price` — فرمتشده با N0
|
||||
- `SortOrder` — ترتیب
|
||||
- `IsActive` — MudChip فعال/غیرفعال
|
||||
- `IsBasePackage` — MudChip پایه/عادی
|
||||
|
||||
**سایر:**
|
||||
- Dialog size: `MaxWidth.Small` → `MaxWidth.Medium`
|
||||
- CreateNew defaults: `IsActive=true, DiscountMultiplier=2.0, MagicWalletMultiplier=2.5, ...`
|
||||
- فیکس `HasPurchasedGoldenPackage` → `HasPurchasedPackage` در `UserNetworkInfo.razor`
|
||||
|
||||
### فاز 8c — FrontOffice Package Pages ✅
|
||||
|
||||
> کامیت: FO `d71d463` (5 فایل، +109/-56)
|
||||
|
||||
**NuGet:** `0.0.182` → `0.0.185` + local feed source
|
||||
|
||||
**PackageDetail.razor.cs:**
|
||||
- مهاجرت `GetPackageAsync` (admin RPC) → `GetCustomerPackageDetailsAsync` (customer RPC)
|
||||
- Features: از hardcoded ثابت → از `PackageFeature` API داینامیک
|
||||
- Specifications: از hardcoded → از `PackageFeature.IsHighlighted` API
|
||||
- حذف ۵ hardcoded feature string + ۴ hardcoded specification
|
||||
|
||||
**PackageService.cs:**
|
||||
- `PackageDto`: اضافه ۸ فیلد جدید (ActivationFee, DiscountMultiplier, MagicWalletMultiplier, etc.)
|
||||
- `GetAllPackagesAsync`: مپ فیلدهای جدید از `CustomerPackageModel`
|
||||
- `GetUserPackageStatusAsync`: از stub → اتصال واقعی به `GetUserPackageStatusAsync` RPC
|
||||
|
||||
**Packages.razor:**
|
||||
- Un-exclude از build (حذف `<Content Remove>` + `<Compile Remove>`)
|
||||
- جایگزینی ۳ feature bullet hardcoded → dynamic features:
|
||||
- `SupportsDirectPurchase` → پرداخت مستقیم
|
||||
- `SupportsDayaPurchase` → پرداخت با اعتبار دایا
|
||||
- `DiscountMultiplier` → ضریب تخفیف: X.Xx
|
||||
- `MagicWalletMultiplier` → کیف پول جادویی: X.Xx
|
||||
- `IsBasePackage` → پکیج پایه ⭐
|
||||
|
||||
### فاز 8d — Proto Cleanup ✅
|
||||
|
||||
> کامیت: CMS `7554d70` (2 فایل، -103) | FO `40882c8` | BO `c96377a`
|
||||
|
||||
**حذف ۴ deprecated RPC:**
|
||||
- `PurchaseGoldenPackage` — جایگزین: `CustomerPurchasePackage`
|
||||
- `VerifyGoldenPackagePurchase` — جایگزین: `CustomerVerifyPackagePurchase`
|
||||
- `InitiateBasePackagePayment` — جایگزین: `CustomerPurchasePackage`
|
||||
- `VerifyBasePackagePayment` — جایگزین: `CustomerVerifyPackagePurchase`
|
||||
|
||||
**حذف ۸ deprecated message type:**
|
||||
- `PurchaseGoldenPackageRequest` / `PurchaseGoldenPackageResponse`
|
||||
- `VerifyGoldenPackagePurchaseRequest` / `VerifyGoldenPackagePurchaseResponse`
|
||||
- `InitiateBasePackagePaymentRequest` / `InitiateBasePackagePaymentResponse`
|
||||
- `VerifyBasePackagePaymentRequest` / `VerifyBasePackagePaymentResponse`
|
||||
|
||||
**حفظ شده:** `GetUserPackageStatus` RPC + messages (هنوز در استفاده)
|
||||
|
||||
**NuGet:** `0.0.185` → `0.0.186` (همه ریپوها)
|
||||
|
||||
### فاز 8e — Per-Package Commission Reports ✅
|
||||
|
||||
> کامیت: CMS `aaaf7fc` | FO `a956cb9` | BO `8be98ae`
|
||||
|
||||
**Proto (commission.proto):**
|
||||
- اضافه `package_id` فیلتر به ۴ request message: `GetUserCommissionPayoutsRequest`, `GetUserWeeklyBalancesRequest`, `GetMyCommissionPayoutsRequest`, `GetMyWeeklyBalancesRequest`
|
||||
- اضافه `package_id` + `package_title` به ۴ response model: `UserCommissionPayoutModel`, `UserWeeklyBalanceModel`, `CustomerCommissionPayoutModel`, `CustomerWeeklyBalanceModel`
|
||||
|
||||
**CMS (12 فایل):**
|
||||
- ۴ Query record: اضافه `public long? PackageId { get; init; }`
|
||||
- ۴ Handler: اضافه `.Include(x => x.Package)` + فیلتر `Where(x => x.PackageId == request.PackageId.Value)` + map `PackageId`/`PackageTitle`
|
||||
- ۳ Response DTO: اضافه `PackageId` + `PackageTitle`
|
||||
- `CommissionProfile.cs`: تنظیم mappingهای Mapster برای admin + customer
|
||||
|
||||
**BackOffice (6 فایل):**
|
||||
- کامپوننت جدید `PackageSelect.razor/.cs`: dropdown قابل استفاده مجدد با بارگذاری پکیجها از `PackageContract`
|
||||
- `UserPayouts.razor/.cs`: فیلتر PackageSelect + ستون پکیج با MudChip
|
||||
- `BalancesReport.razor`: فیلتر PackageSelect + ستون پکیج با MudChip + mapping PackageTitle
|
||||
|
||||
**FrontOffice (7 فایل):**
|
||||
- `CommissionDtos.cs`: اضافه `PackageId` + `PackageTitle` به `CommissionPayoutDto` و `WeeklyBalanceDto`
|
||||
- `CommissionService.cs`: اضافه پارامتر `packageId` به `GetMyCommissionPayoutsAsync` و `GetMyWeeklyBalanceAsync`
|
||||
- `CommissionDashboardPage.razor/.cs`: فیلتر dropdown پکیج + ستون «پکیج» با MudChip (دسکتاپ + موبایل)
|
||||
- `WeeklyBalancePage.razor/.cs`: فیلتر MudSelect پکیج + نمایش MudChip پکیج در بخش اطلاعات هفته
|
||||
|
||||
**NuGet:** `0.0.186` → `0.0.187` (همه ریپوها)
|
||||
|
||||
### فاز 8f — UI Completion (T4.2 + T4.3 + T4.13 + F2 + F3) ✅
|
||||
|
||||
> کامیت: CMS `dcd1135` | FO `3bffc13` | BO `e020354`
|
||||
|
||||
**CMS (T4.13 — PackageFeature CRUD):**
|
||||
- Proto: اضافه `repeated int64 feature_ids` به ۴ message (Create/Update Request, Get/GetAll Response)
|
||||
- `CreateNewPackageCommand/Handler`: sync FeatureIds → ساخت `PackageFeature` records
|
||||
- `UpdatePackageCommand/Handler`: sync FeatureIds → حذف قبلیها + ساخت جدید
|
||||
- `GetPackage/GetAllPackageByFilter`: اضافه `.Include(x => x.PackageFeatures)` + map FeatureIds
|
||||
|
||||
**BackOffice (F2 + T4.13):**
|
||||
- **F2:** کامپوننت جدید `ChangeParentDialog.razor/.cs` — مودال جابجایی در شبکه با NewParentId, NewLeg, Reason
|
||||
- **F2:** دکمه «تغییر والد» در `UserNetworkInfo.razor`
|
||||
- **T4.13:** checkbox matrix فیچرها در `CreateDialog` و `UpdateDialog` — بارگذاری از `ConfigurationContractClient`
|
||||
|
||||
**FrontOffice (T4.2 + T4.3 + F3):**
|
||||
- **T4.2:** پرداخت شرطی در `Checkout.razor` بر اساس `SupportsDirectPurchase`/`SupportsDayaPurchase`
|
||||
- **T4.3:** منطق خرید مجدد در `MyPackages.razor` — بارگذاری `MagicWalletStatus` + CTA شرطی + progress bar
|
||||
- **F3:** نمایش PV سفارش در `Store/OrderDetail.razor` — `CalculateOrderPVAsync` + جدول PV هر محصول
|
||||
|
||||
**NuGet:** `0.0.187` → `0.0.188` (همه ریپوها)
|
||||
|
||||
---
|
||||
|
||||
## مرحله ۴ — UI (FrontOffice + BackOffice)
|
||||
|
||||
> ⏱️ **۵ روز** (v3: +۲) | وابستگی: مرحله ۲ + ۳ | ریسک: متوسط
|
||||
|
||||
### T4.1 — کاشیهای پکیج داینامیک
|
||||
|
||||
**فایل:** `FrontOffice/src/.../Pages/Package/Packages.razor`
|
||||
|
||||
```razor
|
||||
@* قبل: hardcoded *@
|
||||
@* بعد: *@
|
||||
@foreach (var package in _packages.OrderBy(p => p.SortOrder))
|
||||
{
|
||||
<PackageCard Package="@package"
|
||||
OnPurchase="StartPurchase"
|
||||
ShowFeatures="true"
|
||||
ShowPV="true" />
|
||||
}
|
||||
```
|
||||
|
||||
### T4.2 — مودال پرداخت شرطی ✅ FO:`3bffc13`
|
||||
|
||||
**پیادهسازی:**
|
||||
- `Checkout.razor.cs`: اضافه `PackageService` injection، بارگذاری پکیجها با `GetAllPackagesAsync()`
|
||||
- `Checkout.razor`: دکمههای پرداخت شرطی بر اساس `SupportsDirectPurchase` و `SupportsDayaPurchase`
|
||||
- اضافه `DayaLoanPayment()` method + alert برای عدم وجود روش پرداخت
|
||||
- `Pack` record: اضافه `SupportsDirectPurchase` و `SupportsDayaPurchase`
|
||||
|
||||
### T4.3 — MyPackages + Re-Purchase ✅ FO:`3bffc13`
|
||||
|
||||
**پیادهسازی:**
|
||||
- `MyPackages.razor.cs`: بارگذاری `MagicWalletStatus` از `WalletService.GetMagicWalletStatusAsync()`
|
||||
- فرمول خرید مجدد: `WalletMode == 0 && PurchaseCycleCount >= 1 && MagicRemainingDeposit == 0`
|
||||
- `MyPackages.razor`: CTA شرطی «🎉 چرخه جادویی تکمیل شد!» + دکمه «خرید پکیج جدید»
|
||||
- بخش پیشرفت کیف پول جادویی: مبلغ واریزی، باقیمانده، اعتبار دریافتی + progress bar
|
||||
|
||||
### T4.8 — FrontOffice: CommissionDashboard per-package (🆕 v3) ✅ FO:`a956cb9`
|
||||
|
||||
**پیادهسازی:**
|
||||
- `CommissionDtos.cs`: اضافه `PackageId` + `PackageTitle` به `CommissionPayoutDto` و `WeeklyBalanceDto`
|
||||
- `CommissionService.cs`: اضافه پارامتر `packageId` به `GetMyCommissionPayoutsAsync` و `GetMyWeeklyBalanceAsync`
|
||||
- `CommissionDashboardPage.razor`: اضافه dropdown فیلتر پکیج + ستون «پکیج» با MudChip + نمایش پکیج در card موبایل
|
||||
- `CommissionDashboardPage.razor.cs`: inject `PackageService`، فیلد `_filterPackageId`، بارگذاری لیست پکیجها
|
||||
|
||||
### T4.9 — FrontOffice: WeeklyBalance per-package (🆕 v3) ✅ FO:`a956cb9`
|
||||
|
||||
**پیادهسازی:**
|
||||
- `WeeklyBalancePage.razor`: اضافه MudSelect فیلتر پکیج کنار WeekSelector + نمایش MudChip پکیج در بخش اطلاعات هفته
|
||||
- `WeeklyBalancePage.razor.cs`: inject `PackageService`، فیلد `_filterPackageId`، ارسال به `CommissionService.GetMyWeeklyBalanceAsync`
|
||||
|
||||
### T4.10-T4.12 — BackOffice: گزارشهای پورسانت per-package (🆕 v3) ✅ BO:`8be98ae`
|
||||
|
||||
**پیادهسازی:**
|
||||
- کامپوننت جدید `PackageSelect.razor/.cs`: dropdown قابل استفاده مجدد با بارگذاری پکیجها از `PackageContract`
|
||||
- `UserPayouts.razor/.cs`: فیلتر PackageSelect + ستون پکیج با MudChip
|
||||
- `BalancesReport.razor`: فیلتر PackageSelect + ستون پکیج با MudChip + mapping `PackageTitle`
|
||||
|
||||
### T4.13 — BackOffice: Package CRUD + Quick Access فیچرها (🆕 v3) ✅ CMS:`dcd1135` BO:`e020354`
|
||||
|
||||
**CMS پیادهسازی:**
|
||||
- Proto: اضافه `repeated int64 feature_ids` به ۴ message (Create/Update Request, Get/GetAll Response)
|
||||
- `CreateNewPackageCommand/Handler`: اضافه `FeatureIds` + ساخت `PackageFeature` records
|
||||
- `UpdatePackageCommand/Handler`: اضافه `FeatureIds` + sync (حذف قبلیها + ساخت جدید)
|
||||
- `GetPackageQueryHandler`: اضافه `.Include(x => x.PackageFeatures)` + map `FeatureIds`
|
||||
- `GetAllPackageByFilterQueryHandler`: اضافه `.Include(x => x.PackageFeatures)` قبل از `PaginatedListAsync`
|
||||
- NuGet: `0.0.187` → `0.0.188`
|
||||
|
||||
**BO پیادهسازی:**
|
||||
- `CreateDialog.razor/.cs`: بارگذاری `ClubFeatures` از `ConfigurationContractClient` + checkbox matrix
|
||||
- `UpdateDialog.razor/.cs`: همان pattern + pre-populate از `Model.FeatureIds`
|
||||
- Mapster: `Adapt<UpdatePackageRequest>()` خودکار `FeatureIds` را map میکند
|
||||
|
||||
---
|
||||
|
||||
## مرحله ۵ — تست و استقرار
|
||||
|
||||
> ⏱️ **۳ روز** (v3: +۱) | وابستگی: مرحله ۴
|
||||
|
||||
### Checklist تست
|
||||
|
||||
**خرید + فعالسازی:**
|
||||
- [ ] خرید پکیج نقرهای (ZarinPal)
|
||||
- [ ] خرید پکیج پایه (ZarinPal)
|
||||
- [ ] خرید پکیج پایه (Daya Loan)
|
||||
- [ ] خرید پکیج پایه (Manual Payment)
|
||||
- [ ] فعالسازی باشگاه با پکیج نقرهای → فیچرهای محدود
|
||||
- [ ] فعالسازی باشگاه با پکیج پایه → همه فیچرها
|
||||
|
||||
**چرخه Magic + خرید مجدد:**
|
||||
- [ ] تکمیل چرخه Magic → ریست وضعیت
|
||||
- [ ] خرید مجدد بعد تکمیل چرخه (همان پکیج)
|
||||
- [ ] خرید مجدد با پکیج متفاوت (پایه → نقرهای)
|
||||
|
||||
**پورسانت per-package (v3):**
|
||||
- [ ] Commission Pool جداگانه هر پکیج
|
||||
- [ ] تعادل 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)
|
||||
- [x] UI: کاشیهای داینامیک FrontOffice
|
||||
- [x] UI: ماتریس فیچر + Quick Access BackOffice
|
||||
- [ ] Rollback: بدون data loss
|
||||
|
||||
---
|
||||
|
||||
## 📅 تقویم پیشنهادی (v3)
|
||||
|
||||
| هفته | روز | تسک |
|
||||
|------|-----|------|
|
||||
| هفته ۱ | روز ۱ | مرحله ۰: فیکس ۴ باگ |
|
||||
| | روز ۲-۳ | مرحله ۱: 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 |
|
||||
|
||||
---
|
||||
|
||||
## 🔗 ارجاعات
|
||||
|
||||
| مستند | محتوا |
|
||||
|-------|-------|
|
||||
| [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 |
|
||||
|
||||
---
|
||||
|
||||
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۱۰ — فاز ۰-۸f تکمیل (۲۷ کامیت: ۱۷ CMS + ۷ FO + ۵ BO) | NuGet v0.0.188 | T4.2+T4.3+T4.13+F2+F3 کامل | باقیمانده: تست + deploy*
|
||||
@@ -0,0 +1,494 @@
|
||||
# 🏗️ تحلیل تحول پکیجبیس — تاثیر بر تجربه کاربر (UX)
|
||||
|
||||
> **وضعیت:** در حال تحلیل
|
||||
> **تاریخ:** ۱۴۰۴/۱۲/۰۶
|
||||
> **پیشنیاز:** [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) v2
|
||||
> **هدف:** مستندسازی تاثیر تغییر رویکرد پکیجبیس بر تجربه مشتری و ادمین در فرانتها
|
||||
|
||||
---
|
||||
|
||||
## فهرست
|
||||
|
||||
1. [چشمانداز کلی](#۱-چشمانداز-کلی)
|
||||
2. [تجربه مشتری (FrontOffice) — قبل و بعد](#۲-تجربه-مشتری-frontoffice--قبل-و-بعد)
|
||||
3. [تجربه ادمین (BackOffice) — قبل و بعد](#۳-تجربه-ادمین-backoffice--قبل-و-بعد)
|
||||
4. [تسکهای تحول — مرحلهبهمرحله](#۴-تسکهای-تحول--مرحلهبهمرحله)
|
||||
5. [پیشبینی نیازمندیهای آینده](#۵-پیشبینی-نیازمندیهای-آینده)
|
||||
6. [ماتریس تاثیرگذاری بر صفحات](#۶-ماتریس-تاثیرگذاری-بر-صفحات)
|
||||
|
||||
---
|
||||
|
||||
## ۱. چشمانداز کلی
|
||||
|
||||
### فلسفه تغییر
|
||||
|
||||
| بُعد | **فعلی (تکپکیج)** | **هدف (چندپکیج)** |
|
||||
|------|-------------------|--------------------|
|
||||
| **مدل قیمتی** | فقط ۵۶M تومان — "همه یا هیچ" | سطوح متنوع (نقرهای ۵.۶M, پایه ۵۶M, ...) — "ورود تدریجی" |
|
||||
| **تجربه ورود** | سنگین — کاربر باید ۵۶M بپردازد | سبک — شروع از ۵.۶M و ارتقا بعدی |
|
||||
| **چرخه عمر** | یکبار خرید → برای همیشه | چندبار خرید → هر چرخه Magic Wallet |
|
||||
| **فیچرها** | ثابت — همه فیچرها برای همه | پویا — هر پکیج فیچرهای خودش |
|
||||
| **کمیسیون** | یک Pool مشترک | Pool جداگانه هر پکیج |
|
||||
| **مدیریت** | hardcoded — تغییر = deploy | داینامیک — ادمین از پنل تغییر میدهد |
|
||||
|
||||
### چه کسانی تاثیر میبینند؟
|
||||
|
||||
```
|
||||
👤 مشتری (FrontOffice):
|
||||
├── ثبتنامکننده جدید: گزینههای بیشتر → تصمیمگیری آسانتر
|
||||
├── مشتری فعال: دکمه "ارتقا" + "خرید مجدد"
|
||||
└── مشتری Magic: نمایش پیشرفت چرخه + آمادهسازی خرید بعدی
|
||||
|
||||
👔 ادمین (BackOffice):
|
||||
├── مدیر محصول: CRUD پکیج + ماتریس فیچر
|
||||
├── مدیر مالی: Commission Pool جداگانه + گزارشها
|
||||
└── پشتیبان: فعالسازی دستی با انتخاب پکیج
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۲. تجربه مشتری (FrontOffice) — قبل و بعد
|
||||
|
||||
### ۲.۱ صفحه لیست پکیجها (`Packages.razor`)
|
||||
|
||||
#### قبل (فعلی):
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ پکیج طلایی │
|
||||
│ ──────────── │
|
||||
│ ✅ دسترسی به باشگاه مشتریان │
|
||||
│ ✅ کیفپول جادویی │
|
||||
│ ✅ فروشگاه تخفیفی │
|
||||
│ │
|
||||
│ 💰 ۵۶,۰۰۰,۰۰۰ تومان │
|
||||
│ │
|
||||
│ [خرید پکیج] │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### بعد (پکیجبیس):
|
||||
```
|
||||
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
|
||||
│ 🥈 پکیج نقرهای │ │ 🏆 پکیج پایه │ │ 💎 پکیج ویژه │
|
||||
│ ──────────── │ │ ──────────── │ │ ──────────── │
|
||||
│ ✅ باشگاه مشتریان │ │ ✅ باشگاه مشتریان │ │ ✅ باشگاه مشتریان │
|
||||
│ ✅ کیفپول جادویی │ │ ✅ کیفپول جادویی │ │ ✅ کیفپول جادویی │
|
||||
│ ❌ فروشگاه تخفیفی │ │ ✅ فروشگاه تخفیفی │ │ ✅ فروشگاه تخفیفی │
|
||||
│ ❌ پشتیبانی اختصاصی │ │ ❌ پشتیبانی اختصاصی │ │ ✅ پشتیبانی اختصاصی │
|
||||
│ │ │ │ │ │
|
||||
│ 💰 ۵,۶۰۰,۰۰۰ تومان │ │ 💰 ۵۶,۰۰۰,۰۰۰ تومان │ │ 💰 ??? تومان │
|
||||
│ │ │ ⭐ محبوبترین │ │ 🆕 بزودی │
|
||||
│ [خرید] [جزئیات] │ │ [خرید] [جزئیات] │ │ [در انتظار] │
|
||||
│ ────────────────── │ │ ────────────────── │ │ ────────────────── │
|
||||
│ 📊 PV: 5,600,000 │ │ 📊 PV: 56,000,000 │ │ │
|
||||
│ 🎁 هدیه: 11,200,000 │ │ 🎁 هدیه: 112,000,000 │ │ │
|
||||
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘
|
||||
```
|
||||
|
||||
**تغییرات کلیدی:**
|
||||
- کاشیها از API میآیند (نه hardcoded)
|
||||
- فیچرهای هر پکیج از `PackageFeature` خوانده میشود
|
||||
- نمایش PV (Point Value) برای هر پکیج
|
||||
- نمایش Gift Value (= `Price × DiscountMultiplier`)
|
||||
- دکمههای شرطی: دایا فقط برای پکیجهای `SupportsDayaPurchase`
|
||||
- Badge «محبوبترین» / «ارزانترین» بر اساس `SortOrder`
|
||||
|
||||
### ۲.۲ صفحه پکیجهای من (`MyPackages.razor`)
|
||||
|
||||
#### قبل:
|
||||
```
|
||||
وضعیت عضویت: فعال ✅
|
||||
پکیج: طلایی
|
||||
تاریخ فعالسازی: ۱۴۰۳/۰۹/۱۵
|
||||
```
|
||||
|
||||
#### بعد:
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 📦 پکیج فعال: پکیج پایه │
|
||||
│ ──────────── │
|
||||
│ وضعیت: فعال ✅ | چرخه: ۲ | مدت: ۱۸۰ روز │
|
||||
│ │
|
||||
│ ┌──── کیفپول جادویی ────┐ │
|
||||
│ │ موجودی: ۱۲,۳۰۰,۰۰۰ │ │
|
||||
│ │ شارژ: ۴۳۵,۰۰۰,۰۰۰ │ │
|
||||
│ │ سقف: ۱,۰۰۰,۰۰۰,۰۰۰ │ │
|
||||
│ │ ████████░░░░ ۴۳.۵% │ │
|
||||
│ └─────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌──── PV انباشته ────┐ │
|
||||
│ │ PV کل: ۸۹,۶۰۰,۰۰۰ │ │
|
||||
│ │ آخرین سفارش: ۴.۲M │ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
│ ❌ چرخه جادویی تکمیل نشده — هنوز امکان خرید مجدد نیست │
|
||||
│ ───── یا ───── │
|
||||
│ ✅ چرخه جادویی تکمیل شد! [خرید پکیج جدید] │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
┌─── تاریخچه چرخهها ───┐
|
||||
│ چرخه ۱: پایه — ۱۴۰۳/۰۹ تا ۱۴۰۴/۰۳ — ✅ تکمیل │
|
||||
│ چرخه ۲: پایه — ۱۴۰۴/۰۳ تا ادامه دارد — 🔄 فعال │
|
||||
└────────────────────────┘
|
||||
```
|
||||
|
||||
**تغییرات کلیدی:**
|
||||
- نمایش شماره چرخه و نوع پکیج
|
||||
- نوار پیشرفت Magic Wallet (چقدر تا تکمیل چرخه)
|
||||
- PV انباشته (از `CalculateOrderPV`)
|
||||
- دکمه شرطی «خرید مجدد» (فقط بعد تکمیل چرخه)
|
||||
- تاریخچه چرخهها (از `ClubMembershipCycle`)
|
||||
|
||||
### ۲.۳ صفحه چکاوت (`Checkout.razor`)
|
||||
|
||||
#### قبل:
|
||||
```
|
||||
سبد خرید:
|
||||
محصول A × 2 = ۲,۰۰۰,۰۰۰ تومان
|
||||
مالیات (۹%): ۱۸۰,۰۰۰ تومان
|
||||
────────────────
|
||||
جمع: ۲,۱۸۰,۰۰۰ تومان
|
||||
```
|
||||
|
||||
#### بعد:
|
||||
```
|
||||
سبد خرید:
|
||||
محصول A × 2 = ۲,۰۰۰,۰۰۰ تومان
|
||||
مالیات (۹%): ۱۸۰,۰۰۰ تومان
|
||||
────────────────
|
||||
جمع: ۲,۱۸۰,۰۰۰ تومان
|
||||
|
||||
📊 PV این سفارش: ۲,۰۰۰,۰۰۰ ← جدید
|
||||
💎 PV انباشته: ۹۱,۶۰۰,۰۰۰ ← جدید
|
||||
```
|
||||
|
||||
### ۲.۴ پرداخت پکیج — مودال خرید
|
||||
|
||||
#### قبل:
|
||||
```
|
||||
┌─── خرید پکیج طلایی ───┐
|
||||
│ │
|
||||
│ مبلغ: ۵۶,۰۰۰,۰۰۰ تومان │
|
||||
│ │
|
||||
│ [پرداخت آنلاین] │
|
||||
│ [اقساط دایا] │
|
||||
│ [پرداخت دستی] │
|
||||
└──────────────────────────┘
|
||||
```
|
||||
|
||||
#### بعد:
|
||||
```
|
||||
┌─── خرید پکیج نقرهای ───┐ ┌─── خرید پکیج پایه ───┐
|
||||
│ │ │ │
|
||||
│ مبلغ: ۵,۶۰۰,۰۰۰ تومان │ │ مبلغ: ۵۶,۰۰۰,۰۰۰ تومان│
|
||||
│ │ │ │
|
||||
│ سهم باشگاه: ۲,۵۲۰,۰۰۰ │ │ سهم باشگاه: ۲۵,۲۰۰,۰۰│
|
||||
│ شارژ کیفپول: ۵,۶۰۰,۰۰۰ │ │ شارژ کیفپول: ۵۶,۰۰۰,۰│
|
||||
│ هدیه تخفیفی: ۱۱,۲۰۰,۰۰۰ │ │ هدیه تخفیفی: ۱۱۲,۰۰۰,۰│
|
||||
│ │ │ │
|
||||
│ [پرداخت آنلاین] ✅ │ │ [پرداخت آنلاین] ✅ │
|
||||
│ [اقساط دایا] ❌ ندارد │ │ [اقساط دایا] ✅ │
|
||||
│ [پرداخت دستی] ✅ │ │ [پرداخت دستی] ✅ │
|
||||
└────────────────────────────┘ └────────────────────────┘
|
||||
```
|
||||
|
||||
**تغییرات کلیدی:**
|
||||
- نمایش breakdown مالی: سهم باشگاه + شارژ کیفپول + هدیه تخفیفی
|
||||
- دکمههای پرداخت شرطی بر اساس `SupportsDayaPurchase` / `SupportsDirectPurchase`
|
||||
- متن قرارداد داینامیک بر اساس پکیج انتخابشده
|
||||
|
||||
### ۲.۵ صفحه تنظیمات مشتری (`Settings.razor`) — جدید
|
||||
|
||||
```
|
||||
┌─── تنظیمات اعلانها ───┐
|
||||
│ │
|
||||
│ 📧 اعلان ایمیل: [✅] │
|
||||
│ 📱 اعلان SMS: [✅] │
|
||||
│ 🔔 اعلان Push: [❌] │
|
||||
│ │
|
||||
│ [ذخیره تغییرات] │
|
||||
└──────────────────────────┘
|
||||
```
|
||||
> وصل به RPC: `UpdateCustomerSettings`
|
||||
|
||||
### ۲.۶ تاریخچه سفارشات — دکمه تکرار
|
||||
|
||||
```
|
||||
┌─── تاریخچه سفارشات ────────────────────────────────────────┐
|
||||
│ # │ تاریخ │ مبلغ │ وضعیت │ PV │ عملیات │
|
||||
│───┼────────────┼────────────┼───────────┼───────────┼────────│
|
||||
│ 1 │ ۱۴۰۴/۱۱/۰۲│ ۴,۲۰۰,۰۰۰ │ تحویل ✅ │ ۴,۲۰۰,۰۰ │ [🔄] [📍]│
|
||||
│ 2 │ ۱۴۰۴/۱۰/۱۵│ ۱,۸۰۰,۰۰۰ │ ارسال 📦 │ ۱,۸۰۰,۰۰ │ [📍]│
|
||||
│ 3 │ ۱۴۰۴/۰۹/۲۰│ ۳,۵۰۰,۰۰۰ │ تحویل ✅ │ ۳,۵۰۰,۰۰ │ [🔄] [📍]│
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
|
||||
🔄 = تکرار سفارش (CustomerReorderPreviousOrder)
|
||||
📍 = ردیابی سفارش (CustomerTrackOrder)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۳. تجربه ادمین (BackOffice) — قبل و بعد
|
||||
|
||||
### ۳.۱ مدیریت پکیجها (`PackageMainPage.razor`)
|
||||
|
||||
#### قبل:
|
||||
```
|
||||
┌─── مدیریت پکیجها ────────────────────────────────┐
|
||||
│ # │ عنوان │ قیمت │ وضعیت │ عملیات │
|
||||
│───┼──────────┼─────────────┼───────┼──────────────│
|
||||
│ 1 │ طلایی │ ۵۶,۰۰۰,۰۰۰ │ فعال │ [ویرایش] │
|
||||
└────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
#### بعد:
|
||||
```
|
||||
┌─── مدیریت پکیجها ──────────────────────────────────────────────────────┐
|
||||
│ # │ عنوان │ قیمت │ سهم باشگاه │ ضریب │ دایا │ پایه │ ترتیب│ عملیات │
|
||||
│───┼─────────┼─────────────┼────────────┼────────┼──────┼──────┼──────┼───────────────│
|
||||
│ 1 │ نقرهای │ ۵,۶۰۰,۰۰۰ │ ۲,۵۲۰,۰۰۰ │ ×2.0 │ ❌ │ ❌ │ 1 │ [✏️] [📋] [❌] │
|
||||
│ 2 │ پایه │ ۵۶,۰۰۰,۰۰۰ │ ۲۵,۲۰۰,۰۰│ ×2.0 │ ✅ │ ✅ │ 2 │ [✏️] [📋] [❌] │
|
||||
└──────────────────────────────────────────────────────────────────────────┘
|
||||
|
||||
✏️ = ویرایش 📋 = مدیریت فیچرها ❌ = حذف
|
||||
```
|
||||
|
||||
### ۳.۲ ماتریس فیچر × پکیج (`PackageFeatureMatrixPage.razor`) — صفحه جدید
|
||||
|
||||
```
|
||||
┌─── ماتریس فیچر × پکیج ─────────────────────────────────────────┐
|
||||
│ │
|
||||
│ فیچر │ نقرهای │ پایه │ ویژه │
|
||||
│ ─────────────────────────┼─────────┼────────┼──────────────────│
|
||||
│ دسترسی به باشگاه │ ✅ │ ✅ │ ✅ │
|
||||
│ کیفپول جادویی │ ✅ │ ✅ │ ✅ │
|
||||
│ فروشگاه عادی │ ✅ │ ✅ │ ✅ │
|
||||
│ فروشگاه تخفیفی │ ❌ │ ✅ │ ✅ │
|
||||
│ محصولات ClubExclusive │ ❌ │ ✅ │ ✅ │
|
||||
│ پشتیبانی اختصاصی │ ❌ │ ❌ │ ✅ │
|
||||
│ کمیسیون شبکه │ ✅ │ ✅ │ ✅ │
|
||||
│ ─────────────────────────┼─────────┼────────┼──────────────────│
|
||||
│ │ [ذخیره] │ [ذخیره]│ [ذخیره] │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
|
||||
ادمین با checkbox فیچرها را به هر پکیج اختصاص میدهد.
|
||||
وصل به RPC: AssignFeatureToMembership
|
||||
```
|
||||
|
||||
### ۳.۳ فعالسازی باشگاه (`ActivateClubDialog.razor`)
|
||||
|
||||
#### قبل:
|
||||
```
|
||||
فعالسازی باشگاه مشتریان
|
||||
کاربر: علی محمدی
|
||||
[فعالسازی] ← hardcoded 56M + همه فیچرها
|
||||
```
|
||||
|
||||
#### بعد:
|
||||
```
|
||||
فعالسازی باشگاه مشتریان
|
||||
کاربر: علی محمدی
|
||||
پکیج: [▼ انتخاب پکیج ▼] ← dropdown از API
|
||||
├── نقرهای (۵,۶۰۰,۰۰۰)
|
||||
└── پایه (۵۶,۰۰۰,۰۰۰)
|
||||
|
||||
جزئیات:
|
||||
سهم باشگاه: _________ (خودکار)
|
||||
فیچرها: _________ (از ماتریس پکیج)
|
||||
|
||||
[فعالسازی]
|
||||
```
|
||||
|
||||
### ۳.۴ داشبورد (`Index.razor`) — بهبود
|
||||
|
||||
```
|
||||
┌─── آمار باشگاه ────────────────────────────────────────────────┐
|
||||
│ │
|
||||
│ 👥 کل اعضا: ۱,۲۴۰ │
|
||||
│ 📦 پکیج نقرهای: ۸۲۰ | پکیج پایه: ۴۲۰ │
|
||||
│ 💰 Pool نقرهای: ۲,۰۶۶,۴۰۰,۰۰۰ | Pool پایه: ۱۰,۵۸۴,۰۰۰,۰۰│
|
||||
│ ⚠️ هشدار: ۱۲ محصول موجودی کم │
|
||||
│ │
|
||||
│ ┌── موجودی انبار ──┐ ┌── ارزش کل انبار ──┐ │
|
||||
│ │ ۳,۴۵۰ آیتم │ │ ۸۹,۲۰۰,۰۰۰,۰۰۰ │ │
|
||||
│ │ ۱۲ نوع محصول │ │ ریال │ │
|
||||
│ └───────────────────┘ └───────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
|
||||
وصل به: GetInventorySummary, GetStockValueReport, GetLowStockProducts
|
||||
```
|
||||
|
||||
### ۳.۵ مدیریت شبکه (`UserNetworkInfo.razor`) — بهبود
|
||||
|
||||
```
|
||||
┌─── مدیریت شبکه ─────────────────────────────────────────┐
|
||||
│ │
|
||||
│ کاربر: سارا احمدی (ID: 1045) │
|
||||
│ پکیج: نقرهای │ چرخه: ۱ │ PV: ۵,۶۰۰,۰۰۰ │
|
||||
│ Parent: علی محمدی (ID: 1001) │
|
||||
│ شاخه: چپ │ عمق: ۳ │
|
||||
│ │
|
||||
│ [جابجایی در شبکه] ← مودال: انتخاب parent جدید │
|
||||
│ │
|
||||
└───────────────────────────────────────────────────────────┘
|
||||
|
||||
وصل به: ChangeNetworkParent
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ۴. تسکهای تحول — مرحلهبهمرحله
|
||||
|
||||
### مرحله ۱: زیرساخت Domain + DB (پایه)
|
||||
|
||||
> ⚠️ **بدون این مرحله هیچکدام از تغییرات UI ممکن نیست**
|
||||
|
||||
| # | تسک | لایه | فایلها | شرح |
|
||||
|---|------|------|--------|------|
|
||||
| T1.1 | اضافه ۷ فیلد به Package entity | Domain | Package.cs, PackageConfiguration.cs | SortOrder, IsActive, IsBasePackage, SupportsDayaPurchase, SupportsDirectPurchase, ActivationFee, DiscountMultiplier, MagicWalletMultiplier |
|
||||
| T1.2 | ایجاد PackageFeature entity | Domain | PackageFeature.cs, PackageFeatureConfiguration.cs | join table: Package ↔ ClubFeature |
|
||||
| T1.3 | اضافه PackageId به ClubMembership | Domain | ClubMembership.cs | FK nullable → بعد migration → required |
|
||||
| T1.4 | اضافه PackageId به ClubMembershipCycle | Domain | ClubMembershipCycle.cs | FK nullable → بعد migration → required |
|
||||
| T1.5 | اضافه PackageId به WeeklyCommissionPool | Domain | WeeklyCommissionPool.cs | FK + Unique(WeekDefinitionId, PackageId) |
|
||||
| T1.6 | اضافه PackageId به UserCommissionPayout | Domain | UserCommissionPayout.cs | FK nullable |
|
||||
| T1.7 | حذف ۵ SystemConstants | Domain | SystemConstants.cs | BasePackageAmount, DayaLoanAmount, ClubActivationFee, ClubMembershipGiftValue, MagicWalletMultiplier |
|
||||
| T1.8 | EF Migration + Seed | Infrastructure | Migration file | ۲ پکیج + فیچرها + FKها |
|
||||
| T1.9 | Data Migration Script | Infrastructure | SQL script | کاربران فعلی → PackageId = پکیج پایه |
|
||||
| T1.10 | بروزرسانی Protoها | Proto | package.proto, clubmembership.proto, commission.proto | فیلدهای جدید |
|
||||
|
||||
### مرحله ۲: منطق کسبوکار (Handlers)
|
||||
|
||||
> **هر handler باید از Package entity مقادیر مالی بخواند**
|
||||
|
||||
| # | تسک | فایل | شرح |
|
||||
|---|------|------|------|
|
||||
| T2.1 | Generic Verify Handler | VerifyPackagePurchaseCommandHandler.cs | DiscountMultiplier از Package + ساخت UserPackagePurchase |
|
||||
| T2.2 | Generic Purchase Handler | PurchasePackageCommandHandler.cs | حذف "طلایی" و ID=4 |
|
||||
| T2.3 | ActivateClubMembership بهبود | ActivateClubMembershipCommandHandler.cs | فیچر از PackageFeature + ActivationFee از Package |
|
||||
| T2.4 | EXIT Magic Mode ریست | UserOrderService.cs | PackagePurchaseMethod=None, membership.IsActive=false |
|
||||
| T2.5 | Guards re-purchase | G1-G3 handlers | اجازه خرید اگر MagicCompletedAt پر |
|
||||
| T2.6 | Re-contract | AcceptClubMembershipContractCommandHandler.cs | اجازه قرارداد مجدد |
|
||||
| T2.7 | Manual Payment بهبود | CreateManualPaymentCommandHandler.cs | DiscountMultiplier از Package |
|
||||
| T2.8 | Daya Loan بهبود | CheckAndProcessDayaLoansCommandHandler.cs | حذف ID=4 |
|
||||
| T2.9 | PackageFeature CRUD | جدید | ادمین بتواند فیچر ↔ پکیج مدیریت کند |
|
||||
| T2.10 | JWT claims جدید | JWT builder | اضافه CanRepurchase + PackageType |
|
||||
|
||||
### مرحله ۳: محاسبه پورسانت (Commission)
|
||||
|
||||
| # | تسک | فایل | شرح |
|
||||
|---|------|------|------|
|
||||
| T3.1 | SP WeeklyBalances + PackageId | sp_CalculateWeeklyBalances.sql | فیلتر بر اساس PackageId |
|
||||
| T3.2 | SP CommissionPool + PackageId | sp_CalculateWeeklyCommissionPool.sql | Pool جداگانه هر پکیج |
|
||||
| T3.3 | Loop روی پکیجها | WeeklyCommissionCalculationService.cs | هر پکیج فعال → محاسبه جداگانه |
|
||||
| T3.4 | ORM Strategy بهبود | OrmCommissionCalculationStrategy.cs | فیلتر PackageId |
|
||||
| T3.5 | تست محاسبات | — | با داده واقعی staging |
|
||||
|
||||
### مرحله ۴: FrontOffice UI
|
||||
|
||||
| # | تسک | صفحه | شرح |
|
||||
|---|------|------|------|
|
||||
| T4.1 | کاشیهای داینامیک | Packages.razor | لود از API + فیچر مقایسه |
|
||||
| T4.2 | مودال پرداخت شرطی | PackageDetail.razor | دکمه دایا فقط اگر SupportsDayaPurchase |
|
||||
| T4.3 | MyPackages re-purchase | MyPackages.razor | نوار پیشرفت + دکمه خرید مجدد |
|
||||
| T4.4 | ActivationSection داینامیک | ActivationSection.razor | قیمت از پکیج |
|
||||
| T4.5 | قرارداد داینامیک | ClubMembershipContractDialog.razor | متن متناسب با پکیج |
|
||||
| T4.6 | PV در Checkout | Checkout.razor | نمایش PV سفارش |
|
||||
| T4.7 | تکرار سفارش | Store Orders pages | دکمه 🔄 |
|
||||
| T4.8 | ردیابی سفارش | OrderTracking.razor | وصل به API |
|
||||
| T4.9 | تنظیمات اعلان | Settings.razor | فرم Email/SMS/Push |
|
||||
|
||||
### مرحله ۵: BackOffice UI
|
||||
|
||||
| # | تسک | صفحه | شرح |
|
||||
|---|------|------|------|
|
||||
| T5.1 | CRUD پکیج بهبود | PackageMainPage.razor | فیلدهای جدید + ستونهای اضافه |
|
||||
| T5.2 | ماتریس فیچر | PackageFeatureMatrixPage.razor (جدید) | checkbox grid |
|
||||
| T5.3 | ActivateClub dropdown | ActivateClubDialog.razor | انتخاب پکیج |
|
||||
| T5.4 | داشبورد بهبود | Index.razor | آمار Pool جداگانه + موجودی |
|
||||
| T5.5 | شبکه بهبود | UserNetworkInfo.razor | جابجایی parent |
|
||||
| T5.6 | موجودی کم | LowStockPage.razor | وصل API |
|
||||
| T5.7 | گزارش ارزش انبار | InventoryMainPage.razor | تب گزارش |
|
||||
| T5.8 | عملیات دستهای | InventoryMainPage.razor | Bulk Add/Update |
|
||||
|
||||
### مرحله ۶: تست و استقرار
|
||||
|
||||
| # | تسک | شرح |
|
||||
|---|------|------|
|
||||
| T6.1 | تست خرید هر پکیج | ZarinPal + Manual |
|
||||
| T6.2 | تست re-purchase | تکمیل چرخه → خرید مجدد |
|
||||
| T6.3 | تست Commission Pool | جداگانه بودن هر پکیج |
|
||||
| T6.4 | تست Migration | rollback plan |
|
||||
| T6.5 | Deploy staging → production | blue-green |
|
||||
|
||||
---
|
||||
|
||||
## ۵. پیشبینی نیازمندیهای آینده
|
||||
|
||||
### ۵.۱ نیازمندیهای مشتری (که فعلاً اولویت پایین هستند)
|
||||
|
||||
| # | نیاز | RPC آماده? | توضیح |
|
||||
|---|------|-----------|-------|
|
||||
| N1 | ارتقای پکیج (نقرهای → پایه) | ❌ جدید | پرداخت تفاضل + فعالسازی فیچرهای جدید |
|
||||
| N2 | مقایسه پکیجها side-by-side | ❌ جدید | جدول فیچر مقایسهای (client-side) |
|
||||
| N3 | اعلان قبل از اتمام چرخه | ❌ جدید | Background service: 5 روز قبل → push/SMS |
|
||||
| N4 | گزارش PV ماهانه | CalculateOrderPV ✅ | جدول PV هر ماه + نمودار |
|
||||
| N5 | پروفایل شبکه | ❌ جدید | مشتری درخت خودش را ببیند |
|
||||
|
||||
### ۵.۲ نیازمندیهای ادمین (که فعلاً اولویت پایین هستند)
|
||||
|
||||
| # | نیاز | RPC آماده? | توضیح |
|
||||
|---|------|-----------|-------|
|
||||
| N6 | پکیج تخفیفی زماندار | ❌ جدید | پکیج با قیمت ویژه برای مدت محدود |
|
||||
| N7 | گزارش تبدیل (conversion) | ❌ جدید | چند نفر از نقرهای به پایه ارتقا دادند |
|
||||
| N8 | هشدار Pool خالی | ❌ جدید | اگر Pool یک پکیج خالی شد → هشدار |
|
||||
| N9 | export گزارش مالی | GetStockValueReport ✅ | دانلود Excel |
|
||||
| N10 | تخصیص فیچر bulk | AssignFeatureToMembership ✅ | فیچر به همه اعضای یک پکیج |
|
||||
|
||||
---
|
||||
|
||||
## ۶. ماتریس تاثیرگذاری بر صفحات
|
||||
|
||||
### FrontOffice
|
||||
|
||||
| صفحه | تغییر | شدت | مرحله |
|
||||
|------|-------|------|-------|
|
||||
| Packages.razor | بازنویسی کامل — کاشیهای داینامیک | 🔴 | مرحله ۴ |
|
||||
| PackageDetail.razor | فیچرها از API + دکمه شرطی | 🟡 | مرحله ۴ |
|
||||
| MyPackages.razor | چرخه + پیشرفت + re-purchase | 🔴 | مرحله ۴ |
|
||||
| Checkout.razor | PV display | 🟢 | مرحله ۴ |
|
||||
| ActivationSection.razor | قیمت داینامیک | 🟡 | مرحله ۴ |
|
||||
| ClubMembershipContractDialog.razor | متن داینامیک | 🟡 | مرحله ۴ |
|
||||
| PaymentCallback.razor | تغییر JWT claims | 🟡 | مرحله ۴ |
|
||||
| MembershipPage.razor | نمایش نوع پکیج | 🟢 | مرحله ۴ |
|
||||
| Settings.razor | فرم اعلان جدید | 🟡 | مرحله ۴ |
|
||||
| Store Orders | دکمه تکرار + ردیابی | 🟡 | مرحله ۴ |
|
||||
|
||||
### BackOffice
|
||||
|
||||
| صفحه | تغییر | شدت | مرحله |
|
||||
|------|-------|------|-------|
|
||||
| PackageMainPage.razor | ستونهای جدید + CRUD بهبود | 🟡 | مرحله ۵ |
|
||||
| PackageFeatureMatrixPage.razor | **صفحه کاملاً جدید** | 🔴 | مرحله ۵ |
|
||||
| ActivateClubDialog.razor | dropdown پکیج | 🟡 | مرحله ۵ |
|
||||
| Index.razor (Dashboard) | آمار Pool جداگانه + موجودی | 🟡 | مرحله ۵ |
|
||||
| UserNetworkInfo.razor | جابجایی + نمایش پکیج | 🟡 | مرحله ۵ |
|
||||
| ClubMembers.razor | ستون پکیج | 🟢 | مرحله ۵ |
|
||||
| Statistics.razor | چارت توزیع پکیج | 🟡 | مرحله ۵ |
|
||||
| InventoryMainPage.razor | خلاصه + گزارش + bulk | 🟡 | مرحله ۵ |
|
||||
| LowStockPage.razor | وصل API | 🟢 | مرحله ۵ |
|
||||
|
||||
---
|
||||
|
||||
## 🔗 ارجاعات
|
||||
|
||||
| مستند | ربط |
|
||||
|-------|-----|
|
||||
| [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) | طراحی فنی ۳۹ تغییر |
|
||||
| [FEATURE-BACKLOG.md](FEATURE-BACKLOG.md) | بکلاگ ۱۲ RPC آماده |
|
||||
| [GRPC-SERVICES-AUDIT.md](../cms/GRPC-SERVICES-AUDIT.md) | آدیت ۳۴۲ RPC |
|
||||
| [BUSINESS-01-CLUB-COMMISSION.md](../business/BUSINESS-01-CLUB-COMMISSION.md) | مستند باشگاه و کمیسیون |
|
||||
| [BUSINESS-04-USER-MEMBERSHIP.md](../business/BUSINESS-04-USER-MEMBERSHIP.md) | مستند عضویت کاربر |
|
||||
|
||||
---
|
||||
|
||||
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۰۶*
|
||||
Reference in New Issue
Block a user