some edites and readme texts

This commit is contained in:
Kazem Alghasi 2026-08-02 04:50:17 +03:30
parent 50940d4ee8
commit 4ce5fa8f96
3 changed files with 260 additions and 65 deletions

View File

@ -3,8 +3,12 @@
namespace App\Filament\Resources\ShipmentResource\Pages;
use App\Filament\Resources\ShipmentResource;
use App\Imports\OldShipmentsImport; // اضافه شدن کلاس ایمپورت صحیح
use Filament\Actions;
use Filament\Actions\Action; // اضافه شدن اکشن
use Filament\Forms\Components\FileUpload; // اضافه شدن فایل آپلود
use Filament\Resources\Pages\ListRecords;
use Maatwebsite\Excel\Facades\Excel;
class ListShipments extends ListRecords
{
@ -13,6 +17,35 @@ class ListShipments extends ListRecords
protected function getHeaderActions(): array
{
return [
// دکمه ایمپورت اکسل قدیمی
Action::make('import-old-shipments')
->label('آپلود اکسل سفارشات قدیمی')
->icon('heroicon-o-arrow-up-tray')
->color('warning') // رنگ زرد برای قدیمی بودن
->form([
FileUpload::make('file')
->label('فایل اکسل شیت List')
->required()
->directory('excel') // ذخیره موقت در این پوشه
->acceptedFileTypes([
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // اصلاح میم‌تایپ xlsx
'application/vnd.ms-excel' // xls
])
])
->action(function (array $data) {
// پاس دادن مسیر فایل آپلود شده به کلاس ایمپورت
Excel::import(new OldShipmentsImport, $data['file']);
\Illuminate\Support\Facades\Cache::forget('shipments_list');
\Filament\Notifications\Notification::make()
->title('عملیات موفق')
->body('سفارشات با موفقیت از فایل اکسل وارد دیتابیس شدند.')
->success()
->send();
}),
// دکمه‌های پیش‌فرض
Actions\CreateAction::make(),
];
}

View File

@ -0,0 +1,104 @@
<?php
namespace App\Imports;
use App\Models\Shipment;
use Maatwebsite\Excel\Concerns\OnEachRow;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithStartRow;
class OldShipmentsImport implements OnEachRow, WithHeadingRow, WithStartRow
{
/**
* چون ممکنه در فایل اکسل چندین سطر اول هدر هستند، می‌اییم ۳ سطر اول رو رد کنیم.
* هدر اصلی معمولاً ردیف ۱۰ یا ۱۱ هست.
*/
protected int $startRow = 3;
/**
* متد الزامی برای WithStartRow
*/
public function startRow(): int
{
return $this->startRow;
}
/**
* تبدیل تاریخ شمسی/میلادی به میلادی برای ذخیره در دیتابیس
*/
private function convertDateToGregorian($dateStr)
{
if (preg_match('/\d{4}\/\d{2}\/\d{2,4}/', $dateStr)) {
$parts = explode('/', $dateStr);
if (strlen($parts[2]) === 4) {
list($y, $m, $d) = $parts;
return "$y-$m-$d";
}
}
return $dateStr;
}
public function onRow(\Maatwebsite\Excel\Row $row)
{
$rowIndex = $row->getIndex();
$cells = $row->toArray();
// ۱. ردیف‌های خالی یا هدرها را رد کنیم
if (empty($cells[1]) || in_array($cells[1], ['HAWB No.', 'Date', 'Forwarder', 'Shipper']) || in_array($cells[0], ['HEAD', 'List'])) {
return;
}
// ۲. استخراج داده‌ها (بر اساس شیت لیست شما)
$data = [
'awb_no' => $cells[0],
'direction' => 'Outbound', // طبق اکسل شما بیشتر صادرات است
'type' => $cells[8] === 'DOC' ? 'DOC' : 'NON DOC',
'status' => $cells[18] ?? 'Processed', // فیلد Last State
'reason_for_export' => $cells[17] ?? '',
'weight' => is_numeric($cells[11]) ? $cells[11] : 0,
'volumetric_weight' => is_numeric($cells[12]) ? $cells[12] : 0,
'chargeable_weight' => is_numeric($cells[13]) ? $cells[13] : 0,
'dimensions' => trim(($cells[14] ?? '') . ' * ' . ($cells[15] ?? '') . ' * ' . ($cells[16] ?? '')),
// اصلاح تداخل ایندکس: ایندکس 18 برای status رزرو شد، قیمت را از ایندکس بعدی شروع کردیم
'shipping_price' => is_numeric($cells[19] ?? null) ? $cells[19] : 0,
'extra_service' => is_numeric($cells[20] ?? null) ? $cells[20] : 0,
'packing_cost' => is_numeric($cells[21] ?? null) ? $cells[21] : 0,
'discount' => is_numeric($cells[22] ?? null) ? $cells[22] : 0,
'total_fee' => is_numeric($cells[23] ?? null) ? $cells[23] : 0,
'net_dirham' => is_numeric($cells[25] ?? null) ? $cells[25] : 0,
'net_rial' => is_numeric($cells[26] ?? null) ? $cells[26] : 0,
'sender_name' => $cells[2],
'sender_company' => '',
'sender_phone' => $cells[3],
'sender_email' => $cells[4],
'sender_address' => $cells[5],
'sender_city' => $cells[6],
'sender_zip' => $cells[7],
'sender_id_number' => '',
'receiver_name' => $cells[9],
'receiver_company' => '',
'receiver_phone' => $cells[10],
// اصلاح تداخل ایندکس: ایندکس 11 مربوط به weight است، ایمیل گیرنده را به ایندکس بعدی منتقل کردیم
'receiver_email' => $cells[12] ?? '',
// رفع خطای متغیر ناموجود: خواندن مستقیم از cells به جای data
'receiver_address' => ($cells[5] ?? '') . ' ' . ($cells[6] ?? ''),
'receiver_city' => $cells[6] ?? '',
'receiver_zip' => $cells[13],
'receiver_id_number' => $cells[14],
'user_id' => 1, // به صورت پیش‌فرض برای سفارشات قدیمی که کاربر خاصی ندارند
];
// ۳. تبدیل تاریخ (Date)
if (!empty($cells[1])) {
$data['created_at'] = $this->convertDateToGregorian($cells[1]);
}
// ۴. ذخیره یا آپدیت در دیتابیس
Shipment::updateOrCreate(
['awb_no' => $data['awb_no']],
$data
);
}
}

188
README.md
View File

@ -1,103 +1,161 @@
# 🚀 IFNEX Logistics Management System
> Replacing Manual Excel Workflows with a Modern Headless Architecture
> جایگزینی فرآیندهای دستی مبتنی بر اکسل با یک معماری Headless مدرن
![Laravel](https://img.shields.io/badge/Laravel-12-FF2D20?style=for-the-badge&logo=laravel&logoColor=white)
![WordPress](https://img.shields.io/badge/WordPress-6.x-21759B?style=for-the-badge&logo=wordpress&logoColor=white)
![PHP](https://img.shields.io/badge/PHP-8.2+-777BB4?style=for-the-badge&logo=php&logoColor=white)
![MySQL](https://img.shields.io/badge/MySQL-8.0-4479A1?style=for-the-badge&logo=mysql&logoColor=white)
**Author:** VernaSoft Group (Kazem Alghasi)
| مورد | توضیحات |
| :--- | :--- |
| **ویرایش سند** | v2.0 (نقشه راه ۴ فازی) |
| **توسعه‌دهنده** | VernaSoft Group — Kazem Alghasi |
| **مشتری** | شرکت حمل و نقل بین‌المللی ایف‌نکس (IFNEX) — اصفهان |
---
## 📖 درباره پروژه
سیستم مدیریت لجستیک ایف‌نکس (IFNEX) یک راه‌حل جامع برای جایگزینی فرآیندهای مبتنی بر فایل‌های اکسل در شرکت‌های حمل و نقل بین‌المللی است. این سیستم با استفاده از معماری هدلس (Headless)، وردپرس را برای ظاهر سایت و سئو، و لاراول را به عنوان قلب تپنده و موتور محاسباتی به کار می‌گیرد.
سیستم مدیریت لجستیک ایف‌نکس (IFNEX) یک راه‌حل جامع برای جایگزینی فرآیندهای مبتنی بر فایل‌های اکسل در شرکت‌های حمل و نقل بین‌المللی است. این سیستم با استفاده از معماری Headless، وردپرس را برای ظاهر سایت و سئو، و لاراول را بهعنوان قلب تپنده و موتور محاسباتی به کار می‌گیرد.
### چرا این پروژه متفاوت است؟
به جای اینکه اپراتورها وزن حجمی را محاسبه کنند، زون‌ها را در ۴ شیت مختلف جستجو کنند و با ماشین حساب قیمت نهایی را حساب کنند، اکنون تمام این فرآیند در کسر از ثانیه و بدون هیچ خطای انسانی انجام می‌شود.
به‌جای آنکه اپراتورها وزن حجمی را محاسبه کنند، زون‌ها را در ۴ شیت مختلف جستجو کنند و با ماشینحساب قیمت نهایی را حساب کنند، اکنون تمام این فرآیند در کسر از ثانیه و بدون هیچ خطای انسانی انجام می‌شود. همچنین، به دلیل تحریم‌های بین‌المللی و مسدود بودن دسترسی مستقیم به API شرکت‌های DHL/FedEx/UPS از ایران، این سیستم از طریق یک سرور VPS پل (در فاز ۳) مشکل ترکینگ خودکار را حل می‌کند.
---
## 🏗️ معماری سیستم (Tech Architecture)
سیستم بر اساس الگوی Headless توسعه یافته است. این یعنی فرانت‌اند (وردپرس) و بک‌اند (لاراول) کاملاً از هم جدا شده‌اند و فقط از طریق REST API با هم ارتباط دارند.
## 🏗️ معماری سیستم
سیستم بر اساس الگوی Headless توسعه یافته است. فرانت‌اند (وردپرس) و بک‌اند (لاراول) کاملاً از هم جدا شده‌اند و فقط از طریق REST API با هم ارتباط دارند.
- **فرانت‌اند (WordPress):** وظیفه مدیریت ظاهر، منوها، لندینگ پیج‌ها (طراحی شده مشابه DHL) و سئو.
- **بک‌اند (Laravel 12):** وظیفه مدیریت دیتابیس، پنل ادمین (Filament)، موتور فرمول‌نویسی قیمت، و ارائه API ها.
- **پل ارتباطی (Custom WP Plugin):** یک پلاگین اختصاصی برای وردپرس که درخواست‌های کاربران را به لاراول ارسال می‌کند.
| لایه | تکنولوژی | نقش |
| :--- | :--- | :--- |
| **فرانت‌اند** | WordPress | مدیریت ظاهر، منوها، لندینگ پیج‌ها، صفحات ثابت، وبلاگ سئو |
| **بک‌اند** | Laravel 11 | API سرور، پنل ادمین (Filament)، موتور قیمت‌گذاری، صدور PDF، کیف پول |
| **پل ارتباطی** | پلاگین اختصاصی IFNEX Bridge | ارسال درخواست‌های کاربر از وردپرس به لاراول |
| **زیرساخت رهگیری** | VPS خارج از کشور (در فاز ۳) | واسط برای دسترسی به APIهای رهگیری بین‌المللی |
---
## ✨ ویژگی‌های کلیدی (فاز ۱ - تکمیل شده)
## 🗺️ نقشه راه ۴ فازی
این پروژه به چهار فاز تقسیم شده تا هم تحویل تدریجی ارزش به مشتری حفظ شود و هم ریسک دوباره‌کاری حذف گردد.
### ۱. موتور قیمت‌گذاری هوشمند (Pricing Engine)
محاسبه دقیق هزینه ارسال بر اساس فرمول‌های استاندارد جهانی:
- محاسبه خودکار وزن حجمی `(طول × عرض × ارتفاع / 5000)`.
- استخراج خودکار زون مقصد بر اساس جدول کشورها و نوع ارسال (صادرات/واردات).
- اعمال نرخ لحظه‌ای ارز (درهم/دلار/یوان/یورو) و ضریب سود شرکت.
| فاز | هدف اصلی | مدت زمان | وضعیت |
| :--- | :--- | :--- | :--- |
| **فاز ۰** | بنیان داده + وب‌سایت + ترکینگ دستی + مهاجرت داده‌های تاریخی | ۴ هفته | 🚧 در دست اقدام |
| **فاز ۱** | موتور قیمت‌گذاری کامل + ثبت سفارش آنلاین + تولید PDFها | ۴-۶ هفته | ⏳ در صف |
| **فاز ۲** | حساب کاربری مشتری + کیف پول + حسابداری ساده + تخفیف حجمی | ۴ هفته | ⏳ در صف |
| **فاز ۳** | VPS پل + API ترکینگ زنده + CRM + داشبورد مالی تحلیلی | ۶-۸ هفته | ⏳ در صف |
> 💡 جزئیات کامل هر فاز، اسکیمای دیتابیس، جدول زمانی و معیارهای پذیرش در سند `01_Documents/Phase0_Proposal.md` آمده است.
---
## ✨ ویژگی‌های کلیدی فاز ۰ (مورد اجرا)
### ۱. اسکیمای دیتابیس اصلاح‌شده (بر اساس فایل اکسل عملیاتی)
- جدول `countries` با ۴ زون مجزا (صادرات/واردات × پارسل/داکیومنت) — به‌جای ۲ زون قبلی
- پشتیبانی از ۳ نوع سرویس: `DOC_NORMAL`, `DOC_ECONOMY`, `PARCEL`
- جدول `shipment_carrier_mappings` برای نگاشت چند شرکت حمل به هر بارنامه
- جدول `shipment_tracking_events` برای ذخیره تایم‌لاین کامل رویدادهای هر مرسوله
### ۲. پنل مدیریت اختصاصی (Laravel Filament)
- مدیریت کامل ۲۳۳ کشور با زون‌های صادرات و واردات.
- ماژول ایمپورت اکسل: آپلود مستقیم فایل‌های اکسل تعرفه‌ها توسط ادمین (خواندن خودکار شیت‌های Import/Export).
- فرم تنظیمات سیستم: تغییر سریع ارزها و ضریب سود بدون دستکاری در کد.
- مدیریت ۲۳۳ کشور با زون‌های صادرات و واردات
- ماژول ایمپورت اکسل تعرفه‌ها (در فاز ۱)
- فرم تنظیمات سیستم: تغییر سریع ارزها و ضریب سود بدون دستکاری کد
- UX تخصصی اپراتور ترکینگ: افزودن رویداد در چند ثانیه با فیلدهای از پیش پر شده
### ۳. ارتباطات API و فرانت‌اند
- **API استعلام قیمت:** ایجاد `POST /api/calculate-price` برای دریافت اطلاعات وردپرس.
- **پلاگین وردپرس (IFNEX Bridge):** توسعه یک افزونه مستقل از قالب وردپرس.
- **شورت‌کد استعلام قیمت:** فرم مدرن با جاوااسکریپت برای دریافت و نمایش آنی شمارش (ریال/درهم) در سایت.
- **API استعلام قیمت (در فاز ۱):** `POST /api/calculate-price`
- **API ترکینگ (در فاز ۰):** `GET /api/track/{awb_no}`
- **پلاگین IFNEX Bridge:** شورت‌کد `[ifnex_tracking_form]` برای فرم رهگیری در وردپرس
- **امنیت:** API Key + Rate Limiting + CORS whitelist + Form Request Validation
### ۴. مهاجرت داده‌های تاریخی
- انتقال ۳۹۵۰ رکورد تاریخی از فایل اکسل به دیتابیس جدید
- اعتبارسنجی و پاکسازی خودکار داده‌ها
- در دسترس قرار دادن تاریخچه‌ی کامل برای مشتریان قدیمی
---
## 📁 ساختار پروژه (Project Structure)
## 📁 ساختار پروژه
```text
IFNEX-Logistics/
├── 01_Documents/ # مستندات و اسناد فنی پروژه
│ ├── PRD_v2.md # سند نیازمندی‌ها (توضیح دیتابیس، منطق فرمول‌ها و فازبندی‌ها)
│ └── Project_Roadmap.md # نقشه راه و چک‌لیست کارهای انجام شده و در دست اقدام
├── 01_Documents/ # مستندات فنی پروژه
│ ├── PRD_v2.md # سند نیازمندی‌ها (نسخه قدیمی — به‌زودی بازنویسی)
│ ├── Phase0_Proposal.md # ⭐ سند پیشنهاد فاز ۰ (نقشه راه جدید)
│ └── Project_Roadmap.md # نقشه راه و چک‌لیست (به‌زودی به‌روزرسانی)
├── 02_Design/ # فایل‌های مربوط به رابط کاربری (UI/UX و فیگما)
│ └── Assets/ # لوگوها، آیکون‌ها و...
├── 02_Design/ # فایل‌های UI/UX و فیگما
│ └── Assets/ # لوگوها، آیکون‌ها
├── 03_WordPress/ # سیستم مدیریت محتوای سایت (فرانت‌اند)
│ └── wp-content/
│ └── plugins/
│ └── ifnex-bridge/ # پلاگین اختصاصی ما برای ارتباط با لاراول
├── 03_WordPress/ # سیستم مدیریت محتوا (فرانت‌اند)
│ └── wp-content/plugins/
│ └── ifnex-bridge/ # پلاگین اختصاصی ارتباط با لاراول
└── 04_Laravel/ # هسته مرکزی سیستم (بک‌اند)
├── app/
│ ├── Models/ # مدل‌های دیتابیس (Country, ShippingRate, Shipment, SystemSetting)
│ ├── Services/ # کلاس‌های منطقی تجاری (مثل PriceCalculatorService)
│ ├── Http/Controllers/Api/ # کنترلرهای API
│ ├── Imports/ # کلاس‌های خواندن فایل‌های اکسل (ShippingRatesImport)
│ └── Filament/ # پنل مدیریت ادمین (Resources و Pages)
│ ├── Models/ # Country, Shipment, ShipmentTrackingEvent, ...
│ ├── Services/ # PriceCalculatorService (فاز ۱), TrackingService
│ ├── Http/Controllers/Api/ # TrackController, PricingController, ...
│ ├── Imports/ # ShippingRatesImport, HistoricalShipmentsImport
│ └── Filament/ # پنل مدیریت ادمین
├── database/
│ ├── migrations/ # فایل‌های ساخت جداول دیتابیس
│ └── seeders/ # داده‌های اولیه (کشورها)
├── config/ # تنظیمات سیستم (فایل‌های .php)
└── resources/ # فایل‌های ویو (Blade) برای پنل و ایمپورتورها
│ ├── migrations/ # جداول دیتابیس
│ └── seeders/ # داده‌های اولیه (۲۳۳ کشور)
└── config/ # تنظیمات سیستم
---
🚀 راه‌اندازی و اجرای پروژه (Localhost)
🚀 راه‌اندازی و اجرا (Localhost)
پیش‌نیازها
XAMPP (شامل PHP 8.2+ و MySQL)
XAMPP یا مشابه (PHP 8.2+ و MySQL 8+)
Composer
Node.js و NPM (برای ابزارهای پیش‌فرض وردپرس/المنتور)
مراحل نصب
مخزن کد را کلون کنید و وارد پوشه 04_Laravel شوید.
دستور composer install را برای نصب پکیج‌های لاراول اجرا کنید.
فایل .env.example را به .env کپی کرده و اطلاعات دیتابیس XAMPP را وارد کنید.
دستور php artisan key:generate را برای ایجاد کلید اپلیکیشن اجرا کنید.
دستور php artisan migrate را برای ساخت جداول اجرا کنید.
دستور php artisan db:seed را برای درج داده‌های اولیه (کشورها و تنظیمات ارز) بزنید.
برای پنل ادمین دستور php artisan serve و برای وردپرس از لوکال هاست وردپرس استفاده کنید.
Node.js و NPM (برای ابزارهای وردپرس/المنتور)
مراحل نصب (بخش لاراول)
# ۱. کلون مخزن و وارد شدن به پوشه لاراول
git clone https://www.git.vernahost.ir/gitmodir110/ifnex.git
cd ifnex/04_Laravel
# ۲. نصب پکیج‌ها
composer install
# ۳. کپی فایل محیط و تنظیم دیتابیس
cp .env.example .env
# فایل .env را ویرایش کرده و اطلاعات دیتابیس XAMPP را وارد کنید
# ۴. تولید کلید اپلیکیشن
php artisan key:generate
# ۵. اجرای Migration ها
php artisan migrate
# ۶. درج داده‌های اولیه (کشورها و نرخ ارز اولیه)
php artisan db:seed
# ۷. اجرای سرور توسعه
php artisan serve
مراحل نصب (بخش وردپرس)
۱. پوشه‌ی 03_WordPress را در htdocs یا مسیر هاست وردپرس قرار دهید.
۲. وردپرس را به‌صورت معمول نصب کنید.
۳. پلاگین ifnex-bridge را از مسیر wp-content/plugins/ifnex-bridge فعال کنید.
۴. در تنظیمات پلاگین، URL لاراول و API Key را وارد کنید.
۵. شورت‌کد [ifnex_tracking_form] را در صفحه‌ی «رهگیری مرسوله» قرار دهید.
⚠️ نکات امنیتی و تولید (Production)
هرگز فایل .env را در مخزن کد (Git) کامیت نکنید.
در محیط سرور واقعی، حتماً APP_DEBUG=false را در .env تنظیم کنید.
برای محیط سرور واقعی، نیاز به پیکربندی وب‌سرور (Nginx/Apache) و تنظیمات CORS برای ارتباط WP و Laravel دارید.
📜 مستندات بیشتر
هرگز فایل .env را در مخزن کد (Git) کامیت نکنید (در .gitignore تأیید شده).
در محیط تولید، APP_DEBUG=false را در .env تنظیم کنید.
برای محیط تولید، پیکربندی وب‌سرور (Nginx/Apache) و تنظیمات CORS برای ارتباط WP و Laravel ضروری است.
برای API ترکینگ خودکار (فاز ۳)، سرور VPS پل در خارج از کشور راه‌اندازی شود — راهنمای کامل در سند فاز ۳.
📚 مستندات بیشتر
برای مطالعه دقیق منطق‌های سیستم، حتماً فایل‌های داخل پوشه 01_Documents را مطالعه کنید:
PRD_v2.md: شامل معماری دقیق دیتابیس (Schema) استخراج شده از فایل اکسل عملیاتی شرکت.
Project_Roadmap.md: شامل لیست کارهای انجام شده و کارهای در دست اقدام (Checklist) بر اساس فازبندی پروژه.
© 2024 Vernasoft Group (Kazem Alghasi). All rights reserved.
فایل محتوا
Phase0_Proposal.md ⭐ سند پیشنهاد فاز ۰ — شامل اسکیمای دیتابیس، جدول زمانی، ریسک‌ها، معیارهای پذیرش
PRD_v2.md سند نیازمندی‌ها (نسخه قدیمی — برخی بخش‌های آن در سند فاز ۰ بازنویسی شده)
Project_Roadmap.md چک‌لیست کارهای انجام‌شده و در دست اقدام (به‌زودی به‌روزرسانی می‌شود)
🔐 امنیت و گزارش مشکلات
اگر آسیب‌پذیری امنیتی کشف کردید، لطفاً مستقیماً به kazem@vernasoft.group (یا ایمیل جایگزین تعیین‌شده) اطلاع دهید و آن را در Issue عمومی مخزن قرار ندهید.
📜 لایسنس
© 2026 VernaSoft Group (Kazem Alghasi). All rights reserved.
این پروژه اختصاصی شرکت IFNEX است و کپی یا استفاده‌ی غیرمجاز از آن ممنوع است.