# Merancang Rekonsiliasi Sesi Kas POS di Sebuah ERP

> Bagaimana saya merancang modal awal, kas masuk/keluar, selisih ekspektasi vs hitungan, dan jejak audit append-only untuk POS carwash Indonesia nyata.

URL: https://www.matthewswong.com/id/blog/pos-cash-session-reconciliation-design/

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

> **Key takeaway:** Sesi kas POS adalah catatan per-shift: kasir membuka dengan modal awal yang dihitung, setiap penjualan tunai dan pengeluaran dicatat, dan saat tutup sistem menghitung kas ekspektasi sebagai modal awal ditambah kas masuk dikurangi kas keluar. Kasir menghitung laci fisik, selisihnya adalah varians, dan kedua angka plus siapa yang menutup ditulis ke log audit append-only.

Ketika saya membangun JID Carwash ERP untuk sebuah UKM carwash Indonesia, satu fitur yang paling membuat pemilik cemas bukanlah penggajian atau inventaris. Melainkan laci kas. Setiap shift, kasir menangani setumpuk uang kertas fisik, dan di akhir hari pemilik ingin satu jawaban jujur: apakah uang di laci cocok dengan yang seharusnya menurut sistem? Mendapatkan jawaban itu secara andal adalah keseluruhan tugas modul sesi kas.

Godaannya adalah menyimpan satu saldo kas berjalan tunggal dan menyesuaikannya di setiap transaksi. Saya belajar dengan cara sulit bahwa ini model yang salah. Saldo berjalan menyembunyikan riwayat, tidak bisa menjawab siapa yang bertugas ketika selisih muncul, dan mengubah bug konkurensi menjadi uang hilang. Sebagai gantinya saya memodelkan sesi kas sebagai catatan eksplisit yang tidak-bisa-diubah-setelah-ditutup, dan saya membuat buku kas sebagai tampilan turunan alih-alih tabel yang bisa ditulisi siapa pun.

## Alur kerja kasir nyata di carwash

Sebelum menulis satu model Prisma pun saya duduk di kasir dan mengamati. Carwash ini menjalankan dua shift sehari di beberapa cabang. Sebuah shift dimulai ketika kasir menghitung laci dan mencatat modal awal, biasanya sekitar Rp 500.000 dalam pecahan kecil untuk kembalian. Sepanjang hari uang tunai masuk dari order cuci dan keluar untuk pengeluaran kecil seperti membeli detergen atau membayar kasbon, uang muka karyawan. Di akhir shift kasir menghitung laci lagi, menyerahkan ke orang berikutnya, dan uang di atas modal disetorkan.

- Buka: kasir menghitung laci secara fisik dan mencatat modal awal untuk shift.
- Selama: kas masuk dari penjualan tunai yang dibayar, kas keluar untuk pengeluaran kecil dan pencairan kasbon, masing-masing dicatat sebagai pergerakan tersendiri.
- Tutup: kasir menghitung laci lagi, sistem menampilkan kas ekspektasi, dan selisihnya menjadi varians yang tercatat.
- Serah terima: semua di atas modal disetorkan dan shift berikutnya membuka sesi baru.

## Memodelkan sesi kas, bukan saldo

Entitas inti adalah CashSession yang tercakup pada satu cabang, satu karyawan, dan satu status. Uang disimpan sebagai bilangan bulat Rupiah Indonesia di seluruh basis kode, tidak pernah sebagai angka floating-point, karena IDR tidak memiliki sub-unit dalam penggunaan sehari-hari dan float diam-diam merusak jumlah. Jumlah pembukaan dan penutupan-terhitung berada langsung di sesi; semua yang terjadi di antaranya adalah aliran pergerakan kas yang mereferensikan sesi tersebut.

> Setiap query daftar dan detail di API tercakup berdasarkan branchId. Versi awal membiarkan seorang manajer di cabang A memuat id sesi dari cabang B hanya dengan menebak URL, sebuah IDOR klasik. Mencakup berdasarkan branchId di klausa where Prisma pada setiap pembacaan menutupnya. Perlakukan id sesi sebagai non-rahasia dan cakupan cabang sebagai batas yang sebenarnya.

