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 + +
+ +- :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. + +
+ +## 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 + +
+ +- :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. + +
+ +## 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). diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..0f81271 --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,207 @@ +# Installation Guide + +This guide will walk you through installing, verifying, and uninstalling Spendwise Tracker. + +## Requirements + +Before installing Spendwise Tracker, ensure your system meets the following requirements: + +- **Python**: Version 3.11 or higher +- **Operating System**: macOS, Linux, or Windows +- **uv**: Package installer (installation instructions below) + +## Installing uv + +Spendwise Tracker is distributed as a Python package and is best installed using [uv](https://docs.astral.sh/uv/), a fast Python package installer and resolver. + +=== "macOS / Linux" + + ```bash + curl -LsSf https://astral.sh/uv/install.sh | sh + ``` + +=== "Windows" + + ```powershell + powershell -c "irm https://astral.sh/uv/install.ps1 | iex" + ``` + +After installation, you may need to restart your terminal or add uv to your PATH. + +## Installing Spendwise Tracker + +Once you have `uv` installed, you can install Spendwise Tracker using the `uv tool install` command: + +```bash +uv tool install spendwise-tracker +``` + +This command will: + +1. Download the latest version of Spendwise Tracker from PyPI +2. Install it in an isolated environment +3. Make the `expense-tracker` command available in your terminal + +### Installing a Specific Version + +To install a specific version, use: + +```bash +uv tool install spendwise-tracker==0.1.0 +``` + +Check the [Releases](https://github.com/7174Andy/expense-tracker/releases) page for available versions. + +## Verifying the Installation + +After installation, verify that Spendwise Tracker is working correctly: + +### 1. Launch the Application + +Start the application to ensure the GUI launches properly: + +```bash +expense-tracker +``` + +The Spendwise Tracker GUI window should open. If the application starts successfully, the installation is complete! + +### 2. Verify Database Location + +On first launch, Spendwise Tracker will create its database files in a platform-specific location: + +=== "macOS" + + ``` + ~/Library/Application Support/spendwise-tracker/ + ``` + +=== "Linux / Unix" + + ``` + ~/.local/share/spendwise-tracker/ + ``` + +=== "Windows" + + ``` + %LOCALAPPDATA%\spendwise-tracker\ + ``` + +You can verify these directories exist after launching the application once. + +## Troubleshooting + +### Command Not Found + +If you get a "command not found" error after installation: + +1. **Check if uv's bin directory is in your PATH**: + + === "macOS / Linux" + + ```bash + echo $PATH + ``` + + === "Windows" + + ```powershell + echo %PATH% + ``` + +2. **Add uv's bin directory to your PATH**: + + === "macOS / Linux" + + Add to `~/.bashrc` or `~/.zshrc`: + + ```bash + export PATH="$HOME/.local/bin:$PATH" + ``` + + === "Windows" + + uv typically adds itself to PATH automatically during installation. + +3. **Restart your terminal** and try again + +### Python Version Issues + +If you encounter Python version errors: + +```bash +# Check your Python version +python --version +``` + +Or: + +```bash +python3 --version +``` + +Ensure Python 3.11 or higher is installed. If not, install or update Python before proceeding. + +### Permission Errors + +On macOS/Linux, if you encounter permission errors, ensure you're not using `sudo`. The `uv tool install` command should work without elevated privileges. + +## Updating Spendwise Tracker + +To update to the latest version: + +```bash +uv tool upgrade spendwise-tracker +``` + +To update to a specific version: + +```bash +uv tool install spendwise-tracker==0.2.0 --force +``` + +## Uninstalling Spendwise Tracker + +### Uninstall the Application + +To remove Spendwise Tracker from your system: + +```bash +uv tool uninstall spendwise-tracker +``` + +This will remove the application but **will not delete your data**. + +### Remove User Data + +If you also want to delete your transaction data and merchant categories, manually remove the data directory: + +=== "macOS" + + ```bash + rm -rf ~/Library/Application\ Support/spendwise-tracker/ + ``` + +=== "Linux / Unix" + + ```bash + rm -rf ~/.local/share/spendwise-tracker/ + ``` + +=== "Windows" + + ```powershell + Remove-Item -Recurse -Force "$env:LOCALAPPDATA\spendwise-tracker" + ``` + +!!! warning "Data Loss Warning" + +Deleting the data directory will permanently remove all your transactions, merchant categories, and settings. This action cannot be undone. Make sure to back up your data if needed before proceeding. + +## Getting Help + +If you encounter issues not covered in this guide: + +1. Check the [GitHub Issues](https://github.com/7174Andy/expense-tracker/issues) page +2. Open a new issue with details about your problem diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..9fbc037 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,69 @@ +site_name: Spendwise Documentation +site_url: https://7174Andy.github.io/spendwise +theme: + name: material + icon: + repo: fontawesome/brands/github + palette: + # Palette toggle for dark mode + - scheme: slate + primary: deep orange + toggle: + icon: material/brightness-4 + name: Switch to light mode + + # Palette toggle for light mode + - scheme: default + primary: deep orange + toggle: + icon: material/brightness-7 + name: Switch to dark mode + +markdown_extensions: + # Python Markdown extensions + - abbr + - admonition + - attr_list + - def_list + - footnotes + - md_in_html + - tables + - toc: + permalink: true + toc_depth: 3 + + # PyMdown Extensions + - pymdownx.arithmatex: + generic: true + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.details + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.highlight: + anchor_linenums: true + line_spans: __span + pygments_lang_class: true + - pymdownx.inlinehilite + - pymdownx.keys + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.snippets + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tabbed: + alternate_style: true + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tilde + +nav: + - Home: index.md + - Installation: installation.md + - Getting Started: getting-started.md + - Categorization: categorization.md diff --git a/pyproject.toml b/pyproject.toml index 6f2a4db..7d7fa7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,8 +17,13 @@ dependencies = [ [project.optional-dependencies] dev = [ - "pytest>=8.4.2", - "ruff>=0.14.4", + "pytest", + "ruff", +] + +docs = [ + "mkdocs-material", + "mike", ] [project.scripts]