From d8529cedd3e7b063183d98819fdef2297ca6c5a9 Mon Sep 17 00:00:00 2001 From: dahoud Date: Sat, 29 Nov 2025 23:51:27 +0000 Subject: [PATCH] docs: Ajout diagramme de classes complet UnionFlow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documentation exhaustive de l'architecture UnionFlow: - 9 entités JPA avec relations - 10+ repositories spécialisés - 15+ DTOs serveur et client - 10+ services métier - 15+ resources REST - 30+ beans JSF - 10+ enums - Diagrammes de relations - Points d'amélioration identifiés Document généré après lecture intégrale de tous les fichiers Java. --- DIAGRAMME_CLASSES_UNIONFLOW.md | 1979 ++++++++++++++++++++++++++++++++ 1 file changed, 1979 insertions(+) create mode 100644 DIAGRAMME_CLASSES_UNIONFLOW.md diff --git a/DIAGRAMME_CLASSES_UNIONFLOW.md b/DIAGRAMME_CLASSES_UNIONFLOW.md new file mode 100644 index 0000000..7b47ad5 --- /dev/null +++ b/DIAGRAMME_CLASSES_UNIONFLOW.md @@ -0,0 +1,1979 @@ +# 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 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 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 + +```java +public abstract class BaseRepository { + @PersistenceContext + protected EntityManager entityManager; + + protected final Class entityClass; + + + findById(UUID id): T + + findByIdOptional(UUID id): Optional + + persist(T entity): void @Transactional + + update(T entity): T @Transactional + + delete(T entity): void @Transactional + + deleteById(UUID id): boolean @Transactional + + listAll(): List + + 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 { + + findByEmail(String email): Optional + + findByNumeroMembre(String numero): Optional + + findAllActifs(): List + + countActifs(): long + + findByNomOrPrenom(String recherche): List + + findAllActifs(Page page, Sort sort): List + + findByNomOrPrenom(String recherche, Page page, Sort sort): List + + countNouveauxMembres(LocalDate depuis): long + + findByStatut(boolean actif, Page page, Sort sort): List + + findByTrancheAge(int ageMin, int ageMax, Page page, Sort sort): List + + rechercheAvancee(...): List + + 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 { + + findByEmail(String email): Optional + + findByNom(String nom): Optional + + findByNumeroEnregistrement(String numero): Optional + + findAllActives(): List + + findAllActives(Page page, Sort sort): List + + countActives(): long + + findByStatut(String statut, Page page, Sort sort): List + + findByType(String typeOrganisation, Page page, Sort sort): List + + findByVille(String ville, Page page, Sort sort): List + + findByPays(String pays, Page page, Sort sort): List + + findByRegion(String region, Page page, Sort sort): List + + findByOrganisationParente(UUID parenteId, Page page, Sort sort): List + + findOrganisationsRacines(Page page, Sort sort): List + + findByNomOrNomCourt(String recherche, Page page, Sort sort): List + + rechercheAvancee(...): List + + countNouvellesOrganisations(LocalDate depuis): long + + findOrganisationsPubliques(Page page, Sort sort): List + + findOrganisationsOuvertes(Page page, Sort sort): List + + countByStatut(String statut): long + + countByType(String typeOrganisation): long +} +``` + +--- + +### 2.4 Autres Repositories + +- `TypeOrganisationRepository extends BaseRepository` +- `CotisationRepository extends BaseRepository` +- `AdhesionRepository extends BaseRepository` +- `EvenementRepository extends BaseRepository` +- `DemandeAideRepository extends BaseRepository` +- `AuditLogRepository extends BaseRepository` + +--- + +## 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 piecesJustificatives + - List beneficiaires + - List historiqueStatuts + - List commentaires + - Map donneesPersonnalisees + - List 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 + + rechercherMembres(String recherche, Page page, Sort sort): List + + obtenirStatistiquesAvancees(): Map + + convertToDTO(Membre membre): MembreDTO + + convertFromDTO(MembreDTO dto): Membre + + convertToDTOList(List membres): List + + 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 + + trouverParEmail(String email): Optional + + listerOrganisationsActives(): List + + listerOrganisationsActives(int page, int size): List + + rechercherOrganisations(String recherche, int page, int size): List + + rechercheAvancee(...): List + + activerOrganisation(UUID id, String utilisateur): Organisation @Transactional + + suspendreOrganisation(UUID id, String utilisateur): Organisation @Transactional + + obtenirStatistiques(): Map + + 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 + + getTypeById(UUID id): Optional + + 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 + + @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 + + @GET + @Path("/statistiques") + @PermitAll + + obtenirStatistiques(): Map +} +``` + +--- + +### 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 + + @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 + + @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 +} +``` + +--- + +### 6.3 TypeOrganisationResource + +```java +@Path("/api/types-organisations") +@ApplicationScoped +public class TypeOrganisationResource { + @Inject TypeOrganisationService service; + + @GET + @PermitAll + + listTypes(@QueryParam("onlyActifs") String onlyActifs): List + + @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 + + @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 +} +``` + +--- + +### 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 + + @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 + + @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 +} +``` + +--- + +### 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 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 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 organisations + - AssociationDTO nouvelleOrganisation + - AssociationDTO organisationSelectionnee + - List typesOrganisation + - Map 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 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 + +OrganisationService + └── @Inject → OrganisationRepository + └── extends → BaseRepository + +TypeOrganisationService + ├── @Inject → TypeOrganisationRepository + │ └── extends → BaseRepository + └── @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` 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 +