# Expense Tracker with SQLite

This utility is a command-line expense tracker that stores data in a local SQLite database. It allows you to add, view, and delete expenses, providing a persistent record of your spending without needing a complex server setup.

**Modules Used:**
*   [[programming/python/modules/sqlite3-module|sqlite3]]: To interact with the SQLite database.
*   [[programming/python/modules/argparse-module|argparse]]: To handle command-line arguments.
*   `datetime`: To timestamp entries.

## The Code

Save this as `expense_tracker.py`.

```python
import sqlite3
import argparse
from datetime import datetime
import sys

DB_NAME = "expenses.db"

def init_db():
    """Initialize the database and create the table if it doesn't exist."""
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS expenses
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                  date TEXT,
                  category TEXT,
                  amount REAL,
                  description TEXT)''')
    conn.commit()
    conn.close()

def add_expense(amount, category, description):
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    c.execute("INSERT INTO expenses (date, category, amount, description) VALUES (?, ?, ?, ?)",
              (date, category, amount, description))
    conn.commit()
    conn.close()
    print(f"Added: ${amount:.2f} for {category}")

def view_expenses(category=None):
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    
    if category:
        c.execute("SELECT * FROM expenses WHERE category = ?", (category,))
    else:
        c.execute("SELECT * FROM expenses")
        
    rows = c.fetchall()
    conn.close()

    if not rows:
        print("No expenses found.")
        return

    print(f"{'ID':<5} {'Date':<20} {'Category':<15} {'Amount':<10} {'Description'}")
    print("-" * 70)
    
    total = 0
    for row in rows:
        # row: (id, date, category, amount, description)
        print(f"{row[0]:<5} {row[1]:<20} {row[2]:<15} ${row[3]:<9.2f} {row[4]}")
        total += row[3]
        
    print("-" * 70)
    print(f"Total: ${total:.2f}")

def delete_expense(expense_id):
    conn = sqlite3.connect(DB_NAME)
    c = conn.cursor()
    c.execute("DELETE FROM expenses WHERE id = ?", (expense_id,))
    if c.rowcount > 0:
        print(f"Expense {expense_id} deleted.")
    else:
        print(f"Expense {expense_id} not found.")
    conn.commit()
    conn.close()

if __name__ == "__main__":
    init_db()
    
    parser = argparse.ArgumentParser(description="Simple Expense Tracker")
    subparsers = parser.add_subparsers(dest="command", help="Command to run")

    # Add Command
    add_parser = subparsers.add_parser("add", help="Add a new expense")
    add_parser.add_argument("amount", type=float, help="Amount spent")
    add_parser.add_argument("category", help="Category (e.g., Food, Transport)")
    add_parser.add_argument("description", help="Description of the expense")

    # View Command
    view_parser = subparsers.add_parser("view", help="View expenses")
    view_parser.add_argument("--category", help="Filter by category")

    # Delete Command
    del_parser = subparsers.add_parser("delete", help="Delete an expense")
    del_parser.add_argument("id", type=int, help="ID of the expense to delete")

    args = parser.parse_args()

    if args.command == "add":
        add_expense(args.amount, args.category, args.description)
    elif args.command == "view":
        view_expenses(args.category)
    elif args.command == "delete":
        delete_expense(args.id)
    else:
        parser.print_help()
```

## Usage

```bash
# Add expenses
python expense_tracker.py add 15.50 Food "Lunch at diner"
python expense_tracker.py add 50.00 Transport "Gas"

# View all expenses
python expense_tracker.py view

# View only Food expenses
python expense_tracker.py view --category Food

# Delete an expense by ID (find ID from view command)
python expense_tracker.py delete 1
```

[[programming/python/python]]