Compare commits

..

14 Commits

Author SHA1 Message Date
masoodafar-web df1affa46e docs: mark T4.2, T4.3, T4.13, F2, F3 as completed — phase 8f
- PACKAGE-TRANSFORMATION-TASKS.md: add phase 8f section, mark T4.2/T4.3/T4.13 complete
- FEATURE-BACKLOG.md: mark F2 (ChangeNetworkParent) + F3 (CalculateOrderPV) complete
- NuGet v0.0.188 | CMS:dcd1135 FO:3bffc13 BO:e020354
2026-02-26 22:10:45 +03:30
masoodafar-web 38aababc1a docs: update for Phase 8e — per-package commission reports
- PACKAGE-TRANSFORMATION-TASKS: mark T4.8-T4.12 completed, add Phase 8e section, update tree diagram, bump to NuGet v0.0.187
- OVERVIEW-03-CHANGELOG: add Phase 8e entry, mark commission per-package items done, update timeline & summary table
2026-02-26 21:13:16 +03:30
masoodafar-web e6d086b559 Docs: Phase 8b-8d — BO CRUD expansion + FO Customer RPCs + Proto cleanup
- PACKAGE-TRANSFORMATION-TASKS.md: Add phases 8b, 8c, 8d with full details
  Updated overview diagram, commit hashes, status to 0-8d complete
- OVERVIEW-03-CHANGELOG.md: Add Phase 8b (BO CRUD) + Phase 8a+8c (FO)
  Updated summary table to 99% (240/241 complete)
2026-02-26 18:04:04 +03:30
masoodafar-web a61a987b57 docs: Add Phase 8a — Checkout wire-up + NuGet plan 2026-02-26 03:36:33 +03:30
masoodafar-web d94b09878a docs: Update TASKS for Phase 7a-c completion (16 commits across 3 repos)
- Phase 7a: Cosmetic cleanup (CMS+FO+BO)
- Phase 7b: FrontOffice RPC migration to Customer* RPCs
- Phase 7c: Delete 4 deprecated CQRS handlers (1125 lines removed)
- Updated overview diagram, commit list, and footer
2026-02-26 03:06:22 +03:30
masoodafar-web 0aa126af1c Docs: Phase 5-6 completion — per-package commission + deprecation cleanup
- CHANGELOG: Phase 5 (per-pkg commission, golden cleanup) + Phase 6 (deprecation, ConfigService MagicWallet)
- ROADMAP: Progress 83%→93%, timeline updated through Phase 6
- TASKS: Mark مرحله ۳ (پورسانت) , add commits 607f791→7176fe4→d19c569
2026-02-26 01:14:51 +03:30
masoodafar-web 37330a3e45 docs: update all documentation for Package-Based Transformation Phase 0-4
- OVERVIEW-03-CHANGELOG: Add complete Package-Based section (Phase 0-4) with
  commit references, add summary table row, update timeline
- OVERVIEW-05-ROADMAP: Add Package-Based progress bar (83%), update DONE/NOW
  sections with Phase 0-4 complete and Phase 5-6 pending
- OVERVIEW-02-INDEX: Add 4 new roadmap files to index, update file counts
- BIZ-PACKAGE-BASED-SYSTEM: Status → 'در حال پیاده‌سازی — فاز 0-4 تکمیل'
  with all 7 commit hashes
- PACKAGE-TRANSFORMATION-TASKS: Mark Phase 0/1/2 as complete with commit refs,
  update overview diagram with completion markers
2026-02-26 00:32:33 +03:30
masoodafar-web 977ef69e26 docs(biz): v5 — قرارداد یک‌بار (Q19) + فیچر DIFF (Q20) + First/Last Activation (Q21-Q22) + carryover تغییر پکیج (Q23)
تغییرات بنیادی v5:
- Q19: قرارداد باشگاه فقط یک بار امضا — حذف re-contract از G5, A10, T2.7
- Q20: فیچرها DIFF/تفاضل — FeatureDiffService جدید (مقایسه + اعمال اختلاف)
- Q21: ClubMembership: ActivatedAt → FirstActivationDate + LastActivationDate + FirstPackageId + LastPackageId
- Q22: تشخیص فعال‌شدگان هفته از LastActivationDate
- Q23: carryover strictly per-package — تغییر پکیج = carryover قبلی شمرده نمی‌شود

بخش‌های جدید:
- 5.4: قرارداد یک‌بار + فلوچارت خرید مجدد بدون قرارداد
- 5.5: الگوریتم DIFF فیچرها + مثال عملی + کد پیشنهادی
- 5.6: تشخیص فعال‌شدگان هفته (SQL)
- ClubMembership entity v5 با ۴ فیلد جدید

اصلاحات:
- EXIT Magic Mode: حذف membership.IsActive=false
- State diagram: re-purchase بدون قرارداد
- Migration: ActivatedAt → First/LastActivationDate
- Impact Analysis: 95+ تغییر (51 اصلی + 44 سایدافکت)
- Timeline: ~28 روز مجموع، ~24 روز critical path
2026-02-25 21:50:02 +03:30
masoodafar-web 1885fcbd3b docs: BIZ-PACKAGE-BASED-SYSTEM v4 — comprehensive side-effect discovery
44 NEW side effects discovered across 6 layers (total: 92 changes):

Side Effects — CMS Domain (3):

Side Effects — CMS Application (10):
- ChargeMagicWalletCommandHandler: global MagicWalletMaxDeposit (1B)
- VerifyMagicWalletChargeCommandHandler: global multiplier ×2.5
- UserOrderService EXIT/ENTRY: global caps → user trapped/ejected wrong
- 3 FluentValidation validators: hardcoded 1B ceiling
- GetAllFeatureIds(): ALL features granted regardless of package
- JWT: no PackageId/CanRepurchase, just boolean HasPurchased
- WalletGrpcService.GetMagicWalletStatus: global caps to frontend
- 4 Notifications: no PackageId in interface

Side Effects — Background (3):
- ClubMembershipCycleSeedService: seeds with hardcoded amounts
- DayaLoanStatusCheckWorker: global DayaLoanAmount
- ChatikaAccountActivationWorker: no package filter

