BenzaTracker
A fuel expense tracker with three interfaces (command line, desktop and web) on one shared core: refuel log, spending KPIs, monthly chart and PDF reports, stored in JSON or SQLite.
- Role
- Author
- When
- October 2025 to present
- Stack
- Python, Flask, SQLite, ttkbootstrap, ReportLab, Docker
Context
"Benza" is Italian slang for petrol. The idea was simple: log every refuel and see what the car really costs to run. It became a small exercise in structuring one Python codebase so the same logic can serve very different front ends.
What I built
Each refuel records the date, litres, amount paid, price per litre, station and odometer reading. From that log the app computes total spending, total litres, average price and monthly average, draws a monthly bar chart with matplotlib and exports a PDF report with ReportLab.
The interesting part is the structure. The domain code (data classes for entries and reports, KPI calculation, PDF export) knows nothing about how it is displayed or stored:
- Storage is behind a small
Storeprotocol with two implementations: a JSON file written atomically, and SQLite. A factory picks one from the environment configuration. - Interfaces are three thin layers over the same core: a terminal CLI, a desktop GUI built with ttkbootstrap, and a Flask web app with Jinja templates. A single entry point (
python -m benzatracker) chooses which one to start. - Deployment: a Dockerfile and Compose file run the web version with the SQLite database on a mounted volume.
Engineering
The project uses the src/ layout with pyproject.toml, Ruff and mypy through pre-commit hooks, and a GitHub Actions workflow that runs the pytest suite on Python 3.10 to 3.12. Tests cover both storage backends, the KPI calculations and the CLI.