@php /** * Fungsi untuk meringkas daftar angsuran yang banyak */ function getAngsuranLabel($item) { $cleanItem = preg_replace('/\s+/', ' ', trim((string) $item)); $parts = explode(' - ', $cleanItem, 2); return trim($parts[0] ?? ''); } function getAngsuranStatus($item) { $cleanItem = preg_replace('/\s+/', ' ', trim((string) $item)); $parts = explode(' - ', $cleanItem, 2); return trim($parts[1] ?? 'Lainnya'); } function extractSpbAngsuranNumber($label) { if (preg_match('/^\d+$/', trim($label))) { return (int) trim($label); } return null; } function extractSemesterAngsuran($label) { $clean = preg_replace('/\s+/', '', str_ireplace('[Cuti]', '', (string) $label)); if (!preg_match('/(?:S|Semester)(\d+)-(\d+)/i', $clean, $m)) { return null; } return [ 'semester' => (int) $m[1], 'angsuran' => (int) $m[2], 'label' => 'Semester' . ((int) $m[1]) . '-' . ((int) $m[2]), ]; } function compressNumberRanges($numbers) { $numbers = array_values(array_unique(array_filter($numbers, fn($n) => is_int($n) || ctype_digit((string) $n)))); sort($numbers); if (empty($numbers)) return ''; $ranges = []; $start = $numbers[0]; $prev = $numbers[0]; for ($i = 1; $i < count($numbers); $i++) { $current = (int) $numbers[$i]; if ($current === $prev + 1) { $prev = $current; continue; } $ranges[] = ($start === $prev) ? (string) $start : "{$start} s.d. {$prev}"; $start = $current; $prev = $current; } $ranges[] = ($start === $prev) ? (string) $start : "{$start} s.d. {$prev}"; return implode(', ', $ranges); } function compressSemesterRanges($entries) { if (empty($entries)) return ''; $unique = []; foreach ($entries as $entry) { if (!$entry) continue; $key = "{$entry['semester']}-{$entry['angsuran']}"; $unique[$key] = $entry; } $entries = array_values($unique); usort($entries, function ($a, $b) { if ($a['semester'] !== $b['semester']) return $a['semester'] <=> $b['semester']; return $a['angsuran'] <=> $b['angsuran']; }); if (empty($entries)) return ''; $ranges = []; $start = $entries[0]; $prev = $entries[0]; for ($i = 1; $i < count($entries); $i++) { $current = $entries[$i]; $sameSemesterSequence = $current['semester'] === $prev['semester'] && $current['angsuran'] === $prev['angsuran'] + 1; $nextSemesterReset = $current['semester'] === $prev['semester'] + 1 && $current['angsuran'] === 1; if ($sameSemesterSequence || $nextSemesterReset) { $prev = $current; continue; } $ranges[] = ($start['label'] === $prev['label']) ? $start['label'] : "{$start['label']} s.d. {$prev['label']}"; $start = $current; $prev = $current; } $ranges[] = ($start['label'] === $prev['label']) ? $start['label'] : "{$start['label']} s.d. {$prev['label']}"; return implode(', ', $ranges); } function ringkasAngsuran($raw, $mode = 'number') { if (empty($raw) || $raw === '-') return '-'; $items = is_array($raw) ? $raw : explode(', ', $raw); $parsed = []; $fallback = []; foreach ($items as $item) { $label = getAngsuranLabel($item); if ($mode === 'semester') { $entry = extractSemesterAngsuran($label); if ($entry) { $parsed[] = $entry; } else { $fallback[] = $label; } } else { $number = extractSpbAngsuranNumber($label); if ($number !== null) { $parsed[] = $number; } else { $fallback[] = $label; } } } $compressed = $mode === 'semester' ? compressSemesterRanges($parsed) : compressNumberRanges($parsed); $all = array_filter(array_merge($compressed ? [$compressed] : [], array_values(array_unique($fallback)))); return empty($all) ? '-' : implode(', ', $all); } function renderStatusBadges($details, $mode = 'number') { if (empty($details) || !is_array($details)) return '-'; $statusGroups = [ 'salah_transfer' => [], 'terbayar' => [], 'lalu' => [], 'belum' => [], 'cuti' => [], 'lainnya' => [], ]; foreach ($details as $item) { $raw = strtolower((string) $item); if (strpos($raw, 'salah transfer') !== false) { $statusGroups['salah_transfer'][] = $item; } elseif (strpos($raw, '[cuti]') !== false) { $statusGroups['cuti'][] = $item; } elseif (strpos($raw, 'terbayar') !== false) { $statusGroups['terbayar'][] = $item; } elseif (strpos($raw, 'lalu') !== false) { $statusGroups['lalu'][] = $item; } elseif (strpos($raw, 'depan') !== false) { // Dibayar bulan depan tetap dianggap belum lunas pada bulan laporan $statusGroups['belum'][] = $item; } elseif (strpos($raw, 'belum') !== false) { $statusGroups['belum'][] = $item; } else { $statusGroups['lainnya'][] = $item; } } $html = ''; foreach ($statusGroups as $statusKey => $items) { if (empty($items)) continue; // Untuk kebutuhan cetak: status BELUM BAYAR tidak ditampilkan, diganti "-" if ($statusKey === 'belum') continue; $ringkas = ringkasAngsuran($items, $mode); if ($ringkas === '-') continue; $suffix = $statusKey === 'cuti' ? ' [Cuti]' : ($statusKey === 'salah_transfer' ? ' [Salah Transfer]' : ''); $label = htmlspecialchars($ringkas . $suffix, ENT_QUOTES, 'UTF-8'); $style = getStatusStyle($items[0]); $html .= '' . $label . ''; } return $html ?: '-'; } /** * Fungsi untuk memberikan style berdasarkan status (menggunakan inline style karena DomPDF) */ function getStatusStyle($status) { $statusLower = strtolower($status); if (strpos($statusLower, '[cuti]') !== false) { return 'background-color: #fef3c7; color: #92400e; font-style: italic;'; // Orange untuk cuti } elseif (strpos($statusLower, 'salah transfer') !== false) { return 'background-color: #fee2e2; color: #991b1b; border: 1px solid #f87171;'; // Merah untuk salah transfer } elseif (strpos($statusLower, 'terbayar') !== false) { return 'background-color: #d1fae5; color: #065f46;'; // Hijau untuk terbayar } elseif (strpos($statusLower, 'lalu') !== false) { return 'background-color: #dbeafe; color: #1e40af;'; // Biru untuk lalu } elseif (strpos($statusLower, 'belum') !== false) { return 'background-color: #f3f4f6; color: #374151;'; // Belum tidak pakai merah di versi cetak } return 'background-color: #f3f4f6; color: #374151;'; // Default gray } /** * Fungsi untuk mengekstrak nama komponen dari detail atribut */ function getKomponenName($detail) { // Contoh: "Biaya KRS (Rp 195.000) - BELUM BAYAR" → "Biaya KRS" $parts = explode('(', $detail); return trim($parts[0]); } function isAtributPaidForDisplay($detail) { $lower = strtolower((string) $detail); return strpos($lower, 'terbayar') !== false || strpos($lower, 'lalu') !== false; } function renderAtributCellValue($details, $keyName, $paidHistory = [], $showLunasFromHistory = true) { if (empty($details) || !is_array($details)) { $details = []; } $found = null; foreach ($details as $detail) { if (mb_strtolower(trim(getKomponenName($detail))) === mb_strtolower(trim((string) $keyName))) { $found = $detail; break; } } if (!$found && $showLunasFromHistory) { $normalizedKey = mb_strtolower(trim((string) $keyName)); $hasPaidHistory = collect($paidHistory ?? []) ->contains(fn($item) => mb_strtolower(trim((string) $item)) === $normalizedKey); if ($hasPaidHistory) { return 'Lunas'; } } if (!$found) return '-'; $lower = strtolower((string) $found); if (strpos($lower, 'belum') !== false || strpos($lower, 'depan') !== false) { return '-'; } if (strpos($lower, '[cuti]') !== false) { return 'Cuti'; } if (preg_match('/\(Rp\s?([\d.]+)\)/', $found, $m)) { $nominal = 'Rp ' . $m[1]; } else { $nominal = 'Lunas'; } $color = '#374151'; if (strpos($lower, 'terbayar') !== false) { $color = '#065f46'; } elseif (strpos($lower, 'lalu') !== false) { $color = '#1e40af'; } elseif (strpos($lower, 'belum') !== false) { $color = '#b91c1c'; } return '' . htmlspecialchars($nominal, ENT_QUOTES, 'UTF-8') . ''; } function isAtributBelumLunasSampaiBulanIni($detail) { $komponenName = strtolower(getKomponenName((string) $detail)); $isJaketAtauRutin = strpos($komponenName, 'rutin') !== false; $detailLower = strtolower((string) $detail); $isBelumAtauLunasDepan = strpos($detailLower, 'belum') !== false || strpos($detailLower, 'depan') !== false; return $isJaketAtauRutin && $isBelumAtauLunasDepan; } /** * Fungsi untuk menentukan style badge sumber informasi */ function getSumberInfoStyle($jenis) { $jenisLower = strtolower($jenis); if ($jenisLower === 'bagi_hasil') { return 'background-color: #dbeafe; color: #1e40af; border: 1px solid #3b82f6; font-weight: bold;'; // Biru } return 'background-color: #f3f4f6; color: #374151; border: 1px solid #d1d5db;'; // Abu-abu } /** * Fungsi untuk mendapatkan icon/indikator bagi hasil */ function getBagiHasilIndicator($totalBagiHasilRaw) { if ($totalBagiHasilRaw > 0) { return '💰'; // Emoji uang } return ''; } /** * Jumlah nominal atribut terbayar per nama komponen (seluruh baris alokasi), selaras tampilan sel. */ function sumAtributNominalPaidByKomponenKey(array $alokasiData, string $keyName): int { $keyNorm = mb_strtolower(trim($keyName)); $sum = 0; foreach ($alokasiData as $mhs) { foreach (($mhs['atribut_details'] ?? []) as $detail) { if (mb_strtolower(trim(getKomponenName($detail))) !== $keyNorm) { continue; } if (!isAtributPaidForDisplay($detail)) { continue; } $lower = strtolower((string) $detail); if (strpos($lower, 'belum') !== false || strpos($lower, 'depan') !== false) { continue; } if (isAtributBelumLunasSampaiBulanIni($detail)) { continue; } if (preg_match('/\(Rp\s?([\d.]+)\)/', $detail, $m)) { $sum += (int) str_replace('.', '', $m[1]); } } } return $sum; } @endphp LAPORAN ALOKASI PEMBAYARAN MAHASISWA

LAPORAN ALOKASI PEMBAYARAN MAHASISWA

Kampus: {{ $namaKampus }} | Periode: {{ $bulan }} {{ $tahun }}

{{-- LEGENDA --}} {{-- LEGENDA --}}
Hijau: Dibayar bulan ini
Biru: Bayar bulan sebelumnya
Belum bayar: ditampilkan sebagai "-"
Oranye: Status CUTI
Merah: Salah Transfer
{{-- A. BIAYA TETAP (SPB, SPP, UKT) --}} @if($mode === 'rektor' || $mode === 'mitra') @if(isset($alokasiData) && count($alokasiData) > 0)
@if($mode === 'rektor') BIAYA RUTIN & ATRIBUT (SPB, SPP, UKT, KRS, dll) @else BIAYA RUTIN (SPB, SPP, UKT) @endif
@foreach(collect($alokasiData)->groupBy('periode_masuk') as $periode => $mahasiswas) @php $showSpb = collect($mahasiswas)->contains(fn($row) => !empty($row['spb_angsuran']) && $row['spb_angsuran'] !== '-'); $showSpp = collect($mahasiswas)->contains(fn($row) => !empty($row['spp_angsuran']) && $row['spp_angsuran'] !== '-'); $showUkt = collect($mahasiswas)->contains(fn($row) => !empty($row['ukt_angsuran']) && $row['ukt_angsuran'] !== '-'); $dynamicAtributKeys = $mode === 'rektor' ? collect($mahasiswas) ->flatMap(fn($row) => $row['atribut_details'] ?? []) ->filter(fn($detail) => isAtributPaidForDisplay($detail)) ->map(fn($detail) => getKomponenName($detail)) ->filter(fn($name) => !empty($name)) ->unique() ->values() ->all() : []; @endphp @if($showSpb) @endif @if($showSpp) @endif @if($showUkt) @endif @foreach($dynamicAtributKeys as $attrKey) @endforeach @if($showSpb) @endif @if($showSpp) @endif @if($showUkt) @endif @php $no = 1; @endphp @foreach($mahasiswas as $mhs) @if($showSpb) @endif @if($showSpp) @endif @if($showUkt) @endif @foreach($dynamicAtributKeys as $attrKey) @endforeach @endforeach
Periode Masuk: {{ $periode }}
No Mahasiswa / Jurusan StatusSPBSPPUKT{{ $attrKey }}Total
Ang ke-NominalAng ke-NominalAng ke-Nominal
{{ $no++ }} {{ $mhs['nama'] }} {{ $mhs['nim'] }} | {{ $mhs['jurusan'] }} | {{ $mhs['sumber_informasi'] }} {{ $mhs['status'] }}{!! renderStatusBadges($mhs['spb_details'] ?? [], 'number') !!} {{ number_format($mhs['spb_nominal_raw'] ?? 0, 0, ',', '.') }}{!! renderStatusBadges($mhs['spp_details'] ?? [], 'semester') !!} {{ number_format($mhs['spp_nominal_raw'] ?? 0, 0, ',', '.') }}{!! renderStatusBadges($mhs['ukt_details'] ?? [], 'semester') !!} {{ number_format($mhs['ukt_nominal_raw'] ?? 0, 0, ',', '.') }}{!! renderAtributCellValue($mhs['atribut_details'] ?? [], $attrKey, $mhs['atribut_paid_history'] ?? [], $mode === 'rektor') !!} @if($mode === 'rektor') {{ number_format($mhs['total_nominal_raw'] ?? 0, 0, ',', '.') }} @else {{ number_format(($mhs['spb_nominal_raw'] ?? 0) + ($mhs['spp_nominal_raw'] ?? 0) + ($mhs['ukt_nominal_raw'] ?? 0), 0, ',', '.') }} @endif
@endforeach @php $allAlokasi = collect($alokasiData); $globalShowSpb = $allAlokasi->contains(fn($row) => !empty($row['spb_angsuran']) && $row['spb_angsuran'] !== '-'); $globalShowSpp = $allAlokasi->contains(fn($row) => !empty($row['spp_angsuran']) && $row['spp_angsuran'] !== '-'); $globalShowUkt = $allAlokasi->contains(fn($row) => !empty($row['ukt_angsuran']) && $row['ukt_angsuran'] !== '-'); $globalAtributKeys = $mode === 'rektor' ? $allAlokasi ->flatMap(fn($row) => $row['atribut_details'] ?? []) ->filter(fn($detail) => isAtributPaidForDisplay($detail)) ->map(fn($detail) => getKomponenName($detail)) ->filter(fn($name) => !empty($name)) ->unique() ->values() ->all() : []; $sumSpbGlobal = (int) $allAlokasi->sum(fn($r) => (int) ($r['spb_nominal_raw'] ?? 0)); $sumSppGlobal = (int) $allAlokasi->sum(fn($r) => (int) ($r['spp_nominal_raw'] ?? 0)); $sumUktGlobal = (int) $allAlokasi->sum(fn($r) => (int) ($r['ukt_nominal_raw'] ?? 0)); $sumTotalGlobalRektor = (int) $allAlokasi->sum(fn($r) => (int) ($r['total_nominal_raw'] ?? 0)); $sumTotalGlobalMitra = (int) $allAlokasi->sum(fn($r) => (int) ($r['spb_nominal_raw'] ?? 0) + (int) ($r['spp_nominal_raw'] ?? 0) + (int) ($r['ukt_nominal_raw'] ?? 0)); @endphp @if($globalShowSpb) @endif @if($globalShowSpp) @endif @if($globalShowUkt) @endif @foreach($globalAtributKeys as $attrKey) @endforeach @if($globalShowSpb) @endif @if($globalShowSpp) @endif @if($globalShowUkt) @endif @if($globalShowSpb) @endif @if($globalShowSpp) @endif @if($globalShowUkt) @endif @foreach($globalAtributKeys as $attrKey) @php $sumAttr = sumAtributNominalPaidByKomponenKey($allAlokasi->all(), $attrKey); @endphp @endforeach
Total seluruh periode masuk
TotalSPBSPPUKT{{ $attrKey }}Total
Ang ke-NominalAng ke-NominalAng ke-Nominal
Jumlah nominal (semua mahasiswa) {{ number_format($sumSpbGlobal, 0, ',', '.') }} {{ number_format($sumSppGlobal, 0, ',', '.') }} {{ number_format($sumUktGlobal, 0, ',', '.') }}{{ $sumAttr > 0 ? number_format($sumAttr, 0, ',', '.') : '—' }} @if($mode === 'rektor') {{ number_format($sumTotalGlobalRektor, 0, ',', '.') }} @else {{ number_format($sumTotalGlobalMitra, 0, ',', '.') }} @endif
@endif @endif {{-- B. BIAYA RUTIN & ATRIBUT --}} @if($mode === 'keuangan') @if(isset($alokasiData) && count($alokasiData) > 0)
BIAYA RUTIN & ATRIBUT - KRS, dll
@php $hasAtributData = false; @endphp @foreach(collect($alokasiData)->groupBy('periode_masuk') as $periode => $mahasiswas) @php $periodRows = collect($mahasiswas)->filter(function($mhs) { $details = collect($mhs['atribut_details'] ?? []); return $details->contains(fn($detail) => isAtributPaidForDisplay($detail)); })->values(); @endphp @if($periodRows->isEmpty()) @continue @endif @php $noAtribut = 1; $hasAtributData = true; @endphp @foreach($periodRows as $mhs) @endforeach @endforeach @if($hasAtributData) @php $totalAtributSeluruhPeriode = collect($alokasiData) ->filter(function ($mhs) { $details = collect($mhs['atribut_details'] ?? []); return $details->contains(fn($detail) => isAtributPaidForDisplay($detail)); }) ->sum(fn($m) => (int) ($m['atribut_nominal_raw'] ?? 0)); @endphp @endif @if(!$hasAtributData) @endif
No Mahasiswa / Jurusan Komponen Atribut Total Atribut
Periode Masuk: {{ $periode }}
{{ $noAtribut++ }} {{ $mhs['nama'] }} {{ $mhs['nim'] }} | {{ $mhs['jurusan'] }} | {{ $mhs['sumber_informasi'] }} @foreach(collect($mhs['atribut_details'])->filter(fn($detail) => isAtributPaidForDisplay($detail)) as $detail) @php $komponenName = getKomponenName($detail); $statusStyle = getStatusStyle($detail); $showDashForAtributBelumLunas = isAtributBelumLunasSampaiBulanIni($detail); @endphp
@if($showDashForAtributBelumLunas) - @else • {{ $komponenName }} @if(strpos(strtolower($detail), '[cuti]') !== false) (CUTI) @endif @endif
@endforeach
{{ number_format($mhs['atribut_nominal_raw'] ?? 0, 0, ',', '.') }}
Total seluruh periode masuk {{ number_format($totalAtributSeluruhPeriode, 0, ',', '.') }}
Tidak ada data biaya atribut untuk periode ini
@endif @endif {{-- Biaya non-rutin (100% hak kampus): keuangan + rektor. Mitra: data dikosongkan di controller. --}} @if(($mode === 'keuangan' || $mode === 'rektor') && isset($nonRutinData) && count($nonRutinData) > 0)
BIAYA NON TETAP — 100% hak kampus
@foreach($nonRutinData as $idx => $nr) @endforeach @php $sumNonRutin = collect($nonRutinData)->sum(fn($nr) => (int) ($nr['nominal_raw'] ?? 0)); @endphp
No Mahasiswa Rincian Komponen Pembayaran Tgl Bayar Total Bayar
{{ $idx + 1 }} {{ $nr['nama'] }} {{ $nr['nim'] }} | {{ $nr['jurusan'] }} | {{ $nr['sumber_informasi'] }} @foreach($nr['details'] as $det)
• {{ $det['komponen'] }} {{ $det['nominal'] }}
@endforeach
{{ $nr['details'][0]['tanggal'] ?? '-' }} {{ number_format($nr['nominal_raw'], 0, ',', '.') }}
Total {{ number_format($sumNonRutin, 0, ',', '.') }}
@endif @if($mode === 'rektor' || $mode === 'mitra') {{-- D. BAGI HASIL --}} @php $bh = $bagiHasilSummary ?? []; // Laporan mitra: hanya bagian bagi hasil SPP/SPB/UKT (tanpa hak kampus 100% / biaya lain). $bagiHasilAdaIsi = $mode === 'mitra' ? (($bh['total_nominal_bagi_hasil'] ?? 0) > 0 || ($bh['total_hak_kampus_spp'] ?? 0) > 0 || ($bh['total_hak_mitra'] ?? 0) > 0 || ($bh['total_potongan_spp'] ?? 0) > 0) : (($bh['total_nominal_bagi_hasil'] ?? 0) > 0 || ($bh['total_hak_kampus_spp'] ?? 0) > 0 || ($bh['total_hak_kampus_selain_spp'] ?? 0) > 0 || ($bh['total_hak_mitra'] ?? 0) > 0); $sumberDetailAll = collect($bh['sumber_informasi_detail'] ?? []); $sumberDetailBagiHasil = $sumberDetailAll->filter(function ($s) { return ($s['total_nominal_awal'] ?? 0) > 0 || ($s['total_nominal'] ?? 0) > 0 || ($s['potongan_spp'] ?? 0) > 0 || ($s['hak_kampus_spp'] ?? 0) > 0 || ($s['hak_mitra'] ?? 0) > 0; })->values(); $sumberDetailHakKampusLain = $sumberDetailAll->filter(function ($s) { return ($s['hak_kampus_selain_spp'] ?? 0) > 0 || ($s['potongan_selain_spp'] ?? 0) > 0; })->values(); $adaBagiHasilSpp = ($bh['total_nominal_bagi_hasil'] ?? 0) > 0 || ($bh['total_hak_kampus_spp'] ?? 0) > 0 || ($bh['total_hak_mitra'] ?? 0) > 0 || ($bh['total_potongan_spp'] ?? 0) > 0; $adaHakKampusLain = ($bh['total_hak_kampus_selain_spp'] ?? 0) > 0 || ($bh['total_potongan_selain_spp'] ?? 0) > 0; @endphp @if($bagiHasilAdaIsi) @if($adaBagiHasilSpp)
BAGI HASIL — SPP / SPB / UKT
@if($sumberDetailBagiHasil->isNotEmpty()) @php $dhSumPotongan = (int) $sumberDetailBagiHasil->sum(fn($s) => (int) ($s['potongan_spp'] ?? 0)); $dhSumDasar = (int) $sumberDetailBagiHasil->sum(fn($s) => (int) ($s['total_nominal'] ?? 0)); $dhSumHakKampus = (int) $sumberDetailBagiHasil->sum(fn($s) => (int) ($s['hak_kampus_spp'] ?? 0)); $dhSumHakMitra = (int) $sumberDetailBagiHasil->sum(function ($s) { $isKomisiRow = strtolower((string) ($s['jenis_sumber_informasi'] ?? '')) === 'komisi'; return $isKomisiRow ? 0 : (int) ($s['hak_mitra'] ?? 0); }); $dhSumJmlMhs = (int) $sumberDetailBagiHasil->sum(fn($s) => (int) ($s['jumlah_mahasiswa'] ?? 0)); @endphp @foreach($sumberDetailBagiHasil as $sumber) @php $isKomisi = strtolower((string)($sumber['jenis_sumber_informasi'] ?? '')) === 'komisi'; @endphp @endforeach
DETAIL PER SUMBER — BAGI HASIL (SPP / SPB / UKT)
Sumber Informasi % Kampus % Mitra Potongan (SPP/SPB/UKT) Pembayaran masuk (net) Hak Kampus Hak Mitra Jml Mhs
{{ $sumber['nama'] ?? '-' }} @if($isKomisi)
Komisi: hak mitra 0, dialokasikan ke hak kampus @endif
{{ $sumber['bank_name'] ?? '-' }} - {{ $sumber['nomor_rekening'] ?? '-' }}
{{ number_format($sumber['persen_kampus'], 1) }}% @if($isKomisi) 0.0% @else {{ number_format($sumber['persen_mitra'], 1) }}% @endif Rp {{ number_format($sumber['potongan_spp'] ?? 0, 0, ',', '.') }} Rp {{ number_format($sumber['total_nominal'] ?? 0, 0, ',', '.') }} Rp {{ number_format($sumber['hak_kampus_spp'] ?? 0, 0, ',', '.') }} Rp {{ number_format($isKomisi ? 0 : $sumber['hak_mitra'], 0, ',', '.') }} {{ $sumber['jumlah_mahasiswa'] }}
Total Rp {{ number_format($dhSumPotongan, 0, ',', '.') }} Rp {{ number_format($dhSumDasar, 0, ',', '.') }} Rp {{ number_format($dhSumHakKampus, 0, ',', '.') }} Rp {{ number_format($dhSumHakMitra, 0, ',', '.') }} {{ $dhSumJmlMhs }}
@endif @endif @if($mode === 'mitra')
Catatan: Laporan ini untuk mitra — hanya pembagian SPP / SPB / UKT. Biaya rutin, jaket, KRS, dan biaya lain merupakan hak kampus penuh dan tidak ditampilkan di laporan mitra.
@else
Catatan: Pembagian kontrak bagi hasil hanya untuk SPP, SPB, UKT.
K2 (bagi_hasil): potongan pada SPP/SPB/UKT mengurangi hak mitra (ditanggung oleh K2).
Bagi hasil selain K2: potongan pada SPP/SPB/UKT mengurangi nominal bagi hasil (ditanggung bersama).
Internal / komisi (SPP/SPB/UKT): potongan pada SPP/SPB/UKT mengurangi hak kampus (ditanggung oleh kampus).
Total hak kampus laporan = jumlah hak kampus SPP/SPB/UKT + Biaya Non Tetap
@endif
Catatan Rekonsiliasi: Total Salah Transfer dijumlahkan dari nominal pembayaran valid (SPB/SPP/UKT/RUTIN/JAKET/ATRIBUT) yang bertanda salah transfer pada periode laporan.
@endif @endif {{-- FOOTER TOTAL --}}
@php // Definisikan kategori untuk memudahkan pengecekan $isRektor = $mode === 'rektor'; $isMitra = $mode === 'mitra'; $isKeuangan = $mode === 'keuangan'; $alokasiCollectionFooter = collect($alokasiData ?? []); $showTotalSpbFooter = $alokasiCollectionFooter->contains(fn($row) => !empty($row['spb_angsuran']) && $row['spb_angsuran'] !== '-'); $showTotalSppFooter = $alokasiCollectionFooter->contains(fn($row) => !empty($row['spp_angsuran']) && $row['spp_angsuran'] !== '-'); $showTotalUktFooter = $alokasiCollectionFooter->contains(fn($row) => !empty($row['ukt_angsuran']) && $row['ukt_angsuran'] !== '-'); @endphp {{-- Kategori A: Biaya Pendidikan (Untuk Rektor & Mitra) --}} @if($isRektor || $isMitra) @if($showTotalSpbFooter)
Total SPB {{ number_format($totalAll['spb'] ?? 0, 0, ',', '.') }}
@endif @if($showTotalSppFooter)
Total SPP {{ number_format($totalAll['spp'] ?? 0, 0, ',', '.') }}
@endif @if($showTotalUktFooter)
Total UKT {{ number_format($totalAll['ukt'] ?? 0, 0, ',', '.') }}
@endif @endif {{-- Kategori B: Biaya Internal (Untuk Rektor & Keuangan) --}} @if($isRektor || $isKeuangan)
Total Atribut (KRS, dll) {{ number_format($totalAll['atribut'] ?? 0, 0, ',', '.') }}
@if(isset($totalAll['nonRutin']) && $totalAll['nonRutin'] > 0)
Total BIAYA NON TETAP {{ number_format($totalAll['nonRutin'] ?? 0, 0, ',', '.') }}
@endif @endif {{-- Potongan: rektor = seluruh; mitra = hanya SPP/SPB/UKT (selaras isi laporan mitra) --}} @if($isRektor && ($bagiHasilSummary['total_potongan'] ?? 0) > 0)
Total Potongan Mahasiswa {{ number_format($bagiHasilSummary['total_potongan'] ?? 0, 0, ',', '.') }}
@elseif($isMitra && ($bagiHasilSummary['total_potongan_spp'] ?? 0) > 0)
Potongan (SPP/SPB/UKT) {{ number_format($bagiHasilSummary['total_potongan_spp'] ?? 0, 0, ',', '.') }}
@endif @php $totalSalahTransferPdf = (float) ($bagiHasilSummary['total_nominal_salah_transfer'] ?? 0); // Mitra: hak kampus di footer = porsi SPP/SPB/UKT saja. $hakKampusDasarPdf = $isMitra ? (float) ($bagiHasilSummary['total_hak_kampus_spp'] ?? 0) : (float) ($bagiHasilSummary['total_hak_kampus'] ?? 0); $hakKampusBersihPdf = $isMitra ? max(0, $hakKampusDasarPdf - $totalSalahTransferPdf) : (float) ($bagiHasilSummary['total_hak_kampus_setelah_salah_transfer'] ?? max(0, $hakKampusDasarPdf - $totalSalahTransferPdf)); $showHakKampusFooter = ($isRektor || $isMitra) && isset($bagiHasilSummary['total_hak_kampus']); $grandTotalAngsuran = 0; if ($isMitra) { $grandTotalAngsuran = ($totalAll['spb'] ?? 0) + ($totalAll['spp'] ?? 0) + ($totalAll['ukt'] ?? 0); } elseif ($isKeuangan) { $grandTotalAngsuran = ($totalAll['atribut'] ?? 0) + ($totalAll['nonRutin'] ?? 0); } else { $grandTotalAngsuran = $totalAll['grand'] ?? 0; } @endphp {{-- PPH 23 (di atas ringkasan konsolidasi / rekonsiliasi hak kampus) --}} @if($isRektor || $isMitra)
PPH 23 {{ number_format($totalAll['pph23'] ?? 0, 0, ',', '.') }}
@endif @if($showHakKampusFooter) {{-- Ringkasan bisnis / konsolidasi (bukan baris paling bawah; paling bawah = hak kampus bersih) --}}
@if($isMitra) TOTAL BAGI HASIL MITRA @else TOTAL KESELURUHAN PEMBAYARAN @endif Rp {{ number_format($grandTotalAngsuran, 0, ',', '.') }}
{{-- Rekonsiliasi hak kampus (salah transfer); urutan: ST → dasar → rumus → TOTAL HAK KAMPUS BERSIH (paling bawah) --}} @if($totalSalahTransferPdf > 0)
Total Salah Transfer (sudah masuk rekening kampus) {{ number_format($totalSalahTransferPdf, 0, ',', '.') }}
Hak Kampus (dasar alokasi bagi hasil) {{ number_format($hakKampusDasarPdf, 0, ',', '.') }}
Perhitungan hak kampus bersih {{ number_format($hakKampusDasarPdf, 0, ',', '.') }} - {{ number_format($totalSalahTransferPdf, 0, ',', '.') }} = {{ number_format($hakKampusBersihPdf, 0, ',', '.') }}
@endif @if($isRektor || $isMitra)
TOTAL HAK MITRA {{ number_format($bagiHasilSummary['total_hak_mitra'] ?? 0, 0, ',', '.') }}
@endif
{{ $totalSalahTransferPdf > 0 ? 'TOTAL HAK KAMPUS BERSIH' : 'TOTAL HAK KAMPUS' }}@if($isMitra)
(porsi SPP / SPB / UKT)@endif
{{ number_format($totalSalahTransferPdf > 0 ? $hakKampusBersihPdf : $hakKampusDasarPdf, 0, ',', '.') }}
@else {{-- Keuangan, atau Rektor/Mitra tanpa data hak kampus di footer: satu bar grand --}}
@if($isMitra) TOTAL BAGI HASIL MITRA @elseif($isKeuangan) TOTAL PENDAPATAN INTERNAL (NET) @else TOTAL KESELURUHAN PEMBAYARAN @endif Rp {{ number_format($grandTotalAngsuran, 0, ',', '.') }}
@endif
{{-- TTD: tampil di semua mode export; penandatangan tetap Bagian Keuangan --}}
Mengetahui,
Bagian Keuangan
(........................................)