# Diagramme de Classes - UnionFlow

## Vue d'ensemble

UnionFlow est une application de gestion d'organisations (Lions Clubs, Associations, Coopératives, etc.) avec gestion des membres, cotisations, événements et système de solidarité.

**Architecture modulaire :**
- `unionflow-server-api` : Contrats API (DTOs, Enums, Interfaces)
- `unionflow-server-impl-quarkus` : Implémentation serveur (Entités JPA, Services, Resources REST)
- `unionflow-client-quarkus-primefaces-freya` : Client web JSF/PrimeFaces

---

## 1. ENTITÉS JPA (Server Implementation)

### 1.1 BaseEntity (Classe abstraite)

```java
@MappedSuperclass
public abstract class BaseEntity {
    - UUID id (PK, @GeneratedValue UUID)
    - LocalDateTime dateCreation
    - LocalDateTime dateModification
    - String creePar
    - String modifiePar
    - Long version (@Version)
    - Boolean actif
    
    + onCreate() @PrePersist
    + onUpdate() @PreUpdate
}
```

**Relations :** Toutes les entités héritent de `BaseEntity`

---

### 1.2 Membre

```java
@Entity
@Table(name = "membres")
public class Membre extends BaseEntity {
    - String numeroMembre (unique, @NotBlank)
    - String prenom (@NotBlank)
    - String nom (@NotBlank)
    - String email (unique, @Email, @NotBlank)
    - String motDePasse
    - String telephone
    - LocalDate dateNaissance (@NotNull)
    - LocalDate dateAdhesion (@NotNull)
    - String roles
    
    // Relations
    - Organisation organisation (@ManyToOne, LAZY)
    
    + getNomComplet(): String
    + isMajeur(): boolean
    + getAge(): int
}
```

**Relations :**
- `@ManyToOne` → `Organisation` (membre appartient à une organisation)

---

### 1.3 Organisation

```java
@Entity
@Table(name = "organisations")
public class Organisation extends BaseEntity {
    - String nom (@NotBlank)
    - String nomCourt
    - String typeOrganisation (@NotBlank)
    - String statut (@NotBlank)
    - String description
    - LocalDate dateFondation
    - String numeroEnregistrement (unique)
    
    // Contact
    - String email (unique, @Email, @NotBlank)
    - String telephone
    - String telephoneSecondaire
    - String emailSecondaire
    
    // Adresse
    - String adresse
    - String ville
    - String codePostal
    - String region
    - String pays
    - BigDecimal latitude
    - BigDecimal longitude
    
    // Web
    - String siteWeb
    - String logo
    - String reseauxSociaux
    
    // Hiérarchie
    - UUID organisationParenteId
    - Integer niveauHierarchique
    
    // Statistiques
    - Integer nombreMembres
    - Integer nombreAdministrateurs
    
    // Finances
    - BigDecimal budgetAnnuel
    - String devise
    - Boolean cotisationObligatoire
    - BigDecimal montantCotisationAnnuelle
    
    // Compléments
    - String objectifs
    - String activitesPrincipales
    - String certifications
    - String partenaires
    - String notes
    - Boolean organisationPublique
    - Boolean accepteNouveauxMembres
    
    // Relations
    - List<Membre> membres (@OneToMany, mappedBy="organisation", LAZY)
    
    + getNomComplet(): String
    + getAncienneteAnnees(): int
    + isRecente(): boolean
    + isActive(): boolean
    + ajouterMembre()
    + retirerMembre()
    + activer(String utilisateur)
    + suspendre(String utilisateur)
    + dissoudre(String utilisateur)
}
```

**Relations :**
- `@OneToMany` → `Membre` (une organisation a plusieurs membres)
- Auto-référence via `organisationParenteId` (hiérarchie)

---

### 1.4 TypeOrganisationEntity

```java
@Entity
@Table(name = "uf_type_organisation")
public class TypeOrganisationEntity extends BaseEntity {
    - String code (unique, @NotBlank)
    - String libelle (@NotBlank)
    - String description
    - Integer ordreAffichage
}
```

**Relations :** Aucune (entité de référence)

---

### 1.5 Cotisation

```java
@Entity
@Table(name = "cotisations")
public class Cotisation extends BaseEntity {
    - String numeroReference (unique, @NotBlank)
    - Membre membre (@ManyToOne, @NotNull)
    - String typeCotisation (@NotBlank)
    - BigDecimal montantDu (@NotNull, @DecimalMin(0))
    - BigDecimal montantPaye (@DecimalMin(0))
    - String codeDevise (@NotBlank, @Pattern("^[A-Z]{3}$"))
    - String statut (@NotBlank, @Pattern)
    - LocalDate dateEcheance (@NotNull)
    - LocalDateTime datePaiement
    - String description
    - String periode
    - Integer annee (@NotNull, @Min(2020), @Max(2100))
    - Integer mois (@Min(1), @Max(12))
    - String observations
    - Boolean recurrente
    - Integer nombreRappels
    - LocalDateTime dateDernierRappel
    - UUID valideParId
    - String nomValidateur
    - LocalDateTime dateValidation
    - String methodePaiement
    - String referencePaiement
    
    + getMontantRestant(): BigDecimal
    + isEntierementPayee(): boolean
    + isEnRetard(): boolean
    + genererNumeroReference(): String (static)
}
```

**Relations :**
- `@ManyToOne` → `Membre` (une cotisation appartient à un membre)

---

### 1.6 Adhesion

```java
@Entity
@Table(name = "adhesions")
public class Adhesion extends BaseEntity {
    - String numeroReference (unique, @NotBlank)
    - Membre membre (@ManyToOne, @NotNull)
    - Organisation organisation (@ManyToOne, @NotNull)
    - LocalDate dateDemande (@NotNull)
    - BigDecimal fraisAdhesion (@NotNull, @DecimalMin(0))
    - BigDecimal montantPaye (@DecimalMin(0))
    - String codeDevise (@NotBlank, @Pattern("^[A-Z]{3}$"))
    - String statut (@NotBlank, @Pattern)
    - LocalDate dateApprobation
    - LocalDateTime datePaiement
    - String methodePaiement
    - String referencePaiement
    - String motifRejet
    - String observations
    - String approuvePar
    - LocalDate dateValidation
    
    + isPayeeIntegralement(): boolean
    + isEnAttentePaiement(): boolean
    + getMontantRestant(): BigDecimal
}
```

**Relations :**
- `@ManyToOne` → `Membre`
- `@ManyToOne` → `Organisation`

---

### 1.7 Evenement

```java
@Entity
@Table(name = "evenements")
public class Evenement extends BaseEntity {
    - String titre (@NotBlank, @Size(3-200))
    - String description (@Size(max=2000))
    - LocalDateTime dateDebut (@NotNull)
    - LocalDateTime dateFin
    - String lieu (@Size(max=500))
    - String adresse (@Size(max=1000))
    - TypeEvenement typeEvenement (@Enumerated)
    - StatutEvenement statut (@Enumerated)
    - Integer capaciteMax (@Min(0))
    - BigDecimal prix (@DecimalMin("0.00"))
    - Boolean inscriptionRequise
    - LocalDateTime dateLimiteInscription
    - String instructionsParticulieres
    - String contactOrganisateur
    - String materielRequis
    - Boolean visiblePublic
    - Boolean actif
    
    // Relations
    - Organisation organisation (@ManyToOne, LAZY)
    - Membre organisateur (@ManyToOne, LAZY)
    - List<InscriptionEvenement> inscriptions (@OneToMany, mappedBy="evenement", LAZY)
    
    enum TypeEvenement { ASSEMBLEE_GENERALE, REUNION, FORMATION, ... }
    enum StatutEvenement { PLANIFIE, CONFIRME, EN_COURS, TERMINE, ANNULE, REPORTE }
    
    + isOuvertAuxInscriptions(): boolean
    + getNombreInscrits(): int
    + isComplet(): boolean
    + isEnCours(): boolean
    + isTermine(): boolean
    + getDureeEnHeures(): Long
    + getPlacesRestantes(): Integer
    + isMemberInscrit(UUID membreId): boolean
    + getTauxRemplissage(): Double
}
```

