Files
unionflow-server-impl-quarkus/DIAGRAMME_CLASSES_UNIONFLOW.md
dahoud d8529cedd3 docs: Ajout diagramme de classes complet UnionFlow
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.
2025-11-29 23:51:27 +00:00

53 KiB

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)

@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

@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 :

  • @ManyToOneOrganisation (membre appartient à une organisation)

1.3 Organisation

@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 :

  • @OneToManyMembre (une organisation a plusieurs membres)
  • Auto-référence via organisationParenteId (hiérarchie)

1.4 TypeOrganisationEntity

@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

@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 :

  • @ManyToOneMembre (une cotisation appartient à un membre)

1.6 Adhesion

@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 :

  • @ManyToOneMembre
  • @ManyToOneOrganisation

1.7 Evenement

@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 :

  • @ManyToOneOrganisation
  • @ManyToOneMembre (organisateur)
  • @OneToManyInscriptionEvenement

1.8 InscriptionEvenement

@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 :

  • @ManyToOneMembre
  • @ManyToOneEvenement

1.9 DemandeAide

@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 :

  • @ManyToOneMembre (demandeur)
  • @ManyToOneMembre (evaluateur)
  • @ManyToOneOrganisation

1.10 AuditLog

@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

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

@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

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

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

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

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

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

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

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

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

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

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

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

4.2 StatutOrganisation

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

4.3 TypeOrganisation

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

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

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

4.6 TypeEvenementMetier

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

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

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

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

@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

@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

@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

@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

@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

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

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)

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

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

@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

@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

@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

@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

@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

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

10.3 JwtTokenManager

@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

@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 MembreCotisation (actuellement via @ManyToOne dans Cotisation)
    • Pas de relation OrganisationEvenement (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