Feature: Tierschutz-Check, KI-Züchter-Features, Export, SEO-Update

Tierschutz-System (immer aktiv, nicht abschaltbar):
- welfare_check.py: regelbasierte Prüfung IK, Alter, Deckpause, Wurfanzahl, Genetik
- Grün/Gelb/Rot-Modal bei Wurf anlegen + Probeverpaarung
- Bei kritischem Befund + "Trotzdem fortfahren" → automatische Admin-Mail
- Tierschutz-Check nie durch Nutzer deaktivierbar

KI-Züchter-Features (pro User an/abschaltbar außer Tierschutz):
- routes/zucht_ki.py: 5 Endpunkte — Wurfankündigung, Genetik-Erklärung,
  Paarungsanalyse, Hund-Beschreibung, Jahresbericht
- Toggles in Einstellungen (ki_zucht_* Felder)
- KI-Buttons in litters.js + zuchthunde.js

KI-Routing: Privilegierte Rollen (Admin, Züchter, Moderator, Manager)
nutzen Claude Sonnet primär, lokales LLM als Fallback

Datenexport: routes/breeder_export.py — ZIP mit HTML-Dossier + ODS
(odfpy hinzugefügt in requirements.txt)

Admin-Profil: POST /admin/breeder/create-profile für Schnellprofil ohne
Antragsprozess; Admin-Rolle bleibt erhalten

Wurfformular: Dropdown aus Zuchtkartei für Vater/Mutter mit Auto-Fill;
litters.vater_id + mutter_id als FK auf zucht_hunde

Probeverpaarung: heart-fill Icon + Welfare-Block im Ergebnis

Landing Page: Züchter-Section + Feature-Gruppe, Meta-Tags, JSON-LD,
keywords, softwareVersion 2.1

SEO: llms.txt vollständig überarbeitet, robots.txt Züchter-Pfade,
sitemap.xml um Wurfbörse + Züchter-Profile erweitert

SW by-v474, APP_VER 451
This commit is contained in:
rene 2026-04-28 19:49:54 +02:00
parent 91340be5a3
commit c8ae514c01
20 changed files with 2129 additions and 200 deletions

View file

@ -160,6 +160,8 @@ from routes.breeder import router as breeder_router
from routes.litters import router as litters_router
from routes.breeder_photos import router as breeder_photos_router
from routes.zucht_hunde import router as zucht_hunde_router
from routes.breeder_export import router as breeder_export_router
from routes.zucht_ki import router as zucht_ki_router
app.include_router(auth_router, prefix="/api/auth", tags=["Auth"])
app.include_router(dogs_router, prefix="/api/dogs", tags=["Hunde"])
@ -189,6 +191,8 @@ app.include_router(breeder_router, prefix="/api", tags=["Züchter"
app.include_router(litters_router, prefix="/api", tags=["Würfe"])
app.include_router(breeder_photos_router, prefix="/api", tags=["Züchter-Fotos"])
app.include_router(zucht_hunde_router, prefix="/api", tags=["Zuchtkartei"])
app.include_router(breeder_export_router, prefix="/api", tags=["Export"])
app.include_router(zucht_ki_router, prefix="/api", tags=["Züchter-KI"])
app.include_router(webcal_router, prefix="/api/webcal", tags=["WebCal"])
app.include_router(profile_router, prefix="/api/profile", tags=["Profil"])
app.include_router(import_router, prefix="/api/import", tags=["Import"])
@ -255,6 +259,7 @@ async def sitemap():
("https://banyaro.app/info", "monthly", "0.9"),
("https://banyaro.app/wiki/rassen", "weekly", "0.8"),
("https://banyaro.app/knigge", "monthly", "0.8"),
("https://banyaro.app/wurfboerse", "daily", "0.8"),
]
try:
@ -262,8 +267,6 @@ async def sitemap():
rassen = conn.execute(
"SELECT slug FROM wiki_rassen WHERE slug IS NOT NULL AND slug != '' LIMIT 500"
).fetchall()
if rassen:
urls.append(("https://banyaro.app/wiki/rassen", "weekly", "0.8"))
for r in rassen:
urls.append((f"https://banyaro.app/wiki/rasse/{r['slug']}", "monthly", "0.7"))
@ -272,6 +275,20 @@ async def sitemap():
).fetchall()
for e in events:
urls.append((f"https://banyaro.app/api/events/{e['id']}", "weekly", "0.5"))
# Öffentliche Züchter-Profile
breeders = conn.execute(
"SELECT bp.zwingername FROM breeder_profiles bp "
"JOIN users u ON u.id = bp.user_id "
"WHERE bp.verified_at IS NOT NULL AND u.rolle = 'breeder'"
).fetchall()
for b in breeders:
if b["zwingername"]:
from urllib.parse import quote
urls.append((
f"https://banyaro.app/breeder/{quote(b['zwingername'])}",
"weekly", "0.7"
))
except Exception:
pass