ifnex/04_Laravel/README.md
Kazem Alghasi 285acdae89 docs(project): update project status, roadmap, and documentation
Update project documentation to reflect the completion of Phase 0 and Phase 1, and the commencement of Phase 2. This includes archiving obsolete documents, updating the README with a new architectural overview, and refining the project checklist and status reports.

- Archive obsolete PRD and Roadmap documents
- Update `IFNEX_Phase0_Checklist.md` with completed tasks and Phase 2 roadmap
- Update `STATUS.md` with recent development progress for August 2026
- Refactor `04_Laravel/README.md` to include detailed technical specifications and architecture diagrams
- Update root `README.md` with updated versioning and system architecture visualization
- Refine `PriceCalculatorServiceTest.php` to align with updated service output structures
2026-08-07 05:58:12 +03:30

480 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

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.

---
## 📄 فایل ۲: `04_Laravel/README.md` (پوشه لاراول)
```markdown
# 🚀 IFNEX Laravel Backend
> هسته مرکزی سیستم مدیریت لجستیک ایف‌نکس
| مورد | توضیحات |
| :--- | :--- |
| **نسخه لاراول** | Laravel 11.x |
| **نسخه PHP** | PHP 8.2+ |
| **پنل ادمین** | Filament 3.3.x |
| **دیتابیس** | MySQL 8+ |
| **تاریخ آخرین به‌روزرسانی** | 2026-08-07 |
---
## 📋 فهرست مطالب
1. [پیش‌نیازها](#پیشنیازها)
2. [نصب و راه‌اندازی](#نصب-و-راهاندازی)
3. [ساختار پوشه‌ها](#ساختار-پوشهها)
4. [API Endpoints](#api-endpoints)
5. [Artisan Commands](#artisan-commands)
6. [تست‌ها](#تستها)
7. [پیکربندی](#پیکربندی)
8. [نکات امنیتی](#نکات-امنیتی)
---
## پیش‌نیازها
قبل از شروع، مطمئن شوید که موارد زیر روی سیستم شما نصب هستند:
| ابزار | نسخه حداقل | نصب |
|-------|-----------|-----|
| PHP | 8.2+ | [دانلود](https://www.php.net/downloads) |
| Composer | 2.x | [دانلود](https://getcomposer.org/) |
| MySQL | 8+ | [دانلود](https://dev.mysql.com/downloads/) |
| Node.js & NPM | 18+ | [دانلود](https://nodejs.org/) (اختیاری - برای WordPress tools) |
| XAMPP/WAMP | آخرین نسخه | [دانلود](https://www.apachefriends.org/) (پیشنهادی برای Windows) |
---
## نصب و راه‌اندازی
### ۱. کلون مخزن و ورود به پوشه لاراول
```bash
# کلون مخزن
git clone https://www.git.vernahost.ir/gitmodir110/ifnex.git
# ورود به پوشه لاراول
cd ifnex/04_Laravel
۲. نصب پکیج‌های Composer
composer install
۳. کپی فایل محیط و تنظیم دیتابیس
# کپی فایل محیط
cp .env.example .env
# ویرایش فایل .env و تنظیم اطلاعات دیتابیس
nano .env # یا هر ویرایشگر دلخواه
تنظیمات مهم در فایل .env:
# دیتابیس
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=ifnex_db
DB_USERNAME=root
DB_PASSWORD=
# API Key برای ترکینگ
IFNEX_API_KEY=ifnex-local-dev-key
# CORS - فقط دامنه وردپرس
CORS_ALLOWED_ORIGINS=http://localhost:8080
# Rate Limiting
IFNEX_TRACKING_RATE_LIMIT=60
# Currency API (برای فاز ۲)
CURRENCY_API_KEY=your_api_key_here
۴. تولید کلید اپلیکیشن
php artisan key:generate
۵. ایجاد دیتابیس
# ورود به MySQL
mysql -u root -p
# ایجاد دیتابیس
CREATE DATABASE ifnex_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
EXIT;
۶. اجرای Migration ها
php artisan migrate --force
۷. درج داده‌های اولیه (Seeders)
# این دستور ۲۳۳ کشور + تنظیمات اولیه + کاربر ادمین را ایجاد می‌کند
php artisan db:seed --force
اطلاعات ورود پیش‌فرض به پنل ادمین:
URL: http://localhost:8000/admin
Email: admin@ifnex.local
Password: password (در Seeder تنظیم شده)
۸. اجرای سرور توسعه
php artisan serve
اکنون پروژه در http://localhost:8000 قابل دسترسی است.
ساختار پوشه‌ها
04_Laravel/
├── app/
│ ├── Models/ # مدل‌های Eloquent
│ │ ├── Country.php # کشورها با ۴ زون
│ │ ├── Shipment.php # مرسولات
│ │ ├── ShipmentItem.php # اقلام گمرکی (۹ ردیف)
│ │ ├── ShippingRate.php # تعرفه‌های حمل
│ │ ├── ShipmentCarrierMapping.php # نگاشت کدهای ترکینگ
│ │ ├── ShipmentTrackingEvent.php # رویدادهای ترکینگ
│ │ ├── SystemSetting.php # تنظیمات سیستم
│ │ └── User.php # کاربران
│ │
│ ├── Enums/ # Enum ها
│ │ ├── ShipmentDirection.php # import/export
│ │ ├── ShipmentType.php # DOC_NORMAL/DOC_ECONOMY/PARCEL
│ │ ├── ShipmentStatus.php # ۷ وضعیت مرسوله
│ │ ├── CarrierCode.php # ۹ شرکت حمل
│ │ ├── TrackingSource.php # manual/api_carrier/api_aggregator
│ │ └── UserRole.php # ۴ نقش کاربری
│ │
│ ├── Services/ # لایه سرویس (Business Logic)
│ │ ├── PriceCalculatorService.php # ⭐ موتور قیمت‌گذاری
│ │ └── TrackingService.php # سرویس ترکینگ
│ │
│ ├── Http/
│ │ ├── Controllers/
│ │ │ ├── Api/
│ │ │ │ ├── TrackController.php # API ترکینگ
│ │ │ │ ├── PricingController.php # API استعلام قیمت
│ │ │ │ ├── WalletController.php # API کیف پول
│ │ │ │ └── DiscountCodeController.php # API تخفیف
│ │ │ ├── OrderController.php # فرم ثبت سفارش
│ │ │ ├── PricingPageController.php # صفحه استعلام قیمت
│ │ │ └── ShipmentPdfController.php # تولید PDF
│ │ ├── Middleware/
│ │ │ └── ApiKeyMiddleware.php # احراز هویت API
│ │ └── Requests/ # Form Request Validation
│ │
│ ├── Imports/ # Excel Imports
│ │ ├── ShippingRatesImport.php # واردات تعرفه‌ها
│ │ ├── HistoricalShipmentsImport.php # واردات مرسولات تاریخی
│ │ └── RateSheetImport.php # شیت‌های نرخ
│ │
│ ├── Console/Commands/ # Artisan Commands
│ │ ├── ImportShippingRates.php # واردات تعرفه‌ها
│ │ ├── ImportHistoricalData.php # واردات داده‌های تاریخی
│ │ └── UpdateExchangeRates.php # به‌روزرسانی نرخ ارز
│ │
│ └── Filament/ # پنل ادمین Filament
│ ├── Resources/
│ │ ├── CountryResource.php
│ │ ├── ShipmentResource.php
│ │ ├── ShippingRateResource.php
│ │ └── ShipmentItemResource.php
│ └── Pages/
│ └── IfnexSettingsPage.php # صفحه تنظیمات
├── database/
│ ├── migrations/ # Migration ها
│ │ ├── 2026_08_02_000001_create_countries_table.php
│ │ ├── 2026_08_02_000002_create_shipments_table.php
│ │ ├── 2026_08_02_000003_create_shipping_rates_table.php
│ │ ├── 2026_08_02_000004_create_shipment_carrier_mappings_table.php
│ │ ├── 2026_08_02_000005_create_shipment_tracking_events_table.php
│ │ ├── 2026_08_02_000006_create_system_settings_table.php
│ │ └── 2026_08_02_000007_update_users_table.php
│ └── seeders/ # Seeders
│ ├── CountriesTableSeeder.php
│ ├── SystemSettingSeeder.php
│ └── DatabaseSeeder.php
├── routes/
│ ├── web.php # روت‌های وب (فرم‌ها و صفحات)
│ └── api.php # روت‌های API
├── resources/views/
│ ├── layouts/app.blade.php # لایاوت اصلی
│ ├── orders/ # فرم ثبت سفارش
│ ├── pricing/ # صفحه استعلام قیمت
│ └── pdfs/ # قالب‌های PDF
├── config/
│ ├── ifnex.php # تنظیمات اختصاصی IFNEX
│ └── cors.php # تنظیمات CORS
├── tests/
│ └── Feature/
│ └── Services/
│ └── PriceCalculatorServiceTest.php # ⭐ تست‌های موتور قیمت
├── bootstrap/
│ └── app.php # Bootstrap لاراول ۱۱
├── .env.example # نمونه فایل محیط
├── composer.json # وابستگی‌های Composer
└── README.md # این فایل
API Endpoints
🔓 API های عمومی (نیاز به API Key)
۱. رهگیری مرسوله
GET /api/v1/track/{awb_no}
Headers:
Authorization: Bearer {IFNEX_API_KEY}
مثال:
curl -H "Authorization: Bearer ifnex-local-dev-key" \
http://localhost:8000/api/v1/track/980100010
پاسخ موفق (200 OK):
{
"success": true,
"data": {
"awb_no": "980100010",
"status": "delivered",
"carrier_mappings": [...],
"tracking_events": [...]
}
}
۲. استعلام قیمت
POST /api/v1/calculate
Body (JSON):
{
"direction": "export",
"type": "DOC_NORMAL",
"country_iso": "US",
"weight": 2.5,
"volumetric_weight": 3.0,
"extra_service": 10.00
}
مثال:
curl -X POST http://localhost:8000/api/v1/calculate \
-H "Content-Type: application/json" \
-d '{
"direction": "export",
"type": "DOC_NORMAL",
"country_iso": "US",
"weight": 2.5,
"volumetric_weight": 3.0
}'
پاسخ موفق:
{
"base_price": 40.00,
"net_dirham": 50.00,
"net_rial": 22750000,
"total_fee": 24906510.9,
"zone": 1,
"chargeable_weight": 3.0
}
💳 API های کیف پول (فاز ۲)
۱. بررسی موجودی
GET /api/v1/wallet/balance
۲. شارژ کیف پول
POST /api/v1/wallet/charge
Body:
{
"amount": 1000000,
"description": "شارژ اولیه"
}
۳. تاریخچه تراکنش‌ها
GET /api/v1/wallet/transactions
🎟️ API های تخفیف (فاز ۲)
۱. لیست کدهای تخفیف فعال
GET /api/v1/discounts/active
۲. اعتبارسنجی کد تخفیف
POST /api/v1/discounts/validate
Body:
{
"code": "SUMMER20",
"amount": 1000000
}
Artisan Commands
📥 واردات داده‌ها
۱. واردات تعرفه‌های حمل از اکسل
# واردات عادی
php artisan ifnex:import:rates storage/app/public/rates.xlsx
# پاک‌سازی و واردات مجدد
php artisan ifnex:import:rates storage/app/public/rates.xlsx --clear
# تست بدون ذخیره (Dry Run)
php artisan ifnex:import:rates storage/app/public/rates.xlsx --dry-run
۲. واردات مرسولات تاریخی
php artisan ifnex:import:shipments storage/app/public/historical.xlsx
💱 به‌روزرسانی نرخ ارز (فاز ۲)
# به‌روزرسانی دستی
php artisan ifnex:update-exchange-rates
# تنظیم Cron Job برای به‌روزرسانی روزانه
# crontab -e
# 0 0 * * * cd /path/to/04_Laravel && php artisan ifnex:update-exchange-rates >> /dev/null 2>&1
🧪 تست‌ها
# اجرای همه تست‌ها
php artisan test
# اجرای تست‌های یک کلاس خاص
php artisan test --filter=PriceCalculatorServiceTest
# اجرای تست با نمایش دقیق
php artisan test --filter=it_calculates_price_correctly_for_standard_package
# گزارش پوشش تست (نیاز به Xdebug)
php artisan test --coverage
تست‌ها
تست‌های موجود
۱. PriceCalculatorServiceTest
این تست کلاس PriceCalculatorService را به طور کامل تست می‌کند:
php artisan test --filter=PriceCalculatorServiceTest
موارد تست شده:
✅ محاسبه صحیح قیمت برای بسته استاندارد
✅ استفاده از وزن حجمی وقتی از وزن واقعی بزرگتر است
✅ اعمال صحیح ضریب سود و VAT
✅ اعمال هزینه‌های جانبی
✅ اعمال کد تخفیف درصدی و ثابت
نوشتن تست جدید
برای نوشتن تست جدید، از این الگو استفاده کنید:
<?php
namespace Tests\Feature\Services;
use App\Models\Country;
use App\Models\ShippingRate;
use App\Models\SystemSetting;
use App\Services\PriceCalculatorService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
class PriceCalculatorServiceTest extends TestCase
{
use RefreshDatabase;
#[Test]
public function it_calculates_price_correctly()
{
// 1. تنظیم SystemSetting ها
SystemSetting::create(['key' => 'profit_margin', 'value' => 1.0]);
SystemSetting::create(['key' => 'aed_to_irr', 'value' => 1.0]);
SystemSetting::create(['key' => 'vat_rate', 'value' => 0.0]);
SystemSetting::create(['key' => 'packing_cost_default', 'value' => 0]);
// 2. ایجاد داده‌های تست
$country = Country::factory()->create([...]);
ShippingRate::create([...]);
// 3. اجرای سرویس
$service = app(PriceCalculatorService::class);
$result = $service->calculate([...]);
// 4. بررسی نتیجه
$this->assertEquals(50.00, $result['total_fee']);
}
}
پیکربندی
فایل config/ifnex.php
return [
// API Key برای احراز هویت
'api_key' => env('IFNEX_API_KEY', 'default-key'),
// Rate Limiting
'tracking_rate_limit' => env('IFNEX_TRACKING_RATE_LIMIT', 60),
// Currency API
'currency_api_key' => env('CURRENCY_API_KEY'),
'currency_api_url' => env('CURRENCY_API_URL', 'https://api.freecurrencyapi.com/v1/latest'),
];
فایل config/cors.php
return [
'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => explode(',', env('CORS_ALLOWED_ORIGINS', '*')),
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];
نکات امنیتی
🚫 هرگز این کارها را نکنید
هرگز فایل .env را در Git کامیت نکنید
# بررسی کنید در .gitignore باشد
.env
.env.local
.env.production
هرگز APP_DEBUG=true را در محیط تولید بگذارید
# Production
APP_DEBUG=false
هرگز از CORS * در محیط تولید استفاده نکنید
# فقط دامنه وردپرس
CORS_ALLOWED_ORIGINS=https://your-wordpress-domain.com
هرگز API Key را در کد Hardcode نکنید
// ❌ اشتباه
$apiKey = 'secret-key-123';
// ✅ درست
$apiKey = config('ifnex.api_key');
🐛 عیب‌یابی
مشکل: CHECK constraint failed: direction
علت: Factory مقادیر پیش‌فرض اشتباه می‌سازد (مثلاً 'Outbound' به جای 'export')
راه‌حل: در تست‌ها از ShippingRate::create() به جای ShippingRate::factory()->create() استفاده کنید:
ShippingRate::create([
'direction' => 'export', // حروف کوچک
'type' => 'DOC_NORMAL',
'weight' => 1.0,
'zone_1' => 20.00,
// ... بقیه zone ها
]);
مشکل: No rate found for the given parameters
علت: Query نمی‌تواند نرخ مناسبی پیدا کند
راه‌حل:
بررسی کنید که zone_column درست است (zone_1, zone_2, ...)
مطمئن شوید که وزن در تست بیشتر از وزن‌های موجود در دیتابیس نیست
SystemSetting ها را در تست Mock کنید
📞 پشتیبانی
اگر سوالی داشتید که در این فایل یا مستندات 01_Documents پاسخ آن نبود، از کاربر (Kazem) بپرسید — حدس نزنید.
© 2026 VernaSoft Group. Internal use only.