Skema buku besar penagihan yang bisa direkonsiliasi: invoice dan pembayaran
Pelajari cara merancang skema buku besar penagihan dengan invoice, pembayaran, kredit, dan penyesuaian terpisah agar finance mudah merekonsiliasi dan diaudit.

Mengapa data penagihan berhenti rekonsiliasi
Bagi finance, “rekonsiliasi” adalah janji sederhana: total dalam laporan cocok dengan catatan sumber, dan setiap angka dapat ditelusuri. Jika bulan menunjukkan $12,430 terkumpul, Anda harus bisa menunjuk pembayaran tepatnya (dan refund bila ada), melihat invoice yang mereka terapkan, dan menjelaskan setiap perbedaan dengan catatan bertanggal.
Data penagihan biasanya berhenti rekonsiliasi ketika database menyimpan hasil alih-alih fakta. Kolom seperti paid_amount, balance, atau amount_due diperbarui seiring waktu oleh logika aplikasi. Satu bug, satu retry, atau satu “perbaikan” manual bisa dengan diam-diam mengubah sejarah. Minggu kemudian, tabel invoice mengatakan sebuah invoice "dibayar", tetapi baris pembayaran tidak cocok jumlahnya, atau ada refund tanpa kredit yang sesuai.
Penyebab umum lain adalah mencampur berbagai jenis dokumen. Invoice bukanlah pembayaran. Credit memo bukan refund. Penyesuaian bukan diskon. Ketika semuanya dipak dalam satu baris “transactions” dengan banyak field opsional, pelaporan berubah jadi tebak-tebakan dan audit jadi argumen.
Ketidaksesuaian mendasar itu sederhana: aplikasi sering peduli dengan keadaan saat ini ("apakah akses aktif?"), sementara finance peduli dengan jejak ("apa yang terjadi, kapan, dan kenapa?"). Skema buku besar penagihan harus mendukung keduanya, tapi keterlacakan harus menang.
Rancang untuk hasil ini:
- Total jelas per pelanggan, per invoice, dan per periode akuntansi
- Setiap perubahan dicatat sebagai baris baru (tidak ditimpa)
- Rantai lengkap dari invoice ke pembayaran, kredit, refund, dan penyesuaian
- Kemampuan untuk menghitung ulang total dari entri mentah dan mendapatkan jawaban yang sama
Contoh: jika seorang pelanggan membayar $100, lalu mendapat kredit $20, laporan Anda harus menunjukkan $100 terkumpul, $20 dikreditkan, dan $80 bersih, tanpa mengubah jumlah invoice asli.
Pisahkan invoice, pembayaran, kredit, dan penyesuaian
Jika Anda menginginkan skema buku besar penagihan yang rekonsiliasi, perlakukan tiap jenis dokumen sebagai jenis kejadian yang berbeda. Mencampurnya ke dalam satu tabel “transactions” terlihat rapi, tetapi mengaburkan makna.
Sebuah invoice adalah klaim: “pelanggan berutang kepada kita.” Simpan sebagai dokumen dengan header (pelanggan, nomor invoice, tanggal terbit, tanggal jatuh tempo, mata uang, total) dan baris terpisah (apa yang dijual, kuantitas, harga satuan, kategori pajak). Tidak apa-apa menyimpan total header untuk kecepatan, tetapi Anda harus selalu bisa menjelaskannya dari baris-barisnya.
Sebuah pembayaran adalah pergerakan uang: “kas berpindah dari pelanggan ke kita.” Dalam alur kartu, sering ada otorisasi (bank menyetujui) dan capture (uang benar-benar diambil). Banyak sistem menyimpan otorisasi sebagai catatan operasional dan hanya memasukkan pembayaran yang ditangkap ke ledger, supaya Anda tidak melebihkan pelaporan kas.
Sebuah credit memo mengurangi apa yang pelanggan hutangkan tanpa harus mengembalikan uang. Sebuah refund adalah kas keluar. Mereka sering terjadi bersama, tapi bukan hal yang sama.
- Invoice: menambah piutang dan pendapatan (atau pendapatan ditangguhkan)
- Pembayaran: menambah kas dan mengurangi piutang
- Credit memo: mengurangi piutang
- Refund: mengurangi kas
Sebuah penyesuaian adalah koreksi yang dibuat tim Anda ketika kenyataan tidak cocok dengan catatan. Penyesuaian perlu konteks agar finance bisa mempercayainya. Simpan siapa yang membuatnya, kapan diposting, kode alasan, dan catatan singkat. Contoh: “write off 0.03 karena pembulatan,” atau “migrasi saldo legacy.”
Aturan praktis: tanyakan, “Apakah ini akan ada jika tidak ada yang melakukan kesalahan?” Invoice, pembayaran, credit memo, dan refund tetap ada. Penyesuaian harus jarang, diberi label jelas, dan mudah direview.
Pilih model ledger yang bisa diaudit oleh finance
Skema buku besar penagihan yang rekonsiliasi dimulai dari satu ide: dokumen menjelaskan apa yang terjadi, dan posting ledger membuktikan totalnya. Invoice, pembayaran, atau credit memo adalah dokumen. Ledger adalah sekumpulan entri yang menambahkan, titik.
Dokumen vs posting (simpan keduanya)
Simpan dokumen (header dan baris invoice, kuitansi pembayaran, credit memo) karena orang perlu membacanya. Tapi jangan mengandalkan total dokumen saja sebagai sumber kebenaran untuk rekonsiliasi.
Sebaliknya, posting setiap dokumen ke tabel ledger sebagai satu atau beberapa entri yang tidak dapat diubah. Maka finance bisa menjumlahkan entri berdasarkan akun, pelanggan, mata uang, dan tanggal posting dan mendapatkan jawaban yang sama setiap kali.
Model ramah-audit sederhana mengikuti beberapa aturan:
- Entri tidak dapat diubah: jangan pernah mengedit jumlah yang sudah diposting; perubahan adalah entri baru.
- Peristiwa posting jelas: setiap dokumen membuat batch posting dengan referensi unik.
- Logika seimbang: entri saling menyeimbangkan (sering debit sama kredit di level perusahaan).
- Tanggal terpisah: simpan tanggal dokumen (yang dilihat pelanggan) dan tanggal posting (yang masuk laporan).
- Referensi stabil: simpan referensi eksternal (nomor invoice, ID processor pembayaran) bersama ID internal.
Kunci alami vs ID surrogate
Gunakan ID surrogate untuk join dan performa, tapi juga simpan kunci alami yang stabil yang bertahan dari migrasi dan re-import. Finance akan meminta “Invoice INV-10483” lama setelah ID database berubah. Perlakukan nomor invoice dan ID provider (mis. charge ID) sebagai field kelas-satu.
Pembalikan tanpa menghapus sejarah
Jika sesuatu harus dibatalkan, jangan hapus atau timpa. Posting pembalikan: entri baru yang mencerminkan jumlah asli dengan tanda berlawanan, yang ditautkan kembali ke posting asli.
Contoh: pembayaran $100 yang diterapkan ke invoice yang salah menjadi dua langkah: balikkan posting yang salah, lalu posting aplikasi baru ke invoice yang benar.
Blue print skema langkah-demi-langkah (tabel dan kunci)
Skema buku besar penagihan lebih mudah rekonsiliasi ketika tiap jenis dokumen punya tabel sendiri dan Anda menghubungkannya dengan record alokasi eksplisit (daripada menebak hubungan nanti).
Mulai dengan set kecil tabel inti, masing-masing dengan primary key jelas (UUID atau bigserial) dan foreign key yang wajib:
- customers:
customer_id(PK), plus identifier stabil sepertiexternal_ref(unik) - invoices:
invoice_id(PK),customer_id(FK),invoice_number(unik),issue_date,due_date,currency - invoice_lines:
invoice_line_id(PK),invoice_id(FK),line_type,description,qty,unit_price,tax_code,amount - payments:
payment_id(PK),customer_id(FK),payment_date,method,currency,gross_amount - credits:
credit_id(PK),customer_id(FK),credit_number(unik),credit_date,currency,amount
Lalu tambahkan tabel yang membuat total dapat diaudit: alokasi. Satu pembayaran atau kredit bisa menutup beberapa invoice, dan satu invoice bisa dibayar oleh beberapa pembayaran.
Gunakan tabel join dengan kunci sendiri (bukan hanya composite key):
- payment_allocations:
payment_allocation_id(PK),payment_id(FK),invoice_id(FK),allocated_amount,posted_at - credit_allocations:
credit_allocation_id(PK),credit_id(FK),invoice_id(FK),allocated_amount,posted_at
Terakhir, simpan penyesuaian terpisah sehingga finance bisa melihat apa yang berubah dan mengapa. Tabel adjustments dapat mereferensikan record target dengan invoice_id (nullable) dan menyimpan jumlah delta, tanpa menulis ulang sejarah.
Tambahkan field audit di mana pun Anda memposting uang:
created_at,created_byreason_code(write-off, rounding, goodwill, chargeback)source_system(manual, import, Stripe, support tool)
Kredit, refund, dan write-off tanpa merusak total
Kebanyakan masalah rekonsiliasi dimulai ketika kredit dan refund dicatat sebagai “pembayaran negatif,” atau ketika write-off dicampur ke baris invoice. Skema buku besar yang bersih menjaga tiap jenis dokumen dalam record terpisah, dan tempat mereka berinteraksi hanya lewat alokasi eksplisit.
Sebuah kredit harus menunjukkan mengapa Anda mengurangi hutang pelanggan. Jika itu berlaku untuk satu invoice, catat satu credit memo dan alokasikan ke invoice tersebut. Jika berlaku untuk beberapa invoice, alokasikan credit memo yang sama ke banyak invoice. Kredit tetap satu dokumen dengan banyak alokasi.
Refund adalah kejadian mirip pembayaran, bukan pembayaran negatif. Refund adalah kas keluar, jadi perlakukan sebagai record sendiri (seringkali terkait ke pembayaran asli untuk referensi), lalu alokasikan seperti pembayaran. Ini menjaga jejak audit jelas ketika mutasi bank menampilkan pembayaran masuk dan refund keluar.
Pembayaran parsial dan kredit parsial bekerja sama: simpan total pembayaran atau kredit di barisnya sendiri, dan gunakan baris alokasi untuk berapa banyak yang diterapkan ke tiap invoice.
Aturan posting yang mencegah penghitungan ganda
Aturan ini menghilangkan sebagian besar “perbedaan misterius”:
- Jangan pernah menyimpan pembayaran negatif. Gunakan record refund.
- Jangan pernah mengurangi total invoice setelah diposting. Gunakan credit memo atau penyesuaian.
- Post dokumen sekali (dengan timestamp
posted_at) dan jangan edit jumlah setelah diposting. - Satu-satunya hal yang mengubah saldo invoice adalah jumlah alokasi yang diposting.
- Write-off adalah penyesuaian dengan kode alasan, dialokasikan ke invoice seperti kredit.
Pajak, biaya, mata uang, dan pilihan pembulatan
Sebagian besar masalah rekonsiliasi bermula dari total yang tidak bisa Anda buat ulang. Aturan paling aman sederhana: simpan baris mentah yang membuat tagihan, dan juga simpan total yang Anda tunjukkan ke pelanggan.
Pajak dan biaya: simpan di level baris
Simpan jumlah pajak dan biaya per item baris, bukan hanya sebagai ringkasan tingkat invoice. Produk berbeda bisa punya tarif pajak berbeda, biaya mungkin kena pajak atau tidak, dan pengecualian sering berlaku hanya ke sebagian invoice. Jika Anda hanya menyimpan tax_total, suatu saat Anda akan menemui kasus yang tidak bisa dijelaskan.
Simpan:
- Baris mentah (apa yang dijual, qty, harga satuan, diskon)
- Total terhitung tiap baris (line_subtotal, line_tax, line_total)
- Total ringkasan invoice (subtotal, tax_total, total)
- Tarif pajak dan tipe pajak yang digunakan
- Biaya sebagai baris tersendiri (mis. “Payment processing fee”)
Ini memungkinkan finance membangun kembali total dan memastikan pajak dihitung sama setiap kali.
Multi-mata uang: simpan apa yang terjadi dan bagaimana Anda melaporkannya
Jika Anda mendukung banyak mata uang, catat nilai mata uang transaksi dan juga nilai pelaporan. Minimum praktis: currency_code pada setiap dokumen moneter, fx_rate yang digunakan saat posting, dan jumlah pelaporan terpisah (mis. amount_reporting) jika pembukuan Anda ditutup dalam satu mata uang.
Contoh: pelanggan ditagih 100.00 EUR plus 20.00 EUR VAT. Simpan baris dan total dalam EUR itu, plus fx_rate yang dipakai saat posting invoice, dan total yang dikonversi untuk pelaporan.
Pembulatan perlu perlakuan sendiri. Pilih satu aturan pembulatan (per baris atau per invoice) dan patuhi. Saat pembulatan menciptakan selisih, catat secara eksplisit sebagai baris penyesuaian pembulatan (atau entri penyesuaian kecil) daripada diam-diam mengubah total.
Status, tanggal posting, dan apa yang tidak boleh disimpan
Rekonsiliasi menjadi berantakan ketika “status” digunakan sebagai jalan pintas untuk kebenaran akuntansi. Perlakukan status sebagai label alur kerja, dan jadikan entri ledger yang diposting sebagai sumber kebenaran.
Buat status ketat dan membosankan. Masing-masing harus menjawab: apakah dokumen ini bisa memengaruhi total?
- Draft: internal saja, belum diposting, tidak boleh masuk laporan
- Issued: final dan dikirim, siap diposting (atau sudah diposting)
- Void: dibatalkan; jika pernah diposting, harus dibalik
- Paid: lunas sepenuhnya oleh pembayaran dan kredit yang diposting
- Refunded: uang telah dikembalikan lewat refund yang diposting
Tanggal lebih penting dari yang kebanyakan tim duga. Finance akan bertanya, “Bulan mana ini seharusnya masuk?” dan jawaban Anda tidak boleh bergantung pada log aktivitas UI.
issued_at: ketika invoice menjadi finalposted_at: ketika muncul di laporan akuntansisettled_at: ketika dana clear atau pembayaran dikonfirmasivoided_at/refunded_at: ketika pembalikan menjadi efektif
Apa yang tidak boleh disimpan sebagai kebenaran: angka turunan yang tidak bisa Anda bangun ulang dari ledger. Field seperti balance_due, is_overdue, dan customer_lifetime_value boleh ada sebagai view cache hanya jika Anda selalu bisa menghitung ulang dari invoices, payments, credits, allocations, dan adjustments.
Contoh kecil: retry pembayaran mengenai gateway dua kali. Tanpa idempotency_key, Anda menyimpan dua pembayaran, menandai invoice "paid", lalu finance melihat ekstra $100 di kas. Simpan idempotency_key unik per percobaan charge eksternal dan tolak duplikat di level database.
Laporan yang diharapkan finance sejak hari pertama
Skema buku besar penagihan membuktikan dirinya ketika finance bisa menjawab pertanyaan dasar dengan cepat dan mendapatkan total yang sama setiap kali.
Sebagian besar tim mulai dengan:
- Aging piutang: jumlah yang masih terbuka per pelanggan dan bucket umur (0-30, 31-60, dll.)
- Kas diterima: uang yang masuk per hari, minggu, dan bulan, berdasarkan tanggal posting pembayaran
- Pendapatan vs kas: invoice yang diposting vs pembayaran yang diposting
- Jejak audit untuk ekspor: jalur drill-back dari baris ekspor GL ke dokumen dan baris alokasi yang membuatnya
Aging adalah tempat alokasi paling penting. Aging bukan “total invoice minus total pembayaran.” Itu adalah “apa yang tersisa terbuka pada tiap invoice pada suatu tanggal.” Itu memerlukan penyimpanan bagaimana setiap pembayaran, kredit, atau penyesuaian diterapkan ke invoice spesifik, dan kapan alokasi itu diposting.
Kas diterima harus digerakkan oleh tabel payments, bukan status invoice. Pelanggan bisa membayar lebih awal, terlambat, atau parsial.
Pendapatan vs kas adalah alasan invoice dan pembayaran harus tetap terpisah. Contoh: Anda keluarkan invoice $1,000 pada 30 Maret, terima $600 pada 5 April, dan keluarkan kredit $100 pada 20 April. Pendapatan masuk ke Maret (posting invoice), kas masuk ke April (posting pembayaran), dan kredit mengurangi piutang saat diposting. Alokasi yang mengikat semuanya.
Contoh skenario: satu pelanggan, empat jenis dokumen
Satu pelanggan, satu bulan, empat jenis dokumen. Setiap dokumen disimpan sekali, dan uang bergerak melalui tabel alokasi (kadang disebut “applications”). Itu membuat saldo akhir mudah dihitung ulang dan diaudit.
Asumsikan pelanggan C-1001 (Acme Co.).
Record yang Anda buat
invoices
| invoice_id | customer_id | invoice_date | posted_at | currency | total |
|---|---|---|---|---|---|
| INV-10 | C-1001 | 2026-01-05 | 2026-01-05 | USD | 120.00 |
payments
| payment_id | customer_id | received_at | posted_at | method | amount |
|---|---|---|---|---|---|
| PAY-77 | C-1001 | 2026-01-10 | 2026-01-10 | card | 70.00 |
credits (credit memo, goodwill credit, dll.)
| credit_id | customer_id | credit_date | posted_at | reason | amount |
|---|---|---|---|---|---|
| CR-5 | C-1001 | 2026-01-12 | 2026-01-12 | service issue | 20.00 |
adjustments (koreksi setelah fakta, bukan penjualan baru)
| adjustment_id | customer_id | adjustment_date | posted_at | note | amount |
|---|---|---|---|---|---|
| ADJ-3 | C-1001 | 2026-01-15 | 2026-01-15 | underbilled fee | 5.00 |
allocations (inilah yang benar-benar merekonsiliasi saldo)
| allocation_id | doc_type_from | doc_id_from | doc_type_to | doc_id_to | posted_at | amount |
|---|---|---|---|---|---|---|
| AL-900 | payment | PAY-77 | invoice | INV-10 | 2026-01-10 | 70.00 |
| AL-901 | credit | CR-5 | invoice | INV-10 | 2026-01-12 | 20.00 |
Cara saldo invoice dihitung
Untuk INV-10, auditor dapat menghitung ulang saldo terbuka dari baris sumber:
open_balance = invoice.total + sum(adjustments) - sum(allocations)
Jadi: 120.00 + 5.00 - (70.00 + 20.00) = 35.00 jatuh tempo.
Untuk menelusuri “35.00” kembali:
- Mulai dari total invoice (INV-10)
- Tambahkan penyesuaian yang diposting yang terkait invoice yang sama (ADJ-3)
- Kurangi setiap alokasi yang diposting yang diterapkan ke invoice (AL-900, AL-901)
- Pastikan setiap alokasi menunjuk ke dokumen sumber yang nyata (PAY-77, CR-5)
- Verifikasi tanggal dan
posted_atuntuk menjelaskan timeline
Kesalahan umum yang merusak rekonsiliasi
Sebagian besar masalah rekonsiliasi bukanlah “bug matematika.” Mereka adalah aturan yang hilang, sehingga kejadian nyata yang sama dicatat dua cara berbeda tergantung siapa yang menyentuhnya.
Perangkap umum adalah menggunakan baris negatif sebagai jalan pintas. Baris invoice negatif, pembayaran negatif, dan baris pajak negatif bisa berarti hal berbeda. Jika Anda mengizinkan negatif, definisikan satu kebijakan pembalikan yang ketat (mis. hanya gunakan baris pembalikan yang merujuk baris asli, dan jangan mencampur semantik pembalikan dengan diskon).
Penyebab sering lain adalah mengubah sejarah. Jika sebuah invoice sudah diterbitkan, jangan edit nanti untuk menyesuaikan harga baru atau alamat yang dikoreksi. Simpan dokumen asli dan posting penyesuaian atau credit document yang menjelaskan perubahan.
Polanya yang biasanya merusak total:
- Menggunakan baris negatif tanpa aturan pembalikan yang ketat dan referensi ke baris asli
- Mengedit invoice lama setelah diterbitkan alih-alih posting penyesuaian atau nota kredit
- Mencampur ID transaksi gateway dengan ID internal tanpa tabel pemetaan dan sumber kebenaran yang jelas
- Membiarkan kode aplikasi menghitung total sementara baris pendukung (tax, fee, rounding, allocations) hilang
- Tidak memisahkan “pergerakan uang” (cash movement) dari “alokasi uang” (invoice mana yang dibayar)
Poin terakhir ini menyebabkan kebingungan paling besar. Contoh: pelanggan membayar $100, lalu Anda menerapkan $60 ke Invoice A dan $40 ke Invoice B. Pembayaran adalah satu pergerakan kas, tetapi itu membuat dua alokasi. Jika Anda hanya menyimpan “payment = invoice,” Anda tidak bisa mendukung pembayaran parsial, kelebihan bayar, atau realokasi.
Checklist dan langkah berikutnya
Sebelum menambah fitur, pastikan dasar-dasarnya kuat. Skema buku besar penagihan rekonsiliasi ketika setiap total dapat ditelusuri ke baris spesifik, dan setiap perubahan memiliki jejak audit.
Pemeriksaan rekonsiliasi cepat
Jalankan pemeriksaan ini pada sampel kecil (satu pelanggan, satu bulan) lalu pada dataset penuh:
- Setiap angka yang diposting di laporan menelusuri ke baris sumber (invoice line, payment, credit memo, adjustment) dengan tanggal posting dan mata uang.
- Alokasi tidak pernah melebihi dokumen yang mereka terapkan (total alokasi pembayaran ≤ total pembayaran; sama untuk kredit).
- Tidak ada yang dihapus. Entri yang salah dibalik dengan alasan, lalu dikoreksi dengan baris baru yang diposting.
- Saldo terbuka dapat diturunkan, bukan disimpan (saldo terbuka invoice = total invoice minus alokasi dan kredit yang diposting).
- Total dokumen cocok dengan barisnya (header invoice sama dengan jumlah baris, pajak, dan biaya setelah aturan pembulatan Anda).
Langkah berikutnya untuk mengirim sesuatu yang dapat digunakan
Setelah skema Anda solid, bangun alur operasional di sekelilingnya:
- Layar admin untuk membuat, memposting, dan membalik invoice, pembayaran, kredit, dan penyesuaian dengan catatan wajib
- Tampilan rekonsiliasi yang menunjukkan dokumen dan alokasi berdampingan, termasuk siapa yang memposting apa dan kapan
- Ekspor yang diharapkan finance (berdasarkan tanggal posting, per pelanggan, atau pemetaan GL jika ada)
- Alur penutupan periode: kunci tanggal posting untuk bulan yang ditutup, dan minta entri pembalikan untuk koreksi terlambat
- Skenario uji (refund, pembayaran parsial, write-off) yang harus cocok dengan total yang diharapkan
Jika Anda menginginkan jalur lebih cepat ke portal finance internal yang bekerja, AppMaster (appmaster.io) dapat membantu Anda memodelkan skema PostgreSQL, menghasilkan API, dan membangun layar admin dari sumber yang sama, sehingga aturan posting dan alokasi tetap konsisten seiring aplikasi berkembang.
FAQ
Rekonsiliasi berarti setiap total yang dilaporkan bisa dibangun kembali dari catatan sumber dan ditelusuri ke entri bertanggal. Jika laporan Anda mengatakan terkumpul $12,430, Anda harus bisa menunjuk pembayaran dan refund yang diposting yang jumlahnya sama, tanpa bergantung pada field yang ditimpa.
Penyebab paling umum adalah menyimpan “hasil” yang berubah seperti paid_amount atau balance_due seakan-akan itu fakta. Jika field itu diperbarui oleh retry, bug, atau edit manual, jejak historis hilang dan total tidak lagi mencerminkan apa yang sebenarnya terjadi.
Karena setiap jenis dokumen mewakili kejadian dunia nyata dengan makna akuntansi yang berbeda. Saat semuanya dimasukkan ke satu baris “transaction” dengan field opsional, pelaporan jadi tebak-tebakan dan audit jadi perdebatan tentang maksud baris tersebut.
Credit memo mengurangi apa yang pelanggan hutangkan, tetapi tidak selalu mengeluarkan uang. Refund adalah uang yang keluar dari Anda, biasanya terkait pembayaran sebelumnya. Menganggap keduanya sama (atau sebagai pembayaran negatif) mempersulit pelaporan kas dan pencocokan bank.
Lakukan pembalikan daripada mengedit atau menghapus. Buat entri baru yang mencerminkan jumlah asli dengan tanda berlawanan, hubungkan ke posting asli, lalu posting alokasi yang benar sehingga jejak audit menunjukkan apa yang berubah dan mengapa.
Gunakan record alokasi eksplisit (applications) yang menghubungkan pembayaran atau kredit ke satu atau beberapa invoice dengan allocated_amount dan posted_at. Saldo terbuka invoice harus dapat dihitung dari total invoice ditambah penyesuaian dikurangi alokasi yang diposting.
Simpan kedua tanggal: tanggal dokumen dan tanggal posting. Tanggal dokumen adalah yang dilihat pelanggan, sedangkan tanggal posting menentukan kapan muncul di laporan finance dan penutupan periode, sehingga total akhir bulan tidak berubah hanya karena seseorang mengedit record kemudian.
Simpan detail pajak dan biaya di tingkat baris, ditambah total yang tepat yang Anda tampilkan ke pelanggan. Jika hanya menyimpan tax_total di tingkat invoice, Anda akan menemui kasus yang tidak bisa dijelaskan atau direproduksi, terutama dengan tarif pajak beragam dan pengecualian.
Simpan jumlah dalam mata uang transaksi dan juga simpan jumlah untuk pelaporan dengan menggunakan kurs (fx_rate) yang dipakai saat posting. Pilih satu aturan pembulatan (per baris atau per invoice) dan catat perbedaan pembulatan secara eksplisit agar total dapat dibangun kembali persis.
Gunakan status sebagai alur kerja saja (Draft, Issued, Void, Paid), dan jadikan entri ledger yang diposting serta alokasi sebagai kebenaran akuntansi. Status bisa keliru; entri yang tidak dapat diubah memungkinkan finance menghitung ulang total dengan cara yang sama setiap saat.


