Introduce a shipment status history system to audit status changes, including the reason for change and the user responsible. This includes a new `ShipmentStatusHistory` model and a bulk action in the Filament ShipmentResource to transition statuses. Enhance the rate import workflow by adding a downloadable Excel template and refactoring the `ImportRatesPage` to use the modern Filament form schema. - Add `ShipmentStatusHistory` model and migration - Add bulk `changeStatus` action to `ShipmentResource` - Add `source` field to tracking events - Implement `ShippingRatesTemplateExport` for rate template downloads - Refactor `ImportRatesPage` form implementation and UI - Add `statusHistories` relationship to `Shipment` model
104 lines
3.3 KiB
PHP
104 lines
3.3 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 = [
|
|
'user_id', 'awb_no', 'forwarder', 'direction', 'type', 'status', 'reason_for_export',
|
|
'weight', 'volumetric_weight', 'chargeable_weight', 'dimensions',
|
|
'shipping_price', 'extra_service', 'packing_cost', 'domestic_pickup', 'domestic_delivery',
|
|
'warehousing_cost', 'vat_amount', 'discount', 'total_fee', 'net_dirham', 'net_rial',
|
|
'from_country_id', 'to_country_id',
|
|
'sender_name', 'sender_company', 'sender_phone', 'sender_email',
|
|
'sender_address', 'sender_city', 'sender_state', 'sender_zip', 'sender_id_number',
|
|
'receiver_name', 'receiver_company', 'receiver_phone', 'receiver_email',
|
|
'receiver_address', 'receiver_city', 'receiver_state', 'receiver_zip', 'receiver_id_number',
|
|
'customer_notes', 'cod_amount', 'declared_value', 'content_description',
|
|
];
|
|
|
|
protected function casts(): array
|
|
{
|
|
return [
|
|
'direction' => \App\Enums\ShipmentDirection::class,
|
|
'type' => \App\Enums\ShipmentType::class,
|
|
'status' => \App\Enums\ShipmentStatus::class,
|
|
'weight' => 'decimal:2',
|
|
'volumetric_weight' => 'decimal:2',
|
|
'chargeable_weight' => 'decimal:2',
|
|
'shipping_price' => 'decimal:2',
|
|
'extra_service' => 'decimal:2',
|
|
'packing_cost' => 'decimal:2',
|
|
'domestic_pickup' => 'decimal:2',
|
|
'domestic_delivery' => 'decimal:2',
|
|
'warehousing_cost' => 'decimal:2',
|
|
'vat_amount' => 'decimal:2',
|
|
'discount' => 'decimal:2',
|
|
'total_fee' => 'decimal:2',
|
|
'net_dirham' => 'decimal:2',
|
|
'net_rial' => 'decimal:2',
|
|
'cod_amount' => 'decimal:2',
|
|
'declared_value' => 'decimal:2',
|
|
];
|
|
}
|
|
|
|
public function user(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
public function statusHistories(): HasMany
|
|
{
|
|
return $this->hasMany(ShipmentStatusHistory::class)->orderByDesc('created_at');
|
|
}
|
|
|
|
public function isParcel(): bool
|
|
{
|
|
return $this->type === \App\Enums\ShipmentType::Parcel;
|
|
}
|
|
|
|
public function isDocument(): bool
|
|
{
|
|
return $this->type !== \App\Enums\ShipmentType::Parcel;
|
|
}
|
|
|
|
public function getInvoiceTotalUsdAttribute(): float
|
|
{
|
|
return $this->items->sum('total_usd');
|
|
}
|
|
|
|
public function packages(): HasMany
|
|
{
|
|
return $this->hasMany(ShipmentPackage::class)->orderBy('package_no');
|
|
}
|
|
}
|