DHL Modul v0.5 Shipping Label ok

This commit is contained in:
Kevin Adametz 2025-08-22 18:18:26 +02:00
parent 480fdc65ed
commit 8fdaa0ba1d
122 changed files with 17938 additions and 2239 deletions

View file

@ -0,0 +1,149 @@
<?php
namespace Acme\Dhl\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use App\Models\ShoppingOrder;
/**
* DHL Shipment Model for both outbound shipments and returns
*/
class DhlShipment extends Model
{
protected $table = 'dhl_package_shipments';
protected $fillable = [
'order_id',
'dhl_shipment_no',
'routing_code',
'type',
'related_shipment_id',
'product_code',
'billing_number',
'weight_kg',
'label_format',
'label_path',
'status',
'tracking_status',
'last_tracked_at',
'api_response_data'
];
protected $casts = [
'api_response_data' => 'array',
'last_tracked_at' => 'datetime',
'weight_kg' => 'decimal:3'
];
public const STATUS_MAP = [
'pre-transit' => 'created',
'transit' => 'in_transit',
'out_for_delivery' => 'out_for_delivery',
'delivered' => 'delivered',
'exception' => 'exception',
'returned' => 'returned',
'failed' => 'failed',
'unknown' => 'unknown'
];
/**
* Get the tracking events for this shipment
*/
public function trackingEvents(): HasMany
{
return $this->hasMany(DhlTrackingEvent::class, 'shipment_id');
}
/**
* Get the related shopping order for this shipment
*/
public function shoppingOrder(): BelongsTo
{
return $this->belongsTo(ShoppingOrder::class, 'order_id');
}
/**
* Get the related shipment (for returns)
*/
public function relatedShipment(): BelongsTo
{
return $this->belongsTo(self::class, 'related_shipment_id');
}
/**
* Get returns for this shipment (if this is an outbound shipment)
*/
public function returns(): HasMany
{
return $this->hasMany(self::class, 'related_shipment_id');
}
/**
* Scope for outbound shipments
*/
public function scopeOutbound($query)
{
return $query->where('type', 'outbound');
}
/**
* Scope for return shipments
*/
public function scopeReturns($query)
{
return $query->where('type', 'return');
}
/**
* Scope for shipments by order
*/
public function scopeForOrder($query, int $orderId)
{
return $query->where('order_id', $orderId);
}
/**
* Check if this is a return shipment
*/
public function isReturn(): bool
{
return $this->type === 'return';
}
/**
* Check if this is an outbound shipment
*/
public function isOutbound(): bool
{
return $this->type === 'outbound';
}
/**
* Get the latest tracking status
*/
public function getLatestStatus(): ?string
{
return $this->trackingEvents()
->orderBy('event_time', 'desc')
->first()
?->status_text;
}
/**
* Check if shipment can be canceled
*/
public function canCancel(): bool
{
return in_array($this->status, ['created', 'pending']);
}
/**
* Check if shipment is delivered
*/
public function isDelivered(): bool
{
return $this->status === 'delivered';
}
}

View file

@ -0,0 +1,52 @@
<?php
namespace Acme\Dhl\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
/**
* DHL Tracking Event Model for detailed tracking history
*/
class DhlTrackingEvent extends Model
{
protected $table = 'dhl_package_tracking_events';
protected $fillable = [
'shipment_id',
'status_code',
'status_text',
'location',
'event_time',
'raw'
];
protected $casts = [
'raw' => 'array',
'event_time' => 'datetime'
];
/**
* Get the shipment this event belongs to
*/
public function shipment(): BelongsTo
{
return $this->belongsTo(DhlShipment::class, 'shipment_id');
}
/**
* Scope for events ordered by time
*/
public function scopeOrderedByTime($query, string $direction = 'desc')
{
return $query->orderBy('event_time', $direction);
}
/**
* Scope for recent events
*/
public function scopeRecent($query, int $days = 30)
{
return $query->where('event_time', '>=', now()->subDays($days));
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace Acme\Dhl\Models;
use Illuminate\Database\Eloquent\Model;
class ReturnLabel extends Model
{
protected $fillable = ['order_id', 'dhl_return_no', 'label_path'];
}

View file

@ -0,0 +1,19 @@
<?php
namespace Acme\Dhl\Models;
use Illuminate\Database\Eloquent\Model;
class Shipment extends Model
{
protected $fillable = ['order_id', 'carrier', 'dhl_shipment_no', 'product_code', 'billing_number', 'weight_kg', 'status', 'label_format', 'label_path', 'meta'];
protected $casts = ['meta' => 'array',];
public function labels()
{
return $this->hasMany(ShipmentLabel::class);
}
public function events()
{
return $this->hasMany(TrackingEvent::class);
}
}

View file

@ -0,0 +1,14 @@
<?php
namespace Acme\Dhl\Models;
use Illuminate\Database\Eloquent\Model;
class ShipmentLabel extends Model
{
protected $fillable = ['shipment_id', 'format', 'path'];
public function shipment()
{
return $this->belongsTo(Shipment::class);
}
}

View file

@ -0,0 +1,16 @@
<?php
namespace Acme\Dhl\Models;
use Illuminate\Database\Eloquent\Model;
class TrackingEvent extends Model
{
public $timestamps = false;
protected $fillable = ['shipment_id', 'status_code', 'status_text', 'location', 'event_time', 'raw'];
protected $casts = ['raw' => 'array', 'event_time' => 'datetime',];
public function shipment()
{
return $this->belongsTo(Shipment::class);
}
}