18

Audit Modul Buku Kas Umum (BKU) 2026

Updated: Sep 2026Oleh: SystemModul Keuangan & Akuntansi

AUDIT KOMPREHENSIF MODUL BUKU KAS UMUM (BKU)

Edisi Sistem: v2026.3 | Tanggal Pelaksanaan: 18 September 2026 Auditor Sistem: Antigravity AI Senior Technical Auditor & Finance Core Team


📋 1. Eksekutif Ringkasan & Ruang Lingkup Audit#

Audit mendalam ini mengevaluasi seluruh komponen Modul Buku Kas Umum (BKU) dalam sistem ERP BUMDes Bolulango. BKU merupakan instrumen pencatatan kronologis seluruh mutasi kas & bank yang berfungsi sebagai single source of truth untuk likuiditas riil entitas.

Komponen yang Diaudit

Memuat diagram alur...
Dimensi AuditFile UtamaStatus
Server Page (SSR)page.tsx (app/dashboard/keuangan/bku/)
Client ComponentBKUClient.tsx
Backend Enginereport.ts (getBKUReport L257-L424)
Print Pagepage.tsx (app/print/buku-kas/)
Export Utilsexport-utils.ts (exportBKUExcel L593-L607)
Safe Arithmeticaccounting.ts (L1-L45)
Alternate Data Sourcejournal-quick.ts (getRecentUnitTransactions L109-L232)
DokumentasiPANDUAN_BKU_HOLDING.md

🏆 2. Scorecard Hasil Audit#

#Area AuditSkorVerdict
1Arsitektur & Separation of Concerns🟢 AExcellent
2Backend Engine (getBKUReport)🟢 ASolid
3Safe Money Arithmetic🟢 A+Gold Standard
4Unit Filtering & Konsolidasi🟢 ACorrect
5RBAC & Access Control (Halaman BKU)🟢 AEnforced
6UI/UX Client Component🟢 APremium
7Tutup Buku (Closing) Integration🟢 AWorking
8Print Page (Buku Kas)✅ AFIXED
9Export Excel (exportBKUExcel)✅ AFIXED
10Export CSV🟢 B+Minor Issues
11Negative Balance Warning🟢 AProactive
12Dokumentasi SOP🟢 B+Good
OVERALL🟢 A-P0 Fixed • Medium items open

✅ 3. Temuan POSITIF (Keunggulan Sistem)#

3.1 Backend Engine Matang & Akurat

getBKUReport() di report.ts:257-424 menunjukkan implementasi yang sangat solid:

  • Identifikasi Akun Kas Strict: Filter menggunakan code.like.1-100%,1-101%,1-102%,1-103% plus fallback 1101,1102 — menutup semua kemungkinan format kode COA.
  • Status Guard: Hanya jurnal status = 'approved' yang masuk BKU. Draft journals tidak pernah mencemari saldo kas.
  • Safe Money Arithmetic: Menggunakan safeMoney(), safeAdd(), safeSubtract() dari accounting.ts — mengeliminasi IEEE 754 floating point errors pada akumulasi Rupiah.
  • Saldo Awal Kalkulasi Benar: beginningBalance dihitung dari semua journal_line_items pada akun kas sebelum startDate, bukan hardcoded.
  • Running Balance Kronologis: Sort multi-level yang sangat baik: entry_date → created_at → entry_number → debit-first → id fallback.
  • Eliminasi Konsolidasi Sudah Dihapus: Komentar di L335-338 menjelaskan kenapa filter TRF-% dihapus (menyembunyikan suntikan dana → saldo minus).

3.2 RBAC Berlapis

Server (page.tsx) → getCurrentUser() → isRestricted check
 → assignedUnitId binding
Backend (getBKUReport) → requireRoleGuard()
  • ✅ Role manajer_unit, kepala_unit, kepala_sub_unit, admin_unit otomatis di-restrict ke unit mereka.
  • requireRoleGuard() di backend menambahkan lapisan keamanan kedua.

3.3 Konsolidasi Hierarki Multi-Level

getAllChildUnitIds() memungkinkan consolidated view yang recursive — mendukung struktur holding → sub-unit → sub-sub-unit tanpa batas kedalaman.

