Lewati ke konten

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

AspekKeterangan
Nama MenuBuku Pengawasan Gaji
Lokasi (Tahun NORMAL)Sidebar → Buku PengawasanGaji
Lokasi (Tahun LAMPAU)Sidebar → Data AwalHutangGaji
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

#KeunggulanTier 2 Terkait
1Jurnal granular 23 debet + 11 kredit otomatis dari 1 form input#02, #11
2Auto-fill potongan turunan BPJS dari komponen perhitungan#02
3PPh Pesangon — toggle cerdas dengan threshold otomatis#02, #10
4PPh 21 dual-mode (Dipotong vs Ditanggung) — alur jurnal beda otomatis#11
53 mode tampilan REKAP / DETAIL / ALL — fleksibel per sudut pandang user#08, #10
6UI dinamis per-COA (kolom & label menyesuaikan tbl_coa)#10
7Pembayaran 1-klik via drawer + outstanding tagihan otomatis#08, #13
8Konteks 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.BuildJurnalLinesAsync loop semua komponen, generate Transaksi line per komponen non-zero (baris dengan jumlah=0 di-skip)
  • Setiap line dapat COA & NamaAkun dari tbl_coa via ICoaService.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_pengawasangaji dalam 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:

  • useEffect di InputGajiModal.tsx dengan 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.confirm Antd
  • 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:

ModeJurnal yang Dibentuk
DipotongKredit: Hutang PPh Pasal 21 (mengurangi gaji bersih yang diterima karyawan)
DitanggungDebet: 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 (_100 Rutin “21610” vs _401 Pesangon “21611”) agar memudahkan equalisasi dengan SPT Masa Bulanan

Bagaimana Booku Melakukannya:

  • Validasi simpan cek konsistensi: kalau pilih “Dipotong” → PotonganHutangPPhPasal21Rutin harus > 0; kalau “Ditanggung” → PPhDitanggungRutin harus > 0 (analog untuk Pesangon)
  • BuildJurnalLinesAsync deterministik 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:

ModePemilihTampilanAksi Tersedia
REKAP (default)filter Bulan = REKAP12 baris bulan fixed (Januari–Desember, termasuk yang kosong) + grand totalDetail Perbulan, Detail Pembayaran, Bayar
DETAILfilter Bulan = nama bulan (Januari, …)Rincian gaji 1 bulan tertentu (bisa multi-record) + grand totalEdit, Hapus, Lihat Jurnal
ALLfilter Bulan = ALLRincian seluruh records dikelompokkan per bulan + subtotal per bulan + grand totalEdit, 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:

  • displayItems useMemo dengan branch per mode (REKAP loop 12 bulan + empty placeholder, ALL detail+subtotal+separator, DETAIL flat)
  • Synthetic marker rows via nomorID negatif: -1 grand total, -50..-61 empty bulan REKAP, -100..-111 subtotal ALL, ≤-200 separator ALL
  • noMap precomputed → nomor urut tetap 1-12 di REKAP (termasuk empty bulan), 1-N di DETAIL/ALL (tanpa gap di antara marker)
  • getAksiMenuItems skip 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_Akun dari tbl_coa kalau 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: columnDefs filter kolom by isVisible(meta) + override header by info?.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 GetOutstandingHutangGajiAsync di BuktiPengeluaranService parse NomorBP (BPHG-{Tahun}-{NomorBulan}), agregat SUM(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:

KonteksYang Berubah
Tahun Buku NORMAL, tahun aktifSemua aksi visible (Input, Edit, Hapus, Bayar); judul “Buku Pengawasan Gaji”; mode REKAP/DETAIL/ALL semua available
Tahun Buku NORMAL, telusur tahun closedMode 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 header X-Tahun-Buku per request → backend pilih DB transaksi yang sesuai
  • State filterTahun !== TahunBukuAktif → kondisi “tahun closed”, aktifkan visibility rules read-only via view-mode-action-scope-pattern.md Lapis 2 (SHOW + DISABLED + tooltip)
  • Mode LAMPAU vs NORMAL via prop pageMode (PageMode_BukuPengawasan vs PageMode_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