Skip to content

Latest commit

Β 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ“Έ SpendSnap AI

Your Financial Memory

FastAPI React Native TypeScript Python License: MIT

Stop losing receipts. Start understanding your money.
SpendSnap turns any receipt photo, UPI screenshot, or bank PDF into a searchable, categorized expense record β€” automatically.


✨ What It Does

Input β†’ Output
πŸ“· Receipt photo OCR + regex parsing { merchant, amount, date, category, source_type }
πŸ–ΌοΈ UPI/bank screenshot Filename heuristic + OCR Labelled source_type: "screenshot"
πŸ“„ PDF bank statement pdfplumber β†’ Vision fallback Full transaction history
πŸ’¬ Bank SMS text Regex + normalisation { merchant, amount, date, category, source_type: "sms" }

Current Phase: Month 1 core pipeline β€” input β†’ OCR/PDF extraction β†’ parsed JSON β†’ database.


πŸ—οΈ Architecture

spendsnap/
β”œβ”€β”€ Run_SpendSnap_Dashboard.bat       # One-click Windows launcher
β”‚
β”œβ”€β”€ backend/                          # Python Β· FastAPI
β”‚   β”œβ”€β”€ main.py                       # API routes: upload, list, update, delete
β”‚   β”œβ”€β”€ ocr.py                        # Vision API + Mock OCR + PDF extraction + date parser
β”‚   β”œβ”€β”€ models.py                     # Receipt & Expense ORM (SQLAlchemy)
β”‚   β”œβ”€β”€ schemas.py                    # Pydantic request/response schemas
β”‚   β”œβ”€β”€ database.py                   # Session management (SQLite β†’ Postgres-ready)
β”‚   β”œβ”€β”€ config.py                     # pydantic-settings + .env
β”‚   β”œβ”€β”€ index.html                    # Browser dashboard (served at /)
β”‚   β”œβ”€β”€ test_pipeline.py              # Integration test suite
β”‚   β”œβ”€β”€ requirements.txt
β”‚   β”œβ”€β”€ sms_parsers/                  # Bank SMS normalisation (HDFC, ICICI, SBI, Paytm)
β”‚   └── data/
β”‚       └── merchants.json            # Indian merchant β†’ category lookup (Phase 3)
β”‚
└── mobile/                           # TypeScript Β· React Native Β· Expo SDK 56
    β”œβ”€β”€ App.tsx                       # Camera upload, dark-mode feed, edit modal
    β”œβ”€β”€ index.ts                      # Expo entry point
    β”œβ”€β”€ app.json                      # Expo app config
    └── package.json

Data flow:

[Camera / Gallery / PDF]
        β”‚
        β–Ό
POST /api/upload
        β”‚
   β”Œβ”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚ Image?            PDF?          β”‚
   β”‚  Google Vision    pdfplumber    β”‚
   β”‚  (mock fallback)  (Vision fallback for scanned)
   β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
        β”‚ raw_text
        β–Ό
  Regex Parser
  merchant Β· amount Β· transaction_date (OCR-extracted)
        β”‚
        β–Ό
  SQLite / Postgres
  Receipt + Expense rows
  (source_type Β· user_id stub Β· ai fields ready)

πŸš€ Quick Start

Option A β€” Windows One-Click (No CLI needed)

Double-click:  Run_SpendSnap_Dashboard.bat

This will:

  1. Start the FastAPI backend in a minimised background window
  2. Open http://127.0.0.1:8000 in your default browser
  3. Keep a control window open β€” press any key to stop the server

πŸ’‘ Test without real receipts: Upload any image named swiggy, starbucks, fuel, amazon, or canteen to trigger realistic mock receipt templates. Name it phonepe_screenshot_... to test screenshot source detection.


Option B β€” Manual CLI

1. Backend

cd backend
python -m venv venv
.\venv\Scripts\activate          # Windows
# source venv/bin/activate       # macOS / Linux

pip install -r requirements.txt
uvicorn main:app --reload --host 127.0.0.1 --port 8000

Interactive API docs: http://127.0.0.1:8000/docs

2. Mobile (Expo)

cd mobile
npm install
npm run start
Key Action
a Open Android emulator
i Open iOS simulator
Scan QR Open in Expo Go on physical device

3. Integration Tests

cd backend
.\venv\Scripts\python test_pipeline.py

Tests covered:

  • βœ… Health check (OCR mode, DB type, upload limit)
  • βœ… Oversized file rejection (HTTP 413)
  • βœ… Unsupported file type rejection (HTTP 415)
  • βœ… Swiggy receipt upload β€” merchant, amount, transaction_date, source_type
  • βœ… Screenshot source_type detection from filename
  • βœ… Expense list ordering
  • βœ… Expense update (including source_type and category)
  • βœ… Expense delete + verify removal