3.4 UI/UX Premium

  • ✅ Glassmorphism cards dengan dark mode support penuh.
  • ✅ Summary cards (Saldo Awal, Mutasi Kas, Saldo Akhir) informatif.
  • ✅ Warning banner untuk saldo negatif (defensive UI).
  • ✅ Consolidated vs Isolated toggle yang intuitif.
  • ✅ Link ke jurnal edit dari setiap baris referensi (drill-down audit trail).
  • ✅ Print-ready CSS classes (print:hidden, print:bg-transparent, dll).
  • ✅ Loading state dengan opacity transition.

3.5 Integrasi Ekosistem

  • ✅ Transfer Kas dan Treasury actions me-revalidatePath('/dashboard/keuangan/bku') setelah mutasi.
  • ✅ Sidebar navigation terdaftar sebagai menu utama.
  • ✅ AI ActionCardRenderer memiliki redirect alias /dashboard/bku/dashboard/keuangan/bku.

🔴 4. Temuan KRITIS (Harus Diperbaiki)#

4.1 [CRITICAL] ✅ [FIXED] Print Page Menggunakan Data Source Berbeda & Cacat Logika Saldo

✅ RESOLVED — 18 September 2026 app/print/buku-kas/page.tsx telah direfactor penuh untuk menggunakan getBKUReport() sebagai data source tunggal. Draft journals tidak akan pernah masuk cetakan. Running balance kini sepenuhnya server-side. FormalSignatures unitName juga diperbaiki dari hardcoded ke nama unit sebenarnya. Indikator status tutup buku ditambahkan.

Halaman Utama BKU: Menggunakan getBKUReport() dari lib/actions/finance/report.ts

  • ✅ Filter status = 'approved'
  • ✅ Safe money arithmetic
  • ✅ Multi-level sort
  • ✅ Proper debit/credit columns

Halaman Print: Menggunakan getRecentUnitTransactions() dari lib/actions/journal-quick.ts

  • TIDAK memfilter status = 'approved' — jurnal DRAFT bisa masuk ke cetakan resmi
  • Menggunakan model data amount + type bukan debit/credit — mismatch dengan struktur BKU
  • Running balance dihitung ulang di JSX (line 162) dengan logika yang cacat:
tsx
// CACAT: amount > 0 = masuk, amount < 0 = keluar 
// Tapi getRecentUnitTransactions SELALU return amount positif + type field
const currentBalance = beginningBalance + transactions.slice(0, idx + 1)
 .reduce((acc, curr) => 
 acc + (curr.amount > 0 ? curr.amount : 0) - (curr.amount < 0 ? Math.abs(curr.amount) : 0), 0
 )

Masalah: getRecentUnitTransactions() return amount = Math.max(debit, credit) (selalu positif) dan type = 'in' | 'out'. Logika amount < 0 tidak pernah true, sehingga semua transaksi dianggap "masuk" dan saldo running balance selalu naik.

  • Transactions di-reverse (processed.reverse() di L229) untuk display "newest first", tapi print page menampilkannya sequential — urutan salah.
  • Tidak menggunakan Safe Money Arithmetic — rentan floating point errors.

Severity: 🔴 CRITICAL — Dokumen resmi yang dicetak dan ditandatangani bisa menampilkan angka yang salah.

Rekomendasi: Print page harus menggunakan getBKUReport() yang sama sebagai data source, atau minimal di-refactor agar menggunakan data source dengan kualitas yang setara.


4.2 [CRITICAL] ✅ [FIXED] Export Excel Menggunakan Field yang Tidak Ada

✅ RESOLVED — 18 September 2026 exportBKUExcel() di export-utils.ts telah diperbaiki. Field mapping sekarang benar: beginningBalance, entries, finalBalance, ref.

typescript
// exportBKUExcel expects:
data.startBalance // ❌ Actual: data.beginningBalance
data.transactions // ❌ Actual: data.entries
data.endBalance // ❌ Actual: data.finalBalance
t.evidence_no // ❌ Actual: t.ref

Akibat: File Excel yang dihasilkan akan berisi:

  • Saldo Awal: 0 (bukan angka sebenarnya)
  • Kolom transaksi: kosong/undefined
  • Saldo Akhir: 0

Severity: 🔴 CRITICAL — Export Excel menghasilkan data kosong/salah. User mungkin tidak sadar karena file tetap ter-download.

Rekomendasi: Selaraskan field mapping di exportBKUExcel() dengan output getBKUReport():

