✅ Multi-Package Support (3.5.1) - Add shipment_packages migration and ShipmentPackage model - Add packages() relation to Shipment model - Update CustomerOrderController to accept packages[] array - Auto-calculate volumetric weight from dimensions (L*W*H/5000) - Repeater UI for adding/removing packages - Real-time summary of total weights ✅ Invoice Form for PARCEL (3.5.2) - New step in order form (only for PARCEL type) - Customs items: description, HS Code, quantity, unit price (USD) - Auto-calculate total per item and invoice total - Maximum 9 items - 5-step order form structure ✅ PDF Redesign (3.5.4) - Install picqer/php-barcode-generator - Redesign AWB with barcode, From/To, Value, Service, Type - Redesign Invoice with 9-row table, legal declaration - Redesign Label to A5 landscape with large barcode - DOC/PARCEL condition (only PARCEL has invoice) - Barcode as base64 embed ✅ Technical Fixes (3.5.5) - Add Enum casts to Shipment model (status, direction, type) - Fix deselectAfterCompletion -> deselectRecordsAfterCompletion - Migration for shipment_items (row_number, unit_price) - Migration to make name nullable - Fix Enum method names (DocNormal/DocEconomy) ✅ Tracking Test (3.5.6) - Update TrackController with status_label - Redesign tracking page with beautiful timeline - Status box with colored badge - Timeline with date, description, location, source - Carrier mappings section Documentation: - Update README, Laravel_README, Roadmap, Checklist - Add IFNEX_Meeting_Summary.md for client presentation - Update IFNEX_I18N_Strategy.md (moved to deploy phase) Phase 3.5 — 90% complete (i18n moved to deploy phase)"
142 lines
3.2 KiB
PHP
142 lines
3.2 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
|
|
class Shipment extends Model
|
|
{
|
|
protected $fillable = [
|
|
'awb_no',
|
|
'forwarder',
|
|
'direction',
|
|
'type',
|
|
'status',
|
|
'from_country_id',
|
|
'to_country_id',
|
|
// Weight & Dimensions
|
|
'weight',
|
|
'volumetric_weight',
|
|
'chargeable_weight',
|
|
'dimensions',
|
|
// Financial
|
|
'shipping_price',
|
|
'extra_service',
|
|
'domestic_pickup',
|
|
'packing_cost',
|
|
'domestic_delivery',
|
|
'warehousing_cost',
|
|
'discount',
|
|
'vat_amount',
|
|
'total_fee',
|
|
'net_dirham',
|
|
'net_rial',
|
|
'invoice_total_usd',
|
|
// Sender
|
|
'sender_name',
|
|
'sender_company',
|
|
'sender_phone',
|
|
'sender_email',
|
|
'sender_address',
|
|
'sender_city',
|
|
'sender_zip',
|
|
'sender_id_number',
|
|
// Receiver
|
|
'receiver_name',
|
|
'receiver_company',
|
|
'receiver_phone',
|
|
'receiver_email',
|
|
'receiver_address',
|
|
'receiver_city',
|
|
'receiver_zip',
|
|
'receiver_id_number',
|
|
// Customs
|
|
'reason_for_export',
|
|
'content_description',
|
|
];
|
|
|
|
protected $casts = [
|
|
'weight' => 'decimal:3',
|
|
'volumetric_weight' => 'decimal:3',
|
|
'chargeable_weight' => 'decimal:3',
|
|
'status' => \App\Enums\ShipmentStatus::class,
|
|
'direction' => \App\Enums\ShipmentDirection::class,
|
|
'type' => \App\Enums\ShipmentType::class,
|
|
];
|
|
|
|
// === Relationships ===
|
|
|
|
public function fromCountry(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Country::class, 'from_country_id');
|
|
}
|
|
|
|
public function toCountry(): BelongsTo
|
|
{
|
|
return $this->belongsTo(Country::class, 'to_country_id');
|
|
}
|
|
|
|
public function items(): HasMany
|
|
{
|
|
return $this->hasMany(ShipmentItem::class);
|
|
}
|
|
|
|
public function carrierMappings(): HasMany
|
|
{
|
|
return $this->hasMany(ShipmentCarrierMapping::class);
|
|
}
|
|
|
|
public function trackingEvents(): HasMany
|
|
{
|
|
return $this->hasMany(ShipmentTrackingEvent::class);
|
|
}
|
|
|
|
/**
|
|
* بستههای مرسوله (Multi-Package)
|
|
*/
|
|
public function packages(): HasMany
|
|
{
|
|
return $this->hasMany(ShipmentPackage::class);
|
|
}
|
|
|
|
// === Scopes ===
|
|
|
|
public function scopeByAwb($query, string $awbNo)
|
|
{
|
|
return $query->where('awb_no', $awbNo);
|
|
}
|
|
|
|
public function scopeExport($query)
|
|
{
|
|
return $query->where('direction', 'export');
|
|
}
|
|
|
|
public function scopeImport($query)
|
|
{
|
|
return $query->where('direction', 'import');
|
|
}
|
|
|
|
// === Helpers ===
|
|
|
|
/**
|
|
* دریافت آخرین رویداد ترکینگ
|
|
*/
|
|
public function latestTrackingEvent()
|
|
{
|
|
return $this->trackingEvents()
|
|
->orderBy('event_date', 'desc')
|
|
->orderBy('event_time', 'desc')
|
|
->first();
|
|
}
|
|
|
|
/**
|
|
* آیا مرسوله تحویل داده شده؟
|
|
*/
|
|
public function isDelivered(): bool
|
|
{
|
|
return $this->status === 'delivered';
|
|
}
|
|
}
|