ajout de script / modif d'enum et simplification du lancement en local
This commit is contained in:
+48
-148
@@ -1,157 +1,57 @@
|
||||
-- =============================================
|
||||
-- 02_indexes.sql : Index FK + colonnes critiques
|
||||
-- =============================================
|
||||
-- ============================================================
|
||||
-- 02_indexes.sql — Indexes pour améliorer les perfs
|
||||
-- ============================================================
|
||||
|
||||
-- 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
|
||||
-- ===========================================
|
||||
-- Messages (par dossier + tri par date)
|
||||
-- Utilisé dans verify.sql (EXPLAIN + ORDER BY cree_le)
|
||||
-- ===========================================
|
||||
CREATE INDEX IF NOT EXISTS idx_messages_id_dossier_cree_le
|
||||
ON messages (id_dossier, cree_le);
|
||||
ON messages (id_dossier, cree_le DESC);
|
||||
|
||||
-- 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
|
||||
-- ===========================================
|
||||
-- Evenements (filtrés par enfant + date)
|
||||
-- Utilisé dans verify.sql (WHERE id_enfant AND date_debut >= ...)
|
||||
-- ===========================================
|
||||
CREATE INDEX IF NOT EXISTS idx_evenements_id_enfant_date_debut
|
||||
ON evenements (id_enfant, date_debut);
|
||||
ON evenements (id_enfant, date_debut DESC);
|
||||
|
||||
-- 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
|
||||
-- ===========================================
|
||||
-- Notifications (par utilisateur + lues/non lues + tri par date)
|
||||
-- Utilisé dans verify.sql (WHERE id_utilisateur AND lu=false ORDER BY cree_le DESC)
|
||||
-- ===========================================
|
||||
CREATE INDEX IF NOT EXISTS idx_notifications_user_lu_cree_le
|
||||
ON notifications (id_utilisateur, lu, cree_le);
|
||||
ON notifications (id_utilisateur, lu, cree_le DESC);
|
||||
|
||||
-- Option : index partiel pour "non lues"
|
||||
-- CREATE INDEX IF NOT EXISTS idx_notifications_non_lues
|
||||
-- ON notifications (id_utilisateur, cree_le)
|
||||
-- WHERE lu = false;
|
||||
-- ===========================================
|
||||
-- Dossiers (filtrés par parent + enfant + statut + tri par date)
|
||||
-- Utilisé dans verify.sql
|
||||
-- ===========================================
|
||||
CREATE INDEX IF NOT EXISTS idx_dossiers_id_parent_enfant_statut_cree_le
|
||||
ON dossiers (id_parent, id_enfant, statut, cree_le DESC);
|
||||
|
||||
-- ===========
|
||||
-- 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);
|
||||
-- ===========================================
|
||||
-- Contrats (lookup par dossier unique)
|
||||
-- ===========================================
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_contrats_id_dossier
|
||||
ON contrats (id_dossier);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_validations_statut
|
||||
ON validations (statut);
|
||||
-- ===========================================
|
||||
-- JSONB indexes (si filtres fréquents sur planning/planning_souhaite)
|
||||
-- Exemple dans verify.sql : dossiers.planning_souhaite @> ...
|
||||
-- ===========================================
|
||||
CREATE INDEX IF NOT EXISTS idx_dossiers_planning_souhaite_gin
|
||||
ON dossiers USING gin (planning_souhaite jsonb_path_ops);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_contrats_planning_gin
|
||||
ON contrats USING gin (planning jsonb_path_ops);
|
||||
|
||||
-- ===========================================
|
||||
-- Sanity check : validation des emails uniques
|
||||
-- Déjà couvert par UNIQUE dans la table utilisateurs
|
||||
-- ===========================================
|
||||
|
||||
-- ===========================================
|
||||
-- Bonus : accélérer les jointures fréquentes
|
||||
-- (utilisateurs.id, enfants.id, parents.id_utilisateur sont PK → déjà indexées automatiquement)
|
||||
-- ===========================================
|
||||
|
||||
+58
-124
@@ -1,140 +1,74 @@
|
||||
-- =============================================
|
||||
-- 03_checks.sql : Contraintes CHECK & NOT NULL
|
||||
-- A exécuter après 01_init.sql (et 02_indexes.sql)
|
||||
-- =============================================
|
||||
-- ============================================================
|
||||
-- 03_checks.sql — Contraintes d'intégrité métier
|
||||
-- ============================================================
|
||||
|
||||
-- ==============
|
||||
-- ===========================================
|
||||
-- UTILISATEURS
|
||||
-- ==============
|
||||
-- (Regex email déjà présente dans 01_init.sql)
|
||||
-- Optionnel : forcer prenom/nom non vides si fournis
|
||||
-- ===========================================
|
||||
|
||||
-- Email déjà couvert par UNIQUE + regex dans le schéma
|
||||
-- Vérifier que mobile et téléphone fixe ne sont pas identiques
|
||||
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)
|
||||
ADD CONSTRAINT chk_telephone_diff CHECK (
|
||||
mobile IS NULL OR telephone_fixe IS NULL OR mobile <> telephone_fixe
|
||||
);
|
||||
|
||||
-- =================
|
||||
-- ENFANTS_PARENTS
|
||||
-- =================
|
||||
-- (PK composite déjà en place, rien à ajouter ici)
|
||||
-- ===========================================
|
||||
-- ENFANTS
|
||||
-- ===========================================
|
||||
|
||||
-- ========
|
||||
-- Si l’enfant est "a_naitre", la date_prevue_naissance doit être renseignée
|
||||
ALTER TABLE enfants
|
||||
ADD CONSTRAINT chk_enfant_date_prevue
|
||||
CHECK (
|
||||
(statut = 'a_naitre' AND date_prevue_naissance IS NOT NULL)
|
||||
OR (statut <> 'a_naitre')
|
||||
);
|
||||
|
||||
-- Si l’enfant est déjà né, sa date_naissance doit être renseignée
|
||||
ALTER TABLE enfants
|
||||
ADD CONSTRAINT chk_enfant_date_naissance
|
||||
CHECK (
|
||||
(statut IN ('actif','scolarise') AND date_naissance IS NOT NULL)
|
||||
OR (statut = 'a_naitre')
|
||||
);
|
||||
|
||||
-- ===========================================
|
||||
-- DOSSIERS
|
||||
-- ========
|
||||
-- ===========================================
|
||||
|
||||
-- Budget positif si renseigné
|
||||
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');
|
||||
ADD CONSTRAINT chk_dossier_budget_pos CHECK (budget IS NULL OR budget > 0);
|
||||
|
||||
-- ========
|
||||
-- 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
|
||||
-- =========
|
||||
-- ===========================================
|
||||
|
||||
-- Cohérence des dates : date_debut obligatoire pour un contrat signé
|
||||
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);
|
||||
ADD CONSTRAINT chk_contrat_date_debut
|
||||
CHECK (
|
||||
(statut = 'brouillon' OR date_debut IS NOT NULL)
|
||||
);
|
||||
|
||||
-- ==================
|
||||
-- AVENANTS_CONTRATS
|
||||
-- ==================
|
||||
-- Rien de spécifique (statut enum déjà en place)
|
||||
|
||||
-- =========
|
||||
-- ===========================================
|
||||
-- EVENEMENTS
|
||||
-- =========
|
||||
-- ===========================================
|
||||
|
||||
-- Cohérence des dates : début < fin
|
||||
ALTER TABLE evenements
|
||||
ADD CONSTRAINT chk_evenements_dates_coherentes
|
||||
CHECK (date_fin IS NULL OR date_debut IS NULL OR date_fin >= date_debut);
|
||||
ADD CONSTRAINT chk_evenement_dates
|
||||
CHECK (date_fin IS NULL OR date_debut <= date_fin);
|
||||
|
||||
-- =================
|
||||
-- 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)
|
||||
-- ===========================================
|
||||
|
||||
-- Si statut = 'valide', alors modifie_le doit être >= cree_le
|
||||
ALTER TABLE validations
|
||||
ADD CONSTRAINT chk_validation_modif
|
||||
CHECK (
|
||||
(statut <> 'valide')
|
||||
OR (modifie_le IS NULL OR modifie_le >= cree_le)
|
||||
);
|
||||
|
||||
+85
-132
@@ -1,150 +1,103 @@
|
||||
-- =============================================
|
||||
-- 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
|
||||
-- =============================================
|
||||
-- ============================================================
|
||||
-- 05_triggers.sql — Triggers métier et maintenance
|
||||
-- ============================================================
|
||||
|
||||
-- 1) Fonction unique de mise à jour du timestamp
|
||||
-- ===========================================
|
||||
-- 1. Mettre à jour automatiquement modifie_le
|
||||
-- ===========================================
|
||||
CREATE OR REPLACE FUNCTION set_modifie_le()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.modifie_le := NOW();
|
||||
RETURN NEW;
|
||||
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
|
||||
-- Appliquer sur les tables qui ont modifie_le
|
||||
CREATE TRIGGER trg_update_modifie_le_utilisateurs
|
||||
BEFORE UPDATE ON utilisateurs
|
||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
||||
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
|
||||
CREATE TRIGGER trg_update_modifie_le_dossiers
|
||||
BEFORE UPDATE ON dossiers
|
||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
||||
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
|
||||
CREATE TRIGGER trg_update_modifie_le_contrats
|
||||
BEFORE UPDATE ON contrats
|
||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
||||
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
|
||||
CREATE TRIGGER trg_update_modifie_le_avenants
|
||||
BEFORE UPDATE ON avenants_contrats
|
||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
||||
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
|
||||
CREATE TRIGGER trg_update_modifie_le_evenements
|
||||
BEFORE UPDATE ON evenements
|
||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
||||
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
|
||||
CREATE TRIGGER trg_update_modifie_le_validations
|
||||
BEFORE UPDATE ON validations
|
||||
FOR EACH ROW EXECUTE FUNCTION set_modifie_le();
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION set_modifie_le();
|
||||
|
||||
-- ===========================================
|
||||
-- 2. Empêcher plusieurs contrats actifs par dossier
|
||||
-- ===========================================
|
||||
CREATE OR REPLACE FUNCTION prevent_multiple_active_contrats()
|
||||
RETURNS TRIGGER AS $$
|
||||
DECLARE
|
||||
nb_actifs INT;
|
||||
BEGIN
|
||||
IF NEW.statut IN ('en_attente_signature','valide') THEN
|
||||
SELECT COUNT(*) INTO nb_actifs
|
||||
FROM contrats
|
||||
WHERE id_dossier = NEW.id_dossier
|
||||
AND statut IN ('en_attente_signature','valide')
|
||||
AND id <> COALESCE(NEW.id, gen_random_uuid());
|
||||
|
||||
IF nb_actifs > 0 THEN
|
||||
RAISE EXCEPTION 'Un contrat actif existe déjà pour ce dossier (%).', NEW.id_dossier;
|
||||
END IF;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_one_active_contrat_per_dossier
|
||||
BEFORE INSERT OR UPDATE ON contrats
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION prevent_multiple_active_contrats();
|
||||
|
||||
-- ===========================================
|
||||
-- 3. Empêcher événements incohérents
|
||||
-- - Pas de chevauchement de congés pour le même AM
|
||||
-- ===========================================
|
||||
CREATE OR REPLACE FUNCTION prevent_overlapping_events()
|
||||
RETURNS TRIGGER AS $$
|
||||
DECLARE
|
||||
nb_overlap INT;
|
||||
BEGIN
|
||||
IF NEW.id_am IS NOT NULL AND NEW.date_debut IS NOT NULL AND NEW.date_fin IS NOT NULL THEN
|
||||
SELECT COUNT(*) INTO nb_overlap
|
||||
FROM evenements ev
|
||||
WHERE ev.id_am = NEW.id_am
|
||||
AND ev.id <> COALESCE(NEW.id, gen_random_uuid())
|
||||
AND ev.date_fin >= NEW.date_debut
|
||||
AND ev.date_debut <= NEW.date_fin;
|
||||
|
||||
IF nb_overlap > 0 THEN
|
||||
RAISE EXCEPTION 'Conflit d''événements : chevauchement détecté pour AM %', NEW.id_am;
|
||||
END IF;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_no_overlapping_am_events
|
||||
BEFORE INSERT OR UPDATE ON evenements
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION prevent_overlapping_events();
|
||||
|
||||
Reference in New Issue
Block a user