| {{ $loop->iteration }} |
'{{ $d['nik_show'] ?? $d['nik'] }} |
{{ $d['nama_karyawan'] }} |
{{ $d['nama_jabatan'] }} |
{{ $d['kode_dept'] }} |
{{ $d['kode_cabang'] }} |
@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;
$total_potongan_istirahat = 0;
$rekap_istirahat = [];
@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 {
$has_schedule = false;
$nama_hari = getHari($tanggal_presensi);
if (isset($mapJadwalByDate[$tanggal_presensi])) $has_schedule = true;
elseif (isset($mapJadwalGrupByDate[$tanggal_presensi])) $has_schedule = true;
elseif (isset($mapJadwalByDay[$nama_hari])) $has_schedule = true;
else {
$keyDC = $d['kode_dept'] . '|' . $d['kode_cabang'];
$mapD = $jadwal_bydept[$keyDC] ?? [];
if (isset($mapD[$nama_hari])) $has_schedule = true;
elseif (isset($jadwal_global[$nama_hari])) $has_schedule = true;
}
$is_libur = !$has_schedule;
}
$tipe_hari = $is_libur ? 2 : 1;
// Cek snapshot lembur (data terkunci)
$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) !== null;
if ($snapshot_lembur) {
$jml_jam_lembur = $d[$tanggal_presensi]['jam_lembur_aktual'];
} else {
$lembur = hitungLembur($ceklembur_data);
$jml_jam_lembur = !empty($ceklembur_data) ? $lembur : 0;
}
$nama_hari = getHari($tanggal_presensi);
// O(1) libur lookup
$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 =
'' . e($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 .
'
';
$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;
if (!empty($d[$tanggal_presensi]['istirahat_out']) && !empty($d[$tanggal_presensi]['istirahat_in'])) {
$rekap_istirahat[] = '' . date('H:i', strtotime($d[$tanggal_presensi]['istirahat_out'])) . ' - ' . date('H:i', strtotime($d[$tanggal_presensi]['istirahat_in'])) . '';
} else {
$rekap_istirahat[] = 'Belum Absen';
}
$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_terlambat .
$ket_denda .
$ket_pulang_cepat .
$ket_potongan_jam .
$ket_jam_lembur;
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;
$ket =
'IZIN
' .
e($d[$tanggal_presensi]['keterangan_izin_absen']) .
'
PJ : ' .
formatAngkaDesimal($potongan_jam) .
' Jam';
@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
' .
e($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
' .
e($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) . '' : '';
$ket =
'Alpa
PJ : ' .
formatAngkaDesimal($potongan_jam) .
' Jam' .
$ket_denda_alpa;
@endphp
@endif
@else
@php
$bgcolor = 'red';
$textcolor = 'white';
$ket = '';
$potongan_jam = 0;
// Jika hari ini libur khusus karyawan, tandai libur
if (!empty($ceklibur)) {
$bgcolor = 'green';
$textcolor = 'white';
$jml_libur++;
$ket = e($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) {
// Ada jadwal tapi tidak ada presensi sama sekali → Alpa & potong full jam kerja
$jml_alfa++;
$potongan_jam = is_array($totalJamJadwal) ? $totalJamJadwal['total_jam'] : $totalJamJadwal;
// Untuk alpa yang belum ada di database, denda = 0
$denda = 0;
$ket =
'Alpa
PJ : ' .
formatAngkaDesimal($potongan_jam) .
' Jam';
}
}
// 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
{!! $ket !!}
|
@php
$tanggal_presensi = date('Y-m-d', strtotime('+1 day', strtotime($tanggal_presensi)));
@endphp
@endwhile
@if ($generalsetting->absen_istirahat == 1)
{!! implode(' ', $rekap_istirahat) !!}
@else
-
@endif
|
{{ formatAngka($total_denda) }} |
{{ formatAngkaDesimal($total_potongan_jam) }} |
{{ formatAngkaDesimal($total_jam_lembur) }} |
{{ $jml_hadir }} |
{{ $jml_izin }} |
{{ $jml_sakit }} |
{{ $jml_alfa }} |
{{ $jml_libur }} |
{{ $jml_terlambat }} |
{{ $jml_tidakscanmasuk }} |
{{ $jml_tidakscanpulang }} |
{{ $jml_pulangcepat }} |
@endforeach
{{-- LEGEND --}}