5886e1b269
UX: Upgrades-Tab — Button zeigt vorhandene Rechnung an, SW by-v1074
...
- Backend: /admin/upgrade-requests liefert pro Request die offene
Rechnung (id+number+status) per Subquery aus der invoices-Tabelle
(status draft|sent → also nicht bezahlt, nicht storniert)
- Frontend: Wenn schon eine Rechnung existiert, wird statt 'Rechnung
erstellen' (orange) der Button 'Rechnung bearbeiten' (gelb,
#eab308) gezeigt. Klick lädt die Rechnung und öffnet das Modal im
Edit-Modus — kein doppeltes Anlegen, Nummerierung bleibt sauber.
2026-05-26 13:50:03 +02:00
c03884cb81
Perf: 9 Performance-Fixes — SW by-v1072
...
Backend:
- DB: 3 neue Indizes (forum_posts thread+user, routes user) — Forum/Routen-Queries
- Caching: cache.py (TTL-Cache ohne neue Dependency) für 5 statische Listen
(training_exercises, pflege_tipps, wiki_stats, wiki_gruppen, help_articles)
- diary.py + breeder_photos.py: Bildverarbeitung (ffmpeg/PIL/EXIF) per
run_in_executor → blockiert Event-Loop nicht mehr
- scheduler.py: 11 kollidierende Jobs auf 5-Min-Intervalle gestaggert, coalesce=True
- social.py: ORDER BY RANDOM() ohne LIMIT in 2 Stellen gefixt
- alerts.py: Haversine-Loop bekommt SQL-Bounding-Box-Vorfilter
Frontend:
- sw.js: Tile-Cache mit LRU-Eviction (max 500 Einträge)
- admin.js: Event-Listener-Leak — Tab-Klicks per Delegation statt N Listener
- api.js: compressImage() Helper — Client-seitiges Resize auf max 2000px
(HEIC/Videos/<500KB unverändert), integriert in 8 Upload-Stellen
(diary, dog-profile×2, walks, poison, lost, health×2)
Bump APP_VER 1071 → 1072 (sw.js, app.js, main.py, index.html)
2026-05-26 06:30:36 +02:00
3abf974d29
Feature: Parallele Bild-Uploads, Heartbeat last_seen, Admin zuletzt aktiv, SW by-v1071
...
- Tagebuch: Bilder werden parallel hochgeladen (Promise.all), Button zeigt Fortschritt
- Auth: /heartbeat Route ergänzt — aktualisiert last_seen alle 5 Min
- Admin: last_seen + last_login in Nutzer-Liste angezeigt (🟢 /🔵 /⚪ )
- Bump SW by-v1071
2026-05-25 20:26:58 +02:00
738571d958
Fix: Verlauf-Tab kein Endlos-Spinner + Save-422 bei null-Feldern
...
- Verlauf: _verlaufLoading-Flag verhindert parallele Loads
- Verlauf: el nach await neu holen (stale DOM-Referenz nach Re-Render)
- Verlauf: bei _renderContent() Shell nur rendern wenn keine Sessions im Cache
- Backend: hund_stimmung/zufriedenheit als Optional[str/int] → akzeptiert null
2026-05-19 18:28:56 +02:00
cc841ef6d7
Feature: Trainingsprotokoll-Tab in Übungen, kein Tagebuch-Spam
...
- Neuer Tab 'Protokoll' in der Übungen-Seite: zeigt alle Trainingseinheiten
chronologisch nach Datum gruppiert (Heute/Gestern/Datum-Label)
- Jede Einheit: Übungsname, Wdh., Erfolgs-Emoji, Stimmung, Sterne, Notiz, TOP-Badge
- 'Weitere laden' Pagination (30 Einheiten pro Seite)
- Backend: Training erstellt keine Tagebuch-Einträge mehr (weder bei ist_top noch manuell)
- Frontend: 'Als Meilenstein ins Tagebuch' Checkbox komplett entfernt
- onDogChange setzt Verlauf-State zurück
2026-05-19 18:17:50 +02:00
a1c4d2ab2b
Fix: /me-Endpoint gibt geburtstag zurück (war vergessen)
2026-05-16 12:57:19 +02:00
b54d9fda99
Fix: users.geburtstag Migration + Format TT.MM statt MM-DD
...
- database.py: ALTER TABLE users ADD COLUMN geburtstag TEXT (fehlte!)
- profile.py: Validierung auf \d{2}\.\d{2} (TT.MM Format)
- settings.js: Placeholder/Pattern auf TT.MM geändert
- worlds.js: Birthday-Check auf DD.MM Format angepasst
SW by-v1029, APP_VER 1029
2026-05-16 12:02:52 +02:00
a4377033ec
Feature: User-Geburtstag im Profil + Glückwunsch in JETZT-Welt
...
Settings:
- Feld 'Dein Geburtstag (optional)' im Profil-Formular (Format MM-TT)
- Hinweis: nur für Geburtstagsgrüße, kein Jahr nötig
- profile.py: geburtstag gespeichert + Format-Validierung MM-DD
JETZT-Welt wenn heute User-Geburtstag:
- Greet-Text: 'Herzlichen Glückwunsch' statt Tageszeit-Gruß
- Animiertes Geburtstags-Reminder-Card (confetti + cake Icons)
- 'Alles Gute zum Geburtstag, [Name]!'
SW by-v1028, APP_VER 1028
2026-05-16 11:55:34 +02:00
be9f263e0d
Feature: Stats-Band + Tagebuch-Einträge, km alle Routen (public+privat)
...
- landing.html: neues Stats-Band-Element 'Tagebuch-Einträge' (#big-diary)
mit Wert aus diary_entries (war bereits im API-Response vorhanden)
- stats.py km-Query: explizit WHERE is_valid=1 (kein is_public-Filter —
private Routen werden mitgezählt, nur ungültige Aufzeichnungen ausgeschlossen)
- SW by-v998, APP_VER 998
2026-05-15 18:34:03 +02:00
c59326af17
Fix+Polish: Phosphor-Icons Danke-Overlay, Quartalsbericht paid_amount
...
Giftköder Danke-Overlay (poison.js):
- Emoji 🚨 /🐾 /📡 durch Phosphor-Icons ersetzt: siren, paw-print, wifi-slash
Quartalsbericht (invoices.py + admin.js):
- Backend: _effective_gross() — für bezahlte Rechnungen wird paid_amount statt
amount_gross für die Quartalssumme verwendet (Kulanz/Teilzahlung korrekt)
- Admin-Preview: effectiveAmt in der Vorschau-Tabelle, bei Abweichung Hinweis
"(RG: xx,xx €)" für Nachvollziehbarkeit
- CSV: Spalte "Betrag (eingegangen)" + separate Spalte "Rechnungsbetrag"
- SW by-v995, APP_VER 995
2026-05-15 18:18:22 +02:00
3fae57a0e2
Feat: Kontaktformular im Impressum + /api/contact Endpoint ohne Auth (SW by-v986)
2026-05-15 16:46:37 +02:00
e714580d77
Feat: Cashflow auf paid_amount, Differenz-Badge, Kulanz-Abschreibung im Bezahlt-Modal (SW by-v984)
2026-05-15 16:06:08 +02:00
0f6b5afd6a
Fix: Syntaxfehler in invoices.py — fehlende schließende Klammer bei _s()
2026-05-15 15:56:25 +02:00
68fd9c0e38
Fix: En-Dash in PDF durch Bindestrich ersetzen + _s() Sanitizer für alle Texteingaben (SW by-v982)
2026-05-15 15:50:02 +02:00
78f3077317
UX: Freischalten zeigt Rechnungsentwurf-Nummer im Toast + Confirm-Hinweis (SW by-v980)
2026-05-15 14:01:45 +02:00
49e01683ad
Fix: 'Fällig bis' Umlaut korrigiert im PDF-Info-Block
2026-05-15 13:51:26 +02:00
ed6dd8da13
Fix: Quartalssumme korrekt (alle inkl. Storno), Netto ausgeblendet (SW by-v977)
2026-05-15 13:38:08 +02:00
6104132714
Feat: Quartalsbericht — Stornozeilen mit Minusbeträgen, nach Datum sortiert, Summen netten sich heraus (SW by-v976)
2026-05-15 13:27:05 +02:00
b10b3140eb
Fix: Stornorechnung referenziert Originalnummer + Datum (§14 UStG Pflicht)
2026-05-15 13:18:32 +02:00
cabb2fd6f7
Fix: iOS Modal scrollIntoView bei Tastatur; CSV Stornierte mit 0€ + Stornonummer (SW by-v975)
2026-05-15 13:15:49 +02:00
8f3d639e34
Fix: Stornierte/Entwurfs-Rechnungen aus Quartalsbericht und Cashflow-Summen ausgeschlossen
2026-05-15 12:49:04 +02:00
aea5f04bc1
Fix: Von-Gründer-eingeladen → 100% dauerhaft (statt 50%); SW by-v972
2026-05-15 12:25:41 +02:00
2163169b73
Feat: Rabattsystem in Rechnungserstellung integriert (Gründer/Referral)
...
- _get_discount_info() Hilfsfunktion in admin.py (Gründer 100%, Referral-Stufen 20/30/50%, von Gründer eingeladen 50%)
- list_upgrade_requests liefert discount_pct + discount_reason pro User
- GET /admin/users/{user_id}/discount Endpoint
- _handle_upgrade_invoices nutzt Rabatt für amount_net/discount_pct/after_disc + passende Notiz
- scheduler.py _create_renewal_invoice_draft: inline Rabattberechnung + korrekte Beträge
- admin.js: Discount-Badge in Upgrade-Card, data-Attribute am Invoice-Button, _discountNote(), discount_pct + notes im Modal vorbelegt
2026-05-15 12:21:33 +02:00
699926cd76
Fix: Rechnung-Hinweistext auf AGB-konforme Jahresbeitrags-Notiz umgestellt
...
Alle drei Rechnungs-Einstiegspunkte (Admin-Upgrade-Button, automatische
Verlängerung via Scheduler, manuelles Upgrade via admin.py) erhalten jetzt
den einheitlichen Hinweis zum Jahresbeitrag gem. AGB ohne Rückerstattung.
2026-05-15 12:06:05 +02:00
a9f7923716
Feat: Kündigung blockt Erneuerungsentwurf; Upgrade storniert alte Rechnungen + legt neuen Entwurf an
2026-05-15 12:00:27 +02:00
b14a251bdc
Feat: Entwurf bearbeiten (PATCH), erneut senden; SW by-v968
2026-05-15 11:33:48 +02:00
a2d089bce4
Fix: SMTP_SUPPORT_PASS Fallback in mailer, scaninput Logging
2026-05-15 11:29:16 +02:00
41a4808ad5
Fix: Storno sendet PDF+Mail+Scaninput; /scaninput Volume in staging ergänzt
2026-05-15 11:18:48 +02:00
8e36eb0611
Fix: PDF — breiter Header-Balken mit Logo, eine Seite, Hinweis-Prefix, Footer fix
2026-05-15 11:13:28 +02:00
0a466ef6ce
Feat: Rechnungsadresse — Profil, Upgrade-Modal Hinweis, Rechnung-erstellen-Button in Upgrade-Cards (SW by-v967)
2026-05-15 10:59:12 +02:00
95b70d5119
Fix: Rechnungs-PDF komplett neu — DIN-5008-Layout, Überlagerung behoben, Bankverbindung, Footer, Deutsche Formatierung
2026-05-15 10:45:49 +02:00
5dddacff96
Feat: Admin action-items invoices_unpaid, CSV-Download, Quartalsbericht-Versand
2026-05-15 10:06:04 +02:00
77093774f9
Feat: Admin-Rechnungs-Endpoints — invoices_unpaid, CSV-Download, Quartalsbericht-Versand
...
- action_items(): invoices_unpaid (status='sent') zum Return-Dict hinzugefügt
- GET /api/admin/invoices/quarterly/{year}/{q}/csv — CSV-Download (Semikolon-getrennt, UTF-8-BOM für Excel)
- POST /api/admin/invoices/send-quarterly-report — sendet CSV-Anhang an Steuerberater + Zusammenfassung an René (SMTP_FROM); graceful fallback wenn attachments noch nicht von mailer.py unterstützt
2026-05-15 10:04:46 +02:00
b68a12587a
Feature: Rechnungs-System (invoices) — Backend komplett
...
- DB-Migration: invoices + invoice_items Tabellen inkl. Indizes
- routes/invoices.py: vollständiger Admin-Router (prefix /api/admin/invoices)
- CRUD: Liste, Detail, Erstellen, Senden, Bezahlen, Stornieren
- PDF-Generierung via fpdf2 mit §14-UStG-Pflichtangaben (Kleinunternehmer-Hinweis)
- Cashflow-Übersicht und Quartalsbericht
- PDF-Download-Endpunkt
- Speicherung in /scaninput + optionaler Paperless-Upload
- mailer.py: send_email() + Backends um optionale PDF-Anhänge erweitert
(Brevo: base64, SMTP: MIMEApplication)
- main.py: invoices_router registriert
- docker-compose.yml: /volume1/scaninput:/scaninput Volume hinzugefügt
2026-05-15 10:04:23 +02:00
c032b9a3fb
Fix: Stats-Kotbeutel → waste_basket Typ in osm_pois (zeigt echte Mülleimer-Zahl)
2026-05-14 22:47:14 +02:00
6495a5ff6b
Fix: Stats-Kotbeutel aus osm_pois statt user_map_pois (zeigt 125.750 statt 2)
2026-05-14 22:45:50 +02:00
07db68aea2
Fix: Geburtstag aller Hunde + Kotbeutel-Stationen in Stats (SW by-v962)
...
- worlds.js: bdayDog = _dogs.find(...) — Geburtstag gilt für alle Hunde, nicht nur den aktiven
- Banner, KI-Call, "Was hat sich X gewünscht?" nutzen bdayDog.name
- stats.py: kotbeutel-Count aus user_map_pois WHERE type='kotbeutel'
- landing: Stats-Band 5. Kachel "Kotbeutel-Stationen"
2026-05-14 22:00:52 +02:00
f9160307bc
Landing: emotionaler Hero, Social-Proof-Stats, Testimonial-Slots, Scroll-Animationen (SW by-v952)
...
- Hero-Headline: "Weil jeder Moment mit ihm zählt." (warm/emotional statt Feature-Liste)
- CTA umbenannt: "Kostenlos starten" statt "Ich bin Hundebesitzer"
- Hero-Stats-Zeile: live Nutzer/Hunde/km-Zähler (nur wenn >0)
- Stats-Band: orangener Balken mit 4 Live-Kennzahlen nach der Zwei-Welten-Section
- Testimonial-Section: 3 Platzhalter-Karten zwischen Features und Züchter-Bereich
- Scroll-Animationen: IntersectionObserver auf alle Cards (fade-up)
- API: /api/stats/public — öffentlicher Endpoint, 5-Min-Cache
2026-05-14 18:23:23 +02:00
35bc38eb34
Fix: Analytics-Tab zeigt verständliche Fehlermeldung bei Umami-Auth-Fehler
2026-05-14 17:01:46 +02:00
0bd4c33557
Fix: Kündigungs-Mail + Settings — Ablaufdatum korrekt formatiert (SW by-v950)
2026-05-14 16:47:57 +02:00
3b666c545f
Feature: Abo-Kündigung + Ablaufdatum + Dog-Auswahl nach Downgrade (SW by-v945)
2026-05-14 13:56:55 +02:00
6762efa04e
UX: Upgrade-Freischaltung — reichhaltige HTML-Bestätigungsmail (SW by-v941)
2026-05-14 13:17:23 +02:00
163a6ff6a5
Fix: upgrade_requests Query in action_items try/except — schützt bestehende Action Items
2026-05-14 13:01:51 +02:00
947832f63d
Fix+Debug: generate-previews mit Dir-Info + no such column fix (SW by-v939)
2026-05-14 12:54:31 +02:00
8080d7cda1
Fix: no such column d.user_id — diary hat kein user_id, Dog-Check reicht (SW by-v939)
2026-05-14 12:48:05 +02:00
3f0e09e5d2
Perf: Wiki Breed-Fotos nutzen _preview.webp + breeds/ in generate-previews (SW by-v938)
2026-05-14 12:42:20 +02:00
567478a866
Fix: Altes Hundeprofil-Foto wird beim Überschreiben gelöscht (SW by-v930)
...
- dogs.py /photo: alte foto_url vor Upload merken, nach Speichern von Disk löschen
- dog-profile.js: Hintergrund-Cache nach Foto-Wechsel invalidieren
2026-05-14 11:47:08 +02:00
00457f52f9
Fix: Datenschutz Hintergrundbild + Dog-Refresh nach Anlegen (SW by-v928)
...
- dogs.py: welcome-dashboard Foto-Queries filtern jetzt auch nach user_id
- worlds.js: Background Cache-Key enthält user_id (kein Cross-User Leakage)
- worlds.js: Worlds.refresh(appState) neu
- dog-profile.js: Worlds.refresh() nach Hund anlegen aufrufen
2026-05-14 11:35:53 +02:00
4332b1195e
Refactor: Züchter-Antrag in Upgrade-Flow integriert (SW by-v925)
...
- /breeder/apply: Dokument jetzt optional (File(None)), kann per Mail nachgereicht werden
- _showUpgradeModal('breeder'): enthält jetzt Zwinger-Formular (Zwingername*, Rasse*,
Verein, Stadt, VDH-Checkbox, optionales Dokument)
→ sendet /breeder/apply + /auth/upgrade-request in einem Schritt
- Züchter-Profil-Karte in Settings: 'Züchter werden'-Button entfernt
→ für neue User ohne Antrag wird die Card vollständig ausgeblendet
→ 'Neu beantragen' bei Ablehnung öffnet jetzt _showUpgradeModal('breeder')
- Verifizierte Züchter: Card unverändert (Profil, Edit, KI-Settings)
2026-05-14 11:17:49 +02:00
706e84186e
Fix: Admin Züchter-Liste — NULLS LAST durch CASE ersetzen, is_zucht_hund entfernt
2026-05-14 10:14:47 +02:00