254 lines
7.5 KiB
PHP
254 lines
7.5 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Carbon\Carbon;
|
|
|
|
class ProgresKerja extends Model
|
|
{
|
|
use HasFactory;
|
|
|
|
protected $table = 'progres_kerjas'; // Ubah dari 'progres_kerja' ke 'progres_kerjas'
|
|
protected $primaryKey = 'id_progres';
|
|
|
|
protected $fillable = [
|
|
'id_penugasan',
|
|
'id_teknisi',
|
|
'tugas',
|
|
'deskripsi_progres',
|
|
'status_progres',
|
|
'persentase_pekerjaan',
|
|
'foto_progress',
|
|
'tanggal_update'
|
|
];
|
|
|
|
protected $casts = [
|
|
'tanggal_update' => 'datetime',
|
|
'persentase_pekerjaan' => 'integer',
|
|
];
|
|
|
|
// Status progres options
|
|
public static $statusProgres = [
|
|
'belum_mulai' => 'Belum Mulai',
|
|
'dalam_progres' => 'Dalam Progres',
|
|
'terhenti' => 'Terhenti',
|
|
'selesai' => 'Selesai',
|
|
'ditunda' => 'Ditunda'
|
|
];
|
|
|
|
// Boot method untuk auto update tanggal_update
|
|
protected static function boot()
|
|
{
|
|
parent::boot();
|
|
|
|
static::creating(function ($model) {
|
|
$model->tanggal_update = now();
|
|
});
|
|
|
|
static::updating(function ($model) {
|
|
$model->tanggal_update = now();
|
|
});
|
|
}
|
|
|
|
// Relationships
|
|
public function teknisi()
|
|
{
|
|
return $this->belongsTo(Teknisi::class, 'id_teknisi', 'id_teknisi');
|
|
}
|
|
|
|
public function penugasan()
|
|
{
|
|
return $this->belongsTo(Penugasan::class, 'id_penugasan', 'id_penugasan');
|
|
}
|
|
|
|
// Scopes
|
|
public function scopeByStatus($query, $status)
|
|
{
|
|
return $query->where('status_progres', $status);
|
|
}
|
|
|
|
public function scopeByTeknisi($query, $teknisiId)
|
|
{
|
|
return $query->where('id_teknisi', $teknisiId);
|
|
}
|
|
|
|
public function scopeByDateRange($query, $startDate = null, $endDate = null)
|
|
{
|
|
if ($startDate) {
|
|
$query->whereDate('tanggal_update', '>=', $startDate);
|
|
}
|
|
|
|
if ($endDate) {
|
|
$query->whereDate('tanggal_update', '<=', $endDate);
|
|
}
|
|
|
|
return $query;
|
|
}
|
|
|
|
// Accessors
|
|
public function getStatusFormattedAttribute()
|
|
{
|
|
return self::$statusProgres[$this->status_progres] ?? 'Unknown';
|
|
}
|
|
|
|
public function getStatusBadgeClassAttribute()
|
|
{
|
|
$badgeClasses = [
|
|
'belum_mulai' => 'badge-secondary',
|
|
'dalam_progres' => 'badge-primary',
|
|
'terhenti' => 'badge-danger',
|
|
'selesai' => 'badge-success',
|
|
'ditunda' => 'badge-warning'
|
|
];
|
|
|
|
return $badgeClasses[$this->status_progres] ?? 'badge-secondary';
|
|
}
|
|
|
|
public function getTanggalUpdateFormattedAttribute()
|
|
{
|
|
return $this->tanggal_update ? $this->tanggal_update->format('d/m/Y H:i') : '-';
|
|
}
|
|
|
|
public function getHasFotoAttribute()
|
|
{
|
|
return !empty($this->foto_progress);
|
|
}
|
|
|
|
public function getFotoProgressUrlAttribute()
|
|
{
|
|
if ($this->foto_progress) {
|
|
return asset('storage/progress_photos/' . $this->foto_progress);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public function getDaysSinceUpdateAttribute()
|
|
{
|
|
if ($this->tanggal_update) {
|
|
return $this->tanggal_update->diffInDays(now());
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// Methods
|
|
public function autoUpdateStatus()
|
|
{
|
|
$percentage = $this->persentase_pekerjaan;
|
|
|
|
if ($percentage == 0) {
|
|
$newStatus = 'belum_mulai';
|
|
} elseif ($percentage > 0 && $percentage < 100) {
|
|
$newStatus = 'dalam_progres';
|
|
} elseif ($percentage == 100) {
|
|
$newStatus = 'selesai';
|
|
} else {
|
|
return; // No change needed
|
|
}
|
|
|
|
// Only update if status is different
|
|
if ($this->status_progres !== $newStatus) {
|
|
$this->update(['status_progres' => $newStatus]);
|
|
}
|
|
}
|
|
|
|
public function canTransitionTo($newStatus)
|
|
{
|
|
$allowedTransitions = [
|
|
'belum_mulai' => ['dalam_progres', 'ditunda'],
|
|
'dalam_progres' => ['terhenti', 'selesai', 'ditunda'],
|
|
'terhenti' => ['dalam_progres', 'ditunda'],
|
|
'selesai' => [], // Cannot transition from completed
|
|
'ditunda' => ['belum_mulai', 'dalam_progres']
|
|
];
|
|
|
|
$currentStatus = $this->status_progres;
|
|
|
|
return in_array($newStatus, $allowedTransitions[$currentStatus] ?? []);
|
|
}
|
|
|
|
// Static methods
|
|
public static function getByTeknisi($teknisiId)
|
|
{
|
|
return self::with(['teknisi', 'penugasan'])
|
|
->where('id_teknisi', $teknisiId)
|
|
->orderBy('tanggal_update', 'desc')
|
|
->get();
|
|
}
|
|
|
|
public static function getRecentUpdates($limit = 10)
|
|
{
|
|
return self::with(['teknisi', 'penugasan'])
|
|
->orderBy('tanggal_update', 'desc')
|
|
->limit($limit)
|
|
->get();
|
|
}
|
|
|
|
public static function getStatistics()
|
|
{
|
|
$total = self::count();
|
|
$byStatus = self::selectRaw('status_progres, COUNT(*) as count')
|
|
->groupBy('status_progres')
|
|
->pluck('count', 'status_progres')
|
|
->toArray();
|
|
|
|
$statistics = [
|
|
'total' => $total,
|
|
'belum_mulai' => $byStatus['belum_mulai'] ?? 0,
|
|
'dalam_progres' => $byStatus['dalam_progres'] ?? 0,
|
|
'terhenti' => $byStatus['terhenti'] ?? 0,
|
|
'selesai' => $byStatus['selesai'] ?? 0,
|
|
'ditunda' => $byStatus['ditunda'] ?? 0,
|
|
];
|
|
|
|
// Add percentages
|
|
if ($total > 0) {
|
|
$statistics['completion_rate'] = round(($statistics['selesai'] / $total) * 100, 1);
|
|
$statistics['in_progress_rate'] = round(($statistics['dalam_progres'] / $total) * 100, 1);
|
|
} else {
|
|
$statistics['completion_rate'] = 0;
|
|
$statistics['in_progress_rate'] = 0;
|
|
}
|
|
|
|
return $statistics;
|
|
}
|
|
|
|
public static function getOverdueProgress($days = 7)
|
|
{
|
|
return self::with(['teknisi', 'penugasan'])
|
|
->whereIn('status_progres', ['dalam_progres', 'terhenti'])
|
|
->where('tanggal_update', '<', now()->subDays($days))
|
|
->orderBy('tanggal_update', 'asc')
|
|
->get();
|
|
}
|
|
|
|
public static function getProgressSummaryByTeknisi()
|
|
{
|
|
return self::with('teknisi')
|
|
->selectRaw('id_teknisi, status_progres, COUNT(*) as count')
|
|
->groupBy('id_teknisi', 'status_progres')
|
|
->get()
|
|
->groupBy('id_teknisi')
|
|
->map(function ($items) {
|
|
$teknisi = $items->first()->teknisi;
|
|
$summary = [
|
|
'teknisi_id' => $teknisi->id_teknisi,
|
|
'teknisi_nama' => $teknisi->nama,
|
|
'total' => $items->sum('count'),
|
|
'belum_mulai' => 0,
|
|
'dalam_progres' => 0,
|
|
'terhenti' => 0,
|
|
'selesai' => 0,
|
|
'ditunda' => 0,
|
|
];
|
|
|
|
foreach ($items as $item) {
|
|
$summary[$item->status_progres] = $item->count;
|
|
}
|
|
|
|
return $summary;
|
|
})
|
|
->values();
|
|
}
|
|
} |