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; namespace App\Filament\Resources\ShipmentResource\Pages;
use App\Filament\Resources\ShipmentResource; use App\Filament\Resources\ShipmentResource;
use App\Imports\OldShipmentsImport; // اضافه شدن کلاس ایمپورت صحیح
use Filament\Actions; use Filament\Actions;
use Filament\Actions\Action; // اضافه شدن اکشن
use Filament\Forms\Components\FileUpload; // اضافه شدن فایل آپلود
use Filament\Resources\Pages\ListRecords; use Filament\Resources\Pages\ListRecords;
use Maatwebsite\Excel\Facades\Excel;
class ListShipments extends ListRecords class ListShipments extends ListRecords
{ {
@ -13,6 +17,35 @@ class ListShipments extends ListRecords
protected function getHeaderActions(): array protected function getHeaderActions(): array
{ {
return [ 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(), 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 # 🚀 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) | **ویرایش سند** | v2.0 (نقشه راه ۴ فازی) |
![MySQL](https://img.shields.io/badge/MySQL-8.0-4479A1?style=for-the-badge&logo=mysql&logoColor=white) | **توسعه‌دهنده** | VernaSoft Group — Kazem Alghasi |
| **مشتری** | شرکت حمل و نقل بین‌المللی ایف‌نکس (IFNEX) — اصفهان |
**Author:** VernaSoft Group (Kazem Alghasi)
--- ---
## 📖 درباره پروژه ## 📖 درباره پروژه
سیستم مدیریت لجستیک ایف‌نکس (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) ### ۲. پنل مدیریت اختصاصی (Laravel Filament)
- مدیریت کامل ۲۳۳ کشور با زون‌های صادرات و واردات. - مدیریت ۲۳۳ کشور با زون‌های صادرات و واردات
- ماژول ایمپورت اکسل: آپلود مستقیم فایل‌های اکسل تعرفه‌ها توسط ادمین (خواندن خودکار شیت‌های Import/Export). - ماژول ایمپورت اکسل تعرفه‌ها (در فاز ۱)
- فرم تنظیمات سیستم: تغییر سریع ارزها و ضریب سود بدون دستکاری در کد. - فرم تنظیمات سیستم: تغییر سریع ارزها و ضریب سود بدون دستکاری کد
- UX تخصصی اپراتور ترکینگ: افزودن رویداد در چند ثانیه با فیلدهای از پیش پر شده
### ۳. ارتباطات API و فرانت‌اند ### ۳. ارتباطات API و فرانت‌اند
- **API استعلام قیمت:** ایجاد `POST /api/calculate-price` برای دریافت اطلاعات وردپرس. - **API استعلام قیمت (در فاز ۱):** `POST /api/calculate-price`
- **پلاگین وردپرس (IFNEX Bridge):** توسعه یک افزونه مستقل از قالب وردپرس. - **API ترکینگ (در فاز ۰):** `GET /api/track/{awb_no}`
- **شورت‌کد استعلام قیمت:** فرم مدرن با جاوااسکریپت برای دریافت و نمایش آنی شمارش (ریال/درهم) در سایت. - **پلاگین IFNEX Bridge:** شورت‌کد `[ifnex_tracking_form]` برای فرم رهگیری در وردپرس
- **امنیت:** API Key + Rate Limiting + CORS whitelist + Form Request Validation
### ۴. مهاجرت داده‌های تاریخی
- انتقال ۳۹۵۰ رکورد تاریخی از فایل اکسل به دیتابیس جدید
- اعتبارسنجی و پاکسازی خودکار داده‌ها
- در دسترس قرار دادن تاریخچه‌ی کامل برای مشتریان قدیمی
--- ---
## 📁 ساختار پروژه (Project Structure) ## 📁 ساختار پروژه
```text ```text
IFNEX-Logistics/ IFNEX-Logistics/
├── 01_Documents/ # مستندات و اسناد فنی پروژه ├── 01_Documents/ # مستندات فنی پروژه
│ ├── PRD_v2.md # سند نیازمندی‌ها (توضیح دیتابیس، منطق فرمول‌ها و فازبندی‌ها) │ ├── PRD_v2.md # سند نیازمندی‌ها (نسخه قدیمی — به‌زودی بازنویسی)
│ └── Project_Roadmap.md # نقشه راه و چک‌لیست کارهای انجام شده و در دست اقدام │ ├── Phase0_Proposal.md # ⭐ سند پیشنهاد فاز ۰ (نقشه راه جدید)
│ └── Project_Roadmap.md # نقشه راه و چک‌لیست (به‌زودی به‌روزرسانی)
│ │
├── 02_Design/ # فایل‌های مربوط به رابط کاربری (UI/UX و فیگما) ├── 02_Design/ # فایل‌های UI/UX و فیگما
│ └── Assets/ # لوگوها، آیکون‌ها و... │ └── Assets/ # لوگوها، آیکون‌ها
│ │
├── 03_WordPress/ # سیستم مدیریت محتوای سایت (فرانت‌اند) ├── 03_WordPress/ # سیستم مدیریت محتوا (فرانت‌اند)
│ └── wp-content/ │ └── wp-content/plugins/
│ └── plugins/ │ └── ifnex-bridge/ # پلاگین اختصاصی ارتباط با لاراول
│ └── ifnex-bridge/ # پلاگین اختصاصی ما برای ارتباط با لاراول
│ │
└── 04_Laravel/ # هسته مرکزی سیستم (بک‌اند) └── 04_Laravel/ # هسته مرکزی سیستم (بک‌اند)
├── app/ ├── app/
│ ├── Models/ # مدل‌های دیتابیس (Country, ShippingRate, Shipment, SystemSetting) │ ├── Models/ # Country, Shipment, ShipmentTrackingEvent, ...
│ ├── Services/ # کلاس‌های منطقی تجاری (مثل PriceCalculatorService) │ ├── Services/ # PriceCalculatorService (فاز ۱), TrackingService
│ ├── Http/Controllers/Api/ # کنترلرهای API │ ├── Http/Controllers/Api/ # TrackController, PricingController, ...
│ ├── Imports/ # کلاس‌های خواندن فایل‌های اکسل (ShippingRatesImport) │ ├── Imports/ # ShippingRatesImport, HistoricalShipmentsImport
│ └── Filament/ # پنل مدیریت ادمین (Resources و Pages) │ └── Filament/ # پنل مدیریت ادمین
├── database/ ├── database/
│ ├── migrations/ # فایل‌های ساخت جداول دیتابیس │ ├── migrations/ # جداول دیتابیس
│ └── seeders/ # داده‌های اولیه (کشورها) │ └── seeders/ # داده‌های اولیه (۲۳۳ کشور)
├── config/ # تنظیمات سیستم (فایل‌های .php) └── config/ # تنظیمات سیستم
└── resources/ # فایل‌های ویو (Blade) برای پنل و ایمپورتورها
---
🚀 راه‌اندازی و اجرای پروژه (Localhost) 🚀 راه‌اندازی و اجرا (Localhost)
پیش‌نیازها پیش‌نیازها
XAMPP (شامل PHP 8.2+ و MySQL) XAMPP یا مشابه (PHP 8.2+ و MySQL 8+)
Composer Composer
Node.js و NPM (برای ابزارهای پیش‌فرض وردپرس/المنتور) Node.js و NPM (برای ابزارهای وردپرس/المنتور)
مراحل نصب مراحل نصب (بخش لاراول)
مخزن کد را کلون کنید و وارد پوشه 04_Laravel شوید.
دستور composer install را برای نصب پکیج‌های لاراول اجرا کنید. # ۱. کلون مخزن و وارد شدن به پوشه لاراول
فایل .env.example را به .env کپی کرده و اطلاعات دیتابیس XAMPP را وارد کنید. git clone https://www.git.vernahost.ir/gitmodir110/ifnex.git
دستور php artisan key:generate را برای ایجاد کلید اپلیکیشن اجرا کنید. cd ifnex/04_Laravel
دستور php artisan migrate را برای ساخت جداول اجرا کنید.
دستور php artisan db:seed را برای درج داده‌های اولیه (کشورها و تنظیمات ارز) بزنید. # ۲. نصب پکیج‌ها
برای پنل ادمین دستور php artisan serve و برای وردپرس از لوکال هاست وردپرس استفاده کنید. 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) ⚠️ نکات امنیتی و تولید (Production)
هرگز فایل .env را در مخزن کد (Git) کامیت نکنید. هرگز فایل .env را در مخزن کد (Git) کامیت نکنید (در .gitignore تأیید شده).
در محیط سرور واقعی، حتماً APP_DEBUG=false را در .env تنظیم کنید. در محیط تولید، APP_DEBUG=false را در .env تنظیم کنید.
برای محیط سرور واقعی، نیاز به پیکربندی وب‌سرور (Nginx/Apache) و تنظیمات CORS برای ارتباط WP و Laravel دارید. برای محیط تولید، پیکربندی وب‌سرور (Nginx/Apache) و تنظیمات CORS برای ارتباط WP و Laravel ضروری است.
📜 مستندات بیشتر برای API ترکینگ خودکار (فاز ۳)، سرور VPS پل در خارج از کشور راه‌اندازی شود — راهنمای کامل در سند فاز ۳.
📚 مستندات بیشتر
برای مطالعه دقیق منطق‌های سیستم، حتماً فایل‌های داخل پوشه 01_Documents را مطالعه کنید: برای مطالعه دقیق منطق‌های سیستم، حتماً فایل‌های داخل پوشه 01_Documents را مطالعه کنید:
PRD_v2.md: شامل معماری دقیق دیتابیس (Schema) استخراج شده از فایل اکسل عملیاتی شرکت. فایل محتوا
Project_Roadmap.md: شامل لیست کارهای انجام شده و کارهای در دست اقدام (Checklist) بر اساس فازبندی پروژه. Phase0_Proposal.md ⭐ سند پیشنهاد فاز ۰ — شامل اسکیمای دیتابیس، جدول زمانی، ریسک‌ها، معیارهای پذیرش
© 2024 Vernasoft Group (Kazem Alghasi). All rights reserved. PRD_v2.md سند نیازمندی‌ها (نسخه قدیمی — برخی بخش‌های آن در سند فاز ۰ بازنویسی شده)
Project_Roadmap.md چک‌لیست کارهای انجام‌شده و در دست اقدام (به‌زودی به‌روزرسانی می‌شود)
🔐 امنیت و گزارش مشکلات
اگر آسیب‌پذیری امنیتی کشف کردید، لطفاً مستقیماً به kazem@vernasoft.group (یا ایمیل جایگزین تعیین‌شده) اطلاع دهید و آن را در Issue عمومی مخزن قرار ندهید.
📜 لایسنس
© 2026 VernaSoft Group (Kazem Alghasi). All rights reserved.
این پروژه اختصاصی شرکت IFNEX است و کپی یا استفاده‌ی غیرمجاز از آن ممنوع است.