Feature: Sprint31 — 9 Features merged (Streak, Ausgaben, KI-Tierarzt, Rückrufe, Adoption, Vet+Befunde, Hundepass, Playdate, Rassenerkennung)
- Trainings-Streak: streak.py, DB training_streaks, Scheduler 19:00, Widget in welcome.js, Ping in uebungen.js
- Ausgaben-Tracker: expenses.py, expenses.js, DB expenses-Tabelle
- KI-Tierarztfragen: ki.py /tierarzt, health.js Button+Modal, DB ki_tierarzt_log
- Rückruf-Alarm: recalls.py, recalls.js, DB feed_recalls, Scheduler 08:00 RASFF
- Adoption: adoption.py, adoption.js, DB adoption_cache
- Tierarzt-Favorit + Befunde: tieraerzte.py /my-favorite+/favorite, health_docs.py, health.js, api.js, DB favorite_vets+health_documents
- Digitaler Hundepass: passport.py, dog-profile.js, main.py /pass/{token}, DB vaccinations+medications+dog_passport_meta+passport_shares, requirements.txt fpdf2
- Playdate-Matching: playdate.py, playdate.js, DB playdate_listings+playdate_requests
- Rassen-Erkennung: ki.py /rasse-erkennung (Claude Vision), dog-profile.js+wiki.js, CSS .rasse-result-card, DB ki_rasse_log
This commit is contained in:
parent
031c6028ac
commit
742ad189e8
26 changed files with 5734 additions and 27 deletions
|
|
@ -1657,3 +1657,203 @@ def _migrate(conn_factory):
|
|||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_hdm_wins_dog ON hund_des_monats_wins(dog_id);
|
||||
""")
|
||||
|
||||
# Trainings-Streak-Tabelle
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS training_streaks (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
dog_id INTEGER NOT NULL REFERENCES dogs(id) ON DELETE CASCADE,
|
||||
current_streak INTEGER NOT NULL DEFAULT 0,
|
||||
longest_streak INTEGER NOT NULL DEFAULT 0,
|
||||
last_training_date TEXT,
|
||||
UNIQUE(user_id, dog_id)
|
||||
)
|
||||
""")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_streaks_user ON training_streaks(user_id)")
|
||||
|
||||
# Ausgaben-Tracker
|
||||
conn.executescript("""
|
||||
CREATE TABLE IF NOT EXISTS expenses (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
dog_id INTEGER REFERENCES dogs(id) ON DELETE SET NULL,
|
||||
kategorie TEXT NOT NULL,
|
||||
betrag REAL NOT NULL,
|
||||
datum TEXT NOT NULL,
|
||||
notiz TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_expenses_user ON expenses(user_id, datum DESC);
|
||||
""")
|
||||
|
||||
# KI-Tierarztfragen Rate-Limit-Log
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS ki_tierarzt_log (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
dog_id INTEGER,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
""")
|
||||
|
||||
# KI Rassen-Erkennungs-Log (Rate-Limit: 10/Tag pro User)
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS ki_rasse_log (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
""")
|
||||
conn.execute("""
|
||||
CREATE INDEX IF NOT EXISTS idx_ki_rasse_log_user
|
||||
ON ki_rasse_log(user_id, created_at DESC)
|
||||
""")
|
||||
|
||||
# feed_recalls — Rückruf-Alarm für Tierfutter (RASFF)
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS feed_recalls (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
external_id TEXT NOT NULL UNIQUE,
|
||||
titel TEXT NOT NULL,
|
||||
produkt TEXT,
|
||||
gefahr TEXT,
|
||||
herkunft TEXT,
|
||||
datum TEXT NOT NULL,
|
||||
quelle TEXT NOT NULL DEFAULT 'rasff',
|
||||
url TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
""")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_recalls_datum ON feed_recalls(datum DESC)")
|
||||
|
||||
# Adoption-Cache
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS adoption_cache (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
external_id TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
rasse TEXT,
|
||||
alter_jahre REAL,
|
||||
geschlecht TEXT,
|
||||
foto_url TEXT,
|
||||
tierheim TEXT,
|
||||
tierheim_plz TEXT,
|
||||
tierheim_lat REAL,
|
||||
tierheim_lon REAL,
|
||||
adoptions_url TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
expires_at TEXT NOT NULL
|
||||
)
|
||||
""")
|
||||
|
||||
# ---- Favoriten-Tierarzt + Gesundheitsdokumente ----
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS favorite_vets (
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
vet_id INTEGER NOT NULL REFERENCES tieraerzte(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (user_id, vet_id)
|
||||
)
|
||||
""")
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS health_documents (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
dog_id INTEGER NOT NULL REFERENCES dogs(id) ON DELETE CASCADE,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
typ TEXT NOT NULL,
|
||||
titel TEXT NOT NULL,
|
||||
beschreibung TEXT,
|
||||
file_path TEXT NOT NULL,
|
||||
file_type TEXT NOT NULL,
|
||||
datum TEXT,
|
||||
vet_id INTEGER REFERENCES tieraerzte(id),
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
""")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_health_docs_dog ON health_documents(dog_id, created_at DESC)")
|
||||
|
||||
# Digitaler Hundepass — Impfungen, Medikamente, Metadaten, Share-Links
|
||||
try:
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS vaccinations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
dog_id INTEGER NOT NULL REFERENCES dogs(id) ON DELETE CASCADE,
|
||||
krankheit TEXT NOT NULL,
|
||||
datum TEXT NOT NULL,
|
||||
naechste TEXT,
|
||||
tierarzt TEXT,
|
||||
charge_nr TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
""")
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS medications (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
dog_id INTEGER NOT NULL REFERENCES dogs(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
dosierung TEXT,
|
||||
von TEXT,
|
||||
bis TEXT,
|
||||
notiz TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
""")
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS dog_passport_meta (
|
||||
dog_id INTEGER PRIMARY KEY REFERENCES dogs(id) ON DELETE CASCADE,
|
||||
blutgruppe TEXT,
|
||||
allergien TEXT,
|
||||
besonderheiten TEXT,
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
""")
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS passport_shares (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
dog_id INTEGER NOT NULL REFERENCES dogs(id) ON DELETE CASCADE,
|
||||
token TEXT NOT NULL UNIQUE,
|
||||
valid_until TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
)
|
||||
""")
|
||||
conn.execute("""
|
||||
CREATE INDEX IF NOT EXISTS idx_passport_shares_token ON passport_shares(token)
|
||||
""")
|
||||
logger.info("Migration: Hundepass-Tabellen bereit.")
|
||||
except Exception as e:
|
||||
logger.warning(f"Migration Hundepass: {e}")
|
||||
|
||||
# ---- Playdate ----
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS playdate_listings (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
dog_id INTEGER NOT NULL REFERENCES dogs(id) ON DELETE CASCADE,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
lat REAL NOT NULL,
|
||||
lon REAL NOT NULL,
|
||||
ort_name TEXT,
|
||||
radius_km INTEGER NOT NULL DEFAULT 10,
|
||||
beschreibung TEXT,
|
||||
aktiv INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
UNIQUE(dog_id)
|
||||
)
|
||||
""")
|
||||
conn.execute("""
|
||||
CREATE INDEX IF NOT EXISTS idx_playdate_listings_geo
|
||||
ON playdate_listings(lat, lon) WHERE aktiv=1
|
||||
""")
|
||||
conn.execute("""
|
||||
CREATE TABLE IF NOT EXISTS playdate_requests (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
from_dog_id INTEGER NOT NULL REFERENCES dogs(id) ON DELETE CASCADE,
|
||||
to_dog_id INTEGER NOT NULL REFERENCES dogs(id) ON DELETE CASCADE,
|
||||
from_user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
to_user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
nachricht TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
UNIQUE(from_dog_id, to_dog_id)
|
||||
)
|
||||
""")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue