ifnex/AGENT.md
Kazem Alghasi 7fb20b4afb docs: update project documentation and roadmap status
Update AGENT.md, CLIENT_DELIVERY.md, and README.md to reflect the
completion of Phase 3.6 milestones.

- Update project status from 80% to 95% completion
- Document E2E verification of the commitment form and order approval flows
- Detail the implementation of the multi-currency credit system and
  customer financial overview
- Update the employee checklist automation details
- Document the redesigned PDF templates (AWB, Invoice, Label) using
  dompdf
- Include newly implemented security features like 6-layer API rate
  limiting
- Reflect code cleanup activities including removal of debug tools and
  test files
2026-10-04 02:32:59 +03:30

296 lines
21 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

🎯 خلاصه پروژه
سیستم مدیریت لجستیک بین‌المللی با معماری Headless (Laravel 11 به‌عنوان بک‌اند، WordPress به‌عنوان فرانت‌اند، Filament 3.3 به‌عنوان پنل مدیریت). جایگزین فرآیندهای دستی مبتنی بر اکسل شده و از Multi-Package، فاکتور گمرکی (Invoice)، کیف پول دیجیتال، درگاه پرداخت Zarinpal، تولید PDF با بارکد، فلوی تأیید سفارش، تعهدنامه، SMS کاوه‌نگار، سیستم اعتبار چندارزی و سیستم رهگیری پیشرفته پشتیبانی می‌کند.
وضعیت فعلی: فازهای ۰، ۱، ۲، ۳ و ۳.۵ تکمیل شده‌اند. فاز ۳.۶ (اصلاحات جلسه کارفرما) حدود ۹۵٪ انجام شده است. در این جلسه موارد زیر تکمیل شد:
✅ فلوی کامل سفارش (ثبت → تأیید → تعهدنامه → پرداخت) E2E تست شد
✅ بازطراحی داشبورد + لاگین Filament (navy+amber brand identity)
✅ بازطراحی AWB + Invoice + Label PDF (dompdf, table-based)
✅ صفحه «وضعیت مالی مشتری» در پنل ادمین (۴ KPI + بدهی‌های ارزی + سفارشات/تراکنش‌ها)
✅ سیستم اعتبار چندارزی کامل (درخواست ۹) — بدهی به همان ارز، تسویه با نرخ روز
✅ ویجت هشدار بدهی‌های ارزی تسویه‌نشده + badge روی منو
✅ Rate Limiting روی همه APIها (۶ لایه: auth/sms/public/customer/wallet/staff)
✅ چک‌لیست خودکار کارمند بعد از تأیید سفارش (درخواست ۵)
✅ نمایش بدهی ارزی در پورتال مشتری وردپرس
✅ استایل‌دهی صفحه پروفایل مشتری در وردپرس
✅ پاک‌سازی کد (حذف فایل‌های تستی، تأیید تمیزی opcache_reset/dd/dump)
چندزبانه (i18n) همچنان به زمان دیپلوی موکول است.
---
## 🧰 تکنولوژی‌ها و نسخه‌ها
| لایه | تکنولوژی | نسخه / توضیح |
|------|-----------|--------------|
| **Backend** | Laravel | 11.x |
| **PHP** | PHP | ^8.2 (۸.۳ نیز پشتیبانی می‌شود) |
| **Admin Panel** | Filament | 3.3.x |
| **Frontend** | WordPress | 7.x + قالب سفارشی IFNEX |
| **Authentication** | Laravel Sanctum + Bridge Auth | بدون رمز عبور (API Key مشترک) |
| **Payment** | Zarinpal + Mock Gateway (تست) | کلید sandbox برای تست لوکال |
| **PDF & Barcode** | Dompdf + picqer/php-barcode-generator | تولید AWB، Invoice، Label، فاکتور واردات |
| **SMS** | Kavenegar | تأیید موبایل + اعلان وضعیت سفارش |
| **Excel** | maatwebsite/excel | Import/Export نرخ‌ها و داده‌های تاریخی |
| **Date/Time** | morilog/jalali + Carbon | تاریخ شمسی در نمایش، میلادی در DB |
| **Database** | MySQL | 8.0+ (تست‌ها با SQLite) |
| **Queue** | Redis (ترجیح) / Database | برای پردازش‌های سنگین |
| **Server** | HestiaCP + Nginx + PHP-FPM | تولید (api.ifnex.vernahost.ir) |
---
## 📂 ساختار دایرکتوری (کلیدی)
```
IFNEX-Logistics/
├── 01_Documents/ # مستندات فنی (تحلیل اکسل، نقشه راه، چک‌لیست، ...)
├── 03_WordPress/ # فرانت‌اند وردپرس
│ ├── wp-content/themes/ifnex/ # قالب سفارشی
│ └── wp-content/plugins/ifnex-bridge/ # پلاگین ارتباط با لاراول
├── 04_Laravel/ # بک‌اند لاراول (هسته اصلی)
│ ├── app/
│ │ ├── Enums/ # ShipmentStatus, ShipmentDirection, ShipmentType, PaymentGateway, TransactionStatus
│ │ ├── Filament/ # ۱۷ Resource + Pages (Settings, ImportRates, BulkTrackingImport, FinancialReport) + Widgets
│ │ ├── Http/Controllers/Api/ # Track, Pricing, Auth, Bridge, Customer, Wallet, Payment, Staff, CommitmentForm, ...
│ │ ├── Http/Middleware/ # ApiKeyMiddleware
│ │ ├── Models/ # ۲۲ مدل (Shipment, ShipmentPackage, CommitmentForm, Wallet, ...)
│ │ ├── Notifications/ # DB notifications + SMS (ShipmentApprovedSms, PaymentSuccessSms, SmsChannel, ...)
│ │ ├── Observers/ # ShipmentObserver (تریگر نوتیفیکیشن/SMS روی تغییر وضعیت)
│ │ ├── Services/ # PriceCalculator, Pdf, Tracking, OrderPayment, Wallet, Zarinpal, KavenegarSms
│ │ ├── Traits/ # Auditable
│ │ ├── Imports/ # OldShipmentsImport, ShippingRatesImport
│ │ └── Exports/ # ShippingRatesTemplateExport
│ ├── database/migrations/ # ۵۲ migration
│ ├── resources/views/pdfs/ # awb, invoice, label, import-invoice (با بارکد)
│ └── routes/api.php # ۴۰+ endpoint
├── AGENT.md # همین سند
├── CLIENT_DELIVERY.md # چک‌لیست وضعیت تحویل مشتری (منبع اصلی وضعیت تحویل)
├── DEPLOYMENT.md # راهنمای استقرار در سرور
└── 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` وارد لاراول می‌شوند.
- پاسخ شامل `token` Sanctum (معتبر ۳۰ روز) و اطلاعات کاربر است.
- کلید `IFNEX_BRIDGE_API_KEY` باید در هر دو طرف (`.env` لاراول و تنظیمات پلاگین وردپرس) یکسان باشد.
- توکن در usermeta کاربر وردپرس (`ifnex_laravel_token`) ذخیره می‌شود و روی 401 خودکار باطل/تجدید می‌شود.
### ۶. رهگیری (Tracking)
- کاربر با شماره AWB جستجو می‌کند.
- سیستم رویدادهای رهگیری را از جدول `shipment_tracking_events` با `source` (manual, api, import, system, customer) نمایش می‌دهد.
- ایمپورت گروهی وضعیت ترکینگ با CSV از پنل (صفحه BulkTrackingImport).
### ۷. قیمت‌گذاری (Pricing)
- بر اساس ۴ زون مجزا (Export/Import × Parcel/Doc) و ۳ نوع سرویس.
- فرمول: قیمت پایه (AED) × ضریب سود × نرخ تبدیل به ریال + هزینه‌های جانبی (Packing, Domestic Pickup, ...) + VAT (۹٪).
- محموله‌های بالای ۳۰ کیلوگرم مشمول نرخ ویژه (Spot Rate) هستند و محاسبه آنلاین ندارند.
### ۸. فلوی تأیید سفارش (Approval Flow)
- مشتری بعد از ثبت سفارش، **مستقیم به درگاه نمی‌رود**؛ سفارش با وضعیت `pending_approval` ثبت می‌شود.
- کارمند/مدیر از پنل فیلمنت (اکشن تأیید در ShipmentResource) یا API (`/staff/orders/{id}/approve|reject`) تأیید می‌کند.
- فقط بعد از `approved`، گزینه‌های پرداخت (کیف پول / درگاه) در وردپرس باز می‌شود؛ پرداخت موفق سفارش را `processed` می‌کند (PaymentController در callback با `is_order_payment` در metadata).
- سفارش‌های `approved` (پرداخت‌نشده) روی مانده حساب کاربر (account_balance در profile) اثر می‌گذارند.
### ۹. تعهدنامه و اسناد سفارش (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) — نیمه‌کاره
- فعلاً فقط دو ستون `credit_limit/credit_used` روی جدول users + `CustomerCreditResource` در فیلمنت.
- ⚠️ اکشن‌های افزایش/کاهش اعتبار هنوز روی ستون‌های ناموجود `wallet_transactions.user_id` و تایپ‌های `credit_add/credit_reduce` می‌نویسند (خراب) و اعتبار در فلوی سفارش/پرداخت هم استفاده نشده.
- نیاز کارفرما: بدهی به **ارز سفارش** (مثلاً ۵۰ یورو بدهکار) + تسویه ریالی با نرخ روز → نیاز به بازطراحی دارد.
### ۱۲. Audit Log
- trait `App\Traits\Auditable` روی مدل‌های اصلی (User, Shipment, Wallet, ...) اعمال شده و در `AuditLogResource` قابل مشاهده است.
- `ShipmentStatusHistory` با ستون‌های `from_status/to_status/reason` + ثبت نام کاربر تغییردهنده.
---
## ⚙️ دستورات روزمره (برای ایجنت)
```bash
# نصب وابستگی‌ها
composer install
# تنظیم محیط
cp .env.example .env
php artisan key:generate
# دیتابیس (ابتدا باید ایجاد شود)
php artisan migrate --force
php artisan db:seed --force
# اجرای سرور توسعه
php artisan serve
# اجرای Queue (برای پردازش‌های سنگین)
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)
```env
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 اختصاصی
IFNEX_API_KEY=ifnex-local-dev-key
IFNEX_BRIDGE_API_KEY=ifnex-bridge-secret-key-2026-vernasoft # باید با وردپرس یکی باشد
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_SUCCESS_URL=http://localhost/IFNEX-Logistics/03_WordPress/wallet
ZARINPAL_FRONTEND_FAILURE_URL=http://localhost/IFNEX-Logistics/03_WordPress/wallet
# 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 | در .gitignore باشد |
| APP_DEBUG=true در Production | APP_DEBUG=false |
| PDF فارسی (AWB/Invoice/Label) | همیشه انگلیسی (برای حمل بین‌المللی) |
| کپی از DHL | طراحی منحصر به فرد IFNEX |
| استفاده از wire:click برای دانلود | استفاده از `<a href>` با روت مستقیم |
| getFormActions() در Custom Pages | استفاده از wire:click در Blade |
| هدایت AJAX به redirect() | استفاده از payment_url در response JSON |
| متدهای نوتیفیکیشن بیرون از کلاس | داخل کلاس IFNEX_User_Bridge |
| روت staff/admin بدون چک نقش | چک نقش/مالکیت در middleware یا ابتدای کنترلر |
| سفارش مستقیم به درگاه بعد از ثبت | فلوی pending_approval → approved → پرداخت |
## 📌 نکات ویژه برای ایجنت
- هنگام تولید کد جدید، حتماً از Enum‌ها به جای رشته‌های سخت‌کد شده استفاده کن.
- برای هر مدل جدید، migration، مدل، و در صورت نیاز کنترلر/ریسورس Filament بساز.
- خطاهای رایج:
- عدم وجود فیلد 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 استفاده کن.
- مدیریت تاریخ: همیشه از Carbon استفاده کن و تاریخ را به‌صورت Y-m-d H:i:s در DB ذخیره کن.
- برای کوئری‌های سنگین، از chunk() یا cursor() استفاده کن تا حافظه مصرف نشود.
- **هنگام استفاده از هر Model در فایل جدید، حتماً `use App\Models\...` را import کن** — باگ اخیر `SystemSetting` در PaymentController/ShipmentObserver/TrackingService فلوی تأیید/پرداخت را می‌شکست (در کامیت `2737e26` رفع شد).
- **در مارک‌آپ شورت‌کدهای وردپرس، باز/بسته بودن div ها را متوازن نگه دار** — باگ «مرحله ۲ فرم سفارش لود نمی‌شود» ریشه‌اش یک div بسته‌نشده در shortcodes.php بود که مراحل را داخل هم nest می‌کرد؛ هک‌های MutationObserver/setInterval هیچ‌کدام مشکل را حل نمی‌کردند و حذف شدند.
- **هک‌های موقت دیباگ** (`opcache_reset()` و `header()` بالای فایل‌های پلاگین، cache-buster با `time()`) فقط برای کار لوکال هستند و قبل از دیپلوی باید حذف شوند.
## 🧭 کارهای باقی‌مانده (فاز ۳.۶ — به‌روزرسانی 2026-10-04)
# کار وضعیت
1 تست انتهای فلوی سفارش: آپلود تعهدنامه → تأیید کارمند → پرداخت کیف پول/درگاه ✅ انجام شد (2026-10-04) — فلوی کامل E2E تأیید شد
2 امنیت: چک نقش /staff/* ✅، چک مالکیت PDF/تعهدنامه ✅، محدودسازی discount-codes ✅، rate limiting ✅ (۶ لایه throttle) ✅ انجام شد (2026-10-04)
3 بازطراحی سیستم اعتبار (بدهی چندارزی) + نمایش در پورتال مشتری + ویجت هشدار داشبورد ✅ انجام شد (2026-10-04) — CustomerCreditService کامل + race condition اصلاح شد
4 چک‌لیست خودکار کارمند بعد از تأیید سفارش ✅ انجام شد — instantiateChecklist() در approve() صدا زده می‌شود
5 سند پیشنهادی سیستم مالی (درخواست ۱۳ کارفرما) ⏳ موکول به آینده
6 پاک‌سازی: فایل‌های تستی، cache-busterها، !important ها ✅ انجام شد (2026-10-04) — test_pdf_generation.php حذف شد؛ opcache_reset/dd() پاک؛ !important‌ها ضروری و نگه‌داشته شدند
7 نمایش وزن واقعی/حجمی در خلاصه قیمت وردپرس ✅ در API موجود است (weight + volumetric_weight در پاسخ)
8 چندزبانه (i18n) — به زمان دیپلوی موکول شده ⏳ دیپلوی
وضعیت کلی فاز ۳.۶: ~۹۵٪ تکمیل. تنها موارد باقی‌مانده: i18n (زمان دیپلوی) + سند پیشنهادی مالی (آینده).
---
## 📚 مستندات مرجع (برای مطالعه بیشتر)
| فایل | محتوا |
|------|-------|
| 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/DESIGN_SYSTEM.md | رنگ‌ها، تایپوگرافی، فاصله‌گذاری |
| DEPLOYMENT.md | راهنمای کامل استقرار روی سرور |
| 04_Laravel/README.md | راهنمای بک‌اند |
---
تاریخ: 2026-10-04
نسخه: 1.3
تهیه‌کننده: VernaSoft Group — Kazem Alghasi