typescript
export function exportBKUExcel(data: any, period: string) {
 const exporter = new ExcelExporter()
 const rows = []
 rows.push(['BUKU KAS UMUM', `Periode: ${period}`, '', '', '', ''])
 rows.push([''])
 rows.push(['Saldo Awal', '', '', '', '', data.beginningBalance || 0]) // FIX
 if (data.entries) { // FIX: was data.transactions
 data.entries.forEach((t: any) => {
 rows.push([t.date, t.ref || '', t.description, t.debit || 0, t.credit || 0, t.balance || 0]) // FIX
 })
 }
 rows.push(['Saldo Akhir', '', '', '', '', data.finalBalance || 0]) // FIX
 exporter.addTableSheet('BKU', ['Tanggal', 'No Bukti', 'Uraian', 'Penerimaan', 'Pengeluaran', 'Saldo'], rows)
 exporter.save('BKU.xlsx')
}

🟡 5. Temuan MEDIUM (Sebaiknya Diperbaiki)#

5.1 [MEDIUM] ✅ [FIXED] Export CSV Hitung Total dari filteredEntries, Bukan All Entries

✅ RESOLVED — 18 September 2026

  • totalMasukAll / totalKeluarAll sekarang selalu dihitung dari allEntries (tidak terpengaruh search filter)
  • Summary card Mutasi Kas kini selalu menampilkan angka keseluruhan periode
  • Footer table menampilkan konteks filter: "Total Keseluruhan (filter aktif: X/Y transaksi)"
  • Baris tambahan "Total Terfilter" (amber row) muncul di bawah footer saat search aktif
  • CSV export selalu mengekspor ALL entries, bukan hanya yang terfilter
  • Fix memory leak URL.revokeObjectURL() juga diterapkan
  • Fix CSV escaping: handle newline dan special chars

5.2 [MEDIUM] ✅ [FIXED] Redundansi Panggilan getAllChildUnitIds

✅ RESOLVED — 18 September 2026 getAllChildUnitIds() kini di-cache sekali di awal getBKUReport() sebagai cachedChildUnitIds. Ketiga titik penggunaan (account filter, beginning balance, transactions) menggunakan hasil yang sama. Mengeliminasi 2 dari 3 recursive DB round-trips.

5.3 [MEDIUM] Print Page Tidak Memanfaatkan FormalSignatures dengan Benar

Di print/buku-kas/page.tsx:185-189:

tsx
<FormalSignatures 
 auditId={`bku-print-{unit_id}-{month}-${year}`} 
 variant="unit" 
 unitName="Unit" // ❌ Hardcoded "Unit" — bukan nama unit sebenarnya
/>

Nama unit pada tanda tangan tercetak "Unit" alih-alih nama unit bisnis yang sebenarnya.

5.4 [MEDIUM] ✅ [FIXED] Tidak Ada Pagination / Virtualisasi untuk Data Besar

✅ RESOLVED — 18 September 2026 Pagination 100 baris per halaman diterapkan di BKUClient.tsx menggunakan paginatedEntries. Kontrol navigasi halaman (prev/next + nomor halaman) ditampilkan di bawah tabel dengan UI premium. Page di-reset otomatis saat filter atau search berubah.

5.5 [MEDIUM] Print Page Tidak Menampilkan Status Tutup Buku

Halaman utama BKU menampilkan badge "🔒 Terkunci (Tutup Buku)" tapi halaman print tidak memiliki indikator ini sama sekali.


🔵 6. Temuan MINOR (Nice to Have)#

6.1 [LOW] Duplicated Dark Mode Classes

6.2 [LOW] any Type Pervasive

6.3 [LOW] CSV Export Tidak Menangani Karakter Khusus Sepenuhnya

6.4 [LOW] FormalReportHeader Period Format Inkonsisten

6.5 [LOW] URL Object Leak di CSV Export


🏗️ 7. Analisis Arsitektur#

7.1 Kepatuhan SAK EP

Kriteria SAK EPStatusKeterangan
BKU mencatat pergerakan kas riil (bukan accrual)Hanya akun kas/bank (1-1xx) yang masuk
Transaksi non-kas (penyusutan, amortisasi) tidak masuk BKUFilter by COA code
Saldo awal = akumulasi historis sebelum periodeDihitung dari semua approved journals < startDate
Kronologis (urut tanggal)Multi-level sort
Hanya jurnal yang disetujui (approved)✅ Backend / ❌ PrintPrint page tidak filter status
Saldo berjalan akurat✅ Backend / ❌ PrintPrint page running balance cacat

📊 8. Matriks Risiko & Prioritas Perbaikan#

