Files
docs/04-FRONTEND/FrontOffice/gap-analysis.md
T
masoodafar-web 119e870a26 feat: Complete overhaul of FourSat documentation structure and content
- 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
2025-12-04 17:32:31 +03:30

34 KiB
Raw Blame History

📊 تحلیل جامع 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:

 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:

[ ] 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:

[ ] 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:

[ ] 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:

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:

[ ] 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

// 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

// 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

@* 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:

{
  "sub": "123",                    // UserId
  "email": "user@example.com",
  "phone": "09123456789",
  "IsSignMainContract": "True",
  "exp": 1234567890
}

استخراج UserId:

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 (خام):

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 (مشتری‌محور):

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)

نکته مهم: دقت کنیم که هیچ چیزی را جا نیندازیم و خارج از ساختار حرکت نکنیم