@if ($generalsetting->logo && Storage::exists('public/logo/' . $generalsetting->logo)) Logo Perusahaan @else Logo Default @endif

LAPORAN PRESENSI
{{ $generalsetting->nama_perusahaan }}
PERIODE {{ date('d-m-Y', strtotime($periode_dari)) }} - {{ date('d-m-Y', strtotime($periode_sampai)) }}

{{ $generalsetting->alamat }}
{{ $generalsetting->telepon }}
@csrf @if (!empty($request_params['kode_cabang'])) @endif @if (!empty($request_params['kode_dept'])) @endif @if (!empty($request_params['nik'])) @endif @if (!empty($request_params['jenis_upah'])) @endif
@csrf @if (!empty($request_params['kode_cabang'])) @endif @if (!empty($request_params['kode_dept'])) @endif @if (!empty($request_params['nik'])) @endif @if (!empty($request_params['jenis_upah'])) @endif
@php $tanggal_presensi = $periode_dari; @endphp @while (strtotime($tanggal_presensi) <= strtotime($periode_sampai)) @php $tanggal_presensi = date('Y-m-d', strtotime('+1 day', strtotime($tanggal_presensi))); @endphp @endwhile @php $tanggal_presensi = $periode_dari; @endphp @while (strtotime($tanggal_presensi) <= strtotime($periode_sampai)) @php $tanggal_presensi = date('Y-m-d', strtotime('+1 day', strtotime($tanggal_presensi))); @endphp @endwhile @foreach ($laporan_presensi as $d) @php $tanggal_presensi = $periode_dari; // Mapping jadwal untuk NIK ini dari berbagai sumber $mapJadwalByDate = $jadwal_bydate[$d['nik']] ?? []; $mapJadwalGrupByDate = $jadwal_grup_bydate[$d['nik']] ?? []; $mapJadwalByDay = $jadwal_byday[$d['nik']] ?? []; @endphp @php $total_denda = 0; $total_potongan_jam = 0; $total_jam_lembur = 0; $jml_hadir = 0; $jml_sakit = 0; $jml_izin = 0; $jml_cuti = 0; $jml_libur = 0; $jml_alfa = 0; $jml_terlambat = 0; $jml_pulangcepat = 0; $jml_tidakscanmasuk = 0; $jml_tidakscanpulang = 0; $lemburKhusus = $lembur_khusus_map[$d['nik']] ?? null; @endphp @while (strtotime($tanggal_presensi) <= strtotime($periode_sampai)) @php $denda = 0; $potongan_jam = 0; // Optimized: Check libur using pre-loaded data (no DB query) $is_libur_nasional = isset($libur_nasional_dates[$tanggal_presensi]); if ($is_libur_nasional) { $is_libur = true; } else { // Check if karyawan has a schedule for this date (same 5-level priority) $has_schedule = false; $nama_hari_check = getHari($tanggal_presensi); if (isset($mapJadwalByDate[$tanggal_presensi])) $has_schedule = true; elseif (isset($mapJadwalGrupByDate[$tanggal_presensi])) $has_schedule = true; elseif (isset($mapJadwalByDay[$nama_hari_check])) $has_schedule = true; else { $keyDC = $d['kode_dept'] . '|' . $d['kode_cabang']; $mapD = $jadwal_bydept[$keyDC] ?? []; if (isset($mapD[$nama_hari_check])) $has_schedule = true; elseif (isset($jadwal_global[$nama_hari_check])) $has_schedule = true; } $is_libur = !$has_schedule; } $tipe_hari = $is_libur ? 2 : 1; // Cek apakah data lembur sudah di-snapshot (dikunci) $lembur_key = $d['nik'] . '|' . $tanggal_presensi; $ceklembur_data = $datalembur_indexed[$lembur_key] ?? []; $snapshot_lembur = isset($d[$tanggal_presensi]) && $d[$tanggal_presensi]['jam_lembur_aktual'] !== null; if ($snapshot_lembur) { // Gunakan data snapshot dari tabel presensi $jml_jam_lembur = $d[$tanggal_presensi]['is_lembur_khusus'] ? $d[$tanggal_presensi]['jam_lembur_aktual'] : $d[$tanggal_presensi]['jam_lembur_netto']; } else { // Hitung secara live (belum dikunci) — O(1) indexed lookup $lembur_aktual = hitungLembur($ceklembur_data); $jam_netto_harian = $lembur_aktual > 0 ? hitungJamNetto($lembur_aktual, $tipe_hari) : 0; // Jika ada lembur khusus, gunakan JAM AKTUAL (Gross) if ($lemburKhusus) { $jml_jam_lembur = $lembur_aktual; } else { $jml_jam_lembur = $jam_netto_harian; } } $nama_hari = getHari($tanggal_presensi); // O(1) libur lookup for display purposes $libur_key = $d['nik'] . '|' . $tanggal_presensi; $ceklibur = $datalibur_indexed[$libur_key] ?? ($datalibur_by_tanggal[$tanggal_presensi] ?? []); @endphp @if (isset($d[$tanggal_presensi])) @if ($d[$tanggal_presensi]['status'] == 'h') @php $bgcolor = ''; $textcolor = ''; $jml_hadir++; $ket_nama_jam_kerja = '

