- simple-icons als kompakter Index im Repository (3.459 Marken, 2 MB gzip),
erzeugt von scripts/vendor_simple_icons.py bzw. `make vendor-icons`
- logo.dev und Brandfetch als optionale Adapter, ohne Schlüssel übersprungen
- Favicon-Fallback und generierter Buchstaben-Avatar als Garantie
- Bei eindeutigem Offline-Treffer unterbleiben Anfragen nach außen komplett
- Cache im Dateisystem nach SHA-256, Auslieferung nur über /api/logos/{id}
mit immutable-Header und ETag
- Markenfarbe aus SVG-Fills bzw. per k-Means (k=4) über 64x64 Pixel, dazu eine
aufgehellte Variante mit mindestens 4,5:1 Kontrast auf dunklem Grund
- Kandidatensuche mit Vorauswahl, Auswahl, Upload und Zurücksetzen
- Bildtyp wird nur noch am Inhalt bestimmt, nicht an der gemeldeten Kopfzeile
- 60 neue Tests, insgesamt 208 grün
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
115 lines
4.6 KiB
Markdown
115 lines
4.6 KiB
Markdown
# moneyfy
|
||
|
||
Selbst gehostete Web-Anwendung zur Planung monatlicher Kosten und Einkünfte.
|
||
Single-User, deutschsprachige Oberfläche, ausgelegt für den Betrieb im Homelab
|
||
hinter einem Reverse Proxy.
|
||
|
||
> **Status:** in Entwicklung. Siehe [CHANGELOG.md](CHANGELOG.md).
|
||
|
||
## Screenshots
|
||
|
||
_Platzhalter – werden ergänzt, sobald die Oberfläche steht._
|
||
|
||
| Dashboard | Cashflow-Kalender | Firmen |
|
||
|---|---|---|
|
||
| _folgt_ | _folgt_ | _folgt_ |
|
||
|
||
## Funktionsumfang
|
||
|
||
- Wiederkehrende Zahlungen und Einkünfte über vollständige RFC-5545-RRULEs,
|
||
inklusive Werktagsverschiebung nach NRW-Feiertagen.
|
||
- Preishistorie je Vertrag, sodass vergangene Monate betragstreu bleiben.
|
||
- Verträge mit Mindestlaufzeit, Kündigungsfrist und automatischer Verlängerung.
|
||
- Ratenzahlungen mit Restschuld- und Restratenberechnung.
|
||
- Rücklagenbildung für nicht-monatliche Posten.
|
||
- Firmenlogos und Markenfarben, lokal zwischengespeichert (siehe unten).
|
||
- Auswertungen: Monatsübersicht, Cashflow-Kalender, 12-Monats-Forecast,
|
||
Kategorien, Abo-Übersicht, Jahresvergleich, Budgets, Sparziele.
|
||
- Benachrichtigungen per SMTP und Apprise.
|
||
|
||
## Technischer Stack
|
||
|
||
| Bereich | Technologie |
|
||
|---|---|
|
||
| Backend | Python 3.12, FastAPI, SQLAlchemy 2 (async), Alembic, Pydantic v2 |
|
||
| Datenbank | PostgreSQL 17 |
|
||
| Scheduler | APScheduler (in-process) |
|
||
| Frontend | React 18, TypeScript, Vite, TailwindCSS |
|
||
| Charts | Recharts |
|
||
| Tests | pytest + httpx, vitest + testing-library |
|
||
|
||
## Schnellstart (lokale Entwicklung)
|
||
|
||
Voraussetzungen: Python 3.12, [uv](https://docs.astral.sh/uv/), Node 20+,
|
||
eine erreichbare PostgreSQL-17-Instanz.
|
||
|
||
```bash
|
||
git clone https://git.menzel.center/menzeljonas/moneyfy.git
|
||
cd moneyfy
|
||
cp .env.example backend/.env # DATABASE_URL und SECRET_KEY anpassen
|
||
|
||
make install # Backend-Abhängigkeiten in backend/.venv
|
||
make migrate # Schema anlegen
|
||
make seed # Kategoriebaum und Standardregeln
|
||
make dev # http://localhost:8000/api/docs
|
||
```
|
||
|
||
Nützliche Ziele: `make test`, `make lint`, `make format`, `make check`.
|
||
|
||
## Konfiguration
|
||
|
||
Alle Einstellungen kommen aus Umgebungsvariablen; `.env.example` enthält die
|
||
vollständige, kommentierte Liste. Die wichtigsten:
|
||
|
||
| Variable | Standard | Bedeutung |
|
||
|---|---|---|
|
||
| `DATABASE_URL` | – | PostgreSQL-DSN, `postgresql://` wird auf asyncpg umgestellt |
|
||
| `SECRET_KEY` | – | Signaturschlüssel für JWTs, mind. 32 Zeichen (`openssl rand -hex 32`) |
|
||
| `MONEYFY_ADMIN_USER` / `MONEYFY_ADMIN_PASSWORD` | `admin` / – | Beim Erststart angelegter Benutzer |
|
||
| `TIMEZONE` | `Europe/Berlin` | Zeitzone der gesamten Anwendung |
|
||
| `HOLIDAY_REGION` | `DE-NW` | Feiertagsregion für Werktagsverschiebungen |
|
||
| `LOGO_STORAGE_DIR` | `/data/logos` | Verzeichnis des Logo-Caches |
|
||
| `LOGODEV_API_KEY` / `BRANDFETCH_API_KEY` | leer | Optionale Logo-Provider, ohne Schlüssel übersprungen |
|
||
| `SMTP_*` | leer | Mailversand für Benachrichtigungen |
|
||
| `APPRISE_URLS` | leer | Komma-separierte Apprise-Ziele |
|
||
| `COOKIE_SECURE` | `true` | Hinter HTTPS `true`, für lokales HTTP `false` |
|
||
| `SCHEDULER_ENABLED` | `true` | Täglicher Benachrichtigungslauf um 07:00 |
|
||
|
||
## Logos und Markenfarben
|
||
|
||
Jede Firma bekommt ein Bild. Die Provider-Kette arbeitet der Reihe nach:
|
||
|
||
1. **simple-icons** – rund 3.500 Marken, im Repository unter
|
||
`backend/app/assets/simple_icons.json.gz` mitgeliefert. Kein Schlüssel, kein
|
||
Netzzugriff. Neu erzeugen mit `make vendor-icons`.
|
||
2. **logo.dev** – nur mit `LOGODEV_API_KEY`.
|
||
3. **Brandfetch** – nur mit `BRANDFETCH_API_KEY` und hinterlegter Domain.
|
||
4. **Favicon** – über den Google-Dienst, wenn eine Domain bekannt oder aus dem
|
||
Namen ableitbar ist.
|
||
5. **Generierter Avatar** – Buchstaben-Monogramm mit fester Farbe aus dem
|
||
Namens-Hash. Schlägt nie fehl.
|
||
|
||
Findet die Kette einen eindeutigen Treffer im lokalen Katalog, unterbleiben die
|
||
Anfragen nach außen vollständig – die Firmenliste verlässt den Server nicht. Im
|
||
Auswahldialog (`POST /api/merchants/{id}/logo/search`) läuft dagegen bewusst die
|
||
ganze Kette, damit Alternativen zur Wahl stehen.
|
||
|
||
Ausgewählte Logos landen unter `LOGO_STORAGE_DIR`, benannt nach ihrem
|
||
SHA-256-Hash, und werden nur über `GET /api/logos/{id}` ausgeliefert. Beim
|
||
Seitenaufruf entsteht dadurch kein Zugriff auf fremde Dienste. Ein Upload oder
|
||
eine bewusste Auswahl setzt den Status auf `manual` und wird von der Automatik
|
||
nie überschrieben.
|
||
|
||
## Projektstruktur
|
||
|
||
```
|
||
backend/ FastAPI-Anwendung, Modelle, Services, Alembic-Migrationen, Tests
|
||
frontend/ React-Oberfläche (Vite)
|
||
docs/ Betriebs- und Runner-Dokumentation
|
||
.gitea/ Gitea-Actions-Workflows
|
||
```
|
||
|
||
## Lizenz
|
||
|
||
[MIT](LICENSE)
|