generated from theradcoza/Laravel-Docker-Dev-Template
140 lines
3.2 KiB
PHP
140 lines
3.2 KiB
PHP
<?php
|
|
//Testing branch
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use OwenIt\Auditing\Contracts\Auditable;
|
|
|
|
class Shift extends Model implements Auditable
|
|
{
|
|
use HasFactory;
|
|
use \OwenIt\Auditing\Auditable;
|
|
|
|
protected $fillable = [
|
|
'title',
|
|
'shift_date',
|
|
'planned_start_time',
|
|
'planned_end_time',
|
|
'actual_start_time',
|
|
'actual_end_time',
|
|
'status',
|
|
'notes',
|
|
'created_by',
|
|
'started_by',
|
|
];
|
|
|
|
protected function casts(): array
|
|
{
|
|
return [
|
|
'shift_date' => 'date',
|
|
'actual_start_time' => 'datetime',
|
|
'actual_end_time' => 'datetime',
|
|
];
|
|
}
|
|
|
|
// --- Relationships ---
|
|
|
|
public function creator(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'created_by');
|
|
}
|
|
|
|
public function starter(): BelongsTo
|
|
{
|
|
return $this->belongsTo(User::class, 'started_by');
|
|
}
|
|
|
|
public function staff(): BelongsToMany
|
|
{
|
|
return $this->belongsToMany(User::class, 'shift_staff')
|
|
->withPivot('assigned_by')
|
|
->withTimestamps();
|
|
}
|
|
|
|
public function shiftStaff(): HasMany
|
|
{
|
|
return $this->hasMany(ShiftStaff::class);
|
|
}
|
|
|
|
public function attendances(): HasMany
|
|
{
|
|
return $this->hasMany(ShiftAttendance::class);
|
|
}
|
|
|
|
// --- State Checks ---
|
|
|
|
public function isPlanned(): bool
|
|
{
|
|
return $this->status === 'planned';
|
|
}
|
|
|
|
public function isInProgress(): bool
|
|
{
|
|
return $this->status === 'in_progress';
|
|
}
|
|
|
|
public function isCompleted(): bool
|
|
{
|
|
return $this->status === 'completed';
|
|
}
|
|
|
|
// --- Computed Attributes ---
|
|
|
|
public function getPlannedDurationHoursAttribute(): float
|
|
{
|
|
$start = \Carbon\Carbon::parse($this->planned_start_time);
|
|
$end = \Carbon\Carbon::parse($this->planned_end_time);
|
|
|
|
if ($end->lt($start)) {
|
|
$end->addDay();
|
|
}
|
|
|
|
return round($start->diffInMinutes($end) / 60, 2);
|
|
}
|
|
|
|
public function getActualDurationHoursAttribute(): ?float
|
|
{
|
|
if (!$this->actual_start_time || !$this->actual_end_time) {
|
|
return null;
|
|
}
|
|
|
|
return round($this->actual_start_time->diffInMinutes($this->actual_end_time) / 60, 2);
|
|
}
|
|
|
|
// --- Scopes ---
|
|
|
|
public function scopePlanned($query)
|
|
{
|
|
return $query->where('status', 'planned');
|
|
}
|
|
|
|
public function scopeInProgress($query)
|
|
{
|
|
return $query->where('status', 'in_progress');
|
|
}
|
|
|
|
public function scopeCompleted($query)
|
|
{
|
|
return $query->where('status', 'completed');
|
|
}
|
|
|
|
public function scopeForDate($query, $date)
|
|
{
|
|
return $query->where('shift_date', $date);
|
|
}
|
|
|
|
public function scopeForDateRange($query, $from, $to)
|
|
{
|
|
return $query->whereBetween('shift_date', [$from, $to]);
|
|
}
|
|
|
|
public function scopeForStaff($query, $userId)
|
|
{
|
|
return $query->whereHas('staff', fn ($q) => $q->where('users.id', $userId));
|
|
}
|
|
}
|