diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..e965576 --- /dev/null +++ b/.github/workflows/docs.yml @@ -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 diff --git a/.gitignore b/.gitignore index 2a50af5..60e4961 100644 --- a/.gitignore +++ b/.gitignore @@ -45,4 +45,7 @@ uv.lock .vscode/ # DS_Store files -.DS_Store \ No newline at end of file +.DS_Store + +# MkDocs build output +site/ diff --git a/docs/categorization.md b/docs/categorization.md new file mode 100644 index 0000000..510f2fe --- /dev/null +++ b/docs/categorization.md @@ -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. diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..cc025e4 --- /dev/null +++ b/docs/getting-started.md @@ -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 diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..e8f4c7f --- /dev/null +++ b/docs/index.md @@ -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 + +