migrate to gtea from bistbucket
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Modules\RestaurantDelivery\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Modules\RestaurantDelivery\Enums\DeliveryStatus;
|
||||
|
||||
class DeliveryStatusHistory extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public const TABLE_NAME = 'restaurant_delivery_status_history';
|
||||
|
||||
protected $table = self::TABLE_NAME;
|
||||
|
||||
protected $fillable = [
|
||||
'delivery_id',
|
||||
'rider_id',
|
||||
'from_status',
|
||||
'to_status',
|
||||
'changed_by_type',
|
||||
'changed_by_id',
|
||||
'latitude',
|
||||
'longitude',
|
||||
'notes',
|
||||
'meta',
|
||||
'duration_from_previous',
|
||||
'duration_from_start',
|
||||
'changed_at',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'latitude' => 'decimal:7',
|
||||
'longitude' => 'decimal:7',
|
||||
'meta' => 'array',
|
||||
'changed_at' => 'datetime',
|
||||
];
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::creating(function ($history) {
|
||||
// Calculate durations
|
||||
$delivery = Delivery::find($history->delivery_id);
|
||||
|
||||
if ($delivery) {
|
||||
// Duration from delivery creation
|
||||
$history->duration_from_start = $delivery->created_at->diffInSeconds(now());
|
||||
|
||||
// Duration from previous status
|
||||
$previousHistory = static::where('delivery_id', $history->delivery_id)
|
||||
->orderBy('changed_at', 'desc')
|
||||
->first();
|
||||
|
||||
if ($previousHistory) {
|
||||
$history->duration_from_previous = $previousHistory->changed_at->diffInSeconds(now());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Relationships
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public function delivery(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Delivery::class, 'delivery_id');
|
||||
}
|
||||
|
||||
public function rider(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Rider::class, 'rider_id');
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Scopes
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public function scopeForDelivery($query, int $deliveryId)
|
||||
{
|
||||
return $query->where('delivery_id', $deliveryId);
|
||||
}
|
||||
|
||||
public function scopeByStatus($query, string $status)
|
||||
{
|
||||
return $query->where('to_status', $status);
|
||||
}
|
||||
|
||||
public function scopeRecent($query)
|
||||
{
|
||||
return $query->orderBy('changed_at', 'desc');
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Accessors
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public function getFromStatusEnumAttribute(): ?DeliveryStatus
|
||||
{
|
||||
return $this->from_status ? DeliveryStatus::tryFrom($this->from_status) : null;
|
||||
}
|
||||
|
||||
public function getToStatusEnumAttribute(): DeliveryStatus
|
||||
{
|
||||
return DeliveryStatus::from($this->to_status);
|
||||
}
|
||||
|
||||
public function getFromStatusLabelAttribute(): ?string
|
||||
{
|
||||
return $this->from_status_enum?->label();
|
||||
}
|
||||
|
||||
public function getToStatusLabelAttribute(): string
|
||||
{
|
||||
return $this->to_status_enum->label();
|
||||
}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Methods
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
public function getDurationFormatted(): string
|
||||
{
|
||||
if (! $this->duration_from_previous) {
|
||||
return '-';
|
||||
}
|
||||
|
||||
$seconds = $this->duration_from_previous;
|
||||
|
||||
if ($seconds < 60) {
|
||||
return "{$seconds}s";
|
||||
}
|
||||
|
||||
$minutes = floor($seconds / 60);
|
||||
$remainingSeconds = $seconds % 60;
|
||||
|
||||
if ($minutes < 60) {
|
||||
return "{$minutes}m {$remainingSeconds}s";
|
||||
}
|
||||
|
||||
$hours = floor($minutes / 60);
|
||||
$remainingMinutes = $minutes % 60;
|
||||
|
||||
return "{$hours}h {$remainingMinutes}m";
|
||||
}
|
||||
|
||||
public function hasLocation(): bool
|
||||
{
|
||||
return $this->latitude !== null && $this->longitude !== null;
|
||||
}
|
||||
|
||||
public function getCoordinates(): ?array
|
||||
{
|
||||
if (! $this->hasLocation()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
'lat' => $this->latitude,
|
||||
'lng' => $this->longitude,
|
||||
];
|
||||
}
|
||||
|
||||
public static function getTimeline(int $deliveryId): array
|
||||
{
|
||||
return static::forDelivery($deliveryId)
|
||||
->orderBy('changed_at')
|
||||
->get()
|
||||
->map(fn ($history) => [
|
||||
'status' => $history->to_status,
|
||||
'label' => $history->to_status_label,
|
||||
'color' => $history->to_status_enum->color(),
|
||||
'icon' => $history->to_status_enum->icon(),
|
||||
'changed_at' => $history->changed_at->toIso8601String(),
|
||||
'changed_at_human' => $history->changed_at->diffForHumans(),
|
||||
'duration' => $history->getDurationFormatted(),
|
||||
'notes' => $history->notes,
|
||||
'location' => $history->getCoordinates(),
|
||||
'changed_by' => $history->changed_by_type,
|
||||
])
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user