Spesifikasi Teknis Buku Kas Umum (BKU)
๐ ๏ธ 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:
typescriptlet 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 Holding1-101%: Kas Operasional / Kas Kasir Unit1-102%: Kas Kecil / Petty Cash Perbendaharaan1-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:
- Jurnal Manual Terverifikasi: Memiliki status
approved. - Jurnal Otomatis Subsistem: Transaksi dari mesin POS kasir, pembayaran piutang simpan pinjam USP, dan transfer antar-brankas yang telah divalidasi memiliki status
posted. - 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):
typescriptconst 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:
- Tanggal Transaksi (
entry_date ASC) - Waktu Pembuatan (
created_at ASC) - Nomor Bukti Voucher (
entry_number ASC) - Aliran Kas (Debit / Uang Masuk didahulukan sebelum Kredit / Uang Keluar)
- Tie-Breaker Deterministik (
id ASC)
๐ 3. Keamanan & Multi-Unit RBAC#
3.1. Isolasi Akses Tingkat Server Action
Fungsi getBKUReport() mengintegrasikan resolveFinanceRBAC(unitId) secara wajib:
typescriptexport 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 parameterunitId=alldiabaikan dan dipaksa kembali ke unit miliknya.
๐ 4. Spesifikasi Ekspor & Pencetakan Dokumen#
- 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.
- Ekspor Excel (
exportBKUExcel):
- Skema kolom (8 kolom):
Tanggal,No Bukti,Uraian Transaksi,Akun Kas,Unit Usaha,Penerimaan,Pengeluaran,Saldo. - Metadata
Unit: ...danPeriode: ...tertera di header lembar kerja. - Baris rekapitulasi
TOTAL MUTASI(Total Masuk & Total Keluar) sertaSALDO AKHIR KAS. - Penamaan file dinamis:
BKU-[Nama_Unit]-[Periode].xlsx.
- Ekspor CSV (
exportToCSV):
- Skema kolom (8 kolom):
Tanggal,No. Bukti,Keterangan,Akun Sumber,Unit Usaha,Masuk (Rp),Keluar (Rp),Saldo (Rp). - Kolom
No. BuktidanKeterangandipisahkan 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 Tes | Fokus Pengujian | Kriteria Lolos |
|---|---|---|
BKU-T01 | Role Guard & Isolasi RBAC | Menolak pengguna ilegal & mengunci akun kasir ke unit sendiri |
BKU-T02 | Harmonisasi Status posted | Transaksi approved dan posted keduanya dihitung ke mutasi kas |
BKU-T03 | Data Pump Pagination | Saldo awal mengagregasi ribuan baris (> 1.000) tanpa terpotong |
BKU-T04 | Prioritas Keterangan Baris Item | line.description lebih diprioritaskan daripada voucher header |
BKU-T05 | Presisi SafeMoney Arithmetic | Menghitung akumulasi saldo berjalan tanpa floating point drift |
BKU-T06 | Audit Trail Metadata | Memuat reference_type, is_automated, dan status pada tiap baris data |
BKU-T07 | Presisi Tutup Buku Konsolidasi | Tidak mengunci holding secara keliru jika hanya 1 unit yang tutup buku |
BKU-T08 | Presisi Tutup Buku Unit Mandiri | Mengunci unit tunggal secara akurat ketika periode telah ditutup |
BKU-T09 | Subledger getRecentUnitTransactions | Filter status sah approved & posted, deteksi akun kas 1-100, dan SafeMoney |
BKU-T10 | Standardisasi Format Ekspor | Format 8 kolom baku pada PDF & Excel, rekapitulasi mutasi, dan nama file dinamis |