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:
36
docs/by-gemini/README.md
Normal file
36
docs/by-gemini/README.md
Normal 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.
|
||||
48
docs/by-gemini/architecture.md
Normal file
48
docs/by-gemini/architecture.md
Normal 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. |
|
||||
```
|
||||
72
docs/by-gemini/deployment.md
Normal file
72
docs/by-gemini/deployment.md
Normal 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
66
docs/by-gemini/scripts.md
Normal 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. |
|
||||
```
|
||||
61
docs/by-gemini/user-guide.md
Normal file
61
docs/by-gemini/user-guide.md
Normal 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.
|
||||
```
|
||||
Reference in New Issue
Block a user