aef6861e21
Matches code fix — IPG now charges DiscountBalance = BasePackageAmount × 2 Same as DayaLoan and ManualPayment. Total for all methods: 56M + 112M = 168M
174 lines
6.4 KiB
Markdown
174 lines
6.4 KiB
Markdown
# 🏆 سیستم باشگاه، کمیسیون و درخت شبکهای
|
||
|
||
> **منابع ادغامشده:** `club-commission-system-complete.md`, `balance-calculation-rules.md`, `club-membership-contract-system.md`
|
||
> **آخرین بروزرسانی:** اسفند ۱۴۰۴
|
||
|
||
---
|
||
|
||
## ۱. مفاهیم کلیدی
|
||
|
||
| مفهوم | توضیح |
|
||
|-------|--------|
|
||
| **عضویت باشگاه** | خرید پکیج طلایی (۵۶M) → فعالسازی (۲۵.۲M) → عضو فعال باشگاه |
|
||
| **درخت باینری** | هر کاربر حداکثر ۲ فرزند مستقیم (چپ/راست) — بدون محدودیت عمق |
|
||
| **کمیسیون هفتگی** | محاسبه بر اساس تعادل چپ/راست — یکشنبه ۰۰:۰۵ (Hangfire cron) |
|
||
| **۳ کیف پول** | `Balance` (نقدی) + `NetworkBalance` (طلایی/کمیسیون) + `DiscountBalance` (تخفیفی) |
|
||
|
||
---
|
||
|
||
## ۲. ساختار درخت باینری
|
||
|
||
```
|
||
Root
|
||
/ \
|
||
Left Right
|
||
/ \ / \
|
||
L1 L2 R1 R2
|
||
/ \ / \ / \ / \
|
||
... ... ... ... ... ← بدون محدودیت عمق
|
||
```
|
||
|
||
**قوانین:**
|
||
- هر نود حداکثر ۲ فرزند (Binary) — `MaxDirectChildrenPerLeg = 1`
|
||
- جایگذاری: `LegPosition` ∈ {Left=0, Right=1} (enum `NetworkLeg`)
|
||
- مدل شبکه مستقیم روی entity `User` — فیلدهای `NetworkParentId`, `LegPosition`, `NetworkChildren`
|
||
- محاسبه کمیسیون تا عمق ۱۵ سطح (`CommissionMaxNetworkLevel = 15`) — اما درخت بدون محدودیت رشد میکند
|
||
|
||
---
|
||
|
||
## ۳. فلوی عضویت و فعالسازی
|
||
|
||
```
|
||
خرید پکیج طلایی (56M تومان)
|
||
│
|
||
▼
|
||
نمایش مودال قرارداد (غیرقابلبستهشدن)
|
||
│
|
||
▼
|
||
مشاهده متن قرارداد ← ReadContract RPC
|
||
│
|
||
▼
|
||
درخواست OTP ← RequestContractOtp (Kavenegar SMS)
|
||
│
|
||
▼
|
||
وارد کردن کد ← VerifyContractOtp
|
||
│
|
||
▼
|
||
امضای قرارداد ← AcceptContract
|
||
│
|
||
├─→ شارژ ۲ کیف پول: Balance += 56M, DiscountBalance += 112M (2×)
|
||
│ (NetworkBalance شارژ نمیشود — فقط برای کمیسیون)
|
||
├─→ کسر هزینه فعالسازی (25.2M از Balance)
|
||
├─→ واریز 25.2M به Pool هفتگی (ClubActivationFee)
|
||
├─→ قرارگیری در درخت باینری
|
||
└─→ رفرش JWT Token (claims جدید)
|
||
|
||
⚠️ در خرید با وام دایا:
|
||
├─→ Balance += 56M
|
||
└─→ DiscountBalance += 112M (دو برابر — DayaLoanAmount × 2)
|
||
```
|
||
|
||
---
|
||
|
||
## ۴. الگوریتم محاسبه کمیسیون هفتگی
|
||
|
||
### ۴.۱ فرمول ۴ مرحلهای
|
||
|
||
```
|
||
مرحله ۱: جمع فروش هر پا
|
||
SumLeft = Σ(فروشهای پای چپ در هفته جاری + CanOverLeft)
|
||
SumRight = Σ(فروشهای پای راست در هفته جاری + CanOverRight)
|
||
|
||
مرحله ۲: محاسبه تعادل
|
||
WeeklyBalance = MIN(SumLeft, SumRight)
|
||
|
||
مرحله ۳: محاسبه باقیمانده (Carryover)
|
||
CanOverLeft = SumLeft - WeeklyBalance
|
||
CanOverRight = SumRight - WeeklyBalance
|
||
|
||
مرحله ۴: سقف هفتگی
|
||
IF WeeklyBalance > 300 → WeeklyBalance = 300
|
||
IF CanOverLeft > 300 → Flush (CanOverLeft = 0)
|
||
IF CanOverRight > 300 → Flush (CanOverRight = 0)
|
||
```
|
||
|
||
### ۴.۲ مثال عددی (درخت ۵ سطحی)
|
||
|
||
```
|
||
هفته ۱: چپ=120, راست=80 → Balance=80, Over(L=40, R=0)
|
||
هفته ۲: چپ=90+40=130, راست=150 → Balance=130, Over(L=0, R=20)
|
||
هفته ۳: چپ=200, راست=180+20=200 → Balance=200, Over(L=0, R=0)
|
||
هفته ۴: چپ=500, راست=100 → Balance=100, Over(L=400→FLUSH=0, R=0)
|
||
```
|
||
|
||
### ۴.۳ Pool هفتگی و توزیع
|
||
|
||
```
|
||
منبع Pool: هر فعالسازی عضو → 25.2M واریز به Pool
|
||
توزیع: بر اساس WeeklyBalance هر عضو / مجموع WeeklyBalanceها
|
||
SP: sp_CalculateWeeklyBalances → sp_CalculateWeeklyCommissionPool
|
||
فرمت هفته: "YYYY-Www" (شمسی، شنبهپایه)
|
||
```
|
||
|
||
---
|
||
|
||
## ۵. تنظیمات سیستمی (SystemConstants)
|
||
|
||
| ثابت (SystemConstants) | مقدار | توضیح |
|
||
|------|-------|--------|
|
||
| `ClubActivationFee` | 25,200,000 | هزینه فعالسازی (ریال) |
|
||
| `ClubMembershipGiftValue` | 25,200,000 | واریز به Pool |
|
||
| `BasePackageAmount` | 56,000,000 | قیمت پکیج طلایی (ریال) |
|
||
| `DayaLoanAmount` | 56,000,000 | مبلغ وام دایا (ریال) |
|
||
| `CommissionMaxWeeklyBalancesPerLeg` | 300 | سقف هفتگی هر پا |
|
||
| `CommissionMaxNetworkLevel` | 15 | عمق محاسبه کمیسیون (نه محدودیت درخت) |
|
||
| `MaxDirectChildrenPerLeg` | 1 | حداکثر فرزند مستقیم هر پا |
|
||
| `MinimumWithdrawAmount` | 1,000,000 | حداقل مبلغ برداشت (ریال) |
|
||
| `ShopVAT` | 0.1 (10%) | مالیات ارزش افزوده |
|
||
| `CommissionCalculationMethod` | "SP" | روش محاسبه = Stored Procedure |
|
||
|
||
---
|
||
|
||
## ۶. ۳ سناریوی خرید پکیج طلایی
|
||
|
||
| سناریو | فلو | وضعیت |
|
||
|--------|------|--------|
|
||
| **وام دایا** | درخواست وام → تأیید → Balance=56M + Discount=112M (مجموع ۱۶۸M) | ✅ پیادهشده |
|
||
| **درگاه مستقیم** | IPG → callback → Balance=56M + Discount=112M (مجموع ۱۶۸M) | ✅ پیادهشده |
|
||
| **پرداخت دستی** | کارتبهکارت → آپلود رسید → تأیید ادمین → شارژ | ⚠️ طراحیشده |
|
||
|
||
---
|
||
|
||
## ۷. یکپارچهسازی وام دایا
|
||
|
||
```
|
||
Hangfire Worker (هر ۲۰ دقیقه — cron: */20 * * * *)
|
||
│
|
||
▼
|
||
بررسی درخواستهای pending
|
||
│
|
||
▼
|
||
ارسال به API دایا (Mock/Real switchable)
|
||
│
|
||
▼
|
||
دریافت نتیجه → شارژ ۲ کیفپول
|
||
│
|
||
├─→ Balance += 56M (DayaLoanAmount)
|
||
└─→ DiscountBalance += 112M (DayaLoanAmount × 2 — دو برابر)
|
||
مجموع: 168M
|
||
|
||
Hangfire retry: [AutomaticRetry(Attempts = 3)]
|
||
```
|
||
|
||
---
|
||
|
||
## ۸. Chatika AI — اولین فیچر باشگاه
|
||
|
||
| آیتم | جزئیات |
|
||
|------|---------|
|
||
| **نوع** | Hangfire recurring job |
|
||
| **فرکانس** | هر ۵ دقیقه |
|
||
| **Retry** | Polly — ۳ تلاش، backoff نمایی |
|
||
| **فعالسازی** | فقط برای اعضای فعال باشگاه |
|
||
| **وضعیت** | ✅ Production ready |
|