# quartermaster

Household budget tracker. FastAPI + HTMX frontend, SQLite backend.

## Pages

* `/` budget configuration. One section per category (Incomes, Fixed Amount
  Bills, Debt Minimums, Primary Debt Target, Food and Essentials,
  Subscriptions, Other). Every section accepts name + amount entries and
  shows a running total. The Primary Debt Target is a pointer to a Debt
  Minimums row.
* `/month/YYYY-MM` monthly view. Snapshots the budget at creation time and
  tracks an `applied` amount per entry alongside the planned amount. Each
  row is annotated when its name or planned value has been edited away
  from the snapshot, or when the row was added after creation. Per-month
  debt target is independent of the budget's target after snapshot.

Navigate between months with the prev / next buttons or the dropdown
picker. A "This month" link on `/` jumps to the current `YYYY-MM`; if it
has not been created yet, you land on the create flow.

## Requirements

* Python 3.12+
* [uv](https://github.com/astral-sh/uv) for dependency management

## Setup

```sh
uv sync
uv run alembic upgrade head
```

The SQLite file lives at `./quartermaster.db` by default. Override with the
`QUARTERMASTER_DB_URL` environment variable (any SQLAlchemy URL).

## Run

```sh
uv run uvicorn quartermaster.main:app --reload
```

Open http://127.0.0.1:8000.

## Tests

```sh
uv run pytest
```

Tests run against an in-memory SQLite database; no migration step needed.

## Backups

The SQLite data file is precious and gitignored. Before any schema
change or destructive operation, back it up:

```sh
./scripts/backup-db.sh <reason>
```

Backups land next to the database in `./backups/` by default
(`QUARTERMASTER_BACKUP_DIR=/some/path` to override) as
`quartermaster-YYYYMMDD-HHMMSS-{slug}.db` using SQLite's online backup
API (safe even while the app is writing). Alembic invokes the script
automatically before every migration via `alembic/env.py`; retention
is forever for now. To restore, stop the app, copy the chosen backup
over `quartermaster.db`, and restart.

## Project Layout

```
src/quartermaster/
  main.py            FastAPI app factory
  routes.py          Budget configuration HTTP handlers
  routes_month.py    Monthly view HTTP handlers
  service.py         Budget queries, totals, target logic
  month_service.py   Snapshot, deviation, per-month CRUD
  models.py          SQLAlchemy models and Section enum
  db.py              Engine, session, PRAGMA foreign_keys=ON
  config.py          DB URL resolution
  templates/         Jinja2 templates (base, index, month, partials)
  static/            CSS
alembic/             Migrations
tests/               pytest suite
```

## Deferred

A transaction log that rolls up into `applied` on a per-entry per-month
basis is deferred. Once implemented it may replace the hand-edited applied
field.