Side Effects — FrontOffice (9):
- Contract text '56M toman' = LEGAL LIABILITY
- Magic wallet ×2.5 and deposit cap hardcoded (6 places + C# code)
- 'پکیج طلایی' hardcoded (5+ places) — wrong name
- PackageId=1 hardcoded in activation flow

Side Effects — BackOffice (8):
- ManualActivationDialog: 56M hardcoded + disabled + no package selector
- SystemConfigurationPage: global settings need per-package
- CSV exports (3 places): no package column

Impact: 48 core changes + 44 side effects = 92 total
Timeline: v3 17 days → v4 22 days critical path (+5 days)
2026-02-25 00:27:14 +03:30
masoodafar-web 33d5ae9305 docs: BIZ-PACKAGE-BASED-SYSTEM v3 — per-package commission deep analysis
Major v3 changes:
- Q12-Q18: MaxWeeklyBalancesPerLeg, MaxNetworkLevel, MagicWalletMaxDeposit,
  MagicWalletMaxCredit all become per-package (not global SystemConstants)
- NetworkWeeklyBalance gets PackageId + Unique(UserId,WeekId,PackageId)
- SP changes: @MaxBalancesPerLeg and @MaxNetworkLevel as dynamic params
  (removing hardcoded 300/15)
- SpCommissionCalculationStrategy: pass package settings to SPs
- Carryover per-package: week-shifting only for same PackageId records
- commission.proto: package_id+package_title in 4 message types,
  new CustomerCommissionPackageSummary message, package filter in requests
- FrontOffice: commission dashboard with per-package summary cards
- BackOffice: package filter dropdown in all commission reports + CSV
- Package Create/Edit: Quick Access checkboxes for features inline
- Seed data: silver MaxBalancesPerLeg=30, MagicWalletMax=100M/250M
- Migration: NetworkWeeklyBalances existing records get base PackageId
- Impact Analysis: 39 -> 48+ changes across 6 layers
- Timeline: 14 -> 17 days critical path (+3 days for per-package work)

Updated docs:
- business/BIZ-PACKAGE-BASED-SYSTEM.md (v2 -> v3)
- roadmap/PACKAGE-TRANSFORMATION-TASKS.md (synced with v3)
2026-02-24 23:48:09 +03:30
masoodafar-web 01244f426e docs: package-based transformation — complete roadmap + UX impact + feature backlog
New documents:
- roadmap/FEATURE-BACKLOG.md: 12 kept RPCs → feature tasks with priority,
  target pages, and time estimates (F1-F12)
- roadmap/PACKAGE-TRANSFORMATION-UX.md: UX impact analysis —
  before/after wireframes for 19 pages (10 FO + 9 BO),
  customer + admin experience changes, future needs prediction
- roadmap/PACKAGE-TRANSFORMATION-TASKS.md: step-by-step implementation
  plan (6 phases, ~13 day critical path), atomic tasks with
  code diffs, dependency graph, test checklist

Updated:
- cms/GRPC-SERVICES-AUDIT.md: cross-references to new docs

Total: 998 lines of documentation covering:
- 12 RPC feature tasks prioritized by package-based relevance
- 19 page wireframes (before/after comparison)
- 39 transformation tasks broken into 6 phases
- 10 predicted future requirements (N1-N10)
- Risk analysis + rollback plan + calendar
2026-02-24 23:18:50 +03:30
masoodafar-web 3575e483b9 docs: deep analysis of 24 dead gRPC RPCs — keep 12, archive 12
Analyzed all 24 dead RPC implementations line-by-line:
- 12 KEEP (future-proof): CustomerReorderPreviousOrder, CustomerTrackOrder,
  CalculateOrderPV, GetInventorySummary, GetStockValueReport, BulkAddStock,
  BulkUpdateProductStock, GetConfigurationByKey, UpdateCustomerSettings,
  ChangeNetworkParent, AssignFeatureToMembership, GetLowStockProducts
- 12 ARCHIVE: fms.proto (2), BulkAdjustStock, 2 empty order stubs,
  2 non-functional configs, 2 redundant city ops, 3 duplicate RPCs

Key findings:
- 17/24 were actually FULLY IMPLEMENTED, just never wired to frontend
- fms.proto is the only completely dead proto file (no service class)
- Archive != Delete — marked for exclusion only
2026-02-24 22:40:44 +03:30
masoodafar-web 09b8b804d4 docs: audit all CMS gRPC services — 342 RPCs, 125 unused from frontends, 24 dead code 2026-02-24 22:25:53 +03:30
masoodafar-web dd5a2617cf docs: BIZ-PACKAGE-BASED-SYSTEM v2 — deep analysis + approved decisions
- 6 bugs found (DiscountBalance, UserPackagePurchase, re-purchase blocked)
- 15 hardcodes identified for removal
- 7 guards blocking re-purchase analyzed
- 5 payment path inconsistencies documented
- 39 changes across 6 layers planned
- 5 phases: bugfix → infra → logic → commission → UI → test
- v1 draft preserved as BIZ-PACKAGE-BASED-SYSTEM-v1-draft.md
2026-02-24 21:34:59 +03:30
9 changed files with 3583 additions and 422 deletions
@@ -0,0 +1,554 @@
# 📦 سیستم مبتنی بر پکیج (Package-Based System)
> **وضعیت:** تحلیل و بررسی — منتظر تایید
> **تاریخ:** اسفند ۱۴۰۴
> **تاثیرگذاری:** زیاد — بخش‌های متعدد سیستم تحت تاثیر قرار می‌گیرد
---
## ۱. خلاصه فیچر
**وضعیت فعلی:** سیستم فقط یک پکیج پایه (۵۶ میلیون تومان) دارد و همه چیز حول آن می‌چرخد.
**وضعیت هدف:** سیستم چندین پکیج با قیمت‌ها و ویژگی‌های متفاوت پشتیبانی می‌کند. هر پکیج روش‌های پرداخت، محاسبه پورسانت، شارژ کیف پول و فیچرهای مختص خود را دارد.
```
مثال پکیج‌ها:
┌──────────────┬──────────────┬──────────────┬──────────────┐
│ 🥈 نقره‌ای │ 🥇 طلایی │ 💎 الماسی │ ⭐ ویژه │
│ ۵.۶M تومان │ ۵۶M تومان │ ؟؟ تومان │ ؟؟ تومان │
│ │ (پکیج پایه) │ │ │
│ فقط مستقیم │ دایا+مستقیم │ فقط مستقیم │ فقط مستقیم │
│ فیچر محدود │ همه فیچرها │ همه فیچرها │ همه+اختصاصی │
└──────────────┴──────────────┴──────────────┴──────────────┘
```
---
## ۲. وضعیت فعلی سیستم (AS-IS)
### ۲.۱ فلوی فعلی فعالسازی
```mermaid
flowchart TD
A["کاربر وارد سیستم می‌شود"] --> B{"روش پرداخت"}
B -->|"خرید الماس دایا"| C["DayaLoan — ۵۶M"]
B -->|"پرداخت مستقیم"| D["درگاه بانکی — ۵۶M"]
C --> E["بررسی موفقیت پرداخت"]
D --> E
E --> F["شارژ کیف پول"]
F --> G["مدال قرارداد باشگاه مشتریان"]
G --> H["تایید OTP + امضا"]
H --> I["فعال‌سازی عضویت باشگاه"]
I --> J["اختصاص فیچرها"]
I --> K["ایجاد Cycle"]
I --> L["اضافه به Commission Pool"]
J --> M["✅ کاربر فعال — لینک معرف"]
```
### ۲.۲ جریان پول فعلی
```
کاربر ۵۶M پرداخت می‌کند
├── Balance (کیف پول عادی) += ۵۶,۰۰۰,۰۰۰ ریال
├── DiscountBalance (اعتباری) += ۱۱۲,۰۰۰,۰۰۰ ریال (×۲)
└── Club Activation:
├── CommissionPool += ۲۵,۲۰۰,۰۰۰ ریال (ClubActivationFee)
└── GiftValue = ۲۵,۲۰۰,۰۰۰ ریال (اطلاع‌رسانی)
```
### ۲.۳ مقادیر Hardcoded فعلی (`SystemConstants.cs`)
| ثابت | مقدار | کاربرد |
|------|-------|--------|
| `BasePackageAmount` | ۵۶,۰۰۰,۰۰۰ | قیمت پکیج |
| `DayaLoanAmount` | ۵۶,۰۰۰,۰۰۰ | مبلغ وام دایا |
| `ClubActivationFee` | ۲۵,۲۰۰,۰۰۰ | سهم هفتگی Commission Pool |
| `ClubMembershipGiftValue` | ۲۵,۲۰۰,۰۰۰ | ارزش هدیه حق عضویت |
| `MagicWalletMultiplier` | ×۲.۵ | ضریب کیف پول جادویی |
### ۲.۴ مشکلات فعلی
| # | مشکل | فایل |
|---|------|------|
| ۱ | پکیج ID=4 **hardcoded** در `InitiateBasePackagePaymentCommandHandler` | Application/Commands |
| ۲ | مبلغ ۵۶M **hardcoded** در `SystemConstants` و چندین handler | Domain/Common |
| ۳ | فیچرها **همه یکجا** assign می‌شن (۴ فیچر ثابت: چتیکا، بیمه، تریپ، لرن) | ActivateClubMembershipHandler |
| ۴ | Commission Pool فقط با `ClubActivationFee` ثابت پر می‌شه | ActivateClubMembershipHandler |
| ۵ | `DiscountBalance = Amount × 2` — ضریب hardcoded | VerifyPayment handlers |
| ۶ | فرانت‌اند فقط یک مسیر خرید نشون میده | FrontOffice pages |
---
## ۳. طراحی پیشنهادی (TO-BE)
### ۳.۱ فلوی جدید فعالسازی
```mermaid
flowchart TD
A["کاربر وارد سیستم"] --> B["صفحه پکیج‌ها<br/>(کاشی‌های نقره‌ای/طلایی/الماسی/...)"]
B -->|"کلیک روی پکیج"| C{"نوع پکیج"}
C -->|"پکیج پایه (طلایی)"| D["مدال با دو گزینه:<br/>۱. خرید الماس دایا<br/>۲. پرداخت مستقیم"]
C -->|"پکیج‌های دیگر"| E["مدال با یک گزینه:<br/>فقط پرداخت مستقیم<br/>+ توضیحات + قیمت"]
D -->|"دایا"| F["فلوی دایا"]
D -->|"مستقیم"| G["درگاه پرداخت"]
E --> G
F --> H["پرداخت موفق"]
G --> H
H --> I["شارژ کیف پول<br/>(متناسب با قیمت پکیج)"]
I --> J["مدال قرارداد باشگاه"]
J --> K["OTP + امضا"]
K --> L["فعال‌سازی<br/>+ اختصاص فیچرهای پکیج"]
L --> M["✅ کاربر فعال"]
```
### ۳.۲ تغییرات Entity — Package
**فعلی:**
```csharp
public class Package : BaseAuditableEntity
{
public string Title { get; set; }
public string Description { get; set; }
public string ImagePath { get; set; }
public long Price { get; set; }
}
```
**پیشنهادی:**
```csharp
public class Package : BaseAuditableEntity
{
public string Title { get; set; }
public string Description { get; set; }
public string ImagePath { get; set; }
public long Price { get; set; } // قیمت پکیج (ریال)
// === فیلدهای جدید ===
public int SortOrder { get; set; } // ترتیب نمایش
public bool IsActive { get; set; } = true; // فعال/غیرفعال
public bool IsBasePackage { get; set; } // آیا پکیج پایه است؟
public bool SupportsDayaPurchase { get; set; } // پشتیبانی از خرید دایا
public bool SupportsDirectPurchase { get; set; } = true; // پشتیبانی از پرداخت مستقیم
// === محاسبات مالی ===
public long ActivationFee { get; set; } // سهم Commission Pool
public long GiftValue { get; set; } // ارزش هدیه
public decimal DiscountMultiplier { get; set; } = 2.0m; // ضریب شارژ DiscountBalance
// === Navigation ===
public virtual ICollection<PackageFeature> PackageFeatures { get; set; }
public virtual ICollection<UserPackagePurchase> Purchases { get; set; }
}
```
### ۳.۳ Entity جدید — PackageFeature (پل بین پکیج و فیچر)
```csharp
/// <summary>
/// مشخص می‌کند هر پکیج چه فیچرهایی را فعال می‌کند
/// </summary>
public class PackageFeature : BaseAuditableEntity
{
public long PackageId { get; set; }
public virtual Package Package { get; set; }
public long ClubFeatureId { get; set; }
public virtual ClubFeature ClubFeature { get; set; }
public bool IsIncluded { get; set; } = true; // آیا این فیچر در پکیج هست؟
}
```
### ۳.۴ تغییرات Entity — ClubMembership
```csharp
public class ClubMembership : BaseAuditableEntity
{
// ... فیلدهای فعلی حفظ می‌شوند ...
// === فیلد جدید ===
public long PackageId { get; set; } // کدام پکیج خریداری شده
public virtual Package Package { get; set; }
}
```
### ۳.۵ تغییرات Entity — ClubMembershipCycle
```csharp
public class ClubMembershipCycle : BaseAuditableEntity
{
// ... فیلدهای فعلی حفظ می‌شوند ...
// === فیلد جدید ===
public long PackageId { get; set; } // پکیج این سایکل
public virtual Package Package { get; set; }
// PackageAmount قبلاً وجود دارد — از Package.Price پر می‌شود
}
```
### ۳.۶ تغییرات Entity — WeeklyCommissionPool
```csharp
public class WeeklyCommissionPool : BaseAuditableEntity
{
// ... فیلدهای فعلی حفظ می‌شوند ...
// === فیلد جدید ===
public long PackageId { get; set; } // Pool جداگانه برای هر پکیج
public virtual Package Package { get; set; }
}
```
### ۳.۷ جریان پول جدید
```
پکیج نقره‌ای (۵.۶M):
├── Balance += ۵,۶۰۰,۰۰۰
├── DiscountBalance += ۱۱,۲۰۰,۰۰۰ (×۲)
└── CommissionPool += ActivationFee مخصوص نقره‌ای
پکیج طلایی/پایه (۵۶M):
├── Balance += ۵۶,۰۰۰,۰۰۰
├── DiscountBalance += ۱۱۲,۰۰۰,۰۰۰ (×۲)
└── CommissionPool += ۲۵,۲۰۰,۰۰۰
پکیج الماسی (??M):
├── Balance += ??
├── DiscountBalance += ?? (×۲)
└── CommissionPool += ActivationFee مخصوص الماسی
```
---
## ۴. محاسبه پورسانت — تغییرات
### ۴.۱ وضعیت فعلی
```
یک WeeklyCommissionPool برای کل هفته
TotalAmount = مجموع ActivationFee همه فعالسازی‌ها
ValuePerBalance = TotalAmount ÷ مجموع Balance‌ها
همه یکسان محاسبه می‌شوند
```
### ۴.۲ وضعیت هدف
```
برای هر پکیج، یک WeeklyCommissionPool جداگانه:
Pool_نقره‌ای:
TotalAmount = مجموع ActivationFee خریداران نقره‌ای این هفته
Balance‌ها = فقط از شبکه خریداران نقره‌ای
ValuePerBalance = Pool_نقره‌ای ÷ Balance_نقره‌ای
Pool_طلایی:
TotalAmount = مجموع ActivationFee خریداران طلایی این هفته
Balance‌ها = فقط از شبکه خریداران طلایی
ValuePerBalance = Pool_طلایی ÷ Balance_طلایی
```
### ۴.۳ نکته مهم: ساختار شبکه یکی است
```
[Ali]
/ \
[Sara] [Reza] ← شبکه باینری یکی‌ست
/ \ / \
[M1] [M2] [M3] [M4]
ولی محاسبات جدا:
- Ali با پکیج طلایی → پورسانت از Pool طلایی
- Sara با پکیج نقره‌ای → پورسانت از Pool نقره‌ای
- Reza با پکیج طلایی → پورسانت از Pool طلایی
```
### ۴.۴ تغییرات Stored Procedure
**`sp_CalculateWeeklyBalances`** باید:
- پارامتر `@PackageId` بگیرد
- فقط کاربرانی که این پکیج را خریده‌اند فیلتر کند
- برای هر پکیج جداگانه اجرا شود
**`sp_CalculateWeeklyCommissionPool`** باید:
- پارامتر `@PackageId` بگیرد
- Pool مخصوص آن پکیج را بخواند
- پرداخت‌ها فقط به خریداران آن پکیج اختصاص یابد
---
## ۵. فیچرهای باشگاه مشتریان بر اساس پکیج
### ۵.۱ وضعیت فعلی
وقتی کاربر فعال می‌شود، **همه ۴ فیچر** یکجا assign می‌شوند:
```csharp
// ActivateClubMembershipCommandHandler — خط ~350
var allFeatureIds = ClubFeatureTypeExtensions.GetAllFeatureIds();
foreach (var featureId in allFeatureIds)
{
userClubFeatures.Add(new UserClubFeature { ... });
}
```
### ۵.۲ وضعیت هدف
فیچرها بر اساس جدول `PackageFeature` تعیین می‌شوند:
| فیچر | نقره‌ای | طلایی (پایه) | الماسی |
|------|---------|-------------|--------|
| چتیکا | ❌ | ✅ | ✅ |
| بیمه | ❌ | ✅ | ✅ |
| تریپ | ✅ | ✅ | ✅ |
| لرن | ✅ | ✅ | ✅ |
| فیچر VIP | ❌ | ❌ | ✅ |
*مقادیر بالا نمونه‌ای هستند — قابل تنظیم از BackOffice*
### ۵.۳ تغییر در ActivateClubMembershipHandler
```
قبلی:
GetAllFeatureIds() → assign all
جدید:
Package.PackageFeatures
.Where(pf => pf.IsIncluded)
.Select(pf => pf.ClubFeatureId)
→ assign only included features
```
---
## ۶. تغییرات UI — FrontOffice
### ۶.۱ صفحه پکیج‌ها (کاشی‌ها)
```
┌─────────────────────────────────────────────────────┐
│ انتخاب پکیج باشگاه مشتریان │
├─────────────┬──────────────┬──────────────┬─────────┤
│ │ │ │ │
│ 🥈 نقره‌ای │ 🥇 طلایی │ 💎 الماسی │ ⭐ ویژه │
│ ۵.۶M │ ۵۶M │ ؟؟M │ ؟؟M │
│ │ │ │ │
│ ● لرن │ ● چتیکا │ ● همه │ ● همه │
│ ● تریپ │ ● بیمه │ ● + VIP │ ● +... │
│ │ ● تریپ │ │ │
│ │ ● لرن │ │ │
│ │ │ │ │
│ [انتخاب] │ [انتخاب] │ [انتخاب] │[انتخاب]│
└─────────────┴──────────────┴──────────────┴─────────┘
```
### ۶.۲ مدال پرداخت — پکیج پایه (طلایی)
```
┌─────────────────────────────────────────┐
│ خرید پکیج طلایی — ۵۶M تومان │
│ │
│ توضیحات: ... │
│ │
│ روش‌های پرداخت: │
│ ┌─────────────────────────────────┐ │
│ │ 💎 خرید از طریق الماس دایا │ │
│ └─────────────────────────────────┘ │
│ ┌─────────────────────────────────┐ │
│ │ 💳 پرداخت مستقیم (درگاه بانکی) │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘
```
### ۶.۳ مدال پرداخت — پکیج‌های دیگر (نقره‌ای و بالاتر)
```
┌─────────────────────────────────────────┐
│ خرید پکیج نقره‌ای — ۵.۶M تومان │
│ │
│ توضیحات: ... │
│ ویژگی‌ها: لرن، تریپ │
│ │
│ ┌─────────────────────────────────┐ │
│ │ 💳 پرداخت و فعال‌سازی │ │
│ └─────────────────────────────────┘ │
└─────────────────────────────────────────┘
```
---
## ۷. بخش‌های تحت تاثیر (Impact Analysis)
### ۷.۱ جدول تاثیرپذیری
| # | لایه | فایل/بخش | نوع تغییر | شدت |
|---|------|----------|-----------|-----|
| ۱ | **Domain** | `Package.cs` | اضافه فیلد | 🟡 متوسط |
| ۲ | **Domain** | `PackageFeature.cs`**جدید** | Entity جدید | 🔴 زیاد |
| ۳ | **Domain** | `ClubMembership.cs` | اضافه `PackageId` | 🟡 متوسط |
| ۴ | **Domain** | `ClubMembershipCycle.cs` | اضافه `PackageId` | 🟡 متوسط |
| ۵ | **Domain** | `WeeklyCommissionPool.cs` | اضافه `PackageId` | 🔴 زیاد |
| ۶ | **Domain** | `SystemConstants.cs` | حذف hardcode‌ها → خوانش از Package | 🟡 متوسط |
| ۷ | **Application** | `ActivateClubMembershipCommandHandler` | فیچر بر اساس پکیج | 🔴 زیاد |
| ۸ | **Application** | `InitiateBasePackagePaymentCommandHandler` | حذف ID=4 hardcoded | 🟡 متوسط |
| ۹ | **Application** | `VerifyBasePackagePaymentCommandHandler` | شارژ متناسب با پکیج | 🔴 زیاد |
| ۱۰ | **Application** | `VerifyPackagePurchasePaymentCommandHandler` | شارژ متناسب با پکیج | 🔴 زیاد |
| ۱۱ | **Application** | `ManualPaymentCommandHandler` | شارژ متناسب با پکیج | 🟡 متوسط |
| ۱۲ | **Application** | `CustomerPurchasePackageCommandHandler` | پشتیبانی روش‌های پرداخت پکیج | 🟡 متوسط |
| ۱۳ | **Infra** | `sp_CalculateWeeklyBalances` | پارامتر PackageId | 🔴 زیاد |
| ۱۴ | **Infra** | `sp_CalculateWeeklyCommissionPool` | Pool جداگانه هر پکیج | 🔴 زیاد |
| ۱۵ | **Infra** | `WeeklyCommissionCalculationService` | Loop روی پکیج‌ها | 🟡 متوسط |
| ۱۶ | **Infra** | EF Configurations | جدول جدید + FK‌ها | 🟡 متوسط |
| ۱۷ | **Infra** | Database Migration | schema changes | 🟡 متوسط |
| ۱۸ | **Proto** | `package.proto` | فیلدهای جدید پکیج | 🟢 کم |
| ۱۹ | **Proto** | `clubmembership.proto` | PackageId در response | 🟢 کم |
| ۲۰ | **Proto** | `commission.proto` | PackageId در pool/payout | 🟢 کم |
| ۲۱ | **FrontOffice** | صفحه انتخاب پکیج | UI جدید (کاشی‌ها) | 🔴 زیاد |
| ۲۲ | **FrontOffice** | مدال پرداخت | دو مدال متفاوت | 🔴 زیاد |
| ۲۳ | **FrontOffice** | `MyPackages.razor` | نمایش نوع پکیج | 🟡 متوسط |
| ۲۴ | **FrontOffice** | `ActivateClubDialog.razor` | ارتباط با پکیج | 🟡 متوسط |
| ۲۵ | **BackOffice** | صفحه مدیریت پکیج‌ها | CRUD فیلدهای جدید | 🟡 متوسط |
| ۲۶ | **BackOffice** | صفحه فیچر پکیج‌ها — **جدید** | ماتریس پکیج×فیچر | 🔴 زیاد |
| ۲۷ | **BackOffice** | `ActivateClubDialog.razor` | انتخاب پکیج | 🟡 متوسط |
### ۷.۲ ریسک‌ها
| ریسک | احتمال | شدت | راه‌حل |
|------|--------|-----|--------|
| داده‌های فعلی — کاربران بدون PackageId | قطعی | زیاد | Migration: کاربران فعلی → PackageId = پکیج پایه |
| Commission Pool فعلی بدون PackageId | قطعی | زیاد | Migration: Pool‌های موجود → PackageId = پکیج پایه |
| SP تغییر → محاسبات اشتباه | متوسط | بحرانی | تست جامع + محیط staging |
| مبالغ hardcoded در جاهای پراکنده | زیاد | متوسط | Audit کامل کدبیس |
| عدم سازگاری FrontOffice/BackOffice | متوسط | متوسط | تست end-to-end |
---
## ۸. فازبندی پیاده‌سازی
### فاز ۱ — زیرساخت (Domain + DB) ≈ ۳-۴ روز
| تسک | شرح |
|-----|------|
| T1.1 | بروزرسانی `Package` entity (فیلدهای جدید) |
| T1.2 | ایجاد `PackageFeature` entity + EF Configuration |
| T1.3 | اضافه کردن `PackageId` به `ClubMembership` |
| T1.4 | اضافه کردن `PackageId` به `ClubMembershipCycle` |
| T1.5 | اضافه کردن `PackageId` به `WeeklyCommissionPool` |
| T1.6 | Database Migration + Seed data (پکیج پایه + فیچرها) |
| T1.7 | Migration: کاربران/Pool‌های فعلی → PackageId = پکیج پایه |
| T1.8 | بروزرسانی Proto‌ها |
### فاز ۲ — منطق کسب‌وکار (Application) ≈ ۴-۵ روز
| تسک | شرح |
|-----|------|
| T2.1 | بروزرسانی `ActivateClubMembershipCommandHandler` — فیچر بر اساس پکیج |
| T2.2 | بروزرسانی Verify handlers — شارژ کیف پول متناسب با پکیج |
| T2.3 | حذف مقادیر hardcoded از `SystemConstants` → خوانش از Package |
| T2.4 | بروزرسانی `InitiateBasePackagePayment` → Generic `InitiatePackagePayment` |
| T2.5 | بروزرسانی `ManualPaymentCommandHandler` — پشتیبانی پکیج متغیر |
| T2.6 | CRUD پکیج با فیلدهای جدید (gRPC handlers) |
| T2.7 | CRUD `PackageFeature` (ماتریس پکیج×فیچر) |
### فاز ۳ — محاسبه پورسانت ≈ ۳-۴ روز
| تسک | شرح |
|-----|------|
| T3.1 | بروزرسانی `sp_CalculateWeeklyBalances` — فیلتر بر اساس PackageId |
| T3.2 | بروزرسانی `sp_CalculateWeeklyCommissionPool` — Pool جداگانه |
| T3.3 | بروزرسانی `WeeklyCommissionCalculationService` — Loop روی پکیج‌ها |
| T3.4 | تست محاسبات با داده واقعی |
### فاز ۴ — UI (FrontOffice + BackOffice) ≈ ۴-۵ روز
| تسک | شرح |
|-----|------|
| T4.1 | صفحه کاشی‌های پکیج (FrontOffice) |
| T4.2 | مدال پرداخت پکیج پایه (دایا + مستقیم) |
| T4.3 | مدال پرداخت پکیج‌های دیگر (فقط مستقیم) |
| T4.4 | بروزرسانی `MyPackages.razor` — نمایش نوع پکیج |
| T4.5 | بروزرسانی `ActivateClubDialog.razor` — ارتباط با پکیج |
| T4.6 | BackOffice: CRUD پکیج با فیلدهای جدید |
| T4.7 | BackOffice: صفحه ماتریس فیچرهای پکیج |
| T4.8 | BackOffice: `ActivateClubDialog` — انتخاب پکیج |
### فاز ۵ — تست و استقرار ≈ ۲-۳ روز
| تسک | شرح |
|-----|------|
| T5.1 | تست end-to-end فلوی خرید هر پکیج |
| T5.2 | تست محاسبه پورسانت جداگانه |
| T5.3 | تست migration داده‌های فعلی |
| T5.4 | Deploy به staging + تست |
| T5.5 | Deploy به production |
---
## ۹. Seed Data — پکیج‌های اولیه
```sql
-- Migration: Seed packages
INSERT INTO Packages (Title, Description, Price, IsActive, IsBasePackage,
SupportsDayaPurchase, SupportsDirectPurchase, ActivationFee, GiftValue,
DiscountMultiplier, SortOrder)
VALUES
('نقره‌ای', 'پکیج نقره‌ای باشگاه مشتریان', 5600000, 1, 0,
0, 1, ???, ???, 2.0, 1),
('طلایی', 'پکیج طلایی باشگاه مشتریان (پایه)', 56000000, 1, 1,
1, 1, 25200000, 25200000, 2.0, 2);
-- Migration: ربط فیچرها به پکیج‌ها
INSERT INTO PackageFeatures (PackageId, ClubFeatureId, IsIncluded) VALUES
-- نقره‌ای: فقط تریپ و لرن
(@silverId, @tripId, 1),
(@silverId, @learnId, 1),
-- طلایی: همه فیچرها
(@goldId, @chatikaId, 1),
(@goldId, @bimeId, 1),
(@goldId, @tripId, 1),
(@goldId, @learnId, 1);
-- Migration: کاربران فعلی → پکیج پایه
UPDATE ClubMemberships SET PackageId = @goldId WHERE PackageId IS NULL;
UPDATE ClubMembershipCycles SET PackageId = @goldId WHERE PackageId IS NULL;
UPDATE WeeklyCommissionPools SET PackageId = @goldId WHERE PackageId IS NULL;
```
---
## ۱۰. سوالات باز (نیاز به تصمیم‌گیری)
| # | سوال | گزینه‌ها |
|---|------|---------|
| ۱ | `ActivationFee` و `GiftValue` پکیج نقره‌ای چقدر باشد؟ | نسبت به قیمت؟ مقدار ثابت؟ |
| ۲ | آیا کاربر می‌تواند بعداً پکیج خود را ارتقا دهد (upgrade)؟ | بله → فقط مابه‌التفاوت / خیر |
| ۳ | `DiscountMultiplier` برای همه پکیج‌ها ×۲ باشد؟ | یکسان / متفاوت به ازای هر پکیج |
| ۴ | ضریب `MagicWallet` (×۲.۵) برای پکیج‌های کوچکتر هم همان باشد؟ | بله / خیر |
| ۵ | فیچرهای پکیج نقره‌ای دقیقاً کدام‌ها هستند؟ | لرن+تریپ؟ فقط لرن؟ |
| ۶ | آیا یک کاربر می‌تواند چند پکیج همزمان داشته باشد؟ | فقط یکی / امکان خرید چندتا |
| ۷ | نام و تعداد دقیق پکیج‌ها چیست؟ | نقره‌ای+طلایی؟ بیشتر؟ |
| ۸ | کاربرانی که با دایا فعال شدن، چه پکیجی دارند؟ | طلایی (پایه) |
---
## ۱۱. تخمین زمانی
| فاز | مدت | وابستگی |
|-----|------|---------|
| فاز ۱ — زیرساخت | ۳-۴ روز | — |
| فاز ۲ — منطق | ۴-۵ روز | فاز ۱ |
| فاز ۳ — پورسانت | ۳-۴ روز | فاز ۱ |
| فاز ۴ — UI | ۴-۵ روز | فاز ۲ |
| فاز ۵ — تست | ۲-۳ روز | فاز ۳, ۴ |
| **مجموع** | **~۱۶-۲۱ روز کاری** | |
> فازهای ۲ و ۳ قابل موازی‌سازی هستند.
File diff suppressed because it is too large Load Diff
+219
View File
@@ -0,0 +1,219 @@
# آدیت سرویس‌های gRPC — CMS
> تاریخ: ۱۴۰۴/۰۴
> آخرین بروزرسانی: ۱۴۰۴/۱۲/۰۶
> هدف: شناسایی RPCهایی که از هیچ‌کدام از فرانت‌ها (FrontOffice مشتری + BackOffice ادمین) فراخوانی نمی‌شوند + تصمیم‌گیری نگهداری vs آرشیو
---
## 📊 خلاصه آمار
| متریک | تعداد |
|--------|-------|
| کل فایل‌های proto | 43 (بدون google/) |
| کل سرویس‌های gRPC | 42 |
| **کل RPC متدها** | **342** |
| استفاده‌شده در FrontOffice | 92 |
| استفاده‌شده در BackOffice | 159 |
| **استفاده‌شده (مجموع یکتا)** | **217** |
| **استفاده‌نشده از فرانت‌ها** | **125** |
| ↳ استفاده‌شده داخلی CMS | 101 |
| ↳ **کد مُرده واقعی** | **24** |
---
## 🔴 بخش ۱ — تحلیل ۲۴ RPC مُرده: نگهداری vs آرشیو
### ✅ نگهداری (آینده‌نگرانه — ۱۲ عدد)
> این RPCها پیاده‌سازی کامل دارند و در نقشه‌راه آینده محصول کاربرد دارند.
| # | RPC | فایل Proto | کیفیت کد | دلیل نگهداری |
|---|-----|-----------|---------|-------------|
| 1 | `CustomerReorderPreviousOrder` | userorder.proto | ✅ **کامل** — آیتم‌های سفارش قبلی به سبد اضافه می‌شود | UX حیاتی: «تکرار سفارش قبلی» — فیچر رایج فروشگاهی، فقط نیاز به دکمه در FrontOffice |
| 2 | `CustomerTrackOrder` | userorder.proto | ✅ **کامل** — وضعیت + TrackingCode + DeliveryInfo | UX حیاتی: «ردیابی سفارش» — وقتی ارسال پستی فعال شود ضروری است |
| 3 | `CalculateOrderPV` | userorder.proto | ✅ **کامل** — PV هر آیتم + جمع کل | سیستم MLM: محاسبه PV (Point Value) سفارش — برای فاز بعدی کمیسیون بر اساس خرید |
| 4 | `GetInventorySummary` | inventory.proto | ✅ **کامل** — آمار تعداد + ارزش کل | داشبورد ادمین: خلاصه موجودی انبار — نیاز به کارت در BackOffice Dashboard |
| 5 | `GetStockValueReport` | inventory.proto | ✅ **کامل** — گزارش ارزش ریالی موجودی | گزارش مالی: ارزش دارایی انبار — برای حسابداری ضروری |
| 6 | `BulkAddStock` | inventory.proto | ✅ **کامل** — loop با error handling | عملیات انبوه: افزودن موجودی دسته‌ای — بعد از ورود کالای فیزیکی |
| 7 | `BulkUpdateProductStock` | products.proto | ✅ **کامل** — Set/Add/Subtract با error handling | عملیات انبوه: بروزرسانی دسته‌ای موجودی محصول |
| 8 | `GetConfigurationByKey` | configuration.proto | ✅ **کامل** — خواندن از SystemConstants | API مفید: دریافت یک تنظیم خاص بدون بارگذاری همه — performance بهتر |
| 9 | `UpdateCustomerSettings` | user.proto | ✅ **کامل** — Email/SMS/Push notifications | تنظیمات اعلان‌ها: وقتی پنل تنظیمات مشتری ساخته شود |
| 10 | `ChangeNetworkParent` | networkmembership.proto | ✅ **CQRS کامل** → MoveInNetworkCommand | مدیریت شبکه: جابجایی کاربر در درخت — ابزار ادمین ضروری |
| 11 | `AssignFeatureToMembership` | clubmembership.proto | ✅ **CQRS کامل** → AssignClubFeatureCommand | مدیریت عضویت: اختصاص فیچر به عضویت — برای فاز بسته‌بندی پویا |
| 12 | `GetLowStockProducts` | products.proto | ✅ **کامل** — فیلتر threshold + pagination | هشدار موجودی: مکمل GetLowStockItems — فیلتر ClubExclusive اضافه دارد |
### 🗑️ آرشیو (حذف امن — ۱۲ عدد)
> این RPCها یا stub خالی هستند، یا جایگزین بهتری دارند، یا هرگز ساخته نشدند.
| # | RPC | فایل Proto | وضعیت کد | دلیل آرشیو |
|---|-----|-----------|---------|-----------|
| 1 | `CreateNewFileInfo` | fms.proto | ❌ **۰ رفرنس** — هیچ Service/Handler ندارد | سرویس FMS هرگز طراحی نشد — فایل‌ها از imageresolver استفاده می‌کنند |
| 2 | `DeleteFileInfo` | fms.proto | ❌ **۰ رفرنس** — هیچ Service/Handler ندارد | همان — کل fms.proto حذف‌شدنی |
| 3 | `BulkAdjustStock` | inventory.proto | ❌ **۰ رفرنس** — حتی Service method ندارد | هرگز پیاده‌سازی نشد — از AdjustStock تکی استفاده می‌شود |
| 4 | `CreateNewOrderForCustomer` | userorder.proto | ❌ **Stub خالی**`return new()` | مسیر سفارش مشتری از SubmitShopBuyOrder می‌گذرد — تکراری |
| 5 | `SubmitOrderForCustomer` | userorder.proto | ❌ **Stub خالی**`return new()` | مسیر سفارش مشتری از SubmitShopBuyOrder می‌گذرد — تکراری |
| 6 | `DeactivateConfiguration` | configuration.proto | ❌ **throw میکند** — «تنظیمات فقط خواندنی هستند» | عمداً غیرفعال شده — SystemConstants ثابت هستند |
| 7 | `GetConfigurationHistory` | configuration.proto | ❌ **خالی برمی‌گرداند**`return new()` | SystemConstants تاریخچه ندارند — بی‌معنی |
| 8 | `DeleteCity` | City.proto | ✅ کامل ولی **بی‌نیاز** | شهرها seed دیتا هستند — حذف شهر باعث خرابی آدرس‌ها می‌شود |
| 9 | `UpdateCity` | City.proto | ✅ کامل ولی **بی‌نیاز** | شهرها از سرویس خارجی seed شده‌اند — ویرایش دستی نیاز نیست |
| 10 | `GetOrdersByDateRange` | userorder.proto | ✅ کامل ولی **تکراری** | `GetAllUserOrderByFilter` همین قابلیت + فیلترهای بیشتر دارد |
| 11 | `GetServiceHealth` | health.proto | ✅ کامل ولی **تکراری** | `GetSystemHealth` کل سیستم را برمی‌گرداند — فیلتر client-side کافی است |
| 12 | `GetCategoryByIdForCustomer` | category.proto | ✅ کامل ولی **تکراری** | `GetCategory` (admin) + `GetAllCategoriesForCustomer` کافی است |
---
## 🟡 بخش ۲ — استفاده داخلی CMS (Internal Only — ۱۰۱ عدد)
> این RPCها از فرانت‌ها فراخوانی نمی‌شوند ولی **در کد بکند CMS فعال هستند** (background services, handlers, internal flows). **حذف نشوند!**
### B1. احراز هویت و کاربر (user.proto)
| RPC | رفرنس CMS | علت |
|-----|-----------|-----|
| `CreateNewUser` | 175 | ثبت‌نام کاربر — اصلی‌ترین فلو |
| `GetJwtToken` | 38 | صدور توکن JWT |
| `AdminGetJwtToken` | 19 | لاگین ادمین |
| `SetPasswordForUser` | 24 | تنظیم رمز عبور |
| `ChangeCustomerPassword` | 5 | تغییر رمز مشتری |
| `UploadCustomerAvatar` | 6 | آپلود آواتار |
| `GetCustomerProfile` | 13 | پروفایل مشتری |
| `GetCustomerReferrals` | 13 | لیست معرفی‌شدگان |
| `GetCustomerSettings` | 13 | تنظیمات مشتری |
### B2. بسته‌ها و پرداخت (package.proto / manualpayment.proto)
| RPC | رفرنس CMS | علت |
|-----|-----------|-----|
| `PurchaseGoldenPackage` | 21 | خرید بسته طلایی — فلو فعال |
| `VerifyGoldenPackagePurchase` | 22 | تأیید خرید بسته طلایی |
| `CustomerPurchasePackage` | 3 | خرید مشتری (proto-generated + service) |
| `CustomerVerifyPackagePurchase` | 3 | تأیید خرید مشتری |
| `GetCustomerPurchaseHistory` | 13 | تاریخچه خرید |
| `ProcessManualMembershipPayment` | 20 | پرداخت دستی عضویت |
### B3. شبکه و عضویت (networkmembership.proto / clubmembership.proto)
| RPC | رفرنس CMS | علت |
|-----|-----------|-----|
| `JoinNetwork` | 14 | پیوستن به شبکه — فراخوانی خودکار |
| `RemoveFromNetwork` | 14 | حذف از شبکه |
### B4. کمیسیون (commission.proto)
| RPC | رفرنس CMS | علت |
|-----|-----------|-----|
| `CalculateWeeklyBalances` | 26 | سرویس پس‌زمینه هفتگی |
| `CalculateWeeklyCommissionPool` | 22 | سرویس پس‌زمینه هفتگی |
| `ProcessUserPayouts` | 15 | پردازش پرداخت‌ها |
| `GetCommissionPayoutHistory` | 20 | تاریخچه پرداخت کمیسیون |
### B5. انبارداری (inventory.proto)
| RPC | رفرنس CMS | علت |
|-----|-----------|-----|
| `ConfirmSale` | 10 | تأیید فروش — فلو سفارش |
| `ReserveStock` | 12 | رزرو موجودی — فلو سفارش |
| `ReleaseReservation` | 10 | آزادسازی رزرو |
| `ProcessReturn` | 6 | پردازش مرجوعی |
| `DeleteWarehouse` | 18 | حذف انبار |
| `GetInventoryByProduct` | 26 | موجودی بر اساس محصول |
| `GetInventoryItem` | 19 | آیتم انبار |
| `GetWarehouse` | 18 | دریافت انبار |
| `SetDefaultWarehouse` | 18 | تنظیم انبار پیش‌فرض |
| `UpdateWarehouse` | 18 | بروزرسانی انبار |
| `GetStockMovementsByInventoryItem` | 17 | حرکات موجودی |
### B6. تراکنش‌ها (transactions.proto)
| RPC | رفرنس CMS | علت |
|-----|-----------|-----|
| `CreateNewTransactions` | 26 | ایجاد تراکنش — فلو پرداخت |
| `DeleteTransactions` | 23 | حذف تراکنش |
| `GetAllTransactionsByFilter` | 25 | لیست تراکنش‌ها |
| `CustomerPaymentVerification` | 3 | تأیید پرداخت مشتری |
| `GetCustomerTransaction` | 27 | تراکنش مشتری |
| `GetCustomerTransactionsByFilter` | 14 | فیلتر تراکنش‌ها |
| `RefundTransaction` | 31 | استرداد تراکنش |
| `UpdateTransactions` | 23 | بروزرسانی تراکنش |
| `VerifyTransaction` | 24 | تأیید تراکنش |
### B7. سایر CRUD داخلی (خلاصه)
> ۵۸ RPC در فایل‌های contract, usercontract, factordetails, productcategory, productgalleries, productimages, userwallet, userwalletchangelog, otptoken, usercarts, discountproduct, public_messages, category, products, producttag, tag, City, useraddress, userorder — همه CRUD داخلی با ≥3 رفرنس در CMS.
---
## 🟢 بخش ۳ — سرویس‌های کاملاً مورد استفاده
### فایل‌های proto که تمام RPCهایشان استفاده می‌شود:
| فایل Proto | کل RPC | استفاده FO | استفاده BO |
|-----------|--------|-----------|-----------|
| appversion.proto | 3 | ✅ 1 | ✅ 3 |
| blogcategory.proto | 6 | ✅ 2 | ✅ 6 |
| blogpost.proto | 11 | ✅ 5 | ✅ 9 |
| blogpostimage.proto | 4 | ✅ 0 | ✅ 4 |
| discountcategory.proto | 4 | ✅ 1 | ✅ 4 |
| discountorder.proto | 7 | ✅ 3 | ✅ 4 |
| discountshoppingcart.proto | 5 | ✅ 5 | ✅ 0 |
| manualpayment.proto | 5 | ✅ 0 | ✅ 4 |
| public_messages.proto | 8 | ✅ 0 | ✅ 7 |
| role.proto | 5 | ✅ 0 | ✅ 5 |
| sitepage.proto | 10 | ✅ 2 | ✅ 10 |
| sitepagesettings.proto | 5 | ✅ 1 | ✅ 5 |
| tag.proto | 6 | ✅ 0 | ✅ 5 |
| userrole.proto | 5 | ✅ 0 | ✅ 5 |
---
## 📋 بخش ۴ — خلاصه تصمیمات
### ماتریکس نهایی ۲۴ RPC مُرده
```
✅ نگهداری (12): CustomerReorderPreviousOrder, CustomerTrackOrder,
CalculateOrderPV, GetInventorySummary, GetStockValueReport,
BulkAddStock, BulkUpdateProductStock, GetConfigurationByKey,
UpdateCustomerSettings, ChangeNetworkParent,
AssignFeatureToMembership, GetLowStockProducts
🗑️ آرشیو (12): CreateNewFileInfo, DeleteFileInfo, BulkAdjustStock,
CreateNewOrderForCustomer, SubmitOrderForCustomer,
DeactivateConfiguration, GetConfigurationHistory,
DeleteCity, UpdateCity, GetOrdersByDateRange,
GetServiceHealth, GetCategoryByIdForCustomer
```
### فایل‌های proto آرشیو‌شدنی (کامل)
| فایل | وضعیت | اقدام |
|------|-------|-------|
| **fms.proto** | کل فایل مُرده (2 RPC) | حذف از csproj — ساخته نشود |
### RPCهای آرشیو‌شدنی (جزئی — داخل فایل‌های فعال)
| فایل Proto | RPCهای آرشیو | RPCهای فعال |
|-----------|-------------|-------------|
| inventory.proto | `BulkAdjustStock` (1) | 23 فعال |
| userorder.proto | `CreateNewOrderForCustomer`, `SubmitOrderForCustomer` (2) | 18 فعال |
| configuration.proto | `DeactivateConfiguration`, `GetConfigurationHistory` (2) | 5 فعال |
| City.proto | `DeleteCity`, `UpdateCity` (2) | 6 فعال |
| health.proto | `GetServiceHealth` (1) | 1 فعال |
| category.proto | `GetCategoryByIdForCustomer` (1) | 7 فعال |
---
## ⚠️ نکات مهم
1. **آرشیو ≠ حذف!** — RPCهای آرشیو‌شده با `[Obsolete]` + `#region [ARCHIVED]` علامت‌گذاری شدند (کامیت `13dd0f5`)
2. RPCهای دسته B (Internal — ۱۰۱ عدد) **حیاتی** هستند — بدون آنها سیستم از کار می‌افتد
3. RPCهای «نگهداری» (۱۲ عدد) کد **کامل و آماده** دارند — بکلاگ فیچر: [FEATURE-BACKLOG.md](../roadmap/FEATURE-BACKLOG.md)
4. **fms.proto** از csproj اکسکلود شد (کامیت `13dd0f5`)
5. نقشه‌راه تحول پکیج‌بیس: [PACKAGE-TRANSFORMATION-TASKS.md](../roadmap/PACKAGE-TRANSFORMATION-TASKS.md)
6. قبل از هر تغییر، حتماً `grep -rn "RpcName" CMS/src/` بزنید تا مطمئن شوید
---
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۰۶*
+11 -4
View File
@@ -3,8 +3,8 @@
> **فهرست کامل ۱۵ فایل مستند پروژه FourSat (کارا بازار سلامت)** > **فهرست کامل ۱۵ فایل مستند پروژه FourSat (کارا بازار سلامت)**
> **تاریخ تجمیع:** اسفند ۱۴۰۴ > **تاریخ تجمیع:** اسفند ۱۴۰۴
> **تعداد فایل‌های مبدأ:** ۵۳ فایل (~۳۲,۰۰۰ خط) > **تعداد فایل‌های مبدأ:** ۵۳ فایل (~۳۲,۰۰۰ خط)
> **تعداد فایل‌های نهایی:** ۱۷ فایل (۱۵ اصلی + ۲ roadmap) > **تعداد فایل‌های نهایی:** ۲۲ فایل (۱۵ اصلی + ۷ roadmap/business)
> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (فعال‌سازی درگاه + مرج Production + بهبود UI) > **آخرین بروزرسانی:** اسفند ۱۴۰۴ (تحول پکیج‌بیس فاز ۰-۴ + فعال‌سازی درگاه + مرج Production)
--- ---
@@ -35,7 +35,10 @@ totalDoc/
└── 📁 roadmap/ (فیچرهای جدید — در حال توسعه) └── 📁 roadmap/ (فیچرهای جدید — در حال توسعه)
├── MAGIC-WALLET-SPEC.md مشخصات کیف‌پول جادویی ├── MAGIC-WALLET-SPEC.md مشخصات کیف‌پول جادویی
── MAGIC-WALLET-PLAN.md پلن پیاده‌سازی + checklist ── MAGIC-WALLET-PLAN.md پلن پیاده‌سازی + checklist
├── PACKAGE-TRANSFORMATION-TASKS.md تسک‌های تحول پکیج‌بیس (فاز 0-5)
├── PACKAGE-TRANSFORMATION-UX.md تاثیر بر UX فرانت‌ها
└── FEATURE-BACKLOG.md بکلاگ ۱۲ RPC آماده
``` ```
--- ---
@@ -77,7 +80,11 @@ totalDoc/
| # | فایل | موضوع | خلاصه | | # | فایل | موضوع | خلاصه |
|---|------|--------|--------| |---|------|--------|--------|
| R1 | [MAGIC-WALLET-SPEC](../roadmap/MAGIC-WALLET-SPEC.md) | کیف‌پول جادویی — مشخصات | State Machine، ضریب ×2.5، سقف 100M، قوانین، API، مدل داده | | R1 | [MAGIC-WALLET-SPEC](../roadmap/MAGIC-WALLET-SPEC.md) | کیف‌پول جادویی — مشخصات | State Machine، ضریب ×2.5، سقف 100M، قوانین، API، مدل داده |
| R2 | [MAGIC-WALLET-PLAN](../roadmap/MAGIC-WALLET-PLAN.md) | کیف‌پول جادویی — پلن | ۶ فاز، **فاز 1-5 تکمیل ✅**، فاز 6 باقی | | R2 | [MAGIC-WALLET-PLAN](../roadmap/MAGIC-WALLET-PLAN.md) | کیف‌پول جادویی — پلن | ۶ فاز، **فاز 1-6 تکمیل ✅** |
| R3 | [PACKAGE-TRANSFORMATION-TASKS](../roadmap/PACKAGE-TRANSFORMATION-TASKS.md) | تحول پکیج‌بیس — تسک‌ها | ۵ فاز، **فاز 0-4 تکمیل ✅**، فاز 5-6 در انتظار |
| R4 | [PACKAGE-TRANSFORMATION-UX](../roadmap/PACKAGE-TRANSFORMATION-UX.md) | تاثیر بر UX | تحلیل تاثیر بر FrontOffice + BackOffice |
| R5 | [FEATURE-BACKLOG](../roadmap/FEATURE-BACKLOG.md) | بکلاگ فیچرها | ۱۲ RPC آماده بدون UI، اولویت‌بندی‌شده |
| R6 | [BIZ-PACKAGE-BASED-SYSTEM](../business/BIZ-PACKAGE-BASED-SYSTEM.md) | طراحی سیستم پکیج‌بیس | v5، ۲۳ تصمیم + ۵۱ تغییر + ۴۴ سایدافکت |
--- ---
+114 -6
View File
@@ -1,7 +1,7 @@
# 📜 تاریخچه کارهای انجام‌شده # 📜 تاریخچه کارهای انجام‌شده
> **همه فعالیت‌های پروژه به صورت بولت با توضیح یک‌خطی و درصد تکمیل** > **همه فعالیت‌های پروژه به صورت بولت با توضیح یک‌خطی و درصد تکمیل**
> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (بروزرسانی: فعال‌سازی درگاه + مرج پروداکشن + بهبود UI ادمین) > **آخرین بروزرسانی:** اسفند ۱۴۰۴ (بروزرسانی: فاز ۸e — Per-Package Commission Reports | NuGet v0.0.187)
--- ---
@@ -9,12 +9,13 @@
| حوزه | تعداد آیتم | تکمیل‌شده | درصد کل | | حوزه | تعداد آیتم | تکمیل‌شده | درصد کل |
|------|-----------|----------|---------| |------|-----------|----------|---------|
| **BackOffice** | 61 | 60 | **98%** | | **BackOffice** | 61 | 61 | **100%** |
| **FrontOffice** | 40 | 38 | **95%** | | **FrontOffice** | 40 | 40 | **100%** |
| **CMS Core** | 58 | 56 | **97%** | | **CMS Core** | 72 | 72 | **100%** |
| **Package-Based System** | 35 | 35 | **100%** |
| **Deployment** | 22 | 21 | **95%** | | **Deployment** | 22 | 21 | **95%** |
| **Migration** | 16 | 16 | **100%** | | **Migration** | 16 | 16 | **100%** |
| **مجموع** | **197** | **191** | **97%** | | **مجموع** | **246** | **245** | **99%** |
--- ---
@@ -66,6 +67,13 @@
- ✅ فیلتر کاربر در صفحه ClubMembers — UserAutoComplete در تولبار جستجو - ✅ فیلتر کاربر در صفحه ClubMembers — UserAutoComplete در تولبار جستجو
- ✅ نمایش نام کاربر در WalletManagementPage — TemplateColumn با UserName + ID - ✅ نمایش نام کاربر در WalletManagementPage — TemplateColumn با UserName + ID
### Phase 8b: CRUD پکیج کامل (اسفند ۱۴۰۴)
- ✅ CreateDialog: اضافه ۱۲ فیلد جدید — SortOrder, ActivationFee, DiscountMultiplier, MagicWallet*, MaxBalancesPerLeg, MaxNetworkLevel, IsActive, IsBasePackage, SupportsDirectPurchase, SupportsDayaPurchase
- ✅ UpdateDialog: همان ۱۲ فیلد جدید — ایجاد فرم کامل ادمین
- ✅ PackageMainPage Grid: ۴ ستون جدید — قیمت (N0), ترتیب, وضعیت (فعال/غیرفعال chip), نوع (پایه/عادی chip)
- ✅ فیکس `HasPurchasedGoldenPackage``HasPurchasedPackage` — UserNetworkInfo.razor
- ✅ NuGet bump 0.0.184 → 0.0.186 + local feed source
--- ---
## ۲. FrontOffice — فازها (95% کامل) ## ۲. FrontOffice — فازها (95% کامل)
@@ -97,6 +105,13 @@
- ✅ دکمه پرداخت شارژ کیف‌پول اعتباری — ChargeDiscountWallet.razor فعال شد (حذف «بزودی») - ✅ دکمه پرداخت شارژ کیف‌پول اعتباری — ChargeDiscountWallet.razor فعال شد (حذف «بزودی»)
- ✅ دکمه پرداخت شارژ کیف‌پول جادویی — MagicWallet.razor فعال شد (حذف «بزودی») - ✅ دکمه پرداخت شارژ کیف‌پول جادویی — MagicWallet.razor فعال شد (حذف «بزودی»)
- ✅ دکمه‌های پرداخت مستقیم خرید پکیج — Index.razor هر دو شاخه فعال شدند (حذف «بزودی») - ✅ دکمه‌های پرداخت مستقیم خرید پکیج — Index.razor هر دو شاخه فعال شدند (حذف «بزودی»)
### Phase 8a+8c: Checkout + Package Pages (اسفند ۱۴۰۴)
- ✅ Checkout wire-up — مهاجرت به `CustomerPurchasePackageAsync` (حذف dead code قدیمی)
- ✅ PackageDetail: `GetPackageAsync``GetCustomerPackageDetailsAsync` — features/specs از API (نه hardcoded)
- ✅ Packages.razor: un-exclude از build + dynamic feature bullets از `CustomerPackageModel`
- ✅ PackageService: `PackageDto` غنی‌شده با ۸ فیلد جدید + `GetUserPackageStatusAsync` متصل به RPC واقعی
- ✅ NuGet bump 0.0.182 → 0.0.186 + local feed source
- ✅ فیکس GwUrl پروداکشن — تصحیح از cms.kbs1.ir به cms.kbs2.ir - ✅ فیکس GwUrl پروداکشن — تصحیح از cms.kbs1.ir به cms.kbs2.ir
### محتوا و ناوبری ### محتوا و ناوبری
@@ -217,7 +232,98 @@
--- ---
## ۷. Timeline (جدول زمانی) ## ۷. تحول سیستم پکیج‌بیس (Package-Based Transformation) — 90%
> 📦 تبدیل سیستم تک‌پکیجی hardcoded به معماری چند‌پکیجی داینامیک
> مرجع: [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) | [PACKAGE-TRANSFORMATION-TASKS.md](../roadmap/PACKAGE-TRANSFORMATION-TASKS.md)
### Phase 0 — فیکس باگ‌های فوری ✅ (`8b9c317`, `fe3edd1`)
- ✅ B1: DiscountBalance شارژ نمی‌شد در VerifyGoldenPackagePurchase — اضافه `DiscountBalance += Amount × 2` + WalletChangeLog
- ✅ B2: UserPackagePurchase ساخته نمی‌شد در VerifyGoldenPackagePurchase — ساخت record بعد verify
- ✅ B3: UserPackagePurchase ساخته نمی‌شد در VerifyPackagePurchase — ساخت record
- ✅ B4: UserPackagePurchase ساخته نمی‌شد در VerifyBasePackagePayment — ساخت record
- ✅ B6: EXIT Magic Mode — ریست PackagePurchaseMethod + بستن چرخه فعلی
### Phase 1 — زیرساخت Domain ✅ (`ae92ab8`)
- ✅ T1.1: Package Entity — ۱۱ فیلد جدید (SortOrder, IsActive, IsBasePackage, DiscountMultiplier, MagicWalletMultiplier, ...)
- ✅ T1.2: PackageFeature Entity — رابطه M:N بین Package و ClubFeature
- ✅ T1.3: ClubMembership — ۴ فیلد First/Last Activation + PackageId
- ✅ T1.4-T1.6: اضافه PackageId به ClubMembershipCycle, WeeklyCommissionPool, UserCommissionPayout, NetworkWeeklyBalance, UserWalletChangeLog
- ✅ T1.7: علامت‌گذاری ۹ SystemConstants به‌عنوان [Obsolete]
- ✅ T1.8: EF Configurations — Index, Precision, FK relations
### Phase 1.5 — Migration + Data Seed ✅ (`a9cd2fd`)
- ✅ EF Migration `AddPackageBasedSystem` — ستون‌ها + جداول + ایندکس‌ها
- ✅ Golden Package Seed (Id=1) — Price=56M, ActivationFee=25.2M, DiscountMultiplier=2.0, MagicWalletMultiplier=2.5
- ✅ Data Backfill — تمام رکوردهای موجود → PackageId=1
- ✅ فیکس nullable DateTime/long در ClubMembership
- ✅ فیکس Shadow FK PackageId1
### Phase 2 — منطق کسب‌وکار ✅ (`8e5c7c5`)
- ✅ T2.1: ActivateClubMembership — ActivationFee از Package entity
- ✅ T2.2: AcceptClubMembershipContract — Package features از DB
- ✅ T2.3: CalculateWeeklyBalances — MaxBalancesPerLeg per-package
- ✅ T2.4: ProcessUserPayouts — PackageId tracking
- ✅ T2.5: DayaLoans — Package.Price بجای hardcoded
- ✅ T2.6: ManualPayment — Package.Price بجای hardcoded
- ✅ T2.7: InitiateBasePackage/VerifyBasePackage — Package-based
- ✅ T2.8: ChargeMagicWallet/VerifyMagicWalletCharge — MagicWalletMultiplier per-package
- ✅ T2.9: OrmCommissionCalculationStrategy — MaxBalancesPerLeg/MaxNetworkLevel per-package
- ✅ T2.10: ConfigurationService/UserOrderService/UserWalletService — Package reads
-**نتیجه:** صفر مصرف SystemConstants deprecated باقی مانده
### Phase 3 — بازسازی لایه Package ✅ (`ccb938e`)
- ✅ Proto: ۱۱ فیلد جدید در ۵ message (CreateNewPackageRequest, UpdatePackageRequest, GetPackageResponse, ...)
- ✅ GetUserPackageStatus — پیاده‌سازی (قبلاً NotImplementedException بود!)
- ✅ CustomerVerifyPackagePurchase — شارژ کیف‌پول اضافه شد (قبلاً missing بود!)
- ✅ VerifyGoldenPackagePurchase — `package.DiscountMultiplier` بجای hardcoded ×2
- ✅ GetAllPackageByFilter — فیلتر IsDeleted
- ✅ GetCustomerPackages — فیلتر IsDeleted + IncludeInactive + SortOrder
- ✅ GetCustomerPackageDetails — PackageFeatures از DB
- ✅ GetCustomerPurchaseHistory — Include Transaction
- ✅ UpdatePackageCommand — ۱۲ فیلد جدید
### Phase 4 — تکمیل CRUD + Legacy Fixes ✅ (`0002a5a`)
- ✅ CreateNewPackageCommand — ۱۲ فیلد جدید با default‌های مناسب
- ✅ GetPackageResponseDto — ۱۲ فیلد جدید (Mapster auto-map)
- ✅ GetAllPackageByFilterResponseModel — ۱۲ فیلد جدید
- ✅ PurchaseGoldenPackage — حذف Title string match شکننده (`"طلایی"/"golden"`) → `IsDeleted/IsActive/SupportsDirectPurchase`
- ✅ VerifyPackagePurchase — حذف hardcoded `order.Amount × 2``package.DiscountMultiplier` از DB
### Phase 5 — پورسانت per-package + پاکسازی golden ✅ (`607f791`, `7176fe4`)
- ✅ ORM Commission: per-user-package calculation via `ClubMembership.LastPackageId`
- userPackageMap، per-user maxBalancesPerLeg/maxNetworkLevel
- Carryover keyed by (UserId, PackageId) tuple
- ✅ SP Commission: loop over packages، pass `@PackageId/@InputMaxBalancesPerLeg/@InputMaxNetworkLevel`
- ✅ sp_CalculateWeeklyBalances: ۳ پارامتر جدید، فیلتر `cm.LastPackageId = @PackageId`، ستون PackageId در INSERT
- ✅ Fix: `cm.PackageId``cm.LastPackageId` — match actual DB column name
- ✅ Fix golden/طلایی string refs in user-facing messages (ActivateClubMembership)
- ✅ Rename `HasPurchasedGoldenPackage``HasPurchasedPackage` (DTO + Handler + Proto + Mapping)
### Phase 6 — Deprecation cleanup + ConfigurationService ✅ (`d19c569`)
- ✅ Mark `PurchaseGoldenPackage`/`VerifyGoldenPackagePurchase` RPCs as `deprecated = true`
- ✅ Mark `InitiateBasePackagePayment`/`VerifyBasePackagePayment` RPCs as `deprecated = true`
- ✅ Remove deprecated SystemConstants from `GetAllAsDict`/`GetAllWithDescriptions` helpers
- ✅ Add MagicWallet per-package values to ConfigurationService (Multiplier, MaxDeposit, MaxCredit)
- ✅ تأیید: صفر رفرنس فعال به ۹ SystemConstants منسوخ — dead code آماده حذف
### Phase 7 — UI ✅ (گزارش per-package)
- ⬜ FrontOffice: کاشی‌های داینامیک پکیج
- ⬜ FrontOffice: MyPackages + re-purchase
- ✅ FrontOffice: Commission Dashboard per-package — فیلتر dropdown پکیج + ستون پکیج + MudChip (دسکتاپ + موبایل)
- ✅ FrontOffice: WeeklyBalance per-package — فیلتر MudSelect پکیج + MudChip اطلاعات هفته
- ✅ BackOffice: فیلتر پکیج در گزارش‌ها — PackageSelect component + UserPayouts + BalancesReport
### Phase 8e — Per-Package Commission Reports ✅ (CMS:`aaaf7fc` FO:`a956cb9` BO:`8be98ae`)
- ✅ Proto: اضافه `package_id` فیلتر به ۴ request + `package_id`/`package_title` به ۴ response model
- ✅ CMS: اضافه PackageId فیلتر به ۴ query + handler + ۳ DTO + CommissionProfile mapping
- ✅ BO: کامپوننت PackageSelect + فیلتر و ستون پکیج در UserPayouts + BalancesReport
- ✅ FO: فیلتر و ستون پکیج در CommissionDashboard + WeeklyBalance
- ✅ NuGet: `0.0.186``0.0.187`
---
## ۸. Timeline (جدول زمانی)
| زمان | رویداد | درصد پروژه | | زمان | رویداد | درصد پروژه |
|------|--------|-----------| |------|--------|-----------|
@@ -232,3 +338,5 @@
| اسفند ۱۴۰۳ (هفته ۴) | مستندات + نهایی‌سازی | 95% | | اسفند ۱۴۰۳ (هفته ۴) | مستندات + نهایی‌سازی | 95% |
| اسفند ۱۴۰۴ (هفته ۱-۲) | 🪄 کیف‌پول جادویی (فاز 1-6) + اصلاح VAT 10% | 96% | | اسفند ۱۴۰۴ (هفته ۱-۲) | 🪄 کیف‌پول جادویی (فاز 1-6) + اصلاح VAT 10% | 96% |
| اسفند ۱۴۰۴ (هفته ۳) | 🚀 فعال‌سازی درگاه + بهبود UI ادمین + مرج پروداکشن | 97% | | اسفند ۱۴۰۴ (هفته ۳) | 🚀 فعال‌سازی درگاه + بهبود UI ادمین + مرج پروداکشن | 97% |
| اسفند ۱۴۰۴ (هفته ۴) | 📦 تحول پکیج‌بیس فاز ۰-۶ (Domain → Migration → Business → Package → CRUD → Commission per-pkg → Deprecation) | 97% |
| اسفند ۱۴۰۴ (هفته ۵) | 📦 فاز 8e: گزارش‌های پورسانت per-package (Proto + CMS + BO + FO) | 98% |
+5 -2
View File
@@ -1,20 +1,21 @@
# 🗺️ نقشه راه، ریسک‌ها و کارهای باقیمانده # 🗺️ نقشه راه، ریسک‌ها و کارهای باقیمانده
> **Roadmap + Risk Register + Dependencies + Priorities** > **Roadmap + Risk Register + Dependencies + Priorities**
> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (بروزرسانی: فعال‌سازی درگاه + مرج پروداکشن + بهبود UI) > **آخرین بروزرسانی:** اسفند ۱۴۰۴ (بروزرسانی: تحول پکیج‌بیس فاز ۰-۶ + per-package commission + deprecation cleanup)
--- ---
## ۱. وضعیت فعلی پروژه ## ۱. وضعیت فعلی پروژه
``` ```
██████████████████████████████████████████████████ 97% ██████████████████████████████████████████████████ 95%
Core Platform ████████████████████████████████████████████████ 98% Core Platform ████████████████████████████████████████████████ 98%
Club System ████████████████████████████████████████████████ 98% Club System ████████████████████████████████████████████████ 98%
E-Commerce ████████████████████████████████████████████████ 98% E-Commerce ████████████████████████████████████████████████ 98%
Payment ████████████████████████████████████████████████ 97% Payment ████████████████████████████████████████████████ 97%
Magic Wallet ████████████████████████████████████████████████ 100% Magic Wallet ████████████████████████████████████████████████ 100%
Package-Based ██████████████████████████████████████████████░░ 93%
UI/UX █████████████████████████████████████████████░░░ 93% UI/UX █████████████████████████████████████████████░░░ 93%
Deployment ██████████████████████████████████████████████░░ 95% Deployment ██████████████████████████████████████████████░░ 95%
Documentation ████████████████████████████████████████████████ 100% Documentation ████████████████████████████████████████████████ 100%
@@ -207,8 +208,10 @@ DONE (اسفند ۱۴۰۴):
→ بهبود UI ادمین (UserAutoComplete + نام کاربر در کیف‌پول) ✅ → بهبود UI ادمین (UserAutoComplete + نام کاربر در کیف‌پول) ✅
→ مرج پروداکشن هر ۳ ریپو (CMS + FO + BO) ✅ → مرج پروداکشن هر ۳ ریپو (CMS + FO + BO) ✅
→ اجرای Migration روی پروداکشن ✅ → اجرای Migration روی پروداکشن ✅
→ 📦 تحول پکیج‌بیس فاز 0-6 ✅ (Domain → Migration → Business → Package → CRUD → Commission per-pkg → Deprecation)
NOW (این ماه): NOW (این ماه):
→ 📦 فاز 7: UI (کاشی‌های داینامیک + فیلتر پکیج + MyPackages)
→ EF Migration نهایی → EF Migration نهایی
→ تست کامل پروداکشن → تست کامل پروداکشن
+81
View File
@@ -0,0 +1,81 @@
# 📋 فیچر بکلاگ — RPCهای آماده (بدون UI)
> تاریخ: ۱۴۰۴/۱۲/۱۰
> منبع: آدیت gRPC (کامیت `3575e48`) → ۱۲ RPC کامل بدون فرانت
> اولویت‌بندی: بر اساس ارزش کسب‌وکار + نیازمندی پکیج‌بیس
---
## 🎯 خلاصه
از ۲۴ RPC مُرده شناسایی‌شده، **۱۲ عدد پیاده‌سازی کامل** دارند ولی هرگز از فرانت‌ها وصل نشدند. این‌ها فیچرهای آماده هستند که فقط نیاز به UI دارند.
---
## 📊 ماتریس فیچر × اولویت
### 🔴 اولویت بالا — مرتبط با پکیج‌بیس کردن
| # | RPC | تارگت | صفحه | اقدام | تخمین |
|---|-----|-------|------|-------|-------|
| F1 | `AssignFeatureToMembership` | BackOffice | ClubFeaturesPage.razor | دکمه «اختصاص فیچر به عضو» + ماتریس PackageFeature | ۴ ساعت |
| F2 | `ChangeNetworkParent` | BackOffice | UserNetworkInfo.razor | ✅ دکمه «تغییر والد» + مودال ChangeParentDialog | BO:`e020354` |
| F3 | `CalculateOrderPV` | FrontOffice | Store/OrderDetail.razor | ✅ نمایش PV سفارش + PV هر محصول | FO:`3bffc13` |
### 🟡 اولویت متوسط — بهبود UX فروشگاه
| # | RPC | تارگت | صفحه | اقدام | تخمین |
|---|-----|-------|------|-------|-------|
| F4 | `CustomerReorderPreviousOrder` | FrontOffice | OrderHistory (Store/Discount) | دکمه «تکرار سفارش» در هر ردیف تاریخچه | ۳ ساعت |
| F5 | `CustomerTrackOrder` | FrontOffice | OrderTracking.razor | وصل Tracking API → نمایش TrackingCode + وضعیت ارسال | ۴ ساعت |
| F6 | `UpdateCustomerSettings` | FrontOffice | Profile/Settings.razor | فرم تنظیمات اعلان (Email/SMS/Push) + دکمه ذخیره | ۳ ساعت |
| F7 | `GetLowStockProducts` | BackOffice | LowStockPage.razor | وصل API → فیلتر threshold + هشدار بصری | ۳ ساعت |
### 🟢 اولویت پایین — گزارش‌دهی و عملیات انبوه
| # | RPC | تارگت | صفحه | اقدام | تخمین |
|---|-----|-------|------|-------|-------|
| F8 | `GetInventorySummary` | BackOffice | InventoryMainPage.razor | کارت خلاصه بالای صفحه (تعداد کل + ارزش ریالی) | ۳ ساعت |
| F9 | `GetStockValueReport` | BackOffice | InventoryMainPage.razor | تب «گزارش ارزش» + دانلود Excel | ۴ ساعت |
| F10 | `BulkAddStock` | BackOffice | InventoryMainPage.razor | دکمه «افزودن دسته‌ای» + آپلود CSV/فرم چندتایی | ۶ ساعت |
| F11 | `BulkUpdateProductStock` | BackOffice | InventoryMainPage.razor | دکمه «بروزرسانی دسته‌ای» (Set/Add/Subtract) | ۶ ساعت |
| F12 | `GetConfigurationByKey` | Internal | — | بدون UI — استفاده داخلی بهینه بجای GetAll | ۰ |
---
## 📐 نقشه پیاده‌سازی
### فاز A — همراه پکیج‌بیس (فاز ۴ BIZ-PACKAGE-BASED-SYSTEM)
```
F1 (AssignFeatureToMembership) → با T4.6 (ماتریس PackageFeature) ادغام
F2 (ChangeNetworkParent) ✅ تکمیل → BO:`e020354`
F3 (CalculateOrderPV) ✅ تکمیل → FO:`3bffc13`
```
### فاز B — بعد از پکیج‌بیس (Sprint بعدی)
```
F4 → F7: بهبود UX فروشگاه و مشتری
تخمین: ۱۳ ساعت = ~۲ روز
```
### فاز C — آینده (بدون فوریت)
```
F8 → F12: گزارش‌دهی و عملیات انبوه
تخمین: ۱۹ ساعت = ~۳ روز
```
---
## 🔗 ارجاعات
| مستند | محتوا |
|-------|-------|
| [GRPC-SERVICES-AUDIT.md](../cms/GRPC-SERVICES-AUDIT.md) | آدیت کامل ۳۴۲ RPC — ۱۲ نگهداری + ۱۲ آرشیو |
| [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) | طراحی سیستم پکیج‌بیس — ۳۹ تغییر |
---
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۱۰ — F2+F3 تکمیل | باقی‌مانده فاز A: F1*
+781
View File
@@ -0,0 +1,781 @@
# 🔄 نقشه‌راه تحول پکیج‌بیس — تسک‌های گام‌به‌گام
> **وضعیت:** در حال اجرا — **فاز ۰-۸f (UI تکمیل) ✅** | NuGet v0.0.188 | تست باقی‌مانده
> **تاریخ:** ۱۴۰۴/۱۲/۱۰
> **پیش‌نیاز:** [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) **v3** (تکمیل پورسانت per-package)
> **هدف:** شکستن **۴۸+ تغییر** به تسک‌های اتمیک با ترتیب اجرا و وابستگی‌ها
> **کامیت‌ها:**
> CMS: `8b9c317`→`fe3edd1`→`ae92ab8`→`a9cd2fd`→`8e5c7c5`→`ccb938e`→`0002a5a`→`607f791`→`7176fe4`→`d19c569`→`469d97b`→`161f796`→`8446e0e`→`ce8e248`→`7554d70`→`aaaf7fc`→`dcd1135`
> FrontOffice: `b82cac4`→`71f391a`→`0bbc11e`→`d71d463`→`40882c8`→`a956cb9`→`3bffc13`
> BackOffice: `f1b0085`→`89f5241`→`c96377a`→`8be98ae`→`e020354`
> ⚠️ **تغییرات v3:** پورسانت per-package، carryover مجزا، SP parameters داینامیک، گزارش‌دهی FO/BO per-package
---
## 📊 نمای کلی
```
مرحله ۰: فیکس باگ فوری (۱ روز) ✅ `8b9c317` + `fe3edd1`
└─→ مرحله ۱: زیرساخت Domain + DB (۴ روز) ✅ `ae92ab8`
└─→ مرحله ۱.۵: Migration + Seed ✅ `a9cd2fd`
├─→ مرحله ۲: منطق کسب‌وکار (۴ روز) ✅ `8e5c7c5`
│ └─→ مرحله ۳: بازسازی لایه Package ✅ `ccb938e`
│ └─→ مرحله ۴: CRUD + Legacy Fixes ✅ `0002a5a`
│ └─→ مرحله UI (۵ روز) ✅
└─→ مرحله ۳: پورسانت (۴ روز) ✅ `607f791`+`7176fe4`
└─→ مرحله ۶: Deprecation cleanup ✅ `d19c569`
└─→ مرحله ۷: Migration + Cleanup ✅
├─→ 7a: Cosmetic cleanup ✅ CMS:`469d97b` FO:`b82cac4` BO:`f1b0085`
├─→ 7b: FO RPC migration ✅ CMS:`161f796` FO:`71f391a`
└─→ 7c: Delete deprecated ✅ CMS:`8446e0e`
└─→ مرحله ۸: FO/BO Completion
├─→ 8a: Checkout wire-up ✅ FO:`0bbc11e`
├─→ 8b: BO CRUD expansion ✅ CMS:`ce8e248` BO:`89f5241`
├─→ 8c: FO Package pages ✅ FO:`d71d463`
└─→ 8d: Proto cleanup ✅ CMS:`7554d70` FO:`40882c8` BO:`c96377a`
└─→ 8e: Per-package reports ✅ CMS:`aaaf7fc` FO:`a956cb9` BO:`8be98ae`
└─→ 8f: UI completion ✅ CMS:`dcd1135` FO:`3bffc13` BO:`e020354`
└─→ مرحله ۵: تست + استقرار (۳ روز) ⬜
مسیر بحرانی: ۰→۱→۱.۵→۲→۳→۴→UI→۵ = ~۱۷ روز | انجام‌شده: ۰→8f (~۱۷ روز)
```
---
## مرحله ۰ — فیکس باگ‌های فوری ✅
> ✅ تکمیل‌شده | کامیت: `8b9c317` + `fe3edd1`
### ✅ وضعیت باگ‌ها (بررسی اولیه لازم)
| # | باگ | Handler | شرح فیکس |
|---|------|---------|----------|
| B1 | DiscountBalance شارژ نمی‌شود | `VerifyGoldenPackagePurchaseCommandHandler` | اضافه `DiscountBalance += Amount × 2` + WalletChangeLog |
| B2 | UserPackagePurchase ساخته نمی‌شود | `VerifyGoldenPackagePurchaseCommandHandler` | ساخت record بعد verify موفق |
| B3 | UserPackagePurchase ساخته نمی‌شود | `VerifyPackagePurchaseCommandHandler` | ساخت record بعد verify موفق |
| B4 | UserPackagePurchase ساخته نمی‌شود | `VerifyBasePackagePaymentCommandHandler` | ساخت record بعد verify موفق |
#### دستور کار B1:
```
1. باز کردن VerifyGoldenPackagePurchaseCommandHandler.cs
2. پیدا کردن جایی که Balance شارژ می‌شود
3. اضافه کردن:
wallet.DiscountBalance += command.Amount * 2;
// + ساخت WalletChangeLog برای DiscountBalance
4. تست: verify → چک DiscountBalance در DB
```
#### دستور کار B2-B4 (الگوی مشترک):
```
1. بعد از verify موفق و شارژ wallet:
var purchase = new UserPackagePurchase
{
UserId = userId,
PackageId = packageId, // فعلاً BasePackageId = 4
PurchaseDate = DateTime.UtcNow,
Amount = amount,
PurchaseMethod = purchaseMethod, // ZarinPal, BFF, etc.
TransactionId = transactionId,
IsVerified = true
};
_context.UserPackagePurchases.Add(purchase);
2. تست: verify → چک UserPackagePurchases table
```
---
## مرحله ۱ — زیرساخت (Domain + DB) ✅
> ✅ تکمیل‌شده | کامیت: `ae92ab8` (Phase 1) + `a9cd2fd` (Phase 1.5 Migration)
### T1.1 — بروزرسانی Package Entity (۱۱ فیلد جدید — v3)
**فایل:** `CMS/src/CMSMicroservice.Domain/Entities/Package.cs`
```diff
+ public int SortOrder { get; set; }
+ public bool IsActive { get; set; } = true;
+ public bool IsBasePackage { get; set; }
+ public bool SupportsDayaPurchase { get; set; }
+ public bool SupportsDirectPurchase { get; set; } = true;
+ public long ActivationFee { get; set; }
+ public decimal DiscountMultiplier { get; set; } = 2.0m;
+ public decimal MagicWalletMultiplier { get; set; } = 2.5m;
+ // === v3: تنظیمات پورسانت per-package ===
+ public int MaxBalancesPerLeg { get; set; } = 300; // نقره‌ای=۳۰
+ public int MaxNetworkLevel { get; set; } = 15;
+ // === v3: سقف کیف‌پول جادویی per-package ===
+ public long MagicWalletMaxDeposit { get; set; } = 1_000_000_000;
+ public long MagicWalletMaxCredit { get; set; } = 2_500_000_000;
+
+ public virtual ICollection<PackageFeature> PackageFeatures { get; set; }
```
**EF Config:** `PackageConfiguration.cs`
- حداکثر یک `IsBasePackage = true` (Index filter)
- Precision for decimal fields
### T1.2 — ایجاد PackageFeature Entity
**فایل جدید:** `CMS/src/CMSMicroservice.Domain/Entities/PackageFeature.cs`
```csharp
public class PackageFeature : BaseAuditableEntity
{
public long PackageId { get; set; }
public virtual Package Package { get; set; }
public long ClubFeatureId { get; set; }
public virtual ClubFeature ClubFeature { get; set; }
public bool IsIncluded { get; set; } = true;
}
```
### T1.3-T1.6 — اضافه PackageId به entityها
| Entity | فیلد | Required? | توضیح | v3? |
|--------|------|-----------|-------|-----|
| ClubMembership | `long? PackageId` | nullable (بعد migration → required) | آخرین پکیج | |
| ClubMembershipCycle | `long PackageId` | required | پکیج این چرخه | |
| WeeklyCommissionPool | `long PackageId` | required + Unique(WeekDefId, PkgId) | Pool هر پکیج | |
| UserCommissionPayout | `long? PackageId` | nullable + **Unique(UserId, WeekId, PkgId)** | ردیابی | 🔄 |
| **NetworkWeeklyBalance** | **`long PackageId`** | **required + Unique(UserId, WeekId, PkgId)** | **تعادل per-package** | **🆕** |
### T1.7 — حذف SystemConstants (v3: ۷ ثابت)
**فایل:** `CMS/src/CMSMicroservice.Domain/Common/SystemConstants.cs`
```diff
- public const long BasePackageAmount = 56_000_000;
- public const long DayaLoanAmount = 56_000_000;
- public const long ClubActivationFee = 25_200_000;
- public const long ClubMembershipGiftValue = 25_200_000;
- public const decimal MagicWalletMultiplier = 2.5m;
- // === v3: انتقال به Package entity ===
- public const int CommissionMaxWeeklyBalancesPerLeg = 300;
- public const int CommissionMaxNetworkLevel = 15;
```
> ⚠️ **قبل از حذف:** grep تمام مصرف‌کننده‌ها → جایگزین با `Package.Property`
> ⚠️ **v3:** `CommissionMaxWeeklyBalancesPerLeg` و `CommissionMaxNetworkLevel` هم باید per-package شوند
### T1.8 — Database Migration
```bash
dotnet ef migrations add AddPackageBasedSystem
```
**شامل:**
- ستون‌های جدید Package
- جدول PackageFeatures
- FKها در 4 entity
- Unique constraint
### T1.9 — Data Migration Script
```sql
-- 1. بروزرسانی پکیج فعلی (ID=4 → اضافه فیلدهای جدید)
UPDATE "CMS"."Packages" SET
"SortOrder" = 2,
"IsActive" = true,
"IsBasePackage" = true,
"SupportsDayaPurchase" = true,
"SupportsDirectPurchase" = true,
"ActivationFee" = 25200000,
"DiscountMultiplier" = 2.0,
"MagicWalletMultiplier" = 2.5,
-- v3: تنظیمات پورسانت
"MaxBalancesPerLeg" = 300,
"MaxNetworkLevel" = 15,
"MagicWalletMaxDeposit" = 1000000000,
"MagicWalletMaxCredit" = 2500000000
WHERE "Id" = 4;
-- 2. Link existing data to base package
UPDATE "CMS"."ClubMemberships" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
UPDATE "CMS"."ClubMembershipCycles" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
UPDATE "CMS"."WeeklyCommissionPools" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
UPDATE "CMS"."UserCommissionPayouts" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
-- v3: NetworkWeeklyBalance هم PackageId می‌گیره
UPDATE "CMS"."NetworkWeeklyBalances" SET "PackageId" = 4 WHERE "PackageId" IS NULL;
-- 3. Seed Silver package (شامل فیلدهای v3)
INSERT INTO "CMS"."Packages" (..., "MaxBalancesPerLeg", "MaxNetworkLevel",
"MagicWalletMaxDeposit", "MagicWalletMaxCredit", ...)
VALUES ('پکیج نقره‌ای', 5600000, ..., 30, 15, 100000000, 250000000, ...);
```
### T1.10 — بروزرسانی Protoها
| Proto File | تغیر | v3? |
|-----------|-------|-----|
| package.proto | فیلدهای جدید Package message (۱۱ فیلد) | 🔄 |
| clubmembership.proto | package_id در request/response | |
| commission.proto | **`package_id` + `package_title`** در ۴ message | **🆕** |
| commission.proto | **Message جدید: `CustomerCommissionPackageSummary`** | **🆕** |
| commission.proto | **فیلتر `package_id` در Requestها** | **🆕** |
### T1.11 — اضافه PackageId به NetworkWeeklyBalance (🆕 v3)
**فایل:** `CMS/src/CMSMicroservice.Domain/Entities/NetworkWeeklyBalance.cs`
```diff
+ public long PackageId { get; set; }
+ public virtual Package Package { get; set; }
```
**EF Config:** اضافه Unique Index:
```csharp
builder.HasIndex(e => new { e.UserId, e.WeekDefinitionId, e.PackageId }).IsUnique();
builder.HasOne(e => e.Package).WithMany().HasForeignKey(e => e.PackageId);
```
> ⚠️ **تاثیر حجم:** رکوردهای تعادل ×N (تعداد پکیج). مثلاً ۱۰۰۰ کاربر × ۲ پکیج = ۲۰۰۰ رکورد هفتگی
### T1.12 — Data Migration: NetworkWeeklyBalance (🆕 v3)
```sql
-- رکوردهای موجود → پکیج پایه
UPDATE "CMS"."NetworkWeeklyBalances"
SET "PackageId" = (SELECT "Id" FROM "CMS"."Packages" WHERE "IsBasePackage" = true LIMIT 1)
WHERE "PackageId" IS NULL;
```
---
## مرحله ۲ — منطق کسب‌وکار ✅
> ✅ تکمیل‌شده | کامیت: `8e5c7c5` (Phase 2) + `ccb938e` (Phase 3) + `0002a5a` (Phase 4)
### T2.1 — Generic Verify Handler
**هدف:** ادغام VerifyGolden + VerifyBase + VerifyGeneric → یک handler
**الگوریتم:**
```
1. دریافت TransactionId از request
2. خواندن Transaction → PackageId → Package entity
3. verify با درگاه (ZarinPal/BFF/...)
4. اگر موفق:
a. wallet.Balance += Package.Price
b. wallet.DiscountBalance += Package.Price × Package.DiscountMultiplier
c. ساخت WalletChangeLog (Balance)
d. ساخت WalletChangeLog (DiscountBalance)
e. ساخت UserPackagePurchase record
f. اگر اولین خرید: JoinNetwork
g. بروزرسانی ClubMembershipCycle.PackageId
5. return success + receipt
```
### T2.2 — Generic Purchase Handler
**هدف:** ادغام PurchaseGolden + PurchasePackage + InitiateBase → یک handler
**تغییرات:**
- حذف فیلتر `Title.Contains("طلایی")`
- حذف `BasePackageId = 4`
- خواندن Package entity از DB بر اساس `request.PackageId`
- Gateway URL + Amount از Package.Price
### T2.3-T2.4 — ActivateClubMembership بهبود
**تغییرات:**
```diff
- var features = await GetAllFeatureIds(); // همه فیچرها
+ var features = await GetPackageFeatures(packageId); // فیچرهای پکیج
- membership.PackageAmount = SystemConstants.BasePackageAmount;
+ membership.PackageAmount = package.Price;
- var activationFee = SystemConstants.ClubActivationFee;
+ var activationFee = package.ActivationFee;
```
### T2.5-T2.6 — Re-Purchase Logic
**EXIT Magic Mode — تغییرات:**
```diff
wallet.WalletMode = WalletMode.Normal;
wallet.MagicCompletedAt = DateTime.UtcNow;
cycle.MagicCompletedAt = DateTime.UtcNow;
+ user.PackagePurchaseMethod = PackagePurchaseMethod.None;
+ membership.IsActive = false;
+ cycle.IsCurrentCycle = false;
```
**Guard تغییرات:**
```diff
- if (user.PackagePurchaseMethod != PackagePurchaseMethod.None)
- throw new RpcException("قبلاً پکیج خریداری شده");
+ if (user.PackagePurchaseMethod != PackagePurchaseMethod.None
+ && !HasCompletedMagicCycle(membership))
+ throw new RpcException("چرخه جاری هنوز تکمیل نشده");
```
### T2.7 — JWT Claims جدید
```diff
claims.Add("HasPurchasedPackage", "true");
+ claims.Add("CanRepurchase", HasCompletedMagicCycle(membership).ToString());
+ claims.Add("PackageId", membership.PackageId?.ToString() ?? "");
+ claims.Add("PackageTitle", package?.Title ?? "");
```
---
## مرحله ۳ — محاسبه پورسانت (موازی با مرحله ۲) ✅
> ✅ تکمیل‌شده | کامیت: `607f791` + `7176fe4` | ⏱️ **۴ روز** | ریسک: بحرانی (مالی)
### T3.1-T3.2 — SPs + PackageId + پارامترهای داینامیک (🔄 v3)
```sql
-- sp_CalculateWeeklyBalances — v3: حذف hardcode
ALTER PROCEDURE sp_CalculateWeeklyBalances
@WeekDefinitionId BIGINT,
@PackageId BIGINT,
@MaxBalancesPerLeg INT, -- v3: از Package entity (نه ۳۰۰ hardcode!)
@MaxNetworkLevel INT -- v3: از Package entity (نه ۱۵ hardcode!)
AS
BEGIN
-- فیلتر: فقط کاربرانی که این پکیج را دارند
-- carryover: فقط رکوردهای PackageId = @PackageId
-- cap: از @MaxBalancesPerLeg (نه ۳۰۰)
-- depth: CTE تا @MaxNetworkLevel (نه ۱۵)
INSERT INTO "CMS"."NetworkWeeklyBalances" ("PackageId", ...)
SELECT @PackageId, ...
FROM "CMS"."UserWallets" w
INNER JOIN "CMS"."ClubMemberships" m ON m."UserId" = w."UserId"
WHERE m."PackageId" = @PackageId
AND m."IsActive" = true;
END;
```
### T3.3 — Loop Service (🔄 v3: ارسال تنظیمات پکیج)
```csharp
// WeeklyCommissionCalculationService.cs
var activePackages = await _context.Packages
.Where(p => p.IsActive && !p.IsDeleted)
.ToListAsync();
foreach (var package in activePackages)
{
_logger.LogInformation(
"Calculating commission for package {Id}: {Title} " +
"(MaxBalances={Max}, MaxLevel={Level})",
package.Id, package.Title,
package.MaxBalancesPerLeg, package.MaxNetworkLevel);
// v3: پاس دادن تنظیمات پکیج
await strategy.CalculateWeeklyBalancesAsync(
weekId, package.Id,
package.MaxBalancesPerLeg, package.MaxNetworkLevel);
await strategy.CalculateWeeklyPoolAsync(weekId, package.Id);
}
```
### T3.4 — OrmCommissionCalculationStrategy (🔄 v3)
**تغییرات:**
```diff
- var maxBalances = SystemConstants.CommissionMaxWeeklyBalancesPerLeg; // 300
- var maxLevel = SystemConstants.CommissionMaxNetworkLevel; // 15
+ // پارامتر از بیرون — per-package
+ int maxBalances = maxBalancesPerLeg; // e.g., نقره‌ای=30, پایه=300
+ int maxLevel = maxNetworkLevel;
- // فیلتر کاربران
+ // فیلتر کاربران بر اساس پکیج
+ .Where(m => m.PackageId == packageId && m.IsActive)
- // carryover
+ // carryover: فقط رکوردهای همان PackageId
+ .Where(b => b.PackageId == packageId && b.WeekDefinitionId == prevWeekId)
```
### T3.5 — SpCommissionCalculationStrategy (🆕 v3)
```csharp
// قبل: فقط WeekDefinitionId
await connection.ExecuteAsync("CMS.sp_CalculateWeeklyBalances",
new { WeekDefinitionId = weekId, ForceRecalculate = true });
// بعد (v3): پکیج + تنظیمات داینامیک
await connection.ExecuteAsync("CMS.sp_CalculateWeeklyBalances",
new {
WeekDefinitionId = weekId,
PackageId = package.Id,
MaxBalancesPerLeg = package.MaxBalancesPerLeg,
MaxNetworkLevel = package.MaxNetworkLevel,
ForceRecalculate = true
});
```
### T3.6 — Carryover per-package (🆕 v3)
> ⚠️ **بحرانی:** week-shifting باید فقط رکوردهای همان PackageId را shift کند
```
هفته ۱۰ → هفته ۱۱:
علی: carryover_پایه = {Left: surplus, Right: surplus} ← جداگانه
علی: carryover_نقره‌ای = {Left: 0, Right: 0} ← جداگانه
✖ اشتباه: قاطی کردن carryover پایه و نقره‌ای!
✔ صحیح: هر PackageId فقط carryover خودش را می‌بینه
```
### ⚠️ نکته بحرانی
> پورسانت = پول واقعی. **هر تغییر در SPs باید:**
> 1. ابتدا در staging با داده واقعی تست شود
> 2. نتایج قبل و بعد مقایسه شوند
> 3. Rollback plan آماده باشد
> 4. در production ابتدا read-only اجرا شود (بدون commit)
---
## مرحله ۷ — Migration + Cleanup (سه‌گانه) ✅
> ✅ تکمیل‌شده | ⏱️ **۱ روز** | ریسک: پایین
### فاز 7a — Cosmetic Cleanup ✅
> کامیت: CMS `469d97b` | FO `b82cac4` | BO `f1b0085`
**CMS:**
- حذف orphaned `PurchasePackage` handler (۳ فایل، بدون caller)
- فیکس doc-comments: `طلایی``پکیج` در ۶ فایل (enums, entities, handlers)
**FrontOffice:**
- حذف hardcoded `پکیج طلایی` از `MyPackages.razor` و `Packages.razor`
- اضافه `PackageTitle` property به `UserPackageStatusDto` record
**BackOffice:**
- تغییر label `پکیج طلایی``خرید پکیج` در `UserNetworkInfo.razor`
### فاز 7b — FrontOffice RPC Migration ✅
> کامیت: CMS `161f796` | FO `71f391a`
**CMS:**
- `CustomerPurchasePackage`: embed `orderId` در callback URL قبل از ارسال به درگاه
- `$"{request.CallbackUrl}{separator}orderId={purchase.Id}"`
**FrontOffice:**
- `Profile/Index.razor.cs`: مهاجرت `InitiateBasePackagePaymentAsync``CustomerPurchasePackageAsync`
- `Profile/PaymentCallback.razor`: مهاجرت `VerifyBasePackagePaymentAsync``CustomerVerifyPackagePurchaseAsync`
- پارامترهای جدید: `PackageId`, `CallbackUrl`, `PurchaseMethod`, `OrderId`, `Authority`, `Status`
### فاز 7c — Delete Deprecated Handlers ✅
> کامیت: CMS `8446e0e` (14 فایل، 1125 حذف)
**حذف ۴ handler CQRS (۱۲ فایل):**
- `PurchaseGoldenPackage/` (Command, Handler, Validator)
- `VerifyGoldenPackagePurchase/` (Command, Handler, Validator)
- `InitiateBasePackagePayment/` (Command, Handler, Validator)
- `VerifyBasePackagePayment/` (Command, Handler, Validator)
**Cleanup:**
- `PackageService.cs`: حذف ۴ gRPC override method (proto RPCs حالا auto-throw `Unimplemented`)
- `PackageProfile.cs`: حذف ۶ Mapster mapping block + ۴ using directive
- Build: 0 Error ✅
---
## مرحله ۸ — FrontOffice Checkout + NuGet
> 🔄 در حال اجرا | فاز 8a تکمیل ✅
### فاز 8a — Checkout Wire-up ✅
> کامیت: FO `0bbc11e`
**Checkout.razor.cs:**
- حذف dead code: `ProcessPayment()` از flow قدیمی `TransactionsContract + UserOrderContract` استفاده می‌کرد
- Rewrite با `CustomerPurchasePackageAsync` (مثل Profile/Index.razor.cs)
- Callback URL → `/profile/payment-callback` (از صفحه verify موجود استفاده مجدد)
- حذف DI بلااستفاده: `UserOrderContract`, `TransactionContract`
- حذف usings: `Transactions`, `UserOrder`, `WellKnownTypes`
**Profile/Index.razor.cs (cosmetic):**
- Rename `basePackage``selectedPackage`, `tempCallbackUrl``callbackUrl`
### فاز 8b — BackOffice Package CRUD Expansion ✅
> کامیت: CMS `ce8e248` | BO `89f5241` (7 فایل، +138/-23)
**NuGet Rebuild:**
- Proto version bump: `0.0.184``0.0.185`
- Pack و deploy به local feed (`/nupkg`)
- BackOffice NuGet.config: اضافه local feed source
**CreateDialog.razor (۱۲ فیلد جدید):**
- `SortOrder` — MudNumericField<int> ترتیب نمایش
- `ActivationFee` — MudNumericField<long> هزینه فعال‌سازی
- `DiscountMultiplier` — MudNumericField<double> ضریب تخفیف
- `MagicWalletMultiplier` — MudNumericField<double> ضریب کیف پول جادویی
- `MagicWalletMaxDeposit` — MudNumericField<long> سقف واریز جادویی
- `MagicWalletMaxCredit` — MudNumericField<long> سقف اعتبار جادویی
- `MaxBalancesPerLeg` — MudNumericField<int> حداکثر تعادل هر پا
- `MaxNetworkLevel` — MudNumericField<int> حداکثر سطح شبکه
- `IsActive` — MudCheckBox فعال/غیرفعال
- `IsBasePackage` — MudCheckBox پکیج پایه
- `SupportsDirectPurchase` — MudCheckBox پرداخت مستقیم
- `SupportsDayaPurchase` — MudCheckBox اعتبار دایا
**UpdateDialog.razor:** همان ۱۲ فیلد
**PackageMainPage Grid (۴ ستون جدید):**
- `Price` — فرمت‌شده با N0
- `SortOrder` — ترتیب
- `IsActive` — MudChip فعال/غیرفعال
- `IsBasePackage` — MudChip پایه/عادی
**سایر:**
- Dialog size: `MaxWidth.Small``MaxWidth.Medium`
- CreateNew defaults: `IsActive=true, DiscountMultiplier=2.0, MagicWalletMultiplier=2.5, ...`
- فیکس `HasPurchasedGoldenPackage``HasPurchasedPackage` در `UserNetworkInfo.razor`
### فاز 8c — FrontOffice Package Pages ✅
> کامیت: FO `d71d463` (5 فایل، +109/-56)
**NuGet:** `0.0.182``0.0.185` + local feed source
**PackageDetail.razor.cs:**
- مهاجرت `GetPackageAsync` (admin RPC) → `GetCustomerPackageDetailsAsync` (customer RPC)
- Features: از hardcoded ثابت → از `PackageFeature` API داینامیک
- Specifications: از hardcoded → از `PackageFeature.IsHighlighted` API
- حذف ۵ hardcoded feature string + ۴ hardcoded specification
**PackageService.cs:**
- `PackageDto`: اضافه ۸ فیلد جدید (ActivationFee, DiscountMultiplier, MagicWalletMultiplier, etc.)
- `GetAllPackagesAsync`: مپ فیلدهای جدید از `CustomerPackageModel`
- `GetUserPackageStatusAsync`: از stub → اتصال واقعی به `GetUserPackageStatusAsync` RPC
**Packages.razor:**
- Un-exclude از build (حذف `<Content Remove>` + `<Compile Remove>`)
- جایگزینی ۳ feature bullet hardcoded → dynamic features:
- `SupportsDirectPurchase` → پرداخت مستقیم
- `SupportsDayaPurchase` → پرداخت با اعتبار دایا
- `DiscountMultiplier` → ضریب تخفیف: X.Xx
- `MagicWalletMultiplier` → کیف پول جادویی: X.Xx
- `IsBasePackage` → پکیج پایه ⭐
### فاز 8d — Proto Cleanup ✅
> کامیت: CMS `7554d70` (2 فایل، -103) | FO `40882c8` | BO `c96377a`
**حذف ۴ deprecated RPC:**
- `PurchaseGoldenPackage` — جایگزین: `CustomerPurchasePackage`
- `VerifyGoldenPackagePurchase` — جایگزین: `CustomerVerifyPackagePurchase`
- `InitiateBasePackagePayment` — جایگزین: `CustomerPurchasePackage`
- `VerifyBasePackagePayment` — جایگزین: `CustomerVerifyPackagePurchase`
**حذف ۸ deprecated message type:**
- `PurchaseGoldenPackageRequest` / `PurchaseGoldenPackageResponse`
- `VerifyGoldenPackagePurchaseRequest` / `VerifyGoldenPackagePurchaseResponse`
- `InitiateBasePackagePaymentRequest` / `InitiateBasePackagePaymentResponse`
- `VerifyBasePackagePaymentRequest` / `VerifyBasePackagePaymentResponse`
**حفظ شده:** `GetUserPackageStatus` RPC + messages (هنوز در استفاده)
**NuGet:** `0.0.185``0.0.186` (همه ریپوها)
### فاز 8e — Per-Package Commission Reports ✅
> کامیت: CMS `aaaf7fc` | FO `a956cb9` | BO `8be98ae`
**Proto (commission.proto):**
- اضافه `package_id` فیلتر به ۴ request message: `GetUserCommissionPayoutsRequest`, `GetUserWeeklyBalancesRequest`, `GetMyCommissionPayoutsRequest`, `GetMyWeeklyBalancesRequest`
- اضافه `package_id` + `package_title` به ۴ response model: `UserCommissionPayoutModel`, `UserWeeklyBalanceModel`, `CustomerCommissionPayoutModel`, `CustomerWeeklyBalanceModel`
**CMS (12 فایل):**
- ۴ Query record: اضافه `public long? PackageId { get; init; }`
- ۴ Handler: اضافه `.Include(x => x.Package)` + فیلتر `Where(x => x.PackageId == request.PackageId.Value)` + map `PackageId`/`PackageTitle`
- ۳ Response DTO: اضافه `PackageId` + `PackageTitle`
- `CommissionProfile.cs`: تنظیم mapping‌های Mapster برای admin + customer
**BackOffice (6 فایل):**
- کامپوننت جدید `PackageSelect.razor/.cs`: dropdown قابل استفاده مجدد با بارگذاری پکیج‌ها از `PackageContract`
- `UserPayouts.razor/.cs`: فیلتر PackageSelect + ستون پکیج با MudChip
- `BalancesReport.razor`: فیلتر PackageSelect + ستون پکیج با MudChip + mapping PackageTitle
**FrontOffice (7 فایل):**
- `CommissionDtos.cs`: اضافه `PackageId` + `PackageTitle` به `CommissionPayoutDto` و `WeeklyBalanceDto`
- `CommissionService.cs`: اضافه پارامتر `packageId` به `GetMyCommissionPayoutsAsync` و `GetMyWeeklyBalanceAsync`
- `CommissionDashboardPage.razor/.cs`: فیلتر dropdown پکیج + ستون «پکیج» با MudChip (دسکتاپ + موبایل)
- `WeeklyBalancePage.razor/.cs`: فیلتر MudSelect پکیج + نمایش MudChip پکیج در بخش اطلاعات هفته
**NuGet:** `0.0.186``0.0.187` (همه ریپوها)
### فاز 8f — UI Completion (T4.2 + T4.3 + T4.13 + F2 + F3) ✅
> کامیت: CMS `dcd1135` | FO `3bffc13` | BO `e020354`
**CMS (T4.13 — PackageFeature CRUD):**
- Proto: اضافه `repeated int64 feature_ids` به ۴ message (Create/Update Request, Get/GetAll Response)
- `CreateNewPackageCommand/Handler`: sync FeatureIds → ساخت `PackageFeature` records
- `UpdatePackageCommand/Handler`: sync FeatureIds → حذف قبلی‌ها + ساخت جدید
- `GetPackage/GetAllPackageByFilter`: اضافه `.Include(x => x.PackageFeatures)` + map FeatureIds
**BackOffice (F2 + T4.13):**
- **F2:** کامپوننت جدید `ChangeParentDialog.razor/.cs` — مودال جابجایی در شبکه با NewParentId, NewLeg, Reason
- **F2:** دکمه «تغییر والد» در `UserNetworkInfo.razor`
- **T4.13:** checkbox matrix فیچرها در `CreateDialog` و `UpdateDialog` — بارگذاری از `ConfigurationContractClient`
**FrontOffice (T4.2 + T4.3 + F3):**
- **T4.2:** پرداخت شرطی در `Checkout.razor` بر اساس `SupportsDirectPurchase`/`SupportsDayaPurchase`
- **T4.3:** منطق خرید مجدد در `MyPackages.razor` — بارگذاری `MagicWalletStatus` + CTA شرطی + progress bar
- **F3:** نمایش PV سفارش در `Store/OrderDetail.razor``CalculateOrderPVAsync` + جدول PV هر محصول
**NuGet:** `0.0.187``0.0.188` (همه ریپوها)
---
## مرحله ۴ — UI (FrontOffice + BackOffice)
> ⏱️ **۵ روز** (v3: +۲) | وابستگی: مرحله ۲ + ۳ | ریسک: متوسط
### T4.1 — کاشی‌های پکیج داینامیک
**فایل:** `FrontOffice/src/.../Pages/Package/Packages.razor`
```razor
@* قبل: hardcoded *@
@* بعد: *@
@foreach (var package in _packages.OrderBy(p => p.SortOrder))
{
<PackageCard Package="@package"
OnPurchase="StartPurchase"
ShowFeatures="true"
ShowPV="true" />
}
```
### T4.2 — مودال پرداخت شرطی ✅ FO:`3bffc13`
**پیاده‌سازی:**
- `Checkout.razor.cs`: اضافه `PackageService` injection، بارگذاری پکیج‌ها با `GetAllPackagesAsync()`
- `Checkout.razor`: دکمه‌های پرداخت شرطی بر اساس `SupportsDirectPurchase` و `SupportsDayaPurchase`
- اضافه `DayaLoanPayment()` method + alert برای عدم وجود روش پرداخت
- `Pack` record: اضافه `SupportsDirectPurchase` و `SupportsDayaPurchase`
### T4.3 — MyPackages + Re-Purchase ✅ FO:`3bffc13`
**پیاده‌سازی:**
- `MyPackages.razor.cs`: بارگذاری `MagicWalletStatus` از `WalletService.GetMagicWalletStatusAsync()`
- فرمول خرید مجدد: `WalletMode == 0 && PurchaseCycleCount >= 1 && MagicRemainingDeposit == 0`
- `MyPackages.razor`: CTA شرطی «🎉 چرخه جادویی تکمیل شد!» + دکمه «خرید پکیج جدید»
- بخش پیشرفت کیف پول جادویی: مبلغ واریزی، باقی‌مانده، اعتبار دریافتی + progress bar
### T4.8 — FrontOffice: CommissionDashboard per-package (🆕 v3) ✅ FO:`a956cb9`
**پیاده‌سازی:**
- `CommissionDtos.cs`: اضافه `PackageId` + `PackageTitle` به `CommissionPayoutDto` و `WeeklyBalanceDto`
- `CommissionService.cs`: اضافه پارامتر `packageId` به `GetMyCommissionPayoutsAsync` و `GetMyWeeklyBalanceAsync`
- `CommissionDashboardPage.razor`: اضافه dropdown فیلتر پکیج + ستون «پکیج» با MudChip + نمایش پکیج در card موبایل
- `CommissionDashboardPage.razor.cs`: inject `PackageService`، فیلد `_filterPackageId`، بارگذاری لیست پکیج‌ها
### T4.9 — FrontOffice: WeeklyBalance per-package (🆕 v3) ✅ FO:`a956cb9`
**پیاده‌سازی:**
- `WeeklyBalancePage.razor`: اضافه MudSelect فیلتر پکیج کنار WeekSelector + نمایش MudChip پکیج در بخش اطلاعات هفته
- `WeeklyBalancePage.razor.cs`: inject `PackageService`، فیلد `_filterPackageId`، ارسال به `CommissionService.GetMyWeeklyBalanceAsync`
### T4.10-T4.12 — BackOffice: گزارش‌های پورسانت per-package (🆕 v3) ✅ BO:`8be98ae`
**پیاده‌سازی:**
- کامپوننت جدید `PackageSelect.razor/.cs`: dropdown قابل استفاده مجدد با بارگذاری پکیج‌ها از `PackageContract`
- `UserPayouts.razor/.cs`: فیلتر PackageSelect + ستون پکیج با MudChip
- `BalancesReport.razor`: فیلتر PackageSelect + ستون پکیج با MudChip + mapping `PackageTitle`
### T4.13 — BackOffice: Package CRUD + Quick Access فیچرها (🆕 v3) ✅ CMS:`dcd1135` BO:`e020354`
**CMS پیاده‌سازی:**
- Proto: اضافه `repeated int64 feature_ids` به ۴ message (Create/Update Request, Get/GetAll Response)
- `CreateNewPackageCommand/Handler`: اضافه `FeatureIds` + ساخت `PackageFeature` records
- `UpdatePackageCommand/Handler`: اضافه `FeatureIds` + sync (حذف قبلی‌ها + ساخت جدید)
- `GetPackageQueryHandler`: اضافه `.Include(x => x.PackageFeatures)` + map `FeatureIds`
- `GetAllPackageByFilterQueryHandler`: اضافه `.Include(x => x.PackageFeatures)` قبل از `PaginatedListAsync`
- NuGet: `0.0.187``0.0.188`
**BO پیاده‌سازی:**
- `CreateDialog.razor/.cs`: بارگذاری `ClubFeatures` از `ConfigurationContractClient` + checkbox matrix
- `UpdateDialog.razor/.cs`: همان pattern + pre-populate از `Model.FeatureIds`
- Mapster: `Adapt<UpdatePackageRequest>()` خودکار `FeatureIds` را map می‌کند
---
## مرحله ۵ — تست و استقرار
> ⏱️ **۳ روز** (v3: +۱) | وابستگی: مرحله ۴
### Checklist تست
**خرید + فعال‌سازی:**
- [ ] خرید پکیج نقره‌ای (ZarinPal)
- [ ] خرید پکیج پایه (ZarinPal)
- [ ] خرید پکیج پایه (Daya Loan)
- [ ] خرید پکیج پایه (Manual Payment)
- [ ] فعالسازی باشگاه با پکیج نقره‌ای → فیچرهای محدود
- [ ] فعالسازی باشگاه با پکیج پایه → همه فیچرها
**چرخه Magic + خرید مجدد:**
- [ ] تکمیل چرخه Magic → ریست وضعیت
- [ ] خرید مجدد بعد تکمیل چرخه (همان پکیج)
- [ ] خرید مجدد با پکیج متفاوت (پایه → نقره‌ای)
**پورسانت per-package (v3):**
- [ ] Commission Pool جداگانه هر پکیج
- [ ] تعادل per-package: MaxBalancesPerLeg متفاوت (پایه=۳۰۰, نقره‌ای=۳۰)
- [ ] Carryover مجزا: shift فقط رکوردهای همان PackageId
- [ ] SP پارامترها صحیح: @MaxBalancesPerLeg و @MaxNetworkLevel از Package
- [ ] NetworkWeeklyBalance رکوردها: ۲ پکیج = ۲× رکورد
**گزارش per-package (v3):**
- [ ] FO: مشتری کارت‌های خلاصه per-package را می‌بیند
- [ ] FO: مجموع پاداش = جمع همه پکیج‌ها
- [ ] BO: فیلتر dropdown پکیج کار می‌کند
- [ ] BO: CSV export شامل ستون پکیج
**Migration + سایر:**
- [ ] Data Migration — PackageId در رکوردهای قبلی (شامل NetworkWeeklyBalance)
- [ ] JWT claims جدید (CanRepurchase, PackageId)
- [x] UI: کاشی‌های داینامیک FrontOffice
- [x] UI: ماتریس فیچر + Quick Access BackOffice
- [ ] Rollback: بدون data loss
---
## 📅 تقویم پیشنهادی (v3)
| هفته | روز | تسک |
|------|-----|------|
| هفته ۱ | روز ۱ | مرحله ۰: فیکس ۴ باگ |
| | روز ۲-۳ | مرحله ۱: Package entity (۱۱ فیلد) + PackageFeature |
| | روز ۴-۵ | مرحله ۱: FKها + NetworkWeeklyBalance + Migration |
| هفته ۲ | روز ۶-۷ | مرحله ۲: Generic handlers + re-purchase |
| | روز ۶-۸ | مرحله ۳: SP params + carryover per-package (موازی) |
| | روز ۸-۱۰ | مرحله ۲: Guards + JWT + Manual |
| هفته ۳ | روز ۱۱-۱۲ | مرحله ۴: FrontOffice UI + گزارش per-package |
| | روز ۱۳-۱۴ | مرحله ۴: BackOffice UI + گزارش per-package |
| | روز ۱۵-۱۷ | مرحله ۵: تست + deploy |
---
## 🔗 ارجاعات
| مستند | محتوا |
|-------|-------|
| [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) | طراحی فنی — **۴۸+ تغییر** (v3) + باگ‌ها |
| [PACKAGE-TRANSFORMATION-UX.md](PACKAGE-TRANSFORMATION-UX.md) | تاثیر UX بر فرانت‌ها |
| [FEATURE-BACKLOG.md](FEATURE-BACKLOG.md) | بکلاگ ۱۲ RPC آماده |
| [GRPC-SERVICES-AUDIT.md](../cms/GRPC-SERVICES-AUDIT.md) | آدیت ۳۴۲ RPC |
---
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۱۰ — فاز ۰-۸f تکمیل (۲۷ کامیت: ۱۷ CMS + ۷ FO + ۵ BO) | NuGet v0.0.188 | T4.2+T4.3+T4.13+F2+F3 کامل | باقی‌مانده: تست + deploy*
+494
View File
@@ -0,0 +1,494 @@
# 🏗️ تحلیل تحول پکیج‌بیس — تاثیر بر تجربه کاربر (UX)
> **وضعیت:** در حال تحلیل
> **تاریخ:** ۱۴۰۴/۱۲/۰۶
> **پیش‌نیاز:** [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) v2
> **هدف:** مستندسازی تاثیر تغییر رویکرد پکیج‌بیس بر تجربه مشتری و ادمین در فرانت‌ها
---
## فهرست
1. [چشم‌انداز کلی](#۱-چشمانداز-کلی)
2. [تجربه مشتری (FrontOffice) — قبل و بعد](#۲-تجربه-مشتری-frontoffice--قبل-و-بعد)
3. [تجربه ادمین (BackOffice) — قبل و بعد](#۳-تجربه-ادمین-backoffice--قبل-و-بعد)
4. [تسک‌های تحول — مرحله‌به‌مرحله](#۴-تسکهای-تحول--مرحلهبهمرحله)
5. [پیش‌بینی نیازمندی‌های آینده](#۵-پیشبینی-نیازمندیهای-آینده)
6. [ماتریس تاثیرگذاری بر صفحات](#۶-ماتریس-تاثیرگذاری-بر-صفحات)
---
## ۱. چشم‌انداز کلی
### فلسفه تغییر
| بُعد | **فعلی (تک‌پکیج)** | **هدف (چند‌پکیج)** |
|------|-------------------|--------------------|
| **مدل قیمتی** | فقط ۵۶M تومان — "همه یا هیچ" | سطوح متنوع (نقره‌ای ۵.۶M, پایه ۵۶M, ...) — "ورود تدریجی" |
| **تجربه ورود** | سنگین — کاربر باید ۵۶M بپردازد | سبک — شروع از ۵.۶M و ارتقا بعدی |
| **چرخه عمر** | یک‌بار خرید → برای همیشه | چند‌بار خرید → هر چرخه Magic Wallet |
| **فیچرها** | ثابت — همه فیچرها برای همه | پویا — هر پکیج فیچرهای خودش |
| **کمیسیون** | یک Pool مشترک | Pool جداگانه هر پکیج |
| **مدیریت** | hardcoded — تغییر = deploy | داینامیک — ادمین از پنل تغییر می‌دهد |
### چه کسانی تاثیر می‌بینند؟
```
👤 مشتری (FrontOffice):
├── ثبت‌نام‌کننده جدید: گزینه‌های بیشتر → تصمیم‌گیری آسان‌تر
├── مشتری فعال: دکمه "ارتقا" + "خرید مجدد"
└── مشتری Magic: نمایش پیشرفت چرخه + آماده‌سازی خرید بعدی
👔 ادمین (BackOffice):
├── مدیر محصول: CRUD پکیج + ماتریس فیچر
├── مدیر مالی: Commission Pool جداگانه + گزارش‌ها
└── پشتیبان: فعالسازی دستی با انتخاب پکیج
```
---
## ۲. تجربه مشتری (FrontOffice) — قبل و بعد
### ۲.۱ صفحه لیست پکیج‌ها (`Packages.razor`)
#### قبل (فعلی):
```
┌─────────────────────────────────────────────┐
│ پکیج طلایی │
│ ──────────── │
│ ✅ دسترسی به باشگاه مشتریان │
│ ✅ کیف‌پول جادویی │
│ ✅ فروشگاه تخفیفی │
│ │
│ 💰 ۵۶,۰۰۰,۰۰۰ تومان │
│ │
│ [خرید پکیج] │
└─────────────────────────────────────────────┘
```
#### بعد (پکیج‌بیس):
```
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ 🥈 پکیج نقره‌ای │ │ 🏆 پکیج پایه │ │ 💎 پکیج ویژه │
│ ──────────── │ │ ──────────── │ │ ──────────── │
│ ✅ باشگاه مشتریان │ │ ✅ باشگاه مشتریان │ │ ✅ باشگاه مشتریان │
│ ✅ کیف‌پول جادویی │ │ ✅ کیف‌پول جادویی │ │ ✅ کیف‌پول جادویی │
│ ❌ فروشگاه تخفیفی │ │ ✅ فروشگاه تخفیفی │ │ ✅ فروشگاه تخفیفی │
│ ❌ پشتیبانی اختصاصی │ │ ❌ پشتیبانی اختصاصی │ │ ✅ پشتیبانی اختصاصی │
│ │ │ │ │ │
│ 💰 ۵,۶۰۰,۰۰۰ تومان │ │ 💰 ۵۶,۰۰۰,۰۰۰ تومان │ │ 💰 ??? تومان │
│ │ │ ⭐ محبوب‌ترین │ │ 🆕 بزودی │
│ [خرید] [جزئیات] │ │ [خرید] [جزئیات] │ │ [در انتظار] │
│ ────────────────── │ │ ────────────────── │ │ ────────────────── │
│ 📊 PV: 5,600,000 │ │ 📊 PV: 56,000,000 │ │ │
│ 🎁 هدیه: 11,200,000 │ │ 🎁 هدیه: 112,000,000 │ │ │
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘
```
**تغییرات کلیدی:**
- کاشی‌ها از API می‌آیند (نه hardcoded)
- فیچرهای هر پکیج از `PackageFeature` خوانده می‌شود
- نمایش PV (Point Value) برای هر پکیج
- نمایش Gift Value (= `Price × DiscountMultiplier`)
- دکمه‌های شرطی: دایا فقط برای پکیج‌های `SupportsDayaPurchase`
- Badge «محبوب‌ترین» / «ارزان‌ترین» بر اساس `SortOrder`
### ۲.۲ صفحه پکیج‌های من (`MyPackages.razor`)
#### قبل:
```
وضعیت عضویت: فعال ✅
پکیج: طلایی
تاریخ فعالسازی: ۱۴۰۳/۰۹/۱۵
```
#### بعد:
```
┌─────────────────────────────────────────────────────────────┐
│ 📦 پکیج فعال: پکیج پایه │
│ ──────────── │
│ وضعیت: فعال ✅ | چرخه: ۲ | مدت: ۱۸۰ روز │
│ │
│ ┌──── کیف‌پول جادویی ────┐ │
│ │ موجودی: ۱۲,۳۰۰,۰۰۰ │ │
│ │ شارژ: ۴۳۵,۰۰۰,۰۰۰ │ │
│ │ سقف: ۱,۰۰۰,۰۰۰,۰۰۰ │ │
│ │ ████████░░░░ ۴۳.۵% │ │
│ └─────────────────────────┘ │
│ │
│ ┌──── PV انباشته ────┐ │
│ │ PV کل: ۸۹,۶۰۰,۰۰۰ │ │
│ │ آخرین سفارش: ۴.۲M │ │
│ └─────────────────────┘ │
│ │
│ ❌ چرخه جادویی تکمیل نشده — هنوز امکان خرید مجدد نیست │
│ ───── یا ───── │
│ ✅ چرخه جادویی تکمیل شد! [خرید پکیج جدید] │
└─────────────────────────────────────────────────────────────┘
┌─── تاریخچه چرخه‌ها ───┐
│ چرخه ۱: پایه — ۱۴۰۳/۰۹ تا ۱۴۰۴/۰۳ — ✅ تکمیل │
│ چرخه ۲: پایه — ۱۴۰۴/۰۳ تا ادامه دارد — 🔄 فعال │
└────────────────────────┘
```
**تغییرات کلیدی:**
- نمایش شماره چرخه و نوع پکیج
- نوار پیشرفت Magic Wallet (چقدر تا تکمیل چرخه)
- PV انباشته (از `CalculateOrderPV`)
- دکمه شرطی «خرید مجدد» (فقط بعد تکمیل چرخه)
- تاریخچه چرخه‌ها (از `ClubMembershipCycle`)
### ۲.۳ صفحه چک‌اوت (`Checkout.razor`)
#### قبل:
```
سبد خرید:
محصول A × 2 = ۲,۰۰۰,۰۰۰ تومان
مالیات (۹%): ۱۸۰,۰۰۰ تومان
────────────────
جمع: ۲,۱۸۰,۰۰۰ تومان
```
#### بعد:
```
سبد خرید:
محصول A × 2 = ۲,۰۰۰,۰۰۰ تومان
مالیات (۹%): ۱۸۰,۰۰۰ تومان
────────────────
جمع: ۲,۱۸۰,۰۰۰ تومان
📊 PV این سفارش: ۲,۰۰۰,۰۰۰ ← جدید
💎 PV انباشته: ۹۱,۶۰۰,۰۰۰ ← جدید
```
### ۲.۴ پرداخت پکیج — مودال خرید
#### قبل:
```
┌─── خرید پکیج طلایی ───┐
│ │
│ مبلغ: ۵۶,۰۰۰,۰۰۰ تومان │
│ │
│ [پرداخت آنلاین] │
│ [اقساط دایا] │
│ [پرداخت دستی] │
└──────────────────────────┘
```
#### بعد:
```
┌─── خرید پکیج نقره‌ای ───┐ ┌─── خرید پکیج پایه ───┐
│ │ │ │
│ مبلغ: ۵,۶۰۰,۰۰۰ تومان │ │ مبلغ: ۵۶,۰۰۰,۰۰۰ تومان│
│ │ │ │
│ سهم باشگاه: ۲,۵۲۰,۰۰۰ │ │ سهم باشگاه: ۲۵,۲۰۰,۰۰│
│ شارژ کیف‌پول: ۵,۶۰۰,۰۰۰ │ │ شارژ کیف‌پول: ۵۶,۰۰۰,۰│
│ هدیه تخفیفی: ۱۱,۲۰۰,۰۰۰ │ │ هدیه تخفیفی: ۱۱۲,۰۰۰,۰│
│ │ │ │
│ [پرداخت آنلاین] ✅ │ │ [پرداخت آنلاین] ✅ │
│ [اقساط دایا] ❌ ندارد │ │ [اقساط دایا] ✅ │
│ [پرداخت دستی] ✅ │ │ [پرداخت دستی] ✅ │
└────────────────────────────┘ └────────────────────────┘
```
**تغییرات کلیدی:**
- نمایش breakdown مالی: سهم باشگاه + شارژ کیف‌پول + هدیه تخفیفی
- دکمه‌های پرداخت شرطی بر اساس `SupportsDayaPurchase` / `SupportsDirectPurchase`
- متن قرارداد داینامیک بر اساس پکیج انتخاب‌شده
### ۲.۵ صفحه تنظیمات مشتری (`Settings.razor`) — جدید
```
┌─── تنظیمات اعلان‌ها ───┐
│ │
│ 📧 اعلان ایمیل: [✅] │
│ 📱 اعلان SMS: [✅] │
│ 🔔 اعلان Push: [❌] │
│ │
│ [ذخیره تغییرات] │
└──────────────────────────┘
```
> وصل به RPC: `UpdateCustomerSettings`
### ۲.۶ تاریخچه سفارشات — دکمه تکرار
```
┌─── تاریخچه سفارشات ────────────────────────────────────────┐
│ # │ تاریخ │ مبلغ │ وضعیت │ PV │ عملیات │
│───┼────────────┼────────────┼───────────┼───────────┼────────│
│ 1 │ ۱۴۰۴/۱۱/۰۲│ ۴,۲۰۰,۰۰۰ │ تحویل ✅ │ ۴,۲۰۰,۰۰ │ [🔄] [📍]│
│ 2 │ ۱۴۰۴/۱۰/۱۵│ ۱,۸۰۰,۰۰۰ │ ارسال 📦 │ ۱,۸۰۰,۰۰ │ [📍]│
│ 3 │ ۱۴۰۴/۰۹/۲۰│ ۳,۵۰۰,۰۰۰ │ تحویل ✅ │ ۳,۵۰۰,۰۰ │ [🔄] [📍]│
└─────────────────────────────────────────────────────────────┘
🔄 = تکرار سفارش (CustomerReorderPreviousOrder)
📍 = ردیابی سفارش (CustomerTrackOrder)
```
---
## ۳. تجربه ادمین (BackOffice) — قبل و بعد
### ۳.۱ مدیریت پکیج‌ها (`PackageMainPage.razor`)
#### قبل:
```
┌─── مدیریت پکیج‌ها ────────────────────────────────┐
│ # │ عنوان │ قیمت │ وضعیت │ عملیات │
│───┼──────────┼─────────────┼───────┼──────────────│
│ 1 │ طلایی │ ۵۶,۰۰۰,۰۰۰ │ فعال │ [ویرایش] │
└────────────────────────────────────────────────────┘
```
#### بعد:
```
┌─── مدیریت پکیج‌ها ──────────────────────────────────────────────────────┐
│ # │ عنوان │ قیمت │ سهم باشگاه │ ضریب │ دایا │ پایه │ ترتیب│ عملیات │
│───┼─────────┼─────────────┼────────────┼────────┼──────┼──────┼──────┼───────────────│
│ 1 │ نقره‌ای │ ۵,۶۰۰,۰۰۰ │ ۲,۵۲۰,۰۰۰ │ ×2.0 │ ❌ │ ❌ │ 1 │ [✏️] [📋] [❌] │
│ 2 │ پایه │ ۵۶,۰۰۰,۰۰۰ │ ۲۵,۲۰۰,۰۰│ ×2.0 │ ✅ │ ✅ │ 2 │ [✏️] [📋] [❌] │
└──────────────────────────────────────────────────────────────────────────┘
✏️ = ویرایش 📋 = مدیریت فیچرها ❌ = حذف
```
### ۳.۲ ماتریس فیچر × پکیج (`PackageFeatureMatrixPage.razor`) — صفحه جدید
```
┌─── ماتریس فیچر × پکیج ─────────────────────────────────────────┐
│ │
│ فیچر │ نقره‌ای │ پایه │ ویژه │
│ ─────────────────────────┼─────────┼────────┼──────────────────│
│ دسترسی به باشگاه │ ✅ │ ✅ │ ✅ │
│ کیف‌پول جادویی │ ✅ │ ✅ │ ✅ │
│ فروشگاه عادی │ ✅ │ ✅ │ ✅ │
│ فروشگاه تخفیفی │ ❌ │ ✅ │ ✅ │
│ محصولات ClubExclusive │ ❌ │ ✅ │ ✅ │
│ پشتیبانی اختصاصی │ ❌ │ ❌ │ ✅ │
│ کمیسیون شبکه │ ✅ │ ✅ │ ✅ │
│ ─────────────────────────┼─────────┼────────┼──────────────────│
│ │ [ذخیره] │ [ذخیره]│ [ذخیره] │
└─────────────────────────────────────────────────────────────────┘
ادمین با checkbox فیچرها را به هر پکیج اختصاص می‌دهد.
وصل به RPC: AssignFeatureToMembership
```
### ۳.۳ فعالسازی باشگاه (`ActivateClubDialog.razor`)
#### قبل:
```
فعالسازی باشگاه مشتریان
کاربر: علی محمدی
[فعالسازی] ← hardcoded 56M + همه فیچرها
```
#### بعد:
```
فعالسازی باشگاه مشتریان
کاربر: علی محمدی
پکیج: [▼ انتخاب پکیج ▼] ← dropdown از API
├── نقره‌ای (۵,۶۰۰,۰۰۰)
└── پایه (۵۶,۰۰۰,۰۰۰)
جزئیات:
سهم باشگاه: _________ (خودکار)
فیچرها: _________ (از ماتریس پکیج)
[فعالسازی]
```
### ۳.۴ داشبورد (`Index.razor`) — بهبود
```
┌─── آمار باشگاه ────────────────────────────────────────────────┐
│ │
│ 👥 کل اعضا: ۱,۲۴۰ │
│ 📦 پکیج نقره‌ای: ۸۲۰ | پکیج پایه: ۴۲۰ │
│ 💰 Pool نقره‌ای: ۲,۰۶۶,۴۰۰,۰۰۰ | Pool پایه: ۱۰,۵۸۴,۰۰۰,۰۰│
│ ⚠️ هشدار: ۱۲ محصول موجودی کم │
│ │
│ ┌── موجودی انبار ──┐ ┌── ارزش کل انبار ──┐ │
│ │ ۳,۴۵۰ آیتم │ │ ۸۹,۲۰۰,۰۰۰,۰۰۰ │ │
│ │ ۱۲ نوع محصول │ │ ریال │ │
│ └───────────────────┘ └───────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
وصل به: GetInventorySummary, GetStockValueReport, GetLowStockProducts
```
### ۳.۵ مدیریت شبکه (`UserNetworkInfo.razor`) — بهبود
```
┌─── مدیریت شبکه ─────────────────────────────────────────┐
│ │
│ کاربر: سارا احمدی (ID: 1045) │
│ پکیج: نقره‌ای │ چرخه: ۱ │ PV: ۵,۶۰۰,۰۰۰ │
│ Parent: علی محمدی (ID: 1001) │
│ شاخه: چپ │ عمق: ۳ │
│ │
│ [جابجایی در شبکه] ← مودال: انتخاب parent جدید │
│ │
└───────────────────────────────────────────────────────────┘
وصل به: ChangeNetworkParent
```
---
## ۴. تسک‌های تحول — مرحله‌به‌مرحله
### مرحله ۱: زیرساخت Domain + DB (پایه)
> ⚠️ **بدون این مرحله هیچ‌کدام از تغییرات UI ممکن نیست**
| # | تسک | لایه | فایل‌ها | شرح |
|---|------|------|--------|------|
| T1.1 | اضافه ۷ فیلد به Package entity | Domain | Package.cs, PackageConfiguration.cs | SortOrder, IsActive, IsBasePackage, SupportsDayaPurchase, SupportsDirectPurchase, ActivationFee, DiscountMultiplier, MagicWalletMultiplier |
| T1.2 | ایجاد PackageFeature entity | Domain | PackageFeature.cs, PackageFeatureConfiguration.cs | join table: Package ↔ ClubFeature |
| T1.3 | اضافه PackageId به ClubMembership | Domain | ClubMembership.cs | FK nullable → بعد migration → required |
| T1.4 | اضافه PackageId به ClubMembershipCycle | Domain | ClubMembershipCycle.cs | FK nullable → بعد migration → required |
| T1.5 | اضافه PackageId به WeeklyCommissionPool | Domain | WeeklyCommissionPool.cs | FK + Unique(WeekDefinitionId, PackageId) |
| T1.6 | اضافه PackageId به UserCommissionPayout | Domain | UserCommissionPayout.cs | FK nullable |
| T1.7 | حذف ۵ SystemConstants | Domain | SystemConstants.cs | BasePackageAmount, DayaLoanAmount, ClubActivationFee, ClubMembershipGiftValue, MagicWalletMultiplier |
| T1.8 | EF Migration + Seed | Infrastructure | Migration file | ۲ پکیج + فیچرها + FKها |
| T1.9 | Data Migration Script | Infrastructure | SQL script | کاربران فعلی → PackageId = پکیج پایه |
| T1.10 | بروزرسانی Protoها | Proto | package.proto, clubmembership.proto, commission.proto | فیلدهای جدید |
### مرحله ۲: منطق کسب‌وکار (Handlers)
> **هر handler باید از Package entity مقادیر مالی بخواند**
| # | تسک | فایل | شرح |
|---|------|------|------|
| T2.1 | Generic Verify Handler | VerifyPackagePurchaseCommandHandler.cs | DiscountMultiplier از Package + ساخت UserPackagePurchase |
| T2.2 | Generic Purchase Handler | PurchasePackageCommandHandler.cs | حذف "طلایی" و ID=4 |
| T2.3 | ActivateClubMembership بهبود | ActivateClubMembershipCommandHandler.cs | فیچر از PackageFeature + ActivationFee از Package |
| T2.4 | EXIT Magic Mode ریست | UserOrderService.cs | PackagePurchaseMethod=None, membership.IsActive=false |
| T2.5 | Guards re-purchase | G1-G3 handlers | اجازه خرید اگر MagicCompletedAt پر |
| T2.6 | Re-contract | AcceptClubMembershipContractCommandHandler.cs | اجازه قرارداد مجدد |
| T2.7 | Manual Payment بهبود | CreateManualPaymentCommandHandler.cs | DiscountMultiplier از Package |
| T2.8 | Daya Loan بهبود | CheckAndProcessDayaLoansCommandHandler.cs | حذف ID=4 |
| T2.9 | PackageFeature CRUD | جدید | ادمین بتواند فیچر ↔ پکیج مدیریت کند |
| T2.10 | JWT claims جدید | JWT builder | اضافه CanRepurchase + PackageType |
### مرحله ۳: محاسبه پورسانت (Commission)
| # | تسک | فایل | شرح |
|---|------|------|------|
| T3.1 | SP WeeklyBalances + PackageId | sp_CalculateWeeklyBalances.sql | فیلتر بر اساس PackageId |
| T3.2 | SP CommissionPool + PackageId | sp_CalculateWeeklyCommissionPool.sql | Pool جداگانه هر پکیج |
| T3.3 | Loop روی پکیج‌ها | WeeklyCommissionCalculationService.cs | هر پکیج فعال → محاسبه جداگانه |
| T3.4 | ORM Strategy بهبود | OrmCommissionCalculationStrategy.cs | فیلتر PackageId |
| T3.5 | تست محاسبات | — | با داده واقعی staging |
### مرحله ۴: FrontOffice UI
| # | تسک | صفحه | شرح |
|---|------|------|------|
| T4.1 | کاشی‌های داینامیک | Packages.razor | لود از API + فیچر مقایسه |
| T4.2 | مودال پرداخت شرطی | PackageDetail.razor | دکمه دایا فقط اگر SupportsDayaPurchase |
| T4.3 | MyPackages re-purchase | MyPackages.razor | نوار پیشرفت + دکمه خرید مجدد |
| T4.4 | ActivationSection داینامیک | ActivationSection.razor | قیمت از پکیج |
| T4.5 | قرارداد داینامیک | ClubMembershipContractDialog.razor | متن متناسب با پکیج |
| T4.6 | PV در Checkout | Checkout.razor | نمایش PV سفارش |
| T4.7 | تکرار سفارش | Store Orders pages | دکمه 🔄 |
| T4.8 | ردیابی سفارش | OrderTracking.razor | وصل به API |
| T4.9 | تنظیمات اعلان | Settings.razor | فرم Email/SMS/Push |
### مرحله ۵: BackOffice UI
| # | تسک | صفحه | شرح |
|---|------|------|------|
| T5.1 | CRUD پکیج بهبود | PackageMainPage.razor | فیلدهای جدید + ستون‌های اضافه |
| T5.2 | ماتریس فیچر | PackageFeatureMatrixPage.razor (جدید) | checkbox grid |
| T5.3 | ActivateClub dropdown | ActivateClubDialog.razor | انتخاب پکیج |
| T5.4 | داشبورد بهبود | Index.razor | آمار Pool جداگانه + موجودی |
| T5.5 | شبکه بهبود | UserNetworkInfo.razor | جابجایی parent |
| T5.6 | موجودی کم | LowStockPage.razor | وصل API |
| T5.7 | گزارش ارزش انبار | InventoryMainPage.razor | تب گزارش |
| T5.8 | عملیات دسته‌ای | InventoryMainPage.razor | Bulk Add/Update |
### مرحله ۶: تست و استقرار
| # | تسک | شرح |
|---|------|------|
| T6.1 | تست خرید هر پکیج | ZarinPal + Manual |
| T6.2 | تست re-purchase | تکمیل چرخه → خرید مجدد |
| T6.3 | تست Commission Pool | جداگانه بودن هر پکیج |
| T6.4 | تست Migration | rollback plan |
| T6.5 | Deploy staging → production | blue-green |
---
## ۵. پیش‌بینی نیازمندی‌های آینده
### ۵.۱ نیازمندی‌های مشتری (که فعلاً اولویت پایین هستند)
| # | نیاز | RPC آماده? | توضیح |
|---|------|-----------|-------|
| N1 | ارتقای پکیج (نقره‌ای → پایه) | ❌ جدید | پرداخت تفاضل + فعالسازی فیچرهای جدید |
| N2 | مقایسه پکیج‌ها side-by-side | ❌ جدید | جدول فیچر مقایسه‌ای (client-side) |
| N3 | اعلان قبل از اتمام چرخه | ❌ جدید | Background service: 5 روز قبل → push/SMS |
| N4 | گزارش PV ماهانه | CalculateOrderPV ✅ | جدول PV هر ماه + نمودار |
| N5 | پروفایل شبکه | ❌ جدید | مشتری درخت خودش را ببیند |
### ۵.۲ نیازمندی‌های ادمین (که فعلاً اولویت پایین هستند)
| # | نیاز | RPC آماده? | توضیح |
|---|------|-----------|-------|
| N6 | پکیج تخفیفی زمان‌دار | ❌ جدید | پکیج با قیمت ویژه برای مدت محدود |
| N7 | گزارش تبدیل (conversion) | ❌ جدید | چند نفر از نقره‌ای به پایه ارتقا دادند |
| N8 | هشدار Pool خالی | ❌ جدید | اگر Pool یک پکیج خالی شد → هشدار |
| N9 | export گزارش مالی | GetStockValueReport ✅ | دانلود Excel |
| N10 | تخصیص فیچر bulk | AssignFeatureToMembership ✅ | فیچر به همه اعضای یک پکیج |
---
## ۶. ماتریس تاثیرگذاری بر صفحات
### FrontOffice
| صفحه | تغییر | شدت | مرحله |
|------|-------|------|-------|
| Packages.razor | بازنویسی کامل — کاشی‌های داینامیک | 🔴 | مرحله ۴ |
| PackageDetail.razor | فیچرها از API + دکمه شرطی | 🟡 | مرحله ۴ |
| MyPackages.razor | چرخه + پیشرفت + re-purchase | 🔴 | مرحله ۴ |
| Checkout.razor | PV display | 🟢 | مرحله ۴ |
| ActivationSection.razor | قیمت داینامیک | 🟡 | مرحله ۴ |
| ClubMembershipContractDialog.razor | متن داینامیک | 🟡 | مرحله ۴ |
| PaymentCallback.razor | تغییر JWT claims | 🟡 | مرحله ۴ |
| MembershipPage.razor | نمایش نوع پکیج | 🟢 | مرحله ۴ |
| Settings.razor | فرم اعلان جدید | 🟡 | مرحله ۴ |
| Store Orders | دکمه تکرار + ردیابی | 🟡 | مرحله ۴ |
### BackOffice
| صفحه | تغییر | شدت | مرحله |
|------|-------|------|-------|
| PackageMainPage.razor | ستون‌های جدید + CRUD بهبود | 🟡 | مرحله ۵ |
| PackageFeatureMatrixPage.razor | **صفحه کاملاً جدید** | 🔴 | مرحله ۵ |
| ActivateClubDialog.razor | dropdown پکیج | 🟡 | مرحله ۵ |
| Index.razor (Dashboard) | آمار Pool جداگانه + موجودی | 🟡 | مرحله ۵ |
| UserNetworkInfo.razor | جابجایی + نمایش پکیج | 🟡 | مرحله ۵ |
| ClubMembers.razor | ستون پکیج | 🟢 | مرحله ۵ |
| Statistics.razor | چارت توزیع پکیج | 🟡 | مرحله ۵ |
| InventoryMainPage.razor | خلاصه + گزارش + bulk | 🟡 | مرحله ۵ |
| LowStockPage.razor | وصل API | 🟢 | مرحله ۵ |
---
## 🔗 ارجاعات
| مستند | ربط |
|-------|-----|
| [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) | طراحی فنی ۳۹ تغییر |
| [FEATURE-BACKLOG.md](FEATURE-BACKLOG.md) | بکلاگ ۱۲ RPC آماده |
| [GRPC-SERVICES-AUDIT.md](../cms/GRPC-SERVICES-AUDIT.md) | آدیت ۳۴۲ RPC |
| [BUSINESS-01-CLUB-COMMISSION.md](../business/BUSINESS-01-CLUB-COMMISSION.md) | مستند باشگاه و کمیسیون |
| [BUSINESS-04-USER-MEMBERSHIP.md](../business/BUSINESS-04-USER-MEMBERSHIP.md) | مستند عضویت کاربر |
---
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۰۶*