Saturday, March 7, 2026

Project Jugnu

Project Jugnu: Automating Indian Personal Finance with Firefly III and Python

Managing personal finances shouldn't require a daily manual grind. I wanted a lightweight, local-first envelope budgeting tool, but I quickly ran into a major roadblock: standard out-of-the-box (OOTB) tools simply do not play nicely with the Indian banking ecosystem.

Here is how I bypassed the friction of manual CSV uploads and built a custom, automated ingestion pipeline for my home server using Docker, Firefly III, and a custom Python parser I call Project Jugnu.

1. The Problem: Indian Banking vs. Standard APIs

If you use accounts like HDFC, IDFC, or Kotak, or investment platforms like Zerodha and Upstox, you already know the pain. Individual APIs are rarely available for retail banking, meaning you are stuck manually downloading and uploading PDF or CSV statements.

Furthermore, Indian banking SMS alerts are incredibly chaotic. Standard OOTB importers struggle with:

  • Timezone Drift: Defaulting to UTC, which pushes late-night IST transactions into the wrong calendar day.

  • Duplicate Entries: Failing to intelligently link a withdrawal and a deposit as a single "Transfer" when moving money between your own accounts.

I needed a system with less friction.

2. The Architecture: Local-First Ledger

I chose Firefly III as the core engine. It is a fantastic double-entry bookkeeping ledger. To keep my data private, I deployed it on my home server using docker-compose.

Here is the simplified docker-compose.yml stack to get the app and the PostgreSQL database running:

YAML
services:
  app:
    image: 'firefly-iii/core:latest' 
    container_name: firefly_app
    ports:
      - '5006:8080'
    environment:
      - APP_KEY=ThisIsASecretKeyOfExactly32Chars! 
      - DB_CONNECTION=pgsql
      - DB_HOST=db 
      - DB_PORT=5432
      - TZ=Asia/Kolkata 
    depends_on:
      - db

  db:
    image: 'postgres:15-alpine'
    container_name: firefly_db
    environment:
      - POSTGRES_USER=firefly
      - POSTGRES_PASSWORD=secret
      - POSTGRES_DB=firefly
    volumes:
      - ./firefly_db_data:/var/lib/postgresql/data

Pro-Tip: Setting the TZ=Asia/Kolkata environment variable is absolutely critical here to ensure the UI renders your transaction times correctly!

3. The Solution: Enter "Project Jugnu"

To solve the SMS parsing issue, I wrote a custom middleware script specifically tuned for Indian bank formats.

Key Features of Project Jugnu:

  • Native IST Handling: It natively formats timestamps with the +05:30 offset so Firefly III logs the exact local time.

  • The "Catch & Merge" Logic: To avoid duplicate entries when transferring money between two of my own accounts, the script uses the UPI Reference Number. When the second SMS arrives, instead of creating a duplicate entry, it catches the 422 Unprocessable Entity API error and sends a PUT request to merge both alerts into a single, clean "Transfer" transaction.

You can check out the source code and run it yourself here: https://github.com/vikrant-pune/Project-Jugnu

4. Troubleshooting: Finding Your Data

If you ever need to manually inspect your database to fix a botched CSV import, you can connect a SQL client (like DBeaver) to your exposed 5432 port.

Watch out for this common trap: When you connect, you will likely see an empty database named postgres. Do not panic! This is just a default admin database. You need to expand your database list and specifically open the firefly database to find your actual transactions and accounts tables.


No comments:

Post a Comment