f5173a4def
- CHANGELOG: اضافه Phase 18 BackOffice + فعالسازی درگاه FO + تنظیمات محیطی CMS + مرج پروداکشن - PAYMENT-FINANCE: MerchantId واقعی + تنظیمات محیطی Staging/Production + Magic فاز 6 کامل - ROADMAP: بروزرسانی درصدها + Magic 100% + Payment 97% + DONE section - TECH-02: ساختار فولدر + UserAutoComplete + WalletManagement + دکمههای درگاه - BUSINESS-01: Magic Wallet فاز 1-6 کامل - TECH-04: Migration پروداکشن ExpandDiscountProductFullInformation + حذف u21 تکراری - TECH-03: جزئیات مرج پروداکشن + تنظیمات appsettings.Production.json - MAGIC-WALLET-PLAN: وضعیت کامل - INDEX: بروزرسانی تاریخ
10 KiB
10 KiB
🪄 پلن پیادهسازی کیفپول جادویی
مرجع: MAGIC-WALLET-SPEC
تخمین کل: ~۷ روز کاری
وضعیت: ✅ کامل — همه ۶ فاز پیادهسازی و مرج شده
وابستگی مستقل: تکمیل ChargeDiscountWallet (ربطی به جادویی ندارد) ✅
فازبندی
فاز ۱ — مدل داده و Migration (روز ۱)
هدف: زیرساخت دیتابیس و enumها
فایلهای تغییری:
├── UserWallet.cs → + WalletMode, MagicTotalDeposited, MagicTotalCredited, MagicActivatedAt, MagicCompletedAt
├── WalletMode.cs → enum جدید (Normal=0, Magic=1)
├── TransactionType.cs → + MagicWalletDeposit=14, MagicWalletBonus=15
├── SystemConstants.cs → + MagicWalletMultiplier, MagicWalletMaxDeposit, MagicWalletMaxCredit
├── UserWalletConfiguration.cs → EF config برای فیلدهای جدید
├── ClubMembershipCycle.cs → 🆕 entity جدید (حل مشکل تاریخ کمیسیون)
├── ClubMembershipCycleConfiguration.cs → EF config
├── Migration: AddMagicWalletFields → dotnet ef migrations add
└── Migration: AddClubMembershipCycle → dotnet ef migrations add + data seed
تست: Migration اجرا بشه، فیلدها در DB ایجاد بشن، defaultها درست باشن. هر ClubMembership موجود یه رکورد Cycle=1 داشته باشه.
فاز ۲ — Trigger ورود/خروج Magic (روز ۲)
هدف: State Machine خودکار
فایلهای تغییری:
├── SubmitShopBuyOrderCommandHandler.cs
│ ├── بعد از کسر Balance: check ورود به Magic
│ └── بعد از کسر Balance: check خروج از Magic
│
├── ActivateClubMembershipCommandHandler.cs
│ ├── ActivatedAt فقط بار اول ست بشه (دیگه overwrite نشه)
│ └── هر بار یک ClubMembershipCycle جدید اضافه بشه
│
├── (Optional) Domain Event: WalletModeChangedEvent
│ └── برای لاگ و نوتیفیکیشن
│
└── User.cs (یا UserWallet)
└── + PurchaseCycleCount (int) — تعداد دور خرید پکیج
تست:
- سناریو ۱: Balance=0 بعد از خرید → WalletMode=Magic ✅
- سناریو ۲: بدون پکیج + Balance=0 → نباید Magic بشه ❌
- سناریو ۳: Magic + Balance=0 + TotalDeposited=50M (سقف پر نشده) → هنوز Magic! نباید خارج بشه ❌
- سناریو ۴: Magic + Balance=0 + TotalDeposited=100M (سقف پر) → خروج ✅
- سناریو ۵: Magic + Balance=30M + TotalDeposited=100M → هنوز Magic! (بالانس داره) ❌
- سناریو ۶: خروج از Magic → خرید مجدد پکیج → Balance=0 → Magic مجدد با سقف ریستشده ✅
- سناریو ۷: دور دوم → TotalDeposited, TotalCredited = 0 (ریست) ✅
فاز ۳ — API شارژ جادویی (روز ۳-۴)
هدف: مسیر کامل شارژ از درگاه با ضریب ×2.5
فایلهای جدید:
├── InitiateMagicChargeCommand.cs
├── InitiateMagicChargeCommandHandler.cs
├── InitiateMagicChargeCommandValidator.cs
├── VerifyMagicChargeCommand.cs
├── VerifyMagicChargeCommandHandler.cs
├── MagicWalletController.cs → GET /api/wallet/verify-magic-charge
│
├── userwallet.proto → + InitiateMagicCharge, GetMagicWalletStatus RPCs
└── UserWalletService.cs → implement new RPCs
نکات مهم:
├── هر شارژ = ۲ تراکنش (Deposit + Bonus)
├── هر شارژ = ۱ WalletChangeLog (اجباری)
├── Validation: WalletMode==Magic && TotalDeposited+Amount <= Cap
└── Callback: /api/wallet/verify-magic-charge → redirect FrontOffice
تست:
- واریز 10M → Balance += 25M, TotalDeposited += 10M ✅
- واریز بیشتر از سقف → خطا ❌
- واریز در Normal Mode → خطا ❌
- ۲ تراکنش + ۱ لاگ ثبت شده ✅
فاز ۴ — غیرفعالسازی کمیسیون + تاریخ Cycle (روز ۴.۵)
هدف: کاربرهای Magic از کمیسیون خارج بشن + تاریخ کمیسیون از Cycle بخونه
فایلهای تغییری:
├── CalculateWeeklyBalancesCommandHandler.cs
│ ├── فیلتر: WHERE wallet.WalletMode != Magic
│ └── تاریخ: ActivatedAt → ClubMembershipCycle.PackagePurchasedAt
│
├── sp_CalculateWeeklyBalances.sql
│ ├── + JOIN UserWallets WHERE WalletMode = 0
│ └── WHERE cm.ActivatedAt → cc.PackagePurchasedAt (AND cc.IsCurrentCycle = 1)
│
└── WeekRepository (اگه date range query داره)
└── آپدیت query
تست:
- کاربر Magic در محاسبات هفتگی شرکت نکنه ✅
- کاربر دور ۲ (پکیج مجدد): با تاریخ PackagePurchasedAt جدید امتیاز بگیره ✅
- تاریخ اصلی ActivatedAt تغییر نکرده باشه ✅
فاز ۵ — صفحات FrontOffice (روز ۵-۶)
هدف: UI شارژ جادویی + نمایش وضعیت
فایلهای جدید:
├── Pages/Profile/MagicWallet.razor → فرم شارژ + پروگرسبار سقف
├── Pages/Profile/MagicWallet.razor.cs → code-behind
├── Pages/Profile/MagicPaymentCallback.razor → نتیجه پرداخت
└── Pages/Profile/MagicPaymentCallback.razor.cs
فایلهای تغییری:
├── WalletService.cs → + InitiateMagicChargeAsync, GetMagicWalletStatusAsync
├── RouteConstants.cs → + MagicWallet, MagicPaymentCallback
├── Pages/Profile/Index.razor → بنر Magic Mode
├── Pages/Profile/Wallet.razor → پروگرس سقف + لینک شارژ
└── NavMenu / Sidebar → لینک شرطی به صفحه جادویی
UI شارژ جادویی:
┌──────────────────────────────────────────────┐
│ 🪄 کیفپول جادویی │
│ │
│ وضعیت: فعال ✅ │
│ مجموع واریزی: 30M / 100M تومان │
│ ██████████░░░░░░░░░░░░░░░░░░░░ 30% │
│ مجموع اعتبار دریافتی: 75M تومان │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ مبلغ واریز: [________] تومان │ │
│ │ اعتبار دریافتی: 0 × 2.5 = 0 تومان │ │
│ │ باقیمانده سقف: 70M تومان │ │
│ │ │ │
│ │ [ 🔒 پرداخت از درگاه ] │ │
│ └──────────────────────────────────────┘ │
└──────────────────────────────────────────────┘
فاز ۶ — محدودیت خرید مجدد پکیج (روز ۷)
هدف: بعد از Magic فقط IPG مجاز باشه
فایلهای تغییری:
├── CheckAndProcessDayaLoansCommandHandler.cs
│ └── if PurchaseCycleCount > 0 → reject
│
├── Package Purchase UI (FrontOffice)
│ └── if PurchaseCycleCount > 0 → hide Daya button
│
└── ActivateClubMembershipCommandHandler.cs
└── if WalletMode == Magic → "ابتدا جادویی تمام شود"
Checklist پیادهسازی
- فاز ۱: WalletMode enum
- فاز ۱: UserWallet entity + 5 فیلد جدید
- فاز ۱: ClubMembershipCycle entity (جدید)
- فاز ۱: TransactionType + 2 مقدار
- فاز ۱: SystemConstants + 3 ثابت
- فاز ۱: EF Configuration (UserWallet + ClubMembershipCycle)
- فاز ۱: Migration: AddMagicWalletFields (u21 — اعمال شده ✅)
- فاز ۱: Migration: AddClubMembershipCycle + data seed (74 رکورد seed شده ✅)
- فاز ۲: Trigger ورود Magic (SubmitShopBuyOrder)
- فاز ۲: Trigger خروج Magic
- فاز ۲: ActivateClubMembership → ActivatedAt نگهداشته بشه + Cycle جدید
- فاز ۲: PurchaseCycleCount
- فاز ۳: InitiateMagicChargeCommand + Handler
- فاز ۳: VerifyMagicChargeCommand + Handler
- فاز ۳: MagicWalletController (HTTP callback)
- فاز ۳: gRPC Proto + Service
- فاز ۳: ۲ تراکنش + ۱ لاگ (اجباری)
- فاز ۴: فیلتر کمیسیون Magic (C# handler + SP)
- فاز ۴: تاریخ کمیسیون: ActivatedAt → Cycle.PackagePurchasedAt (C# + SP)
- فاز ۵: MagicWallet.razor
- فاز ۵: MagicPaymentCallback — نتیجه پرداخت از طریق ?payment= query param در همان MagicWallet.razor هندل میشه
- فاز ۵: WalletService gRPC client
- فاز ۵: Profile + Wallet page updates
- فاز ۶: Daya restriction (CheckAndProcessDayaLoansCommandHandler + FO Purchase UI)
- فاز ۶: Club activation restriction (ActivateClubMembershipCommandHandler + WalletMode guard)
وابستگی مستقل: تکمیل ChargeDiscountWallet ✅
✅ تکمیل شد — مستقل از کیفپول جادویی پیادهسازی شد.
انجام شده:
├── ChargeDiscountWalletCommandHandler — CQRS handler ✅
├── VerifyDiscountWalletChargeCommandHandler — ✅
├── PaymentCallbackController → GET /api/wallet/verify-discount-charge ✅
├── userwallet.proto → rpc InitiateDiscountCharge ✅
├── UserWalletService.cs → InitiateDiscountCharge override ✅
├── WalletService.cs (FO) → InitiateDiscountChargeAsync ✅
├── ChargeDiscountWallet.razor + .razor.cs (FO) ✅
├── RouteConstants → ChargeDiscountWallet ✅
└── Wallet.razor → دکمه شارژ اعتباری ✅