# Diagramme de Classes - UnionFlow ## Vue d'ensemble UnionFlow est une application de gestion d'organisations (Lions Clubs, Associations, Coopératives, etc.) avec gestion des membres, cotisations, événements et système de solidarité. **Architecture modulaire :** - `unionflow-server-api` : Contrats API (DTOs, Enums, Interfaces) - `unionflow-server-impl-quarkus` : Implémentation serveur (Entités JPA, Services, Resources REST) - `unionflow-client-quarkus-primefaces-freya` : Client web JSF/PrimeFaces --- ## 1. ENTITÉS JPA (Server Implementation) ### 1.1 BaseEntity (Classe abstraite) ```java @MappedSuperclass public abstract class BaseEntity { - UUID id (PK, @GeneratedValue UUID) - LocalDateTime dateCreation - LocalDateTime dateModification - String creePar - String modifiePar - Long version (@Version) - Boolean actif + onCreate() @PrePersist + onUpdate() @PreUpdate } ``` **Relations :** Toutes les entités héritent de `BaseEntity` --- ### 1.2 Membre ```java @Entity @Table(name = "membres") public class Membre extends BaseEntity { - String numeroMembre (unique, @NotBlank) - String prenom (@NotBlank) - String nom (@NotBlank) - String email (unique, @Email, @NotBlank) - String motDePasse - String telephone - LocalDate dateNaissance (@NotNull) - LocalDate dateAdhesion (@NotNull) - String roles // Relations - Organisation organisation (@ManyToOne, LAZY) + getNomComplet(): String + isMajeur(): boolean + getAge(): int } ``` **Relations :** - `@ManyToOne` → `Organisation` (membre appartient à une organisation) --- ### 1.3 Organisation ```java @Entity @Table(name = "organisations") public class Organisation extends BaseEntity { - String nom (@NotBlank) - String nomCourt - String typeOrganisation (@NotBlank) - String statut (@NotBlank) - String description - LocalDate dateFondation - String numeroEnregistrement (unique) // Contact - String email (unique, @Email, @NotBlank) - String telephone - String telephoneSecondaire - String emailSecondaire // Adresse - String adresse - String ville - String codePostal - String region - String pays - BigDecimal latitude - BigDecimal longitude // Web - String siteWeb - String logo - String reseauxSociaux // Hiérarchie - UUID organisationParenteId - Integer niveauHierarchique // Statistiques - Integer nombreMembres - Integer nombreAdministrateurs // Finances - BigDecimal budgetAnnuel - String devise - Boolean cotisationObligatoire - BigDecimal montantCotisationAnnuelle // Compléments - String objectifs - String activitesPrincipales - String certifications - String partenaires - String notes - Boolean organisationPublique - Boolean accepteNouveauxMembres // Relations - List membres (@OneToMany, mappedBy="organisation", LAZY) + getNomComplet(): String + getAncienneteAnnees(): int + isRecente(): boolean + isActive(): boolean + ajouterMembre() + retirerMembre() + activer(String utilisateur) + suspendre(String utilisateur) + dissoudre(String utilisateur) } ``` **Relations :** - `@OneToMany` → `Membre` (une organisation a plusieurs membres) - Auto-référence via `organisationParenteId` (hiérarchie) --- ### 1.4 TypeOrganisationEntity ```java @Entity @Table(name = "uf_type_organisation") public class TypeOrganisationEntity extends BaseEntity { - String code (unique, @NotBlank) - String libelle (@NotBlank) - String description - Integer ordreAffichage } ``` **Relations :** Aucune (entité de référence) --- ### 1.5 Cotisation ```java @Entity @Table(name = "cotisations") public class Cotisation extends BaseEntity { - String numeroReference (unique, @NotBlank) - Membre membre (@ManyToOne, @NotNull) - String typeCotisation (@NotBlank) - BigDecimal montantDu (@NotNull, @DecimalMin(0)) - BigDecimal montantPaye (@DecimalMin(0)) - String codeDevise (@NotBlank, @Pattern("^[A-Z]{3}$")) - String statut (@NotBlank, @Pattern) - LocalDate dateEcheance (@NotNull) - LocalDateTime datePaiement - String description - String periode - Integer annee (@NotNull, @Min(2020), @Max(2100)) - Integer mois (@Min(1), @Max(12)) - String observations - Boolean recurrente - Integer nombreRappels - LocalDateTime dateDernierRappel - UUID valideParId - String nomValidateur - LocalDateTime dateValidation - String methodePaiement - String referencePaiement + getMontantRestant(): BigDecimal + isEntierementPayee(): boolean + isEnRetard(): boolean + genererNumeroReference(): String (static) } ``` **Relations :** - `@ManyToOne` → `Membre` (une cotisation appartient à un membre) --- ### 1.6 Adhesion ```java @Entity @Table(name = "adhesions") public class Adhesion extends BaseEntity { - String numeroReference (unique, @NotBlank) - Membre membre (@ManyToOne, @NotNull) - Organisation organisation (@ManyToOne, @NotNull) - LocalDate dateDemande (@NotNull) - BigDecimal fraisAdhesion (@NotNull, @DecimalMin(0)) - BigDecimal montantPaye (@DecimalMin(0)) - String codeDevise (@NotBlank, @Pattern("^[A-Z]{3}$")) - String statut (@NotBlank, @Pattern) - LocalDate dateApprobation - LocalDateTime datePaiement - String methodePaiement - String referencePaiement - String motifRejet - String observations - String approuvePar - LocalDate dateValidation + isPayeeIntegralement(): boolean + isEnAttentePaiement(): boolean + getMontantRestant(): BigDecimal } ``` **Relations :** - `@ManyToOne` → `Membre` - `@ManyToOne` → `Organisation` --- ### 1.7 Evenement ```java @Entity @Table(name = "evenements") public class Evenement extends BaseEntity { - String titre (@NotBlank, @Size(3-200)) - String description (@Size(max=2000)) - LocalDateTime dateDebut (@NotNull) - LocalDateTime dateFin - String lieu (@Size(max=500)) - String adresse (@Size(max=1000)) - TypeEvenement typeEvenement (@Enumerated) - StatutEvenement statut (@Enumerated) - Integer capaciteMax (@Min(0)) - BigDecimal prix (@DecimalMin("0.00")) - Boolean inscriptionRequise - LocalDateTime dateLimiteInscription - String instructionsParticulieres - String contactOrganisateur - String materielRequis - Boolean visiblePublic - Boolean actif // Relations - Organisation organisation (@ManyToOne, LAZY) - Membre organisateur (@ManyToOne, LAZY) - List inscriptions (@OneToMany, mappedBy="evenement", LAZY) enum TypeEvenement { ASSEMBLEE_GENERALE, REUNION, FORMATION, ... } enum StatutEvenement { PLANIFIE, CONFIRME, EN_COURS, TERMINE, ANNULE, REPORTE } + isOuvertAuxInscriptions(): boolean + getNombreInscrits(): int + isComplet(): boolean + isEnCours(): boolean + isTermine(): boolean + getDureeEnHeures(): Long + getPlacesRestantes(): Integer + isMemberInscrit(UUID membreId): boolean + getTauxRemplissage(): Double } ``` **Relations :** - `@ManyToOne` → `Organisation` - `@ManyToOne` → `Membre` (organisateur) - `@OneToMany` → `InscriptionEvenement` --- ### 1.8 InscriptionEvenement ```java @Entity @Table(name = "inscriptions_evenement") public class InscriptionEvenement extends BaseEntity { - Membre membre (@ManyToOne, @NotNull) - Evenement evenement (@ManyToOne, @NotNull) - LocalDateTime dateInscription - StatutInscription statut (@Enumerated) - String commentaire enum StatutInscription { CONFIRMEE, EN_ATTENTE, ANNULEE, REFUSEE } + isConfirmee(): boolean + isEnAttente(): boolean + isAnnulee(): boolean + confirmer() + annuler(String commentaire) + mettreEnAttente(String commentaire) + refuser(String commentaire) } ``` **Relations :** - `@ManyToOne` → `Membre` - `@ManyToOne` → `Evenement` --- ### 1.9 DemandeAide ```java @Entity @Table(name = "demandes_aide") public class DemandeAide extends BaseEntity { - String titre (@NotBlank) - String description (@NotBlank, TEXT) - TypeAide typeAide (@Enumerated, @NotNull) - StatutAide statut (@Enumerated, @NotNull) - BigDecimal montantDemande - BigDecimal montantApprouve - LocalDateTime dateDemande - LocalDateTime dateEvaluation - LocalDateTime dateVersement - Membre demandeur (@ManyToOne, @NotNull) - Membre evaluateur (@ManyToOne) - Organisation organisation (@ManyToOne, @NotNull) - String justification (TEXT) - String commentaireEvaluation (TEXT) - Boolean urgence - String documentsFournis + isEnAttente(): boolean + isApprouvee(): boolean + isRejetee(): boolean + isUrgente(): boolean + getPourcentageApprobation(): BigDecimal } ``` **Relations :** - `@ManyToOne` → `Membre` (demandeur) - `@ManyToOne` → `Membre` (evaluateur) - `@ManyToOne` → `Organisation` --- ### 1.10 AuditLog ```java @Entity @Table(name = "audit_logs") public class AuditLog extends BaseEntity { - String typeAction - String severite - String utilisateur - String role - String module - String description - String details (TEXT) - String ipAddress - String userAgent - String sessionId - LocalDateTime dateHeure - String donneesAvant (TEXT) - String donneesApres (TEXT) - String entiteId - String entiteType } ``` **Relations :** Aucune (entité de log) --- ## 2. REPOSITORIES (Server Implementation) ### 2.1 BaseRepository ```java public abstract class BaseRepository { @PersistenceContext protected EntityManager entityManager; protected final Class entityClass; + findById(UUID id): T + findByIdOptional(UUID id): Optional + persist(T entity): void @Transactional + update(T entity): T @Transactional + delete(T entity): void @Transactional + deleteById(UUID id): boolean @Transactional + listAll(): List + count(): long + existsById(UUID id): boolean + getEntityManager(): EntityManager } ``` **Relations :** - Générique sur `BaseEntity` - Utilisé par tous les repositories --- ### 2.2 MembreRepository ```java @ApplicationScoped public class MembreRepository extends BaseRepository { + findByEmail(String email): Optional + findByNumeroMembre(String numero): Optional + findAllActifs(): List + countActifs(): long + findByNomOrPrenom(String recherche): List + findAllActifs(Page page, Sort sort): List + findByNomOrPrenom(String recherche, Page page, Sort sort): List + countNouveauxMembres(LocalDate depuis): long + findByStatut(boolean actif, Page page, Sort sort): List + findByTrancheAge(int ageMin, int ageMax, Page page, Sort sort): List + rechercheAvancee(...): List + countMembresActifs(UUID organisationId, LocalDateTime debut, LocalDateTime fin): Long + countMembresInactifs(UUID organisationId, LocalDateTime debut, LocalDateTime fin): Long + calculerMoyenneAge(UUID organisationId, LocalDateTime debut, LocalDateTime fin): Double } ``` --- ### 2.3 OrganisationRepository ```java @ApplicationScoped public class OrganisationRepository extends BaseRepository { + findByEmail(String email): Optional + findByNom(String nom): Optional + findByNumeroEnregistrement(String numero): Optional + findAllActives(): List + findAllActives(Page page, Sort sort): List + countActives(): long + findByStatut(String statut, Page page, Sort sort): List + findByType(String typeOrganisation, Page page, Sort sort): List + findByVille(String ville, Page page, Sort sort): List + findByPays(String pays, Page page, Sort sort): List + findByRegion(String region, Page page, Sort sort): List + findByOrganisationParente(UUID parenteId, Page page, Sort sort): List + findOrganisationsRacines(Page page, Sort sort): List + findByNomOrNomCourt(String recherche, Page page, Sort sort): List + rechercheAvancee(...): List + countNouvellesOrganisations(LocalDate depuis): long + findOrganisationsPubliques(Page page, Sort sort): List + findOrganisationsOuvertes(Page page, Sort sort): List + countByStatut(String statut): long + countByType(String typeOrganisation): long } ``` --- ### 2.4 Autres Repositories - `TypeOrganisationRepository extends BaseRepository` - `CotisationRepository extends BaseRepository` - `AdhesionRepository extends BaseRepository` - `EvenementRepository extends BaseRepository` - `DemandeAideRepository extends BaseRepository` - `AuditLogRepository extends BaseRepository` --- ## 3. DTOs SERVEUR (Server API) ### 3.1 BaseDTO (Classe abstraite) ```java public abstract class BaseDTO implements Serializable { - UUID id - LocalDateTime dateCreation (@JsonFormat) - LocalDateTime dateModification (@JsonFormat) - String creePar - String modifiePar - Long version - Boolean actif + marquerCommeNouveau(String utilisateur): void + marquerCommeModifie(String utilisateur): void + desactiver(String utilisateur): void + reactiver(String utilisateur): void + isNouveau(): boolean + isActif(): boolean } ``` **Relations :** Tous les DTOs héritent de `BaseDTO` --- ### 3.2 MembreDTO ```java public class MembreDTO extends BaseDTO { - String numeroMembre (@Size(max=50)) - String nom (@NotBlank, @Size(2-50), @Pattern) - String prenom (@NotBlank, @Size(2-50), @Pattern) - String email (@NotBlank, @Email, @Size(max=100)) - String telephone (@Size(max=20)) - LocalDate dateNaissance (@Past) - String adresse (@Size(max=200)) - String profession (@Size(max=100)) - String statutMatrimonial (@Size(max=20)) - String nationalite (@Size(max=50)) - String numeroIdentite (@Size(max=50)) - String typeIdentite (@Size(max=20)) - StatutMembre statut (@NotNull) - UUID associationId (@NotNull) - String associationNom - LocalDate dateAdhesion - String region (@Size(max=50)) - String ville (@Size(max=50)) - String quartier (@Size(max=50)) - String role (@Size(max=50)) - Boolean membreBureau - Boolean responsable - String photoUrl (@Size(max=255)) + getStatutLibelle(): String + sontDonneesValides(): boolean } ``` --- ### 3.3 OrganisationDTO ```java public class OrganisationDTO extends BaseDTO { - String nom (@NotBlank, @Size) - String nomCourt (@Size(max=50)) - TypeOrganisation typeOrganisation (@NotNull) - StatutOrganisation statut (@NotNull) - String description (@Size(max=2000)) - LocalDate dateFondation - String numeroEnregistrement (@Size(max=100)) - String adresse (@Size(max=500)) - String ville (@Size(max=100)) - String region (@Size(max=100)) - String pays (@Size(max=100)) - String codePostal (@Pattern) - BigDecimal latitude (@DecimalMin(-90), @DecimalMax(90)) - BigDecimal longitude (@DecimalMin(-180), @DecimalMax(180)) - String telephone (@Pattern) - String telephoneSecondaire (@Pattern) - String email (@Email, @Size(max=200)) - String emailSecondaire (@Email, @Size(max=200)) - String siteWeb (@Pattern, @Size(max=500)) - String logo (@Size(max=500)) - UUID organisationParenteId - String nomOrganisationParente - Integer niveauHierarchique - Integer nombreMembres - Integer nombreAdministrateurs - BigDecimal budgetAnnuel (@DecimalMin(0), @Digits) - String devise (@Pattern("^[A-Z]{3}$")) - String objectifs (@Size(max=2000)) - String activitesPrincipales (@Size(max=2000)) - String reseauxSociaux (@Size(max=1000)) - String certifications (@Size(max=500)) - String partenaires (@Size(max=1000)) - String notes (@Size(max=1000)) - Boolean organisationPublique - Boolean accepteNouveauxMembres - Boolean cotisationObligatoire - BigDecimal montantCotisationAnnuelle (@DecimalMin(0), @Digits) + estActive(): boolean + estInactive(): boolean + estSuspendue(): boolean + estEnCreation(): boolean + estDissoute(): boolean + getAncienneteAnnees(): int + getAncienneteMois(): int + possedGeolocalisation(): boolean + estOrganisationRacine(): boolean + possedeSousOrganisations(): boolean + getNomAffichage(): String + getAdresseComplete(): String + getRatioAdministrateurs(): double + hasBudget(): boolean + activer(String utilisateur): void + suspendre(String utilisateur): void + dissoudre(String utilisateur): void + desactiver(String utilisateur): void + mettreAJourNombreMembres(int nouveauNombre, String utilisateur): void + ajouterMembre(String utilisateur): void + retirerMembre(String utilisateur): void } ``` --- ### 3.4 TypeOrganisationDTO ```java public class TypeOrganisationDTO extends BaseDTO { - String code (@NotBlank, @Size(max=50)) - String libelle (@NotBlank, @Size(max=150)) - String description (@Size(max=500)) - Integer ordreAffichage - Boolean actif } ``` --- ### 3.5 CotisationDTO ```java public class CotisationDTO extends BaseDTO { - String numeroReference (@NotBlank, @Size(max=50)) - UUID membreId (@NotNull) - String numeroMembre - String nomMembre - UUID associationId (@NotNull) - String nomAssociation - String typeCotisation (@NotNull, @Pattern) - String libelle (@NotBlank, @Size(max=100)) - String description (@Size(max=500)) - BigDecimal montantDu (@NotNull, @DecimalMin(0, inclusive=false)) - BigDecimal montantPaye (@DecimalMin(0)) - String codeDevise (@NotBlank, @Size(3)) - String statut (@NotNull, @Pattern) - LocalDate dateEcheance (@NotNull) - LocalDateTime datePaiement - String methodePaiement (@Pattern) - String referencePaiement (@Size(max=100)) - String periode (@Size(max=50)) - Integer annee (@Min(2020), @Max(2050)) - Integer mois (@Min(1), @Max(12)) - String observations (@Size(max=500)) - Boolean recurrente - Integer nombreRappels (@Min(0)) - LocalDateTime dateDernierRappel - UUID validePar - String nomValidateur + isPayeeIntegralement(): boolean + isEnRetard(): boolean + getMontantRestant(): BigDecimal + getPourcentagePaiement(): int + getJoursRetard(): long + getTypeCotisationLibelle(): String + getStatutLibelle(): String + getMethodePaiementLibelle(): String + mettreAJourStatut(): void + marquerCommePaye(BigDecimal montant, String methode, String reference): void } ``` --- ### 3.6 AdhesionDTO ```java public class AdhesionDTO extends BaseDTO { - String numeroReference (@NotBlank, @Size(max=50)) - UUID membreId (@NotNull) - String numeroMembre - String nomMembre - String emailMembre - UUID organisationId (@NotNull) - String nomOrganisation - LocalDate dateDemande (@NotNull) - BigDecimal fraisAdhesion (@NotNull, @DecimalMin(0, inclusive=false)) - BigDecimal montantPaye (@DecimalMin(0)) - String codeDevise (@NotBlank, @Pattern("^[A-Z]{3}$")) - String statut (@NotBlank, @Pattern) - LocalDate dateApprobation - LocalDateTime datePaiement - String methodePaiement (@Pattern) - String referencePaiement (@Size(max=100)) - String motifRejet (@Size(max=1000)) - String observations (@Size(max=1000)) - String approuvePar (@Size(max=255)) - LocalDate dateValidation + isPayeeIntegralement(): boolean + isEnAttentePaiement(): boolean + getMontantRestant(): BigDecimal + getPourcentagePaiement(): int + getJoursDepuisDemande(): long + getStatutLibelle(): String + getStatutSeverity(): String + getStatutIcon(): String + getMethodePaiementLibelle(): String + getDateDemandeFormatee(): String + getDateApprobationFormatee(): String + getDatePaiementFormatee(): String + getFraisAdhesionFormatte(): String + getMontantPayeFormatte(): String + getMontantRestantFormatte(): String } ``` --- ### 3.7 EvenementDTO ```java public class EvenementDTO extends BaseDTO { - String titre (@NotBlank, @Size(3-200)) - String description (@Size(max=2000)) - TypeEvenementMetier typeEvenement (@NotNull) - StatutEvenement statut (@NotNull) - PrioriteEvenement priorite - LocalDate dateDebut (@NotNull, @Future) - LocalDate dateFin - LocalTime heureDebut - LocalTime heureFin - String lieu (@NotBlank, @Size(max=100)) - String adresse (@Size(max=200)) - String ville (@Size(max=50)) - String region (@Size(max=50)) - BigDecimal latitude (@DecimalMin(-90), @DecimalMax(90)) - BigDecimal longitude (@DecimalMin(-180), @DecimalMax(180)) - UUID associationId (@NotNull) - String nomAssociation - String organisateur (@Size(max=100)) - String emailOrganisateur (@Email, @Size(max=100)) - String telephoneOrganisateur (@Pattern) - Integer capaciteMax (@Min(1), @Max(10000)) - Integer participantsInscrits (@Min(0)) - Integer participantsPresents (@Min(0)) - BigDecimal budget (@DecimalMin(0), @Digits) - BigDecimal coutReel (@DecimalMin(0), @Digits) - String codeDevise (@Pattern) - Boolean inscriptionObligatoire - LocalDate dateLimiteInscription - Boolean evenementPublic - Boolean recurrent - String frequenceRecurrence (@Pattern) - String instructions (@Size(max=500)) - String materielNecessaire (@Size(max=500)) - String conditionsMeteo (@Size(max=100)) - String imageUrl (@Size(max=255)) - String couleurTheme (@Pattern) - LocalDateTime dateAnnulation - String raisonAnnulation (@Size(max=500)) - Long annulePar - String nomAnnulateur + estEnCours(): boolean + estTermine(): boolean + estAnnule(): boolean + estComplet(): boolean + getPlacesDisponibles(): int + getTauxRemplissage(): int + getTauxPresence(): int + sontInscriptionsOuvertes(): boolean + getDureeEnHeures(): long + estEvenementMultiJours(): boolean + getTypeEvenementLibelle(): String + getStatutLibelle(): String + getPrioriteLibelle(): String + getAdresseComplete(): String + hasCoordonnees(): boolean + getEcartBudgetaire(): BigDecimal + estBudgetDepasse(): boolean } ``` --- ### 3.8 DemandeAideDTO ```java public class DemandeAideDTO extends BaseDTO { - String numeroReference (@Pattern) - TypeAide typeAide (@NotNull) - String titre (@NotBlank, @Size(3-200)) - String description (@NotBlank, @Size(3-2000)) - String justification (@Size(max=2000)) - BigDecimal montantDemande (@DecimalMin(0, inclusive=false), @Digits) - BigDecimal montantApprouve (@DecimalMin(0, inclusive=false), @Digits) - BigDecimal montantVerse (@DecimalMin(0, inclusive=false), @Digits) - String devise (@Pattern, default="XOF") - UUID membreDemandeurId (@NotNull) - String nomDemandeur - String numeroMembreDemandeur - String evaluateurId - String evaluateurNom - String approvateurId - String approvateurNom - UUID associationId (@NotNull) - String nomAssociation - StatutAide statut (@NotNull, default=EN_ATTENTE) - PrioriteAide priorite (@NotNull, default=NORMALE) - String motifRejet (@Size(max=500)) - String commentairesEvaluateur (@Size(max=1000)) - LocalDateTime dateSoumission - LocalDateTime dateLimiteTraitement - LocalDateTime dateEvaluation - LocalDateTime dateApprobation - LocalDateTime dateVersement - LocalDateTime dateCloture - List piecesJustificatives - List beneficiaires - List historiqueStatuts - List commentaires - Map donneesPersonnalisees - List tags - Boolean estConfidentielle - Boolean necessiteSuivi - Double scorePriorite - Integer nombreVues - LocalisationDTO localisation - ContactUrgenceDTO contactUrgence - LocalDate dateLimite - Boolean justificatifsFournis - String documentsJoints (@Size(max=1000)) - LocalDate dateDebutAide - LocalDate dateFinAide - UUID membreAidantId - String nomAidant - String modeVersement (@Size(max=50)) - String numeroTransaction (@Size(max=100)) - UUID rejeteParId - String rejetePar - LocalDateTime dateRejet - String raisonRejet (@Size(max=500)) + estModifiable(): boolean + peutEtreAnnulee(): boolean + estUrgente(): boolean + estTerminee(): boolean + estEnSucces(): boolean + getPourcentageAvancement(): double + getDelaiRestantHeures(): long + estDelaiDepasse(): boolean + getDureeTraitementJours(): long + getStatutLibelle(): String + getPrioriteLibelle(): String + approuver(UUID evaluateurId, String nomEvaluateur, BigDecimal montantApprouve, String commentaires): void + rejeter(UUID evaluateurId, String nomEvaluateur, String raison): void + demarrerAide(UUID aidantId, String nomAidant): void + terminerAvecVersement(BigDecimal montantVerse, String modeVersement, String numeroTransaction): void + incrementerVues(): void + genererNumeroReference(): String (static) } ``` --- ### 3.9 AuditLogDTO ```java public class AuditLogDTO extends BaseDTO { - String typeAction - String severite - String utilisateur - String role - String module - String description - String details - String ipAddress - String userAgent - String sessionId - LocalDateTime dateHeure - String donneesAvant - String donneesApres - String entiteId - String entiteType } ``` --- ## 4. ENUMS (Server API) ### 4.1 StatutMembre ```java public enum StatutMembre { ACTIF("Actif"), INACTIF("Inactif"), SUSPENDU("Suspendu"), DEMISSIONNAIRE("Démissionnaire"), EXCLU("Exclu"); - String libelle + getLibelle(): String } ``` --- ### 4.2 StatutOrganisation ```java public enum StatutOrganisation { ACTIVE("Active"), INACTIVE("Inactive"), SUSPENDUE("Suspendue"), EN_CREATION("En création"), DISSOUTE("Dissoute"); - String libelle + getLibelle(): String } ``` --- ### 4.3 TypeOrganisation ```java public enum TypeOrganisation { LIONS_CLUB("Lions Club"), ASSOCIATION("Association"), FEDERATION("Fédération"), COOPERATIVE("Coopérative"), MUTUELLE("Mutuelle"), SYNDICAT("Syndicat"), FONDATION("Fondation"), ONG("ONG"); - String libelle + getLibelle(): String } ``` --- ### 4.4 StatutCotisation ```java public enum StatutCotisation { EN_ATTENTE("En attente"), PAYEE("Payée"), PARTIELLEMENT_PAYEE("Partiellement payée"), EN_RETARD("En retard"), ANNULEE("Annulée"), REMBOURSEE("Remboursée"); - String libelle + getLibelle(): String } ``` --- ### 4.5 StatutEvenement ```java public enum StatutEvenement { PLANIFIE("Planifié"), CONFIRME("Confirmé"), EN_COURS("En cours"), TERMINE("Terminé"), ANNULE("Annulé"), REPORTE("Reporté"); - String libelle + getLibelle(): String } ``` --- ### 4.6 TypeEvenementMetier ```java public enum TypeEvenementMetier { ASSEMBLEE_GENERALE("Assemblée Générale"), REUNION("Réunion"), FORMATION("Formation"), CONFERENCE("Conférence"), ATELIER("Atelier"), SEMINAIRE("Séminaire"), EVENEMENT_SOCIAL("Événement Social"), MANIFESTATION("Manifestation"), CELEBRATION("Célébration"), AUTRE("Autre"); - String libelle + getLibelle(): String } ``` --- ### 4.7 StatutAide ```java public enum StatutAide { BROUILLON("Brouillon"), SOUMISE("Soumise"), EN_ATTENTE("En attente"), EN_COURS_EVALUATION("En cours d'évaluation"), INFORMATIONS_REQUISES("Informations requises"), APPROUVEE("Approuvée"), APPROUVEE_PARTIELLEMENT("Approuvée partiellement"), EN_COURS_TRAITEMENT("En cours de traitement"), EN_COURS_VERSEMENT("En cours de versement"), VERSEE("Versée"), LIVREE("Livrée"), TERMINEE("Terminée"), REJETEE("Rejetée"), ANNULEE("Annulée"), EXPIREE("Expirée"), SUSPENDUE("Suspendue"), EN_SUIVI("En suivi"), CLOTUREE("Clôturée"); - String libelle + permetModification(): boolean + permetAnnulation(): boolean + isEstFinal(): boolean + isSucces(): boolean + getLibelle(): String } ``` --- ### 4.8 TypeAide ```java public enum TypeAide { FINANCIERE("Aide financière"), MATERIELLE("Aide matérielle"), ALIMENTAIRE("Aide alimentaire"), MEDICALE("Aide médicale"), SCOLAIRE("Aide scolaire"), LOGEMENT("Aide au logement"), EMPLOI("Aide à l'emploi"), FORMATION("Aide à la formation"), AUTRE("Autre"); - String libelle + getLibelle(): String } ``` --- ### 4.9 PrioriteAide ```java public enum PrioriteAide { BASSE("Basse"), NORMALE("Normale"), HAUTE("Haute"), URGENTE("Urgente"), CRITIQUE("Critique"); - String libelle + isUrgente(): boolean + getLibelle(): String } ``` --- ## 5. SERVICES SERVEUR (Server Implementation) ### 5.1 MembreService ```java @ApplicationScoped public class MembreService { @Inject MembreRepository membreRepository; @PersistenceContext EntityManager entityManager; + creerMembre(Membre membre): Membre @Transactional + mettreAJourMembre(UUID id, Membre membreMiseAJour): Membre @Transactional + desactiverMembre(UUID id): void @Transactional + genererNumeroMembre(): String (private) + compterMembresActifs(): long + listerMembresActifs(Page page, Sort sort): List + rechercherMembres(String recherche, Page page, Sort sort): List + obtenirStatistiquesAvancees(): Map + convertToDTO(Membre membre): MembreDTO + convertFromDTO(MembreDTO dto): Membre + convertToDTOList(List membres): List + updateFromDTO(Membre membre, MembreDTO dto): void + rechercheAvancee(MembreSearchCriteria criteria, Page page, Sort sort): MembreSearchResultDTO } ``` **Dépendances :** - `MembreRepository` - `EntityManager` --- ### 5.2 OrganisationService ```java @ApplicationScoped public class OrganisationService { @Inject OrganisationRepository organisationRepository; + creerOrganisation(Organisation organisation): Organisation @Transactional + mettreAJourOrganisation(UUID id, Organisation organisationMiseAJour, String utilisateur): Organisation @Transactional + supprimerOrganisation(UUID id, String utilisateur): void @Transactional + trouverParId(UUID id): Optional + trouverParEmail(String email): Optional + listerOrganisationsActives(): List + listerOrganisationsActives(int page, int size): List + rechercherOrganisations(String recherche, int page, int size): List + rechercheAvancee(...): List + activerOrganisation(UUID id, String utilisateur): Organisation @Transactional + suspendreOrganisation(UUID id, String utilisateur): Organisation @Transactional + obtenirStatistiques(): Map + convertToDTO(Organisation organisation): OrganisationDTO + convertFromDTO(OrganisationDTO dto): Organisation } ``` **Dépendances :** - `OrganisationRepository` --- ### 5.3 TypeOrganisationService ```java @ApplicationScoped public class TypeOrganisationService { @Inject TypeOrganisationRepository repository; @Inject KeycloakService keycloakService; + listTypes(Boolean onlyActifs): List + getTypeById(UUID id): Optional + create(TypeOrganisationDTO dto): TypeOrganisationDTO @Transactional + update(UUID id, TypeOrganisationDTO dto): TypeOrganisationDTO @Transactional + delete(UUID id): void @Transactional + convertToDTO(TypeOrganisationEntity entity): TypeOrganisationDTO + convertFromDTO(TypeOrganisationDTO dto): TypeOrganisationEntity } ``` **Dépendances :** - `TypeOrganisationRepository` - `KeycloakService` --- ### 5.4 Autres Services - `CotisationService` - `AdhesionService` - `EvenementService` - `DemandeAideService` - `AuditService` - `KeycloakService` - `NotificationService` - `ExportService` - `PaiementService` - `WaveService` --- ## 6. RESOURCES REST (Server Implementation) ### 6.1 MembreResource ```java @Path("/api/membres") @ApplicationScoped public class MembreResource { @Inject MembreService membreService; @GET @PermitAll + listerMembres(@QueryParam("page") int page, @QueryParam("size") int size): List @GET @Path("/{id}") @PermitAll + obtenirMembre(@PathParam("id") UUID id): MembreDTO @POST @PermitAll + creerMembre(MembreDTO dto): Response @PUT @Path("/{id}") @PermitAll + mettreAJourMembre(@PathParam("id") UUID id, MembreDTO dto): Response @DELETE @Path("/{id}") @PermitAll + supprimerMembre(@PathParam("id") UUID id): Response @GET @Path("/recherche") @PermitAll + rechercherMembres(@QueryParam("q") String query, @QueryParam("page") int page, @QueryParam("size") int size): List @GET @Path("/statistiques") @PermitAll + obtenirStatistiques(): Map } ``` --- ### 6.2 OrganisationResource ```java @Path("/api/organisations") @ApplicationScoped public class OrganisationResource { @Inject OrganisationService organisationService; @GET @PermitAll + listerToutes(@QueryParam("page") int page, @QueryParam("size") int size): List @GET @Path("/{id}") @PermitAll + obtenirOrganisation(@PathParam("id") UUID id): OrganisationDTO @POST @PermitAll + creerOrganisation(OrganisationDTO dto): Response @PUT @Path("/{id}") @PermitAll + mettreAJourOrganisation(@PathParam("id") UUID id, OrganisationDTO dto): Response @DELETE @Path("/{id}") @PermitAll + supprimerOrganisation(@PathParam("id") UUID id): Response @GET @Path("/recherche") @PermitAll + rechercheAvancee(...): List @POST @Path("/{id}/activer") @PermitAll + activerOrganisation(@PathParam("id") UUID id): Response @POST @Path("/{id}/suspendre") @PermitAll + suspendreOrganisation(@PathParam("id") UUID id): Response @GET @Path("/statistiques") @PermitAll + obtenirStatistiques(): Map } ``` --- ### 6.3 TypeOrganisationResource ```java @Path("/api/types-organisations") @ApplicationScoped public class TypeOrganisationResource { @Inject TypeOrganisationService service; @GET @PermitAll + listTypes(@QueryParam("onlyActifs") String onlyActifs): List @GET @Path("/{id}") @PermitAll + getTypeById(@PathParam("id") UUID id): TypeOrganisationDTO @POST @PermitAll + create(TypeOrganisationDTO dto): Response @PUT @Path("/{id}") @PermitAll + update(@PathParam("id") UUID id, TypeOrganisationDTO dto): Response @DELETE @Path("/{id}") @PermitAll + delete(@PathParam("id") UUID id): Response } ``` --- ### 6.4 Autres Resources - `CotisationResource` - `AdhesionResource` - `EvenementResource` - `DemandeAideResource` - `AuditResource` - `NotificationResource` - `ExportResource` - `DashboardResource` - `HealthResource` - `WaveResource` - `PreferencesResource` --- ## 7. DTOs CLIENT (Client) ### 7.1 MembreDTO (Client) ```java public class MembreDTO implements Serializable { - UUID id - String numeroMembre (@Size(max=50)) - String nom (@NotBlank, @Size(2-50), @Pattern) - String prenom (@NotBlank, @Size(2-50), @Pattern) - String email (@NotBlank, @Email, @Size(max=100)) - String telephone (@Size(max=20)) - LocalDate dateNaissance (@Past) - String adresse (@Size(max=200)) - String profession (@Size(max=100)) - String statutMatrimonial (@Size(max=20)) - String nationalite (@Size(max=50)) - String numeroIdentite (@Size(max=50)) - String typeIdentite (@Size(max=20)) - String photoUrl (@Size(max=255)) - String statut (@NotNull) - UUID associationId (@NotNull) - String associationNom - LocalDateTime dateInscription - LocalDateTime dateDerniereModification - String creePar - String modifiePar - Boolean responsable - LocalDate dateAdhesion - String region (@Size(max=50)) - String ville (@Size(max=50)) - String quartier (@Size(max=50)) - String role (@Size(max=50)) // Propriétés dérivées (calculées) + getInitiales(): String + getTypeMembre(): String + getTypeSeverity(): String + getTypeIcon(): String + getStatutIcon(): String + getEntite(): String + getAnciennete(): String + getCotisationStatut(): String + getCotisationColor(): String + getDernierPaiement(): String + getTauxParticipation(): String + getEvenementsAnnee(): String } ``` --- ### 7.2 AssociationDTO (Client) ```java @JsonIgnoreProperties(ignoreUnknown = true) public class AssociationDTO implements Serializable { - UUID id - String nom (@NotBlank) - String nomCourt - String description - String adresse - String telephone - String email - String siteWeb - String logo - String typeAssociation (@NotNull, @JsonProperty("typeOrganisation")) - LocalDate dateFondation (@JsonProperty("dateFondation")) - String numeroRegistre (@JsonProperty("numeroEnregistrement")) - String statut - Integer nombreMembres - Integer nombreAdministrateurs - String responsablePrincipal - String telephoneResponsable - String emailResponsable - LocalDateTime dateDerniereActivite - LocalDateTime dateCreation - LocalDateTime dateModification - Long version - Boolean actif - String region - String ville - String quartier - String pays - String codePostal - String activitesPrincipales - String objectifs - String partenaires - String certifications - String reseauxSociaux - String notes - Boolean organisationPublique - Boolean accepteNouveauxMembres - Boolean cotisationObligatoire - BigDecimal budgetAnnuel - String devise - BigDecimal montantCotisationAnnuelle - String telephoneSecondaire - String emailSecondaire - UUID organisationParenteId - String nomOrganisationParente - Integer niveauHierarchique - BigDecimal latitude - BigDecimal longitude + getTypeLibelle(): String + getStatutLibelle(): String + getStatutSeverity(): String + getAdresseComplete(): String } ``` --- ### 7.3 Autres DTOs Client - `TypeOrganisationClientDTO` - `CotisationDTO` - `AdhesionDTO` - `EvenementDTO` - `DemandeAideDTO` - `AuditLogDTO` - `AnalyticsDataDTO` - `WaveBalanceDTO` - `WaveCheckoutSessionDTO` --- ## 8. SERVICES CLIENT (Client) ### 8.1 MembreService (REST Client) ```java @RestClient @RegisterRestClient(configKey = "unionflow-api") public interface MembreService { @GET @Path("/api/membres") + listerToutes(@QueryParam("page") int page, @QueryParam("size") int size): List @GET @Path("/api/membres/{id}") + obtenirMembre(@PathParam("id") UUID id): MembreDTO @POST @Path("/api/membres") + creer(MembreDTO dto): MembreDTO @PUT @Path("/api/membres/{id}") + modifier(@PathParam("id") UUID id, MembreDTO dto): MembreDTO @DELETE @Path("/api/membres/{id}") + supprimer(@PathParam("id") UUID id): void @GET @Path("/api/membres/recherche") + rechercher(@QueryParam("q") String query, @QueryParam("page") int page, @QueryParam("size") int size): List } ``` --- ### 8.2 AssociationService (REST Client) ```java @RestClient @RegisterRestClient(configKey = "unionflow-api") public interface AssociationService { @GET @Path("/api/organisations") + listerToutes(@QueryParam("page") int page, @QueryParam("size") int size): List @GET @Path("/api/organisations/{id}") + obtenirOrganisation(@PathParam("id") UUID id): AssociationDTO @POST @Path("/api/organisations") + creerOrganisation(AssociationDTO dto): AssociationDTO @PUT @Path("/api/organisations/{id}") + mettreAJourOrganisation(@PathParam("id") UUID id, AssociationDTO dto): AssociationDTO @DELETE @Path("/api/organisations/{id}") + supprimerOrganisation(@PathParam("id") UUID id): void @GET @Path("/api/organisations/recherche") + rechercheAvancee(...): List @POST @Path("/api/organisations/{id}/activer") + activerOrganisation(@PathParam("id") UUID id): void @POST @Path("/api/organisations/{id}/suspendre") + suspendreOrganisation(@PathParam("id") UUID id): void @GET @Path("/api/organisations/statistiques") + obtenirStatistiques(): Map } ``` --- ### 8.3 Autres Services Client - `TypeOrganisationClientService` - `CotisationService` - `AdhesionService` - `EvenementService` - `DemandeAideService` - `AuditService` - `NotificationClientService` - `ExportClientService` - `PreferencesService` - `WaveService` - `ValidationService` --- ## 9. BEANS JSF (Client - View) ### 9.1 MembreInscriptionBean ```java @Named("membreInscriptionBean") @ViewScoped public class MembreInscriptionBean implements Serializable { @Inject @RestClient MembreService membreService; @Inject @RestClient AssociationService associationService; @Inject ValidationService validationService; // Champs du formulaire - String prenom - String nom - LocalDate dateNaissance - String sexe - String email - String telephoneMobile - String adresse - String ville - String codePostal - String region - String pays - String profession - String situationMatrimoniale - String nationalite - String contactUrgenceNom - String contactUrgenceTelephone - String contactUrgenceLien - String organisationId - String typeAdhesion - String numeroGenere - List organisations - int etapeCourante - String membreIdString - boolean modeModification - MembreDTO membreSelectionne + init(): void @PostConstruct + chargerMembreSiModification(): void + inscrire(): String + enregistrerBrouillon(): String + preparerNouveauMembre(): void + peutAccepterNouveauMembre(): boolean + isEtapePersonnelleComplete(): boolean + isEtapeCoordonneeComplete(): boolean + isEtapeAdhesionComplete(): boolean + isEtapeDocumentsComplete(): boolean + getProgressionPourcentage(): int } ``` **Dépendances :** - `MembreService` (REST Client) - `AssociationService` (REST Client) - `ValidationService` --- ### 9.2 MembreListeBean ```java @Named("membreListeBean") @ViewScoped public class MembreListeBean implements Serializable { @Inject @RestClient MembreService membreService; @Inject @RestClient AssociationService associationService; - List membres - MembreDTO membreSelectionne - String recherche - String membreSelectionneIdString - int page = 0 - int size = 20 + init(): void @PostConstruct + chargerMembres(): void + rechercherMembres(): void + modifierMembre(MembreDTO membre): String + supprimerMembre(MembreDTO membre): void + basculerStatutMembre(MembreDTO membre): void + voirProfil(MembreDTO membre): String + chargerMembreSelectionne(): void } ``` **Dépendances :** - `MembreService` (REST Client) - `AssociationService` (REST Client) --- ### 9.3 OrganisationsBean ```java @Named("organisationsBean") @ViewScoped public class OrganisationsBean implements Serializable { @Inject @RestClient AssociationService associationService; @Inject @RestClient TypeOrganisationClientService typeOrganisationService; - List organisations - AssociationDTO nouvelleOrganisation - AssociationDTO organisationSelectionnee - List typesOrganisation - Map statistiques - String recherche - String statutFiltre - String typeFiltre - int page = 0 - int size = 20 - String statutActive = "ACTIVE" + init(): void @PostConstruct + chargerOrganisations(): void + chargerStatistiques(): void + chargerTypesOrganisation(): void + preparerNouvelleOrganisation(): void + creerOrganisation(): void + modifierOrganisation(): void + supprimerOrganisation(AssociationDTO org): void + basculerStatutOrganisation(AssociationDTO org): void + rechercherOrganisations(String query): void + recharger(): void + setOrganisationSelectionnee(AssociationDTO org): void } ``` **Dépendances :** - `AssociationService` (REST Client) - `TypeOrganisationClientService` (REST Client) --- ### 9.4 Autres Beans - `OrganisationDetailBean` - `TypeOrganisationsAdminBean` - `CotisationsBean` - `CotisationsGestionBean` - `AdhesionsBean` - `EvenementsBean` - `DemandesAideBean` - `DashboardBean` - `AuditBean` - `UserSession` - `LoginBean` - `PreferencesBean` - `ParametresBean` - `SuperAdminBean` - `UtilisateursBean` - `EntitesGestionBean` - `MembreRechercheBean` - `MembreProfilBean` - `MembreDashboardBean` - `MembreCotisationBean` - `PersonnelBean` - `FavorisBean` - `RapportsBean` - `RolesBean` - `SecurityStatusBean` - `SouscriptionBean` - `WaveBean` - `FormulaireBean` - `AdminFormulaireBean` - `DocumentsBean` - `DemandesBean` - `ConfigurationBean` - `GuideBean` - `GuestPreferences` - `NavigationBean` - `HelloView` --- ## 10. SÉCURITÉ (Client) ### 10.1 AuthenticationFilter ```java @WebFilter(urlPatterns = "/pages/*") public class AuthenticationFilter implements Filter { @Inject JwtTokenManager tokenManager; @Inject UserSession userSession; + doFilter(ServletRequest request, ServletResponse response, FilterChain chain): void + init(FilterConfig filterConfig): void + destroy(): void } ``` --- ### 10.2 JwtClientRequestFilter ```java @Provider public class JwtClientRequestFilter implements ClientRequestFilter { @Inject JwtTokenManager tokenManager; + filter(ClientRequestContext requestContext): void } ``` --- ### 10.3 JwtTokenManager ```java @ApplicationScoped public class JwtTokenManager { - String accessToken - String refreshToken - LocalDateTime tokenExpiry + getAccessToken(): String + setAccessToken(String token): void + getRefreshToken(): String + setRefreshToken(String token): void + isTokenValid(): boolean + clearTokens(): void } ``` --- ### 10.4 UserSession ```java @Named("userSession") @SessionScoped public class UserSession implements Serializable { - String username - String email - String nomComplet - String typeCompte - List roles - String accessToken - String refreshToken + init(): void @PostConstruct + logout(): String + isAuthenticated(): boolean + hasRole(String role): boolean + isSuperAdmin(): boolean + isAdmin(): boolean + isMembre(): boolean } ``` --- ## 11. DIAGRAMME DE RELATIONS ### 11.1 Relations Entités ``` BaseEntity (abstract) ↑ ├── Membre │ └── @ManyToOne → Organisation │ ├── Organisation │ ├── @OneToMany → Membre │ └── Auto-référence (organisationParenteId) │ ├── TypeOrganisationEntity │ ├── Cotisation │ └── @ManyToOne → Membre │ ├── Adhesion │ ├── @ManyToOne → Membre │ └── @ManyToOne → Organisation │ ├── Evenement │ ├── @ManyToOne → Organisation │ ├── @ManyToOne → Membre (organisateur) │ └── @OneToMany → InscriptionEvenement │ ├── InscriptionEvenement │ ├── @ManyToOne → Membre │ └── @ManyToOne → Evenement │ ├── DemandeAide │ ├── @ManyToOne → Membre (demandeur) │ ├── @ManyToOne → Membre (evaluateur) │ └── @ManyToOne → Organisation │ └── AuditLog ``` ### 11.2 Relations Services ``` MembreService └── @Inject → MembreRepository └── extends → BaseRepository OrganisationService └── @Inject → OrganisationRepository └── extends → BaseRepository TypeOrganisationService ├── @Inject → TypeOrganisationRepository │ └── extends → BaseRepository └── @Inject → KeycloakService ``` ### 11.3 Relations REST ``` MembreResource └── @Inject → MembreService OrganisationResource └── @Inject → OrganisationService TypeOrganisationResource └── @Inject → TypeOrganisationService ``` ### 11.4 Relations Client ``` MembreInscriptionBean ├── @Inject @RestClient → MembreService (interface) ├── @Inject @RestClient → AssociationService (interface) └── @Inject → ValidationService MembreListeBean ├── @Inject @RestClient → MembreService (interface) └── @Inject @RestClient → AssociationService (interface) OrganisationsBean ├── @Inject @RestClient → AssociationService (interface) └── @Inject @RestClient → TypeOrganisationClientService (interface) ``` --- ## 12. PATTERNS ET ARCHITECTURE ### 12.1 Patterns Utilisés 1. **Repository Pattern** : `BaseRepository` avec implémentations spécialisées 2. **DTO Pattern** : Séparation entités JPA / DTOs API 3. **Service Layer** : Logique métier dans les services 4. **REST Client Pattern** : Interfaces MicroProfile Rest Client côté client 5. **Bean Pattern** : Beans JSF pour la présentation 6. **Filter Pattern** : Filtres pour authentification et JWT 7. **Base Entity Pattern** : `BaseEntity` pour audit et soft delete ### 12.2 Architecture en Couches ``` ┌─────────────────────────────────────┐ │ CLIENT (JSF/PrimeFaces) │ │ - Beans (View) │ │ - DTOs Client │ │ - Services REST Client │ └─────────────────────────────────────┘ ↕ HTTP/REST ┌─────────────────────────────────────┐ │ SERVER API │ │ - Resources REST (JAX-RS) │ │ - Services │ │ - Repositories │ └─────────────────────────────────────┘ ↕ JPA ┌─────────────────────────────────────┐ │ DATABASE │ │ - Entités JPA │ │ - Relations │ └─────────────────────────────────────┘ ``` --- ## 13. POINTS D'AMÉLIORATION IDENTIFIÉS ### 13.1 Modélisation 1. **Relations manquantes** : - Pas de relation explicite `Membre` ↔ `Cotisation` (actuellement via `@ManyToOne` dans `Cotisation`) - Pas de relation `Organisation` ↔ `Evenement` (actuellement via `@ManyToOne` dans `Evenement`) 2. **Redondance** : - `MembreDTO` existe côté serveur ET client avec des différences - `AssociationDTO` (client) vs `OrganisationDTO` (serveur) - alignement partiel 3. **Champs optionnels non persistés** : - Dans `MembreInscriptionBean`, plusieurs champs (sexe, contactUrgence, etc.) ne sont pas dans `MembreDTO` serveur 4. **Enums vs Entités** : - `TypeOrganisation` existe en Enum ET en Entité (`TypeOrganisationEntity`) - risque de désynchronisation ### 13.2 Suggestions d'amélioration 1. **Unifier les DTOs** : Créer un seul DTO partagé ou mapper automatiquement 2. **Compléter les relations JPA** : Ajouter les relations bidirectionnelles manquantes 3. **Persister tous les champs** : Ajouter les champs manquants dans `Membre` ou créer une entité `ContactUrgence` 4. **Synchroniser Enum/Entité** : Utiliser uniquement l'entité `TypeOrganisationEntity` ou synchroniser automatiquement 5. **Audit complet** : S'assurer que tous les champs d'audit sont remplis automatiquement 6. **Validation cohérente** : Aligner les validations entre client et serveur --- ## 14. CONCLUSION Ce diagramme de classes représente l'architecture complète d'UnionFlow avec : - **9 entités JPA** principales - **10+ repositories** spécialisés - **15+ DTOs** serveur et client - **10+ services** métier - **15+ resources REST** - **30+ beans JSF** - **10+ enums** de statuts et types L'architecture suit les principes DRY et WOU avec des composants réutilisables et une séparation claire des responsabilités. --- **Date de génération** : 2025-01-29 **Version** : 1.0