βš™οΈ Configuration

Create backend/.env to override any default:

# ── Database ─────────────────────────────────────────────────
# Default: local SQLite. Switch to Postgres for production.
DATABASE_URL=postgresql://user:password@localhost:5432/spendsnap

# ── OCR ──────────────────────────────────────────────────────
# Omit to use Mock OCR (no credentials needed for local dev).
GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account.json

# ── Uploads ──────────────────────────────────────────────────
MAX_UPLOAD_SIZE_MB=10

# ── CORS ─────────────────────────────────────────────────────
# Add your production domain when deploying.
# Default allows localhost:8081 (Expo) and localhost:3000.
CORS_ORIGINS=["https://app.yourdomain.com","http://localhost:8081"]

πŸ”Œ API Reference

Method Endpoint Description
GET / Browser dashboard UI
GET /api/health Server status, OCR mode, upload limit
POST /api/upload Upload image or PDF β†’ returns parsed expense
POST /api/expenses/sms Parse bank SMS text β†’ returns parsed expense
GET /api/expenses All expenses, ordered by receipt date
PUT /api/expenses/{id} Correct any field (merchant, amount, category, source_type)
DELETE /api/expenses/{id} Remove expense + deletes image file from disk

Upload response shape:

{
  "receipt": {
    "id": 1,
    "file_path": "backend/uploads/uuid.png",
    "raw_text": "Swiggy Delivery Receipt\n...",
    "created_at": "2026-06-20T13:42:00Z"
  },
  "expense": {
    "id": 1,
    "merchant": "Bundl Technologies Private Ltd",
    "amount": 349.0,
    "category": "Uncategorized",
    "transaction_date": "2026-06-20T13:42:00",
    "source_type": "photo",
    "ai_suggested_category": null,
    "category_confidence": null,
    "user_id": null,
    "created_at": "2026-06-21T10:00:00Z"
  }
}

Accepted file types: .jpg, .jpeg, .png, .webp, .pdf
Max upload size: 10 MB (configurable via MAX_UPLOAD_SIZE_MB)


πŸ—„οΈ Data Model

Expense table

Column Type Description
id int Primary key
receipt_id int FK Linked receipt row
merchant string Extracted from first OCR line
amount float Largest/labelled total on receipt
transaction_date datetime? Date extracted from OCR text (not upload time)
category string "Uncategorized" until Phase 3
source_type string photo | screenshot | pdf | sms
ai_suggested_category string? Populated by Claude in Phase 3
category_confidence float? AI confidence score (0.0–1.0)
user_id string? Auth stub β€” wired up in Phase 2
created_at datetime Upload timestamp

πŸ—ΊοΈ Roadmap

Phase Weeks Status Milestone
1 β€” Core Pipeline 1–3 βœ… Done Image/PDF β†’ OCR β†’ DB with full audit fields
2 β€” Mobile Shell 3–5 πŸ”„ In progress Camera picker, upload UX, user auth
3 β€” Smart Features 5–10 πŸ“‹ Planned Claude AI categorisation, subscription detection, weekly summaries
4 β€” Warranty Vault 10–14 πŸ“‹ Planned Product parsing, warranty tracking, push notifications

Next up (Phase 2):

  • Upload progress bar + offline queue for slow connections
  • Auth via Supabase β€” wire user_id to expense rows
  • Supabase Storage for receipt images (replace local file_path)
  • Bank SMS normalisation layer (sms_parsers/hdfc.py, sms_parsers/icici.py, …)

πŸ› οΈ Tech Stack

Layer Technology Reason
Mobile React Native + Expo SDK 56 Single codebase, camera + file picker, TypeScript
Backend FastAPI (Python) Python-native OCR/AI libs, async I/O
OCR Google Cloud Vision Best Hindi/regional text and messy fonts
PDF pdfplumber + PyMuPDF Machine-readable first; renders scanned pages as fallback
Database SQLite β†’ Postgres-ready Zero-config dev, production-grade swap
ORM SQLAlchemy 2.0 Type-safe queries
Validation Pydantic v2 Schema enforcement, .env settings

🀝 Contributing

  1. Fork β†’ branch off main
  2. Follow the phase order β€” don't build Phase 3 features before Phase 2 is solid
  3. Test with at least 5 real receipt images before opening a PR
  4. When you encounter a new Indian merchant name, add it to backend/data/merchants.json

πŸ“„ License

MIT Β· Built with β˜• and too many Indian restaurant bills.

About

The problem with most expense trackers is that they assume people will manually enter expenses. Nobody does that for more than a week. Spendsnap is the suggested solution.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages