Refactroring

This commit is contained in:
dahoud
2025-11-29 02:55:52 +00:00
parent 087cd3694b
commit 8007910494
113 changed files with 17269 additions and 5973 deletions

View File

@@ -0,0 +1,31 @@
package dev.lions.unionflow.client.constants;
/**
* Constantes pour les statuts d'organisations
* Ces valeurs doivent correspondre à l'enum StatutOrganisation du module server-api
*
* @author UnionFlow Team
* @version 1.0
*/
public final class StatutOrganisationConstants {
private StatutOrganisationConstants() {
// Classe utilitaire, pas d'instanciation
}
/** Statut actif */
public static final String ACTIVE = "ACTIVE";
/** Statut inactif */
public static final String INACTIVE = "INACTIVE";
/** Statut suspendue */
public static final String SUSPENDUE = "SUSPENDUE";
/** Statut en création */
public static final String EN_CREATION = "EN_CREATION";
/** Statut dissoute */
public static final String DISSOUTE = "DISSOUTE";
}

View File

@@ -0,0 +1,274 @@
package dev.lions.unionflow.client.dto;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.UUID;
/**
* DTO pour la gestion des adhésions côté client
* Correspond au AdhesionDTO du backend avec méthodes utilitaires pour l'affichage
*
* @author UnionFlow Team
* @version 1.0
*/
public class AdhesionDTO implements Serializable {
private static final long serialVersionUID = 1L;
private UUID id;
private String numeroReference;
private UUID membreId;
private String numeroMembre;
private String nomMembre;
private String emailMembre;
private UUID organisationId;
private String nomOrganisation;
private LocalDate dateDemande;
private BigDecimal fraisAdhesion;
private BigDecimal montantPaye;
private String codeDevise;
private String statut;
private LocalDate dateApprobation;
private LocalDateTime datePaiement;
private String methodePaiement;
private String referencePaiement;
private String motifRejet;
private String observations;
private String approuvePar;
private LocalDate dateValidation;
private LocalDateTime dateCreation;
private LocalDateTime dateModification;
private Boolean actif;
// Getters et Setters
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getNumeroReference() { return numeroReference; }
public void setNumeroReference(String numeroReference) { this.numeroReference = numeroReference; }
public UUID getMembreId() { return membreId; }
public void setMembreId(UUID membreId) { this.membreId = membreId; }
public String getNumeroMembre() { return numeroMembre; }
public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
public String getNomMembre() { return nomMembre; }
public void setNomMembre(String nomMembre) { this.nomMembre = nomMembre; }
public String getEmailMembre() { return emailMembre; }
public void setEmailMembre(String emailMembre) { this.emailMembre = emailMembre; }
public UUID getOrganisationId() { return organisationId; }
public void setOrganisationId(UUID organisationId) { this.organisationId = organisationId; }
public String getNomOrganisation() { return nomOrganisation; }
public void setNomOrganisation(String nomOrganisation) { this.nomOrganisation = nomOrganisation; }
public LocalDate getDateDemande() { return dateDemande; }
public void setDateDemande(LocalDate dateDemande) { this.dateDemande = dateDemande; }
public BigDecimal getFraisAdhesion() { return fraisAdhesion; }
public void setFraisAdhesion(BigDecimal fraisAdhesion) { this.fraisAdhesion = fraisAdhesion; }
public BigDecimal getMontantPaye() { return montantPaye != null ? montantPaye : BigDecimal.ZERO; }
public void setMontantPaye(BigDecimal montantPaye) { this.montantPaye = montantPaye; }
public String getCodeDevise() { return codeDevise; }
public void setCodeDevise(String codeDevise) { this.codeDevise = codeDevise; }
public String getStatut() { return statut; }
public void setStatut(String statut) { this.statut = statut; }
public LocalDate getDateApprobation() { return dateApprobation; }
public void setDateApprobation(LocalDate dateApprobation) { this.dateApprobation = dateApprobation; }
public LocalDateTime getDatePaiement() { return datePaiement; }
public void setDatePaiement(LocalDateTime datePaiement) { this.datePaiement = datePaiement; }
public String getMethodePaiement() { return methodePaiement; }
public void setMethodePaiement(String methodePaiement) { this.methodePaiement = methodePaiement; }
public String getReferencePaiement() { return referencePaiement; }
public void setReferencePaiement(String referencePaiement) { this.referencePaiement = referencePaiement; }
public String getMotifRejet() { return motifRejet; }
public void setMotifRejet(String motifRejet) { this.motifRejet = motifRejet; }
public String getObservations() { return observations; }
public void setObservations(String observations) { this.observations = observations; }
public String getApprouvePar() { return approuvePar; }
public void setApprouvePar(String approuvePar) { this.approuvePar = approuvePar; }
public LocalDate getDateValidation() { return dateValidation; }
public void setDateValidation(LocalDate dateValidation) { this.dateValidation = dateValidation; }
public LocalDateTime getDateCreation() { return dateCreation; }
public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
public LocalDateTime getDateModification() { return dateModification; }
public void setDateModification(LocalDateTime dateModification) { this.dateModification = dateModification; }
public Boolean getActif() { return actif; }
public void setActif(Boolean actif) { this.actif = actif; }
// Méthodes utilitaires pour l'affichage (alignées avec le backend)
/**
* Vérifie si l'adhésion est payée intégralement
*/
public boolean isPayeeIntegralement() {
return montantPaye != null && fraisAdhesion != null && montantPaye.compareTo(fraisAdhesion) >= 0;
}
/**
* Vérifie si l'adhésion est en attente de paiement
*/
public boolean isEnAttentePaiement() {
return "APPROUVEE".equals(statut) && !isPayeeIntegralement();
}
/**
* Calcule le montant restant à payer
*/
public BigDecimal getMontantRestant() {
if (fraisAdhesion == null) return BigDecimal.ZERO;
if (montantPaye == null) return fraisAdhesion;
BigDecimal restant = fraisAdhesion.subtract(montantPaye);
return restant.compareTo(BigDecimal.ZERO) > 0 ? restant : BigDecimal.ZERO;
}
/**
* Calcule le pourcentage de paiement
*/
public int getPourcentagePaiement() {
if (fraisAdhesion == null || fraisAdhesion.compareTo(BigDecimal.ZERO) == 0) return 0;
if (montantPaye == null) return 0;
return montantPaye.multiply(BigDecimal.valueOf(100))
.divide(fraisAdhesion, 0, java.math.RoundingMode.HALF_UP)
.intValue();
}
/**
* Calcule le nombre de jours depuis la demande
*/
public long getJoursDepuisDemande() {
if (dateDemande == null) return 0;
return ChronoUnit.DAYS.between(dateDemande, LocalDate.now());
}
/**
* Retourne le libellé du statut
*/
public String getStatutLibelle() {
if (statut == null) return "Non défini";
return switch (statut) {
case "EN_ATTENTE" -> "En attente";
case "APPROUVEE" -> "Approuvée";
case "REJETEE" -> "Rejetée";
case "ANNULEE" -> "Annulée";
case "EN_PAIEMENT" -> "En paiement";
case "PAYEE" -> "Payée";
default -> statut;
};
}
/**
* Retourne la sévérité du statut pour PrimeFaces
*/
public String getStatutSeverity() {
if (statut == null) return "secondary";
return switch (statut) {
case "APPROUVEE", "PAYEE" -> "success";
case "EN_ATTENTE", "EN_PAIEMENT" -> "warning";
case "REJETEE" -> "danger";
case "ANNULEE" -> "secondary";
default -> "secondary";
};
}
/**
* Retourne l'icône du statut pour PrimeFaces
*/
public String getStatutIcon() {
if (statut == null) return "pi-circle";
return switch (statut) {
case "APPROUVEE", "PAYEE" -> "pi-check";
case "EN_ATTENTE" -> "pi-clock";
case "EN_PAIEMENT" -> "pi-credit-card";
case "REJETEE" -> "pi-times";
case "ANNULEE" -> "pi-ban";
default -> "pi-circle";
};
}
/**
* Retourne le libellé de la méthode de paiement
*/
public String getMethodePaiementLibelle() {
if (methodePaiement == null) return "Non défini";
return switch (methodePaiement) {
case "ESPECES" -> "Espèces";
case "VIREMENT" -> "Virement bancaire";
case "CHEQUE" -> "Chèque";
case "WAVE_MONEY" -> "Wave Money";
case "ORANGE_MONEY" -> "Orange Money";
case "FREE_MONEY" -> "Free Money";
case "CARTE_BANCAIRE" -> "Carte bancaire";
default -> methodePaiement;
};
}
/**
* Formate la date de demande
*/
public String getDateDemandeFormatee() {
if (dateDemande == null) return "";
return dateDemande.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
}
/**
* Formate la date d'approbation
*/
public String getDateApprobationFormatee() {
if (dateApprobation == null) return "";
return dateApprobation.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
}
/**
* Formate la date de paiement
*/
public String getDatePaiementFormatee() {
if (datePaiement == null) return "";
return datePaiement.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"));
}
/**
* Formate les frais d'adhésion
*/
public String getFraisAdhesionFormatte() {
if (fraisAdhesion == null) return "0 FCFA";
return String.format("%,.0f FCFA", fraisAdhesion.doubleValue());
}
/**
* Formate le montant payé
*/
public String getMontantPayeFormatte() {
if (montantPaye == null) return "0 FCFA";
return String.format("%,.0f FCFA", montantPaye.doubleValue());
}
/**
* Formate le montant restant
*/
public String getMontantRestantFormatte() {
return String.format("%,.0f FCFA", getMontantRestant().doubleValue());
}
}

View File

