Studi Kasus

Cashflow Tracker “Stephen”

Bot Telegram pencatat keuangan yang mengerti kalimat sehari-hari, lengkap dengan REST API dan aplikasi Flutter. Saya pakai sendiri setiap hari, dan ia berjalan tanpa ditunggui di VPS sendiri.

Peran
Perancang & pengembang tunggal
Status
Berjalan di produksi
Lingkup
Bot, API, aplikasi, infrastruktur
Kode
Repo privat
Kenapa tidak ada tautan demo? Aplikasinya terkunci di balik API key dan terhubung ke rekening saya sendiri, jadi membukanya untuk umum tidak masuk akal — baik dari sisi keamanan maupun privasi. Halaman ini menggantikannya: arsitektur, keputusan, dan angkanya bisa dinilai tanpa saya harus membuka data pribadi.

Masalah yang diselesaikan

Aplikasi pencatat keuangan yang ada menuntut disiplin yang saya tidak punya: buka aplikasi, pilih kategori, pilih dompet, ketik nominal. Tiga langkah terlalu banyak untuk hal yang harus dilakukan lima kali sehari, dan begitu satu hari terlewat, catatannya tidak pernah dikejar lagi.

Jadi saya balik arahnya: pencatatan harus menyesuaikan kebiasaan, bukan sebaliknya. Cukup ketik “makan siang 35rb pakai bni” ke Telegram — aplikasi yang memang sudah terbuka sepanjang hari. Dan untuk transaksi yang meninggalkan jejak email, bahkan mengetik pun tidak perlu.

Arsitektur

Empat jalur masuk, satu otak, satu basis data.

  Telegram  ──webhook──►┐
                        │
  Gmail ──Apps Script──►│                      ┌─────────────┐
       (POST /ingest)   ├──►  FastAPI  ──ORM──►│  PostgreSQL │
                        │     (uvicorn)        │   (Neon,    │
  Aplikasi Flutter ────►│        │             │  Singapura) │
       (REST /api)      │        │             └─────────────┘
                        │        ▼
  systemd timer  ──────►┘   Gemini 2.5 Flash-Lite
       (/cron/*)             + fallback regex

  ── VPS Ubuntu 24.04, Singapura ──────────────────────
     Caddy (HTTPS otomatis) → uvicorn 127.0.0.1:8000
     dijaga systemd · timer menggantikan cron eksternal

Satu logika, tiga permukaan

Bot Telegram, REST API, dan aplikasi Flutter memakai lapisan logika yang sama. Aturan kategori, konversi dolar, dan penggabungan transfer tidak pernah ditulis dua kali.

AI dengan jaring pengaman

Gemini menangani kalimat bebas. Kalau kuotanya habis atau responsnya gagal, parser regex mengambil alih — set saldo dan cek saldo tetap jalan tanpa AI sama sekali.

Masuk sendiri dari email

Google Apps Script membaca email notifikasi transaksi dari beberapa dompet dan rekening, lalu mengirimnya ke /ingest. Bot menebak kategori dari nama merchant dan mengirim notifikasi dengan tombol koreksi.

Angka yang bisa diperiksa

159Test backend (pytest)
36Test aplikasi (Flutter)
26Tahap pengembangan
0→60 dtkCold start setelah pindah VPS

Perjalanan

Yang paling banyak mengubah bentuk sistemnya.

Tahap awal

Bot yang cuma bisa mencatat

Webhook Telegram di Render, satu dompet, satu jenis transaksi. Hambatan pertama justru sepele: WEBHOOK_SECRET bawaan Render memuat karakter yang ditolak Telegram, dan WEBHOOK_URL harus base URL tanpa akhiran /webhook.

Tahap menengah

Multi-dompet, laporan, dan anggaran

Beberapa dompet dan rekening sekaligus, plus transfer antar dompet. Laporan grafik, anggaran per kategori dengan peringatan otomatis, transaksi berulang, tag #event, dan ekspor Excel.

Audit

Memeriksa ulang yang sudah jalan

Review kode menemukan tiga cacat senyap: semua tanggal memakai UTC sehingga transaksi pukul 00.00–07.00 WIB tersimpan mundur sehari; pasangan transfer dicari lewat “dua baris terakhir” sehingga bisa menghapus transaksi yang salah; dan update_id Telegram bisa terproses dua kali saat cold start.

Tahap sekarang

Pindah ke VPS sendiri

Dari Render ke IDCloudHost Singapura. Server dikeraskan sendiri, Caddy memegang HTTPS, dan systemd timer menggantikan cron eksternal. Cold start 30–60 detik hilang sepenuhnya, dan jadwal yang terlewat kini diulang otomatis — sesuatu yang tidak pernah dilakukan layanan cron sebelumnya.

Teknologi

Backend
  • Python
  • FastAPI
  • uvicorn
  • SQLAlchemy 2.0
  • pytest
Data
  • PostgreSQL (Neon)
  • SQLite (lokal)
  • openpyxl
  • matplotlib
AI
  • Gemini 2.5 Flash-Lite
  • Fallback regex
Aplikasi
  • Flutter
  • REST API
Infrastruktur
  • Ubuntu 24.04
  • Caddy
  • systemd
  • Let's Encrypt
  • Google Apps Script

Yang saya bawa dari proyek ini

Membangun sesuatu yang saya pakai sendiri setiap hari mengubah cara saya menilai kode. Bug tidak berhenti di laporan — ia mengganggu saya langsung, malam itu juga. Itu yang membuat saya berhenti mengandalkan asumsi dan mulai memeriksa apa yang benar-benar berjalan.