232 lines
6.8 KiB
Markdown
232 lines
6.8 KiB
Markdown
# Saldo
|
|
|
|
Saldo ist eine moderne Flask-PWA für Mehrbenutzer-Haushaltsplanung. Die App fokussiert sich auf Monatsplanung, Überweisungsverteilungen, variable Einkommen, Restbetragsvorschläge und externe Kostenbeteiligung, statt klassische Buchhaltung nachzubauen.
|
|
|
|
Aktueller Projektstand: `0.1.0`
|
|
|
|
## Features
|
|
|
|
- automatische Monatsanlage beim ersten Öffnen eines neuen Kalendermonats
|
|
- Kopieren des Vormonats inklusive Einkommen, Planwerten, Verteilungen und Beteiligungslogik
|
|
- variable Einkommenszeilen pro Monat
|
|
- verpflichtende Anzeigenamen für Nutzer, sichtbar in Avataren, Splits und Budgetdetails
|
|
- Vorschlags-Engine für `Sparen`, `Urlaub`, `Freizeit` und `Persönliche Auszahlung`
|
|
- externe Kostenbeteiligte ohne App-Login
|
|
- PWA mit Manifest und Service Worker
|
|
- Web Push mit VAPID-Keys
|
|
- Rollenmodell mit `admin` und `editor`
|
|
- keine offene Registrierung
|
|
- Healthcheck unter `/health`
|
|
|
|
## Stack
|
|
|
|
- Python 3
|
|
- Flask
|
|
- SQLAlchemy
|
|
- Flask-Login
|
|
- Flask-Migrate / Alembic
|
|
- Jinja Templates
|
|
- leichtes Vanilla JS
|
|
- Chart.js
|
|
- SQLite als Default
|
|
- Gunicorn
|
|
|
|
## Projektstruktur
|
|
|
|
```text
|
|
app/
|
|
admin/ Admin-Views für Benutzer und Beteiligte
|
|
auth/ Login/Logout
|
|
main/ Übersicht, Auswertungen, Healthcheck
|
|
months/ Monatsliste, Locking, manuelles Anlegen
|
|
planning/ Monatliche Bearbeitung von Einkommen, Kosten, Verteilungen
|
|
services/ Domänenlogik für Monate, Vorschläge, Vergleiche, Shares, Push
|
|
static/ CSS, JS, Icons, Manifest, Service Worker
|
|
templates/ Jinja-Templates
|
|
models.py SQLAlchemy-Modelle
|
|
seed.py Seed-Daten
|
|
migrations/ Alembic-Migrationen
|
|
tests/ Pytest-Suite
|
|
```
|
|
|
|
## Lokal starten
|
|
|
|
```bash
|
|
python -m venv .venv
|
|
. .venv/bin/activate
|
|
pip install -r requirements.txt
|
|
export FLASK_APP=wsgi:app
|
|
python -m flask db upgrade
|
|
python -m flask seed
|
|
python -m flask run --debug
|
|
```
|
|
|
|
Die App läuft lokal standardmäßig mit SQLite im `instance`- bzw. konfigurierten Datenverzeichnis.
|
|
Beim ersten Aufruf öffnet sich automatisch die Setup-Seite zur Anlage des ersten Admins.
|
|
|
|
Wichtig für lokale Tests:
|
|
|
|
- die lokale Datenbank liegt standardmäßig in `instance/saldo.db`
|
|
- Uploads und andere Laufzeitdaten liegen ebenfalls im Datenverzeichnis
|
|
- diese Dateien werden über `.gitignore` bewusst nicht versioniert
|
|
- dadurch kannst du lokal testen, später Änderungen pullen und danach einfach wieder `python -m flask db upgrade` ausführen
|
|
|
|
## Wichtige Umgebungsvariablen
|
|
|
|
Siehe [.env.example](/home/hnzio/Projekte/saldo/.env.example).
|
|
|
|
- `SECRET_KEY`
|
|
- `DATABASE_URL`
|
|
- `SALDO_DATA_DIR`
|
|
- `SALDO_ADMIN_USERNAME`
|
|
- `SALDO_ADMIN_PASSWORD`
|
|
- `SALDO_ADMIN_EMAIL`
|
|
- `VAPID_PUBLIC_KEY`
|
|
- `VAPID_PRIVATE_KEY`
|
|
- `VAPID_SUBJECT`
|
|
- `SALDO_ALLOCATION_TARGET_RULES`
|
|
- `SALDO_STRONG_INCOME_CHANGE_THRESHOLD`
|
|
|
|
## CLI-Kommandos
|
|
|
|
```bash
|
|
python -m flask create-admin --username admin2 --display-name "Admin 2" --email admin2@example.com --password secret
|
|
python -m flask bootstrap-admin
|
|
python -m flask seed
|
|
python -m flask run-reminders
|
|
```
|
|
|
|
`seed` legt nur die Grundstruktur an. `bootstrap-admin` bleibt als optionaler CLI-Weg verfügbar.
|
|
`run-reminders` kann auf Cloudron als Scheduled Task oder per Cron ausgeführt werden.
|
|
|
|
## Cloudron-Hinweise
|
|
|
|
Vorbereitete Paketdateien:
|
|
|
|
- `CloudronManifest.json`
|
|
- `Dockerfile`
|
|
- `start.sh`
|
|
- `DESCRIPTION.md`
|
|
- `CHANGELOG`
|
|
- `POSTINSTALL.md`
|
|
|
|
Cloudron-Release-Stand:
|
|
|
|
- App-Version: `0.1.0`
|
|
- Healthcheck: `/health`
|
|
- interner Port: `8000`
|
|
- persistente Daten: `/app/data`
|
|
- Build-Hygiene: `.dockerignore` schließt lokale DBs, `instance/`, Test-Caches und Editor-Dateien aus
|
|
|
|
Empfohlene Env-Konfiguration für eine Cloudron-Subdomain wie `https://saldo.example.com`:
|
|
|
|
```bash
|
|
SECRET_KEY=<random>
|
|
DATABASE_URL=sqlite:////app/data/saldo.db
|
|
SALDO_DATA_DIR=/app/data
|
|
SALDO_ADMIN_USERNAME=admin
|
|
SALDO_ADMIN_PASSWORD=<random>
|
|
SALDO_ADMIN_EMAIL=admin@example.invalid
|
|
VAPID_PUBLIC_KEY=<public>
|
|
VAPID_PRIVATE_KEY=<private>
|
|
VAPID_SUBJECT=mailto:admin@example.invalid
|
|
```
|
|
|
|
Startkommando:
|
|
|
|
```bash
|
|
gunicorn -c gunicorn.conf.py wsgi:app
|
|
```
|
|
|
|
Im Container übernimmt `start.sh` vor dem Start automatisch:
|
|
|
|
```bash
|
|
python -m flask db upgrade
|
|
python -m flask seed
|
|
```
|
|
|
|
Wenn du mit der Cloudron CLI paketierst oder hochlädst:
|
|
|
|
- die lokale SQLite-Datei aus `instance/` wird nicht mitgeschickt
|
|
- lokale `.env`-Dateien werden nicht mitgeschickt
|
|
- Test-/Cache-Dateien und Editor-Metadaten bleiben ebenfalls draußen
|
|
- produktive Daten sollen weiterhin ausschließlich in `/app/data` liegen
|
|
|
|
Cloudron-Kompatibilität in diesem Projekt:
|
|
|
|
- persistente Daten im konfigurierbaren Datenverzeichnis
|
|
- Logging über stdout/stderr
|
|
- Healthcheck-Route `/health`
|
|
- keine Benutzer-Selbstregistrierung
|
|
- Erststart-Setup im Browser für den ersten Admin
|
|
- optionaler Admin-Bootstrap per CLI
|
|
- Reminder-Check als separater wiederverwendbarer CLI-Task
|
|
- neutrale Basisdaten werden auf Fresh-Install automatisch angelegt
|
|
|
|
Hinweis für spätere Update-Verteilung:
|
|
|
|
- Laut Cloudron-Publishing-Workflow wird nach dem ersten Build die Datei `CloudronVersions.json` mit `cloudron versions add` erzeugt und anschließend öffentlich bereitgestellt.
|
|
- Damit erscheinen neue Versionen später automatisch als Community-App-Updates.
|
|
|
|
## Basisdaten
|
|
|
|
Das Seed-Script legt an:
|
|
|
|
- Standardkonten, Kategorien und Einträge
|
|
- Gemeinschaftskonten-Grundstruktur
|
|
|
|
Nicht angelegt werden:
|
|
|
|
- Beispielzugänge
|
|
- Beispielpersonen
|
|
- Demo-Monatswerte
|
|
|
|
## Tests
|
|
|
|
```bash
|
|
python -m pytest -q
|
|
```
|
|
|
|
Aktueller Stand:
|
|
|
|
- 31 Tests grün
|
|
|
|
## Hinweise zur Kernlogik
|
|
|
|
`MonthService.ensure_month()`:
|
|
- legt den aktuellen Kalendermonat automatisch an
|
|
- übernimmt beim Anlegen den letzten vorhandenen Monat
|
|
- fällt beim ersten Start auf einen Seed-Standardmonat zurück
|
|
|
|
`AllocationSuggestionService.recompute()`:
|
|
- berechnet den verteilbaren Restbetrag
|
|
- respektiert gesperrte Zielkonten
|
|
- verteilt den übrigen Betrag gewichtet
|
|
- gleicht Rundungsreste in der letzten Vorschlagszeile aus
|
|
|
|
## PWA und Push
|
|
|
|
- Manifest: [app/static/manifest.json](/home/hnzio/Projekte/saldo/app/static/manifest.json)
|
|
- Service Worker: [app/static/service-worker.js](/home/hnzio/Projekte/saldo/app/static/service-worker.js)
|
|
- Push-Subscription-Route: [app/planning/routes.py](/home/hnzio/Projekte/saldo/app/planning/routes.py:113)
|
|
- Reminder-Logik: [app/services/notification_service.py](/home/hnzio/Projekte/saldo/app/services/notification_service.py)
|
|
|
|
## Git und Releases
|
|
|
|
Repo-Vorbereitung in diesem Stand:
|
|
|
|
- `.gitignore` verhindert, dass lokale SQLite-Datenbank, Uploads und Laufzeitdaten eingecheckt werden
|
|
- `.dockerignore` hält lokale Test- und Laufzeitdateien auch aus Cloudron-Builds heraus
|
|
- `VERSION` und `CHANGELOG` dokumentieren den aktuellen Release-Stand
|
|
- `LICENSE` erlaubt private Nutzung
|
|
|
|
Empfohlene Release-Schritte:
|
|
|
|
```bash
|
|
git init -b main
|
|
git remote add origin https://git.hnz.io/hnzio/saldo.git
|
|
git add .
|
|
git commit -m "chore: prepare saldo 0.1.0 for git and cloudron"
|
|
git push -u origin main
|
|
```
|