119e870a26
- Added FINAL-STATUS.md detailing project completion and key metrics - Created QUICK-REFERENCE.md for quick access to essential documents - Updated README.md with project overview and quick start guide - Established STRUCTURE.md outlining the final documentation structure - Organized and archived old files, ensuring a clean and efficient directory - Enhanced documentation quality with comprehensive metrics and checklists
982 lines
34 KiB
Markdown
982 lines
34 KiB
Markdown
<div dir="rtl" align="right">
|
||
|
||
# 📊 تحلیل جامع FrontOffice - وضعیت فعلی و نقشه راه
|
||
|
||
**تاریخ تحلیل**: ۱۴ آذر ۱۴۰۴ (بروزرسانی شده)
|
||
**وضعیت کلی**: ⚠️ **پیادهسازی BFF (60%)** - هسته مرکزی آماده، نیاز به UI
|
||
**اولویت**: 🟡 **متوسط** - BFF Skeleton آماده، فقط UI باقی مانده
|
||
|
||
---
|
||
|
||
## 🎯 خلاصه اجرایی
|
||
|
||
### وضعیت موجود:
|
||
- ✅ **24 صفحه UI** موجود (Store, Profile, Root pages)
|
||
- ✅ **12 ماژول CQ در BFF** (9 قدیمی + 3 جدید: Club, Network, Commission)
|
||
- ✅ **هسته مرکزی BFF کامل** (ClubMembership, NetworkMembership, Commission)
|
||
- ✅ **معماری gRPC** پیادهسازی شده + Infrastructure آماده
|
||
- ⚠️ **UI Pages برای Club/Network/Commission غایب** (فقط اسکلت BFF)
|
||
|
||
### نیازمندیهای کاربر (7 دسته) - **بروزرسانی شده**:
|
||
1. 🟡 **باشگاه مشتریان** - BFF آماده ✅ | UI غایب ❌
|
||
2. 🟡 **صفحه داشبورد باشگاه** - BFF آماده ✅ | UI غایب ❌
|
||
3. ⚠️ **دیدن اطلاعات در یک نگاه** - Dashboard جامع (نیمهکاره)
|
||
4. ⚠️ **فروشگاه معمولی** - نیاز به بهبود UI/UX
|
||
5. ❌ **پرداخت دستی پکیج طلایی** - فرآیند ناقص
|
||
6. 🟡 **گزارش شبکه و کمیسیون** - BFF آماده ✅ | UI غایب ❌
|
||
7. ❓ **موارد اضافی** - نیازمند تحلیل
|
||
|
||
---
|
||
|
||
## 📁 ساختار فعلی پروژه
|
||
|
||
### 1️⃣ FrontOffice UI (Blazor Server)
|
||
|
||
**مسیر**: `/FrontOffice/src/FrontOffice.Main/Pages/`
|
||
|
||
#### صفحات موجود (24 صفحه):
|
||
|
||
**الف. Root Level (7 صفحه):**
|
||
```
|
||
✅ Index.razor - صفحه اصلی (Hero, Features, Stats)
|
||
✅ About.razor - درباره ما
|
||
✅ Contact.razor - تماس با ما
|
||
✅ FAQ.razor - سوالات متداول
|
||
✅ Checkout.razor - صفحه پرداخت
|
||
✅ RegisterWizard.razor - ثبتنام کاربر
|
||
✅ PackageDetail.razor - جزئیات پکیج
|
||
```
|
||
|
||
**ب. Profile Section (6 صفحه):**
|
||
```
|
||
✅ Profile/Index.razor - داشبورد پروفایل (نمایش _walletNetwork)
|
||
✅ Profile/Personal.razor - اطلاعات شخصی
|
||
✅ Profile/Settings.razor - تنظیمات
|
||
✅ Profile/Wallet.razor - کیف پول (3 موجودی: Credit, Discount, Network)
|
||
⚠️ Profile/Addresses.razor - آدرسها (کامل)
|
||
⚠️ Profile/Tree.razor - شجرهنامه (Mock data - OrganizationChart component)
|
||
```
|
||
|
||
**ج. Store Section (7 صفحه):**
|
||
```
|
||
✅ Store/Products.razor - لیست محصولات
|
||
✅ Store/ProductDetail.razor - جزئیات محصول
|
||
✅ Store/Cart.razor - سبد خرید
|
||
✅ Store/Categories.razor - دستهبندیها
|
||
✅ Store/Orders.razor - سفارشات
|
||
✅ Store/OrderDetail.razor - جزئیات سفارش
|
||
✅ Store/CheckoutSummary.razor - خلاصه پرداخت
|
||
```
|
||
|
||
**د. Shared Components:**
|
||
```
|
||
✅ Shared/MainLayout.razor
|
||
✅ Shared/Footer.razor
|
||
✅ Shared/AuthDialog.razor
|
||
✅ Shared/SimpleOtpDialog.razor
|
||
```
|
||
|
||
---
|
||
|
||
### 2️⃣ FrontOffice.BFF (Backend For Frontend)
|
||
|
||
**مسیر**: `/FrontOffice.BFF/src/`
|
||
|
||
#### معماری (Clean Architecture):
|
||
```
|
||
FrontOffice.BFF/
|
||
├── Application/ # CQRS Handlers + DTOs
|
||
│ ├── CategoryCQ/ ✅ قدیمی
|
||
│ ├── PackageCQ/ ✅ قدیمی
|
||
│ ├── ProductsCQ/ ✅ قدیمی
|
||
│ ├── ShopingCartCQ/ ✅ قدیمی
|
||
│ ├── TransactionCQ/ ✅ قدیمی
|
||
│ ├── UserAddressCQ/ ✅ قدیمی
|
||
│ ├── UserCQ/ ✅ قدیمی
|
||
│ ├── UserOrderCQ/ ✅ قدیمی
|
||
│ ├── UserWalletCQ/ ✅ قدیمی (DiscountBalance موجود)
|
||
│ ├── ClubMembershipCQ/ 🆕 جدید (امروز)
|
||
│ ├── NetworkMembershipCQ/ 🆕 جدید (امروز)
|
||
│ └── CommissionCQ/ 🆕 جدید (امروز)
|
||
├── Domain/ # Entities (minimal)
|
||
├── Infrastructure/ # gRPC clients, DB context
|
||
│ ├── Services/
|
||
│ │ └── ApplicationContractContext.cs ✅ بروز (ClubMemberships, NetworkMemberships)
|
||
│ └── ConfigureGrpcServices.cs ✅ Auto-register
|
||
└── WebApi/
|
||
├── Services/ # gRPC Service Implementations
|
||
│ ├── CategoriesService.cs
|
||
│ ├── PackageService.cs
|
||
│ ├── ProductsService.cs
|
||
│ ├── ShopingCartService.cs
|
||
│ ├── TransactionService.cs
|
||
│ ├── UserAddressService.cs
|
||
│ ├── UserOrderService.cs
|
||
│ ├── UserService.cs
|
||
│ └── UserWalletService.cs
|
||
└── Protobufs/ # gRPC Proto definitions
|
||
```
|
||
|
||
#### 12 ماژول موجود (9 قدیمی + 3 جدید):
|
||
|
||
| ماژول | وضعیت | توضیحات |
|
||
|------|-------|---------|
|
||
| **CategoryCQ** | ✅ کامل | دریافت دستهبندیها |
|
||
| **PackageCQ** | ✅ کامل | دریافت پکیجها |
|
||
| **ProductsCQ** | ✅ کامل | محصولات و گالری |
|
||
| **ShopingCartCQ** | ⚠️ ناقص | Add/Update موجود، Delete/Clear غایب |
|
||
| **TransactionCQ** | ✅ کامل | پرداخت و تأیید |
|
||
| **UserAddressCQ** | ✅ کامل | CRUD آدرسها |
|
||
| **UserCQ** | ✅ کامل | OTP, Login, Profile |
|
||
| **UserOrderCQ** | ✅ کامل | CRUD سفارشات |
|
||
| **UserWalletCQ** | ✅ کامل | GetWallet + DiscountBalance موجود ✅ |
|
||
| **🆕 ClubMembershipCQ** | ✅ اسکلت | GetMyClubMembership, ActivateMyClubMembership |
|
||
| **🆕 NetworkMembershipCQ** | ✅ اسکلت | GetMyNetworkTree, GetMyNetworkStatistics |
|
||
| **🆕 CommissionCQ** | ✅ اسکلت | GetMyCommissionPayouts, GetMyWeeklyBalances |
|
||
|
||
---
|
||
|
||
## 🔴 تحلیل شکافهای بحرانی (Gap Analysis)
|
||
|
||
### دسته A: ماژولهای BFF آماده (اسکلت کامل ✅) - نیاز به UI
|
||
|
||
#### 1️⃣ ClubMembershipCQ - باشگاه مشتریان
|
||
|
||
**✅ در FrontOffice.BFF**: اسکلت کامل شده (امروز ۱۴ آذر)
|
||
**❌ در FrontOffice UI**: هیچ صفحهای برای باشگاه وجود ندارد
|
||
|
||
**✅ در CMS موجود:**
|
||
- Commands: `ActivateClubMembership`, `DeactivateClubMembership`, `AssignClubFeature`
|
||
- Queries: `GetClubMembership`, `GetClubMembershipHistory`, `GetClubStatistics`
|
||
|
||
**✅ کارهای انجام شده در BFF:**
|
||
|
||
**الف. BFF Module (FrontOffice.BFF/Application/):**
|
||
```
|
||
✅ ClubMembershipCQ/
|
||
✅ Commands/
|
||
✅ ActivateMyClubMembership/ # پرداخت 56M
|
||
- ActivateMyClubMembershipCommand.cs
|
||
- ActivateMyClubMembershipCommandHandler.cs
|
||
- ActivateMyClubMembershipResponseDto.cs
|
||
✅ Queries/
|
||
✅ GetMyClubMembership/ # وضعیت عضویت (Active/Inactive/Trial)
|
||
- GetMyClubMembershipQuery.cs
|
||
- GetMyClubMembershipQueryHandler.cs
|
||
- GetMyClubMembershipResponseDto.cs
|
||
```
|
||
|
||
**✅ Infrastructure Updates:**
|
||
```csharp
|
||
✅ IApplicationContractContext + Implementation:
|
||
- ClubMemberships property اضافه شد
|
||
- NetworkMemberships property اضافه شد
|
||
```
|
||
|
||
**ج. UI Pages (FrontOffice/Pages/):**
|
||
```
|
||
[ ] Club/
|
||
[ ] MembershipPage.razor
|
||
- Badge وضعیت (Active/Inactive/Trial)
|
||
- دکمه فعالسازی (56M تومان)
|
||
- نمایش تاریخ انقضا
|
||
- لیست مزایا
|
||
[ ] FeaturesPage.razor
|
||
- کارت هر فیچر (Trial vs VIP)
|
||
- امتیاز لازم (RequiredPoints)
|
||
- Badge فیچرهای فعال
|
||
[ ] Components/
|
||
[ ] ActivationButton.razor # فرم پرداخت
|
||
[ ] FeatureCard.razor # کارت تک فیچر
|
||
```
|
||
|
||
**💰 اثر بیزینسی:**
|
||
- ❌ کاربر نمیتواند عضو باشگاه شود
|
||
- ❌ 56M شارژ Balance/Discount انجام نمیشود
|
||
- ❌ دسترسی به فروشگاه تخفیف وجود ندارد
|
||
|
||
---
|
||
|
||
#### 2️⃣ NetworkMembershipCQ - شبکه باینری
|
||
|
||
**❌ در FrontOffice.BFF**: هیچ چیز موجود نیست
|
||
**⚠️ در FrontOffice UI**: فقط `Profile/Tree.razor` با داده Mock
|
||
|
||
**✅ در CMS موجود:**
|
||
- Commands: `JoinNetwork`, `MoveInNetwork`, `RemoveFromNetwork`
|
||
- Queries: `GetNetworkTree`, `GetUserNetworkPosition`, `GetNetworkMembershipHistory`, `GetNetworkStatistics`
|
||
|
||
**📋 کارهای مورد نیاز:**
|
||
|
||
**الف. BFF Module:**
|
||
```
|
||
[ ] NetworkMembershipCQ/
|
||
[ ] Commands/
|
||
[ ] JoinNetwork/ # عضویت در شبکه
|
||
[ ] Queries/
|
||
[ ] GetMyNetworkTree/ # درخت باینری (MaxDepth: 1-10)
|
||
[ ] GetMyNetworkPosition/ # موقعیت من (Parent, Left, Right)
|
||
[ ] GetMyNetworkStatistics/ # آمار (تعداد چپ/راست/کل)
|
||
[ ] GetNetworkHistory/ # تاریخچه جابجایی
|
||
```
|
||
|
||
**ب. BFF Service:**
|
||
```csharp
|
||
[ ] NetworkMembershipService.cs
|
||
- GetMyNetworkTree(maxDepth) → CMS.GetNetworkTreeAsync(userId, maxDepth)
|
||
- GetMyNetworkPosition() → CMS.GetUserNetworkPositionAsync(userId)
|
||
- GetMyNetworkStatistics() → CMS.GetNetworkStatisticsAsync(userId)
|
||
- JoinNetwork(parentId, position) → CMS.JoinNetworkAsync()
|
||
```
|
||
|
||
**ج. UI Updates:**
|
||
```
|
||
[ ] Profile/Tree.razor
|
||
✅ Component موجود: OrganizationChart
|
||
[ ] حذف Mock data
|
||
[ ] فراخوانی GetMyNetworkTree از BFF
|
||
[ ] Selector عمق درخت (1-10)
|
||
[ ] Lazy loading برای زیرشاخهها
|
||
[ ] دکمه Expand/Collapse
|
||
|
||
[ ] Pages/Network/
|
||
[ ] StatsPage.razor # صفحه آمار شبکه
|
||
- کارت تعداد چپ/راست
|
||
- کارت کل اعضا
|
||
- عمق درخت
|
||
- آخرین عضو جدید
|
||
- نمودار رشد
|
||
[ ] JoinPage.razor # فرم عضویت
|
||
- انتخاب Parent (جستجو)
|
||
- انتخاب Position (Left/Right)
|
||
- پیشنمایش موقعیت
|
||
```
|
||
|
||
**💰 اثر بیزینسی:**
|
||
- ❌ کاربر نمیتواند زیرمجموعه بگیرد
|
||
- ❌ درخت شبکه واقعی نمایش داده نمیشود
|
||
- ❌ محاسبه کمیسیون باینری کار نمیکند
|
||
|
||
---
|
||
|
||
#### 3️⃣ CommissionCQ - کمیسیون و برداشت
|
||
|
||
**⚠️ در FrontOffice.BFF**: فقط `WithdrawBalance` (کامل - در UserWalletCQ)
|
||
**❌ در FrontOffice UI**: هیچ صفحه کمیسیون موجود نیست
|
||
|
||
**✅ در CMS موجود:**
|
||
- Commands: `RequestWithdrawal`, `ApproveWithdrawal`, `ProcessWithdrawal`, `CalculateWeekly*`
|
||
- Queries: `GetUserCommissionPayouts`, `GetUserWeeklyBalances`, `GetWeeklyCommissionPool`, `GetWithdrawalRequests`
|
||
|
||
**📋 کارهای مورد نیاز:**
|
||
|
||
**الف. BFF Module:**
|
||
```
|
||
[ ] CommissionCQ/
|
||
[ ] Queries/
|
||
[ ] GetMyCommissionPayouts/ # لیست پرداختهای کمیسیون
|
||
- GetMyCommissionPayoutsQuery.cs
|
||
- GetMyCommissionPayoutsQueryHandler.cs
|
||
- CommissionPayoutDto.cs (Week, Amount, Status, Date)
|
||
[ ] GetMyWeeklyBalances/ # تعادل هفتگی
|
||
- GetMyWeeklyBalancesQuery.cs
|
||
- GetMyWeeklyBalancesQueryHandler.cs
|
||
- WeeklyBalanceDto.cs (Left, Right, Weaker, Carryover)
|
||
[ ] GetWeeklyPoolInfo/ # اطلاعات استخر هفته
|
||
- GetWeeklyPoolInfoQuery.cs
|
||
- GetWeeklyPoolInfoQueryHandler.cs
|
||
- WeeklyPoolDto.cs (TotalPool, BalanceValue)
|
||
[ ] GetMyWithdrawalHistory/ # تاریخچه برداشتها
|
||
- GetMyWithdrawalHistoryQuery.cs
|
||
- GetMyWithdrawalHistoryQueryHandler.cs
|
||
- WithdrawalHistoryDto.cs
|
||
```
|
||
|
||
**ب. BFF Service:**
|
||
```csharp
|
||
[ ] CommissionService.cs
|
||
- GetMyCommissionPayouts(weekNumber?, status?) → CMS.GetUserCommissionPayoutsAsync(userId)
|
||
- GetMyWeeklyBalances(weekNumber?) → CMS.GetUserWeeklyBalancesAsync(userId)
|
||
- GetWeeklyPoolInfo(weekNumber?) → CMS.GetWeeklyCommissionPoolAsync(weekNumber)
|
||
- GetMyWithdrawalHistory() → CMS.GetWithdrawalRequestsAsync(userId)
|
||
```
|
||
|
||
**توجه**: `WithdrawBalance` در `UserWalletService` قبلاً پیادهسازی شده ✅
|
||
|
||
**ج. UI Pages:**
|
||
```
|
||
[ ] Pages/Commission/
|
||
[ ] DashboardPage.razor # داشبورد کمیسیون
|
||
- کارت استخر هفته (TotalPool, BalanceValue)
|
||
- کارت امتیازات من (LesserLegPoints)
|
||
- پیشبینی کمیسیون این هفته
|
||
- نمودار روند 4 هفته اخیر
|
||
[ ] HistoryPage.razor # تاریخچه پرداختها
|
||
- جدول پرداختهای گذشته
|
||
- فیلتر Status (Pending/Calculated/Paid/Withdrawn)
|
||
- فیلتر هفته
|
||
- نمودار خطی روند
|
||
[ ] WithdrawPage.razor # صفحه برداشت
|
||
✅ قسمتی در Profile/Wallet.razor موجود است
|
||
[ ] جداسازی به صفحه مستقل
|
||
- فرم برداشت (PayoutId, Method, IBAN)
|
||
- نمایش MinWithdrawalAmount
|
||
- نمایش موجودی قابل برداشت
|
||
- تاریخچه برداشتها
|
||
[ ] WeeklyBalancePage.razor # تعادل هفتگی
|
||
- تعادل چپ/راست
|
||
- Carryover از هفته قبل
|
||
- سقف 300 Balance
|
||
- نمودار میلهای هفتهها
|
||
```
|
||
|
||
**💰 اثر بیزینسی:**
|
||
- ❌ کاربر نمیتواند کمیسیون خود را ببیند
|
||
- ✅ برداشت از NetworkBalance کار میکند (در Wallet.razor)
|
||
- ❌ تعادل هفتگی و Carryover نامشخص است
|
||
|
||
---
|
||
|
||
#### 4️⃣ DayaLoanCQ - وام دایا
|
||
|
||
**❌ در FrontOffice.BFF**: هیچ چیز موجود نیست
|
||
**❌ در FrontOffice UI**: هیچ چیز موجود نیست
|
||
|
||
**✅ در CMS موجود:**
|
||
- Commands: `CheckDayaLoanStatus`, `ProcessDayaLoanApproval`
|
||
- Background Worker: Daily check for loan status
|
||
|
||
**📋 کارهای مورد نیاز:**
|
||
|
||
**الف. BFF Module:**
|
||
```
|
||
[ ] DayaLoanCQ/
|
||
[ ] Queries/
|
||
[ ] GetMyDayaLoanStatus/
|
||
- GetMyDayaLoanStatusQuery.cs
|
||
- GetMyDayaLoanStatusQueryHandler.cs
|
||
- DayaLoanStatusDto.cs (Status, ContractNumber, LastCheckDate, ApprovalDate)
|
||
```
|
||
|
||
**ب. BFF Service:**
|
||
```csharp
|
||
[ ] DayaLoanService.cs
|
||
- GetMyDayaLoanStatus() → CMS.GetDayaLoanStatusAsync(userId)
|
||
```
|
||
|
||
**ج. UI Pages:**
|
||
```
|
||
[ ] Pages/DayaLoan/
|
||
[ ] StatusPage.razor
|
||
- Badge وضعیت (PendingReceive/Received/Rejected)
|
||
- نمایش شماره قرارداد
|
||
- تاریخ آخرین بررسی
|
||
- توضیحات وام (168M = 56M×3)
|
||
[ ] Components/
|
||
[ ] StatusBadge.razor
|
||
- رنگبندی (Warning/Success/Error)
|
||
```
|
||
|
||
**💰 اثر بیزینسی:**
|
||
- ❌ کاربر نمیتواند وضعیت وام دایا را ببیند
|
||
- ❌ 168M شارژ (56M×3) نامشخص است
|
||
- ⚠️ Worker پسزمینه فعال است اما UI ندارد
|
||
|
||
---
|
||
|
||
### دسته B: ماژولهای کاملشده (100% BFF)
|
||
|
||
#### 5️⃣ UserWalletCQ - کیفپول
|
||
|
||
**✅ موجود در BFF (کامل):**
|
||
- `GetUserWallet` - دریافت موجودی (✅ DiscountBalance موجود است)
|
||
- `GetAllUserWalletChangeLog` - تاریخچه تراکنشها
|
||
- `WithdrawBalance` - برداشت (✅ کار میکند)
|
||
- `GetUserWithdrawals` - لیست برداشتها
|
||
- `GetWithdrawalSettings` - تنظیمات برداشت (MinAmount)
|
||
|
||
**✅ Response DTO:**
|
||
```csharp
|
||
public class GetUserWalletResponseDto
|
||
{
|
||
✅ public long Balance { get; set; }
|
||
✅ public long NetworkBalance { get; set; }
|
||
✅ public long DiscountBalance { get; set; } // موجود است
|
||
}
|
||
```
|
||
|
||
**⚠️ مشکلات جزئی:**
|
||
1. **فیلترهای ناقص**: `GetAllUserWalletChangeLog` فیلتر ندارد
|
||
- نیاز: Type (Deposit/Withdraw/Purchase), DateRange, ReferenceId
|
||
|
||
**ب. UI Updates:**
|
||
```
|
||
[ ] Profile/Wallet.razor
|
||
✅ نمایش Balance
|
||
✅ نمایش NetworkBalance
|
||
❌ نمایش DiscountBalance (زرد/نارنجی)
|
||
[ ] حذف داده Mock (Discount: "در انتظار اتصال CMS...")
|
||
[ ] افزودن فیلترهای تراکنش:
|
||
- Select نوع (همه/ورودی/خروجی)
|
||
- DateRange picker
|
||
- TextField جستجو ReferenceId
|
||
[ ] نمایش ChangeValue به جای CurrentBalance
|
||
[ ] Pagination برای تراکنشها
|
||
```
|
||
|
||
**💰 اثر بیزینسی:**
|
||
- ⚠️ کاربر DiscountBalance خود را نمیبیند (باشگاه)
|
||
- ⚠️ فیلتر تراکنشها محدود است
|
||
|
||
---
|
||
|
||
#### 6️⃣ ShopingCartCQ - سبد خرید
|
||
|
||
**✅ موجود در BFF:**
|
||
- `AddNewUserCart` - افزودن به سبد
|
||
- `UpdateUserCart` - بهروزرسانی تعداد
|
||
- `GetAllUserCart` - دریافت سبد
|
||
|
||
**❌ غایب:**
|
||
- `ClearCart` - پاک کردن کل سبد
|
||
- `DeleteUserCarts` - حذف یک آیتم
|
||
- `MergeGuestCart` - ادغام سبد مهمان→ورود
|
||
|
||
**📋 کارهای مورد نیاز:**
|
||
|
||
**الف. BFF Commands:**
|
||
```
|
||
[ ] ShopingCartCQ/Commands/
|
||
[ ] ClearCart/
|
||
- ClearCartCommand.cs
|
||
- ClearCartCommandHandler.cs → CMS.ClearUserCartAsync(userId)
|
||
[ ] DeleteCartItem/
|
||
- DeleteCartItemCommand.cs (CartId)
|
||
- DeleteCartItemCommandHandler.cs → CMS.DeleteUserCartsAsync(cartId)
|
||
[ ] MergeGuestCart/
|
||
- MergeGuestCartCommand.cs (SessionId)
|
||
- MergeGuestCartCommandHandler.cs:
|
||
1. Get guest cart by SessionId
|
||
2. Get user cart by UserId
|
||
3. Merge duplicates (sum quantities)
|
||
4. CMS.AddNewUserCart() for each
|
||
```
|
||
|
||
**ب. UI Updates:**
|
||
```
|
||
[ ] Store/Cart.razor
|
||
[ ] دکمه "پاک کردن سبد" (ClearCart)
|
||
[ ] دکمه حذف (DeleteCartItem) در هر سطر
|
||
[ ] SessionId handling:
|
||
- ذخیره در LocalStorage
|
||
- POST به MergeGuestCart بعد از Login
|
||
- نمایش پیام "x محصول از سبد قبلی شما اضافه شد"
|
||
```
|
||
|
||
---
|
||
|
||
#### 7️⃣ DiscountShopCQ - فروشگاه تخفیف
|
||
|
||
**❌ در FrontOffice.BFF**: هیچ چیز موجود نیست
|
||
**❌ در FrontOffice UI**: هیچ صفحهای موجود نیست
|
||
|
||
**✅ در CMS موجود:**
|
||
- Full CRUD for `DiscountProduct`, `DiscountCategory`, `DiscountOrder`
|
||
- BackOffice UI: 3 pages (Products, Categories, Orders)
|
||
|
||
**📋 کارهای مورد نیاز:**
|
||
|
||
**الف. BFF Module:**
|
||
```
|
||
[ ] DiscountShopCQ/
|
||
[ ] Queries/
|
||
[ ] GetDiscountProducts/ # محصولات تخفیف
|
||
[ ] GetDiscountCategories/ # دستهبندیهای تخفیف
|
||
[ ] GetMyDiscountOrders/ # سفارشات تخفیف من
|
||
[ ] Commands/
|
||
[ ] AddToDiscountCart/ # افزودن به سبد تخفیف
|
||
[ ] PlaceDiscountOrder/ # ثبت سفارش با DiscountBalance
|
||
```
|
||
|
||
**ب. BFF Service:**
|
||
```csharp
|
||
[ ] DiscountShopService.cs
|
||
- GetDiscountProducts() → CMS.GetAllDiscountProductsAsync()
|
||
- GetDiscountCategories() → CMS.GetAllDiscountCategoriesAsync()
|
||
- GetMyDiscountOrders() → CMS.GetAllDiscountOrdersAsync(userId)
|
||
- PlaceDiscountOrder(items) → CMS.CreateDiscountOrderAsync()
|
||
```
|
||
|
||
**ج. UI Pages:**
|
||
```
|
||
[ ] Pages/DiscountShop/
|
||
[ ] ProductsPage.razor # لیست محصولات تخفیف
|
||
- نمایش DiscountPercent (بادگ)
|
||
- نمایش MaxDiscountPercentage سقف
|
||
- فیلتر دستهبندی
|
||
- کارت محصول با قیمت اصلی/تخفیفیافته
|
||
[ ] CartPage.razor # سبد تخفیف
|
||
- نمایش DiscountBalance موجود
|
||
- محاسبه قیمت نهایی
|
||
- دکمه Checkout
|
||
[ ] OrdersPage.razor # سفارشات تخفیف
|
||
- لیست سفارشات با Badge "Club Discount"
|
||
- جزئیات تخفیف اعمالشده
|
||
```
|
||
|
||
**💰 اثر بیزینسی:**
|
||
- ❌ کاربر باشگاه نمیتواند از تخفیف استفاده کند
|
||
- ❌ DiscountBalance کاربرد ندارد
|
||
- ❌ 3 صفحه BackOffice بدون UI مشتری
|
||
|
||
---
|
||
|
||
### دسته C: قابلیتهای جزئی (نیازهای اضافی)
|
||
|
||
#### 8️⃣ PublicMessageCQ - پیامهای عمومی
|
||
|
||
**✅ در BackOffice موجود**: صفحه مدیریت پیامها
|
||
**❌ در FrontOffice**: هیچ چیز نیست
|
||
|
||
**📋 کارهای مورد نیاز:**
|
||
```
|
||
[ ] PublicMessageCQ/Queries/GetActivePublicMessages/
|
||
[ ] UI: Pages/Messages/ListPage.razor
|
||
- لیست پیامها با فیلتر Type (News/Announcement/Promotion)
|
||
- Badge اولویت
|
||
- نمایش تاریخ انتشار
|
||
```
|
||
|
||
---
|
||
|
||
#### 9️⃣ NotificationCQ - نوتیفیکیشن
|
||
|
||
**❌ در همه جا موجود نیست**
|
||
|
||
**پیشنهاد:**
|
||
```
|
||
[ ] NotificationCQ/
|
||
[ ] Queries/GetMyNotifications/
|
||
[ ] Commands/MarkAsRead/
|
||
[ ] UI: Bell Icon در Navbar
|
||
- Badge تعداد جدید
|
||
- Dropdown لیست نوتیفیکیشن
|
||
```
|
||
|
||
---
|
||
|
||
#### 🔟 ReferralLinkCQ - لینک دعوت
|
||
|
||
**❌ در همه جا موجود نیست**
|
||
|
||
**پیشنهاد:**
|
||
```
|
||
[ ] ReferralLinkCQ/Queries/GetMyReferralLink/
|
||
[ ] UI: Profile/ReferralPage.razor
|
||
- نمایش لینک دعوت
|
||
- دکمه Copy
|
||
- آمار دعوتشدهها (تعداد)
|
||
- QR Code
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 خلاصه آماری شکافها (بروزرسانی شده)
|
||
|
||
| دسته | تعداد ماژول | وضعیت BFF | وضعیت UI | درصد کل |
|
||
|------|------------|-----------|----------|---------|
|
||
| ✅ کامل (BFF+UI) | 6 | Category, Package, Products, Transaction, UserAddress, UserCQ | موجود | 35% |
|
||
| ✅ BFF آماده | 3 | ClubMembership, NetworkMembership, Commission | **UI غایب** | 20% |
|
||
| ✅ BFF کامل | 2 | UserWallet (DiscountBalance), UserOrder | UI موجود | 15% |
|
||
| ⚠️ نیمهکاره | 1 | ShopingCart (Delete/Clear غایب) | UI موجود | 5% |
|
||
| ❌ غایب بحرانی | 1 | DayaLoan | UI غایب | 5% |
|
||
| ❌ غایب اضافی | 4 | DiscountShop, PublicMessage, Notification, ReferralLink | UI غایب | 20% |
|
||
|
||
**جمع**: 17 ماژول
|
||
**وضعیت BFF**: 60% کامل (12 از 17)
|
||
**وضعیت UI**: 40% کامل (فقط 9 ماژول قدیمی)
|
||
|
||
---
|
||
|
||
## 🎯 اولویتهای باقیمانده (بروزرسانی شده)
|
||
|
||
### فاز 1: UI برای ماژولهای BFF آماده (اولویت بالا 🔴)
|
||
|
||
**هدف**: اتصال UI به BFF موجود
|
||
|
||
```
|
||
[ ] Phase 1A: Club UI (2-3 روز)
|
||
[ ] Pages/Club/MembershipPage.razor
|
||
[ ] Pages/Club/FeaturesPage.razor (اختیاری)
|
||
[ ] Components/Club/ActivationButton.razor
|
||
|
||
[ ] Phase 1B: Network UI (2 روز)
|
||
[ ] Update Profile/Tree.razor (حذف Mock + اتصال به BFF)
|
||
[ ] Pages/Network/StatsPage.razor
|
||
|
||
[ ] Phase 1C: Commission UI (3 روز)
|
||
[ ] Pages/Commission/DashboardPage.razor
|
||
[ ] Pages/Commission/HistoryPage.razor
|
||
[ ] Pages/Commission/WeeklyBalancePage.razor
|
||
|
||
[ ] Phase 1D: Wallet UI Update (1 روز)
|
||
[ ] Update Profile/Wallet.razor (نمایش DiscountBalance - کارت زرد)
|
||
```
|
||
|
||
**زمان تخمینی**: 8-9 روز
|
||
|
||
---
|
||
|
||
### فاز 2: ماژولهای ثانویه (اولویت متوسط 🟡)
|
||
|
||
```
|
||
Day 1-2: DiscountShopCQ
|
||
[ ] BFF Module
|
||
[ ] Pages/DiscountShop/ProductsPage.razor
|
||
[ ] Pages/DiscountShop/CartPage.razor
|
||
|
||
Day 3: ShopingCartCQ Completion
|
||
[ ] Add DeleteCartItem, ClearCart Commands
|
||
[ ] Update Store/Cart.razor
|
||
|
||
Day 4: DayaLoanCQ
|
||
[ ] BFF Module (Query only)
|
||
[ ] Pages/DayaLoan/StatusPage.razor
|
||
|
||
Day 5: PublicMessageCQ
|
||
[ ] BFF Module
|
||
[ ] Pages/Messages/ListPage.razor
|
||
```
|
||
|
||
---
|
||
|
||
### مرحله 3: بهبودهای UI/UX (1 هفته)
|
||
|
||
```
|
||
Day 1-2: Store Improvements
|
||
[ ] Responsive design (mobile-first)
|
||
[ ] Skeleton loaders
|
||
[ ] Image lazy loading
|
||
[ ] Product filters enhancement
|
||
|
||
Day 3-4: Profile Enhancements
|
||
[ ] Avatar upload
|
||
[ ] Settings page completion
|
||
[ ] ReferralPage.razor (لینک دعوت)
|
||
|
||
Day 5: Notification System
|
||
[ ] Bell icon در Navbar
|
||
[ ] Notification dropdown
|
||
[ ] Mark as read
|
||
```
|
||
|
||
---
|
||
|
||
### مرحله 4: قابلیتهای اضافی (اختیاری)
|
||
|
||
```
|
||
[ ] Referral System (لینک دعوت + آمار)
|
||
[ ] Achievement/Rewards System
|
||
[ ] Reports (Excel/PDF export)
|
||
[ ] Advanced Filters (تاریخ، نوع، مبلغ)
|
||
[ ] Mobile App (PWA)
|
||
```
|
||
|
||
---
|
||
|
||
## 🛠️ الگوی پیادهسازی استاندارد
|
||
|
||
### الف. BFF Module Template
|
||
|
||
```
|
||
FrontOffice.BFF/Application/[ModuleName]CQ/
|
||
├── Commands/
|
||
│ └── [ActionName]/
|
||
│ ├── [ActionName]Command.cs
|
||
│ ├── [ActionName]CommandHandler.cs
|
||
│ ├── [ActionName]CommandValidator.cs
|
||
│ └── [ActionName]ResponseDto.cs (optional)
|
||
└── Queries/
|
||
└── [QueryName]/
|
||
├── [QueryName]Query.cs
|
||
├── [QueryName]QueryHandler.cs
|
||
└── [QueryName]ResponseDto.cs
|
||
```
|
||
|
||
**مثال: GetMyClubMembership**
|
||
|
||
```csharp
|
||
// GetMyClubMembershipQuery.cs
|
||
public record GetMyClubMembershipQuery : IRequest<ClubMembershipDto>;
|
||
|
||
// GetMyClubMembershipQueryHandler.cs
|
||
public class GetMyClubMembershipQueryHandler : IRequestHandler<GetMyClubMembershipQuery, ClubMembershipDto>
|
||
{
|
||
private readonly IApplicationContractContext _context;
|
||
private readonly ICurrentUserService _currentUser;
|
||
|
||
public async Task<ClubMembershipDto> Handle(GetMyClubMembershipQuery request, CancellationToken ct)
|
||
{
|
||
var userId = _currentUser.UserId; // از JWT Token
|
||
|
||
var cmsRequest = new GetClubMembershipRequest { UserId = userId };
|
||
var result = await _context.ClubMemberships.GetClubMembershipAsync(cmsRequest, cancellationToken: ct);
|
||
|
||
return new ClubMembershipDto
|
||
{
|
||
UserId = result.UserId,
|
||
IsActive = result.IsActive,
|
||
ActivationDate = result.ActivationDate.ToDateTime(),
|
||
ExpirationDate = result.ExpirationDate.ToDateTime(),
|
||
Status = result.Status // Active/Inactive/Trial
|
||
};
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### ب. gRPC Service Template
|
||
|
||
```csharp
|
||
// FrontOffice.BFF/WebApi/Services/ClubMembershipService.cs
|
||
public class ClubMembershipService : ClubMembershipContract.ClubMembershipContractBase
|
||
{
|
||
private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS;
|
||
|
||
public ClubMembershipService(IDispatchRequestToCQRS dispatchRequestToCQRS)
|
||
{
|
||
_dispatchRequestToCQRS = dispatchRequestToCQRS;
|
||
}
|
||
|
||
public override async Task<GetMyClubMembershipResponse> GetMyClubMembership(Empty request, ServerCallContext context)
|
||
{
|
||
return await _dispatchRequestToCQRS.Handle<GetMyClubMembershipQuery, GetMyClubMembershipResponse>(context);
|
||
}
|
||
|
||
public override async Task<Empty> ActivateClubMembership(ActivateClubMembershipRequest request, ServerCallContext context)
|
||
{
|
||
return await _dispatchRequestToCQRS.Handle<ActivateClubMembershipRequest, ActivateClubMembershipCommand, Empty>(request, context);
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
### ج. UI Page Template
|
||
|
||
```razor
|
||
@* Pages/Club/MembershipPage.razor *@
|
||
@page "/club/membership"
|
||
@inject ClubMembershipContract.ClubMembershipContractClient ClubService
|
||
|
||
<PageTitle>باشگاه مشتریان</PageTitle>
|
||
|
||
<MudContainer MaxWidth="MaxWidth.Large" Class="py-6">
|
||
<MudStack Spacing="3">
|
||
<MudText Typo="Typo.h4">باشگاه مشتریان</MudText>
|
||
|
||
@if (_isLoading)
|
||
{
|
||
<MudProgressCircular Indeterminate="true" />
|
||
}
|
||
else if (_membership != null)
|
||
{
|
||
<MudPaper Elevation="2" Class="pa-4">
|
||
<MudStack Spacing="2">
|
||
<MudChip Color="@GetStatusColor()" Variant="Variant.Filled">
|
||
@GetStatusText()
|
||
</MudChip>
|
||
|
||
@if (!_membership.IsActive)
|
||
{
|
||
<MudButton Variant="Variant.Filled"
|
||
Color="Color.Primary"
|
||
OnClick="ActivateMembership">
|
||
فعالسازی باشگاه (56,000,000 تومان)
|
||
</MudButton>
|
||
}
|
||
else
|
||
{
|
||
<MudText>تاریخ انقضا: @_membership.ExpirationDate.ToPersianDate()</MudText>
|
||
}
|
||
</MudStack>
|
||
</MudPaper>
|
||
}
|
||
</MudStack>
|
||
</MudContainer>
|
||
|
||
@code {
|
||
private ClubMembershipDto? _membership;
|
||
private bool _isLoading = true;
|
||
|
||
protected override async Task OnInitializedAsync()
|
||
{
|
||
try
|
||
{
|
||
var response = await ClubService.GetMyClubMembershipAsync(new Empty());
|
||
_membership = response; // Map to DTO
|
||
}
|
||
finally
|
||
{
|
||
_isLoading = false;
|
||
}
|
||
}
|
||
|
||
private async Task ActivateMembership()
|
||
{
|
||
// پرداخت 56M
|
||
}
|
||
|
||
private Color GetStatusColor() => _membership?.IsActive == true ? Color.Success : Color.Warning;
|
||
private string GetStatusText() => _membership?.IsActive == true ? "فعال" : "غیرفعال";
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 📋 چکلیست شروع توسعه
|
||
|
||
قبل از شروع هر ماژول:
|
||
|
||
```
|
||
[ ] CMS Commands/Queries را شناسایی کردم
|
||
[ ] Proto definitions را یافتم (CMS/Protobuf/*.proto)
|
||
[ ] نمونه Handler موجود در BFF را بررسی کردم
|
||
[ ] JWT Token و CurrentUserService را فهمیدم
|
||
[ ] ساختار DTO مشتریمحور را طراحی کردم
|
||
[ ] Mock data برای UI آماده کردم
|
||
```
|
||
|
||
---
|
||
|
||
## 🚨 نکات بحرانی
|
||
|
||
### 1. تفاوت CMS vs BFF
|
||
|
||
| جنبه | CMS | FrontOffice.BFF |
|
||
|------|-----|-----------------|
|
||
| **مخاطب** | Admin + System | Customer فقط |
|
||
| **داده** | همه کاربران | کاربر جاری (`UserId` از JWT) |
|
||
| **Response** | DTO کامل + Metadata | DTO ساده (فقط فیلدهای لازم) |
|
||
| **Authorization** | Role-based (Admin/User) | User-only (No Admin) |
|
||
| **Input** | `UserId` required | `UserId` از Token (خودکار) |
|
||
|
||
### 2. احراز هویت
|
||
|
||
**JWT Token Structure:**
|
||
```json
|
||
{
|
||
"sub": "123", // UserId
|
||
"email": "user@example.com",
|
||
"phone": "09123456789",
|
||
"IsSignMainContract": "True",
|
||
"exp": 1234567890
|
||
}
|
||
```
|
||
|
||
**استخراج UserId:**
|
||
```csharp
|
||
public class GetMyDataQueryHandler
|
||
{
|
||
private readonly ICurrentUserService _currentUser;
|
||
|
||
public async Task<Response> Handle(Query request, CancellationToken ct)
|
||
{
|
||
var userId = _currentUser.UserId; // از JWT
|
||
// Call CMS with userId
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3. DTO Mapping Pattern
|
||
|
||
**CMS DTO (خام):**
|
||
```csharp
|
||
public class CommissionPayoutDto
|
||
{
|
||
public long Id { get; set; }
|
||
public long UserId { get; set; }
|
||
public int WeekNumber { get; set; }
|
||
public long TotalAmount { get; set; }
|
||
public CommissionPayoutStatus Status { get; set; }
|
||
// ... 10 فیلد دیگر
|
||
}
|
||
```
|
||
|
||
**BFF Response DTO (مشتریمحور):**
|
||
```csharp
|
||
public class MyCommissionPayoutDto
|
||
{
|
||
public long Id { get; set; }
|
||
public string WeekLabel { get; set; } // "هفته 45 - آذر 1403"
|
||
public string AmountFormatted { get; set; } // "1,250,000 تومان"
|
||
public string StatusText { get; set; } // "پرداخت شده"
|
||
public string StatusBadgeColor { get; set; } // "success"
|
||
public string DatePersian { get; set; } // "25 آذر 1403"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 📞 مسائل و سوالات
|
||
|
||
### سوالات باز:
|
||
|
||
1. **پرداخت دستی پکیج طلایی** (نیازمندی #5):
|
||
- منظور چیست؟ آیا جدا از فعالسازی باشگاه (56M) است؟
|
||
- آیا در CMS Handler مربوطه وجود دارد؟
|
||
|
||
2. **فروشگاه "معمولی"** (نیازمندی #4):
|
||
- چه بهبودهای خاصی مدنظر است؟
|
||
- آیا Discount Shop جداست یا همان Store معمولی؟
|
||
|
||
3. **Dashboard "در یک نگاه"** (نیازمندی #3):
|
||
- آیا `Profile/Index.razor` همان Dashboard است؟
|
||
- یا نیاز به صفحه جداگانه `/dashboard` داریم؟
|
||
|
||
4. **گزارش شبکه و کمیسیون** (نیازمندی #6):
|
||
- چه گزارشهای دقیقی مدنظر است؟
|
||
- PDF/Excel export لازم است؟
|
||
|
||
---
|
||
|
||
## 📈 معیارهای موفقیت (Success Metrics)
|
||
|
||
### مرحله 1 (بحرانی):
|
||
- [ ] کاربر بتواند عضو باشگاه شود (پرداخت 56M)
|
||
- [ ] کاربر 3 موجودی کیفپول را ببیند (Balance, Network, Discount)
|
||
- [ ] کاربر درخت شبکه واقعی خود را ببیند (نه Mock)
|
||
- [ ] کاربر کمیسیون هفتگی خود را ببیند
|
||
- [ ] کاربر بتواند برداشت کند (WithdrawBalance)
|
||
|
||
### مرحله 2 (ثانویه):
|
||
- [ ] کاربر از فروشگاه تخفیف خرید کند
|
||
- [ ] کاربر وضعیت وام دایا را ببیند
|
||
- [ ] کاربر پیامهای عمومی را ببیند
|
||
- [ ] سبد خرید: Delete/Clear کار کند
|
||
|
||
### مرحله 3 (UI/UX):
|
||
- [ ] تمام صفحات Responsive باشند
|
||
- [ ] Skeleton loaders در همه جا
|
||
- [ ] لینک دعوت (Referral) فعال باشد
|
||
- [ ] نوتیفیکیشن Bell icon در Navbar
|
||
|
||
---
|
||
|
||
## 🎉 نتیجهگیری
|
||
|
||
**وضعیت فعلی**: 40% تکمیل (9 ماژول پایه)
|
||
**هدف**: 95% تکمیل (17 ماژول کامل)
|
||
**زمان تخمینی**: 4 هفته (3 مرحله اصلی + 1 اختیاری)
|
||
|
||
**اولویتهای کلیدی**:
|
||
1. 🔴 ClubMembership + Dashboard (هفته 1)
|
||
2. 🔴 Network + Commission (هفته 2)
|
||
3. 🟡 DiscountShop + Enhancements (هفته 3)
|
||
4. 🟢 UI/UX Improvements (هفته 4)
|
||
|
||
**نکته مهم**: دقت کنیم که هیچ چیزی را جا نیندازیم و خارج از ساختار حرکت نکنیم ✅
|
||
|
||
</div>
|