ifnex/04_Laravel/app/Models/Shipment.php
Kazem Alghasi 75fd65be2b feat(api): expand shipment data fields and enhance tracking security
Implement additional address and identification fields for both sender
and receiver across the WordPress plugin and Laravel API. This includes
state, postal code, and national ID/passport information.

Key changes:
- Added database migration to include postal and national ID fields in
  the shipments table.
- Updated WordPress order form shortcodes and JavaScript to capture
  new address fields.
- Refactored Laravel `CustomerOrderController` validation and storage
  to support expanded shipment data.
- Implemented tiered data visibility in `TrackController` to protect
  PII, providing masked data to anonymous users and full data to
  owners/admins.
- Fixed weight-based rate lookup logic in `PriceCalculatorService` to
  correctly select the appropriate shipping tier.
2026-10-29 00:51:50 +03:30

212 lines
5.1 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use App\Traits\Auditable;
class Shipment extends Model
{
use Auditable;
protected $fillable = [
'awb_no',
'forwarder',
'direction',
'type',
'status',
'review_state',
'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',
'cod_amount',
'declared_value',
// Import Invoice Fields
'brand_fee',
'report_fee',
'customs_clearance_cost',
'order_registration_fee',
'other_clearance_charges',
'exchange_rate',
'goods_nature',
'invoice_currency',
// Sender
'sender_name',
'sender_company',
'sender_phone',
'sender_email',
'sender_address',
'sender_city',
'sender_zip',
'sender_id_number',
'sender_state',
'sender_postal_code',
'sender_national_id',
// Receiver
'receiver_name',
'receiver_company',
'receiver_phone',
'receiver_email',
'receiver_address',
'receiver_city',
'receiver_zip',
'receiver_id_number',
'receiver_state',
'receiver_postal_code',
'receiver_national_id',
// Customs
'reason_for_export',
'content_description',
'customer_notes',
// User
'user_id',
];
protected $casts = [
'weight' => 'decimal:3',
'volumetric_weight' => 'decimal:3',
'chargeable_weight' => 'decimal:3',
'status' => \App\Enums\ShipmentStatus::class,
'review_state' => \App\Enums\ReviewState::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 user(): BelongsTo
{
return $this->belongsTo(User::class);
}
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);
}
public function reviews(): HasMany
{
return $this->hasMany(ShipmentReview::class)
->orderBy('revision_no');
}
/**
* چک‌لیست‌های عملیاتی مرسوله
*/
public function checklists(): HasMany
{
return $this->hasMany(ShipmentChecklist::class)
->orderBy('created_at', 'desc');
}
/**
* تعهدنامه‌های مرسوله (instance‌های پرشده توسط مشتری)
*/
public function commitmentForms(): HasMany
{
return $this->hasMany(ShipmentCommitmentForm::class)
->orderBy('created_at', 'desc');
}
/**
* تاریخچه تغییرات وضعیت مرسوله
*/
public function statusHistories(): HasMany
{
return $this->hasMany(ShipmentStatusHistory::class)
->orderBy('created_at', 'desc');
}
/**
* اعتبارها (بدهی‌های چندارزی) مرتبط با این مرسوله
*/
public function credits(): HasMany
{
return $this->hasMany(CustomerCredit::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';
}
}