-- ============================================= -- 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)