'date', 'tanggal_mulai' => 'datetime', 'tanggal_diselesaikan' => 'datetime', 'tanggal_garansi_mulai' => 'date', 'tanggal_garansi_selesai' => 'date', 'jarak_meter' => 'decimal:2', 'total_nilai_pekerjaan' => 'decimal:2', 'pakai_pipa_besi' => 'boolean', ]; // =================================== // RELATIONSHIPS // =================================== public function teknisi() { return $this->belongsTo(Teknisi::class, 'id_teknisi', 'id_teknisi'); } public function teknisiPertama() { return $this->teknisi(); } public function tarif() { return $this->belongsTo(TarifPekerjaan::class, 'id_tarif', 'id_tarif'); } public function timTeknisi() { return $this->hasMany(TimTeknisiPenugasan::class, 'id_penugasan', 'id_penugasan'); } public function items() { return $this->hasMany(PenugasanItem::class, 'id_penugasan', 'id_penugasan'); } // =================================== // ACCESSOR - FOTO URL // =================================== public function getFotoSuratUrlAttribute(): ?string { if (!$this->foto_surat) return null; return url('storage/' . $this->foto_surat); // ✅ url() bukan asset() } public function getFotoSebelumUrlAttribute(): ?string { if (!$this->foto_sebelum) return null; return url('storage/' . $this->foto_sebelum); } public function getFotoSesudahUrlAttribute(): ?string { if (!$this->foto_sesudah) return null; return url('storage/' . $this->foto_sesudah); } // =================================== // HELPER - TIM // =================================== public function getAllTimTeknisi() { return $this->timTeknisi()->with('teknisi')->get(); } public function countTotalTim(): int { return $this->timTeknisi()->count(); } public function countTimHadir(): int { return $this->timTeknisi()->where('status_kehadiran', 'hadir')->count(); } public function getOngkosPerOrang(): float { $jumlahHadir = $this->countTimHadir(); if ($jumlahHadir === 0 || !$this->total_nilai_pekerjaan) return 0; return $this->total_nilai_pekerjaan / $jumlahHadir; } // =================================== // HELPER - GARANSI // =================================== public function setGaransiMeteranAir($tanggalMulai = null) { $mulai = $tanggalMulai ? Carbon::parse($tanggalMulai) : Carbon::now(); $this->tanggal_garansi_mulai = $mulai; $this->tanggal_garansi_selesai = $mulai->copy()->addMonths(3); $this->catatan_garansi = 'Garansi 3 bulan untuk pemasangan meteran air (SR)'; } public function isGaransiAktif(): bool { if (!$this->tanggal_garansi_mulai || !$this->tanggal_garansi_selesai) return false; return now()->between($this->tanggal_garansi_mulai, $this->tanggal_garansi_selesai); } public function getSisaHariGaransi(): ?int { if (!$this->tanggal_garansi_selesai) return null; $sisa = now()->diffInDays($this->tanggal_garansi_selesai, false); return $sisa > 0 ? (int)$sisa : 0; } public function scopeGaransiAktif($query) { return $query->whereNotNull('tanggal_garansi_mulai') ->whereNotNull('tanggal_garansi_selesai') ->where('tanggal_garansi_selesai', '>=', now()); } // =================================== // HELPER - STATUS // =================================== public function isDetailLengkap(): bool { return !is_null($this->jenis_pekerjaan); } public function isSelesai(): bool { return $this->status_pekerjaan === 'selesai'; } public function getLabelJenisPekerjaanAttribute(): string { $labels = [ 'sr' => 'SR (Sambungan Rumah)', 'pengembangan_jaringan_pipa' => 'Pengembangan Jaringan Pipa', 'pengangkatan' => 'Pengangkatan', 'pemasangan_gate_valve' => 'Pemasangan Gate Valve', 'gali_urug' => 'Gali Urug', 'perbaikan_jaringan_pipa' => 'Perbaikan Jaringan Pipa', 'pengecatan_pipa_besi' => 'Pengecatan Pipa Besi', 'penyempurnaan_jaringan_pipa' => 'Penyempurnaan Jaringan Pipa', ]; return $labels[$this->jenis_pekerjaan] ?? '-'; } }