From 7a62e3caac55ae30499e3f4e9cab0bc4fdfced5f Mon Sep 17 00:00:00 2001 From: masoodafar-web Date: Wed, 18 Feb 2026 21:44:14 +0330 Subject: [PATCH] docs: move docs to totalDoc, replace with placeholders --- docs/BACKOFFICE-AUDIT.md | 1011 +--------------------------------- docs/BACKOFFICE-CHANGELOG.md | 851 +--------------------------- 2 files changed, 4 insertions(+), 1858 deletions(-) diff --git a/docs/BACKOFFICE-AUDIT.md b/docs/BACKOFFICE-AUDIT.md index fd5df5c..18c6348 100644 --- a/docs/BACKOFFICE-AUDIT.md +++ b/docs/BACKOFFICE-AUDIT.md @@ -1,1010 +1,3 @@ -# 🔍 BackOffice Admin Panel — Deep Audit Report +# Docs moved to totalDoc -**تاریخ:** ۱۴۰۴/۰۴ -**نسخه:** v7.0 — Global Search + Notifications + Export All + NavMenu Badge -**آخرین بروزرسانی:** ۱۴۰۴/۰۴/۱۳ (July 4, 2025) -**هدف:** بررسی عمیق یکپارچگی دیزاین سیستم، UX/UI، بیزینس لاجیک، ساختار صفحات و ناوبری پنل مدیریت - ---- - -## 🏆 وضعیت اجرا — خلاصه - -| فاز | عنوان | وضعیت | تعداد آیتم | انجام‌شده | -|---|---|---|---|---| -| فاز ۱ | زیرساخت دیزاین سیستم | ✅ **کامل** | 5 | 5/5 | -| فاز ۲ | بازطراحی لایوت صفحات | ✅ **کامل** | 6 | 6/6 | -| فاز ۲.۵ | پاکسازی ساختاری | ✅ **کامل** | 7 | 7/7 | -| فاز ۳ | UX بهبودها | ✅ **کامل** | 6 | 6/6 | -| فاز ۳.۵ | ادغام صفحات | ✅ **کامل** | 6 | 6/6 | -| فاز ۴ | فیکس‌های بیزینسی | ✅ **کامل** | 11 | 10/11 | -| فاز ۴.۵ | Cross-Navigation | 🟡 **بخشی** | 5 | 3/5 | -| فاز ۵ | صفحات مفقود (CMS) | ✅ **اکثراً** | 8 | 7/8 | -| فاز ۶ | فیچرهای جدید | ✅ **اکثراً** | 5 | 4/5 | -| | **مجموع** | | **58** | **57/58 (≈98%)** | - -> **۱۶ مورد 🔴 بحرانی → همه انجام شده ✅** -> **۲۴ مورد 🟡 مهم → ۲۳ انجام شده، ۱ باقی‌مانده (DayaLoan — blocked on backend)** -> **۱۸ مورد 🟢 جزئی → ۱۸ انجام شده ✅** - ---- - -## 📋 فهرست - -1. [خلاصه اجرایی](#-خلاصه-اجرایی) -2. [مشکلات بحرانی (Critical)](#-مشکلات-بحرانی-critical) -3. [مشکلات دیزاین سیستم](#-مشکلات-دیزاین-سیستم) -4. [ناهماهنگی‌های لایوت صفحات](#-ناهماهنگیهای-لایوت-صفحات) -5. [مشکلات UX/UI](#-مشکلات-uxui) -6. [تحلیل عمیق جریان‌های UX](#-تحلیل-عمیق-جریانهای-ux) -7. [ضعف‌های بیزینسی و فیچرهای ناقص](#-ضعفهای-بیزینسی-و-فیچرهای-ناقص) -8. [تحلیل تطبیقی CMS ↔ BackOffice](#-تحلیل-تطبیقی-cms--backoffice) -9. [تحلیل ساختاری صفحات و ناوبری](#-تحلیل-ساختاری-صفحات-و-ناوبری) -10. [جدول یافته‌ها به تفکیک صفحه](#-جدول-یافتهها-به-تفکیک-صفحه) -11. [برنامه اجرایی (Action Plan)](#-برنامه-اجرایی-action-plan) - ---- - -## 🎯 خلاصه اجرایی - -پنل مدیریت BackOffice از **۳ الگوی متفاوت لایوت** استفاده می‌کند که هیچ‌کدام با هم هماهنگ نیستند. تم رنگی با FrontOffice متفاوت است، رنگ‌های هاردکد در CSS وجود دارد، صفحه لاگین بسیار ابتدایی است، و چندین فیچر بیزینسی ناقص یا غیرفعال هستند. - -### آمار سریع -| معیار | وضعیت | -|---|---| -| تعداد صفحات | ~40+ صفحه | -| الگوهای لایوت متفاوت | **۳** (باید ۱ باشد) | -| رنگ‌های هاردکد | **۴+** مورد | -| Dark Mode | ❌ ندارد (تنظیمات toggle دارد ولی عملکرد ندارد) | -| Breadcrumb / مسیریابی | ❌ ندارد | -| نوتیفیکیشن لحظه‌ای | ❌ ندارد | -| صفحات بدون Loading State | ~۵ مورد | -| صفحات بدون Empty State | ~۸ مورد | -| فیچرهای غیرفعال/ناقص | ۷+ مورد | -| entity‌های CMS بدون صفحه در BackOffice | **۵** مورد | -| جریان‌های UX شکسته | **۴** مورد | - ---- - -## 🚨 مشکلات بحرانی (Critical) - -### C1 — سه الگوی لایوت ناسازگار - -صفحات از سه الگوی کاملاً متفاوت استفاده می‌کنند: - -| الگو | صفحات | ویژگی | -|---|---|---| -| **Pattern A: `BasePageComponent`** | User, Products, Package, Category, UserOrder, Transactions, UserAddress, UserRole, Role | پنل فیلتر ثابت سمت راست (20%) + جدول (80%)، ارتفاع ثابت 85vh | -| **Pattern B: `MudContainer` آزاد** | Blog, Tag, Content, Settings, DiscountShop, PublicMessages, Commission, Network, Club, Inventory, SystemManagement | فیلتر بالای جدول، بدون ساختار ثابت | -| **Pattern C: بدون Container** | Index (Dashboard) | مستقیم `MudStack` + `MudGrid` بدون `MudContainer` | - -**مشکل:** -- Pattern A فیلتر را در یک ستون عمودی ثابت نمایش می‌دهد (مناسب دسکتاپ، مشکل‌دار در موبایل) -- Pattern B فیلتر را بالای جدول می‌گذارد (استاندارد‌تر) -- Pattern C هیچ ساختاری ندارد -- `BasePageComponent` ارتفاع 85vh هاردکد دارد — responsive نیست -- `BasePageComponent` عرض ثابت xs="2" و xs="10" دارد — در صفحات کوچک شکسته می‌شود - -### C2 — تم رنگی ناهماهنگ با FrontOffice - -| جزء | BackOffice | FrontOffice | وضعیت | -|---|---|---|---| -| Primary | `#0380C0` (آبی) | `#6366f1` (ایندیگو) | ❌ ناهماهنگ | -| Secondary | `#5E4DF9` | `#8b5cf6` | ❌ ناهماهنگ | -| PaletteDark | ندارد | ✅ کامل | ❌ ندارد | -| Loading Color (CSS) | `#1b6ec2` (هاردکد) | متغیر تم | ❌ هاردکد | -| NavMenu Active | `#0380C0` (هاردکد CSS) | متغیر تم | ❌ هاردکد | -| User Icon Border | `#5e4df9` (inline style) | — | ❌ هاردکد | - -### C3 — صفحه لاگین بسیار ابتدایی - -- فقط یک MudPaper ساده با عرض `35%` و ارتفاع `200px` -- بدون لوگو، بدون برندینگ -- بدون عنوان "پنل مدیریت" -- عرض ثابت — در موبایل شکسته می‌شود -- صفحه VerifyCode هم همین مشکلات را دارد (ارتفاع `230px` ثابت) - -### C4 — عنوان اپ قدیمی - -- `MainLayout.razor`: "پنل مدیریت **فرصت**" — باید "پنل مدیریت **کارا بازار سلامت**" باشد - ---- - -## 🎨 مشکلات دیزاین سیستم - -### D1 — Elevation ناسازگار - -| صفحه | Elevation | -|---|---| -| Dashboard Index cards | `MudPaper` (بدون elevation) | -| SystemOverview cards | `MudCard Outlined` | -| Commission Dashboard cards | `MudCard Elevation="2"` | -| Inventory stats cards | `MudCard` (پیش‌فرض = 1) | -| HealthDashboard | `MudCard Elevation="2"` و `"3"` | - -**باید:** همه کارت‌های آماری از یک استایل واحد استفاده کنند. - -### D2 — عدم وجود کامپوننت `StatCard` مشترک - -داشبورد‌ها (Index, SystemOverview, Commission, Inventory) همه کارت‌های آماری دارند اما هرکدام ساختار متفاوتی دارند: -- Index: `MudPaper > MudStack > subtitle2 + h5` -- SystemOverview: `MudCard Outlined > body2 + h5` -- Commission: `MudCard Elevation=2 > h6(color) + h4 + body2` -- Inventory: `MudCard > MudStack Row > (caption + h5) + Icon` - -### D3 — MudDataGrid Height ناسازگار - -| صفحه | Height | -|---|---| -| User, Products, Package, Category | `72vh` (داخل BasePageComponent) | -| Blog, Tag | `65vh` | -| Club, WithdrawalRequests | `75vh` | -| Inventory | `60vh` | -| Content, DiscountShop | بدون Height مشخص | -| Commission WeeklyReports | بدون Height مشخص | - -### D4 — PageSize ناسازگار - -| صفحه | PageSizes | PagerText | -|---|---|---| -| User, Products, Package | `30, 60, 90` | فارسی (بعضی) | -| Blog, Tag | `10, 25, 50` | `RowsPerPageString="تعداد در صفحه"` | -| Commission WeeklyReports | پیش‌فرض | — | -| DiscountShop | پیش‌فرض | — | - -### D5 — MaxWidth ناسازگار - -| صفحه | MaxWidth | -|---|---| -| Blog, Content | `MaxWidth.Large` | -| Tag | `MaxWidth.Medium` | -| Commission, Dashboard, Club, Inventory, Settings | `MaxWidth.ExtraLarge` | -| DiscountShop | `MaxWidth.ExtraExtraLarge` | -| Network | `MaxWidth.ExtraExtraLarge` | -| Pages با BasePageComponent | بدون Container (تمام عرض) | - -### D6 — Button Size و Style ناسازگار - -- بعضی دکمه‌ها `Size.Large` (Products, Package) و بعضی `Size.Small` -- همه دکمه‌ها `Style="cursor:pointer;"` دارند — این **غیرضروری** است (MudButton خودش cursor:pointer دارد) -- Pattern ثابتی برای دکمه "افزودن" نیست: - - Products: `Variant.Filled Color.Primary Size.Large` - - Blog: `Variant.Filled Color.Primary + StartIcon` - - DiscountShop: `Variant.Filled Color.Primary FullWidth + StartIcon` - -### D7 — رنگ‌های هاردکد در CSS - -**`wwwroot/css/app.css`:** -```css -/* Loading progress — باید از متغیر تم استفاده کند */ -background-color: #1b6ec2; /* هاردکد */ -``` - -**`Shared/NavMenu.razor.css`:** -```css -/* Active state — باید از CSS variable استفاده کند */ -color: #0380C0; /* هاردکد */ -``` - -**`Shared/MainLayout.razor`:** -```html - -Style="border: 1px solid #5e4df9;" -``` - -**`wwwroot/css/admin-org-chart.css`:** -```css -/* Border colors هاردکد */ -border-left: 4px solid #4caf50; /* green */ -border-left: 4px solid #ff9800; /* orange */ -border-left: 4px solid #1976d2; /* blue */ -``` - ---- - -## 📐 ناهماهنگی‌های لایوت صفحات - -### L1 — BasePageComponent مشکلات ریسپانسیو - -```html - - - -``` - -- بدون breakpoint — همیشه side-by-side -- `Height="85vh"` ثابت — scroll internal -- فیلتر panel عرض ثابت برای متن فارسی کم است - -### L2 — Drawer همیشه Temporary - -```html - -``` -- در دسکتاپ هم drawer پنهان است و فقط با hamburger باز می‌شود -- **باید:** در دسکتاپ `Responsive` باشد و در موبایل `Temporary` - -### L3 — MainContent padding ناکافی - -```html - - -``` -- `mt-5` اضافی (AppBar خودش جا می‌گیرد) -- بعضی صفحات داخل `MudContainer` هم `Class="mt-4"` دارند — double margin - -### L4 — عدم وجود Breadcrumb - -هیچ صفحه‌ای breadcrumb ندارد. برای پنل مدیریتی با سلسله‌مراتب عمیق (مثلاً Users > User Orders > Order Details) این ضروری است. - ---- - -## 🖥 مشکلات UX/UI - -### U1 — عدم وجود Loading State یکپارچه - -| صفحه | Loading State | -|---|---| -| Dashboard (Index) | ❌ ندارد — داده‌ها بدون loading ظاهر می‌شوند | -| SystemOverview | ✅ `MudProgressCircular` | -| Commission Dashboard | ✅ `MudProgressCircular` | -| Inventory | ❌ ندارد (فقط stats ندارند) | -| DiscountShop | ✅ `MudDataGrid Loading` | -| Content | ✅ `MudDataGrid Loading` | -| Login | ❌ فقط دکمه Disabled می‌شود | - -### U2 — عدم وجود Empty State - -اکثر صفحات وقتی داده‌ای نیست، جدول خالی نشان می‌دهند. فقط Commission WeeklyReports یک `MudAlert` نشان می‌دهد. - -### U3 — Delete Confirmation ناسازگار - -- User: `ShowMessageBox` با "حذف/لغو" -- Products: `ShowMessageBox` با "حذف/لغو" -- Blog: احتمالاً `ShowMessageBox` (مشابه) -- **مشکل:** هیچ‌کدام نام آیتم را نشان نمی‌دهند — فقط "آیا مطمئنید؟" -- **باید:** "آیا از حذف «نام محصول» مطمئنید؟" - -### U4 — عدم وجود اعلان/نوتیفیکیشن - -- هیچ سیستم نوتیفیکیشن لحظه‌ای وجود ندارد -- AppBar فقط نام کاربر دارد — بدون bell icon -- سفارش‌های جدید، درخواست‌های برداشت جدید و غیره بدون اطلاع‌رسانی هستند - -### U5 — عدم وجود جستجوی سراسری - -- هیچ global search در AppBar وجود ندارد -- هر صفحه فیلتر مخصوص خودش را دارد - -### U6 — تاریخ شمسی ناسازگار - -- بعضی صفحات از `MiladiToJalali()` استفاده می‌کنند -- بعضی از `PersianDateTime.ConvertToPersianDateTime()` -- بعضی `ToString("yyyy/MM/dd")` (میلادی!) نشان می‌دهند -- `MudDatePicker` تقویم میلادی دارد — باید جلالی باشد - -### U7 — عدم وجود Dark Mode Toggle - -- `CustomMudTheme.cs` هیچ `PaletteDark` ندارد -- هیچ toggle در AppBar وجود ندارد - -### U8 — عدم وجود Profile/Settings کاربر ادمین - -- AppBar فقط شماره موبایل نشان می‌دهد -- بدون dropdown menu برای پروفایل، تنظیمات، خروج -- خروج فقط از NavMenu امکان‌پذیر است - ---- - -## � تحلیل عمیق جریان‌های UX - -### UXF1 — جریان مدیریت سفارش شکسته - -**مسیر فعلی:** کاربر → لیست سفارش‌ها → جزئیات (دیالوگ) → ؟ - -**مشکلات:** -- آمار سفارش‌ها (مجموع، نمودار وضعیت ارسال) **کامنت شده** — ادمین هیچ overview ندارد -- `_paidOrders` و `_totalPaidAmount` در Dashboard فقط از **۱۰ سفارش اخیر** محاسبه می‌شود (PageSize=10) — عدد نمایشی **اشتباه** است -- بعد از تغییر وضعیت ارسال، هیچ notification به کاربر ارسال نمی‌شود -- اگر ادمین از صفحه User → Orders برود، هیچ breadcrumb نیست تا بفهمد از کجا آمده -- فیلتر `MudDatePicker` تقویم **میلادی** دارد — ادمین ایرانی با تاریخ میلادی آشنا نیست -- فیلتر `DeliveryStatus` مقدارهای `0-4` دارد ولی domain enum مقدار `None=0, Pending=1, InTransit=2, Delivered=3, Returned=4, Cancelled=5` دارد — **Cancelled=5 در فیلتر وجود ندارد!** - -### UXF2 — جریان مالی کاربر (Wallet) وجود ندارد - -**CMS domain:** -- `UserWallet` سه نوع موجودی دارد: `Balance` (اصلی)، `NetworkBalance` (کارمزد/طلایی)، `DiscountBalance` (تخفیف) -- `UserWalletChangeLog` تاریخچه کامل تغییرات هر سه موجودی را ثبت می‌کند - -**BackOffice:** -- ❌ **هیچ صفحه‌ای برای مشاهده موجودی کیف پول کاربران وجود ندارد** -- ❌ هیچ صفحه‌ای برای تاریخچه تغییرات کیف پول وجود ندارد -- فقط در ManualPayments می‌توان شارژ دستی انجام داد — ولی ادمین نمی‌تواند موجودی فعلی را ببیند! -- **سناریو:** ادمین باید موجودی کاربر را بررسی کند → مجبور است مستقیم به DB مراجعه کند - -### UXF3 — جریان فعال‌سازی عضویت باشگاه ناقص - -**CMS domain flow (کامل):** -1. کاربر پکیج می‌خرد (Direct یا DayaLoan) -2. قرارداد عضویت باشگاه امضا می‌شود (`UserContract`) -3. عضویت باشگاه فعال می‌شود (`ClubMembership`) -4. فیچرهای باشگاه اختصاص داده می‌شود (`UserClubFeature`) -5. کاربر وارد شبکه باینری می‌شود (`NetworkParentId + LegPosition`) - -**BackOffice:** -- ✅ صفحه ClubMembers: فعال‌سازی، غیرفعال‌سازی، مشاهده جزئیات -- ❌ **مدیریت ClubFeature (فیچرهای باشگاه) وجود ندارد** — ادمین نمی‌تواند فیچرها را مدیریت کند -- ❌ **مدیریت UserClubFeature وجود ندارد** — نمی‌توان فیچر خاصی را برای کاربر خاص فعال/غیرفعال کرد -- ❌ **مدیریت قراردادها (UserContract) وجود ندارد** — فایل‌های قرارداد امضاشده قابل مشاهده نیست -- ❌ **تاریخچه عضویت باشگاه (ClubMembershipHistory) وجود ندارد** -- ❌ صفحه ClubMembers تاریخ‌ها را **میلادی** نشان می‌دهد - -### UXF4 — جریان وام دایا کاملاً غایب - -**CMS domain:** -- `DayaLoanContract` entity: شامل کد ملی، شماره قرارداد، وضعیت (`Pending/Approved/Rejected/Disbursed/Completed/Failed`)، آخرین استعلام، پردازش شارژ کیف پول -- `DayaLoanCQ`: Commands + EventHandlers + Services — سیستم کامل وام - -**BackOffice:** -- ❌ **هیچ صفحه‌ای برای مدیریت وام دایا وجود ندارد** -- فقط در `UserNetworkInfo` یک نمایش ساده "وضعیت دایا" وجود دارد -- ادمین نمی‌تواند: وام‌های جدید را ببیند، وضعیت را تغییر دهد، استعلام دستی بزند - -### UXF5 — جریان پرداخت دستی (ManualPayment) بدون تأیید مناسب - -**CMS domain:** -- `ManualPaymentStatus`: `Pending → Approved/Rejected/Cancelled` -- تأیید باید توسط SuperAdmin انجام شود — جداسازی نقش creator و approver - -**BackOffice:** -- ✅ صفحه ManualPayments وجود دارد با فیلتر و جزئیات -- ❌ **دکمه تأیید/رد مستقیم در لیست وجود ندارد** — فقط "جزئیات" می‌توان دید -- ❌ هیچ تفاوت بصری بین Pending (نیاز به اقدام) و بقیه وضعیت‌ها نیست -- ❌ عدم وجود counter/badge برای تعداد درخواست‌های در انتظار -- ❌ تصویر فیش واریزی (`ImagePath`) قابل مشاهده نیست -- ❌ بدون فیلتر تاریخی - -### UXF6 — جریان کمیسیون و برداشت — Gap Analysis - -**CMS domain (کامل):** -1. Worker هفتگی: `CalculateWeeklyBalances` → `CalculateWeeklyCommissionPool` → `ProcessUserPayouts` -2. واریز به NetworkBalance کیف پول -3. کاربر درخواست برداشت (`RequestWithdrawal`) -4. ادمین تأیید (`ApproveWithdrawal`) یا رد (`RejectWithdrawal`) -5. پردازش نهایی (`ProcessWithdrawal`) -6. تاریخچه (`CommissionPayoutHistory`) - -**BackOffice — آنچه وجود دارد:** -- ✅ Commission Dashboard (نمای استخر) -- ✅ WeeklyReports (تاریخچه هفتگی) -- ✅ UserPayouts (پرداخت‌ها) -- ✅ WithdrawalRequests (درخواست‌ها) -- ✅ WithdrawalReports (گزارش) -- ✅ WorkerControl (کنترل worker) - -**BackOffice — آنچه ناقص است:** -- ❌ **در WithdrawalRequests دکمه Approve/Reject وجود ندارد** (فقط لیست نمایش می‌دهد) -- ❌ وقتی worker اجرا می‌شود، هیچ progress indicator لحظه‌ای نیست -- ❌ بعد از محاسبه دستی، نتیجه به ادمین نشان داده نمی‌شود (فقط refresh لازم است) -- ❌ تاریخچه اجرای worker (`WorkerExecutionLog`) قابل مشاهده نیست (صفحه WorkerControl آن را نمایش نمی‌دهد) -- ❌ هیچ alert/notification خودکار وقتی درخواست برداشت جدید ثبت می‌شود - -### UXF7 — جریان مدیریت محصولات — ناهماهنگی دو فروشگاه - -**CMS domain:** -- **Products** (محصولات اصلی/پکیج): `Product`, `ProductCategory`, `ProductGallery`, `ProductImage`, `ProductTag` -- **DiscountProducts** (فروشگاه تخفیفی): `DiscountProduct`, `DiscountProductCategory`, `DiscountProductImage` -- **Inventory**: `InventoryItem`, `StockMovement`, `Warehouse` — مشترک بین هر دو - -**BackOffice:** -- Products: دارای BulkEdit، Excel Export، Gallery، Tag assignment، Category drag-drop — **کامل و خوب** -- DiscountProducts: فیلتر دسته‌بندی پیاده‌سازی نشده (`TODO: Load categories`)، بدون Gallery، بدون Tag -- ❌ **هیچ لینکی بین InventoryItem و DiscountProduct وجود ندارد** — ادمین نمی‌فهمد موجودی کدام محصول تخفیفی کم است -- ❌ DiscountProducts از `Items` (client-side) بجای `ServerData` استفاده می‌کند — با داده زیاد کُند می‌شود - -### UXF8 — جریان User Profile ادمین - -**مشکل:** ادمین هیچ "هویت" در سیستم ندارد: -- AppBar فقط `sub` claim (شماره موبایل) نشان می‌دهد -- بدون dropdown menu -- بدون نمایش نام/نقش -- بدون عکس پروفایل -- خروج فقط از drawer ممکن است -- **Settings page** دارای toggleهایی برای Dark Mode و زبان است — ولی **هیچ‌کدام عملکرد واقعی ندارند** (فقط local state هستند) - ---- - -## �💼 ضعف‌های بیزینسی و فیچرهای ناقص - -### B1 — DiscountShop Widget غیرفعال در Dashboard - -```razor - -@* *@ -``` -- پیام "در حال توسعه" نشان می‌دهد - -### B2 — UserOrder آمار کامنت‌شده - -```razor -@* - - جمع سفارش‌ها در بازه فعلی - ... - - *@ -``` -- آمار سفارش و نمودار وضعیت ارسال کامنت شده‌اند - -### B3 — DiscountShop Categories خالی - -```razor -همه -@* TODO: Load categories *@ -``` -- فیلتر دسته‌بندی DiscountProducts هنوز پیاده‌سازی نشده - -### B4 — Dashboard Index محاسبات ناقص - -```csharp -_paidOrders = orderResult.Models.Count(m => m.PaymentStatus==PaymentStatus.Success); -_totalPaidAmount = orderResult.Models - .Where(m => m.PaymentStatus==PaymentStatus.Success) - .Aggregate(0L, (sum, m) => sum + m.Amount); -``` -- فقط از ۱۰ سفارش اول (`PageSize = 10`) آمار می‌گیرد — **نادرست!** -- `_paidOrders` و `_totalPaidAmount` از کل داده‌ها محاسبه نمی‌شوند - -### B5 — عدم وجود Export/خروجی در اکثر صفحات - -| صفحه | Export | -|---|---| -| Products | ✅ Excel | -| بقیه صفحات | ❌ ندارند | - -### B6 — عدم وجود Audit Trail / لاگ فعالیت ادمین - -- هیچ سیستم لاگ فعالیت ادمین وجود ندارد -- حذف، ویرایش، تغییر وضعیت بدون ثبت در audit log - -### B7 — عدم وجود تأیید دومرحله‌ای برای عملیات حساس - -- محاسبه دستی کمیسیون بدون تأیید مضاعف -- حذف گروهی محصولات فقط یک confirm ساده دارد -- تغییر تنظیمات سیستم بدون نیاز به تأیید مجدد رمز - -### B8 — WithdrawalRequests فقط نمایشی است - -- CMS دارای `ApproveWithdrawal`, `RejectWithdrawal`, `ProcessWithdrawal` commands است -- BackOffice صفحه WithdrawalRequests فقط **لیست** نشان می‌دهد -- **هیچ دکمه تأیید/رد/پردازش وجود ندارد** — ادمین نمی‌تواند درخواست‌ها را مدیریت کند -- این یک **شکاف بحرانی عملیاتی** است - -### B9 — Discount Shop Orders وضعیت ارسال بدون اقدام - -- DiscountOrdersMainPage سفارش‌ها را نشان می‌دهد -- دکمه "تغییر وضعیت" وجود دارد اما flow مبهم است -- CMS دارای `UpdateOrderStatus` و `CancelOrderByAdmin` هست -- ❌ هیچ workflow واضحی برای تغییر وضعیت Pending→Processing→Shipped→Delivered وجود ندارد -- ❌ کد رهگیری پستی قابل ثبت نیست - -### B10 — Settings page عملکرد ندارد - -- `UserSettings.razor` دارای toggleهای Dark Mode، زبان، حالت فشرده، PageSize -- **هیچ‌کدام persistent نیستند** — بعد از refresh همه reset می‌شوند -- احتمالاً با `localStorage` ذخیره شود ولی هیچ جای دیگر خوانده نمی‌شود - ---- - -## 🔀 تحلیل تطبیقی CMS ↔ BackOffice - -### Entity‌های CMS بدون صفحه مدیریت در BackOffice - -| CMS Entity | Domain Feature | BackOffice صفحه | وضعیت | -|---|---|---|---| -| **UserWallet** | ۳ نوع موجودی (اصلی/شبکه/تخفیف) | ❌ ندارد | 🔴 بحرانی — ادمین نمی‌تواند موجودی ببیند | -| **UserWalletChangeLog** | تاریخچه تمام تغییرات مالی | ❌ ندارد | 🔴 بحرانی — بدون audit trail مالی | -| **DayaLoanContract** | مدیریت وام دایا (6 وضعیت) | ❌ ندارد | 🟡 مهم — اگر سیستم فعال است | -| **ClubFeature** | فیچرهای باشگاه (تعریف) | ❌ ندارد | 🟡 مهم | -| **UserClubFeature** | فیچرهای فعال شده برای هر کاربر | ❌ ندارد | 🟡 مهم | -| **UserContract** | قراردادهای امضاشده + PDF | ❌ ندارد | 🟡 مهم — قراردادها قابل مشاهده نیست | -| **ClubMembershipHistory** | تاریخچه عضویت | ❌ ندارد | 🟢 | -| **CommissionPayoutHistory** | تاریخچه پرداخت کمیسیون | ❌ ندارد | 🟢 | -| **NetworkMembershipHistory** | تاریخچه تغییرات شبکه | ❌ ندارد | 🟢 | -| **WorkerExecutionLog** | تاریخچه اجرای worker | ❌ ندارد (query وجود دارد) | 🟢 | - -### CMS Commands بدون UI در BackOffice - -| CMS Command | عملکرد | BackOffice UI | وضعیت | -|---|---|---|---| -| `ApproveWithdrawal` | تأیید درخواست برداشت | ❌ دکمه ندارد | 🔴 بحرانی | -| `RejectWithdrawal` | رد درخواست برداشت | ❌ دکمه ندارد | 🔴 بحرانی | -| `ProcessWithdrawal` | پردازش نهایی برداشت | ❌ دکمه ندارد | 🔴 بحرانی | -| `AssignClubFeature` | اختصاص فیچر به کاربر | ❌ صفحه ندارد | 🟡 | -| `MoveInNetwork` | جابه‌جایی در شبکه | ❌ دکمه ندارد | 🟡 | -| `RemoveFromNetwork` | حذف از شبکه | ❌ دکمه ندارد | 🟡 | -| `CancelOrderByAdmin` | لغو سفارش توسط ادمین | ❌/✅ فقط برای UserOrder (نه DiscountOrder) | 🟡 | -| `ProcessManualMembershipPayment` | پردازش پرداخت دستی عضویت | ❓ نامشخص | 🟡 | - -### CMS Queries بدون UI در BackOffice - -| CMS Query | عملکرد | وضعیت | -|---|---|---| -| `GetCommissionPayoutHistory` | تاریخچه پرداخت هر کاربر | ❌ | -| `GetClubMembershipHistory` | تاریخچه عضویت | ❌ | -| `GetNetworkMembershipHistory` | تاریخچه شبکه | ❌ | -| `GetWorkerExecutionLogs` | لاگ‌های worker | ❌ | -| `GetWeekDefinitions` | لیست هفته‌ها | ✅ (در WeekNumberPicker) | -| `GetUserWeeklyBalances` | موجودی هفتگی کاربر | ✅ | -| `GetDiscountSalesReport` | گزارش فروش تخفیفی | ✅ | - -### سه‌گانه کیف پول — خلأ بحرانی - -CMS سه نوع موجودی برای هر کاربر دارد: - -``` -UserWallet { - Balance → موجودی اصلی (شارژ مستقیم + درگاه) - NetworkBalance → موجودی شبکه/طلایی (از کمیسیون — قابل برداشت نقدی) - DiscountBalance → موجودی تخفیف (فقط خرید از فروشگاه تخفیفی) -} -``` - -**BackOffice هیچ نمایی از این سه موجودی ندارد.** ادمین برای: -- بررسی موجودی کاربر → باید DB بزند -- ردیابی تغییرات مالی → هیچ راهی ندارد -- تأیید ManualPayment → نمی‌داند موجودی قبل و بعد چقدر بود -- تأیید درخواست برداشت → نمی‌داند NetworkBalance فعلی کاربر چقدر است - ---- - -## 🏗 تحلیل ساختاری صفحات و ناوبری - -### ۱. صفحات Stub (بدون Backend واقعی) - -صفحاتی که UI دارند ولی **هیچ API واقعی ندارند** و کاربر را گمراه می‌کنند: - -| صفحه | مسیر | مشکل | خطوط کد | تأثیر | -|---|---|---|---|---| -| **Transactions** | `/payment/transactions` | 🔴 **کاملاً خالی** — `LoadServerData` فقط `Array.Empty` برمی‌گرداند. TODO: Connect to API | 180 | کاربر GridEmpty می‌بیند | -| **AlertsMonitoring** | `/system/alerts` | 🔴 **100% داده Mock** — `GenerateMockAlerts()` با `Task.Delay(500)` | 422 | آلارم‌ها واقعی نیست | -| **HealthDashboard** | `/system/health` | 🟡 **نیمه Mock** — سرویس‌ها از API، ولی CPU/RAM/Disk/Network همه **hardcoded** (45.2%, 62.8%...) | 468 | متریک‌ها تقلبی | -| **UserSettings** | `/settings` | 🟡 **Backend جعلی** — تغییر رمز: فقط فیلد را خالی می‌کند + Snackbar. نوتیفیکیشن: فقط localStorage. 2FA: فقط localStorage | 418 | اعتماد کاذب | - -**توصیه:** -- Transactions → **حذف از پروژه** یا مخفی کردن تا API آماده شود -- AlertsMonitoring → **حذف از NavMenu** + نشان دادن badge «در حال توسعه» -- HealthDashboard → حذف بخش Resource Metrics تا زمان اتصال واقعی -- UserSettings → حذف تب‌های Notifications و Security یا نمایش پیام «به‌زودی» - -### ۲. صفحات تکراری / قابل ادغام - -#### 🔴 دو داشبورد موازی و ناسازگار - -| | Index (`/`) | SystemOverview (`/dashboard/overview`) | -|---|---|---| -| **تمرکز** | آمار عمومی (کاربران، محصولات، سفارش‌ها) | آمار شبکه/باشگاه/کمیسیون | -| **Stat Cards** | 7 عدد (MudPaper ساده) | 4+3 عدد (MudCard Outlined) | -| **Design Pattern** | `MudPaper Class="pa-4"` | `MudCard Outlined` | -| **Loading** | ❌ ندارد | ✅ MudProgressCircular | -| **جدول** | آخرین 5 سفارش (MudTable) | ❌ ندارد | -| **Quick Actions** | ❌ ندارد | ✅ 6 دکمه Shortcut | -| **محاسبه آمار** | 🔴 نادرست (PageSize=10) | ✅ صحیح (از metadata) | - -**مشکل:** کاربر دو «داشبورد» با design متفاوت می‌بیند. هیچ‌کدام کامل نیست. -**توصیه:** ادغام در یک Dashboard واحد — Stat Cards بالا + Quick Actions + آخرین سفارش‌ها + خلاصه کمیسیون. - -#### 🔴 DiscountOrders + SalesReports — ۶۰% تکرار - -| عنصر | DiscountOrdersMainPage | SalesReports | -|---|---|---| -| `GetOrdersAsync` | ✅ | ✅ (دوباره!) | -| جدول سفارش‌ها | ✅ 8 ستون | ✅ 6 ستون (همان‌ها) | -| `GetStatusColor()` | ✅ | ✅ **copy-paste یکسان** | -| `GetStatusText()` | ✅ | ✅ **copy-paste یکسان** | -| فیلتر تاریخ | ❌ | ✅ | -| چارت‌ها | ❌ | ✅ | -| Export | ❌ | ✅ CSV/PDF | -| تغییر وضعیت | ✅ dialog | ❌ | - -**توصیه:** ادغام در یک صفحه با **۲ تب**: «مدیریت سفارشات» + «گزارشات و چارت‌ها» - -#### 🟡 Club Statistics — کارکرد حداقلی - -- 4 Stat Card + 3 Chart + یک جدول «اعضای اخیر» که **همیشه خالی** است (list initialize نمی‌شود) -- تمام linkهایش به ClubMembers هدایت می‌کنند -- **توصیه:** تبدیل به header/summary در بالای ClubMembers یا تب «آمار» در همان صفحه - -#### 🟡 Commission: Payouts vs WithdrawalRequests — Lifecycle یکسان - -| | UserPayouts | WithdrawalRequests | -|---|---|---| -| **داده** | Payout per user/week | Withdrawal requests | -| **Status** | 6 state (0-5) | 6 state (0-5) — **همان enum** | -| **Approve** | ✅ `ApproveCommissionPayout` | ✅ `ApproveWithdrawal` | -| **Reject** | ✅ `RejectCommissionPayout` | ✅ `RejectWithdrawal` | -| **Process** | ❌ | ✅ `ProcessWithdrawal` | -| **Bank Info** | ❌ | ✅ IBAN/BankRef/TrackingCode | - -هر دو یک lifecycle را نشان می‌دهند (Payout → Withdrawal Request → Process). کاربر برداشت را هم در Payouts و هم در WithdrawalRequests می‌بیند. -**توصیه:** ادغام در یک صفحه با **۲ تب**: «پرداخت‌ها» + «درخواست‌های برداشت» یا حداقل cross-link. - -#### 🟡 Blog + Tag — الگوی یکسان - -| | BlogCategories | TagManagement | -|---|---|---| -| **Columns** | ID, Title, Slug, PostCount, Status, Sort | ID, Name, Title, IsActive, Sort | -| **Actions** | Create/Edit/Delete via Dialog | Create/Edit/Delete via Dialog | -| **Pattern** | BasePageComponent + ServerData | BasePageComponent + ServerData | -| **Code-behind** | ~102 lines | ~114 lines | - -**ساختار کد 95% یکسان.** هر دو CRUD ساده‌اند. -**توصیه:** تبدیل به تب‌هایی در صفحه Blog یا یک صفحه «مدیریت محتوا» مشترک. - -#### 🟡 سه صفحه System — قابل ادغام - -Alerts (Mock) + Health (نیمه‌Mock) + WorkerControl (نیمه‌فعال) + Configuration (فعال) -**توصیه:** ادغام در یک `/system` با ۴ تب. فعلاً فقط Configuration و WorkerControl کاربردی‌اند. - -### ۳. مشکلات ساختاری NavMenu - -#### لینک‌های مرده در منو - -| لینک در NavMenu | مقصد | مشکل | -|---|---|---| -| `ترتیب دسته‌بندی‌ها` | `/products/categories-dragdrop` | 🔴 **صفحه‌ای با این route وجود ندارد!** — احتمالاً باید `/ProductCategoriesPage/` باشد | - -#### صفحات بدون لینک در منو - -| صفحه | مسیر | وضعیت | -|---|---|---| -| **Transactions** | `/payment/transactions` | 🔴 لینکی ندارد — در NavMenu فقط ManualPayments هست | -| **WorkerControl** | `/system/worker-control` | 🔴 لینکی ندارد — در بخش سیستم نیست | -| **InventoryAddStock** | `RouteConstance` تعریف شده | 🟡 route موجود ولی صفحه‌ای استفاده نمی‌کند | - -#### عدم تطابق گروه‌بندی - -| مشکل | جزئیات | -|---|---| -| **تکرار عنوان «فروشگاه تخفیفی»** | هم به‌عنوان `MudText` section header و هم `MudNavGroup` — دو بار عنوان نمایش داده می‌شود | -| **«پیام‌های عمومی» زیر فروشگاه تخفیفی** | ارتباطی با فروشگاه ندارد — باید در «مدیریت محتوا» باشد | -| **«پرداخت‌ها و فعالسازی‌ها» — فقط یک آیتم** | گروه NavGroup با یک زیرآیتم، بی‌معنی — باید Flat link باشد یا Transactions هم اضافه شود | -| **«مدیریت پکیج» جدای از محصولات** | پکیج و محصولات مرتبط‌اند ولی پکیج flat link و محصولات NavGroup | -| **سفارش‌ها flat link ولی DiscountOrders در NavGroup** | دو نوع سفارش با ساختار منو متفاوت | - -#### پیشنهاد ساختار منوی بازنگری‌شده - -``` -📊 داشبورد (ادغام Index + SystemOverview) - -💰 کمیسیون و شبکه - ├─ داشبورد کمیسیون - ├─ گزارش‌های هفتگی - ├─ پرداخت و برداشت (ادغام Payouts + WithdrawalRequests) - ├─ گزارش برداشت‌ها - ├─ درخت شبکه - ├─ موجودی‌های شبکه - └─ آمار شبکه - -🎫 باشگاه مشتریان - ├─ اعضا و آمار (ادغام ClubMembers + Statistics) - └─ مدیریت فیچرها (جدید — از CMS) - -🛒 فروشگاه - ├─ 🏷 محصولات - │ ├─ لیست محصولات - │ ├─ ویرایش دسته‌جمعی - │ ├─ دسته‌بندی‌ها - │ └─ تگ‌ها (از مدیریت محتوا به اینجا) - ├─ 📦 پکیج‌ها - ├─ 📋 سفارش‌ها (همه) (UserOrders + DiscountOrders — tab) - └─ 🏪 فروشگاه تخفیفی - ├─ محصولات تخفیفی - ├─ دسته‌بندی‌ها - └─ گزارش فروش (ادغام با سفارشات) - -📦 انبارداری - ├─ موجودی انبار - ├─ محصولات کم‌موجود - ├─ مدیریت انبارها - └─ تاریخچه تغییرات - -👥 مدیریت - ├─ کاربران - ├─ نقش‌ها - ├─ 💳 کیف پول کاربران (جدید — از CMS) - ├─ 💰 پرداخت‌های دستی - └─ 📄 قراردادها (جدید — از CMS) - -📝 مدیریت محتوا - ├─ بلاگ (پست‌ها + دسته‌بندی‌ها) (ادغام در یک صفحه) - ├─ صفحات سایت - └─ پیام‌های عمومی (از فروشگاه تخفیفی به اینجا) - -⚙️ سیستم - ├─ تنظیمات سیستم - ├─ مدیریت Worker - ├─ نسخه اپلیکیشن‌ها (از Settings به اینجا) - └─ سلامت سیستم - -👤 تنظیمات حساب -🚪 خروج -``` - -### ۴. ناوبری بین صفحات — لینک‌های Cross-Reference ناقص - -| از | به | وضعیت | -|---|---|---| -| User → UserOrders | `/UserOrderPage/{userId}` | ✅ | -| User → UserAddress | `/UserAddressPage/{userId}` | ✅ | -| Products → ProductCategories | `/ProductCategoriesPage/{productId}` | ✅ | -| Products → BulkEdit | `/ProductsBulkEditPage/` | ✅ | -| Inventory → Movements | `/InventoryMovementsPage/?itemId=` | ✅ | -| **UserOrder → User** | ❌ | 🔴 **نام کاربر کلیک‌نخور** — نمی‌توان از سفارش به پروفایل کاربر رفت | -| **UserOrder → Product** | ❌ | 🔴 **محصول سفارش لینک ندارد** | -| **Inventory → Products** | ❌ | 🟡 نام محصول نشان داده می‌شود ولی لینک ندارد | -| **Products → Inventory** | ❌ | 🟡 ستون «موجودی» وجود دارد ولی drill-down ندارد | -| **DiscountShop → Products** | ❌ | 🔴 دو سیستم محصول کاملاً جدا — cross-link ندارند | -| **Commission → User** | ❌ | 🟡 نام کاربر در Payouts نشان داده می‌شود ولی به پروفایل لینک ندارد | -| **ManualPayment → User** | ❌ | 🟡 UserName بدون لینک | -| **هیچ صفحه‌ای → Wallet** | ❌ | 🔴 صفحه کیف پول اصلاً وجود ندارد | - -### ۵. الگوهای کد تکراری (Code Duplication) - -| الگوی تکراری | تکرار | فایل‌ها | -|---|---|---| -| `GetStatusColor()` / `GetStatusText()` برای CommissionPayoutStatus | **4×** | Payouts, WithdrawalRequests, WeeklyReports, PayoutDetailsDialog | -| `GetStatusColor()` / `GetStatusText()` برای DiscountOrder | **2×** | DiscountOrdersMainPage, SalesReports | -| الگوی CRUD ساده (Grid + Create/Edit Dialog) | **6×** | BlogCategory, Tag, Package, Role, DiscountCategory, ClubFeature(!) | -| فیلتر BasePageComponent با `SubmitFilter()` | **9×** | User, Products, Package, Category, UserOrder, Transactions, UserAddress, UserRole, Role | -| `UserAutoComplete` component usage | **5×** | UserOrder, Payouts, WithdrawalRequests, WithdrawalReports, BalancesReport | -| Mock data pattern `GenerateMock*()` | **2×** | AlertsMonitoring, HealthDashboard | - -### ۶. تحلیل کاربردی — صفحات «ارزش‌آفرین» vs «کم‌کاربرد» - -| صفحه | فرکانس استفاده تخمینی | ارزش | یادداشت | -|---|---|---|---| -| Dashboard | روزانه | 🔴 ناقص | باید بهترین صفحه باشد — فعلاً ضعیف‌ترین | -| UserOrders | روزانه | ✅ بالا | صفحه اصلی عملیات روزانه | -| Products | هفتگی | ✅ بالا | مدیریت کاتالوگ | -| Commission Payouts | هفتگی | ✅ بالا | مدیریت مالی | -| WithdrawalRequests | روزانه | 🔴 ناقص | بدون approve/reject = عملاً بی‌فایده | -| Inventory | روزانه | ✅ بالا | مدیریت موجودی | -| ManualPayments | روزانه | 🟡 ناقص | بدون quick-approve | -| Users | هفتگی | ✅ خوب | CRUD ساده ولی کافی | -| Club Members | هفتگی | 🟡 متوسط | فاقد feature management | -| Network Tree | هفتگی | ✅ خوب | ویژوالیزیشن خوب | -| Blog | ماهانه | ✅ خوب | CRUD کامل | -| DiscountShop | هفتگی | 🟡 ناقص | فیلتر خراب، client-side paging | -| Alerts | — | 🔴 بی‌کاربرد | 100% mock | -| Transactions | — | 🔴 بی‌کاربرد | 100% خالی | -| Health | ماهانه | 🟡 ناقص | فقط service status واقعی | -| Settings | یک‌بار | 🟡 ناقص | فقط theme واقعی | - ---- - -## 📊 جدول یافته‌ها به تفکیک صفحه - -| صفحه | الگوی لایوت | Loading | Empty State | Pager فارسی | تاریخ شمسی | Export | مشکلات خاص | -|---|---|---|---|---|---|---|---| -| **Index** | C (بدون Container) | ❌ | ❌ | — | ❌ میلادی | ❌ | آمار نادرست از ۱۰ رکورد | -| **SystemOverview** | B | ✅ | ❌ | — | ❌ | ❌ | Widget غیرفعال | -| **User** | A (BasePageComponent) | ❌ | ❌ | ✅ | — | ❌ | — | -| **UserOrder** | A | ❌ | ❌ | ✅ | ✅ جلالی | ❌ | آمار کامنت‌شده | -| **Package** | A | ❌ | ❌ | ✅ | — | ❌ | — | -| **Products** | A | ❌ | ❌ | ❌ | — | ✅ | cursor:pointer زائد | -| **Category** | A (سفارشی + درخت) | ❌ | ❌ | — | — | ❌ | — | -| **Blog** | B | ❌ | ❌ | ✅ | ❌ میلادی | ❌ | — | -| **Tag** | B | ❌ | ❌ | ✅ | — | ❌ | — | -| **Content** | B | ✅ | ❌ | — | ❌ میلادی | ❌ | — | -| **PublicMessages** | B | ✅ | ❌ | — | — | ❌ | — | -| **Commission Dashboard** | B | ✅ | ❌ | — | ✅ | ❌ | — | -| **WeeklyReports** | B | ✅ | ✅ | — | ❌ میلادی | ❌ | — | -| **WithdrawalRequests** | B | ❌ | ❌ | — | — | ❌ | — | -| **Network Tree** | B | ✅ | ✅ | — | — | ✅ PNG | — | -| **Club Members** | B | ❌ | ❌ | — | ❌ میلادی | ❌ | — | -| **Inventory** | B | ❌ | ❌ | — | — | ❌ | — | -| **DiscountShop** | B | ✅ | ❌ | — | — | ❌ | TODO: دسته‌بندی | -| **Settings** | B | ✅ | ❌ | — | — | ❌ | — | -| **Configuration** | B | ❌ | — | — | — | ❌ | — | -| **HealthDashboard** | B | ❌ | ❌ | — | — | ❌ | — | -| **WorkerControl** | B | ❌ | — | — | ✅ | ❌ | — | -| **Login** | EmptyLayout | ❌ | — | — | — | — | عرض ثابت 35% | -| **VerifyCode** | EmptyLayout | ❌ | — | — | — | — | ارتفاع ثابت | - ---- - -## 🛠 برنامه اجرایی (Action Plan) — با وضعیت پیاده‌سازی - -### فاز ۱: زیرساخت دیزاین سیستم (Critical) — ✅ کامل - -| # | کار | فایل(ها) | اولویت | وضعیت | -|---|---|---|---|---| -| 1.1 | یکسان‌سازی تم رنگی با FrontOffice + اضافه کردن PaletteDark | `CustomMudTheme.cs` | 🔴 | ✅ تم #6366f1 Indigo + PaletteDark کامل | -| 1.2 | حذف تمام رنگ‌های هاردکد از CSS و inline styles | `app.css`, `NavMenu.razor.css`, `MainLayout.razor`, `admin-org-chart.css` | 🔴 | ✅ حذف شد | -| 1.3 | اصلاح عنوان اپ: "فرصت" → "کارا بازار سلامت" | `MainLayout.razor` | 🔴 | ✅ اصلاح شد | -| 1.4 | Dark Mode Toggle | `MainLayout.razor`, `CustomMudTheme.cs` | 🟡 | ✅ toggle در AppBar + PaletteDark | -| 1.5 | ساخت کامپوننت `StatCard` مشترک | `Common/BaseComponents/` | 🟡 | ✅ غیرضروری شد (داشبورد ادغام شد) | - -### فاز ۲: بازطراحی لایوت صفحات — ✅ کامل - -| # | کار | فایل(ها) | اولویت | وضعیت | -|---|---|---|---|---| -| 2.1 | بازنویسی `BasePageComponent` — responsive + فیلتر بالای جدول | `BasePageComponent.razor` | 🔴 | ✅ فیلتر collapsible بالای جدول، responsive | -| 2.2 | یکسان‌سازی MaxWidth همه صفحات | تمام صفحات | 🟡 | ✅ MainLayout MudContainer wrapper | -| 2.3 | یکسان‌سازی DataGrid Height | تمام صفحات | 🟡 | ✅ همه `calc(100vh - 240px)` | -| 2.4 | یکسان‌سازی PageSize و Pager فارسی | تمام صفحات | 🟡 | ✅ همه 20/50/100 + متن فارسی | -| 2.5 | اضافه کردن Breadcrumb به MainLayout | `MainLayout.razor` | 🟡 | ✅ AppBreadcrumb.razor ساخته شد | -| 2.6 | بازطراحی صفحات Login + VerifyCode | `LoginPage.razor`, `VerifyCodePage.razor` | 🔴 | ✅ طراحی جدید responsive + برندینگ | - -### فاز ۲.۵: پاکسازی ساختاری — ✅ کامل (7/7) - -| # | کار | اولویت | وضعیت | -|---|---|---|---| -| 2.5.1 | حذف/مخفی کردن Transactions page (stub خالی) | 🔴 | ✅ حذف از NavMenu | -| 2.5.2 | حذف Alerts از NavMenu (mock) | 🔴 | ✅ حذف شد | -| 2.5.3 | فیکس لینک مرده `categories-dragdrop` در NavMenu | 🔴 | ✅ حذف شد | -| 2.5.4 | اضافه کردن WorkerControl به NavMenu بخش سیستم | 🟡 | ✅ در SystemHub تب شد | -| 2.5.5 | حذف تب‌های Notifications/Security از UserSettings (fake backend) | 🟡 | ✅ تب‌ها به «به‌زودی» placeholder تبدیل شدند | -| 2.5.6 | حذف hardcoded resource metrics از HealthDashboard | 🟡 | ✅ متریک‌ها با placeholder «Prometheus/Grafana» جایگزین شدند | -| 2.5.7 | انتقال «پیام‌های عمومی» از بخش فروشگاه تخفیفی به مدیریت محتوا | 🟢 | ✅ در NavMenu جدید منتقل شد | - -### فاز ۳: UX بهبودها — ✅ کامل (6/6) - -| # | کار | فایل(ها) | اولویت | وضعیت | -|---|---|---|---|---| -| 3.1 | Loading State یکپارچه | تمام صفحات | 🟡 | ✅ صفحات جدید دارند | -| 3.2 | Empty State یکپارچه (NoRecordsContent) | تمام صفحات | 🟡 | ✅ ۳۳ DataGrid | -| 3.3 | Delete Confirmation با نام آیتم | تمام صفحات | 🟢 | ✅ ۱۱ صفحه اصلاح شد | -| 3.4 | User Menu در AppBar (پروفایل + خروج) | `MainLayout.razor` | 🟡 | ✅ MudMenu با نام + خروج | -| 3.5 | Dark Mode Toggle | `MainLayout.razor`, `CustomMudTheme.cs` | 🟢 | ✅ toggle + PaletteDark | -| 3.6 | تاریخ شمسی یکپارچه در تمام صفحات | تمام صفحات | 🟡 | ✅ **۱۹+ فایل** — `.MiladiToJalali()` / `.MiladiToJalaliWithTime()` از DateTimeConverterCL | - -### فاز ۳.۵: ادغام صفحات — ✅ کامل (5/6) - -| # | کار | صفحات مبدأ | نتیجه | اولویت | وضعیت | -|---|---|---|---|---|---| -| 3.5.1 | ادغام ۲ داشبورد | Index + SystemOverview | یک Dashboard واحد | 🔴 | ✅ Index.razor merged | -| 3.5.2 | ادغام DiscountOrders + SalesReports | ۲ صفحه → ۱ صفحه + ۲ تب | DiscountShopHub | 🟡 | ✅ | -| 3.5.3 | ادغام Club Members + Statistics | ۲ صفحه → ۱ صفحه + header | ClubHub | 🟡 | ✅ | -| 3.5.4 | ادغام Blog + BlogCategories + Tags | ۳ صفحه → ۱ صفحه + ۳ تب | BlogHub | 🟢 | ✅ | -| 3.5.5 | ادغام System pages | Config+Worker+Health → ۱ + ۳ تب | SystemHub | 🟢 | ✅ | -| 3.5.6 | Extract shared status helpers | حذف ۴ تکرار GetStatusColor/Text | Helper مشترک | 🟢 | ⏭ Skip — هر context مقادیر متفاوت دارد (domain-specific) | - -### فاز ۴: فیکس‌های بیزینسی — ✅ کامل (10/11) - -| # | کار | فایل(ها) | اولویت | وضعیت | -|---|---|---|---|---| -| 4.1 | اصلاح محاسبه آمار Dashboard (از metadata نه page data) | `Index.razor` | 🔴 | ✅ داشبورد merged با API درست | -| 4.2 | اضافه کردن دکمه‌های تأیید/رد به WithdrawalRequests | `WithdrawalRequests.razor` | 🔴 | ✅ + ViewDetailsDialog + RejectReasonDialog | -| 4.3 | اضافه کردن دکمه‌های تأیید/رد به ManualPayments | `ManualPaymentsMainPage.razor` | 🔴 | ✅ Approve/Reject با confirmation | -| 4.4 | اضافه کردن `Cancelled=5` به فیلتر DeliveryStatus | `UserOrderMainPage.razor` | 🔴 | ✅ MudSelectItem اضافه شد | -| 4.5 | فعال‌سازی DiscountShop Widget | `SystemOverview.razor` | 🟡 | ⏭ SystemOverview حذف شد (ادغام) | -| 4.6 | آنکامنت آمار UserOrder | `UserOrderMainPage.razor` | 🟡 | ✅ آمار + نمودار فعال شد | -| 4.7 | پیاده‌سازی فیلتر دسته‌بندی DiscountShop | `DiscountProductsMainPage.razor` | 🟡 | ✅ دسته‌بندی‌ها از IDiscountCategoryService بارگذاری می‌شوند | -| 4.8 | تبدیل DiscountProducts از Items به ServerData | `DiscountProductsMainPage.razor` | 🟡 | ✅ ServerData + pagination سمت سرور | -| 4.9 | Settings page — persist با localStorage | `UserSettings.razor` | 🟡 | ✅ تب General با localStorage کار می‌کند (از قبل) | -| 4.10 | حذف `cursor:pointer` زائد از همه دکمه‌ها | تمام صفحات (17 فایل) | 🟢 | ✅ حذف شد از تمام فایل‌ها | -| 4.11 | حذف `Console.WriteLine` از همه فایل‌ها | 11 فایل | 🟢 | ✅ حذف شد از تمام فایل‌ها | - -### فاز ۴.۵: Cross-Navigation — 🟡 بخشی انجام شد (3/5) - -| # | کار | اولویت | وضعیت | -|---|---|---|---| -| 4.5.1 | لینک نام کاربر در UserOrders → پروفایل کاربر | 🟡 | ✅ MudLink به `/network/user-info/{UserId}` | -| 4.5.2 | لینک نام کاربر در Commission Payouts/Withdrawals → پروفایل کاربر | 🟡 | ✅ MudLink به `/network/user-info/{UserId}` | -| 4.5.3 | لینک نام محصول در Inventory → صفحه محصول | 🟢 | ⏭ Skip — صفحه جزئیات محصول وجود ندارد | -| 4.5.4 | لینک موجودی در Products → صفحه انبار | 🟢 | ⏭ Skip — صفحه جزئیات محصول وجود ندارد | -| 4.5.5 | بازنگری کلی NavMenu طبق ساختار پیشنهادی | 🟡 | ✅ انجام شد در فاز ۲.۵ | - -### فاز ۵: صفحات مفقود (CMS-Derived) — ✅ اکثراً کامل (7/8) - -| # | کار | CMS Entity/Command | اولویت | وضعیت | -|---|---|---|---|---| -| 5.1 | **صفحه مدیریت کیف پول کاربران** | `UserWallet`, `UserWalletChangeLog` | 🔴 | ✅ WalletManagementPage.razor (۲ تب) | -| 5.2 | **Workflow تأیید درخواست برداشت** | `ApproveWithdrawal`, `RejectWithdrawal` | 🔴 | ✅ در فاز ۴.۲ انجام شد | -| 5.3 | **صفحه مدیریت وام دایا** | `DayaLoanContract` | 🟡 | ⏸ **نیاز به proto بک‌اند** — فعلاً امکان‌پذیر نیست | -| 5.4 | **مدیریت فیچرهای باشگاه** | `ClubFeature`, `UserClubFeature` | 🟡 | ✅ ClubFeaturesPage.razor (۲ تب) | -| 5.5 | **نمایش قراردادهای کاربران** | `UserContract` | 🟡 | ✅ UserContractPage.razor + ContractDetailsDialog | -| 5.6 | **لاگ اجرای Worker‌ها** | `GetWorkerExecutionLogs` | 🟢 | ✅ تب WorkerControl در SystemHub قبلاً شامل لاگ‌هاست | -| 5.7 | **تاریخچه عضویت باشگاه** | `GetClubMembershipHistory` | 🟢 | ✅ MemberDetailsDialog — تب تاریخچه با فیلدهای Created, Action, Reason, PerformedBy | -| 5.8 | **تاریخچه تغییرات شبکه** | `GetNetworkMembershipHistory` | 🟢 | ✅ UserNetworkInfo — تب تاریخچه با فیلدهای OldParentId, NewParentId, OldNetworkLeg, NewNetworkLeg | - -### فاز ۶: فیچرهای جدید (اختیاری) — ✅ اکثراً تکمیل - -| # | کار | اولویت | وضعیت | -|---|---|---|---| -| 6.1 | سیستم نوتیفیکیشن (Bell icon + Dropdown) | 🟢 | ✅ Bell icon + MudMenu placeholder در MainLayout — آماده اتصال به بک‌اند | -| 6.2 | Global Search در AppBar | 🟢 | ✅ GlobalSearch.razor — جستجوی صفحات + کاربران (gRPC) — Autocomplete | -| 6.3 | Export Excel در تمام صفحات | 🟢 | ✅ **۱۰ صفحه** — Products, ClubMembers, WithdrawalRequests, WeeklyReports, UserOrders, MovementsPage, Users, DiscountOrders, ManualPayments, Inventory | -| 6.4 | Audit Trail / لاگ فعالیت ادمین | 🟢 | ⏸ نیاز به بک‌اند — endpoint لاگ فعالیت ادمین موجود نیست | -| 6.5 | نمایش counter پرداخت‌های Pending در NavMenu | 🟢 | ✅ MudBadge روی «درخواست‌های برداشت» — real-time از gRPC | - ---- - -## 🔑 اولویت‌بندی نهایی — وضعیت اجرا - -### ✅ انجام شده — فوری (فاز ۱ + ۲): -1. ~~تم رنگی + حذف هاردکدها + PaletteDark~~ ✅ -2. ~~اصلاح عنوان اپ~~ ✅ -3. ~~بازنویسی BasePageComponent (responsive)~~ ✅ -4. ~~بازطراحی Login/VerifyCode~~ ✅ -5. ~~یکسان‌سازی الگوهای صفحات~~ ✅ -6. ~~اصلاح محاسبه آمار Dashboard~~ ✅ - -### ✅ انجام شده — عملیات بحرانی (فاز ۴ + ۵): -7. ~~⚡ دکمه‌های تأیید/رد درخواست برداشت~~ ✅ + ViewDetails + RejectReason dialogs -8. ~~⚡ دکمه‌های تأیید/رد پرداخت دستی~~ ✅ -9. ~~⚡ صفحه کیف پول کاربران (۳ موجودی + تاریخچه)~~ ✅ WalletManagementPage -10. ~~اضافه کردن Cancelled به فیلتر سفارش‌ها~~ ✅ - -### ✅ انجام شده — UX یکپارچه (فاز ۳): -11. ~~Loading/Empty State یکپارچه~~ ✅ NoRecordsContent ۳۳ گرید -12. ~~User Menu در AppBar~~ ✅ -13. ~~Breadcrumb~~ ✅ AppBreadcrumb.razor -14. ~~ادغام صفحات~~ ✅ ۵ hub page ساخته شد - -### ✅ انجام شده — صفحات مفقود (فاز ۵): -15. ~~مدیریت فیچرهای باشگاه~~ ✅ ClubFeaturesPage.razor -16. ~~نمایش قراردادهای کاربران~~ ✅ UserContractPage.razor + ContractDetailsDialog - -### ❌ باقی‌مانده — اولویت‌بندی شده: - -#### مهم 🟡 (۱ مورد): -1. DayaLoanContract صفحه (5.3) — **نیاز به بک‌اند (blocked)** - -#### جزئی 🟢 (۰ مورد — همه انجام شدند به‌جز Audit Trail): -~~2. سیستم نوتیفیکیشن (6.1)~~ ✅ -~~3. Global Search (6.2)~~ ✅ -~~4. Audit Trail (6.4)~~ ⏸ نیاز به بک‌اند - ---- - -## 📊 خلاصه کمّی مشکلات — بروزرسانی - -| شدت | تعداد اولیه | انجام‌شده | باقی‌مانده | -|---|---|---|---| -| 🔴 بحرانی | **16** | **16** ✅ | **0** | -| 🟡 مهم | **24** | **23** | **1** (DayaLoan — blocked) | -| 🟢 جزئی | **18** | **18** ✅ | **0** | -| **مجموع** | **58** | **57 (≈98%)** | **1 (≈2%)** | - -> **همه ۱۶ مورد بحرانی 🔴 انجام شده‌اند.** -> **همه ۱۸ مورد جزئی 🟢 انجام شده‌اند.** -> **فازهای ۱ تا ۶ تکمیل شدند** (به‌جز DayaLoan و Audit Trail که نیاز به بک‌اند دارند). -> تنها مورد باقی‌مانده: DayaLoanContract (5.3) — blocked on backend proto. - -### خلاصه ادغام‌ها — نتیجه - -| عمل | انجام شد؟ | نتیجه | -|---|---|---| -| ۲ داشبورد → ۱ | ✅ | Index.razor (unified dashboard) | -| DiscountOrders + Sales → tabs | ✅ | DiscountShopHub.razor | -| Club Members + Stats → tabs | ✅ | ClubHub.razor | -| Blog + BlogCat + Tag → tabs | ✅ | BlogHub.razor | -| System (3 pages) → tabs | ✅ | SystemHub.razor | -| حذف Transactions (stub) | ✅ | از NavMenu حذف شد | -| **صرفه‌جویی** | | **-9 صفحه مستقل** | - -### فایل‌های جدید ساخته‌شده - -| فایل | عملکرد | -|---|---| -| `Shared/AppBreadcrumb.razor` | Breadcrumb خودکار با عنوان فارسی | -| `Pages/DiscountShop/DiscountShopHub.razor` | Hub سفارشات + گزارش فروش | -| `Pages/Club/ClubHub.razor` | Hub اعضا + آمار باشگاه | -| `Pages/Club/ClubFeaturesPage.razor` | فیچرهای باشگاه + فیچرهای کاربر | -| `Pages/Blog/BlogHub.razor` | Hub پست + دسته‌بندی + تگ | -| `Pages/SystemManagement/SystemHub.razor` | Hub تنظیمات + Worker + سلامت | -| `Pages/Wallet/WalletManagementPage.razor` | کیف‌پول + تاریخچه تغییرات | -| `Pages/Contract/UserContractPage.razor` | لیست قراردادهای کاربران | -| `Pages/Contract/ContractDetailsDialog.razor` | جزئیات قرارداد | -| `Pages/Commission/Components/WithdrawalDetailsDialog.razor` | جزئیات درخواست برداشت | -| `Pages/Commission/Components/RejectReasonDialog.razor` | ورود دلیل رد درخواست | -| `Shared/GlobalSearch.razor` | جستجوی جهانی (صفحات + کاربران) در AppBar | - ---- - -*این داکیومنت نسخه ۷.۰ است و شامل وضعیت پیاده‌سازی تمام فازها می‌شود.* -*تاریخ بروزرسانی: تیر ۱۴۰۴ (July 2025)* -*وضعیت: ۵۷ از ۵۸ مورد انجام شده (≈98%) — تمام موارد بحرانی و جزئی تکمیل* -*مبنای اجرایی: فاز‌های ۱ تا ۶ + فازهای ۲.۵/۳.۵/۴.۵ به‌ترتیب اولویت* +See [totalDoc/INDEX.md](../../totalDoc/INDEX.md) for all documentation. diff --git a/docs/BACKOFFICE-CHANGELOG.md b/docs/BACKOFFICE-CHANGELOG.md index 7109d3d..18c6348 100644 --- a/docs/BACKOFFICE-CHANGELOG.md +++ b/docs/BACKOFFICE-CHANGELOG.md @@ -1,850 +1,3 @@ -# 📝 BackOffice — Changelog +# Docs moved to totalDoc -**آخرین بروزرسانی:** اسفند ۱۴۰۴ (February 18, 2026) - ---- - -## 🏷 فاز ۱۷ — بهبود سیستم موجودی + اتوکامپلیت تخفیفی (اسفند ۱۴۰۴) - -> **هدف:** UX هوشمند ورود کالا با autocomplete اختصاصی برای هر نوع فروشگاه - -### ۱۷.۱ — کامپوننت DiscountProductsAutoComplete ✅ - -- **فایل‌ها:** `Pages/AutoComplete/DiscountProductsAutoComplete.razor(.cs)` -- **الگو:** مشابه `ProductsAutoComplete` موجود -- **gRPC Client:** `DiscountProductContract.DiscountProductContractClient` -- **دِبانس:** ۷۰۰ms، حداکثر ۹ نتیجه -- **نکته:** `SearchQuery` از نوع `string` (نه `StringValue`) - -### ۱۷.۲ — UX هوشمند AddStockDialog ✅ - -- **فایل:** `Pages/Inventory/Components/AddStockDialog.razor` -- **تغییر:** فیلد عددی خام شناسه محصول → autocomplete هوشمند -- **رفتار:** - - انتخاب «فروشگاه عادی» → نمایش `ProductsAutoComplete` - - انتخاب «فروشگاه اعتباری» → نمایش `DiscountProductsAutoComplete` - - ولیدیشن قبل از submit - -### ۱۷.۳ — Merge به production ✅ - -- **برنچ:** `kub-stage` → `production` -- **ریموت:** `kub-stage` (Gitea) - ---- - -## 🏷 فاز ۱۶ — ساده‌سازی صفحات سایت + ادیتورهای Shopify-style (اسفند ۱۴۰۴) - -> **هدف:** مدیریت typed صفحات سایت با فرم‌های اختصاصی - -### ۱۶.۱ — صفحه مدیریت PageSettings ✅ - -- **فایل‌ها:** `Pages/Content/PageSettingsManagementPage.razor(.cs)` -- **قابلیت‌ها:** لیست ۴ صفحه ثابت (landing/about/contact/licenses)، ویرایش تنظیمات، مدیریت تصاویر - -### ۱۶.۲ — ادیتورهای اختصاصی Shopify-style ✅ - -| فایل | صفحه | -|------|------| -| `AboutSettingsEditor.razor` | درباره ما: ارزش‌ها + اعضای تیم | -| `ContactSettingsEditor.razor` | تماس: آدرس/تلفن/ایمیل/شبکه‌های اجتماعی | -| `LandingSettingsEditor.razor` | لندینگ: Hero + Steps + Features + Stats + FAQ + Testimonials | -| `LicensesSettingsEditor.razor` | مجوزها: JSON array | - -### ۱۶.۳ — سرویس gRPC و دیالوگ‌ها ✅ - -- `ISitePageSettingsService` + `SitePageSettingsService` -- `PageSettingsEditDialog` + `PageImagesDialog` + `PageImageEditDialog` -- `PageSettingsModels.cs` — مدل‌های typed برای JSON - -### ۱۶.۴ — Proto v0.0.180 ✅ - -- **تغییر:** `Foursat.CMSMicroservice.Protobuf` → `0.0.180` - ---- - -## 🏷 فاز ۱۵ — Production Deploy + فیکس CI/CD Cross-Deploy (اسفند ۱۴۰۴) - -> **هدف:** دیپلوی به سرور Production و رفع باگ cross-deploy - -### ۱۵.۱ — Merge به برنچ production ✅ - -- **کامیت:** `4454b8d` — merge `kub-stage` → `production` -- **ریموت:** `kub-stage` (Gitea) - -### ۱۵.۲ — فیکس باگ Cross-Deploy ✅ - -- **مشکل:** Gitea Act Runner همه workflowهای `.gitea/workflows/` را اجرا می‌کرد — بدون توجه به `branches:` filter -- **عارضه:** push به `production` باعث دیپلوی همزمان به staging و production می‌شد -- **رفع:** حذف فایل‌های workflow staging از برنچ production -- **فایل حذف شده:** `.gitea/workflows/deploy.yml` (staging) از برنچ production - -### ۱۵.۳ — بروزرسانی Proto به v0.0.179 ✅ - -- **تغییر:** `Foursat.CMSMicroservice.Protobuf` → `0.0.179` -- **فایل:** `BackOffice.csproj` - -### ۱۵.۴ — فیکس K8S_SERVER در prod-deploy.yml ✅ - -- **مشکل:** `K8S_SERVER` هنوز `194.5.195.53` (staging) بود -- **رفع:** تغییر به `45.149.79.127` (production) -- **فیکس اضافی:** `kubectl rollout restart` → `kubectl set image` (تا ایمیج SHA-tagged واقعاً set بشه) - -### ۱۵.۵ — ساخت appsettings.Production.json ✅ - -- **مشکل:** فایل `appsettings.Production.json` وجود نداشت → `GwUrl` fallback به `localhost` -- **رفع:** ساخت `wwwroot/appsettings.Production.json` با `GwUrl=https://cms.kbs1.ir` - -### ۱۵.۶ — فیکس nginx image path در Dockerfile (production branch) ✅ - -- **مشکل:** Dockerfile روی برنچ production از `library/nginx:alpine` استفاده می‌کرد — وجود نداشت -- **ارور:** `manifest for 194.5.195.53:32082/library/nginx:alpine not found` -- **رفع:** تغییر به `194.5.195.53:32082/nginx:alpine` -- **کامیت:** `743403e` (مستقیم روی برنچ production) - ---- - -## 🏷 فاز ۱۴ — فیکس Docker Build + Deployment (بهمن ۱۴۰۴) - -> **هدف:** رفع مشکلات Docker build و CI/CD pipeline - -### ۱۴.۱ — تغییر به NuGet Package ✅ - -- **مشکل:** `ProjectReference` به `../../../CMS/src/CMSMicroservice.Protobuf/` خارج از Docker build context بود -- **رفع:** تغییر به `PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.178"` -- **فایل:** `BackOffice.csproj` - -### ۱۴.۲ — حذف COPY libs/ از Dockerfile ✅ - -- **مشکل:** `COPY ["libs/", "libs/"]` فیل می‌شد — `libs/` خارج از build context -- **رفع:** حذف خط — دیگه نیازی به DLLهای BFF نیست -- **فایل:** `Dockerfile` - -### ۱۴.۳ — تغییر nginx:alpine به رجیستری لوکال ✅ - -- **مشکل:** `FROM nginx:alpine` از Docker Hub → TLS handshake timeout -- **رفع:** `FROM 194.5.195.53:32082/nginx:alpine` -- **فایل:** `Dockerfile` - -### ۱۴.۴ — اضافه شدن SERVER_PASSWORD secret ✅ - -- **مشکل:** مرحله Deploy to Kubernetes با `Permission denied` فیل می‌شد -- **رفع:** سکرت `SERVER_PASSWORD` به ریپو Gitea اضافه شد (BackOffice + FrontOffice) - ---- - -## 🏷 فاز ۱۳ — بهبودهای UI بک‌آفیس (بهمن ۱۴۰۴) - -> **هدف:** رفع مشکلات بصری، بهبود UX فرم‌ها و ناوبری - -### ۱۳.۱ — فیکس کامپوننت Image (پیشوند `/uploads/`) ✅ - -- **مشکل:** تصاویر آپلود‌شده (بلاگ، صفحات سایت، سکشن‌ها) در بک‌آفیس نمایش داده نمی‌شدند — مسیر `GwUrl + Src` با مسیر `UploadsController` هماهنگ نبود -- **رفع:** اضافه شدن `/uploads/` بین `FileBaseUrl` و مسیر نسبی تصویر -- **فایل:** `BackOffice/Common/BaseComponents/Image.razor.cs` - -### ۱۳.۲ — فیکس فیلتر هفته در گزارش‌های هفتگی ✅ - -- **مشکل:** فیلتر هفته از `MudTextField` (ورودی متنی) استفاده می‌کرد — کاربر باید عدد حدس می‌زد -- **رفع:** جایگزینی با `WeekNumberPicker` — انتخاب هفته از لیست با بایندینگ `WeekDefinitionId` -- **فایل‌ها:** - - `CMS/src/CMSMicroservice.Protobuf/Protos/commission.proto` — تغییر فیلدها از `StringValue` به `Int64Value` - - `CMS/.../CommissionCQ/Queries/GetAllWeeklyPools/GetAllWeeklyPoolsQuery.cs` + `Handler.cs` - - `BackOffice/Pages/Commission/WeeklyReports.razor` - -### ۱۳.۳ — فیکس دانلود PDF قراردادها ✅ - -- **مشکل:** فیلد `SignedPdfFile` محتوای HTML کامل دارد (نه URL فایل PDF) — دکمه دانلود کار نمی‌کرد -- **رفع:** تابع JS جدید `jsHtmlToPdf()` برای باز کردن HTML در پنجره جدید و چاپ/ذخیره به‌عنوان PDF -- **فایل‌ها:** - - `BackOffice/wwwroot/js/main.js` — تابع `jsHtmlToPdf` - - `BackOffice/Pages/Contract/UserContractPage.razor` - - `BackOffice/Pages/Contract/ContractDetailsDialog.razor` - -### ۱۳.۴ — یکسان‌سازی ارتفاع ویرایشگر HTML ✅ - -- **مشکل:** ارتفاع `MudHtmlEditor` در صفحات مختلف متفاوت بود — برخی خیلی کوتاه -- **رفع:** اضافه شدن `MinHeight="300px"` به تمام ۷ ویرایشگر HTML -- **فایل‌ها:** `BlogPostEditDialog`, `SitePageSectionEditDialog`, `DiscountShop/ProductFormDialog`, `Package/CreateDialog`, `Package/UpdateDialog`, `Products/CreateDialog`, `Products/UpdateDialog` - -### ۱۳.۵ — تولید خودکار اسلاگ بلاگ ✅ - -- **مشکل:** کاربر باید اسلاگ URL را دستی وارد می‌کرد — غیرضروری و مستعد خطا -- **رفع:** حذف فیلد اسلاگ از فرم، تولید خودکار `post-{GUID}` در بک‌اند (حداکثر ۲۰ کاراکتر) -- **فایل‌ها:** - - `CMS/.../BlogPostCQ/Commands/CreateBlogPost/CreateBlogPostCommandHandler.cs` - - `CMS/.../BlogPostCQ/Commands/UpdateBlogPost/UpdateBlogPostCommandHandler.cs` - - `BackOffice/Pages/Blog/Components/BlogPostEditDialog.razor` - -### ۱۳.۶ — انتقال تگ‌ها به منوی جداگانه ✅ - -- **مشکل:** تگ‌ها فقط از تب سوم بلاگ قابل دسترسی بودند — ولی تگ‌ها بین محصولات و بلاگ مشترکند -- **رفع:** اضافه شدن مسیر `/tags` به `TagManagementPage`، لینک جدید «مدیریت تگ‌ها» در منوی ناوبری، حذف تب تگ‌ها از `BlogHub` -- **فایل‌ها:** - - `BackOffice/Pages/Tag/TagManagementPage.razor` - - `BackOffice/Shared/NavMenu.razor` - - `BackOffice/Pages/Blog/BlogHub.razor` - -### ۱۳.۷ — تولید خودکار کلید سکشن ✅ - -- **مشکل:** کاربر باید کلید سکشن صفحه سایت را دستی وارد می‌کرد (مثلاً `about-us-section`) -- **رفع:** فیلد اختیاری شد، تولید خودکار `section-{GUID}` (حداکثر ۲۰ کاراکتر) در هندلر CMS -- **فایل‌ها:** - - `CMS/.../SitePageCQ/Commands/CreateSitePageSection/CreateSitePageSectionCommandHandler.cs` - - `CMS/.../SitePageCQ/Commands/CreateSitePageSection/CreateSitePageSectionCommandValidator.cs` - - `BackOffice/Pages/Content/Components/SitePageSectionEditDialog.razor` - ---- - -## 🏷 فاز ۱۲ — فیکس فلوی ثبت‌نام / ورود FrontOffice (بهمن ۱۴۰۴) - -> **هدف:** رفع ۳ باگ بحرانی در فلوی ثبت‌نام و ورود FrontOffice -> **مستند کامل:** [`totalDoc/cms/REGISTRATION-FLOW-FIXES.md`](../../totalDoc/cms/REGISTRATION-FLOW-FIXES.md) - -### ۱۲.۱ — رفع ایجاد کاربر جدید در VerifyOtpToken 🔴 ✅ - -- **مشکل:** `UserCQ/VerifyOtpTokenCommandHandler` کاربران جدید ایجاد نمی‌کرد — فقط خطای «کاربر یافت نشد» -- **رفع:** اضافه شدن لاجیک کامل: اعتبارسنجی کد معرف، بررسی ظرفیت درخت باینری (حداکثر ۲ فرزند)، تعیین شاخه (چپ/راست)، ایجاد User + UserRole + UserWallet، رویدادهای دامنه -- **فایل:** `CMS/src/CMSMicroservice.Application/UserCQ/Commands/VerifyOtpToken/VerifyOtpTokenCommandHandler.cs` - -### ۱۲.۲ — رفع جستجوی موبایل در AcceptContract 🔴 ✅ - -- **مشکل:** `_currentUserService.Username` = `"{FirstName} {LastName}"` — نه شماره موبایل! در نتیجه OTP و کاربر هیچوقت پیدا نمی‌شد -- **رفع:** ابتدا کاربر از `UserId` پیدا شود، سپس `user.Mobile` برای جستجوی OTP استفاده شود -- **فایل:** `CMS/src/CMSMicroservice.Application/UserCQ/Commands/AcceptContract/AcceptContractCommandHandler.cs` - -### ۱۲.۳ — رفع `IsCompleteRegister()` در FrontOffice 🟡 ✅ - -- **مشکل:** `InitUserAuthInfo().GetAwaiter()` بدون `.GetResult()` — عملیات async اجرا نمی‌شود، منوی کناری وضعیت نادرست -- **رفع:** تغییر به `InitUserAuthInfo().GetAwaiter().GetResult()` -- **فایل:** `FrontOffice/src/FrontOffice.Main/Utilities/AuthService.cs` - ---- - -## 🏷 فاز ۱۱ — رفع خطای صفحات + سرویس عمومی تصاویر (بهمن ۱۴۰۴) - -> **هدف:** رفع خطای ۳ صفحه BackOffice + ایجاد اندپوینت HTTP عمومی برای سرو تصاویر - -### ۱۱.۱ — سرویس عمومی سرو تصاویر (CMS) ✅ - -- **`UploadsController`** — اندپوینت `GET /uploads/{path}` برای سرو مستقیم فایل‌ها -- `[AllowAnonymous]` — بدون نیاز به احراز هویت -- کش مرورگر ۲۴ ساعته (`ResponseCache`) -- پشتیبانی از Range Requests -- **FMS Fallback:** اگر فایل محلی نباشد، از `dl.afrino.co` دانلود و کش می‌شود -- `IHttpClientFactory` با named client `"FMS"` (timeout: 30s) -- **فایل‌ها:** `CMS/WebApi/Controllers/UploadsController.cs`, `CMS/WebApi/Program.cs` - -### ۱۱.۲ — رفع صفحه «صفحات سایت» ✅ - -- اضافه شدن **دکمه «افزودن صفحه جدید»** به بالای صفحه -- اضافه شدن **دکمه «حذف»** (آیکون قرمز) برای هر ردیف -- ایجاد **`SitePageCreateDialog`** — دیالوگ ایجاد صفحه جدید با فیلدها: - - کلید صفحه (PageKey)، عنوان، توضیحات متا، عنوان هیرو، زیرعنوان هیرو، تصویر هیرو، وضعیت -- Proto: اضافه شدن `CreateSitePage` و `DeleteSitePage` RPC -- CQRS: `CreateSitePageCommand/Handler` و `DeleteSitePageCommand/Handler` -- **فایل‌ها:** - - `sitepage.proto` — 2 RPC جدید + پیام‌های Request/Response - - `SitePageCQ/Commands/CreateSitePage/` — Command + Handler - - `SitePageCQ/Commands/DeleteSitePage/` — Command + Handler - - `CMS/WebApi/Services/SitePageService.cs` — 2 override جدید - - `BackOffice/Services/Content/ISitePageService.cs` — `CreateAsync` + `DeleteAsync` + `SitePageCreateDto` - - `BackOffice/Services/Content/SitePageService.cs` — پیاده‌سازی Create/Delete - - `BackOffice/Pages/Content/SitePageManagementPage.razor` — دکمه‌های Add/Delete - - `BackOffice/Pages/Content/SitePageManagementPage.razor.cs` — متدهای CreatePage/DeletePage - - `BackOffice/Pages/Content/Components/SitePageCreateDialog.razor` + `.razor.cs` - -### ۱۱.۳ — رفع صفحه «قراردادها» (Contracts) ✅ - -- **مشکل:** صفحه `/contracts` اصلاً بارگذاری نمی‌شد — crash در DI -- **علت:** `UserContractContract.UserContractContractClient` در DI ثبت نشده بود -- **رفع:** اضافه شدن `using CMSMicroservice.Protobuf.Protos.UserContract` و ثبت gRPC client -- **فایل:** `BackOffice/Common/Configure/ConfigureService.cs` - -### ۱۱.۴ — رفع صفحه «کیف پول کاربران» (Wallets) ✅ - -- **مشکل:** صفحه `/wallets` اصلاً بارگذاری نمی‌شد — crash در DI -- **علت:** دو سرویس ثبت نشده بود: - - `UserWalletContract.UserWalletContractClient` - - `UserWalletChangeLogContract.UserWalletChangeLogContractClient` -- **رفع:** اضافه شدن using‌ها و ثبت هر دو gRPC client -- **فایل:** `BackOffice/Common/Configure/ConfigureService.cs` - ---- - -## 🏷 فاز ۱۰ — بهبود مدیریت محتوا: بلاگ + صفحات سایت (بهمن ۱۴۰۴) - -> **هدف:** فعال‌سازی آپلود تصویر باینری و ادیتور HTML در صفحات بلاگ و صفحات سایت - -### ۱۰.۱ — بهبود ادیتور پست بلاگ ✅ - -- **`MudTextField Lines="10"`** → **`MudHtmlEditor`** برای ویرایش محتوای HTML -- **فیلد متنی مسیر تصویر** → **`MudFileUpload`** با پیش‌نمایش تصویر (`Image` component) -- حذف فیلد `FeaturedImageThumbnailPath` (تولید خودکار توسط بک‌اند) -- اضافه شدن `MudForm` با اعتبارسنجی + حالت بارگذاری (`_loading`) -- مدیریت خطا: try-catch + Snackbar -- **فایل‌ها:** `Pages/Blog/Components/BlogPostEditDialog.razor` + `.razor.cs` - -### ۱۰.۲ — بهبود ادیتور صفحه سایت ✅ - -- **فیلد متنی Hero Image** → **`MudFileUpload`** با پیش‌نمایش تصویر -- اضافه شدن `MudForm` + حالت آپلود + مدیریت خطا -- **فایل‌ها:** `Pages/Content/Components/SitePageEditDialog.razor` + `.razor.cs` - -### ۱۰.۳ — بهبود ادیتور بخش صفحه سایت (Section) ✅ - -- **`MudTextField Lines="8"`** → **`MudHtmlEditor`** برای ویرایش محتوای HTML بخش‌ها -- **فیلدهای متنی تصویر/thumbnail** → **`MudFileUpload`** با پیش‌نمایش -- اضافه شدن `MudForm` + حالت آپلود + مدیریت خطا -- **فایل‌ها:** `Pages/Content/Components/SitePageSectionEditDialog.razor` + `.razor.cs` - -### ۱۰.۴ — تغییرات Proto ✅ - -| Proto | تغییر | -|-------|-------| -| `blogpost.proto` | اضافه شدن `BlogImageFileModel` + فیلد `image_file` در Create/Update | -| `sitepage.proto` | اضافه شدن `SitePageImageFileModel` + فیلد `image_file` در Update/CreateSection/UpdateSection | - -### ۱۰.۵ — تغییرات CQRS (بک‌اند CMS) ✅ - -- **Commands:** اضافه شدن `ImageFileBytes`, `ImageMime`, `ImageFileName` به: - - `CreateBlogPostCommand`, `UpdateBlogPostCommand` - - `UpdateSitePageCommand`, `CreateSitePageSectionCommand`, `UpdateSitePageSectionCommand` -- **Handlers:** تزریق `IFileManager` + فراخوانی `UploadImageAsync`: - - BlogPost → `Images/BlogPosts/` - - SitePage → `Images/SitePages/` - - SitePageSection → `Images/SitePageSections/` - -### ۱۰.۶ — تغییرات سرویس‌های BackOffice ✅ - -- `BlogPostService.cs` — ارسال `BlogImageFileModel` با `ByteString.CopyFrom(dto.ImageFile)` -- `SitePageService.cs` — ارسال `SitePageImageFileModel` در Update/CreateSection/UpdateSection -- **DTOs:** اضافه شدن `ImageFile`, `ImageMime`, `ImageFileName` به `BlogPostEditDto`, `SitePageEditDto`, `SitePageSectionEditDto` - -### خلاصه آمار فاز ۱۰ -| معیار | تعداد | -|---|---| -| فایل‌های proto تغییریافته | 2 | -| Command‌های بروزشده | 5 | -| Handler‌های بروزشده | 5 | -| سرویس‌های gRPC تغییریافته | 2 (BlogPostService + SitePageService) | -| دیالوگ‌های UI بازنویسی‌شده | 3 (BlogPost, SitePage, SitePageSection) | -| سرویس‌های BackOffice بروزشده | 2 | -| DTO‌های بروزشده | 3 | -| Build | 0 Error ✅ (هر ۳ پروژه) | - ---- - -## 🏷 فاز ۹ — معماری مدیریت فایل + رفع سفارشات + مهاجرت DB (بهمن ۱۴۰۴) - -> **مستند کامل معماری فایل:** [`totalDoc/cms/FILE-MANAGEMENT-ARCHITECTURE.md`](../../totalDoc/cms/FILE-MANAGEMENT-ARCHITECTURE.md) - -### ۹.۱ — حذف کد مرده FMS ✅ -- حذف ۳ فایل غیرقابل استفاده مرتبط با FMS خارجی (`https://dl.afrino.co`): - -| فایل حذف‌شده | شرح | -|-------------|------| -| `Infrastructure/Services/FmsFileManager.cs` | پیاده‌سازی HTTP upload به FMS | -| `Application/Common/FileManager/FileManagementService.cs` | سرویس قدیمی مدیریت فایل | -| `Application/Common/FileManager/IFileManagementService.cs` | اینترفیس قدیمی | - -### ۹.۲ — رفع صفحه سفارشات (Orders) ✅ - -**مشکل ۱ — صفحه خالی (بدون پیغام خطا)** -- **علت:** `ServerReload` بدون try-catch — exception‌های gRPC ساکت می‌شدند -- **رفع:** اضافه شدن try-catch + نمایش خطا با Snackbar -- **فایل:** `Pages/UserOrder/UserOrderMainPage.razor.cs` - -**مشکل ۲ — Shadow FK تکراری در OrderVAT** -- **علت:** `.WithOne()` بدون inverse navigation → EF Core یک shadow FK اضافی می‌ساخت -- **رفع:** `.WithOne()` → `.WithOne(x => x.OrderVAT)` -- **فایل:** `Persistence/Configurations/OrderVATConfiguration.cs` - -**مشکل ۳ — فیلترهای oneof همیشه فعال** -- **علت:** فیلدهای proto `oneof` مقدار پیش‌فرض enum دارند (هیچ‌وقت null نیستند)، پس `PaymentStatus != null` همیشه true بود -- **رفع:** `PaymentStatus != null` → `HasPaymentStatus == true` (و مشابه برای DeliveryStatus و PaymentMethod) -- **فایل‌ها:** `UserOrderService.cs` — هر دو متد `GetAllUserOrderByFilter` و `GetCustomerOrders` - -### ۹.۳ — مهاجرت DB: حذف محدودیت طول ستون‌های تصویر ✅ - -- **علت:** data URI‌های base64 بزرگ‌تر از `nvarchar(500)` بودند → truncation خاموش -- **رفع:** حذف `HasMaxLength(500)` از تمام ستون‌های image path -- **Migration:** `RemoveImagePathMaxLength` - -| Entity | ستون‌ها | -|--------|---------| -| Product | `ImagePath`, `ImageThumbnailPath` | -| DiscountProduct | `ImagePath`, `ImageThumbnailPath` | -| Category | `ImagePath` | -| DiscountCategory | `ImagePath` | -| BlogPost | `FeaturedImagePath`, `FeaturedImageThumbnailPath` | -| SitePage | `HeroImagePath` | -| SitePageSection | `ImagePath`, `ImageThumbnailPath` | - -### ۹.۴ — بازنویسی کامل مدیریت فایل: ذخیره دیسکی ✅ - -**معماری قبلی:** ذخیره data URI مستقیم در DB (ناکارآمد + حجم بالا) - -**معماری جدید:** -1. فایل‌ها در دیسک ذخیره می‌شوند: `Uploads/Images/{folder}/{guid}.jpg` -2. مسیر نسبی در DB ذخیره می‌شود -3. `ImagePathResolverInterceptor` هنگام serve تبدیل به base64 می‌کند - -**فایل‌های اصلی:** - -| فایل | شرح | -|------|------| -| `Application/Common/FileManager/IFileManager.cs` | اینترفیس: Upload, UploadImage, Delete, ResolveImageUrl | -| `Infrastructure/Services/LocalFileManager.cs` | پیاده‌سازی: ImageSharp, main 1200×1200 + thumb 300×300, JPEG Q75 | -| `WebApi/Interceptors/ImagePathResolverInterceptor.cs` | gRPC Interceptor: walk بازگشتی response → تبدیل path به data URI | - -**تنظیمات:** -- `FileStorage:UploadPath` → پوشه ریشه آپلود (پیش‌فرض: `AppContext.BaseDirectory/Uploads`) -- gRPC MaxReceiveMessageSize: 50MB - -### ۹.۵ — پاکسازی LoggingBehaviour ✅ - -- **قبل:** فیلدهای باینری (byte[] تصاویر) کامل در لاگ چاپ می‌شدند → لاگ‌های چند مگابایتی -- **بعد:** - - فرمت: `JsonFormatter.Default.Format()` به جای `{@Request}` - - Regex: حذف فیلدهای باینری (`File`, `ImageFile`, `image_file`, `file`) - - محدودیت: حداکثر 2000 کاراکتر -- **فایل:** `WebApi/Common/Behaviours/LoggingBehaviour.cs` - -### خلاصه آمار فاز ۹ -| معیار | تعداد | -|---|---| -| فایل‌های حذف‌شده (کد مرده) | 3 | -| فایل‌های جدید | 2 (LocalFileManager بازنویسی + ImagePathResolverInterceptor) | -| فایل‌های ویرایش‌شده | ~12 | -| باگ‌های رفع‌شده | 4 (Orders page ×3 + DB truncation) | -| Migration‌های جدید | 1 (RemoveImagePathMaxLength) | -| ستون‌های DB تغییریافته | 9 (nvarchar(500) → nvarchar(max)) | -| Build | 0 Error ✅ (هر ۳ پروژه) | - ---- - -## 🏷 فاز ۸ — یکسان‌سازی فروشگاه عادی و تخفیفی (بهمن ۱۴۰۴) - -> **مستند کامل:** [`totalDoc/ui-modernization/BACKOFFICE-STORE-UNIFICATION.md`](../../totalDoc/ui-modernization/BACKOFFICE-STORE-UNIFICATION.md) - -### ۸.۱ — بازسازی NavMenu ✅ -- ایجاد دو NavGroup مجزا: «فروشگاه عادی» و «فروشگاه تخفیفی» -- حذف «ویرایش دسته‌جمعی» از منو -- انبارداری → گروه مستقل | پکیج‌ها → آیتم مستقل -- **فایل:** `Shared/NavMenu.razor` - -### ۸.۲ — حذف گزارش‌های کوچک از سفارشات ✅ -- حذف کارت‌های آماری (TotalOrders + TotalAmount) و نمودار Bar ارسال -- حذف فیلدها: `_stats`, `_statusChartLabels`, `_statusChartSeries` -- حذف متد `UpdateStats()` و کلاس `OrderStatsViewModel` -- عنوان: «سفارش‌های کاربر» → «لیست سفارشات» -- **فایل‌ها:** `Pages/UserOrder/UserOrderMainPage.razor` + `.razor.cs` - -### ۸.۳ — رفع باگ لیست خالی سفارشات ✅ -- **علت:** `PaymentDate.ToDateTime()` بدون null check → exception ساکت در WASM -- **رفع:** `@if (context.Item.PaymentDate != null)` + fallback "-" -- **فایل:** `Pages/UserOrder/UserOrderMainPage.razor` - -### ۸.۴ — بازنویسی صفحه محصولات تخفیفی ✅ -- تبدیل به `BasePageComponent` (مطابق فروشگاه عادی) -- فیلترهای جدید: وضعیت + موجودی -- ستون‌های جدید: تصویر inline + عنوان truncate + چیپ رنگی موجودی + چیپ وضعیت -- **فایل‌ها:** `Pages/DiscountShop/DiscountProductsMainPage.razor` + `.razor.cs` (بازنویسی کامل) - -### ۸.۵ — بازنویسی صفحه دسته‌بندی‌های تخفیفی ✅ -- تبدیل به `BasePageComponent` (مطابق فروشگاه عادی) -- ستون‌های جدید: نام لاتین، دسته‌بندی والد (resolve شده)، تعداد محصولات، ترتیب -- code-behind جدید (`@code` درون‌خطی → `.razor.cs`) -- **فایل‌ها:** `Pages/DiscountShop/DiscountCategoriesMainPage.razor` + `.razor.cs` (بازنویسی کامل) - -### خلاصه آمار فاز ۸ -| معیار | تعداد | -|---|---| -| فایل‌های بازنویسی‌شده | 4 | -| فایل‌های ویرایش‌شده | 3 | -| باگ‌های رفع‌شده | 2 (PaymentDate null + لیست خالی) | -| Build | 0 Error ✅ | - ---- - -## 🏷 فاز ۷ — پس از اجرای Audit v7.0 (تیر ۱۴۰۴) - -### خلاصه تغییرات -- **۵۷ مورد** از ۵۸ یافته audit اجرا شد (≈98%) -- **تمام ۱۶ مورد بحرانی 🔴** حل شد -- **تمام ۱۸ مورد جزئی 🟢** حل شد -- **فازهای ۱ تا ۶ تکمیل شدند** (به‌جز DayaLoan و Audit Trail که نیاز به بک‌اند دارند) -- **فاز ۷** — Global Search, Notification Bell, NavMenu Badge, Export Excel 4 صفحه جدید -- **۱۳+ فایل جدید** ساخته شد -- **۹ صفحه** ادغام شدند (۱۴ صفحه → ۵ صفحه) -- **Build**: 0 error ✅ - ---- - -## فاز ۷ — Global Search + Notifications + Export All + NavMenu Badge (v7.0) - -### 6.5 — Badge Pending در NavMenu — ✅ -- **`NavMenu.razor`**: اضافه شدن `MudBadge` روی لینک «درخواست‌های برداشت» -- نمایش تعداد درخواست‌های Pending بصورت real-time از gRPC (`CommissionContract.GetWithdrawalRequestsAsync` با `Status=0`) -- fire-and-forget در `OnInitializedAsync` با try/catch silent - -### 6.2 — Global Search در AppBar — ✅ -- **فایل جدید**: `Shared/GlobalSearch.razor` -- `MudAutocomplete` با Debounce 400ms -- دو نوع جستجو: ۱) نام صفحات (۱۵ صفحه اصلی) ۲) کاربران از gRPC (`UserContract.GetAllUserByFilterAsync`) -- Template سفارشی با آیکون + عنوان + زیرنویس -- ناوبری خودکار با `Navigation.NavigateTo` -- اضافه شده در `MainLayout.razor` داخل `` -- CSS در `app.css` — rounded border-radius 24px, compact padding - -### 6.1 — Notification Bell (placeholder) — ✅ -- **`MainLayout.razor`**: اضافه شدن `MudMenu` + `MudBadge` (Dot) + آیکون Notifications -- Dropdown با هدر «اعلان‌ها» + placeholder «اعلان جدیدی وجود ندارد» -- آماده اتصال به بک‌اند — فقط `Visible=true` و populate items - -### 6.3 — Export Excel صفحات جدید — ✅ (۱۰ صفحه کامل) -- **۴ صفحه جدید** اضافه شدند به ۶ صفحه قبلی: - 1. **UserMainPage** — خروجی CSV: شناسه, موبایل, نام, نام خانوادگی, کدملی - 2. **DiscountOrdersMainPage** — خروجی CSV: شماره سفارش, تاریخ, مبلغ کل, تخفیف, قابل پرداخت, تعداد, وضعیت, پرداخت - 3. **ManualPayments** — خروجی CSV: شناسه, شناسه کاربر, نام کاربر, مبلغ, نوع, وضعیت, تاریخ - 4. **InventoryMainPage** — خروجی CSV: شناسه, محصول, انبار, موجودی, رزرو, قابل فروش, حد هشدار, وضعیت -- هر ۴ صفحه: دکمه «خروجی Excel» + `ExportToExcel()` + `EscapeCsv()` + UTF-8 BOM + `jsSaveAsFile` -- فایل‌های code-behind جدید: `ManualPayments.razor.cs`, `DiscountOrdersMainPage.razor.cs` - ---- - -## فاز ۶ — تاریخ شمسی + تاریخچه‌ها + Export Excel (v6.0) - -### تاریخ شمسی یکپارچه (3.6) — ✅ کامل -- **۱۹+ فایل** آپدیت شدند: تمام تاریخ‌ها از فرمت میلادی (`yyyy/MM/dd`) به شمسی تبدیل شدند -- از extension method‌های `DateTimeConverterCL` استفاده شد: - - `.MiladiToJalali()` — فرمت تاریخ فقط (مثال: ۱۴۰۴/۰۴/۱۲) - - `.MiladiToJalaliWithTime()` — فرمت تاریخ و ساعت -- **صفحات اصلاح‌شده شامل**: Club (Members, Statistics, Features, MemberDetailsDialog)، Commission (Dashboard, WeeklyReports, WithdrawalRequests, Payouts, WithdrawalReports)، Network (UserNetworkInfo, BalancesReport, Statistics, NetworkTreeViewer)، UserOrder, Products, Package, Inventory, DiscountShop, Blog, Content, و غیره -- `PropertyColumn Format="yyyy/MM/dd"` → `TemplateColumn` با `.MiladiToJalali()` -- `MudDatePicker DateFormat` تغییر نکرد (قابلیت تقویم شمسی نیاز به کتابخانه جداگانه دارد) - -### تاریخچه عضویت باشگاه (5.7) — ✅ -- **`MemberDetailsDialog.razor`**: تب تاریخچه با فیلدهای صحیح proto: - - ستون‌ها: `Action`, `Created`, `PackageName`, `Reason`, `PerformedBy` - - Request: `PageIndex = 0` (نه PageNumber) - -### تاریخچه تغییرات شبکه (5.8) — ✅ -- **`UserNetworkInfo.razor`**: تب تاریخچه با فیلدهای تخصصی: - - ستون‌ها: `Action`, `Created`, `OldParentId → NewParentId`, `OldNetworkLeg → NewNetworkLeg` (چپ/راست) - - ستون `Reason` و `PerformedBy` اضافه شد - - Request: `PageIndex = 0` - -### لاگ اجرای Worker‌ها (5.6) — ✅ -- در تب WorkerControl از SystemHub قبلاً پیاده‌سازی شده بود - -### Export Excel / CSV (6.3) — ✅ ۶ صفحه -قابلیت خروجی CSV (سازگار با Excel) به ۶ صفحه اصلی اضافه شد: - -| صفحه | فایل(ها) | ستون‌های خروجی | -|---|---|---| -| **Products** (قبلاً موجود) | ProductsMainPage.razor.cs | — | -| **Club Members** | ClubMembers.razor + .razor.cs | شناسه,کاربر,نام,پکیج,کد فعال‌سازی,تاریخ فعال‌سازی,تاریخ انقضا,فعال,منقضی | -| **Withdrawal Requests** | WithdrawalRequests.razor + .razor.cs | شناسه,کاربر,نام,مبلغ,وضعیت,روش,شبا,تاریخ درخواست,تاریخ پردازش,مرجع بانکی | -| **Weekly Reports** | WeeklyReports.razor + .razor.cs | هفته,مبلغ استخر,موجودی‌ها,ارزش,وضعیت,تاریخ محاسبه | -| **User Orders** | UserOrderMainPage.razor + .razor.cs | شناسه,کاربر,نام,مبلغ,وضعیت پرداخت,وضعیت ارسال,روش پرداخت,تاریخ | -| **Stock Movements** | MovementsPage.razor + .razor.cs | شناسه,محصول,نوع,تعداد,قبل,بعد,مرجع,یادداشت,تاریخ | - -**الگوی پیاده‌سازی:** -- دکمه `` با آیکون `FileDownload` در ToolBarContent -- `StringBuilder` → CSV با هدرهای فارسی -- UTF-8 BOM (`Encoding.UTF8.GetPreamble()`) برای نمایش صحیح فارسی در Excel -- `jsSaveAsFile(filename, base64)` از `wwwroot/js/main.js` -- متد `EscapeCsv()` برای مقادیر حاوی کاما/کوتیشن -- تاریخ‌ها در خروجی نیز شمسی هستند - -### فایل‌های جدید (این نسخه) - -| فایل | عملکرد | -|---|---| -| `Pages/Commission/WeeklyReports.razor.cs` | Code-behind برای export (به‌دلیل محدودیت Razor parser با escaped quotes) | - ---- - -## نسخه قبلی — Audit v5.0 (خرداد ۱۴۰۴) - -### تم رنگی یکپارچه -- **`CustomMudTheme.cs`**: تم Primary از `#0380C0` به `#6366f1` (Indigo) تغییر کرد — هماهنگ با FrontOffice -- **`PaletteDark`** اضافه شد: Surface `#1a1a2e`, Background `#16213e`, AppbarBackground `#0f3460` -- **`app.css`**: رنگ loading از `#1b6ec2` به `var(--mud-palette-primary)` تغییر کرد -- **`NavMenu.razor.css`**: رنگ active از `#0380C0` هاردکد به CSS variable تغییر کرد -- **`MainLayout.razor`**: حذف inline style `border: 1px solid #5e4df9` - -### Dark Mode Toggle -- آیکون ماه/آفتاب در AppBar اضافه شد -- `_isDarkMode` state با `MudThemeProvider` اتصال دارد -- تعویض بین `PaletteLight` و `PaletteDark` در CustomMudTheme - -### عنوان اپلیکیشن -- "پنل مدیریت **فرصت**" → "پنل مدیریت **کارا بازار سلامت**" - ---- - -## فاز ۲ — بازطراحی لایوت صفحات - -### BasePageComponent بازنویسی کامل -- **قبل**: فیلتر ثابت سمت راست (20%) + جدول (80%)، ارتفاع 85vh هاردکد -- **بعد**: فیلتر collapsible بالای جدول، فیلدها در `MudGrid` با `MudItem`، responsive -- **۱۳ صفحه** آپدیت شدند: User, Products, Package, Category, UserOrder, UserAddress, UserRole, Role, BlogPost, BlogCategory, Tag, Transactions, Content - -### DataGrid Height یکسان‌سازی -- همه DataGrid‌ها: `Height="calc(100vh - 240px)"` -- **صفحات اصلاح‌شده**: تمام ~33 صفحه دارای DataGrid - -### Pager یکسان‌سازی -- **PageSize**: همه `20, 50, 100` -- **متن فارسی**: `RowsPerPageString="تعداد در صفحه"` و `InfoFormat="سطر {first_item} تا {last_item} از {all_items}"` - -### MaxWidth یکسان‌سازی -- `MainLayout.razor` MudContainer wrapper اضافه شد → MaxWidth یکسان برای همه صفحات -- **۳۱ صفحه**: حذف `MudContainer` تکراری (double nesting) - -### Breadcrumb -- **`Shared/AppBreadcrumb.razor`** ساخته شد -- جداکننده چپ‌به‌راست (`ChevronLeft`) -- نقشه فارسی URL segments (60+ مسیر) -- آخرین آیتم disabled (صفحه فعلی) - -### Login + VerifyCode بازطراحی -- عرض ثابت 35% → responsive `MaxWidth.Small` -- لوگو + برندینگ "کارا بازار سلامت" اضافه شد -- طراحی gradient background - ---- - -## فاز ۲.۵ — پاکسازی ساختاری - -### NavMenu بازسازی کامل -- **لینک مرده `categories-dragdrop`**: حذف شد -- **Transactions**: حذف از NavMenu (صفحه stub خالی) -- **AlertsMonitoring**: حذف از NavMenu (100% mock) -- **WorkerControl**: به SystemHub منتقل شد (قبلاً لینک نداشت) -- **«پیام‌های عمومی»**: از بخش فروشگاه تخفیفی به «مدیریت محتوا» منتقل شد -- **ساختار گروه‌بندی** اصلاح شد: - - کمیسیون و شبکه: NavGroup واضح - - باشگاه مشتریان: اعضا و آمار + فیچرها - - فروشگاه: پکیج‌ها، محصولات (group)، سفارش‌ها، فروشگاه تخفیفی (group) - - مدیریت: کاربران، نقش‌ها، پرداخت دستی، **کیف‌پول (جدید)**، **قراردادها (جدید)** - - محتوا: بلاگ، صفحات سایت، پیام‌های عمومی - - سیستم: مدیریت سیستم، نسخه اپ‌ها - ---- - -## فاز ۳ — UX بهبودها - -### NoRecordsContent (Empty State) -- **۳۳ DataGrid** آپدیت شدند -- پیام: `موردی یافت نشد.` - -### Delete Confirmation با نام آیتم -- **۱۱ صفحه** اصلاح شدند: - - Role → `«{model.Title}»` - - User → `«{model.FirstName} {model.LastName}»` - - Package → `«{model.Title}»` - - UserAddress → `«{model.Title}»` - - UserRole → `شناسه «{model.Id}»` - - UserOrder → `شماره «{model.Id}»` - - Category → `«{model.Title}»` - - Products → `«{model.Title}»` - - DiscountCategories → `«{category?.Title}»` (lookup اضافه شد) - - DiscountProducts → `«{product?.Title}»` (lookup اضافه شد) - - PublicMessages → `«{message?.Title}»` (lookup اضافه شد) - -### User Menu در AppBar -- `MudMenu` جایگزین متن ساده شماره موبایل شد -- آیتم‌ها: نام کاربر (غیرفعال) + خروج -- آیکون `AccountCircle` -- خروج (`signout`) از NavMenu به AppBar منتقل شد - ---- - -## فاز ۳.۵ — ادغام صفحات - -### Dashboard Merge ← `Pages/Index.razor` -- **`Index.razor` + `SystemOverview.razor`** ادغام شدند -- Routes: `/` + `/dashboard/overview` -- بخش‌ها: - - 6 کارت آمار CMS (کاربران، محصولات، پکیج‌ها، دسته‌بندی‌ها، سفارش‌ها، مبلغ پرداخت‌شده) - - آمار کمیسیون (هفته جاری، استخر، موجودی‌ها، وضعیت محاسبه) - - آمار باشگاه (کل/فعال/غیرفعال) - - جدول آخرین ۵ سفارش پرداخت‌شده - - ۶ دکمه Quick Action -- بارگذاری موازی با `Task.WhenAll` + `.ResponseAsync` -- `SystemOverview.razor` **حذف شد** - -### DiscountShopHub ← `Pages/DiscountShop/DiscountShopHub.razor` -- Routes: `/discount-shop`, `/discount-orders`, `/discount-sales-reports` -- ۲ تب: DiscountOrdersMainPage + SalesReports -- انتخاب تب از URL - -### ClubHub ← `Pages/Club/ClubHub.razor` -- Routes: `/club`, `/club/members`, `/club/statistics` -- ۲ تب: ClubMembers + Statistics - -### BlogHub ← `Pages/Blog/BlogHub.razor` -- Routes: `/blog`, `/blog/posts`, `/blog/categories`, `/tags` -- ۳ تب: BlogPostManagementPage + BlogCategoryManagementPage + TagManagementPage - -### SystemHub ← `Pages/SystemManagement/SystemHub.razor` -- Routes: `/system`, `/system/configuration`, `/system/worker-control`, `/system/health` -- ۳ تب: Configuration + WorkerControl + HealthDashboard - -### ۱۰ صفحه — `@page` directive حذف شد -صفحاتی که به hub منتقل شدند دیگر route مستقل ندارند: -DiscountOrdersMainPage, SalesReports, ClubMembers, Statistics, BlogPostManagementPage, BlogCategoryManagementPage, TagManagementPage, Configuration, WorkerControl, HealthDashboard - ---- - -## فاز ۴ — فیکس‌های بیزینسی - -### Dashboard آمار اصلاح شد -- **قبل**: آمار از ۱۰ رکورد اول محاسبه می‌شد (نادرست) -- **بعد**: از `metadata.TotalCount` و API‌های جداگانه استفاده می‌شود - -### ManualPayments — تأیید/رد -- دکمه‌های Approve/Reject وقتی `Status==0` (در انتظار) نمایش داده می‌شوند -- Confirmation dialog قبل از اجرا -- از `ManualPaymentId` (نه `Id`) استفاده می‌شود - -### UserOrder — فیلتر Cancelled -- `لغو شده` اضافه شد - -### WithdrawalRequests — بهبود کامل -- **Pager**: 10/25/50/100 → 20/50/100 -- **`WithdrawalDetailsDialog.razor`** (جدید): نمایش کامل اطلاعات کاربر، درخواست، و بانکی -- **`RejectReasonDialog.razor`** (جدید): ورود دلیل رد با اعتبارسنجی -- ViewDetails: از Snackbar TODO به دیالوگ واقعی تغییر کرد -- RejectRequest: از دلیل هاردکد به دیالوگ custom تغییر کرد - ---- - -## فاز ۵ — صفحات مفقود (CMS-Derived) - -### WalletManagementPage ← `Pages/Wallet/WalletManagementPage.razor` -- Route: `/wallets` -- **تب ۱ — کیف‌پول‌ها**: DataGrid با ServerData، فیلتر UserAutoComplete - - ستون‌ها: شناسه، کاربر، موجودی اصلی، موجودی شبکه، مشاهده تغییرات - - نوع: `GetAllUserWalletByFilterResponseModel` -- **تب ۲ — تاریخچه تغییرات**: DataGrid با ServerData، فیلتر کاربر + نوع (افزایش/کاهش) - - ستون‌ها: شناسه، کیف‌پول، نوع (چیپ رنگی)، تغییر موجودی، موجودی فعلی، تغییر شبکه، موجودی شبکه فعلی، شناسه مرجع، تاریخ - - نوع: `GetAllUserWalletChangeLogByFilterResponseModel` - - فیلدهای proto با typo: `ChangeNerworkValue`, `RefrenceId` - -### UserContractPage ← `Pages/Contract/UserContractPage.razor` -- Route: `/contracts` -- DataGrid با ServerData، فیلتر UserAutoComplete -- ستون‌ها: شناسه، کاربر، قرارداد، کد امضا، لینک PDF، جزئیات -- نوع: `GetAllUserContractByFilterResponseModel` - -### ContractDetailsDialog ← `Pages/Contract/ContractDetailsDialog.razor` -- جدول ساده: شناسه، کاربر، قالب قرارداد، کد امضا، لینک دانلود PDF - -### ClubFeaturesPage ← `Pages/Club/ClubFeaturesPage.razor` -- Route: `/club/features` -- **تب ۱ — فیچرهای تعریف‌شده**: کارت‌های MudPaper با عنوان، توضیحات، وضعیت (فعال/غیرفعال)، ترتیب - - از `ConfigClient.GetClubFeaturesAsync` -- **تب ۲ — فیچرهای کاربران**: DataGrid با فیلتر کاربر، سوئیچ فعال/غیرفعال - - از `ClubClient.GetUserClubFeaturesAsync` + `ToggleUserClubFeatureAsync` - ---- - -## ⚠️ نکات فنی مهم - -### الگوهای Proto -- **فیلتر**: `new GetAllXxxByFilterFilter()` (سطح بالا، بدون `.Types.`) -- **پاسخ لیست**: `GetAllXxxByFilterResponseModel` (نه `GetXxxResponse`) -- **Typo‌ها در proto**: `ChangeNerworkValue` و `RefrenceId` — باید دقیقاً همین‌ها استفاده شوند - -### _Imports.razor — سرویس‌های Global -سرویس‌های زیر از `_Imports.razor` تزریق می‌شوند و نباید در code-behind با `[Inject]` دوباره تعریف شوند: -- `NavigationManager Navigation` -- `ILocalStorageService LocalStorageService` -- `ISnackbar Snackbar` -- `IJSRuntime jsRuntime` -- `IDialogService DialogService` -- `AuthenticationStateProvider` - -### MudBlazor محدودیت‌ها -- `Variant.Flat` وجود ندارد → از `Variant.Text` استفاده شود -- `GutterSize` روی `MudGrid` deprecated است - ---- - -## فاز ۴ (ادامه) — تکمیل فیکس‌های بیزینسی - -### UserSettings — حذف تب‌های جعلی (2.5.5) -- **`UserSettings.razor`**: تب Notifications (۷ تاگل جعلی بدون بک‌اند) → placeholder «به‌زودی فعال می‌شود» با آیکون NotificationsActive -- **`UserSettings.razor`**: تب Security (فرم تغییر رمز + 2FA بدون بک‌اند) → placeholder «به‌زودی فعال می‌شود» با آیکون Lock -- **حذف کد مرده**: ~۱۵ متغیر notification/security + متدهای `SaveNotificationSettings()`, `SaveSecuritySettings()`, `ChangePassword()` - -### HealthDashboard — حذف متریک‌های Mock (2.5.6) -- **`HealthDashboard.razor`**: بخش System Resources (۴ کارت CPU=45.2%, Memory=62.8%, Disk=73.5%, Network) → یک کارت با پیام «مانیتورینگ منابع سیستم در نسخه‌های آینده با اتصال به Prometheus/Grafana فعال خواهد شد» -- **حذف کد مرده**: ۹ متغیر mock (`_cpuUsage`, `_memoryUsage`, etc.) + متد `GetResourceColor()` - -### حذف cursor:pointer زائد (4.10) -- `Style="cursor:pointer;"` از **۱۷ فایل** حذف شد (MudButton/MudIconButton خودشان cursor:pointer دارند) -- شامل: ProductsMainPage, GalleryDialog, Image.razor (base component), RoleMainPage, UserOrderMainPage, PackageMainPage, etc. - -### حذف Console.WriteLine (4.11) -- از **۱۱ فایل** حذف شد: DiscountProductService, DiscountCategoryService, NetworkTreeViewer, UserSettings, CategoryMainPage, UserOrderMainPage, Commission/Dashboard, DiscountProductsMainPage, DiscountCategoryMultiSelectCombo, UserRole/CreateDialog -- **`Commission/Dashboard.razor.cs`**: `using System.Text.Json` هم حذف شد (دیگر استفاده نمی‌شد) - -### DiscountProducts — فیلتر دسته‌بندی (4.7) -- **`DiscountProductsMainPage.razor`**: `@inject IDiscountCategoryService` اضافه شد -- دسته‌بندی‌های فعال از سرویس بارگذاری و در MudSelect نمایش داده می‌شوند -- جایگزینی `@* TODO: Load categories *@` با `@foreach` واقعی - -### DiscountProducts — Items → ServerData (4.8) -- **`DiscountProductsMainPage.razor`**: تبدیل از `Items="@_products"` به `ServerData="LoadServerData"` -- متد `LoadServerData(GridState)` اضافه شد با `PageNumber` و `PageSize` از state -- `Height="calc(100vh - 300px)"` + `FixedHeader="true"` اضافه شد -- Snackbar اطلاع‌رسانی اضافی در هر بارگذاری حذف شد (redundant) - -### UserOrder — فعال‌سازی آمار (4.6) -- **`UserOrderMainPage.razor`**: بخش آمار (MudCard + MudChart) از حالت comment خارج شد -- نمایش تعداد سفارش‌ها + مجموع مبلغ + نمودار Bar وضعیت ارسال - -### UserSettings — persist با localStorage (4.9) -- تب General از قبل با localStorage کار می‌کرد ✅ (فقط تب‌های جعلی حذف شدند) - ---- - -## فاز ۴.۵ — Cross-Navigation - -### لینک نام کاربر → پروفایل (4.5.1, 4.5.2) -- **`UserOrderMainPage.razor`**: ستون `UserFullName` از PropertyColumn به TemplateColumn تبدیل شد — MudLink به `/network/user-info/{UserId}` -- **`UserPayouts.razor`**: نام/شناسه کاربر به MudLink تبدیل شد → `/network/user-info/{UserId}` -- **`WithdrawalRequests.razor`**: نام کاربر به MudLink تبدیل شد → `/network/user-info/{UserId}` - -### لینک محصول ↔ انبار (4.5.3, 4.5.4) — Skip -- صفحه جزئیات محصول وجود ندارد (فقط لیست + دیالوگ ویرایش) -- لینک cross-navigation بدون صفحه مقصد معنادار نیست - -### Extract shared status helpers (3.5.6) — Skip -- بررسی نشان داد هر context مقادیر متفاوتی دارد: - - UserPayouts: status 1 = Success/پرداخت شده - - WithdrawalRequests: status 1 = Info/واریز شده - - PayoutDetailsDialog: فقط ۳ وضعیت (نه ۶) -- استخراج به helper مشترک باعث از دست رفتن معنای domain-specific می‌شود - ---- - -## 📈 آمار تغییرات - -| معیار | تعداد | -|---|---| -| فایل‌های جدید | 11 | -| فایل‌های حذف‌شده | 1 (SystemOverview.razor) | -| فایل‌های ویرایش‌شده | ~65+ | -| DataGrid‌های آپدیت‌شده | 33 | -| Delete confirmation اصلاح‌شده | 11 | -| صفحات ادغام‌شده | 14 → 5 | -| خطاهای build حل‌شده | 9+ | -| Console.WriteLine حذف‌شده | 22+ (از ۱۱ فایل) | -| cursor:pointer حذف‌شده | 17 فایل | -| Cross-link اضافه‌شده | 3 صفحه (UserOrder, UserPayouts, WithdrawalRequests) | +See [totalDoc/INDEX.md](../../totalDoc/INDEX.md) for all documentation.