Aplikasi manajemen utang pribadi berbasis Google Apps Script + Google Sheets
Lunasin adalah aplikasi web mobile-first untuk mencatat, memantau, dan mengelola utang piutang secara personal. Dibangun di atas Google Apps Script dengan Google Sheets sebagai database, sehingga gratis, tanpa server, dan data tersimpan langsung di Google Drive Anda.
| Fitur | Keterangan |
|---|---|
| π Dashboard | Ringkasan total hutang, terbayar, dan sisa tagihan secara real-time |
| β Tambah Utang | Catat pokok pinjaman, bunga, jatuh tempo, dan keterangan |
| π³ Catat Pembayaran | Rekam cicilan dengan alokasi otomatis bunga vs. pokok |
| Tambah denda pada tagihan overdue β menambah total tagihan secara langsung, opsional | |
| π° Deteksi Lebih Bayar | Otomatis mendeteksi & menampilkan nominal kelebihan bayar |
| π Riwayat Transaksi | Daftar lengkap semua utang dengan search dan pagination |
| ποΈ Arsip | Simpan transaksi lunas ke arsip tanpa menghapus riwayat |
| π Pencarian | Filter berdasarkan nama, keterangan, status (aktif, lunas, lebih bayar) |
| π Detail & Timeline | Grafik progress, kartu Pokok/Bunga/Total/Sisa/Denda, dan timeline pembayaran per-utang |
| Geser kartu kanan/kiri untuk edit, hapus, atau arsip (mobile) | |
| π Pull-to-Refresh | Tarik ke bawah untuk memperbarui data dari spreadsheet |
| π± Full-Screen Mobile | Dioptimasi untuk Android & iPhone, semua ukuran layar |
| π Copy Link Utang | Salin link read-only per-utang untuk dibagikan ke pihak lain |
| β©οΈ Undo Delete | 5 detik jendela undo setelah menghapus β tidak ada penghapusan tidak sengaja |
| π Catatan per Cicilan | Tambahkan catatan opsional pada setiap pembayaran cicilan |
| π΄ Badge Overdue | Ikon Dashboard menampilkan jumlah utang lewat jatuh tempo secara real-time |
| π³ Haptic Feedback | Getaran kontekstual untuk navigasi, hapus, dan validasi (Android) |
- Backend: Google Apps Script (V8 runtime)
- Database: Google Sheets (2 sheet:
debts+installments) - Frontend: Vanilla HTML/CSS/JS β tidak ada framework, tidak ada dependency eksternal
- Font: Sora + DM Sans via Google Fonts
- Cache: Apps Script CacheService (TTL 300 detik)
- ID: Format
DEBT-YYYYMMDD-XXXX/INST-YYYYMMDD-XXXX
lunasin/
βββ Code.gs # Backend β API handler, CRUD, validasi, rate limiting
βββ Index.html # Entry point β HTML struktur + font preload + GAS includes
βββ Styles.html # Semua CSS β design tokens, komponen, animasi
βββ Script.html # Semua JS β state, UI, event handler, demo mode
βββ ShareView.html # Halaman read-only untuk share link per-utang
- Akun Google
- Google Spreadsheet (baru atau yang sudah ada)
1. Buka Google Spreadsheet
Buka atau buat spreadsheet baru di sheets.google.com.
2. Buka Apps Script Editor
Klik menu Extensions β Apps Script.
3. Salin kode
Di panel kiri editor, buat 5 file berikut:
| File | Cara membuat | Isi dengan |
|---|---|---|
Code.gs |
Sudah ada secara default | Isi file Code.gs dari repo ini |
Index.html |
Klik + β pilih HTML β beri nama Index |
Isi file Index.html |
Styles.html |
Klik + β pilih HTML β beri nama Styles |
Isi file Styles.html |
Script.html |
Klik + β pilih HTML β beri nama Script |
Isi file Script.html |
ShareView.html |
Klik + β pilih HTML β beri nama ShareView |
Isi file ShareView.html |
β οΈ Nama file harus sama persis (case-sensitive).Code.gsmemanggilShareViewdanIndexmemanggilStylesdanScriptviainclude()β salah nama menyebabkan error deploy.
4. Inisialisasi database
Jalankan fungsi initApp() untuk membuat sheet otomatis:
- Pilih fungsi
initAppdari dropdown di toolbar - Klik Run βΆ
- Izinkan akses Google Sheets saat diminta (popup OAuth)
- Pastikan log menampilkan
=== initApp OK ===
Langkah ini membuat sheet
debtsdaninstallmentsbeserta header kolom secara otomatis.
5. Deploy sebagai Web App
- Klik Deploy β New deployment
- Pilih tipe: Web app
- Isi konfigurasi:
- Description:
Lunasin vX.X.X(sesuaikan versinya) - Execute as:
Me - Who has access:
Only myself(atau sesuaikan)
- Description:
- Klik Deploy
- Salin URL Web App yang muncul
6. Buka aplikasi
Akses URL Web App di browser HP Anda. Untuk pengalaman terbaik, tambahkan ke Home Screen:
- Android: Menu browser β Add to Home Screen
- iPhone: Share β Add to Home Screen
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
String | ID unik DEBT-YYYYMMDD-XXXX |
person_name |
String | Nama peminjam |
principal_amount |
Number | Pokok pinjaman (Rupiah) |
interest_amount |
Number | Bunga (Rupiah) |
total_amount |
Number | Total = pokok + bunga + denda |
paid_amount |
Number | Total terbayar |
remaining_amount |
Number | Sisa tagihan |
status |
String | active / paid |
due_date |
String | Jatuh tempo YYYY-MM-DD (opsional) |
created_at |
String | Timestamp ISO 8601 |
notes |
String | Keterangan (opsional) |
updated_at |
String | Timestamp terakhir diperbarui |
overpayment_amount |
Number | Kelebihan bayar (jika ada) |
archived |
Boolean | true jika diarsip |
penalty_total |
Number | Akumulasi denda keterlambatan (jika ada) |
| Kolom | Tipe | Keterangan |
|---|---|---|
id |
String | ID unik INST-YYYYMMDD-XXXX |
debt_id |
String | Referensi ke debts.id |
payment_amount |
Number | Jumlah pembayaran |
payment_date |
String | Tanggal pembayaran YYYY-MM-DD |
created_at |
String | Timestamp ISO 8601 |
notes |
String | Catatan pembayaran (opsional) |
Semua request dikirim via google.script.run.processRequest(jsonString).
{ "action": "getDebts", "page": 1, "limit": 100 }
{ "action": "getDebts", "id": "DEBT-20250101-0001" }
{ "action": "getDebts", "onlyArchived": true }
{ "action": "getDebts", "includeArchived": true, "q": "budi" }{
"action": "createDebt",
"person_name": "Budi Santoso",
"principal_amount": 5000000,
"interest_amount": 500000,
"due_date": "2025-12-01",
"notes": "Pinjaman modal usaha"
}{
"action": "updateDebt",
"id": "DEBT-20250101-0001",
"person_name": "Budi Santoso",
"principal_amount": 6000000,
"interest_amount": 600000
}{
"action": "addPayment",
"debt_id": "DEBT-20250101-0001",
"payment_amount": 1000000,
"payment_date": "2025-03-15",
"notes": "Transfer BCA"
}{ "action": "deleteDebt", "id": "DEBT-20250101-0001" }
{ "action": "archiveDebt", "id": "DEBT-20250101-0001" }
{ "action": "unarchiveDebt", "id": "DEBT-20250101-0001" }{ "action": "healthCheck" }
{ "action": "getAppUrl" }Denda bersifat opsional dan hanya tersedia pada tagihan yang berstatus overdue (lewat jatuh tempo). Denda diakumulasi di kolom
penalty_totaldan langsung menambahtotal_amount.
| Platform | Status |
|---|---|
| Android | β |
| iPhone/iPad | β |
| Desktop | β |
Konstanta di Code.gs yang bisa disesuaikan:
var CACHE_TTL = 300; // Cache TTL dalam detik (default: 5 menit)
var LOCK_MS = 6000; // Lock timeout untuk write operations (ms)
var RATE_LIMIT_MAX = 30; // Maks request per user per window
var RATE_LIMIT_WIN = 60; // Rolling window rate limit (detik)
var SHEET_DEBTS = 'debts'; // Nama sheet utang
var SHEET_INST = 'installments'; // Nama sheet cicilan- Semua input di-sanitasi di backend (
sStr,sName,sNotes) dan frontend sebelum dikirim ke Sheets - Script tag dan atribut event handler di-strip dari semua input
- Lock service digunakan untuk mencegah race condition pada write operations
- Cache di-invalidate setiap kali ada perubahan data
- Rate limiting per user (30 req/menit) mencegah abuse pada URL publik
Saat diakses di luar Google Apps Script (misal: langsung buka Index.html di browser), aplikasi otomatis masuk mode demo dengan data contoh 12 utang termasuk simulasi denda. Tidak ada perubahan yang tersimpan ke spreadsheet.
Bayu Wicaksono
MIT License β bebas digunakan, dimodifikasi, dan didistribusikan dengan mencantumkan kredit.









