docs: experiment with generated documentation, let's keep it in git for
All checks were successful
Deploy to K8s / deploy (push) Successful in 8s
All checks were successful
Deploy to K8s / deploy (push) Successful in 8s
now
This commit is contained in:
214
docs/by-claude-opus/README.md
Normal file
214
docs/by-claude-opus/README.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# FUJ Management — Comprehensive Documentation
|
||||
|
||||
> **FUJ = Frisbee Ultimate Jablonec** — a small sports club in the Czech Republic.
|
||||
|
||||
## What Is This Project?
|
||||
|
||||
FUJ Management is a purpose-built financial management system for a small ultimate frisbee club. It automates the tedious process of tracking **who attended practice**, **how much they owe**, **who has paid**, and **who still owes money** — a workflow that would otherwise require manual cross-referencing between attendance spreadsheets and bank statements.
|
||||
|
||||
The system is built around two Google Sheets (one for attendance, one for payments) and a Fio bank transparent account. A set of Python scripts sync and process the data, while a Flask-based web dashboard provides real-time visibility into fees, payments, and reconciliation status.
|
||||
|
||||
### The Problem It Solves
|
||||
|
||||
Before this system, the club treasurer had to:
|
||||
|
||||
1. **Manually count** attendance marks for each member each month
|
||||
2. **Calculate** whether each person owes 0, 200, or 750 CZK based on how many times they showed up
|
||||
3. **Cross-reference** bank statements to figure out who paid and for which month
|
||||
4. **Chase** members who hadn't paid, often losing track of partial payments and advance payments
|
||||
5. **Handle edge cases** like members paying for multiple months at once, using nicknames in payment messages, or paying via a family member's account
|
||||
|
||||
This system automates steps 1–4 entirely, and provides tooling for step 5.
|
||||
|
||||
## System Overview
|
||||
|
||||
```
|
||||
┌──────────────────────────┐ ┌──────────────────────────┐
|
||||
│ Attendance Sheet │ │ Fio Bank Account │
|
||||
│ (Google Sheets) │ │ (transparent account) │
|
||||
│ │ │ │
|
||||
│ Members × Dates × ✓/✗ │ │ Incoming payments with │
|
||||
│ Tier (A/J/X) │ │ sender, amount, message │
|
||||
└──────────┬───────────────┘ └──────────┬───────────────┘
|
||||
│ │
|
||||
│ CSV export │ API / HTML scraping
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────────────┐ ┌───────────────────────┐
|
||||
│ attendance.py │ │ sync_fio_to_sheets.py │
|
||||
│ │ │ │
|
||||
│ Fetches sheet, │ │ Syncs bank txns to │
|
||||
│ computes fees │ │ Payments Google Sheet │
|
||||
└────────┬────────┘ └───────────┬────────────┘
|
||||
│ │
|
||||
│ ▼
|
||||
│ ┌───────────────────────┐
|
||||
│ │ Payments Sheet │
|
||||
│ │ (Google Sheets) │
|
||||
│ │ │
|
||||
│ │ Date|Amount|Person| │
|
||||
│ │ Purpose|Sender|etc. │
|
||||
│ └───────────┬────────────┘
|
||||
│ │
|
||||
│ ┌─────────────────────────┤
|
||||
│ │ │
|
||||
│ ▼ ▼
|
||||
│ ┌──────────────┐ ┌──────────────────┐
|
||||
│ │infer_payments│ │ match_payments.py │
|
||||
│ │ .py │ │ │
|
||||
│ │ │ │ Reconciliation │
|
||||
│ │ Auto-fills │ │ engine: matches │
|
||||
│ │ Person, │ │ payments against │
|
||||
│ │ Purpose, │ │ expected fees │
|
||||
│ │ Amount │ └────────┬──────────┘
|
||||
│ └──────────────┘ │
|
||||
│ │
|
||||
└────────────────┬───────────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────────┐
|
||||
│ Flask Web App │
|
||||
│ (app.py) │
|
||||
│ │
|
||||
│ /fees – fee │
|
||||
│ table │
|
||||
│ /reconcile – balance │
|
||||
│ matrix │
|
||||
│ /payments – ledger │
|
||||
│ /qr – QR code │
|
||||
└───────────────────────┘
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **Python 3.13+**
|
||||
- **[uv](https://docs.astral.sh/uv/)** — fast Python package manager
|
||||
- **Google Sheets API credentials** — a service account JSON file placed at `.secret/fuj-management-bot-credentials.json`
|
||||
- *Optional*: `FIO_API_TOKEN` environment variable for Fio REST API access (falls back to transparent page scraping)
|
||||
|
||||
### Setup
|
||||
|
||||
```bash
|
||||
# Clone and install dependencies
|
||||
git clone <repo-url>
|
||||
cd fuj-management
|
||||
uv sync # Installs all dependencies from pyproject.toml
|
||||
|
||||
# Place your Google API credentials
|
||||
mkdir -p .secret
|
||||
cp /path/to/your/credentials.json .secret/fuj-management-bot-credentials.json
|
||||
```
|
||||
|
||||
### Common Operations
|
||||
|
||||
| Command | Purpose |
|
||||
|---------|---------|
|
||||
| `make web` | Start the web dashboard at `http://localhost:5001` |
|
||||
| `make sync` | Pull new bank transactions into the Google Sheet |
|
||||
| `make infer` | Auto-fill Person/Purpose/Amount for new transactions |
|
||||
| `make reconcile` | Print a CLI balance report |
|
||||
| `make fees` | Print fee calculation table from attendance |
|
||||
| `make test` | Run the test suite |
|
||||
| `make image` | Build the Docker container image |
|
||||
|
||||
### Typical Workflow
|
||||
|
||||
```
|
||||
make sync → make infer → (manual review in Google Sheets) → make web
|
||||
↓ ↓ ↓ ↓
|
||||
Pull new bank Auto-match Fix any [?] View live
|
||||
transactions payments to flagged rows dashboard
|
||||
into sheet members/months in the sheet
|
||||
```
|
||||
|
||||
## Documentation Index
|
||||
|
||||
| Document | Contents |
|
||||
|----------|----------|
|
||||
| [Architecture](architecture.md) | System design, data flow diagrams, module dependency graph |
|
||||
| [Web Application](web-app.md) | Flask app architecture, routes, templates, interactive features |
|
||||
| [User Guide](user-guide.md) | End-user guide for the web dashboard — what each page shows |
|
||||
| [Scripts Reference](scripts.md) | Detailed reference for all CLI scripts and shared modules |
|
||||
| [Data Model](data-model.md) | Google Sheets schemas, fee calculation rules, bank integration |
|
||||
| [Deployment](deployment.md) | Docker containerization, Gitea CI/CD, Kubernetes deployment |
|
||||
| [Testing](testing.md) | Test infrastructure, coverage, how to write new tests |
|
||||
| [Development Guide](development.md) | Local setup, coding conventions, tooling, project history |
|
||||
|
||||
## Technology Stack
|
||||
|
||||
| Layer | Technology |
|
||||
|-------|-----------|
|
||||
| Language | Python 3.13+ |
|
||||
| Web framework | Flask 3.1 |
|
||||
| Package management | uv + pyproject.toml |
|
||||
| Data sources | Google Sheets API, Fio Bank API / HTML scraping |
|
||||
| QR codes | `qrcode` library (PIL backend) |
|
||||
| Containerization | Docker (Alpine-based) |
|
||||
| CI/CD | Gitea Actions |
|
||||
| Deployment target | Self-hosted Kubernetes |
|
||||
| Frontend | Server-rendered HTML/CSS/JS (terminal-aesthetic theme) |
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
fuj-management/
|
||||
├── app.py # Flask web application (4 routes)
|
||||
├── Makefile # Build automation (13 targets)
|
||||
├── pyproject.toml # Python dependencies and metadata
|
||||
│
|
||||
├── scripts/
|
||||
│ ├── attendance.py # Shared: attendance data + fee calculation
|
||||
│ ├── calculate_fees.py # CLI: print fee table
|
||||
│ ├── match_payments.py # Core: reconciliation engine + CLI report
|
||||
│ ├── infer_payments.py # Auto-fill Person/Purpose in Google Sheet
|
||||
│ ├── sync_fio_to_sheets.py # Sync Fio bank → Google Sheet
|
||||
│ ├── fio_utils.py # Shared: Fio bank data fetching
|
||||
│ └── czech_utils.py # Shared: diacritics normalization + Czech month parsing
|
||||
│
|
||||
├── templates/
|
||||
│ ├── fees.html # Attendance/fees dashboard
|
||||
│ ├── reconcile.html # Payment reconciliation with modals + QR
|
||||
│ └── payments.html # Payments ledger grouped by member
|
||||
│
|
||||
├── tests/
|
||||
│ ├── test_app.py # Flask route tests (mocked data)
|
||||
│ └── test_reconcile_exceptions.py # Reconciliation with fee exceptions
|
||||
│
|
||||
├── build/
|
||||
│ ├── Dockerfile # Alpine-based container image
|
||||
│ └── entrypoint.sh # Container entry point
|
||||
│
|
||||
├── .gitea/workflows/
|
||||
│ ├── build.yaml # CI: build + push Docker image
|
||||
│ └── kubernetes-deploy.yaml # CD: deploy to K8s cluster
|
||||
│
|
||||
├── .secret/ # (gitignored) API credentials
|
||||
├── docs/ # Project documentation
|
||||
│ ├── project-notes.md # Original brainstorming and design notes
|
||||
│ ├── fee-calculation-spec.md # Fee rules and payment matching spec
|
||||
│ ├── scripts.md # Legacy scripts documentation
|
||||
│ └── spec/
|
||||
│ └── fio_to_sheets_sync.md # Fio-to-Sheets sync specification
|
||||
│
|
||||
└── CLAUDE.md # AI assistant context file
|
||||
```
|
||||
|
||||
## Key Design Decisions
|
||||
|
||||
1. **No database** — Google Sheets serves as both the data store and the manual editing interface. This keeps the system simple and accessible to non-technical club members who can review and edit data directly in the spreadsheet.
|
||||
|
||||
2. **PII separation** — No member names or personal data are stored in the git repository. All data is fetched at runtime from Google Sheets and the bank account.
|
||||
|
||||
3. **Idempotent sync** — The Fio-to-Sheets sync uses SHA-256 hashes as deduplication keys, making re-runs safe and append-only.
|
||||
|
||||
4. **Graceful fallbacks** — Bank data can be fetched via the REST API (if a token is available) or by scraping the public transparent account page. The system doesn't break if the API token is missing.
|
||||
|
||||
5. **Czech language support** — Payment messages are in Czech and use diacritics. The system normalizes text (strips diacritics) and understands Czech month names in all grammatical declensions.
|
||||
|
||||
6. **Terminal aesthetic** — The web dashboard uses a monospace, dark-themed, terminal-inspired design that matches the project's pragmatic, CLI-first philosophy.
|
||||
|
||||
---
|
||||
|
||||
*This documentation was generated on 2026-03-03 by Claude Opus, based on a comprehensive analysis of the complete codebase.*
|
||||
Reference in New Issue
Block a user