'decimal:2', 'year' => 'integer', 'month' => 'integer' ]; protected $attributes = [ 'actual_value' => 0, 'achievement_percentage' => 0 ]; /** * Get the user that owns the achievement */ public function user(): BelongsTo { return $this->belongsTo(User::class); } /** * Get the KPI target for this achievement */ public function kpiTarget(): BelongsTo { return $this->belongsTo(KpiTarget::class); } /** * Scope to get achievements for specific year and month */ public function scopeForPeriod($query, $year, $month) { return $query->where('year', $year)->where('month', $month); } /** * Scope to get achievements for current month */ public function scopeCurrentMonth($query) { return $query->where('year', now()->year)->where('month', now()->month); } /** * Scope to get achievements within year range */ public function scopeWithinYearRange($query, $startYear, $endYear) { return $query->whereBetween('year', [$startYear, $endYear]); } /** * Scope to get achievements for specific user */ public function scopeForUser($query, $userId) { return $query->where('user_id', $userId); } /** * Get achievement status */ public function getStatusAttribute(): string { if ($this->achievement_percentage >= 100) { return 'exceeded'; } elseif ($this->achievement_percentage >= 80) { return 'good'; } elseif ($this->achievement_percentage >= 60) { return 'fair'; } else { return 'poor'; } } /** * Get status color for display */ public function getStatusColorAttribute(): string { return match($this->status) { 'exceeded' => 'success', 'good' => 'info', 'fair' => 'warning', 'poor' => 'danger', default => 'secondary' }; } /** * Get period display name (e.g., "Januari 2024") */ public function getPeriodDisplayName(): string { $monthNames = [ 1 => 'Januari', 2 => 'Februari', 3 => 'Maret', 4 => 'April', 5 => 'Mei', 6 => 'Juni', 7 => 'Juli', 8 => 'Agustus', 9 => 'September', 10 => 'Oktober', 11 => 'November', 12 => 'Desember' ]; return $monthNames[$this->month] . ' ' . $this->year; } /** * Get period start date */ public function getPeriodStartDate(): Carbon { return Carbon::createFromDate($this->year, $this->month, 1); } /** * Get period end date */ public function getPeriodEndDate(): Carbon { return Carbon::createFromDate($this->year, $this->month, 1)->endOfMonth(); } /** * Get target value (from stored value or from relation) */ public function getTargetValueAttribute(): int { // Return stored target value if available, otherwise get from relation return $this->target_value ?? $this->kpiTarget?->target_value ?? 0; } /** * Get current target value from relation (for comparison) */ public function getCurrentTargetValueAttribute(): int { return $this->kpiTarget?->target_value ?? 0; } /** * Check if stored target value differs from current target value */ public function hasTargetValueChanged(): bool { return $this->target_value !== $this->current_target_value; } }