**Relations :**
- `@ManyToOne` → `Organisation`
- `@ManyToOne` → `Membre` (organisateur)
- `@OneToMany` → `InscriptionEvenement`

---

### 1.8 InscriptionEvenement

```java
@Entity
@Table(name = "inscriptions_evenement")
public class InscriptionEvenement extends BaseEntity {
    - Membre membre (@ManyToOne, @NotNull)
    - Evenement evenement (@ManyToOne, @NotNull)
    - LocalDateTime dateInscription
    - StatutInscription statut (@Enumerated)
    - String commentaire
    
    enum StatutInscription { CONFIRMEE, EN_ATTENTE, ANNULEE, REFUSEE }
    
    + isConfirmee(): boolean
    + isEnAttente(): boolean
    + isAnnulee(): boolean
    + confirmer()
    + annuler(String commentaire)
    + mettreEnAttente(String commentaire)
    + refuser(String commentaire)
}
```

**Relations :**
- `@ManyToOne` → `Membre`
- `@ManyToOne` → `Evenement`

---

### 1.9 DemandeAide

```java
@Entity
@Table(name = "demandes_aide")
public class DemandeAide extends BaseEntity {
    - String titre (@NotBlank)
    - String description (@NotBlank, TEXT)
    - TypeAide typeAide (@Enumerated, @NotNull)
    - StatutAide statut (@Enumerated, @NotNull)
    - BigDecimal montantDemande
    - BigDecimal montantApprouve
    - LocalDateTime dateDemande
    - LocalDateTime dateEvaluation
    - LocalDateTime dateVersement
    - Membre demandeur (@ManyToOne, @NotNull)
    - Membre evaluateur (@ManyToOne)
    - Organisation organisation (@ManyToOne, @NotNull)
    - String justification (TEXT)
    - String commentaireEvaluation (TEXT)
    - Boolean urgence
    - String documentsFournis
    
    + isEnAttente(): boolean
    + isApprouvee(): boolean
    + isRejetee(): boolean
    + isUrgente(): boolean
    + getPourcentageApprobation(): BigDecimal
}
```

**Relations :**
- `@ManyToOne` → `Membre` (demandeur)
- `@ManyToOne` → `Membre` (evaluateur)
- `@ManyToOne` → `Organisation`

---

### 1.10 AuditLog

```java
@Entity
@Table(name = "audit_logs")
public class AuditLog extends BaseEntity {
    - String typeAction
    - String severite
    - String utilisateur
    - String role
    - String module
    - String description
    - String details (TEXT)
    - String ipAddress
    - String userAgent
    - String sessionId
    - LocalDateTime dateHeure
    - String donneesAvant (TEXT)
    - String donneesApres (TEXT)
    - String entiteId
    - String entiteType
}
```

**Relations :** Aucune (entité de log)

---

## 2. REPOSITORIES (Server Implementation)

### 2.1 BaseRepository<T>

```java
public abstract class BaseRepository<T extends BaseEntity> {
    @PersistenceContext
    protected EntityManager entityManager;
    
    protected final Class<T> entityClass;
    
    + findById(UUID id): T
    + findByIdOptional(UUID id): Optional<T>
    + persist(T entity): void @Transactional
    + update(T entity): T @Transactional
    + delete(T entity): void @Transactional
    + deleteById(UUID id): boolean @Transactional
    + listAll(): List<T>
    + count(): long
    + existsById(UUID id): boolean
    + getEntityManager(): EntityManager
}
```

**Relations :**
- Générique sur `BaseEntity`
- Utilisé par tous les repositories

---

### 2.2 MembreRepository

```java
@ApplicationScoped
public class MembreRepository extends BaseRepository<Membre> {
    + findByEmail(String email): Optional<Membre>
    + findByNumeroMembre(String numero): Optional<Membre>
    + findAllActifs(): List<Membre>
    + countActifs(): long
    + findByNomOrPrenom(String recherche): List<Membre>
    + findAllActifs(Page page, Sort sort): List<Membre>
    + findByNomOrPrenom(String recherche, Page page, Sort sort): List<Membre>
    + countNouveauxMembres(LocalDate depuis): long
    + findByStatut(boolean actif, Page page, Sort sort): List<Membre>
    + findByTrancheAge(int ageMin, int ageMax, Page page, Sort sort): List<Membre>
    + rechercheAvancee(...): List<Membre>
    + countMembresActifs(UUID organisationId, LocalDateTime debut, LocalDateTime fin): Long
    + countMembresInactifs(UUID organisationId, LocalDateTime debut, LocalDateTime fin): Long
    + calculerMoyenneAge(UUID organisationId, LocalDateTime debut, LocalDateTime fin): Double
}
```

---

### 2.3 OrganisationRepository

```java
@ApplicationScoped
public class OrganisationRepository extends BaseRepository<Organisation> {
    + findByEmail(String email): Optional<Organisation>
    + findByNom(String nom): Optional<Organisation>
    + findByNumeroEnregistrement(String numero): Optional<Organisation>
    + findAllActives(): List<Organisation>
    + findAllActives(Page page, Sort sort): List<Organisation>
    + countActives(): long
    + findByStatut(String statut, Page page, Sort sort): List<Organisation>
    + findByType(String typeOrganisation, Page page, Sort sort): List<Organisation>
    + findByVille(String ville, Page page, Sort sort): List<Organisation>
    + findByPays(String pays, Page page, Sort sort): List<Organisation>
    + findByRegion(String region, Page page, Sort sort): List<Organisation>
    + findByOrganisationParente(UUID parenteId, Page page, Sort sort): List<Organisation>
    + findOrganisationsRacines(Page page, Sort sort): List<Organisation>
    + findByNomOrNomCourt(String recherche, Page page, Sort sort): List<Organisation>
    + rechercheAvancee(...): List<Organisation>
    + countNouvellesOrganisations(LocalDate depuis): long
    + findOrganisationsPubliques(Page page, Sort sort): List<Organisation>
    + findOrganisationsOuvertes(Page page, Sort sort): List<Organisation>
    + countByStatut(String statut): long
    + countByType(String typeOrganisation): long
}
```

---

### 2.4 Autres Repositories

- `TypeOrganisationRepository extends BaseRepository<TypeOrganisationEntity>`
- `CotisationRepository extends BaseRepository<Cotisation>`
- `AdhesionRepository extends BaseRepository<Adhesion>`
- `EvenementRepository extends BaseRepository<Evenement>`
- `DemandeAideRepository extends BaseRepository<DemandeAide>`
- `AuditLogRepository extends BaseRepository<AuditLog>`

---

## 3. DTOs SERVEUR (Server API)

### 3.1 BaseDTO (Classe abstraite)

