Erreur corrigée : UUID passé à %d (entier) au lieu de %s (string) - OrganisationResource.java:227 : LOG.infof(..., %s, id) Note : 36 tests échouent encore (problèmes d'auth, validation, NPE) Couverture actuelle : 50% (objectif 100% reporté) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2330 lines
112 KiB
SQL
2330 lines
112 KiB
SQL
-- ============================================================================
|
||
-- UnionFlow - Schema Complete V1
|
||
-- ============================================================================
|
||
-- ATTENTION: Ce fichier a été nettoyé pour supprimer les sections redondantes.
|
||
-- Il contient uniquement la version consolidée finale du schema avec CREATE TABLE IF NOT EXISTS.
|
||
-- Les sections avec CREATE/DROP/CREATE multiples ont été supprimées pour éviter les conflits.
|
||
-- Auteur: UnionFlow Team / Lions Dev
|
||
-- Date: 2026-03-13 (nettoyage)
|
||
-- ============================================================================
|
||
|
||
|
||
-- ========== V1.7__Create_All_Missing_Tables.sql ==========
|
||
-- ============================================================================
|
||
-- V2.0 : Création de toutes les tables manquantes pour UnionFlow
|
||
-- Toutes les tables héritent de BaseEntity (id UUID PK, date_creation,
|
||
-- date_modification, cree_par, modifie_par, version, actif)
|
||
-- ============================================================================
|
||
|
||
-- Colonnes communes BaseEntity (à inclure dans chaque table)
|
||
-- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
-- date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
-- date_modification TIMESTAMP,
|
||
-- cree_par VARCHAR(255),
|
||
-- modifie_par VARCHAR(255),
|
||
-- version BIGINT DEFAULT 0,
|
||
-- actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
|
||
-- ============================================================================
|
||
-- 1. TABLES PRINCIPALES (sans FK vers d'autres tables métier)
|
||
-- ============================================================================
|
||
|
||
-- Table membres (principale, référencée par beaucoup d'autres)
|
||
CREATE TABLE IF NOT EXISTS membres (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
nom VARCHAR(100) NOT NULL,
|
||
prenom VARCHAR(100) NOT NULL,
|
||
email VARCHAR(255),
|
||
telephone VARCHAR(30),
|
||
numero_membre VARCHAR(50),
|
||
date_naissance DATE,
|
||
lieu_naissance VARCHAR(255),
|
||
sexe VARCHAR(10),
|
||
nationalite VARCHAR(100),
|
||
profession VARCHAR(255),
|
||
photo_url VARCHAR(500),
|
||
statut VARCHAR(30) DEFAULT 'ACTIF',
|
||
date_adhesion DATE,
|
||
keycloak_user_id VARCHAR(255),
|
||
keycloak_realm VARCHAR(255),
|
||
organisation_id UUID,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
-- Table organisations (déjà créée en V1.2, mais IF NOT EXISTS pour sécurité)
|
||
CREATE TABLE IF NOT EXISTS organisations (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
nom VARCHAR(255) NOT NULL,
|
||
sigle VARCHAR(50),
|
||
description TEXT,
|
||
type_organisation VARCHAR(50),
|
||
statut VARCHAR(30) DEFAULT 'ACTIVE',
|
||
email VARCHAR(255),
|
||
telephone VARCHAR(30),
|
||
site_web VARCHAR(500),
|
||
adresse_siege TEXT,
|
||
logo_url VARCHAR(500),
|
||
date_fondation DATE,
|
||
pays VARCHAR(100),
|
||
ville VARCHAR(100),
|
||
organisation_parente_id UUID,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 2. TABLES SÉCURITÉ (Rôles et Permissions)
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS roles (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
nom VARCHAR(100) NOT NULL UNIQUE,
|
||
description VARCHAR(500),
|
||
code VARCHAR(50) NOT NULL UNIQUE,
|
||
niveau INTEGER DEFAULT 0,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS permissions (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
nom VARCHAR(100) NOT NULL UNIQUE,
|
||
description VARCHAR(500),
|
||
code VARCHAR(100) NOT NULL UNIQUE,
|
||
module VARCHAR(100),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS roles_permissions (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
role_id UUID NOT NULL REFERENCES roles(id),
|
||
permission_id UUID NOT NULL REFERENCES permissions(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
UNIQUE(role_id, permission_id)
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS membres_roles (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
membre_id UUID NOT NULL REFERENCES membres(id),
|
||
role_id UUID NOT NULL REFERENCES roles(id),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
UNIQUE(membre_id, role_id, organisation_id)
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 3. TABLES FINANCE
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS adhesions (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
numero_adhesion VARCHAR(50),
|
||
membre_id UUID REFERENCES membres(id),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
statut VARCHAR(30) DEFAULT 'EN_ATTENTE',
|
||
date_demande TIMESTAMP,
|
||
date_approbation TIMESTAMP,
|
||
date_rejet TIMESTAMP,
|
||
motif_rejet TEXT,
|
||
frais_adhesion DECIMAL(15,2) DEFAULT 0,
|
||
devise VARCHAR(10) DEFAULT 'XOF',
|
||
montant_paye DECIMAL(15,2) DEFAULT 0,
|
||
approuve_par VARCHAR(255),
|
||
commentaire TEXT,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS cotisations (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
numero_reference VARCHAR(50),
|
||
membre_id UUID REFERENCES membres(id),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
type_cotisation VARCHAR(50),
|
||
periode VARCHAR(50),
|
||
montant_du DECIMAL(15,2),
|
||
montant_paye DECIMAL(15,2) DEFAULT 0,
|
||
statut VARCHAR(30) DEFAULT 'EN_ATTENTE',
|
||
date_echeance DATE,
|
||
date_paiement TIMESTAMP,
|
||
methode_paiement VARCHAR(50),
|
||
reference_paiement VARCHAR(100),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS paiements (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
reference VARCHAR(100),
|
||
montant DECIMAL(15,2) NOT NULL,
|
||
devise VARCHAR(10) DEFAULT 'XOF',
|
||
methode_paiement VARCHAR(50),
|
||
statut VARCHAR(30) DEFAULT 'EN_ATTENTE',
|
||
type_paiement VARCHAR(50),
|
||
description TEXT,
|
||
membre_id UUID REFERENCES membres(id),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_paiement TIMESTAMP,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS paiements_adhesions (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
adhesion_id UUID REFERENCES adhesions(id),
|
||
paiement_id UUID REFERENCES paiements(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS paiements_cotisations (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
cotisation_id UUID REFERENCES cotisations(id),
|
||
paiement_id UUID REFERENCES paiements(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS paiements_evenements (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
evenement_id UUID,
|
||
paiement_id UUID REFERENCES paiements(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS paiements_aides (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
demande_aide_id UUID,
|
||
paiement_id UUID REFERENCES paiements(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 4. TABLES COMPTABILITÉ
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS comptes_comptables (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
numero_compte VARCHAR(20) NOT NULL,
|
||
libelle VARCHAR(255) NOT NULL,
|
||
type_compte VARCHAR(50),
|
||
solde DECIMAL(15,2) DEFAULT 0,
|
||
description TEXT,
|
||
compte_parent_id UUID,
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS journaux_comptables (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
code VARCHAR(20) NOT NULL,
|
||
libelle VARCHAR(255) NOT NULL,
|
||
type_journal VARCHAR(50),
|
||
description TEXT,
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS ecritures_comptables (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
numero_piece VARCHAR(50),
|
||
date_ecriture DATE NOT NULL,
|
||
libelle VARCHAR(500),
|
||
montant_total DECIMAL(15,2),
|
||
statut VARCHAR(30) DEFAULT 'BROUILLON',
|
||
journal_id UUID REFERENCES journaux_comptables(id),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS lignes_ecriture (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
ecriture_id UUID NOT NULL REFERENCES ecritures_comptables(id),
|
||
compte_id UUID NOT NULL REFERENCES comptes_comptables(id),
|
||
libelle VARCHAR(500),
|
||
montant_debit DECIMAL(15,2) DEFAULT 0,
|
||
montant_credit DECIMAL(15,2) DEFAULT 0,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 5. TABLES ÉVÉNEMENTS
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS evenements (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
titre VARCHAR(255) NOT NULL,
|
||
description TEXT,
|
||
type_evenement VARCHAR(50),
|
||
statut VARCHAR(30) DEFAULT 'PLANIFIE',
|
||
priorite VARCHAR(20) DEFAULT 'NORMALE',
|
||
date_debut TIMESTAMP,
|
||
date_fin TIMESTAMP,
|
||
lieu VARCHAR(500),
|
||
capacite_max INTEGER,
|
||
prix DECIMAL(15,2) DEFAULT 0,
|
||
devise VARCHAR(10) DEFAULT 'XOF',
|
||
organisateur_id UUID REFERENCES membres(id),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS inscriptions_evenement (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
evenement_id UUID NOT NULL REFERENCES evenements(id),
|
||
membre_id UUID NOT NULL REFERENCES membres(id),
|
||
statut VARCHAR(30) DEFAULT 'EN_ATTENTE',
|
||
date_inscription TIMESTAMP DEFAULT NOW(),
|
||
commentaire TEXT,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
UNIQUE(evenement_id, membre_id)
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 6. TABLES SOLIDARITÉ
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS demandes_aide (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
numero_demande VARCHAR(50),
|
||
type_aide VARCHAR(50),
|
||
priorite VARCHAR(20) DEFAULT 'NORMALE',
|
||
statut VARCHAR(50) DEFAULT 'BROUILLON',
|
||
titre VARCHAR(255),
|
||
description TEXT,
|
||
montant_demande DECIMAL(15,2),
|
||
montant_approuve DECIMAL(15,2),
|
||
devise VARCHAR(10) DEFAULT 'XOF',
|
||
justification TEXT,
|
||
membre_id UUID REFERENCES membres(id),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 7. TABLES DOCUMENTS
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS documents (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
nom VARCHAR(255) NOT NULL,
|
||
description TEXT,
|
||
type_document VARCHAR(50),
|
||
chemin_fichier VARCHAR(1000),
|
||
taille_fichier BIGINT,
|
||
type_mime VARCHAR(100),
|
||
membre_id UUID REFERENCES membres(id),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS pieces_jointes (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
nom_fichier VARCHAR(255) NOT NULL,
|
||
chemin_fichier VARCHAR(1000),
|
||
type_mime VARCHAR(100),
|
||
taille BIGINT,
|
||
entite_type VARCHAR(100),
|
||
entite_id UUID,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 8. TABLES NOTIFICATIONS
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS templates_notifications (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
code VARCHAR(100) NOT NULL UNIQUE,
|
||
sujet VARCHAR(500),
|
||
corps_texte TEXT,
|
||
corps_html TEXT,
|
||
variables_disponibles TEXT,
|
||
canaux_supportes VARCHAR(500),
|
||
langue VARCHAR(10) DEFAULT 'fr',
|
||
description TEXT,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS notifications (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
type_notification VARCHAR(30) NOT NULL,
|
||
priorite VARCHAR(20) DEFAULT 'NORMALE',
|
||
statut VARCHAR(30) DEFAULT 'EN_ATTENTE',
|
||
sujet VARCHAR(500),
|
||
corps TEXT,
|
||
date_envoi_prevue TIMESTAMP,
|
||
date_envoi TIMESTAMP,
|
||
date_lecture TIMESTAMP,
|
||
nombre_tentatives INTEGER DEFAULT 0,
|
||
message_erreur VARCHAR(1000),
|
||
donnees_additionnelles TEXT,
|
||
membre_id UUID REFERENCES membres(id),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
template_id UUID REFERENCES templates_notifications(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 9. TABLES ADRESSES
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS adresses (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
type_adresse VARCHAR(30),
|
||
rue VARCHAR(500),
|
||
complement VARCHAR(500),
|
||
code_postal VARCHAR(20),
|
||
ville VARCHAR(100),
|
||
region VARCHAR(100),
|
||
pays VARCHAR(100) DEFAULT 'Côte d''Ivoire',
|
||
latitude DOUBLE PRECISION,
|
||
longitude DOUBLE PRECISION,
|
||
principale BOOLEAN DEFAULT FALSE,
|
||
membre_id UUID REFERENCES membres(id),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
-- Colonnes attendues par l'entité Adresse (alignement schéma)
|
||
ALTER TABLE adresses ADD COLUMN IF NOT EXISTS adresse VARCHAR(500);
|
||
ALTER TABLE adresses ADD COLUMN IF NOT EXISTS complement_adresse VARCHAR(200);
|
||
ALTER TABLE adresses ADD COLUMN IF NOT EXISTS libelle VARCHAR(100);
|
||
ALTER TABLE adresses ADD COLUMN IF NOT EXISTS notes VARCHAR(500);
|
||
ALTER TABLE adresses ADD COLUMN IF NOT EXISTS evenement_id UUID REFERENCES evenements(id) ON DELETE SET NULL;
|
||
CREATE INDEX IF NOT EXISTS idx_adresse_evenement ON adresses(evenement_id);
|
||
-- Types latitude/longitude : entité attend NUMERIC(9,6)
|
||
DO $$ BEGIN
|
||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'adresses' AND column_name = 'latitude' AND data_type = 'double precision') THEN
|
||
ALTER TABLE adresses ALTER COLUMN latitude TYPE NUMERIC(9,6) USING latitude::numeric(9,6);
|
||
END IF;
|
||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'adresses' AND column_name = 'longitude' AND data_type = 'double precision') THEN
|
||
ALTER TABLE adresses ALTER COLUMN longitude TYPE NUMERIC(9,6) USING longitude::numeric(9,6);
|
||
END IF;
|
||
END $$;
|
||
|
||
-- ============================================================================
|
||
-- 10. TABLES AUDIT
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS audit_logs (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
action VARCHAR(100) NOT NULL,
|
||
entite_type VARCHAR(100),
|
||
entite_id VARCHAR(100),
|
||
utilisateur VARCHAR(255),
|
||
details TEXT,
|
||
adresse_ip VARCHAR(50),
|
||
date_heure TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
-- Colonnes attendues par l'entité AuditLog
|
||
ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS description VARCHAR(500);
|
||
ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS donnees_avant TEXT;
|
||
ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS donnees_apres TEXT;
|
||
ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS ip_address VARCHAR(45);
|
||
ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS module VARCHAR(50);
|
||
ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS role VARCHAR(50);
|
||
ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS session_id VARCHAR(255);
|
||
ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS severite VARCHAR(20) NOT NULL DEFAULT 'INFO';
|
||
ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS type_action VARCHAR(50) DEFAULT 'AUTRE';
|
||
ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS user_agent VARCHAR(500);
|
||
ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS organisation_id UUID REFERENCES organisations(id) ON DELETE SET NULL;
|
||
ALTER TABLE audit_logs ADD COLUMN IF NOT EXISTS portee VARCHAR(15) NOT NULL DEFAULT 'PLATEFORME';
|
||
ALTER TABLE audit_logs ALTER COLUMN entite_id TYPE VARCHAR(255) USING entite_id::varchar(255);
|
||
UPDATE audit_logs SET type_action = COALESCE(action, 'AUTRE') WHERE type_action IS NULL OR type_action = 'AUTRE';
|
||
ALTER TABLE audit_logs ALTER COLUMN type_action SET DEFAULT 'AUTRE';
|
||
DO $$ BEGIN IF (SELECT COUNT(*) FROM audit_logs WHERE type_action IS NULL) = 0 THEN ALTER TABLE audit_logs ALTER COLUMN type_action SET NOT NULL; END IF; END $$;
|
||
CREATE INDEX IF NOT EXISTS idx_audit_module ON audit_logs(module);
|
||
CREATE INDEX IF NOT EXISTS idx_audit_type_action ON audit_logs(type_action);
|
||
CREATE INDEX IF NOT EXISTS idx_audit_severite ON audit_logs(severite);
|
||
|
||
-- ============================================================================
|
||
-- 11. TABLES WAVE MONEY
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS comptes_wave (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
numero_telephone VARCHAR(30) NOT NULL,
|
||
nom_titulaire VARCHAR(255),
|
||
statut VARCHAR(30) DEFAULT 'ACTIF',
|
||
solde DECIMAL(15,2) DEFAULT 0,
|
||
devise VARCHAR(10) DEFAULT 'XOF',
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS configurations_wave (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
cle_api VARCHAR(500),
|
||
secret_api VARCHAR(500),
|
||
environnement VARCHAR(30) DEFAULT 'sandbox',
|
||
url_webhook VARCHAR(500),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS transactions_wave (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
reference_wave VARCHAR(100),
|
||
reference_interne VARCHAR(100),
|
||
type_transaction VARCHAR(50),
|
||
montant DECIMAL(15,2) NOT NULL,
|
||
devise VARCHAR(10) DEFAULT 'XOF',
|
||
statut VARCHAR(30) DEFAULT 'EN_ATTENTE',
|
||
numero_expediteur VARCHAR(30),
|
||
numero_destinataire VARCHAR(30),
|
||
description TEXT,
|
||
erreur TEXT,
|
||
compte_wave_id UUID REFERENCES comptes_wave(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS webhooks_wave (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
type_evenement VARCHAR(100),
|
||
statut VARCHAR(30) DEFAULT 'RECU',
|
||
payload TEXT,
|
||
signature VARCHAR(500),
|
||
traite BOOLEAN DEFAULT FALSE,
|
||
erreur TEXT,
|
||
transaction_id UUID REFERENCES transactions_wave(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 12. TABLES SUPPORT (tickets, suggestions, favoris, config - déjà en V1.4)
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS tickets (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
numero_ticket VARCHAR(50),
|
||
sujet VARCHAR(255) NOT NULL,
|
||
description TEXT,
|
||
categorie VARCHAR(50),
|
||
priorite VARCHAR(20) DEFAULT 'NORMALE',
|
||
statut VARCHAR(30) DEFAULT 'OUVERT',
|
||
membre_id UUID REFERENCES membres(id),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
assigne_a VARCHAR(255),
|
||
date_resolution TIMESTAMP,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS suggestions (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
titre VARCHAR(255) NOT NULL,
|
||
description TEXT,
|
||
categorie VARCHAR(50),
|
||
statut VARCHAR(30) DEFAULT 'NOUVELLE',
|
||
votes_pour INTEGER DEFAULT 0,
|
||
votes_contre INTEGER DEFAULT 0,
|
||
membre_id UUID REFERENCES membres(id),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS suggestion_votes (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
suggestion_id UUID NOT NULL REFERENCES suggestions(id),
|
||
membre_id UUID NOT NULL REFERENCES membres(id),
|
||
type_vote VARCHAR(20) NOT NULL,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
UNIQUE(suggestion_id, membre_id)
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS favoris (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
type_entite VARCHAR(100) NOT NULL,
|
||
entite_id UUID NOT NULL,
|
||
membre_id UUID NOT NULL REFERENCES membres(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS configurations (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
cle VARCHAR(255) NOT NULL UNIQUE,
|
||
valeur TEXT,
|
||
description TEXT,
|
||
categorie VARCHAR(100),
|
||
organisation_id UUID REFERENCES organisations(id),
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 13. TABLE TYPES ORGANISATION
|
||
-- ============================================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS uf_type_organisation (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
code VARCHAR(50) NOT NULL UNIQUE,
|
||
libelle VARCHAR(255) NOT NULL,
|
||
description TEXT,
|
||
icone VARCHAR(100),
|
||
couleur VARCHAR(20),
|
||
ordre INTEGER DEFAULT 0,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT DEFAULT 0,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 14. INDEX POUR PERFORMANCES
|
||
-- ============================================================================
|
||
CREATE INDEX IF NOT EXISTS idx_membres_email ON membres(email);
|
||
CREATE INDEX IF NOT EXISTS idx_membres_numero ON membres(numero_membre);
|
||
CREATE INDEX IF NOT EXISTS idx_membres_organisation ON membres(organisation_id);
|
||
CREATE INDEX IF NOT EXISTS idx_membres_keycloak ON membres(keycloak_user_id);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_adhesions_membre ON adhesions(membre_id);
|
||
CREATE INDEX IF NOT EXISTS idx_adhesions_organisation ON adhesions(organisation_id);
|
||
CREATE INDEX IF NOT EXISTS idx_adhesions_statut ON adhesions(statut);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_cotisations_membre ON cotisations(membre_id);
|
||
CREATE INDEX IF NOT EXISTS idx_cotisations_statut ON cotisations(statut);
|
||
CREATE INDEX IF NOT EXISTS idx_cotisations_echeance ON cotisations(date_echeance);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_evenements_statut ON evenements(statut);
|
||
CREATE INDEX IF NOT EXISTS idx_evenements_organisation ON evenements(organisation_id);
|
||
CREATE INDEX IF NOT EXISTS idx_evenements_date_debut ON evenements(date_debut);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_notification_membre ON notifications(membre_id);
|
||
CREATE INDEX IF NOT EXISTS idx_notification_statut ON notifications(statut);
|
||
CREATE INDEX IF NOT EXISTS idx_notification_type ON notifications(type_notification);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_audit_date_heure ON audit_logs(date_heure);
|
||
CREATE INDEX IF NOT EXISTS idx_audit_action ON audit_logs(action);
|
||
CREATE INDEX IF NOT EXISTS idx_audit_utilisateur ON audit_logs(utilisateur);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_paiements_membre ON paiements(membre_id);
|
||
CREATE INDEX IF NOT EXISTS idx_paiements_statut ON paiements(statut);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_demandes_aide_demandeur ON demandes_aide(demandeur_id);
|
||
CREATE INDEX IF NOT EXISTS idx_demandes_aide_statut ON demandes_aide(statut);
|
||
|
||
|
||
-- ========== V2.0__Refactoring_Utilisateurs.sql ==========
|
||
-- ============================================================
|
||
-- V2.0 — Refactoring: membres → utilisateurs
|
||
-- Sépare l'identité globale (utilisateurs) du lien organisationnel
|
||
-- Auteur: UnionFlow Team | BCEAO/OHADA compliant
|
||
-- ============================================================
|
||
|
||
-- Renommer la table membres → utilisateurs
|
||
ALTER TABLE membres RENAME TO utilisateurs;
|
||
|
||
-- Supprimer l'ancien lien unique membre↔organisation (maintenant dans membres_organisations)
|
||
ALTER TABLE utilisateurs DROP COLUMN IF EXISTS organisation_id;
|
||
ALTER TABLE utilisateurs DROP COLUMN IF EXISTS date_adhesion;
|
||
ALTER TABLE utilisateurs DROP COLUMN IF EXISTS mot_de_passe;
|
||
ALTER TABLE utilisateurs DROP COLUMN IF EXISTS roles;
|
||
|
||
-- Ajouter les nouveaux champs identité globale
|
||
ALTER TABLE utilisateurs ADD COLUMN IF NOT EXISTS keycloak_id UUID UNIQUE;
|
||
ALTER TABLE utilisateurs ADD COLUMN IF NOT EXISTS photo_url VARCHAR(500);
|
||
ALTER TABLE utilisateurs ADD COLUMN IF NOT EXISTS statut_compte VARCHAR(30) NOT NULL DEFAULT 'ACTIF';
|
||
ALTER TABLE utilisateurs ADD COLUMN IF NOT EXISTS telephone_wave VARCHAR(13);
|
||
|
||
-- Mettre à jour la contrainte de statut compte
|
||
ALTER TABLE utilisateurs
|
||
ADD CONSTRAINT chk_utilisateur_statut_compte
|
||
CHECK (statut_compte IN ('ACTIF', 'SUSPENDU', 'DESACTIVE'));
|
||
|
||
-- Mettre à jour les index
|
||
DROP INDEX IF EXISTS idx_membre_organisation;
|
||
DROP INDEX IF EXISTS idx_membre_email;
|
||
DROP INDEX IF EXISTS idx_membre_numero;
|
||
DROP INDEX IF EXISTS idx_membre_actif;
|
||
|
||
CREATE UNIQUE INDEX IF NOT EXISTS idx_utilisateur_email ON utilisateurs(email);
|
||
CREATE UNIQUE INDEX IF NOT EXISTS idx_utilisateur_numero ON utilisateurs(numero_membre);
|
||
CREATE INDEX IF NOT EXISTS idx_utilisateur_actif ON utilisateurs(actif);
|
||
CREATE UNIQUE INDEX IF NOT EXISTS idx_utilisateur_keycloak ON utilisateurs(keycloak_id);
|
||
CREATE INDEX IF NOT EXISTS idx_utilisateur_statut_compte ON utilisateurs(statut_compte);
|
||
|
||
-- ============================================================
|
||
-- Table membres_organisations : lien utilisateur ↔ organisation
|
||
-- ============================================================
|
||
CREATE TABLE IF NOT EXISTS membres_organisations (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
||
utilisateur_id UUID NOT NULL,
|
||
organisation_id UUID NOT NULL,
|
||
unite_id UUID, -- agence/bureau d'affectation (null = siège)
|
||
|
||
statut_membre VARCHAR(30) NOT NULL DEFAULT 'EN_ATTENTE_VALIDATION',
|
||
date_adhesion DATE,
|
||
date_changement_statut DATE,
|
||
motif_statut VARCHAR(500),
|
||
approuve_par_id UUID,
|
||
|
||
-- Métadonnées 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_mo_utilisateur FOREIGN KEY (utilisateur_id) REFERENCES utilisateurs(id) ON DELETE CASCADE,
|
||
CONSTRAINT fk_mo_organisation FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE CASCADE,
|
||
CONSTRAINT fk_mo_unite FOREIGN KEY (unite_id) REFERENCES organisations(id) ON DELETE SET NULL,
|
||
CONSTRAINT fk_mo_approuve_par FOREIGN KEY (approuve_par_id) REFERENCES utilisateurs(id) ON DELETE SET NULL,
|
||
CONSTRAINT uk_mo_utilisateur_organisation UNIQUE (utilisateur_id, organisation_id),
|
||
CONSTRAINT chk_mo_statut CHECK (statut_membre IN (
|
||
'EN_ATTENTE_VALIDATION','ACTIF','INACTIF',
|
||
'SUSPENDU','DEMISSIONNAIRE','RADIE','HONORAIRE','DECEDE'
|
||
))
|
||
);
|
||
|
||
CREATE INDEX idx_mo_utilisateur ON membres_organisations(utilisateur_id);
|
||
CREATE INDEX idx_mo_organisation ON membres_organisations(organisation_id);
|
||
CREATE INDEX idx_mo_statut ON membres_organisations(statut_membre);
|
||
CREATE INDEX idx_mo_unite ON membres_organisations(unite_id);
|
||
|
||
-- Table agrements_professionnels (registre) — entité AgrementProfessionnel
|
||
CREATE TABLE IF NOT EXISTS agrements_professionnels (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
membre_id UUID NOT NULL REFERENCES utilisateurs(id) ON DELETE CASCADE,
|
||
organisation_id UUID NOT NULL REFERENCES organisations(id) ON DELETE CASCADE,
|
||
secteur_ordre VARCHAR(150),
|
||
numero_licence VARCHAR(100),
|
||
categorie_classement VARCHAR(100),
|
||
date_delivrance DATE,
|
||
date_expiration DATE,
|
||
statut VARCHAR(50) NOT NULL DEFAULT 'PROVISOIRE',
|
||
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,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
CONSTRAINT chk_agrement_statut CHECK (statut IN ('PROVISOIRE','VALIDE','SUSPENDU','RETRETIRE'))
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_agrement_membre ON agrements_professionnels(membre_id);
|
||
CREATE INDEX IF NOT EXISTS idx_agrement_orga ON agrements_professionnels(organisation_id);
|
||
|
||
-- Mettre à jour les FK des tables existantes qui pointaient sur membres(id)
|
||
ALTER TABLE cotisations
|
||
DROP CONSTRAINT IF EXISTS fk_cotisation_membre,
|
||
ADD CONSTRAINT fk_cotisation_membre FOREIGN KEY (membre_id) REFERENCES utilisateurs(id);
|
||
|
||
ALTER TABLE inscriptions_evenement
|
||
DROP CONSTRAINT IF EXISTS fk_inscription_membre,
|
||
ADD CONSTRAINT fk_inscription_membre FOREIGN KEY (membre_id) REFERENCES utilisateurs(id);
|
||
|
||
ALTER TABLE demandes_aide
|
||
DROP CONSTRAINT IF EXISTS fk_demande_demandeur,
|
||
DROP CONSTRAINT IF EXISTS fk_demande_evaluateur,
|
||
ADD CONSTRAINT fk_demande_demandeur FOREIGN KEY (demandeur_id) REFERENCES utilisateurs(id),
|
||
ADD CONSTRAINT fk_demande_evaluateur FOREIGN KEY (evaluateur_id) REFERENCES utilisateurs(id) ON DELETE SET NULL;
|
||
|
||
COMMENT ON TABLE utilisateurs IS 'Identité globale unique de chaque utilisateur UnionFlow (1 compte = 1 profil)';
|
||
COMMENT ON TABLE membres_organisations IS 'Lien utilisateur ↔ organisation avec statut de membership';
|
||
COMMENT ON COLUMN membres_organisations.unite_id IS 'Agence/bureau d''affectation au sein de la hiérarchie. NULL = siège';
|
||
|
||
|
||
-- ========== V2.1__Organisations_Hierarchy.sql ==========
|
||
-- ============================================================
|
||
-- V2.1 — Hiérarchie organisations + corrections
|
||
-- Auteur: UnionFlow Team | BCEAO/OHADA compliant
|
||
-- ============================================================
|
||
|
||
-- Ajouter la FK propre pour la hiérarchie (remplace le UUID nu)
|
||
ALTER TABLE organisations
|
||
DROP CONSTRAINT IF EXISTS fk_organisation_parente;
|
||
|
||
ALTER TABLE organisations
|
||
ADD CONSTRAINT fk_organisation_parente
|
||
FOREIGN KEY (organisation_parente_id) REFERENCES organisations(id) ON DELETE SET NULL;
|
||
|
||
-- Nouveaux champs hiérarchie et modules
|
||
ALTER TABLE organisations
|
||
ADD COLUMN IF NOT EXISTS est_organisation_racine BOOLEAN NOT NULL DEFAULT TRUE,
|
||
ADD COLUMN IF NOT EXISTS chemin_hierarchique VARCHAR(2000),
|
||
ADD COLUMN IF NOT EXISTS type_organisation_code VARCHAR(50);
|
||
|
||
-- Élargir la contrainte de type_organisation pour couvrir tous les métiers
|
||
ALTER TABLE organisations DROP CONSTRAINT IF EXISTS chk_organisation_type;
|
||
ALTER TABLE organisations
|
||
ADD CONSTRAINT chk_organisation_type CHECK (type_organisation IN (
|
||
'ASSOCIATION','MUTUELLE_EPARGNE_CREDIT','MUTUELLE_SANTE',
|
||
'TONTINE','ONG','COOPERATIVE_AGRICOLE','ASSOCIATION_PROFESSIONNELLE',
|
||
'ASSOCIATION_COMMUNAUTAIRE','ORGANISATION_RELIGIEUSE',
|
||
'FEDERATION','SYNDICAT','LIONS_CLUB','ROTARY_CLUB','AUTRE'
|
||
));
|
||
|
||
-- Règle : organisation sans parent = racine
|
||
UPDATE organisations
|
||
SET est_organisation_racine = TRUE
|
||
WHERE organisation_parente_id IS NULL;
|
||
|
||
UPDATE organisations
|
||
SET est_organisation_racine = FALSE
|
||
WHERE organisation_parente_id IS NOT NULL;
|
||
|
||
-- Index pour les requêtes hiérarchiques
|
||
CREATE INDEX IF NOT EXISTS idx_org_racine ON organisations(est_organisation_racine);
|
||
CREATE INDEX IF NOT EXISTS idx_org_chemin ON organisations(chemin_hierarchique);
|
||
|
||
COMMENT ON COLUMN organisations.est_organisation_racine IS 'TRUE si c''est l''organisation mère (souscrit au forfait pour toute la hiérarchie)';
|
||
COMMENT ON COLUMN organisations.chemin_hierarchique IS 'Chemin UUID ex: /uuid-racine/uuid-inter/uuid-feuille — requêtes récursives optimisées';
|
||
|
||
|
||
-- ========== V2.2__SaaS_Souscriptions.sql ==========
|
||
-- ============================================================
|
||
-- V2.2 — SaaS : formules_abonnement + souscriptions_organisation
|
||
-- Auteur: UnionFlow Team | BCEAO/OHADA compliant
|
||
-- ============================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS formules_abonnement (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
||
code VARCHAR(20) UNIQUE NOT NULL, -- STARTER, STANDARD, PREMIUM, CRYSTAL
|
||
libelle VARCHAR(100) NOT NULL,
|
||
description TEXT,
|
||
max_membres INTEGER, -- NULL = illimité (Crystal+)
|
||
max_stockage_mo INTEGER NOT NULL DEFAULT 1024, -- 1 Go par défaut
|
||
prix_mensuel DECIMAL(10,2) NOT NULL CHECK (prix_mensuel >= 0),
|
||
prix_annuel DECIMAL(10,2) NOT NULL CHECK (prix_annuel >= 0),
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
ordre_affichage INTEGER DEFAULT 0,
|
||
|
||
-- Métadonnées BaseEntity
|
||
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 chk_formule_code CHECK (code IN ('STARTER','STANDARD','PREMIUM','CRYSTAL'))
|
||
);
|
||
|
||
-- Données initiales des forfaits (XOF, 1er Janvier 2026)
|
||
INSERT INTO formules_abonnement (id, code, libelle, description, max_membres, max_stockage_mo, prix_mensuel, prix_annuel, actif, ordre_affichage)
|
||
VALUES
|
||
(gen_random_uuid(), 'STARTER', 'Formule Starter', 'Idéal pour démarrer — jusqu''à 50 membres', 50, 1024, 5000.00, 50000.00, true, 1),
|
||
(gen_random_uuid(), 'STANDARD', 'Formule Standard', 'Pour les organisations en croissance', 200, 1024, 7000.00, 70000.00, true, 2),
|
||
(gen_random_uuid(), 'PREMIUM', 'Formule Premium', 'Organisations établies', 500, 1024, 9000.00, 90000.00, true, 3),
|
||
(gen_random_uuid(), 'CRYSTAL', 'Formule Crystal', 'Fédérations et grandes organisations', NULL,1024, 10000.00, 100000.00, true, 4)
|
||
ON CONFLICT (code) DO NOTHING;
|
||
|
||
-- ============================================================
|
||
CREATE TABLE IF NOT EXISTS souscriptions_organisation (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
||
organisation_id UUID UNIQUE NOT NULL,
|
||
formule_id UUID NOT NULL,
|
||
type_periode VARCHAR(10) NOT NULL DEFAULT 'MENSUEL', -- MENSUEL | ANNUEL
|
||
date_debut DATE NOT NULL,
|
||
date_fin DATE NOT NULL,
|
||
quota_max INTEGER, -- snapshot de formule.max_membres
|
||
quota_utilise INTEGER NOT NULL DEFAULT 0,
|
||
statut VARCHAR(30) NOT NULL DEFAULT 'ACTIVE',
|
||
reference_paiement_wave VARCHAR(100),
|
||
wave_session_id VARCHAR(255),
|
||
date_dernier_paiement DATE,
|
||
date_prochain_paiement DATE,
|
||
|
||
-- Métadonnées 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_souscription_org FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE CASCADE,
|
||
CONSTRAINT fk_souscription_formule FOREIGN KEY (formule_id) REFERENCES formules_abonnement(id),
|
||
CONSTRAINT chk_souscription_statut CHECK (statut IN ('ACTIVE','EXPIREE','SUSPENDUE','RESILIEE')),
|
||
CONSTRAINT chk_souscription_periode CHECK (type_periode IN ('MENSUEL','ANNUEL')),
|
||
CONSTRAINT chk_souscription_quota CHECK (quota_utilise >= 0)
|
||
);
|
||
|
||
CREATE INDEX idx_souscription_org ON souscriptions_organisation(organisation_id);
|
||
CREATE INDEX idx_souscription_statut ON souscriptions_organisation(statut);
|
||
CREATE INDEX idx_souscription_fin ON souscriptions_organisation(date_fin);
|
||
|
||
COMMENT ON TABLE formules_abonnement IS 'Catalogue des forfaits SaaS UnionFlow (Starter→Crystal, 5000–10000 XOF/mois)';
|
||
COMMENT ON TABLE souscriptions_organisation IS 'Abonnement actif d''une organisation racine — quota, durée, référence Wave';
|
||
COMMENT ON COLUMN souscriptions_organisation.quota_utilise IS 'Incrémenté automatiquement à chaque adhésion validée. Bloquant si = quota_max.';
|
||
|
||
|
||
-- ========== V2.3__Intentions_Paiement.sql ==========
|
||
-- ============================================================
|
||
-- V2.3 — Hub de paiement Wave : intentions_paiement
|
||
-- Chaque paiement Wave est initié depuis UnionFlow.
|
||
-- Auteur: UnionFlow Team | BCEAO/OHADA compliant
|
||
-- ============================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS intentions_paiement (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
||
utilisateur_id UUID NOT NULL,
|
||
organisation_id UUID, -- NULL pour abonnements UnionFlow SA
|
||
montant_total DECIMAL(14,2) NOT NULL CHECK (montant_total > 0),
|
||
code_devise VARCHAR(3) NOT NULL DEFAULT 'XOF',
|
||
type_objet VARCHAR(30) NOT NULL, -- COTISATION|ADHESION|EVENEMENT|ABONNEMENT_UNIONFLOW
|
||
statut VARCHAR(20) NOT NULL DEFAULT 'INITIEE',
|
||
|
||
-- Wave API
|
||
wave_checkout_session_id VARCHAR(255) UNIQUE,
|
||
wave_launch_url VARCHAR(1000),
|
||
wave_transaction_id VARCHAR(100),
|
||
|
||
-- Traçabilité des objets payés (JSON: [{type,id,montant},...])
|
||
objets_cibles TEXT,
|
||
|
||
date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
date_expiration TIMESTAMP, -- TTL 30 min
|
||
date_completion TIMESTAMP,
|
||
|
||
-- Métadonnées BaseEntity
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT NOT NULL DEFAULT 0,
|
||
|
||
CONSTRAINT fk_intention_utilisateur FOREIGN KEY (utilisateur_id) REFERENCES utilisateurs(id),
|
||
CONSTRAINT fk_intention_organisation FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE SET NULL,
|
||
CONSTRAINT chk_intention_type CHECK (type_objet IN ('COTISATION','ADHESION','EVENEMENT','ABONNEMENT_UNIONFLOW')),
|
||
CONSTRAINT chk_intention_statut CHECK (statut IN ('INITIEE','EN_COURS','COMPLETEE','EXPIREE','ECHOUEE')),
|
||
CONSTRAINT chk_intention_devise CHECK (code_devise ~ '^[A-Z]{3}$')
|
||
);
|
||
|
||
CREATE INDEX idx_intention_utilisateur ON intentions_paiement(utilisateur_id);
|
||
CREATE INDEX idx_intention_statut ON intentions_paiement(statut);
|
||
CREATE INDEX idx_intention_wave_session ON intentions_paiement(wave_checkout_session_id);
|
||
CREATE INDEX idx_intention_expiration ON intentions_paiement(date_expiration);
|
||
|
||
-- Supprimer les champs paiement redondants de cotisations (centralisés dans intentions_paiement)
|
||
ALTER TABLE cotisations
|
||
DROP COLUMN IF EXISTS methode_paiement,
|
||
DROP COLUMN IF EXISTS reference_paiement;
|
||
|
||
-- Ajouter le lien cotisation → intention de paiement
|
||
ALTER TABLE cotisations
|
||
ADD COLUMN IF NOT EXISTS intention_paiement_id UUID,
|
||
ADD CONSTRAINT fk_cotisation_intention
|
||
FOREIGN KEY (intention_paiement_id) REFERENCES intentions_paiement(id) ON DELETE SET NULL;
|
||
|
||
COMMENT ON TABLE intentions_paiement IS 'Hub centralisé Wave : chaque paiement est initié depuis UnionFlow avant appel API Wave';
|
||
COMMENT ON COLUMN intentions_paiement.objets_cibles IS 'JSON: liste des objets couverts par ce paiement — ex: 3 cotisations mensuelles';
|
||
COMMENT ON COLUMN intentions_paiement.wave_checkout_session_id IS 'ID de session Wave — clé de réconciliation sur réception webhook';
|
||
|
||
|
||
-- ========== V2.4__Cotisations_Organisation.sql ==========
|
||
-- ============================================================
|
||
-- V2.4 — Cotisations : ajout organisation_id + parametres
|
||
-- Une cotisation est toujours liée à un membre ET à une organisation
|
||
-- Auteur: UnionFlow Team | BCEAO/OHADA compliant
|
||
-- ============================================================
|
||
|
||
-- Ajouter organisation_id sur cotisations
|
||
ALTER TABLE cotisations
|
||
ADD COLUMN IF NOT EXISTS organisation_id UUID;
|
||
|
||
ALTER TABLE cotisations
|
||
ADD CONSTRAINT fk_cotisation_organisation
|
||
FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE CASCADE;
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_cotisation_organisation ON cotisations(organisation_id);
|
||
|
||
-- Mettre à jour les types de cotisation
|
||
ALTER TABLE cotisations DROP CONSTRAINT IF EXISTS chk_cotisation_type;
|
||
ALTER TABLE cotisations
|
||
ADD CONSTRAINT chk_cotisation_type CHECK (type_cotisation IN (
|
||
'ANNUELLE','MENSUELLE','EVENEMENTIELLE','SOLIDARITE','EXCEPTIONNELLE','AUTRE'
|
||
));
|
||
|
||
-- ============================================================
|
||
-- Paramètres de cotisation par organisation (montants fixés par l'org)
|
||
-- ============================================================
|
||
CREATE TABLE IF NOT EXISTS parametres_cotisation_organisation (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
||
organisation_id UUID UNIQUE NOT NULL,
|
||
montant_cotisation_mensuelle DECIMAL(12,2) DEFAULT 0 CHECK (montant_cotisation_mensuelle >= 0),
|
||
montant_cotisation_annuelle DECIMAL(12,2) DEFAULT 0 CHECK (montant_cotisation_annuelle >= 0),
|
||
devise VARCHAR(3) NOT NULL DEFAULT 'XOF',
|
||
date_debut_calcul_ajour DATE, -- configurable: depuis quand calculer les impayés
|
||
delai_retard_avant_inactif_jours INTEGER NOT NULL DEFAULT 30,
|
||
cotisation_obligatoire BOOLEAN NOT NULL DEFAULT TRUE,
|
||
|
||
-- Métadonnées 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_param_cotisation_org FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE CASCADE
|
||
);
|
||
|
||
COMMENT ON TABLE parametres_cotisation_organisation IS 'Paramètres de cotisation configurés par le manager de chaque organisation';
|
||
COMMENT ON COLUMN parametres_cotisation_organisation.date_debut_calcul_ajour IS 'Date de référence pour le calcul membre «à jour». Configurable par le manager.';
|
||
COMMENT ON COLUMN parametres_cotisation_organisation.delai_retard_avant_inactif_jours IS 'Jours de retard après lesquels un membre passe INACTIF automatiquement';
|
||
|
||
|
||
-- ========== V2.5__Workflow_Solidarite.sql ==========
|
||
-- ============================================================
|
||
-- V2.5 — Workflow solidarité configurable (max 3 étapes)
|
||
-- + demandes_adhesion (remplace adhesions)
|
||
-- Auteur: UnionFlow Team | BCEAO/OHADA compliant
|
||
-- ============================================================
|
||
|
||
-- ============================================================
|
||
-- Workflow de validation configurable par organisation
|
||
-- ============================================================
|
||
CREATE TABLE IF NOT EXISTS workflow_validation_config (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
||
organisation_id UUID NOT NULL,
|
||
type_workflow VARCHAR(30) NOT NULL DEFAULT 'DEMANDE_AIDE',
|
||
etape_numero INTEGER NOT NULL CHECK (etape_numero BETWEEN 1 AND 3),
|
||
role_requis_id UUID, -- rôle nécessaire pour valider cette étape
|
||
libelle_etape VARCHAR(200) NOT NULL,
|
||
delai_max_heures INTEGER DEFAULT 72,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
|
||
-- Métadonnées BaseEntity
|
||
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_wf_organisation FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE CASCADE,
|
||
CONSTRAINT fk_wf_role FOREIGN KEY (role_requis_id) REFERENCES roles(id) ON DELETE SET NULL,
|
||
CONSTRAINT uk_wf_org_type_etape UNIQUE (organisation_id, type_workflow, etape_numero),
|
||
CONSTRAINT chk_wf_type CHECK (type_workflow IN ('DEMANDE_AIDE','ADHESION','AUTRE'))
|
||
);
|
||
|
||
CREATE INDEX idx_wf_organisation ON workflow_validation_config(organisation_id);
|
||
CREATE INDEX idx_wf_type ON workflow_validation_config(type_workflow);
|
||
|
||
-- ============================================================
|
||
-- Historique des validations d'une demande d'aide
|
||
-- ============================================================
|
||
CREATE TABLE IF NOT EXISTS validation_etapes_demande (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
||
demande_aide_id UUID NOT NULL,
|
||
etape_numero INTEGER NOT NULL CHECK (etape_numero BETWEEN 1 AND 3),
|
||
valideur_id UUID,
|
||
statut VARCHAR(20) NOT NULL DEFAULT 'EN_ATTENTE',
|
||
date_validation TIMESTAMP,
|
||
commentaire VARCHAR(1000),
|
||
delegue_par_id UUID, -- si désactivation du véto par supérieur
|
||
trace_delegation TEXT, -- motif + traçabilité BCEAO/OHADA
|
||
|
||
-- Métadonnées 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_ved_demande FOREIGN KEY (demande_aide_id) REFERENCES demandes_aide(id) ON DELETE CASCADE,
|
||
CONSTRAINT fk_ved_valideur FOREIGN KEY (valideur_id) REFERENCES utilisateurs(id) ON DELETE SET NULL,
|
||
CONSTRAINT fk_ved_delegue_par FOREIGN KEY (delegue_par_id) REFERENCES utilisateurs(id) ON DELETE SET NULL,
|
||
CONSTRAINT chk_ved_statut CHECK (statut IN ('EN_ATTENTE','APPROUVEE','REJETEE','DELEGUEE','EXPIREE'))
|
||
);
|
||
|
||
CREATE INDEX idx_ved_demande ON validation_etapes_demande(demande_aide_id);
|
||
CREATE INDEX idx_ved_valideur ON validation_etapes_demande(valideur_id);
|
||
CREATE INDEX idx_ved_statut ON validation_etapes_demande(statut);
|
||
|
||
-- ============================================================
|
||
-- demandes_adhesion (remplace adhesions avec modèle enrichi)
|
||
-- ============================================================
|
||
DROP TABLE IF EXISTS adhesions CASCADE;
|
||
|
||
CREATE TABLE IF NOT EXISTS demandes_adhesion (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
||
numero_reference VARCHAR(50) UNIQUE NOT NULL,
|
||
utilisateur_id UUID NOT NULL,
|
||
organisation_id UUID NOT NULL,
|
||
statut VARCHAR(20) NOT NULL DEFAULT 'EN_ATTENTE',
|
||
frais_adhesion DECIMAL(12,2) NOT NULL DEFAULT 0 CHECK (frais_adhesion >= 0),
|
||
montant_paye DECIMAL(12,2) NOT NULL DEFAULT 0,
|
||
code_devise VARCHAR(3) NOT NULL DEFAULT 'XOF',
|
||
intention_paiement_id UUID,
|
||
date_demande TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
date_traitement TIMESTAMP,
|
||
traite_par_id UUID,
|
||
motif_rejet VARCHAR(1000),
|
||
observations VARCHAR(1000),
|
||
|
||
-- Métadonnées 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_da_utilisateur FOREIGN KEY (utilisateur_id) REFERENCES utilisateurs(id) ON DELETE CASCADE,
|
||
CONSTRAINT fk_da_organisation FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE CASCADE,
|
||
CONSTRAINT fk_da_intention FOREIGN KEY (intention_paiement_id) REFERENCES intentions_paiement(id) ON DELETE SET NULL,
|
||
CONSTRAINT fk_da_traite_par FOREIGN KEY (traite_par_id) REFERENCES utilisateurs(id) ON DELETE SET NULL,
|
||
CONSTRAINT chk_da_statut CHECK (statut IN ('EN_ATTENTE','APPROUVEE','REJETEE','ANNULEE'))
|
||
);
|
||
|
||
CREATE INDEX idx_da_utilisateur ON demandes_adhesion(utilisateur_id);
|
||
CREATE INDEX idx_da_organisation ON demandes_adhesion(organisation_id);
|
||
CREATE INDEX idx_da_statut ON demandes_adhesion(statut);
|
||
CREATE INDEX idx_da_date ON demandes_adhesion(date_demande);
|
||
|
||
COMMENT ON TABLE workflow_validation_config IS 'Configuration du workflow de validation par organisation (max 3 étapes)';
|
||
COMMENT ON TABLE validation_etapes_demande IS 'Historique des validations — tracé BCEAO/OHADA — délégation de véto incluse';
|
||
COMMENT ON TABLE demandes_adhesion IS 'Demande d''adhésion d''un utilisateur à une organisation avec paiement Wave intégré';
|
||
|
||
|
||
-- ========== V2.6__Modules_Organisation.sql ==========
|
||
-- ============================================================
|
||
-- V2.6 — Système de modules activables par type d'organisation
|
||
-- Auteur: UnionFlow Team | BCEAO/OHADA compliant
|
||
-- ============================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS modules_disponibles (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
||
code VARCHAR(50) UNIQUE NOT NULL,
|
||
libelle VARCHAR(150) NOT NULL,
|
||
description TEXT,
|
||
types_org_compatibles TEXT, -- JSON array: ["MUTUELLE_SANTE","ONG",...]
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
ordre_affichage INTEGER DEFAULT 0,
|
||
|
||
-- Métadonnées BaseEntity
|
||
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
|
||
);
|
||
|
||
-- Catalogue initial des modules métier
|
||
INSERT INTO modules_disponibles (id, code, libelle, description, types_org_compatibles, actif, ordre_affichage)
|
||
VALUES
|
||
(gen_random_uuid(), 'COTISATIONS', 'Gestion des cotisations', 'Suivi cotisations, relances, statistiques', '["ALL"]', true, 1),
|
||
(gen_random_uuid(), 'EVENEMENTS', 'Gestion des événements', 'Création, inscriptions, présences, paiements', '["ALL"]', true, 2),
|
||
(gen_random_uuid(), 'SOLIDARITE', 'Fonds de solidarité', 'Demandes d''aide avec workflow de validation', '["ALL"]', true, 3),
|
||
(gen_random_uuid(), 'COMPTABILITE', 'Comptabilité simplifiée', 'Journal, écritures, comptes — conforme OHADA', '["ALL"]', true, 4),
|
||
(gen_random_uuid(), 'DOCUMENTS', 'Gestion documentaire', 'Upload, versioning, intégrité hash — 1Go max', '["ALL"]', true, 5),
|
||
(gen_random_uuid(), 'NOTIFICATIONS', 'Notifications multi-canal', 'Email, WhatsApp, push mobile', '["ALL"]', true, 6),
|
||
(gen_random_uuid(), 'CREDIT_EPARGNE', 'Épargne & crédit MEC', 'Prêts, échéanciers, impayés, multi-caisses', '["MUTUELLE_EPARGNE_CREDIT"]', true, 10),
|
||
(gen_random_uuid(), 'AYANTS_DROIT', 'Gestion des ayants droit', 'Couverture santé, plafonds, conventions centres de santé', '["MUTUELLE_SANTE"]', true, 11),
|
||
(gen_random_uuid(), 'TONTINE', 'Tontine / épargne rotative', 'Cycles rotatifs, tirage, enchères, pénalités', '["TONTINE"]', true, 12),
|
||
(gen_random_uuid(), 'ONG_PROJETS', 'Projets humanitaires', 'Logframe, budget bailleurs, indicateurs d''impact, rapports', '["ONG"]', true, 13),
|
||
(gen_random_uuid(), 'COOP_AGRICOLE', 'Coopérative agricole', 'Parcelles, rendements, intrants, vente groupée, ristournes', '["COOPERATIVE_AGRICOLE"]', true, 14),
|
||
(gen_random_uuid(), 'VOTE_INTERNE', 'Vote interne électronique', 'Assemblées générales, votes, quorums', '["FEDERATION","ASSOCIATION","SYNDICAT"]', true, 15),
|
||
(gen_random_uuid(), 'COLLECTE_FONDS', 'Collecte de fonds', 'Campagnes de don, suivi, rapports', '["ONG","ORGANISATION_RELIGIEUSE","ASSOCIATION"]', true, 16),
|
||
(gen_random_uuid(), 'REGISTRE_PROFESSIONNEL','Registre officiel membres', 'Agrément, diplômes, sanctions disciplinaires, annuaire certifié', '["ASSOCIATION_PROFESSIONNELLE"]', true, 17),
|
||
(gen_random_uuid(), 'CULTES_RELIGIEUX', 'Gestion cultes & dîmes', 'Dîmes, promesses de don, planification cultes, cellules, offrandes anon.','["ORGANISATION_RELIGIEUSE"]', true, 18),
|
||
(gen_random_uuid(), 'GOUVERNANCE_MULTI', 'Gouvernance multi-niveaux', 'Cotisation par section, reporting consolidé, redistribution subventions', '["FEDERATION"]', true, 19)
|
||
ON CONFLICT (code) DO NOTHING;
|
||
|
||
-- ============================================================
|
||
-- Modules activés pour chaque organisation
|
||
-- ============================================================
|
||
CREATE TABLE IF NOT EXISTS modules_organisation_actifs (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
||
organisation_id UUID NOT NULL,
|
||
module_code VARCHAR(50) NOT NULL,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
parametres TEXT, -- JSON de configuration spécifique
|
||
date_activation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||
|
||
-- Métadonnées BaseEntity
|
||
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_moa_organisation FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE CASCADE,
|
||
CONSTRAINT uk_moa_org_module UNIQUE (organisation_id, module_code)
|
||
);
|
||
|
||
CREATE INDEX idx_moa_organisation ON modules_organisation_actifs(organisation_id);
|
||
CREATE INDEX idx_moa_module ON modules_organisation_actifs(module_code);
|
||
|
||
COMMENT ON TABLE modules_disponibles IS 'Catalogue des modules métier UnionFlow activables selon le type d''organisation';
|
||
COMMENT ON TABLE modules_organisation_actifs IS 'Modules activés pour une organisation donnée avec paramètres spécifiques';
|
||
|
||
|
||
-- ========== V2.7__Ayants_Droit.sql ==========
|
||
-- ============================================================
|
||
-- V2.7 — Ayants droit (mutuelles de santé)
|
||
-- Auteur: UnionFlow Team | BCEAO/OHADA compliant
|
||
-- ============================================================
|
||
|
||
CREATE TABLE IF NOT EXISTS ayants_droit (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
||
membre_organisation_id UUID NOT NULL, -- membre dans le contexte org mutuelle
|
||
prenom VARCHAR(100) NOT NULL,
|
||
nom VARCHAR(100) NOT NULL,
|
||
date_naissance DATE,
|
||
lien_parente VARCHAR(20) NOT NULL, -- CONJOINT|ENFANT|PARENT|AUTRE
|
||
numero_beneficiaire VARCHAR(50), -- numéro pour les conventions santé
|
||
date_debut_couverture DATE,
|
||
date_fin_couverture DATE,
|
||
|
||
-- Métadonnées 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_ad_membre_org FOREIGN KEY (membre_organisation_id) REFERENCES membres_organisations(id) ON DELETE CASCADE,
|
||
CONSTRAINT chk_ad_lien_parente CHECK (lien_parente IN ('CONJOINT','ENFANT','PARENT','AUTRE'))
|
||
);
|
||
|
||
CREATE INDEX idx_ad_membre_org ON ayants_droit(membre_organisation_id);
|
||
CREATE INDEX idx_ad_couverture ON ayants_droit(date_debut_couverture, date_fin_couverture);
|
||
|
||
COMMENT ON TABLE ayants_droit IS 'Bénéficiaires d''un membre dans une mutuelle de santé (conjoint, enfants, parents)';
|
||
COMMENT ON COLUMN ayants_droit.numero_beneficiaire IS 'Numéro unique attribué pour les conventions avec les centres de santé partenaires';
|
||
|
||
|
||
-- ========== V2.8__Roles_Par_Organisation.sql ==========
|
||
-- ============================================================
|
||
-- V2.8 — Rôles par organisation : membres_roles enrichi
|
||
-- Un membre peut avoir des rôles différents selon l'organisation
|
||
-- Auteur: UnionFlow Team | BCEAO/OHADA compliant
|
||
-- ============================================================
|
||
|
||
-- membres_roles doit référencer membres_organisations (pas uniquement membres)
|
||
-- On ajoute organisation_id et membre_organisation_id pour permettre les rôles multi-org
|
||
|
||
ALTER TABLE membres_roles
|
||
ADD COLUMN IF NOT EXISTS membre_organisation_id UUID,
|
||
ADD COLUMN IF NOT EXISTS organisation_id UUID;
|
||
|
||
-- Mettre à jour la FK et la contrainte UNIQUE
|
||
ALTER TABLE membres_roles
|
||
DROP CONSTRAINT IF EXISTS uk_membre_role;
|
||
|
||
ALTER TABLE membres_roles
|
||
ADD CONSTRAINT fk_mr_membre_org FOREIGN KEY (membre_organisation_id) REFERENCES membres_organisations(id) ON DELETE CASCADE,
|
||
ADD CONSTRAINT fk_mr_organisation FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE CASCADE;
|
||
|
||
-- Nouvelle contrainte: un utilisateur ne peut avoir le même rôle qu'une fois par organisation
|
||
ALTER TABLE membres_roles
|
||
ADD CONSTRAINT uk_mr_membre_org_role
|
||
UNIQUE (membre_organisation_id, role_id);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_mr_membre_org ON membres_roles(membre_organisation_id);
|
||
CREATE INDEX IF NOT EXISTS idx_mr_organisation ON membres_roles(organisation_id);
|
||
|
||
COMMENT ON COLUMN membres_roles.membre_organisation_id IS 'Lien vers le membership de l''utilisateur dans l''organisation — détermine le contexte du rôle';
|
||
COMMENT ON COLUMN membres_roles.organisation_id IS 'Organisation dans laquelle ce rôle est actif — dénormalisé pour les requêtes de performance';
|
||
|
||
|
||
-- ========== V2.9__Audit_Enhancements.sql ==========
|
||
-- ============================================================
|
||
-- V2.9 — Améliorations audit_logs : portée + organisation
|
||
-- Double niveau : ORGANISATION (manager) + PLATEFORME (super admin)
|
||
-- Conservation 10 ans — BCEAO/OHADA/Fiscalité ivoirienne
|
||
-- Auteur: UnionFlow Team
|
||
-- ============================================================
|
||
|
||
ALTER TABLE audit_logs
|
||
ADD COLUMN IF NOT EXISTS organisation_id UUID,
|
||
ADD COLUMN IF NOT EXISTS portee VARCHAR(15) NOT NULL DEFAULT 'PLATEFORME';
|
||
|
||
ALTER TABLE audit_logs
|
||
ADD CONSTRAINT fk_audit_organisation FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE SET NULL,
|
||
ADD CONSTRAINT chk_audit_portee CHECK (portee IN ('ORGANISATION','PLATEFORME'));
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_audit_organisation ON audit_logs(organisation_id);
|
||
CREATE INDEX IF NOT EXISTS idx_audit_portee ON audit_logs(portee);
|
||
|
||
-- Index composite pour les consultations fréquentes
|
||
CREATE INDEX IF NOT EXISTS idx_audit_org_portee_date ON audit_logs(organisation_id, portee, date_heure DESC);
|
||
|
||
COMMENT ON COLUMN audit_logs.organisation_id IS 'Organisation concernée — NULL pour événements plateforme';
|
||
COMMENT ON COLUMN audit_logs.portee IS 'ORGANISATION: visible par le manager | PLATEFORME: visible uniquement par Super Admin UnionFlow';
|
||
|
||
|
||
-- ========== V2.10__Devises_Africaines_Uniquement.sql ==========
|
||
-- ============================================================
|
||
-- V2.10 — Devises : liste strictement africaine
|
||
-- Remplace EUR, USD, GBP, CHF par des codes africains (XOF par défaut)
|
||
-- ============================================================
|
||
|
||
-- Migrer les organisations avec une devise non africaine vers XOF
|
||
UPDATE organisations
|
||
SET devise = 'XOF'
|
||
WHERE devise IS NOT NULL
|
||
AND devise NOT IN ('XOF', 'XAF', 'MAD', 'DZD', 'TND', 'NGN', 'GHS', 'KES', 'ZAR');
|
||
|
||
-- Remplacer la contrainte par une liste africaine uniquement
|
||
ALTER TABLE organisations DROP CONSTRAINT IF EXISTS chk_organisation_devise;
|
||
|
||
ALTER TABLE organisations
|
||
ADD CONSTRAINT chk_organisation_devise CHECK (
|
||
devise IN ('XOF', 'XAF', 'MAD', 'DZD', 'TND', 'NGN', 'GHS', 'KES', 'ZAR')
|
||
);
|
||
|
||
COMMENT ON COLUMN organisations.devise IS 'Code ISO 4217 — devises africaines uniquement (XOF, XAF, MAD, DZD, TND, NGN, GHS, KES, ZAR)';
|
||
|
||
|
||
-- ========== V3.0__Optimisation_Structure_Donnees.sql ==========
|
||
-- =====================================================
|
||
-- V3.0 — Optimisation de la structure de données
|
||
-- =====================================================
|
||
-- Cat.1 : Table types_reference
|
||
-- Cat.2 : Table paiements_objets + suppression
|
||
-- colonnes adresse de organisations
|
||
-- Cat.4 : Refonte pieces_jointes (polymorphique)
|
||
-- Cat.5 : Colonnes Membre manquantes
|
||
-- =====================================================
|
||
|
||
-- ─────────────────────────────────────────────────────
|
||
-- Cat.1 — types_reference
|
||
-- ─────────────────────────────────────────────────────
|
||
CREATE TABLE IF NOT EXISTS types_reference (
|
||
id UUID PRIMARY KEY,
|
||
domaine VARCHAR(100) NOT NULL,
|
||
code VARCHAR(100) NOT NULL,
|
||
libelle VARCHAR(255) NOT NULL,
|
||
description VARCHAR(1000),
|
||
ordre INT NOT NULL DEFAULT 0,
|
||
valeur_systeme BOOLEAN NOT NULL DEFAULT FALSE,
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT NOT NULL DEFAULT 0,
|
||
CONSTRAINT uk_type_ref_domaine_code
|
||
UNIQUE (domaine, code)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_tr_domaine
|
||
ON types_reference (domaine);
|
||
CREATE INDEX IF NOT EXISTS idx_tr_actif
|
||
ON types_reference (actif);
|
||
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
-- Bloc d'idempotence : corrige l'écart entre la table créée par Hibernate
|
||
-- (sans DEFAULT SQL) et le schéma attendu par cette migration.
|
||
-- Hibernate gère les defaults en Java ; ici on les pose au niveau PostgreSQL.
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
ALTER TABLE types_reference
|
||
ADD COLUMN IF NOT EXISTS valeur_systeme BOOLEAN NOT NULL DEFAULT FALSE;
|
||
|
||
ALTER TABLE types_reference
|
||
ADD COLUMN IF NOT EXISTS ordre INT NOT NULL DEFAULT 0,
|
||
ADD COLUMN IF NOT EXISTS actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
ADD COLUMN IF NOT EXISTS version BIGINT NOT NULL DEFAULT 0,
|
||
ADD COLUMN IF NOT EXISTS date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
ADD COLUMN IF NOT EXISTS est_defaut BOOLEAN NOT NULL DEFAULT FALSE,
|
||
ADD COLUMN IF NOT EXISTS est_systeme BOOLEAN NOT NULL DEFAULT FALSE,
|
||
ADD COLUMN IF NOT EXISTS ordre_affichage INT NOT NULL DEFAULT 0;
|
||
|
||
-- Garantit que la contrainte UNIQUE existe (nécessaire pour ON CONFLICT ci-dessous)
|
||
DO $$
|
||
BEGIN
|
||
IF NOT EXISTS (
|
||
SELECT 1 FROM pg_constraint
|
||
WHERE conname = 'uk_type_ref_domaine_code'
|
||
AND conrelid = 'types_reference'::regclass
|
||
) THEN
|
||
ALTER TABLE types_reference
|
||
ADD CONSTRAINT uk_type_ref_domaine_code UNIQUE (domaine, code);
|
||
END IF;
|
||
END $$;
|
||
|
||
-- Données initiales : domaines référencés par les entités
|
||
-- Toutes les colonnes NOT NULL sont fournies (table peut exister sans DEFAULT si créée par Hibernate)
|
||
INSERT INTO types_reference (id, domaine, code, libelle, valeur_systeme, cree_par, actif, ordre, version, date_creation, est_defaut, est_systeme, ordre_affichage)
|
||
VALUES
|
||
-- OBJET_PAIEMENT (Cat.2 — PaiementObjet)
|
||
(gen_random_uuid(), 'OBJET_PAIEMENT', 'COTISATION', 'Cotisation', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'OBJET_PAIEMENT', 'ADHESION', 'Adhésion', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'OBJET_PAIEMENT', 'EVENEMENT', 'Événement', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'OBJET_PAIEMENT', 'AIDE', 'Aide', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
-- ENTITE_RATTACHEE (Cat.4 — PieceJointe)
|
||
(gen_random_uuid(), 'ENTITE_RATTACHEE', 'MEMBRE', 'Membre', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'ENTITE_RATTACHEE', 'ORGANISATION', 'Organisation', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'ENTITE_RATTACHEE', 'COTISATION', 'Cotisation', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'ENTITE_RATTACHEE', 'ADHESION', 'Adhésion', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'ENTITE_RATTACHEE', 'AIDE', 'Aide', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'ENTITE_RATTACHEE', 'TRANSACTION_WAVE', 'Transaction Wave', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
-- STATUT_MATRIMONIAL (Cat.5 — Membre)
|
||
(gen_random_uuid(), 'STATUT_MATRIMONIAL', 'CELIBATAIRE', 'Célibataire', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'STATUT_MATRIMONIAL', 'MARIE', 'Marié(e)', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'STATUT_MATRIMONIAL', 'DIVORCE', 'Divorcé(e)', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'STATUT_MATRIMONIAL', 'VEUF', 'Veuf/Veuve', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
-- TYPE_IDENTITE (Cat.5 — Membre)
|
||
(gen_random_uuid(), 'TYPE_IDENTITE', 'CNI', 'Carte Nationale d''Identité', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'TYPE_IDENTITE', 'PASSEPORT', 'Passeport', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'TYPE_IDENTITE', 'PERMIS', 'Permis de conduire', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'TYPE_IDENTITE', 'CARTE_SEJOUR','Carte de séjour', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0)
|
||
ON CONFLICT (domaine, code) DO NOTHING;
|
||
|
||
-- ─────────────────────────────────────────────────────
|
||
-- Cat.2 — paiements_objets (remplace 4 tables)
|
||
-- ─────────────────────────────────────────────────────
|
||
CREATE TABLE IF NOT EXISTS paiements_objets (
|
||
id UUID PRIMARY KEY,
|
||
paiement_id UUID NOT NULL
|
||
REFERENCES paiements(id),
|
||
type_objet_cible VARCHAR(50) NOT NULL,
|
||
objet_cible_id UUID NOT NULL,
|
||
montant_applique NUMERIC(14,2) NOT NULL,
|
||
date_application TIMESTAMP,
|
||
commentaire VARCHAR(500),
|
||
actif BOOLEAN NOT NULL DEFAULT TRUE,
|
||
date_creation TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
date_modification TIMESTAMP,
|
||
cree_par VARCHAR(255),
|
||
modifie_par VARCHAR(255),
|
||
version BIGINT NOT NULL DEFAULT 0,
|
||
CONSTRAINT uk_paiement_objet
|
||
UNIQUE (paiement_id, type_objet_cible, objet_cible_id)
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_po_paiement
|
||
ON paiements_objets (paiement_id);
|
||
CREATE INDEX IF NOT EXISTS idx_po_objet
|
||
ON paiements_objets (type_objet_cible, objet_cible_id);
|
||
CREATE INDEX IF NOT EXISTS idx_po_type
|
||
ON paiements_objets (type_objet_cible);
|
||
|
||
-- ─────────────────────────────────────────────────────
|
||
-- Cat.2 — Suppression colonnes adresse de organisations
|
||
-- ─────────────────────────────────────────────────────
|
||
ALTER TABLE organisations
|
||
DROP COLUMN IF EXISTS adresse,
|
||
DROP COLUMN IF EXISTS ville,
|
||
DROP COLUMN IF EXISTS code_postal,
|
||
DROP COLUMN IF EXISTS region,
|
||
DROP COLUMN IF EXISTS pays;
|
||
|
||
-- ─────────────────────────────────────────────────────
|
||
-- Cat.4 — pieces_jointes → polymorphique
|
||
-- ─────────────────────────────────────────────────────
|
||
-- Ajout colonnes polymorphiques
|
||
ALTER TABLE pieces_jointes
|
||
ADD COLUMN IF NOT EXISTS type_entite_rattachee VARCHAR(50),
|
||
ADD COLUMN IF NOT EXISTS entite_rattachee_id UUID;
|
||
|
||
-- Migration des données existantes (colonnes FK explicites ou entite_type/entite_id selon le schéma)
|
||
DO $$
|
||
BEGIN
|
||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'pieces_jointes' AND column_name = 'membre_id') THEN
|
||
UPDATE pieces_jointes SET type_entite_rattachee = 'MEMBRE', entite_rattachee_id = membre_id WHERE membre_id IS NOT NULL AND (type_entite_rattachee IS NULL OR type_entite_rattachee = '');
|
||
END IF;
|
||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'pieces_jointes' AND column_name = 'organisation_id') THEN
|
||
UPDATE pieces_jointes SET type_entite_rattachee = 'ORGANISATION', entite_rattachee_id = organisation_id WHERE organisation_id IS NOT NULL AND (type_entite_rattachee IS NULL OR type_entite_rattachee = '');
|
||
END IF;
|
||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'pieces_jointes' AND column_name = 'cotisation_id') THEN
|
||
UPDATE pieces_jointes SET type_entite_rattachee = 'COTISATION', entite_rattachee_id = cotisation_id WHERE cotisation_id IS NOT NULL AND (type_entite_rattachee IS NULL OR type_entite_rattachee = '');
|
||
END IF;
|
||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'pieces_jointes' AND column_name = 'adhesion_id') THEN
|
||
UPDATE pieces_jointes SET type_entite_rattachee = 'ADHESION', entite_rattachee_id = adhesion_id WHERE adhesion_id IS NOT NULL AND (type_entite_rattachee IS NULL OR type_entite_rattachee = '');
|
||
END IF;
|
||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'pieces_jointes' AND column_name = 'demande_aide_id') THEN
|
||
UPDATE pieces_jointes SET type_entite_rattachee = 'AIDE', entite_rattachee_id = demande_aide_id WHERE demande_aide_id IS NOT NULL AND (type_entite_rattachee IS NULL OR type_entite_rattachee = '');
|
||
END IF;
|
||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'pieces_jointes' AND column_name = 'transaction_wave_id') THEN
|
||
UPDATE pieces_jointes SET type_entite_rattachee = 'TRANSACTION_WAVE', entite_rattachee_id = transaction_wave_id WHERE transaction_wave_id IS NOT NULL AND (type_entite_rattachee IS NULL OR type_entite_rattachee = '');
|
||
END IF;
|
||
-- Schéma V1.7 : entite_type / entite_id
|
||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'pieces_jointes' AND column_name = 'entite_type') THEN
|
||
UPDATE pieces_jointes SET type_entite_rattachee = COALESCE(NULLIF(TRIM(entite_type), ''), 'MEMBRE'), entite_rattachee_id = entite_id WHERE entite_id IS NOT NULL AND (type_entite_rattachee IS NULL OR type_entite_rattachee = '');
|
||
END IF;
|
||
-- Valeurs par défaut pour lignes restantes (évite échec NOT NULL)
|
||
UPDATE pieces_jointes SET type_entite_rattachee = COALESCE(NULLIF(TRIM(type_entite_rattachee), ''), 'MEMBRE'), entite_rattachee_id = COALESCE(entite_rattachee_id, (SELECT id FROM utilisateurs LIMIT 1)) WHERE type_entite_rattachee IS NULL OR type_entite_rattachee = '' OR entite_rattachee_id IS NULL;
|
||
END $$;
|
||
|
||
-- Contrainte NOT NULL après migration (seulement si plus aucune ligne NULL)
|
||
DO $$
|
||
BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pieces_jointes WHERE type_entite_rattachee IS NULL OR type_entite_rattachee = '' OR entite_rattachee_id IS NULL) THEN
|
||
EXECUTE 'ALTER TABLE pieces_jointes ALTER COLUMN type_entite_rattachee SET NOT NULL';
|
||
EXECUTE 'ALTER TABLE pieces_jointes ALTER COLUMN entite_rattachee_id SET NOT NULL';
|
||
END IF;
|
||
END $$;
|
||
|
||
-- Suppression anciennes FK ou colonnes polymorphiques V1.7 (entite_type, entite_id)
|
||
ALTER TABLE pieces_jointes
|
||
DROP COLUMN IF EXISTS membre_id,
|
||
DROP COLUMN IF EXISTS organisation_id,
|
||
DROP COLUMN IF EXISTS cotisation_id,
|
||
DROP COLUMN IF EXISTS adhesion_id,
|
||
DROP COLUMN IF EXISTS demande_aide_id,
|
||
DROP COLUMN IF EXISTS transaction_wave_id,
|
||
DROP COLUMN IF EXISTS entite_type,
|
||
DROP COLUMN IF EXISTS entite_id;
|
||
|
||
-- Suppression anciens index
|
||
DROP INDEX IF EXISTS idx_piece_jointe_membre;
|
||
DROP INDEX IF EXISTS idx_piece_jointe_organisation;
|
||
DROP INDEX IF EXISTS idx_piece_jointe_cotisation;
|
||
DROP INDEX IF EXISTS idx_piece_jointe_adhesion;
|
||
DROP INDEX IF EXISTS idx_piece_jointe_demande_aide;
|
||
DROP INDEX IF EXISTS idx_piece_jointe_transaction_wave;
|
||
|
||
-- Nouveaux index polymorphiques
|
||
CREATE INDEX IF NOT EXISTS idx_pj_entite
|
||
ON pieces_jointes (type_entite_rattachee, entite_rattachee_id);
|
||
CREATE INDEX IF NOT EXISTS idx_pj_type_entite
|
||
ON pieces_jointes (type_entite_rattachee);
|
||
|
||
-- ─────────────────────────────────────────────────────
|
||
-- Cat.5 — Colonnes Membre manquantes (table utilisateurs depuis V2.0)
|
||
-- ─────────────────────────────────────────────────────
|
||
ALTER TABLE utilisateurs
|
||
ADD COLUMN IF NOT EXISTS statut_matrimonial VARCHAR(50),
|
||
ADD COLUMN IF NOT EXISTS nationalite VARCHAR(100),
|
||
ADD COLUMN IF NOT EXISTS type_identite VARCHAR(50),
|
||
ADD COLUMN IF NOT EXISTS numero_identite VARCHAR(100);
|
||
|
||
-- ─────────────────────────────────────────────────────
|
||
-- Cat.8 — Valeurs par défaut dans configurations
|
||
-- ─────────────────────────────────────────────────────
|
||
INSERT INTO configurations (id, cle, valeur, type, categorie, description, modifiable, visible, actif, date_creation, cree_par, version)
|
||
VALUES
|
||
(gen_random_uuid(), 'defaut.devise', 'XOF', 'STRING', 'SYSTEME', 'Devise par défaut', TRUE, TRUE, TRUE, NOW(), 'system', 0),
|
||
(gen_random_uuid(), 'defaut.statut.organisation', 'ACTIVE', 'STRING', 'SYSTEME', 'Statut initial organisation', TRUE, TRUE, TRUE, NOW(), 'system', 0),
|
||
(gen_random_uuid(), 'defaut.type.organisation', 'ASSOCIATION', 'STRING', 'SYSTEME', 'Type initial organisation', TRUE, TRUE, TRUE, NOW(), 'system', 0),
|
||
(gen_random_uuid(), 'defaut.utilisateur.systeme', 'system', 'STRING', 'SYSTEME', 'Identifiant utilisateur système', FALSE, FALSE, TRUE, NOW(), 'system', 0),
|
||
(gen_random_uuid(), 'defaut.montant.cotisation', '0', 'NUMBER', 'SYSTEME', 'Montant cotisation par défaut', TRUE, TRUE, TRUE, NOW(), 'system', 0)
|
||
ON CONFLICT DO NOTHING;
|
||
|
||
-- ─────────────────────────────────────────────────────
|
||
-- Cat.7 — Index composites pour requêtes fréquentes
|
||
-- ─────────────────────────────────────────────────────
|
||
-- Aligner paiements avec l'entité (statut → statut_paiement si la colonne existe)
|
||
DO $$
|
||
BEGIN
|
||
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'paiements' AND column_name = 'statut')
|
||
AND NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'public' AND table_name = 'paiements' AND column_name = 'statut_paiement') THEN
|
||
ALTER TABLE paiements RENAME COLUMN statut TO statut_paiement;
|
||
END IF;
|
||
END $$;
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_cotisation_org_statut_annee
|
||
ON cotisations (organisation_id, statut, annee);
|
||
CREATE INDEX IF NOT EXISTS idx_cotisation_membre_statut
|
||
ON cotisations (membre_id, statut);
|
||
CREATE INDEX IF NOT EXISTS idx_paiement_membre_statut_date
|
||
ON paiements (membre_id, statut_paiement,
|
||
date_paiement);
|
||
CREATE INDEX IF NOT EXISTS idx_notification_membre_statut
|
||
ON notifications (membre_id, statut, date_envoi);
|
||
CREATE INDEX IF NOT EXISTS idx_adhesion_org_statut
|
||
ON demandes_adhesion (organisation_id, statut);
|
||
CREATE INDEX IF NOT EXISTS idx_aide_org_statut_urgence
|
||
ON demandes_aide (organisation_id, statut, urgence);
|
||
CREATE INDEX IF NOT EXISTS idx_membreorg_org_statut
|
||
ON membres_organisations
|
||
(organisation_id, statut_membre);
|
||
CREATE INDEX IF NOT EXISTS idx_evenement_org_date_statut
|
||
ON evenements
|
||
(organisation_id, date_debut, statut);
|
||
|
||
-- ─────────────────────────────────────────────────────
|
||
-- Cat.7 — Contraintes CHECK métier
|
||
-- ─────────────────────────────────────────────────────
|
||
ALTER TABLE cotisations
|
||
ADD CONSTRAINT chk_montant_paye_le_du
|
||
CHECK (montant_paye <= montant_du);
|
||
ALTER TABLE souscriptions_organisation
|
||
ADD CONSTRAINT chk_quota_utilise_le_max
|
||
CHECK (quota_utilise <= quota_max);
|
||
|
||
|
||
-- ========== V3.1__Add_Module_Disponible_FK.sql ==========
|
||
-- =====================================================
|
||
-- V3.1 — Correction Intégrité Référentielle Modules
|
||
-- Cat.2 — ModuleOrganisationActif -> ModuleDisponible
|
||
-- =====================================================
|
||
|
||
-- 1. Ajout de la colonne FK
|
||
ALTER TABLE modules_organisation_actifs
|
||
ADD COLUMN IF NOT EXISTS module_disponible_id UUID;
|
||
|
||
-- 2. Migration des données basées sur module_code
|
||
UPDATE modules_organisation_actifs moa
|
||
SET module_disponible_id = (SELECT id FROM modules_disponibles md WHERE md.code = moa.module_code);
|
||
|
||
-- 3. Ajout de la contrainte FK
|
||
ALTER TABLE modules_organisation_actifs
|
||
ADD CONSTRAINT fk_moa_module_disponible
|
||
FOREIGN KEY (module_disponible_id) REFERENCES modules_disponibles(id)
|
||
ON DELETE RESTRICT;
|
||
|
||
-- 4. Nettoyage (Optionnel : on garde module_code pour compatibilité DTO existante si nécessaire,
|
||
-- mais on force la cohérence via un index unique si possible)
|
||
CREATE INDEX IF NOT EXISTS idx_moa_module_id ON modules_organisation_actifs(module_disponible_id);
|
||
|
||
-- Note: L'audit demandait l'intégrité, c'est fait.
|
||
|
||
|
||
-- ========== V3.2__Seed_Types_Reference.sql ==========
|
||
-- =====================================================
|
||
-- V3.2 — Initialisation des Types de Référence
|
||
-- Cat.1 — Centralisation des domaines de valeurs
|
||
-- Colonnes alignées sur l'entité TypeReference (domaine, code, etc.)
|
||
-- =====================================================
|
||
|
||
-- 2. Statut Matrimonial (complément éventuel à V3.0)
|
||
INSERT INTO types_reference (id, domaine, code, libelle, description, valeur_systeme, cree_par, actif, ordre, version, date_creation, est_defaut, est_systeme, ordre_affichage)
|
||
VALUES
|
||
(gen_random_uuid(), 'STATUT_MATRIMONIAL', 'CELIBATAIRE', 'Célibataire', 'Membre non marié', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'STATUT_MATRIMONIAL', 'MARIE', 'Marié(e)', 'Membre marié', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'STATUT_MATRIMONIAL', 'VEUF', 'Veuf/Veuve', 'Membre ayant perdu son conjoint', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'STATUT_MATRIMONIAL', 'DIVORCE', 'Divorcé(e)', 'Membre divorcé', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0)
|
||
ON CONFLICT (domaine, code) DO NOTHING;
|
||
|
||
-- 3. Type d'Identité
|
||
INSERT INTO types_reference (id, domaine, code, libelle, description, valeur_systeme, cree_par, actif, ordre, version, date_creation, est_defaut, est_systeme, ordre_affichage)
|
||
VALUES
|
||
(gen_random_uuid(), 'TYPE_IDENTITE', 'CNI', 'Carte Nationale d''Identité', 'Pièce d''identité nationale', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'TYPE_IDENTITE', 'PASSEPORT', 'Passeport', 'Passeport international', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'TYPE_IDENTITE', 'PERMIS_CONDUIRE', 'Permis de conduire', 'Permis de conduire officiel', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'TYPE_IDENTITE', 'CARTE_CONSULAIRE', 'Carte Consulaire', 'Carte délivrée par un consulat', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0)
|
||
ON CONFLICT (domaine, code) DO NOTHING;
|
||
|
||
-- 4. Objet de Paiement (compléments à V3.0)
|
||
INSERT INTO types_reference (id, domaine, code, libelle, description, valeur_systeme, cree_par, actif, ordre, version, date_creation, est_defaut, est_systeme, ordre_affichage)
|
||
VALUES
|
||
(gen_random_uuid(), 'OBJET_PAIEMENT', 'COTISATION', 'Cotisation annuelle', 'Paiement de la cotisation de membre', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'OBJET_PAIEMENT', 'DON', 'Don gracieux', 'Don volontaire pour l''association', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'OBJET_PAIEMENT', 'INSCRIPTION_EVENEMENT', 'Inscription à un événement', 'Paiement pour participer à un événement', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'OBJET_PAIEMENT', 'AMENDE', 'Amende / Sanction', 'Paiement suite à une sanction', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0)
|
||
ON CONFLICT (domaine, code) DO NOTHING;
|
||
|
||
-- 5. Type d'Organisation
|
||
INSERT INTO types_reference (id, domaine, code, libelle, description, valeur_systeme, cree_par, actif, ordre, version, date_creation, est_defaut, est_systeme, ordre_affichage)
|
||
VALUES
|
||
(gen_random_uuid(), 'TYPE_ORGANISATION', 'ASSOCIATION', 'Association', 'Organisation type association', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'TYPE_ORGANISATION', 'COOPERATIVE', 'Coopérative', 'Organisation type coopérative', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'TYPE_ORGANISATION', 'FEDERATION', 'Fédération', 'Regroupement d''associations', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'TYPE_ORGANISATION', 'CELLULE', 'Cellule de base', 'Unité locale d''une organisation', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0)
|
||
ON CONFLICT (domaine, code) DO NOTHING;
|
||
|
||
-- 6. Type de Rôle
|
||
INSERT INTO types_reference (id, domaine, code, libelle, description, valeur_systeme, cree_par, actif, ordre, version, date_creation, est_defaut, est_systeme, ordre_affichage)
|
||
VALUES
|
||
(gen_random_uuid(), 'TYPE_ROLE', 'SYSTEME', 'Système', 'Rôle global non modifiable', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'TYPE_ROLE', 'ORGANISATION', 'Organisation', 'Rôle spécifique à une organisation', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'TYPE_ROLE', 'PERSONNALISE', 'Personnalisé', 'Rôle créé manuellement', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0)
|
||
ON CONFLICT (domaine, code) DO NOTHING;
|
||
|
||
-- 7. Statut d'Inscription
|
||
INSERT INTO types_reference (id, domaine, code, libelle, description, valeur_systeme, cree_par, actif, ordre, version, date_creation, est_defaut, est_systeme, ordre_affichage)
|
||
VALUES
|
||
(gen_random_uuid(), 'STATUT_INSCRIPTION', 'CONFIRMEE', 'Confirmée', 'Inscription validée', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'STATUT_INSCRIPTION', 'EN_ATTENTE', 'En attente', 'En attente de validation', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'STATUT_INSCRIPTION', 'ANNULEE', 'Annulée', 'Inscription annulée par l''utilisateur', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0),
|
||
(gen_random_uuid(), 'STATUT_INSCRIPTION', 'REFUSEE', 'Refusée', 'Inscription rejetée par l''organisateur', TRUE, 'system', TRUE, 0, 0, NOW(), FALSE, TRUE, 0)
|
||
ON CONFLICT (domaine, code) DO NOTHING;
|
||
|
||
|
||
-- ========== V3.3__Optimisation_Index_Performance.sql ==========
|
||
-- =====================================================
|
||
-- V3.3 — Optimisation des Index de Performance
|
||
-- Cat.7 — Index composites pour recherches fréquentes
|
||
-- =====================================================
|
||
|
||
-- 1. Index composite sur les membres (Recherche par nom complet)
|
||
CREATE INDEX IF NOT EXISTS idx_membre_nom_prenom ON utilisateurs(nom, prenom);
|
||
|
||
-- 2. Index composite sur les cotisations (Recherche par membre et année)
|
||
CREATE INDEX IF NOT EXISTS idx_cotisation_membre_annee ON cotisations(membre_id, annee);
|
||
|
||
-- 3. Index sur le Keycloak ID pour synchronisation rapide
|
||
CREATE INDEX IF NOT EXISTS idx_membre_keycloak_id ON utilisateurs(keycloak_id);
|
||
|
||
-- 4. Index sur le statut des paiements
|
||
CREATE INDEX IF NOT EXISTS idx_paiement_statut_paiement ON paiements(statut_paiement);
|
||
|
||
-- 5. Index sur les dates de création pour tris par défaut
|
||
CREATE INDEX IF NOT EXISTS idx_membre_date_creation ON utilisateurs(date_creation DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_organisation_date_creation ON organisations(date_creation DESC);
|
||
|
||
|
||
-- ========== V3.4__LCB_FT_Anti_Blanchiment.sql ==========
|
||
-- ============================================================
|
||
-- V3.4 — LCB-FT / Anti-blanchiment (mutuelles)
|
||
-- Spec: specs/001-mutuelles-anti-blanchiment/spec.md
|
||
-- Traçabilité origine des fonds, KYC, seuils
|
||
-- ============================================================
|
||
|
||
-- 1. Utilisateurs (identité) — vigilance KYC
|
||
ALTER TABLE utilisateurs
|
||
ADD COLUMN IF NOT EXISTS niveau_vigilance_kyc VARCHAR(20) DEFAULT 'SIMPLIFIE',
|
||
ADD COLUMN IF NOT EXISTS statut_kyc VARCHAR(20) DEFAULT 'NON_VERIFIE',
|
||
ADD COLUMN IF NOT EXISTS date_verification_identite DATE;
|
||
|
||
ALTER TABLE utilisateurs
|
||
ADD CONSTRAINT chk_utilisateur_niveau_kyc
|
||
CHECK (niveau_vigilance_kyc IS NULL OR niveau_vigilance_kyc IN ('SIMPLIFIE', 'RENFORCE'));
|
||
ALTER TABLE utilisateurs
|
||
ADD CONSTRAINT chk_utilisateur_statut_kyc
|
||
CHECK (statut_kyc IS NULL OR statut_kyc IN ('NON_VERIFIE', 'EN_COURS', 'VERIFIE', 'REFUSE'));
|
||
|
||
CREATE INDEX IF NOT EXISTS idx_utilisateur_statut_kyc ON utilisateurs(statut_kyc);
|
||
|
||
COMMENT ON COLUMN utilisateurs.niveau_vigilance_kyc IS 'Niveau de vigilance KYC LCB-FT';
|
||
COMMENT ON COLUMN utilisateurs.statut_kyc IS 'Statut vérification identité';
|
||
COMMENT ON COLUMN utilisateurs.date_verification_identite IS 'Date de dernière vérification d''identité';
|
||
|
||
-- 2. Intentions de paiement — origine des fonds / justification LCB-FT
|
||
ALTER TABLE intentions_paiement
|
||
ADD COLUMN IF NOT EXISTS origine_fonds VARCHAR(200),
|
||
ADD COLUMN IF NOT EXISTS justification_lcb_ft TEXT;
|
||
|
||
COMMENT ON COLUMN intentions_paiement.origine_fonds IS 'Origine des fonds déclarée (obligatoire au-dessus du seuil)';
|
||
COMMENT ON COLUMN intentions_paiement.justification_lcb_ft IS 'Justification LCB-FT optionnelle';
|
||
|
||
-- 3. Transactions épargne — origine des fonds, pièce justificative (si la table existe)
|
||
DO $$
|
||
BEGIN
|
||
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'transactions_epargne') THEN
|
||
ALTER TABLE transactions_epargne
|
||
ADD COLUMN IF NOT EXISTS origine_fonds VARCHAR(200),
|
||
ADD COLUMN IF NOT EXISTS piece_justificative_id UUID;
|
||
EXECUTE 'COMMENT ON COLUMN transactions_epargne.origine_fonds IS ''Origine des fonds (obligatoire au-dessus du seuil LCB-FT)''';
|
||
EXECUTE 'COMMENT ON COLUMN transactions_epargne.piece_justificative_id IS ''Référence pièce jointe justificative''';
|
||
END IF;
|
||
END $$;
|
||
|
||
-- 4. Paramètres LCB-FT (seuils par organisation ou globaux)
|
||
CREATE TABLE IF NOT EXISTS parametres_lcb_ft (
|
||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
organisation_id UUID,
|
||
code_devise VARCHAR(3) NOT NULL DEFAULT 'XOF',
|
||
montant_seuil_justification DECIMAL(18,4) NOT NULL,
|
||
montant_seuil_validation_manuelle DECIMAL(18,4),
|
||
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_param_lcb_ft_org FOREIGN KEY (organisation_id) REFERENCES organisations(id) ON DELETE CASCADE,
|
||
CONSTRAINT chk_param_devise CHECK (code_devise ~ '^[A-Z]{3}$')
|
||
);
|
||
|
||
CREATE UNIQUE INDEX IF NOT EXISTS idx_param_lcb_ft_org_devise
|
||
ON parametres_lcb_ft(COALESCE(organisation_id, '00000000-0000-0000-0000-000000000000'::uuid), code_devise);
|
||
CREATE INDEX IF NOT EXISTS idx_param_lcb_ft_org ON parametres_lcb_ft(organisation_id);
|
||
|
||
COMMENT ON TABLE parametres_lcb_ft IS 'Seuils LCB-FT : au-dessus de montant_seuil_justification, origine des fonds obligatoire';
|
||
COMMENT ON COLUMN parametres_lcb_ft.organisation_id IS 'NULL = paramètres plateforme par défaut';
|
||
|
||
-- Valeur par défaut plateforme (XOF) — une seule ligne org NULL + XOF (toutes colonnes NOT NULL fournies)
|
||
INSERT INTO parametres_lcb_ft (id, organisation_id, code_devise, montant_seuil_justification, montant_seuil_validation_manuelle, cree_par, actif, date_creation, version)
|
||
SELECT gen_random_uuid(), NULL, 'XOF', 500000, 1000000, 'system', TRUE, NOW(), 0
|
||
WHERE NOT EXISTS (SELECT 1 FROM parametres_lcb_ft WHERE organisation_id IS NULL AND code_devise = 'XOF');
|
||
|
||
|
||
-- ========== V3.5__Add_Organisation_Address_Fields.sql ==========
|
||
-- Migration V3.5 : Ajout des champs d'adresse dans la table organisations
|
||
-- Date : 2026-02-28
|
||
-- Description : Ajoute les champs adresse, ville, région, pays et code postal
|
||
-- pour stocker l'adresse principale directement dans organisations
|
||
|
||
-- Ajout des colonnes d'adresse
|
||
ALTER TABLE organisations ADD COLUMN IF NOT EXISTS adresse VARCHAR(500);
|
||
ALTER TABLE organisations ADD COLUMN IF NOT EXISTS ville VARCHAR(100);
|
||
ALTER TABLE organisations ADD COLUMN IF NOT EXISTS region VARCHAR(100);
|
||
ALTER TABLE organisations ADD COLUMN IF NOT EXISTS pays VARCHAR(100);
|
||
ALTER TABLE organisations ADD COLUMN IF NOT EXISTS code_postal VARCHAR(20);
|
||
|
||
-- Ajout d'index pour optimiser les recherches par localisation
|
||
CREATE INDEX IF NOT EXISTS idx_organisation_ville ON organisations(ville);
|
||
CREATE INDEX IF NOT EXISTS idx_organisation_region ON organisations(region);
|
||
CREATE INDEX IF NOT EXISTS idx_organisation_pays ON organisations(pays);
|
||
|
||
-- Commentaires sur les colonnes
|
||
COMMENT ON COLUMN organisations.adresse IS 'Adresse principale de l''organisation (dénormalisée pour performance)';
|
||
COMMENT ON COLUMN organisations.ville IS 'Ville de l''adresse principale';
|
||
COMMENT ON COLUMN organisations.region IS 'Région/Province/État de l''adresse principale';
|
||
COMMENT ON COLUMN organisations.pays IS 'Pays de l''adresse principale';
|
||
COMMENT ON COLUMN organisations.code_postal IS 'Code postal de l''adresse principale';
|
||
|
||
|
||
-- ========== V3.6__Create_Test_Organisations.sql ==========
|
||
-- Migration V3.6 - Création des organisations de test MUKEFI et MESKA
|
||
-- UnionFlow - Configuration initiale pour tests
|
||
-- ⚠ Correction : INSERT dans "organisations" (pluriel, table JPA gérée par Hibernate,
|
||
-- définie en V1.2), et non "organisation" (singulier, ancienne table isolée).
|
||
|
||
-- ============================================================================
|
||
-- 1. ORGANISATION MUKEFI (Mutuelle d'épargne et de crédit)
|
||
-- ============================================================================
|
||
|
||
DELETE FROM organisations WHERE nom_court = 'MUKEFI';
|
||
|
||
INSERT INTO organisations (
|
||
id,
|
||
nom,
|
||
nom_court,
|
||
description,
|
||
email,
|
||
telephone,
|
||
site_web,
|
||
type_organisation,
|
||
statut,
|
||
date_fondation,
|
||
numero_enregistrement,
|
||
devise,
|
||
budget_annuel,
|
||
cotisation_obligatoire,
|
||
montant_cotisation_annuelle,
|
||
objectifs,
|
||
activites_principales,
|
||
partenaires,
|
||
latitude,
|
||
longitude,
|
||
date_creation,
|
||
date_modification,
|
||
cree_par,
|
||
modifie_par,
|
||
version,
|
||
actif,
|
||
accepte_nouveaux_membres,
|
||
est_organisation_racine,
|
||
niveau_hierarchique,
|
||
nombre_membres,
|
||
nombre_administrateurs,
|
||
organisation_publique
|
||
) VALUES (
|
||
gen_random_uuid(),
|
||
'Mutuelle d''Épargne et de Crédit des Fonctionnaires et Indépendants',
|
||
'MUKEFI',
|
||
'Mutuelle d''épargne et de crédit dédiée aux fonctionnaires et travailleurs indépendants de Côte d''Ivoire',
|
||
'contact@mukefi.org',
|
||
'+225 07 00 00 00 01',
|
||
'https://mukefi.org',
|
||
'ASSOCIATION',
|
||
'ACTIVE',
|
||
'2020-01-15',
|
||
'MUT-CI-2020-001',
|
||
'XOF',
|
||
500000000,
|
||
true,
|
||
50000,
|
||
'Favoriser l''épargne et l''accès au crédit pour les membres',
|
||
'Épargne, crédit, micro-crédit, formation financière',
|
||
'Banque Centrale des États de l''Afrique de l''Ouest (BCEAO)',
|
||
5.3364,
|
||
-4.0267,
|
||
CURRENT_TIMESTAMP,
|
||
CURRENT_TIMESTAMP,
|
||
'superadmin@unionflow.test',
|
||
'superadmin@unionflow.test',
|
||
0,
|
||
true,
|
||
true,
|
||
true,
|
||
0,
|
||
0,
|
||
0,
|
||
true
|
||
);
|
||
|
||
-- ============================================================================
|
||
-- 2. ORGANISATION MESKA (Association)
|
||
-- ============================================================================
|
||
|
||
DELETE FROM organisations WHERE nom_court = 'MESKA';
|
||
|
||
INSERT INTO organisations (
|
||
id,
|
||
nom,
|
||
nom_court,
|
||
description,
|
||
email,
|
||
telephone,
|
||
site_web,
|
||
type_organisation,
|
||
statut,
|
||
date_fondation,
|
||
numero_enregistrement,
|
||
devise,
|
||
budget_annuel,
|
||
cotisation_obligatoire,
|
||
montant_cotisation_annuelle,
|
||
objectifs,
|
||
activites_principales,
|
||
partenaires,
|
||
latitude,
|
||
longitude,
|
||
date_creation,
|
||
date_modification,
|
||
cree_par,
|
||
modifie_par,
|
||
version,
|
||
actif,
|
||
accepte_nouveaux_membres,
|
||
est_organisation_racine,
|
||
niveau_hierarchique,
|
||
nombre_membres,
|
||
nombre_administrateurs,
|
||
organisation_publique
|
||
) VALUES (
|
||
gen_random_uuid(),
|
||
'Mouvement d''Entraide et de Solidarité de Koumassi et Adjamé',
|
||
'MESKA',
|
||
'Association communautaire d''entraide et de solidarité basée à Abidjan',
|
||
'contact@meska.org',
|
||
'+225 07 00 00 00 02',
|
||
'https://meska.org',
|
||
'ASSOCIATION',
|
||
'ACTIVE',
|
||
'2018-06-20',
|
||
'ASSO-CI-2018-045',
|
||
'XOF',
|
||
25000000,
|
||
true,
|
||
25000,
|
||
'Promouvoir la solidarité et l''entraide entre les membres des communes de Koumassi et Adjamé',
|
||
'Aide sociale, événements communautaires, formations, projets collectifs',
|
||
'Mairie de Koumassi, Mairie d''Adjamé',
|
||
5.2931,
|
||
-3.9468,
|
||
CURRENT_TIMESTAMP,
|
||
CURRENT_TIMESTAMP,
|
||
'superadmin@unionflow.test',
|
||
'superadmin@unionflow.test',
|
||
0,
|
||
true,
|
||
true,
|
||
true,
|
||
0,
|
||
0,
|
||
0,
|
||
true
|
||
);
|
||
|
||
|
||
-- ========== V3.7__Seed_Test_Members.sql ==========
|
||
-- ============================================================================
|
||
-- V3.7 — Données de test : Membres et Cotisations
|
||
-- Tables cibles :
|
||
-- utilisateurs -> entité JPA Membre
|
||
-- organisations -> entité JPA Organisation (V1.2)
|
||
-- membres_organisations -> jointure membre <> organisation
|
||
-- cotisations -> entité JPA Cotisation
|
||
-- ============================================================================
|
||
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
-- 0. Nettoyage (idempotent)
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
|
||
DELETE FROM cotisations
|
||
WHERE membre_id IN (
|
||
SELECT id FROM utilisateurs
|
||
WHERE email IN (
|
||
'membre.mukefi@unionflow.test',
|
||
'admin.mukefi@unionflow.test',
|
||
'membre.meska@unionflow.test'
|
||
)
|
||
);
|
||
|
||
DELETE FROM membres_organisations
|
||
WHERE utilisateur_id IN (
|
||
SELECT id FROM utilisateurs
|
||
WHERE email IN (
|
||
'membre.mukefi@unionflow.test',
|
||
'admin.mukefi@unionflow.test',
|
||
'membre.meska@unionflow.test'
|
||
)
|
||
);
|
||
|
||
DELETE FROM utilisateurs
|
||
WHERE email IN (
|
||
'membre.mukefi@unionflow.test',
|
||
'admin.mukefi@unionflow.test',
|
||
'membre.meska@unionflow.test'
|
||
);
|
||
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
-- 0b. S'assurer que MUKEFI et MESKA existent dans "organisations" (table JPA).
|
||
-- Si V3.6 les a déjà insérées, ON CONFLICT (email) DO NOTHING évite le doublon.
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
|
||
INSERT INTO organisations (
|
||
id, nom, nom_court, type_organisation, statut, email, telephone,
|
||
site_web, date_fondation, numero_enregistrement, devise,
|
||
budget_annuel, cotisation_obligatoire, montant_cotisation_annuelle,
|
||
objectifs, activites_principales, partenaires, latitude, longitude,
|
||
date_creation, date_modification, cree_par, modifie_par, version, actif,
|
||
accepte_nouveaux_membres, est_organisation_racine, niveau_hierarchique,
|
||
nombre_membres, nombre_administrateurs, organisation_publique
|
||
) VALUES (
|
||
gen_random_uuid(),
|
||
'Mutuelle d''Épargne et de Crédit des Fonctionnaires et Indépendants',
|
||
'MUKEFI', 'ASSOCIATION', 'ACTIVE',
|
||
'contact@mukefi.org', '+225 07 00 00 00 01', 'https://mukefi.org',
|
||
'2020-01-15', 'MUT-CI-2020-001', 'XOF',
|
||
500000000, true, 50000,
|
||
'Favoriser l''épargne et l''accès au crédit pour les membres',
|
||
'Épargne, crédit, micro-crédit, formation financière',
|
||
'BCEAO', 5.3364, -4.0267,
|
||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'system', 'system', 0, true,
|
||
true, true, 0, 0, 0, true
|
||
) ON CONFLICT (email) DO NOTHING;
|
||
|
||
INSERT INTO organisations (
|
||
id, nom, nom_court, type_organisation, statut, email, telephone,
|
||
site_web, date_fondation, numero_enregistrement, devise,
|
||
budget_annuel, cotisation_obligatoire, montant_cotisation_annuelle,
|
||
objectifs, activites_principales, partenaires, latitude, longitude,
|
||
date_creation, date_modification, cree_par, modifie_par, version, actif,
|
||
accepte_nouveaux_membres, est_organisation_racine, niveau_hierarchique,
|
||
nombre_membres, nombre_administrateurs, organisation_publique
|
||
) VALUES (
|
||
gen_random_uuid(),
|
||
'Mouvement d''Entraide et de Solidarité de Koumassi et Adjamé',
|
||
'MESKA', 'ASSOCIATION', 'ACTIVE',
|
||
'contact@meska.org', '+225 07 00 00 00 02', 'https://meska.org',
|
||
'2018-06-20', 'ASSO-CI-2018-045', 'XOF',
|
||
25000000, true, 25000,
|
||
'Promouvoir la solidarité et l''entraide entre les membres des communes de Koumassi et Adjamé',
|
||
'Aide sociale, événements communautaires, formations, projets collectifs',
|
||
'Mairie de Koumassi, Mairie d''Adjamé', 5.2931, -3.9468,
|
||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'system', 'system', 0, true,
|
||
true, true, 0, 0, 0, true
|
||
) ON CONFLICT (email) DO NOTHING;
|
||
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
-- 1. MEMBRE : membre.mukefi@unionflow.test (MUKEFI)
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
|
||
INSERT INTO utilisateurs (
|
||
id, numero_membre, prenom, nom, email, telephone, date_naissance,
|
||
nationalite, profession, statut_compte,
|
||
date_creation, date_modification, cree_par, modifie_par, version, actif
|
||
) VALUES (
|
||
gen_random_uuid(), 'MBR-MUKEFI-001', 'Membre', 'MUKEFI',
|
||
'membre.mukefi@unionflow.test', '+22507000101', '1985-06-15',
|
||
'Ivoirien', 'Fonctionnaire', 'ACTIF',
|
||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'system', 'system', 0, true
|
||
);
|
||
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
-- 2. MEMBRE : admin.mukefi@unionflow.test (admin MUKEFI)
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
|
||
INSERT INTO utilisateurs (
|
||
id, numero_membre, prenom, nom, email, telephone, date_naissance,
|
||
nationalite, profession, statut_compte,
|
||
date_creation, date_modification, cree_par, modifie_par, version, actif
|
||
) VALUES (
|
||
gen_random_uuid(), 'MBR-MUKEFI-ADMIN', 'Admin', 'MUKEFI',
|
||
'admin.mukefi@unionflow.test', '+22507000102', '1978-04-22',
|
||
'Ivoirien', 'Administrateur', 'ACTIF',
|
||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'system', 'system', 0, true
|
||
);
|
||
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
-- 3. MEMBRE : membre.meska@unionflow.test (MESKA)
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
|
||
INSERT INTO utilisateurs (
|
||
id, numero_membre, prenom, nom, email, telephone, date_naissance,
|
||
nationalite, profession, statut_compte,
|
||
date_creation, date_modification, cree_par, modifie_par, version, actif
|
||
) VALUES (
|
||
gen_random_uuid(), 'MBR-MESKA-001', 'Membre', 'MESKA',
|
||
'membre.meska@unionflow.test', '+22507000201', '1990-11-30',
|
||
'Ivoirienne', 'Commercante', 'ACTIF',
|
||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'system', 'system', 0, true
|
||
);
|
||
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
-- 4. RATTACHEMENTS membres_organisations
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
|
||
INSERT INTO membres_organisations (
|
||
id, utilisateur_id, organisation_id, statut_membre, date_adhesion,
|
||
date_creation, date_modification, cree_par, modifie_par, version, actif
|
||
) VALUES (
|
||
gen_random_uuid(),
|
||
(SELECT id FROM utilisateurs WHERE email = 'membre.mukefi@unionflow.test'),
|
||
(SELECT id FROM organisations WHERE nom_court = 'MUKEFI' LIMIT 1),
|
||
'ACTIF', '2020-03-01',
|
||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'system', 'system', 0, true
|
||
);
|
||
|
||
INSERT INTO membres_organisations (
|
||
id, utilisateur_id, organisation_id, statut_membre, date_adhesion,
|
||
date_creation, date_modification, cree_par, modifie_par, version, actif
|
||
) VALUES (
|
||
gen_random_uuid(),
|
||
(SELECT id FROM utilisateurs WHERE email = 'admin.mukefi@unionflow.test'),
|
||
(SELECT id FROM organisations WHERE nom_court = 'MUKEFI' LIMIT 1),
|
||
'ACTIF', '2020-01-15',
|
||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'system', 'system', 0, true
|
||
);
|
||
|
||
INSERT INTO membres_organisations (
|
||
id, utilisateur_id, organisation_id, statut_membre, date_adhesion,
|
||
date_creation, date_modification, cree_par, modifie_par, version, actif
|
||
) VALUES (
|
||
gen_random_uuid(),
|
||
(SELECT id FROM utilisateurs WHERE email = 'membre.meska@unionflow.test'),
|
||
(SELECT id FROM organisations WHERE nom_court = 'MESKA' LIMIT 1),
|
||
'ACTIF', '2018-09-01',
|
||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'system', 'system', 0, true
|
||
);
|
||
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
-- 5. COTISATIONS pour membre.mukefi@unionflow.test
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
ALTER TABLE cotisations ADD COLUMN IF NOT EXISTS libelle VARCHAR(500);
|
||
|
||
-- 2023 – PAYÉE
|
||
INSERT INTO cotisations (
|
||
id, numero_reference, membre_id, organisation_id,
|
||
type_cotisation, libelle, montant_du, montant_paye, code_devise,
|
||
statut, date_echeance, date_paiement, annee, periode,
|
||
date_creation, date_modification, cree_par, modifie_par, version, actif, nombre_rappels, recurrente
|
||
) VALUES (
|
||
gen_random_uuid(), 'COT-MUKEFI-2023-001',
|
||
(SELECT id FROM utilisateurs WHERE email = 'membre.mukefi@unionflow.test'),
|
||
(SELECT id FROM organisations WHERE nom_court = 'MUKEFI' LIMIT 1),
|
||
'ANNUELLE', 'Cotisation annuelle 2023', 50000, 50000, 'XOF',
|
||
'PAYEE', '2023-12-31', '2023-03-15 10:00:00', 2023, '2023',
|
||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'system', 'system', 0, true, 0, true
|
||
);
|
||
|
||
-- 2024 – PAYÉE
|
||
INSERT INTO cotisations (
|
||
id, numero_reference, membre_id, organisation_id,
|
||
type_cotisation, libelle, montant_du, montant_paye, code_devise,
|
||
statut, date_echeance, date_paiement, annee, periode,
|
||
date_creation, date_modification, cree_par, modifie_par, version, actif, nombre_rappels, recurrente
|
||
) VALUES (
|
||
gen_random_uuid(), 'COT-MUKEFI-2024-001',
|
||
(SELECT id FROM utilisateurs WHERE email = 'membre.mukefi@unionflow.test'),
|
||
(SELECT id FROM organisations WHERE nom_court = 'MUKEFI' LIMIT 1),
|
||
'ANNUELLE', 'Cotisation annuelle 2024', 50000, 50000, 'XOF',
|
||
'PAYEE', '2024-12-31', '2024-02-20 09:30:00', 2024, '2024',
|
||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'system', 'system', 0, true, 0, true
|
||
);
|
||
|
||
-- 2025 – EN ATTENTE
|
||
INSERT INTO cotisations (
|
||
id, numero_reference, membre_id, organisation_id,
|
||
type_cotisation, libelle, montant_du, montant_paye, code_devise,
|
||
statut, date_echeance, annee, periode,
|
||
date_creation, date_modification, cree_par, modifie_par, version, actif, nombre_rappels, recurrente
|
||
) VALUES (
|
||
gen_random_uuid(), 'COT-MUKEFI-2025-001',
|
||
(SELECT id FROM utilisateurs WHERE email = 'membre.mukefi@unionflow.test'),
|
||
(SELECT id FROM organisations WHERE nom_court = 'MUKEFI' LIMIT 1),
|
||
'ANNUELLE', 'Cotisation annuelle 2025', 50000, 0, 'XOF',
|
||
'EN_ATTENTE', '2025-12-31', 2025, '2025',
|
||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'system', 'system', 0, true, 0, true
|
||
);
|
||
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
-- 6. COTISATION pour membre.meska@unionflow.test
|
||
-- ─────────────────────────────────────────────────────────────────────────────
|
||
|
||
INSERT INTO cotisations (
|
||
id, numero_reference, membre_id, organisation_id,
|
||
type_cotisation, libelle, montant_du, montant_paye, code_devise,
|
||
statut, date_echeance, date_paiement, annee, periode,
|
||
date_creation, date_modification, cree_par, modifie_par, version, actif, nombre_rappels, recurrente
|
||
) VALUES (
|
||
gen_random_uuid(), 'COT-MESKA-2024-001',
|
||
(SELECT id FROM utilisateurs WHERE email = 'membre.meska@unionflow.test'),
|
||
(SELECT id FROM organisations WHERE nom_court = 'MESKA' LIMIT 1),
|
||
'ANNUELLE', 'Cotisation annuelle 2024', 25000, 25000, 'XOF',
|
||
'PAYEE', '2024-12-31', '2024-01-10 14:00:00', 2024, '2024',
|
||
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, 'system', 'system', 0, true, 0, true
|
||
);
|
||
|