Configure Maven repository for unionflow-server-api dependency
This commit is contained in:
91
Dockerfile.prod
Normal file
91
Dockerfile.prod
Normal file
@@ -0,0 +1,91 @@
|
||||
####
|
||||
# Dockerfile de production pour UnionFlow Client (Frontend)
|
||||
# Multi-stage build optimisé avec sécurité renforcée
|
||||
####
|
||||
|
||||
## Stage 1 : Build avec Maven
|
||||
FROM maven:3.9.6-eclipse-temurin-17 AS builder
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Copier les fichiers de configuration Maven
|
||||
COPY pom.xml .
|
||||
COPY ../unionflow-server-api/pom.xml ../unionflow-server-api/
|
||||
|
||||
# Télécharger les dépendances (cache Docker)
|
||||
RUN mvn dependency:go-offline -B -pl unionflow-client-quarkus-primefaces-freya -am
|
||||
|
||||
# Copier le code source
|
||||
COPY src ./src
|
||||
|
||||
# Build de l'application avec profil production
|
||||
RUN mvn clean package -DskipTests -B -Dquarkus.profile=prod -pl unionflow-client-quarkus-primefaces-freya
|
||||
|
||||
## Stage 2 : Image de production optimisée et sécurisée
|
||||
FROM registry.access.redhat.com/ubi8/openjdk-17:1.18
|
||||
|
||||
ENV LANGUAGE='fr_FR:fr'
|
||||
|
||||
# Variables d'environnement de production
|
||||
ENV QUARKUS_PROFILE=prod
|
||||
ENV QUARKUS_HTTP_PORT=8086
|
||||
ENV QUARKUS_HTTP_HOST=0.0.0.0
|
||||
|
||||
# Configuration Keycloak/OIDC (production)
|
||||
ENV QUARKUS_OIDC_AUTH_SERVER_URL=https://security.lions.dev/realms/unionflow
|
||||
ENV QUARKUS_OIDC_CLIENT_ID=unionflow-client
|
||||
ENV QUARKUS_OIDC_ENABLED=true
|
||||
ENV QUARKUS_OIDC_TLS_VERIFICATION=required
|
||||
ENV KEYCLOAK_CLIENT_SECRET=changeme
|
||||
|
||||
# Configuration API Backend
|
||||
ENV UNIONFLOW_BACKEND_URL=https://api.lions.dev/unionflow
|
||||
|
||||
# Configuration CORS
|
||||
ENV QUARKUS_HTTP_CORS_ORIGINS=https://unionflow.lions.dev,https://security.lions.dev
|
||||
ENV QUARKUS_HTTP_CORS_ALLOW_CREDENTIALS=true
|
||||
|
||||
# Configuration Session
|
||||
ENV SESSION_TIMEOUT=1800
|
||||
ENV REMEMBER_ME_DURATION=604800
|
||||
|
||||
# Installer curl pour les health checks
|
||||
USER root
|
||||
RUN microdnf install -y curl && \
|
||||
microdnf clean all && \
|
||||
rm -rf /var/cache/yum
|
||||
|
||||
# Créer les répertoires et permissions pour utilisateur non-root
|
||||
RUN mkdir -p /deployments /app/logs && \
|
||||
chown -R 185:185 /deployments /app/logs
|
||||
|
||||
# Passer à l'utilisateur non-root pour la sécurité
|
||||
USER 185
|
||||
|
||||
# Copier l'application depuis le builder (format fast-jar Quarkus)
|
||||
COPY --from=builder --chown=185 /app/target/quarkus-app/ /deployments/
|
||||
|
||||
# Exposer le port
|
||||
EXPOSE 8086
|
||||
|
||||
# Variables JVM optimisées pour production avec sécurité
|
||||
ENV JAVA_OPTS="-Xmx768m -Xms256m \
|
||||
-XX:+UseG1GC \
|
||||
-XX:MaxGCPauseMillis=200 \
|
||||
-XX:+UseStringDeduplication \
|
||||
-XX:+ParallelRefProcEnabled \
|
||||
-XX:+HeapDumpOnOutOfMemoryError \
|
||||
-XX:HeapDumpPath=/app/logs/heapdump.hprof \
|
||||
-Djava.security.egd=file:/dev/./urandom \
|
||||
-Djava.awt.headless=true \
|
||||
-Dfile.encoding=UTF-8 \
|
||||
-Djava.util.logging.manager=org.jboss.logmanager.LogManager \
|
||||
-Dquarkus.profile=${QUARKUS_PROFILE}"
|
||||
|
||||
# Health check avec endpoints Quarkus
|
||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=90s --retries=3 \
|
||||
CMD curl -f http://localhost:8086/q/health/ready || exit 1
|
||||
|
||||
# Point d'entrée avec profil production (format fast-jar)
|
||||
ENTRYPOINT ["sh", "-c", "exec java $JAVA_OPTS -jar /deployments/quarkus-run.jar"]
|
||||
|
||||
247
pom.xml
Normal file
247
pom.xml
Normal file
@@ -0,0 +1,247 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>dev.lions.unionflow</groupId>
|
||||
<artifactId>unionflow-client-quarkus-primefaces-freya</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>UnionFlow Client (Quarkus + PrimeFaces Freya)</name>
|
||||
<description>Client web UnionFlow avec Quarkus et PrimeFaces Freya</description>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
||||
<quarkus.platform.version>3.15.1</quarkus.platform.version>
|
||||
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
|
||||
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
||||
<quarkus-primefaces.version>3.13.3</quarkus-primefaces.version>
|
||||
<primefaces.version>14.0.5</primefaces.version>
|
||||
<omnifaces.version>4.4.1</omnifaces.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${quarkus.platform.group-id}</groupId>
|
||||
<artifactId>${quarkus.platform.artifact-id}</artifactId>
|
||||
<version>${quarkus.platform.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<!-- Quarkus Core -->
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-arc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Quarkus PrimeFaces Extension (includes MyFaces and PrimeFaces) -->
|
||||
<dependency>
|
||||
<groupId>io.quarkiverse.primefaces</groupId>
|
||||
<artifactId>quarkus-primefaces</artifactId>
|
||||
<version>${quarkus-primefaces.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Quarkus OmniFaces Extension (optional but recommended) -->
|
||||
<dependency>
|
||||
<groupId>io.quarkiverse.omnifaces</groupId>
|
||||
<artifactId>quarkus-omnifaces</artifactId>
|
||||
<version>4.4.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- PrimeFaces Themes - Freya -->
|
||||
<dependency>
|
||||
<groupId>org.primefaces.themes</groupId>
|
||||
<artifactId>freya-theme-jakarta</artifactId>
|
||||
<version>5.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Quarkus Undertow -->
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-undertow</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- REST Client pour communiquer avec le serveur -->
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-rest-client</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-rest-client-jackson</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Sécurité JWT et OIDC (Keycloak) -->
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-smallrye-jwt</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-oidc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-oidc-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Configuration -->
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-config-yaml</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Validation -->
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-hibernate-validator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Lombok pour réduire le code boilerplate -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.30</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- UnionFlow Server API - DTOs et interfaces partagées -->
|
||||
<dependency>
|
||||
<groupId>dev.lions.unionflow</groupId>
|
||||
<artifactId>unionflow-server-api</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Lions User Manager Client - Module réutilisable de gestion d'utilisateurs Keycloak -->
|
||||
<!-- COMMENTED OUT: Module not available in repositories
|
||||
<dependency>
|
||||
<groupId>dev.lions.user.manager</groupId>
|
||||
<artifactId>lions-user-manager-client-quarkus-primefaces-freya</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<!-- Scheduler pour le rafraîchissement des tokens -->
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-scheduler</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Export Demo Impl (from Freya template) -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
<version>5.2.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>5.2.5</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.apache.xmlgraphics</groupId>
|
||||
<artifactId>batik-all</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.librepdf</groupId>
|
||||
<artifactId>openpdf</artifactId>
|
||||
<version>1.3.30</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Tests -->
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.rest-assured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>prime-repo</id>
|
||||
<name>PrimeFaces Maven Repository</name>
|
||||
<url>https://repository.primefaces.org</url>
|
||||
<layout>default</layout>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>gitea</id>
|
||||
<name>Gitea Maven Repository</name>
|
||||
<url>https://git.lions.dev/api/packages/lionsdev/maven</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>${quarkus.platform.group-id}</groupId>
|
||||
<artifactId>quarkus-maven-plugin</artifactId>
|
||||
<version>${quarkus.platform.version}</version>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
<goal>generate-code</goal>
|
||||
<goal>generate-code-tests</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
<parameters>true</parameters>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>native</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>native</name>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<skipITs>false</skipITs>
|
||||
<quarkus.package.type>native</quarkus.package.type>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
@@ -0,0 +1,34 @@
|
||||
package dev.lions.unionflow.client;
|
||||
|
||||
import io.quarkus.runtime.Quarkus;
|
||||
import io.quarkus.runtime.QuarkusApplication;
|
||||
import io.quarkus.runtime.annotations.QuarkusMain;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Application principale UnionFlow Client
|
||||
*
|
||||
* @author Lions Dev Team
|
||||
* @version 1.0.0
|
||||
*/
|
||||
@QuarkusMain
|
||||
@ApplicationScoped
|
||||
public class UnionFlowClientApplication implements QuarkusApplication {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(UnionFlowClientApplication.class);
|
||||
|
||||
public static void main(String... args) {
|
||||
Quarkus.run(UnionFlowClientApplication.class, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int run(String... args) throws Exception {
|
||||
LOG.info("UnionFlow Client démarré avec succès!");
|
||||
LOG.info("Interface web disponible sur http://localhost:8082");
|
||||
LOG.info("Page d'accueil sur http://localhost:8082/index.xhtml");
|
||||
|
||||
Quarkus.waitForExit();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package dev.lions.unionflow.client.converter;
|
||||
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.faces.component.UIComponent;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.faces.convert.Converter;
|
||||
import jakarta.faces.convert.FacesConverter;
|
||||
import jakarta.inject.Named;
|
||||
import dev.lions.unionflow.client.view.DemandesBean.Membre;
|
||||
import java.util.UUID;
|
||||
|
||||
@Named
|
||||
@ApplicationScoped
|
||||
@FacesConverter(value = "membreConverter", managed = true)
|
||||
public class MembreConverter implements Converter<Membre> {
|
||||
|
||||
@Override
|
||||
public Membre getAsObject(FacesContext context, UIComponent component, String value) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
// Parse the membre ID from the string value (UUID)
|
||||
UUID membreId = UUID.fromString(value);
|
||||
|
||||
// Create a simple Membre object with just the ID
|
||||
// In a real implementation, you would fetch from database
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
return membre;
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString(FacesContext context, UIComponent component, Membre value) {
|
||||
if (value == null || value.getId() == null) {
|
||||
return "";
|
||||
}
|
||||
return value.getId().toString();
|
||||
}
|
||||
}
|
||||
274
src/main/java/dev/lions/unionflow/client/dto/AdhesionDTO.java
Normal file
274
src/main/java/dev/lions/unionflow/client/dto/AdhesionDTO.java
Normal 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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
331
src/main/java/dev/lions/unionflow/client/dto/AssociationDTO.java
Normal file
331
src/main/java/dev/lions/unionflow/client/dto/AssociationDTO.java
Normal file
@@ -0,0 +1,331 @@
|
||||
package dev.lions.unionflow.client.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* DTO client pour les organisations (alias historique Association).
|
||||
*
|
||||
* Harmonisé avec le contrat serveur `OrganisationDTO`:
|
||||
* - `dateCreation`/`dateModification` d'audit (LocalDateTime) alignés sur BaseDTO avec pattern JSON
|
||||
* - `dateFondation` (LocalDate) pour la date de création fonctionnelle de l'organisation
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class AssociationDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private UUID id;
|
||||
|
||||
@NotBlank(message = "Le nom de l'association est obligatoire")
|
||||
private String nom;
|
||||
|
||||
// Aligné sur OrganisationDTO.nomCourt
|
||||
private String nomCourt;
|
||||
|
||||
private String description;
|
||||
private String adresse;
|
||||
private String telephone;
|
||||
private String email;
|
||||
private String siteWeb;
|
||||
// Aligné sur OrganisationDTO.logo (URL ou chemin du logo)
|
||||
private String logo;
|
||||
|
||||
@NotNull(message = "Le type d'association est obligatoire")
|
||||
@JsonProperty("typeOrganisation")
|
||||
private String typeAssociation;
|
||||
|
||||
// Date de fondation (fonctionnelle), côté serveur: OrganisationDTO.dateFondation
|
||||
@JsonProperty("dateFondation")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate dateFondation;
|
||||
|
||||
// Côté serveur: OrganisationDTO.numeroEnregistrement
|
||||
@JsonProperty("numeroEnregistrement")
|
||||
private String numeroRegistre;
|
||||
private String statut;
|
||||
private Integer nombreMembres;
|
||||
// Aligné sur OrganisationDTO.nombreAdministrateurs
|
||||
private Integer nombreAdministrateurs;
|
||||
private String responsablePrincipal;
|
||||
private String telephoneResponsable;
|
||||
private String emailResponsable;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDerniereActivite;
|
||||
|
||||
// Champs d'audit issus de BaseDTO (côté serveur)
|
||||
@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;
|
||||
private Boolean actif;
|
||||
|
||||
private String region;
|
||||
private String ville;
|
||||
private String quartier;
|
||||
private String pays;
|
||||
// Aligné sur OrganisationDTO.codePostal
|
||||
private String codePostal;
|
||||
|
||||
// Aligné sur OrganisationDTO.activitesPrincipales
|
||||
private String activitesPrincipales;
|
||||
|
||||
// Aligné sur OrganisationDTO.objectifs / partenaires / certifications / reseauxSociaux / notes
|
||||
private String objectifs;
|
||||
private String partenaires;
|
||||
private String certifications;
|
||||
private String reseauxSociaux;
|
||||
private String notes;
|
||||
|
||||
// Aligné sur OrganisationDTO.organisationPublique / accepteNouveauxMembres / cotisationObligatoire
|
||||
private Boolean organisationPublique;
|
||||
private Boolean accepteNouveauxMembres;
|
||||
private Boolean cotisationObligatoire;
|
||||
|
||||
// Aligné sur OrganisationDTO.budgetAnnuel / devise / montantCotisationAnnuelle
|
||||
private BigDecimal budgetAnnuel;
|
||||
private String devise;
|
||||
private BigDecimal montantCotisationAnnuelle;
|
||||
|
||||
// Aligné sur OrganisationDTO.telephoneSecondaire / emailSecondaire
|
||||
private String telephoneSecondaire;
|
||||
private String emailSecondaire;
|
||||
|
||||
// Aligné sur OrganisationDTO.organisationParenteId / nomOrganisationParente / niveauHierarchique
|
||||
private UUID organisationParenteId;
|
||||
private String nomOrganisationParente;
|
||||
private Integer niveauHierarchique;
|
||||
|
||||
// Aligné sur OrganisationDTO.latitude / longitude
|
||||
private BigDecimal latitude;
|
||||
private BigDecimal longitude;
|
||||
|
||||
// Constructeurs
|
||||
public AssociationDTO() {}
|
||||
|
||||
public AssociationDTO(String nom, String typeAssociation) {
|
||||
this.nom = nom;
|
||||
this.typeAssociation = typeAssociation;
|
||||
this.statut = "ACTIVE";
|
||||
this.dateFondation = LocalDate.now();
|
||||
this.nombreMembres = 0;
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
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 getNomCourt() { return nomCourt; }
|
||||
public void setNomCourt(String nomCourt) { this.nomCourt = nomCourt; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public String getAdresse() { return adresse; }
|
||||
public void setAdresse(String adresse) { this.adresse = adresse; }
|
||||
|
||||
public String getTelephone() { return telephone; }
|
||||
public void setTelephone(String telephone) { this.telephone = telephone; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public String getSiteWeb() { return siteWeb; }
|
||||
public void setSiteWeb(String siteWeb) { this.siteWeb = siteWeb; }
|
||||
|
||||
public String getLogo() { return logo; }
|
||||
public void setLogo(String logo) { this.logo = logo; }
|
||||
|
||||
public String getTypeAssociation() { return typeAssociation; }
|
||||
public void setTypeAssociation(String typeAssociation) { this.typeAssociation = typeAssociation; }
|
||||
|
||||
public LocalDate getDateFondation() { return dateFondation; }
|
||||
public void setDateFondation(LocalDate dateFondation) { this.dateFondation = dateFondation; }
|
||||
|
||||
public String getNumeroRegistre() { return numeroRegistre; }
|
||||
public void setNumeroRegistre(String numeroRegistre) { this.numeroRegistre = numeroRegistre; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public Integer getNombreMembres() { return nombreMembres; }
|
||||
public void setNombreMembres(Integer nombreMembres) { this.nombreMembres = nombreMembres; }
|
||||
|
||||
public Integer getNombreAdministrateurs() { return nombreAdministrateurs; }
|
||||
public void setNombreAdministrateurs(Integer nombreAdministrateurs) { this.nombreAdministrateurs = nombreAdministrateurs; }
|
||||
|
||||
public String getResponsablePrincipal() { return responsablePrincipal; }
|
||||
public void setResponsablePrincipal(String responsablePrincipal) { this.responsablePrincipal = responsablePrincipal; }
|
||||
|
||||
public String getTelephoneResponsable() { return telephoneResponsable; }
|
||||
public void setTelephoneResponsable(String telephoneResponsable) { this.telephoneResponsable = telephoneResponsable; }
|
||||
|
||||
public String getEmailResponsable() { return emailResponsable; }
|
||||
public void setEmailResponsable(String emailResponsable) { this.emailResponsable = emailResponsable; }
|
||||
|
||||
public LocalDateTime getDateDerniereActivite() { return dateDerniereActivite; }
|
||||
public void setDateDerniereActivite(LocalDateTime dateDerniereActivite) { this.dateDerniereActivite = dateDerniereActivite; }
|
||||
|
||||
public String getRegion() { return region; }
|
||||
public void setRegion(String region) { this.region = region; }
|
||||
|
||||
public String getVille() { return ville; }
|
||||
public void setVille(String ville) { this.ville = ville; }
|
||||
|
||||
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; }
|
||||
|
||||
public String getCodePostal() { return codePostal; }
|
||||
public void setCodePostal(String codePostal) { this.codePostal = codePostal; }
|
||||
|
||||
public String getActivitesPrincipales() { return activitesPrincipales; }
|
||||
public void setActivitesPrincipales(String activitesPrincipales) { this.activitesPrincipales = activitesPrincipales; }
|
||||
|
||||
public String getObjectifs() { return objectifs; }
|
||||
public void setObjectifs(String objectifs) { this.objectifs = objectifs; }
|
||||
|
||||
public String getPartenaires() { return partenaires; }
|
||||
public void setPartenaires(String partenaires) { this.partenaires = partenaires; }
|
||||
|
||||
public String getCertifications() { return certifications; }
|
||||
public void setCertifications(String certifications) { this.certifications = certifications; }
|
||||
|
||||
public String getReseauxSociaux() { return reseauxSociaux; }
|
||||
public void setReseauxSociaux(String reseauxSociaux) { this.reseauxSociaux = reseauxSociaux; }
|
||||
|
||||
public String getNotes() { return notes; }
|
||||
public void setNotes(String notes) { this.notes = notes; }
|
||||
|
||||
public Boolean getOrganisationPublique() { return organisationPublique; }
|
||||
public void setOrganisationPublique(Boolean organisationPublique) { this.organisationPublique = organisationPublique; }
|
||||
|
||||
public Boolean getAccepteNouveauxMembres() { return accepteNouveauxMembres; }
|
||||
public void setAccepteNouveauxMembres(Boolean accepteNouveauxMembres) { this.accepteNouveauxMembres = accepteNouveauxMembres; }
|
||||
|
||||
public Boolean getCotisationObligatoire() { return cotisationObligatoire; }
|
||||
public void setCotisationObligatoire(Boolean cotisationObligatoire) { this.cotisationObligatoire = cotisationObligatoire; }
|
||||
|
||||
public BigDecimal getBudgetAnnuel() { return budgetAnnuel; }
|
||||
public void setBudgetAnnuel(BigDecimal budgetAnnuel) { this.budgetAnnuel = budgetAnnuel; }
|
||||
|
||||
public String getDevise() { return devise; }
|
||||
public void setDevise(String devise) { this.devise = devise; }
|
||||
|
||||
public BigDecimal getMontantCotisationAnnuelle() { return montantCotisationAnnuelle; }
|
||||
public void setMontantCotisationAnnuelle(BigDecimal montantCotisationAnnuelle) { this.montantCotisationAnnuelle = montantCotisationAnnuelle; }
|
||||
|
||||
public String getTelephoneSecondaire() { return telephoneSecondaire; }
|
||||
public void setTelephoneSecondaire(String telephoneSecondaire) { this.telephoneSecondaire = telephoneSecondaire; }
|
||||
|
||||
public String getEmailSecondaire() { return emailSecondaire; }
|
||||
public void setEmailSecondaire(String emailSecondaire) { this.emailSecondaire = emailSecondaire; }
|
||||
|
||||
public UUID getOrganisationParenteId() { return organisationParenteId; }
|
||||
public void setOrganisationParenteId(UUID organisationParenteId) { this.organisationParenteId = organisationParenteId; }
|
||||
|
||||
public String getNomOrganisationParente() { return nomOrganisationParente; }
|
||||
public void setNomOrganisationParente(String nomOrganisationParente) { this.nomOrganisationParente = nomOrganisationParente; }
|
||||
|
||||
public Integer getNiveauHierarchique() { return niveauHierarchique; }
|
||||
public void setNiveauHierarchique(Integer niveauHierarchique) { this.niveauHierarchique = niveauHierarchique; }
|
||||
|
||||
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 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; }
|
||||
|
||||
public Boolean getActif() { return actif; }
|
||||
public void setActif(Boolean actif) { this.actif = actif; }
|
||||
|
||||
// Propriétés dérivées
|
||||
public String getTypeLibelle() {
|
||||
return switch (typeAssociation != null ? typeAssociation : "") {
|
||||
case "LIONS_CLUB" -> "Club Lions";
|
||||
case "ASSOCIATION_LOCALE" -> "Association Locale";
|
||||
case "FEDERATION" -> "Fédération";
|
||||
case "COOPERATIVE" -> "Coopérative";
|
||||
case "MUTUELLE" -> "Mutuelle";
|
||||
case "SYNDICAT" -> "Syndicat";
|
||||
default -> typeAssociation;
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutLibelle() {
|
||||
return switch (statut != null ? statut : "") {
|
||||
case "ACTIVE" -> "Active";
|
||||
case "INACTIVE" -> "Inactive";
|
||||
case "SUSPENDUE" -> "Suspendue";
|
||||
case "DISSOUTE" -> "Dissoute";
|
||||
default -> statut;
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutSeverity() {
|
||||
return switch (statut != null ? statut : "") {
|
||||
case "ACTIVE" -> "success";
|
||||
case "INACTIVE" -> "warning";
|
||||
case "SUSPENDUE" -> "danger";
|
||||
case "DISSOUTE" -> "secondary";
|
||||
default -> "info";
|
||||
};
|
||||
}
|
||||
|
||||
public String getAdresseComplete() {
|
||||
StringBuilder addr = new StringBuilder();
|
||||
if (adresse != null && !adresse.trim().isEmpty()) {
|
||||
addr.append(adresse);
|
||||
}
|
||||
if (quartier != null && !quartier.trim().isEmpty()) {
|
||||
if (addr.length() > 0) addr.append(", ");
|
||||
addr.append(quartier);
|
||||
}
|
||||
if (ville != null && !ville.trim().isEmpty()) {
|
||||
if (addr.length() > 0) addr.append(", ");
|
||||
addr.append(ville);
|
||||
}
|
||||
if (region != null && !region.trim().isEmpty()) {
|
||||
if (addr.length() > 0) addr.append(", ");
|
||||
addr.append(region);
|
||||
}
|
||||
return addr.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AssociationDTO{" +
|
||||
"id=" + id +
|
||||
", nom='" + nom + '\'' +
|
||||
", typeAssociation='" + typeAssociation + '\'' +
|
||||
", statut='" + statut + '\'' +
|
||||
", nombreMembres=" + nombreMembres +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
185
src/main/java/dev/lions/unionflow/client/dto/AuditLogDTO.java
Normal file
185
src/main/java/dev/lions/unionflow/client/dto/AuditLogDTO.java
Normal 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;
|
||||
}
|
||||
}
|
||||
270
src/main/java/dev/lions/unionflow/client/dto/CotisationDTO.java
Normal file
270
src/main/java/dev/lions/unionflow/client/dto/CotisationDTO.java
Normal file
@@ -0,0 +1,270 @@
|
||||
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 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;
|
||||
|
||||
private UUID id;
|
||||
private String numeroReference;
|
||||
private UUID membreId;
|
||||
private String numeroMembre;
|
||||
private String nomMembre;
|
||||
private UUID associationId;
|
||||
private String nomAssociation;
|
||||
private String typeCotisation;
|
||||
private String libelle;
|
||||
private String description;
|
||||
private BigDecimal montantDu;
|
||||
private BigDecimal montantPaye;
|
||||
private String codeDevise;
|
||||
private String statut;
|
||||
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; }
|
||||
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 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 getTypeCotisation() { return typeCotisation; }
|
||||
public void setTypeCotisation(String typeCotisation) { this.typeCotisation = typeCotisation; }
|
||||
|
||||
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 BigDecimal getMontantDu() { return montantDu; }
|
||||
public void setMontantDu(BigDecimal montantDu) { this.montantDu = montantDu; }
|
||||
|
||||
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 getDateEcheance() { return dateEcheance; }
|
||||
public void setDateEcheance(LocalDate dateEcheance) { this.dateEcheance = dateEcheance; }
|
||||
|
||||
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 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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package dev.lions.unionflow.client.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public class DemandeAideDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private UUID id;
|
||||
private String numeroReference;
|
||||
private String type;
|
||||
private String titre;
|
||||
private String description;
|
||||
private String justification;
|
||||
private BigDecimal montantDemande;
|
||||
private BigDecimal montantAccorde;
|
||||
private String statut;
|
||||
private String urgence;
|
||||
private String localisation;
|
||||
private String motif;
|
||||
private UUID demandeurId;
|
||||
private String demandeur;
|
||||
private String telephone;
|
||||
private String email;
|
||||
private LocalDate dateDemande;
|
||||
private LocalDate dateLimite;
|
||||
private String responsableTraitement;
|
||||
private UUID organisationId;
|
||||
private LocalDateTime dateCreation;
|
||||
|
||||
// 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 String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
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 getJustification() { return justification; }
|
||||
public void setJustification(String justification) { this.justification = justification; }
|
||||
|
||||
public BigDecimal getMontantDemande() { return montantDemande; }
|
||||
public void setMontantDemande(BigDecimal montantDemande) { this.montantDemande = montantDemande; }
|
||||
|
||||
public BigDecimal getMontantAccorde() { return montantAccorde; }
|
||||
public void setMontantAccorde(BigDecimal montantAccorde) { this.montantAccorde = montantAccorde; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getUrgence() { return urgence; }
|
||||
public void setUrgence(String urgence) { this.urgence = urgence; }
|
||||
|
||||
public String getLocalisation() { return localisation; }
|
||||
public void setLocalisation(String localisation) { this.localisation = localisation; }
|
||||
|
||||
public String getMotif() { return motif; }
|
||||
public void setMotif(String motif) { this.motif = motif; }
|
||||
|
||||
public UUID getDemandeurId() { return demandeurId; }
|
||||
public void setDemandeurId(UUID demandeurId) { this.demandeurId = demandeurId; }
|
||||
|
||||
public String getDemandeur() { return demandeur; }
|
||||
public void setDemandeur(String demandeur) { this.demandeur = demandeur; }
|
||||
|
||||
public String getTelephone() { return telephone; }
|
||||
public void setTelephone(String telephone) { this.telephone = telephone; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public LocalDate getDateDemande() { return dateDemande; }
|
||||
public void setDateDemande(LocalDate dateDemande) { this.dateDemande = dateDemande; }
|
||||
|
||||
public LocalDate getDateLimite() { return dateLimite; }
|
||||
public void setDateLimite(LocalDate dateLimite) { this.dateLimite = dateLimite; }
|
||||
|
||||
public String getResponsableTraitement() { return responsableTraitement; }
|
||||
public void setResponsableTraitement(String responsableTraitement) { this.responsableTraitement = responsableTraitement; }
|
||||
|
||||
public UUID getOrganisationId() { return organisationId; }
|
||||
public void setOrganisationId(UUID organisationId) { this.organisationId = organisationId; }
|
||||
|
||||
public LocalDateTime getDateCreation() { return dateCreation; }
|
||||
public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
|
||||
}
|
||||
|
||||
492
src/main/java/dev/lions/unionflow/client/dto/EvenementDTO.java
Normal file
492
src/main/java/dev/lions/unionflow/client/dto/EvenementDTO.java
Normal file
@@ -0,0 +1,492 @@
|
||||
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.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 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 emailOrganisateur;
|
||||
private String telephoneOrganisateur;
|
||||
|
||||
// Participants
|
||||
private Integer capaciteMax;
|
||||
private Integer participantsInscrits;
|
||||
private Integer participantsPresents;
|
||||
|
||||
// Budget
|
||||
private BigDecimal budget;
|
||||
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; }
|
||||
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 getTypeEvenement() { return typeEvenement; }
|
||||
public void setTypeEvenement(String typeEvenement) { this.typeEvenement = typeEvenement; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getPriorite() { return priorite; }
|
||||
public void setPriorite(String priorite) { this.priorite = priorite; }
|
||||
|
||||
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 LocalTime getHeureDebut() { return heureDebut; }
|
||||
public void setHeureDebut(LocalTime heureDebut) { this.heureDebut = heureDebut; }
|
||||
|
||||
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 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 != 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 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);
|
||||
}
|
||||
}
|
||||
181
src/main/java/dev/lions/unionflow/client/dto/FormulaireDTO.java
Normal file
181
src/main/java/dev/lions/unionflow/client/dto/FormulaireDTO.java
Normal file
@@ -0,0 +1,181 @@
|
||||
package dev.lions.unionflow.client.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Positive;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
public class FormulaireDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private UUID id;
|
||||
|
||||
@NotNull
|
||||
private String nom;
|
||||
|
||||
private String description;
|
||||
|
||||
@NotNull
|
||||
@Positive
|
||||
private Integer quotaMaxMembres;
|
||||
|
||||
@NotNull
|
||||
private BigDecimal prixMensuel;
|
||||
|
||||
@NotNull
|
||||
private BigDecimal prixAnnuel;
|
||||
|
||||
private String deviseCode = "XOF"; // Franc CFA
|
||||
|
||||
private boolean actif = true;
|
||||
|
||||
private boolean recommande = false;
|
||||
|
||||
private String couleurTheme;
|
||||
|
||||
private String iconeFormulaire;
|
||||
|
||||
// Fonctionnalités incluses
|
||||
private boolean gestionMembres = true;
|
||||
private boolean gestionCotisations = true;
|
||||
private boolean gestionEvenements = false;
|
||||
private boolean gestionAides = false;
|
||||
private boolean rapportsAvances = false;
|
||||
private boolean supportPrioritaire = false;
|
||||
private boolean sauvegardeAutomatique = false;
|
||||
private boolean personnalisationAvancee = false;
|
||||
private boolean integrationPaiement = false;
|
||||
private boolean notificationsEmail = false;
|
||||
private boolean notificationsSMS = false;
|
||||
private boolean gestionDocuments = false;
|
||||
|
||||
// Métadonnées
|
||||
private LocalDateTime dateCreation;
|
||||
private LocalDateTime dateMiseAJour;
|
||||
private String creePar;
|
||||
private String modifiePar;
|
||||
|
||||
public FormulaireDTO() {}
|
||||
|
||||
// Getters et Setters
|
||||
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 getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public Integer getQuotaMaxMembres() { return quotaMaxMembres; }
|
||||
public void setQuotaMaxMembres(Integer quotaMaxMembres) { this.quotaMaxMembres = quotaMaxMembres; }
|
||||
|
||||
public BigDecimal getPrixMensuel() { return prixMensuel; }
|
||||
public void setPrixMensuel(BigDecimal prixMensuel) { this.prixMensuel = prixMensuel; }
|
||||
|
||||
public BigDecimal getPrixAnnuel() { return prixAnnuel; }
|
||||
public void setPrixAnnuel(BigDecimal prixAnnuel) { this.prixAnnuel = prixAnnuel; }
|
||||
|
||||
public String getDeviseCode() { return deviseCode; }
|
||||
public void setDeviseCode(String deviseCode) { this.deviseCode = deviseCode; }
|
||||
|
||||
public boolean isActif() { return actif; }
|
||||
public void setActif(boolean actif) { this.actif = actif; }
|
||||
|
||||
public boolean isRecommande() { return recommande; }
|
||||
public void setRecommande(boolean recommande) { this.recommande = recommande; }
|
||||
|
||||
public String getCouleurTheme() { return couleurTheme; }
|
||||
public void setCouleurTheme(String couleurTheme) { this.couleurTheme = couleurTheme; }
|
||||
|
||||
public String getIconeFormulaire() { return iconeFormulaire; }
|
||||
public void setIconeFormulaire(String iconeFormulaire) { this.iconeFormulaire = iconeFormulaire; }
|
||||
|
||||
// Fonctionnalités
|
||||
public boolean isGestionMembres() { return gestionMembres; }
|
||||
public void setGestionMembres(boolean gestionMembres) { this.gestionMembres = gestionMembres; }
|
||||
|
||||
public boolean isGestionCotisations() { return gestionCotisations; }
|
||||
public void setGestionCotisations(boolean gestionCotisations) { this.gestionCotisations = gestionCotisations; }
|
||||
|
||||
public boolean isGestionEvenements() { return gestionEvenements; }
|
||||
public void setGestionEvenements(boolean gestionEvenements) { this.gestionEvenements = gestionEvenements; }
|
||||
|
||||
public boolean isGestionAides() { return gestionAides; }
|
||||
public void setGestionAides(boolean gestionAides) { this.gestionAides = gestionAides; }
|
||||
|
||||
public boolean isRapportsAvances() { return rapportsAvances; }
|
||||
public void setRapportsAvances(boolean rapportsAvances) { this.rapportsAvances = rapportsAvances; }
|
||||
|
||||
public boolean isSupportPrioritaire() { return supportPrioritaire; }
|
||||
public void setSupportPrioritaire(boolean supportPrioritaire) { this.supportPrioritaire = supportPrioritaire; }
|
||||
|
||||
public boolean isSauvegardeAutomatique() { return sauvegardeAutomatique; }
|
||||
public void setSauvegardeAutomatique(boolean sauvegardeAutomatique) { this.sauvegardeAutomatique = sauvegardeAutomatique; }
|
||||
|
||||
public boolean isPersonnalisationAvancee() { return personnalisationAvancee; }
|
||||
public void setPersonnalisationAvancee(boolean personnalisationAvancee) { this.personnalisationAvancee = personnalisationAvancee; }
|
||||
|
||||
public boolean isIntegrationPaiement() { return integrationPaiement; }
|
||||
public void setIntegrationPaiement(boolean integrationPaiement) { this.integrationPaiement = integrationPaiement; }
|
||||
|
||||
public boolean isNotificationsEmail() { return notificationsEmail; }
|
||||
public void setNotificationsEmail(boolean notificationsEmail) { this.notificationsEmail = notificationsEmail; }
|
||||
|
||||
public boolean isNotificationsSMS() { return notificationsSMS; }
|
||||
public void setNotificationsSMS(boolean notificationsSMS) { this.notificationsSMS = notificationsSMS; }
|
||||
|
||||
public boolean isGestionDocuments() { return gestionDocuments; }
|
||||
public void setGestionDocuments(boolean gestionDocuments) { this.gestionDocuments = gestionDocuments; }
|
||||
|
||||
// Métadonnées
|
||||
public LocalDateTime getDateCreation() { return dateCreation; }
|
||||
public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
|
||||
|
||||
public LocalDateTime getDateMiseAJour() { return dateMiseAJour; }
|
||||
public void setDateMiseAJour(LocalDateTime dateMiseAJour) { this.dateMiseAJour = dateMiseAJour; }
|
||||
|
||||
public String getCreePar() { return creePar; }
|
||||
public void setCreePar(String creePar) { this.creePar = creePar; }
|
||||
|
||||
public String getModifiePar() { return modifiePar; }
|
||||
public void setModifiePar(String modifiePar) { this.modifiePar = modifiePar; }
|
||||
|
||||
// Méthodes utilitaires
|
||||
public String getPrixMensuelFormat() {
|
||||
return String.format("%,.0f %s", prixMensuel, deviseCode);
|
||||
}
|
||||
|
||||
public String getPrixAnnuelFormat() {
|
||||
return String.format("%,.0f %s", prixAnnuel, deviseCode);
|
||||
}
|
||||
|
||||
public BigDecimal getEconomieAnnuelle() {
|
||||
if (prixMensuel != null && prixAnnuel != null) {
|
||||
BigDecimal coutMensuelAnnuel = prixMensuel.multiply(BigDecimal.valueOf(12));
|
||||
return coutMensuelAnnuel.subtract(prixAnnuel);
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
|
||||
public String getEconomieAnnuelleFormat() {
|
||||
BigDecimal economie = getEconomieAnnuelle();
|
||||
return String.format("%,.0f %s", economie, deviseCode);
|
||||
}
|
||||
|
||||
public int getPourcentageEconomie() {
|
||||
if (prixMensuel != null && prixAnnuel != null) {
|
||||
BigDecimal coutMensuelAnnuel = prixMensuel.multiply(BigDecimal.valueOf(12));
|
||||
BigDecimal economie = getEconomieAnnuelle();
|
||||
if (coutMensuelAnnuel.compareTo(BigDecimal.ZERO) > 0) {
|
||||
return economie.multiply(BigDecimal.valueOf(100))
|
||||
.divide(coutMensuelAnnuel, 0, java.math.RoundingMode.HALF_UP)
|
||||
.intValue();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
320
src/main/java/dev/lions/unionflow/client/dto/MembreDTO.java
Normal file
320
src/main/java/dev/lions/unionflow/client/dto/MembreDTO.java
Normal file
@@ -0,0 +1,320 @@
|
||||
package dev.lions.unionflow.client.dto;
|
||||
|
||||
import dev.lions.unionflow.client.validation.ValidPhoneNumber;
|
||||
import dev.lions.unionflow.client.validation.ValidMemberNumber;
|
||||
import dev.lions.unionflow.client.validation.ValidationGroups;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MembreDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private UUID id;
|
||||
|
||||
/** Numéro unique du membre - OPTIONNEL (généré automatiquement si non fourni) */
|
||||
@Size(max = 50, message = "Le numéro de membre ne peut pas dépasser 50 caractères")
|
||||
private String numeroMembre;
|
||||
|
||||
/** Nom de famille du membre - OBLIGATOIRE */
|
||||
@NotBlank(message = "Le nom est obligatoire")
|
||||
@Size(min = 2, max = 50, message = "Le nom doit contenir entre 2 et 50 caractères")
|
||||
@Pattern(regexp = "^[a-zA-ZÀ-ÿ\\s\\-']+$", message = "Le nom ne peut contenir que des lettres, espaces, tirets et apostrophes")
|
||||
private String nom;
|
||||
|
||||
/** Prénom du membre - OBLIGATOIRE */
|
||||
@NotBlank(message = "Le prénom est obligatoire")
|
||||
@Size(min = 2, max = 50, message = "Le prénom doit contenir entre 2 et 50 caractères")
|
||||
@Pattern(regexp = "^[a-zA-ZÀ-ÿ\\s\\-']+$", message = "Le prénom ne peut contenir que des lettres, espaces, tirets et apostrophes")
|
||||
private String prenom;
|
||||
|
||||
/** Adresse email du membre - OBLIGATOIRE */
|
||||
@NotBlank(message = "L'email est obligatoire")
|
||||
@Email(message = "Format d'email invalide")
|
||||
@Size(max = 100, message = "L'email ne peut pas dépasser 100 caractères")
|
||||
private String email;
|
||||
|
||||
/** Numéro de téléphone du membre - OPTIONNEL (format flexible) */
|
||||
@Size(max = 20, message = "Le téléphone ne peut pas dépasser 20 caractères")
|
||||
private String telephone;
|
||||
|
||||
/** Date de naissance du membre - OPTIONNELLE (définie par défaut à il y a 18 ans si non fournie) */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@Past(message = "La date de naissance doit être dans le passé")
|
||||
private LocalDate dateNaissance;
|
||||
|
||||
@Size(max = 200, message = "L'adresse ne peut pas dépasser 200 caractères")
|
||||
private String adresse;
|
||||
|
||||
@Size(max = 100, message = "La profession ne peut pas dépasser 100 caractères")
|
||||
private String profession;
|
||||
|
||||
@Size(max = 20, message = "Le statut matrimonial ne peut pas dépasser 20 caractères")
|
||||
private String statutMatrimonial;
|
||||
|
||||
@Size(max = 50, message = "La nationalité ne peut pas dépasser 50 caractères")
|
||||
private String nationalite;
|
||||
|
||||
@Size(max = 50, message = "Le numéro d'identité ne peut pas dépasser 50 caractères")
|
||||
private String numeroIdentite;
|
||||
|
||||
@Size(max = 20, message = "Le type d'identité ne peut pas dépasser 20 caractères")
|
||||
private String typeIdentite;
|
||||
|
||||
/** URL de la photo de profil - OPTIONNELLE */
|
||||
@Size(max = 255, message = "L'URL de la photo ne peut pas dépasser 255 caractères")
|
||||
private String photoUrl;
|
||||
|
||||
/** Statut du membre - OBLIGATOIRE */
|
||||
@NotNull(message = "Le statut est obligatoire")
|
||||
private String statut;
|
||||
|
||||
/** Identifiant de l'association - OBLIGATOIRE */
|
||||
@NotNull(message = "L'association est obligatoire")
|
||||
private UUID associationId;
|
||||
|
||||
/** Nom de l'association (lecture seule) */
|
||||
private String associationNom;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateInscription;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDerniereModification;
|
||||
|
||||
private String creePar;
|
||||
private String modifiePar;
|
||||
|
||||
private Boolean membreBureau = false;
|
||||
private Boolean responsable = false;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate dateAdhesion;
|
||||
|
||||
@Size(max = 50, message = "La région ne peut pas dépasser 50 caractères")
|
||||
private String region;
|
||||
|
||||
@Size(max = 50, message = "La ville ne peut pas dépasser 50 caractères")
|
||||
private String ville;
|
||||
|
||||
@Size(max = 50, message = "Le quartier ne peut pas dépasser 50 caractères")
|
||||
private String quartier;
|
||||
|
||||
@Size(max = 50, message = "Le rôle ne peut pas dépasser 50 caractères")
|
||||
private String role;
|
||||
|
||||
// Constructeurs
|
||||
public MembreDTO() {}
|
||||
|
||||
public MembreDTO(String numeroMembre, String nom, String prenom, String email) {
|
||||
this.numeroMembre = numeroMembre;
|
||||
this.nom = nom;
|
||||
this.prenom = prenom;
|
||||
this.email = email;
|
||||
this.statut = "ACTIF";
|
||||
this.dateInscription = LocalDateTime.now();
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public UUID getId() { return id; }
|
||||
public void setId(UUID id) { this.id = id; }
|
||||
|
||||
public String getNumeroMembre() { return numeroMembre; }
|
||||
public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
|
||||
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public String getPrenom() { return prenom; }
|
||||
public void setPrenom(String prenom) { this.prenom = prenom; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public String getTelephone() { return telephone; }
|
||||
public void setTelephone(String telephone) { this.telephone = telephone; }
|
||||
|
||||
public LocalDate getDateNaissance() { return dateNaissance; }
|
||||
public void setDateNaissance(LocalDate dateNaissance) { this.dateNaissance = dateNaissance; }
|
||||
|
||||
public String getAdresse() { return adresse; }
|
||||
public void setAdresse(String adresse) { this.adresse = adresse; }
|
||||
|
||||
public String getProfession() { return profession; }
|
||||
public void setProfession(String profession) { this.profession = profession; }
|
||||
|
||||
public String getStatutMatrimonial() { return statutMatrimonial; }
|
||||
public void setStatutMatrimonial(String statutMatrimonial) { this.statutMatrimonial = statutMatrimonial; }
|
||||
|
||||
public String getNationalite() { return nationalite; }
|
||||
public void setNationalite(String nationalite) { this.nationalite = nationalite; }
|
||||
|
||||
public String getNumeroIdentite() { return numeroIdentite; }
|
||||
public void setNumeroIdentite(String numeroIdentite) { this.numeroIdentite = numeroIdentite; }
|
||||
|
||||
public String getTypeIdentite() { return typeIdentite; }
|
||||
public void setTypeIdentite(String typeIdentite) { this.typeIdentite = typeIdentite; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public UUID getAssociationId() { return associationId; }
|
||||
public void setAssociationId(UUID associationId) { this.associationId = associationId; }
|
||||
|
||||
public String getAssociationNom() { return associationNom; }
|
||||
public void setAssociationNom(String associationNom) { this.associationNom = associationNom; }
|
||||
|
||||
public LocalDateTime getDateInscription() { return dateInscription; }
|
||||
public void setDateInscription(LocalDateTime dateInscription) { this.dateInscription = dateInscription; }
|
||||
|
||||
public LocalDateTime getDateDerniereModification() { return dateDerniereModification; }
|
||||
public void setDateDerniereModification(LocalDateTime dateDerniereModification) { this.dateDerniereModification = dateDerniereModification; }
|
||||
|
||||
public String getCreePar() { return creePar; }
|
||||
public void setCreePar(String creePar) { this.creePar = creePar; }
|
||||
|
||||
public String getModifiePar() { return modifiePar; }
|
||||
public void setModifiePar(String modifiePar) { this.modifiePar = modifiePar; }
|
||||
|
||||
public String getPhotoUrl() { return photoUrl; }
|
||||
public void setPhotoUrl(String photoUrl) { this.photoUrl = photoUrl; }
|
||||
|
||||
public Boolean getMembreBureau() { return membreBureau; }
|
||||
public void setMembreBureau(Boolean membreBureau) { this.membreBureau = membreBureau; }
|
||||
|
||||
public Boolean getResponsable() { return responsable; }
|
||||
public void setResponsable(Boolean responsable) { this.responsable = responsable; }
|
||||
|
||||
public LocalDate getDateAdhesion() { return dateAdhesion; }
|
||||
public void setDateAdhesion(LocalDate dateAdhesion) { this.dateAdhesion = dateAdhesion; }
|
||||
|
||||
public String getRegion() { return region; }
|
||||
public void setRegion(String region) { this.region = region; }
|
||||
|
||||
public String getVille() { return ville; }
|
||||
public void setVille(String ville) { this.ville = ville; }
|
||||
|
||||
public String getQuartier() { return quartier; }
|
||||
public void setQuartier(String quartier) { this.quartier = quartier; }
|
||||
|
||||
public String getRole() { return role; }
|
||||
public void setRole(String role) { this.role = role; }
|
||||
|
||||
// Propriétés dérivées
|
||||
public String getNomComplet() {
|
||||
return (prenom != null ? prenom : "") + " " + (nom != null ? nom : "");
|
||||
}
|
||||
|
||||
public String getInitiales() {
|
||||
StringBuilder initiales = new StringBuilder();
|
||||
if (prenom != null && !prenom.isEmpty()) {
|
||||
initiales.append(prenom.charAt(0));
|
||||
}
|
||||
if (nom != null && !nom.isEmpty()) {
|
||||
initiales.append(nom.charAt(0));
|
||||
}
|
||||
return initiales.toString().toUpperCase();
|
||||
}
|
||||
|
||||
public String getStatutLibelle() {
|
||||
return switch (statut != null ? statut : "") {
|
||||
case "ACTIF" -> "Actif";
|
||||
case "INACTIF" -> "Inactif";
|
||||
case "SUSPENDU" -> "Suspendu";
|
||||
case "RADIE" -> "Radié";
|
||||
default -> statut;
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutSeverity() {
|
||||
return switch (statut != null ? statut : "") {
|
||||
case "ACTIF" -> "success";
|
||||
case "INACTIF" -> "warning";
|
||||
case "SUSPENDU" -> "danger";
|
||||
case "RADIE" -> "secondary";
|
||||
default -> "info";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutIcon() {
|
||||
return switch (statut != null ? statut : "") {
|
||||
case "ACTIF" -> "pi-check";
|
||||
case "INACTIF" -> "pi-times";
|
||||
case "SUSPENDU" -> "pi-ban";
|
||||
case "RADIE" -> "pi-trash";
|
||||
default -> "pi-question";
|
||||
};
|
||||
}
|
||||
|
||||
// Propriétés pour le type de membre (à adapter selon votre logique métier)
|
||||
public String getTypeMembre() {
|
||||
// Retourne le type basé sur les rôles
|
||||
if (Boolean.TRUE.equals(responsable)) return "Responsable";
|
||||
if (Boolean.TRUE.equals(membreBureau)) return "Bureau";
|
||||
return "Membre";
|
||||
}
|
||||
|
||||
public String getTypeSeverity() {
|
||||
if (Boolean.TRUE.equals(responsable)) return "danger";
|
||||
if (Boolean.TRUE.equals(membreBureau)) return "warning";
|
||||
return "info";
|
||||
}
|
||||
|
||||
public String getTypeIcon() {
|
||||
if (Boolean.TRUE.equals(responsable)) return "pi-star-fill";
|
||||
if (Boolean.TRUE.equals(membreBureau)) return "pi-briefcase";
|
||||
return "pi-user";
|
||||
}
|
||||
|
||||
// Propriétés pour l'entité (association)
|
||||
public String getEntite() {
|
||||
return associationNom != null ? associationNom : "Non renseigné";
|
||||
}
|
||||
|
||||
// Propriétés pour l'ancienneté
|
||||
public String getAnciennete() {
|
||||
if (dateInscription == null) return "N/A";
|
||||
long jours = java.time.temporal.ChronoUnit.DAYS.between(dateInscription.toLocalDate(), LocalDate.now());
|
||||
if (jours < 30) return jours + " jours";
|
||||
if (jours < 365) return (jours / 30) + " mois";
|
||||
return (jours / 365) + " ans";
|
||||
}
|
||||
|
||||
// Propriétés pour les cotisations - À implémenter avec les vraies données du module Cotisations
|
||||
public String getCotisationStatut() {
|
||||
return "N/A"; // TODO: Intégrer avec le module Cotisations
|
||||
}
|
||||
|
||||
public String getCotisationColor() {
|
||||
return "text-500"; // Gris neutre par défaut
|
||||
}
|
||||
|
||||
public String getDernierPaiement() {
|
||||
return "N/A"; // TODO: Intégrer avec le module Cotisations
|
||||
}
|
||||
|
||||
// Propriétés pour la participation aux événements - À implémenter avec les vraies données du module Événements
|
||||
public String getTauxParticipation() {
|
||||
return "0"; // TODO: Intégrer avec le module Événements
|
||||
}
|
||||
|
||||
public String getEvenementsAnnee() {
|
||||
return "0"; // TODO: Intégrer avec le module Événements
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MembreDTO{" +
|
||||
"id=" + id +
|
||||
", numeroMembre='" + numeroMembre + '\'' +
|
||||
", nom='" + nom + '\'' +
|
||||
", prenom='" + prenom + '\'' +
|
||||
", email='" + email + '\'' +
|
||||
", statut='" + statut + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package dev.lions.unionflow.client.dto;
|
||||
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SouscriptionDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public enum StatutSouscription {
|
||||
ACTIVE("Actif", "text-green-600", "bg-green-100"),
|
||||
SUSPENDUE("Suspendue", "text-orange-600", "bg-orange-100"),
|
||||
EXPIREE("Expirée", "text-red-600", "bg-red-100"),
|
||||
EN_ATTENTE_PAIEMENT("En attente de paiement", "text-blue-600", "bg-blue-100"),
|
||||
ANNULEE("Annulée", "text-gray-600", "bg-gray-100");
|
||||
|
||||
private final String libelle;
|
||||
private final String couleurTexte;
|
||||
private final String couleurFond;
|
||||
|
||||
StatutSouscription(String libelle, String couleurTexte, String couleurFond) {
|
||||
this.libelle = libelle;
|
||||
this.couleurTexte = couleurTexte;
|
||||
this.couleurFond = couleurFond;
|
||||
}
|
||||
|
||||
public String getLibelle() { return libelle; }
|
||||
public String getCouleurTexte() { return couleurTexte; }
|
||||
public String getCouleurFond() { return couleurFond; }
|
||||
}
|
||||
|
||||
public enum TypeFacturation {
|
||||
MENSUEL("Mensuel"),
|
||||
ANNUEL("Annuel");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
TypeFacturation(String libelle) {
|
||||
this.libelle = libelle;
|
||||
}
|
||||
|
||||
public String getLibelle() { return libelle; }
|
||||
}
|
||||
|
||||
private UUID id;
|
||||
|
||||
@NotNull
|
||||
private UUID organisationId;
|
||||
private String organisationNom;
|
||||
|
||||
@NotNull
|
||||
private UUID formulaireId;
|
||||
private String formulaireNom;
|
||||
|
||||
@NotNull
|
||||
private StatutSouscription statut;
|
||||
|
||||
@NotNull
|
||||
private TypeFacturation typeFacturation;
|
||||
|
||||
@NotNull
|
||||
private LocalDate dateDebut;
|
||||
|
||||
@NotNull
|
||||
private LocalDate dateFin;
|
||||
|
||||
private LocalDate dateDernierPaiement;
|
||||
private LocalDate dateProchainPaiement;
|
||||
|
||||
@NotNull
|
||||
private Integer quotaMaxMembres;
|
||||
|
||||
private Integer membresActuels = 0;
|
||||
|
||||
@NotNull
|
||||
private BigDecimal montantSouscription;
|
||||
|
||||
private String deviseCode = "XOF";
|
||||
|
||||
private String numeroFacture;
|
||||
private String referencePaiement;
|
||||
|
||||
// Informations de renouvellement automatique
|
||||
private boolean renouvellementAutomatique = false;
|
||||
private String methodePaiementDefaut;
|
||||
|
||||
// Notifications
|
||||
private boolean notificationExpiration = true;
|
||||
private boolean notificationQuotaAtteint = true;
|
||||
private int joursAvantNotificationExpiration = 30;
|
||||
|
||||
// Audit
|
||||
private LocalDateTime dateCreation;
|
||||
private LocalDateTime dateMiseAJour;
|
||||
private String creePar;
|
||||
private String modifiePar;
|
||||
|
||||
public SouscriptionDTO() {}
|
||||
|
||||
// Getters et Setters
|
||||
public UUID getId() { return id; }
|
||||
public void setId(UUID id) { this.id = id; }
|
||||
|
||||
public UUID getOrganisationId() { return organisationId; }
|
||||
public void setOrganisationId(UUID organisationId) { this.organisationId = organisationId; }
|
||||
|
||||
public String getOrganisationNom() { return organisationNom; }
|
||||
public void setOrganisationNom(String organisationNom) { this.organisationNom = organisationNom; }
|
||||
|
||||
public UUID getFormulaireId() { return formulaireId; }
|
||||
public void setFormulaireId(UUID formulaireId) { this.formulaireId = formulaireId; }
|
||||
|
||||
public String getFormulaireNom() { return formulaireNom; }
|
||||
public void setFormulaireNom(String formulaireNom) { this.formulaireNom = formulaireNom; }
|
||||
|
||||
public StatutSouscription getStatut() { return statut; }
|
||||
public void setStatut(StatutSouscription statut) { this.statut = statut; }
|
||||
|
||||
public TypeFacturation getTypeFacturation() { return typeFacturation; }
|
||||
public void setTypeFacturation(TypeFacturation typeFacturation) { this.typeFacturation = typeFacturation; }
|
||||
|
||||
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 LocalDate getDateDernierPaiement() { return dateDernierPaiement; }
|
||||
public void setDateDernierPaiement(LocalDate dateDernierPaiement) { this.dateDernierPaiement = dateDernierPaiement; }
|
||||
|
||||
public LocalDate getDateProchainPaiement() { return dateProchainPaiement; }
|
||||
public void setDateProchainPaiement(LocalDate dateProchainPaiement) { this.dateProchainPaiement = dateProchainPaiement; }
|
||||
|
||||
public Integer getQuotaMaxMembres() { return quotaMaxMembres; }
|
||||
public void setQuotaMaxMembres(Integer quotaMaxMembres) { this.quotaMaxMembres = quotaMaxMembres; }
|
||||
|
||||
public Integer getMembresActuels() { return membresActuels; }
|
||||
public void setMembresActuels(Integer membresActuels) { this.membresActuels = membresActuels; }
|
||||
|
||||
public BigDecimal getMontantSouscription() { return montantSouscription; }
|
||||
public void setMontantSouscription(BigDecimal montantSouscription) { this.montantSouscription = montantSouscription; }
|
||||
|
||||
public String getDeviseCode() { return deviseCode; }
|
||||
public void setDeviseCode(String deviseCode) { this.deviseCode = deviseCode; }
|
||||
|
||||
public String getNumeroFacture() { return numeroFacture; }
|
||||
public void setNumeroFacture(String numeroFacture) { this.numeroFacture = numeroFacture; }
|
||||
|
||||
public String getReferencePaiement() { return referencePaiement; }
|
||||
public void setReferencePaiement(String referencePaiement) { this.referencePaiement = referencePaiement; }
|
||||
|
||||
public boolean isRenouvellementAutomatique() { return renouvellementAutomatique; }
|
||||
public void setRenouvellementAutomatique(boolean renouvellementAutomatique) { this.renouvellementAutomatique = renouvellementAutomatique; }
|
||||
|
||||
public String getMethodePaiementDefaut() { return methodePaiementDefaut; }
|
||||
public void setMethodePaiementDefaut(String methodePaiementDefaut) { this.methodePaiementDefaut = methodePaiementDefaut; }
|
||||
|
||||
public boolean isNotificationExpiration() { return notificationExpiration; }
|
||||
public void setNotificationExpiration(boolean notificationExpiration) { this.notificationExpiration = notificationExpiration; }
|
||||
|
||||
public boolean isNotificationQuotaAtteint() { return notificationQuotaAtteint; }
|
||||
public void setNotificationQuotaAtteint(boolean notificationQuotaAtteint) { this.notificationQuotaAtteint = notificationQuotaAtteint; }
|
||||
|
||||
public int getJoursAvantNotificationExpiration() { return joursAvantNotificationExpiration; }
|
||||
public void setJoursAvantNotificationExpiration(int joursAvantNotificationExpiration) { this.joursAvantNotificationExpiration = joursAvantNotificationExpiration; }
|
||||
|
||||
public LocalDateTime getDateCreation() { return dateCreation; }
|
||||
public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
|
||||
|
||||
public LocalDateTime getDateMiseAJour() { return dateMiseAJour; }
|
||||
public void setDateMiseAJour(LocalDateTime dateMiseAJour) { this.dateMiseAJour = dateMiseAJour; }
|
||||
|
||||
public String getCreePar() { return creePar; }
|
||||
public void setCreePar(String creePar) { this.creePar = creePar; }
|
||||
|
||||
public String getModifiePar() { return modifiePar; }
|
||||
public void setModifiePar(String modifiePar) { this.modifiePar = modifiePar; }
|
||||
|
||||
// Méthodes utilitaires
|
||||
public boolean isActive() {
|
||||
return statut == StatutSouscription.ACTIVE && !isExpiree();
|
||||
}
|
||||
|
||||
public boolean isExpiree() {
|
||||
return LocalDate.now().isAfter(dateFin);
|
||||
}
|
||||
|
||||
public boolean isQuotaAtteint() {
|
||||
return membresActuels != null && quotaMaxMembres != null &&
|
||||
membresActuels >= quotaMaxMembres;
|
||||
}
|
||||
|
||||
public int getMembresRestants() {
|
||||
if (membresActuels != null && quotaMaxMembres != null) {
|
||||
return Math.max(0, quotaMaxMembres - membresActuels);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getPourcentageUtilisation() {
|
||||
if (membresActuels != null && quotaMaxMembres != null && quotaMaxMembres > 0) {
|
||||
return (membresActuels * 100) / quotaMaxMembres;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getMontantFormat() {
|
||||
if (montantSouscription != null) {
|
||||
return String.format("%,.0f %s", montantSouscription, deviseCode);
|
||||
}
|
||||
return "0 " + deviseCode;
|
||||
}
|
||||
|
||||
public String getStatutCouleurClass() {
|
||||
return statut != null ? statut.getCouleurTexte() : "text-gray-600";
|
||||
}
|
||||
|
||||
public String getStatutFondClass() {
|
||||
return statut != null ? statut.getCouleurFond() : "bg-gray-100";
|
||||
}
|
||||
|
||||
public String getStatutLibelle() {
|
||||
return statut != null ? statut.getLibelle() : "Inconnu";
|
||||
}
|
||||
|
||||
public long getJoursRestants() {
|
||||
if (dateFin != null) {
|
||||
return ChronoUnit.DAYS.between(LocalDate.now(), dateFin);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isExpirationProche() {
|
||||
long joursRestants = getJoursRestants();
|
||||
return joursRestants <= joursAvantNotificationExpiration && joursRestants > 0;
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
|
||||
102
src/main/java/dev/lions/unionflow/client/dto/WaveBalanceDTO.java
Normal file
102
src/main/java/dev/lions/unionflow/client/dto/WaveBalanceDTO.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package dev.lions.unionflow.client.dto.auth;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
public class LoginRequest {
|
||||
|
||||
@NotBlank(message = "L'email ou nom d'utilisateur est requis")
|
||||
@Size(min = 3, max = 100, message = "L'email ou nom d'utilisateur doit contenir entre 3 et 100 caractères")
|
||||
private String username;
|
||||
|
||||
@NotBlank(message = "Le mot de passe est requis")
|
||||
@Size(min = 6, message = "Le mot de passe doit contenir au moins 6 caractères")
|
||||
private String password;
|
||||
|
||||
@NotBlank(message = "Le type de compte est requis")
|
||||
private String typeCompte;
|
||||
|
||||
private boolean rememberMe;
|
||||
|
||||
public LoginRequest() {}
|
||||
|
||||
public LoginRequest(String username, String password, String typeCompte) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
this.typeCompte = typeCompte;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getTypeCompte() {
|
||||
return typeCompte;
|
||||
}
|
||||
|
||||
public void setTypeCompte(String typeCompte) {
|
||||
this.typeCompte = typeCompte;
|
||||
}
|
||||
|
||||
public boolean isRememberMe() {
|
||||
return rememberMe;
|
||||
}
|
||||
|
||||
public void setRememberMe(boolean rememberMe) {
|
||||
this.rememberMe = rememberMe;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
package dev.lions.unionflow.client.dto.auth;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class LoginResponse {
|
||||
|
||||
private String accessToken;
|
||||
private String refreshToken;
|
||||
private String tokenType = "Bearer";
|
||||
private Long expiresIn;
|
||||
private LocalDateTime expirationDate;
|
||||
|
||||
private UserInfo user;
|
||||
|
||||
public LoginResponse() {}
|
||||
|
||||
public LoginResponse(String accessToken, String refreshToken, Long expiresIn, UserInfo user) {
|
||||
this.accessToken = accessToken;
|
||||
this.refreshToken = refreshToken;
|
||||
this.expiresIn = expiresIn;
|
||||
this.user = user;
|
||||
this.expirationDate = LocalDateTime.now().plusSeconds(expiresIn);
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
public void setTokenType(String tokenType) {
|
||||
this.tokenType = tokenType;
|
||||
}
|
||||
|
||||
public Long getExpiresIn() {
|
||||
return expiresIn;
|
||||
}
|
||||
|
||||
public void setExpiresIn(Long expiresIn) {
|
||||
this.expiresIn = expiresIn;
|
||||
if (expiresIn != null) {
|
||||
this.expirationDate = LocalDateTime.now().plusSeconds(expiresIn);
|
||||
}
|
||||
}
|
||||
|
||||
public LocalDateTime getExpirationDate() {
|
||||
return expirationDate;
|
||||
}
|
||||
|
||||
public void setExpirationDate(LocalDateTime expirationDate) {
|
||||
this.expirationDate = expirationDate;
|
||||
}
|
||||
|
||||
public UserInfo getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(UserInfo user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public boolean isExpired() {
|
||||
return expirationDate != null && LocalDateTime.now().isAfter(expirationDate);
|
||||
}
|
||||
|
||||
public static class UserInfo {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
private String prenom;
|
||||
private String email;
|
||||
private String username;
|
||||
private String typeCompte;
|
||||
private List<String> roles;
|
||||
private List<String> permissions;
|
||||
private EntiteInfo entite;
|
||||
|
||||
public UserInfo() {}
|
||||
|
||||
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 getPrenom() {
|
||||
return prenom;
|
||||
}
|
||||
|
||||
public void setPrenom(String prenom) {
|
||||
this.prenom = prenom;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getTypeCompte() {
|
||||
return typeCompte;
|
||||
}
|
||||
|
||||
public void setTypeCompte(String typeCompte) {
|
||||
this.typeCompte = typeCompte;
|
||||
}
|
||||
|
||||
public List<String> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<String> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
public List<String> getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public void setPermissions(List<String> permissions) {
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public EntiteInfo getEntite() {
|
||||
return entite;
|
||||
}
|
||||
|
||||
public void setEntite(EntiteInfo entite) {
|
||||
this.entite = entite;
|
||||
}
|
||||
|
||||
public String getNomComplet() {
|
||||
if (prenom != null && nom != null) {
|
||||
return prenom + " " + nom;
|
||||
}
|
||||
return nom != null ? nom : username;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EntiteInfo {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
private String type;
|
||||
private String pays;
|
||||
private String ville;
|
||||
|
||||
public EntiteInfo() {}
|
||||
|
||||
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 String getPays() {
|
||||
return pays;
|
||||
}
|
||||
|
||||
public void setPays(String pays) {
|
||||
this.pays = pays;
|
||||
}
|
||||
|
||||
public String getVille() {
|
||||
return ville;
|
||||
}
|
||||
|
||||
public void setVille(String ville) {
|
||||
this.ville = ville;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package dev.lions.unionflow.client.exception;
|
||||
|
||||
import jakarta.faces.FacesException;
|
||||
import jakarta.faces.application.ViewExpiredException;
|
||||
import jakarta.faces.context.ExceptionHandler;
|
||||
import jakarta.faces.context.ExceptionHandlerWrapper;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.faces.event.ExceptionQueuedEvent;
|
||||
import jakarta.faces.event.ExceptionQueuedEventContext;
|
||||
import java.util.Iterator;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class ViewExpiredExceptionHandler extends ExceptionHandlerWrapper {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(ViewExpiredExceptionHandler.class.getName());
|
||||
private ExceptionHandler wrapped;
|
||||
|
||||
public ViewExpiredExceptionHandler(ExceptionHandler wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExceptionHandler getWrapped() {
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle() throws FacesException {
|
||||
Iterator<ExceptionQueuedEvent> iterator = getUnhandledExceptionQueuedEvents().iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
ExceptionQueuedEvent event = iterator.next();
|
||||
ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
|
||||
Throwable throwable = context.getException();
|
||||
|
||||
if (throwable instanceof ViewExpiredException) {
|
||||
ViewExpiredException vee = (ViewExpiredException) throwable;
|
||||
FacesContext facesContext = FacesContext.getCurrentInstance();
|
||||
|
||||
try {
|
||||
LOG.log(Level.INFO, "ViewExpiredException interceptée pour la vue: {0}", vee.getViewId());
|
||||
|
||||
// Vérifier que FacesContext et ExternalContext sont disponibles
|
||||
if (facesContext != null && facesContext.getExternalContext() != null) {
|
||||
// Stocker l'URL demandée pour redirection après connexion si possible
|
||||
String originalURL = vee.getViewId();
|
||||
try {
|
||||
if (facesContext.getExternalContext().getSessionMap() != null) {
|
||||
facesContext.getExternalContext().getSessionMap().put("redirectURL", originalURL);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.log(Level.WARNING, "Impossible de stocker l'URL de redirection: {0}", e.getMessage());
|
||||
}
|
||||
|
||||
// Rediriger vers la racine qui déclenchera Keycloak
|
||||
try {
|
||||
String redirectURL = "/";
|
||||
facesContext.getExternalContext().redirect(
|
||||
facesContext.getExternalContext().getRequestContextPath() + redirectURL
|
||||
);
|
||||
facesContext.responseComplete();
|
||||
} catch (Exception e) {
|
||||
LOG.log(Level.SEVERE, "Erreur lors de la redirection: {0}", e.getMessage());
|
||||
// Fallback: essayer une redirection simple
|
||||
try {
|
||||
facesContext.getExternalContext().redirect("/");
|
||||
facesContext.responseComplete();
|
||||
} catch (Exception fallbackException) {
|
||||
LOG.log(Level.SEVERE, "Impossible de rediriger vers la racine: {0}", fallbackException.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.log(Level.SEVERE, "Erreur dans ViewExpiredExceptionHandler: {0}", e.getMessage());
|
||||
} finally {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Laisser le parent gérer les autres exceptions
|
||||
getWrapped().handle();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.lions.unionflow.client.exception;
|
||||
|
||||
import jakarta.faces.context.ExceptionHandler;
|
||||
import jakarta.faces.context.ExceptionHandlerFactory;
|
||||
|
||||
public class ViewExpiredExceptionHandlerFactory extends ExceptionHandlerFactory {
|
||||
|
||||
private ExceptionHandlerFactory parent;
|
||||
|
||||
public ViewExpiredExceptionHandlerFactory(ExceptionHandlerFactory parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExceptionHandler getExceptionHandler() {
|
||||
return new ViewExpiredExceptionHandler(parent.getExceptionHandler());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
package dev.lions.unionflow.client.security;
|
||||
|
||||
import dev.lions.unionflow.client.view.UserSession;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.servlet.*;
|
||||
import jakarta.servlet.annotation.WebFilter;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Filtre d'authentification pour vérifications supplémentaires
|
||||
* Note: Avec Keycloak OIDC, l'authentification principale est gérée par Quarkus
|
||||
* Ce filtre peut être utilisé pour des vérifications de permissions supplémentaires
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
*/
|
||||
@WebFilter(urlPatterns = {"/pages/secure/*", "/pages/admin/*", "/pages/super-admin/*", "/pages/membre/*"})
|
||||
public class AuthenticationFilter implements Filter {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(AuthenticationFilter.class.getName());
|
||||
|
||||
@Inject
|
||||
private UserSession userSession;
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||
|
||||
String requestURI = httpRequest.getRequestURI();
|
||||
|
||||
// Laisser Quarkus OIDC appliquer l'authentification (rediriger vers Keycloak si nécessaire)
|
||||
// Ici, si l'utilisateur n'est pas encore authentifié, on ne force PAS une redirection custom
|
||||
// pour éviter les boucles / conflits. On délègue au mécanisme Quarkus défini via
|
||||
// quarkus.http.auth.permission.* et quarkus.oidc.*
|
||||
if (!isAuthenticated()) {
|
||||
LOGGER.fine("Requête non authentifiée sur " + requestURI + ", délégation à Quarkus OIDC.");
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
// Vérifier les autorisations spécifiques basées sur les rôles
|
||||
// Note: /pages/secure/access-denied.xhtml est autorisé car elle fait partie de /pages/secure/
|
||||
// qui est accessible à tous les utilisateurs authentifiés
|
||||
if (!hasRequiredPermissions(requestURI)) {
|
||||
LOGGER.warning("Permissions insuffisantes pour: " + requestURI +
|
||||
" (Utilisateur: " + (userSession != null ? userSession.getUsername() : "null") +
|
||||
", Type: " + (userSession != null ? userSession.getTypeCompte() : "null") +
|
||||
", Rôles: " + (userSession != null && userSession.getRoles() != null ? userSession.getRoles() : "null") + ")");
|
||||
httpResponse.sendRedirect(httpRequest.getContextPath() + "/pages/secure/access-denied.xhtml");
|
||||
return;
|
||||
}
|
||||
|
||||
// Continuer la chaîne de filtres
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private boolean isAuthenticated() {
|
||||
// Avec Keycloak OIDC, UserSession vérifie automatiquement l'authentification via JsonWebToken
|
||||
return userSession != null && userSession.isAuthenticated();
|
||||
}
|
||||
|
||||
private boolean hasRequiredPermissions(String requestURI) {
|
||||
// Vérifier que userSession est disponible
|
||||
if (userSession == null) {
|
||||
LOGGER.warning("UserSession est null lors de la vérification des permissions pour: " + requestURI);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pages super-admin : nécessitent le rôle SUPER_ADMIN
|
||||
if (requestURI.contains("/pages/super-admin/")) {
|
||||
boolean isSuperAdmin = userSession.isSuperAdmin();
|
||||
LOGGER.fine("Vérification SUPER_ADMIN pour " + requestURI + ": " + isSuperAdmin +
|
||||
" (Type: " + userSession.getTypeCompte() + ", Rôles: " + userSession.getRoles() + ")");
|
||||
return isSuperAdmin;
|
||||
}
|
||||
|
||||
// Pages admin : nécessitent ADMIN_ENTITE ou SUPER_ADMIN
|
||||
if (requestURI.contains("/pages/admin/")) {
|
||||
boolean isAdmin = userSession.isAdmin();
|
||||
LOGGER.fine("Vérification ADMIN pour " + requestURI + ": " + isAdmin +
|
||||
" (Type: " + userSession.getTypeCompte() + ", Rôles: " + userSession.getRoles() + ")");
|
||||
return isAdmin;
|
||||
}
|
||||
|
||||
// Pages membre : nécessitent le rôle MEMBRE ou tout utilisateur authentifié
|
||||
if (requestURI.contains("/pages/membre/")) {
|
||||
boolean isMembre = userSession.isMembre();
|
||||
LOGGER.fine("Vérification MEMBRE pour " + requestURI + ": " + isMembre +
|
||||
" (Type: " + userSession.getTypeCompte() + ", Rôles: " + userSession.getRoles() + ")");
|
||||
return isMembre;
|
||||
}
|
||||
|
||||
// Pages sécurisées générales - tout utilisateur authentifié peut y accéder
|
||||
if (requestURI.contains("/pages/secure/")) {
|
||||
LOGGER.fine("Accès autorisé à la page sécurisée générale: " + requestURI);
|
||||
return true;
|
||||
}
|
||||
|
||||
LOGGER.warning("URI non reconnue dans hasRequiredPermissions: " + requestURI);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
LOGGER.info("Filtre d'authentification initialisé");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
LOGGER.info("Filtre d'authentification détruit");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package dev.lions.unionflow.client.security;
|
||||
|
||||
import jakarta.annotation.Priority;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.client.ClientRequestContext;
|
||||
import jakarta.ws.rs.client.ClientRequestFilter;
|
||||
import jakarta.ws.rs.core.HttpHeaders;
|
||||
import jakarta.ws.rs.ext.Provider;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Provider
|
||||
@Priority(1000)
|
||||
public class JwtClientRequestFilter implements ClientRequestFilter {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(JwtClientRequestFilter.class.getName());
|
||||
|
||||
@Inject
|
||||
private JwtTokenManager tokenManager;
|
||||
|
||||
@Override
|
||||
public void filter(ClientRequestContext requestContext) throws IOException {
|
||||
if (tokenManager == null) {
|
||||
LOGGER.fine("JwtTokenManager non disponible, requête sans authentification");
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isAuthEndpoint(String path) {
|
||||
return path != null && (
|
||||
path.contains("/auth/login") ||
|
||||
path.contains("/auth/register") ||
|
||||
path.contains("/auth/refresh") ||
|
||||
path.contains("/public/")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package dev.lions.unionflow.client.security;
|
||||
|
||||
import dev.lions.unionflow.client.dto.auth.LoginResponse;
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("jwtTokenManager")
|
||||
@SessionScoped
|
||||
public class JwtTokenManager implements Serializable {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(JwtTokenManager.class.getName());
|
||||
|
||||
@Inject
|
||||
private TokenRefreshService tokenRefreshService;
|
||||
|
||||
private String accessToken;
|
||||
private String refreshToken;
|
||||
private LocalDateTime expirationDate;
|
||||
private String tokenType = "Bearer";
|
||||
|
||||
public void setTokens(LoginResponse loginResponse) {
|
||||
this.accessToken = loginResponse.getAccessToken();
|
||||
this.refreshToken = loginResponse.getRefreshToken();
|
||||
this.expirationDate = loginResponse.getExpirationDate();
|
||||
this.tokenType = loginResponse.getTokenType();
|
||||
|
||||
// Enregistrer le token dans le service global
|
||||
String sessionId = getSessionId();
|
||||
if (sessionId != null) {
|
||||
tokenRefreshService.registerToken(sessionId,
|
||||
this.accessToken,
|
||||
this.refreshToken,
|
||||
loginResponse.getExpiresIn());
|
||||
}
|
||||
|
||||
LOGGER.info("Tokens JWT mis à jour. Expiration: " + expirationDate);
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public String getAuthorizationHeader() {
|
||||
if (accessToken != null) {
|
||||
return tokenType + " " + accessToken;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isTokenValid() {
|
||||
if (accessToken == null || expirationDate == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Considérer le token comme expiré 30 secondes avant l'expiration réelle
|
||||
LocalDateTime expirationWithBuffer = expirationDate.minusSeconds(30);
|
||||
return LocalDateTime.now().isBefore(expirationWithBuffer);
|
||||
}
|
||||
|
||||
public boolean needsRefresh() {
|
||||
if (accessToken == null || expirationDate == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rafraîchir le token 5 minutes avant l'expiration
|
||||
LocalDateTime refreshThreshold = expirationDate.minusMinutes(5);
|
||||
return LocalDateTime.now().isAfter(refreshThreshold);
|
||||
}
|
||||
|
||||
public long getTimeUntilExpiration() {
|
||||
if (expirationDate == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
if (now.isAfter(expirationDate)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return java.time.Duration.between(now, expirationDate).getSeconds();
|
||||
}
|
||||
|
||||
public void clearTokens() {
|
||||
this.accessToken = null;
|
||||
this.refreshToken = null;
|
||||
this.expirationDate = null;
|
||||
|
||||
// Supprimer le token du service global
|
||||
String sessionId = getSessionId();
|
||||
if (sessionId != null) {
|
||||
tokenRefreshService.removeToken(sessionId);
|
||||
}
|
||||
|
||||
LOGGER.info("Tokens JWT supprimés");
|
||||
}
|
||||
|
||||
private String getSessionId() {
|
||||
try {
|
||||
FacesContext facesContext = FacesContext.getCurrentInstance();
|
||||
if (facesContext != null && facesContext.getExternalContext() != null) {
|
||||
return facesContext.getExternalContext().getSessionId(false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.fine("Impossible de récupérer l'ID de session: " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasValidTokens() {
|
||||
return accessToken != null && refreshToken != null && isTokenValid();
|
||||
}
|
||||
|
||||
public LocalDateTime getExpirationDate() {
|
||||
return expirationDate;
|
||||
}
|
||||
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
package dev.lions.unionflow.client.security;
|
||||
|
||||
import dev.lions.unionflow.client.view.UserSession;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Named("permissionChecker")
|
||||
@RequestScoped
|
||||
public class PermissionChecker implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Inject
|
||||
private UserSession userSession;
|
||||
|
||||
// Vérifications basées sur le rôle utilisateur
|
||||
public boolean hasRole(String role) {
|
||||
if (userSession == null || !userSession.isAuthenticated()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String userRole = userSession.getRole();
|
||||
return role.equals(userRole);
|
||||
}
|
||||
|
||||
public boolean hasAnyRole(String... roles) {
|
||||
if (userSession == null || !userSession.isAuthenticated()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String userRole = userSession.getRole();
|
||||
for (String role : roles) {
|
||||
if (role.equals(userRole)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Vérifications basées sur les permissions
|
||||
public boolean canManageMembers() {
|
||||
return hasAnyRole("ADMIN", "GESTIONNAIRE_MEMBRE");
|
||||
}
|
||||
|
||||
public boolean canValidateMembers() {
|
||||
return hasAnyRole("ADMIN", "GESTIONNAIRE_MEMBRE");
|
||||
}
|
||||
|
||||
public boolean canManageFinances() {
|
||||
return hasAnyRole("ADMIN", "TRESORIER", "GESTIONNAIRE_FINANCE");
|
||||
}
|
||||
|
||||
public boolean canManageEvents() {
|
||||
return hasAnyRole("ADMIN", "GESTIONNAIRE_EVENEMENT");
|
||||
}
|
||||
|
||||
public boolean canManageAides() {
|
||||
return hasAnyRole("ADMIN", "GESTIONNAIRE_AIDE");
|
||||
}
|
||||
|
||||
public boolean canViewReports() {
|
||||
return hasAnyRole("ADMIN", "GESTIONNAIRE_MEMBRE", "TRESORIER");
|
||||
}
|
||||
|
||||
public boolean canManageSubscription() {
|
||||
return hasRole("ADMIN");
|
||||
}
|
||||
|
||||
public boolean canManageOrganization() {
|
||||
return hasRole("ADMIN");
|
||||
}
|
||||
|
||||
public boolean canAccessSuperAdmin() {
|
||||
return hasRole("SUPER_ADMIN");
|
||||
}
|
||||
|
||||
// Vérifications basées sur les fonctionnalités du forfait
|
||||
public boolean isFeatureEnabled(String feature) {
|
||||
// Cette méthode vérifiera si la fonctionnalité est incluse dans le forfait souscrit
|
||||
// Pour l'instant, simulation basée sur des rôles
|
||||
|
||||
switch (feature.toLowerCase()) {
|
||||
case "gestion_membres":
|
||||
return true; // Toujours disponible
|
||||
|
||||
case "gestion_cotisations":
|
||||
return true; // Toujours disponible
|
||||
|
||||
case "gestion_evenements":
|
||||
return !hasRole("MEMBER"); // Pas pour les membres simples
|
||||
|
||||
case "gestion_aides":
|
||||
return hasAnyRole("ADMIN", "GESTIONNAIRE_AIDE");
|
||||
|
||||
case "rapports_avances":
|
||||
return hasAnyRole("ADMIN", "SUPER_ADMIN");
|
||||
|
||||
case "integration_paiement":
|
||||
return hasAnyRole("ADMIN", "TRESORIER");
|
||||
|
||||
case "notifications_sms":
|
||||
return hasAnyRole("ADMIN", "SUPER_ADMIN");
|
||||
|
||||
case "gestion_documents":
|
||||
return hasAnyRole("ADMIN", "GESTIONNAIRE_MEMBRE");
|
||||
|
||||
case "support_prioritaire":
|
||||
return hasAnyRole("ADMIN", "SUPER_ADMIN");
|
||||
|
||||
case "personnalisation_avancee":
|
||||
return hasRole("SUPER_ADMIN");
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Vérifications pour l'interface utilisateur
|
||||
public boolean showCreateMemberButton() {
|
||||
return canManageMembers() && isFeatureEnabled("gestion_membres");
|
||||
}
|
||||
|
||||
public boolean showValidateMemberButton() {
|
||||
return canValidateMembers() && isFeatureEnabled("gestion_membres");
|
||||
}
|
||||
|
||||
public boolean showFinancialSection() {
|
||||
return canManageFinances() && isFeatureEnabled("gestion_cotisations");
|
||||
}
|
||||
|
||||
public boolean showEventsSection() {
|
||||
return canManageEvents() && isFeatureEnabled("gestion_evenements");
|
||||
}
|
||||
|
||||
public boolean showAidesSection() {
|
||||
return canManageAides() && isFeatureEnabled("gestion_aides");
|
||||
}
|
||||
|
||||
public boolean showReportsSection() {
|
||||
return canViewReports() && isFeatureEnabled("rapports_avances");
|
||||
}
|
||||
|
||||
public boolean showSubscriptionManagement() {
|
||||
return canManageSubscription();
|
||||
}
|
||||
|
||||
public boolean showAdvancedSettings() {
|
||||
return canManageOrganization() && isFeatureEnabled("personnalisation_avancee");
|
||||
}
|
||||
|
||||
public boolean showSuperAdminFeatures() {
|
||||
return canAccessSuperAdmin();
|
||||
}
|
||||
|
||||
// Vérifications spécifiques aux actions
|
||||
public boolean canCreateEvent() {
|
||||
return canManageEvents() && isFeatureEnabled("gestion_evenements");
|
||||
}
|
||||
|
||||
public boolean canProcessAideRequest() {
|
||||
return canManageAides() && isFeatureEnabled("gestion_aides");
|
||||
}
|
||||
|
||||
public boolean canExportData() {
|
||||
return canViewReports() && isFeatureEnabled("rapports_avances");
|
||||
}
|
||||
|
||||
public boolean canSendNotifications() {
|
||||
return canManageMembers() && (isFeatureEnabled("notifications_email") || isFeatureEnabled("notifications_sms"));
|
||||
}
|
||||
|
||||
public boolean canManageDocuments() {
|
||||
return canManageMembers() && isFeatureEnabled("gestion_documents");
|
||||
}
|
||||
|
||||
// Vérifications pour les limites
|
||||
public boolean canAddNewMember() {
|
||||
if (!canManageMembers()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Vérifier le quota de membres (sera implémenté avec SouscriptionBean)
|
||||
// Pour l'instant, toujours vrai si on a les permissions
|
||||
return true;
|
||||
}
|
||||
|
||||
// Méthodes utilitaires pour l'affichage conditionnel
|
||||
public String getRoleBasedStyleClass() {
|
||||
if (!userSession.isAuthenticated()) {
|
||||
return "guest-mode";
|
||||
}
|
||||
|
||||
String role = userSession.getRole();
|
||||
switch (role) {
|
||||
case "SUPER_ADMIN":
|
||||
return "super-admin-mode";
|
||||
case "ADMIN":
|
||||
return "admin-mode";
|
||||
case "GESTIONNAIRE_MEMBRE":
|
||||
return "gestionnaire-mode";
|
||||
case "TRESORIER":
|
||||
return "tresorier-mode";
|
||||
case "MEMBER":
|
||||
default:
|
||||
return "member-mode";
|
||||
}
|
||||
}
|
||||
|
||||
public String getPermissionMessage(String action) {
|
||||
return "Vous n'avez pas les permissions nécessaires pour " + action;
|
||||
}
|
||||
|
||||
// Getters pour utilisation dans les expressions EL
|
||||
public boolean isAuthenticated() {
|
||||
return userSession != null && userSession.isAuthenticated();
|
||||
}
|
||||
|
||||
public boolean isSuperAdmin() {
|
||||
return hasRole("SUPER_ADMIN");
|
||||
}
|
||||
|
||||
public boolean isAdmin() {
|
||||
return hasRole("ADMIN");
|
||||
}
|
||||
|
||||
public boolean isMember() {
|
||||
return hasRole("MEMBER");
|
||||
}
|
||||
|
||||
public boolean isGestionnaire() {
|
||||
return hasAnyRole("GESTIONNAIRE_MEMBRE", "GESTIONNAIRE_EVENEMENT", "GESTIONNAIRE_AIDE", "GESTIONNAIRE_FINANCE");
|
||||
}
|
||||
|
||||
public boolean isTresorier() {
|
||||
return hasRole("TRESORIER");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package dev.lions.unionflow.client.security;
|
||||
|
||||
import io.quarkus.scheduler.Scheduled;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ApplicationScoped
|
||||
public class TokenCleanupService {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(TokenCleanupService.class.getName());
|
||||
|
||||
@Inject
|
||||
private TokenRefreshService tokenRefreshService;
|
||||
|
||||
@Scheduled(every = "10m")
|
||||
public void cleanupExpiredTokens() {
|
||||
try {
|
||||
LOGGER.fine("Exécution du nettoyage des tokens expirés");
|
||||
tokenRefreshService.cleanupExpiredTokens();
|
||||
LOGGER.fine("Nettoyage des tokens terminé");
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Erreur lors du nettoyage des tokens: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package dev.lions.unionflow.client.security;
|
||||
|
||||
import dev.lions.unionflow.client.dto.auth.LoginResponse;
|
||||
import dev.lions.unionflow.client.service.AuthenticationService;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ApplicationScoped
|
||||
public class TokenRefreshService {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(TokenRefreshService.class.getName());
|
||||
|
||||
@Inject
|
||||
private AuthenticationService authService;
|
||||
|
||||
// Stockage des tokens au niveau application pour éviter les problèmes de contexte session
|
||||
private final Map<String, TokenInfo> activeTokens = new ConcurrentHashMap<>();
|
||||
|
||||
private static class TokenInfo {
|
||||
String accessToken;
|
||||
String refreshToken;
|
||||
long expirationTime;
|
||||
String sessionId;
|
||||
|
||||
TokenInfo(String accessToken, String refreshToken, long expirationTime, String sessionId) {
|
||||
this.accessToken = accessToken;
|
||||
this.refreshToken = refreshToken;
|
||||
this.expirationTime = expirationTime;
|
||||
this.sessionId = sessionId;
|
||||
}
|
||||
|
||||
boolean needsRefresh() {
|
||||
// Rafraîchir 5 minutes avant l'expiration
|
||||
long timeUntilExpiration = expirationTime - System.currentTimeMillis();
|
||||
return timeUntilExpiration < 300000; // 5 minutes en millisecondes
|
||||
}
|
||||
|
||||
boolean isExpired() {
|
||||
return System.currentTimeMillis() > expirationTime;
|
||||
}
|
||||
}
|
||||
|
||||
public void registerToken(String sessionId, String accessToken, String refreshToken, long expiresIn) {
|
||||
if (sessionId != null && accessToken != null) {
|
||||
long expirationTime = System.currentTimeMillis() + (expiresIn * 1000);
|
||||
activeTokens.put(sessionId, new TokenInfo(accessToken, refreshToken, expirationTime, sessionId));
|
||||
LOGGER.info("Token enregistré pour la session: " + sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeToken(String sessionId) {
|
||||
if (sessionId != null) {
|
||||
activeTokens.remove(sessionId);
|
||||
LOGGER.info("Token supprimé pour la session: " + sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
// Cette méthode n'est plus appelée par le scheduler pour éviter les problèmes de contexte
|
||||
// Elle peut être appelée manuellement depuis un contexte avec session active
|
||||
public void checkAndRefreshTokens(String sessionId) {
|
||||
try {
|
||||
TokenInfo tokenInfo = activeTokens.get(sessionId);
|
||||
|
||||
if (tokenInfo != null && tokenInfo.needsRefresh() && tokenInfo.refreshToken != null) {
|
||||
LOGGER.info("Rafraîchissement du token JWT nécessaire pour session: " + sessionId);
|
||||
|
||||
LoginResponse refreshedResponse = authService.refreshToken(tokenInfo.refreshToken);
|
||||
|
||||
if (refreshedResponse != null) {
|
||||
// Mettre à jour les tokens stockés
|
||||
registerToken(sessionId,
|
||||
refreshedResponse.getAccessToken(),
|
||||
refreshedResponse.getRefreshToken(),
|
||||
refreshedResponse.getExpiresIn());
|
||||
|
||||
LOGGER.info("Token JWT rafraîchi avec succès pour session: " + sessionId);
|
||||
} else {
|
||||
LOGGER.warning("Échec du rafraîchissement du token JWT pour session: " + sessionId);
|
||||
handleTokenRefreshFailure(sessionId);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du rafraîchissement du token: " + e.getMessage());
|
||||
handleTokenRefreshFailure(sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean tryRefreshTokenNow(String sessionId) {
|
||||
try {
|
||||
TokenInfo tokenInfo = activeTokens.get(sessionId);
|
||||
|
||||
if (tokenInfo != null && tokenInfo.refreshToken != null) {
|
||||
LoginResponse refreshedResponse = authService.refreshToken(tokenInfo.refreshToken);
|
||||
|
||||
if (refreshedResponse != null) {
|
||||
registerToken(sessionId,
|
||||
refreshedResponse.getAccessToken(),
|
||||
refreshedResponse.getRefreshToken(),
|
||||
refreshedResponse.getExpiresIn());
|
||||
|
||||
LOGGER.info("Token rafraîchi manuellement avec succès pour session: " + sessionId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Échec du rafraîchissement manuel du token: " + e.getMessage());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void handleTokenRefreshFailure(String sessionId) {
|
||||
// En cas d'échec du rafraîchissement, supprimer le token
|
||||
removeToken(sessionId);
|
||||
LOGGER.info("Session expirée - token supprimé pour: " + sessionId);
|
||||
}
|
||||
|
||||
public boolean isTokenExpired(String sessionId) {
|
||||
TokenInfo tokenInfo = activeTokens.get(sessionId);
|
||||
return tokenInfo == null || tokenInfo.isExpired();
|
||||
}
|
||||
|
||||
public long getTimeUntilExpiration(String sessionId) {
|
||||
TokenInfo tokenInfo = activeTokens.get(sessionId);
|
||||
if (tokenInfo != null) {
|
||||
long timeLeft = tokenInfo.expirationTime - System.currentTimeMillis();
|
||||
return Math.max(0, timeLeft / 1000); // Retourner en secondes
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getAccessToken(String sessionId) {
|
||||
TokenInfo tokenInfo = activeTokens.get(sessionId);
|
||||
return tokenInfo != null ? tokenInfo.accessToken : null;
|
||||
}
|
||||
|
||||
// Méthode pour nettoyer les tokens expirés périodiquement
|
||||
public void cleanupExpiredTokens() {
|
||||
activeTokens.entrySet().removeIf(entry -> {
|
||||
boolean expired = entry.getValue().isExpired();
|
||||
if (expired) {
|
||||
LOGGER.info("Suppression du token expiré pour session: " + entry.getKey());
|
||||
}
|
||||
return expired;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
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")
|
||||
@Path("/api/v1/analytics")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface AnalyticsService {
|
||||
|
||||
@GET
|
||||
@Path("/metriques/{typeMetrique}")
|
||||
AnalyticsDataDTO calculerMetrique(
|
||||
@PathParam("typeMetrique") String typeMetrique,
|
||||
@QueryParam("periode") String periode,
|
||||
@QueryParam("organisationId") String organisationId
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/tendances/{typeMetrique}")
|
||||
Map<String, Object> calculerTendanceKPI(
|
||||
@PathParam("typeMetrique") String typeMetrique,
|
||||
@QueryParam("periode") String periode,
|
||||
@QueryParam("organisationId") String organisationId
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/kpis")
|
||||
Map<String, Object> obtenirTousLesKPI(
|
||||
@QueryParam("periode") String periode,
|
||||
@QueryParam("organisationId") String organisationId
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/evolutions")
|
||||
Map<String, Object> obtenirEvolutionsKPI(
|
||||
@QueryParam("periode") String periode,
|
||||
@QueryParam("organisationId") String organisationId
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/performance-globale")
|
||||
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("utilisateurId") String utilisateurId
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.AssociationDTO;
|
||||
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;
|
||||
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/organisations")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface AssociationService {
|
||||
|
||||
@GET
|
||||
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("/recherche")
|
||||
List<AssociationDTO> rechercher(
|
||||
@QueryParam("nom") String nom,
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("region") String region,
|
||||
@QueryParam("ville") String ville,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/type/{type}")
|
||||
List<AssociationDTO> listerParType(@PathParam("type") String type);
|
||||
|
||||
@GET
|
||||
@Path("/region/{region}")
|
||||
List<AssociationDTO> listerParRegion(@PathParam("region") String region);
|
||||
|
||||
@POST
|
||||
AssociationDTO creer(AssociationDTO association);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
AssociationDTO modifier(@PathParam("id") UUID id, AssociationDTO association);
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
// Côté serveur: POST /{id}/activer
|
||||
@POST
|
||||
@Path("/{id}/activer")
|
||||
AssociationDTO activer(@PathParam("id") UUID id);
|
||||
|
||||
// Suspension: POST /{id}/suspendre (alias historique "désactiver")
|
||||
@POST
|
||||
@Path("/{id}/suspendre")
|
||||
AssociationDTO suspendre(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/dissoudre")
|
||||
AssociationDTO dissoudre(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/statistiques")
|
||||
StatistiquesAssociationDTO obtenirStatistiques();
|
||||
|
||||
@GET
|
||||
@Path("/{id}/membres/count")
|
||||
Long compterMembres(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/{id}/performance")
|
||||
PerformanceAssociationDTO obtenirPerformance(@PathParam("id") UUID id);
|
||||
|
||||
// Classes DTO internes
|
||||
class StatistiquesAssociationDTO {
|
||||
public Long totalAssociations;
|
||||
public Long associationsActives;
|
||||
public Long associationsInactives;
|
||||
public Long associationsSuspendues;
|
||||
public Long associationsDissoutes;
|
||||
public Long nouvellesAssociations30Jours;
|
||||
public Double tauxActivite;
|
||||
public java.util.Map<String, Long> repartitionParType;
|
||||
public java.util.Map<String, Long> repartitionParRegion;
|
||||
|
||||
// Constructeurs
|
||||
public StatistiquesAssociationDTO() {}
|
||||
|
||||
// Getters et setters
|
||||
public Long getTotalAssociations() { return totalAssociations; }
|
||||
public void setTotalAssociations(Long totalAssociations) { this.totalAssociations = totalAssociations; }
|
||||
|
||||
public Long getAssociationsActives() { return associationsActives; }
|
||||
public void setAssociationsActives(Long associationsActives) { this.associationsActives = associationsActives; }
|
||||
|
||||
public Long getAssociationsInactives() { return associationsInactives; }
|
||||
public void setAssociationsInactives(Long associationsInactives) { this.associationsInactives = associationsInactives; }
|
||||
|
||||
public Long getAssociationsSuspendues() { return associationsSuspendues; }
|
||||
public void setAssociationsSuspendues(Long associationsSuspendues) { this.associationsSuspendues = associationsSuspendues; }
|
||||
|
||||
public Long getAssociationsDissoutes() { return associationsDissoutes; }
|
||||
public void setAssociationsDissoutes(Long associationsDissoutes) { this.associationsDissoutes = associationsDissoutes; }
|
||||
|
||||
public Long getNouvellesAssociations30Jours() { return nouvellesAssociations30Jours; }
|
||||
public void setNouvellesAssociations30Jours(Long nouvellesAssociations30Jours) { this.nouvellesAssociations30Jours = nouvellesAssociations30Jours; }
|
||||
|
||||
public Double getTauxActivite() { return tauxActivite; }
|
||||
public void setTauxActivite(Double tauxActivite) { this.tauxActivite = tauxActivite; }
|
||||
|
||||
public java.util.Map<String, Long> getRepartitionParType() { return repartitionParType; }
|
||||
public void setRepartitionParType(java.util.Map<String, Long> repartitionParType) { this.repartitionParType = repartitionParType; }
|
||||
|
||||
public java.util.Map<String, Long> getRepartitionParRegion() { return repartitionParRegion; }
|
||||
public void setRepartitionParRegion(java.util.Map<String, Long> repartitionParRegion) { this.repartitionParRegion = repartitionParRegion; }
|
||||
}
|
||||
|
||||
class PerformanceAssociationDTO {
|
||||
public UUID associationId;
|
||||
public String nom;
|
||||
public Integer scoreGlobal;
|
||||
public Integer scoreMembres;
|
||||
public Integer scoreActivites;
|
||||
public Integer scoreFinances;
|
||||
public String tendance;
|
||||
public java.time.LocalDateTime derniereMiseAJour;
|
||||
|
||||
// Constructeurs
|
||||
public PerformanceAssociationDTO() {}
|
||||
|
||||
// Getters et setters
|
||||
public UUID getAssociationId() { return associationId; }
|
||||
public void setAssociationId(UUID associationId) { this.associationId = associationId; }
|
||||
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public Integer getScoreGlobal() { return scoreGlobal; }
|
||||
public void setScoreGlobal(Integer scoreGlobal) { this.scoreGlobal = scoreGlobal; }
|
||||
|
||||
public Integer getScoreMembres() { return scoreMembres; }
|
||||
public void setScoreMembres(Integer scoreMembres) { this.scoreMembres = scoreMembres; }
|
||||
|
||||
public Integer getScoreActivites() { return scoreActivites; }
|
||||
public void setScoreActivites(Integer scoreActivites) { this.scoreActivites = scoreActivites; }
|
||||
|
||||
public Integer getScoreFinances() { return scoreFinances; }
|
||||
public void setScoreFinances(Integer scoreFinances) { this.scoreFinances = scoreFinances; }
|
||||
|
||||
public String getTendance() { return tendance; }
|
||||
public void setTendance(String tendance) { this.tendance = tendance; }
|
||||
|
||||
public java.time.LocalDateTime getDerniereMiseAJour() { return derniereMiseAJour; }
|
||||
public void setDerniereMiseAJour(java.time.LocalDateTime derniereMiseAJour) { this.derniereMiseAJour = derniereMiseAJour; }
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.auth.LoginRequest;
|
||||
import dev.lions.unionflow.client.dto.auth.LoginResponse;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.client.Client;
|
||||
import jakarta.ws.rs.client.ClientBuilder;
|
||||
import jakarta.ws.rs.client.Entity;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@ApplicationScoped
|
||||
public class AuthenticationService {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(AuthenticationService.class.getName());
|
||||
|
||||
@ConfigProperty(name = "unionflow.backend.url", defaultValue = "http://localhost:8080")
|
||||
String backendUrl;
|
||||
|
||||
private final Client client;
|
||||
|
||||
public AuthenticationService() {
|
||||
this.client = ClientBuilder.newClient();
|
||||
}
|
||||
|
||||
public LoginResponse authenticate(LoginRequest loginRequest) {
|
||||
try {
|
||||
String endpoint = backendUrl + "/api/auth/login";
|
||||
|
||||
LOGGER.info("Tentative d'authentification vers: " + endpoint);
|
||||
|
||||
Response response = client.target(endpoint)
|
||||
.request(MediaType.APPLICATION_JSON)
|
||||
.post(Entity.entity(loginRequest, MediaType.APPLICATION_JSON));
|
||||
|
||||
if (response.getStatus() == 200) {
|
||||
LoginResponse loginResponse = response.readEntity(LoginResponse.class);
|
||||
LOGGER.info("Authentification réussie pour l'utilisateur: " + loginRequest.getUsername());
|
||||
return loginResponse;
|
||||
} else {
|
||||
LOGGER.warning("Échec de l'authentification. Code de statut: " + response.getStatus());
|
||||
throw new AuthenticationException("Nom d'utilisateur ou mot de passe incorrect");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'authentification: " + e.getMessage());
|
||||
|
||||
// Mode simulation pour le développement
|
||||
if ("demo".equals(loginRequest.getUsername()) || isValidDemoCredentials(loginRequest)) {
|
||||
return createDemoLoginResponse(loginRequest);
|
||||
}
|
||||
|
||||
throw new AuthenticationException("Erreur de connexion au serveur d'authentification");
|
||||
}
|
||||
}
|
||||
|
||||
public LoginResponse refreshToken(String refreshToken) {
|
||||
try {
|
||||
String endpoint = backendUrl + "/api/auth/refresh";
|
||||
|
||||
Response response = client.target(endpoint)
|
||||
.request(MediaType.APPLICATION_JSON)
|
||||
.header("Authorization", "Bearer " + refreshToken)
|
||||
.post(Entity.text(""));
|
||||
|
||||
if (response.getStatus() == 200) {
|
||||
return response.readEntity(LoginResponse.class);
|
||||
} else {
|
||||
throw new AuthenticationException("Token de rafraîchissement invalide");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du rafraîchissement du token: " + e.getMessage());
|
||||
throw new AuthenticationException("Erreur lors du rafraîchissement du token");
|
||||
}
|
||||
}
|
||||
|
||||
public void logout(String accessToken) {
|
||||
try {
|
||||
String endpoint = backendUrl + "/api/auth/logout";
|
||||
|
||||
client.target(endpoint)
|
||||
.request()
|
||||
.header("Authorization", "Bearer " + accessToken)
|
||||
.post(Entity.text(""));
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Erreur lors de la déconnexion: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidDemoCredentials(LoginRequest request) {
|
||||
return ("admin".equals(request.getUsername()) && "admin".equals(request.getPassword())) ||
|
||||
("superadmin".equals(request.getUsername()) && "admin".equals(request.getPassword())) ||
|
||||
("membre".equals(request.getUsername()) && "membre".equals(request.getPassword()));
|
||||
}
|
||||
|
||||
private LoginResponse createDemoLoginResponse(LoginRequest request) {
|
||||
LoginResponse.UserInfo userInfo = new LoginResponse.UserInfo();
|
||||
|
||||
// UUIDs fixes pour la démonstration (pour cohérence entre les sessions)
|
||||
UUID superAdminId = UUID.fromString("00000000-0000-0000-0000-000000000001");
|
||||
UUID adminId = UUID.fromString("00000000-0000-0000-0000-000000000002");
|
||||
UUID membreId = UUID.fromString("00000000-0000-0000-0000-000000000003");
|
||||
UUID entiteId = UUID.fromString("00000000-0000-0000-0000-000000000010");
|
||||
|
||||
switch (request.getUsername()) {
|
||||
case "superadmin":
|
||||
userInfo.setId(superAdminId);
|
||||
userInfo.setNom("Diallo");
|
||||
userInfo.setPrenom("Amadou");
|
||||
userInfo.setEmail("amadou.diallo@unionflow.sn");
|
||||
userInfo.setUsername("superadmin");
|
||||
userInfo.setTypeCompte("SUPER_ADMIN");
|
||||
userInfo.setRoles(java.util.Arrays.asList("SUPER_ADMIN", "ADMIN"));
|
||||
break;
|
||||
|
||||
case "admin":
|
||||
userInfo.setId(adminId);
|
||||
userInfo.setNom("Traoré");
|
||||
userInfo.setPrenom("Fatou");
|
||||
userInfo.setEmail("fatou.traore@association-example.sn");
|
||||
userInfo.setUsername("admin");
|
||||
userInfo.setTypeCompte("ADMIN_ENTITE");
|
||||
userInfo.setRoles(java.util.Arrays.asList("ADMIN_ENTITE"));
|
||||
|
||||
// Entité de démonstration
|
||||
LoginResponse.EntiteInfo entite = new LoginResponse.EntiteInfo();
|
||||
entite.setId(entiteId);
|
||||
entite.setNom("Association des Jeunes Entrepreneurs");
|
||||
entite.setType("Association");
|
||||
entite.setPays("Sénégal");
|
||||
entite.setVille("Dakar");
|
||||
userInfo.setEntite(entite);
|
||||
break;
|
||||
|
||||
default:
|
||||
userInfo.setId(membreId);
|
||||
userInfo.setNom("Ndiaye");
|
||||
userInfo.setPrenom("Moussa");
|
||||
userInfo.setEmail("moussa.ndiaye@exemple.sn");
|
||||
userInfo.setUsername("membre");
|
||||
userInfo.setTypeCompte("MEMBRE");
|
||||
userInfo.setRoles(java.util.Arrays.asList("MEMBRE"));
|
||||
|
||||
// Entité de démonstration
|
||||
LoginResponse.EntiteInfo entiteMembre = new LoginResponse.EntiteInfo();
|
||||
entiteMembre.setId(entiteId);
|
||||
entiteMembre.setNom("Association des Jeunes Entrepreneurs");
|
||||
entiteMembre.setType("Association");
|
||||
entiteMembre.setPays("Sénégal");
|
||||
entiteMembre.setVille("Dakar");
|
||||
userInfo.setEntite(entiteMembre);
|
||||
break;
|
||||
}
|
||||
|
||||
return new LoginResponse(
|
||||
"demo_access_token_" + System.currentTimeMillis(),
|
||||
"demo_refresh_token_" + System.currentTimeMillis(),
|
||||
3600L, // 1 heure
|
||||
userInfo
|
||||
);
|
||||
}
|
||||
|
||||
public static class AuthenticationException extends RuntimeException {
|
||||
public AuthenticationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AuthenticationException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.CotisationDTO;
|
||||
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("/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);
|
||||
|
||||
/**
|
||||
* Envoie des rappels de cotisations groupés à plusieurs membres (WOU/DRY)
|
||||
*
|
||||
* @param membreIds Liste des IDs des membres destinataires
|
||||
* @return Nombre de rappels envoyés
|
||||
*/
|
||||
@POST
|
||||
@Path("/rappels/groupes")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
Map<String, Integer> envoyerRappelsGroupes(List<UUID> membreIds);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.DemandeAideDTO;
|
||||
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;
|
||||
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/demandes-aide")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface DemandeAideService {
|
||||
|
||||
@GET
|
||||
List<DemandeAideDTO> listerToutes(
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
DemandeAideDTO obtenirParId(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/search")
|
||||
List<DemandeAideDTO> rechercher(
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("urgence") String urgence,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
@POST
|
||||
DemandeAideDTO creer(DemandeAideDTO demande);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
DemandeAideDTO modifier(@PathParam("id") UUID id, DemandeAideDTO demande);
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/approuver")
|
||||
DemandeAideDTO approuver(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/rejeter")
|
||||
DemandeAideDTO rejeter(@PathParam("id") UUID id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.EvenementDTO;
|
||||
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
|
||||
Map<String, Object> listerTous(
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.FormulaireDTO;
|
||||
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;
|
||||
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/formulaires")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface FormulaireService {
|
||||
|
||||
@GET
|
||||
List<FormulaireDTO> listerTous();
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
FormulaireDTO obtenirParId(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/actifs")
|
||||
List<FormulaireDTO> listerActifs();
|
||||
|
||||
@GET
|
||||
@Path("/populaires")
|
||||
List<FormulaireDTO> listerPopulaires();
|
||||
|
||||
@POST
|
||||
FormulaireDTO creer(FormulaireDTO formulaire);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
FormulaireDTO modifier(@PathParam("id") UUID id, FormulaireDTO formulaire);
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/activer")
|
||||
FormulaireDTO activer(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/desactiver")
|
||||
FormulaireDTO desactiver(@PathParam("id") UUID id);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import jakarta.ws.rs.FormParam;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||
import org.jboss.resteasy.reactive.PartType;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MembreImportMultipartForm {
|
||||
@FormParam("file")
|
||||
@PartType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
public byte[] file;
|
||||
|
||||
@FormParam("fileName")
|
||||
public String fileName;
|
||||
|
||||
@FormParam("organisationId")
|
||||
public UUID organisationId;
|
||||
|
||||
@FormParam("typeMembreDefaut")
|
||||
public String typeMembreDefaut;
|
||||
|
||||
@FormParam("mettreAJourExistants")
|
||||
public boolean mettreAJourExistants;
|
||||
|
||||
@FormParam("ignorerErreurs")
|
||||
public boolean ignorerErreurs;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.MembreDTO;
|
||||
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;
|
||||
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/membres")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface MembreService {
|
||||
|
||||
@GET
|
||||
List<MembreDTO> listerTous();
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
MembreDTO obtenirParId(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/numero/{numeroMembre}")
|
||||
MembreDTO obtenirParNumero(@PathParam("numeroMembre") String numeroMembre);
|
||||
|
||||
@GET
|
||||
@Path("/search")
|
||||
List<MembreDTO> rechercher(
|
||||
@QueryParam("nom") String nom,
|
||||
@QueryParam("prenom") String prenom,
|
||||
@QueryParam("email") String email,
|
||||
@QueryParam("telephone") String telephone,
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("associationId") UUID associationId,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/association/{associationId}")
|
||||
List<MembreDTO> listerParAssociation(@PathParam("associationId") UUID associationId);
|
||||
|
||||
@GET
|
||||
@Path("/actifs")
|
||||
List<MembreDTO> listerActifs();
|
||||
|
||||
@GET
|
||||
@Path("/inactifs")
|
||||
List<MembreDTO> listerInactifs();
|
||||
|
||||
@POST
|
||||
MembreDTO creer(MembreDTO membre);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
MembreDTO modifier(@PathParam("id") UUID id, MembreDTO membre);
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/activer")
|
||||
MembreDTO activer(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/desactiver")
|
||||
MembreDTO desactiver(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/suspendre")
|
||||
MembreDTO suspendre(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/radier")
|
||||
MembreDTO radier(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/statistiques")
|
||||
StatistiquesMembreDTO obtenirStatistiques();
|
||||
|
||||
@GET
|
||||
@Path("/export")
|
||||
@Produces({"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "text/csv", "application/pdf", "application/json"})
|
||||
byte[] exporterExcel(
|
||||
@QueryParam("format") @DefaultValue("EXCEL") String format,
|
||||
@QueryParam("associationId") UUID associationId,
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("dateAdhesionDebut") String dateAdhesionDebut,
|
||||
@QueryParam("dateAdhesionFin") String dateAdhesionFin,
|
||||
@QueryParam("colonnes") List<String> colonnesExport,
|
||||
@QueryParam("inclureHeaders") @DefaultValue("true") boolean inclureHeaders,
|
||||
@QueryParam("formaterDates") @DefaultValue("true") boolean formaterDates,
|
||||
@QueryParam("inclureStatistiques") @DefaultValue("false") boolean inclureStatistiques,
|
||||
@QueryParam("motDePasse") String motDePasse
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/export/count")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
Long compterMembresPourExport(
|
||||
@QueryParam("associationId") UUID associationId,
|
||||
@QueryParam("statut") String statut,
|
||||
@QueryParam("type") String type,
|
||||
@QueryParam("dateAdhesionDebut") String dateAdhesionDebut,
|
||||
@QueryParam("dateAdhesionFin") String dateAdhesionFin
|
||||
);
|
||||
|
||||
@POST
|
||||
@Path("/import")
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
ResultatImportDTO importerDonnees(MembreImportMultipartForm form);
|
||||
|
||||
@GET
|
||||
@Path("/import/modele")
|
||||
@Produces("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||
byte[] telechargerModeleImport();
|
||||
|
||||
@GET
|
||||
@Path("/autocomplete/villes")
|
||||
List<String> obtenirVilles(@QueryParam("query") String query);
|
||||
|
||||
@GET
|
||||
@Path("/autocomplete/professions")
|
||||
List<String> obtenirProfessions(@QueryParam("query") String query);
|
||||
|
||||
@POST
|
||||
@Path("/export/selection")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
||||
byte[] exporterSelection(
|
||||
List<UUID> membreIds,
|
||||
@QueryParam("format") @DefaultValue("EXCEL") String format);
|
||||
|
||||
// Classes DTO internes pour les réponses spécialisées
|
||||
class StatistiquesMembreDTO {
|
||||
public Long totalMembres;
|
||||
public Long membresActifs;
|
||||
public Long membresInactifs;
|
||||
public Long membresSuspendus;
|
||||
public Long membresRadies;
|
||||
public Long nouveauxMembres30Jours;
|
||||
public Double tauxActivite;
|
||||
public Double tauxCroissance;
|
||||
|
||||
// Constructeurs
|
||||
public StatistiquesMembreDTO() {}
|
||||
|
||||
// Getters et setters
|
||||
public Long getTotalMembres() { return totalMembres; }
|
||||
public void setTotalMembres(Long totalMembres) { this.totalMembres = totalMembres; }
|
||||
|
||||
public Long getMembresActifs() { return membresActifs; }
|
||||
public void setMembresActifs(Long membresActifs) { this.membresActifs = membresActifs; }
|
||||
|
||||
public Long getMembresInactifs() { return membresInactifs; }
|
||||
public void setMembresInactifs(Long membresInactifs) { this.membresInactifs = membresInactifs; }
|
||||
|
||||
public Long getMembresSuspendus() { return membresSuspendus; }
|
||||
public void setMembresSuspendus(Long membresSuspendus) { this.membresSuspendus = membresSuspendus; }
|
||||
|
||||
public Long getMembresRadies() { return membresRadies; }
|
||||
public void setMembresRadies(Long membresRadies) { this.membresRadies = membresRadies; }
|
||||
|
||||
public Long getNouveauxMembres30Jours() { return nouveauxMembres30Jours; }
|
||||
public void setNouveauxMembres30Jours(Long nouveauxMembres30Jours) { this.nouveauxMembres30Jours = nouveauxMembres30Jours; }
|
||||
|
||||
public Double getTauxActivite() { return tauxActivite; }
|
||||
public void setTauxActivite(Double tauxActivite) { this.tauxActivite = tauxActivite; }
|
||||
|
||||
public Double getTauxCroissance() { return tauxCroissance; }
|
||||
public void setTauxCroissance(Double tauxCroissance) { this.tauxCroissance = tauxCroissance; }
|
||||
}
|
||||
|
||||
class ResultatImportDTO {
|
||||
public Integer totalLignes;
|
||||
public Integer lignesTraitees;
|
||||
public Integer lignesErreur;
|
||||
public List<String> erreurs;
|
||||
public List<MembreDTO> membresImportes;
|
||||
|
||||
// Constructeurs
|
||||
public ResultatImportDTO() {}
|
||||
|
||||
// Getters et setters
|
||||
public Integer getTotalLignes() { return totalLignes; }
|
||||
public void setTotalLignes(Integer totalLignes) { this.totalLignes = totalLignes; }
|
||||
|
||||
public Integer getLignesTraitees() { return lignesTraitees; }
|
||||
public void setLignesTraitees(Integer lignesTraitees) { this.lignesTraitees = lignesTraitees; }
|
||||
|
||||
public Integer getLignesErreur() { return lignesErreur; }
|
||||
public void setLignesErreur(Integer lignesErreur) { this.lignesErreur = lignesErreur; }
|
||||
|
||||
public List<String> getErreurs() { return erreurs; }
|
||||
public void setErreurs(List<String> erreurs) { this.erreurs = erreurs; }
|
||||
|
||||
public List<MembreDTO> getMembresImportes() { return membresImportes; }
|
||||
public void setMembresImportes(List<MembreDTO> membresImportes) { this.membresImportes = membresImportes; }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
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;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Service REST Client pour la gestion des notifications (WOU/DRY)
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
*/
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/notifications")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface NotificationService {
|
||||
|
||||
/**
|
||||
* Envoie des notifications groupées à plusieurs membres (WOU/DRY)
|
||||
*
|
||||
* @param request DTO contenant les IDs des membres, sujet, corps et canaux
|
||||
* @return Nombre de notifications créées
|
||||
*/
|
||||
@POST
|
||||
@Path("/groupees")
|
||||
Map<String, Integer> envoyerNotificationsGroupees(NotificationGroupeeRequest request);
|
||||
|
||||
/**
|
||||
* Classe interne pour les requêtes de notifications groupées (WOU/DRY)
|
||||
*/
|
||||
class NotificationGroupeeRequest {
|
||||
public List<UUID> membreIds;
|
||||
public String sujet;
|
||||
public String corps;
|
||||
public List<String> canaux;
|
||||
|
||||
public NotificationGroupeeRequest() {}
|
||||
|
||||
public NotificationGroupeeRequest(List<UUID> membreIds, String sujet, String corps, List<String> canaux) {
|
||||
this.membreIds = membreIds;
|
||||
this.sujet = sujet;
|
||||
this.corps = corps;
|
||||
this.canaux = canaux;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import jakarta.ws.rs.core.MultivaluedMap;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class RestClientExceptionMapper implements ResponseExceptionMapper<RuntimeException> {
|
||||
|
||||
@Override
|
||||
public RuntimeException toThrowable(Response response) {
|
||||
int status = response.getStatus();
|
||||
String reasonPhrase = response.getStatusInfo().getReasonPhrase();
|
||||
|
||||
// Lire le corps de la réponse pour plus de détails
|
||||
String body = "";
|
||||
try {
|
||||
if (response.hasEntity()) {
|
||||
body = response.readEntity(String.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
body = "Impossible de lire le détail de l'erreur";
|
||||
}
|
||||
|
||||
return switch (status) {
|
||||
case 400 -> new BadRequestException("Requête invalide: " + body);
|
||||
case 401 -> new UnauthorizedException("Non autorisé: " + reasonPhrase);
|
||||
case 403 -> new ForbiddenException("Accès interdit: " + reasonPhrase);
|
||||
case 404 -> new NotFoundException("Ressource non trouvée: " + reasonPhrase);
|
||||
case 409 -> new ConflictException("Conflit: " + body);
|
||||
case 422 -> new UnprocessableEntityException("Données non valides: " + body);
|
||||
case 500 -> new InternalServerErrorException("Erreur serveur interne: " + body);
|
||||
case 502 -> new BadGatewayException("Erreur de passerelle: " + reasonPhrase);
|
||||
case 503 -> new ServiceUnavailableException("Service indisponible: " + reasonPhrase);
|
||||
case 504 -> new GatewayTimeoutException("Timeout de passerelle: " + reasonPhrase);
|
||||
default -> new UnknownHttpStatusException("Erreur HTTP " + status + ": " + reasonPhrase + (body.isEmpty() ? "" : " - " + body));
|
||||
};
|
||||
}
|
||||
|
||||
// Classes d'exception personnalisées
|
||||
public static class BadRequestException extends RuntimeException {
|
||||
public BadRequestException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class UnauthorizedException extends RuntimeException {
|
||||
public UnauthorizedException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class ForbiddenException extends RuntimeException {
|
||||
public ForbiddenException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class NotFoundException extends RuntimeException {
|
||||
public NotFoundException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class ConflictException extends RuntimeException {
|
||||
public ConflictException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class UnprocessableEntityException extends RuntimeException {
|
||||
public UnprocessableEntityException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class InternalServerErrorException extends RuntimeException {
|
||||
public InternalServerErrorException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class BadGatewayException extends RuntimeException {
|
||||
public BadGatewayException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class ServiceUnavailableException extends RuntimeException {
|
||||
public ServiceUnavailableException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class GatewayTimeoutException extends RuntimeException {
|
||||
public GatewayTimeoutException(String message) { super(message); }
|
||||
}
|
||||
|
||||
public static class UnknownHttpStatusException extends RuntimeException {
|
||||
public UnknownHttpStatusException(String message) { super(message); }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import dev.lions.unionflow.client.dto.SouscriptionDTO;
|
||||
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;
|
||||
|
||||
@RegisterRestClient(configKey = "unionflow-api")
|
||||
@Path("/api/souscriptions")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public interface SouscriptionService {
|
||||
|
||||
@GET
|
||||
List<SouscriptionDTO> listerToutes(
|
||||
@QueryParam("organisationId") UUID organisationId,
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
);
|
||||
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
SouscriptionDTO obtenirParId(@PathParam("id") UUID id);
|
||||
|
||||
@GET
|
||||
@Path("/organisation/{organisationId}/active")
|
||||
SouscriptionDTO obtenirActive(@PathParam("organisationId") UUID organisationId);
|
||||
|
||||
@POST
|
||||
SouscriptionDTO creer(SouscriptionDTO souscription);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
SouscriptionDTO modifier(@PathParam("id") UUID id, SouscriptionDTO souscription);
|
||||
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
void supprimer(@PathParam("id") UUID id);
|
||||
|
||||
@PUT
|
||||
@Path("/{id}/renouveler")
|
||||
SouscriptionDTO renouveler(@PathParam("id") UUID id);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package dev.lions.unionflow.client.service;
|
||||
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.Validator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@ApplicationScoped
|
||||
public class ValidationService {
|
||||
|
||||
@Inject
|
||||
Validator validator;
|
||||
|
||||
/**
|
||||
* Valide un objet et retourne la liste des erreurs
|
||||
*/
|
||||
public <T> ValidationResult validate(T object) {
|
||||
Set<ConstraintViolation<T>> violations = validator.validate(object);
|
||||
|
||||
ValidationResult result = new ValidationResult();
|
||||
result.setValid(violations.isEmpty());
|
||||
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (ConstraintViolation<T> violation : violations) {
|
||||
messages.add(violation.getPropertyPath() + ": " + violation.getMessage());
|
||||
}
|
||||
result.setErrorMessages(messages);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide une propriété spécifique d'un objet
|
||||
*/
|
||||
public <T> ValidationResult validateProperty(T object, String propertyName) {
|
||||
Set<ConstraintViolation<T>> violations = validator.validateProperty(object, propertyName);
|
||||
|
||||
ValidationResult result = new ValidationResult();
|
||||
result.setValid(violations.isEmpty());
|
||||
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (ConstraintViolation<T> violation : violations) {
|
||||
messages.add(violation.getMessage());
|
||||
}
|
||||
result.setErrorMessages(messages);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide une valeur contre les contraintes d'une propriété
|
||||
*/
|
||||
public <T> ValidationResult validateValue(Class<T> beanType, String propertyName, Object value) {
|
||||
Set<ConstraintViolation<T>> violations = validator.validateValue(beanType, propertyName, value);
|
||||
|
||||
ValidationResult result = new ValidationResult();
|
||||
result.setValid(violations.isEmpty());
|
||||
|
||||
List<String> messages = new ArrayList<>();
|
||||
for (ConstraintViolation<T> violation : violations) {
|
||||
messages.add(violation.getMessage());
|
||||
}
|
||||
result.setErrorMessages(messages);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Classe pour encapsuler le résultat de validation
|
||||
*/
|
||||
public static class ValidationResult {
|
||||
private boolean valid;
|
||||
private List<String> errorMessages = new ArrayList<>();
|
||||
|
||||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
public void setValid(boolean valid) {
|
||||
this.valid = valid;
|
||||
}
|
||||
|
||||
public List<String> getErrorMessages() {
|
||||
return errorMessages;
|
||||
}
|
||||
|
||||
public void setErrorMessages(List<String> errorMessages) {
|
||||
this.errorMessages = errorMessages;
|
||||
}
|
||||
|
||||
public String getFirstErrorMessage() {
|
||||
return errorMessages.isEmpty() ? null : errorMessages.get(0);
|
||||
}
|
||||
|
||||
public String getAllErrorMessages() {
|
||||
return String.join(", ", errorMessages);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package dev.lions.unionflow.client.validation;
|
||||
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class MemberNumberValidator implements ConstraintValidator<ValidMemberNumber, String> {
|
||||
|
||||
// Pattern pour numéro de membre: M + année + numéro séquentiel
|
||||
private static final Pattern MEMBER_NUMBER_PATTERN = Pattern.compile("^M[0-9]{4}[0-9]{3,6}$");
|
||||
|
||||
@Override
|
||||
public void initialize(ValidMemberNumber constraintAnnotation) {
|
||||
// Initialisation si nécessaire
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(String memberNumber, ConstraintValidatorContext context) {
|
||||
// Null ou vide = invalide pour un numéro de membre
|
||||
if (memberNumber == null || memberNumber.trim().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Nettoyer le numéro (supprimer espaces)
|
||||
String cleanNumber = memberNumber.trim().toUpperCase();
|
||||
|
||||
// Vérifier le pattern
|
||||
if (!MEMBER_NUMBER_PATTERN.matcher(cleanNumber).matches()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Vérifier que l'année est raisonnable (entre 2020 et année actuelle + 1)
|
||||
try {
|
||||
String yearStr = cleanNumber.substring(1, 5);
|
||||
int year = Integer.parseInt(yearStr);
|
||||
int currentYear = java.time.Year.now().getValue();
|
||||
|
||||
if (year < 2020 || year > currentYear + 1) {
|
||||
context.disableDefaultConstraintViolation();
|
||||
context.buildConstraintViolationWithTemplate(
|
||||
"L'année dans le numéro de membre doit être entre 2020 et " + (currentYear + 1)
|
||||
).addConstraintViolation();
|
||||
return false;
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package dev.lions.unionflow.client.validation;
|
||||
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class PhoneNumberValidator implements ConstraintValidator<ValidPhoneNumber, String> {
|
||||
|
||||
// Patterns pour différents formats de téléphone africains
|
||||
private static final Pattern[] PHONE_PATTERNS = {
|
||||
Pattern.compile("^(\\+225|225)?[0-9]{8}$"), // Côte d'Ivoire
|
||||
Pattern.compile("^(\\+221|221)?[0-9]{9}$"), // Sénégal
|
||||
Pattern.compile("^(\\+226|226)?[0-9]{8}$"), // Burkina Faso
|
||||
Pattern.compile("^(\\+223|223)?[0-9]{8}$"), // Mali
|
||||
Pattern.compile("^(\\+228|228)?[0-9]{8}$"), // Togo
|
||||
Pattern.compile("^(\\+229|229)?[0-9]{8}$"), // Bénin
|
||||
Pattern.compile("^(\\+233|233)?[0-9]{9}$"), // Ghana
|
||||
Pattern.compile("^(\\+234|234)?[0-9]{10}$"), // Nigeria
|
||||
Pattern.compile("^[0-9]{8,15}$") // Format générique
|
||||
};
|
||||
|
||||
@Override
|
||||
public void initialize(ValidPhoneNumber constraintAnnotation) {
|
||||
// Initialisation si nécessaire
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(String phone, ConstraintValidatorContext context) {
|
||||
// Null ou vide = valide (utiliser @NotBlank si obligatoire)
|
||||
if (phone == null || phone.trim().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Nettoyer le numéro (supprimer espaces, tirets, etc.)
|
||||
String cleanPhone = phone.replaceAll("[\\s\\-\\(\\)\\.]", "");
|
||||
|
||||
// Vérifier contre tous les patterns
|
||||
for (Pattern pattern : PHONE_PATTERNS) {
|
||||
if (pattern.matcher(cleanPhone).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.lions.unionflow.client.validation;
|
||||
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Documented
|
||||
@Constraint(validatedBy = MemberNumberValidator.class)
|
||||
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ValidMemberNumber {
|
||||
|
||||
String message() default "Numéro de membre invalide. Format attendu: M + année + numéro (ex: M2024001)";
|
||||
|
||||
Class<?>[] groups() default {};
|
||||
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.lions.unionflow.client.validation;
|
||||
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Documented
|
||||
@Constraint(validatedBy = PhoneNumberValidator.class)
|
||||
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface ValidPhoneNumber {
|
||||
|
||||
String message() default "Numéro de téléphone invalide. Formats acceptés: +225XXXXXXXX, 0XXXXXXXXX, etc.";
|
||||
|
||||
Class<?>[] groups() default {};
|
||||
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package dev.lions.unionflow.client.validation;
|
||||
|
||||
/**
|
||||
* Groupes de validation pour différents cas d'usage dans UnionFlow
|
||||
*/
|
||||
public class ValidationGroups {
|
||||
|
||||
/**
|
||||
* Validation pour la création d'un nouveau membre
|
||||
*/
|
||||
public interface CreateMember {}
|
||||
|
||||
/**
|
||||
* Validation pour la mise à jour d'un membre existant
|
||||
*/
|
||||
public interface UpdateMember {}
|
||||
|
||||
/**
|
||||
* Validation pour la création d'une association
|
||||
*/
|
||||
public interface CreateAssociation {}
|
||||
|
||||
/**
|
||||
* Validation pour la mise à jour d'une association
|
||||
*/
|
||||
public interface UpdateAssociation {}
|
||||
|
||||
/**
|
||||
* Validation pour l'inscription rapide (champs minimum requis)
|
||||
*/
|
||||
public interface QuickRegistration {}
|
||||
|
||||
/**
|
||||
* Validation pour l'inscription complète (tous les champs)
|
||||
*/
|
||||
public interface FullRegistration {}
|
||||
|
||||
/**
|
||||
* Validation pour l'importation en masse
|
||||
*/
|
||||
public interface BulkImport {}
|
||||
|
||||
/**
|
||||
* Validation pour les données administratives
|
||||
*/
|
||||
public interface AdminData {}
|
||||
}
|
||||
596
src/main/java/dev/lions/unionflow/client/view/AdhesionsBean.java
Normal file
596
src/main/java/dev/lions/unionflow/client/view/AdhesionsBean.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.dto.FormulaireDTO;
|
||||
import dev.lions.unionflow.client.service.FormulaireService;
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
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.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("adminFormulaireBean")
|
||||
@SessionScoped
|
||||
public class AdminFormulaireBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(AdminFormulaireBean.class.getName());
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private FormulaireService formulaireService;
|
||||
|
||||
private List<FormulaireDTO> formulaires;
|
||||
private FormulaireDTO formulaireSelectionne;
|
||||
private FormulaireDTO nouveauFormulaire;
|
||||
private boolean modeEdition = false;
|
||||
private boolean modeCreation = false;
|
||||
|
||||
// Statistiques
|
||||
private int totalSouscriptions = 0;
|
||||
private BigDecimal revenusFormulaires = BigDecimal.ZERO;
|
||||
private String formulairePlusPopulaire = "";
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initializeData();
|
||||
}
|
||||
|
||||
private void initializeData() {
|
||||
formulaires = new ArrayList<>();
|
||||
try {
|
||||
formulaires = formulaireService.listerTous();
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des formulaires: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Initialiser les statistiques
|
||||
totalSouscriptions = 127; // Plus d'entités avec prix accessibles
|
||||
revenusFormulaires = new BigDecimal("381000"); // 127 * 3000 (moyenne)
|
||||
formulairePlusPopulaire = "Standard";
|
||||
}
|
||||
|
||||
// Actions CRUD
|
||||
public void nouveauFormulaire() {
|
||||
nouveauFormulaire = new FormulaireDTO();
|
||||
nouveauFormulaire.setActif(true);
|
||||
nouveauFormulaire.setDeviseCode("XOF");
|
||||
nouveauFormulaire.setGestionMembres(true);
|
||||
nouveauFormulaire.setGestionCotisations(true);
|
||||
modeCreation = true;
|
||||
modeEdition = false;
|
||||
}
|
||||
|
||||
public void editerFormulaire(FormulaireDTO formulaire) {
|
||||
this.formulaireSelectionne = formulaire;
|
||||
this.nouveauFormulaire = cloneFormulaire(formulaire);
|
||||
modeEdition = true;
|
||||
modeCreation = false;
|
||||
}
|
||||
|
||||
public void sauvegarderFormulaire() {
|
||||
if (modeCreation) {
|
||||
// Générer un nouvel ID UUID
|
||||
nouveauFormulaire.setId(UUID.randomUUID());
|
||||
nouveauFormulaire.setDateCreation(LocalDateTime.now());
|
||||
nouveauFormulaire.setCreePar("Admin");
|
||||
|
||||
formulaires.add(nouveauFormulaire);
|
||||
|
||||
} else if (modeEdition) {
|
||||
// Mettre à jour le formulaire existant
|
||||
int index = formulaires.indexOf(formulaireSelectionne);
|
||||
if (index >= 0) {
|
||||
nouveauFormulaire.setDateMiseAJour(LocalDateTime.now());
|
||||
nouveauFormulaire.setModifiePar("Admin");
|
||||
formulaires.set(index, nouveauFormulaire);
|
||||
}
|
||||
}
|
||||
|
||||
annulerEdition();
|
||||
}
|
||||
|
||||
public void supprimerFormulaire(FormulaireDTO formulaire) {
|
||||
// Vérifier s'il y a des souscriptions actives
|
||||
if (hasActiveSouscriptions(formulaire)) {
|
||||
// Désactiver au lieu de supprimer
|
||||
formulaire.setActif(false);
|
||||
} else {
|
||||
formulaires.remove(formulaire);
|
||||
}
|
||||
}
|
||||
|
||||
public void annulerEdition() {
|
||||
modeCreation = false;
|
||||
modeEdition = false;
|
||||
formulaireSelectionne = null;
|
||||
nouveauFormulaire = null;
|
||||
}
|
||||
|
||||
public void dupliquerFormulaire(FormulaireDTO formulaire) {
|
||||
FormulaireDTO copie = cloneFormulaire(formulaire);
|
||||
copie.setId(UUID.randomUUID());
|
||||
copie.setNom(formulaire.getNom() + " (Copie)");
|
||||
copie.setDateCreation(LocalDateTime.now());
|
||||
copie.setCreePar("Admin");
|
||||
|
||||
this.nouveauFormulaire = copie;
|
||||
modeCreation = true;
|
||||
modeEdition = false;
|
||||
}
|
||||
|
||||
public void activerDesactiverFormulaire(FormulaireDTO formulaire) {
|
||||
formulaire.setActif(!formulaire.isActif());
|
||||
formulaire.setDateMiseAJour(LocalDateTime.now());
|
||||
formulaire.setModifiePar("Admin");
|
||||
}
|
||||
|
||||
// Méthodes utilitaires
|
||||
private FormulaireDTO cloneFormulaire(FormulaireDTO original) {
|
||||
FormulaireDTO copie = new FormulaireDTO();
|
||||
copie.setId(original.getId());
|
||||
copie.setNom(original.getNom());
|
||||
copie.setDescription(original.getDescription());
|
||||
copie.setQuotaMaxMembres(original.getQuotaMaxMembres());
|
||||
copie.setPrixMensuel(original.getPrixMensuel());
|
||||
copie.setPrixAnnuel(original.getPrixAnnuel());
|
||||
copie.setDeviseCode(original.getDeviseCode());
|
||||
copie.setActif(original.isActif());
|
||||
copie.setRecommande(original.isRecommande());
|
||||
copie.setCouleurTheme(original.getCouleurTheme());
|
||||
copie.setIconeFormulaire(original.getIconeFormulaire());
|
||||
|
||||
// Fonctionnalités
|
||||
copie.setGestionMembres(original.isGestionMembres());
|
||||
copie.setGestionCotisations(original.isGestionCotisations());
|
||||
copie.setGestionEvenements(original.isGestionEvenements());
|
||||
copie.setGestionAides(original.isGestionAides());
|
||||
copie.setRapportsAvances(original.isRapportsAvances());
|
||||
copie.setSupportPrioritaire(original.isSupportPrioritaire());
|
||||
copie.setSauvegardeAutomatique(original.isSauvegardeAutomatique());
|
||||
copie.setPersonnalisationAvancee(original.isPersonnalisationAvancee());
|
||||
copie.setIntegrationPaiement(original.isIntegrationPaiement());
|
||||
copie.setNotificationsEmail(original.isNotificationsEmail());
|
||||
copie.setNotificationsSMS(original.isNotificationsSMS());
|
||||
copie.setGestionDocuments(original.isGestionDocuments());
|
||||
|
||||
// Métadonnées
|
||||
copie.setDateCreation(original.getDateCreation());
|
||||
copie.setDateMiseAJour(original.getDateMiseAJour());
|
||||
copie.setCreePar(original.getCreePar());
|
||||
copie.setModifiePar(original.getModifiePar());
|
||||
|
||||
return copie;
|
||||
}
|
||||
|
||||
private boolean hasActiveSouscriptions(FormulaireDTO formulaire) {
|
||||
// Simulation - vérifier s'il y a des souscriptions actives
|
||||
return "Standard".equals(formulaire.getNom()) || "Premium".equals(formulaire.getNom());
|
||||
}
|
||||
|
||||
public boolean canDeleteFormulaire(FormulaireDTO formulaire) {
|
||||
return !hasActiveSouscriptions(formulaire);
|
||||
}
|
||||
|
||||
public String getStatutFormulaire(FormulaireDTO formulaire) {
|
||||
if (formulaire.isActif()) {
|
||||
return hasActiveSouscriptions(formulaire) ? "Actif avec souscriptions" : "Actif";
|
||||
}
|
||||
return "Inactif";
|
||||
}
|
||||
|
||||
public String getCouleurStatut(FormulaireDTO formulaire) {
|
||||
if (formulaire.isActif()) {
|
||||
return hasActiveSouscriptions(formulaire) ? "text-green-600" : "text-blue-600";
|
||||
}
|
||||
return "text-gray-600";
|
||||
}
|
||||
|
||||
// Validation
|
||||
public boolean isFormulaireValide() {
|
||||
if (nouveauFormulaire == null) return false;
|
||||
|
||||
return nouveauFormulaire.getNom() != null && !nouveauFormulaire.getNom().trim().isEmpty() &&
|
||||
nouveauFormulaire.getQuotaMaxMembres() != null && nouveauFormulaire.getQuotaMaxMembres() > 0 &&
|
||||
nouveauFormulaire.getPrixMensuel() != null && nouveauFormulaire.getPrixMensuel().compareTo(BigDecimal.ZERO) > 0 &&
|
||||
nouveauFormulaire.getPrixAnnuel() != null && nouveauFormulaire.getPrixAnnuel().compareTo(BigDecimal.ZERO) > 0;
|
||||
}
|
||||
|
||||
// Listes pour les sélections
|
||||
public List<String> getCouleursTheme() {
|
||||
List<String> couleurs = new ArrayList<>();
|
||||
couleurs.add("bg-blue-500");
|
||||
couleurs.add("bg-green-500");
|
||||
couleurs.add("bg-purple-500");
|
||||
couleurs.add("bg-indigo-500");
|
||||
couleurs.add("bg-red-500");
|
||||
couleurs.add("bg-orange-500");
|
||||
couleurs.add("bg-yellow-500");
|
||||
couleurs.add("bg-teal-500");
|
||||
couleurs.add("bg-pink-500");
|
||||
return couleurs;
|
||||
}
|
||||
|
||||
public List<String> getIconesFormulaire() {
|
||||
List<String> icones = new ArrayList<>();
|
||||
icones.add("pi-star");
|
||||
icones.add("pi-users");
|
||||
icones.add("pi-crown");
|
||||
icones.add("pi-building");
|
||||
icones.add("pi-heart");
|
||||
icones.add("pi-shield");
|
||||
icones.add("pi-trophy");
|
||||
icones.add("pi-diamond");
|
||||
icones.add("pi-thumbs-up");
|
||||
return icones;
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public List<FormulaireDTO> getFormulaires() { return formulaires; }
|
||||
public void setFormulaires(List<FormulaireDTO> formulaires) { this.formulaires = formulaires; }
|
||||
|
||||
public FormulaireDTO getFormulaireSelectionne() { return formulaireSelectionne; }
|
||||
public void setFormulaireSelectionne(FormulaireDTO formulaireSelectionne) { this.formulaireSelectionne = formulaireSelectionne; }
|
||||
|
||||
public FormulaireDTO getNouveauFormulaire() { return nouveauFormulaire; }
|
||||
public void setNouveauFormulaire(FormulaireDTO nouveauFormulaire) { this.nouveauFormulaire = nouveauFormulaire; }
|
||||
|
||||
public boolean isModeEdition() { return modeEdition; }
|
||||
public void setModeEdition(boolean modeEdition) { this.modeEdition = modeEdition; }
|
||||
|
||||
public boolean isModeCreation() { return modeCreation; }
|
||||
public void setModeCreation(boolean modeCreation) { this.modeCreation = modeCreation; }
|
||||
|
||||
public int getTotalSouscriptions() { return totalSouscriptions; }
|
||||
public void setTotalSouscriptions(int totalSouscriptions) { this.totalSouscriptions = totalSouscriptions; }
|
||||
|
||||
public BigDecimal getRevenusFormulaires() { return revenusFormulaires; }
|
||||
public void setRevenusFormulaires(BigDecimal revenusFormulaires) { this.revenusFormulaires = revenusFormulaires; }
|
||||
|
||||
public String getFormulairePlusPopulaire() { return formulairePlusPopulaire; }
|
||||
public void setFormulairePlusPopulaire(String formulairePlusPopulaire) { this.formulairePlusPopulaire = formulairePlusPopulaire; }
|
||||
|
||||
public String getRevenusFormulairesFormat() {
|
||||
return String.format("%,.0f XOF", revenusFormulaires);
|
||||
}
|
||||
}
|
||||
554
src/main/java/dev/lions/unionflow/client/view/AuditBean.java
Normal file
554
src/main/java/dev/lions/unionflow/client/view/AuditBean.java
Normal file
@@ -0,0 +1,554 @@
|
||||
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;
|
||||
private Date dateFin;
|
||||
private String typeAction = "";
|
||||
private String severite = "";
|
||||
private String utilisateur = "";
|
||||
private String module = "";
|
||||
private String ipAddress = "";
|
||||
|
||||
// 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;
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
LOGGER.log(java.util.logging.Level.SEVERE, "Détails de l'erreur de chargement des logs d'audit", e);
|
||||
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();
|
||||
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
// 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()));
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Erreur lors de la conversion Map vers DTO: " + e.getMessage());
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
}
|
||||
|
||||
private boolean correspondAuxFiltres(AuditLogDTO log) {
|
||||
if (log.getDateHeure() == null) return false;
|
||||
|
||||
// Filtre par dates
|
||||
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 (dateFinLDT != null && log.getDateHeure().isAfter(dateFinLDT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filtre par type d'action
|
||||
if (!typeAction.isEmpty() && !typeAction.equals(log.getTypeAction())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filtre par sévérité
|
||||
if (!severite.isEmpty() && !severite.equals(log.getSeverite())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filtre par utilisateur
|
||||
if (!utilisateur.isEmpty() && log.getUtilisateur() != null &&
|
||||
!log.getUtilisateur().toLowerCase().contains(utilisateur.toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filtre par module
|
||||
if (!module.isEmpty() && !module.equals(log.getModule())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filtre par IP
|
||||
if (!ipAddress.isEmpty() && log.getIpAddress() != null &&
|
||||
!log.getIpAddress().contains(ipAddress)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recherche avec filtres via le backend
|
||||
*/
|
||||
public void rechercher() {
|
||||
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();
|
||||
cal.add(Calendar.DAY_OF_MONTH, -7);
|
||||
dateDebut = cal.getTime();
|
||||
|
||||
typeAction = "";
|
||||
severite = "";
|
||||
utilisateur = "";
|
||||
module = "";
|
||||
ipAddress = "";
|
||||
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualise les données
|
||||
*/
|
||||
public void actualiser() {
|
||||
chargerLogs();
|
||||
chargerStatistiques();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
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;
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public Date getDateFin() { return dateFin; }
|
||||
public void setDateFin(Date dateFin) {
|
||||
this.dateFin = dateFin;
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public String getTypeAction() { return typeAction; }
|
||||
public void setTypeAction(String typeAction) {
|
||||
this.typeAction = typeAction;
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public String getSeverite() { return severite; }
|
||||
public void setSeverite(String severite) {
|
||||
this.severite = severite;
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public String getUtilisateur() { return utilisateur; }
|
||||
public void setUtilisateur(String utilisateur) {
|
||||
this.utilisateur = utilisateur;
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public String getModule() { return module; }
|
||||
public void setModule(String module) {
|
||||
this.module = module;
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public String getIpAddress() { return ipAddress; }
|
||||
public void setIpAddress(String ipAddress) {
|
||||
this.ipAddress = ipAddress;
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,836 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.faces.application.FacesMessage;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("configurationBean")
|
||||
@SessionScoped
|
||||
public class ConfigurationBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(ConfigurationBean.class.getName());
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_SUPER_ADMIN_LOGS = "superAdminLogsPage";
|
||||
|
||||
private ConfigurationGenerale general;
|
||||
private ConfigurationSecurite securite;
|
||||
private ConfigurationEmail email;
|
||||
private ConfigurationPaiements paiements;
|
||||
private ConfigurationSysteme système;
|
||||
|
||||
// Propriétés pour la page système
|
||||
private String nomApplication = "UnionFlow";
|
||||
private String versionSysteme = "2.0.1";
|
||||
private String environnement = "PROD";
|
||||
private String timezone = "WAT";
|
||||
private String langueDefaut = "fr";
|
||||
private String deviseDefaut = "XOF";
|
||||
private String urlBaseApplication = "https://unionflow.app";
|
||||
private String formatDate = "dd/MM/yyyy";
|
||||
private String organisationPrincipale = "Lions Clubs Afrique de l'Ouest";
|
||||
|
||||
// Configuration BDD enrichie
|
||||
private String typeBDD = "postgresql";
|
||||
private String serveurBDD = "localhost";
|
||||
private Integer portBDD = 5432;
|
||||
private String nomBDD = "unionflow";
|
||||
private String utilisateurBDD = "unionflow_user";
|
||||
private String motDePasseBDD = "";
|
||||
private Integer taillePoolConnexions = 20;
|
||||
private Boolean sslActifBDD = true;
|
||||
|
||||
// Configuration Email enrichie
|
||||
private String serveurSMTP = "smtp.gmail.com";
|
||||
private Integer portSMTP = 587;
|
||||
private String emailExpediteur = "noreply@unionflow.app";
|
||||
private String nomExpediteur = "UnionFlow Notifications";
|
||||
private Boolean authentificationSMTP = true;
|
||||
private String utilisateurSMTP = "";
|
||||
private String motDePasseSMTP = "";
|
||||
private Boolean tlsActive = true;
|
||||
private Integer limiteTauxEmail = 500;
|
||||
|
||||
// Configuration Sécurité enrichie
|
||||
private Integer timeoutSession = 30;
|
||||
private Integer tentativesMaxConnexion = 5;
|
||||
private Boolean forcerChangementMotDePasse = true;
|
||||
private Boolean authentification2FA = true;
|
||||
private Boolean journaliserEvenementsSecurite = true;
|
||||
private String complexiteMotDePasse = "MEDIUM";
|
||||
private Integer dureeValiditeMotDePasse = 90;
|
||||
private Integer retentionLogs = 365;
|
||||
private Boolean chiffrementBDD = true;
|
||||
|
||||
// Propriétés d'état système
|
||||
private String tempsActivite = "N/A";
|
||||
private Integer utilisateursConnectes = 0;
|
||||
private Integer memoireUtilisee = 0;
|
||||
private String memoireTotal = "N/A";
|
||||
private String derniereSauvegarde = "N/A";
|
||||
|
||||
// Monitoring avancé
|
||||
private Integer cpuUtilisation = 45;
|
||||
private Float disqueDisponible = 127.5f;
|
||||
private Integer connexionsBDDActives = 15;
|
||||
private Integer queueEmailsEnAttente = 23;
|
||||
private Integer logsErreurs24h = 8;
|
||||
private Integer sessionsActives = 127;
|
||||
|
||||
// Configuration avancée
|
||||
private Boolean modeMaintenance = false;
|
||||
private String frequenceSauvegarde = "DAILY";
|
||||
private Integer retentionSauvegardes = 30;
|
||||
private String emailAlertes = "admin@unionflow.app";
|
||||
private Boolean alertesCPU = true;
|
||||
private Boolean alertesMemoire = true;
|
||||
private Boolean alertesDisque = true;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initializeGeneral();
|
||||
initializeSecurite();
|
||||
initializeEmail();
|
||||
initializePaiements();
|
||||
initializeSysteme();
|
||||
initSauvegardes();
|
||||
calculerMetriquesSysteme();
|
||||
}
|
||||
|
||||
private void calculerMetriquesSysteme() {
|
||||
// TODO: Récupérer les métriques système depuis un service de monitoring
|
||||
// Pour l'instant, initialiser avec des valeurs par défaut
|
||||
cpuUtilisation = 0;
|
||||
memoireUtilisee = 0;
|
||||
disqueDisponible = 0.0f;
|
||||
connexionsBDDActives = 0;
|
||||
queueEmailsEnAttente = 0;
|
||||
logsErreurs24h = 0;
|
||||
utilisateursConnectes = 0;
|
||||
sessionsActives = 0;
|
||||
}
|
||||
|
||||
private void initializeGeneral() {
|
||||
general = new ConfigurationGenerale();
|
||||
general.setNomOrganisation("Organisation Centrale");
|
||||
general.setSigleOrganisation("ORG-001");
|
||||
general.setSiteWeb("https://unionflow.app");
|
||||
general.setEmailContact("contact@unionflow.app");
|
||||
general.setLangueDefaut("fr");
|
||||
general.setDevise("XOF");
|
||||
general.setFuseauHoraire("GMT");
|
||||
general.setModeMaintenanceActif(false);
|
||||
}
|
||||
|
||||
private void initializeSecurite() {
|
||||
securite = new ConfigurationSecurite();
|
||||
securite.setLongueurMinMotPasse(8);
|
||||
securite.setExigerMajuscules(true);
|
||||
securite.setExigerChiffres(true);
|
||||
securite.setExigerCaracteresSpeciaux(false);
|
||||
securite.setExpirationMotPasse(90);
|
||||
securite.setTentativesConnexionMax(5);
|
||||
securite.setDureeBlocage(15);
|
||||
securite.setTimeoutSession(60);
|
||||
securite.setDoubleFacteurObligatoire(false);
|
||||
securite.setJournalisationAvancee(true);
|
||||
}
|
||||
|
||||
private void initializeEmail() {
|
||||
email = new ConfigurationEmail();
|
||||
email.setServeurSMTP("smtp.gmail.com");
|
||||
email.setPortSMTP(587);
|
||||
email.setUtilisateurSMTP("noreply@unionflow.app");
|
||||
email.setMotPasseSMTP("**********");
|
||||
email.setUtiliserSSL(true);
|
||||
email.setEmailExpediteur("noreply@unionflow.app");
|
||||
email.setNomExpediteur("UnionFlow Platform");
|
||||
email.setNotifierNouveauMembre(true);
|
||||
email.setNotifierEvenements(true);
|
||||
email.setRappelCotisations(true);
|
||||
}
|
||||
|
||||
private void initializePaiements() {
|
||||
paiements = new ConfigurationPaiements();
|
||||
paiements.setWaveActif(true);
|
||||
paiements.setWaveApiKey("**********");
|
||||
paiements.setWaveSecretKey("**********");
|
||||
paiements.setWaveEnvironnement("sandbox");
|
||||
paiements.setEspècesActif(true);
|
||||
paiements.setChèqueActif(true);
|
||||
paiements.setVirementActif(true);
|
||||
paiements.setIbanOrganisation("CI05 CI01 2345 6789 0123 4567 89");
|
||||
paiements.setFraisPaiement(2.5);
|
||||
}
|
||||
|
||||
private void initializeSysteme() {
|
||||
système = new ConfigurationSysteme();
|
||||
système.setCacheActivé(true);
|
||||
système.setDureeCacheMinutes(30);
|
||||
système.setTailleLotTraitement(100);
|
||||
système.setNiveauLog("INFO");
|
||||
système.setRetentionLogJours(30);
|
||||
système.setMétriquesActivées(true);
|
||||
système.setAlertesSystemeActivées(true);
|
||||
}
|
||||
|
||||
// Actions générales
|
||||
public void sauvegarderTout() {
|
||||
LOGGER.info("Configuration complète sauvegardée à " + LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")));
|
||||
}
|
||||
|
||||
public void reinitialiser() {
|
||||
init();
|
||||
LOGGER.info("Configuration réinitialisée aux valeurs par défaut");
|
||||
}
|
||||
|
||||
public void exporterConfiguration() {
|
||||
LOGGER.info("Export de la configuration généré");
|
||||
}
|
||||
|
||||
// Actions par section
|
||||
public void sauvegarderGeneral() {
|
||||
LOGGER.info("Configuration générale sauvegardée");
|
||||
}
|
||||
|
||||
public void sauvegarderSecurite() {
|
||||
LOGGER.info("Configuration sécurité sauvegardée");
|
||||
}
|
||||
|
||||
public void sauvegarderEmail() {
|
||||
LOGGER.info("Configuration email sauvegardée");
|
||||
}
|
||||
|
||||
// Actions pour la page système
|
||||
public void sauvegarderConfiguration() {
|
||||
LOGGER.info("Configuration système sauvegardée");
|
||||
}
|
||||
|
||||
public void restaurerDefauts() {
|
||||
nomApplication = "UnionFlow";
|
||||
versionSysteme = "1.0.0";
|
||||
environnement = "DEV";
|
||||
LOGGER.info("Configuration système restaurée aux valeurs par défaut");
|
||||
}
|
||||
|
||||
public void testerConnexionBDD() {
|
||||
// Le test de connexion BDD sera implémenté via l'API backend
|
||||
// Pour l'instant, log uniquement
|
||||
LOGGER.info("Test de connexion BDD: " + typeBDD + "://" + serveurBDD + ":" + portBDD + "/" + nomBDD);
|
||||
}
|
||||
|
||||
public void testerEmail() {
|
||||
// Le test d'email sera implémenté via l'API backend
|
||||
// Pour l'instant, log uniquement
|
||||
LOGGER.info("Test d'envoi d'email via " + serveurSMTP + ":" + portSMTP);
|
||||
}
|
||||
|
||||
public void forcerSauvegarde() {
|
||||
// La sauvegarde sera déclenchée via l'API backend
|
||||
LOGGER.info("Sauvegarde forcée du système");
|
||||
derniereSauvegarde = LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm"));
|
||||
}
|
||||
|
||||
public void redemarrerServices() {
|
||||
// Le redémarrage des services sera géré via l'API backend
|
||||
LOGGER.info("Redémarrage des services système en cours...");
|
||||
}
|
||||
|
||||
public void sauvegarderPaiements() {
|
||||
LOGGER.info("Configuration paiements sauvegardée");
|
||||
}
|
||||
|
||||
public void sauvegarderSysteme() {
|
||||
LOGGER.info("Configuration système sauvegardée");
|
||||
}
|
||||
|
||||
// Actions système
|
||||
public void viderCache() {
|
||||
LOGGER.info("Cache vidé avec succès");
|
||||
}
|
||||
|
||||
public void optimiserBaseDonnees() {
|
||||
LOGGER.info("Optimisation de la base de données en cours...");
|
||||
}
|
||||
|
||||
public void sauvegarderBaseDonnees() {
|
||||
LOGGER.info("Sauvegarde de la base de données initiée");
|
||||
}
|
||||
|
||||
public String voirLogsSysteme() {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_SUPER_ADMIN_LOGS + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public ConfigurationGenerale getGeneral() { return general; }
|
||||
public void setGeneral(ConfigurationGenerale general) { this.general = general; }
|
||||
|
||||
public ConfigurationSecurite getSecurite() { return securite; }
|
||||
public void setSecurite(ConfigurationSecurite securite) { this.securite = securite; }
|
||||
|
||||
public ConfigurationEmail getEmail() { return email; }
|
||||
public void setEmail(ConfigurationEmail email) { this.email = email; }
|
||||
|
||||
public ConfigurationPaiements getPaiements() { return paiements; }
|
||||
public void setPaiements(ConfigurationPaiements paiements) { this.paiements = paiements; }
|
||||
|
||||
public ConfigurationSysteme getSystème() { return système; }
|
||||
public void setSystème(ConfigurationSysteme système) { this.système = système; }
|
||||
|
||||
// Classes internes pour la configuration
|
||||
public static class ConfigurationGenerale {
|
||||
private String nomOrganisation;
|
||||
private String sigleOrganisation;
|
||||
private String siteWeb;
|
||||
private String emailContact;
|
||||
private String langueDefaut;
|
||||
private String devise;
|
||||
private String fuseauHoraire;
|
||||
private boolean modeMaintenanceActif;
|
||||
|
||||
// Getters et setters
|
||||
public String getNomOrganisation() { return nomOrganisation; }
|
||||
public void setNomOrganisation(String nomOrganisation) { this.nomOrganisation = nomOrganisation; }
|
||||
|
||||
public String getSigleOrganisation() { return sigleOrganisation; }
|
||||
public void setSigleOrganisation(String sigleOrganisation) { this.sigleOrganisation = sigleOrganisation; }
|
||||
|
||||
public String getSiteWeb() { return siteWeb; }
|
||||
public void setSiteWeb(String siteWeb) { this.siteWeb = siteWeb; }
|
||||
|
||||
public String getEmailContact() { return emailContact; }
|
||||
public void setEmailContact(String emailContact) { this.emailContact = emailContact; }
|
||||
|
||||
public String getLangueDefaut() { return langueDefaut; }
|
||||
public void setLangueDefaut(String langueDefaut) { this.langueDefaut = langueDefaut; }
|
||||
|
||||
public String getDevise() { return devise; }
|
||||
public void setDevise(String devise) { this.devise = devise; }
|
||||
|
||||
public String getFuseauHoraire() { return fuseauHoraire; }
|
||||
public void setFuseauHoraire(String fuseauHoraire) { this.fuseauHoraire = fuseauHoraire; }
|
||||
|
||||
public boolean isModeMaintenanceActif() { return modeMaintenanceActif; }
|
||||
public void setModeMaintenanceActif(boolean modeMaintenanceActif) { this.modeMaintenanceActif = modeMaintenanceActif; }
|
||||
}
|
||||
|
||||
public static class ConfigurationSecurite {
|
||||
private int longueurMinMotPasse;
|
||||
private boolean exigerMajuscules;
|
||||
private boolean exigerChiffres;
|
||||
private boolean exigerCaracteresSpeciaux;
|
||||
private int expirationMotPasse;
|
||||
private int tentativesConnexionMax;
|
||||
private int dureeBlocage;
|
||||
private int timeoutSession;
|
||||
private boolean doubleFacteurObligatoire;
|
||||
private boolean journalisationAvancee;
|
||||
|
||||
// Getters et setters
|
||||
public int getLongueurMinMotPasse() { return longueurMinMotPasse; }
|
||||
public void setLongueurMinMotPasse(int longueurMinMotPasse) { this.longueurMinMotPasse = longueurMinMotPasse; }
|
||||
|
||||
public boolean isExigerMajuscules() { return exigerMajuscules; }
|
||||
public void setExigerMajuscules(boolean exigerMajuscules) { this.exigerMajuscules = exigerMajuscules; }
|
||||
|
||||
public boolean isExigerChiffres() { return exigerChiffres; }
|
||||
public void setExigerChiffres(boolean exigerChiffres) { this.exigerChiffres = exigerChiffres; }
|
||||
|
||||
public boolean isExigerCaracteresSpeciaux() { return exigerCaracteresSpeciaux; }
|
||||
public void setExigerCaracteresSpeciaux(boolean exigerCaracteresSpeciaux) { this.exigerCaracteresSpeciaux = exigerCaracteresSpeciaux; }
|
||||
|
||||
public int getExpirationMotPasse() { return expirationMotPasse; }
|
||||
public void setExpirationMotPasse(int expirationMotPasse) { this.expirationMotPasse = expirationMotPasse; }
|
||||
|
||||
public int getTentativesConnexionMax() { return tentativesConnexionMax; }
|
||||
public void setTentativesConnexionMax(int tentativesConnexionMax) { this.tentativesConnexionMax = tentativesConnexionMax; }
|
||||
|
||||
public int getDureeBlocage() { return dureeBlocage; }
|
||||
public void setDureeBlocage(int dureeBlocage) { this.dureeBlocage = dureeBlocage; }
|
||||
|
||||
public int getTimeoutSession() { return timeoutSession; }
|
||||
public void setTimeoutSession(int timeoutSession) { this.timeoutSession = timeoutSession; }
|
||||
|
||||
public boolean isDoubleFacteurObligatoire() { return doubleFacteurObligatoire; }
|
||||
public void setDoubleFacteurObligatoire(boolean doubleFacteurObligatoire) { this.doubleFacteurObligatoire = doubleFacteurObligatoire; }
|
||||
|
||||
public boolean isJournalisationAvancee() { return journalisationAvancee; }
|
||||
public void setJournalisationAvancee(boolean journalisationAvancee) { this.journalisationAvancee = journalisationAvancee; }
|
||||
}
|
||||
|
||||
public static class ConfigurationEmail {
|
||||
private String serveurSMTP;
|
||||
private int portSMTP;
|
||||
private String utilisateurSMTP;
|
||||
private String motPasseSMTP;
|
||||
private boolean utiliserSSL;
|
||||
private String emailExpediteur;
|
||||
private String nomExpediteur;
|
||||
private boolean notifierNouveauMembre;
|
||||
private boolean notifierEvenements;
|
||||
private boolean rappelCotisations;
|
||||
|
||||
// Getters et setters
|
||||
public String getServeurSMTP() { return serveurSMTP; }
|
||||
public void setServeurSMTP(String serveurSMTP) { this.serveurSMTP = serveurSMTP; }
|
||||
|
||||
public int getPortSMTP() { return portSMTP; }
|
||||
public void setPortSMTP(int portSMTP) { this.portSMTP = portSMTP; }
|
||||
|
||||
public String getUtilisateurSMTP() { return utilisateurSMTP; }
|
||||
public void setUtilisateurSMTP(String utilisateurSMTP) { this.utilisateurSMTP = utilisateurSMTP; }
|
||||
|
||||
public String getMotPasseSMTP() { return motPasseSMTP; }
|
||||
public void setMotPasseSMTP(String motPasseSMTP) { this.motPasseSMTP = motPasseSMTP; }
|
||||
|
||||
public boolean isUtiliserSSL() { return utiliserSSL; }
|
||||
public void setUtiliserSSL(boolean utiliserSSL) { this.utiliserSSL = utiliserSSL; }
|
||||
|
||||
public String getEmailExpediteur() { return emailExpediteur; }
|
||||
public void setEmailExpediteur(String emailExpediteur) { this.emailExpediteur = emailExpediteur; }
|
||||
|
||||
public String getNomExpediteur() { return nomExpediteur; }
|
||||
public void setNomExpediteur(String nomExpediteur) { this.nomExpediteur = nomExpediteur; }
|
||||
|
||||
public boolean isNotifierNouveauMembre() { return notifierNouveauMembre; }
|
||||
public void setNotifierNouveauMembre(boolean notifierNouveauMembre) { this.notifierNouveauMembre = notifierNouveauMembre; }
|
||||
|
||||
public boolean isNotifierEvenements() { return notifierEvenements; }
|
||||
public void setNotifierEvenements(boolean notifierEvenements) { this.notifierEvenements = notifierEvenements; }
|
||||
|
||||
public boolean isRappelCotisations() { return rappelCotisations; }
|
||||
public void setRappelCotisations(boolean rappelCotisations) { this.rappelCotisations = rappelCotisations; }
|
||||
}
|
||||
|
||||
public static class ConfigurationPaiements {
|
||||
private boolean waveActif;
|
||||
private String waveApiKey;
|
||||
private String waveSecretKey;
|
||||
private String waveEnvironnement;
|
||||
private boolean espècesActif;
|
||||
private boolean chèqueActif;
|
||||
private boolean virementActif;
|
||||
private String ibanOrganisation;
|
||||
private double fraisPaiement;
|
||||
|
||||
// Getters et setters
|
||||
public boolean isWaveActif() { return waveActif; }
|
||||
public void setWaveActif(boolean waveActif) { this.waveActif = waveActif; }
|
||||
|
||||
public String getWaveApiKey() { return waveApiKey; }
|
||||
public void setWaveApiKey(String waveApiKey) { this.waveApiKey = waveApiKey; }
|
||||
|
||||
public String getWaveSecretKey() { return waveSecretKey; }
|
||||
public void setWaveSecretKey(String waveSecretKey) { this.waveSecretKey = waveSecretKey; }
|
||||
|
||||
public String getWaveEnvironnement() { return waveEnvironnement; }
|
||||
public void setWaveEnvironnement(String waveEnvironnement) { this.waveEnvironnement = waveEnvironnement; }
|
||||
|
||||
public boolean isEspècesActif() { return espècesActif; }
|
||||
public void setEspècesActif(boolean espècesActif) { this.espècesActif = espècesActif; }
|
||||
|
||||
public boolean isChèqueActif() { return chèqueActif; }
|
||||
public void setChèqueActif(boolean chèqueActif) { this.chèqueActif = chèqueActif; }
|
||||
|
||||
public boolean isVirementActif() { return virementActif; }
|
||||
public void setVirementActif(boolean virementActif) { this.virementActif = virementActif; }
|
||||
|
||||
public String getIbanOrganisation() { return ibanOrganisation; }
|
||||
public void setIbanOrganisation(String ibanOrganisation) { this.ibanOrganisation = ibanOrganisation; }
|
||||
|
||||
public double getFraisPaiement() { return fraisPaiement; }
|
||||
public void setFraisPaiement(double fraisPaiement) { this.fraisPaiement = fraisPaiement; }
|
||||
}
|
||||
|
||||
// Getters et setters pour les propriétés système
|
||||
public String getNomApplication() { return nomApplication; }
|
||||
public void setNomApplication(String nomApplication) { this.nomApplication = nomApplication; }
|
||||
|
||||
public String getVersionSysteme() { return versionSysteme; }
|
||||
public void setVersionSysteme(String versionSysteme) { this.versionSysteme = versionSysteme; }
|
||||
|
||||
public String getEnvironnement() { return environnement; }
|
||||
public void setEnvironnement(String environnement) { this.environnement = environnement; }
|
||||
|
||||
public String getTimezone() { return timezone; }
|
||||
public void setTimezone(String timezone) { this.timezone = timezone; }
|
||||
|
||||
public String getLangueDefaut() { return langueDefaut; }
|
||||
public void setLangueDefaut(String langueDefaut) { this.langueDefaut = langueDefaut; }
|
||||
|
||||
public String getTypeBDD() { return typeBDD; }
|
||||
public void setTypeBDD(String typeBDD) { this.typeBDD = typeBDD; }
|
||||
|
||||
public String getServeurBDD() { return serveurBDD; }
|
||||
public void setServeurBDD(String serveurBDD) { this.serveurBDD = serveurBDD; }
|
||||
|
||||
public Integer getPortBDD() { return portBDD; }
|
||||
public void setPortBDD(Integer portBDD) { this.portBDD = portBDD; }
|
||||
|
||||
public String getNomBDD() { return nomBDD; }
|
||||
public void setNomBDD(String nomBDD) { this.nomBDD = nomBDD; }
|
||||
|
||||
public String getServeurSMTP() { return serveurSMTP; }
|
||||
public void setServeurSMTP(String serveurSMTP) { this.serveurSMTP = serveurSMTP; }
|
||||
|
||||
public Integer getPortSMTP() { return portSMTP; }
|
||||
public void setPortSMTP(Integer portSMTP) { this.portSMTP = portSMTP; }
|
||||
|
||||
public String getEmailExpediteur() { return emailExpediteur; }
|
||||
public void setEmailExpediteur(String emailExpediteur) { this.emailExpediteur = emailExpediteur; }
|
||||
|
||||
public Boolean getAuthentificationSMTP() { return authentificationSMTP; }
|
||||
public void setAuthentificationSMTP(Boolean authentificationSMTP) { this.authentificationSMTP = authentificationSMTP; }
|
||||
|
||||
public Boolean getTlsActive() { return tlsActive; }
|
||||
public void setTlsActive(Boolean tlsActive) { this.tlsActive = tlsActive; }
|
||||
|
||||
public Integer getTimeoutSession() { return timeoutSession; }
|
||||
public void setTimeoutSession(Integer timeoutSession) { this.timeoutSession = timeoutSession; }
|
||||
|
||||
public Integer getTentativesMaxConnexion() { return tentativesMaxConnexion; }
|
||||
public void setTentativesMaxConnexion(Integer tentativesMaxConnexion) { this.tentativesMaxConnexion = tentativesMaxConnexion; }
|
||||
|
||||
public Boolean getForcerChangementMotDePasse() { return forcerChangementMotDePasse; }
|
||||
public void setForcerChangementMotDePasse(Boolean forcerChangementMotDePasse) { this.forcerChangementMotDePasse = forcerChangementMotDePasse; }
|
||||
|
||||
public Boolean getAuthentification2FA() { return authentification2FA; }
|
||||
public void setAuthentification2FA(Boolean authentification2FA) { this.authentification2FA = authentification2FA; }
|
||||
|
||||
public Boolean getJournaliserEvenementsSecurite() { return journaliserEvenementsSecurite; }
|
||||
public void setJournaliserEvenementsSecurite(Boolean journaliserEvenementsSecurite) { this.journaliserEvenementsSecurite = journaliserEvenementsSecurite; }
|
||||
|
||||
public String getTempsActivite() { return tempsActivite; }
|
||||
public void setTempsActivite(String tempsActivite) { this.tempsActivite = tempsActivite; }
|
||||
|
||||
public Integer getUtilisateursConnectes() { return utilisateursConnectes; }
|
||||
public void setUtilisateursConnectes(Integer utilisateursConnectes) { this.utilisateursConnectes = utilisateursConnectes; }
|
||||
|
||||
public Integer getMemoireUtilisee() { return memoireUtilisee; }
|
||||
public void setMemoireUtilisee(Integer memoireUtilisee) { this.memoireUtilisee = memoireUtilisee; }
|
||||
|
||||
public String getMemoireTotal() { return memoireTotal; }
|
||||
public void setMemoireTotal(String memoireTotal) { this.memoireTotal = memoireTotal; }
|
||||
|
||||
public String getDerniereSauvegarde() { return derniereSauvegarde; }
|
||||
public void setDerniereSauvegarde(String derniereSauvegarde) { this.derniereSauvegarde = derniereSauvegarde; }
|
||||
|
||||
// Nouveaux getters/setters pour configuration enrichie
|
||||
public String getDeviseDefaut() { return deviseDefaut; }
|
||||
public void setDeviseDefaut(String deviseDefaut) { this.deviseDefaut = deviseDefaut; }
|
||||
|
||||
public String getUrlBaseApplication() { return urlBaseApplication; }
|
||||
public void setUrlBaseApplication(String urlBaseApplication) { this.urlBaseApplication = urlBaseApplication; }
|
||||
|
||||
public String getFormatDate() { return formatDate; }
|
||||
public void setFormatDate(String formatDate) { this.formatDate = formatDate; }
|
||||
|
||||
public String getOrganisationPrincipale() { return organisationPrincipale; }
|
||||
public void setOrganisationPrincipale(String organisationPrincipale) { this.organisationPrincipale = organisationPrincipale; }
|
||||
|
||||
public String getUtilisateurBDD() { return utilisateurBDD; }
|
||||
public void setUtilisateurBDD(String utilisateurBDD) { this.utilisateurBDD = utilisateurBDD; }
|
||||
|
||||
public String getMotDePasseBDD() { return motDePasseBDD; }
|
||||
public void setMotDePasseBDD(String motDePasseBDD) { this.motDePasseBDD = motDePasseBDD; }
|
||||
|
||||
public Integer getTaillePoolConnexions() { return taillePoolConnexions; }
|
||||
public void setTaillePoolConnexions(Integer taillePoolConnexions) { this.taillePoolConnexions = taillePoolConnexions; }
|
||||
|
||||
public Boolean getSslActifBDD() { return sslActifBDD; }
|
||||
public void setSslActifBDD(Boolean sslActifBDD) { this.sslActifBDD = sslActifBDD; }
|
||||
|
||||
public String getNomExpediteur() { return nomExpediteur; }
|
||||
public void setNomExpediteur(String nomExpediteur) { this.nomExpediteur = nomExpediteur; }
|
||||
|
||||
public String getUtilisateurSMTP() { return utilisateurSMTP; }
|
||||
public void setUtilisateurSMTP(String utilisateurSMTP) { this.utilisateurSMTP = utilisateurSMTP; }
|
||||
|
||||
public String getMotDePasseSMTP() { return motDePasseSMTP; }
|
||||
public void setMotDePasseSMTP(String motDePasseSMTP) { this.motDePasseSMTP = motDePasseSMTP; }
|
||||
|
||||
public Integer getLimiteTauxEmail() { return limiteTauxEmail; }
|
||||
public void setLimiteTauxEmail(Integer limiteTauxEmail) { this.limiteTauxEmail = limiteTauxEmail; }
|
||||
|
||||
public String getComplexiteMotDePasse() { return complexiteMotDePasse; }
|
||||
public void setComplexiteMotDePasse(String complexiteMotDePasse) { this.complexiteMotDePasse = complexiteMotDePasse; }
|
||||
|
||||
public Integer getDureeValiditeMotDePasse() { return dureeValiditeMotDePasse; }
|
||||
public void setDureeValiditeMotDePasse(Integer dureeValiditeMotDePasse) { this.dureeValiditeMotDePasse = dureeValiditeMotDePasse; }
|
||||
|
||||
public Integer getRetentionLogs() { return retentionLogs; }
|
||||
public void setRetentionLogs(Integer retentionLogs) { this.retentionLogs = retentionLogs; }
|
||||
|
||||
public Boolean getChiffrementBDD() { return chiffrementBDD; }
|
||||
public void setChiffrementBDD(Boolean chiffrementBDD) { this.chiffrementBDD = chiffrementBDD; }
|
||||
|
||||
public Integer getCpuUtilisation() { return cpuUtilisation; }
|
||||
public void setCpuUtilisation(Integer cpuUtilisation) { this.cpuUtilisation = cpuUtilisation; }
|
||||
|
||||
public Float getDisqueDisponible() { return disqueDisponible; }
|
||||
public void setDisqueDisponible(Float disqueDisponible) { this.disqueDisponible = disqueDisponible; }
|
||||
|
||||
public Integer getConnexionsBDDActives() { return connexionsBDDActives; }
|
||||
public void setConnexionsBDDActives(Integer connexionsBDDActives) { this.connexionsBDDActives = connexionsBDDActives; }
|
||||
|
||||
public Integer getQueueEmailsEnAttente() { return queueEmailsEnAttente; }
|
||||
public void setQueueEmailsEnAttente(Integer queueEmailsEnAttente) { this.queueEmailsEnAttente = queueEmailsEnAttente; }
|
||||
|
||||
public Integer getLogsErreurs24h() { return logsErreurs24h; }
|
||||
public void setLogsErreurs24h(Integer logsErreurs24h) { this.logsErreurs24h = logsErreurs24h; }
|
||||
|
||||
public Integer getSessionsActives() { return sessionsActives; }
|
||||
public void setSessionsActives(Integer sessionsActives) { this.sessionsActives = sessionsActives; }
|
||||
|
||||
public Boolean getModeMaintenance() { return modeMaintenance; }
|
||||
public void setModeMaintenance(Boolean modeMaintenance) { this.modeMaintenance = modeMaintenance; }
|
||||
|
||||
public String getFrequenceSauvegarde() { return frequenceSauvegarde; }
|
||||
public void setFrequenceSauvegarde(String frequenceSauvegarde) { this.frequenceSauvegarde = frequenceSauvegarde; }
|
||||
|
||||
public Integer getRetentionSauvegardes() { return retentionSauvegardes; }
|
||||
public void setRetentionSauvegardes(Integer retentionSauvegardes) { this.retentionSauvegardes = retentionSauvegardes; }
|
||||
|
||||
public String getEmailAlertes() { return emailAlertes; }
|
||||
public void setEmailAlertes(String emailAlertes) { this.emailAlertes = emailAlertes; }
|
||||
|
||||
public Boolean getAlertesCPU() { return alertesCPU; }
|
||||
public void setAlertesCPU(Boolean alertesCPU) { this.alertesCPU = alertesCPU; }
|
||||
|
||||
public Boolean getAlertesMemoire() { return alertesMemoire; }
|
||||
public void setAlertesMemoire(Boolean alertesMemoire) { this.alertesMemoire = alertesMemoire; }
|
||||
|
||||
public Boolean getAlertesDisque() { return alertesDisque; }
|
||||
public void setAlertesDisque(Boolean alertesDisque) { this.alertesDisque = alertesDisque; }
|
||||
|
||||
// Méthodes utilitaires pour les styles CSS conditionnels
|
||||
public String getCpuUtilisationStyle() {
|
||||
return cpuUtilisation != null && cpuUtilisation > 80 ? "text-red-500" : "text-green-500";
|
||||
}
|
||||
|
||||
public String getDisqueDisponibleStyle() {
|
||||
return disqueDisponible != null && disqueDisponible < 10 ? "text-red-500" : "text-blue-500";
|
||||
}
|
||||
|
||||
public String getQueueEmailsStyle() {
|
||||
return queueEmailsEnAttente != null && queueEmailsEnAttente > 100 ? "text-orange-500" : "text-green-500";
|
||||
}
|
||||
|
||||
public String getLogsErreursStyle() {
|
||||
return logsErreurs24h != null && logsErreurs24h > 50 ? "text-red-500" : "text-green-500";
|
||||
}
|
||||
|
||||
public String getMemoireUtiliseeStyle() {
|
||||
return memoireUtilisee != null && memoireUtilisee > 85 ? "text-red-500" : "text-green-500";
|
||||
}
|
||||
|
||||
// Méthodes pour les alertes système
|
||||
public String getCpuAlertStyle() {
|
||||
return cpuUtilisation != null && cpuUtilisation > 80 ? "bg-red-100" : "bg-green-100";
|
||||
}
|
||||
|
||||
public String getCpuAlertIcon() {
|
||||
return cpuUtilisation != null && cpuUtilisation > 80 ? "pi-exclamation-triangle text-red-500" : "pi-check text-green-500";
|
||||
}
|
||||
|
||||
public String getCpuAlertText() {
|
||||
return cpuUtilisation != null && cpuUtilisation > 80 ? "ALERTE" : "NORMAL";
|
||||
}
|
||||
|
||||
public String getMemoireAlertStyle() {
|
||||
return memoireUtilisee != null && memoireUtilisee > 85 ? "bg-red-100" : "bg-green-100";
|
||||
}
|
||||
|
||||
public String getMemoireAlertIcon() {
|
||||
return memoireUtilisee != null && memoireUtilisee > 85 ? "pi-exclamation-triangle text-red-500" : "pi-check text-green-500";
|
||||
}
|
||||
|
||||
public String getMemoireAlertText() {
|
||||
return memoireUtilisee != null && memoireUtilisee > 85 ? "ALERTE" : "NORMAL";
|
||||
}
|
||||
|
||||
public String getDisqueAlertStyle() {
|
||||
return disqueDisponible != null && disqueDisponible < 10 ? "bg-red-100" : "bg-green-100";
|
||||
}
|
||||
|
||||
public String getDisqueAlertIcon() {
|
||||
return disqueDisponible != null && disqueDisponible < 10 ? "pi-exclamation-triangle text-red-500" : "pi-check text-green-500";
|
||||
}
|
||||
|
||||
public String getDisqueAlertText() {
|
||||
return disqueDisponible != null && disqueDisponible < 10 ? "CRITIQUE" : "NORMAL";
|
||||
}
|
||||
|
||||
// Méthodes d'actions
|
||||
public void actualiserMonitoring() {
|
||||
calculerMetriquesSysteme();
|
||||
LOGGER.info("Monitoring actualisé");
|
||||
}
|
||||
|
||||
public void nettoyerCache() {
|
||||
LOGGER.info("Cache système nettoyé");
|
||||
}
|
||||
|
||||
public void auditSysteme() {
|
||||
LOGGER.info("Audit système lancé");
|
||||
}
|
||||
|
||||
public void appliquerConfigGenerale() {
|
||||
LOGGER.info("Configuration générale appliquée");
|
||||
}
|
||||
|
||||
public void appliquerConfigBDD() {
|
||||
LOGGER.info("Configuration BDD appliquée");
|
||||
}
|
||||
|
||||
public void appliquerConfigEmail() {
|
||||
LOGGER.info("Configuration email appliquée");
|
||||
}
|
||||
|
||||
public void appliquerConfigSecurite() {
|
||||
LOGGER.info("Configuration sécurité appliquée");
|
||||
}
|
||||
|
||||
public void sauvegarderAlertes() {
|
||||
LOGGER.info("Configuration des alertes sauvegardée");
|
||||
}
|
||||
|
||||
// Propriétés et méthodes pour les sauvegardes (WOU/DRY)
|
||||
private List<Sauvegarde> sauvegardes = new ArrayList<>();
|
||||
|
||||
public void initSauvegardes() {
|
||||
chargerSauvegardes();
|
||||
}
|
||||
|
||||
private void chargerSauvegardes() {
|
||||
sauvegardes = new ArrayList<>();
|
||||
|
||||
try {
|
||||
// TODO: Implémenter l'appel au service de sauvegarde quand il sera disponible côté serveur
|
||||
// Exemple: sauvegardes = sauvegardeService.listerSauvegardes()
|
||||
// .stream()
|
||||
// .map(dto -> convertToSauvegarde(dto))
|
||||
// .collect(Collectors.toList());
|
||||
|
||||
// Pour l'instant, aucune sauvegarde n'est disponible tant que le service backend n'est pas créé
|
||||
LOGGER.info("Chargement de " + sauvegardes.size() + " sauvegardes depuis le backend");
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des sauvegardes: " + e.getMessage());
|
||||
sauvegardes = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
public void creerSauvegarde() {
|
||||
LOGGER.info("Création d'une nouvelle sauvegarde");
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Sauvegarde",
|
||||
"La sauvegarde est en cours de création..."));
|
||||
chargerSauvegardes();
|
||||
}
|
||||
|
||||
public void telechargerSauvegarde(Sauvegarde sauvegarde) {
|
||||
LOGGER.info("Téléchargement de la sauvegarde: " + sauvegarde.getDate());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Téléchargement",
|
||||
"Téléchargement de la sauvegarde en cours..."));
|
||||
}
|
||||
|
||||
public void restaurerSauvegarde(Sauvegarde sauvegarde) {
|
||||
LOGGER.info("Restauration de la sauvegarde: " + sauvegarde.getDate());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Restauration",
|
||||
"La restauration est en cours..."));
|
||||
}
|
||||
|
||||
public void supprimerSauvegarde(Sauvegarde sauvegarde) {
|
||||
LOGGER.info("Suppression de la sauvegarde: " + sauvegarde.getDate());
|
||||
sauvegardes.remove(sauvegarde);
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Suppression",
|
||||
"Sauvegarde supprimée avec succès"));
|
||||
}
|
||||
|
||||
public List<Sauvegarde> getSauvegardes() { return sauvegardes; }
|
||||
public void setSauvegardes(List<Sauvegarde> sauvegardes) { this.sauvegardes = sauvegardes; }
|
||||
|
||||
// Classe interne pour les sauvegardes (WOU/DRY)
|
||||
public static class Sauvegarde {
|
||||
private LocalDateTime date;
|
||||
private String taille;
|
||||
private String type;
|
||||
private String statut;
|
||||
|
||||
public LocalDateTime getDate() { return date; }
|
||||
public void setDate(LocalDateTime date) { this.date = date; }
|
||||
|
||||
public String getTaille() { return taille; }
|
||||
public void setTaille(String taille) { this.taille = taille; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getStatutSeverity() {
|
||||
return switch (statut) {
|
||||
case "VALIDE" -> "success";
|
||||
case "EN_COURS" -> "warning";
|
||||
case "ERREUR" -> "danger";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutIcon() {
|
||||
return switch (statut) {
|
||||
case "VALIDE" -> "pi-check";
|
||||
case "EN_COURS" -> "pi-clock";
|
||||
case "ERREUR" -> "pi-times";
|
||||
default -> "pi-circle";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConfigurationSysteme {
|
||||
private boolean cacheActivé;
|
||||
private int dureeCacheMinutes;
|
||||
private int tailleLotTraitement;
|
||||
private String niveauLog;
|
||||
private int retentionLogJours;
|
||||
private boolean métriquesActivées;
|
||||
private boolean alertesSystemeActivées;
|
||||
|
||||
// Getters et setters
|
||||
public boolean isCacheActivé() { return cacheActivé; }
|
||||
public void setCacheActivé(boolean cacheActivé) { this.cacheActivé = cacheActivé; }
|
||||
|
||||
public int getDureeCacheMinutes() { return dureeCacheMinutes; }
|
||||
public void setDureeCacheMinutes(int dureeCacheMinutes) { this.dureeCacheMinutes = dureeCacheMinutes; }
|
||||
|
||||
public int getTailleLotTraitement() { return tailleLotTraitement; }
|
||||
public void setTailleLotTraitement(int tailleLotTraitement) { this.tailleLotTraitement = tailleLotTraitement; }
|
||||
|
||||
public String getNiveauLog() { return niveauLog; }
|
||||
public void setNiveauLog(String niveauLog) { this.niveauLog = niveauLog; }
|
||||
|
||||
public int getRetentionLogJours() { return retentionLogJours; }
|
||||
public void setRetentionLogJours(int retentionLogJours) { this.retentionLogJours = retentionLogJours; }
|
||||
|
||||
public boolean isMétriquesActivées() { return métriquesActivées; }
|
||||
public void setMétriquesActivées(boolean métriquesActivées) { this.métriquesActivées = métriquesActivées; }
|
||||
|
||||
public boolean isAlertesSystemeActivées() { return alertesSystemeActivées; }
|
||||
public void setAlertesSystemeActivées(boolean alertesSystemeActivées) { this.alertesSystemeActivées = alertesSystemeActivées; }
|
||||
}
|
||||
}
|
||||
1038
src/main/java/dev/lions/unionflow/client/view/CotisationsBean.java
Normal file
1038
src/main/java/dev/lions/unionflow/client/view/CotisationsBean.java
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
673
src/main/java/dev/lions/unionflow/client/view/DashboardBean.java
Normal file
673
src/main/java/dev/lions/unionflow/client/view/DashboardBean.java
Normal file
@@ -0,0 +1,673 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
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")
|
||||
@ViewScoped
|
||||
public class DashboardBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(DashboardBean.class.getName());
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_MEMBRE_INSCRIPTION = "membreInscriptionPage";
|
||||
private static final String OUTCOME_COTISATION_PAIEMENT = "cotisationPaiementPage";
|
||||
private static final String OUTCOME_EVENEMENT_CREATION = "evenementCreationPage";
|
||||
private static final String OUTCOME_ADHESION_VALIDATION = "adhesionValidationPage";
|
||||
private static final String OUTCOME_COTISATION_RELANCES = "cotisationRelancesPage";
|
||||
private static final String OUTCOME_AIDE_TRAITEMENT = "aideTraitementPage";
|
||||
private static final String OUTCOME_EVENEMENT_GESTION = "evenementGestionPage";
|
||||
|
||||
@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 = 0;
|
||||
private String totalCotisations = "0";
|
||||
private int pendingAides = 0;
|
||||
private int upcomingEvents = 0;
|
||||
|
||||
// Nouvelles propriétés pour le dashboard enrichi
|
||||
private int totalMembers = 0;
|
||||
private String aidesDistribuees = "0";
|
||||
private int tauxParticipation = 0;
|
||||
|
||||
// Propriétés pour les alertes
|
||||
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 = 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 = 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 = 0;
|
||||
private int aidesEnAttente = 0;
|
||||
private int evenementsAPlanifier = 0;
|
||||
|
||||
// Propriétés financières
|
||||
private Date moisSelectionne = new Date();
|
||||
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 = 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);
|
||||
int annee = mois.getYear();
|
||||
int numeroMois = mois.getMonthValue();
|
||||
|
||||
// Appeler le backend pour obtenir les cotisations du mois
|
||||
BigDecimal montant = BigDecimal.ZERO;
|
||||
try {
|
||||
List<dev.lions.unionflow.client.dto.CotisationDTO> cotisations =
|
||||
cotisationService.rechercher(null, "PAYEE", null, annee, numeroMois, 0, 10000);
|
||||
|
||||
// Calculer le total des cotisations payées pour ce mois
|
||||
montant = cotisations.stream()
|
||||
.map(c -> c.getMontantPaye() != null ? c.getMontantPaye() : BigDecimal.ZERO)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
LOGGER.info("Évolution financière: " + libelleMois + " = " + montant + " FCFA");
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Impossible de charger les cotisations pour " + libelleMois + ": " + e.getMessage());
|
||||
}
|
||||
|
||||
evolutionFinanciere.add(new MoisFinancier(libelleMois, montant));
|
||||
}
|
||||
|
||||
// Calculer tendances depuis les données réelles
|
||||
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
|
||||
public int getActiveMembers() { return activeMembers; }
|
||||
public void setActiveMembers(int activeMembers) { this.activeMembers = activeMembers; }
|
||||
|
||||
public String getTotalCotisations() { return totalCotisations; }
|
||||
public void setTotalCotisations(String totalCotisations) { this.totalCotisations = totalCotisations; }
|
||||
|
||||
public int getPendingAides() { return pendingAides; }
|
||||
public void setPendingAides(int pendingAides) { this.pendingAides = pendingAides; }
|
||||
|
||||
public int getUpcomingEvents() { return upcomingEvents; }
|
||||
public void setUpcomingEvents(int upcomingEvents) { this.upcomingEvents = upcomingEvents; }
|
||||
|
||||
public int getTotalMembers() { return totalMembers; }
|
||||
public void setTotalMembers(int totalMembers) { this.totalMembers = totalMembers; }
|
||||
|
||||
public String getAidesDistribuees() { return aidesDistribuees; }
|
||||
public void setAidesDistribuees(String aidesDistribuees) { this.aidesDistribuees = aidesDistribuees; }
|
||||
|
||||
public int getTauxParticipation() { return tauxParticipation; }
|
||||
public void setTauxParticipation(int tauxParticipation) { this.tauxParticipation = tauxParticipation; }
|
||||
|
||||
public int getCotisationsRetard() { return cotisationsRetard; }
|
||||
public void setCotisationsRetard(int cotisationsRetard) { this.cotisationsRetard = cotisationsRetard; }
|
||||
|
||||
public int getAdhesionsExpiration() { return adhesionsExpiration; }
|
||||
public void setAdhesionsExpiration(int adhesionsExpiration) { this.adhesionsExpiration = adhesionsExpiration; }
|
||||
|
||||
public int getDemandesToTraiter() { return demandesToTraiter; }
|
||||
public void setDemandesToTraiter(int demandesToTraiter) { this.demandesToTraiter = demandesToTraiter; }
|
||||
|
||||
public int getTachesFinaliser() { return tachesFinaliser; }
|
||||
public void setTachesFinaliser(int tachesFinaliser) { this.tachesFinaliser = tachesFinaliser; }
|
||||
|
||||
public int getMembresEvolutionPourcent() { return membresEvolutionPourcent; }
|
||||
public void setMembresEvolutionPourcent(int membresEvolutionPourcent) { this.membresEvolutionPourcent = membresEvolutionPourcent; }
|
||||
|
||||
public int getCotisationsEvolutionPourcent() { return cotisationsEvolutionPourcent; }
|
||||
public void setCotisationsEvolutionPourcent(int cotisationsEvolutionPourcent) { this.cotisationsEvolutionPourcent = cotisationsEvolutionPourcent; }
|
||||
|
||||
public String getObjectifCotisations() { return objectifCotisations; }
|
||||
public void setObjectifCotisations(String objectifCotisations) { this.objectifCotisations = objectifCotisations; }
|
||||
|
||||
public int getAidesApprouvees() { return aidesApprouvees; }
|
||||
public void setAidesApprouvees(int aidesApprouvees) { this.aidesApprouvees = aidesApprouvees; }
|
||||
|
||||
public int getMembresParticipants() { return membresParticipants; }
|
||||
public void setMembresParticipants(int membresParticipants) { this.membresParticipants = membresParticipants; }
|
||||
|
||||
public String getPeriodeGraph() { return periodeGraph; }
|
||||
public void setPeriodeGraph(String periodeGraph) { this.periodeGraph = periodeGraph; }
|
||||
|
||||
public String getFiltreActivite() { return filtreActivite; }
|
||||
public void setFiltreActivite(String filtreActivite) { this.filtreActivite = filtreActivite; }
|
||||
|
||||
public int getCotisationsAJour() { return cotisationsAJour; }
|
||||
public void setCotisationsAJour(int cotisationsAJour) { this.cotisationsAJour = cotisationsAJour; }
|
||||
|
||||
public int getCotisationsRetardPourcent() { return cotisationsRetardPourcent; }
|
||||
public void setCotisationsRetardPourcent(int cotisationsRetardPourcent) { this.cotisationsRetardPourcent = cotisationsRetardPourcent; }
|
||||
|
||||
public int getCotisationsImpayees() { return cotisationsImpayees; }
|
||||
public void setCotisationsImpayees(int cotisationsImpayees) { this.cotisationsImpayees = cotisationsImpayees; }
|
||||
|
||||
public int getAdhesionsPendantes() { return adhesionsPendantes; }
|
||||
public void setAdhesionsPendantes(int adhesionsPendantes) { this.adhesionsPendantes = adhesionsPendantes; }
|
||||
|
||||
public int getAidesEnAttente() { return aidesEnAttente; }
|
||||
public void setAidesEnAttente(int aidesEnAttente) { this.aidesEnAttente = aidesEnAttente; }
|
||||
|
||||
public int getEvenementsAPlanifier() { return evenementsAPlanifier; }
|
||||
public void setEvenementsAPlanifier(int evenementsAPlanifier) { this.evenementsAPlanifier = evenementsAPlanifier; }
|
||||
|
||||
public Date getMoisSelectionne() { return moisSelectionne; }
|
||||
public void setMoisSelectionne(Date moisSelectionne) { this.moisSelectionne = moisSelectionne; }
|
||||
|
||||
public String getRecettesMois() { return recettesMois; }
|
||||
public void setRecettesMois(String recettesMois) { this.recettesMois = recettesMois; }
|
||||
|
||||
public String getDepensesMois() { return depensesMois; }
|
||||
public void setDepensesMois(String depensesMois) { this.depensesMois = depensesMois; }
|
||||
|
||||
public String getSoldeMois() { return soldeMois; }
|
||||
public void setSoldeMois(String soldeMois) { this.soldeMois = soldeMois; }
|
||||
|
||||
public String getTresorerie() { return tresorerie; }
|
||||
public void setTresorerie(String tresorerie) { this.tresorerie = tresorerie; }
|
||||
|
||||
public String getCurrentDate() { return currentDate; }
|
||||
public void setCurrentDate(String currentDate) { this.currentDate = currentDate; }
|
||||
|
||||
public int getTauxActivite() { return tauxActivite; }
|
||||
public void setTauxActivite(int tauxActivite) { this.tauxActivite = tauxActivite; }
|
||||
|
||||
public int getTauxObjectifCotisations() { return tauxObjectifCotisations; }
|
||||
public void setTauxObjectifCotisations(int tauxObjectifCotisations) { this.tauxObjectifCotisations = tauxObjectifCotisations; }
|
||||
|
||||
public int getTauxAidesTraitees() { return tauxAidesTraitees; }
|
||||
public void setTauxAidesTraitees(int tauxAidesTraitees) { this.tauxAidesTraitees = tauxAidesTraitees; }
|
||||
|
||||
public int getTauxEngagement() { return tauxEngagement; }
|
||||
public void setTauxEngagement(int tauxEngagement) { this.tauxEngagement = tauxEngagement; }
|
||||
|
||||
public int getTachesCompletees() { return tachesCompletees; }
|
||||
public void setTachesCompletees(int tachesCompletees) { this.tachesCompletees = tachesCompletees; }
|
||||
|
||||
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() {
|
||||
if (recentActivities == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return recentActivities;
|
||||
}
|
||||
|
||||
public void actualiser() {
|
||||
chargerDonneesBackend();
|
||||
}
|
||||
|
||||
// Actions de navigation (WOU/DRY - utilisation de navigation outcomes)
|
||||
public String redirectToNewMember() {
|
||||
return OUTCOME_MEMBRE_INSCRIPTION + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String redirectToCotisation() {
|
||||
return OUTCOME_COTISATION_PAIEMENT + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String redirectToEvenement() {
|
||||
return OUTCOME_EVENEMENT_CREATION + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String redirectToAdhesionValidation() {
|
||||
return OUTCOME_ADHESION_VALIDATION + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String redirectToRelances() {
|
||||
return OUTCOME_COTISATION_RELANCES + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String redirectToAidesTraitement() {
|
||||
return OUTCOME_AIDE_TRAITEMENT + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String redirectToEvenementPlanning() {
|
||||
return OUTCOME_EVENEMENT_GESTION + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public void generateRapport() {
|
||||
// Logique de génération de rapport
|
||||
}
|
||||
|
||||
public void exportFinancialReport() {
|
||||
// Logique d'export du rapport financier
|
||||
}
|
||||
|
||||
public void onMoisChange() {
|
||||
// Logique de mise à jour lors du changement de mois
|
||||
}
|
||||
|
||||
// Classe interne pour les activités enrichie
|
||||
public static class Activity implements Serializable {
|
||||
private LocalDateTime date;
|
||||
private String type;
|
||||
private String severity;
|
||||
private String icon;
|
||||
private String titre;
|
||||
private String description;
|
||||
private String montant;
|
||||
private String userNom;
|
||||
private String userRole;
|
||||
|
||||
public Activity(LocalDateTime date, String type, String severity, String icon,
|
||||
String titre, String description, String montant, String userNom, String userRole) {
|
||||
this.date = date;
|
||||
this.type = type;
|
||||
this.severity = severity;
|
||||
this.icon = icon;
|
||||
this.titre = titre;
|
||||
this.description = description;
|
||||
this.montant = montant;
|
||||
this.userNom = userNom;
|
||||
this.userRole = userRole;
|
||||
}
|
||||
|
||||
// Getters et setters
|
||||
public LocalDateTime getDate() { return date; }
|
||||
public void setDate(LocalDateTime date) { this.date = date; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getSeverity() { return severity; }
|
||||
public void setSeverity(String severity) { this.severity = severity; }
|
||||
|
||||
public String getIcon() { return icon; }
|
||||
public void setIcon(String icon) { this.icon = icon; }
|
||||
|
||||
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 getMontant() { return montant; }
|
||||
public void setMontant(String montant) { this.montant = montant; }
|
||||
|
||||
public String getUserNom() { return userNom; }
|
||||
public void setUserNom(String userNom) { this.userNom = userNom; }
|
||||
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,711 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.dto.DemandeAideDTO;
|
||||
import dev.lions.unionflow.client.service.DemandeAideService;
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
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.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.Map;
|
||||
|
||||
@Named("demandesAideBean")
|
||||
@SessionScoped
|
||||
public class DemandesAideBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(DemandesAideBean.class.getName());
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_DEMANDES_HISTORIQUE = "demandesHistoriquePage";
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private DemandeAideService demandeAideService;
|
||||
|
||||
private List<DemandeAide> toutesLesDemandes;
|
||||
private List<DemandeAide> demandesFiltrees;
|
||||
private List<DemandeAide> demandesSelectionnees;
|
||||
private List<DemandeAide> demandesPrioritaires;
|
||||
private List<EtapeWorkflow> etapesWorkflow;
|
||||
private DemandeAide demandeSelectionnee;
|
||||
private NouvelleDemande nouvelleDemande;
|
||||
private Filtres filtres;
|
||||
private StatistiquesDemandes statistiques;
|
||||
|
||||
// Propriétés pour le dialogue de détails
|
||||
private boolean dialogDetailsVisible;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initializeFiltres();
|
||||
initializeStatistiques();
|
||||
initializeDemandes();
|
||||
initializeNouvelleDemande();
|
||||
initializeDemandesPrioritaires();
|
||||
initializeEtapesWorkflow();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
private void initializeFiltres() {
|
||||
filtres = new Filtres();
|
||||
demandesSelectionnees = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void initializeStatistiques() {
|
||||
statistiques = new StatistiquesDemandes();
|
||||
try {
|
||||
List<DemandeAideDTO> demandesDTO = demandeAideService.listerToutes(0, 1000);
|
||||
statistiques.setTotalDemandes(demandesDTO.size());
|
||||
long enAttente = demandesDTO.stream().filter(d -> "EN_ATTENTE".equals(d.getStatut())).count();
|
||||
statistiques.setDemandesEnAttente((int) enAttente);
|
||||
long approuvees = demandesDTO.stream().filter(d -> "APPROUVEE".equals(d.getStatut())).count();
|
||||
statistiques.setDemandesApprouvees((int) approuvees);
|
||||
long rejetees = demandesDTO.stream().filter(d -> "REJETEE".equals(d.getStatut())).count();
|
||||
statistiques.setDemandesRejetees((int) rejetees);
|
||||
BigDecimal montantTotal = demandesDTO.stream()
|
||||
.filter(d -> d.getMontantAccorde() != null)
|
||||
.map(DemandeAideDTO::getMontantAccorde)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
statistiques.setMontantTotalAide(montantTotal.toString() + " FCFA");
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du calcul des statistiques: " + e.getMessage());
|
||||
statistiques.setTotalDemandes(0);
|
||||
statistiques.setDemandesEnAttente(0);
|
||||
statistiques.setDemandesApprouvees(0);
|
||||
statistiques.setDemandesRejetees(0);
|
||||
statistiques.setMontantTotalAide("0 FCFA");
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeEtapesWorkflow() {
|
||||
etapesWorkflow = new ArrayList<>();
|
||||
|
||||
try {
|
||||
// Charger toutes les demandes depuis le backend pour calculer les étapes
|
||||
List<DemandeAideDTO> demandesDTO = demandeAideService.listerToutes(0, 10000);
|
||||
|
||||
// Calculer le nombre de demandes par statut depuis les données réelles
|
||||
long enAttenteCount = demandesDTO.stream().filter(d -> "EN_ATTENTE".equals(d.getStatut())).count();
|
||||
long enEvaluationCount = demandesDTO.stream().filter(d -> "EN_EVALUATION".equals(d.getStatut())).count();
|
||||
long enVisiteCount = demandesDTO.stream().filter(d -> "EN_VISITE".equals(d.getStatut())).count();
|
||||
long enDecisionCount = demandesDTO.stream().filter(d -> "EN_DECISION".equals(d.getStatut())).count();
|
||||
long enVersementCount = demandesDTO.stream().filter(d -> "EN_VERSEMENT".equals(d.getStatut())).count();
|
||||
long enSuiviCount = demandesDTO.stream().filter(d -> "EN_SUIVI".equals(d.getStatut())).count();
|
||||
|
||||
// Créer les étapes workflow avec les nombres réels
|
||||
EtapeWorkflow enAttente = new EtapeWorkflow();
|
||||
enAttente.setLibelle("En Attente");
|
||||
enAttente.setIcon("pi-clock");
|
||||
enAttente.setCouleur("orange-500");
|
||||
enAttente.setNombre((int) enAttenteCount);
|
||||
etapesWorkflow.add(enAttente);
|
||||
|
||||
EtapeWorkflow evaluation = new EtapeWorkflow();
|
||||
evaluation.setLibelle("Évaluation");
|
||||
evaluation.setIcon("pi-search");
|
||||
evaluation.setCouleur("blue-500");
|
||||
evaluation.setNombre((int) enEvaluationCount);
|
||||
etapesWorkflow.add(evaluation);
|
||||
|
||||
EtapeWorkflow visite = new EtapeWorkflow();
|
||||
visite.setLibelle("Visite");
|
||||
visite.setIcon("pi-home");
|
||||
visite.setCouleur("purple-500");
|
||||
visite.setNombre((int) enVisiteCount);
|
||||
etapesWorkflow.add(visite);
|
||||
|
||||
EtapeWorkflow decision = new EtapeWorkflow();
|
||||
decision.setLibelle("Décision");
|
||||
decision.setIcon("pi-check-circle");
|
||||
decision.setCouleur("yellow-500");
|
||||
decision.setNombre((int) enDecisionCount);
|
||||
etapesWorkflow.add(decision);
|
||||
|
||||
EtapeWorkflow versement = new EtapeWorkflow();
|
||||
versement.setLibelle("Versement");
|
||||
versement.setIcon("pi-dollar");
|
||||
versement.setCouleur("green-500");
|
||||
versement.setNombre((int) enVersementCount);
|
||||
etapesWorkflow.add(versement);
|
||||
|
||||
EtapeWorkflow suivi = new EtapeWorkflow();
|
||||
suivi.setLibelle("Suivi");
|
||||
suivi.setIcon("pi-chart-line");
|
||||
suivi.setCouleur("indigo-500");
|
||||
suivi.setNombre((int) enSuiviCount);
|
||||
etapesWorkflow.add(suivi);
|
||||
|
||||
LOGGER.info("Étapes workflow initialisées depuis les données backend");
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'initialisation des étapes workflow: " + e.getMessage());
|
||||
etapesWorkflow = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeDemandes() {
|
||||
toutesLesDemandes = new ArrayList<>();
|
||||
|
||||
try {
|
||||
List<DemandeAideDTO> demandesDTO = demandeAideService.listerToutes(0, 1000);
|
||||
for (DemandeAideDTO dto : demandesDTO) {
|
||||
DemandeAide demande = convertToDemandeAide(dto);
|
||||
toutesLesDemandes.add(demande);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des demandes d'aide: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private DemandeAide convertToDemandeAide(DemandeAideDTO dto) {
|
||||
DemandeAide demande = new DemandeAide();
|
||||
demande.setId(dto.getId());
|
||||
demande.setDemandeur(dto.getDemandeur());
|
||||
demande.setTelephone(dto.getTelephone());
|
||||
demande.setEmail(dto.getEmail());
|
||||
demande.setType(dto.getType());
|
||||
demande.setStatut(dto.getStatut());
|
||||
demande.setUrgence(dto.getUrgence());
|
||||
demande.setLocalisation(dto.getLocalisation());
|
||||
demande.setMotif(dto.getMotif() != null ? dto.getMotif() : dto.getTitre());
|
||||
demande.setDescription(dto.getDescription());
|
||||
demande.setMontantDemande(dto.getMontantDemande());
|
||||
demande.setMontantAccorde(dto.getMontantAccorde());
|
||||
demande.setDateDemande(dto.getDateDemande());
|
||||
demande.setDateLimite(dto.getDateLimite());
|
||||
demande.setResponsableTraitement(dto.getResponsableTraitement());
|
||||
return demande;
|
||||
}
|
||||
|
||||
private void initializeDemandesPrioritaires() {
|
||||
try {
|
||||
List<DemandeAideDTO> demandesDTO = demandeAideService.rechercher("EN_ATTENTE", null, "CRITIQUE", 0, 6);
|
||||
demandesPrioritaires = demandesDTO.stream()
|
||||
.map(this::convertToDemandeAide)
|
||||
.filter(d -> !d.getStatut().equals("TERMINEE") && !d.getStatut().equals("REJETEE"))
|
||||
.limit(6)
|
||||
.collect(Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des demandes prioritaires: " + e.getMessage());
|
||||
demandesPrioritaires = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeNouvelleDemande() {
|
||||
nouvelleDemande = new NouvelleDemande();
|
||||
nouvelleDemande.setUrgence("NORMALE");
|
||||
nouvelleDemande.setDateLimite(LocalDate.now().plusWeeks(2));
|
||||
}
|
||||
|
||||
private void appliquerFiltres() {
|
||||
demandesFiltrees = toutesLesDemandes.stream()
|
||||
.filter(this::appliquerFiltre)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean appliquerFiltre(DemandeAide demande) {
|
||||
if (filtres.getDemandeur() != null && !filtres.getDemandeur().trim().isEmpty()) {
|
||||
if (!demande.getDemandeur().toLowerCase().contains(filtres.getDemandeur().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getType() != null && !filtres.getType().trim().isEmpty()) {
|
||||
if (!demande.getType().equals(filtres.getType())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getStatut() != null && !filtres.getStatut().trim().isEmpty()) {
|
||||
if (!demande.getStatut().equals(filtres.getStatut())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getUrgence() != null && !filtres.getUrgence().trim().isEmpty()) {
|
||||
if (!demande.getUrgence().equals(filtres.getUrgence())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getLocalisation() != null && !filtres.getLocalisation().trim().isEmpty()) {
|
||||
if (!demande.getLocalisation().toLowerCase().contains(filtres.getLocalisation().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getDateDebut() != null) {
|
||||
if (demande.getDateDemande().isBefore(filtres.getDateDebut())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getDateFin() != null) {
|
||||
if (demande.getDateDemande().isAfter(filtres.getDateFin())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Actions
|
||||
public void rechercher() {
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void reinitialiserFiltres() {
|
||||
filtres = new Filtres();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void creerDemande() {
|
||||
DemandeAide nouvelleDem = new DemandeAide();
|
||||
nouvelleDem.setId(UUID.randomUUID());
|
||||
nouvelleDem.setDemandeur(nouvelleDemande.getDemandeur());
|
||||
nouvelleDem.setTelephone(nouvelleDemande.getTelephone());
|
||||
nouvelleDem.setEmail(nouvelleDemande.getEmail());
|
||||
nouvelleDem.setType(nouvelleDemande.getType());
|
||||
nouvelleDem.setLocalisation(nouvelleDemande.getLocalisation());
|
||||
nouvelleDem.setMontantDemande(nouvelleDemande.getMontantDemande());
|
||||
nouvelleDem.setUrgence(nouvelleDemande.getUrgence());
|
||||
nouvelleDem.setDateLimite(nouvelleDemande.getDateLimite());
|
||||
nouvelleDem.setMotif(nouvelleDemande.getMotif());
|
||||
nouvelleDem.setDescription(nouvelleDemande.getDescription());
|
||||
nouvelleDem.setStatut("EN_ATTENTE");
|
||||
nouvelleDem.setDateDemande(LocalDate.now());
|
||||
|
||||
toutesLesDemandes.add(nouvelleDem);
|
||||
appliquerFiltres();
|
||||
initializeDemandesPrioritaires();
|
||||
|
||||
LOGGER.info("Nouvelle demande d'aide créée pour: " + nouvelleDem.getDemandeur());
|
||||
initializeNouvelleDemande();
|
||||
}
|
||||
|
||||
public void approuverDemande() {
|
||||
if (demandeSelectionnee != null) {
|
||||
demandeSelectionnee.setStatut("APPROUVEE");
|
||||
if (demandeSelectionnee.getMontantAccorde() == null) {
|
||||
demandeSelectionnee.setMontantAccorde(demandeSelectionnee.getMontantDemande().multiply(new BigDecimal("0.8")));
|
||||
}
|
||||
LOGGER.info("Demande approuvée pour: " + demandeSelectionnee.getDemandeur());
|
||||
appliquerFiltres();
|
||||
initializeDemandesPrioritaires();
|
||||
}
|
||||
}
|
||||
|
||||
public void rejeterDemande() {
|
||||
if (demandeSelectionnee != null) {
|
||||
demandeSelectionnee.setStatut("REJETEE");
|
||||
LOGGER.info("Demande rejetée pour: " + demandeSelectionnee.getDemandeur());
|
||||
appliquerFiltres();
|
||||
initializeDemandesPrioritaires();
|
||||
}
|
||||
}
|
||||
|
||||
public String voirHistorique() {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_DEMANDES_HISTORIQUE + "?id=" + demandeSelectionnee.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
public void envoyerNotification() {
|
||||
LOGGER.info("Notification envoyée pour la demande de: " + demandeSelectionnee.getDemandeur());
|
||||
}
|
||||
|
||||
// Méthodes pour la page de traitement (WOU/DRY - réutilisables)
|
||||
public void approuver(DemandeAide demande) {
|
||||
demandeSelectionnee = demande;
|
||||
approuverDemande();
|
||||
}
|
||||
|
||||
public void rejeter(DemandeAide demande) {
|
||||
demandeSelectionnee = demande;
|
||||
rejeterDemande();
|
||||
}
|
||||
|
||||
public void voirDetails(DemandeAide demande) {
|
||||
demandeSelectionnee = demande;
|
||||
dialogDetailsVisible = true;
|
||||
LOGGER.info("Affichage des détails de la demande: " + demande.getId());
|
||||
}
|
||||
|
||||
public void fermerDialogDetails() {
|
||||
dialogDetailsVisible = false;
|
||||
demandeSelectionnee = null;
|
||||
}
|
||||
|
||||
public void actualiser() {
|
||||
initializeDemandes();
|
||||
initializeStatistiques();
|
||||
appliquerFiltres();
|
||||
LOGGER.info("Données actualisées");
|
||||
}
|
||||
|
||||
public void dupliquerDemande() {
|
||||
if (demandeSelectionnee != null) {
|
||||
DemandeAide copie = new DemandeAide();
|
||||
copie.setId(UUID.randomUUID());
|
||||
copie.setDemandeur(demandeSelectionnee.getDemandeur());
|
||||
copie.setTelephone(demandeSelectionnee.getTelephone());
|
||||
copie.setEmail(demandeSelectionnee.getEmail());
|
||||
copie.setType(demandeSelectionnee.getType());
|
||||
copie.setLocalisation(demandeSelectionnee.getLocalisation());
|
||||
copie.setMontantDemande(demandeSelectionnee.getMontantDemande());
|
||||
copie.setUrgence(demandeSelectionnee.getUrgence());
|
||||
copie.setMotif(demandeSelectionnee.getMotif() + " (Copie)");
|
||||
copie.setDescription(demandeSelectionnee.getDescription());
|
||||
copie.setStatut("EN_ATTENTE");
|
||||
copie.setDateDemande(LocalDate.now());
|
||||
|
||||
toutesLesDemandes.add(copie);
|
||||
appliquerFiltres();
|
||||
LOGGER.info("Demande dupliquée pour: " + copie.getDemandeur());
|
||||
}
|
||||
}
|
||||
|
||||
public void exporterDemandes() {
|
||||
LOGGER.info("Export de " + demandesFiltrees.size() + " demandes d'aide");
|
||||
}
|
||||
|
||||
// Méthodes pour les graphiques (WOU/DRY) - Retirées car PrimeFaces ne supporte plus les charts
|
||||
// Utiliser une bibliothèque JavaScript externe (Chart.js, ApexCharts, etc.) dans le XHTML
|
||||
public Object getChartModelType() {
|
||||
// Les graphiques sont gérés directement dans le XHTML avec des bibliothèques JavaScript
|
||||
// Retourne les données pour un éventuel graphique client-side
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object getChartModelStatut() {
|
||||
// Les graphiques sont gérés directement dans le XHTML avec des bibliothèques JavaScript
|
||||
// Retourne les données pour un éventuel graphique client-side
|
||||
return null;
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public List<DemandeAide> getToutesLesDemandes() { return toutesLesDemandes; }
|
||||
public void setToutesLesDemandes(List<DemandeAide> toutesLesDemandes) { this.toutesLesDemandes = toutesLesDemandes; }
|
||||
|
||||
public List<DemandeAide> getDemandesFiltrees() { return demandesFiltrees; }
|
||||
public void setDemandesFiltrees(List<DemandeAide> demandesFiltrees) { this.demandesFiltrees = demandesFiltrees; }
|
||||
|
||||
public List<DemandeAide> getDemandesSelectionnees() { return demandesSelectionnees; }
|
||||
public void setDemandesSelectionnees(List<DemandeAide> demandesSelectionnees) { this.demandesSelectionnees = demandesSelectionnees; }
|
||||
|
||||
public List<DemandeAide> getDemandesPrioritaires() { return demandesPrioritaires; }
|
||||
public void setDemandesPrioritaires(List<DemandeAide> demandesPrioritaires) { this.demandesPrioritaires = demandesPrioritaires; }
|
||||
|
||||
public List<EtapeWorkflow> getEtapesWorkflow() { return etapesWorkflow; }
|
||||
public void setEtapesWorkflow(List<EtapeWorkflow> etapesWorkflow) { this.etapesWorkflow = etapesWorkflow; }
|
||||
|
||||
public DemandeAide getDemandeSelectionnee() { return demandeSelectionnee; }
|
||||
public void setDemandeSelectionnee(DemandeAide demandeSelectionnee) { this.demandeSelectionnee = demandeSelectionnee; }
|
||||
|
||||
public NouvelleDemande getNouvelleDemande() { return nouvelleDemande; }
|
||||
public void setNouvelleDemande(NouvelleDemande nouvelleDemande) { this.nouvelleDemande = nouvelleDemande; }
|
||||
|
||||
public Filtres getFiltres() { return filtres; }
|
||||
public void setFiltres(Filtres filtres) { this.filtres = filtres; }
|
||||
|
||||
public StatistiquesDemandes getStatistiques() { return statistiques; }
|
||||
public void setStatistiques(StatistiquesDemandes statistiques) { this.statistiques = statistiques; }
|
||||
|
||||
public boolean isDialogDetailsVisible() { return dialogDetailsVisible; }
|
||||
public void setDialogDetailsVisible(boolean dialogDetailsVisible) { this.dialogDetailsVisible = dialogDetailsVisible; }
|
||||
|
||||
// Classes internes
|
||||
public static class DemandeAide {
|
||||
private UUID id;
|
||||
private String demandeur;
|
||||
private String telephone;
|
||||
private String email;
|
||||
private String type;
|
||||
private String statut;
|
||||
private String urgence;
|
||||
private String localisation;
|
||||
private String motif;
|
||||
private String description;
|
||||
private BigDecimal montantDemande;
|
||||
private BigDecimal montantAccorde;
|
||||
private LocalDate dateDemande;
|
||||
private LocalDate dateLimite;
|
||||
private String responsableTraitement;
|
||||
|
||||
// Getters et setters
|
||||
public UUID getId() { return id; }
|
||||
public void setId(UUID id) { this.id = id; }
|
||||
|
||||
public String getDemandeur() { return demandeur; }
|
||||
public void setDemandeur(String demandeur) { this.demandeur = demandeur; }
|
||||
|
||||
public String getTelephone() { return telephone; }
|
||||
public void setTelephone(String telephone) { this.telephone = telephone; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getUrgence() { return urgence; }
|
||||
public void setUrgence(String urgence) { this.urgence = urgence; }
|
||||
|
||||
public String getLocalisation() { return localisation; }
|
||||
public void setLocalisation(String localisation) { this.localisation = localisation; }
|
||||
|
||||
public String getMotif() { return motif; }
|
||||
public void setMotif(String motif) { this.motif = motif; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public BigDecimal getMontantDemande() { return montantDemande; }
|
||||
public void setMontantDemande(BigDecimal montantDemande) { this.montantDemande = montantDemande; }
|
||||
|
||||
public BigDecimal getMontantAccorde() { return montantAccorde; }
|
||||
public void setMontantAccorde(BigDecimal montantAccorde) { this.montantAccorde = montantAccorde; }
|
||||
|
||||
public LocalDate getDateDemande() { return dateDemande; }
|
||||
public void setDateDemande(LocalDate dateDemande) { this.dateDemande = dateDemande; }
|
||||
|
||||
public LocalDate getDateLimite() { return dateLimite; }
|
||||
public void setDateLimite(LocalDate dateLimite) { this.dateLimite = dateLimite; }
|
||||
|
||||
public String getResponsableTraitement() { return responsableTraitement; }
|
||||
public void setResponsableTraitement(String responsableTraitement) { this.responsableTraitement = responsableTraitement; }
|
||||
|
||||
// Propriétés dérivées
|
||||
public String getTypeLibelle() {
|
||||
return switch (type) {
|
||||
case "AIDE_MEDICALE" -> "Aide Médicale";
|
||||
case "AIDE_ALIMENTAIRE" -> "Aide Alimentaire";
|
||||
case "AIDE_EDUCATIVE" -> "Aide Éducative";
|
||||
case "AIDE_LOGEMENT" -> "Aide Logement";
|
||||
case "AIDE_URGENCE" -> "Aide d'Urgence";
|
||||
default -> type;
|
||||
};
|
||||
}
|
||||
|
||||
public String getTypeSeverity() {
|
||||
return switch (type) {
|
||||
case "AIDE_MEDICALE" -> "danger";
|
||||
case "AIDE_ALIMENTAIRE" -> "warning";
|
||||
case "AIDE_EDUCATIVE" -> "info";
|
||||
case "AIDE_LOGEMENT" -> "secondary";
|
||||
case "AIDE_URGENCE" -> "primary";
|
||||
default -> "primary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getTypeIcon() {
|
||||
return switch (type) {
|
||||
case "AIDE_MEDICALE" -> "pi-heart";
|
||||
case "AIDE_ALIMENTAIRE" -> "pi-shopping-cart";
|
||||
case "AIDE_EDUCATIVE" -> "pi-book";
|
||||
case "AIDE_LOGEMENT" -> "pi-home";
|
||||
case "AIDE_URGENCE" -> "pi-exclamation-triangle";
|
||||
default -> "pi-question";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutLibelle() {
|
||||
return switch (statut) {
|
||||
case "EN_ATTENTE" -> "En Attente";
|
||||
case "EN_EVALUATION" -> "En Évaluation";
|
||||
case "APPROUVEE" -> "Approuvée";
|
||||
case "REJETEE" -> "Rejetée";
|
||||
case "EN_COURS" -> "En Cours";
|
||||
case "TERMINEE" -> "Terminée";
|
||||
default -> statut;
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutSeverity() {
|
||||
return switch (statut) {
|
||||
case "EN_ATTENTE" -> "warning";
|
||||
case "EN_EVALUATION" -> "info";
|
||||
case "APPROUVEE" -> "success";
|
||||
case "REJETEE" -> "danger";
|
||||
case "EN_COURS" -> "primary";
|
||||
case "TERMINEE" -> "secondary";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutIcon() {
|
||||
return switch (statut) {
|
||||
case "EN_ATTENTE" -> "pi-clock";
|
||||
case "EN_EVALUATION" -> "pi-search";
|
||||
case "APPROUVEE" -> "pi-check";
|
||||
case "REJETEE" -> "pi-times";
|
||||
case "EN_COURS" -> "pi-play";
|
||||
case "TERMINEE" -> "pi-check-circle";
|
||||
default -> "pi-circle";
|
||||
};
|
||||
}
|
||||
|
||||
public String getUrgenceSeverity() {
|
||||
return switch (urgence) {
|
||||
case "FAIBLE" -> "secondary";
|
||||
case "NORMALE" -> "info";
|
||||
case "ELEVEE" -> "warning";
|
||||
case "CRITIQUE" -> "danger";
|
||||
default -> "primary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getDateDemandeFormatee() {
|
||||
if (dateDemande == null) return "";
|
||||
return dateDemande.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
|
||||
}
|
||||
|
||||
public String getMontantDemandeFormatte() {
|
||||
if (montantDemande == null) return "";
|
||||
return String.format("%,.0f FCFA", montantDemande);
|
||||
}
|
||||
|
||||
public String getMontantAccordeFormatte() {
|
||||
if (montantAccorde == null) return "";
|
||||
return String.format("%,.0f FCFA", montantAccorde);
|
||||
}
|
||||
|
||||
public long getJoursDepuisDemande() {
|
||||
if (dateDemande == null) return 0;
|
||||
return ChronoUnit.DAYS.between(dateDemande, LocalDate.now());
|
||||
}
|
||||
}
|
||||
|
||||
public static class NouvelleDemande {
|
||||
private String demandeur;
|
||||
private String telephone;
|
||||
private String email;
|
||||
private String type;
|
||||
private String localisation;
|
||||
private BigDecimal montantDemande;
|
||||
private String urgence;
|
||||
private LocalDate dateLimite;
|
||||
private String motif;
|
||||
private String description;
|
||||
|
||||
// Getters et setters
|
||||
public String getDemandeur() { return demandeur; }
|
||||
public void setDemandeur(String demandeur) { this.demandeur = demandeur; }
|
||||
|
||||
public String getTelephone() { return telephone; }
|
||||
public void setTelephone(String telephone) { this.telephone = telephone; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getLocalisation() { return localisation; }
|
||||
public void setLocalisation(String localisation) { this.localisation = localisation; }
|
||||
|
||||
public BigDecimal getMontantDemande() { return montantDemande; }
|
||||
public void setMontantDemande(BigDecimal montantDemande) { this.montantDemande = montantDemande; }
|
||||
|
||||
public String getUrgence() { return urgence; }
|
||||
public void setUrgence(String urgence) { this.urgence = urgence; }
|
||||
|
||||
public LocalDate getDateLimite() { return dateLimite; }
|
||||
public void setDateLimite(LocalDate dateLimite) { this.dateLimite = dateLimite; }
|
||||
|
||||
public String getMotif() { return motif; }
|
||||
public void setMotif(String motif) { this.motif = motif; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
}
|
||||
|
||||
public static class Filtres {
|
||||
private String demandeur;
|
||||
private String type;
|
||||
private String statut;
|
||||
private String urgence;
|
||||
private String localisation;
|
||||
private LocalDate dateDebut;
|
||||
private LocalDate dateFin;
|
||||
|
||||
// Getters et setters
|
||||
public String getDemandeur() { return demandeur; }
|
||||
public void setDemandeur(String demandeur) { this.demandeur = demandeur; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getUrgence() { return urgence; }
|
||||
public void setUrgence(String urgence) { this.urgence = urgence; }
|
||||
|
||||
public String getLocalisation() { return localisation; }
|
||||
public void setLocalisation(String localisation) { this.localisation = localisation; }
|
||||
|
||||
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 StatistiquesDemandes {
|
||||
private int totalDemandes;
|
||||
private int demandesEnAttente;
|
||||
private int demandesApprouvees;
|
||||
private int demandesRejetees;
|
||||
private String montantTotalAide;
|
||||
|
||||
// Getters et setters
|
||||
public int getTotalDemandes() { return totalDemandes; }
|
||||
public void setTotalDemandes(int totalDemandes) { this.totalDemandes = totalDemandes; }
|
||||
|
||||
public int getDemandesEnAttente() { return demandesEnAttente; }
|
||||
public void setDemandesEnAttente(int demandesEnAttente) { this.demandesEnAttente = demandesEnAttente; }
|
||||
|
||||
public int getDemandesApprouvees() { return demandesApprouvees; }
|
||||
public void setDemandesApprouvees(int demandesApprouvees) { this.demandesApprouvees = demandesApprouvees; }
|
||||
|
||||
public int getDemandesRejetees() { return demandesRejetees; }
|
||||
public void setDemandesRejetees(int demandesRejetees) { this.demandesRejetees = demandesRejetees; }
|
||||
|
||||
public String getMontantTotalAide() { return montantTotalAide; }
|
||||
public void setMontantTotalAide(String montantTotalAide) { this.montantTotalAide = montantTotalAide; }
|
||||
}
|
||||
|
||||
public static class EtapeWorkflow {
|
||||
private String libelle;
|
||||
private String icon;
|
||||
private String couleur;
|
||||
private int nombre;
|
||||
|
||||
// Getters et setters
|
||||
public String getLibelle() { return libelle; }
|
||||
public void setLibelle(String libelle) { this.libelle = libelle; }
|
||||
|
||||
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 int getNombre() { return nombre; }
|
||||
public void setNombre(int nombre) { this.nombre = nombre; }
|
||||
}
|
||||
}
|
||||
478
src/main/java/dev/lions/unionflow/client/view/DemandesBean.java
Normal file
478
src/main/java/dev/lions/unionflow/client/view/DemandesBean.java
Normal file
@@ -0,0 +1,478 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("demandeBean")
|
||||
@SessionScoped
|
||||
public class DemandesBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(DemandesBean.class.getName());
|
||||
|
||||
private List<Demande> demandes;
|
||||
private List<Demande> selectedDemandes;
|
||||
private List<Demande> demandesUrgentes;
|
||||
private List<Demande> dernieresDemandes;
|
||||
private List<Gestionnaire> gestionnairesDisponibles;
|
||||
private Membre membreDemandeur;
|
||||
private NouvelleDemande nouvelleDemande;
|
||||
private Demande demandeSelectionnee;
|
||||
|
||||
// Filtres
|
||||
private String searchFilter;
|
||||
private String statutFilter;
|
||||
private String typeFilter;
|
||||
private String prioriteFilter;
|
||||
private LocalDate dateFilter;
|
||||
|
||||
// Assignation en lot
|
||||
private UUID gestionnaireAssignation;
|
||||
private String commentaireAssignation;
|
||||
|
||||
// Statistiques
|
||||
private int enAttente = 0;
|
||||
private int urgentes = 0;
|
||||
private int traitees = 0;
|
||||
private int delaiMoyenTraitement = 0;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initializeDemandes();
|
||||
initializeGestionnaires();
|
||||
initializeNouvelleDemande();
|
||||
calculerStatistiques();
|
||||
selectedDemandes = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void initializeDemandes() {
|
||||
demandes = new ArrayList<>();
|
||||
// TODO: Charger depuis le backend via DemandeAideService
|
||||
// Pour l'instant, liste vide - les données viendront du backend
|
||||
}
|
||||
|
||||
private void calculerStatistiques() {
|
||||
if (demandes == null || demandes.isEmpty()) {
|
||||
enAttente = 0;
|
||||
urgentes = 0;
|
||||
traitees = 0;
|
||||
delaiMoyenTraitement = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculer depuis les données réelles
|
||||
enAttente = (int) demandes.stream()
|
||||
.filter(d -> "EN_ATTENTE".equals(d.getStatut()))
|
||||
.count();
|
||||
|
||||
urgentes = (int) demandes.stream()
|
||||
.filter(d -> "URGENTE".equals(d.getPriorite()))
|
||||
.count();
|
||||
|
||||
traitees = (int) demandes.stream()
|
||||
.filter(d -> "APPROUVEE".equals(d.getStatut()) || "REJETEE".equals(d.getStatut()))
|
||||
.count();
|
||||
|
||||
// Calculer le délai moyen de traitement
|
||||
long totalJours = demandes.stream()
|
||||
.filter(d -> d.getDateDepot() != null && "APPROUVEE".equals(d.getStatut()))
|
||||
.mapToLong(d -> ChronoUnit.DAYS.between(d.getDateDepot(), LocalDate.now()))
|
||||
.sum();
|
||||
long countTraitees = demandes.stream()
|
||||
.filter(d -> d.getDateDepot() != null && "APPROUVEE".equals(d.getStatut()))
|
||||
.count();
|
||||
delaiMoyenTraitement = countTraitees > 0 ? (int) (totalJours / countTraitees) : 0;
|
||||
|
||||
// Initialiser les sous-listes
|
||||
demandesUrgentes = demandes.stream()
|
||||
.filter(d -> "URGENTE".equals(d.getPriorite()) || "EN_ATTENTE".equals(d.getStatut()))
|
||||
.limit(3)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
dernieresDemandes = demandes.stream()
|
||||
.sorted((d1, d2) -> {
|
||||
if (d1.getDateDepot() == null) return 1;
|
||||
if (d2.getDateDepot() == null) return -1;
|
||||
return d2.getDateDepot().compareTo(d1.getDateDepot());
|
||||
})
|
||||
.limit(4)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void initializeGestionnaires() {
|
||||
gestionnairesDisponibles = new ArrayList<>();
|
||||
gestionnairesDisponibles.add(new Gestionnaire(UUID.fromString("00000000-0000-0000-0000-000000000500"), "Marie Gestionnaire"));
|
||||
gestionnairesDisponibles.add(new Gestionnaire(UUID.fromString("00000000-0000-0000-0000-000000000600"), "Paul Superviseur"));
|
||||
gestionnairesDisponibles.add(new Gestionnaire(UUID.fromString("00000000-0000-0000-0000-000000000700"), "Fatou Responsable"));
|
||||
}
|
||||
|
||||
private void initializeNouvelleDemande() {
|
||||
nouvelleDemande = new NouvelleDemande();
|
||||
nouvelleDemande.setPriorite("NORMALE");
|
||||
nouvelleDemande.setDateEcheance(LocalDate.now().plusWeeks(2));
|
||||
}
|
||||
|
||||
public List<Membre> rechercherMembres(String query) {
|
||||
List<Membre> resultats = new ArrayList<>();
|
||||
|
||||
String[] noms = {"Marie Kouassi", "Paul Traoré", "Fatou Sanogo", "Jean Ouattara", "Aissata Koné"};
|
||||
for (int i = 0; i < noms.length; i++) {
|
||||
if (noms[i].toLowerCase().contains(query.toLowerCase())) {
|
||||
Membre membre = new Membre();
|
||||
membre.setId(UUID.fromString(String.format("00000000-0000-0000-0000-%012d", i + 1)));
|
||||
membre.setNomComplet(noms[i]);
|
||||
membre.setNumeroMembre("M" + String.format("%06d", 1000 + i));
|
||||
resultats.add(membre);
|
||||
}
|
||||
}
|
||||
|
||||
return resultats;
|
||||
}
|
||||
|
||||
// Actions
|
||||
public void voirDemande(Demande demande) {
|
||||
this.demandeSelectionnee = demande;
|
||||
LOGGER.info("Voir demande: " + demande.getObjet());
|
||||
}
|
||||
|
||||
public void traiterDemande(Demande demande) {
|
||||
demande.setStatut("EN_COURS");
|
||||
LOGGER.info("Traitement demande: " + demande.getObjet());
|
||||
}
|
||||
|
||||
public void approuverDemande(Demande demande) {
|
||||
demande.setStatut("APPROUVEE");
|
||||
LOGGER.info("Demande approuvée: " + demande.getObjet());
|
||||
}
|
||||
|
||||
public void rejeterDemande(Demande demande) {
|
||||
demande.setStatut("REJETEE");
|
||||
LOGGER.info("Demande rejetée: " + demande.getObjet());
|
||||
}
|
||||
|
||||
public void assignerDemande(Demande demande) {
|
||||
LOGGER.info("Assigner demande: " + demande.getObjet());
|
||||
}
|
||||
|
||||
public void voirPiecesJointes(Demande demande) {
|
||||
LOGGER.info("Voir pièces jointes: " + demande.getObjet());
|
||||
}
|
||||
|
||||
public void creerDemande() {
|
||||
LOGGER.info("Créer nouvelle demande: " + nouvelleDemande.getObjet());
|
||||
initializeNouvelleDemande();
|
||||
}
|
||||
|
||||
public void effectuerAssignationLot() {
|
||||
LOGGER.info("Assignation en lot à gestionnaire ID: " + gestionnaireAssignation);
|
||||
}
|
||||
|
||||
public void marquerTraitees() {
|
||||
selectedDemandes.forEach(d -> d.setStatut("TRAITEE"));
|
||||
LOGGER.info("Marquées comme traitées: " + selectedDemandes.size());
|
||||
}
|
||||
|
||||
public void exporterSelection() {
|
||||
LOGGER.info("Export de " + selectedDemandes.size() + " demandes");
|
||||
}
|
||||
|
||||
public void exporterDemandes() {
|
||||
LOGGER.info("Export de toutes les demandes");
|
||||
}
|
||||
|
||||
public void actualiser() {
|
||||
LOGGER.info("Actualisation des données");
|
||||
initializeDemandes();
|
||||
calculerStatistiques();
|
||||
}
|
||||
|
||||
public void filtrerUrgentes() {
|
||||
LOGGER.info("Filtrer les demandes urgentes");
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public List<Demande> getDemandes() { return demandes; }
|
||||
public void setDemandes(List<Demande> demandes) { this.demandes = demandes; }
|
||||
|
||||
public List<Demande> getSelectedDemandes() { return selectedDemandes; }
|
||||
public void setSelectedDemandes(List<Demande> selectedDemandes) { this.selectedDemandes = selectedDemandes; }
|
||||
|
||||
public List<Demande> getDemandesUrgentes() { return demandesUrgentes; }
|
||||
public void setDemandesUrgentes(List<Demande> demandesUrgentes) { this.demandesUrgentes = demandesUrgentes; }
|
||||
|
||||
public List<Demande> getDernieresDemandes() { return dernieresDemandes; }
|
||||
public void setDernieresDemandes(List<Demande> dernieresDemandes) { this.dernieresDemandes = dernieresDemandes; }
|
||||
|
||||
public List<Gestionnaire> getGestionnairesDisponibles() { return gestionnairesDisponibles; }
|
||||
public void setGestionnairesDisponibles(List<Gestionnaire> gestionnairesDisponibles) { this.gestionnairesDisponibles = gestionnairesDisponibles; }
|
||||
|
||||
public Membre getMembreDemandeur() { return membreDemandeur; }
|
||||
public void setMembreDemandeur(Membre membreDemandeur) { this.membreDemandeur = membreDemandeur; }
|
||||
|
||||
public NouvelleDemande getNouvelleDemande() { return nouvelleDemande; }
|
||||
public void setNouvelleDemande(NouvelleDemande nouvelleDemande) { this.nouvelleDemande = nouvelleDemande; }
|
||||
|
||||
public String getSearchFilter() { return searchFilter; }
|
||||
public void setSearchFilter(String searchFilter) { this.searchFilter = searchFilter; }
|
||||
|
||||
public String getStatutFilter() { return statutFilter; }
|
||||
public void setStatutFilter(String statutFilter) { this.statutFilter = statutFilter; }
|
||||
|
||||
public String getTypeFilter() { return typeFilter; }
|
||||
public void setTypeFilter(String typeFilter) { this.typeFilter = typeFilter; }
|
||||
|
||||
public String getPrioriteFilter() { return prioriteFilter; }
|
||||
public void setPrioriteFilter(String prioriteFilter) { this.prioriteFilter = prioriteFilter; }
|
||||
|
||||
public LocalDate getDateFilter() { return dateFilter; }
|
||||
public void setDateFilter(LocalDate dateFilter) { this.dateFilter = dateFilter; }
|
||||
|
||||
public UUID getGestionnaireAssignation() { return gestionnaireAssignation; }
|
||||
public void setGestionnaireAssignation(UUID gestionnaireAssignation) { this.gestionnaireAssignation = gestionnaireAssignation; }
|
||||
|
||||
public String getCommentaireAssignation() { return commentaireAssignation; }
|
||||
public void setCommentaireAssignation(String commentaireAssignation) { this.commentaireAssignation = commentaireAssignation; }
|
||||
|
||||
public int getEnAttente() { return enAttente; }
|
||||
public void setEnAttente(int enAttente) { this.enAttente = enAttente; }
|
||||
|
||||
public int getUrgentes() { return urgentes; }
|
||||
public void setUrgentes(int urgentes) { this.urgentes = urgentes; }
|
||||
|
||||
public int getTraitees() { return traitees; }
|
||||
public void setTraitees(int traitees) { this.traitees = traitees; }
|
||||
|
||||
public int getDelaiMoyenTraitement() { return delaiMoyenTraitement; }
|
||||
public void setDelaiMoyenTraitement(int delaiMoyenTraitement) { this.delaiMoyenTraitement = delaiMoyenTraitement; }
|
||||
|
||||
public Demande getDemandeSelectionnee() { return demandeSelectionnee; }
|
||||
public void setDemandeSelectionnee(Demande demandeSelectionnee) { this.demandeSelectionnee = demandeSelectionnee; }
|
||||
|
||||
// Classes internes
|
||||
public static class Demande {
|
||||
private UUID id;
|
||||
private String reference;
|
||||
private String objet;
|
||||
private String type;
|
||||
private String statut;
|
||||
private String priorite;
|
||||
private String nomDemandeur;
|
||||
private String numeroMembre;
|
||||
private String telephoneDemandeur;
|
||||
private LocalDate dateDepot;
|
||||
private LocalDate dateEcheance;
|
||||
private String heureDepot;
|
||||
private String assigneA;
|
||||
private String demandeur;
|
||||
private boolean hasPiecesJointes = false;
|
||||
|
||||
// Getters et setters
|
||||
public UUID getId() { return id; }
|
||||
public void setId(UUID id) { this.id = id; }
|
||||
|
||||
public String getReference() { return reference; }
|
||||
public void setReference(String reference) { this.reference = reference; }
|
||||
|
||||
public String getObjet() { return objet; }
|
||||
public void setObjet(String objet) { this.objet = objet; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getPriorite() { return priorite; }
|
||||
public void setPriorite(String priorite) { this.priorite = priorite; }
|
||||
|
||||
public String getNomDemandeur() { return nomDemandeur; }
|
||||
public void setNomDemandeur(String nomDemandeur) { this.nomDemandeur = nomDemandeur; }
|
||||
|
||||
public String getNumeroMembre() { return numeroMembre; }
|
||||
public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
|
||||
|
||||
public String getTelephoneDemandeur() { return telephoneDemandeur; }
|
||||
public void setTelephoneDemandeur(String telephoneDemandeur) { this.telephoneDemandeur = telephoneDemandeur; }
|
||||
|
||||
public LocalDate getDateDepot() { return dateDepot; }
|
||||
public void setDateDepot(LocalDate dateDepot) { this.dateDepot = dateDepot; }
|
||||
|
||||
public LocalDate getDateEcheance() { return dateEcheance; }
|
||||
public void setDateEcheance(LocalDate dateEcheance) { this.dateEcheance = dateEcheance; }
|
||||
|
||||
public String getHeureDepot() { return heureDepot; }
|
||||
public void setHeureDepot(String heureDepot) { this.heureDepot = heureDepot; }
|
||||
|
||||
public String getAssigneA() { return assigneA; }
|
||||
public void setAssigneA(String assigneA) { this.assigneA = assigneA; }
|
||||
|
||||
public String getDemandeur() { return demandeur != null ? demandeur : nomDemandeur; }
|
||||
public void setDemandeur(String demandeur) { this.demandeur = demandeur; }
|
||||
|
||||
public boolean isHasPiecesJointes() { return hasPiecesJointes; }
|
||||
public void setHasPiecesJointes(boolean hasPiecesJointes) { this.hasPiecesJointes = hasPiecesJointes; }
|
||||
|
||||
// Propriétés dérivées
|
||||
public String getNomCompletDemandeur() { return nomDemandeur; }
|
||||
public String getInitialesDemandeur() {
|
||||
if (nomDemandeur == null) return "??";
|
||||
String[] parts = nomDemandeur.split(" ");
|
||||
return parts.length >= 2 ? parts[0].substring(0,1) + parts[1].substring(0,1) : nomDemandeur.substring(0, Math.min(2, nomDemandeur.length()));
|
||||
}
|
||||
|
||||
public String getTypeIcon() {
|
||||
return switch (type) {
|
||||
case "ADHESION" -> "pi-user-plus";
|
||||
case "AIDE_FINANCIERE" -> "pi-money-bill";
|
||||
case "CERTIFICAT" -> "pi-file";
|
||||
case "MUTATION" -> "pi-arrow-right-arrow-left";
|
||||
case "RECLAMATION" -> "pi-exclamation-triangle";
|
||||
default -> "pi-question";
|
||||
};
|
||||
}
|
||||
|
||||
public String getTypeColorClass() {
|
||||
return switch (type) {
|
||||
case "ADHESION" -> "bg-blue-500";
|
||||
case "AIDE_FINANCIERE" -> "bg-green-500";
|
||||
case "CERTIFICAT" -> "bg-purple-500";
|
||||
case "MUTATION" -> "bg-orange-500";
|
||||
case "RECLAMATION" -> "bg-red-500";
|
||||
default -> "bg-gray-500";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutSeverity() {
|
||||
return switch (statut) {
|
||||
case "EN_ATTENTE" -> "warning";
|
||||
case "EN_COURS" -> "info";
|
||||
case "APPROUVEE" -> "success";
|
||||
case "REJETEE" -> "danger";
|
||||
case "URGENTE" -> "danger";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutIcon() {
|
||||
return switch (statut) {
|
||||
case "EN_ATTENTE" -> "pi-clock";
|
||||
case "EN_COURS" -> "pi-spin pi-spinner";
|
||||
case "APPROUVEE" -> "pi-check";
|
||||
case "REJETEE" -> "pi-times";
|
||||
case "URGENTE" -> "pi-exclamation-triangle";
|
||||
default -> "pi-circle";
|
||||
};
|
||||
}
|
||||
|
||||
public String getPrioriteSeverity() {
|
||||
return switch (priorite) {
|
||||
case "URGENTE" -> "danger";
|
||||
case "HAUTE" -> "warning";
|
||||
case "NORMALE" -> "info";
|
||||
case "BASSE" -> "secondary";
|
||||
default -> "primary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getPrioriteIcon() {
|
||||
return switch (priorite) {
|
||||
case "URGENTE" -> "pi-exclamation-triangle";
|
||||
case "HAUTE" -> "pi-arrow-up";
|
||||
case "NORMALE" -> "pi-minus";
|
||||
case "BASSE" -> "pi-arrow-down";
|
||||
default -> "pi-circle";
|
||||
};
|
||||
}
|
||||
|
||||
public String getDateDepotRelative() {
|
||||
if (dateDepot == null) return "";
|
||||
long jours = ChronoUnit.DAYS.between(dateDepot, LocalDate.now());
|
||||
if (jours == 0) return "aujourd'hui";
|
||||
if (jours == 1) return "hier";
|
||||
return "il y a " + jours + " jours";
|
||||
}
|
||||
|
||||
public String getEcheanceClass() {
|
||||
if (dateEcheance == null) return "";
|
||||
long jours = ChronoUnit.DAYS.between(LocalDate.now(), dateEcheance);
|
||||
if (jours < 0) return "text-red-500 font-bold";
|
||||
if (jours <= 3) return "text-orange-500 font-bold";
|
||||
return "text-600";
|
||||
}
|
||||
}
|
||||
|
||||
public static class Membre {
|
||||
private UUID id;
|
||||
private String nomComplet;
|
||||
private String numeroMembre;
|
||||
|
||||
public UUID getId() { return id; }
|
||||
public void setId(UUID id) { this.id = id; }
|
||||
|
||||
public String getNomComplet() { return nomComplet; }
|
||||
public void setNomComplet(String nomComplet) { this.nomComplet = nomComplet; }
|
||||
|
||||
public String getNumeroMembre() { return numeroMembre; }
|
||||
public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
|
||||
|
||||
public String getInitiales() {
|
||||
if (nomComplet == null) return "??";
|
||||
String[] parts = nomComplet.split(" ");
|
||||
return parts.length >= 2 ? parts[0].substring(0,1) + parts[1].substring(0,1) : nomComplet.substring(0, Math.min(2, nomComplet.length()));
|
||||
}
|
||||
}
|
||||
|
||||
public static class NouvelleDemande {
|
||||
private String objet;
|
||||
private String type;
|
||||
private String priorite;
|
||||
private String description;
|
||||
private LocalDate dateEcheance;
|
||||
private UUID assigneA;
|
||||
|
||||
public String getObjet() { return objet; }
|
||||
public void setObjet(String objet) { this.objet = objet; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getPriorite() { return priorite; }
|
||||
public void setPriorite(String priorite) { this.priorite = priorite; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public LocalDate getDateEcheance() { return dateEcheance; }
|
||||
public void setDateEcheance(LocalDate dateEcheance) { this.dateEcheance = dateEcheance; }
|
||||
|
||||
public UUID getAssigneA() { return assigneA; }
|
||||
public void setAssigneA(UUID assigneA) { this.assigneA = assigneA; }
|
||||
}
|
||||
|
||||
public static class Gestionnaire {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
|
||||
public Gestionnaire() {}
|
||||
|
||||
public Gestionnaire(UUID id, String nom) {
|
||||
this.id = id;
|
||||
this.nom = 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; }
|
||||
}
|
||||
}
|
||||
636
src/main/java/dev/lions/unionflow/client/view/DocumentsBean.java
Normal file
636
src/main/java/dev/lions/unionflow/client/view/DocumentsBean.java
Normal file
@@ -0,0 +1,636 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
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.UUID;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Named("documentsBean")
|
||||
@SessionScoped
|
||||
public class DocumentsBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(DocumentsBean.class.getName());
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_DOCUMENTS_VERSIONS = "documentsVersionsPage";
|
||||
|
||||
private List<Document> tousLesDocuments;
|
||||
private List<Document> documentsFiltres;
|
||||
private List<Document> documentsSelectionnes;
|
||||
private List<Dossier> dossiersAffichage;
|
||||
private List<Dossier> dossiersDisponibles;
|
||||
private List<NiveauNavigation> cheminNavigation;
|
||||
|
||||
private Document documentSelectionne;
|
||||
private Dossier dossierSelectionne;
|
||||
private NouveauDocument nouveauDocument;
|
||||
private Filtres filtres;
|
||||
private StatistiquesDocuments statistiques;
|
||||
|
||||
private String modeAffichage = "GRID"; // GRID ou LIST
|
||||
private UUID dossierActuelId;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initializeFiltres();
|
||||
initializeStatistiques();
|
||||
initializeDossiers();
|
||||
initializeDocuments();
|
||||
initializeNouveauDocument();
|
||||
initializeNavigation();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
private void initializeFiltres() {
|
||||
filtres = new Filtres();
|
||||
documentsSelectionnes = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void initializeStatistiques() {
|
||||
statistiques = new StatistiquesDocuments();
|
||||
try {
|
||||
// Les statistiques seront calculées depuis les documents réels
|
||||
// Pour l'instant, initialiser avec des valeurs par défaut
|
||||
statistiques.setTotalDocuments(tousLesDocuments != null ? tousLesDocuments.size() : 0);
|
||||
statistiques.setTotalDossiers(dossiersDisponibles != null ? dossiersDisponibles.size() : 0);
|
||||
statistiques.setEspaceUtilise("0 GB");
|
||||
statistiques.setPartagesMois(0);
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du calcul des statistiques: " + e.getMessage());
|
||||
statistiques.setTotalDocuments(0);
|
||||
statistiques.setTotalDossiers(0);
|
||||
statistiques.setEspaceUtilise("0 GB");
|
||||
statistiques.setPartagesMois(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeDossiers() {
|
||||
dossiersAffichage = new ArrayList<>();
|
||||
dossiersDisponibles = new ArrayList<>();
|
||||
// Les dossiers seront chargés depuis l'API backend
|
||||
// Pour l'instant, laisser les listes vides plutôt que des données mockées
|
||||
}
|
||||
|
||||
private void initializeDocuments() {
|
||||
tousLesDocuments = new ArrayList<>();
|
||||
// Les documents seront chargés depuis l'API backend
|
||||
// Pour l'instant, laisser la liste vide plutôt que des données mockées
|
||||
}
|
||||
|
||||
private void initializeNouveauDocument() {
|
||||
nouveauDocument = new NouveauDocument();
|
||||
nouveauDocument.setAccesRestreint(false);
|
||||
}
|
||||
|
||||
private void initializeNavigation() {
|
||||
cheminNavigation = new ArrayList<>();
|
||||
|
||||
NiveauNavigation racine = new NiveauNavigation();
|
||||
racine.setNom("📁 Racine");
|
||||
racine.setDossierId(null);
|
||||
cheminNavigation.add(racine);
|
||||
|
||||
// Si on est dans un dossier spécifique, ajouter le niveau
|
||||
if (dossierActuelId != null) {
|
||||
Dossier dossierActuel = dossiersDisponibles.stream()
|
||||
.filter(d -> d.getId().equals(dossierActuelId))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
|
||||
if (dossierActuel != null) {
|
||||
NiveauNavigation niveau = new NiveauNavigation();
|
||||
niveau.setNom(dossierActuel.getNom());
|
||||
niveau.setDossierId(dossierActuel.getId());
|
||||
cheminNavigation.add(niveau);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void appliquerFiltres() {
|
||||
documentsFiltres = tousLesDocuments.stream()
|
||||
.filter(this::appliquerFiltre)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean appliquerFiltre(Document document) {
|
||||
// Filtre par dossier actuel
|
||||
if (dossierActuelId != null) {
|
||||
if (document.getDossierId() == null || !document.getDossierId().equals(dossierActuelId)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Si on est à la racine, ne montrer que les documents sans dossier parent
|
||||
if (document.getDossierId() != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getNom() != null && !filtres.getNom().trim().isEmpty()) {
|
||||
if (!document.getNom().toLowerCase().contains(filtres.getNom().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getType() != null && !filtres.getType().trim().isEmpty()) {
|
||||
if (!document.getType().equals(filtres.getType())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getCategorie() != null && !filtres.getCategorie().trim().isEmpty()) {
|
||||
if (!document.getCategorie().equals(filtres.getCategorie())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getStatut() != null && !filtres.getStatut().trim().isEmpty()) {
|
||||
if (!document.getStatut().equals(filtres.getStatut())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getAuteur() != null && !filtres.getAuteur().trim().isEmpty()) {
|
||||
if (!document.getAuteur().toLowerCase().contains(filtres.getAuteur().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getMotsCles() != null && !filtres.getMotsCles().trim().isEmpty()) {
|
||||
if (!document.getMotsCles().toLowerCase().contains(filtres.getMotsCles().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getDateDebut() != null) {
|
||||
if (document.getDateCreation().toLocalDate().isBefore(filtres.getDateDebut())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getDateFin() != null) {
|
||||
if (document.getDateCreation().toLocalDate().isAfter(filtres.getDateFin())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getTailleMax() != null && filtres.getTailleMax() > 0) {
|
||||
long tailleMaxBytes = filtres.getTailleMax().longValue() * 1024 * 1024; // Conversion MB vers bytes
|
||||
if (document.getTailleBytes() > tailleMaxBytes) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Actions
|
||||
public void rechercher() {
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void reinitialiserFiltres() {
|
||||
filtres = new Filtres();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void changerModeAffichage(String mode) {
|
||||
this.modeAffichage = mode;
|
||||
}
|
||||
|
||||
public void naviguerVersDossier(Dossier dossier) {
|
||||
this.dossierActuelId = dossier.getId();
|
||||
initializeNavigation();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void telechargerNouveauDocument() {
|
||||
Document nouveau = new Document();
|
||||
nouveau.setId(UUID.randomUUID());
|
||||
nouveau.setNom("Nouveau Document " + (tousLesDocuments.size() + 1));
|
||||
nouveau.setCategorie(nouveauDocument.getCategorie());
|
||||
nouveau.setDescription(nouveauDocument.getDescription());
|
||||
nouveau.setMotsCles(nouveauDocument.getMotsCles());
|
||||
nouveau.setDossierId(nouveauDocument.getDossierId());
|
||||
nouveau.setStatut("BROUILLON");
|
||||
nouveau.setAuteur("Utilisateur Actuel");
|
||||
nouveau.setDateCreation(LocalDateTime.now());
|
||||
nouveau.setDateModification(LocalDateTime.now());
|
||||
nouveau.setTailleBytes(1024000L); // 1MB par défaut
|
||||
nouveau.setNombreVues(0);
|
||||
nouveau.setNombreTelecharements(0);
|
||||
nouveau.setType("PDF"); // Type par défaut
|
||||
|
||||
tousLesDocuments.add(nouveau);
|
||||
appliquerFiltres();
|
||||
|
||||
LOGGER.info("Document téléchargé: " + nouveau.getNom());
|
||||
initializeNouveauDocument();
|
||||
}
|
||||
|
||||
public void telechargerDocument(Document document) {
|
||||
document.setNombreTelecharements(document.getNombreTelecharements() + 1);
|
||||
LOGGER.info("Téléchargement du document: " + document.getNom());
|
||||
}
|
||||
|
||||
public void supprimerDocument(Document document) {
|
||||
tousLesDocuments.remove(document);
|
||||
appliquerFiltres();
|
||||
LOGGER.info("Document supprimé: " + document.getNom());
|
||||
}
|
||||
|
||||
public void dupliquerDocument() {
|
||||
if (documentSelectionne != null) {
|
||||
Document copie = new Document();
|
||||
copie.setId(UUID.randomUUID());
|
||||
copie.setNom(documentSelectionne.getNom() + " (Copie)");
|
||||
copie.setType(documentSelectionne.getType());
|
||||
copie.setCategorie(documentSelectionne.getCategorie());
|
||||
copie.setStatut("BROUILLON");
|
||||
copie.setAuteur("Utilisateur Actuel");
|
||||
copie.setDescription(documentSelectionne.getDescription());
|
||||
copie.setMotsCles(documentSelectionne.getMotsCles());
|
||||
copie.setDossierId(documentSelectionne.getDossierId());
|
||||
copie.setTailleBytes(documentSelectionne.getTailleBytes());
|
||||
copie.setDateCreation(LocalDateTime.now());
|
||||
copie.setDateModification(LocalDateTime.now());
|
||||
copie.setNombreVues(0);
|
||||
copie.setNombreTelecharements(0);
|
||||
|
||||
tousLesDocuments.add(copie);
|
||||
appliquerFiltres();
|
||||
LOGGER.info("Document dupliqué: " + copie.getNom());
|
||||
}
|
||||
}
|
||||
|
||||
public void archiverDocument() {
|
||||
if (documentSelectionne != null) {
|
||||
documentSelectionne.setStatut("ARCHIVE");
|
||||
LOGGER.info("Document archivé: " + documentSelectionne.getNom());
|
||||
appliquerFiltres();
|
||||
}
|
||||
}
|
||||
|
||||
public void supprimerDefinitivement() {
|
||||
if (documentSelectionne != null) {
|
||||
tousLesDocuments.remove(documentSelectionne);
|
||||
appliquerFiltres();
|
||||
LOGGER.info("Document supprimé définitivement: " + documentSelectionne.getNom());
|
||||
}
|
||||
}
|
||||
|
||||
public String voirHistoriqueVersions() {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_DOCUMENTS_VERSIONS + "?id=" + documentSelectionne.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
public boolean estSelectionne(Document document) {
|
||||
return documentsSelectionnes.contains(document);
|
||||
}
|
||||
|
||||
public void toggleSelection(Document document) {
|
||||
if (documentsSelectionnes.contains(document)) {
|
||||
documentsSelectionnes.remove(document);
|
||||
} else {
|
||||
documentsSelectionnes.add(document);
|
||||
}
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public List<Document> getTousLesDocuments() { return tousLesDocuments; }
|
||||
public void setTousLesDocuments(List<Document> tousLesDocuments) { this.tousLesDocuments = tousLesDocuments; }
|
||||
|
||||
public List<Document> getDocumentsFiltres() { return documentsFiltres; }
|
||||
public void setDocumentsFiltres(List<Document> documentsFiltres) { this.documentsFiltres = documentsFiltres; }
|
||||
|
||||
public List<Document> getDocumentsSelectionnes() { return documentsSelectionnes; }
|
||||
public void setDocumentsSelectionnes(List<Document> documentsSelectionnes) { this.documentsSelectionnes = documentsSelectionnes; }
|
||||
|
||||
public List<Dossier> getDossiersAffichage() { return dossiersAffichage; }
|
||||
public void setDossiersAffichage(List<Dossier> dossiersAffichage) { this.dossiersAffichage = dossiersAffichage; }
|
||||
|
||||
public List<Dossier> getDossiersDisponibles() { return dossiersDisponibles; }
|
||||
public void setDossiersDisponibles(List<Dossier> dossiersDisponibles) { this.dossiersDisponibles = dossiersDisponibles; }
|
||||
|
||||
public List<NiveauNavigation> getCheminNavigation() { return cheminNavigation; }
|
||||
public void setCheminNavigation(List<NiveauNavigation> cheminNavigation) { this.cheminNavigation = cheminNavigation; }
|
||||
|
||||
public Document getDocumentSelectionne() { return documentSelectionne; }
|
||||
public void setDocumentSelectionne(Document documentSelectionne) { this.documentSelectionne = documentSelectionne; }
|
||||
|
||||
public Dossier getDossierSelectionne() { return dossierSelectionne; }
|
||||
public void setDossierSelectionne(Dossier dossierSelectionne) { this.dossierSelectionne = dossierSelectionne; }
|
||||
|
||||
public NouveauDocument getNouveauDocument() { return nouveauDocument; }
|
||||
public void setNouveauDocument(NouveauDocument nouveauDocument) { this.nouveauDocument = nouveauDocument; }
|
||||
|
||||
public Filtres getFiltres() { return filtres; }
|
||||
public void setFiltres(Filtres filtres) { this.filtres = filtres; }
|
||||
|
||||
public StatistiquesDocuments getStatistiques() { return statistiques; }
|
||||
public void setStatistiques(StatistiquesDocuments statistiques) { this.statistiques = statistiques; }
|
||||
|
||||
public String getModeAffichage() { return modeAffichage; }
|
||||
public void setModeAffichage(String modeAffichage) { this.modeAffichage = modeAffichage; }
|
||||
|
||||
public UUID getDossierActuelId() { return dossierActuelId; }
|
||||
public void setDossierActuelId(UUID dossierActuelId) { this.dossierActuelId = dossierActuelId; }
|
||||
|
||||
// Classes internes
|
||||
public static class Document {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
private String description;
|
||||
private String type;
|
||||
private String categorie;
|
||||
private String statut;
|
||||
private String auteur;
|
||||
private String motsCles;
|
||||
private UUID dossierId;
|
||||
private long tailleBytes;
|
||||
private LocalDateTime dateCreation;
|
||||
private LocalDateTime dateModification;
|
||||
private int nombreVues;
|
||||
private int nombreTelecharements;
|
||||
private boolean accesRestreint;
|
||||
|
||||
// Getters et setters
|
||||
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 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 getCategorie() { return categorie; }
|
||||
public void setCategorie(String categorie) { this.categorie = categorie; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getAuteur() { return auteur; }
|
||||
public void setAuteur(String auteur) { this.auteur = auteur; }
|
||||
|
||||
public String getMotsCles() { return motsCles; }
|
||||
public void setMotsCles(String motsCles) { this.motsCles = motsCles; }
|
||||
|
||||
public UUID getDossierId() { return dossierId; }
|
||||
public void setDossierId(UUID dossierId) { this.dossierId = dossierId; }
|
||||
|
||||
public long getTailleBytes() { return tailleBytes; }
|
||||
public void setTailleBytes(long tailleBytes) { this.tailleBytes = tailleBytes; }
|
||||
|
||||
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 int getNombreVues() { return nombreVues; }
|
||||
public void setNombreVues(int nombreVues) { this.nombreVues = nombreVues; }
|
||||
|
||||
public int getNombreTelecharements() { return nombreTelecharements; }
|
||||
public void setNombreTelecharements(int nombreTelecharements) { this.nombreTelecharements = nombreTelecharements; }
|
||||
|
||||
public boolean isAccesRestreint() { return accesRestreint; }
|
||||
public void setAccesRestreint(boolean accesRestreint) { this.accesRestreint = accesRestreint; }
|
||||
|
||||
// Propriétés dérivées
|
||||
public String getTypeIcon() {
|
||||
return switch (type) {
|
||||
case "PDF" -> "pi-file-pdf";
|
||||
case "WORD" -> "pi-file-word";
|
||||
case "EXCEL" -> "pi-file-excel";
|
||||
case "POWERPOINT" -> "pi-file";
|
||||
case "IMAGE" -> "pi-image";
|
||||
default -> "pi-file";
|
||||
};
|
||||
}
|
||||
|
||||
public String getTypeCouleur() {
|
||||
return switch (type) {
|
||||
case "PDF" -> "red-500";
|
||||
case "WORD" -> "blue-500";
|
||||
case "EXCEL" -> "green-500";
|
||||
case "POWERPOINT" -> "orange-500";
|
||||
case "IMAGE" -> "purple-500";
|
||||
default -> "gray-500";
|
||||
};
|
||||
}
|
||||
|
||||
public String getCategorieLibelle() {
|
||||
return switch (categorie) {
|
||||
case "ADMINISTRATIF" -> "Administratif";
|
||||
case "FINANCIER" -> "Financier";
|
||||
case "JURIDIQUE" -> "Juridique";
|
||||
case "COMMUNICATION" -> "Communication";
|
||||
case "FORMATION" -> "Formation";
|
||||
case "AUTRE" -> "Autre";
|
||||
default -> categorie;
|
||||
};
|
||||
}
|
||||
|
||||
public String getCategorieSeverity() {
|
||||
return switch (categorie) {
|
||||
case "ADMINISTRATIF" -> "info";
|
||||
case "FINANCIER" -> "success";
|
||||
case "JURIDIQUE" -> "danger";
|
||||
case "COMMUNICATION" -> "warning";
|
||||
case "FORMATION" -> "primary";
|
||||
case "AUTRE" -> "secondary";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutLibelle() {
|
||||
return switch (statut) {
|
||||
case "BROUILLON" -> "Brouillon";
|
||||
case "VALIDE" -> "Validé";
|
||||
case "ARCHIVE" -> "Archivé";
|
||||
case "EXPIRE" -> "Expiré";
|
||||
default -> statut;
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutSeverity() {
|
||||
return switch (statut) {
|
||||
case "BROUILLON" -> "warning";
|
||||
case "VALIDE" -> "success";
|
||||
case "ARCHIVE" -> "secondary";
|
||||
case "EXPIRE" -> "danger";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getTaille() {
|
||||
if (tailleBytes < 1024) {
|
||||
return tailleBytes + " B";
|
||||
} else if (tailleBytes < 1024 * 1024) {
|
||||
return Math.round(tailleBytes / 1024.0) + " KB";
|
||||
} else {
|
||||
return Math.round(tailleBytes / (1024.0 * 1024)) + " MB";
|
||||
}
|
||||
}
|
||||
|
||||
public String getDateCreationFormatee() {
|
||||
if (dateCreation == null) return "";
|
||||
return dateCreation.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
|
||||
}
|
||||
|
||||
public String getDateCreationRelative() {
|
||||
if (dateCreation == null) return "";
|
||||
long jours = ChronoUnit.DAYS.between(dateCreation.toLocalDate(), LocalDate.now());
|
||||
if (jours == 0) return "Aujourd'hui";
|
||||
if (jours == 1) return "Hier";
|
||||
if (jours < 7) return "Il y a " + jours + " jours";
|
||||
if (jours < 30) return "Il y a " + (jours / 7) + " semaine" + (jours / 7 > 1 ? "s" : "");
|
||||
return "Il y a " + (jours / 30) + " mois";
|
||||
}
|
||||
}
|
||||
|
||||
public static class Dossier {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
private String couleur;
|
||||
private int nombreDocuments;
|
||||
private LocalDateTime derniereModification;
|
||||
private String cheminComplet;
|
||||
|
||||
// Getters et setters
|
||||
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 getCouleur() { return couleur; }
|
||||
public void setCouleur(String couleur) { this.couleur = couleur; }
|
||||
|
||||
public int getNombreDocuments() { return nombreDocuments; }
|
||||
public void setNombreDocuments(int nombreDocuments) { this.nombreDocuments = nombreDocuments; }
|
||||
|
||||
public LocalDateTime getDerniereModification() { return derniereModification; }
|
||||
public void setDerniereModification(LocalDateTime derniereModification) { this.derniereModification = derniereModification; }
|
||||
|
||||
public String getCheminComplet() { return cheminComplet; }
|
||||
public void setCheminComplet(String cheminComplet) { this.cheminComplet = cheminComplet; }
|
||||
|
||||
public String getDerniereModificationRelative() {
|
||||
if (derniereModification == null) return "";
|
||||
long jours = ChronoUnit.DAYS.between(derniereModification.toLocalDate(), LocalDate.now());
|
||||
if (jours == 0) return "aujourd'hui";
|
||||
if (jours == 1) return "hier";
|
||||
return "il y a " + jours + " jours";
|
||||
}
|
||||
}
|
||||
|
||||
public static class NouveauDocument {
|
||||
private String categorie;
|
||||
private String description;
|
||||
private String motsCles;
|
||||
private UUID dossierId;
|
||||
private boolean accesRestreint;
|
||||
|
||||
// Getters et setters
|
||||
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 getMotsCles() { return motsCles; }
|
||||
public void setMotsCles(String motsCles) { this.motsCles = motsCles; }
|
||||
|
||||
public UUID getDossierId() { return dossierId; }
|
||||
public void setDossierId(UUID dossierId) { this.dossierId = dossierId; }
|
||||
|
||||
public boolean isAccesRestreint() { return accesRestreint; }
|
||||
public void setAccesRestreint(boolean accesRestreint) { this.accesRestreint = accesRestreint; }
|
||||
}
|
||||
|
||||
public static class Filtres {
|
||||
private String nom;
|
||||
private String type;
|
||||
private String categorie;
|
||||
private String statut;
|
||||
private String auteur;
|
||||
private String motsCles;
|
||||
private LocalDate dateDebut;
|
||||
private LocalDate dateFin;
|
||||
private Double tailleMax;
|
||||
|
||||
// Getters et setters
|
||||
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 String getCategorie() { return categorie; }
|
||||
public void setCategorie(String categorie) { this.categorie = categorie; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getAuteur() { return auteur; }
|
||||
public void setAuteur(String auteur) { this.auteur = auteur; }
|
||||
|
||||
public String getMotsCles() { return motsCles; }
|
||||
public void setMotsCles(String motsCles) { this.motsCles = motsCles; }
|
||||
|
||||
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 Double getTailleMax() { return tailleMax; }
|
||||
public void setTailleMax(Double tailleMax) { this.tailleMax = tailleMax; }
|
||||
}
|
||||
|
||||
public static class StatistiquesDocuments {
|
||||
private int totalDocuments;
|
||||
private int totalDossiers;
|
||||
private String espaceUtilise;
|
||||
private int partagesMois;
|
||||
|
||||
// Getters et setters
|
||||
public int getTotalDocuments() { return totalDocuments; }
|
||||
public void setTotalDocuments(int totalDocuments) { this.totalDocuments = totalDocuments; }
|
||||
|
||||
public int getTotalDossiers() { return totalDossiers; }
|
||||
public void setTotalDossiers(int totalDossiers) { this.totalDossiers = totalDossiers; }
|
||||
|
||||
public String getEspaceUtilise() { return espaceUtilise; }
|
||||
public void setEspaceUtilise(String espaceUtilise) { this.espaceUtilise = espaceUtilise; }
|
||||
|
||||
public int getPartagesMois() { return partagesMois; }
|
||||
public void setPartagesMois(int partagesMois) { this.partagesMois = partagesMois; }
|
||||
}
|
||||
|
||||
public static class NiveauNavigation {
|
||||
private String nom;
|
||||
private UUID dossierId;
|
||||
|
||||
// Getters et setters
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public UUID getDossierId() { return dossierId; }
|
||||
public void setDossierId(UUID dossierId) { this.dossierId = dossierId; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,697 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.dto.AssociationDTO;
|
||||
import dev.lions.unionflow.client.service.AssociationService;
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
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.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("entitesGestionBean")
|
||||
@SessionScoped
|
||||
public class EntitesGestionBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(EntitesGestionBean.class.getName());
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_ENTITE_DETAILS = "entiteDetailsPage";
|
||||
private static final String OUTCOME_ADMIN_MEMBRES_GESTION = "adminMembresGestionPage";
|
||||
private static final String OUTCOME_ENTITE_CONFIGURATION = "entiteConfigurationPage";
|
||||
private static final String OUTCOME_ENTITE_RAPPORTS = "entiteRapportsPage";
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private AssociationService associationService;
|
||||
|
||||
private List<Entite> toutesLesEntites;
|
||||
private List<Entite> entitesFiltrees;
|
||||
private List<Entite> entitesSelectionnees;
|
||||
private Entite entiteSelectionne;
|
||||
private Entite nouvelleEntite;
|
||||
private Filtres filtres;
|
||||
private Statistiques statistiques;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initializeFiltres();
|
||||
initializeEntites();
|
||||
initializeStatistiques();
|
||||
initializeNouvelleEntite();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
private void initializeFiltres() {
|
||||
filtres = new Filtres();
|
||||
entitesSelectionnees = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void initializeStatistiques() {
|
||||
statistiques = new Statistiques();
|
||||
try {
|
||||
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);
|
||||
int totalMembres = associations.stream()
|
||||
.mapToInt(a -> a.getNombreMembres() != null ? a.getNombreMembres() : 0)
|
||||
.sum();
|
||||
statistiques.setTotalMembres(totalMembres);
|
||||
double moyenne = associations.isEmpty() ? 0 : (double) totalMembres / associations.size();
|
||||
statistiques.setMoyenneMembresParEntite((int) moyenne);
|
||||
statistiques.setRevenus("0 FCFA"); // TODO: Calculer depuis les souscriptions/paiements réels
|
||||
statistiques.setSouscriptionsExpirantes(0); // TODO: Calculer depuis les souscriptions expirantes
|
||||
statistiques.setEntitesQuotaAtteint(0); // TODO: Calculer depuis les entités avec quota atteint
|
||||
statistiques.setFormulairePopulaire("N/A"); // TODO: Calculer depuis les statistiques de souscription
|
||||
statistiques.setTauxRenouvellement(0.0f); // TODO: Calculer depuis les statistiques de renouvellement
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du calcul des statistiques: " + e.getMessage());
|
||||
statistiques.setTotalEntites(0);
|
||||
statistiques.setEntitesActives(0);
|
||||
statistiques.setTotalMembres(0);
|
||||
statistiques.setMoyenneMembresParEntite(0);
|
||||
}
|
||||
calculerStatistiquesSouscriptions();
|
||||
}
|
||||
|
||||
private void initializeEntites() {
|
||||
toutesLesEntites = new ArrayList<>();
|
||||
try {
|
||||
List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
|
||||
for (AssociationDTO dto : associations) {
|
||||
Entite entite = convertToEntite(dto);
|
||||
toutesLesEntites.add(entite);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des entités: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Entite convertToEntite(AssociationDTO dto) {
|
||||
Entite entite = new Entite();
|
||||
entite.setId(dto.getId());
|
||||
entite.setNom(dto.getNom());
|
||||
entite.setCodeEntite(dto.getNumeroRegistre());
|
||||
entite.setType(dto.getTypeAssociation());
|
||||
entite.setRegion(dto.getRegion());
|
||||
entite.setStatut(dto.getStatut());
|
||||
entite.setNombreMembres(dto.getNombreMembres() != null ? dto.getNombreMembres() : 0);
|
||||
entite.setMembresUtilises(dto.getNombreMembres() != null ? dto.getNombreMembres() : 0);
|
||||
entite.setAdresse(dto.getAdresse());
|
||||
entite.setTelephone(dto.getTelephone());
|
||||
entite.setEmail(dto.getEmail());
|
||||
entite.setDescription(dto.getDescription());
|
||||
entite.setDerniereActivite(dto.getDateDerniereActivite());
|
||||
|
||||
// TODO: Récupérer les informations de souscription depuis un service dédié
|
||||
// Pour l'instant, initialiser avec des valeurs par défaut
|
||||
entite.setForfaitSouscrit("Non défini");
|
||||
entite.setMembresQuota(0);
|
||||
entite.setMontantMensuel("0 FCFA");
|
||||
entite.setDateExpirationSouscription(null);
|
||||
entite.setStatutSouscription("NON_DEFINI");
|
||||
|
||||
return entite;
|
||||
}
|
||||
|
||||
private void initializeNouvelleEntite() {
|
||||
nouvelleEntite = new Entite();
|
||||
}
|
||||
|
||||
private void appliquerFiltres() {
|
||||
entitesFiltrees = toutesLesEntites.stream()
|
||||
.filter(this::appliquerFiltre)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean appliquerFiltre(Entite entite) {
|
||||
// Filtre par nom
|
||||
if (filtres.getNom() != null && !filtres.getNom().trim().isEmpty()) {
|
||||
if (!entite.getNom().toLowerCase().contains(filtres.getNom().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre par type
|
||||
if (filtres.getType() != null && !filtres.getType().trim().isEmpty()) {
|
||||
if (!entite.getType().equals(filtres.getType())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre par statut
|
||||
if (filtres.getStatut() != null && !filtres.getStatut().trim().isEmpty()) {
|
||||
if (!entite.getStatut().equals(filtres.getStatut())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre par région
|
||||
if (filtres.getRegion() != null && !filtres.getRegion().trim().isEmpty()) {
|
||||
if (!entite.getRegion().equals(filtres.getRegion())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre par forfait
|
||||
if (filtres.getForfait() != null && !filtres.getForfait().trim().isEmpty()) {
|
||||
if (!entite.getForfaitSouscrit().equals(filtres.getForfait())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre par alerte quota
|
||||
if (filtres.getAlerteQuota() != null && !filtres.getAlerteQuota().trim().isEmpty()) {
|
||||
if ("OUI".equals(filtres.getAlerteQuota()) && !entite.isQuotaProche()) {
|
||||
return false;
|
||||
}
|
||||
if ("NON".equals(filtres.getAlerteQuota()) && entite.isQuotaProche()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre par alerte expiration
|
||||
if (filtres.getAlerteExpiration() != null && !filtres.getAlerteExpiration().trim().isEmpty()) {
|
||||
if ("OUI".equals(filtres.getAlerteExpiration()) && !entite.isExpirationProche()) {
|
||||
return false;
|
||||
}
|
||||
if ("NON".equals(filtres.getAlerteExpiration()) && entite.isExpirationProche()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre par statut souscription
|
||||
if (filtres.getStatutSouscription() != null && !filtres.getStatutSouscription().trim().isEmpty()) {
|
||||
if (!entite.getStatutSouscription().equals(filtres.getStatutSouscription())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Actions
|
||||
public void rechercher() {
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void reinitialiserFiltres() {
|
||||
filtres = new Filtres();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public String voirEntite(Entite entite) {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_ENTITE_DETAILS + "?id=" + entite.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
public void creerEntite() {
|
||||
nouvelleEntite.setId(UUID.randomUUID());
|
||||
nouvelleEntite.setCodeEntite("ENT" + String.format("%03d", toutesLesEntites.size() + 1));
|
||||
nouvelleEntite.setStatut("ACTIVE");
|
||||
nouvelleEntite.setNombreMembres(0);
|
||||
nouvelleEntite.setDerniereActivite(LocalDateTime.now());
|
||||
|
||||
toutesLesEntites.add(nouvelleEntite);
|
||||
appliquerFiltres();
|
||||
|
||||
LOGGER.info("Nouvelle entité créée: " + nouvelleEntite.getNom());
|
||||
|
||||
initializeNouvelleEntite();
|
||||
}
|
||||
|
||||
public String gererMembres() {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_ADMIN_MEMBRES_GESTION + "?entiteId=" + entiteSelectionne.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
public String configurerEntite() {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_ENTITE_CONFIGURATION + "?id=" + entiteSelectionne.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
public String voirRapports() {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_ENTITE_RAPPORTS + "?id=" + entiteSelectionne.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
public void suspendreEntite() {
|
||||
entiteSelectionne.setStatut("SUSPENDUE");
|
||||
LOGGER.info("Entité suspendue: " + entiteSelectionne.getNom());
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void reactiverEntite() {
|
||||
entiteSelectionne.setStatut("ACTIVE");
|
||||
LOGGER.info("Entité réactivée: " + entiteSelectionne.getNom());
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void supprimerEntite() {
|
||||
toutesLesEntites.remove(entiteSelectionne);
|
||||
LOGGER.info("Entité supprimée: " + entiteSelectionne.getNom());
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void exporterEntites() {
|
||||
LOGGER.info("Export de " + entitesFiltrees.size() + " entités");
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public List<Entite> getToutesLesEntites() { return toutesLesEntites; }
|
||||
public void setToutesLesEntites(List<Entite> toutesLesEntites) { this.toutesLesEntites = toutesLesEntites; }
|
||||
|
||||
public List<Entite> getEntitesFiltrees() { return entitesFiltrees; }
|
||||
public void setEntitesFiltrees(List<Entite> entitesFiltrees) { this.entitesFiltrees = entitesFiltrees; }
|
||||
|
||||
public List<Entite> getEntitesSelectionnees() { return entitesSelectionnees; }
|
||||
public void setEntitesSelectionnees(List<Entite> entitesSelectionnees) { this.entitesSelectionnees = entitesSelectionnees; }
|
||||
|
||||
public Entite getEntiteSelectionne() { return entiteSelectionne; }
|
||||
public void setEntiteSelectionne(Entite entiteSelectionne) { this.entiteSelectionne = entiteSelectionne; }
|
||||
|
||||
public Entite getNouvelleEntite() { return nouvelleEntite; }
|
||||
public void setNouvelleEntite(Entite nouvelleEntite) { this.nouvelleEntite = nouvelleEntite; }
|
||||
|
||||
public Filtres getFiltres() { return filtres; }
|
||||
public void setFiltres(Filtres filtres) { this.filtres = filtres; }
|
||||
|
||||
public Statistiques getStatistiques() { return statistiques; }
|
||||
public void setStatistiques(Statistiques statistiques) { this.statistiques = statistiques; }
|
||||
|
||||
// Méthodes utilitaires pour les souscriptions
|
||||
private void calculerStatistiquesSouscriptions() {
|
||||
if (toutesLesEntites == null || statistiques == null) {
|
||||
return; // Sécurité si appelé avant initialisation complète
|
||||
}
|
||||
|
||||
int expirantes = 0;
|
||||
int quotaAtteint = 0;
|
||||
|
||||
for (Entite entite : toutesLesEntites) {
|
||||
if (entite.isExpirationProche()) {
|
||||
expirantes++;
|
||||
}
|
||||
if (entite.isQuotaAtteint()) {
|
||||
quotaAtteint++;
|
||||
}
|
||||
}
|
||||
|
||||
statistiques.setSouscriptionsExpirantes(expirantes);
|
||||
statistiques.setEntitesQuotaAtteint(quotaAtteint);
|
||||
}
|
||||
|
||||
public void renouvelerSouscription() {
|
||||
if (entiteSelectionne != null) {
|
||||
entiteSelectionne.setDateExpirationSouscription(LocalDate.now().plusMonths(12));
|
||||
entiteSelectionne.setStatutSouscription("ACTIVE");
|
||||
LOGGER.info("Souscription renouvelée pour: " + entiteSelectionne.getNom());
|
||||
appliquerFiltres();
|
||||
}
|
||||
}
|
||||
|
||||
public void upgraderForfait() {
|
||||
if (entiteSelectionne != null) {
|
||||
String forfaitActuel = entiteSelectionne.getForfaitSouscrit();
|
||||
switch (forfaitActuel) {
|
||||
case "Starter":
|
||||
entiteSelectionne.setForfaitSouscrit("Standard");
|
||||
entiteSelectionne.setMembresQuota(200);
|
||||
entiteSelectionne.setMontantMensuel("3 000 FCFA");
|
||||
break;
|
||||
case "Standard":
|
||||
entiteSelectionne.setForfaitSouscrit("Premium");
|
||||
entiteSelectionne.setMembresQuota(500);
|
||||
entiteSelectionne.setMontantMensuel("4 000 FCFA");
|
||||
break;
|
||||
case "Premium":
|
||||
entiteSelectionne.setForfaitSouscrit("Cristal");
|
||||
entiteSelectionne.setMembresQuota(2000);
|
||||
entiteSelectionne.setMontantMensuel("5 000 FCFA");
|
||||
break;
|
||||
}
|
||||
LOGGER.info("Forfait upgradé pour: " + entiteSelectionne.getNom());
|
||||
appliquerFiltres();
|
||||
}
|
||||
}
|
||||
|
||||
public void gererQuotas() {
|
||||
LOGGER.info("Gestion des quotas pour toutes les entités");
|
||||
}
|
||||
|
||||
public void envoyerRelancesSouscriptions() {
|
||||
int compteur = 0;
|
||||
for (Entite entite : toutesLesEntites) {
|
||||
if (entite.isExpirationProche()) {
|
||||
LOGGER.info("Relance envoyée à: " + entite.getNom());
|
||||
compteur++;
|
||||
}
|
||||
}
|
||||
LOGGER.info(compteur + " relances de souscription envoyées");
|
||||
}
|
||||
|
||||
// Actions groupées
|
||||
public void renouvelerSouscriptionsGroupees() {
|
||||
int compteur = 0;
|
||||
for (Entite entite : entitesSelectionnees) {
|
||||
entite.setDateExpirationSouscription(LocalDate.now().plusMonths(12));
|
||||
entite.setStatutSouscription("ACTIVE");
|
||||
compteur++;
|
||||
}
|
||||
LOGGER.info(compteur + " souscriptions renouvelées en masse");
|
||||
entitesSelectionnees.clear();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void suspendreEntitesGroupees() {
|
||||
int compteur = 0;
|
||||
for (Entite entite : entitesSelectionnees) {
|
||||
entite.setStatut("SUSPENDUE");
|
||||
compteur++;
|
||||
}
|
||||
LOGGER.info(compteur + " entités suspendues en masse");
|
||||
entitesSelectionnees.clear();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void reactiverEntitesGroupees() {
|
||||
int compteur = 0;
|
||||
for (Entite entite : entitesSelectionnees) {
|
||||
entite.setStatut("ACTIVE");
|
||||
compteur++;
|
||||
}
|
||||
LOGGER.info(compteur + " entités réactivées en masse");
|
||||
entitesSelectionnees.clear();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void proposerUpgradeGroupees() {
|
||||
int compteur = 0;
|
||||
for (Entite entite : entitesSelectionnees) {
|
||||
if (entite.isQuotaProche()) {
|
||||
// Simulation d'envoi de proposition d'upgrade
|
||||
LOGGER.info("Proposition d'upgrade envoyée à: " + entite.getNom());
|
||||
compteur++;
|
||||
}
|
||||
}
|
||||
LOGGER.info(compteur + " propositions d'upgrade envoyées");
|
||||
}
|
||||
|
||||
// Classes internes
|
||||
public static class Entite {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
private String codeEntite;
|
||||
private String type;
|
||||
private String region;
|
||||
private String statut;
|
||||
private int nombreMembres;
|
||||
private String adresse;
|
||||
private String telephone;
|
||||
private String email;
|
||||
private String description;
|
||||
private LocalDateTime derniereActivite;
|
||||
private Administrateur administrateur;
|
||||
|
||||
// Informations de souscription
|
||||
private String forfaitSouscrit = "Standard";
|
||||
private int membresQuota = 200;
|
||||
private int membresUtilises;
|
||||
private LocalDate dateExpirationSouscription;
|
||||
private String statutSouscription = "ACTIVE";
|
||||
private String montantMensuel = "3 000 FCFA";
|
||||
|
||||
// Getters et setters
|
||||
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 getCodeEntite() { return codeEntite; }
|
||||
public void setCodeEntite(String codeEntite) { this.codeEntite = codeEntite; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getRegion() { return region; }
|
||||
public void setRegion(String region) { this.region = region; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public int getNombreMembres() { return nombreMembres; }
|
||||
public void setNombreMembres(int nombreMembres) { this.nombreMembres = nombreMembres; }
|
||||
|
||||
public String getAdresse() { return adresse; }
|
||||
public void setAdresse(String adresse) { this.adresse = adresse; }
|
||||
|
||||
public String getTelephone() { return telephone; }
|
||||
public void setTelephone(String telephone) { this.telephone = telephone; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public LocalDateTime getDerniereActivite() { return derniereActivite; }
|
||||
public void setDerniereActivite(LocalDateTime derniereActivite) { this.derniereActivite = derniereActivite; }
|
||||
|
||||
public Administrateur getAdministrateur() { return administrateur; }
|
||||
public void setAdministrateur(Administrateur administrateur) { this.administrateur = administrateur; }
|
||||
|
||||
// Propriétés dérivées
|
||||
public String getTypeLibelle() {
|
||||
return switch (type) {
|
||||
case "ASSOCIATION" -> "Association";
|
||||
case "CLUB" -> "Club";
|
||||
case "GROUPE" -> "Groupe";
|
||||
case "GROUPE_JEUNES" -> "Groupe Jeunes";
|
||||
case "BRANCHE" -> "Branche";
|
||||
default -> type;
|
||||
};
|
||||
}
|
||||
|
||||
public String getTypeSeverity() {
|
||||
return switch (type) {
|
||||
case "ASSOCIATION" -> "info";
|
||||
case "CLUB" -> "success";
|
||||
case "GROUPE" -> "warning";
|
||||
case "GROUPE_JEUNES" -> "primary";
|
||||
case "BRANCHE" -> "secondary";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getTypeIcon() {
|
||||
return switch (type) {
|
||||
case "ASSOCIATION" -> "pi-users";
|
||||
case "CLUB" -> "pi-home";
|
||||
case "GROUPE" -> "pi-sitemap";
|
||||
case "GROUPE_JEUNES" -> "pi-star";
|
||||
case "BRANCHE" -> "pi-share-alt";
|
||||
default -> "pi-building";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutSeverity() {
|
||||
return switch (statut) {
|
||||
case "ACTIVE" -> "success";
|
||||
case "INACTIVE" -> "warning";
|
||||
case "SUSPENDUE" -> "danger";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutIcon() {
|
||||
return switch (statut) {
|
||||
case "ACTIVE" -> "pi-check";
|
||||
case "INACTIVE" -> "pi-pause";
|
||||
case "SUSPENDUE" -> "pi-ban";
|
||||
default -> "pi-circle";
|
||||
};
|
||||
}
|
||||
|
||||
public String getDerniereActiviteFormatee() {
|
||||
if (derniereActivite == null) return "N/A";
|
||||
return derniereActivite.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
|
||||
}
|
||||
|
||||
public String getDerniereActiviteRelative() {
|
||||
if (derniereActivite == null) return "";
|
||||
long jours = ChronoUnit.DAYS.between(derniereActivite.toLocalDate(), LocalDate.now());
|
||||
if (jours == 0) return "Aujourd'hui";
|
||||
if (jours == 1) return "Hier";
|
||||
if (jours < 7) return "Il y a " + jours + " jours";
|
||||
if (jours < 30) return "Il y a " + (jours / 7) + " semaine" + (jours / 7 > 1 ? "s" : "");
|
||||
return "Il y a " + (jours / 30) + " mois";
|
||||
}
|
||||
|
||||
// Getters et setters pour les informations de souscription
|
||||
public String getForfaitSouscrit() { return forfaitSouscrit; }
|
||||
public void setForfaitSouscrit(String forfaitSouscrit) { this.forfaitSouscrit = forfaitSouscrit; }
|
||||
|
||||
public int getMembresQuota() { return membresQuota; }
|
||||
public void setMembresQuota(int membresQuota) { this.membresQuota = membresQuota; }
|
||||
|
||||
public int getMembresUtilises() { return membresUtilises; }
|
||||
public void setMembresUtilises(int membresUtilises) { this.membresUtilises = membresUtilises; }
|
||||
|
||||
public LocalDate getDateExpirationSouscription() { return dateExpirationSouscription; }
|
||||
public void setDateExpirationSouscription(LocalDate dateExpirationSouscription) { this.dateExpirationSouscription = dateExpirationSouscription; }
|
||||
|
||||
public String getStatutSouscription() { return statutSouscription; }
|
||||
public void setStatutSouscription(String statutSouscription) { this.statutSouscription = statutSouscription; }
|
||||
|
||||
public String getMontantMensuel() { return montantMensuel; }
|
||||
public void setMontantMensuel(String montantMensuel) { this.montantMensuel = montantMensuel; }
|
||||
|
||||
// Méthodes utilitaires pour les souscriptions
|
||||
public boolean isQuotaProche() {
|
||||
return getMembresUtilises() >= (getMembresQuota() * 0.85);
|
||||
}
|
||||
|
||||
public boolean isQuotaAtteint() {
|
||||
return getMembresUtilises() >= getMembresQuota();
|
||||
}
|
||||
|
||||
public boolean isExpirationProche() {
|
||||
if (dateExpirationSouscription == null) return false;
|
||||
return ChronoUnit.DAYS.between(LocalDate.now(), dateExpirationSouscription) <= 30;
|
||||
}
|
||||
|
||||
public int getPourcentageUtilisationQuota() {
|
||||
if (membresQuota == 0) return 0;
|
||||
return (membresUtilises * 100) / membresQuota;
|
||||
}
|
||||
|
||||
public String getForfaitCouleur() {
|
||||
return switch (forfaitSouscrit) {
|
||||
case "Starter" -> "primary";
|
||||
case "Standard" -> "success";
|
||||
case "Premium" -> "warning";
|
||||
case "Cristal" -> "info";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getForfaitIcone() {
|
||||
return switch (forfaitSouscrit) {
|
||||
case "Starter" -> "pi-star";
|
||||
case "Standard" -> "pi-users";
|
||||
case "Premium" -> "pi-crown";
|
||||
case "Cristal" -> "pi-diamond";
|
||||
default -> "pi-circle";
|
||||
};
|
||||
}
|
||||
|
||||
public long getJoursAvantExpiration() {
|
||||
if (dateExpirationSouscription == null) return 0;
|
||||
return ChronoUnit.DAYS.between(LocalDate.now(), dateExpirationSouscription);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Administrateur {
|
||||
private String nomComplet;
|
||||
private String email;
|
||||
|
||||
// Getters et setters
|
||||
public String getNomComplet() { return nomComplet; }
|
||||
public void setNomComplet(String nomComplet) { this.nomComplet = nomComplet; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
}
|
||||
|
||||
public static class Filtres {
|
||||
private String nom;
|
||||
private String type;
|
||||
private String statut;
|
||||
private String region;
|
||||
private String forfait;
|
||||
private String alerteQuota;
|
||||
private String alerteExpiration;
|
||||
private String statutSouscription;
|
||||
|
||||
// Getters et setters
|
||||
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 String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getRegion() { return region; }
|
||||
public void setRegion(String region) { this.region = region; }
|
||||
|
||||
public String getForfait() { return forfait; }
|
||||
public void setForfait(String forfait) { this.forfait = forfait; }
|
||||
|
||||
public String getAlerteQuota() { return alerteQuota; }
|
||||
public void setAlerteQuota(String alerteQuota) { this.alerteQuota = alerteQuota; }
|
||||
|
||||
public String getAlerteExpiration() { return alerteExpiration; }
|
||||
public void setAlerteExpiration(String alerteExpiration) { this.alerteExpiration = alerteExpiration; }
|
||||
|
||||
public String getStatutSouscription() { return statutSouscription; }
|
||||
public void setStatutSouscription(String statutSouscription) { this.statutSouscription = statutSouscription; }
|
||||
}
|
||||
|
||||
public static class Statistiques {
|
||||
private int totalEntites;
|
||||
private int entitesActives;
|
||||
private int totalMembres;
|
||||
private String revenus;
|
||||
private int souscriptionsExpirantes;
|
||||
private int entitesQuotaAtteint;
|
||||
private String formulairePopulaire;
|
||||
private float tauxRenouvellement;
|
||||
private int moyenneMembresParEntite;
|
||||
|
||||
// Getters et setters
|
||||
public int getTotalEntites() { return totalEntites; }
|
||||
public void setTotalEntites(int totalEntites) { this.totalEntites = totalEntites; }
|
||||
|
||||
public int getEntitesActives() { return entitesActives; }
|
||||
public void setEntitesActives(int entitesActives) { this.entitesActives = entitesActives; }
|
||||
|
||||
public int getTotalMembres() { return totalMembres; }
|
||||
public void setTotalMembres(int totalMembres) { this.totalMembres = totalMembres; }
|
||||
|
||||
public String getRevenus() { return revenus; }
|
||||
public void setRevenus(String revenus) { this.revenus = revenus; }
|
||||
|
||||
public int getSouscriptionsExpirantes() { return souscriptionsExpirantes; }
|
||||
public void setSouscriptionsExpirantes(int souscriptionsExpirantes) { this.souscriptionsExpirantes = souscriptionsExpirantes; }
|
||||
|
||||
public int getEntitesQuotaAtteint() { return entitesQuotaAtteint; }
|
||||
public void setEntitesQuotaAtteint(int entitesQuotaAtteint) { this.entitesQuotaAtteint = entitesQuotaAtteint; }
|
||||
|
||||
public String getFormulairePopulaire() { return formulairePopulaire; }
|
||||
public void setFormulairePopulaire(String formulairePopulaire) { this.formulairePopulaire = formulairePopulaire; }
|
||||
|
||||
public float getTauxRenouvellement() { return tauxRenouvellement; }
|
||||
public void setTauxRenouvellement(float tauxRenouvellement) { this.tauxRenouvellement = tauxRenouvellement; }
|
||||
|
||||
public int getMoyenneMembresParEntite() { return moyenneMembresParEntite; }
|
||||
public void setMoyenneMembresParEntite(int moyenneMembresParEntite) { this.moyenneMembresParEntite = moyenneMembresParEntite; }
|
||||
|
||||
public String getTauxRenouvellementFormat() {
|
||||
return String.format("%.1f%%", tauxRenouvellement);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,879 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.dto.EvenementDTO;
|
||||
import dev.lions.unionflow.client.service.EvenementService;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.faces.application.FacesMessage;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import org.primefaces.event.SelectEvent;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Bean JSF pour la gestion des événements
|
||||
* Refactorisé pour utiliser directement EvenementDTO et se connecter au backend
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
*/
|
||||
@Named("evenementsBean")
|
||||
@SessionScoped
|
||||
public class EvenementsBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(EvenementsBean.class.getName());
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private EvenementService evenementService;
|
||||
|
||||
@Inject
|
||||
private UserSession userSession;
|
||||
|
||||
// Date sélectionnée dans le calendrier
|
||||
private LocalDate dateSelectionnee;
|
||||
|
||||
// Données principales - Utilisation directe de EvenementDTO
|
||||
private List<EvenementDTO> tousLesEvenements;
|
||||
private List<EvenementDTO> evenementsFiltres;
|
||||
private List<EvenementDTO> evenementsSelectionnes;
|
||||
private List<EvenementDTO> evenementsProchains;
|
||||
private EvenementDTO evenementSelectionne;
|
||||
|
||||
// Formulaire nouveau événement
|
||||
private EvenementDTO nouvelEvenement;
|
||||
|
||||
// Filtres
|
||||
private FiltresEvenement filtres;
|
||||
|
||||
// Statistiques
|
||||
private StatistiquesEvenements statistiques;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
LOGGER.info("Initialisation de EvenementsBean");
|
||||
initializeFiltres();
|
||||
initializeNouvelEvenement();
|
||||
chargerEvenements();
|
||||
chargerEvenementsProchains();
|
||||
chargerStatistiques();
|
||||
}
|
||||
|
||||
private void initializeFiltres() {
|
||||
filtres = new FiltresEvenement();
|
||||
evenementsSelectionnes = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void initializeNouvelEvenement() {
|
||||
nouvelEvenement = new EvenementDTO();
|
||||
nouvelEvenement.setPriorite("NORMALE");
|
||||
nouvelEvenement.setStatut("PLANIFIE");
|
||||
nouvelEvenement.setDateDebut(LocalDate.now().plusWeeks(1));
|
||||
nouvelEvenement.setHeureDebut(LocalTime.of(9, 0));
|
||||
nouvelEvenement.setHeureFin(LocalTime.of(17, 0));
|
||||
nouvelEvenement.setCodeDevise("XOF");
|
||||
nouvelEvenement.setEvenementPublic(true);
|
||||
nouvelEvenement.setInscriptionObligatoire(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Méthode publique pour réinitialiser le formulaire
|
||||
*/
|
||||
public void reinitialiserFormulaire() {
|
||||
initializeNouvelEvenement();
|
||||
}
|
||||
|
||||
/**
|
||||
* Charge tous les événements depuis le backend
|
||||
*/
|
||||
public void chargerEvenements() {
|
||||
try {
|
||||
LOGGER.info("Chargement des événements depuis le backend");
|
||||
Map<String, Object> response = evenementService.listerTous(0, 1000, "dateDebut", "asc");
|
||||
|
||||
tousLesEvenements = new ArrayList<>();
|
||||
|
||||
// Le backend peut retourner soit une liste de DTOs, soit une Map avec "data"
|
||||
if (response.containsKey("data")) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> data = (List<Object>) response.get("data");
|
||||
|
||||
if (data != null) {
|
||||
for (Object item : data) {
|
||||
if (item instanceof EvenementDTO) {
|
||||
tousLesEvenements.add((EvenementDTO) item);
|
||||
} else if (item instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
EvenementDTO dto = convertMapToDTO((Map<String, Object>) item);
|
||||
tousLesEvenements.add(dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Si la réponse est directement une liste
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> data = (List<Object>) response.get("evenements");
|
||||
if (data != null) {
|
||||
for (Object item : data) {
|
||||
if (item instanceof EvenementDTO) {
|
||||
tousLesEvenements.add((EvenementDTO) item);
|
||||
} else if (item instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
EvenementDTO dto = convertMapToDTO((Map<String, Object>) item);
|
||||
tousLesEvenements.add(dto);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
appliquerFiltres();
|
||||
LOGGER.info("Événements chargés: " + tousLesEvenements.size());
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des événements: " + e.getMessage());
|
||||
LOGGER.log(java.util.logging.Level.SEVERE, "Détails de l'erreur de chargement des événements", e);
|
||||
tousLesEvenements = new ArrayList<>();
|
||||
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Erreur lors du chargement des événements: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Charge les événements à venir
|
||||
*/
|
||||
public void chargerEvenementsProchains() {
|
||||
try {
|
||||
LOGGER.info("Chargement des événements à venir");
|
||||
Map<String, Object> response = evenementService.listerAVenir(0, 6);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Map<String, Object>> data = (List<Map<String, Object>>) response.get("data");
|
||||
|
||||
if (data != null) {
|
||||
evenementsProchains = data.stream()
|
||||
.map(this::convertMapToDTO)
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
evenementsProchains = new ArrayList<>();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des événements à venir: " + e.getMessage());
|
||||
evenementsProchains = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Charge les statistiques depuis le backend
|
||||
*/
|
||||
public void chargerStatistiques() {
|
||||
try {
|
||||
LOGGER.info("Chargement des statistiques");
|
||||
Map<String, Object> countResponse = evenementService.compter();
|
||||
|
||||
statistiques = new StatistiquesEvenements();
|
||||
|
||||
// Calculer les statistiques depuis les événements chargés
|
||||
if (tousLesEvenements != null && !tousLesEvenements.isEmpty()) {
|
||||
statistiques.setTotalEvenements(tousLesEvenements.size());
|
||||
|
||||
long actifs = tousLesEvenements.stream()
|
||||
.filter(e -> "PLANIFIE".equals(e.getStatut()) ||
|
||||
"CONFIRME".equals(e.getStatut()) ||
|
||||
"EN_COURS".equals(e.getStatut()))
|
||||
.count();
|
||||
statistiques.setEvenementsActifs((int) actifs);
|
||||
|
||||
int totalParticipants = tousLesEvenements.stream()
|
||||
.mapToInt(e -> e.getParticipantsInscrits() != null ? e.getParticipantsInscrits() : 0)
|
||||
.sum();
|
||||
statistiques.setParticipantsTotal(totalParticipants);
|
||||
|
||||
BigDecimal totalBudget = tousLesEvenements.stream()
|
||||
.map(e -> e.getBudget() != null ? e.getBudget() : BigDecimal.ZERO)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
statistiques.setBudgetTotal(String.format("%,.0f FCFA", totalBudget.doubleValue()));
|
||||
|
||||
double moyenne = (double) totalParticipants / tousLesEvenements.size();
|
||||
statistiques.setMoyenneParticipants((int) moyenne);
|
||||
|
||||
// Calculer les événements créés ce mois depuis les données backend
|
||||
LocalDate debutMois = LocalDate.now().withDayOfMonth(1);
|
||||
long evenementsCeMois = tousLesEvenements.stream()
|
||||
.filter(e -> e.getDateCreation() != null &&
|
||||
!e.getDateCreation().isBefore(debutMois.atStartOfDay()))
|
||||
.count();
|
||||
statistiques.setEvenementsCeMois((int) evenementsCeMois);
|
||||
|
||||
// Calculer le taux de participation moyen depuis les données backend
|
||||
double tauxMoyen = tousLesEvenements.stream()
|
||||
.filter(e -> e.getCapaciteMax() != null && e.getCapaciteMax() > 0)
|
||||
.mapToDouble(e -> {
|
||||
int inscrits = e.getParticipantsInscrits() != null ? e.getParticipantsInscrits() : 0;
|
||||
return (double) inscrits / e.getCapaciteMax() * 100.0;
|
||||
})
|
||||
.average()
|
||||
.orElse(0.0);
|
||||
statistiques.setTauxParticipationMoyen((int) tauxMoyen);
|
||||
} else {
|
||||
statistiques.setTotalEvenements(0);
|
||||
statistiques.setEvenementsActifs(0);
|
||||
statistiques.setParticipantsTotal(0);
|
||||
statistiques.setBudgetTotal("0 FCFA");
|
||||
statistiques.setMoyenneParticipants(0);
|
||||
statistiques.setEvenementsCeMois(0);
|
||||
statistiques.setTauxParticipationMoyen(0);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des statistiques: " + e.getMessage());
|
||||
statistiques = new StatistiquesEvenements();
|
||||
statistiques.setTotalEvenements(0);
|
||||
statistiques.setEvenementsActifs(0);
|
||||
statistiques.setParticipantsTotal(0);
|
||||
statistiques.setBudgetTotal("0 FCFA");
|
||||
statistiques.setMoyenneParticipants(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convertit une Map en EvenementDTO
|
||||
*/
|
||||
private EvenementDTO convertMapToDTO(Map<String, Object> map) {
|
||||
EvenementDTO dto = new EvenementDTO();
|
||||
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
if (map.get("titre") != null) dto.setTitre(map.get("titre").toString());
|
||||
if (map.get("description") != null) dto.setDescription(map.get("description").toString());
|
||||
|
||||
// Type d'événement - peut être un enum ou une String
|
||||
// Gérer à la fois "typeEvenement" et "type" pour compatibilité
|
||||
Object typeObj = map.get("typeEvenement");
|
||||
if (typeObj == null) {
|
||||
typeObj = map.get("type"); // Fallback sur "type" si "typeEvenement" n'existe pas
|
||||
}
|
||||
if (typeObj != null) {
|
||||
dto.setTypeEvenement(typeObj instanceof Enum ? typeObj.toString() : typeObj.toString());
|
||||
}
|
||||
|
||||
// Statut - peut être un enum ou une String
|
||||
if (map.get("statut") != null) {
|
||||
Object statut = map.get("statut");
|
||||
dto.setStatut(statut instanceof Enum ? statut.toString() : statut.toString());
|
||||
}
|
||||
|
||||
// Priorité - peut être un enum ou une String
|
||||
if (map.get("priorite") != null) {
|
||||
Object priorite = map.get("priorite");
|
||||
dto.setPriorite(priorite instanceof Enum ? priorite.toString() : priorite.toString());
|
||||
}
|
||||
|
||||
if (map.get("lieu") != null) dto.setLieu(map.get("lieu").toString());
|
||||
if (map.get("adresse") != null) dto.setAdresse(map.get("adresse").toString());
|
||||
if (map.get("ville") != null) dto.setVille(map.get("ville").toString());
|
||||
if (map.get("region") != null) dto.setRegion(map.get("region").toString());
|
||||
if (map.get("organisateur") != null) dto.setOrganisateur(map.get("organisateur").toString());
|
||||
if (map.get("emailOrganisateur") != null) dto.setEmailOrganisateur(map.get("emailOrganisateur").toString());
|
||||
if (map.get("telephoneOrganisateur") != null) dto.setTelephoneOrganisateur(map.get("telephoneOrganisateur").toString());
|
||||
|
||||
// Conversion des nombres
|
||||
if (map.get("capaciteMax") != null) {
|
||||
Object cap = map.get("capaciteMax");
|
||||
if (cap instanceof Number) {
|
||||
dto.setCapaciteMax(((Number) cap).intValue());
|
||||
} else {
|
||||
dto.setCapaciteMax(Integer.parseInt(cap.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (map.get("participantsInscrits") != null) {
|
||||
Object part = map.get("participantsInscrits");
|
||||
if (part instanceof Number) {
|
||||
dto.setParticipantsInscrits(((Number) part).intValue());
|
||||
} else {
|
||||
dto.setParticipantsInscrits(Integer.parseInt(part.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (map.get("participantsPresents") != null) {
|
||||
Object part = map.get("participantsPresents");
|
||||
if (part instanceof Number) {
|
||||
dto.setParticipantsPresents(((Number) part).intValue());
|
||||
} else {
|
||||
dto.setParticipantsPresents(Integer.parseInt(part.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
// Conversion des BigDecimal
|
||||
if (map.get("budget") != null) {
|
||||
Object budget = map.get("budget");
|
||||
if (budget instanceof BigDecimal) {
|
||||
dto.setBudget((BigDecimal) budget);
|
||||
} else if (budget instanceof Number) {
|
||||
dto.setBudget(BigDecimal.valueOf(((Number) budget).doubleValue()));
|
||||
} else {
|
||||
dto.setBudget(new BigDecimal(budget.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (map.get("coutReel") != null) {
|
||||
Object cout = map.get("coutReel");
|
||||
if (cout instanceof BigDecimal) {
|
||||
dto.setCoutReel((BigDecimal) cout);
|
||||
} else if (cout instanceof Number) {
|
||||
dto.setCoutReel(BigDecimal.valueOf(((Number) cout).doubleValue()));
|
||||
} else {
|
||||
dto.setCoutReel(new BigDecimal(cout.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (map.get("codeDevise") != null) dto.setCodeDevise(map.get("codeDevise").toString());
|
||||
|
||||
// Conversion des dates
|
||||
if (map.get("dateDebut") != null) {
|
||||
Object date = map.get("dateDebut");
|
||||
if (date instanceof LocalDate) {
|
||||
dto.setDateDebut((LocalDate) date);
|
||||
} else if (date instanceof String) {
|
||||
dto.setDateDebut(LocalDate.parse(date.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (map.get("dateFin") != null) {
|
||||
Object date = map.get("dateFin");
|
||||
if (date instanceof LocalDate) {
|
||||
dto.setDateFin((LocalDate) date);
|
||||
} else if (date instanceof String) {
|
||||
dto.setDateFin(LocalDate.parse(date.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
// Conversion des heures
|
||||
if (map.get("heureDebut") != null) {
|
||||
Object heure = map.get("heureDebut");
|
||||
if (heure instanceof LocalTime) {
|
||||
dto.setHeureDebut((LocalTime) heure);
|
||||
} else if (heure instanceof String) {
|
||||
dto.setHeureDebut(LocalTime.parse(heure.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (map.get("heureFin") != null) {
|
||||
Object heure = map.get("heureFin");
|
||||
if (heure instanceof LocalTime) {
|
||||
dto.setHeureFin((LocalTime) heure);
|
||||
} else if (heure instanceof String) {
|
||||
dto.setHeureFin(LocalTime.parse(heure.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
// Association
|
||||
if (map.get("associationId") != null) {
|
||||
Object assocId = map.get("associationId");
|
||||
if (assocId instanceof UUID) {
|
||||
dto.setAssociationId((UUID) assocId);
|
||||
} else {
|
||||
dto.setAssociationId(UUID.fromString(assocId.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
if (map.get("nomAssociation") != null) dto.setNomAssociation(map.get("nomAssociation").toString());
|
||||
|
||||
// Options booléennes
|
||||
if (map.get("inscriptionObligatoire") != null) {
|
||||
Object insc = map.get("inscriptionObligatoire");
|
||||
dto.setInscriptionObligatoire(insc instanceof Boolean ? (Boolean) insc : Boolean.parseBoolean(insc.toString()));
|
||||
}
|
||||
|
||||
if (map.get("evenementPublic") != null) {
|
||||
Object pub = map.get("evenementPublic");
|
||||
dto.setEvenementPublic(pub instanceof Boolean ? (Boolean) pub : Boolean.parseBoolean(pub.toString()));
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Erreur lors de la conversion Map vers DTO: " + e.getMessage());
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applique les filtres sur les événements
|
||||
*/
|
||||
public void appliquerFiltres() {
|
||||
if (tousLesEvenements == null) {
|
||||
evenementsFiltres = new ArrayList<>();
|
||||
return;
|
||||
}
|
||||
|
||||
evenementsFiltres = tousLesEvenements.stream()
|
||||
.filter(this::appliquerFiltre)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean appliquerFiltre(EvenementDTO evenement) {
|
||||
if (filtres == null) return true;
|
||||
|
||||
if (filtres.getTitre() != null && !filtres.getTitre().trim().isEmpty()) {
|
||||
if (evenement.getTitre() == null ||
|
||||
!evenement.getTitre().toLowerCase().contains(filtres.getTitre().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getType() != null && !filtres.getType().trim().isEmpty()) {
|
||||
if (!filtres.getType().equals(evenement.getTypeEvenement())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getStatut() != null && !filtres.getStatut().trim().isEmpty()) {
|
||||
if (!filtres.getStatut().equals(evenement.getStatut())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getOrganisateur() != null && !filtres.getOrganisateur().trim().isEmpty()) {
|
||||
if (evenement.getOrganisateur() == null ||
|
||||
!evenement.getOrganisateur().toLowerCase().contains(filtres.getOrganisateur().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getPriorite() != null && !filtres.getPriorite().trim().isEmpty()) {
|
||||
if (!filtres.getPriorite().equals(evenement.getPriorite())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getDateDebut() != null && evenement.getDateDebut() != null) {
|
||||
if (evenement.getDateDebut().isBefore(filtres.getDateDebut())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getDateFin() != null && evenement.getDateDebut() != null) {
|
||||
if (evenement.getDateDebut().isAfter(filtres.getDateFin())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recherche d'événements
|
||||
*/
|
||||
public void rechercher() {
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
/**
|
||||
* Réinitialise les filtres
|
||||
*/
|
||||
public void reinitialiserFiltres() {
|
||||
filtres = new FiltresEvenement();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un nouvel événement
|
||||
*/
|
||||
public void creerEvenement() {
|
||||
try {
|
||||
LOGGER.info("Création d'un nouvel événement: " + nouvelEvenement.getTitre());
|
||||
|
||||
EvenementDTO evenementCree = evenementService.creer(nouvelEvenement);
|
||||
|
||||
// Recharger les événements
|
||||
chargerEvenements();
|
||||
chargerEvenementsProchains();
|
||||
chargerStatistiques();
|
||||
|
||||
// Réinitialiser le formulaire
|
||||
initializeNouvelEvenement();
|
||||
|
||||
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès",
|
||||
"Événement créé avec succès");
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la création de l'événement: " + e.getMessage());
|
||||
LOGGER.log(java.util.logging.Level.SEVERE, "Détails de l'erreur de création d'événement", e);
|
||||
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Erreur lors de la création de l'événement: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifie un événement existant
|
||||
*/
|
||||
public void modifierEvenement() {
|
||||
try {
|
||||
if (evenementSelectionne == null || evenementSelectionne.getId() == null) {
|
||||
ajouterMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Aucun événement sélectionné");
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.info("Modification de l'événement: " + evenementSelectionne.getId());
|
||||
|
||||
EvenementDTO evenementModifie = evenementService.modifier(
|
||||
evenementSelectionne.getId(), evenementSelectionne);
|
||||
|
||||
// Recharger les événements
|
||||
chargerEvenements();
|
||||
chargerEvenementsProchains();
|
||||
chargerStatistiques();
|
||||
|
||||
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès",
|
||||
"Événement modifié avec succès");
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la modification: " + e.getMessage());
|
||||
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Erreur lors de la modification: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime un événement
|
||||
*/
|
||||
public void supprimerEvenement() {
|
||||
try {
|
||||
if (evenementSelectionne == null || evenementSelectionne.getId() == null) {
|
||||
ajouterMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Aucun événement sélectionné");
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.info("Suppression de l'événement: " + evenementSelectionne.getId());
|
||||
|
||||
evenementService.supprimer(evenementSelectionne.getId());
|
||||
|
||||
// Recharger les événements
|
||||
chargerEvenements();
|
||||
chargerEvenementsProchains();
|
||||
chargerStatistiques();
|
||||
|
||||
evenementSelectionne = null;
|
||||
|
||||
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès",
|
||||
"Événement supprimé avec succès");
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la suppression: " + e.getMessage());
|
||||
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Erreur lors de la suppression: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Annule un événement
|
||||
*/
|
||||
public void annulerEvenement() {
|
||||
try {
|
||||
if (evenementSelectionne == null || evenementSelectionne.getId() == null) {
|
||||
ajouterMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Aucun événement sélectionné");
|
||||
return;
|
||||
}
|
||||
|
||||
evenementSelectionne.setStatut("ANNULE");
|
||||
modifierEvenement();
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'annulation: " + e.getMessage());
|
||||
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Erreur lors de l'annulation: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sélectionne un événement
|
||||
*/
|
||||
public void selectionnerEvenement(EvenementDTO evenement) {
|
||||
this.evenementSelectionne = evenement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Actualise les données
|
||||
*/
|
||||
public void actualiser() {
|
||||
chargerEvenements();
|
||||
chargerEvenementsProchains();
|
||||
chargerStatistiques();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inscrit le membre actuel à un événement
|
||||
*/
|
||||
public void sinscrireEvenement(EvenementDTO evenement) {
|
||||
try {
|
||||
if (evenement == null || evenement.getId() == null) {
|
||||
ajouterMessage(FacesMessage.SEVERITY_WARN, "Attention", "Événement invalide");
|
||||
return;
|
||||
}
|
||||
|
||||
// Vérifier la capacité avec les méthodes existantes de EvenementDTO
|
||||
if (evenement.isComplet()) {
|
||||
ajouterMessage(FacesMessage.SEVERITY_WARN, "Complet",
|
||||
"Cet événement est complet");
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.info("Inscription à l'événement: " + evenement.getId());
|
||||
|
||||
// Créer un participant pour l'utilisateur courant
|
||||
UUID userId = userSession.getCurrentUser() != null ? userSession.getCurrentUser().getId() : null;
|
||||
if (userId == null) {
|
||||
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Vous devez être connecté pour vous inscrire");
|
||||
return;
|
||||
}
|
||||
|
||||
// Appeler le service backend pour l'inscription
|
||||
evenementService.inscrireParticipant(evenement.getId(), userId);
|
||||
|
||||
// Mettre à jour le nombre d'inscrits localement
|
||||
Integer inscrits = evenement.getParticipantsInscrits();
|
||||
evenement.setParticipantsInscrits(inscrits != null ? inscrits + 1 : 1);
|
||||
|
||||
ajouterMessage(FacesMessage.SEVERITY_INFO, "Succès",
|
||||
"Inscription à l'événement enregistrée");
|
||||
|
||||
// Actualiser les données
|
||||
chargerEvenements();
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'inscription: " + e.getMessage());
|
||||
ajouterMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Erreur lors de l'inscription: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handlers pour le calendrier PrimeFaces Schedule
|
||||
*/
|
||||
public void onDateSelect(SelectEvent<Date> event) {
|
||||
if (event != null && event.getObject() != null) {
|
||||
Date date = event.getObject();
|
||||
this.dateSelectionnee = date.toInstant()
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.toLocalDate();
|
||||
|
||||
// Préparer un nouvel événement à cette date
|
||||
this.nouvelEvenement = new EvenementDTO();
|
||||
this.nouvelEvenement.setDateDebut(dateSelectionnee);
|
||||
this.nouvelEvenement.setDateFin(dateSelectionnee);
|
||||
this.nouvelEvenement.setHeureDebut(LocalTime.of(9, 0));
|
||||
this.nouvelEvenement.setHeureFin(LocalTime.of(18, 0));
|
||||
|
||||
LOGGER.info("Date sélectionnée: " + dateSelectionnee);
|
||||
}
|
||||
}
|
||||
|
||||
public void onEventSelect(SelectEvent<Object> event) {
|
||||
if (event != null && event.getObject() != null) {
|
||||
try {
|
||||
// Récupérer l'événement sélectionné depuis le ScheduleModel
|
||||
Object eventObject = event.getObject();
|
||||
|
||||
// Essayer de trouver l'événement correspondant
|
||||
if (eventObject instanceof org.primefaces.model.ScheduleEvent) {
|
||||
org.primefaces.model.ScheduleEvent<?> scheduleEvent =
|
||||
(org.primefaces.model.ScheduleEvent<?>) eventObject;
|
||||
String eventId = scheduleEvent.getId();
|
||||
|
||||
if (eventId != null) {
|
||||
// Chercher dans la liste des événements
|
||||
for (EvenementDTO evt : tousLesEvenements) {
|
||||
if (evt.getId() != null && evt.getId().toString().equals(eventId)) {
|
||||
this.evenementSelectionne = evt;
|
||||
LOGGER.info("Événement sélectionné: " + evt.getTitre());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Erreur sélection événement: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onEventMove(Object event) {
|
||||
// Les modifications de date sont gérées par le backend lors de la sauvegarde
|
||||
// Cette méthode capture l'événement de déplacement mais la logique est simplifiée
|
||||
// car les classes ScheduleEntryMoveEvent ne sont pas disponibles
|
||||
LOGGER.info("Événement déplacé - actualisation nécessaire");
|
||||
ajouterMessage(FacesMessage.SEVERITY_INFO, "Info",
|
||||
"Pour modifier les dates, veuillez éditer l'événement");
|
||||
}
|
||||
|
||||
public void onEventResize(Object event) {
|
||||
// Les modifications de durée sont gérées par le backend lors de la sauvegarde
|
||||
// Cette méthode capture l'événement de redimensionnement mais la logique est simplifiée
|
||||
// car les classes ScheduleEntryResizeEvent ne sont pas disponibles
|
||||
LOGGER.info("Événement redimensionné - actualisation nécessaire");
|
||||
ajouterMessage(FacesMessage.SEVERITY_INFO, "Info",
|
||||
"Pour modifier la durée, veuillez éditer l'événement");
|
||||
}
|
||||
|
||||
// Getters/Setters pour les nouvelles propriétés
|
||||
public LocalDate getDateSelectionnee() { return dateSelectionnee; }
|
||||
public void setDateSelectionnee(LocalDate dateSelectionnee) { this.dateSelectionnee = dateSelectionnee; }
|
||||
|
||||
// Méthodes utilitaires
|
||||
|
||||
private void ajouterMessage(FacesMessage.Severity severity, String resume, String detail) {
|
||||
FacesContext.getCurrentInstance()
|
||||
.addMessage(null, new FacesMessage(severity, resume, detail));
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
|
||||
public List<EvenementDTO> getTousLesEvenements() { return tousLesEvenements; }
|
||||
public void setTousLesEvenements(List<EvenementDTO> tousLesEvenements) {
|
||||
this.tousLesEvenements = tousLesEvenements;
|
||||
}
|
||||
|
||||
public List<EvenementDTO> getEvenementsFiltres() { return evenementsFiltres; }
|
||||
public void setEvenementsFiltres(List<EvenementDTO> evenementsFiltres) {
|
||||
this.evenementsFiltres = evenementsFiltres;
|
||||
}
|
||||
|
||||
public List<EvenementDTO> getEvenementsSelectionnes() { return evenementsSelectionnes; }
|
||||
public void setEvenementsSelectionnes(List<EvenementDTO> evenementsSelectionnes) {
|
||||
this.evenementsSelectionnes = evenementsSelectionnes;
|
||||
}
|
||||
|
||||
public List<EvenementDTO> getEvenementsProchains() { return evenementsProchains; }
|
||||
public void setEvenementsProchains(List<EvenementDTO> evenementsProchains) {
|
||||
this.evenementsProchains = evenementsProchains;
|
||||
}
|
||||
|
||||
public EvenementDTO getEvenementSelectionne() { return evenementSelectionne; }
|
||||
public void setEvenementSelectionne(EvenementDTO evenementSelectionne) {
|
||||
this.evenementSelectionne = evenementSelectionne;
|
||||
}
|
||||
|
||||
public EvenementDTO getNouvelEvenement() { return nouvelEvenement; }
|
||||
public void setNouvelEvenement(EvenementDTO nouvelEvenement) {
|
||||
this.nouvelEvenement = nouvelEvenement;
|
||||
}
|
||||
|
||||
public FiltresEvenement getFiltres() { return filtres; }
|
||||
public void setFiltres(FiltresEvenement filtres) { this.filtres = filtres; }
|
||||
|
||||
public StatistiquesEvenements getStatistiques() { return statistiques; }
|
||||
public void setStatistiques(StatistiquesEvenements statistiques) {
|
||||
this.statistiques = statistiques;
|
||||
}
|
||||
|
||||
// Classes internes pour les filtres et statistiques
|
||||
|
||||
public static class FiltresEvenement implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String titre;
|
||||
private String type;
|
||||
private String statut;
|
||||
private String organisateur;
|
||||
private String priorite;
|
||||
private LocalDate dateDebut;
|
||||
private LocalDate dateFin;
|
||||
|
||||
// Getters et setters
|
||||
public String getTitre() { return titre; }
|
||||
public void setTitre(String titre) { this.titre = titre; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getOrganisateur() { return organisateur; }
|
||||
public void setOrganisateur(String organisateur) { this.organisateur = organisateur; }
|
||||
|
||||
public String getPriorite() { return priorite; }
|
||||
public void setPriorite(String priorite) { this.priorite = priorite; }
|
||||
|
||||
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 StatistiquesEvenements implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private int totalEvenements;
|
||||
private int evenementsActifs;
|
||||
private int participantsTotal;
|
||||
private String budgetTotal;
|
||||
private int moyenneParticipants;
|
||||
private int evenementsCeMois;
|
||||
private int tauxParticipationMoyen;
|
||||
|
||||
// Getters et setters
|
||||
public int getTotalEvenements() { return totalEvenements; }
|
||||
public void setTotalEvenements(int totalEvenements) {
|
||||
this.totalEvenements = totalEvenements;
|
||||
}
|
||||
|
||||
public int getEvenementsActifs() { return evenementsActifs; }
|
||||
public void setEvenementsActifs(int evenementsActifs) {
|
||||
this.evenementsActifs = evenementsActifs;
|
||||
}
|
||||
|
||||
public int getParticipantsTotal() { return participantsTotal; }
|
||||
public void setParticipantsTotal(int participantsTotal) {
|
||||
this.participantsTotal = participantsTotal;
|
||||
}
|
||||
|
||||
public String getBudgetTotal() { return budgetTotal; }
|
||||
public void setBudgetTotal(String budgetTotal) {
|
||||
this.budgetTotal = budgetTotal;
|
||||
}
|
||||
|
||||
public int getMoyenneParticipants() { return moyenneParticipants; }
|
||||
public void setMoyenneParticipants(int moyenneParticipants) {
|
||||
this.moyenneParticipants = moyenneParticipants;
|
||||
}
|
||||
|
||||
public int getEvenementsCeMois() { return evenementsCeMois; }
|
||||
public void setEvenementsCeMois(int evenementsCeMois) {
|
||||
this.evenementsCeMois = evenementsCeMois;
|
||||
}
|
||||
|
||||
public int getTauxParticipationMoyen() { return tauxParticipationMoyen; }
|
||||
public void setTauxParticipationMoyen(int tauxParticipationMoyen) {
|
||||
this.tauxParticipationMoyen = tauxParticipationMoyen;
|
||||
}
|
||||
}
|
||||
}
|
||||
470
src/main/java/dev/lions/unionflow/client/view/FavorisBean.java
Normal file
470
src/main/java/dev/lions/unionflow/client/view/FavorisBean.java
Normal 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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.dto.FormulaireDTO;
|
||||
import dev.lions.unionflow.client.dto.SouscriptionDTO;
|
||||
import dev.lions.unionflow.client.service.FormulaireService;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
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.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("formulaireBean")
|
||||
@RequestScoped
|
||||
public class FormulaireBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(FormulaireBean.class.getName());
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_SOUSCRIPTION_CHECKOUT = "souscriptionCheckoutPage";
|
||||
private static final String OUTCOME_FORMULAIRE_DETAILS = "formulaireDetailsPage";
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private FormulaireService formulaireService;
|
||||
|
||||
private List<FormulaireDTO> formulaires;
|
||||
private List<FormulaireDTO> formulairesPopulaires;
|
||||
private FormulaireDTO formulaireSelectionne;
|
||||
private SouscriptionDTO.TypeFacturation typeFacturationSelectionne = SouscriptionDTO.TypeFacturation.MENSUEL;
|
||||
|
||||
// Filtres
|
||||
private Integer membresMax;
|
||||
private BigDecimal budgetMax;
|
||||
private String categorieFiltre = "ALL";
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initializeFormulaires();
|
||||
}
|
||||
|
||||
private void initializeFormulaires() {
|
||||
formulaires = new ArrayList<>();
|
||||
try {
|
||||
formulaires = formulaireService.listerActifs();
|
||||
formulairesPopulaires = formulaireService.listerPopulaires();
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des formulaires: " + e.getMessage());
|
||||
formulaires = new ArrayList<>();
|
||||
formulairesPopulaires = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
public void selectionnerFormulaire(FormulaireDTO formulaire) {
|
||||
this.formulaireSelectionne = formulaire;
|
||||
}
|
||||
|
||||
public String procederSouscription() {
|
||||
if (formulaireSelectionne != null) {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_SOUSCRIPTION_CHECKOUT + "?formulaire=" +
|
||||
formulaireSelectionne.getId() +
|
||||
"&facturation=" + typeFacturationSelectionne.name() +
|
||||
"&faces-redirect=true";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String voirDetailsFormulaire(FormulaireDTO formulaire) {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_FORMULAIRE_DETAILS + "?id=" + formulaire.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
public List<FormulaireDTO> getFormulairesFiltres() {
|
||||
return formulaires.stream()
|
||||
.filter(f -> {
|
||||
// Filtre par nombre de membres
|
||||
if (membresMax != null && f.getQuotaMaxMembres() > membresMax) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filtre par budget
|
||||
if (budgetMax != null) {
|
||||
BigDecimal prix = (typeFacturationSelectionne == SouscriptionDTO.TypeFacturation.MENSUEL)
|
||||
? f.getPrixMensuel() : f.getPrixAnnuel();
|
||||
if (prix.compareTo(budgetMax) > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre par catégorie
|
||||
if (!"ALL".equals(categorieFiltre)) {
|
||||
switch (categorieFiltre) {
|
||||
case "SMALL":
|
||||
return f.getQuotaMaxMembres() <= 50;
|
||||
case "MEDIUM":
|
||||
return f.getQuotaMaxMembres() > 50 && f.getQuotaMaxMembres() <= 200;
|
||||
case "LARGE":
|
||||
return f.getQuotaMaxMembres() > 200;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.toList();
|
||||
}
|
||||
|
||||
public void resetFiltres() {
|
||||
membresMax = null;
|
||||
budgetMax = null;
|
||||
categorieFiltre = "ALL";
|
||||
}
|
||||
|
||||
public String getPrixAffiche(FormulaireDTO formulaire) {
|
||||
if (typeFacturationSelectionne == SouscriptionDTO.TypeFacturation.MENSUEL) {
|
||||
return formulaire.getPrixMensuelFormat() + "/mois";
|
||||
} else {
|
||||
return formulaire.getPrixAnnuelFormat() + "/an";
|
||||
}
|
||||
}
|
||||
|
||||
public String getEconomieAffichee(FormulaireDTO formulaire) {
|
||||
if (typeFacturationSelectionne == SouscriptionDTO.TypeFacturation.ANNUEL) {
|
||||
int pourcentage = formulaire.getPourcentageEconomie();
|
||||
if (pourcentage > 0) {
|
||||
return "Économisez " + pourcentage + "%";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public boolean isFormulaireFonctionnaliteActive(FormulaireDTO formulaire, String fonctionnalite) {
|
||||
switch (fonctionnalite.toLowerCase()) {
|
||||
case "membres":
|
||||
return formulaire.isGestionMembres();
|
||||
case "cotisations":
|
||||
return formulaire.isGestionCotisations();
|
||||
case "evenements":
|
||||
return formulaire.isGestionEvenements();
|
||||
case "aides":
|
||||
return formulaire.isGestionAides();
|
||||
case "rapports":
|
||||
return formulaire.isRapportsAvances();
|
||||
case "support":
|
||||
return formulaire.isSupportPrioritaire();
|
||||
case "sauvegarde":
|
||||
return formulaire.isSauvegardeAutomatique();
|
||||
case "personnalisation":
|
||||
return formulaire.isPersonnalisationAvancee();
|
||||
case "paiement":
|
||||
return formulaire.isIntegrationPaiement();
|
||||
case "email":
|
||||
return formulaire.isNotificationsEmail();
|
||||
case "sms":
|
||||
return formulaire.isNotificationsSMS();
|
||||
case "documents":
|
||||
return formulaire.isGestionDocuments();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getComparaisonClasse() {
|
||||
return formulaires.size() <= 3 ? "col-12 md:col-4" : "col-12 md:col-6 lg:col-3";
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public List<FormulaireDTO> getFormulaires() { return formulaires; }
|
||||
public void setFormulaires(List<FormulaireDTO> formulaires) { this.formulaires = formulaires; }
|
||||
|
||||
public List<FormulaireDTO> getFormulairesPopulaires() { return formulairesPopulaires; }
|
||||
public void setFormulairesPopulaires(List<FormulaireDTO> formulairesPopulaires) { this.formulairesPopulaires = formulairesPopulaires; }
|
||||
|
||||
public FormulaireDTO getFormulaireSelectionne() { return formulaireSelectionne; }
|
||||
public void setFormulaireSelectionne(FormulaireDTO formulaireSelectionne) { this.formulaireSelectionne = formulaireSelectionne; }
|
||||
|
||||
public SouscriptionDTO.TypeFacturation getTypeFacturationSelectionne() { return typeFacturationSelectionne; }
|
||||
public void setTypeFacturationSelectionne(SouscriptionDTO.TypeFacturation typeFacturationSelectionne) { this.typeFacturationSelectionne = typeFacturationSelectionne; }
|
||||
|
||||
public Integer getMembresMax() { return membresMax; }
|
||||
public void setMembresMax(Integer membresMax) { this.membresMax = membresMax; }
|
||||
|
||||
public BigDecimal getBudgetMax() { return budgetMax; }
|
||||
public void setBudgetMax(BigDecimal budgetMax) { this.budgetMax = budgetMax; }
|
||||
|
||||
public String getCategorieFiltre() { return categorieFiltre; }
|
||||
public void setCategorieFiltre(String categorieFiltre) { this.categorieFiltre = categorieFiltre; }
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.inject.Named;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Named("guestPreferences")
|
||||
@SessionScoped
|
||||
public class GuestPreferences implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String theme = "blue-light";
|
||||
private String layout = "light";
|
||||
private String componentTheme = "blue-light";
|
||||
private String darkMode = "light";
|
||||
private String menuMode = "layout-sidebar";
|
||||
private String topbarTheme = "light";
|
||||
private String menuTheme = "light";
|
||||
private String inputStyle = "outlined";
|
||||
private boolean lightLogo = false;
|
||||
|
||||
public String getTheme() {
|
||||
return theme;
|
||||
}
|
||||
|
||||
public void setTheme(String theme) {
|
||||
this.theme = theme;
|
||||
}
|
||||
|
||||
public String getLayout() {
|
||||
return layout;
|
||||
}
|
||||
|
||||
public void setLayout(String layout) {
|
||||
this.layout = layout;
|
||||
}
|
||||
|
||||
public String getComponentTheme() {
|
||||
return componentTheme;
|
||||
}
|
||||
|
||||
public void setComponentTheme(String componentTheme) {
|
||||
this.componentTheme = componentTheme;
|
||||
}
|
||||
|
||||
public String getDarkMode() {
|
||||
return darkMode;
|
||||
}
|
||||
|
||||
public void setDarkMode(String darkMode) {
|
||||
this.darkMode = darkMode;
|
||||
this.lightLogo = "dark".equals(darkMode);
|
||||
}
|
||||
|
||||
public String getMenuMode() {
|
||||
return menuMode;
|
||||
}
|
||||
|
||||
public void setMenuMode(String menuMode) {
|
||||
this.menuMode = menuMode;
|
||||
}
|
||||
|
||||
public String getTopbarTheme() {
|
||||
return topbarTheme;
|
||||
}
|
||||
|
||||
public void setTopbarTheme(String topbarTheme) {
|
||||
this.topbarTheme = topbarTheme;
|
||||
}
|
||||
|
||||
public String getMenuTheme() {
|
||||
return menuTheme;
|
||||
}
|
||||
|
||||
public void setMenuTheme(String menuTheme) {
|
||||
this.menuTheme = menuTheme;
|
||||
}
|
||||
|
||||
public String getInputStyle() {
|
||||
return inputStyle;
|
||||
}
|
||||
|
||||
public void setInputStyle(String inputStyle) {
|
||||
this.inputStyle = inputStyle;
|
||||
}
|
||||
|
||||
public boolean isLightLogo() {
|
||||
return lightLogo;
|
||||
}
|
||||
|
||||
public void setLightLogo(boolean lightLogo) {
|
||||
this.lightLogo = lightLogo;
|
||||
}
|
||||
|
||||
public String getInputStyleClass() {
|
||||
return "p-input-" + inputStyle;
|
||||
}
|
||||
|
||||
public String getLayoutClass() {
|
||||
return "layout-" + layout + " layout-theme-" + theme;
|
||||
}
|
||||
|
||||
public List<ComponentTheme> getComponentThemes() {
|
||||
List<ComponentTheme> themes = new ArrayList<>();
|
||||
themes.add(new ComponentTheme("blue-light", "Blue", "#007ad9"));
|
||||
themes.add(new ComponentTheme("green-light", "Green", "#28a745"));
|
||||
themes.add(new ComponentTheme("orange-light", "Orange", "#fd7e14"));
|
||||
themes.add(new ComponentTheme("purple-light", "Purple", "#6f42c1"));
|
||||
themes.add(new ComponentTheme("pink-light", "Pink", "#e83e8c"));
|
||||
themes.add(new ComponentTheme("indigo-light", "Indigo", "#6610f2"));
|
||||
themes.add(new ComponentTheme("teal-light", "Teal", "#20c997"));
|
||||
themes.add(new ComponentTheme("cyan-light", "Cyan", "#17a2b8"));
|
||||
return themes;
|
||||
}
|
||||
|
||||
public void onMenuTypeChange() {
|
||||
// Called when menu type changes
|
||||
}
|
||||
|
||||
public static class ComponentTheme {
|
||||
private String file;
|
||||
private String name;
|
||||
private String color;
|
||||
|
||||
public ComponentTheme(String file, String name, String color) {
|
||||
this.file = file;
|
||||
this.name = name;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public String getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getColor() {
|
||||
return color;
|
||||
}
|
||||
}
|
||||
}
|
||||
241
src/main/java/dev/lions/unionflow/client/view/GuideBean.java
Normal file
241
src/main/java/dev/lions/unionflow/client/view/GuideBean.java
Normal file
@@ -0,0 +1,241 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.inject.Named;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Named("guideBean")
|
||||
@SessionScoped
|
||||
public class GuideBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// Structure du guide
|
||||
private List<SectionGuide> toutesSections;
|
||||
private SectionGuide sectionCourante;
|
||||
private String sectionActiveId = "default";
|
||||
private int sectionActive = 0;
|
||||
|
||||
// Recherche
|
||||
private String termeRecherche = "";
|
||||
|
||||
public GuideBean() {
|
||||
initialiserSections();
|
||||
sectionCourante = new SectionGuide("default", "Accueil", "", "", 0, false);
|
||||
}
|
||||
|
||||
private void initialiserSections() {
|
||||
toutesSections = new ArrayList<>();
|
||||
|
||||
// Section 1: Premiers pas
|
||||
toutesSections.add(new SectionGuide("premiers-pas-connexion", "Se connecter", "Premiers Pas", "Apprendre à se connecter à UnionFlow", 5, false));
|
||||
toutesSections.add(new SectionGuide("premiers-pas-interface", "Découvrir l'interface", "Premiers Pas", "Navigation et organisation de l'interface", 8, false));
|
||||
toutesSections.add(new SectionGuide("premiers-pas-profil", "Configurer son profil", "Premiers Pas", "Personnaliser ses informations personnelles", 10, false));
|
||||
toutesSections.add(new SectionGuide("premiers-pas-navigation", "Navigation dans le système", "Premiers Pas", "Utiliser les menus et raccourcis", 6, false));
|
||||
|
||||
// Section 2: Gestion des membres
|
||||
toutesSections.add(new SectionGuide("membres-inscription", "Inscrire un membre", "Gestion Membres", "Processus d'inscription d'un nouveau membre", 12, false));
|
||||
toutesSections.add(new SectionGuide("membres-modification", "Modifier un profil", "Gestion Membres", "Mettre à jour les informations d'un membre", 8, false));
|
||||
toutesSections.add(new SectionGuide("membres-recherche", "Rechercher des membres", "Gestion Membres", "Utiliser les filtres de recherche avancée", 6, false));
|
||||
toutesSections.add(new SectionGuide("membres-export", "Exporter la liste", "Gestion Membres", "Générer des exports Excel et PDF", 10, false));
|
||||
toutesSections.add(new SectionGuide("membres-historique", "Consulter l'historique", "Gestion Membres", "Suivre les modifications et activités", 7, false));
|
||||
|
||||
// Section 3: Finances
|
||||
toutesSections.add(new SectionGuide("finances-cotisations", "Gérer les cotisations", "Finances", "Configuration et suivi des cotisations", 15, false));
|
||||
toutesSections.add(new SectionGuide("finances-paiements", "Enregistrer les paiements", "Finances", "Saisie manuelle et automatique", 12, false));
|
||||
toutesSections.add(new SectionGuide("finances-relances", "Relances automatiques", "Finances", "Configuration des rappels de paiement", 10, false));
|
||||
toutesSections.add(new SectionGuide("finances-rapports", "Rapports financiers", "Finances", "Générer des bilans et statistiques", 18, false));
|
||||
|
||||
// Section 4: Événements
|
||||
toutesSections.add(new SectionGuide("events-creation", "Créer un événement", "Événements", "Planifier et organiser des événements", 15, false));
|
||||
toutesSections.add(new SectionGuide("events-inscriptions", "Gérer les inscriptions", "Événements", "Suivre les participations", 10, false));
|
||||
toutesSections.add(new SectionGuide("events-communication", "Communication événement", "Événements", "Envoyer invitations et rappels", 12, false));
|
||||
toutesSections.add(new SectionGuide("events-bilan", "Bilan post-événement", "Événements", "Analyser la participation et satisfaction", 8, false));
|
||||
|
||||
// Section 5: Rapports
|
||||
toutesSections.add(new SectionGuide("rapports-creation", "Créer des rapports", "Rapports", "Utiliser le générateur de rapports", 20, false));
|
||||
toutesSections.add(new SectionGuide("rapports-tableaux", "Tableaux de bord", "Rapports", "Configurer ses indicateurs personnalisés", 15, false));
|
||||
toutesSections.add(new SectionGuide("rapports-export", "Export et partage", "Rapports", "Distribuer les rapports aux parties prenantes", 10, false));
|
||||
|
||||
// Section 6: Administration
|
||||
toutesSections.add(new SectionGuide("admin-utilisateurs", "Gestion des utilisateurs", "Administration", "Créer et gérer les comptes utilisateurs", 18, false));
|
||||
toutesSections.add(new SectionGuide("admin-permissions", "Rôles et permissions", "Administration", "Configuration des droits d'accès", 22, false));
|
||||
toutesSections.add(new SectionGuide("admin-parametres", "Paramètres système", "Administration", "Configuration générale de l'application", 25, false));
|
||||
toutesSections.add(new SectionGuide("admin-sauvegarde", "Sauvegarde et sécurité", "Administration", "Protéger et sauvegarder les données", 15, false));
|
||||
toutesSections.add(new SectionGuide("admin-audit", "Journal d'audit", "Administration", "Surveiller l'activité et la sécurité", 12, false));
|
||||
}
|
||||
|
||||
// Getters pour les sections par catégorie
|
||||
public List<SectionGuide> getSectionsPremiersPas() {
|
||||
return toutesSections.stream()
|
||||
.filter(s -> "Premiers Pas".equals(s.getCategorie()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<SectionGuide> getSectionsMembres() {
|
||||
return toutesSections.stream()
|
||||
.filter(s -> "Gestion Membres".equals(s.getCategorie()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<SectionGuide> getSectionsFinances() {
|
||||
return toutesSections.stream()
|
||||
.filter(s -> "Finances".equals(s.getCategorie()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<SectionGuide> getSectionsEvenements() {
|
||||
return toutesSections.stream()
|
||||
.filter(s -> "Événements".equals(s.getCategorie()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<SectionGuide> getSectionsRapports() {
|
||||
return toutesSections.stream()
|
||||
.filter(s -> "Rapports".equals(s.getCategorie()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<SectionGuide> getSectionsAdmin() {
|
||||
return toutesSections.stream()
|
||||
.filter(s -> "Administration".equals(s.getCategorie()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// Statistiques de progression
|
||||
public int getTotalSections() {
|
||||
return toutesSections.size();
|
||||
}
|
||||
|
||||
public int getSectionsLues() {
|
||||
return (int) toutesSections.stream().filter(SectionGuide::isLu).count();
|
||||
}
|
||||
|
||||
public int getPourcentageProgression() {
|
||||
if (getTotalSections() == 0) return 0;
|
||||
return (getSectionsLues() * 100) / getTotalSections();
|
||||
}
|
||||
|
||||
// Navigation
|
||||
public void naviguerVers(String sectionId) {
|
||||
this.sectionActiveId = sectionId;
|
||||
this.sectionCourante = toutesSections.stream()
|
||||
.filter(s -> s.getId().equals(sectionId))
|
||||
.findFirst()
|
||||
.orElse(new SectionGuide("default", "Accueil", "", "", 0, false));
|
||||
}
|
||||
|
||||
public void sectionPrecedente() {
|
||||
int index = trouverIndexSection(sectionActiveId);
|
||||
if (index > 0) {
|
||||
naviguerVers(toutesSections.get(index - 1).getId());
|
||||
}
|
||||
}
|
||||
|
||||
public void sectionSuivante() {
|
||||
int index = trouverIndexSection(sectionActiveId);
|
||||
if (index < toutesSections.size() - 1) {
|
||||
naviguerVers(toutesSections.get(index + 1).getId());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAPrecedent() {
|
||||
return trouverIndexSection(sectionActiveId) > 0;
|
||||
}
|
||||
|
||||
public boolean isASuivant() {
|
||||
int index = trouverIndexSection(sectionActiveId);
|
||||
return index >= 0 && index < toutesSections.size() - 1;
|
||||
}
|
||||
|
||||
private int trouverIndexSection(String sectionId) {
|
||||
for (int i = 0; i < toutesSections.size(); i++) {
|
||||
if (toutesSections.get(i).getId().equals(sectionId)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Marquer comme lu
|
||||
public void marquerCommeLu() {
|
||||
if (sectionCourante != null && !sectionCourante.getId().equals("default")) {
|
||||
sectionCourante.setLu(true);
|
||||
// Mettre à jour aussi dans la liste principale
|
||||
toutesSections.stream()
|
||||
.filter(s -> s.getId().equals(sectionCourante.getId()))
|
||||
.findFirst()
|
||||
.ifPresent(s -> s.setLu(true));
|
||||
}
|
||||
}
|
||||
|
||||
// Recherche
|
||||
public List<SectionGuide> getResultatsRecherche() {
|
||||
if (termeRecherche == null || termeRecherche.trim().isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
String terme = termeRecherche.toLowerCase();
|
||||
return toutesSections.stream()
|
||||
.filter(s -> s.getTitre().toLowerCase().contains(terme) ||
|
||||
s.getDescription().toLowerCase().contains(terme) ||
|
||||
s.getCategorie().toLowerCase().contains(terme))
|
||||
.limit(8)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public SectionGuide getSectionCourante() { return sectionCourante; }
|
||||
public void setSectionCourante(SectionGuide sectionCourante) { this.sectionCourante = sectionCourante; }
|
||||
|
||||
public String getSectionActiveId() { return sectionActiveId; }
|
||||
public void setSectionActiveId(String sectionActiveId) { this.sectionActiveId = sectionActiveId; }
|
||||
|
||||
public int getSectionActive() { return sectionActive; }
|
||||
public void setSectionActive(int sectionActive) { this.sectionActive = sectionActive; }
|
||||
|
||||
public String getTermeRecherche() { return termeRecherche; }
|
||||
public void setTermeRecherche(String termeRecherche) { this.termeRecherche = termeRecherche; }
|
||||
|
||||
// Classe interne SectionGuide
|
||||
public static class SectionGuide implements Serializable {
|
||||
private String id;
|
||||
private String titre;
|
||||
private String categorie;
|
||||
private String description;
|
||||
private int tempsLecture; // en minutes
|
||||
private boolean lu;
|
||||
|
||||
public SectionGuide() {}
|
||||
|
||||
public SectionGuide(String id, String titre, String categorie, String description, int tempsLecture, boolean lu) {
|
||||
this.id = id;
|
||||
this.titre = titre;
|
||||
this.categorie = categorie;
|
||||
this.description = description;
|
||||
this.tempsLecture = tempsLecture;
|
||||
this.lu = lu;
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public String getId() { return id; }
|
||||
public void setId(String id) { this.id = id; }
|
||||
|
||||
public String getTitre() { return titre; }
|
||||
public void setTitre(String titre) { this.titre = titre; }
|
||||
|
||||
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 int getTempsLecture() { return tempsLecture; }
|
||||
public void setTempsLecture(int tempsLecture) { this.tempsLecture = tempsLecture; }
|
||||
|
||||
public boolean isLu() { return lu; }
|
||||
public void setLu(boolean lu) { this.lu = lu; }
|
||||
}
|
||||
}
|
||||
48
src/main/java/dev/lions/unionflow/client/view/HelloView.java
Normal file
48
src/main/java/dev/lions/unionflow/client/view/HelloView.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Named;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Named("helloView")
|
||||
@RequestScoped
|
||||
public class HelloView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String message = "Bienvenue sur UnionFlow avec Quarkus et PrimeFaces!";
|
||||
private String name;
|
||||
private String greeting;
|
||||
|
||||
public void sayHello() {
|
||||
if (name != null && !name.isEmpty()) {
|
||||
greeting = "Bonjour " + name + " ! Bienvenue sur UnionFlow.";
|
||||
} else {
|
||||
greeting = "Veuillez entrer votre nom.";
|
||||
}
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getGreeting() {
|
||||
return greeting;
|
||||
}
|
||||
|
||||
public void setGreeting(String greeting) {
|
||||
this.greeting = greeting;
|
||||
}
|
||||
}
|
||||
84
src/main/java/dev/lions/unionflow/client/view/LoginBean.java
Normal file
84
src/main/java/dev/lions/unionflow/client/view/LoginBean.java
Normal file
@@ -0,0 +1,84 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.faces.context.ExternalContext;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import org.eclipse.microprofile.jwt.JsonWebToken;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Bean de gestion de l'authentification via Keycloak OIDC
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
*/
|
||||
@Named("loginBean")
|
||||
@RequestScoped
|
||||
public class LoginBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(LoginBean.class.getName());
|
||||
|
||||
@Inject
|
||||
private JsonWebToken jwt;
|
||||
|
||||
@Inject
|
||||
private UserSession userSession;
|
||||
|
||||
/**
|
||||
* Redirige vers Keycloak pour l'authentification
|
||||
* L'authentification est gérée automatiquement par Quarkus OIDC
|
||||
*/
|
||||
public void login() {
|
||||
try {
|
||||
// La redirection vers Keycloak est gérée automatiquement par Quarkus OIDC
|
||||
// via la configuration dans application.properties
|
||||
LOGGER.info("Redirection vers Keycloak pour l'authentification");
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la redirection vers Keycloak: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Déconnexion de l'utilisateur
|
||||
* Redirige vers l'endpoint de déconnexion Keycloak
|
||||
*/
|
||||
public String logout() {
|
||||
try {
|
||||
// Nettoyer la session locale
|
||||
userSession.clearSession();
|
||||
|
||||
// Invalider la session JSF
|
||||
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
|
||||
|
||||
LOGGER.info("Déconnexion réussie");
|
||||
|
||||
// Redirection vers Keycloak pour la déconnexion complète
|
||||
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
|
||||
String logoutUrl = "/auth/logout";
|
||||
externalContext.redirect(logoutUrl);
|
||||
|
||||
return null; // La redirection est gérée par redirect()
|
||||
|
||||
} catch (IOException e) {
|
||||
LOGGER.warning("Erreur lors de la déconnexion: " + e.getMessage());
|
||||
|
||||
// Même en cas d'erreur, invalider la session locale
|
||||
userSession.clearSession();
|
||||
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
|
||||
|
||||
return "/?faces-redirect=true";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'utilisateur est authentifié
|
||||
*/
|
||||
public boolean isAuthenticated() {
|
||||
return jwt != null && jwt.getName() != null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,575 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.dto.CotisationDTO;
|
||||
import dev.lions.unionflow.client.dto.MembreDTO;
|
||||
import dev.lions.unionflow.client.service.CotisationService;
|
||||
import dev.lions.unionflow.client.service.MembreService;
|
||||
import jakarta.faces.view.ViewScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.faces.application.FacesMessage;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Bean pour la gestion des cotisations d'un membre (WOU/DRY)
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
*/
|
||||
@Named("membreCotisationBean")
|
||||
@ViewScoped
|
||||
public class MembreCotisationBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(MembreCotisationBean.class.getName());
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy");
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_MEMBRE_HISTORIQUE_COTISATIONS = "membreHistoriqueCotisationsPage";
|
||||
private static final String OUTCOME_MEMBRE_PROFIL = "membreProfilPage";
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private MembreService membreService;
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private CotisationService cotisationService;
|
||||
|
||||
// ID du membre (depuis viewParam)
|
||||
private UUID membreId;
|
||||
|
||||
// Données du membre
|
||||
private MembreDTO membre;
|
||||
|
||||
// Propriétés de base
|
||||
private String numeroMembre;
|
||||
private String statutCotisations;
|
||||
private String derniereMAJ;
|
||||
private boolean peutPayer;
|
||||
|
||||
// Statistiques
|
||||
private int cotisationsPayees;
|
||||
private int cotisationsEnAttente;
|
||||
private BigDecimal montantDu;
|
||||
private BigDecimal totalVerse;
|
||||
private int progressionAnnuelle;
|
||||
|
||||
// Filtres
|
||||
private String anneeFilter = "2024";
|
||||
private String statutFilter = "";
|
||||
private String typeFilter = "";
|
||||
|
||||
// Paiement
|
||||
private Object cotisationSelectionnee;
|
||||
private String modePaiementChoisi = "WAVE";
|
||||
private String numeroWave;
|
||||
private String commentairePaiement;
|
||||
private BigDecimal montantAPayer = BigDecimal.ZERO;
|
||||
private String banqueAssociation = "Banque Atlantique";
|
||||
private String ibanAssociation = "SN12 1234 5678 9012 3456 7890 12";
|
||||
|
||||
// Prélèvement automatique
|
||||
private String numeroWaveAuto;
|
||||
private int jourPrelevement = 5;
|
||||
private boolean notificationSMS = true;
|
||||
private String cotisationMensuelle = "5,000 FCFA";
|
||||
|
||||
// Listes
|
||||
private List<Cotisation> cotisations = new ArrayList<>();
|
||||
private List<Echeance> prochainesEcheances = new ArrayList<>();
|
||||
private List<Cotisation> cotisationsImpayees = new ArrayList<>();
|
||||
|
||||
// Totaux périodes
|
||||
private BigDecimal totalPayePeriode = BigDecimal.ZERO;
|
||||
private BigDecimal totalEnAttentePeriode = BigDecimal.ZERO;
|
||||
private BigDecimal totalEnRetardPeriode = BigDecimal.ZERO;
|
||||
private int tauxConformite = 85;
|
||||
|
||||
// État
|
||||
private String statutMembre = "Actif";
|
||||
private String typeMembre = "Membre Actif";
|
||||
private String statutSeverity = "success";
|
||||
private int scorePonctualite = 85;
|
||||
private String commentairePonctualite = "Excellent membre, toujours à jour";
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
// Si membreId est null, essayer de le récupérer depuis les paramètres de requête
|
||||
if (membreId == null) {
|
||||
String idParam = FacesContext.getCurrentInstance()
|
||||
.getExternalContext()
|
||||
.getRequestParameterMap()
|
||||
.get("id");
|
||||
if (idParam != null && !idParam.isEmpty()) {
|
||||
try {
|
||||
membreId = UUID.fromString(idParam);
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOGGER.severe("ID de membre invalide: " + idParam);
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"ID de membre invalide"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (membreId != null) {
|
||||
chargerMembre();
|
||||
chargerCotisations();
|
||||
calculerStatistiques();
|
||||
} else {
|
||||
LOGGER.warning("Aucun membreId fourni, impossible de charger les cotisations");
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Aucun membre sélectionné"));
|
||||
initialiserDonneesVides();
|
||||
}
|
||||
}
|
||||
|
||||
private void chargerMembre() {
|
||||
try {
|
||||
membre = membreService.obtenirParId(membreId);
|
||||
if (membre != null) {
|
||||
numeroMembre = membre.getNumeroMembre();
|
||||
statutCotisations = membre.getStatut() != null ? membre.getStatut() : "ACTIF";
|
||||
derniereMAJ = LocalDate.now().format(DATE_FORMATTER);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement du membre: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de charger le membre: " + e.getMessage()));
|
||||
initialiserDonneesVides();
|
||||
}
|
||||
}
|
||||
|
||||
private void chargerCotisations() {
|
||||
try {
|
||||
List<CotisationDTO> cotisationsDTO = cotisationService.obtenirParMembre(membreId, 0, 100);
|
||||
cotisations = new ArrayList<>();
|
||||
|
||||
for (CotisationDTO dto : cotisationsDTO) {
|
||||
Cotisation cotisation = convertirEnCotisation(dto);
|
||||
cotisations.add(cotisation);
|
||||
|
||||
if (!"PAYEE".equals(cotisation.getStatut()) && !"PAYE".equals(cotisation.getStatut())) {
|
||||
cotisationsImpayees.add(cotisation);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des cotisations: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de charger les cotisations: " + e.getMessage()));
|
||||
cotisations = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private Cotisation convertirEnCotisation(CotisationDTO dto) {
|
||||
Cotisation cotisation = new Cotisation();
|
||||
cotisation.setReference(dto.getNumeroReference() != null ? dto.getNumeroReference() : "");
|
||||
cotisation.setLibelle(dto.getLibelle() != null ? dto.getLibelle() : "Cotisation");
|
||||
|
||||
// Formater la période depuis la date d'échéance
|
||||
if (dto.getDateEcheance() != null) {
|
||||
String[] moisNoms = {"Janvier", "Février", "Mars", "Avril", "Mai", "Juin",
|
||||
"Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"};
|
||||
int mois = dto.getDateEcheance().getMonthValue();
|
||||
int annee = dto.getDateEcheance().getYear();
|
||||
cotisation.setPeriode(moisNoms[mois - 1] + " " + annee);
|
||||
} else {
|
||||
cotisation.setPeriode("");
|
||||
}
|
||||
|
||||
cotisation.setType(dto.getTypeCotisation() != null ? dto.getTypeCotisation() : "MENSUELLE");
|
||||
cotisation.setMontant(dto.getMontantDu() != null ? dto.getMontantDu() : BigDecimal.ZERO);
|
||||
cotisation.setStatut(dto.getStatut() != null ? dto.getStatut() : "EN_ATTENTE");
|
||||
cotisation.setDateEcheance(dto.getDateEcheance());
|
||||
|
||||
// Convertir LocalDateTime en LocalDate pour datePaiement
|
||||
if (dto.getDatePaiement() != null) {
|
||||
cotisation.setDatePaiement(dto.getDatePaiement().toLocalDate());
|
||||
}
|
||||
|
||||
cotisation.setModePaiement(dto.getMethodePaiement() != null ? dto.getMethodePaiement() : null);
|
||||
return cotisation;
|
||||
}
|
||||
|
||||
private void calculerStatistiques() {
|
||||
cotisationsPayees = (int) cotisations.stream()
|
||||
.filter(c -> "PAYEE".equals(c.getStatut()) || "PAYE".equals(c.getStatut()))
|
||||
.count();
|
||||
cotisationsEnAttente = (int) cotisations.stream()
|
||||
.filter(c -> "EN_ATTENTE".equals(c.getStatut()))
|
||||
.count();
|
||||
montantDu = cotisations.stream()
|
||||
.filter(c -> !"PAYEE".equals(c.getStatut()) && !"PAYE".equals(c.getStatut()))
|
||||
.map(Cotisation::getMontant)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
totalVerse = cotisations.stream()
|
||||
.filter(c -> "PAYEE".equals(c.getStatut()) || "PAYE".equals(c.getStatut()))
|
||||
.map(Cotisation::getMontant)
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
// Calculer la progression annuelle (basée sur le nombre de cotisations payées)
|
||||
int totalCotisationsAnnee = (int) cotisations.stream()
|
||||
.filter(c -> c.getDateEcheance() != null && c.getDateEcheance().getYear() == LocalDate.now().getYear())
|
||||
.count();
|
||||
progressionAnnuelle = totalCotisationsAnnee > 0
|
||||
? (cotisationsPayees * 100) / totalCotisationsAnnee
|
||||
: 0;
|
||||
|
||||
peutPayer = !cotisationsImpayees.isEmpty();
|
||||
}
|
||||
|
||||
private void initialiserDonneesVides() {
|
||||
numeroMembre = "";
|
||||
statutCotisations = "Non renseigné";
|
||||
derniereMAJ = "";
|
||||
peutPayer = false;
|
||||
cotisationsPayees = 0;
|
||||
cotisationsEnAttente = 0;
|
||||
montantDu = BigDecimal.ZERO;
|
||||
totalVerse = BigDecimal.ZERO;
|
||||
progressionAnnuelle = 0;
|
||||
cotisations = new ArrayList<>();
|
||||
cotisationsImpayees = new ArrayList<>();
|
||||
}
|
||||
|
||||
|
||||
// Actions
|
||||
public String voirHistoriqueComplet() {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_MEMBRE_HISTORIQUE_COTISATIONS + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public void telechargerRecus() {
|
||||
// Logique de téléchargement des reçus
|
||||
}
|
||||
|
||||
public void payerCotisation(Object cotisation) {
|
||||
// Logique de paiement d'une cotisation
|
||||
}
|
||||
|
||||
public void actualiser() {
|
||||
// Actualiser les données depuis le backend (WOU/DRY)
|
||||
chargerMembre();
|
||||
chargerCotisations();
|
||||
calculerStatistiques();
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Actualisation",
|
||||
"Les données ont été actualisées"));
|
||||
}
|
||||
|
||||
public String confirmerPaiement() {
|
||||
// Logique de confirmation de paiement
|
||||
return null;
|
||||
}
|
||||
|
||||
public void paiementWave() {
|
||||
// Logique de paiement Wave Money
|
||||
}
|
||||
|
||||
public void genererAttestation() {
|
||||
// Logique de génération d'attestation
|
||||
}
|
||||
|
||||
public void demanderRecu() {
|
||||
// Logique de demande de reçu
|
||||
}
|
||||
|
||||
public void activerPrelevementAuto() {
|
||||
// Logique d'activation du prélèvement automatique
|
||||
}
|
||||
|
||||
public void telechargerRecu(Object cotisation) {
|
||||
// Logique de téléchargement de reçu
|
||||
}
|
||||
|
||||
public void voirDetails(Object cotisation) {
|
||||
// Logique d'affichage des détails
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public UUID getMembreId() { return membreId; }
|
||||
public void setMembreId(UUID membreId) { this.membreId = membreId; }
|
||||
|
||||
public MembreDTO getMembre() { return membre; }
|
||||
public void setMembre(MembreDTO membre) { this.membre = membre; }
|
||||
|
||||
public String getNumeroMembre() { return numeroMembre; }
|
||||
public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
|
||||
|
||||
public String getStatutCotisations() { return statutCotisations; }
|
||||
public void setStatutCotisations(String statutCotisations) { this.statutCotisations = statutCotisations; }
|
||||
|
||||
public String getDerniereMAJ() { return derniereMAJ; }
|
||||
public void setDerniereMAJ(String derniereMAJ) { this.derniereMAJ = derniereMAJ; }
|
||||
|
||||
public boolean isPeutPayer() { return peutPayer; }
|
||||
public void setPeutPayer(boolean peutPayer) { this.peutPayer = peutPayer; }
|
||||
|
||||
public int getCotisationsPayees() { return cotisationsPayees; }
|
||||
public void setCotisationsPayees(int cotisationsPayees) { this.cotisationsPayees = cotisationsPayees; }
|
||||
|
||||
public int getCotisationsEnAttente() { return cotisationsEnAttente; }
|
||||
public void setCotisationsEnAttente(int cotisationsEnAttente) { this.cotisationsEnAttente = cotisationsEnAttente; }
|
||||
|
||||
public BigDecimal getMontantDu() { return montantDu; }
|
||||
public void setMontantDu(BigDecimal montantDu) { this.montantDu = montantDu; }
|
||||
|
||||
public BigDecimal getTotalVerse() { return totalVerse; }
|
||||
public void setTotalVerse(BigDecimal totalVerse) { this.totalVerse = totalVerse; }
|
||||
|
||||
public int getProgressionAnnuelle() { return progressionAnnuelle; }
|
||||
public void setProgressionAnnuelle(int progressionAnnuelle) { this.progressionAnnuelle = progressionAnnuelle; }
|
||||
|
||||
public String getAnneeFilter() { return anneeFilter; }
|
||||
public void setAnneeFilter(String anneeFilter) { this.anneeFilter = anneeFilter; }
|
||||
|
||||
public String getStatutFilter() { return statutFilter; }
|
||||
public void setStatutFilter(String statutFilter) { this.statutFilter = statutFilter; }
|
||||
|
||||
public String getTypeFilter() { return typeFilter; }
|
||||
public void setTypeFilter(String typeFilter) { this.typeFilter = typeFilter; }
|
||||
|
||||
public List<Cotisation> getCotisations() { return cotisations; }
|
||||
public void setCotisations(List<Cotisation> cotisations) { this.cotisations = cotisations; }
|
||||
|
||||
public List<Echeance> getProchainesEcheances() { return prochainesEcheances; }
|
||||
public void setProchainesEcheances(List<Echeance> prochainesEcheances) { this.prochainesEcheances = prochainesEcheances; }
|
||||
|
||||
public Object getCotisationSelectionnee() { return cotisationSelectionnee; }
|
||||
public void setCotisationSelectionnee(Object cotisationSelectionnee) { this.cotisationSelectionnee = cotisationSelectionnee; }
|
||||
|
||||
public List<Cotisation> getCotisationsImpayees() { return cotisationsImpayees; }
|
||||
public void setCotisationsImpayees(List<Cotisation> cotisationsImpayees) { this.cotisationsImpayees = cotisationsImpayees; }
|
||||
|
||||
public String getModePaiementChoisi() { return modePaiementChoisi; }
|
||||
public void setModePaiementChoisi(String modePaiementChoisi) { this.modePaiementChoisi = modePaiementChoisi; }
|
||||
|
||||
public String getNumeroWave() { return numeroWave; }
|
||||
public void setNumeroWave(String numeroWave) { this.numeroWave = numeroWave; }
|
||||
|
||||
public String getCommentairePaiement() { return commentairePaiement; }
|
||||
public void setCommentairePaiement(String commentairePaiement) { this.commentairePaiement = commentairePaiement; }
|
||||
|
||||
public BigDecimal getMontantAPayer() { return montantAPayer; }
|
||||
public void setMontantAPayer(BigDecimal montantAPayer) { this.montantAPayer = montantAPayer; }
|
||||
|
||||
public String getBanqueAssociation() { return banqueAssociation; }
|
||||
public void setBanqueAssociation(String banqueAssociation) { this.banqueAssociation = banqueAssociation; }
|
||||
|
||||
public String getIbanAssociation() { return ibanAssociation; }
|
||||
public void setIbanAssociation(String ibanAssociation) { this.ibanAssociation = ibanAssociation; }
|
||||
|
||||
public String getNumeroWaveAuto() { return numeroWaveAuto; }
|
||||
public void setNumeroWaveAuto(String numeroWaveAuto) { this.numeroWaveAuto = numeroWaveAuto; }
|
||||
|
||||
public int getJourPrelevement() { return jourPrelevement; }
|
||||
public void setJourPrelevement(int jourPrelevement) { this.jourPrelevement = jourPrelevement; }
|
||||
|
||||
public boolean isNotificationSMS() { return notificationSMS; }
|
||||
public void setNotificationSMS(boolean notificationSMS) { this.notificationSMS = notificationSMS; }
|
||||
|
||||
public String getCotisationMensuelle() { return cotisationMensuelle; }
|
||||
public void setCotisationMensuelle(String cotisationMensuelle) { this.cotisationMensuelle = cotisationMensuelle; }
|
||||
|
||||
public BigDecimal getTotalPayePeriode() { return totalPayePeriode; }
|
||||
public void setTotalPayePeriode(BigDecimal totalPayePeriode) { this.totalPayePeriode = totalPayePeriode; }
|
||||
|
||||
public BigDecimal getTotalEnAttentePeriode() { return totalEnAttentePeriode; }
|
||||
public void setTotalEnAttentePeriode(BigDecimal totalEnAttentePeriode) { this.totalEnAttentePeriode = totalEnAttentePeriode; }
|
||||
|
||||
public BigDecimal getTotalEnRetardPeriode() { return totalEnRetardPeriode; }
|
||||
public void setTotalEnRetardPeriode(BigDecimal totalEnRetardPeriode) { this.totalEnRetardPeriode = totalEnRetardPeriode; }
|
||||
|
||||
public int getTauxConformite() { return tauxConformite; }
|
||||
public void setTauxConformite(int tauxConformite) { this.tauxConformite = tauxConformite; }
|
||||
|
||||
public String getStatutMembre() { return statutMembre; }
|
||||
public void setStatutMembre(String statutMembre) { this.statutMembre = statutMembre; }
|
||||
|
||||
public String getTypeMembre() { return typeMembre; }
|
||||
public void setTypeMembre(String typeMembre) { this.typeMembre = typeMembre; }
|
||||
|
||||
public String getStatutSeverity() { return statutSeverity; }
|
||||
public void setStatutSeverity(String statutSeverity) { this.statutSeverity = statutSeverity; }
|
||||
|
||||
public int getScorePonctualite() { return scorePonctualite; }
|
||||
public void setScorePonctualite(int scorePonctualite) { this.scorePonctualite = scorePonctualite; }
|
||||
|
||||
public String getCommentairePonctualite() { return commentairePonctualite; }
|
||||
public void setCommentairePonctualite(String commentairePonctualite) { this.commentairePonctualite = commentairePonctualite; }
|
||||
|
||||
public boolean isPeutPayerWave() { return true; }
|
||||
|
||||
// Méthodes pour les charts
|
||||
public Object getHistoriquePaiementsChart() {
|
||||
// Retourner un objet chart model vide pour l'instant
|
||||
return null;
|
||||
}
|
||||
|
||||
// Classes internes pour les données
|
||||
public static class Cotisation {
|
||||
private String reference;
|
||||
private String libelle;
|
||||
private String periode;
|
||||
private String type;
|
||||
private BigDecimal montant;
|
||||
private String statut;
|
||||
private LocalDate dateEcheance;
|
||||
private LocalDate datePaiement;
|
||||
private String modePaiement;
|
||||
|
||||
// Getters et setters
|
||||
public String getReference() { return reference; }
|
||||
public void setReference(String reference) { this.reference = reference; }
|
||||
|
||||
public String getLibelle() { return libelle; }
|
||||
public void setLibelle(String libelle) { this.libelle = libelle; }
|
||||
|
||||
public String getPeriode() { return periode; }
|
||||
public void setPeriode(String periode) { this.periode = periode; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public BigDecimal getMontant() { return montant; }
|
||||
public void setMontant(BigDecimal montant) { this.montant = montant; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public LocalDate getDateEcheance() { return dateEcheance; }
|
||||
public void setDateEcheance(LocalDate dateEcheance) { this.dateEcheance = dateEcheance; }
|
||||
|
||||
public LocalDate getDatePaiement() { return datePaiement; }
|
||||
public void setDatePaiement(LocalDate datePaiement) { this.datePaiement = datePaiement; }
|
||||
|
||||
public String getModePaiement() { return modePaiement; }
|
||||
public void setModePaiement(String modePaiement) { this.modePaiement = modePaiement; }
|
||||
|
||||
// Propriétés dérivées pour l'affichage
|
||||
public String getTypeSeverity() {
|
||||
return switch (type) {
|
||||
case "MENSUELLE" -> "info";
|
||||
case "SPECIALE" -> "warning";
|
||||
case "ADHESION" -> "success";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getTypeIcon() {
|
||||
return switch (type) {
|
||||
case "MENSUELLE" -> "pi-calendar";
|
||||
case "SPECIALE" -> "pi-star";
|
||||
case "ADHESION" -> "pi-user-plus";
|
||||
default -> "pi-circle";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutSeverity() {
|
||||
return switch (statut) {
|
||||
case "PAYEE", "PAYE" -> "success";
|
||||
case "EN_ATTENTE" -> "warning";
|
||||
case "EN_RETARD" -> "danger";
|
||||
case "PARTIELLEMENT_PAYEE" -> "info";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutIcon() {
|
||||
return switch (statut) {
|
||||
case "PAYEE", "PAYE" -> "pi-check";
|
||||
case "EN_ATTENTE" -> "pi-clock";
|
||||
case "EN_RETARD" -> "pi-exclamation-triangle";
|
||||
case "PARTIELLEMENT_PAYEE" -> "pi-check-circle";
|
||||
default -> "pi-circle";
|
||||
};
|
||||
}
|
||||
|
||||
public String getRetardColor() {
|
||||
return switch (statut) {
|
||||
case "EN_RETARD" -> "text-red-500";
|
||||
case "EN_ATTENTE" -> "text-orange-500";
|
||||
default -> "text-600";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutEcheance() {
|
||||
return switch (statut) {
|
||||
case "EN_RETARD" -> "En retard";
|
||||
case "EN_ATTENTE" -> "À venir";
|
||||
case "PAYEE", "PAYE" -> "Payée";
|
||||
case "PARTIELLEMENT_PAYEE" -> "Partiellement payée";
|
||||
default -> "Non payée";
|
||||
};
|
||||
}
|
||||
|
||||
public String getModePaiementIcon() {
|
||||
return switch (modePaiement != null ? modePaiement : "") {
|
||||
case "Wave Money" -> "pi-mobile";
|
||||
case "Virement" -> "pi-building";
|
||||
case "Espèces" -> "pi-money-bill";
|
||||
default -> "pi-circle";
|
||||
};
|
||||
}
|
||||
|
||||
public String getCouleurMontant() {
|
||||
return "text-900";
|
||||
}
|
||||
}
|
||||
|
||||
public static class Echeance {
|
||||
private String libelle;
|
||||
private String periode;
|
||||
private String montant;
|
||||
private String dateEcheance;
|
||||
private String urgence;
|
||||
private String couleurUrgence;
|
||||
|
||||
// Getters et setters
|
||||
public String getLibelle() { return libelle; }
|
||||
public void setLibelle(String libelle) { this.libelle = libelle; }
|
||||
|
||||
public String getPeriode() { return periode; }
|
||||
public void setPeriode(String periode) { this.periode = periode; }
|
||||
|
||||
public String getMontant() { return montant; }
|
||||
public void setMontant(String montant) { this.montant = montant; }
|
||||
|
||||
public String getDateEcheance() { return dateEcheance; }
|
||||
public void setDateEcheance(String dateEcheance) { this.dateEcheance = dateEcheance; }
|
||||
|
||||
public String getUrgence() { return urgence; }
|
||||
public void setUrgence(String urgence) { this.urgence = urgence; }
|
||||
|
||||
public String getCouleurUrgence() { return couleurUrgence; }
|
||||
public void setCouleurUrgence(String couleurUrgence) { this.couleurUrgence = couleurUrgence; }
|
||||
|
||||
public String getUrgenceSeverity() {
|
||||
return switch (urgence) {
|
||||
case "En retard" -> "danger";
|
||||
case "Bientôt" -> "warning";
|
||||
default -> "info";
|
||||
};
|
||||
}
|
||||
|
||||
public String getCouleurMontant() {
|
||||
return "text-900";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,416 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Named("membreDashboardBean")
|
||||
@SessionScoped
|
||||
public class MembreDashboardBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_MEMBRE_EVENEMENT = "membreEvenementPage";
|
||||
private static final String OUTCOME_MEMBRE_COTISATIONS = "membreCotisationsPage";
|
||||
|
||||
// Membre actuel
|
||||
private Membre membre;
|
||||
|
||||
// Statistiques
|
||||
private String statutCotisations;
|
||||
private int evenementsInscrits;
|
||||
private int aidesRecues;
|
||||
private int messagesNonLus;
|
||||
|
||||
// Progression
|
||||
private int cotisationsPayees;
|
||||
private int cotisationsTotales;
|
||||
private int progressionCotisations;
|
||||
private int tauxParticipation;
|
||||
private int evenementsAssistes;
|
||||
private String anciennete;
|
||||
private String dateAdhesionFormatee;
|
||||
|
||||
// Listes
|
||||
private List<Alerte> alertes = new ArrayList<>();
|
||||
private List<Evenement> prochainsEvenements = new ArrayList<>();
|
||||
private List<Rappel> rappels = new ArrayList<>();
|
||||
private List<Activite> activiteRecente = new ArrayList<>();
|
||||
|
||||
// État
|
||||
private boolean peutPayerCotisations;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initializeMembre();
|
||||
initializeStatistiques();
|
||||
initializeAlertes();
|
||||
initializeEvenements();
|
||||
initializeRappels();
|
||||
initializeActivite();
|
||||
}
|
||||
|
||||
private void initializeMembre() {
|
||||
membre = new Membre();
|
||||
membre.setPrenom("Jean");
|
||||
membre.setNom("Dupont");
|
||||
membre.setNumeroMembre("M240001");
|
||||
membre.setTypeMembre("Membre Actif");
|
||||
membre.setDateAdhesion("15/06/2020");
|
||||
membre.setPhotoUrl(null); // Pas de photo par défaut
|
||||
}
|
||||
|
||||
private void initializeStatistiques() {
|
||||
this.statutCotisations = "À jour";
|
||||
this.evenementsInscrits = 3;
|
||||
this.aidesRecues = 2;
|
||||
this.messagesNonLus = 5;
|
||||
this.cotisationsPayees = 10;
|
||||
this.cotisationsTotales = 12;
|
||||
this.progressionCotisations = 83;
|
||||
this.tauxParticipation = 75;
|
||||
this.evenementsAssistes = 15;
|
||||
this.anciennete = "4 ans";
|
||||
this.dateAdhesionFormatee = "15 juin 2020";
|
||||
this.peutPayerCotisations = true;
|
||||
}
|
||||
|
||||
private void initializeAlertes() {
|
||||
Alerte alerte1 = new Alerte();
|
||||
alerte1.setTitre("Cotisation de décembre");
|
||||
alerte1.setMessage("Votre cotisation mensuelle de décembre est due le 15/12/2024");
|
||||
alerte1.setDateRelative("Il y a 2 jours");
|
||||
alerte1.setIcone("pi-dollar");
|
||||
alerte1.setCouleurIcone("text-orange-500");
|
||||
alerte1.setCouleurFond("rgba(255, 193, 7, 0.1)");
|
||||
alerte1.setCouleurBordure("border-orange-500");
|
||||
alertes.add(alerte1);
|
||||
|
||||
Alerte alerte2 = new Alerte();
|
||||
alerte2.setTitre("Nouvel événement");
|
||||
alerte2.setMessage("Assemblée générale prévue le 28 décembre 2024");
|
||||
alerte2.setDateRelative("Hier");
|
||||
alerte2.setIcone("pi-calendar");
|
||||
alerte2.setCouleurIcone("text-blue-500");
|
||||
alerte2.setCouleurFond("rgba(13, 110, 253, 0.1)");
|
||||
alerte2.setCouleurBordure("border-blue-500");
|
||||
alertes.add(alerte2);
|
||||
}
|
||||
|
||||
private void initializeEvenements() {
|
||||
Evenement event1 = new Evenement();
|
||||
event1.setTitre("Assemblée Générale Ordinaire");
|
||||
event1.setDateComplete("Samedi 28 décembre 2024 - 09h00");
|
||||
event1.setLieu("Siège de l'association");
|
||||
event1.setPrixFormate("Gratuit");
|
||||
event1.setNombreParticipants("45 inscrits");
|
||||
event1.setStatutInscription("Inscrit");
|
||||
event1.setSeverityInscription("success");
|
||||
event1.setIconeType("pi-users");
|
||||
event1.setCouleurCategorie("bg-blue-500");
|
||||
event1.setCouleurBordure("border-blue-500");
|
||||
event1.setPeutAnnuler(true);
|
||||
prochainsEvenements.add(event1);
|
||||
|
||||
Evenement event2 = new Evenement();
|
||||
event2.setTitre("Formation premiers secours");
|
||||
event2.setDateComplete("Dimanche 15 janvier 2025 - 14h00");
|
||||
event2.setLieu("Centre de formation");
|
||||
event2.setPrixFormate("2,500 FCFA");
|
||||
event2.setNombreParticipants("12 inscrits");
|
||||
event2.setStatutInscription("En attente");
|
||||
event2.setSeverityInscription("warning");
|
||||
event2.setIconeType("pi-heart");
|
||||
event2.setCouleurCategorie("bg-red-500");
|
||||
event2.setCouleurBordure("border-red-500");
|
||||
event2.setPeutAnnuler(false);
|
||||
prochainsEvenements.add(event2);
|
||||
}
|
||||
|
||||
private void initializeRappels() {
|
||||
Rappel rappel1 = new Rappel();
|
||||
rappel1.setTitre("Cotisation décembre");
|
||||
rappel1.setEcheance("Dans 3 jours");
|
||||
rappel1.setIcone("pi-dollar");
|
||||
rappel1.setCouleurIcone("text-orange-500");
|
||||
rappel1.setCouleurFond("surface-100");
|
||||
rappels.add(rappel1);
|
||||
|
||||
Rappel rappel2 = new Rappel();
|
||||
rappel2.setTitre("Renouvellement adhésion");
|
||||
rappel2.setEcheance("Dans 2 mois");
|
||||
rappel2.setIcone("pi-id-card");
|
||||
rappel2.setCouleurIcone("text-blue-500");
|
||||
rappel2.setCouleurFond("surface-100");
|
||||
rappels.add(rappel2);
|
||||
}
|
||||
|
||||
private void initializeActivite() {
|
||||
Activite activite1 = new Activite();
|
||||
activite1.setTitre("Cotisation payée");
|
||||
activite1.setDescription("Cotisation de novembre 2024 - 5,000 FCFA");
|
||||
activite1.setDateRelative("Il y a 5 jours");
|
||||
activite1.setIcone("pi-check");
|
||||
activite1.setCouleurCategorie("bg-green-500");
|
||||
activiteRecente.add(activite1);
|
||||
|
||||
Activite activite2 = new Activite();
|
||||
activite2.setTitre("Participation événement");
|
||||
activite2.setDescription("Sortie culturelle au musée");
|
||||
activite2.setDateRelative("Il y a 1 semaine");
|
||||
activite2.setIcone("pi-calendar");
|
||||
activite2.setCouleurCategorie("bg-blue-500");
|
||||
activiteRecente.add(activite2);
|
||||
|
||||
Activite activite3 = new Activite();
|
||||
activite3.setTitre("Inscription événement");
|
||||
activite3.setDescription("Assemblée générale ordinaire");
|
||||
activite3.setDateRelative("Il y a 2 semaines");
|
||||
activite3.setIcone("pi-user-plus");
|
||||
activite3.setCouleurCategorie("bg-purple-500");
|
||||
activiteRecente.add(activite3);
|
||||
}
|
||||
|
||||
// Actions
|
||||
public void marquerLue(Alerte alerte) {
|
||||
alertes.remove(alerte);
|
||||
}
|
||||
|
||||
public String voirEvenement(Evenement evenement) {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_MEMBRE_EVENEMENT + "?id=" + evenement.getTitre() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
public void annulerInscription(Evenement evenement) {
|
||||
evenement.setStatutInscription("Annulé");
|
||||
evenement.setSeverityInscription("danger");
|
||||
evenement.setPeutAnnuler(false);
|
||||
}
|
||||
|
||||
public String payerCotisations() {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_MEMBRE_COTISATIONS + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public Membre getMembre() { return membre; }
|
||||
public void setMembre(Membre membre) { this.membre = membre; }
|
||||
|
||||
public String getStatutCotisations() { return statutCotisations; }
|
||||
public void setStatutCotisations(String statutCotisations) { this.statutCotisations = statutCotisations; }
|
||||
|
||||
public int getEvenementsInscrits() { return evenementsInscrits; }
|
||||
public void setEvenementsInscrits(int evenementsInscrits) { this.evenementsInscrits = evenementsInscrits; }
|
||||
|
||||
public int getAidesRecues() { return aidesRecues; }
|
||||
public void setAidesRecues(int aidesRecues) { this.aidesRecues = aidesRecues; }
|
||||
|
||||
public int getMessagesNonLus() { return messagesNonLus; }
|
||||
public void setMessagesNonLus(int messagesNonLus) { this.messagesNonLus = messagesNonLus; }
|
||||
|
||||
public int getCotisationsPayees() { return cotisationsPayees; }
|
||||
public void setCotisationsPayees(int cotisationsPayees) { this.cotisationsPayees = cotisationsPayees; }
|
||||
|
||||
public int getCotisationsTotales() { return cotisationsTotales; }
|
||||
public void setCotisationsTotales(int cotisationsTotales) { this.cotisationsTotales = cotisationsTotales; }
|
||||
|
||||
public int getProgressionCotisations() { return progressionCotisations; }
|
||||
public void setProgressionCotisations(int progressionCotisations) { this.progressionCotisations = progressionCotisations; }
|
||||
|
||||
public int getTauxParticipation() { return tauxParticipation; }
|
||||
public void setTauxParticipation(int tauxParticipation) { this.tauxParticipation = tauxParticipation; }
|
||||
|
||||
public int getEvenementsAssistes() { return evenementsAssistes; }
|
||||
public void setEvenementsAssistes(int evenementsAssistes) { this.evenementsAssistes = evenementsAssistes; }
|
||||
|
||||
public String getAnciennete() { return anciennete; }
|
||||
public void setAnciennete(String anciennete) { this.anciennete = anciennete; }
|
||||
|
||||
public String getDateAdhesionFormatee() { return dateAdhesionFormatee; }
|
||||
public void setDateAdhesionFormatee(String dateAdhesionFormatee) { this.dateAdhesionFormatee = dateAdhesionFormatee; }
|
||||
|
||||
public List<Alerte> getAlertes() { return alertes; }
|
||||
public void setAlertes(List<Alerte> alertes) { this.alertes = alertes; }
|
||||
|
||||
public List<Evenement> getProchainsEvenements() { return prochainsEvenements; }
|
||||
public void setProchainsEvenements(List<Evenement> prochainsEvenements) { this.prochainsEvenements = prochainsEvenements; }
|
||||
|
||||
public List<Rappel> getRappels() { return rappels; }
|
||||
public void setRappels(List<Rappel> rappels) { this.rappels = rappels; }
|
||||
|
||||
public List<Activite> getActiviteRecente() { return activiteRecente; }
|
||||
public void setActiviteRecente(List<Activite> activiteRecente) { this.activiteRecente = activiteRecente; }
|
||||
|
||||
public boolean isPeutPayerCotisations() { return peutPayerCotisations; }
|
||||
public void setPeutPayerCotisations(boolean peutPayerCotisations) { this.peutPayerCotisations = peutPayerCotisations; }
|
||||
|
||||
// Classes internes
|
||||
public static class Membre {
|
||||
private String prenom;
|
||||
private String nom;
|
||||
private String numeroMembre;
|
||||
private String typeMembre;
|
||||
private String dateAdhesion;
|
||||
private String photoUrl;
|
||||
|
||||
public String getPrenom() { return prenom; }
|
||||
public void setPrenom(String prenom) { this.prenom = prenom; }
|
||||
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public String getNumeroMembre() { return numeroMembre; }
|
||||
public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
|
||||
|
||||
public String getTypeMembre() { return typeMembre; }
|
||||
public void setTypeMembre(String typeMembre) { this.typeMembre = typeMembre; }
|
||||
|
||||
public String getDateAdhesion() { return dateAdhesion; }
|
||||
public void setDateAdhesion(String dateAdhesion) { this.dateAdhesion = dateAdhesion; }
|
||||
|
||||
public String getPhotoUrl() { return photoUrl; }
|
||||
public void setPhotoUrl(String photoUrl) { this.photoUrl = photoUrl; }
|
||||
|
||||
public String getInitiales() {
|
||||
return (prenom != null ? prenom.substring(0, 1) : "") +
|
||||
(nom != null ? nom.substring(0, 1) : "");
|
||||
}
|
||||
}
|
||||
|
||||
public static class Alerte {
|
||||
private String titre;
|
||||
private String message;
|
||||
private String dateRelative;
|
||||
private String icone;
|
||||
private String couleurIcone;
|
||||
private String couleurFond;
|
||||
private String couleurBordure;
|
||||
|
||||
// Getters et setters
|
||||
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 String getDateRelative() { return dateRelative; }
|
||||
public void setDateRelative(String dateRelative) { this.dateRelative = dateRelative; }
|
||||
|
||||
public String getIcone() { return icone; }
|
||||
public void setIcone(String icone) { this.icone = icone; }
|
||||
|
||||
public String getCouleurIcone() { return couleurIcone; }
|
||||
public void setCouleurIcone(String couleurIcone) { this.couleurIcone = couleurIcone; }
|
||||
|
||||
public String getCouleurFond() { return couleurFond; }
|
||||
public void setCouleurFond(String couleurFond) { this.couleurFond = couleurFond; }
|
||||
|
||||
public String getCouleurBordure() { return couleurBordure; }
|
||||
public void setCouleurBordure(String couleurBordure) { this.couleurBordure = couleurBordure; }
|
||||
}
|
||||
|
||||
public static class Evenement {
|
||||
private String titre;
|
||||
private String dateComplete;
|
||||
private String lieu;
|
||||
private String prixFormate;
|
||||
private String nombreParticipants;
|
||||
private String statutInscription;
|
||||
private String severityInscription;
|
||||
private String iconeType;
|
||||
private String couleurCategorie;
|
||||
private String couleurBordure;
|
||||
private boolean peutAnnuler;
|
||||
|
||||
// Getters et setters
|
||||
public String getTitre() { return titre; }
|
||||
public void setTitre(String titre) { this.titre = titre; }
|
||||
|
||||
public String getDateComplete() { return dateComplete; }
|
||||
public void setDateComplete(String dateComplete) { this.dateComplete = dateComplete; }
|
||||
|
||||
public String getLieu() { return lieu; }
|
||||
public void setLieu(String lieu) { this.lieu = lieu; }
|
||||
|
||||
public String getPrixFormate() { return prixFormate; }
|
||||
public void setPrixFormate(String prixFormate) { this.prixFormate = prixFormate; }
|
||||
|
||||
public String getNombreParticipants() { return nombreParticipants; }
|
||||
public void setNombreParticipants(String nombreParticipants) { this.nombreParticipants = nombreParticipants; }
|
||||
|
||||
public String getStatutInscription() { return statutInscription; }
|
||||
public void setStatutInscription(String statutInscription) { this.statutInscription = statutInscription; }
|
||||
|
||||
public String getSeverityInscription() { return severityInscription; }
|
||||
public void setSeverityInscription(String severityInscription) { this.severityInscription = severityInscription; }
|
||||
|
||||
public String getIconeType() { return iconeType; }
|
||||
public void setIconeType(String iconeType) { this.iconeType = iconeType; }
|
||||
|
||||
public String getCouleurCategorie() { return couleurCategorie; }
|
||||
public void setCouleurCategorie(String couleurCategorie) { this.couleurCategorie = couleurCategorie; }
|
||||
|
||||
public String getCouleurBordure() { return couleurBordure; }
|
||||
public void setCouleurBordure(String couleurBordure) { this.couleurBordure = couleurBordure; }
|
||||
|
||||
public boolean isPeutAnnuler() { return peutAnnuler; }
|
||||
public void setPeutAnnuler(boolean peutAnnuler) { this.peutAnnuler = peutAnnuler; }
|
||||
|
||||
public String getCouleurPrix() {
|
||||
return prixFormate.equals("Gratuit") ? "text-green-500" : "text-blue-500";
|
||||
}
|
||||
}
|
||||
|
||||
public static class Rappel {
|
||||
private String titre;
|
||||
private String echeance;
|
||||
private String icone;
|
||||
private String couleurIcone;
|
||||
private String couleurFond;
|
||||
|
||||
// Getters et setters
|
||||
public String getTitre() { return titre; }
|
||||
public void setTitre(String titre) { this.titre = titre; }
|
||||
|
||||
public String getEcheance() { return echeance; }
|
||||
public void setEcheance(String echeance) { this.echeance = echeance; }
|
||||
|
||||
public String getIcone() { return icone; }
|
||||
public void setIcone(String icone) { this.icone = icone; }
|
||||
|
||||
public String getCouleurIcone() { return couleurIcone; }
|
||||
public void setCouleurIcone(String couleurIcone) { this.couleurIcone = couleurIcone; }
|
||||
|
||||
public String getCouleurFond() { return couleurFond; }
|
||||
public void setCouleurFond(String couleurFond) { this.couleurFond = couleurFond; }
|
||||
}
|
||||
|
||||
public static class Activite {
|
||||
private String titre;
|
||||
private String description;
|
||||
private String dateRelative;
|
||||
private String icone;
|
||||
private String couleurCategorie;
|
||||
|
||||
// Getters et setters
|
||||
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 getDateRelative() { return dateRelative; }
|
||||
public void setDateRelative(String dateRelative) { this.dateRelative = dateRelative; }
|
||||
|
||||
public String getIcone() { return icone; }
|
||||
public void setIcone(String icone) { this.icone = icone; }
|
||||
|
||||
public String getCouleurCategorie() { return couleurCategorie; }
|
||||
public void setCouleurCategorie(String couleurCategorie) { this.couleurCategorie = couleurCategorie; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.service.MembreService;
|
||||
import dev.lions.unionflow.client.service.AssociationService;
|
||||
import dev.lions.unionflow.server.api.dto.organisation.OrganisationDTO;
|
||||
import dev.lions.unionflow.client.dto.AssociationDTO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import jakarta.faces.view.ViewScoped;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.faces.application.FacesMessage;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("membreExportBean")
|
||||
@ViewScoped
|
||||
@Getter
|
||||
@Setter
|
||||
public class MembreExportBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(MembreExportBean.class.getName());
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
MembreService membreService;
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
AssociationService associationService;
|
||||
|
||||
// Configuration de l'export
|
||||
private String formatExport = "EXCEL";
|
||||
private String scopeExport = "TOUS";
|
||||
private List<String> colonnesExport = new ArrayList<>();
|
||||
|
||||
// Filtres
|
||||
private String statutFilter = "";
|
||||
private String typeFilter = "";
|
||||
private UUID organisationId;
|
||||
private LocalDate dateAdhesionDebut;
|
||||
private LocalDate dateAdhesionFin;
|
||||
|
||||
// Options d'export
|
||||
private boolean inclureHeaders = true;
|
||||
private boolean formaterDates = true;
|
||||
private boolean inclureStatistiques = false;
|
||||
private boolean chiffrerDonnees = false;
|
||||
private String motDePasseExport = "";
|
||||
|
||||
// Organisations disponibles
|
||||
private List<OrganisationDTO> organisationsDisponibles = new ArrayList<>();
|
||||
|
||||
// Statistiques
|
||||
private int totalMembres = 0;
|
||||
private int membresActifs = 0;
|
||||
private int membresInactifs = 0;
|
||||
private int nombreMembresAExporter = 0;
|
||||
|
||||
// Historique des exports
|
||||
private List<ExportHistorique> historiqueExports = new ArrayList<>();
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
chargerOrganisations();
|
||||
chargerStatistiques();
|
||||
initialiserColonnesExport();
|
||||
}
|
||||
|
||||
private void chargerOrganisations() {
|
||||
organisationsDisponibles = new ArrayList<>();
|
||||
try {
|
||||
List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
|
||||
for (AssociationDTO assoc : associations) {
|
||||
OrganisationDTO org = new OrganisationDTO();
|
||||
org.setId(assoc.getId());
|
||||
org.setNom(assoc.getNom());
|
||||
org.setVille(assoc.getVille());
|
||||
organisationsDisponibles.add(org);
|
||||
}
|
||||
LOGGER.info("Chargement de " + organisationsDisponibles.size() + " organisations disponibles");
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des organisations: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void chargerStatistiques() {
|
||||
try {
|
||||
MembreService.StatistiquesMembreDTO stats = membreService.obtenirStatistiques();
|
||||
if (stats != null) {
|
||||
totalMembres = stats.getTotalMembres() != null ? stats.getTotalMembres().intValue() : 0;
|
||||
membresActifs = stats.getMembresActifs() != null ? stats.getMembresActifs().intValue() : 0;
|
||||
membresInactifs = stats.getMembresInactifs() != null ? stats.getMembresInactifs().intValue() : 0;
|
||||
}
|
||||
actualiserCompteur();
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des statistiques: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void initialiserColonnesExport() {
|
||||
colonnesExport = new ArrayList<>();
|
||||
colonnesExport.add("PERSO");
|
||||
colonnesExport.add("CONTACT");
|
||||
colonnesExport.add("ADHESION");
|
||||
}
|
||||
|
||||
public void actualiserCompteur() {
|
||||
actualiserCompteur(null);
|
||||
}
|
||||
|
||||
public void actualiserCompteur(jakarta.faces.event.AjaxBehaviorEvent event) {
|
||||
try {
|
||||
// Appel au backend pour obtenir le comptage exact selon les filtres
|
||||
String statut = null;
|
||||
if ("ACTIFS".equals(scopeExport)) {
|
||||
statut = "ACTIF";
|
||||
} else if ("INACTIFS".equals(scopeExport)) {
|
||||
statut = "INACTIF";
|
||||
} else if (statutFilter != null && !statutFilter.isEmpty()) {
|
||||
statut = statutFilter;
|
||||
}
|
||||
|
||||
String dateAdhesionDebutStr = dateAdhesionDebut != null ? dateAdhesionDebut.toString() : null;
|
||||
String dateAdhesionFinStr = dateAdhesionFin != null ? dateAdhesionFin.toString() : null;
|
||||
|
||||
Long count = membreService.compterMembresPourExport(
|
||||
organisationId,
|
||||
statut,
|
||||
typeFilter != null && !typeFilter.isEmpty() ? typeFilter : null,
|
||||
dateAdhesionDebutStr,
|
||||
dateAdhesionFinStr
|
||||
);
|
||||
|
||||
nombreMembresAExporter = count != null ? count.intValue() : 0;
|
||||
|
||||
LOGGER.info("Comptage des membres pour export: " + nombreMembresAExporter);
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'actualisation du compteur: " + e.getMessage());
|
||||
// Fallback sur estimation basée sur les statistiques
|
||||
if ("TOUS".equals(scopeExport)) {
|
||||
nombreMembresAExporter = totalMembres;
|
||||
} else if ("ACTIFS".equals(scopeExport)) {
|
||||
nombreMembresAExporter = membresActifs;
|
||||
} else if ("INACTIFS".equals(scopeExport)) {
|
||||
nombreMembresAExporter = membresInactifs;
|
||||
} else {
|
||||
nombreMembresAExporter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void exporterMembres() {
|
||||
if (colonnesExport == null || colonnesExport.isEmpty()) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Veuillez sélectionner au moins une catégorie de colonnes à exporter"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (nombreMembresAExporter == 0) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Aucun membre ne correspond aux critères sélectionnés"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
LOGGER.info("Export des membres: format=" + formatExport + ", nombre=" + nombreMembresAExporter);
|
||||
|
||||
String dateAdhesionDebutStr = dateAdhesionDebut != null ? dateAdhesionDebut.toString() : null;
|
||||
String dateAdhesionFinStr = dateAdhesionFin != null ? dateAdhesionFin.toString() : null;
|
||||
|
||||
// Générer un mot de passe aléatoire si le chiffrement est demandé
|
||||
String motDePasse = null;
|
||||
if (chiffrerDonnees) {
|
||||
if (motDePasseExport != null && !motDePasseExport.trim().isEmpty()) {
|
||||
motDePasse = motDePasseExport;
|
||||
} else {
|
||||
// Générer un mot de passe aléatoire de 12 caractères
|
||||
motDePasse = genererMotDePasseAleatoire();
|
||||
}
|
||||
}
|
||||
|
||||
byte[] exportData = membreService.exporterExcel(
|
||||
formatExport,
|
||||
organisationId,
|
||||
statutFilter,
|
||||
typeFilter,
|
||||
dateAdhesionDebutStr,
|
||||
dateAdhesionFinStr,
|
||||
colonnesExport,
|
||||
inclureHeaders,
|
||||
formaterDates,
|
||||
inclureStatistiques && "EXCEL".equals(formatExport), // Statistiques uniquement pour Excel
|
||||
motDePasse
|
||||
);
|
||||
|
||||
FacesContext facesContext = FacesContext.getCurrentInstance();
|
||||
HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
|
||||
|
||||
response.reset();
|
||||
String contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
||||
String extension = "xlsx";
|
||||
|
||||
if ("CSV".equals(formatExport)) {
|
||||
contentType = "text/csv";
|
||||
extension = "csv";
|
||||
}
|
||||
|
||||
response.setContentType(contentType);
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"membres_export_" +
|
||||
LocalDate.now() + "." + extension + "\"");
|
||||
response.setContentLength(exportData.length);
|
||||
|
||||
response.getOutputStream().write(exportData);
|
||||
response.getOutputStream().flush();
|
||||
facesContext.responseComplete();
|
||||
|
||||
// Ajouter à l'historique
|
||||
ExportHistorique historique = new ExportHistorique();
|
||||
historique.setDate(LocalDateTime.now());
|
||||
historique.setFormat(formatExport);
|
||||
historique.setNombreMembres(nombreMembresAExporter);
|
||||
historique.setTaille(formatTaille(exportData.length));
|
||||
historiqueExports.add(0, historique); // Ajouter au début
|
||||
|
||||
// Afficher le mot de passe si le chiffrement était demandé
|
||||
if (chiffrerDonnees && motDePasse != null) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Fichier protégé",
|
||||
"Le fichier a été protégé par un mot de passe. " +
|
||||
"Mot de passe: " + motDePasse +
|
||||
" (Note: Le fichier est protégé contre la modification, mais peut toujours être ouvert)"));
|
||||
}
|
||||
|
||||
LOGGER.info("Export généré et téléchargé: " + exportData.length + " bytes");
|
||||
} catch (IOException e) {
|
||||
LOGGER.severe("Erreur lors du téléchargement de l'export: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de télécharger l'export: " + e.getMessage()));
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'export: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible d'exporter les membres: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
private String formatTaille(long bytes) {
|
||||
if (bytes < 1024) {
|
||||
return bytes + " B";
|
||||
} else if (bytes < 1024 * 1024) {
|
||||
return String.format("%.2f KB", bytes / 1024.0);
|
||||
} else {
|
||||
return String.format("%.2f MB", bytes / (1024.0 * 1024.0));
|
||||
}
|
||||
}
|
||||
|
||||
public void telechargerExport(ExportHistorique export) {
|
||||
// L'historique est stocké localement dans la session, pas de téléchargement depuis le serveur
|
||||
LOGGER.info("Export historique consulté: " + export.getDate() + " - " + export.getFormat());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Information",
|
||||
"L'export du " + export.getDate().format(java.time.format.DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm")) +
|
||||
" n'est plus disponible. Veuillez générer un nouvel export."));
|
||||
}
|
||||
|
||||
private String genererMotDePasseAleatoire() {
|
||||
String caracteres = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%&*";
|
||||
java.util.Random random = new java.util.Random();
|
||||
StringBuilder motDePasse = new StringBuilder(12);
|
||||
for (int i = 0; i < 12; i++) {
|
||||
motDePasse.append(caracteres.charAt(random.nextInt(caracteres.length())));
|
||||
}
|
||||
return motDePasse.toString();
|
||||
}
|
||||
|
||||
public void reinitialiser() {
|
||||
formatExport = "EXCEL";
|
||||
scopeExport = "TOUS";
|
||||
colonnesExport = new ArrayList<>();
|
||||
colonnesExport.add("PERSO");
|
||||
colonnesExport.add("CONTACT");
|
||||
colonnesExport.add("ADHESION");
|
||||
statutFilter = "";
|
||||
typeFilter = "";
|
||||
organisationId = null;
|
||||
dateAdhesionDebut = null;
|
||||
dateAdhesionFin = null;
|
||||
inclureHeaders = true;
|
||||
formaterDates = true;
|
||||
inclureStatistiques = false;
|
||||
chiffrerDonnees = false;
|
||||
motDePasseExport = "";
|
||||
actualiserCompteur();
|
||||
}
|
||||
|
||||
// Classe interne pour l'historique des exports
|
||||
@Getter
|
||||
@Setter
|
||||
public static class ExportHistorique implements Serializable {
|
||||
private LocalDateTime date;
|
||||
private String format;
|
||||
private int nombreMembres;
|
||||
private String taille;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.service.MembreService;
|
||||
import dev.lions.unionflow.client.service.MembreImportMultipartForm;
|
||||
import dev.lions.unionflow.client.service.AssociationService;
|
||||
import dev.lions.unionflow.server.api.dto.organisation.OrganisationDTO;
|
||||
import dev.lions.unionflow.client.dto.AssociationDTO;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import jakarta.faces.view.ViewScoped;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.faces.application.FacesMessage;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import org.primefaces.event.FileUploadEvent;
|
||||
import org.primefaces.model.file.UploadedFile;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("membreImportBean")
|
||||
@ViewScoped
|
||||
@Getter
|
||||
@Setter
|
||||
public class MembreImportBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(MembreImportBean.class.getName());
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
MembreService membreService;
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
AssociationService associationService;
|
||||
|
||||
// Fichier à importer
|
||||
private UploadedFile fichierImport;
|
||||
|
||||
// Options d'import
|
||||
private boolean mettreAJourExistants = false;
|
||||
private boolean ignorerErreurs = false;
|
||||
private UUID organisationId;
|
||||
private String typeMembreDefaut = "";
|
||||
|
||||
// Organisations disponibles
|
||||
private List<OrganisationDTO> organisationsDisponibles = new ArrayList<>();
|
||||
|
||||
// Résultat de l'import
|
||||
private ResultatImport resultatImport;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
chargerOrganisations();
|
||||
}
|
||||
|
||||
private void chargerOrganisations() {
|
||||
organisationsDisponibles = new ArrayList<>();
|
||||
try {
|
||||
List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
|
||||
for (AssociationDTO assoc : associations) {
|
||||
OrganisationDTO org = new OrganisationDTO();
|
||||
org.setId(assoc.getId());
|
||||
org.setNom(assoc.getNom());
|
||||
org.setVille(assoc.getVille());
|
||||
organisationsDisponibles.add(org);
|
||||
}
|
||||
LOGGER.info("Chargement de " + organisationsDisponibles.size() + " organisations disponibles");
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des organisations: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gère l'upload du fichier (appelé par PrimeFaces FileUpload)
|
||||
*/
|
||||
public void handleFileUpload(FileUploadEvent event) {
|
||||
fichierImport = event.getFile();
|
||||
LOGGER.info("Fichier sélectionné: " + (fichierImport != null ? fichierImport.getFileName() : "null"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Lance l'import des membres
|
||||
*/
|
||||
public void importerMembres() {
|
||||
if (fichierImport == null || fichierImport.getFileName() == null || fichierImport.getFileName().isEmpty()) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Veuillez sélectionner un fichier à importer"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
LOGGER.info("Import du fichier: " + fichierImport.getFileName());
|
||||
|
||||
byte[] fileContent = fichierImport.getContent();
|
||||
String fileName = fichierImport.getFileName();
|
||||
|
||||
// Créer le formulaire multipart
|
||||
MembreImportMultipartForm form = new MembreImportMultipartForm();
|
||||
form.file = fileContent;
|
||||
form.fileName = fileName;
|
||||
form.organisationId = organisationId;
|
||||
form.typeMembreDefaut = typeMembreDefaut != null && !typeMembreDefaut.isEmpty() ? typeMembreDefaut : "ACTIF";
|
||||
form.mettreAJourExistants = mettreAJourExistants;
|
||||
form.ignorerErreurs = ignorerErreurs;
|
||||
|
||||
// Appeler le service REST
|
||||
MembreService.ResultatImportDTO result = membreService.importerDonnees(form);
|
||||
|
||||
// Convertir le résultat
|
||||
resultatImport = new ResultatImport();
|
||||
resultatImport.setTotalTraite(result.getTotalLignes() != null ? result.getTotalLignes() : 0);
|
||||
resultatImport.setReussis(result.getLignesTraitees() != null ? result.getLignesTraitees() : 0);
|
||||
resultatImport.setEchecs(result.getLignesErreur() != null ? result.getLignesErreur() : 0);
|
||||
resultatImport.setIgnores(0);
|
||||
|
||||
// Convertir les erreurs
|
||||
List<ErreurImport> erreursList = new ArrayList<>();
|
||||
if (result.getErreurs() != null) {
|
||||
for (int i = 0; i < result.getErreurs().size(); i++) {
|
||||
ErreurImport erreur = new ErreurImport();
|
||||
erreur.setLigne(i + 1);
|
||||
erreur.setMessage(result.getErreurs().get(i));
|
||||
erreursList.add(erreur);
|
||||
}
|
||||
}
|
||||
resultatImport.setErreurs(erreursList);
|
||||
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès",
|
||||
"Import terminé: " + resultatImport.getReussis() + " membres importés avec succès" +
|
||||
(resultatImport.getEchecs() > 0 ? ", " + resultatImport.getEchecs() + " erreurs" : "")));
|
||||
|
||||
// Réinitialiser le fichier
|
||||
fichierImport = null;
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'import: " + e.getMessage());
|
||||
LOGGER.log(java.util.logging.Level.SEVERE, "Détails de l'erreur d'import", e);
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible d'importer le fichier: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public void telechargerModele() {
|
||||
try {
|
||||
LOGGER.info("Téléchargement du modèle d'import");
|
||||
|
||||
byte[] modele = membreService.telechargerModeleImport();
|
||||
|
||||
FacesContext facesContext = FacesContext.getCurrentInstance();
|
||||
HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
|
||||
|
||||
response.reset();
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"modele_import_membres.xlsx\"");
|
||||
response.setContentLength(modele.length);
|
||||
|
||||
response.getOutputStream().write(modele);
|
||||
response.getOutputStream().flush();
|
||||
facesContext.responseComplete();
|
||||
|
||||
LOGGER.info("Modèle d'import téléchargé");
|
||||
} catch (IOException e) {
|
||||
LOGGER.severe("Erreur lors du téléchargement du modèle: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de télécharger le modèle: " + e.getMessage()));
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du téléchargement du modèle: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de télécharger le modèle: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public void reinitialiser() {
|
||||
fichierImport = null;
|
||||
mettreAJourExistants = false;
|
||||
ignorerErreurs = false;
|
||||
organisationId = null;
|
||||
typeMembreDefaut = "";
|
||||
resultatImport = null;
|
||||
}
|
||||
|
||||
// Classe interne pour le résultat de l'import
|
||||
@Getter
|
||||
@Setter
|
||||
public static class ResultatImport implements Serializable {
|
||||
private int totalTraite;
|
||||
private int reussis;
|
||||
private int echecs;
|
||||
private int ignores;
|
||||
private List<ErreurImport> erreurs = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class ErreurImport implements Serializable {
|
||||
private int ligne;
|
||||
private String message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,496 @@
|
||||
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.faces.view.ViewScoped;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.faces.application.FacesMessage;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("membreInscriptionBean")
|
||||
@ViewScoped
|
||||
public class MembreInscriptionBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(MembreInscriptionBean.class.getName());
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_MEMBRE_LISTE = "membreListPage";
|
||||
private static final String OUTCOME_DASHBOARD = "dashboardPage";
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
MembreService membreService;
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
AssociationService associationService;
|
||||
|
||||
@Inject
|
||||
ValidationService validationService;
|
||||
|
||||
@Inject
|
||||
SouscriptionBean souscriptionBean;
|
||||
|
||||
// Propriétés système
|
||||
private String numeroGenere;
|
||||
|
||||
// Informations personnelles
|
||||
private String prenom;
|
||||
private String nom;
|
||||
private String email;
|
||||
private String telephone;
|
||||
private String telephoneMobile;
|
||||
private String adresse;
|
||||
private String ville;
|
||||
private String codePostal;
|
||||
private String pays = "Sénégal";
|
||||
private LocalDate dateNaissance;
|
||||
private String lieuNaissance;
|
||||
private String nationalite = "Sénégalaise";
|
||||
private String sexe;
|
||||
private String situationMatrimoniale;
|
||||
private String profession;
|
||||
private String employeur;
|
||||
|
||||
// Informations d'urgence
|
||||
private String contactUrgenceNom;
|
||||
private String contactUrgenceTelephone;
|
||||
private String contactUrgenceLien;
|
||||
|
||||
// Informations bancaires
|
||||
private String numeroBanque;
|
||||
private String nomBanque;
|
||||
private String ribIban;
|
||||
|
||||
// Informations adhésion
|
||||
private String typeAdhesion;
|
||||
private String numeroParrain;
|
||||
private String nomParrain;
|
||||
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;
|
||||
|
||||
// Statut de validation
|
||||
private String statutValidation = "EN_ATTENTE"; // EN_ATTENTE, VALIDE, REFUSE
|
||||
|
||||
// Informations complémentaires
|
||||
private String competencesSpeciales;
|
||||
private String centresInteret;
|
||||
private String commentaires;
|
||||
|
||||
// Photo et documents
|
||||
private String photoPath;
|
||||
private List<String> documentsJoints = new ArrayList<>();
|
||||
private org.primefaces.model.file.UploadedFile uploadedPhoto;
|
||||
private String photoBase64;
|
||||
|
||||
public MembreInscriptionBean() {
|
||||
// Initialisation par défaut
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
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
|
||||
public String inscrire() {
|
||||
try {
|
||||
// Vérifier d'abord si l'organisation peut accepter de nouveaux membres
|
||||
if (!peutAccepterNouveauMembre()) {
|
||||
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
|
||||
"Quota atteint", "Cette organisation a atteint son quota maximum de membres.");
|
||||
FacesContext.getCurrentInstance().addMessage(null, message);
|
||||
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);
|
||||
nouveauMembre.setNom(nom);
|
||||
nouveauMembre.setPrenom(prenom);
|
||||
nouveauMembre.setEmail(email);
|
||||
nouveauMembre.setTelephone(telephone);
|
||||
nouveauMembre.setDateNaissance(dateNaissance);
|
||||
nouveauMembre.setAdresse(adresse);
|
||||
nouveauMembre.setProfession(profession);
|
||||
nouveauMembre.setStatutMatrimonial(situationMatrimoniale);
|
||||
nouveauMembre.setNationalite(nationalite);
|
||||
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()) {
|
||||
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
|
||||
"Erreurs de validation", validationResult.getFirstErrorMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null, message);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Appel du service REST pour créer le membre
|
||||
MembreDTO membreCreee = membreService.creer(nouveauMembre);
|
||||
|
||||
// Gestion de la photo si disponible
|
||||
if (photoBase64 != null && !photoBase64.trim().isEmpty()) {
|
||||
LOGGER.info("Photo cadrée reçue: " + photoBase64.length() + " caractères");
|
||||
// Note: La sauvegarde de la photo sera implémentée ultérieurement via un service dédié.
|
||||
// Le service appellera l'API backend pour stocker la photo associée au membre.
|
||||
}
|
||||
|
||||
LOGGER.info("Membre inscrit avec succès: " + membreCreee.getNomComplet());
|
||||
|
||||
// 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 réussie",
|
||||
"Le membre " + membreCreee.getNomComplet() + " a été inscrit avec succès (N° " + membreCreee.getNumeroMembre() + ")");
|
||||
context.addMessage(null, message);
|
||||
|
||||
return OUTCOME_MEMBRE_LISTE + "?faces-redirect=true";
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'inscription: " + e.getMessage());
|
||||
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
|
||||
"Erreur", "Erreur lors de l'inscription: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null, message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Méthodes de validation en temps réel
|
||||
public void validateNom() {
|
||||
if (nom != null && !nom.trim().isEmpty()) {
|
||||
ValidationService.ValidationResult result = validationService.validateValue(MembreDTO.class, "nom", nom);
|
||||
if (!result.isValid()) {
|
||||
LOGGER.info("Erreur validation nom: " + result.getFirstErrorMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void validatePrenom() {
|
||||
if (prenom != null && !prenom.trim().isEmpty()) {
|
||||
ValidationService.ValidationResult result = validationService.validateValue(MembreDTO.class, "prenom", prenom);
|
||||
if (!result.isValid()) {
|
||||
LOGGER.info("Erreur validation prénom: " + result.getFirstErrorMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void validateEmail() {
|
||||
if (email != null && !email.trim().isEmpty()) {
|
||||
ValidationService.ValidationResult result = validationService.validateValue(MembreDTO.class, "email", email);
|
||||
if (!result.isValid()) {
|
||||
LOGGER.info("Erreur validation email: " + result.getFirstErrorMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void validateTelephone() {
|
||||
if (telephone != null && !telephone.trim().isEmpty()) {
|
||||
ValidationService.ValidationResult result = validationService.validateValue(MembreDTO.class, "telephone", telephone);
|
||||
if (!result.isValid()) {
|
||||
LOGGER.info("Erreur validation téléphone: " + result.getFirstErrorMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String annuler() {
|
||||
return OUTCOME_DASHBOARD + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public void handleFileUpload(org.primefaces.event.FileUploadEvent event) {
|
||||
// Logique d'upload de documents
|
||||
org.primefaces.model.file.UploadedFile file = event.getFile();
|
||||
if (file != null) {
|
||||
documentsJoints.add(file.getFileName());
|
||||
}
|
||||
}
|
||||
|
||||
public void ajouterDocument() {
|
||||
// Logique d'ajout de document
|
||||
}
|
||||
|
||||
public void supprimerDocument(String document) {
|
||||
documentsJoints.remove(document);
|
||||
}
|
||||
|
||||
public void rechercherParrain() {
|
||||
// Logique de recherche de parrain
|
||||
if (numeroParrain != null && !numeroParrain.trim().isEmpty()) {
|
||||
// Simulation de recherche
|
||||
nomParrain = "Membre trouvé - " + numeroParrain;
|
||||
}
|
||||
}
|
||||
|
||||
public String enregistrerBrouillon() {
|
||||
// Logique d'enregistrement en brouillon
|
||||
return null; // Rester sur la même page
|
||||
}
|
||||
|
||||
// Méthodes pour la progression
|
||||
public boolean isEtapePersonnelleComplete() {
|
||||
return prenom != null && !prenom.trim().isEmpty() &&
|
||||
nom != null && !nom.trim().isEmpty() &&
|
||||
dateNaissance != null &&
|
||||
sexe != null && !sexe.trim().isEmpty();
|
||||
}
|
||||
|
||||
public boolean isEtapeCoordonneeComplete() {
|
||||
return adresse != null && !adresse.trim().isEmpty() &&
|
||||
ville != null && !ville.trim().isEmpty() &&
|
||||
email != null && !email.trim().isEmpty() &&
|
||||
telephoneMobile != null && !telephoneMobile.trim().isEmpty();
|
||||
}
|
||||
|
||||
public boolean isEtapeAdhesionComplete() {
|
||||
return typeAdhesion != null && !typeAdhesion.trim().isEmpty();
|
||||
}
|
||||
|
||||
public boolean isEtapeDocumentsComplete() {
|
||||
return !documentsJoints.isEmpty() || (photoBase64 != null && !photoBase64.trim().isEmpty());
|
||||
}
|
||||
|
||||
public int getProgressionPourcentage() {
|
||||
int etapesCompletes = 0;
|
||||
if (isEtapePersonnelleComplete()) etapesCompletes++;
|
||||
if (isEtapeCoordonneeComplete()) etapesCompletes++;
|
||||
if (isEtapeAdhesionComplete()) etapesCompletes++;
|
||||
if (isEtapeDocumentsComplete()) etapesCompletes++;
|
||||
return (etapesCompletes * 100) / 4;
|
||||
}
|
||||
|
||||
public boolean isFormulaireValide() {
|
||||
// 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) {
|
||||
LOGGER.info("SouscriptionBean non disponible - autorisation par défaut");
|
||||
return true;
|
||||
}
|
||||
return souscriptionBean.peutAccepterNouveauMembre();
|
||||
}
|
||||
|
||||
public String getMessageQuotaOrganisation() {
|
||||
if (souscriptionBean != null) {
|
||||
return souscriptionBean.getMessageQuota();
|
||||
}
|
||||
return "Informations de quota non disponibles";
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public String getNumeroGenere() { return numeroGenere; }
|
||||
public void setNumeroGenere(String numeroGenere) { this.numeroGenere = numeroGenere; }
|
||||
|
||||
public String getPrenom() { return prenom; }
|
||||
public void setPrenom(String prenom) { this.prenom = prenom; }
|
||||
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public String getTelephone() { return telephone; }
|
||||
public void setTelephone(String telephone) { this.telephone = telephone; }
|
||||
|
||||
public String getTelephoneMobile() { return telephoneMobile; }
|
||||
public void setTelephoneMobile(String telephoneMobile) { this.telephoneMobile = telephoneMobile; }
|
||||
|
||||
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 getCodePostal() { return codePostal; }
|
||||
public void setCodePostal(String codePostal) { this.codePostal = codePostal; }
|
||||
|
||||
public String getPays() { return pays; }
|
||||
public void setPays(String pays) { this.pays = pays; }
|
||||
|
||||
public LocalDate getDateNaissance() { return dateNaissance; }
|
||||
public void setDateNaissance(LocalDate dateNaissance) { this.dateNaissance = dateNaissance; }
|
||||
|
||||
public String getLieuNaissance() { return lieuNaissance; }
|
||||
public void setLieuNaissance(String lieuNaissance) { this.lieuNaissance = lieuNaissance; }
|
||||
|
||||
public String getNationalite() { return nationalite; }
|
||||
public void setNationalite(String nationalite) { this.nationalite = nationalite; }
|
||||
|
||||
public String getSexe() { return sexe; }
|
||||
public void setSexe(String sexe) { this.sexe = sexe; }
|
||||
|
||||
public String getSituationMatrimoniale() { return situationMatrimoniale; }
|
||||
public void setSituationMatrimoniale(String situationMatrimoniale) { this.situationMatrimoniale = situationMatrimoniale; }
|
||||
|
||||
public String getProfession() { return profession; }
|
||||
public void setProfession(String profession) { this.profession = profession; }
|
||||
|
||||
public String getEmployeur() { return employeur; }
|
||||
public void setEmployeur(String employeur) { this.employeur = employeur; }
|
||||
|
||||
public String getContactUrgenceNom() { return contactUrgenceNom; }
|
||||
public void setContactUrgenceNom(String contactUrgenceNom) { this.contactUrgenceNom = contactUrgenceNom; }
|
||||
|
||||
public String getContactUrgenceTelephone() { return contactUrgenceTelephone; }
|
||||
public void setContactUrgenceTelephone(String contactUrgenceTelephone) { this.contactUrgenceTelephone = contactUrgenceTelephone; }
|
||||
|
||||
public String getContactUrgenceLien() { return contactUrgenceLien; }
|
||||
public void setContactUrgenceLien(String contactUrgenceLien) { this.contactUrgenceLien = contactUrgenceLien; }
|
||||
|
||||
public String getNumeroBanque() { return numeroBanque; }
|
||||
public void setNumeroBanque(String numeroBanque) { this.numeroBanque = numeroBanque; }
|
||||
|
||||
public String getNomBanque() { return nomBanque; }
|
||||
public void setNomBanque(String nomBanque) { this.nomBanque = nomBanque; }
|
||||
|
||||
public String getRibIban() { return ribIban; }
|
||||
public void setRibIban(String ribIban) { this.ribIban = ribIban; }
|
||||
|
||||
public String getTypeAdhesion() { return typeAdhesion; }
|
||||
public void setTypeAdhesion(String typeAdhesion) { this.typeAdhesion = typeAdhesion; }
|
||||
|
||||
public String getNumeroParrain() { return numeroParrain; }
|
||||
public void setNumeroParrain(String numeroParrain) { this.numeroParrain = numeroParrain; }
|
||||
|
||||
public String getNomParrain() { return nomParrain; }
|
||||
public void setNomParrain(String nomParrain) { this.nomParrain = nomParrain; }
|
||||
|
||||
public String getMotifAdhesion() { return motifAdhesion; }
|
||||
public void setMotifAdhesion(String motifAdhesion) { this.motifAdhesion = motifAdhesion; }
|
||||
|
||||
public boolean isAccepteReglement() { return accepteReglement; }
|
||||
public void setAccepteReglement(boolean accepteReglement) { this.accepteReglement = accepteReglement; }
|
||||
|
||||
public boolean isAcceptePrelevement() { return acceptePrelevement; }
|
||||
public void setAcceptePrelevement(boolean acceptePrelevement) { this.acceptePrelevement = acceptePrelevement; }
|
||||
|
||||
public boolean isAutorisationMarketing() { return autorisationMarketing; }
|
||||
public void setAutorisationMarketing(boolean autorisationMarketing) { this.autorisationMarketing = autorisationMarketing; }
|
||||
|
||||
public String getCompetencesSpeciales() { return competencesSpeciales; }
|
||||
public void setCompetencesSpeciales(String competencesSpeciales) { this.competencesSpeciales = competencesSpeciales; }
|
||||
|
||||
public String getCentresInteret() { return centresInteret; }
|
||||
public void setCentresInteret(String centresInteret) { this.centresInteret = centresInteret; }
|
||||
|
||||
public String getCommentaires() { return commentaires; }
|
||||
public void setCommentaires(String commentaires) { this.commentaires = commentaires; }
|
||||
|
||||
public String getPhotoPath() { return photoPath; }
|
||||
public void setPhotoPath(String photoPath) { this.photoPath = photoPath; }
|
||||
|
||||
public List<String> getDocumentsJoints() { return documentsJoints; }
|
||||
public void setDocumentsJoints(List<String> documentsJoints) { this.documentsJoints = documentsJoints; }
|
||||
|
||||
public org.primefaces.model.file.UploadedFile getUploadedPhoto() { return uploadedPhoto; }
|
||||
public void setUploadedPhoto(org.primefaces.model.file.UploadedFile uploadedPhoto) { this.uploadedPhoto = uploadedPhoto; }
|
||||
|
||||
public String getPhotoBase64() { return photoBase64; }
|
||||
public void setPhotoBase64(String photoBase64) { this.photoBase64 = photoBase64; }
|
||||
|
||||
public String getOrganisationId() { return organisationId; }
|
||||
public void setOrganisationId(String organisationId) { this.organisationId = organisationId; }
|
||||
|
||||
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; }
|
||||
|
||||
// Listes pour les sélections
|
||||
public List<String> getSexeOptions() {
|
||||
List<String> options = new ArrayList<>();
|
||||
options.add("Masculin");
|
||||
options.add("Féminin");
|
||||
return options;
|
||||
}
|
||||
|
||||
public List<String> getSituationMatrimonialeOptions() {
|
||||
List<String> options = new ArrayList<>();
|
||||
options.add("Célibataire");
|
||||
options.add("Marié(e)");
|
||||
options.add("Divorcé(e)");
|
||||
options.add("Veuf(ve)");
|
||||
return options;
|
||||
}
|
||||
|
||||
public List<String> getTypeAdhesionOptions() {
|
||||
List<String> options = new ArrayList<>();
|
||||
options.add("Membre actif");
|
||||
options.add("Membre associé");
|
||||
options.add("Membre bienfaiteur");
|
||||
options.add("Membre honoraire");
|
||||
return options;
|
||||
}
|
||||
|
||||
public List<String> getContactUrgenceLienOptions() {
|
||||
List<String> options = new ArrayList<>();
|
||||
options.add("Conjoint(e)");
|
||||
options.add("Parent");
|
||||
options.add("Enfant");
|
||||
options.add("Frère/Sœur");
|
||||
options.add("Ami(e)");
|
||||
options.add("Autre");
|
||||
return options;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,699 @@
|
||||
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 dev.lions.unionflow.client.service.NotificationService;
|
||||
import dev.lions.unionflow.client.service.CotisationService;
|
||||
import dev.lions.unionflow.server.api.dto.membre.MembreSearchCriteria;
|
||||
import dev.lions.unionflow.server.api.dto.organisation.OrganisationDTO;
|
||||
import dev.lions.unionflow.client.dto.AssociationDTO;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import jakarta.faces.view.ViewScoped;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.faces.application.FacesMessage;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
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;
|
||||
|
||||
@Named("membreListeBean")
|
||||
@ViewScoped
|
||||
@Getter
|
||||
@Setter
|
||||
public class MembreListeBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(MembreListeBean.class.getName());
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
MembreService membreService;
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
AssociationService associationService;
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
NotificationService notificationService;
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
CotisationService cotisationService;
|
||||
|
||||
// Statistiques générales - Utilisation directe du DTO du service
|
||||
@Getter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
|
||||
private MembreService.StatistiquesMembreDTO statistiques;
|
||||
|
||||
// Filtres - Utilisation du DTO du serveur API (DRY/WOU)
|
||||
@Getter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
|
||||
private MembreSearchCriteria searchCriteria = MembreSearchCriteria.builder().build();
|
||||
|
||||
// Filtres additionnels non couverts par MembreSearchCriteria (spécifiques à l'UI)
|
||||
private String typeFilter = "";
|
||||
private String cotisationFilter = "";
|
||||
private Boolean desEnfants;
|
||||
|
||||
// Messages groupés
|
||||
private String sujetMessage;
|
||||
private String contenuMessage;
|
||||
private List<String> canauxMessage = new ArrayList<>();
|
||||
|
||||
// Contact membre
|
||||
private MembreDTO membreAContacter;
|
||||
private String messageContact;
|
||||
private String sujetContact;
|
||||
private boolean dialogContactVisible = false;
|
||||
|
||||
// Import/Export
|
||||
private boolean mettreAJourExistants = false;
|
||||
private String formatExport = "EXCEL";
|
||||
private List<String> colonnesExport = new ArrayList<>();
|
||||
private boolean exporterSelection = false;
|
||||
|
||||
// Données
|
||||
// Pas de getter Lombok car getter personnalisé retourne membresFiltres
|
||||
@Getter(AccessLevel.NONE) @Setter(AccessLevel.NONE)
|
||||
private List<MembreDTO> membres = new ArrayList<>();
|
||||
private List<MembreDTO> selectedMembres = new ArrayList<>();
|
||||
private List<MembreDTO> membresFiltres = new ArrayList<>();
|
||||
// Utilisation directe de OrganisationDTO du serveur API (DRY/WOU)
|
||||
private List<OrganisationDTO> organisationsDisponibles = new ArrayList<>();
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
try {
|
||||
chargerMembres();
|
||||
chargerStatistiques();
|
||||
chargerOrganisations();
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'initialisation: " + e.getMessage());
|
||||
// Initialiser les statistiques à null (sera géré par les getters)
|
||||
this.statistiques = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void chargerMembres() {
|
||||
try {
|
||||
// Récupération de tous les membres via le service REST
|
||||
membres = membreService.listerTous();
|
||||
membresFiltres = new ArrayList<>(membres);
|
||||
|
||||
LOGGER.info("Chargement de " + membres.size() + " membres depuis le serveur");
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Impossible de charger les membres depuis le serveur: " + e.getMessage());
|
||||
// Pas de données mockées - laisser la liste vide
|
||||
membres = new ArrayList<>();
|
||||
membresFiltres = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private void chargerStatistiques() {
|
||||
try {
|
||||
// Récupération directe du DTO de statistiques (DRY/WOU)
|
||||
this.statistiques = membreService.obtenirStatistiques();
|
||||
LOGGER.info("Statistiques chargées: " + (statistiques != null ? statistiques.getTotalMembres() : 0) + " membres");
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Impossible de charger les statistiques: " + e.getMessage());
|
||||
this.statistiques = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void chargerOrganisations() {
|
||||
organisationsDisponibles = new ArrayList<>();
|
||||
try {
|
||||
// Utilisation directe de AssociationDTO (pas de OrganisationService disponible)
|
||||
List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
|
||||
for (AssociationDTO assoc : associations) {
|
||||
// Conversion vers OrganisationDTO pour compatibilité avec MembreSearchCriteria
|
||||
OrganisationDTO org = new OrganisationDTO();
|
||||
org.setId(assoc.getId());
|
||||
org.setNom(assoc.getNom());
|
||||
organisationsDisponibles.add(org);
|
||||
}
|
||||
LOGGER.info("Chargement de " + organisationsDisponibles.size() + " organisations disponibles");
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des organisations: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Actions de recherche et filtrage
|
||||
public void rechercher() {
|
||||
try {
|
||||
// Utilisation de MembreSearchCriteria (DRY/WOU)
|
||||
searchCriteria.sanitize();
|
||||
// Si query est défini, l'utiliser pour nom (recherche générale)
|
||||
String nomRecherche = searchCriteria.getQuery() != null ? searchCriteria.getQuery() : searchCriteria.getNom();
|
||||
List<MembreDTO> resultats = membreService.rechercher(
|
||||
nomRecherche, // nom (ou query si défini)
|
||||
searchCriteria.getPrenom(), // prenom
|
||||
searchCriteria.getEmail(), // email
|
||||
searchCriteria.getTelephone(), // telephone
|
||||
searchCriteria.getStatut(),
|
||||
searchCriteria.getOrganisationIds() != null && !searchCriteria.getOrganisationIds().isEmpty()
|
||||
? searchCriteria.getOrganisationIds().get(0) : null, // associationId
|
||||
0, // page
|
||||
100 // size
|
||||
);
|
||||
|
||||
membresFiltres = resultats;
|
||||
LOGGER.info("Recherche effectuée: " + membresFiltres.size() + " résultats");
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la recherche: " + e.getMessage());
|
||||
membresFiltres = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
public void reinitialiserFiltres() {
|
||||
// Réinitialisation du DTO de critères de recherche (DRY/WOU)
|
||||
searchCriteria = MembreSearchCriteria.builder().build();
|
||||
typeFilter = "";
|
||||
cotisationFilter = "";
|
||||
desEnfants = null;
|
||||
|
||||
membresFiltres = new ArrayList<>(membres);
|
||||
}
|
||||
|
||||
public void actualiser() {
|
||||
chargerMembres();
|
||||
chargerStatistiques();
|
||||
chargerOrganisations();
|
||||
}
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_MEMBRE_LISTE = "membreListPage";
|
||||
private static final String OUTCOME_MEMBRE_PROFIL = "membreProfilPage";
|
||||
private static final String OUTCOME_MEMBRE_MODIFIER = "membreModifierPage";
|
||||
private static final String OUTCOME_COTISATIONS = "cotisationCollectPage";
|
||||
|
||||
public String modifierMembre(MembreDTO membre) {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_MEMBRE_MODIFIER + "?id=" + membre.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
// Propriétés pour la page de modification
|
||||
private UUID membreSelectionneId;
|
||||
private MembreDTO membreSelectionne;
|
||||
|
||||
public void chargerMembreSelectionne() {
|
||||
if (membreSelectionneId != null) {
|
||||
try {
|
||||
membreSelectionne = membreService.obtenirParId(membreSelectionneId);
|
||||
LOGGER.info("Membre chargé pour modification: " + membreSelectionne.getNomComplet());
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement du membre: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de charger le membre: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String modifierMembreSelectionne() {
|
||||
try {
|
||||
membreService.modifier(membreSelectionne.getId(), membreSelectionne);
|
||||
LOGGER.info("Membre modifié: " + membreSelectionne.getNomComplet());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès",
|
||||
"Le membre a été modifié avec succès"));
|
||||
return OUTCOME_MEMBRE_LISTE + "?faces-redirect=true";
|
||||
} 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 le membre: " + e.getMessage()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Méthode pour obtenir la liste des organisations pour le dropdown (WOU/DRY)
|
||||
public List<jakarta.faces.model.SelectItem> getOrganisationsSelectItems() {
|
||||
List<jakarta.faces.model.SelectItem> items = new ArrayList<>();
|
||||
items.add(new jakarta.faces.model.SelectItem("", "Toutes entités"));
|
||||
for (OrganisationDTO org : organisationsDisponibles) {
|
||||
items.add(new jakarta.faces.model.SelectItem(org.getId().toString(), org.getNom()));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
public String gererCotisations(MembreDTO membre) {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_COTISATIONS + "?membreId=" + membre.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
public void appliquerFiltresAvances() {
|
||||
// Appliquer les filtres avancés en utilisant MembreSearchCriteria (DRY/WOU)
|
||||
searchCriteria.sanitize();
|
||||
rechercher();
|
||||
LOGGER.info("Application des filtres avancés: " + searchCriteria.getDescription());
|
||||
}
|
||||
|
||||
// Méthodes de complétion pour les autocomplétions (WOU/DRY - réutilisables)
|
||||
public List<String> completerVilles(String query) {
|
||||
try {
|
||||
// Utilisation du service REST pour obtenir les villes distinctes (WOU/DRY)
|
||||
return membreService.obtenirVilles(query);
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la récupération des villes: " + e.getMessage());
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> completerProfessions(String query) {
|
||||
try {
|
||||
// Utilisation du service REST pour obtenir les professions distinctes (WOU/DRY)
|
||||
return membreService.obtenirProfessions(query);
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la récupération des professions: " + e.getMessage());
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
// Actions supplémentaires pour les membres
|
||||
public void suspendreMembre(MembreDTO membre) {
|
||||
try {
|
||||
membreService.suspendre(membre.getId());
|
||||
membre.setStatut("SUSPENDU");
|
||||
LOGGER.info("Membre suspendu: " + membre.getNomComplet());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès",
|
||||
"Le membre a été suspendu avec succès"));
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la suspension: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de suspendre le membre: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public void reactiverMembre(MembreDTO membre) {
|
||||
try {
|
||||
membreService.activer(membre.getId());
|
||||
membre.setStatut("ACTIF");
|
||||
LOGGER.info("Membre réactivé: " + membre.getNomComplet());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès",
|
||||
"Le membre a été réactivé avec succès"));
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la réactivation: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de réactiver le membre: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public void contacterMembre(MembreDTO membre) {
|
||||
this.membreAContacter = membre;
|
||||
this.sujetContact = "";
|
||||
this.messageContact = "";
|
||||
this.dialogContactVisible = true;
|
||||
LOGGER.info("Ouverture du dialogue de contact pour: " + membre.getNomComplet());
|
||||
}
|
||||
|
||||
public void envoyerMessageContact() {
|
||||
if (membreAContacter == null || messageContact == null || messageContact.trim().isEmpty()) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Veuillez saisir un message"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String sujet = sujetContact != null && !sujetContact.trim().isEmpty()
|
||||
? sujetContact
|
||||
: "Message depuis UnionFlow";
|
||||
|
||||
// Envoyer la notification via le service
|
||||
List<UUID> membreIds = List.of(membreAContacter.getId());
|
||||
List<String> canaux = List.of("IN_APP", "EMAIL");
|
||||
|
||||
NotificationService.NotificationGroupeeRequest request =
|
||||
new NotificationService.NotificationGroupeeRequest(membreIds, sujet, messageContact, canaux);
|
||||
|
||||
notificationService.envoyerNotificationsGroupees(request);
|
||||
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès",
|
||||
"Message envoyé à " + membreAContacter.getNomComplet()));
|
||||
|
||||
// Fermer le dialog
|
||||
this.dialogContactVisible = false;
|
||||
this.membreAContacter = null;
|
||||
this.sujetContact = "";
|
||||
this.messageContact = "";
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'envoi du message: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible d'envoyer le message: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public void annulerContact() {
|
||||
this.dialogContactVisible = false;
|
||||
this.membreAContacter = null;
|
||||
this.sujetContact = "";
|
||||
this.messageContact = "";
|
||||
}
|
||||
|
||||
public void rappelCotisationsGroupe() {
|
||||
if (selectedMembres == null || selectedMembres.isEmpty()) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Veuillez sélectionner au moins un membre"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
LOGGER.info("Envoi de rappels de cotisations à " + selectedMembres.size() + " membres");
|
||||
List<UUID> membreIds = selectedMembres.stream()
|
||||
.map(MembreDTO::getId)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
Map<String, Integer> result = cotisationService.envoyerRappelsGroupes(membreIds);
|
||||
int rappelsEnvoyes = result != null && result.containsKey("rappelsEnvoyes")
|
||||
? result.get("rappelsEnvoyes") : membreIds.size();
|
||||
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès",
|
||||
"Rappels de cotisations envoyés à " + rappelsEnvoyes + " membres"));
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'envoi des rappels: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible d'envoyer les rappels: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public void exporterSelection() {
|
||||
if (selectedMembres == null || selectedMembres.isEmpty()) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Veuillez sélectionner au moins un membre"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
LOGGER.info("Export de la sélection: " + selectedMembres.size() + " membres");
|
||||
List<UUID> membreIds = selectedMembres.stream()
|
||||
.map(MembreDTO::getId)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
byte[] excelData = membreService.exporterSelection(membreIds, formatExport);
|
||||
|
||||
// Téléchargement du fichier Excel via JSF (WOU/DRY - réutilise la logique d'export)
|
||||
FacesContext facesContext = FacesContext.getCurrentInstance();
|
||||
HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
|
||||
|
||||
response.reset();
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"membres_selection_" +
|
||||
LocalDate.now() + "." + (formatExport != null ? formatExport.toLowerCase() : "xlsx") + "\"");
|
||||
response.setContentLength(excelData.length);
|
||||
|
||||
response.getOutputStream().write(excelData);
|
||||
response.getOutputStream().flush();
|
||||
facesContext.responseComplete();
|
||||
|
||||
LOGGER.info("Export Excel généré et téléchargé: " + excelData.length + " bytes");
|
||||
} catch (IOException e) {
|
||||
LOGGER.severe("Erreur lors du téléchargement de l'export: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de télécharger l'export: " + e.getMessage()));
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'export: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible d'exporter la sélection: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public void envoyerMessageGroupe() {
|
||||
if (selectedMembres == null || selectedMembres.isEmpty()) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Veuillez sélectionner au moins un membre"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (sujetMessage == null || sujetMessage.trim().isEmpty()) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Le sujet du message est obligatoire"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (contenuMessage == null || contenuMessage.trim().isEmpty()) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Le contenu du message est obligatoire"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
LOGGER.info("Envoi de message groupé à " + selectedMembres.size() + " membres");
|
||||
List<UUID> membreIds = selectedMembres.stream()
|
||||
.map(MembreDTO::getId)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
NotificationService.NotificationGroupeeRequest request =
|
||||
new NotificationService.NotificationGroupeeRequest(
|
||||
membreIds,
|
||||
sujetMessage,
|
||||
contenuMessage,
|
||||
canauxMessage != null ? canauxMessage : new ArrayList<>()
|
||||
);
|
||||
|
||||
Map<String, Integer> result = notificationService.envoyerNotificationsGroupees(request);
|
||||
int notificationsCreees = result != null && result.containsKey("notificationsCreees")
|
||||
? result.get("notificationsCreees") : membreIds.size();
|
||||
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès",
|
||||
"Message envoyé à " + notificationsCreees + " membres"));
|
||||
// Réinitialiser les champs
|
||||
sujetMessage = null;
|
||||
contenuMessage = null;
|
||||
canauxMessage = new ArrayList<>();
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'envoi du message: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible d'envoyer le message: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
// Import/Export
|
||||
public void importerMembres() {
|
||||
// Logique d'import des membres
|
||||
LOGGER.info("Import des membres");
|
||||
}
|
||||
|
||||
public void telechargerModele() {
|
||||
// Télécharger modèle d'import
|
||||
LOGGER.info("Téléchargement du modèle");
|
||||
}
|
||||
|
||||
// Actions avec DTOs
|
||||
public String voirProfil(MembreDTO membre) {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_MEMBRE_PROFIL + "?id=" + membre.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
public void activerMembre(MembreDTO membre) {
|
||||
try {
|
||||
membreService.activer(membre.getId());
|
||||
membre.setStatut("ACTIF");
|
||||
LOGGER.info("Membre activé: " + membre.getNomComplet());
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'activation: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void desactiverMembre(MembreDTO membre) {
|
||||
try {
|
||||
membreService.desactiver(membre.getId());
|
||||
membre.setStatut("INACTIF");
|
||||
LOGGER.info("Membre désactivé: " + membre.getNomComplet());
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la désactivation: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void exporterMembres() {
|
||||
try {
|
||||
byte[] excelData = membreService.exporterExcel(formatExport, null,
|
||||
searchCriteria.getStatut() != null && !searchCriteria.getStatut().isEmpty()
|
||||
? searchCriteria.getStatut() : null);
|
||||
|
||||
// Téléchargement du fichier Excel via JSF
|
||||
FacesContext facesContext = FacesContext.getCurrentInstance();
|
||||
HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
|
||||
|
||||
response.reset();
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setHeader("Content-Disposition", "attachment; filename=\"membres_export_" +
|
||||
LocalDate.now() + "." + (formatExport != null ? formatExport.toLowerCase() : "xlsx") + "\"");
|
||||
response.setContentLength(excelData.length);
|
||||
|
||||
response.getOutputStream().write(excelData);
|
||||
response.getOutputStream().flush();
|
||||
facesContext.responseComplete();
|
||||
|
||||
LOGGER.info("Export Excel généré et téléchargé: " + excelData.length + " bytes");
|
||||
} catch (IOException e) {
|
||||
LOGGER.severe("Erreur lors du téléchargement de l'export: " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de l'export: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Getters et Setters pour les statistiques (compatibilité avec les pages XHTML)
|
||||
public int getTotalMembres() {
|
||||
return statistiques != null && statistiques.getTotalMembres() != null
|
||||
? statistiques.getTotalMembres().intValue() : 0;
|
||||
}
|
||||
|
||||
public int getMembresActifs() {
|
||||
return statistiques != null && statistiques.getMembresActifs() != null
|
||||
? statistiques.getMembresActifs().intValue() : 0;
|
||||
}
|
||||
|
||||
public int getCotisationsAJour() {
|
||||
// Calcul approximatif (à implémenter côté serveur)
|
||||
return (int) (getMembresActifs() * 0.85);
|
||||
}
|
||||
|
||||
public int getNouveauxMembres() {
|
||||
return statistiques != null && statistiques.getNouveauxMembres30Jours() != null
|
||||
? statistiques.getNouveauxMembres30Jours().intValue() : 0;
|
||||
}
|
||||
|
||||
public int getMembresInactifs() {
|
||||
return statistiques != null && statistiques.getMembresInactifs() != null
|
||||
? statistiques.getMembresInactifs().intValue() : 0;
|
||||
}
|
||||
|
||||
// Getters et Setters de compatibilité pour les filtres (délégation à MembreSearchCriteria)
|
||||
public String getSearchFilter() {
|
||||
return searchCriteria.getQuery() != null ? searchCriteria.getQuery() : "";
|
||||
}
|
||||
public void setSearchFilter(String searchFilter) {
|
||||
searchCriteria.setQuery(searchFilter != null && !searchFilter.isEmpty() ? searchFilter : null);
|
||||
}
|
||||
|
||||
public String getStatutFilter() {
|
||||
return searchCriteria.getStatut() != null ? searchCriteria.getStatut() : "";
|
||||
}
|
||||
public void setStatutFilter(String statutFilter) {
|
||||
searchCriteria.setStatut(statutFilter != null && !statutFilter.isEmpty() ? statutFilter : null);
|
||||
}
|
||||
|
||||
// typeFilter et cotisationFilter sont gérés par Lombok @Getter @Setter
|
||||
|
||||
public String getEntiteFilter() {
|
||||
// Retourne le premier ID d'organisation si présent
|
||||
if (searchCriteria.getOrganisationIds() != null && !searchCriteria.getOrganisationIds().isEmpty()) {
|
||||
return searchCriteria.getOrganisationIds().get(0).toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
public void setEntiteFilter(String entiteFilter) {
|
||||
if (entiteFilter != null && !entiteFilter.isEmpty()) {
|
||||
try {
|
||||
UUID orgId = UUID.fromString(entiteFilter);
|
||||
searchCriteria.setOrganisationIds(List.of(orgId));
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOGGER.warning("ID d'organisation invalide: " + entiteFilter);
|
||||
}
|
||||
} else {
|
||||
searchCriteria.setOrganisationIds(null);
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getAgeMin() { return searchCriteria.getAgeMin(); }
|
||||
public void setAgeMin(Integer ageMin) { searchCriteria.setAgeMin(ageMin); }
|
||||
|
||||
public Integer getAgeMax() { return searchCriteria.getAgeMax(); }
|
||||
public void setAgeMax(Integer ageMax) { searchCriteria.setAgeMax(ageMax); }
|
||||
|
||||
public String getGenreFilter() {
|
||||
// MembreSearchCriteria n'a pas de champ genre, on pourrait utiliser un champ personnalisé
|
||||
// Pour l'instant, on retourne vide
|
||||
return "";
|
||||
}
|
||||
public void setGenreFilter(String genreFilter) {
|
||||
// À implémenter si nécessaire dans MembreSearchCriteria
|
||||
}
|
||||
|
||||
public String getVilleFilter() { return searchCriteria.getVille() != null ? searchCriteria.getVille() : ""; }
|
||||
public void setVilleFilter(String villeFilter) {
|
||||
searchCriteria.setVille(villeFilter != null && !villeFilter.isEmpty() ? villeFilter : null);
|
||||
}
|
||||
|
||||
public LocalDate getDateAdhesionDebut() { return searchCriteria.getDateAdhesionMin(); }
|
||||
public void setDateAdhesionDebut(LocalDate dateAdhesionDebut) { searchCriteria.setDateAdhesionMin(dateAdhesionDebut); }
|
||||
|
||||
public LocalDate getDateAdhesionFin() { return searchCriteria.getDateAdhesionMax(); }
|
||||
public void setDateAdhesionFin(LocalDate dateAdhesionFin) { searchCriteria.setDateAdhesionMax(dateAdhesionFin); }
|
||||
|
||||
public String getProfessionFilter() { return searchCriteria.getProfession() != null ? searchCriteria.getProfession() : ""; }
|
||||
public void setProfessionFilter(String professionFilter) {
|
||||
searchCriteria.setProfession(professionFilter != null && !professionFilter.isEmpty() ? professionFilter : null);
|
||||
}
|
||||
|
||||
// desEnfants, sujetMessage, contenuMessage, canauxMessage, mettreAJourExistants,
|
||||
// formatExport, colonnesExport, exporterSelection, selectedMembres, membresFiltres,
|
||||
// organisationsDisponibles sont gérés par Lombok @Getter @Setter
|
||||
|
||||
// Getter pour MembreSearchCriteria (pour utilisation avancée)
|
||||
public MembreSearchCriteria getSearchCriteria() { return searchCriteria; }
|
||||
public void setSearchCriteria(MembreSearchCriteria searchCriteria) { this.searchCriteria = searchCriteria; }
|
||||
|
||||
// Getter spécial pour membres (retourne membresFiltres pour compatibilité)
|
||||
public List<MembreDTO> getMembres() { return membresFiltres; }
|
||||
public void setMembres(List<MembreDTO> membres) { this.membres = membres; }
|
||||
|
||||
// Getter de compatibilité pour les pages XHTML utilisant "entitesDisponibles"
|
||||
// Note: liste.xhtml devrait utiliser organisationsDisponibles directement (WOU/DRY)
|
||||
@Deprecated
|
||||
public List<Entite> getEntitesDisponibles() {
|
||||
// Conversion de OrganisationDTO vers Entite pour compatibilité
|
||||
List<Entite> entites = new ArrayList<>();
|
||||
for (OrganisationDTO org : organisationsDisponibles) {
|
||||
Entite entite = new Entite();
|
||||
entite.setId(org.getId());
|
||||
entite.setNom(org.getNom());
|
||||
entites.add(entite);
|
||||
}
|
||||
return entites;
|
||||
}
|
||||
|
||||
// Classe interne de compatibilité (à supprimer après mise à jour de liste.xhtml)
|
||||
@Deprecated
|
||||
public static class Entite implements Serializable {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
|
||||
// Getters et setters explicites (Lombok peut avoir des problèmes avec les classes internes)
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,747 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.dto.MembreDTO;
|
||||
import dev.lions.unionflow.client.service.MembreService;
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
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.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
import org.primefaces.event.FileUploadEvent;
|
||||
|
||||
@Named("membreProfilBean")
|
||||
@SessionScoped
|
||||
public class MembreProfilBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(MembreProfilBean.class.getName());
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_MEMBRE_LISTE = "membreListPage";
|
||||
private static final String OUTCOME_MEMBRE_COTISATIONS = "membreCotisationsPage";
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private MembreService membreService;
|
||||
|
||||
private Membre membre;
|
||||
private Membre membreEdit;
|
||||
private Statistiques statistiques;
|
||||
private CotisationsData cotisations;
|
||||
private EvenementsData evenements;
|
||||
private AidesData aides;
|
||||
private DemandesData demandes;
|
||||
private HistoriqueData historique;
|
||||
private ContactData contact;
|
||||
private UUID membreId;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
if (membreId == null) {
|
||||
LOGGER.warning("Aucun membreId fourni, impossible de charger le profil");
|
||||
return;
|
||||
}
|
||||
chargerMembre();
|
||||
chargerStatistiques();
|
||||
chargerCotisations();
|
||||
chargerEvenements();
|
||||
chargerAides();
|
||||
chargerDemandes();
|
||||
chargerHistorique();
|
||||
initContact();
|
||||
}
|
||||
|
||||
private void chargerMembre() {
|
||||
try {
|
||||
MembreDTO dto = membreService.obtenirParId(membreId);
|
||||
membre = convertToMembre(dto);
|
||||
|
||||
// Copie pour l'édition
|
||||
membreEdit = new Membre();
|
||||
copierMembre(membre, membreEdit);
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement du membre: " + e.getMessage());
|
||||
membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
}
|
||||
}
|
||||
|
||||
private Membre convertToMembre(MembreDTO dto) {
|
||||
Membre membre = new Membre();
|
||||
membre.setId(dto.getId());
|
||||
membre.setNumeroMembre(dto.getNumeroMembre());
|
||||
membre.setPrenom(dto.getPrenom());
|
||||
membre.setNom(dto.getNom());
|
||||
membre.setEmail(dto.getEmail());
|
||||
membre.setTelephone(dto.getTelephone());
|
||||
membre.setDateNaissance(dto.getDateNaissance());
|
||||
// Note: Genre, situation familiale, ville, pays, type membre ne sont pas disponibles dans MembreDTO client
|
||||
// Ces champs seront ajoutés ultérieurement si nécessaire
|
||||
membre.setProfession(dto.getProfession());
|
||||
membre.setAdresse(dto.getAdresse());
|
||||
membre.setStatut(dto.getStatut() != null ? dto.getStatut() : "ACTIF");
|
||||
membre.setDateAdhesion(dto.getDateInscription() != null ? dto.getDateInscription().toLocalDate() : null);
|
||||
return membre;
|
||||
}
|
||||
|
||||
private void chargerStatistiques() {
|
||||
statistiques = new Statistiques();
|
||||
statistiques.setEvenementsParticipes(24);
|
||||
statistiques.setCotisationsPayees(12);
|
||||
statistiques.setAidesRecues(2);
|
||||
statistiques.setScoreEngagement(95);
|
||||
statistiques.setTauxParticipation(85);
|
||||
statistiques.setEvenementsAnnee(8);
|
||||
statistiques.setEvenementsTotal(24);
|
||||
statistiques.setEvenementsOrganises(3);
|
||||
statistiques.setAbsences(2);
|
||||
}
|
||||
|
||||
private void chargerCotisations() {
|
||||
cotisations = new CotisationsData();
|
||||
cotisations.setStatutActuel("À jour");
|
||||
cotisations.setStatutSeverity("success");
|
||||
cotisations.setDernierPaiement("15/07/2024");
|
||||
cotisations.setProchaineEcheance("15/08/2024");
|
||||
cotisations.setProchaineEcheanceClass("text-green-500");
|
||||
cotisations.setTotalAnnee("120 000 FCFA");
|
||||
|
||||
// Historique des paiements
|
||||
List<PaiementCotisation> historique = new ArrayList<>();
|
||||
for (int i = 1; i <= 6; i++) {
|
||||
PaiementCotisation paiement = new PaiementCotisation();
|
||||
paiement.setDate(LocalDate.now().minusMonths(i));
|
||||
paiement.setMontant(10000.0);
|
||||
paiement.setModePaiement(i % 2 == 0 ? "Wave Money" : "Espèces");
|
||||
paiement.setModeIcon(i % 2 == 0 ? "pi-mobile" : "pi-money-bill");
|
||||
paiement.setStatut("Validé");
|
||||
paiement.setStatutSeverity("success");
|
||||
historique.add(paiement);
|
||||
}
|
||||
cotisations.setHistorique(historique);
|
||||
}
|
||||
|
||||
private void chargerEvenements() {
|
||||
evenements = new EvenementsData();
|
||||
List<EvenementParticipation> recents = new ArrayList<>();
|
||||
|
||||
String[] titres = {"Réunion mensuelle", "Action humanitaire", "Formation leadership", "Collecte de fonds"};
|
||||
String[] lieux = {"Hôtel Radisson", "École Primaire", "Centre de formation", "Stade Léopold Sédar Senghor"};
|
||||
String[] types = {"REUNION", "ACTION", "FORMATION", "COLLECTE"};
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
EvenementParticipation evt = new EvenementParticipation();
|
||||
evt.setTitre(titres[i]);
|
||||
evt.setDate(LocalDate.now().minusDays(i * 7).toString());
|
||||
evt.setLieu(lieux[i]);
|
||||
evt.setParticipation(i < 3 ? "Présent" : "Absent");
|
||||
evt.setParticipationSeverity(i < 3 ? "success" : "danger");
|
||||
evt.setRole(i == 0 ? "Organisateur" : "Participant");
|
||||
evt.setTypeIcon("pi-calendar");
|
||||
evt.setTypeColorClass("bg-blue-500");
|
||||
recents.add(evt);
|
||||
}
|
||||
evenements.setRecents(recents);
|
||||
}
|
||||
|
||||
private void chargerAides() {
|
||||
aides = new AidesData();
|
||||
List<Aide> recues = new ArrayList<>();
|
||||
|
||||
Aide aide1 = new Aide();
|
||||
aide1.setType("Aide médicale");
|
||||
aide1.setMontant(50000.0);
|
||||
aide1.setDate(LocalDate.of(2024, 5, 10));
|
||||
aide1.setStatut("Validée");
|
||||
aide1.setStatutSeverity("success");
|
||||
aide1.setTypeIcon("pi-heart");
|
||||
aide1.setTypeColor("text-red-500");
|
||||
recues.add(aide1);
|
||||
|
||||
Aide aide2 = new Aide();
|
||||
aide2.setType("Aide scolaire");
|
||||
aide2.setMontant(25000.0);
|
||||
aide2.setDate(LocalDate.of(2024, 1, 15));
|
||||
aide2.setStatut("Validée");
|
||||
aide2.setStatutSeverity("success");
|
||||
aide2.setTypeIcon("pi-book");
|
||||
aide2.setTypeColor("text-blue-500");
|
||||
recues.add(aide2);
|
||||
|
||||
aides.setRecues(recues);
|
||||
}
|
||||
|
||||
private void chargerDemandes() {
|
||||
demandes = new DemandesData();
|
||||
List<Demande> enCours = new ArrayList<>();
|
||||
|
||||
Demande demande1 = new Demande();
|
||||
demande1.setType("Certificat");
|
||||
demande1.setObjet("Certificat d'adhésion");
|
||||
demande1.setDateDepot(LocalDate.now().minusDays(3));
|
||||
demande1.setStatut("En cours");
|
||||
demande1.setStatutSeverity("warning");
|
||||
enCours.add(demande1);
|
||||
|
||||
demandes.setEnCours(enCours);
|
||||
}
|
||||
|
||||
private void chargerHistorique() {
|
||||
historique = new HistoriqueData();
|
||||
List<Activite> activites = new ArrayList<>();
|
||||
|
||||
String[] descriptions = {
|
||||
"Profil mis à jour",
|
||||
"Participation à la réunion mensuelle",
|
||||
"Paiement de cotisation validé",
|
||||
"Nouvelle adhésion enregistrée"
|
||||
};
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Activite activite = new Activite();
|
||||
activite.setDescription(descriptions[i]);
|
||||
activite.setDate(LocalDateTime.now().minusDays(i * 2).toString());
|
||||
activite.setAuteur(i == 0 ? "Jean DIALLO" : "Admin");
|
||||
activite.setIcone(i % 2 == 0 ? "pi-user" : "pi-calendar");
|
||||
activite.setCouleur(i % 2 == 0 ? "text-blue-500" : "text-green-500");
|
||||
if (i == 2) {
|
||||
activite.setDetails("Montant: 10 000 FCFA via Wave Money");
|
||||
}
|
||||
activites.add(activite);
|
||||
}
|
||||
historique.setActivites(activites);
|
||||
}
|
||||
|
||||
private void initContact() {
|
||||
contact = new ContactData();
|
||||
contact.setCanaux(new ArrayList<>());
|
||||
}
|
||||
|
||||
// Actions
|
||||
public void changerPhoto(FileUploadEvent event) {
|
||||
// Logique de changement de photo
|
||||
LOGGER.info("Photo changée: " + event.getFile().getFileName());
|
||||
}
|
||||
|
||||
public String gererCotisations() {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_MEMBRE_COTISATIONS + "?id=" + membre.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
public void sauvegarderModifications() {
|
||||
copierMembre(membreEdit, membre);
|
||||
LOGGER.info("Profil mis à jour pour: " + membre.getNomComplet());
|
||||
}
|
||||
|
||||
public void envoyerMessage() {
|
||||
LOGGER.info("Message envoyé: " + contact.getSujet() + " via " + contact.getCanaux());
|
||||
contact = new ContactData();
|
||||
contact.setCanaux(new ArrayList<>());
|
||||
}
|
||||
|
||||
public void envoyerRappelCotisation() {
|
||||
LOGGER.info("Rappel de cotisation envoyé à: " + membre.getEmail());
|
||||
}
|
||||
|
||||
public void suspendre() {
|
||||
membre.setStatut("SUSPENDU");
|
||||
LOGGER.info("Membre suspendu: " + membre.getNomComplet());
|
||||
}
|
||||
|
||||
public void reactiver() {
|
||||
membre.setStatut("ACTIF");
|
||||
LOGGER.info("Membre réactivé: " + membre.getNomComplet());
|
||||
}
|
||||
|
||||
public void exporterDonnees() {
|
||||
LOGGER.info("Export des données pour: " + membre.getNomComplet());
|
||||
}
|
||||
|
||||
public String supprimer() {
|
||||
LOGGER.info("Membre supprimé: " + membre.getNomComplet());
|
||||
return OUTCOME_MEMBRE_LISTE + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
private void copierMembre(Membre source, Membre destination) {
|
||||
destination.setId(source.getId());
|
||||
destination.setPrenom(source.getPrenom());
|
||||
destination.setNom(source.getNom());
|
||||
destination.setEmail(source.getEmail());
|
||||
destination.setTelephone(source.getTelephone());
|
||||
destination.setDateNaissance(source.getDateNaissance());
|
||||
destination.setProfession(source.getProfession());
|
||||
destination.setAdresse(source.getAdresse());
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public Membre getMembre() { return membre; }
|
||||
public void setMembre(Membre membre) { this.membre = membre; }
|
||||
|
||||
public Membre getMembreEdit() { return membreEdit; }
|
||||
public void setMembreEdit(Membre membreEdit) { this.membreEdit = membreEdit; }
|
||||
|
||||
public Statistiques getStatistiques() { return statistiques; }
|
||||
public void setStatistiques(Statistiques statistiques) { this.statistiques = statistiques; }
|
||||
|
||||
public CotisationsData getCotisations() { return cotisations; }
|
||||
public void setCotisations(CotisationsData cotisations) { this.cotisations = cotisations; }
|
||||
|
||||
public EvenementsData getEvenements() { return evenements; }
|
||||
public void setEvenements(EvenementsData evenements) { this.evenements = evenements; }
|
||||
|
||||
public AidesData getAides() { return aides; }
|
||||
public void setAides(AidesData aides) { this.aides = aides; }
|
||||
|
||||
public DemandesData getDemandes() { return demandes; }
|
||||
public void setDemandes(DemandesData demandes) { this.demandes = demandes; }
|
||||
|
||||
public HistoriqueData getHistorique() { return historique; }
|
||||
public void setHistorique(HistoriqueData historique) { this.historique = historique; }
|
||||
|
||||
public ContactData getContact() { return contact; }
|
||||
public void setContact(ContactData contact) { this.contact = contact; }
|
||||
|
||||
public UUID getMembreId() { return membreId; }
|
||||
public void setMembreId(UUID membreId) { this.membreId = membreId; }
|
||||
|
||||
// Classes internes
|
||||
public static class Membre {
|
||||
private UUID id;
|
||||
private String numeroMembre;
|
||||
private String prenom;
|
||||
private String nom;
|
||||
private String email;
|
||||
private String telephone;
|
||||
private LocalDate dateNaissance;
|
||||
private String genre;
|
||||
private String situationFamiliale;
|
||||
private String profession;
|
||||
private String adresse;
|
||||
private String ville;
|
||||
private String pays;
|
||||
private String typeMembre;
|
||||
private String statut;
|
||||
private String entite;
|
||||
private LocalDate dateAdhesion;
|
||||
private String cotisationStatut;
|
||||
private int tauxParticipation;
|
||||
private String photoUrl;
|
||||
private List<MembreFamille> famille = new ArrayList<>();
|
||||
|
||||
// Getters et setters
|
||||
public UUID getId() { return id; }
|
||||
public void setId(UUID id) { this.id = id; }
|
||||
|
||||
public String getNumeroMembre() { return numeroMembre; }
|
||||
public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
|
||||
|
||||
public String getPrenom() { return prenom; }
|
||||
public void setPrenom(String prenom) { this.prenom = prenom; }
|
||||
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public String getTelephone() { return telephone; }
|
||||
public void setTelephone(String telephone) { this.telephone = telephone; }
|
||||
|
||||
public LocalDate getDateNaissance() { return dateNaissance; }
|
||||
public void setDateNaissance(LocalDate dateNaissance) { this.dateNaissance = dateNaissance; }
|
||||
|
||||
public String getGenre() { return genre; }
|
||||
public void setGenre(String genre) { this.genre = genre; }
|
||||
|
||||
public String getSituationFamiliale() { return situationFamiliale; }
|
||||
public void setSituationFamiliale(String situationFamiliale) { this.situationFamiliale = situationFamiliale; }
|
||||
|
||||
public String getProfession() { return profession; }
|
||||
public void setProfession(String profession) { this.profession = profession; }
|
||||
|
||||
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 getPays() { return pays; }
|
||||
public void setPays(String pays) { this.pays = pays; }
|
||||
|
||||
public String getTypeMembre() { return typeMembre; }
|
||||
public void setTypeMembre(String typeMembre) { this.typeMembre = typeMembre; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getEntite() { return entite; }
|
||||
public void setEntite(String entite) { this.entite = entite; }
|
||||
|
||||
public LocalDate getDateAdhesion() { return dateAdhesion; }
|
||||
public void setDateAdhesion(LocalDate dateAdhesion) { this.dateAdhesion = dateAdhesion; }
|
||||
|
||||
public String getCotisationStatut() { return cotisationStatut; }
|
||||
public void setCotisationStatut(String cotisationStatut) { this.cotisationStatut = cotisationStatut; }
|
||||
|
||||
public int getTauxParticipation() { return tauxParticipation; }
|
||||
public void setTauxParticipation(int tauxParticipation) { this.tauxParticipation = tauxParticipation; }
|
||||
|
||||
public String getPhotoUrl() { return photoUrl; }
|
||||
public void setPhotoUrl(String photoUrl) { this.photoUrl = photoUrl; }
|
||||
|
||||
public List<MembreFamille> getFamille() { return famille; }
|
||||
public void setFamille(List<MembreFamille> famille) { this.famille = famille; }
|
||||
|
||||
// Propriétés dérivées
|
||||
public String getNomComplet() {
|
||||
return prenom + " " + nom;
|
||||
}
|
||||
|
||||
public String getInitiales() {
|
||||
return (prenom != null ? prenom.substring(0, 1) : "") +
|
||||
(nom != null ? nom.substring(0, 1) : "");
|
||||
}
|
||||
|
||||
public String getStatutSeverity() {
|
||||
return switch (statut) {
|
||||
case "ACTIF" -> "success";
|
||||
case "INACTIF" -> "warning";
|
||||
case "SUSPENDU" -> "danger";
|
||||
case "RADIE" -> "danger";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutIcon() {
|
||||
return switch (statut) {
|
||||
case "ACTIF" -> "pi-check";
|
||||
case "INACTIF" -> "pi-pause";
|
||||
case "SUSPENDU" -> "pi-ban";
|
||||
case "RADIE" -> "pi-times";
|
||||
default -> "pi-circle";
|
||||
};
|
||||
}
|
||||
|
||||
public String getTypeSeverity() {
|
||||
return switch (typeMembre) {
|
||||
case "ACTIF" -> "info";
|
||||
case "ASSOCIE" -> "success";
|
||||
case "BIENFAITEUR" -> "warning";
|
||||
case "HONORAIRE" -> "secondary";
|
||||
default -> "info";
|
||||
};
|
||||
}
|
||||
|
||||
public String getTypeIcon() {
|
||||
return switch (typeMembre) {
|
||||
case "ACTIF" -> "pi-user";
|
||||
case "ASSOCIE" -> "pi-users";
|
||||
case "BIENFAITEUR" -> "pi-star";
|
||||
case "HONORAIRE" -> "pi-crown";
|
||||
default -> "pi-user";
|
||||
};
|
||||
}
|
||||
|
||||
public String getAnciennete() {
|
||||
if (dateAdhesion == null) return "N/A";
|
||||
long mois = java.time.temporal.ChronoUnit.MONTHS.between(dateAdhesion, LocalDate.now());
|
||||
if (mois < 12) return mois + " mois";
|
||||
return (mois / 12) + " an" + (mois / 12 > 1 ? "s" : "");
|
||||
}
|
||||
|
||||
public String getCotisationColor() {
|
||||
return cotisationStatut != null && cotisationStatut.equals("À jour") ? "text-green-500" : "text-red-500";
|
||||
}
|
||||
}
|
||||
|
||||
public static class MembreFamille {
|
||||
private String nomComplet;
|
||||
private String relation;
|
||||
private LocalDate dateNaissance;
|
||||
private boolean beneficiaire;
|
||||
|
||||
// Getters et setters
|
||||
public String getNomComplet() { return nomComplet; }
|
||||
public void setNomComplet(String nomComplet) { this.nomComplet = nomComplet; }
|
||||
|
||||
public String getRelation() { return relation; }
|
||||
public void setRelation(String relation) { this.relation = relation; }
|
||||
|
||||
public LocalDate getDateNaissance() { return dateNaissance; }
|
||||
public void setDateNaissance(LocalDate dateNaissance) { this.dateNaissance = dateNaissance; }
|
||||
|
||||
public boolean isBeneficiaire() { return beneficiaire; }
|
||||
public void setBeneficiaire(boolean beneficiaire) { this.beneficiaire = beneficiaire; }
|
||||
}
|
||||
|
||||
public static class Statistiques {
|
||||
private int evenementsParticipes;
|
||||
private int cotisationsPayees;
|
||||
private int aidesRecues;
|
||||
private int scoreEngagement;
|
||||
private int tauxParticipation;
|
||||
private int evenementsAnnee;
|
||||
private int evenementsTotal;
|
||||
private int evenementsOrganises;
|
||||
private int absences;
|
||||
|
||||
// Getters et setters
|
||||
public int getEvenementsParticipes() { return evenementsParticipes; }
|
||||
public void setEvenementsParticipes(int evenementsParticipes) { this.evenementsParticipes = evenementsParticipes; }
|
||||
|
||||
public int getCotisationsPayees() { return cotisationsPayees; }
|
||||
public void setCotisationsPayees(int cotisationsPayees) { this.cotisationsPayees = cotisationsPayees; }
|
||||
|
||||
public int getAidesRecues() { return aidesRecues; }
|
||||
public void setAidesRecues(int aidesRecues) { this.aidesRecues = aidesRecues; }
|
||||
|
||||
public int getScoreEngagement() { return scoreEngagement; }
|
||||
public void setScoreEngagement(int scoreEngagement) { this.scoreEngagement = scoreEngagement; }
|
||||
|
||||
public int getTauxParticipation() { return tauxParticipation; }
|
||||
public void setTauxParticipation(int tauxParticipation) { this.tauxParticipation = tauxParticipation; }
|
||||
|
||||
public int getEvenementsAnnee() { return evenementsAnnee; }
|
||||
public void setEvenementsAnnee(int evenementsAnnee) { this.evenementsAnnee = evenementsAnnee; }
|
||||
|
||||
public int getEvenementsTotal() { return evenementsTotal; }
|
||||
public void setEvenementsTotal(int evenementsTotal) { this.evenementsTotal = evenementsTotal; }
|
||||
|
||||
public int getEvenementsOrganises() { return evenementsOrganises; }
|
||||
public void setEvenementsOrganises(int evenementsOrganises) { this.evenementsOrganises = evenementsOrganises; }
|
||||
|
||||
public int getAbsences() { return absences; }
|
||||
public void setAbsences(int absences) { this.absences = absences; }
|
||||
}
|
||||
|
||||
public static class CotisationsData {
|
||||
private String statutActuel;
|
||||
private String statutSeverity;
|
||||
private String dernierPaiement;
|
||||
private String prochaineEcheance;
|
||||
private String prochaineEcheanceClass;
|
||||
private String totalAnnee;
|
||||
private List<PaiementCotisation> historique = new ArrayList<>();
|
||||
|
||||
// Getters et setters
|
||||
public String getStatutActuel() { return statutActuel; }
|
||||
public void setStatutActuel(String statutActuel) { this.statutActuel = statutActuel; }
|
||||
|
||||
public String getStatutSeverity() { return statutSeverity; }
|
||||
public void setStatutSeverity(String statutSeverity) { this.statutSeverity = statutSeverity; }
|
||||
|
||||
public String getDernierPaiement() { return dernierPaiement; }
|
||||
public void setDernierPaiement(String dernierPaiement) { this.dernierPaiement = dernierPaiement; }
|
||||
|
||||
public String getProchaineEcheance() { return prochaineEcheance; }
|
||||
public void setProchaineEcheance(String prochaineEcheance) { this.prochaineEcheance = prochaineEcheance; }
|
||||
|
||||
public String getProchaineEcheanceClass() { return prochaineEcheanceClass; }
|
||||
public void setProchaineEcheanceClass(String prochaineEcheanceClass) { this.prochaineEcheanceClass = prochaineEcheanceClass; }
|
||||
|
||||
public String getTotalAnnee() { return totalAnnee; }
|
||||
public void setTotalAnnee(String totalAnnee) { this.totalAnnee = totalAnnee; }
|
||||
|
||||
public List<PaiementCotisation> getHistorique() { return historique; }
|
||||
public void setHistorique(List<PaiementCotisation> historique) { this.historique = historique; }
|
||||
}
|
||||
|
||||
public static class PaiementCotisation {
|
||||
private LocalDate date;
|
||||
private Double montant;
|
||||
private String modePaiement;
|
||||
private String modeIcon;
|
||||
private String statut;
|
||||
private String statutSeverity;
|
||||
|
||||
// Getters et setters
|
||||
public LocalDate getDate() { return date; }
|
||||
public void setDate(LocalDate date) { this.date = date; }
|
||||
|
||||
public Double getMontant() { return montant; }
|
||||
public void setMontant(Double montant) { this.montant = montant; }
|
||||
|
||||
public String getModePaiement() { return modePaiement; }
|
||||
public void setModePaiement(String modePaiement) { this.modePaiement = modePaiement; }
|
||||
|
||||
public String getModeIcon() { return modeIcon; }
|
||||
public void setModeIcon(String modeIcon) { this.modeIcon = modeIcon; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getStatutSeverity() { return statutSeverity; }
|
||||
public void setStatutSeverity(String statutSeverity) { this.statutSeverity = statutSeverity; }
|
||||
}
|
||||
|
||||
public static class EvenementsData {
|
||||
private List<EvenementParticipation> recents = new ArrayList<>();
|
||||
|
||||
public List<EvenementParticipation> getRecents() { return recents; }
|
||||
public void setRecents(List<EvenementParticipation> recents) { this.recents = recents; }
|
||||
}
|
||||
|
||||
public static class EvenementParticipation {
|
||||
private String titre;
|
||||
private String date;
|
||||
private String lieu;
|
||||
private String participation;
|
||||
private String participationSeverity;
|
||||
private String role;
|
||||
private String typeIcon;
|
||||
private String typeColorClass;
|
||||
|
||||
// Getters et setters
|
||||
public String getTitre() { return titre; }
|
||||
public void setTitre(String titre) { this.titre = titre; }
|
||||
|
||||
public String getDate() { return date; }
|
||||
public void setDate(String date) { this.date = date; }
|
||||
|
||||
public String getLieu() { return lieu; }
|
||||
public void setLieu(String lieu) { this.lieu = lieu; }
|
||||
|
||||
public String getParticipation() { return participation; }
|
||||
public void setParticipation(String participation) { this.participation = participation; }
|
||||
|
||||
public String getParticipationSeverity() { return participationSeverity; }
|
||||
public void setParticipationSeverity(String participationSeverity) { this.participationSeverity = participationSeverity; }
|
||||
|
||||
public String getRole() { return role; }
|
||||
public void setRole(String role) { this.role = role; }
|
||||
|
||||
public String getTypeIcon() { return typeIcon; }
|
||||
public void setTypeIcon(String typeIcon) { this.typeIcon = typeIcon; }
|
||||
|
||||
public String getTypeColorClass() { return typeColorClass; }
|
||||
public void setTypeColorClass(String typeColorClass) { this.typeColorClass = typeColorClass; }
|
||||
}
|
||||
|
||||
public static class AidesData {
|
||||
private List<Aide> recues = new ArrayList<>();
|
||||
|
||||
public List<Aide> getRecues() { return recues; }
|
||||
public void setRecues(List<Aide> recues) { this.recues = recues; }
|
||||
}
|
||||
|
||||
public static class Aide {
|
||||
private String type;
|
||||
private Double montant;
|
||||
private LocalDate date;
|
||||
private String statut;
|
||||
private String statutSeverity;
|
||||
private String typeIcon;
|
||||
private String typeColor;
|
||||
|
||||
// Getters et setters
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public Double getMontant() { return montant; }
|
||||
public void setMontant(Double montant) { this.montant = montant; }
|
||||
|
||||
public LocalDate getDate() { return date; }
|
||||
public void setDate(LocalDate date) { this.date = date; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getStatutSeverity() { return statutSeverity; }
|
||||
public void setStatutSeverity(String statutSeverity) { this.statutSeverity = statutSeverity; }
|
||||
|
||||
public String getTypeIcon() { return typeIcon; }
|
||||
public void setTypeIcon(String typeIcon) { this.typeIcon = typeIcon; }
|
||||
|
||||
public String getTypeColor() { return typeColor; }
|
||||
public void setTypeColor(String typeColor) { this.typeColor = typeColor; }
|
||||
}
|
||||
|
||||
public static class DemandesData {
|
||||
private List<Demande> enCours = new ArrayList<>();
|
||||
|
||||
public List<Demande> getEnCours() { return enCours; }
|
||||
public void setEnCours(List<Demande> enCours) { this.enCours = enCours; }
|
||||
}
|
||||
|
||||
public static class Demande {
|
||||
private String type;
|
||||
private String objet;
|
||||
private LocalDate dateDepot;
|
||||
private String statut;
|
||||
private String statutSeverity;
|
||||
|
||||
// Getters et setters
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getObjet() { return objet; }
|
||||
public void setObjet(String objet) { this.objet = objet; }
|
||||
|
||||
public LocalDate getDateDepot() { return dateDepot; }
|
||||
public void setDateDepot(LocalDate dateDepot) { this.dateDepot = dateDepot; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getStatutSeverity() { return statutSeverity; }
|
||||
public void setStatutSeverity(String statutSeverity) { this.statutSeverity = statutSeverity; }
|
||||
}
|
||||
|
||||
public static class HistoriqueData {
|
||||
private List<Activite> activites = new ArrayList<>();
|
||||
|
||||
public List<Activite> getActivites() { return activites; }
|
||||
public void setActivites(List<Activite> activites) { this.activites = activites; }
|
||||
}
|
||||
|
||||
public static class Activite {
|
||||
private String description;
|
||||
private String date;
|
||||
private String auteur;
|
||||
private String icone;
|
||||
private String couleur;
|
||||
private String details;
|
||||
|
||||
// Getters et setters
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public String getDate() { return date; }
|
||||
public void setDate(String date) { this.date = date; }
|
||||
|
||||
public String getAuteur() { return auteur; }
|
||||
public void setAuteur(String auteur) { this.auteur = auteur; }
|
||||
|
||||
public String getIcone() { return icone; }
|
||||
public void setIcone(String icone) { this.icone = icone; }
|
||||
|
||||
public String getCouleur() { return couleur; }
|
||||
public void setCouleur(String couleur) { this.couleur = couleur; }
|
||||
|
||||
public String getDetails() { return details; }
|
||||
public void setDetails(String details) { this.details = details; }
|
||||
}
|
||||
|
||||
public static class ContactData {
|
||||
private String sujet;
|
||||
private String message;
|
||||
private List<String> canaux = new ArrayList<>();
|
||||
|
||||
// Getters et setters
|
||||
public String getSujet() { return sujet; }
|
||||
public void setSujet(String sujet) { this.sujet = sujet; }
|
||||
|
||||
public String getMessage() { return message; }
|
||||
public void setMessage(String message) { this.message = message; }
|
||||
|
||||
public List<String> getCanaux() { return canaux; }
|
||||
public void setCanaux(List<String> canaux) { this.canaux = canaux; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,738 @@
|
||||
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.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.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("membreRechercheBean")
|
||||
@SessionScoped
|
||||
public class MembreRechercheBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(MembreRechercheBean.class.getName());
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_MEMBRE_PROFIL = "membreProfilPage";
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private MembreService membreService;
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private AssociationService associationService;
|
||||
|
||||
private Filtres filtres;
|
||||
private Statistiques statistiques;
|
||||
private List<Membre> resultats;
|
||||
private List<Membre> selectedMembres;
|
||||
private List<Membre> tousLesMembres;
|
||||
private List<Entite> entitesDisponibles;
|
||||
private List<RechercheSauvegardee> recherchesSauvegardees;
|
||||
private RechercheSauvegardee nouvelleRechercheSauvegardee;
|
||||
private MessageGroupe messageGroupe;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initializeFiltres();
|
||||
initializeStatistiques();
|
||||
initializeDonnees();
|
||||
initializeEntites();
|
||||
initializeRecherchesSauvegardees();
|
||||
initializeMessageGroupe();
|
||||
effectuerRecherche();
|
||||
}
|
||||
|
||||
private void initializeFiltres() {
|
||||
filtres = new Filtres();
|
||||
filtres.setStatuts(new ArrayList<>());
|
||||
filtres.setTypesMembre(new ArrayList<>());
|
||||
filtres.setEntites(new ArrayList<>());
|
||||
filtres.setStatutsCotisation(new ArrayList<>());
|
||||
filtres.setGenres(new ArrayList<>());
|
||||
}
|
||||
|
||||
private void initializeStatistiques() {
|
||||
statistiques = new Statistiques();
|
||||
try {
|
||||
List<MembreDTO> membres = membreService.listerTous();
|
||||
statistiques.setTotalMembres(membres.size());
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du calcul des statistiques: " + e.getMessage());
|
||||
statistiques.setTotalMembres(0);
|
||||
}
|
||||
statistiques.setResultatsActuels(0);
|
||||
statistiques.setFiltresActifs(0);
|
||||
statistiques.setTempsRecherche(0);
|
||||
}
|
||||
|
||||
private void initializeDonnees() {
|
||||
tousLesMembres = new ArrayList<>();
|
||||
selectedMembres = new ArrayList<>();
|
||||
|
||||
try {
|
||||
List<MembreDTO> membresDTO = membreService.listerTous();
|
||||
for (MembreDTO dto : membresDTO) {
|
||||
Membre membre = convertToMembre(dto);
|
||||
tousLesMembres.add(membre);
|
||||
}
|
||||
resultats = new ArrayList<>(tousLesMembres);
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des membres: " + e.getMessage());
|
||||
resultats = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private Membre convertToMembre(MembreDTO dto) {
|
||||
Membre membre = new Membre();
|
||||
membre.setId(dto.getId());
|
||||
membre.setNumeroMembre(dto.getNumeroMembre());
|
||||
membre.setNom(dto.getNom());
|
||||
membre.setPrenom(dto.getPrenom());
|
||||
membre.setEmail(dto.getEmail());
|
||||
membre.setTelephone(dto.getTelephone());
|
||||
membre.setProfession(dto.getProfession());
|
||||
membre.setVille(""); // Ville non disponible dans MembreDTO
|
||||
membre.setTypeMembre("ACTIF"); // Type membre non disponible dans MembreDTO
|
||||
if (dto.getStatut() != null) {
|
||||
membre.setStatut(dto.getStatut());
|
||||
} else {
|
||||
membre.setStatut("ACTIF");
|
||||
}
|
||||
membre.setDateAdhesion(dto.getDateInscription() != null ? dto.getDateInscription().toLocalDate() : null);
|
||||
return membre;
|
||||
}
|
||||
|
||||
private void initializeEntites() {
|
||||
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);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des entités: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeRecherchesSauvegardees() {
|
||||
recherchesSauvegardees = new ArrayList<>();
|
||||
nouvelleRechercheSauvegardee = new RechercheSauvegardee();
|
||||
}
|
||||
|
||||
private void initializeMessageGroupe() {
|
||||
messageGroupe = new MessageGroupe();
|
||||
messageGroupe.setCanaux(new ArrayList<>());
|
||||
}
|
||||
|
||||
// Actions principales
|
||||
public void effectuerRecherche() {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
List<MembreDTO> membresDTO = membreService.rechercher(
|
||||
filtres.getNom(),
|
||||
filtres.getPrenom(),
|
||||
filtres.getEmail(),
|
||||
filtres.getTelephone(),
|
||||
filtres.getStatuts() != null && !filtres.getStatuts().isEmpty() ? filtres.getStatuts().get(0) : null,
|
||||
null,
|
||||
0,
|
||||
100
|
||||
);
|
||||
|
||||
resultats = membresDTO.stream()
|
||||
.map(this::convertToMembre)
|
||||
.collect(Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la recherche: " + e.getMessage());
|
||||
resultats = new ArrayList<>();
|
||||
}
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
|
||||
// Mise à jour des statistiques
|
||||
statistiques.setResultatsActuels(resultats.size());
|
||||
statistiques.setFiltresActifs(compterFiltresActifs());
|
||||
statistiques.setTempsRecherche((int)(endTime - startTime));
|
||||
|
||||
selectedMembres.clear();
|
||||
}
|
||||
|
||||
private boolean appliquerFiltres(Membre membre) {
|
||||
// Filtre nom
|
||||
if (filtres.getNom() != null && !filtres.getNom().trim().isEmpty()) {
|
||||
if (!membre.getNom().toLowerCase().contains(filtres.getNom().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre prénom
|
||||
if (filtres.getPrenom() != null && !filtres.getPrenom().trim().isEmpty()) {
|
||||
if (!membre.getPrenom().toLowerCase().contains(filtres.getPrenom().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre email
|
||||
if (filtres.getEmail() != null && !filtres.getEmail().trim().isEmpty()) {
|
||||
if (!membre.getEmail().toLowerCase().contains(filtres.getEmail().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre téléphone
|
||||
if (filtres.getTelephone() != null && !filtres.getTelephone().trim().isEmpty()) {
|
||||
if (!membre.getTelephone().contains(filtres.getTelephone())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre numéro membre
|
||||
if (filtres.getNumeroMembre() != null && !filtres.getNumeroMembre().trim().isEmpty()) {
|
||||
if (!membre.getNumeroMembre().toLowerCase().contains(filtres.getNumeroMembre().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre profession
|
||||
if (filtres.getProfession() != null && !filtres.getProfession().trim().isEmpty()) {
|
||||
if (!membre.getProfession().toLowerCase().contains(filtres.getProfession().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre statuts
|
||||
if (filtres.getStatuts() != null && !filtres.getStatuts().isEmpty()) {
|
||||
if (!filtres.getStatuts().contains(membre.getStatut())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre types membre
|
||||
if (filtres.getTypesMembre() != null && !filtres.getTypesMembre().isEmpty()) {
|
||||
if (!filtres.getTypesMembre().contains(membre.getTypeMembre())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre âge
|
||||
if (filtres.getAgeMin() != null && membre.getAge() < filtres.getAgeMin()) {
|
||||
return false;
|
||||
}
|
||||
if (filtres.getAgeMax() != null && membre.getAge() > filtres.getAgeMax()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filtre ville
|
||||
if (filtres.getVille() != null && !filtres.getVille().trim().isEmpty()) {
|
||||
if (!membre.getVille().toLowerCase().contains(filtres.getVille().toLowerCase())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre genres
|
||||
if (filtres.getGenres() != null && !filtres.getGenres().isEmpty()) {
|
||||
if (!filtres.getGenres().contains(membre.getGenre())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Filtre taux participation
|
||||
if (filtres.getTauxParticipationMin() != null && membre.getTauxParticipation() < filtres.getTauxParticipationMin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filtre événements min
|
||||
if (filtres.getEvenementsMin() != null && membre.getEvenementsAnnee() < filtres.getEvenementsMin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filtre a des enfants
|
||||
if (filtres.getADesEnfants() != null && filtres.getADesEnfants() && !membre.isADesEnfants()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filtre a reçu aides
|
||||
if (filtres.getARecuAides() != null && filtres.getARecuAides() && !membre.isARecuAides()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filtre dates d'adhésion
|
||||
if (filtres.getDateAdhesionDebut() != null && membre.getDateAdhesion().isBefore(filtres.getDateAdhesionDebut())) {
|
||||
return false;
|
||||
}
|
||||
if (filtres.getDateAdhesionFin() != null && membre.getDateAdhesion().isAfter(filtres.getDateAdhesionFin())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private int compterFiltresActifs() {
|
||||
int count = 0;
|
||||
|
||||
if (filtres.getNom() != null && !filtres.getNom().trim().isEmpty()) count++;
|
||||
if (filtres.getPrenom() != null && !filtres.getPrenom().trim().isEmpty()) count++;
|
||||
if (filtres.getEmail() != null && !filtres.getEmail().trim().isEmpty()) count++;
|
||||
if (filtres.getTelephone() != null && !filtres.getTelephone().trim().isEmpty()) count++;
|
||||
if (filtres.getNumeroMembre() != null && !filtres.getNumeroMembre().trim().isEmpty()) count++;
|
||||
if (filtres.getProfession() != null && !filtres.getProfession().trim().isEmpty()) count++;
|
||||
if (filtres.getStatuts() != null && !filtres.getStatuts().isEmpty()) count++;
|
||||
if (filtres.getTypesMembre() != null && !filtres.getTypesMembre().isEmpty()) count++;
|
||||
if (filtres.getAgeMin() != null) count++;
|
||||
if (filtres.getAgeMax() != null) count++;
|
||||
if (filtres.getVille() != null && !filtres.getVille().trim().isEmpty()) count++;
|
||||
if (filtres.getGenres() != null && !filtres.getGenres().isEmpty()) count++;
|
||||
if (filtres.getTauxParticipationMin() != null) count++;
|
||||
if (filtres.getEvenementsMin() != null) count++;
|
||||
if (filtres.getCotisationsMin() != null) count++;
|
||||
if (filtres.getADesEnfants() != null && filtres.getADesEnfants()) count++;
|
||||
if (filtres.getARecuAides() != null && filtres.getARecuAides()) count++;
|
||||
if (filtres.getDateAdhesionDebut() != null) count++;
|
||||
if (filtres.getDateAdhesionFin() != null) count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public void reinitialiserFiltres() {
|
||||
initializeFiltres();
|
||||
effectuerRecherche();
|
||||
}
|
||||
|
||||
public void actualiserResultats() {
|
||||
effectuerRecherche();
|
||||
}
|
||||
|
||||
public void nouvelleRecherche() {
|
||||
reinitialiserFiltres();
|
||||
}
|
||||
|
||||
// Actions sur les membres
|
||||
public String voirProfil(Membre membre) {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_MEMBRE_PROFIL + "?id=" + membre.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
public void contacterMembre(Membre membre) {
|
||||
LOGGER.info("Contacter le membre: " + membre.getNomComplet());
|
||||
}
|
||||
|
||||
public void ajouterAuGroupe(Membre membre) {
|
||||
LOGGER.info("Ajouter au groupe: " + membre.getNomComplet());
|
||||
}
|
||||
|
||||
// Gestion des recherches sauvegardées
|
||||
public void sauvegarderRecherche() {
|
||||
nouvelleRechercheSauvegardee.setId(UUID.randomUUID());
|
||||
nouvelleRechercheSauvegardee.setNombreCriteres(compterFiltresActifs());
|
||||
nouvelleRechercheSauvegardee.setDateCreation(LocalDate.now());
|
||||
|
||||
recherchesSauvegardees.add(nouvelleRechercheSauvegardee);
|
||||
|
||||
LOGGER.info("Recherche sauvegardée: " + nouvelleRechercheSauvegardee.getNom());
|
||||
|
||||
nouvelleRechercheSauvegardee = new RechercheSauvegardee();
|
||||
}
|
||||
|
||||
public void chargerRecherche(RechercheSauvegardee recherche) {
|
||||
// Simuler le chargement des critères
|
||||
reinitialiserFiltres();
|
||||
|
||||
if (recherche.getNom().contains("actifs")) {
|
||||
filtres.getStatuts().add("ACTIF");
|
||||
}
|
||||
if (recherche.getNom().contains("retard")) {
|
||||
filtres.getStatutsCotisation().add("EN_RETARD");
|
||||
}
|
||||
|
||||
effectuerRecherche();
|
||||
LOGGER.info("Recherche chargée: " + recherche.getNom());
|
||||
}
|
||||
|
||||
public void supprimerRecherche(RechercheSauvegardee recherche) {
|
||||
recherchesSauvegardees.remove(recherche);
|
||||
LOGGER.info("Recherche supprimée: " + recherche.getNom());
|
||||
}
|
||||
|
||||
// Actions groupées
|
||||
public void envoyerMessageGroupe() {
|
||||
LOGGER.info("Message '" + messageGroupe.getSujet() + "' envoyé à " +
|
||||
selectedMembres.size() + " membres via " + messageGroupe.getCanaux());
|
||||
|
||||
messageGroupe = new MessageGroupe();
|
||||
messageGroupe.setCanaux(new ArrayList<>());
|
||||
}
|
||||
|
||||
public void exporterSelection() {
|
||||
LOGGER.info("Export de " + selectedMembres.size() + " membres sélectionnés");
|
||||
}
|
||||
|
||||
// Méthodes d'autocomplétion
|
||||
public List<String> completerProfessions(String query) {
|
||||
List<String> professions = List.of("Enseignant", "Médecin", "Ingénieur", "Commerçant", "Agriculteur",
|
||||
"Fonctionnaire", "Artisan", "Avocat", "Architecte", "Pharmacien");
|
||||
return professions.stream()
|
||||
.filter(profession -> profession.toLowerCase().contains(query.toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<String> completerVilles(String query) {
|
||||
List<String> villes = List.of("Dakar", "Thiès", "Kaolack", "Saint-Louis", "Ziguinchor",
|
||||
"Diourbel", "Tambacounda", "Kolda", "Fatick", "Louga");
|
||||
return villes.stream()
|
||||
.filter(ville -> ville.toLowerCase().contains(query.toLowerCase()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public Filtres getFiltres() { return filtres; }
|
||||
public void setFiltres(Filtres filtres) { this.filtres = filtres; }
|
||||
|
||||
public Statistiques getStatistiques() { return statistiques; }
|
||||
public void setStatistiques(Statistiques statistiques) { this.statistiques = statistiques; }
|
||||
|
||||
public List<Membre> getResultats() { return resultats; }
|
||||
public void setResultats(List<Membre> resultats) { this.resultats = resultats; }
|
||||
|
||||
public List<Membre> getSelectedMembres() { return selectedMembres; }
|
||||
public void setSelectedMembres(List<Membre> selectedMembres) { this.selectedMembres = selectedMembres; }
|
||||
|
||||
public List<Entite> getEntitesDisponibles() { return entitesDisponibles; }
|
||||
public void setEntitesDisponibles(List<Entite> entitesDisponibles) { this.entitesDisponibles = entitesDisponibles; }
|
||||
|
||||
public List<RechercheSauvegardee> getRecherchesSauvegardees() { return recherchesSauvegardees; }
|
||||
public void setRecherchesSauvegardees(List<RechercheSauvegardee> recherchesSauvegardees) { this.recherchesSauvegardees = recherchesSauvegardees; }
|
||||
|
||||
public RechercheSauvegardee getNouvelleRechercheSauvegardee() { return nouvelleRechercheSauvegardee; }
|
||||
public void setNouvelleRechercheSauvegardee(RechercheSauvegardee nouvelleRechercheSauvegardee) { this.nouvelleRechercheSauvegardee = nouvelleRechercheSauvegardee; }
|
||||
|
||||
public MessageGroupe getMessageGroupe() { return messageGroupe; }
|
||||
public void setMessageGroupe(MessageGroupe messageGroupe) { this.messageGroupe = messageGroupe; }
|
||||
|
||||
// Classes internes
|
||||
public static class Filtres {
|
||||
private String nom;
|
||||
private String prenom;
|
||||
private String email;
|
||||
private String telephone;
|
||||
private String numeroMembre;
|
||||
private String profession;
|
||||
private List<String> statuts = new ArrayList<>();
|
||||
private List<String> typesMembre = new ArrayList<>();
|
||||
private List<Long> entites = new ArrayList<>();
|
||||
private List<String> statutsCotisation = new ArrayList<>();
|
||||
private List<String> genres = new ArrayList<>();
|
||||
private Integer ageMin;
|
||||
private Integer ageMax;
|
||||
private String ville;
|
||||
private LocalDate dateAdhesionDebut;
|
||||
private LocalDate dateAdhesionFin;
|
||||
private Integer tauxParticipationMin;
|
||||
private Integer evenementsMin;
|
||||
private Integer cotisationsMin;
|
||||
private Boolean aDesEnfants;
|
||||
private Boolean aRecuAides;
|
||||
|
||||
// Getters et setters
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public String getPrenom() { return prenom; }
|
||||
public void setPrenom(String prenom) { this.prenom = prenom; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public String getTelephone() { return telephone; }
|
||||
public void setTelephone(String telephone) { this.telephone = telephone; }
|
||||
|
||||
public String getNumeroMembre() { return numeroMembre; }
|
||||
public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
|
||||
|
||||
public String getProfession() { return profession; }
|
||||
public void setProfession(String profession) { this.profession = profession; }
|
||||
|
||||
public List<String> getStatuts() { return statuts; }
|
||||
public void setStatuts(List<String> statuts) { this.statuts = statuts; }
|
||||
|
||||
public List<String> getTypesMembre() { return typesMembre; }
|
||||
public void setTypesMembre(List<String> typesMembre) { this.typesMembre = typesMembre; }
|
||||
|
||||
public List<Long> getEntites() { return entites; }
|
||||
public void setEntites(List<Long> entites) { this.entites = entites; }
|
||||
|
||||
public List<String> getStatutsCotisation() { return statutsCotisation; }
|
||||
public void setStatutsCotisation(List<String> statutsCotisation) { this.statutsCotisation = statutsCotisation; }
|
||||
|
||||
public List<String> getGenres() { return genres; }
|
||||
public void setGenres(List<String> genres) { this.genres = genres; }
|
||||
|
||||
public Integer getAgeMin() { return ageMin; }
|
||||
public void setAgeMin(Integer ageMin) { this.ageMin = ageMin; }
|
||||
|
||||
public Integer getAgeMax() { return ageMax; }
|
||||
public void setAgeMax(Integer ageMax) { this.ageMax = ageMax; }
|
||||
|
||||
public String getVille() { return ville; }
|
||||
public void setVille(String ville) { this.ville = ville; }
|
||||
|
||||
public LocalDate getDateAdhesionDebut() { return dateAdhesionDebut; }
|
||||
public void setDateAdhesionDebut(LocalDate dateAdhesionDebut) { this.dateAdhesionDebut = dateAdhesionDebut; }
|
||||
|
||||
public LocalDate getDateAdhesionFin() { return dateAdhesionFin; }
|
||||
public void setDateAdhesionFin(LocalDate dateAdhesionFin) { this.dateAdhesionFin = dateAdhesionFin; }
|
||||
|
||||
public Integer getTauxParticipationMin() { return tauxParticipationMin; }
|
||||
public void setTauxParticipationMin(Integer tauxParticipationMin) { this.tauxParticipationMin = tauxParticipationMin; }
|
||||
|
||||
public Integer getEvenementsMin() { return evenementsMin; }
|
||||
public void setEvenementsMin(Integer evenementsMin) { this.evenementsMin = evenementsMin; }
|
||||
|
||||
public Integer getCotisationsMin() { return cotisationsMin; }
|
||||
public void setCotisationsMin(Integer cotisationsMin) { this.cotisationsMin = cotisationsMin; }
|
||||
|
||||
public Boolean getADesEnfants() { return aDesEnfants; }
|
||||
public void setADesEnfants(Boolean aDesEnfants) { this.aDesEnfants = aDesEnfants; }
|
||||
|
||||
public Boolean getARecuAides() { return aRecuAides; }
|
||||
public void setARecuAides(Boolean aRecuAides) { this.aRecuAides = aRecuAides; }
|
||||
}
|
||||
|
||||
public static class Statistiques {
|
||||
private int totalMembres;
|
||||
private int resultatsActuels;
|
||||
private int filtresActifs;
|
||||
private int tempsRecherche;
|
||||
|
||||
// Getters et setters
|
||||
public int getTotalMembres() { return totalMembres; }
|
||||
public void setTotalMembres(int totalMembres) { this.totalMembres = totalMembres; }
|
||||
|
||||
public int getResultatsActuels() { return resultatsActuels; }
|
||||
public void setResultatsActuels(int resultatsActuels) { this.resultatsActuels = resultatsActuels; }
|
||||
|
||||
public int getFiltresActifs() { return filtresActifs; }
|
||||
public void setFiltresActifs(int filtresActifs) { this.filtresActifs = filtresActifs; }
|
||||
|
||||
public int getTempsRecherche() { return tempsRecherche; }
|
||||
public void setTempsRecherche(int tempsRecherche) { this.tempsRecherche = tempsRecherche; }
|
||||
}
|
||||
|
||||
public static class Membre {
|
||||
private UUID id;
|
||||
private String numeroMembre;
|
||||
private String nom;
|
||||
private String prenom;
|
||||
private String email;
|
||||
private String telephone;
|
||||
private String profession;
|
||||
private String ville;
|
||||
private String typeMembre;
|
||||
private String statut;
|
||||
private String entite;
|
||||
private LocalDate dateAdhesion;
|
||||
private String cotisationStatut;
|
||||
private int tauxParticipation;
|
||||
private int evenementsAnnee;
|
||||
private String photoUrl;
|
||||
private String genre;
|
||||
private int age;
|
||||
private boolean aDesEnfants;
|
||||
private boolean aRecuAides;
|
||||
|
||||
// Getters et setters
|
||||
public UUID getId() { return id; }
|
||||
public void setId(UUID id) { this.id = id; }
|
||||
|
||||
public String getNumeroMembre() { return numeroMembre; }
|
||||
public void setNumeroMembre(String numeroMembre) { this.numeroMembre = numeroMembre; }
|
||||
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public String getPrenom() { return prenom; }
|
||||
public void setPrenom(String prenom) { this.prenom = prenom; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public String getTelephone() { return telephone; }
|
||||
public void setTelephone(String telephone) { this.telephone = telephone; }
|
||||
|
||||
public String getProfession() { return profession; }
|
||||
public void setProfession(String profession) { this.profession = profession; }
|
||||
|
||||
public String getVille() { return ville; }
|
||||
public void setVille(String ville) { this.ville = ville; }
|
||||
|
||||
public String getTypeMembre() { return typeMembre; }
|
||||
public void setTypeMembre(String typeMembre) { this.typeMembre = typeMembre; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getEntite() { return entite; }
|
||||
public void setEntite(String entite) { this.entite = entite; }
|
||||
|
||||
public LocalDate getDateAdhesion() { return dateAdhesion; }
|
||||
public void setDateAdhesion(LocalDate dateAdhesion) { this.dateAdhesion = dateAdhesion; }
|
||||
|
||||
public String getCotisationStatut() { return cotisationStatut; }
|
||||
public void setCotisationStatut(String cotisationStatut) { this.cotisationStatut = cotisationStatut; }
|
||||
|
||||
public int getTauxParticipation() { return tauxParticipation; }
|
||||
public void setTauxParticipation(int tauxParticipation) { this.tauxParticipation = tauxParticipation; }
|
||||
|
||||
public int getEvenementsAnnee() { return evenementsAnnee; }
|
||||
public void setEvenementsAnnee(int evenementsAnnee) { this.evenementsAnnee = evenementsAnnee; }
|
||||
|
||||
public String getPhotoUrl() { return photoUrl; }
|
||||
public void setPhotoUrl(String photoUrl) { this.photoUrl = photoUrl; }
|
||||
|
||||
public String getGenre() { return genre; }
|
||||
public void setGenre(String genre) { this.genre = genre; }
|
||||
|
||||
public int getAge() { return age; }
|
||||
public void setAge(int age) { this.age = age; }
|
||||
|
||||
public boolean isADesEnfants() { return aDesEnfants; }
|
||||
public void setADesEnfants(boolean aDesEnfants) { this.aDesEnfants = aDesEnfants; }
|
||||
|
||||
public boolean isARecuAides() { return aRecuAides; }
|
||||
public void setARecuAides(boolean aRecuAides) { this.aRecuAides = aRecuAides; }
|
||||
|
||||
// Propriétés dérivées
|
||||
public String getNomComplet() {
|
||||
return prenom + " " + nom;
|
||||
}
|
||||
|
||||
public String getInitiales() {
|
||||
return (prenom != null ? prenom.substring(0, 1) : "") +
|
||||
(nom != null ? nom.substring(0, 1) : "");
|
||||
}
|
||||
|
||||
public String getTypeSeverity() {
|
||||
return switch (typeMembre) {
|
||||
case "ACTIF" -> "info";
|
||||
case "ASSOCIE" -> "success";
|
||||
case "BIENFAITEUR" -> "warning";
|
||||
case "HONORAIRE" -> "secondary";
|
||||
default -> "info";
|
||||
};
|
||||
}
|
||||
|
||||
public String getTypeIcon() {
|
||||
return switch (typeMembre) {
|
||||
case "ACTIF" -> "pi-user";
|
||||
case "ASSOCIE" -> "pi-users";
|
||||
case "BIENFAITEUR" -> "pi-star";
|
||||
case "HONORAIRE" -> "pi-crown";
|
||||
default -> "pi-user";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutSeverity() {
|
||||
return switch (statut) {
|
||||
case "ACTIF" -> "success";
|
||||
case "INACTIF" -> "warning";
|
||||
case "SUSPENDU" -> "danger";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutIcon() {
|
||||
return switch (statut) {
|
||||
case "ACTIF" -> "pi-check";
|
||||
case "INACTIF" -> "pi-pause";
|
||||
case "SUSPENDU" -> "pi-ban";
|
||||
default -> "pi-circle";
|
||||
};
|
||||
}
|
||||
|
||||
public String getAnciennete() {
|
||||
if (dateAdhesion == null) return "N/A";
|
||||
long mois = java.time.temporal.ChronoUnit.MONTHS.between(dateAdhesion, LocalDate.now());
|
||||
if (mois < 12) return mois + " mois";
|
||||
return (mois / 12) + " an" + (mois / 12 > 1 ? "s" : "");
|
||||
}
|
||||
|
||||
public String getDernierPaiement() {
|
||||
return cotisationStatut.equals("À jour") ? "Ce mois" : "En retard";
|
||||
}
|
||||
|
||||
public String getCotisationColor() {
|
||||
return cotisationStatut.equals("À jour") ? "text-green-500" : "text-red-500";
|
||||
}
|
||||
}
|
||||
|
||||
public static class Entite {
|
||||
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; }
|
||||
}
|
||||
|
||||
public static class RechercheSauvegardee {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
private String description;
|
||||
private int nombreCriteres;
|
||||
private LocalDate dateCreation;
|
||||
private boolean publique;
|
||||
|
||||
// Getters et setters
|
||||
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 getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public int getNombreCriteres() { return nombreCriteres; }
|
||||
public void setNombreCriteres(int nombreCriteres) { this.nombreCriteres = nombreCriteres; }
|
||||
|
||||
public LocalDate getDateCreation() { return dateCreation; }
|
||||
public void setDateCreation(LocalDate dateCreation) { this.dateCreation = dateCreation; }
|
||||
|
||||
public boolean isPublique() { return publique; }
|
||||
public void setPublique(boolean publique) { this.publique = publique; }
|
||||
}
|
||||
|
||||
public static class MessageGroupe {
|
||||
private String sujet;
|
||||
private String contenu;
|
||||
private List<String> canaux = new ArrayList<>();
|
||||
|
||||
// Getters et setters
|
||||
public String getSujet() { return sujet; }
|
||||
public void setSujet(String sujet) { this.sujet = sujet; }
|
||||
|
||||
public String getContenu() { return contenu; }
|
||||
public void setContenu(String contenu) { this.contenu = contenu; }
|
||||
|
||||
public List<String> getCanaux() { return canaux; }
|
||||
public void setCanaux(List<String> canaux) { this.canaux = canaux; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Bean de navigation avec authentification Keycloak OIDC
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
*/
|
||||
@Named("navigationBean")
|
||||
@RequestScoped
|
||||
public class NavigationBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(NavigationBean.class.getName());
|
||||
|
||||
@Inject
|
||||
private UserSession userSession;
|
||||
|
||||
public void checkAuthentication() throws IOException {
|
||||
FacesContext context = FacesContext.getCurrentInstance();
|
||||
|
||||
if (isUserAuthenticated()) {
|
||||
// L'utilisateur est connecté, rediriger vers le dashboard approprié
|
||||
String dashboardUrl = getDashboardUrlForUserType();
|
||||
context.getExternalContext().redirect(
|
||||
context.getExternalContext().getRequestContextPath() + dashboardUrl
|
||||
);
|
||||
} else {
|
||||
// L'utilisateur n'est pas connecté, rediriger vers la racine qui déclenchera Keycloak
|
||||
context.getExternalContext().redirect(
|
||||
context.getExternalContext().getRequestContextPath() + "/"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public String redirectToLogin() {
|
||||
// Redirection vers la racine qui déclenchera automatiquement Keycloak
|
||||
return "/?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String goToDashboard() {
|
||||
if (!isUserAuthenticated()) {
|
||||
return redirectToLogin();
|
||||
}
|
||||
|
||||
return getDashboardUrlForUserType() + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String redirectToDashboard() {
|
||||
return goToDashboard();
|
||||
}
|
||||
|
||||
public String goToProfile() {
|
||||
if (!isUserAuthenticated()) {
|
||||
return redirectToLogin();
|
||||
}
|
||||
|
||||
return "/pages/secure/profile?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String goToSettings() {
|
||||
if (!isUserAuthenticated()) {
|
||||
return redirectToLogin();
|
||||
}
|
||||
|
||||
if (userSession.isSuperAdmin()) {
|
||||
return "/pages/super-admin/configuration/systeme?faces-redirect=true";
|
||||
} else if (userSession.isAdmin()) {
|
||||
return "/pages/admin/parametres?faces-redirect=true";
|
||||
} else {
|
||||
return "/pages/membre/parametres?faces-redirect=true";
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isUserAuthenticated() {
|
||||
// Avec Keycloak OIDC, UserSession vérifie automatiquement l'authentification via JsonWebToken
|
||||
return userSession != null && userSession.isAuthenticated();
|
||||
}
|
||||
|
||||
private String getDashboardUrlForUserType() {
|
||||
if (userSession == null || userSession.getTypeCompte() == null) {
|
||||
return "/pages/secure/dashboard.xhtml";
|
||||
}
|
||||
|
||||
switch (userSession.getTypeCompte()) {
|
||||
case "SUPER_ADMIN":
|
||||
return "/pages/super-admin/dashboard.xhtml";
|
||||
case "ADMIN_ENTITE":
|
||||
return "/pages/admin/dashboard.xhtml";
|
||||
case "MEMBRE":
|
||||
return "/pages/membre/dashboard.xhtml";
|
||||
default:
|
||||
LOGGER.warning("Type de compte non reconnu: " + userSession.getTypeCompte());
|
||||
return "/pages/secure/dashboard.xhtml";
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canAccessSuperAdminPages() {
|
||||
return isUserAuthenticated() && userSession.isSuperAdmin();
|
||||
}
|
||||
|
||||
public boolean canAccessAdminPages() {
|
||||
return isUserAuthenticated() && userSession.isAdmin();
|
||||
}
|
||||
|
||||
public boolean canAccessMemberPages() {
|
||||
return isUserAuthenticated() && userSession.isMembre();
|
||||
}
|
||||
|
||||
public String getCurrentPageTitle() {
|
||||
FacesContext context = FacesContext.getCurrentInstance();
|
||||
String viewId = context.getViewRoot().getViewId();
|
||||
|
||||
if (viewId.contains("dashboard")) {
|
||||
return "Tableau de Bord";
|
||||
} else if (viewId.contains("membres")) {
|
||||
return "Gestion des Membres";
|
||||
} else if (viewId.contains("entites")) {
|
||||
return "Gestion des Entités";
|
||||
} else if (viewId.contains("configuration")) {
|
||||
return "Configuration";
|
||||
} else if (viewId.contains("rapports")) {
|
||||
return "Rapports et Statistiques";
|
||||
}
|
||||
|
||||
return "UnionFlow";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.dto.AssociationDTO;
|
||||
import dev.lions.unionflow.client.service.AssociationService;
|
||||
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.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
|
||||
/**
|
||||
* Bean de consultation d'une organisation (fiche détaillée en lecture seule).
|
||||
*/
|
||||
@Named("organisationDetailBean")
|
||||
@ViewScoped
|
||||
public class OrganisationDetailBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(OrganisationDetailBean.class.getName());
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
AssociationService associationService;
|
||||
|
||||
private AssociationDTO organisation;
|
||||
|
||||
private UUID organisationId;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
// Récupérer l'ID depuis les paramètres de requête
|
||||
String idParam = FacesContext.getCurrentInstance()
|
||||
.getExternalContext()
|
||||
.getRequestParameterMap()
|
||||
.get("id");
|
||||
|
||||
if (idParam != null && !idParam.isBlank()) {
|
||||
try {
|
||||
organisationId = UUID.fromString(idParam);
|
||||
chargerOrganisation();
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOGGER.severe("ID d'organisation invalide: " + idParam);
|
||||
ajouterMessageErreur("Organisation introuvable", "Identifiant invalide.");
|
||||
}
|
||||
} else {
|
||||
ajouterMessageErreur("Organisation introuvable", "Aucun identifiant fourni.");
|
||||
}
|
||||
}
|
||||
|
||||
public void chargerOrganisation() {
|
||||
if (organisationId == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
organisation = associationService.obtenirParId(organisationId);
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement de l'organisation: " + e.getMessage());
|
||||
ajouterMessageErreur("Organisation introuvable",
|
||||
"Impossible de charger les détails de l'organisation.");
|
||||
}
|
||||
}
|
||||
|
||||
public void revenirAListe() throws IOException {
|
||||
FacesContext.getCurrentInstance()
|
||||
.getExternalContext()
|
||||
.redirect(FacesContext.getCurrentInstance()
|
||||
.getExternalContext()
|
||||
.getRequestContextPath() + "/pages/secure/organisation/liste.xhtml");
|
||||
}
|
||||
|
||||
private void ajouterMessageErreur(String resume, String detail) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, resume, detail));
|
||||
}
|
||||
|
||||
public AssociationDTO getOrganisation() {
|
||||
return organisation;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,448 @@
|
||||
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 (dev.lions.unionflow.client.service.RestClientExceptionMapper.UnauthorizedException e) {
|
||||
// Non bloquant: afficher une info et calculer depuis la liste
|
||||
LOGGER.warning("Statistiques non autorisées (401): " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO,
|
||||
"Information",
|
||||
"Statistiques indisponibles (non autorisé) — affichage des données sans stats."));
|
||||
totalOrganisations = organisations.size();
|
||||
organisationsActives = organisations.stream()
|
||||
.filter(o -> o.getStatut() != null && StatutOrganisationConstants.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);
|
||||
|
||||
// S'assurer que le catalogue des types est chargé avant d'initialiser le formulaire
|
||||
if (typesCatalogue == null || typesCatalogue.isEmpty()) {
|
||||
chargerTypesOrganisation();
|
||||
}
|
||||
|
||||
// Déterminer un type par défaut dynamique (premier type actif du catalogue)
|
||||
String typeDefaut = null;
|
||||
if (typesCatalogue != null) {
|
||||
typeDefaut = typesCatalogue.stream()
|
||||
.filter(t -> t.getActif() == null || Boolean.TRUE.equals(t.getActif()))
|
||||
.map(TypeOrganisationClientDTO::getCode)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
nouvelleOrganisation.setTypeAssociation(typeDefaut);
|
||||
nouvelleOrganisation.setDateFondation(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.suspendre(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"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recherche les organisations dont le nom contient la requête fournie.
|
||||
* Méthode utilitaire côté client qui délègue au service REST backend.
|
||||
*
|
||||
* @param query terme de recherche (partie du nom)
|
||||
* @return liste d'organisations correspondant au critère, ou liste vide en cas d'erreur
|
||||
*/
|
||||
public List<AssociationDTO> rechercherOrganisations(String query) {
|
||||
if (query == null || query.trim().isEmpty()) {
|
||||
return organisations; // rien saisi : on renvoie la liste actuelle
|
||||
}
|
||||
try {
|
||||
// On délègue au endpoint /api/organisations/recherche avec uniquement le nom rempli.
|
||||
List<AssociationDTO> resultats = associationService.rechercher(
|
||||
query, // nom
|
||||
null, // type
|
||||
null, // statut
|
||||
null, // region
|
||||
null, // ville
|
||||
0, // page
|
||||
100 // size
|
||||
);
|
||||
LOGGER.info("Recherche d'organisations pour '" + query + "': " +
|
||||
(resultats != null ? resultats.size() : 0) + " résultat(s)");
|
||||
return resultats != null ? resultats : List.of();
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la recherche d'organisations pour '" + query + "': " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR,
|
||||
"Erreur", "Impossible de rechercher les organisations: " + e.getMessage()));
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recharge la liste et les statistiques (DRY)
|
||||
*/
|
||||
public void recharger() {
|
||||
chargerOrganisations();
|
||||
chargerStatistiques();
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
566
src/main/java/dev/lions/unionflow/client/view/PersonnelBean.java
Normal file
566
src/main/java/dev/lions/unionflow/client/view/PersonnelBean.java
Normal 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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.view.RapportsBean.HistoriqueRapport;
|
||||
import jakarta.faces.view.ViewScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.faces.application.FacesMessage;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Bean pour la page de détails d'un rapport (WOU/DRY)
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
*/
|
||||
@Named("rapportDetailsBean")
|
||||
@ViewScoped
|
||||
public class RapportDetailsBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(RapportDetailsBean.class.getName());
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("dd/MM/yyyy");
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_RAPPORTS = "rapportMembresPage";
|
||||
|
||||
@Inject
|
||||
private RapportsBean rapportsBean;
|
||||
|
||||
private UUID rapportId;
|
||||
private HistoriqueRapport rapport;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
// Récupérer l'ID du rapport depuis le paramètre de requête
|
||||
String idParam = FacesContext.getCurrentInstance()
|
||||
.getExternalContext()
|
||||
.getRequestParameterMap()
|
||||
.get("id");
|
||||
|
||||
if (idParam != null && !idParam.isEmpty()) {
|
||||
try {
|
||||
rapportId = UUID.fromString(idParam);
|
||||
chargerRapport();
|
||||
} catch (IllegalArgumentException e) {
|
||||
LOGGER.severe("ID de rapport invalide: " + idParam);
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"ID de rapport invalide"));
|
||||
}
|
||||
} else {
|
||||
// Si pas d'ID, utiliser le rapport sélectionné depuis RapportsBean (WOU/DRY)
|
||||
if (rapportsBean != null && rapportsBean.getRapportSelectionne() != null) {
|
||||
rapport = rapportsBean.getRapportSelectionne();
|
||||
rapportId = rapport.getId();
|
||||
} else {
|
||||
LOGGER.warning("Aucun rapport sélectionné et aucun ID fourni");
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Aucun rapport à afficher"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void chargerRapport() {
|
||||
if (rapportsBean == null) {
|
||||
LOGGER.severe("RapportsBean non injecté");
|
||||
return;
|
||||
}
|
||||
|
||||
// Chercher le rapport dans la liste de RapportsBean (WOU/DRY - réutilise les données)
|
||||
if (rapportsBean.getHistoriqueRapports() != null) {
|
||||
rapport = rapportsBean.getHistoriqueRapports().stream()
|
||||
.filter(r -> r.getId().equals(rapportId))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
if (rapport == null) {
|
||||
LOGGER.warning("Rapport non trouvé avec l'ID: " + rapportId);
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Rapport non trouvé"));
|
||||
}
|
||||
}
|
||||
|
||||
public String retourner() {
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_RAPPORTS + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public void telechargerRapport() {
|
||||
if (rapport != null) {
|
||||
try {
|
||||
// Vérifier que le rapport est disponible
|
||||
if (!"GENERE".equals(rapport.getStatut())) {
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_WARN, "Attention",
|
||||
"Le rapport n'est pas encore disponible au téléchargement."));
|
||||
return;
|
||||
}
|
||||
|
||||
LOGGER.info("Téléchargement du rapport: " + rapport.getTypeLibelle()
|
||||
+ " (ID: " + rapport.getId() + ")");
|
||||
|
||||
// Le téléchargement sera géré par le XHTML avec p:fileDownload ou un lien direct
|
||||
// vers le endpoint REST qui génère le fichier
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Téléchargement",
|
||||
"Le téléchargement du rapport '" + rapport.getTypeLibelle() + "' va commencer."));
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du téléchargement du rapport: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de télécharger le rapport. Veuillez réessayer."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void regenererRapport() {
|
||||
if (rapport != null) {
|
||||
try {
|
||||
LOGGER.info("Régénération du rapport: " + rapport.getTypeLibelle()
|
||||
+ " (ID: " + rapport.getId() + ")");
|
||||
|
||||
// Mettre à jour le statut du rapport localement
|
||||
rapport.setStatut("EN_GENERATION");
|
||||
rapport.setDateGeneration(LocalDate.now());
|
||||
|
||||
// Rafraîchir les données depuis RapportsBean (WOU/DRY)
|
||||
if (rapportsBean != null) {
|
||||
rapportsBean.actualiser();
|
||||
// Recharger le rapport mis à jour
|
||||
chargerRapport();
|
||||
}
|
||||
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Régénération",
|
||||
"Le rapport '" + rapport.getTypeLibelle() + "' est en cours de régénération. "
|
||||
+ "Vous serez notifié une fois la génération terminée."));
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la régénération du rapport: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de régénérer le rapport. Veuillez réessayer."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public UUID getRapportId() { return rapportId; }
|
||||
public void setRapportId(UUID rapportId) { this.rapportId = rapportId; }
|
||||
|
||||
public HistoriqueRapport getRapport() { return rapport; }
|
||||
public void setRapport(HistoriqueRapport rapport) { this.rapport = rapport; }
|
||||
|
||||
// Méthodes utilitaires pour l'affichage
|
||||
public String getDateGenerationFormatee() {
|
||||
if (rapport != null && rapport.getDateGeneration() != null) {
|
||||
return rapport.getDateGeneration().format(DATE_FORMATTER);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
public boolean isRapportDisponible() {
|
||||
return rapport != null && "GENERE".equals(rapport.getStatut());
|
||||
}
|
||||
}
|
||||
|
||||
798
src/main/java/dev/lions/unionflow/client/view/RapportsBean.java
Normal file
798
src/main/java/dev/lions/unionflow/client/view/RapportsBean.java
Normal file
@@ -0,0 +1,798 @@
|
||||
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 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.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;
|
||||
|
||||
@Named("rapportsBean")
|
||||
@SessionScoped
|
||||
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");
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_RAPPORT_DETAILS = "rapportDetailsPage";
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private AnalyticsService analyticsService;
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private MembreService membreService;
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private CotisationService cotisationService;
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private EvenementService evenementService;
|
||||
|
||||
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> kpisList;
|
||||
private List<Alerte> alertes;
|
||||
private List<HistoriqueRapport> historiqueRapports;
|
||||
|
||||
private NouveauRapport nouveauRapport;
|
||||
private HistoriqueRapport rapportSelectionne;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initializePeriodes();
|
||||
chargerDonnees();
|
||||
}
|
||||
|
||||
private void initializePeriodes() {
|
||||
periodeRapide = "TRENTE_DERNIERS_JOURS";
|
||||
dateDebut = LocalDate.now().minusDays(30);
|
||||
dateFin = LocalDate.now();
|
||||
groupeComparaison = "PERIODE_PRECEDENTE";
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, "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);
|
||||
|
||||
indicateurs.setTotalMembres(totalMembres);
|
||||
indicateurs.setCroissanceMembres(calculerCroissance("NOMBRE_MEMBRES_ACTIFS"));
|
||||
indicateurs.setRevenus(formatMontantCourt(totalRevenus) + " FCFA");
|
||||
indicateurs.setCroissanceRevenus(calculerCroissance("TOTAL_COTISATIONS_COLLECTEES"));
|
||||
indicateurs.setTotalEvenements(totalEvenements);
|
||||
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());
|
||||
initialiserIndicateursVides();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule les répartitions
|
||||
*/
|
||||
private void calculerRepartitions() {
|
||||
repartitionMembres = new ArrayList<>();
|
||||
try {
|
||||
List<dev.lions.unionflow.client.dto.MembreDTO> membres = membreService.listerTous();
|
||||
long actifs = membres.stream().filter(m -> "ACTIF".equals(m.getStatut())).count();
|
||||
long inactifs = membres.stream().filter(m -> "INACTIF".equals(m.getStatut())).count();
|
||||
long total = membres.size();
|
||||
|
||||
if (total > 0) {
|
||||
RepartitionMembres actifsRep = new RepartitionMembres();
|
||||
actifsRep.setLibelle("Membres Actifs");
|
||||
actifsRep.setNombre((int) actifs);
|
||||
actifsRep.setPourcentage((double) actifs / total * 100.0);
|
||||
actifsRep.setCouleur("green-500");
|
||||
repartitionMembres.add(actifsRep);
|
||||
|
||||
RepartitionMembres inactifsRep = new RepartitionMembres();
|
||||
inactifsRep.setLibelle("Membres Inactifs");
|
||||
inactifsRep.setNombre((int) inactifs);
|
||||
inactifsRep.setPourcentage((double) inactifs / total * 100.0);
|
||||
inactifsRep.setCouleur("orange-500");
|
||||
repartitionMembres.add(inactifsRep);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du calcul de la répartition des membres: " + e.getMessage());
|
||||
}
|
||||
|
||||
sourceRevenus = new ArrayList<>();
|
||||
try {
|
||||
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);
|
||||
|
||||
if (totalRevenus.compareTo(BigDecimal.ZERO) > 0) {
|
||||
SourceRevenus cotisations = new SourceRevenus();
|
||||
cotisations.setLibelle("Cotisations");
|
||||
cotisations.setMontant(formatMontantCourt(totalRevenus));
|
||||
cotisations.setPourcentage(100.0);
|
||||
cotisations.setCouleur("blue-500");
|
||||
cotisations.setIcon("pi-users");
|
||||
sourceRevenus.add(cotisations);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du calcul des sources de revenus: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule les objectifs
|
||||
*/
|
||||
private void calculerObjectifs() {
|
||||
objectifs = new ArrayList<>();
|
||||
try {
|
||||
int totalMembres = membreService.listerTous().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);
|
||||
|
||||
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 calcul des objectifs: " + 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 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<>();
|
||||
historiqueRapports = new ArrayList<>();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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());
|
||||
|
||||
HistoriqueRapport nouveauHistorique = new HistoriqueRapport();
|
||||
nouveauHistorique.setId(UUID.randomUUID());
|
||||
nouveauHistorique.setType(nouveauRapport.getType());
|
||||
nouveauHistorique.setTypeLibelle(getTypeLibelle(nouveauRapport.getType()));
|
||||
nouveauHistorique.setTypeIcon(getTypeIcon(nouveauRapport.getType()));
|
||||
nouveauHistorique.setTypeCouleur(getTypeCouleur(nouveauRapport.getType()));
|
||||
nouveauHistorique.setDateGeneration(LocalDate.now());
|
||||
nouveauHistorique.setPeriodeCouverte(getPeriodeDescription(nouveauRapport.getPeriode()));
|
||||
nouveauHistorique.setGenerePar("Utilisateur Actuel");
|
||||
nouveauHistorique.setStatut("EN_COURS");
|
||||
|
||||
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) {
|
||||
return switch (type) {
|
||||
case "FINANCIER" -> "Rapport Financier";
|
||||
case "MEMBRES" -> "Rapport Membres";
|
||||
case "ACTIVITES" -> "Rapport Activités";
|
||||
case "PERFORMANCE" -> "Rapport Performance";
|
||||
case "COMPLET" -> "Rapport Complet";
|
||||
default -> type;
|
||||
};
|
||||
}
|
||||
|
||||
private String getTypeIcon(String type) {
|
||||
return switch (type) {
|
||||
case "FINANCIER" -> "pi-dollar";
|
||||
case "MEMBRES" -> "pi-users";
|
||||
case "ACTIVITES" -> "pi-calendar";
|
||||
case "PERFORMANCE" -> "pi-chart-bar";
|
||||
case "COMPLET" -> "pi-file";
|
||||
default -> "pi-file";
|
||||
};
|
||||
}
|
||||
|
||||
private String getTypeCouleur(String type) {
|
||||
return switch (type) {
|
||||
case "FINANCIER" -> "green-500";
|
||||
case "MEMBRES" -> "blue-500";
|
||||
case "ACTIVITES" -> "orange-500";
|
||||
case "PERFORMANCE" -> "purple-500";
|
||||
case "COMPLET" -> "indigo-500";
|
||||
default -> "gray-500";
|
||||
};
|
||||
}
|
||||
|
||||
private String getPeriodeDescription(String periode) {
|
||||
return switch (periode) {
|
||||
case "7_JOURS" -> "7 derniers jours";
|
||||
case "30_JOURS" -> "30 derniers jours";
|
||||
case "3_MOIS" -> "3 derniers mois";
|
||||
case "6_MOIS" -> "6 derniers mois";
|
||||
case "ANNEE_COURANTE" -> "Année en cours";
|
||||
case "PERSONNALISEE" -> "Période personnalisée";
|
||||
default -> periode;
|
||||
};
|
||||
}
|
||||
|
||||
public String voirRapport(HistoriqueRapport rapport) {
|
||||
rapportSelectionne = rapport;
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_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;
|
||||
chargerDonnees();
|
||||
}
|
||||
|
||||
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 String getGroupeComparaison() { return groupeComparaison; }
|
||||
public void setGroupeComparaison(String groupeComparaison) { this.groupeComparaison = groupeComparaison; }
|
||||
|
||||
public IndicateursGlobaux getIndicateurs() { return indicateurs; }
|
||||
public void setIndicateurs(IndicateursGlobaux indicateurs) { this.indicateurs = indicateurs; }
|
||||
|
||||
public List<EvolutionMensuelle> getEvolutionMensuelle() { return evolutionMensuelle; }
|
||||
public void setEvolutionMensuelle(List<EvolutionMensuelle> evolutionMensuelle) { this.evolutionMensuelle = evolutionMensuelle; }
|
||||
|
||||
public List<Objectif> getObjectifs() { return objectifs; }
|
||||
public void setObjectifs(List<Objectif> objectifs) { this.objectifs = objectifs; }
|
||||
|
||||
public List<RepartitionMembres> getRepartitionMembres() { return repartitionMembres; }
|
||||
public void setRepartitionMembres(List<RepartitionMembres> repartitionMembres) { this.repartitionMembres = repartitionMembres; }
|
||||
|
||||
public List<SourceRevenus> getSourceRevenus() { return sourceRevenus; }
|
||||
public void setSourceRevenus(List<SourceRevenus> sourceRevenus) { this.sourceRevenus = sourceRevenus; }
|
||||
|
||||
public List<TopEntite> getTopEntites() { return topEntites; }
|
||||
public void setTopEntites(List<TopEntite> topEntites) { this.topEntites = topEntites; }
|
||||
|
||||
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; }
|
||||
|
||||
public List<HistoriqueRapport> getHistoriqueRapports() { return historiqueRapports; }
|
||||
public void setHistoriqueRapports(List<HistoriqueRapport> historiqueRapports) { this.historiqueRapports = historiqueRapports; }
|
||||
|
||||
public NouveauRapport getNouveauRapport() { return nouveauRapport; }
|
||||
public void setNouveauRapport(NouveauRapport nouveauRapport) { this.nouveauRapport = nouveauRapport; }
|
||||
|
||||
public HistoriqueRapport getRapportSelectionne() { return rapportSelectionne; }
|
||||
public void setRapportSelectionne(HistoriqueRapport rapportSelectionne) { this.rapportSelectionne = rapportSelectionne; }
|
||||
|
||||
// Classes internes (conservées pour compatibilité avec les pages XHTML)
|
||||
public static class IndicateursGlobaux {
|
||||
private int totalMembres;
|
||||
private double croissanceMembres;
|
||||
private String revenus;
|
||||
private double croissanceRevenus;
|
||||
private int totalEvenements;
|
||||
private double croissanceEvenements;
|
||||
private String totalAides;
|
||||
private double croissanceAides;
|
||||
|
||||
public int getTotalMembres() { return totalMembres; }
|
||||
public void setTotalMembres(int totalMembres) { this.totalMembres = totalMembres; }
|
||||
|
||||
public double getCroissanceMembres() { return croissanceMembres; }
|
||||
public void setCroissanceMembres(double croissanceMembres) { this.croissanceMembres = croissanceMembres; }
|
||||
|
||||
public String getRevenus() { return revenus; }
|
||||
public void setRevenus(String revenus) { this.revenus = revenus; }
|
||||
|
||||
public double getCroissanceRevenus() { return croissanceRevenus; }
|
||||
public void setCroissanceRevenus(double croissanceRevenus) { this.croissanceRevenus = croissanceRevenus; }
|
||||
|
||||
public int getTotalEvenements() { return totalEvenements; }
|
||||
public void setTotalEvenements(int totalEvenements) { this.totalEvenements = totalEvenements; }
|
||||
|
||||
public double getCroissanceEvenements() { return croissanceEvenements; }
|
||||
public void setCroissanceEvenements(double croissanceEvenements) { this.croissanceEvenements = croissanceEvenements; }
|
||||
|
||||
public String getTotalAides() { return totalAides; }
|
||||
public void setTotalAides(String totalAides) { this.totalAides = totalAides; }
|
||||
|
||||
public double getCroissanceAides() { return croissanceAides; }
|
||||
public void setCroissanceAides(double croissanceAides) { this.croissanceAides = croissanceAides; }
|
||||
}
|
||||
|
||||
public static class EvolutionMensuelle {
|
||||
private String libelle;
|
||||
private int membres;
|
||||
private double revenus;
|
||||
private int hauteurMembres;
|
||||
private int hauteurRevenus;
|
||||
|
||||
public String getLibelle() { return libelle; }
|
||||
public void setLibelle(String libelle) { this.libelle = libelle; }
|
||||
|
||||
public int getMembres() { return membres; }
|
||||
public void setMembres(int membres) { this.membres = membres; }
|
||||
|
||||
public double getRevenus() { return revenus; }
|
||||
public void setRevenus(double revenus) { this.revenus = revenus; }
|
||||
|
||||
public int getHauteurMembres() { return hauteurMembres; }
|
||||
public void setHauteurMembres(int hauteurMembres) { this.hauteurMembres = hauteurMembres; }
|
||||
|
||||
public int getHauteurRevenus() { return hauteurRevenus; }
|
||||
public void setHauteurRevenus(int hauteurRevenus) { this.hauteurRevenus = hauteurRevenus; }
|
||||
}
|
||||
|
||||
public static class Objectif {
|
||||
private String libelle;
|
||||
private String realise;
|
||||
private String cible;
|
||||
private int pourcentage;
|
||||
|
||||
public String getLibelle() { return libelle; }
|
||||
public void setLibelle(String libelle) { this.libelle = libelle; }
|
||||
|
||||
public String getRealise() { return realise; }
|
||||
public void setRealise(String realise) { this.realise = realise; }
|
||||
|
||||
public String getCible() { return cible; }
|
||||
public void setCible(String cible) { this.cible = cible; }
|
||||
|
||||
public int getPourcentage() { return pourcentage; }
|
||||
public void setPourcentage(int pourcentage) { this.pourcentage = pourcentage; }
|
||||
}
|
||||
|
||||
public static class RepartitionMembres {
|
||||
private String libelle;
|
||||
private int nombre;
|
||||
private double pourcentage;
|
||||
private String couleur;
|
||||
|
||||
public String getLibelle() { return libelle; }
|
||||
public void setLibelle(String libelle) { this.libelle = libelle; }
|
||||
|
||||
public int getNombre() { return nombre; }
|
||||
public void setNombre(int nombre) { this.nombre = nombre; }
|
||||
|
||||
public double getPourcentage() { return pourcentage; }
|
||||
public void setPourcentage(double pourcentage) { this.pourcentage = pourcentage; }
|
||||
|
||||
public String getCouleur() { return couleur; }
|
||||
public void setCouleur(String couleur) { this.couleur = couleur; }
|
||||
}
|
||||
|
||||
public static class SourceRevenus {
|
||||
private String libelle;
|
||||
private String montant;
|
||||
private double pourcentage;
|
||||
private String couleur;
|
||||
private String icon;
|
||||
|
||||
public String getLibelle() { return libelle; }
|
||||
public void setLibelle(String libelle) { this.libelle = libelle; }
|
||||
|
||||
public String getMontant() { return montant; }
|
||||
public void setMontant(String montant) { this.montant = montant; }
|
||||
|
||||
public double getPourcentage() { return pourcentage; }
|
||||
public void setPourcentage(double pourcentage) { this.pourcentage = pourcentage; }
|
||||
|
||||
public String getCouleur() { return couleur; }
|
||||
public void setCouleur(String couleur) { this.couleur = couleur; }
|
||||
|
||||
public String getIcon() { return icon; }
|
||||
public void setIcon(String icon) { this.icon = icon; }
|
||||
}
|
||||
|
||||
public static class TopEntite {
|
||||
private int rang;
|
||||
private String nom;
|
||||
private String typeIcon;
|
||||
private int score;
|
||||
private String tendance;
|
||||
|
||||
public int getRang() { return rang; }
|
||||
public void setRang(int rang) { this.rang = rang; }
|
||||
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public String getTypeIcon() { return typeIcon; }
|
||||
public void setTypeIcon(String typeIcon) { this.typeIcon = typeIcon; }
|
||||
|
||||
public int getScore() { return score; }
|
||||
public void setScore(int score) { this.score = score; }
|
||||
|
||||
public String getTendance() { return tendance; }
|
||||
public void setTendance(String tendance) { this.tendance = tendance; }
|
||||
}
|
||||
|
||||
public static class KPI {
|
||||
private String libelle;
|
||||
private String valeur;
|
||||
private int progression;
|
||||
private double variation;
|
||||
private String tendance;
|
||||
private String icon;
|
||||
private String couleur;
|
||||
|
||||
public String getLibelle() { return libelle; }
|
||||
public void setLibelle(String libelle) { this.libelle = libelle; }
|
||||
|
||||
public String getValeur() { return valeur; }
|
||||
public void setValeur(String valeur) { this.valeur = valeur; }
|
||||
|
||||
public int getProgression() { return progression; }
|
||||
public void setProgression(int progression) { this.progression = progression; }
|
||||
|
||||
public double getVariation() { return variation; }
|
||||
public void setVariation(double variation) { this.variation = variation; }
|
||||
|
||||
public String getTendance() { return tendance; }
|
||||
public void setTendance(String tendance) { this.tendance = tendance; }
|
||||
|
||||
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 Alerte {
|
||||
private String titre;
|
||||
private String description;
|
||||
private String priorite;
|
||||
private String severite;
|
||||
private String severiteCouleur;
|
||||
private String icon;
|
||||
private String dateDetection;
|
||||
|
||||
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 getPriorite() { return priorite; }
|
||||
public void setPriorite(String priorite) { this.priorite = priorite; }
|
||||
|
||||
public String getSeverite() { return severite; }
|
||||
public void setSeverite(String severite) { this.severite = severite; }
|
||||
|
||||
public String getSeveriteCouleur() { return severiteCouleur; }
|
||||
public void setSeveriteCouleur(String severiteCouleur) { this.severiteCouleur = severiteCouleur; }
|
||||
|
||||
public String getIcon() { return icon; }
|
||||
public void setIcon(String icon) { this.icon = icon; }
|
||||
|
||||
public String getDateDetection() { return dateDetection; }
|
||||
public void setDateDetection(String dateDetection) { this.dateDetection = dateDetection; }
|
||||
}
|
||||
|
||||
public static class HistoriqueRapport {
|
||||
private UUID id;
|
||||
private String type;
|
||||
private String typeLibelle;
|
||||
private String typeIcon;
|
||||
private String typeCouleur;
|
||||
private LocalDate dateGeneration;
|
||||
private String periodeCouverte;
|
||||
private String generePar;
|
||||
private String statut;
|
||||
|
||||
public UUID getId() { return id; }
|
||||
public void setId(UUID id) { this.id = id; }
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getTypeLibelle() { return typeLibelle; }
|
||||
public void setTypeLibelle(String typeLibelle) { this.typeLibelle = typeLibelle; }
|
||||
|
||||
public String getTypeIcon() { return typeIcon; }
|
||||
public void setTypeIcon(String typeIcon) { this.typeIcon = typeIcon; }
|
||||
|
||||
public String getTypeCouleur() { return typeCouleur; }
|
||||
public void setTypeCouleur(String typeCouleur) { this.typeCouleur = typeCouleur; }
|
||||
|
||||
public LocalDate getDateGeneration() { return dateGeneration; }
|
||||
public void setDateGeneration(LocalDate dateGeneration) { this.dateGeneration = dateGeneration; }
|
||||
|
||||
public String getPeriodeCouverte() { return periodeCouverte; }
|
||||
public void setPeriodeCouverte(String periodeCouverte) { this.periodeCouverte = periodeCouverte; }
|
||||
|
||||
public String getGenerePar() { return generePar; }
|
||||
public void setGenerePar(String generePar) { this.generePar = generePar; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getDateGenerationFormatee() {
|
||||
if (dateGeneration == null) return "";
|
||||
return dateGeneration.format(DATE_FORMATTER);
|
||||
}
|
||||
|
||||
public String getStatutSeverity() {
|
||||
return switch (statut) {
|
||||
case "GENERE" -> "success";
|
||||
case "EN_COURS" -> "warning";
|
||||
case "PLANIFIE" -> "info";
|
||||
case "ERREUR" -> "danger";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static class NouveauRapport {
|
||||
private String type;
|
||||
private String format;
|
||||
private String periode;
|
||||
private String detail;
|
||||
private String commentaires;
|
||||
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getFormat() { return format; }
|
||||
public void setFormat(String format) { this.format = format; }
|
||||
|
||||
public String getPeriode() { return periode; }
|
||||
public void setPeriode(String periode) { this.periode = periode; }
|
||||
|
||||
public String getDetail() { return detail; }
|
||||
public void setDetail(String detail) { this.detail = detail; }
|
||||
|
||||
public String getCommentaires() { return commentaires; }
|
||||
public void setCommentaires(String commentaires) { this.commentaires = commentaires; }
|
||||
}
|
||||
}
|
||||
367
src/main/java/dev/lions/unionflow/client/view/RolesBean.java
Normal file
367
src/main/java/dev/lions/unionflow/client/view/RolesBean.java
Normal file
@@ -0,0 +1,367 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.inject.Named;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Named("rolesBean")
|
||||
@SessionScoped
|
||||
public class RolesBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// Filtres
|
||||
private String filtreNom = "";
|
||||
private String filtreType = "";
|
||||
private String filtreStatut = "";
|
||||
|
||||
// Rôles
|
||||
private List<Role> roles;
|
||||
private Role roleSelectionne;
|
||||
private Role nouveauRole = new Role();
|
||||
|
||||
public RolesBean() {
|
||||
initialiserRoles();
|
||||
}
|
||||
|
||||
private void initialiserRoles() {
|
||||
// Initialiser avec une liste vide - les rôles seront chargés depuis le backend quand le service sera disponible
|
||||
roles = new ArrayList<>();
|
||||
// TODO: Charger depuis RoleService quand disponible
|
||||
// Exemple: roles = roleService.listerTous();
|
||||
}
|
||||
|
||||
// Getters pour les KPIs
|
||||
public int getTotalRoles() {
|
||||
return roles.size();
|
||||
}
|
||||
|
||||
public int getRolesActifs() {
|
||||
return (int) roles.stream().filter(r -> r.getStatut() == StatutRole.ACTIF).count();
|
||||
}
|
||||
|
||||
public int getUtilisateursAvecRoles() {
|
||||
return roles.stream().mapToInt(Role::getNombreUtilisateurs).sum();
|
||||
}
|
||||
|
||||
public int getPermissionsUniques() {
|
||||
return roles.stream()
|
||||
.flatMap(r -> r.getPermissions().stream())
|
||||
.collect(Collectors.toSet())
|
||||
.size();
|
||||
}
|
||||
|
||||
// Filtrage des rôles
|
||||
public List<Role> getRolesFiltres() {
|
||||
return roles.stream()
|
||||
.filter(this::correspondAuxFiltres)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean correspondAuxFiltres(Role role) {
|
||||
boolean nomOk = filtreNom.isEmpty() ||
|
||||
role.getNom().toLowerCase().contains(filtreNom.toLowerCase()) ||
|
||||
role.getDescription().toLowerCase().contains(filtreNom.toLowerCase());
|
||||
|
||||
boolean typeOk = filtreType.isEmpty() || role.getType().name().equals(filtreType);
|
||||
boolean statutOk = filtreStatut.isEmpty() || role.getStatut().name().equals(filtreStatut);
|
||||
|
||||
return nomOk && typeOk && statutOk;
|
||||
}
|
||||
|
||||
public void reinitialiserFiltres() {
|
||||
filtreNom = "";
|
||||
filtreType = "";
|
||||
filtreStatut = "";
|
||||
}
|
||||
|
||||
// Actions
|
||||
public void voirRole(Role role) {
|
||||
this.roleSelectionne = role;
|
||||
// Charger les détails complets du rôle
|
||||
role.chargerDetailsComplets();
|
||||
}
|
||||
|
||||
public void modifierRole(Role role) {
|
||||
this.roleSelectionne = role;
|
||||
}
|
||||
|
||||
public void gererUtilisateurs(Role role) {
|
||||
this.roleSelectionne = role;
|
||||
}
|
||||
|
||||
public void creerRole() {
|
||||
// Validation
|
||||
if (nouveauRole.getNom().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Génération des propriétés
|
||||
nouveauRole.setCode(genererCodeRole(nouveauRole.getNom()));
|
||||
nouveauRole.setCouleurFond(genererCouleurAleatoire());
|
||||
nouveauRole.setCouleurTexte("#ffffff");
|
||||
nouveauRole.setStatut(StatutRole.ACTIF);
|
||||
nouveauRole.setDateModification(LocalDateTime.now());
|
||||
nouveauRole.setModifiePar("Utilisateur Courant");
|
||||
|
||||
// Ajout à la liste
|
||||
roles.add(nouveauRole);
|
||||
|
||||
// Réinitialisation
|
||||
nouveauRole = new Role();
|
||||
}
|
||||
|
||||
private String genererCodeRole(String nom) {
|
||||
return nom.toUpperCase()
|
||||
.replaceAll("[^A-Z0-9]", "_")
|
||||
.replaceAll("_{2,}", "_");
|
||||
}
|
||||
|
||||
private String genererCouleurAleatoire() {
|
||||
String[] couleurs = {"#ff6b6b", "#4ecdc4", "#45b7d1", "#96ceb4", "#feca57",
|
||||
"#a55eea", "#fd79a8", "#6c5ce7", "#74b9ff", "#00b894"};
|
||||
Random random = new Random();
|
||||
return couleurs[random.nextInt(couleurs.length)];
|
||||
}
|
||||
|
||||
public List<Permission> getPermissionsDisponibles() {
|
||||
List<Permission> permissions = new ArrayList<>();
|
||||
permissions.add(new Permission("GESTION_COMPLETE", "Gestion Complète"));
|
||||
permissions.add(new Permission("ADMIN_SYSTEME", "Administration Système"));
|
||||
permissions.add(new Permission("GESTION_USERS", "Gestion des Utilisateurs"));
|
||||
permissions.add(new Permission("GESTION_ORGS", "Gestion des Organisations"));
|
||||
permissions.add(new Permission("GESTION_MEMBRES", "Gestion des Membres"));
|
||||
permissions.add(new Permission("GESTION_EVENTS", "Gestion des Événements"));
|
||||
permissions.add(new Permission("COMPTABILITE", "Comptabilité"));
|
||||
permissions.add(new Permission("COTISATIONS", "Cotisations"));
|
||||
permissions.add(new Permission("DOCUMENTS", "Documents"));
|
||||
permissions.add(new Permission("COMMUNICATIONS", "Communications"));
|
||||
permissions.add(new Permission("RAPPORTS", "Rapports"));
|
||||
permissions.add(new Permission("AUDIT", "Audit"));
|
||||
permissions.add(new Permission("CONSULTATION", "Consultation"));
|
||||
return permissions;
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public String getFiltreNom() { return filtreNom; }
|
||||
public void setFiltreNom(String filtreNom) { this.filtreNom = filtreNom; }
|
||||
|
||||
public String getFiltreType() { return filtreType; }
|
||||
public void setFiltreType(String filtreType) { this.filtreType = filtreType; }
|
||||
|
||||
public String getFiltreStatut() { return filtreStatut; }
|
||||
public void setFiltreStatut(String filtreStatut) { this.filtreStatut = filtreStatut; }
|
||||
|
||||
public Role getRoleSelectionne() { return roleSelectionne; }
|
||||
public void setRoleSelectionne(Role roleSelectionne) { this.roleSelectionne = roleSelectionne; }
|
||||
|
||||
public Role getNouveauRole() { return nouveauRole; }
|
||||
public void setNouveauRole(Role nouveauRole) { this.nouveauRole = nouveauRole; }
|
||||
|
||||
// Classes internes
|
||||
public static class Role implements Serializable {
|
||||
private String code;
|
||||
private String nom;
|
||||
private String description;
|
||||
private TypeRole type;
|
||||
private StatutRole statut;
|
||||
private String icone;
|
||||
private String couleurFond;
|
||||
private String couleurTexte;
|
||||
private List<String> permissions;
|
||||
private int nombreUtilisateurs;
|
||||
private LocalDateTime dateModification;
|
||||
private String modifiePar;
|
||||
|
||||
// Détails complets (chargés à la demande)
|
||||
private List<Permission> permissionsDetaillees;
|
||||
private List<Utilisateur> utilisateursAssignes;
|
||||
|
||||
public Role() {
|
||||
this.permissions = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Role(String code, String nom, String description, TypeRole type, StatutRole statut,
|
||||
String icone, String couleurFond, String couleurTexte, List<String> permissions,
|
||||
int nombreUtilisateurs, LocalDateTime dateModification, String modifiePar) {
|
||||
this.code = code;
|
||||
this.nom = nom;
|
||||
this.description = description;
|
||||
this.type = type;
|
||||
this.statut = statut;
|
||||
this.icone = icone;
|
||||
this.couleurFond = couleurFond;
|
||||
this.couleurTexte = couleurTexte;
|
||||
this.permissions = permissions != null ? permissions : new ArrayList<>();
|
||||
this.nombreUtilisateurs = nombreUtilisateurs;
|
||||
this.dateModification = dateModification;
|
||||
this.modifiePar = modifiePar;
|
||||
}
|
||||
|
||||
public void chargerDetailsComplets() {
|
||||
// Simuler le chargement des détails
|
||||
permissionsDetaillees = new ArrayList<>();
|
||||
for (String perm : permissions) {
|
||||
permissionsDetaillees.add(new Permission(perm, getLibellePermission(perm)));
|
||||
}
|
||||
|
||||
utilisateursAssignes = new ArrayList<>();
|
||||
for (int i = 0; i < Math.min(nombreUtilisateurs, 10); i++) {
|
||||
utilisateursAssignes.add(new Utilisateur("Utilisateur " + (i+1), "Test"));
|
||||
}
|
||||
}
|
||||
|
||||
private String getLibellePermission(String code) {
|
||||
Map<String, String> libelles = new HashMap<>();
|
||||
libelles.put("GESTION_COMPLETE", "Gestion Complète");
|
||||
libelles.put("ADMIN_SYSTEME", "Administration Système");
|
||||
libelles.put("GESTION_USERS", "Gestion des Utilisateurs");
|
||||
libelles.put("GESTION_ORGS", "Gestion des Organisations");
|
||||
libelles.put("GESTION_MEMBRES", "Gestion des Membres");
|
||||
libelles.put("GESTION_EVENTS", "Gestion des Événements");
|
||||
libelles.put("COMPTABILITE", "Comptabilité");
|
||||
libelles.put("COTISATIONS", "Cotisations");
|
||||
libelles.put("DOCUMENTS", "Documents");
|
||||
libelles.put("COMMUNICATIONS", "Communications");
|
||||
libelles.put("RAPPORTS", "Rapports");
|
||||
libelles.put("AUDIT", "Audit");
|
||||
libelles.put("CONSULTATION", "Consultation");
|
||||
return libelles.getOrDefault(code, code);
|
||||
}
|
||||
|
||||
// Propriétés calculées
|
||||
public String getTypeLibelle() {
|
||||
switch (type) {
|
||||
case SYSTEME: return "Système";
|
||||
case PERSONNALISE: return "Personnalisé";
|
||||
case TEMPORAIRE: return "Temporaire";
|
||||
default: return type.name();
|
||||
}
|
||||
}
|
||||
|
||||
public String getTypeSeverity() {
|
||||
switch (type) {
|
||||
case SYSTEME: return "danger";
|
||||
case PERSONNALISE: return "info";
|
||||
case TEMPORAIRE: return "warning";
|
||||
default: return "secondary";
|
||||
}
|
||||
}
|
||||
|
||||
public String getStatutLibelle() {
|
||||
switch (statut) {
|
||||
case ACTIF: return "Actif";
|
||||
case INACTIF: return "Inactif";
|
||||
case SUSPENDU: return "Suspendu";
|
||||
default: return statut.name();
|
||||
}
|
||||
}
|
||||
|
||||
public String getStatutSeverity() {
|
||||
switch (statut) {
|
||||
case ACTIF: return "success";
|
||||
case INACTIF: return "secondary";
|
||||
case SUSPENDU: return "warning";
|
||||
default: return "secondary";
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getPermissionsPrincipales() {
|
||||
return permissions.stream().limit(3).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public int getPermissionsCount() {
|
||||
return permissions.size();
|
||||
}
|
||||
|
||||
public String getDateModificationFormatee() {
|
||||
return dateModification.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
|
||||
}
|
||||
|
||||
public boolean isModifiable() {
|
||||
return type != TypeRole.SYSTEME;
|
||||
}
|
||||
|
||||
public boolean isSupprimable() {
|
||||
return type != TypeRole.SYSTEME && nombreUtilisateurs == 0;
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public String getCode() { return code; }
|
||||
public void setCode(String code) { this.code = code; }
|
||||
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public TypeRole getType() { return type; }
|
||||
public void setType(TypeRole type) { this.type = type; }
|
||||
|
||||
public StatutRole getStatut() { return statut; }
|
||||
public void setStatut(StatutRole statut) { this.statut = statut; }
|
||||
|
||||
public String getIcone() { return icone; }
|
||||
public void setIcone(String icone) { this.icone = icone; }
|
||||
|
||||
public String getCouleurFond() { return couleurFond; }
|
||||
public void setCouleurFond(String couleurFond) { this.couleurFond = couleurFond; }
|
||||
|
||||
public String getCouleurTexte() { return couleurTexte; }
|
||||
public void setCouleurTexte(String couleurTexte) { this.couleurTexte = couleurTexte; }
|
||||
|
||||
public List<String> getPermissions() { return permissions; }
|
||||
public void setPermissions(List<String> permissions) { this.permissions = permissions; }
|
||||
|
||||
public int getNombreUtilisateurs() { return nombreUtilisateurs; }
|
||||
public void setNombreUtilisateurs(int nombreUtilisateurs) { this.nombreUtilisateurs = nombreUtilisateurs; }
|
||||
|
||||
public LocalDateTime getDateModification() { return dateModification; }
|
||||
public void setDateModification(LocalDateTime dateModification) { this.dateModification = dateModification; }
|
||||
|
||||
public String getModifiePar() { return modifiePar; }
|
||||
public void setModifiePar(String modifiePar) { this.modifiePar = modifiePar; }
|
||||
|
||||
public List<Permission> getPermissionsDetaillees() { return permissionsDetaillees; }
|
||||
public List<Utilisateur> getUtilisateursAssignes() { return utilisateursAssignes; }
|
||||
}
|
||||
|
||||
public enum TypeRole {
|
||||
SYSTEME, PERSONNALISE, TEMPORAIRE
|
||||
}
|
||||
|
||||
public enum StatutRole {
|
||||
ACTIF, INACTIF, SUSPENDU
|
||||
}
|
||||
|
||||
public static class Permission implements Serializable {
|
||||
private String code;
|
||||
private String libelle;
|
||||
|
||||
public Permission(String code, String libelle) {
|
||||
this.code = code;
|
||||
this.libelle = libelle;
|
||||
}
|
||||
|
||||
public String getCode() { return code; }
|
||||
public String getLibelle() { return libelle; }
|
||||
}
|
||||
|
||||
public static class Utilisateur implements Serializable {
|
||||
private String nom;
|
||||
private String prenom;
|
||||
|
||||
public Utilisateur(String nom, String prenom) {
|
||||
this.nom = nom;
|
||||
this.prenom = prenom;
|
||||
}
|
||||
|
||||
public String getNom() { return nom; }
|
||||
public String getPrenom() { return prenom; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.security.JwtTokenManager;
|
||||
import dev.lions.unionflow.client.security.TokenRefreshService;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Named("securityStatusBean")
|
||||
@RequestScoped
|
||||
public class SecurityStatusBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Inject
|
||||
private JwtTokenManager tokenManager;
|
||||
|
||||
@Inject
|
||||
private TokenRefreshService tokenRefreshService;
|
||||
|
||||
@Inject
|
||||
private UserSession userSession;
|
||||
|
||||
public String getSecurityStatusIcon() {
|
||||
if (!userSession.isAuthenticated() || !tokenManager.hasValidTokens()) {
|
||||
return "pi-shield text-red-500";
|
||||
}
|
||||
|
||||
long timeLeft = tokenManager.getTimeUntilExpiration();
|
||||
if (timeLeft < 300) { // Moins de 5 minutes
|
||||
return "pi-exclamation-triangle text-orange-500";
|
||||
} else if (timeLeft < 900) { // Moins de 15 minutes
|
||||
return "pi-clock text-yellow-500";
|
||||
} else {
|
||||
return "pi-shield text-green-500";
|
||||
}
|
||||
}
|
||||
|
||||
public String getSecurityStatusMessage() {
|
||||
if (!userSession.isAuthenticated() || !tokenManager.hasValidTokens()) {
|
||||
return "Session expirée";
|
||||
}
|
||||
|
||||
long timeLeft = tokenManager.getTimeUntilExpiration();
|
||||
long minutes = timeLeft / 60;
|
||||
|
||||
if (timeLeft < 300) {
|
||||
return "Session expire dans " + minutes + " min";
|
||||
} else if (timeLeft < 900) {
|
||||
return "Session active (" + minutes + " min restantes)";
|
||||
} else {
|
||||
return "Session sécurisée";
|
||||
}
|
||||
}
|
||||
|
||||
public String getSecurityStatusSeverity() {
|
||||
if (!userSession.isAuthenticated() || !tokenManager.hasValidTokens()) {
|
||||
return "danger";
|
||||
}
|
||||
|
||||
long timeLeft = tokenManager.getTimeUntilExpiration();
|
||||
if (timeLeft < 300) {
|
||||
return "warning";
|
||||
} else if (timeLeft < 900) {
|
||||
return "info";
|
||||
} else {
|
||||
return "success";
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshTokenManually() {
|
||||
try {
|
||||
String sessionId = getSessionId();
|
||||
if (sessionId != null && tokenRefreshService.tryRefreshTokenNow(sessionId)) {
|
||||
// Token rafraîchi avec succès
|
||||
} else {
|
||||
// Échec du rafraîchissement
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Gestion d'erreur
|
||||
}
|
||||
}
|
||||
|
||||
private String getSessionId() {
|
||||
try {
|
||||
jakarta.faces.context.FacesContext facesContext =
|
||||
jakarta.faces.context.FacesContext.getCurrentInstance();
|
||||
if (facesContext != null && facesContext.getExternalContext() != null) {
|
||||
return facesContext.getExternalContext().getSessionId(false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Contexte non disponible
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isTokenExpiringSoon() {
|
||||
return tokenManager.getTimeUntilExpiration() < 900; // 15 minutes
|
||||
}
|
||||
|
||||
public boolean isTokenCritical() {
|
||||
return tokenManager.getTimeUntilExpiration() < 300; // 5 minutes
|
||||
}
|
||||
|
||||
public int getTokenExpirationMinutes() {
|
||||
return (int) (tokenManager.getTimeUntilExpiration() / 60);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.dto.SouscriptionDTO;
|
||||
import dev.lions.unionflow.client.service.SouscriptionService;
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
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.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("souscriptionBean")
|
||||
@SessionScoped
|
||||
public class SouscriptionBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(SouscriptionBean.class.getName());
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_SOUSCRIPTION_UPGRADE = "souscriptionUpgradePage";
|
||||
private static final String OUTCOME_SOUSCRIPTION_CHANGE_PLAN = "souscriptionChangePlanPage";
|
||||
private static final String OUTCOME_SOUSCRIPTION_RENEW = "souscriptionRenewPage";
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private SouscriptionService souscriptionService;
|
||||
|
||||
private UUID organisationId; // À injecter depuis la session
|
||||
|
||||
private List<SouscriptionDTO> souscriptionsOrganisation;
|
||||
private SouscriptionDTO souscriptionActive;
|
||||
private SouscriptionDTO souscriptionSelectionnee;
|
||||
|
||||
// Statistiques quota
|
||||
private int membresActuels = 0;
|
||||
private int quotaMaximum = 0;
|
||||
private boolean quotaAtteint = false;
|
||||
private int membresRestants = 0;
|
||||
|
||||
// Alertes
|
||||
private boolean alerteExpirationProche = false;
|
||||
private boolean alerteQuotaProche = false;
|
||||
private int joursAvantExpiration = 0;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
if (organisationId != null) {
|
||||
initializeData();
|
||||
} else {
|
||||
LOGGER.warning("Aucun organisationId fourni, impossible de charger les souscriptions");
|
||||
souscriptionsOrganisation = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeData() {
|
||||
try {
|
||||
souscriptionsOrganisation = souscriptionService.listerToutes(organisationId, 0, 100);
|
||||
souscriptionActive = souscriptionService.obtenirActive(organisationId);
|
||||
if (souscriptionActive == null && !souscriptionsOrganisation.isEmpty()) {
|
||||
souscriptionActive = souscriptionsOrganisation.stream()
|
||||
.filter(s -> s.getStatut() == SouscriptionDTO.StatutSouscription.ACTIVE)
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
}
|
||||
updateStatistiques();
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des souscriptions: " + e.getMessage());
|
||||
souscriptionsOrganisation = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStatistiques() {
|
||||
if (souscriptionActive != null) {
|
||||
membresActuels = souscriptionActive.getMembresActuels();
|
||||
quotaMaximum = souscriptionActive.getQuotaMaxMembres();
|
||||
membresRestants = souscriptionActive.getMembresRestants();
|
||||
quotaAtteint = souscriptionActive.isQuotaAtteint();
|
||||
|
||||
// Calculer les alertes
|
||||
joursAvantExpiration = (int) souscriptionActive.getJoursRestants();
|
||||
alerteExpirationProche = souscriptionActive.isExpirationProche();
|
||||
alerteQuotaProche = souscriptionActive.getPourcentageUtilisation() >= 85;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean peutAccepterNouveauMembre() {
|
||||
return souscriptionActive != null &&
|
||||
souscriptionActive.isActive() &&
|
||||
!souscriptionActive.isQuotaAtteint();
|
||||
}
|
||||
|
||||
public String getMessageQuota() {
|
||||
if (souscriptionActive == null) {
|
||||
return "Aucune souscription active";
|
||||
}
|
||||
|
||||
if (quotaAtteint) {
|
||||
return "Quota maximum atteint (" + quotaMaximum + " membres)";
|
||||
}
|
||||
|
||||
if (alerteQuotaProche) {
|
||||
return "Attention: quota bientôt atteint (" + membresActuels + "/" + quotaMaximum + ")";
|
||||
}
|
||||
|
||||
return membresRestants + " membre(s) restant(s) sur " + quotaMaximum;
|
||||
}
|
||||
|
||||
public String getCouleurJaugeQuota() {
|
||||
int pourcentage = souscriptionActive != null ? souscriptionActive.getPourcentageUtilisation() : 0;
|
||||
|
||||
if (pourcentage >= 100) return "danger";
|
||||
if (pourcentage >= 85) return "warning";
|
||||
if (pourcentage >= 70) return "info";
|
||||
return "success";
|
||||
}
|
||||
|
||||
public String upgraderFormulaire() {
|
||||
// Logique pour upgrader vers un formulaire supérieur
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_SOUSCRIPTION_UPGRADE + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String changerFormulaire() {
|
||||
// Logique pour changer de formulaire
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_SOUSCRIPTION_CHANGE_PLAN + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String renouvelerSouscription() {
|
||||
// Logique pour renouveler la souscription
|
||||
// Utilisation de navigation outcome au lieu de chemin direct (WOU/DRY)
|
||||
return OUTCOME_SOUSCRIPTION_RENEW + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public void activerNotificationQuota(boolean activer) {
|
||||
if (souscriptionActive != null) {
|
||||
souscriptionActive.setNotificationQuotaAtteint(activer);
|
||||
// Appel service pour sauvegarder
|
||||
}
|
||||
}
|
||||
|
||||
public void activerNotificationExpiration(boolean activer) {
|
||||
if (souscriptionActive != null) {
|
||||
souscriptionActive.setNotificationExpiration(activer);
|
||||
// Appel service pour sauvegarder
|
||||
}
|
||||
}
|
||||
|
||||
public List<AlerteQuota> getAlertesQuota() {
|
||||
List<AlerteQuota> alertes = new ArrayList<>();
|
||||
|
||||
if (alerteExpirationProche) {
|
||||
AlerteQuota alerte = new AlerteQuota();
|
||||
alerte.setType("EXPIRATION");
|
||||
alerte.setSeverite("warning");
|
||||
alerte.setIcone("pi-clock");
|
||||
alerte.setTitre("Souscription expire bientôt");
|
||||
alerte.setMessage("Votre souscription expire dans " + joursAvantExpiration + " jour(s)");
|
||||
alerte.setAction("Renouveler maintenant");
|
||||
alerte.setActionUrl("/pages/secure/souscription/renew");
|
||||
alertes.add(alerte);
|
||||
}
|
||||
|
||||
if (alerteQuotaProche && !quotaAtteint) {
|
||||
AlerteQuota alerte = new AlerteQuota();
|
||||
alerte.setType("QUOTA_PROCHE");
|
||||
alerte.setSeverite("info");
|
||||
alerte.setIcone("pi-users");
|
||||
alerte.setTitre("Quota bientôt atteint");
|
||||
alerte.setMessage("Vous approchez de votre limite (" + membresActuels + "/" + quotaMaximum + ")");
|
||||
alerte.setAction("Upgrader le plan");
|
||||
alerte.setActionUrl("/pages/secure/souscription/upgrade");
|
||||
alertes.add(alerte);
|
||||
}
|
||||
|
||||
if (quotaAtteint) {
|
||||
AlerteQuota alerte = new AlerteQuota();
|
||||
alerte.setType("QUOTA_ATTEINT");
|
||||
alerte.setSeverite("danger");
|
||||
alerte.setIcone("pi-exclamation-triangle");
|
||||
alerte.setTitre("Quota maximum atteint");
|
||||
alerte.setMessage("Vous ne pouvez plus accepter de nouveaux membres");
|
||||
alerte.setAction("Upgrader maintenant");
|
||||
alerte.setActionUrl("/pages/secure/souscription/upgrade");
|
||||
alertes.add(alerte);
|
||||
}
|
||||
|
||||
return alertes;
|
||||
}
|
||||
|
||||
public String getSeveriteQuota() {
|
||||
if (quotaAtteint) return "danger";
|
||||
if (alerteQuotaProche) return "warning";
|
||||
return "info";
|
||||
}
|
||||
|
||||
public String getIconeStatut() {
|
||||
if (souscriptionActive == null) return "pi-times-circle text-red-500";
|
||||
if (souscriptionActive.isActive()) return "pi-check-circle text-green-500";
|
||||
if (souscriptionActive.getStatut() == SouscriptionDTO.StatutSouscription.EXPIREE) return "pi-clock text-red-500";
|
||||
if (souscriptionActive.getStatut() == SouscriptionDTO.StatutSouscription.SUSPENDUE) return "pi-pause text-orange-500";
|
||||
return "pi-info-circle text-blue-500";
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public List<SouscriptionDTO> getSouscriptionsOrganisation() { return souscriptionsOrganisation; }
|
||||
public void setSouscriptionsOrganisation(List<SouscriptionDTO> souscriptionsOrganisation) { this.souscriptionsOrganisation = souscriptionsOrganisation; }
|
||||
|
||||
public SouscriptionDTO getSouscriptionActive() { return souscriptionActive; }
|
||||
public void setSouscriptionActive(SouscriptionDTO souscriptionActive) { this.souscriptionActive = souscriptionActive; }
|
||||
|
||||
public SouscriptionDTO getSouscriptionSelectionnee() { return souscriptionSelectionnee; }
|
||||
public void setSouscriptionSelectionnee(SouscriptionDTO souscriptionSelectionnee) { this.souscriptionSelectionnee = souscriptionSelectionnee; }
|
||||
|
||||
public int getMembresActuels() { return membresActuels; }
|
||||
public void setMembresActuels(int membresActuels) { this.membresActuels = membresActuels; }
|
||||
|
||||
public int getQuotaMaximum() { return quotaMaximum; }
|
||||
public void setQuotaMaximum(int quotaMaximum) { this.quotaMaximum = quotaMaximum; }
|
||||
|
||||
public boolean isQuotaAtteint() { return quotaAtteint; }
|
||||
public void setQuotaAtteint(boolean quotaAtteint) { this.quotaAtteint = quotaAtteint; }
|
||||
|
||||
public int getMembresRestants() { return membresRestants; }
|
||||
public void setMembresRestants(int membresRestants) { this.membresRestants = membresRestants; }
|
||||
|
||||
public boolean isAlerteExpirationProche() { return alerteExpirationProche; }
|
||||
public void setAlerteExpirationProche(boolean alerteExpirationProche) { this.alerteExpirationProche = alerteExpirationProche; }
|
||||
|
||||
public boolean isAlerteQuotaProche() { return alerteQuotaProche; }
|
||||
public void setAlerteQuotaProche(boolean alerteQuotaProche) { this.alerteQuotaProche = alerteQuotaProche; }
|
||||
|
||||
public int getJoursAvantExpiration() { return joursAvantExpiration; }
|
||||
public void setJoursAvantExpiration(int joursAvantExpiration) { this.joursAvantExpiration = joursAvantExpiration; }
|
||||
|
||||
// Classe interne pour les alertes
|
||||
public static class AlerteQuota implements Serializable {
|
||||
private String type;
|
||||
private String severite;
|
||||
private String icone;
|
||||
private String titre;
|
||||
private String message;
|
||||
private String action;
|
||||
private String actionUrl;
|
||||
|
||||
// Getters et Setters
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
|
||||
public String getSeverite() { return severite; }
|
||||
public void setSeverite(String severite) { this.severite = severite; }
|
||||
|
||||
public String getIcone() { return icone; }
|
||||
public void setIcone(String icone) { this.icone = icone; }
|
||||
|
||||
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 String getAction() { return action; }
|
||||
public void setAction(String action) { this.action = action; }
|
||||
|
||||
public String getActionUrl() { return actionUrl; }
|
||||
public void setActionUrl(String actionUrl) { this.actionUrl = actionUrl; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,613 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.dto.AssociationDTO;
|
||||
import dev.lions.unionflow.client.service.AssociationService;
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
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.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("superAdminBean")
|
||||
@SessionScoped
|
||||
public class SuperAdminBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(SuperAdminBean.class.getName());
|
||||
|
||||
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
|
||||
private static final String OUTCOME_ENTITE_NOUVELLE = "entiteNouvellePage";
|
||||
private static final String OUTCOME_ENTITE_GESTION = "entiteGestionPage";
|
||||
private static final String OUTCOME_SUPER_ADMIN_RAPPORTS = "superAdminRapportsPage";
|
||||
private static final String OUTCOME_SUPER_ADMIN_CONFIGURATION = "superAdminConfigurationPage";
|
||||
private static final String OUTCOME_SUPER_ADMIN_ALERTES = "superAdminAlertesPage";
|
||||
private static final String OUTCOME_SUPER_ADMIN_ACTIVITE = "superAdminActivitePage";
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private AssociationService associationService;
|
||||
|
||||
private String nomComplet;
|
||||
private String derniereConnexion;
|
||||
private int totalEntites;
|
||||
private int totalAdministrateurs;
|
||||
private int totalMembres;
|
||||
private String revenusGlobaux;
|
||||
private int alertesCount;
|
||||
private String croissanceEntites;
|
||||
private int activiteJournaliere;
|
||||
|
||||
// Pourcentages de croissance calculés
|
||||
private String croissanceMembres = "0";
|
||||
private String croissanceRevenus = "0";
|
||||
private int nouvellesEntites = 0;
|
||||
private int utilisateursActifs = 0;
|
||||
|
||||
// Pourcentages pour les progress bars (jauges)
|
||||
private int pourcentageMembres = 0;
|
||||
private int pourcentageOrganisations = 0;
|
||||
private int pourcentageRevenus = 0;
|
||||
private int pourcentageActivite = 0;
|
||||
|
||||
// Métriques de souscription
|
||||
private int totalSouscriptions;
|
||||
private int souscriptionsActives;
|
||||
private int souscriptionsExpirantSous30Jours;
|
||||
private float tauxConversion;
|
||||
|
||||
// Revenus par forfait
|
||||
private BigDecimal revenusStarter = BigDecimal.ZERO;
|
||||
private BigDecimal revenusStandard = BigDecimal.ZERO;
|
||||
private BigDecimal revenusPremmium = BigDecimal.ZERO;
|
||||
private BigDecimal revenusCristal = BigDecimal.ZERO;
|
||||
|
||||
// Métriques système
|
||||
private float disponibiliteSysteme;
|
||||
private int tempsReponsMoyen;
|
||||
private int ticketsSupportOuverts;
|
||||
private float satisfactionClient;
|
||||
|
||||
private List<Alerte> alertesRecentes;
|
||||
private List<Entite> topEntites;
|
||||
private List<TypeEntite> repartitionTypes;
|
||||
private List<Activite> activitesRecentes;
|
||||
private List<EvolutionMois> evolutionEntites;
|
||||
private RevenusData revenus;
|
||||
private String periodeEvolution = "12M";
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initializeUserInfo();
|
||||
initializeKPIs();
|
||||
initializeAlertes();
|
||||
initializeEntites();
|
||||
initializeRepartitionTypes();
|
||||
initializeActivites();
|
||||
initializeEvolution();
|
||||
initializeRevenus();
|
||||
}
|
||||
|
||||
private void initializeUserInfo() {
|
||||
// TODO: Récupérer depuis le contexte de sécurité (Keycloak)
|
||||
nomComplet = "Administrateur Système";
|
||||
derniereConnexion = LocalDateTime.now().format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"));
|
||||
}
|
||||
|
||||
private void initializeKPIs() {
|
||||
try {
|
||||
List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
|
||||
totalEntites = associations.size();
|
||||
totalAdministrateurs = associations.size(); // TODO: Calculer depuis les utilisateurs
|
||||
int totalMembresCalc = associations.stream()
|
||||
.mapToInt(a -> a.getNombreMembres() != null ? a.getNombreMembres() : 0)
|
||||
.sum();
|
||||
totalMembres = totalMembresCalc;
|
||||
revenusGlobaux = "0 FCFA"; // TODO: Calculer depuis les souscriptions/paiements réels
|
||||
alertesCount = 0; // TODO: Calculer depuis les alertes réelles
|
||||
|
||||
// Calculer la croissance des entités (comparaison avec le mois précédent)
|
||||
// Pour l'instant, on ne peut pas calculer sans historique, donc 0
|
||||
croissanceEntites = "0";
|
||||
nouvellesEntites = 0; // TODO: Calculer depuis l'historique
|
||||
|
||||
// Calculer la croissance des membres (comparaison avec le mois précédent)
|
||||
// Pour l'instant, on ne peut pas calculer sans historique, donc 0
|
||||
croissanceMembres = "0"; // TODO: Calculer depuis l'historique des membres
|
||||
|
||||
croissanceRevenus = "0"; // TODO: Calculer depuis l'historique des revenus
|
||||
activiteJournaliere = 0; // TODO: Calculer depuis les logs d'activité
|
||||
utilisateursActifs = 0; // TODO: Calculer depuis les sessions actives
|
||||
|
||||
// Calculer les pourcentages pour les progress bars (jauges)
|
||||
calculerPourcentagesJauges();
|
||||
|
||||
// Initialiser les métriques de souscription
|
||||
totalSouscriptions = 0; // TODO: Calculer depuis les souscriptions réelles
|
||||
souscriptionsActives = 0; // TODO: Calculer depuis les souscriptions actives
|
||||
souscriptionsExpirantSous30Jours = 0; // TODO: Calculer depuis les souscriptions expirantes
|
||||
tauxConversion = 0.0f; // TODO: Calculer depuis les statistiques de conversion
|
||||
|
||||
// Revenus par forfait - TODO: Calculer depuis les souscriptions/paiements réels
|
||||
revenusStarter = BigDecimal.ZERO;
|
||||
revenusStandard = BigDecimal.ZERO;
|
||||
revenusPremmium = BigDecimal.ZERO;
|
||||
revenusCristal = BigDecimal.ZERO;
|
||||
|
||||
// Métriques système - TODO: Récupérer depuis un service de monitoring
|
||||
disponibiliteSysteme = 0.0f;
|
||||
tempsReponsMoyen = 0; // ms
|
||||
ticketsSupportOuverts = 0; // TODO: Calculer depuis les tickets support réels
|
||||
satisfactionClient = 0.0f; // /5 - TODO: Calculer depuis les évaluations réelles
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du calcul des KPIs: " + e.getMessage());
|
||||
totalEntites = 0;
|
||||
totalAdministrateurs = 0;
|
||||
totalMembres = 0;
|
||||
revenusGlobaux = "0 FCFA";
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeAlertes() {
|
||||
// Initialiser avec une liste vide - les alertes seront chargées depuis le backend quand le service sera disponible
|
||||
alertesRecentes = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void initializeEntites() {
|
||||
topEntites = new ArrayList<>();
|
||||
try {
|
||||
List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
|
||||
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 -> {
|
||||
Entite entite = new Entite();
|
||||
entite.setId(a.getId());
|
||||
entite.setNom(a.getNom());
|
||||
entite.setTypeEntite(a.getTypeAssociation());
|
||||
entite.setNombreMembres(a.getNombreMembres() != null ? a.getNombreMembres() : 0);
|
||||
return entite;
|
||||
})
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des top entités: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeRepartitionTypes() {
|
||||
// Initialiser avec une liste vide - la répartition sera calculée depuis les données réelles quand disponible
|
||||
repartitionTypes = new ArrayList<>();
|
||||
try {
|
||||
// TODO: Calculer la répartition depuis les données réelles des organisations
|
||||
// List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
|
||||
// Grouper par type et calculer les pourcentages
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Impossible de calculer la répartition des types: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeActivites() {
|
||||
// Initialiser avec une liste vide - les activités seront chargées depuis le backend quand le service sera disponible
|
||||
activitesRecentes = new ArrayList<>();
|
||||
// TODO: Charger depuis un service d'audit/logs quand disponible
|
||||
}
|
||||
|
||||
private void initializeEvolution() {
|
||||
// Initialiser avec une liste vide - l'évolution sera calculée depuis les données réelles quand disponible
|
||||
evolutionEntites = new ArrayList<>();
|
||||
// TODO: Calculer l'évolution mensuelle depuis les données historiques des organisations
|
||||
}
|
||||
|
||||
private void initializeRevenus() {
|
||||
// Initialiser avec des valeurs par défaut - les revenus seront calculés depuis les paiements réels quand disponible
|
||||
revenus = new RevenusData();
|
||||
revenus.setMensuel("0 FCFA");
|
||||
revenus.setAnnuel("0 FCFA");
|
||||
revenus.setCroissance("0");
|
||||
revenus.setMoyenne("0 FCFA");
|
||||
revenus.setCroissanceMensuelle("0");
|
||||
revenus.setObjectifAnnuel("0 FCFA");
|
||||
revenus.setDerniereMAJ(LocalDate.now().format(DateTimeFormatter.ofPattern("dd/MM/yyyy")));
|
||||
revenus.setEvolution(new ArrayList<>());
|
||||
// TODO: Calculer depuis les paiements/souscriptions réels quand le service sera disponible
|
||||
}
|
||||
|
||||
// Actions (WOU/DRY - utilisation de navigation outcomes)
|
||||
public String creerEntite() {
|
||||
return OUTCOME_ENTITE_NOUVELLE + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String gererEntites() {
|
||||
return OUTCOME_ENTITE_GESTION + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String genererRapport() {
|
||||
return OUTCOME_SUPER_ADMIN_RAPPORTS + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String configurer() {
|
||||
return OUTCOME_SUPER_ADMIN_CONFIGURATION + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public void voirAlerte(Alerte alerte) {
|
||||
LOGGER.info("Voir alerte: " + alerte.getTitre());
|
||||
}
|
||||
|
||||
public String voirToutesAlertes() {
|
||||
return OUTCOME_SUPER_ADMIN_ALERTES + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public String voirTouteActivite() {
|
||||
return OUTCOME_SUPER_ADMIN_ACTIVITE + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
public void exporterRapportFinancier() {
|
||||
LOGGER.info("Export du rapport financier généré");
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public String getNomComplet() { return nomComplet; }
|
||||
public void setNomComplet(String nomComplet) { this.nomComplet = nomComplet; }
|
||||
|
||||
public String getDerniereConnexion() { return derniereConnexion; }
|
||||
public void setDerniereConnexion(String derniereConnexion) { this.derniereConnexion = derniereConnexion; }
|
||||
|
||||
public int getTotalEntites() { return totalEntites; }
|
||||
public void setTotalEntites(int totalEntites) { this.totalEntites = totalEntites; }
|
||||
|
||||
public int getTotalAdministrateurs() { return totalAdministrateurs; }
|
||||
public void setTotalAdministrateurs(int totalAdministrateurs) { this.totalAdministrateurs = totalAdministrateurs; }
|
||||
|
||||
public int getTotalMembres() { return totalMembres; }
|
||||
public void setTotalMembres(int totalMembres) { this.totalMembres = totalMembres; }
|
||||
|
||||
public String getRevenusGlobaux() { return revenusGlobaux; }
|
||||
public void setRevenusGlobaux(String revenusGlobaux) { this.revenusGlobaux = revenusGlobaux; }
|
||||
|
||||
public int getAlertesCount() { return alertesCount; }
|
||||
public void setAlertesCount(int alertesCount) { this.alertesCount = alertesCount; }
|
||||
|
||||
public String getCroissanceEntites() { return croissanceEntites; }
|
||||
public void setCroissanceEntites(String croissanceEntites) { this.croissanceEntites = croissanceEntites; }
|
||||
|
||||
public int getActiviteJournaliere() { return activiteJournaliere; }
|
||||
public void setActiviteJournaliere(int activiteJournaliere) { this.activiteJournaliere = activiteJournaliere; }
|
||||
|
||||
// Getters pour les nouvelles métriques
|
||||
public int getTotalSouscriptions() { return totalSouscriptions; }
|
||||
public void setTotalSouscriptions(int totalSouscriptions) { this.totalSouscriptions = totalSouscriptions; }
|
||||
|
||||
public int getSouscriptionsActives() { return souscriptionsActives; }
|
||||
public void setSouscriptionsActives(int souscriptionsActives) { this.souscriptionsActives = souscriptionsActives; }
|
||||
|
||||
public int getSouscriptionsExpirantSous30Jours() { return souscriptionsExpirantSous30Jours; }
|
||||
public void setSouscriptionsExpirantSous30Jours(int souscriptionsExpirantSous30Jours) { this.souscriptionsExpirantSous30Jours = souscriptionsExpirantSous30Jours; }
|
||||
|
||||
public float getTauxConversion() { return tauxConversion; }
|
||||
public void setTauxConversion(float tauxConversion) { this.tauxConversion = tauxConversion; }
|
||||
|
||||
public BigDecimal getRevenusStarter() { return revenusStarter; }
|
||||
public void setRevenusStarter(BigDecimal revenusStarter) { this.revenusStarter = revenusStarter; }
|
||||
|
||||
public BigDecimal getRevenusStandard() { return revenusStandard; }
|
||||
public void setRevenusStandard(BigDecimal revenusStandard) { this.revenusStandard = revenusStandard; }
|
||||
|
||||
public BigDecimal getRevenusPremmium() { return revenusPremmium; }
|
||||
public void setRevenusPremmium(BigDecimal revenusPremmium) { this.revenusPremmium = revenusPremmium; }
|
||||
|
||||
public BigDecimal getRevenusCristal() { return revenusCristal; }
|
||||
public void setRevenusCristal(BigDecimal revenusCristal) { this.revenusCristal = revenusCristal; }
|
||||
|
||||
public float getDisponibiliteSysteme() { return disponibiliteSysteme; }
|
||||
public void setDisponibiliteSysteme(float disponibiliteSysteme) { this.disponibiliteSysteme = disponibiliteSysteme; }
|
||||
|
||||
public int getTempsReponsMoyen() { return tempsReponsMoyen; }
|
||||
public void setTempsReponsMoyen(int tempsReponsMoyen) { this.tempsReponsMoyen = tempsReponsMoyen; }
|
||||
|
||||
public int getTicketsSupportOuverts() { return ticketsSupportOuverts; }
|
||||
public void setTicketsSupportOuverts(int ticketsSupportOuverts) { this.ticketsSupportOuverts = ticketsSupportOuverts; }
|
||||
|
||||
public float getSatisfactionClient() { return satisfactionClient; }
|
||||
public void setSatisfactionClient(float satisfactionClient) { this.satisfactionClient = satisfactionClient; }
|
||||
|
||||
// Méthodes utilitaires
|
||||
public String getRevenusStarterFormat() {
|
||||
return String.format("%,.0f FCFA", revenusStarter);
|
||||
}
|
||||
|
||||
public String getRevenusStandardFormat() {
|
||||
return String.format("%,.0f FCFA", revenusStandard);
|
||||
}
|
||||
|
||||
public String getRevenusPremmiumFormat() {
|
||||
return String.format("%,.0f FCFA", revenusPremmium);
|
||||
}
|
||||
|
||||
public String getRevenusCristalFormat() {
|
||||
return String.format("%,.0f FCFA", revenusCristal);
|
||||
}
|
||||
|
||||
public String getTauxConversionFormat() {
|
||||
return String.format("%.1f%%", tauxConversion);
|
||||
}
|
||||
|
||||
public String getDisponibiliteSystemeFormat() {
|
||||
return String.format("%.1f%%", disponibiliteSysteme);
|
||||
}
|
||||
|
||||
public String getSatisfactionClientFormat() {
|
||||
return String.format("%.1f/5", satisfactionClient);
|
||||
}
|
||||
|
||||
public List<Alerte> getAlertesRecentes() { return alertesRecentes; }
|
||||
public void setAlertesRecentes(List<Alerte> alertesRecentes) { this.alertesRecentes = alertesRecentes; }
|
||||
|
||||
public List<Entite> getTopEntites() { return topEntites; }
|
||||
public void setTopEntites(List<Entite> topEntites) { this.topEntites = topEntites; }
|
||||
|
||||
public List<TypeEntite> getRepartitionTypes() { return repartitionTypes; }
|
||||
public void setRepartitionTypes(List<TypeEntite> repartitionTypes) { this.repartitionTypes = repartitionTypes; }
|
||||
|
||||
public List<Activite> getActivitesRecentes() { return activitesRecentes; }
|
||||
public void setActivitesRecentes(List<Activite> activitesRecentes) { this.activitesRecentes = activitesRecentes; }
|
||||
|
||||
public List<EvolutionMois> getEvolutionEntites() { return evolutionEntites; }
|
||||
public void setEvolutionEntites(List<EvolutionMois> evolutionEntites) { this.evolutionEntites = evolutionEntites; }
|
||||
|
||||
public RevenusData getRevenus() { return revenus; }
|
||||
public void setRevenus(RevenusData revenus) { this.revenus = revenus; }
|
||||
|
||||
public String getPeriodeEvolution() { return periodeEvolution; }
|
||||
public void setPeriodeEvolution(String periodeEvolution) { this.periodeEvolution = periodeEvolution; }
|
||||
|
||||
// Getters pour les nouvelles propriétés
|
||||
public String getCroissanceMembres() { return croissanceMembres; }
|
||||
public void setCroissanceMembres(String croissanceMembres) { this.croissanceMembres = croissanceMembres; }
|
||||
|
||||
public String getCroissanceRevenus() { return croissanceRevenus; }
|
||||
public void setCroissanceRevenus(String croissanceRevenus) { this.croissanceRevenus = croissanceRevenus; }
|
||||
|
||||
public int getNouvellesEntites() { return nouvellesEntites; }
|
||||
public void setNouvellesEntites(int nouvellesEntites) { this.nouvellesEntites = nouvellesEntites; }
|
||||
|
||||
public int getUtilisateursActifs() { return utilisateursActifs; }
|
||||
public void setUtilisateursActifs(int utilisateursActifs) { this.utilisateursActifs = utilisateursActifs; }
|
||||
|
||||
/**
|
||||
* Calcule les pourcentages pour les progress bars (jauges) basés sur des objectifs réalistes
|
||||
*/
|
||||
private void calculerPourcentagesJauges() {
|
||||
// Objectif : 1000 membres (100%)
|
||||
int objectifMembres = 1000;
|
||||
pourcentageMembres = totalMembres > 0 ? Math.min(100, (totalMembres * 100) / objectifMembres) : 0;
|
||||
|
||||
// Objectif : 50 organisations (100%)
|
||||
int objectifOrganisations = 50;
|
||||
pourcentageOrganisations = totalEntites > 0 ? Math.min(100, (totalEntites * 100) / objectifOrganisations) : 0;
|
||||
|
||||
// Objectif : 10 000 000 FCFA de revenus (100%)
|
||||
// Pour l'instant, si revenus = 0, on met 0%
|
||||
try {
|
||||
String revenusStr = revenusGlobaux.replaceAll("[^0-9]", "");
|
||||
if (!revenusStr.isEmpty()) {
|
||||
long revenusLong = Long.parseLong(revenusStr);
|
||||
long objectifRevenus = 10_000_000L; // 10 millions FCFA
|
||||
pourcentageRevenus = revenusLong > 0 ? Math.min(100, (int) ((revenusLong * 100) / objectifRevenus)) : 0;
|
||||
} else {
|
||||
pourcentageRevenus = 0;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
pourcentageRevenus = 0;
|
||||
}
|
||||
|
||||
// Objectif : 100 activités journalières (100%)
|
||||
int objectifActivite = 100;
|
||||
pourcentageActivite = activiteJournaliere > 0 ? Math.min(100, (activiteJournaliere * 100) / objectifActivite) : 0;
|
||||
}
|
||||
|
||||
// Getters pour les pourcentages des jauges
|
||||
public int getPourcentageMembres() { return pourcentageMembres; }
|
||||
public void setPourcentageMembres(int pourcentageMembres) { this.pourcentageMembres = pourcentageMembres; }
|
||||
|
||||
public int getPourcentageOrganisations() { return pourcentageOrganisations; }
|
||||
public void setPourcentageOrganisations(int pourcentageOrganisations) { this.pourcentageOrganisations = pourcentageOrganisations; }
|
||||
|
||||
public int getPourcentageRevenus() { return pourcentageRevenus; }
|
||||
public void setPourcentageRevenus(int pourcentageRevenus) { this.pourcentageRevenus = pourcentageRevenus; }
|
||||
|
||||
public int getPourcentageActivite() { return pourcentageActivite; }
|
||||
public void setPourcentageActivite(int pourcentageActivite) { this.pourcentageActivite = pourcentageActivite; }
|
||||
|
||||
// Classes internes
|
||||
public static class Alerte {
|
||||
private UUID id;
|
||||
private String titre;
|
||||
private String entite;
|
||||
private String date;
|
||||
private String icone;
|
||||
private String couleur;
|
||||
|
||||
// Getters et setters
|
||||
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 getEntite() { return entite; }
|
||||
public void setEntite(String entite) { this.entite = entite; }
|
||||
|
||||
public String getDate() { return date; }
|
||||
public void setDate(String date) { this.date = date; }
|
||||
|
||||
public String getIcone() { return icone; }
|
||||
public void setIcone(String icone) { this.icone = icone; }
|
||||
|
||||
public String getCouleur() { return couleur; }
|
||||
public void setCouleur(String couleur) { this.couleur = couleur; }
|
||||
}
|
||||
|
||||
public static class Entite {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
private String typeEntite;
|
||||
private int nombreMembres;
|
||||
|
||||
// Getters et setters
|
||||
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 getTypeEntite() { return typeEntite; }
|
||||
public void setTypeEntite(String typeEntite) { this.typeEntite = typeEntite; }
|
||||
|
||||
public int getNombreMembres() { return nombreMembres; }
|
||||
public void setNombreMembres(int nombreMembres) { this.nombreMembres = nombreMembres; }
|
||||
}
|
||||
|
||||
public static class TypeEntite {
|
||||
private String nom;
|
||||
private String description;
|
||||
private int nombre;
|
||||
private int pourcentage;
|
||||
private String icone;
|
||||
private String couleurBg;
|
||||
private String couleurTexte;
|
||||
|
||||
// Getters et setters
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public int getNombre() { return nombre; }
|
||||
public void setNombre(int nombre) { this.nombre = nombre; }
|
||||
|
||||
public int getPourcentage() { return pourcentage; }
|
||||
public void setPourcentage(int pourcentage) { this.pourcentage = pourcentage; }
|
||||
|
||||
public String getIcone() { return icone; }
|
||||
public void setIcone(String icone) { this.icone = icone; }
|
||||
|
||||
public String getCouleurBg() { return couleurBg; }
|
||||
public void setCouleurBg(String couleurBg) { this.couleurBg = couleurBg; }
|
||||
|
||||
public String getCouleurTexte() { return couleurTexte; }
|
||||
public void setCouleurTexte(String couleurTexte) { this.couleurTexte = couleurTexte; }
|
||||
}
|
||||
|
||||
public static class Activite {
|
||||
private UUID id;
|
||||
private String description;
|
||||
private String entite;
|
||||
private String date;
|
||||
private String icone;
|
||||
private String utilisateur;
|
||||
private String details;
|
||||
|
||||
// Getters et setters
|
||||
public UUID getId() { return id; }
|
||||
public void setId(UUID id) { this.id = id; }
|
||||
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
|
||||
public String getEntite() { return entite; }
|
||||
public void setEntite(String entite) { this.entite = entite; }
|
||||
|
||||
public String getDate() { return date; }
|
||||
public void setDate(String date) { this.date = date; }
|
||||
|
||||
public String getIcone() { return icone; }
|
||||
public void setIcone(String icone) { this.icone = icone; }
|
||||
|
||||
public String getUtilisateur() { return utilisateur; }
|
||||
public void setUtilisateur(String utilisateur) { this.utilisateur = utilisateur; }
|
||||
|
||||
public String getDetails() { return details; }
|
||||
public void setDetails(String details) { this.details = details; }
|
||||
}
|
||||
|
||||
public static class EvolutionMois {
|
||||
private String periode;
|
||||
private int valeur;
|
||||
private int hauteur;
|
||||
|
||||
// Getters et setters
|
||||
public String getPeriode() { return periode; }
|
||||
public void setPeriode(String periode) { this.periode = periode; }
|
||||
|
||||
public int getValeur() { return valeur; }
|
||||
public void setValeur(int valeur) { this.valeur = valeur; }
|
||||
|
||||
public int getHauteur() { return hauteur; }
|
||||
public void setHauteur(int hauteur) { this.hauteur = hauteur; }
|
||||
}
|
||||
|
||||
public static class RevenusData {
|
||||
private String mensuel;
|
||||
private String annuel;
|
||||
private String croissance;
|
||||
private String moyenne;
|
||||
private String croissanceMensuelle;
|
||||
private String objectifAnnuel;
|
||||
private String derniereMAJ;
|
||||
private List<MoisRevenu> evolution = new ArrayList<>();
|
||||
|
||||
// Getters et setters
|
||||
public String getMensuel() { return mensuel; }
|
||||
public void setMensuel(String mensuel) { this.mensuel = mensuel; }
|
||||
|
||||
public String getAnnuel() { return annuel; }
|
||||
public void setAnnuel(String annuel) { this.annuel = annuel; }
|
||||
|
||||
public String getCroissance() { return croissance; }
|
||||
public void setCroissance(String croissance) { this.croissance = croissance; }
|
||||
|
||||
public String getMoyenne() { return moyenne; }
|
||||
public void setMoyenne(String moyenne) { this.moyenne = moyenne; }
|
||||
|
||||
public String getCroissanceMensuelle() { return croissanceMensuelle; }
|
||||
public void setCroissanceMensuelle(String croissanceMensuelle) { this.croissanceMensuelle = croissanceMensuelle; }
|
||||
|
||||
public String getObjectifAnnuel() { return objectifAnnuel; }
|
||||
public void setObjectifAnnuel(String objectifAnnuel) { this.objectifAnnuel = objectifAnnuel; }
|
||||
|
||||
public String getDerniereMAJ() { return derniereMAJ; }
|
||||
public void setDerniereMAJ(String derniereMAJ) { this.derniereMAJ = derniereMAJ; }
|
||||
|
||||
public List<MoisRevenu> getEvolution() { return evolution; }
|
||||
public void setEvolution(List<MoisRevenu> evolution) { this.evolution = evolution; }
|
||||
}
|
||||
|
||||
public static class MoisRevenu {
|
||||
private String nom;
|
||||
private int hauteur;
|
||||
private String valeur;
|
||||
|
||||
// Getters et setters
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public int getHauteur() { return hauteur; }
|
||||
public void setHauteur(int hauteur) { this.hauteur = hauteur; }
|
||||
|
||||
public String getValeur() { return valeur; }
|
||||
public void setValeur(String valeur) { this.valeur = valeur; }
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
|
||||
535
src/main/java/dev/lions/unionflow/client/view/UserSession.java
Normal file
535
src/main/java/dev/lions/unionflow/client/view/UserSession.java
Normal file
@@ -0,0 +1,535 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import org.eclipse.microprofile.jwt.JsonWebToken;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Gestion de la session utilisateur avec Keycloak OIDC
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
*/
|
||||
@Named("userSession")
|
||||
@SessionScoped
|
||||
public class UserSession implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(UserSession.class.getName());
|
||||
|
||||
@Inject
|
||||
private JsonWebToken jwt;
|
||||
|
||||
private String username;
|
||||
private boolean authenticated = false;
|
||||
private String typeCompte;
|
||||
private List<String> roles;
|
||||
private List<String> permissions;
|
||||
private CurrentUser currentUser;
|
||||
private EntiteInfo entite;
|
||||
|
||||
public UserSession() {
|
||||
// Session par défaut non authentifiée
|
||||
clearSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise la session depuis le token OIDC Keycloak
|
||||
* Appelé automatiquement après l'authentification
|
||||
*/
|
||||
public void initializeFromOidcToken() {
|
||||
if (jwt != null && jwt.getName() != null) {
|
||||
this.authenticated = true;
|
||||
this.username = jwt.getClaim("preferred_username");
|
||||
if (this.username == null) {
|
||||
this.username = jwt.getName();
|
||||
}
|
||||
|
||||
// Récupérer les informations du token
|
||||
String email = jwt.getClaim("email");
|
||||
String givenName = jwt.getClaim("given_name");
|
||||
String familyName = jwt.getClaim("family_name");
|
||||
|
||||
// Récupérer les rôles depuis le token
|
||||
this.roles = extractRolesFromToken();
|
||||
LOGGER.info("Rôles assignés à this.roles: " + this.roles);
|
||||
LOGGER.info("Vérification contains('SUPER_ADMIN'): " + (this.roles != null && this.roles.contains("SUPER_ADMIN")));
|
||||
this.typeCompte = determineTypeCompte();
|
||||
LOGGER.info("Type de compte déterminé: " + this.typeCompte);
|
||||
|
||||
// Mettre à jour les informations utilisateur
|
||||
this.currentUser = new CurrentUser();
|
||||
this.currentUser.setUsername(this.username);
|
||||
this.currentUser.setEmail(email);
|
||||
this.currentUser.setPrenom(givenName);
|
||||
this.currentUser.setNom(familyName);
|
||||
|
||||
// Générer un ID depuis le subject du token
|
||||
String subject = jwt.getSubject();
|
||||
if (subject != null) {
|
||||
try {
|
||||
this.currentUser.setId(UUID.fromString(subject));
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Si le subject n'est pas un UUID, générer un UUID déterministe
|
||||
this.currentUser.setId(UUID.nameUUIDFromBytes(subject.getBytes()));
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info("Session utilisateur initialisée depuis Keycloak pour: " + this.username +
|
||||
" (Type: " + typeCompte + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convertit un objet JSON en String de manière sécurisée
|
||||
* Gère les cas où l'objet est un JsonStringImpl, String, ou autre type
|
||||
*/
|
||||
private String convertToString(Object obj) {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
if (obj instanceof String) {
|
||||
String str = (String) obj;
|
||||
// Nettoyer les guillemets qui pourraient être présents
|
||||
str = str.trim();
|
||||
if (str.startsWith("'") && str.endsWith("'") && str.length() > 1) {
|
||||
str = str.substring(1, str.length() - 1);
|
||||
}
|
||||
if (str.startsWith("\"") && str.endsWith("\"") && str.length() > 1) {
|
||||
str = str.substring(1, str.length() - 1);
|
||||
}
|
||||
return str.trim();
|
||||
}
|
||||
// Gérer JsonStringImpl et autres types JSON
|
||||
String str = obj.toString();
|
||||
// Nettoyer les guillemets qui pourraient être présents
|
||||
str = str.trim();
|
||||
if (str.startsWith("'") && str.endsWith("'") && str.length() > 1) {
|
||||
str = str.substring(1, str.length() - 1);
|
||||
}
|
||||
if (str.startsWith("\"") && str.endsWith("\"") && str.length() > 1) {
|
||||
str = str.substring(1, str.length() - 1);
|
||||
}
|
||||
return str.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrait et convertit une liste de rôles depuis un objet JSON
|
||||
*/
|
||||
private List<String> extractRolesFromList(Object rolesObj) {
|
||||
List<String> roles = new ArrayList<>();
|
||||
if (rolesObj instanceof List) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> rolesList = (List<Object>) rolesObj;
|
||||
for (Object roleObj : rolesList) {
|
||||
String role = convertToString(roleObj);
|
||||
if (role != null && !role.isEmpty()) {
|
||||
// S'assurer que c'est vraiment un String en créant une nouvelle instance
|
||||
roles.add(new String(role));
|
||||
LOGGER.fine("Rôle converti: '" + role + "' (type: " + role.getClass().getName() + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extrait les rôles depuis le token JWT
|
||||
*/
|
||||
private List<String> extractRolesFromToken() {
|
||||
List<String> extractedRoles = new ArrayList<>();
|
||||
|
||||
// Rôles dans "realm_access.roles"
|
||||
try {
|
||||
Object realmAccess = jwt.getClaim("realm_access");
|
||||
if (realmAccess instanceof java.util.Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
java.util.Map<String, Object> realmMap = (java.util.Map<String, Object>) realmAccess;
|
||||
Object rolesObj = realmMap.get("roles");
|
||||
List<String> realmRoles = extractRolesFromList(rolesObj);
|
||||
if (!realmRoles.isEmpty()) {
|
||||
extractedRoles.addAll(realmRoles);
|
||||
LOGGER.info("Rôles extraits depuis realm_access.roles: " + realmRoles);
|
||||
}
|
||||
} else if (realmAccess instanceof List) {
|
||||
// Fallback: si realm_access est directement une liste de rôles
|
||||
List<String> realmRoles = extractRolesFromList(realmAccess);
|
||||
if (!realmRoles.isEmpty()) {
|
||||
extractedRoles.addAll(realmRoles);
|
||||
LOGGER.info("Rôles extraits depuis realm_access (liste): " + realmRoles);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Erreur lors de l'extraction des rôles realm: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Rôles dans "resource_access"
|
||||
try {
|
||||
Object resourceAccess = jwt.getClaim("resource_access");
|
||||
if (resourceAccess instanceof java.util.Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
java.util.Map<String, Object> resourceMap = (java.util.Map<String, Object>) resourceAccess;
|
||||
for (Object value : resourceMap.values()) {
|
||||
if (value instanceof java.util.Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
java.util.Map<String, Object> clientMap = (java.util.Map<String, Object>) value;
|
||||
Object rolesObj = clientMap.get("roles");
|
||||
List<String> clientRoles = extractRolesFromList(rolesObj);
|
||||
if (!clientRoles.isEmpty()) {
|
||||
extractedRoles.addAll(clientRoles);
|
||||
LOGGER.info("Rôles extraits depuis resource_access: " + clientRoles);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Erreur lors de l'extraction des rôles client: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Fallback: essayer d'extraire les rôles depuis le claim "roles" directement
|
||||
if (extractedRoles.isEmpty()) {
|
||||
try {
|
||||
Object rolesClaim = jwt.getClaim("roles");
|
||||
List<String> directRoles = extractRolesFromList(rolesClaim);
|
||||
if (!directRoles.isEmpty()) {
|
||||
extractedRoles.addAll(directRoles);
|
||||
LOGGER.info("Rôles extraits depuis claim 'roles': " + directRoles);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Erreur lors de l'extraction des rôles depuis claim 'roles': " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info("Total des rôles extraits: " + extractedRoles);
|
||||
return extractedRoles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Détermine le type de compte depuis les rôles
|
||||
*/
|
||||
private String determineTypeCompte() {
|
||||
// Utiliser this.roles pour s'assurer qu'on utilise la bonne variable d'instance
|
||||
List<String> rolesToCheck = this.roles;
|
||||
|
||||
if (rolesToCheck == null || rolesToCheck.isEmpty()) {
|
||||
LOGGER.warning("Aucun rôle trouvé, type de compte par défaut: MEMBRE");
|
||||
return "MEMBRE";
|
||||
}
|
||||
|
||||
LOGGER.info("Détermination du type de compte depuis les rôles: " + rolesToCheck);
|
||||
LOGGER.info("Nombre de rôles: " + rolesToCheck.size());
|
||||
|
||||
// Vérifier le type des éléments de la liste
|
||||
if (!rolesToCheck.isEmpty()) {
|
||||
Object firstRole = rolesToCheck.get(0);
|
||||
LOGGER.info("Type du premier rôle: " + (firstRole != null ? firstRole.getClass().getName() : "null"));
|
||||
LOGGER.info("Premier rôle (toString): '" + firstRole + "'");
|
||||
LOGGER.info("Premier rôle (length): " + (firstRole != null ? firstRole.toString().length() : 0));
|
||||
// Vérifier les caractères du premier rôle
|
||||
if (firstRole != null) {
|
||||
String firstRoleStr = firstRole.toString();
|
||||
LOGGER.info("Premier rôle (bytes): " + java.util.Arrays.toString(firstRoleStr.getBytes()));
|
||||
}
|
||||
}
|
||||
|
||||
// Vérifier SUPER_ADMIN en parcourant la liste (plus robuste que contains)
|
||||
for (String role : rolesToCheck) {
|
||||
if (role != null) {
|
||||
// Nettoyer la chaîne : retirer les guillemets et espaces
|
||||
String roleStr = role.toString().trim();
|
||||
// Retirer les guillemets simples et doubles au début et à la fin
|
||||
if (roleStr.startsWith("'") && roleStr.endsWith("'")) {
|
||||
roleStr = roleStr.substring(1, roleStr.length() - 1);
|
||||
}
|
||||
if (roleStr.startsWith("\"") && roleStr.endsWith("\"")) {
|
||||
roleStr = roleStr.substring(1, roleStr.length() - 1);
|
||||
}
|
||||
roleStr = roleStr.trim();
|
||||
|
||||
LOGGER.info("Vérification du rôle: '" + roleStr + "' (longueur: " + roleStr.length() + ", original: '" + role + "')");
|
||||
if ("SUPER_ADMIN".equals(roleStr) || "super-admin".equalsIgnoreCase(roleStr)) {
|
||||
LOGGER.info("✅ Type de compte détecté: SUPER_ADMIN (rôle trouvé: '" + roleStr + "')");
|
||||
return "SUPER_ADMIN";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: utiliser contains() pour compatibilité
|
||||
boolean hasSuperAdmin = rolesToCheck.contains("SUPER_ADMIN");
|
||||
boolean hasSuperAdminLower = rolesToCheck.contains("super-admin");
|
||||
LOGGER.info("Contient 'SUPER_ADMIN' (contains): " + hasSuperAdmin);
|
||||
LOGGER.info("Contient 'super-admin' (contains): " + hasSuperAdminLower);
|
||||
|
||||
if (hasSuperAdmin || hasSuperAdminLower) {
|
||||
LOGGER.info("✅ Type de compte détecté: SUPER_ADMIN (via contains)");
|
||||
return "SUPER_ADMIN";
|
||||
}
|
||||
|
||||
// Vérifier ADMIN_ENTITE (mais pas si c'est juste "ADMIN" qui pourrait être ambigu)
|
||||
if (rolesToCheck.contains("ADMIN_ENTITE")) {
|
||||
LOGGER.info("Type de compte détecté: ADMIN_ENTITE");
|
||||
return "ADMIN_ENTITE";
|
||||
}
|
||||
|
||||
// Vérifier les autres rôles admin (avec précaution pour éviter les faux positifs)
|
||||
for (String role : rolesToCheck) {
|
||||
if (role != null && (role.equals("ADMIN") || role.equalsIgnoreCase("admin"))) {
|
||||
LOGGER.info("Type de compte détecté: ADMIN_ENTITE (via rôle ADMIN)");
|
||||
return "ADMIN_ENTITE";
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.warning("Aucun rôle admin trouvé, type de compte par défaut: MEMBRE");
|
||||
return "MEMBRE";
|
||||
}
|
||||
|
||||
public void clearSession() {
|
||||
this.authenticated = false;
|
||||
this.username = null;
|
||||
this.typeCompte = null;
|
||||
this.roles = null;
|
||||
this.permissions = null;
|
||||
this.currentUser = null;
|
||||
this.entite = null;
|
||||
|
||||
LOGGER.info("Session utilisateur effacée");
|
||||
}
|
||||
|
||||
// Méthodes de vérification des rôles et permissions
|
||||
public boolean hasRole(String role) {
|
||||
return roles != null && roles.contains(role);
|
||||
}
|
||||
|
||||
public boolean hasPermission(String permission) {
|
||||
return permissions != null && permissions.contains(permission);
|
||||
}
|
||||
|
||||
public boolean isSuperAdmin() {
|
||||
return "SUPER_ADMIN".equals(typeCompte) || hasRole("SUPER_ADMIN");
|
||||
}
|
||||
|
||||
public boolean isAdmin() {
|
||||
return isSuperAdmin() || "ADMIN_ENTITE".equals(typeCompte) || hasRole("ADMIN_ENTITE");
|
||||
}
|
||||
|
||||
public boolean isMembre() {
|
||||
return "MEMBRE".equals(typeCompte) || hasRole("MEMBRE");
|
||||
}
|
||||
|
||||
// Méthode pour obtenir le rôle principal
|
||||
public String getRole() {
|
||||
if (isSuperAdmin()) {
|
||||
return "SUPER_ADMIN";
|
||||
}
|
||||
if (isAdmin()) {
|
||||
return "ADMIN";
|
||||
}
|
||||
if (typeCompte != null) {
|
||||
return typeCompte;
|
||||
}
|
||||
if (roles != null && !roles.isEmpty()) {
|
||||
return roles.get(0);
|
||||
}
|
||||
return "MEMBER";
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public boolean isAuthenticated() {
|
||||
// Vérifier via JsonWebToken
|
||||
if (jwt != null && jwt.getName() != null && !authenticated) {
|
||||
initializeFromOidcToken();
|
||||
}
|
||||
return authenticated || (jwt != null && jwt.getName() != null);
|
||||
}
|
||||
|
||||
public void setAuthenticated(boolean authenticated) {
|
||||
this.authenticated = authenticated;
|
||||
}
|
||||
|
||||
public String getTypeCompte() {
|
||||
// Si le type de compte n'est pas encore déterminé, l'initialiser
|
||||
if (typeCompte == null && jwt != null && jwt.getName() != null) {
|
||||
LOGGER.info("getTypeCompte() appelé avant initialisation, initialisation en cours...");
|
||||
initializeFromOidcToken();
|
||||
}
|
||||
return typeCompte;
|
||||
}
|
||||
|
||||
public void setTypeCompte(String typeCompte) {
|
||||
this.typeCompte = typeCompte;
|
||||
}
|
||||
|
||||
public List<String> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<String> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
|
||||
public List<String> getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public void setPermissions(List<String> permissions) {
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public CurrentUser getCurrentUser() {
|
||||
return currentUser;
|
||||
}
|
||||
|
||||
public void setCurrentUser(CurrentUser currentUser) {
|
||||
this.currentUser = currentUser;
|
||||
}
|
||||
|
||||
public EntiteInfo getEntite() {
|
||||
return entite;
|
||||
}
|
||||
|
||||
public void setEntite(EntiteInfo entite) {
|
||||
this.entite = entite;
|
||||
}
|
||||
|
||||
// Classes internes
|
||||
public static class CurrentUser implements Serializable {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
private String prenom;
|
||||
private String email;
|
||||
private String username;
|
||||
|
||||
public String getNomComplet() {
|
||||
if (prenom != null && nom != null) {
|
||||
return prenom + " " + nom;
|
||||
}
|
||||
return nom != null ? nom : username;
|
||||
}
|
||||
|
||||
public String getInitiales() {
|
||||
StringBuilder initiales = new StringBuilder();
|
||||
if (prenom != null && !prenom.isEmpty()) {
|
||||
initiales.append(prenom.charAt(0));
|
||||
}
|
||||
if (nom != null && !nom.isEmpty()) {
|
||||
initiales.append(nom.charAt(0));
|
||||
}
|
||||
return initiales.toString().toUpperCase();
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
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 getPrenom() {
|
||||
return prenom;
|
||||
}
|
||||
|
||||
public void setPrenom(String prenom) {
|
||||
this.prenom = prenom;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EntiteInfo implements Serializable {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
private String type;
|
||||
private String pays;
|
||||
private String ville;
|
||||
|
||||
public String getDescription() {
|
||||
StringBuilder desc = new StringBuilder();
|
||||
if (nom != null) {
|
||||
desc.append(nom);
|
||||
}
|
||||
if (ville != null && pays != null) {
|
||||
desc.append(" (").append(ville).append(", ").append(pays).append(")");
|
||||
}
|
||||
return desc.toString();
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
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 String getPays() {
|
||||
return pays;
|
||||
}
|
||||
|
||||
public void setPays(String pays) {
|
||||
this.pays = pays;
|
||||
}
|
||||
|
||||
public String getVille() {
|
||||
return ville;
|
||||
}
|
||||
|
||||
public void setVille(String ville) {
|
||||
this.ville = ville;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,399 @@
|
||||
package dev.lions.unionflow.client.view;
|
||||
|
||||
import dev.lions.unionflow.client.dto.AssociationDTO;
|
||||
import dev.lions.unionflow.client.service.AssociationService;
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
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.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@Named("utilisateursBean")
|
||||
@SessionScoped
|
||||
public class UtilisateursBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger LOGGER = Logger.getLogger(UtilisateursBean.class.getName());
|
||||
|
||||
@Inject
|
||||
@RestClient
|
||||
private AssociationService associationService;
|
||||
|
||||
private List<Utilisateur> tousLesUtilisateurs;
|
||||
private List<Utilisateur> utilisateursFiltres;
|
||||
private List<Utilisateur> utilisateursSelectionnes;
|
||||
private List<Organisation> organisationsDisponibles;
|
||||
|
||||
private Utilisateur utilisateurSelectionne;
|
||||
private NouvelUtilisateur nouvelUtilisateur;
|
||||
private Filtres filtres;
|
||||
private StatistiquesUtilisateurs statistiques;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
initializeFiltres();
|
||||
initializeOrganisations();
|
||||
initializeUtilisateurs();
|
||||
initializeStatistiques();
|
||||
initializeNouvelUtilisateur();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
private void initializeFiltres() {
|
||||
filtres = new Filtres();
|
||||
utilisateursSelectionnes = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void initializeStatistiques() {
|
||||
statistiques = new StatistiquesUtilisateurs();
|
||||
// Les statistiques seront calculées depuis l'API backend quand elle sera disponible
|
||||
statistiques.setTotalUtilisateurs(tousLesUtilisateurs != null ? tousLesUtilisateurs.size() : 0);
|
||||
statistiques.setUtilisateursConnectes(0);
|
||||
statistiques.setAdministrateurs(0);
|
||||
statistiques.setUtilisateursDesactives(0);
|
||||
}
|
||||
|
||||
private void initializeOrganisations() {
|
||||
organisationsDisponibles = new ArrayList<>();
|
||||
try {
|
||||
List<AssociationDTO> associations = associationService.listerToutes(0, 1000);
|
||||
for (AssociationDTO assoc : associations) {
|
||||
Organisation org = new Organisation();
|
||||
org.setId(assoc.getId());
|
||||
org.setNom(assoc.getNom());
|
||||
organisationsDisponibles.add(org);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement des organisations: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeUtilisateurs() {
|
||||
tousLesUtilisateurs = new ArrayList<>();
|
||||
// Les utilisateurs seront chargés depuis l'API backend quand elle sera disponible
|
||||
// Pour l'instant, retourner une liste vide
|
||||
LOGGER.info("Initialisation des utilisateurs - API backend non disponible");
|
||||
}
|
||||
|
||||
private void initializeNouvelUtilisateur() {
|
||||
nouvelUtilisateur = new NouvelUtilisateur();
|
||||
nouvelUtilisateur.setRole("USER");
|
||||
nouvelUtilisateur.setEnvoyerEmail(true);
|
||||
}
|
||||
|
||||
private void appliquerFiltres() {
|
||||
utilisateursFiltres = tousLesUtilisateurs.stream()
|
||||
.filter(this::appliquerFiltre)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean appliquerFiltre(Utilisateur utilisateur) {
|
||||
if (filtres.getRecherche() != null && !filtres.getRecherche().trim().isEmpty()) {
|
||||
String recherche = filtres.getRecherche().toLowerCase();
|
||||
if (!utilisateur.getNomComplet().toLowerCase().contains(recherche) &&
|
||||
!utilisateur.getEmail().toLowerCase().contains(recherche)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getRole() != null && !filtres.getRole().trim().isEmpty()) {
|
||||
if (!utilisateur.getRole().equals(filtres.getRole())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getStatut() != null && !filtres.getStatut().trim().isEmpty()) {
|
||||
if (!utilisateur.getStatut().equals(filtres.getStatut())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtres.getOrganisation() != null && !filtres.getOrganisation().toString().trim().isEmpty()) {
|
||||
if (!utilisateur.getOrganisationId().equals(filtres.getOrganisation())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Actions
|
||||
public void rechercher() {
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void reinitialiserFiltres() {
|
||||
filtres = new Filtres();
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void creerUtilisateur() {
|
||||
// À implémenter quand l'API backend sera disponible
|
||||
LOGGER.info("Création d'utilisateur - API backend non disponible");
|
||||
initializeNouvelUtilisateur();
|
||||
}
|
||||
|
||||
public void activerUtilisateur(Utilisateur utilisateur) {
|
||||
// À implémenter quand l'API backend sera disponible
|
||||
LOGGER.info("Activation d'utilisateur - API backend non disponible");
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void desactiverUtilisateur(Utilisateur utilisateur) {
|
||||
// À implémenter quand l'API backend sera disponible
|
||||
LOGGER.info("Désactivation d'utilisateur - API backend non disponible");
|
||||
appliquerFiltres();
|
||||
}
|
||||
|
||||
public void exporterUtilisateurs() {
|
||||
// À implémenter quand l'API backend sera disponible
|
||||
LOGGER.info("Export d'utilisateurs - API backend non disponible");
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public List<Utilisateur> getTousLesUtilisateurs() { return tousLesUtilisateurs; }
|
||||
public void setTousLesUtilisateurs(List<Utilisateur> tousLesUtilisateurs) { this.tousLesUtilisateurs = tousLesUtilisateurs; }
|
||||
|
||||
public List<Utilisateur> getUtilisateursFiltres() { return utilisateursFiltres; }
|
||||
public void setUtilisateursFiltres(List<Utilisateur> utilisateursFiltres) { this.utilisateursFiltres = utilisateursFiltres; }
|
||||
|
||||
public List<Utilisateur> getUtilisateursSelectionnes() { return utilisateursSelectionnes; }
|
||||
public void setUtilisateursSelectionnes(List<Utilisateur> utilisateursSelectionnes) { this.utilisateursSelectionnes = utilisateursSelectionnes; }
|
||||
|
||||
public List<Organisation> getOrganisationsDisponibles() { return organisationsDisponibles; }
|
||||
public void setOrganisationsDisponibles(List<Organisation> organisationsDisponibles) { this.organisationsDisponibles = organisationsDisponibles; }
|
||||
|
||||
public Utilisateur getUtilisateurSelectionne() { return utilisateurSelectionne; }
|
||||
public void setUtilisateurSelectionne(Utilisateur utilisateurSelectionne) { this.utilisateurSelectionne = utilisateurSelectionne; }
|
||||
|
||||
public NouvelUtilisateur getNouvelUtilisateur() { return nouvelUtilisateur; }
|
||||
public void setNouvelUtilisateur(NouvelUtilisateur nouvelUtilisateur) { this.nouvelUtilisateur = nouvelUtilisateur; }
|
||||
|
||||
public Filtres getFiltres() { return filtres; }
|
||||
public void setFiltres(Filtres filtres) { this.filtres = filtres; }
|
||||
|
||||
public StatistiquesUtilisateurs getStatistiques() { return statistiques; }
|
||||
public void setStatistiques(StatistiquesUtilisateurs statistiques) { this.statistiques = statistiques; }
|
||||
|
||||
// Classes internes
|
||||
public static class Utilisateur {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
private String prenom;
|
||||
private String email;
|
||||
private String telephone;
|
||||
private String role;
|
||||
private String statut;
|
||||
private UUID organisationId;
|
||||
private LocalDateTime dateCreation;
|
||||
private LocalDateTime derniereConnexion;
|
||||
|
||||
// Getters et setters
|
||||
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 getPrenom() { return prenom; }
|
||||
public void setPrenom(String prenom) { this.prenom = prenom; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public String getTelephone() { return telephone; }
|
||||
public void setTelephone(String telephone) { this.telephone = telephone; }
|
||||
|
||||
public String getRole() { return role; }
|
||||
public void setRole(String role) { this.role = role; }
|
||||
|
||||
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 LocalDateTime getDateCreation() { return dateCreation; }
|
||||
public void setDateCreation(LocalDateTime dateCreation) { this.dateCreation = dateCreation; }
|
||||
|
||||
public LocalDateTime getDerniereConnexion() { return derniereConnexion; }
|
||||
public void setDerniereConnexion(LocalDateTime derniereConnexion) { this.derniereConnexion = derniereConnexion; }
|
||||
|
||||
// Propriétés dérivées
|
||||
public String getNomComplet() {
|
||||
return prenom + " " + nom;
|
||||
}
|
||||
|
||||
public String getRoleLibelle() {
|
||||
return switch (role) {
|
||||
case "USER" -> "Utilisateur";
|
||||
case "GESTIONNAIRE" -> "Gestionnaire";
|
||||
case "ADMIN" -> "Administrateur";
|
||||
case "SUPER_ADMIN" -> "Super Admin";
|
||||
default -> role;
|
||||
};
|
||||
}
|
||||
|
||||
public String getRoleSeverity() {
|
||||
return switch (role) {
|
||||
case "USER" -> "info";
|
||||
case "GESTIONNAIRE" -> "primary";
|
||||
case "ADMIN" -> "warning";
|
||||
case "SUPER_ADMIN" -> "danger";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutLibelle() {
|
||||
return switch (statut) {
|
||||
case "ACTIF" -> "Actif";
|
||||
case "INACTIF" -> "Inactif";
|
||||
case "SUSPENDU" -> "Suspendu";
|
||||
case "ATTENTE" -> "En attente";
|
||||
default -> statut;
|
||||
};
|
||||
}
|
||||
|
||||
public String getStatutSeverity() {
|
||||
return switch (statut) {
|
||||
case "ACTIF" -> "success";
|
||||
case "INACTIF" -> "secondary";
|
||||
case "SUSPENDU" -> "danger";
|
||||
case "ATTENTE" -> "warning";
|
||||
default -> "secondary";
|
||||
};
|
||||
}
|
||||
|
||||
public String getOrganisationNom() {
|
||||
// Simulation - en réalité, on ferait un lookup dans la base
|
||||
if (organisationId == null) return "Non définie";
|
||||
String orgIdStr = organisationId.toString();
|
||||
if (orgIdStr.contains("000000000100")) return "Direction Générale";
|
||||
if (orgIdStr.contains("000000000200")) return "Services Financiers";
|
||||
if (orgIdStr.contains("000000000300")) return "Ressources Humaines";
|
||||
if (orgIdStr.contains("000000000400")) return "Communication";
|
||||
return "Non définie";
|
||||
}
|
||||
|
||||
public String getDateCreationFormatee() {
|
||||
if (dateCreation == null) return "";
|
||||
return dateCreation.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
|
||||
}
|
||||
|
||||
public String getDerniereConnexionFormatee() {
|
||||
if (derniereConnexion == null) return "Jamais";
|
||||
return derniereConnexion.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"));
|
||||
}
|
||||
|
||||
public String getDerniereConnexionRelative() {
|
||||
if (derniereConnexion == null) return "Jamais connecté";
|
||||
long jours = ChronoUnit.DAYS.between(derniereConnexion, LocalDateTime.now());
|
||||
if (jours == 0) return "Aujourd'hui";
|
||||
if (jours == 1) return "Hier";
|
||||
if (jours < 7) return "Il y a " + jours + " jours";
|
||||
if (jours < 30) return "Il y a " + (jours / 7) + " semaine(s)";
|
||||
return "Il y a " + (jours / 30) + " mois";
|
||||
}
|
||||
}
|
||||
|
||||
public static class NouvelUtilisateur {
|
||||
private String nom;
|
||||
private String prenom;
|
||||
private String email;
|
||||
private String telephone;
|
||||
private String role;
|
||||
private UUID organisationId;
|
||||
private String motDePasse;
|
||||
private boolean envoyerEmail;
|
||||
|
||||
// Getters et setters
|
||||
public String getNom() { return nom; }
|
||||
public void setNom(String nom) { this.nom = nom; }
|
||||
|
||||
public String getPrenom() { return prenom; }
|
||||
public void setPrenom(String prenom) { this.prenom = prenom; }
|
||||
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
|
||||
public String getTelephone() { return telephone; }
|
||||
public void setTelephone(String telephone) { this.telephone = telephone; }
|
||||
|
||||
public String getRole() { return role; }
|
||||
public void setRole(String role) { this.role = role; }
|
||||
|
||||
public UUID getOrganisationId() { return organisationId; }
|
||||
public void setOrganisationId(UUID organisationId) { this.organisationId = organisationId; }
|
||||
|
||||
public String getMotDePasse() { return motDePasse; }
|
||||
public void setMotDePasse(String motDePasse) { this.motDePasse = motDePasse; }
|
||||
|
||||
public boolean isEnvoyerEmail() { return envoyerEmail; }
|
||||
public void setEnvoyerEmail(boolean envoyerEmail) { this.envoyerEmail = envoyerEmail; }
|
||||
}
|
||||
|
||||
public static class Filtres {
|
||||
private String recherche;
|
||||
private String role;
|
||||
private String statut;
|
||||
private String connexion;
|
||||
private UUID organisation;
|
||||
|
||||
// Getters et setters
|
||||
public String getRecherche() { return recherche; }
|
||||
public void setRecherche(String recherche) { this.recherche = recherche; }
|
||||
|
||||
public String getRole() { return role; }
|
||||
public void setRole(String role) { this.role = role; }
|
||||
|
||||
public String getStatut() { return statut; }
|
||||
public void setStatut(String statut) { this.statut = statut; }
|
||||
|
||||
public String getConnexion() { return connexion; }
|
||||
public void setConnexion(String connexion) { this.connexion = connexion; }
|
||||
|
||||
public UUID getOrganisation() { return organisation; }
|
||||
public void setOrganisation(UUID organisation) { this.organisation = organisation; }
|
||||
}
|
||||
|
||||
public static class StatistiquesUtilisateurs {
|
||||
private int totalUtilisateurs;
|
||||
private int utilisateursConnectes;
|
||||
private int administrateurs;
|
||||
private int utilisateursDesactives;
|
||||
|
||||
// Getters et setters
|
||||
public int getTotalUtilisateurs() { return totalUtilisateurs; }
|
||||
public void setTotalUtilisateurs(int totalUtilisateurs) { this.totalUtilisateurs = totalUtilisateurs; }
|
||||
|
||||
public int getUtilisateursConnectes() { return utilisateursConnectes; }
|
||||
public void setUtilisateursConnectes(int utilisateursConnectes) { this.utilisateursConnectes = utilisateursConnectes; }
|
||||
|
||||
public int getAdministrateurs() { return administrateurs; }
|
||||
public void setAdministrateurs(int administrateurs) { this.administrateurs = administrateurs; }
|
||||
|
||||
public int getUtilisateursDesactives() { return utilisateursDesactives; }
|
||||
public void setUtilisateursDesactives(int utilisateursDesactives) { this.utilisateursDesactives = utilisateursDesactives; }
|
||||
}
|
||||
|
||||
public static class Organisation {
|
||||
private UUID id;
|
||||
private String nom;
|
||||
|
||||
// Getters et setters
|
||||
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; }
|
||||
}
|
||||
}
|
||||
279
src/main/java/dev/lions/unionflow/client/view/WaveBean.java
Normal file
279
src/main/java/dev/lions/unionflow/client/view/WaveBean.java
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
653
src/main/resources/META-INF/faces-config.xml
Normal file
653
src/main/resources/META-INF/faces-config.xml
Normal file
@@ -0,0 +1,653 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<faces-config xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
|
||||
https://jakarta.ee/xml/ns/jakartaee/web-facesconfig_4_0.xsd"
|
||||
version="4.0">
|
||||
|
||||
<name>UnionFlow</name>
|
||||
|
||||
<ordering>
|
||||
<after>
|
||||
<name>omnifaces</name>
|
||||
</after>
|
||||
</ordering>
|
||||
|
||||
<factory>
|
||||
<exception-handler-factory>
|
||||
dev.lions.unionflow.client.exception.ViewExpiredExceptionHandlerFactory
|
||||
</exception-handler-factory>
|
||||
</factory>
|
||||
|
||||
<application>
|
||||
<locale-config>
|
||||
<default-locale>fr</default-locale>
|
||||
<supported-locale>fr</supported-locale>
|
||||
<supported-locale>en</supported-locale>
|
||||
</locale-config>
|
||||
</application>
|
||||
|
||||
<navigation-rule>
|
||||
<from-view-id>*</from-view-id>
|
||||
|
||||
<!-- Dashboard -->
|
||||
<navigation-case>
|
||||
<description>Page d'accueil / Dashboard</description>
|
||||
<from-outcome>dashboardPage</from-outcome>
|
||||
<to-view-id>/pages/secure/dashboard.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Membre -->
|
||||
<navigation-case>
|
||||
<description>Page de liste des membres</description>
|
||||
<from-outcome>membreListPage</from-outcome>
|
||||
<to-view-id>/pages/secure/membre/liste.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'inscription de membre</description>
|
||||
<from-outcome>membreInscriptionPage</from-outcome>
|
||||
<to-view-id>/pages/secure/membre/inscription.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de profil de membre</description>
|
||||
<from-outcome>membreProfilPage</from-outcome>
|
||||
<to-view-id>/pages/secure/membre/profil.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de recherche de membre</description>
|
||||
<from-outcome>membreRecherchePage</from-outcome>
|
||||
<to-view-id>/pages/secure/membre/recherche.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de modification de membre</description>
|
||||
<from-outcome>membreModifierPage</from-outcome>
|
||||
<to-view-id>/pages/secure/membre/inscription.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de cotisations d'un membre</description>
|
||||
<from-outcome>membreCotisationsPage</from-outcome>
|
||||
<to-view-id>/pages/secure/membre/cotisations.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Organisation -->
|
||||
<navigation-case>
|
||||
<description>Page de liste des organisations</description>
|
||||
<from-outcome>organisationListPage</from-outcome>
|
||||
<to-view-id>/pages/secure/organisation/liste.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de création d'organisation</description>
|
||||
<from-outcome>organisationNouvellePage</from-outcome>
|
||||
<to-view-id>/pages/secure/organisation/nouvelle.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de détail d'organisation</description>
|
||||
<from-outcome>organisationDetailPage</from-outcome>
|
||||
<to-view-id>/pages/secure/organisation/detail.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Événement -->
|
||||
<navigation-case>
|
||||
<description>Page de gestion des événements</description>
|
||||
<from-outcome>evenementGestionPage</from-outcome>
|
||||
<to-view-id>/pages/secure/evenement/gestion.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de création d'événement</description>
|
||||
<from-outcome>evenementCreationPage</from-outcome>
|
||||
<to-view-id>/pages/secure/evenement/creation.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de planification d'événement</description>
|
||||
<from-outcome>evenementPlanificationPage</from-outcome>
|
||||
<to-view-id>/pages/secure/evenement/planification.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de logistique d'événement</description>
|
||||
<from-outcome>evenementLogistiquePage</from-outcome>
|
||||
<to-view-id>/pages/secure/evenement/logistique.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de bilan d'événement</description>
|
||||
<from-outcome>evenementBilanPage</from-outcome>
|
||||
<to-view-id>/pages/secure/evenement/bilan.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de réservations d'événement</description>
|
||||
<from-outcome>evenementReservationsPage</from-outcome>
|
||||
<to-view-id>/pages/secure/evenement/reservations.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de calendrier d'événements</description>
|
||||
<from-outcome>evenementCalendrierPage</from-outcome>
|
||||
<to-view-id>/pages/secure/evenement/calendrier.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de participants d'événement</description>
|
||||
<from-outcome>evenementParticipantsPage</from-outcome>
|
||||
<to-view-id>/pages/secure/evenement/participants.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de participation à un événement</description>
|
||||
<from-outcome>evenementParticipationPage</from-outcome>
|
||||
<to-view-id>/pages/secure/evenement/participation.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Cotisation -->
|
||||
<navigation-case>
|
||||
<description>Page de collecte de cotisations</description>
|
||||
<from-outcome>cotisationCollectPage</from-outcome>
|
||||
<to-view-id>/pages/secure/cotisation/collect.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de paiement de cotisation</description>
|
||||
<from-outcome>cotisationPaiementPage</from-outcome>
|
||||
<to-view-id>/pages/secure/cotisation/paiement.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'historique des cotisations</description>
|
||||
<from-outcome>cotisationHistoriquePage</from-outcome>
|
||||
<to-view-id>/pages/secure/cotisation/historique.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de rappels de cotisations</description>
|
||||
<from-outcome>cotisationRelancesPage</from-outcome>
|
||||
<to-view-id>/pages/secure/cotisation/relances.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de rapports de cotisations</description>
|
||||
<from-outcome>cotisationRapportsPage</from-outcome>
|
||||
<to-view-id>/pages/secure/cotisation/rapports.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Adhésion -->
|
||||
<navigation-case>
|
||||
<description>Page de liste des adhésions</description>
|
||||
<from-outcome>adhesionListPage</from-outcome>
|
||||
<to-view-id>/pages/secure/adhesion/liste.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de nouvelle adhésion</description>
|
||||
<from-outcome>adhesionNouvellePage</from-outcome>
|
||||
<to-view-id>/pages/secure/adhesion/new.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de demande d'adhésion</description>
|
||||
<from-outcome>adhesionDemandePage</from-outcome>
|
||||
<to-view-id>/pages/secure/adhesion/demande.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de validation d'adhésion</description>
|
||||
<from-outcome>adhesionValidationPage</from-outcome>
|
||||
<to-view-id>/pages/secure/adhesion/validation.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de paiement d'adhésion</description>
|
||||
<from-outcome>adhesionPaiementPage</from-outcome>
|
||||
<to-view-id>/pages/secure/adhesion/paiement.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de renouvellement d'adhésion</description>
|
||||
<from-outcome>adhesionRenouvellementPage</from-outcome>
|
||||
<to-view-id>/pages/secure/adhesion/renouvellement.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'historique des adhésions</description>
|
||||
<from-outcome>adhesionHistoriquePage</from-outcome>
|
||||
<to-view-id>/pages/secure/adhesion/history.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'adhésions en attente</description>
|
||||
<from-outcome>adhesionPendingPage</from-outcome>
|
||||
<to-view-id>/pages/secure/adhesion/pending.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Aide -->
|
||||
<navigation-case>
|
||||
<description>Page de demande d'aide</description>
|
||||
<from-outcome>aideDemandePage</from-outcome>
|
||||
<to-view-id>/pages/secure/aide/demande.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de traitement des demandes d'aide</description>
|
||||
<from-outcome>aideTraitementPage</from-outcome>
|
||||
<to-view-id>/pages/secure/aide/traitement.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'historique des demandes d'aide</description>
|
||||
<from-outcome>aideHistoriquePage</from-outcome>
|
||||
<to-view-id>/pages/secure/aide/historique.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de FAQ</description>
|
||||
<from-outcome>aideFaqPage</from-outcome>
|
||||
<to-view-id>/pages/secure/aide/faq.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de documentation</description>
|
||||
<from-outcome>aideDocumentationPage</from-outcome>
|
||||
<to-view-id>/pages/secure/aide/documentation.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de guide</description>
|
||||
<from-outcome>aideGuidePage</from-outcome>
|
||||
<to-view-id>/pages/secure/aide/guide.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de tutoriels</description>
|
||||
<from-outcome>aideTutorielsPage</from-outcome>
|
||||
<to-view-id>/pages/secure/aide/tutoriels.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de support</description>
|
||||
<from-outcome>aideSupportPage</from-outcome>
|
||||
<to-view-id>/pages/secure/aide/support.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de tickets</description>
|
||||
<from-outcome>aideTicketsPage</from-outcome>
|
||||
<to-view-id>/pages/secure/aide/tickets.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de statistiques d'aide</description>
|
||||
<from-outcome>aideStatistiquesPage</from-outcome>
|
||||
<to-view-id>/pages/secure/aide/statistiques.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Rapport -->
|
||||
<navigation-case>
|
||||
<description>Page de rapports de membres</description>
|
||||
<from-outcome>rapportMembresPage</from-outcome>
|
||||
<to-view-id>/pages/secure/rapport/membres.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de rapports financiers</description>
|
||||
<from-outcome>rapportFinancesPage</from-outcome>
|
||||
<to-view-id>/pages/secure/rapport/finances.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de rapports d'activités</description>
|
||||
<from-outcome>rapportActivitesPage</from-outcome>
|
||||
<to-view-id>/pages/secure/rapport/activites.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'export de rapports</description>
|
||||
<from-outcome>rapportExportPage</from-outcome>
|
||||
<to-view-id>/pages/secure/rapport/export.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de détails d'un rapport</description>
|
||||
<from-outcome>rapportDetailsPage</from-outcome>
|
||||
<to-view-id>/pages/secure/rapport/details.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Personnel -->
|
||||
<navigation-case>
|
||||
<description>Page de profil personnel</description>
|
||||
<from-outcome>personnelProfilPage</from-outcome>
|
||||
<to-view-id>/pages/secure/personnel/profil.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de notifications personnelles</description>
|
||||
<from-outcome>personnelNotificationsPage</from-outcome>
|
||||
<to-view-id>/pages/secure/personnel/notifications.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de documents personnels</description>
|
||||
<from-outcome>personnelDocumentsPage</from-outcome>
|
||||
<to-view-id>/pages/secure/personnel/documents.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'agenda personnel</description>
|
||||
<from-outcome>personnelAgendaPage</from-outcome>
|
||||
<to-view-id>/pages/secure/personnel/agenda.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'activités personnelles</description>
|
||||
<from-outcome>personnelActivitesPage</from-outcome>
|
||||
<to-view-id>/pages/secure/personnel/activites.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de favoris personnels</description>
|
||||
<from-outcome>personnelFavorisPage</from-outcome>
|
||||
<to-view-id>/pages/secure/personnel/favoris.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de paramètres personnels</description>
|
||||
<from-outcome>personnelParametresPage</from-outcome>
|
||||
<to-view-id>/pages/secure/personnel/parametres.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de préférences personnelles</description>
|
||||
<from-outcome>personnelPreferencesPage</from-outcome>
|
||||
<to-view-id>/pages/secure/personnel/preferences.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Admin -->
|
||||
<navigation-case>
|
||||
<description>Page de gestion des utilisateurs</description>
|
||||
<from-outcome>adminUtilisateursPage</from-outcome>
|
||||
<to-view-id>/pages/secure/admin/utilisateurs.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de gestion des rôles</description>
|
||||
<from-outcome>adminRolesPage</from-outcome>
|
||||
<to-view-id>/pages/secure/admin/roles.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de paramètres d'administration</description>
|
||||
<from-outcome>adminParametresPage</from-outcome>
|
||||
<to-view-id>/pages/secure/admin/parametres.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'audit</description>
|
||||
<from-outcome>adminAuditPage</from-outcome>
|
||||
<to-view-id>/pages/secure/admin/audit.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de sauvegarde</description>
|
||||
<from-outcome>adminSauvegardePage</from-outcome>
|
||||
<to-view-id>/pages/secure/admin/sauvegarde.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Souscription -->
|
||||
<navigation-case>
|
||||
<description>Page de dashboard de souscription</description>
|
||||
<from-outcome>souscriptionDashboardPage</from-outcome>
|
||||
<to-view-id>/pages/secure/souscription/dashboard.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'upgrade de souscription</description>
|
||||
<from-outcome>souscriptionUpgradePage</from-outcome>
|
||||
<to-view-id>/pages/secure/souscription/upgrade.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de changement de plan de souscription</description>
|
||||
<from-outcome>souscriptionChangePlanPage</from-outcome>
|
||||
<to-view-id>/pages/secure/souscription/change-plan.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de renouvellement de souscription</description>
|
||||
<from-outcome>souscriptionRenewPage</from-outcome>
|
||||
<to-view-id>/pages/secure/souscription/renew.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Super Admin -->
|
||||
<navigation-case>
|
||||
<description>Page de logs système (Super Admin)</description>
|
||||
<from-outcome>superAdminLogsPage</from-outcome>
|
||||
<to-view-id>/pages/super-admin/logs.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de création d'entité (Super Admin)</description>
|
||||
<from-outcome>entiteNouvellePage</from-outcome>
|
||||
<to-view-id>/pages/super-admin/entites/nouvelle.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de gestion des entités (Super Admin)</description>
|
||||
<from-outcome>entiteGestionPage</from-outcome>
|
||||
<to-view-id>/pages/super-admin/entites/gestion.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de rapports (Super Admin)</description>
|
||||
<from-outcome>superAdminRapportsPage</from-outcome>
|
||||
<to-view-id>/pages/super-admin/rapports.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de configuration (Super Admin)</description>
|
||||
<from-outcome>superAdminConfigurationPage</from-outcome>
|
||||
<to-view-id>/pages/super-admin/configuration.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'alertes (Super Admin)</description>
|
||||
<from-outcome>superAdminAlertesPage</from-outcome>
|
||||
<to-view-id>/pages/super-admin/alertes.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'activité (Super Admin)</description>
|
||||
<from-outcome>superAdminActivitePage</from-outcome>
|
||||
<to-view-id>/pages/super-admin/activite.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de détails d'entité</description>
|
||||
<from-outcome>entiteDetailsPage</from-outcome>
|
||||
<to-view-id>/pages/super-admin/entites/details.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de gestion des membres (Admin)</description>
|
||||
<from-outcome>adminMembresGestionPage</from-outcome>
|
||||
<to-view-id>/pages/admin/membres/gestion.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de configuration d'entité</description>
|
||||
<from-outcome>entiteConfigurationPage</from-outcome>
|
||||
<to-view-id>/pages/super-admin/entites/configuration.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de rapports d'entité</description>
|
||||
<from-outcome>entiteRapportsPage</from-outcome>
|
||||
<to-view-id>/pages/super-admin/entites/rapports.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Demandes d'aide -->
|
||||
<navigation-case>
|
||||
<description>Page d'historique des demandes d'aide</description>
|
||||
<from-outcome>demandesHistoriquePage</from-outcome>
|
||||
<to-view-id>/pages/admin/demandes/historique.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Formulaires -->
|
||||
<navigation-case>
|
||||
<description>Page de checkout de souscription</description>
|
||||
<from-outcome>souscriptionCheckoutPage</from-outcome>
|
||||
<to-view-id>/pages/secure/souscription/checkout.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de détails de formulaire</description>
|
||||
<from-outcome>formulaireDetailsPage</from-outcome>
|
||||
<to-view-id>/pages/public/formulaires/details.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Documents -->
|
||||
<navigation-case>
|
||||
<description>Page d'historique des versions de documents</description>
|
||||
<from-outcome>documentsVersionsPage</from-outcome>
|
||||
<to-view-id>/pages/admin/documents/versions.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Membre -->
|
||||
<navigation-case>
|
||||
<description>Page d'événement (Membre)</description>
|
||||
<from-outcome>membreEvenementPage</from-outcome>
|
||||
<to-view-id>/pages/membre/evenement.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de cotisations (Membre)</description>
|
||||
<from-outcome>membreCotisationsPage</from-outcome>
|
||||
<to-view-id>/pages/membre/cotisations.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'historique des cotisations (Membre)</description>
|
||||
<from-outcome>membreHistoriqueCotisationsPage</from-outcome>
|
||||
<to-view-id>/pages/membre/historique-cotisations.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<!-- Autres -->
|
||||
<navigation-case>
|
||||
<description>Page de profil</description>
|
||||
<from-outcome>profilePage</from-outcome>
|
||||
<to-view-id>/pages/secure/profile.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page d'accès refusé</description>
|
||||
<from-outcome>accessDeniedPage</from-outcome>
|
||||
<to-view-id>/pages/secure/access-denied.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de statistiques</description>
|
||||
<from-outcome>statsPage</from-outcome>
|
||||
<to-view-id>/pages/secure/stats.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
<navigation-case>
|
||||
<description>Page de rapports</description>
|
||||
<from-outcome>reportsPage</from-outcome>
|
||||
<to-view-id>/pages/secure/reports.xhtml</to-view-id>
|
||||
<redirect />
|
||||
</navigation-case>
|
||||
|
||||
</navigation-rule>
|
||||
</faces-config>
|
||||
4257
src/main/resources/META-INF/resources/css/layout-dark.css
Normal file
4257
src/main/resources/META-INF/resources/css/layout-dark.css
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
$primaryColor:lighten(#2170E7, 5%);
|
||||
$primaryTextColor:#ffffff;
|
||||
|
||||
@import '../../sass/variables/layout/_layout_dark';
|
||||
@import '../../sass/layout/_layout';
|
||||
4257
src/main/resources/META-INF/resources/css/layout-light.css
Normal file
4257
src/main/resources/META-INF/resources/css/layout-light.css
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
$primaryColor:#2170E7;
|
||||
$primaryTextColor:#ffffff;
|
||||
|
||||
@import '../../sass/variables/layout/_layout_light';
|
||||
@import '../../sass/layout/_layout';
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user