```java
public abstract class BaseDTO implements Serializable {
    - UUID id
    - LocalDateTime dateCreation (@JsonFormat)
    - LocalDateTime dateModification (@JsonFormat)
    - String creePar
    - String modifiePar
    - Long version
    - Boolean actif
    
    + marquerCommeNouveau(String utilisateur): void
    + marquerCommeModifie(String utilisateur): void
    + desactiver(String utilisateur): void
    + reactiver(String utilisateur): void
    + isNouveau(): boolean
    + isActif(): boolean
}
```

**Relations :** Tous les DTOs héritent de `BaseDTO`

---

### 3.2 MembreDTO

```java
public class MembreDTO extends BaseDTO {
    - String numeroMembre (@Size(max=50))
    - String nom (@NotBlank, @Size(2-50), @Pattern)
    - String prenom (@NotBlank, @Size(2-50), @Pattern)
    - String email (@NotBlank, @Email, @Size(max=100))
    - String telephone (@Size(max=20))
    - LocalDate dateNaissance (@Past)
    - String adresse (@Size(max=200))
    - String profession (@Size(max=100))
    - String statutMatrimonial (@Size(max=20))
    - String nationalite (@Size(max=50))
    - String numeroIdentite (@Size(max=50))
    - String typeIdentite (@Size(max=20))
    - StatutMembre statut (@NotNull)
    - UUID associationId (@NotNull)
    - String associationNom
    - LocalDate dateAdhesion
    - String region (@Size(max=50))
    - String ville (@Size(max=50))
    - String quartier (@Size(max=50))
    - String role (@Size(max=50))
    - Boolean membreBureau
    - Boolean responsable
    - String photoUrl (@Size(max=255))
    
    + getStatutLibelle(): String
    + sontDonneesValides(): boolean
}
```

---

### 3.3 OrganisationDTO

```java
public class OrganisationDTO extends BaseDTO {
    - String nom (@NotBlank, @Size)
    - String nomCourt (@Size(max=50))
    - TypeOrganisation typeOrganisation (@NotNull)
    - StatutOrganisation statut (@NotNull)
    - String description (@Size(max=2000))
    - LocalDate dateFondation
    - String numeroEnregistrement (@Size(max=100))
    - String adresse (@Size(max=500))
    - String ville (@Size(max=100))
    - String region (@Size(max=100))
    - String pays (@Size(max=100))
    - String codePostal (@Pattern)
    - BigDecimal latitude (@DecimalMin(-90), @DecimalMax(90))
    - BigDecimal longitude (@DecimalMin(-180), @DecimalMax(180))
    - String telephone (@Pattern)
    - String telephoneSecondaire (@Pattern)
    - String email (@Email, @Size(max=200))
    - String emailSecondaire (@Email, @Size(max=200))
    - String siteWeb (@Pattern, @Size(max=500))
    - String logo (@Size(max=500))
    - UUID organisationParenteId
    - String nomOrganisationParente
    - Integer niveauHierarchique
    - Integer nombreMembres
    - Integer nombreAdministrateurs
    - BigDecimal budgetAnnuel (@DecimalMin(0), @Digits)
    - String devise (@Pattern("^[A-Z]{3}$"))
    - String objectifs (@Size(max=2000))
    - String activitesPrincipales (@Size(max=2000))
    - String reseauxSociaux (@Size(max=1000))
    - String certifications (@Size(max=500))
    - String partenaires (@Size(max=1000))
    - String notes (@Size(max=1000))
    - Boolean organisationPublique
    - Boolean accepteNouveauxMembres
    - Boolean cotisationObligatoire
    - BigDecimal montantCotisationAnnuelle (@DecimalMin(0), @Digits)
    
    + estActive(): boolean
    + estInactive(): boolean
    + estSuspendue(): boolean
    + estEnCreation(): boolean
    + estDissoute(): boolean
    + getAncienneteAnnees(): int
    + getAncienneteMois(): int
    + possedGeolocalisation(): boolean
    + estOrganisationRacine(): boolean
    + possedeSousOrganisations(): boolean
    + getNomAffichage(): String
    + getAdresseComplete(): String
    + getRatioAdministrateurs(): double
    + hasBudget(): boolean
    + activer(String utilisateur): void
    + suspendre(String utilisateur): void
    + dissoudre(String utilisateur): void
    + desactiver(String utilisateur): void
    + mettreAJourNombreMembres(int nouveauNombre, String utilisateur): void
    + ajouterMembre(String utilisateur): void
    + retirerMembre(String utilisateur): void
}
```

---

### 3.4 TypeOrganisationDTO

```java
public class TypeOrganisationDTO extends BaseDTO {
    - String code (@NotBlank, @Size(max=50))
    - String libelle (@NotBlank, @Size(max=150))
    - String description (@Size(max=500))
    - Integer ordreAffichage
    - Boolean actif
}
```

---

### 3.5 CotisationDTO

```java
public class CotisationDTO extends BaseDTO {
    - String numeroReference (@NotBlank, @Size(max=50))
    - UUID membreId (@NotNull)
    - String numeroMembre
    - String nomMembre
    - UUID associationId (@NotNull)
    - String nomAssociation
    - String typeCotisation (@NotNull, @Pattern)
    - String libelle (@NotBlank, @Size(max=100))
    - String description (@Size(max=500))
    - BigDecimal montantDu (@NotNull, @DecimalMin(0, inclusive=false))
    - BigDecimal montantPaye (@DecimalMin(0))
    - String codeDevise (@NotBlank, @Size(3))
    - String statut (@NotNull, @Pattern)
    - LocalDate dateEcheance (@NotNull)
    - LocalDateTime datePaiement
    - String methodePaiement (@Pattern)
    - String referencePaiement (@Size(max=100))
    - String periode (@Size(max=50))
    - Integer annee (@Min(2020), @Max(2050))
    - Integer mois (@Min(1), @Max(12))
    - String observations (@Size(max=500))
    - Boolean recurrente
    - Integer nombreRappels (@Min(0))
    - LocalDateTime dateDernierRappel
    - UUID validePar
    - String nomValidateur
    
    + isPayeeIntegralement(): boolean
    + isEnRetard(): boolean
    + getMontantRestant(): BigDecimal
    + getPourcentagePaiement(): int
    + getJoursRetard(): long
    + getTypeCotisationLibelle(): String
    + getStatutLibelle(): String
    + getMethodePaiementLibelle(): String
    + mettreAJourStatut(): void
    + marquerCommePaye(BigDecimal montant, String methode, String reference): void
}
```

---

### 3.6 AdhesionDTO

```java
public class AdhesionDTO extends BaseDTO {
    - String numeroReference (@NotBlank, @Size(max=50))
    - UUID membreId (@NotNull)
    - String numeroMembre
    - String nomMembre
    - String emailMembre
    - UUID organisationId (@NotNull)
    - String nomOrganisation
    - LocalDate dateDemande (@NotNull)
    - BigDecimal fraisAdhesion (@NotNull, @DecimalMin(0, inclusive=false))
    - BigDecimal montantPaye (@DecimalMin(0))
    - String codeDevise (@NotBlank, @Pattern("^[A-Z]{3}$"))
    - String statut (@NotBlank, @Pattern)
    - LocalDate dateApprobation
    - LocalDateTime datePaiement
    - String methodePaiement (@Pattern)
    - String referencePaiement (@Size(max=100))
    - String motifRejet (@Size(max=1000))
    - String observations (@Size(max=1000))
    - String approuvePar (@Size(max=255))
    - LocalDate dateValidation
    
    + isPayeeIntegralement(): boolean
    + isEnAttentePaiement(): boolean
    + getMontantRestant(): BigDecimal
    + getPourcentagePaiement(): int
    + getJoursDepuisDemande(): long
    + getStatutLibelle(): String
    + getStatutSeverity(): String
    + getStatutIcon(): String
    + getMethodePaiementLibelle(): String
    + getDateDemandeFormatee(): String
    + getDateApprobationFormatee(): String
    + getDatePaiementFormatee(): String
    + getFraisAdhesionFormatte(): String
    + getMontantPayeFormatte(): String
    + getMontantRestantFormatte(): String
}
```