' . $d[$tanggal_presensi]['nama_jam_kerja'] . '

'; $ket_jadwal_kerja = '

' . date('H:i', strtotime($d[$tanggal_presensi]['jam_masuk'])) . ' - ' . date('H:i', strtotime($d[$tanggal_presensi]['jam_pulang'])) . '

'; $jam_masuk = $tanggal_presensi . ' ' . $d[$tanggal_presensi]['jam_masuk']; $jam_in = !empty($d[$tanggal_presensi]['jam_in']) ? date('H:i', strtotime($d[$tanggal_presensi]['jam_in'])) : '✘'; $jam_out = !empty($d[$tanggal_presensi]['jam_out']) ? date('H:i', strtotime($d[$tanggal_presensi]['jam_out'])) : '✘'; $color_jam_in = !empty($d[$tanggal_presensi]['jam_in']) ? 'green' : 'red'; $color_jam_out = !empty($d[$tanggal_presensi]['jam_out']) ? 'green' : 'red'; $ket_presensi = '

' . $jam_in . ' - ' . $jam_out . '

'; $istirahat_out = !empty($d[$tanggal_presensi]['istirahat_out']) ? date('H:i', strtotime($d[$tanggal_presensi]['istirahat_out'])) : '✘'; $istirahat_in = !empty($d[$tanggal_presensi]['istirahat_in']) ? date('H:i', strtotime($d[$tanggal_presensi]['istirahat_in'])) : '✘'; $color_istirahat_in = !empty($d[$tanggal_presensi]['istirahat_in']) ? '#3498db' : 'red'; $color_istirahat_out = !empty($d[$tanggal_presensi]['istirahat_out']) ? '#3498db' : 'red'; $ket_istirahat = ""; if ($generalsetting->absen_istirahat == 1) { $ket_istirahat = '

' . $istirahat_in . ' - ' . $istirahat_out . '

'; } $terlambat = hitungjamterlambat($d[$tanggal_presensi]['jam_in'], $jam_masuk); $color_terlambat = $terlambat != null ? $terlambat['color'] : ''; $ket_terlambat = $terlambat != null ? '

' . $terlambat['show_laporan'] . '

' : ''; // Cek apakah denda sudah dikunci (ada di database) $denda_dari_db = isset($d[$tanggal_presensi]['denda']) && $d[$tanggal_presensi]['denda'] !== null ? $d[$tanggal_presensi]['denda'] : null; if ($denda_dari_db !== null) { // Gunakan denda dari database (sudah dikunci) $denda = $denda_dari_db; // Hitung potongan jam tetap menggunakan rumus if ($terlambat != null) { if ($terlambat['desimal_terlambat'] < 1) { $potongan_jam_terlambat = 0; } else { $potongan_jam_terlambat = $terlambat['desimal_terlambat'] > $d[$tanggal_presensi]['total_jam'] ? $d[$tanggal_presensi]['total_jam'] : $terlambat['desimal_terlambat']; } if ($terlambat['menitterlambat'] > 0) { $jml_terlambat++; } } else { $potongan_jam_terlambat = 0; } } else { // Hitung denda menggunakan rumus (belum dikunci) if ($terlambat != null) { if ($terlambat['desimal_terlambat'] < 1) { $potongan_jam_terlambat = 0; $denda = hitungdenda($denda_list, $terlambat['menitterlambat']); } else { $potongan_jam_terlambat = $terlambat['desimal_terlambat'] > $d[$tanggal_presensi]['total_jam'] ? $d[$tanggal_presensi]['total_jam'] : $terlambat['desimal_terlambat']; $denda = 0; } if ($terlambat['menitterlambat'] > 0) { $jml_terlambat++; } } else { $potongan_jam_terlambat = 0; $denda = 0; } } $ket_denda = $denda != 0 ? '

