docs: experiment with generated documentation, let's keep it in git for
All checks were successful
Deploy to K8s / deploy (push) Successful in 8s

now
This commit is contained in:
2026-03-11 11:57:30 +01:00
parent e83d6af1f5
commit 9b99f6d33b
17 changed files with 2367 additions and 0 deletions

36
docs/by-gemini/README.md Normal file
View File

@@ -0,0 +1,36 @@
# FUJ Management System
Welcome to the **FUJ Management System**, a streamlined solution for managing Ultimate Frisbee club finances, attendance, and member payments. This system automates the tedious parts of club management, keeping your ledger clean and your reconciliation painless.
## 🚀 Mission
The project's goal is to minimize manual entry and potential human error in club management by:
1. **Automating Bank Synchronization**: Periodically fetching transactions from Fio bank.
2. **Smart Inference**: Using heuristics to match bank transactions to members and payment periods.
3. **Visual Reconciliation**: Providing a clear, real-time web dashboard for managers to track who has paid and who is in debt.
## ✨ Key Features
- **Seamless Bank Integration**: Synchronize transactions directly from the Fio bank API into a Google Spreadsheet.
- **Intelligent Matching**: Automatic detection of member names and payment periods from transaction messages using diacritic-insensitive Czech text processing.
- **Dynamic Dashboard**: A Flask-powered web interface displaying monthly fees, payment status (OK, Partial, Unpaid), and total balances.
- **Manual Overrides**: Support for fee exceptions and manual payment matching when automation needs a human touch.
- **QR Payment Generation**: Integrated QR code generation to make paying outstanding fees trivial for members.
## 🛠 Tech Stack
- **Backend**: Python 3.12+ (managed with `uv`)
- **Web Framework**: Flask with Jinja2 templates
- **Data Storage**: Google Sheets (used as a collaborative database)
- **APIs**: Fio Bank API, Google Sheets API v4
- **Containerization**: Docker / OCI Images
- **Automation**: `Makefile` based workflow
---
## 📂 Documentation Guide
- [Architecture](architecture.md): High-level system design and data flow.
- [User Guide](user-guide.md): How to operate the system as a club manager.
- [Support Scripts](scripts.md): Detailed reference for CLI tools.
- [Deployment](deployment.md): Technical setup and infrastructure instructions.

View File