---

### 3.7 EvenementDTO

```java
public class EvenementDTO extends BaseDTO {
    - String titre (@NotBlank, @Size(3-200))
    - String description (@Size(max=2000))
    - TypeEvenementMetier typeEvenement (@NotNull)
    - StatutEvenement statut (@NotNull)
    - PrioriteEvenement priorite
    - LocalDate dateDebut (@NotNull, @Future)
    - LocalDate dateFin
    - LocalTime heureDebut
    - LocalTime heureFin
    - String lieu (@NotBlank, @Size(max=100))
    - String adresse (@Size(max=200))
    - String ville (@Size(max=50))
    - String region (@Size(max=50))
    - BigDecimal latitude (@DecimalMin(-90), @DecimalMax(90))
    - BigDecimal longitude (@DecimalMin(-180), @DecimalMax(180))
    - UUID associationId (@NotNull)
    - String nomAssociation
    - String organisateur (@Size(max=100))
    - String emailOrganisateur (@Email, @Size(max=100))
    - String telephoneOrganisateur (@Pattern)
    - Integer capaciteMax (@Min(1), @Max(10000))
    - Integer participantsInscrits (@Min(0))
    - Integer participantsPresents (@Min(0))
    - BigDecimal budget (@DecimalMin(0), @Digits)
    - BigDecimal coutReel (@DecimalMin(0), @Digits)
    - String codeDevise (@Pattern)
    - Boolean inscriptionObligatoire
    - LocalDate dateLimiteInscription
    - Boolean evenementPublic
    - Boolean recurrent
    - String frequenceRecurrence (@Pattern)
    - String instructions (@Size(max=500))
    - String materielNecessaire (@Size(max=500))
    - String conditionsMeteo (@Size(max=100))
    - String imageUrl (@Size(max=255))
    - String couleurTheme (@Pattern)
    - LocalDateTime dateAnnulation
    - String raisonAnnulation (@Size(max=500))
    - Long annulePar
    - String nomAnnulateur
    
    + estEnCours(): boolean
    + estTermine(): boolean
    + estAnnule(): boolean
    + estComplet(): boolean
    + getPlacesDisponibles(): int
    + getTauxRemplissage(): int
    + getTauxPresence(): int
    + sontInscriptionsOuvertes(): boolean
    + getDureeEnHeures(): long
    + estEvenementMultiJours(): boolean
    + getTypeEvenementLibelle(): String
    + getStatutLibelle(): String
    + getPrioriteLibelle(): String
    + getAdresseComplete(): String
    + hasCoordonnees(): boolean
    + getEcartBudgetaire(): BigDecimal
    + estBudgetDepasse(): boolean
}
```

---

### 3.8 DemandeAideDTO

```java
public class DemandeAideDTO extends BaseDTO {
    - String numeroReference (@Pattern)
    - TypeAide typeAide (@NotNull)
    - String titre (@NotBlank, @Size(3-200))
    - String description (@NotBlank, @Size(3-2000))
    - String justification (@Size(max=2000))
    - BigDecimal montantDemande (@DecimalMin(0, inclusive=false), @Digits)
    - BigDecimal montantApprouve (@DecimalMin(0, inclusive=false), @Digits)
    - BigDecimal montantVerse (@DecimalMin(0, inclusive=false), @Digits)
    - String devise (@Pattern, default="XOF")
    - UUID membreDemandeurId (@NotNull)
    - String nomDemandeur
    - String numeroMembreDemandeur
    - String evaluateurId
    - String evaluateurNom
    - String approvateurId
    - String approvateurNom
    - UUID associationId (@NotNull)
    - String nomAssociation
    - StatutAide statut (@NotNull, default=EN_ATTENTE)
    - PrioriteAide priorite (@NotNull, default=NORMALE)
    - String motifRejet (@Size(max=500))
    - String commentairesEvaluateur (@Size(max=1000))
    - LocalDateTime dateSoumission
    - LocalDateTime dateLimiteTraitement
    - LocalDateTime dateEvaluation
    - LocalDateTime dateApprobation
    - LocalDateTime dateVersement
    - LocalDateTime dateCloture
    - List<PieceJustificativeDTO> piecesJustificatives
    - List<BeneficiaireAideDTO> beneficiaires
    - List<HistoriqueStatutDTO> historiqueStatuts
    - List<CommentaireAideDTO> commentaires
    - Map<String, Object> donneesPersonnalisees
    - List<String> tags
    - Boolean estConfidentielle
    - Boolean necessiteSuivi
    - Double scorePriorite
    - Integer nombreVues
    - LocalisationDTO localisation
    - ContactUrgenceDTO contactUrgence
    - LocalDate dateLimite
    - Boolean justificatifsFournis
    - String documentsJoints (@Size(max=1000))
    - LocalDate dateDebutAide
    - LocalDate dateFinAide
    - UUID membreAidantId
    - String nomAidant
    - String modeVersement (@Size(max=50))
    - String numeroTransaction (@Size(max=100))
    - UUID rejeteParId
    - String rejetePar
    - LocalDateTime dateRejet
    - String raisonRejet (@Size(max=500))
    
    + estModifiable(): boolean
    + peutEtreAnnulee(): boolean
    + estUrgente(): boolean
    + estTerminee(): boolean
    + estEnSucces(): boolean
    + getPourcentageAvancement(): double
    + getDelaiRestantHeures(): long
    + estDelaiDepasse(): boolean
    + getDureeTraitementJours(): long
    + getStatutLibelle(): String
    + getPrioriteLibelle(): String
    + approuver(UUID evaluateurId, String nomEvaluateur, BigDecimal montantApprouve, String commentaires): void
    + rejeter(UUID evaluateurId, String nomEvaluateur, String raison): void
    + demarrerAide(UUID aidantId, String nomAidant): void
    + terminerAvecVersement(BigDecimal montantVerse, String modeVersement, String numeroTransaction): void
    + incrementerVues(): void
    + genererNumeroReference(): String (static)
}
```

---

### 3.9 AuditLogDTO

```java
public class AuditLogDTO extends BaseDTO {
    - String typeAction
    - String severite
    - String utilisateur
    - String role
    - String module
    - String description
    - String details
    - String ipAddress
    - String userAgent
    - String sessionId
    - LocalDateTime dateHeure
    - String donneesAvant
    - String donneesApres
    - String entiteId
    - String entiteType
}
```

---

## 4. ENUMS (Server API)

### 4.1 StatutMembre

```java
public enum StatutMembre {
    ACTIF("Actif"),
    INACTIF("Inactif"),
    SUSPENDU("Suspendu"),
    DEMISSIONNAIRE("Démissionnaire"),
    EXCLU("Exclu");
    
    - String libelle
    + getLibelle(): String
}
```

---

### 4.2 StatutOrganisation