Denda : ' . formatAngka($denda) . '

' : ''; $pulangcepat = hitungpulangcepat( $tanggal_presensi, $d[$tanggal_presensi]['jam_out'], $d[$tanggal_presensi]['jam_pulang'], $d[$tanggal_presensi]['istirahat'], $d[$tanggal_presensi]['jam_awal_istirahat'], $d[$tanggal_presensi]['jam_akhir_istirahat'], $d[$tanggal_presensi]['lintashari'], ); $pulangcepat = $pulangcepat > $d[$tanggal_presensi]['total_jam'] ? $d[$tanggal_presensi]['total_jam'] : $pulangcepat; if ($pulangcepat != null) { $jml_pulangcepat++; } $ket_pulang_cepat = $pulangcepat != null ? '

PC : ' . $pulangcepat . ' Jam

' : ''; $color_pulang_cepat = $pulangcepat != null ? 'red' : ''; $potongan_tidak_absen_masuk_atau_pulang = empty($d[$tanggal_presensi]['jam_out']) || empty($d[$tanggal_presensi]['jam_in']) ? $d[$tanggal_presensi]['total_jam'] : 0; $potongan_istirahat = hitungPotonganIstirahat( $d[$tanggal_presensi]['istirahat_out'], $d[$tanggal_presensi]['istirahat_in'], $d[$tanggal_presensi]['jam_awal_istirahat'], $d[$tanggal_presensi]['jam_akhir_istirahat'] ); $status_potongan_istirahat = $d[$tanggal_presensi]['status_potongan_istirahat'] ?? $generalsetting->potongan_istirahat; $potongan_jam = $potongan_tidak_absen_masuk_atau_pulang == 0 ? $pulangcepat + $potongan_jam_terlambat + ($status_potongan_istirahat == 1 ? $potongan_istirahat : 0) : $potongan_tidak_absen_masuk_atau_pulang; $status_potongan_harian = isset($d[$tanggal_presensi]['status_potongan']) ? $d[$tanggal_presensi]['status_potongan'] : $generalsetting->status_potongan_jam; if ($status_potongan_harian == 0) { $potongan_jam = 0; } $ket_potongan_jam = !empty($potongan_jam) ? '

PJ: ' . formatAngkaDesimal($potongan_jam) . ' Jam

' : ''; $ket_jam_lembur = $jml_jam_lembur > 0 ? '

Lembur :' . $jml_jam_lembur . ' Jam

' : ''; $ket = $ket_nama_jam_kerja . $ket_jadwal_kerja . $ket_presensi . $ket_istirahat . $ket_terlambat . $ket_denda . $ket_pulang_cepat . $ket_potongan_jam . $ket_jam_lembur; // $ket = // $ket_nama_jam_kerja . // $ket_jadwal_kerja . // '
' . // $ket_presensi . // '
' . // $ket_terlambat . // '
' . // $ket_denda . // $ket_pulang_cepat . // '
' . // $ket_potongan_jam; if (empty($d[$tanggal_presensi]['jam_in'])) { $jml_tidakscanmasuk++; } if (empty($d[$tanggal_presensi]['jam_out'])) { $jml_tidakscanpulang++; } @endphp @elseif($d[$tanggal_presensi]['status'] == 'i') @php $bgcolor = '#dea51f'; $textcolor = 'white'; $jml_izin++; $potongan_jam = $d[$tanggal_presensi]['total_jam']; // Cek apakah denda sudah dikunci (untuk izin biasanya 0, tapi ambil dari DB jika ada) $denda_dari_db = isset($d[$tanggal_presensi]['denda']) && $d[$tanggal_presensi]['denda'] !== null ? $d[$tanggal_presensi]['denda'] : null; $denda = $denda_dari_db !== null ? $denda_dari_db : 0; $pjl_izin = $generalsetting->status_potongan_jam == 1 ? '

