Files
fuj-management/docs/fee-calculation-spec.md
Jan Novak 3bfea4e0a4 feat: initial dashboard implementation and robust attendance parsing
- Added a Makefile to easily run project scripts (fees, match, web, image)
- Modified attendance.py to dynamically handle a variable number of header rows from the Google Sheet
- Updated both attendance calculations and calculate_fees terminal output to show actual attendance counts (e.g., '750 CZK (3)')
- Created a Flask web dashboard (app.py and templates/fees.html) to view member fees in an attractive, condensed, terminal-like UI
- Bound the Flask server to port 5000 and added a routing alias from '/' to '/fees'
- Configured Python virtual environment (.venv) creation directly into the Makefile to resolve global pip install errors on macOS

Co-authored-by: Antigravity <antigravity@deepmind.com>
2026-02-27 13:20:42 +01:00

70 lines
2.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Fee Calculation Spec — Tuesday Practices
## Data Source
- Google Sheet: `1E2e_gT_K5AwSRCDLDTa2UetZTkHmBOcz0kFbBUNUNBA`
- Sheet: first sheet only (Tuesday practices, 20:3022:00)
- Public export URL (CSV): `https://docs.google.com/spreadsheets/d/1E2e_gT_K5AwSRCDLDTa2UetZTkHmBOcz0kFbBUNUNBA/export?format=csv`
## Sheet Structure
| Row | Content |
| --- | --- |
| 1 | Header: title in col A, dates in cols D+ (format `M/D/YYYY`) |
| 2 | Venue per date (irrelevant for pricing) |
| 3 | Total attendees per date |
| 4+ | Member rows: Name (col A), Tier (col B), Total (col C), attendance TRUE/FALSE (cols D+) |
Member rows end when the Name column is empty.
## Tiers
| Code | Meaning | Pays from this sheet? |
| --- | --- | --- |
| A | Adult | Yes |
| J | Junior | No (paid via separate attendance sheet) |
| X | Exempt | No |
## Fee Rules (Adults only)
Fees are calculated per calendar month based on the number of attended practices in that month.
| Practices in month | Fee |
| --- | --- |
| 0 | 0 CZK |
| 1 | 200 CZK |
| 2 or more | 750 CZK |
## Payment Matching
### Bank Account
- Fio banka transparent account: `2800359168/2010`
- Owner: Nathan Heilmann
- Public view: `https://ib.fio.cz/ib/transparent?a=2800359168`
### Data Access
- **Without API token**: scrape the public transparent account HTML page
- **With API token**: Fio REST API at `https://fioapi.fio.cz/v1/rest/periods/{token}/{from}/{to}/transactions.json`
- Token is generated in Fio internetbanking (Settings → API)
- Rate limit: 1 request per 30 seconds per token
- Available fields: date, amount, currency, sender account, sender name, VS, SS, KS, user identification, message, type, and more
### Matching Approach
Payments are matched to members using best-effort heuristics, with uncertain matches flagged for manual review.
1. **Name matching**: Normalize (strip diacritics, lowercase) sender name and message text, compare against member names and nicknames
2. **Month parsing**: Extract Czech month names (leden, únor, ...) and numeric patterns (01/26, 1/2026) from the message
3. **Amount validation**: Check if amount aligns with expected fees (200, 750, or multiples)
4. **Multi-person splitting**: When a message references multiple members, split the payment across them
### Advance Payments
If a payment references a month with no attendance data yet, it is tracked as **credit** on the member's account. The credit is applied once that month's attendance is recorded.
## PII Constraint
No member names or personal data are committed to git. All data is fetched at runtime from the Google Sheet and bank account.