## Buku kas adalah tampilan turunan, bukan tabel yang ditulisi

Pemilik menginginkan buku kas berjalan, disebut buku kas, yang menampilkan setiap entri secara kronologis. Pendekatan naif adalah tabel CashLedgerEntry yang Anda sisipi di setiap transaksi. Saya sengaja tidak membangun itu. Sebagai gantinya CashLedgerEntry adalah tampilan union turunan yang dirakit saat baca dari tabel sumber sebenarnya: pergerakan kas, pembayaran yang diselesaikan, dan pengeluaran. Tidak ada jalur tulis ke buku besar, sehingga ia tidak akan pernah menyimpang dari transaksi yang diringkasnya.

Ini mencerminkan aturan yang saya terapkan di mana-mana dalam ERP: cache dan ringkasan harus memiliki satu sumber kebenaran. Jumlah stok produk juga adalah cache; kebenarannya adalah jumlah dari pergerakan stok. Jika angka turunan dan sumbernya tidak sepakat, sumber yang menang dan nilai turunan cukup dihitung ulang. Prinsip itu menghilangkan seluruh kategori bug rekonsiliasi di mana ringkasan diam-diam berbohong.

## Ekspektasi vs hitungan: rumus varians

Saat tutup, layanan menjumlahkan pergerakan untuk sesi tersebut dan menghitung kas ekspektasi. Rumusnya adalah yang standar industri: modal awal ditambah total kas masuk dikurangi total kas keluar. Kasir memasukkan jumlah yang dihitung secara fisik, dan varians adalah hitungan dikurangi ekspektasi. Varians positif adalah kelebihan, yang negatif adalah kekurangan, sesuai dengan konsep akuntansi cash over and short.

Perhatikan bahwa penutupan ekspektasi disnapshot ke baris pada waktu tutup. Saya tidak menghitungnya ulang kemudian dari pergerakan langsung, karena koreksi bertanggal mundur pada suatu order tidak boleh diam-diam mengubah terhadap apa suatu shift direkonsiliasi berbulan-bulan lalu. Snapshot membekukan rekonsiliasi sebagaimana adanya ketika manusia menghitung laci.

> Penyelesaian pembayaran menggunakan kunci idempotensi. Kasir menekan konfirmasi dua kali, atau koneksi seluler tidak stabil yang mengulang, tidak boleh membuat dua pergerakan kas masuk untuk satu cucian. Layanan penyelesaian mendeduplikasi berdasarkan kunci yang dipasok klien sehingga pengulangan mengembalikan hasil asli alih-alih menghitung ganda. Idempotensi adalah bagian inti dari arus kas yang sehat, bukan tambahan.

## Penanganan varians dan siapa yang boleh menutup

Tidak setiap varians adalah kecurangan, dan sistem tidak boleh memperlakukannya begitu. Target carwash jauh di bawah satu persen dari penjualan tunai; panduan industri menempatkan laci yang dikelola baik di bawah 0,1 persen. Saya membangun kebijakan dua tingkat: varians kecil dalam ambang yang dapat dikonfigurasi ditutup otomatis dengan catatan tercatat, sementara apa pun di luar itu memerlukan manajer untuk meninjau dan menyetujui penutupan. Satu kekurangan kecil didokumentasikan tanpa tuduhan; modul menampilkan pola lintas shift, karena kekurangan kecil berulang adalah sinyal yang lebih kuat daripada satu yang besar.

| Rentang varians | Siapa yang boleh menutup | Apa yang dicatat |
| --- | --- | --- |
| Dalam ambang | Kasir yang bertugas | Tutup otomatis dengan catatan varians |
| Di luar ambang | Hanya manajer atau pemilik | Teks alasan plus id penyetuju |
| Pola berulang | Tinjauan pemilik | Tanda laporan lintas shift |

## Jejak audit yang membuatnya dapat dipertanggungjawabkan

