c78850f86e
BUSINESS-02: - فرمول هایبرید: حذف MIN، اضافه validation کیفپول اعتباری - فلوی خرید: اضافه مرحله بررسی موجودی + UserWalletChangeLog - نامگذاری جدید کیفپولها: اصلی، اعتباری، پاداش تیمی - جدول وضعیت: اضافه WalletChangeLog + Validation BUSINESS-03: - بخش ۹ جدید: ExpirePendingOrdersService (۱۵ دقیقه) - دیاگرام Mermaid فلوی انقضا TECH-03: - فیکس URL پروداکشن (kbs1→kbs2) + هشدار - ۴ کامیت جدید در بخش ۹.۲ - بخش ۹.۳ فیکس URL پروداکشن - بخش ۹.۴ نامگذاری کیفپولها
555 lines
25 KiB
Markdown
555 lines
25 KiB
Markdown
# 📦 سیستم مبتنی بر پکیج (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 | ۴-۵ روز | فاز ۲ |
|
||
| فاز ۵ — تست | ۲-۳ روز | فاز ۳, ۴ |
|
||
| **مجموع** | **~۱۶-۲۱ روز کاری** | |
|
||
|
||
> فازهای ۲ و ۳ قابل موازیسازی هستند.
|