Globinours/migrations/001_init.sql

174 lines
6 KiB
SQL

-- 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;