```java
public enum StatutOrganisation {
    ACTIVE("Active"),
    INACTIVE("Inactive"),
    SUSPENDUE("Suspendue"),
    EN_CREATION("En création"),
    DISSOUTE("Dissoute");
    
    - String libelle
    + getLibelle(): String
}
```

---

### 4.3 TypeOrganisation

```java
public enum TypeOrganisation {
    LIONS_CLUB("Lions Club"),
    ASSOCIATION("Association"),
    FEDERATION("Fédération"),
    COOPERATIVE("Coopérative"),
    MUTUELLE("Mutuelle"),
    SYNDICAT("Syndicat"),
    FONDATION("Fondation"),
    ONG("ONG");
    
    - String libelle
    + getLibelle(): String
}
```

---

### 4.4 StatutCotisation

```java
public enum StatutCotisation {
    EN_ATTENTE("En attente"),
    PAYEE("Payée"),
    PARTIELLEMENT_PAYEE("Partiellement payée"),
    EN_RETARD("En retard"),
    ANNULEE("Annulée"),
    REMBOURSEE("Remboursée");
    
    - String libelle
    + getLibelle(): String
}
```

---

### 4.5 StatutEvenement

```java
public enum StatutEvenement {
    PLANIFIE("Planifié"),
    CONFIRME("Confirmé"),
    EN_COURS("En cours"),
    TERMINE("Terminé"),
    ANNULE("Annulé"),
    REPORTE("Reporté");
    
    - String libelle
    + getLibelle(): String
}
```

---

### 4.6 TypeEvenementMetier

```java
public enum TypeEvenementMetier {
    ASSEMBLEE_GENERALE("Assemblée Générale"),
    REUNION("Réunion"),
    FORMATION("Formation"),
    CONFERENCE("Conférence"),
    ATELIER("Atelier"),
    SEMINAIRE("Séminaire"),
    EVENEMENT_SOCIAL("Événement Social"),
    MANIFESTATION("Manifestation"),
    CELEBRATION("Célébration"),
    AUTRE("Autre");
    
    - String libelle
    + getLibelle(): String
}
```

---

### 4.7 StatutAide

```java
public enum StatutAide {
    BROUILLON("Brouillon"),
    SOUMISE("Soumise"),
    EN_ATTENTE("En attente"),
    EN_COURS_EVALUATION("En cours d'évaluation"),
    INFORMATIONS_REQUISES("Informations requises"),
    APPROUVEE("Approuvée"),
    APPROUVEE_PARTIELLEMENT("Approuvée partiellement"),
    EN_COURS_TRAITEMENT("En cours de traitement"),
    EN_COURS_VERSEMENT("En cours de versement"),
    VERSEE("Versée"),
    LIVREE("Livrée"),
    TERMINEE("Terminée"),
    REJETEE("Rejetée"),
    ANNULEE("Annulée"),
    EXPIREE("Expirée"),
    SUSPENDUE("Suspendue"),
    EN_SUIVI("En suivi"),
    CLOTUREE("Clôturée");
    
    - String libelle
    + permetModification(): boolean
    + permetAnnulation(): boolean
    + isEstFinal(): boolean
    + isSucces(): boolean
    + getLibelle(): String
}
```

---

### 4.8 TypeAide

```java
public enum TypeAide {
    FINANCIERE("Aide financière"),
    MATERIELLE("Aide matérielle"),
    ALIMENTAIRE("Aide alimentaire"),
    MEDICALE("Aide médicale"),
    SCOLAIRE("Aide scolaire"),
    LOGEMENT("Aide au logement"),
    EMPLOI("Aide à l'emploi"),
    FORMATION("Aide à la formation"),
    AUTRE("Autre");
    
    - String libelle
    + getLibelle(): String
}
```

---

### 4.9 PrioriteAide

```java
public enum PrioriteAide {
    BASSE("Basse"),
    NORMALE("Normale"),
    HAUTE("Haute"),
    URGENTE("Urgente"),
    CRITIQUE("Critique");
    
    - String libelle
    + isUrgente(): boolean
    + getLibelle(): String
}
```

---

## 5. SERVICES SERVEUR (Server Implementation)

### 5.1 MembreService

```java
@ApplicationScoped
public class MembreService {
    @Inject MembreRepository membreRepository;
    @PersistenceContext EntityManager entityManager;
    
    + creerMembre(Membre membre): Membre @Transactional
    + mettreAJourMembre(UUID id, Membre membreMiseAJour): Membre @Transactional
    + desactiverMembre(UUID id): void @Transactional
    + genererNumeroMembre(): String (private)
    + compterMembresActifs(): long
    + listerMembresActifs(Page page, Sort sort): List<Membre>
    + rechercherMembres(String recherche, Page page, Sort sort): List<Membre>
    + obtenirStatistiquesAvancees(): Map<String, Object>
    + convertToDTO(Membre membre): MembreDTO
    + convertFromDTO(MembreDTO dto): Membre
    + convertToDTOList(List<Membre> membres): List<MembreDTO>
    + updateFromDTO(Membre membre, MembreDTO dto): void
    + rechercheAvancee(MembreSearchCriteria criteria, Page page, Sort sort): MembreSearchResultDTO
}
```

**Dépendances :**
- `MembreRepository`
- `EntityManager`

---

### 5.2 OrganisationService

```java
@ApplicationScoped
public class OrganisationService {
    @Inject OrganisationRepository organisationRepository;
    
    + creerOrganisation(Organisation organisation): Organisation @Transactional
    + mettreAJourOrganisation(UUID id, Organisation organisationMiseAJour, String utilisateur): Organisation @Transactional
    + supprimerOrganisation(UUID id, String utilisateur): void @Transactional
    + trouverParId(UUID id): Optional<Organisation>
    + trouverParEmail(String email): Optional<Organisation>
    + listerOrganisationsActives(): List<Organisation>
    + listerOrganisationsActives(int page, int size): List<Organisation>
    + rechercherOrganisations(String recherche, int page, int size): List<Organisation>
    + rechercheAvancee(...): List<Organisation>
    + activerOrganisation(UUID id, String utilisateur): Organisation @Transactional
    + suspendreOrganisation(UUID id, String utilisateur): Organisation @Transactional
    + obtenirStatistiques(): Map<String, Object>
    + convertToDTO(Organisation organisation): OrganisationDTO
    + convertFromDTO(OrganisationDTO dto): Organisation
}
```

**Dépendances :**
- `OrganisationRepository`

---

### 5.3 TypeOrganisationService

```java
@ApplicationScoped
public class TypeOrganisationService {
    @Inject TypeOrganisationRepository repository;
    @Inject KeycloakService keycloakService;
    
    + listTypes(Boolean onlyActifs): List<TypeOrganisationDTO>
    + getTypeById(UUID id): Optional<TypeOrganisationDTO>
    + create(TypeOrganisationDTO dto): TypeOrganisationDTO @Transactional
    + update(UUID id, TypeOrganisationDTO dto): TypeOrganisationDTO @Transactional
    + delete(UUID id): void @Transactional
    + convertToDTO(TypeOrganisationEntity entity): TypeOrganisationDTO
    + convertFromDTO(TypeOrganisationDTO dto): TypeOrganisationEntity
}
```

**Dépendances :**
- `TypeOrganisationRepository`
- `KeycloakService`

---

### 5.4 Autres Services

- `CotisationService`
- `AdhesionService`
- `EvenementService`
- `DemandeAideService`
- `AuditService`
- `KeycloakService`
- `NotificationService`
- `ExportService`
- `PaiementService`
- `WaveService`

