Files
docs/overview/OVERVIEW-03-CHANGELOG.md
masoodafar-web e3850f9dd8 docs: فاز ۱۱ — فیکس‌های پرداخت ZarinPal + تصحیح تومان/ریال + امنیت Callback URL
- CHANGELOG: Phase 11 (11a-11f) — ZarinPal verify fix, تومان/ریال مدل, صفحه موفقیت, حذف ×۱۰ دوبار, callback URL امنیت
- BUSINESS-02: تصحیح مدل ارزی (DB=تومان نه ریال), ZarinPal verify fix, جدول callback URL امنیت
- TECH-01: اضافه CmsBaseUrl/FrontOfficeBaseUrl به appsettings, توضیح امنیت Open Redirect
- TECH-02: اضافه PaymentCallback.razor, وضعیت‌های جدید
- ROADMAP: بروزرسانی Payment 97→99%, اضافه فاز ۱۱ به DONE list
2026-02-27 22:33:35 +03:30

34 KiB
Raw Permalink Blame History

📜 تاریخچه کارهای انجام‌شده

همه فعالیت‌های پروژه به صورت بولت با توضیح یک‌خطی و درصد تکمیل
آخرین بروزرسانی: اسفند ۱۴۰۴ (بروزرسانی: فاز ۱۱ — فیکس‌های پرداخت ZarinPal + امنیت Callback URL + اصلاح تومان/ریال)


خلاصه کلی

حوزه تعداد آیتم تکمیل‌شده درصد کل
BackOffice 67 67 100%
FrontOffice 60 60 100%
CMS Core 89 89 100%
Package-Based System 52 52 100%
Deployment 22 21 95%
Migration 21 21 100%
مجموع 311 310 99.5%

۱. BackOffice — فازها (98% کامل)

Phase 1-3: پایه و ساختار

  • ارتقا به MudBlazor v8 — تغییر تمام کامپوننت‌ها به API جدید
  • پیاده‌سازی MainLayout با Drawer و AppBar — RTL support
  • ایجاد NavMenu با آیکون‌ها و گروه‌بندی — دسته‌بندی منطقی
  • پیاده‌سازی الگوی Code-behind — جدا کردن logic از markup
  • اضافه کردن Theme سفارشی — رنگ‌ها و فونت Vazirmatn

Phase 4-6: محصولات و فروشگاه

  • صفحه لیست محصولات — MudDataGrid با pagination
  • فرم ایجاد/ویرایش محصول — MudForm با FluentValidation
  • آپلود تصویر محصول — Drag & drop با preview
  • مدیریت دسته‌بندی‌ها — CRUD درختی
  • AppImage کامپوننت — تصاویر مربعی ۱:۱ همه‌جا

Phase 7-9: سفارشات و مالی

  • لیست سفارشات — فیلتر وضعیت، تاریخ، مبلغ
  • جزئیات سفارش — آیتم‌ها + تراکنش‌ها
  • تغییر وضعیت سفارش — با تأیید دیالوگ
  • گزارش مالی — خلاصه تراکنش‌ها

Phase 10-12: کاربران و باشگاه

  • لیست کاربران — جستجو + فیلتر نقش
  • مدیریت عضویت باشگاه — فعال/غیرفعال
  • نمای درخت شبکه — نمایش باینری با سطوح
  • مدیریت کمیسیون — مشاهده Pool هفتگی

Phase 13-15: محتوا و تنظیمات

  • مدیریت بلاگ — CRUD پست‌ها با ادیتور HTML
  • مدیریت صفحات سایت — Shopify-style typed editors
  • HomePageEditor — ویرایش Hero, Featured, Promotion
  • AboutPageEditor — ویرایش متن درباره‌ما
  • ContactPageEditor — اطلاعات تماس
  • LicensesPageEditor — مجوزها
  • ادیتور SystemConstants — تنظیمات key-value

Phase 16-17: موجودی و نهایی‌سازی

  • صفحه موجودی — با MudAutocomplete برای انتخاب محصول
  • ایجاد خودکار رکورد موجودی — هنگام ساخت محصول
  • Hangfire InventorySync — ایجاد رکوردهای گمشده
  • Dark Mode — طراحی نشده (Phase آینده)

