18

Spesifikasi Teknis Buku Kas Umum (BKU)

Updated: Sep 2026Oleh: SystemSistem ERP & Teknologi Inti

๐Ÿ› ๏ธ SPESIFIKASI TEKNIS SISTEM & ARSITEKTUR

Modul Buku Kas Umum & Cash Subledger Engine (Single-Point Entry)#

ERP BUMDes Mandiri Sejahtera Stack: Next.js 15 (App Router) + Supabase PostgreSQL + TypeScript (Strict) + Tailwind CSS + SafeMoney Engine


๐Ÿ›๏ธ 1. Arsitektur Komponen & Alur Data#

Modul Buku Kas Umum (BKU) merupakan pilar utama pengelolaan kas dan bank (Cash & Bank Subledger) dalam sistem ERP BUMDes Mandiri Sejahtera. BKU berfungsi sebagai instrumen pencatatan kronologis mutasi kas riil (uang tunai brankas dan saldo rekening bank operasional) dari 20 unit usaha secara real-time yang dapat direkonsiliasi sempurna dengan Buku Besar (General Ledger) akun kas 1-1xxx.

Memuat diagram alur...

โš™๏ธ 2. Core Engine Specifications#

2.1. Identifikasi Akun Kas & Bank (Strict Prefix Recognition)

Untuk menjamin tidak ada akun non-kas yang mencemari BKU, kueri akun menggunakan penyaringan spesifik pada tabel coa:

typescript
let accountQuery = supabase
 .from('coa')
 .select('id, code, name, unit_id')
 .or('code.like.1-100%,code.like.1-101%,code.like.1-102%,code.like.1-103%,code.eq.1101,code.eq.1102')
 .ilike('account_type', 'asset')

Kriteria ini mencakup:

  • 1-100%: Kas Tunai Utama / Brankas Kantor Holding
  • 1-101%: Kas Operasional / Kas Kasir Unit
  • 1-102%: Kas Kecil / Petty Cash Perbendaharaan
  • 1-103%: Kas Bank Operasional (Bank Mandiri, Bank BRI, BPD)
  • 1101, 1102: Fallback format kode numerik 4 digit

2.2. Harmonisasi Status Transaksi (approved & posted)

Untuk mengeliminasi selisih saldo (unreconciled variance) antara BKU dengan Buku Besar akun kas:

  1. Jurnal Manual Terverifikasi: Memiliki status approved.
  2. Jurnal Otomatis Subsistem: Transaksi dari mesin POS kasir, pembayaran piutang simpan pinjam USP, dan transfer antar-brankas yang telah divalidasi memiliki status posted.
  3. Filter Baku BKU:
typescript
.in('journal_entries.status', ['approved', 'posted'])

Dengan penyelarasan ini, BKU dan Buku Besar Akun 1-1xxx selalu menghasilkan saldo akhir yang identik (variansi Rp 0).


2.3. Data Pump Streaming Pagination (Anti-Truncation Engine)

PostgREST Supabase menerapkan batas default 1.000 baris per kueri. Tanpa streaming batching, entitas dengan ribuan transaksi historis akan mengalami pemotongan data saldo awal secara senyap (silent truncation).

BKU menerapkan loop Data Pump Pagination dengan klausa deterministik .order('id', { ascending: true }) pada kueri saldo awal dan transaksi mutasi:

typescript
// Saldo Awal Streaming Loop
let begFrom = 0
const begStep = 1000
let begHasMore = true

while (begHasMore) {
 const { data: chunk } = await begQuery.range(begFrom, begFrom + begStep - 1)
 if (!chunk || chunk.length === 0) {
 begHasMore = false
 } else {
 chunk.forEach((line: any) => {
 const debit = safeMoney(line.debit)
 const credit = safeMoney(line.credit)
 beginningBalance = safeAdd(beginningBalance, safeSubtract(debit, credit))
 })
 if (chunk.length < begStep) begHasMore = false
 else begFrom += begStep
 }
}

2.4. SafeMoney Arithmetic Standard (Anti-IEEE 754 Floating Drift)

Perhitungan kas tidak diperkenankan menggunakan operator bawaan JavaScript biasa guna mencegah cents drift. Seluruh penjumlahan dan pengurangan saldo kas menggunakan fungsi presisi dari lib/accounting.ts:

  • safeMoney(val): Pembulatan sanitasi ke 2 desimal.
  • safeAdd(a, b): Penjumlahan berbasis sen integer.
  • safeSubtract(a, b): Pengurangan berbasis sen integer.

Formula Running Balance BKU:

Saldo Berjalan_i = Saldo Berjalan_{i-1} + Debit_i - Credit_i

2.5. Prioritas Deskripsi Baris Transaksi

Untuk memberikan visibilitas penuh bagi auditor dan pengawas desa, narasi transaksi diutamakan dari rincian pos belanja kas (line.description) sebelum melakukan fallback ke judul umum voucher (journal_entries.description):

typescript
const effectiveDescription = 
 (line.description || '').trim() || 
 (line.journal_entries?.description || '').trim() || 
 '-'

2.6. Pengurutan Kronologis Multi-Tier Deterministik