@@ -0,0 +1,48 @@
# System Architecture
The FUJ Management system is designed around a **"Sheet-as-a-Database"** architecture. This allows for easy manual editing and transparency while enabling powerful automation.
## 🔄 High-Level Data Flow
```mermaid
graph TD
Fio[Fio Bank API] -->|Sync Script| GS(Google Spreadsheet)
Att[Attendance Sheet] -->|CSV Export| App(Flask Web App)
GS -->|API Fetch| App
App -->|Display| UI[Manager Dashboard]
GS -.->|Manual Edits| GS
App -->|Generate| QR[QR Codes for Members]
```
### 1. Data Ingestion (Bank to Sheet)
The synchronization pipeline moves raw bank data into a structured format:
- `sync_fio_to_sheets.py` fetches transactions and appends them to the "Transactions" sheet.
- Each transaction is assigned a unique `Sync ID` to prevent duplicates.
- `infer_payments.py` processes new rows, attempting to fill the `Person`, `Purpose`, and `Inferred Amount` columns based on the message and sender.
### 2. Logic & Reconciliation
The core logic resides in shared Python scripts:
- **Attendance**: `attendance.py` pulls the latest practice data from a separate attendance sheet and calculates expected fees (e.g., 0/200/750 CZK rules).
- **Matching**: `match_payments.py` performs the "heavy lifting" by correlating members, months, and payments. It handles partial payments, overpayments (credits), and manual exceptions.
### 3. Presentation Layer
The Flask application (`app.py`) serves as the primary interface:
- **Fees View**: Shows attendance-based charges.
- **Reconciliation View**: The main "truth" dashboard showing balance per member.
- **Payments View**: Historical list of transactions grouped by member.
## 🛡 Security & Authentication
- **Fio Bank**: Authorized via a private API token (kept in `.secret/`).
- **Google Sheets**: Authenticated via a **Service Account** or **OAuth2** (using `.secret/fuj-management-bot-credentials.json`).
- **Environment**: Secrets are never committed; the `.secret/` directory is git-ignored.
## 🧩 Key Components
| Component | Responsibility |
| :--- | :--- |
| **Google Spreadsheet** | Unified source of truth for transactions and manual overrides. |
| **scripts/** | A suite of CLI utilities for batch processing and data maintenance. |
| **Flask App** | Read-only views for state visualization and QR code generation. |
| **czech_utils.py** | Diacritic-normalization and NLP for Czech month/name parsing. |
```

View File

@@ -0,0 +1,72 @@
# Deployment & Technical Setup
This document provides instructions for developers and devops engineers to set up and deploy the FUJ Management system.
## 🛠 Prerequisites
- **Python 3.12+**: The project uses modern type hinting and syntax features.
- **uv**: High-performance Python package installer and resolver.
- Install via brew: `brew install uv`
- **Docker** (Optional): For containerized deployments.
## ⚙️ Initial Setup
1. **Clone the repository**:
```bash
git clone <repo-url>
cd fuj-management
```
2. **Install dependencies**:
Using `uv`, everything is handled automatically:
```bash
make venv
```
3. **Secrets Management**:
Create a `.secret/` directory. You will need two main credentials:
- `fuj-management-bot-credentials.json`: A Google Cloud Service Account key with access to the Sheets API.
- `fio-token.txt`: (Implicitly used by `fio_utils.py`) Your Fio bank API token.
Ensure these are never committed! They are ignored by `.gitignore`.
## 🐳 Containerization
The project can be built and run as an OCI image.
1. **Build the image**:
```bash
make image
```
This uses the `build/Dockerfile`, which is optimized for small size and security.
2. **Run the container**:
```bash
make run
```
The app exposes port `5001`.
## 🧪 Testing & Validation
The project includes a suite of infrastructure and logic tests.
- **Run all tests**:
```bash
make test
```
- **Verbose output**:
```bash
make test-v
```
Tests are located in the `tests/` directory and use the standard Python `unittest` framework. They cover:
- CSV parsing logic.
- Fee calculation rules.
- Name matching and normalization.
## 🚀 Future Roadmap
- **Automated Backups**: Regular snapshots of the Google Sheet.
- **Authentication Layer**: Login for the web dashboard (currently assumes internal VPN or trusted environment).
- **Gitea Actions**: Continuous Integration for building and testing images.
```

66
docs/by-gemini/scripts.md Normal file
View File

@@ -0,0 +1,66 @@
# Support Scripts Reference
The project includes several CLI utilities located in the `scripts/` directory. Most are accessible via `make` targets.
## 🚀 Primary Scripts
### `sync_fio_to_sheets.py`
**Target**: `make sync` | `make sync-2026`
- **Purpose**: Downloads transactions from Fio bank via API and appends new ones to the Google Sheet.
- **Key Logic**: Uses a `Sync ID` (SHA-256 hash of transaction details) to ensure that even if the sync is run multiple times, no duplicate rows are created.
- **Arguments**:
- `--days`: How many days back to look (default 30).
- `--from/--to`: Specific date range.
- `--sort-by-date`: Re-sorts the spreadsheet after appending.
### `infer_payments.py`
**Target**: `make infer`
- **Purpose**: Processes the "Transactions" sheet to fill in `Person`, `Purpose`, and `Inferred Amount`.
- **Logic**:
- Analyzes the `Sender` and `Message` fields.
- Uses `match_payments.py` heuristics to find members.
- If confidence is low, prefixes the name with `[?]` to flag it for manual review.
- Won't overwrite cells that already have data (respecting your manual fixes).
### `match_payments.py`
**Target**: `make match` | `make reconcile`
- **Purpose**: The core "Reconciliation Engine".
- **Logic**:
- Fetches attendance fees (from `attendance.py`).
- Fetches transaction data.
- Correlates them based on inferred `Person` and `Purpose`.
- Handles "rollover" balances—extra money from one month is tracked as a credit for the next.
---
## 🛠 Utility Modules
### `attendance.py`
- Handles the connection to the Google Attendance sheet (exported as CSV).
- Implements the club's fee rules:
- 0 practices = 0 CZK
- 1 practice = 200 CZK
- 2+ practices = 750 CZK
- *Note*: Fee calculation only applies to members in Tier "A" (Adults).
### `czech_utils.py`
- **Normalization**: Strips diacritics and lowercases text (e.g., `František` -> `frantisek`).
- **Month Parsing**: Advanced regex to detect month references in Czech (e.g., "leden-brezen", "11+12/25", "na únor").
### `fio_utils.py`
- Low-level wrapper for the Fio Bank API.
- Handles HTTP requests and JSON parsing for transaction lists.
---
## ⚙️ Makefile Summary
| Command | Action |
| :--- | :--- |
| `make fees` | Preview calculated fees based on attendance. |
| `make sync` | Sync last 30 days of bank data. |
| `make infer` | Run smart tagging on the sheet. |
| `make reconcile` | Run a text-based reconciliation report in terminal. |
| `make web` | Start the Flask dashboard. |
| `make test` | Run the test suite. |
```

View File

@@ -0,0 +1,61 @@
# User Guide
This guide is intended for club managers who use the FUJ Management system for day-to-day operations.
## 🛠 Operational Workflow
To keep the club finances up-to-date, follow these steps periodically (e.g., once a week):
1. **Sync Bank Transactions**:
Run the sync script to pull the latest payments from Fio.
```bash
make sync
```
2. **Infer Payments**:
Let the system automatically tag who paid for what.
```bash
make infer
```
3. **Manual Review (Google Sheets)**:
Open the Google Spreadsheet. Check rows with the `[?]` prefix in the `Person` column—these require human confirmation.
- If correct: Remove the `[?]` prefix.
- If incorrect: Manually fix the `Person` and `Purpose`.
- If a payment covers a special case: Use the **exceptions** sheet to override expected fees.
4. **Check Reconciliation Dashboard**:
Start the web app to see the final balance report.
```bash
make web
```
Navigate to `http://localhost:5001/reconcile`.
---
## 📊 Understanding the Dashboard
### Reconciliation Page
- **Green (OK)**: Member has paid exactly what was expected (or more).
- **Orange (Partial)**: Some payment was received, but there's still a debt.
- **Red (UNPAID)**: No payment recorded for this month.
- **Blue (SURPLUS)**: Payment received for a month where no fee was expected.
### Handling Debts
If a member is in debt, you can click on the unpaid/partial cell to get a **QR Platba** link. You can send this link or screenshot to the member to facilitate quick payment.
---
## ❓ FAQ & Troubleshooting
### Why is a payment "Unmatched"?
A payment stays unmatched if neither the sender name nor the message contains recognizable member names or nicknames.
- **Fix**: Manually enter the member's name in the `Person` column in the Google Sheet.
### How do I handle a "Family Discount" or "Prepaid Year"?
Use the `exceptions` sheet in the Google Spreadsheet.
1. Add the member's name (exactly as it appears in attendance).
2. Enter the month (e.g., `2026-03`).
3. Enter the new `Amount` (use `0` for prepaid).
4. Add a `Note` for clarity.
### The web app is slow to load.
The app fetches data from Google Sheets API on every request. This ensures real-time data but can take a few seconds. The "Performance Breakdown" footer shows exactly where the time was spent.
```