Keunggulan Booku: Buku Pengawasan Gaji
Tier 3 — keunggulan-keunggulan Booku yang muncul saat user memakai menu Buku Pengawasan Gaji dan form Input Gaji.
📘 Deskripsi user-friendly:
deskripsi/buku-pengawasan-gaji.md
1. Identitas Menu
| Aspek | Keterangan |
|---|---|
| Nama Menu | Buku Pengawasan Gaji |
| Lokasi (Tahun NORMAL) | Sidebar → Buku Pengawasan → Gaji |
| Lokasi (Tahun LAMPAU) | Sidebar → Data Awal → Hutang → Gaji |
| Deskripsi User-Facing | 📘 Deskripsi & tutorial menu |
Buku Pengawasan Gaji adalah halaman untuk mencatat hutang gaji perusahaan ke karyawan (agregat per bulan) dan melacak pelunasannya. Berbeda dengan aplikasi payroll yang fokus per-karyawan, Booku memandang gaji sebagai tagihan korporat per bulan — input sekali, lalu Booku pecah ke 23 baris debet granular + 11 baris kredit (potongan, hutang gaji, PPh) secara otomatis lewat jurnal yang dibentuk dari satu form input.
Form Input Gaji memungkinkan user memecah komponen gaji menjadi rincian halus (Produksi vs Administrasi × 11 komponen masing-masing + 8 potongan), dengan auto-kalkulasi subtotal di setiap level dan auto-fill turunan BPJS.
2. Ringkasan Keunggulan
| # | Keunggulan | Tier 2 Terkait |
|---|---|---|
| 1 | Jurnal granular 23 debet + 11 kredit otomatis dari 1 form input | #02, #11 |
| 2 | Auto-fill potongan turunan BPJS dari komponen perhitungan | #02 |
| 3 | PPh Pesangon — toggle cerdas dengan threshold otomatis | #02, #10 |
| 4 | PPh 21 dual-mode (Dipotong vs Ditanggung) — alur jurnal beda otomatis | #11 |
| 5 | 3 mode tampilan REKAP / DETAIL / ALL — fleksibel per sudut pandang user | #08, #10 |
| 6 | UI dinamis per-COA (kolom & label menyesuaikan tbl_coa) | #10 |
| 7 | Pembayaran 1-klik via drawer + outstanding tagihan otomatis | #08, #13 |
| 8 | Konteks tahun buku adaptif (NORMAL vs LAMPAU / aktif vs closed) | #08, #10 |
3. Detail per Keunggulan
3.1 Jurnal Granular 23 Debet + 11 Kredit Otomatis dari 1 Form Input
Apa yang dirasakan user: User cukup mengisi satu form Input Gaji (Produksi + Administrasi + Potongan + PPh). Saat Simpan, Booku otomatis membentuk jurnal multi-line yang detail dan terpisah per komponen — sampai 23 baris Debet granular + 11 baris Kredit dalam 1 voucher. User tidak perlu hafal mana akun untuk Biaya Gaji Produksi vs Biaya BPJS TK JKK/JKM Produksi vs Biaya Tunjangan PPh 21 — semua sudah ditentukan via konstanta KodeTautanCOA.
Mengapa penting:
- Laporan Laba Rugi & Buku Besar otomatis dapat rincian per komponen biaya — bukan agregat. Manajemen bisa lihat “Biaya BPJS Kesehatan Produksi” sebagai line item terpisah dari “Biaya Gaji Produksi” → analisis biaya per komponen jadi mudah.
- Equalisasi dengan SPT Masa PPh 21 & SPT Tahunan PPh Badan lebih akurat karena PPh 21 Rutin & PPh 21 Pesangon di-jurnal ke 2 akun terpisah (
HutangPPhPasal21_100“21610” untuk Rutin,HutangPPhPasal21_401“21611” untuk Pesangon) - Aplikasi payroll lain umumnya hanya generate jurnal agregat (“Beban Gaji” 1 baris debet) — user harus turun manual untuk rincian
Bagaimana Booku Melakukannya:
- Backend
GajiService.BuildJurnalLinesAsyncloop semua komponen, generateTransaksiline per komponen non-zero (baris dengan jumlah=0 di-skip) - Setiap line dapat
COA&NamaAkundaritbl_coaviaICoaService.GetCoaNameAsync(bukan hardcode) — saat user ganti kode COA di Data Master, jurnal otomatis ikut - Lawan Transaksi pakai konstanta Internal (
INT/Internal) — sama dengan transaksi reklasifikasi internal lain di Booku - Save jurnal + simpan ke
tbl_pengawasangajidalam 1 SaveChangesAsync (atomic) → kalau gagal, rollback otomatis - Saat Edit Gaji: NomorJV tetap, hapus jurnal lama + buat baru dalam transaksi yang sama
- Multi-user safe: pakai retry exponential backoff (200ms/500ms/1000ms + jitter) untuk handle race condition
MAX(Nomor_ID)+1
→ Cross-link: #02 Automatic Everything, #11 Jurnal Multi-line
3.2 Auto-Fill Potongan Turunan BPJS dari Komponen Perhitungan
Apa yang dirasakan user: Saat user mengisi komponen-komponen BPJS Kesehatan (Produksi/Administrasi/Dibayar Karyawan), field Potongan_Hutang_BPJS_Kesehatan di kolom Potongan otomatis ter-update dengan total semua komponennya. Sama untuk BPJS Ketenagakerjaan (JKK/JKM + JHT/IP + porsi karyawan). User tidak perlu menjumlahkan manual.
Mengapa penting:
- Iuran BPJS terdiri dari banyak sub-komponen (Produksi vs Administrasi, JKK/JKM vs JHT/IP, porsi perusahaan vs karyawan) — kalau dihitung manual rawan typo
- Hasil potongan ini harus = tagihan ke pihak ketiga (BPJS Kesehatan / BPJS TK) yang dicatat di menu Buku Pengawasan Turunan Gaji → kalau salah jumlah, akan muncul “Selisih ≠ 0” di menu turunan
- Auto-fill menjamin sinkronisasi otomatis antara Buku Pengawasan Gaji dan turunannya
Bagaimana Booku Melakukannya:
useEffectdiInputGajiModal.tsxdengan dependency komponen BPJS — saat berubah, recompute total & set ke field potongan- Hanya aktif di
JalurMasuk_Default— di JalurMasuk turunan (turunan-bpjs-kesehatan/turunan-bpjs-ketenagakerjaan) field potongan dapat di-edit manual untuk koreksi cepat - Logic mengikuti konvensi internal (event TextChanged pada komponen BPJS)
→ Cross-link: #02 Automatic Everything
3.3 PPh Pesangon — Toggle Cerdas dengan Threshold Otomatis
Apa yang dirasakan user: Group radio “PPh Pesangon Dipotong/Ditanggung” awalnya disabled. Saat user mengisi field Pesangon Karyawan dan total Pesangon > Rp 50 juta (threshold PPh 21 final tarif progresif), Booku otomatis menampilkan konfirmasi: “Apakah ada PPh untuk Pesangon?”. Jika “Ya” → group radio enabled, user pilih mode (Dipotong vs Ditanggung). Jika ≤ 50 juta atau “Tidak ada PPh”, group otomatis disabled & value PPh-Pesangon di-clear.
Mengapa penting:
- Pesangon adalah penghasilan tidak teratur dengan aturan PPh 21 berbeda (tarif final progresif: 0% sampai 50jt, 5% sampai 100jt, 15% sampai 500jt, 25% di atas 500jt)
- Tanpa toggle threshold, user kebingungan kapan harus menerapkan tarif Pesangon vs Rutin — bisa salah hitung PPh
- Threshold 50jt otomatis trigger UI → user dapat reminder edukatif tanpa harus baca dokumentasi pajak
Bagaimana Booku Melakukannya:
- Event LostFocus pada 2 field Pesangon (Produksi + Administrasi) → cek total > 50jt →
Modal.confirmAntd - Helper
hitungPPhPesangonProgresif(jumlah)disiapkan (5%/15%/25% tier 50jt/100jt/500jt) tapi tidak auto-assign ke field — sesuai keputusan internal (“Sementara ini belum dibutuhkan perhitungan”). User tetap input manual nominal PPh sesuai perhitungan kebijakan perusahaan - Mode EDIT: toggle disabled (PPh mode tidak boleh berubah saat edit) — sehingga konsistensi jurnal terjaga
→ Cross-link: #02 Automatic Everything, #10 UI Dinamis
3.4 PPh 21 Dual-Mode (Dipotong vs Ditanggung) — Alur Jurnal Beda Otomatis
Apa yang dirasakan user: Saat input gaji, user pilih radio PPh 21 Rutin: Dipotong / Ditanggung (dan opsional Pesangon kalau ada). Setelah Simpan, Booku otomatis bentuk jurnal yang berbeda struktur tergantung mode:
| Mode | Jurnal yang Dibentuk |
|---|---|
| Dipotong | Kredit: Hutang PPh Pasal 21 (mengurangi gaji bersih yang diterima karyawan) |
| Ditanggung | Debet: Biaya PPh Pasal 21 (sebagai biaya perusahaan) + Kredit: Hutang PPh Pasal 21 (tagihan ke negara tetap muncul) |
Mengapa penting:
- Kebijakan PPh 21 perusahaan berbeda-beda — ada yang potong dari gaji, ada yang ditanggung perusahaan sebagai benefit. Dua mode ini punya dampak laporan keuangan yang sangat berbeda (mode Ditanggung = biaya naik, gaji bersih karyawan tetap utuh)
- Aplikasi payroll standar biasanya hanya mendukung 1 mode; di Booku, sekali pilih radio, jurnal otomatis ikut — user tidak perlu hafal logikanya
- Plus: PPh 21 Rutin & Pesangon di-jurnal ke akun terpisah (
_100Rutin “21610” vs_401Pesangon “21611”) agar memudahkan equalisasi dengan SPT Masa Bulanan
Bagaimana Booku Melakukannya:
- Validasi simpan cek konsistensi: kalau pilih “Dipotong” →
PotonganHutangPPhPasal21Rutinharus > 0; kalau “Ditanggung” →PPhDitanggungRutinharus > 0 (analog untuk Pesangon) BuildJurnalLinesAsyncdeterministik per mode — Rutin & Pesangon di-treat independent (boleh kombinasi: Rutin Dipotong + Pesangon Ditanggung)- Saat Edit: mode PPh terkunci (group radio disabled) untuk hindari inkonsistensi jurnal vs tabel pengawasan
→ Cross-link: #11 Jurnal Multi-line
3.5 3 Mode Tampilan REKAP / DETAIL / ALL — Fleksibel per Sudut Pandang User
Apa yang dirasakan user: Dropdown filter Bulan di header bukan sekadar filter, tapi sekaligus pemilih 3 sudut pandang terhadap data gaji:
| Mode | Pemilih | Tampilan | Aksi Tersedia |
|---|---|---|---|
| REKAP (default) | filter Bulan = REKAP | 12 baris bulan fixed (Januari–Desember, termasuk yang kosong) + grand total | Detail Perbulan, Detail Pembayaran, Bayar |
| DETAIL | filter Bulan = nama bulan (Januari, …) | Rincian gaji 1 bulan tertentu (bisa multi-record) + grand total | Edit, Hapus, Lihat Jurnal |
| ALL | filter Bulan = ALL | Rincian seluruh records dikelompokkan per bulan + subtotal per bulan + grand total | Edit, Hapus, Lihat Jurnal |
Mengapa penting:
- Konsisten dengan konvensi standar yang menampilkan 12 baris fixed di mode REKAP — user existing tidak perlu adaptasi
- Mode REKAP dengan 12 baris fixed memungkinkan user langsung lihat slot kosong — bulan mana yang belum di-input
- Mode ALL berguna untuk audit cross-bulan (validasi subtotal REKAP = jumlah records di DETAIL) atau cetak laporan komprehensif
- Konsep “scope aksi = scope row” (REKAP = bulan-level, DETAIL/ALL = record-level) menjaga predictability menu — user tidak menebak aksi mana yang muncul
Bagaimana Booku Melakukannya:
displayItemsuseMemo dengan branch per mode (REKAP loop 12 bulan + empty placeholder, ALL detail+subtotal+separator, DETAIL flat)- Synthetic marker rows via
nomorIDnegatif:-1grand total,-50..-61empty bulan REKAP,-100..-111subtotal ALL,≤-200separator ALL noMapprecomputed → nomor urut tetap 1-12 di REKAP (termasuk empty bulan), 1-N di DETAIL/ALL (tanpa gap di antara marker)getAksiMenuItemsskip semua marker rows (nomorID < 0) → tidak ada aksi misleading pada row sintetis
→ Cross-link: #08 Simple for User, #10 UI Dinamis
3.6 UI Dinamis Per-COA (Kolom & Label Menyesuaikan tbl_coa)
Apa yang dirasakan user: Tabel utama & form Input Gaji menyesuaikan diri dengan setting COA perusahaan:
- Kolom yang COA-nya di-set “Visibilitas: Tidak” di Data COA → otomatis hidden baik di tabel utama maupun form input
- Header kolom / label field pakai
Nama_Akundaritbl_coakalau ada — bukan label default. Mis. perusahaan rename COA “Biaya Gaji Produksi” jadi “Beban Gaji Pegawai Pabrik” → label di Booku ikut otomatis
Mengapa penting:
- Setiap perusahaan punya struktur COA berbeda — ada yang tidak pakai komponen tertentu (mis. tidak ada Asuransi Karyawan terpisah), atau pakai nomenklatur berbeda
- Tanpa visibility per-COA, kolom-kolom yang tidak relevan jadi clutter → user kebingungan
- Konsisten dengan filosofi Booku: COA adalah single source of truth untuk struktur akun perusahaan
Bagaimana Booku Melakukannya:
- Saat halaman/modal mount, paralel fetch
coaService.getByCode(kodeTautan)untuk semua KodeTautanCOA yang dipakai (~25 kode tautan COA untuk Gaji) - Hasil di-simpan di
visibilityMap: Record<string, { visible, namaAkun }>(state useMemo) - Tabel utama:
columnDefsfilter kolom byisVisible(meta)+ override header byinfo?.namaAkun - Form Input: pasangan label+input di-conditional render by
visibilityMap - Pengecualian: PPh 21 Rutin & Pesangon mempertahankan label custom (sesuai keputusan internal) — overlay label tidak diambil dari Nama_Akun
→ Cross-link: #10 UI Dinamis
3.7 Pembayaran 1-Klik via Drawer + Outstanding Tagihan Otomatis
Apa yang dirasakan user: Di mode REKAP, klik kanan baris bulan → Bayar. Booku otomatis: (1) buka Detail Pembayaran Drawer di sisi kanan (riwayat pembayaran bulan tsb + info Sisa Pembayaran + status Lunas/Belum Lunas), (2) langsung membuka modal Input Pengeluaran Bank/Cash dengan preset lengkap (Kategori “Pembayaran Hutang” terkunci, Peruntukan “Pembayaran Hutang Gaji” terkunci, Lawan Transaksi KRY/Karyawan Internal terisi otomatis, NomorBP = NomorBPHG bulan tsb), (3) tabel kanan modal menampilkan 1 baris tagihan dengan Jumlah Tagihan, Sudah Dibayar, Sisa Tagihan, dan Jumlah Bayar default = sisa. User tinggal pilih Sarana Pembayaran (bank/cash) lalu Simpan.
Mengapa penting:
- Mencatat pembayaran gaji manual = pindah menu, isi 10+ field, hafal Lawan Transaksi → boros waktu & rawan salah
- Pattern 1-klik ini share dengan modul Hutang/Piutang Karyawan, Pemegang Saham, Pihak Ketiga, Afiliasi, Pajak → user belajar sekali, pakai di banyak menu
- Drawer punya status visual (Lunas hijau / Belum Lunas oranye) → user langsung tahu apa yang perlu dibayar
Bagaimana Booku Melakukannya:
- Frontend
useBuktiPengeluaranStore.openAddModal()dengan preset dari menu → modal share dengan menu Bukti Pengeluaran utama tapi field-field locked sesuai konteks - Backend
GetOutstandingHutangGajiAsyncdiBuktiPengeluaranServiceparseNomorBP(BPHG-{Tahun}-{NomorBulan}), agregatSUM(JumlahGajiDibayarkan)semua record bulan tsb, hitung sisa = total −SUM(JumlahBayar), return 1 item ke modal - Multi-record per bulan handled: SUM agregat di backend menjamin Sisa Tagihan benar meski user input gaji multi-record di Januari (kasus gelombang pembayaran / per-divisi / dst.)
- Saat hutang sudah lunas → tombol Bayar otomatis disabled + tooltip “Sudah Lunas” (Lapis 2 dari
view-mode-action-scope-pattern.md)
→ Cross-link: #08 Simple for User, #13 Buku Pengawasan Penerimaan/Pengeluaran
3.8 Konteks Tahun Buku Adaptif (NORMAL vs LAMPAU / Aktif vs Closed)
Apa yang dirasakan user: Tampilan menu otomatis menyesuaikan dengan konteks tahun buku:
| Konteks | Yang Berubah |
|---|---|
| Tahun Buku NORMAL, tahun aktif | Semua aksi visible (Input, Edit, Hapus, Bayar); judul “Buku Pengawasan Gaji”; mode REKAP/DETAIL/ALL semua available |
| Tahun Buku NORMAL, telusur tahun closed | Mode read-only — Input/Edit/Hapus/Bayar hidden; pewarnaan row tahun lalu (abu-abu); Lihat Jurnal tetap available |
| Tahun Buku LAMPAU (Data Awal) | Judul ganti jadi “Saldo Akhir Hutang Gaji”; alur input data historis (saldo akhir manual); drawer Detail Pembayaran sembunyikan tombol Tambah Pembayaran + tampilkan Alert info |
Mengapa penting:
- Booku punya multi-tenant per tahun — 1 database transaksi per tahun (mis.
bookuid_booku_dummycli_2022). User bisa telusur tahun lampau tanpa mengganggu tahun aktif - Mode LAMPAU butuh alur input berbeda karena saldo awal diinput manual (bukan hasil transaksi); jurnal balancing-nya juga beda
- Tanpa adaptasi konteks, user bisa tanpa sadar mengubah data tahun closed → audit trail rusak
Bagaimana Booku Melakukannya:
- Frontend ganti tahun via filter →
gajiService.getAllForYear(tahun)override headerX-Tahun-Bukuper request → backend pilih DB transaksi yang sesuai - State
filterTahun !== TahunBukuAktif→ kondisi “tahun closed”, aktifkan visibility rules read-only viaview-mode-action-scope-pattern.mdLapis 2 (SHOW + DISABLED + tooltip) - Mode LAMPAU vs NORMAL via prop
pageMode(PageMode_BukuPengawasanvsPageMode_DataAwal) +useAppStore().JenisTahunBuku - Dual-entry route:
/buku-pengawasan/gaji(NORMAL) +/data-awal/hutang/gaji/gaji(LAMPAU) → komponen yang sama dengan prop berbeda
→ Cross-link: #08 Simple for User, #10 UI Dinamis
4. Nilai Tambah untuk User
“Form Input Gaji 3-panel yang otomatis bentuk jurnal granular sampai 23 baris debet + 11 baris kredit dari 1x simpan, plus pembayaran 1-klik via drawer — tidak ada lagi setup payroll yang rumit, tidak perlu hafal akun apa yang dipakai.”
Booku memandang gaji sebagai tagihan korporat per bulan, bukan kewajiban per-karyawan yang harus di-track satu per satu. User cukup input agregat sebulan (atau beberapa kali kalau ada gelombang pembayaran), sisanya Booku yang urus: jurnal granular, sinkronisasi potongan ke Buku Pengawasan Turunan Gaji, sampai outstanding tagihan otomatis muncul saat klik Bayar.
5. Catatan Implementasi
Detail teknis lengkap (algoritma jurnal, struktur DTO, validasi, marker nomorID, mode tampilan, dst) ada di:
Terakhir diperbarui: 23-05-2026