ERP Multi-Perusahaan: Transaksi Intercompany dan Eliminasi

Foto oleh daveynin on flickr
Transaksi intercompany adalah penjualan, pembelian, pinjaman, atau transfer antara dua entitas hukum yang berada dalam satu grup korporat yang sama, misalnya satu anak perusahaan menagih anak perusahaan lain untuk barang atau jasa. Masing-masing entitas mencatat sisi transaksinya sendiri di pembukuannya, tetapi karena kedua pihak berada dalam grup yang sama, transaksi tersebut harus dihilangkan saat menyusun laporan keuangan konsolidasi agar grup tidak terlihat menjual kepada dirinya sendiri.
Sebuah grup tidak boleh mengakui laba atau pendapatan dari berdagang dengan dirinya sendiri, sehingga standar akuntansi seperti IFRS 10 mewajibkan penghapusan penjualan intercompany, cost of goods sold, serta saldo AR dan AP sebelum menyusun laporan keuangan konsolidasi. Tanpa eliminasi, pendapatan dan balance sheet grup akan terlihat lebih besar dari yang sebenarnya akibat aktivitas internal yang tidak berdampak pada pihak luar.
Beri flag pada akun yang layak dieliminasi, hubungkan kedua sisi setiap posting intercompany melalui id pasangan bersama pada saat dibuat, dan jalankan job di akhir periode yang menyusuri pasangan-pasangan yang tertaut itu lalu memposting jurnal pembalik di entitas konsolidasi terpisah. Menjaga job tersebut idempoten dan bisa dijalankan ulang memungkinkan Anda mengoreksi periode sebelumnya tanpa menggandakan entri eliminasi.
Bisa, dan umumnya sebaiknya berbagi satu master record agar lawan transaksi intercompany dapat diresolusi secara konsisten di semua entitas. Tiap perusahaan tetap mempertahankan termin kredit, price list, dan buku besar open-item sendiri terhadap pelanggan atau vendor bersama tersebut, sehingga identitas bersama itu tidak menghilangkan fleksibilitas per entitas.
Mesin konsolidasi memerlukan persentase kepemilikan pada relasi perusahaan agar dapat membagi ekuitas dan laba bersih anak perusahaan yang dimiliki sebagian itu antara grup dan minority interest, yang kadang disebut juga non-controlling interest. Pembagian ini dihitung setelah eliminasi dan translasi mata uang, dan dilaporkan sebagai baris terpisah pada ekuitas dan laporan laba rugi konsolidasi.

