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:
parent
96e7a97b52
commit
6f48ec581d
8 changed files with 570 additions and 52 deletions
|
|
@ -88,6 +88,14 @@ def init_db():
|
|||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_diary_dog ON diary(dog_id, datum DESC);
|
||||
|
||||
-- TAGEBUCH ↔ HUNDE (n:m — ein Eintrag kann mehrere Hunde betreffen)
|
||||
CREATE TABLE IF NOT EXISTS diary_dogs (
|
||||
diary_id INTEGER NOT NULL REFERENCES diary(id) ON DELETE CASCADE,
|
||||
dog_id INTEGER NOT NULL REFERENCES dogs(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (diary_id, dog_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_diary_dogs_dog ON diary_dogs(dog_id);
|
||||
|
||||
-- GESUNDHEIT
|
||||
CREATE TABLE IF NOT EXISTS health (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
|
@ -186,6 +194,15 @@ def init_db():
|
|||
PRIMARY KEY (walk_id, user_id)
|
||||
);
|
||||
|
||||
-- GASSI-TREFFEN ↔ HUNDE (n:m — Teilnehmer kann mehrere Hunde mitbringen)
|
||||
CREATE TABLE IF NOT EXISTS walk_participant_dogs (
|
||||
walk_id INTEGER NOT NULL REFERENCES walks(id) ON DELETE CASCADE,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
dog_id INTEGER NOT NULL REFERENCES dogs(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (walk_id, user_id, dog_id)
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_wpd_dog ON walk_participant_dogs(dog_id);
|
||||
|
||||
-- FORUM
|
||||
CREATE TABLE IF NOT EXISTS forum_threads (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
|
@ -234,4 +251,48 @@ def init_db():
|
|||
|
||||
""")
|
||||
|
||||
# Migrations: neue Spalten zu bestehenden Tabellen hinzufügen (idempotent)
|
||||
_migrate(conn_factory=db)
|
||||
|
||||
logger.info("Datenbank initialisiert.")
|
||||
|
||||
|
||||
def _migrate(conn_factory):
|
||||
"""Fügt fehlende Spalten hinzu und führt Datenmigration durch (idempotent)."""
|
||||
migrations = [
|
||||
# Giftköder: Auflösungs-Details für spätere KI-Analyse
|
||||
("poison", "geloest_von", "INTEGER"),
|
||||
("poison", "geloest_at", "TEXT"),
|
||||
("poison", "geloest_grund", "TEXT"),
|
||||
# Gesundheit: erweiterte Felder je nach Eintragstyp
|
||||
("health", "charge_nr", "TEXT"),
|
||||
("health", "tierarzt_name", "TEXT"),
|
||||
("health", "kosten", "REAL"),
|
||||
("health", "diagnose", "TEXT"),
|
||||
("health", "dosierung", "TEXT"),
|
||||
("health", "haeufigkeit", "TEXT"),
|
||||
("health", "aktiv", "INTEGER NOT NULL DEFAULT 1"),
|
||||
("health", "bis_datum", "TEXT"),
|
||||
("health", "schweregrad", "TEXT"),
|
||||
("health", "reaktion", "TEXT"),
|
||||
("health", "datei_url", "TEXT"),
|
||||
("health", "datei_typ", "TEXT"),
|
||||
]
|
||||
with conn_factory() as conn:
|
||||
for table, column, col_type in migrations:
|
||||
existing = [
|
||||
row[1] for row in
|
||||
conn.execute(f"PRAGMA table_info({table})").fetchall()
|
||||
]
|
||||
if column not in existing:
|
||||
conn.execute(
|
||||
f"ALTER TABLE {table} ADD COLUMN {column} {col_type}"
|
||||
)
|
||||
logger.info(f"Migration: {table}.{column} hinzugefügt.")
|
||||
|
||||
# Datenmigration: diary_dogs für bestehende Einträge befüllen
|
||||
conn.execute("""
|
||||
INSERT OR IGNORE INTO diary_dogs (diary_id, dog_id)
|
||||
SELECT id, dog_id FROM diary
|
||||
""")
|
||||
logger.info("Migration: diary_dogs Backfill abgeschlossen.")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue