# Akuntansi Multi-Currency di ERP: Kurs, Laba Selisih, Rounding IDR

> Mendesain akuntansi multi-currency di ERP custom: journal line dua mata uang, laba selisih kurs realized vs unrealized, dan aturan rounding IDR yang jarang dibahas.

URL: https://www.matthewswong.com/id/blog/erp-multi-currency-accounting/

- Author: Matthews Wong (https://www.matthewswong.com/id/about/)
- Published: 2026-04-09
- Updated: 2026-04-09
- Category: ERP

Pertama kali klien meminta saya menambahkan invoice USD ke ERP berbasis IDR, estimasi saya dua minggu. Perubahan skemanya selesai dua hari. Tiga bulan sisanya habis untuk semua hal di sekelilingnya: kurs mana yang berlaku di tanggal mana, apa yang terjadi saat invoice USD dibayar dengan kurs berbeda, bagaimana revaluasi akhir bulan bekerja, dan kenapa laporan AR aging tiba-tiba menampilkan customer berutang minus 37 rupiah. Multi-currency bukan sekadar field di form — ini subsistem akuntansi.

Artikel ini adalah desain yang saya harap saya punya sejak hari pertama, dibentuk dari pengalaman membangun AP/AR untuk ANCoraPRO di NestJS dan PostgreSQL: data model dua mata uang, pipeline kurs, laba rugi realized versus unrealized, dan realita rounding mata uang fungsional yang praktis tidak punya angka desimal.

## Data Model: Setiap Line Membawa Dua Mata Uang

Aturan yang tidak bisa ditawar dari IAS 21, standar akuntansi yang mengatur efek selisih kurs: entitas membukukan dalam mata uang fungsionalnya — untuk perusahaan Indonesia, hampir selalu IDR — dan transaksi mata uang asing ditranslasikan dengan kurs pada tanggal transaksi. Skema Anda harus mencerminkan dualitas itu di setiap line moneter: nilai dokumen dalam mata uang transaksi, dan nilai yang dibukukan dalam mata uang fungsional, dikonversi sekali saat posting lalu dibekukan.

Dibekukan adalah kata kuncinya. Kelas bug multi-currency terbesar yang saya lihat di ERP custom adalah hanya menyimpan nilai asing lalu mengonversi saat dibaca, memakai kurs terkini. Akibatnya laporan berubah retroaktif setiap tabel kurs di-update, dan dua cetakan ledger yang sama tidak cocok. Simpan kurs yang dipakai, simpan nilai hasil konversi, dan jangan pernah menghitung ulang keduanya:

Perhatikan amount_functional adalah NUMERIC tanpa desimal. IDR modern tidak punya subunit yang terpakai — sen ada di undang-undang tapi tidak di pembayaran — jadi membukukan nilai fungsional dalam rupiah utuh sejak awal menyelamatkan Anda dari saldo pecahan hantu di kemudian hari. Sisi mata uang transaksi tetap dua desimal karena USD, SGD, dan EUR memang memakainya.

## Kurs: Satu Pipeline, Tiga Jenis Kurs

Keputusan desain kedua adalah kurs mana berlaku kapan. Dalam praktik di Indonesia Anda akan berurusan dengan sampai tiga keluarga kurs, dan tabel kurs Anda harus tahu yang mana:

Kurs transaksi — kurs pada tanggal dokumen, dipakai membukukan invoice dan tagihan. Kebanyakan klien memakai kurs referensi JISDOR dari Bank Indonesia untuk USD; dipublikasikan per hari kerja dan paling tidak bisa diperdebatkan saat audit.

Kurs pajak — Kementerian Keuangan menerbitkan kurs mingguan yang wajib dipakai untuk dokumen pajak. Invoice Anda bisa sah membawa satu kurs untuk akuntansi dan kurs lain untuk perhitungan PPN; desain untuk kedua field, jangan asumsikan sama.

Kurs penutup — kurs pada tanggal neraca, dipakai merevaluasi saldo moneter terbuka di akhir bulan sesuai IAS 21. Inilah yang menggerakkan laba rugi unrealized.

Secara operasional saya memperlakukan kurs sebagai data referensi append-only dengan kolom source: fetch harian otomatis menulis baris BI_JISDOR, finance bisa memasukkan override MANUAL untuk mata uang yang tidak tercakup feed, dan tidak ada yang meng-update baris yang sudah ada. Kalau ada kurs salah, Anda memasukkan kurs koreksi dan mem-posting ulang dokumen terdampak secara sengaja — perbaikan retroaktif diam-diam adalah awal pembukuan berhenti rekonsil.

Pro tip: buat service posting gagal dengan jelas saat tidak ada kurs untuk tanggal dokumen, alih-alih fallback ke kurs terakhir yang tersedia. Fallback terasa membantu saat development, lalu diam-diam membukukan invoice hari Jumat dengan kurs hari Rabu di production. Tim finance memaafkan posting yang terblokir; mereka tidak memaafkan angka salah yang ketahuan tiga bulan kemudian.

## Laba Selisih Kurs Realized vs Unrealized: Dua Peristiwa Berbeda

Selisih kurs datang dalam tepat dua rasa, dan mencampuradukkannya adalah bug konseptual paling umum di modul multi-currency buatan sendiri:

## Laba rugi realized

Terjadi saat pelunasan. Invoice dibukukan dengan satu kurs, pembayaran terkonversi dengan kurs lain, dan selisihnya adalah uang nyata yang masuk laporan laba rugi begitu pembayaran efektif.

## Laba rugi unrealized

Terjadi saat tutup periode. Saldo mata uang asing yang masih terbuka direvaluasi dengan kurs penutup. Tidak ada kas berpindah — ini penyesuaian di atas kertas, dan akan dibalik atau disesuaikan lagi periode berikutnya.

Logika pelunasan layak diberi contoh kerja, karena invariant subledger yang dilindunginya adalah yang menjaga AR dan AP tetap jujur:

Invariant itu — open item harus menutup ke nol di mata uang transaksi DAN mata uang fungsional — adalah hal yang harus dites tanpa ampun. Setiap pembayaran parsial, setiap credit note, setiap write-off wajib mempertahankannya. Mesin akuntansi Odoo melakukan hal yang sama dengan jurnal exchange difference otomatisnya: selisih dibukukan ke akun FX khusus, tidak pernah ke piutangnya sendiri.

## Revaluasi Akhir Bulan Tanpa Drama

FX unrealized adalah batch job, dan cara paling bersih yang saya temukan untuk menjalankannya di ERP custom adalah prosedur empat langkah yang sepenuhnya bisa dibalik:

1. Pilih semua item moneter terbuka dalam mata uang asing: line AR dan AP yang belum dibayar, rekening bank valas, uang muka dan deposit.
2. Revaluasi masing-masing dengan kurs penutup tanggal akhir periode dan hitung delta terhadap nilai buku fungsionalnya saat ini.
3. Posting satu jurnal revaluasi per mata uang, bertanggal hari terakhir periode, terhadap akun laba dan rugi FX unrealized.
4. Posting pembalik otomatis bertanggal hari pertama periode berikutnya. Pelunasan kemudian menghitung selisih realized terhadap kurs pembukuan asli, tidak terganggu noise revaluasi.

Pakai pola reversing entry meskipun akuntan Anda bilang ERP yang dipakainya dulu menyesuaikan saldo langsung di tempat. Pembalikan menjaga revaluasi benar-benar terpisah dari histori transaksional, artinya closing yang kacau bisa diulang dengan membalik satu jurnal, bukan mengurai open item yang sudah teradjust satu per satu.

## Realita Rounding IDR

Rounding terdengar seperti catatan kaki sampai trial balance Anda selisih 1 rupiah dan auditor ingin tahu kenapa. Aturan yang sekarang saya bangun sejak awal:

Round di level line, sekali, saat posting — half-up ke rupiah utuh untuk nilai fungsional. Menjumlahkan line yang sudah dibulatkan itu stabil; membulatkan hasil penjumlahan tidak bisa direproduksi dari komponennya.

Paksa jurnal balance setelah rounding: kalau debit dan kredit selisih beberapa rupiah akibat rounding per line, posting selisihnya ke akun rounding khusus secara otomatis. Jangan biarkan posting gagal atau, lebih buruk, mengakali line sungguhan.

Simpan kurs dengan enam desimal. Kuotasi bergaya JISDOR membawa presisi lebih dari dua desimal, dan memotong kurs adalah sumber drift kumulatif diam-diam di akun bervolume tinggi.

Selesaikan residu kecil otomatis: pembayaran yang menyisakan saldo terbuka di bawah ambang yang bisa dikonfigurasi, misal 100 rupiah, sebaiknya otomatis di-write-off ke akun rounding alih-alih menghantui AR aging selamanya.

Tidak ada ilmu komputer canggih di sini. Ini cuma soal memutuskan kebijakan secara eksplisit, mengodekannya di satu tempat — service posting — dan menolak membiarkan tiap layar berhitung sendiri-sendiri.

## Intinya

Akuntansi multi-currency di ERP berdiri di empat kaki: penyimpanan dua mata uang dengan kurs yang dibekukan, pipeline kurs append-only yang disiplin, pemisahan ketat selisih realized dan unrealized, dan kebijakan rounding eksplisit yang ditegakkan di lapisan posting. Benahi itu semua dan sisanya — laporan, dashboard, aging — mengikuti dengan sendirinya, karena angka dasarnya bisa dipercaya.

Dan sebelum menulis kode apa pun, duduklah dengan akuntan klien selama satu jam dan sepakati kurs mana berlaku untuk dokumen mana. Percakapan itu lebih murah daripada refactor mana pun yang akan Anda lakukan.

## Sumber dan bacaan lanjutan

- IFRS Foundation — IAS 21: The Effects of Changes in Foreign Exchange Rates
- Dokumentasi Odoo 18 — Sistem Multi-Currency di Accounting
- Bank Indonesia — Data Kurs Referensi JISDOR

> **Key takeaway:** Menambahkan invoice USD ke ERP berbasis IDR memakan dua hari perubahan skema dan tiga bulan untuk segala hal di sekitarnya: kurs mana yang berlaku pada tanggal mana, bagaimana invoice yang dibayar pada kurs berbeda direkonsiliasi, dan bagaimana pembulatan Rupiah ditangani agar ledger tetap seimbang.

## Source links

- https://www.ifrs.org/issued-standards/list-of-standards/ias-21-the-effects-of-changes-in-foreign-exchange-rates/
- https://www.odoo.com/documentation/18.0/applications/finance/accounting/get_started/multi_currency.html
- https://www.bi.go.id/en/statistik/informasi-kurs/jisdor/Default.aspx

## FAQ

### Mengapa nilai mata uang fungsional hasil konversi harus dibekukan saat posting, bukan dihitung ulang saat dibaca?

Jika hanya menyimpan nilai asing lalu mengonversi saat dibaca, laporan akan berubah retroaktif setiap tabel kurs diperbarui sehingga dua cetakan ledger yang sama bisa tidak cocok. Aturan dalam artikel ini adalah menyimpan kurs yang dipakai dan nilai hasil konversi secara bersamaan, lalu tidak pernah menghitung ulang keduanya. Cara ini menjaga ledger tetap stabil dan dapat diaudit.

### Apa saja tiga jenis kurs dalam praktik ERP di Indonesia dan mengapa masing-masing penting?

Kurs transaksi (JISDOR, dipakai pada tanggal dokumen) membukukan invoice dan tagihan; kurs pajak mingguan dari Kementerian Keuangan wajib dipakai untuk perhitungan PPN dan boleh berbeda dari kurs akuntansi; serta kurs penutup yang merevaluasi saldo mata uang asing terbuka di akhir bulan untuk menghasilkan selisih kurs unrealized. Mendesain untuk ketiga field ini sejak awal menghindari kesalahan umum yang mengasumsikan semua dokumen memakai kurs yang sama.

### Apa perbedaan antara laba rugi selisih kurs realized dan unrealized?

Laba rugi realized terjadi saat pelunasan: invoice dibukukan dengan satu kurs dan pembayaran terkonversi dengan kurs lain, sehingga selisihnya adalah uang nyata yang langsung masuk laporan laba rugi. Laba rugi unrealized terjadi saat tutup periode: saldo mata uang asing yang masih terbuka direvaluasi dengan kurs penutup sebagai penyesuaian di atas kertas, lalu dibalik atau disesuaikan kembali di periode berikutnya tanpa ada kas yang berpindah.

### Mengapa artikel ini merekomendasikan pola reversing entry untuk revaluasi akhir bulan, bukan menyesuaikan saldo langsung di tempat?

Memposting jurnal revaluasi di hari terakhir periode dan pembalik otomatisnya di hari pertama periode berikutnya menjaga revaluasi benar-benar terpisah dari histori transaksional. Artinya closing yang kacau bisa diperbaiki cukup dengan membalik satu jurnal, bukan mengurai open item yang sudah teradjust satu per satu, sehingga prosesnya sepenuhnya dapat diulang dan diaudit.

### Aturan rounding IDR apa saja yang diterapkan artikel ini di lapisan posting?

Nilai fungsional dibulatkan half-up ke rupiah utuh di level line saat posting — bukan setelah dijumlahkan — karena membulatkan hasil penjumlahan tidak bisa direproduksi dari komponennya. Selisih debit-kredit akibat rounding per line otomatis diposting ke akun rounding khusus, kurs disimpan dengan enam desimal untuk menghindari drift kumulatif, dan saldo terbuka di bawah ambang yang bisa dikonfigurasi (artikel menyebut 100 rupiah) otomatis di-write-off ke akun rounding yang sama.

---

- HTML version: https://www.matthewswong.com/id/blog/erp-multi-currency-accounting/
- English: https://www.matthewswong.com/en/blog/erp-multi-currency-accounting/
- Site index for agents: https://www.matthewswong.com/llms.txt
- Sitemap: https://www.matthewswong.com/sitemap.xml
- API description (OpenAPI): https://www.matthewswong.com/openapi.json
