Car-Repairs-Shop/app/Models/Appointment.php
sackey e839d40a99
Some checks are pending
linter / quality (push) Waiting to run
tests / ci (push) Waiting to run
Initial commit
2025-07-30 17:15:50 +00:00

215 lines
5.3 KiB
PHP

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Carbon\Carbon;
class Appointment extends Model
{
/** @use HasFactory<\Database\Factories\AppointmentFactory> */
use HasFactory;
protected $fillable = [
'customer_id',
'vehicle_id',
'assigned_technician_id',
'scheduled_datetime',
'estimated_duration_minutes',
'appointment_type',
'service_requested',
'customer_notes',
'internal_notes',
'status',
'checked_in_at',
'completed_at',
'service_order_id',
];
protected $casts = [
'scheduled_datetime' => 'datetime',
'checked_in_at' => 'datetime',
'completed_at' => 'datetime',
'estimated_duration_minutes' => 'integer',
];
// Relationships
public function customer(): BelongsTo
{
return $this->belongsTo(Customer::class);
}
public function vehicle(): BelongsTo
{
return $this->belongsTo(Vehicle::class);
}
public function assignedTechnician(): BelongsTo
{
return $this->belongsTo(Technician::class, 'assigned_technician_id');
}
public function serviceOrder(): BelongsTo
{
return $this->belongsTo(ServiceOrder::class);
}
// Scopes
public function scopeToday($query)
{
return $query->whereDate('scheduled_datetime', today());
}
public function scopeUpcoming($query)
{
return $query->where('scheduled_datetime', '>=', now());
}
public function scopeForTechnician($query, $technicianId)
{
return $query->where('assigned_technician_id', $technicianId);
}
public function scopeByStatus($query, $status)
{
return $query->where('status', $status);
}
public function scopeInDateRange($query, $startDate, $endDate)
{
return $query->whereBetween('scheduled_datetime', [$startDate, $endDate]);
}
// Accessors & Mutators
public function getFormattedDateTimeAttribute(): string
{
return $this->scheduled_datetime->format('M j, Y g:i A');
}
public function getFormattedDateAttribute(): string
{
return $this->scheduled_datetime->format('M j, Y');
}
public function getFormattedTimeAttribute(): string
{
return $this->scheduled_datetime->format('g:i A');
}
public function getEndTimeAttribute(): Carbon
{
return $this->scheduled_datetime->addMinutes($this->estimated_duration_minutes);
}
public function getFormattedEndTimeAttribute(): string
{
return $this->end_time->format('g:i A');
}
public function getStatusColorAttribute(): string
{
return match($this->status) {
'scheduled' => 'blue',
'confirmed' => 'green',
'in_progress' => 'yellow',
'completed' => 'emerald',
'cancelled' => 'red',
'no_show' => 'gray',
default => 'blue'
};
}
public function getTypeColorAttribute(): string
{
return match($this->appointment_type) {
'maintenance' => 'blue',
'repair' => 'red',
'inspection' => 'yellow',
'estimate' => 'purple',
'pickup' => 'green',
'delivery' => 'indigo',
default => 'blue'
};
}
// Helper Methods
public function canBeModified(): bool
{
return in_array($this->status, ['scheduled', 'confirmed']) &&
$this->scheduled_datetime->isFuture();
}
public function canBeCheckedIn(): bool
{
return $this->status === 'confirmed' &&
$this->scheduled_datetime->isPast() &&
!$this->checked_in_at;
}
public function canBeCompleted(): bool
{
return in_array($this->status, ['confirmed', 'in_progress']) &&
$this->checked_in_at;
}
public function isOverdue(): bool
{
return $this->status === 'scheduled' &&
$this->scheduled_datetime->isPast();
}
public function getDurationInHours(): float
{
return round($this->estimated_duration_minutes / 60, 1);
}
// Status Management
public function confirm(): bool
{
if ($this->status === 'scheduled') {
return $this->update(['status' => 'confirmed']);
}
return false;
}
public function checkIn(): bool
{
if ($this->canBeCheckedIn()) {
return $this->update([
'status' => 'in_progress',
'checked_in_at' => now()
]);
}
return false;
}
public function complete(): bool
{
if ($this->canBeCompleted()) {
return $this->update([
'status' => 'completed',
'completed_at' => now()
]);
}
return false;
}
public function cancel(): bool
{
if ($this->canBeModified()) {
return $this->update(['status' => 'cancelled']);
}
return false;
}
public function markNoShow(): bool
{
if ($this->isOverdue()) {
return $this->update(['status' => 'no_show']);
}
return false;
}
}