Di bagian pertama saya sudah bercerita kenapa akhirnya membuat Expense Tracker dan fitur-fitur utama yang ada di dalamnya.
Nah, di bagian ini saya ingin sedikit masuk ke “belakang layar”. Bukan membahas kode baris per baris, tapi lebih ke logika bagaimana aplikasi ini bekerja supaya saldo pengguna selalu tetap benar.
Jujur saja, sebelum mengerjakan project ini saya sempat berpikir kalau aplikasi pencatat keuangan itu sederhana. Tinggal simpan data pemasukan dan pengeluaran ke database, selesai.
Ternyata tidak sesederhana itu.
Ada banyak kondisi yang harus dipikirkan supaya data tetap konsisten. Dan justru di sinilah saya belajar cukup banyak.
Menambahkan Transaksi Ternyata Tidak Sesederhana INSERT ke Database
Misalnya saya memiliki rekening BCA dengan saldo awal sebesar Rp2.000.000.
Kemudian saya ingin mencatat pengeluaran sebesar Rp250.000 untuk membeli kebutuhan bulanan.
Kalau dipikir sekilas, prosesnya mungkin hanya seperti ini.
- Simpan transaksi.
- Selesai.
Padahal kenyataannya ada beberapa langkah yang harus dilakukan.
Pertama, sistem harus memastikan rekening yang dipilih memang ada.
Setelah itu sistem mengecek apakah saldo rekening masih mencukupi.
Kalau ternyata saldo kurang, proses langsung dihentikan.
Kalau saldo cukup, baru saldo rekening dikurangi sesuai nominal transaksi.
Barulah setelah itu data transaksi disimpan ke database.
Urutan ini penting.
Saya tidak ingin ada kondisi di mana transaksi berhasil disimpan, tetapi saldo rekening gagal diperbarui. Atau sebaliknya, saldo berubah tetapi transaksi tidak tercatat.
Kalau sampai itu terjadi, data keuangan pengguna bisa berantakan.
Kenapa Saya Menambahkan Validasi Saldo?
Menurut saya, validasi saldo adalah salah satu fitur yang wajib ada.
Misalnya seseorang memiliki saldo Rp100.000.
Lalu ia mencoba mencatat pengeluaran sebesar Rp500.000.
Kalau aplikasi tetap mengizinkan transaksi tersebut, saldo akan berubah menjadi minus.
Untuk aplikasi yang saya buat, saya memutuskan untuk tidak mengizinkan hal itu.
Begitu pengguna menekan tombol simpan, sistem akan langsung mengecek saldo rekening.
Kalau nominal transaksi lebih besar daripada saldo yang tersedia, transaksi langsung dibatalkan.
Pengguna akan mendapatkan informasi bahwa saldo tidak mencukupi.
Dengan cara ini data yang tersimpan akan selalu masuk akal.
Logika Saat Menambahkan Pemasukan
Kalau transaksi yang dibuat adalah pemasukan, prosesnya sedikit lebih sederhana.
Misalnya saya baru menerima pembayaran dari klien sebesar Rp1.500.000.
Saya memilih rekening Mandiri sebagai tujuan.
Yang dilakukan sistem adalah:
- Menambahkan saldo rekening Mandiri.
- Menyimpan data transaksi.
Setelah transaksi berhasil, dashboard juga otomatis ikut berubah.
Total saldo bertambah.
Total pemasukan ikut bertambah.
Saldo rekening Mandiri juga langsung diperbarui.
Semuanya terjadi secara otomatis tanpa perlu menghitung ulang secara manual.
Bagian yang Paling Menarik: Edit Transaksi
Menurut saya, fitur edit transaksi justru menjadi bagian yang paling menantang selama membuat aplikasi ini.
Awalnya saya mengira proses edit cukup dengan menjalankan query UPDATE.
Ternyata tidak bisa sesederhana itu.
Misalnya ada kondisi seperti ini.
Saldo rekening saat ini adalah:
Rp900.000
Di dalam riwayat terdapat transaksi:
Pengeluaran Rp100.000.
Kemudian pengguna mengedit transaksi tersebut menjadi:
Pengeluaran Rp300.000.
Kalau sistem hanya mengubah nominal transaksi menjadi Rp300.000 tanpa memperbaiki saldo, hasil akhirnya akan salah.
Karena itu saya menggunakan pendekatan yang berbeda.
Sebelum menyimpan data baru, sistem akan menghapus efek transaksi lama terlebih dahulu.
Artinya saldo dikembalikan seperti sebelum transaksi dibuat.
Baru setelah itu sistem menghitung transaksi yang baru.
Misalnya seperti ini.
Saldo setelah transaksi lama:
Rp900.000
Transaksi lama:
Pengeluaran Rp100.000
Sistem mengembalikan Rp100.000.
Saldo menjadi:
Rp1.000.000
Kemudian transaksi baru:
Pengeluaran Rp300.000
Saldo berubah lagi menjadi:
Rp700.000
Dengan cara ini hasil akhirnya selalu benar.
Walaupun langkahnya lebih panjang, saya merasa pendekatan ini jauh lebih aman.
Hal yang Sama Berlaku Saat Menghapus Transaksi
Logika delete ternyata juga tidak sesederhana menghapus data.
Misalnya saya menghapus transaksi pengeluaran Rp200.000.
Kalau transaksi langsung dihapus begitu saja, saldo rekening akan tetap berkurang Rp200.000.
Padahal seharusnya saldo dikembalikan.
Karena itu urutannya menjadi seperti ini.
Pertama, sistem membaca transaksi yang akan dihapus.
Kemudian melihat jenis transaksinya.
Kalau yang dihapus adalah pengeluaran, maka saldo rekening ditambah kembali.
Kalau yang dihapus adalah pemasukan, maka saldo rekening dikurangi.
Setelah saldo selesai diperbaiki, barulah data transaksi benar-benar dihapus.
Dengan cara ini saldo selalu sesuai dengan kondisi sebenarnya.
Belajar Menggunakan Database Transaction
Salah satu hal baru yang saya pelajari selama mengerjakan project ini adalah pentingnya database transaction.
Misalnya ada tiga proses yang harus dilakukan.
- Update saldo rekening.
- Simpan transaksi.
- Perbarui data dashboard.
Bagaimana kalau proses pertama berhasil, tetapi proses kedua gagal?
Kalau tidak menggunakan transaction, database bisa berada dalam kondisi yang tidak konsisten.
Misalnya saldo sudah berkurang, tetapi transaksi tidak pernah tersimpan.
Tentu ini akan menjadi masalah besar.
Karena itu saya menggunakan transaction di PostgreSQL.
Secara sederhana alurnya seperti ini.
Semua proses dimulai terlebih dahulu.
Kalau semuanya berhasil, perubahan disimpan secara permanen.
Kalau salah satu gagal, semua perubahan dibatalkan.
Jadi database kembali seperti sebelum proses dimulai.
Konsep ini memang sederhana, tetapi sangat penting untuk aplikasi yang berhubungan dengan data keuangan.
Dashboard Selalu Mengambil Data Terbaru
Salah satu hal yang saya inginkan sejak awal adalah dashboard selalu menampilkan data yang up-to-date.
Setiap kali pengguna menambahkan transaksi baru, saya tidak ingin pengguna harus menghitung ulang total saldo secara manual.
Begitu transaksi berhasil disimpan, dashboard langsung memperlihatkan perubahan.
Total saldo bertambah atau berkurang.
Total pemasukan ikut berubah.
Total pengeluaran juga berubah.
Saldo masing-masing rekening ikut diperbarui.
Dari sisi pengguna, semuanya terlihat instan.
Padahal di belakang layar ada beberapa proses yang berjalan terlebih dahulu.
Kenapa Saya Memilih Konsep Banyak Rekening?
Banyak aplikasi pencatat keuangan hanya menyediakan satu saldo utama.
Menurut saya, pendekatan seperti itu kurang fleksibel.
Di kehidupan sehari-hari saya menggunakan beberapa tempat untuk menyimpan uang.
Ada rekening bank.
Ada e-wallet.
Ada uang tunai.
Masing-masing memiliki saldo sendiri.
Karena itu saya membuat sistem yang memungkinkan pengguna memiliki banyak rekening.
Saat membuat transaksi, pengguna tinggal memilih rekening mana yang digunakan.
Dengan cara ini pengguna bisa mengetahui saldo setiap rekening secara terpisah tanpa harus menghitung sendiri.
Selain lebih rapi, informasi yang ditampilkan juga terasa lebih realistis.
Semakin Dikerjakan, Semakin Banyak Hal Baru yang Dipelajari
Awalnya saya mengira project ini hanya akan menjadi latihan CRUD biasa.
Tetapi setelah mulai menambahkan validasi, autentikasi, update saldo otomatis, rollback, dan database transaction, saya jadi sadar kalau membangun aplikasi keuangan ternyata membutuhkan perhatian lebih terhadap detail.
Walaupun fiturnya terlihat sederhana dari luar, ada cukup banyak logika yang harus dipastikan berjalan dengan benar.
Dan justru bagian-bagian seperti inilah yang menurut saya paling seru selama proses development.
Di artikel berikutnya saya akan membahas teknologi yang saya gunakan selama membangun project ini, mulai dari Next.js App Router, PostgreSQL, Tailwind CSS, JWT Authentication, hingga bagaimana saya menyusun struktur folder agar project tetap rapi dan mudah dikembangkan seiring bertambahnya fitur.
Link Github : https://github.com/ahmadzipur/expense-tracker.git