Phase 18: بهبود UI ادمین (اسفند ۱۴۰۴)

  • UserAutoComplete در ActivateClubDialog — جایگزین MudNumericField برای انتخاب کاربر
  • فیلتر کاربر در صفحه ClubMembers — UserAutoComplete در تولبار جستجو
  • نمایش نام کاربر در WalletManagementPage — TemplateColumn با UserName + ID

Phase 8b: CRUD پکیج کامل (اسفند ۱۴۰۴)

  • CreateDialog: اضافه ۱۲ فیلد جدید — SortOrder, ActivationFee, DiscountMultiplier, MagicWallet*, MaxBalancesPerLeg, MaxNetworkLevel, IsActive, IsBasePackage, SupportsDirectPurchase, SupportsDayaPurchase
  • UpdateDialog: همان ۱۲ فیلد جدید — ایجاد فرم کامل ادمین
  • PackageMainPage Grid: ۴ ستون جدید — قیمت (N0), ترتیب, وضعیت (فعال/غیرفعال chip), نوع (پایه/عادی chip)
  • فیکس HasPurchasedGoldenPackageHasPurchasedPackage — UserNetworkInfo.razor
  • NuGet bump 0.0.184 → 0.0.186 + local feed source

۲. FrontOffice — فازها (95% کامل)

UI Modernization Phase 1-3

  • ارتقا به MudBlazor v8 — همه کامپوننت‌ها
  • MainLayout جدید — Header + Footer + RTL
  • AuthLayout — صفحات Login/Register
  • Landing Page — Hero + Features + Counter + CTA
  • اصلاح انیمیشن Counter — linear interpolation

فروشگاه (Phase 4-5)

  • Regular Store — لیست محصولات با Lazy Load (12/page)
  • Discount Store — لیست با Lazy Load + hybrid payment
  • ProductCard مشترک — تصویر مربعی + قیمت + دکمه
  • CategoryFilter — فیلتر دسته‌بندی sidebar
  • ProductDetail — جزئیات + تصویر بزرگ + سبد
  • سبد خرید — Regular + Discount جداگانه
  • Checkout — پرداخت ZarinPal + ترکیبی

باشگاه (Phase 6)

  • داشبورد باشگاه — ۳ کیف‌پول + آمار
  • نمای درخت شبکه — باینری بصری
  • امضای قرارداد — OTP + scroll-to-bottom
  • صفحه Chatika — چت AI
  • کیف‌پول جادویی — MagicWallet.razor + فرم شارژ + پروگرس‌بار سقف

فعال‌سازی درگاه پرداخت (اسفند ۱۴۰۴)

  • دکمه پرداخت شارژ کیف‌پول اعتباری — ChargeDiscountWallet.razor فعال شد (حذف «بزودی»)
  • دکمه پرداخت شارژ کیف‌پول جادویی — MagicWallet.razor فعال شد (حذف «بزودی»)
  • دکمه‌های پرداخت مستقیم خرید پکیج — Index.razor هر دو شاخه فعال شدند (حذف «بزودی»)

فیکس‌های پرداخت و UX (اسفند ۱۴۰۴ — Phase 11)

  • صفحه موفقیت پرداختTransactionId بجای RefId + موجودی واقعی + Href="/profile" (FO:5ded91a)
  • حذف دوبار ×۱۰ — FO مستقیم تومان ارسال می‌کند، CMS/ZarinPal ×۱۰ می‌کند (FO:2f9ef15)
  • حذف CallbackUrl از درخواستIndex.razor.cs و Checkout.razor.cs دیگر URL ارسال نمی‌کنند (FO:2b1dc47)
  • ۳ کامیت، ۷ فایل تغییر

Phase 8a+8c: Checkout + Package Pages (اسفند ۱۴۰۴)

  • Checkout wire-up — مهاجرت به CustomerPurchasePackageAsync (حذف dead code قدیمی)
  • PackageDetail: GetPackageAsyncGetCustomerPackageDetailsAsync — 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

Phase 10a: PackagePurchaseDialog — دیالوگ داینامیک خرید پکیج (اسفند ۱۴۰۴)

  • PackagePurchaseDialog.razor — دیالوگ ۲ مرحله‌ای: مرحله ۱ = کاشی‌های پکیج (responsive grid)، مرحله ۲ = انتخاب روش پرداخت
  • حذف دیالوگ inline خرید «پکیج پایه» از Index.razor — جایگزین با دیالوگ داینامیک
  • بارگذاری پکیج‌ها از PackageService.GetAllPackagesAsync() — نمایش عنوان + قیمت + ویژگی‌ها
  • پشتیبانی از ۲ روش پرداخت: مستقیم (درگاه بانکی) + اعتبار دایا (فقط پکیج پایه + دور اول)
  • CSS کلاس‌های جدید: .pkg-tile, .pkg-tile-badge, .pkg-payment-option
  • کامیت: a3681a8 (FO)

