DelayReason::class, 'weather_condition' => WeatherCondition::class, 'delay_date' => 'date', 'lost_hours' => 'decimal:2', ]; } public function task(): BelongsTo { return $this->belongsTo(Task::class); } public function reporter(): BelongsTo { return $this->belongsTo(User::class, 'reported_by'); } protected static function booted(): void { static::created(function (TaskDelay $td) { if (auth()->check() && $td->task) { $reason = $td->reason_type instanceof DelayReason ? $td->reason_type->label() : $td->reason_type; $dateStr = $td->delay_date ? $td->delay_date->format('Y-m-d') : 'unknown date'; $td->task->activities()->create([ 'user_id' => auth()->id(), 'description' => "logged delay: '{$reason}' on {$dateStr} ({$td->lost_hours}h lost).", 'type' => 'delay_add', ]); } }); static::updated(function (TaskDelay $td) { if (auth()->check() && $td->task) { $dirty = $td->getDirty(); $changes = []; if (array_key_exists('lost_hours', $dirty)) { $changes[] = "changed delay hours to {$td->lost_hours}h"; } if (array_key_exists('reason_type', $dirty)) { $reason = $td->reason_type instanceof DelayReason ? $td->reason_type->label() : $td->reason_type; $changes[] = "changed delay reason to '{$reason}'"; } if (!empty($changes)) { $td->task->activities()->create([ 'user_id' => auth()->id(), 'description' => "updated delay: " . implode(', ', $changes) . '.', 'type' => 'delay_update', ]); } } }); static::deleted(function (TaskDelay $td) { if (auth()->check() && $td->task) { $reason = $td->reason_type instanceof DelayReason ? $td->reason_type->label() : $td->reason_type; $dateStr = $td->delay_date ? $td->delay_date->format('Y-m-d') : 'unknown date'; $td->task->activities()->create([ 'user_id' => auth()->id(), 'description' => "removed delay: '{$reason}' on {$dateStr}.", 'type' => 'delay_remove', ]); } }); } // --- Accessors --- public function getIsWeatherRelatedAttribute(): bool { return $this->reason_type === DelayReason::Weather; } public function getLostDaysAttribute(): float { return round((float) $this->lost_hours / 8, 1); } }