Foto oleh daveynin on flickr
Ringkasan Utama
Panduan ini menunjukkan cara menambahkan dukungan multi-perusahaan ke ERP custom: bagikan master data seperti chart of accounts dan item master antar entitas, batasi pengaturan pajak dan mata uang per perusahaan, hubungkan invoice intercompany dengan id pasangan, lalu buat jurnal eliminasi otomatis agar laporan konsolidasi bersaldo nol tanpa rekonsiliasi manual.
Sebagian besar sistem ERP dirancang untuk satu perusahaan saja. Begitu bisnis mendirikan entitas hukum kedua, entah unit trading, anak perusahaan manufaktur, atau cabang regional, asumsi yang tertanam dalam model data satu perusahaan mulai bermasalah: data pelanggan yang sama terduplikasi di berbagai database, penjualan antar perusahaan terlihat seperti pendapatan riil, dan tim finance akhirnya merekonsiliasi entitas secara manual lewat spreadsheet setiap akhir bulan.
Artikel ini membahas cara merancang dukungan multi-perusahaan pada ERP custom: master data mana yang dibagi bersama versus tetap lokal per entitas, cara memodelkan penagihan intercompany agar kedua sisi transaksi tetap terhubung, cara menghasilkan jurnal eliminasi secara otomatis alih-alih manual, dan apa yang berubah saat semuanya digabung menjadi satu laporan konsolidasi.
Sebelum menulis satu pun aturan posting intercompany, tentukan data mana yang berada di atas level perusahaan dan mana yang tetap terbatas pada satu entitas. Jika keliru, pelanggan yang sama bisa terduplikasi lima kali dengan lima kode berbeda, atau setup pajak lokal satu entitas malah bocor ke pembukuan entitas lain.
Solusi praktisnya adalah menambahkan dimensi perusahaan pada setiap tabel transaksional, ditambah beberapa tabel master yang sengaja tidak diberi dimensi itu. Logika pelaporan dan posting kemudian memfilter berdasarkan perusahaan; lookup master data tidak.
Setelah master data bersama disepakati, pertanyaan skema berikutnya adalah bagaimana satu perusahaan membatasi lingkup segalanya. Pendekatan paling bersih adalah entitas Company sebagai first-class citizen dengan mata uang basis, kalender fiskal, dan subset chart of accounts aktif sendiri, yang dirujuk lewat kolom company id di setiap tabel ledger, invoice, dan jurnal.
Di sinilah dukungan multi-perusahaan terbayar secara operasional: mengonboarding anak perusahaan baru cukup dengan menambah satu baris Company dan beberapa record pasangan intercompany, bukan migrasi skema.
Jika Anda menambahkan dukungan multi-perusahaan ke skema satu perusahaan yang sudah berjalan, tambahkan kolom company id dengan nilai default sama dengan id perusahaan tunggal yang sudah ada terlebih dahulu, lakukan backfill, baru kemudian jadikan wajib. Cara ini membuat migrasi tetap bisa dibalik jika ada yang gagal di tengah jalan.
Penjualan intercompany harus menghasilkan dua transaksi independen yang seimbang, invoice AR di entitas penjual dan bill AP di entitas pembeli, yang tetap terhubung agar job eliminasi bisa menemukan kedua sisinya nanti. Perlakukan ini sebagai satu operasi bisnis dengan dua efek ledger, bukan dua posting terpisah yang kebetulan saling mereferensi.
Kode di bawah menunjukkan bentuk operasi tersebut: satu pemanggilan fungsi yang membuat kedua sisi secara atomik, sehingga kegagalan di tengah proses tidak pernah menyisakan satu perusahaan dengan invoice terposting sementara yang lain tidak mendapat apa-apa.
// Posting an intercompany sale: one call creates both legs
async function postIntercompanySale(input: {
sellingCompanyId: string;
buyingCompanyId: string;
itemId: string;
qty: number;
unitPrice: number; // in sellingCompany's currency
postingDate: string;
}) {
const icPair = await getIntercompanyPair(
input.sellingCompanyId,
input.buyingCompanyId
);
// 1. AR invoice on the selling entity
const arInvoice = await createInvoice({
companyId: input.sellingCompanyId,
customerId: icPair.counterpartyCustomerId, // maps to buying company
lines: [{ itemId: input.itemId, qty: input.qty, price: input.unitPrice }],
intercompanyPairId: icPair.id,
postingDate: input.postingDate,
});
// 2. AP bill on the buying entity, converted to its base currency
const fxRate = await getRate(icPair.sellCurrency, icPair.buyCurrency, input.postingDate);
const apBill = await createBill({
companyId: input.buyingCompanyId,
vendorId: icPair.counterpartySupplierId, // maps to selling company
lines: [{
itemId: input.itemId,
qty: input.qty,
price: round(input.unitPrice * fxRate, 2),
}],
intercompanyPairId: icPair.id,
postingDate: input.postingDate,
});
// 3. Link both legs so the elimination job can find the pair later
await linkIntercompanyDocuments(arInvoice.id, apBill.id);
return { arInvoice, apBill };
}Bungkus seluruh fungsi ini dalam satu transaksi database. Posting intercompany yang setengah jalan adalah salah satu masalah rekonsiliasi paling menyita waktu untuk diurai kembali, karena begitu ada yang menyadarinya, periode di salah satu sisi mungkin sudah ditutup.
Pada saat tutup periode, setiap pasangan AR dan AP intercompany, serta setiap pasangan pendapatan dan cost of goods sold intercompany, perlu dibalik untuk tampilan konsolidasi, sambil tetap tidak tersentuh di pembukuan masing-masing entitas. Job eliminasi menyusuri tautan pasangan intercompany yang dibuat saat posting, mengelompokkannya berdasarkan grup konsolidasi, dan menghasilkan satu jurnal eliminasi per pasangan.
| Baris eliminasi | Akun | Debit (IDR) | Kredit (IDR) |
|---|---|---|---|
| Eliminasi konsolidasi | Pendapatan penjualan intercompany | 100,000,000 | — |
| Eliminasi konsolidasi | Cost of goods sold (intercompany) | — | 100,000,000 |
| Eliminasi konsolidasi | Utang usaha intercompany | — | 100,000,000 |
| Eliminasi konsolidasi | Piutang usaha intercompany | 100,000,000 | — |
Dua baris eliminasi membalik pasangan penjualan versus biaya yang tercatat di akun pendapatan dan cost of goods sold; dua lainnya membalik pasangan AR dan AP yang tercatat di balance sheet. Semua ini tidak pernah menyentuh pembukuan asli Perusahaan A atau Perusahaan B, jurnal eliminasi hanya diposting di entitas konsolidasi, sehingga jejak audit di level entitas tetap sama seperti aslinya.
Eliminasi hanya berfungsi jika nilai debit dan kredit cocok persis, termasuk setelah konversi mata uang. Selisih satu hari antara waktu entitas penjual posting dan waktu entitas pembeli posting, atau kurs yang sudah kedaluwarsa di salah satu sisi, akan menghasilkan eliminasi yang tidak bersaldo nol, rekonsiliasi tanggal posting dan kurs sebelum menjalankan job, bukan sesudahnya.
Eliminasi menangani noise intercompany, tetapi menggabungkan beberapa entitas menjadi satu laporan konsolidasi memunculkan dua pertanyaan lagi: dalam mata uang apa Anda melaporkan, dan apa yang terjadi bila induk perusahaan memiliki kurang dari seratus persen saham anak perusahaan.
Di sinilah dimensi perusahaan dari bagian rancangan sebelumnya kembali terbayar: laporan konsolidasi sebenarnya hanyalah tampilan yang difilter, ditranslasi, dan dinetkan dari tabel transaksional yang sama yang sudah dibaca oleh laporan-laporan lain.
Tim yang membangun dukungan multi-perusahaan dari awal cenderung menemui beberapa masalah yang sama berulang kali. Antisipasi ini sebelum muncul di production.
Semua ini tidak memerlukan arsitektur yang eksotis. Dimensi perusahaan, tabel pasangan intercompany, flag pada akun yang layak dieliminasi, dan job eliminasi yang bisa dijalankan ulang sudah mencakup sebagian besar kasus grup multi-entitas di dunia nyata, termasuk kasus mata uang dan kepemilikan sebagian yang akhirnya dihadapi kebanyakan ERP custom.