3c729304db
Corrections verified against actual CMS/BackOffice/FrontOffice source code: - ClubActivationFee: 25,200,000 (not 25,000,000) - Tree depth: no limit (15 is commission calculation depth only) - IPG wallet charge: Balance=56M + Discount=56M - DayaLoan wallet charge: Balance=56M + Discount=112M (2×) - Discount: per-product MaxDiscountPercent (not fixed 30%) - VAT: 10% (ShopVAT) vs 9% (discount store PlaceOrder) - Kavenegar template: 'Afrino' only (not verify-foursat) - SMS sender: 1000001110100 - DayaLoan job: every 20min (not 15min) - Commission job: Sunday 00:05 (not Saturday) - Network tree: on User entity (not separate NetworkNode table) - UserWallets entity (not UserWalletBalances) - OTP: 6 digits, 5 attempts, 2min TTL, 60s cooldown - Removed non-existent constants (ClubJoiningPercentage, ClubActivationThreshold) - Fixed Hangfire Chatika interval: every 5min - Removed InventorySync from recurring jobs list
239 lines
7.3 KiB
Markdown
239 lines
7.3 KiB
Markdown
# 👤 سفر کاربر، ثبتنام و چرخه عضویت
|
||
|
||
> **منابع ادغامشده:** `club-membership-contract-system.md`, `REGISTRATION-FLOW-FIXES.md`, `chatika-integration.md`, `club-feature-management-services.md`, `ADMIN-CUSTOMER-SEPARATION-FIX.md`, `ICURRENTUSERSERVICE-IMPLEMENTATION.md`
|
||
> **آخرین بروزرسانی:** اسفند ۱۴۰۴
|
||
|
||
---
|
||
|
||
## ۱. فلوی کامل چرخه کاربر
|
||
|
||
```
|
||
ورود به سایت
|
||
│
|
||
▼
|
||
ثبتنام (موبایل + OTP)
|
||
│
|
||
▼
|
||
تکمیل پروفایل
|
||
│
|
||
▼
|
||
┌─────────────────────┬────────────────────────┐
|
||
│ مسیر عادی │ مسیر باشگاه │
|
||
├─────────────────────┼────────────────────────┤
|
||
│ خرید از فروشگاه │ خرید پکیج طلایی (56M) │
|
||
│ مشاهده بلاگ │ امضای قرارداد (OTP) │
|
||
│ استفاده از خدمات │ فعالسازی (25M) │
|
||
│ │ عضویت در درخت باینری │
|
||
│ │ دسترسی فروشگاه تخفیفی │
|
||
│ │ دسترسی فیچرهای باشگاه │
|
||
│ │ کسب کمیسیون هفتگی │
|
||
└─────────────────────┴────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## ۲. ثبتنام و احراز هویت
|
||
|
||
### ۲.۱ فلوی ثبتنام
|
||
|
||
```
|
||
صفحه ثبتنام
|
||
│
|
||
▼
|
||
ورود شماره موبایل
|
||
│
|
||
▼
|
||
ارسال OTP (Kavenegar SMS API)
|
||
│
|
||
▼
|
||
تأیید کد OTP
|
||
│
|
||
├─→ کاربر جدید: ساخت User + JWT Token
|
||
└─→ کاربر موجود: ورود + JWT Token
|
||
|
||
JWT Claims:
|
||
• UserId
|
||
• PhoneNumber
|
||
• IsClubMember (bool)
|
||
• Roles[] (Admin, Customer)
|
||
• ReferralCode
|
||
```
|
||
|
||
### ۲.۲ اصلاحات ثبتنام
|
||
|
||
| مشکل | راهحل | وضعیت |
|
||
|------|---------|--------|
|
||
| OTP تکراری | Cooldown: ۶۰ ثانیه بین درخواستها | ✅ |
|
||
| شماره نامعتبر | Regex validation ایران `^09\d{9}$` | ✅ |
|
||
| حمله brute-force | MaxAttempts: ۵ تلاش برای تأیید کد | ✅ |
|
||
| انقضای کد | TTL: ۲ دقیقه | ✅ |
|
||
| طول کد | ۶ رقم | ✅ |
|
||
| قالب SMS | Kavenegar template: `Afrino` | ✅ |
|
||
|
||
---
|
||
|
||
## ۳. جداسازی Admin/Customer
|
||
|
||
### ۳.۱ مشکل قبلی
|
||
|
||
```
|
||
قبل:
|
||
Admin و Customer هر دو از یک DbContext و Identity استفاده میکردند
|
||
یک ادمین میتوانست به صورت Customer هم ظاهر شود ← تداخل Claims
|
||
|
||
بعد (اصلاحشده):
|
||
✅ ICurrentUserService → تشخیص دقیق نقش فعلی
|
||
✅ جداسازی Authorization Policy
|
||
✅ Admin claims فقط در BackOffice
|
||
✅ Customer claims فقط در FrontOffice
|
||
```
|
||
|
||
### ۳.۲ ICurrentUserService
|
||
|
||
```csharp
|
||
public interface ICurrentUserService {
|
||
Guid UserId { get; }
|
||
string PhoneNumber { get; }
|
||
bool IsClubMember { get; }
|
||
bool IsAdmin { get; }
|
||
string[] Roles { get; }
|
||
Guid? ReferrerId { get; }
|
||
}
|
||
|
||
// پیادهسازی: از HttpContext.User.Claims خوانده میشود
|
||
// ثبت: services.AddScoped<ICurrentUserService, CurrentUserService>()
|
||
```
|
||
|
||
---
|
||
|
||
## ۴. قرارداد عضویت باشگاه
|
||
|
||
### ۴.۱ فلوی امضای قرارداد
|
||
|
||
```
|
||
خرید پکیج طلایی → Redirect به صفحه قرارداد
|
||
│
|
||
▼
|
||
نمایش Modal غیرقابلبستهشدن
|
||
│
|
||
▼
|
||
ReadContract RPC → نمایش متن قرارداد (Markdown/HTML)
|
||
│
|
||
▼
|
||
کاربر باید تا انتهای متن اسکرول کند
|
||
│
|
||
▼
|
||
فعال شدن دکمه "ارسال کد تأیید"
|
||
│
|
||
▼
|
||
RequestContractOtp → ارسال SMS
|
||
│
|
||
▼
|
||
ورود کد ← VerifyContractOtp
|
||
│
|
||
├─→ معتبر: AcceptContract → فعالسازی عضویت
|
||
└─→ نامعتبر: پیام خطا (حداکثر ۵ تلاش)
|
||
```
|
||
|
||
### ۴.۲ ذخیرهسازی قرارداد
|
||
|
||
```csharp
|
||
// از کد: UserContract : BaseAuditableEntity
|
||
public class UserContract {
|
||
public long UserId { get; set; }
|
||
public virtual User User { get; set; }
|
||
public long ContractId { get; set; } // FK → Contract
|
||
public virtual Contract Contract { get; set; }
|
||
public string SignGuid { get; set; } // GUID یکتای امضا
|
||
public string SignedPdfFile { get; set; } // فایل PDF امضاشده
|
||
// فیلدهای BaseAuditableEntity: CreatedAt, ModifiedAt, ...
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## ۵. فیچرهای باشگاه (Club Features)
|
||
|
||
### ۵.۱ سرویس مدیریت
|
||
|
||
```csharp
|
||
public interface IClubFeatureService {
|
||
Task<List<ClubFeature>> GetUserFeaturesAsync(Guid userId);
|
||
Task ActivateFeatureAsync(Guid userId, string featureCode);
|
||
Task DeactivateFeatureAsync(Guid userId, string featureCode);
|
||
Task<bool> HasFeatureAsync(Guid userId, string featureCode);
|
||
}
|
||
```
|
||
|
||
### ۵.۲ فیچرهای موجود
|
||
|
||
| کد فیچر | نام | توضیح | وضعیت |
|
||
|----------|------|--------|--------|
|
||
| `DISCOUNT_STORE` | فروشگاه تخفیفی | دسترسی به فروشگاه ۳۰% تخفیف | ✅ فعال |
|
||
| `CHATIKA_AI` | چاتیکا | مشاوره هوش مصنوعی | ✅ فعال |
|
||
| `COMMISSION` | کمیسیون | دریافت کمیسیون هفتگی | ✅ فعال |
|
||
| `NETWORK_VIEW` | نمای شبکه | مشاهده درخت باینری | ✅ فعال |
|
||
| `DAYA_LOAN` | وام دایا | درخواست وام | ⚠️ بلاکشده |
|
||
|
||
### ۵.۳ UserClubFeature Entity
|
||
|
||
```csharp
|
||
public class UserClubFeature {
|
||
public Guid Id { get; set; }
|
||
public Guid UserId { get; set; }
|
||
public string FeatureCode { get; set; }
|
||
public bool IsActive { get; set; }
|
||
public DateTime ActivatedAt { get; set; }
|
||
public DateTime? DeactivatedAt { get; set; }
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## ۶. ناوبری Auth-Aware
|
||
|
||
```csharp
|
||
// صفحه اصلی — مسیردهی هوشمند
|
||
if (IsAuthenticated && IsClubMember)
|
||
→ نمایش داشبورد باشگاه + فروشگاه تخفیفی
|
||
else if (IsAuthenticated)
|
||
→ نمایش فروشگاه عادی + پروفایل
|
||
else
|
||
→ نمایش Landing Page + ثبتنام
|
||
```
|
||
|
||
---
|
||
|
||
## ۷. کدهای معرف (Referral)
|
||
|
||
```
|
||
هر عضو باشگاه → یک ReferralCode یکتا
|
||
لینک: https://foursat.ir/register?ref={ReferralCode}
|
||
|
||
ثبتنام با لینک:
|
||
│
|
||
▼
|
||
ذخیره ReferrerId در پروفایل کاربر جدید
|
||
│
|
||
▼
|
||
هنگام خرید پکیج → زیرمجموعه Referrer در درخت باینری
|
||
│
|
||
▼
|
||
Referrer → دریافت bonus (طبق شرایط باشگاه)
|
||
```
|
||
|
||
---
|
||
|
||
## ۸. خلاصه وضعیت
|
||
|
||
| ماژول | وضعیت | درصد |
|
||
|-------|--------|------|
|
||
| ثبتنام OTP | ✅ | 100% |
|
||
| جداسازی Admin/Customer | ✅ | 100% |
|
||
| ICurrentUserService | ✅ | 100% |
|
||
| قرارداد باشگاه + OTP | ✅ | 100% |
|
||
| فیچرهای باشگاه | ✅ | 100% |
|
||
| Referral System | ✅ | 100% |
|
||
| ناوبری Auth-Aware | ✅ | 100% |
|
||
| مشاهده درخت شبکه (FrontOffice) | ✅ | 100% |
|