Mutasi kas diurutkan secara ketat pada memori backend agar merefleksikan urutan fisik transaksi di lapangan:

  1. Tanggal Transaksi (entry_date ASC)
  2. Waktu Pembuatan (created_at ASC)
  3. Nomor Bukti Voucher (entry_number ASC)
  4. Aliran Kas (Debit / Uang Masuk didahulukan sebelum Kredit / Uang Keluar)
  5. Tie-Breaker Deterministik (id ASC)

๐Ÿ”’ 3. Keamanan & Multi-Unit RBAC#

3.1. Isolasi Akses Tingkat Server Action

Fungsi getBKUReport() mengintegrasikan resolveFinanceRBAC(unitId) secara wajib:

typescript
export async function getBKUReport(unitId: string = 'all', startDate?: string, endDate?: string, consolidated: boolean = false) {
 await requireRoleGuard()
 const { effectiveUnitId, isRestricted } = await resolveFinanceRBAC(unitId)
 const targetUnitId = effectiveUnitId === 'all' ? null : effectiveUnitId

 // Jika pengguna operasional terisolasi tapi tidak memiliki unit asosiasi, tolak akses dengan payload kosong
 if (targetUnitId === 'none') {
 return { beginningBalance: 0, entries: [], finalBalance: 0, isClosed: false }
 }

3.2. Whitelist Hak Akses Holding vs Unit

Halaman app/dashboard/keuangan/bku/page.tsx membagi pengguna ke dalam dua kelompok hak akses:

  • Holding Whitelist (HOLDING_ROLES): super_admin, superadmin, direktur, bendahara, sekretaris, pengawas, pengawas_1, pengawas_2, auditor, admin_keuangan, admin_keuangan_pusat. Hak: Bebas melihat BKU konsolidasi holding atau memilih salah satu dari 20 unit usaha.
  • Unit Restricted (ROLES_RESTRICTED_FALLBACK): manajer_unit, kepala_unit, kepala_sub_unit, admin_unit, kasir, kasir_toko, admin_gudang, kolektor_usp, koordinator_kandang, anak_kandang, unit_manager, staf_unit. Hak: Terkunci mutlak pada unit kerja masing-masing (assigned_unit_id). Percobaan injeksi parameter unitId=all diabaikan dan dipaksa kembali ke unit miliknya.

๐Ÿ“Š 4. Spesifikasi Ekspor & Pencetakan Dokumen#

  1. Ekspor PDF (exportBKUPDF):
  • Memuat identitas BUMDes, Nama Unit Usaha, dan Rentang Periode.
  • Kolom tabel baku (8 kolom): Tanggal, No. Bukti, Uraian Transaksi, Akun Kas, Unit Usaha, Penerimaan (Rp), Pengeluaran (Rp), Saldo Kas (Rp).
  • Menampilkan tanda tangan pejabat unit/holding adaptif via PDFReportBuilder.addSignatures().
  • Nama file dinamis: BKU-[Nama_Unit]-[Periode].pdf.
  1. Ekspor Excel (exportBKUExcel):
  • Skema kolom (8 kolom): Tanggal, No Bukti, Uraian Transaksi, Akun Kas, Unit Usaha, Penerimaan, Pengeluaran, Saldo.
  • Metadata Unit: ... dan Periode: ... tertera di header lembar kerja.
  • Baris rekapitulasi TOTAL MUTASI (Total Masuk & Total Keluar) serta SALDO AKHIR KAS.
  • Penamaan file dinamis: BKU-[Nama_Unit]-[Periode].xlsx.
  1. Ekspor CSV (exportToCSV):
  • Skema kolom (8 kolom): Tanggal, No. Bukti, Keterangan, Akun Sumber, Unit Usaha, Masuk (Rp), Keluar (Rp), Saldo (Rp).
  • Kolom No. Bukti dan Keterangan dipisahkan menjadi kolom mandiri untuk integrasi aplikasi audit eksternal.
  • Penamaan file dinamis: BKU-[Nama_Unit]-[Periode].csv.

๐Ÿงช 5. Matriks Verifikasi & Pengujian Otomatis#

Verifikasi modul BKU dilindungi oleh 16 test cases otomatis pada __tests__/actions/bku_remediation.test.ts:

ID TesFokus PengujianKriteria Lolos
BKU-T01Role Guard & Isolasi RBACMenolak pengguna ilegal & mengunci akun kasir ke unit sendiri
BKU-T02Harmonisasi Status postedTransaksi approved dan posted keduanya dihitung ke mutasi kas
BKU-T03Data Pump PaginationSaldo awal mengagregasi ribuan baris (> 1.000) tanpa terpotong
BKU-T04Prioritas Keterangan Baris Itemline.description lebih diprioritaskan daripada voucher header
BKU-T05Presisi SafeMoney ArithmeticMenghitung akumulasi saldo berjalan tanpa floating point drift
BKU-T06Audit Trail MetadataMemuat reference_type, is_automated, dan status pada tiap baris data
BKU-T07Presisi Tutup Buku KonsolidasiTidak mengunci holding secara keliru jika hanya 1 unit yang tutup buku
BKU-T08Presisi Tutup Buku Unit MandiriMengunci unit tunggal secara akurat ketika periode telah ditutup
BKU-T09Subledger getRecentUnitTransactionsFilter status sah approved & posted, deteksi akun kas 1-100, dan SafeMoney
BKU-T10Standardisasi Format EksporFormat 8 kolom baku pada PDF & Excel, rekapitulasi mutasi, dan nama file dinamis

Apakah panduan ini membantu Anda?