2026 · Open Source

pph21 — Pajak Payroll Indonesia Jadi Package

Kalkulator PPh 21 dan BPJS open source untuk Node.js dan browser, dipublikasikan ke npm. Sembilan jenis pegawai, TER dan Pasal 17, versioned per tahun pajak, setiap hasil bisa dilacak ke dasar hukumnya.

  • TypeScript
  • Vitest
  • dayjs
  • tsup
  • semantic-release

GitHub ↗npm ↗

PeranPenulis tunggal — desain, implementasi, verifikasi
StatusTerbit di npm sebagai pph21, lisensi MIT, rilis otomatis dari main
DomainPPh 21 (PMK 168/2023), BPJS, insentif PPh 21 DTP PMK 105/2025
StackTypeScript, Vitest, dayjs, tsup
Test8 suite — semua jenis pegawai, integritas tabel TER, bracket progresif, BPJS, DTP

Kenapa dibuat

Di Sistem Payroll 800+ Karyawan, logika PPh 21 dan BPJS terkubur di dalam aplikasi NestJS, menempel ke database dan queue-nya. Itu wajar untuk sistem produksi, tapi artinya bagian yang paling sulit dan paling bisa dipakai ulang — logika pajaknya sendiri — tidak bisa diambil proyek lain, di-review terpisah, atau dijadikan open source.

pph21 adalah logika itu, diekstrak dan digeneralisasi melampaui aturan satu klien ke sembilan kategori pegawai yang diatur PMK 168/2023, lalu dipublikasikan sebagai package berdiri sendiri. Bagian sulitnya bukan menyambungkannya ke aplikasi — tapi memastikan hitungan pajak payroll Indonesia benar, yang ternyata bukan satu formula, melainkan sembilan aturan yang saling tumpang tindih dan berubah menurut jadwal pemerintah, bukan jadwal saya.

Keputusan

Satu field menentukan aturan mana yang berlaku

employeeType adalah discriminated union — pegawai-tetap, bukan-pegawai, peserta-kegiatan, dewan-komisaris, dan lima lainnya — TypeScript menyempitkan sisa input agar sesuai. Honorarium freelancer dan gaji bulanan pegawai tetap dikenai aturan yang benar-benar berbeda (50% × bruto × Pasal 17 vs. bruto × TER Bulanan); kalau digabung jadi satu calculate(input) generik, perbedaan itu bersembunyi di balik field opsional yang tidak bisa dipertanggungjawabkan siapa pun. Sembilan kalkulator, satu entry point, tidak ada ambiguitas soal aturan mana yang berjalan.

Konstanta di-versioned per tahun pajak, bukan ditimpa

Nilai PTKP, tabel TER, bracket Pasal 17, batas atas BPJS — setiap angka resmi ada di src/constants/, diberi kunci per tahun di tax-years.ts. Tahun pajak baru berarti objek konfigurasi baru yang menyalin tahun sebelumnya dan hanya meng-override yang berubah; tidak ada yang diubah di tempat. Prinsipnya sama dengan konstanta yang bisa diedit admin di sistem payroll — bedanya ini library tanpa database, jadi audit trail-nya git history dan CHANGELOG.md, bukan tabel.

Setiap hasil menjelaskan dirinya sendiri

Return type-nya bukan sekadar angka — ada dpp, method, kategori dan rate ter kalau relevan, breakdown per baris sesuai urutan bukti potong, dan string regulation yang mengutip dasar hukumnya. Angka tanpa metode yang menyertainya adalah tiket support yang menunggu waktu; angka yang sudah membawa penjelasannya sendiri tidak.

Diverifikasi ke PDF peraturan, bukan situs kalkulator

Dua sumber sekunder independen yang dicek saat membangun tabel TER ternyata diam-diam salah di bracket TER B/C — cukup mirip untuk lolos dari sekilas pandang, cukup salah untuk mengacaukan potongan pajak seseorang. Setiap tabel diverifikasi langsung ke teks resmi PMK/PP, didukung assertion integritas tabel (rate tidak menurun, batas kontigu) dan golden test yang direproduksi dari contoh perhitungan resmi DJP — hasil pph21 untuk contoh di quick-start cocok sampai ke angka rupiah dengan contoh DJP.

Insentif DTP 2026 sebagai opsi tambahan, bukan kasus khusus

PMK 105/2025 memperkenalkan insentif pajak DTP (ditanggung pemerintah) untuk 2026, berlaku hanya pada kondisi penghasilan tertentu. Daripada mencabangkan kalkulator inti, insentif ini jadi objek konfigurasi kedua (dtp: { eligible, baselineMonthlyGross }) yang ditumpuk di atas — saat berlaku, pph21 menjadi nol dan jumlahnya pindah ke dtpAmount. Kalkulator yang sudah ada sebelum insentif ini tidak perlu tahu insentif ini ada.

Hasil

  • Terbit dan siap dipasang: npm install pph21.
  • Rilis terverifikasi CI — setiap push ke main di-versioned otomatis oleh semantic-release berdasarkan Conventional Commits; tidak ada nomor versi yang diubah manual.
  • CONSTANTS.md mendokumentasikan persis file mana yang harus disentuh untuk perubahan peraturan tertentu, jadi update tahun pajak berikutnya tidak perlu membaca ulang source code untuk mencarinya.
  • Sengaja dibatasi ruang lingkupnya: PPh 26 untuk ekspatriat non-resident, generate XML e-Bupot, dan konsolidasi akhir tahun multi-pemberi-kerja disebutkan eksplisit sebagai di luar cakupan di README, bukan dibangun setengah jadi.