@php
$bd = is_array($breakdown ?? null) ? $breakdown : [];
$allowFixed = (float) ($bd['allowance_fixed'] ?? 0);
$allowPosition = (float) ($bd['allowance_position'] ?? 0);
$allowSkill = (float) ($bd['allowance_skill'] ?? 0);
$allowMedicalHousing = (float) ($bd['allowance_medical_housing'] ?? 0);
$allowOther = (float) ($bd['allowance_other'] ?? 0);
$allowTotal = (float) ($bd['allowance_total'] ?? 0);
$overtimeRate = (float) ($bd['overtime_rate'] ?? 0);
$incentive = (float) (($bd['incentive_amount'] ?? 0));
$overtimeNominal = (float) (($bd['overtime_nominal'] ?? 0));
$reimburse = (float) (($bd['reimburse_nominal'] ?? 0));
$specialPayrollBonusNominal = (float) (($bd['special_overtime_payroll_bonus_nominal'] ?? 0));
$specialSeparateBonusNominal = (float) (($bd['special_overtime_separate_bonus_nominal'] ?? 0));
$specialSummary = is_array($bd['special_overtime_summary'] ?? null) ? $bd['special_overtime_summary'] : [];
$bpjsDetailRows = is_array($bd['bpjs_details'] ?? null) ? $bd['bpjs_details'] : [];
$bpjsSummary = is_array($bd['bpjs_summary'] ?? null) ? $bd['bpjs_summary'] : [];
$bpjsSourceMode = (string) ($bd['bpjs_source_mode'] ?? 'live_period');
$bpjsEffectiveDate = (string) ($bd['bpjs_effective_date'] ?? $effectiveEnd ?? '');
$bpjsGeneralRow = collect($bpjsDetailRows)->firstWhere('basis_type', 'general');
$bpjsJpRow = collect($bpjsDetailRows)->firstWhere('basis_type', 'jp');
$bpjsHealthRow = collect($bpjsDetailRows)->firstWhere('basis_type', 'health');
$bpjsBasisGeneralDisplay = (float) ($bpjsGeneralRow['basis_source_nominal'] ?? ($bd['bpjs_basis_general_nominal'] ?? 0));
$bpjsBasisJpDisplay = (float) ($bpjsJpRow['basis_source_nominal'] ?? ($bd['bpjs_basis_jp_nominal'] ?? 0));
$bpjsBasisHealthDisplay = (float) ($bpjsHealthRow['basis_source_nominal'] ?? ($bd['bpjs_basis_health_nominal'] ?? 0));
$pph21Method = (string) ($bd['pph21_method'] ?? 'legacy_flat_rate');
$pph21PtkpStatus = (string) ($bd['pph21_ptkp_status'] ?? '');
$pph21TerCategory = (string) ($bd['pph21_ter_category'] ?? '');
$pph21TaxableGross = (float) ($bd['pph21_taxable_gross'] ?? 0);
$pph21CalculationDetails = is_array($bd['pph21_calculation_details'] ?? null) ? $bd['pph21_calculation_details'] : [];
$pph21RuleCode = (string) ($pph21CalculationDetails['rule_set_code'] ?? '');
$pph21CalculationDate = (string) ($pph21CalculationDetails['calculation_date'] ?? $effectiveEnd ?? '');
$pph21HasNpwp = array_key_exists('has_npwp', $pph21CalculationDetails) ? (bool) $pph21CalculationDetails['has_npwp'] : null;
$pph21BracketMin = isset($pph21CalculationDetails['bracket_min']) ? (float) $pph21CalculationDetails['bracket_min'] : null;
$pph21BracketMax = isset($pph21CalculationDetails['bracket_max']) ? (float) $pph21CalculationDetails['bracket_max'] : null;
$pph21GrossComponents = is_array($pph21CalculationDetails['gross_components'] ?? null) ? $pph21CalculationDetails['gross_components'] : [];
$pph21GrossReductions = is_array($pph21CalculationDetails['gross_reductions'] ?? null) ? $pph21CalculationDetails['gross_reductions'] : [];
$pph21GrossBeforeDeductions = (float) ($pph21CalculationDetails['gross_before_internal_deductions'] ?? $pph21TaxableGross);
$pph21LegacyBasis = (float) ($pph21CalculationDetails['legacy_basis'] ?? $pph21TaxableGross);
$pph21FormulaBasis = $pph21Method === 'legacy_flat_rate' ? $pph21LegacyBasis : $pph21TaxableGross;
$pph21RawResult = round($pph21FormulaBasis * (float) $pph21Rate, 2);
$pph21FormulaLabel = $pph21Method === 'ter_monthly'
? 'Bruto Kena Pajak x Tarif TER'
: ($pph21Method === 'legacy_flat_rate' ? 'Basis Fallback x Tarif Fallback' : 'PPh21 dinonaktifkan');
$pph21IsSnapshot = !empty($payment);
$pph21MethodLabel = match ($pph21Method) {
'ter_monthly' => 'TER Bulanan',
'legacy_flat_rate' => 'Fallback Tarif Lama',
'disabled' => 'Dinonaktifkan',
default => strtoupper(str_replace('_', ' ', $pph21Method)),
};
// "Penambah": tunjangan + insentif + upah lembur + reimburse approved.
$additionsTotal = max(0.0, $allowTotal + $incentive + $overtimeNominal + $reimburse);
$dedAbsence = (float) (($bd['absence_deduction_nominal'] ?? 0));
$dedLate = (float) (($bd['late_deduction_nominal'] ?? 0));
$dynamicDeductionRows = collect(is_array($bd['dynamic_deduction_components'] ?? null) ? $bd['dynamic_deduction_components'] : [])
->filter(fn ($row) => (float) ($row['amount'] ?? 0) > 0)
->values();
$dedDynamic = (float) ($bd['dynamic_deduction_nominal'] ?? $dynamicDeductionRows->sum(fn ($row) => (float) ($row['amount'] ?? 0)));
$dedBpjs = (float) ($bpjsNominal ?? 0);
$dedPph21 = (float) ($pph21Nominal ?? 0);
$deductionsTotal = max(0.0, $dedAbsence + $dedLate + $dedDynamic + $dedBpjs + $dedPph21);
$grossNominalDisplay = (float) ($bd['gross_nominal'] ?? 0);
$grossBeforeInternalDeductionsDisplay = max(0.0, $grossNominalDisplay + $dedAbsence + $dedLate);
$salaryScheme = (string) ($bd['salary_scheme'] ?? '');
$absenceMode = (string) ($bd['absence_deduction_mode'] ?? '');
// Samakan indikator HK web dengan detail attendance/PDF: basis jam, bukan hitung hari integer.
$payrollBasisDisplay = is_array($payrollBasis ?? null) ? $payrollBasis : [];
$hkHoursPerDayDisplay = (float) ($payrollBasisDisplay['hours_per_day'] ?? ($profil->jam_per_hari ?? 8));
$hkBaseHoursDisplay = (float) ($payrollBasisDisplay['monthly_hour_base'] ?? (((float) ($profil->hk_basis ?? 21)) * $hkHoursPerDayDisplay));
$hkBasisDisplay = $hkHoursPerDayDisplay > 0 ? ($hkBaseHoursDisplay / $hkHoursPerDayDisplay) : (float) ($profil->hk_basis ?? 21);
$sumNormalHoursDisplay = 0.0;
$deficitHoursDisplay = 0.0;
foreach (($dailyRows ?? []) as $detailRow) {
$sumNormalHoursDisplay += max(0.0, (float) ($detailRow['normal_hours'] ?? 0));
$dayCredit = $resolvePayrollDayCredit((array) $detailRow, $hkHoursPerDayDisplay, $profil);
if (($dayCredit['hk_flag'] ?? 0) === 1) {
$deficitHoursDisplay += (float) ($dayCredit['deficit_hours'] ?? 0.0);
}
}
$jamTidakMasukDisplay = max(0.0, $deficitHoursDisplay);
$jamMasukNormalDisplay = max(0.0, $hkBaseHoursDisplay - $jamTidakMasukDisplay);
$hkMasukDisplay = $hkHoursPerDayDisplay > 0 ? ($jamMasukNormalDisplay / $hkHoursPerDayDisplay) : 0.0;
$rawOvertimeHoursDisplay = (float) ($overtimeHours ?? ($bd['overtime_hours'] ?? 0));
$weightedOvertimeHoursDisplay = (float) ($bd['weighted_overtime_hours'] ?? $rawOvertimeHoursDisplay);
$calculatedBaseSalaryDisplay = max(0.0, $grossBeforeInternalDeductionsDisplay - $allowTotal - $incentive - $overtimeNominal);
$subtotalIncomeDisplay = max(0.0, $calculatedBaseSalaryDisplay + $allowTotal + $incentive + $overtimeNominal + $reimburse);
$grandTakePayDisplay = (float) ($netNominal ?? ($bd['net_nominal'] ?? 0));
$unapprovedHourRows = collect($dailyRows ?? [])
->filter(function ($row) {
$isApproved = (bool) ($row['is_approved'] ?? false);
if ($isApproved || !empty($row['leave_tag_label'])) {
return false;
}
$in = trim((string) ($row['in_time'] ?? ''));
$out = trim((string) ($row['out_time'] ?? ''));
$hasInOut = $in !== '' && $in !== '-' && $out !== '' && $out !== '-';
$hasHours = (float) ($row['actual_hours'] ?? 0) > 0
|| (float) ($row['overtime_hours'] ?? 0) > 0
|| (float) ($row['overtime_hours_gross'] ?? 0) > 0;
return $hasInOut || $hasHours;
})
->values();
$unapprovedDateCount = $unapprovedHourRows
->pluck('work_date')
->filter()
->unique()
->count();
$unapprovedDatePreview = $unapprovedHourRows
->pluck('work_date')
->filter()
->unique()
->take(10)
->implode(', ');
$unapprovedActualHours = $unapprovedHourRows
->sum(fn ($row) => (float) ($row['actual_hours'] ?? 0));
@endphp
@if ($unapprovedDateCount > 0)
Catatan approval:
ada {{ $unapprovedDateCount }} tanggal dengan jam/log belum approve.
Jam pada tanggal tersebut belum dianggap final di payroll.
@if ($unapprovedActualHours > 0)
Estimasi jam log belum approve: {{ number_format($unapprovedActualHours, 2, ',', '.') }} jam.
@endif
@if ($unapprovedDatePreview !== '')
Tanggal: {{ $unapprovedDatePreview }}{{ $unapprovedDateCount > 10 ? ', ...' : '' }}
@endif
@endif
Basis Jam Profil{{ number_format($hkBaseHoursDisplay, 2, ',', '.') }} jam
HK basis: {{ number_format($hkBasisDisplay, 2, ',', '.') }} x {{ number_format($hkHoursPerDayDisplay, 2, ',', '.') }} jam
Total Jam Kurang{{ number_format($jamTidakMasukDisplay, 2, ',', '.') }} jam
Pengurang dari basis jam profil
HK Masuk Riil{{ number_format($hkMasukDisplay, 2, ',', '.') }}/{{ number_format($hkBasisDisplay, 2, ',', '.') }}
Jam normal: {{ number_format($jamMasukNormalDisplay, 2, ',', '.') }} / {{ number_format($hkBaseHoursDisplay, 2, ',', '.') }}
Jam Tertagih{{ number_format(($billedHours ?? $approvedHours), 2, ',', '.') }} jam
Aktual: {{ number_format($approvedHours, 2, ',', '.') }} jam
Alpha / Cuti / LemburA {{ number_format($alphaDays ?? 0, 0, ',', '.') }} | C {{ number_format($cutiDays ?? 0, 0, ',', '.') }} | OT {{ number_format($overtimeHours ?? 0, 2, ',', '.') }}j
Rate/Jam (Base/{{ (int) ($monthlyHourBase ?? 173) }})Rp {{ number_format($hourlyRate, 2, ',', '.') }}
PPh21Rp {{ number_format($pph21Nominal, 2, ',', '.') }} ({{ number_format($pph21Rate * 100, 2, ',', '.') }}%)
{{ $pph21MethodLabel }}{{ $pph21TerCategory !== '' ? ' | TER '.$pph21TerCategory : '' }}{{ $pph21PtkpStatus !== '' ? ' | '.$pph21PtkpStatus : '' }}
BPJS PotonganRp {{ number_format($bpjsNominal, 2, ',', '.') }} ({{ number_format($bpjsRateTotal * 100, 2, ',', '.') }}%)
{{ $bpjsSourceMode === 'snapshot_paid' ? 'Snapshot dari payroll yang sudah dibayar.' : 'Live hitung dari rule aktif periode ini.' }}
Reimbursement ApprovedRp {{ number_format($reimburseNominal, 2, ',', '.') }}
Netto DibayarkanRp {{ number_format($netNominal, 2, ',', '.') }}
Bonus SPL Khusus Masuk PayrollRp {{ number_format($specialPayrollBonusNominal, 2, ',', '.') }}
{{ number_format((float) ($bd['special_overtime_payroll_bonus_hours'] ?? 0), 2, ',', '.') }} jam | {{ number_format((int) ($bd['special_overtime_payroll_bonus_hk'] ?? 0), 0, ',', '.') }} HK
Bonus SPL Khusus Bayar TerpisahRp {{ number_format($specialSeparateBonusNominal, 2, ',', '.') }}
{{ number_format((float) ($bd['special_overtime_separate_bonus_hours'] ?? 0), 2, ',', '.') }} jam | {{ number_format((int) ($bd['special_overtime_separate_bonus_hk'] ?? 0), 0, ',', '.') }} HK
Rincian Perhitungan PPh21
{{ $pph21IsSnapshot ? 'Snapshot Bayar' : 'Live Periode' }}
{{ $pph21MethodLabel }}
Tanggal acuan: {{ $pph21CalculationDate !== '' ? $pph21CalculationDate : '-' }}
Rule Digunakan
{{ $pph21RuleCode !== '' ? $pph21RuleCode : ($pph21Method === 'legacy_flat_rate' ? 'Fallback Internal' : '-') }}
Status Pajak Karyawan
PTKP {{ $pph21PtkpStatus !== '' ? $pph21PtkpStatus : 'Belum Diisi' }}
NPWP: {{ $pph21HasNpwp === null ? '-' : ($pph21HasNpwp ? 'Ada' : 'Tidak Ada') }}
Kategori dan Tarif
{{ $pph21TerCategory !== '' ? 'TER '.$pph21TerCategory : $pph21MethodLabel }}
{{ number_format($pph21Rate * 100, 4, ',', '.') }}%
PPh21 Dipotong
Rp {{ number_format($pph21Nominal, 2, ',', '.') }}
A. Pembentuk Penghasilan Bruto Kena Pajak
@if (!empty($pph21GrossComponents))
| Penghasilan gaji terhitung | Rp {{ number_format((float) ($pph21GrossComponents['salary_income'] ?? 0), 2, ',', '.') }} |
| Tunjangan kena pajak | Rp {{ number_format((float) ($pph21GrossComponents['allowances'] ?? 0), 2, ',', '.') }} |
| Insentif kena pajak | Rp {{ number_format((float) ($pph21GrossComponents['incentive'] ?? 0), 2, ',', '.') }} |
| Lembur yang masuk bruto kena pajak | Rp {{ number_format((float) ($pph21GrossComponents['overtime'] ?? 0), 2, ',', '.') }} |
@else
| Rincian pembentuk bruto belum tersedia pada snapshot pembayaran lama. |
@endif
| Bruto sebelum potongan internal | Rp {{ number_format($pph21GrossBeforeDeductions, 2, ',', '.') }} |
| Potongan ketidakhadiran | - Rp {{ number_format((float) ($pph21GrossReductions['absence'] ?? 0), 2, ',', '.') }} |
| Potongan keterlambatan | - Rp {{ number_format((float) ($pph21GrossReductions['late'] ?? 0), 2, ',', '.') }} |
| Penghasilan bruto kena pajak | Rp {{ number_format($pph21TaxableGross, 2, ',', '.') }} |
B. Pemilihan Tarif dan Rumus
@if ($pph21Method === 'ter_monthly')
Kategori berdasarkan PTKP:
{{ $pph21PtkpStatus }} → TER {{ $pph21TerCategory }}
Bracket bruto yang terpilih:
Rp {{ number_format((float) ($pph21BracketMin ?? 0), 0, ',', '.') }}
s/d
{{ $pph21BracketMax === null ? 'tanpa batas' : 'Rp '.number_format($pph21BracketMax, 0, ',', '.') }}
@elseif ($pph21Method === 'legacy_flat_rate')
PTKP atau rule TER belum lengkap. Sistem memakai basis fallback sebesar
Rp {{ number_format($pph21LegacyBasis, 2, ',', '.') }}.
@endif
Tarif diterapkan:
{{ number_format($pph21Rate * 100, 4, ',', '.') }}%
{{ $pph21FormulaLabel }}
Rp {{ number_format($pph21FormulaBasis, 2, ',', '.') }}
× {{ number_format($pph21Rate * 100, 4, ',', '.') }}%
Hasil PPh21
Rp {{ number_format($pph21RawResult, 2, ',', '.') }}
@if (!empty($pph21CalculationDetails['fallback_used']))
Perlu diperbaiki: lengkapi Status PTKP karyawan atau rule TER periode ini agar payroll tidak memakai fallback internal.
@endif
@if ($bpjsSourceMode === 'snapshot_paid')
Snapshot Bayar
@else
Live Periode
@endif
Rate BPJS dibaca per tanggal acuan {{ $bpjsEffectiveDate !== '' ? $bpjsEffectiveDate : '-' }}.
{{ $bpjsSourceMode === 'snapshot_paid'
? 'Karena payroll periode ini sudah ditandai bayar, rincian BPJS di bawah memakai snapshot yang tersimpan saat pembayaran dibuat. Perubahan rate BPJS tahun depan tidak mengubah angka periode ini.'
: 'Payroll periode ini belum dibayar, jadi rincian BPJS di bawah memakai rule aktif pada akhir periode payroll. Jika histori BPJS berubah sebelum dibayar, nominal simulasi bisa ikut berubah.' }}
@if (!empty($bpjsSummary['full']))
{{ $bpjsSummary['full'] }}
@endif
@if (!empty($payrollReportOnly))
Report Jam Only.
Jam, HK, dan detail attendance tetap dihitung untuk laporan, tetapi nominal gaji, lembur, BPJS, PPh21, dan take pay dibuat Rp 0 serta tidak masuk proses bayar.
@endif
@if (!empty($payrollReimburseOnly))
Rembes/Reimburse Only.
Jam, HK, dan detail attendance tetap dihitung untuk laporan, tetapi gaji, lembur, BPJS, dan PPh21 dibuat Rp 0. Yang masuk proses bayar hanya nominal rembes/reimburse approved.
@endif
Gaji Pokok Terhitung
@if ($salaryScheme !== '')
{{ strtoupper($salaryScheme) }}
@endif
Rp {{ number_format($calculatedBaseSalaryDisplay, 2, ',', '.') }}
Base bulanan: Rp {{ number_format($monthlyBaseSalary, 2, ',', '.') }}
Jam tertagih: {{ number_format(($billedHours ?? $approvedHours), 2, ',', '.') }} jam x Rp {{ number_format($hourlyRate, 2, ',', '.') }}
Total lembur:
{{ number_format($overtimeRate, 2, ',', '.') }}
@if (abs($weightedOvertimeHoursDisplay - $rawOvertimeHoursDisplay) > 0.0001)
x
{{ number_format($weightedOvertimeHoursDisplay, 2, ',', '.') }} jam
@endif
| Gaji lembur: Rp {{ number_format($overtimeNominal, 2, ',', '.') }}
@if ($absenceMode !== '')
Mode potongan alpha: {{ strtoupper($absenceMode) }}
@endif
Komponen Penambah
Tunjangan Total
Rp {{ number_format($allowTotal, 2, ',', '.') }}
@if ($allowFixed > 0)
Tunjangan Tetap
Rp {{ number_format($allowFixed, 2, ',', '.') }}
@endif
@if ($allowPosition > 0)
Tunjangan Jabatan
Rp {{ number_format($allowPosition, 2, ',', '.') }}
@endif
@if ($allowSkill > 0)
Tunjangan Keahlian
Rp {{ number_format($allowSkill, 2, ',', '.') }}
@endif
@if ($allowMedicalHousing > 0)
Medical/Housing
Rp {{ number_format($allowMedicalHousing, 2, ',', '.') }}
@endif
@if ($allowOther > 0)
Tunjangan Lainnya
Rp {{ number_format($allowOther, 2, ',', '.') }}
@endif
@if ($incentive > 0)
Insentif
Rp {{ number_format($incentive, 2, ',', '.') }}
@endif
@if ($specialPayrollBonusNominal > 0)
Bonus SPL Khusus (Payroll)
Rp {{ number_format($specialPayrollBonusNominal, 2, ',', '.') }}
@endif
@if ($overtimeNominal > 0)
Upah Lembur
Rp {{ number_format($overtimeNominal, 2, ',', '.') }}
@endif
@if ($reimburse > 0)
Reimbursement
Rp {{ number_format($reimburse, 2, ',', '.') }}
@endif
Total Penambah
Rp {{ number_format($additionsTotal, 2, ',', '.') }}
Komponen Pengurang
@if ($dedAbsence > 0)
Potongan Tidak Masuk (Alpha)
Rp {{ number_format($dedAbsence, 2, ',', '.') }}
@endif
@if ($dedLate > 0)
Potongan Keterlambatan
Rp {{ number_format($dedLate, 2, ',', '.') }}
@endif
@foreach ($dynamicDeductionRows as $dedRow)
{{ $dedRow['component_name'] ?? $dedRow['component_code'] ?? 'Potongan Lain' }}
Rp {{ number_format((float) ($dedRow['amount'] ?? 0), 2, ',', '.') }}
@endforeach
BPJS
Rp {{ number_format($dedBpjs, 2, ',', '.') }}
PPh21
Rp {{ number_format($dedPph21, 2, ',', '.') }}
Total Pengurang
Rp {{ number_format($deductionsTotal, 2, ',', '.') }}
Base gaji bulanan terdeteksi: Rp {{ number_format($monthlyBaseSalary, 2, ',', '.') }} |
Progress bulan: {{ number_format(($monthlyAttendance['approved_hours'] ?? 0), 2, ',', '.') }} jam.
@if (!empty($bankAccountLabel))
| Rekening Default: {{ $bankAccountLabel }}
@endif
@if (!empty($taxProofNo))
| No Bukti Potong: {{ $taxProofNo }}
@endif
Rincian Program BPJS Periode Ini
Basis umum: Rp {{ number_format($bpjsBasisGeneralDisplay, 2, ',', '.') }} |
Basis JP: Rp {{ number_format($bpjsBasisJpDisplay, 2, ',', '.') }} |
Basis Kesehatan: Rp {{ number_format($bpjsBasisHealthDisplay, 2, ',', '.') }}.
@php
$bpjsCompanyTotalDisplay = collect($bpjsDetailRows)->sum(fn ($row) => (float) ($row['company_nominal'] ?? 0));
$bpjsEmployeeTotalDisplay = collect($bpjsDetailRows)->sum(fn ($row) => (float) ($row['employee_nominal'] ?? 0));
@endphp
Total BPJS Perusahaan
Rp {{ number_format($bpjsCompanyTotalDisplay, 2, ',', '.') }}
Total BPJS Karyawan
Rp {{ number_format($bpjsEmployeeTotalDisplay, 2, ',', '.') }}
| Program |
Basis |
Basis Hitung |
Plafon |
Co (Perusahaan) |
Emp (Karyawan) |
Catatan |
@forelse ($bpjsDetailRows as $bpjsRow)
|
{{ $bpjsRow['component_code'] ?? '-' }}
{{ $bpjsRow['component_name'] ?? '-' }}
|
{{ strtoupper((string) ($bpjsRow['basis_type'] ?? 'general')) }} |
Src: Rp {{ number_format((float) ($bpjsRow['basis_source_nominal'] ?? 0), 2, ',', '.') }}
Dipakai: Rp {{ number_format((float) ($bpjsRow['basis_nominal'] ?? 0), 2, ',', '.') }}
|
@php
$bpjsBasisSource = (float) ($bpjsRow['basis_source_nominal'] ?? 0);
$bpjsBasisUsed = (float) ($bpjsRow['basis_nominal'] ?? 0);
$bpjsCeilingMin = (float) ($bpjsRow['ceiling_min_nominal'] ?? 0);
$bpjsCeilingMax = (float) ($bpjsRow['ceiling_max_nominal'] ?? $bpjsRow['ceiling_nominal'] ?? 0);
$bpjsCeilingApplied = ($bpjsCeilingMin > 0 && $bpjsBasisSource < $bpjsCeilingMin && $bpjsBasisUsed > $bpjsBasisSource)
|| ($bpjsCeilingMax > 0 && $bpjsBasisSource > $bpjsCeilingMax && $bpjsBasisUsed < $bpjsBasisSource);
@endphp
@if ($bpjsCeilingApplied)
@if ($bpjsCeilingMin > 0 && $bpjsBasisSource < $bpjsCeilingMin)
Min Rp {{ number_format($bpjsCeilingMin, 2, ',', '.') }}
@endif
@if ($bpjsCeilingMax > 0 && $bpjsBasisSource > $bpjsCeilingMax)
Max Rp {{ number_format($bpjsCeilingMax, 2, ',', '.') }}
@endif
@else
-
@endif
|
{{ number_format((float) ($bpjsRow['rate_company_percent'] ?? 0), 2, ',', '.') }}%
Rp {{ number_format((float) ($bpjsRow['company_nominal'] ?? 0), 2, ',', '.') }}
@if (!empty($bpjsRow['is_enrolled']) && (float) ($bpjsRow['rate_company_percent'] ?? 0) > 0)
Report Only
@endif
|
{{ number_format((float) ($bpjsRow['rate_employee_percent'] ?? 0), 2, ',', '.') }}%
Rp {{ number_format((float) ($bpjsRow['employee_nominal'] ?? 0), 2, ',', '.') }}
@if (!empty($bpjsRow['is_enrolled']))
@if (!empty($bpjsRow['deduct_to_payroll']))
Potong Payroll
@else
Report Only
@endif
@else
Tidak Ikut
@endif
|
{{ $bpjsRow['notes'] ?? '-' }} |
@empty
| Belum ada rincian program BPJS yang bisa ditampilkan untuk periode ini. |
@endforelse
Rincian Sub Total & Grand Total
| Komponen |
Keterangan |
Nominal |
| Gaji Pokok Sesuai Hitungan Kehadiran |
|
Rp {{ number_format($calculatedBaseSalaryDisplay, 2, ',', '.') }} |
| Total Lembur |
{{ number_format($overtimeRate, 2, ',', '.') }}
@if (abs($weightedOvertimeHoursDisplay - $rawOvertimeHoursDisplay) > 0.0001)
x
{{ number_format($weightedOvertimeHoursDisplay, 2, ',', '.') }} jam
@endif
|
Rp {{ number_format($overtimeNominal, 2, ',', '.') }} |
| Komponen Penambah |
Tunjangan, insentif/bonus payroll, dan reimbursement approved. |
Rp {{ number_format($allowTotal + $incentive + $reimburse, 2, ',', '.') }} |
| Sub Total Pendapatan |
Gaji pokok terhitung + lembur + penambah. |
Rp {{ number_format($subtotalIncomeDisplay, 2, ',', '.') }} |
@if ($dedAbsence > 0)
| Potongan Tidak Masuk / Alpha |
Sesuai mode potongan {{ strtoupper($absenceMode ?: '-') }}. |
Rp {{ number_format($dedAbsence, 2, ',', '.') }} |
@endif
@if ($dedLate > 0)
| Potongan Keterlambatan |
{{ number_format((float) ($bd['late_hours'] ?? 0), 2, ',', '.') }} jam x Rp {{ number_format((float) ($bd['late_rate_per_hour'] ?? 0), 2, ',', '.') }} |
Rp {{ number_format($dedLate, 2, ',', '.') }} |
@endif
@foreach ($dynamicDeductionRows as $dedRow)
| {{ $dedRow['component_name'] ?? $dedRow['component_code'] ?? 'Potongan Lain' }} |
{{ ($dedRow['source'] ?? '') === 'override' ? 'Import/override profil bulan.' : 'Komponen potongan profil gaji.' }}
|
Rp {{ number_format((float) ($dedRow['amount'] ?? 0), 2, ',', '.') }} |
@endforeach
| BPJS Karyawan |
Potongan payroll dari program BPJS aktif. |
Rp {{ number_format($dedBpjs, 2, ',', '.') }} |
| PPh21 |
{{ $pph21MethodLabel }}{{ $pph21TerCategory !== '' ? ' kategori '.$pph21TerCategory : '' }}{{ $pph21PtkpStatus !== '' ? ' (PTKP '.$pph21PtkpStatus.')' : '' }}: {{ number_format($pph21Rate * 100, 2, ',', '.') }}% dari bruto kena pajak Rp {{ number_format($pph21TaxableGross, 2, ',', '.') }}. |
Rp {{ number_format($dedPph21, 2, ',', '.') }} |
| Sub Total Pengurang |
Total seluruh komponen pengurang payroll. |
Rp {{ number_format($deductionsTotal, 2, ',', '.') }} |
| Grand Total (Take Pay) |
Sub Total Pendapatan - Sub Total Pengurang. |
Rp {{ number_format($grandTakePayDisplay, 2, ',', '.') }} |
@if (!empty($specialSummary['rows']))
Rincian Bonus SPL Khusus
| No SPL |
Tanggal |
Jenis |
Mode Bayar |
Bonus Jam |
Bonus HK |
Nominal |
Catatan |
@foreach (($specialSummary['rows'] ?? []) as $specialRow)
| {{ $specialRow['document_no'] ?? '-' }} |
{{ $specialRow['work_date'] ?? '-' }} |
{{ $specialRow['overtime_type_label'] ?? '-' }} |
{{ $specialRow['payment_mode_label'] ?? '-' }} |
{{ number_format((float) ($specialRow['bonus_hours'] ?? 0), 2, ',', '.') }} |
{{ number_format((int) ($specialRow['bonus_hk'] ?? 0), 0, ',', '.') }} |
Rp {{ number_format((float) ($specialRow['nominal'] ?? 0), 2, ',', '.') }} |
{{ $specialRow['notes'] ?? '-' }} |
@endforeach
Bonus mode Gabung Payroll sudah ikut ke komponen penambah payroll.
Bonus mode Bayar Terpisah hanya tampil sebagai referensi dan tidak ikut netto payroll.
@endif