Phase 10b: ۴ فیکس UI پکیج (اسفند ۱۴۰۴)

  • Toman/Rial: قیمت از سرور به ریال ← FormattedPrice حالا Price / 10 برای نمایش صحیح تومان
  • لیبل: «ضریب تخفیف» → «ضریب اعتبار» (دیالوگ + صفحه لیست پکیج‌ها)
  • دکمه بازگشت: وجود داشت (ArrowForward + BackToList) — تأیید عملکرد
  • HTML Description: @((MarkupString)pkg.Description) بجای متن ساده
  • کامیت: 3c1a8ff (FO)

Phase 11: فیکس‌های پرداخت + تومان/ریال + امنیت Callback URL (اسفند ۱۴۰۴)

11a: اصلاح مدل تومان/ریال (CMS+FO)

تصحیح مهم: دیتابیس به تومان ذخیره می‌کند نه ریال. فقط درگاه ZarinPal ریال نیاز دارد (×۱۰).

  • ZarinPalPaymentService.InitiatePaymentAsync — مبلغ ×۱۰ تبدیل به ریال فقط هنگام ارسال به ZarinPal
  • ZarinPalPaymentService.VerifyPaymentWithAmountAsync — مبلغ ×۱۰ هنگام verify
  • FrontOffice نمایش مستقیم مبلغ تومان (بدون /10) — فیکس MagicWallet.razor, ChargeDiscountWallet.razor.cs
  • حذف Price / 10 اضافی در ClubMembershipContractDialog.razor

11b: فیکس ZarinPal Verify — رفع خطای Code=-1 (CMS:721661a)

باگ: VerifyPaymentAsync با ۲ آرگومان مبلغ صفر (0) ارسال می‌کرد → ZarinPal Code=-1 برمی‌گرداند

  • PackageService — lookup PaymentTransaction.Amount + استفاده از overload ۳ آرگومانه
  • TransactionsService — همان فیکس
  • VerifyDiscountWalletChargeCommandHandler — مبلغ از PaymentTransaction + رفع کپی‌پیست باگ
  • VerifyPackagePurchaseCommandHandler — مبلغ از PaymentTransaction
  • IPaymentGatewayService — default impl ۳ آرگومانه با NotImplementedException
  • MockPaymentGatewayService + DayaPaymentService — اضافه overload ۳ آرگومانه
  • ۷ فایل تغییر

11c: بهبود صفحه موفقیت پرداخت (FO:5ded91a)

  • PaymentCallback.razor — نمایش TransactionId بجای RefId برای کد رهگیری
  • نمایش موجودی واقعی کیف‌پول از WalletService.GetBalancesAsync() (نه مقدار ثابت)
  • دکمه بازگشت: Href="/profile" بجای history.back() (جلوگیری از حلقه بازگشت به درگاه)

11d: حذف دوبار ×۱۰ شارژ کیف‌پول (FO:2f9ef15)

باگ: FO مبلغ تومان را ×۱۰ تبدیل به ریال می‌کرد، سپس CMS/ZarinPal دوباره ×۱۰ → مبلغ ۱۰۰ برابر

  • MagicWallet.razor.cs — حذف تبدیل ×۱۰ (ارسال مستقیم تومان)
  • MagicWallet.razor — فیکس Max و فیلتر preset مبالغ
  • ChargeDiscountWallet.razor.cs — حذف تبدیل ×۱۰
  • ClubMembershipContractDialog.razor — حذف Price/10 اضافی
  • ۴ فایل تغییر

11e: فیکس مسیر Callback کیف‌پول (CMS:ed2b20a)

  • PaymentCallbackController — مسیر redirect از /magic-wallet به /profile/magic-wallet
  • ایجاد appsettings.Development.json — URL‌های محلی (localhost:32846 و localhost:5268)
  • تصحیح کامنت‌های proto: «ریال» → «تومان»

11f: امنیت Callback URL — حذف از ورودی کاربر (CMS:0107308, FO:2b1dc47)