---

## 6. RESOURCES REST (Server Implementation)

### 6.1 MembreResource

```java
@Path("/api/membres")
@ApplicationScoped
public class MembreResource {
    @Inject MembreService membreService;
    
    @GET
    @PermitAll
    + listerMembres(@QueryParam("page") int page, @QueryParam("size") int size): List<MembreDTO>
    
    @GET
    @Path("/{id}")
    @PermitAll
    + obtenirMembre(@PathParam("id") UUID id): MembreDTO
    
    @POST
    @PermitAll
    + creerMembre(MembreDTO dto): Response
    
    @PUT
    @Path("/{id}")
    @PermitAll
    + mettreAJourMembre(@PathParam("id") UUID id, MembreDTO dto): Response
    
    @DELETE
    @Path("/{id}")
    @PermitAll
    + supprimerMembre(@PathParam("id") UUID id): Response
    
    @GET
    @Path("/recherche")
    @PermitAll
    + rechercherMembres(@QueryParam("q") String query, @QueryParam("page") int page, @QueryParam("size") int size): List<MembreDTO>
    
    @GET
    @Path("/statistiques")
    @PermitAll
    + obtenirStatistiques(): Map<String, Object>
}
```

---

### 6.2 OrganisationResource

```java
@Path("/api/organisations")
@ApplicationScoped
public class OrganisationResource {
    @Inject OrganisationService organisationService;
    
    @GET
    @PermitAll
    + listerToutes(@QueryParam("page") int page, @QueryParam("size") int size): List<OrganisationDTO>
    
    @GET
    @Path("/{id}")
    @PermitAll
    + obtenirOrganisation(@PathParam("id") UUID id): OrganisationDTO
    
    @POST
    @PermitAll
    + creerOrganisation(OrganisationDTO dto): Response
    
    @PUT
    @Path("/{id}")
    @PermitAll
    + mettreAJourOrganisation(@PathParam("id") UUID id, OrganisationDTO dto): Response
    
    @DELETE
    @Path("/{id}")
    @PermitAll
    + supprimerOrganisation(@PathParam("id") UUID id): Response
    
    @GET
    @Path("/recherche")
    @PermitAll
    + rechercheAvancee(...): List<OrganisationDTO>
    
    @POST
    @Path("/{id}/activer")
    @PermitAll
    + activerOrganisation(@PathParam("id") UUID id): Response
    
    @POST
    @Path("/{id}/suspendre")
    @PermitAll
    + suspendreOrganisation(@PathParam("id") UUID id): Response
    
    @GET
    @Path("/statistiques")
    @PermitAll
    + obtenirStatistiques(): Map<String, Object>
}
```

---

### 6.3 TypeOrganisationResource

```java
@Path("/api/types-organisations")
@ApplicationScoped
public class TypeOrganisationResource {
    @Inject TypeOrganisationService service;
    
    @GET
    @PermitAll
    + listTypes(@QueryParam("onlyActifs") String onlyActifs): List<TypeOrganisationDTO>
    
    @GET
    @Path("/{id}")
    @PermitAll
    + getTypeById(@PathParam("id") UUID id): TypeOrganisationDTO
    
    @POST
    @PermitAll
    + create(TypeOrganisationDTO dto): Response
    
    @PUT
    @Path("/{id}")
    @PermitAll
    + update(@PathParam("id") UUID id, TypeOrganisationDTO dto): Response
    
    @DELETE
    @Path("/{id}")
    @PermitAll
    + delete(@PathParam("id") UUID id): Response
}
```

---

### 6.4 Autres Resources

- `CotisationResource`
- `AdhesionResource`
- `EvenementResource`
- `DemandeAideResource`
- `AuditResource`
- `NotificationResource`
- `ExportResource`
- `DashboardResource`
- `HealthResource`
- `WaveResource`
- `PreferencesResource`

---

## 7. DTOs CLIENT (Client)

### 7.1 MembreDTO (Client)

```java
public class MembreDTO implements Serializable {
    - UUID id
    - String numeroMembre (@Size(max=50))
    - String nom (@NotBlank, @Size(2-50), @Pattern)
    - String prenom (@NotBlank, @Size(2-50), @Pattern)
    - String email (@NotBlank, @Email, @Size(max=100))
    - String telephone (@Size(max=20))
    - LocalDate dateNaissance (@Past)
    - String adresse (@Size(max=200))
    - String profession (@Size(max=100))
    - String statutMatrimonial (@Size(max=20))
    - String nationalite (@Size(max=50))
    - String numeroIdentite (@Size(max=50))
    - String typeIdentite (@Size(max=20))
    - String photoUrl (@Size(max=255))
    - String statut (@NotNull)
    - UUID associationId (@NotNull)
    - String associationNom
    - LocalDateTime dateInscription
    - LocalDateTime dateDerniereModification
    - String creePar
    - String modifiePar
    - Boolean responsable
    - LocalDate dateAdhesion
    - String region (@Size(max=50))
    - String ville (@Size(max=50))
    - String quartier (@Size(max=50))
    - String role (@Size(max=50))
    
    // Propriétés dérivées (calculées)
    + getInitiales(): String
    + getTypeMembre(): String
    + getTypeSeverity(): String
    + getTypeIcon(): String
    + getStatutIcon(): String
    + getEntite(): String
    + getAnciennete(): String
    + getCotisationStatut(): String
    + getCotisationColor(): String
    + getDernierPaiement(): String
    + getTauxParticipation(): String
    + getEvenementsAnnee(): String
}
```

---

### 7.2 AssociationDTO (Client)

```java
@JsonIgnoreProperties(ignoreUnknown = true)
public class AssociationDTO implements Serializable {
    - UUID id
    - String nom (@NotBlank)
    - String nomCourt
    - String description
    - String adresse
    - String telephone
    - String email
    - String siteWeb
    - String logo
    - String typeAssociation (@NotNull, @JsonProperty("typeOrganisation"))
    - LocalDate dateFondation (@JsonProperty("dateFondation"))
    - String numeroRegistre (@JsonProperty("numeroEnregistrement"))
    - String statut
    - Integer nombreMembres
    - Integer nombreAdministrateurs
    - String responsablePrincipal
    - String telephoneResponsable
    - String emailResponsable
    - LocalDateTime dateDerniereActivite
    - LocalDateTime dateCreation
    - LocalDateTime dateModification
    - Long version
    - Boolean actif
    - String region
    - String ville
    - String quartier
    - String pays
    - String codePostal
    - String activitesPrincipales
    - String objectifs
    - String partenaires
    - String certifications
    - String reseauxSociaux
    - String notes
    - Boolean organisationPublique
    - Boolean accepteNouveauxMembres
    - Boolean cotisationObligatoire
    - BigDecimal budgetAnnuel
    - String devise
    - BigDecimal montantCotisationAnnuelle
    - String telephoneSecondaire
    - String emailSecondaire
    - UUID organisationParenteId
    - String nomOrganisationParente
    - Integer niveauHierarchique
    - BigDecimal latitude
    - BigDecimal longitude
    
    + getTypeLibelle(): String
    + getStatutLibelle(): String
    + getStatutSeverity(): String
    + getAdresseComplete(): String
}
```

---

### 7.3 Autres DTOs Client

- `TypeOrganisationClientDTO`
- `CotisationDTO`
- `AdhesionDTO`
- `EvenementDTO`
- `DemandeAideDTO`
- `AuditLogDTO`
- `AnalyticsDataDTO`
- `WaveBalanceDTO`
- `WaveCheckoutSessionDTO`

