Ringkasan Utama
Pelaporan keuangan otomatis di ERP kustom berhasil bila setiap laporan — Laba Rugi, neraca, arus kas, laporan pajak, dan laporan manajemen — adalah query atas satu jurnal double-entry, dengan periode yang sudah dilaporkan dikunci. Tidak ada data yang diketik ulang, sehingga trial balance selalu mutakhir dan tutup bulan tidak lagi diawali rekonsiliasi spreadsheet dengan buku besar.
Pada Februari 2026, Gartner memprediksi bahwa tim keuangan yang memakai aplikasi ERP cloud dengan asisten AI tertanam dapat mempercepat tutup buku (financial close) hingga 30% pada 2028. Anda tidak perlu menunggu suite cloud untuk memulainya: di UKM Indonesia, saya menemukan bahwa pelaporan keuangan biasanya merupakan modul bernilai tertinggi — yang dilihat CFO dan pemilik setiap minggu. Dalam pekerjaan konsultasi ERP lepas saya, saya membangun mesin pelaporan keuangan yang menghasilkan Laba Rugi, Neraca, Arus Kas, dan laporan manajemen sepenuhnya dari buku besar umum, tanpa pekerjaan spreadsheet manual. Artikel ini membahas arsitekturnya.
Fondasi Chart of Accounts
Setiap laporan keuangan pada dasarnya adalah tampilan atas bagan akun (CoA) dan entri jurnal yang diposting terhadapnya. Sebelum menulis kode pelaporan apa pun, dapatkan struktur CoA yang benar. Saya menggunakan hierarki empat level: Kategori (Aset, Kewajiban, Ekuitas, Pendapatan, Beban) → Kelompok → Sub-kelompok → Akun.
Mesin Jurnal Double-Entry
Mesin jurnal yang saya bangun menegakkan akuntansi double-entry di tingkat database: setiap entri jurnal harus memiliki total debit yang sama dengan total kredit, atau transaksinya dibatalkan. Aturan ini melibatkan beberapa baris, jadi tidak bisa berupa batasan CHECK biasa, yang di PostgreSQL hanya melihat baris yang sedang ditulis; aturan ini butuh pemeriksaan atas seluruh baris entri saat commit, misalnya constraint trigger yang ditangguhkan (deferred). Setiap baris journal_entry memiliki header (tanggal, referensi, deskripsi, jenis) dan beberapa journal_lines (account_id, debit, kredit). Laporan keuangan adalah agregasi atas journal_lines ini, difilter berdasarkan rentang tanggal dan dikelompokkan menurut hierarki akun, sehingga setiap transaksi yang diposting dengan benar — faktur AP, pembayaran AR, penggajian — otomatis muncul di semua laporan keuangan tanpa pemetaan tambahan.
Financial Reporting Engine — NestJS + PostgreSQL
Chart of Accounts (4-level hierarchy)
├── ASSETS
│ ├── Current Assets
│ │ ├── Cash & Bank [11000–11999]
│ │ └── Accounts Receiv. [12000–12999]
│ └── Fixed Assets [15000–15999]
├── LIABILITIES
│ └── Accounts Payable [21000–21999]
├── EQUITY [30000–39999]
├── REVENUE [40000–49999]
└── EXPENSES [50000–59999]
journal_lines (the single source of truth)
┌─────────────────────────────────────────────────┐
│ id │ journal_id │ account_id │ debit │ credit │
│ ...│ ... │ 11001 │ 1000 │ 0 │ <- Cash receipt
│ ...│ ... │ 40001 │ 0 │ 1000 │ <- Revenue
└─────────────────────────────────────────────────┘
↓ Aggregated by NestJS ReportService
P&L Report Balance Sheet Cash Flow
Revenue: 500M Assets: 2.1B Operating: +400M
COGS: (300M) Liab: 800M Investing: (50M)
Gross: 200M Equity: 1.3B Financing: (20M)
Net: 150M Net: 330MDari pengalaman saya membangun sistem ERP sebagai konsultan ERP lepas: selalu implementasikan fitur 'period lock'. PKP wajib melaporkan SPT Masa PPN paling lambat akhir bulan berikutnya, dan wajib pajak badan menyampaikan SPT Tahunan PPh Badan paling lama empat bulan setelah akhir tahun pajak (PMK 81/2024 Pasal 169 dan 171). Setelah periode yang sudah dilaporkan dikunci, tidak ada entri jurnal baru yang dapat diposting ke periode itu — ini mencegah perubahan retroaktif yang akan membatalkan SPT yang sudah disampaikan. Kunci diberlakukan di tingkat database dengan trigger, bukan hanya di lapisan aplikasi.
Pembuatan Laporan Otomatis
Tiga laporan keuangan inti yang saya bangun dibuat sesuai permintaan melalui endpoint NestJS. Endpoint L/R menerima rentang tanggal dan mengembalikan akun pendapatan yang dijumlahkan sebagai pemasukan dan akun beban yang dijumlahkan sebagai biaya, lengkap dengan laba kotor dan laba bersih. Endpoint Neraca menghitung total aset, kewajiban, dan ekuitas pada tanggal tertentu (kumulatif sejak awal, bukan per periode), dan endpoint Arus Kas mengelompokkan pergerakan kas ke aktivitas operasi, investasi, dan pendanaan berdasarkan tag akun. Untuk entitas Indonesia, ikuti PSAK 201 (penyajian) dan PSAK 207 (arus kas) sesuai penomoran IAI sejak 1 Januari 2024, atau SAK EP untuk entitas privat yang berlaku sejak 1 Januari 2025.
Laporan Manajemen dan Segmentasi
Selain laporan wajib, manajemen menginginkan L/R per pusat biaya (berapa banyak yang dihabiskan setiap departemen?), profitabilitas proyek, dan analisis margin produk. Saya mendukung ini melalui cost_center_id dan project_id di setiap baris jurnal. CFO di klien saya mendapatkan email mingguan (dibuat secara otomatis setiap Senin pukul 06.00 WIB) dengan L/R per pusat biaya dilampirkan sebagai file Excel.
-- PostgreSQL: P&L report query
SELECT
coa.category,
coa.group_name,
coa.account_name,
coa.account_code,
SUM(jl.debit - jl.credit) AS net_amount
FROM journal_lines jl
JOIN journal_entries je ON jl.journal_id = je.id
JOIN chart_of_accounts coa ON jl.account_id = coa.id
WHERE
je.posted_at BETWEEN :start_date AND :end_date
AND je.status = 'posted'
AND coa.category IN ('REVENUE', 'EXPENSE')
AND (je.locked_period IS NULL OR je.locked_period >= :start_date)
GROUP BY coa.category, coa.group_name, coa.account_name, coa.account_code
ORDER BY coa.account_code;
-- Period lock enforcement (trigger)
CREATE OR REPLACE FUNCTION check_period_lock()
RETURNS TRIGGER AS $$
BEGIN
IF EXISTS (
SELECT 1 FROM period_locks
WHERE period_year = EXTRACT(YEAR FROM NEW.posting_date)
AND period_month = EXTRACT(MONTH FROM NEW.posting_date)
AND locked = TRUE
) THEN
RAISE EXCEPTION 'Period % is locked — no new entries allowed',
TO_CHAR(NEW.posting_date, 'YYYY-MM');
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_check_period_lock
BEFORE INSERT ON journal_entries
FOR EACH ROW EXECUTE FUNCTION check_period_lock();Bagaimana Saya Mendekati Ini
Mesin pelaporan yang saya bangun adalah modul NestJS dengan empat service: JournalService (posting dan validasi), ReportService (query L/R, Neraca, Arus Kas), SegmentService (filter pusat biaya dan proyek), dan ExportService (PDF via Puppeteer, Excel via exceljs). Semua laporan di-cache di Redis dengan TTL 5 menit.
Jika klien Anda memiliki beberapa entitas legal atau bertransaksi dalam mata uang asing, pelaporan keuangan konsolidasi memerlukan penjabaran mata uang — mengonversi akun anak perusahaan dari mata uang fungsionalnya ke mata uang penyajian dengan kurs yang tepat. Ini adalah sumber kesalahan umum saat ditangani secara manual. Saya menyimpan kurs harian dan mengikuti PSAK 221 (sebelumnya PSAK 10, berbasis IAS 21) atau FASB ASC 830, sesuai kebutuhan pelaporan klien: aset dan liabilitas dijabarkan dengan kurs penutup, penghasilan dan beban dengan kurs pada tanggal transaksi, dan menurut PSAK 221 paragraf 39 selisih penjabarannya diakui dalam penghasilan komprehensif lain, bukan laba rugi.
Integrasi Laporan Pajak (PPN dan PPh)
Sejak masa pajak Januari 2025, Faktur Pajak dan SPT Masa PPN diadministrasikan melalui Coretax DJP, dan SPT Tahunan PPh mulai tahun pajak 2025 juga dilaporkan di sana. ERP yang saya bangun menghubungkan setiap baris jurnal ke kode pajak opsional (PPN 12% atas DPP Nilai Lain 11/12 untuk barang dan jasa nonmewah menurut PMK 131/2024, PPh 23 2% atas jasa, dan seterusnya). Laporan PPN memfilter baris jurnal berdasarkan kode pajak dan masa pajak, menampilkan pajak masukan dan keluaran, lalu menghitung PPN kurang bayar atau lebih bayar. Coretax mengimpor XML sesuai template DJP — faktur pajak, bukti potong, sebagian lampiran SPT Tahunan — sehingga saya membuat file tersebut langsung dari buku besar. Lampiran 1 (Rekonsiliasi Laporan Keuangan) SPT Tahunan Badan bergantung pada sektor usaha, jadi petakan ke bagan akun sejak awal.
Kesiapan Audit dan Jejak Dokumen
Untuk perusahaan Indonesia yang wajib diaudit, setiap entri jurnal memerlukan dokumen pendukung. Pasal 68 UU 40/2007 mewajibkan audit oleh akuntan publik antara lain bila perseroan menghimpun atau mengelola dana masyarakat, merupakan perseroan terbuka, merupakan persero, atau memiliki aset atau peredaran usaha paling sedikit Rp50 miliar. Sistem yang saya bangun menghubungkan entri jurnal ke dokumen sumber — faktur AP, faktur AR, rekening koran, voucher pembayaran — sehingga auditor dapat mengklik baris jurnal mana pun dan melihat dokumen aslinya. Kapabilitas 'drill-down ke sumber' inilah yang membedakan ERP sungguhan dari spreadsheet canggih. Saat auditor eksternal atau kantor pajak meminta bukti pendukung suatu transaksi, saya bisa menampilkannya dalam 30 detik.
Sumber & Bacaan Lebih Lanjut
- Gartner / CFO Dive — Advanced ERPs Could Cut Financial Close Times by 30%
- IAI — Perubahan Penomoran PSAK dan ISAK dalam SAK Indonesia (effective 1 January 2024)
- IAI — Draf Eksposur Amendemen PSAK 221 (paragraph 39: translation into a presentation currency)
- Mekari Jurnal — PSAK 10 kini bernomor PSAK 221
- IAI — Sosialisasi SAK Entitas Privat (effective 1 January 2025)
- Deloitte DART — ASC 830 translation process
- PostgreSQL documentation — Constraints (CHECK limitations)
- PostgreSQL documentation — CREATE TRIGGER (deferred constraint triggers)
- DJP — Penyesuaian Tarif PPN (PMK 131/2024, DPP Nilai Lain 11/12)
- DJP — Pemotongan Pajak Penghasilan Pasal 23
- JDIH BPK — PMK No. 81 Tahun 2024 (Articles 169 and 171: filing deadlines)
- DJP — KT-12/2025 Perkembangan Informasi Terkini Coretax DJP
- DJP — Template XML dan Converter Excel ke XML (Coretax imports)
- DJP Coretaxpedia — Lapor SPT Tahunan Badan
- JDIH BPK — UU No. 40 Tahun 2007 tentang Perseroan Terbatas (Article 68)
