- Add DEPLOYMENT_HANDOFF.md for client IT team with full production steps - Fix ApiKeyMiddleware: correct Response import and fail-closed on unset key - Remove committed Bridge API secret from all tracked docs - Document seed, admin provisioning, WP user sync, Kavenegar, and wp-config hardening - Reformat AGENT.md, README.md, CLIENT_DELIVERY.md to consistent structure
24 KiB
راهنمای ایجنت — پروژهٔ IFNEX Logistics
تاریخ: ۲۰۲۶-۱۰-۰۴ نسخه: ۱.۳ تهیهکننده: VernaSoft Group — Kazem Alghasi
۱. خلاصهٔ پروژه
سیستم مدیریت لجستیک بینالمللی با معماری Headless: Laravel 11 بهعنوان بکاند، WordPress بهعنوان فرانتاند و Filament 3.3 بهعنوان پنل مدیریت. این سیستم جایگزین فرآیندهای دستی مبتنی بر اکسل شده و از Multi-Package، فاکتور گمرکی، کیف پول دیجیتال، درگاه پرداخت Zarinpal، تولید PDF با بارکد، فلوی تأیید سفارش، تعهدنامه، SMS کاوهنگار، سیستم اعتبار چندارزی و رهگیری پیشرفته پشتیبانی میکند.
وضعیت فعلی
فازهای ۰، ۱، ۲، ۳ و ۳.۵ تکمیل شدهاند. فاز ۳.۶ (اصلاحات جلسهٔ کارفرما) حدود ۹۵٪ انجام شده است:
- فلوی کامل سفارش (ثبت ← تأیید ← تعهدنامه ← پرداخت) — تست End-to-End
- بازطراحی داشبورد و Login پنل Filament (هویت بصری navy + amber)
- بازطراحی PDFهای AWB، Invoice و Label (dompdf، چیدمان جدولی)
- صفحهٔ «وضعیت مالی مشتری» در پنل ادمین (۴ KPI + بدهیهای ارزی + سفارشها و تراکنشها)
- سیستم اعتبار چندارزی کامل (درخواست ۹) — بدهی به همان ارز، تسویه با نرخ روز
- ویجت هشدار بدهیهای ارزی تسویهنشده + badge روی منو
- Rate Limiting روی همهٔ APIها (۶ لایه throttle: auth / sms / public / customer / wallet / staff)
- چکلیست خودکار کارمند پس از تأیید سفارش (درخواست ۵)
- نمایش بدهی ارزی در پورتال مشتری وردپرس
- استایلدهی صفحهٔ پروفایل مشتری در وردپرس
- پاکسازی کد (حذف فایلهای تستی، تأیید تمیزی
opcache_reset/dd/dump)
چندزبانه (i18n) همچنان به زمان دیپلوی موکول است.
۲. تکنولوژیها و نسخهها
| لایه | تکنولوژی | نسخه / توضیح |
|---|---|---|
| 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 | Import / Export نرخها و دادههای تاریخی |
| تاریخ و زمان | morilog/jalali + Carbon | تاریخ شمسی در نمایش، میلادی در DB |
| دیتابیس | MySQL | 8.0+ (تستها با SQLite) |
| صف | Redis (ترجیحی) / Database | برای پردازشهای سنگین |
| سرور | HestiaCP + Nginx + PHP-FPM | تولید (api.ifnex.vernahost.ir) |
۳. ساختار دایرکتوری
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بههمراه نام کاربر تغییردهنده است.
۵. دستورات روزمره
# نصب وابستگیها
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)
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 برای دانلود |
استفاده از <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، مدل و در صورت نیاز کنترلر یا 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 موجود است (weight + volumetric_weight در پاسخ) |
| ۸ | چندزبانه (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 |
راهنمای کامل استقرار روی سرور |
DEPLOYMENT_HANDOFF.md |
تحویل استقرار به تیم IT کارفرما |
04_Laravel/README.md |
راهنمای بکاند |
CLIENT_DELIVERY.md |
چکلیست وضعیت تحویل مشتری (منبع اصلی وضعیت تحویل) |