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
This commit is contained in:
@@ -207,11 +207,12 @@
|
|||||||
|
|
||||||
## ⚠️ نکات مهم
|
## ⚠️ نکات مهم
|
||||||
|
|
||||||
1. **آرشیو ≠ حذف!** — RPCهای آرشیوشده فقط با `// [ARCHIVED]` علامتگذاری میشوند
|
1. **آرشیو ≠ حذف!** — RPCهای آرشیوشده با `[Obsolete]` + `#region [ARCHIVED]` علامتگذاری شدند (کامیت `13dd0f5`)
|
||||||
2. RPCهای دسته B (Internal — ۱۰۱ عدد) **حیاتی** هستند — بدون آنها سیستم از کار میافتد
|
2. RPCهای دسته B (Internal — ۱۰۱ عدد) **حیاتی** هستند — بدون آنها سیستم از کار میافتد
|
||||||
3. RPCهای «نگهداری» (۱۲ عدد) کد **کامل و آماده** دارند — فقط نیاز به وصل شدن از فرانت
|
3. RPCهای «نگهداری» (۱۲ عدد) کد **کامل و آماده** دارند — بکلاگ فیچر: [FEATURE-BACKLOG.md](../roadmap/FEATURE-BACKLOG.md)
|
||||||
4. **fms.proto** تنها فایل proto کاملاً مُرده است — میتواند از csproj اکسکلود شود
|
4. **fms.proto** از csproj اکسکلود شد (کامیت `13dd0f5`)
|
||||||
5. قبل از هر تغییر، حتماً `grep -rn "RpcName" CMS/src/` بزنید تا مطمئن شوید
|
5. نقشهراه تحول پکیجبیس: [PACKAGE-TRANSFORMATION-TASKS.md](../roadmap/PACKAGE-TRANSFORMATION-TASKS.md)
|
||||||
|
6. قبل از هر تغییر، حتماً `grep -rn "RpcName" CMS/src/` بزنید تا مطمئن شوید
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
# 📋 فیچر بکلاگ — RPCهای آماده (بدون UI)
|
||||||
|
|
||||||
|
> تاریخ: ۱۴۰۴/۱۲/۰۶
|
||||||
|
> منبع: آدیت gRPC (کامیت `3575e48`) → ۱۲ RPC کامل بدون فرانت
|
||||||
|
> اولویتبندی: بر اساس ارزش کسبوکار + نیازمندی پکیجبیس
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 خلاصه
|
||||||
|
|
||||||
|
از ۲۴ RPC مُرده شناساییشده، **۱۲ عدد پیادهسازی کامل** دارند ولی هرگز از فرانتها وصل نشدند. اینها فیچرهای آماده هستند که فقط نیاز به UI دارند.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 ماتریس فیچر × اولویت
|
||||||
|
|
||||||
|
### 🔴 اولویت بالا — مرتبط با پکیجبیس کردن
|
||||||
|
|
||||||
|
| # | RPC | تارگت | صفحه | اقدام | تخمین |
|
||||||
|
|---|-----|-------|------|-------|-------|
|
||||||
|
| F1 | `AssignFeatureToMembership` | BackOffice | ClubFeaturesPage.razor | دکمه «اختصاص فیچر به عضو» + ماتریس PackageFeature | ۴ ساعت |
|
||||||
|
| F2 | `ChangeNetworkParent` | BackOffice | UserNetworkInfo.razor | دکمه «جابجایی در شبکه» + مودال انتخاب parent جدید | ۶ ساعت |
|
||||||
|
| F3 | `CalculateOrderPV` | FrontOffice | Checkout.razor + MyPackages.razor | نمایش PV سفارش در چکاوت + PV انباشته در صفحه پکیجها | ۴ ساعت |
|
||||||
|
|
||||||
|
### 🟡 اولویت متوسط — بهبود 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) → با تستهای شبکه فاز ۵ ادغام
|
||||||
|
F3 (CalculateOrderPV) → با T4.3 (MyPackages re-purchase) ادغام
|
||||||
|
```
|
||||||
|
|
||||||
|
### فاز 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) | طراحی سیستم پکیجبیس — ۳۹ تغییر |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۰۶*
|
||||||
@@ -0,0 +1,418 @@
|
|||||||
|
# 🔄 نقشهراه تحول پکیجبیس — تسکهای گامبهگام
|
||||||
|
|
||||||
|
> **وضعیت:** تاییدشده — آماده شروع
|
||||||
|
> **تاریخ:** ۱۴۰۴/۱۲/۰۶
|
||||||
|
> **پیشنیاز:** [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) v2
|
||||||
|
> **هدف:** شکستن ۳۹ تغییر به تسکهای اتمیک با ترتیب اجرا و وابستگیها
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 نمای کلی
|
||||||
|
|
||||||
|
```
|
||||||
|
مرحله ۰: فیکس باگ فوری (۱ روز)
|
||||||
|
└─→ مرحله ۱: زیرساخت Domain + DB (۳ روز)
|
||||||
|
├─→ مرحله ۲: منطق کسبوکار (۴ روز) ← موازی
|
||||||
|
│ └─→ مرحله ۴: FrontOffice UI (۳ روز)
|
||||||
|
└─→ مرحله ۳: پورسانت (۳ روز) ← موازی
|
||||||
|
└─→ مرحله ۵: BackOffice UI (۳ روز)
|
||||||
|
└─→ مرحله ۶: تست + استقرار (۲ روز)
|
||||||
|
|
||||||
|
مسیر بحرانی: ۰→۱→۲→۴→۶ = ~۱۳ روز
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## مرحله ۰ — فیکس باگهای فوری
|
||||||
|
|
||||||
|
> ⏱️ ۱ روز | وابستگی: ندارد | ریسک: کم
|
||||||
|
|
||||||
|
### ✅ وضعیت باگها (بررسی اولیه لازم)
|
||||||
|
|
||||||
|
| # | باگ | 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)
|
||||||
|
|
||||||
|
> ⏱️ ۳ روز | وابستگی: مرحله ۰ | ریسک: متوسط (migration)
|
||||||
|
|
||||||
|
### T1.1 — بروزرسانی Package Entity
|
||||||
|
|
||||||
|
**فایل:** `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;
|
||||||
|
+ 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? | توضیح |
|
||||||
|
|--------|------|-----------|-------|
|
||||||
|
| ClubMembership | `long? PackageId` | nullable (بعد migration → required) | آخرین پکیج |
|
||||||
|
| ClubMembershipCycle | `long PackageId` | required | پکیج این چرخه |
|
||||||
|
| WeeklyCommissionPool | `long PackageId` | required + Unique(WeekDefId, PkgId) | Pool هر پکیج |
|
||||||
|
| UserCommissionPayout | `long? PackageId` | nullable | ردیابی |
|
||||||
|
|
||||||
|
### T1.7 — حذف SystemConstants
|
||||||
|
|
||||||
|
**فایل:** `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; // اگر وجود داشت
|
||||||
|
```
|
||||||
|
|
||||||
|
> ⚠️ **قبل از حذف:** grep تمام مصرفکنندهها → جایگزین با `Package.Property`
|
||||||
|
|
||||||
|
### 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
|
||||||
|
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;
|
||||||
|
|
||||||
|
-- 3. Seed Silver package
|
||||||
|
INSERT INTO "CMS"."Packages" (...) VALUES ('پکیج نقرهای', 5600000, ...);
|
||||||
|
```
|
||||||
|
|
||||||
|
### T1.10 — بروزرسانی Protoها
|
||||||
|
|
||||||
|
| Proto File | تغییر |
|
||||||
|
|-----------|-------|
|
||||||
|
| package.proto | فیلدهای جدید Package message |
|
||||||
|
| clubmembership.proto | package_id در request/response |
|
||||||
|
| commission.proto | package_id در pool/payout messages |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## مرحله ۲ — منطق کسبوکار
|
||||||
|
|
||||||
|
> ⏱️ ۴ روز | وابستگی: مرحله ۱ | ریسک: بالا (رگرسیون)
|
||||||
|
|
||||||
|
### 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 ?? "");
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## مرحله ۳ — محاسبه پورسانت (موازی با مرحله ۲)
|
||||||
|
|
||||||
|
> ⏱️ ۳ روز | وابستگی: مرحله ۱ | ریسک: بحرانی (مالی)
|
||||||
|
|
||||||
|
### T3.1-T3.2 — SPs + PackageId
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- sp_CalculateWeeklyBalances:
|
||||||
|
ALTER PROCEDURE sp_CalculateWeeklyBalances
|
||||||
|
@WeekDefinitionId BIGINT,
|
||||||
|
@PackageId BIGINT -- ← جدید
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
-- فیلتر بالانسها فقط کاربرانی که این پکیج را دارند
|
||||||
|
INSERT INTO "CMS"."WeeklyBalances" (...)
|
||||||
|
SELECT ...
|
||||||
|
FROM "CMS"."UserWallets" w
|
||||||
|
INNER JOIN "CMS"."ClubMemberships" m ON m."UserId" = w."UserId"
|
||||||
|
WHERE m."PackageId" = @PackageId -- ← فیلتر
|
||||||
|
AND m."IsActive" = true
|
||||||
|
AND w."WalletMode" = 0; -- Normal only
|
||||||
|
END;
|
||||||
|
```
|
||||||
|
|
||||||
|
### T3.3 — Loop Service
|
||||||
|
|
||||||
|
```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}",
|
||||||
|
package.Id, package.Title);
|
||||||
|
|
||||||
|
await strategy.CalculateWeeklyBalancesAsync(weekId, package.Id);
|
||||||
|
await strategy.CalculateWeeklyPoolAsync(weekId, package.Id);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ⚠️ نکته بحرانی
|
||||||
|
|
||||||
|
> پورسانت = پول واقعی. **هر تغییر در SPs باید:**
|
||||||
|
> 1. ابتدا در staging با داده واقعی تست شود
|
||||||
|
> 2. نتایج قبل و بعد مقایسه شوند
|
||||||
|
> 3. Rollback plan آماده باشد
|
||||||
|
> 4. در production ابتدا read-only اجرا شود (بدون commit)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## مرحله ۴ — FrontOffice UI
|
||||||
|
|
||||||
|
> ⏱️ ۳ روز | وابستگی: مرحله ۲ | ریسک: متوسط
|
||||||
|
|
||||||
|
### 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 — مودال پرداخت شرطی
|
||||||
|
|
||||||
|
```razor
|
||||||
|
@if (_selectedPackage.SupportsDirectPurchase)
|
||||||
|
{
|
||||||
|
<MudButton OnClick="PayOnline">پرداخت آنلاین</MudButton>
|
||||||
|
}
|
||||||
|
@if (_selectedPackage.SupportsDayaPurchase)
|
||||||
|
{
|
||||||
|
<MudButton OnClick="PayDaya">اقساط دایا</MudButton>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### T4.3 — MyPackages + Re-Purchase
|
||||||
|
|
||||||
|
```razor
|
||||||
|
@if (_canRepurchase)
|
||||||
|
{
|
||||||
|
<MudAlert Severity="Severity.Success">
|
||||||
|
🎉 چرخه جادویی تکمیل شد! میتوانید پکیج جدید بخرید.
|
||||||
|
</MudAlert>
|
||||||
|
<MudButton Href="/packages">خرید پکیج جدید</MudButton>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<MagicWalletProgress Wallet="@_wallet" Cycle="@_currentCycle" />
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## مرحله ۵ — BackOffice UI
|
||||||
|
|
||||||
|
> ⏱️ ۳ روز | وابستگی: مرحله ۳ | ریسک: کم
|
||||||
|
|
||||||
|
_(تسکها در PACKAGE-TRANSFORMATION-UX.md بخش ۳ مستند شده)_
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## مرحله ۶ — تست و استقرار
|
||||||
|
|
||||||
|
> ⏱️ ۲ روز | وابستگی: مرحله ۴ و ۵
|
||||||
|
|
||||||
|
### Checklist تست
|
||||||
|
|
||||||
|
- [ ] خرید پکیج نقرهای (ZarinPal)
|
||||||
|
- [ ] خرید پکیج پایه (ZarinPal)
|
||||||
|
- [ ] خرید پکیج پایه (Daya Loan)
|
||||||
|
- [ ] خرید پکیج پایه (Manual Payment)
|
||||||
|
- [ ] فعالسازی باشگاه با پکیج نقرهای → فیچرهای محدود
|
||||||
|
- [ ] فعالسازی باشگاه با پکیج پایه → همه فیچرها
|
||||||
|
- [ ] تکمیل چرخه Magic → ریست وضعیت
|
||||||
|
- [ ] خرید مجدد بعد تکمیل چرخه
|
||||||
|
- [ ] Commission Pool جداگانه هر پکیج
|
||||||
|
- [ ] Data Migration — PackageId در رکوردهای قبلی
|
||||||
|
- [ ] JWT claims جدید (CanRepurchase, PackageId)
|
||||||
|
- [ ] UI: کاشیهای داینامیک FrontOffice
|
||||||
|
- [ ] UI: ماتریس فیچر BackOffice
|
||||||
|
- [ ] Rollback: بدون data loss
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📅 تقویم پیشنهادی
|
||||||
|
|
||||||
|
| هفته | روز | تسک |
|
||||||
|
|------|-----|------|
|
||||||
|
| هفته ۱ | روز ۱ | مرحله ۰: فیکس ۴ باگ |
|
||||||
|
| | روز ۲-۳ | مرحله ۱: Package entity + PackageFeature |
|
||||||
|
| | روز ۴ | مرحله ۱: FKها + Migration |
|
||||||
|
| هفته ۲ | روز ۵-۶ | مرحله ۲: Generic handlers + re-purchase |
|
||||||
|
| | روز ۵-۶ | مرحله ۳: SP + Loop (موازی) |
|
||||||
|
| | روز ۷-۸ | مرحله ۲: Guards + JWT + Manual |
|
||||||
|
| هفته ۳ | روز ۹-۱۰ | مرحله ۴: FrontOffice UI |
|
||||||
|
| | روز ۱۱ | مرحله ۵: BackOffice UI |
|
||||||
|
| | روز ۱۲-۱۳ | مرحله ۶: تست + deploy |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔗 ارجاعات
|
||||||
|
|
||||||
|
| مستند | محتوا |
|
||||||
|
|-------|-------|
|
||||||
|
| [BIZ-PACKAGE-BASED-SYSTEM.md](../business/BIZ-PACKAGE-BASED-SYSTEM.md) | طراحی فنی — ۳۹ تغییر + باگها |
|
||||||
|
| [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 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۰۶*
|
||||||
@@ -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) | مستند عضویت کاربر |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
*آخرین بروزرسانی: ۱۴۰۴/۱۲/۰۶*
|
||||||
Reference in New Issue
Block a user