PJ : ' . formatAngkaDesimal($potongan_jam) . ' Jam

' : ''; $ket = '

IZIN

' . $d[$tanggal_presensi]['keterangan_izin_absen'] . '

' . $pjl_izin; if ($generalsetting->status_potongan_jam == 0) { $potongan_jam = 0; } @endphp @elseif($d[$tanggal_presensi]['status'] == 's') @php $bgcolor = '#c8075b'; $textcolor = 'white'; $jml_sakit++; // Cek apakah denda sudah dikunci (untuk sakit biasanya 0, tapi ambil dari DB jika ada) $denda_dari_db = isset($d[$tanggal_presensi]['denda']) && $d[$tanggal_presensi]['denda'] !== null ? $d[$tanggal_presensi]['denda'] : null; $denda = $denda_dari_db !== null ? $denda_dari_db : 0; $ket = '

SAKIT

' . $d[$tanggal_presensi]['keterangan_izin_sakit'] . ' '; @endphp @elseif($d[$tanggal_presensi]['status'] == 'c') @php $bgcolor = '#0164b5'; $textcolor = 'white'; $jml_cuti++; // Cek apakah denda sudah dikunci (untuk cuti biasanya 0, tapi ambil dari DB jika ada) $denda_dari_db = isset($d[$tanggal_presensi]['denda']) && $d[$tanggal_presensi]['denda'] !== null ? $d[$tanggal_presensi]['denda'] : null; $denda = $denda_dari_db !== null ? $denda_dari_db : 0; $ket = '

CUTI

' . $d[$tanggal_presensi]['keterangan_izin_cuti'] . ''; @endphp @elseif($d[$tanggal_presensi]['status'] == 'a') @php $bgcolor = 'red'; $textcolor = 'white'; $jml_alfa++; $potongan_jam = $d[$tanggal_presensi]['total_jam']; // Cek apakah denda sudah dikunci (ada di database) $denda_dari_db = isset($d[$tanggal_presensi]['denda']) && $d[$tanggal_presensi]['denda'] !== null ? $d[$tanggal_presensi]['denda'] : null; // Untuk alpa, denda biasanya 0 atau null, tapi tetap ambil dari DB jika sudah dikunci $denda = $denda_dari_db !== null ? $denda_dari_db : 0; $ket_denda_alpa = $denda != 0 ? '

Denda : ' . formatAngka($denda) . '

' : ''; $status_potongan_harian_alpa = isset($d[$tanggal_presensi]['status_potongan']) ? $d[$tanggal_presensi]['status_potongan'] : $generalsetting->status_potongan_jam; $pjl_alpa = $status_potongan_harian_alpa == 1 ? 'PJ : ' . formatAngkaDesimal($potongan_jam) . ' Jam' : ''; $ket = '

Alpa

' . $pjl_alpa . $ket_denda_alpa; if ($status_potongan_harian_alpa == 0) { $potongan_jam = 0; } @endphp @endif @else @php $is_future = strtotime($tanggal_presensi) > strtotime(date('Y-m-d')); $bgcolor = $is_future ? '' : 'red'; $textcolor = $is_future ? '' : 'white'; $ket = ''; $potongan_jam = 0; // Jika hari ini libur khusus karyawan, tandai libur if (!empty($ceklibur)) { $bgcolor = 'green'; $textcolor = 'white'; $jml_libur++; $ket = $ceklibur[0]['keterangan']; } else { // Bukan libur → cek jadwal berurutan: // 1) Jadwal by-date per karyawan $totalJamJadwal = $mapJadwalByDate[$tanggal_presensi] ?? null; // 2) Kalau kosong, cek jadwal grup by-date if ($totalJamJadwal === null) { $totalJamJadwal = $mapJadwalGrupByDate[$tanggal_presensi] ?? null; } // 3) Kalau masih kosong, cek jadwal by-day per karyawan if ($totalJamJadwal === null) { $totalJamJadwal = $mapJadwalByDay[$nama_hari] ?? null; } // 4) Kalau masih kosong, cek jadwal by-day per departemen & cabang if ($totalJamJadwal === null) { $keyDeptCabang = $d['kode_dept'] . '|' . $d['kode_cabang']; $mapDept = $jadwal_bydept[$keyDeptCabang] ?? []; $totalJamJadwal = $mapDept[$nama_hari] ?? null; } // 5) Kalau masih kosong, cek jadwal global if ($totalJamJadwal === null) { $totalJamJadwal = $jadwal_global[$nama_hari] ?? null; } if ($totalJamJadwal !== null) { // Handle if totalJamJadwal is an array (new format) $tJam = is_array($totalJamJadwal) ? $totalJamJadwal['total_jam'] : $totalJamJadwal; // Ada jadwal tapi tidak ada presensi sama sekali → Alpa & potong full jam kerja if (!$is_future) { $jml_alfa++; $potongan_jam = $tJam; // Untuk alpa yang belum ada di database, denda = 0 $denda = 0; $pjl_alpa_else = $generalsetting->status_potongan_jam == 1 ? 'PJ : ' . formatAngkaDesimal($potongan_jam) . ' Jam' : ''; $ket = '

