-- 001_init.sql PRAGMA foreign_keys = ON; CREATE TABLE IF NOT EXISTS _migrations ( name TEXT PRIMARY KEY, applied_at TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'admin', created_at TEXT NOT NULL DEFAULT (datetime('now')) ); -- Référentiels CREATE TABLE IF NOT EXISTS ref_medications ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, -- ex: Doxybactin molecule TEXT, -- ex: doxycycline form TEXT, -- ex: cp / sirop / inj notes TEXT ); CREATE TABLE IF NOT EXISTS ref_vaccines ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL UNIQUE, -- ex: TCL / Rage notes TEXT ); CREATE TABLE IF NOT EXISTS animals ( id INTEGER PRIMARY KEY AUTOINCREMENT, internal_code TEXT NOT NULL UNIQUE, -- ex: 2026-001-CHOCOLAT name TEXT NOT NULL, species TEXT NOT NULL DEFAULT 'chat', sex TEXT CHECK (sex IN ('M','F','U')) NOT NULL DEFAULT 'U', birth_date TEXT, -- YYYY-MM-DD chip_id TEXT, -- puce status TEXT NOT NULL DEFAULT 'refuge', -- refuge / fa / reserve / adopte / fugue / decede fiv INTEGER NOT NULL DEFAULT 0, felv INTEGER NOT NULL DEFAULT 0, sterilized INTEGER NOT NULL DEFAULT 0, color TEXT, notes TEXT, current_address TEXT, current_lat REAL, current_lng REAL, rescue_address TEXT, rescue_lat REAL, rescue_lng REAL, rescue_location_name TEXT, created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')) ); CREATE INDEX IF NOT EXISTS idx_animals_status ON animals(status); CREATE INDEX IF NOT EXISTS idx_animals_name ON animals(name); CREATE INDEX IF NOT EXISTS idx_animals_code ON animals(internal_code); CREATE TABLE IF NOT EXISTS adoptions ( id INTEGER PRIMARY KEY AUTOINCREMENT, animal_id INTEGER NOT NULL, adopter_name TEXT NOT NULL, adopter_phone TEXT, adopter_email TEXT, adoption_date DATE NOT NULL, notes TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, adopter_address TEXT, adopter_postal_code TEXT, adopter_city TEXT, adopter_country TEXT DEFAULT 'France', FOREIGN KEY(animal_id) REFERENCES animals(id) ); CREATE TABLE IF NOT EXISTS animal_movements ( id INTEGER PRIMARY KEY AUTOINCREMENT, animal_id INTEGER NOT NULL, kind TEXT NOT NULL CHECK(kind IN ('entry','exit')), place TEXT, lieu TEXT, contact_name TEXT, contact_phone TEXT, contact_email TEXT, note TEXT, created_at TEXT NOT NULL DEFAULT(datetime('now')), FOREIGN KEY(animal_id) REFERENCES animals(id) ); -- Mesures (poids/temp/etc.) CREATE TABLE IF NOT EXISTS measurements ( id INTEGER PRIMARY KEY AUTOINCREMENT, animal_id INTEGER NOT NULL, measured_at TEXT NOT NULL DEFAULT (datetime('now')), type TEXT NOT NULL, -- weight / temp / rr / hr ... value REAL NOT NULL, unit TEXT NOT NULL, notes TEXT, created_by INTEGER, FOREIGN KEY(animal_id) REFERENCES animals(id) ON DELETE CASCADE, FOREIGN KEY(created_by) REFERENCES users(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS idx_measurements_animal_date ON measurements(animal_id, measured_at); -- Notes médicales “style dossier patient” CREATE TABLE IF NOT EXISTS medical_notes ( id INTEGER PRIMARY KEY AUTOINCREMENT, animal_id INTEGER NOT NULL, noted_at TEXT NOT NULL DEFAULT (datetime('now')), kind TEXT NOT NULL, -- consult / controle / symptome / diagnostic / acte / hosp / autre reason TEXT, -- motif symptoms TEXT, -- symptômes exam TEXT, -- examen clinique diagnosis TEXT, -- diagnostic / hypothèses plan TEXT, -- plan / conduite à tenir temperature_c REAL, -- optionnel weight_kg REAL, -- optionnel created_by INTEGER, FOREIGN KEY(animal_id) REFERENCES animals(id) ON DELETE CASCADE, FOREIGN KEY(created_by) REFERENCES users(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS idx_mednotes_animal_date ON medical_notes(animal_id, noted_at); -- Traitements (référentiel médocs) CREATE TABLE IF NOT EXISTS treatments ( id INTEGER PRIMARY KEY AUTOINCREMENT, animal_id INTEGER NOT NULL, medication_id INTEGER NOT NULL, route TEXT, -- PO/SC/IM/Topique... dose_text TEXT NOT NULL, -- "1/2 cp matin/soir" start_date TEXT NOT NULL, -- YYYY-MM-DD end_date TEXT, -- YYYY-MM-DD ongoing INTEGER NOT NULL DEFAULT 1, notes TEXT, created_by INTEGER, FOREIGN KEY(animal_id) REFERENCES animals(id) ON DELETE CASCADE, FOREIGN KEY(medication_id) REFERENCES ref_medications(id) ON DELETE RESTRICT, FOREIGN KEY(created_by) REFERENCES users(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS idx_treatments_animal_ongoing ON treatments(animal_id, ongoing); -- Vaccins CREATE TABLE IF NOT EXISTS vaccinations ( id INTEGER PRIMARY KEY AUTOINCREMENT, animal_id INTEGER NOT NULL, vaccine_id INTEGER NOT NULL, done_date TEXT NOT NULL, -- YYYY-MM-DD due_date TEXT, -- rappel lot TEXT, notes TEXT, created_by INTEGER, FOREIGN KEY(animal_id) REFERENCES animals(id) ON DELETE CASCADE, FOREIGN KEY(vaccine_id) REFERENCES ref_vaccines(id) ON DELETE RESTRICT, FOREIGN KEY(created_by) REFERENCES users(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS idx_vaccinations_due ON vaccinations(due_date); -- Vue résumé médical (liste animaux) CREATE VIEW IF NOT EXISTS v_animals_med_summary AS SELECT a.id AS animal_id, (SELECT mn.noted_at FROM medical_notes mn WHERE mn.animal_id = a.id ORDER BY mn.noted_at DESC LIMIT 1) AS last_med_at, (SELECT COUNT(*) FROM treatments t WHERE t.animal_id = a.id AND t.ongoing = 1) AS ongoing_treatments, (SELECT MIN(v.due_date) FROM vaccinations v WHERE v.animal_id = a.id AND v.due_date IS NOT NULL AND date(v.due_date) >= date('now')) AS next_vaccine_due FROM animals a;