اصلاح امنیتی: هیچ callback URL نباید از ورودی کاربر بیاید — همه از appsettings.json خوانده شوند

  • PackageService — خواندن FrontOfficeBaseUrl از IConfiguration بجای request.CallbackUrl
  • TransactionsService — همان فیکس، خواندن از config
  • تأیید: MagicWallet و DiscountWallet از قبل از CmsBaseUrl config می‌خوانند
  • تأیید: DiscountShop PlaceOrder از قبل از CmsBaseUrl config می‌خواند
  • FO: حذف CallbackUrl از Index.razor.cs و Checkout.razor.cs
  • جدول Callback URL‌ها:
فلو Callback URL منبع
خرید پکیج FrontOfficeBaseUrl/profile/payment-callback?orderId=X config
کیف‌پول جادویی CmsBaseUrl/api/wallet/verify-magic-charge config
کیف‌پول اعتباری CmsBaseUrl/api/wallet/verify-discount-charge config
فروشگاه اعتباری CmsBaseUrl/api/payment/discount-order/callback?orderId=X config
تراکنش عمومی FrontOfficeBaseUrl/profile/payment-callback config

محتوا و ناوبری

  • بلاگ — لیست + جزئیات + pagination
  • صفحات سایت — About, Contact, FAQ, Terms, Privacy, Licenses
  • ناوبری Auth-Aware — مسیردهی بر اساس نقش
  • Home → Club Dashboard / Store بر اساس وضعیت
  • Mobile Responsive — Phase 7 (برنامه‌ریزی‌شده)
  • PWA — نیاز به Service Worker
  • Bottom Navigation (موبایل) — طراحی نشده

۳. CMS Core (97% کامل)

ساختار و معماری

  • CQRS با MediatR — Commands + Queries + Handlers
  • gRPC Services — ۱۱ سرویس اصلی
  • EF Core 9 — Migrations + Seeding
  • Hangfire — ۴ Background Job
  • JWT Authentication — Claims-based
  • ICurrentUserService — جداسازی Admin/Customer

محصولات و فروشگاه

  • Product CRUD — با auto-inventory
  • Category CRUD — درختی
  • Inventory management — auto-create + sync job
  • GetProductsPaged — با PaginationState
  • File upload/download — streaming gRPC

مالی و پرداخت

  • ZarinPal Integration — IPG + Verify
  • PYMS Service — سرویس مرکزی پرداخت
  • ۳ Wallet System — Balance, Network, Discount
  • Transaction logging — همه تراکنش‌ها

باشگاه

  • Binary Tree — SP_GetNetworkTree
  • Weekly Balance Calculation — sp_CalculateWeeklyBalances
  • Commission Pool — sp_CalculateWeeklyCommissionPool
  • Contract System — OTP + acceptance
  • Club Features — activate/deactivate
  • DayaLoan Integration — Hangfire + Polly