---

## 8. SERVICES CLIENT (Client)

### 8.1 MembreService (REST Client)

```java
@RestClient
@RegisterRestClient(configKey = "unionflow-api")
public interface MembreService {
    @GET
    @Path("/api/membres")
    + listerToutes(@QueryParam("page") int page, @QueryParam("size") int size): List<MembreDTO>
    
    @GET
    @Path("/api/membres/{id}")
    + obtenirMembre(@PathParam("id") UUID id): MembreDTO
    
    @POST
    @Path("/api/membres")
    + creer(MembreDTO dto): MembreDTO
    
    @PUT
    @Path("/api/membres/{id}")
    + modifier(@PathParam("id") UUID id, MembreDTO dto): MembreDTO
    
    @DELETE
    @Path("/api/membres/{id}")
    + supprimer(@PathParam("id") UUID id): void
    
    @GET
    @Path("/api/membres/recherche")
    + rechercher(@QueryParam("q") String query, @QueryParam("page") int page, @QueryParam("size") int size): List<MembreDTO>
}
```

---

### 8.2 AssociationService (REST Client)

```java
@RestClient
@RegisterRestClient(configKey = "unionflow-api")
public interface AssociationService {
    @GET
    @Path("/api/organisations")
    + listerToutes(@QueryParam("page") int page, @QueryParam("size") int size): List<AssociationDTO>
    
    @GET
    @Path("/api/organisations/{id}")
    + obtenirOrganisation(@PathParam("id") UUID id): AssociationDTO
    
    @POST
    @Path("/api/organisations")
    + creerOrganisation(AssociationDTO dto): AssociationDTO
    
    @PUT
    @Path("/api/organisations/{id}")
    + mettreAJourOrganisation(@PathParam("id") UUID id, AssociationDTO dto): AssociationDTO
    
    @DELETE
    @Path("/api/organisations/{id}")
    + supprimerOrganisation(@PathParam("id") UUID id): void
    
    @GET
    @Path("/api/organisations/recherche")
    + rechercheAvancee(...): List<AssociationDTO>
    
    @POST
    @Path("/api/organisations/{id}/activer")
    + activerOrganisation(@PathParam("id") UUID id): void
    
    @POST
    @Path("/api/organisations/{id}/suspendre")
    + suspendreOrganisation(@PathParam("id") UUID id): void
    
    @GET
    @Path("/api/organisations/statistiques")
    + obtenirStatistiques(): Map<String, Object>
}
```

---

### 8.3 Autres Services Client

- `TypeOrganisationClientService`
- `CotisationService`
- `AdhesionService`
- `EvenementService`
- `DemandeAideService`
- `AuditService`
- `NotificationClientService`
- `ExportClientService`
- `PreferencesService`
- `WaveService`
- `ValidationService`

---

## 9. BEANS JSF (Client - View)

### 9.1 MembreInscriptionBean

```java
@Named("membreInscriptionBean")
@ViewScoped
public class MembreInscriptionBean implements Serializable {
    @Inject @RestClient MembreService membreService;
    @Inject @RestClient AssociationService associationService;
    @Inject ValidationService validationService;
    
    // Champs du formulaire
    - String prenom
    - String nom
    - LocalDate dateNaissance
    - String sexe
    - String email
    - String telephoneMobile
    - String adresse
    - String ville
    - String codePostal
    - String region
    - String pays
    - String profession
    - String situationMatrimoniale
    - String nationalite
    - String contactUrgenceNom
    - String contactUrgenceTelephone
    - String contactUrgenceLien
    - String organisationId
    - String typeAdhesion
    - String numeroGenere
    - List<AssociationDTO> organisations
    - int etapeCourante
    - String membreIdString
    - boolean modeModification
    - MembreDTO membreSelectionne
    
    + init(): void @PostConstruct
    + chargerMembreSiModification(): void
    + inscrire(): String
    + enregistrerBrouillon(): String
    + preparerNouveauMembre(): void
    + peutAccepterNouveauMembre(): boolean
    + isEtapePersonnelleComplete(): boolean
    + isEtapeCoordonneeComplete(): boolean
    + isEtapeAdhesionComplete(): boolean
    + isEtapeDocumentsComplete(): boolean
    + getProgressionPourcentage(): int
}
```

**Dépendances :**
- `MembreService` (REST Client)
- `AssociationService` (REST Client)
- `ValidationService`

---

### 9.2 MembreListeBean

```java
@Named("membreListeBean")
@ViewScoped
public class MembreListeBean implements Serializable {
    @Inject @RestClient MembreService membreService;
    @Inject @RestClient AssociationService associationService;
    
    - List<MembreDTO> membres
    - MembreDTO membreSelectionne
    - String recherche
    - String membreSelectionneIdString
    - int page = 0
    - int size = 20
    
    + init(): void @PostConstruct
    + chargerMembres(): void
    + rechercherMembres(): void
    + modifierMembre(MembreDTO membre): String
    + supprimerMembre(MembreDTO membre): void
    + basculerStatutMembre(MembreDTO membre): void
    + voirProfil(MembreDTO membre): String
    + chargerMembreSelectionne(): void
}
```

**Dépendances :**
- `MembreService` (REST Client)
- `AssociationService` (REST Client)

---

### 9.3 OrganisationsBean

```java
@Named("organisationsBean")
@ViewScoped
public class OrganisationsBean implements Serializable {
    @Inject @RestClient AssociationService associationService;
    @Inject @RestClient TypeOrganisationClientService typeOrganisationService;
    
    - List<AssociationDTO> organisations
    - AssociationDTO nouvelleOrganisation
    - AssociationDTO organisationSelectionnee
    - List<TypeOrganisationClientDTO> typesOrganisation
    - Map<String, Object> statistiques
    - String recherche
    - String statutFiltre
    - String typeFiltre
    - int page = 0
    - int size = 20
    - String statutActive = "ACTIVE"
    
    + init(): void @PostConstruct
    + chargerOrganisations(): void
    + chargerStatistiques(): void
    + chargerTypesOrganisation(): void
    + preparerNouvelleOrganisation(): void
    + creerOrganisation(): void
    + modifierOrganisation(): void
    + supprimerOrganisation(AssociationDTO org): void
    + basculerStatutOrganisation(AssociationDTO org): void
    + rechercherOrganisations(String query): void
    + recharger(): void
    + setOrganisationSelectionnee(AssociationDTO org): void
}
```

**Dépendances :**
- `AssociationService` (REST Client)
- `TypeOrganisationClientService` (REST Client)

---

### 9.4 Autres Beans

- `OrganisationDetailBean`
- `TypeOrganisationsAdminBean`
- `CotisationsBean`
- `CotisationsGestionBean`
- `AdhesionsBean`
- `EvenementsBean`
- `DemandesAideBean`
- `DashboardBean`
- `AuditBean`
- `UserSession`
- `LoginBean`
- `PreferencesBean`
- `ParametresBean`
- `SuperAdminBean`
- `UtilisateursBean`
- `EntitesGestionBean`
- `MembreRechercheBean`
- `MembreProfilBean`
- `MembreDashboardBean`
- `MembreCotisationBean`
- `PersonnelBean`
- `FavorisBean`
- `RapportsBean`
- `RolesBean`
- `SecurityStatusBean`
- `SouscriptionBean`
- `WaveBean`
- `FormulaireBean`
- `AdminFormulaireBean`
- `DocumentsBean`
- `DemandesBean`
- `ConfigurationBean`
- `GuideBean`
- `GuestPreferences`
- `NavigationBean`
- `HelloView`