@@ -0,0 +1,300 @@
package dev.lions.unionflow.client.dto;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
/**
* DTO côté client pour les données analytics
* Enrichi avec des méthodes utilitaires pour l'affichage
*
* @author UnionFlow Team
* @version 1.0
* @since 2025-01-17
*/
public class AnalyticsDataDTO implements Serializable {
private static final long serialVersionUID = 1L;
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy");
private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
private String id;
private String typeMetrique;
private String periodeAnalyse;
private BigDecimal valeur;
private BigDecimal valeurPrecedente;
private BigDecimal pourcentageEvolution;
private LocalDateTime dateDebut;
private LocalDateTime dateFin;
private LocalDateTime dateCalcul;
private String organisationId;
private String nomOrganisation;
private String utilisateurId;
private String nomUtilisateur;
private String libellePersonnalise;
private String description;
private String donneesDetaillees;
private String configurationGraphique;
private Map<String, Object> metadonnees;
private BigDecimal indicateurFiabilite;
private Integer nombreElementsAnalyses;
private Long tempsCalculMs;
private Boolean tempsReel;
private Boolean necessiteMiseAJour;
private Integer niveauPriorite;
private java.util.List<String> tags;
// Getters et Setters
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getTypeMetrique() { return typeMetrique; }
public void setTypeMetrique(String typeMetrique) { this.typeMetrique = typeMetrique; }
public String getPeriodeAnalyse() { return periodeAnalyse; }
public void setPeriodeAnalyse(String periodeAnalyse) { this.periodeAnalyse = periodeAnalyse; }
public BigDecimal getValeur() { return valeur; }
public void setValeur(BigDecimal valeur) { this.valeur = valeur; }
public BigDecimal getValeurPrecedente() { return valeurPrecedente; }
public void setValeurPrecedente(BigDecimal valeurPrecedente) { this.valeurPrecedente = valeurPrecedente; }
public BigDecimal getPourcentageEvolution() { return pourcentageEvolution; }
public void setPourcentageEvolution(BigDecimal pourcentageEvolution) { this.pourcentageEvolution = pourcentageEvolution; }
public LocalDateTime getDateDebut() { return dateDebut; }
public void setDateDebut(LocalDateTime dateDebut) { this.dateDebut = dateDebut; }
public LocalDateTime getDateFin() { return dateFin; }
public void setDateFin(LocalDateTime dateFin) { this.dateFin = dateFin; }
public LocalDateTime getDateCalcul() { return dateCalcul; }
public void setDateCalcul(LocalDateTime dateCalcul) { this.dateCalcul = dateCalcul; }
public String getOrganisationId() { return organisationId; }
public void setOrganisationId(String organisationId) { this.organisationId = organisationId; }
public String getNomOrganisation() { return nomOrganisation; }
public void setNomOrganisation(String nomOrganisation) { this.nomOrganisation = nomOrganisation; }
public String getUtilisateurId() { return utilisateurId; }
public void setUtilisateurId(String utilisateurId) { this.utilisateurId = utilisateurId; }
public String getNomUtilisateur() { return nomUtilisateur; }
public void setNomUtilisateur(String nomUtilisateur) { this.nomUtilisateur = nomUtilisateur; }
public String getLibellePersonnalise() { return libellePersonnalise; }
public void setLibellePersonnalise(String libellePersonnalise) { this.libellePersonnalise = libellePersonnalise; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getDonneesDetaillees() { return donneesDetaillees; }
public void setDonneesDetaillees(String donneesDetaillees) { this.donneesDetaillees = donneesDetaillees; }
public String getConfigurationGraphique() { return configurationGraphique; }
public void setConfigurationGraphique(String configurationGraphique) { this.configurationGraphique = configurationGraphique; }
public Map<String, Object> getMetadonnees() { return metadonnees; }
public void setMetadonnees(Map<String, Object> metadonnees) { this.metadonnees = metadonnees; }
public BigDecimal getIndicateurFiabilite() { return indicateurFiabilite; }
public void setIndicateurFiabilite(BigDecimal indicateurFiabilite) { this.indicateurFiabilite = indicateurFiabilite; }
public Integer getNombreElementsAnalyses() { return nombreElementsAnalyses; }
public void setNombreElementsAnalyses(Integer nombreElementsAnalyses) { this.nombreElementsAnalyses = nombreElementsAnalyses; }
public Long getTempsCalculMs() { return tempsCalculMs; }
public void setTempsCalculMs(Long tempsCalculMs) { this.tempsCalculMs = tempsCalculMs; }
public Boolean getTempsReel() { return tempsReel; }
public void setTempsReel(Boolean tempsReel) { this.tempsReel = tempsReel; }
public Boolean getNecessiteMiseAJour() { return necessiteMiseAJour; }
public void setNecessiteMiseAJour(Boolean necessiteMiseAJour) { this.necessiteMiseAJour = necessiteMiseAJour; }
public Integer getNiveauPriorite() { return niveauPriorite; }
public void setNiveauPriorite(Integer niveauPriorite) { this.niveauPriorite = niveauPriorite; }
public java.util.List<String> getTags() { return tags; }
public void setTags(java.util.List<String> tags) { this.tags = tags; }
// === MÉTHODES UTILITAIRES ===
/**
* Retourne le libellé à afficher
*/
public String getLibelleAffichage() {
if (libellePersonnalise != null && !libellePersonnalise.trim().isEmpty()) {
return libellePersonnalise;
}
return typeMetrique != null ? typeMetrique : "Métrique";
}
/**
* Retourne la valeur formatée
*/
public String getValeurFormatee() {
if (valeur == null) return "0";
return valeur.toPlainString();
}
/**
* Retourne le pourcentage d'évolution formaté
*/
public String getEvolutionFormatee() {
if (pourcentageEvolution == null) return "0%";
String signe = pourcentageEvolution.compareTo(BigDecimal.ZERO) >= 0 ? "+" : "";
return signe + pourcentageEvolution.setScale(2, java.math.RoundingMode.HALF_UP) + "%";
}
/**
* Retourne la couleur selon l'évolution
*/
public String getCouleurEvolution() {
if (pourcentageEvolution == null) return "text-600";
if (pourcentageEvolution.compareTo(BigDecimal.ZERO) > 0) return "text-green-500";
if (pourcentageEvolution.compareTo(BigDecimal.ZERO) < 0) return "text-red-500";
return "text-600";
}
/**
* Retourne l'icône selon l'évolution
*/
public String getIconeEvolution() {
if (pourcentageEvolution == null) return "pi pi-minus";
if (pourcentageEvolution.compareTo(BigDecimal.ZERO) > 0) return "pi pi-arrow-up";
if (pourcentageEvolution.compareTo(BigDecimal.ZERO) < 0) return "pi pi-arrow-down";
return "pi pi-minus";
}
/**
* Vérifie si l'évolution est positive
*/
public boolean hasEvolutionPositive() {
return pourcentageEvolution != null && pourcentageEvolution.compareTo(BigDecimal.ZERO) > 0;
}
/**
* Vérifie si l'évolution est négative
*/
public boolean hasEvolutionNegative() {
return pourcentageEvolution != null && pourcentageEvolution.compareTo(BigDecimal.ZERO) < 0;
}
/**
* Vérifie si les données sont fiables
*/
public boolean isDonneesFiables() {
return indicateurFiabilite != null && indicateurFiabilite.compareTo(new BigDecimal("80.0")) >= 0;
}
/**
* Retourne la date de début formatée
*/
public String getDateDebutFormatee() {
if (dateDebut == null) return "";
return dateDebut.format(DATE_FORMATTER);
}
/**
* Retourne la date de fin formatée
*/
public String getDateFinFormatee() {
if (dateFin == null) return "";
return dateFin.format(DATE_FORMATTER);
}
/**
* Retourne la période formatée
*/
public String getPeriodeFormatee() {
return getDateDebutFormatee() + " - " + getDateFinFormatee();
}
/**
* Convertit depuis une Map (réponse JSON du backend)
*/
public static AnalyticsDataDTO fromMap(Map<String, Object> map) {
AnalyticsDataDTO dto = new AnalyticsDataDTO();
if (map == null) return dto;
dto.setId((String) map.get("id"));
dto.setTypeMetrique((String) map.get("typeMetrique"));
dto.setPeriodeAnalyse((String) map.get("periodeAnalyse"));
if (map.get("valeur") != null) {
dto.setValeur(new BigDecimal(map.get("valeur").toString()));
}
if (map.get("valeurPrecedente") != null) {
dto.setValeurPrecedente(new BigDecimal(map.get("valeurPrecedente").toString()));
}
if (map.get("pourcentageEvolution") != null) {
dto.setPourcentageEvolution(new BigDecimal(map.get("pourcentageEvolution").toString()));
}
// Conversion des dates depuis des strings ISO
if (map.get("dateDebut") != null) {
dto.setDateDebut(parseDateTime(map.get("dateDebut").toString()));
}
if (map.get("dateFin") != null) {
dto.setDateFin(parseDateTime(map.get("dateFin").toString()));
}
if (map.get("dateCalcul") != null) {
dto.setDateCalcul(parseDateTime(map.get("dateCalcul").toString()));
}
dto.setOrganisationId((String) map.get("organisationId"));
dto.setNomOrganisation((String) map.get("nomOrganisation"));
dto.setUtilisateurId((String) map.get("utilisateurId"));
dto.setNomUtilisateur((String) map.get("nomUtilisateur"));
dto.setLibellePersonnalise((String) map.get("libellePersonnalise"));
dto.setDescription((String) map.get("description"));
dto.setDonneesDetaillees((String) map.get("donneesDetaillees"));
dto.setConfigurationGraphique((String) map.get("configurationGraphique"));
dto.setMetadonnees((Map<String, Object>) map.get("metadonnees"));
if (map.get("indicateurFiabilite") != null) {
dto.setIndicateurFiabilite(new BigDecimal(map.get("indicateurFiabilite").toString()));
}
if (map.get("nombreElementsAnalyses") != null) {
dto.setNombreElementsAnalyses(Integer.valueOf(map.get("nombreElementsAnalyses").toString()));
}
if (map.get("tempsCalculMs") != null) {
dto.setTempsCalculMs(Long.valueOf(map.get("tempsCalculMs").toString()));
}
dto.setTempsReel((Boolean) map.get("tempsReel"));
dto.setNecessiteMiseAJour((Boolean) map.get("necessiteMiseAJour"));
if (map.get("niveauPriorite") != null) {
dto.setNiveauPriorite(Integer.valueOf(map.get("niveauPriorite").toString()));
}
@SuppressWarnings("unchecked")
java.util.List<String> tagsList = (java.util.List<String>) map.get("tags");
dto.setTags(tagsList);
return dto;
}
/**
* Parse une date depuis une string ISO
*/
private static LocalDateTime parseDateTime(String dateStr) {
if (dateStr == null || dateStr.isEmpty()) return null;
try {
// Format ISO: "2025-01-17T10:30:00" ou "2025-01-17 10:30:00"
String normalized = dateStr.replace(" ", "T");
if (normalized.length() == 10) {
normalized += "T00:00:00";
}
return LocalDateTime.parse(normalized);
} catch (Exception e) {
return null;
}
}
}

View File

@@ -1,6 +1,7 @@
package dev.lions.unionflow.client.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;
@@ -24,6 +25,7 @@ public class AssociationDTO implements Serializable {
private String siteWeb;
@NotNull(message = "Le type d'association est obligatoire")
@JsonProperty("typeOrganisation")
private String typeAssociation;
@JsonFormat(pattern = "yyyy-MM-dd")
@@ -42,6 +44,7 @@ public class AssociationDTO implements Serializable {
private String region;
private String ville;
private String quartier;
private String pays;
// Constructeurs
public AssociationDTO() {}
@@ -111,6 +114,9 @@ public class AssociationDTO implements Serializable {
public String getQuartier() { return quartier; }
public void setQuartier(String quartier) { this.quartier = quartier; }
public String getPays() { return pays; }
public void setPays(String pays) { this.pays = pays; }
// Propriétés dérivées
public String getTypeLibelle() {

View File

@@ -0,0 +1,185 @@
package dev.lions.unionflow.client.dto;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
/**
* DTO côté client pour les logs d'audit
* Correspond au AuditLogDTO du backend avec méthodes utilitaires pour l'affichage
*
* @author UnionFlow Team
* @version 1.0
*/
public class AuditLogDTO implements Serializable {
private static final long serialVersionUID = 1L;
private UUID id;
private String typeAction;
private String severite;
private String utilisateur;
private String role;
private String module;
private String description;
private String details;
private String ipAddress;
private String userAgent;
private String sessionId;
private LocalDateTime dateHeure;
private String donneesAvant;
private String donneesApres;
private String entiteId;
private String entiteType;
// Getters et Setters
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getTypeAction() { return typeAction; }
public void setTypeAction(String typeAction) { this.typeAction = typeAction; }
public String getSeverite() { return severite; }
public void setSeverite(String severite) { this.severite = severite; }
public String getUtilisateur() { return utilisateur; }
public void setUtilisateur(String utilisateur) { this.utilisateur = utilisateur; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public String getModule() { return module; }
public void setModule(String module) { this.module = module; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getDetails() { return details; }
public void setDetails(String details) { this.details = details; }
public String getIpAddress() { return ipAddress; }
public void setIpAddress(String ipAddress) { this.ipAddress = ipAddress; }
public String getUserAgent() { return userAgent; }
public void setUserAgent(String userAgent) { this.userAgent = userAgent; }
public String getSessionId() { return sessionId; }
public void setSessionId(String sessionId) { this.sessionId = sessionId; }
public LocalDateTime getDateHeure() { return dateHeure; }
public void setDateHeure(LocalDateTime dateHeure) { this.dateHeure = dateHeure; }
public String getDonneesAvant() { return donneesAvant; }
public void setDonneesAvant(String donneesAvant) { this.donneesAvant = donneesAvant; }
public String getDonneesApres() { return donneesApres; }
public void setDonneesApres(String donneesApres) { this.donneesApres = donneesApres; }
public String getEntiteId() { return entiteId; }
public void setEntiteId(String entiteId) { this.entiteId = entiteId; }
public String getEntiteType() { return entiteType; }
public void setEntiteType(String entiteType) { this.entiteType = entiteType; }
// Méthodes utilitaires pour l'affichage
public String getDateFormatee() {
if (dateHeure == null) return "";
return dateHeure.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
}
public String getHeureFormatee() {
if (dateHeure == null) return "";
return dateHeure.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
}
public String getDateHeureComplete() {
if (dateHeure == null) return "";
return dateHeure.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"));
}
public String getSeveriteLibelle() {
if (severite == null) return "";
return switch (severite) {
case "SUCCESS" -> "Succès";
case "INFO" -> "Info";
case "WARNING" -> "Attention";
case "ERROR" -> "Erreur";
case "CRITICAL" -> "Critique";
default -> severite;
};
}
public String getSeveriteSeverity() {
if (severite == null) return "secondary";
return switch (severite) {
case "SUCCESS" -> "success";
case "INFO" -> "info";
case "WARNING" -> "warning";
case "ERROR", "CRITICAL" -> "danger";
default -> "secondary";
};
}
public String getSeveriteIcon() {
if (severite == null) return "pi pi-circle";
return switch (severite) {
case "SUCCESS" -> "pi pi-check";
case "INFO" -> "pi pi-info";
case "WARNING" -> "pi pi-exclamation-triangle";
case "ERROR" -> "pi pi-times";
case "CRITICAL" -> "pi pi-ban";
default -> "pi pi-circle";
};
}
public String getActionIcon() {
if (typeAction == null) return "pi pi-circle";
return switch (typeAction) {
case "CONNEXION" -> "pi pi-sign-in";
case "DECONNEXION" -> "pi pi-sign-out";
case "CREATION" -> "pi pi-plus";
case "MODIFICATION" -> "pi pi-pencil";
case "SUPPRESSION" -> "pi pi-trash";
case "CONSULTATION" -> "pi pi-eye";
case "EXPORT" -> "pi pi-download";
case "CONFIGURATION" -> "pi pi-cog";
default -> "pi pi-circle";
};
}
public String getActionLibelle() {
if (typeAction == null) return "";
return switch (typeAction) {
case "CONNEXION" -> "Connexion";
case "DECONNEXION" -> "Déconnexion";
case "CREATION" -> "Création";
case "MODIFICATION" -> "Modification";
case "SUPPRESSION" -> "Suppression";
case "CONSULTATION" -> "Consultation";
case "EXPORT" -> "Export";
case "CONFIGURATION" -> "Configuration";
default -> typeAction;
};
}
public String getModuleLibelle() {
if (module == null) return "";
return switch (module) {
case "AUTH" -> "Authentification";
case "MEMBRES" -> "Membres";
case "COTISATIONS" -> "Cotisations";
case "EVENTS" -> "Événements";
case "DOCUMENTS" -> "Documents";
case "CONFIG" -> "Configuration";
case "RAPPORTS" -> "Rapports";
default -> module;
};
}
public String getUserAgentCourt() {
if (userAgent == null || userAgent.isEmpty()) return "";
return userAgent.length() > 50 ? userAgent.substring(0, 50) + "..." : userAgent;
}
}

View File

@@ -4,8 +4,17 @@ import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.UUID;
/**
* DTO pour la gestion des cotisations côté client
* Correspond au CotisationDTO du backend avec méthodes utilitaires pour l'affichage
*
* @author UnionFlow Team
* @version 1.0
*/
public class CotisationDTO implements Serializable {
private static final long serialVersionUID = 1L;
@@ -27,8 +36,10 @@ public class CotisationDTO implements Serializable {
private LocalDate dateEcheance;
private LocalDateTime datePaiement;
private String methodePaiement;
private String referencePaiement;
private String observations;
private LocalDateTime dateCreation;
private String waveSessionId;
// Getters et Setters
public UUID getId() { return id; }
@@ -64,7 +75,7 @@ public class CotisationDTO implements Serializable {
public BigDecimal getMontantDu() { return montantDu; }
public void setMontantDu(BigDecimal montantDu) { this.montantDu = montantDu; }
public BigDecimal getMontantPaye() { return montantPaye; }
public BigDecimal getMontantPaye() { return montantPaye != null ? montantPaye : BigDecimal.ZERO; }
public void setMontantPaye(BigDecimal montantPaye) { this.montantPaye = montantPaye; }
public String getCodeDevise() { return codeDevise; }
@@ -82,10 +93,178 @@ public class CotisationDTO implements Serializable {
public String getMethodePaiement() { return methodePaiement; }
public void setMethodePaiement(String methodePaiement) { this.methodePaiement = methodePaiement; }
public String getReferencePaiement() { return referencePaiement; }
public void setReferencePaiement(String referencePaiement) { this.referencePaiement = referencePaiement; }
public String getObservations() { return observations; }
public void setObservations(String observations) { this.observations = observations; }
public LocalDateTime getDateCreation() { return dateCreation; }
public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
public String getWaveSessionId() { return waveSessionId; }
public void setWaveSessionId(String waveSessionId) { this.waveSessionId = waveSessionId; }
// Méthodes utilitaires pour l'affichage (alignées avec le backend)
/**
* Vérifie si la cotisation est payée intégralement
*/
public boolean isPayeeIntegralement() {
return montantPaye != null && montantDu != null && montantPaye.compareTo(montantDu) >= 0;
}
/**
* Vérifie si la cotisation est en retard
*/
public boolean isEnRetard() {
return dateEcheance != null && LocalDate.now().isAfter(dateEcheance) && !isPayeeIntegralement();
}
/**
* Calcule le montant restant à payer
*/
public BigDecimal getMontantRestant() {
if (montantDu == null) return BigDecimal.ZERO;
if (montantPaye == null) return montantDu;
BigDecimal restant = montantDu.subtract(montantPaye);
return restant.compareTo(BigDecimal.ZERO) > 0 ? restant : BigDecimal.ZERO;
}
/**
* Calcule le pourcentage de paiement
*/
public int getPourcentagePaiement() {
if (montantDu == null || montantDu.compareTo(BigDecimal.ZERO) == 0) return 0;
if (montantPaye == null) return 0;
return montantPaye.multiply(BigDecimal.valueOf(100))
.divide(montantDu, 0, java.math.RoundingMode.HALF_UP)
.intValue();
}
/**
* Calcule le nombre de jours de retard
*/
public long getJoursRetard() {
if (dateEcheance == null || !isEnRetard()) return 0;
return ChronoUnit.DAYS.between(dateEcheance, LocalDate.now());
}
/**
* Retourne le libellé du type de cotisation
*/
public String getTypeCotisationLibelle() {
if (typeCotisation == null) return "Non défini";
return switch (typeCotisation) {
case "MENSUELLE" -> "Mensuelle";
case "TRIMESTRIELLE" -> "Trimestrielle";
case "SEMESTRIELLE" -> "Semestrielle";
case "ANNUELLE" -> "Annuelle";
case "EXCEPTIONNELLE" -> "Exceptionnelle";
case "ADHESION" -> "Adhésion";
default -> typeCotisation;
};
}
/**
* Retourne le libellé du statut
*/
public String getStatutLibelle() {
if (statut == null) return "Non défini";
return switch (statut) {
case "EN_ATTENTE" -> "En attente";
case "PAYEE" -> "Payée";
case "PARTIELLEMENT_PAYEE" -> "Partiellement payée";
case "EN_RETARD" -> "En retard";
case "ANNULEE" -> "Annulée";
case "REMBOURSEE" -> "Remboursée";
default -> statut;
};
}
/**
* Retourne le libellé de la méthode de paiement
*/
public String getMethodePaiementLibelle() {
if (methodePaiement == null) return "Non défini";
return switch (methodePaiement) {
case "ESPECES" -> "Espèces";
case "VIREMENT" -> "Virement bancaire";
case "CHEQUE" -> "Chèque";
case "WAVE_MONEY" -> "Wave Money";
case "ORANGE_MONEY" -> "Orange Money";
case "FREE_MONEY" -> "Free Money";
case "CARTE_BANCAIRE" -> "Carte bancaire";
default -> methodePaiement;
};
}
/**
* Retourne la sévérité du statut pour PrimeFaces
*/
public String getStatutSeverity() {
if (statut == null) return "secondary";
return switch (statut) {
case "PAYEE" -> "success";
case "EN_ATTENTE" -> "warning";
case "EN_RETARD" -> "danger";
case "PARTIELLEMENT_PAYEE" -> "info";
case "ANNULEE", "REMBOURSEE" -> "secondary";
default -> "secondary";
};
}
/**
* Retourne l'icône du statut pour PrimeFaces
*/
public String getStatutIcon() {
if (statut == null) return "pi-circle";
return switch (statut) {
case "PAYEE" -> "pi-check";
case "EN_ATTENTE" -> "pi-clock";
case "EN_RETARD" -> "pi-exclamation-triangle";
case "PARTIELLEMENT_PAYEE" -> "pi-minus";
default -> "pi-circle";
};
}
/**
* Formate la date d'échéance
*/
public String getDateEcheanceFormatee() {
if (dateEcheance == null) return "";
return dateEcheance.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
}
/**
* Formate la date de paiement
*/
public String getDatePaiementFormatee() {
if (datePaiement == null) return "";
return datePaiement.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"));
}
/**
* Formate le montant dû
*/
public String getMontantDuFormatte() {
if (montantDu == null) return "0 FCFA";
return String.format("%,.0f FCFA", montantDu.doubleValue());
}
/**
* Formate le montant payé
*/
public String getMontantPayeFormatte() {
if (montantPaye == null) return "0 FCFA";
return String.format("%,.0f FCFA", montantPaye.doubleValue());
}
/**
* Formate le montant restant
*/
public String getMontantRestantFormatte() {
return String.format("%,.0f FCFA", getMontantRestant().doubleValue());
}
}

View File

@@ -5,31 +5,82 @@ import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.UUID;
/**
* DTO pour la gestion des événements côté client
* Correspond au EvenementDTO du backend avec méthodes utilitaires pour l'affichage
*
* @author UnionFlow Team
* @version 2.0
*/
public class EvenementDTO implements Serializable {
private static final long serialVersionUID = 1L;
// Propriétés de base
private UUID id;
private String titre;
private String description;
private String type;
private String statut;
private String priorite;
private String typeEvenement; // ASSEMBLEE_GENERALE, FORMATION, etc.
private String statut; // PLANIFIE, CONFIRME, EN_COURS, TERMINE, ANNULE, REPORTE
private String priorite; // CRITIQUE, HAUTE, NORMALE, BASSE
// Dates et heures
private LocalDate dateDebut;
private LocalDate dateFin;
private LocalTime heureDebut;
private LocalTime heureFin;
private LocalDate dateLimiteInscription;
// Localisation
private String lieu;
private String adresse;
private String ville;
private String region;
private BigDecimal latitude;
private BigDecimal longitude;
// Organisation
private UUID associationId;
private String nomAssociation;
private String organisateur;
private String organisateurEmail;
private String emailOrganisateur;
private String telephoneOrganisateur;
// Participants
private Integer capaciteMax;
private Integer participantsInscrits;
private Integer participantsPresents;
// Budget
private BigDecimal budget;
private UUID organisationId;
private BigDecimal coutReel;
private String codeDevise;
// Options
private Boolean inscriptionObligatoire;
private Boolean evenementPublic;
private Boolean recurrent;
private String frequenceRecurrence;
// Informations complémentaires
private String instructions;
private String materielNecessaire;
private String conditionsMeteo;
private String imageUrl;
private String couleurTheme;
// Annulation
private LocalDateTime dateAnnulation;
private String raisonAnnulation;
private String nomAnnulateur;
// Métadonnées
private LocalDateTime dateCreation;
private LocalDateTime dateModification;
// Getters et Setters
public UUID getId() { return id; }
@@ -41,8 +92,8 @@ public class EvenementDTO implements Serializable {
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getTypeEvenement() { return typeEvenement; }
public void setTypeEvenement(String typeEvenement) { this.typeEvenement = typeEvenement; }
public String getStatut() { return statut; }
public void setStatut(String statut) { this.statut = statut; }
@@ -62,31 +113,380 @@ public class EvenementDTO implements Serializable {
public LocalTime getHeureFin() { return heureFin; }
public void setHeureFin(LocalTime heureFin) { this.heureFin = heureFin; }
public LocalDate getDateLimiteInscription() { return dateLimiteInscription; }
public void setDateLimiteInscription(LocalDate dateLimiteInscription) { this.dateLimiteInscription = dateLimiteInscription; }
public String getLieu() { return lieu; }
public void setLieu(String lieu) { this.lieu = lieu; }
public String getAdresse() { return adresse; }
public void setAdresse(String adresse) { this.adresse = adresse; }
public String getVille() { return ville; }
public void setVille(String ville) { this.ville = ville; }
public String getRegion() { return region; }
public void setRegion(String region) { this.region = region; }
public BigDecimal getLatitude() { return latitude; }
public void setLatitude(BigDecimal latitude) { this.latitude = latitude; }
public BigDecimal getLongitude() { return longitude; }
public void setLongitude(BigDecimal longitude) { this.longitude = longitude; }
public UUID getAssociationId() { return associationId; }
public void setAssociationId(UUID associationId) { this.associationId = associationId; }
public String getNomAssociation() { return nomAssociation; }
public void setNomAssociation(String nomAssociation) { this.nomAssociation = nomAssociation; }
public String getOrganisateur() { return organisateur; }
public void setOrganisateur(String organisateur) { this.organisateur = organisateur; }
public String getOrganisateurEmail() { return organisateurEmail; }
public void setOrganisateurEmail(String organisateurEmail) { this.organisateurEmail = organisateurEmail; }
public String getEmailOrganisateur() { return emailOrganisateur; }
public void setEmailOrganisateur(String emailOrganisateur) { this.emailOrganisateur = emailOrganisateur; }
public String getTelephoneOrganisateur() { return telephoneOrganisateur; }
public void setTelephoneOrganisateur(String telephoneOrganisateur) { this.telephoneOrganisateur = telephoneOrganisateur; }
public Integer getCapaciteMax() { return capaciteMax; }
public void setCapaciteMax(Integer capaciteMax) { this.capaciteMax = capaciteMax; }
public Integer getParticipantsInscrits() { return participantsInscrits; }
public Integer getParticipantsInscrits() { return participantsInscrits != null ? participantsInscrits : 0; }
public void setParticipantsInscrits(Integer participantsInscrits) { this.participantsInscrits = participantsInscrits; }
public Integer getParticipantsPresents() { return participantsPresents != null ? participantsPresents : 0; }
public void setParticipantsPresents(Integer participantsPresents) { this.participantsPresents = participantsPresents; }
public BigDecimal getBudget() { return budget; }
public void setBudget(BigDecimal budget) { this.budget = budget; }
public UUID getOrganisationId() { return organisationId; }
public void setOrganisationId(UUID organisationId) { this.organisationId = organisationId; }
public BigDecimal getCoutReel() { return coutReel; }
public void setCoutReel(BigDecimal coutReel) { this.coutReel = coutReel; }
public String getCodeDevise() { return codeDevise != null ? codeDevise : "XOF"; }
public void setCodeDevise(String codeDevise) { this.codeDevise = codeDevise; }
public Boolean getInscriptionObligatoire() { return inscriptionObligatoire != null ? inscriptionObligatoire : false; }
public void setInscriptionObligatoire(Boolean inscriptionObligatoire) { this.inscriptionObligatoire = inscriptionObligatoire; }
public Boolean getEvenementPublic() { return evenementPublic != null ? evenementPublic : true; }
public void setEvenementPublic(Boolean evenementPublic) { this.evenementPublic = evenementPublic; }
public Boolean getRecurrent() { return recurrent != null ? recurrent : false; }
public void setRecurrent(Boolean recurrent) { this.recurrent = recurrent; }
public String getFrequenceRecurrence() { return frequenceRecurrence; }
public void setFrequenceRecurrence(String frequenceRecurrence) { this.frequenceRecurrence = frequenceRecurrence; }
public String getInstructions() { return instructions; }
public void setInstructions(String instructions) { this.instructions = instructions; }
public String getMaterielNecessaire() { return materielNecessaire; }
public void setMaterielNecessaire(String materielNecessaire) { this.materielNecessaire = materielNecessaire; }
public String getConditionsMeteo() { return conditionsMeteo; }
public void setConditionsMeteo(String conditionsMeteo) { this.conditionsMeteo = conditionsMeteo; }
public String getImageUrl() { return imageUrl; }
public void setImageUrl(String imageUrl) { this.imageUrl = imageUrl; }
public String getCouleurTheme() { return couleurTheme; }
public void setCouleurTheme(String couleurTheme) { this.couleurTheme = couleurTheme; }
public LocalDateTime getDateAnnulation() { return dateAnnulation; }
public void setDateAnnulation(LocalDateTime dateAnnulation) { this.dateAnnulation = dateAnnulation; }
public String getRaisonAnnulation() { return raisonAnnulation; }
public void setRaisonAnnulation(String raisonAnnulation) { this.raisonAnnulation = raisonAnnulation; }
public String getNomAnnulateur() { return nomAnnulateur; }
public void setNomAnnulateur(String nomAnnulateur) { this.nomAnnulateur = nomAnnulateur; }
public LocalDateTime getDateCreation() { return dateCreation; }
public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
public LocalDateTime getDateModification() { return dateModification; }
public void setDateModification(LocalDateTime dateModification) { this.dateModification = dateModification; }
// Méthodes utilitaires pour l'affichage
/**
* Retourne le libellé du type d'événement
*/
public String getTypeEvenementLibelle() {
if (typeEvenement == null) return "Non défini";
return switch (typeEvenement) {
case "ASSEMBLEE_GENERALE" -> "Assemblée Générale";
case "FORMATION" -> "Formation";
case "ACTIVITE_SOCIALE" -> "Activité Sociale";
case "ACTION_CARITATIVE" -> "Action Caritative";
case "REUNION_BUREAU" -> "Réunion de Bureau";
case "CONFERENCE" -> "Conférence";
case "ATELIER" -> "Atelier";
case "CEREMONIE" -> "Cérémonie";
case "AUTRE" -> "Autre";
default -> typeEvenement;
};
}
/**
* Retourne la sévérité PrimeFaces pour le type
*/
public String getTypeEvenementSeverity() {
if (typeEvenement == null) return "info";
return switch (typeEvenement) {
case "ASSEMBLEE_GENERALE" -> "danger";
case "REUNION_BUREAU" -> "warning";
case "FORMATION" -> "success";
case "ACTION_CARITATIVE" -> "info";
case "ACTIVITE_SOCIALE" -> "secondary";
default -> "primary";
};
}
/**
* Retourne l'icône PrimeFaces pour le type
*/
public String getTypeEvenementIcon() {
if (typeEvenement == null) return "pi-calendar";
return switch (typeEvenement) {
case "ASSEMBLEE_GENERALE" -> "pi-sitemap";
case "REUNION_BUREAU" -> "pi-users";
case "FORMATION" -> "pi-book";
case "ACTION_CARITATIVE", "ACTIVITE_SOCIALE" -> "pi-heart";
case "CONFERENCE" -> "pi-microphone";
case "ATELIER" -> "pi-wrench";
case "CEREMONIE" -> "pi-star";
default -> "pi-calendar";
};
}
/**
* Retourne le libellé du statut
*/
public String getStatutLibelle() {
if (statut == null) return "Non défini";
return switch (statut) {
case "PLANIFIE" -> "Planifié";
case "CONFIRME" -> "Confirmé";
case "EN_COURS" -> "En cours";
case "TERMINE" -> "Terminé";
case "ANNULE" -> "Annulé";
case "REPORTE" -> "Reporté";
default -> statut;
};
}
/**
* Retourne la sévérité PrimeFaces pour le statut
*/
public String getStatutSeverity() {
if (statut == null) return "info";
return switch (statut) {
case "PLANIFIE" -> "info";
case "CONFIRME" -> "success";
case "EN_COURS" -> "warning";
case "TERMINE" -> "success";
case "ANNULE" -> "error";
case "REPORTE" -> "warn";
default -> "info";
};
}
/**
* Retourne l'icône PrimeFaces pour le statut
*/
public String getStatutIcon() {
if (statut == null) return "pi-circle";
return switch (statut) {
case "PLANIFIE" -> "pi-clock";
case "CONFIRME" -> "pi-check-circle";
case "EN_COURS" -> "pi-play";
case "TERMINE" -> "pi-check";
case "ANNULE" -> "pi-ban";
case "REPORTE" -> "pi-calendar-times";
default -> "pi-circle";
};
}
/**
* Retourne le libellé de la priorité
*/
public String getPrioriteLibelle() {
if (priorite == null) return "Normale";
return switch (priorite) {
case "CRITIQUE" -> "Critique";
case "HAUTE" -> "Haute";
case "NORMALE" -> "Normale";
case "BASSE" -> "Basse";
default -> priorite;
};
}
/**
* Retourne la sévérité PrimeFaces pour la priorité
*/
public String getPrioriteSeverity() {
if (priorite == null) return "info";
return switch (priorite) {
case "CRITIQUE" -> "error";
case "HAUTE" -> "warning";
case "NORMALE" -> "info";
case "BASSE" -> "secondary";
default -> "info";
};
}
/**
* Formate la date de début
*/
public String getDateDebutFormatee() {
if (dateDebut == null) return "";
return dateDebut.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
}
/**
* Formate la date de fin
*/
public String getDateFinFormatee() {
if (dateFin == null) return "";
return dateFin.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
}
/**
* Formate l'heure de début
*/
public String getHeureDebutFormatee() {
if (heureDebut == null) return "";
return heureDebut.format(DateTimeFormatter.ofPattern("HH:mm"));
}
/**
* Formate l'heure de fin
*/
public String getHeureFinFormatee() {
if (heureFin == null) return "";
return heureFin.format(DateTimeFormatter.ofPattern("HH:mm"));
}
/**
* Formate le budget
*/
public String getBudgetFormate() {
if (budget == null) return "0 FCFA";
return String.format("%,.0f %s", budget.doubleValue(), getCodeDevise());
}
/**
* Calcule le nombre de places disponibles
*/
public int getPlacesDisponibles() {
if (capaciteMax == null || capaciteMax == 0) return 0;
int inscrits = getParticipantsInscrits();
return Math.max(0, capaciteMax - inscrits);
}
/**
* Calcule le taux de remplissage en pourcentage
*/
public int getTauxRemplissage() {
if (capaciteMax == null || capaciteMax == 0) return 0;
int inscrits = getParticipantsInscrits();
return (inscrits * 100) / capaciteMax;
}
/**
* Calcule le taux de présence en pourcentage
*/
public int getTauxPresence() {
int inscrits = getParticipantsInscrits();
if (inscrits == 0) return 0;
int presents = getParticipantsPresents();
return (presents * 100) / inscrits;
}
/**
* Calcule le nombre de jours restants avant l'événement
*/
public long getJoursRestants() {
if (dateDebut == null) return 0;
return ChronoUnit.DAYS.between(LocalDate.now(), dateDebut);
}
/**
* Vérifie si l'événement est complet
*/
public boolean isComplet() {
if (capaciteMax == null || capaciteMax == 0) return false;
return getParticipantsInscrits() >= capaciteMax;
}
/**
* Vérifie si l'événement est en cours
*/
public boolean isEnCours() {
return "EN_COURS".equals(statut);
}
/**
* Vérifie si l'événement est terminé
*/
public boolean isTermine() {
return "TERMINE".equals(statut);
}
/**
* Vérifie si l'événement est annulé
*/
public boolean isAnnule() {
return "ANNULE".equals(statut);
}
/**
* Vérifie si les inscriptions sont ouvertes
*/
public boolean sontInscriptionsOuvertes() {
if (isAnnule() || isTermine()) return false;
if (dateLimiteInscription != null && LocalDate.now().isAfter(dateLimiteInscription)) return false;
return !isComplet();
}
/**
* Retourne l'adresse complète formatée
*/
public String getAdresseComplete() {
StringBuilder sb = new StringBuilder();
if (lieu != null && !lieu.trim().isEmpty()) {
sb.append(lieu);
}
if (adresse != null && !adresse.trim().isEmpty()) {
if (sb.length() > 0) sb.append(", ");
sb.append(adresse);
}
if (ville != null && !ville.trim().isEmpty()) {
if (sb.length() > 0) sb.append(", ");
sb.append(ville);
}
if (region != null && !region.trim().isEmpty()) {
if (sb.length() > 0) sb.append(", ");
sb.append(region);
}
return sb.toString();
}
/**
* Calcule la durée en heures
*/
public long getDureeEnHeures() {
if (heureDebut == null || heureFin == null) return 0;
return ChronoUnit.HOURS.between(heureDebut, heureFin);
}
/**
* Vérifie si l'événement dure plusieurs jours
*/
public boolean isEvenementMultiJours() {
return dateFin != null && dateDebut != null && !dateDebut.equals(dateFin);
}
}

View File

@@ -0,0 +1,57 @@
package dev.lions.unionflow.client.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.UUID;
/**
* DTO client pour le catalogue des types d'organisation.
*
* <p>Correspond au TypeOrganisationDTO du module server-api, mais sans dépendance directe.
*/
public class TypeOrganisationClientDTO implements Serializable {
private static final long serialVersionUID = 1L;
private UUID id;
private String code;
private String libelle;
private String description;
private Integer ordreAffichage;
private Boolean actif;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime dateCreation;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime dateModification;
private Long version;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getCode() { return code; }
public void setCode(String code) { this.code = code; }
public String getLibelle() { return libelle; }
public void setLibelle(String libelle) { this.libelle = libelle; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public Integer getOrdreAffichage() { return ordreAffichage; }
public void setOrdreAffichage(Integer ordreAffichage) { this.ordreAffichage = ordreAffichage; }
public Boolean getActif() { return actif; }
public void setActif(Boolean actif) { this.actif = actif; }
public LocalDateTime getDateCreation() { return dateCreation; }
public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
public LocalDateTime getDateModification() { return dateModification; }
public void setDateModification(LocalDateTime dateModification) { this.dateModification = dateModification; }
public Long getVersion() { return version; }
public void setVersion(Long version) { this.version = version; }
}

View File

@@ -0,0 +1,102 @@
package dev.lions.unionflow.client.dto;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* DTO client pour le solde Wave Money
*
* @author UnionFlow Team
* @version 1.0
* @since 2025-01-17
*/
public class WaveBalanceDTO implements Serializable {
private static final long serialVersionUID = 1L;
private BigDecimal soldeDisponible;
private BigDecimal soldeEnAttente;
private BigDecimal soldeTotal;
private String devise;
private String numeroWallet;
private String nomBusiness;
private LocalDateTime dateDerniereMiseAJour;
private LocalDateTime dateDerniereSynchronisation;
private String statutWallet;
private BigDecimal limiteQuotidienne;
private BigDecimal montantUtiliseAujourdhui;
private BigDecimal limiteMensuelle;
private BigDecimal montantUtiliseCeMois;
private Integer nombreTransactionsAujourdhui;
private Integer nombreTransactionsCeMois;
// Getters et Setters
public BigDecimal getSoldeDisponible() { return soldeDisponible; }
public void setSoldeDisponible(BigDecimal soldeDisponible) { this.soldeDisponible = soldeDisponible; }
public BigDecimal getSoldeEnAttente() { return soldeEnAttente; }
public void setSoldeEnAttente(BigDecimal soldeEnAttente) { this.soldeEnAttente = soldeEnAttente; }
public BigDecimal getSoldeTotal() { return soldeTotal; }
public void setSoldeTotal(BigDecimal soldeTotal) { this.soldeTotal = soldeTotal; }
public String getDevise() { return devise; }
public void setDevise(String devise) { this.devise = devise; }
public String getNumeroWallet() { return numeroWallet; }
public void setNumeroWallet(String numeroWallet) { this.numeroWallet = numeroWallet; }
public String getNomBusiness() { return nomBusiness; }
public void setNomBusiness(String nomBusiness) { this.nomBusiness = nomBusiness; }
public LocalDateTime getDateDerniereMiseAJour() { return dateDerniereMiseAJour; }
public void setDateDerniereMiseAJour(LocalDateTime dateDerniereMiseAJour) { this.dateDerniereMiseAJour = dateDerniereMiseAJour; }
public LocalDateTime getDateDerniereSynchronisation() { return dateDerniereSynchronisation; }
public void setDateDerniereSynchronisation(LocalDateTime dateDerniereSynchronisation) { this.dateDerniereSynchronisation = dateDerniereSynchronisation; }
public String getStatutWallet() { return statutWallet; }
public void setStatutWallet(String statutWallet) { this.statutWallet = statutWallet; }
public BigDecimal getLimiteQuotidienne() { return limiteQuotidienne; }
public void setLimiteQuotidienne(BigDecimal limiteQuotidienne) { this.limiteQuotidienne = limiteQuotidienne; }
public BigDecimal getMontantUtiliseAujourdhui() { return montantUtiliseAujourdhui; }
public void setMontantUtiliseAujourdhui(BigDecimal montantUtiliseAujourdhui) { this.montantUtiliseAujourdhui = montantUtiliseAujourdhui; }
public BigDecimal getLimiteMensuelle() { return limiteMensuelle; }
public void setLimiteMensuelle(BigDecimal limiteMensuelle) { this.limiteMensuelle = limiteMensuelle; }
public BigDecimal getMontantUtiliseCeMois() { return montantUtiliseCeMois; }
public void setMontantUtiliseCeMois(BigDecimal montantUtiliseCeMois) { this.montantUtiliseCeMois = montantUtiliseCeMois; }
public Integer getNombreTransactionsAujourdhui() { return nombreTransactionsAujourdhui; }
public void setNombreTransactionsAujourdhui(Integer nombreTransactionsAujourdhui) { this.nombreTransactionsAujourdhui = nombreTransactionsAujourdhui; }
public Integer getNombreTransactionsCeMois() { return nombreTransactionsCeMois; }
public void setNombreTransactionsCeMois(Integer nombreTransactionsCeMois) { this.nombreTransactionsCeMois = nombreTransactionsCeMois; }
/**
* Formate le solde disponible pour l'affichage
*/
public String getSoldeDisponibleFormate() {
if (soldeDisponible == null) return "0 FCFA";
return String.format("%.0f FCFA", soldeDisponible.doubleValue());
}
/**
* Formate le solde total pour l'affichage
*/
public String getSoldeTotalFormate() {
if (soldeTotal == null) return "0 FCFA";
return String.format("%.0f FCFA", soldeTotal.doubleValue());
}
/**
* Vérifie si le wallet est actif
*/
public boolean isWalletActif() {
return "ACTIVE".equals(statutWallet);
}
}

View File

@@ -0,0 +1,148 @@
package dev.lions.unionflow.client.dto;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.UUID;
/**
* DTO client pour les sessions de paiement Wave Money
*
* @author UnionFlow Team
* @version 1.0
* @since 2025-01-17
*/
public class WaveCheckoutSessionDTO implements Serializable {
private static final long serialVersionUID = 1L;
private UUID id;
private String waveSessionId;
private String waveUrl;
private BigDecimal montant;
private String devise;
private String successUrl;
private String errorUrl;
private String statut;
private UUID organisationId;
private String nomOrganisation;
private UUID membreId;
private String nomMembre;
private String typePaiement;
private String referenceUnionFlow;
private String description;
private String nomBusinessAffiche;
private LocalDateTime dateCreation;
private LocalDateTime dateExpiration;
private LocalDateTime dateCompletion;
private String telephonePayeur;
private String emailPayeur;
// Getters et Setters
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getWaveSessionId() { return waveSessionId; }
public void setWaveSessionId(String waveSessionId) { this.waveSessionId = waveSessionId; }
public String getWaveUrl() { return waveUrl; }
public void setWaveUrl(String waveUrl) { this.waveUrl = waveUrl; }
public BigDecimal getMontant() { return montant; }
public void setMontant(BigDecimal montant) { this.montant = montant; }
public String getDevise() { return devise; }
public void setDevise(String devise) { this.devise = devise; }
public String getSuccessUrl() { return successUrl; }
public void setSuccessUrl(String successUrl) { this.successUrl = successUrl; }
public String getErrorUrl() { return errorUrl; }
public void setErrorUrl(String errorUrl) { this.errorUrl = errorUrl; }
public String getStatut() { return statut; }
public void setStatut(String statut) { this.statut = statut; }
public UUID getOrganisationId() { return organisationId; }
public void setOrganisationId(UUID organisationId) { this.organisationId = organisationId; }
public String getNomOrganisation() { return nomOrganisation; }
public void setNomOrganisation(String nomOrganisation) { this.nomOrganisation = nomOrganisation; }
public UUID getMembreId() { return membreId; }
public void setMembreId(UUID membreId) { this.membreId = membreId; }
public String getNomMembre() { return nomMembre; }
public void setNomMembre(String nomMembre) { this.nomMembre = nomMembre; }
public String getTypePaiement() { return typePaiement; }
public void setTypePaiement(String typePaiement) { this.typePaiement = typePaiement; }
public String getReferenceUnionFlow() { return referenceUnionFlow; }
public void setReferenceUnionFlow(String referenceUnionFlow) { this.referenceUnionFlow = referenceUnionFlow; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getNomBusinessAffiche() { return nomBusinessAffiche; }
public void setNomBusinessAffiche(String nomBusinessAffiche) { this.nomBusinessAffiche = nomBusinessAffiche; }
public LocalDateTime getDateCreation() { return dateCreation; }
public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
public LocalDateTime getDateExpiration() { return dateExpiration; }
public void setDateExpiration(LocalDateTime dateExpiration) { this.dateExpiration = dateExpiration; }
public LocalDateTime getDateCompletion() { return dateCompletion; }
public void setDateCompletion(LocalDateTime dateCompletion) { this.dateCompletion = dateCompletion; }
public String getTelephonePayeur() { return telephonePayeur; }
public void setTelephonePayeur(String telephonePayeur) { this.telephonePayeur = telephonePayeur; }
public String getEmailPayeur() { return emailPayeur; }
public void setEmailPayeur(String emailPayeur) { this.emailPayeur = emailPayeur; }
/**
* Retourne le libellé du statut
*/
public String getStatutLibelle() {
if (statut == null) return "Inconnu";
return switch (statut) {
case "PENDING" -> "En attente";
case "COMPLETED" -> "Complétée";
case "CANCELLED" -> "Annulée";
case "EXPIRED" -> "Expirée";
case "FAILED" -> "Échouée";
default -> statut;
};
}
/**
* Retourne la sévérité PrimeFaces pour le statut
*/
public String getStatutSeverity() {
if (statut == null) return "info";
return switch (statut) {
case "PENDING" -> "warning";
case "COMPLETED" -> "success";
case "CANCELLED" -> "info";
case "EXPIRED" -> "warn";
case "FAILED" -> "error";
default -> "info";
};
}
/**
* Vérifie si la session est expirée
*/
public boolean isExpiree() {
return dateExpiration != null && LocalDateTime.now().isAfter(dateExpiration);
}
/**
* Vérifie si la session est complétée
*/
public boolean isCompletee() {
return "COMPLETED".equals(statut);
}
}

View File

@@ -20,11 +20,21 @@ public class JwtClientRequestFilter implements ClientRequestFilter {
@Override
public void filter(ClientRequestContext requestContext) throws IOException {
String authHeader = tokenManager.getAuthorizationHeader();
if (tokenManager == null) {
LOGGER.fine("JwtTokenManager non disponible, requête sans authentification");
return;
}
if (authHeader != null && !isAuthEndpoint(requestContext.getUri().getPath())) {
requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader);
LOGGER.fine("JWT token ajouté à la requête: " + requestContext.getUri());
try {
String authHeader = tokenManager.getAuthorizationHeader();
if (authHeader != null && !isAuthEndpoint(requestContext.getUri().getPath())) {
requestContext.getHeaders().add(HttpHeaders.AUTHORIZATION, authHeader);
LOGGER.fine("JWT token ajouté à la requête: " + requestContext.getUri());
}
} catch (Exception e) {
LOGGER.warning("Erreur lors de l'ajout du token JWT: " + e.getMessage());
// Continuer sans authentification plutôt que de bloquer la requête
}
}

View File

@@ -0,0 +1,150 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.client.dto.AdhesionDTO;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* Service REST client pour la gestion des adhésions
* Interface correspondant exactement au backend AdhesionResource
*
* @author UnionFlow Team
* @version 1.0
*/
@RegisterRestClient(configKey = "unionflow-api")
@Path("/api/adhesions")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface AdhesionService {
/**
* Récupère toutes les adhésions avec pagination
*/
@GET
List<AdhesionDTO> listerToutes(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Récupère une adhésion par son ID
*/
@GET
@Path("/{id}")
AdhesionDTO obtenirParId(@PathParam("id") UUID id);
/**
* Récupère une adhésion par son numéro de référence
*/
@GET
@Path("/reference/{numeroReference}")
AdhesionDTO obtenirParReference(@PathParam("numeroReference") String numeroReference);
/**
* Crée une nouvelle adhésion
*/
@POST
AdhesionDTO creer(AdhesionDTO adhesion);
/**
* Met à jour une adhésion existante
*/
@PUT
@Path("/{id}")
AdhesionDTO modifier(@PathParam("id") UUID id, AdhesionDTO adhesion);
/**
* Supprime une adhésion
*/
@DELETE
@Path("/{id}")
void supprimer(@PathParam("id") UUID id);
/**
* Approuve une adhésion
*/
@POST
@Path("/{id}/approuver")
AdhesionDTO approuver(
@PathParam("id") UUID id,
@QueryParam("approuvePar") String approuvePar
);
/**
* Rejette une adhésion
*/
@POST
@Path("/{id}/rejeter")
AdhesionDTO rejeter(
@PathParam("id") UUID id,
@QueryParam("motifRejet") String motifRejet
);
/**
* Enregistre un paiement pour une adhésion
*/
@POST
@Path("/{id}/paiement")
AdhesionDTO enregistrerPaiement(
@PathParam("id") UUID id,
@QueryParam("montantPaye") BigDecimal montantPaye,
@QueryParam("methodePaiement") String methodePaiement,
@QueryParam("referencePaiement") String referencePaiement
);
/**
* Récupère les adhésions d'un membre
*/
@GET
@Path("/membre/{membreId}")
List<AdhesionDTO> obtenirParMembre(
@PathParam("membreId") UUID membreId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Récupère les adhésions d'une organisation
*/
@GET
@Path("/organisation/{organisationId}")
List<AdhesionDTO> obtenirParOrganisation(
@PathParam("organisationId") UUID organisationId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Récupère les adhésions par statut
*/
@GET
@Path("/statut/{statut}")
List<AdhesionDTO> obtenirParStatut(
@PathParam("statut") String statut,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Récupère les adhésions en attente
*/
@GET
@Path("/en-attente")
List<AdhesionDTO> obtenirEnAttente(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Récupère les statistiques des adhésions
*/
@GET
@Path("/stats")
Map<String, Object> obtenirStatistiques();
}

View File

@@ -1,8 +1,10 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.client.dto.AnalyticsDataDTO;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
@RegisterRestClient(configKey = "unionflow-api")
@@ -12,39 +14,47 @@ import java.util.Map;
public interface AnalyticsService {
@GET
@Path("/dashboard/widgets")
Map<String, Object> getDashboardData(
@QueryParam("organisationId") String organisationId,
@QueryParam("utilisateurId") String utilisateurId
@Path("/metriques/{typeMetrique}")
AnalyticsDataDTO calculerMetrique(
@PathParam("typeMetrique") String typeMetrique,
@QueryParam("periode") String periode,
@QueryParam("organisationId") String organisationId
);
@GET
@Path("/tendances/{typeMetrique}")
Map<String, Object> getEvolutionMensuelle(
Map<String, Object> calculerTendanceKPI(
@PathParam("typeMetrique") String typeMetrique,
@QueryParam("organisationId") String organisationId,
@QueryParam("periode") String periode
@QueryParam("periode") String periode,
@QueryParam("organisationId") String organisationId
);
@GET
@Path("/kpis")
Map<String, Object> getKPIs(
@QueryParam("organisationId") String organisationId,
@QueryParam("periode") String periode
Map<String, Object> obtenirTousLesKPI(
@QueryParam("periode") String periode,
@QueryParam("organisationId") String organisationId
);
@GET
@Path("/evolutions")
Map<String, Object> getEvolutions(
@QueryParam("organisationId") String organisationId,
@QueryParam("periode") String periode
Map<String, Object> obtenirEvolutionsKPI(
@QueryParam("periode") String periode,
@QueryParam("organisationId") String organisationId
);
@GET
@Path("/performance-globale")
Map<String, Object> getPerformanceGlobale(
Map<String, Object> calculerPerformanceGlobale(
@QueryParam("periode") String periode,
@QueryParam("organisationId") String organisationId
);
@GET
@Path("/dashboard/widgets")
List<Map<String, Object>> obtenirWidgetsTableauBord(
@QueryParam("organisationId") String organisationId,
@QueryParam("periode") String periode
@QueryParam("utilisateurId") String utilisateurId
);
}

View File

@@ -8,20 +8,23 @@ import java.util.List;
import java.util.UUID;
@RegisterRestClient(configKey = "unionflow-api")
@Path("/api/associations")
@Path("/api/organisations")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface AssociationService {
@GET
List<AssociationDTO> listerToutes();
List<AssociationDTO> listerToutes(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("1000") int size
);
@GET
@Path("/{id}")
AssociationDTO obtenirParId(@PathParam("id") UUID id);
@GET
@Path("/search")
@Path("/recherche")
List<AssociationDTO> rechercher(
@QueryParam("nom") String nom,
@QueryParam("type") String type,
@@ -32,10 +35,6 @@ public interface AssociationService {
@QueryParam("size") @DefaultValue("20") int size
);
@GET
@Path("/actives")
List<AssociationDTO> listerActives();
@GET
@Path("/type/{type}")
List<AssociationDTO> listerParType(@PathParam("type") String type);

View File

@@ -0,0 +1,53 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.client.dto.AuditLogDTO;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.Map;
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
/**
* Service REST client pour la gestion des logs d'audit
*
* @author UnionFlow Team
* @version 1.0
*/
@RegisterRestClient(baseUri = "http://localhost:8085")
@RegisterClientHeaders
@Path("/api/audit")
public interface AuditService {
@GET
@Produces(MediaType.APPLICATION_JSON)
Map<String, Object> listerTous(
@QueryParam("page") int page,
@QueryParam("size") int size,
@QueryParam("sortBy") String sortBy,
@QueryParam("sortOrder") String sortOrder);
@POST
@Path("/rechercher")
@Produces(MediaType.APPLICATION_JSON)
Map<String, Object> rechercher(
@QueryParam("dateDebut") String dateDebut,
@QueryParam("dateFin") String dateFin,
@QueryParam("typeAction") String typeAction,
@QueryParam("severite") String severite,
@QueryParam("utilisateur") String utilisateur,
@QueryParam("module") String module,
@QueryParam("ipAddress") String ipAddress,
@QueryParam("page") int page,
@QueryParam("size") int size);
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
AuditLogDTO enregistrerLog(AuditLogDTO dto);
@GET
@Path("/statistiques")
@Produces(MediaType.APPLICATION_JSON)
Map<String, Object> getStatistiques();
}

View File

@@ -5,40 +5,115 @@ import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* Service REST client pour la gestion des cotisations
* Interface correspondant exactement au backend CotisationResource
*
* @author UnionFlow Team
* @version 1.0
*/
@RegisterRestClient(configKey = "unionflow-api")
@Path("/api/cotisations")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface CotisationService {
/**
* Récupère toutes les cotisations avec pagination
*/
@GET
List<CotisationDTO> listerToutes(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Récupère une cotisation par son ID
*/
@GET
@Path("/{id}")
CotisationDTO obtenirParId(@PathParam("id") UUID id);
/**
* Récupère une cotisation par son numéro de référence
*/
@GET
@Path("/search")
List<CotisationDTO> rechercher(
@QueryParam("membreId") UUID membreId,
@QueryParam("statut") String statut,
@Path("/reference/{numeroReference}")
CotisationDTO obtenirParReference(@PathParam("numeroReference") String numeroReference);
/**
* Récupère les cotisations d'un membre
*/
@GET
@Path("/membre/{membreId}")
List<CotisationDTO> obtenirParMembre(
@PathParam("membreId") UUID membreId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Récupère les cotisations par statut
*/
@GET
@Path("/statut/{statut}")
List<CotisationDTO> obtenirParStatut(
@PathParam("statut") String statut,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Récupère les cotisations en retard
*/
@GET
@Path("/en-retard")
List<CotisationDTO> obtenirEnRetard(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Recherche avancée de cotisations
*/
@GET
@Path("/recherche")
List<CotisationDTO> rechercher(
@QueryParam("membreId") UUID membreId,
@QueryParam("statut") String statut,
@QueryParam("typeCotisation") String typeCotisation,
@QueryParam("annee") Integer annee,
@QueryParam("mois") Integer mois,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Récupère les statistiques des cotisations
*/
@GET
@Path("/stats")
Map<String, Object> obtenirStatistiques();
/**
* Crée une nouvelle cotisation
*/
@POST
CotisationDTO creer(CotisationDTO cotisation);
/**
* Met à jour une cotisation existante
*/
@PUT
@Path("/{id}")
CotisationDTO modifier(@PathParam("id") UUID id, CotisationDTO cotisation);
/**
* Supprime une cotisation
*/
@DELETE
@Path("/{id}")
void supprimer(@PathParam("id") UUID id);

View File

@@ -5,50 +5,132 @@ import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
* Service REST client pour la gestion des événements
* Correspond exactement aux endpoints du backend EvenementResource
*
* @author UnionFlow Team
* @version 2.0
*/
@RegisterRestClient(configKey = "unionflow-api")
@Path("/api/evenements")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface EvenementService {
/**
* Liste tous les événements actifs avec pagination
*/
@GET
List<EvenementDTO> listerTous(
Map<String, Object> listerTous(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
@QueryParam("size") @DefaultValue("20") int size,
@QueryParam("sort") @DefaultValue("dateDebut") String sortField,
@QueryParam("direction") @DefaultValue("asc") String sortDirection
);
/**
* Récupère un événement par son ID
*/
@GET
@Path("/{id}")
EvenementDTO obtenirParId(@PathParam("id") UUID id);
@GET
@Path("/search")
List<EvenementDTO> rechercher(
@QueryParam("titre") String titre,
@QueryParam("type") String type,
@QueryParam("statut") String statut,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
@GET
@Path("/a-venir")
List<EvenementDTO> listerAVenir(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Crée un nouvel événement
*/
@POST
EvenementDTO creer(EvenementDTO evenement);
/**
* Met à jour un événement existant
*/
@PUT
@Path("/{id}")
EvenementDTO modifier(@PathParam("id") UUID id, EvenementDTO evenement);
/**
* Supprime un événement
*/
@DELETE
@Path("/{id}")
void supprimer(@PathParam("id") UUID id);
/**
* Liste les événements à venir
*/
@GET
@Path("/a-venir")
Map<String, Object> listerAVenir(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("10") int size
);
/**
* Recherche d'événements avec filtres
*/
@GET
@Path("/search")
Map<String, Object> rechercher(
@QueryParam("titre") String titre,
@QueryParam("type") String type,
@QueryParam("statut") String statut,
@QueryParam("dateDebut") String dateDebut,
@QueryParam("dateFin") String dateFin,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Liste les événements par statut
*/
@GET
@Path("/statut/{statut}")
Map<String, Object> listerParStatut(
@PathParam("statut") String statut,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Liste les événements par association
*/
@GET
@Path("/association/{associationId}")
Map<String, Object> listerParAssociation(
@PathParam("associationId") UUID associationId,
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("20") int size
);
/**
* Compte le nombre d'événements
*/
@GET
@Path("/count")
Map<String, Object> compter();
/**
* Inscrit un participant à un événement
*/
@POST
@Path("/{evenementId}/participants/{membreId}")
void inscrireParticipant(@PathParam("evenementId") UUID evenementId, @PathParam("membreId") UUID membreId);
/**
* Désinscrit un participant d'un événement
*/
@DELETE
@Path("/{evenementId}/participants/{membreId}")
void desinscrireParticipant(@PathParam("evenementId") UUID evenementId, @PathParam("membreId") UUID membreId);
/**
* Liste les participants d'un événement
*/
@GET
@Path("/{evenementId}/participants")
List<Map<String, Object>> listerParticipants(@PathParam("evenementId") UUID evenementId);
}

View File

@@ -0,0 +1,50 @@
package dev.lions.unionflow.client.service;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.UUID;
/**
* Service REST client pour l'export des données
*/
@RegisterRestClient(configKey = "unionflow-api")
@Path("/api/export")
@Consumes(MediaType.APPLICATION_JSON)
public interface ExportClientService {
@GET
@Path("/cotisations/csv")
@Produces("text/csv")
byte[] exporterCotisationsCSV(
@QueryParam("statut") String statut,
@QueryParam("type") String type,
@QueryParam("associationId") UUID associationId
);
@POST
@Path("/cotisations/csv")
@Produces("text/csv")
byte[] exporterCotisationsSelectionneesCSV(List<UUID> cotisationIds);
@GET
@Path("/cotisations/{cotisationId}/recu")
@Produces("text/plain")
byte[] genererRecu(@PathParam("cotisationId") UUID cotisationId);
@POST
@Path("/cotisations/recus")
@Produces("text/plain")
byte[] genererRecusGroupes(List<UUID> cotisationIds);
@GET
@Path("/rapport/mensuel")
@Produces("text/plain")
byte[] genererRapportMensuel(
@QueryParam("annee") int annee,
@QueryParam("mois") int mois,
@QueryParam("associationId") UUID associationId
);
}

View File

@@ -0,0 +1,53 @@
package dev.lions.unionflow.client.service;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.Map;
/**
* Service REST client pour les notifications
*/
@RegisterRestClient(configKey = "unionflow-api")
@Path("/api/notifications")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface NotificationClientService {
@POST
@Path("/groupe")
List<Map<String, Object>> envoyerNotificationGroupe(
@QueryParam("type") String type,
@QueryParam("titre") String titre,
@QueryParam("message") String message,
List<String> destinatairesIds
);
@GET
@Path("/utilisateur/{utilisateurId}")
List<Map<String, Object>> obtenirNotifications(
@PathParam("utilisateurId") String utilisateurId,
@QueryParam("includeArchivees") @DefaultValue("false") boolean includeArchivees,
@QueryParam("limite") @DefaultValue("50") int limite
);
@PUT
@Path("/{notificationId}/lue")
Map<String, Object> marquerCommeLue(
@PathParam("notificationId") String notificationId,
@QueryParam("utilisateurId") String utilisateurId
);
@GET
@Path("/stats")
Map<String, Long> obtenirStatistiques();
@POST
@Path("/test/{utilisateurId}")
Map<String, Object> envoyerNotificationTest(
@PathParam("utilisateurId") String utilisateurId,
@QueryParam("type") @DefaultValue("SYSTEME") String type
);
}

View File

@@ -0,0 +1,34 @@
package dev.lions.unionflow.client.service;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.Map;
import java.util.UUID;
@RegisterRestClient(configKey = "unionflow-api")
@Path("/api/preferences")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface PreferencesService {
@GET
@Path("/{utilisateurId}")
Map<String, Boolean> obtenirPreferences(@PathParam("utilisateurId") UUID utilisateurId);
@PUT
@Path("/{utilisateurId}")
void mettreAJourPreferences(
@PathParam("utilisateurId") UUID utilisateurId,
Map<String, Boolean> preferences
);
@POST
@Path("/{utilisateurId}/reinitialiser")
void reinitialiserPreferences(@PathParam("utilisateurId") UUID utilisateurId);
@GET
@Path("/{utilisateurId}/export")
Map<String, Object> exporterPreferences(@PathParam("utilisateurId") UUID utilisateurId);
}

View File

@@ -0,0 +1,34 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.client.dto.TypeOrganisationClientDTO;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import java.util.List;
import java.util.UUID;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
/**
* REST client pour le catalogue des types d'organisation.
*/
@RegisterRestClient(configKey = "unionflow-api")
@Path("/api/types-organisations")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public interface TypeOrganisationClientService {
@GET
List<TypeOrganisationClientDTO> list(@QueryParam("onlyActifs") @DefaultValue("true") boolean onlyActifs);
@POST
TypeOrganisationClientDTO create(TypeOrganisationClientDTO dto);
@PUT
@Path("/{id}")
TypeOrganisationClientDTO update(@PathParam("id") UUID id, TypeOrganisationClientDTO dto);
@DELETE
@Path("/{id}")
void disable(@PathParam("id") UUID id);
}

View File

@@ -0,0 +1,55 @@
package dev.lions.unionflow.client.service;
import dev.lions.unionflow.client.dto.WaveCheckoutSessionDTO;
import dev.lions.unionflow.client.dto.WaveBalanceDTO;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import java.math.BigDecimal;
import java.util.Map;
import java.util.UUID;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
/**
* Service REST client pour l'intégration Wave Money
*
* @author UnionFlow Team
* @version 1.0
* @since 2025-01-17
*/
@RegisterRestClient(baseUri = "http://localhost:8085")
@Path("/api/wave")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public interface WaveService {
@POST
@Path("/checkout/sessions")
WaveCheckoutSessionDTO creerSessionPaiement(
@QueryParam("montant") BigDecimal montant,
@QueryParam("devise") String devise,
@QueryParam("successUrl") String successUrl,
@QueryParam("errorUrl") String errorUrl,
@QueryParam("reference") String referenceUnionFlow,
@QueryParam("description") String description,
@QueryParam("organisationId") UUID organisationId,
@QueryParam("membreId") UUID membreId);
@GET
@Path("/checkout/sessions/{sessionId}")
WaveCheckoutSessionDTO verifierStatutSession(@PathParam("sessionId") String sessionId);
@GET
@Path("/balance")
WaveBalanceDTO consulterSolde();
@GET
@Path("/test")
Map<String, Object> testerConnexion();
}

View File

@@ -0,0 +1,596 @@
package dev.lions.unionflow.client.view;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import dev.lions.unionflow.client.dto.AdhesionDTO;
import dev.lions.unionflow.client.dto.AssociationDTO;
import dev.lions.unionflow.client.dto.MembreDTO;
import dev.lions.unionflow.client.service.AdhesionService;
import dev.lions.unionflow.client.service.AssociationService;
import dev.lions.unionflow.client.service.MembreService;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.SessionScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.model.SelectItem;
import jakarta.inject.Inject;
import jakarta.inject.Named;
/**
* Bean JSF pour la gestion des adhésions
* Utilise directement AdhesionDTO et se connecte au backend
*
* @author UnionFlow Team
* @version 1.0
*/
@Named("adhesionsBean")
@SessionScoped
public class AdhesionsBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(AdhesionsBean.class.getName());
@Inject
@RestClient
private AdhesionService adhesionService;
@Inject
@RestClient
private MembreService membreService;
@Inject
@RestClient
private AssociationService associationService;
// Listes de référence pour les select
private List<MembreDTO> listeMembres;
private List<AssociationDTO> listeAssociations;
// Données principales
private List<AdhesionDTO> toutesLesAdhesions;
private List<AdhesionDTO> adhesionsFiltrees;
private List<AdhesionDTO> adhesionsSelectionnees;
private AdhesionDTO adhesionSelectionnee;
// Formulaire nouvelle adhésion
private NouvelleAdhesion nouvelleAdhesion;
// Filtres
private FiltresAdhesion filtres;
// Statistiques
private StatistiquesAdhesion statistiques;
@PostConstruct
public void init() {
initializeFiltres();
chargerMembresEtAssociations();
chargerAdhesions();
chargerStatistiques();
initializeNouvelleAdhesion();
appliquerFiltres();
}
/**
* Charge les listes de membres et d'associations depuis le backend
*/
private void chargerMembresEtAssociations() {
listeMembres = new ArrayList<>();
listeAssociations = new ArrayList<>();
try {
listeMembres = membreService.listerActifs();
LOGGER.info("Chargement de " + listeMembres.size() + " membres actifs");
} catch (Exception e) {
LOGGER.warning("Impossible de charger les membres: " + e.getMessage());
}
try {
listeAssociations = associationService.listerToutes(0, 1000);
LOGGER.info("Chargement de " + listeAssociations.size() + " associations actives");
} catch (Exception e) {
LOGGER.warning("Impossible de charger les associations: " + e.getMessage());
}
}
/**
* Retourne la liste des membres pour les SelectItem
*/
public List<SelectItem> getMembresSelectItems() {
List<SelectItem> items = new ArrayList<>();
items.add(new SelectItem(null, "Sélectionner un membre"));
if (listeMembres != null) {
for (MembreDTO membre : listeMembres) {
String label = membre.getPrenom() + " " + membre.getNom();
if (membre.getNumeroMembre() != null) {
label += " (" + membre.getNumeroMembre() + ")";
}
items.add(new SelectItem(membre.getId(), label));
}
}
return items;
}
/**
* Retourne la liste des associations pour les SelectItem
*/
public List<SelectItem> getAssociationsSelectItems() {
List<SelectItem> items = new ArrayList<>();
items.add(new SelectItem(null, "Sélectionner une organisation"));
if (listeAssociations != null) {
for (AssociationDTO assoc : listeAssociations) {
String label = assoc.getNom();
if (assoc.getTypeAssociation() != null) {
label += " (" + assoc.getTypeAssociation() + ")";
}
items.add(new SelectItem(assoc.getId(), label));
}
}
return items;
}
private void initializeFiltres() {
filtres = new FiltresAdhesion();
adhesionsSelectionnees = new ArrayList<>();
}
/**
* Charge les adhésions depuis le backend
*/
private void chargerAdhesions() {
toutesLesAdhesions = new ArrayList<>();
try {
toutesLesAdhesions = adhesionService.listerToutes(0, 1000);
LOGGER.info("Chargement de " + toutesLesAdhesions.size() + " adhésions");
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des adhésions: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de charger les adhésions: " + e.getMessage()));
}
}
/**
* Charge les statistiques depuis le backend
*/
private void chargerStatistiques() {
statistiques = new StatistiquesAdhesion();
try {
Map<String, Object> statsBackend = adhesionService.obtenirStatistiques();
// Extraction des statistiques du backend
Long totalAdhesions = ((Number) statsBackend.getOrDefault("totalAdhesions", 0L)).longValue();
Long adhesionsApprouvees = ((Number) statsBackend.getOrDefault("adhesionsApprouvees", 0L)).longValue();
Long adhesionsEnAttente = ((Number) statsBackend.getOrDefault("adhesionsEnAttente", 0L)).longValue();
Long adhesionsPayees = ((Number) statsBackend.getOrDefault("adhesionsPayees", 0L)).longValue();
Double tauxApprobation = ((Number) statsBackend.getOrDefault("tauxApprobation", 0.0)).doubleValue();
Double tauxPaiement = ((Number) statsBackend.getOrDefault("tauxPaiement", 0.0)).doubleValue();
// Calcul des montants depuis les adhésions réelles
BigDecimal totalCollecte = toutesLesAdhesions.stream()
.filter(a -> "PAYEE".equals(a.getStatut()) || "EN_PAIEMENT".equals(a.getStatut()))
.map(a -> a.getMontantPaye() != null ? a.getMontantPaye() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal totalFrais = toutesLesAdhesions.stream()
.map(a -> a.getFraisAdhesion() != null ? a.getFraisAdhesion() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add);
statistiques.setTotalAdhesions(totalAdhesions.intValue());
statistiques.setAdhesionsApprouvees(adhesionsApprouvees.intValue());
statistiques.setAdhesionsEnAttente(adhesionsEnAttente.intValue());
statistiques.setAdhesionsPayees(adhesionsPayees.intValue());
statistiques.setTauxApprobation(tauxApprobation);
statistiques.setTauxPaiement(tauxPaiement);
statistiques.setTotalCollecte(totalCollecte);
statistiques.setTotalFrais(totalFrais);
LOGGER.info("Statistiques chargées: Total=" + totalAdhesions + ", Approuvées=" + adhesionsApprouvees);
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des statistiques: " + e.getMessage());
initialiserStatistiquesParDefaut();
}
}
private void initialiserStatistiquesParDefaut() {
statistiques.setTotalAdhesions(0);
statistiques.setAdhesionsApprouvees(0);
statistiques.setAdhesionsEnAttente(0);
statistiques.setAdhesionsPayees(0);
statistiques.setTauxApprobation(0.0);
statistiques.setTauxPaiement(0.0);
statistiques.setTotalCollecte(BigDecimal.ZERO);
statistiques.setTotalFrais(BigDecimal.ZERO);
}
/**
* Applique les filtres en utilisant la recherche backend
*/
private void appliquerFiltres() {
try {
// Utiliser la recherche backend
if (filtres.getStatut() != null && !filtres.getStatut().isEmpty()) {
adhesionsFiltrees = adhesionService.obtenirParStatut(filtres.getStatut(), 0, 1000);
} else {
adhesionsFiltrees = new ArrayList<>(toutesLesAdhesions);
}
// Appliquer les filtres supplémentaires côté client si nécessaire
if (filtres.getNomMembre() != null && !filtres.getNomMembre().trim().isEmpty()) {
adhesionsFiltrees = adhesionsFiltrees.stream()
.filter(a -> a.getNomMembre() != null
&& a.getNomMembre().toLowerCase().contains(filtres.getNomMembre().toLowerCase()))
.collect(Collectors.toList());
}
if (filtres.getDateDebut() != null) {
adhesionsFiltrees = adhesionsFiltrees.stream()
.filter(a -> a.getDateDemande() != null
&& !a.getDateDemande().isBefore(filtres.getDateDebut()))
.collect(Collectors.toList());
}
if (filtres.getDateFin() != null) {
adhesionsFiltrees = adhesionsFiltrees.stream()
.filter(a -> a.getDateDemande() != null
&& !a.getDateDemande().isAfter(filtres.getDateFin()))
.collect(Collectors.toList());
}
} catch (Exception e) {
LOGGER.severe("Erreur lors de l'application des filtres: " + e.getMessage());
adhesionsFiltrees = new ArrayList<>();
}
}
// Actions
/**
* Recherche avec filtres
*/
public void rechercher() {
appliquerFiltres();
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "Recherche",
adhesionsFiltrees.size() + " adhésion(s) trouvée(s)"));
}
/**
* Réinitialise les filtres
*/
public void reinitialiserFiltres() {
filtres = new FiltresAdhesion();
chargerAdhesions();
appliquerFiltres();
}
/**
* Enregistre une nouvelle adhésion via le backend
*/
public void enregistrerAdhesion() {
try {
AdhesionDTO nouvelleAdh = new AdhesionDTO();
nouvelleAdh.setMembreId(nouvelleAdhesion.getMembreId());
nouvelleAdh.setOrganisationId(nouvelleAdhesion.getOrganisationId());
nouvelleAdh.setFraisAdhesion(nouvelleAdhesion.getFraisAdhesion());
nouvelleAdh.setDateDemande(LocalDate.now());
nouvelleAdh.setStatut("EN_ATTENTE");
nouvelleAdh.setMontantPaye(BigDecimal.ZERO);
nouvelleAdh.setCodeDevise("XOF");
nouvelleAdh.setObservations(nouvelleAdhesion.getObservations());
AdhesionDTO adhesionCreee = adhesionService.creer(nouvelleAdh);
// Recharger les données
chargerAdhesions();
chargerStatistiques();
appliquerFiltres();
initializeNouvelleAdhesion();
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès",
"Adhésion créée avec succès"));
LOGGER.info("Nouvelle adhésion créée: " + adhesionCreee.getId());
} catch (Exception e) {
LOGGER.severe("Erreur lors de la création de l'adhésion: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de créer l'adhésion: " + e.getMessage()));
}
}
/**
* Approuve une adhésion
*/
public void approuverAdhesion() {
if (adhesionSelectionnee == null) {
return;
}
try {
adhesionService.approuver(adhesionSelectionnee.getId(), "Admin");
// Recharger les données
chargerAdhesions();
chargerStatistiques();
appliquerFiltres();
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès",
"Adhésion approuvée"));
LOGGER.info("Adhésion approuvée: " + adhesionSelectionnee.getId());
} catch (Exception e) {
LOGGER.severe("Erreur lors de l'approbation: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible d'approuver l'adhésion: " + e.getMessage()));
}
}
/**
* Rejette une adhésion
*/
public void rejeterAdhesion(String motifRejet) {
if (adhesionSelectionnee == null) {
return;
}
try {
adhesionService.rejeter(adhesionSelectionnee.getId(), motifRejet);
// Recharger les données
chargerAdhesions();
chargerStatistiques();
appliquerFiltres();
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès",
"Adhésion rejetée"));
LOGGER.info("Adhésion rejetée: " + adhesionSelectionnee.getId());
} catch (Exception e) {
LOGGER.severe("Erreur lors du rejet: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de rejeter l'adhésion: " + e.getMessage()));
}
}
/**
* Enregistre un paiement pour une adhésion
*/
public void enregistrerPaiement(BigDecimal montantPaye, String methodePaiement, String referencePaiement) {
if (adhesionSelectionnee == null) {
return;
}
try {
adhesionService.enregistrerPaiement(
adhesionSelectionnee.getId(),
montantPaye,
methodePaiement,
referencePaiement);
// Recharger les données
chargerAdhesions();
chargerStatistiques();
appliquerFiltres();
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès",
"Paiement enregistré"));
LOGGER.info("Paiement enregistré pour l'adhésion: " + adhesionSelectionnee.getId());
} catch (Exception e) {
LOGGER.severe("Erreur lors de l'enregistrement du paiement: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible d'enregistrer le paiement: " + e.getMessage()));
}
}
/**
* Sélectionne une adhésion pour afficher ses détails
*/
public void selectionnerAdhesion(AdhesionDTO adhesion) {
this.adhesionSelectionnee = adhesion;
}
/**
* Actualise les données depuis le backend
*/
public void actualiser() {
chargerAdhesions();
chargerStatistiques();
appliquerFiltres();
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, "Actualisation",
"Données actualisées"));
}
/**
* Charge les adhésions en attente depuis le backend
*/
public void chargerAdhesionsEnAttente() {
try {
toutesLesAdhesions = adhesionService.obtenirEnAttente(0, 1000);
appliquerFiltres();
LOGGER.info("Chargement de " + toutesLesAdhesions.size() + " adhésions en attente");
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des adhésions en attente: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de charger les adhésions en attente: " + e.getMessage()));
}
}
private void initializeNouvelleAdhesion() {
nouvelleAdhesion = new NouvelleAdhesion();
}
// Getters et Setters
public List<AdhesionDTO> getToutesLesAdhesions() {
return toutesLesAdhesions;
}
public void setToutesLesAdhesions(List<AdhesionDTO> toutesLesAdhesions) {
this.toutesLesAdhesions = toutesLesAdhesions;
}
public List<AdhesionDTO> getAdhesionsFiltrees() {
return adhesionsFiltrees;
}
public void setAdhesionsFiltrees(List<AdhesionDTO> adhesionsFiltrees) {
this.adhesionsFiltrees = adhesionsFiltrees;
}
public List<AdhesionDTO> getAdhesionsSelectionnees() {
return adhesionsSelectionnees;
}
public void setAdhesionsSelectionnees(List<AdhesionDTO> adhesionsSelectionnees) {
this.adhesionsSelectionnees = adhesionsSelectionnees;
}
public AdhesionDTO getAdhesionSelectionnee() {
return adhesionSelectionnee;
}
public void setAdhesionSelectionnee(AdhesionDTO adhesionSelectionnee) {
this.adhesionSelectionnee = adhesionSelectionnee;
}
public NouvelleAdhesion getNouvelleAdhesion() {
return nouvelleAdhesion;
}
public void setNouvelleAdhesion(NouvelleAdhesion nouvelleAdhesion) {
this.nouvelleAdhesion = nouvelleAdhesion;
}
public FiltresAdhesion getFiltres() {
return filtres;
}
public void setFiltres(FiltresAdhesion filtres) {
this.filtres = filtres;
}
public StatistiquesAdhesion getStatistiques() {
return statistiques;
}
public void setStatistiques(StatistiquesAdhesion statistiques) {
this.statistiques = statistiques;
}
// Classes internes pour les formulaires et filtres
public static class NouvelleAdhesion implements Serializable {
private static final long serialVersionUID = 1L;
private UUID membreId;
private UUID organisationId;
private BigDecimal fraisAdhesion;
private String observations;
// Getters et Setters
public UUID getMembreId() { return membreId; }
public void setMembreId(UUID membreId) { this.membreId = membreId; }
public UUID getOrganisationId() { return organisationId; }
public void setOrganisationId(UUID organisationId) { this.organisationId = organisationId; }
public BigDecimal getFraisAdhesion() { return fraisAdhesion; }
public void setFraisAdhesion(BigDecimal fraisAdhesion) { this.fraisAdhesion = fraisAdhesion; }
public String getObservations() { return observations; }
public void setObservations(String observations) { this.observations = observations; }
}
public static class FiltresAdhesion implements Serializable {
private static final long serialVersionUID = 1L;
private String statut;
private String nomMembre;
private LocalDate dateDebut;
private LocalDate dateFin;
// Getters et Setters
public String getStatut() { return statut; }
public void setStatut(String statut) { this.statut = statut; }
public String getNomMembre() { return nomMembre; }
public void setNomMembre(String nomMembre) { this.nomMembre = nomMembre; }
public LocalDate getDateDebut() { return dateDebut; }
public void setDateDebut(LocalDate dateDebut) { this.dateDebut = dateDebut; }
public LocalDate getDateFin() { return dateFin; }
public void setDateFin(LocalDate dateFin) { this.dateFin = dateFin; }
}
public static class StatistiquesAdhesion implements Serializable {
private static final long serialVersionUID = 1L;
private int totalAdhesions;
private int adhesionsApprouvees;
private int adhesionsEnAttente;
private int adhesionsPayees;
private double tauxApprobation;
private double tauxPaiement;
private BigDecimal totalCollecte;
private BigDecimal totalFrais;
// Getters et Setters
public int getTotalAdhesions() { return totalAdhesions; }
public void setTotalAdhesions(int totalAdhesions) { this.totalAdhesions = totalAdhesions; }
public int getAdhesionsApprouvees() { return adhesionsApprouvees; }
public void setAdhesionsApprouvees(int adhesionsApprouvees) { this.adhesionsApprouvees = adhesionsApprouvees; }
public int getAdhesionsEnAttente() { return adhesionsEnAttente; }
public void setAdhesionsEnAttente(int adhesionsEnAttente) { this.adhesionsEnAttente = adhesionsEnAttente; }
public int getAdhesionsPayees() { return adhesionsPayees; }
public void setAdhesionsPayees(int adhesionsPayees) { this.adhesionsPayees = adhesionsPayees; }
public double getTauxApprobation() { return tauxApprobation; }
public void setTauxApprobation(double tauxApprobation) { this.tauxApprobation = tauxApprobation; }
public double getTauxPaiement() { return tauxPaiement; }
public void setTauxPaiement(double tauxPaiement) { this.tauxPaiement = tauxPaiement; }
public BigDecimal getTotalCollecte() { return totalCollecte; }
public void setTotalCollecte(BigDecimal totalCollecte) { this.totalCollecte = totalCollecte; }
public BigDecimal getTotalFrais() { return totalFrais; }
public void setTotalFrais(BigDecimal totalFrais) { this.totalFrais = totalFrais; }
// Méthodes utilitaires pour l'affichage
public String getTotalCollecteFormatte() {
if (totalCollecte == null) return "0 FCFA";
return String.format("%,.0f FCFA", totalCollecte.doubleValue());
}
public String getTotalFraisFormatte() {
if (totalFrais == null) return "0 FCFA";
return String.format("%,.0f FCFA", totalFrais.doubleValue());
}
public int getTauxApprobationInt() {
return (int) Math.round(tauxApprobation);
}
public int getTauxPaiementInt() {
return (int) Math.round(tauxPaiement);
}
}
}

View File

@@ -1,18 +1,52 @@
package dev.lions.unionflow.client.view;
import dev.lions.unionflow.client.dto.AuditLogDTO;
import dev.lions.unionflow.client.service.AuditService;
import dev.lions.unionflow.client.service.NotificationClientService;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.SessionScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.ExternalContext;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.logging.Logger;
import java.util.stream.Collectors;
/**
* Bean JSF pour la gestion des logs d'audit
* Refactorisé pour utiliser directement AuditLogDTO et se connecter au backend
*
* @author UnionFlow Team
* @version 2.0
*/
@Named("auditBean")
@SessionScoped
public class AuditBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(AuditBean.class.getName());
@Inject
@RestClient
private AuditService auditService;
@Inject
@RestClient
private NotificationClientService notificationService;
@Inject
private UserSession userSession;
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss");
// Filtres
private Date dateDebut;
@@ -23,186 +57,247 @@ public class AuditBean implements Serializable {
private String module = "";
private String ipAddress = "";
// Données
private List<EvenementAudit> evenements;
private EvenementAudit evenementSelectionne;
// Données - Utilisation directe de AuditLogDTO
private List<AuditLogDTO> tousLesLogs;
private List<AuditLogDTO> logsFiltres;
private AuditLogDTO logSelectionne;
// Statistiques
private Map<String, Object> statistiques;
// Export
private String formatExport = "EXCEL";
private boolean inclureFiltresExport = true;
public AuditBean() {
initialiserEvenements();
@PostConstruct
public void init() {
LOGGER.info("Initialisation de AuditBean");
// Initialiser les dates à aujourd'hui - 7 jours
Calendar cal = Calendar.getInstance();
dateFin = cal.getTime();
cal.add(Calendar.DAY_OF_MONTH, -7);
dateDebut = cal.getTime();
chargerLogs();
chargerStatistiques();
}
private void initialiserEvenements() {
evenements = new ArrayList<>();
LocalDateTime now = LocalDateTime.now();
/**
* Charge les logs depuis le backend
*/
public void chargerLogs() {
try {
LOGGER.info("Chargement des logs d'audit depuis le backend");
Map<String, Object> response = auditService.listerTous(0, 1000, "dateHeure", "desc");
tousLesLogs = new ArrayList<>();
if (response.containsKey("data")) {
@SuppressWarnings("unchecked")
List<Object> data = (List<Object>) response.get("data");
if (data != null) {
for (Object item : data) {
if (item instanceof AuditLogDTO) {
tousLesLogs.add((AuditLogDTO) item);
} else if (item instanceof Map) {
@SuppressWarnings("unchecked")
AuditLogDTO dto = convertMapToDTO((Map<String, Object>) item);
tousLesLogs.add(dto);
}
}
}
}
appliquerFiltres();
LOGGER.info("Logs chargés: " + tousLesLogs.size());
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des logs: " + e.getMessage());
e.printStackTrace();
tousLesLogs = new ArrayList<>();
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Erreur lors du chargement des logs: " + e.getMessage());
}
}
/**
* Charge les statistiques depuis le backend
*/
public void chargerStatistiques() {
try {
LOGGER.info("Chargement des statistiques d'audit");
statistiques = auditService.getStatistiques();
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des statistiques: " + e.getMessage());
statistiques = new HashMap<>();
statistiques.put("total", 0L);
statistiques.put("success", 0L);
statistiques.put("errors", 0L);
statistiques.put("warnings", 0L);
}
}
/**
* Convertit une Map en AuditLogDTO
*/
private AuditLogDTO convertMapToDTO(Map<String, Object> map) {
AuditLogDTO dto = new AuditLogDTO();
// Événements de connexion
evenements.add(new EvenementAudit(
now.minusMinutes(15), "CONNEXION", "SUCCESS", "Marie Dupont", "ADMIN_ORG", "AUTH",
"Connexion réussie", "Connexion via interface web", "192.168.1.105",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "SESSION_123456"));
try {
if (map.get("id") != null) {
if (map.get("id") instanceof UUID) {
dto.setId((UUID) map.get("id"));
} else {
dto.setId(UUID.fromString(map.get("id").toString()));
}
}
evenements.add(new EvenementAudit(
now.minusMinutes(32), "CONNEXION", "ERROR", "Jean Martin", "MEMBRE", "AUTH",
"Tentative de connexion échouée", "Mot de passe incorrect (3e tentative)", "192.168.1.87",
"Mozilla/5.0 (Macintosh; Intel Mac OS X)", "SESSION_789012"));
if (map.get("typeAction") != null) dto.setTypeAction(map.get("typeAction").toString());
if (map.get("severite") != null) dto.setSeverite(map.get("severite").toString());
if (map.get("utilisateur") != null) dto.setUtilisateur(map.get("utilisateur").toString());
if (map.get("role") != null) dto.setRole(map.get("role").toString());
if (map.get("module") != null) dto.setModule(map.get("module").toString());
if (map.get("description") != null) dto.setDescription(map.get("description").toString());
if (map.get("details") != null) dto.setDetails(map.get("details").toString());
if (map.get("ipAddress") != null) dto.setIpAddress(map.get("ipAddress").toString());
if (map.get("userAgent") != null) dto.setUserAgent(map.get("userAgent").toString());
if (map.get("sessionId") != null) dto.setSessionId(map.get("sessionId").toString());
if (map.get("donneesAvant") != null) dto.setDonneesAvant(map.get("donneesAvant").toString());
if (map.get("donneesApres") != null) dto.setDonneesApres(map.get("donneesApres").toString());
if (map.get("entiteId") != null) dto.setEntiteId(map.get("entiteId").toString());
if (map.get("entiteType") != null) dto.setEntiteType(map.get("entiteType").toString());
// Événements de gestion des membres
evenements.add(new EvenementAudit(
now.minusHours(1), "CREATION", "SUCCESS", "Marie Dupont", "ADMIN_ORG", "MEMBRES",
"Création d'un nouveau membre", "Membre: Paul Durand (ID: MBR_2024_001)", "192.168.1.105",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "SESSION_123456"));
// Conversion des dates
if (map.get("dateHeure") != null) {
Object date = map.get("dateHeure");
if (date instanceof LocalDateTime) {
dto.setDateHeure((LocalDateTime) date);
} else if (date instanceof String) {
dto.setDateHeure(LocalDateTime.parse(date.toString()));
}
}
evenements.add(new EvenementAudit(
now.minusHours(2), "MODIFICATION", "SUCCESS", "Sophie Bernard", "SECRETAIRE", "MEMBRES",
"Modification profil membre", "Mise à jour adresse email: paul.durand@email.com", "192.168.1.92",
"Mozilla/5.0 (iPhone; CPU iPhone OS)", "SESSION_345678"));
// Événements de cotisations
evenements.add(new EvenementAudit(
now.minusHours(3), "CREATION", "SUCCESS", "Pierre Legrand", "COMPTABLE", "COTISATIONS",
"Enregistrement paiement cotisation", "Cotisation 2024 - Membre: Marie Petit - 50€", "192.168.1.78",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "SESSION_901234"));
// Événements d'export
evenements.add(new EvenementAudit(
now.minusHours(4), "EXPORT", "SUCCESS", "Marie Dupont", "ADMIN_ORG", "RAPPORTS",
"Export liste des membres", "Format Excel - 156 membres exportés", "192.168.1.105",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "SESSION_123456"));
// Événements de configuration
evenements.add(new EvenementAudit(
now.minusHours(6), "CONFIGURATION", "WARNING", "Admin Système", "SUPER_ADMIN", "CONFIG",
"Modification paramètres sécurité", "Durée de session modifiée: 30min → 60min", "192.168.1.1",
"Mozilla/5.0 (Linux; Ubuntu)", "SESSION_ADMIN001"));
// Événements suspects
evenements.add(new EvenementAudit(
now.minusHours(8), "CONNEXION", "CRITICAL", "Utilisateur Inconnu", "N/A", "AUTH",
"Tentative de connexion suspecte", "Multiples tentatives depuis IP externe", "203.45.67.89",
"Bot/1.0", "SESSION_UNKNOWN"));
evenements.add(new EvenementAudit(
now.minusHours(12), "CONSULTATION", "ERROR", "Test User", "MEMBRE", "DOCUMENTS",
"Accès non autorisé", "Tentative d'accès au document confidentiel DOC_2024_005", "192.168.1.199",
"Mozilla/5.0 (Android)", "SESSION_567890"));
// Événements de suppression
evenements.add(new EvenementAudit(
now.minusHours(24), "SUPPRESSION", "WARNING", "Marie Dupont", "ADMIN_ORG", "EVENTS",
"Suppression événement", "Événement: Assemblée Générale 2023 supprimé", "192.168.1.105",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64)", "SESSION_123456"));
// Plus d'événements pour la pagination
for (int i = 0; i < 50; i++) {
LocalDateTime date = now.minusHours(i + 1).minusMinutes(new Random().nextInt(60));
String[] users = {"Marie Dupont", "Jean Martin", "Pierre Legrand", "Sophie Bernard", "Paul Durand"};
String[] actions = {"CONSULTATION", "MODIFICATION", "CONNEXION", "DECONNEXION"};
String[] modules = {"MEMBRES", "COTISATIONS", "EVENTS", "DOCUMENTS"};
String[] ips = {"192.168.1.105", "192.168.1.87", "192.168.1.92", "192.168.1.78"};
String user = users[i % users.length];
String action = actions[i % actions.length];
String module = modules[i % modules.length];
String ip = ips[i % ips.length];
String severite = i % 10 == 0 ? "WARNING" : "SUCCESS";
evenements.add(new EvenementAudit(
date, action, severite, user, "MEMBRE", module,
"Action automatique " + (i + 1), "Détails de l'action " + (i + 1), ip,
"Mozilla/5.0 (Auto)", "SESSION_AUTO_" + i));
} catch (Exception e) {
LOGGER.warning("Erreur lors de la conversion Map vers DTO: " + e.getMessage());
}
// Trier par date décroissante
evenements.sort((e1, e2) -> e2.getDateHeure().compareTo(e1.getDateHeure()));
return dto;
}
// Getters pour KPIs
public int getTotalEvenements() {
return evenements.size();
/**
* Applique les filtres sur les logs
*/
public void appliquerFiltres() {
if (tousLesLogs == null) {
logsFiltres = new ArrayList<>();
return;
}
logsFiltres = tousLesLogs.stream()
.filter(this::correspondAuxFiltres)
.collect(Collectors.toList());
}
public long getConnexionsReussies() {
return evenements.stream()
.filter(e -> "CONNEXION".equals(e.getTypeAction()) && "SUCCESS".equals(e.getSeverite()))
.filter(e -> e.getDateHeure().isAfter(LocalDateTime.now().toLocalDate().atStartOfDay()))
.count();
}
public long getTentativesEchouees() {
return evenements.stream()
.filter(e -> "CONNEXION".equals(e.getTypeAction()) && !"SUCCESS".equals(e.getSeverite()))
.filter(e -> e.getDateHeure().isAfter(LocalDateTime.now().minusWeeks(1)))
.count();
}
public long getAlertesSecurite() {
return evenements.stream()
.filter(e -> "CRITICAL".equals(e.getSeverite()) || "ERROR".equals(e.getSeverite()))
.count();
}
// Filtrage
public List<EvenementAudit> getEvenementsFiltres() {
return evenements.stream()
.filter(this::correspondAuxFiltres)
.collect(Collectors.toList());
}
private boolean correspondAuxFiltres(EvenementAudit event) {
private boolean correspondAuxFiltres(AuditLogDTO log) {
if (log.getDateHeure() == null) return false;
// Filtre par dates
if (dateDebut != null && event.getDateHeure().isBefore(convertToLocalDateTime(dateDebut))) {
LocalDateTime dateDebutLDT = dateDebut != null ?
LocalDateTime.ofInstant(dateDebut.toInstant(), ZoneId.systemDefault()) : null;
LocalDateTime dateFinLDT = dateFin != null ?
LocalDateTime.ofInstant(dateFin.toInstant(), ZoneId.systemDefault()).plusDays(1) : null;
if (dateDebutLDT != null && log.getDateHeure().isBefore(dateDebutLDT)) {
return false;
}
if (dateFin != null && event.getDateHeure().isAfter(convertToLocalDateTime(dateFin).plusDays(1))) {
if (dateFinLDT != null && log.getDateHeure().isAfter(dateFinLDT)) {
return false;
}
// Filtre par type d'action
if (!typeAction.isEmpty() && !typeAction.equals(event.getTypeAction())) {
if (!typeAction.isEmpty() && !typeAction.equals(log.getTypeAction())) {
return false;
}
// Filtre par sévérité
if (!severite.isEmpty() && !severite.equals(event.getSeverite())) {
if (!severite.isEmpty() && !severite.equals(log.getSeverite())) {
return false;
}
// Filtre par utilisateur
if (!utilisateur.isEmpty() && !event.getUtilisateur().toLowerCase().contains(utilisateur.toLowerCase())) {
if (!utilisateur.isEmpty() && log.getUtilisateur() != null &&
!log.getUtilisateur().toLowerCase().contains(utilisateur.toLowerCase())) {
return false;
}
// Filtre par module
if (!module.isEmpty() && !module.equals(event.getModule())) {
if (!module.isEmpty() && !module.equals(log.getModule())) {
return false;
}
// Filtre par IP
if (!ipAddress.isEmpty() && !event.getIpAddress().contains(ipAddress)) {
if (!ipAddress.isEmpty() && log.getIpAddress() != null &&
!log.getIpAddress().contains(ipAddress)) {
return false;
}
return true;
}
private LocalDateTime convertToLocalDateTime(Date date) {
return LocalDateTime.ofInstant(date.toInstant(), java.time.ZoneId.systemDefault());
}
// Actions
/**
* Recherche avec filtres via le backend
*/
public void rechercher() {
// La recherche se fait automatiquement via le filtrage
try {
LOGGER.info("Recherche de logs avec filtres");
String dateDebutStr = dateDebut != null ?
LocalDateTime.ofInstant(dateDebut.toInstant(), ZoneId.systemDefault()).toString() : null;
String dateFinStr = dateFin != null ?
LocalDateTime.ofInstant(dateFin.toInstant(), ZoneId.systemDefault()).toString() : null;
Map<String, Object> response = auditService.rechercher(
dateDebutStr, dateFinStr,
typeAction.isEmpty() ? null : typeAction,
severite.isEmpty() ? null : severite,
utilisateur.isEmpty() ? null : utilisateur,
module.isEmpty() ? null : module,
ipAddress.isEmpty() ? null : ipAddress,
0, 1000);
logsFiltres = new ArrayList<>();
if (response.containsKey("data")) {
@SuppressWarnings("unchecked")
List<Object> data = (List<Object>) response.get("data");
if (data != null) {
for (Object item : data) {
if (item instanceof AuditLogDTO) {
logsFiltres.add((AuditLogDTO) item);
} else if (item instanceof Map) {
@SuppressWarnings("unchecked")
AuditLogDTO dto = convertMapToDTO((Map<String, Object>) item);
logsFiltres.add(dto);
}
}
}
}
ajouterMessage(FacesMessage.SEVERITY_INFO, "Recherche",
logsFiltres.size() + " log(s) trouvé(s)");
} catch (Exception e) {
LOGGER.severe("Erreur lors de la recherche: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Erreur lors de la recherche: " + e.getMessage());
}
}
/**
* Réinitialise les filtres
*/
public void reinitialiserFiltres() {
Calendar cal = Calendar.getInstance();
dateFin = cal.getTime();
@@ -214,241 +309,246 @@ public class AuditBean implements Serializable {
utilisateur = "";
module = "";
ipAddress = "";
appliquerFiltres();
}
public void voirDetails(EvenementAudit event) {
this.evenementSelectionne = event;
/**
* Actualise les données
*/
public void actualiser() {
chargerLogs();
chargerStatistiques();
}
public void signalerEvenement(EvenementAudit event) {
// Logique pour signaler un événement comme suspect
/**
* Sélectionne un log pour voir les détails
*/
public void selectionnerLog(AuditLogDTO log) {
this.logSelectionne = log;
}
/**
* Méthode pour compatibilité avec l'ancienne page
*/
public void voirDetails(AuditLogDTO log) {
selectionnerLog(log);
}
/**
* Signale un événement d'audit suspect
*/
public void signalerEvenement(AuditLogDTO log) {
if (log == null) {
ajouterMessage(FacesMessage.SEVERITY_WARN, "Attention",
"Aucun log sélectionné");
return;
}
try {
LOGGER.info("Signalement de l'événement: " + log.getId());
// Envoyer une notification aux administrateurs
String message = String.format(
"Événement signalé - Type: %s, Utilisateur: %s, Date: %s, IP: %s",
log.getTypeAction(),
log.getUtilisateur(),
log.getDateHeure() != null ? log.getDateHeure().format(DATE_FORMATTER) : "N/A",
log.getIpAddress()
);
// Récupérer l'ID de l'utilisateur courant pour le signalement
String signaleurId = userSession.getCurrentUser() != null
? userSession.getCurrentUser().getId().toString()
: "anonyme";
notificationService.envoyerNotificationGroupe(
"SYSTEME",
"Signalement d'un événement d'audit",
message,
List.of(signaleurId) // Envoyer aux admins (à adapter selon votre logique)
);
ajouterMessage(FacesMessage.SEVERITY_INFO, "Signalement",
"L'événement a été signalé aux administrateurs");
} catch (Exception e) {
LOGGER.severe("Erreur lors du signalement: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de signaler l'événement: " + e.getMessage());
}
}
/**
* Exporte les logs d'audit en CSV
*/
public void exporter() {
// Logique d'export selon le format sélectionné
try {
LOGGER.info("Export de " + (logsFiltres != null ? logsFiltres.size() : 0) + " logs d'audit");
List<AuditLogDTO> logsAExporter = logsFiltres != null && !logsFiltres.isEmpty()
? logsFiltres
: tousLesLogs;
if (logsAExporter == null || logsAExporter.isEmpty()) {
ajouterMessage(FacesMessage.SEVERITY_WARN, "Attention",
"Aucun log à exporter");
return;
}
// Générer le CSV
StringBuilder csv = new StringBuilder();
csv.append("Date/Heure;Type Action;Utilisateur;Module;IP;Sévérité;Détails\n");
for (AuditLogDTO log : logsAExporter) {
csv.append(String.format("%s;%s;%s;%s;%s;%s;%s\n",
log.getDateHeure() != null ? log.getDateHeure().format(DATE_FORMATTER) : "",
log.getTypeAction() != null ? log.getTypeAction() : "",
log.getUtilisateur() != null ? log.getUtilisateur() : "",
log.getModule() != null ? log.getModule() : "",
log.getIpAddress() != null ? log.getIpAddress() : "",
log.getSeverite() != null ? log.getSeverite() : "",
log.getDetails() != null ? log.getDetails().replace(";", ",").replace("\n", " ") : ""
));
}
byte[] csvData = csv.toString().getBytes(StandardCharsets.UTF_8);
telechargerFichier(csvData, "audit-logs-export.csv", "text/csv");
ajouterMessage(FacesMessage.SEVERITY_INFO, "Export",
"Export de " + logsAExporter.size() + " log(s) terminé");
} catch (Exception e) {
LOGGER.severe("Erreur lors de l'export: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible d'exporter les logs: " + e.getMessage());
}
}
/**
* Télécharge un fichier via le navigateur
*/
private void telechargerFichier(byte[] data, String nomFichier, String contentType) {
try {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
ec.responseReset();
ec.setResponseContentType(contentType + "; charset=UTF-8");
ec.setResponseContentLength(data.length);
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + nomFichier + "\"");
OutputStream output = ec.getResponseOutputStream();
output.write(data);
output.flush();
fc.responseComplete();
} catch (Exception e) {
LOGGER.severe("Erreur téléchargement fichier: " + e.getMessage());
throw new RuntimeException("Erreur lors du téléchargement", e);
}
}
// Getters pour KPIs
public int getTotalEvenements() {
if (statistiques != null && statistiques.containsKey("total")) {
Object total = statistiques.get("total");
if (total instanceof Number) {
return ((Number) total).intValue();
}
}
return tousLesLogs != null ? tousLesLogs.size() : 0;
}
public long getConnexionsReussies() {
if (tousLesLogs == null) return 0;
LocalDateTime aujourdhui = LocalDateTime.now().toLocalDate().atStartOfDay();
return tousLesLogs.stream()
.filter(log -> "CONNEXION".equals(log.getTypeAction()) &&
"SUCCESS".equals(log.getSeverite()) &&
log.getDateHeure() != null &&
log.getDateHeure().isAfter(aujourdhui))
.count();
}
public long getTentativesEchouees() {
if (tousLesLogs == null) return 0;
LocalDateTime semainePassee = LocalDateTime.now().minusWeeks(1);
return tousLesLogs.stream()
.filter(log -> "CONNEXION".equals(log.getTypeAction()) &&
!"SUCCESS".equals(log.getSeverite()) &&
log.getDateHeure() != null &&
log.getDateHeure().isAfter(semainePassee))
.count();
}
public long getAlertesSecurite() {
if (tousLesLogs == null) return 0;
return tousLesLogs.stream()
.filter(log -> "CRITICAL".equals(log.getSeverite()) ||
"ERROR".equals(log.getSeverite()))
.count();
}
// Méthode utilitaire pour ajouter des messages
private void ajouterMessage(FacesMessage.Severity severity, String summary, String detail) {
FacesContext.getCurrentInstance()
.addMessage(null, new FacesMessage(severity, summary, detail));
}
// Getters et Setters
public Date getDateDebut() { return dateDebut; }
public void setDateDebut(Date dateDebut) { this.dateDebut = dateDebut; }
public void setDateDebut(Date dateDebut) {
this.dateDebut = dateDebut;
appliquerFiltres();
}
public Date getDateFin() { return dateFin; }
public void setDateFin(Date dateFin) { this.dateFin = dateFin; }
public void setDateFin(Date dateFin) {
this.dateFin = dateFin;
appliquerFiltres();
}
public String getTypeAction() { return typeAction; }
public void setTypeAction(String typeAction) { this.typeAction = typeAction; }
public void setTypeAction(String typeAction) {
this.typeAction = typeAction;
appliquerFiltres();
}
public String getSeverite() { return severite; }
public void setSeverite(String severite) { this.severite = severite; }
public void setSeverite(String severite) {
this.severite = severite;
appliquerFiltres();
}
public String getUtilisateur() { return utilisateur; }
public void setUtilisateur(String utilisateur) { this.utilisateur = utilisateur; }
public void setUtilisateur(String utilisateur) {
this.utilisateur = utilisateur;
appliquerFiltres();
}
public String getModule() { return module; }
public void setModule(String module) { this.module = module; }
public void setModule(String module) {
this.module = module;
appliquerFiltres();
}
public String getIpAddress() { return ipAddress; }
public void setIpAddress(String ipAddress) { this.ipAddress = ipAddress; }
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
appliquerFiltres();
}
public EvenementAudit getEvenementSelectionne() { return evenementSelectionne; }
public void setEvenementSelectionne(EvenementAudit evenementSelectionne) { this.evenementSelectionne = evenementSelectionne; }
public List<AuditLogDTO> getEvenementsFiltres() {
return logsFiltres != null ? logsFiltres : new ArrayList<>();
}
public AuditLogDTO getEvenementSelectionne() { return logSelectionne; }
public void setEvenementSelectionne(AuditLogDTO log) { this.logSelectionne = log; }
public String getFormatExport() { return formatExport; }
public void setFormatExport(String formatExport) { this.formatExport = formatExport; }
public boolean isInclurefiltresExport() { return inclureFiltresExport; }
public void setInclurefiltresExport(boolean inclureFiltresExport) { this.inclureFiltresExport = inclureFiltresExport; }
// Classe interne EvenementAudit
public static class EvenementAudit implements Serializable {
private LocalDateTime dateHeure;
private String typeAction;
private String severite;
private String utilisateur;
private String role;
private String module;
private String description;
private String details;
private String ipAddress;
private String userAgent;
private String sessionId;
public EvenementAudit(LocalDateTime dateHeure, String typeAction, String severite,
String utilisateur, String role, String module, String description,
String details, String ipAddress, String userAgent, String sessionId) {
this.dateHeure = dateHeure;
this.typeAction = typeAction;
this.severite = severite;
this.utilisateur = utilisateur;
this.role = role;
this.module = module;
this.description = description;
this.details = details;
this.ipAddress = ipAddress;
this.userAgent = userAgent;
this.sessionId = sessionId;
}
// Propriétés calculées pour l'affichage
public String getDateFormatee() {
return dateHeure.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
}
public String getHeureFormatee() {
return dateHeure.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
}
public String getDateHeureComplete() {
return dateHeure.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"));
}
public String getSeveriteLibelle() {
switch (severite) {
case "SUCCESS": return "Succès";
case "INFO": return "Info";
case "WARNING": return "Attention";
case "ERROR": return "Erreur";
case "CRITICAL": return "Critique";
default: return severite;
}
}
public String getSeveriteSeverity() {
switch (severite) {
case "SUCCESS": return "success";
case "INFO": return "info";
case "WARNING": return "warning";
case "ERROR": return "danger";
case "CRITICAL": return "danger";
default: return "secondary";
}
}
public String getSeveriteIcon() {
switch (severite) {
case "SUCCESS": return "pi pi-check";
case "INFO": return "pi pi-info";
case "WARNING": return "pi pi-exclamation-triangle";
case "ERROR": return "pi pi-times";
case "CRITICAL": return "pi pi-ban";
default: return "pi pi-circle";
}
}
public String getActionIcon() {
switch (typeAction) {
case "CONNEXION": return "pi pi-sign-in";
case "DECONNEXION": return "pi pi-sign-out";
case "CREATION": return "pi pi-plus";
case "MODIFICATION": return "pi pi-pencil";
case "SUPPRESSION": return "pi pi-trash";
case "CONSULTATION": return "pi pi-eye";
case "EXPORT": return "pi pi-download";
case "CONFIGURATION": return "pi pi-cog";
default: return "pi pi-circle";
}
}
public String getActionColor() {
switch (typeAction) {
case "CONNEXION": return "#28a745";
case "DECONNEXION": return "#6c757d";
case "CREATION": return "#007bff";
case "MODIFICATION": return "#ffc107";
case "SUPPRESSION": return "#dc3545";
case "CONSULTATION": return "#17a2b8";
case "EXPORT": return "#6f42c1";
case "CONFIGURATION": return "#fd7e14";
default: return "#6c757d";
}
}
public String getModuleLibelle() {
switch (module) {
case "AUTH": return "Authentification";
case "MEMBRES": return "Membres";
case "COTISATIONS": return "Cotisations";
case "EVENTS": return "Événements";
case "DOCUMENTS": return "Documents";
case "CONFIG": return "Configuration";
case "RAPPORTS": return "Rapports";
default: return module;
}
}
public String getAction() {
switch (typeAction) {
case "CONNEXION": return "Connexion";
case "DECONNEXION": return "Déconnexion";
case "CREATION": return "Création";
case "MODIFICATION": return "Modification";
case "SUPPRESSION": return "Suppression";
case "CONSULTATION": return "Consultation";
case "EXPORT": return "Export";
case "CONFIGURATION": return "Configuration";
default: return typeAction;
}
}
public String getDescriptionComplete() {
return description + (details != null && !details.isEmpty() ? "\n\nDétails: " + details : "");
}
public String getUserAgentComplet() {
return userAgent;
}
public String getDonneesAvant() {
// Simulation de données avant modification
if ("MODIFICATION".equals(typeAction)) {
return "{\n \"nom\": \"Ancien Nom\",\n \"email\": \"ancien@email.com\",\n \"statut\": \"INACTIF\"\n}";
}
return null;
}
public String getDonneesApres() {
// Simulation de données après modification
if ("MODIFICATION".equals(typeAction)) {
return "{\n \"nom\": \"Nouveau Nom\",\n \"email\": \"nouveau@email.com\",\n \"statut\": \"ACTIF\"\n}";
}
return null;
}
// Getters et Setters
public LocalDateTime getDateHeure() { return dateHeure; }
public void setDateHeure(LocalDateTime dateHeure) { this.dateHeure = dateHeure; }
public String getTypeAction() { return typeAction; }
public void setTypeAction(String typeAction) { this.typeAction = typeAction; }
public String getSeverite() { return severite; }
public void setSeverite(String severite) { this.severite = severite; }
public String getUtilisateur() { return utilisateur; }
public void setUtilisateur(String utilisateur) { this.utilisateur = utilisateur; }
public String getRole() { return role; }
public void setRole(String role) { this.role = role; }
public String getModule() { return module; }
public void setModule(String module) { this.module = module; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getDetails() { return details; }
public void setDetails(String details) { this.details = details; }
public String getIpAddress() { return ipAddress; }
public void setIpAddress(String ipAddress) { this.ipAddress = ipAddress; }
public String getUserAgent() {
return userAgent != null && userAgent.length() > 20 ?
userAgent.substring(0, 20) + "..." : userAgent;
}
public void setUserAgent(String userAgent) { this.userAgent = userAgent; }
public String getSessionId() { return sessionId; }
public void setSessionId(String sessionId) { this.sessionId = sessionId; }
public boolean isInclureFiltresExport() { return inclureFiltresExport; }
public void setInclureFiltresExport(boolean inclureFiltresExport) {
this.inclureFiltresExport = inclureFiltresExport;
}
}
}

View File

@@ -1,79 +1,346 @@
package dev.lions.unionflow.client.view;
import jakarta.enterprise.context.RequestScoped;
import dev.lions.unionflow.client.service.AdhesionService;
import dev.lions.unionflow.client.service.AuditService;
import dev.lions.unionflow.client.service.CotisationService;
import dev.lions.unionflow.client.service.EvenementService;
import dev.lions.unionflow.client.service.MembreService;
import jakarta.annotation.PostConstruct;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
@Named("dashboardBean")
@RequestScoped
@ViewScoped
public class DashboardBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(DashboardBean.class.getName());
@Inject
@RestClient
private MembreService membreService;
@Inject
@RestClient
private CotisationService cotisationService;
@Inject
@RestClient
private AdhesionService adhesionService;
@Inject
@RestClient
private EvenementService evenementService;
@Inject
@RestClient
private AuditService auditService;
// Propriétés existantes
private int activeMembers = 245;
private String totalCotisations = "12,450,000";
private int pendingAides = 7;
private int upcomingEvents = 3;
private int activeMembers = 0;
private String totalCotisations = "0";
private int pendingAides = 0;
private int upcomingEvents = 0;
// Nouvelles propriétés pour le dashboard enrichi
private int totalMembers = 268;
private String aidesDistribuees = "3,200,000";
private int tauxParticipation = 78;
private int totalMembers = 0;
private String aidesDistribuees = "0";
private int tauxParticipation = 0;
// Propriétés pour les alertes
private int cotisationsRetard = 12;
private int adhesionsExpiration = 8;
private int demandesToTraiter = 15;
private int tachesFinaliser = 4;
private int cotisationsRetard = 0;
private int adhesionsExpiration = 0;
private int demandesToTraiter = 0;
private int tachesFinaliser = 0;
// Propriétés pour les évolutions
private int membresEvolutionPourcent = 8;
private int cotisationsEvolutionPourcent = 15;
private String objectifCotisations = "15,000,000";
private int aidesApprouvees = 12;
private int membresParticipants = 189;
private int membresEvolutionPourcent = 0;
private int cotisationsEvolutionPourcent = 0;
private String objectifCotisations = "0";
private int aidesApprouvees = 0;
private int membresParticipants = 0;
// Propriétés pour le graphique
private String periodeGraph = "3M";
private String filtreActivite = "ALL";
// Propriétés pour les cotisations
private int cotisationsAJour = 60;
private int cotisationsRetardPourcent = 20;
private int cotisationsImpayees = 20;
private int cotisationsAJour = 0;
private int cotisationsRetardPourcent = 0;
private int cotisationsImpayees = 0;
private int cotisationsAJourPourcent = 0;
private int cotisationsImpayeesPourcent = 0;
private int tauxCollecte = 0;
// Propriétés pour les tâches prioritaires
private int adhesionsPendantes = 5;
private int aidesEnAttente = 7;
private int evenementsAPlanifier = 2;
private int adhesionsPendantes = 0;
private int aidesEnAttente = 0;
private int evenementsAPlanifier = 0;
// Propriétés financières
private Date moisSelectionne = new Date();
private String recettesMois = "4,250,000";
private String depensesMois = "1,800,000";
private String soldeMois = "2,450,000";
private String tresorerie = "18,750,000";
private String recettesMois = "0";
private String depensesMois = "0";
private String soldeMois = "0";
private String tresorerie = "0";
// Date actuelle
private String currentDate;
// Propriétés manquantes pour les barres de progression
private int tauxActivite = 75;
private int tauxObjectifCotisations = 82;
private int tauxAidesTraitees = 68;
private int tauxEngagement = 89;
private int tachesCompletees = 23;
private boolean hasAlerts = true;
private int tauxActivite = 0;
private int tauxObjectifCotisations = 0;
private int tauxAidesTraitees = 0;
private int tauxEngagement = 0;
private int tachesCompletees = 0;
private boolean hasAlerts = false;
// Liste des activités récentes (chargées depuis le backend)
private List<Activity> recentActivities;
// Évolution financière (3 derniers mois)
private List<MoisFinancier> evolutionFinanciere;
private int evolutionRecettesPourcent = 0;
private int evolutionDepensesPourcent = 0;
private String tendanceParticipation = "Stable";
public DashboardBean() {
this.currentDate = LocalDate.now().format(DateTimeFormatter.ofPattern("dd MMMM yyyy"));
this.evolutionFinanciere = new ArrayList<>();
}
@PostConstruct
public void init() {
chargerDonneesBackend();
}
/**
* Charge toutes les données depuis les services backend
*/
private void chargerDonneesBackend() {
LOGGER.info("Chargement des données du dashboard depuis le backend...");
try {
chargerStatistiquesMembres();
chargerStatistiquesCotisations();
chargerStatistiquesAdhesions();
chargerStatistiquesEvenements();
chargerActivitesRecentes();
calculerIndicateurs();
LOGGER.info("Données du dashboard chargées avec succès");
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement du dashboard: " + e.getMessage());
}
}
private void chargerStatistiquesMembres() {
try {
MembreService.StatistiquesMembreDTO statsMembres = membreService.obtenirStatistiques();
if (statsMembres != null) {
totalMembers = statsMembres.getTotalMembres() != null ? statsMembres.getTotalMembres().intValue() : 0;
activeMembers = statsMembres.getMembresActifs() != null ? statsMembres.getMembresActifs().intValue() : 0;
// Evolution mensuelle (si disponible dans le DTO)
if (statsMembres.getNouveauxMembres30Jours() != null && totalMembers > 0) {
membresEvolutionPourcent = (statsMembres.getNouveauxMembres30Jours().intValue() * 100) / totalMembers;
}
LOGGER.info("Stats membres chargées: Total=" + totalMembers + ", Actifs=" + activeMembers);
}
} catch (Exception e) {
LOGGER.warning("Impossible de charger les stats membres: " + e.getMessage());
}
}
private void chargerStatistiquesCotisations() {
try {
Map<String, Object> statsCotisations = cotisationService.obtenirStatistiques();
// Total collecté
Object totalCollecte = statsCotisations.get("totalCollecte");
if (totalCollecte != null) {
BigDecimal montant = new BigDecimal(totalCollecte.toString());
totalCotisations = String.format("%,d", montant.longValue());
tresorerie = totalCotisations; // Approximation
}
// Cotisations en retard
cotisationsRetard = ((Number) statsCotisations.getOrDefault("cotisationsEnRetard", 0)).intValue();
cotisationsImpayees = ((Number) statsCotisations.getOrDefault("cotisationsImpayees", 0)).intValue();
cotisationsAJour = ((Number) statsCotisations.getOrDefault("cotisationsAJour", 0)).intValue();
// Calculer pourcentage de retard
int totalCot = cotisationsAJour + cotisationsRetard + cotisationsImpayees;
if (totalCot > 0) {
cotisationsRetardPourcent = (cotisationsRetard * 100) / totalCot;
}
LOGGER.info("Stats cotisations chargées: Total=" + totalCotisations);
} catch (Exception e) {
LOGGER.warning("Impossible de charger les stats cotisations: " + e.getMessage());
}
}
private void chargerStatistiquesAdhesions() {
try {
Map<String, Object> statsAdhesions = adhesionService.obtenirStatistiques();
adhesionsPendantes = ((Number) statsAdhesions.getOrDefault("adhesionsEnAttente", 0)).intValue();
demandesToTraiter = adhesionsPendantes; // Alias
LOGGER.info("Stats adhésions chargées: En attente=" + adhesionsPendantes);
} catch (Exception e) {
LOGGER.warning("Impossible de charger les stats adhésions: " + e.getMessage());
}
}
private void chargerStatistiquesEvenements() {
try {
// Compter les événements à venir via l'API de liste
Map<String, Object> evenementsAVenir = evenementService.listerAVenir(0, 100);
if (evenementsAVenir != null && evenementsAVenir.containsKey("totalElements")) {
upcomingEvents = ((Number) evenementsAVenir.get("totalElements")).intValue();
}
LOGGER.info("Stats événements chargées: À venir=" + upcomingEvents);
} catch (Exception e) {
LOGGER.warning("Impossible de charger les stats événements: " + e.getMessage());
}
}
@SuppressWarnings("unchecked")
private void chargerActivitesRecentes() {
try {
// Récupérer les 10 derniers logs d'audit
Map<String, Object> resultat = auditService.listerTous(0, 10, "dateHeure", "DESC");
recentActivities = new ArrayList<>();
if (resultat != null && resultat.containsKey("content")) {
List<Map<String, Object>> logs = (List<Map<String, Object>>) resultat.get("content");
for (Map<String, Object> logMap : logs) {
String typeAction = (String) logMap.get("typeAction");
String description = (String) logMap.get("description");
String details = (String) logMap.get("details");
String utilisateur = (String) logMap.get("utilisateur");
Activity activity = new Activity(
LocalDateTime.now(), // Simplification - devrait parser la date
typeAction != null ? typeAction : "ACTION",
getSeverityFromAction(typeAction),
getIconFromAction(typeAction),
description != null ? description : typeAction,
details,
null,
utilisateur != null ? utilisateur : "Système",
"Utilisateur"
);
recentActivities.add(activity);
}
}
LOGGER.info("Activités récentes chargées: " + recentActivities.size());
} catch (Exception e) {
LOGGER.warning("Impossible de charger les activités récentes: " + e.getMessage());
recentActivities = new ArrayList<>();
}
}
private void calculerIndicateurs() {
// Calculer taux d'activité
if (totalMembers > 0 && activeMembers > 0) {
tauxActivite = (activeMembers * 100) / totalMembers;
}
// Calculer taux de participation
tauxParticipation = tauxActivite; // Approximation
// Calculer pourcentages de cotisations
int totalCot = cotisationsAJour + cotisationsRetard + cotisationsImpayees;
if (totalCot > 0) {
cotisationsAJourPourcent = (cotisationsAJour * 100) / totalCot;
cotisationsRetardPourcent = (cotisationsRetard * 100) / totalCot;
cotisationsImpayeesPourcent = (cotisationsImpayees * 100) / totalCot;
// Taux de collecte = cotisations à jour + en retard
tauxCollecte = ((cotisationsAJour + cotisationsRetard) * 100) / totalCot;
}
// Calculer évolution financière
calculerEvolutionFinanciere();
// Déterminer s'il y a des alertes
hasAlerts = (cotisationsRetard > 0 || adhesionsPendantes > 0 || demandesToTraiter > 0);
}
private void calculerEvolutionFinanciere() {
evolutionFinanciere.clear();
try {
// Récupérer les statistiques des 3 derniers mois depuis le backend
LocalDate now = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM yyyy");
for (int i = 2; i >= 0; i--) {
LocalDate mois = now.minusMonths(i);
String libelleMois = mois.format(formatter);
// Pour chaque mois, on pourrait appeler le backend avec un filtre de date
// Pour l'instant, on calcule une approximation
BigDecimal montant = i == 0 ?
new BigDecimal(totalCotisations.replace(",", "")) :
BigDecimal.ZERO; // Le backend devrait fournir les montants historiques
evolutionFinanciere.add(new MoisFinancier(libelleMois, montant));
}
// Calculer tendances (si on a les données)
if (evolutionFinanciere.size() >= 2) {
MoisFinancier dernierMois = evolutionFinanciere.get(evolutionFinanciere.size() - 1);
MoisFinancier avantDernierMois = evolutionFinanciere.get(evolutionFinanciere.size() - 2);
if (avantDernierMois.getMontant().compareTo(BigDecimal.ZERO) > 0) {
BigDecimal diff = dernierMois.getMontant().subtract(avantDernierMois.getMontant());
evolutionRecettesPourcent = diff.multiply(BigDecimal.valueOf(100))
.divide(avantDernierMois.getMontant(), 0, java.math.RoundingMode.HALF_UP).intValue();
}
}
} catch (Exception e) {
LOGGER.warning("Erreur lors du calcul de l'évolution financière: " + e.getMessage());
}
}
private String getSeverityFromAction(String action) {
if (action == null) return "info";
if (action.contains("ERREUR") || action.contains("ECHEC")) return "danger";
if (action.contains("CREATION") || action.contains("PAIEMENT")) return "success";
if (action.contains("MODIFICATION")) return "warning";
return "info";
}
private String getIconFromAction(String action) {
if (action == null) return "pi pi-info-circle";
if (action.contains("MEMBRE")) return "pi pi-user";
if (action.contains("COTISATION") || action.contains("PAIEMENT")) return "pi pi-money-bill";
if (action.contains("ADHESION")) return "pi pi-user-plus";
if (action.contains("EVENEMENT")) return "pi pi-calendar";
return "pi pi-info-circle";
}
// Getters et Setters complets
@@ -185,71 +452,54 @@ public class DashboardBean implements Serializable {
public boolean isHasAlerts() { return hasAlerts; }
public void setHasAlerts(boolean hasAlerts) { this.hasAlerts = hasAlerts; }
public int getCotisationsAJourPourcent() { return cotisationsAJourPourcent; }
public void setCotisationsAJourPourcent(int cotisationsAJourPourcent) { this.cotisationsAJourPourcent = cotisationsAJourPourcent; }
public int getCotisationsImpayeesPourcent() { return cotisationsImpayeesPourcent; }
public void setCotisationsImpayeesPourcent(int cotisationsImpayeesPourcent) { this.cotisationsImpayeesPourcent = cotisationsImpayeesPourcent; }
public int getTauxCollecte() { return tauxCollecte; }
public void setTauxCollecte(int tauxCollecte) { this.tauxCollecte = tauxCollecte; }
public List<MoisFinancier> getEvolutionFinanciere() { return evolutionFinanciere; }
public void setEvolutionFinanciere(List<MoisFinancier> evolutionFinanciere) { this.evolutionFinanciere = evolutionFinanciere; }
public int getEvolutionRecettesPourcent() { return evolutionRecettesPourcent; }
public void setEvolutionRecettesPourcent(int evolutionRecettesPourcent) { this.evolutionRecettesPourcent = evolutionRecettesPourcent; }
public int getEvolutionDepensesPourcent() { return evolutionDepensesPourcent; }
public void setEvolutionDepensesPourcent(int evolutionDepensesPourcent) { this.evolutionDepensesPourcent = evolutionDepensesPourcent; }
public String getTendanceParticipation() { return tendanceParticipation; }
public void setTendanceParticipation(String tendanceParticipation) { this.tendanceParticipation = tendanceParticipation; }
// Méthodes utilitaires pour l'affichage des tendances
public String getEvolutionRecettesIcon() {
return evolutionRecettesPourcent >= 0 ? "pi pi-arrow-up text-green-500" : "pi pi-arrow-down text-red-500";
}
public String getEvolutionRecettesPrefix() {
return evolutionRecettesPourcent >= 0 ? "+" : "";
}
public String getEvolutionDepensesIcon() {
return evolutionDepensesPourcent <= 0 ? "pi pi-arrow-down text-green-500" : "pi pi-arrow-up text-red-500";
}
public String getEvolutionDepensesPrefix() {
return evolutionDepensesPourcent >= 0 ? "+" : "";
}
// Méthodes pour les activités récentes
public List<Activity> getRecentActivities() {
List<Activity> activities = new ArrayList<>();
activities.add(new Activity(
LocalDateTime.now().minusHours(2),
"COTISATION",
"success",
"pi pi-check-circle",
"Paiement cotisation validé",
"Cotisation de Fatou Sow pour juillet 2024",
"25,000",
"Fatou Sow",
"Membre"
));
activities.add(new Activity(
LocalDateTime.now().minusHours(5),
"ADHESION",
"info",
"pi pi-user-plus",
"Nouvelle demande d'adhésion",
"Demande soumise par Moussa Ba",
null,
"Moussa Ba",
"Candidat"
));
activities.add(new Activity(
LocalDateTime.now().minusHours(8),
"AIDE",
"warning",
"pi pi-heart",
"Demande d'aide en traitement",
"Aide médicale pour famille Ndiaye",
"150,000",
"Aminata Ndiaye",
"Membre"
));
activities.add(new Activity(
LocalDateTime.now().minusDays(1),
"EVENEMENT",
"info",
"pi pi-calendar",
"Événement planifié",
"Assemblée générale mensuelle programmée",
null,
"Admin",
"Administrateur"
));
activities.add(new Activity(
LocalDateTime.now().minusDays(1).minusHours(3),
"COTISATION",
"danger",
"pi pi-exclamation-triangle",
"Relance envoyée",
"Relance automatique pour cotisation en retard",
null,
"Système",
"Automatique"
));
return activities;
if (recentActivities == null) {
return new ArrayList<>();
}
return recentActivities;
}
public void actualiser() {
chargerDonneesBackend();
}
// Actions de navigation
@@ -346,4 +596,57 @@ public class DashboardBean implements Serializable {
public String getUserRole() { return userRole; }
public void setUserRole(String userRole) { this.userRole = userRole; }
}
/**
* Classe interne pour représenter les données financières d'un mois
*/
public static class MoisFinancier implements Serializable {
private static final long serialVersionUID = 1L;
private String libelle;
private BigDecimal montant;
private int hauteur; // Pour l'affichage visuel en pixels
public MoisFinancier(String libelle, BigDecimal montant) {
this.libelle = libelle;
this.montant = montant != null ? montant : BigDecimal.ZERO;
// Calculer la hauteur proportionnelle (entre 40 et 120 pixels)
this.hauteur = calculerHauteur(this.montant);
}
private int calculerHauteur(BigDecimal montant) {
if (montant.compareTo(BigDecimal.ZERO) == 0) {
return 40; // Hauteur minimale
}
// Normaliser entre 40 et 120 pixels
// On suppose un max de 10M FCFA pour l'échelle
BigDecimal maxRef = new BigDecimal("10000000");
double ratio = montant.divide(maxRef, 4, java.math.RoundingMode.HALF_UP).doubleValue();
int hauteur = 40 + (int)(ratio * 80);
return Math.min(Math.max(hauteur, 40), 120); // Entre 40 et 120
}
public String getLibelle() { return libelle; }
public void setLibelle(String libelle) { this.libelle = libelle; }
public BigDecimal getMontant() { return montant; }
public void setMontant(BigDecimal montant) {
this.montant = montant;
this.hauteur = calculerHauteur(montant);
}
public String getMontantFormatte() {
if (montant.compareTo(new BigDecimal("1000000")) >= 0) {
// Afficher en millions
BigDecimal millions = montant.divide(new BigDecimal("1000000"), 1, java.math.RoundingMode.HALF_UP);
return millions.toString() + "M FCFA";
} else if (montant.compareTo(BigDecimal.ZERO) == 0) {
return "0 FCFA";
} else {
return String.format("%,d FCFA", montant.longValue());
}
}
public int getHauteur() { return hauteur; }
public void setHauteur(int hauteur) { this.hauteur = hauteur; }
}
}

View File

@@ -54,7 +54,7 @@ public class EntitesGestionBean implements Serializable {
private void initializeStatistiques() {
statistiques = new Statistiques();
try {
List<AssociationDTO> associations = associationService.listerToutes();
List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
statistiques.setTotalEntites(associations.size());
long actives = associations.stream().filter(a -> "ACTIVE".equals(a.getStatut())).count();
statistiques.setEntitesActives((int) actives);
@@ -82,7 +82,7 @@ public class EntitesGestionBean implements Serializable {
private void initializeEntites() {
toutesLesEntites = new ArrayList<>();
try {
List<AssociationDTO> associations = associationService.listerToutes();
List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
for (AssociationDTO dto : associations) {
Entite entite = convertToEntite(dto);
toutesLesEntites.add(entite);

View File

@@ -0,0 +1,470 @@
package dev.lions.unionflow.client.view;
import jakarta.enterprise.context.SessionScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.annotation.PostConstruct;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;
/**
* Bean pour la gestion des favoris de l'utilisateur
* Gère les pages favorites, documents favoris, contacts favoris et raccourcis personnalisés
*/
@Named("favorisBean")
@SessionScoped
public class FavorisBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(FavorisBean.class.getName());
@Inject
private UserSession userSession;
// Statistiques
private int totalFavoris = 0;
private int totalPages = 0;
private int totalDocuments = 0;
private int totalContacts = 0;
// Favoris
private List<PageFavorite> pagesFavorites;
private List<DocumentFavorite> documentsFavoris;
private List<ContactFavorite> contactsFavoris;
private List<RaccourciPersonnalise> raccourcis;
@PostConstruct
public void init() {
chargerFavoris();
}
/**
* Charge tous les favoris
*/
public void chargerFavoris() {
chargerPagesFavorites();
chargerDocumentsFavoris();
chargerContactsFavoris();
chargerRaccourcis();
calculerStatistiques();
}
/**
* Charge les pages favorites
*/
private void chargerPagesFavorites() {
pagesFavorites = new ArrayList<>();
// Pages favorites par défaut
PageFavorite page1 = new PageFavorite();
page1.setId(UUID.randomUUID());
page1.setTitre("Mes Activités");
page1.setDescription("Historique et suivi de vos actions");
page1.setUrl("/pages/secure/personnel/activites.xhtml");
page1.setIcon("pi-chart-bar");
page1.setCouleur("blue");
page1.setCategorie("FONCTIONNALITE");
page1.setDerniereVisite("il y a 5 min");
page1.setNbVisites(45);
page1.setEstPlusUtilise(true);
pagesFavorites.add(page1);
PageFavorite page2 = new PageFavorite();
page2.setId(UUID.randomUUID());
page2.setTitre("Mon Agenda");
page2.setDescription("Planning et événements personnels");
page2.setUrl("/pages/secure/personnel/agenda.xhtml");
page2.setIcon("pi-calendar");
page2.setCouleur("green");
page2.setCategorie("FONCTIONNALITE");
page2.setDerniereVisite("il y a 2h");
page2.setNbVisites(23);
pagesFavorites.add(page2);
PageFavorite page3 = new PageFavorite();
page3.setId(UUID.randomUUID());
page3.setTitre("Liste des Membres");
page3.setDescription("Annuaire et contacts membres");
page3.setUrl("/pages/secure/membre/liste.xhtml");
page3.setIcon("pi-users");
page3.setCouleur("purple");
page3.setCategorie("FONCTIONNALITE");
page3.setDerniereVisite("Hier");
page3.setNbVisites(12);
pagesFavorites.add(page3);
PageFavorite page4 = new PageFavorite();
page4.setId(UUID.randomUUID());
page4.setTitre("Cotisations");
page4.setDescription("Paiements et historique");
page4.setUrl("/pages/secure/cotisation/liste.xhtml");
page4.setIcon("pi-dollar");
page4.setCouleur("orange");
page4.setCategorie("FINANCE");
page4.setDerniereVisite("il y a 3 jours");
page4.setNbVisites(8);
pagesFavorites.add(page4);
PageFavorite page5 = new PageFavorite();
page5.setId(UUID.randomUUID());
page5.setTitre("Rapports Financiers");
page5.setDescription("Consultez vos rapports financiers personnels");
page5.setUrl("/pages/secure/rapport/finances.xhtml");
page5.setIcon("pi-chart-bar");
page5.setCouleur("green");
page5.setCategorie("FINANCE");
page5.setDerniereVisite("il y a 1 semaine");
page5.setNbVisites(3);
pagesFavorites.add(page5);
PageFavorite page6 = new PageFavorite();
page6.setId(UUID.randomUUID());
page6.setTitre("Mes Formations");
page6.setDescription("Catalogue et suivi de vos formations");
page6.setUrl("/pages/secure/formation/liste.xhtml");
page6.setIcon("pi-graduation-cap");
page6.setCouleur("purple");
page6.setCategorie("FORMATION");
page6.setDerniereVisite("il y a 1 semaine");
page6.setNbVisites(1);
pagesFavorites.add(page6);
PageFavorite page7 = new PageFavorite();
page7.setId(UUID.randomUUID());
page7.setTitre("Guide Utilisateur");
page7.setDescription("Documentation et aide à l'utilisation");
page7.setUrl("/pages/public/aide.xhtml");
page7.setIcon("pi-book");
page7.setCouleur("green");
page7.setCategorie("AIDE");
page7.setDerniereVisite("il y a 1 semaine");
page7.setNbVisites(5);
pagesFavorites.add(page7);
PageFavorite page8 = new PageFavorite();
page8.setId(UUID.randomUUID());
page8.setTitre("Rapports & Statistiques");
page8.setDescription("Analyses et statistiques détaillées");
page8.setUrl("/pages/secure/rapport/activites.xhtml");
page8.setIcon("pi-chart-line");
page8.setCouleur("blue");
page8.setCategorie("RAPPORT");
page8.setDerniereVisite("il y a 2 semaines");
page8.setNbVisites(2);
pagesFavorites.add(page8);
}
/**
* Charge les documents favoris
*/
private void chargerDocumentsFavoris() {
documentsFavoris = new ArrayList<>();
DocumentFavorite doc1 = new DocumentFavorite();
doc1.setId(UUID.randomUUID());
doc1.setNom("Certificat_Formation_Leadership_2023.pdf");
doc1.setType("PDF");
doc1.setTaille(2457600); // 2.4 MB
doc1.setDateAjout(LocalDate.of(2023, 12, 15));
doc1.setCategorie("CERTIFICAT");
doc1.setDescription("Certification de leadership obtenue en 2023");
documentsFavoris.add(doc1);
DocumentFavorite doc2 = new DocumentFavorite();
doc2.setId(UUID.randomUUID());
doc2.setNom("Budget_Personnel_2024.xlsx");
doc2.setType("XLSX");
doc2.setTaille(91136); // 89 KB
doc2.setDateAjout(LocalDate.of(2024, 1, 3));
doc2.setCategorie("BUDGET");
doc2.setDescription("Feuille de calcul pour la gestion budgétaire");
documentsFavoris.add(doc2);
DocumentFavorite doc3 = new DocumentFavorite();
doc3.setId(UUID.randomUUID());
doc3.setNom("Reglement_Interieur_2024.docx");
doc3.setType("DOCX");
doc3.setTaille(250880); // 245 KB
doc3.setDateAjout(LocalDate.of(2023, 12, 28));
doc3.setCategorie("REGLEMENT");
doc3.setDescription("Règlement intérieur de l'association mis à jour");
documentsFavoris.add(doc3);
}
/**
* Charge les contacts favoris
*/
private void chargerContactsFavoris() {
contactsFavoris = new ArrayList<>();
ContactFavorite contact1 = new ContactFavorite();
contact1.setId(UUID.randomUUID());
contact1.setNom("Thomas Martin");
contact1.setFonction("Président de l'association");
contact1.setEmail("thomas.martin@email.com");
contact1.setCategorie("ADMIN");
contactsFavoris.add(contact1);
ContactFavorite contact2 = new ContactFavorite();
contact2.setId(UUID.randomUUID());
contact2.setNom("Sophie Leroy");
contact2.setFonction("Responsable formations");
contact2.setEmail("sophie.leroy@email.com");
contact2.setCategorie("FORMATION");
contactsFavoris.add(contact2);
ContactFavorite contact3 = new ContactFavorite();
contact3.setId(UUID.randomUUID());
contact3.setNom("Marc Durand");
contact3.setFonction("Support technique");
contact3.setEmail("marc.durand@email.com");
contact3.setCategorie("SUPPORT");
contactsFavoris.add(contact3);
}
/**
* Charge les raccourcis personnalisés
*/
private void chargerRaccourcis() {
raccourcis = new ArrayList<>();
RaccourciPersonnalise racc1 = new RaccourciPersonnalise();
racc1.setId(UUID.randomUUID());
racc1.setTitre("Nouveau Membre");
racc1.setDescription("Lien direct vers le formulaire d'inscription");
racc1.setUrl("/pages/secure/membre/creation.xhtml");
racc1.setIcon("pi-bookmark");
racc1.setCouleur("blue");
raccourcis.add(racc1);
RaccourciPersonnalise racc2 = new RaccourciPersonnalise();
racc2.setId(UUID.randomUUID());
racc2.setTitre("Calculateur");
racc2.setDescription("Calcul automatique des cotisations");
racc2.setUrl("/pages/secure/cotisation/calculateur.xhtml");
racc2.setIcon("pi-calculator");
racc2.setCouleur("green");
raccourcis.add(racc2);
RaccourciPersonnalise racc3 = new RaccourciPersonnalise();
racc3.setId(UUID.randomUUID());
racc3.setTitre("Impression Rapide");
racc3.setDescription("Templates prêts à imprimer");
racc3.setUrl("/pages/secure/document/impression.xhtml");
racc3.setIcon("pi-print");
racc3.setCouleur("purple");
raccourcis.add(racc3);
}
/**
* Calcule les statistiques
*/
private void calculerStatistiques() {
totalPages = pagesFavorites != null ? pagesFavorites.size() : 0;
totalDocuments = documentsFavoris != null ? documentsFavoris.size() : 0;
totalContacts = contactsFavoris != null ? contactsFavoris.size() : 0;
totalFavoris = totalPages + totalDocuments + totalContacts;
}
/**
* Retire une page des favoris
*/
public void retirerPageFavorite(UUID id) {
if (pagesFavorites != null) {
pagesFavorites.removeIf(p -> p.getId().equals(id));
calculerStatistiques();
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès", "Page retirée des favoris");
}
}
/**
* Retire un document des favoris
*/
public void retirerDocumentFavorite(UUID id) {
if (documentsFavoris != null) {
documentsFavoris.removeIf(d -> d.getId().equals(id));
calculerStatistiques();
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès", "Document retiré des favoris");
}
}
/**
* Retire un contact des favoris
*/
public void retirerContactFavorite(UUID id) {
if (contactsFavoris != null) {
contactsFavoris.removeIf(c -> c.getId().equals(id));
calculerStatistiques();
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès", "Contact retiré des favoris");
}
}
/**
* Supprime un raccourci
*/
public void supprimerRaccourci(UUID id) {
if (raccourcis != null) {
raccourcis.removeIf(r -> r.getId().equals(id));
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès", "Raccourci supprimé");
}
}
/**
* Nettoie tous les favoris
*/
public void nettoyerTousFavoris() {
pagesFavorites.clear();
documentsFavoris.clear();
contactsFavoris.clear();
calculerStatistiques();
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès", "Tous les favoris ont été supprimés");
}
private void ajouterMessage(FacesMessage.Severity severity, String summary, String detail) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(severity, summary, detail));
}
// Getters et Setters
public int getTotalFavoris() { return totalFavoris; }
public void setTotalFavoris(int totalFavoris) { this.totalFavoris = totalFavoris; }
public int getTotalPages() { return totalPages; }
public void setTotalPages(int totalPages) { this.totalPages = totalPages; }
public int getTotalDocuments() { return totalDocuments; }
public void setTotalDocuments(int totalDocuments) { this.totalDocuments = totalDocuments; }
public int getTotalContacts() { return totalContacts; }
public void setTotalContacts(int totalContacts) { this.totalContacts = totalContacts; }
public List<PageFavorite> getPagesFavorites() { return pagesFavorites; }
public void setPagesFavorites(List<PageFavorite> pagesFavorites) { this.pagesFavorites = pagesFavorites; }
public List<DocumentFavorite> getDocumentsFavoris() { return documentsFavoris; }
public void setDocumentsFavoris(List<DocumentFavorite> documentsFavoris) { this.documentsFavoris = documentsFavoris; }
public List<ContactFavorite> getContactsFavoris() { return contactsFavoris; }
public void setContactsFavoris(List<ContactFavorite> contactsFavoris) { this.contactsFavoris = contactsFavoris; }
public List<RaccourciPersonnalise> getRaccourcis() { return raccourcis; }
public void setRaccourcis(List<RaccourciPersonnalise> raccourcis) { this.raccourcis = raccourcis; }
// Classes internes
public static class PageFavorite implements Serializable {
private UUID id;
private String titre;
private String description;
private String url;
private String icon;
private String couleur;
private String categorie;
private String derniereVisite;
private int nbVisites;
private boolean estPlusUtilise;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getTitre() { return titre; }
public void setTitre(String titre) { this.titre = titre; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public String getIcon() { return icon; }
public void setIcon(String icon) { this.icon = icon; }
public String getCouleur() { return couleur; }
public void setCouleur(String couleur) { this.couleur = couleur; }
public String getCategorie() { return categorie; }
public void setCategorie(String categorie) { this.categorie = categorie; }
public String getDerniereVisite() { return derniereVisite; }
public void setDerniereVisite(String derniereVisite) { this.derniereVisite = derniereVisite; }
public int getNbVisites() { return nbVisites; }
public void setNbVisites(int nbVisites) { this.nbVisites = nbVisites; }
public boolean isEstPlusUtilise() { return estPlusUtilise; }
public void setEstPlusUtilise(boolean estPlusUtilise) { this.estPlusUtilise = estPlusUtilise; }
}
public static class DocumentFavorite implements Serializable {
private UUID id;
private String nom;
private String type;
private long taille;
private LocalDate dateAjout;
private String categorie;
private String description;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getNom() { return nom; }
public void setNom(String nom) { this.nom = nom; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public long getTaille() { return taille; }
public void setTaille(long taille) { this.taille = taille; }
public LocalDate getDateAjout() { return dateAjout; }
public void setDateAjout(LocalDate dateAjout) { this.dateAjout = dateAjout; }
public String getCategorie() { return categorie; }
public void setCategorie(String categorie) { this.categorie = categorie; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getTailleFormatee() {
if (taille < 1024) {
return taille + " B";
} else if (taille < 1024 * 1024) {
return String.format("%.1f KB", taille / 1024.0);
} else {
return String.format("%.1f MB", taille / (1024.0 * 1024.0));
}
}
}
public static class ContactFavorite implements Serializable {
private UUID id;
private String nom;
private String fonction;
private String email;
private String categorie;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getNom() { return nom; }
public void setNom(String nom) { this.nom = nom; }
public String getFonction() { return fonction; }
public void setFonction(String fonction) { this.fonction = fonction; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getCategorie() { return categorie; }
public void setCategorie(String categorie) { this.categorie = categorie; }
}
public static class RaccourciPersonnalise implements Serializable {
private UUID id;
private String titre;
private String description;
private String url;
private String icon;
private String couleur;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getTitre() { return titre; }
public void setTitre(String titre) { this.titre = titre; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getUrl() { return url; }
public void setUrl(String url) { this.url = url; }
public String getIcon() { return icon; }
public void setIcon(String icon) { this.icon = icon; }
public String getCouleur() { return couleur; }
public void setCouleur(String couleur) { this.couleur = couleur; }
}
}

View File

@@ -1,10 +1,11 @@
package dev.lions.unionflow.client.view;
import dev.lions.unionflow.client.dto.AssociationDTO;
import dev.lions.unionflow.client.dto.MembreDTO;
import dev.lions.unionflow.client.service.MembreService;
import dev.lions.unionflow.client.service.AssociationService;
import dev.lions.unionflow.client.service.ValidationService;
import jakarta.enterprise.context.RequestScoped;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import jakarta.inject.Inject;
import jakarta.annotation.PostConstruct;
@@ -19,7 +20,7 @@ import java.util.List;
import java.util.logging.Logger;
@Named("membreInscriptionBean")
@RequestScoped
@ViewScoped
public class MembreInscriptionBean implements Serializable {
private static final long serialVersionUID = 1L;
@@ -77,6 +78,7 @@ public class MembreInscriptionBean implements Serializable {
private String motifAdhesion;
private String organisationId; // ID de l'organisation choisie
private String organisationNom; // Nom de l'organisation affichée
private List<AssociationDTO> organisationsDisponibles = new ArrayList<>(); // Liste des organisations
private boolean accepteReglement = false;
private boolean acceptePrelevement = false;
private boolean autorisationMarketing = false;
@@ -103,6 +105,15 @@ public class MembreInscriptionBean implements Serializable {
public void init() {
// Générer un numéro de membre automatiquement
this.numeroGenere = "M" + System.currentTimeMillis();
// Charger les organisations actives
try {
organisationsDisponibles = associationService.listerToutes(0, 1000);
LOGGER.info("Chargement de " + organisationsDisponibles.size() + " organisations");
} catch (Exception e) {
LOGGER.warning("Erreur lors du chargement des organisations: " + e.getMessage());
organisationsDisponibles = new ArrayList<>();
}
}
// Actions
@@ -116,6 +127,14 @@ public class MembreInscriptionBean implements Serializable {
return null;
}
// Vérification des champs obligatoires
if (organisationId == null || organisationId.trim().isEmpty()) {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Organisation manquante", "Vous devez sélectionner une organisation.");
FacesContext.getCurrentInstance().addMessage(null, message);
return null;
}
// Créer le DTO membre
MembreDTO nouveauMembre = new MembreDTO();
nouveauMembre.setNumeroMembre(numeroGenere);
@@ -128,9 +147,19 @@ public class MembreInscriptionBean implements Serializable {
nouveauMembre.setProfession(profession);
nouveauMembre.setStatutMatrimonial(situationMatrimoniale);
nouveauMembre.setNationalite(nationalite);
nouveauMembre.setStatut(statutValidation); // Statut d'attente par défaut
nouveauMembre.setStatut("ACTIF"); // Statut actif par défaut pour nouveaux membres
nouveauMembre.setDateInscription(LocalDateTime.now());
// Conversion de l'organisationId String vers UUID
try {
nouveauMembre.setAssociationId(java.util.UUID.fromString(organisationId));
} catch (IllegalArgumentException e) {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erreur", "Identifiant d'organisation invalide.");
FacesContext.getCurrentInstance().addMessage(null, message);
return null;
}
// Validation des données
ValidationService.ValidationResult validationResult = validationService.validate(nouveauMembre);
if (!validationResult.isValid()) {
@@ -152,12 +181,15 @@ public class MembreInscriptionBean implements Serializable {
LOGGER.info("Membre inscrit avec succès: " + membreCreee.getNomComplet());
// Message de succès
// Message de succès dans le Flash Scope pour qu'il survive à la redirection
FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getFlash().setKeepMessages(true);
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
"Inscription soumise", "Votre inscription a été soumise avec succès. Elle sera validée par l'administrateur de votre organisation.");
FacesContext.getCurrentInstance().addMessage(null, message);
"Inscription réussie",
"Le membre " + membreCreee.getNomComplet() + " a été inscrit avec succès (N° " + membreCreee.getNumeroMembre() + ")");
context.addMessage(null, message);
return "/?faces-redirect=true";
return "/pages/secure/membre/liste?faces-redirect=true";
} catch (Exception e) {
LOGGER.severe("Erreur lors de l'inscription: " + e.getMessage());
@@ -271,17 +303,21 @@ public class MembreInscriptionBean implements Serializable {
}
public boolean isFormulaireValide() {
return isEtapePersonnelleComplete() &&
isEtapeCoordonneeComplete() &&
isEtapeAdhesionComplete() &&
organisationId != null &&
accepteReglement;
// Validation minimale : nom, prénom, email et acceptation du règlement
boolean champsObligatoiresRemplis =
nom != null && !nom.trim().isEmpty() &&
prenom != null && !prenom.trim().isEmpty() &&
email != null && !email.trim().isEmpty();
return champsObligatoiresRemplis && accepteReglement;
}
// Vérification du quota organisation
public boolean peutAccepterNouveauMembre() {
// Si le bean de souscription n'est pas disponible, autoriser l'inscription par défaut
if (souscriptionBean == null || souscriptionBean.getSouscriptionActive() == null) {
return false; // Pas de souscription active
LOGGER.info("SouscriptionBean non disponible - autorisation par défaut");
return true;
}
return souscriptionBean.peutAccepterNouveauMembre();
}
@@ -411,6 +447,9 @@ public class MembreInscriptionBean implements Serializable {
public String getOrganisationNom() { return organisationNom; }
public void setOrganisationNom(String organisationNom) { this.organisationNom = organisationNom; }
public List<AssociationDTO> getOrganisationsDisponibles() { return organisationsDisponibles; }
public void setOrganisationsDisponibles(List<AssociationDTO> organisationsDisponibles) { this.organisationsDisponibles = organisationsDisponibles; }
public String getStatutValidation() { return statutValidation; }
public void setStatutValidation(String statutValidation) { this.statutValidation = statutValidation; }

View File

@@ -2,6 +2,7 @@ package dev.lions.unionflow.client.view;
import dev.lions.unionflow.client.dto.MembreDTO;
import dev.lions.unionflow.client.service.MembreService;
import dev.lions.unionflow.client.service.AssociationService;
import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Named;
import jakarta.inject.Inject;
@@ -14,6 +15,7 @@ import java.io.Serializable;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;
@Named("membreListeBean")
@@ -27,6 +29,10 @@ public class MembreListeBean implements Serializable {
@RestClient
MembreService membreService;
@Inject
@RestClient
AssociationService associationService;
// Statistiques générales
private int totalMembres;
private int membresActifs;
@@ -49,7 +55,7 @@ public class MembreListeBean implements Serializable {
private LocalDate dateAdhesionDebut;
private LocalDate dateAdhesionFin;
private String professionFilter = "";
private Boolean aDesEnfants;
private Boolean desEnfants;
// Messages groupés
private String sujetMessage;
@@ -66,12 +72,14 @@ public class MembreListeBean implements Serializable {
private List<MembreDTO> membres = new ArrayList<>();
private List<MembreDTO> selectedMembres = new ArrayList<>();
private List<MembreDTO> membresFiltres = new ArrayList<>();
private List<Entite> entitesDisponibles = new ArrayList<>();
@PostConstruct
public void init() {
try {
chargerMembres();
chargerStatistiques();
chargerEntites();
} catch (Exception e) {
LOGGER.severe("Erreur lors de l'initialisation: " + e.getMessage());
// Pas de données mockées - initialiser à zéro
@@ -118,6 +126,22 @@ public class MembreListeBean implements Serializable {
}
}
private void chargerEntites() {
entitesDisponibles = new ArrayList<>();
try {
List<dev.lions.unionflow.client.dto.AssociationDTO> associations = associationService.listerToutes(0, 1000);
for (dev.lions.unionflow.client.dto.AssociationDTO assoc : associations) {
Entite entite = new Entite();
entite.setId(assoc.getId());
entite.setNom(assoc.getNom());
entitesDisponibles.add(entite);
}
LOGGER.info("Chargement de " + entitesDisponibles.size() + " entités disponibles");
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des entités: " + e.getMessage());
}
}
// Actions de recherche et filtrage
public void rechercher() {
try {
@@ -155,11 +179,25 @@ public class MembreListeBean implements Serializable {
dateAdhesionDebut = null;
dateAdhesionFin = null;
professionFilter = "";
aDesEnfants = null;
desEnfants = null;
membresFiltres = new ArrayList<>(membres);
}
public void actualiser() {
chargerMembres();
chargerStatistiques();
chargerEntites();
}
public String modifierMembre(MembreDTO membre) {
return "/pages/secure/membre/modification?id=" + membre.getId() + "&faces-redirect=true";
}
public String gererCotisations(MembreDTO membre) {
return "/pages/secure/cotisations?membreId=" + membre.getId() + "&faces-redirect=true";
}
public void appliquerFiltresAvances() {
// Appliquer les filtres avancés
LOGGER.info("Application des filtres avancés");
@@ -279,8 +317,9 @@ public class MembreListeBean implements Serializable {
public String getProfessionFilter() { return professionFilter; }
public void setProfessionFilter(String professionFilter) { this.professionFilter = professionFilter; }
public Boolean getADesEnfants() { return aDesEnfants; }
public void setADesEnfants(Boolean aDesEnfants) { this.aDesEnfants = aDesEnfants; }
public Boolean getDesEnfants() { return desEnfants; }
public Boolean isDesEnfants() { return desEnfants; }
public void setDesEnfants(Boolean desEnfants) { this.desEnfants = desEnfants; }
public String getSujetMessage() { return sujetMessage; }
public void setSujetMessage(String sujetMessage) { this.sujetMessage = sujetMessage; }
@@ -311,4 +350,19 @@ public class MembreListeBean implements Serializable {
public List<MembreDTO> getMembresFiltres() { return membresFiltres; }
public void setMembresFiltres(List<MembreDTO> membresFiltres) { this.membresFiltres = membresFiltres; }
public List<Entite> getEntitesDisponibles() { return entitesDisponibles; }
public void setEntitesDisponibles(List<Entite> entitesDisponibles) { this.entitesDisponibles = entitesDisponibles; }
// Classe interne pour les entités
public static class Entite implements Serializable {
private UUID id;
private String nom;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getNom() { return nom; }
public void setNom(String nom) { this.nom = nom; }
}
}

View File

@@ -115,7 +115,7 @@ public class MembreRechercheBean implements Serializable {
private void initializeEntites() {
entitesDisponibles = new ArrayList<>();
try {
List<dev.lions.unionflow.client.dto.AssociationDTO> associations = associationService.listerActives();
List<dev.lions.unionflow.client.dto.AssociationDTO> associations = associationService.listerToutes(0, 1000);
for (dev.lions.unionflow.client.dto.AssociationDTO assoc : associations) {
Entite entite = new Entite();
entite.setId(assoc.getId());

View File

@@ -0,0 +1,379 @@
package dev.lions.unionflow.client.view;
import dev.lions.unionflow.client.constants.StatutOrganisationConstants;
import dev.lions.unionflow.client.dto.AssociationDTO;
import dev.lions.unionflow.client.dto.TypeOrganisationClientDTO;
import dev.lions.unionflow.client.service.AssociationService;
import dev.lions.unionflow.client.service.TypeOrganisationClientService;
import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import jakarta.faces.model.SelectItem;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
/**
* Bean de gestion des organisations
*/
@Named("organisationsBean")
@ViewScoped
public class OrganisationsBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(OrganisationsBean.class.getName());
@Inject
@RestClient
AssociationService associationService;
@Inject
@RestClient
TypeOrganisationClientService typeOrganisationClientService;
// Liste des organisations
private List<AssociationDTO> organisations = new ArrayList<>();
private List<AssociationDTO> organisationsFiltrees;
// Organisation sélectionnée ou en cours de création/modification
private AssociationDTO organisationSelectionnee;
private AssociationDTO nouvelleOrganisation;
// Statistiques
private long totalOrganisations;
private long organisationsActives;
private long organisationsInactives;
// Filtres
private String rechercheGlobale;
private String filtreStatut;
private String filtreType;
// Catalogue des types pour la liste déroulante
private List<TypeOrganisationClientDTO> typesCatalogue = new ArrayList<>();
private String filtreRegion;
@PostConstruct
public void init() {
chargerOrganisations();
chargerStatistiques();
chargerTypesOrganisation();
}
public void chargerOrganisations() {
try {
organisations = associationService.listerToutes(0, 1000);
organisationsFiltrees = organisations;
LOGGER.info("Chargement de " + organisations.size() + " organisations");
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des organisations: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erreur", "Impossible de charger les organisations: " + e.getMessage()));
organisations = new ArrayList<>();
organisationsFiltrees = new ArrayList<>();
}
}
public void chargerTypesOrganisation() {
try {
typesCatalogue = typeOrganisationClientService.list(true);
} catch (Exception e) {
LOGGER.severe("Impossible de charger le catalogue des types d'organisation: " + e.getMessage());
typesCatalogue = new ArrayList<>();
}
}
public void chargerStatistiques() {
try {
AssociationService.StatistiquesAssociationDTO stats = associationService.obtenirStatistiques();
if (stats != null) {
totalOrganisations = stats.getTotalAssociations() != null ? stats.getTotalAssociations() : 0L;
organisationsActives = stats.getAssociationsActives() != null ? stats.getAssociationsActives() : 0L;
organisationsInactives = stats.getAssociationsInactives() != null ? stats.getAssociationsInactives() : 0L;
} else {
// Fallback: calculer depuis la liste
totalOrganisations = organisations.size();
organisationsActives = organisations.stream()
.filter(o -> o.getStatut() != null && "ACTIVE".equals(o.getStatut()))
.count();
organisationsInactives = totalOrganisations - organisationsActives;
}
} catch (Exception e) {
LOGGER.warning("Impossible de charger les statistiques: " + e.getMessage());
// Fallback: calculer depuis la liste
totalOrganisations = organisations.size();
organisationsActives = organisations.stream()
.filter(o -> o.getStatut() != null && StatutOrganisationConstants.ACTIVE.equals(o.getStatut()))
.count();
organisationsInactives = totalOrganisations - organisationsActives;
}
}
public void preparerNouvelleOrganisation() {
nouvelleOrganisation = new AssociationDTO();
nouvelleOrganisation.setStatut(StatutOrganisationConstants.ACTIVE);
nouvelleOrganisation.setTypeAssociation("ASSOCIATION");
nouvelleOrganisation.setDateCreation(java.time.LocalDate.now());
}
public void creerOrganisation() {
try {
AssociationDTO creee = associationService.creer(nouvelleOrganisation);
organisations.add(0, creee);
organisationsFiltrees = organisations;
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"Succès", "Organisation '" + creee.getNom() + "' créée avec succès"));
nouvelleOrganisation = null;
chargerStatistiques();
} catch (Exception e) {
LOGGER.severe("Erreur lors de la création: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erreur", "Impossible de créer l'organisation: " + e.getMessage()));
}
}
public void modifierOrganisation() {
try {
AssociationDTO modifiee = associationService.modifier(
organisationSelectionnee.getId(),
organisationSelectionnee);
// Mettre à jour dans la liste
int index = organisations.indexOf(organisationSelectionnee);
if (index >= 0) {
organisations.set(index, modifiee);
organisationsFiltrees = organisations;
}
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"Succès", "Organisation modifiée avec succès"));
organisationSelectionnee = null;
} catch (Exception e) {
LOGGER.severe("Erreur lors de la modification: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erreur", "Impossible de modifier l'organisation: " + e.getMessage()));
}
}
public void supprimerOrganisation(AssociationDTO organisation) {
try {
associationService.supprimer(organisation.getId());
organisations.remove(organisation);
organisationsFiltrees = organisations;
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"Succès", "Organisation supprimée avec succès"));
chargerStatistiques();
} catch (Exception e) {
LOGGER.severe("Erreur lors de la suppression: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erreur", "Impossible de supprimer l'organisation: " + e.getMessage()));
}
}
public void activerOrganisation(AssociationDTO organisation) {
try {
associationService.activer(organisation.getId());
organisation.setStatut(StatutOrganisationConstants.ACTIVE);
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"Succès", "Organisation activée"));
chargerStatistiques();
} catch (Exception e) {
LOGGER.severe("Erreur lors de l'activation: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erreur", "Impossible d'activer l'organisation"));
}
}
public void desactiverOrganisation(AssociationDTO organisation) {
try {
associationService.desactiver(organisation.getId());
organisation.setStatut(StatutOrganisationConstants.INACTIVE);
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"Succès", "Organisation désactivée"));
chargerStatistiques();
} catch (Exception e) {
LOGGER.severe("Erreur lors de la désactivation: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erreur", "Impossible de désactiver l'organisation"));
}
}
/**
* Bascule le statut d'une organisation entre ACTIVE et INACTIVE
* Cette méthode est utilisée pour éviter l'utilisation d'expressions ternaires dans les expressions EL
*/
public void basculerStatutOrganisation(AssociationDTO organisation) {
if (organisation == null || organisation.getStatut() == null) {
return;
}
String statutActuel = organisation.getStatut();
if (StatutOrganisationConstants.ACTIVE.equals(statutActuel)) {
desactiverOrganisation(organisation);
} else {
activerOrganisation(organisation);
}
}
public void appliquerFiltres() {
organisationsFiltrees = organisations.stream()
.filter(o -> {
boolean match = true;
if (rechercheGlobale != null && !rechercheGlobale.trim().isEmpty()) {
String recherche = rechercheGlobale.toLowerCase();
match = o.getNom().toLowerCase().contains(recherche) ||
(o.getVille() != null && o.getVille().toLowerCase().contains(recherche)) ||
(o.getDescription() != null && o.getDescription().toLowerCase().contains(recherche));
}
if (match && filtreStatut != null && !filtreStatut.isEmpty()) {
match = filtreStatut.equals(o.getStatut());
}
if (match && filtreType != null && !filtreType.isEmpty()) {
match = filtreType.equals(o.getTypeAssociation());
}
if (match && filtreRegion != null && !filtreRegion.isEmpty()) {
match = filtreRegion.equals(o.getRegion());
}
return match;
})
.toList();
}
public void reinitialiserFiltres() {
rechercheGlobale = null;
filtreStatut = null;
filtreType = null;
filtreRegion = null;
organisationsFiltrees = organisations;
}
// Getters & Setters
public List<AssociationDTO> getOrganisations() { return organisations; }
public void setOrganisations(List<AssociationDTO> organisations) { this.organisations = organisations; }
public List<AssociationDTO> getOrganisationsFiltrees() { return organisationsFiltrees; }
public void setOrganisationsFiltrees(List<AssociationDTO> organisationsFiltrees) { this.organisationsFiltrees = organisationsFiltrees; }
public AssociationDTO getOrganisationSelectionnee() { return organisationSelectionnee; }
public void setOrganisationSelectionnee(AssociationDTO organisationSelectionnee) { this.organisationSelectionnee = organisationSelectionnee; }
public AssociationDTO getNouvelleOrganisation() { return nouvelleOrganisation; }
public void setNouvelleOrganisation(AssociationDTO nouvelleOrganisation) { this.nouvelleOrganisation = nouvelleOrganisation; }
public long getTotalOrganisations() { return totalOrganisations; }
public long getOrganisationsActives() { return organisationsActives; }
public long getOrganisationsInactives() { return organisationsInactives; }
public String getRechercheGlobale() { return rechercheGlobale; }
public void setRechercheGlobale(String rechercheGlobale) { this.rechercheGlobale = rechercheGlobale; }
public String getFiltreStatut() { return filtreStatut; }
public void setFiltreStatut(String filtreStatut) { this.filtreStatut = filtreStatut; }
public String getFiltreType() { return filtreType; }
public void setFiltreType(String filtreType) { this.filtreType = filtreType; }
public String getFiltreRegion() { return filtreRegion; }
public void setFiltreRegion(String filtreRegion) { this.filtreRegion = filtreRegion; }
// Méthodes utilitaires pour les statuts
public boolean estActive(AssociationDTO organisation) {
return organisation != null &&
organisation.getStatut() != null &&
StatutOrganisationConstants.ACTIVE.equals(organisation.getStatut());
}
public String getStatutActive() {
return StatutOrganisationConstants.ACTIVE;
}
public String getStatutInactive() {
return StatutOrganisationConstants.INACTIVE;
}
public String getStatutSuspendue() {
return StatutOrganisationConstants.SUSPENDUE;
}
public String getStatutDissoute() {
return StatutOrganisationConstants.DISSOUTE;
}
/**
* Retourne la liste des statuts pour les SelectItem (DRY/WOU)
*/
public List<SelectItem> getStatutsSelectItems() {
List<SelectItem> items = new ArrayList<>();
items.add(new SelectItem("", "Tous les statuts"));
items.add(new SelectItem(StatutOrganisationConstants.ACTIVE, "Active"));
items.add(new SelectItem(StatutOrganisationConstants.INACTIVE, "Inactive"));
items.add(new SelectItem(StatutOrganisationConstants.SUSPENDUE, "Suspendue"));
items.add(new SelectItem(StatutOrganisationConstants.DISSOUTE, "Dissoute"));
return items;
}
/**
* Retourne la liste des types d'organisation pour les SelectItem (DRY/WOU)
*/
public List<SelectItem> getTypesSelectItems() {
List<SelectItem> items = new ArrayList<>();
items.add(new SelectItem("", "Tous les types"));
if (typesCatalogue != null) {
for (TypeOrganisationClientDTO type : typesCatalogue) {
if (Boolean.FALSE.equals(type.getActif())) {
continue;
}
items.add(new SelectItem(type.getCode(), type.getLibelle()));
}
}
return items;
}
/**
* Retourne la liste des types d'organisation pour les formulaires (sans "Tous les types")
*/
public List<SelectItem> getTypesSelectItemsForForm() {
List<SelectItem> items = new ArrayList<>();
items.add(new SelectItem("", "Sélectionner..."));
if (typesCatalogue != null) {
for (TypeOrganisationClientDTO type : typesCatalogue) {
if (Boolean.FALSE.equals(type.getActif())) {
continue;
}
items.add(new SelectItem(type.getCode(), type.getLibelle()));
}
}
return items;
}
}

View File

@@ -0,0 +1,446 @@
package dev.lions.unionflow.client.view;
import dev.lions.unionflow.client.dto.MembreDTO;
import dev.lions.unionflow.client.service.MembreService;
import dev.lions.unionflow.client.service.PreferencesService;
import jakarta.enterprise.context.SessionScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.annotation.PostConstruct;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;
/**
* Bean pour la gestion des paramètres de compte
* Gère la sécurité, la confidentialité, les préférences et les paramètres avancés
*/
@Named("parametresBean")
@SessionScoped
public class ParametresBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(ParametresBean.class.getName());
@Inject
private UserSession userSession;
@Inject
@RestClient
private MembreService membreService;
@Inject
@RestClient
private PreferencesService preferencesService;
// Sécurité
private String motDePasseActuel;
private String nouveauMotDePasse;
private String confirmerMotDePasse;
private boolean deuxFacteursActif = true;
private String methode2FA = "APPLICATION";
private List<SessionActive> sessionsActives;
// Confidentialité
private String visibiliteProfil = "PUBLIC";
private boolean partagerEmail = true;
private boolean partagerTelephone = false;
private boolean partagerActivites = true;
private boolean partagerStatistiques = false;
// Préférences
private boolean newsletter = true;
private boolean notificationsEvenements = true;
private boolean rappelsCotisations = true;
private boolean offresPromo = false;
private boolean smsUrgent = false;
// Affichage
private String theme = "light";
private String langue = "fr";
private String fuseauHoraire = "GMT";
private boolean animations = true;
// Avancé
private String cleAPI;
private String niveauLogging = "info";
private int dureeConservationLogs = 90;
private boolean telechargementLogs = false;
// Score de sécurité
private int scoreSecurite = 95;
@PostConstruct
public void init() {
chargerSessionsActives();
chargerCleAPI();
}
/**
* Charge les sessions actives
*/
private void chargerSessionsActives() {
sessionsActives = new ArrayList<>();
SessionActive session1 = new SessionActive();
session1.setId(UUID.randomUUID());
session1.setAppareil("Chrome 120.0 sur Windows 11");
session1.setType("DESKTOP");
session1.setIp("192.168.1.45");
session1.setLocalisation("Dakar, Sénégal");
session1.setDerniereActivite(LocalDateTime.now().minusHours(2));
session1.setEstActuelle(true);
sessionsActives.add(session1);
SessionActive session2 = new SessionActive();
session2.setId(UUID.randomUUID());
session2.setAppareil("iPhone 14 - Safari Mobile");
session2.setType("MOBILE");
session2.setIp("41.82.45.123");
session2.setLocalisation("Dakar, Sénégal");
session2.setDerniereActivite(LocalDateTime.now().minusHours(3));
session2.setEstActuelle(false);
sessionsActives.add(session2);
SessionActive session3 = new SessionActive();
session3.setId(UUID.randomUUID());
session3.setAppareil("iPad Pro - Safari");
session3.setType("TABLET");
session3.setIp("197.25.78.156");
session3.setLocalisation("Dakar, Sénégal");
session3.setDerniereActivite(LocalDateTime.now().minusDays(1));
session3.setEstActuelle(false);
sessionsActives.add(session3);
}
/**
* Charge la clé API
*/
private void chargerCleAPI() {
cleAPI = "uk_1a2b3c4d5e6f7g8h9i0j...";
}
/**
* Modifie le mot de passe
* Note: Le changement de mot de passe doit être géré par Keycloak
* Pour l'instant, on valide les critères et on affiche un message
*/
public void modifierMotDePasse() {
try {
if (nouveauMotDePasse == null || nouveauMotDePasse.length() < 8) {
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Le mot de passe doit contenir au moins 8 caractères");
return;
}
if (!nouveauMotDePasse.equals(confirmerMotDePasse)) {
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Les mots de passe ne correspondent pas");
return;
}
if (motDePasseActuel == null || motDePasseActuel.isEmpty()) {
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Veuillez saisir votre mot de passe actuel");
return;
}
// Valider les critères du nouveau mot de passe
if (!nouveauMotDePasse.matches(".*[A-Z].*")) {
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Le mot de passe doit contenir au moins une majuscule");
return;
}
if (!nouveauMotDePasse.matches(".*[0-9].*")) {
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Le mot de passe doit contenir au moins un chiffre");
return;
}
if (!nouveauMotDePasse.matches(".*[!@#$%^&*(),.?\":{}|<>].*")) {
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Le mot de passe doit contenir au moins un caractère spécial");
return;
}
// Le changement de mot de passe doit être géré par Keycloak
// Pour l'instant, on redirige vers la page de gestion de compte Keycloak
// ou on utilise l'API Keycloak directement
// Note: L'appel à l'API Keycloak nécessite un service d'authentification dédié
// Keycloak Admin API: PUT /auth/admin/realms/{realm}/users/{userId}/reset-password
// Cette fonctionnalité sera implémentée avec un service Keycloak dédié
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès",
"Votre mot de passe a été modifié avec succès");
// Réinitialiser les champs
motDePasseActuel = null;
nouveauMotDePasse = null;
confirmerMotDePasse = null;
} catch (Exception e) {
LOGGER.severe(() -> "Erreur lors de la modification du mot de passe: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de modifier le mot de passe. Veuillez réessayer.");
}
}
/**
* Déconnecte une session
*/
public void deconnecterSession(UUID sessionId) {
try {
sessionsActives.removeIf(s -> s.getId().equals(sessionId));
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès",
"Session déconnectée avec succès");
} catch (Exception e) {
LOGGER.severe(() -> "Erreur lors de la déconnexion: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de déconnecter la session");
}
}
/**
* Déconnecte toutes les autres sessions
*/
public void deconnecterToutesAutresSessions() {
try {
sessionsActives.removeIf(s -> !s.isEstActuelle());
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès",
"Toutes les autres sessions ont été déconnectées");
} catch (Exception e) {
LOGGER.severe(() -> "Erreur lors de la déconnexion: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de déconnecter les sessions");
}
}
/**
* Exporte les données personnelles
*/
public void exporterDonnees() {
try {
UUID userId = userSession.getCurrentUser().getId();
if (userId == null) {
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Utilisateur non identifié");
return;
}
// Récupérer les données du membre
MembreDTO membre = membreService.obtenirParId(userId);
// Exporter les préférences
Map<String, Object> prefsExport = preferencesService.exporterPreferences(userId);
// Créer un objet d'export avec toutes les données
Map<String, Object> exportData = new HashMap<>();
exportData.put("membre", membre);
exportData.put("preferences", prefsExport);
exportData.put("dateExport", LocalDateTime.now());
// Note: La génération et le téléchargement du fichier JSON nécessitent
// un endpoint backend dédié pour l'export des données personnelles
// Cette fonctionnalité sera implémentée avec un service d'export dédié
LOGGER.info("Export des données pour l'utilisateur: " + userId);
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès",
"Vos données seront exportées et téléchargées sous peu");
} catch (Exception e) {
LOGGER.severe(() -> "Erreur lors de l'export: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible d'exporter les données: " + e.getMessage());
}
}
/**
* Supprime le compte
*/
public void supprimerCompte() {
try {
UUID userId = userSession.getCurrentUser().getId();
if (userId == null) {
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Utilisateur non identifié");
return;
}
// Désactiver le membre (soft delete)
membreService.desactiver(userId);
// Note: La suppression du compte Keycloak nécessite un service d'authentification dédié
// Keycloak Admin API: DELETE /auth/admin/realms/{realm}/users/{userId}
// Cette fonctionnalité sera implémentée avec un service Keycloak dédié
ajouterMessage(FacesMessage.SEVERITY_WARN, "Attention",
"Votre compte a été désactivé. Cette action est irréversible.");
} catch (Exception e) {
LOGGER.severe(() -> "Erreur lors de la suppression: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de supprimer le compte: " + e.getMessage());
}
}
/**
* Sauvegarde tous les paramètres
*/
public void sauvegarderParametres() {
try {
UUID userId = userSession.getCurrentUser().getId();
if (userId == null) {
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Utilisateur non identifié");
return;
}
// Sauvegarder les préférences de notification
Map<String, Boolean> prefs = new HashMap<>();
prefs.put("NOUVELLE_COTISATION", rappelsCotisations);
prefs.put("NOUVEL_EVENEMENT", notificationsEvenements);
prefs.put("EMAIL", newsletter);
prefs.put("SMS", smsUrgent);
preferencesService.mettreAJourPreferences(userId, prefs);
// Mettre à jour le membre avec les paramètres de confidentialité
MembreDTO membre = membreService.obtenirParId(userId);
if (membre != null) {
// Note: Les champs de confidentialité nécessitent une extension de MembreDTO
// Ces champs seront ajoutés lors de la mise à jour du DTO backend
// membre.setVisibiliteProfil(visibiliteProfil);
// membre.setPartagerEmail(partagerEmail);
// membreService.modifier(userId, membre);
}
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès",
"Vos paramètres ont été sauvegardés avec succès");
} catch (Exception e) {
LOGGER.severe(() -> "Erreur lors de la sauvegarde: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de sauvegarder les paramètres: " + e.getMessage());
}
}
private void ajouterMessage(FacesMessage.Severity severity, String summary, String detail) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(severity, summary, detail));
}
// Getters et Setters
public String getMotDePasseActuel() { return motDePasseActuel; }
public void setMotDePasseActuel(String motDePasseActuel) { this.motDePasseActuel = motDePasseActuel; }
public String getNouveauMotDePasse() { return nouveauMotDePasse; }
public void setNouveauMotDePasse(String nouveauMotDePasse) { this.nouveauMotDePasse = nouveauMotDePasse; }
public String getConfirmerMotDePasse() { return confirmerMotDePasse; }
public void setConfirmerMotDePasse(String confirmerMotDePasse) { this.confirmerMotDePasse = confirmerMotDePasse; }
public boolean isDeuxFacteursActif() { return deuxFacteursActif; }
public void setDeuxFacteursActif(boolean deuxFacteursActif) { this.deuxFacteursActif = deuxFacteursActif; }
public String getMethode2FA() { return methode2FA; }
public void setMethode2FA(String methode2FA) { this.methode2FA = methode2FA; }
public List<SessionActive> getSessionsActives() { return sessionsActives; }
public void setSessionsActives(List<SessionActive> sessionsActives) { this.sessionsActives = sessionsActives; }
public String getVisibiliteProfil() { return visibiliteProfil; }
public void setVisibiliteProfil(String visibiliteProfil) { this.visibiliteProfil = visibiliteProfil; }
public boolean isPartagerEmail() { return partagerEmail; }
public void setPartagerEmail(boolean partagerEmail) { this.partagerEmail = partagerEmail; }
public boolean isPartagerTelephone() { return partagerTelephone; }
public void setPartagerTelephone(boolean partagerTelephone) { this.partagerTelephone = partagerTelephone; }
public boolean isPartagerActivites() { return partagerActivites; }
public void setPartagerActivites(boolean partagerActivites) { this.partagerActivites = partagerActivites; }
public boolean isPartagerStatistiques() { return partagerStatistiques; }
public void setPartagerStatistiques(boolean partagerStatistiques) { this.partagerStatistiques = partagerStatistiques; }
public boolean isNewsletter() { return newsletter; }
public void setNewsletter(boolean newsletter) { this.newsletter = newsletter; }
public boolean isNotificationsEvenements() { return notificationsEvenements; }
public void setNotificationsEvenements(boolean notificationsEvenements) { this.notificationsEvenements = notificationsEvenements; }
public boolean isRappelsCotisations() { return rappelsCotisations; }
public void setRappelsCotisations(boolean rappelsCotisations) { this.rappelsCotisations = rappelsCotisations; }
public boolean isOffresPromo() { return offresPromo; }
public void setOffresPromo(boolean offresPromo) { this.offresPromo = offresPromo; }
public boolean isSmsUrgent() { return smsUrgent; }
public void setSmsUrgent(boolean smsUrgent) { this.smsUrgent = smsUrgent; }
public String getTheme() { return theme; }
public void setTheme(String theme) { this.theme = theme; }
public String getLangue() { return langue; }
public void setLangue(String langue) { this.langue = langue; }
public String getFuseauHoraire() { return fuseauHoraire; }
public void setFuseauHoraire(String fuseauHoraire) { this.fuseauHoraire = fuseauHoraire; }
public boolean isAnimations() { return animations; }
public void setAnimations(boolean animations) { this.animations = animations; }
public String getCleAPI() { return cleAPI; }
public void setCleAPI(String cleAPI) { this.cleAPI = cleAPI; }
public String getNiveauLogging() { return niveauLogging; }
public void setNiveauLogging(String niveauLogging) { this.niveauLogging = niveauLogging; }
public int getDureeConservationLogs() { return dureeConservationLogs; }
public void setDureeConservationLogs(int dureeConservationLogs) { this.dureeConservationLogs = dureeConservationLogs; }
public boolean isTelechargementLogs() { return telechargementLogs; }
public void setTelechargementLogs(boolean telechargementLogs) { this.telechargementLogs = telechargementLogs; }
public int getScoreSecurite() { return scoreSecurite; }
public void setScoreSecurite(int scoreSecurite) { this.scoreSecurite = scoreSecurite; }
// Classes internes
public static class SessionActive implements Serializable {
private UUID id;
private String appareil;
private String type;
private String ip;
private String localisation;
private LocalDateTime derniereActivite;
private boolean estActuelle;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getAppareil() { return appareil; }
public void setAppareil(String appareil) { this.appareil = appareil; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getIp() { return ip; }
public void setIp(String ip) { this.ip = ip; }
public String getLocalisation() { return localisation; }
public void setLocalisation(String localisation) { this.localisation = localisation; }
public LocalDateTime getDerniereActivite() { return derniereActivite; }
public void setDerniereActivite(LocalDateTime derniereActivite) { this.derniereActivite = derniereActivite; }
public boolean isEstActuelle() { return estActuelle; }
public void setEstActuelle(boolean estActuelle) { this.estActuelle = estActuelle; }
public String getDerniereActiviteFormatee() {
if (derniereActivite == null) return "Inconnu";
long hours = java.time.temporal.ChronoUnit.HOURS.between(derniereActivite, LocalDateTime.now());
if (hours < 1) return "Il y a moins d'une heure";
if (hours < 24) return "Il y a " + hours + "h";
long days = hours / 24;
return "Il y a " + days + " jour" + (days > 1 ? "s" : "");
}
}
}

View File

@@ -0,0 +1,566 @@
package dev.lions.unionflow.client.view;
import dev.lions.unionflow.client.dto.MembreDTO;
import dev.lions.unionflow.client.service.MembreService;
import dev.lions.unionflow.client.service.EvenementService;
import dev.lions.unionflow.client.service.CotisationService;
import dev.lions.unionflow.client.dto.EvenementDTO;
import dev.lions.unionflow.client.dto.CotisationDTO;
import dev.lions.unionflow.client.view.UserSession;
import jakarta.enterprise.context.SessionScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.annotation.PostConstruct;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@Named("personnelBean")
@SessionScoped
public class PersonnelBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(PersonnelBean.class.getName());
@Inject
private UserSession userSession;
@Inject
@RestClient
private MembreService membreService;
@Inject
@RestClient
private EvenementService evenementService;
@Inject
@RestClient
private CotisationService cotisationService;
private MembreDTO membre;
private StatistiquesProfil statistiques;
private List<ActiviteRecente> activitesRecentes;
private List<DocumentPersonnel> documents;
private List<NotificationPersonnelle> notifications;
@PostConstruct
public void init() {
chargerProfil();
chargerStatistiques();
chargerActivitesRecentes();
chargerDocuments();
chargerNotifications();
}
/**
* Charge le profil du membre connecté
*/
private void chargerProfil() {
try {
if (userSession != null && userSession.getCurrentUser() != null) {
String email = userSession.getCurrentUser().getEmail();
if (email != null) {
// Rechercher le membre par email
List<MembreDTO> membres = membreService.listerTous();
membre = membres.stream()
.filter(m -> email.equals(m.getEmail()))
.findFirst()
.orElse(null);
if (membre == null) {
LOGGER.warning(() -> "Aucun membre trouvé pour l'email: " + email);
} else {
LOGGER.info("Profil chargé pour le membre: " + membre.getNomComplet());
}
}
}
} catch (Exception e) {
LOGGER.severe(() -> "Erreur lors du chargement du profil: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de charger votre profil. Veuillez réessayer.");
}
}
/**
* Charge les statistiques du profil
*/
private void chargerStatistiques() {
statistiques = new StatistiquesProfil();
try {
if (membre != null) {
// Actions réalisées (calculées depuis les activités)
statistiques.setActionsRealisees(calculerActionsRealisees());
// Événements participés
statistiques.setEvenementsParticipes(calculerEvenementsParticipes());
// Taux de participation
statistiques.setTauxParticipation(calculerTauxParticipation());
// Évaluation moyenne (basée sur les cotisations payées et événements participés)
statistiques.setEvaluationMoyenne(calculerEvaluationMoyenne());
}
} catch (Exception e) {
LOGGER.severe(() -> "Erreur lors du calcul des statistiques: " + e.getMessage());
initialiserStatistiquesVides();
}
}
private int calculerActionsRealisees() {
// Calculer depuis les activités récentes chargées
if (activitesRecentes != null && !activitesRecentes.isEmpty()) {
return activitesRecentes.size();
}
// Si pas encore chargées, estimer depuis les cotisations et événements
try {
if (membre != null) {
List<CotisationDTO> cotisations = cotisationService.obtenirParMembre(membre.getId(), 0, 100);
Map<String, Object> evenementsMap = evenementService.listerTous(0, 100, "dateDebut", "desc");
int nbCotisations = cotisations != null ? cotisations.size() : 0;
int nbEvenements = 0;
if (evenementsMap != null && evenementsMap.containsKey("content")) {
@SuppressWarnings("unchecked")
List<Map<String, Object>> content = (List<Map<String, Object>>) evenementsMap.get("content");
nbEvenements = content != null ? content.size() : 0;
}
return nbCotisations + nbEvenements;
}
} catch (Exception e) {
LOGGER.warning(() -> "Erreur lors du calcul des actions: " + e.getMessage());
}
return 0;
}
private int calculerEvenementsParticipes() {
try {
if (membre != null) {
// Récupérer tous les événements et filtrer ceux où le membre a participé
Map<String, Object> evenementsMap = evenementService.listerTous(0, 100, "dateDebut", "desc");
if (evenementsMap != null && evenementsMap.containsKey("content")) {
@SuppressWarnings("unchecked")
List<Map<String, Object>> content = (List<Map<String, Object>>) evenementsMap.get("content");
if (content != null) {
// Pour l'instant, on estime que le membre a participé à 30% des événements
return (int) (content.size() * 0.3);
}
}
}
} catch (Exception e) {
LOGGER.warning(() -> "Erreur lors du calcul des événements: " + e.getMessage());
}
return 0;
}
private double calculerTauxParticipation() {
try {
if (membre != null) {
// Calculer le taux basé sur les cotisations payées vs dues
List<CotisationDTO> cotisations = cotisationService.obtenirParMembre(membre.getId(), 0, 100);
if (cotisations != null && !cotisations.isEmpty()) {
long payees = cotisations.stream()
.filter(c -> "PAYEE".equals(c.getStatut()))
.count();
return cotisations.size() > 0 ? (payees * 100.0 / cotisations.size()) : 0.0;
}
}
} catch (Exception e) {
LOGGER.warning(() -> "Erreur lors du calcul du taux de participation: " + e.getMessage());
}
return 0.0;
}
private double calculerEvaluationMoyenne() {
try {
if (membre != null) {
// Basé sur le taux de participation et les cotisations
double tauxParticipation = calculerTauxParticipation();
List<CotisationDTO> cotisations = cotisationService.obtenirParMembre(membre.getId(), 0, 100);
double baseNote = 3.0; // Note de base
if (tauxParticipation >= 90) {
baseNote = 5.0;
} else if (tauxParticipation >= 75) {
baseNote = 4.5;
} else if (tauxParticipation >= 50) {
baseNote = 4.0;
} else if (tauxParticipation >= 25) {
baseNote = 3.5;
}
// Ajuster selon le nombre de cotisations
if (cotisations != null && cotisations.size() > 10) {
baseNote = Math.min(5.0, baseNote + 0.2);
}
return Math.round(baseNote * 10.0) / 10.0;
}
} catch (Exception e) {
LOGGER.warning(() -> "Erreur lors du calcul de l'évaluation: " + e.getMessage());
}
return 4.0;
}
/**
* Charge les activités récentes
*/
private void chargerActivitesRecentes() {
activitesRecentes = new ArrayList<>();
try {
if (membre != null) {
// Charger les cotisations récentes
List<CotisationDTO> cotisations = cotisationService.obtenirParMembre(membre.getId(), 0, 10);
if (cotisations != null) {
for (CotisationDTO cot : cotisations) {
ActiviteRecente act = new ActiviteRecente();
act.setTitre("Cotisation " + (cot.getStatut() != null ? cot.getStatut() : ""));
act.setDescription("Montant: " + (cot.getMontantPaye() != null ? cot.getMontantPaye() : "0") + " " +
(cot.getCodeDevise() != null ? cot.getCodeDevise() : "FCFA"));
if (cot.getDatePaiement() != null) {
act.setDateHeure(formatDateRelative(cot.getDatePaiement().toString()));
} else if (cot.getDateCreation() != null) {
act.setDateHeure(formatDateRelative(cot.getDateCreation().toString()));
} else {
act.setDateHeure("Récemment");
}
act.setIcon("pi-dollar");
act.setCouleur("green-500");
activitesRecentes.add(act);
}
}
// Charger les événements récents
Map<String, Object> evenementsMap = evenementService.listerAVenir(0, 5);
if (evenementsMap != null && evenementsMap.containsKey("content")) {
@SuppressWarnings("unchecked")
List<Map<String, Object>> content = (List<Map<String, Object>>) evenementsMap.get("content");
if (content != null) {
for (Map<String, Object> evtMap : content) {
ActiviteRecente act = new ActiviteRecente();
act.setTitre("Événement: " + (evtMap.get("titre") != null ? evtMap.get("titre").toString() : ""));
act.setDescription("Événement à venir");
if (evtMap.get("dateDebut") != null) {
act.setDateHeure(formatDateRelative(evtMap.get("dateDebut").toString()));
} else {
act.setDateHeure("Bientôt");
}
act.setIcon("pi-calendar");
act.setCouleur("blue-500");
activitesRecentes.add(act);
}
}
}
// Ajouter une activité de connexion
ActiviteRecente connexion = new ActiviteRecente();
connexion.setTitre("Connexion système");
connexion.setDescription("Dernière connexion réussie");
connexion.setDateHeure("il y a 2h");
connexion.setIcon("pi-sign-in");
connexion.setCouleur("purple-500");
activitesRecentes.add(0, connexion);
// Limiter à 10 activités
if (activitesRecentes.size() > 10) {
activitesRecentes = activitesRecentes.subList(0, 10);
}
}
} catch (Exception e) {
LOGGER.severe(() -> "Erreur lors du chargement des activités: " + e.getMessage());
// Créer au moins une activité par défaut
if (activitesRecentes.isEmpty()) {
ActiviteRecente act = new ActiviteRecente();
act.setTitre("Connexion système");
act.setDescription("Dernière connexion réussie");
act.setDateHeure("Récemment");
act.setIcon("pi-sign-in");
act.setCouleur("blue-500");
activitesRecentes.add(act);
}
}
}
private String formatDateRelative(String dateStr) {
try {
LocalDateTime date = LocalDateTime.parse(dateStr.replace("Z", ""));
long hours = ChronoUnit.HOURS.between(date, LocalDateTime.now());
if (hours < 1) {
return "il y a moins d'une heure";
} else if (hours < 24) {
return "il y a " + hours + "h";
} else {
long days = ChronoUnit.DAYS.between(date, LocalDateTime.now());
return "il y a " + days + " jour" + (days > 1 ? "s" : "");
}
} catch (Exception e) {
return "Récemment";
}
}
private String formatDateRelative(LocalDate date) {
try {
long days = ChronoUnit.DAYS.between(date, LocalDate.now());
if (days == 0) {
return "Aujourd'hui";
} else if (days == 1) {
return "Hier";
} else if (days < 7) {
return "il y a " + days + " jour" + (days > 1 ? "s" : "");
} else if (days < 30) {
long weeks = days / 7;
return "il y a " + weeks + " semaine" + (weeks > 1 ? "s" : "");
} else {
long months = days / 30;
return "il y a " + months + " mois";
}
} catch (Exception e) {
return "Récemment";
}
}
/**
* Charge les documents personnels
*/
private void chargerDocuments() {
documents = new ArrayList<>();
try {
if (membre != null) {
// Créer des documents basés sur les cotisations et événements
List<CotisationDTO> cotisations = cotisationService.obtenirParMembre(membre.getId(), 0, 20);
if (cotisations != null) {
for (CotisationDTO cot : cotisations) {
if ("PAYEE".equals(cot.getStatut()) && cot.getDatePaiement() != null) {
DocumentPersonnel doc = new DocumentPersonnel();
doc.setId(cot.getId());
doc.setNom("Reçu de cotisation - " + (cot.getNumeroReference() != null ? cot.getNumeroReference() : "N/A"));
doc.setType("PDF");
doc.setDateCreation(cot.getDatePaiement().toLocalDate());
doc.setTaille(245000); // 245 KB
documents.add(doc);
}
}
}
// Ajouter quelques documents par défaut
DocumentPersonnel doc1 = new DocumentPersonnel();
doc1.setId(UUID.randomUUID());
doc1.setNom("Certificat d'adhésion.pdf");
doc1.setType("PDF");
doc1.setDateCreation(LocalDate.now().minusMonths(6));
doc1.setTaille(512000);
documents.add(doc1);
DocumentPersonnel doc2 = new DocumentPersonnel();
doc2.setId(UUID.randomUUID());
doc2.setNom("Règlement intérieur.pdf");
doc2.setType("PDF");
doc2.setDateCreation(LocalDate.now().minusMonths(3));
doc2.setTaille(1024000);
documents.add(doc2);
}
} catch (Exception e) {
LOGGER.warning("Erreur lors du chargement des documents: " + e.getMessage());
}
}
/**
* Charge les notifications personnelles
*/
private void chargerNotifications() {
notifications = new ArrayList<>();
try {
if (membre != null) {
// Créer des notifications basées sur les événements à venir
Map<String, Object> evenementsMap = evenementService.listerAVenir(0, 5);
if (evenementsMap != null && evenementsMap.containsKey("content")) {
@SuppressWarnings("unchecked")
List<Map<String, Object>> content = (List<Map<String, Object>>) evenementsMap.get("content");
if (content != null) {
for (Map<String, Object> evtMap : content) {
NotificationPersonnelle notif = new NotificationPersonnelle();
notif.setId(UUID.randomUUID());
notif.setTitre("Nouvel événement");
notif.setMessage("Un nouvel événement a été programmé: " +
(evtMap.get("titre") != null ? evtMap.get("titre").toString() : ""));
if (evtMap.get("dateCreation") != null) {
try {
notif.setDateCreation(LocalDate.parse(evtMap.get("dateCreation").toString().substring(0, 10)));
} catch (Exception e) {
notif.setDateCreation(LocalDate.now().minusDays(1));
}
} else {
notif.setDateCreation(LocalDate.now().minusDays(1));
}
notif.setLue(false);
notifications.add(notif);
}
}
}
// Ajouter des notifications par défaut
NotificationPersonnelle notif1 = new NotificationPersonnelle();
notif1.setId(UUID.randomUUID());
notif1.setTitre("Bienvenue");
notif1.setMessage("Bienvenue dans votre espace personnel UnionFlow");
notif1.setDateCreation(LocalDate.now().minusDays(7));
notif1.setLue(true);
notifications.add(0, notif1);
}
} catch (Exception e) {
LOGGER.warning("Erreur lors du chargement des notifications: " + e.getMessage());
}
}
/**
* Met à jour le profil
*/
public void mettreAJourProfil() {
try {
if (membre != null) {
membre = membreService.modifier(membre.getId(), membre);
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès",
"Votre profil a été mis à jour avec succès.");
}
} catch (Exception e) {
LOGGER.severe("Erreur lors de la mise à jour du profil: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de mettre à jour votre profil. Veuillez réessayer.");
}
}
/**
* Actualise les données
*/
public void actualiser() {
chargerProfil();
chargerStatistiques();
chargerActivitesRecentes();
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès", "Données actualisées.");
}
private void initialiserStatistiquesVides() {
statistiques.setActionsRealisees(0);
statistiques.setEvenementsParticipes(0);
statistiques.setTauxParticipation(0.0);
statistiques.setEvaluationMoyenne(0.0);
}
private void ajouterMessage(FacesMessage.Severity severity, String summary, String detail) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(severity, summary, detail));
}
// Getters et Setters
public MembreDTO getMembre() { return membre; }
public void setMembre(MembreDTO membre) { this.membre = membre; }
public StatistiquesProfil getStatistiques() { return statistiques; }
public void setStatistiques(StatistiquesProfil statistiques) { this.statistiques = statistiques; }
public List<ActiviteRecente> getActivitesRecentes() { return activitesRecentes; }
public void setActivitesRecentes(List<ActiviteRecente> activitesRecentes) { this.activitesRecentes = activitesRecentes; }
public List<DocumentPersonnel> getDocuments() { return documents; }
public void setDocuments(List<DocumentPersonnel> documents) { this.documents = documents; }
public List<NotificationPersonnelle> getNotifications() { return notifications; }
public void setNotifications(List<NotificationPersonnelle> notifications) { this.notifications = notifications; }
// Classes internes
public static class StatistiquesProfil implements Serializable {
private int actionsRealisees;
private int evenementsParticipes;
private double tauxParticipation;
private double evaluationMoyenne;
public int getActionsRealisees() { return actionsRealisees; }
public void setActionsRealisees(int actionsRealisees) { this.actionsRealisees = actionsRealisees; }
public int getEvenementsParticipes() { return evenementsParticipes; }
public void setEvenementsParticipes(int evenementsParticipes) { this.evenementsParticipes = evenementsParticipes; }
public double getTauxParticipation() { return tauxParticipation; }
public void setTauxParticipation(double tauxParticipation) { this.tauxParticipation = tauxParticipation; }
public double getEvaluationMoyenne() { return evaluationMoyenne; }
public void setEvaluationMoyenne(double evaluationMoyenne) { this.evaluationMoyenne = evaluationMoyenne; }
}
public static class ActiviteRecente implements Serializable {
private String titre;
private String description;
private String dateHeure;
private String icon;
private String couleur;
public String getTitre() { return titre; }
public void setTitre(String titre) { this.titre = titre; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public String getDateHeure() { return dateHeure; }
public void setDateHeure(String dateHeure) { this.dateHeure = dateHeure; }
public String getIcon() { return icon; }
public void setIcon(String icon) { this.icon = icon; }
public String getCouleur() { return couleur; }
public void setCouleur(String couleur) { this.couleur = couleur; }
}
public static class DocumentPersonnel implements Serializable {
private UUID id;
private String nom;
private String type;
private LocalDate dateCreation;
private long taille;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getNom() { return nom; }
public void setNom(String nom) { this.nom = nom; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public LocalDate getDateCreation() { return dateCreation; }
public void setDateCreation(LocalDate dateCreation) { this.dateCreation = dateCreation; }
public long getTaille() { return taille; }
public void setTaille(long taille) { this.taille = taille; }
}
public static class NotificationPersonnelle implements Serializable {
private UUID id;
private String titre;
private String message;
private LocalDate dateCreation;
private boolean lue;
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
public String getTitre() { return titre; }
public void setTitre(String titre) { this.titre = titre; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public LocalDate getDateCreation() { return dateCreation; }
public void setDateCreation(LocalDate dateCreation) { this.dateCreation = dateCreation; }
public boolean isLue() { return lue; }
public void setLue(boolean lue) { this.lue = lue; }
}
}

View File

@@ -0,0 +1,292 @@
package dev.lions.unionflow.client.view;
import dev.lions.unionflow.client.service.PreferencesService;
import jakarta.enterprise.context.SessionScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.annotation.PostConstruct;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;
/**
* Bean pour la gestion des préférences utilisateur
* Gère l'apparence, les notifications, la confidentialité et le tableau de bord
*/
@Named("preferencesBean")
@SessionScoped
public class PreferencesBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(PreferencesBean.class.getName());
@Inject
private UserSession userSession;
@Inject
@RestClient
private PreferencesService preferencesService;
// Apparence
private String theme = "light";
private String couleurAccent = "blue";
private String langue = "fr";
private String fuseauHoraire = "GMT";
private String formatDate = "dd/mm/yyyy";
// Notifications
private boolean notifEvenements = true;
private boolean notifMessages = true;
private boolean notifCotisations = true;
private boolean notifSysteme = false;
private boolean emailQuotidien = false;
private boolean emailHebdo = true;
private boolean emailUrgent = true;
private boolean emailPromo = false;
private boolean smsUrgent = false;
private boolean smsRappels = false;
private boolean smsEvenements = false;
private String heuresSMS = "08-20";
// Confidentialité
private String visibiliteProfil = "publique";
private boolean doubleAuth = true;
private boolean connexionSecure = true;
private boolean deconnexionAuto = false;
private String dureeSession = "480";
// Tableau de bord
private boolean widgetActivites = true;
private boolean widgetEvenements = true;
private boolean widgetCotisations = false;
private boolean widgetNotifications = true;
private boolean widgetStatistiques = false;
private boolean widgetMeteo = false;
private String layoutDashboard = "grid-3";
private String pageAccueil = "dashboard";
private String elementsPage = "25";
private boolean animations = true;
@PostConstruct
public void init() {
chargerPreferences();
}
/**
* Charge les préférences depuis le backend
*/
private void chargerPreferences() {
try {
UUID userId = userSession.getCurrentUser().getId();
if (userId != null) {
Map<String, Boolean> prefs = preferencesService.obtenirPreferences(userId);
// Mapper les préférences du backend vers les propriétés du bean
notifEvenements = prefs.getOrDefault("NOUVEL_EVENEMENT", true);
notifCotisations = prefs.getOrDefault("NOUVELLE_COTISATION", true);
notifSysteme = prefs.getOrDefault("NOUVEAU_MEMBRE", false);
emailUrgent = prefs.getOrDefault("EMAIL", true);
smsUrgent = prefs.getOrDefault("SMS", false);
}
} catch (Exception e) {
LOGGER.warning(() -> "Erreur lors du chargement des préférences: " + e.getMessage());
// Utiliser les valeurs par défaut en cas d'erreur
}
}
/**
* Sauvegarde toutes les préférences
*/
public void sauvegarderPreferences() {
try {
UUID userId = userSession.getCurrentUser().getId();
if (userId == null) {
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Utilisateur non identifié");
return;
}
// Créer un Map avec toutes les préférences de notification
Map<String, Boolean> prefs = new HashMap<>();
prefs.put("NOUVEL_EVENEMENT", notifEvenements);
prefs.put("NOUVELLE_COTISATION", notifCotisations);
prefs.put("NOUVEAU_MEMBRE", notifSysteme);
prefs.put("EMAIL", emailUrgent);
prefs.put("SMS", smsUrgent);
prefs.put("RAPPEL_COTISATION", smsRappels);
prefs.put("RAPPEL_EVENEMENT", smsEvenements);
// Appeler le service backend
preferencesService.mettreAJourPreferences(userId, prefs);
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès",
"Vos préférences ont été enregistrées avec succès");
} catch (Exception e) {
LOGGER.severe(() -> "Erreur lors de la sauvegarde: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible d'enregistrer les préférences: " + e.getMessage());
}
}
/**
* Réinitialise les préférences aux valeurs par défaut
*/
public void reinitialiserPreferences() {
try {
UUID userId = userSession.getCurrentUser().getId();
if (userId == null) {
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Utilisateur non identifié");
return;
}
preferencesService.reinitialiserPreferences(userId);
// Recharger les préférences
chargerPreferences();
// Réinitialiser les autres préférences locales
theme = "light";
couleurAccent = "blue";
langue = "fr";
fuseauHoraire = "GMT";
formatDate = "dd/mm/yyyy";
emailQuotidien = false;
emailHebdo = true;
emailPromo = false;
visibiliteProfil = "publique";
doubleAuth = true;
connexionSecure = true;
deconnexionAuto = false;
dureeSession = "480";
widgetActivites = true;
widgetEvenements = true;
widgetCotisations = false;
widgetNotifications = true;
widgetStatistiques = false;
widgetMeteo = false;
layoutDashboard = "grid-3";
pageAccueil = "dashboard";
elementsPage = "25";
animations = true;
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès",
"Les préférences ont été réinitialisées aux valeurs par défaut");
} catch (Exception e) {
LOGGER.severe(() -> "Erreur lors de la réinitialisation: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de réinitialiser les préférences: " + e.getMessage());
}
}
private void ajouterMessage(FacesMessage.Severity severity, String summary, String detail) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(severity, summary, detail));
}
// Getters et Setters
public String getTheme() { return theme; }
public void setTheme(String theme) { this.theme = theme; }
public String getCouleurAccent() { return couleurAccent; }
public void setCouleurAccent(String couleurAccent) { this.couleurAccent = couleurAccent; }
public String getLangue() { return langue; }
public void setLangue(String langue) { this.langue = langue; }
public String getFuseauHoraire() { return fuseauHoraire; }
public void setFuseauHoraire(String fuseauHoraire) { this.fuseauHoraire = fuseauHoraire; }
public String getFormatDate() { return formatDate; }
public void setFormatDate(String formatDate) { this.formatDate = formatDate; }
public boolean isNotifEvenements() { return notifEvenements; }
public void setNotifEvenements(boolean notifEvenements) { this.notifEvenements = notifEvenements; }
public boolean isNotifMessages() { return notifMessages; }
public void setNotifMessages(boolean notifMessages) { this.notifMessages = notifMessages; }
public boolean isNotifCotisations() { return notifCotisations; }
public void setNotifCotisations(boolean notifCotisations) { this.notifCotisations = notifCotisations; }
public boolean isNotifSysteme() { return notifSysteme; }
public void setNotifSysteme(boolean notifSysteme) { this.notifSysteme = notifSysteme; }
public boolean isEmailQuotidien() { return emailQuotidien; }
public void setEmailQuotidien(boolean emailQuotidien) { this.emailQuotidien = emailQuotidien; }
public boolean isEmailHebdo() { return emailHebdo; }
public void setEmailHebdo(boolean emailHebdo) { this.emailHebdo = emailHebdo; }
public boolean isEmailUrgent() { return emailUrgent; }
public void setEmailUrgent(boolean emailUrgent) { this.emailUrgent = emailUrgent; }
public boolean isEmailPromo() { return emailPromo; }
public void setEmailPromo(boolean emailPromo) { this.emailPromo = emailPromo; }
public boolean isSmsUrgent() { return smsUrgent; }
public void setSmsUrgent(boolean smsUrgent) { this.smsUrgent = smsUrgent; }
public boolean isSmsRappels() { return smsRappels; }
public void setSmsRappels(boolean smsRappels) { this.smsRappels = smsRappels; }
public boolean isSmsEvenements() { return smsEvenements; }
public void setSmsEvenements(boolean smsEvenements) { this.smsEvenements = smsEvenements; }
public String getHeuresSMS() { return heuresSMS; }
public void setHeuresSMS(String heuresSMS) { this.heuresSMS = heuresSMS; }
public String getVisibiliteProfil() { return visibiliteProfil; }
public void setVisibiliteProfil(String visibiliteProfil) { this.visibiliteProfil = visibiliteProfil; }
public boolean isDoubleAuth() { return doubleAuth; }
public void setDoubleAuth(boolean doubleAuth) { this.doubleAuth = doubleAuth; }
public boolean isConnexionSecure() { return connexionSecure; }
public void setConnexionSecure(boolean connexionSecure) { this.connexionSecure = connexionSecure; }
public boolean isDeconnexionAuto() { return deconnexionAuto; }
public void setDeconnexionAuto(boolean deconnexionAuto) { this.deconnexionAuto = deconnexionAuto; }
public String getDureeSession() { return dureeSession; }
public void setDureeSession(String dureeSession) { this.dureeSession = dureeSession; }
public boolean isWidgetActivites() { return widgetActivites; }
public void setWidgetActivites(boolean widgetActivites) { this.widgetActivites = widgetActivites; }
public boolean isWidgetEvenements() { return widgetEvenements; }
public void setWidgetEvenements(boolean widgetEvenements) { this.widgetEvenements = widgetEvenements; }
public boolean isWidgetCotisations() { return widgetCotisations; }
public void setWidgetCotisations(boolean widgetCotisations) { this.widgetCotisations = widgetCotisations; }
public boolean isWidgetNotifications() { return widgetNotifications; }
public void setWidgetNotifications(boolean widgetNotifications) { this.widgetNotifications = widgetNotifications; }
public boolean isWidgetStatistiques() { return widgetStatistiques; }
public void setWidgetStatistiques(boolean widgetStatistiques) { this.widgetStatistiques = widgetStatistiques; }
public boolean isWidgetMeteo() { return widgetMeteo; }
public void setWidgetMeteo(boolean widgetMeteo) { this.widgetMeteo = widgetMeteo; }
public String getLayoutDashboard() { return layoutDashboard; }
public void setLayoutDashboard(String layoutDashboard) { this.layoutDashboard = layoutDashboard; }
public String getPageAccueil() { return pageAccueil; }
public void setPageAccueil(String pageAccueil) { this.pageAccueil = pageAccueil; }
public String getElementsPage() { return elementsPage; }
public void setElementsPage(String elementsPage) { this.elementsPage = elementsPage; }
public boolean isAnimations() { return animations; }
public void setAnimations(boolean animations) { this.animations = animations; }
}

View File

@@ -1,12 +1,13 @@
package dev.lions.unionflow.client.view;
import dev.lions.unionflow.client.dto.AnalyticsDataDTO;
import dev.lions.unionflow.client.service.AnalyticsService;
import dev.lions.unionflow.client.service.MembreService;
import dev.lions.unionflow.client.service.CotisationService;
import dev.lions.unionflow.client.service.EvenementService;
import dev.lions.unionflow.client.service.DemandeAideService;
import dev.lions.unionflow.client.service.AssociationService;
import jakarta.enterprise.context.SessionScoped;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.annotation.PostConstruct;
@@ -16,6 +17,7 @@ import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.math.BigDecimal;
import java.util.logging.Logger;
@@ -26,6 +28,7 @@ public class RapportsBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(RapportsBean.class.getName());
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy");
@Inject
@RestClient
@@ -43,28 +46,26 @@ public class RapportsBean implements Serializable {
@RestClient
private EvenementService evenementService;
@Inject
@RestClient
private DemandeAideService demandeAideService;
@Inject
@RestClient
private AssociationService associationService;
private String organisationId; // À injecter depuis la session
// Filtres de période
private String periodeRapide;
private LocalDate dateDebut;
private LocalDate dateFin;
private String groupeComparaison;
// Données analytics
private Map<String, Object> kpis;
private Map<String, Object> evolutions;
// Données calculées pour l'affichage
private IndicateursGlobaux indicateurs;
private List<EvolutionMensuelle> evolutionMensuelle;
private List<Objectif> objectifs;
private List<RepartitionMembres> repartitionMembres;
private List<SourceRevenus> sourceRevenus;
private List<TopEntite> topEntites;
private List<KPI> kpis;
private List<KPI> kpisList;
private List<Alerte> alertes;
private List<HistoriqueRapport> historiqueRapports;
@@ -74,130 +75,117 @@ public class RapportsBean implements Serializable {
@PostConstruct
public void init() {
initializePeriodes();
initializeIndicateurs();
initializeEvolutionMensuelle();
initializeObjectifs();
initializeRepartitions();
initializeTopEntites();
initializeKPIs();
initializeAlertes();
initializeHistoriqueRapports();
initializeNouveauRapport();
chargerDonnees();
}
private void initializePeriodes() {
periodeRapide = "30_JOURS";
periodeRapide = "TRENTE_DERNIERS_JOURS";
dateDebut = LocalDate.now().minusDays(30);
dateFin = LocalDate.now();
groupeComparaison = "PERIODE_PRECEDENTE";
}
private void initializeIndicateurs() {
/**
* Charge les données depuis le backend
*/
public void chargerDonnees() {
try {
String periode = mapperPeriode(periodeRapide);
// Charger les KPIs depuis le backend
kpis = analyticsService.obtenirTousLesKPI(organisationId, periode);
// Charger les évolutions
evolutions = analyticsService.obtenirEvolutionsKPI(organisationId, periode);
// Calculer les indicateurs globaux
calculerIndicateurs();
// Calculer les répartitions
calculerRepartitions();
// Calculer les objectifs
calculerObjectifs();
// Initialiser les listes vides
evolutionMensuelle = new ArrayList<>();
topEntites = new ArrayList<>();
kpisList = new ArrayList<>();
alertes = new ArrayList<>();
historiqueRapports = new ArrayList<>();
// Convertir les KPIs en liste pour l'affichage
convertirKPIsEnListe();
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des données: " + e.getMessage());
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
"Impossible de charger les données. Veuillez réessayer.");
initialiserDonneesVides();
}
}
/**
* Mappe la période rapide vers le format backend
*/
private String mapperPeriode(String periodeRapide) {
return switch (periodeRapide) {
case "7_JOURS" -> "SEPT_DERNIERS_JOURS";
case "30_JOURS", "TRENTE_DERNIERS_JOURS" -> "TRENTE_DERNIERS_JOURS";
case "3_MOIS" -> "TROIS_DERNIERS_MOIS";
case "6_MOIS" -> "SIX_DERNIERS_MOIS";
case "ANNEE_COURANTE" -> "CETTE_ANNEE";
default -> "TRENTE_DERNIERS_JOURS";
};
}
/**
* Calcule les indicateurs globaux depuis les données réelles
*/
private void calculerIndicateurs() {
indicateurs = new IndicateursGlobaux();
try {
int totalMembres = membreService.listerTous().size();
int totalEvenements = evenementService.listerTous(0, 1000).size();
int totalEvenements = evenementService.listerTous(0, 1000, "dateCreation", "desc").size();
BigDecimal totalRevenus = cotisationService.listerToutes(0, 1000).stream()
.filter(c -> "PAYEE".equals(c.getStatut()) || "PARTIELLEMENT_PAYEE".equals(c.getStatut()))
.map(c -> c.getMontantPaye() != null ? c.getMontantPaye() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add);
BigDecimal totalAides = demandeAideService.listerToutes(0, 1000).stream()
.filter(d -> d.getMontantAccorde() != null)
.map(d -> d.getMontantAccorde())
.reduce(BigDecimal.ZERO, BigDecimal::add);
indicateurs.setTotalMembres(totalMembres);
indicateurs.setCroissanceMembres(0.0); // À calculer depuis les données historiques
indicateurs.setCroissanceMembres(calculerCroissance("NOMBRE_MEMBRES_ACTIFS"));
indicateurs.setRevenus(formatMontantCourt(totalRevenus) + " FCFA");
indicateurs.setCroissanceRevenus(0.0); // À calculer depuis les données historiques
indicateurs.setCroissanceRevenus(calculerCroissance("TOTAL_COTISATIONS_COLLECTEES"));
indicateurs.setTotalEvenements(totalEvenements);
indicateurs.setCroissanceEvenements(0.0); // À calculer depuis les données historiques
indicateurs.setTotalAides(formatMontantCourt(totalAides) + " FCFA");
indicateurs.setCroissanceAides(0.0); // À calculer depuis les données historiques
indicateurs.setCroissanceEvenements(calculerCroissance("NOMBRE_EVENEMENTS_ORGANISES"));
indicateurs.setTotalAides(formatMontantCourt(BigDecimal.ZERO) + " FCFA");
indicateurs.setCroissanceAides(0.0);
} catch (Exception e) {
LOGGER.severe("Erreur lors du calcul des indicateurs: " + e.getMessage());
indicateurs.setTotalMembres(0);
indicateurs.setCroissanceMembres(0.0);
indicateurs.setRevenus("0 FCFA");
indicateurs.setCroissanceRevenus(0.0);
indicateurs.setTotalEvenements(0);
indicateurs.setCroissanceEvenements(0.0);
indicateurs.setTotalAides("0 FCFA");
indicateurs.setCroissanceAides(0.0);
initialiserIndicateursVides();
}
}
private void initializeEvolutionMensuelle() {
evolutionMensuelle = new ArrayList<>();
try {
if (organisationId != null && dateDebut != null && dateFin != null) {
String periode = "CUSTOM"; // À mapper depuis dateDebut/dateFin
analyticsService.getEvolutionMensuelle("NOMBRE_MEMBRES_ACTIFS", organisationId, periode);
// Traiter les données de l'API
// Pour l'instant, initialiser avec des données vides
/**
* Calcule la croissance depuis les évolutions
*/
private double calculerCroissance(String typeMetrique) {
if (evolutions != null && evolutions.containsKey(typeMetrique)) {
Object evolution = evolutions.get(typeMetrique);
if (evolution instanceof BigDecimal) {
return ((BigDecimal) evolution).doubleValue();
} else if (evolution instanceof Number) {
return ((Number) evolution).doubleValue();
}
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement de l'évolution mensuelle: " + e.getMessage());
}
// Si pas de données, laisser la liste vide plutôt que des données mockées
return 0.0;
}
private void initializeObjectifs() {
objectifs = new ArrayList<>();
try {
int totalMembres = membreService.listerTous().size();
int totalEvenements = evenementService.listerTous(0, 1000).size();
int totalDemandes = demandeAideService.listerToutes(0, 1000).size();
BigDecimal totalRevenus = cotisationService.listerToutes(0, 1000).stream()
.filter(c -> "PAYEE".equals(c.getStatut()) || "PARTIELLEMENT_PAYEE".equals(c.getStatut()))
.map(c -> c.getMontantPaye() != null ? c.getMontantPaye() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add);
Objectif obj1 = new Objectif();
obj1.setLibelle("Nouveaux Membres");
obj1.setRealise(String.valueOf(totalMembres));
obj1.setCible(String.valueOf((int) (totalMembres * 1.2))); // Objectif 20% supérieur
obj1.setPourcentage(totalMembres > 0 ? (int) ((double) totalMembres / (totalMembres * 1.2) * 100) : 0);
objectifs.add(obj1);
Objectif obj2 = new Objectif();
obj2.setLibelle("Revenus Cotisations");
obj2.setRealise(formatMontantCourt(totalRevenus));
obj2.setCible(formatMontantCourt(totalRevenus.multiply(new BigDecimal("1.2"))));
obj2.setPourcentage(83); // À calculer
objectifs.add(obj2);
Objectif obj3 = new Objectif();
obj3.setLibelle("Événements Organisés");
obj3.setRealise(String.valueOf(totalEvenements));
obj3.setCible(String.valueOf((int) (totalEvenements * 1.2)));
obj3.setPourcentage(totalEvenements > 0 ? (int) ((double) totalEvenements / (totalEvenements * 1.2) * 100) : 0);
objectifs.add(obj3);
Objectif obj4 = new Objectif();
obj4.setLibelle("Aides Accordées");
obj4.setRealise(String.valueOf(totalDemandes));
obj4.setCible(String.valueOf((int) (totalDemandes * 1.3)));
obj4.setPourcentage(totalDemandes > 0 ? (int) ((double) totalDemandes / (totalDemandes * 1.3) * 100) : 0);
objectifs.add(obj4);
} catch (Exception e) {
LOGGER.severe("Erreur lors du calcul des objectifs: " + e.getMessage());
}
}
private String formatMontantCourt(BigDecimal montant) {
if (montant == null) return "0";
double millions = montant.doubleValue() / 1_000_000.0;
if (millions >= 1) {
return String.format("%.1fM", millions);
}
return String.format("%.0fK", montant.doubleValue() / 1_000.0);
}
private void initializeRepartitions() {
/**
* Calcule les répartitions
*/
private void calculerRepartitions() {
repartitionMembres = new ArrayList<>();
try {
List<dev.lions.unionflow.client.dto.MembreDTO> membres = membreService.listerTous();
@@ -235,7 +223,7 @@ public class RapportsBean implements Serializable {
SourceRevenus cotisations = new SourceRevenus();
cotisations.setLibelle("Cotisations");
cotisations.setMontant(formatMontantCourt(totalRevenus));
cotisations.setPourcentage(100.0); // Pour l'instant, uniquement cotisations
cotisations.setPourcentage(100.0);
cotisations.setCouleur("blue-500");
cotisations.setIcon("pi-users");
sourceRevenus.add(cotisations);
@@ -245,71 +233,141 @@ public class RapportsBean implements Serializable {
}
}
private void initializeTopEntites() {
topEntites = new ArrayList<>();
/**
* Calcule les objectifs
*/
private void calculerObjectifs() {
objectifs = new ArrayList<>();
try {
List<dev.lions.unionflow.client.dto.AssociationDTO> associations = associationService.listerActives();
topEntites = associations.stream()
.sorted((a1, a2) -> {
int m1 = a1.getNombreMembres() != null ? a1.getNombreMembres() : 0;
int m2 = a2.getNombreMembres() != null ? a2.getNombreMembres() : 0;
return Integer.compare(m2, m1);
})
.limit(5)
.map(a -> {
TopEntite entite = new TopEntite();
entite.setRang(0); // À calculer
entite.setNom(a.getNom());
entite.setTypeIcon("pi-users");
entite.setScore(0); // À calculer depuis les métriques
entite.setTendance("STABLE"); // À calculer
return entite;
})
.collect(java.util.stream.Collectors.toList());
int totalMembres = membreService.listerTous().size();
int totalEvenements = evenementService.listerTous(0, 1000, "dateCreation", "desc").size();
// Assigner les rangs
for (int i = 0; i < topEntites.size(); i++) {
topEntites.get(i).setRang(i + 1);
}
BigDecimal totalRevenus = cotisationService.listerToutes(0, 1000).stream()
.filter(c -> "PAYEE".equals(c.getStatut()) || "PARTIELLEMENT_PAYEE".equals(c.getStatut()))
.map(c -> c.getMontantPaye() != null ? c.getMontantPaye() : BigDecimal.ZERO)
.reduce(BigDecimal.ZERO, BigDecimal::add);
Objectif obj1 = new Objectif();
obj1.setLibelle("Nouveaux Membres");
obj1.setRealise(String.valueOf(totalMembres));
int cibleMembres = (int) (totalMembres * 1.2);
obj1.setCible(String.valueOf(cibleMembres));
obj1.setPourcentage(totalMembres > 0 ? (int) ((double) totalMembres / cibleMembres * 100) : 0);
objectifs.add(obj1);
Objectif obj2 = new Objectif();
obj2.setLibelle("Revenus Cotisations");
obj2.setRealise(formatMontantCourt(totalRevenus));
BigDecimal cibleRevenus = totalRevenus.multiply(new BigDecimal("1.2"));
obj2.setCible(formatMontantCourt(cibleRevenus));
obj2.setPourcentage(totalRevenus.compareTo(BigDecimal.ZERO) > 0 ?
(int) (totalRevenus.divide(cibleRevenus, 2, java.math.RoundingMode.HALF_UP).doubleValue() * 100) : 0);
objectifs.add(obj2);
Objectif obj3 = new Objectif();
obj3.setLibelle("Événements Organisés");
obj3.setRealise(String.valueOf(totalEvenements));
int cibleEvenements = (int) (totalEvenements * 1.2);
obj3.setCible(String.valueOf(cibleEvenements));
obj3.setPourcentage(totalEvenements > 0 ? (int) ((double) totalEvenements / cibleEvenements * 100) : 0);
objectifs.add(obj3);
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des top entités: " + e.getMessage());
LOGGER.severe("Erreur lors du calcul des objectifs: " + e.getMessage());
}
}
private void initializeKPIs() {
kpis = new ArrayList<>();
try {
if (organisationId != null && dateDebut != null && dateFin != null) {
String periode = "CUSTOM"; // À mapper depuis dateDebut/dateFin
analyticsService.getKPIs(organisationId, periode);
// Traiter les données de l'API
// Pour l'instant, laisser la liste vide plutôt que des données mockées
}
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des KPIs: " + e.getMessage());
/**
* Convertit les KPIs Map en liste pour l'affichage
*/
private void convertirKPIsEnListe() {
kpisList = new ArrayList<>();
if (kpis != null) {
kpis.forEach((type, valeur) -> {
KPI kpi = new KPI();
kpi.setLibelle(getLibelleMetrique(type.toString()));
kpi.setValeur(valeur instanceof BigDecimal ?
((BigDecimal) valeur).toPlainString() : valeur.toString());
kpi.setProgression(0);
kpi.setVariation(calculerCroissance(type.toString()));
kpi.setTendance(kpi.getVariation() > 0 ? "HAUSSE" : kpi.getVariation() < 0 ? "BAISSE" : "STABLE");
kpi.setIcon(getIconeMetrique(type.toString()));
kpi.setCouleur(getCouleurMetrique(type.toString()));
kpisList.add(kpi);
});
}
}
private void initializeAlertes() {
private String getLibelleMetrique(String type) {
return switch (type) {
case "NOMBRE_MEMBRES_ACTIFS" -> "Membres Actifs";
case "TOTAL_COTISATIONS_COLLECTEES" -> "Cotisations Collectées";
case "NOMBRE_EVENEMENTS_ORGANISES" -> "Événements Organisés";
default -> type;
};
}
private String getIconeMetrique(String type) {
return switch (type) {
case "NOMBRE_MEMBRES_ACTIFS" -> "pi-users";
case "TOTAL_COTISATIONS_COLLECTEES" -> "pi-dollar";
case "NOMBRE_EVENEMENTS_ORGANISES" -> "pi-calendar";
default -> "pi-chart-bar";
};
}
private String getCouleurMetrique(String type) {
return switch (type) {
case "NOMBRE_MEMBRES_ACTIFS" -> "blue-500";
case "TOTAL_COTISATIONS_COLLECTEES" -> "green-500";
case "NOMBRE_EVENEMENTS_ORGANISES" -> "orange-500";
default -> "gray-500";
};
}
private String formatMontantCourt(BigDecimal montant) {
if (montant == null) return "0";
double millions = montant.doubleValue() / 1_000_000.0;
if (millions >= 1) {
return String.format("%.1fM", millions);
}
return String.format("%.0fK", montant.doubleValue() / 1_000.0);
}
private void initialiserDonneesVides() {
indicateurs = new IndicateursGlobaux();
initialiserIndicateursVides();
evolutionMensuelle = new ArrayList<>();
objectifs = new ArrayList<>();
repartitionMembres = new ArrayList<>();
sourceRevenus = new ArrayList<>();
topEntites = new ArrayList<>();
kpisList = new ArrayList<>();
alertes = new ArrayList<>();
// Les alertes seront calculées depuis les données réelles
// Pour l'instant, laisser la liste vide plutôt que des données mockées
}
private void initializeHistoriqueRapports() {
historiqueRapports = new ArrayList<>();
// L'historique des rapports sera chargé depuis la base de données
// Pour l'instant, laisser la liste vide plutôt que des données mockées
}
private void initializeNouveauRapport() {
nouveauRapport = new NouveauRapport();
nouveauRapport.setFormat("PDF");
nouveauRapport.setPeriode("30_JOURS");
nouveauRapport.setDetail("STANDARD");
private void initialiserIndicateursVides() {
indicateurs.setTotalMembres(0);
indicateurs.setCroissanceMembres(0.0);
indicateurs.setRevenus("0 FCFA");
indicateurs.setCroissanceRevenus(0.0);
indicateurs.setTotalEvenements(0);
indicateurs.setCroissanceEvenements(0.0);
indicateurs.setTotalAides("0 FCFA");
indicateurs.setCroissanceAides(0.0);
}
// Actions
/**
* Actualise les données
*/
public void actualiser() {
chargerDonnees();
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès", "Données actualisées avec succès.");
}
/**
* Génère un nouveau rapport
*/
public void genererRapport() {
LOGGER.info("Génération du rapport " + nouveauRapport.getType() + " en format " + nouveauRapport.getFormat());
@@ -326,6 +384,14 @@ public class RapportsBean implements Serializable {
historiqueRapports.add(0, nouveauHistorique);
initializeNouveauRapport();
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès", "Rapport en cours de génération.");
}
private void initializeNouveauRapport() {
nouveauRapport = new NouveauRapport();
nouveauRapport.setFormat("PDF");
nouveauRapport.setPeriode("30_JOURS");
nouveauRapport.setDetail("STANDARD");
}
private String getTypeLibelle(String type) {
@@ -374,20 +440,33 @@ public class RapportsBean implements Serializable {
}
public String voirRapport(HistoriqueRapport rapport) {
return "/pages/admin/rapports/details?id=" + rapport.getId() + "&faces-redirect=true";
rapportSelectionne = rapport;
return "/pages/secure/rapport/details?faces-redirect=true";
}
public void telechargerRapport(HistoriqueRapport rapport) {
LOGGER.info("Téléchargement du rapport: " + rapport.getTypeLibelle());
ajouterMessage(FacesMessage.SEVERITY_INFO, "Téléchargement",
"Le téléchargement du rapport va commencer.");
}
public void exporterDonnees() {
LOGGER.info("Export des données statistiques");
ajouterMessage(FacesMessage.SEVERITY_INFO, "Export",
"L'export des données va commencer.");
}
private void ajouterMessage(FacesMessage.Severity severity, String summary, String detail) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(severity, summary, detail));
}
// Getters et Setters
public String getPeriodeRapide() { return periodeRapide; }
public void setPeriodeRapide(String periodeRapide) { this.periodeRapide = periodeRapide; }
public void setPeriodeRapide(String periodeRapide) {
this.periodeRapide = periodeRapide;
chargerDonnees();
}
public LocalDate getDateDebut() { return dateDebut; }
public void setDateDebut(LocalDate dateDebut) { this.dateDebut = dateDebut; }
@@ -416,8 +495,8 @@ public class RapportsBean implements Serializable {
public List<TopEntite> getTopEntites() { return topEntites; }
public void setTopEntites(List<TopEntite> topEntites) { this.topEntites = topEntites; }
public List<KPI> getKpis() { return kpis; }
public void setKpis(List<KPI> kpis) { this.kpis = kpis; }
public List<KPI> getKpis() { return kpisList; }
public void setKpis(List<KPI> kpis) { this.kpisList = kpis; }
public List<Alerte> getAlertes() { return alertes; }
public void setAlertes(List<Alerte> alertes) { this.alertes = alertes; }
@@ -431,7 +510,7 @@ public class RapportsBean implements Serializable {
public HistoriqueRapport getRapportSelectionne() { return rapportSelectionne; }
public void setRapportSelectionne(HistoriqueRapport rapportSelectionne) { this.rapportSelectionne = rapportSelectionne; }
// Classes internes
// Classes internes (conservées pour compatibilité avec les pages XHTML)
public static class IndicateursGlobaux {
private int totalMembres;
private double croissanceMembres;
@@ -442,7 +521,6 @@ public class RapportsBean implements Serializable {
private String totalAides;
private double croissanceAides;
// Getters et setters
public int getTotalMembres() { return totalMembres; }
public void setTotalMembres(int totalMembres) { this.totalMembres = totalMembres; }
@@ -475,7 +553,6 @@ public class RapportsBean implements Serializable {
private int hauteurMembres;
private int hauteurRevenus;
// Getters et setters
public String getLibelle() { return libelle; }
public void setLibelle(String libelle) { this.libelle = libelle; }
@@ -498,7 +575,6 @@ public class RapportsBean implements Serializable {
private String cible;
private int pourcentage;
// Getters et setters
public String getLibelle() { return libelle; }
public void setLibelle(String libelle) { this.libelle = libelle; }
@@ -518,7 +594,6 @@ public class RapportsBean implements Serializable {
private double pourcentage;
private String couleur;
// Getters et setters
public String getLibelle() { return libelle; }
public void setLibelle(String libelle) { this.libelle = libelle; }
@@ -539,7 +614,6 @@ public class RapportsBean implements Serializable {
private String couleur;
private String icon;
// Getters et setters
public String getLibelle() { return libelle; }
public void setLibelle(String libelle) { this.libelle = libelle; }
@@ -563,7 +637,6 @@ public class RapportsBean implements Serializable {
private int score;
private String tendance;
// Getters et setters
public int getRang() { return rang; }
public void setRang(int rang) { this.rang = rang; }
@@ -589,7 +662,6 @@ public class RapportsBean implements Serializable {
private String icon;
private String couleur;
// Getters et setters
public String getLibelle() { return libelle; }
public void setLibelle(String libelle) { this.libelle = libelle; }
@@ -621,7 +693,6 @@ public class RapportsBean implements Serializable {
private String icon;
private String dateDetection;
// Getters et setters
public String getTitre() { return titre; }
public void setTitre(String titre) { this.titre = titre; }
@@ -655,7 +726,6 @@ public class RapportsBean implements Serializable {
private String generePar;
private String statut;
// Getters et setters
public UUID getId() { return id; }
public void setId(UUID id) { this.id = id; }
@@ -685,7 +755,7 @@ public class RapportsBean implements Serializable {
public String getDateGenerationFormatee() {
if (dateGeneration == null) return "";
return dateGeneration.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
return dateGeneration.format(DATE_FORMATTER);
}
public String getStatutSeverity() {
@@ -706,7 +776,6 @@ public class RapportsBean implements Serializable {
private String detail;
private String commentaires;
// Getters et setters
public String getType() { return type; }
public void setType(String type) { this.type = type; }
@@ -722,4 +791,4 @@ public class RapportsBean implements Serializable {
public String getCommentaires() { return commentaires; }
public void setCommentaires(String commentaires) { this.commentaires = commentaires; }
}
}
}

View File

@@ -83,7 +83,7 @@ public class SuperAdminBean implements Serializable {
private void initializeKPIs() {
try {
List<AssociationDTO> associations = associationService.listerToutes();
List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
totalEntites = associations.size();
totalAdministrateurs = associations.size(); // À calculer depuis les utilisateurs
int totalMembresCalc = associations.stream()
@@ -183,7 +183,7 @@ public class SuperAdminBean implements Serializable {
private void initializeEntites() {
topEntites = new ArrayList<>();
try {
List<AssociationDTO> associations = associationService.listerActives();
List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
topEntites = associations.stream()
.sorted((a1, a2) -> {
int m1 = a1.getNombreMembres() != null ? a1.getNombreMembres() : 0;

View File

@@ -0,0 +1,150 @@
package dev.lions.unionflow.client.view;
import dev.lions.unionflow.client.dto.TypeOrganisationClientDTO;
import dev.lions.unionflow.client.service.TypeOrganisationClientService;
import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.logging.Logger;
import org.eclipse.microprofile.rest.client.inject.RestClient;
/**
* Bean de gestion du catalogue des types d'organisation (UI Super Admin).
*/
@Named("typeOrganisationsAdminBean")
@ViewScoped
public class TypeOrganisationsAdminBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final Logger LOGGER = Logger.getLogger(TypeOrganisationsAdminBean.class.getName());
@Inject
@RestClient
TypeOrganisationClientService typeOrganisationClientService;
private List<TypeOrganisationClientDTO> types = new ArrayList<>();
/** Type actuellement édité dans le dialogue (nouveau ou existant). */
private TypeOrganisationClientDTO typeCourant;
private TypeOrganisationClientDTO typeSelectionne;
@PostConstruct
public void init() {
chargerTypes();
}
public void chargerTypes() {
try {
types = typeOrganisationClientService.list(false);
} catch (Exception e) {
LOGGER.severe("Erreur lors du chargement des types d'organisation: " + e.getMessage());
types = new ArrayList<>();
}
}
public void preparerNouveauType() {
typeCourant = new TypeOrganisationClientDTO();
typeCourant.setActif(true);
typeSelectionne = null;
}
private void creerType() {
try {
TypeOrganisationClientDTO cree = typeOrganisationClientService.create(typeCourant);
types.add(cree);
typeCourant = null;
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"Succès", "Type d'organisation créé avec succès"));
} catch (Exception e) {
LOGGER.severe("Erreur lors de la création du type d'organisation: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erreur", "Impossible de créer le type d'organisation: " + e.getMessage()));
}
}
/**
* Méthode unique utilisée par le bouton "Enregistrer" du dialogue.
* Si un nouveau type est en cours d'édition, on crée, sinon on met à jour le type sélectionné.
*/
public void enregistrerType() {
if (typeCourant == null) {
return;
}
if (typeCourant.getId() == null) {
creerType();
} else {
sauvegarderType();
}
}
private void sauvegarderType() {
if (typeCourant == null || typeCourant.getId() == null) {
return;
}
try {
TypeOrganisationClientDTO maj =
typeOrganisationClientService.update(typeCourant.getId(), typeCourant);
// Remplacer dans la liste
types.replaceAll(t -> t.getId().equals(maj.getId()) ? maj : t);
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"Succès", "Type d'organisation mis à jour"));
} catch (Exception e) {
LOGGER.severe("Erreur lors de la mise à jour du type d'organisation: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erreur", "Impossible de mettre à jour le type d'organisation: " + e.getMessage()));
}
}
public void desactiverType(UUID id) {
try {
typeOrganisationClientService.disable(id);
types.stream()
.filter(t -> t.getId().equals(id))
.findFirst()
.ifPresent(t -> t.setActif(false));
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO,
"Succès", "Type d'organisation désactivé"));
} catch (Exception e) {
LOGGER.severe("Erreur lors de la désactivation du type d'organisation: " + e.getMessage());
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Erreur", "Impossible de désactiver le type d'organisation: " + e.getMessage()));
}
}
// Getters / Setters
public List<TypeOrganisationClientDTO> getTypes() { return types; }
public void setTypes(List<TypeOrganisationClientDTO> types) { this.types = types; }
public TypeOrganisationClientDTO getTypeSelectionne() { return typeSelectionne; }
public void setTypeSelectionne(TypeOrganisationClientDTO typeSelectionne) {
this.typeSelectionne = typeSelectionne;
this.typeCourant = typeSelectionne;
}
/**
* Retourne le type actuellement édité dans le dialogue.
* Initialise un nouveau type par défaut si aucun n'est encore défini,
* ce qui évite les erreurs "Target Unreachable" lors de la validation JSF.
*/
public TypeOrganisationClientDTO getTypeCourant() {
if (typeCourant == null) {
typeCourant = new TypeOrganisationClientDTO();
typeCourant.setActif(true);
}
return typeCourant;
}
public void setTypeCourant(TypeOrganisationClientDTO typeCourant) { this.typeCourant = typeCourant; }
}

View File

@@ -65,7 +65,7 @@ public class UtilisateursBean implements Serializable {
private void initializeOrganisations() {
organisationsDisponibles = new ArrayList<>();
try {
List<AssociationDTO> associations = associationService.listerActives();
List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
for (AssociationDTO assoc : associations) {
Organisation org = new Organisation();
org.setId(assoc.getId());

View File

@@ -0,0 +1,279 @@
package dev.lions.unionflow.client.view;
import dev.lions.unionflow.client.dto.WaveBalanceDTO;
import dev.lions.unionflow.client.dto.WaveCheckoutSessionDTO;
import dev.lions.unionflow.client.service.WaveService;
import jakarta.annotation.PostConstruct;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.jboss.logging.Logger;
/**
* Bean JSF pour la gestion des paiements Wave Money
*
* @author UnionFlow Team
* @version 1.0
* @since 2025-01-17
*/
@Named
@ViewScoped
public class WaveBean implements Serializable {
private static final Logger LOGGER = Logger.getLogger(WaveBean.class);
private static final long serialVersionUID = 1L;
@Inject @org.eclipse.microprofile.rest.client.inject.RestClient WaveService waveService;
// Session de paiement en cours
private WaveCheckoutSessionDTO sessionEnCours;
private WaveBalanceDTO solde;
// Données pour créer une session
private BigDecimal montantPaiement;
private String devisePaiement = "XOF";
private String descriptionPaiement;
private String typePaiement = "COTISATION";
private UUID organisationId;
private UUID membreId;
private String referenceUnionFlow;
// Résultat du test de connexion
private Map<String, Object> resultatTest;
@PostConstruct
public void init() {
LOGGER.info("Initialisation de WaveBean");
chargerSolde();
}
/**
* Crée une session de paiement Wave
*/
public void creerSessionPaiement() {
try {
LOGGER.infof("Création d'une session Wave: montant=%s", montantPaiement);
if (montantPaiement == null || montantPaiement.compareTo(BigDecimal.ZERO) <= 0) {
ajouterMessage(
FacesMessage.SEVERITY_ERROR, "Erreur", "Le montant doit être supérieur à zéro");
return;
}
// Construire les URLs de redirection
String baseUrl = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
String successUrl = baseUrl + "/pages/secure/wave/success.xhtml";
String errorUrl = baseUrl + "/pages/secure/wave/error.xhtml";
sessionEnCours =
waveService.creerSessionPaiement(
montantPaiement,
devisePaiement,
successUrl,
errorUrl,
referenceUnionFlow,
descriptionPaiement,
organisationId,
membreId);
LOGGER.infof("Session créée: %s", sessionEnCours != null ? sessionEnCours.getWaveSessionId() : "null");
ajouterMessage(
FacesMessage.SEVERITY_INFO,
"Succès",
"Session de paiement créée avec succès. Redirection vers Wave...");
// Rediriger vers l'URL Wave
if (sessionEnCours != null && sessionEnCours.getWaveUrl() != null) {
FacesContext.getCurrentInstance()
.getExternalContext()
.redirect(sessionEnCours.getWaveUrl());
}
} catch (Exception e) {
LOGGER.errorf(e, "Erreur lors de la création de la session: %s", e.getMessage());
ajouterMessage(
FacesMessage.SEVERITY_ERROR,
"Erreur",
"Erreur lors de la création de la session: " + e.getMessage());
}
}
/**
* Vérifie le statut d'une session
*/
public void verifierStatutSession(String sessionId) {
try {
LOGGER.infof("Vérification du statut de la session: %s", sessionId);
sessionEnCours = waveService.verifierStatutSession(sessionId);
} catch (Exception e) {
LOGGER.errorf(e, "Erreur lors de la vérification du statut: %s", e.getMessage());
ajouterMessage(
FacesMessage.SEVERITY_ERROR,
"Erreur",
"Erreur lors de la vérification du statut: " + e.getMessage());
}
}
/**
* Charge le solde Wave
*/
public void chargerSolde() {
try {
LOGGER.info("Chargement du solde Wave");
solde = waveService.consulterSolde();
} catch (Exception e) {
LOGGER.errorf(e, "Erreur lors du chargement du solde: %s", e.getMessage());
// Ne pas afficher d'erreur si Wave n'est pas configuré
solde = null;
}
}
/**
* Teste la connexion à l'API Wave
*/
public void testerConnexion() {
try {
LOGGER.info("Test de connexion à l'API Wave");
resultatTest = waveService.testerConnexion();
if (resultatTest != null && "OK".equals(resultatTest.get("statut"))) {
ajouterMessage(
FacesMessage.SEVERITY_INFO,
"Succès",
"Connexion à l'API Wave réussie: " + resultatTest.get("message"));
} else {
ajouterMessage(
FacesMessage.SEVERITY_WARN,
"Attention",
resultatTest != null
? resultatTest.get("message").toString()
: "Erreur lors du test de connexion");
}
} catch (Exception e) {
LOGGER.errorf(e, "Erreur lors du test de connexion: %s", e.getMessage());
ajouterMessage(
FacesMessage.SEVERITY_ERROR,
"Erreur",
"Erreur lors du test de connexion: " + e.getMessage());
}
}
/**
* Réinitialise les données du formulaire
*/
public void reinitialiserFormulaire() {
montantPaiement = null;
devisePaiement = "XOF";
descriptionPaiement = null;
typePaiement = "COTISATION";
referenceUnionFlow = null;
sessionEnCours = null;
}
// Méthodes utilitaires
private void ajouterMessage(
jakarta.faces.application.FacesMessage.Severity severity, String resume, String detail) {
FacesContext.getCurrentInstance()
.addMessage(null, new FacesMessage(severity, resume, detail));
}
/**
* Vérifie si Wave est disponible
*/
public boolean isWaveDisponible() {
return solde != null && solde.isWalletActif();
}
// Getters et Setters
public WaveCheckoutSessionDTO getSessionEnCours() {
return sessionEnCours;
}
public void setSessionEnCours(WaveCheckoutSessionDTO sessionEnCours) {
this.sessionEnCours = sessionEnCours;
}
public WaveBalanceDTO getSolde() {
return solde;
}
public void setSolde(WaveBalanceDTO solde) {
this.solde = solde;
}
public BigDecimal getMontantPaiement() {
return montantPaiement;
}
public void setMontantPaiement(BigDecimal montantPaiement) {
this.montantPaiement = montantPaiement;
}
public String getDevisePaiement() {
return devisePaiement;
}
public void setDevisePaiement(String devisePaiement) {
this.devisePaiement = devisePaiement;
}
public String getDescriptionPaiement() {
return descriptionPaiement;
}
public void setDescriptionPaiement(String descriptionPaiement) {
this.descriptionPaiement = descriptionPaiement;
}
public String getTypePaiement() {
return typePaiement;
}
public void setTypePaiement(String typePaiement) {
this.typePaiement = typePaiement;
}
public UUID getOrganisationId() {
return organisationId;
}
public void setOrganisationId(UUID organisationId) {
this.organisationId = organisationId;
}
public UUID getMembreId() {
return membreId;
}
public void setMembreId(UUID membreId) {
this.membreId = membreId;
}
public String getReferenceUnionFlow() {
return referenceUnionFlow;
}
public void setReferenceUnionFlow(String referenceUnionFlow) {
this.referenceUnionFlow = referenceUnionFlow;
}
public Map<String, Object> getResultatTest() {
return resultatTest;
}
public void setResultatTest(Map<String, Object> resultatTest) {
this.resultatTest = resultatTest;
}
}