Merge pull request '[BDD] Conformité CDC v1.3 - Schéma unifié' (#64) from feature/3-ajout-champs-bdd into master
Merge pull request #64: [BDD] Conformité CDC v1.3 - Schéma unifié Modifications du schéma BDD.sql pour conformité CDC v1.3. Closes #3
This commit is contained in:
commit
fd4f5e6b12
@ -46,19 +46,20 @@ CREATE TABLE utilisateurs (
|
|||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||||
email VARCHAR(255) NOT NULL UNIQUE,
|
email VARCHAR(255) NOT NULL UNIQUE,
|
||||||
CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'),
|
CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'),
|
||||||
password TEXT NOT NULL,
|
password TEXT, -- NULL avant création via token
|
||||||
prenom VARCHAR(100),
|
prenom VARCHAR(100),
|
||||||
nom VARCHAR(100),
|
nom VARCHAR(100),
|
||||||
genre genre_type,
|
genre genre_type,
|
||||||
role role_type NOT NULL,
|
role role_type NOT NULL,
|
||||||
statut statut_utilisateur_type DEFAULT 'en_attente',
|
statut statut_utilisateur_type DEFAULT 'en_attente',
|
||||||
mobile VARCHAR(20),
|
telephone VARCHAR(20), -- Unifié (mobile privilégié)
|
||||||
telephone_fixe VARCHAR(20),
|
|
||||||
adresse TEXT,
|
adresse TEXT,
|
||||||
date_naissance DATE,
|
date_naissance DATE,
|
||||||
photo_url TEXT,
|
photo_url TEXT, -- Obligatoire pour AM, non utilisé pour parents
|
||||||
consentement_photo BOOLEAN DEFAULT false,
|
consentement_photo BOOLEAN DEFAULT false,
|
||||||
date_consentement_photo TIMESTAMPTZ,
|
date_consentement_photo TIMESTAMPTZ,
|
||||||
|
token_creation_mdp VARCHAR(255), -- Token pour créer MDP après validation
|
||||||
|
token_creation_mdp_expire_le TIMESTAMPTZ, -- Expiration 7 jours
|
||||||
changement_mdp_obligatoire BOOLEAN DEFAULT false,
|
changement_mdp_obligatoire BOOLEAN DEFAULT false,
|
||||||
cree_le TIMESTAMPTZ DEFAULT now(),
|
cree_le TIMESTAMPTZ DEFAULT now(),
|
||||||
modifie_le TIMESTAMPTZ DEFAULT now(),
|
modifie_le TIMESTAMPTZ DEFAULT now(),
|
||||||
@ -68,16 +69,19 @@ CREATE TABLE utilisateurs (
|
|||||||
situation_familiale situation_familiale_type
|
situation_familiale situation_familiale_type
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- Index pour recherche par token
|
||||||
|
CREATE INDEX idx_utilisateurs_token_creation_mdp
|
||||||
|
ON utilisateurs(token_creation_mdp)
|
||||||
|
WHERE token_creation_mdp IS NOT NULL;
|
||||||
|
|
||||||
-- ==========================================================
|
-- ==========================================================
|
||||||
-- Table : assistantes_maternelles
|
-- Table : assistantes_maternelles
|
||||||
-- ==========================================================
|
-- ==========================================================
|
||||||
CREATE TABLE assistantes_maternelles (
|
CREATE TABLE assistantes_maternelles (
|
||||||
id_utilisateur UUID PRIMARY KEY REFERENCES utilisateurs(id) ON DELETE CASCADE,
|
id_utilisateur UUID PRIMARY KEY REFERENCES utilisateurs(id) ON DELETE CASCADE,
|
||||||
numero_agrement VARCHAR(50),
|
numero_agrement VARCHAR(50),
|
||||||
date_agrement DATE,
|
date_agrement DATE NOT NULL, -- Obligatoire selon CDC v1.3
|
||||||
nir_chiffre CHAR(15),
|
nir_chiffre CHAR(15),
|
||||||
annee_experience SMALLINT,
|
|
||||||
specialite VARCHAR (100),
|
|
||||||
nb_max_enfants INT,
|
nb_max_enfants INT,
|
||||||
place_disponible INT,
|
place_disponible INT,
|
||||||
biographie TEXT,
|
biographie TEXT,
|
||||||
@ -100,7 +104,7 @@ CREATE TABLE enfants (
|
|||||||
statut statut_enfant_type,
|
statut statut_enfant_type,
|
||||||
prenom VARCHAR(100),
|
prenom VARCHAR(100),
|
||||||
nom VARCHAR(100),
|
nom VARCHAR(100),
|
||||||
genre genre_type,
|
genre genre_type NOT NULL, -- Obligatoire selon CDC
|
||||||
date_naissance DATE,
|
date_naissance DATE,
|
||||||
date_prevue_naissance DATE,
|
date_prevue_naissance DATE,
|
||||||
photo_url TEXT,
|
photo_url TEXT,
|
||||||
|
|||||||
@ -1,277 +0,0 @@
|
|||||||
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- ENUMS
|
|
||||||
-- ==========================================================
|
|
||||||
DO $$ BEGIN
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'role_type') THEN
|
|
||||||
CREATE TYPE role_type AS ENUM ('parent', 'gestionnaire', 'super_admin', 'assistante_maternelle','administrateur');
|
|
||||||
END IF;
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'genre_type') THEN
|
|
||||||
CREATE TYPE genre_type AS ENUM ('H', 'F', 'Autre');
|
|
||||||
END IF;
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'statut_utilisateur_type') THEN
|
|
||||||
CREATE TYPE statut_utilisateur_type AS ENUM ('en_attente','actif','suspendu');
|
|
||||||
END IF;
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'statut_enfant_type') THEN
|
|
||||||
CREATE TYPE statut_enfant_type AS ENUM ('a_naitre','actif','scolarise');
|
|
||||||
END IF;
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'statut_dossier_type') THEN
|
|
||||||
CREATE TYPE statut_dossier_type AS ENUM ('envoye','accepte','refuse');
|
|
||||||
END IF;
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'statut_contrat_type') THEN
|
|
||||||
CREATE TYPE statut_contrat_type AS ENUM ('brouillon','en_attente_signature','valide','resilie');
|
|
||||||
END IF;
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'statut_avenant_type') THEN
|
|
||||||
CREATE TYPE statut_avenant_type AS ENUM ('propose','accepte','refuse');
|
|
||||||
END IF;
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'type_evenement_type') THEN
|
|
||||||
CREATE TYPE type_evenement_type AS ENUM ('absence_enfant','conge_am','conge_parent','arret_maladie_am','evenement_rpe');
|
|
||||||
END IF;
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'statut_evenement_type') THEN
|
|
||||||
CREATE TYPE statut_evenement_type AS ENUM ('propose','valide','refuse');
|
|
||||||
END IF;
|
|
||||||
IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'statut_validation_type') THEN
|
|
||||||
CREATE TYPE statut_validation_type AS ENUM ('en_attente','valide','refuse');
|
|
||||||
END IF;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : utilisateurs
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE utilisateurs (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
email VARCHAR(255) NOT NULL UNIQUE,
|
|
||||||
CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'),
|
|
||||||
password TEXT NOT NULL,
|
|
||||||
prenom VARCHAR(100),
|
|
||||||
nom VARCHAR(100),
|
|
||||||
genre genre_type,
|
|
||||||
role role_type NOT NULL,
|
|
||||||
statut statut_utilisateur_type DEFAULT 'en_attente',
|
|
||||||
telephone VARCHAR(20),
|
|
||||||
adresse TEXT,
|
|
||||||
photo_url TEXT,
|
|
||||||
consentement_photo BOOLEAN DEFAULT false,
|
|
||||||
date_consentement_photo TIMESTAMPTZ,
|
|
||||||
changement_mdp_obligatoire BOOLEAN DEFAULT false,
|
|
||||||
cree_le TIMESTAMPTZ DEFAULT now(),
|
|
||||||
modifie_le TIMESTAMPTZ DEFAULT now(),
|
|
||||||
ville VARCHAR(150),
|
|
||||||
code_postal VARCHAR(10),
|
|
||||||
mobile VARCHAR(20),
|
|
||||||
telephone_fixe VARCHAR(20),
|
|
||||||
profession VARCHAR(150),
|
|
||||||
situation_familiale VARCHAR(50),
|
|
||||||
date_naissance DATE
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : assistantes_maternelles
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE assistantes_maternelles (
|
|
||||||
id_utilisateur UUID PRIMARY KEY REFERENCES utilisateurs(id) ON DELETE CASCADE,
|
|
||||||
numero_agrement VARCHAR(50),
|
|
||||||
nir_chiffre CHAR(15),
|
|
||||||
nb_max_enfants INT,
|
|
||||||
biographie TEXT,
|
|
||||||
disponible BOOLEAN DEFAULT true,
|
|
||||||
ville_residence VARCHAR(100),
|
|
||||||
date_agrement DATE,
|
|
||||||
annee_experience SMALLINT,
|
|
||||||
specialite VARCHAR(100),
|
|
||||||
place_disponible INT
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : parentschange les donnée de init
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE parents (
|
|
||||||
id_utilisateur UUID PRIMARY KEY REFERENCES utilisateurs(id) ON DELETE CASCADE,
|
|
||||||
id_co_parent UUID REFERENCES utilisateurs(id)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : enfants
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE enfants (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
statut statut_enfant_type,
|
|
||||||
prenom VARCHAR(100),
|
|
||||||
nom VARCHAR(100),
|
|
||||||
genre genre_type,
|
|
||||||
date_naissance DATE,
|
|
||||||
date_prevue_naissance DATE,
|
|
||||||
photo_url TEXT,
|
|
||||||
consentement_photo BOOLEAN DEFAULT false,
|
|
||||||
date_consentement_photo TIMESTAMPTZ,
|
|
||||||
est_multiple BOOLEAN DEFAULT false
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : enfants_parents
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE enfants_parents (
|
|
||||||
id_parent UUID REFERENCES parents(id_utilisateur) ON DELETE CASCADE,
|
|
||||||
id_enfant UUID REFERENCES enfants(id) ON DELETE CASCADE,
|
|
||||||
PRIMARY KEY (id_parent, id_enfant)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : dossiers
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE dossiers (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
id_parent UUID REFERENCES parents(id_utilisateur) ON DELETE CASCADE,
|
|
||||||
id_enfant UUID REFERENCES enfants(id) ON DELETE CASCADE,
|
|
||||||
presentation TEXT,
|
|
||||||
type_contrat VARCHAR(50),
|
|
||||||
repas BOOLEAN DEFAULT false,
|
|
||||||
budget NUMERIC(10,2),
|
|
||||||
planning_souhaite JSONB,
|
|
||||||
statut statut_dossier_type DEFAULT 'envoye',
|
|
||||||
cree_le TIMESTAMPTZ DEFAULT now(),
|
|
||||||
modifie_le TIMESTAMPTZ DEFAULT now()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : messages
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE messages (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
id_dossier UUID REFERENCES dossiers(id) ON DELETE CASCADE,
|
|
||||||
id_expediteur UUID REFERENCES utilisateurs(id) ON DELETE CASCADE,
|
|
||||||
contenu TEXT,
|
|
||||||
re_redige_par_ia BOOLEAN DEFAULT false,
|
|
||||||
cree_le TIMESTAMPTZ DEFAULT now()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : contrats
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE contrats (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
id_dossier UUID UNIQUE REFERENCES dossiers(id) ON DELETE CASCADE,
|
|
||||||
planning JSONB,
|
|
||||||
tarif_horaire NUMERIC(6,2),
|
|
||||||
indemnites_repas NUMERIC(6,2),
|
|
||||||
date_debut DATE,
|
|
||||||
statut statut_contrat_type DEFAULT 'brouillon',
|
|
||||||
signe_parent BOOLEAN DEFAULT false,
|
|
||||||
signe_am BOOLEAN DEFAULT false,
|
|
||||||
finalise_le TIMESTAMPTZ,
|
|
||||||
cree_le TIMESTAMPTZ DEFAULT now(),
|
|
||||||
modifie_le TIMESTAMPTZ DEFAULT now()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : avenants_contrats
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE avenants_contrats (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
id_contrat UUID REFERENCES contrats(id) ON DELETE CASCADE,
|
|
||||||
modifications JSONB,
|
|
||||||
initie_par UUID REFERENCES utilisateurs(id),
|
|
||||||
statut statut_avenant_type DEFAULT 'propose',
|
|
||||||
cree_le TIMESTAMPTZ DEFAULT now(),
|
|
||||||
modifie_le TIMESTAMPTZ DEFAULT now()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : evenements
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE evenements (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
type type_evenement_type,
|
|
||||||
id_enfant UUID REFERENCES enfants(id) ON DELETE CASCADE,
|
|
||||||
id_am UUID REFERENCES utilisateurs(id),
|
|
||||||
id_parent UUID REFERENCES parents(id_utilisateur),
|
|
||||||
cree_par UUID REFERENCES utilisateurs(id),
|
|
||||||
date_debut TIMESTAMPTZ,
|
|
||||||
date_fin TIMESTAMPTZ,
|
|
||||||
commentaires TEXT,
|
|
||||||
statut statut_evenement_type DEFAULT 'propose',
|
|
||||||
delai_grace TIMESTAMPTZ,
|
|
||||||
urgent BOOLEAN DEFAULT false,
|
|
||||||
cree_le TIMESTAMPTZ DEFAULT now(),
|
|
||||||
modifie_le TIMESTAMPTZ DEFAULT now()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : signalements_bugs
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE signalements_bugs (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
id_utilisateur UUID REFERENCES utilisateurs(id),
|
|
||||||
description TEXT,
|
|
||||||
cree_le TIMESTAMPTZ DEFAULT now()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : uploads
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE uploads (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
id_utilisateur UUID REFERENCES utilisateurs(id) ON DELETE SET NULL,
|
|
||||||
fichier_url TEXT NOT NULL,
|
|
||||||
type VARCHAR(50),
|
|
||||||
cree_le TIMESTAMPTZ DEFAULT now()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : notifications
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE notifications (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
id_utilisateur UUID REFERENCES utilisateurs(id) ON DELETE CASCADE,
|
|
||||||
contenu TEXT,
|
|
||||||
lu BOOLEAN DEFAULT false,
|
|
||||||
cree_le TIMESTAMPTZ DEFAULT now()
|
|
||||||
);
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Table : validations
|
|
||||||
-- ==========================================================
|
|
||||||
CREATE TABLE validations (
|
|
||||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
||||||
id_utilisateur UUID REFERENCES utilisateurs(id),
|
|
||||||
type VARCHAR(50),
|
|
||||||
statut statut_validation_type DEFAULT 'en_attente',
|
|
||||||
cree_le TIMESTAMPTZ DEFAULT now(),
|
|
||||||
modifie_le TIMESTAMPTZ DEFAULT now(),
|
|
||||||
valide_par UUID REFERENCES utilisateurs(id),
|
|
||||||
commentaire TEXT
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- Initialisation d'un administrateur par défaut
|
|
||||||
-- ==========================================================
|
|
||||||
|
|
||||||
-- ==========================================================
|
|
||||||
-- SEED: Super Administrateur par défaut
|
|
||||||
-- ==========================================================
|
|
||||||
-- Mot de passe: 4dm1n1strateur
|
|
||||||
INSERT INTO utilisateurs (
|
|
||||||
id,
|
|
||||||
email,
|
|
||||||
password,
|
|
||||||
prenom,
|
|
||||||
nom,
|
|
||||||
role,
|
|
||||||
statut,
|
|
||||||
cree_le,
|
|
||||||
modifie_le
|
|
||||||
)
|
|
||||||
VALUES (
|
|
||||||
gen_random_uuid(),
|
|
||||||
'admin@ptits-pas.fr',
|
|
||||||
'$2b$12$Fo5ly1YlTj3O6lXf.IUgoeUqEebBGpmoM5zLbzZx.CueorSE7z2E2',
|
|
||||||
'Admin',
|
|
||||||
'Système',
|
|
||||||
'super_admin',
|
|
||||||
'actif',
|
|
||||||
now(),
|
|
||||||
now()
|
|
||||||
)
|
|
||||||
ON CONFLICT (email) DO NOTHING;
|
|
||||||
@ -1,157 +0,0 @@
|
|||||||
-- =============================================
|
|
||||||
-- 02_indexes.sql : Index FK + colonnes critiques
|
|
||||||
-- =============================================
|
|
||||||
|
|
||||||
-- Recommandation : exécuter après 01_init.sql
|
|
||||||
|
|
||||||
-- ===========
|
|
||||||
-- UTILISATEURS
|
|
||||||
-- ===========
|
|
||||||
-- Recherche par email (insensibilité à la casse pour lookup)
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_utilisateurs_lower_courriel
|
|
||||||
ON utilisateurs (LOWER(courriel));
|
|
||||||
|
|
||||||
-- ===========
|
|
||||||
-- ASSISTANTES_MATERNELLES
|
|
||||||
-- ===========
|
|
||||||
-- FK -> utilisateurs(id)
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_am_id_utilisateur
|
|
||||||
ON assistantes_maternelles (id_utilisateur);
|
|
||||||
|
|
||||||
-- =======
|
|
||||||
-- PARENTS
|
|
||||||
-- =======
|
|
||||||
-- FK -> utilisateurs(id)
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_parents_id_utilisateur
|
|
||||||
ON parents (id_utilisateur);
|
|
||||||
|
|
||||||
-- Co-parent (nullable)
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_parents_id_co_parent
|
|
||||||
ON parents (id_co_parent);
|
|
||||||
|
|
||||||
-- =======
|
|
||||||
-- ENFANTS
|
|
||||||
-- =======
|
|
||||||
-- (souvent filtrés par statut / date_naissance ? à activer si besoin)
|
|
||||||
-- CREATE INDEX IF NOT EXISTS idx_enfants_statut ON enfants (statut);
|
|
||||||
-- CREATE INDEX IF NOT EXISTS idx_enfants_date_naissance ON enfants (date_naissance);
|
|
||||||
|
|
||||||
-- ================
|
|
||||||
-- ENFANTS_PARENTS (N:N)
|
|
||||||
-- ================
|
|
||||||
-- PK composite déjà en place (id_parent, id_enfant), ajouter index individuels si jointures unilatérales fréquentes
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_enfants_parents_id_parent
|
|
||||||
ON enfants_parents (id_parent);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_enfants_parents_id_enfant
|
|
||||||
ON enfants_parents (id_enfant);
|
|
||||||
|
|
||||||
-- ========
|
|
||||||
-- DOSSIERS
|
|
||||||
-- ========
|
|
||||||
-- FK -> parent / enfant
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_dossiers_id_parent
|
|
||||||
ON dossiers (id_parent);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_dossiers_id_enfant
|
|
||||||
ON dossiers (id_enfant);
|
|
||||||
|
|
||||||
-- Statut (filtrages "à traiter", "envoyé", etc.)
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_dossiers_statut
|
|
||||||
ON dossiers (statut);
|
|
||||||
|
|
||||||
-- JSONB : si on fait des requêtes @> sur le planning souhaité
|
|
||||||
-- CREATE INDEX IF NOT EXISTS idx_dossiers_planning_souhaite_gin
|
|
||||||
-- ON dossiers USING GIN (planning_souhaite);
|
|
||||||
|
|
||||||
-- ========
|
|
||||||
-- MESSAGES
|
|
||||||
-- ========
|
|
||||||
-- Filtrage par dossier + tri chronologique
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_messages_id_dossier_cree_le
|
|
||||||
ON messages (id_dossier, cree_le);
|
|
||||||
|
|
||||||
-- Recherche par expéditeur
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_messages_id_expediteur_cree_le
|
|
||||||
ON messages (id_expediteur, cree_le);
|
|
||||||
|
|
||||||
-- =========
|
|
||||||
-- CONTRATS
|
|
||||||
-- =========
|
|
||||||
-- UNIQUE(id_dossier) existe déjà -> index implicite
|
|
||||||
-- Tri / filtres fréquents
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_contrats_statut
|
|
||||||
ON contrats (statut);
|
|
||||||
|
|
||||||
-- JSONB planning : activer si on requête par clé
|
|
||||||
-- CREATE INDEX IF NOT EXISTS idx_contrats_planning_gin
|
|
||||||
-- ON contrats USING GIN (planning);
|
|
||||||
|
|
||||||
-- ==================
|
|
||||||
-- AVENANTS_CONTRATS
|
|
||||||
-- ==================
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_avenants_contrats_id_contrat_cree_le
|
|
||||||
ON avenants_contrats (id_contrat, cree_le);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_avenants_contrats_initie_par
|
|
||||||
ON avenants_contrats (initie_par);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_avenants_contrats_statut
|
|
||||||
ON avenants_contrats (statut);
|
|
||||||
|
|
||||||
-- =========
|
|
||||||
-- EVENEMENTS
|
|
||||||
-- =========
|
|
||||||
-- Accès par enfant + période
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_evenements_id_enfant_date_debut
|
|
||||||
ON evenements (id_enfant, date_debut);
|
|
||||||
|
|
||||||
-- Filtrage par auteur / AM / parent
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_evenements_cree_par
|
|
||||||
ON evenements (cree_par);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_evenements_id_am
|
|
||||||
ON evenements (id_am);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_evenements_id_parent
|
|
||||||
ON evenements (id_parent);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_evenements_type
|
|
||||||
ON evenements (type);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_evenements_statut
|
|
||||||
ON evenements (statut);
|
|
||||||
|
|
||||||
-- =================
|
|
||||||
-- SIGNALEMENTS_BUGS
|
|
||||||
-- =================
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_signalements_bugs_id_utilisateur_cree_le
|
|
||||||
ON signalements_bugs (id_utilisateur, cree_le);
|
|
||||||
|
|
||||||
-- =======
|
|
||||||
-- UPLOADS
|
|
||||||
-- =======
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_uploads_id_utilisateur_cree_le
|
|
||||||
ON uploads (id_utilisateur, cree_le);
|
|
||||||
|
|
||||||
-- =============
|
|
||||||
-- NOTIFICATIONS
|
|
||||||
-- =============
|
|
||||||
-- Requêtes fréquentes : non lues + ordre chrono
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_notifications_user_lu_cree_le
|
|
||||||
ON notifications (id_utilisateur, lu, cree_le);
|
|
||||||
|
|
||||||
-- Option : index partiel pour "non lues"
|
|
||||||
-- CREATE INDEX IF NOT EXISTS idx_notifications_non_lues
|
|
||||||
-- ON notifications (id_utilisateur, cree_le)
|
|
||||||
-- WHERE lu = false;
|
|
||||||
|
|
||||||
-- ===========
|
|
||||||
-- VALIDATIONS
|
|
||||||
-- ===========
|
|
||||||
-- Requêtes par utilisateur validé, par statut et par date
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_validations_id_utilisateur_cree_le
|
|
||||||
ON validations (id_utilisateur, cree_le);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_validations_statut
|
|
||||||
ON validations (statut);
|
|
||||||
@ -1,140 +0,0 @@
|
|||||||
-- =============================================
|
|
||||||
-- 03_checks.sql : Contraintes CHECK & NOT NULL
|
|
||||||
-- A exécuter après 01_init.sql (et 02_indexes.sql)
|
|
||||||
-- =============================================
|
|
||||||
|
|
||||||
-- ==============
|
|
||||||
-- UTILISATEURS
|
|
||||||
-- ==============
|
|
||||||
-- (Regex email déjà présente dans 01_init.sql)
|
|
||||||
-- Optionnel : forcer prenom/nom non vides si fournis
|
|
||||||
ALTER TABLE utilisateurs
|
|
||||||
ADD CONSTRAINT chk_utilisateurs_prenom_non_vide
|
|
||||||
CHECK (prenom IS NULL OR btrim(prenom) <> ''),
|
|
||||||
ADD CONSTRAINT chk_utilisateurs_nom_non_vide
|
|
||||||
CHECK (nom IS NULL OR btrim(nom) <> '');
|
|
||||||
|
|
||||||
-- =========================
|
|
||||||
-- ASSISTANTES_MATERNELLES
|
|
||||||
-- =========================
|
|
||||||
-- NIR : aujourd’hui en 15 chiffres (Sprint 2 : chiffrement)
|
|
||||||
ALTER TABLE assistantes_maternelles
|
|
||||||
ADD CONSTRAINT chk_am_nir_format
|
|
||||||
CHECK (nir_chiffre IS NULL OR nir_chiffre ~ '^[0-9]{15}$'),
|
|
||||||
ADD CONSTRAINT chk_am_nb_max_enfants
|
|
||||||
CHECK (nb_max_enfants IS NULL OR nb_max_enfants BETWEEN 0 AND 10),
|
|
||||||
ADD CONSTRAINT chk_am_ville_non_vide
|
|
||||||
CHECK (ville_residence IS NULL OR btrim(ville_residence) <> '');
|
|
||||||
|
|
||||||
-- =========
|
|
||||||
-- PARENTS
|
|
||||||
-- =========
|
|
||||||
-- Interdiction d’être co-parent de soi-même
|
|
||||||
ALTER TABLE parents
|
|
||||||
ADD CONSTRAINT chk_parents_co_parent_diff
|
|
||||||
CHECK (id_co_parent IS NULL OR id_co_parent <> id_utilisateur);
|
|
||||||
|
|
||||||
-- =========
|
|
||||||
-- ENFANTS
|
|
||||||
-- =========
|
|
||||||
-- Cohérence statut / dates de naissance
|
|
||||||
ALTER TABLE enfants
|
|
||||||
ADD CONSTRAINT chk_enfants_dates_exclusives
|
|
||||||
CHECK (NOT (date_naissance IS NOT NULL AND date_prevue_naissance IS NOT NULL)),
|
|
||||||
ADD CONSTRAINT chk_enfants_statut_dates
|
|
||||||
CHECK (
|
|
||||||
-- a_naitre => date_prevue_naissance requise
|
|
||||||
(statut = 'a_naitre' AND date_prevue_naissance IS NOT NULL)
|
|
||||||
OR
|
|
||||||
-- actif/scolarise => date_naissance requise
|
|
||||||
(statut IN ('actif','scolarise') AND date_naissance IS NOT NULL)
|
|
||||||
OR statut IS NULL -- si statut non encore fixé
|
|
||||||
),
|
|
||||||
ADD CONSTRAINT chk_enfants_consentement_coherent
|
|
||||||
CHECK (
|
|
||||||
(consentement_photo = true AND date_consentement_photo IS NOT NULL)
|
|
||||||
OR
|
|
||||||
(consentement_photo = false AND date_consentement_photo IS NULL)
|
|
||||||
);
|
|
||||||
|
|
||||||
-- =================
|
|
||||||
-- ENFANTS_PARENTS
|
|
||||||
-- =================
|
|
||||||
-- (PK composite déjà en place, rien à ajouter ici)
|
|
||||||
|
|
||||||
-- ========
|
|
||||||
-- DOSSIERS
|
|
||||||
-- ========
|
|
||||||
ALTER TABLE dossiers
|
|
||||||
ADD CONSTRAINT chk_dossiers_budget_nonneg
|
|
||||||
CHECK (budget IS NULL OR budget >= 0),
|
|
||||||
ADD CONSTRAINT chk_dossiers_type_contrat_non_vide
|
|
||||||
CHECK (type_contrat IS NULL OR btrim(type_contrat) <> ''),
|
|
||||||
ADD CONSTRAINT chk_dossiers_planning_json
|
|
||||||
CHECK (planning_souhaite IS NULL OR jsonb_typeof(planning_souhaite) = 'object');
|
|
||||||
|
|
||||||
-- ========
|
|
||||||
-- MESSAGES
|
|
||||||
-- ========
|
|
||||||
-- Contenu obligatoire, non vide
|
|
||||||
ALTER TABLE messages
|
|
||||||
ALTER COLUMN contenu SET NOT NULL;
|
|
||||||
ALTER TABLE messages
|
|
||||||
ADD CONSTRAINT chk_messages_contenu_non_vide
|
|
||||||
CHECK (btrim(contenu) <> '');
|
|
||||||
|
|
||||||
-- =========
|
|
||||||
-- CONTRATS
|
|
||||||
-- =========
|
|
||||||
ALTER TABLE contrats
|
|
||||||
ADD CONSTRAINT chk_contrats_tarif_nonneg
|
|
||||||
CHECK (tarif_horaire IS NULL OR tarif_horaire >= 0),
|
|
||||||
ADD CONSTRAINT chk_contrats_indemnites_nonneg
|
|
||||||
CHECK (indemnites_repas IS NULL OR indemnites_repas >= 0);
|
|
||||||
|
|
||||||
-- ==================
|
|
||||||
-- AVENANTS_CONTRATS
|
|
||||||
-- ==================
|
|
||||||
-- Rien de spécifique (statut enum déjà en place)
|
|
||||||
|
|
||||||
-- =========
|
|
||||||
-- EVENEMENTS
|
|
||||||
-- =========
|
|
||||||
ALTER TABLE evenements
|
|
||||||
ADD CONSTRAINT chk_evenements_dates_coherentes
|
|
||||||
CHECK (date_fin IS NULL OR date_debut IS NULL OR date_fin >= date_debut);
|
|
||||||
|
|
||||||
-- =================
|
|
||||||
-- SIGNALEMENTS_BUGS
|
|
||||||
-- =================
|
|
||||||
-- Description obligatoire, non vide
|
|
||||||
ALTER TABLE signalements_bugs
|
|
||||||
ALTER COLUMN description SET NOT NULL;
|
|
||||||
ALTER TABLE signalements_bugs
|
|
||||||
ADD CONSTRAINT chk_bugs_description_non_vide
|
|
||||||
CHECK (btrim(description) <> '');
|
|
||||||
|
|
||||||
-- =======
|
|
||||||
-- UPLOADS
|
|
||||||
-- =======
|
|
||||||
-- URL obligatoire + format basique (chemin absolu ou http(s))
|
|
||||||
ALTER TABLE uploads
|
|
||||||
ALTER COLUMN fichier_url SET NOT NULL;
|
|
||||||
ALTER TABLE uploads
|
|
||||||
ADD CONSTRAINT chk_uploads_url_format
|
|
||||||
CHECK (fichier_url ~ '^(https?://.+|/[^\\s]+)$');
|
|
||||||
|
|
||||||
-- =============
|
|
||||||
-- NOTIFICATIONS
|
|
||||||
-- =============
|
|
||||||
-- Contenu obligatoire, non vide
|
|
||||||
ALTER TABLE notifications
|
|
||||||
ALTER COLUMN contenu SET NOT NULL;
|
|
||||||
ALTER TABLE notifications
|
|
||||||
ADD CONSTRAINT chk_notifications_contenu_non_vide
|
|
||||||
CHECK (btrim(contenu) <> '');
|
|
||||||
|
|
||||||
-- ===========
|
|
||||||
-- VALIDATIONS
|
|
||||||
-- ===========
|
|
||||||
-- Rien de plus ici (Sprint 1 Ticket 8 enrichira la table)
|
|
||||||
@ -1,190 +0,0 @@
|
|||||||
-- ==========================================================
|
|
||||||
-- 04_fk_policies.sql : normalisation des politiques ON DELETE
|
|
||||||
-- A exécuter après 01_init.sql et 03_checks.sql
|
|
||||||
-- ==========================================================
|
|
||||||
|
|
||||||
-- Helper: Drop FK d'une table/colonne si elle existe (par son/leurs noms de colonne)
|
|
||||||
-- puis recrée la contrainte avec la clause fournie
|
|
||||||
-- Utilise information_schema pour retrouver le nom de contrainte auto-généré
|
|
||||||
-- NB: schema = public
|
|
||||||
|
|
||||||
-- ========== messages.id_expediteur -> utilisateurs.id : SET NULL (au lieu de CASCADE)
|
|
||||||
DO $$
|
|
||||||
DECLARE
|
|
||||||
conname text;
|
|
||||||
BEGIN
|
|
||||||
SELECT tc.constraint_name INTO conname
|
|
||||||
FROM information_schema.table_constraints tc
|
|
||||||
JOIN information_schema.key_column_usage kcu
|
|
||||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
|
||||||
WHERE tc.table_schema='public'
|
|
||||||
AND tc.table_name='messages'
|
|
||||||
AND tc.constraint_type='FOREIGN KEY'
|
|
||||||
AND kcu.column_name='id_expediteur';
|
|
||||||
IF conname IS NOT NULL THEN
|
|
||||||
EXECUTE format('ALTER TABLE public.messages DROP CONSTRAINT %I', conname);
|
|
||||||
END IF;
|
|
||||||
EXECUTE $sql$
|
|
||||||
ALTER TABLE public.messages
|
|
||||||
ADD CONSTRAINT fk_messages_id_expediteur
|
|
||||||
FOREIGN KEY (id_expediteur) REFERENCES public.utilisateurs(id) ON DELETE SET NULL
|
|
||||||
$sql$;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
-- ========== parents.id_co_parent -> utilisateurs.id : SET NULL
|
|
||||||
DO $$
|
|
||||||
DECLARE conname text;
|
|
||||||
BEGIN
|
|
||||||
SELECT tc.constraint_name INTO conname
|
|
||||||
FROM information_schema.table_constraints tc
|
|
||||||
JOIN information_schema.key_column_usage kcu
|
|
||||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
|
||||||
WHERE tc.table_schema='public'
|
|
||||||
AND tc.table_name='parents'
|
|
||||||
AND tc.constraint_type='FOREIGN KEY'
|
|
||||||
AND kcu.column_name='id_co_parent';
|
|
||||||
IF conname IS NOT NULL THEN
|
|
||||||
EXECUTE format('ALTER TABLE public.parents DROP CONSTRAINT %I', conname);
|
|
||||||
END IF;
|
|
||||||
EXECUTE $sql$
|
|
||||||
ALTER TABLE public.parents
|
|
||||||
ADD CONSTRAINT fk_parents_id_co_parent
|
|
||||||
FOREIGN KEY (id_co_parent) REFERENCES public.utilisateurs(id) ON DELETE SET NULL
|
|
||||||
$sql$;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
-- ========== avenants_contrats.initie_par -> utilisateurs.id : SET NULL
|
|
||||||
DO $$
|
|
||||||
DECLARE conname text;
|
|
||||||
BEGIN
|
|
||||||
SELECT tc.constraint_name INTO conname
|
|
||||||
FROM information_schema.table_constraints tc
|
|
||||||
JOIN information_schema.key_column_usage kcu
|
|
||||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
|
||||||
WHERE tc.table_schema='public'
|
|
||||||
AND tc.table_name='avenants_contrats'
|
|
||||||
AND tc.constraint_type='FOREIGN KEY'
|
|
||||||
AND kcu.column_name='initie_par';
|
|
||||||
IF conname IS NOT NULL THEN
|
|
||||||
EXECUTE format('ALTER TABLE public.avenants_contrats DROP CONSTRAINT %I', conname);
|
|
||||||
END IF;
|
|
||||||
EXECUTE $sql$
|
|
||||||
ALTER TABLE public.avenants_contrats
|
|
||||||
ADD CONSTRAINT fk_avenants_contrats_initie_par
|
|
||||||
FOREIGN KEY (initie_par) REFERENCES public.utilisateurs(id) ON DELETE SET NULL
|
|
||||||
$sql$;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
-- ========== evenements.id_am -> utilisateurs.id : SET NULL
|
|
||||||
DO $$
|
|
||||||
DECLARE conname text;
|
|
||||||
BEGIN
|
|
||||||
SELECT tc.constraint_name INTO conname
|
|
||||||
FROM information_schema.table_constraints tc
|
|
||||||
JOIN information_schema.key_column_usage kcu
|
|
||||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
|
||||||
WHERE tc.table_schema='public'
|
|
||||||
AND tc.table_name='evenements'
|
|
||||||
AND tc.constraint_type='FOREIGN KEY'
|
|
||||||
AND kcu.column_name='id_am';
|
|
||||||
IF conname IS NOT NULL THEN
|
|
||||||
EXECUTE format('ALTER TABLE public.evenements DROP CONSTRAINT %I', conname);
|
|
||||||
END IF;
|
|
||||||
EXECUTE $sql$
|
|
||||||
ALTER TABLE public.evenements
|
|
||||||
ADD CONSTRAINT fk_evenements_id_am
|
|
||||||
FOREIGN KEY (id_am) REFERENCES public.utilisateurs(id) ON DELETE SET NULL
|
|
||||||
$sql$;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
-- ========== evenements.id_parent -> parents.id_utilisateur : SET NULL
|
|
||||||
DO $$
|
|
||||||
DECLARE conname text;
|
|
||||||
BEGIN
|
|
||||||
SELECT tc.constraint_name INTO conname
|
|
||||||
FROM information_schema.table_constraints tc
|
|
||||||
JOIN information_schema.key_column_usage kcu
|
|
||||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
|
||||||
WHERE tc.table_schema='public'
|
|
||||||
AND tc.table_name='evenements'
|
|
||||||
AND tc.constraint_type='FOREIGN KEY'
|
|
||||||
AND kcu.column_name='id_parent';
|
|
||||||
IF conname IS NOT NULL THEN
|
|
||||||
EXECUTE format('ALTER TABLE public.evenements DROP CONSTRAINT %I', conname);
|
|
||||||
END IF;
|
|
||||||
EXECUTE $sql$
|
|
||||||
ALTER TABLE public.evenements
|
|
||||||
ADD CONSTRAINT fk_evenements_id_parent
|
|
||||||
FOREIGN KEY (id_parent) REFERENCES public.parents(id_utilisateur) ON DELETE SET NULL
|
|
||||||
$sql$;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
-- ========== evenements.cree_par -> utilisateurs.id : SET NULL
|
|
||||||
DO $$
|
|
||||||
DECLARE conname text;
|
|
||||||
BEGIN
|
|
||||||
SELECT tc.constraint_name INTO conname
|
|
||||||
FROM information_schema.table_constraints tc
|
|
||||||
JOIN information_schema.key_column_usage kcu
|
|
||||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
|
||||||
WHERE tc.table_schema='public'
|
|
||||||
AND tc.table_name='evenements'
|
|
||||||
AND tc.constraint_type='FOREIGN KEY'
|
|
||||||
AND kcu.column_name='cree_par';
|
|
||||||
IF conname IS NOT NULL THEN
|
|
||||||
EXECUTE format('ALTER TABLE public.evenements DROP CONSTRAINT %I', conname);
|
|
||||||
END IF;
|
|
||||||
EXECUTE $sql$
|
|
||||||
ALTER TABLE public.evenements
|
|
||||||
ADD CONSTRAINT fk_evenements_cree_par
|
|
||||||
FOREIGN KEY (cree_par) REFERENCES public.utilisateurs(id) ON DELETE SET NULL
|
|
||||||
$sql$;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
-- ========== signalements_bugs.id_utilisateur -> utilisateurs.id : SET NULL
|
|
||||||
DO $$
|
|
||||||
DECLARE conname text;
|
|
||||||
BEGIN
|
|
||||||
SELECT tc.constraint_name INTO conname
|
|
||||||
FROM information_schema.table_constraints tc
|
|
||||||
JOIN information_schema.key_column_usage kcu
|
|
||||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
|
||||||
WHERE tc.table_schema='public'
|
|
||||||
AND tc.table_name='signalements_bugs'
|
|
||||||
AND tc.constraint_type='FOREIGN KEY'
|
|
||||||
AND kcu.column_name='id_utilisateur';
|
|
||||||
IF conname IS NOT NULL THEN
|
|
||||||
EXECUTE format('ALTER TABLE public.signalements_bugs DROP CONSTRAINT %I', conname);
|
|
||||||
END IF;
|
|
||||||
EXECUTE $sql$
|
|
||||||
ALTER TABLE public.signalements_bugs
|
|
||||||
ADD CONSTRAINT fk_signalements_bugs_id_utilisateur
|
|
||||||
FOREIGN KEY (id_utilisateur) REFERENCES public.utilisateurs(id) ON DELETE SET NULL
|
|
||||||
$sql$;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
-- ========== validations.id_utilisateur -> utilisateurs.id : SET NULL
|
|
||||||
DO $$
|
|
||||||
DECLARE conname text;
|
|
||||||
BEGIN
|
|
||||||
SELECT tc.constraint_name INTO conname
|
|
||||||
FROM information_schema.table_constraints tc
|
|
||||||
JOIN information_schema.key_column_usage kcu
|
|
||||||
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
|
|
||||||
WHERE tc.table_schema='public'
|
|
||||||
AND tc.table_name='validations'
|
|
||||||
AND tc.constraint_type='FOREIGN KEY'
|
|
||||||
AND kcu.column_name='id_utilisateur';
|
|
||||||
IF conname IS NOT NULL THEN
|
|
||||||
EXECUTE format('ALTER TABLE public.validations DROP CONSTRAINT %I', conname);
|
|
||||||
END IF;
|
|
||||||
EXECUTE $sql$
|
|
||||||
ALTER TABLE public.validations
|
|
||||||
ADD CONSTRAINT fk_validations_id_utilisateur
|
|
||||||
FOREIGN KEY (id_utilisateur) REFERENCES public.utilisateurs(id) ON DELETE SET NULL
|
|
||||||
$sql$;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
-- NB:
|
|
||||||
-- D'autres FK déjà correctes : CASCADE (assistantes_maternelles, parents, enfants_parents, dossiers, messages.id_dossier, contrats, avenants_contrats.id_contrat, evenements.id_enfant), SET NULL (uploads).
|
|
||||||
-- On laisse ON UPDATE par défaut (NO ACTION), car les UUID ne changent pas.
|
|
||||||
@ -1,150 +0,0 @@
|
|||||||
-- =============================================
|
|
||||||
-- 05_triggers.sql : Timestamps automatiques
|
|
||||||
-- - Ajoute (si absent) cree_le DEFAULT now() et modifie_le DEFAULT now()
|
|
||||||
-- - Crée un trigger BEFORE UPDATE pour mettre à jour modifie_le
|
|
||||||
-- - Idempotent (DROP TRIGGER IF EXISTS / IF NOT EXISTS)
|
|
||||||
-- A exécuter après 01_init.sql, 02_indexes.sql, 03_checks.sql
|
|
||||||
-- =============================================
|
|
||||||
|
|
||||||
-- 1) Fonction unique de mise à jour du timestamp
|
|
||||||
CREATE OR REPLACE FUNCTION set_modifie_le()
|
|
||||||
RETURNS TRIGGER AS $$
|
|
||||||
BEGIN
|
|
||||||
NEW.modifie_le := NOW();
|
|
||||||
RETURN NEW;
|
|
||||||
END;
|
|
||||||
$$ LANGUAGE plpgsql;
|
|
||||||
|
|
||||||
-- Helper macro-like: pour chaque table, s'assurer des colonnes & trigger
|
|
||||||
-- (on ne peut pas faire de macro, donc on répète pour chaque table)
|
|
||||||
|
|
||||||
-- Liste des tables concernées :
|
|
||||||
-- utilisateurs, assistantes_maternelles, parents, enfants, enfants_parents,
|
|
||||||
-- dossiers, messages, contrats, avenants_contrats, evenements,
|
|
||||||
-- signalements_bugs, uploads, notifications, validations
|
|
||||||
|
|
||||||
-- ========== UTILISATEURS
|
|
||||||
ALTER TABLE utilisateurs
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_utilisateurs_set_modifie_le ON utilisateurs;
|
|
||||||
CREATE TRIGGER trg_utilisateurs_set_modifie_le
|
|
||||||
BEFORE UPDATE ON utilisateurs
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== ASSISTANTES_MATERNELLES
|
|
||||||
ALTER TABLE assistantes_maternelles
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_am_set_modifie_le ON assistantes_maternelles;
|
|
||||||
CREATE TRIGGER trg_am_set_modifie_le
|
|
||||||
BEFORE UPDATE ON assistantes_maternelles
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== PARENTS
|
|
||||||
ALTER TABLE parents
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_parents_set_modifie_le ON parents;
|
|
||||||
CREATE TRIGGER trg_parents_set_modifie_le
|
|
||||||
BEFORE UPDATE ON parents
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== ENFANTS
|
|
||||||
ALTER TABLE enfants
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_enfants_set_modifie_le ON enfants;
|
|
||||||
CREATE TRIGGER trg_enfants_set_modifie_le
|
|
||||||
BEFORE UPDATE ON enfants
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== ENFANTS_PARENTS (table de liaison)
|
|
||||||
ALTER TABLE enfants_parents
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_enfants_parents_set_modifie_le ON enfants_parents;
|
|
||||||
CREATE TRIGGER trg_enfants_parents_set_modifie_le
|
|
||||||
BEFORE UPDATE ON enfants_parents
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== DOSSIERS
|
|
||||||
ALTER TABLE dossiers
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_dossiers_set_modifie_le ON dossiers;
|
|
||||||
CREATE TRIGGER trg_dossiers_set_modifie_le
|
|
||||||
BEFORE UPDATE ON dossiers
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== MESSAGES
|
|
||||||
ALTER TABLE messages
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_messages_set_modifie_le ON messages;
|
|
||||||
CREATE TRIGGER trg_messages_set_modifie_le
|
|
||||||
BEFORE UPDATE ON messages
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== CONTRATS
|
|
||||||
ALTER TABLE contrats
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_contrats_set_modifie_le ON contrats;
|
|
||||||
CREATE TRIGGER trg_contrats_set_modifie_le
|
|
||||||
BEFORE UPDATE ON contrats
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== AVENANTS_CONTRATS
|
|
||||||
ALTER TABLE avenants_contrats
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_avenants_contrats_set_modifie_le ON avenants_contrats;
|
|
||||||
CREATE TRIGGER trg_avenants_contrats_set_modifie_le
|
|
||||||
BEFORE UPDATE ON avenants_contrats
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== EVENEMENTS
|
|
||||||
ALTER TABLE evenements
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_evenements_set_modifie_le ON evenements;
|
|
||||||
CREATE TRIGGER trg_evenements_set_modifie_le
|
|
||||||
BEFORE UPDATE ON evenements
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== SIGNALEMENTS_BUGS
|
|
||||||
ALTER TABLE signalements_bugs
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_signalements_bugs_set_modifie_le ON signalements_bugs;
|
|
||||||
CREATE TRIGGER trg_signalements_bugs_set_modifie_le
|
|
||||||
BEFORE UPDATE ON signalements_bugs
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== UPLOADS
|
|
||||||
ALTER TABLE uploads
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_uploads_set_modifie_le ON uploads;
|
|
||||||
CREATE TRIGGER trg_uploads_set_modifie_le
|
|
||||||
BEFORE UPDATE ON uploads
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== NOTIFICATIONS
|
|
||||||
ALTER TABLE notifications
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_notifications_set_modifie_le ON notifications;
|
|
||||||
CREATE TRIGGER trg_notifications_set_modifie_le
|
|
||||||
BEFORE UPDATE ON notifications
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
|
|
||||||
-- ========== VALIDATIONS
|
|
||||||
ALTER TABLE validations
|
|
||||||
ADD COLUMN IF NOT EXISTS cree_le TIMESTAMP DEFAULT NOW(),
|
|
||||||
ADD COLUMN IF NOT EXISTS modifie_le TIMESTAMP DEFAULT NOW();
|
|
||||||
DROP TRIGGER IF EXISTS trg_validations_set_modifie_le ON validations;
|
|
||||||
CREATE TRIGGER trg_validations_set_modifie_le
|
|
||||||
BEFORE UPDATE ON validations
|
|
||||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
-- ==========================================================
|
|
||||||
-- 06_validations_enrich.sql : Traçabilité complète des validations
|
|
||||||
-- - Ajoute la colonne 'valide_par' (FK -> utilisateurs.id)
|
|
||||||
-- - ON DELETE SET NULL pour conserver l'historique
|
|
||||||
-- - Ajoute index utiles pour les requêtes (valideur, statut, date)
|
|
||||||
-- A exécuter après : 01_init.sql, 02_indexes.sql, 03_checks.sql, 04_fk_policies.sql, 05_triggers.sql
|
|
||||||
-- ==========================================================
|
|
||||||
|
|
||||||
BEGIN;
|
|
||||||
|
|
||||||
-- 1) Colonne 'valide_par' si absente
|
|
||||||
ALTER TABLE validations
|
|
||||||
ADD COLUMN IF NOT EXISTS valide_par UUID NULL;
|
|
||||||
|
|
||||||
-- 2) FK vers utilisateurs(id), ON DELETE SET NULL
|
|
||||||
DO $$
|
|
||||||
DECLARE conname text;
|
|
||||||
BEGIN
|
|
||||||
SELECT tc.constraint_name INTO conname
|
|
||||||
FROM information_schema.table_constraints tc
|
|
||||||
JOIN information_schema.key_column_usage kcu
|
|
||||||
ON tc.constraint_name = kcu.constraint_name
|
|
||||||
AND tc.table_schema = kcu.table_schema
|
|
||||||
WHERE tc.table_schema = 'public'
|
|
||||||
AND tc.table_name = 'validations'
|
|
||||||
AND tc.constraint_type= 'FOREIGN KEY'
|
|
||||||
AND kcu.column_name = 'valide_par';
|
|
||||||
|
|
||||||
IF conname IS NOT NULL THEN
|
|
||||||
EXECUTE format('ALTER TABLE public.validations DROP CONSTRAINT %I', conname);
|
|
||||||
END IF;
|
|
||||||
|
|
||||||
EXECUTE $sql$
|
|
||||||
ALTER TABLE public.validations
|
|
||||||
ADD CONSTRAINT fk_validations_valide_par
|
|
||||||
FOREIGN KEY (valide_par) REFERENCES public.utilisateurs(id) ON DELETE SET NULL
|
|
||||||
$sql$;
|
|
||||||
END $$;
|
|
||||||
|
|
||||||
-- 3) Index pour accélérer les recherches
|
|
||||||
-- - qui a validé quoi récemment ?
|
|
||||||
-- - toutes les validations par statut / par date
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_validations_valide_par_cree_le
|
|
||||||
ON validations (valide_par, cree_le);
|
|
||||||
|
|
||||||
-- Certains existent peut-être déjà : on sécurise
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_validations_id_utilisateur_cree_le
|
|
||||||
ON validations (id_utilisateur, cree_le);
|
|
||||||
|
|
||||||
CREATE INDEX IF NOT EXISTS idx_validations_statut
|
|
||||||
ON validations (statut);
|
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
-- Script d'importation des données CSV dans la base Postgres du docker dev
|
|
||||||
-- À exécuter dans le conteneur ou via psql connecté à la base
|
|
||||||
-- psql -U admin -d ptitpas_db -f /docker-entrypoint-initdb.d/07_import.sql
|
|
||||||
-- Exemple d'utilisation :
|
|
||||||
|
|
||||||
|
|
||||||
-- Import utilisateurs
|
|
||||||
\copy utilisateurs FROM 'bdd/data_test/utilisateurs.csv' DELIMITER ',' CSV HEADER;
|
|
||||||
|
|
||||||
-- Import assistantes_maternelles
|
|
||||||
\copy assistantes_maternelles FROM 'bdd/data_test/assistantes_maternelles.csv' DELIMITER ',' CSV HEADER;
|
|
||||||
|
|
||||||
-- Import parents
|
|
||||||
\copy parents FROM 'bdd/data_test/parents.csv' DELIMITER ',' CSV HEADER;
|
|
||||||
|
|
||||||
-- Import enfants
|
|
||||||
\copy enfants FROM 'bdd/data_test/enfants.csv' DELIMITER ',' CSV HEADER;
|
|
||||||
|
|
||||||
-- Import enfants_parents
|
|
||||||
\copy enfants_parents FROM 'bdd/data_test/enfants_parents.csv' DELIMITER ',' CSV HEADER;
|
|
||||||
|
|
||||||
-- Import dossiers
|
|
||||||
\copy dossiers FROM 'bdd/data_test/dossiers.csv' DELIMITER ',' CSV HEADER;
|
|
||||||
|
|
||||||
-- Import contrats
|
|
||||||
\copy contrats FROM 'bdd/data_test/contrats.csv' DELIMITER ',' CSV HEADER;
|
|
||||||
|
|
||||||
-- Import validations
|
|
||||||
\copy validations FROM 'bdd/data_test/validations.csv' DELIMITER ',' CSV HEADER;
|
|
||||||
|
|
||||||
-- Import notifications
|
|
||||||
\copy notifications FROM 'bdd/data_test/notifications.csv' DELIMITER ',' CSV HEADER;
|
|
||||||
|
|
||||||
-- Import uploads
|
|
||||||
\copy uploads FROM 'bdd/data_test/uploads.csv' DELIMITER ',' CSV HEADER;
|
|
||||||
|
|
||||||
-- Import evenements
|
|
||||||
\copy evenements FROM 'bdd/data_test/evenements.csv' DELIMITER ',' CSV HEADER;
|
|
||||||
|
|
||||||
-- Remarque :
|
|
||||||
-- Les chemins doivent être accessibles depuis le conteneur Docker (monter le dossier si besoin)
|
|
||||||
-- Adapter l'utilisateur, la base et le chemin si nécessaire
|
|
||||||
@ -9,7 +9,7 @@ services:
|
|||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
POSTGRES_DB: ${POSTGRES_DB}
|
POSTGRES_DB: ${POSTGRES_DB}
|
||||||
volumes:
|
volumes:
|
||||||
- ./database/migrations/01_init.sql:/docker-entrypoint-initdb.d/01_init.sql
|
- ./database/BDD.sql:/docker-entrypoint-initdb.d/01_init.sql
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
networks:
|
networks:
|
||||||
- ptitspas_network
|
- ptitspas_network
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user