Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Deploy MkDocs to Github Pages

on:
release:
types:
- published
push:
branches:
- main
permissions:
contents: write

jobs:
docs:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up UV
uses: astral-sh/setup-uv@v6

- name: Install Dependencies
run: |
uv sync --extra dev --extra docs

- name: Set up git user
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"

- name: Build and upload docs (release)
if: ${{ github.event_name == 'release' && github.event.action == 'published' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
uv run mike deploy --update-aliases --allow-empty --push "${{ github.event.release.tag_name }}" latest

- name: Build and upload docs (dev)
if: ${{ github.event_name == 'push' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
uv run mike deploy --update-aliases --allow-empty --push dev
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,7 @@ uv.lock
.vscode/

# DS_Store files
.DS_Store
.DS_Store

# MkDocs build output
site/
83 changes: 83 additions & 0 deletions docs/categorization.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Categorization

Spendwise automatically categorizes transactions by recognizing merchant names. This page explains how the system works and how you can teach it new categories.

## How It Works

When a transaction is imported or added, Spendwise assigns a category through the following steps:

```mermaid
flowchart TD
A[New transaction] --> B{Amount > 0?}
B -- Yes --> C[Assign 'Income']
B -- No --> D[Normalize merchant name]
D --> E{Exact match in database?}
E -- Yes --> F[Use stored category]
E -- No --> G{Fuzzy match ≥ 90%?}
G -- Yes --> F
G -- No --> H[Assign 'Uncategorized']
```

### Step 1: Income Detection

If the transaction amount is positive, it is automatically categorized as **Income** regardless of the merchant name.

### Step 2: Merchant Normalization

For expenses, Spendwise normalizes the raw merchant description to create a consistent lookup key. Normalization includes:

- Converting to uppercase
- Removing digits and special characters (`#`, `*`)
- Stripping common words like `PENDING`, `MOBILE`, `PURCHASE`
- Removing trailing state abbreviations (e.g., `CA`, `NY`)
- Collapsing extra whitespace

For example:

| Raw Description | Normalized Key |
|-------------------------------------|--------------------|
| `PENDING STARBUCKS #1234 CA` | `STARBUCKS` |
| `Mobile Purchase AMAZON.COM 56789` | `AMAZON.COM` |
| `TRADER JOE'S #567 LOS ANGELES CA` | `TRADER JOE'S LOS ANGELES` |

### Step 3: Exact Match

The normalized key is compared against stored merchant-category mappings in the database. If an exact match is found, that category is used.

### Step 4: Fuzzy Match

If no exact match exists, Spendwise uses fuzzy string matching (powered by [rapidfuzz](https://github.com/rapidfuzz/RapidFuzz)) to find the closest known merchant. A match is accepted only if the similarity score is **90% or higher**.

This handles minor variations in how the same merchant appears across statements, such as:

- `STARBUCKS` vs `STARBUCKS COFFEE`
- `AMAZON.COM` vs `AMAZON COM`

If no match meets the 90% threshold, the transaction is labeled **Uncategorized**.

## Teaching Spendwise New Categories

You train the categorization system simply by editing transactions:

1. **Double-click** a transaction (or select it and click **Edit Transaction**)
2. Change the **Category** field to your preferred category (e.g., `Groceries`, `Dining`, `Transport`)
3. Click **Save**

When you save a category change, two things happen:

1. **The merchant mapping is saved** -- Spendwise stores the normalized merchant name with its new category
2. **Uncategorized transactions are re-evaluated** -- All existing transactions marked as "Uncategorized" are checked against the updated mappings, and any that match (exact or fuzzy) are automatically recategorized

!!! example
You edit a Starbucks transaction and change its category from "Uncategorized" to "Coffee". Spendwise saves the mapping `STARBUCKS → Coffee`. All other uncategorized Starbucks transactions are instantly recategorized to "Coffee" as well.

## Category Suggestions

When you open the edit dialog for an uncategorized transaction, Spendwise checks if a mapping already exists for that merchant's normalized name. If a match is found, the category field is pre-filled with the suggested category -- you can accept it by clicking **Save** or type a different one.

## Tips for Effective Categorization

- **Categorize early** -- The more merchant mappings Spendwise learns, the fewer uncategorized transactions you'll see on future imports.
- **Be consistent** -- Use the same category names across merchants (e.g., always use "Dining" rather than mixing "Dining", "Restaurants", and "Eating Out").
- **Let fuzzy matching work for you** -- You don't need to categorize every slight variation of a merchant. Once you categorize `STARBUCKS`, variations like `STARBUCKS COFFEE` will match automatically.
- **Review after importing** -- After importing a new statement, scan for "Uncategorized" transactions and assign categories. Each one teaches Spendwise for future imports.
99 changes: 99 additions & 0 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Getting Started

This guide walks you through launching Spendwise for the first time, importing your first bank statement, and navigating the interface.

## Launching the Application

After [installing](installation.md) Spendwise, start it from your terminal:

```bash
expense-tracker
```

The main window opens with three tabs: **Transactions**, **Statistics**, and **Heatmap**.

## Importing a Bank Statement

The fastest way to populate Spendwise is by importing a Bank of America PDF statement.

### 1. Download Your Statement

Log in to your Bank of America account and download a monthly statement as a PDF.

!!! note
Only Bank of America PDF statements are supported at this time. Other bank formats will not be parsed correctly.

### 2. Import the PDF

1. In the **Transactions** tab, click **Import Statement** (top-right of the toolbar)
2. Click **Browse** and select your downloaded PDF
3. Click **Upload**

Spendwise extracts each transaction from the PDF and automatically categorizes them using its [merchant categorization system](categorization.md). A success message confirms the import.

### 3. Review Your Transactions

After importing, your transactions appear in the table with the following columns:

| Column | Description |
|-------------|--------------------------------------------------|
| Date | Transaction date |
| Amount | Negative for expenses, positive for income |
| Category | Auto-assigned category (or "Uncategorized") |
| Description | Original merchant description from the statement |

## Adding a Transaction Manually

You can also add transactions by hand:

1. Click **Add Transaction** in the toolbar
2. Fill in the amount, category, and description (the date defaults to today)
3. Click **Save**

## Editing a Transaction

To correct a transaction's details or update its category:

1. **Double-click** a transaction in the table (or select it and click **Edit Transaction**)
2. Modify the amount, category, or description
3. Click **Save**

!!! tip
When you change a transaction's category, Spendwise remembers the mapping and automatically applies it to other uncategorized transactions from the same merchant. See [Categorization](categorization.md) for details.

## Deleting Transactions

1. Select one or more transactions in the table
2. Click **Delete Transaction**
3. Confirm the deletion in the dialog

## Searching Transactions

Use the search bar in the toolbar to filter transactions by keyword:

1. Type a keyword (e.g., a merchant name or category) into the search field
2. Press ++enter++ or click **Search**
3. Click **Clear Search** to remove the filter

## Browsing Pages

Transactions are displayed 100 per page, sorted by date (newest first). Use the **Previous** and **Next** buttons at the bottom to navigate between pages.

## Viewing Statistics

Switch to the **Statistics** tab to see monthly summaries:

- **Net income** for the selected month
- **Top spending categories** ranked by total amount
- Use the **<** and **>** buttons to browse between months

## Viewing the Spending Heatmap

Switch to the **Heatmap** tab for a calendar visualization of your daily spending:

- Darker colors indicate higher spending days
- Click on any day to jump to the **Transactions** tab filtered to that date

## Next Steps

- Learn how [Categorization](categorization.md) works to keep your transactions organized automatically
120 changes: 120 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Spendwise Expense Tracker

**Take control of your spending.** Spendwise is an open-source desktop app that imports your Bank of America PDF statements, automatically categorizes transactions, and visualizes your spending patterns -- all locally on your machine.

[Get Started](getting-started.md){ .md-button .md-button--primary }
[Installation](installation.md){ .md-button }

---

## Features

<div class="grid cards" markdown>

- :material-file-pdf-box:{ .lg .middle } **PDF Statement Import**

---

Import Bank of America PDF statements and automatically extract every transaction -- no manual data entry needed.

- :material-tag-text:{ .lg .middle } **Smart Categorization**

---

Intelligent merchant recognition using fuzzy matching with a 90% accuracy threshold. Categorize once, and Spendwise remembers.

[:octicons-arrow-right-24: How it works](categorization.md)

- :material-table-edit:{ .lg .middle } **Transaction Management**

---

Add, edit, delete, and search transactions with a clean tabular interface and pagination.

- :material-chart-bar:{ .lg .middle } **Monthly Statistics**

---

View net income and top spending categories by month to understand where your money goes.

- :material-calendar-month:{ .lg .middle } **Spending Heatmap**

---

Interactive calendar visualization with color-coded daily spending. Click any day to drill into its transactions.

- :material-sync:{ .lg .middle } **Auto-Recategorization**

---

Update a merchant's category once, and all matching uncategorized transactions are instantly recategorized.

</div>

## Quick Install

Install with [uv](https://docs.astral.sh/uv/) in two commands:

=== "macOS / Linux"

```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install spendwise-tracker
```

=== "Windows"

```powershell
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
uv tool install spendwise-tracker
```

Then launch the app:

```bash
expense-tracker
```

!!! tip "Need more details?"
See the full [Installation Guide](installation.md) for version pinning, troubleshooting, and uninstall instructions.

## Quick Start

<div class="grid cards" markdown>

- :material-numeric-1-circle:{ .lg .middle } **Import a statement**

---

Click **Import Statement** in the toolbar, select a Bank of America PDF, and your transactions appear instantly.

- :material-numeric-2-circle:{ .lg .middle } **Review & categorize**

---

Double-click any transaction to edit its category. Spendwise learns and applies the mapping to future imports.

- :material-numeric-3-circle:{ .lg .middle } **Search & browse**

---

Use the search bar to filter by keyword. Navigate pages with **Previous** / **Next** (100 transactions per page).

- :material-numeric-4-circle:{ .lg .middle } **Explore your data**

---

Switch to the **Statistics** tab for monthly summaries or the **Heatmap** tab for a calendar view of daily spending.

</div>

## Requirements

| | Requirement |
|---|---|
| :material-language-python: | Python 3.11 or higher |
| :material-desktop-classic: | macOS, Linux, or Windows |

## License

Spendwise is released under the [MIT License](https://github.com/7174Andy/expense-tracker/blob/main/LICENSE).
Loading