-- Migration V1.3: Conversion des colonnes ID de BIGINT vers UUID -- Auteur: UnionFlow Team -- Date: 2025-01-16 -- Description: Convertit toutes les colonnes ID et clés étrangères de BIGINT vers UUID -- ATTENTION: Cette migration supprime toutes les données existantes pour simplifier la conversion -- Pour une migration avec préservation des données, voir V1.3.1__Convert_Ids_To_UUID_With_Data.sql -- ============================================ -- ÉTAPE 1: Suppression des contraintes de clés étrangères -- ============================================ -- Supprimer les contraintes de clés étrangères existantes DO $$ BEGIN -- Supprimer FK membres -> organisations IF EXISTS ( SELECT 1 FROM information_schema.table_constraints WHERE constraint_name = 'fk_membre_organisation' AND table_name = 'membres' ) THEN ALTER TABLE membres DROP CONSTRAINT fk_membre_organisation; END IF; -- Supprimer FK cotisations -> membres IF EXISTS ( SELECT 1 FROM information_schema.table_constraints WHERE constraint_name LIKE 'fk_cotisation%' AND table_name = 'cotisations' ) THEN ALTER TABLE cotisations DROP CONSTRAINT IF EXISTS fk_cotisation_membre CASCADE; END IF; -- Supprimer FK evenements -> organisations IF EXISTS ( SELECT 1 FROM information_schema.table_constraints WHERE constraint_name LIKE 'fk_evenement%' AND table_name = 'evenements' ) THEN ALTER TABLE evenements DROP CONSTRAINT IF EXISTS fk_evenement_organisation CASCADE; END IF; -- Supprimer FK inscriptions_evenement -> membres et evenements IF EXISTS ( SELECT 1 FROM information_schema.table_constraints WHERE constraint_name LIKE 'fk_inscription%' AND table_name = 'inscriptions_evenement' ) THEN ALTER TABLE inscriptions_evenement DROP CONSTRAINT IF EXISTS fk_inscription_membre CASCADE; ALTER TABLE inscriptions_evenement DROP CONSTRAINT IF EXISTS fk_inscription_evenement CASCADE; END IF; -- Supprimer FK demandes_aide -> membres et organisations IF EXISTS ( SELECT 1 FROM information_schema.table_constraints WHERE constraint_name LIKE 'fk_demande%' AND table_name = 'demandes_aide' ) THEN ALTER TABLE demandes_aide DROP CONSTRAINT IF EXISTS fk_demande_demandeur CASCADE; ALTER TABLE demandes_aide DROP CONSTRAINT IF EXISTS fk_demande_evaluateur CASCADE; ALTER TABLE demandes_aide DROP CONSTRAINT IF EXISTS fk_demande_organisation CASCADE; END IF; END $$; -- ============================================ -- ÉTAPE 2: Supprimer les séquences (BIGSERIAL) -- ============================================ DROP SEQUENCE IF EXISTS membres_SEQ CASCADE; DROP SEQUENCE IF EXISTS cotisations_SEQ CASCADE; DROP SEQUENCE IF EXISTS evenements_SEQ CASCADE; DROP SEQUENCE IF EXISTS organisations_id_seq CASCADE; -- ============================================ -- ÉTAPE 3: Supprimer les tables existantes (pour recréation avec UUID) -- ============================================ -- Supprimer les tables dans l'ordre inverse des dépendances DROP TABLE IF EXISTS inscriptions_evenement CASCADE; DROP TABLE IF EXISTS demandes_aide CASCADE; DROP TABLE IF EXISTS cotisations CASCADE; DROP TABLE IF EXISTS evenements CASCADE; DROP TABLE IF EXISTS membres CASCADE; DROP TABLE IF EXISTS organisations CASCADE; -- ============================================ -- ÉTAPE 4: Recréer les tables avec UUID -- ============================================ -- Table organisations avec UUID CREATE TABLE organisations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- Informations de base nom VARCHAR(200) NOT NULL, nom_court VARCHAR(50), type_organisation VARCHAR(50) NOT NULL DEFAULT 'ASSOCIATION', statut VARCHAR(50) NOT NULL DEFAULT 'ACTIVE', description TEXT, date_fondation DATE, numero_enregistrement VARCHAR(100) UNIQUE, -- Informations de contact email VARCHAR(255) NOT NULL UNIQUE, telephone VARCHAR(20), telephone_secondaire VARCHAR(20), email_secondaire VARCHAR(255), -- Adresse adresse VARCHAR(500), ville VARCHAR(100), code_postal VARCHAR(20), region VARCHAR(100), pays VARCHAR(100), -- Coordonnées géographiques latitude DECIMAL(9,6) CHECK (latitude >= -90 AND latitude <= 90), longitude DECIMAL(9,6) CHECK (longitude >= -180 AND longitude <= 180), -- Web et réseaux sociaux site_web VARCHAR(500), logo VARCHAR(500), reseaux_sociaux VARCHAR(1000), -- Hiérarchie organisation_parente_id UUID, niveau_hierarchique INTEGER NOT NULL DEFAULT 0, -- Statistiques nombre_membres INTEGER NOT NULL DEFAULT 0, nombre_administrateurs INTEGER NOT NULL DEFAULT 0, -- Finances budget_annuel DECIMAL(14,2) CHECK (budget_annuel >= 0), devise VARCHAR(3) DEFAULT 'XOF', cotisation_obligatoire BOOLEAN NOT NULL DEFAULT FALSE, montant_cotisation_annuelle DECIMAL(12,2) CHECK (montant_cotisation_annuelle >= 0), -- Informations complémentaires objectifs TEXT, activites_principales TEXT, certifications VARCHAR(500), partenaires VARCHAR(1000), notes VARCHAR(1000), -- Paramètres organisation_publique BOOLEAN NOT NULL DEFAULT TRUE, accepte_nouveaux_membres BOOLEAN NOT NULL DEFAULT TRUE, -- Métadonnées (héritées de BaseEntity) actif BOOLEAN NOT NULL DEFAULT TRUE, date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, date_modification TIMESTAMP, cree_par VARCHAR(255), modifie_par VARCHAR(255), version BIGINT NOT NULL DEFAULT 0, -- Contraintes CONSTRAINT chk_organisation_statut CHECK (statut IN ('ACTIVE', 'SUSPENDUE', 'DISSOUTE', 'EN_ATTENTE')), CONSTRAINT chk_organisation_type CHECK (type_organisation IN ( 'ASSOCIATION', 'LIONS_CLUB', 'ROTARY_CLUB', 'COOPERATIVE', 'FONDATION', 'ONG', 'SYNDICAT', 'AUTRE' )), CONSTRAINT chk_organisation_devise CHECK (devise IN ('XOF', 'EUR', 'USD', 'GBP', 'CHF')), CONSTRAINT chk_organisation_niveau CHECK (niveau_hierarchique >= 0 AND niveau_hierarchique <= 10), CONSTRAINT chk_organisation_membres CHECK (nombre_membres >= 0), CONSTRAINT chk_organisation_admins CHECK (nombre_administrateurs >= 0), -- Clé étrangère pour hiérarchie CONSTRAINT fk_organisation_parente FOREIGN KEY (organisation_parente_id) REFERENCES organisations(id) ON DELETE SET NULL ); -- Table membres avec UUID CREATE TABLE membres ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), numero_membre VARCHAR(20) UNIQUE NOT NULL, prenom VARCHAR(100) NOT NULL, nom VARCHAR(100) NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, mot_de_passe VARCHAR(255), telephone VARCHAR(20), date_naissance DATE NOT NULL, date_adhesion DATE NOT NULL, roles VARCHAR(500), -- Clé étrangère vers organisations organisation_id UUID, -- Métadonnées (héritées de BaseEntity) actif BOOLEAN NOT NULL DEFAULT TRUE, date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, date_modification TIMESTAMP, cree_par VARCHAR(255), modifie_par VARCHAR(255), version BIGINT NOT NULL DEFAULT 0, CONSTRAINT fk_membre_organisation FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE SET NULL ); -- Table cotisations avec UUID CREATE TABLE cotisations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), numero_reference VARCHAR(50) UNIQUE NOT NULL, membre_id UUID NOT NULL, type_cotisation VARCHAR(50) NOT NULL, montant_du DECIMAL(12,2) NOT NULL CHECK (montant_du >= 0), montant_paye DECIMAL(12,2) NOT NULL DEFAULT 0 CHECK (montant_paye >= 0), code_devise VARCHAR(3) NOT NULL DEFAULT 'XOF', statut VARCHAR(30) NOT NULL, date_echeance DATE NOT NULL, date_paiement TIMESTAMP, description VARCHAR(500), periode VARCHAR(20), annee INTEGER NOT NULL CHECK (annee >= 2020 AND annee <= 2100), mois INTEGER CHECK (mois >= 1 AND mois <= 12), observations VARCHAR(1000), recurrente BOOLEAN NOT NULL DEFAULT FALSE, nombre_rappels INTEGER NOT NULL DEFAULT 0 CHECK (nombre_rappels >= 0), date_dernier_rappel TIMESTAMP, valide_par_id UUID, nom_validateur VARCHAR(100), date_validation TIMESTAMP, methode_paiement VARCHAR(50), reference_paiement VARCHAR(100), -- Métadonnées (héritées de BaseEntity) actif BOOLEAN NOT NULL DEFAULT TRUE, date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, date_modification TIMESTAMP, cree_par VARCHAR(255), modifie_par VARCHAR(255), version BIGINT NOT NULL DEFAULT 0, CONSTRAINT fk_cotisation_membre FOREIGN KEY (membre_id) REFERENCES membres(id) ON DELETE CASCADE, CONSTRAINT chk_cotisation_statut CHECK (statut IN ('EN_ATTENTE', 'PAYEE', 'EN_RETARD', 'PARTIELLEMENT_PAYEE', 'ANNULEE')), CONSTRAINT chk_cotisation_devise CHECK (code_devise ~ '^[A-Z]{3}$') ); -- Table evenements avec UUID CREATE TABLE evenements ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), titre VARCHAR(200) NOT NULL, description VARCHAR(2000), date_debut TIMESTAMP NOT NULL, date_fin TIMESTAMP, lieu VARCHAR(255) NOT NULL, adresse VARCHAR(500), ville VARCHAR(100), pays VARCHAR(100), code_postal VARCHAR(20), latitude DECIMAL(9,6), longitude DECIMAL(9,6), type_evenement VARCHAR(50) NOT NULL, statut VARCHAR(50) NOT NULL, url_inscription VARCHAR(500), url_informations VARCHAR(500), image_url VARCHAR(500), capacite_max INTEGER, cout_participation DECIMAL(12,2), devise VARCHAR(3), est_public BOOLEAN NOT NULL DEFAULT TRUE, tags VARCHAR(500), notes VARCHAR(1000), -- Clé étrangère vers organisations organisation_id UUID, -- Métadonnées (héritées de BaseEntity) actif BOOLEAN NOT NULL DEFAULT TRUE, date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, date_modification TIMESTAMP, cree_par VARCHAR(255), modifie_par VARCHAR(255), version BIGINT NOT NULL DEFAULT 0, CONSTRAINT fk_evenement_organisation FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE SET NULL ); -- Table inscriptions_evenement avec UUID CREATE TABLE inscriptions_evenement ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), membre_id UUID NOT NULL, evenement_id UUID NOT NULL, date_inscription TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, statut VARCHAR(20) DEFAULT 'CONFIRMEE', commentaire VARCHAR(500), -- Métadonnées (héritées de BaseEntity) actif BOOLEAN NOT NULL DEFAULT TRUE, date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, date_modification TIMESTAMP, cree_par VARCHAR(255), modifie_par VARCHAR(255), version BIGINT NOT NULL DEFAULT 0, CONSTRAINT fk_inscription_membre FOREIGN KEY (membre_id) REFERENCES membres(id) ON DELETE CASCADE, CONSTRAINT fk_inscription_evenement FOREIGN KEY (evenement_id) REFERENCES evenements(id) ON DELETE CASCADE, CONSTRAINT chk_inscription_statut CHECK (statut IN ('CONFIRMEE', 'EN_ATTENTE', 'ANNULEE', 'REFUSEE')), CONSTRAINT uk_inscription_membre_evenement UNIQUE (membre_id, evenement_id) ); -- Table demandes_aide avec UUID CREATE TABLE demandes_aide ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), titre VARCHAR(200) NOT NULL, description TEXT NOT NULL, type_aide VARCHAR(50) NOT NULL, statut VARCHAR(50) NOT NULL, montant_demande DECIMAL(10,2), montant_approuve DECIMAL(10,2), date_demande TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, date_evaluation TIMESTAMP, date_versement TIMESTAMP, justification TEXT, commentaire_evaluation TEXT, urgence BOOLEAN NOT NULL DEFAULT FALSE, documents_fournis VARCHAR(500), -- Clés étrangères demandeur_id UUID NOT NULL, evaluateur_id UUID, organisation_id UUID NOT NULL, -- Métadonnées (héritées de BaseEntity) actif BOOLEAN NOT NULL DEFAULT TRUE, date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, date_modification TIMESTAMP, cree_par VARCHAR(255), modifie_par VARCHAR(255), version BIGINT NOT NULL DEFAULT 0, CONSTRAINT fk_demande_demandeur FOREIGN KEY (demandeur_id) REFERENCES membres(id) ON DELETE CASCADE, CONSTRAINT fk_demande_evaluateur FOREIGN KEY (evaluateur_id) REFERENCES membres(id) ON DELETE SET NULL, CONSTRAINT fk_demande_organisation FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE CASCADE ); -- ============================================ -- ÉTAPE 5: Recréer les index -- ============================================ -- Index pour organisations CREATE INDEX idx_organisation_nom ON organisations(nom); CREATE INDEX idx_organisation_email ON organisations(email); CREATE INDEX idx_organisation_statut ON organisations(statut); CREATE INDEX idx_organisation_type ON organisations(type_organisation); CREATE INDEX idx_organisation_ville ON organisations(ville); CREATE INDEX idx_organisation_pays ON organisations(pays); CREATE INDEX idx_organisation_parente ON organisations(organisation_parente_id); CREATE INDEX idx_organisation_numero_enregistrement ON organisations(numero_enregistrement); CREATE INDEX idx_organisation_actif ON organisations(actif); CREATE INDEX idx_organisation_date_creation ON organisations(date_creation); CREATE INDEX idx_organisation_publique ON organisations(organisation_publique); CREATE INDEX idx_organisation_accepte_membres ON organisations(accepte_nouveaux_membres); CREATE INDEX idx_organisation_statut_actif ON organisations(statut, actif); -- Index pour membres CREATE INDEX idx_membre_email ON membres(email); CREATE INDEX idx_membre_numero ON membres(numero_membre); CREATE INDEX idx_membre_actif ON membres(actif); CREATE INDEX idx_membre_organisation ON membres(organisation_id); -- Index pour cotisations CREATE INDEX idx_cotisation_membre ON cotisations(membre_id); CREATE INDEX idx_cotisation_reference ON cotisations(numero_reference); CREATE INDEX idx_cotisation_statut ON cotisations(statut); CREATE INDEX idx_cotisation_echeance ON cotisations(date_echeance); CREATE INDEX idx_cotisation_type ON cotisations(type_cotisation); CREATE INDEX idx_cotisation_annee_mois ON cotisations(annee, mois); -- Index pour evenements CREATE INDEX idx_evenement_date_debut ON evenements(date_debut); CREATE INDEX idx_evenement_statut ON evenements(statut); CREATE INDEX idx_evenement_type ON evenements(type_evenement); CREATE INDEX idx_evenement_organisation ON evenements(organisation_id); -- Index pour inscriptions_evenement CREATE INDEX idx_inscription_membre ON inscriptions_evenement(membre_id); CREATE INDEX idx_inscription_evenement ON inscriptions_evenement(evenement_id); CREATE INDEX idx_inscription_date ON inscriptions_evenement(date_inscription); -- Index pour demandes_aide CREATE INDEX idx_demande_demandeur ON demandes_aide(demandeur_id); CREATE INDEX idx_demande_evaluateur ON demandes_aide(evaluateur_id); CREATE INDEX idx_demande_organisation ON demandes_aide(organisation_id); CREATE INDEX idx_demande_statut ON demandes_aide(statut); CREATE INDEX idx_demande_type ON demandes_aide(type_aide); CREATE INDEX idx_demande_date_demande ON demandes_aide(date_demande); -- ============================================ -- ÉTAPE 6: Commentaires sur les tables -- ============================================ COMMENT ON TABLE organisations IS 'Table des organisations (Lions Clubs, Associations, Coopératives, etc.) avec UUID'; COMMENT ON TABLE membres IS 'Table des membres avec UUID'; COMMENT ON TABLE cotisations IS 'Table des cotisations avec UUID'; COMMENT ON TABLE evenements IS 'Table des événements avec UUID'; COMMENT ON TABLE inscriptions_evenement IS 'Table des inscriptions aux événements avec UUID'; COMMENT ON TABLE demandes_aide IS 'Table des demandes d''aide avec UUID'; COMMENT ON COLUMN organisations.id IS 'UUID unique de l''organisation'; COMMENT ON COLUMN membres.id IS 'UUID unique du membre'; COMMENT ON COLUMN cotisations.id IS 'UUID unique de la cotisation'; COMMENT ON COLUMN evenements.id IS 'UUID unique de l''événement'; COMMENT ON COLUMN inscriptions_evenement.id IS 'UUID unique de l''inscription'; COMMENT ON COLUMN demandes_aide.id IS 'UUID unique de la demande d''aide';