Backend Sprint 2+3: Health-Modul, Multi-Dog Tagebuch, Pillow, Migrations

- database.py: diary_dogs + walk_participant_dogs Tabellen, idempotente
  Migration für Health-Felder (charge_nr, kosten, diagnose, …), Backfill
- routes/health.py: vollständiges Health-Modul (war Stub), CRUD für
  Impfung/Entwurmung/Tierarzt/Medikament/Gewicht/Allergie/Dokument
- routes/diary.py: Multi-Dog n:m via diary_dogs (dog_ids in allen Endpoints)
- routes/dogs.py: Foto-Upload konvertiert HEIC/PNG/WebP → JPEG via Pillow
- routes/poison.py: Resolve mit Grundauswahl + Soft-Delete (geloest_von/at/grund)
- ki.py: health_summary() für KI-Gesundheitsbericht
- main.py: /favicon.ico Route
- requirements.txt: Pillow 11.2.1 + pillow-heif 0.22.0
This commit is contained in:
rene 2026-04-13 19:29:51 +02:00
parent 96e7a97b52
commit 6f48ec581d
8 changed files with 570 additions and 52 deletions

View file

@ -35,6 +35,10 @@ class PoisonCreate(BaseModel):
typ: str = "unbekannt"
class PoisonResolve(BaseModel):
grund: str = "beseitigt" # beseitigt | fehlerhaft | anderes
# ------------------------------------------------------------------
# GET /api/poison — aktive Meldungen im Umkreis (kein Login nötig)
# ------------------------------------------------------------------
@ -114,7 +118,11 @@ async def confirm_poison(poison_id: int, user=Depends(get_current_user)):
# Nur der Melder selbst oder ein Admin
# ------------------------------------------------------------------
@router.post("/{poison_id}/resolve")
async def resolve_poison(poison_id: int, user=Depends(get_current_user)):
async def resolve_poison(
poison_id: int,
data: PoisonResolve = PoisonResolve(),
user=Depends(get_current_user)
):
with db() as conn:
entry = conn.execute(
"SELECT * FROM poison WHERE id=?", (poison_id,)
@ -124,7 +132,16 @@ async def resolve_poison(poison_id: int, user=Depends(get_current_user)):
e = dict(entry)
if e["user_id"] != user["id"] and user.get("rolle") != "admin":
raise HTTPException(403, "Keine Berechtigung.")
conn.execute("UPDATE poison SET geloest=1 WHERE id=?", (poison_id,))
# Soft-Delete: Eintrag bleibt für spätere KI-Musteranalyse erhalten
conn.execute(
"""UPDATE poison
SET geloest=1,
geloest_von=?,
geloest_at=datetime('now'),
geloest_grund=?
WHERE id=?""",
(user["id"], data.grund, poison_id)
)
return {"ok": True}