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.
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 :
@ManyToOne→Organisation(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 :
@OneToMany→Membre(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 :
@ManyToOne→Membre(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 :
@ManyToOne→Membre@ManyToOne→Organisation
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 :
@ManyToOne→Organisation@ManyToOne→Membre(organisateur)@OneToMany→InscriptionEvenement
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 :
@ManyToOne→Membre@ManyToOne→Evenement
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 :
@ManyToOne→Membre(demandeur)@ManyToOne→Membre(evaluateur)@ManyToOne→Organisation
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 :
MembreRepositoryEntityManager
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 :
TypeOrganisationRepositoryKeycloakService
5.4 Autres Services
CotisationServiceAdhesionServiceEvenementServiceDemandeAideServiceAuditServiceKeycloakServiceNotificationServiceExportServicePaiementServiceWaveService
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
CotisationResourceAdhesionResourceEvenementResourceDemandeAideResourceAuditResourceNotificationResourceExportResourceDashboardResourceHealthResourceWaveResourcePreferencesResource
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
TypeOrganisationClientDTOCotisationDTOAdhesionDTOEvenementDTODemandeAideDTOAuditLogDTOAnalyticsDataDTOWaveBalanceDTOWaveCheckoutSessionDTO
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
TypeOrganisationClientServiceCotisationServiceAdhesionServiceEvenementServiceDemandeAideServiceAuditServiceNotificationClientServiceExportClientServicePreferencesServiceWaveServiceValidationService
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
OrganisationDetailBeanTypeOrganisationsAdminBeanCotisationsBeanCotisationsGestionBeanAdhesionsBeanEvenementsBeanDemandesAideBeanDashboardBeanAuditBeanUserSessionLoginBeanPreferencesBeanParametresBeanSuperAdminBeanUtilisateursBeanEntitesGestionBeanMembreRechercheBeanMembreProfilBeanMembreDashboardBeanMembreCotisationBeanPersonnelBeanFavorisBeanRapportsBeanRolesBeanSecurityStatusBeanSouscriptionBeanWaveBeanFormulaireBeanAdminFormulaireBeanDocumentsBeanDemandesBeanConfigurationBeanGuideBeanGuestPreferencesNavigationBeanHelloView
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
- Repository Pattern :
BaseRepository<T>avec implémentations spécialisées - DTO Pattern : Séparation entités JPA / DTOs API
- Service Layer : Logique métier dans les services
- REST Client Pattern : Interfaces MicroProfile Rest Client côté client
- Bean Pattern : Beans JSF pour la présentation
- Filter Pattern : Filtres pour authentification et JWT
- Base Entity Pattern :
BaseEntitypour 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
-
Relations manquantes :
- Pas de relation explicite
Membre↔Cotisation(actuellement via@ManyToOnedansCotisation) - Pas de relation
Organisation↔Evenement(actuellement via@ManyToOnedansEvenement)
- Pas de relation explicite
-
Redondance :
MembreDTOexiste côté serveur ET client avec des différencesAssociationDTO(client) vsOrganisationDTO(serveur) - alignement partiel
-
Champs optionnels non persistés :
- Dans
MembreInscriptionBean, plusieurs champs (sexe, contactUrgence, etc.) ne sont pas dansMembreDTOserveur
- Dans
-
Enums vs Entités :
TypeOrganisationexiste en Enum ET en Entité (TypeOrganisationEntity) - risque de désynchronisation
13.2 Suggestions d'amélioration
- Unifier les DTOs : Créer un seul DTO partagé ou mapper automatiquement
- Compléter les relations JPA : Ajouter les relations bidirectionnelles manquantes
- Persister tous les champs : Ajouter les champs manquants dans
Membreou créer une entitéContactUrgence - Synchroniser Enum/Entité : Utiliser uniquement l'entité
TypeOrganisationEntityou synchroniser automatiquement - Audit complet : S'assurer que tous les champs d'audit sont remplis automatiquement
- 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