ifnex/04_Laravel
Kazem Alghasi ed5bae9997 feat(exchange): implement exchange rate history tracking
Introduce a mechanism to track and audit changes in exchange rates.
This includes:
- Creating `ExchangeRateHistory` model and migration to store rate changes.
- Implementing `ExchangeRateService` to encapsulate rate logic.
- Updating `UpdateExchangeRates` command to record history when rates change.
- Adding `ExchangeRateHistoryResource` to the Filament admin panel for monitoring.
2026-08-10 03:04:18 +03:30
..
.postman feat(wallet): complete wallet system with admin adjust, freeze/unfreeze, activity logs 2026-08-07 22:51:42 +03:30
app feat(exchange): implement exchange rate history tracking 2026-08-10 03:04:18 +03:30
bootstrap feat(laravel): implement user synchronization and shipment schema 2026-08-08 04:58:01 +03:30
config feat(auth): implement role-based access control using spatie/laravel-permission 2026-08-10 02:44:23 +03:30
database feat(exchange): implement exchange rate history tracking 2026-08-10 03:04:18 +03:30
postman feat(wallet): complete wallet system with admin adjust, freeze/unfreeze, activity logs 2026-08-07 22:51:42 +03:30
public feat(finance): implement Filament admin panel and expand wallet/discount features 2026-08-08 03:15:51 +03:30
resources feat(admin): configure filament panel with custom branding and notifications 2026-08-09 05:14:36 +03:30
routes feat(wallet): complete online payment with Zarinpal + mock gateway 2026-08-08 00:46:54 +03:30
storage feat: Complete Phase 1 core logic and WP bridge setup 2026-08-01 04:01:22 +03:30
tests feat(finance): implement Filament admin panel and expand wallet/discount features 2026-08-08 03:15:51 +03:30
.editorconfig feat: Complete Phase 1 core logic and WP bridge setup 2026-08-01 04:01:22 +03:30
.env.example feat(wallet): complete wallet system with admin adjust, freeze/unfreeze, activity logs 2026-08-07 22:51:42 +03:30
.phpunit.result.cache feat(ui): implement unified design system and financial reporting 2026-08-08 06:13:09 +03:30
artisan feat: Complete Phase 1 core logic and WP bridge setup 2026-08-01 04:01:22 +03:30
composer.json feat(auth): implement role-based access control using spatie/laravel-permission 2026-08-10 02:44:23 +03:30
composer.lock feat(auth): implement role-based access control using spatie/laravel-permission 2026-08-10 02:44:23 +03:30
echo feat(wallet): complete wallet system with admin adjust, freeze/unfreeze, activity logs 2026-08-07 22:51:42 +03:30
package.json feat: Complete Phase 1 core logic and WP bridge setup 2026-08-01 04:01:22 +03:30
phpunit.xml feat: Complete Phase 1 core logic and WP bridge setup 2026-08-01 04:01:22 +03:30
README.md docs(project): update project status, roadmap, and documentation 2026-08-07 05:58:12 +03:30
vite.config.js feat: Complete Phase 1 core logic and WP bridge setup 2026-08-01 04:01:22 +03:30


📄 فایل ۲: 04_Laravel/README.md (پوشه لاراول)

# 🚀 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.