Project ini adalah bot WhatsApp yang berfungsi sebagai asisten keuangan pribadi. Dibangun dengan Node.js, bot ini mampu memahami input bahasa natural, membaca teks dari gambar struk (OCR dengan preprocessing gambar), dan secara otomatis mencatat transaksi ke dalam database MySQL. Dilengkapi dengan fitur pencarian dan edit transaksi, dukungan multi-mata uang, serta caching respons AI untuk mengurangi biaya API.
- Backend: Node.js + ExpressJS
- WhatsApp API:
whatsapp-web.js - QR Code:
qrcode-terminal - OCR:
EasyOCR(Python) dengan dukungan bahasa Indonesia & Inggris - Image Preprocessing:
jimp(grayscale, contrast, resizing) - AI (NLP): DeepSeek AI via
openailibrary - Caching:
lru-cacheuntuk mengurangi API calls dan meningkatkan kecepatan - Database:
mysql2 - Environment:
dotenv
-
Clone atau Unduh Kode
git clone https://github.com/your-username/wa-finance-bot.git cd wa-finance-bot -
Install Dependencies Jalankan perintah berikut di terminal:
npm install
-
Setup Database
- Buat sebuah database baru di server MySQL Anda (contoh:
wa_finance). - Impor skema tabel dengan menjalankan isi dari file
setup.sqldi database Anda. Skema akan membuat tabeltransactions,transaction_items,user_settings,accounts/account_members,account_invites,audit_logs,budgets, danrecurring_rules.
- Buat sebuah database baru di server MySQL Anda (contoh:
-
Konfigurasi Environment
- Salin file
.env.examplemenjadi file baru bernama.env.# Di Windows copy .env.example .env # Di macOS/Linux cp .env.example .env
- Buka file
.envdan isi semua nilai yang diperlukan:DB_HOST: Alamat host database Anda.DB_USER: Username untuk koneksi database.DB_PASSWORD: Password untuk koneksi database.DB_NAME: Nama database yang Anda buat.DEEPSEEK_API_KEY: API key Anda dari DeepSeek AI.
- Salin file
Setelah semua konfigurasi selesai, jalankan bot dengan perintah:
npm startTunggu beberapa saat, sebuah QR code akan muncul di terminal. Pindai (scan) QR code tersebut menggunakan aplikasi WhatsApp di ponsel Anda (dari menu Perangkat Tertaut / Linked Devices).
Setelah berhasil, Anda akan melihat pesan "Client is ready!" di terminal.
docker compose up --buildnpm install -g pm2
npm run start:pm2- Default berjalan di port
3000(bisa diubah dengan envPORT) - Endpoint healthcheck:
GET /health - Endpoint metrics:
GET /metrics - Endpoint
/api/*bisa diaktifkan dengan envHTTP_API_KEY(request harus membawa headerx-api-key) - Import statement CSV:
POST /api/import/statement
- Summary:
GET /api/dashboard/summary?accountId=1&start=2026-03-01&end=2026-03-31¤cy=IDR - Timeseries:
GET /api/dashboard/timeseries?accountId=1&start=2026-03-01&end=2026-03-31&bucket=day¤cy=IDR - Breakdown kategori:
GET /api/dashboard/by-category?accountId=1&start=2026-03-01&end=2026-03-31&type=OUT&limit=20¤cy=IDR - Breakdown merchant:
GET /api/dashboard/by-merchant?accountId=1&start=2026-03-01&end=2026-03-31&type=OUT&limit=20¤cy=IDR - Budget status:
GET /api/dashboard/budget-status?accountId=1&month=2026-03¤cy=IDR
API transaksi:
- List/pagination:
GET /api/transactions?accountId=1&start=2026-03-01&end=2026-03-31&type=OUT&limit=20&offset=0 - Search:
GET /api/transactions?accountId=1&q=parkir&limit=20&offset=0 - Detail:
GET /api/transactions/123?accountId=1
Audit log:
GET /api/audit?accountId=1&limit=50&offset=0
Catatan Docker:
- Di Docker, gunakan env
PYTHON_BIN=python3jika commandpythontidak tersedia.
Contoh request import:
curl -X POST http://localhost:3000/api/import/statement ^
-H "content-type: application/json" ^
-H "x-api-key: change-me" ^
-d "{\"accountId\":1,\"dryRun\":true,\"csv\":\"date,amount,description\\n2026-03-01,12000,Grab Food\\n\"}"Anda bisa berinteraksi dengan bot melalui beberapa cara:
-
Pesan Teks Langsung: Kirim pesan dalam bahasa sehari-hari.
-
tadi bayar parkir 5000
-
dapet transferan 1.5 juta dari klien
-
-
Kirim Gambar Struk: Kirim foto struk atau bukti transfer tanpa teks tambahan. Bot akan memindai gambar tersebut.
-
Kirim Gambar + Teks: Kirim foto bukti pembayaran beserta caption untuk memberikan konteks tambahan.
-
(Gambar struk bensin) > Isi Pertamax 250rb
-
-
Perintah Tambahan:
cari <keyword>– Mencari transaksi berdasarkan kata kunci.cari <keyword> page <n>– Pagination hasil pencarian.laporan– Menampilkan menu periode laporan.export ringkas <periode>– Export CSV ringkas (contoh:export ringkas bulan ini).export detail <periode>– Export CSV per-item (contoh:export detail bulan ini).export 2026-03-01 2026-03-31– Export range custom.struk terakhir– Mengirim file struk terakhir yang tersimpan.undo/batal– Membatalkan transaksi terakhir.undo kembali– Mengembalikan transaksi terakhir yang dibatalkan.edit transaksi terakhir jumlah <jumlah>– Mengubah nominal transaksi terakhir.edit transaksi <id> jumlah <jumlah>– Mengubah nominal transaksi berdasarkan ID.hapus transaksi <id>– Menghapus transaksi berdasarkan ID (bisa di-undo denganundo kembali).set currency <kode>– Mengubah preferensi mata uang (IDR, USD, EUR).help/menu– Menampilkan daftar perintah.budget set <kategori> <jumlah>– Set budget kategori bulan ini.budget list– Melihat status budget bulan ini.ulang list– List transaksi berulang.ulang tambah <in|out> <jumlah> <kategori> ; <keterangan> ; <tgl 1-28>– Tambah transaksi berulang.ulang hapus <id>– Menonaktifkan transaksi berulang.token– Menampilkan token akun aktif (khusus owner).token reset– Reset token akun aktif (khusus owner).pakai token <token>– Masuk ke akun orang lain untuk monitoring (read-only).monitor off– Kembali ke akun kamu sendiri.akun– Menampilkan daftar akun yang kamu punya akses.akun pilih <nomor>– Mengganti akun aktif.akun baru– Membuat akun baru (pencatatan terpisah).invite– Membuat token invite viewer (single-use, 30 hari).invite editor– Membuat token invite editor (bisa mencatat).invite list– Melihat daftar invite.invite cabut <id>– Mencabut invite tertentu.akses list– Melihat member yang punya akses ke akun aktif.akses cabut <user_id>– Mencabut akses user tertentu (khusus owner).kategori list– Menampilkan daftar kategori akun.kategori tambah <nama>– Menambah kategori baru.kategori map <keyword> => <kategori>– Mapping keyword merchant ke kategori.kategori rules– Menampilkan daftar mapping.merchant map <keyword> => <merchant>– Normalisasi nama merchant.merchant rules– Menampilkan daftar mapping merchant.
Bot akan membalas dengan konfirmasi jika data berhasil dicatat di database.
Catatan:
- Beberapa perintah sensitif (token/invite/akses/export/struk) hanya bisa dipakai lewat chat pribadi (bukan grup).
Berikut adalah fitur-fitur baru yang telah ditambahkan untuk meningkatkan kemampuan bot:
- Gunakan perintah
cari <keyword>untuk mencari transaksi berdasarkan kata kunci dalam deskripsi atau nama item. - Contoh:
cari parkirakan menampilkan semua transaksi yang mengandung kata "parkir".
- Pada beberapa flow (contoh:
laporan, preview transaksi, dan pilih kategori), bot akan mengirim List/Buttons agar lebih enak ditap. - Jika perangkat tidak mendukung, bot otomatis fallback ke perintah teks biasa.
- Gunakan perintah
edit transaksi terakhir jumlah <jumlah baru>untuk mengubah nominal transaksi terakhir. - Contoh:
edit transaksi terakhir jumlah 75000akan mengubah nominal transaksi terakhir menjadi 75.000.
- Setiap transaksi dapat dicatat dalam mata uang yang berbeda (IDR, USD, EUR).
- Gunakan perintah
set currency <kode>untuk mengubah preferensi mata uang Anda (contoh:set currency USD). - Laporan otomatis akan dikonversi ke mata uang yang Anda pilih.
- Gambar struk akan diproses terlebih dahulu menggunakan
jimp(grayscale, normalize, kontras, denoise ringan) sebelum dikenali oleh EasyOCR. - Meningkatkan akurasi pengenalan teks pada gambar dengan pencahayaan buruk atau noise.
- EasyOCR mencoba auto-rotate (0/90/180/270) dan akan fallback ke gambar mentah jika hasil preprocessing kosong.
- Ada post-processing untuk memperbaiki karakter yang sering tertukar (contoh:
01G→BIG,7OOGR→700GR).
Env terkait OCR:
OCR_TIMEOUT_MS(default 120000)PYTHON_BIN(defaultpython)OCR_LEXICON_EXTRA(opsional, daftar kata dipisah koma untuk koreksi OCR, contoh:OCR_LEXICON_EXTRA=INDOMARET,NISSIN,TANGO)OCR_DEBUG_SAVE(opsional, simpan output OCR mentah & postprocess)
Evaluasi OCR batch:
node scripts/ocr_eval.js path\to\folder\images- Hasil pemrosesan AI untuk teks yang sama akan disimpan dalam cache menggunakan
lru-cache. - Mengurangi jumlah panggilan API dan mempercepat respons untuk permintaan yang berulang.
- Tabel
transactionssekarang memiliki kolomcurrency(CHAR(3)) untuk menyimpan mata uang transaksi. - Tabel
user_settingsuntuk menyimpan preferensi mata uang per pengguna.
- Setiap pencatatan berada di dalam sebuah akun (
accounts). - Owner bisa membagikan token agar orang lain bisa melihat laporan/pencarian (mode monitoring/read-only).
- Aksi yang mengubah data (mencatat, edit, batal) akan ditolak saat sedang mode monitoring.
- Untuk sharing yang lebih aman per orang, owner bisa pakai
invite(token single-use) dan mencabut akses denganakses cabut.
Contoh:
- Kamu kirim:
token→ dapat token - Pacar kamu kirim:
pakai token <token-kamu>→ bisa lihatlaporandancari ...
- Setelah kamu kirim transaksi (teks/foto struk), bot akan mengirim preview dulu.
- Balas
okuntuk menyimpan ataubataluntuk membatalkan. - Jika ada validasi yang gagal, bot akan minta diperbaiki (atau gunakan
ok paksa). - Bot juga mendukung Interactive Messages (List/Buttons) untuk aksi cepat (OK/Batal/Lihat) dan pilih kategori/periode (jika client mendukung).
- Bisa koreksi sebelum simpan:
ubah transaksi <n> jumlah <angka>ubah transaksi <n> kategori <teks>ubah transaksi <n> keterangan <teks>ubah transaksi <n> tanggal YYYY-MM-DDubah transaksi <n> item tambah <nama> <qty> <harga>ubah transaksi <n> item ubah <no> <qty> <harga>ubah transaksi <n> item hapus <no>
- Export transaksi jadi CSV untuk periode tertentu.
- Mode ringkas:
export ringkas bulan ini - Mode detail per-item:
export detail bulan ini - Range custom:
export 2026-03-01 2026-03-31 - Secara default kolom
receipt_pathtidak ditampilkan. Aktifkan dengan envEXPORT_INCLUDE_RECEIPT_PATH=true.
- Fitur retention bersifat opsional (default nonaktif) agar struk tetap tersedia untuk kebutuhan audit.
- Aktifkan dengan env
RECEIPT_RETENTION_DAYS(mis.RECEIPT_RETENTION_DAYS=30) untuk menghapus struk lama setelah N hari.
- Kirim
struk terakhiruntuk mendapatkan file struk terakhir yang tersimpan.
- Set budget:
budget set <kategori> <jumlah> - Lihat status:
budget list - Notifikasi otomatis saat pemakaian budget melewati 80% dan 100% (dikirim saat transaksi tersimpan).
- Ringkasan harian otomatis (sekitar jam 21:00).
- Ringkasan mingguan otomatis (Senin sekitar jam 09:00, untuk minggu sebelumnya).
- Tambah:
ulang tambah <in|out> <jumlah> <kategori> ; <keterangan> ; <tgl 1-28> - Lihat:
ulang list - Nonaktif:
ulang hapus <id>
- Jika struk yang sama terkirim lagi, bot akan memberi peringatan “kemungkinan duplikat” di preview.
- Deteksi menggunakan kombinasi hash gambar, hash teks OCR, dan fingerprint transaksi.
- Perubahan penting (buat invite, join token, insert/edit/hapus transaksi) dicatat di tabel
audit_logs.
/healthstatus 503- Cek
schema.missingTables/missingColumnsdi response. - Cek Python EasyOCR (
python -c "import easyocr; print(1)") dan pastikanPYTHON_BINsesuai.
- Cek
- OCR lambat/timeout
- Naikkan
OCR_TIMEOUT_MS(contoh180000) dan coba lagi. - Aktifkan
OCR_DEBUG_SAVE=trueuntuk menyimpan hasil OCR mentah & postprocess dipublic/uploads/ocr_debug.
- Naikkan
- Error “Unknown column …”
- Restart aplikasi supaya
ensureSchema()menjalankan migrasi kolom yang missing.
- Restart aplikasi supaya
- Backup (contoh MySQL):
mysqldump -u <user> -p <db_name> > backup.sql
- Restore:
mysql -u <user> -p <db_name> < backup.sql
- Poin 2 (WhatsApp Cloud API) dan poin 3 (Dashboard admin) disimpan sebagai milestone berikutnya untuk stabilitas dan UX admin.