═══════════════════════════════════════════════════════════════════════════ تاریخچه توسعه سیستم مدیریت نماینده‌ها (Agents Management System) NexPanel - پنل مدیریتی VPN Reseller ═══════════════════════════════════════════════════════════════════════════ 📅 تاریخ شروع: فاز اول 👤 توسعه‌دهندگان: GitHub Copilot + User 🎯 هدف کلی: اضافه کردن سیستم مدیریت نماینده‌ها با قابلیت‌های کامل CRUD ═══════════════════════════════════════════════════════════════════════════ 🔷 فاز اول: طراحی و استخراج رابط کاربری (UI/UX) ═══════════════════════════════════════════════════════════════════════════ ✅ کار انجام شده: ──────────────── 1. استخراج تمام مودال‌ها از کد اصلی - 7 موداِل مختلف برای مدیریت نماینده‌ها - موداِل اضافه کردن نماینده (Add Agent) - موداِل ویرایش نماینده (Edit Agent) - موداِل حذف نماینده (Delete Agent) - موداِل حذف یک‌تنی (Delete Single Agent) - موداِل ویرایش هزینه (Edit Cost) - موداِل تسویه حساب (Settle Agent) - موداِل شارژ کیف پول (Charge Agent) 2. ایجاد فایل dedicated برای موداِل‌ها - فایل: agents-modals.php - مقدار کد: حدود 500 خط - موقعیت: public/panels/superadmin/agents-modals.php 3. طراحی ساختار Bootstrap - استفاده از Grid System (col-6 برای 50%, col-lg-4 برای 33%) - کد رنگی‌شده: هر موداِل رنگ مختص خود را دارد - Icons: Font Awesome 6.5.1 ═══════════════════════════════════════════════════════════════════════════ 🔷 فاز دوم: پیاده‌سازی فیلدهای شرطی (Conditional Form Fields) ═══════════════════════════════════════════════════════════════════════════ ✅ کار انجام شده: ──────────────── 1. درک نوع قیمت‌گذاری - نوع متغیر (Variable): قیمت بر اساس هر گیگابایت - نوع ثابت (Fixed): قیمت ماهانه مشخص 2. ایجاد فیلدهای شرطی - انتخاب "نوع حجم" را اضافه کردیم - فیلدهای قیمت بر اساس نوع نمایش/پنهان می‌شوند 3. توابع جاوا‌اسکریپت برای مدیریت فیلدها - toggleAddAgentPricingFields(): مدیریت فیلدهای موداِل اضافه کردن - toggleEditAgentPricingFields(): مدیریت فیلدهای موداِل ویرایش 4. استفاده از classList API - col-6 ↔ col-lg-4 تبدیل می‌شود بر اساس نوع - Responsive design بهتر می‌شود ═══════════════════════════════════════════════════════════════════════════ 🔷 فاز سوم: طراحی و اجرای Schema دیتابیس ═══════════════════════════════════════════════════════════════════════════ ✅ تغییرات دیتابیس: ────────────────── جدول: users ستون‌های جدید اضافه شده: ┌─────────────────────┬──────────────┬─────────────────────────────────┐ │ نام ستون │ نوع │ شرح │ ├─────────────────────┼──────────────┼─────────────────────────────────┤ │ volume_type │ VARCHAR(20) │ متغیر (variable) یا ثابت (fixed)│ │ price_per_gb │ DECIMAL(...)│ قیمت برای هر گیگابایت │ │ max_gb_per_month │ INT │ حداکثر GB در ماه (برای Fixed) │ │ monthly_price │ DECIMAL(...) │ قیمت ماهانه (برای Fixed) │ │ created_by │ INT │ شناسه Super Admin که این‌ها را │ │ │ │ اضافه کرد (Audit Trail) │ └─────────────────────┴──────────────┴─────────────────────────────────┘ 💾 SQL Query: ALTER TABLE users ADD COLUMN volume_type VARCHAR(20) AFTER wallet_balance; ALTER TABLE users ADD COLUMN price_per_gb DECIMAL(12,4) AFTER volume_type; ALTER TABLE users ADD COLUMN max_gb_per_month INT AFTER price_per_gb; ALTER TABLE users ADD COLUMN monthly_price DECIMAL(12,4) AFTER max_gb_per_month; ALTER TABLE users ADD COLUMN created_by INT AFTER monthly_price; ═══════════════════════════════════════════════════════════════════════════ 🔷 فاز چهارم: ایجاد API Endpoint برای اضافه کردن نماینده ═══════════════════════════════════════════════════════════════════════════ ✅ فایل ایجاد شده: ────────────────── 📄 /api/agents/add.php 🔐 امنیت: • checkAuth(1) - فقط Super Admin می‌تواند استفاده کند • HTTP Status Codes: 201 (موفق), 400 (خطا), 401 (دسترسی رد), 500 (سرور) 📥 ورودی‌های مورد انتظار (JSON): { "display_name": "نام نمایندگی", "username": "نام‌کاربری انگلیسی", "password": "رمزعبور", "phone": "شماره تلفن", "parent_id": 5, // (اختیاری) شناسه بازارکن "volume_type": "variable", // یا "fixed" // اگر variable: "price_per_gb": 15000, // اگر fixed: "max_gb_per_month": 100, "monthly_price": 50000 } ✅ بررسی‌های صورت‌گرفته: 1. display_name: الزامی و غیرخالی 2. username: • الزامی • 3-50 کاراکتر • فقط حروف انگلیسی، اعداد و خط تیره • منحصر به فرد (چک برابری در دیتابیس) 3. password: • الزامی • حداقل 6 کاراکتر • با password_hash() ایمن‌سازی می‌شود 4. phone: الزامی 5. volume_type: "variable" یا "fixed" 6. price_per_gb: الزامی برای Variable، بزرگتر از 0 7. max_gb_per_month: الزامی برای Fixed، بزرگتر از 0 8. monthly_price: الزامی برای Fixed، بزرگتر از 0 📤 خروجی (JSON): ✅ موفقیت: { "success": true, "message": "نماینده با موفقیت اضافه شد", "agent_id": 6 } ❌ خطا: { "success": false, "errors": ["نام‌کاربری باید 3-50 کاراکتر باشد", "..."] } 💾 عملیات دیتابیس: • INSERT: در جدول users با role_id = 2 • بیش‌تر فیلدها: - status = "active" - wallet_balance = 0 - created_at = NOW() - created_by = $_SESSION['user']['id'] (Super Admin ID) 📊 Activity Logging: • هر نماینده جدید در activity_logs ثبت می‌شود • برای Audit Trail ═══════════════════════════════════════════════════════════════════════════ 🔷 فاز پنجم: ادغام Frontend با Backend ═══════════════════════════════════════════════════════════════════════════ ✅ مقابله با مشکلات: ───────────────────── 🐛 مشکل اول: عدم تطابق نام‌های فیلد (Field Name Mismatch) ────────────────────────────────────────────────────── مشکل: • Form Frontend: pricePerGb (camelCase) • API Backend: price_per_gb (snake_case) • نتیجه: Validation Error می‌شد راه‌حل: • تمام نام‌های input در agents-modals.php را به snake_case تغییر دادیم • display_name, username, password, parent_id, volume_type, etc. ✅ نتیجه: مشکل حل شد 🐛 مشکل دوم: روش ارسال Form نادرست ─────────────────────────────────── مشکل: • Form بدون method="POST" بود • Browser به اشتباه GET request می‌کرد • URL می‌شد: agents.php?display_name=... راه‌حل: • method="POST" را به فرم اضافه کردیم • JavaScript handler با preventDefault() اجرا می‌شود ✅ نتیجه: AJAX درست‌تر کار می‌کند ═══════════════════════════════════════════════════════════════════════════ 🔷 فاز ششم: ایجاد Dropdown بازارکن‌ها از دیتابیس ═══════════════════════════════════════════════════════════════════════════ ✅ کار انجام شده: ────────────────── 1. Query دیتابیس: SELECT id, display_name FROM users WHERE role_id = 5 AND status = "active" 2. موارد (حالت فعلی): • شناسه 5: "Marketer" (یک بازارکن تست) 3. Dropdown در Modal: • گزینه اول: "انتخاب بازارکن (اختیاری)" • سایر موارد: فهرستی از بازارکن‌های فعال ═══════════════════════════════════════════════════════════════════════════ 🔷 فاز هفتم: اضافه کردن Form Submission Handler ═══════════════════════════════════════════════════════════════════════════ ✅ JavaScript Handler ایجاد شده: ──────────────────────────────── locationinFile: agents-modals.php کوی کد: document.getElementById('addAgentForm').addEventListener('submit', async (e) => { e.preventDefault(); const formData = new FormData(this); const data = Object.fromEntries(formData); try { const response = await fetch('/NexPanel/api/agents/add.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(data) }); const result = await response.json(); if (result.success) { alert('✅ نماینده با موفقیت اضافه شد'); location.reload(); } else { alert('❌ خطا: ' + result.errors.join('\n')); } } catch (error) { alert('❌ خطای سرور'); } }); 💡 نکات: • FormData برای جمع‌آوری داده‌های فرم • JSON.stringify برای تبدیل به JSON • fetch() برای AJAX Request • location.reload() برای تازه‌کردن صفحه پس از موفقیت ═══════════════════════════════════════════════════════════════════════════ 🔷 فاز هشتم: نمایش پویا نماینده‌ها از دیتابیس ═══════════════════════════════════════════════════════════════════════════ ✅ تغییرات در agents.php: ──────────────────────── 1. Query نماینده‌ها: SELECT id, username, display_name, phone, status, wallet_balance, volume_type, price_per_gb, max_gb_per_month, monthly_price FROM users WHERE role_id = 2 ORDER BY created_at DESC 2. PHP Loop برای نمایش: 3. داده‌های نمایش‌داده‌شده: • تصویر پروفایل (فعلاً ثابت است) • نام نمایندگی • وضعیت (فعال/غیرفعال) • قیمت: بر اساس نوع - Variable: price_per_gb + "تومان" - Fixed: monthly_price + "تومان" • موجودی کیف پول (wallet_balance) • دکمه‌های عملیات ═══════════════════════════════════════════════════════════════════════════ 🔷 فاز نهم: تست عملی و تایید موفقیت ═══════════════════════════════════════════════════════════════════════════ ✅ تست‌های انجام شده: ────────────────────── 1. اضافه کردن نماینده اول: • نام نمایندگی: سارا رضایی • نام‌کاربری: sara-rezaei • رمزعبور: (امن‌سازی شده) • نوع قیمت: Variable • قیمت هر گیگ: 15,000 تومان • بازارکن: ID 5 (اختیاری) • وضعیت: ✅ موفق 2. بررسی دیتابیس: • دستور: SELECT * FROM users WHERE role_id = 2 ORDER BY id DESC LIMIT 5 • نتیجه: نماینده جدید در دیتابیس ثبت شد • شناسه: 6 • created_by: 1 (Super Admin) 3. بررسی نمایش صفحه: • نماینده جدید (سارا رضایی) در کارت‌ها نمایش می‌یابد • قیمت درست: 15,000 تومان • موجودی: 0 تومان ═══════════════════════════════════════════════════════════════════════════ 📊 خلاصه وضعیت فعلی ═══════════════════════════════════════════════════════════════════════════ ✅ COMPLETED (تکمیل شده): ──────────────────────── • استخراج و سازماندهی موداِل‌ها • فیلدهای شرطی برای نوع قیمت‌گذاری • Schema دیتابیس با 5 ستون جدید • API Endpoint برای اضافه کردن نماینده • Dropdown بازارکن‌ها از دیتابیس • Form Submission Handler (AJAX) • نمایش پویا نماینده‌ها از دیتابیس • تست و تایید موفقیت 🟡 PARTIALLY COMPLETE (نیمه‌تکمیل): ───────────────────────────────────── • بررسی اعتبار (Validation): سمت سرور ✅، سمت کلاینت ⚠️ ❌ NOT YET IMPLEMENTED (هنوز اجرا نشده): ────────────────────────────────────────── • loadAgentData(agentId): بارگذاری داده‌های نماینده برای ویرایش • ویرایش نماینده (/api/agents/edit.php) • حذف نماینده (/api/agents/delete.php) • تسویه حساب (/api/agents/settle.php) • شارژ کیف پول (/api/agents/charge.php) • جستجو و فیلتر نماینده‌ها • آپلود تصویر پروفایل ═══════════════════════════════════════════════════════════════════════════ 📁 فایل‌های تغییر‌یافته ═══════════════════════════════════════════════════════════════════════════ 1. ✨ agents-modals.php (جدید) • موقعیت: public/panels/superadmin/agents-modals.php • حجم: ~500 خط • محتوا: تمام 7 موداِل مدیریت نماینده‌ها 2. 📝 agents.php (ویرایش‌شده) • استعلام نماینده‌ها از دیتابیس • Loop برای نمایش کارت‌ها • require_once agents-modals.php 3. 🔧 api/agents/add.php (جدید) • موقعیت: public/api/agents/add.php • حجم: ~150 خط • محتوا: POST endpoint برای اضافه کردن نماینده 4. 🗄️ config/database.php • بدون تغییر (استفاده شده توسط API) ═══════════════════════════════════════════════════════════════════════════ 🎯 دستاورد‌های کلیدی ═══════════════════════════════════════════════════════════════════════════ ✅ سیستم ایجاد نماینده کامل است ✅ سیستم نمایش نماینده‌ها از دیتابیس کار می‌کند ✅ معتبرسازی سمت سرور قوی است ✅ Security: password_hash()، session check، SQL prepared statements ✅ Audit Trail: created_by برای ردیابی چه کسی نماینده را اضافه کرد ✅ Responsive Design: Bootstrap Grid System ✅ RTL Support: فارسی درست نمایش داده می‌شود ═══════════════════════════════════════════════════════════════════════════ 🚀 مراحل بعدی پیشنهادی ═══════════════════════════════════════════════════════════════════════════ اولویت ۱ (بالا): ویرایش نماینده • loadAgentData(agentId) تابع • api/agents/edit.php endpoint • Form validation برای ویرایش اولویت ۲ (بالا): حذف نماینده • حذف تک نماینده • حذف انبوهی (bulk delete) • api/agents/delete.php endpoint اولویت ۳ (متوسط): شارژ/تسویه • api/agents/charge.php • api/agents/settle.php • جدول transactions اولویت ۴ (پایین): جستجو و فیلتر • جستجوی نام نماینده • فیلتر بر اساس وضعیت • Client-side یا Server-side ═══════════════════════════════════════════════════════════════════════════ 📌 توصیه‌های مهم برای توسعه آینده ═══════════════════════════════════════════════════════════════════════════ 1. همیشه معتبرسازی دوگانه استفاده کنید (Client + Server) 2. نام‌های فیلد را برای consistency استاندارد کنید (snake_case برای API) 3. هر تغییر در دیتابیس را لاگ کنید (Audit Trail) 4. سرویس‌های حساس را با checkAuth() محافظت کنید 5. REST API endpoints را کاملاً توثیق کنید 6. خطاهای کاربر‌پسند را ارائه دهید ═══════════════════════════════════════════════════════════════════════════ پایان تاریخچه ═══════════════════════════════════════════════════════════════════════════