diff --git a/ai_brain.py b/ai_brain.py index fe3ee35..30b461d 100644 --- a/ai_brain.py +++ b/ai_brain.py @@ -18,7 +18,7 @@ def get_system_instruction(): SKEMA JSON: [ {{ - "tipe": "pemasukan" | "pengeluaran" | "investasi", + "tipe": "pemasukan" | "pengeluaran" | "investasi" | "saldo", "item": "deskripsi singkat transaksi", "nominal": angka integer, "kategori": {categories_str} @@ -28,10 +28,11 @@ def get_system_instruction(): ATURAN KETAT: 1. Gunakan format LIST [ ... ] meskipun hanya ada satu transaksi. -2. Konversi singkatan angka: "k" / "rb" = 1000, "jt" / "juta" = 1000000. -3. Jika nominal dalam teks (misal: "setengah juta", "seratus ribu"), ubah ke angka integer (misal: 500000, 100000). -4. Fokus pada uang masuk, keluar, atau investasi. -5. Jawaban HANYA berupa JSON murni tanpa teks pengantar. Jika tidak ada transaksi sama sekali, kembalikan [ {{ "error": true }} ]. +2. Gunakan tipe "saldo" jika pengguna menyebutkan total uang/saldo saat ini (misal: "saldo saya 1 juta"). +3. Konversi singkatan angka: "k" / "rb" = 1000, "jt" / "juta" = 1000000. +4. Jika nominal dalam teks (misal: "setengah juta", "seratus ribu"), ubah ke angka integer (misal: 500000, 100000). +5. Fokus pada uang masuk, keluar, atau investasi/saldo. +6. Jawaban HANYA berupa JSON murni tanpa teks pengantar. Jika tidak ada transaksi sama sekali, kembalikan [ {{ "error": true }} ]. """ return instruction diff --git a/database.py b/database.py index 5b6a4bd..9c363ab 100644 --- a/database.py +++ b/database.py @@ -669,3 +669,25 @@ def get_all_transactions_export(month_str=None, user_id=None): finally: cursor.close() conn.close() + +def get_user_balance(user_id): + """ + Menghitung total saldo saat ini dari user (Pemasukan - Pengeluaran - Investasi). + """ + conn = get_connection() + try: + cursor = conn.cursor(dictionary=True) + # Hitung saldo: sum income - sum expense - sum investment + cursor.execute(''' + SELECT + SUM(CASE WHEN tipe = 'pemasukan' THEN nominal ELSE 0 END) - + SUM(CASE WHEN tipe = 'pengeluaran' THEN nominal ELSE 0 END) - + SUM(CASE WHEN tipe = 'investasi' THEN nominal ELSE 0 END) as balance + FROM transactions + WHERE user_id = %s + ''', (user_id,)) + res = cursor.fetchone() + return res['balance'] if res['balance'] is not None else 0 + finally: + cursor.close() + conn.close() diff --git a/handlers/nlp_message.py b/handlers/nlp_message.py index fddeaf5..958c024 100644 --- a/handlers/nlp_message.py +++ b/handlers/nlp_message.py @@ -40,7 +40,30 @@ def handle_text(message): # Save to database based on type try: - if tipe in ["pemasukan", "pengeluaran", "investasi"]: + if tipe == "saldo": + # Reconcile balance + current_balance = database.get_user_balance(user_id) + diff = nominal - current_balance + + if diff == 0: + summary_lines.append(f"💰 *Saldo:* Sudah sesuai di angka Rp {nominal:,.0f}") + success_count += 1 + continue + + # Determine if reconciliation is income or expense + rec_tipe = "pemasukan" if diff > 0 else "pengeluaran" + rec_nominal = abs(diff) + rec_item = "Penyesuaian Saldo" + + last_id = database.insert_transaction(user_id, rec_tipe, rec_item, rec_nominal, "lainnya") + + icon = "💰" + summary_lines.append( + f"{icon} *Saldo disesuaikan:* Rp {current_balance:,.0f} ➔ Rp {nominal:,.0f} (`T-{last_id}`)" + ) + success_count += 1 + + elif tipe in ["pemasukan", "pengeluaran", "investasi"]: last_id = database.insert_transaction(user_id, tipe, item, nominal, kategori) if tipe == "pemasukan":