---

## 10. SÉCURITÉ (Client)

### 10.1 AuthenticationFilter

```java
@WebFilter(urlPatterns = "/pages/*")
public class AuthenticationFilter implements Filter {
    @Inject JwtTokenManager tokenManager;
    @Inject UserSession userSession;
    
    + doFilter(ServletRequest request, ServletResponse response, FilterChain chain): void
    + init(FilterConfig filterConfig): void
    + destroy(): void
}
```

---

### 10.2 JwtClientRequestFilter

```java
@Provider
public class JwtClientRequestFilter implements ClientRequestFilter {
    @Inject JwtTokenManager tokenManager;
    
    + filter(ClientRequestContext requestContext): void
}
```

---

### 10.3 JwtTokenManager

```java
@ApplicationScoped
public class JwtTokenManager {
    - String accessToken
    - String refreshToken
    - LocalDateTime tokenExpiry
    
    + getAccessToken(): String
    + setAccessToken(String token): void
    + getRefreshToken(): String
    + setRefreshToken(String token): void
    + isTokenValid(): boolean
    + clearTokens(): void
}
```

---

### 10.4 UserSession

```java
@Named("userSession")
@SessionScoped
public class UserSession implements Serializable {
    - String username
    - String email
    - String nomComplet
    - String typeCompte
    - List<String> roles
    - String accessToken
    - String refreshToken
    
    + init(): void @PostConstruct
    + logout(): String
    + isAuthenticated(): boolean
    + hasRole(String role): boolean
    + isSuperAdmin(): boolean
    + isAdmin(): boolean
    + isMembre(): boolean
}
```

---

## 11. DIAGRAMME DE RELATIONS

### 11.1 Relations Entités

```
BaseEntity (abstract)
    ↑
    ├── Membre
    │   └── @ManyToOne → Organisation
    │
    ├── Organisation
    │   ├── @OneToMany → Membre
    │   └── Auto-référence (organisationParenteId)
    │
    ├── TypeOrganisationEntity
    │
    ├── Cotisation
    │   └── @ManyToOne → Membre
    │
    ├── Adhesion
    │   ├── @ManyToOne → Membre
    │   └── @ManyToOne → Organisation
    │
    ├── Evenement
    │   ├── @ManyToOne → Organisation
    │   ├── @ManyToOne → Membre (organisateur)
    │   └── @OneToMany → InscriptionEvenement
    │
    ├── InscriptionEvenement
    │   ├── @ManyToOne → Membre
    │   └── @ManyToOne → Evenement
    │
    ├── DemandeAide
    │   ├── @ManyToOne → Membre (demandeur)
    │   ├── @ManyToOne → Membre (evaluateur)
    │   └── @ManyToOne → Organisation
    │
    └── AuditLog
```

### 11.2 Relations Services

```
MembreService
    └── @Inject → MembreRepository
        └── extends → BaseRepository<Membre>

OrganisationService
    └── @Inject → OrganisationRepository
        └── extends → BaseRepository<Organisation>

TypeOrganisationService
    ├── @Inject → TypeOrganisationRepository
    │   └── extends → BaseRepository<TypeOrganisationEntity>
    └── @Inject → KeycloakService
```

### 11.3 Relations REST

```
MembreResource
    └── @Inject → MembreService

OrganisationResource
    └── @Inject → OrganisationService

TypeOrganisationResource
    └── @Inject → TypeOrganisationService
```

### 11.4 Relations Client

```
MembreInscriptionBean
    ├── @Inject @RestClient → MembreService (interface)
    ├── @Inject @RestClient → AssociationService (interface)
    └── @Inject → ValidationService

MembreListeBean
    ├── @Inject @RestClient → MembreService (interface)
    └── @Inject @RestClient → AssociationService (interface)

OrganisationsBean
    ├── @Inject @RestClient → AssociationService (interface)
    └── @Inject @RestClient → TypeOrganisationClientService (interface)
```

---

## 12. PATTERNS ET ARCHITECTURE

### 12.1 Patterns Utilisés

1. **Repository Pattern** : `BaseRepository<T>` avec implémentations spécialisées
2. **DTO Pattern** : Séparation entités JPA / DTOs API
3. **Service Layer** : Logique métier dans les services
4. **REST Client Pattern** : Interfaces MicroProfile Rest Client côté client
5. **Bean Pattern** : Beans JSF pour la présentation
6. **Filter Pattern** : Filtres pour authentification et JWT
7. **Base Entity Pattern** : `BaseEntity` pour audit et soft delete

### 12.2 Architecture en Couches

```
┌─────────────────────────────────────┐
│   CLIENT (JSF/PrimeFaces)           │
│   - Beans (View)                    │
│   - DTOs Client                      │
│   - Services REST Client             │
└─────────────────────────────────────┘
              ↕ HTTP/REST
┌─────────────────────────────────────┐
│   SERVER API                         │
│   - Resources REST (JAX-RS)          │
│   - Services                        │
│   - Repositories                     │
└─────────────────────────────────────┘
              ↕ JPA
┌─────────────────────────────────────┐
│   DATABASE                           │
│   - Entités JPA                      │
│   - Relations                        │
└─────────────────────────────────────┘
```

---

## 13. POINTS D'AMÉLIORATION IDENTIFIÉS

### 13.1 Modélisation

1. **Relations manquantes** :
   - Pas de relation explicite `Membre` ↔ `Cotisation` (actuellement via `@ManyToOne` dans `Cotisation`)
   - Pas de relation `Organisation` ↔ `Evenement` (actuellement via `@ManyToOne` dans `Evenement`)

2. **Redondance** :
   - `MembreDTO` existe côté serveur ET client avec des différences
   - `AssociationDTO` (client) vs `OrganisationDTO` (serveur) - alignement partiel

3. **Champs optionnels non persistés** :
   - Dans `MembreInscriptionBean`, plusieurs champs (sexe, contactUrgence, etc.) ne sont pas dans `MembreDTO` serveur

4. **Enums vs Entités** :
   - `TypeOrganisation` existe en Enum ET en Entité (`TypeOrganisationEntity`) - risque de désynchronisation

### 13.2 Suggestions d'amélioration

1. **Unifier les DTOs** : Créer un seul DTO partagé ou mapper automatiquement
2. **Compléter les relations JPA** : Ajouter les relations bidirectionnelles manquantes
3. **Persister tous les champs** : Ajouter les champs manquants dans `Membre` ou créer une entité `ContactUrgence`
4. **Synchroniser Enum/Entité** : Utiliser uniquement l'entité `TypeOrganisationEntity` ou synchroniser automatiquement
5. **Audit complet** : S'assurer que tous les champs d'audit sont remplis automatiquement
6. **Validation cohérente** : Aligner les validations entre client et serveur

---

## 14. CONCLUSION

Ce diagramme de classes représente l'architecture complète d'UnionFlow avec :
- **9 entités JPA** principales
- **10+ repositories** spécialisés
- **15+ DTOs** serveur et client
- **10+ services** métier
- **15+ resources REST**
- **30+ beans JSF**
- **10+ enums** de statuts et types

L'architecture suit les principes DRY et WOU avec des composants réutilisables et une séparation claire des responsabilités.

---

**Date de génération** : 2025-01-29
**Version** : 1.0

