partial update create kpi and progress bar
This commit is contained in:
168
app/Models/KpiAchievement.php
Normal file
168
app/Models/KpiAchievement.php
Normal file
@@ -0,0 +1,168 @@
|
||||
<?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 KpiAchievement extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'kpi_target_id',
|
||||
'target_value',
|
||||
'actual_value',
|
||||
'achievement_percentage',
|
||||
'year',
|
||||
'month',
|
||||
'notes'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'achievement_percentage' => '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;
|
||||
}
|
||||
}
|
||||
61
app/Models/KpiTarget.php
Normal file
61
app/Models/KpiTarget.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
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\HasMany;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class KpiTarget extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'target_value',
|
||||
'is_active',
|
||||
'description'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'is_active' => 'boolean'
|
||||
];
|
||||
|
||||
protected $attributes = [
|
||||
'is_active' => true
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the user that owns the KPI target
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the achievements for this target
|
||||
*/
|
||||
public function achievements(): HasMany
|
||||
{
|
||||
return $this->hasMany(KpiAchievement::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scope to get active targets
|
||||
*/
|
||||
public function scopeActive($query)
|
||||
{
|
||||
return $query->where('is_active', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if target is currently active
|
||||
*/
|
||||
public function isCurrentlyActive(): bool
|
||||
{
|
||||
return $this->is_active;
|
||||
}
|
||||
}
|
||||
@@ -132,4 +132,64 @@ class User extends Authenticatable
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all KPI targets for the User
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function kpiTargets()
|
||||
{
|
||||
return $this->hasMany(KpiTarget::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all KPI achievements for the User
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function kpiAchievements()
|
||||
{
|
||||
return $this->hasMany(KpiAchievement::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user is mechanic
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isMechanic()
|
||||
{
|
||||
return $this->hasRole('mechanic');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current KPI target (no longer filtered by year/month)
|
||||
*
|
||||
* @return KpiTarget|null
|
||||
*/
|
||||
public function getCurrentKpiTarget()
|
||||
{
|
||||
return $this->kpiTargets()
|
||||
->where('is_active', true)
|
||||
->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get KPI achievement for specific year and month
|
||||
*
|
||||
* @param int $year
|
||||
* @param int $month
|
||||
* @return KpiAchievement|null
|
||||
*/
|
||||
public function getKpiAchievement($year = null, $month = null)
|
||||
{
|
||||
$year = $year ?? now()->year;
|
||||
$month = $month ?? now()->month;
|
||||
|
||||
return $this->kpiAchievements()
|
||||
->where('year', $year)
|
||||
->where('month', $month)
|
||||
->first();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user