Feature: Vollständige Züchter-Rolle — Antrag, Würfe, Stammbaum, Genetik
Basis-Features (Schritte 1–11): - Züchter-Antrag mit Dokument-Upload, Admin-Prüfung, E-Mail-Benachrichtigungen - Öffentliches Züchter-Profil + Karten-Marker (lila, certificate-Icon) - Wurfverwaltung: Würfe, Welpen, Gewichtsverlauf, Foto-System - Wurfbörse (öffentlich) mit Filtersuche nach Rasse/Status - Läufigkeits-Tracker: Deckdatum + Wurftermin (+63 Tage, nur für Züchter) - Interessenten-Chat: Kontakt-Button in Wurfbörse und Züchter-Profil - Sidebar-Einträge: Zuchtkartei + Wurfverwaltung für Züchter/Admin Stammbaum & Genetik (Schritte 1–8): - Zuchtkartei: Hunde-Stammdaten mit Vater/Mutter-Verknüpfung - Stammbaum-Visualisierung: 4 Generationen, horizontales CSS-Grid - Gesundheitstests (HD, ED, OCD, Augen…) mit farbigen Ergebnis-Badges - Genetische Tests (MDR1, PRA, DM…): clear/carrier/affected - Titel & Auszeichnungen (CAC, CACIB, IPO…) - Probeverpaarung: IK-Berechnung nach Wright + Ampel-Bewertung - Teilen-Link für öffentliche Hunde-Profile - Kaufvertrag: druckbares HTML-Dokument pro Welpe Technisch: 4 neue Route-Dateien, 5 neue Page-Module, 11 neue DB-Tabellen, icons shield-check + certificate + tree-structure im Sprite — SW by-v465, APP_VER 444
This commit is contained in:
parent
58cb2b4ad3
commit
91340be5a3
24 changed files with 6660 additions and 27 deletions
|
|
@ -549,6 +549,8 @@ def _migrate(conn_factory):
|
|||
("notes", "location_name", "TEXT"),
|
||||
("notes", "parent_label", "TEXT"),
|
||||
("users", "notes_ki_enabled", "INTEGER NOT NULL DEFAULT 1"),
|
||||
# Züchter-Rolle
|
||||
("users", "breeder_status", "TEXT"),
|
||||
]
|
||||
with conn_factory() as conn:
|
||||
for table, column, col_type in migrations:
|
||||
|
|
@ -1223,3 +1225,178 @@ def _migrate(conn_factory):
|
|||
conn.execute("CREATE INDEX IF NOT EXISTS idx_diary_created ON diary(dog_id, created_at DESC)")
|
||||
conn.execute("CREATE INDEX IF NOT EXISTS idx_notes_created ON notes(user_id, created_at DESC)")
|
||||
logger.info("Migration: Performance-Indizes bereit.")
|
||||
|
||||
# Züchter-Tabellen
|
||||
conn.executescript("""
|
||||
CREATE TABLE IF NOT EXISTS breeder_profiles (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL UNIQUE REFERENCES users(id) ON DELETE CASCADE,
|
||||
zwingername TEXT NOT NULL,
|
||||
rasse_text TEXT NOT NULL,
|
||||
verein TEXT NOT NULL,
|
||||
vdh_mitglied INTEGER NOT NULL DEFAULT 0,
|
||||
stadt TEXT NOT NULL,
|
||||
website TEXT,
|
||||
beschreibung TEXT,
|
||||
location_lat REAL,
|
||||
location_lng REAL,
|
||||
verified_at TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS breeder_documents (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
dokument_typ TEXT NOT NULL,
|
||||
file_path TEXT NOT NULL,
|
||||
uploaded_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
""")
|
||||
logger.info("Migration: breeder_profiles + breeder_documents bereit.")
|
||||
|
||||
# Würfe + Welpen
|
||||
conn.executescript("""
|
||||
CREATE TABLE IF NOT EXISTS litters (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
breeder_id INTEGER NOT NULL REFERENCES breeder_profiles(id) ON DELETE CASCADE,
|
||||
vater_name TEXT,
|
||||
mutter_name TEXT,
|
||||
geburt_datum TEXT,
|
||||
erwartetes_datum TEXT,
|
||||
welpen_gesamt INTEGER,
|
||||
welpen_verfuegbar INTEGER,
|
||||
beschreibung TEXT,
|
||||
gesundheitstests TEXT,
|
||||
preis_spanne TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'geplant',
|
||||
sichtbar INTEGER NOT NULL DEFAULT 1,
|
||||
sichtbar_bis TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_litters_breeder ON litters(breeder_id, created_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_litters_status ON litters(status, sichtbar);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS puppies (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
wurf_id INTEGER NOT NULL REFERENCES litters(id) ON DELETE CASCADE,
|
||||
name TEXT,
|
||||
geschlecht TEXT,
|
||||
farbe TEXT,
|
||||
chip_nr TEXT,
|
||||
geburtsgewicht REAL,
|
||||
status TEXT NOT NULL DEFAULT 'verfuegbar',
|
||||
status_sichtbar INTEGER NOT NULL DEFAULT 1,
|
||||
notiz TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_puppies_wurf ON puppies(wurf_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS puppy_weights (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
welpe_id INTEGER NOT NULL REFERENCES puppies(id) ON DELETE CASCADE,
|
||||
gewicht_g REAL NOT NULL,
|
||||
gemessen_am TEXT NOT NULL
|
||||
);
|
||||
""")
|
||||
logger.info("Migration: litters + puppies + puppy_weights bereit.")
|
||||
|
||||
# Züchter-Fotos
|
||||
conn.executescript("""
|
||||
CREATE TABLE IF NOT EXISTS breeder_photos (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
breeder_id INTEGER NOT NULL REFERENCES breeder_profiles(id) ON DELETE CASCADE,
|
||||
entity_type TEXT NOT NULL,
|
||||
entity_id INTEGER NOT NULL,
|
||||
file_path TEXT NOT NULL,
|
||||
thumbnail_path TEXT,
|
||||
caption TEXT,
|
||||
is_primary INTEGER NOT NULL DEFAULT 0,
|
||||
visibility TEXT NOT NULL DEFAULT 'public',
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
uploaded_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_breeder_photos_entity
|
||||
ON breeder_photos(entity_type, entity_id);
|
||||
""")
|
||||
logger.info("Migration: breeder_photos bereit.")
|
||||
|
||||
# Züchter-Hunde-Stammdaten (Stammbaum, Gesundheit, Genetik, Titel)
|
||||
conn.executescript("""
|
||||
CREATE TABLE IF NOT EXISTS zucht_hunde (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
breeder_id INTEGER REFERENCES breeder_profiles(id) ON DELETE SET NULL,
|
||||
name TEXT NOT NULL,
|
||||
rufname TEXT,
|
||||
geschlecht TEXT,
|
||||
geburtsdatum TEXT,
|
||||
sterbedatum TEXT,
|
||||
chip_nr TEXT,
|
||||
taetowiernummer TEXT,
|
||||
zuchtbuchnummer TEXT,
|
||||
farbe TEXT,
|
||||
vater_id INTEGER REFERENCES zucht_hunde(id),
|
||||
mutter_id INTEGER REFERENCES zucht_hunde(id),
|
||||
zuechter_name TEXT,
|
||||
eigentuemer_name TEXT,
|
||||
is_public INTEGER NOT NULL DEFAULT 1,
|
||||
notiz TEXT,
|
||||
foto_url TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_zucht_hunde_breeder ON zucht_hunde(breeder_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_zucht_hunde_eltern ON zucht_hunde(vater_id, mutter_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS dog_health_tests (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
hund_id INTEGER NOT NULL REFERENCES zucht_hunde(id) ON DELETE CASCADE,
|
||||
test_typ TEXT NOT NULL,
|
||||
test_name TEXT,
|
||||
ergebnis TEXT NOT NULL,
|
||||
untersuch_am TEXT NOT NULL,
|
||||
gueltig_bis TEXT,
|
||||
untersucher TEXT,
|
||||
labor TEXT,
|
||||
zertifikat_nr TEXT,
|
||||
is_public INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_dog_health_tests_hund ON dog_health_tests(hund_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS dog_genetic_tests (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
hund_id INTEGER NOT NULL REFERENCES zucht_hunde(id) ON DELETE CASCADE,
|
||||
marker_name TEXT NOT NULL,
|
||||
marker_kategorie TEXT,
|
||||
genotyp TEXT,
|
||||
ergebnis_klasse TEXT,
|
||||
getestet_am TEXT NOT NULL,
|
||||
labor TEXT,
|
||||
zertifikat_nr TEXT,
|
||||
is_public INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_dog_genetic_tests_hund ON dog_genetic_tests(hund_id);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS dog_titles (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
hund_id INTEGER NOT NULL REFERENCES zucht_hunde(id) ON DELETE CASCADE,
|
||||
titel_typ TEXT NOT NULL,
|
||||
titel_name TEXT NOT NULL,
|
||||
verliehen_am TEXT NOT NULL,
|
||||
ort TEXT,
|
||||
richter TEXT,
|
||||
ausstellung TEXT,
|
||||
formwert TEXT,
|
||||
is_public INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_dog_titles_hund ON dog_titles(hund_id);
|
||||
""")
|
||||
logger.info("Migration: zucht_hunde + dog_health_tests + dog_genetic_tests + dog_titles bereit.")
|
||||
|
||||
# Läufigkeit: Deckdatum + Wurftermin
|
||||
existing_h = [row[1] for row in conn.execute("PRAGMA table_info(health)").fetchall()]
|
||||
for col, typedef in [("deckdatum", "TEXT"), ("wurftermin", "TEXT")]:
|
||||
if col not in existing_h:
|
||||
conn.execute(f"ALTER TABLE health ADD COLUMN {col} {typedef}")
|
||||
logger.info(f"Migration: health.{col} hinzugefügt.")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue