leftJoin('teknisis', 'kasbons.id_teknisi', '=', 'teknisis.id_teknisi') ->select('kasbons.*', 'teknisis.nama as nama_teknisi') ->orderBy('kasbons.created_at', 'desc') ->limit(5)->get(); $recentAbsensi = DB::table('absensis') ->leftJoin('teknisis', 'absensis.id_teknisi', '=', 'teknisis.id_teknisi') ->select('absensis.*', 'teknisis.nama as nama_teknisi') ->orderBy('absensis.tanggal', 'desc') ->limit(5)->get(); $recentPekerjaan = DB::table('penugasans') ->leftJoin('teknisis', 'penugasans.id_teknisi', '=', 'teknisis.id_teknisi') ->select('penugasans.*', 'teknisis.nama as nama_teknisi') ->orderBy('penugasans.created_at', 'desc') ->limit(5)->get(); return view('Admin.Laporan', compact( 'statistics', 'recentKasbon', 'recentAbsensi', 'recentPekerjaan' )); } catch (Exception $e) { \Log::error('Laporan Error: ' . $e->getMessage()); return back()->with('error', 'Gagal memuat laporan: ' . $e->getMessage()); } } /** * Get statistics for AJAX refresh */ public function statistics() { return response()->json([ 'success' => true, 'data' => Laporan::getStatistics() ]); } /** * Detailed Kasbon Report */ public function kasbon(Request $request) { $filters = $request->only(['tanggal_dari', 'tanggal_sampai', 'status', 'id_teknisi', 'search']); $data = Laporan::getKasbonData($filters)->paginate(15)->appends($filters); $teknisis = Teknisi::orderBy('nama')->get(); // Statistik ringkas kasbon $statsKasbon = [ 'total' => DB::table('kasbons')->count(), 'lunas' => DB::table('kasbons')->where('status', 'lunas')->count(), 'belum_lunas' => DB::table('kasbons')->where('status', 'belum_lunas')->count(), 'total_nominal' => DB::table('kasbons')->sum('jumlah_kasbon'), 'total_belum_lunas' => DB::table('kasbons')->where('status', 'belum_lunas')->sum('jumlah_kasbon'), ]; return view('Admin.Laporan.kasbon', compact('data', 'teknisis', 'filters', 'statsKasbon')); } /** * Detailed Teknisi/Kehadiran Report */ public function teknisi(Request $request) { $filters = $request->only(['tanggal_dari', 'tanggal_sampai', 'search']); $data = Laporan::getTeknisiData($filters)->get(); return view('Admin.Laporan.teknisi', compact('data', 'filters')); } /** * Detailed Absensi Report */ public function absensi(Request $request) { $filters = $request->only(['tanggal_dari', 'tanggal_sampai', 'status', 'id_teknisi', 'search', 'tanggal']); if (!empty($filters['tanggal'])) { $filters['tanggal_dari'] = $filters['tanggal']; $filters['tanggal_sampai'] = $filters['tanggal']; } $data = Laporan::getAbsensiData($filters)->paginate(15)->appends($filters); $teknisis = Teknisi::orderBy('nama')->get(); // Statistik absensi bulan ini $statsAbsensi = [ 'hadir' => DB::table('absensis')->where('status', 'hadir')->whereMonth('tanggal', date('m'))->whereYear('tanggal', date('Y'))->count(), 'izin' => DB::table('absensis')->where('status', 'izin')->whereMonth('tanggal', date('m'))->whereYear('tanggal', date('Y'))->count(), 'sakit' => DB::table('absensis')->where('status', 'sakit')->whereMonth('tanggal', date('m'))->whereYear('tanggal', date('Y'))->count(), 'alpha' => DB::table('absensis')->where('status', 'alpha')->whereMonth('tanggal', date('m'))->whereYear('tanggal', date('Y'))->count(), ]; return view('Admin.Laporan.absensi', compact('data', 'teknisis', 'filters', 'statsAbsensi')); } /** * Detailed Pekerjaan Report */ public function pekerjaan(Request $request) { $filters = $request->only(['tanggal_dari', 'tanggal_sampai', 'status', 'id_teknisi', 'search', 'tanggal']); if (!empty($filters['tanggal'])) { $filters['tanggal_dari'] = $filters['tanggal']; $filters['tanggal_sampai'] = $filters['tanggal']; } $data = Laporan::getPekerjaanData($filters)->paginate(15)->appends($filters); $teknisis = Teknisi::orderBy('nama')->get(); $statsPekerjaan = [ 'total' => DB::table('penugasans')->count(), 'selesai' => DB::table('penugasans')->where('status_pekerjaan', 'selesai')->count(), 'proses' => DB::table('penugasans')->where('status_pekerjaan', 'proses')->count(), 'pending' => DB::table('penugasans')->where('status_pekerjaan', 'pending')->count(), ]; return view('Admin.Laporan.pekerjaan', compact('data', 'teknisis', 'filters', 'statsPekerjaan')); } // ============================================================ // LAPORAN PENGGAJIAN & DATA TEKNISI // ============================================================ public function penggajian(Request $request) { $filters = $request->only(['tanggal_dari', 'tanggal_sampai', 'status', 'id_teknisi', 'search', 'tanggal']); if (!empty($filters['tanggal'])) { $filters['tanggal_dari'] = $filters['tanggal']; $filters['tanggal_sampai'] = $filters['tanggal']; } $query = DB::table('penggajians') ->leftJoin('teknisis', 'penggajians.id_teknisi', '=', 'teknisis.id_teknisi') ->select('penggajians.*', 'teknisis.nama as nama_teknisi') ->orderBy('penggajians.created_at', 'desc'); if (!empty($filters['id_teknisi'])) { $query->where('penggajians.id_teknisi', $filters['id_teknisi']); } if (!empty($filters['status'])) { $query->where('penggajians.status_pembayaran', $filters['status']); } if (!empty($filters['tanggal_dari'])) { $query->whereDate('penggajians.created_at', '>=', $filters['tanggal_dari']); } if (!empty($filters['tanggal_sampai'])) { $query->whereDate('penggajians.created_at', '<=', $filters['tanggal_sampai']); } $data = $query->paginate(15)->appends($filters); $teknisis = Teknisi::orderBy('nama')->get(); $statsPenggajian = [ 'total' => DB::table('penggajians')->count(), 'lunas' => DB::table('penggajians')->where('status_pembayaran', 'lunas')->count(), 'belum' => DB::table('penggajians')->where('status_pembayaran', 'belum_bayar')->count(), ]; return view('Admin.Laporan.penggajian', compact('data', 'teknisis', 'filters', 'statsPenggajian')); } public function dataTeknisi(Request $request) { $filters = $request->only(['status', 'search']); $query = Teknisi::query(); if (!empty($filters['search'])) { $query->where('nama', 'like', '%'.$filters['search'].'%'); } if (!empty($filters['status'])) { $query->where('status', $filters['status']); } $data = $query->paginate(15)->appends($filters); $statsTeknisi = [ 'total' => Teknisi::count(), 'aktif' => Teknisi::where('status', 'aktif')->count(), 'nonaktif' => Teknisi::where('status', 'nonaktif')->count(), ]; return view('Admin.Laporan.data_teknisi', compact('data', 'filters', 'statsTeknisi')); } // ============================================================ // CETAK LAPORAN (PRINT) METHODS // ============================================================ /** * Cetak Laporan Kasbon */ public function exportKasbon(Request $request) { $filters = $request->only(['tanggal_dari', 'tanggal_sampai', 'status', 'id_teknisi', 'search']); $data = Laporan::getKasbonData($filters)->get(); $title = 'Kasbon Teknisi'; $type = 'kasbon'; $columns = ['Nama Teknisi', 'Tanggal Pinjam', 'Jumlah Kasbon', 'Status', 'Keperluan']; return view('Admin.Laporan.print', compact('data', 'filters', 'title', 'type', 'columns')); } /** * Cetak Laporan Teknisi/Kehadiran */ public function exportTeknisi(Request $request) { $filters = $request->only(['tanggal_dari', 'tanggal_sampai', 'search']); $data = Laporan::getTeknisiData($filters)->get(); $title = 'Performa & Kehadiran Teknisi'; $type = 'teknisi'; $columns = ['Nama Teknisi', 'Status', 'Hadir', 'Izin', 'Sakit', 'Alpha', 'Total Hari', 'Persentase']; return view('Admin.Laporan.print', compact('data', 'filters', 'title', 'type', 'columns')); } /** * Cetak Laporan Absensi */ public function exportAbsensi(Request $request) { $filters = $request->only(['tanggal_dari', 'tanggal_sampai', 'status', 'id_teknisi', 'search']); $data = Laporan::getAbsensiData($filters)->get(); $title = 'Absensi Harian'; $type = 'absensi'; $columns = ['Nama Teknisi', 'Tanggal', 'Status Kehadiran', 'Keterangan']; return view('Admin.Laporan.print', compact('data', 'filters', 'title', 'type', 'columns')); } /** * Cetak Laporan Pekerjaan */ public function exportPekerjaan(Request $request) { $filters = $request->only(['tanggal_dari', 'tanggal_sampai', 'status', 'id_teknisi', 'search']); $data = Laporan::getPekerjaanData($filters)->get(); $title = 'Pekerjaan Teknisi'; $type = 'pekerjaan'; $columns = ['ID', 'Jenis Pekerjaan', 'Nama Teknisi', 'Status', 'Tgl Mulai', 'Tgl Selesai']; return view('Admin.Laporan.print', compact('data', 'filters', 'title', 'type', 'columns')); } /** * Cetak Laporan Penggajian */ public function exportPenggajian(Request $request) { $filters = $request->only(['tanggal_dari', 'tanggal_sampai', 'status', 'id_teknisi', 'search', 'tanggal']); if (!empty($filters['tanggal'])) { $filters['tanggal_dari'] = $filters['tanggal']; $filters['tanggal_sampai'] = $filters['tanggal']; } $query = DB::table('penggajians') ->leftJoin('teknisis', 'penggajians.id_teknisi', '=', 'teknisis.id_teknisi') ->select('penggajians.*', 'teknisis.nama as nama_teknisi') ->orderBy('penggajians.created_at', 'desc'); if (!empty($filters['id_teknisi'])) { $query->where('penggajians.id_teknisi', $filters['id_teknisi']); } if (!empty($filters['status'])) { $query->where('penggajians.status_pembayaran', $filters['status']); } if (!empty($filters['tanggal_dari'])) { $query->whereDate('penggajians.created_at', '>=', $filters['tanggal_dari']); } if (!empty($filters['tanggal_sampai'])) { $query->whereDate('penggajians.created_at', '<=', $filters['tanggal_sampai']); } $data = $query->get(); $title = 'Laporan Penggajian'; $type = 'penggajian'; $columns = ['Nama Teknisi', 'Periode', 'Total Gaji', 'Status Pembayaran']; return view('Admin.Laporan.print', compact('data', 'filters', 'title', 'type', 'columns')); } /** * Cetak Laporan Data Teknisi */ public function exportDataTeknisi(Request $request) { $filters = $request->only(['status', 'search']); $query = Teknisi::query(); if (!empty($filters['search'])) { $query->where('nama', 'like', '%'.$filters['search'].'%'); } if (!empty($filters['status'])) { $query->where('status', $filters['status']); } $data = $query->get(); $title = 'Data Teknisi'; $type = 'data_teknisi'; $columns = ['Nama Teknisi', 'Email', 'No Telepon', 'Tanggal Masuk', 'Status']; return view('Admin.Laporan.print', compact('data', 'filters', 'title', 'type', 'columns')); } /** * Generic export (from Ringkasan page) */ public function export(Request $request) { $jenis = $request->get('jenis_laporan', 'kasbon'); switch ($jenis) { case 'kasbon': return $this->exportKasbon($request); case 'teknisi': return $this->exportTeknisi($request); case 'absensi': return $this->exportAbsensi($request); case 'pekerjaan': return $this->exportPekerjaan($request); case 'penggajian': return $this->exportPenggajian($request); case 'data_teknisi': return $this->exportDataTeknisi($request); default: return back()->with('error', 'Jenis laporan tidak valid.'); } } }