# راهنمای ایجنت — پروژهٔ IFNEX Logistics > **تاریخ:** ۲۰۲۶-۱۰-۳۰ > **نسخه:** ۱.۴ > **تهیه‌کننده:** VernaSoft Group — Kazem Alghasi --- ## ۱. خلاصهٔ پروژه سیستم مدیریت لجستیک بین‌المللی با معماری Headless: **Laravel 11** به‌عنوان بک‌اند، **WordPress** به‌عنوان فرانت‌اند و **Filament 3.3** به‌عنوان پنل مدیریت. این سیستم جایگزین فرآیندهای دستی مبتنی بر اکسل شده و از Multi-Package، فاکتور گمرکی، کیف پول دیجیتال، درگاه پرداخت Zarinpal، تولید PDF با بارکد، فلوی تأیید سفارش، تعهدنامه، SMS کاوه‌نگار، سیستم اعتبار چندارزی، رهگیری پیشرفته، **سیستم ۴-رُبعی نرخ‌ها** و **فاکتورهای دستی مدیر** پشتیبانی می‌کند. ### وضعیت فعلی فازهای ۰، ۱، ۲، ۳، ۳.۵ و ۳.۶ تکمیل شده‌اند. فاز ۳.۷ (اصلاحات ارزی و فاکتور دستی) تکمیل شد: - [x] فلوی کامل سفارش (ثبت ← تأیید ← تعهدنامه ← پرداخت) — تست End-to-End - [x] بازطراحی داشبورد و Login پنل Filament (هویت بصری navy + amber) - [x] بازطراحی PDFهای AWB، Invoice و Label (dompdf، چیدمان جدولی) - [x] صفحهٔ «وضعیت مالی مشتری» در پنل ادمین (۴ KPI + بدهی‌های ارزی + سفارش‌ها و تراکنش‌ها) - [x] سیستم اعتبار چندارزی کامل (درخواست ۹) — بدهی به همان ارز، تسویه با نرخ روز - [x] ویجت هشدار بدهی‌های ارزی تسویه‌نشده + badge روی منو - [x] Rate Limiting روی همهٔ APIها (۶ لایه throttle: auth / sms / public / customer / wallet / staff) - [x] چک‌لیست خودکار کارمند پس از تأیید سفارش (درخواست ۵) - [x] نمایش بدهی ارزی در پورتال مشتری وردپرس - [x] استایل‌دهی صفحهٔ پروفایل مشتری در وردپرس - [x] پاک‌سازی کد (حذف فایل‌های تستی، تأیید تمیزی `opcache_reset` / `dd` / `dump`) - [x] **سیستم ۴-رُبعی نرخ‌ها** (Export/Import × Doc/Parcel) با ایمپورت از اکسل - [x] **معماری IRR-only** — ارز مبنا = ریال ایران؛ تبدیل ارز در زمان ایمپورت - [x] **فاکتورهای دستی مدیر** — صدور، پرداخت از کیف پول، اعلان خودکار به مشتری چندزبانه (i18n) همچنان به زمان دیپلوی موکول است. ### معماری ارزی (Currency Architecture) > **قاعده طلایی:** ارز مبنا در کل سیستم = **ریال ایران (IRR)**. هیچ واحد دیگری (تومان، درهم، دلار، یورو) در نمایش قیمت‌های داخلی یا ذخیره‌سازی استفاده نمی‌شود. | نوع داده | ارز ذخیره | تبدیل | |---|---|---| | نرخ‌های حمل (`rate_entries`) | IRR | در زمان ایمپورت با نرخ روز | | فاکتورهای دستی (`manual_invoices`) | IRR | مستقیم | | تراکنش‌های کیف پول (`wallet_transactions`) | IRR | مستقیم | | **بدهی‌های ارزی مشتری** (`customer_credits`) | **ارز خارجی** | در زمان تسویه با نرخ روز | **نرخ‌های ارز** از جدول `currencies` خوانده می‌شوند. مدیر به‌صورت دستی یا از API (Exir.io، موقتاً غیرفعال) نرخ را به‌روز می‌کند. API نرخ‌ها با وضعیت `pending` ذخیره می‌شوند و مدیر باید تأیید کند (`approved`). **تفاوت نرخ‌های حمل و بدهی ارزی:** - نرخ‌های حمل به IRR ذخیره می‌شوند (در زمان ایمپورت با نرخ روز تبدیل می‌شوند) — تغییرات نرخ روز روی نرخ‌های ذخیره‌شده اثر ندارد. - بدهی ارزی به ارز خارجی ذخیره می‌شود — در زمان تسویه با نرخ روز محاسبه می‌شود. ### فیچر فاکتورهای دستی مدیر (Manual Invoices) مدیر می‌تواند برای هر مشتری فاکتور صادر کند (برای خدمات خارج از سفارش: انبارداری، مشاوره تلفنی، هزینه‌های جانبی و...). - **پنل ادمین:** `Manual invoices` (گروه «مالی») - **مدل:** `ManualInvoice` + `ManualInvoiceService` + `CustomerInvoiceController` - **جریان:** 1. مدیر فاکتور صادر می‌کند → `status = 'pending_payment'` 2. اعلان خودکار به مشتری ارسال می‌شود (`ManualInvoiceCreatedNotification`) 3. مشتری در پورتال وردپرس فاکتور را می‌بیند (تب «فاکتورهای دستی») 4. با کلیک روی «پرداخت از کیف پول»، مبلغ از کیف پول کسر می‌شود 5. تراکنش با نوع `invoice_payment` در `wallet_transactions` ثبت می‌شود - **شماره فاکتور:** فرمت `INV-YYYY-NNNNNN` (مثلاً `INV-2026-000001`) - **وضعیت‌ها:** `pending_payment` / `paid` / `cancelled` / `expired` - **اعلام در پورتال:** badge قرمز در منوی سایدبار + اعلان در تب اعلان‌ها + ویجت داشبورد + تفکیک در وضعیت مالی ### خط قرمزهای معماری ارزی | ❌ هرگز | ✅ همیشه | |---|---| | ذخیره نرخ‌ها به AED/USD | ذخیره به IRR | | نمایش قیمت به «درهم» در فرم/پورتال | نمایش به «ریال» | | تبدیل در زمان محاسبه قیمت | تبدیل در زمان ایمپورت | | وجود fallback عددی برای نرخ ارز | خطای واضح اگه نرخ تنظیم نشده | | استفاده از «تومان» در کد/UI | فقط «ریال» | --- ## ۲. تکنولوژی‌ها و نسخه‌ها | لایه | تکنولوژی | نسخه / توضیح | |------|-----------|--------------| | Backend | Laravel | 11.x | | زبان | PHP | ^8.2 (۸.۳ نیز پشتیبانی می‌شود) | | پنل مدیریت | Filament | 3.3.x | | فرانت‌اند | WordPress | 7.x + قالب سفارشی IFNEX | | احراز هویت | Laravel Sanctum + Bridge Auth | بدون رمز عبور (کلید API مشترک) | | پرداخت | Zarinpal + Mock Gateway (تست) | کلید sandbox برای تست لوکال | | PDF و بارکد | Dompdf + picqer/php-barcode-generator | AWB، Invoice، Label، فاکتور واردات | | پیامک | Kavenegar | تأیید موبایل + اعلان وضعیت سفارش | | اکسل | maatwebsite/excel + PhpSpreadsheet | Import / Export نرخ‌ها و داده‌های تاریخی | | تاریخ و زمان | morilog/jalali + Carbon | تاریخ شمسی در نمایش، میلادی در DB | | دیتابیس | MySQL | 8.0+ (تست‌ها با SQLite) | | صف | Redis (ترجیحی) / Database | برای پردازش‌های سنگین | | سرور | HestiaCP + Nginx + PHP-FPM | تولید (api.ifnex.vernahost.ir) | --- ## ۳. ساختار دایرکتوری ```text IFNEX-Logistics/ ├── 01_Documents/ # مستندات فنی │ ├── IFNEX_File_Map.md # نقشهٔ ۱۰۰+ فایل پروژه │ ├── IFNEX_Roadmap.md # نقشهٔ راه فازی │ ├── IFNEX_Phase0_Checklist.md # چک‌لیست تکمیل فازها │ ├── IFNEX_ADR.md # تصمیمات معماری (ADR-001 تا 009) │ ├── EXCEL_ANALYSIS.md # تحلیل داده‌های تاریخی │ ├── IFNEX_I18N_Strategy.md # استراتژی چندزبانه │ └── IFNEX_Commercial_Model.md # مدل تجاری │ ├── 03_WordPress/ # فرانت‌اند وردپرس │ └── wp-content/ │ ├── themes/ifnex/ # قالب سفارشی │ └── plugins/ifnex-bridge/ # پلاگین ارتباط با لاراول │ ├── includes/ # api-client، user-bridge، shortcodes، tracking-form │ └── assets/ # CSS و JS فرم سفارش │ ├── 04_Laravel/ # بک‌اند لاراول (هستهٔ اصلی) │ ├── app/ │ │ ├── Enums/ # ShipmentStatus، ShipmentDirection، ShipmentType، PaymentGateway، TransactionStatus │ │ ├── Filament/ # ۱۷ Resource + Pages + Widgets │ │ ├── Http/ │ │ │ ├── Controllers/Api/ # Track، Pricing، Auth، Bridge، Customer، Wallet، Payment، Staff، CommitmentForm │ │ │ └── Middleware/ # ApiKeyMiddleware │ │ ├── Models/ # ۲۶ مدل Eloquent │ │ ├── Notifications/ # DB notifications + SMS │ │ ├── Observers/ # ShipmentObserver │ │ ├── Services/ # PriceCalculator، Pdf، Tracking، OrderPayment، Wallet، Zarinpal، KavenegarSms │ │ ├── Traits/ # Auditable │ │ ├── Imports/ # OldShipments، ShippingRates │ │ └── Exports/ # ShippingRatesTemplateExport │ ├── database/migrations/ # ۵۲ migration │ ├── resources/views/pdfs/ # awb، invoice، label، import-invoice │ └── routes/api.php # ۴۰+ endpoint │ ├── AGENT.md # همین سند ├── CLIENT_DELIVERY.md # چک‌لیست وضعیت تحویل مشتری (منبع اصلی) ├── DEPLOYMENT.md # راهنمای استقرار روی سرور ├── DEPLOYMENT_HANDOFF.md # تحویل استقرار به تیم IT کارفرما └── README.md # معرفی کلی پروژه ``` --- ## ۴. مفاهیم کلیدی بیزینس ### ۴.۱ مرسوله (Shipment) | مورد | مقدار | |------|-------| | انواع (`Type`) | `DOC_NORMAL`، `DOC_ECONOMY`، `PARCEL` | | جهت (`Direction`) | `export` (صادرات) و `import` (واردات) | | وضعیت (`Status`) | `pending_approval` ← `approved` ← `processed` ← `picked_up` ← `in_transit` ← `out_for_delivery` ← `delivered` / `failed` / `returned` / `cancelled` (به‌همراه `pending_payment` legacy و `archived`) | هر مرسوله دارای چند بسته (`packages`)، اقلام گمرکی (`items` — فقط برای PARCEL)، تاریخچهٔ تغییرات وضعیت (`statusHistories`)، شرکت‌های حمل (`carrierMappings`)، رویدادهای رهگیری (`trackingEvents`) و تعهدنامه‌ها (`commitmentForms`) است. ### ۴.۲ بسته (Package) - هر مرسوله می‌تواند چندین بسته داشته باشد (جدول `shipment_packages`). - وزن حجمی = `(Length × Width × Height) / 5000` (استاندارد IATA). - وزن قابل پرداخت = `max(وزن واقعی، وزن حجمی)`. ### ۴.۳ فاکتور گمرکی (Invoice) - فقط برای مرسوله‌های نوع `PARCEL` صادر می‌شود. - حداکثر ۹ قلم کالا (شرح، HS Code، تعداد، قیمت واحد، مجموع به USD). - مجموع کل فاکتور در `shipments.invoice_total_usd` ذخیره می‌شود. - **فاکتور واردات (Import Invoice):** فیلدهای brand_fee، report_fee، customs_clearance_cost، order_registration_fee و… به‌همراه قالب PDF مطابق شیت ENG Invoice. ### ۴.۴ کیف پول (Wallet) - هر کاربر یک کیف پول دارد. - تراکنش‌ها (`WalletTransaction`) با نوع `deposit`، `order_payment`، `refund`، `withdrawal` به‌صورت polymorphic به Payment یا سفارش متصل هستند. - پرداخت از کیف پول یا درگاه Zarinpal (با Mock برای تست)، به‌همراه freeze / unfreeze و activity log کامل. ### ۴.۵ احراز هویت Bridge - کاربران وردپرس بدون نیاز به رمز عبور از طریق `POST /api/v1/bridge/login` با ارسال `bridge_api_key` و `wp_user_id` وارد لاراول می‌شوند. - پاسخ شامل توکن Sanctum (معتبر ۳۰ روز) و اطلاعات کاربر است. - کلید `IFNEX_BRIDGE_API_KEY` باید در هر دو طرف (`.env` لاراول و تنظیمات پلاگین وردپرس) یکسان باشد. - توکن در usermeta کاربر وردپرس (`ifnex_laravel_token`) ذخیره می‌شود و روی ۴۰۱ خودکار باطل و تجدید می‌شود. - کلید `IFNEX_API_KEY` کلید عمومی بخش رهگیری است و `ApiKeyMiddleware` آن را با `!==` مقایسه می‌کند؛ اگر خالی بماند، درخواست با توکن خالی از guard عبور می‌کند. - ⚠️ `BridgeAuthController` فقط مقدار `change-this-secret-key` را رد می‌کند. این مقدار عمداً غیرکارکردی است تا جایگزینی‌اش فراموش نشود — **هر مقدار دیگری، حتی مواردی که شبیه placeholder باشند، یک کلید معتبر محسوب می‌شود.** - 🔐 هرگز کلید واقعی را در این فایل، در `DEPLOYMENT.md` یا در `04_Laravel/README.md` ننویس. مقادیری که قبلاً در این مخزن ثبت شده‌اند را **لو‌رفته فرض کن و چرخش بده.** ### ۴.۶ رهگیری (Tracking) - کاربر با شمارهٔ AWB جستجو می‌کند. - سیستم رویدادهای رهگیری را از جدول `shipment_tracking_events` با فیلد `source` (manual، api، import، system، customer) نمایش می‌دهد. - ایمپورت گروهی وضعیت ترکینگ با CSV از پنل (صفحهٔ BulkTrackingImport) انجام می‌شود. ### ۴.۷ قیمت‌گذاری (Pricing) - بر اساس ۴ زون مجزا (Export/Import × Parcel/Doc) و ۳ نوع سرویس. - فرمول: قیمت پایه (AED) × ضریب سود × نرخ تبدیل به ریال + هزینه‌های جانبی (Packing، Domestic Pickup، …) + مالیات بر ارزش افزوده (۹٪). - محموله‌های بالای ۳۰ کیلوگرم مشمول نرخ ویژه (Spot Rate) هستند و محاسبهٔ آنلاین ندارند. ### ۴.۸ فلوی تأیید سفارش (Approval Flow) - مشتری بعد از ثبت سفارش **مستقیم به درگاه نمی‌رود**؛ سفارش با وضعیت `pending_approval` ثبت می‌شود. - کارمند یا مدیر از پنل فیلمنت (اکشن تأیید در `ShipmentResource`) یا از API (`/staff/orders/{id}/approve|reject`) تأیید می‌کند. - فقط پس از `approved`، گزینه‌های پرداخت (کیف پول / درگاه) در وردپرس باز می‌شود. پرداخت موفق سفارش را `processed` می‌کند (`PaymentController` در callback با `is_order_payment` در metadata). - سفارش‌های `approved` پرداخت‌نشده روی مانده حساب کاربر (`account_balance` در پروفایل) اثر می‌گذارند. ### ۴.۹ تعهدنامه و اسناد سفارش (Commitment Forms) - مدیر فرم‌های تعهدنامه را در فیلمنت (`CommitmentFormResource`) با direction (export / import / both) آپلود می‌کند. - مشتری در جزئیات سفارش وردپرس لیست تعهدنامه‌ها را می‌بیند ← دانلود / چاپ / امضا ← آپلود فایل امضاشده (`POST /orders/{shipment}/commitment-forms/{form}/upload`) که در جدول `shipment_commitment_forms` ثبت می‌شود. - دانلود AWB، Invoice و Label نیز از همین بخش (`/orders/{shipment}/pdf/*`) انجام می‌شود. - ✅ چک مالکیت اعمال شده: `ShipmentPolicy` + بررسی `user_id` در کنترلرهای PDF و تعهدنامه (کامیت `8cf4075`). - دانلود قالب تعهدنامه از route محافظت‌شده با auth (جایگزین asset عمومی) و دانلود ادمین از دیسک secure از طریق روت‌های `admin.commitment-forms.*` انجام می‌شود. ### ۴.۱۰ اعلان‌ها و SMS کاوه‌نگار - تنظیمات از `SystemSetting` خوانده می‌شود (`kavenegar_api_key` به‌همراه سوییچ هر نوع پیام، مانند `kavenegar_send_shipment_approved`). - نوتیفیکیشن‌ها: `ShipmentApprovedSms`، `ShipmentRejectedSms`، `PaymentSuccessSms`، `TrackingUpdatedSms` به‌همراه کانال `SmsChannel`. - تریگر اصلی: `ShipmentObserver` (روی تغییر وضعیت Shipment) و `PaymentController` (پرداخت موفق). تأیید موبایل: `MobileVerificationController`. - در `.env` لوکال کلید کاوه‌نگار خالی است؛ تا وقتی تنظیم نشود SMS ارسال نمی‌شود (فقط DB notification). ### ۴.۱۱ اعتبار مشتری (Credit) — چندارزی - سیستم کامل با `CustomerCreditService` (متدهای `grantCredit()`، `settle()`، `getCustomerDebtsByCurrency()`) و جدول‌های `customer_credits` و `credit_settlements` پیاده‌سازی شده است. - بدهی به همان ارز ثبت می‌شود و تسویه با نرخ روز انجام می‌گیرد. race condition در `settle()` با `lockForUpdate()` و بررسی مجدد مانده اصلاح شد. - فقط `super_admin` مجاز به اعطای اعتبار است (Policy). ### ۴.۱۲ Audit Log - trait `App\Traits\Auditable` روی مدل‌های اصلی (User، Shipment، Wallet و…) اعمال شده و در `AuditLogResource` قابل مشاهده است. - `ShipmentStatusHistory` دارای ستون‌های `from_status` / `to_status` / `reason` به‌همراه نام کاربر تغییردهنده است. ### ۴.۱۳ معماری کیف‌پول‌محور (Wallet-Centric Architecture) سیستم مالی IFNEX بر مبنای **کیف پول مشتری** کار می‌کند. همه پرداخت‌ها از کیف پول عبور می‌کنند. #### ساختار کیف پول: - هر کاربر یک **کیف پول** دارد (`wallets` table) - موجودی کیف پول به **ریال (IRR)** است - تراکنش‌ها در `wallet_transactions` ثبت می‌شوند با نوع‌های: - `deposit` — شارژ کیف پول (از درگاه یا دستی توسط ادمین) - `withdrawal` — برداشت/کسر - `order_payment` — پرداخت سفارش - `refund` — بازگشت وجه - `credit_settlement` — تسویه بدهی ارزی (با نرخ روز) - `invoice_payment` — پرداخت فاکتور دستی #### جریان پرداخت (همه از کیف پول می‌گذرند): | سناریو | مسیر | |---|---| | شارژ کیف پول | درگاه Zarinpal → `walletService->completeDeposit()` → افزایش موجودی | | پرداخت سفارش | `OrderPaymentService->payFromWallet()` → کسر از کیف پول + ثبت `order_payment` | | پرداخت فاکتور دستی | `ManualInvoiceService->payFromWallet()` → کسر از کیف پول + ثبت `invoice_payment` | | تسویه بدهی ارزی | `CustomerCreditService->settle()` (with `$fromWallet=true`) → کسر از کیف پول + ثبت `credit_settlement` | #### مزایای این معماری: - ✅ همه پرداخت‌ها در یک جدول (`wallet_transactions`) ثبت می‌شوند — تاریخچه واحد - ✅ موجودی کیف پول منهای بدهی‌ها = مانده حساب واقعی مشتری - ✅ مدیر می‌تواند موجودی را به‌صورت دستی تنظیم کند (`manualDeposit` / `manualWithdrawal`) - ✅ قفل کیف پول (`freeze`) در همه پرداخت‌ها اعمال می‌شود - ✅ Race condition با `lockForUpdate()` در پرداخت‌های همزمان مدیریت می‌شود #### ویژگی‌های کلیدی مدل Wallet: ```php $wallet->balance // موجودی فعلی (ریال) $wallet->isFrozen() // آیا مسدود است؟ $wallet->hasSufficientBalance($amount) // آیا موجودی کافی است؟ $wallet->freeze($reason, $admin) // مسدود کردن توسط ادمین $wallet->unfreeze($admin) // رفع مسدودیت ``` #### قاعده طلایی: > هیچ پرداختی بدون عبور از کیف پول ثبت نمی‌شود. اگه در آینده درگاه جدیدی اضافه شود (مثلاً Stripe)، باید مبلغ ابتدا به کیف پول واریز شود (`deposit`) و سپس از کیف پول کسر شود (`order_payment` / `invoice_payment`). ### ۴.۱۴ فاکتورهای دستی مدیر (Manual Invoices) مدیر می‌تواند برای هر مشتری فاکتور صادر کند (خدمات خارج از سفارش). مشتری در پورتالش فاکتور را می‌بیند و از کیف پول پرداخت می‌کند. - **مدل:** `ManualInvoice` + `ManualInvoiceService` + `CustomerInvoiceController` - **پنل ادمین:** `ManualInvoiceResource` در گروه «مالی» - **پورتال وردپرس:** تب «فاکتورهای دستی» با badge قرمز برای فاکتورهای pending - **شماره فاکتور:** `INV-YYYY-NNNNNN` (مثلاً `INV-2026-000001`) - **وضعیت‌ها:** `pending_payment` / `paid` / `cancelled` / `expired` - **اعلان خودکار:** `ManualInvoiceCreatedNotification` به مشتری ارسال می‌شود - **پرداخت:** از کیف پول مشتری (کسر + ثبت تراکنش `invoice_payment`) ### ۴.۱۵ نرخ‌های حمل و سیستم ۴-رُبعی نرخ‌های حمل در جدول `rate_entries` به‌صورت **۴-رُبعی** ذخیره می‌شوند: - جهت: `import` / `export` - نوع سرویس: `document` / `parcel` - وزن × زون: ماتریس نگاشت زون‌ها در `country_zones` (هر کشور می‌تواند زون متفاوت برای Doc و Parcel داشته باشد). > **نکته مهم:** `DOC_ECONOMY` فعلاً به همان نرخ `DOC_NORMAL` محاسبه می‌شود. برای تفکیک کامل، باید `service_type` در `rate_entries` به ۳ مقدار گسترش پیدا کند. --- ## ۵. دستورات روزمره ```bash # نصب وابستگی‌ها composer install # تنظیم محیط cp .env.example .env php artisan key:generate # دیتابیس (ابتدا باید ایجاد شود) php artisan migrate --force php artisan db:seed --force # اجرای سرور توسعه php artisan serve # اجرای صف (پردازش‌های سنگین) php artisan queue:work # تست‌ها php artisan test # پاک‌سازی و بازسازی کش php artisan optimize:clear php artisan config:cache php artisan route:cache php artisan view:cache php artisan filament:clear-cached-components # ایمپورت / اکسپورت نرخ‌ها php artisan ifnex:import:rates {path} php artisan ifnex:import:shipments {path} php artisan ifnex:import:tracking {path} # به‌روزرسانی نرخ ارز (کرون) php artisan ifnex:update-rates --source=ecb # تولید API Token برای ادمین php artisan ifnex:token ``` --- ## ۶. متغیرهای محیطی کلیدی (`.env`) ```dotenv APP_ENV=local APP_DEBUG=true APP_URL=http://localhost:8000 DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=ifnex_db DB_USERNAME=root DB_PASSWORD= # IFNEX اختصاصی — پیش از استقرار با رشتهٔ تصادفی جایگزین کن # مقدار change-this-secret-key عمداً غیرکارکردی است تا جایگزینی فراموش نشود IFNEX_API_KEY=change-this-secret-key IFNEX_BRIDGE_API_KEY=change-this-secret-key # باید عیناً با وردپرس یکی باشد IFNEX_TRACKING_RATE_LIMIT=60 # CORS (فقط دامنه‌های مجاز وردپرس) CORS_ALLOWED_ORIGINS=http://localhost,http://127.0.0.1 # Zarinpal (برای تست از Mock استفاده کن) ZARINPAL_MERCHANT_ID=fake-merchant-id-for-testing # اگر fake باشد، MockGateway فعال می‌شود ZARINPAL_SANDBOX=true ZARINPAL_CALLBACK_URL=http://localhost:8000/api/v1/payment/callback ZARINPAL_FRONTEND_FAILURE_URL=http://localhost/IFNEX-Logistics/03_WordPress/wallet # نکته: ZARINPAL_FRONTEND_SUCCESS_URL در کد خوانده نمی‌شود؛ ریدایرکت موفق # از frontend_callback ارسالی وردپرس تعیین می‌شود. # Kavenegar SMS (خالی = فقط DB notification) KAVENEGAR_API_KEY= KAVENEGAR_SENDER=10008566 # Wallet WALLET_MIN_DEPOSIT=10000 WALLET_MAX_DEPOSIT=500000000 WALLET_AUTO_CREATE=true ``` --- ## ۷. خط قرمزها (ممنوعیت‌های مطلق) | ❌ هرگز | ✅ همیشه | |---------|----------| | برگرداندن کشورها به ۲ زون | ۴ زون مجزا (Export/Import × Parcel/Doc) | | استفاده از ۲ نوع سرویس | ۳ نوع (`DOC_NORMAL`، `DOC_ECONOMY`، `PARCEL`) | | ذخیرهٔ تاریخ شمسی در DB | ذخیرهٔ timestamp میلادی + تبدیل در نمایش | | `CORS *` در Production | CORS محدود به دامنهٔ وردپرس | | کامیت `.env` در Git | قرار دادن `.env` در `.gitignore` | | `APP_DEBUG=true` در Production | `APP_DEBUG=false` | | PDF فارسی (AWB / Invoice / Label) | همیشه انگلیسی (برای حمل بین‌المللی) | | کپی از DHL | طراحی منحصر به فرد IFNEX | | استفاده از `wire:click` برای دانلود | استفاده از `` با روت مستقیم | | `getFormActions()` در Custom Pages | استفاده از `wire:click` در Blade | | هدایت AJAX به `redirect()` | استفاده از `payment_url` در response JSON | | متدهای نوتیفیکیشن بیرون از کلاس | داخل کلاس `IFNEX_User_Bridge` | | روت staff/admin بدون چک نقش | چک نقش یا مالکیت در middleware یا ابتدای کنترلر | | هدایت مستقیم سفارش به درگاه پس از ثبت | فلوی `pending_approval` ← `approved` ← پرداخت | | **ذخیره نرخ‌ها به AED/USD** | **ذخیره به IRR (تبدیل در ایمپورت)** | | **نمایش قیمت به «درهم» در UI** | **نمایش به «ریال»** | | **استفاده از «تومان» در کد/UI** | **فقط «ریال»** | | **fallback عددی برای نرخ ارز** | **خطای واضح اگه نرخ تنظیم نشده** | | **تغییر `customer_credits` به IRR** | **بدهی ارزی به ارز خارجی، تسویه با نرخ روز** | --- ## ۸. نکات ویژه برای ایجنت ### اصول کلی - هنگام تولید کد جدید، حتماً از Enum‌ها به‌جای رشته‌های سخت‌کدشده استفاده کن. - برای هر مدل جدید، migration، مدل و در صورت نیاز کنترلر یا Resource فیلمنت بساز. - هنگام استفاده از هر Model در فایل جدید، حتماً `use App\Models\...` را import کن. (باگ اخیر نبودِ import برای `SystemSetting` در `PaymentController` / `ShipmentObserver` / `TrackingService`، فلوی تأیید و پرداخت را می‌شکست — کامیت `2737e26`). - مدیریت تاریخ همیشه با Carbon انجام می‌شود و ذخیره به‌صورت `Y-m-d H:i:s` در DB است. - برای کوئری‌های سنگین از `chunk()` یا `cursor()` استفاده کن تا حافظه مصرف نشود. ### خطاهای رایج - نبودِ فیلد `deleted_at` در کوئری‌ها (در صورت استفاده از SoftDeletes). - فراموشی `fillable` یا `casts` در مدل‌ها. - فراموشی `$with` برای بارگذاری روابط در Resourceها. - استفاده از `redirect()` در کنترلرهای API (باید JSON برگردانند). ### قواعد حوزهٔ کار - برای تغییر وضعیت مرسوله، حتماً تاریخچه را به‌روز کن (`ShipmentStatusHistory` با `from_status` / `to_status` / `reason`). - در فرم سفارش مشتری، مرحلهٔ Invoice فقط برای نوع PARCEL نمایش داده می‌شود. - تولید PDF با بارکد به‌صورت base64 embed انجام می‌شود. - Bridge Auth نیازی به رمز عبور ندارد و فقط از `IFNEX_BRIDGE_API_KEY` استفاده می‌کند. - تست لوکال پرداخت: از `ZARINPAL_MERCHANT_ID=fake-merchant-id-for-testing` برای فعال‌سازی Mock Gateway استفاده کن. ### هشدارهای تاریخی - **مارک‌آپ شورت‌کدهای وردپرس:** باز و بسته بودن `div`ها را متوازن نگه دار. باگ «مرحلهٔ ۲ فرم سفارش لود نمی‌شود» ریشه‌اش یک `div` بسته‌نشده در `shortcodes.php` بود که مراحل را داخل هم nest می‌کرد. هک‌های MutationObserver و setInterval هیچ‌کدام مشکل را حل نکردند و حذف شدند. - **هک‌های موقت دیباگ:** `opcache_reset()` و `header()` در بالای فایل‌های پلاگین و cache-buster با `time()` فقط برای کار لوکال هستند و باید پیش از دیپلوی حذف شوند. --- ## ۹. کارهای باقی‌مانده ### فاز ۳.۶ (اصلاحات جلسه کارفرما) — ✅ تکمیل (۲۰۲۶-۱۰-۰۴) | # | کار | وضعیت | |---|-----|--------| | ۱ | تست انتهای فلوی سفارش: آپلود تعهدنامه ← تأیید کارمند ← پرداخت کیف پول یا درگاه | ✅ | | ۲ | امنیت: چک نقش `/staff/*`، چک مالکیت PDF و تعهدنامه، محدودسازی discount-codes، rate limiting | ✅ | | ۳ | بازطراحی سیستم اعتبار چندارزی + نمایش در پورتال مشتری + ویجت هشدار داشبورد | ✅ | | ۴ | چک‌لیست خودکار کارمند پس از تأیید سفارش | ✅ (`instantiateChecklist()` در `approve()`) | | ۶ | پاک‌سازی: فایل‌های تستی، cache-busterها، `!important`ها | ✅ | | ۷ | نمایش وزن واقعی و حجمی در خلاصهٔ قیمت وردپرس | ✅ (در API موجود است) | ### فاز ۳.۷ (اصلاحات ارزی و فاکتور دستی) — ✅ تکمیل (۲۰۲۶-۱۰-۳۰) | # | کار | وضعیت | |---|-----|--------| | ۱ | **سیستم ۴-رُبعی نرخ‌ها** (Export/Import × Doc/Parcel) با ایمپورت از اکسل | ✅ | | ۲ | **معماری IRR-only** — ارز مبنا = ریال ایران، حذف جفت‌ارز | ✅ | | ۳ | **ایمپورت فایل اکسل اصلی مشتری** + قالب جدید `IFNEX_Rate_Template.xlsx` | ✅ | | ۴ | **حذف تمام «تومان» و «درهم» از نمایش قیمت‌های داخلی** | ✅ | | ۵ | **فاکتورهای دستی مدیر** (صدور + پرداخت از کیف پول + اعلان خودکار) | ✅ | | ۶ | **تب «فاکتورهای دستی» در پورتال وردپرس** (لیست + جزئیات + پرداخت) | ✅ | | ۷ | **اضافه شدن فاکتورها به وضعیت مالی و داشبورد مشتری** | ✅ | | ۸ | **فرمت هزارگان در فیلدهای عددی فرم فاکتور ادمین** | ✅ | ### فاز ۳.۸ (موکول به آینده) | # | کار | وضعیت | اولویت | |---|-----|--------|---------| | ۱ | چندزبانه (i18n) | ⏳ موکول به زمان دیپلوی | متوسط | | ۲ | سند پیشنهادی سیستم مالی (درخواست ۱۳ کارفرما) | ⏳ موکول به آینده | پایین | | ۳ | پلاگین SMS (به‌صورت ماژول قابل فعال‌سازی) | ⏳ منتظر پنل SMS مشتری | متوسط | | ۴ | لاین واردات از چین (ماژول مجزا) | ⏳ مطالعاتاتی | پایین | | ۵ | دفترچه آدرس (Address Book) مشتری | 📋 مطرح‌شده | متوسط | | ۶ | **ارز مرجع قابل تنظیم** (نسخه Pro) | 📋 مطرح‌شده — `01_Documents/IFNEX_Pro_Backlog.md` | پایین (نسخه Pro) | | ۷ | سیستم بروزرسانی + لایسنس (Domain Lock) | 📋 مطرح‌شده — `01_Documents/IFNEX_Pro_Backlog.md` | پایین (نسخه Pro) | | ۸ | favicon و صفحه `/` سفارشی لاراول | 📋 | پایین | | ۹ | بازطراحی صفحه لاگین لاراول | 📋 | پایین | --- ## ۱۰. مستندات مرجع | فایل | محتوا | |------|-------| | `01_Documents/EXCEL_ANALYSIS.md` | تحلیل کامل فایل‌های اکسل (۳۹۵۰ رکورد، فرمول‌ها، زون‌ها) | | `01_Documents/IFNEX_Phase0_Checklist.md` | چک‌لیست کامل فازها (۰ تا ۳.۵) | | `01_Documents/IFNEX_Roadmap.md` | نقشهٔ راه فازی (تا فاز ۳.۶) | | `01_Documents/IFNEX_File_Map.md` | نقشهٔ ۱۰۰+ فایل پروژه | | `01_Documents/IFNEX_I18N_Strategy.md` | استراتژی چندزبانه (برای زمان دیپلوی) | | `01_Documents/IFNEX_Commercial_Model.md` | مدل تجاری و پلن‌های فروش | | `01_Documents/IFNEX_Pro_Backlog.md` | فیچرهای نسخه Pro (ارز مرجع قابل تنظیم، لایسنس، آپدیت) | | `01_Documents/DESIGN_SYSTEM.md` | رنگ‌ها، تایپوگرافی، فاصله‌گذاری | | `DEPLOYMENT.md` | راهنمای ایمپورت نرخ‌ها (سیستم ۴-رُبعی) | | `DEPLOYMENT_HANDOFF.md` | تحویل استقرار به تیم IT کارفرما | | `04_Laravel/README.md` | راهنمای بک‌اند | | `CLIENT_DELIVERY.md` | چک‌لیست وضعیت تحویل مشتری (منبع اصلی وضعیت تحویل) |