<div align="center">

# SmartWallet

A terminal-based personal finance tracker with a tree-structured budget system.

![App Screenshot](docs/screenshot.png)

<p>
  <img src="https://img.shields.io/badge/Python_3.12-3776ab?style=for-the-badge&logo=python&logoColor=white" alt="Python" />
  <img src="https://img.shields.io/badge/Textual_TUI-1a1a2e?style=for-the-badge" alt="Textual" />
  <img src="https://img.shields.io/badge/JSON-000000?style=for-the-badge&logo=json&logoColor=white" alt="JSON" />
</p>
<p>
  <img src="https://img.shields.io/badge/uv-de5fe9?style=for-the-badge" alt="uv" />
  <img src="https://img.shields.io/badge/pytest-0a9edc?style=for-the-badge&logo=pytest&logoColor=white" alt="pytest" />
  <img src="https://img.shields.io/badge/ruff-d7ff64?style=for-the-badge&logo=ruff&logoColor=black" alt="ruff" />
</p>

</div>

## Overview

SmartWallet is an offline-first TUI application for managing personal finances. It organizes income and expenses in a hierarchical tree structure — categories can nest infinitely (e.g., Home -> Bills -> Electricity), and each leaf holds a signed transaction. The entire budget persists locally as a JSON file with schema versioning.

Built as a university project demonstrating the **Composite** and **Factory Method** design patterns with a clean MVC architecture separating business logic from the Textual-powered terminal UI.

## Features

- **Tree-structured budget** — infinite category nesting with recursive balance calculation
- **Modern TUI** — custom dark theme with color-coded income/expenses
- **Keyboard-driven** — modal dialogs for add, edit, delete, and navigation
- **Offline-first** — all data stored locally in `~/.smartwallet/budget.json`
- **Schema versioning** — safe data migrations for future releases
- **27 unit tests** — full coverage of model, factory, and persistence layers

## Installation

Requires [uv](https://docs.astral.sh/uv/getting-started/installation/) (recommended) or [pipx](https://pipx.pypa.io/stable/installation/).

Install as a standalone CLI tool (isolated environment, added to PATH):

```bash
uv tool install smartwallet
```

Or with pipx:

```bash
pipx install smartwallet
```

Then run:

```bash
smartwallet
```

To upgrade or uninstall:

```bash
uv tool upgrade smartwallet    # or: pipx upgrade smartwallet
uv tool uninstall smartwallet  # or: pipx uninstall smartwallet
```

## Local Setup (development)

1. Clone the repository:
   ```bash
   git clone https://github.com/alwoodm/smartwallet.git
   cd smartwallet
   ```
2. Install dependencies (requires [uv](https://docs.astral.sh/uv/)):
   ```bash
   uv sync
   ```
3. Run the application:
   ```bash
   uv run smartwallet
   ```

## Keybindings

| Key         | Action              |
|-------------|---------------------|
| `a`         | Add subcategory     |
| `t`         | Add transaction     |
| `e`         | Edit selected       |
| `d`         | Delete selected     |
| `Tab`       | Next tree node      |
| `Shift+Tab` | Previous tree node  |
| `q`         | Quit                |

## Development

```bash
uv run ruff check .          # Lint
uv run ruff format --check . # Format check
uv run pytest                # Run tests
uv run pytest --cov          # Tests with coverage
uv build                     # Build package
```

## Architecture

The project follows an **MVC** architecture with four independent modules:

| Module         | Location                         | Responsibility                          |
|----------------|----------------------------------|-----------------------------------------|
| **Model**      | `src/smartwallet/model/`         | Data structures, balance calculation    |
| **Factory**    | `src/smartwallet/factory/`       | Validated object creation               |
| **Persistence**| `src/smartwallet/persistence.py` | JSON serialization/deserialization      |
| **UI**         | `src/smartwallet/ui/`            | Textual TUI (screens, widgets, modals)  |

For detailed documentation including design pattern analysis, see [`docs/architecture.md`](docs/architecture.md).

## License

This project is licensed under the [MIT](LICENSE) license.
