Ringkasan Utama
Multi-mata uang di ERP Indonesia berarti satu mata uang fungsional, yaitu IDR, dengan setiap transaksi valas disimpan dalam nominal aslinya dan nilai Rupiahnya, ditambah kurs pajak mingguan Kementerian Keuangan untuk PPN di faktur pajak. Revaluasi akhir periode kemudian menyatakan ulang saldo terbuka dengan kurs penutup, sesuai PSAK 221 (sebelumnya PSAK 10), sehingga buku besar tetap konsisten setelah kurs bergerak.
Bagi bisnis Indonesia yang berdagang lintas negara — mengimpor bahan baku, mengekspor produk, atau menagih klien dalam USD atau SGD — penanganan multi-mata uang di ERP bukan pilihan. Artinya juga harus hidup dengan dua set kurs resmi: kurs harian Bank Indonesia, yang dipakai modul ini untuk pembukuan, dan kurs pajak mingguan dari Kementerian Keuangan, yang wajib dipakai untuk PPN pada faktur pajak bermata uang asing. Di proyek-proyek yang pernah saya kerjakan, tim keuangan perusahaan dagang menghabiskan beberapa hari setiap bulan untuk mengonversi transaksi valuta asing ke Rupiah secara manual. Sebagai konsultan ERP lepas, saya membangun modul multi-mata uang untuk salah satu klien yang menangani seluruh siklusnya: input transaksi dalam mata uang apa pun, perhitungan ekuivalen IDR otomatis, revaluasi akhir periode, dan pelaporan konsolidasi dalam Rupiah.
Arsitektur Mata Uang
Sistem yang saya bangun memiliki satu mata uang fungsional (IDR — Rupiah Indonesia) sebagai basis. Semua laporan keuangan dalam IDR. Transaksi mata uang asing disimpan dengan jumlah mata uang asing asli dan ekuivalen IDR pada tanggal transaksi. Pendekatan dual-amount ini adalah standar dalam sistem akuntansi dan menyederhanakan pelaporan.
Penyimpanan Kurs dan Pembaruan
Saya mengelola tabel exchange_rates dengan kolom currency_pair (misalnya 'USD/IDR'), rate_date, buy_rate, sell_rate, dan mid_rate. Setiap hari kerja, job cron NestJS pukul 08.30 WIB mengambil Kurs Transaksi BI dari layanan web wsKursBI milik Bank Indonesia: kurs jual dan kurs beli yang diumumkan pukul 08.00 WIB, dengan titik tengah USD yang mengacu pada JISDOR hari kerja sebelumnya (kurs referensi USD/IDR BI, dipublikasikan pukul 15.15 WIB). Bisnis juga dapat memasukkan kurs kustom secara manual bila memakai kurs hasil negosiasi dengan bank — hal yang lazim untuk transaksi USD bernilai besar. Semua kurs historis disimpan (tidak pernah ditimpa) sehingga nilai IDR untuk transaksi apa pun di masa lalu dapat direkonstruksi dengan tepat.
Multi-Currency ERP Architecture (IDR as Functional Currency)
Exchange Rate Source
├── Bank Indonesia wsKursBI (working days, 08:30 WIB) ← Kurs Transaksi BI
│ └── exchange_rates table (historical, never overwritten)
└── Manual override (for negotiated bank rates)
Foreign Currency Transaction Flow:
┌─────────────────────────────────────────────────────────┐
│ AP Invoice: USD 10,000 │
│ │
│ ERP looks up USD/IDR rate: 17,880 (example rate) │
│ │
│ Journal Entry posted: │
│ DEBIT Expense Account IDR 178,800,000 │
│ CREDIT AP Payable — USD USD 10,000 / IDR 178,800K │
└──────────────────────────┬──────────────────────────────┘
│ Payment date: rate 17,950
▼
┌─────────────────────────────────────────────────────────┐
│ Payment: USD 10,000 × 17,950 = IDR 179,500,000 │
│ │
│ DEBIT AP Payable — USD IDR 178,800,000 │
│ DEBIT Forex Loss Account IDR 700,000 ← diff │
│ CREDIT Bank — USD IDR 179,500,000 │
└─────────────────────────────────────────────────────────┘
Month-end Revaluation:
Open FC balances × closing rate − original IDR = unrealized P/L
Posted as reversing journal (reverses on day 1 of next period)Dari pengalaman saya sebagai konsultan ERP lepas: jadikan kurs Bank Indonesia sebagai default, tetapi selalu izinkan pengguna menggantinya untuk transaksi tertentu. PSAK 221 (penomoran baru IAI untuk PSAK 10 sejak 1 Januari 2024) mengharuskan kurs spot pada tanggal transaksi, dan kurs yang benar-benar diterapkan bank sering sedikit berbeda dari kurs BI, jadi simpan keduanya di setiap transaksi. Pajak punya aturan sendiri: Pasal 21 PP 44/2022 mewajibkan PPN atas penjualan dalam mata uang asing dikonversi dengan kurs yang ditetapkan Menteri Keuangan yang berlaku saat Faktur Pajak seharusnya dibuat, yaitu kurs pajak mingguan, jadi simpan juga kurs tersebut di faktur.
Menangani Transaksi Mata Uang Asing
Ketika faktur AP datang dalam USD, layar entri menampilkan jumlah USD, dan sistem mencari kurs USD/IDR saat ini untuk menghitung ekuivalen IDR. Entri jurnal mencatat: debit Beban (ekuivalen IDR), kredit Utang Usaha — USD (jumlah USD asli + ekuivalen IDR). Ketika pembayaran dilakukan, jika kurs IDR/USD telah berubah, pembayaran menghasilkan entri laba atau rugi selisih kurs.
Revaluasi Akhir Periode
Pada akhir bulan, saldo moneter mata uang asing yang masih terbuka (faktur yang belum dibayar, rekening bank dalam valuta asing) harus dinilai ulang dengan kurs penutup. Job revaluasi membaca semua saldo valas terbuka, menghitung selisih antara ekuivalen IDR awal dan ekuivalen IDR saat ini pada kurs penutup, lalu memposting jurnal laba/rugi selisih kurs yang belum terealisasi. PSAK 221 dan IAS 21 mewajibkan pos moneter dijabarkan dengan kurs penutup dan selisihnya diakui di laba rugi; membalik jurnal tersebut di awal periode berikutnya (ditandai dengan reverse_on_date) adalah pilihan desain saya, agar pembayaran tetap mengukur laba/rugi terealisasinya terhadap kurs awal. Tanpa dukungan ERP, semua ini dikerjakan manual — saya pernah melihat perusahaan melewatkannya dan menghasilkan neraca yang tidak akurat secara material.
// NestJS: Bank Indonesia exchange rate fetcher
// Kurs Transaksi BI is announced at 08:00 WIB on working days
@Cron('30 8 * * 1-5', { timeZone: 'Asia/Jakarta' })
async fetchBankIndonesiaRates() {
const pairs = ['USD/IDR', 'EUR/IDR', 'SGD/IDR', 'CNY/IDR'];
const today = new Date().toISOString().split('T')[0];
const res = await fetch(
`https://www.bi.go.id/biwebservice/wskursbi.asmx/getSubKursLokal2?tgl=${today}`
);
// Parse BI XML: nil_subkurslokal is the quote unit (100 for JPY)
for (const { pair, unit, buy, sell } of parsedRates) {
await this.exchangeRateRepo.upsert({
currencyPair: pair,
rateDate: today,
buyRate: buy / unit,
sellRate: sell / unit,
midRate: (buy + sell) / 2 / unit,
source: 'bank_indonesia',
}, ['currencyPair', 'rateDate']);
}
this.logger.log(`Updated ${pairs.length} exchange rates from BI`);
}
// PostgreSQL: transaction schema with dual amounts
ALTER TABLE journal_lines ADD COLUMN foreign_currency VARCHAR(3);
ALTER TABLE journal_lines ADD COLUMN foreign_amount NUMERIC(15,2);
ALTER TABLE journal_lines ADD COLUMN exchange_rate NUMERIC(12,6);
-- IDR check: foreign_amount carries the line's sign (negative on credits)
ALTER TABLE journal_lines ADD CONSTRAINT chk_idr_consistency
CHECK (
foreign_amount IS NULL
OR ABS((debit - credit) - (foreign_amount * exchange_rate)) < 1
);Bagaimana Saya Mendekati Ini
Implementasi multi-mata uang menambahkan tiga kolom ke setiap transaksi keuangan: foreign_currency, foreign_amount, dan exchange_rate. Jumlah IDR selalu dihitung sebagai foreign_amount × exchange_rate, dan check constraint PostgreSQL memvalidasinya di setiap baris jurnal sehingga masalah pembulatan langsung tertangkap. Saya memakai 6 angka desimal untuk kurs: USD/IDR (JISDOR Rp17.899,00 pada 12 Oktober 2026) tidak membutuhkannya, tetapi Bank Indonesia mengutip JPY per 100 yen dan VND di 0,69, sehingga fetcher membagi kurs dengan satuan kutipannya dan menyimpan kurs per unit.
Jika klien Anda memiliki beberapa entitas yang saling bertransaksi dalam mata uang berbeda, eliminasi antar-perusahaan dalam laporan konsolidasi menjadi jauh lebih rumit. Kedua sisi transaksi antar-perusahaan bisa mencatat jumlah IDR yang berbeda (karena kurs pada tanggal faktur berbeda dari kurs pada tanggal pembayaran). Ini menimbulkan selisih rekonsiliasi antar-perusahaan yang harus dieliminasi secara eksplisit dalam konsolidasi. Saya menanganinya dengan modul eliminasi antar-perusahaan khusus dan mewajibkan semua transaksi antar-perusahaan memakai kurs rata-rata bulanan yang terstandarisasi, bukan kurs spot — pendekatan yang diterima IAS 21 hanya selama kurs tidak berfluktuasi signifikan.
Rekonsiliasi Bank Multi-Mata Uang
Rekonsiliasi bank lebih kompleks dengan beberapa mata uang: Anda merekonsiliasi laporan bank USD terhadap transaksi USD di ERP, kemudian juga merekonsiliasi ekuivalen IDR. Saya menyediakan layar rekonsiliasi per rekening bank per mata uang, menampilkan transaksi outstanding dalam mata uang asing diurutkan berdasarkan jumlah dan tanggal.
Pelaporan Manajemen dalam IDR
Semua laporan manajemen disajikan dalam IDR, dengan kolom sekunder opsional yang menampilkan jumlah mata uang asing asli untuk bisnis yang banyak bertransaksi dalam FC. L/R menampilkan total pendapatan dan biaya dalam IDR, dengan baris Forex untuk laba/rugi selisih kurs yang terealisasi dan belum terealisasi. Menampilkan komponen Forex secara terpisah membantu manajemen memahami kinerja operasional sebenarnya versus dampak mata uang.
Sumber & Bacaan Lebih Lanjut
- Bank Indonesia — JISDOR, Kurs Acuan Non-USD/IDR, dan Kurs Transaksi
- NetSuite — The Multi-Currency Accounting Guide
- Dynamic Netsoft — ERP Framework for Multi-Country Operations
- Bank Indonesia — Kurs Transaksi BI (JPY quoted per 100 units)
- Bank Indonesia — JISDOR history
- IAI — Perubahan Penomoran PSAK dan ISAK (PSAK 10 menjadi PSAK 221)
- Kementerian Keuangan — Kurs Pajak (weekly KMK rates)
- JDIH BPK — PP No. 44 Tahun 2022 (Article 21: PPN conversion rate)
- BDO — Accounting for foreign exchange transactions under IAS 21