Alpa

' . $pjl_alpa_else; if ($generalsetting->status_potongan_jam == 0) { $potongan_jam = 0; } } } } // Jika ada lembur terpisah, tetap tampilkan info lembur if (!empty($ceklembur_data)) { $bgcolor = 'white'; $textcolor = 'black'; $ket_jam_lembur = '

Lembur :' . $jml_jam_lembur . ' Jam

'; $ket = $ket_jam_lembur; } @endphp @endif @php $total_denda += $denda; $total_potongan_jam += $potongan_jam; $total_jam_lembur += $jml_jam_lembur; $bgcolor = $is_libur ? 'orange' : $bgcolor; @endphp @php $tanggal_presensi = date('Y-m-d', strtotime('+1 day', strtotime($tanggal_presensi))); @endphp @endwhile {{-- This block ensures that if status_potongan_jam is OFF, daily PJ is not displayed --}} @php $status_potongan_final = isset($d[$tanggal_presensi]['status_potongan']) ? $d[$tanggal_presensi]['status_potongan'] : $generalsetting->status_potongan_jam; @endphp @if ($status_potongan_final == 1) @if (!empty($ket_potongan_jam) || !empty($ket_denda_alpa)) @php $ket .= !empty($ket_potongan_jam) ? $ket_potongan_jam : ''; $ket .= !empty($ket_denda_alpa) ? $ket_denda_alpa : ''; @endphp @endif @endif @php if ($generalsetting->status_potongan_jam == 0) { $total_potongan_jam = 0; } elseif ($total_potongan_jam > $generalsetting->total_jam_bulan) { $total_potongan_jam = $generalsetting->total_jam_bulan; } @endphp @endforeach
No Nik Nama Karyawan Jabatan Dept Cabang Tanggal Denda Pot. Jam Lembur Rekap
{{ getHari(date('Y-m-d', strtotime($tanggal_presensi))) }}Hadir Izin Sakit Alfa Libur Terlambat Tidak Scan Masuk Tidak Scan Pulang Pulang Cepat
{{ date('d', strtotime($tanggal_presensi)) }}
{{ $loop->iteration }} '{{ $d['nik_show'] ?? $d['nik'] }} {{ $d['nama_karyawan'] }} {{ $d['nama_jabatan'] }} {{ $d['kode_dept'] }} {{ $d['kode_cabang'] }} @if(isset($d[$tanggal_presensi]['status_potongan'])) @endif {!! $ket !!} {{ formatAngka($total_denda) }} {{ formatAngkaDesimal($total_potongan_jam) }} {{ formatAngkaDesimal($total_jam_lembur) }} @if ($lemburKhusus) @endif {{ $jml_hadir }} {{ $jml_izin }} {{ $jml_sakit }} {{ $jml_alfa }} {{ $jml_libur }} {{ $jml_terlambat }} {{ $jml_tidakscanmasuk }} {{ $jml_tidakscanpulang }} {{ $jml_pulangcepat }}
Kode Keterangan
PC Pulang Cepat
PJ Potongan Jam