#TemuanSeverityImpactEffortStatus
4.1Print Page data source & saldo cacat🔴 CRITICALDokumen resmi salahMediumFIXED
4.2Export Excel field mismatch🔴 CRITICALExcel kosong/salahLowFIXED
5.1CSV total inkonsisten saat filter aktif🟡 MEDIUMLaporan menyesatkanLowFIXED
5.2Redundansi getAllChildUnitIds🟡 MEDIUMPerformanceLowFIXED
5.3Print unitName hardcoded🟡 MEDIUMTanda tangan salahLowFIXED
5.4Tidak ada pagination🟡 MEDIUMPerformance mobileMediumFIXED
5.5Print tidak tampilkan status tutup buku🟡 MEDIUMKonteks audit hilangLowFIXED
6.1Duplicated CSS classes🔵 LOWBundle sizeLowFIXED
6.2Pervasive any types🔵 LOWType safetyMediumFIXED
6.3CSV escaping kurang lengkap🔵 LOWRare edge caseLowFIXED
6.4Inkonsistensi format periode🔵 LOWUX confusionLowFIXED
6.5URL object leak🔵 LOWMinor memory leakLowFIXED

🛠️ 9. Rekomendasi Perbaikan Strategis#

9.1 Fase 1: Critical Fixes (P0)

A. Perbaiki Print Page BKU

Ganti data source di print/buku-kas/page.tsx untuk menggunakan getBKUReport().

B. Perbaiki Export Excel

Selaraskan field mapping di exportBKUExcel().

9.2 Fase 2: Medium Priority (P1-P2)

  1. Pisahkan total keseluruhan vs total terfilter
  2. Cache getAllChildUnitIds di awal getBKUReport()
  3. Fix unitName di FormalSignatures print page
  4. Tambahkan indikator tutup buku di print page
  5. Implement pagination

9.3 Fase 3: Polish (P3)

✅ RESOLVED — 18 September 2026

  1. Clean up duplicated CSS classes (Cleared)
  2. Define proper TypeScript interfaces (lib/types/bku.ts) and eliminated any usage.
  3. Standardize period format (using em-dash consistently) across dashboard, print page, and exports.
  4. Use proper CSV library (Optional, CSV is stable now)
  5. Tambahkan URL.revokeObjectURL() setelah download

🔒 10. Audit Keamanan#

AspekStatusDetail
Server-side role guardrequireRoleGuard() di setiap server action
Unit-level isolationisRestricted + assignedUnitId di page.tsx
SQL Injection preventionMenggunakan Supabase SDK (parameterized queries)
XSS preventionReact auto-escaping
RBAC Bypass Risk🟢Semua mutating action sudah dilindungi requireRoleGuard
Data exfiltration risk🟢✅ Terselesaikan. Setiap aksi Export CSV, Excel, dan Print PDF dicatat secara silent ke dalam tabel audit_logs (RLS Tier-5) mencakup: actor, timestamp, unit_id, dan jumlah baris data.
Injeksi HTML/XSS🟢Data description sudah di-escape otomatis oleh React

📝 11. Kesimpulan#

Modul BKU pada ERP BUMDes Bolulango memiliki arsitektur backend yang kuat dan mesin komputasi yang akurat. Safe money arithmetic, multi-level sorting, dan RBAC berlapis menunjukkan standar engineering yang matang.

Namun, terdapat 2 cacat kritis yang memerlukan perbaikan segera:

  1. Print page menggunakan data source berbeda yang tidak memfilter status jurnal dan memiliki logika running balance yang cacat — berisiko menghasilkan dokumen resmi dengan angka salah.
  2. Export Excel menggunakan field mapping yang salah — menghasilkan file dengan data kosong.

Kedua masalah ini bersifat "silent failure" — sistem tidak error, file tetap ter-download, tapi isinya salah. Ini adalah tipe bug yang paling berbahaya karena user mungkin tidak menyadarinya.

❗ IMPORTANT Rekomendasi Utama: Perbaiki kedua temuan P0 sebelum akhir periode pelaporan. Setelah perbaikan, lakukan cross-check manual antara halaman BKU dashboard, print preview, dan file Excel/CSV untuk memverifikasi konsistensi angka.


Dokumen audit ini dibuat secara sistematis oleh Antigravity AI Senior Technical Auditor untuk memastikan transparansi, akuntabilitas, dan kualitas tata kelola keuangan BUMDes Bolulango menuju standar Gold Standard.

Apakah panduan ini membantu Anda?