# 📊 تحلیل جامع 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; // GetMyClubMembershipQueryHandler.cs public class GetMyClubMembershipQueryHandler : IRequestHandler { private readonly IApplicationContractContext _context; private readonly ICurrentUserService _currentUser; public async Task 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 GetMyClubMembership(Empty request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(context); } public override async Task ActivateClubMembership(ActivateClubMembershipRequest request, ServerCallContext context) { return await _dispatchRequestToCQRS.Handle(request, context); } } ``` --- ### ج. UI Page Template ```razor @* Pages/Club/MembershipPage.razor *@ @page "/club/membership" @inject ClubMembershipContract.ClubMembershipContractClient ClubService باشگاه مشتریان باشگاه مشتریان @if (_isLoading) { } else if (_membership != null) { @GetStatusText() @if (!_membership.IsActive) { فعال‌سازی باشگاه (56,000,000 تومان) } else { تاریخ انقضا: @_membership.ExpirationDate.ToPersianDate() } } @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 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) **نکته مهم**: دقت کنیم که هیچ چیزی را جا نیندازیم و خارج از ساختار حرکت نکنیم ✅