'date', 'planned_start' => 'date', 'planned_end' => 'date', 'actual_start' => 'date', 'actual_end' => 'date', 'progress' => 'decimal:2', 'metadata' => 'array', ]; public function trackable(): MorphTo { return $this->morphTo(); } /** * Scope for a specific date range */ public function scopeDateRange($query, $from, $to) { return $query->whereBetween('snapshot_date', [$from, $to]); } /** * Scope for specific trackable */ public function scopeForTrackable($query, $model, $id = null) { $query->where('trackable_type', $model); if ($id) { $query->where('trackable_id', $id); } return $query; } /** * Get latest snapshot for a trackable */ public static function latestFor($model, $id): ?self { return static::forTrackable($model, $id) ->latest('snapshot_date') ->first(); } /** * Get progress trend (last N snapshots) */ public static function trendFor($model, $id, int $limit = 10): array { return static::forTrackable($model, $id) ->orderBy('snapshot_date') ->take($limit) ->get(['snapshot_date', 'progress', 'method']) ->toArray(); } }