🪄 کیف‌پول جادویی (Magic Wallet) — فاز 1-6

  • فاز ۱: WalletMode enum + UserWallet fields + ClubMembershipCycle entity + TransactionType (14,15)
  • فاز ۲: Trigger ورود/خروج Magic در SubmitShopBuyOrder + ActivateClubMembership Cycle
  • فاز ۳: ChargeMagicWallet + VerifyMagicWalletCharge + HTTP callback + gRPC RPCs
  • فاز ۴: فیلتر Magic از کمیسیون (C# + SP) + تاریخ Cycle
  • فاز ۵: MagicWallet.razor UI + WalletService + تایل داشبورد
  • فاز ۶: محدودیت دایا بعد از دور اول + محدودیت فعالسازی در حالت Magic

VAT

  • اصلاح VAT از 9% به 10% در همه فایل‌ها (VatCalculator, UserOrderService, Checkout, VATService)

فعال‌سازی درگاه و تنظیمات محیطی (اسفند ۱۴۰۴)

  • تنظیم MerchantId جدید ZarinPal — 4225d555-5fa9-4df0-9b61-1ce152cbbba8
  • تنظیمات محیطی — Staging: UseSandbox=true / Production: UseSandbox=false
  • فعال‌سازی MagicWalletCycleSeed در Production
  • تنظیم Kestrel Http2 + Seq logging برای Production
  • بهبود user_name در proto — فیلد جدید در GetAllUserWalletByFilterResponseModel
  • اغنای پاسخ UserWalletService — join با جدول Users برای نمایش نام کاربر
  • ارتقای Proto NuGet به نسخه 0.0.183

فیکس‌های پرداخت و امنیت (اسفند ۱۴۰۴ — Phase 11)

  • ZarinPal Verify fix — رفع باگ amount=0 در VerifyPaymentAsync (Code=-1) — ۳ آرگومانه overload
  • تصحیح مدل تومان/ریال — DB به تومان ذخیره می‌کند، فقط ZarinPal ریال (×۱۰) نیاز دارد
  • Callback URL از configPackageService و TransactionsService از FrontOfficeBaseUrl config می‌خوانند (نه از ورودی)
  • فیکس مسیر redirect/magic-wallet/profile/magic-wallet در PaymentCallbackController
  • appsettings.Development.json — URL‌های محلی برای توسعه (CmsBaseUrl + FrontOfficeBaseUrl)
  • کامیت‌ها: 721661aed2b20a0107308

محتوا

  • Blog CRUD — با pagination
  • SitePage Settings — JSON typed
  • SystemConfigurations — key-value
  • Product Bundle — طراحی‌شده، پیاده‌سازی نشده
  • Manual Payment — طراحی‌شده، پیاده‌سازی نشده
  • API Rate Limiting — برنامه‌ریزی‌شده

۴. Deployment و زیرساخت (95% کامل)

  • Docker Compose — تمام سرویس‌ها
  • Dockerfile (CMS) — multi-stage build
  • K8s Manifests — Deployment + Service + Ingress
  • CI/CD Pipeline — Gitea Actions
  • Nexus Repository — NuGet + Docker proxy
  • Offline Deployment — کامل با اسکریپت‌ها
  • Proto Package — NuGet packaging + distribution
  • Health Check scripts — K8s + service
  • Mirror Configuration — Docker + NuGet
  • Base Image Caching — pull + save + load
  • مرج پروداکشن CMS — حل conflict در appsettings.Production.json + حذف migration تکراری u21
  • مرج پروداکشن FrontOffice — ۲۱ فایل، ۴۰۰ insertion + فیکس GwUrl
  • مرج پروداکشن BackOffice — ۳۶ فایل، بدون conflict
  • اجرای Migration روی پروداکشن — ExpandDiscountProductFullInformation روی DB کی‌بی‌اس
  • Monitoring (Prometheus/Grafana) — برنامه‌ریزی‌شده
  • Log Aggregation (ELK/Seq) — Seq تنظیم شده در Production (http://seq-svc:5341)

۵. Migration (100% کامل)

  • FrontOffice REST → gRPC — همه سرویس‌ها migrate شدند
  • BackOffice REST → gRPC — همه سرویس‌ها migrate شدند
  • BFF حذف — یک لایه کمتر در deployment
  • API Gateway (Ocelot) حذف — K8s Ingress جایگزین
  • Data Migration — Users, Products, Orders, Club
  • Geography Seeder — ۳۱ استان + ۱۲۰۰ شهر
  • SQL Scripts — ۱۴ اسکریپت مهاجرت اجرا شدند
  • Proto Package Unification — یک package مشترک
  • Binary Tree Reconstruction — از سیستم قدیم

DataMigration Tool (اسفند ۱۴۰۴)

  • ابزار مستقل مهاجرت داده — .NET 9 Console + Dapper + Polly + Serilog
  • Smart Retry Policy — فقط خطاهای transient SQL (deadlock, timeout, transport) — نه خطاهای منطقی
  • FK Disable/Enable — NOCHECK/CHECK حول مهاجرت برای حل FK violation
  • TruncateTargetTables — حل مشکل duplicate key (IX_ClubMembership_UserId)
  • Fallback Table Name — اگر جدول مقصد rename شده (UserWalletChangeLogsUserWalletHistories)
  • PostMigration SQL — همه مراحل با IF COL_LENGTH / OBJECT_ID guard شده
  • کامیت‌ها: 0e8c6fd8385c9031cc464

EF Migration — Staging (اسفند ۱۴۰۴)

  • اعمال migrations روی DB استیجینگ KBS (185.252.31.42,2019/KBS) — موفق
  • اعمال migrations روی DB اپلیکیشن (194.5.195.53,31433/Foursat) — موفق
  • آخرین migration: 20260227024734_Q27_HistoryTables_And_RenameWalletHistory (۵۵ migration مجموع)
  • حل خطای لاگین Invalid column name 'FirstActivationDate' — دو DB مختلف بودند

۶. مستندات (100% کامل)

  • ایجاد totalDoc repository — مخزن مرکزی docs
  • جمع‌آوری ۵۳ فایل از ۵ مخزن مختلف
  • تجمیع به ۱۵ فایل ساختارمند — Business + Technical + Overview
  • Index و Cross-reference — نقشه ارتباطات
  • واژه‌نامه و استانداردها
  • نقشه راه آینده

۷. تحول سیستم پکیج‌بیس (Package-Based Transformation) — 90%

📦 تبدیل سیستم تک‌پکیجی hardcoded به معماری چند‌پکیجی داینامیک مرجع: BIZ-PACKAGE-BASED-SYSTEM.md | 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 × 2package.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.PackageIdcm.LastPackageId — match actual DB column name
  • Fix golden/طلایی string refs in user-facing messages (ActivateClubMembership)
  • Rename HasPurchasedGoldenPackageHasPurchasedPackage (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.1860.0.187

Phase 9 — Q24-Q30 Business Decisions + History Infrastructure

9a: Q24+Q26 — Balance Threshold + SP Worker (CMS:a1024a3)

  • Q24: آستانه موجودی Balance <= 1_000_000 ریال برای ورود Magic و خرید مجدد (بجای == 0)
  • Q26: StoredProcedureDeploymentService (IHostedService) — خواندن فایل‌های .sql از embedded resource، مقایسه checksum و اعمال خودکار در startup

9b: Q27 — History Tables Entities (CMS:fdbb91d)

  • PackageHistory entity — فیلدهای Old*/New* برای Price, ActivationFee, MagicMultiplier, MagicMaxDeposit, MaxBalancesPerLeg, IsActive
  • ClubMembershipCycleHistory entity — فیلدهای Old*/New* برای IsCurrentCycle, MagicStartedAt, MagicCompletedAt
  • PackageAction و ClubMembershipCycleAction enums
  • EF Configurations + DbSets + Navigation Properties

9c: Q28 — UI Guidance (FO:474d364 BO:6939780)

  • FrontOffice: ۷ صفحه با MudAlert (G1-G7) — Packages, Checkout, MyPackages, MagicWallet, Commission, Membership, ActivationSection
  • BackOffice: ۶ صفحه با MudAlert (G8-G13) — PackageCRUD, ClubFeatures, ManualPayments, Commission Dashboard, UserPayouts, ClubMembers

9d: Rename + History Interceptor + Migration (CMS:10d2ca2)

  • تغییر نام UserWalletChangeLogUserWalletHistory در ۵۴+ فایل (entities, configs, DTOs, commands, queries, protos, services)
  • تغییر نام ۳۴ فایل و ۱۱ دایرکتوری
  • تغییر نام proto: userwalletchangelog.protouserwallethistory.proto
  • IHasHistory<T> generic interface — متد CreateHistorySnapshot برای ثبت خودکار
  • HistoryTrackingSaveChangesInterceptor — reflection-based، auto-fill Old* از OriginalValues
  • Package implements IHasHistory<PackageHistory>
  • EF Migration Q27_HistoryTables_And_RenameWalletHistoryRenameTable (حفظ داده) + rename PK/FK/Index via sp_rename
  • NuGet: 0.0.1870.0.188

Phase 10 — استقرار + DataMigration + UI خرید پکیج

10a: DataMigration Tool (Local — بدون remote)

  • ابزار مستقل مهاجرت داده — .NET 9 Console app + Dapper (bulk copy) + Polly (retry) + Serilog (logging)
  • مهاجرت ۱۸ جدول از DB پروداکشن (185.252.31.42,2019/Foursat) به استیجینگ (KBS)
  • Smart Retry — فقط خطاهای transient (deadlock/timeout/transport)، نه خطاهای منطقی
  • FK Disable/Enable — ALTER TABLE NOCHECK/CHECK CONSTRAINT حول هر مهاجرت
  • TruncateTargetTables — حل duplicate key (IX_ClubMembership_UserId) هنگام اجرای مجدد
  • Fallback Table Name — جدول مقصد rename شده؟ (UserWalletChangeLogsUserWalletHistories)
  • PostMigration SQL — همه مراحل با IF COL_LENGTH/OBJECT_ID guard شده (سازگار با هر دو schema)
  • کامیت‌ها: 0e8c6fd8385c90 (MERGE fix) → 31cc464 (FK+truncate+PostMigration)

10b: EF Migration Staging

  • اعمال ۵۵ migration روی DB استیجینگ KBS (185.252.31.42,2019;Database=KBS)
  • اعمال ۵۵ migration روی DB اپلیکیشن (194.5.195.53,31433;Database=Foursat)
  • آخرین migration: 20260227024734_Q27_HistoryTables_And_RenameWalletHistory
  • حل خطای لاگین: Invalid column name 'FirstActivationDate' — CMS به DB دیگری وصل بود

10c: PackagePurchaseDialog — دیالوگ داینامیک خرید (FO:a3681a8)

  • PackagePurchaseDialog.razor — دیالوگ ۲ مرحله‌ای جایگزین دیالوگ hardcoded «پکیج پایه»
  • مرحله ۱: نمایش کاشی‌های پکیج (responsive grid 2-3 ستونه) با عنوان + قیمت + ویژگی‌ها + badge «پایه»
  • مرحله ۲: انتخاب روش پرداخت (مستقیم + اعتبار دایا) با خلاصه پکیج انتخابی
  • بارگذاری از PackageService.GetAllPackagesAsync() + PackagePurchaseResult record
  • محدودیت دایا: فقط SupportsDayaPurchase && PurchaseCycleCount == 0
  • CSS: .pkg-tile, .pkg-tile-badge, .pkg-payment-option در site.css
  • NuGet: 0.0.1880.0.189

10d: ۴ فیکس UI پکیج (FO:3c1a8ff)

  • Toman/Rial: قیمت از سرور به ریال ← FormattedPrice حالا Price / 10 برای نمایش صحیح تومان
  • لیبل: «ضریب تخفیف» → «ضریب اعتبار» (دیالوگ + صفحه لیست پکیج‌ها)
  • دکمه بازگشت: وجود داشت (ArrowForward + BackToList) — تأیید عملکرد
  • HTML Description: @((MarkupString)pkg.Description) بجای متن ساده

۸. Timeline (جدول زمانی)

زمان رویداد درصد پروژه
مهر ۱۴۰۳ شروع پروژه، معماری CMS 10%
آبان ۱۴۰۳ CQRS + gRPC + EF Core 20%
آذر ۱۴۰۳ باشگاه + درخت باینری + کمیسیون 35%
دی ۱۴۰۳ فروشگاه عادی + پرداخت از کیف‌پول 45%
بهمن ۱۴۰۳ فروشگاه اعتباری + وام دایا 55%
اسفند ۱۴۰۳ (هفته ۱) UI Modernization Phase 1-3 65%
اسفند ۱۴۰۳ (هفته ۲) Site Pages + BackOffice audit 75%
اسفند ۱۴۰۳ (هفته ۳) Inventory + Lazy Load + Images 85%
اسفند ۱۴۰۳ (هفته ۴) مستندات + نهایی‌سازی 95%
اسفند ۱۴۰۴ (هفته ۱-۲) 🪄 کیف‌پول جادویی (فاز 1-6) + اصلاح VAT 10% 96%
اسفند ۱۴۰۴ (هفته ۳) 🚀 فعال‌سازی درگاه + بهبود UI ادمین + مرج پروداکشن 97%
اسفند ۱۴۰۴ (هفته ۴) 📦 تحول پکیج‌بیس فاز ۰-۶ (Domain → Migration → Business → Package → CRUD → Commission per-pkg → Deprecation) 97%
اسفند ۱۴۰۴ (هفته ۵) 📦 فاز 8e: گزارش‌های پورسانت per-package (Proto + CMS + BO + FO) 98%
اسفند ۱۴۰۴ (هفته ۶) 📦 فاز ۹: Q24-Q30 (آستانه + SP Worker + History Tables + UI Guidance + Rename + Interceptor + Migration) 99%
اسفند ۱۴۰۴ (هفته ۷) 📦 فاز ۱۰: DataMigration Tool + EF Staging + PackagePurchaseDialog + UI Fixes (Toman/Rial + لیبل + HTML) 99.5%
اسفند ۱۴۰۴ (هفته ۸) 💳 فاز ۱۱: فیکس ZarinPal Verify + اصلاح تومان/ریال + صفحه موفقیت + حذف دوبار ×۱۰ + امنیت Callback URL 99.5%