Setiap pembukaan, pergerakan, dan penutupan menulis ke AuditLog append-only. Baris tidak pernah diperbarui atau dihapus, informasi yang dapat mengidentifikasi pribadi diredaksi saat tulis, dan setiap entri mencatat siapa melakukan apa, kapan, dan terhadap sesi serta cabang mana. Ketika pemilik bertanya mengapa cabang B kurang Rp 40.000 pada hari Selasa, jawabannya adalah query, bukan tebakan. Log audit itulah yang mengubah setumpuk uang menjadi proses yang dapat dipertanggungjawabkan yang benar-benar dipercaya pemilik.

Hasil dari desain ini adalah rekonsiliasi berhenti menjadi perdebatan. Angka-angka diturunkan dari pergerakan yang tidak dapat diubah, varians dibekukan saat tutup, izin menentukan siapa yang dapat menyetujui, dan log audit mengingat segalanya. Itulah perbedaan antara perangkat lunak yang melacak uang dan perangkat lunak yang pemilik bersedia mempertaruhkan bisnisnya.

## Sources

- Cashier balancing (Wikipedia)
- Cash Over and Short: turning till discrepancies into an audit trail (Beancount.io)
- How to manage cash float in POS systems (ConnectPOS)

## Source links

- https://en.wikipedia.org/wiki/Cashier_balancing
- https://beancount.io/blog/2026/07/08/cash-over-and-short-account-till-discrepancy-bookkeeping
- https://www.connectpos.com/how-to-manage-cash-float-in-pos/

## FAQ

### Apa itu sesi kas POS dan mengapa tidak sekadar melacak saldo berjalan?

Sesi kas adalah catatan per-shift dengan modal awal, aliran pergerakan kas, dan jumlah penutupan terhitung. Ini lebih baik daripada saldo berjalan tunggal karena menyimpan siapa yang bertugas, kapan setiap pergerakan terjadi, dan membekukan rekonsiliasi saat tutup. Saldo berjalan menyembunyikan riwayat itu dan mengubah bug konkurensi apa pun menjadi uang yang tidak bisa Anda lacak.

### Bagaimana cara menghitung kas penutupan ekspektasi dan varians?

Penutupan ekspektasi sama dengan modal awal ditambah total kas masuk dikurangi total kas keluar untuk shift. Kasir menghitung laci fisik dan varians adalah jumlah terhitung dikurangi jumlah ekspektasi. Varians positif adalah kelebihan dan yang negatif adalah kekurangan, sesuai konsep akuntansi cash over and short.

### Mengapa buku kas sebaiknya berupa tampilan turunan alih-alih tabel?

Tabel buku besar yang ditulisi bisa diam-diam menyimpang dari transaksi yang seharusnya diringkasnya, terutama saat ada pengulangan atau kegagalan sebagian. Menurunkan buku kas sebagai union saat-baca dari tabel pergerakan, pembayaran, dan pengeluaran yang sebenarnya berarti tidak ada jalur tulis untuk dirusak. Jika total turunan pernah tidak sepakat dengan sumbernya, sumber yang menang dan tampilan dihitung ulang.

### Siapa yang seharusnya boleh menutup sesi kas dengan varians?

Gunakan kebijakan bertingkat. Varians dalam ambang yang dapat dikonfigurasi bisa ditutup oleh kasir yang bertugas dengan catatan tercatat. Apa pun di luar ambang memerlukan manajer atau pemilik untuk meninjau, memasukkan alasan, dan menyetujui, dan kekurangan kecil berulang sebaiknya ditandai untuk tinjauan pemilik lintas shift alih-alih dinilai satu shift saja.

### Bagaimana menjaga rekonsiliasi kas tetap dapat dipertanggungjawabkan dan diaudit?

Tulis setiap pembukaan, pergerakan, dan penutupan ke log audit append-only yang tidak pernah diperbarui atau dihapus, dengan informasi yang dapat mengidentifikasi pribadi diredaksi saat tulis. Snapshot jumlah penutupan ekspektasi ke sesi saat tutup sehingga suntingan bertanggal mundur kemudian tidak bisa menulis ulang terhadap apa suatu shift direkonsiliasi. Bersama-sama ini membuat selisih apa pun dapat dijawab dengan query alih-alih tebakan.

---

- HTML version: https://www.matthewswong.com/id/blog/pos-cash-session-reconciliation-design/
- English: https://www.matthewswong.com/en/blog/pos-cash-session-reconciliation-design/
- 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
