diff --git a/04_Laravel/app/Filament/Resources/ShipmentResource/Pages/ListShipments.php b/04_Laravel/app/Filament/Resources/ShipmentResource/Pages/ListShipments.php index 9787ecf..f840549 100644 --- a/04_Laravel/app/Filament/Resources/ShipmentResource/Pages/ListShipments.php +++ b/04_Laravel/app/Filament/Resources/ShipmentResource/Pages/ListShipments.php @@ -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(), ]; } diff --git a/04_Laravel/app/Imports/OldShipmentsImport.php b/04_Laravel/app/Imports/OldShipmentsImport.php new file mode 100644 index 0000000..f1105fb --- /dev/null +++ b/04_Laravel/app/Imports/OldShipmentsImport.php @@ -0,0 +1,104 @@ +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 + ); + } +} diff --git a/README.md b/README.md index a87eea9..ce0f9e8 100644 --- a/README.md +++ b/README.md @@ -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. \ No newline at end of file +فایل محتوا +Phase0_Proposal.md ⭐ سند پیشنهاد فاز ۰ — شامل اسکیمای دیتابیس، جدول زمانی، ریسک‌ها، معیارهای پذیرش +PRD_v2.md سند نیازمندی‌ها (نسخه قدیمی — برخی بخش‌های آن در سند فاز ۰ بازنویسی شده) +Project_Roadmap.md چک‌لیست کارهای انجام‌شده و در دست اقدام (به‌زودی به‌روزرسانی می‌شود) +🔐 امنیت و گزارش مشکلات +اگر آسیب‌پذیری امنیتی کشف کردید، لطفاً مستقیماً به kazem@vernasoft.group (یا ایمیل جایگزین تعیین‌شده) اطلاع دهید و آن را در Issue عمومی مخزن قرار ندهید. + +📜 لایسنس +© 2026 VernaSoft Group (Kazem Alghasi). All rights reserved. + +این پروژه اختصاصی شرکت IFNEX است و کپی یا استفاده‌ی غیرمجاز از آن ممنوع است. \ No newline at end of file