Reconciliation Kami Selalu Match. Sampai Diskon Ikut Campur di Dalam Transaksi.
Reconciliation akan selalu match untuk yang amount-nya persis seperti yang dikirim bank. Tapi tidak dengan transakasi yang ada diskon, fee, atau voucher, reconciliation yang tadinya rapi berubah jadi mimpi buruk setiap akhir bulan.
Reconciliation kami selalu match, untuk yang amount-nya persis seperti yang dikirim bank. Satu angka, satu sumber, gampang dicocokkan. Tidak ada yang perlu didebat.
Begitu masuk ke payment dan transfer yang ada diskon, fee, atau voucher, reconciliation yang tadinya rapi berubah jadi mimpi buruk setiap akhir bulan.
Bukan karena datanya salah. Karena datanya sudah tidak lengkap sejak awal.
Masalahnya bukan di reconciliation tool, atau kecepatan proses. Masalahnya satu level lebih dalam: cara kami menyimpan transaksi sejak awal.
Setiap transaksi payment disimpan sebagai satu angka total, `total_amount`. Diskon, fee, dan voucher semuanya sudah tercampur di dalamnya sebelum baris itu masuk ke database.
Untuk topup, ini tidak masalah, karena tidak ada komponen lain yang ikut campur. Amount di sistem kami sama persis dengan amount di bank.
Tapi begitu ada diskon, angka yang tersimpan bukan lagi angka asli. Dia sudah jadi hasil akhir dari perhitungan yang komponennya tidak pernah disimpan satu per satu.
Setiap akhir bulan, tim finance mulai panik.
Partner statement datang dengan breakdown per komponen: base amount, discount, fee, semuanya terpisah. Sistem kami cuma punya satu angka gabungan.
Untuk mencocokkan keduanya, ops harus menghitung ulang secara manual, membongkar total_amount itu untuk menebak berapa sebenarnya diskon yang dipotong, berapa fee-nya, berapa voucher-nya. Kadang hasilnya cocok. Kadang tidak, dan tidak ada yang tahu apakah selisihnya karena salah hitung, atau karena memang ada transaksi yang belum settle.
Transaksi yang tidak bisa direkonsiliasi ini menumpuk. Bukan satu dua, tapi berbulan-bulan, karena tidak ada yang bisa dengan cepat mengonfirmasi mana yang benar. Begitu closing bulanan tiba, tumpukan itu berubah jadi krisis yang harus diselesaikan dalam beberapa hari.
Yang hilang bukan proses reconciliation-nya. Yang hilang adalah komponen aslinya.
Reconciliation tidak akan pernah rapi kalau data yang direkonsiliasi sudah kehilangan detail sejak disimpan. `total_amount` itu sudah final, sudah tergabung, dan tidak bisa dipisah lagi tanpa menebak.
Keputusan yang sebenarnya dihindari bukan soal tool reconciliation yang lebih canggih. Tapi soal bagaimana transaksi seharusnya disimpan sejak hari pertama: sebagai satu angka gabungan, atau sebagai kumpulan komponen independen, base amount, discount, fee, voucher, masing-masing punya barisnya sendiri.
Menyimpan satu angka gabungan lebih cepat untuk di-ship. Tidak perlu skema tambahan, tidak perlu migrasi data, tidak perlu mikirin double-entry. Tapi kecepatan itu utang, dan utangnya jatuh tempo tepat di reconciliation dan closing bulanan.
Yang menyelesaikannya bukan tool baru. Tapi keputusan menyimpan transaksi sebagai ledger.
Di satu perusahaan, kami membangun ulang lapisan pencatatan transaksi ini sebagai ledger, dengan prinsip double-entry bookkeeping. Setiap komponen dicatat sebagai entry independen, base amount, discount, fee, voucher, masing-masing punya barisnya sendiri, bukan hasil kalkulasi yang sudah digabung.
Begitu ledger ini ada, mencari breakdown asli untuk dicocokkan dengan partner statement jadi mungkin lagi, karena komponennya memang tersimpan apa adanya, bukan hasil tebakan mundur.
Reconciliation yang tadinya jadi krisis bulanan berubah jadi rutinitas harian. Tidak ada lagi tumpukan transaksi yang belum direkonsiliasi menjelang closing, karena tidak ada lagi yang menunggu untuk ditebak. Proses manual untuk menghitung ulang angka asli, yang sebelumnya jadi kerjaan tetap ops, bisa dihapus sepenuhnya. Ops sekarang hanya menangani kasus yang memang butuh keputusan manual, bukan menangani angka yang seharusnya sudah jelas sejak awal.
Ini bukan keputusan yang sekali diambil lalu selesai untuk selamanya.
Saya sudah menyelesaikan masalah ini satu kali. Tapi begitu pindah ke perusahaan berikutnya, saya menemukan pola yang sama lagi: transaksi disimpan sebagai satu angka gabungan, karena lebih cepat untuk di-ship, dan belum ada yang merasakan sakitnya sampai reconciliation mulai kacau.
Keputusan menyimpan komponen sebagai ledger independen bukan soal preferensi teknis. Itu keputusan tentang siapa yang menanggung cost-nya nanti: tim yang membangunnya sekarang, atau tim finance dan ops yang harus menebak ulang setiap bulan.
Sebelum transaksi dengan lebih dari satu komponen disimpan sebagai satu angka, ada pertanyaan yang harus kamu jawab dulu.
Apakah transaksi ini akan selalu sesederhana topup, satu angka, satu sumber, atau akan ada komponen lain yang menempel di atasnya nanti?
Kalau breakdown-nya hilang, apakah kamu masih bisa mencocokkan dengan partner statement tanpa menebak?
Siapa yang akan menanggung cost-nya kalau breakdown ini harus direkonstruksi manual tiap bulan, kamu sekarang, atau tim finance dan ops nanti?
Sebetulnya kita bisa generate query reconciliation, bahkan bisa bantu menebak breakdown dari total_amount dengan pattern matching. Tapi kita tidak bisa mengembalikan komponen yang memang tidak pernah disimpan. Dia cuma bisa menebak lebih cepat, bukan menghilangkan tebakan itu sendiri.
Ledger bukan soal pembukuan yang lebih rapi. Ledger adalah keputusan bahwa kamu tidak mau menebak breakdown transaksi kamu sendiri, sekarang atau tiga tahun lagi.
Kalau transaksi kamu masih disimpan sebagai satu angka begitu komponen lain ikut campur, reconciliation kamu bukan sedang baik-baik saja. Dia cuma belum sampai ke bulan closing yang membongkarnya.