docs: Wiki-Seiten mit Projektdokumentation befüllen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@@ -1,2 +1,122 @@
|
||||
# Architektur-Übersicht
|
||||
|
||||
## Stack
|
||||
|
||||
| Schicht | Technologie |
|
||||
|---|---|
|
||||
| Frontend | Angular 21, Standalone Components, Signals |
|
||||
| Styling | Tailwind CSS v4, Flowbite Design System |
|
||||
| Charts | ApexCharts 3.46 |
|
||||
| i18n | ngx-translate (DE, FR, IT, EN) |
|
||||
| Backend | Django REST Framework, Python 3.12 |
|
||||
| Auth | SimpleJWT (Access 60min, Refresh 7d, Rotation + Blacklist) |
|
||||
| Datenbank | PostgreSQL |
|
||||
| E-Mail | Brevo SMTP (`smtp-relay.brevo.com:587`) |
|
||||
| Server | Hetzner Ubuntu 24.04, Gunicorn + Nginx, Certbot (HTTPS) |
|
||||
| Font | Roboto via `@fontsource/roboto` (selbst-gehostet, DSGVO-konform) |
|
||||
|
||||
## Verzeichnisstruktur
|
||||
|
||||
```
|
||||
armarium-suite/
|
||||
├── backend/
|
||||
│ ├── core/ # Django-Projektkonfiguration (settings, urls)
|
||||
│ ├── finance/ # Haupt-App (Models, Views, Serializers)
|
||||
│ │ ├── migrations/
|
||||
│ │ ├── models.py
|
||||
│ │ ├── views.py
|
||||
│ │ ├── serializers.py
|
||||
│ │ ├── email.py # send_email() Helper
|
||||
│ │ └── backends.py # EmailAuthBackend
|
||||
│ ├── templates/emails/ # HTML + Plaintext E-Mail-Templates
|
||||
│ ├── requirements.txt
|
||||
│ └── .env # Nicht im Repo
|
||||
└── frontend/
|
||||
├── src/app/
|
||||
│ ├── auth/ # Login, Register, ForgotPassword, ResetPassword, VerifyEmail
|
||||
│ ├── dashboard/
|
||||
│ ├── services/ # ApiService, AuthService, FinancialYearService, ...
|
||||
│ ├── layout/ # Shell, Navbar, Sidebar
|
||||
│ └── ...
|
||||
├── src/assets/i18n/ # de.json, en.json, fr.json, it.json
|
||||
└── src/budget-app-theme.css # Tailwind v4 Custom Theme (Violet Primary)
|
||||
```
|
||||
|
||||
## Datenmodelle
|
||||
|
||||
| Modell | Beschreibung |
|
||||
|---|---|
|
||||
| `Profile` | Erweitertes User-Profil (Avatar, Kanton, 2FA, Tokens, Prefs) |
|
||||
| `Account` | Konten (asset, expense, revenue) |
|
||||
| `Transaction` | Doppelte Buchführung (source + destination Account) |
|
||||
| `Budget` | Budgetkategorien (7 Kategorien) |
|
||||
| `Expense` | Ausgaben mit Fälligkeitsdatum |
|
||||
| `Deadline` | Termine (Steuern, Versicherung, Rechnung, etc.) |
|
||||
| `UserSession` | Aktive Sessions mit Gerätename, IP, JWT-JTI |
|
||||
| `BackupCode` | 2FA-Backup-Codes (SHA-256-Hash) |
|
||||
| `FinancialYear` | Jahresplanung (User oder Haushalt) |
|
||||
| `YearlyIncome` | Einnahmen pro Jahr |
|
||||
| `YearlyBudgetItem` | Fixkosten pro Jahr |
|
||||
| `Household` | Gemeinsamer Haushalt |
|
||||
| `HouseholdMembership` | Haushalt-Mitgliedschaft mit Rolle und Status |
|
||||
|
||||
## API-Endpunkte (Übersicht)
|
||||
|
||||
### Auth
|
||||
| Methode | Endpunkt | Beschreibung |
|
||||
|---|---|---|
|
||||
| POST | `/api/auth/register/` | Registrierung (sendet Bestätigungsmail) |
|
||||
| POST | `/api/auth/verify-email/` | E-Mail bestätigen |
|
||||
| POST | `/api/auth/token/` | Login |
|
||||
| POST | `/api/auth/token/refresh/` | JWT erneuern |
|
||||
| POST | `/api/auth/logout/` | Logout + Blacklist |
|
||||
| POST | `/api/auth/password/` | Passwort ändern |
|
||||
| POST | `/api/auth/password-reset/` | Reset anfordern |
|
||||
| POST | `/api/auth/password-reset/confirm/` | Neues Passwort setzen |
|
||||
| POST | `/api/auth/2fa/login/` | TOTP-Verifikation |
|
||||
| POST | `/api/auth/2fa/setup/` | 2FA einrichten |
|
||||
| POST | `/api/auth/2fa/enable/` | 2FA aktivieren |
|
||||
| POST | `/api/auth/2fa/disable/` | 2FA deaktivieren |
|
||||
| POST | `/api/auth/2fa/recover/` | Recovery-Code anfordern |
|
||||
| POST | `/api/auth/2fa/recover/confirm/` | Recovery bestätigen |
|
||||
| GET | `/api/auth/sessions/` | Session-Liste |
|
||||
| DELETE | `/api/auth/sessions/<key>/` | Session widerrufen |
|
||||
| DELETE | `/api/auth/sessions/revoke-all/` | Alle anderen Sessions widerrufen |
|
||||
|
||||
### Daten
|
||||
| Methode | Endpunkt | Beschreibung |
|
||||
|---|---|---|
|
||||
| GET/PUT | `/api/profile/` | Profil lesen/aktualisieren |
|
||||
| GET/POST/PUT/DELETE | `/api/accounts/` | Konten |
|
||||
| GET/POST/PUT/DELETE | `/api/transactions/` | Transaktionen |
|
||||
| GET/POST/PUT/DELETE | `/api/budgets/` | Budgets |
|
||||
| GET/POST/PUT/DELETE | `/api/expenses/` | Ausgaben |
|
||||
| GET/POST/PUT/DELETE | `/api/deadlines/` | Termine |
|
||||
| GET | `/api/export/` | ZIP-Export (6 PDFs) |
|
||||
| GET | `/api/search/` | Globale Suche |
|
||||
| GET | `/api/notifications/` | Benachrichtigungen |
|
||||
| PATCH | `/api/notifications/prefs/` | Benachrichtigungs-Prefs |
|
||||
|
||||
### Jahresplanung
|
||||
| Methode | Endpunkt | Beschreibung |
|
||||
|---|---|---|
|
||||
| GET/POST | `/api/financial-years/` | Jahre auflisten / erstellen |
|
||||
| GET/PATCH/DELETE | `/api/financial-years/<year>/` | Jahr-Detail |
|
||||
| POST | `/api/financial-years/<year>/copy-from/<source>/` | Jahr kopieren |
|
||||
| GET/POST | `/api/financial-years/<year>/incomes/` | Einnahmen |
|
||||
| GET/POST | `/api/financial-years/<year>/budget-items/` | Fixkosten |
|
||||
| GET/POST | `/api/households/` | Haushalte |
|
||||
| POST | `/api/households/<pk>/invite/` | Mitglied einladen |
|
||||
| POST | `/api/households/<pk>/accept/` | Einladung annehmen |
|
||||
| POST | `/api/households/<pk>/leave/` | Haushalt verlassen |
|
||||
|
||||
## Sicherheits-Architektur
|
||||
|
||||
- **JWT**: Access-Token 60min, Refresh-Token 7 Tage, Rotation + Blacklist
|
||||
- **2FA**: TOTP (pyotp), HMAC-signierter Temp-Token (5min), Replay-Schutz, 8 Backup-Codes (SHA-256)
|
||||
- **Passwort-Reset**: Token als SHA-256-Hash in DB, 15min TTL, anti-enumeration Response
|
||||
- **E-Mail-Verifikation**: Token als SHA-256-Hash, 24h TTL
|
||||
- **Rate-Limiting**: 5/min Auth, 200/min User, 20/min Anon
|
||||
- **Sessions**: Alle Sessions werden bei Passwortänderung/-reset invalidiert
|
||||
- **Produktion**: HTTPS-Redirect, HSTS (1 Jahr), Secure Cookies, Content-Type-Nosniff
|
||||
- **CAPTCHA**: Cloudflare Turnstile auf Login + Register
|
||||
|
||||
@@ -1,2 +1,90 @@
|
||||
# Contributing Guide
|
||||
|
||||
## Branch-Strategie
|
||||
|
||||
```
|
||||
main ← Produktions-Stand (entspricht Live-Server)
|
||||
develop ← Aktiver Entwicklungs-Branch
|
||||
feature/* ← Feature-Branches (werden in develop gemergt)
|
||||
fix/* ← Bugfix-Branches
|
||||
```
|
||||
|
||||
- Neue Features immer von `develop` abzweigen
|
||||
- Fertige Features via Merge (no-ff) in `develop`
|
||||
- `develop` → `main` nur bei einem Release
|
||||
|
||||
## Commit-Konventionen
|
||||
|
||||
Format: `type: kurze Beschreibung`
|
||||
|
||||
| Typ | Verwendung |
|
||||
|---|---|
|
||||
| `feat` | Neues Feature |
|
||||
| `fix` | Bugfix |
|
||||
| `chore` | Build, Konfiguration, Abhängigkeiten |
|
||||
| `docs` | Dokumentation |
|
||||
| `refactor` | Refactoring ohne Funktionsänderung |
|
||||
| `security` | Sicherheits-Fix |
|
||||
|
||||
Beispiele:
|
||||
```
|
||||
feat: email verification on registration
|
||||
fix: mobile navbar overflow on small screens
|
||||
chore: update Brevo SMTP config in .env.example
|
||||
```
|
||||
|
||||
## Release-Prozess
|
||||
|
||||
1. `develop` vollständig und getestet
|
||||
2. CHANGELOG.md aktualisieren (`[Unreleased]` → `[x.y.z] - YYYY-MM-DD`)
|
||||
3. Commit auf `develop`, Push
|
||||
4. `develop` → `main` mergen (no-ff)
|
||||
5. Tag `vx.y.z` erstellen und pushen
|
||||
6. Deploy auf Hetzner (siehe [Deployment-Guide](Deployment-Guide))
|
||||
|
||||
## Versionierung
|
||||
|
||||
Semantic Versioning: `MAJOR.MINOR.PATCH`
|
||||
|
||||
| | Wann |
|
||||
|---|---|
|
||||
| PATCH | Bugfixes, kleine Anpassungen |
|
||||
| MINOR | Neue Features, abwärtskompatibel |
|
||||
| MAJOR | Breaking Changes |
|
||||
|
||||
## Codeberg Remote
|
||||
|
||||
```
|
||||
SSH: ssh://git@codeberg.org/Armarium-Suite/armarium-suite.git
|
||||
HTTPS: https://codeberg.org/Armarium-Suite/armarium-suite.git
|
||||
```
|
||||
|
||||
## i18n-Regel
|
||||
|
||||
Neue Texte immer in **allen 4 Sprachdateien** gleichzeitig erfassen:
|
||||
|
||||
```
|
||||
frontend/src/assets/i18n/de.json ← Deutsch (Primärsprache)
|
||||
frontend/src/assets/i18n/en.json
|
||||
frontend/src/assets/i18n/fr.json
|
||||
frontend/src/assets/i18n/it.json
|
||||
```
|
||||
|
||||
## Design-Regeln
|
||||
|
||||
- Primary Color: Violet (`#7c3aed` / `bg-violet-700`)
|
||||
- Icons: Flowbite Outline für Navbar/Modals, Fill für Sidebar-Navigation
|
||||
- Kein Flowbite JS Runtime — alle Interaktionen als Angular Signals
|
||||
- Touch-Targets: mindestens `p-2` auf Icon-Buttons
|
||||
- Mobile-first: `grid-cols-1 sm:grid-cols-2`, `flex-col sm:flex-row`
|
||||
|
||||
## Sicherheits-Checkliste
|
||||
|
||||
Vor jedem Merge in `develop` prüfen:
|
||||
|
||||
- [ ] Keine Credentials im Code (Tokens, Passwörter, API-Keys)
|
||||
- [ ] Neue Endpunkte mit `IsAuthenticated` oder `AllowAny` korrekt gesetzt
|
||||
- [ ] Neue `AllowAny`-Endpunkte mit `AuthThrottle` (5/min) gesichert
|
||||
- [ ] Neue Felder in Serializer-`exclude` wenn nötig
|
||||
- [ ] Migrations erstellt und geprüft
|
||||
- [ ] i18n in allen 4 Sprachen aktualisiert
|
||||
|
||||
+110
@@ -1,2 +1,112 @@
|
||||
# Deployment-Guide
|
||||
|
||||
## Server-Infos
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| Server | `armarium-test` |
|
||||
| IPv4 | `178.104.167.52` |
|
||||
| OS | Ubuntu 24.04 |
|
||||
| SSH | `ssh root@178.104.167.52` |
|
||||
| App-Verzeichnis | `/home/armarium/armarium-suite/` |
|
||||
| Frontend-Dist | `/home/armarium/armarium-suite/frontend/dist/budget-frontend/browser` |
|
||||
| Systemd-Service | `armarium.service` |
|
||||
| Gunicorn Socket | `unix:/run/armarium/armarium.sock` |
|
||||
| Nginx-Config | `/etc/nginx/sites-enabled/` |
|
||||
| Domain | `https://app.armarium.ch` (Certbot, HTTPS) |
|
||||
|
||||
## Deploy-Schritte
|
||||
|
||||
```bash
|
||||
# 1. Einloggen
|
||||
ssh root@178.104.167.52
|
||||
|
||||
# 2. Code aktualisieren
|
||||
cd /home/armarium/armarium-suite
|
||||
git pull origin main
|
||||
|
||||
# 3. Backend: Abhängigkeiten + Migrationen
|
||||
cd backend
|
||||
source venv/bin/activate
|
||||
pip install -r requirements.txt --quiet
|
||||
python manage.py migrate
|
||||
|
||||
# 4. Frontend bauen
|
||||
cd ../frontend
|
||||
npm install --silent
|
||||
npm run build -- --configuration production
|
||||
|
||||
# 5. Service neu starten
|
||||
systemctl restart armarium
|
||||
```
|
||||
|
||||
## Logs
|
||||
|
||||
```bash
|
||||
# Live-Logs (Gunicorn/Django)
|
||||
journalctl -u armarium -f
|
||||
|
||||
# Nginx Access-Log
|
||||
tail -f /var/log/nginx/access.log
|
||||
```
|
||||
|
||||
## .env auf dem Server
|
||||
|
||||
Die Datei `/home/armarium/armarium-suite/backend/.env` ist **nicht im Repo** und muss nach dem ersten Setup manuell gepflegt werden.
|
||||
|
||||
Neue Variablen nach einem Update manuell ergänzen:
|
||||
|
||||
```bash
|
||||
nano /home/armarium/armarium-suite/backend/.env
|
||||
```
|
||||
|
||||
### Wichtige Produktions-Variablen
|
||||
|
||||
```env
|
||||
SECRET_KEY=...
|
||||
DEBUG=False
|
||||
ALLOWED_HOSTS=178.104.167.52,app.armarium.ch
|
||||
CSRF_TRUSTED_ORIGINS=https://app.armarium.ch
|
||||
CORS_ALLOWED_ORIGINS=https://app.armarium.ch
|
||||
DB_NAME=armarium_db
|
||||
DB_USER=armarium_user
|
||||
DB_PASSWORD=...
|
||||
DB_HOST=localhost
|
||||
DB_PORT=5432
|
||||
TURNSTILE_SECRET_KEY=...
|
||||
FRONTEND_URL=https://app.armarium.ch
|
||||
EMAIL_HOST=smtp-relay.brevo.com
|
||||
EMAIL_PORT=587
|
||||
EMAIL_USE_TLS=True
|
||||
EMAIL_HOST_USER=...
|
||||
EMAIL_HOST_PASSWORD=...
|
||||
DEFAULT_FROM_EMAIL=noreply@armarium.ch
|
||||
```
|
||||
|
||||
## Nginx
|
||||
|
||||
Nginx-Config unter `/etc/nginx/sites-enabled/`. Nach Änderungen:
|
||||
|
||||
```bash
|
||||
nginx -t && systemctl reload nginx
|
||||
```
|
||||
|
||||
> **Wichtig:** Die `/api/`- und `/admin/`-Location-Blöcke müssen `proxy_set_header X-Forwarded-Proto https;` enthalten — sonst erzeugt Django's `SECURE_SSL_REDIRECT` eine 301-Schleife.
|
||||
|
||||
## E-Mail testen
|
||||
|
||||
```bash
|
||||
cd /home/armarium/armarium-suite/backend
|
||||
source venv/bin/activate
|
||||
python manage.py shell
|
||||
```
|
||||
|
||||
```python
|
||||
from finance.email import send_email
|
||||
send_email('password_changed', {}, 'Test', 'deine@email.ch')
|
||||
```
|
||||
|
||||
## Bekannte Hinweise
|
||||
|
||||
- Roboto-Fonts erscheinen als 404 in Nginx-Logs (`/media/roboto-*`) — unkritisch, Fonts laden aus dem Angular-Bundle
|
||||
- `DEBUG=False` aktiviert automatisch SMTP, HTTPS-Redirect, HSTS und Secure Cookies
|
||||
|
||||
+111
@@ -1,2 +1,113 @@
|
||||
# Developer Setup
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- WSL2 (Ubuntu) auf Windows — oder direkt Linux/macOS
|
||||
- Python 3.12
|
||||
- Node.js 20+
|
||||
- PostgreSQL
|
||||
- Git
|
||||
|
||||
## Repository klonen
|
||||
|
||||
```bash
|
||||
git clone ssh://git@codeberg.org/Armarium-Suite/armarium-suite.git
|
||||
cd armarium-suite
|
||||
```
|
||||
|
||||
## Backend Setup
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
|
||||
# Virtuelle Umgebung erstellen und aktivieren
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
|
||||
# Abhängigkeiten installieren
|
||||
pip install -r requirements.txt
|
||||
|
||||
# .env erstellen (Vorlage: .env.example)
|
||||
cp .env.example .env
|
||||
# .env mit eigenen Werten befüllen (DB, Secret Key, etc.)
|
||||
|
||||
# Datenbank erstellen (PostgreSQL)
|
||||
createdb budget_db
|
||||
|
||||
# Migrationen anwenden
|
||||
python manage.py migrate
|
||||
|
||||
# Entwicklungsserver starten
|
||||
python manage.py runserver
|
||||
```
|
||||
|
||||
### Wichtige `.env`-Variablen
|
||||
|
||||
```env
|
||||
SECRET_KEY=...
|
||||
DEBUG=True
|
||||
ALLOWED_HOSTS=localhost,127.0.0.1
|
||||
DB_NAME=budget_db
|
||||
DB_USER=...
|
||||
DB_PASSWORD=...
|
||||
DB_HOST=localhost
|
||||
DB_PORT=5432
|
||||
TURNSTILE_SECRET_KEY=... # Cloudflare Turnstile (bei DEBUG=True automatisch bypassed)
|
||||
EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend # Brevo auch lokal nutzen
|
||||
EMAIL_HOST=smtp-relay.brevo.com
|
||||
EMAIL_PORT=587
|
||||
EMAIL_USE_TLS=True
|
||||
EMAIL_HOST_USER=...
|
||||
EMAIL_HOST_PASSWORD=...
|
||||
DEFAULT_FROM_EMAIL=noreply@armarium.ch
|
||||
FRONTEND_URL=http://localhost:4200
|
||||
```
|
||||
|
||||
> Bei `DEBUG=True` werden Mails standardmässig nur im Terminal ausgegeben. `EMAIL_BACKEND` auf SMTP setzen um Brevo auch lokal zu nutzen.
|
||||
|
||||
## Frontend Setup
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
|
||||
# Abhängigkeiten installieren
|
||||
npm install
|
||||
|
||||
# Dev-Server starten (Proxy zu Django auf :8000)
|
||||
npm start
|
||||
```
|
||||
|
||||
Die App ist dann unter `http://localhost:4200` erreichbar. Der Angular Dev-Server proxied `/api/`-Requests automatisch via `proxy.conf.json` zu Django.
|
||||
|
||||
## Beide Server gleichzeitig starten
|
||||
|
||||
```bash
|
||||
# Im Root-Verzeichnis
|
||||
./start.sh
|
||||
```
|
||||
|
||||
## Branch-Strategie
|
||||
|
||||
| Branch | Zweck |
|
||||
|---|---|
|
||||
| `main` | Produktions-Stand, entspricht dem Live-Server |
|
||||
| `develop` | Aktiver Entwicklungs-Branch, Basis für Features |
|
||||
| `feature/*` | Feature-Branches, werden in `develop` gemergt |
|
||||
|
||||
## i18n
|
||||
|
||||
Alle 4 Sprachdateien immer gleichzeitig aktualisieren:
|
||||
|
||||
```
|
||||
frontend/src/assets/i18n/de.json
|
||||
frontend/src/assets/i18n/en.json
|
||||
frontend/src/assets/i18n/fr.json
|
||||
frontend/src/assets/i18n/it.json
|
||||
```
|
||||
|
||||
## Design System
|
||||
|
||||
- **Primary Color**: Violet (`#7c3aed`)
|
||||
- **Theme**: `frontend/src/budget-app-theme.css` (Tailwind v4)
|
||||
- **Icons**: Flowbite Outline für Navbar/Modals, Fill für Sidebar-Navigation
|
||||
- **Kein Flowbite JS**: Dropdowns/Modals als Angular Signals (`signal<boolean>`)
|
||||
|
||||
@@ -1,2 +1,152 @@
|
||||
# Feature-Dokumentation
|
||||
|
||||
## Authentifizierung
|
||||
|
||||
### Registrierung
|
||||
- E-Mail + Passwort (min. 8 Zeichen)
|
||||
- Cloudflare Turnstile CAPTCHA
|
||||
- Nach Registrierung: Bestätigungsmail mit Link (24h gültig)
|
||||
- Route: `/register`
|
||||
|
||||
### Login
|
||||
- E-Mail-basiert (kein Username), case-insensitiv
|
||||
- "Angemeldet bleiben"-Checkbox: `localStorage` (persistent) vs. `sessionStorage`
|
||||
- Bei aktivierter 2FA: zweistufiger Flow (Credentials → TOTP-Code)
|
||||
- Route: `/login`
|
||||
|
||||
### Passwort vergessen
|
||||
- E-Mail eingeben → Reset-Link per Mail (15min gültig)
|
||||
- Anti-Enumeration: gleiche Antwort unabhängig ob Konto existiert
|
||||
- Route: `/forgot-password`
|
||||
|
||||
### Passwort zurücksetzen
|
||||
- Token aus Mail-Link, neues Passwort eingeben
|
||||
- Bei Erfolg: alle aktiven Sessions werden invalidiert
|
||||
- Route: `/reset-password?token=...`
|
||||
|
||||
### E-Mail-Verifikation
|
||||
- Token aus Bestätigungsmail, automatische Verifikation beim Laden
|
||||
- Route: `/verify-email?token=...`
|
||||
|
||||
---
|
||||
|
||||
## 2-Faktor-Authentifizierung (2FA)
|
||||
|
||||
- **Setup**: QR-Code scannen mit Authenticator-App (Proton Pass, Aegis, Raivo OTP)
|
||||
- **Login**: 6-stelliger TOTP-Code, wechselt alle 30 Sekunden
|
||||
- **Backup-Codes**: 8 Codes im Format `XXXXXXXX-XXXXXXXX`, SHA-256-Hash in DB; Copy + PDF-Download
|
||||
- **Recovery**: E-Mail-Code (15min) wenn Gerät verloren; deaktiviert 2FA
|
||||
- Verwaltung unter: `/settings`
|
||||
|
||||
---
|
||||
|
||||
## Dashboard (`/dashboard`)
|
||||
|
||||
### KPI-Cards
|
||||
- Gesamteinnahmen, Fixkosten, Variable Ausgaben, Verfügbarer Betrag, Sparquote
|
||||
|
||||
### Einnahmen vs. Ausgaben (Bar Chart)
|
||||
- 3 Serien: Einnahmen, Fixkosten, Variable Ausgaben
|
||||
- Jahres-Dropdown (öffnet nach oben)
|
||||
- ApexCharts, custom Tooltip in Landessprache
|
||||
|
||||
### Fixkostenaufschlüsselung (Pie Chart)
|
||||
- %-Labels direkt auf Segmenten
|
||||
- Toggle-Button wechselt zur Listenansicht (Name, CHF, %)
|
||||
|
||||
### Sparquote
|
||||
- Progress-Bar mit Violet Ziel-Marker
|
||||
- Ziel personalisierbar über Settings-Toggle (gespeichert im Profil)
|
||||
|
||||
---
|
||||
|
||||
## Jahresplanung (`/financial-year`)
|
||||
|
||||
- **Jahres-Dropdown**: verfügbare Jahre auswählen
|
||||
- **3 Summary-Cards**: Einnahmen, Fixkosten, Verfügbar + Sparquote
|
||||
- **Tab Einnahmen**: Inline-CRUD für Einnahmequellen pro Jahr
|
||||
- **Tab Fixkosten**: Inline-CRUD für Fixkostenpositionen pro Jahr
|
||||
- **Neues Jahr starten**: max. 1 Jahr im Voraus, Daten aus Vorjahr kopierbar
|
||||
- **Haushalt**: gemeinsamen Haushalt gründen, Mitglieder einladen, Rollen verwalten
|
||||
|
||||
---
|
||||
|
||||
## Kalender (`/calendar`)
|
||||
|
||||
- Jahresansicht mit Monats-Klick für Detailansicht
|
||||
- Schweizer Feiertage und Schulferien nach Kanton (OpenHolidays API, mit Fallback)
|
||||
- Persönliche Termine (Deadlines) einpflegen
|
||||
- iCal-Feed abonnieren (persönlicher Link unter Einstellungen)
|
||||
|
||||
---
|
||||
|
||||
## Konten (`/accounts`)
|
||||
|
||||
- Drei Kontotypen: Asset (Bank/Cash), Expense (Empfänger), Revenue (Einnahmequelle)
|
||||
- Vollständiges CRUD
|
||||
|
||||
---
|
||||
|
||||
## Budgets (`/budgets`)
|
||||
|
||||
- 7 Kategorien: Fixkosten, Mobilfunk/Internet, Abonnements, Freizeit, Steuerrücklagen, Versicherungen, Kredite
|
||||
- Info-Modal wenn keine Konten vorhanden
|
||||
|
||||
---
|
||||
|
||||
## Ausgaben (`/expenses`)
|
||||
|
||||
- 10 Kategorien, optionales Fälligkeitsdatum
|
||||
- Kategoriefilter
|
||||
- Info-Modal wenn keine Konten vorhanden
|
||||
|
||||
---
|
||||
|
||||
## Transaktionen (`/transactions`)
|
||||
|
||||
- Doppelte Buchführung (Source + Destination Account)
|
||||
- Vollständiges CRUD
|
||||
|
||||
---
|
||||
|
||||
## Einstellungen (`/settings`)
|
||||
|
||||
| Bereich | Beschreibung |
|
||||
|---|---|
|
||||
| Profil | Avatar, Name, Kanton, Sprache, Recovery-E-Mail |
|
||||
| 2FA | Aktivieren/Deaktivieren, QR-Code, Backup-Codes |
|
||||
| Aktive Sessions | Alle eingeloggten Geräte, einzeln widerrufbar |
|
||||
| Benachrichtigungen | Toggles für Termine, Budget-Warnungen, Monatszusammenfassung |
|
||||
| Datenexport | ZIP mit 6 PDFs (Profil, Konten, Budgets, Ausgaben, Transaktionen, Termine) |
|
||||
| Danger Zone | Account löschen (dreistufig: Export → Passwort + Phrase → Redirect) |
|
||||
|
||||
---
|
||||
|
||||
## E-Mail-Benachrichtigungen
|
||||
|
||||
| Trigger | Template | Gültigkeit |
|
||||
|---|---|---|
|
||||
| Registrierung | `registration_confirm` | 24h |
|
||||
| Passwort zurücksetzen | `password_reset` | 15min |
|
||||
| Passwort geändert | `password_changed` | — |
|
||||
| E-Mail-Adresse geändert | `email_changed` | — |
|
||||
| 2FA-Recovery | `2fa_recovery` | 15min |
|
||||
|
||||
Alle Mails: HTML + Plaintext-Fallback, Absender `noreply@armarium.ch` via Brevo.
|
||||
|
||||
---
|
||||
|
||||
## Lokalisierung
|
||||
|
||||
- 4 Sprachen: Deutsch, Englisch, Französisch, Italienisch
|
||||
- Sprachwahl auf Login/Register und in den Einstellungen
|
||||
- Browser-Sprache wird automatisch erkannt
|
||||
- Schweizer Feiertage in der gewählten App-Sprache
|
||||
|
||||
---
|
||||
|
||||
## Globale Suche
|
||||
|
||||
- Suche über Konten, Budgets, Ausgaben, Transaktionen, Termine
|
||||
- Mindestlänge: 2 Zeichen
|
||||
- Erreichbar via Suchfeld in der Navbar
|
||||
|
||||
Reference in New Issue
Block a user