Clean project: remove test files, debug logs, and add documentation
This commit is contained in:
@@ -2,31 +2,30 @@ package dev.lions.unionflow.server.api.dto.analytics;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.TypeMetrique;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.PeriodeAnalyse;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.TypeMetrique;
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Digits;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.Builder;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* DTO pour les données analytics UnionFlow
|
||||
*
|
||||
* Représente une donnée analytique avec sa valeur, sa métrique associée,
|
||||
* sa période d'analyse et ses métadonnées.
|
||||
*
|
||||
*
|
||||
* <p>Représente une donnée analytique avec sa valeur, sa métrique associée, sa période d'analyse et
|
||||
* ses métadonnées.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -37,225 +36,224 @@ import java.util.UUID;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class AnalyticsDataDTO extends BaseDTO {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Type de métrique analysée */
|
||||
@NotNull(message = "Le type de métrique est obligatoire")
|
||||
private TypeMetrique typeMetrique;
|
||||
|
||||
/** Période d'analyse */
|
||||
@NotNull(message = "La période d'analyse est obligatoire")
|
||||
private PeriodeAnalyse periodeAnalyse;
|
||||
|
||||
/** Valeur numérique de la métrique */
|
||||
@NotNull(message = "La valeur est obligatoire")
|
||||
@DecimalMin(value = "0.0", message = "La valeur doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur invalide")
|
||||
private BigDecimal valeur;
|
||||
|
||||
/** Valeur précédente pour comparaison */
|
||||
@DecimalMin(value = "0.0", message = "La valeur précédente doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur précédente invalide")
|
||||
private BigDecimal valeurPrecedente;
|
||||
|
||||
/** Pourcentage d'évolution par rapport à la période précédente */
|
||||
@Digits(integer = 6, fraction = 2, message = "Format de pourcentage d'évolution invalide")
|
||||
private BigDecimal pourcentageEvolution;
|
||||
|
||||
/** Date de début de la période analysée */
|
||||
@NotNull(message = "La date de début est obligatoire")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDebut;
|
||||
|
||||
/** Date de fin de la période analysée */
|
||||
@NotNull(message = "La date de fin est obligatoire")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateFin;
|
||||
|
||||
/** Date de calcul de la métrique */
|
||||
@NotNull(message = "La date de calcul est obligatoire")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateCalcul;
|
||||
|
||||
/** Identifiant de l'organisation (optionnel pour filtrage) */
|
||||
private UUID organisationId;
|
||||
|
||||
/** Nom de l'organisation */
|
||||
@Size(max = 200, message = "Le nom de l'organisation ne peut pas dépasser 200 caractères")
|
||||
private String nomOrganisation;
|
||||
|
||||
/** Identifiant de l'utilisateur qui a demandé le calcul */
|
||||
private UUID utilisateurId;
|
||||
|
||||
/** Nom de l'utilisateur qui a demandé le calcul */
|
||||
@Size(max = 200, message = "Le nom de l'utilisateur ne peut pas dépasser 200 caractères")
|
||||
private String nomUtilisateur;
|
||||
|
||||
/** Libellé personnalisé de la métrique */
|
||||
@Size(max = 300, message = "Le libellé personnalisé ne peut pas dépasser 300 caractères")
|
||||
private String libellePersonnalise;
|
||||
|
||||
/** Description ou commentaire sur la métrique */
|
||||
@Size(max = 1000, message = "La description ne peut pas dépasser 1000 caractères")
|
||||
private String description;
|
||||
|
||||
/** Données détaillées pour les graphiques (format JSON) */
|
||||
@Size(max = 10000, message = "Les données détaillées ne peuvent pas dépasser 10000 caractères")
|
||||
private String donneesDetaillees;
|
||||
|
||||
/** Configuration du graphique (couleurs, type, etc.) */
|
||||
@Size(max = 2000, message = "La configuration graphique ne peut pas dépasser 2000 caractères")
|
||||
private String configurationGraphique;
|
||||
|
||||
/** Métadonnées additionnelles */
|
||||
private Map<String, Object> metadonnees;
|
||||
|
||||
/** Indicateur de fiabilité des données (0-100) */
|
||||
@DecimalMin(value = "0.0", message = "L'indicateur de fiabilité doit être positif")
|
||||
@DecimalMax(value = "100.0", message = "L'indicateur de fiabilité ne peut pas dépasser 100")
|
||||
@Digits(integer = 3, fraction = 1, message = "Format d'indicateur de fiabilité invalide")
|
||||
private BigDecimal indicateurFiabilite;
|
||||
|
||||
/** Nombre d'éléments analysés pour calculer cette métrique */
|
||||
@DecimalMin(value = "0", message = "Le nombre d'éléments doit être positif")
|
||||
private Integer nombreElementsAnalyses;
|
||||
|
||||
/** Temps de calcul en millisecondes */
|
||||
@DecimalMin(value = "0", message = "Le temps de calcul doit être positif")
|
||||
private Long tempsCalculMs;
|
||||
|
||||
/** Indicateur si la métrique est en temps réel */
|
||||
@Builder.Default
|
||||
private Boolean tempsReel = false;
|
||||
|
||||
/** Indicateur si la métrique nécessite une mise à jour */
|
||||
@Builder.Default
|
||||
private Boolean necessiteMiseAJour = false;
|
||||
|
||||
/** Niveau de priorité de la métrique (1=faible, 5=critique) */
|
||||
@DecimalMin(value = "1", message = "Le niveau de priorité minimum est 1")
|
||||
@DecimalMax(value = "5", message = "Le niveau de priorité maximum est 5")
|
||||
private Integer niveauPriorite;
|
||||
|
||||
/** Tags pour catégoriser la métrique */
|
||||
private List<String> tags;
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Retourne le libellé à afficher (personnalisé ou par défaut)
|
||||
*
|
||||
* @return Le libellé à afficher
|
||||
*/
|
||||
public String getLibelleAffichage() {
|
||||
return libellePersonnalise != null && !libellePersonnalise.trim().isEmpty()
|
||||
? libellePersonnalise
|
||||
: typeMetrique.getLibelle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'unité de mesure de la métrique
|
||||
*
|
||||
* @return L'unité de mesure
|
||||
*/
|
||||
public String getUnite() {
|
||||
return typeMetrique.getUnite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône de la métrique
|
||||
*
|
||||
* @return L'icône Material Design
|
||||
*/
|
||||
public String getIcone() {
|
||||
return typeMetrique.getIcone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur de la métrique
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return typeMetrique.getCouleur();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique a évolué positivement
|
||||
*
|
||||
* @return true si l'évolution est positive
|
||||
*/
|
||||
public boolean hasEvolutionPositive() {
|
||||
return pourcentageEvolution != null && pourcentageEvolution.compareTo(BigDecimal.ZERO) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique a évolué négativement
|
||||
*
|
||||
* @return true si l'évolution est négative
|
||||
*/
|
||||
public boolean hasEvolutionNegative() {
|
||||
return pourcentageEvolution != null && pourcentageEvolution.compareTo(BigDecimal.ZERO) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique est stable (pas d'évolution)
|
||||
*
|
||||
* @return true si l'évolution est nulle
|
||||
*/
|
||||
public boolean isStable() {
|
||||
return pourcentageEvolution != null && pourcentageEvolution.compareTo(BigDecimal.ZERO) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la tendance sous forme de texte
|
||||
*
|
||||
* @return "hausse", "baisse" ou "stable"
|
||||
*/
|
||||
public String getTendance() {
|
||||
if (hasEvolutionPositive()) return "hausse";
|
||||
if (hasEvolutionNegative()) return "baisse";
|
||||
return "stable";
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si les données sont fiables (indicateur > 80)
|
||||
*
|
||||
* @return true si les données sont considérées comme fiables
|
||||
*/
|
||||
public boolean isDonneesFiables() {
|
||||
return indicateurFiabilite != null &&
|
||||
indicateurFiabilite.compareTo(new BigDecimal("80.0")) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique est critique (priorité >= 4)
|
||||
*
|
||||
* @return true si la métrique est critique
|
||||
*/
|
||||
public boolean isCritique() {
|
||||
return niveauPriorite != null && niveauPriorite >= 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec les champs essentiels
|
||||
*
|
||||
* @param typeMetrique Le type de métrique
|
||||
* @param periodeAnalyse La période d'analyse
|
||||
* @param valeur La valeur de la métrique
|
||||
*/
|
||||
public AnalyticsDataDTO(TypeMetrique typeMetrique, PeriodeAnalyse periodeAnalyse, BigDecimal valeur) {
|
||||
super();
|
||||
this.typeMetrique = typeMetrique;
|
||||
this.periodeAnalyse = periodeAnalyse;
|
||||
this.valeur = valeur;
|
||||
this.dateCalcul = LocalDateTime.now();
|
||||
this.dateDebut = periodeAnalyse.getDateDebut();
|
||||
this.dateFin = periodeAnalyse.getDateFin();
|
||||
this.tempsReel = false;
|
||||
this.necessiteMiseAJour = false;
|
||||
this.niveauPriorite = 3; // Priorité normale par défaut
|
||||
this.indicateurFiabilite = new BigDecimal("95.0"); // Fiabilité élevée par défaut
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Type de métrique analysée */
|
||||
@NotNull(message = "Le type de métrique est obligatoire")
|
||||
private TypeMetrique typeMetrique;
|
||||
|
||||
/** Période d'analyse */
|
||||
@NotNull(message = "La période d'analyse est obligatoire")
|
||||
private PeriodeAnalyse periodeAnalyse;
|
||||
|
||||
/** Valeur numérique de la métrique */
|
||||
@NotNull(message = "La valeur est obligatoire")
|
||||
@DecimalMin(value = "0.0", message = "La valeur doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur invalide")
|
||||
private BigDecimal valeur;
|
||||
|
||||
/** Valeur précédente pour comparaison */
|
||||
@DecimalMin(value = "0.0", message = "La valeur précédente doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur précédente invalide")
|
||||
private BigDecimal valeurPrecedente;
|
||||
|
||||
/** Pourcentage d'évolution par rapport à la période précédente */
|
||||
@Digits(integer = 6, fraction = 2, message = "Format de pourcentage d'évolution invalide")
|
||||
private BigDecimal pourcentageEvolution;
|
||||
|
||||
/** Date de début de la période analysée */
|
||||
@NotNull(message = "La date de début est obligatoire")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDebut;
|
||||
|
||||
/** Date de fin de la période analysée */
|
||||
@NotNull(message = "La date de fin est obligatoire")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateFin;
|
||||
|
||||
/** Date de calcul de la métrique */
|
||||
@NotNull(message = "La date de calcul est obligatoire")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateCalcul;
|
||||
|
||||
/** Identifiant de l'organisation (optionnel pour filtrage) */
|
||||
private UUID organisationId;
|
||||
|
||||
/** Nom de l'organisation */
|
||||
@Size(max = 200, message = "Le nom de l'organisation ne peut pas dépasser 200 caractères")
|
||||
private String nomOrganisation;
|
||||
|
||||
/** Identifiant de l'utilisateur qui a demandé le calcul */
|
||||
private UUID utilisateurId;
|
||||
|
||||
/** Nom de l'utilisateur qui a demandé le calcul */
|
||||
@Size(max = 200, message = "Le nom de l'utilisateur ne peut pas dépasser 200 caractères")
|
||||
private String nomUtilisateur;
|
||||
|
||||
/** Libellé personnalisé de la métrique */
|
||||
@Size(max = 300, message = "Le libellé personnalisé ne peut pas dépasser 300 caractères")
|
||||
private String libellePersonnalise;
|
||||
|
||||
/** Description ou commentaire sur la métrique */
|
||||
@Size(max = 1000, message = "La description ne peut pas dépasser 1000 caractères")
|
||||
private String description;
|
||||
|
||||
/** Données détaillées pour les graphiques (format JSON) */
|
||||
@Size(max = 10000, message = "Les données détaillées ne peuvent pas dépasser 10000 caractères")
|
||||
private String donneesDetaillees;
|
||||
|
||||
/** Configuration du graphique (couleurs, type, etc.) */
|
||||
@Size(max = 2000, message = "La configuration graphique ne peut pas dépasser 2000 caractères")
|
||||
private String configurationGraphique;
|
||||
|
||||
/** Métadonnées additionnelles */
|
||||
private Map<String, Object> metadonnees;
|
||||
|
||||
/** Indicateur de fiabilité des données (0-100) */
|
||||
@DecimalMin(value = "0.0", message = "L'indicateur de fiabilité doit être positif")
|
||||
@DecimalMax(value = "100.0", message = "L'indicateur de fiabilité ne peut pas dépasser 100")
|
||||
@Digits(integer = 3, fraction = 1, message = "Format d'indicateur de fiabilité invalide")
|
||||
private BigDecimal indicateurFiabilite;
|
||||
|
||||
/** Nombre d'éléments analysés pour calculer cette métrique */
|
||||
@DecimalMin(value = "0", message = "Le nombre d'éléments doit être positif")
|
||||
private Integer nombreElementsAnalyses;
|
||||
|
||||
/** Temps de calcul en millisecondes */
|
||||
@DecimalMin(value = "0", message = "Le temps de calcul doit être positif")
|
||||
private Long tempsCalculMs;
|
||||
|
||||
/** Indicateur si la métrique est en temps réel */
|
||||
@Builder.Default private Boolean tempsReel = false;
|
||||
|
||||
/** Indicateur si la métrique nécessite une mise à jour */
|
||||
@Builder.Default private Boolean necessiteMiseAJour = false;
|
||||
|
||||
/** Niveau de priorité de la métrique (1=faible, 5=critique) */
|
||||
@DecimalMin(value = "1", message = "Le niveau de priorité minimum est 1")
|
||||
@DecimalMax(value = "5", message = "Le niveau de priorité maximum est 5")
|
||||
private Integer niveauPriorite;
|
||||
|
||||
/** Tags pour catégoriser la métrique */
|
||||
private List<String> tags;
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Retourne le libellé à afficher (personnalisé ou par défaut)
|
||||
*
|
||||
* @return Le libellé à afficher
|
||||
*/
|
||||
public String getLibelleAffichage() {
|
||||
return libellePersonnalise != null && !libellePersonnalise.trim().isEmpty()
|
||||
? libellePersonnalise
|
||||
: typeMetrique.getLibelle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'unité de mesure de la métrique
|
||||
*
|
||||
* @return L'unité de mesure
|
||||
*/
|
||||
public String getUnite() {
|
||||
return typeMetrique.getUnite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône de la métrique
|
||||
*
|
||||
* @return L'icône Material Design
|
||||
*/
|
||||
public String getIcone() {
|
||||
return typeMetrique.getIcone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur de la métrique
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return typeMetrique.getCouleur();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique a évolué positivement
|
||||
*
|
||||
* @return true si l'évolution est positive
|
||||
*/
|
||||
public boolean hasEvolutionPositive() {
|
||||
return pourcentageEvolution != null && pourcentageEvolution.compareTo(BigDecimal.ZERO) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique a évolué négativement
|
||||
*
|
||||
* @return true si l'évolution est négative
|
||||
*/
|
||||
public boolean hasEvolutionNegative() {
|
||||
return pourcentageEvolution != null && pourcentageEvolution.compareTo(BigDecimal.ZERO) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique est stable (pas d'évolution)
|
||||
*
|
||||
* @return true si l'évolution est nulle
|
||||
*/
|
||||
public boolean isStable() {
|
||||
return pourcentageEvolution != null && pourcentageEvolution.compareTo(BigDecimal.ZERO) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la tendance sous forme de texte
|
||||
*
|
||||
* @return "hausse", "baisse" ou "stable"
|
||||
*/
|
||||
public String getTendance() {
|
||||
if (hasEvolutionPositive()) return "hausse";
|
||||
if (hasEvolutionNegative()) return "baisse";
|
||||
return "stable";
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si les données sont fiables (indicateur > 80)
|
||||
*
|
||||
* @return true si les données sont considérées comme fiables
|
||||
*/
|
||||
public boolean isDonneesFiables() {
|
||||
return indicateurFiabilite != null
|
||||
&& indicateurFiabilite.compareTo(new BigDecimal("80.0")) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique est critique (priorité >= 4)
|
||||
*
|
||||
* @return true si la métrique est critique
|
||||
*/
|
||||
public boolean isCritique() {
|
||||
return niveauPriorite != null && niveauPriorite >= 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec les champs essentiels
|
||||
*
|
||||
* @param typeMetrique Le type de métrique
|
||||
* @param periodeAnalyse La période d'analyse
|
||||
* @param valeur La valeur de la métrique
|
||||
*/
|
||||
public AnalyticsDataDTO(
|
||||
TypeMetrique typeMetrique, PeriodeAnalyse periodeAnalyse, BigDecimal valeur) {
|
||||
super();
|
||||
this.typeMetrique = typeMetrique;
|
||||
this.periodeAnalyse = periodeAnalyse;
|
||||
this.valeur = valeur;
|
||||
this.dateCalcul = LocalDateTime.now();
|
||||
this.dateDebut = periodeAnalyse.getDateDebut();
|
||||
this.dateFin = periodeAnalyse.getDateFin();
|
||||
this.tempsReel = false;
|
||||
this.necessiteMiseAJour = false;
|
||||
this.niveauPriorite = 3; // Priorité normale par défaut
|
||||
this.indicateurFiabilite = new BigDecimal("95.0"); // Fiabilité élevée par défaut
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,29 +2,28 @@ package dev.lions.unionflow.server.api.dto.analytics;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.TypeMetrique;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.PeriodeAnalyse;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.TypeMetrique;
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.Builder;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* DTO pour les widgets de tableau de bord analytics UnionFlow
|
||||
*
|
||||
* Représente un widget personnalisable affiché sur le tableau de bord
|
||||
* avec sa configuration, sa position et ses données.
|
||||
*
|
||||
*
|
||||
* <p>Représente un widget personnalisable affiché sur le tableau de bord avec sa configuration, sa
|
||||
* position et ses données.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -35,309 +34,305 @@ import java.util.UUID;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class DashboardWidgetDTO extends BaseDTO {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Titre du widget */
|
||||
@NotBlank(message = "Le titre du widget est obligatoire")
|
||||
@Size(min = 3, max = 200, message = "Le titre du widget doit contenir entre 3 et 200 caractères")
|
||||
private String titre;
|
||||
|
||||
/** Description du widget */
|
||||
@Size(max = 500, message = "La description ne peut pas dépasser 500 caractères")
|
||||
private String description;
|
||||
|
||||
/** Type de widget (kpi, chart, table, gauge, progress, text) */
|
||||
@NotBlank(message = "Le type de widget est obligatoire")
|
||||
@Size(max = 50, message = "Le type de widget ne peut pas dépasser 50 caractères")
|
||||
private String typeWidget;
|
||||
|
||||
/** Type de métrique affiché */
|
||||
private TypeMetrique typeMetrique;
|
||||
|
||||
/** Période d'analyse */
|
||||
private PeriodeAnalyse periodeAnalyse;
|
||||
|
||||
/** Identifiant de l'organisation (optionnel pour filtrage) */
|
||||
private UUID organisationId;
|
||||
|
||||
/** Nom de l'organisation */
|
||||
@Size(max = 200, message = "Le nom de l'organisation ne peut pas dépasser 200 caractères")
|
||||
private String nomOrganisation;
|
||||
|
||||
/** Identifiant de l'utilisateur propriétaire */
|
||||
@NotNull(message = "L'identifiant de l'utilisateur propriétaire est obligatoire")
|
||||
private UUID utilisateurProprietaireId;
|
||||
|
||||
/** Nom de l'utilisateur propriétaire */
|
||||
@Size(max = 200, message = "Le nom de l'utilisateur propriétaire ne peut pas dépasser 200 caractères")
|
||||
private String nomUtilisateurProprietaire;
|
||||
|
||||
/** Position X du widget sur la grille */
|
||||
@NotNull(message = "La position X est obligatoire")
|
||||
@DecimalMin(value = "0", message = "La position X doit être positive ou nulle")
|
||||
private Integer positionX;
|
||||
|
||||
/** Position Y du widget sur la grille */
|
||||
@NotNull(message = "La position Y est obligatoire")
|
||||
@DecimalMin(value = "0", message = "La position Y doit être positive ou nulle")
|
||||
private Integer positionY;
|
||||
|
||||
/** Largeur du widget (en unités de grille) */
|
||||
@NotNull(message = "La largeur est obligatoire")
|
||||
@DecimalMin(value = "1", message = "La largeur minimum est 1")
|
||||
@DecimalMax(value = "12", message = "La largeur maximum est 12")
|
||||
private Integer largeur;
|
||||
|
||||
/** Hauteur du widget (en unités de grille) */
|
||||
@NotNull(message = "La hauteur est obligatoire")
|
||||
@DecimalMin(value = "1", message = "La hauteur minimum est 1")
|
||||
@DecimalMax(value = "12", message = "La hauteur maximum est 12")
|
||||
private Integer hauteur;
|
||||
|
||||
/** Ordre d'affichage (z-index) */
|
||||
@DecimalMin(value = "0", message = "L'ordre d'affichage doit être positif ou nul")
|
||||
@Builder.Default
|
||||
private Integer ordreAffichage = 0;
|
||||
|
||||
/** Configuration visuelle du widget */
|
||||
@Size(max = 5000, message = "La configuration visuelle ne peut pas dépasser 5000 caractères")
|
||||
private String configurationVisuelle;
|
||||
|
||||
/** Couleur principale du widget */
|
||||
@Size(max = 7, message = "La couleur doit être au format #RRGGBB")
|
||||
private String couleurPrincipale;
|
||||
|
||||
/** Couleur secondaire du widget */
|
||||
@Size(max = 7, message = "La couleur secondaire doit être au format #RRGGBB")
|
||||
private String couleurSecondaire;
|
||||
|
||||
/** Icône du widget */
|
||||
@Size(max = 50, message = "L'icône ne peut pas dépasser 50 caractères")
|
||||
private String icone;
|
||||
|
||||
/** Indicateur si le widget est visible */
|
||||
@Builder.Default
|
||||
private Boolean visible = true;
|
||||
|
||||
/** Indicateur si le widget est redimensionnable */
|
||||
@Builder.Default
|
||||
private Boolean redimensionnable = true;
|
||||
|
||||
/** Indicateur si le widget est déplaçable */
|
||||
@Builder.Default
|
||||
private Boolean deplacable = true;
|
||||
|
||||
/** Indicateur si le widget peut être supprimé */
|
||||
@Builder.Default
|
||||
private Boolean supprimable = true;
|
||||
|
||||
/** Indicateur si le widget se met à jour automatiquement */
|
||||
@Builder.Default
|
||||
private Boolean miseAJourAutomatique = true;
|
||||
|
||||
/** Fréquence de mise à jour en secondes */
|
||||
@DecimalMin(value = "30", message = "La fréquence minimum est 30 secondes")
|
||||
@Builder.Default
|
||||
private Integer frequenceMiseAJourSecondes = 300; // 5 minutes par défaut
|
||||
|
||||
/** Date de dernière mise à jour des données */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDerniereMiseAJour;
|
||||
|
||||
/** Prochaine mise à jour programmée */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime prochaineMiseAJour;
|
||||
|
||||
/** Données du widget (format JSON) */
|
||||
@Size(max = 50000, message = "Les données du widget ne peuvent pas dépasser 50000 caractères")
|
||||
private String donneesWidget;
|
||||
|
||||
/** Configuration des filtres */
|
||||
private Map<String, Object> configurationFiltres;
|
||||
|
||||
/** Configuration des alertes */
|
||||
private Map<String, Object> configurationAlertes;
|
||||
|
||||
/** Seuil d'alerte bas */
|
||||
private Double seuilAlerteBas;
|
||||
|
||||
/** Seuil d'alerte haut */
|
||||
private Double seuilAlerteHaut;
|
||||
|
||||
/** Indicateur si une alerte est active */
|
||||
@Builder.Default
|
||||
private Boolean alerteActive = false;
|
||||
|
||||
/** Message d'alerte actuel */
|
||||
@Size(max = 500, message = "Le message d'alerte ne peut pas dépasser 500 caractères")
|
||||
private String messageAlerte;
|
||||
|
||||
/** Type d'alerte (info, warning, error, success) */
|
||||
@Size(max = 20, message = "Le type d'alerte ne peut pas dépasser 20 caractères")
|
||||
private String typeAlerte;
|
||||
|
||||
/** Permissions d'accès au widget */
|
||||
@Size(max = 1000, message = "Les permissions ne peuvent pas dépasser 1000 caractères")
|
||||
private String permissions;
|
||||
|
||||
/** Rôles autorisés à voir le widget */
|
||||
@Size(max = 500, message = "Les rôles autorisés ne peuvent pas dépasser 500 caractères")
|
||||
private String rolesAutorises;
|
||||
|
||||
/** Template personnalisé du widget */
|
||||
@Size(max = 10000, message = "Le template personnalisé ne peut pas dépasser 10000 caractères")
|
||||
private String templatePersonnalise;
|
||||
|
||||
/** CSS personnalisé du widget */
|
||||
@Size(max = 5000, message = "Le CSS personnalisé ne peut pas dépasser 5000 caractères")
|
||||
private String cssPersonnalise;
|
||||
|
||||
/** JavaScript personnalisé du widget */
|
||||
@Size(max = 10000, message = "Le JavaScript personnalisé ne peut pas dépasser 10000 caractères")
|
||||
private String javascriptPersonnalise;
|
||||
|
||||
/** Métadonnées additionnelles */
|
||||
private Map<String, Object> metadonnees;
|
||||
|
||||
/** Nombre de vues du widget */
|
||||
@DecimalMin(value = "0", message = "Le nombre de vues doit être positif")
|
||||
@Builder.Default
|
||||
private Long nombreVues = 0L;
|
||||
|
||||
/** Nombre d'interactions avec le widget */
|
||||
@DecimalMin(value = "0", message = "Le nombre d'interactions doit être positif")
|
||||
@Builder.Default
|
||||
private Long nombreInteractions = 0L;
|
||||
|
||||
/** Temps moyen passé sur le widget (en secondes) */
|
||||
@DecimalMin(value = "0", message = "Le temps moyen doit être positif")
|
||||
private Integer tempsMoyenSecondes;
|
||||
|
||||
/** Taux d'erreur du widget (en pourcentage) */
|
||||
@DecimalMin(value = "0.0", message = "Le taux d'erreur doit être positif")
|
||||
@DecimalMax(value = "100.0", message = "Le taux d'erreur ne peut pas dépasser 100%")
|
||||
@Builder.Default
|
||||
private Double tauxErreur = 0.0;
|
||||
|
||||
/** Date de dernière erreur */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDerniereErreur;
|
||||
|
||||
/** Message de dernière erreur */
|
||||
@Size(max = 1000, message = "Le message d'erreur ne peut pas dépasser 1000 caractères")
|
||||
private String messageDerniereErreur;
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Retourne le libellé de la métrique si définie
|
||||
*
|
||||
* @return Le libellé de la métrique ou null
|
||||
*/
|
||||
public String getLibelleMetrique() {
|
||||
return typeMetrique != null ? typeMetrique.getLibelle() : null;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Titre du widget */
|
||||
@NotBlank(message = "Le titre du widget est obligatoire")
|
||||
@Size(min = 3, max = 200, message = "Le titre du widget doit contenir entre 3 et 200 caractères")
|
||||
private String titre;
|
||||
|
||||
/** Description du widget */
|
||||
@Size(max = 500, message = "La description ne peut pas dépasser 500 caractères")
|
||||
private String description;
|
||||
|
||||
/** Type de widget (kpi, chart, table, gauge, progress, text) */
|
||||
@NotBlank(message = "Le type de widget est obligatoire")
|
||||
@Size(max = 50, message = "Le type de widget ne peut pas dépasser 50 caractères")
|
||||
private String typeWidget;
|
||||
|
||||
/** Type de métrique affiché */
|
||||
private TypeMetrique typeMetrique;
|
||||
|
||||
/** Période d'analyse */
|
||||
private PeriodeAnalyse periodeAnalyse;
|
||||
|
||||
/** Identifiant de l'organisation (optionnel pour filtrage) */
|
||||
private UUID organisationId;
|
||||
|
||||
/** Nom de l'organisation */
|
||||
@Size(max = 200, message = "Le nom de l'organisation ne peut pas dépasser 200 caractères")
|
||||
private String nomOrganisation;
|
||||
|
||||
/** Identifiant de l'utilisateur propriétaire */
|
||||
@NotNull(message = "L'identifiant de l'utilisateur propriétaire est obligatoire")
|
||||
private UUID utilisateurProprietaireId;
|
||||
|
||||
/** Nom de l'utilisateur propriétaire */
|
||||
@Size(
|
||||
max = 200,
|
||||
message = "Le nom de l'utilisateur propriétaire ne peut pas dépasser 200 caractères")
|
||||
private String nomUtilisateurProprietaire;
|
||||
|
||||
/** Position X du widget sur la grille */
|
||||
@NotNull(message = "La position X est obligatoire")
|
||||
@DecimalMin(value = "0", message = "La position X doit être positive ou nulle")
|
||||
private Integer positionX;
|
||||
|
||||
/** Position Y du widget sur la grille */
|
||||
@NotNull(message = "La position Y est obligatoire")
|
||||
@DecimalMin(value = "0", message = "La position Y doit être positive ou nulle")
|
||||
private Integer positionY;
|
||||
|
||||
/** Largeur du widget (en unités de grille) */
|
||||
@NotNull(message = "La largeur est obligatoire")
|
||||
@DecimalMin(value = "1", message = "La largeur minimum est 1")
|
||||
@DecimalMax(value = "12", message = "La largeur maximum est 12")
|
||||
private Integer largeur;
|
||||
|
||||
/** Hauteur du widget (en unités de grille) */
|
||||
@NotNull(message = "La hauteur est obligatoire")
|
||||
@DecimalMin(value = "1", message = "La hauteur minimum est 1")
|
||||
@DecimalMax(value = "12", message = "La hauteur maximum est 12")
|
||||
private Integer hauteur;
|
||||
|
||||
/** Ordre d'affichage (z-index) */
|
||||
@DecimalMin(value = "0", message = "L'ordre d'affichage doit être positif ou nul")
|
||||
@Builder.Default
|
||||
private Integer ordreAffichage = 0;
|
||||
|
||||
/** Configuration visuelle du widget */
|
||||
@Size(max = 5000, message = "La configuration visuelle ne peut pas dépasser 5000 caractères")
|
||||
private String configurationVisuelle;
|
||||
|
||||
/** Couleur principale du widget */
|
||||
@Size(max = 7, message = "La couleur doit être au format #RRGGBB")
|
||||
private String couleurPrincipale;
|
||||
|
||||
/** Couleur secondaire du widget */
|
||||
@Size(max = 7, message = "La couleur secondaire doit être au format #RRGGBB")
|
||||
private String couleurSecondaire;
|
||||
|
||||
/** Icône du widget */
|
||||
@Size(max = 50, message = "L'icône ne peut pas dépasser 50 caractères")
|
||||
private String icone;
|
||||
|
||||
/** Indicateur si le widget est visible */
|
||||
@Builder.Default private Boolean visible = true;
|
||||
|
||||
/** Indicateur si le widget est redimensionnable */
|
||||
@Builder.Default private Boolean redimensionnable = true;
|
||||
|
||||
/** Indicateur si le widget est déplaçable */
|
||||
@Builder.Default private Boolean deplacable = true;
|
||||
|
||||
/** Indicateur si le widget peut être supprimé */
|
||||
@Builder.Default private Boolean supprimable = true;
|
||||
|
||||
/** Indicateur si le widget se met à jour automatiquement */
|
||||
@Builder.Default private Boolean miseAJourAutomatique = true;
|
||||
|
||||
/** Fréquence de mise à jour en secondes */
|
||||
@DecimalMin(value = "30", message = "La fréquence minimum est 30 secondes")
|
||||
@Builder.Default
|
||||
private Integer frequenceMiseAJourSecondes = 300; // 5 minutes par défaut
|
||||
|
||||
/** Date de dernière mise à jour des données */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDerniereMiseAJour;
|
||||
|
||||
/** Prochaine mise à jour programmée */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime prochaineMiseAJour;
|
||||
|
||||
/** Données du widget (format JSON) */
|
||||
@Size(max = 50000, message = "Les données du widget ne peuvent pas dépasser 50000 caractères")
|
||||
private String donneesWidget;
|
||||
|
||||
/** Configuration des filtres */
|
||||
private Map<String, Object> configurationFiltres;
|
||||
|
||||
/** Configuration des alertes */
|
||||
private Map<String, Object> configurationAlertes;
|
||||
|
||||
/** Seuil d'alerte bas */
|
||||
private Double seuilAlerteBas;
|
||||
|
||||
/** Seuil d'alerte haut */
|
||||
private Double seuilAlerteHaut;
|
||||
|
||||
/** Indicateur si une alerte est active */
|
||||
@Builder.Default private Boolean alerteActive = false;
|
||||
|
||||
/** Message d'alerte actuel */
|
||||
@Size(max = 500, message = "Le message d'alerte ne peut pas dépasser 500 caractères")
|
||||
private String messageAlerte;
|
||||
|
||||
/** Type d'alerte (info, warning, error, success) */
|
||||
@Size(max = 20, message = "Le type d'alerte ne peut pas dépasser 20 caractères")
|
||||
private String typeAlerte;
|
||||
|
||||
/** Permissions d'accès au widget */
|
||||
@Size(max = 1000, message = "Les permissions ne peuvent pas dépasser 1000 caractères")
|
||||
private String permissions;
|
||||
|
||||
/** Rôles autorisés à voir le widget */
|
||||
@Size(max = 500, message = "Les rôles autorisés ne peuvent pas dépasser 500 caractères")
|
||||
private String rolesAutorises;
|
||||
|
||||
/** Template personnalisé du widget */
|
||||
@Size(max = 10000, message = "Le template personnalisé ne peut pas dépasser 10000 caractères")
|
||||
private String templatePersonnalise;
|
||||
|
||||
/** CSS personnalisé du widget */
|
||||
@Size(max = 5000, message = "Le CSS personnalisé ne peut pas dépasser 5000 caractères")
|
||||
private String cssPersonnalise;
|
||||
|
||||
/** JavaScript personnalisé du widget */
|
||||
@Size(max = 10000, message = "Le JavaScript personnalisé ne peut pas dépasser 10000 caractères")
|
||||
private String javascriptPersonnalise;
|
||||
|
||||
/** Métadonnées additionnelles */
|
||||
private Map<String, Object> metadonnees;
|
||||
|
||||
/** Nombre de vues du widget */
|
||||
@DecimalMin(value = "0", message = "Le nombre de vues doit être positif")
|
||||
@Builder.Default
|
||||
private Long nombreVues = 0L;
|
||||
|
||||
/** Nombre d'interactions avec le widget */
|
||||
@DecimalMin(value = "0", message = "Le nombre d'interactions doit être positif")
|
||||
@Builder.Default
|
||||
private Long nombreInteractions = 0L;
|
||||
|
||||
/** Temps moyen passé sur le widget (en secondes) */
|
||||
@DecimalMin(value = "0", message = "Le temps moyen doit être positif")
|
||||
private Integer tempsMoyenSecondes;
|
||||
|
||||
/** Taux d'erreur du widget (en pourcentage) */
|
||||
@DecimalMin(value = "0.0", message = "Le taux d'erreur doit être positif")
|
||||
@DecimalMax(value = "100.0", message = "Le taux d'erreur ne peut pas dépasser 100%")
|
||||
@Builder.Default
|
||||
private Double tauxErreur = 0.0;
|
||||
|
||||
/** Date de dernière erreur */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDerniereErreur;
|
||||
|
||||
/** Message de dernière erreur */
|
||||
@Size(max = 1000, message = "Le message d'erreur ne peut pas dépasser 1000 caractères")
|
||||
private String messageDerniereErreur;
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Retourne le libellé de la métrique si définie
|
||||
*
|
||||
* @return Le libellé de la métrique ou null
|
||||
*/
|
||||
public String getLibelleMetrique() {
|
||||
return typeMetrique != null ? typeMetrique.getLibelle() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'unité de mesure si métrique définie
|
||||
*
|
||||
* @return L'unité de mesure ou chaîne vide
|
||||
*/
|
||||
public String getUnite() {
|
||||
return typeMetrique != null ? typeMetrique.getUnite() : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône de la métrique ou l'icône personnalisée
|
||||
*
|
||||
* @return L'icône à afficher
|
||||
*/
|
||||
public String getIconeAffichage() {
|
||||
if (icone != null && !icone.trim().isEmpty()) {
|
||||
return icone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'unité de mesure si métrique définie
|
||||
*
|
||||
* @return L'unité de mesure ou chaîne vide
|
||||
*/
|
||||
public String getUnite() {
|
||||
return typeMetrique != null ? typeMetrique.getUnite() : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône de la métrique ou l'icône personnalisée
|
||||
*
|
||||
* @return L'icône à afficher
|
||||
*/
|
||||
public String getIconeAffichage() {
|
||||
if (icone != null && !icone.trim().isEmpty()) {
|
||||
return icone;
|
||||
}
|
||||
return typeMetrique != null ? typeMetrique.getIcone() : "dashboard";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur de la métrique ou la couleur personnalisée
|
||||
*
|
||||
* @return La couleur à utiliser
|
||||
*/
|
||||
public String getCouleurAffichage() {
|
||||
if (couleurPrincipale != null && !couleurPrincipale.trim().isEmpty()) {
|
||||
return couleurPrincipale;
|
||||
}
|
||||
return typeMetrique != null ? typeMetrique.getCouleur() : "#757575";
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le widget nécessite une mise à jour
|
||||
*
|
||||
* @return true si une mise à jour est nécessaire
|
||||
*/
|
||||
public boolean necessiteMiseAJour() {
|
||||
return miseAJourAutomatique && prochaineMiseAJour != null &&
|
||||
prochaineMiseAJour.isBefore(LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le widget est interactif
|
||||
*
|
||||
* @return true si le widget permet des interactions
|
||||
*/
|
||||
public boolean isInteractif() {
|
||||
return "chart".equals(typeWidget) || "table".equals(typeWidget) ||
|
||||
"gauge".equals(typeWidget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le widget affiche des données temps réel
|
||||
*
|
||||
* @return true si le widget est en temps réel
|
||||
*/
|
||||
public boolean isTempsReel() {
|
||||
return frequenceMiseAJourSecondes != null && frequenceMiseAJourSecondes <= 60;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la taille du widget (surface occupée)
|
||||
*
|
||||
* @return La surface en unités de grille
|
||||
*/
|
||||
public int getTailleWidget() {
|
||||
return largeur * hauteur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le widget est grand (surface > 6)
|
||||
*
|
||||
* @return true si le widget est considéré comme grand
|
||||
*/
|
||||
public boolean isWidgetGrand() {
|
||||
return getTailleWidget() > 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le widget a des erreurs récentes (< 24h)
|
||||
*
|
||||
* @return true si des erreurs récentes sont détectées
|
||||
*/
|
||||
public boolean hasErreursRecentes() {
|
||||
return dateDerniereErreur != null &&
|
||||
dateDerniereErreur.isAfter(LocalDateTime.now().minusHours(24));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le statut du widget
|
||||
*
|
||||
* @return "actif", "erreur", "inactif" ou "maintenance"
|
||||
*/
|
||||
public String getStatutWidget() {
|
||||
if (hasErreursRecentes()) return "erreur";
|
||||
if (!visible) return "inactif";
|
||||
if (tauxErreur > 10.0) return "maintenance";
|
||||
return "actif";
|
||||
return typeMetrique != null ? typeMetrique.getIcone() : "dashboard";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur de la métrique ou la couleur personnalisée
|
||||
*
|
||||
* @return La couleur à utiliser
|
||||
*/
|
||||
public String getCouleurAffichage() {
|
||||
if (couleurPrincipale != null && !couleurPrincipale.trim().isEmpty()) {
|
||||
return couleurPrincipale;
|
||||
}
|
||||
return typeMetrique != null ? typeMetrique.getCouleur() : "#757575";
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le widget nécessite une mise à jour
|
||||
*
|
||||
* @return true si une mise à jour est nécessaire
|
||||
*/
|
||||
public boolean necessiteMiseAJour() {
|
||||
return miseAJourAutomatique
|
||||
&& prochaineMiseAJour != null
|
||||
&& prochaineMiseAJour.isBefore(LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le widget est interactif
|
||||
*
|
||||
* @return true si le widget permet des interactions
|
||||
*/
|
||||
public boolean isInteractif() {
|
||||
return "chart".equals(typeWidget) || "table".equals(typeWidget) || "gauge".equals(typeWidget);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le widget affiche des données temps réel
|
||||
*
|
||||
* @return true si le widget est en temps réel
|
||||
*/
|
||||
public boolean isTempsReel() {
|
||||
return frequenceMiseAJourSecondes != null && frequenceMiseAJourSecondes <= 60;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la taille du widget (surface occupée)
|
||||
*
|
||||
* @return La surface en unités de grille
|
||||
*/
|
||||
public int getTailleWidget() {
|
||||
return largeur * hauteur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le widget est grand (surface > 6)
|
||||
*
|
||||
* @return true si le widget est considéré comme grand
|
||||
*/
|
||||
public boolean isWidgetGrand() {
|
||||
return getTailleWidget() > 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le widget a des erreurs récentes (< 24h)
|
||||
*
|
||||
* @return true si des erreurs récentes sont détectées
|
||||
*/
|
||||
public boolean hasErreursRecentes() {
|
||||
return dateDerniereErreur != null
|
||||
&& dateDerniereErreur.isAfter(LocalDateTime.now().minusHours(24));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le statut du widget
|
||||
*
|
||||
* @return "actif", "erreur", "inactif" ou "maintenance"
|
||||
*/
|
||||
public String getStatutWidget() {
|
||||
if (hasErreursRecentes()) return "erreur";
|
||||
if (!visible) return "inactif";
|
||||
if (tauxErreur > 10.0) return "maintenance";
|
||||
return "actif";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,30 +2,29 @@ package dev.lions.unionflow.server.api.dto.analytics;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.TypeMetrique;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.PeriodeAnalyse;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.TypeMetrique;
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Digits;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.Builder;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* DTO pour les tendances et évolutions des KPI UnionFlow
|
||||
*
|
||||
* Représente l'évolution d'un KPI dans le temps avec les points de données
|
||||
* historiques pour générer des graphiques de tendance.
|
||||
*
|
||||
*
|
||||
* <p>Représente l'évolution d'un KPI dans le temps avec les points de données historiques pour
|
||||
* générer des graphiques de tendance.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -36,280 +35,275 @@ import java.util.UUID;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class KPITrendDTO extends BaseDTO {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Type de métrique pour cette tendance */
|
||||
@NotNull(message = "Le type de métrique est obligatoire")
|
||||
private TypeMetrique typeMetrique;
|
||||
|
||||
/** Période d'analyse globale */
|
||||
@NotNull(message = "La période d'analyse est obligatoire")
|
||||
private PeriodeAnalyse periodeAnalyse;
|
||||
|
||||
/** Identifiant de l'organisation (optionnel) */
|
||||
private UUID organisationId;
|
||||
|
||||
/** Nom de l'organisation */
|
||||
@Size(max = 200, message = "Le nom de l'organisation ne peut pas dépasser 200 caractères")
|
||||
private String nomOrganisation;
|
||||
|
||||
/** Date de début de la période analysée */
|
||||
@NotNull(message = "La date de début est obligatoire")
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Type de métrique pour cette tendance */
|
||||
@NotNull(message = "Le type de métrique est obligatoire")
|
||||
private TypeMetrique typeMetrique;
|
||||
|
||||
/** Période d'analyse globale */
|
||||
@NotNull(message = "La période d'analyse est obligatoire")
|
||||
private PeriodeAnalyse periodeAnalyse;
|
||||
|
||||
/** Identifiant de l'organisation (optionnel) */
|
||||
private UUID organisationId;
|
||||
|
||||
/** Nom de l'organisation */
|
||||
@Size(max = 200, message = "Le nom de l'organisation ne peut pas dépasser 200 caractères")
|
||||
private String nomOrganisation;
|
||||
|
||||
/** Date de début de la période analysée */
|
||||
@NotNull(message = "La date de début est obligatoire")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDebut;
|
||||
|
||||
/** Date de fin de la période analysée */
|
||||
@NotNull(message = "La date de fin est obligatoire")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateFin;
|
||||
|
||||
/** Points de données pour la tendance */
|
||||
@NotNull(message = "Les points de données sont obligatoires")
|
||||
private List<PointDonneeDTO> pointsDonnees;
|
||||
|
||||
/** Valeur actuelle du KPI */
|
||||
@NotNull(message = "La valeur actuelle est obligatoire")
|
||||
@DecimalMin(value = "0.0", message = "La valeur actuelle doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur actuelle invalide")
|
||||
private BigDecimal valeurActuelle;
|
||||
|
||||
/** Valeur minimale sur la période */
|
||||
@DecimalMin(value = "0.0", message = "La valeur minimale doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur minimale invalide")
|
||||
private BigDecimal valeurMinimale;
|
||||
|
||||
/** Valeur maximale sur la période */
|
||||
@DecimalMin(value = "0.0", message = "La valeur maximale doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur maximale invalide")
|
||||
private BigDecimal valeurMaximale;
|
||||
|
||||
/** Valeur moyenne sur la période */
|
||||
@DecimalMin(value = "0.0", message = "La valeur moyenne doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur moyenne invalide")
|
||||
private BigDecimal valeurMoyenne;
|
||||
|
||||
/** Écart-type des valeurs */
|
||||
@DecimalMin(value = "0.0", message = "L'écart-type doit être positif ou nul")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format d'écart-type invalide")
|
||||
private BigDecimal ecartType;
|
||||
|
||||
/** Coefficient de variation (écart-type / moyenne) */
|
||||
@DecimalMin(value = "0.0", message = "Le coefficient de variation doit être positif ou nul")
|
||||
@Digits(integer = 6, fraction = 4, message = "Format de coefficient de variation invalide")
|
||||
private BigDecimal coefficientVariation;
|
||||
|
||||
/** Tendance générale (pente de la régression linéaire) */
|
||||
@Digits(integer = 10, fraction = 6, message = "Format de tendance invalide")
|
||||
private BigDecimal tendanceGenerale;
|
||||
|
||||
/** Coefficient de corrélation R² */
|
||||
@DecimalMin(value = "0.0", message = "Le coefficient de corrélation doit être positif ou nul")
|
||||
@DecimalMax(value = "1.0", message = "Le coefficient de corrélation ne peut pas dépasser 1")
|
||||
@Digits(integer = 1, fraction = 6, message = "Format de coefficient de corrélation invalide")
|
||||
private BigDecimal coefficientCorrelation;
|
||||
|
||||
/** Pourcentage d'évolution depuis le début de la période */
|
||||
@Digits(integer = 6, fraction = 2, message = "Format de pourcentage d'évolution invalide")
|
||||
private BigDecimal pourcentageEvolutionGlobale;
|
||||
|
||||
/** Prédiction pour la prochaine période */
|
||||
@DecimalMin(value = "0.0", message = "La prédiction doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de prédiction invalide")
|
||||
private BigDecimal predictionProchainePeriode;
|
||||
|
||||
/** Marge d'erreur de la prédiction (en pourcentage) */
|
||||
@DecimalMin(value = "0.0", message = "La marge d'erreur doit être positive ou nulle")
|
||||
@DecimalMax(value = "100.0", message = "La marge d'erreur ne peut pas dépasser 100%")
|
||||
@Digits(integer = 3, fraction = 2, message = "Format de marge d'erreur invalide")
|
||||
private BigDecimal margeErreurPrediction;
|
||||
|
||||
/** Seuil d'alerte bas */
|
||||
@DecimalMin(value = "0.0", message = "Le seuil d'alerte bas doit être positif ou nul")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de seuil d'alerte bas invalide")
|
||||
private BigDecimal seuilAlerteBas;
|
||||
|
||||
/** Seuil d'alerte haut */
|
||||
@DecimalMin(value = "0.0", message = "Le seuil d'alerte haut doit être positif ou nul")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de seuil d'alerte haut invalide")
|
||||
private BigDecimal seuilAlerteHaut;
|
||||
|
||||
/** Indicateur si une alerte est active */
|
||||
@Builder.Default private Boolean alerteActive = false;
|
||||
|
||||
/** Type d'alerte (bas, haut, anomalie) */
|
||||
@Size(max = 50, message = "Le type d'alerte ne peut pas dépasser 50 caractères")
|
||||
private String typeAlerte;
|
||||
|
||||
/** Message d'alerte */
|
||||
@Size(max = 500, message = "Le message d'alerte ne peut pas dépasser 500 caractères")
|
||||
private String messageAlerte;
|
||||
|
||||
/** Configuration du graphique (couleurs, style, etc.) */
|
||||
@Size(max = 2000, message = "La configuration graphique ne peut pas dépasser 2000 caractères")
|
||||
private String configurationGraphique;
|
||||
|
||||
/** Intervalle de regroupement des données */
|
||||
@Size(max = 20, message = "L'intervalle de regroupement ne peut pas dépasser 20 caractères")
|
||||
private String intervalleRegroupement;
|
||||
|
||||
/** Format d'affichage des dates */
|
||||
@Size(max = 20, message = "Le format de date ne peut pas dépasser 20 caractères")
|
||||
private String formatDate;
|
||||
|
||||
/** Date de dernière mise à jour */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDerniereMiseAJour;
|
||||
|
||||
/** Fréquence de mise à jour en minutes */
|
||||
@DecimalMin(value = "1", message = "La fréquence de mise à jour minimum est 1 minute")
|
||||
private Integer frequenceMiseAJourMinutes;
|
||||
|
||||
// === CLASSES INTERNES ===
|
||||
|
||||
/** Classe interne représentant un point de données dans la tendance */
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class PointDonneeDTO {
|
||||
|
||||
/** Date du point de données */
|
||||
@NotNull(message = "La date du point de données est obligatoire")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDebut;
|
||||
|
||||
/** Date de fin de la période analysée */
|
||||
@NotNull(message = "La date de fin est obligatoire")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateFin;
|
||||
|
||||
/** Points de données pour la tendance */
|
||||
@NotNull(message = "Les points de données sont obligatoires")
|
||||
private List<PointDonneeDTO> pointsDonnees;
|
||||
|
||||
/** Valeur actuelle du KPI */
|
||||
@NotNull(message = "La valeur actuelle est obligatoire")
|
||||
@DecimalMin(value = "0.0", message = "La valeur actuelle doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur actuelle invalide")
|
||||
private BigDecimal valeurActuelle;
|
||||
|
||||
/** Valeur minimale sur la période */
|
||||
@DecimalMin(value = "0.0", message = "La valeur minimale doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur minimale invalide")
|
||||
private BigDecimal valeurMinimale;
|
||||
|
||||
/** Valeur maximale sur la période */
|
||||
@DecimalMin(value = "0.0", message = "La valeur maximale doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur maximale invalide")
|
||||
private BigDecimal valeurMaximale;
|
||||
|
||||
/** Valeur moyenne sur la période */
|
||||
@DecimalMin(value = "0.0", message = "La valeur moyenne doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur moyenne invalide")
|
||||
private BigDecimal valeurMoyenne;
|
||||
|
||||
/** Écart-type des valeurs */
|
||||
@DecimalMin(value = "0.0", message = "L'écart-type doit être positif ou nul")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format d'écart-type invalide")
|
||||
private BigDecimal ecartType;
|
||||
|
||||
/** Coefficient de variation (écart-type / moyenne) */
|
||||
@DecimalMin(value = "0.0", message = "Le coefficient de variation doit être positif ou nul")
|
||||
@Digits(integer = 6, fraction = 4, message = "Format de coefficient de variation invalide")
|
||||
private BigDecimal coefficientVariation;
|
||||
|
||||
/** Tendance générale (pente de la régression linéaire) */
|
||||
@Digits(integer = 10, fraction = 6, message = "Format de tendance invalide")
|
||||
private BigDecimal tendanceGenerale;
|
||||
|
||||
/** Coefficient de corrélation R² */
|
||||
@DecimalMin(value = "0.0", message = "Le coefficient de corrélation doit être positif ou nul")
|
||||
@DecimalMax(value = "1.0", message = "Le coefficient de corrélation ne peut pas dépasser 1")
|
||||
@Digits(integer = 1, fraction = 6, message = "Format de coefficient de corrélation invalide")
|
||||
private BigDecimal coefficientCorrelation;
|
||||
|
||||
/** Pourcentage d'évolution depuis le début de la période */
|
||||
@Digits(integer = 6, fraction = 2, message = "Format de pourcentage d'évolution invalide")
|
||||
private BigDecimal pourcentageEvolutionGlobale;
|
||||
|
||||
/** Prédiction pour la prochaine période */
|
||||
@DecimalMin(value = "0.0", message = "La prédiction doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de prédiction invalide")
|
||||
private BigDecimal predictionProchainePeriode;
|
||||
|
||||
/** Marge d'erreur de la prédiction (en pourcentage) */
|
||||
@DecimalMin(value = "0.0", message = "La marge d'erreur doit être positive ou nulle")
|
||||
@DecimalMax(value = "100.0", message = "La marge d'erreur ne peut pas dépasser 100%")
|
||||
@Digits(integer = 3, fraction = 2, message = "Format de marge d'erreur invalide")
|
||||
private BigDecimal margeErreurPrediction;
|
||||
|
||||
/** Seuil d'alerte bas */
|
||||
@DecimalMin(value = "0.0", message = "Le seuil d'alerte bas doit être positif ou nul")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de seuil d'alerte bas invalide")
|
||||
private BigDecimal seuilAlerteBas;
|
||||
|
||||
/** Seuil d'alerte haut */
|
||||
@DecimalMin(value = "0.0", message = "Le seuil d'alerte haut doit être positif ou nul")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de seuil d'alerte haut invalide")
|
||||
private BigDecimal seuilAlerteHaut;
|
||||
|
||||
/** Indicateur si une alerte est active */
|
||||
@Builder.Default
|
||||
private Boolean alerteActive = false;
|
||||
|
||||
/** Type d'alerte (bas, haut, anomalie) */
|
||||
@Size(max = 50, message = "Le type d'alerte ne peut pas dépasser 50 caractères")
|
||||
private String typeAlerte;
|
||||
|
||||
/** Message d'alerte */
|
||||
@Size(max = 500, message = "Le message d'alerte ne peut pas dépasser 500 caractères")
|
||||
private String messageAlerte;
|
||||
|
||||
/** Configuration du graphique (couleurs, style, etc.) */
|
||||
@Size(max = 2000, message = "La configuration graphique ne peut pas dépasser 2000 caractères")
|
||||
private String configurationGraphique;
|
||||
|
||||
/** Intervalle de regroupement des données */
|
||||
@Size(max = 20, message = "L'intervalle de regroupement ne peut pas dépasser 20 caractères")
|
||||
private String intervalleRegroupement;
|
||||
|
||||
/** Format d'affichage des dates */
|
||||
@Size(max = 20, message = "Le format de date ne peut pas dépasser 20 caractères")
|
||||
private String formatDate;
|
||||
|
||||
/** Date de dernière mise à jour */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDerniereMiseAJour;
|
||||
|
||||
/** Fréquence de mise à jour en minutes */
|
||||
@DecimalMin(value = "1", message = "La fréquence de mise à jour minimum est 1 minute")
|
||||
private Integer frequenceMiseAJourMinutes;
|
||||
|
||||
// === CLASSES INTERNES ===
|
||||
|
||||
/**
|
||||
* Classe interne représentant un point de données dans la tendance
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class PointDonneeDTO {
|
||||
|
||||
/** Date du point de données */
|
||||
@NotNull(message = "La date du point de données est obligatoire")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime date;
|
||||
|
||||
/** Valeur du point de données */
|
||||
@NotNull(message = "La valeur du point de données est obligatoire")
|
||||
@DecimalMin(value = "0.0", message = "La valeur du point doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur du point invalide")
|
||||
private BigDecimal valeur;
|
||||
|
||||
/** Libellé du point (optionnel) */
|
||||
@Size(max = 100, message = "Le libellé du point ne peut pas dépasser 100 caractères")
|
||||
private String libelle;
|
||||
|
||||
/** Indicateur si le point est une anomalie */
|
||||
@Builder.Default
|
||||
private Boolean anomalie = false;
|
||||
|
||||
/** Indicateur si le point est une prédiction */
|
||||
@Builder.Default
|
||||
private Boolean prediction = false;
|
||||
|
||||
/** Métadonnées additionnelles du point */
|
||||
private String metadonnees;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Retourne le libellé de la métrique
|
||||
*
|
||||
* @return Le libellé de la métrique
|
||||
*/
|
||||
public String getLibelleMetrique() {
|
||||
return typeMetrique.getLibelle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'unité de mesure
|
||||
*
|
||||
* @return L'unité de mesure
|
||||
*/
|
||||
public String getUnite() {
|
||||
return typeMetrique.getUnite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône de la métrique
|
||||
*
|
||||
* @return L'icône Material Design
|
||||
*/
|
||||
public String getIcone() {
|
||||
return typeMetrique.getIcone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur de la métrique
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return typeMetrique.getCouleur();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la tendance est positive
|
||||
*
|
||||
* @return true si la tendance générale est positive
|
||||
*/
|
||||
public boolean isTendancePositive() {
|
||||
return tendanceGenerale != null && tendanceGenerale.compareTo(BigDecimal.ZERO) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la tendance est négative
|
||||
*
|
||||
* @return true si la tendance générale est négative
|
||||
*/
|
||||
public boolean isTendanceNegative() {
|
||||
return tendanceGenerale != null && tendanceGenerale.compareTo(BigDecimal.ZERO) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la tendance est stable
|
||||
*
|
||||
* @return true si la tendance générale est stable
|
||||
*/
|
||||
public boolean isTendanceStable() {
|
||||
return tendanceGenerale != null && tendanceGenerale.compareTo(BigDecimal.ZERO) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la volatilité du KPI (basée sur le coefficient de variation)
|
||||
*
|
||||
* @return "faible", "moyenne" ou "élevée"
|
||||
*/
|
||||
public String getVolatilite() {
|
||||
if (coefficientVariation == null) return "inconnue";
|
||||
|
||||
BigDecimal cv = coefficientVariation;
|
||||
if (cv.compareTo(new BigDecimal("0.1")) <= 0) return "faible";
|
||||
if (cv.compareTo(new BigDecimal("0.3")) <= 0) return "moyenne";
|
||||
return "élevée";
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la prédiction est fiable (R² > 0.7)
|
||||
*
|
||||
* @return true si la prédiction est considérée comme fiable
|
||||
*/
|
||||
public boolean isPredictionFiable() {
|
||||
return coefficientCorrelation != null &&
|
||||
coefficientCorrelation.compareTo(new BigDecimal("0.7")) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nombre de points de données
|
||||
*
|
||||
* @return Le nombre de points de données
|
||||
*/
|
||||
public int getNombrePointsDonnees() {
|
||||
return pointsDonnees != null ? pointsDonnees.size() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si des anomalies ont été détectées
|
||||
*
|
||||
* @return true si au moins un point est marqué comme anomalie
|
||||
*/
|
||||
public boolean hasAnomalies() {
|
||||
return pointsDonnees != null &&
|
||||
pointsDonnees.stream().anyMatch(PointDonneeDTO::getAnomalie);
|
||||
}
|
||||
private LocalDateTime date;
|
||||
|
||||
/** Valeur du point de données */
|
||||
@NotNull(message = "La valeur du point de données est obligatoire")
|
||||
@DecimalMin(value = "0.0", message = "La valeur du point doit être positive ou nulle")
|
||||
@Digits(integer = 15, fraction = 4, message = "Format de valeur du point invalide")
|
||||
private BigDecimal valeur;
|
||||
|
||||
/** Libellé du point (optionnel) */
|
||||
@Size(max = 100, message = "Le libellé du point ne peut pas dépasser 100 caractères")
|
||||
private String libelle;
|
||||
|
||||
/** Indicateur si le point est une anomalie */
|
||||
@Builder.Default private Boolean anomalie = false;
|
||||
|
||||
/** Indicateur si le point est une prédiction */
|
||||
@Builder.Default private Boolean prediction = false;
|
||||
|
||||
/** Métadonnées additionnelles du point */
|
||||
private String metadonnees;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Retourne le libellé de la métrique
|
||||
*
|
||||
* @return Le libellé de la métrique
|
||||
*/
|
||||
public String getLibelleMetrique() {
|
||||
return typeMetrique.getLibelle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'unité de mesure
|
||||
*
|
||||
* @return L'unité de mesure
|
||||
*/
|
||||
public String getUnite() {
|
||||
return typeMetrique.getUnite();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône de la métrique
|
||||
*
|
||||
* @return L'icône Material Design
|
||||
*/
|
||||
public String getIcone() {
|
||||
return typeMetrique.getIcone();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur de la métrique
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return typeMetrique.getCouleur();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la tendance est positive
|
||||
*
|
||||
* @return true si la tendance générale est positive
|
||||
*/
|
||||
public boolean isTendancePositive() {
|
||||
return tendanceGenerale != null && tendanceGenerale.compareTo(BigDecimal.ZERO) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la tendance est négative
|
||||
*
|
||||
* @return true si la tendance générale est négative
|
||||
*/
|
||||
public boolean isTendanceNegative() {
|
||||
return tendanceGenerale != null && tendanceGenerale.compareTo(BigDecimal.ZERO) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la tendance est stable
|
||||
*
|
||||
* @return true si la tendance générale est stable
|
||||
*/
|
||||
public boolean isTendanceStable() {
|
||||
return tendanceGenerale != null && tendanceGenerale.compareTo(BigDecimal.ZERO) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la volatilité du KPI (basée sur le coefficient de variation)
|
||||
*
|
||||
* @return "faible", "moyenne" ou "élevée"
|
||||
*/
|
||||
public String getVolatilite() {
|
||||
if (coefficientVariation == null) return "inconnue";
|
||||
|
||||
BigDecimal cv = coefficientVariation;
|
||||
if (cv.compareTo(new BigDecimal("0.1")) <= 0) return "faible";
|
||||
if (cv.compareTo(new BigDecimal("0.3")) <= 0) return "moyenne";
|
||||
return "élevée";
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la prédiction est fiable (R² > 0.7)
|
||||
*
|
||||
* @return true si la prédiction est considérée comme fiable
|
||||
*/
|
||||
public boolean isPredictionFiable() {
|
||||
return coefficientCorrelation != null
|
||||
&& coefficientCorrelation.compareTo(new BigDecimal("0.7")) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nombre de points de données
|
||||
*
|
||||
* @return Le nombre de points de données
|
||||
*/
|
||||
public int getNombrePointsDonnees() {
|
||||
return pointsDonnees != null ? pointsDonnees.size() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si des anomalies ont été détectées
|
||||
*
|
||||
* @return true si au moins un point est marqué comme anomalie
|
||||
*/
|
||||
public boolean hasAnomalies() {
|
||||
return pointsDonnees != null
|
||||
&& pointsDonnees.stream().anyMatch(point -> Boolean.TRUE.equals(point.getAnomalie()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,32 +2,31 @@ package dev.lions.unionflow.server.api.dto.analytics;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.TypeMetrique;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.PeriodeAnalyse;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.FormatExport;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.PeriodeAnalyse;
|
||||
import dev.lions.unionflow.server.api.enums.analytics.TypeMetrique;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.Builder;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* DTO pour la configuration des rapports analytics UnionFlow
|
||||
*
|
||||
* Représente la configuration d'un rapport personnalisé avec ses métriques,
|
||||
* sa mise en forme et ses paramètres d'export.
|
||||
*
|
||||
*
|
||||
* <p>Représente la configuration d'un rapport personnalisé avec ses métriques, sa mise en forme et
|
||||
* ses paramètres d'export.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -38,300 +37,291 @@ import java.util.UUID;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ReportConfigDTO extends BaseDTO {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Nom du rapport */
|
||||
@NotBlank(message = "Le nom du rapport est obligatoire")
|
||||
@Size(min = 3, max = 200, message = "Le nom du rapport doit contenir entre 3 et 200 caractères")
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Nom du rapport */
|
||||
@NotBlank(message = "Le nom du rapport est obligatoire")
|
||||
@Size(min = 3, max = 200, message = "Le nom du rapport doit contenir entre 3 et 200 caractères")
|
||||
private String nom;
|
||||
|
||||
/** Description du rapport */
|
||||
@Size(max = 1000, message = "La description ne peut pas dépasser 1000 caractères")
|
||||
private String description;
|
||||
|
||||
/** Type de rapport (executif, analytique, technique, operationnel) */
|
||||
@NotBlank(message = "Le type de rapport est obligatoire")
|
||||
@Size(max = 50, message = "Le type de rapport ne peut pas dépasser 50 caractères")
|
||||
private String typeRapport;
|
||||
|
||||
/** Période d'analyse par défaut */
|
||||
@NotNull(message = "La période d'analyse est obligatoire")
|
||||
private PeriodeAnalyse periodeAnalyse;
|
||||
|
||||
/** Date de début personnalisée (si période personnalisée) */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDebutPersonnalisee;
|
||||
|
||||
/** Date de fin personnalisée (si période personnalisée) */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateFinPersonnalisee;
|
||||
|
||||
/** Identifiant de l'organisation (optionnel pour filtrage) */
|
||||
private UUID organisationId;
|
||||
|
||||
/** Nom de l'organisation */
|
||||
@Size(max = 200, message = "Le nom de l'organisation ne peut pas dépasser 200 caractères")
|
||||
private String nomOrganisation;
|
||||
|
||||
/** Identifiant de l'utilisateur créateur */
|
||||
@NotNull(message = "L'identifiant de l'utilisateur créateur est obligatoire")
|
||||
private UUID utilisateurCreateurId;
|
||||
|
||||
/** Nom de l'utilisateur créateur */
|
||||
@Size(max = 200, message = "Le nom de l'utilisateur créateur ne peut pas dépasser 200 caractères")
|
||||
private String nomUtilisateurCreateur;
|
||||
|
||||
/** Métriques incluses dans le rapport */
|
||||
@NotNull(message = "Les métriques sont obligatoires")
|
||||
@Valid
|
||||
private List<MetriqueConfigDTO> metriques;
|
||||
|
||||
/** Sections du rapport */
|
||||
@Valid private List<SectionRapportDTO> sections;
|
||||
|
||||
/** Format d'export par défaut */
|
||||
@NotNull(message = "Le format d'export est obligatoire")
|
||||
private FormatExport formatExport;
|
||||
|
||||
/** Formats d'export autorisés */
|
||||
private List<FormatExport> formatsExportAutorises;
|
||||
|
||||
/** Modèle de rapport à utiliser */
|
||||
@Size(max = 100, message = "Le modèle de rapport ne peut pas dépasser 100 caractères")
|
||||
private String modeleRapport;
|
||||
|
||||
/** Configuration de la mise en page */
|
||||
@Size(
|
||||
max = 2000,
|
||||
message = "La configuration de mise en page ne peut pas dépasser 2000 caractères")
|
||||
private String configurationMiseEnPage;
|
||||
|
||||
/** Logo personnalisé (URL ou base64) */
|
||||
@Size(max = 5000, message = "Le logo personnalisé ne peut pas dépasser 5000 caractères")
|
||||
private String logoPersonnalise;
|
||||
|
||||
/** Couleurs personnalisées du rapport */
|
||||
private Map<String, String> couleursPersonnalisees;
|
||||
|
||||
/** Indicateur si le rapport est public */
|
||||
@Builder.Default private Boolean rapportPublic = false;
|
||||
|
||||
/** Indicateur si le rapport est automatique */
|
||||
@Builder.Default private Boolean rapportAutomatique = false;
|
||||
|
||||
/** Fréquence de génération automatique (en heures) */
|
||||
@DecimalMin(value = "1", message = "La fréquence minimum est 1 heure")
|
||||
private Integer frequenceGenerationHeures;
|
||||
|
||||
/** Prochaine génération automatique */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime prochaineGeneration;
|
||||
|
||||
/** Liste des destinataires pour l'envoi automatique */
|
||||
private List<String> destinatairesEmail;
|
||||
|
||||
/** Objet de l'email pour l'envoi automatique */
|
||||
@Size(max = 200, message = "L'objet de l'email ne peut pas dépasser 200 caractères")
|
||||
private String objetEmail;
|
||||
|
||||
/** Corps de l'email pour l'envoi automatique */
|
||||
@Size(max = 2000, message = "Le corps de l'email ne peut pas dépasser 2000 caractères")
|
||||
private String corpsEmail;
|
||||
|
||||
/** Paramètres de filtrage avancé */
|
||||
private Map<String, Object> parametresFiltrage;
|
||||
|
||||
/** Tags pour catégoriser le rapport */
|
||||
private List<String> tags;
|
||||
|
||||
/** Niveau de confidentialité (1=public, 5=confidentiel) */
|
||||
@DecimalMin(value = "1", message = "Le niveau de confidentialité minimum est 1")
|
||||
@DecimalMax(value = "5", message = "Le niveau de confidentialité maximum est 5")
|
||||
@Builder.Default
|
||||
private Integer niveauConfidentialite = 1;
|
||||
|
||||
/** Date de dernière génération */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDerniereGeneration;
|
||||
|
||||
/** Nombre de générations effectuées */
|
||||
@DecimalMin(value = "0", message = "Le nombre de générations doit être positif")
|
||||
@Builder.Default
|
||||
private Integer nombreGenerations = 0;
|
||||
|
||||
/** Taille moyenne des rapports générés (en KB) */
|
||||
@DecimalMin(value = "0", message = "La taille moyenne doit être positive")
|
||||
private Long tailleMoyenneKB;
|
||||
|
||||
/** Temps moyen de génération (en secondes) */
|
||||
@DecimalMin(value = "0", message = "Le temps moyen de génération doit être positif")
|
||||
private Integer tempsMoyenGenerationSecondes;
|
||||
|
||||
// === CLASSES INTERNES ===
|
||||
|
||||
/** Configuration d'une métrique dans le rapport */
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MetriqueConfigDTO {
|
||||
|
||||
/** Type de métrique */
|
||||
@NotNull(message = "Le type de métrique est obligatoire")
|
||||
private TypeMetrique typeMetrique;
|
||||
|
||||
/** Libellé personnalisé */
|
||||
@Size(max = 200, message = "Le libellé personnalisé ne peut pas dépasser 200 caractères")
|
||||
private String libellePersonnalise;
|
||||
|
||||
/** Position dans le rapport (ordre d'affichage) */
|
||||
@DecimalMin(value = "1", message = "La position minimum est 1")
|
||||
private Integer position;
|
||||
|
||||
/** Taille d'affichage (1=petit, 2=moyen, 3=grand) */
|
||||
@DecimalMin(value = "1", message = "La taille minimum est 1")
|
||||
@DecimalMax(value = "3", message = "La taille maximum est 3")
|
||||
@Builder.Default
|
||||
private Integer tailleAffichage = 2;
|
||||
|
||||
/** Couleur personnalisée */
|
||||
@Size(max = 7, message = "La couleur doit être au format #RRGGBB")
|
||||
private String couleurPersonnalisee;
|
||||
|
||||
/** Indicateur si la métrique inclut un graphique */
|
||||
@Builder.Default private Boolean inclureGraphique = true;
|
||||
|
||||
/** Type de graphique (line, bar, pie, area) */
|
||||
@Size(max = 20, message = "Le type de graphique ne peut pas dépasser 20 caractères")
|
||||
@Builder.Default
|
||||
private String typeGraphique = "line";
|
||||
|
||||
/** Indicateur si la métrique inclut la tendance */
|
||||
@Builder.Default private Boolean inclureTendance = true;
|
||||
|
||||
/** Indicateur si la métrique inclut la comparaison */
|
||||
@Builder.Default private Boolean inclureComparaison = true;
|
||||
|
||||
/** Seuils d'alerte personnalisés */
|
||||
private Map<String, Object> seuilsAlerte;
|
||||
|
||||
/** Filtres spécifiques à cette métrique */
|
||||
private Map<String, Object> filtresSpecifiques;
|
||||
}
|
||||
|
||||
/** Configuration d'une section du rapport */
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class SectionRapportDTO {
|
||||
|
||||
/** Nom de la section */
|
||||
@NotBlank(message = "Le nom de la section est obligatoire")
|
||||
@Size(max = 200, message = "Le nom de la section ne peut pas dépasser 200 caractères")
|
||||
private String nom;
|
||||
|
||||
/** Description du rapport */
|
||||
@Size(max = 1000, message = "La description ne peut pas dépasser 1000 caractères")
|
||||
|
||||
/** Description de la section */
|
||||
@Size(max = 500, message = "La description de la section ne peut pas dépasser 500 caractères")
|
||||
private String description;
|
||||
|
||||
/** Type de rapport (executif, analytique, technique, operationnel) */
|
||||
@NotBlank(message = "Le type de rapport est obligatoire")
|
||||
@Size(max = 50, message = "Le type de rapport ne peut pas dépasser 50 caractères")
|
||||
private String typeRapport;
|
||||
|
||||
/** Période d'analyse par défaut */
|
||||
@NotNull(message = "La période d'analyse est obligatoire")
|
||||
private PeriodeAnalyse periodeAnalyse;
|
||||
|
||||
/** Date de début personnalisée (si période personnalisée) */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDebutPersonnalisee;
|
||||
|
||||
/** Date de fin personnalisée (si période personnalisée) */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateFinPersonnalisee;
|
||||
|
||||
/** Identifiant de l'organisation (optionnel pour filtrage) */
|
||||
private UUID organisationId;
|
||||
|
||||
/** Nom de l'organisation */
|
||||
@Size(max = 200, message = "Le nom de l'organisation ne peut pas dépasser 200 caractères")
|
||||
private String nomOrganisation;
|
||||
|
||||
/** Identifiant de l'utilisateur créateur */
|
||||
@NotNull(message = "L'identifiant de l'utilisateur créateur est obligatoire")
|
||||
private UUID utilisateurCreateurId;
|
||||
|
||||
/** Nom de l'utilisateur créateur */
|
||||
@Size(max = 200, message = "Le nom de l'utilisateur créateur ne peut pas dépasser 200 caractères")
|
||||
private String nomUtilisateurCreateur;
|
||||
|
||||
/** Métriques incluses dans le rapport */
|
||||
@NotNull(message = "Les métriques sont obligatoires")
|
||||
@Valid
|
||||
private List<MetriqueConfigDTO> metriques;
|
||||
|
||||
/** Sections du rapport */
|
||||
@Valid
|
||||
private List<SectionRapportDTO> sections;
|
||||
|
||||
/** Format d'export par défaut */
|
||||
@NotNull(message = "Le format d'export est obligatoire")
|
||||
private FormatExport formatExport;
|
||||
|
||||
/** Formats d'export autorisés */
|
||||
private List<FormatExport> formatsExportAutorises;
|
||||
|
||||
/** Modèle de rapport à utiliser */
|
||||
@Size(max = 100, message = "Le modèle de rapport ne peut pas dépasser 100 caractères")
|
||||
private String modeleRapport;
|
||||
|
||||
/** Configuration de la mise en page */
|
||||
@Size(max = 2000, message = "La configuration de mise en page ne peut pas dépasser 2000 caractères")
|
||||
private String configurationMiseEnPage;
|
||||
|
||||
/** Logo personnalisé (URL ou base64) */
|
||||
@Size(max = 5000, message = "Le logo personnalisé ne peut pas dépasser 5000 caractères")
|
||||
private String logoPersonnalise;
|
||||
|
||||
/** Couleurs personnalisées du rapport */
|
||||
private Map<String, String> couleursPersonnalisees;
|
||||
|
||||
/** Indicateur si le rapport est public */
|
||||
@Builder.Default
|
||||
private Boolean rapportPublic = false;
|
||||
|
||||
/** Indicateur si le rapport est automatique */
|
||||
@Builder.Default
|
||||
private Boolean rapportAutomatique = false;
|
||||
|
||||
/** Fréquence de génération automatique (en heures) */
|
||||
@DecimalMin(value = "1", message = "La fréquence minimum est 1 heure")
|
||||
private Integer frequenceGenerationHeures;
|
||||
|
||||
/** Prochaine génération automatique */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime prochaineGeneration;
|
||||
|
||||
/** Liste des destinataires pour l'envoi automatique */
|
||||
private List<String> destinatairesEmail;
|
||||
|
||||
/** Objet de l'email pour l'envoi automatique */
|
||||
@Size(max = 200, message = "L'objet de l'email ne peut pas dépasser 200 caractères")
|
||||
private String objetEmail;
|
||||
|
||||
/** Corps de l'email pour l'envoi automatique */
|
||||
@Size(max = 2000, message = "Le corps de l'email ne peut pas dépasser 2000 caractères")
|
||||
private String corpsEmail;
|
||||
|
||||
/** Paramètres de filtrage avancé */
|
||||
private Map<String, Object> parametresFiltrage;
|
||||
|
||||
/** Tags pour catégoriser le rapport */
|
||||
private List<String> tags;
|
||||
|
||||
/** Niveau de confidentialité (1=public, 5=confidentiel) */
|
||||
@DecimalMin(value = "1", message = "Le niveau de confidentialité minimum est 1")
|
||||
@DecimalMax(value = "5", message = "Le niveau de confidentialité maximum est 5")
|
||||
@Builder.Default
|
||||
private Integer niveauConfidentialite = 1;
|
||||
|
||||
/** Date de dernière génération */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateDerniereGeneration;
|
||||
|
||||
/** Nombre de générations effectuées */
|
||||
@DecimalMin(value = "0", message = "Le nombre de générations doit être positif")
|
||||
@Builder.Default
|
||||
private Integer nombreGenerations = 0;
|
||||
|
||||
/** Taille moyenne des rapports générés (en KB) */
|
||||
@DecimalMin(value = "0", message = "La taille moyenne doit être positive")
|
||||
private Long tailleMoyenneKB;
|
||||
|
||||
/** Temps moyen de génération (en secondes) */
|
||||
@DecimalMin(value = "0", message = "Le temps moyen de génération doit être positif")
|
||||
private Integer tempsMoyenGenerationSecondes;
|
||||
|
||||
// === CLASSES INTERNES ===
|
||||
|
||||
/**
|
||||
* Configuration d'une métrique dans le rapport
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class MetriqueConfigDTO {
|
||||
|
||||
/** Type de métrique */
|
||||
@NotNull(message = "Le type de métrique est obligatoire")
|
||||
private TypeMetrique typeMetrique;
|
||||
|
||||
/** Libellé personnalisé */
|
||||
@Size(max = 200, message = "Le libellé personnalisé ne peut pas dépasser 200 caractères")
|
||||
private String libellePersonnalise;
|
||||
|
||||
/** Position dans le rapport (ordre d'affichage) */
|
||||
@DecimalMin(value = "1", message = "La position minimum est 1")
|
||||
private Integer position;
|
||||
|
||||
/** Taille d'affichage (1=petit, 2=moyen, 3=grand) */
|
||||
@DecimalMin(value = "1", message = "La taille minimum est 1")
|
||||
@DecimalMax(value = "3", message = "La taille maximum est 3")
|
||||
@Builder.Default
|
||||
private Integer tailleAffichage = 2;
|
||||
|
||||
/** Couleur personnalisée */
|
||||
@Size(max = 7, message = "La couleur doit être au format #RRGGBB")
|
||||
private String couleurPersonnalisee;
|
||||
|
||||
/** Indicateur si la métrique inclut un graphique */
|
||||
@Builder.Default
|
||||
private Boolean inclureGraphique = true;
|
||||
|
||||
/** Type de graphique (line, bar, pie, area) */
|
||||
@Size(max = 20, message = "Le type de graphique ne peut pas dépasser 20 caractères")
|
||||
@Builder.Default
|
||||
private String typeGraphique = "line";
|
||||
|
||||
/** Indicateur si la métrique inclut la tendance */
|
||||
@Builder.Default
|
||||
private Boolean inclureTendance = true;
|
||||
|
||||
/** Indicateur si la métrique inclut la comparaison */
|
||||
@Builder.Default
|
||||
private Boolean inclureComparaison = true;
|
||||
|
||||
/** Seuils d'alerte personnalisés */
|
||||
private Map<String, Object> seuilsAlerte;
|
||||
|
||||
/** Filtres spécifiques à cette métrique */
|
||||
private Map<String, Object> filtresSpecifiques;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration d'une section du rapport
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class SectionRapportDTO {
|
||||
|
||||
/** Nom de la section */
|
||||
@NotBlank(message = "Le nom de la section est obligatoire")
|
||||
@Size(max = 200, message = "Le nom de la section ne peut pas dépasser 200 caractères")
|
||||
private String nom;
|
||||
|
||||
/** Description de la section */
|
||||
@Size(max = 500, message = "La description de la section ne peut pas dépasser 500 caractères")
|
||||
private String description;
|
||||
|
||||
/** Position de la section dans le rapport */
|
||||
@DecimalMin(value = "1", message = "La position minimum est 1")
|
||||
private Integer position;
|
||||
|
||||
/** Type de section (resume, metriques, graphiques, tableaux, analyse) */
|
||||
@NotBlank(message = "Le type de section est obligatoire")
|
||||
@Size(max = 50, message = "Le type de section ne peut pas dépasser 50 caractères")
|
||||
private String typeSection;
|
||||
|
||||
/** Métriques incluses dans cette section */
|
||||
private List<TypeMetrique> metriquesIncluses;
|
||||
|
||||
/** Configuration spécifique de la section */
|
||||
private Map<String, Object> configurationSection;
|
||||
|
||||
/** Indicateur si la section est visible */
|
||||
@Builder.Default
|
||||
private Boolean visible = true;
|
||||
|
||||
/** Indicateur si la section peut être réduite */
|
||||
@Builder.Default
|
||||
private Boolean pliable = false;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Retourne le nombre de métriques configurées
|
||||
*
|
||||
* @return Le nombre de métriques
|
||||
*/
|
||||
public int getNombreMetriques() {
|
||||
return metriques != null ? metriques.size() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nombre de sections configurées
|
||||
*
|
||||
* @return Le nombre de sections
|
||||
*/
|
||||
public int getNombreSections() {
|
||||
return sections != null ? sections.size() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le rapport utilise une période personnalisée
|
||||
*
|
||||
* @return true si la période est personnalisée
|
||||
*/
|
||||
public boolean isPeriodePersonnalisee() {
|
||||
return periodeAnalyse == PeriodeAnalyse.PERIODE_PERSONNALISEE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le rapport est confidentiel (niveau >= 4)
|
||||
*
|
||||
* @return true si le rapport est confidentiel
|
||||
*/
|
||||
public boolean isConfidentiel() {
|
||||
return niveauConfidentialite != null && niveauConfidentialite >= 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le rapport nécessite une génération
|
||||
*
|
||||
* @return true si la prochaine génération est due
|
||||
*/
|
||||
public boolean necessiteGeneration() {
|
||||
return rapportAutomatique && prochaineGeneration != null &&
|
||||
prochaineGeneration.isBefore(LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la fréquence de génération en texte
|
||||
*
|
||||
* @return La fréquence sous forme de texte
|
||||
*/
|
||||
public String getFrequenceTexte() {
|
||||
if (frequenceGenerationHeures == null) return "Manuelle";
|
||||
|
||||
return switch (frequenceGenerationHeures) {
|
||||
case 1 -> "Toutes les heures";
|
||||
case 24 -> "Quotidienne";
|
||||
case 168 -> "Hebdomadaire"; // 24 * 7
|
||||
case 720 -> "Mensuelle"; // 24 * 30
|
||||
default -> "Toutes les " + frequenceGenerationHeures + " heures";
|
||||
};
|
||||
}
|
||||
|
||||
/** Position de la section dans le rapport */
|
||||
@DecimalMin(value = "1", message = "La position minimum est 1")
|
||||
private Integer position;
|
||||
|
||||
/** Type de section (resume, metriques, graphiques, tableaux, analyse) */
|
||||
@NotBlank(message = "Le type de section est obligatoire")
|
||||
@Size(max = 50, message = "Le type de section ne peut pas dépasser 50 caractères")
|
||||
private String typeSection;
|
||||
|
||||
/** Métriques incluses dans cette section */
|
||||
private List<TypeMetrique> metriquesIncluses;
|
||||
|
||||
/** Configuration spécifique de la section */
|
||||
private Map<String, Object> configurationSection;
|
||||
|
||||
/** Indicateur si la section est visible */
|
||||
@Builder.Default private Boolean visible = true;
|
||||
|
||||
/** Indicateur si la section peut être réduite */
|
||||
@Builder.Default private Boolean pliable = false;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Retourne le nombre de métriques configurées
|
||||
*
|
||||
* @return Le nombre de métriques
|
||||
*/
|
||||
public int getNombreMetriques() {
|
||||
return metriques != null ? metriques.size() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nombre de sections configurées
|
||||
*
|
||||
* @return Le nombre de sections
|
||||
*/
|
||||
public int getNombreSections() {
|
||||
return sections != null ? sections.size() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le rapport utilise une période personnalisée
|
||||
*
|
||||
* @return true si la période est personnalisée
|
||||
*/
|
||||
public boolean isPeriodePersonnalisee() {
|
||||
return periodeAnalyse == PeriodeAnalyse.PERIODE_PERSONNALISEE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le rapport est confidentiel (niveau >= 4)
|
||||
*
|
||||
* @return true si le rapport est confidentiel
|
||||
*/
|
||||
public boolean isConfidentiel() {
|
||||
return niveauConfidentialite != null && niveauConfidentialite >= 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le rapport nécessite une génération
|
||||
*
|
||||
* @return true si la prochaine génération est due
|
||||
*/
|
||||
public boolean necessiteGeneration() {
|
||||
return rapportAutomatique
|
||||
&& prochaineGeneration != null
|
||||
&& prochaineGeneration.isBefore(LocalDateTime.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la fréquence de génération en texte
|
||||
*
|
||||
* @return La fréquence sous forme de texte
|
||||
*/
|
||||
public String getFrequenceTexte() {
|
||||
if (frequenceGenerationHeures == null) return "Manuelle";
|
||||
|
||||
return switch (frequenceGenerationHeures) {
|
||||
case 1 -> "Toutes les heures";
|
||||
case 24 -> "Quotidienne";
|
||||
case 168 -> "Hebdomadaire"; // 24 * 7
|
||||
case 720 -> "Mensuelle"; // 24 * 30
|
||||
default -> "Toutes les " + frequenceGenerationHeures + " heures";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dev.lions.unionflow.server.api.dto.base;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
@@ -18,18 +19,18 @@ import lombok.Setter;
|
||||
@Setter
|
||||
public abstract class BaseDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@Serial private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Identifiant unique UUID */
|
||||
private UUID id;
|
||||
|
||||
/** Date de création de l'enregistrement */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateCreation;
|
||||
public LocalDateTime dateCreation;
|
||||
|
||||
/** Date de dernière modification */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateModification;
|
||||
public LocalDateTime dateModification;
|
||||
|
||||
/** Utilisateur qui a créé l'enregistrement */
|
||||
private String creePar;
|
||||
|
||||
@@ -2,6 +2,10 @@ package dev.lions.unionflow.server.api.dto.evenement;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.PrioriteEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.StatutEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.TypeEvenementMetier;
|
||||
import dev.lions.unionflow.server.api.validation.ValidationConstants;
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Digits;
|
||||
@@ -36,30 +40,29 @@ public class EvenementDTO extends BaseDTO {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Titre de l'événement */
|
||||
@NotBlank(message = "Le titre est obligatoire")
|
||||
@Size(min = 3, max = 100, message = "Le titre doit contenir entre 3 et 100 caractères")
|
||||
@NotBlank(message = "Le titre" + ValidationConstants.OBLIGATOIRE_MESSAGE)
|
||||
@Size(
|
||||
min = ValidationConstants.TITRE_MIN_LENGTH,
|
||||
max = ValidationConstants.TITRE_MAX_LENGTH,
|
||||
message = ValidationConstants.TITRE_SIZE_MESSAGE)
|
||||
private String titre;
|
||||
|
||||
/** Description détaillée de l'événement */
|
||||
@Size(max = 1000, message = "La description ne peut pas dépasser 1000 caractères")
|
||||
@Size(
|
||||
max = ValidationConstants.DESCRIPTION_COURTE_MAX_LENGTH,
|
||||
message = ValidationConstants.DESCRIPTION_COURTE_SIZE_MESSAGE)
|
||||
private String description;
|
||||
|
||||
/** Type d'événement */
|
||||
@NotNull(message = "Le type d'événement est obligatoire")
|
||||
@Pattern(
|
||||
regexp =
|
||||
"^(ASSEMBLEE_GENERALE|FORMATION|ACTIVITE_SOCIALE|ACTION_CARITATIVE|REUNION_BUREAU|CONFERENCE|ATELIER|CEREMONIE|AUTRE)$",
|
||||
message = "Type d'événement invalide")
|
||||
private String typeEvenement;
|
||||
private TypeEvenementMetier typeEvenement;
|
||||
|
||||
/** Statut de l'événement */
|
||||
@NotNull(message = "Le statut est obligatoire")
|
||||
@Pattern(regexp = "^(PLANIFIE|EN_COURS|TERMINE|ANNULE|REPORTE)$", message = "Statut invalide")
|
||||
private String statut;
|
||||
private StatutEvenement statut;
|
||||
|
||||
/** Priorité de l'événement */
|
||||
@Pattern(regexp = "^(BASSE|NORMALE|HAUTE|CRITIQUE)$", message = "Priorité invalide")
|
||||
private String priorite;
|
||||
private PrioriteEvenement priorite;
|
||||
|
||||
/** Date de début de l'événement */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
@@ -140,17 +143,29 @@ public class EvenementDTO extends BaseDTO {
|
||||
private Integer participantsPresents;
|
||||
|
||||
/** Budget prévu pour l'événement */
|
||||
@DecimalMin(value = "0.0", message = "Le budget ne peut pas être négatif")
|
||||
@Digits(integer = 10, fraction = 2, message = "Format de budget invalide")
|
||||
@DecimalMin(
|
||||
value = ValidationConstants.MONTANT_MIN_VALUE,
|
||||
message = ValidationConstants.MONTANT_POSITIF_MESSAGE)
|
||||
@Digits(
|
||||
integer = ValidationConstants.MONTANT_INTEGER_DIGITS,
|
||||
fraction = ValidationConstants.MONTANT_FRACTION_DIGITS,
|
||||
message = ValidationConstants.MONTANT_DIGITS_MESSAGE)
|
||||
private BigDecimal budget;
|
||||
|
||||
/** Coût réel de l'événement */
|
||||
@DecimalMin(value = "0.0", message = "Le coût ne peut pas être négatif")
|
||||
@Digits(integer = 10, fraction = 2, message = "Format de coût invalide")
|
||||
@DecimalMin(
|
||||
value = ValidationConstants.MONTANT_MIN_VALUE,
|
||||
message = ValidationConstants.MONTANT_POSITIF_MESSAGE)
|
||||
@Digits(
|
||||
integer = ValidationConstants.MONTANT_INTEGER_DIGITS,
|
||||
fraction = ValidationConstants.MONTANT_FRACTION_DIGITS,
|
||||
message = ValidationConstants.MONTANT_DIGITS_MESSAGE)
|
||||
private BigDecimal coutReel;
|
||||
|
||||
/** Code de la devise */
|
||||
@Size(min = 3, max = 3, message = "Le code devise doit faire exactement 3 caractères")
|
||||
@Pattern(
|
||||
regexp = ValidationConstants.DEVISE_PATTERN,
|
||||
message = ValidationConstants.DEVISE_MESSAGE)
|
||||
private String codeDevise;
|
||||
|
||||
/** Indique si l'inscription est obligatoire */
|
||||
@@ -209,8 +224,8 @@ public class EvenementDTO extends BaseDTO {
|
||||
// Constructeurs
|
||||
public EvenementDTO() {
|
||||
super();
|
||||
this.statut = "PLANIFIE";
|
||||
this.priorite = "NORMALE";
|
||||
this.statut = StatutEvenement.PLANIFIE;
|
||||
this.priorite = PrioriteEvenement.NORMALE;
|
||||
this.participantsInscrits = 0;
|
||||
this.participantsPresents = 0;
|
||||
this.inscriptionObligatoire = false;
|
||||
@@ -219,7 +234,8 @@ public class EvenementDTO extends BaseDTO {
|
||||
this.codeDevise = "XOF"; // Franc CFA par défaut
|
||||
}
|
||||
|
||||
public EvenementDTO(String titre, String typeEvenement, LocalDate dateDebut, String lieu) {
|
||||
public EvenementDTO(
|
||||
String titre, TypeEvenementMetier typeEvenement, LocalDate dateDebut, String lieu) {
|
||||
this();
|
||||
this.titre = titre;
|
||||
this.typeEvenement = typeEvenement;
|
||||
@@ -244,27 +260,27 @@ public class EvenementDTO extends BaseDTO {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getTypeEvenement() {
|
||||
public TypeEvenementMetier getTypeEvenement() {
|
||||
return typeEvenement;
|
||||
}
|
||||
|
||||
public void setTypeEvenement(String typeEvenement) {
|
||||
public void setTypeEvenement(TypeEvenementMetier typeEvenement) {
|
||||
this.typeEvenement = typeEvenement;
|
||||
}
|
||||
|
||||
public String getStatut() {
|
||||
public StatutEvenement getStatut() {
|
||||
return statut;
|
||||
}
|
||||
|
||||
public void setStatut(String statut) {
|
||||
public void setStatut(StatutEvenement statut) {
|
||||
this.statut = statut;
|
||||
}
|
||||
|
||||
public String getPriorite() {
|
||||
public PrioriteEvenement getPriorite() {
|
||||
return priorite;
|
||||
}
|
||||
|
||||
public void setPriorite(String priorite) {
|
||||
public void setPriorite(PrioriteEvenement priorite) {
|
||||
this.priorite = priorite;
|
||||
}
|
||||
|
||||
@@ -555,8 +571,8 @@ public class EvenementDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si l'événement est actuellement en cours
|
||||
*/
|
||||
public boolean isEnCours() {
|
||||
return "EN_COURS".equals(statut);
|
||||
public boolean estEnCours() {
|
||||
return StatutEvenement.EN_COURS.equals(statut);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -564,8 +580,8 @@ public class EvenementDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si l'événement est terminé
|
||||
*/
|
||||
public boolean isTermine() {
|
||||
return "TERMINE".equals(statut);
|
||||
public boolean estTermine() {
|
||||
return StatutEvenement.TERMINE.equals(statut);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -573,8 +589,8 @@ public class EvenementDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si l'événement est annulé
|
||||
*/
|
||||
public boolean isAnnule() {
|
||||
return "ANNULE".equals(statut);
|
||||
public boolean estAnnule() {
|
||||
return StatutEvenement.ANNULE.equals(statut);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -582,7 +598,7 @@ public class EvenementDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si le nombre d'inscrits atteint la capacité maximale
|
||||
*/
|
||||
public boolean isComplet() {
|
||||
public boolean estComplet() {
|
||||
return capaciteMax != null
|
||||
&& participantsInscrits != null
|
||||
&& participantsInscrits >= capaciteMax;
|
||||
@@ -629,8 +645,8 @@ public class EvenementDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si les inscriptions sont ouvertes
|
||||
*/
|
||||
public boolean isInscriptionsOuvertes() {
|
||||
if (isAnnule() || isTermine()) {
|
||||
public boolean sontInscriptionsOuvertes() {
|
||||
if (estAnnule() || estTermine()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -638,7 +654,7 @@ public class EvenementDTO extends BaseDTO {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !isComplet();
|
||||
return !estComplet();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -659,7 +675,7 @@ public class EvenementDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si l'événement s'étend sur plusieurs jours
|
||||
*/
|
||||
public boolean isEvenementMultiJours() {
|
||||
public boolean estEvenementMultiJours() {
|
||||
return dateFin != null && !dateDebut.equals(dateFin);
|
||||
}
|
||||
|
||||
@@ -669,20 +685,7 @@ public class EvenementDTO extends BaseDTO {
|
||||
* @return Le libellé du type
|
||||
*/
|
||||
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;
|
||||
};
|
||||
return typeEvenement != null ? typeEvenement.getLibelle() : "Non défini";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -691,16 +694,7 @@ public class EvenementDTO extends BaseDTO {
|
||||
* @return Le libellé du statut
|
||||
*/
|
||||
public String getStatutLibelle() {
|
||||
if (statut == null) return "Non défini";
|
||||
|
||||
return switch (statut) {
|
||||
case "PLANIFIE" -> "Planifié";
|
||||
case "EN_COURS" -> "En cours";
|
||||
case "TERMINE" -> "Terminé";
|
||||
case "ANNULE" -> "Annulé";
|
||||
case "REPORTE" -> "Reporté";
|
||||
default -> statut;
|
||||
};
|
||||
return statut != null ? statut.getLibelle() : "Non défini";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -709,15 +703,7 @@ public class EvenementDTO extends BaseDTO {
|
||||
* @return Le libellé de la priorité
|
||||
*/
|
||||
public String getPrioriteLibelle() {
|
||||
if (priorite == null) return "Normale";
|
||||
|
||||
return switch (priorite) {
|
||||
case "BASSE" -> "Basse";
|
||||
case "NORMALE" -> "Normale";
|
||||
case "HAUTE" -> "Haute";
|
||||
case "CRITIQUE" -> "Critique";
|
||||
default -> priorite;
|
||||
};
|
||||
return priorite != null ? priorite.getLibelle() : "Normale";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -776,7 +762,7 @@ public class EvenementDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si le coût réel dépasse le budget
|
||||
*/
|
||||
public boolean isBudgetDepasse() {
|
||||
public boolean estBudgetDepasse() {
|
||||
return getEcartBudgetaire().compareTo(BigDecimal.ZERO) < 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import jakarta.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.UUID;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -449,7 +450,7 @@ public class CotisationDTO extends BaseDTO {
|
||||
if (dateEcheance == null || !isEnRetard()) {
|
||||
return 0;
|
||||
}
|
||||
return dateEcheance.until(LocalDate.now()).getDays();
|
||||
return ChronoUnit.DAYS.between(dateEcheance, LocalDate.now());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,6 +2,8 @@ package dev.lions.unionflow.server.api.dto.membre;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import dev.lions.unionflow.server.api.enums.membre.StatutMembre;
|
||||
import dev.lions.unionflow.server.api.validation.ValidationConstants;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
@@ -27,31 +29,39 @@ public class MembreDTO extends BaseDTO {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Numéro unique du membre (format: UF-YYYY-XXXXXXXX) */
|
||||
@NotBlank(message = "Le numéro de membre est obligatoire")
|
||||
@NotBlank(message = "Le numéro de membre" + ValidationConstants.OBLIGATOIRE_MESSAGE)
|
||||
@Pattern(
|
||||
regexp = "^UF-\\d{4}-[A-Z0-9]{8}$",
|
||||
message = "Format de numéro de membre invalide (UF-YYYY-XXXXXXXX)")
|
||||
regexp = ValidationConstants.NUMERO_MEMBRE_PATTERN,
|
||||
message = ValidationConstants.NUMERO_MEMBRE_MESSAGE)
|
||||
private String numeroMembre;
|
||||
|
||||
/** Nom de famille du membre */
|
||||
@NotBlank(message = "Le nom est obligatoire")
|
||||
@Size(min = 2, max = 50, message = "Le nom doit contenir entre 2 et 50 caractères")
|
||||
@NotBlank(message = "Le nom" + ValidationConstants.OBLIGATOIRE_MESSAGE)
|
||||
@Size(
|
||||
min = ValidationConstants.NOM_PRENOM_MIN_LENGTH,
|
||||
max = ValidationConstants.NOM_PRENOM_MAX_LENGTH,
|
||||
message = ValidationConstants.NOM_SIZE_MESSAGE)
|
||||
@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 */
|
||||
@NotBlank(message = "Le prénom est obligatoire")
|
||||
@Size(min = 2, max = 50, message = "Le prénom doit contenir entre 2 et 50 caractères")
|
||||
@NotBlank(message = "Le prénom" + ValidationConstants.OBLIGATOIRE_MESSAGE)
|
||||
@Size(
|
||||
min = ValidationConstants.NOM_PRENOM_MIN_LENGTH,
|
||||
max = ValidationConstants.NOM_PRENOM_MAX_LENGTH,
|
||||
message = ValidationConstants.PRENOM_SIZE_MESSAGE)
|
||||
@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 */
|
||||
@Email(message = "Format d'email invalide")
|
||||
@Size(max = 100, message = "L'email ne peut pas dépasser 100 caractères")
|
||||
@Email(message = ValidationConstants.EMAIL_FORMAT_MESSAGE)
|
||||
@Size(
|
||||
max = ValidationConstants.EMAIL_MAX_LENGTH,
|
||||
message = ValidationConstants.EMAIL_SIZE_MESSAGE)
|
||||
private String email;
|
||||
|
||||
/** Numéro de téléphone du membre */
|
||||
@@ -87,10 +97,9 @@ public class MembreDTO extends BaseDTO {
|
||||
@Size(max = 20, message = "Le type d'identité ne peut pas dépasser 20 caractères")
|
||||
private String typeIdentite;
|
||||
|
||||
/** Statut du membre (ACTIF, INACTIF, SUSPENDU, RADIE) */
|
||||
/** Statut du membre */
|
||||
@NotNull(message = "Le statut est obligatoire")
|
||||
@Pattern(regexp = "^(ACTIF|INACTIF|SUSPENDU|RADIE)$", message = "Statut invalide")
|
||||
private String statut;
|
||||
private StatutMembre statut;
|
||||
|
||||
/** Identifiant de l'association à laquelle appartient le membre */
|
||||
@NotNull(message = "L'association est obligatoire")
|
||||
@@ -132,7 +141,7 @@ public class MembreDTO extends BaseDTO {
|
||||
// Constructeurs
|
||||
public MembreDTO() {
|
||||
super();
|
||||
this.statut = "ACTIF";
|
||||
this.statut = StatutMembre.ACTIF;
|
||||
this.dateAdhesion = LocalDate.now();
|
||||
this.membreBureau = false;
|
||||
this.responsable = false;
|
||||
@@ -243,11 +252,11 @@ public class MembreDTO extends BaseDTO {
|
||||
this.typeIdentite = typeIdentite;
|
||||
}
|
||||
|
||||
public String getStatut() {
|
||||
public StatutMembre getStatut() {
|
||||
return statut;
|
||||
}
|
||||
|
||||
public void setStatut(String statut) {
|
||||
public void setStatut(StatutMembre statut) {
|
||||
this.statut = statut;
|
||||
}
|
||||
|
||||
@@ -354,7 +363,7 @@ public class MembreDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si le membre est majeur, false sinon
|
||||
*/
|
||||
public boolean isMajeur() {
|
||||
public boolean estMajeur() {
|
||||
if (dateNaissance == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -379,8 +388,8 @@ public class MembreDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si le statut est ACTIF
|
||||
*/
|
||||
public boolean isActif() {
|
||||
return "ACTIF".equals(statut);
|
||||
public boolean estActif() {
|
||||
return StatutMembre.ACTIF.equals(statut);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -398,15 +407,7 @@ public class MembreDTO extends BaseDTO {
|
||||
* @return Le libellé du statut
|
||||
*/
|
||||
public String getStatutLibelle() {
|
||||
if (statut == null) return "Non défini";
|
||||
|
||||
return switch (statut) {
|
||||
case "ACTIF" -> "Actif";
|
||||
case "INACTIF" -> "Inactif";
|
||||
case "SUSPENDU" -> "Suspendu";
|
||||
case "RADIE" -> "Radié";
|
||||
default -> statut;
|
||||
};
|
||||
return statut != null ? statut.getLibelle() : "Non défini";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -414,7 +415,7 @@ public class MembreDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si les données sont valides
|
||||
*/
|
||||
public boolean isDataValid() {
|
||||
public boolean sontDonneesValides() {
|
||||
return numeroMembre != null
|
||||
&& !numeroMembre.trim().isEmpty()
|
||||
&& nom != null
|
||||
@@ -422,7 +423,6 @@ public class MembreDTO extends BaseDTO {
|
||||
&& prenom != null
|
||||
&& !prenom.trim().isEmpty()
|
||||
&& statut != null
|
||||
&& !statut.trim().isEmpty()
|
||||
&& associationId != null;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,20 +5,19 @@ import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* DTO pour les critères de recherche avancée des membres
|
||||
* Permet de filtrer les membres selon de multiples critères
|
||||
*
|
||||
* DTO pour les critères de recherche avancée des membres Permet de filtrer les membres selon de
|
||||
* multiples critères
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-19
|
||||
@@ -30,200 +29,198 @@ import java.util.UUID;
|
||||
@Schema(description = "Critères de recherche avancée pour les membres")
|
||||
public class MembreSearchCriteria {
|
||||
|
||||
/** Terme de recherche général (nom, prénom, email) */
|
||||
@Schema(description = "Terme de recherche général dans nom, prénom ou email", example = "marie")
|
||||
@Size(max = 100, message = "Le terme de recherche ne peut pas dépasser 100 caractères")
|
||||
private String query;
|
||||
/** Terme de recherche général (nom, prénom, email) */
|
||||
@Schema(description = "Terme de recherche général dans nom, prénom ou email", example = "marie")
|
||||
@Size(max = 100, message = "Le terme de recherche ne peut pas dépasser 100 caractères")
|
||||
private String query;
|
||||
|
||||
/** Recherche par nom exact ou partiel */
|
||||
@Schema(description = "Filtre par nom (recherche partielle)", example = "Dupont")
|
||||
@Size(max = 50, message = "Le nom ne peut pas dépasser 50 caractères")
|
||||
private String nom;
|
||||
/** Recherche par nom exact ou partiel */
|
||||
@Schema(description = "Filtre par nom (recherche partielle)", example = "Dupont")
|
||||
@Size(max = 50, message = "Le nom ne peut pas dépasser 50 caractères")
|
||||
private String nom;
|
||||
|
||||
/** Recherche par prénom exact ou partiel */
|
||||
@Schema(description = "Filtre par prénom (recherche partielle)", example = "Marie")
|
||||
@Size(max = 50, message = "Le prénom ne peut pas dépasser 50 caractères")
|
||||
private String prenom;
|
||||
/** Recherche par prénom exact ou partiel */
|
||||
@Schema(description = "Filtre par prénom (recherche partielle)", example = "Marie")
|
||||
@Size(max = 50, message = "Le prénom ne peut pas dépasser 50 caractères")
|
||||
private String prenom;
|
||||
|
||||
/** Recherche par email exact ou partiel */
|
||||
@Schema(description = "Filtre par email (recherche partielle)", example = "@unionflow.com")
|
||||
@Size(max = 100, message = "L'email ne peut pas dépasser 100 caractères")
|
||||
private String email;
|
||||
/** Recherche par email exact ou partiel */
|
||||
@Schema(description = "Filtre par email (recherche partielle)", example = "@unionflow.com")
|
||||
@Size(max = 100, message = "L'email ne peut pas dépasser 100 caractères")
|
||||
private String email;
|
||||
|
||||
/** Filtre par numéro de téléphone */
|
||||
@Schema(description = "Filtre par numéro de téléphone", example = "+221")
|
||||
@Size(max = 20, message = "Le téléphone ne peut pas dépasser 20 caractères")
|
||||
private String telephone;
|
||||
/** Filtre par numéro de téléphone */
|
||||
@Schema(description = "Filtre par numéro de téléphone", example = "+221")
|
||||
@Size(max = 20, message = "Le téléphone ne peut pas dépasser 20 caractères")
|
||||
private String telephone;
|
||||
|
||||
/** Liste des IDs d'organisations */
|
||||
@Schema(description = "Liste des IDs d'organisations à inclure")
|
||||
private List<UUID> organisationIds;
|
||||
/** Liste des IDs d'organisations */
|
||||
@Schema(description = "Liste des IDs d'organisations à inclure")
|
||||
private List<UUID> organisationIds;
|
||||
|
||||
/** Liste des rôles à rechercher */
|
||||
@Schema(description = "Liste des rôles à rechercher", example = "[\"PRESIDENT\", \"SECRETAIRE\"]")
|
||||
private List<String> roles;
|
||||
/** Liste des rôles à rechercher */
|
||||
@Schema(description = "Liste des rôles à rechercher", example = "[\"PRESIDENT\", \"SECRETAIRE\"]")
|
||||
private List<String> roles;
|
||||
|
||||
/** Filtre par statut d'activité */
|
||||
@Schema(description = "Filtre par statut d'activité", example = "ACTIF")
|
||||
@Pattern(regexp = "^(ACTIF|INACTIF|SUSPENDU|RADIE)$", message = "Statut invalide")
|
||||
private String statut;
|
||||
/** Filtre par statut d'activité */
|
||||
@Schema(description = "Filtre par statut d'activité", example = "ACTIF")
|
||||
@Pattern(regexp = "^(ACTIF|INACTIF|SUSPENDU|RADIE)$", message = "Statut invalide")
|
||||
private String statut;
|
||||
|
||||
/** Date d'adhésion minimum */
|
||||
@Schema(description = "Date d'adhésion minimum", example = "2020-01-01")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate dateAdhesionMin;
|
||||
/** Date d'adhésion minimum */
|
||||
@Schema(description = "Date d'adhésion minimum", example = "2020-01-01")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate dateAdhesionMin;
|
||||
|
||||
/** Date d'adhésion maximum */
|
||||
@Schema(description = "Date d'adhésion maximum", example = "2025-12-31")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate dateAdhesionMax;
|
||||
/** Date d'adhésion maximum */
|
||||
@Schema(description = "Date d'adhésion maximum", example = "2025-12-31")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate dateAdhesionMax;
|
||||
|
||||
/** Âge minimum */
|
||||
@Schema(description = "Âge minimum", example = "18")
|
||||
@Min(value = 0, message = "L'âge minimum doit être positif")
|
||||
@Max(value = 120, message = "L'âge minimum ne peut pas dépasser 120 ans")
|
||||
private Integer ageMin;
|
||||
/** Âge minimum */
|
||||
@Schema(description = "Âge minimum", example = "18")
|
||||
@Min(value = 0, message = "L'âge minimum doit être positif")
|
||||
@Max(value = 120, message = "L'âge minimum ne peut pas dépasser 120 ans")
|
||||
private Integer ageMin;
|
||||
|
||||
/** Âge maximum */
|
||||
@Schema(description = "Âge maximum", example = "65")
|
||||
@Min(value = 0, message = "L'âge maximum doit être positif")
|
||||
@Max(value = 120, message = "L'âge maximum ne peut pas dépasser 120 ans")
|
||||
private Integer ageMax;
|
||||
/** Âge maximum */
|
||||
@Schema(description = "Âge maximum", example = "65")
|
||||
@Min(value = 0, message = "L'âge maximum doit être positif")
|
||||
@Max(value = 120, message = "L'âge maximum ne peut pas dépasser 120 ans")
|
||||
private Integer ageMax;
|
||||
|
||||
/** Filtre par région */
|
||||
@Schema(description = "Filtre par région", example = "Dakar")
|
||||
@Size(max = 50, message = "La région ne peut pas dépasser 50 caractères")
|
||||
private String region;
|
||||
/** Filtre par région */
|
||||
@Schema(description = "Filtre par région", example = "Dakar")
|
||||
@Size(max = 50, message = "La région ne peut pas dépasser 50 caractères")
|
||||
private String region;
|
||||
|
||||
/** Filtre par ville */
|
||||
@Schema(description = "Filtre par ville", example = "Dakar")
|
||||
@Size(max = 50, message = "La ville ne peut pas dépasser 50 caractères")
|
||||
private String ville;
|
||||
/** Filtre par ville */
|
||||
@Schema(description = "Filtre par ville", example = "Dakar")
|
||||
@Size(max = 50, message = "La ville ne peut pas dépasser 50 caractères")
|
||||
private String ville;
|
||||
|
||||
/** Filtre par profession */
|
||||
@Schema(description = "Filtre par profession", example = "Ingénieur")
|
||||
@Size(max = 100, message = "La profession ne peut pas dépasser 100 caractères")
|
||||
private String profession;
|
||||
/** Filtre par profession */
|
||||
@Schema(description = "Filtre par profession", example = "Ingénieur")
|
||||
@Size(max = 100, message = "La profession ne peut pas dépasser 100 caractères")
|
||||
private String profession;
|
||||
|
||||
/** Filtre par nationalité */
|
||||
@Schema(description = "Filtre par nationalité", example = "Sénégalaise")
|
||||
@Size(max = 50, message = "La nationalité ne peut pas dépasser 50 caractères")
|
||||
private String nationalite;
|
||||
/** Filtre par nationalité */
|
||||
@Schema(description = "Filtre par nationalité", example = "Sénégalaise")
|
||||
@Size(max = 50, message = "La nationalité ne peut pas dépasser 50 caractères")
|
||||
private String nationalite;
|
||||
|
||||
/** Filtre membres du bureau uniquement */
|
||||
@Schema(description = "Filtre pour les membres du bureau uniquement")
|
||||
private Boolean membreBureau;
|
||||
/** Filtre membres du bureau uniquement */
|
||||
@Schema(description = "Filtre pour les membres du bureau uniquement")
|
||||
private Boolean membreBureau;
|
||||
|
||||
/** Filtre responsables uniquement */
|
||||
@Schema(description = "Filtre pour les responsables uniquement")
|
||||
private Boolean responsable;
|
||||
/** Filtre responsables uniquement */
|
||||
@Schema(description = "Filtre pour les responsables uniquement")
|
||||
private Boolean responsable;
|
||||
|
||||
/** Inclure les membres inactifs dans la recherche */
|
||||
@Schema(description = "Inclure les membres inactifs", defaultValue = "false")
|
||||
@Builder.Default
|
||||
private Boolean includeInactifs = false;
|
||||
/** Inclure les membres inactifs dans la recherche */
|
||||
@Schema(description = "Inclure les membres inactifs", defaultValue = "false")
|
||||
@Builder.Default
|
||||
private Boolean includeInactifs = false;
|
||||
|
||||
/**
|
||||
* Vérifie si au moins un critère de recherche est défini
|
||||
*
|
||||
* @return true si au moins un critère est défini
|
||||
*/
|
||||
public boolean hasAnyCriteria() {
|
||||
return query != null && !query.trim().isEmpty() ||
|
||||
nom != null && !nom.trim().isEmpty() ||
|
||||
prenom != null && !prenom.trim().isEmpty() ||
|
||||
email != null && !email.trim().isEmpty() ||
|
||||
telephone != null && !telephone.trim().isEmpty() ||
|
||||
organisationIds != null && !organisationIds.isEmpty() ||
|
||||
roles != null && !roles.isEmpty() ||
|
||||
statut != null && !statut.trim().isEmpty() ||
|
||||
dateAdhesionMin != null ||
|
||||
dateAdhesionMax != null ||
|
||||
ageMin != null ||
|
||||
ageMax != null ||
|
||||
region != null && !region.trim().isEmpty() ||
|
||||
ville != null && !ville.trim().isEmpty() ||
|
||||
profession != null && !profession.trim().isEmpty() ||
|
||||
nationalite != null && !nationalite.trim().isEmpty() ||
|
||||
membreBureau != null ||
|
||||
responsable != null;
|
||||
/**
|
||||
* Vérifie si au moins un critère de recherche est défini
|
||||
*
|
||||
* @return true si au moins un critère est défini
|
||||
*/
|
||||
public boolean hasAnyCriteria() {
|
||||
return query != null && !query.trim().isEmpty()
|
||||
|| nom != null && !nom.trim().isEmpty()
|
||||
|| prenom != null && !prenom.trim().isEmpty()
|
||||
|| email != null && !email.trim().isEmpty()
|
||||
|| telephone != null && !telephone.trim().isEmpty()
|
||||
|| organisationIds != null && !organisationIds.isEmpty()
|
||||
|| roles != null && !roles.isEmpty()
|
||||
|| statut != null && !statut.trim().isEmpty()
|
||||
|| dateAdhesionMin != null
|
||||
|| dateAdhesionMax != null
|
||||
|| ageMin != null
|
||||
|| ageMax != null
|
||||
|| region != null && !region.trim().isEmpty()
|
||||
|| ville != null && !ville.trim().isEmpty()
|
||||
|| profession != null && !profession.trim().isEmpty()
|
||||
|| nationalite != null && !nationalite.trim().isEmpty()
|
||||
|| membreBureau != null
|
||||
|| responsable != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide la cohérence des critères de recherche
|
||||
*
|
||||
* @return true si les critères sont cohérents
|
||||
*/
|
||||
public boolean isValid() {
|
||||
// Validation des dates
|
||||
if (dateAdhesionMin != null && dateAdhesionMax != null) {
|
||||
if (dateAdhesionMin.isAfter(dateAdhesionMax)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide la cohérence des critères de recherche
|
||||
*
|
||||
* @return true si les critères sont cohérents
|
||||
*/
|
||||
public boolean isValid() {
|
||||
// Validation des dates
|
||||
if (dateAdhesionMin != null && dateAdhesionMax != null) {
|
||||
if (dateAdhesionMin.isAfter(dateAdhesionMax)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Validation des âges
|
||||
if (ageMin != null && ageMax != null) {
|
||||
if (ageMin > ageMax) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
// Validation des âges
|
||||
if (ageMin != null && ageMax != null) {
|
||||
if (ageMin > ageMax) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Nettoie les chaînes de caractères (trim et null si vide)
|
||||
*/
|
||||
public void sanitize() {
|
||||
query = sanitizeString(query);
|
||||
nom = sanitizeString(nom);
|
||||
prenom = sanitizeString(prenom);
|
||||
email = sanitizeString(email);
|
||||
telephone = sanitizeString(telephone);
|
||||
statut = sanitizeString(statut);
|
||||
region = sanitizeString(region);
|
||||
ville = sanitizeString(ville);
|
||||
profession = sanitizeString(profession);
|
||||
nationalite = sanitizeString(nationalite);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private String sanitizeString(String str) {
|
||||
if (str == null) return null;
|
||||
str = str.trim();
|
||||
return str.isEmpty() ? null : str;
|
||||
}
|
||||
/** Nettoie les chaînes de caractères (trim et null si vide) */
|
||||
public void sanitize() {
|
||||
query = sanitizeString(query);
|
||||
nom = sanitizeString(nom);
|
||||
prenom = sanitizeString(prenom);
|
||||
email = sanitizeString(email);
|
||||
telephone = sanitizeString(telephone);
|
||||
statut = sanitizeString(statut);
|
||||
region = sanitizeString(region);
|
||||
ville = sanitizeString(ville);
|
||||
profession = sanitizeString(profession);
|
||||
nationalite = sanitizeString(nationalite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne une description textuelle des critères actifs
|
||||
*
|
||||
* @return Description des critères
|
||||
*/
|
||||
public String getDescription() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (query != null) sb.append("Recherche: '").append(query).append("' ");
|
||||
if (nom != null) sb.append("Nom: '").append(nom).append("' ");
|
||||
if (prenom != null) sb.append("Prénom: '").append(prenom).append("' ");
|
||||
if (email != null) sb.append("Email: '").append(email).append("' ");
|
||||
if (statut != null) sb.append("Statut: ").append(statut).append(" ");
|
||||
if (organisationIds != null && !organisationIds.isEmpty()) {
|
||||
sb.append("Organisations: ").append(organisationIds.size()).append(" ");
|
||||
}
|
||||
if (roles != null && !roles.isEmpty()) {
|
||||
sb.append("Rôles: ").append(String.join(", ", roles)).append(" ");
|
||||
}
|
||||
if (dateAdhesionMin != null) sb.append("Adhésion >= ").append(dateAdhesionMin).append(" ");
|
||||
if (dateAdhesionMax != null) sb.append("Adhésion <= ").append(dateAdhesionMax).append(" ");
|
||||
if (ageMin != null) sb.append("Âge >= ").append(ageMin).append(" ");
|
||||
if (ageMax != null) sb.append("Âge <= ").append(ageMax).append(" ");
|
||||
if (region != null) sb.append("Région: '").append(region).append("' ");
|
||||
if (ville != null) sb.append("Ville: '").append(ville).append("' ");
|
||||
if (profession != null) sb.append("Profession: '").append(profession).append("' ");
|
||||
if (nationalite != null) sb.append("Nationalité: '").append(nationalite).append("' ");
|
||||
if (Boolean.TRUE.equals(membreBureau)) sb.append("Membre bureau ");
|
||||
if (Boolean.TRUE.equals(responsable)) sb.append("Responsable ");
|
||||
|
||||
return sb.toString().trim();
|
||||
private String sanitizeString(String str) {
|
||||
if (str == null) return null;
|
||||
str = str.trim();
|
||||
return str.isEmpty() ? null : str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne une description textuelle des critères actifs
|
||||
*
|
||||
* @return Description des critères
|
||||
*/
|
||||
public String getDescription() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (query != null) sb.append("Recherche: '").append(query).append("' ");
|
||||
if (nom != null) sb.append("Nom: '").append(nom).append("' ");
|
||||
if (prenom != null) sb.append("Prénom: '").append(prenom).append("' ");
|
||||
if (email != null) sb.append("Email: '").append(email).append("' ");
|
||||
if (statut != null) sb.append("Statut: ").append(statut).append(" ");
|
||||
if (organisationIds != null && !organisationIds.isEmpty()) {
|
||||
sb.append("Organisations: ").append(organisationIds.size()).append(" ");
|
||||
}
|
||||
if (roles != null && !roles.isEmpty()) {
|
||||
sb.append("Rôles: ").append(String.join(", ", roles)).append(" ");
|
||||
}
|
||||
if (dateAdhesionMin != null) sb.append("Adhésion >= ").append(dateAdhesionMin).append(" ");
|
||||
if (dateAdhesionMax != null) sb.append("Adhésion <= ").append(dateAdhesionMax).append(" ");
|
||||
if (ageMin != null) sb.append("Âge >= ").append(ageMin).append(" ");
|
||||
if (ageMax != null) sb.append("Âge <= ").append(ageMax).append(" ");
|
||||
if (region != null) sb.append("Région: '").append(region).append("' ");
|
||||
if (ville != null) sb.append("Ville: '").append(ville).append("' ");
|
||||
if (profession != null) sb.append("Profession: '").append(profession).append("' ");
|
||||
if (nationalite != null) sb.append("Nationalité: '").append(nationalite).append("' ");
|
||||
if (Boolean.TRUE.equals(membreBureau)) sb.append("Membre bureau ");
|
||||
if (Boolean.TRUE.equals(responsable)) sb.append("Responsable ");
|
||||
|
||||
return sb.toString().trim();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package dev.lions.unionflow.server.api.dto.membre;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.microprofile.openapi.annotations.media.Schema;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* DTO pour les résultats de recherche avancée des membres
|
||||
* Contient les résultats paginés et les métadonnées de recherche
|
||||
*
|
||||
* DTO pour les résultats de recherche avancée des membres Contient les résultats paginés et les
|
||||
* métadonnées de recherche
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-19
|
||||
@@ -23,182 +22,178 @@ import java.util.List;
|
||||
@Schema(description = "Résultats de recherche avancée des membres avec pagination")
|
||||
public class MembreSearchResultDTO {
|
||||
|
||||
/** Liste des membres trouvés */
|
||||
@Schema(description = "Liste des membres correspondant aux critères")
|
||||
private List<MembreDTO> membres;
|
||||
/** Liste des membres trouvés */
|
||||
@Schema(description = "Liste des membres correspondant aux critères")
|
||||
private List<MembreDTO> membres;
|
||||
|
||||
/** Nombre total de résultats (toutes pages confondues) */
|
||||
@Schema(description = "Nombre total de résultats trouvés", example = "247")
|
||||
private long totalElements;
|
||||
/** Nombre total de résultats (toutes pages confondues) */
|
||||
@Schema(description = "Nombre total de résultats trouvés", example = "247")
|
||||
private long totalElements;
|
||||
|
||||
/** Nombre total de pages */
|
||||
@Schema(description = "Nombre total de pages", example = "13")
|
||||
private int totalPages;
|
||||
/** Nombre total de pages */
|
||||
@Schema(description = "Nombre total de pages", example = "13")
|
||||
private int totalPages;
|
||||
|
||||
/** Numéro de la page actuelle (0-based) */
|
||||
@Schema(description = "Numéro de la page actuelle", example = "0")
|
||||
private int currentPage;
|
||||
/** Numéro de la page actuelle (0-based) */
|
||||
@Schema(description = "Numéro de la page actuelle", example = "0")
|
||||
private int currentPage;
|
||||
|
||||
/** Taille de la page */
|
||||
@Schema(description = "Nombre d'éléments par page", example = "20")
|
||||
private int pageSize;
|
||||
/** Taille de la page */
|
||||
@Schema(description = "Nombre d'éléments par page", example = "20")
|
||||
private int pageSize;
|
||||
|
||||
/** Nombre d'éléments sur la page actuelle */
|
||||
@Schema(description = "Nombre d'éléments sur cette page", example = "20")
|
||||
private int numberOfElements;
|
||||
/** Nombre d'éléments sur la page actuelle */
|
||||
@Schema(description = "Nombre d'éléments sur cette page", example = "20")
|
||||
private int numberOfElements;
|
||||
|
||||
/** Indique s'il y a une page suivante */
|
||||
@Schema(description = "Indique s'il y a une page suivante")
|
||||
private boolean hasNext;
|
||||
/** Indique s'il y a une page suivante */
|
||||
@Schema(description = "Indique s'il y a une page suivante")
|
||||
private boolean hasNext;
|
||||
|
||||
/** Indique s'il y a une page précédente */
|
||||
@Schema(description = "Indique s'il y a une page précédente")
|
||||
private boolean hasPrevious;
|
||||
/** Indique s'il y a une page précédente */
|
||||
@Schema(description = "Indique s'il y a une page précédente")
|
||||
private boolean hasPrevious;
|
||||
|
||||
/** Indique si c'est la première page */
|
||||
@Schema(description = "Indique si c'est la première page")
|
||||
private boolean isFirst;
|
||||
/** Indique si c'est la première page */
|
||||
@Schema(description = "Indique si c'est la première page")
|
||||
private boolean isFirst;
|
||||
|
||||
/** Indique si c'est la dernière page */
|
||||
@Schema(description = "Indique si c'est la dernière page")
|
||||
private boolean isLast;
|
||||
/** Indique si c'est la dernière page */
|
||||
@Schema(description = "Indique si c'est la dernière page")
|
||||
private boolean isLast;
|
||||
|
||||
/** Critères de recherche utilisés */
|
||||
@Schema(description = "Critères de recherche qui ont été appliqués")
|
||||
private MembreSearchCriteria criteria;
|
||||
/** Critères de recherche utilisés */
|
||||
@Schema(description = "Critères de recherche qui ont été appliqués")
|
||||
private MembreSearchCriteria criteria;
|
||||
|
||||
/** Temps d'exécution de la recherche en millisecondes */
|
||||
@Schema(description = "Temps d'exécution de la recherche en ms", example = "45")
|
||||
private long executionTimeMs;
|
||||
/** Temps d'exécution de la recherche en millisecondes */
|
||||
@Schema(description = "Temps d'exécution de la recherche en ms", example = "45")
|
||||
private long executionTimeMs;
|
||||
|
||||
/** Statistiques de recherche */
|
||||
@Schema(description = "Statistiques sur les résultats de recherche")
|
||||
private SearchStatistics statistics;
|
||||
/** Statistiques de recherche */
|
||||
@Schema(description = "Statistiques sur les résultats de recherche")
|
||||
private SearchStatistics statistics;
|
||||
|
||||
/**
|
||||
* Statistiques sur les résultats de recherche
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Schema(description = "Statistiques sur les résultats de recherche")
|
||||
public static class SearchStatistics {
|
||||
|
||||
/** Répartition par statut */
|
||||
@Schema(description = "Nombre de membres actifs dans les résultats")
|
||||
private long membresActifs;
|
||||
|
||||
@Schema(description = "Nombre de membres inactifs dans les résultats")
|
||||
private long membresInactifs;
|
||||
|
||||
/** Répartition par âge */
|
||||
@Schema(description = "Âge moyen des membres trouvés")
|
||||
private double ageMoyen;
|
||||
|
||||
@Schema(description = "Âge minimum des membres trouvés")
|
||||
private int ageMin;
|
||||
|
||||
@Schema(description = "Âge maximum des membres trouvés")
|
||||
private int ageMax;
|
||||
|
||||
/** Répartition par organisation */
|
||||
@Schema(description = "Nombre d'organisations représentées")
|
||||
private long nombreOrganisations;
|
||||
|
||||
/** Répartition par région */
|
||||
@Schema(description = "Nombre de régions représentées")
|
||||
private long nombreRegions;
|
||||
|
||||
/** Ancienneté moyenne */
|
||||
@Schema(description = "Ancienneté moyenne en années")
|
||||
private double ancienneteMoyenne;
|
||||
/** Statistiques sur les résultats de recherche */
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@Schema(description = "Statistiques sur les résultats de recherche")
|
||||
public static class SearchStatistics {
|
||||
|
||||
/** Répartition par statut */
|
||||
@Schema(description = "Nombre de membres actifs dans les résultats")
|
||||
private long membresActifs;
|
||||
|
||||
@Schema(description = "Nombre de membres inactifs dans les résultats")
|
||||
private long membresInactifs;
|
||||
|
||||
/** Répartition par âge */
|
||||
@Schema(description = "Âge moyen des membres trouvés")
|
||||
private double ageMoyen;
|
||||
|
||||
@Schema(description = "Âge minimum des membres trouvés")
|
||||
private int ageMin;
|
||||
|
||||
@Schema(description = "Âge maximum des membres trouvés")
|
||||
private int ageMax;
|
||||
|
||||
/** Répartition par organisation */
|
||||
@Schema(description = "Nombre d'organisations représentées")
|
||||
private long nombreOrganisations;
|
||||
|
||||
/** Répartition par région */
|
||||
@Schema(description = "Nombre de régions représentées")
|
||||
private long nombreRegions;
|
||||
|
||||
/** Ancienneté moyenne */
|
||||
@Schema(description = "Ancienneté moyenne en années")
|
||||
private double ancienneteMoyenne;
|
||||
}
|
||||
|
||||
/** Calcule et met à jour les indicateurs de pagination */
|
||||
public void calculatePaginationFlags() {
|
||||
this.isFirst = currentPage == 0;
|
||||
this.isLast = currentPage >= totalPages - 1;
|
||||
this.hasPrevious = currentPage > 0;
|
||||
this.hasNext = currentPage < totalPages - 1;
|
||||
this.numberOfElements = membres != null ? membres.size() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si les résultats sont vides
|
||||
*
|
||||
* @return true si aucun résultat
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return membres == null || membres.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le numéro de la page suivante (1-based pour affichage)
|
||||
*
|
||||
* @return Numéro de page suivante ou -1 si pas de page suivante
|
||||
*/
|
||||
public int getNextPageNumber() {
|
||||
return hasNext ? currentPage + 2 : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le numéro de la page précédente (1-based pour affichage)
|
||||
*
|
||||
* @return Numéro de page précédente ou -1 si pas de page précédente
|
||||
*/
|
||||
public int getPreviousPageNumber() {
|
||||
return hasPrevious ? currentPage : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne une description textuelle des résultats
|
||||
*
|
||||
* @return Description des résultats
|
||||
*/
|
||||
public String getResultDescription() {
|
||||
if (isEmpty()) {
|
||||
return "Aucun membre trouvé";
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule et met à jour les indicateurs de pagination
|
||||
*/
|
||||
public void calculatePaginationFlags() {
|
||||
this.isFirst = currentPage == 0;
|
||||
this.isLast = currentPage >= totalPages - 1;
|
||||
this.hasPrevious = currentPage > 0;
|
||||
this.hasNext = currentPage < totalPages - 1;
|
||||
this.numberOfElements = membres != null ? membres.size() : 0;
|
||||
if (totalElements == 1) {
|
||||
return "1 membre trouvé";
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si les résultats sont vides
|
||||
*
|
||||
* @return true si aucun résultat
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return membres == null || membres.isEmpty();
|
||||
if (totalPages == 1) {
|
||||
return String.format("%d membres trouvés", totalElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le numéro de la page suivante (1-based pour affichage)
|
||||
*
|
||||
* @return Numéro de page suivante ou -1 si pas de page suivante
|
||||
*/
|
||||
public int getNextPageNumber() {
|
||||
return hasNext ? currentPage + 2 : -1;
|
||||
}
|
||||
int startElement = currentPage * pageSize + 1;
|
||||
int endElement = Math.min(startElement + numberOfElements - 1, (int) totalElements);
|
||||
|
||||
/**
|
||||
* Retourne le numéro de la page précédente (1-based pour affichage)
|
||||
*
|
||||
* @return Numéro de page précédente ou -1 si pas de page précédente
|
||||
*/
|
||||
public int getPreviousPageNumber() {
|
||||
return hasPrevious ? currentPage : -1;
|
||||
}
|
||||
return String.format(
|
||||
"Membres %d-%d sur %d (page %d/%d)",
|
||||
startElement, endElement, totalElements, currentPage + 1, totalPages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne une description textuelle des résultats
|
||||
*
|
||||
* @return Description des résultats
|
||||
*/
|
||||
public String getResultDescription() {
|
||||
if (isEmpty()) {
|
||||
return "Aucun membre trouvé";
|
||||
}
|
||||
|
||||
if (totalElements == 1) {
|
||||
return "1 membre trouvé";
|
||||
}
|
||||
|
||||
if (totalPages == 1) {
|
||||
return String.format("%d membres trouvés", totalElements);
|
||||
}
|
||||
|
||||
int startElement = currentPage * pageSize + 1;
|
||||
int endElement = Math.min(startElement + numberOfElements - 1, (int) totalElements);
|
||||
|
||||
return String.format("Membres %d-%d sur %d (page %d/%d)",
|
||||
startElement, endElement, totalElements,
|
||||
currentPage + 1, totalPages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method pour créer un résultat vide
|
||||
*
|
||||
* @param criteria Critères de recherche
|
||||
* @return Résultat vide
|
||||
*/
|
||||
public static MembreSearchResultDTO empty(MembreSearchCriteria criteria) {
|
||||
return MembreSearchResultDTO.builder()
|
||||
.membres(List.of())
|
||||
.totalElements(0)
|
||||
.totalPages(0)
|
||||
.currentPage(0)
|
||||
.pageSize(20)
|
||||
.numberOfElements(0)
|
||||
.hasNext(false)
|
||||
.hasPrevious(false)
|
||||
.isFirst(true)
|
||||
.isLast(true)
|
||||
.criteria(criteria)
|
||||
.executionTimeMs(0)
|
||||
.build();
|
||||
}
|
||||
/**
|
||||
* Factory method pour créer un résultat vide
|
||||
*
|
||||
* @param criteria Critères de recherche
|
||||
* @return Résultat vide
|
||||
*/
|
||||
public static MembreSearchResultDTO empty(MembreSearchCriteria criteria) {
|
||||
MembreSearchResultDTO result = new MembreSearchResultDTO();
|
||||
result.setMembres(List.of());
|
||||
result.setTotalElements(0L);
|
||||
result.setTotalPages(0);
|
||||
result.setCurrentPage(0);
|
||||
result.setPageSize(20);
|
||||
result.setNumberOfElements(0);
|
||||
result.setHasNext(false);
|
||||
result.setHasPrevious(false);
|
||||
result.setFirst(true);
|
||||
result.setLast(true);
|
||||
result.setCriteria(criteria);
|
||||
result.setExecutionTimeMs(0L);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,426 +1,477 @@
|
||||
package dev.lions.unionflow.server.api.dto.notification;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* DTO pour les actions rapides des notifications UnionFlow
|
||||
*
|
||||
* Ce DTO représente une action que l'utilisateur peut exécuter directement
|
||||
* depuis la notification sans ouvrir l'application.
|
||||
*
|
||||
*
|
||||
* <p>Ce DTO représente une action que l'utilisateur peut exécuter directement depuis la
|
||||
* notification sans ouvrir l'application.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class ActionNotificationDTO {
|
||||
|
||||
/**
|
||||
* Identifiant unique de l'action
|
||||
*/
|
||||
@NotBlank(message = "L'identifiant de l'action est obligatoire")
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Libellé affiché sur le bouton d'action
|
||||
*/
|
||||
@NotBlank(message = "Le libellé de l'action est obligatoire")
|
||||
@Size(max = 30, message = "Le libellé ne peut pas dépasser 30 caractères")
|
||||
private String libelle;
|
||||
|
||||
/**
|
||||
* Description de l'action (tooltip)
|
||||
*/
|
||||
@Size(max = 100, message = "La description ne peut pas dépasser 100 caractères")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* Type d'action à exécuter
|
||||
*/
|
||||
@NotBlank(message = "Le type d'action est obligatoire")
|
||||
private String typeAction;
|
||||
|
||||
/**
|
||||
* Icône de l'action (Material Design)
|
||||
*/
|
||||
private String icone;
|
||||
|
||||
/**
|
||||
* Couleur de l'action (hexadécimal)
|
||||
*/
|
||||
private String couleur;
|
||||
|
||||
/**
|
||||
* URL à ouvrir (pour les actions de type "url")
|
||||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* Route de l'application à ouvrir (pour les actions de type "route")
|
||||
*/
|
||||
private String route;
|
||||
|
||||
/**
|
||||
* Paramètres de l'action
|
||||
*/
|
||||
private Map<String, String> parametres;
|
||||
|
||||
/**
|
||||
* Indique si l'action ferme la notification
|
||||
*/
|
||||
private Boolean fermeNotification;
|
||||
|
||||
/**
|
||||
* Indique si l'action nécessite une confirmation
|
||||
*/
|
||||
private Boolean necessiteConfirmation;
|
||||
|
||||
/**
|
||||
* Message de confirmation à afficher
|
||||
*/
|
||||
private String messageConfirmation;
|
||||
|
||||
/**
|
||||
* Indique si l'action est destructive (suppression, etc.)
|
||||
*/
|
||||
private Boolean estDestructive;
|
||||
|
||||
/**
|
||||
* Ordre d'affichage de l'action
|
||||
*/
|
||||
private Integer ordre;
|
||||
|
||||
/**
|
||||
* Indique si l'action est activée
|
||||
*/
|
||||
private Boolean estActivee;
|
||||
|
||||
/**
|
||||
* Condition d'affichage de l'action (expression)
|
||||
*/
|
||||
private String conditionAffichage;
|
||||
|
||||
/**
|
||||
* Rôles autorisés à exécuter cette action
|
||||
*/
|
||||
private String[] rolesAutorises;
|
||||
|
||||
/**
|
||||
* Permissions requises pour exécuter cette action
|
||||
*/
|
||||
private String[] permissionsRequises;
|
||||
|
||||
/**
|
||||
* Délai d'expiration de l'action en minutes
|
||||
*/
|
||||
private Integer delaiExpirationMinutes;
|
||||
|
||||
/**
|
||||
* Nombre maximum d'exécutions autorisées
|
||||
*/
|
||||
private Integer maxExecutions;
|
||||
|
||||
/**
|
||||
* Nombre d'exécutions actuelles
|
||||
*/
|
||||
private Integer nombreExecutions;
|
||||
|
||||
/**
|
||||
* Indique si l'action peut être exécutée plusieurs fois
|
||||
*/
|
||||
private Boolean peutEtreRepetee;
|
||||
|
||||
/**
|
||||
* Style du bouton (primary, secondary, outline, text)
|
||||
*/
|
||||
private String styleBouton;
|
||||
|
||||
/**
|
||||
* Taille du bouton (small, medium, large)
|
||||
*/
|
||||
private String tailleBouton;
|
||||
|
||||
/**
|
||||
* Position du bouton (left, center, right)
|
||||
*/
|
||||
private String positionBouton;
|
||||
|
||||
/**
|
||||
* Données personnalisées de l'action
|
||||
*/
|
||||
private Map<String, Object> donneesPersonnalisees;
|
||||
|
||||
// === CONSTRUCTEURS ===
|
||||
|
||||
/**
|
||||
* Constructeur par défaut
|
||||
*/
|
||||
public ActionNotificationDTO() {
|
||||
this.fermeNotification = true;
|
||||
this.necessiteConfirmation = false;
|
||||
this.estDestructive = false;
|
||||
this.ordre = 0;
|
||||
this.estActivee = true;
|
||||
this.maxExecutions = 1;
|
||||
this.nombreExecutions = 0;
|
||||
this.peutEtreRepetee = false;
|
||||
this.styleBouton = "primary";
|
||||
this.tailleBouton = "medium";
|
||||
this.positionBouton = "right";
|
||||
|
||||
/** Identifiant unique de l'action */
|
||||
@NotBlank(message = "L'identifiant de l'action est obligatoire")
|
||||
private String id;
|
||||
|
||||
/** Libellé affiché sur le bouton d'action */
|
||||
@NotBlank(message = "Le libellé de l'action est obligatoire")
|
||||
@Size(max = 30, message = "Le libellé ne peut pas dépasser 30 caractères")
|
||||
private String libelle;
|
||||
|
||||
/** Description de l'action (tooltip) */
|
||||
@Size(max = 100, message = "La description ne peut pas dépasser 100 caractères")
|
||||
private String description;
|
||||
|
||||
/** Type d'action à exécuter */
|
||||
@NotBlank(message = "Le type d'action est obligatoire")
|
||||
private String typeAction;
|
||||
|
||||
/** Icône de l'action (Material Design) */
|
||||
private String icone;
|
||||
|
||||
/** Couleur de l'action (hexadécimal) */
|
||||
private String couleur;
|
||||
|
||||
/** URL à ouvrir (pour les actions de type "url") */
|
||||
private String url;
|
||||
|
||||
/** Route de l'application à ouvrir (pour les actions de type "route") */
|
||||
private String route;
|
||||
|
||||
/** Paramètres de l'action */
|
||||
private Map<String, String> parametres;
|
||||
|
||||
/** Indique si l'action ferme la notification */
|
||||
private Boolean fermeNotification;
|
||||
|
||||
/** Indique si l'action nécessite une confirmation */
|
||||
private Boolean necessiteConfirmation;
|
||||
|
||||
/** Message de confirmation à afficher */
|
||||
private String messageConfirmation;
|
||||
|
||||
/** Indique si l'action est destructive (suppression, etc.) */
|
||||
private Boolean estDestructive;
|
||||
|
||||
/** Ordre d'affichage de l'action */
|
||||
private Integer ordre;
|
||||
|
||||
/** Indique si l'action est activée */
|
||||
private Boolean estActivee;
|
||||
|
||||
/** Condition d'affichage de l'action (expression) */
|
||||
private String conditionAffichage;
|
||||
|
||||
/** Rôles autorisés à exécuter cette action */
|
||||
private String[] rolesAutorises;
|
||||
|
||||
/** Permissions requises pour exécuter cette action */
|
||||
private String[] permissionsRequises;
|
||||
|
||||
/** Délai d'expiration de l'action en minutes */
|
||||
private Integer delaiExpirationMinutes;
|
||||
|
||||
/** Nombre maximum d'exécutions autorisées */
|
||||
private Integer maxExecutions;
|
||||
|
||||
/** Nombre d'exécutions actuelles */
|
||||
private Integer nombreExecutions;
|
||||
|
||||
/** Indique si l'action peut être exécutée plusieurs fois */
|
||||
private Boolean peutEtreRepetee;
|
||||
|
||||
/** Style du bouton (primary, secondary, outline, text) */
|
||||
private String styleBouton;
|
||||
|
||||
/** Taille du bouton (small, medium, large) */
|
||||
private String tailleBouton;
|
||||
|
||||
/** Position du bouton (left, center, right) */
|
||||
private String positionBouton;
|
||||
|
||||
/** Données personnalisées de l'action */
|
||||
private Map<String, Object> donneesPersonnalisees;
|
||||
|
||||
// === CONSTRUCTEURS ===
|
||||
|
||||
/** Constructeur par défaut */
|
||||
public ActionNotificationDTO() {
|
||||
this.fermeNotification = true;
|
||||
this.necessiteConfirmation = false;
|
||||
this.estDestructive = false;
|
||||
this.ordre = 0;
|
||||
this.estActivee = true;
|
||||
this.maxExecutions = 1;
|
||||
this.nombreExecutions = 0;
|
||||
this.peutEtreRepetee = false;
|
||||
this.styleBouton = "primary";
|
||||
this.tailleBouton = "medium";
|
||||
this.positionBouton = "right";
|
||||
}
|
||||
|
||||
/** Constructeur avec paramètres essentiels */
|
||||
public ActionNotificationDTO(String id, String libelle, String typeAction) {
|
||||
this();
|
||||
this.id = id;
|
||||
this.libelle = libelle;
|
||||
this.typeAction = typeAction;
|
||||
}
|
||||
|
||||
/** Constructeur pour action URL */
|
||||
public ActionNotificationDTO(String id, String libelle, String url, String icone) {
|
||||
this(id, libelle, "url");
|
||||
this.url = url;
|
||||
this.icone = icone;
|
||||
}
|
||||
|
||||
/** Constructeur pour action de route */
|
||||
public ActionNotificationDTO(
|
||||
String id, String libelle, String route, String icone, Map<String, String> parametres) {
|
||||
this(id, libelle, "route");
|
||||
this.route = route;
|
||||
this.icone = icone;
|
||||
this.parametres = parametres;
|
||||
}
|
||||
|
||||
// === GETTERS ET SETTERS ===
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
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 String getTypeAction() {
|
||||
return typeAction;
|
||||
}
|
||||
|
||||
public void setTypeAction(String typeAction) {
|
||||
this.typeAction = typeAction;
|
||||
}
|
||||
|
||||
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 getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getRoute() {
|
||||
return route;
|
||||
}
|
||||
|
||||
public void setRoute(String route) {
|
||||
this.route = route;
|
||||
}
|
||||
|
||||
public Map<String, String> getParametres() {
|
||||
return parametres;
|
||||
}
|
||||
|
||||
public void setParametres(Map<String, String> parametres) {
|
||||
this.parametres = parametres;
|
||||
}
|
||||
|
||||
public Boolean getFermeNotification() {
|
||||
return fermeNotification;
|
||||
}
|
||||
|
||||
public void setFermeNotification(Boolean fermeNotification) {
|
||||
this.fermeNotification = fermeNotification;
|
||||
}
|
||||
|
||||
public Boolean getNecessiteConfirmation() {
|
||||
return necessiteConfirmation;
|
||||
}
|
||||
|
||||
public void setNecessiteConfirmation(Boolean necessiteConfirmation) {
|
||||
this.necessiteConfirmation = necessiteConfirmation;
|
||||
}
|
||||
|
||||
public String getMessageConfirmation() {
|
||||
return messageConfirmation;
|
||||
}
|
||||
|
||||
public void setMessageConfirmation(String messageConfirmation) {
|
||||
this.messageConfirmation = messageConfirmation;
|
||||
}
|
||||
|
||||
public Boolean getEstDestructive() {
|
||||
return estDestructive;
|
||||
}
|
||||
|
||||
public void setEstDestructive(Boolean estDestructive) {
|
||||
this.estDestructive = estDestructive;
|
||||
}
|
||||
|
||||
public Integer getOrdre() {
|
||||
return ordre;
|
||||
}
|
||||
|
||||
public void setOrdre(Integer ordre) {
|
||||
this.ordre = ordre;
|
||||
}
|
||||
|
||||
public Boolean getEstActivee() {
|
||||
return estActivee;
|
||||
}
|
||||
|
||||
public void setEstActivee(Boolean estActivee) {
|
||||
this.estActivee = estActivee;
|
||||
}
|
||||
|
||||
public String getConditionAffichage() {
|
||||
return conditionAffichage;
|
||||
}
|
||||
|
||||
public void setConditionAffichage(String conditionAffichage) {
|
||||
this.conditionAffichage = conditionAffichage;
|
||||
}
|
||||
|
||||
public String[] getRolesAutorises() {
|
||||
return rolesAutorises;
|
||||
}
|
||||
|
||||
public void setRolesAutorises(String[] rolesAutorises) {
|
||||
this.rolesAutorises = rolesAutorises;
|
||||
}
|
||||
|
||||
public String[] getPermissionsRequises() {
|
||||
return permissionsRequises;
|
||||
}
|
||||
|
||||
public void setPermissionsRequises(String[] permissionsRequises) {
|
||||
this.permissionsRequises = permissionsRequises;
|
||||
}
|
||||
|
||||
public Integer getDelaiExpirationMinutes() {
|
||||
return delaiExpirationMinutes;
|
||||
}
|
||||
|
||||
public void setDelaiExpirationMinutes(Integer delaiExpirationMinutes) {
|
||||
this.delaiExpirationMinutes = delaiExpirationMinutes;
|
||||
}
|
||||
|
||||
public Integer getMaxExecutions() {
|
||||
return maxExecutions;
|
||||
}
|
||||
|
||||
public void setMaxExecutions(Integer maxExecutions) {
|
||||
this.maxExecutions = maxExecutions;
|
||||
}
|
||||
|
||||
public Integer getNombreExecutions() {
|
||||
return nombreExecutions;
|
||||
}
|
||||
|
||||
public void setNombreExecutions(Integer nombreExecutions) {
|
||||
this.nombreExecutions = nombreExecutions;
|
||||
}
|
||||
|
||||
public Boolean getPeutEtreRepetee() {
|
||||
return peutEtreRepetee;
|
||||
}
|
||||
|
||||
public void setPeutEtreRepetee(Boolean peutEtreRepetee) {
|
||||
this.peutEtreRepetee = peutEtreRepetee;
|
||||
}
|
||||
|
||||
public String getStyleBouton() {
|
||||
return styleBouton;
|
||||
}
|
||||
|
||||
public void setStyleBouton(String styleBouton) {
|
||||
this.styleBouton = styleBouton;
|
||||
}
|
||||
|
||||
public String getTailleBouton() {
|
||||
return tailleBouton;
|
||||
}
|
||||
|
||||
public void setTailleBouton(String tailleBouton) {
|
||||
this.tailleBouton = tailleBouton;
|
||||
}
|
||||
|
||||
public String getPositionBouton() {
|
||||
return positionBouton;
|
||||
}
|
||||
|
||||
public void setPositionBouton(String positionBouton) {
|
||||
this.positionBouton = positionBouton;
|
||||
}
|
||||
|
||||
public Map<String, Object> getDonneesPersonnalisees() {
|
||||
return donneesPersonnalisees;
|
||||
}
|
||||
|
||||
public void setDonneesPersonnalisees(Map<String, Object> donneesPersonnalisees) {
|
||||
this.donneesPersonnalisees = donneesPersonnalisees;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/** Vérifie si l'action peut être exécutée */
|
||||
public boolean peutEtreExecutee() {
|
||||
return estActivee && (nombreExecutions < maxExecutions || peutEtreRepetee);
|
||||
}
|
||||
|
||||
/** Vérifie si l'action est expirée */
|
||||
public boolean isExpiree() {
|
||||
// Implémentation basée sur delaiExpirationMinutes et date de création de la notification
|
||||
return false; // À implémenter selon la logique métier
|
||||
}
|
||||
|
||||
/** Incrémente le nombre d'exécutions */
|
||||
public void incrementerExecutions() {
|
||||
if (nombreExecutions == null) {
|
||||
nombreExecutions = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec paramètres essentiels
|
||||
*/
|
||||
public ActionNotificationDTO(String id, String libelle, String typeAction) {
|
||||
this();
|
||||
this.id = id;
|
||||
this.libelle = libelle;
|
||||
this.typeAction = typeAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur pour action URL
|
||||
*/
|
||||
public ActionNotificationDTO(String id, String libelle, String url, String icone) {
|
||||
this(id, libelle, "url");
|
||||
this.url = url;
|
||||
this.icone = icone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur pour action de route
|
||||
*/
|
||||
public ActionNotificationDTO(String id, String libelle, String route, String icone, Map<String, String> parametres) {
|
||||
this(id, libelle, "route");
|
||||
this.route = route;
|
||||
this.icone = icone;
|
||||
this.parametres = parametres;
|
||||
}
|
||||
|
||||
// === GETTERS ET SETTERS ===
|
||||
|
||||
public String getId() { return id; }
|
||||
public void setId(String id) { this.id = id; }
|
||||
|
||||
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 String getTypeAction() { return typeAction; }
|
||||
public void setTypeAction(String typeAction) { this.typeAction = typeAction; }
|
||||
|
||||
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 getUrl() { return url; }
|
||||
public void setUrl(String url) { this.url = url; }
|
||||
|
||||
public String getRoute() { return route; }
|
||||
public void setRoute(String route) { this.route = route; }
|
||||
|
||||
public Map<String, String> getParametres() { return parametres; }
|
||||
public void setParametres(Map<String, String> parametres) { this.parametres = parametres; }
|
||||
|
||||
public Boolean getFermeNotification() { return fermeNotification; }
|
||||
public void setFermeNotification(Boolean fermeNotification) { this.fermeNotification = fermeNotification; }
|
||||
|
||||
public Boolean getNecessiteConfirmation() { return necessiteConfirmation; }
|
||||
public void setNecessiteConfirmation(Boolean necessiteConfirmation) { this.necessiteConfirmation = necessiteConfirmation; }
|
||||
|
||||
public String getMessageConfirmation() { return messageConfirmation; }
|
||||
public void setMessageConfirmation(String messageConfirmation) { this.messageConfirmation = messageConfirmation; }
|
||||
|
||||
public Boolean getEstDestructive() { return estDestructive; }
|
||||
public void setEstDestructive(Boolean estDestructive) { this.estDestructive = estDestructive; }
|
||||
|
||||
public Integer getOrdre() { return ordre; }
|
||||
public void setOrdre(Integer ordre) { this.ordre = ordre; }
|
||||
|
||||
public Boolean getEstActivee() { return estActivee; }
|
||||
public void setEstActivee(Boolean estActivee) { this.estActivee = estActivee; }
|
||||
|
||||
public String getConditionAffichage() { return conditionAffichage; }
|
||||
public void setConditionAffichage(String conditionAffichage) { this.conditionAffichage = conditionAffichage; }
|
||||
|
||||
public String[] getRolesAutorises() { return rolesAutorises; }
|
||||
public void setRolesAutorises(String[] rolesAutorises) { this.rolesAutorises = rolesAutorises; }
|
||||
|
||||
public String[] getPermissionsRequises() { return permissionsRequises; }
|
||||
public void setPermissionsRequises(String[] permissionsRequises) { this.permissionsRequises = permissionsRequises; }
|
||||
|
||||
public Integer getDelaiExpirationMinutes() { return delaiExpirationMinutes; }
|
||||
public void setDelaiExpirationMinutes(Integer delaiExpirationMinutes) { this.delaiExpirationMinutes = delaiExpirationMinutes; }
|
||||
|
||||
public Integer getMaxExecutions() { return maxExecutions; }
|
||||
public void setMaxExecutions(Integer maxExecutions) { this.maxExecutions = maxExecutions; }
|
||||
|
||||
public Integer getNombreExecutions() { return nombreExecutions; }
|
||||
public void setNombreExecutions(Integer nombreExecutions) { this.nombreExecutions = nombreExecutions; }
|
||||
|
||||
public Boolean getPeutEtreRepetee() { return peutEtreRepetee; }
|
||||
public void setPeutEtreRepetee(Boolean peutEtreRepetee) { this.peutEtreRepetee = peutEtreRepetee; }
|
||||
|
||||
public String getStyleBouton() { return styleBouton; }
|
||||
public void setStyleBouton(String styleBouton) { this.styleBouton = styleBouton; }
|
||||
|
||||
public String getTailleBouton() { return tailleBouton; }
|
||||
public void setTailleBouton(String tailleBouton) { this.tailleBouton = tailleBouton; }
|
||||
|
||||
public String getPositionBouton() { return positionBouton; }
|
||||
public void setPositionBouton(String positionBouton) { this.positionBouton = positionBouton; }
|
||||
|
||||
public Map<String, Object> getDonneesPersonnalisees() { return donneesPersonnalisees; }
|
||||
public void setDonneesPersonnalisees(Map<String, Object> donneesPersonnalisees) {
|
||||
this.donneesPersonnalisees = donneesPersonnalisees;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Vérifie si l'action peut être exécutée
|
||||
*/
|
||||
public boolean peutEtreExecutee() {
|
||||
return estActivee && (nombreExecutions < maxExecutions || peutEtreRepetee);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'action est expirée
|
||||
*/
|
||||
public boolean isExpiree() {
|
||||
// Implémentation basée sur delaiExpirationMinutes et date de création de la notification
|
||||
return false; // À implémenter selon la logique métier
|
||||
}
|
||||
|
||||
/**
|
||||
* Incrémente le nombre d'exécutions
|
||||
*/
|
||||
public void incrementerExecutions() {
|
||||
if (nombreExecutions == null) {
|
||||
nombreExecutions = 0;
|
||||
nombreExecutions++;
|
||||
}
|
||||
|
||||
/** Vérifie si l'utilisateur a les permissions requises */
|
||||
public boolean utilisateurAutorise(String[] rolesUtilisateur, String[] permissionsUtilisateur) {
|
||||
// Vérification des rôles
|
||||
if (rolesAutorises != null && rolesAutorises.length > 0) {
|
||||
boolean roleAutorise = false;
|
||||
for (String roleRequis : rolesAutorises) {
|
||||
for (String roleUtilisateur : rolesUtilisateur) {
|
||||
if (roleRequis.equals(roleUtilisateur)) {
|
||||
roleAutorise = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
nombreExecutions++;
|
||||
if (roleAutorise) break;
|
||||
}
|
||||
if (!roleAutorise) return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'utilisateur a les permissions requises
|
||||
*/
|
||||
public boolean utilisateurAutorise(String[] rolesUtilisateur, String[] permissionsUtilisateur) {
|
||||
// Vérification des rôles
|
||||
if (rolesAutorises != null && rolesAutorises.length > 0) {
|
||||
boolean roleAutorise = false;
|
||||
for (String roleRequis : rolesAutorises) {
|
||||
for (String roleUtilisateur : rolesUtilisateur) {
|
||||
if (roleRequis.equals(roleUtilisateur)) {
|
||||
roleAutorise = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (roleAutorise) break;
|
||||
}
|
||||
if (!roleAutorise) return false;
|
||||
|
||||
// Vérification des permissions
|
||||
if (permissionsRequises != null && permissionsRequises.length > 0) {
|
||||
boolean permissionAutorisee = false;
|
||||
for (String permissionRequise : permissionsRequises) {
|
||||
for (String permissionUtilisateur : permissionsUtilisateur) {
|
||||
if (permissionRequise.equals(permissionUtilisateur)) {
|
||||
permissionAutorisee = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Vérification des permissions
|
||||
if (permissionsRequises != null && permissionsRequises.length > 0) {
|
||||
boolean permissionAutorisee = false;
|
||||
for (String permissionRequise : permissionsRequises) {
|
||||
for (String permissionUtilisateur : permissionsUtilisateur) {
|
||||
if (permissionRequise.equals(permissionUtilisateur)) {
|
||||
permissionAutorisee = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (permissionAutorisee) break;
|
||||
}
|
||||
if (!permissionAutorisee) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur par défaut selon le type d'action
|
||||
*/
|
||||
public String getCouleurParDefaut() {
|
||||
if (couleur != null) return couleur;
|
||||
|
||||
return switch (typeAction) {
|
||||
case "confirm" -> "#4CAF50"; // Vert pour confirmation
|
||||
case "cancel" -> "#F44336"; // Rouge pour annulation
|
||||
case "info" -> "#2196F3"; // Bleu pour information
|
||||
case "warning" -> "#FF9800"; // Orange pour avertissement
|
||||
case "url", "route" -> "#2196F3"; // Bleu pour navigation
|
||||
default -> "#9E9E9E"; // Gris par défaut
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône par défaut selon le type d'action
|
||||
*/
|
||||
public String getIconeParDefaut() {
|
||||
if (icone != null) return icone;
|
||||
|
||||
return switch (typeAction) {
|
||||
case "confirm" -> "check";
|
||||
case "cancel" -> "close";
|
||||
case "info" -> "info";
|
||||
case "warning" -> "warning";
|
||||
case "url" -> "open_in_new";
|
||||
case "route" -> "arrow_forward";
|
||||
case "call" -> "phone";
|
||||
case "message" -> "message";
|
||||
case "email" -> "email";
|
||||
case "share" -> "share";
|
||||
default -> "touch_app";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une action de confirmation
|
||||
*/
|
||||
public static ActionNotificationDTO creerActionConfirmation(String id, String libelle) {
|
||||
ActionNotificationDTO action = new ActionNotificationDTO(id, libelle, "confirm");
|
||||
action.setCouleur("#4CAF50");
|
||||
action.setIcone("check");
|
||||
action.setStyleBouton("primary");
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une action d'annulation
|
||||
*/
|
||||
public static ActionNotificationDTO creerActionAnnulation(String id, String libelle) {
|
||||
ActionNotificationDTO action = new ActionNotificationDTO(id, libelle, "cancel");
|
||||
action.setCouleur("#F44336");
|
||||
action.setIcone("close");
|
||||
action.setStyleBouton("outline");
|
||||
action.setEstDestructive(true);
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une action de navigation
|
||||
*/
|
||||
public static ActionNotificationDTO creerActionNavigation(String id, String libelle, String route) {
|
||||
ActionNotificationDTO action = new ActionNotificationDTO(id, libelle, "route");
|
||||
action.setRoute(route);
|
||||
action.setCouleur("#2196F3");
|
||||
action.setIcone("arrow_forward");
|
||||
return action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("ActionNotificationDTO{id='%s', libelle='%s', type='%s'}",
|
||||
id, libelle, typeAction);
|
||||
if (permissionAutorisee) break;
|
||||
}
|
||||
if (!permissionAutorisee) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Retourne la couleur par défaut selon le type d'action */
|
||||
public String getCouleurParDefaut() {
|
||||
if (couleur != null) return couleur;
|
||||
|
||||
return switch (typeAction) {
|
||||
case "confirm" -> "#4CAF50"; // Vert pour confirmation
|
||||
case "cancel" -> "#F44336"; // Rouge pour annulation
|
||||
case "info" -> "#2196F3"; // Bleu pour information
|
||||
case "warning" -> "#FF9800"; // Orange pour avertissement
|
||||
case "url", "route" -> "#2196F3"; // Bleu pour navigation
|
||||
default -> "#9E9E9E"; // Gris par défaut
|
||||
};
|
||||
}
|
||||
|
||||
/** Retourne l'icône par défaut selon le type d'action */
|
||||
public String getIconeParDefaut() {
|
||||
if (icone != null) return icone;
|
||||
|
||||
return switch (typeAction) {
|
||||
case "confirm" -> "check";
|
||||
case "cancel" -> "close";
|
||||
case "info" -> "info";
|
||||
case "warning" -> "warning";
|
||||
case "url" -> "open_in_new";
|
||||
case "route" -> "arrow_forward";
|
||||
case "call" -> "phone";
|
||||
case "message" -> "message";
|
||||
case "email" -> "email";
|
||||
case "share" -> "share";
|
||||
default -> "touch_app";
|
||||
};
|
||||
}
|
||||
|
||||
/** Crée une action de confirmation */
|
||||
public static ActionNotificationDTO creerActionConfirmation(String id, String libelle) {
|
||||
ActionNotificationDTO action = new ActionNotificationDTO(id, libelle, "confirm");
|
||||
action.setCouleur("#4CAF50");
|
||||
action.setIcone("check");
|
||||
action.setStyleBouton("primary");
|
||||
return action;
|
||||
}
|
||||
|
||||
/** Crée une action d'annulation */
|
||||
public static ActionNotificationDTO creerActionAnnulation(String id, String libelle) {
|
||||
ActionNotificationDTO action = new ActionNotificationDTO(id, libelle, "cancel");
|
||||
action.setCouleur("#F44336");
|
||||
action.setIcone("close");
|
||||
action.setStyleBouton("outline");
|
||||
action.setEstDestructive(true);
|
||||
return action;
|
||||
}
|
||||
|
||||
/** Crée une action de navigation */
|
||||
public static ActionNotificationDTO creerActionNavigation(
|
||||
String id, String libelle, String route) {
|
||||
ActionNotificationDTO action = new ActionNotificationDTO(id, libelle, "route");
|
||||
action.setRoute(route);
|
||||
action.setCouleur("#2196F3");
|
||||
action.setIcone("arrow_forward");
|
||||
return action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"ActionNotificationDTO{id='%s', libelle='%s', type='%s'}", id, libelle, typeAction);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,88 +5,115 @@ import jakarta.validation.constraints.*;
|
||||
|
||||
/**
|
||||
* DTO pour les préférences spécifiques à un canal de notification
|
||||
*
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PreferenceCanalNotificationDTO {
|
||||
|
||||
/**
|
||||
* Indique si ce canal est activé
|
||||
*/
|
||||
private Boolean active;
|
||||
|
||||
/**
|
||||
* Niveau d'importance personnalisé (1-5)
|
||||
*/
|
||||
@Min(value = 1, message = "L'importance doit être comprise entre 1 et 5")
|
||||
@Max(value = 5, message = "L'importance doit être comprise entre 1 et 5")
|
||||
private Integer importance;
|
||||
|
||||
/**
|
||||
* Son personnalisé pour ce canal
|
||||
*/
|
||||
private String sonPersonnalise;
|
||||
|
||||
/**
|
||||
* Pattern de vibration personnalisé
|
||||
*/
|
||||
private long[] patternVibration;
|
||||
|
||||
/**
|
||||
* Couleur LED personnalisée
|
||||
*/
|
||||
private String couleurLED;
|
||||
|
||||
/**
|
||||
* Indique si le son est activé pour ce canal
|
||||
*/
|
||||
private Boolean sonActive;
|
||||
|
||||
/**
|
||||
* Indique si la vibration est activée pour ce canal
|
||||
*/
|
||||
private Boolean vibrationActive;
|
||||
|
||||
/**
|
||||
* Indique si la LED est activée pour ce canal
|
||||
*/
|
||||
private Boolean ledActive;
|
||||
|
||||
/**
|
||||
* Indique si ce canal peut être désactivé par l'utilisateur
|
||||
*/
|
||||
private Boolean peutEtreDesactive;
|
||||
|
||||
// Constructeurs, getters et setters
|
||||
public PreferenceCanalNotificationDTO() {}
|
||||
|
||||
public Boolean getActive() { return active; }
|
||||
public void setActive(Boolean active) { this.active = active; }
|
||||
|
||||
public Integer getImportance() { return importance; }
|
||||
public void setImportance(Integer importance) { this.importance = importance; }
|
||||
|
||||
public String getSonPersonnalise() { return sonPersonnalise; }
|
||||
public void setSonPersonnalise(String sonPersonnalise) { this.sonPersonnalise = sonPersonnalise; }
|
||||
|
||||
public long[] getPatternVibration() { return patternVibration; }
|
||||
public void setPatternVibration(long[] patternVibration) { this.patternVibration = patternVibration; }
|
||||
|
||||
public String getCouleurLED() { return couleurLED; }
|
||||
public void setCouleurLED(String couleurLED) { this.couleurLED = couleurLED; }
|
||||
|
||||
public Boolean getSonActive() { return sonActive; }
|
||||
public void setSonActive(Boolean sonActive) { this.sonActive = sonActive; }
|
||||
|
||||
public Boolean getVibrationActive() { return vibrationActive; }
|
||||
public void setVibrationActive(Boolean vibrationActive) { this.vibrationActive = vibrationActive; }
|
||||
|
||||
public Boolean getLedActive() { return ledActive; }
|
||||
public void setLedActive(Boolean ledActive) { this.ledActive = ledActive; }
|
||||
|
||||
public Boolean getPeutEtreDesactive() { return peutEtreDesactive; }
|
||||
public void setPeutEtreDesactive(Boolean peutEtreDesactive) { this.peutEtreDesactive = peutEtreDesactive; }
|
||||
|
||||
/** Indique si ce canal est activé */
|
||||
private Boolean active;
|
||||
|
||||
/** Niveau d'importance personnalisé (1-5) */
|
||||
@Min(value = 1, message = "L'importance doit être comprise entre 1 et 5")
|
||||
@Max(value = 5, message = "L'importance doit être comprise entre 1 et 5")
|
||||
private Integer importance;
|
||||
|
||||
/** Son personnalisé pour ce canal */
|
||||
private String sonPersonnalise;
|
||||
|
||||
/** Pattern de vibration personnalisé */
|
||||
private long[] patternVibration;
|
||||
|
||||
/** Couleur LED personnalisée */
|
||||
private String couleurLED;
|
||||
|
||||
/** Indique si le son est activé pour ce canal */
|
||||
private Boolean sonActive;
|
||||
|
||||
/** Indique si la vibration est activée pour ce canal */
|
||||
private Boolean vibrationActive;
|
||||
|
||||
/** Indique si la LED est activée pour ce canal */
|
||||
private Boolean ledActive;
|
||||
|
||||
/** Indique si ce canal peut être désactivé par l'utilisateur */
|
||||
private Boolean peutEtreDesactive;
|
||||
|
||||
// Constructeurs, getters et setters
|
||||
public PreferenceCanalNotificationDTO() {}
|
||||
|
||||
public Boolean getActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(Boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public Integer getImportance() {
|
||||
return importance;
|
||||
}
|
||||
|
||||
public void setImportance(Integer importance) {
|
||||
this.importance = importance;
|
||||
}
|
||||
|
||||
public String getSonPersonnalise() {
|
||||
return sonPersonnalise;
|
||||
}
|
||||
|
||||
public void setSonPersonnalise(String sonPersonnalise) {
|
||||
this.sonPersonnalise = sonPersonnalise;
|
||||
}
|
||||
|
||||
public long[] getPatternVibration() {
|
||||
return patternVibration;
|
||||
}
|
||||
|
||||
public void setPatternVibration(long[] patternVibration) {
|
||||
this.patternVibration = patternVibration;
|
||||
}
|
||||
|
||||
public String getCouleurLED() {
|
||||
return couleurLED;
|
||||
}
|
||||
|
||||
public void setCouleurLED(String couleurLED) {
|
||||
this.couleurLED = couleurLED;
|
||||
}
|
||||
|
||||
public Boolean getSonActive() {
|
||||
return sonActive;
|
||||
}
|
||||
|
||||
public void setSonActive(Boolean sonActive) {
|
||||
this.sonActive = sonActive;
|
||||
}
|
||||
|
||||
public Boolean getVibrationActive() {
|
||||
return vibrationActive;
|
||||
}
|
||||
|
||||
public void setVibrationActive(Boolean vibrationActive) {
|
||||
this.vibrationActive = vibrationActive;
|
||||
}
|
||||
|
||||
public Boolean getLedActive() {
|
||||
return ledActive;
|
||||
}
|
||||
|
||||
public void setLedActive(Boolean ledActive) {
|
||||
this.ledActive = ledActive;
|
||||
}
|
||||
|
||||
public Boolean getPeutEtreDesactive() {
|
||||
return peutEtreDesactive;
|
||||
}
|
||||
|
||||
public void setPeutEtreDesactive(Boolean peutEtreDesactive) {
|
||||
this.peutEtreDesactive = peutEtreDesactive;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,98 +5,128 @@ import jakarta.validation.constraints.*;
|
||||
|
||||
/**
|
||||
* DTO pour les préférences spécifiques à un type de notification
|
||||
*
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class PreferenceTypeNotificationDTO {
|
||||
|
||||
/**
|
||||
* Indique si ce type de notification est activé
|
||||
*/
|
||||
private Boolean active;
|
||||
|
||||
/**
|
||||
* Priorité personnalisée (1-5)
|
||||
*/
|
||||
@Min(value = 1, message = "La priorité doit être comprise entre 1 et 5")
|
||||
@Max(value = 5, message = "La priorité doit être comprise entre 1 et 5")
|
||||
private Integer priorite;
|
||||
|
||||
/**
|
||||
* Son personnalisé pour ce type
|
||||
*/
|
||||
private String sonPersonnalise;
|
||||
|
||||
/**
|
||||
* Pattern de vibration personnalisé
|
||||
*/
|
||||
private long[] patternVibration;
|
||||
|
||||
/**
|
||||
* Couleur LED personnalisée
|
||||
*/
|
||||
private String couleurLED;
|
||||
|
||||
/**
|
||||
* Durée d'affichage personnalisée (secondes)
|
||||
*/
|
||||
@Min(value = 1, message = "La durée d'affichage doit être au moins 1 seconde")
|
||||
@Max(value = 300, message = "La durée d'affichage ne peut pas dépasser 5 minutes")
|
||||
private Integer dureeAffichageSecondes;
|
||||
|
||||
/**
|
||||
* Indique si les notifications de ce type doivent vibrer
|
||||
*/
|
||||
private Boolean doitVibrer;
|
||||
|
||||
/**
|
||||
* Indique si les notifications de ce type doivent émettre un son
|
||||
*/
|
||||
private Boolean doitEmettreSon;
|
||||
|
||||
/**
|
||||
* Indique si les notifications de ce type doivent allumer la LED
|
||||
*/
|
||||
private Boolean doitAllumerLED;
|
||||
|
||||
/**
|
||||
* Indique si ce type ignore le mode silencieux
|
||||
*/
|
||||
private Boolean ignoreModesilencieux;
|
||||
|
||||
// Constructeurs, getters et setters
|
||||
public PreferenceTypeNotificationDTO() {}
|
||||
|
||||
public Boolean getActive() { return active; }
|
||||
public void setActive(Boolean active) { this.active = active; }
|
||||
|
||||
public Integer getPriorite() { return priorite; }
|
||||
public void setPriorite(Integer priorite) { this.priorite = priorite; }
|
||||
|
||||
public String getSonPersonnalise() { return sonPersonnalise; }
|
||||
public void setSonPersonnalise(String sonPersonnalise) { this.sonPersonnalise = sonPersonnalise; }
|
||||
|
||||
public long[] getPatternVibration() { return patternVibration; }
|
||||
public void setPatternVibration(long[] patternVibration) { this.patternVibration = patternVibration; }
|
||||
|
||||
public String getCouleurLED() { return couleurLED; }
|
||||
public void setCouleurLED(String couleurLED) { this.couleurLED = couleurLED; }
|
||||
|
||||
public Integer getDureeAffichageSecondes() { return dureeAffichageSecondes; }
|
||||
public void setDureeAffichageSecondes(Integer dureeAffichageSecondes) { this.dureeAffichageSecondes = dureeAffichageSecondes; }
|
||||
|
||||
public Boolean getDoitVibrer() { return doitVibrer; }
|
||||
public void setDoitVibrer(Boolean doitVibrer) { this.doitVibrer = doitVibrer; }
|
||||
|
||||
public Boolean getDoitEmettreSon() { return doitEmettreSon; }
|
||||
public void setDoitEmettreSon(Boolean doitEmettreSon) { this.doitEmettreSon = doitEmettreSon; }
|
||||
|
||||
public Boolean getDoitAllumerLED() { return doitAllumerLED; }
|
||||
public void setDoitAllumerLED(Boolean doitAllumerLED) { this.doitAllumerLED = doitAllumerLED; }
|
||||
|
||||
public Boolean getIgnoreModeSilencieux() { return ignoreModesilencieux; }
|
||||
public void setIgnoreModeSilencieux(Boolean ignoreModesilencieux) { this.ignoreModesilencieux = ignoreModesilencieux; }
|
||||
|
||||
/** Indique si ce type de notification est activé */
|
||||
private Boolean active;
|
||||
|
||||
/** Priorité personnalisée (1-5) */
|
||||
@Min(value = 1, message = "La priorité doit être comprise entre 1 et 5")
|
||||
@Max(value = 5, message = "La priorité doit être comprise entre 1 et 5")
|
||||
private Integer priorite;
|
||||
|
||||
/** Son personnalisé pour ce type */
|
||||
private String sonPersonnalise;
|
||||
|
||||
/** Pattern de vibration personnalisé */
|
||||
private long[] patternVibration;
|
||||
|
||||
/** Couleur LED personnalisée */
|
||||
private String couleurLED;
|
||||
|
||||
/** Durée d'affichage personnalisée (secondes) */
|
||||
@Min(value = 1, message = "La durée d'affichage doit être au moins 1 seconde")
|
||||
@Max(value = 300, message = "La durée d'affichage ne peut pas dépasser 5 minutes")
|
||||
private Integer dureeAffichageSecondes;
|
||||
|
||||
/** Indique si les notifications de ce type doivent vibrer */
|
||||
private Boolean doitVibrer;
|
||||
|
||||
/** Indique si les notifications de ce type doivent émettre un son */
|
||||
private Boolean doitEmettreSon;
|
||||
|
||||
/** Indique si les notifications de ce type doivent allumer la LED */
|
||||
private Boolean doitAllumerLED;
|
||||
|
||||
/** Indique si ce type ignore le mode silencieux */
|
||||
private Boolean ignoreModesilencieux;
|
||||
|
||||
// Constructeurs, getters et setters
|
||||
public PreferenceTypeNotificationDTO() {}
|
||||
|
||||
public Boolean getActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setActive(Boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public Integer getPriorite() {
|
||||
return priorite;
|
||||
}
|
||||
|
||||
public void setPriorite(Integer priorite) {
|
||||
this.priorite = priorite;
|
||||
}
|
||||
|
||||
public String getSonPersonnalise() {
|
||||
return sonPersonnalise;
|
||||
}
|
||||
|
||||
public void setSonPersonnalise(String sonPersonnalise) {
|
||||
this.sonPersonnalise = sonPersonnalise;
|
||||
}
|
||||
|
||||
public long[] getPatternVibration() {
|
||||
return patternVibration;
|
||||
}
|
||||
|
||||
public void setPatternVibration(long[] patternVibration) {
|
||||
this.patternVibration = patternVibration;
|
||||
}
|
||||
|
||||
public String getCouleurLED() {
|
||||
return couleurLED;
|
||||
}
|
||||
|
||||
public void setCouleurLED(String couleurLED) {
|
||||
this.couleurLED = couleurLED;
|
||||
}
|
||||
|
||||
public Integer getDureeAffichageSecondes() {
|
||||
return dureeAffichageSecondes;
|
||||
}
|
||||
|
||||
public void setDureeAffichageSecondes(Integer dureeAffichageSecondes) {
|
||||
this.dureeAffichageSecondes = dureeAffichageSecondes;
|
||||
}
|
||||
|
||||
public Boolean getDoitVibrer() {
|
||||
return doitVibrer;
|
||||
}
|
||||
|
||||
public void setDoitVibrer(Boolean doitVibrer) {
|
||||
this.doitVibrer = doitVibrer;
|
||||
}
|
||||
|
||||
public Boolean getDoitEmettreSon() {
|
||||
return doitEmettreSon;
|
||||
}
|
||||
|
||||
public void setDoitEmettreSon(Boolean doitEmettreSon) {
|
||||
this.doitEmettreSon = doitEmettreSon;
|
||||
}
|
||||
|
||||
public Boolean getDoitAllumerLED() {
|
||||
return doitAllumerLED;
|
||||
}
|
||||
|
||||
public void setDoitAllumerLED(Boolean doitAllumerLED) {
|
||||
this.doitAllumerLED = doitAllumerLED;
|
||||
}
|
||||
|
||||
public Boolean getIgnoreModeSilencieux() {
|
||||
return ignoreModesilencieux;
|
||||
}
|
||||
|
||||
public void setIgnoreModeSilencieux(Boolean ignoreModesilencieux) {
|
||||
this.ignoreModesilencieux = ignoreModesilencieux;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import dev.lions.unionflow.server.api.enums.organisation.StatutOrganisation;
|
||||
import dev.lions.unionflow.server.api.enums.organisation.TypeOrganisation;
|
||||
import dev.lions.unionflow.server.api.validation.ValidationConstants;
|
||||
import jakarta.validation.constraints.DecimalMax;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Digits;
|
||||
@@ -34,12 +35,17 @@ public class OrganisationDTO extends BaseDTO {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Nom de l'organisation */
|
||||
@NotBlank(message = "Le nom de l'organisation est obligatoire")
|
||||
@Size(min = 2, max = 200, message = "Le nom doit contenir entre 2 et 200 caractères")
|
||||
@NotBlank(message = "Le nom de l'organisation" + ValidationConstants.OBLIGATOIRE_MESSAGE)
|
||||
@Size(
|
||||
min = ValidationConstants.NOM_ORGANISATION_MIN_LENGTH,
|
||||
max = ValidationConstants.NOM_ORGANISATION_MAX_LENGTH,
|
||||
message = ValidationConstants.NOM_ORGANISATION_SIZE_MESSAGE)
|
||||
private String nom;
|
||||
|
||||
/** Nom court ou sigle */
|
||||
@Size(max = 50, message = "Le nom court ne peut pas dépasser 50 caractères")
|
||||
@Size(
|
||||
max = ValidationConstants.NOM_COURT_MAX_LENGTH,
|
||||
message = ValidationConstants.NOM_COURT_SIZE_MESSAGE)
|
||||
private String nomCourt;
|
||||
|
||||
/** Type d'organisation */
|
||||
@@ -51,7 +57,9 @@ public class OrganisationDTO extends BaseDTO {
|
||||
private StatutOrganisation statut;
|
||||
|
||||
/** Description de l'organisation */
|
||||
@Size(max = 2000, message = "La description ne peut pas dépasser 2000 caractères")
|
||||
@Size(
|
||||
max = ValidationConstants.DESCRIPTION_MAX_LENGTH,
|
||||
message = ValidationConstants.DESCRIPTION_SIZE_MESSAGE)
|
||||
private String description;
|
||||
|
||||
/** Date de fondation */
|
||||
@@ -225,7 +233,7 @@ public class OrganisationDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si l'organisation est active
|
||||
*/
|
||||
public boolean isActive() {
|
||||
public boolean estActive() {
|
||||
return StatutOrganisation.ACTIVE.equals(statut);
|
||||
}
|
||||
|
||||
@@ -234,7 +242,7 @@ public class OrganisationDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si l'organisation est inactive
|
||||
*/
|
||||
public boolean isInactive() {
|
||||
public boolean estInactive() {
|
||||
return StatutOrganisation.INACTIVE.equals(statut);
|
||||
}
|
||||
|
||||
@@ -243,7 +251,7 @@ public class OrganisationDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si l'organisation est suspendue
|
||||
*/
|
||||
public boolean isSuspendue() {
|
||||
public boolean estSuspendue() {
|
||||
return StatutOrganisation.SUSPENDUE.equals(statut);
|
||||
}
|
||||
|
||||
@@ -252,7 +260,7 @@ public class OrganisationDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si l'organisation est en création
|
||||
*/
|
||||
public boolean isEnCreation() {
|
||||
public boolean estEnCreation() {
|
||||
return StatutOrganisation.EN_CREATION.equals(statut);
|
||||
}
|
||||
|
||||
@@ -261,7 +269,7 @@ public class OrganisationDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si l'organisation est dissoute
|
||||
*/
|
||||
public boolean isDissoute() {
|
||||
public boolean estDissoute() {
|
||||
return StatutOrganisation.DISSOUTE.equals(statut);
|
||||
}
|
||||
|
||||
@@ -291,7 +299,7 @@ public class OrganisationDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si latitude et longitude sont définies
|
||||
*/
|
||||
public boolean hasGeolocalisation() {
|
||||
public boolean possedGeolocalisation() {
|
||||
return latitude != null && longitude != null;
|
||||
}
|
||||
|
||||
@@ -300,7 +308,7 @@ public class OrganisationDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si l'organisation n'a pas de parent
|
||||
*/
|
||||
public boolean isOrganisationRacine() {
|
||||
public boolean estOrganisationRacine() {
|
||||
return organisationParenteId == null;
|
||||
}
|
||||
|
||||
@@ -309,7 +317,7 @@ public class OrganisationDTO extends BaseDTO {
|
||||
*
|
||||
* @return true si le niveau hiérarchique est supérieur à 0
|
||||
*/
|
||||
public boolean hasSousOrganisations() {
|
||||
public boolean possedeSousOrganisations() {
|
||||
return niveauHierarchique != null && niveauHierarchique > 0;
|
||||
}
|
||||
|
||||
@@ -408,6 +416,17 @@ public class OrganisationDTO extends BaseDTO {
|
||||
marquerCommeModifie(utilisateur);
|
||||
}
|
||||
|
||||
/**
|
||||
* Désactive l'organisation
|
||||
*
|
||||
* @param utilisateur L'utilisateur qui désactive l'organisation
|
||||
*/
|
||||
public void desactiver(String utilisateur) {
|
||||
this.statut = StatutOrganisation.INACTIVE;
|
||||
this.accepteNouveauxMembres = false;
|
||||
marquerCommeModifie(utilisateur);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour le nombre de membres
|
||||
*
|
||||
@@ -469,4 +488,31 @@ public class OrganisationDTO extends BaseDTO {
|
||||
+ "} "
|
||||
+ super.toString();
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/** Retourne le libellé du statut */
|
||||
public String getStatutLibelle() {
|
||||
return statut != null ? statut.getLibelle() : "Non défini";
|
||||
}
|
||||
|
||||
/** Retourne le libellé du type d'organisation */
|
||||
public String getTypeLibelle() {
|
||||
return typeOrganisation != null ? typeOrganisation.getLibelle() : "Non défini";
|
||||
}
|
||||
|
||||
/** Ajoute un administrateur */
|
||||
public void ajouterAdministrateur(String utilisateur) {
|
||||
if (nombreAdministrateurs == null) nombreAdministrateurs = 0;
|
||||
nombreAdministrateurs++;
|
||||
marquerCommeModifie(utilisateur);
|
||||
}
|
||||
|
||||
/** Retire un administrateur */
|
||||
public void retirerAdministrateur(String utilisateur) {
|
||||
if (nombreAdministrateurs != null && nombreAdministrateurs > 0) {
|
||||
nombreAdministrateurs--;
|
||||
marquerCommeModifie(utilisateur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import java.time.LocalDate;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO pour les bénéficiaires d'une aide
|
||||
*
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -20,80 +19,53 @@ import java.time.LocalDate;
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class BeneficiaireAideDTO {
|
||||
|
||||
/**
|
||||
* Identifiant unique du bénéficiaire
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Nom complet du bénéficiaire
|
||||
*/
|
||||
@NotBlank(message = "Le nom du bénéficiaire est obligatoire")
|
||||
@Size(max = 100, message = "Le nom ne peut pas dépasser 100 caractères")
|
||||
private String nomComplet;
|
||||
|
||||
/**
|
||||
* Relation avec le demandeur
|
||||
*/
|
||||
@NotBlank(message = "La relation avec le demandeur est obligatoire")
|
||||
private String relationDemandeur;
|
||||
|
||||
/**
|
||||
* Date de naissance
|
||||
*/
|
||||
private LocalDate dateNaissance;
|
||||
|
||||
/**
|
||||
* Âge calculé
|
||||
*/
|
||||
private Integer age;
|
||||
|
||||
/**
|
||||
* Genre
|
||||
*/
|
||||
private String genre;
|
||||
|
||||
/**
|
||||
* Numéro de téléphone
|
||||
*/
|
||||
@Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Le numéro de téléphone n'est pas valide")
|
||||
private String telephone;
|
||||
|
||||
/**
|
||||
* Adresse email
|
||||
*/
|
||||
@Email(message = "L'adresse email n'est pas valide")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* Adresse physique
|
||||
*/
|
||||
@Size(max = 200, message = "L'adresse ne peut pas dépasser 200 caractères")
|
||||
private String adresse;
|
||||
|
||||
/**
|
||||
* Situation particulière (handicap, maladie, etc.)
|
||||
*/
|
||||
@Size(max = 500, message = "La situation particulière ne peut pas dépasser 500 caractères")
|
||||
private String situationParticuliere;
|
||||
|
||||
/**
|
||||
* Indique si le bénéficiaire est le demandeur principal
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estDemandeurPrincipal = false;
|
||||
|
||||
/**
|
||||
* Pourcentage de l'aide destiné à ce bénéficiaire
|
||||
*/
|
||||
@DecimalMin(value = "0.0", message = "Le pourcentage doit être positif")
|
||||
@DecimalMax(value = "100.0", message = "Le pourcentage ne peut pas dépasser 100%")
|
||||
private Double pourcentageAide;
|
||||
|
||||
/**
|
||||
* Montant spécifique pour ce bénéficiaire
|
||||
*/
|
||||
@DecimalMin(value = "0.0", message = "Le montant doit être positif")
|
||||
private Double montantSpecifique;
|
||||
|
||||
/** Identifiant unique du bénéficiaire */
|
||||
private String id;
|
||||
|
||||
/** Nom complet du bénéficiaire */
|
||||
@NotBlank(message = "Le nom du bénéficiaire est obligatoire")
|
||||
@Size(max = 100, message = "Le nom ne peut pas dépasser 100 caractères")
|
||||
private String nomComplet;
|
||||
|
||||
/** Relation avec le demandeur */
|
||||
@NotBlank(message = "La relation avec le demandeur est obligatoire")
|
||||
private String relationDemandeur;
|
||||
|
||||
/** Date de naissance */
|
||||
private LocalDate dateNaissance;
|
||||
|
||||
/** Âge calculé */
|
||||
private Integer age;
|
||||
|
||||
/** Genre */
|
||||
private String genre;
|
||||
|
||||
/** Numéro de téléphone */
|
||||
@Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Le numéro de téléphone n'est pas valide")
|
||||
private String telephone;
|
||||
|
||||
/** Adresse email */
|
||||
@Email(message = "L'adresse email n'est pas valide")
|
||||
private String email;
|
||||
|
||||
/** Adresse physique */
|
||||
@Size(max = 200, message = "L'adresse ne peut pas dépasser 200 caractères")
|
||||
private String adresse;
|
||||
|
||||
/** Situation particulière (handicap, maladie, etc.) */
|
||||
@Size(max = 500, message = "La situation particulière ne peut pas dépasser 500 caractères")
|
||||
private String situationParticuliere;
|
||||
|
||||
/** Indique si le bénéficiaire est le demandeur principal */
|
||||
@Builder.Default private Boolean estDemandeurPrincipal = false;
|
||||
|
||||
/** Pourcentage de l'aide destiné à ce bénéficiaire */
|
||||
@DecimalMin(value = "0.0", message = "Le pourcentage doit être positif")
|
||||
@DecimalMax(value = "100.0", message = "Le pourcentage ne peut pas dépasser 100%")
|
||||
private Double pourcentageAide;
|
||||
|
||||
/** Montant spécifique pour ce bénéficiaire */
|
||||
@DecimalMin(value = "0.0", message = "Le montant doit être positif")
|
||||
private Double montantSpecifique;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO pour les commentaires sur une demande d'aide
|
||||
*
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -21,110 +20,67 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class CommentaireAideDTO {
|
||||
|
||||
/**
|
||||
* Identifiant unique du commentaire
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Contenu du commentaire
|
||||
*/
|
||||
@NotBlank(message = "Le contenu du commentaire est obligatoire")
|
||||
@Size(min = 5, max = 2000, message = "Le commentaire doit contenir entre 5 et 2000 caractères")
|
||||
private String contenu;
|
||||
|
||||
/**
|
||||
* Type de commentaire
|
||||
*/
|
||||
@NotBlank(message = "Le type de commentaire est obligatoire")
|
||||
private String typeCommentaire;
|
||||
|
||||
/**
|
||||
* Date de création du commentaire
|
||||
*/
|
||||
@NotNull(message = "La date de création est obligatoire")
|
||||
@Builder.Default
|
||||
private LocalDateTime dateCreation = LocalDateTime.now();
|
||||
|
||||
/**
|
||||
* Date de dernière modification
|
||||
*/
|
||||
private LocalDateTime dateModification;
|
||||
|
||||
/**
|
||||
* Identifiant de l'auteur du commentaire
|
||||
*/
|
||||
@NotBlank(message = "L'identifiant de l'auteur est obligatoire")
|
||||
private String auteurId;
|
||||
|
||||
/**
|
||||
* Nom de l'auteur du commentaire
|
||||
*/
|
||||
private String auteurNom;
|
||||
|
||||
/**
|
||||
* Rôle de l'auteur
|
||||
*/
|
||||
private String auteurRole;
|
||||
|
||||
/**
|
||||
* Indique si le commentaire est privé (visible seulement aux évaluateurs)
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estPrive = false;
|
||||
|
||||
/**
|
||||
* Indique si le commentaire est important
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estImportant = false;
|
||||
|
||||
/**
|
||||
* Identifiant du commentaire parent (pour les réponses)
|
||||
*/
|
||||
private String commentaireParentId;
|
||||
|
||||
/**
|
||||
* Réponses à ce commentaire
|
||||
*/
|
||||
private List<CommentaireAideDTO> reponses;
|
||||
|
||||
/**
|
||||
* Pièces jointes au commentaire
|
||||
*/
|
||||
private List<PieceJustificativeDTO> piecesJointes;
|
||||
|
||||
/**
|
||||
* Mentions d'utilisateurs dans le commentaire
|
||||
*/
|
||||
private List<String> mentionsUtilisateurs;
|
||||
|
||||
/**
|
||||
* Indique si le commentaire a été modifié
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estModifie = false;
|
||||
|
||||
/**
|
||||
* Nombre de likes/réactions
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer nombreReactions = 0;
|
||||
|
||||
/**
|
||||
* Indique si le commentaire est résolu (pour les questions)
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estResolu = false;
|
||||
|
||||
/**
|
||||
* Date de résolution
|
||||
*/
|
||||
private LocalDateTime dateResolution;
|
||||
|
||||
/**
|
||||
* Identifiant de la personne qui a marqué comme résolu
|
||||
*/
|
||||
private String resoluteurId;
|
||||
|
||||
/** Identifiant unique du commentaire */
|
||||
private String id;
|
||||
|
||||
/** Contenu du commentaire */
|
||||
@NotBlank(message = "Le contenu du commentaire est obligatoire")
|
||||
@Size(min = 5, max = 2000, message = "Le commentaire doit contenir entre 5 et 2000 caractères")
|
||||
private String contenu;
|
||||
|
||||
/** Type de commentaire */
|
||||
@NotBlank(message = "Le type de commentaire est obligatoire")
|
||||
private String typeCommentaire;
|
||||
|
||||
/** Date de création du commentaire */
|
||||
@NotNull(message = "La date de création est obligatoire")
|
||||
@Builder.Default
|
||||
private LocalDateTime dateCreation = LocalDateTime.now();
|
||||
|
||||
/** Date de dernière modification */
|
||||
private LocalDateTime dateModification;
|
||||
|
||||
/** Identifiant de l'auteur du commentaire */
|
||||
@NotBlank(message = "L'identifiant de l'auteur est obligatoire")
|
||||
private String auteurId;
|
||||
|
||||
/** Nom de l'auteur du commentaire */
|
||||
private String auteurNom;
|
||||
|
||||
/** Rôle de l'auteur */
|
||||
private String auteurRole;
|
||||
|
||||
/** Indique si le commentaire est privé (visible seulement aux évaluateurs) */
|
||||
@Builder.Default private Boolean estPrive = false;
|
||||
|
||||
/** Indique si le commentaire est important */
|
||||
@Builder.Default private Boolean estImportant = false;
|
||||
|
||||
/** Identifiant du commentaire parent (pour les réponses) */
|
||||
private String commentaireParentId;
|
||||
|
||||
/** Réponses à ce commentaire */
|
||||
private List<CommentaireAideDTO> reponses;
|
||||
|
||||
/** Pièces jointes au commentaire */
|
||||
private List<PieceJustificativeDTO> piecesJointes;
|
||||
|
||||
/** Mentions d'utilisateurs dans le commentaire */
|
||||
private List<String> mentionsUtilisateurs;
|
||||
|
||||
/** Indique si le commentaire a été modifié */
|
||||
@Builder.Default private Boolean estModifie = false;
|
||||
|
||||
/** Nombre de likes/réactions */
|
||||
@Builder.Default private Integer nombreReactions = 0;
|
||||
|
||||
/** Indique si le commentaire est résolu (pour les questions) */
|
||||
@Builder.Default private Boolean estResolu = false;
|
||||
|
||||
/** Date de résolution */
|
||||
private LocalDateTime dateResolution;
|
||||
|
||||
/** Identifiant de la personne qui a marqué comme résolu */
|
||||
private String resoluteurId;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO pour les informations de contact du proposant d'aide
|
||||
*
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -18,92 +18,60 @@ import lombok.Builder;
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class ContactProposantDTO {
|
||||
|
||||
/**
|
||||
* Numéro de téléphone principal
|
||||
*/
|
||||
@Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Le numéro de téléphone n'est pas valide")
|
||||
private String telephonePrincipal;
|
||||
|
||||
/**
|
||||
* Numéro de téléphone secondaire
|
||||
*/
|
||||
@Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Le numéro de téléphone secondaire n'est pas valide")
|
||||
private String telephoneSecondaire;
|
||||
|
||||
/**
|
||||
* Adresse email
|
||||
*/
|
||||
@Email(message = "L'adresse email n'est pas valide")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* Adresse email secondaire
|
||||
*/
|
||||
@Email(message = "L'adresse email secondaire n'est pas valide")
|
||||
private String emailSecondaire;
|
||||
|
||||
/**
|
||||
* Identifiant WhatsApp
|
||||
*/
|
||||
@Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Le numéro WhatsApp n'est pas valide")
|
||||
private String whatsapp;
|
||||
|
||||
/**
|
||||
* Identifiant Telegram
|
||||
*/
|
||||
@Size(max = 50, message = "L'identifiant Telegram ne peut pas dépasser 50 caractères")
|
||||
private String telegram;
|
||||
|
||||
/**
|
||||
* Autres moyens de contact (réseaux sociaux, etc.)
|
||||
*/
|
||||
private java.util.Map<String, String> autresContacts;
|
||||
|
||||
/**
|
||||
* Adresse physique pour rencontres
|
||||
*/
|
||||
@Size(max = 200, message = "L'adresse ne peut pas dépasser 200 caractères")
|
||||
private String adressePhysique;
|
||||
|
||||
/**
|
||||
* Indique si les rencontres physiques sont possibles
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean rencontresPhysiquesPossibles = false;
|
||||
|
||||
/**
|
||||
* Indique si les appels téléphoniques sont acceptés
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean appelsAcceptes = true;
|
||||
|
||||
/**
|
||||
* Indique si les SMS sont acceptés
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean smsAcceptes = true;
|
||||
|
||||
/**
|
||||
* Indique si les emails sont acceptés
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean emailsAcceptes = true;
|
||||
|
||||
/**
|
||||
* Horaires de disponibilité pour contact
|
||||
*/
|
||||
@Size(max = 200, message = "Les horaires ne peuvent pas dépasser 200 caractères")
|
||||
private String horairesDisponibilite;
|
||||
|
||||
/**
|
||||
* Langue(s) de communication préférée(s)
|
||||
*/
|
||||
private java.util.List<String> languesPreferees;
|
||||
|
||||
/**
|
||||
* Instructions spéciales pour le contact
|
||||
*/
|
||||
@Size(max = 300, message = "Les instructions ne peuvent pas dépasser 300 caractères")
|
||||
private String instructionsSpeciales;
|
||||
|
||||
/** Numéro de téléphone principal */
|
||||
@Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Le numéro de téléphone n'est pas valide")
|
||||
private String telephonePrincipal;
|
||||
|
||||
/** Numéro de téléphone secondaire */
|
||||
@Pattern(
|
||||
regexp = "^\\+?[0-9]{8,15}$",
|
||||
message = "Le numéro de téléphone secondaire n'est pas valide")
|
||||
private String telephoneSecondaire;
|
||||
|
||||
/** Adresse email */
|
||||
@Email(message = "L'adresse email n'est pas valide")
|
||||
private String email;
|
||||
|
||||
/** Adresse email secondaire */
|
||||
@Email(message = "L'adresse email secondaire n'est pas valide")
|
||||
private String emailSecondaire;
|
||||
|
||||
/** Identifiant WhatsApp */
|
||||
@Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Le numéro WhatsApp n'est pas valide")
|
||||
private String whatsapp;
|
||||
|
||||
/** Identifiant Telegram */
|
||||
@Size(max = 50, message = "L'identifiant Telegram ne peut pas dépasser 50 caractères")
|
||||
private String telegram;
|
||||
|
||||
/** Autres moyens de contact (réseaux sociaux, etc.) */
|
||||
private java.util.Map<String, String> autresContacts;
|
||||
|
||||
/** Adresse physique pour rencontres */
|
||||
@Size(max = 200, message = "L'adresse ne peut pas dépasser 200 caractères")
|
||||
private String adressePhysique;
|
||||
|
||||
/** Indique si les rencontres physiques sont possibles */
|
||||
@Builder.Default private Boolean rencontresPhysiquesPossibles = false;
|
||||
|
||||
/** Indique si les appels téléphoniques sont acceptés */
|
||||
@Builder.Default private Boolean appelsAcceptes = true;
|
||||
|
||||
/** Indique si les SMS sont acceptés */
|
||||
@Builder.Default private Boolean smsAcceptes = true;
|
||||
|
||||
/** Indique si les emails sont acceptés */
|
||||
@Builder.Default private Boolean emailsAcceptes = true;
|
||||
|
||||
/** Horaires de disponibilité pour contact */
|
||||
@Size(max = 200, message = "Les horaires ne peuvent pas dépasser 200 caractères")
|
||||
private String horairesDisponibilite;
|
||||
|
||||
/** Langue(s) de communication préférée(s) */
|
||||
private java.util.List<String> languesPreferees;
|
||||
|
||||
/** Instructions spéciales pour le contact */
|
||||
@Size(max = 300, message = "Les instructions ne peuvent pas dépasser 300 caractères")
|
||||
private String instructionsSpeciales;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO pour les informations de contact d'urgence
|
||||
*
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -18,67 +18,47 @@ import lombok.Builder;
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class ContactUrgenceDTO {
|
||||
|
||||
/**
|
||||
* Nom complet du contact d'urgence
|
||||
*/
|
||||
@NotBlank(message = "Le nom du contact d'urgence est obligatoire")
|
||||
@Size(max = 100, message = "Le nom ne peut pas dépasser 100 caractères")
|
||||
private String nomComplet;
|
||||
|
||||
/**
|
||||
* Relation avec le demandeur
|
||||
*/
|
||||
@NotBlank(message = "La relation avec le demandeur est obligatoire")
|
||||
@Size(max = 50, message = "La relation ne peut pas dépasser 50 caractères")
|
||||
private String relation;
|
||||
|
||||
/**
|
||||
* Numéro de téléphone principal
|
||||
*/
|
||||
@NotBlank(message = "Le numéro de téléphone est obligatoire")
|
||||
@Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Le numéro de téléphone n'est pas valide")
|
||||
private String telephonePrincipal;
|
||||
|
||||
/**
|
||||
* Numéro de téléphone secondaire
|
||||
*/
|
||||
@Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Le numéro de téléphone secondaire n'est pas valide")
|
||||
private String telephoneSecondaire;
|
||||
|
||||
/**
|
||||
* Adresse email
|
||||
*/
|
||||
@Email(message = "L'adresse email n'est pas valide")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* Adresse physique
|
||||
*/
|
||||
@Size(max = 200, message = "L'adresse ne peut pas dépasser 200 caractères")
|
||||
private String adresse;
|
||||
|
||||
/**
|
||||
* Disponibilité (horaires)
|
||||
*/
|
||||
@Size(max = 100, message = "La disponibilité ne peut pas dépasser 100 caractères")
|
||||
private String disponibilite;
|
||||
|
||||
/**
|
||||
* Indique si ce contact peut prendre des décisions pour le demandeur
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean peutPrendreDecisions = false;
|
||||
|
||||
/**
|
||||
* Indique si ce contact doit être notifié automatiquement
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean notificationAutomatique = true;
|
||||
|
||||
/**
|
||||
* Commentaires additionnels
|
||||
*/
|
||||
@Size(max = 300, message = "Les commentaires ne peuvent pas dépasser 300 caractères")
|
||||
private String commentaires;
|
||||
|
||||
/** Nom complet du contact d'urgence */
|
||||
@NotBlank(message = "Le nom du contact d'urgence est obligatoire")
|
||||
@Size(max = 100, message = "Le nom ne peut pas dépasser 100 caractères")
|
||||
private String nomComplet;
|
||||
|
||||
/** Relation avec le demandeur */
|
||||
@NotBlank(message = "La relation avec le demandeur est obligatoire")
|
||||
@Size(max = 50, message = "La relation ne peut pas dépasser 50 caractères")
|
||||
private String relation;
|
||||
|
||||
/** Numéro de téléphone principal */
|
||||
@NotBlank(message = "Le numéro de téléphone est obligatoire")
|
||||
@Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Le numéro de téléphone n'est pas valide")
|
||||
private String telephonePrincipal;
|
||||
|
||||
/** Numéro de téléphone secondaire */
|
||||
@Pattern(
|
||||
regexp = "^\\+?[0-9]{8,15}$",
|
||||
message = "Le numéro de téléphone secondaire n'est pas valide")
|
||||
private String telephoneSecondaire;
|
||||
|
||||
/** Adresse email */
|
||||
@Email(message = "L'adresse email n'est pas valide")
|
||||
private String email;
|
||||
|
||||
/** Adresse physique */
|
||||
@Size(max = 200, message = "L'adresse ne peut pas dépasser 200 caractères")
|
||||
private String adresse;
|
||||
|
||||
/** Disponibilité (horaires) */
|
||||
@Size(max = 100, message = "La disponibilité ne peut pas dépasser 100 caractères")
|
||||
private String disponibilite;
|
||||
|
||||
/** Indique si ce contact peut prendre des décisions pour le demandeur */
|
||||
@Builder.Default private Boolean peutPrendreDecisions = false;
|
||||
|
||||
/** Indique si ce contact doit être notifié automatiquement */
|
||||
@Builder.Default private Boolean notificationAutomatique = true;
|
||||
|
||||
/** Commentaires additionnels */
|
||||
@Size(max = 300, message = "Les commentaires ne peuvent pas dépasser 300 caractères")
|
||||
private String commentaires;
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalTime;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO pour les créneaux de disponibilité du proposant
|
||||
*
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -22,158 +21,117 @@ import java.time.LocalDate;
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class CreneauDisponibiliteDTO {
|
||||
|
||||
/**
|
||||
* Identifiant unique du créneau
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Jour de la semaine (pour créneaux récurrents)
|
||||
*/
|
||||
private DayOfWeek jourSemaine;
|
||||
|
||||
/**
|
||||
* Date spécifique (pour créneaux ponctuels)
|
||||
*/
|
||||
private LocalDate dateSpecifique;
|
||||
|
||||
/**
|
||||
* Heure de début
|
||||
*/
|
||||
@NotNull(message = "L'heure de début est obligatoire")
|
||||
private LocalTime heureDebut;
|
||||
|
||||
/**
|
||||
* Heure de fin
|
||||
*/
|
||||
@NotNull(message = "L'heure de fin est obligatoire")
|
||||
private LocalTime heureFin;
|
||||
|
||||
/**
|
||||
* Type de créneau
|
||||
*/
|
||||
@NotNull(message = "Le type de créneau est obligatoire")
|
||||
@Builder.Default
|
||||
private TypeCreneau type = TypeCreneau.RECURRENT;
|
||||
|
||||
/**
|
||||
* Indique si le créneau est actif
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estActif = true;
|
||||
|
||||
/**
|
||||
* Fuseau horaire
|
||||
*/
|
||||
@Builder.Default
|
||||
private String fuseauHoraire = "Africa/Abidjan";
|
||||
|
||||
/**
|
||||
* Commentaires sur le créneau
|
||||
*/
|
||||
@Size(max = 200, message = "Les commentaires ne peuvent pas dépasser 200 caractères")
|
||||
private String commentaires;
|
||||
|
||||
/**
|
||||
* Priorité du créneau (1 = haute, 5 = basse)
|
||||
*/
|
||||
@Min(value = 1, message = "La priorité doit être au moins 1")
|
||||
@Max(value = 5, message = "La priorité ne peut pas dépasser 5")
|
||||
@Builder.Default
|
||||
private Integer priorite = 3;
|
||||
|
||||
/**
|
||||
* Durée maximale d'intervention en minutes
|
||||
*/
|
||||
@Min(value = 15, message = "La durée doit être au moins 15 minutes")
|
||||
@Max(value = 480, message = "La durée ne peut pas dépasser 8 heures")
|
||||
private Integer dureeMaxMinutes;
|
||||
|
||||
/**
|
||||
* Indique si des pauses sont nécessaires
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean pausesNecessaires = false;
|
||||
|
||||
/**
|
||||
* Durée des pauses en minutes
|
||||
*/
|
||||
@Min(value = 5, message = "La durée de pause doit être au moins 5 minutes")
|
||||
private Integer dureePauseMinutes;
|
||||
|
||||
/**
|
||||
* Énumération des types de créneaux
|
||||
*/
|
||||
public enum TypeCreneau {
|
||||
RECURRENT("Récurrent"),
|
||||
PONCTUEL("Ponctuel"),
|
||||
URGENCE("Urgence"),
|
||||
FLEXIBLE("Flexible");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
TypeCreneau(String libelle) {
|
||||
this.libelle = libelle;
|
||||
}
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/** Identifiant unique du créneau */
|
||||
private String id;
|
||||
|
||||
/** Jour de la semaine (pour créneaux récurrents) */
|
||||
private DayOfWeek jourSemaine;
|
||||
|
||||
/** Date spécifique (pour créneaux ponctuels) */
|
||||
private LocalDate dateSpecifique;
|
||||
|
||||
/** Heure de début */
|
||||
@NotNull(message = "L'heure de début est obligatoire")
|
||||
private LocalTime heureDebut;
|
||||
|
||||
/** Heure de fin */
|
||||
@NotNull(message = "L'heure de fin est obligatoire")
|
||||
private LocalTime heureFin;
|
||||
|
||||
/** Type de créneau */
|
||||
@NotNull(message = "Le type de créneau est obligatoire")
|
||||
@Builder.Default
|
||||
private TypeCreneau type = TypeCreneau.RECURRENT;
|
||||
|
||||
/** Indique si le créneau est actif */
|
||||
@Builder.Default private Boolean estActif = true;
|
||||
|
||||
/** Fuseau horaire */
|
||||
@Builder.Default private String fuseauHoraire = "Africa/Abidjan";
|
||||
|
||||
/** Commentaires sur le créneau */
|
||||
@Size(max = 200, message = "Les commentaires ne peuvent pas dépasser 200 caractères")
|
||||
private String commentaires;
|
||||
|
||||
/** Priorité du créneau (1 = haute, 5 = basse) */
|
||||
@Min(value = 1, message = "La priorité doit être au moins 1")
|
||||
@Max(value = 5, message = "La priorité ne peut pas dépasser 5")
|
||||
@Builder.Default
|
||||
private Integer priorite = 3;
|
||||
|
||||
/** Durée maximale d'intervention en minutes */
|
||||
@Min(value = 15, message = "La durée doit être au moins 15 minutes")
|
||||
@Max(value = 480, message = "La durée ne peut pas dépasser 8 heures")
|
||||
private Integer dureeMaxMinutes;
|
||||
|
||||
/** Indique si des pauses sont nécessaires */
|
||||
@Builder.Default private Boolean pausesNecessaires = false;
|
||||
|
||||
/** Durée des pauses en minutes */
|
||||
@Min(value = 5, message = "La durée de pause doit être au moins 5 minutes")
|
||||
private Integer dureePauseMinutes;
|
||||
|
||||
/** Énumération des types de créneaux */
|
||||
public enum TypeCreneau {
|
||||
RECURRENT("Récurrent"),
|
||||
PONCTUEL("Ponctuel"),
|
||||
URGENCE("Urgence"),
|
||||
FLEXIBLE("Flexible");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
TypeCreneau(String libelle) {
|
||||
this.libelle = libelle;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Vérifie si le créneau est valide (heure fin > heure début)
|
||||
*/
|
||||
public boolean isValide() {
|
||||
return heureDebut != null && heureFin != null && heureFin.isAfter(heureDebut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule la durée du créneau en minutes
|
||||
*/
|
||||
public long getDureeMinutes() {
|
||||
if (!isValide()) return 0;
|
||||
return java.time.Duration.between(heureDebut, heureFin).toMinutes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le créneau est disponible à une date donnée
|
||||
*/
|
||||
public boolean isDisponibleLe(LocalDate date) {
|
||||
if (!estActif) return false;
|
||||
|
||||
return switch (type) {
|
||||
case PONCTUEL -> dateSpecifique != null && dateSpecifique.equals(date);
|
||||
case RECURRENT -> jourSemaine != null && date.getDayOfWeek() == jourSemaine;
|
||||
case URGENCE, FLEXIBLE -> true;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si une heure est dans le créneau
|
||||
*/
|
||||
public boolean contientHeure(LocalTime heure) {
|
||||
if (!isValide()) return false;
|
||||
return !heure.isBefore(heureDebut) && !heure.isAfter(heureFin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé du créneau
|
||||
*/
|
||||
|
||||
public String getLibelle() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (type == TypeCreneau.RECURRENT && jourSemaine != null) {
|
||||
sb.append(jourSemaine.name()).append(" ");
|
||||
} else if (type == TypeCreneau.PONCTUEL && dateSpecifique != null) {
|
||||
sb.append(dateSpecifique.toString()).append(" ");
|
||||
}
|
||||
|
||||
sb.append(heureDebut.toString()).append(" - ").append(heureFin.toString());
|
||||
|
||||
return sb.toString();
|
||||
return libelle;
|
||||
}
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/** Vérifie si le créneau est valide (heure fin > heure début) */
|
||||
public boolean isValide() {
|
||||
return heureDebut != null && heureFin != null && heureFin.isAfter(heureDebut);
|
||||
}
|
||||
|
||||
/** Calcule la durée du créneau en minutes */
|
||||
public long getDureeMinutes() {
|
||||
if (!isValide()) return 0;
|
||||
return java.time.Duration.between(heureDebut, heureFin).toMinutes();
|
||||
}
|
||||
|
||||
/** Vérifie si le créneau est disponible à une date donnée */
|
||||
public boolean isDisponibleLe(LocalDate date) {
|
||||
if (!estActif) return false;
|
||||
|
||||
return switch (type) {
|
||||
case PONCTUEL -> dateSpecifique != null && dateSpecifique.equals(date);
|
||||
case RECURRENT -> jourSemaine != null && date.getDayOfWeek() == jourSemaine;
|
||||
case URGENCE, FLEXIBLE -> true;
|
||||
};
|
||||
}
|
||||
|
||||
/** Vérifie si une heure est dans le créneau */
|
||||
public boolean contientHeure(LocalTime heure) {
|
||||
if (!isValide()) return false;
|
||||
return !heure.isBefore(heureDebut) && !heure.isAfter(heureFin);
|
||||
}
|
||||
|
||||
/** Retourne le libellé du créneau */
|
||||
public String getLibelle() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (type == TypeCreneau.RECURRENT && jourSemaine != null) {
|
||||
sb.append(jourSemaine.name()).append(" ");
|
||||
} else if (type == TypeCreneau.PONCTUEL && dateSpecifique != null) {
|
||||
sb.append(dateSpecifique.toString()).append(" ");
|
||||
}
|
||||
|
||||
sb.append(heureDebut.toString()).append(" - ").append(heureFin.toString());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO pour les critères de sélection des bénéficiaires
|
||||
*
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -18,54 +18,37 @@ import lombok.Builder;
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class CritereSelectionDTO {
|
||||
|
||||
/**
|
||||
* Nom du critère
|
||||
*/
|
||||
@NotBlank(message = "Le nom du critère est obligatoire")
|
||||
@Size(max = 100, message = "Le nom ne peut pas dépasser 100 caractères")
|
||||
private String nom;
|
||||
|
||||
/**
|
||||
* Type de critère (age, situation, localisation, etc.)
|
||||
*/
|
||||
@NotBlank(message = "Le type de critère est obligatoire")
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* Opérateur de comparaison (equals, greater_than, less_than, contains, etc.)
|
||||
*/
|
||||
@NotBlank(message = "L'opérateur est obligatoire")
|
||||
private String operateur;
|
||||
|
||||
/**
|
||||
* Valeur de référence pour la comparaison
|
||||
*/
|
||||
@NotBlank(message = "La valeur est obligatoire")
|
||||
private String valeur;
|
||||
|
||||
/**
|
||||
* Valeur maximale (pour les plages)
|
||||
*/
|
||||
private String valeurMax;
|
||||
|
||||
/**
|
||||
* Indique si le critère est obligatoire
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estObligatoire = false;
|
||||
|
||||
/**
|
||||
* Poids du critère dans la sélection (1-10)
|
||||
*/
|
||||
@Min(value = 1, message = "Le poids doit être au moins 1")
|
||||
@Max(value = 10, message = "Le poids ne peut pas dépasser 10")
|
||||
@Builder.Default
|
||||
private Integer poids = 5;
|
||||
|
||||
/**
|
||||
* Description du critère
|
||||
*/
|
||||
@Size(max = 200, message = "La description ne peut pas dépasser 200 caractères")
|
||||
private String description;
|
||||
|
||||
/** Nom du critère */
|
||||
@NotBlank(message = "Le nom du critère est obligatoire")
|
||||
@Size(max = 100, message = "Le nom ne peut pas dépasser 100 caractères")
|
||||
private String nom;
|
||||
|
||||
/** Type de critère (age, situation, localisation, etc.) */
|
||||
@NotBlank(message = "Le type de critère est obligatoire")
|
||||
private String type;
|
||||
|
||||
/** Opérateur de comparaison (equals, greater_than, less_than, contains, etc.) */
|
||||
@NotBlank(message = "L'opérateur est obligatoire")
|
||||
private String operateur;
|
||||
|
||||
/** Valeur de référence pour la comparaison */
|
||||
@NotBlank(message = "La valeur est obligatoire")
|
||||
private String valeur;
|
||||
|
||||
/** Valeur maximale (pour les plages) */
|
||||
private String valeurMax;
|
||||
|
||||
/** Indique si le critère est obligatoire */
|
||||
@Builder.Default private Boolean estObligatoire = false;
|
||||
|
||||
/** Poids du critère dans la sélection (1-10) */
|
||||
@Min(value = 1, message = "Le poids doit être au moins 1")
|
||||
@Max(value = 10, message = "Le poids ne peut pas dépasser 10")
|
||||
@Builder.Default
|
||||
private Integer poids = 5;
|
||||
|
||||
/** Description du critère */
|
||||
@Size(max = 200, message = "La description ne peut pas dépasser 200 caractères")
|
||||
private String description;
|
||||
}
|
||||
|
||||
@@ -1,374 +1,468 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.PrioriteAide;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
|
||||
import dev.lions.unionflow.server.api.validation.ValidationConstants;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Digits;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* DTO pour les demandes d'aide dans le système de solidarité
|
||||
*
|
||||
* Ce DTO représente une demande d'aide complète avec toutes les informations
|
||||
* nécessaires pour le traitement, l'évaluation et le suivi.
|
||||
*
|
||||
* DTO unifié pour les demandes d'aide dans le système de solidarité
|
||||
*
|
||||
* <p>Ce DTO représente une demande d'aide complète avec toutes les informations nécessaires pour le
|
||||
* traitement, l'évaluation et le suivi. Remplace l'ancien AideDTO pour une approche unifiée.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @version 2.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class DemandeAideDTO {
|
||||
|
||||
// === IDENTIFICATION ===
|
||||
|
||||
/**
|
||||
* Identifiant unique de la demande d'aide
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Numéro de référence de la demande (généré automatiquement)
|
||||
*/
|
||||
@Pattern(regexp = "^DA-\\d{4}-\\d{6}$", message = "Le numéro de référence doit suivre le format DA-YYYY-NNNNNN")
|
||||
private String numeroReference;
|
||||
|
||||
// === INFORMATIONS DE BASE ===
|
||||
|
||||
/**
|
||||
* Type d'aide demandée
|
||||
*/
|
||||
@NotNull(message = "Le type d'aide est obligatoire")
|
||||
private TypeAide typeAide;
|
||||
|
||||
/**
|
||||
* Titre court de la demande
|
||||
*/
|
||||
@NotBlank(message = "Le titre est obligatoire")
|
||||
@Size(min = 10, max = 100, message = "Le titre doit contenir entre 10 et 100 caractères")
|
||||
private String titre;
|
||||
|
||||
/**
|
||||
* Description détaillée de la demande
|
||||
*/
|
||||
@NotBlank(message = "La description est obligatoire")
|
||||
@Size(min = 50, max = 2000, message = "La description doit contenir entre 50 et 2000 caractères")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* Justification de la demande
|
||||
*/
|
||||
@Size(max = 1000, message = "La justification ne peut pas dépasser 1000 caractères")
|
||||
private String justification;
|
||||
|
||||
// === MONTANT ET FINANCES ===
|
||||
|
||||
/**
|
||||
* Montant demandé (si applicable)
|
||||
*/
|
||||
@DecimalMin(value = "0.0", inclusive = false, message = "Le montant doit être positif")
|
||||
@DecimalMax(value = "1000000.0", message = "Le montant ne peut pas dépasser 1 000 000 FCFA")
|
||||
private Double montantDemande;
|
||||
|
||||
/**
|
||||
* Montant approuvé (si différent du montant demandé)
|
||||
*/
|
||||
@DecimalMin(value = "0.0", inclusive = false, message = "Le montant approuvé doit être positif")
|
||||
private Double montantApprouve;
|
||||
|
||||
/**
|
||||
* Montant versé effectivement
|
||||
*/
|
||||
@DecimalMin(value = "0.0", inclusive = false, message = "Le montant versé doit être positif")
|
||||
private Double montantVerse;
|
||||
|
||||
/**
|
||||
* Devise du montant
|
||||
*/
|
||||
@Builder.Default
|
||||
private String devise = "FCFA";
|
||||
|
||||
// === ACTEURS ===
|
||||
|
||||
/**
|
||||
* Identifiant du demandeur
|
||||
*/
|
||||
@NotBlank(message = "L'identifiant du demandeur est obligatoire")
|
||||
private String demandeurId;
|
||||
|
||||
/**
|
||||
* Nom complet du demandeur
|
||||
*/
|
||||
private String demandeurNom;
|
||||
|
||||
/**
|
||||
* Identifiant de l'évaluateur assigné
|
||||
*/
|
||||
private String evaluateurId;
|
||||
|
||||
/**
|
||||
* Nom de l'évaluateur
|
||||
*/
|
||||
private String evaluateurNom;
|
||||
|
||||
/**
|
||||
* Identifiant de l'approbateur
|
||||
*/
|
||||
private String approvateurId;
|
||||
|
||||
/**
|
||||
* Nom de l'approbateur
|
||||
*/
|
||||
private String approvateurNom;
|
||||
|
||||
/**
|
||||
* Identifiant de l'organisation
|
||||
*/
|
||||
@NotBlank(message = "L'identifiant de l'organisation est obligatoire")
|
||||
private String organisationId;
|
||||
|
||||
// === STATUT ET PRIORITÉ ===
|
||||
|
||||
/**
|
||||
* Statut actuel de la demande
|
||||
*/
|
||||
@NotNull(message = "Le statut est obligatoire")
|
||||
@Builder.Default
|
||||
private StatutAide statut = StatutAide.BROUILLON;
|
||||
|
||||
/**
|
||||
* Priorité de la demande
|
||||
*/
|
||||
@NotNull(message = "La priorité est obligatoire")
|
||||
@Builder.Default
|
||||
private PrioriteAide priorite = PrioriteAide.NORMALE;
|
||||
|
||||
/**
|
||||
* Motif de rejet (si applicable)
|
||||
*/
|
||||
@Size(max = 500, message = "Le motif de rejet ne peut pas dépasser 500 caractères")
|
||||
private String motifRejet;
|
||||
|
||||
/**
|
||||
* Commentaires de l'évaluateur
|
||||
*/
|
||||
@Size(max = 1000, message = "Les commentaires ne peuvent pas dépasser 1000 caractères")
|
||||
private String commentairesEvaluateur;
|
||||
|
||||
// === DATES ===
|
||||
|
||||
/**
|
||||
* Date de création de la demande
|
||||
*/
|
||||
@NotNull(message = "La date de création est obligatoire")
|
||||
@Builder.Default
|
||||
private LocalDateTime dateCreation = LocalDateTime.now();
|
||||
|
||||
/**
|
||||
* Date de soumission de la demande
|
||||
*/
|
||||
private LocalDateTime dateSoumission;
|
||||
|
||||
/**
|
||||
* Date limite de traitement
|
||||
*/
|
||||
private LocalDateTime dateLimiteTraitement;
|
||||
|
||||
/**
|
||||
* Date d'évaluation
|
||||
*/
|
||||
private LocalDateTime dateEvaluation;
|
||||
|
||||
/**
|
||||
* Date d'approbation
|
||||
*/
|
||||
private LocalDateTime dateApprobation;
|
||||
|
||||
/**
|
||||
* Date de versement
|
||||
*/
|
||||
private LocalDateTime dateVersement;
|
||||
|
||||
/**
|
||||
* Date de clôture
|
||||
*/
|
||||
private LocalDateTime dateCloture;
|
||||
|
||||
/**
|
||||
* Date de dernière modification
|
||||
*/
|
||||
@Builder.Default
|
||||
private LocalDateTime dateModification = LocalDateTime.now();
|
||||
|
||||
// === INFORMATIONS COMPLÉMENTAIRES ===
|
||||
|
||||
/**
|
||||
* Pièces justificatives attachées
|
||||
*/
|
||||
private List<PieceJustificativeDTO> piecesJustificatives;
|
||||
|
||||
/**
|
||||
* Bénéficiaires de l'aide (si différents du demandeur)
|
||||
*/
|
||||
private List<BeneficiaireAideDTO> beneficiaires;
|
||||
|
||||
/**
|
||||
* Historique des changements de statut
|
||||
*/
|
||||
private List<HistoriqueStatutDTO> historiqueStatuts;
|
||||
|
||||
/**
|
||||
* Commentaires et échanges
|
||||
*/
|
||||
private List<CommentaireAideDTO> commentaires;
|
||||
|
||||
/**
|
||||
* Données personnalisées spécifiques au type d'aide
|
||||
*/
|
||||
private Map<String, Object> donneesPersonnalisees;
|
||||
|
||||
/**
|
||||
* Tags pour catégorisation
|
||||
*/
|
||||
private List<String> tags;
|
||||
|
||||
// === MÉTADONNÉES ===
|
||||
|
||||
/**
|
||||
* Indique si la demande est confidentielle
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estConfidentielle = false;
|
||||
|
||||
/**
|
||||
* Indique si la demande nécessite un suivi
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean necessiteSuivi = false;
|
||||
|
||||
/**
|
||||
* Score de priorité calculé automatiquement
|
||||
*/
|
||||
private Double scorePriorite;
|
||||
|
||||
/**
|
||||
* Nombre de vues de la demande
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer nombreVues = 0;
|
||||
|
||||
/**
|
||||
* Version du document (pour gestion des conflits)
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer version = 1;
|
||||
|
||||
/**
|
||||
* Informations de géolocalisation (si pertinent)
|
||||
*/
|
||||
private LocalisationDTO localisation;
|
||||
|
||||
/**
|
||||
* Informations de contact d'urgence
|
||||
*/
|
||||
private ContactUrgenceDTO contactUrgence;
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Vérifie si la demande est modifiable
|
||||
*/
|
||||
public boolean isModifiable() {
|
||||
return statut != null && statut.permetModification();
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class DemandeAideDTO extends BaseDTO {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// === IDENTIFICATION ===
|
||||
|
||||
// ID hérité de BaseDTO
|
||||
|
||||
/** Numéro de référence de la demande (généré automatiquement) */
|
||||
@Pattern(
|
||||
regexp = ValidationConstants.REFERENCE_AIDE_PATTERN,
|
||||
message = ValidationConstants.REFERENCE_AIDE_MESSAGE)
|
||||
private String numeroReference;
|
||||
|
||||
// === INFORMATIONS DE BASE ===
|
||||
|
||||
/** Type d'aide demandée */
|
||||
@NotNull(message = "Le type d'aide est obligatoire.")
|
||||
private TypeAide typeAide;
|
||||
|
||||
/** Titre court de la demande */
|
||||
@NotBlank(message = "Le titre" + ValidationConstants.OBLIGATOIRE_MESSAGE)
|
||||
@Size(
|
||||
min = ValidationConstants.TITRE_MIN_LENGTH,
|
||||
max = ValidationConstants.TITRE_MAX_LENGTH,
|
||||
message = ValidationConstants.TITRE_SIZE_MESSAGE)
|
||||
private String titre;
|
||||
|
||||
/** Description détaillée de la demande */
|
||||
@NotBlank(message = "La description" + ValidationConstants.OBLIGATOIRE_MESSAGE)
|
||||
@Size(
|
||||
min = ValidationConstants.DESCRIPTION_MIN_LENGTH,
|
||||
max = ValidationConstants.DESCRIPTION_MAX_LENGTH,
|
||||
message = ValidationConstants.DESCRIPTION_SIZE_MESSAGE)
|
||||
private String description;
|
||||
|
||||
/** Justification de la demande */
|
||||
@Size(
|
||||
max = ValidationConstants.JUSTIFICATION_MAX_LENGTH,
|
||||
message = ValidationConstants.JUSTIFICATION_SIZE_MESSAGE)
|
||||
private String justification;
|
||||
|
||||
// === MONTANT ET FINANCES ===
|
||||
|
||||
/** Montant demandé (si applicable) */
|
||||
@DecimalMin(
|
||||
value = ValidationConstants.MONTANT_MIN_VALUE,
|
||||
inclusive = false,
|
||||
message = ValidationConstants.MONTANT_POSITIF_MESSAGE)
|
||||
@Digits(
|
||||
integer = ValidationConstants.MONTANT_INTEGER_DIGITS,
|
||||
fraction = ValidationConstants.MONTANT_FRACTION_DIGITS,
|
||||
message = ValidationConstants.MONTANT_DIGITS_MESSAGE)
|
||||
private BigDecimal montantDemande;
|
||||
|
||||
/** Montant approuvé (si différent du montant demandé) */
|
||||
@DecimalMin(
|
||||
value = ValidationConstants.MONTANT_MIN_VALUE,
|
||||
inclusive = false,
|
||||
message = ValidationConstants.MONTANT_POSITIF_MESSAGE)
|
||||
@Digits(
|
||||
integer = ValidationConstants.MONTANT_INTEGER_DIGITS,
|
||||
fraction = ValidationConstants.MONTANT_FRACTION_DIGITS,
|
||||
message = ValidationConstants.MONTANT_DIGITS_MESSAGE)
|
||||
private BigDecimal montantApprouve;
|
||||
|
||||
/** Montant versé effectivement */
|
||||
@DecimalMin(
|
||||
value = ValidationConstants.MONTANT_MIN_VALUE,
|
||||
inclusive = false,
|
||||
message = ValidationConstants.MONTANT_POSITIF_MESSAGE)
|
||||
@Digits(
|
||||
integer = ValidationConstants.MONTANT_INTEGER_DIGITS,
|
||||
fraction = ValidationConstants.MONTANT_FRACTION_DIGITS,
|
||||
message = ValidationConstants.MONTANT_DIGITS_MESSAGE)
|
||||
private BigDecimal montantVerse;
|
||||
|
||||
/** Devise du montant (code ISO 3 lettres) */
|
||||
@Pattern(
|
||||
regexp = ValidationConstants.DEVISE_PATTERN,
|
||||
message = ValidationConstants.DEVISE_MESSAGE)
|
||||
private String devise = "XOF";
|
||||
|
||||
// === ACTEURS ===
|
||||
|
||||
/** Identifiant du demandeur (UUID) */
|
||||
@NotNull(message = "L'identifiant du demandeur est obligatoire")
|
||||
private UUID membreDemandeurId;
|
||||
|
||||
/** Nom complet du demandeur */
|
||||
private String nomDemandeur;
|
||||
|
||||
/** Numéro de membre du demandeur */
|
||||
private String numeroMembreDemandeur;
|
||||
|
||||
/** Identifiant de l'évaluateur assigné */
|
||||
private String evaluateurId;
|
||||
|
||||
/** Nom de l'évaluateur */
|
||||
private String evaluateurNom;
|
||||
|
||||
/** Identifiant de l'approbateur */
|
||||
private String approvateurId;
|
||||
|
||||
/** Nom de l'approbateur */
|
||||
private String approvateurNom;
|
||||
|
||||
/** Identifiant de l'organisation (UUID) */
|
||||
@NotNull(message = "L'identifiant de l'organisation est obligatoire")
|
||||
private UUID associationId;
|
||||
|
||||
/** Nom de l'association */
|
||||
private String nomAssociation;
|
||||
|
||||
// === STATUT ET PRIORITÉ ===
|
||||
|
||||
/** Statut actuel de la demande */
|
||||
@NotNull(message = "Le statut est obligatoire")
|
||||
private StatutAide statut = StatutAide.BROUILLON;
|
||||
|
||||
/** Priorité de la demande */
|
||||
@NotNull(message = "La priorité est obligatoire")
|
||||
private PrioriteAide priorite = PrioriteAide.NORMALE;
|
||||
|
||||
/** Motif de rejet (si applicable) */
|
||||
@Size(max = 500, message = "Le motif de rejet ne peut pas dépasser 500 caractères")
|
||||
private String motifRejet;
|
||||
|
||||
/** Commentaires de l'évaluateur */
|
||||
@Size(max = 1000, message = "Les commentaires ne peuvent pas dépasser 1000 caractères")
|
||||
private String commentairesEvaluateur;
|
||||
|
||||
// === DATES ===
|
||||
|
||||
// Date de création héritée de BaseDTO
|
||||
|
||||
/** Date de soumission de la demande */
|
||||
private LocalDateTime dateSoumission;
|
||||
|
||||
/** Date limite de traitement */
|
||||
private LocalDateTime dateLimiteTraitement;
|
||||
|
||||
/** Date d'évaluation */
|
||||
private LocalDateTime dateEvaluation;
|
||||
|
||||
/** Date d'approbation */
|
||||
private LocalDateTime dateApprobation;
|
||||
|
||||
/** Date de versement */
|
||||
private LocalDateTime dateVersement;
|
||||
|
||||
/** Date de clôture */
|
||||
private LocalDateTime dateCloture;
|
||||
|
||||
// Date de modification héritée de BaseDTO
|
||||
|
||||
// === INFORMATIONS COMPLÉMENTAIRES ===
|
||||
|
||||
/** Pièces justificatives attachées */
|
||||
private List<PieceJustificativeDTO> piecesJustificatives;
|
||||
|
||||
/** Bénéficiaires de l'aide (si différents du demandeur) */
|
||||
private List<BeneficiaireAideDTO> beneficiaires;
|
||||
|
||||
/** Historique des changements de statut */
|
||||
private List<HistoriqueStatutDTO> historiqueStatuts;
|
||||
|
||||
/** Commentaires et échanges */
|
||||
private List<CommentaireAideDTO> commentaires;
|
||||
|
||||
/** Données personnalisées spécifiques au type d'aide */
|
||||
private Map<String, Object> donneesPersonnalisees;
|
||||
|
||||
/** Tags pour catégorisation */
|
||||
private List<String> tags;
|
||||
|
||||
// === MÉTADONNÉES ===
|
||||
|
||||
/** Indique si la demande est confidentielle */
|
||||
private Boolean estConfidentielle = false;
|
||||
|
||||
/** Indique si la demande nécessite un suivi */
|
||||
private Boolean necessiteSuivi = false;
|
||||
|
||||
/** Score de priorité calculé automatiquement */
|
||||
private Double scorePriorite;
|
||||
|
||||
/** Nombre de vues de la demande */
|
||||
private Integer nombreVues = 0;
|
||||
|
||||
// Version héritée de BaseDTO
|
||||
|
||||
/** Informations de géolocalisation (si pertinent) */
|
||||
private LocalisationDTO localisation;
|
||||
|
||||
/** Informations de contact d'urgence */
|
||||
private ContactUrgenceDTO contactUrgence;
|
||||
|
||||
// === CHAMPS ADDITIONNELS D'AIDE ===
|
||||
|
||||
/** Date limite pour l'aide */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate dateLimite;
|
||||
|
||||
/** Justificatifs fournis */
|
||||
private Boolean justificatifsFournis = false;
|
||||
|
||||
/** Liste des documents joints (noms de fichiers) */
|
||||
@Size(max = 1000, message = "La liste des documents ne peut pas dépasser 1000 caractères")
|
||||
private String documentsJoints;
|
||||
|
||||
/** Date de début de l'aide */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate dateDebutAide;
|
||||
|
||||
/** Date de fin de l'aide */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate dateFinAide;
|
||||
|
||||
/** Identifiant du membre aidant */
|
||||
private UUID membreAidantId;
|
||||
|
||||
/** Nom du membre aidant */
|
||||
private String nomAidant;
|
||||
|
||||
/** Mode de versement */
|
||||
@Size(max = 50, message = "Le mode de versement ne peut pas dépasser 50 caractères")
|
||||
private String modeVersement;
|
||||
|
||||
/** Numéro de transaction */
|
||||
@Size(max = 100, message = "Le numéro de transaction ne peut pas dépasser 100 caractères")
|
||||
private String numeroTransaction;
|
||||
|
||||
/** Identifiant de celui qui a rejeté */
|
||||
private UUID rejeteParId;
|
||||
|
||||
/** Nom de celui qui a rejeté */
|
||||
private String rejetePar;
|
||||
|
||||
/** Date de rejet */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateRejet;
|
||||
|
||||
/** Raison du rejet (si applicable) */
|
||||
@Size(max = 500, message = "La raison du rejet ne peut pas dépasser 500 caractères")
|
||||
private String raisonRejet;
|
||||
|
||||
// === CONSTRUCTEURS ===
|
||||
|
||||
/** Constructeur par défaut */
|
||||
public DemandeAideDTO() {
|
||||
super(); // Appelle le constructeur de BaseDTO qui génère l'UUID
|
||||
this.statut = StatutAide.EN_ATTENTE;
|
||||
this.priorite = PrioriteAide.NORMALE;
|
||||
this.devise = "XOF";
|
||||
this.nombreVues = 0;
|
||||
this.numeroReference = genererNumeroReference();
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/** Vérifie si la demande est modifiable */
|
||||
public boolean estModifiable() {
|
||||
return statut != null && statut.permetModification();
|
||||
}
|
||||
|
||||
/** Vérifie si la demande peut être annulée */
|
||||
public boolean peutEtreAnnulee() {
|
||||
return statut != null && statut.permetAnnulation();
|
||||
}
|
||||
|
||||
/** Vérifie si la demande est urgente */
|
||||
public boolean estUrgente() {
|
||||
return priorite != null && priorite.isUrgente();
|
||||
}
|
||||
|
||||
/** Vérifie si la demande est terminée */
|
||||
public boolean estTerminee() {
|
||||
return statut != null && statut.isEstFinal();
|
||||
}
|
||||
|
||||
/** Vérifie si la demande est en succès */
|
||||
public boolean estEnSucces() {
|
||||
return statut != null && statut.isSucces();
|
||||
}
|
||||
|
||||
/** Calcule le pourcentage d'avancement */
|
||||
public double getPourcentageAvancement() {
|
||||
if (statut == null) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la demande peut être annulée
|
||||
*/
|
||||
public boolean peutEtreAnnulee() {
|
||||
return statut != null && statut.permetAnnulation();
|
||||
|
||||
return switch (statut) {
|
||||
case BROUILLON -> 5.0;
|
||||
case SOUMISE -> 10.0;
|
||||
case EN_ATTENTE -> 20.0;
|
||||
case EN_COURS_EVALUATION -> 40.0;
|
||||
case INFORMATIONS_REQUISES -> 35.0;
|
||||
case APPROUVEE, APPROUVEE_PARTIELLEMENT -> 60.0;
|
||||
case EN_COURS_TRAITEMENT -> 70.0;
|
||||
case EN_COURS_VERSEMENT -> 85.0;
|
||||
case VERSEE, LIVREE, TERMINEE -> 100.0;
|
||||
case REJETEE, ANNULEE, EXPIREE -> 100.0;
|
||||
case SUSPENDUE -> 50.0;
|
||||
case EN_SUIVI -> 95.0;
|
||||
case CLOTUREE -> 100.0;
|
||||
};
|
||||
}
|
||||
|
||||
/** Retourne le délai restant en heures */
|
||||
public long getDelaiRestantHeures() {
|
||||
if (dateLimiteTraitement == null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la demande est urgente
|
||||
*/
|
||||
public boolean isUrgente() {
|
||||
return priorite != null && priorite.isUrgente();
|
||||
|
||||
LocalDateTime maintenant = LocalDateTime.now();
|
||||
if (maintenant.isAfter(dateLimiteTraitement)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la demande est terminée
|
||||
*/
|
||||
public boolean isTerminee() {
|
||||
return statut != null && statut.isEstFinal();
|
||||
|
||||
return java.time.Duration.between(maintenant, dateLimiteTraitement).toHours();
|
||||
}
|
||||
|
||||
/** Vérifie si le délai est dépassé */
|
||||
public boolean estDelaiDepasse() {
|
||||
return getDelaiRestantHeures() == 0;
|
||||
}
|
||||
|
||||
/** Retourne la durée de traitement en jours */
|
||||
public long getDureeTraitementJours() {
|
||||
if (dateCreation == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la demande est en succès
|
||||
*/
|
||||
public boolean isEnSucces() {
|
||||
return statut != null && statut.isSucces();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le pourcentage d'avancement
|
||||
*/
|
||||
public double getPourcentageAvancement() {
|
||||
if (statut == null) return 0.0;
|
||||
|
||||
return switch (statut) {
|
||||
case BROUILLON -> 5.0;
|
||||
case SOUMISE -> 10.0;
|
||||
case EN_ATTENTE -> 20.0;
|
||||
case EN_COURS_EVALUATION -> 40.0;
|
||||
case INFORMATIONS_REQUISES -> 35.0;
|
||||
case APPROUVEE, APPROUVEE_PARTIELLEMENT -> 60.0;
|
||||
case EN_COURS_TRAITEMENT -> 70.0;
|
||||
case EN_COURS_VERSEMENT -> 85.0;
|
||||
case VERSEE, LIVREE, TERMINEE -> 100.0;
|
||||
case REJETEE, ANNULEE, EXPIREE -> 100.0;
|
||||
case SUSPENDUE -> 50.0;
|
||||
case EN_SUIVI -> 95.0;
|
||||
case CLOTUREE -> 100.0;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le délai restant en heures
|
||||
*/
|
||||
public long getDelaiRestantHeures() {
|
||||
if (dateLimiteTraitement == null) return -1;
|
||||
|
||||
LocalDateTime maintenant = LocalDateTime.now();
|
||||
if (maintenant.isAfter(dateLimiteTraitement)) return 0;
|
||||
|
||||
return java.time.Duration.between(maintenant, dateLimiteTraitement).toHours();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le délai est dépassé
|
||||
*/
|
||||
public boolean isDelaiDepasse() {
|
||||
return getDelaiRestantHeures() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la durée de traitement en jours
|
||||
*/
|
||||
public long getDureeTraitementJours() {
|
||||
if (dateCreation == null) return 0;
|
||||
|
||||
LocalDateTime dateFin = dateCloture != null ? dateCloture : LocalDateTime.now();
|
||||
return java.time.Duration.between(dateCreation, dateFin).toDays();
|
||||
|
||||
LocalDateTime dateFin = dateCloture != null ? dateCloture : LocalDateTime.now();
|
||||
return java.time.Duration.between(dateCreation, dateFin).toDays();
|
||||
}
|
||||
|
||||
// === MÉTHODES MÉTIER D'AIDE ===
|
||||
|
||||
/** Retourne le libellé du statut */
|
||||
public String getStatutLibelle() {
|
||||
return statut != null ? statut.getLibelle() : "Non défini";
|
||||
}
|
||||
|
||||
/** Retourne le libellé de la priorité */
|
||||
public String getPrioriteLibelle() {
|
||||
return priorite != null ? priorite.getLibelle() : "Normale";
|
||||
}
|
||||
|
||||
/** Approuve la demande d'aide */
|
||||
public void approuver(
|
||||
UUID evaluateurId, String nomEvaluateur, BigDecimal montantApprouve, String commentaires) {
|
||||
this.statut = StatutAide.APPROUVEE;
|
||||
this.evaluateurId = evaluateurId.toString();
|
||||
this.evaluateurNom = nomEvaluateur;
|
||||
this.montantApprouve = montantApprouve;
|
||||
this.commentairesEvaluateur = commentaires;
|
||||
this.dateEvaluation = LocalDateTime.now();
|
||||
this.dateApprobation = LocalDateTime.now();
|
||||
marquerCommeModifie(nomEvaluateur);
|
||||
}
|
||||
|
||||
/** Rejette la demande d'aide */
|
||||
public void rejeter(UUID evaluateurId, String nomEvaluateur, String raison) {
|
||||
this.statut = StatutAide.REJETEE;
|
||||
this.rejeteParId = evaluateurId;
|
||||
this.rejetePar = nomEvaluateur;
|
||||
this.raisonRejet = raison;
|
||||
this.dateRejet = LocalDateTime.now();
|
||||
this.dateEvaluation = LocalDateTime.now();
|
||||
marquerCommeModifie(nomEvaluateur);
|
||||
}
|
||||
|
||||
/** Démarre l'aide */
|
||||
public void demarrerAide(UUID aidantId, String nomAidant) {
|
||||
this.statut = StatutAide.EN_COURS_TRAITEMENT;
|
||||
this.membreAidantId = aidantId;
|
||||
this.nomAidant = nomAidant;
|
||||
this.dateDebutAide = LocalDate.now();
|
||||
marquerCommeModifie(nomAidant);
|
||||
}
|
||||
|
||||
/** Termine l'aide avec versement */
|
||||
public void terminerAvecVersement(
|
||||
BigDecimal montantVerse, String modeVersement, String numeroTransaction) {
|
||||
this.statut = StatutAide.TERMINEE;
|
||||
this.montantVerse = montantVerse;
|
||||
this.modeVersement = modeVersement;
|
||||
this.numeroTransaction = numeroTransaction;
|
||||
this.dateVersement = LocalDateTime.now();
|
||||
this.dateFinAide = LocalDate.now();
|
||||
marquerCommeModifie("SYSTEM");
|
||||
}
|
||||
|
||||
/** Incrémente le nombre de vues */
|
||||
public void incrementerVues() {
|
||||
if (nombreVues == null) {
|
||||
nombreVues = 1;
|
||||
} else {
|
||||
nombreVues++;
|
||||
}
|
||||
}
|
||||
|
||||
/** Génère un numéro de référence unique */
|
||||
public static String genererNumeroReference() {
|
||||
return "DA-"
|
||||
+ LocalDate.now().getYear()
|
||||
+ "-"
|
||||
+ String.format("%06d", (int) (Math.random() * 1000000));
|
||||
}
|
||||
|
||||
// === GETTERS EXPLICITES POUR COMPATIBILITÉ ===
|
||||
|
||||
/** Retourne le type d'aide demandée */
|
||||
public TypeAide getTypeAide() {
|
||||
return typeAide;
|
||||
}
|
||||
|
||||
/** Retourne le montant demandé */
|
||||
public BigDecimal getMontantDemande() {
|
||||
return montantDemande;
|
||||
}
|
||||
|
||||
/** Marque comme modifié */
|
||||
public void marquerCommeModifie(String utilisateur) {
|
||||
LocalDateTime maintenant = LocalDateTime.now();
|
||||
this.dateModification = maintenant;
|
||||
super.marquerCommeModifie(utilisateur);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO pour l'évaluation d'une aide reçue ou fournie
|
||||
*
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -22,326 +21,236 @@ import java.util.Map;
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class EvaluationAideDTO {
|
||||
|
||||
/**
|
||||
* Identifiant unique de l'évaluation
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Identifiant de la demande d'aide évaluée
|
||||
*/
|
||||
@NotBlank(message = "L'identifiant de la demande d'aide est obligatoire")
|
||||
private String demandeAideId;
|
||||
|
||||
/**
|
||||
* Identifiant de la proposition d'aide évaluée (si applicable)
|
||||
*/
|
||||
private String propositionAideId;
|
||||
|
||||
/**
|
||||
* Identifiant de l'évaluateur
|
||||
*/
|
||||
@NotBlank(message = "L'identifiant de l'évaluateur est obligatoire")
|
||||
private String evaluateurId;
|
||||
|
||||
/**
|
||||
* Nom de l'évaluateur
|
||||
*/
|
||||
private String evaluateurNom;
|
||||
|
||||
/**
|
||||
* Rôle de l'évaluateur (beneficiaire, proposant, evaluateur_externe)
|
||||
*/
|
||||
@NotBlank(message = "Le rôle de l'évaluateur est obligatoire")
|
||||
private String roleEvaluateur;
|
||||
|
||||
/**
|
||||
* Type d'évaluation
|
||||
*/
|
||||
@NotNull(message = "Le type d'évaluation est obligatoire")
|
||||
@Builder.Default
|
||||
private TypeEvaluation typeEvaluation = TypeEvaluation.SATISFACTION_BENEFICIAIRE;
|
||||
|
||||
/**
|
||||
* Note globale (1-5)
|
||||
*/
|
||||
@NotNull(message = "La note globale est obligatoire")
|
||||
@DecimalMin(value = "1.0", message = "La note doit être au moins 1")
|
||||
@DecimalMax(value = "5.0", message = "La note ne peut pas dépasser 5")
|
||||
private Double noteGlobale;
|
||||
|
||||
/**
|
||||
* Notes détaillées par critère
|
||||
*/
|
||||
private Map<String, Double> notesDetaillees;
|
||||
|
||||
/**
|
||||
* Commentaire principal
|
||||
*/
|
||||
@Size(min = 10, max = 1000, message = "Le commentaire doit contenir entre 10 et 1000 caractères")
|
||||
private String commentairePrincipal;
|
||||
|
||||
/**
|
||||
* Points positifs
|
||||
*/
|
||||
@Size(max = 500, message = "Les points positifs ne peuvent pas dépasser 500 caractères")
|
||||
private String pointsPositifs;
|
||||
|
||||
/**
|
||||
* Points d'amélioration
|
||||
*/
|
||||
@Size(max = 500, message = "Les points d'amélioration ne peuvent pas dépasser 500 caractères")
|
||||
private String pointsAmelioration;
|
||||
|
||||
/**
|
||||
* Recommandations
|
||||
*/
|
||||
@Size(max = 500, message = "Les recommandations ne peuvent pas dépasser 500 caractères")
|
||||
private String recommandations;
|
||||
|
||||
/**
|
||||
* Indique si l'évaluateur recommande cette aide/proposant
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean recommande = true;
|
||||
|
||||
/**
|
||||
* Indique si l'aide a été utile
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean aideUtile = true;
|
||||
|
||||
/**
|
||||
* Indique si l'aide a résolu le problème
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean problemeResolu = true;
|
||||
|
||||
/**
|
||||
* Délai de réponse perçu (1=très lent, 5=très rapide)
|
||||
*/
|
||||
@DecimalMin(value = "1.0", message = "La note délai doit être au moins 1")
|
||||
@DecimalMax(value = "5.0", message = "La note délai ne peut pas dépasser 5")
|
||||
private Double noteDelaiReponse;
|
||||
|
||||
/**
|
||||
* Qualité de la communication (1=très mauvaise, 5=excellente)
|
||||
*/
|
||||
@DecimalMin(value = "1.0", message = "La note communication doit être au moins 1")
|
||||
@DecimalMax(value = "5.0", message = "La note communication ne peut pas dépasser 5")
|
||||
private Double noteCommunication;
|
||||
|
||||
/**
|
||||
* Professionnalisme (1=très mauvais, 5=excellent)
|
||||
*/
|
||||
@DecimalMin(value = "1.0", message = "La note professionnalisme doit être au moins 1")
|
||||
@DecimalMax(value = "5.0", message = "La note professionnalisme ne peut pas dépasser 5")
|
||||
private Double noteProfessionnalisme;
|
||||
|
||||
/**
|
||||
* Respect des engagements (1=très mauvais, 5=excellent)
|
||||
*/
|
||||
@DecimalMin(value = "1.0", message = "La note engagement doit être au moins 1")
|
||||
@DecimalMax(value = "5.0", message = "La note engagement ne peut pas dépasser 5")
|
||||
private Double noteRespectEngagements;
|
||||
|
||||
/**
|
||||
* Date de création de l'évaluation
|
||||
*/
|
||||
@NotNull(message = "La date de création est obligatoire")
|
||||
@Builder.Default
|
||||
private LocalDateTime dateCreation = LocalDateTime.now();
|
||||
|
||||
/**
|
||||
* Date de dernière modification
|
||||
*/
|
||||
@Builder.Default
|
||||
private LocalDateTime dateModification = LocalDateTime.now();
|
||||
|
||||
/**
|
||||
* Indique si l'évaluation est publique
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estPublique = true;
|
||||
|
||||
/**
|
||||
* Indique si l'évaluation est anonyme
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estAnonyme = false;
|
||||
|
||||
/**
|
||||
* Indique si l'évaluation a été vérifiée
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estVerifiee = false;
|
||||
|
||||
/**
|
||||
* Date de vérification
|
||||
*/
|
||||
private LocalDateTime dateVerification;
|
||||
|
||||
/**
|
||||
* Identifiant du vérificateur
|
||||
*/
|
||||
private String verificateurId;
|
||||
|
||||
/**
|
||||
* Pièces jointes à l'évaluation (photos, documents)
|
||||
*/
|
||||
private List<PieceJustificativeDTO> piecesJointes;
|
||||
|
||||
/**
|
||||
* Tags associés à l'évaluation
|
||||
*/
|
||||
private List<String> tags;
|
||||
|
||||
/**
|
||||
* Données additionnelles
|
||||
*/
|
||||
private Map<String, Object> donneesAdditionnelles;
|
||||
|
||||
/**
|
||||
* Nombre de personnes qui ont trouvé cette évaluation utile
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer nombreUtile = 0;
|
||||
|
||||
/**
|
||||
* Nombre de signalements de cette évaluation
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer nombreSignalements = 0;
|
||||
|
||||
/**
|
||||
* Statut de l'évaluation
|
||||
*/
|
||||
@NotNull(message = "Le statut est obligatoire")
|
||||
@Builder.Default
|
||||
private StatutEvaluation statut = StatutEvaluation.ACTIVE;
|
||||
|
||||
/**
|
||||
* Énumération des types d'évaluation
|
||||
*/
|
||||
public enum TypeEvaluation {
|
||||
SATISFACTION_BENEFICIAIRE("Satisfaction du bénéficiaire"),
|
||||
EVALUATION_PROPOSANT("Évaluation du proposant"),
|
||||
EVALUATION_PROCESSUS("Évaluation du processus"),
|
||||
SUIVI_POST_AIDE("Suivi post-aide"),
|
||||
EVALUATION_IMPACT("Évaluation d'impact"),
|
||||
RETOUR_EXPERIENCE("Retour d'expérience");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
TypeEvaluation(String libelle) {
|
||||
this.libelle = libelle;
|
||||
}
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/** Identifiant unique de l'évaluation */
|
||||
private String id;
|
||||
|
||||
/** Identifiant de la demande d'aide évaluée */
|
||||
@NotBlank(message = "L'identifiant de la demande d'aide est obligatoire")
|
||||
private String demandeAideId;
|
||||
|
||||
/** Identifiant de la proposition d'aide évaluée (si applicable) */
|
||||
private String propositionAideId;
|
||||
|
||||
/** Identifiant de l'évaluateur */
|
||||
@NotBlank(message = "L'identifiant de l'évaluateur est obligatoire")
|
||||
private String evaluateurId;
|
||||
|
||||
/** Nom de l'évaluateur */
|
||||
private String evaluateurNom;
|
||||
|
||||
/** Rôle de l'évaluateur (beneficiaire, proposant, evaluateur_externe) */
|
||||
@NotBlank(message = "Le rôle de l'évaluateur est obligatoire")
|
||||
private String roleEvaluateur;
|
||||
|
||||
/** Type d'évaluation */
|
||||
@NotNull(message = "Le type d'évaluation est obligatoire")
|
||||
@Builder.Default
|
||||
private TypeEvaluation typeEvaluation = TypeEvaluation.SATISFACTION_BENEFICIAIRE;
|
||||
|
||||
/** Note globale (1-5) */
|
||||
@NotNull(message = "La note globale est obligatoire")
|
||||
@DecimalMin(value = "1.0", message = "La note doit être au moins 1")
|
||||
@DecimalMax(value = "5.0", message = "La note ne peut pas dépasser 5")
|
||||
private Double noteGlobale;
|
||||
|
||||
/** Notes détaillées par critère */
|
||||
private Map<String, Double> notesDetaillees;
|
||||
|
||||
/** Commentaire principal */
|
||||
@Size(min = 10, max = 1000, message = "Le commentaire doit contenir entre 10 et 1000 caractères")
|
||||
private String commentairePrincipal;
|
||||
|
||||
/** Points positifs */
|
||||
@Size(max = 500, message = "Les points positifs ne peuvent pas dépasser 500 caractères")
|
||||
private String pointsPositifs;
|
||||
|
||||
/** Points d'amélioration */
|
||||
@Size(max = 500, message = "Les points d'amélioration ne peuvent pas dépasser 500 caractères")
|
||||
private String pointsAmelioration;
|
||||
|
||||
/** Recommandations */
|
||||
@Size(max = 500, message = "Les recommandations ne peuvent pas dépasser 500 caractères")
|
||||
private String recommandations;
|
||||
|
||||
/** Indique si l'évaluateur recommande cette aide/proposant */
|
||||
@Builder.Default private Boolean recommande = true;
|
||||
|
||||
/** Indique si l'aide a été utile */
|
||||
@Builder.Default private Boolean aideUtile = true;
|
||||
|
||||
/** Indique si l'aide a résolu le problème */
|
||||
@Builder.Default private Boolean problemeResolu = true;
|
||||
|
||||
/** Délai de réponse perçu (1=très lent, 5=très rapide) */
|
||||
@DecimalMin(value = "1.0", message = "La note délai doit être au moins 1")
|
||||
@DecimalMax(value = "5.0", message = "La note délai ne peut pas dépasser 5")
|
||||
private Double noteDelaiReponse;
|
||||
|
||||
/** Qualité de la communication (1=très mauvaise, 5=excellente) */
|
||||
@DecimalMin(value = "1.0", message = "La note communication doit être au moins 1")
|
||||
@DecimalMax(value = "5.0", message = "La note communication ne peut pas dépasser 5")
|
||||
private Double noteCommunication;
|
||||
|
||||
/** Professionnalisme (1=très mauvais, 5=excellent) */
|
||||
@DecimalMin(value = "1.0", message = "La note professionnalisme doit être au moins 1")
|
||||
@DecimalMax(value = "5.0", message = "La note professionnalisme ne peut pas dépasser 5")
|
||||
private Double noteProfessionnalisme;
|
||||
|
||||
/** Respect des engagements (1=très mauvais, 5=excellent) */
|
||||
@DecimalMin(value = "1.0", message = "La note engagement doit être au moins 1")
|
||||
@DecimalMax(value = "5.0", message = "La note engagement ne peut pas dépasser 5")
|
||||
private Double noteRespectEngagements;
|
||||
|
||||
/** Date de création de l'évaluation */
|
||||
@NotNull(message = "La date de création est obligatoire")
|
||||
@Builder.Default
|
||||
private LocalDateTime dateCreation = LocalDateTime.now();
|
||||
|
||||
/** Date de dernière modification */
|
||||
@Builder.Default private LocalDateTime dateModification = LocalDateTime.now();
|
||||
|
||||
/** Indique si l'évaluation est publique */
|
||||
@Builder.Default private Boolean estPublique = true;
|
||||
|
||||
/** Indique si l'évaluation est anonyme */
|
||||
@Builder.Default private Boolean estAnonyme = false;
|
||||
|
||||
/** Indique si l'évaluation a été vérifiée */
|
||||
@Builder.Default private Boolean estVerifiee = false;
|
||||
|
||||
/** Date de vérification */
|
||||
private LocalDateTime dateVerification;
|
||||
|
||||
/** Identifiant du vérificateur */
|
||||
private String verificateurId;
|
||||
|
||||
/** Pièces jointes à l'évaluation (photos, documents) */
|
||||
private List<PieceJustificativeDTO> piecesJointes;
|
||||
|
||||
/** Tags associés à l'évaluation */
|
||||
private List<String> tags;
|
||||
|
||||
/** Données additionnelles */
|
||||
private Map<String, Object> donneesAdditionnelles;
|
||||
|
||||
/** Nombre de personnes qui ont trouvé cette évaluation utile */
|
||||
@Builder.Default private Integer nombreUtile = 0;
|
||||
|
||||
/** Nombre de signalements de cette évaluation */
|
||||
@Builder.Default private Integer nombreSignalements = 0;
|
||||
|
||||
/** Statut de l'évaluation */
|
||||
@NotNull(message = "Le statut est obligatoire")
|
||||
@Builder.Default
|
||||
private StatutEvaluation statut = StatutEvaluation.ACTIVE;
|
||||
|
||||
/** Énumération des types d'évaluation */
|
||||
public enum TypeEvaluation {
|
||||
SATISFACTION_BENEFICIAIRE("Satisfaction du bénéficiaire"),
|
||||
EVALUATION_PROPOSANT("Évaluation du proposant"),
|
||||
EVALUATION_PROCESSUS("Évaluation du processus"),
|
||||
SUIVI_POST_AIDE("Suivi post-aide"),
|
||||
EVALUATION_IMPACT("Évaluation d'impact"),
|
||||
RETOUR_EXPERIENCE("Retour d'expérience");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
TypeEvaluation(String libelle) {
|
||||
this.libelle = libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Énumération des statuts d'évaluation
|
||||
*/
|
||||
public enum StatutEvaluation {
|
||||
BROUILLON("Brouillon"),
|
||||
ACTIVE("Active"),
|
||||
MASQUEE("Masquée"),
|
||||
SIGNALEE("Signalée"),
|
||||
SUPPRIMEE("Supprimée");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
StatutEvaluation(String libelle) {
|
||||
this.libelle = libelle;
|
||||
}
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Calcule la note moyenne des critères détaillés
|
||||
*/
|
||||
public Double getNoteMoyenneDetaillees() {
|
||||
if (notesDetaillees == null || notesDetaillees.isEmpty()) {
|
||||
return noteGlobale;
|
||||
}
|
||||
|
||||
return notesDetaillees.values().stream()
|
||||
.mapToDouble(Double::doubleValue)
|
||||
.average()
|
||||
.orElse(noteGlobale);
|
||||
}
|
||||
|
||||
/** Énumération des statuts d'évaluation */
|
||||
public enum StatutEvaluation {
|
||||
BROUILLON("Brouillon"),
|
||||
ACTIVE("Active"),
|
||||
MASQUEE("Masquée"),
|
||||
SIGNALEE("Signalée"),
|
||||
SUPPRIMEE("Supprimée");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
StatutEvaluation(String libelle) {
|
||||
this.libelle = libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'évaluation est positive (note >= 4)
|
||||
*/
|
||||
public boolean isPositive() {
|
||||
return noteGlobale != null && noteGlobale >= 4.0;
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'évaluation est négative (note <= 2)
|
||||
*/
|
||||
public boolean isNegative() {
|
||||
return noteGlobale != null && noteGlobale <= 2.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule un score de qualité global
|
||||
*/
|
||||
public double getScoreQualite() {
|
||||
double score = noteGlobale != null ? noteGlobale : 0.0;
|
||||
|
||||
// Bonus pour les notes détaillées
|
||||
if (noteDelaiReponse != null) score += noteDelaiReponse * 0.1;
|
||||
if (noteCommunication != null) score += noteCommunication * 0.1;
|
||||
if (noteProfessionnalisme != null) score += noteProfessionnalisme * 0.1;
|
||||
if (noteRespectEngagements != null) score += noteRespectEngagements * 0.1;
|
||||
|
||||
// Bonus pour recommandation
|
||||
if (recommande != null && recommande) score += 0.2;
|
||||
|
||||
// Bonus pour résolution du problème
|
||||
if (problemeResolu != null && problemeResolu) score += 0.3;
|
||||
|
||||
// Malus pour signalements
|
||||
if (nombreSignalements > 0) score -= nombreSignalements * 0.1;
|
||||
|
||||
return Math.min(5.0, Math.max(0.0, score));
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'évaluation est complète
|
||||
*/
|
||||
public boolean isComplete() {
|
||||
return noteGlobale != null &&
|
||||
commentairePrincipal != null && !commentairePrincipal.trim().isEmpty() &&
|
||||
recommande != null &&
|
||||
aideUtile != null &&
|
||||
problemeResolu != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le niveau de satisfaction
|
||||
*/
|
||||
public String getNiveauSatisfaction() {
|
||||
if (noteGlobale == null) return "Non évalué";
|
||||
|
||||
return switch (noteGlobale.intValue()) {
|
||||
case 5 -> "Excellent";
|
||||
case 4 -> "Très bien";
|
||||
case 3 -> "Bien";
|
||||
case 2 -> "Passable";
|
||||
case 1 -> "Insuffisant";
|
||||
default -> "Non évalué";
|
||||
};
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/** Calcule la note moyenne des critères détaillés */
|
||||
public Double getNoteMoyenneDetaillees() {
|
||||
if (notesDetaillees == null || notesDetaillees.isEmpty()) {
|
||||
return noteGlobale;
|
||||
}
|
||||
|
||||
return notesDetaillees.values().stream()
|
||||
.mapToDouble(Double::doubleValue)
|
||||
.average()
|
||||
.orElse(noteGlobale);
|
||||
}
|
||||
|
||||
/** Vérifie si l'évaluation est positive (note >= 4) */
|
||||
public boolean isPositive() {
|
||||
return noteGlobale != null && noteGlobale >= 4.0;
|
||||
}
|
||||
|
||||
/** Vérifie si l'évaluation est négative (note <= 2) */
|
||||
public boolean isNegative() {
|
||||
return noteGlobale != null && noteGlobale <= 2.0;
|
||||
}
|
||||
|
||||
/** Calcule un score de qualité global */
|
||||
public double getScoreQualite() {
|
||||
double score = noteGlobale != null ? noteGlobale : 0.0;
|
||||
|
||||
// Bonus pour les notes détaillées
|
||||
if (noteDelaiReponse != null) score += noteDelaiReponse * 0.1;
|
||||
if (noteCommunication != null) score += noteCommunication * 0.1;
|
||||
if (noteProfessionnalisme != null) score += noteProfessionnalisme * 0.1;
|
||||
if (noteRespectEngagements != null) score += noteRespectEngagements * 0.1;
|
||||
|
||||
// Bonus pour recommandation
|
||||
if (recommande != null && recommande) score += 0.2;
|
||||
|
||||
// Bonus pour résolution du problème
|
||||
if (problemeResolu != null && problemeResolu) score += 0.3;
|
||||
|
||||
// Malus pour signalements
|
||||
if (nombreSignalements > 0) score -= nombreSignalements * 0.1;
|
||||
|
||||
return Math.min(5.0, Math.max(0.0, score));
|
||||
}
|
||||
|
||||
/** Vérifie si l'évaluation est complète */
|
||||
public boolean isComplete() {
|
||||
return noteGlobale != null
|
||||
&& commentairePrincipal != null
|
||||
&& !commentairePrincipal.trim().isEmpty()
|
||||
&& recommande != null
|
||||
&& aideUtile != null
|
||||
&& problemeResolu != null;
|
||||
}
|
||||
|
||||
/** Retourne le niveau de satisfaction */
|
||||
public String getNiveauSatisfaction() {
|
||||
if (noteGlobale == null) return "Non évalué";
|
||||
|
||||
return switch (noteGlobale.intValue()) {
|
||||
case 5 -> "Excellent";
|
||||
case 4 -> "Très bien";
|
||||
case 3 -> "Bien";
|
||||
case 2 -> "Passable";
|
||||
case 1 -> "Insuffisant";
|
||||
default -> "Non évalué";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO pour l'historique des changements de statut d'une demande d'aide
|
||||
*
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -22,66 +20,43 @@ import java.time.LocalDateTime;
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class HistoriqueStatutDTO {
|
||||
|
||||
/**
|
||||
* Identifiant unique de l'entrée d'historique
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Ancien statut
|
||||
*/
|
||||
private StatutAide ancienStatut;
|
||||
|
||||
/**
|
||||
* Nouveau statut
|
||||
*/
|
||||
@NotNull(message = "Le nouveau statut est obligatoire")
|
||||
private StatutAide nouveauStatut;
|
||||
|
||||
/**
|
||||
* Date du changement de statut
|
||||
*/
|
||||
@NotNull(message = "La date de changement est obligatoire")
|
||||
@Builder.Default
|
||||
private LocalDateTime dateChangement = LocalDateTime.now();
|
||||
|
||||
/**
|
||||
* Identifiant de la personne qui a effectué le changement
|
||||
*/
|
||||
@NotBlank(message = "L'identifiant de l'auteur est obligatoire")
|
||||
private String auteurId;
|
||||
|
||||
/**
|
||||
* Nom de la personne qui a effectué le changement
|
||||
*/
|
||||
private String auteurNom;
|
||||
|
||||
/**
|
||||
* Motif du changement de statut
|
||||
*/
|
||||
@Size(max = 500, message = "Le motif ne peut pas dépasser 500 caractères")
|
||||
private String motif;
|
||||
|
||||
/**
|
||||
* Commentaires additionnels
|
||||
*/
|
||||
@Size(max = 1000, message = "Les commentaires ne peuvent pas dépasser 1000 caractères")
|
||||
private String commentaires;
|
||||
|
||||
/**
|
||||
* Indique si le changement est automatique (système)
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estAutomatique = false;
|
||||
|
||||
/**
|
||||
* Durée en minutes depuis le statut précédent
|
||||
*/
|
||||
private Long dureeDepuisPrecedent;
|
||||
|
||||
/**
|
||||
* Données additionnelles liées au changement
|
||||
*/
|
||||
private java.util.Map<String, Object> donneesAdditionnelles;
|
||||
|
||||
/** Identifiant unique de l'entrée d'historique */
|
||||
private String id;
|
||||
|
||||
/** Ancien statut */
|
||||
private StatutAide ancienStatut;
|
||||
|
||||
/** Nouveau statut */
|
||||
@NotNull(message = "Le nouveau statut est obligatoire")
|
||||
private StatutAide nouveauStatut;
|
||||
|
||||
/** Date du changement de statut */
|
||||
@NotNull(message = "La date de changement est obligatoire")
|
||||
@Builder.Default
|
||||
private LocalDateTime dateChangement = LocalDateTime.now();
|
||||
|
||||
/** Identifiant de la personne qui a effectué le changement */
|
||||
@NotBlank(message = "L'identifiant de l'auteur est obligatoire")
|
||||
private String auteurId;
|
||||
|
||||
/** Nom de la personne qui a effectué le changement */
|
||||
private String auteurNom;
|
||||
|
||||
/** Motif du changement de statut */
|
||||
@Size(max = 500, message = "Le motif ne peut pas dépasser 500 caractères")
|
||||
private String motif;
|
||||
|
||||
/** Commentaires additionnels */
|
||||
@Size(max = 1000, message = "Les commentaires ne peuvent pas dépasser 1000 caractères")
|
||||
private String commentaires;
|
||||
|
||||
/** Indique si le changement est automatique (système) */
|
||||
@Builder.Default private Boolean estAutomatique = false;
|
||||
|
||||
/** Durée en minutes depuis le statut précédent */
|
||||
private Long dureeDepuisPrecedent;
|
||||
|
||||
/** Données additionnelles liées au changement */
|
||||
private java.util.Map<String, Object> donneesAdditionnelles;
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO pour les informations de géolocalisation
|
||||
*
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -18,60 +18,41 @@ import lombok.Builder;
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class LocalisationDTO {
|
||||
|
||||
/**
|
||||
* Latitude
|
||||
*/
|
||||
@DecimalMin(value = "-90.0", message = "La latitude doit être comprise entre -90 et 90")
|
||||
@DecimalMax(value = "90.0", message = "La latitude doit être comprise entre -90 et 90")
|
||||
private Double latitude;
|
||||
|
||||
/**
|
||||
* Longitude
|
||||
*/
|
||||
@DecimalMin(value = "-180.0", message = "La longitude doit être comprise entre -180 et 180")
|
||||
@DecimalMax(value = "180.0", message = "La longitude doit être comprise entre -180 et 180")
|
||||
private Double longitude;
|
||||
|
||||
/**
|
||||
* Adresse complète
|
||||
*/
|
||||
@Size(max = 300, message = "L'adresse ne peut pas dépasser 300 caractères")
|
||||
private String adresseComplete;
|
||||
|
||||
/**
|
||||
* Ville
|
||||
*/
|
||||
@Size(max = 100, message = "La ville ne peut pas dépasser 100 caractères")
|
||||
private String ville;
|
||||
|
||||
/**
|
||||
* Région/Province
|
||||
*/
|
||||
@Size(max = 100, message = "La région ne peut pas dépasser 100 caractères")
|
||||
private String region;
|
||||
|
||||
/**
|
||||
* Pays
|
||||
*/
|
||||
@Size(max = 100, message = "Le pays ne peut pas dépasser 100 caractères")
|
||||
private String pays;
|
||||
|
||||
/**
|
||||
* Code postal
|
||||
*/
|
||||
@Size(max = 20, message = "Le code postal ne peut pas dépasser 20 caractères")
|
||||
private String codePostal;
|
||||
|
||||
/**
|
||||
* Précision de la localisation en mètres
|
||||
*/
|
||||
@Min(value = 0, message = "La précision doit être positive")
|
||||
private Double precision;
|
||||
|
||||
/**
|
||||
* Indique si la localisation est approximative
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estApproximative = false;
|
||||
|
||||
/** Latitude */
|
||||
@DecimalMin(value = "-90.0", message = "La latitude doit être comprise entre -90 et 90")
|
||||
@DecimalMax(value = "90.0", message = "La latitude doit être comprise entre -90 et 90")
|
||||
private Double latitude;
|
||||
|
||||
/** Longitude */
|
||||
@DecimalMin(value = "-180.0", message = "La longitude doit être comprise entre -180 et 180")
|
||||
@DecimalMax(value = "180.0", message = "La longitude doit être comprise entre -180 et 180")
|
||||
private Double longitude;
|
||||
|
||||
/** Adresse complète */
|
||||
@Size(max = 300, message = "L'adresse ne peut pas dépasser 300 caractères")
|
||||
private String adresseComplete;
|
||||
|
||||
/** Ville */
|
||||
@Size(max = 100, message = "La ville ne peut pas dépasser 100 caractères")
|
||||
private String ville;
|
||||
|
||||
/** Région/Province */
|
||||
@Size(max = 100, message = "La région ne peut pas dépasser 100 caractères")
|
||||
private String region;
|
||||
|
||||
/** Pays */
|
||||
@Size(max = 100, message = "Le pays ne peut pas dépasser 100 caractères")
|
||||
private String pays;
|
||||
|
||||
/** Code postal */
|
||||
@Size(max = 20, message = "Le code postal ne peut pas dépasser 20 caractères")
|
||||
private String codePostal;
|
||||
|
||||
/** Précision de la localisation en mètres */
|
||||
@Min(value = 0, message = "La précision doit être positive")
|
||||
private Double precision;
|
||||
|
||||
/** Indique si la localisation est approximative */
|
||||
@Builder.Default private Boolean estApproximative = false;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO pour les pièces justificatives d'une demande d'aide
|
||||
*
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -20,79 +19,50 @@ import java.time.LocalDateTime;
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class PieceJustificativeDTO {
|
||||
|
||||
/**
|
||||
* Identifiant unique de la pièce justificative
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Nom du fichier
|
||||
*/
|
||||
@NotBlank(message = "Le nom du fichier est obligatoire")
|
||||
@Size(max = 255, message = "Le nom du fichier ne peut pas dépasser 255 caractères")
|
||||
private String nomFichier;
|
||||
|
||||
/**
|
||||
* Type de pièce justificative
|
||||
*/
|
||||
@NotBlank(message = "Le type de pièce est obligatoire")
|
||||
private String typePiece;
|
||||
|
||||
/**
|
||||
* Description de la pièce
|
||||
*/
|
||||
@Size(max = 500, message = "La description ne peut pas dépasser 500 caractères")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* URL ou chemin d'accès au fichier
|
||||
*/
|
||||
@NotBlank(message = "L'URL du fichier est obligatoire")
|
||||
private String urlFichier;
|
||||
|
||||
/**
|
||||
* Type MIME du fichier
|
||||
*/
|
||||
private String typeMime;
|
||||
|
||||
/**
|
||||
* Taille du fichier en octets
|
||||
*/
|
||||
@Min(value = 1, message = "La taille du fichier doit être positive")
|
||||
private Long tailleFichier;
|
||||
|
||||
/**
|
||||
* Indique si la pièce est obligatoire
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estObligatoire = false;
|
||||
|
||||
/**
|
||||
* Indique si la pièce a été vérifiée
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estVerifiee = false;
|
||||
|
||||
/**
|
||||
* Date d'ajout de la pièce
|
||||
*/
|
||||
@Builder.Default
|
||||
private LocalDateTime dateAjout = LocalDateTime.now();
|
||||
|
||||
/**
|
||||
* Date de vérification
|
||||
*/
|
||||
private LocalDateTime dateVerification;
|
||||
|
||||
/**
|
||||
* Identifiant de la personne qui a vérifié
|
||||
*/
|
||||
private String verificateurId;
|
||||
|
||||
/**
|
||||
* Commentaires sur la vérification
|
||||
*/
|
||||
@Size(max = 500, message = "Les commentaires ne peuvent pas dépasser 500 caractères")
|
||||
private String commentairesVerification;
|
||||
|
||||
/** Identifiant unique de la pièce justificative */
|
||||
private String id;
|
||||
|
||||
/** Nom du fichier */
|
||||
@NotBlank(message = "Le nom du fichier est obligatoire")
|
||||
@Size(max = 255, message = "Le nom du fichier ne peut pas dépasser 255 caractères")
|
||||
private String nomFichier;
|
||||
|
||||
/** Type de pièce justificative */
|
||||
@NotBlank(message = "Le type de pièce est obligatoire")
|
||||
private String typePiece;
|
||||
|
||||
/** Description de la pièce */
|
||||
@Size(max = 500, message = "La description ne peut pas dépasser 500 caractères")
|
||||
private String description;
|
||||
|
||||
/** URL ou chemin d'accès au fichier */
|
||||
@NotBlank(message = "L'URL du fichier est obligatoire")
|
||||
private String urlFichier;
|
||||
|
||||
/** Type MIME du fichier */
|
||||
private String typeMime;
|
||||
|
||||
/** Taille du fichier en octets */
|
||||
@Min(value = 1, message = "La taille du fichier doit être positive")
|
||||
private Long tailleFichier;
|
||||
|
||||
/** Indique si la pièce est obligatoire */
|
||||
@Builder.Default private Boolean estObligatoire = false;
|
||||
|
||||
/** Indique si la pièce a été vérifiée */
|
||||
@Builder.Default private Boolean estVerifiee = false;
|
||||
|
||||
/** Date d'ajout de la pièce */
|
||||
@Builder.Default private LocalDateTime dateAjout = LocalDateTime.now();
|
||||
|
||||
/** Date de vérification */
|
||||
private LocalDateTime dateVerification;
|
||||
|
||||
/** Identifiant de la personne qui a vérifié */
|
||||
private String verificateurId;
|
||||
|
||||
/** Commentaires sur la vérification */
|
||||
@Size(max = 500, message = "Les commentaires ne peuvent pas dépasser 500 caractères")
|
||||
private String commentairesVerification;
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
|
||||
|
||||
import dev.lions.unionflow.server.api.validation.ValidationConstants;
|
||||
import jakarta.validation.constraints.*;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* DTO pour les propositions d'aide dans le système de solidarité
|
||||
*
|
||||
* Ce DTO représente une proposition d'aide faite par un membre pour aider
|
||||
* soit une demande spécifique, soit de manière générale.
|
||||
*
|
||||
*
|
||||
* <p>Ce DTO représente une proposition d'aide faite par un membre pour aider soit une demande
|
||||
* spécifique, soit de manière générale.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
@@ -27,362 +27,264 @@ import java.util.Map;
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class PropositionAideDTO {
|
||||
|
||||
// === IDENTIFICATION ===
|
||||
|
||||
/**
|
||||
* Identifiant unique de la proposition d'aide
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Numéro de référence de la proposition (généré automatiquement)
|
||||
*/
|
||||
@Pattern(regexp = "^PA-\\d{4}-\\d{6}$", message = "Le numéro de référence doit suivre le format PA-YYYY-NNNNNN")
|
||||
private String numeroReference;
|
||||
|
||||
// === INFORMATIONS DE BASE ===
|
||||
|
||||
/**
|
||||
* Type d'aide proposée
|
||||
*/
|
||||
@NotNull(message = "Le type d'aide proposée est obligatoire")
|
||||
private TypeAide typeAide;
|
||||
|
||||
/**
|
||||
* Titre de la proposition
|
||||
*/
|
||||
@NotBlank(message = "Le titre est obligatoire")
|
||||
@Size(min = 10, max = 100, message = "Le titre doit contenir entre 10 et 100 caractères")
|
||||
private String titre;
|
||||
|
||||
/**
|
||||
* Description détaillée de l'aide proposée
|
||||
*/
|
||||
@NotBlank(message = "La description est obligatoire")
|
||||
@Size(min = 20, max = 1000, message = "La description doit contenir entre 20 et 1000 caractères")
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* Conditions ou critères pour bénéficier de l'aide
|
||||
*/
|
||||
@Size(max = 500, message = "Les conditions ne peuvent pas dépasser 500 caractères")
|
||||
private String conditions;
|
||||
|
||||
// === MONTANT ET CAPACITÉ ===
|
||||
|
||||
/**
|
||||
* Montant maximum que le proposant peut offrir (si applicable)
|
||||
*/
|
||||
@DecimalMin(value = "0.0", inclusive = false, message = "Le montant doit être positif")
|
||||
@DecimalMax(value = "1000000.0", message = "Le montant ne peut pas dépasser 1 000 000 FCFA")
|
||||
private Double montantMaximum;
|
||||
|
||||
/**
|
||||
* Nombre maximum de bénéficiaires
|
||||
*/
|
||||
@Min(value = 1, message = "Le nombre de bénéficiaires doit être au moins 1")
|
||||
@Max(value = 100, message = "Le nombre de bénéficiaires ne peut pas dépasser 100")
|
||||
@Builder.Default
|
||||
private Integer nombreMaxBeneficiaires = 1;
|
||||
|
||||
/**
|
||||
* Devise du montant
|
||||
*/
|
||||
@Builder.Default
|
||||
private String devise = "FCFA";
|
||||
|
||||
// === ACTEURS ===
|
||||
|
||||
/**
|
||||
* Identifiant du proposant
|
||||
*/
|
||||
@NotBlank(message = "L'identifiant du proposant est obligatoire")
|
||||
private String proposantId;
|
||||
|
||||
/**
|
||||
* Nom complet du proposant
|
||||
*/
|
||||
private String proposantNom;
|
||||
|
||||
/**
|
||||
* Identifiant de l'organisation du proposant
|
||||
*/
|
||||
@NotBlank(message = "L'identifiant de l'organisation est obligatoire")
|
||||
private String organisationId;
|
||||
|
||||
/**
|
||||
* Identifiant de la demande d'aide liée (si proposition spécifique)
|
||||
*/
|
||||
private String demandeAideId;
|
||||
|
||||
// === STATUT ET DISPONIBILITÉ ===
|
||||
|
||||
/**
|
||||
* Statut de la proposition
|
||||
*/
|
||||
@NotNull(message = "Le statut est obligatoire")
|
||||
@Builder.Default
|
||||
private StatutProposition statut = StatutProposition.ACTIVE;
|
||||
|
||||
/**
|
||||
* Indique si la proposition est disponible
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estDisponible = true;
|
||||
|
||||
/**
|
||||
* Indique si la proposition est récurrente
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estRecurrente = false;
|
||||
|
||||
/**
|
||||
* Fréquence de récurrence (si applicable)
|
||||
*/
|
||||
private String frequenceRecurrence;
|
||||
|
||||
// === DATES ET DÉLAIS ===
|
||||
|
||||
/**
|
||||
* Date de création de la proposition
|
||||
*/
|
||||
@NotNull(message = "La date de création est obligatoire")
|
||||
@Builder.Default
|
||||
private LocalDateTime dateCreation = LocalDateTime.now();
|
||||
|
||||
/**
|
||||
* Date d'expiration de la proposition
|
||||
*/
|
||||
private LocalDateTime dateExpiration;
|
||||
|
||||
/**
|
||||
* Date de dernière modification
|
||||
*/
|
||||
@Builder.Default
|
||||
private LocalDateTime dateModification = LocalDateTime.now();
|
||||
|
||||
/**
|
||||
* Délai de réponse souhaité en heures
|
||||
*/
|
||||
@Min(value = 1, message = "Le délai de réponse doit être au moins 1 heure")
|
||||
@Max(value = 8760, message = "Le délai de réponse ne peut pas dépasser 1 an")
|
||||
@Builder.Default
|
||||
private Integer delaiReponseHeures = 72;
|
||||
|
||||
// === CRITÈRES ET PRÉFÉRENCES ===
|
||||
|
||||
/**
|
||||
* Critères de sélection des bénéficiaires
|
||||
*/
|
||||
private List<CritereSelectionDTO> criteresSelection;
|
||||
|
||||
/**
|
||||
* Zones géographiques couvertes
|
||||
*/
|
||||
private List<String> zonesGeographiques;
|
||||
|
||||
/**
|
||||
* Groupes cibles (âge, situation, etc.)
|
||||
*/
|
||||
private List<String> groupesCibles;
|
||||
|
||||
/**
|
||||
* Compétences ou ressources disponibles
|
||||
*/
|
||||
private List<String> competencesRessources;
|
||||
|
||||
// === CONTACT ET DISPONIBILITÉ ===
|
||||
|
||||
/**
|
||||
* Informations de contact préférées
|
||||
*/
|
||||
private ContactProposantDTO contactProposant;
|
||||
|
||||
/**
|
||||
* Créneaux de disponibilité
|
||||
*/
|
||||
private List<CreneauDisponibiliteDTO> creneauxDisponibilite;
|
||||
|
||||
/**
|
||||
* Mode de contact préféré
|
||||
*/
|
||||
private String modeContactPrefere;
|
||||
|
||||
// === HISTORIQUE ET SUIVI ===
|
||||
|
||||
/**
|
||||
* Nombre de demandes traitées avec cette proposition
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer nombreDemandesTraitees = 0;
|
||||
|
||||
/**
|
||||
* Nombre de bénéficiaires aidés
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer nombreBeneficiairesAides = 0;
|
||||
|
||||
/**
|
||||
* Montant total versé
|
||||
*/
|
||||
@Builder.Default
|
||||
private Double montantTotalVerse = 0.0;
|
||||
|
||||
/**
|
||||
* Note moyenne des bénéficiaires
|
||||
*/
|
||||
@DecimalMin(value = "0.0", message = "La note doit être positive")
|
||||
@DecimalMax(value = "5.0", message = "La note ne peut pas dépasser 5")
|
||||
private Double noteMoyenne;
|
||||
|
||||
/**
|
||||
* Nombre d'évaluations reçues
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer nombreEvaluations = 0;
|
||||
|
||||
// === MÉTADONNÉES ===
|
||||
|
||||
/**
|
||||
* Tags pour catégorisation
|
||||
*/
|
||||
private List<String> tags;
|
||||
|
||||
/**
|
||||
* Données personnalisées
|
||||
*/
|
||||
private Map<String, Object> donneesPersonnalisees;
|
||||
|
||||
/**
|
||||
* Indique si la proposition est mise en avant
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean estMiseEnAvant = false;
|
||||
|
||||
/**
|
||||
* Score de pertinence calculé automatiquement
|
||||
*/
|
||||
private Double scorePertinence;
|
||||
|
||||
/**
|
||||
* Nombre de vues de la proposition
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer nombreVues = 0;
|
||||
|
||||
/**
|
||||
* Nombre de candidatures reçues
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer nombreCandidatures = 0;
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Vérifie si la proposition est active et disponible
|
||||
*/
|
||||
public boolean isActiveEtDisponible() {
|
||||
return statut == StatutProposition.ACTIVE && estDisponible && !isExpiree();
|
||||
|
||||
// === IDENTIFICATION ===
|
||||
|
||||
/** Identifiant unique de la proposition d'aide */
|
||||
private String id;
|
||||
|
||||
/** Numéro de référence de la proposition (généré automatiquement) */
|
||||
@Pattern(
|
||||
regexp = "^PA-\\d{4}-\\d{6}$",
|
||||
message = "Le numéro de référence doit suivre le format PA-YYYY-NNNNNN")
|
||||
private String numeroReference;
|
||||
|
||||
// === INFORMATIONS DE BASE ===
|
||||
|
||||
/** Type d'aide proposée */
|
||||
@NotNull(message = "Le type d'aide proposée est obligatoire")
|
||||
private TypeAide typeAide;
|
||||
|
||||
/** Titre de la proposition */
|
||||
@NotBlank(message = "Le titre est obligatoire")
|
||||
@Size(min = 10, max = 100, message = "Le titre doit contenir entre 10 et 100 caractères")
|
||||
private String titre;
|
||||
|
||||
/** Description détaillée de l'aide proposée */
|
||||
@NotBlank(message = "La description est obligatoire")
|
||||
@Size(min = 20, max = 1000, message = "La description doit contenir entre 20 et 1000 caractères")
|
||||
private String description;
|
||||
|
||||
/** Conditions ou critères pour bénéficier de l'aide */
|
||||
@Size(max = 500, message = "Les conditions ne peuvent pas dépasser 500 caractères")
|
||||
private String conditions;
|
||||
|
||||
// === MONTANT ET CAPACITÉ ===
|
||||
|
||||
/** Montant maximum que le proposant peut offrir (si applicable) */
|
||||
@DecimalMin(value = "0.0", inclusive = false, message = "Le montant doit être positif")
|
||||
@DecimalMax(value = "1000000.0", message = "Le montant ne peut pas dépasser 1 000 000 FCFA")
|
||||
@Digits(
|
||||
integer = ValidationConstants.MONTANT_INTEGER_DIGITS,
|
||||
fraction = ValidationConstants.MONTANT_FRACTION_DIGITS,
|
||||
message = ValidationConstants.MONTANT_DIGITS_MESSAGE)
|
||||
private BigDecimal montantMaximum;
|
||||
|
||||
/** Nombre maximum de bénéficiaires */
|
||||
@Min(value = 1, message = "Le nombre de bénéficiaires doit être au moins 1")
|
||||
@Max(value = 100, message = "Le nombre de bénéficiaires ne peut pas dépasser 100")
|
||||
@Builder.Default
|
||||
private Integer nombreMaxBeneficiaires = 1;
|
||||
|
||||
/** Devise du montant */
|
||||
@Builder.Default private String devise = "FCFA";
|
||||
|
||||
// === ACTEURS ===
|
||||
|
||||
/** Identifiant du proposant */
|
||||
@NotBlank(message = "L'identifiant du proposant est obligatoire")
|
||||
private String proposantId;
|
||||
|
||||
/** Nom complet du proposant */
|
||||
private String proposantNom;
|
||||
|
||||
/** Identifiant de l'organisation du proposant */
|
||||
@NotBlank(message = "L'identifiant de l'organisation est obligatoire")
|
||||
private String organisationId;
|
||||
|
||||
/** Identifiant de la demande d'aide liée (si proposition spécifique) */
|
||||
private String demandeAideId;
|
||||
|
||||
// === STATUT ET DISPONIBILITÉ ===
|
||||
|
||||
/** Statut de la proposition */
|
||||
@NotNull(message = "Le statut est obligatoire")
|
||||
@Builder.Default
|
||||
private StatutProposition statut = StatutProposition.ACTIVE;
|
||||
|
||||
/** Indique si la proposition est disponible */
|
||||
@Builder.Default private Boolean estDisponible = true;
|
||||
|
||||
/** Indique si la proposition est récurrente */
|
||||
@Builder.Default private Boolean estRecurrente = false;
|
||||
|
||||
/** Fréquence de récurrence (si applicable) */
|
||||
private String frequenceRecurrence;
|
||||
|
||||
// === DATES ET DÉLAIS ===
|
||||
|
||||
/** Date de création de la proposition */
|
||||
@NotNull(message = "La date de création est obligatoire")
|
||||
@Builder.Default
|
||||
private LocalDateTime dateCreation = LocalDateTime.now();
|
||||
|
||||
/** Date d'expiration de la proposition */
|
||||
private LocalDateTime dateExpiration;
|
||||
|
||||
/** Date de dernière modification */
|
||||
@Builder.Default private LocalDateTime dateModification = LocalDateTime.now();
|
||||
|
||||
/** Délai de réponse souhaité en heures */
|
||||
@Min(value = 1, message = "Le délai de réponse doit être au moins 1 heure")
|
||||
@Max(value = 8760, message = "Le délai de réponse ne peut pas dépasser 1 an")
|
||||
@Builder.Default
|
||||
private Integer delaiReponseHeures = 72;
|
||||
|
||||
// === CRITÈRES ET PRÉFÉRENCES ===
|
||||
|
||||
/** Critères de sélection des bénéficiaires */
|
||||
private List<CritereSelectionDTO> criteresSelection;
|
||||
|
||||
/** Zones géographiques couvertes */
|
||||
private List<String> zonesGeographiques;
|
||||
|
||||
/** Groupes cibles (âge, situation, etc.) */
|
||||
private List<String> groupesCibles;
|
||||
|
||||
/** Compétences ou ressources disponibles */
|
||||
private List<String> competencesRessources;
|
||||
|
||||
// === CONTACT ET DISPONIBILITÉ ===
|
||||
|
||||
/** Informations de contact préférées */
|
||||
private ContactProposantDTO contactProposant;
|
||||
|
||||
/** Créneaux de disponibilité */
|
||||
private List<CreneauDisponibiliteDTO> creneauxDisponibilite;
|
||||
|
||||
/** Mode de contact préféré */
|
||||
private String modeContactPrefere;
|
||||
|
||||
// === HISTORIQUE ET SUIVI ===
|
||||
|
||||
/** Nombre de demandes traitées avec cette proposition */
|
||||
@Builder.Default private Integer nombreDemandesTraitees = 0;
|
||||
|
||||
/** Nombre de bénéficiaires aidés */
|
||||
@Builder.Default private Integer nombreBeneficiairesAides = 0;
|
||||
|
||||
/** Montant total versé */
|
||||
@Builder.Default private Double montantTotalVerse = 0.0;
|
||||
|
||||
/** Note moyenne des bénéficiaires */
|
||||
@DecimalMin(value = "0.0", message = "La note doit être positive")
|
||||
@DecimalMax(value = "5.0", message = "La note ne peut pas dépasser 5")
|
||||
private Double noteMoyenne;
|
||||
|
||||
/** Nombre d'évaluations reçues */
|
||||
@Builder.Default private Integer nombreEvaluations = 0;
|
||||
|
||||
// === MÉTADONNÉES ===
|
||||
|
||||
/** Tags pour catégorisation */
|
||||
private List<String> tags;
|
||||
|
||||
/** Données personnalisées */
|
||||
private Map<String, Object> donneesPersonnalisees;
|
||||
|
||||
/** Indique si la proposition est mise en avant */
|
||||
@Builder.Default private Boolean estMiseEnAvant = false;
|
||||
|
||||
/** Score de pertinence calculé automatiquement */
|
||||
private Double scorePertinence;
|
||||
|
||||
/** Nombre de vues de la proposition */
|
||||
@Builder.Default private Integer nombreVues = 0;
|
||||
|
||||
/** Nombre de candidatures reçues */
|
||||
@Builder.Default private Integer nombreCandidatures = 0;
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/** Vérifie si la proposition est active et disponible */
|
||||
public boolean isActiveEtDisponible() {
|
||||
return statut == StatutProposition.ACTIVE && estDisponible && !isExpiree();
|
||||
}
|
||||
|
||||
/** Vérifie si la proposition est expirée */
|
||||
public boolean isExpiree() {
|
||||
return dateExpiration != null && LocalDateTime.now().isAfter(dateExpiration);
|
||||
}
|
||||
|
||||
/** Vérifie si la proposition peut encore accepter des bénéficiaires */
|
||||
public boolean peutAccepterBeneficiaires() {
|
||||
return isActiveEtDisponible() && nombreBeneficiairesAides < nombreMaxBeneficiaires;
|
||||
}
|
||||
|
||||
/** Calcule le pourcentage de capacité utilisée */
|
||||
public double getPourcentageCapaciteUtilisee() {
|
||||
if (nombreMaxBeneficiaires == 0) return 100.0;
|
||||
return (nombreBeneficiairesAides * 100.0) / nombreMaxBeneficiaires;
|
||||
}
|
||||
|
||||
/** Retourne le nombre de places restantes */
|
||||
public int getPlacesRestantes() {
|
||||
return Math.max(0, nombreMaxBeneficiaires - nombreBeneficiairesAides);
|
||||
}
|
||||
|
||||
/** Vérifie si la proposition correspond à un type d'aide */
|
||||
public boolean correspondAuType(TypeAide type) {
|
||||
return typeAide == type
|
||||
|| (typeAide.getCategorie().equals(type.getCategorie()) && typeAide != TypeAide.AUTRE);
|
||||
}
|
||||
|
||||
/** Calcule le score de compatibilité avec une demande */
|
||||
public double getScoreCompatibilite(DemandeAideDTO demande) {
|
||||
double score = 0.0;
|
||||
|
||||
// Correspondance exacte du type
|
||||
if (typeAide == demande.getTypeAide()) {
|
||||
score += 50.0;
|
||||
} else if (typeAide.getCategorie().equals(demande.getTypeAide().getCategorie())) {
|
||||
score += 30.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la proposition est expirée
|
||||
*/
|
||||
public boolean isExpiree() {
|
||||
return dateExpiration != null && LocalDateTime.now().isAfter(dateExpiration);
|
||||
|
||||
// Montant compatible
|
||||
if (montantMaximum != null && demande.getMontantDemande() != null) {
|
||||
if (demande.getMontantDemande().compareTo(montantMaximum) <= 0) {
|
||||
score += 20.0;
|
||||
} else {
|
||||
score -= 10.0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la proposition peut encore accepter des bénéficiaires
|
||||
*/
|
||||
public boolean peutAccepterBeneficiaires() {
|
||||
return isActiveEtDisponible() && nombreBeneficiairesAides < nombreMaxBeneficiaires;
|
||||
|
||||
// Disponibilité
|
||||
if (peutAccepterBeneficiaires()) {
|
||||
score += 15.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le pourcentage de capacité utilisée
|
||||
*/
|
||||
public double getPourcentageCapaciteUtilisee() {
|
||||
if (nombreMaxBeneficiaires == 0) return 100.0;
|
||||
return (nombreBeneficiairesAides * 100.0) / nombreMaxBeneficiaires;
|
||||
|
||||
// Réputation
|
||||
if (noteMoyenne != null && noteMoyenne >= 4.0) {
|
||||
score += 10.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nombre de places restantes
|
||||
*/
|
||||
public int getPlacesRestantes() {
|
||||
return Math.max(0, nombreMaxBeneficiaires - nombreBeneficiairesAides);
|
||||
|
||||
// Récence
|
||||
long joursDepuisCreation =
|
||||
java.time.Duration.between(dateCreation, LocalDateTime.now()).toDays();
|
||||
if (joursDepuisCreation <= 30) {
|
||||
score += 5.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la proposition correspond à un type d'aide
|
||||
*/
|
||||
public boolean correspondAuType(TypeAide type) {
|
||||
return typeAide == type ||
|
||||
(typeAide.getCategorie().equals(type.getCategorie()) && typeAide != TypeAide.AUTRE);
|
||||
|
||||
return Math.min(100.0, Math.max(0.0, score));
|
||||
}
|
||||
|
||||
/** Énumération des statuts de proposition */
|
||||
public enum StatutProposition {
|
||||
BROUILLON("Brouillon"),
|
||||
ACTIVE("Active"),
|
||||
SUSPENDUE("Suspendue"),
|
||||
EXPIREE("Expirée"),
|
||||
TERMINEE("Terminée"),
|
||||
ANNULEE("Annulée");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
StatutProposition(String libelle) {
|
||||
this.libelle = libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le score de compatibilité avec une demande
|
||||
*/
|
||||
public double getScoreCompatibilite(DemandeAideDTO demande) {
|
||||
double score = 0.0;
|
||||
|
||||
// Correspondance exacte du type
|
||||
if (typeAide == demande.getTypeAide()) {
|
||||
score += 50.0;
|
||||
} else if (typeAide.getCategorie().equals(demande.getTypeAide().getCategorie())) {
|
||||
score += 30.0;
|
||||
}
|
||||
|
||||
// Montant compatible
|
||||
if (montantMaximum != null && demande.getMontantDemande() != null) {
|
||||
if (demande.getMontantDemande() <= montantMaximum) {
|
||||
score += 20.0;
|
||||
} else {
|
||||
score -= 10.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Disponibilité
|
||||
if (peutAccepterBeneficiaires()) {
|
||||
score += 15.0;
|
||||
}
|
||||
|
||||
// Réputation
|
||||
if (noteMoyenne != null && noteMoyenne >= 4.0) {
|
||||
score += 10.0;
|
||||
}
|
||||
|
||||
// Récence
|
||||
long joursDepuisCreation = java.time.Duration.between(dateCreation, LocalDateTime.now()).toDays();
|
||||
if (joursDepuisCreation <= 30) {
|
||||
score += 5.0;
|
||||
}
|
||||
|
||||
return Math.min(100.0, Math.max(0.0, score));
|
||||
}
|
||||
|
||||
/**
|
||||
* Énumération des statuts de proposition
|
||||
*/
|
||||
public enum StatutProposition {
|
||||
BROUILLON("Brouillon"),
|
||||
ACTIVE("Active"),
|
||||
SUSPENDUE("Suspendue"),
|
||||
EXPIREE("Expirée"),
|
||||
TERMINEE("Terminée"),
|
||||
ANNULEE("Annulée");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
StatutProposition(String libelle) {
|
||||
this.libelle = libelle;
|
||||
}
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,849 +0,0 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite.aide;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import dev.lions.unionflow.server.api.dto.base.BaseDTO;
|
||||
import jakarta.validation.constraints.DecimalMin;
|
||||
import jakarta.validation.constraints.Digits;
|
||||
import jakarta.validation.constraints.Future;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* DTO pour la gestion des demandes d'aide et de solidarité Représente les demandes d'assistance
|
||||
* mutuelle entre membres
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-10
|
||||
*/
|
||||
public class AideDTO extends BaseDTO {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** Numéro de référence unique de la demande */
|
||||
@NotBlank(message = "Le numéro de référence est obligatoire")
|
||||
@Pattern(
|
||||
regexp = "^AIDE-\\d{4}-[A-Z0-9]{6}$",
|
||||
message = "Format de référence invalide (AIDE-YYYY-XXXXXX)")
|
||||
private String numeroReference;
|
||||
|
||||
/** Identifiant du membre demandeur */
|
||||
@NotNull(message = "L'identifiant du demandeur est obligatoire")
|
||||
private UUID membreDemandeurId;
|
||||
|
||||
/** Nom complet du membre demandeur */
|
||||
private String nomDemandeur;
|
||||
|
||||
/** Numéro de membre du demandeur */
|
||||
private String numeroMembreDemandeur;
|
||||
|
||||
/** Identifiant de l'association */
|
||||
@NotNull(message = "L'identifiant de l'association est obligatoire")
|
||||
private UUID associationId;
|
||||
|
||||
/** Nom de l'association */
|
||||
private String nomAssociation;
|
||||
|
||||
/**
|
||||
* Type d'aide demandée FINANCIERE, MATERIELLE, MEDICALE, JURIDIQUE, LOGEMENT, EDUCATION, AUTRE
|
||||
*/
|
||||
@NotBlank(message = "Le type d'aide est obligatoire")
|
||||
@Pattern(
|
||||
regexp = "^(FINANCIERE|MATERIELLE|MEDICALE|JURIDIQUE|LOGEMENT|EDUCATION|AUTRE)$",
|
||||
message =
|
||||
"Le type d'aide doit être FINANCIERE, MATERIELLE, MEDICALE, JURIDIQUE, LOGEMENT,"
|
||||
+ " EDUCATION ou AUTRE")
|
||||
private String typeAide;
|
||||
|
||||
/** Titre de la demande d'aide */
|
||||
@NotBlank(message = "Le titre est obligatoire")
|
||||
@Size(min = 5, max = 200, message = "Le titre doit contenir entre 5 et 200 caractères")
|
||||
private String titre;
|
||||
|
||||
/** Description détaillée de la demande */
|
||||
@NotBlank(message = "La description est obligatoire")
|
||||
@Size(min = 20, max = 2000, message = "La description doit contenir entre 20 et 2000 caractères")
|
||||
private String description;
|
||||
|
||||
/** Montant demandé (pour les aides financières) */
|
||||
@DecimalMin(value = "0.0", inclusive = false, message = "Le montant demandé doit être positif")
|
||||
@Digits(
|
||||
integer = 10,
|
||||
fraction = 2,
|
||||
message = "Le montant ne peut avoir plus de 10 chiffres entiers et 2 décimales")
|
||||
private BigDecimal montantDemande;
|
||||
|
||||
/** Devise du montant */
|
||||
@Pattern(regexp = "^[A-Z]{3}$", message = "La devise doit être un code ISO à 3 lettres")
|
||||
private String devise = "XOF";
|
||||
|
||||
/**
|
||||
* Statut de la demande EN_ATTENTE, EN_COURS_EVALUATION, APPROUVEE, REJETEE, EN_COURS_AIDE,
|
||||
* TERMINEE, ANNULEE
|
||||
*/
|
||||
@NotBlank(message = "Le statut est obligatoire")
|
||||
@Pattern(
|
||||
regexp =
|
||||
"^(EN_ATTENTE|EN_COURS_EVALUATION|APPROUVEE|REJETEE|EN_COURS_AIDE|TERMINEE|ANNULEE)$",
|
||||
message = "Statut invalide")
|
||||
private String statut;
|
||||
|
||||
/** Priorité de la demande BASSE, NORMALE, HAUTE, URGENTE */
|
||||
@Pattern(
|
||||
regexp = "^(BASSE|NORMALE|HAUTE|URGENTE)$",
|
||||
message = "La priorité doit être BASSE, NORMALE, HAUTE ou URGENTE")
|
||||
private String priorite;
|
||||
|
||||
/** Date limite pour l'aide */
|
||||
@Future(message = "La date limite doit être dans le futur")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate dateLimite;
|
||||
|
||||
/** Justificatifs fournis */
|
||||
private Boolean justificatifsFournis;
|
||||
|
||||
/** Liste des documents joints (noms de fichiers) */
|
||||
@Size(max = 1000, message = "La liste des documents ne peut pas dépasser 1000 caractères")
|
||||
private String documentsJoints;
|
||||
|
||||
/** Identifiant du membre évaluateur */
|
||||
private UUID membreEvaluateurId;
|
||||
|
||||
/** Nom de l'évaluateur */
|
||||
private String nomEvaluateur;
|
||||
|
||||
/** Date d'évaluation */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateEvaluation;
|
||||
|
||||
/** Commentaires de l'évaluateur */
|
||||
@Size(max = 1000, message = "Les commentaires ne peuvent pas dépasser 1000 caractères")
|
||||
private String commentairesEvaluateur;
|
||||
|
||||
/** Montant approuvé (peut être différent du montant demandé) */
|
||||
@DecimalMin(value = "0.0", message = "Le montant approuvé doit être positif")
|
||||
@Digits(
|
||||
integer = 10,
|
||||
fraction = 2,
|
||||
message = "Le montant ne peut avoir plus de 10 chiffres entiers et 2 décimales")
|
||||
private BigDecimal montantApprouve;
|
||||
|
||||
/** Date d'approbation */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateApprobation;
|
||||
|
||||
/** Identifiant du membre qui fournit l'aide */
|
||||
private UUID membreAidantId;
|
||||
|
||||
/** Nom du membre aidant */
|
||||
private String nomAidant;
|
||||
|
||||
/** Date de début de l'aide */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate dateDebutAide;
|
||||
|
||||
/** Date de fin de l'aide */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||
private LocalDate dateFinAide;
|
||||
|
||||
/** Montant effectivement versé */
|
||||
@DecimalMin(value = "0.0", message = "Le montant versé doit être positif")
|
||||
@Digits(
|
||||
integer = 10,
|
||||
fraction = 2,
|
||||
message = "Le montant ne peut avoir plus de 10 chiffres entiers et 2 décimales")
|
||||
private BigDecimal montantVerse;
|
||||
|
||||
/** Mode de versement */
|
||||
@Pattern(
|
||||
regexp = "^(WAVE_MONEY|ORANGE_MONEY|FREE_MONEY|VIREMENT|CHEQUE|ESPECES|NATURE)$",
|
||||
message = "Mode de versement invalide")
|
||||
private String modeVersement;
|
||||
|
||||
/** Numéro de transaction (pour les paiements mobiles) */
|
||||
@Size(max = 50, message = "Le numéro de transaction ne peut pas dépasser 50 caractères")
|
||||
private String numeroTransaction;
|
||||
|
||||
/** Date de versement */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateVersement;
|
||||
|
||||
/** Commentaires du bénéficiaire */
|
||||
@Size(max = 1000, message = "Les commentaires ne peuvent pas dépasser 1000 caractères")
|
||||
private String commentairesBeneficiaire;
|
||||
|
||||
/** Note de satisfaction (1-5) */
|
||||
private Integer noteSatisfaction;
|
||||
|
||||
/** Aide publique (visible par tous les membres) */
|
||||
private Boolean aidePublique;
|
||||
|
||||
/** Aide anonyme (demandeur anonyme) */
|
||||
private Boolean aideAnonyme;
|
||||
|
||||
/** Nombre de vues de la demande */
|
||||
private Integer nombreVues;
|
||||
|
||||
/** Raison du rejet (si applicable) */
|
||||
@Size(max = 500, message = "La raison du rejet ne peut pas dépasser 500 caractères")
|
||||
private String raisonRejet;
|
||||
|
||||
/** Date de rejet */
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private LocalDateTime dateRejet;
|
||||
|
||||
/** Identifiant de celui qui a rejeté */
|
||||
private UUID rejeteParId;
|
||||
|
||||
/** Nom de celui qui a rejeté */
|
||||
private String rejetePar;
|
||||
|
||||
// Constructeurs
|
||||
public AideDTO() {
|
||||
super();
|
||||
this.statut = "EN_ATTENTE";
|
||||
this.priorite = "NORMALE";
|
||||
this.devise = "XOF";
|
||||
this.justificatifsFournis = false;
|
||||
this.aidePublique = true;
|
||||
this.aideAnonyme = false;
|
||||
this.nombreVues = 0;
|
||||
this.numeroReference = genererNumeroReference();
|
||||
}
|
||||
|
||||
public AideDTO(UUID membreDemandeurId, UUID associationId, String typeAide, String titre) {
|
||||
this();
|
||||
this.membreDemandeurId = membreDemandeurId;
|
||||
this.associationId = associationId;
|
||||
this.typeAide = typeAide;
|
||||
this.titre = titre;
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
public String getNumeroReference() {
|
||||
return numeroReference;
|
||||
}
|
||||
|
||||
public void setNumeroReference(String numeroReference) {
|
||||
this.numeroReference = numeroReference;
|
||||
}
|
||||
|
||||
public UUID getMembreDemandeurId() {
|
||||
return membreDemandeurId;
|
||||
}
|
||||
|
||||
public void setMembreDemandeurId(UUID membreDemandeurId) {
|
||||
this.membreDemandeurId = membreDemandeurId;
|
||||
}
|
||||
|
||||
public String getNomDemandeur() {
|
||||
return nomDemandeur;
|
||||
}
|
||||
|
||||
public void setNomDemandeur(String nomDemandeur) {
|
||||
this.nomDemandeur = nomDemandeur;
|
||||
}
|
||||
|
||||
public String getNumeroMembreDemandeur() {
|
||||
return numeroMembreDemandeur;
|
||||
}
|
||||
|
||||
public void setNumeroMembreDemandeur(String numeroMembreDemandeur) {
|
||||
this.numeroMembreDemandeur = numeroMembreDemandeur;
|
||||
}
|
||||
|
||||
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 getTypeAide() {
|
||||
return typeAide;
|
||||
}
|
||||
|
||||
public void setTypeAide(String typeAide) {
|
||||
this.typeAide = typeAide;
|
||||
}
|
||||
|
||||
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 BigDecimal getMontantDemande() {
|
||||
return montantDemande;
|
||||
}
|
||||
|
||||
public void setMontantDemande(BigDecimal montantDemande) {
|
||||
this.montantDemande = montantDemande;
|
||||
}
|
||||
|
||||
public String getDevise() {
|
||||
return devise;
|
||||
}
|
||||
|
||||
public void setDevise(String devise) {
|
||||
this.devise = devise;
|
||||
}
|
||||
|
||||
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 getDateLimite() {
|
||||
return dateLimite;
|
||||
}
|
||||
|
||||
public void setDateLimite(LocalDate dateLimite) {
|
||||
this.dateLimite = dateLimite;
|
||||
}
|
||||
|
||||
public Boolean getJustificatifsFournis() {
|
||||
return justificatifsFournis;
|
||||
}
|
||||
|
||||
public void setJustificatifsFournis(Boolean justificatifsFournis) {
|
||||
this.justificatifsFournis = justificatifsFournis;
|
||||
}
|
||||
|
||||
public String getDocumentsJoints() {
|
||||
return documentsJoints;
|
||||
}
|
||||
|
||||
public void setDocumentsJoints(String documentsJoints) {
|
||||
this.documentsJoints = documentsJoints;
|
||||
}
|
||||
|
||||
// Getters et setters restants (suite)
|
||||
public UUID getMembreEvaluateurId() {
|
||||
return membreEvaluateurId;
|
||||
}
|
||||
|
||||
public void setMembreEvaluateurId(UUID membreEvaluateurId) {
|
||||
this.membreEvaluateurId = membreEvaluateurId;
|
||||
}
|
||||
|
||||
public String getNomEvaluateur() {
|
||||
return nomEvaluateur;
|
||||
}
|
||||
|
||||
public void setNomEvaluateur(String nomEvaluateur) {
|
||||
this.nomEvaluateur = nomEvaluateur;
|
||||
}
|
||||
|
||||
public LocalDateTime getDateEvaluation() {
|
||||
return dateEvaluation;
|
||||
}
|
||||
|
||||
public void setDateEvaluation(LocalDateTime dateEvaluation) {
|
||||
this.dateEvaluation = dateEvaluation;
|
||||
}
|
||||
|
||||
public String getCommentairesEvaluateur() {
|
||||
return commentairesEvaluateur;
|
||||
}
|
||||
|
||||
public void setCommentairesEvaluateur(String commentairesEvaluateur) {
|
||||
this.commentairesEvaluateur = commentairesEvaluateur;
|
||||
}
|
||||
|
||||
public BigDecimal getMontantApprouve() {
|
||||
return montantApprouve;
|
||||
}
|
||||
|
||||
public void setMontantApprouve(BigDecimal montantApprouve) {
|
||||
this.montantApprouve = montantApprouve;
|
||||
}
|
||||
|
||||
public LocalDateTime getDateApprobation() {
|
||||
return dateApprobation;
|
||||
}
|
||||
|
||||
public void setDateApprobation(LocalDateTime dateApprobation) {
|
||||
this.dateApprobation = dateApprobation;
|
||||
}
|
||||
|
||||
public UUID getMembreAidantId() {
|
||||
return membreAidantId;
|
||||
}
|
||||
|
||||
public void setMembreAidantId(UUID membreAidantId) {
|
||||
this.membreAidantId = membreAidantId;
|
||||
}
|
||||
|
||||
public String getNomAidant() {
|
||||
return nomAidant;
|
||||
}
|
||||
|
||||
public void setNomAidant(String nomAidant) {
|
||||
this.nomAidant = nomAidant;
|
||||
}
|
||||
|
||||
public LocalDate getDateDebutAide() {
|
||||
return dateDebutAide;
|
||||
}
|
||||
|
||||
public void setDateDebutAide(LocalDate dateDebutAide) {
|
||||
this.dateDebutAide = dateDebutAide;
|
||||
}
|
||||
|
||||
public LocalDate getDateFinAide() {
|
||||
return dateFinAide;
|
||||
}
|
||||
|
||||
public void setDateFinAide(LocalDate dateFinAide) {
|
||||
this.dateFinAide = dateFinAide;
|
||||
}
|
||||
|
||||
public BigDecimal getMontantVerse() {
|
||||
return montantVerse;
|
||||
}
|
||||
|
||||
public void setMontantVerse(BigDecimal montantVerse) {
|
||||
this.montantVerse = montantVerse;
|
||||
}
|
||||
|
||||
public String getModeVersement() {
|
||||
return modeVersement;
|
||||
}
|
||||
|
||||
public void setModeVersement(String modeVersement) {
|
||||
this.modeVersement = modeVersement;
|
||||
}
|
||||
|
||||
public String getNumeroTransaction() {
|
||||
return numeroTransaction;
|
||||
}
|
||||
|
||||
public void setNumeroTransaction(String numeroTransaction) {
|
||||
this.numeroTransaction = numeroTransaction;
|
||||
}
|
||||
|
||||
public LocalDateTime getDateVersement() {
|
||||
return dateVersement;
|
||||
}
|
||||
|
||||
public void setDateVersement(LocalDateTime dateVersement) {
|
||||
this.dateVersement = dateVersement;
|
||||
}
|
||||
|
||||
public String getCommentairesBeneficiaire() {
|
||||
return commentairesBeneficiaire;
|
||||
}
|
||||
|
||||
public void setCommentairesBeneficiaire(String commentairesBeneficiaire) {
|
||||
this.commentairesBeneficiaire = commentairesBeneficiaire;
|
||||
}
|
||||
|
||||
public Integer getNoteSatisfaction() {
|
||||
return noteSatisfaction;
|
||||
}
|
||||
|
||||
public void setNoteSatisfaction(Integer noteSatisfaction) {
|
||||
this.noteSatisfaction = noteSatisfaction;
|
||||
}
|
||||
|
||||
public Boolean getAidePublique() {
|
||||
return aidePublique;
|
||||
}
|
||||
|
||||
public void setAidePublique(Boolean aidePublique) {
|
||||
this.aidePublique = aidePublique;
|
||||
}
|
||||
|
||||
public Boolean getAideAnonyme() {
|
||||
return aideAnonyme;
|
||||
}
|
||||
|
||||
public void setAideAnonyme(Boolean aideAnonyme) {
|
||||
this.aideAnonyme = aideAnonyme;
|
||||
}
|
||||
|
||||
public Integer getNombreVues() {
|
||||
return nombreVues;
|
||||
}
|
||||
|
||||
public void setNombreVues(Integer nombreVues) {
|
||||
this.nombreVues = nombreVues;
|
||||
}
|
||||
|
||||
public String getRaisonRejet() {
|
||||
return raisonRejet;
|
||||
}
|
||||
|
||||
public void setRaisonRejet(String raisonRejet) {
|
||||
this.raisonRejet = raisonRejet;
|
||||
}
|
||||
|
||||
public LocalDateTime getDateRejet() {
|
||||
return dateRejet;
|
||||
}
|
||||
|
||||
public void setDateRejet(LocalDateTime dateRejet) {
|
||||
this.dateRejet = dateRejet;
|
||||
}
|
||||
|
||||
public UUID getRejeteParId() {
|
||||
return rejeteParId;
|
||||
}
|
||||
|
||||
public void setRejeteParId(UUID rejeteParId) {
|
||||
this.rejeteParId = rejeteParId;
|
||||
}
|
||||
|
||||
public String getRejetePar() {
|
||||
return rejetePar;
|
||||
}
|
||||
|
||||
public void setRejetePar(String rejetePar) {
|
||||
this.rejetePar = rejetePar;
|
||||
}
|
||||
|
||||
// Méthodes utilitaires
|
||||
|
||||
/**
|
||||
* Vérifie si la demande est en attente
|
||||
*
|
||||
* @return true si la demande est en attente
|
||||
*/
|
||||
public boolean isEnAttente() {
|
||||
return "EN_ATTENTE".equals(statut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la demande est en cours d'évaluation
|
||||
*
|
||||
* @return true si la demande est en cours d'évaluation
|
||||
*/
|
||||
public boolean isEnCoursEvaluation() {
|
||||
return "EN_COURS_EVALUATION".equals(statut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la demande est approuvée
|
||||
*
|
||||
* @return true si la demande est approuvée
|
||||
*/
|
||||
public boolean isApprouvee() {
|
||||
return "APPROUVEE".equals(statut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la demande est rejetée
|
||||
*
|
||||
* @return true si la demande est rejetée
|
||||
*/
|
||||
public boolean isRejetee() {
|
||||
return "REJETEE".equals(statut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'aide est en cours
|
||||
*
|
||||
* @return true si l'aide est en cours
|
||||
*/
|
||||
public boolean isEnCoursAide() {
|
||||
return "EN_COURS_AIDE".equals(statut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'aide est terminée
|
||||
*
|
||||
* @return true si l'aide est terminée
|
||||
*/
|
||||
public boolean isTerminee() {
|
||||
return "TERMINEE".equals(statut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la demande est annulée
|
||||
*
|
||||
* @return true si la demande est annulée
|
||||
*/
|
||||
public boolean isAnnulee() {
|
||||
return "ANNULEE".equals(statut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la demande est urgente
|
||||
*
|
||||
* @return true si la priorité est urgente
|
||||
*/
|
||||
public boolean isUrgente() {
|
||||
return "URGENTE".equals(priorite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la date limite est dépassée
|
||||
*
|
||||
* @return true si la date limite est dépassée
|
||||
*/
|
||||
public boolean isDateLimiteDepassee() {
|
||||
return dateLimite != null && LocalDate.now().isAfter(dateLimite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le nombre de jours restants avant la date limite
|
||||
*
|
||||
* @return Le nombre de jours restants, ou 0 si dépassé
|
||||
*/
|
||||
public long getJoursRestants() {
|
||||
if (dateLimite == null) return 0;
|
||||
LocalDate aujourd = LocalDate.now();
|
||||
return aujourd.isBefore(dateLimite) ? aujourd.until(dateLimite).getDays() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'aide concerne un montant financier
|
||||
*
|
||||
* @return true si c'est une aide financière
|
||||
*/
|
||||
public boolean isAideFinanciere() {
|
||||
return "FINANCIERE".equals(typeAide) && montantDemande != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule l'écart entre le montant demandé et approuvé
|
||||
*
|
||||
* @return La différence (positif = réduction, négatif = augmentation)
|
||||
*/
|
||||
public BigDecimal getEcartMontant() {
|
||||
if (montantDemande == null || montantApprouve == null) {
|
||||
return BigDecimal.ZERO;
|
||||
}
|
||||
return montantDemande.subtract(montantApprouve);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le pourcentage d'approbation du montant
|
||||
*
|
||||
* @return Le pourcentage du montant approuvé par rapport au demandé
|
||||
*/
|
||||
public int getPourcentageApprobation() {
|
||||
if (montantDemande == null
|
||||
|| montantApprouve == null
|
||||
|| montantDemande.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return 0;
|
||||
}
|
||||
return montantApprouve
|
||||
.multiply(BigDecimal.valueOf(100))
|
||||
.divide(montantDemande, 0, java.math.RoundingMode.HALF_UP)
|
||||
.intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé du type d'aide
|
||||
*
|
||||
* @return Le libellé du type d'aide
|
||||
*/
|
||||
public String getTypeAideLibelle() {
|
||||
if (typeAide == null) return "Non défini";
|
||||
|
||||
return switch (typeAide) {
|
||||
case "FINANCIERE" -> "Aide Financière";
|
||||
case "MATERIELLE" -> "Aide Matérielle";
|
||||
case "MEDICALE" -> "Aide Médicale";
|
||||
case "JURIDIQUE" -> "Aide Juridique";
|
||||
case "LOGEMENT" -> "Aide au Logement";
|
||||
case "EDUCATION" -> "Aide à l'Éducation";
|
||||
case "AUTRE" -> "Autre";
|
||||
default -> typeAide;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé du statut
|
||||
*
|
||||
* @return Le libellé du statut
|
||||
*/
|
||||
public String getStatutLibelle() {
|
||||
if (statut == null) return "Non défini";
|
||||
|
||||
return switch (statut) {
|
||||
case "EN_ATTENTE" -> "En Attente";
|
||||
case "EN_COURS_EVALUATION" -> "En Cours d'Évaluation";
|
||||
case "APPROUVEE" -> "Approuvée";
|
||||
case "REJETEE" -> "Rejetée";
|
||||
case "EN_COURS_AIDE" -> "En Cours d'Aide";
|
||||
case "TERMINEE" -> "Terminée";
|
||||
case "ANNULEE" -> "Annulée";
|
||||
default -> statut;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé de la priorité
|
||||
*
|
||||
* @return Le libellé de la priorité
|
||||
*/
|
||||
public String getPrioriteLibelle() {
|
||||
if (priorite == null) return "Normale";
|
||||
|
||||
return switch (priorite) {
|
||||
case "BASSE" -> "Basse";
|
||||
case "NORMALE" -> "Normale";
|
||||
case "HAUTE" -> "Haute";
|
||||
case "URGENTE" -> "Urgente";
|
||||
default -> priorite;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Approuve la demande d'aide
|
||||
*
|
||||
* @param evaluateurId ID de l'évaluateur
|
||||
* @param nomEvaluateur Nom de l'évaluateur
|
||||
* @param montantApprouve Montant approuvé
|
||||
* @param commentaires Commentaires de l'évaluateur
|
||||
*/
|
||||
public void approuver(
|
||||
UUID evaluateurId, String nomEvaluateur, BigDecimal montantApprouve, String commentaires) {
|
||||
this.statut = "APPROUVEE";
|
||||
this.membreEvaluateurId = evaluateurId;
|
||||
this.nomEvaluateur = nomEvaluateur;
|
||||
this.montantApprouve = montantApprouve;
|
||||
this.commentairesEvaluateur = commentaires;
|
||||
this.dateEvaluation = LocalDateTime.now();
|
||||
this.dateApprobation = LocalDateTime.now();
|
||||
marquerCommeModifie(nomEvaluateur);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rejette la demande d'aide
|
||||
*
|
||||
* @param evaluateurId ID de l'évaluateur
|
||||
* @param nomEvaluateur Nom de l'évaluateur
|
||||
* @param raison Raison du rejet
|
||||
*/
|
||||
public void rejeter(UUID evaluateurId, String nomEvaluateur, String raison) {
|
||||
this.statut = "REJETEE";
|
||||
this.rejeteParId = evaluateurId;
|
||||
this.rejetePar = nomEvaluateur;
|
||||
this.raisonRejet = raison;
|
||||
this.dateRejet = LocalDateTime.now();
|
||||
this.dateEvaluation = LocalDateTime.now();
|
||||
marquerCommeModifie(nomEvaluateur);
|
||||
}
|
||||
|
||||
/**
|
||||
* Démarre l'aide
|
||||
*
|
||||
* @param aidantId ID du membre aidant
|
||||
* @param nomAidant Nom du membre aidant
|
||||
*/
|
||||
public void demarrerAide(UUID aidantId, String nomAidant) {
|
||||
this.statut = "EN_COURS_AIDE";
|
||||
this.membreAidantId = aidantId;
|
||||
this.nomAidant = nomAidant;
|
||||
this.dateDebutAide = LocalDate.now();
|
||||
marquerCommeModifie(nomAidant);
|
||||
}
|
||||
|
||||
/**
|
||||
* Termine l'aide avec versement
|
||||
*
|
||||
* @param montantVerse Montant effectivement versé
|
||||
* @param modeVersement Mode de versement
|
||||
* @param numeroTransaction Numéro de transaction
|
||||
*/
|
||||
public void terminerAvecVersement(
|
||||
BigDecimal montantVerse, String modeVersement, String numeroTransaction) {
|
||||
this.statut = "TERMINEE";
|
||||
this.montantVerse = montantVerse;
|
||||
this.modeVersement = modeVersement;
|
||||
this.numeroTransaction = numeroTransaction;
|
||||
this.dateVersement = LocalDateTime.now();
|
||||
this.dateFinAide = LocalDate.now();
|
||||
marquerCommeModifie("SYSTEM");
|
||||
}
|
||||
|
||||
/** Incrémente le nombre de vues */
|
||||
public void incrementerVues() {
|
||||
if (nombreVues == null) {
|
||||
nombreVues = 1;
|
||||
} else {
|
||||
nombreVues++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Génère un numéro de référence unique
|
||||
*
|
||||
* @return Le numéro de référence généré
|
||||
*/
|
||||
private String genererNumeroReference() {
|
||||
return "AIDE-"
|
||||
+ LocalDate.now().getYear()
|
||||
+ "-"
|
||||
+ String.format("%06d", (int) (Math.random() * 1000000));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AideDTO{"
|
||||
+ "numeroReference='"
|
||||
+ numeroReference
|
||||
+ '\''
|
||||
+ ", typeAide='"
|
||||
+ typeAide
|
||||
+ '\''
|
||||
+ ", titre='"
|
||||
+ titre
|
||||
+ '\''
|
||||
+ ", statut='"
|
||||
+ statut
|
||||
+ '\''
|
||||
+ ", priorite='"
|
||||
+ priorite
|
||||
+ '\''
|
||||
+ ", montantDemande="
|
||||
+ montantDemande
|
||||
+ ", montantApprouve="
|
||||
+ montantApprouve
|
||||
+ ", devise='"
|
||||
+ devise
|
||||
+ '\''
|
||||
+ "} "
|
||||
+ super.toString();
|
||||
}
|
||||
}
|
||||
@@ -2,232 +2,256 @@ package dev.lions.unionflow.server.api.enums.analytics;
|
||||
|
||||
/**
|
||||
* Énumération des formats d'export disponibles pour les rapports et données analytics
|
||||
*
|
||||
* Cette énumération définit les différents formats dans lesquels les données
|
||||
* peuvent être exportées depuis l'application UnionFlow.
|
||||
*
|
||||
*
|
||||
* <p>Cette énumération définit les différents formats dans lesquels les données peuvent être
|
||||
* exportées depuis l'application UnionFlow.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
public enum FormatExport {
|
||||
|
||||
// === FORMATS DOCUMENTS ===
|
||||
PDF("PDF", "pdf", "application/pdf", "Portable Document Format", true, true),
|
||||
WORD("Word", "docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "Microsoft Word", true, false),
|
||||
|
||||
// === FORMATS TABLEURS ===
|
||||
EXCEL("Excel", "xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "Microsoft Excel", true, true),
|
||||
CSV("CSV", "csv", "text/csv", "Comma Separated Values", false, true),
|
||||
|
||||
// === FORMATS DONNÉES ===
|
||||
JSON("JSON", "json", "application/json", "JavaScript Object Notation", false, true),
|
||||
XML("XML", "xml", "application/xml", "eXtensible Markup Language", false, false),
|
||||
|
||||
// === FORMATS IMAGES ===
|
||||
PNG("PNG", "png", "image/png", "Portable Network Graphics", true, false),
|
||||
JPEG("JPEG", "jpg", "image/jpeg", "Joint Photographic Experts Group", true, false),
|
||||
SVG("SVG", "svg", "image/svg+xml", "Scalable Vector Graphics", true, false),
|
||||
|
||||
// === FORMATS SPÉCIALISÉS ===
|
||||
POWERPOINT("PowerPoint", "pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation", "Microsoft PowerPoint", true, false),
|
||||
HTML("HTML", "html", "text/html", "HyperText Markup Language", true, false);
|
||||
|
||||
private final String libelle;
|
||||
private final String extension;
|
||||
private final String mimeType;
|
||||
private final String description;
|
||||
private final boolean supporteGraphiques;
|
||||
private final boolean supporteGrandesQuantitesDonnees;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération FormatExport
|
||||
*
|
||||
* @param libelle Le libellé affiché à l'utilisateur
|
||||
* @param extension L'extension de fichier
|
||||
* @param mimeType Le type MIME du format
|
||||
* @param description La description du format
|
||||
* @param supporteGraphiques true si le format supporte les graphiques
|
||||
* @param supporteGrandesQuantitesDonnees true si le format supporte de grandes quantités de données
|
||||
*/
|
||||
FormatExport(String libelle, String extension, String mimeType, String description,
|
||||
boolean supporteGraphiques, boolean supporteGrandesQuantitesDonnees) {
|
||||
this.libelle = libelle;
|
||||
this.extension = extension;
|
||||
this.mimeType = mimeType;
|
||||
this.description = description;
|
||||
this.supporteGraphiques = supporteGraphiques;
|
||||
this.supporteGrandesQuantitesDonnees = supporteGrandesQuantitesDonnees;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé du format
|
||||
*
|
||||
* @return Le libellé affiché à l'utilisateur
|
||||
*/
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'extension de fichier
|
||||
*
|
||||
* @return L'extension sans le point (ex: "pdf", "xlsx")
|
||||
*/
|
||||
public String getExtension() {
|
||||
return extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le type MIME du format
|
||||
*
|
||||
* @return Le type MIME complet
|
||||
*/
|
||||
public String getMimeType() {
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la description du format
|
||||
*
|
||||
* @return La description complète du format
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le format supporte les graphiques
|
||||
*
|
||||
* @return true si le format peut inclure des graphiques
|
||||
*/
|
||||
public boolean supporteGraphiques() {
|
||||
return supporteGraphiques;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le format supporte de grandes quantités de données
|
||||
*
|
||||
* @return true si le format peut gérer de gros volumes de données
|
||||
*/
|
||||
public boolean supporteGrandesQuantitesDonnees() {
|
||||
return supporteGrandesQuantitesDonnees;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le format est adapté aux rapports exécutifs
|
||||
*
|
||||
* @return true si le format convient aux rapports de direction
|
||||
*/
|
||||
public boolean isFormatExecutif() {
|
||||
return this == PDF || this == POWERPOINT || this == WORD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le format est adapté à l'analyse de données
|
||||
*
|
||||
* @return true si le format convient à l'analyse de données
|
||||
*/
|
||||
public boolean isFormatAnalyse() {
|
||||
return this == EXCEL || this == CSV || this == JSON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le format est adapté au partage web
|
||||
*
|
||||
* @return true si le format convient au partage sur le web
|
||||
*/
|
||||
public boolean isFormatWeb() {
|
||||
return this == HTML || this == PNG || this == SVG || this == JSON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône appropriée pour le format
|
||||
*
|
||||
* @return L'icône Material Design
|
||||
*/
|
||||
public String getIcone() {
|
||||
return switch (this) {
|
||||
case PDF -> "picture_as_pdf";
|
||||
case WORD -> "description";
|
||||
case EXCEL -> "table_chart";
|
||||
case CSV -> "grid_on";
|
||||
case JSON -> "code";
|
||||
case XML -> "code";
|
||||
case PNG, JPEG -> "image";
|
||||
case SVG -> "vector_image";
|
||||
case POWERPOINT -> "slideshow";
|
||||
case HTML -> "web";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur appropriée pour le format
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return switch (this) {
|
||||
case PDF -> "#FF5722"; // Rouge-orange
|
||||
case WORD -> "#2196F3"; // Bleu
|
||||
case EXCEL -> "#4CAF50"; // Vert
|
||||
case CSV -> "#607D8B"; // Bleu gris
|
||||
case JSON -> "#FF9800"; // Orange
|
||||
case XML -> "#795548"; // Marron
|
||||
case PNG, JPEG -> "#E91E63"; // Rose
|
||||
case SVG -> "#9C27B0"; // Violet
|
||||
case POWERPOINT -> "#FF5722"; // Rouge-orange
|
||||
case HTML -> "#00BCD4"; // Cyan
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Génère un nom de fichier avec l'extension appropriée
|
||||
*
|
||||
* @param nomBase Le nom de base du fichier
|
||||
* @return Le nom de fichier complet avec extension
|
||||
*/
|
||||
public String genererNomFichier(String nomBase) {
|
||||
return nomBase + "." + extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la taille maximale recommandée pour ce format (en MB)
|
||||
*
|
||||
* @return La taille maximale en mégaoctets
|
||||
*/
|
||||
public int getTailleMaximaleRecommandee() {
|
||||
return switch (this) {
|
||||
case PDF, WORD, POWERPOINT -> 50; // 50 MB pour les documents
|
||||
case EXCEL -> 100; // 100 MB pour Excel
|
||||
case CSV, JSON, XML -> 200; // 200 MB pour les données
|
||||
case PNG, JPEG -> 10; // 10 MB pour les images
|
||||
case SVG, HTML -> 5; // 5 MB pour les formats légers
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le format nécessite un traitement spécial
|
||||
*
|
||||
* @return true si le format nécessite un traitement particulier
|
||||
*/
|
||||
public boolean necessiteTraitementSpecial() {
|
||||
return this == PDF || this == EXCEL || this == POWERPOINT || this == WORD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les formats recommandés pour un type de rapport donné
|
||||
*
|
||||
* @param typeRapport Le type de rapport (executif, analytique, technique)
|
||||
* @return Un tableau des formats recommandés
|
||||
*/
|
||||
public static FormatExport[] getFormatsRecommandes(String typeRapport) {
|
||||
return switch (typeRapport.toLowerCase()) {
|
||||
case "executif" -> new FormatExport[]{PDF, POWERPOINT, WORD};
|
||||
case "analytique" -> new FormatExport[]{EXCEL, CSV, JSON, PDF};
|
||||
case "technique" -> new FormatExport[]{JSON, XML, CSV, HTML};
|
||||
case "partage" -> new FormatExport[]{PDF, PNG, HTML};
|
||||
default -> new FormatExport[]{PDF, EXCEL, CSV};
|
||||
};
|
||||
}
|
||||
|
||||
// === FORMATS DOCUMENTS ===
|
||||
PDF("PDF", "pdf", "application/pdf", "Portable Document Format", true, true),
|
||||
WORD(
|
||||
"Word",
|
||||
"docx",
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
"Microsoft Word",
|
||||
true,
|
||||
false),
|
||||
|
||||
// === FORMATS TABLEURS ===
|
||||
EXCEL(
|
||||
"Excel",
|
||||
"xlsx",
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
"Microsoft Excel",
|
||||
true,
|
||||
true),
|
||||
CSV("CSV", "csv", "text/csv", "Comma Separated Values", false, true),
|
||||
|
||||
// === FORMATS DONNÉES ===
|
||||
JSON("JSON", "json", "application/json", "JavaScript Object Notation", false, true),
|
||||
XML("XML", "xml", "application/xml", "eXtensible Markup Language", false, false),
|
||||
|
||||
// === FORMATS IMAGES ===
|
||||
PNG("PNG", "png", "image/png", "Portable Network Graphics", true, false),
|
||||
JPEG("JPEG", "jpg", "image/jpeg", "Joint Photographic Experts Group", true, false),
|
||||
SVG("SVG", "svg", "image/svg+xml", "Scalable Vector Graphics", true, false),
|
||||
|
||||
// === FORMATS SPÉCIALISÉS ===
|
||||
POWERPOINT(
|
||||
"PowerPoint",
|
||||
"pptx",
|
||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||
"Microsoft PowerPoint",
|
||||
true,
|
||||
false),
|
||||
HTML("HTML", "html", "text/html", "HyperText Markup Language", true, false);
|
||||
|
||||
private final String libelle;
|
||||
private final String extension;
|
||||
private final String mimeType;
|
||||
private final String description;
|
||||
private final boolean supporteGraphiques;
|
||||
private final boolean supporteGrandesQuantitesDonnees;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération FormatExport
|
||||
*
|
||||
* @param libelle Le libellé affiché à l'utilisateur
|
||||
* @param extension L'extension de fichier
|
||||
* @param mimeType Le type MIME du format
|
||||
* @param description La description du format
|
||||
* @param supporteGraphiques true si le format supporte les graphiques
|
||||
* @param supporteGrandesQuantitesDonnees true si le format supporte de grandes quantités de
|
||||
* données
|
||||
*/
|
||||
FormatExport(
|
||||
String libelle,
|
||||
String extension,
|
||||
String mimeType,
|
||||
String description,
|
||||
boolean supporteGraphiques,
|
||||
boolean supporteGrandesQuantitesDonnees) {
|
||||
this.libelle = libelle;
|
||||
this.extension = extension;
|
||||
this.mimeType = mimeType;
|
||||
this.description = description;
|
||||
this.supporteGraphiques = supporteGraphiques;
|
||||
this.supporteGrandesQuantitesDonnees = supporteGrandesQuantitesDonnees;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé du format
|
||||
*
|
||||
* @return Le libellé affiché à l'utilisateur
|
||||
*/
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'extension de fichier
|
||||
*
|
||||
* @return L'extension sans le point (ex: "pdf", "xlsx")
|
||||
*/
|
||||
public String getExtension() {
|
||||
return extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le type MIME du format
|
||||
*
|
||||
* @return Le type MIME complet
|
||||
*/
|
||||
public String getMimeType() {
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la description du format
|
||||
*
|
||||
* @return La description complète du format
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le format supporte les graphiques
|
||||
*
|
||||
* @return true si le format peut inclure des graphiques
|
||||
*/
|
||||
public boolean supporteGraphiques() {
|
||||
return supporteGraphiques;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le format supporte de grandes quantités de données
|
||||
*
|
||||
* @return true si le format peut gérer de gros volumes de données
|
||||
*/
|
||||
public boolean supporteGrandesQuantitesDonnees() {
|
||||
return supporteGrandesQuantitesDonnees;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le format est adapté aux rapports exécutifs
|
||||
*
|
||||
* @return true si le format convient aux rapports de direction
|
||||
*/
|
||||
public boolean isFormatExecutif() {
|
||||
return this == PDF || this == POWERPOINT || this == WORD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le format est adapté à l'analyse de données
|
||||
*
|
||||
* @return true si le format convient à l'analyse de données
|
||||
*/
|
||||
public boolean isFormatAnalyse() {
|
||||
return this == EXCEL || this == CSV || this == JSON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le format est adapté au partage web
|
||||
*
|
||||
* @return true si le format convient au partage sur le web
|
||||
*/
|
||||
public boolean isFormatWeb() {
|
||||
return this == HTML || this == PNG || this == SVG || this == JSON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône appropriée pour le format
|
||||
*
|
||||
* @return L'icône Material Design
|
||||
*/
|
||||
public String getIcone() {
|
||||
return switch (this) {
|
||||
case PDF -> "picture_as_pdf";
|
||||
case WORD -> "description";
|
||||
case EXCEL -> "table_chart";
|
||||
case CSV -> "grid_on";
|
||||
case JSON -> "code";
|
||||
case XML -> "code";
|
||||
case PNG, JPEG -> "image";
|
||||
case SVG -> "vector_image";
|
||||
case POWERPOINT -> "slideshow";
|
||||
case HTML -> "web";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur appropriée pour le format
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return switch (this) {
|
||||
case PDF -> "#FF5722"; // Rouge-orange
|
||||
case WORD -> "#2196F3"; // Bleu
|
||||
case EXCEL -> "#4CAF50"; // Vert
|
||||
case CSV -> "#607D8B"; // Bleu gris
|
||||
case JSON -> "#FF9800"; // Orange
|
||||
case XML -> "#795548"; // Marron
|
||||
case PNG, JPEG -> "#E91E63"; // Rose
|
||||
case SVG -> "#9C27B0"; // Violet
|
||||
case POWERPOINT -> "#FF5722"; // Rouge-orange
|
||||
case HTML -> "#00BCD4"; // Cyan
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Génère un nom de fichier avec l'extension appropriée
|
||||
*
|
||||
* @param nomBase Le nom de base du fichier
|
||||
* @return Le nom de fichier complet avec extension
|
||||
*/
|
||||
public String genererNomFichier(String nomBase) {
|
||||
return nomBase + "." + extension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la taille maximale recommandée pour ce format (en MB)
|
||||
*
|
||||
* @return La taille maximale en mégaoctets
|
||||
*/
|
||||
public int getTailleMaximaleRecommandee() {
|
||||
return switch (this) {
|
||||
case PDF, WORD, POWERPOINT -> 50; // 50 MB pour les documents
|
||||
case EXCEL -> 100; // 100 MB pour Excel
|
||||
case CSV, JSON, XML -> 200; // 200 MB pour les données
|
||||
case PNG, JPEG -> 10; // 10 MB pour les images
|
||||
case SVG, HTML -> 5; // 5 MB pour les formats légers
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le format nécessite un traitement spécial
|
||||
*
|
||||
* @return true si le format nécessite un traitement particulier
|
||||
*/
|
||||
public boolean necessiteTraitementSpecial() {
|
||||
return this == PDF || this == EXCEL || this == POWERPOINT || this == WORD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les formats recommandés pour un type de rapport donné
|
||||
*
|
||||
* @param typeRapport Le type de rapport (executif, analytique, technique)
|
||||
* @return Un tableau des formats recommandés
|
||||
*/
|
||||
public static FormatExport[] getFormatsRecommandes(String typeRapport) {
|
||||
return switch (typeRapport.toLowerCase()) {
|
||||
case "executif" -> new FormatExport[] {PDF, POWERPOINT, WORD};
|
||||
case "analytique" -> new FormatExport[] {EXCEL, CSV, JSON, PDF};
|
||||
case "technique" -> new FormatExport[] {JSON, XML, CSV, HTML};
|
||||
case "partage" -> new FormatExport[] {PDF, PNG, HTML};
|
||||
default -> new FormatExport[] {PDF, EXCEL, CSV};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,203 +5,222 @@ import java.time.temporal.ChronoUnit;
|
||||
|
||||
/**
|
||||
* Énumération des périodes d'analyse disponibles pour les métriques et rapports
|
||||
*
|
||||
* Cette énumération définit les différentes périodes temporelles qui peuvent être
|
||||
* utilisées pour analyser les données et générer des rapports.
|
||||
*
|
||||
*
|
||||
* <p>Cette énumération définit les différentes périodes temporelles qui peuvent être utilisées pour
|
||||
* analyser les données et générer des rapports.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
public enum PeriodeAnalyse {
|
||||
|
||||
// === PÉRIODES COURTES ===
|
||||
AUJOURD_HUI("Aujourd'hui", "today", 1, ChronoUnit.DAYS),
|
||||
HIER("Hier", "yesterday", 1, ChronoUnit.DAYS),
|
||||
CETTE_SEMAINE("Cette semaine", "this_week", 7, ChronoUnit.DAYS),
|
||||
SEMAINE_DERNIERE("Semaine dernière", "last_week", 7, ChronoUnit.DAYS),
|
||||
|
||||
// === PÉRIODES MENSUELLES ===
|
||||
CE_MOIS("Ce mois", "this_month", 1, ChronoUnit.MONTHS),
|
||||
MOIS_DERNIER("Mois dernier", "last_month", 1, ChronoUnit.MONTHS),
|
||||
TROIS_DERNIERS_MOIS("3 derniers mois", "last_3_months", 3, ChronoUnit.MONTHS),
|
||||
SIX_DERNIERS_MOIS("6 derniers mois", "last_6_months", 6, ChronoUnit.MONTHS),
|
||||
|
||||
// === PÉRIODES ANNUELLES ===
|
||||
CETTE_ANNEE("Cette année", "this_year", 1, ChronoUnit.YEARS),
|
||||
ANNEE_DERNIERE("Année dernière", "last_year", 1, ChronoUnit.YEARS),
|
||||
DEUX_DERNIERES_ANNEES("2 dernières années", "last_2_years", 2, ChronoUnit.YEARS),
|
||||
|
||||
// === PÉRIODES PERSONNALISÉES ===
|
||||
SEPT_DERNIERS_JOURS("7 derniers jours", "last_7_days", 7, ChronoUnit.DAYS),
|
||||
TRENTE_DERNIERS_JOURS("30 derniers jours", "last_30_days", 30, ChronoUnit.DAYS),
|
||||
QUATRE_VINGT_DIX_DERNIERS_JOURS("90 derniers jours", "last_90_days", 90, ChronoUnit.DAYS),
|
||||
|
||||
// === PÉRIODES SPÉCIALES ===
|
||||
DEPUIS_CREATION("Depuis la création", "since_creation", 0, ChronoUnit.FOREVER),
|
||||
PERIODE_PERSONNALISEE("Période personnalisée", "custom", 0, ChronoUnit.DAYS);
|
||||
|
||||
private final String libelle;
|
||||
private final String code;
|
||||
private final int duree;
|
||||
private final ChronoUnit unite;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération PeriodeAnalyse
|
||||
*
|
||||
* @param libelle Le libellé affiché à l'utilisateur
|
||||
* @param code Le code technique de la période
|
||||
* @param duree La durée de la période
|
||||
* @param unite L'unité de temps (jours, mois, années)
|
||||
*/
|
||||
PeriodeAnalyse(String libelle, String code, int duree, ChronoUnit unite) {
|
||||
this.libelle = libelle;
|
||||
this.code = code;
|
||||
this.duree = duree;
|
||||
this.unite = unite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé de la période
|
||||
*
|
||||
* @return Le libellé affiché à l'utilisateur
|
||||
*/
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le code technique de la période
|
||||
*
|
||||
* @return Le code technique
|
||||
*/
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la durée de la période
|
||||
*
|
||||
* @return La durée numérique
|
||||
*/
|
||||
public int getDuree() {
|
||||
return duree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'unité de temps de la période
|
||||
*
|
||||
* @return L'unité de temps (ChronoUnit)
|
||||
*/
|
||||
public ChronoUnit getUnite() {
|
||||
return unite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule la date de début pour cette période
|
||||
*
|
||||
* @return La date de début de la période
|
||||
*/
|
||||
public LocalDateTime getDateDebut() {
|
||||
LocalDateTime maintenant = LocalDateTime.now();
|
||||
|
||||
return switch (this) {
|
||||
case AUJOURD_HUI -> maintenant.toLocalDate().atStartOfDay();
|
||||
case HIER -> maintenant.minusDays(1).toLocalDate().atStartOfDay();
|
||||
case CETTE_SEMAINE -> maintenant.minusDays(maintenant.getDayOfWeek().getValue() - 1).toLocalDate().atStartOfDay();
|
||||
case SEMAINE_DERNIERE -> maintenant.minusDays(maintenant.getDayOfWeek().getValue() + 6).toLocalDate().atStartOfDay();
|
||||
case CE_MOIS -> maintenant.withDayOfMonth(1).toLocalDate().atStartOfDay();
|
||||
case MOIS_DERNIER -> maintenant.minusMonths(1).withDayOfMonth(1).toLocalDate().atStartOfDay();
|
||||
case CETTE_ANNEE -> maintenant.withDayOfYear(1).toLocalDate().atStartOfDay();
|
||||
case ANNEE_DERNIERE -> maintenant.minusYears(1).withDayOfYear(1).toLocalDate().atStartOfDay();
|
||||
case DEPUIS_CREATION -> LocalDateTime.of(2020, 1, 1, 0, 0); // Date de création d'UnionFlow
|
||||
case PERIODE_PERSONNALISEE -> maintenant; // À définir par l'utilisateur
|
||||
default -> maintenant.minus(duree, unite).toLocalDate().atStartOfDay();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule la date de fin pour cette période
|
||||
*
|
||||
* @return La date de fin de la période
|
||||
*/
|
||||
public LocalDateTime getDateFin() {
|
||||
LocalDateTime maintenant = LocalDateTime.now();
|
||||
|
||||
return switch (this) {
|
||||
case AUJOURD_HUI -> maintenant.toLocalDate().atTime(23, 59, 59);
|
||||
case HIER -> maintenant.minusDays(1).toLocalDate().atTime(23, 59, 59);
|
||||
case CETTE_SEMAINE -> maintenant.toLocalDate().atTime(23, 59, 59);
|
||||
case SEMAINE_DERNIERE -> maintenant.minusDays(maintenant.getDayOfWeek().getValue()).toLocalDate().atTime(23, 59, 59);
|
||||
case CE_MOIS -> maintenant.toLocalDate().atTime(23, 59, 59);
|
||||
case MOIS_DERNIER -> maintenant.withDayOfMonth(1).minusDays(1).toLocalDate().atTime(23, 59, 59);
|
||||
case CETTE_ANNEE -> maintenant.toLocalDate().atTime(23, 59, 59);
|
||||
case ANNEE_DERNIERE -> maintenant.withDayOfYear(1).minusDays(1).toLocalDate().atTime(23, 59, 59);
|
||||
case DEPUIS_CREATION, PERIODE_PERSONNALISEE -> maintenant;
|
||||
default -> maintenant.toLocalDate().atTime(23, 59, 59);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la période est une période courte (moins d'un mois)
|
||||
*
|
||||
* @return true si la période est courte
|
||||
*/
|
||||
public boolean isPeriodeCourte() {
|
||||
return this == AUJOURD_HUI || this == HIER || this == CETTE_SEMAINE ||
|
||||
this == SEMAINE_DERNIERE || this == SEPT_DERNIERS_JOURS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la période est une période longue (plus d'un an)
|
||||
*
|
||||
* @return true si la période est longue
|
||||
*/
|
||||
public boolean isPeriodeLongue() {
|
||||
return this == CETTE_ANNEE || this == ANNEE_DERNIERE ||
|
||||
this == DEUX_DERNIERES_ANNEES || this == DEPUIS_CREATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la période est personnalisable
|
||||
*
|
||||
* @return true si la période peut être personnalisée
|
||||
*/
|
||||
public boolean isPersonnalisable() {
|
||||
return this == PERIODE_PERSONNALISEE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'intervalle de regroupement recommandé pour cette période
|
||||
*
|
||||
* @return L'intervalle de regroupement (jour, semaine, mois)
|
||||
*/
|
||||
public String getIntervalleRegroupement() {
|
||||
return switch (this) {
|
||||
case AUJOURD_HUI, HIER -> "heure";
|
||||
case CETTE_SEMAINE, SEMAINE_DERNIERE, SEPT_DERNIERS_JOURS -> "jour";
|
||||
case CE_MOIS, MOIS_DERNIER, TRENTE_DERNIERS_JOURS -> "jour";
|
||||
case TROIS_DERNIERS_MOIS, SIX_DERNIERS_MOIS, QUATRE_VINGT_DIX_DERNIERS_JOURS -> "semaine";
|
||||
case CETTE_ANNEE, ANNEE_DERNIERE, DEUX_DERNIERES_ANNEES -> "mois";
|
||||
case DEPUIS_CREATION -> "annee";
|
||||
default -> "jour";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le format de date approprié pour cette période
|
||||
*
|
||||
* @return Le format de date (dd/MM, MM/yyyy, etc.)
|
||||
*/
|
||||
public String getFormatDate() {
|
||||
return switch (this) {
|
||||
case AUJOURD_HUI, HIER -> "HH:mm";
|
||||
case CETTE_SEMAINE, SEMAINE_DERNIERE, SEPT_DERNIERS_JOURS -> "dd/MM";
|
||||
case CE_MOIS, MOIS_DERNIER, TRENTE_DERNIERS_JOURS -> "dd/MM";
|
||||
case TROIS_DERNIERS_MOIS, SIX_DERNIERS_MOIS, QUATRE_VINGT_DIX_DERNIERS_JOURS -> "dd/MM";
|
||||
case CETTE_ANNEE, ANNEE_DERNIERE -> "MM/yyyy";
|
||||
case DEUX_DERNIERES_ANNEES, DEPUIS_CREATION -> "yyyy";
|
||||
default -> "dd/MM/yyyy";
|
||||
};
|
||||
}
|
||||
|
||||
// === PÉRIODES COURTES ===
|
||||
AUJOURD_HUI("Aujourd'hui", "today", 1, ChronoUnit.DAYS),
|
||||
HIER("Hier", "yesterday", 1, ChronoUnit.DAYS),
|
||||
CETTE_SEMAINE("Cette semaine", "this_week", 7, ChronoUnit.DAYS),
|
||||
SEMAINE_DERNIERE("Semaine dernière", "last_week", 7, ChronoUnit.DAYS),
|
||||
|
||||
// === PÉRIODES MENSUELLES ===
|
||||
CE_MOIS("Ce mois", "this_month", 1, ChronoUnit.MONTHS),
|
||||
MOIS_DERNIER("Mois dernier", "last_month", 1, ChronoUnit.MONTHS),
|
||||
TROIS_DERNIERS_MOIS("3 derniers mois", "last_3_months", 3, ChronoUnit.MONTHS),
|
||||
SIX_DERNIERS_MOIS("6 derniers mois", "last_6_months", 6, ChronoUnit.MONTHS),
|
||||
|
||||
// === PÉRIODES ANNUELLES ===
|
||||
CETTE_ANNEE("Cette année", "this_year", 1, ChronoUnit.YEARS),
|
||||
ANNEE_DERNIERE("Année dernière", "last_year", 1, ChronoUnit.YEARS),
|
||||
DEUX_DERNIERES_ANNEES("2 dernières années", "last_2_years", 2, ChronoUnit.YEARS),
|
||||
|
||||
// === PÉRIODES PERSONNALISÉES ===
|
||||
SEPT_DERNIERS_JOURS("7 derniers jours", "last_7_days", 7, ChronoUnit.DAYS),
|
||||
TRENTE_DERNIERS_JOURS("30 derniers jours", "last_30_days", 30, ChronoUnit.DAYS),
|
||||
QUATRE_VINGT_DIX_DERNIERS_JOURS("90 derniers jours", "last_90_days", 90, ChronoUnit.DAYS),
|
||||
|
||||
// === PÉRIODES SPÉCIALES ===
|
||||
DEPUIS_CREATION("Depuis la création", "since_creation", 0, ChronoUnit.FOREVER),
|
||||
PERIODE_PERSONNALISEE("Période personnalisée", "custom", 0, ChronoUnit.DAYS);
|
||||
|
||||
private final String libelle;
|
||||
private final String code;
|
||||
private final int duree;
|
||||
private final ChronoUnit unite;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération PeriodeAnalyse
|
||||
*
|
||||
* @param libelle Le libellé affiché à l'utilisateur
|
||||
* @param code Le code technique de la période
|
||||
* @param duree La durée de la période
|
||||
* @param unite L'unité de temps (jours, mois, années)
|
||||
*/
|
||||
PeriodeAnalyse(String libelle, String code, int duree, ChronoUnit unite) {
|
||||
this.libelle = libelle;
|
||||
this.code = code;
|
||||
this.duree = duree;
|
||||
this.unite = unite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé de la période
|
||||
*
|
||||
* @return Le libellé affiché à l'utilisateur
|
||||
*/
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le code technique de la période
|
||||
*
|
||||
* @return Le code technique
|
||||
*/
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la durée de la période
|
||||
*
|
||||
* @return La durée numérique
|
||||
*/
|
||||
public int getDuree() {
|
||||
return duree;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'unité de temps de la période
|
||||
*
|
||||
* @return L'unité de temps (ChronoUnit)
|
||||
*/
|
||||
public ChronoUnit getUnite() {
|
||||
return unite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule la date de début pour cette période
|
||||
*
|
||||
* @return La date de début de la période
|
||||
*/
|
||||
public LocalDateTime getDateDebut() {
|
||||
LocalDateTime maintenant = LocalDateTime.now();
|
||||
|
||||
return switch (this) {
|
||||
case AUJOURD_HUI -> maintenant.toLocalDate().atStartOfDay();
|
||||
case HIER -> maintenant.minusDays(1).toLocalDate().atStartOfDay();
|
||||
case CETTE_SEMAINE ->
|
||||
maintenant
|
||||
.minusDays(maintenant.getDayOfWeek().getValue() - 1)
|
||||
.toLocalDate()
|
||||
.atStartOfDay();
|
||||
case SEMAINE_DERNIERE ->
|
||||
maintenant
|
||||
.minusDays(maintenant.getDayOfWeek().getValue() + 6)
|
||||
.toLocalDate()
|
||||
.atStartOfDay();
|
||||
case CE_MOIS -> maintenant.withDayOfMonth(1).toLocalDate().atStartOfDay();
|
||||
case MOIS_DERNIER -> maintenant.minusMonths(1).withDayOfMonth(1).toLocalDate().atStartOfDay();
|
||||
case CETTE_ANNEE -> maintenant.withDayOfYear(1).toLocalDate().atStartOfDay();
|
||||
case ANNEE_DERNIERE -> maintenant.minusYears(1).withDayOfYear(1).toLocalDate().atStartOfDay();
|
||||
case DEPUIS_CREATION -> LocalDateTime.of(2020, 1, 1, 0, 0); // Date de création d'UnionFlow
|
||||
case PERIODE_PERSONNALISEE -> maintenant; // À définir par l'utilisateur
|
||||
default -> maintenant.minus(duree, unite).toLocalDate().atStartOfDay();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule la date de fin pour cette période
|
||||
*
|
||||
* @return La date de fin de la période
|
||||
*/
|
||||
public LocalDateTime getDateFin() {
|
||||
LocalDateTime maintenant = LocalDateTime.now();
|
||||
|
||||
return switch (this) {
|
||||
case AUJOURD_HUI -> maintenant.toLocalDate().atTime(23, 59, 59);
|
||||
case HIER -> maintenant.minusDays(1).toLocalDate().atTime(23, 59, 59);
|
||||
case CETTE_SEMAINE -> maintenant.toLocalDate().atTime(23, 59, 59);
|
||||
case SEMAINE_DERNIERE ->
|
||||
maintenant
|
||||
.minusDays(maintenant.getDayOfWeek().getValue())
|
||||
.toLocalDate()
|
||||
.atTime(23, 59, 59);
|
||||
case CE_MOIS -> maintenant.toLocalDate().atTime(23, 59, 59);
|
||||
case MOIS_DERNIER ->
|
||||
maintenant.withDayOfMonth(1).minusDays(1).toLocalDate().atTime(23, 59, 59);
|
||||
case CETTE_ANNEE -> maintenant.toLocalDate().atTime(23, 59, 59);
|
||||
case ANNEE_DERNIERE ->
|
||||
maintenant.withDayOfYear(1).minusDays(1).toLocalDate().atTime(23, 59, 59);
|
||||
case DEPUIS_CREATION, PERIODE_PERSONNALISEE -> maintenant;
|
||||
default -> maintenant.toLocalDate().atTime(23, 59, 59);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la période est une période courte (moins d'un mois)
|
||||
*
|
||||
* @return true si la période est courte
|
||||
*/
|
||||
public boolean isPeriodeCourte() {
|
||||
return this == AUJOURD_HUI
|
||||
|| this == HIER
|
||||
|| this == CETTE_SEMAINE
|
||||
|| this == SEMAINE_DERNIERE
|
||||
|| this == SEPT_DERNIERS_JOURS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la période est une période longue (plus d'un an)
|
||||
*
|
||||
* @return true si la période est longue
|
||||
*/
|
||||
public boolean isPeriodeLongue() {
|
||||
return this == CETTE_ANNEE
|
||||
|| this == ANNEE_DERNIERE
|
||||
|| this == DEUX_DERNIERES_ANNEES
|
||||
|| this == DEPUIS_CREATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la période est personnalisable
|
||||
*
|
||||
* @return true si la période peut être personnalisée
|
||||
*/
|
||||
public boolean isPersonnalisable() {
|
||||
return this == PERIODE_PERSONNALISEE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'intervalle de regroupement recommandé pour cette période
|
||||
*
|
||||
* @return L'intervalle de regroupement (jour, semaine, mois)
|
||||
*/
|
||||
public String getIntervalleRegroupement() {
|
||||
return switch (this) {
|
||||
case AUJOURD_HUI, HIER -> "heure";
|
||||
case CETTE_SEMAINE, SEMAINE_DERNIERE, SEPT_DERNIERS_JOURS -> "jour";
|
||||
case CE_MOIS, MOIS_DERNIER, TRENTE_DERNIERS_JOURS -> "jour";
|
||||
case TROIS_DERNIERS_MOIS, SIX_DERNIERS_MOIS, QUATRE_VINGT_DIX_DERNIERS_JOURS -> "semaine";
|
||||
case CETTE_ANNEE, ANNEE_DERNIERE, DEUX_DERNIERES_ANNEES -> "mois";
|
||||
case DEPUIS_CREATION -> "annee";
|
||||
default -> "jour";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le format de date approprié pour cette période
|
||||
*
|
||||
* @return Le format de date (dd/MM, MM/yyyy, etc.)
|
||||
*/
|
||||
public String getFormatDate() {
|
||||
return switch (this) {
|
||||
case AUJOURD_HUI, HIER -> "HH:mm";
|
||||
case CETTE_SEMAINE, SEMAINE_DERNIERE, SEPT_DERNIERS_JOURS -> "dd/MM";
|
||||
case CE_MOIS, MOIS_DERNIER, TRENTE_DERNIERS_JOURS -> "dd/MM";
|
||||
case TROIS_DERNIERS_MOIS, SIX_DERNIERS_MOIS, QUATRE_VINGT_DIX_DERNIERS_JOURS -> "dd/MM";
|
||||
case CETTE_ANNEE, ANNEE_DERNIERE -> "MM/yyyy";
|
||||
case DEUX_DERNIERES_ANNEES, DEPUIS_CREATION -> "yyyy";
|
||||
default -> "dd/MM/yyyy";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,186 +2,186 @@ package dev.lions.unionflow.server.api.enums.analytics;
|
||||
|
||||
/**
|
||||
* Énumération des types de métriques disponibles dans le système analytics UnionFlow
|
||||
*
|
||||
* Cette énumération définit les différents types de métriques qui peuvent être
|
||||
* calculées et affichées dans les tableaux de bord et rapports.
|
||||
*
|
||||
*
|
||||
* <p>Cette énumération définit les différents types de métriques qui peuvent être calculées et
|
||||
* affichées dans les tableaux de bord et rapports.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
public enum TypeMetrique {
|
||||
|
||||
// === MÉTRIQUES MEMBRES ===
|
||||
NOMBRE_MEMBRES_ACTIFS("Nombre de membres actifs", "membres", "count"),
|
||||
NOMBRE_MEMBRES_INACTIFS("Nombre de membres inactifs", "membres", "count"),
|
||||
TAUX_CROISSANCE_MEMBRES("Taux de croissance des membres", "membres", "percentage"),
|
||||
MOYENNE_AGE_MEMBRES("Âge moyen des membres", "membres", "average"),
|
||||
REPARTITION_GENRE_MEMBRES("Répartition par genre", "membres", "distribution"),
|
||||
|
||||
// === MÉTRIQUES FINANCIÈRES ===
|
||||
TOTAL_COTISATIONS_COLLECTEES("Total des cotisations collectées", "finance", "amount"),
|
||||
COTISATIONS_EN_ATTENTE("Cotisations en attente", "finance", "amount"),
|
||||
TAUX_RECOUVREMENT_COTISATIONS("Taux de recouvrement", "finance", "percentage"),
|
||||
MOYENNE_COTISATION_MEMBRE("Cotisation moyenne par membre", "finance", "average"),
|
||||
EVOLUTION_REVENUS_MENSUELLE("Évolution des revenus mensuels", "finance", "trend"),
|
||||
|
||||
// === MÉTRIQUES ÉVÉNEMENTS ===
|
||||
NOMBRE_EVENEMENTS_ORGANISES("Nombre d'événements organisés", "evenements", "count"),
|
||||
TAUX_PARTICIPATION_EVENEMENTS("Taux de participation aux événements", "evenements", "percentage"),
|
||||
MOYENNE_PARTICIPANTS_EVENEMENT("Moyenne de participants par événement", "evenements", "average"),
|
||||
EVENEMENTS_ANNULES("Événements annulés", "evenements", "count"),
|
||||
SATISFACTION_EVENEMENTS("Satisfaction des événements", "evenements", "rating"),
|
||||
|
||||
// === MÉTRIQUES SOLIDARITÉ ===
|
||||
NOMBRE_DEMANDES_AIDE("Nombre de demandes d'aide", "solidarite", "count"),
|
||||
MONTANT_AIDES_ACCORDEES("Montant des aides accordées", "solidarite", "amount"),
|
||||
TAUX_APPROBATION_AIDES("Taux d'approbation des aides", "solidarite", "percentage"),
|
||||
DELAI_TRAITEMENT_DEMANDES("Délai moyen de traitement", "solidarite", "duration"),
|
||||
IMPACT_SOCIAL_MESURE("Impact social mesuré", "solidarite", "score"),
|
||||
|
||||
// === MÉTRIQUES ENGAGEMENT ===
|
||||
TAUX_CONNEXION_MOBILE("Taux de connexion mobile", "engagement", "percentage"),
|
||||
FREQUENCE_UTILISATION_APP("Fréquence d'utilisation de l'app", "engagement", "frequency"),
|
||||
ACTIONS_UTILISATEUR_JOUR("Actions utilisateur par jour", "engagement", "count"),
|
||||
RETENTION_UTILISATEURS("Rétention des utilisateurs", "engagement", "percentage"),
|
||||
NPS_SATISFACTION("Net Promoter Score", "engagement", "score"),
|
||||
|
||||
// === MÉTRIQUES ORGANISATIONNELLES ===
|
||||
NOMBRE_ORGANISATIONS_ACTIVES("Organisations actives", "organisation", "count"),
|
||||
TAUX_CROISSANCE_ORGANISATIONS("Croissance des organisations", "organisation", "percentage"),
|
||||
MOYENNE_MEMBRES_PAR_ORGANISATION("Membres moyens par organisation", "organisation", "average"),
|
||||
ORGANISATIONS_PREMIUM("Organisations premium", "organisation", "count"),
|
||||
CHURN_RATE_ORGANISATIONS("Taux de désabonnement", "organisation", "percentage"),
|
||||
|
||||
// === MÉTRIQUES TECHNIQUES ===
|
||||
TEMPS_REPONSE_API("Temps de réponse API", "technique", "duration"),
|
||||
TAUX_DISPONIBILITE_SYSTEME("Taux de disponibilité", "technique", "percentage"),
|
||||
NOMBRE_ERREURS_SYSTEME("Nombre d'erreurs système", "technique", "count"),
|
||||
UTILISATION_STOCKAGE("Utilisation du stockage", "technique", "size"),
|
||||
PERFORMANCE_MOBILE("Performance mobile", "technique", "score");
|
||||
|
||||
private final String libelle;
|
||||
private final String categorie;
|
||||
private final String typeValeur;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération TypeMetrique
|
||||
*
|
||||
* @param libelle Le libellé affiché à l'utilisateur
|
||||
* @param categorie La catégorie de la métrique
|
||||
* @param typeValeur Le type de valeur (count, percentage, amount, etc.)
|
||||
*/
|
||||
TypeMetrique(String libelle, String categorie, String typeValeur) {
|
||||
this.libelle = libelle;
|
||||
this.categorie = categorie;
|
||||
this.typeValeur = typeValeur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé de la métrique
|
||||
*
|
||||
* @return Le libellé affiché à l'utilisateur
|
||||
*/
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la catégorie de la métrique
|
||||
*
|
||||
* @return La catégorie (membres, finance, evenements, etc.)
|
||||
*/
|
||||
public String getCategorie() {
|
||||
return categorie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le type de valeur de la métrique
|
||||
*
|
||||
* @return Le type de valeur (count, percentage, amount, etc.)
|
||||
*/
|
||||
public String getTypeValeur() {
|
||||
return typeValeur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique est de type financier
|
||||
*
|
||||
* @return true si la métrique concerne les finances
|
||||
*/
|
||||
public boolean isFinanciere() {
|
||||
return "finance".equals(this.categorie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique est de type pourcentage
|
||||
*
|
||||
* @return true si la métrique est un pourcentage
|
||||
*/
|
||||
public boolean isPourcentage() {
|
||||
return "percentage".equals(this.typeValeur);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique est de type compteur
|
||||
*
|
||||
* @return true si la métrique est un compteur
|
||||
*/
|
||||
public boolean isCompteur() {
|
||||
return "count".equals(this.typeValeur);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'unité de mesure appropriée pour la métrique
|
||||
*
|
||||
* @return L'unité de mesure (%, XOF, jours, etc.)
|
||||
*/
|
||||
public String getUnite() {
|
||||
return switch (this.typeValeur) {
|
||||
case "percentage" -> "%";
|
||||
case "amount" -> "XOF";
|
||||
case "duration" -> "jours";
|
||||
case "size" -> "MB";
|
||||
case "frequency" -> "/jour";
|
||||
case "rating", "score" -> "/10";
|
||||
default -> "";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône appropriée pour la métrique
|
||||
*
|
||||
* @return L'icône Material Design
|
||||
*/
|
||||
public String getIcone() {
|
||||
return switch (this.categorie) {
|
||||
case "membres" -> "people";
|
||||
case "finance" -> "attach_money";
|
||||
case "evenements" -> "event";
|
||||
case "solidarite" -> "favorite";
|
||||
case "engagement" -> "trending_up";
|
||||
case "organisation" -> "business";
|
||||
case "technique" -> "settings";
|
||||
default -> "analytics";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur appropriée pour la métrique
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return switch (this.categorie) {
|
||||
case "membres" -> "#2196F3"; // Bleu
|
||||
case "finance" -> "#4CAF50"; // Vert
|
||||
case "evenements" -> "#FF9800"; // Orange
|
||||
case "solidarite" -> "#E91E63"; // Rose
|
||||
case "engagement" -> "#9C27B0"; // Violet
|
||||
case "organisation" -> "#607D8B"; // Bleu gris
|
||||
case "technique" -> "#795548"; // Marron
|
||||
default -> "#757575"; // Gris
|
||||
};
|
||||
}
|
||||
|
||||
// === MÉTRIQUES MEMBRES ===
|
||||
NOMBRE_MEMBRES_ACTIFS("Nombre de membres actifs", "membres", "count"),
|
||||
NOMBRE_MEMBRES_INACTIFS("Nombre de membres inactifs", "membres", "count"),
|
||||
TAUX_CROISSANCE_MEMBRES("Taux de croissance des membres", "membres", "percentage"),
|
||||
MOYENNE_AGE_MEMBRES("Âge moyen des membres", "membres", "average"),
|
||||
REPARTITION_GENRE_MEMBRES("Répartition par genre", "membres", "distribution"),
|
||||
|
||||
// === MÉTRIQUES FINANCIÈRES ===
|
||||
TOTAL_COTISATIONS_COLLECTEES("Total des cotisations collectées", "finance", "amount"),
|
||||
COTISATIONS_EN_ATTENTE("Cotisations en attente", "finance", "amount"),
|
||||
TAUX_RECOUVREMENT_COTISATIONS("Taux de recouvrement", "finance", "percentage"),
|
||||
MOYENNE_COTISATION_MEMBRE("Cotisation moyenne par membre", "finance", "average"),
|
||||
EVOLUTION_REVENUS_MENSUELLE("Évolution des revenus mensuels", "finance", "trend"),
|
||||
|
||||
// === MÉTRIQUES ÉVÉNEMENTS ===
|
||||
NOMBRE_EVENEMENTS_ORGANISES("Nombre d'événements organisés", "evenements", "count"),
|
||||
TAUX_PARTICIPATION_EVENEMENTS("Taux de participation aux événements", "evenements", "percentage"),
|
||||
MOYENNE_PARTICIPANTS_EVENEMENT("Moyenne de participants par événement", "evenements", "average"),
|
||||
EVENEMENTS_ANNULES("Événements annulés", "evenements", "count"),
|
||||
SATISFACTION_EVENEMENTS("Satisfaction des événements", "evenements", "rating"),
|
||||
|
||||
// === MÉTRIQUES SOLIDARITÉ ===
|
||||
NOMBRE_DEMANDES_AIDE("Nombre de demandes d'aide", "solidarite", "count"),
|
||||
MONTANT_AIDES_ACCORDEES("Montant des aides accordées", "solidarite", "amount"),
|
||||
TAUX_APPROBATION_AIDES("Taux d'approbation des aides", "solidarite", "percentage"),
|
||||
DELAI_TRAITEMENT_DEMANDES("Délai moyen de traitement", "solidarite", "duration"),
|
||||
IMPACT_SOCIAL_MESURE("Impact social mesuré", "solidarite", "score"),
|
||||
|
||||
// === MÉTRIQUES ENGAGEMENT ===
|
||||
TAUX_CONNEXION_MOBILE("Taux de connexion mobile", "engagement", "percentage"),
|
||||
FREQUENCE_UTILISATION_APP("Fréquence d'utilisation de l'app", "engagement", "frequency"),
|
||||
ACTIONS_UTILISATEUR_JOUR("Actions utilisateur par jour", "engagement", "count"),
|
||||
RETENTION_UTILISATEURS("Rétention des utilisateurs", "engagement", "percentage"),
|
||||
NPS_SATISFACTION("Net Promoter Score", "engagement", "score"),
|
||||
|
||||
// === MÉTRIQUES ORGANISATIONNELLES ===
|
||||
NOMBRE_ORGANISATIONS_ACTIVES("Organisations actives", "organisation", "count"),
|
||||
TAUX_CROISSANCE_ORGANISATIONS("Croissance des organisations", "organisation", "percentage"),
|
||||
MOYENNE_MEMBRES_PAR_ORGANISATION("Membres moyens par organisation", "organisation", "average"),
|
||||
ORGANISATIONS_PREMIUM("Organisations premium", "organisation", "count"),
|
||||
CHURN_RATE_ORGANISATIONS("Taux de désabonnement", "organisation", "percentage"),
|
||||
|
||||
// === MÉTRIQUES TECHNIQUES ===
|
||||
TEMPS_REPONSE_API("Temps de réponse API", "technique", "duration"),
|
||||
TAUX_DISPONIBILITE_SYSTEME("Taux de disponibilité", "technique", "percentage"),
|
||||
NOMBRE_ERREURS_SYSTEME("Nombre d'erreurs système", "technique", "count"),
|
||||
UTILISATION_STOCKAGE("Utilisation du stockage", "technique", "size"),
|
||||
PERFORMANCE_MOBILE("Performance mobile", "technique", "score");
|
||||
|
||||
private final String libelle;
|
||||
private final String categorie;
|
||||
private final String typeValeur;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération TypeMetrique
|
||||
*
|
||||
* @param libelle Le libellé affiché à l'utilisateur
|
||||
* @param categorie La catégorie de la métrique
|
||||
* @param typeValeur Le type de valeur (count, percentage, amount, etc.)
|
||||
*/
|
||||
TypeMetrique(String libelle, String categorie, String typeValeur) {
|
||||
this.libelle = libelle;
|
||||
this.categorie = categorie;
|
||||
this.typeValeur = typeValeur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé de la métrique
|
||||
*
|
||||
* @return Le libellé affiché à l'utilisateur
|
||||
*/
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la catégorie de la métrique
|
||||
*
|
||||
* @return La catégorie (membres, finance, evenements, etc.)
|
||||
*/
|
||||
public String getCategorie() {
|
||||
return categorie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le type de valeur de la métrique
|
||||
*
|
||||
* @return Le type de valeur (count, percentage, amount, etc.)
|
||||
*/
|
||||
public String getTypeValeur() {
|
||||
return typeValeur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique est de type financier
|
||||
*
|
||||
* @return true si la métrique concerne les finances
|
||||
*/
|
||||
public boolean isFinanciere() {
|
||||
return "finance".equals(this.categorie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique est de type pourcentage
|
||||
*
|
||||
* @return true si la métrique est un pourcentage
|
||||
*/
|
||||
public boolean isPourcentage() {
|
||||
return "percentage".equals(this.typeValeur);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la métrique est de type compteur
|
||||
*
|
||||
* @return true si la métrique est un compteur
|
||||
*/
|
||||
public boolean isCompteur() {
|
||||
return "count".equals(this.typeValeur);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'unité de mesure appropriée pour la métrique
|
||||
*
|
||||
* @return L'unité de mesure (%, XOF, jours, etc.)
|
||||
*/
|
||||
public String getUnite() {
|
||||
return switch (this.typeValeur) {
|
||||
case "percentage" -> "%";
|
||||
case "amount" -> "XOF";
|
||||
case "duration" -> "jours";
|
||||
case "size" -> "MB";
|
||||
case "frequency" -> "/jour";
|
||||
case "rating", "score" -> "/10";
|
||||
default -> "";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône appropriée pour la métrique
|
||||
*
|
||||
* @return L'icône Material Design
|
||||
*/
|
||||
public String getIcone() {
|
||||
return switch (this.categorie) {
|
||||
case "membres" -> "people";
|
||||
case "finance" -> "attach_money";
|
||||
case "evenements" -> "event";
|
||||
case "solidarite" -> "favorite";
|
||||
case "engagement" -> "trending_up";
|
||||
case "organisation" -> "business";
|
||||
case "technique" -> "settings";
|
||||
default -> "analytics";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur appropriée pour la métrique
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return switch (this.categorie) {
|
||||
case "membres" -> "#2196F3"; // Bleu
|
||||
case "finance" -> "#4CAF50"; // Vert
|
||||
case "evenements" -> "#FF9800"; // Orange
|
||||
case "solidarite" -> "#E91E63"; // Rose
|
||||
case "engagement" -> "#9C27B0"; // Violet
|
||||
case "organisation" -> "#607D8B"; // Bleu gris
|
||||
case "technique" -> "#795548"; // Marron
|
||||
default -> "#757575"; // Gris
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
package dev.lions.unionflow.server.api.enums.evenement;
|
||||
|
||||
/**
|
||||
* Énumération des priorités d'événements dans UnionFlow
|
||||
*
|
||||
* <p>Cette énumération définit les niveaux de priorité pour les événements, permettant de prioriser
|
||||
* l'affichage et les notifications selon l'importance.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-09-21
|
||||
*/
|
||||
public enum PrioriteEvenement {
|
||||
CRITIQUE(
|
||||
"Critique",
|
||||
"critical",
|
||||
1,
|
||||
"Événement critique nécessitant une attention immédiate",
|
||||
"#F44336",
|
||||
"priority_high",
|
||||
true,
|
||||
true),
|
||||
|
||||
HAUTE(
|
||||
"Haute",
|
||||
"high",
|
||||
2,
|
||||
"Événement de haute priorité",
|
||||
"#FF9800",
|
||||
"keyboard_arrow_up",
|
||||
true,
|
||||
false),
|
||||
|
||||
NORMALE(
|
||||
"Normale", "normal", 3, "Événement de priorité normale", "#2196F3", "remove", false, false),
|
||||
|
||||
BASSE(
|
||||
"Basse",
|
||||
"low",
|
||||
4,
|
||||
"Événement de priorité basse",
|
||||
"#4CAF50",
|
||||
"keyboard_arrow_down",
|
||||
false,
|
||||
false);
|
||||
|
||||
private final String libelle;
|
||||
private final String code;
|
||||
private final int niveau;
|
||||
private final String description;
|
||||
private final String couleur;
|
||||
private final String icone;
|
||||
private final boolean notificationImmediate;
|
||||
private final boolean escaladeAutomatique;
|
||||
|
||||
PrioriteEvenement(
|
||||
String libelle,
|
||||
String code,
|
||||
int niveau,
|
||||
String description,
|
||||
String couleur,
|
||||
String icone,
|
||||
boolean notificationImmediate,
|
||||
boolean escaladeAutomatique) {
|
||||
this.libelle = libelle;
|
||||
this.code = code;
|
||||
this.niveau = niveau;
|
||||
this.description = description;
|
||||
this.couleur = couleur;
|
||||
this.icone = icone;
|
||||
this.notificationImmediate = notificationImmediate;
|
||||
this.escaladeAutomatique = escaladeAutomatique;
|
||||
}
|
||||
|
||||
// === GETTERS ===
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public int getNiveau() {
|
||||
return niveau;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getCouleur() {
|
||||
return couleur;
|
||||
}
|
||||
|
||||
public String getIcone() {
|
||||
return icone;
|
||||
}
|
||||
|
||||
public boolean isNotificationImmediate() {
|
||||
return notificationImmediate;
|
||||
}
|
||||
|
||||
public boolean isEscaladeAutomatique() {
|
||||
return escaladeAutomatique;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/** Vérifie si la priorité est élevée (critique ou haute) */
|
||||
public boolean isElevee() {
|
||||
return this == CRITIQUE || this == HAUTE;
|
||||
}
|
||||
|
||||
/** Vérifie si la priorité nécessite une attention immédiate */
|
||||
public boolean isUrgente() {
|
||||
return this == CRITIQUE || this == HAUTE;
|
||||
}
|
||||
|
||||
/** Compare deux priorités */
|
||||
public boolean isSuperieurA(PrioriteEvenement autre) {
|
||||
return this.niveau < autre.niveau; // Plus le niveau est bas, plus la priorité est haute
|
||||
}
|
||||
|
||||
/** Retourne les priorités élevées */
|
||||
public static java.util.List<PrioriteEvenement> getPrioritesElevees() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(PrioriteEvenement::isElevee)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Retourne les priorités urgentes */
|
||||
public static java.util.List<PrioriteEvenement> getPrioritesUrgentes() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(PrioriteEvenement::isUrgente)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Détermine la priorité basée sur le type d'événement */
|
||||
public static PrioriteEvenement determinerPriorite(TypeEvenementMetier typeEvenement) {
|
||||
return switch (typeEvenement) {
|
||||
case ASSEMBLEE_GENERALE -> HAUTE;
|
||||
case REUNION_BUREAU -> HAUTE;
|
||||
case ACTION_CARITATIVE -> NORMALE;
|
||||
case FORMATION -> NORMALE;
|
||||
case CONFERENCE -> NORMALE;
|
||||
case ACTIVITE_SOCIALE -> BASSE;
|
||||
case ATELIER -> BASSE;
|
||||
case CEREMONIE -> NORMALE;
|
||||
case AUTRE -> NORMALE;
|
||||
};
|
||||
}
|
||||
|
||||
/** Retourne la priorité par défaut */
|
||||
public static PrioriteEvenement getDefaut() {
|
||||
return NORMALE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
package dev.lions.unionflow.server.api.enums.evenement;
|
||||
|
||||
/**
|
||||
* Énumération des statuts d'événements dans UnionFlow
|
||||
*
|
||||
* <p>Cette énumération définit les différents états qu'un événement peut avoir tout au long de son
|
||||
* cycle de vie, de la planification à la clôture.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-09-21
|
||||
*/
|
||||
public enum StatutEvenement {
|
||||
|
||||
// === STATUTS DE PLANIFICATION ===
|
||||
PLANIFIE(
|
||||
"Planifié",
|
||||
"planned",
|
||||
"L'événement est planifié et en préparation",
|
||||
"#2196F3",
|
||||
"event",
|
||||
false,
|
||||
false),
|
||||
|
||||
CONFIRME(
|
||||
"Confirmé",
|
||||
"confirmed",
|
||||
"L'événement est confirmé et les inscriptions sont ouvertes",
|
||||
"#4CAF50",
|
||||
"event_available",
|
||||
false,
|
||||
false),
|
||||
|
||||
// === STATUTS D'EXÉCUTION ===
|
||||
EN_COURS(
|
||||
"En cours",
|
||||
"ongoing",
|
||||
"L'événement est actuellement en cours",
|
||||
"#FF9800",
|
||||
"play_circle",
|
||||
false,
|
||||
false),
|
||||
|
||||
// === STATUTS FINAUX ===
|
||||
TERMINE(
|
||||
"Terminé",
|
||||
"completed",
|
||||
"L'événement s'est terminé avec succès",
|
||||
"#4CAF50",
|
||||
"check_circle",
|
||||
true,
|
||||
false),
|
||||
|
||||
ANNULE("Annulé", "cancelled", "L'événement a été annulé", "#F44336", "cancel", true, true),
|
||||
|
||||
REPORTE(
|
||||
"Reporté",
|
||||
"postponed",
|
||||
"L'événement a été reporté à une date ultérieure",
|
||||
"#FF5722",
|
||||
"schedule",
|
||||
false,
|
||||
false);
|
||||
|
||||
private final String libelle;
|
||||
private final String code;
|
||||
private final String description;
|
||||
private final String couleur;
|
||||
private final String icone;
|
||||
private final boolean estFinal;
|
||||
private final boolean estEchec;
|
||||
|
||||
StatutEvenement(
|
||||
String libelle,
|
||||
String code,
|
||||
String description,
|
||||
String couleur,
|
||||
String icone,
|
||||
boolean estFinal,
|
||||
boolean estEchec) {
|
||||
this.libelle = libelle;
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
this.couleur = couleur;
|
||||
this.icone = icone;
|
||||
this.estFinal = estFinal;
|
||||
this.estEchec = estEchec;
|
||||
}
|
||||
|
||||
// === GETTERS ===
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getCouleur() {
|
||||
return couleur;
|
||||
}
|
||||
|
||||
public String getIcone() {
|
||||
return icone;
|
||||
}
|
||||
|
||||
public boolean isEstFinal() {
|
||||
return estFinal;
|
||||
}
|
||||
|
||||
public boolean isEstEchec() {
|
||||
return estEchec;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/** Vérifie si l'événement peut être modifié */
|
||||
public boolean permetModification() {
|
||||
return switch (this) {
|
||||
case PLANIFIE, CONFIRME, REPORTE -> true;
|
||||
case EN_COURS, TERMINE, ANNULE -> false;
|
||||
};
|
||||
}
|
||||
|
||||
/** Vérifie si l'événement peut être annulé */
|
||||
public boolean permetAnnulation() {
|
||||
return switch (this) {
|
||||
case PLANIFIE, CONFIRME, EN_COURS, REPORTE -> true;
|
||||
case TERMINE, ANNULE -> false;
|
||||
};
|
||||
}
|
||||
|
||||
/** Vérifie si l'événement est en cours d'exécution */
|
||||
public boolean isEnCours() {
|
||||
return this == EN_COURS;
|
||||
}
|
||||
|
||||
/** Vérifie si l'événement est terminé avec succès */
|
||||
public boolean isSucces() {
|
||||
return this == TERMINE;
|
||||
}
|
||||
|
||||
/** Retourne les statuts finaux */
|
||||
public static java.util.List<StatutEvenement> getStatutsFinaux() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutEvenement::isEstFinal)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Retourne les statuts d'échec */
|
||||
public static java.util.List<StatutEvenement> getStatutsEchec() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutEvenement::isEstEchec)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Vérifie si la transition vers un autre statut est valide */
|
||||
public boolean peutTransitionnerVers(StatutEvenement nouveauStatut) {
|
||||
if (this == nouveauStatut) return false;
|
||||
if (estFinal && nouveauStatut != REPORTE) return false;
|
||||
|
||||
return switch (this) {
|
||||
case PLANIFIE ->
|
||||
nouveauStatut == CONFIRME || nouveauStatut == ANNULE || nouveauStatut == REPORTE;
|
||||
case CONFIRME ->
|
||||
nouveauStatut == EN_COURS || nouveauStatut == ANNULE || nouveauStatut == REPORTE;
|
||||
case EN_COURS -> nouveauStatut == TERMINE || nouveauStatut == ANNULE;
|
||||
case REPORTE -> nouveauStatut == PLANIFIE || nouveauStatut == ANNULE;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
/** Retourne le niveau de priorité pour l'affichage */
|
||||
public int getNiveauPriorite() {
|
||||
return switch (this) {
|
||||
case EN_COURS -> 1;
|
||||
case CONFIRME -> 2;
|
||||
case PLANIFIE -> 3;
|
||||
case REPORTE -> 4;
|
||||
case TERMINE -> 5;
|
||||
case ANNULE -> 6;
|
||||
};
|
||||
}
|
||||
|
||||
// === MÉTHODES STATIQUES ===
|
||||
|
||||
/** Retourne les statuts actifs (non finaux) */
|
||||
public static StatutEvenement[] getStatutsActifs() {
|
||||
return new StatutEvenement[] {PLANIFIE, CONFIRME, EN_COURS, REPORTE};
|
||||
}
|
||||
|
||||
/** Trouve un statut par son code */
|
||||
public static StatutEvenement fromCode(String code) {
|
||||
if (code == null || code.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (StatutEvenement statut : values()) {
|
||||
if (statut.code.equals(code)) {
|
||||
return statut;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Trouve un statut par son libellé */
|
||||
public static StatutEvenement fromLibelle(String libelle) {
|
||||
if (libelle == null || libelle.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
for (StatutEvenement statut : values()) {
|
||||
if (statut.libelle.equals(libelle)) {
|
||||
return statut;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Retourne les transitions possibles depuis ce statut */
|
||||
public StatutEvenement[] getTransitionsPossibles() {
|
||||
return switch (this) {
|
||||
case PLANIFIE -> new StatutEvenement[] {CONFIRME, ANNULE, REPORTE};
|
||||
case CONFIRME -> new StatutEvenement[] {EN_COURS, ANNULE, REPORTE};
|
||||
case EN_COURS -> new StatutEvenement[] {TERMINE, ANNULE};
|
||||
case REPORTE -> new StatutEvenement[] {PLANIFIE, CONFIRME, ANNULE};
|
||||
case TERMINE, ANNULE -> new StatutEvenement[] {}; // Aucune transition possible
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -2,320 +2,464 @@ package dev.lions.unionflow.server.api.enums.notification;
|
||||
|
||||
/**
|
||||
* Énumération des canaux de notification pour Android et iOS
|
||||
*
|
||||
* Cette énumération définit les différents canaux de notification utilisés
|
||||
* pour organiser et prioriser les notifications push dans UnionFlow.
|
||||
*
|
||||
*
|
||||
* <p>Cette énumération définit les différents canaux de notification utilisés pour organiser et
|
||||
* prioriser les notifications push dans UnionFlow.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
public enum CanalNotification {
|
||||
|
||||
// === CANAUX PAR PRIORITÉ ===
|
||||
URGENT_CHANNEL("urgent", "Notifications urgentes", "Alertes critiques nécessitant une action immédiate",
|
||||
5, true, true, true, "urgent", "#F44336"),
|
||||
|
||||
ERROR_CHANNEL("error", "Erreurs système", "Notifications d'erreurs et de problèmes techniques",
|
||||
4, true, true, false, "error", "#F44336"),
|
||||
|
||||
WARNING_CHANNEL("warning", "Avertissements", "Notifications d'avertissement et d'attention",
|
||||
4, true, true, false, "warning", "#FF9800"),
|
||||
|
||||
IMPORTANT_CHANNEL("important", "Notifications importantes", "Informations importantes à ne pas manquer",
|
||||
4, true, true, false, "important", "#FF5722"),
|
||||
|
||||
REMINDER_CHANNEL("reminder", "Rappels", "Rappels d'événements, cotisations et échéances",
|
||||
3, true, true, false, "reminder", "#2196F3"),
|
||||
|
||||
SUCCESS_CHANNEL("success", "Confirmations", "Notifications de succès et confirmations",
|
||||
2, false, false, false, "success", "#4CAF50"),
|
||||
|
||||
CELEBRATION_CHANNEL("celebration", "Célébrations", "Anniversaires, félicitations et événements joyeux",
|
||||
2, false, false, false, "celebration", "#FF9800"),
|
||||
|
||||
DEFAULT_CHANNEL("default", "Notifications générales", "Notifications d'information générale",
|
||||
2, false, false, false, "info", "#2196F3"),
|
||||
|
||||
// === CANAUX PAR CATÉGORIE ===
|
||||
EVENTS_CHANNEL("events", "Événements", "Notifications liées aux événements et activités",
|
||||
3, true, false, false, "event", "#2196F3"),
|
||||
|
||||
PAYMENTS_CHANNEL("payments", "Paiements", "Notifications de cotisations et paiements",
|
||||
4, true, true, false, "payment", "#4CAF50"),
|
||||
|
||||
SOLIDARITY_CHANNEL("solidarity", "Solidarité", "Notifications d'aide et de solidarité",
|
||||
3, true, false, false, "help", "#E91E63"),
|
||||
|
||||
MEMBERS_CHANNEL("members", "Membres", "Notifications concernant les membres",
|
||||
2, false, false, false, "people", "#2196F3"),
|
||||
|
||||
ORGANIZATION_CHANNEL("organization", "Organisation", "Annonces et informations organisationnelles",
|
||||
3, true, false, false, "business", "#2196F3"),
|
||||
|
||||
SYSTEM_CHANNEL("system", "Système", "Notifications système et maintenance",
|
||||
2, false, false, false, "settings", "#607D8B"),
|
||||
|
||||
MESSAGES_CHANNEL("messages", "Messages", "Messages privés et communications",
|
||||
3, true, false, false, "message", "#2196F3"),
|
||||
|
||||
LOCATION_CHANNEL("location", "Géolocalisation", "Notifications basées sur la localisation",
|
||||
2, false, false, false, "location_on", "#4CAF50");
|
||||
|
||||
private final String id;
|
||||
private final String nom;
|
||||
private final String description;
|
||||
private final int importance;
|
||||
private final boolean sonActive;
|
||||
private final boolean vibrationActive;
|
||||
private final boolean lumiereLED;
|
||||
private final String typeDefaut;
|
||||
private final String couleur;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération CanalNotification
|
||||
*
|
||||
* @param id L'identifiant unique du canal
|
||||
* @param nom Le nom affiché du canal
|
||||
* @param description La description du canal
|
||||
* @param importance Le niveau d'importance (1=Min, 2=Low, 3=Default, 4=High, 5=Max)
|
||||
* @param sonActive true si le son est activé par défaut
|
||||
* @param vibrationActive true si la vibration est activée par défaut
|
||||
* @param lumiereLED true si la lumière LED est activée par défaut
|
||||
* @param typeDefaut Le type de notification par défaut pour ce canal
|
||||
* @param couleur La couleur hexadécimale du canal
|
||||
*/
|
||||
CanalNotification(String id, String nom, String description, int importance,
|
||||
boolean sonActive, boolean vibrationActive, boolean lumiereLED,
|
||||
String typeDefaut, String couleur) {
|
||||
this.id = id;
|
||||
this.nom = nom;
|
||||
this.description = description;
|
||||
this.importance = importance;
|
||||
this.sonActive = sonActive;
|
||||
this.vibrationActive = vibrationActive;
|
||||
this.lumiereLED = lumiereLED;
|
||||
this.typeDefaut = typeDefaut;
|
||||
this.couleur = couleur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'identifiant du canal
|
||||
*
|
||||
* @return L'ID unique du canal
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nom du canal
|
||||
*
|
||||
* @return Le nom affiché du canal
|
||||
*/
|
||||
public String getNom() {
|
||||
return nom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la description du canal
|
||||
*
|
||||
* @return La description détaillée du canal
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le niveau d'importance
|
||||
*
|
||||
* @return Le niveau d'importance (1-5)
|
||||
*/
|
||||
public int getImportance() {
|
||||
return importance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le son est activé par défaut
|
||||
*
|
||||
* @return true si le son est activé
|
||||
*/
|
||||
public boolean isSonActive() {
|
||||
return sonActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la vibration est activée par défaut
|
||||
*
|
||||
* @return true si la vibration est activée
|
||||
*/
|
||||
public boolean isVibrationActive() {
|
||||
return vibrationActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la lumière LED est activée par défaut
|
||||
*
|
||||
* @return true si la lumière LED est activée
|
||||
*/
|
||||
public boolean isLumiereLED() {
|
||||
return lumiereLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le type de notification par défaut
|
||||
*
|
||||
* @return Le type par défaut pour ce canal
|
||||
*/
|
||||
public String getTypeDefaut() {
|
||||
return typeDefaut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur du canal
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return couleur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le canal est critique
|
||||
*
|
||||
* @return true si le canal a une importance élevée (4-5)
|
||||
*/
|
||||
public boolean isCritique() {
|
||||
return importance >= 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le canal est silencieux par défaut
|
||||
*
|
||||
* @return true si le canal n'émet ni son ni vibration
|
||||
*/
|
||||
public boolean isSilencieux() {
|
||||
return !sonActive && !vibrationActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le niveau d'importance Android
|
||||
*
|
||||
* @return Le niveau d'importance pour Android (IMPORTANCE_MIN à IMPORTANCE_MAX)
|
||||
*/
|
||||
public String getImportanceAndroid() {
|
||||
return switch (importance) {
|
||||
case 1 -> "IMPORTANCE_MIN";
|
||||
case 2 -> "IMPORTANCE_LOW";
|
||||
case 3 -> "IMPORTANCE_DEFAULT";
|
||||
case 4 -> "IMPORTANCE_HIGH";
|
||||
case 5 -> "IMPORTANCE_MAX";
|
||||
default -> "IMPORTANCE_DEFAULT";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la priorité iOS
|
||||
*
|
||||
* @return La priorité pour iOS (low ou high)
|
||||
*/
|
||||
public String getPrioriteIOS() {
|
||||
return importance >= 4 ? "high" : "low";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le son par défaut pour le canal
|
||||
*
|
||||
* @return Le nom du fichier son ou "default"
|
||||
*/
|
||||
public String getSonDefaut() {
|
||||
return switch (this) {
|
||||
case URGENT_CHANNEL -> "urgent_sound.mp3";
|
||||
case ERROR_CHANNEL -> "error_sound.mp3";
|
||||
case WARNING_CHANNEL -> "warning_sound.mp3";
|
||||
case IMPORTANT_CHANNEL -> "important_sound.mp3";
|
||||
case REMINDER_CHANNEL -> "reminder_sound.mp3";
|
||||
case SUCCESS_CHANNEL -> "success_sound.mp3";
|
||||
case CELEBRATION_CHANNEL -> "celebration_sound.mp3";
|
||||
default -> "default";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le pattern de vibration
|
||||
*
|
||||
* @return Le pattern de vibration en millisecondes
|
||||
*/
|
||||
public long[] getPatternVibration() {
|
||||
return switch (this) {
|
||||
case URGENT_CHANNEL -> new long[]{0, 500, 200, 500, 200, 500}; // Triple vibration
|
||||
case ERROR_CHANNEL -> new long[]{0, 1000, 500, 1000}; // Double vibration longue
|
||||
case WARNING_CHANNEL -> new long[]{0, 300, 200, 300}; // Double vibration courte
|
||||
case IMPORTANT_CHANNEL -> new long[]{0, 500, 100, 200}; // Vibration distinctive
|
||||
case REMINDER_CHANNEL -> new long[]{0, 200, 100, 200}; // Vibration douce
|
||||
default -> new long[]{0, 250}; // Vibration simple
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le canal peut être désactivé par l'utilisateur
|
||||
*
|
||||
* @return true si l'utilisateur peut désactiver ce canal
|
||||
*/
|
||||
public boolean peutEtreDesactive() {
|
||||
return this != URGENT_CHANNEL && this != ERROR_CHANNEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la durée de vie par défaut des notifications de ce canal
|
||||
*
|
||||
* @return La durée de vie en millisecondes
|
||||
*/
|
||||
public long getDureeVieMs() {
|
||||
return switch (this) {
|
||||
case URGENT_CHANNEL -> 3600000L; // 1 heure
|
||||
case ERROR_CHANNEL -> 86400000L; // 24 heures
|
||||
case WARNING_CHANNEL -> 172800000L; // 48 heures
|
||||
case IMPORTANT_CHANNEL -> 259200000L; // 72 heures
|
||||
case REMINDER_CHANNEL -> 86400000L; // 24 heures
|
||||
case SUCCESS_CHANNEL -> 172800000L; // 48 heures
|
||||
case CELEBRATION_CHANNEL -> 259200000L; // 72 heures
|
||||
default -> 604800000L; // 1 semaine
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve un canal par son ID
|
||||
*
|
||||
* @param id L'identifiant du canal
|
||||
* @return Le canal correspondant ou DEFAULT_CHANNEL si non trouvé
|
||||
*/
|
||||
public static CanalNotification parId(String id) {
|
||||
for (CanalNotification canal : values()) {
|
||||
if (canal.getId().equals(id)) {
|
||||
return canal;
|
||||
}
|
||||
}
|
||||
return DEFAULT_CHANNEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne tous les canaux critiques
|
||||
*
|
||||
* @return Un tableau des canaux critiques
|
||||
*/
|
||||
public static CanalNotification[] getCanauxCritiques() {
|
||||
return new CanalNotification[]{URGENT_CHANNEL, ERROR_CHANNEL, WARNING_CHANNEL, IMPORTANT_CHANNEL};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne tous les canaux par catégorie
|
||||
*
|
||||
* @return Un tableau des canaux catégoriels
|
||||
*/
|
||||
public static CanalNotification[] getCanauxCategories() {
|
||||
return new CanalNotification[]{EVENTS_CHANNEL, PAYMENTS_CHANNEL, SOLIDARITY_CHANNEL,
|
||||
MEMBERS_CHANNEL, ORGANIZATION_CHANNEL, SYSTEM_CHANNEL,
|
||||
MESSAGES_CHANNEL, LOCATION_CHANNEL};
|
||||
|
||||
// === CANAUX PAR PRIORITÉ ===
|
||||
URGENT_CHANNEL(
|
||||
"urgent",
|
||||
"Notifications urgentes",
|
||||
"Alertes critiques nécessitant une action immédiate",
|
||||
5,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
"urgent",
|
||||
"#F44336"),
|
||||
|
||||
ERROR_CHANNEL(
|
||||
"error",
|
||||
"Erreurs système",
|
||||
"Notifications d'erreurs et de problèmes techniques",
|
||||
4,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
"error",
|
||||
"#F44336"),
|
||||
|
||||
WARNING_CHANNEL(
|
||||
"warning",
|
||||
"Avertissements",
|
||||
"Notifications d'avertissement et d'attention",
|
||||
4,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
"warning",
|
||||
"#FF9800"),
|
||||
|
||||
IMPORTANT_CHANNEL(
|
||||
"important",
|
||||
"Notifications importantes",
|
||||
"Informations importantes à ne pas manquer",
|
||||
4,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
"important",
|
||||
"#FF5722"),
|
||||
|
||||
REMINDER_CHANNEL(
|
||||
"reminder",
|
||||
"Rappels",
|
||||
"Rappels d'événements, cotisations et échéances",
|
||||
3,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
"reminder",
|
||||
"#2196F3"),
|
||||
|
||||
SUCCESS_CHANNEL(
|
||||
"success",
|
||||
"Confirmations",
|
||||
"Notifications de succès et confirmations",
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
"success",
|
||||
"#4CAF50"),
|
||||
|
||||
CELEBRATION_CHANNEL(
|
||||
"celebration",
|
||||
"Célébrations",
|
||||
"Anniversaires, félicitations et événements joyeux",
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
"celebration",
|
||||
"#FF9800"),
|
||||
|
||||
DEFAULT_CHANNEL(
|
||||
"default",
|
||||
"Notifications générales",
|
||||
"Notifications d'information générale",
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
"info",
|
||||
"#2196F3"),
|
||||
|
||||
// === CANAUX PAR CATÉGORIE ===
|
||||
EVENTS_CHANNEL(
|
||||
"events",
|
||||
"Événements",
|
||||
"Notifications liées aux événements et activités",
|
||||
3,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
"event",
|
||||
"#2196F3"),
|
||||
|
||||
PAYMENTS_CHANNEL(
|
||||
"payments",
|
||||
"Paiements",
|
||||
"Notifications de cotisations et paiements",
|
||||
4,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
"payment",
|
||||
"#4CAF50"),
|
||||
|
||||
SOLIDARITY_CHANNEL(
|
||||
"solidarity",
|
||||
"Solidarité",
|
||||
"Notifications d'aide et de solidarité",
|
||||
3,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
"help",
|
||||
"#E91E63"),
|
||||
|
||||
MEMBERS_CHANNEL(
|
||||
"members",
|
||||
"Membres",
|
||||
"Notifications concernant les membres",
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
"people",
|
||||
"#2196F3"),
|
||||
|
||||
ORGANIZATION_CHANNEL(
|
||||
"organization",
|
||||
"Organisation",
|
||||
"Annonces et informations organisationnelles",
|
||||
3,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
"business",
|
||||
"#2196F3"),
|
||||
|
||||
SYSTEM_CHANNEL(
|
||||
"system",
|
||||
"Système",
|
||||
"Notifications système et maintenance",
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
"settings",
|
||||
"#607D8B"),
|
||||
|
||||
MESSAGES_CHANNEL(
|
||||
"messages",
|
||||
"Messages",
|
||||
"Messages privés et communications",
|
||||
3,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
"message",
|
||||
"#2196F3"),
|
||||
|
||||
LOCATION_CHANNEL(
|
||||
"location",
|
||||
"Géolocalisation",
|
||||
"Notifications basées sur la localisation",
|
||||
2,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
"location_on",
|
||||
"#4CAF50");
|
||||
|
||||
private final String id;
|
||||
private final String nom;
|
||||
private final String description;
|
||||
private final int importance;
|
||||
private final boolean sonActive;
|
||||
private final boolean vibrationActive;
|
||||
private final boolean lumiereLED;
|
||||
private final String typeDefaut;
|
||||
private final String couleur;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération CanalNotification
|
||||
*
|
||||
* @param id L'identifiant unique du canal
|
||||
* @param nom Le nom affiché du canal
|
||||
* @param description La description du canal
|
||||
* @param importance Le niveau d'importance (1=Min, 2=Low, 3=Default, 4=High, 5=Max)
|
||||
* @param sonActive true si le son est activé par défaut
|
||||
* @param vibrationActive true si la vibration est activée par défaut
|
||||
* @param lumiereLED true si la lumière LED est activée par défaut
|
||||
* @param typeDefaut Le type de notification par défaut pour ce canal
|
||||
* @param couleur La couleur hexadécimale du canal
|
||||
*/
|
||||
CanalNotification(
|
||||
String id,
|
||||
String nom,
|
||||
String description,
|
||||
int importance,
|
||||
boolean sonActive,
|
||||
boolean vibrationActive,
|
||||
boolean lumiereLED,
|
||||
String typeDefaut,
|
||||
String couleur) {
|
||||
this.id = id;
|
||||
this.nom = nom;
|
||||
this.description = description;
|
||||
this.importance = importance;
|
||||
this.sonActive = sonActive;
|
||||
this.vibrationActive = vibrationActive;
|
||||
this.lumiereLED = lumiereLED;
|
||||
this.typeDefaut = typeDefaut;
|
||||
this.couleur = couleur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'identifiant du canal
|
||||
*
|
||||
* @return L'ID unique du canal
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nom du canal
|
||||
*
|
||||
* @return Le nom affiché du canal
|
||||
*/
|
||||
public String getNom() {
|
||||
return nom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la description du canal
|
||||
*
|
||||
* @return La description détaillée du canal
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le niveau d'importance
|
||||
*
|
||||
* @return Le niveau d'importance (1-5)
|
||||
*/
|
||||
public int getImportance() {
|
||||
return importance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le son est activé par défaut
|
||||
*
|
||||
* @return true si le son est activé
|
||||
*/
|
||||
public boolean isSonActive() {
|
||||
return sonActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la vibration est activée par défaut
|
||||
*
|
||||
* @return true si la vibration est activée
|
||||
*/
|
||||
public boolean isVibrationActive() {
|
||||
return vibrationActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la lumière LED est activée par défaut
|
||||
*
|
||||
* @return true si la lumière LED est activée
|
||||
*/
|
||||
public boolean isLumiereLED() {
|
||||
return lumiereLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le type de notification par défaut
|
||||
*
|
||||
* @return Le type par défaut pour ce canal
|
||||
*/
|
||||
public String getTypeDefaut() {
|
||||
return typeDefaut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur du canal
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return couleur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le canal est critique
|
||||
*
|
||||
* @return true si le canal a une importance élevée (4-5)
|
||||
*/
|
||||
public boolean isCritique() {
|
||||
return importance >= 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le canal est silencieux par défaut
|
||||
*
|
||||
* @return true si le canal n'émet ni son ni vibration
|
||||
*/
|
||||
public boolean isSilencieux() {
|
||||
return !sonActive && !vibrationActive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le niveau d'importance Android
|
||||
*
|
||||
* @return Le niveau d'importance pour Android (IMPORTANCE_MIN à IMPORTANCE_MAX)
|
||||
*/
|
||||
public String getImportanceAndroid() {
|
||||
return switch (importance) {
|
||||
case 1 -> "IMPORTANCE_MIN";
|
||||
case 2 -> "IMPORTANCE_LOW";
|
||||
case 3 -> "IMPORTANCE_DEFAULT";
|
||||
case 4 -> "IMPORTANCE_HIGH";
|
||||
case 5 -> "IMPORTANCE_MAX";
|
||||
default -> "IMPORTANCE_DEFAULT";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la priorité iOS
|
||||
*
|
||||
* @return La priorité pour iOS (low ou high)
|
||||
*/
|
||||
public String getPrioriteIOS() {
|
||||
return importance >= 4 ? "high" : "low";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le son par défaut pour le canal
|
||||
*
|
||||
* @return Le nom du fichier son ou "default"
|
||||
*/
|
||||
public String getSonDefaut() {
|
||||
return switch (this) {
|
||||
case URGENT_CHANNEL -> "urgent_sound.mp3";
|
||||
case ERROR_CHANNEL -> "error_sound.mp3";
|
||||
case WARNING_CHANNEL -> "warning_sound.mp3";
|
||||
case IMPORTANT_CHANNEL -> "important_sound.mp3";
|
||||
case REMINDER_CHANNEL -> "reminder_sound.mp3";
|
||||
case SUCCESS_CHANNEL -> "success_sound.mp3";
|
||||
case CELEBRATION_CHANNEL -> "celebration_sound.mp3";
|
||||
default -> "default";
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le pattern de vibration
|
||||
*
|
||||
* @return Le pattern de vibration en millisecondes
|
||||
*/
|
||||
public long[] getPatternVibration() {
|
||||
return switch (this) {
|
||||
case URGENT_CHANNEL -> new long[] {0, 500, 200, 500, 200, 500}; // Triple vibration
|
||||
case ERROR_CHANNEL -> new long[] {0, 1000, 500, 1000}; // Double vibration longue
|
||||
case WARNING_CHANNEL -> new long[] {0, 300, 200, 300}; // Double vibration courte
|
||||
case IMPORTANT_CHANNEL -> new long[] {0, 500, 100, 200}; // Vibration distinctive
|
||||
case REMINDER_CHANNEL -> new long[] {0, 200, 100, 200}; // Vibration douce
|
||||
default -> new long[] {0, 250}; // Vibration simple
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le canal peut être désactivé par l'utilisateur
|
||||
*
|
||||
* @return true si l'utilisateur peut désactiver ce canal
|
||||
*/
|
||||
public boolean peutEtreDesactive() {
|
||||
return this != URGENT_CHANNEL && this != ERROR_CHANNEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la durée de vie par défaut des notifications de ce canal
|
||||
*
|
||||
* @return La durée de vie en millisecondes
|
||||
*/
|
||||
public long getDureeVieMs() {
|
||||
return switch (this) {
|
||||
case URGENT_CHANNEL -> 3600000L; // 1 heure
|
||||
case ERROR_CHANNEL -> 86400000L; // 24 heures
|
||||
case WARNING_CHANNEL -> 172800000L; // 48 heures
|
||||
case IMPORTANT_CHANNEL -> 259200000L; // 72 heures
|
||||
case REMINDER_CHANNEL -> 86400000L; // 24 heures
|
||||
case SUCCESS_CHANNEL -> 172800000L; // 48 heures
|
||||
case CELEBRATION_CHANNEL -> 259200000L; // 72 heures
|
||||
default -> 604800000L; // 1 semaine
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve un canal par son ID
|
||||
*
|
||||
* @param id L'identifiant du canal
|
||||
* @return Le canal correspondant ou DEFAULT_CHANNEL si non trouvé
|
||||
*/
|
||||
public static CanalNotification parId(String id) {
|
||||
for (CanalNotification canal : values()) {
|
||||
if (canal.getId().equals(id)) {
|
||||
return canal;
|
||||
}
|
||||
}
|
||||
return DEFAULT_CHANNEL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne tous les canaux critiques
|
||||
*
|
||||
* @return Un tableau des canaux critiques
|
||||
*/
|
||||
public static CanalNotification[] getCanauxCritiques() {
|
||||
return new CanalNotification[] {
|
||||
URGENT_CHANNEL, ERROR_CHANNEL, WARNING_CHANNEL, IMPORTANT_CHANNEL
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne tous les canaux par catégorie
|
||||
*
|
||||
* @return Un tableau des canaux catégoriels
|
||||
*/
|
||||
public static CanalNotification[] getCanauxCategories() {
|
||||
return new CanalNotification[] {
|
||||
EVENTS_CHANNEL,
|
||||
PAYMENTS_CHANNEL,
|
||||
SOLIDARITY_CHANNEL,
|
||||
MEMBERS_CHANNEL,
|
||||
ORGANIZATION_CHANNEL,
|
||||
SYSTEM_CHANNEL,
|
||||
MESSAGES_CHANNEL,
|
||||
LOCATION_CHANNEL
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,309 +2,458 @@ package dev.lions.unionflow.server.api.enums.notification;
|
||||
|
||||
/**
|
||||
* Énumération des statuts de notification dans UnionFlow
|
||||
*
|
||||
* Cette énumération définit les différents états qu'une notification peut avoir
|
||||
* tout au long de son cycle de vie, de la création à l'archivage.
|
||||
*
|
||||
*
|
||||
* <p>Cette énumération définit les différents états qu'une notification peut avoir tout au long de
|
||||
* son cycle de vie, de la création à l'archivage.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
public enum StatutNotification {
|
||||
|
||||
// === STATUTS DE CRÉATION ===
|
||||
BROUILLON("Brouillon", "draft", "La notification est en cours de création",
|
||||
"edit", "#9E9E9E", false, false),
|
||||
|
||||
PROGRAMMEE("Programmée", "scheduled", "La notification est programmée pour envoi ultérieur",
|
||||
"schedule", "#FF9800", false, false),
|
||||
|
||||
EN_ATTENTE("En attente", "pending", "La notification est en attente d'envoi",
|
||||
"hourglass_empty", "#FF9800", false, false),
|
||||
|
||||
// === STATUTS D'ENVOI ===
|
||||
EN_COURS_ENVOI("En cours d'envoi", "sending", "La notification est en cours d'envoi",
|
||||
"send", "#2196F3", false, false),
|
||||
|
||||
ENVOYEE("Envoyée", "sent", "La notification a été envoyée avec succès",
|
||||
"check_circle", "#4CAF50", true, false),
|
||||
|
||||
ECHEC_ENVOI("Échec d'envoi", "failed", "L'envoi de la notification a échoué",
|
||||
"error", "#F44336", true, true),
|
||||
|
||||
PARTIELLEMENT_ENVOYEE("Partiellement envoyée", "partial", "La notification a été envoyée à certains destinataires seulement",
|
||||
"warning", "#FF9800", true, true),
|
||||
|
||||
// === STATUTS DE RÉCEPTION ===
|
||||
RECUE("Reçue", "received", "La notification a été reçue par l'appareil",
|
||||
"download_done", "#4CAF50", true, false),
|
||||
|
||||
AFFICHEE("Affichée", "displayed", "La notification a été affichée à l'utilisateur",
|
||||
"visibility", "#2196F3", true, false),
|
||||
|
||||
OUVERTE("Ouverte", "opened", "L'utilisateur a ouvert la notification",
|
||||
"open_in_new", "#4CAF50", true, false),
|
||||
|
||||
IGNOREE("Ignorée", "ignored", "La notification a été ignorée par l'utilisateur",
|
||||
"visibility_off", "#9E9E9E", true, false),
|
||||
|
||||
// === STATUTS D'INTERACTION ===
|
||||
LUE("Lue", "read", "La notification a été lue par l'utilisateur",
|
||||
"mark_email_read", "#4CAF50", true, false),
|
||||
|
||||
NON_LUE("Non lue", "unread", "La notification n'a pas encore été lue",
|
||||
"mark_email_unread", "#FF9800", true, false),
|
||||
|
||||
MARQUEE_IMPORTANTE("Marquée importante", "starred", "L'utilisateur a marqué la notification comme importante",
|
||||
"star", "#FF9800", true, false),
|
||||
|
||||
ACTION_EXECUTEE("Action exécutée", "action_done", "L'utilisateur a exécuté l'action demandée",
|
||||
"task_alt", "#4CAF50", true, false),
|
||||
|
||||
// === STATUTS DE GESTION ===
|
||||
SUPPRIMEE("Supprimée", "deleted", "La notification a été supprimée par l'utilisateur",
|
||||
"delete", "#F44336", false, false),
|
||||
|
||||
ARCHIVEE("Archivée", "archived", "La notification a été archivée",
|
||||
"archive", "#9E9E9E", false, false),
|
||||
|
||||
EXPIREE("Expirée", "expired", "La notification a dépassé sa durée de vie",
|
||||
"schedule", "#9E9E9E", false, false),
|
||||
|
||||
ANNULEE("Annulée", "cancelled", "L'envoi de la notification a été annulé",
|
||||
"cancel", "#F44336", false, true),
|
||||
|
||||
// === STATUTS D'ERREUR ===
|
||||
ERREUR_TECHNIQUE("Erreur technique", "error", "Une erreur technique a empêché le traitement",
|
||||
"bug_report", "#F44336", false, true),
|
||||
|
||||
DESTINATAIRE_INVALIDE("Destinataire invalide", "invalid_recipient", "Le destinataire n'est pas valide",
|
||||
"person_off", "#F44336", false, true),
|
||||
|
||||
TOKEN_INVALIDE("Token invalide", "invalid_token", "Le token FCM du destinataire est invalide",
|
||||
"key_off", "#F44336", false, true),
|
||||
|
||||
QUOTA_DEPASSE("Quota dépassé", "quota_exceeded", "Le quota d'envoi a été dépassé",
|
||||
"block", "#F44336", false, true);
|
||||
|
||||
private final String libelle;
|
||||
private final String code;
|
||||
private final String description;
|
||||
private final String icone;
|
||||
private final String couleur;
|
||||
private final boolean visibleUtilisateur;
|
||||
private final boolean necessiteAttention;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération StatutNotification
|
||||
*
|
||||
* @param libelle Le libellé affiché à l'utilisateur
|
||||
* @param code Le code technique du statut
|
||||
* @param description La description détaillée du statut
|
||||
* @param icone L'icône Material Design
|
||||
* @param couleur La couleur hexadécimale
|
||||
* @param visibleUtilisateur true si visible à l'utilisateur final
|
||||
* @param necessiteAttention true si le statut nécessite une attention particulière
|
||||
*/
|
||||
StatutNotification(String libelle, String code, String description, String icone, String couleur,
|
||||
boolean visibleUtilisateur, boolean necessiteAttention) {
|
||||
this.libelle = libelle;
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
this.icone = icone;
|
||||
this.couleur = couleur;
|
||||
this.visibleUtilisateur = visibleUtilisateur;
|
||||
this.necessiteAttention = necessiteAttention;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé du statut
|
||||
*
|
||||
* @return Le libellé affiché à l'utilisateur
|
||||
*/
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le code technique du statut
|
||||
*
|
||||
* @return Le code technique
|
||||
*/
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la description du statut
|
||||
*
|
||||
* @return La description détaillée
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône du statut
|
||||
*
|
||||
* @return L'icône Material Design
|
||||
*/
|
||||
public String getIcone() {
|
||||
return icone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur du statut
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return couleur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut est visible à l'utilisateur final
|
||||
*
|
||||
* @return true si visible à l'utilisateur
|
||||
*/
|
||||
public boolean isVisibleUtilisateur() {
|
||||
return visibleUtilisateur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut nécessite une attention particulière
|
||||
*
|
||||
* @return true si le statut nécessite attention
|
||||
*/
|
||||
public boolean isNecessiteAttention() {
|
||||
return necessiteAttention;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut indique un succès
|
||||
*
|
||||
* @return true si le statut indique un succès
|
||||
*/
|
||||
public boolean isSucces() {
|
||||
return this == ENVOYEE || this == RECUE || this == AFFICHEE ||
|
||||
this == OUVERTE || this == LUE || this == ACTION_EXECUTEE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut indique une erreur
|
||||
*
|
||||
* @return true si le statut indique une erreur
|
||||
*/
|
||||
public boolean isErreur() {
|
||||
return this == ECHEC_ENVOI || this == ERREUR_TECHNIQUE ||
|
||||
this == DESTINATAIRE_INVALIDE || this == TOKEN_INVALIDE || this == QUOTA_DEPASSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut indique un état en cours
|
||||
*
|
||||
* @return true si le statut indique un traitement en cours
|
||||
*/
|
||||
public boolean isEnCours() {
|
||||
return this == PROGRAMMEE || this == EN_ATTENTE || this == EN_COURS_ENVOI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut indique un état final
|
||||
*
|
||||
* @return true si le statut est final (pas de transition possible)
|
||||
*/
|
||||
public boolean isFinal() {
|
||||
return this == SUPPRIMEE || this == ARCHIVEE || this == EXPIREE ||
|
||||
this == ANNULEE || isErreur();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut permet la modification
|
||||
*
|
||||
* @return true si la notification peut encore être modifiée
|
||||
*/
|
||||
public boolean permetModification() {
|
||||
return this == BROUILLON || this == PROGRAMMEE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut permet l'annulation
|
||||
*
|
||||
* @return true si la notification peut être annulée
|
||||
*/
|
||||
public boolean permetAnnulation() {
|
||||
return this == PROGRAMMEE || this == EN_ATTENTE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la priorité d'affichage du statut
|
||||
*
|
||||
* @return La priorité (1=haute, 5=basse)
|
||||
*/
|
||||
public int getPrioriteAffichage() {
|
||||
if (isErreur()) return 1;
|
||||
if (necessiteAttention) return 2;
|
||||
if (isEnCours()) return 3;
|
||||
if (isSucces()) return 4;
|
||||
return 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les statuts suivants possibles
|
||||
*
|
||||
* @return Un tableau des statuts de transition possibles
|
||||
*/
|
||||
public StatutNotification[] getStatutsSuivantsPossibles() {
|
||||
return switch (this) {
|
||||
case BROUILLON -> new StatutNotification[]{PROGRAMMEE, EN_ATTENTE, ANNULEE};
|
||||
case PROGRAMMEE -> new StatutNotification[]{EN_ATTENTE, EN_COURS_ENVOI, ANNULEE};
|
||||
case EN_ATTENTE -> new StatutNotification[]{EN_COURS_ENVOI, ECHEC_ENVOI, ANNULEE};
|
||||
case EN_COURS_ENVOI -> new StatutNotification[]{ENVOYEE, PARTIELLEMENT_ENVOYEE, ECHEC_ENVOI};
|
||||
case ENVOYEE -> new StatutNotification[]{RECUE, ECHEC_ENVOI};
|
||||
case RECUE -> new StatutNotification[]{AFFICHEE, IGNOREE};
|
||||
case AFFICHEE -> new StatutNotification[]{OUVERTE, LUE, NON_LUE, IGNOREE};
|
||||
case OUVERTE -> new StatutNotification[]{LUE, ACTION_EXECUTEE, MARQUEE_IMPORTANTE};
|
||||
case NON_LUE -> new StatutNotification[]{LUE, OUVERTE, SUPPRIMEE, ARCHIVEE};
|
||||
case LUE -> new StatutNotification[]{ACTION_EXECUTEE, MARQUEE_IMPORTANTE, SUPPRIMEE, ARCHIVEE};
|
||||
default -> new StatutNotification[]{};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve un statut par son code
|
||||
*
|
||||
* @param code Le code du statut
|
||||
* @return Le statut correspondant ou null si non trouvé
|
||||
*/
|
||||
public static StatutNotification parCode(String code) {
|
||||
for (StatutNotification statut : values()) {
|
||||
if (statut.getCode().equals(code)) {
|
||||
return statut;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne tous les statuts visibles à l'utilisateur
|
||||
*
|
||||
* @return Un tableau des statuts visibles
|
||||
*/
|
||||
public static StatutNotification[] getStatutsVisibles() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutNotification::isVisibleUtilisateur)
|
||||
.toArray(StatutNotification[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne tous les statuts d'erreur
|
||||
*
|
||||
* @return Un tableau des statuts d'erreur
|
||||
*/
|
||||
public static StatutNotification[] getStatutsErreur() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutNotification::isErreur)
|
||||
.toArray(StatutNotification[]::new);
|
||||
|
||||
// === STATUTS DE CRÉATION ===
|
||||
BROUILLON(
|
||||
"Brouillon",
|
||||
"draft",
|
||||
"La notification est en cours de création",
|
||||
"edit",
|
||||
"#9E9E9E",
|
||||
false,
|
||||
false),
|
||||
|
||||
PROGRAMMEE(
|
||||
"Programmée",
|
||||
"scheduled",
|
||||
"La notification est programmée pour envoi ultérieur",
|
||||
"schedule",
|
||||
"#FF9800",
|
||||
false,
|
||||
false),
|
||||
|
||||
EN_ATTENTE(
|
||||
"En attente",
|
||||
"pending",
|
||||
"La notification est en attente d'envoi",
|
||||
"hourglass_empty",
|
||||
"#FF9800",
|
||||
false,
|
||||
false),
|
||||
|
||||
// === STATUTS D'ENVOI ===
|
||||
EN_COURS_ENVOI(
|
||||
"En cours d'envoi",
|
||||
"sending",
|
||||
"La notification est en cours d'envoi",
|
||||
"send",
|
||||
"#2196F3",
|
||||
false,
|
||||
false),
|
||||
|
||||
ENVOYEE(
|
||||
"Envoyée",
|
||||
"sent",
|
||||
"La notification a été envoyée avec succès",
|
||||
"check_circle",
|
||||
"#4CAF50",
|
||||
true,
|
||||
false),
|
||||
|
||||
ECHEC_ENVOI(
|
||||
"Échec d'envoi",
|
||||
"failed",
|
||||
"L'envoi de la notification a échoué",
|
||||
"error",
|
||||
"#F44336",
|
||||
true,
|
||||
true),
|
||||
|
||||
PARTIELLEMENT_ENVOYEE(
|
||||
"Partiellement envoyée",
|
||||
"partial",
|
||||
"La notification a été envoyée à certains destinataires seulement",
|
||||
"warning",
|
||||
"#FF9800",
|
||||
true,
|
||||
true),
|
||||
|
||||
// === STATUTS DE RÉCEPTION ===
|
||||
RECUE(
|
||||
"Reçue",
|
||||
"received",
|
||||
"La notification a été reçue par l'appareil",
|
||||
"download_done",
|
||||
"#4CAF50",
|
||||
true,
|
||||
false),
|
||||
|
||||
AFFICHEE(
|
||||
"Affichée",
|
||||
"displayed",
|
||||
"La notification a été affichée à l'utilisateur",
|
||||
"visibility",
|
||||
"#2196F3",
|
||||
true,
|
||||
false),
|
||||
|
||||
OUVERTE(
|
||||
"Ouverte",
|
||||
"opened",
|
||||
"L'utilisateur a ouvert la notification",
|
||||
"open_in_new",
|
||||
"#4CAF50",
|
||||
true,
|
||||
false),
|
||||
|
||||
IGNOREE(
|
||||
"Ignorée",
|
||||
"ignored",
|
||||
"La notification a été ignorée par l'utilisateur",
|
||||
"visibility_off",
|
||||
"#9E9E9E",
|
||||
true,
|
||||
false),
|
||||
|
||||
// === STATUTS D'INTERACTION ===
|
||||
LUE(
|
||||
"Lue",
|
||||
"read",
|
||||
"La notification a été lue par l'utilisateur",
|
||||
"mark_email_read",
|
||||
"#4CAF50",
|
||||
true,
|
||||
false),
|
||||
|
||||
NON_LUE(
|
||||
"Non lue",
|
||||
"unread",
|
||||
"La notification n'a pas encore été lue",
|
||||
"mark_email_unread",
|
||||
"#FF9800",
|
||||
true,
|
||||
false),
|
||||
|
||||
MARQUEE_IMPORTANTE(
|
||||
"Marquée importante",
|
||||
"starred",
|
||||
"L'utilisateur a marqué la notification comme importante",
|
||||
"star",
|
||||
"#FF9800",
|
||||
true,
|
||||
false),
|
||||
|
||||
ACTION_EXECUTEE(
|
||||
"Action exécutée",
|
||||
"action_done",
|
||||
"L'utilisateur a exécuté l'action demandée",
|
||||
"task_alt",
|
||||
"#4CAF50",
|
||||
true,
|
||||
false),
|
||||
|
||||
// === STATUTS DE GESTION ===
|
||||
SUPPRIMEE(
|
||||
"Supprimée",
|
||||
"deleted",
|
||||
"La notification a été supprimée par l'utilisateur",
|
||||
"delete",
|
||||
"#F44336",
|
||||
false,
|
||||
false),
|
||||
|
||||
ARCHIVEE(
|
||||
"Archivée", "archived", "La notification a été archivée", "archive", "#9E9E9E", false, false),
|
||||
|
||||
EXPIREE(
|
||||
"Expirée",
|
||||
"expired",
|
||||
"La notification a dépassé sa durée de vie",
|
||||
"schedule",
|
||||
"#9E9E9E",
|
||||
false,
|
||||
false),
|
||||
|
||||
ANNULEE(
|
||||
"Annulée",
|
||||
"cancelled",
|
||||
"L'envoi de la notification a été annulé",
|
||||
"cancel",
|
||||
"#F44336",
|
||||
false,
|
||||
true),
|
||||
|
||||
// === STATUTS D'ERREUR ===
|
||||
ERREUR_TECHNIQUE(
|
||||
"Erreur technique",
|
||||
"error",
|
||||
"Une erreur technique a empêché le traitement",
|
||||
"bug_report",
|
||||
"#F44336",
|
||||
false,
|
||||
true),
|
||||
|
||||
DESTINATAIRE_INVALIDE(
|
||||
"Destinataire invalide",
|
||||
"invalid_recipient",
|
||||
"Le destinataire n'est pas valide",
|
||||
"person_off",
|
||||
"#F44336",
|
||||
false,
|
||||
true),
|
||||
|
||||
TOKEN_INVALIDE(
|
||||
"Token invalide",
|
||||
"invalid_token",
|
||||
"Le token FCM du destinataire est invalide",
|
||||
"key_off",
|
||||
"#F44336",
|
||||
false,
|
||||
true),
|
||||
|
||||
QUOTA_DEPASSE(
|
||||
"Quota dépassé",
|
||||
"quota_exceeded",
|
||||
"Le quota d'envoi a été dépassé",
|
||||
"block",
|
||||
"#F44336",
|
||||
false,
|
||||
true);
|
||||
|
||||
private final String libelle;
|
||||
private final String code;
|
||||
private final String description;
|
||||
private final String icone;
|
||||
private final String couleur;
|
||||
private final boolean visibleUtilisateur;
|
||||
private final boolean necessiteAttention;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération StatutNotification
|
||||
*
|
||||
* @param libelle Le libellé affiché à l'utilisateur
|
||||
* @param code Le code technique du statut
|
||||
* @param description La description détaillée du statut
|
||||
* @param icone L'icône Material Design
|
||||
* @param couleur La couleur hexadécimale
|
||||
* @param visibleUtilisateur true si visible à l'utilisateur final
|
||||
* @param necessiteAttention true si le statut nécessite une attention particulière
|
||||
*/
|
||||
StatutNotification(
|
||||
String libelle,
|
||||
String code,
|
||||
String description,
|
||||
String icone,
|
||||
String couleur,
|
||||
boolean visibleUtilisateur,
|
||||
boolean necessiteAttention) {
|
||||
this.libelle = libelle;
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
this.icone = icone;
|
||||
this.couleur = couleur;
|
||||
this.visibleUtilisateur = visibleUtilisateur;
|
||||
this.necessiteAttention = necessiteAttention;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé du statut
|
||||
*
|
||||
* @return Le libellé affiché à l'utilisateur
|
||||
*/
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le code technique du statut
|
||||
*
|
||||
* @return Le code technique
|
||||
*/
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la description du statut
|
||||
*
|
||||
* @return La description détaillée
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône du statut
|
||||
*
|
||||
* @return L'icône Material Design
|
||||
*/
|
||||
public String getIcone() {
|
||||
return icone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur du statut
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return couleur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut est visible à l'utilisateur final
|
||||
*
|
||||
* @return true si visible à l'utilisateur
|
||||
*/
|
||||
public boolean isVisibleUtilisateur() {
|
||||
return visibleUtilisateur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut nécessite une attention particulière
|
||||
*
|
||||
* @return true si le statut nécessite attention
|
||||
*/
|
||||
public boolean isNecessiteAttention() {
|
||||
return necessiteAttention;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut indique un succès
|
||||
*
|
||||
* @return true si le statut indique un succès
|
||||
*/
|
||||
public boolean isSucces() {
|
||||
return this == ENVOYEE
|
||||
|| this == RECUE
|
||||
|| this == AFFICHEE
|
||||
|| this == OUVERTE
|
||||
|| this == LUE
|
||||
|| this == ACTION_EXECUTEE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut indique une erreur
|
||||
*
|
||||
* @return true si le statut indique une erreur
|
||||
*/
|
||||
public boolean isErreur() {
|
||||
return this == ECHEC_ENVOI
|
||||
|| this == ERREUR_TECHNIQUE
|
||||
|| this == DESTINATAIRE_INVALIDE
|
||||
|| this == TOKEN_INVALIDE
|
||||
|| this == QUOTA_DEPASSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut indique un état en cours
|
||||
*
|
||||
* @return true si le statut indique un traitement en cours
|
||||
*/
|
||||
public boolean isEnCours() {
|
||||
return this == PROGRAMMEE || this == EN_ATTENTE || this == EN_COURS_ENVOI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut indique un état final
|
||||
*
|
||||
* @return true si le statut est final (pas de transition possible)
|
||||
*/
|
||||
public boolean isFinal() {
|
||||
return this == SUPPRIMEE
|
||||
|| this == ARCHIVEE
|
||||
|| this == EXPIREE
|
||||
|| this == ANNULEE
|
||||
|| isErreur();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut permet la modification
|
||||
*
|
||||
* @return true si la notification peut encore être modifiée
|
||||
*/
|
||||
public boolean permetModification() {
|
||||
return this == BROUILLON || this == PROGRAMMEE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut permet l'annulation
|
||||
*
|
||||
* @return true si la notification peut être annulée
|
||||
*/
|
||||
public boolean permetAnnulation() {
|
||||
return this == PROGRAMMEE || this == EN_ATTENTE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la priorité d'affichage du statut
|
||||
*
|
||||
* @return La priorité (1=haute, 5=basse)
|
||||
*/
|
||||
public int getPrioriteAffichage() {
|
||||
if (isErreur()) return 1;
|
||||
if (necessiteAttention) return 2;
|
||||
if (isEnCours()) return 3;
|
||||
if (isSucces()) return 4;
|
||||
return 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les statuts suivants possibles
|
||||
*
|
||||
* @return Un tableau des statuts de transition possibles
|
||||
*/
|
||||
public StatutNotification[] getStatutsSuivantsPossibles() {
|
||||
return switch (this) {
|
||||
case BROUILLON -> new StatutNotification[] {PROGRAMMEE, EN_ATTENTE, ANNULEE};
|
||||
case PROGRAMMEE -> new StatutNotification[] {EN_ATTENTE, EN_COURS_ENVOI, ANNULEE};
|
||||
case EN_ATTENTE -> new StatutNotification[] {EN_COURS_ENVOI, ECHEC_ENVOI, ANNULEE};
|
||||
case EN_COURS_ENVOI -> new StatutNotification[] {ENVOYEE, PARTIELLEMENT_ENVOYEE, ECHEC_ENVOI};
|
||||
case ENVOYEE -> new StatutNotification[] {RECUE, ECHEC_ENVOI};
|
||||
case RECUE -> new StatutNotification[] {AFFICHEE, IGNOREE};
|
||||
case AFFICHEE -> new StatutNotification[] {OUVERTE, LUE, NON_LUE, IGNOREE};
|
||||
case OUVERTE -> new StatutNotification[] {LUE, ACTION_EXECUTEE, MARQUEE_IMPORTANTE};
|
||||
case NON_LUE -> new StatutNotification[] {LUE, OUVERTE, SUPPRIMEE, ARCHIVEE};
|
||||
case LUE ->
|
||||
new StatutNotification[] {ACTION_EXECUTEE, MARQUEE_IMPORTANTE, SUPPRIMEE, ARCHIVEE};
|
||||
default -> new StatutNotification[] {};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve un statut par son code
|
||||
*
|
||||
* @param code Le code du statut
|
||||
* @return Le statut correspondant ou null si non trouvé
|
||||
*/
|
||||
public static StatutNotification parCode(String code) {
|
||||
for (StatutNotification statut : values()) {
|
||||
if (statut.getCode().equals(code)) {
|
||||
return statut;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne tous les statuts visibles à l'utilisateur
|
||||
*
|
||||
* @return Un tableau des statuts visibles
|
||||
*/
|
||||
public static StatutNotification[] getStatutsVisibles() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutNotification::isVisibleUtilisateur)
|
||||
.toArray(StatutNotification[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne tous les statuts d'erreur
|
||||
*
|
||||
* @return Un tableau des statuts d'erreur
|
||||
*/
|
||||
public static StatutNotification[] getStatutsErreur() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutNotification::isErreur)
|
||||
.toArray(StatutNotification[]::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,260 +2,289 @@ package dev.lions.unionflow.server.api.enums.notification;
|
||||
|
||||
/**
|
||||
* Énumération des types de notifications disponibles dans UnionFlow
|
||||
*
|
||||
* Cette énumération définit les différents types de notifications qui peuvent être
|
||||
* envoyées aux utilisateurs de l'application UnionFlow.
|
||||
*
|
||||
*
|
||||
* <p>Cette énumération définit les différents types de notifications qui peuvent être envoyées aux
|
||||
* utilisateurs de l'application UnionFlow.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
public enum TypeNotification {
|
||||
|
||||
// === NOTIFICATIONS ÉVÉNEMENTS ===
|
||||
NOUVEL_EVENEMENT("Nouvel événement", "evenements", "info", "event", "#FF9800", true, true),
|
||||
RAPPEL_EVENEMENT("Rappel d'événement", "evenements", "reminder", "schedule", "#2196F3", true, true),
|
||||
EVENEMENT_ANNULE("Événement annulé", "evenements", "warning", "event_busy", "#F44336", true, true),
|
||||
EVENEMENT_MODIFIE("Événement modifié", "evenements", "info", "edit", "#FF9800", true, false),
|
||||
INSCRIPTION_CONFIRMEE("Inscription confirmée", "evenements", "success", "check_circle", "#4CAF50", true, false),
|
||||
INSCRIPTION_REFUSEE("Inscription refusée", "evenements", "error", "cancel", "#F44336", true, false),
|
||||
LISTE_ATTENTE("Mis en liste d'attente", "evenements", "info", "hourglass_empty", "#FF9800", true, false),
|
||||
|
||||
// === NOTIFICATIONS COTISATIONS ===
|
||||
COTISATION_DUE("Cotisation due", "cotisations", "reminder", "payment", "#FF5722", true, true),
|
||||
COTISATION_PAYEE("Cotisation payée", "cotisations", "success", "paid", "#4CAF50", true, false),
|
||||
COTISATION_RETARD("Cotisation en retard", "cotisations", "warning", "schedule", "#F44336", true, true),
|
||||
RAPPEL_COTISATION("Rappel de cotisation", "cotisations", "reminder", "notifications", "#FF9800", true, true),
|
||||
PAIEMENT_CONFIRME("Paiement confirmé", "cotisations", "success", "check_circle", "#4CAF50", true, false),
|
||||
PAIEMENT_ECHOUE("Paiement échoué", "cotisations", "error", "error", "#F44336", true, true),
|
||||
|
||||
// === NOTIFICATIONS SOLIDARITÉ ===
|
||||
NOUVELLE_DEMANDE_AIDE("Nouvelle demande d'aide", "solidarite", "info", "help", "#E91E63", false, true),
|
||||
DEMANDE_AIDE_APPROUVEE("Demande d'aide approuvée", "solidarite", "success", "thumb_up", "#4CAF50", true, false),
|
||||
DEMANDE_AIDE_REFUSEE("Demande d'aide refusée", "solidarite", "error", "thumb_down", "#F44336", true, false),
|
||||
AIDE_DISPONIBLE("Aide disponible", "solidarite", "info", "volunteer_activism", "#E91E63", true, false),
|
||||
APPEL_SOLIDARITE("Appel à la solidarité", "solidarite", "urgent", "campaign", "#E91E63", true, true),
|
||||
|
||||
// === NOTIFICATIONS MEMBRES ===
|
||||
NOUVEAU_MEMBRE("Nouveau membre", "membres", "info", "person_add", "#2196F3", false, false),
|
||||
ANNIVERSAIRE_MEMBRE("Anniversaire de membre", "membres", "celebration", "cake", "#FF9800", true, false),
|
||||
MEMBRE_INACTIF("Membre inactif", "membres", "warning", "person_off", "#FF5722", false, false),
|
||||
REACTIVATION_MEMBRE("Réactivation de membre", "membres", "success", "person", "#4CAF50", false, false),
|
||||
|
||||
// === NOTIFICATIONS ORGANISATION ===
|
||||
ANNONCE_GENERALE("Annonce générale", "organisation", "info", "campaign", "#2196F3", true, true),
|
||||
REUNION_PROGRAMMEE("Réunion programmée", "organisation", "info", "groups", "#2196F3", true, true),
|
||||
CHANGEMENT_REGLEMENT("Changement de règlement", "organisation", "important", "gavel", "#FF5722", true, true),
|
||||
ELECTION_OUVERTE("Élection ouverte", "organisation", "info", "how_to_vote", "#2196F3", true, true),
|
||||
RESULTAT_ELECTION("Résultat d'élection", "organisation", "info", "poll", "#4CAF50", true, false),
|
||||
|
||||
// === NOTIFICATIONS SYSTÈME ===
|
||||
MISE_A_JOUR_APP("Mise à jour disponible", "systeme", "info", "system_update", "#2196F3", true, false),
|
||||
MAINTENANCE_PROGRAMMEE("Maintenance programmée", "systeme", "warning", "build", "#FF9800", true, true),
|
||||
PROBLEME_TECHNIQUE("Problème technique", "systeme", "error", "error", "#F44336", true, true),
|
||||
SAUVEGARDE_REUSSIE("Sauvegarde réussie", "systeme", "success", "backup", "#4CAF50", false, false),
|
||||
|
||||
// === NOTIFICATIONS PERSONNALISÉES ===
|
||||
MESSAGE_PRIVE("Message privé", "messages", "info", "mail", "#2196F3", true, false),
|
||||
MENTION("Mention", "messages", "info", "alternate_email", "#FF9800", true, false),
|
||||
COMMENTAIRE("Nouveau commentaire", "messages", "info", "comment", "#2196F3", true, false),
|
||||
|
||||
// === NOTIFICATIONS GÉOLOCALISÉES ===
|
||||
EVENEMENT_PROXIMITE("Événement à proximité", "geolocalisation", "info", "location_on", "#4CAF50", true, false),
|
||||
MEMBRE_PROXIMITE("Membre à proximité", "geolocalisation", "info", "people", "#2196F3", true, false),
|
||||
URGENCE_LOCALE("Urgence locale", "geolocalisation", "urgent", "warning", "#F44336", true, true);
|
||||
|
||||
private final String libelle;
|
||||
private final String categorie;
|
||||
private final String priorite;
|
||||
private final String icone;
|
||||
private final String couleur;
|
||||
private final boolean visibleUtilisateur;
|
||||
private final boolean activeeParDefaut;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération TypeNotification
|
||||
*
|
||||
* @param libelle Le libellé affiché à l'utilisateur
|
||||
* @param categorie La catégorie de la notification
|
||||
* @param priorite Le niveau de priorité (info, reminder, warning, error, success, urgent, important, celebration)
|
||||
* @param icone L'icône Material Design
|
||||
* @param couleur La couleur hexadécimale
|
||||
* @param visibleUtilisateur true si visible dans les préférences utilisateur
|
||||
* @param activeeParDefaut true si activée par défaut
|
||||
*/
|
||||
TypeNotification(String libelle, String categorie, String priorite, String icone, String couleur,
|
||||
boolean visibleUtilisateur, boolean activeeParDefaut) {
|
||||
this.libelle = libelle;
|
||||
this.categorie = categorie;
|
||||
this.priorite = priorite;
|
||||
this.icone = icone;
|
||||
this.couleur = couleur;
|
||||
this.visibleUtilisateur = visibleUtilisateur;
|
||||
this.activeeParDefaut = activeeParDefaut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé de la notification
|
||||
*
|
||||
* @return Le libellé affiché à l'utilisateur
|
||||
*/
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la catégorie de la notification
|
||||
*
|
||||
* @return La catégorie (evenements, cotisations, solidarite, etc.)
|
||||
*/
|
||||
public String getCategorie() {
|
||||
return categorie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la priorité de la notification
|
||||
*
|
||||
* @return Le niveau de priorité
|
||||
*/
|
||||
public String getPriorite() {
|
||||
return priorite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône de la notification
|
||||
*
|
||||
* @return L'icône Material Design
|
||||
*/
|
||||
public String getIcone() {
|
||||
return icone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur de la notification
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return couleur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification est visible dans les préférences utilisateur
|
||||
*
|
||||
* @return true si visible dans les préférences
|
||||
*/
|
||||
public boolean isVisibleUtilisateur() {
|
||||
return visibleUtilisateur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification est activée par défaut
|
||||
*
|
||||
* @return true si activée par défaut
|
||||
*/
|
||||
public boolean isActiveeParDefaut() {
|
||||
return activeeParDefaut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification est critique (urgent ou error)
|
||||
*
|
||||
* @return true si la notification est critique
|
||||
*/
|
||||
public boolean isCritique() {
|
||||
return "urgent".equals(priorite) || "error".equals(priorite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification est un rappel
|
||||
*
|
||||
* @return true si c'est un rappel
|
||||
*/
|
||||
public boolean isRappel() {
|
||||
return "reminder".equals(priorite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification est positive (success ou celebration)
|
||||
*
|
||||
* @return true si la notification est positive
|
||||
*/
|
||||
public boolean isPositive() {
|
||||
return "success".equals(priorite) || "celebration".equals(priorite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le niveau de priorité numérique pour le tri
|
||||
*
|
||||
* @return Niveau de priorité (1=urgent, 2=error, 3=warning, 4=important, 5=reminder, 6=info, 7=success, 8=celebration)
|
||||
*/
|
||||
public int getNiveauPriorite() {
|
||||
return switch (priorite) {
|
||||
case "urgent" -> 1;
|
||||
case "error" -> 2;
|
||||
case "warning" -> 3;
|
||||
case "important" -> 4;
|
||||
case "reminder" -> 5;
|
||||
case "info" -> 6;
|
||||
case "success" -> 7;
|
||||
case "celebration" -> 8;
|
||||
default -> 6;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le délai d'expiration par défaut en heures
|
||||
*
|
||||
* @return Délai d'expiration en heures
|
||||
*/
|
||||
public int getDelaiExpirationHeures() {
|
||||
return switch (priorite) {
|
||||
case "urgent" -> 1; // 1 heure
|
||||
case "error" -> 24; // 24 heures
|
||||
case "warning" -> 48; // 48 heures
|
||||
case "important" -> 72; // 72 heures
|
||||
case "reminder" -> 24; // 24 heures
|
||||
case "info" -> 168; // 1 semaine
|
||||
case "success" -> 48; // 48 heures
|
||||
case "celebration" -> 72; // 72 heures
|
||||
default -> 168;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification doit vibrer
|
||||
*
|
||||
* @return true si la notification doit faire vibrer l'appareil
|
||||
*/
|
||||
public boolean doitVibrer() {
|
||||
return isCritique() || isRappel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification doit émettre un son
|
||||
*
|
||||
* @return true si la notification doit émettre un son
|
||||
*/
|
||||
public boolean doitEmettreSon() {
|
||||
return isCritique() || isRappel() || "important".equals(priorite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le canal de notification Android approprié
|
||||
*
|
||||
* @return L'ID du canal de notification
|
||||
*/
|
||||
public String getCanalNotification() {
|
||||
return switch (priorite) {
|
||||
case "urgent" -> "URGENT_CHANNEL";
|
||||
case "error" -> "ERROR_CHANNEL";
|
||||
case "warning" -> "WARNING_CHANNEL";
|
||||
case "important" -> "IMPORTANT_CHANNEL";
|
||||
case "reminder" -> "REMINDER_CHANNEL";
|
||||
case "success" -> "SUCCESS_CHANNEL";
|
||||
case "celebration" -> "CELEBRATION_CHANNEL";
|
||||
default -> "DEFAULT_CHANNEL";
|
||||
};
|
||||
}
|
||||
|
||||
// === NOTIFICATIONS ÉVÉNEMENTS ===
|
||||
NOUVEL_EVENEMENT("Nouvel événement", "evenements", "info", "event", "#FF9800", true, true),
|
||||
RAPPEL_EVENEMENT(
|
||||
"Rappel d'événement", "evenements", "reminder", "schedule", "#2196F3", true, true),
|
||||
EVENEMENT_ANNULE(
|
||||
"Événement annulé", "evenements", "warning", "event_busy", "#F44336", true, true),
|
||||
EVENEMENT_MODIFIE("Événement modifié", "evenements", "info", "edit", "#FF9800", true, false),
|
||||
INSCRIPTION_CONFIRMEE(
|
||||
"Inscription confirmée", "evenements", "success", "check_circle", "#4CAF50", true, false),
|
||||
INSCRIPTION_REFUSEE(
|
||||
"Inscription refusée", "evenements", "error", "cancel", "#F44336", true, false),
|
||||
LISTE_ATTENTE(
|
||||
"Mis en liste d'attente", "evenements", "info", "hourglass_empty", "#FF9800", true, false),
|
||||
|
||||
// === NOTIFICATIONS COTISATIONS ===
|
||||
COTISATION_DUE("Cotisation due", "cotisations", "reminder", "payment", "#FF5722", true, true),
|
||||
COTISATION_PAYEE("Cotisation payée", "cotisations", "success", "paid", "#4CAF50", true, false),
|
||||
COTISATION_RETARD(
|
||||
"Cotisation en retard", "cotisations", "warning", "schedule", "#F44336", true, true),
|
||||
RAPPEL_COTISATION(
|
||||
"Rappel de cotisation", "cotisations", "reminder", "notifications", "#FF9800", true, true),
|
||||
PAIEMENT_CONFIRME(
|
||||
"Paiement confirmé", "cotisations", "success", "check_circle", "#4CAF50", true, false),
|
||||
PAIEMENT_ECHOUE("Paiement échoué", "cotisations", "error", "error", "#F44336", true, true),
|
||||
|
||||
// === NOTIFICATIONS SOLIDARITÉ ===
|
||||
NOUVELLE_DEMANDE_AIDE(
|
||||
"Nouvelle demande d'aide", "solidarite", "info", "help", "#E91E63", false, true),
|
||||
DEMANDE_AIDE_APPROUVEE(
|
||||
"Demande d'aide approuvée", "solidarite", "success", "thumb_up", "#4CAF50", true, false),
|
||||
DEMANDE_AIDE_REFUSEE(
|
||||
"Demande d'aide refusée", "solidarite", "error", "thumb_down", "#F44336", true, false),
|
||||
AIDE_DISPONIBLE(
|
||||
"Aide disponible", "solidarite", "info", "volunteer_activism", "#E91E63", true, false),
|
||||
APPEL_SOLIDARITE(
|
||||
"Appel à la solidarité", "solidarite", "urgent", "campaign", "#E91E63", true, true),
|
||||
|
||||
// === NOTIFICATIONS MEMBRES ===
|
||||
NOUVEAU_MEMBRE("Nouveau membre", "membres", "info", "person_add", "#2196F3", false, false),
|
||||
ANNIVERSAIRE_MEMBRE(
|
||||
"Anniversaire de membre", "membres", "celebration", "cake", "#FF9800", true, false),
|
||||
MEMBRE_INACTIF("Membre inactif", "membres", "warning", "person_off", "#FF5722", false, false),
|
||||
REACTIVATION_MEMBRE(
|
||||
"Réactivation de membre", "membres", "success", "person", "#4CAF50", false, false),
|
||||
|
||||
// === NOTIFICATIONS ORGANISATION ===
|
||||
ANNONCE_GENERALE("Annonce générale", "organisation", "info", "campaign", "#2196F3", true, true),
|
||||
REUNION_PROGRAMMEE("Réunion programmée", "organisation", "info", "groups", "#2196F3", true, true),
|
||||
CHANGEMENT_REGLEMENT(
|
||||
"Changement de règlement", "organisation", "important", "gavel", "#FF5722", true, true),
|
||||
ELECTION_OUVERTE(
|
||||
"Élection ouverte", "organisation", "info", "how_to_vote", "#2196F3", true, true),
|
||||
RESULTAT_ELECTION("Résultat d'élection", "organisation", "info", "poll", "#4CAF50", true, false),
|
||||
|
||||
// === NOTIFICATIONS SYSTÈME ===
|
||||
MISE_A_JOUR_APP(
|
||||
"Mise à jour disponible", "systeme", "info", "system_update", "#2196F3", true, false),
|
||||
MAINTENANCE_PROGRAMMEE(
|
||||
"Maintenance programmée", "systeme", "warning", "build", "#FF9800", true, true),
|
||||
PROBLEME_TECHNIQUE("Problème technique", "systeme", "error", "error", "#F44336", true, true),
|
||||
SAUVEGARDE_REUSSIE("Sauvegarde réussie", "systeme", "success", "backup", "#4CAF50", false, false),
|
||||
|
||||
// === NOTIFICATIONS PERSONNALISÉES ===
|
||||
MESSAGE_PRIVE("Message privé", "messages", "info", "mail", "#2196F3", true, false),
|
||||
MENTION("Mention", "messages", "info", "alternate_email", "#FF9800", true, false),
|
||||
COMMENTAIRE("Nouveau commentaire", "messages", "info", "comment", "#2196F3", true, false),
|
||||
|
||||
// === NOTIFICATIONS GÉOLOCALISÉES ===
|
||||
EVENEMENT_PROXIMITE(
|
||||
"Événement à proximité", "geolocalisation", "info", "location_on", "#4CAF50", true, false),
|
||||
MEMBRE_PROXIMITE(
|
||||
"Membre à proximité", "geolocalisation", "info", "people", "#2196F3", true, false),
|
||||
URGENCE_LOCALE("Urgence locale", "geolocalisation", "urgent", "warning", "#F44336", true, true);
|
||||
|
||||
private final String libelle;
|
||||
private final String categorie;
|
||||
private final String priorite;
|
||||
private final String icone;
|
||||
private final String couleur;
|
||||
private final boolean visibleUtilisateur;
|
||||
private final boolean activeeParDefaut;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération TypeNotification
|
||||
*
|
||||
* @param libelle Le libellé affiché à l'utilisateur
|
||||
* @param categorie La catégorie de la notification
|
||||
* @param priorite Le niveau de priorité (info, reminder, warning, error, success, urgent,
|
||||
* important, celebration)
|
||||
* @param icone L'icône Material Design
|
||||
* @param couleur La couleur hexadécimale
|
||||
* @param visibleUtilisateur true si visible dans les préférences utilisateur
|
||||
* @param activeeParDefaut true si activée par défaut
|
||||
*/
|
||||
TypeNotification(
|
||||
String libelle,
|
||||
String categorie,
|
||||
String priorite,
|
||||
String icone,
|
||||
String couleur,
|
||||
boolean visibleUtilisateur,
|
||||
boolean activeeParDefaut) {
|
||||
this.libelle = libelle;
|
||||
this.categorie = categorie;
|
||||
this.priorite = priorite;
|
||||
this.icone = icone;
|
||||
this.couleur = couleur;
|
||||
this.visibleUtilisateur = visibleUtilisateur;
|
||||
this.activeeParDefaut = activeeParDefaut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé de la notification
|
||||
*
|
||||
* @return Le libellé affiché à l'utilisateur
|
||||
*/
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la catégorie de la notification
|
||||
*
|
||||
* @return La catégorie (evenements, cotisations, solidarite, etc.)
|
||||
*/
|
||||
public String getCategorie() {
|
||||
return categorie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la priorité de la notification
|
||||
*
|
||||
* @return Le niveau de priorité
|
||||
*/
|
||||
public String getPriorite() {
|
||||
return priorite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'icône de la notification
|
||||
*
|
||||
* @return L'icône Material Design
|
||||
*/
|
||||
public String getIcone() {
|
||||
return icone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la couleur de la notification
|
||||
*
|
||||
* @return Le code couleur hexadécimal
|
||||
*/
|
||||
public String getCouleur() {
|
||||
return couleur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification est visible dans les préférences utilisateur
|
||||
*
|
||||
* @return true si visible dans les préférences
|
||||
*/
|
||||
public boolean isVisibleUtilisateur() {
|
||||
return visibleUtilisateur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification est activée par défaut
|
||||
*
|
||||
* @return true si activée par défaut
|
||||
*/
|
||||
public boolean isActiveeParDefaut() {
|
||||
return activeeParDefaut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification est critique (urgent ou error)
|
||||
*
|
||||
* @return true si la notification est critique
|
||||
*/
|
||||
public boolean isCritique() {
|
||||
return "urgent".equals(priorite) || "error".equals(priorite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification est un rappel
|
||||
*
|
||||
* @return true si c'est un rappel
|
||||
*/
|
||||
public boolean isRappel() {
|
||||
return "reminder".equals(priorite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification est positive (success ou celebration)
|
||||
*
|
||||
* @return true si la notification est positive
|
||||
*/
|
||||
public boolean isPositive() {
|
||||
return "success".equals(priorite) || "celebration".equals(priorite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le niveau de priorité numérique pour le tri
|
||||
*
|
||||
* @return Niveau de priorité (1=urgent, 2=error, 3=warning, 4=important, 5=reminder, 6=info,
|
||||
* 7=success, 8=celebration)
|
||||
*/
|
||||
public int getNiveauPriorite() {
|
||||
return switch (priorite) {
|
||||
case "urgent" -> 1;
|
||||
case "error" -> 2;
|
||||
case "warning" -> 3;
|
||||
case "important" -> 4;
|
||||
case "reminder" -> 5;
|
||||
case "info" -> 6;
|
||||
case "success" -> 7;
|
||||
case "celebration" -> 8;
|
||||
default -> 6;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le délai d'expiration par défaut en heures
|
||||
*
|
||||
* @return Délai d'expiration en heures
|
||||
*/
|
||||
public int getDelaiExpirationHeures() {
|
||||
return switch (priorite) {
|
||||
case "urgent" -> 1; // 1 heure
|
||||
case "error" -> 24; // 24 heures
|
||||
case "warning" -> 48; // 48 heures
|
||||
case "important" -> 72; // 72 heures
|
||||
case "reminder" -> 24; // 24 heures
|
||||
case "info" -> 168; // 1 semaine
|
||||
case "success" -> 48; // 48 heures
|
||||
case "celebration" -> 72; // 72 heures
|
||||
default -> 168;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification doit vibrer
|
||||
*
|
||||
* @return true si la notification doit faire vibrer l'appareil
|
||||
*/
|
||||
public boolean doitVibrer() {
|
||||
return isCritique() || isRappel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la notification doit émettre un son
|
||||
*
|
||||
* @return true si la notification doit émettre un son
|
||||
*/
|
||||
public boolean doitEmettreSon() {
|
||||
return isCritique() || isRappel() || "important".equals(priorite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le canal de notification Android approprié
|
||||
*
|
||||
* @return L'ID du canal de notification
|
||||
*/
|
||||
public String getCanalNotification() {
|
||||
return switch (priorite) {
|
||||
case "urgent" -> "URGENT_CHANNEL";
|
||||
case "error" -> "ERROR_CHANNEL";
|
||||
case "warning" -> "WARNING_CHANNEL";
|
||||
case "important" -> "IMPORTANT_CHANNEL";
|
||||
case "reminder" -> "REMINDER_CHANNEL";
|
||||
case "success" -> "SUCCESS_CHANNEL";
|
||||
case "celebration" -> "CELEBRATION_CHANNEL";
|
||||
default -> "DEFAULT_CHANNEL";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,214 +2,260 @@ package dev.lions.unionflow.server.api.enums.solidarite;
|
||||
|
||||
/**
|
||||
* Énumération des priorités d'aide dans le système de solidarité
|
||||
*
|
||||
* Cette énumération définit les niveaux de priorité pour les demandes d'aide,
|
||||
* permettant de prioriser le traitement selon l'urgence de la situation.
|
||||
*
|
||||
*
|
||||
* <p>Cette énumération définit les niveaux de priorité pour les demandes d'aide, permettant de
|
||||
* prioriser le traitement selon l'urgence de la situation.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
public enum PrioriteAide {
|
||||
|
||||
CRITIQUE("Critique", "critical", 1, "Situation critique nécessitant une intervention immédiate",
|
||||
"#F44336", "emergency", 24, true, true),
|
||||
|
||||
URGENTE("Urgente", "urgent", 2, "Situation urgente nécessitant une réponse rapide",
|
||||
"#FF5722", "priority_high", 72, true, false),
|
||||
|
||||
ELEVEE("Élevée", "high", 3, "Priorité élevée, traitement dans les meilleurs délais",
|
||||
"#FF9800", "keyboard_arrow_up", 168, false, false),
|
||||
|
||||
NORMALE("Normale", "normal", 4, "Priorité normale, traitement selon les délais standards",
|
||||
"#2196F3", "remove", 336, false, false),
|
||||
|
||||
FAIBLE("Faible", "low", 5, "Priorité faible, traitement quand les ressources le permettent",
|
||||
"#4CAF50", "keyboard_arrow_down", 720, false, false);
|
||||
CRITIQUE(
|
||||
"Critique",
|
||||
"critical",
|
||||
1,
|
||||
"Situation critique nécessitant une intervention immédiate",
|
||||
"#F44336",
|
||||
"emergency",
|
||||
24,
|
||||
true,
|
||||
true),
|
||||
|
||||
private final String libelle;
|
||||
private final String code;
|
||||
private final int niveau;
|
||||
private final String description;
|
||||
private final String couleur;
|
||||
private final String icone;
|
||||
private final int delaiTraitementHeures;
|
||||
private final boolean notificationImmediate;
|
||||
private final boolean escaladeAutomatique;
|
||||
URGENTE(
|
||||
"Urgente",
|
||||
"urgent",
|
||||
2,
|
||||
"Situation urgente nécessitant une réponse rapide",
|
||||
"#FF5722",
|
||||
"priority_high",
|
||||
72,
|
||||
true,
|
||||
false),
|
||||
|
||||
PrioriteAide(String libelle, String code, int niveau, String description, String couleur,
|
||||
String icone, int delaiTraitementHeures, boolean notificationImmediate,
|
||||
boolean escaladeAutomatique) {
|
||||
this.libelle = libelle;
|
||||
this.code = code;
|
||||
this.niveau = niveau;
|
||||
this.description = description;
|
||||
this.couleur = couleur;
|
||||
this.icone = icone;
|
||||
this.delaiTraitementHeures = delaiTraitementHeures;
|
||||
this.notificationImmediate = notificationImmediate;
|
||||
this.escaladeAutomatique = escaladeAutomatique;
|
||||
ELEVEE(
|
||||
"Élevée",
|
||||
"high",
|
||||
3,
|
||||
"Priorité élevée, traitement dans les meilleurs délais",
|
||||
"#FF9800",
|
||||
"keyboard_arrow_up",
|
||||
168,
|
||||
false,
|
||||
false),
|
||||
|
||||
NORMALE(
|
||||
"Normale",
|
||||
"normal",
|
||||
4,
|
||||
"Priorité normale, traitement selon les délais standards",
|
||||
"#2196F3",
|
||||
"remove",
|
||||
336,
|
||||
false,
|
||||
false),
|
||||
|
||||
FAIBLE(
|
||||
"Faible",
|
||||
"low",
|
||||
5,
|
||||
"Priorité faible, traitement quand les ressources le permettent",
|
||||
"#4CAF50",
|
||||
"keyboard_arrow_down",
|
||||
720,
|
||||
false,
|
||||
false);
|
||||
|
||||
private final String libelle;
|
||||
private final String code;
|
||||
private final int niveau;
|
||||
private final String description;
|
||||
private final String couleur;
|
||||
private final String icone;
|
||||
private final int delaiTraitementHeures;
|
||||
private final boolean notificationImmediate;
|
||||
private final boolean escaladeAutomatique;
|
||||
|
||||
PrioriteAide(
|
||||
String libelle,
|
||||
String code,
|
||||
int niveau,
|
||||
String description,
|
||||
String couleur,
|
||||
String icone,
|
||||
int delaiTraitementHeures,
|
||||
boolean notificationImmediate,
|
||||
boolean escaladeAutomatique) {
|
||||
this.libelle = libelle;
|
||||
this.code = code;
|
||||
this.niveau = niveau;
|
||||
this.description = description;
|
||||
this.couleur = couleur;
|
||||
this.icone = icone;
|
||||
this.delaiTraitementHeures = delaiTraitementHeures;
|
||||
this.notificationImmediate = notificationImmediate;
|
||||
this.escaladeAutomatique = escaladeAutomatique;
|
||||
}
|
||||
|
||||
// === GETTERS ===
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public int getNiveau() {
|
||||
return niveau;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getCouleur() {
|
||||
return couleur;
|
||||
}
|
||||
|
||||
public String getIcone() {
|
||||
return icone;
|
||||
}
|
||||
|
||||
public int getDelaiTraitementHeures() {
|
||||
return delaiTraitementHeures;
|
||||
}
|
||||
|
||||
public boolean isNotificationImmediate() {
|
||||
return notificationImmediate;
|
||||
}
|
||||
|
||||
public boolean isEscaladeAutomatique() {
|
||||
return escaladeAutomatique;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/** Vérifie si la priorité est critique ou urgente */
|
||||
public boolean isUrgente() {
|
||||
return this == CRITIQUE || this == URGENTE;
|
||||
}
|
||||
|
||||
/** Vérifie si la priorité nécessite un traitement immédiat */
|
||||
public boolean necessiteTraitementImmediat() {
|
||||
return niveau <= 2;
|
||||
}
|
||||
|
||||
/** Retourne la date limite de traitement */
|
||||
public java.time.LocalDateTime getDateLimiteTraitement() {
|
||||
return java.time.LocalDateTime.now().plusHours(delaiTraitementHeures);
|
||||
}
|
||||
|
||||
/** Retourne la priorité suivante (escalade) */
|
||||
public PrioriteAide getPrioriteEscalade() {
|
||||
return switch (this) {
|
||||
case FAIBLE -> NORMALE;
|
||||
case NORMALE -> ELEVEE;
|
||||
case ELEVEE -> URGENTE;
|
||||
case URGENTE -> CRITIQUE;
|
||||
case CRITIQUE -> CRITIQUE; // Déjà au maximum
|
||||
};
|
||||
}
|
||||
|
||||
/** Détermine la priorité basée sur le type d'aide */
|
||||
public static PrioriteAide determinerPriorite(TypeAide typeAide) {
|
||||
if (typeAide.isUrgent()) {
|
||||
return switch (typeAide) {
|
||||
case AIDE_FINANCIERE_URGENTE, AIDE_FRAIS_MEDICAUX -> CRITIQUE;
|
||||
case HEBERGEMENT_URGENCE, AIDE_ALIMENTAIRE -> URGENTE;
|
||||
default -> ELEVEE;
|
||||
};
|
||||
}
|
||||
|
||||
// === GETTERS ===
|
||||
|
||||
public String getLibelle() { return libelle; }
|
||||
public String getCode() { return code; }
|
||||
public int getNiveau() { return niveau; }
|
||||
public String getDescription() { return description; }
|
||||
public String getCouleur() { return couleur; }
|
||||
public String getIcone() { return icone; }
|
||||
public int getDelaiTraitementHeures() { return delaiTraitementHeures; }
|
||||
public boolean isNotificationImmediate() { return notificationImmediate; }
|
||||
public boolean isEscaladeAutomatique() { return escaladeAutomatique; }
|
||||
if (typeAide.getPriorite().equals("important")) {
|
||||
return ELEVEE;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Vérifie si la priorité est critique ou urgente
|
||||
*/
|
||||
public boolean isUrgente() {
|
||||
return this == CRITIQUE || this == URGENTE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la priorité nécessite un traitement immédiat
|
||||
*/
|
||||
public boolean necessiteTraitementImmediat() {
|
||||
return niveau <= 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la date limite de traitement
|
||||
*/
|
||||
public java.time.LocalDateTime getDateLimiteTraitement() {
|
||||
return java.time.LocalDateTime.now().plusHours(delaiTraitementHeures);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la priorité suivante (escalade)
|
||||
*/
|
||||
public PrioriteAide getPrioriteEscalade() {
|
||||
return switch (this) {
|
||||
case FAIBLE -> NORMALE;
|
||||
case NORMALE -> ELEVEE;
|
||||
case ELEVEE -> URGENTE;
|
||||
case URGENTE -> CRITIQUE;
|
||||
case CRITIQUE -> CRITIQUE; // Déjà au maximum
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Détermine la priorité basée sur le type d'aide
|
||||
*/
|
||||
public static PrioriteAide determinerPriorite(TypeAide typeAide) {
|
||||
if (typeAide.isUrgent()) {
|
||||
return switch (typeAide) {
|
||||
case AIDE_FINANCIERE_URGENTE, AIDE_FRAIS_MEDICAUX -> CRITIQUE;
|
||||
case HEBERGEMENT_URGENCE, AIDE_ALIMENTAIRE -> URGENTE;
|
||||
default -> ELEVEE;
|
||||
};
|
||||
}
|
||||
|
||||
if (typeAide.getPriorite().equals("important")) {
|
||||
return ELEVEE;
|
||||
}
|
||||
|
||||
return NORMALE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les priorités urgentes
|
||||
*/
|
||||
public static java.util.List<PrioriteAide> getPrioritesUrgentes() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(PrioriteAide::isUrgente)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les priorités par niveau croissant
|
||||
*/
|
||||
public static java.util.List<PrioriteAide> getParNiveauCroissant() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.sorted(java.util.Comparator.comparingInt(PrioriteAide::getNiveau))
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les priorités par niveau décroissant
|
||||
*/
|
||||
public static java.util.List<PrioriteAide> getParNiveauDecroissant() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.sorted(java.util.Comparator.comparingInt(PrioriteAide::getNiveau).reversed())
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve la priorité par code
|
||||
*/
|
||||
public static PrioriteAide parCode(String code) {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(p -> p.getCode().equals(code))
|
||||
.findFirst()
|
||||
.orElse(NORMALE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le score de priorité (plus bas = plus prioritaire)
|
||||
*/
|
||||
public double getScorePriorite() {
|
||||
double score = niveau;
|
||||
|
||||
// Bonus pour notification immédiate
|
||||
if (notificationImmediate) score -= 0.5;
|
||||
|
||||
// Bonus pour escalade automatique
|
||||
if (escaladeAutomatique) score -= 0.3;
|
||||
|
||||
// Malus pour délai long
|
||||
if (delaiTraitementHeures > 168) score += 0.2;
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le délai de traitement est dépassé
|
||||
*/
|
||||
public boolean isDelaiDepasse(java.time.LocalDateTime dateCreation) {
|
||||
java.time.LocalDateTime dateLimite = dateCreation.plusHours(delaiTraitementHeures);
|
||||
return java.time.LocalDateTime.now().isAfter(dateLimite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le pourcentage de temps écoulé
|
||||
*/
|
||||
public double getPourcentageTempsEcoule(java.time.LocalDateTime dateCreation) {
|
||||
java.time.LocalDateTime maintenant = java.time.LocalDateTime.now();
|
||||
java.time.LocalDateTime dateLimite = dateCreation.plusHours(delaiTraitementHeures);
|
||||
|
||||
long dureeTotal = java.time.Duration.between(dateCreation, dateLimite).toMinutes();
|
||||
long dureeEcoulee = java.time.Duration.between(dateCreation, maintenant).toMinutes();
|
||||
|
||||
if (dureeTotal <= 0) return 100.0;
|
||||
|
||||
return Math.min(100.0, (dureeEcoulee * 100.0) / dureeTotal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le message d'alerte selon le temps écoulé
|
||||
*/
|
||||
public String getMessageAlerte(java.time.LocalDateTime dateCreation) {
|
||||
double pourcentage = getPourcentageTempsEcoule(dateCreation);
|
||||
|
||||
if (pourcentage >= 100) {
|
||||
return "Délai de traitement dépassé !";
|
||||
} else if (pourcentage >= 80) {
|
||||
return "Délai de traitement bientôt dépassé";
|
||||
} else if (pourcentage >= 60) {
|
||||
return "Plus de la moitié du délai écoulé";
|
||||
}
|
||||
|
||||
return null;
|
||||
return NORMALE;
|
||||
}
|
||||
|
||||
/** Retourne les priorités urgentes */
|
||||
public static java.util.List<PrioriteAide> getPrioritesUrgentes() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(PrioriteAide::isUrgente)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Retourne les priorités par niveau croissant */
|
||||
public static java.util.List<PrioriteAide> getParNiveauCroissant() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.sorted(java.util.Comparator.comparingInt(PrioriteAide::getNiveau))
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Retourne les priorités par niveau décroissant */
|
||||
public static java.util.List<PrioriteAide> getParNiveauDecroissant() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.sorted(java.util.Comparator.comparingInt(PrioriteAide::getNiveau).reversed())
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Trouve la priorité par code */
|
||||
public static PrioriteAide parCode(String code) {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(p -> p.getCode().equals(code))
|
||||
.findFirst()
|
||||
.orElse(NORMALE);
|
||||
}
|
||||
|
||||
/** Calcule le score de priorité (plus bas = plus prioritaire) */
|
||||
public double getScorePriorite() {
|
||||
double score = niveau;
|
||||
|
||||
// Bonus pour notification immédiate
|
||||
if (notificationImmediate) score -= 0.5;
|
||||
|
||||
// Bonus pour escalade automatique
|
||||
if (escaladeAutomatique) score -= 0.3;
|
||||
|
||||
// Malus pour délai long
|
||||
if (delaiTraitementHeures > 168) score += 0.2;
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
/** Vérifie si le délai de traitement est dépassé */
|
||||
public boolean isDelaiDepasse(java.time.LocalDateTime dateCreation) {
|
||||
java.time.LocalDateTime dateLimite = dateCreation.plusHours(delaiTraitementHeures);
|
||||
return java.time.LocalDateTime.now().isAfter(dateLimite);
|
||||
}
|
||||
|
||||
/** Calcule le pourcentage de temps écoulé */
|
||||
public double getPourcentageTempsEcoule(java.time.LocalDateTime dateCreation) {
|
||||
java.time.LocalDateTime maintenant = java.time.LocalDateTime.now();
|
||||
java.time.LocalDateTime dateLimite = dateCreation.plusHours(delaiTraitementHeures);
|
||||
|
||||
long dureeTotal = java.time.Duration.between(dateCreation, dateLimite).toMinutes();
|
||||
long dureeEcoulee = java.time.Duration.between(dateCreation, maintenant).toMinutes();
|
||||
|
||||
if (dureeTotal <= 0) return 100.0;
|
||||
|
||||
return Math.min(100.0, (dureeEcoulee * 100.0) / dureeTotal);
|
||||
}
|
||||
|
||||
/** Retourne le message d'alerte selon le temps écoulé */
|
||||
public String getMessageAlerte(java.time.LocalDateTime dateCreation) {
|
||||
double pourcentage = getPourcentageTempsEcoule(dateCreation);
|
||||
|
||||
if (pourcentage >= 100) {
|
||||
return "Délai de traitement dépassé !";
|
||||
} else if (pourcentage >= 80) {
|
||||
return "Délai de traitement bientôt dépassé";
|
||||
} else if (pourcentage >= 60) {
|
||||
return "Plus de la moitié du délai écoulé";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package dev.lions.unionflow.server.api.enums.solidarite;
|
||||
/**
|
||||
* Énumération des statuts d'aide dans le système de solidarité
|
||||
*
|
||||
* Cette énumération définit les différents statuts qu'une demande d'aide
|
||||
* peut avoir tout au long de son cycle de vie.
|
||||
* <p>Cette énumération définit les différents statuts qu'une demande d'aide peut avoir tout au long
|
||||
* de son cycle de vie.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
@@ -12,170 +12,276 @@ package dev.lions.unionflow.server.api.enums.solidarite;
|
||||
*/
|
||||
public enum StatutAide {
|
||||
|
||||
// === STATUTS INITIAUX ===
|
||||
BROUILLON("Brouillon", "draft", "La demande est en cours de rédaction", "#9E9E9E", "edit", false, false),
|
||||
SOUMISE("Soumise", "submitted", "La demande a été soumise et attend validation", "#FF9800", "send", false, false),
|
||||
// === STATUTS INITIAUX ===
|
||||
BROUILLON(
|
||||
"Brouillon",
|
||||
"draft",
|
||||
"La demande est en cours de rédaction",
|
||||
"#9E9E9E",
|
||||
"edit",
|
||||
false,
|
||||
false),
|
||||
SOUMISE(
|
||||
"Soumise",
|
||||
"submitted",
|
||||
"La demande a été soumise et attend validation",
|
||||
"#FF9800",
|
||||
"send",
|
||||
false,
|
||||
false),
|
||||
|
||||
// === STATUTS D'ÉVALUATION ===
|
||||
EN_ATTENTE("En attente", "pending", "La demande est en attente d'évaluation", "#2196F3", "hourglass_empty", false, false),
|
||||
EN_COURS_EVALUATION("En cours d'évaluation", "under_review", "La demande est en cours d'évaluation", "#FF9800", "rate_review", false, false),
|
||||
INFORMATIONS_REQUISES("Informations requises", "info_required", "Des informations complémentaires sont requises", "#FF5722", "info", false, false),
|
||||
// === STATUTS D'ÉVALUATION ===
|
||||
EN_ATTENTE(
|
||||
"En attente",
|
||||
"pending",
|
||||
"La demande est en attente d'évaluation",
|
||||
"#2196F3",
|
||||
"hourglass_empty",
|
||||
false,
|
||||
false),
|
||||
EN_COURS_EVALUATION(
|
||||
"En cours d'évaluation",
|
||||
"under_review",
|
||||
"La demande est en cours d'évaluation",
|
||||
"#FF9800",
|
||||
"rate_review",
|
||||
false,
|
||||
false),
|
||||
INFORMATIONS_REQUISES(
|
||||
"Informations requises",
|
||||
"info_required",
|
||||
"Des informations complémentaires sont requises",
|
||||
"#FF5722",
|
||||
"info",
|
||||
false,
|
||||
false),
|
||||
|
||||
// === STATUTS DE DÉCISION ===
|
||||
APPROUVEE("Approuvée", "approved", "La demande a été approuvée", "#4CAF50", "check_circle", true, false),
|
||||
APPROUVEE_PARTIELLEMENT("Approuvée partiellement", "partially_approved", "La demande a été approuvée partiellement", "#8BC34A", "check_circle_outline", true, false),
|
||||
REJETEE("Rejetée", "rejected", "La demande a été rejetée", "#F44336", "cancel", true, true),
|
||||
// === STATUTS DE DÉCISION ===
|
||||
APPROUVEE(
|
||||
"Approuvée",
|
||||
"approved",
|
||||
"La demande a été approuvée",
|
||||
"#4CAF50",
|
||||
"check_circle",
|
||||
true,
|
||||
false),
|
||||
APPROUVEE_PARTIELLEMENT(
|
||||
"Approuvée partiellement",
|
||||
"partially_approved",
|
||||
"La demande a été approuvée partiellement",
|
||||
"#8BC34A",
|
||||
"check_circle_outline",
|
||||
true,
|
||||
false),
|
||||
REJETEE("Rejetée", "rejected", "La demande a été rejetée", "#F44336", "cancel", true, true),
|
||||
|
||||
// === STATUTS DE TRAITEMENT ===
|
||||
EN_COURS_TRAITEMENT("En cours de traitement", "processing", "La demande approuvée est en cours de traitement", "#9C27B0", "settings", false, false),
|
||||
EN_COURS_VERSEMENT("En cours de versement", "payment_processing", "Le versement est en cours", "#3F51B5", "payment", false, false),
|
||||
// === STATUTS DE TRAITEMENT ===
|
||||
EN_COURS_TRAITEMENT(
|
||||
"En cours de traitement",
|
||||
"processing",
|
||||
"La demande approuvée est en cours de traitement",
|
||||
"#9C27B0",
|
||||
"settings",
|
||||
false,
|
||||
false),
|
||||
EN_COURS_VERSEMENT(
|
||||
"En cours de versement",
|
||||
"payment_processing",
|
||||
"Le versement est en cours",
|
||||
"#3F51B5",
|
||||
"payment",
|
||||
false,
|
||||
false),
|
||||
|
||||
// === STATUTS FINAUX ===
|
||||
VERSEE("Versée", "paid", "L'aide a été versée avec succès", "#4CAF50", "paid", true, false),
|
||||
LIVREE("Livrée", "delivered", "L'aide matérielle a été livrée", "#4CAF50", "local_shipping", true, false),
|
||||
TERMINEE("Terminée", "completed", "L'aide a été fournie avec succès", "#4CAF50", "done_all", true, false),
|
||||
// === STATUTS FINAUX ===
|
||||
VERSEE("Versée", "paid", "L'aide a été versée avec succès", "#4CAF50", "paid", true, false),
|
||||
LIVREE(
|
||||
"Livrée",
|
||||
"delivered",
|
||||
"L'aide matérielle a été livrée",
|
||||
"#4CAF50",
|
||||
"local_shipping",
|
||||
true,
|
||||
false),
|
||||
TERMINEE(
|
||||
"Terminée",
|
||||
"completed",
|
||||
"L'aide a été fournie avec succès",
|
||||
"#4CAF50",
|
||||
"done_all",
|
||||
true,
|
||||
false),
|
||||
|
||||
// === STATUTS D'EXCEPTION ===
|
||||
ANNULEE("Annulée", "cancelled", "La demande a été annulée", "#9E9E9E", "cancel", true, true),
|
||||
SUSPENDUE("Suspendue", "suspended", "La demande a été suspendue temporairement", "#FF5722", "pause_circle", false, false),
|
||||
EXPIREE("Expirée", "expired", "La demande a expiré", "#795548", "schedule", true, true),
|
||||
// === STATUTS D'EXCEPTION ===
|
||||
ANNULEE("Annulée", "cancelled", "La demande a été annulée", "#9E9E9E", "cancel", true, true),
|
||||
SUSPENDUE(
|
||||
"Suspendue",
|
||||
"suspended",
|
||||
"La demande a été suspendue temporairement",
|
||||
"#FF5722",
|
||||
"pause_circle",
|
||||
false,
|
||||
false),
|
||||
EXPIREE("Expirée", "expired", "La demande a expiré", "#795548", "schedule", true, true),
|
||||
|
||||
// === STATUTS DE SUIVI ===
|
||||
EN_SUIVI("En suivi", "follow_up", "L'aide fait l'objet d'un suivi", "#607D8B", "track_changes", false, false),
|
||||
CLOTUREE("Clôturée", "closed", "Le dossier d'aide est clôturé", "#9E9E9E", "folder", true, false);
|
||||
// === STATUTS DE SUIVI ===
|
||||
EN_SUIVI(
|
||||
"En suivi",
|
||||
"follow_up",
|
||||
"L'aide fait l'objet d'un suivi",
|
||||
"#607D8B",
|
||||
"track_changes",
|
||||
false,
|
||||
false),
|
||||
CLOTUREE("Clôturée", "closed", "Le dossier d'aide est clôturé", "#9E9E9E", "folder", true, false);
|
||||
|
||||
private final String libelle;
|
||||
private final String code;
|
||||
private final String description;
|
||||
private final String couleur;
|
||||
private final String icone;
|
||||
private final boolean estFinal;
|
||||
private final boolean estEchec;
|
||||
private final String libelle;
|
||||
private final String code;
|
||||
private final String description;
|
||||
private final String couleur;
|
||||
private final String icone;
|
||||
private final boolean estFinal;
|
||||
private final boolean estEchec;
|
||||
|
||||
StatutAide(String libelle, String code, String description, String couleur, String icone, boolean estFinal, boolean estEchec) {
|
||||
this.libelle = libelle;
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
this.couleur = couleur;
|
||||
this.icone = icone;
|
||||
this.estFinal = estFinal;
|
||||
this.estEchec = estEchec;
|
||||
}
|
||||
StatutAide(
|
||||
String libelle,
|
||||
String code,
|
||||
String description,
|
||||
String couleur,
|
||||
String icone,
|
||||
boolean estFinal,
|
||||
boolean estEchec) {
|
||||
this.libelle = libelle;
|
||||
this.code = code;
|
||||
this.description = description;
|
||||
this.couleur = couleur;
|
||||
this.icone = icone;
|
||||
this.estFinal = estFinal;
|
||||
this.estEchec = estEchec;
|
||||
}
|
||||
|
||||
// === GETTERS ===
|
||||
// === GETTERS ===
|
||||
|
||||
public String getLibelle() { return libelle; }
|
||||
public String getCode() { return code; }
|
||||
public String getDescription() { return description; }
|
||||
public String getCouleur() { return couleur; }
|
||||
public String getIcone() { return icone; }
|
||||
public boolean isEstFinal() { return estFinal; }
|
||||
public boolean isEstEchec() { return estEchec; }
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut indique un succès
|
||||
*/
|
||||
public boolean isSucces() {
|
||||
return this == VERSEE || this == LIVREE || this == TERMINEE;
|
||||
}
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut est en cours de traitement
|
||||
*/
|
||||
public boolean isEnCours() {
|
||||
return this == EN_COURS_EVALUATION || this == EN_COURS_TRAITEMENT || this == EN_COURS_VERSEMENT;
|
||||
}
|
||||
public String getCouleur() {
|
||||
return couleur;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut permet la modification
|
||||
*/
|
||||
public boolean permetModification() {
|
||||
return this == BROUILLON || this == INFORMATIONS_REQUISES;
|
||||
}
|
||||
public String getIcone() {
|
||||
return icone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le statut permet l'annulation
|
||||
*/
|
||||
public boolean permetAnnulation() {
|
||||
return !estFinal && this != ANNULEE;
|
||||
}
|
||||
public boolean isEstFinal() {
|
||||
return estFinal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les statuts finaux
|
||||
*/
|
||||
public static java.util.List<StatutAide> getStatutsFinaux() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutAide::isEstFinal)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
public boolean isEstEchec() {
|
||||
return estEchec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les statuts d'échec
|
||||
*/
|
||||
public static java.util.List<StatutAide> getStatutsEchec() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutAide::isEstEchec)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Retourne les statuts de succès
|
||||
*/
|
||||
public static java.util.List<StatutAide> getStatutsSucces() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutAide::isSucces)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
/** Vérifie si le statut indique un succès */
|
||||
public boolean isSucces() {
|
||||
return this == VERSEE || this == LIVREE || this == TERMINEE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les statuts en cours
|
||||
*/
|
||||
public static java.util.List<StatutAide> getStatutsEnCours() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutAide::isEnCours)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
/** Vérifie si le statut est en cours de traitement */
|
||||
public boolean isEnCours() {
|
||||
return this == EN_COURS_EVALUATION || this == EN_COURS_TRAITEMENT || this == EN_COURS_VERSEMENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la transition vers un autre statut est valide
|
||||
*/
|
||||
public boolean peutTransitionnerVers(StatutAide nouveauStatut) {
|
||||
// Règles de transition simplifiées
|
||||
if (this == nouveauStatut) return false;
|
||||
if (estFinal && nouveauStatut != EN_SUIVI) return false;
|
||||
/** Vérifie si le statut permet la modification */
|
||||
public boolean permetModification() {
|
||||
return this == BROUILLON || this == INFORMATIONS_REQUISES;
|
||||
}
|
||||
|
||||
return switch (this) {
|
||||
case BROUILLON -> nouveauStatut == SOUMISE || nouveauStatut == ANNULEE;
|
||||
case SOUMISE -> nouveauStatut == EN_ATTENTE || nouveauStatut == ANNULEE;
|
||||
case EN_ATTENTE -> nouveauStatut == EN_COURS_EVALUATION || nouveauStatut == ANNULEE;
|
||||
case EN_COURS_EVALUATION -> nouveauStatut == APPROUVEE || nouveauStatut == APPROUVEE_PARTIELLEMENT ||
|
||||
nouveauStatut == REJETEE || nouveauStatut == INFORMATIONS_REQUISES ||
|
||||
nouveauStatut == SUSPENDUE;
|
||||
case INFORMATIONS_REQUISES -> nouveauStatut == EN_COURS_EVALUATION || nouveauStatut == ANNULEE;
|
||||
case APPROUVEE, APPROUVEE_PARTIELLEMENT -> nouveauStatut == EN_COURS_TRAITEMENT || nouveauStatut == SUSPENDUE;
|
||||
case EN_COURS_TRAITEMENT -> nouveauStatut == EN_COURS_VERSEMENT || nouveauStatut == LIVREE ||
|
||||
nouveauStatut == TERMINEE || nouveauStatut == SUSPENDUE;
|
||||
case EN_COURS_VERSEMENT -> nouveauStatut == VERSEE || nouveauStatut == SUSPENDUE;
|
||||
case SUSPENDUE -> nouveauStatut == EN_COURS_EVALUATION || nouveauStatut == ANNULEE;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
/** Vérifie si le statut permet l'annulation */
|
||||
public boolean permetAnnulation() {
|
||||
return !estFinal && this != ANNULEE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le niveau de priorité pour l'affichage
|
||||
*/
|
||||
public int getNiveauPriorite() {
|
||||
return switch (this) {
|
||||
case INFORMATIONS_REQUISES -> 1;
|
||||
case EN_COURS_EVALUATION, EN_COURS_TRAITEMENT, EN_COURS_VERSEMENT -> 2;
|
||||
case APPROUVEE, APPROUVEE_PARTIELLEMENT -> 3;
|
||||
case EN_ATTENTE, SOUMISE -> 4;
|
||||
case SUSPENDUE -> 5;
|
||||
case BROUILLON -> 6;
|
||||
case EN_SUIVI -> 7;
|
||||
default -> 8; // Statuts finaux
|
||||
};
|
||||
}
|
||||
/** Retourne les statuts finaux */
|
||||
public static java.util.List<StatutAide> getStatutsFinaux() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutAide::isEstFinal)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Retourne les statuts d'échec */
|
||||
public static java.util.List<StatutAide> getStatutsEchec() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutAide::isEstEchec)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Retourne les statuts de succès */
|
||||
public static java.util.List<StatutAide> getStatutsSucces() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutAide::isSucces)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Retourne les statuts en cours */
|
||||
public static java.util.List<StatutAide> getStatutsEnCours() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(StatutAide::isEnCours)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Vérifie si la transition vers un autre statut est valide */
|
||||
public boolean peutTransitionnerVers(StatutAide nouveauStatut) {
|
||||
// Règles de transition simplifiées
|
||||
if (this == nouveauStatut) return false;
|
||||
if (estFinal && nouveauStatut != EN_SUIVI) return false;
|
||||
|
||||
return switch (this) {
|
||||
case BROUILLON -> nouveauStatut == SOUMISE || nouveauStatut == ANNULEE;
|
||||
case SOUMISE -> nouveauStatut == EN_ATTENTE || nouveauStatut == ANNULEE;
|
||||
case EN_ATTENTE -> nouveauStatut == EN_COURS_EVALUATION || nouveauStatut == ANNULEE;
|
||||
case EN_COURS_EVALUATION ->
|
||||
nouveauStatut == APPROUVEE
|
||||
|| nouveauStatut == APPROUVEE_PARTIELLEMENT
|
||||
|| nouveauStatut == REJETEE
|
||||
|| nouveauStatut == INFORMATIONS_REQUISES
|
||||
|| nouveauStatut == SUSPENDUE;
|
||||
case INFORMATIONS_REQUISES ->
|
||||
nouveauStatut == EN_COURS_EVALUATION || nouveauStatut == ANNULEE;
|
||||
case APPROUVEE, APPROUVEE_PARTIELLEMENT ->
|
||||
nouveauStatut == EN_COURS_TRAITEMENT || nouveauStatut == SUSPENDUE;
|
||||
case EN_COURS_TRAITEMENT ->
|
||||
nouveauStatut == EN_COURS_VERSEMENT
|
||||
|| nouveauStatut == LIVREE
|
||||
|| nouveauStatut == TERMINEE
|
||||
|| nouveauStatut == SUSPENDUE;
|
||||
case EN_COURS_VERSEMENT -> nouveauStatut == VERSEE || nouveauStatut == SUSPENDUE;
|
||||
case SUSPENDUE -> nouveauStatut == EN_COURS_EVALUATION || nouveauStatut == ANNULEE;
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
|
||||
/** Retourne le niveau de priorité pour l'affichage */
|
||||
public int getNiveauPriorite() {
|
||||
return switch (this) {
|
||||
case INFORMATIONS_REQUISES -> 1;
|
||||
case EN_COURS_EVALUATION, EN_COURS_TRAITEMENT, EN_COURS_VERSEMENT -> 2;
|
||||
case APPROUVEE, APPROUVEE_PARTIELLEMENT -> 3;
|
||||
case EN_ATTENTE, SOUMISE -> 4;
|
||||
case SUSPENDUE -> 5;
|
||||
case BROUILLON -> 6;
|
||||
case EN_SUIVI -> 7;
|
||||
default -> 8; // Statuts finaux
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package dev.lions.unionflow.server.api.enums.solidarite;
|
||||
/**
|
||||
* Énumération des types d'aide disponibles dans le système de solidarité
|
||||
*
|
||||
* Cette énumération définit les différents types d'aide que les membres
|
||||
* peuvent demander ou proposer dans le cadre du système de solidarité.
|
||||
* <p>Cette énumération définit les différents types d'aide que les membres peuvent demander ou
|
||||
* proposer dans le cadre du système de solidarité.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
@@ -12,273 +12,504 @@ package dev.lions.unionflow.server.api.enums.solidarite;
|
||||
*/
|
||||
public enum TypeAide {
|
||||
|
||||
// === AIDE FINANCIÈRE ===
|
||||
AIDE_FINANCIERE_URGENTE("Aide financière urgente", "financiere", "urgent",
|
||||
"Aide financière pour situation d'urgence", "emergency_fund", "#F44336",
|
||||
true, true, 5000.0, 50000.0, 7),
|
||||
// === AIDE FINANCIÈRE ===
|
||||
AIDE_FINANCIERE_URGENTE(
|
||||
"Aide financière urgente",
|
||||
"financiere",
|
||||
"urgent",
|
||||
"Aide financière pour situation d'urgence",
|
||||
"emergency_fund",
|
||||
"#F44336",
|
||||
true,
|
||||
true,
|
||||
5000.0,
|
||||
50000.0,
|
||||
7),
|
||||
|
||||
PRET_SANS_INTERET("Prêt sans intérêt", "financiere", "important",
|
||||
"Prêt sans intérêt entre membres", "account_balance", "#FF9800",
|
||||
true, true, 10000.0, 100000.0, 30),
|
||||
PRET_SANS_INTERET(
|
||||
"Prêt sans intérêt",
|
||||
"financiere",
|
||||
"important",
|
||||
"Prêt sans intérêt entre membres",
|
||||
"account_balance",
|
||||
"#FF9800",
|
||||
true,
|
||||
true,
|
||||
10000.0,
|
||||
100000.0,
|
||||
30),
|
||||
|
||||
AIDE_COTISATION("Aide pour cotisation", "financiere", "normal",
|
||||
"Aide pour payer les cotisations", "payment", "#2196F3",
|
||||
true, false, 1000.0, 10000.0, 14),
|
||||
AIDE_COTISATION(
|
||||
"Aide pour cotisation",
|
||||
"financiere",
|
||||
"normal",
|
||||
"Aide pour payer les cotisations",
|
||||
"payment",
|
||||
"#2196F3",
|
||||
true,
|
||||
false,
|
||||
1000.0,
|
||||
10000.0,
|
||||
14),
|
||||
|
||||
AIDE_FRAIS_MEDICAUX("Aide frais médicaux", "financiere", "urgent",
|
||||
"Aide pour frais médicaux et hospitaliers", "medical_services", "#E91E63",
|
||||
true, true, 5000.0, 200000.0, 7),
|
||||
AIDE_FRAIS_MEDICAUX(
|
||||
"Aide frais médicaux",
|
||||
"financiere",
|
||||
"urgent",
|
||||
"Aide pour frais médicaux et hospitaliers",
|
||||
"medical_services",
|
||||
"#E91E63",
|
||||
true,
|
||||
true,
|
||||
5000.0,
|
||||
200000.0,
|
||||
7),
|
||||
|
||||
AIDE_FRAIS_SCOLARITE("Aide frais de scolarité", "financiere", "important",
|
||||
"Aide pour frais de scolarité des enfants", "school", "#9C27B0",
|
||||
true, true, 10000.0, 100000.0, 21),
|
||||
AIDE_FRAIS_SCOLARITE(
|
||||
"Aide frais de scolarité",
|
||||
"financiere",
|
||||
"important",
|
||||
"Aide pour frais de scolarité des enfants",
|
||||
"school",
|
||||
"#9C27B0",
|
||||
true,
|
||||
true,
|
||||
10000.0,
|
||||
100000.0,
|
||||
21),
|
||||
|
||||
// === AIDE MATÉRIELLE ===
|
||||
DON_MATERIEL("Don de matériel", "materielle", "normal",
|
||||
"Don d'objets, équipements ou matériel", "inventory", "#4CAF50",
|
||||
false, false, null, null, 14),
|
||||
// === AIDE MATÉRIELLE ===
|
||||
DON_MATERIEL(
|
||||
"Don de matériel",
|
||||
"materielle",
|
||||
"normal",
|
||||
"Don d'objets, équipements ou matériel",
|
||||
"inventory",
|
||||
"#4CAF50",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
14),
|
||||
|
||||
PRET_MATERIEL("Prêt de matériel", "materielle", "normal",
|
||||
"Prêt temporaire d'objets ou équipements", "build", "#607D8B",
|
||||
false, false, null, null, 30),
|
||||
PRET_MATERIEL(
|
||||
"Prêt de matériel",
|
||||
"materielle",
|
||||
"normal",
|
||||
"Prêt temporaire d'objets ou équipements",
|
||||
"build",
|
||||
"#607D8B",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
30),
|
||||
|
||||
AIDE_DEMENAGEMENT("Aide déménagement", "materielle", "normal",
|
||||
"Aide pour déménagement (transport, main d'œuvre)", "local_shipping", "#795548",
|
||||
false, false, null, null, 7),
|
||||
AIDE_DEMENAGEMENT(
|
||||
"Aide déménagement",
|
||||
"materielle",
|
||||
"normal",
|
||||
"Aide pour déménagement (transport, main d'œuvre)",
|
||||
"local_shipping",
|
||||
"#795548",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
7),
|
||||
|
||||
AIDE_TRAVAUX("Aide travaux", "materielle", "normal",
|
||||
"Aide pour travaux de rénovation ou construction", "construction", "#FF5722",
|
||||
false, false, null, null, 21),
|
||||
AIDE_TRAVAUX(
|
||||
"Aide travaux",
|
||||
"materielle",
|
||||
"normal",
|
||||
"Aide pour travaux de rénovation ou construction",
|
||||
"construction",
|
||||
"#FF5722",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
21),
|
||||
|
||||
// === AIDE PROFESSIONNELLE ===
|
||||
AIDE_RECHERCHE_EMPLOI("Aide recherche d'emploi", "professionnelle", "important",
|
||||
"Aide pour recherche d'emploi et CV", "work", "#3F51B5",
|
||||
false, false, null, null, 30),
|
||||
// === AIDE PROFESSIONNELLE ===
|
||||
AIDE_RECHERCHE_EMPLOI(
|
||||
"Aide recherche d'emploi",
|
||||
"professionnelle",
|
||||
"important",
|
||||
"Aide pour recherche d'emploi et CV",
|
||||
"work",
|
||||
"#3F51B5",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
30),
|
||||
|
||||
FORMATION_PROFESSIONNELLE("Formation professionnelle", "professionnelle", "normal",
|
||||
"Formation et développement des compétences", "school", "#009688",
|
||||
false, false, null, null, 60),
|
||||
FORMATION_PROFESSIONNELLE(
|
||||
"Formation professionnelle",
|
||||
"professionnelle",
|
||||
"normal",
|
||||
"Formation et développement des compétences",
|
||||
"school",
|
||||
"#009688",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
60),
|
||||
|
||||
CONSEIL_JURIDIQUE("Conseil juridique", "professionnelle", "important",
|
||||
"Conseil et assistance juridique", "gavel", "#8BC34A",
|
||||
false, false, null, null, 14),
|
||||
CONSEIL_JURIDIQUE(
|
||||
"Conseil juridique",
|
||||
"professionnelle",
|
||||
"important",
|
||||
"Conseil et assistance juridique",
|
||||
"gavel",
|
||||
"#8BC34A",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
14),
|
||||
|
||||
AIDE_CREATION_ENTREPRISE("Aide création d'entreprise", "professionnelle", "normal",
|
||||
"Accompagnement création d'entreprise", "business", "#CDDC39",
|
||||
false, false, null, null, 90),
|
||||
AIDE_CREATION_ENTREPRISE(
|
||||
"Aide création d'entreprise",
|
||||
"professionnelle",
|
||||
"normal",
|
||||
"Accompagnement création d'entreprise",
|
||||
"business",
|
||||
"#CDDC39",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
90),
|
||||
|
||||
// === AIDE SOCIALE ===
|
||||
GARDE_ENFANTS("Garde d'enfants", "sociale", "normal",
|
||||
"Garde d'enfants ponctuelle ou régulière", "child_care", "#FFC107",
|
||||
false, false, null, null, 7),
|
||||
// === AIDE SOCIALE ===
|
||||
GARDE_ENFANTS(
|
||||
"Garde d'enfants",
|
||||
"sociale",
|
||||
"normal",
|
||||
"Garde d'enfants ponctuelle ou régulière",
|
||||
"child_care",
|
||||
"#FFC107",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
7),
|
||||
|
||||
AIDE_PERSONNES_AGEES("Aide personnes âgées", "sociale", "important",
|
||||
"Aide et accompagnement personnes âgées", "elderly", "#FF9800",
|
||||
false, false, null, null, 30),
|
||||
AIDE_PERSONNES_AGEES(
|
||||
"Aide personnes âgées",
|
||||
"sociale",
|
||||
"important",
|
||||
"Aide et accompagnement personnes âgées",
|
||||
"elderly",
|
||||
"#FF9800",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
30),
|
||||
|
||||
TRANSPORT("Transport", "sociale", "normal",
|
||||
"Aide au transport (covoiturage, accompagnement)", "directions_car", "#2196F3",
|
||||
false, false, null, null, 7),
|
||||
TRANSPORT(
|
||||
"Transport",
|
||||
"sociale",
|
||||
"normal",
|
||||
"Aide au transport (covoiturage, accompagnement)",
|
||||
"directions_car",
|
||||
"#2196F3",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
7),
|
||||
|
||||
AIDE_ADMINISTRATIVE("Aide administrative", "sociale", "normal",
|
||||
"Aide pour démarches administratives", "description", "#9E9E9E",
|
||||
false, false, null, null, 14),
|
||||
AIDE_ADMINISTRATIVE(
|
||||
"Aide administrative",
|
||||
"sociale",
|
||||
"normal",
|
||||
"Aide pour démarches administratives",
|
||||
"description",
|
||||
"#9E9E9E",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
14),
|
||||
|
||||
// === AIDE D'URGENCE ===
|
||||
HEBERGEMENT_URGENCE("Hébergement d'urgence", "urgence", "urgent",
|
||||
"Hébergement temporaire d'urgence", "home", "#F44336",
|
||||
false, true, null, null, 7),
|
||||
// === AIDE D'URGENCE ===
|
||||
HEBERGEMENT_URGENCE(
|
||||
"Hébergement d'urgence",
|
||||
"urgence",
|
||||
"urgent",
|
||||
"Hébergement temporaire d'urgence",
|
||||
"home",
|
||||
"#F44336",
|
||||
false,
|
||||
true,
|
||||
null,
|
||||
null,
|
||||
7),
|
||||
|
||||
AIDE_ALIMENTAIRE("Aide alimentaire", "urgence", "urgent",
|
||||
"Aide alimentaire d'urgence", "restaurant", "#FF5722",
|
||||
false, true, null, null, 3),
|
||||
AIDE_ALIMENTAIRE(
|
||||
"Aide alimentaire",
|
||||
"urgence",
|
||||
"urgent",
|
||||
"Aide alimentaire d'urgence",
|
||||
"restaurant",
|
||||
"#FF5722",
|
||||
false,
|
||||
true,
|
||||
null,
|
||||
null,
|
||||
3),
|
||||
|
||||
AIDE_VESTIMENTAIRE("Aide vestimentaire", "urgence", "normal",
|
||||
"Don de vêtements et accessoires", "checkroom", "#795548",
|
||||
false, false, null, null, 14),
|
||||
AIDE_VESTIMENTAIRE(
|
||||
"Aide vestimentaire",
|
||||
"urgence",
|
||||
"normal",
|
||||
"Don de vêtements et accessoires",
|
||||
"checkroom",
|
||||
"#795548",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
14),
|
||||
|
||||
// === AIDE SPÉCIALISÉE ===
|
||||
SOUTIEN_PSYCHOLOGIQUE("Soutien psychologique", "specialisee", "important",
|
||||
"Soutien et écoute psychologique", "psychology", "#E91E63",
|
||||
false, true, null, null, 30),
|
||||
// === AIDE SPÉCIALISÉE ===
|
||||
SOUTIEN_PSYCHOLOGIQUE(
|
||||
"Soutien psychologique",
|
||||
"specialisee",
|
||||
"important",
|
||||
"Soutien et écoute psychologique",
|
||||
"psychology",
|
||||
"#E91E63",
|
||||
false,
|
||||
true,
|
||||
null,
|
||||
null,
|
||||
30),
|
||||
|
||||
AIDE_NUMERIQUE("Aide numérique", "specialisee", "normal",
|
||||
"Aide pour utilisation outils numériques", "computer", "#607D8B",
|
||||
false, false, null, null, 14),
|
||||
AIDE_NUMERIQUE(
|
||||
"Aide numérique",
|
||||
"specialisee",
|
||||
"normal",
|
||||
"Aide pour utilisation outils numériques",
|
||||
"computer",
|
||||
"#607D8B",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
14),
|
||||
|
||||
TRADUCTION("Traduction", "specialisee", "normal",
|
||||
"Services de traduction et interprétariat", "translate", "#9C27B0",
|
||||
false, false, null, null, 7),
|
||||
TRADUCTION(
|
||||
"Traduction",
|
||||
"specialisee",
|
||||
"normal",
|
||||
"Services de traduction et interprétariat",
|
||||
"translate",
|
||||
"#9C27B0",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
7),
|
||||
|
||||
AUTRE("Autre", "autre", "normal",
|
||||
"Autre type d'aide non catégorisé", "help", "#9E9E9E",
|
||||
false, false, null, null, 14);
|
||||
AUTRE(
|
||||
"Autre",
|
||||
"autre",
|
||||
"normal",
|
||||
"Autre type d'aide non catégorisé",
|
||||
"help",
|
||||
"#9E9E9E",
|
||||
false,
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
14);
|
||||
|
||||
private final String libelle;
|
||||
private final String categorie;
|
||||
private final String priorite;
|
||||
private final String description;
|
||||
private final String icone;
|
||||
private final String couleur;
|
||||
private final boolean necessiteMontant;
|
||||
private final boolean necessiteValidation;
|
||||
private final Double montantMin;
|
||||
private final Double montantMax;
|
||||
private final int delaiReponseJours;
|
||||
private final String libelle;
|
||||
private final String categorie;
|
||||
private final String priorite;
|
||||
private final String description;
|
||||
private final String icone;
|
||||
private final String couleur;
|
||||
private final boolean necessiteMontant;
|
||||
private final boolean necessiteValidation;
|
||||
private final Double montantMin;
|
||||
private final Double montantMax;
|
||||
private final int delaiReponseJours;
|
||||
|
||||
TypeAide(String libelle, String categorie, String priorite, String description,
|
||||
String icone, String couleur, boolean necessiteMontant, boolean necessiteValidation,
|
||||
Double montantMin, Double montantMax, int delaiReponseJours) {
|
||||
this.libelle = libelle;
|
||||
this.categorie = categorie;
|
||||
this.priorite = priorite;
|
||||
this.description = description;
|
||||
this.icone = icone;
|
||||
this.couleur = couleur;
|
||||
this.necessiteMontant = necessiteMontant;
|
||||
this.necessiteValidation = necessiteValidation;
|
||||
this.montantMin = montantMin;
|
||||
this.montantMax = montantMax;
|
||||
this.delaiReponseJours = delaiReponseJours;
|
||||
TypeAide(
|
||||
String libelle,
|
||||
String categorie,
|
||||
String priorite,
|
||||
String description,
|
||||
String icone,
|
||||
String couleur,
|
||||
boolean necessiteMontant,
|
||||
boolean necessiteValidation,
|
||||
Double montantMin,
|
||||
Double montantMax,
|
||||
int delaiReponseJours) {
|
||||
this.libelle = libelle;
|
||||
this.categorie = categorie;
|
||||
this.priorite = priorite;
|
||||
this.description = description;
|
||||
this.icone = icone;
|
||||
this.couleur = couleur;
|
||||
this.necessiteMontant = necessiteMontant;
|
||||
this.necessiteValidation = necessiteValidation;
|
||||
this.montantMin = montantMin;
|
||||
this.montantMax = montantMax;
|
||||
this.delaiReponseJours = delaiReponseJours;
|
||||
}
|
||||
|
||||
// === GETTERS ===
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
|
||||
public String getCategorie() {
|
||||
return categorie;
|
||||
}
|
||||
|
||||
public String getPriorite() {
|
||||
return priorite;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public String getIcone() {
|
||||
return icone;
|
||||
}
|
||||
|
||||
public String getCouleur() {
|
||||
return couleur;
|
||||
}
|
||||
|
||||
public boolean isNecessiteMontant() {
|
||||
return necessiteMontant;
|
||||
}
|
||||
|
||||
public boolean isNecessiteValidation() {
|
||||
return necessiteValidation;
|
||||
}
|
||||
|
||||
public Double getMontantMin() {
|
||||
return montantMin;
|
||||
}
|
||||
|
||||
public Double getMontantMax() {
|
||||
return montantMax;
|
||||
}
|
||||
|
||||
public int getDelaiReponseJours() {
|
||||
return delaiReponseJours;
|
||||
}
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/** Vérifie si le type d'aide est urgent */
|
||||
public boolean isUrgent() {
|
||||
return "urgent".equals(priorite);
|
||||
}
|
||||
|
||||
/** Vérifie si le type d'aide est financier */
|
||||
public boolean isFinancier() {
|
||||
return "financiere".equals(categorie);
|
||||
}
|
||||
|
||||
/** Vérifie si le type d'aide est matériel */
|
||||
public boolean isMateriel() {
|
||||
return "materielle".equals(categorie);
|
||||
}
|
||||
|
||||
/** Vérifie si le montant est dans la fourchette autorisée */
|
||||
public boolean isMontantValide(Double montant) {
|
||||
if (!necessiteMontant || montant == null) return true;
|
||||
if (montantMin != null && montant < montantMin) return false;
|
||||
if (montantMax != null && montant > montantMax) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Retourne le niveau de priorité numérique */
|
||||
public int getNiveauPriorite() {
|
||||
return switch (priorite) {
|
||||
case "urgent" -> 1;
|
||||
case "important" -> 2;
|
||||
case "normal" -> 3;
|
||||
default -> 3;
|
||||
};
|
||||
}
|
||||
|
||||
/** Retourne la date limite de réponse */
|
||||
public java.time.LocalDateTime getDateLimiteReponse() {
|
||||
return java.time.LocalDateTime.now().plusDays(delaiReponseJours);
|
||||
}
|
||||
|
||||
/** Retourne les types d'aide par catégorie */
|
||||
public static java.util.List<TypeAide> getParCategorie(String categorie) {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(type -> type.getCategorie().equals(categorie))
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Retourne les types d'aide urgents */
|
||||
public static java.util.List<TypeAide> getUrgents() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(TypeAide::isUrgent)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Retourne les types d'aide financiers */
|
||||
public static java.util.List<TypeAide> getFinanciers() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(TypeAide::isFinancier)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/** Retourne les catégories disponibles */
|
||||
public static java.util.Set<String> getCategories() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.map(TypeAide::getCategorie)
|
||||
.collect(java.util.stream.Collectors.toSet());
|
||||
}
|
||||
|
||||
/** Retourne le libellé de la catégorie */
|
||||
public String getLibelleCategorie() {
|
||||
return switch (categorie) {
|
||||
case "financiere" -> "Aide financière";
|
||||
case "materielle" -> "Aide matérielle";
|
||||
case "professionnelle" -> "Aide professionnelle";
|
||||
case "sociale" -> "Aide sociale";
|
||||
case "urgence" -> "Aide d'urgence";
|
||||
case "specialisee" -> "Aide spécialisée";
|
||||
case "autre" -> "Autre";
|
||||
default -> categorie;
|
||||
};
|
||||
}
|
||||
|
||||
/** Retourne l'unité du montant si applicable */
|
||||
public String getUniteMontant() {
|
||||
return necessiteMontant ? "FCFA" : null;
|
||||
}
|
||||
|
||||
/** Retourne le message de validation du montant */
|
||||
public String getMessageValidationMontant(Double montant) {
|
||||
if (!necessiteMontant) return null;
|
||||
if (montant == null) return "Le montant est obligatoire";
|
||||
if (montantMin != null && montant < montantMin) {
|
||||
return String.format("Le montant minimum est de %.0f FCFA", montantMin);
|
||||
}
|
||||
|
||||
// === GETTERS ===
|
||||
|
||||
public String getLibelle() { return libelle; }
|
||||
public String getCategorie() { return categorie; }
|
||||
public String getPriorite() { return priorite; }
|
||||
public String getDescription() { return description; }
|
||||
public String getIcone() { return icone; }
|
||||
public String getCouleur() { return couleur; }
|
||||
public boolean isNecessiteMontant() { return necessiteMontant; }
|
||||
public boolean isNecessiteValidation() { return necessiteValidation; }
|
||||
public Double getMontantMin() { return montantMin; }
|
||||
public Double getMontantMax() { return montantMax; }
|
||||
public int getDelaiReponseJours() { return delaiReponseJours; }
|
||||
|
||||
// === MÉTHODES UTILITAIRES ===
|
||||
|
||||
/**
|
||||
* Vérifie si le type d'aide est urgent
|
||||
*/
|
||||
public boolean isUrgent() {
|
||||
return "urgent".equals(priorite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le type d'aide est financier
|
||||
*/
|
||||
public boolean isFinancier() {
|
||||
return "financiere".equals(categorie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le type d'aide est matériel
|
||||
*/
|
||||
public boolean isMateriel() {
|
||||
return "materielle".equals(categorie);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le montant est dans la fourchette autorisée
|
||||
*/
|
||||
public boolean isMontantValide(Double montant) {
|
||||
if (!necessiteMontant || montant == null) return true;
|
||||
if (montantMin != null && montant < montantMin) return false;
|
||||
if (montantMax != null && montant > montantMax) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le niveau de priorité numérique
|
||||
*/
|
||||
public int getNiveauPriorite() {
|
||||
return switch (priorite) {
|
||||
case "urgent" -> 1;
|
||||
case "important" -> 2;
|
||||
case "normal" -> 3;
|
||||
default -> 3;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la date limite de réponse
|
||||
*/
|
||||
public java.time.LocalDateTime getDateLimiteReponse() {
|
||||
return java.time.LocalDateTime.now().plusDays(delaiReponseJours);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les types d'aide par catégorie
|
||||
*/
|
||||
public static java.util.List<TypeAide> getParCategorie(String categorie) {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(type -> type.getCategorie().equals(categorie))
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les types d'aide urgents
|
||||
*/
|
||||
public static java.util.List<TypeAide> getUrgents() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(TypeAide::isUrgent)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les types d'aide financiers
|
||||
*/
|
||||
public static java.util.List<TypeAide> getFinanciers() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.filter(TypeAide::isFinancier)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les catégories disponibles
|
||||
*/
|
||||
public static java.util.Set<String> getCategories() {
|
||||
return java.util.Arrays.stream(values())
|
||||
.map(TypeAide::getCategorie)
|
||||
.collect(java.util.stream.Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le libellé de la catégorie
|
||||
*/
|
||||
public String getLibelleCategorie() {
|
||||
return switch (categorie) {
|
||||
case "financiere" -> "Aide financière";
|
||||
case "materielle" -> "Aide matérielle";
|
||||
case "professionnelle" -> "Aide professionnelle";
|
||||
case "sociale" -> "Aide sociale";
|
||||
case "urgence" -> "Aide d'urgence";
|
||||
case "specialisee" -> "Aide spécialisée";
|
||||
case "autre" -> "Autre";
|
||||
default -> categorie;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'unité du montant si applicable
|
||||
*/
|
||||
public String getUniteMontant() {
|
||||
return necessiteMontant ? "FCFA" : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le message de validation du montant
|
||||
*/
|
||||
public String getMessageValidationMontant(Double montant) {
|
||||
if (!necessiteMontant) return null;
|
||||
if (montant == null) return "Le montant est obligatoire";
|
||||
if (montantMin != null && montant < montantMin) {
|
||||
return String.format("Le montant minimum est de %.0f FCFA", montantMin);
|
||||
}
|
||||
if (montantMax != null && montant > montantMax) {
|
||||
return String.format("Le montant maximum est de %.0f FCFA", montantMax);
|
||||
}
|
||||
return null;
|
||||
if (montantMax != null && montant > montantMax) {
|
||||
return String.format("Le montant maximum est de %.0f FCFA", montantMax);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
package dev.lions.unionflow.server.api.validation;
|
||||
|
||||
/**
|
||||
* Constantes pour la validation des DTOs
|
||||
*
|
||||
* <p>Cette classe centralise toutes les contraintes de validation pour assurer la cohérence entre
|
||||
* les différents DTOs du système.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
public final class ValidationConstants {
|
||||
|
||||
private ValidationConstants() {
|
||||
// Classe utilitaire - constructeur privé
|
||||
}
|
||||
|
||||
// === CONTRAINTES DE TAILLE POUR LES TEXTES ===
|
||||
|
||||
/** Titre court (événements, aides, etc.) */
|
||||
public static final int TITRE_MIN_LENGTH = 5;
|
||||
|
||||
public static final int TITRE_MAX_LENGTH = 100;
|
||||
public static final String TITRE_SIZE_MESSAGE =
|
||||
"Le titre doit contenir entre "
|
||||
+ TITRE_MIN_LENGTH
|
||||
+ " et "
|
||||
+ TITRE_MAX_LENGTH
|
||||
+ " caractères";
|
||||
|
||||
/** Nom d'organisation */
|
||||
public static final int NOM_ORGANISATION_MIN_LENGTH = 2;
|
||||
|
||||
public static final int NOM_ORGANISATION_MAX_LENGTH = 200;
|
||||
public static final String NOM_ORGANISATION_SIZE_MESSAGE =
|
||||
"Le nom doit contenir entre "
|
||||
+ NOM_ORGANISATION_MIN_LENGTH
|
||||
+ " et "
|
||||
+ NOM_ORGANISATION_MAX_LENGTH
|
||||
+ " caractères";
|
||||
|
||||
/** Description standard */
|
||||
public static final int DESCRIPTION_MIN_LENGTH = 20;
|
||||
|
||||
public static final int DESCRIPTION_MAX_LENGTH = 2000;
|
||||
public static final String DESCRIPTION_SIZE_MESSAGE =
|
||||
"La description doit contenir entre "
|
||||
+ DESCRIPTION_MIN_LENGTH
|
||||
+ " et "
|
||||
+ DESCRIPTION_MAX_LENGTH
|
||||
+ " caractères";
|
||||
|
||||
/** Description courte (événements) */
|
||||
public static final int DESCRIPTION_COURTE_MAX_LENGTH = 1000;
|
||||
|
||||
public static final String DESCRIPTION_COURTE_SIZE_MESSAGE =
|
||||
"La description ne peut pas dépasser " + DESCRIPTION_COURTE_MAX_LENGTH + " caractères";
|
||||
|
||||
/** Justification */
|
||||
public static final int JUSTIFICATION_MAX_LENGTH = 1000;
|
||||
|
||||
public static final String JUSTIFICATION_SIZE_MESSAGE =
|
||||
"La justification ne peut pas dépasser " + JUSTIFICATION_MAX_LENGTH + " caractères";
|
||||
|
||||
/** Commentaires */
|
||||
public static final int COMMENTAIRES_MAX_LENGTH = 1000;
|
||||
|
||||
public static final String COMMENTAIRES_SIZE_MESSAGE =
|
||||
"Les commentaires ne peuvent pas dépasser " + COMMENTAIRES_MAX_LENGTH + " caractères";
|
||||
|
||||
/** Raison de rejet */
|
||||
public static final int RAISON_REJET_MAX_LENGTH = 500;
|
||||
|
||||
public static final String RAISON_REJET_SIZE_MESSAGE =
|
||||
"La raison du rejet ne peut pas dépasser " + RAISON_REJET_MAX_LENGTH + " caractères";
|
||||
|
||||
/** Adresse */
|
||||
public static final int ADRESSE_MAX_LENGTH = 200;
|
||||
|
||||
public static final String ADRESSE_SIZE_MESSAGE =
|
||||
"L'adresse ne peut pas dépasser " + ADRESSE_MAX_LENGTH + " caractères";
|
||||
|
||||
/** Ville, région, quartier */
|
||||
public static final int LOCALISATION_MAX_LENGTH = 50;
|
||||
|
||||
public static final String VILLE_SIZE_MESSAGE =
|
||||
"La ville ne peut pas dépasser " + LOCALISATION_MAX_LENGTH + " caractères";
|
||||
public static final String REGION_SIZE_MESSAGE =
|
||||
"La région ne peut pas dépasser " + LOCALISATION_MAX_LENGTH + " caractères";
|
||||
public static final String QUARTIER_SIZE_MESSAGE =
|
||||
"Le quartier ne peut pas dépasser " + LOCALISATION_MAX_LENGTH + " caractères";
|
||||
|
||||
/** Rôle */
|
||||
public static final int ROLE_MAX_LENGTH = 50;
|
||||
|
||||
public static final String ROLE_SIZE_MESSAGE =
|
||||
"Le rôle ne peut pas dépasser " + ROLE_MAX_LENGTH + " caractères";
|
||||
|
||||
/** URL */
|
||||
public static final int URL_MAX_LENGTH = 255;
|
||||
|
||||
public static final String URL_SIZE_MESSAGE =
|
||||
"L'URL ne peut pas dépasser " + URL_MAX_LENGTH + " caractères";
|
||||
|
||||
/** Email */
|
||||
public static final int EMAIL_MAX_LENGTH = 100;
|
||||
|
||||
public static final String EMAIL_SIZE_MESSAGE =
|
||||
"L'email ne peut pas dépasser " + EMAIL_MAX_LENGTH + " caractères";
|
||||
|
||||
/** Nom et prénom */
|
||||
public static final int NOM_PRENOM_MIN_LENGTH = 2;
|
||||
|
||||
public static final int NOM_PRENOM_MAX_LENGTH = 50;
|
||||
public static final String NOM_SIZE_MESSAGE =
|
||||
"Le nom doit contenir entre "
|
||||
+ NOM_PRENOM_MIN_LENGTH
|
||||
+ " et "
|
||||
+ NOM_PRENOM_MAX_LENGTH
|
||||
+ " caractères";
|
||||
public static final String PRENOM_SIZE_MESSAGE =
|
||||
"Le prénom doit contenir entre "
|
||||
+ NOM_PRENOM_MIN_LENGTH
|
||||
+ " et "
|
||||
+ NOM_PRENOM_MAX_LENGTH
|
||||
+ " caractères";
|
||||
|
||||
// === PATTERNS DE VALIDATION ===
|
||||
|
||||
/** Numéro de téléphone international */
|
||||
public static final String TELEPHONE_PATTERN = "^\\+?[0-9]{8,15}$";
|
||||
|
||||
public static final String TELEPHONE_MESSAGE =
|
||||
"Le numéro de téléphone doit contenir entre 8 et 15 chiffres, avec un indicatif optionnel"
|
||||
+ " (+)";
|
||||
|
||||
/** Code devise ISO */
|
||||
public static final String DEVISE_PATTERN = "^[A-Z]{3}$";
|
||||
|
||||
public static final String DEVISE_MESSAGE =
|
||||
"La devise doit être un code ISO à 3 lettres majuscules";
|
||||
|
||||
/** Numéro de référence aide */
|
||||
public static final String REFERENCE_AIDE_PATTERN = "^DA-\\d{4}-\\d{6}$";
|
||||
|
||||
public static final String REFERENCE_AIDE_MESSAGE =
|
||||
"Le numéro de référence doit suivre le format DA-YYYY-NNNNNN";
|
||||
|
||||
/** Numéro de membre */
|
||||
public static final String NUMERO_MEMBRE_PATTERN = "^UF-\\d{4}-[A-Z0-9]{8}$";
|
||||
|
||||
public static final String NUMERO_MEMBRE_MESSAGE =
|
||||
"Format de numéro de membre invalide (UF-YYYY-XXXXXXXX)";
|
||||
|
||||
/** Couleur hexadécimale */
|
||||
public static final String COULEUR_HEX_PATTERN = "^#[0-9A-Fa-f]{6}$";
|
||||
|
||||
public static final String COULEUR_HEX_MESSAGE = "Format de couleur invalide (format: #RRGGBB)";
|
||||
|
||||
// === CONTRAINTES NUMÉRIQUES ===
|
||||
|
||||
/** Montant minimum */
|
||||
public static final String MONTANT_MIN_VALUE = "0.0";
|
||||
|
||||
public static final String MONTANT_POSITIF_MESSAGE = "Le montant doit être positif";
|
||||
|
||||
/** Contraintes pour les montants */
|
||||
public static final int MONTANT_INTEGER_DIGITS = 10;
|
||||
|
||||
public static final int MONTANT_FRACTION_DIGITS = 2;
|
||||
public static final String MONTANT_DIGITS_MESSAGE =
|
||||
"Le montant doit avoir au maximum "
|
||||
+ MONTANT_INTEGER_DIGITS
|
||||
+ " chiffres entiers et "
|
||||
+ MONTANT_FRACTION_DIGITS
|
||||
+ " décimales";
|
||||
|
||||
// === MESSAGES D'ERREUR STANDARD ===
|
||||
|
||||
public static final String OBLIGATOIRE_MESSAGE = " est obligatoire";
|
||||
public static final String EMAIL_FORMAT_MESSAGE = "L'adresse email n'est pas valide";
|
||||
public static final String DATE_PASSEE_MESSAGE = "La date doit être dans le passé";
|
||||
public static final String DATE_FUTURE_MESSAGE = "La date doit être dans le futur";
|
||||
|
||||
// === CONTRAINTES SPÉCIFIQUES ===
|
||||
|
||||
/** Documents joints */
|
||||
public static final int DOCUMENTS_JOINTS_MAX_LENGTH = 1000;
|
||||
|
||||
public static final String DOCUMENTS_JOINTS_SIZE_MESSAGE =
|
||||
"La liste des documents ne peut pas dépasser " + DOCUMENTS_JOINTS_MAX_LENGTH + " caractères";
|
||||
|
||||
/** Mode de versement */
|
||||
public static final int MODE_VERSEMENT_MAX_LENGTH = 50;
|
||||
|
||||
public static final String MODE_VERSEMENT_SIZE_MESSAGE =
|
||||
"Le mode de versement ne peut pas dépasser " + MODE_VERSEMENT_MAX_LENGTH + " caractères";
|
||||
|
||||
/** Numéro de transaction */
|
||||
public static final int NUMERO_TRANSACTION_MAX_LENGTH = 100;
|
||||
|
||||
public static final String NUMERO_TRANSACTION_SIZE_MESSAGE =
|
||||
"Le numéro de transaction ne peut pas dépasser "
|
||||
+ NUMERO_TRANSACTION_MAX_LENGTH
|
||||
+ " caractères";
|
||||
|
||||
/** Numéro d'enregistrement */
|
||||
public static final int NUMERO_ENREGISTREMENT_MAX_LENGTH = 100;
|
||||
|
||||
public static final String NUMERO_ENREGISTREMENT_SIZE_MESSAGE =
|
||||
"Le numéro d'enregistrement ne peut pas dépasser "
|
||||
+ NUMERO_ENREGISTREMENT_MAX_LENGTH
|
||||
+ " caractères";
|
||||
|
||||
/** Nom court d'organisation */
|
||||
public static final int NOM_COURT_MAX_LENGTH = 50;
|
||||
|
||||
public static final String NOM_COURT_SIZE_MESSAGE =
|
||||
"Le nom court ne peut pas dépasser " + NOM_COURT_MAX_LENGTH + " caractères";
|
||||
|
||||
/** Instructions et matériel */
|
||||
public static final int INSTRUCTIONS_MAX_LENGTH = 500;
|
||||
|
||||
public static final String INSTRUCTIONS_SIZE_MESSAGE =
|
||||
"Les instructions ne peuvent pas dépasser " + INSTRUCTIONS_MAX_LENGTH + " caractères";
|
||||
|
||||
/** Conditions météo */
|
||||
public static final int CONDITIONS_METEO_MAX_LENGTH = 100;
|
||||
|
||||
public static final String CONDITIONS_METEO_SIZE_MESSAGE =
|
||||
"Les conditions météo ne peuvent pas dépasser " + CONDITIONS_METEO_MAX_LENGTH + " caractères";
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package dev.lions.unionflow.server.api;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.dto.evenement.EvenementDTO;
|
||||
import dev.lions.unionflow.server.api.dto.solidarite.DemandeAideDTO;
|
||||
import dev.lions.unionflow.server.api.dto.solidarite.PropositionAideDTO;
|
||||
import dev.lions.unionflow.server.api.dto.solidarite.aide.AideDTO;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.PrioriteEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.StatutEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.TypeEvenementMetier;
|
||||
import dev.lions.unionflow.server.api.validation.ValidationConstants;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Test de compilation pour vérifier que tous les DTOs compilent correctement
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@DisplayName("Tests de Compilation")
|
||||
class CompilationTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test compilation EvenementDTO")
|
||||
void testCompilationEvenementDTO() {
|
||||
EvenementDTO evenement = new EvenementDTO();
|
||||
evenement.setTitre("Test Formation");
|
||||
evenement.setStatut(StatutEvenement.PLANIFIE);
|
||||
evenement.setPriorite(PrioriteEvenement.NORMALE);
|
||||
evenement.setTypeEvenement(TypeEvenementMetier.FORMATION);
|
||||
evenement.setDateDebut(LocalDate.now().plusDays(30));
|
||||
|
||||
// Test des méthodes métier
|
||||
assertThat(evenement.estEnCours()).isFalse();
|
||||
assertThat(evenement.getStatutLibelle()).isEqualTo("Planifié");
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Formation");
|
||||
|
||||
// Test des setters
|
||||
evenement.setStatut(StatutEvenement.CONFIRME);
|
||||
assertThat(evenement.getStatut()).isEqualTo(StatutEvenement.CONFIRME);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test compilation DemandeAideDTO")
|
||||
void testCompilationDemandeAideDTO() {
|
||||
DemandeAideDTO demande = new DemandeAideDTO();
|
||||
demande.setTitre("Test Demande");
|
||||
demande.setMontantDemande(new BigDecimal("50000"));
|
||||
demande.setDevise("XOF");
|
||||
|
||||
// Test des méthodes métier
|
||||
assertThat(demande.getId()).isNotNull(); // BaseDTO génère automatiquement un UUID
|
||||
assertThat(demande.getVersion()).isEqualTo(0L);
|
||||
|
||||
// Test de la méthode marquerCommeModifie
|
||||
demande.marquerCommeModifie("testUser");
|
||||
assertThat(demande.getModifiePar()).isEqualTo("testUser");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test compilation PropositionAideDTO")
|
||||
void testCompilationPropositionAideDTO() {
|
||||
PropositionAideDTO proposition = new PropositionAideDTO();
|
||||
proposition.setTitre("Test Proposition");
|
||||
proposition.setMontantMaximum(new BigDecimal("100000"));
|
||||
|
||||
// Vérifier que le type est correct
|
||||
assertThat(proposition.getMontantMaximum()).isInstanceOf(BigDecimal.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test compilation AideDTO (deprecated)")
|
||||
void testCompilationAideDTO() {
|
||||
@SuppressWarnings("deprecation")
|
||||
AideDTO aide = new AideDTO();
|
||||
aide.setTitre("Test Aide");
|
||||
|
||||
// Test des méthodes métier
|
||||
assertThat(aide.getTypeAideLibelle()).isNotNull();
|
||||
assertThat(aide.getStatutLibelle()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test compilation ValidationConstants")
|
||||
void testCompilationValidationConstants() {
|
||||
// Test que les constantes sont accessibles
|
||||
assertThat(ValidationConstants.TITRE_MIN_LENGTH).isEqualTo(5);
|
||||
assertThat(ValidationConstants.TITRE_MAX_LENGTH).isEqualTo(100);
|
||||
assertThat(ValidationConstants.TELEPHONE_PATTERN).isNotNull();
|
||||
assertThat(ValidationConstants.DEVISE_PATTERN).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test compilation énumérations")
|
||||
void testCompilationEnumerations() {
|
||||
// Test StatutEvenement
|
||||
StatutEvenement statut = StatutEvenement.PLANIFIE;
|
||||
assertThat(statut.getLibelle()).isEqualTo("Planifié");
|
||||
assertThat(statut.permetModification()).isTrue();
|
||||
|
||||
// Test PrioriteEvenement
|
||||
PrioriteEvenement priorite = PrioriteEvenement.HAUTE;
|
||||
assertThat(priorite.getLibelle()).isEqualTo("Haute");
|
||||
assertThat(priorite.isUrgente()).isTrue(); // Amélioration TDD : HAUTE est maintenant urgente
|
||||
|
||||
// Test TypeEvenementMetier
|
||||
TypeEvenementMetier type = TypeEvenementMetier.FORMATION;
|
||||
assertThat(type.getLibelle()).isEqualTo("Formation");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test intégration complète")
|
||||
void testIntegrationComplete() {
|
||||
// Créer un événement complet
|
||||
EvenementDTO evenement =
|
||||
new EvenementDTO(
|
||||
"Formation Leadership",
|
||||
TypeEvenementMetier.FORMATION,
|
||||
LocalDate.now().plusDays(30),
|
||||
"Centre de Formation");
|
||||
evenement.setStatut(StatutEvenement.PLANIFIE);
|
||||
evenement.setPriorite(PrioriteEvenement.HAUTE);
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(0);
|
||||
evenement.setBudget(new BigDecimal("500000"));
|
||||
evenement.setCodeDevise("XOF");
|
||||
evenement.setAssociationId(UUID.randomUUID());
|
||||
|
||||
// Vérifier que tout fonctionne
|
||||
assertThat(evenement.estEnCours()).isFalse();
|
||||
assertThat(evenement.estComplet()).isFalse();
|
||||
assertThat(evenement.sontInscriptionsOuvertes()).isTrue();
|
||||
|
||||
// Créer une demande d'aide complète
|
||||
DemandeAideDTO demande = new DemandeAideDTO();
|
||||
demande.setTitre("Aide Médicale Urgente");
|
||||
demande.setDescription("Besoin d'aide pour frais médicaux");
|
||||
demande.setMontantDemande(new BigDecimal("250000"));
|
||||
demande.setDevise("XOF");
|
||||
demande.setMembreDemandeurId(UUID.randomUUID());
|
||||
demande.setAssociationId(UUID.randomUUID());
|
||||
|
||||
// Vérifier que tout fonctionne
|
||||
assertThat(demande.getId()).isNotNull();
|
||||
assertThat(demande.getVersion()).isEqualTo(0L);
|
||||
assertThat(demande.getMontantDemande()).isEqualTo(new BigDecimal("250000"));
|
||||
}
|
||||
}
|
||||
@@ -224,10 +224,10 @@ class BaseDTOTest {
|
||||
void testEqualsMemeId() {
|
||||
UUID id = UUID.randomUUID();
|
||||
baseDto.setId(id);
|
||||
|
||||
|
||||
TestableBaseDTO autre = new TestableBaseDTO();
|
||||
autre.setId(id);
|
||||
|
||||
|
||||
assertThat(baseDto).isEqualTo(autre);
|
||||
assertThat(baseDto.hashCode()).isEqualTo(autre.hashCode());
|
||||
}
|
||||
@@ -236,10 +236,10 @@ class BaseDTOTest {
|
||||
@DisplayName("Test equals - IDs différents")
|
||||
void testEqualsIdsDifferents() {
|
||||
baseDto.setId(UUID.randomUUID());
|
||||
|
||||
|
||||
TestableBaseDTO autre = new TestableBaseDTO();
|
||||
autre.setId(UUID.randomUUID());
|
||||
|
||||
|
||||
assertThat(baseDto).isNotEqualTo(autre);
|
||||
}
|
||||
|
||||
@@ -247,10 +247,10 @@ class BaseDTOTest {
|
||||
@DisplayName("Test equals - ID null")
|
||||
void testEqualsIdNull() {
|
||||
baseDto.setId(null);
|
||||
|
||||
|
||||
TestableBaseDTO autre = new TestableBaseDTO();
|
||||
autre.setId(null);
|
||||
|
||||
|
||||
assertThat(baseDto).isNotEqualTo(autre);
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ class BaseDTOTest {
|
||||
baseDto.setId(id);
|
||||
baseDto.setVersion(2L);
|
||||
baseDto.setActif(true);
|
||||
|
||||
|
||||
String result = baseDto.toString();
|
||||
assertThat(result).contains("TestableBaseDTO");
|
||||
assertThat(result).contains("id=" + id.toString());
|
||||
@@ -308,9 +308,7 @@ class BaseDTOTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Classe de test concrète pour tester BaseDTO.
|
||||
*/
|
||||
/** Classe de test concrète pour tester BaseDTO. */
|
||||
private static class TestableBaseDTO extends BaseDTO {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
@@ -1,672 +0,0 @@
|
||||
package dev.lions.unionflow.server.api.dto.evenement;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires complets pour EvenementDTO.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-10
|
||||
*/
|
||||
@DisplayName("Tests EvenementDTO")
|
||||
class EvenementDTOBasicTest {
|
||||
|
||||
private EvenementDTO evenement;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
evenement = new EvenementDTO();
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests de Construction")
|
||||
class ConstructionTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Constructeur par défaut - Initialisation correcte")
|
||||
void testConstructeurParDefaut() {
|
||||
EvenementDTO newEvenement = new EvenementDTO();
|
||||
|
||||
assertThat(newEvenement.getId()).isNotNull();
|
||||
assertThat(newEvenement.getDateCreation()).isNotNull();
|
||||
assertThat(newEvenement.isActif()).isTrue();
|
||||
assertThat(newEvenement.getVersion()).isEqualTo(0L);
|
||||
assertThat(newEvenement.getStatut()).isEqualTo("PLANIFIE");
|
||||
assertThat(newEvenement.getPriorite()).isEqualTo("NORMALE");
|
||||
assertThat(newEvenement.getParticipantsInscrits()).isEqualTo(0);
|
||||
assertThat(newEvenement.getParticipantsPresents()).isEqualTo(0);
|
||||
assertThat(newEvenement.getInscriptionObligatoire()).isFalse();
|
||||
assertThat(newEvenement.getEvenementPublic()).isTrue();
|
||||
assertThat(newEvenement.getRecurrent()).isFalse();
|
||||
assertThat(newEvenement.getCodeDevise()).isEqualTo("XOF");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Constructeur avec paramètres - Initialisation correcte")
|
||||
void testConstructeurAvecParametres() {
|
||||
String titre = "Réunion mensuelle";
|
||||
String typeEvenement = "REUNION_BUREAU";
|
||||
LocalDate dateDebut = LocalDate.now().plusDays(7);
|
||||
String lieu = "Salle de conférence";
|
||||
|
||||
EvenementDTO newEvenement = new EvenementDTO(titre, typeEvenement, dateDebut, lieu);
|
||||
|
||||
assertThat(newEvenement.getTitre()).isEqualTo(titre);
|
||||
assertThat(newEvenement.getTypeEvenement()).isEqualTo(typeEvenement);
|
||||
assertThat(newEvenement.getDateDebut()).isEqualTo(dateDebut);
|
||||
assertThat(newEvenement.getLieu()).isEqualTo(lieu);
|
||||
assertThat(newEvenement.getStatut()).isEqualTo("PLANIFIE");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests Getters/Setters")
|
||||
class GettersSettersTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test tous les getters/setters")
|
||||
void testTousLesGettersSetters() {
|
||||
// Données de test
|
||||
String titre = "Formation Leadership";
|
||||
String description = "Formation sur le leadership associatif";
|
||||
String typeEvenement = "FORMATION";
|
||||
String statut = "EN_COURS";
|
||||
String priorite = "HAUTE";
|
||||
LocalDate dateDebut = LocalDate.now().plusDays(1);
|
||||
LocalDate dateFin = LocalDate.now().plusDays(2);
|
||||
LocalTime heureDebut = LocalTime.of(9, 0);
|
||||
LocalTime heureFin = LocalTime.of(17, 0);
|
||||
String lieu = "Centre de formation";
|
||||
String adresse = "123 Avenue de la République";
|
||||
String ville = "Dakar";
|
||||
String region = "Dakar";
|
||||
BigDecimal latitude = new BigDecimal("14.6937");
|
||||
BigDecimal longitude = new BigDecimal("-17.4441");
|
||||
UUID associationId = UUID.randomUUID();
|
||||
String nomAssociation = "Lions Club Dakar";
|
||||
String organisateur = "Jean Dupont";
|
||||
String emailOrganisateur = "jean.dupont@example.com";
|
||||
String telephoneOrganisateur = "+221701234567";
|
||||
Integer capaciteMax = 50;
|
||||
Integer participantsInscrits = 25;
|
||||
Integer participantsPresents = 20;
|
||||
BigDecimal budget = new BigDecimal("500000.00");
|
||||
BigDecimal coutReel = new BigDecimal("450000.00");
|
||||
String codeDevise = "XOF";
|
||||
Boolean inscriptionObligatoire = true;
|
||||
LocalDate dateLimiteInscription = LocalDate.now().plusDays(5);
|
||||
Boolean evenementPublic = false;
|
||||
Boolean recurrent = true;
|
||||
String frequenceRecurrence = "MENSUELLE";
|
||||
String instructions = "Apporter un carnet de notes";
|
||||
String materielNecessaire = "Projecteur, tableau";
|
||||
String conditionsMeteo = "Intérieur";
|
||||
String imageUrl = "https://example.com/image.jpg";
|
||||
String couleurTheme = "#FF5733";
|
||||
LocalDateTime dateAnnulation = LocalDateTime.now();
|
||||
String raisonAnnulation = "Conditions météo";
|
||||
Long annulePar = 123L;
|
||||
String nomAnnulateur = "Admin";
|
||||
|
||||
// Test des setters
|
||||
evenement.setTitre(titre);
|
||||
evenement.setDescription(description);
|
||||
evenement.setTypeEvenement(typeEvenement);
|
||||
evenement.setStatut(statut);
|
||||
evenement.setPriorite(priorite);
|
||||
evenement.setDateDebut(dateDebut);
|
||||
evenement.setDateFin(dateFin);
|
||||
evenement.setHeureDebut(heureDebut);
|
||||
evenement.setHeureFin(heureFin);
|
||||
evenement.setLieu(lieu);
|
||||
evenement.setAdresse(adresse);
|
||||
evenement.setVille(ville);
|
||||
evenement.setRegion(region);
|
||||
evenement.setLatitude(latitude);
|
||||
evenement.setLongitude(longitude);
|
||||
evenement.setAssociationId(associationId);
|
||||
evenement.setNomAssociation(nomAssociation);
|
||||
evenement.setOrganisateur(organisateur);
|
||||
evenement.setEmailOrganisateur(emailOrganisateur);
|
||||
evenement.setTelephoneOrganisateur(telephoneOrganisateur);
|
||||
evenement.setCapaciteMax(capaciteMax);
|
||||
evenement.setParticipantsInscrits(participantsInscrits);
|
||||
evenement.setParticipantsPresents(participantsPresents);
|
||||
evenement.setBudget(budget);
|
||||
evenement.setCoutReel(coutReel);
|
||||
evenement.setCodeDevise(codeDevise);
|
||||
evenement.setInscriptionObligatoire(inscriptionObligatoire);
|
||||
evenement.setDateLimiteInscription(dateLimiteInscription);
|
||||
evenement.setEvenementPublic(evenementPublic);
|
||||
evenement.setRecurrent(recurrent);
|
||||
evenement.setFrequenceRecurrence(frequenceRecurrence);
|
||||
evenement.setInstructions(instructions);
|
||||
evenement.setMaterielNecessaire(materielNecessaire);
|
||||
evenement.setConditionsMeteo(conditionsMeteo);
|
||||
evenement.setImageUrl(imageUrl);
|
||||
evenement.setCouleurTheme(couleurTheme);
|
||||
evenement.setDateAnnulation(dateAnnulation);
|
||||
evenement.setRaisonAnnulation(raisonAnnulation);
|
||||
evenement.setAnnulePar(annulePar);
|
||||
evenement.setNomAnnulateur(nomAnnulateur);
|
||||
|
||||
// Test des getters
|
||||
assertThat(evenement.getTitre()).isEqualTo(titre);
|
||||
assertThat(evenement.getDescription()).isEqualTo(description);
|
||||
assertThat(evenement.getTypeEvenement()).isEqualTo(typeEvenement);
|
||||
assertThat(evenement.getStatut()).isEqualTo(statut);
|
||||
assertThat(evenement.getPriorite()).isEqualTo(priorite);
|
||||
assertThat(evenement.getDateDebut()).isEqualTo(dateDebut);
|
||||
assertThat(evenement.getDateFin()).isEqualTo(dateFin);
|
||||
assertThat(evenement.getHeureDebut()).isEqualTo(heureDebut);
|
||||
assertThat(evenement.getHeureFin()).isEqualTo(heureFin);
|
||||
assertThat(evenement.getLieu()).isEqualTo(lieu);
|
||||
assertThat(evenement.getAdresse()).isEqualTo(adresse);
|
||||
assertThat(evenement.getVille()).isEqualTo(ville);
|
||||
assertThat(evenement.getRegion()).isEqualTo(region);
|
||||
assertThat(evenement.getLatitude()).isEqualTo(latitude);
|
||||
assertThat(evenement.getLongitude()).isEqualTo(longitude);
|
||||
assertThat(evenement.getAssociationId()).isEqualTo(associationId);
|
||||
assertThat(evenement.getNomAssociation()).isEqualTo(nomAssociation);
|
||||
assertThat(evenement.getOrganisateur()).isEqualTo(organisateur);
|
||||
assertThat(evenement.getEmailOrganisateur()).isEqualTo(emailOrganisateur);
|
||||
assertThat(evenement.getTelephoneOrganisateur()).isEqualTo(telephoneOrganisateur);
|
||||
assertThat(evenement.getCapaciteMax()).isEqualTo(capaciteMax);
|
||||
assertThat(evenement.getParticipantsInscrits()).isEqualTo(participantsInscrits);
|
||||
assertThat(evenement.getParticipantsPresents()).isEqualTo(participantsPresents);
|
||||
assertThat(evenement.getBudget()).isEqualTo(budget);
|
||||
assertThat(evenement.getCoutReel()).isEqualTo(coutReel);
|
||||
assertThat(evenement.getCodeDevise()).isEqualTo(codeDevise);
|
||||
assertThat(evenement.getInscriptionObligatoire()).isEqualTo(inscriptionObligatoire);
|
||||
assertThat(evenement.getDateLimiteInscription()).isEqualTo(dateLimiteInscription);
|
||||
assertThat(evenement.getEvenementPublic()).isEqualTo(evenementPublic);
|
||||
assertThat(evenement.getRecurrent()).isEqualTo(recurrent);
|
||||
assertThat(evenement.getFrequenceRecurrence()).isEqualTo(frequenceRecurrence);
|
||||
assertThat(evenement.getInstructions()).isEqualTo(instructions);
|
||||
assertThat(evenement.getMaterielNecessaire()).isEqualTo(materielNecessaire);
|
||||
assertThat(evenement.getConditionsMeteo()).isEqualTo(conditionsMeteo);
|
||||
assertThat(evenement.getImageUrl()).isEqualTo(imageUrl);
|
||||
assertThat(evenement.getCouleurTheme()).isEqualTo(couleurTheme);
|
||||
assertThat(evenement.getDateAnnulation()).isEqualTo(dateAnnulation);
|
||||
assertThat(evenement.getRaisonAnnulation()).isEqualTo(raisonAnnulation);
|
||||
assertThat(evenement.getAnnulePar()).isEqualTo(annulePar);
|
||||
assertThat(evenement.getNomAnnulateur()).isEqualTo(nomAnnulateur);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests Méthodes Métier")
|
||||
class MethodesMetierTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes de statut")
|
||||
void testMethodesStatut() {
|
||||
// Test isEnCours
|
||||
evenement.setStatut("EN_COURS");
|
||||
assertThat(evenement.isEnCours()).isTrue();
|
||||
evenement.setStatut("PLANIFIE");
|
||||
assertThat(evenement.isEnCours()).isFalse();
|
||||
|
||||
// Test isTermine
|
||||
evenement.setStatut("TERMINE");
|
||||
assertThat(evenement.isTermine()).isTrue();
|
||||
evenement.setStatut("PLANIFIE");
|
||||
assertThat(evenement.isTermine()).isFalse();
|
||||
|
||||
// Test isAnnule
|
||||
evenement.setStatut("ANNULE");
|
||||
assertThat(evenement.isAnnule()).isTrue();
|
||||
evenement.setStatut("PLANIFIE");
|
||||
assertThat(evenement.isAnnule()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes de capacité")
|
||||
void testMethodesCapacite() {
|
||||
// Test isComplet - cas avec capaciteMax null
|
||||
evenement.setCapaciteMax(null);
|
||||
evenement.setParticipantsInscrits(50);
|
||||
assertThat(evenement.isComplet()).isFalse();
|
||||
|
||||
// Test isComplet - cas avec participantsInscrits null (capaciteMax définie)
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(null);
|
||||
assertThat(evenement.isComplet()).isFalse();
|
||||
|
||||
// Test isComplet - cas avec les deux null
|
||||
evenement.setCapaciteMax(null);
|
||||
evenement.setParticipantsInscrits(null);
|
||||
assertThat(evenement.isComplet()).isFalse();
|
||||
|
||||
// Test isComplet - cas normal complet
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(50);
|
||||
assertThat(evenement.isComplet()).isTrue();
|
||||
|
||||
// Test isComplet - cas normal non complet
|
||||
evenement.setParticipantsInscrits(30);
|
||||
assertThat(evenement.isComplet()).isFalse();
|
||||
|
||||
// Test getPlacesDisponibles
|
||||
assertThat(evenement.getPlacesDisponibles()).isEqualTo(20);
|
||||
|
||||
evenement.setCapaciteMax(null);
|
||||
assertThat(evenement.getPlacesDisponibles()).isEqualTo(0);
|
||||
|
||||
// Test getTauxRemplissage
|
||||
evenement.setCapaciteMax(100);
|
||||
evenement.setParticipantsInscrits(75);
|
||||
assertThat(evenement.getTauxRemplissage()).isEqualTo(75);
|
||||
|
||||
evenement.setCapaciteMax(0);
|
||||
assertThat(evenement.getTauxRemplissage()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isComplet - branches spécifiques")
|
||||
void testIsCompletBranchesSpecifiques() {
|
||||
// Test spécifique pour la branche: capaciteMax != null && participantsInscrits == null
|
||||
// Nous devons nous assurer que capaciteMax est définie ET que participantsInscrits est null
|
||||
evenement.setCapaciteMax(100); // Défini explicitement
|
||||
evenement.setParticipantsInscrits(null); // Null explicitement
|
||||
|
||||
// Cette condition devrait évaluer:
|
||||
// capaciteMax != null (true) && participantsInscrits != null (false) && ...
|
||||
// Donc retourner false à cause du court-circuit sur participantsInscrits != null
|
||||
assertThat(evenement.isComplet()).isFalse();
|
||||
|
||||
// Test pour vérifier que la branche participantsInscrits != null est bien testée
|
||||
// Maintenant avec participantsInscrits défini
|
||||
evenement.setParticipantsInscrits(50); // Défini mais < capaciteMax
|
||||
assertThat(evenement.isComplet()).isFalse();
|
||||
|
||||
// Et maintenant avec participantsInscrits >= capaciteMax
|
||||
evenement.setParticipantsInscrits(100); // Égal à capaciteMax
|
||||
assertThat(evenement.isComplet()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getTauxPresence")
|
||||
void testGetTauxPresence() {
|
||||
evenement.setParticipantsInscrits(100);
|
||||
evenement.setParticipantsPresents(80);
|
||||
assertThat(evenement.getTauxPresence()).isEqualTo(80);
|
||||
|
||||
evenement.setParticipantsInscrits(0);
|
||||
assertThat(evenement.getTauxPresence()).isEqualTo(0);
|
||||
|
||||
evenement.setParticipantsInscrits(null);
|
||||
assertThat(evenement.getTauxPresence()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isInscriptionsOuvertes")
|
||||
void testIsInscriptionsOuvertes() {
|
||||
// Événement normal avec places disponibles
|
||||
evenement.setStatut("PLANIFIE");
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(30);
|
||||
assertThat(evenement.isInscriptionsOuvertes()).isTrue();
|
||||
|
||||
// Événement annulé
|
||||
evenement.setStatut("ANNULE");
|
||||
assertThat(evenement.isInscriptionsOuvertes()).isFalse();
|
||||
|
||||
// Événement terminé
|
||||
evenement.setStatut("TERMINE");
|
||||
assertThat(evenement.isInscriptionsOuvertes()).isFalse();
|
||||
|
||||
// Événement complet
|
||||
evenement.setStatut("PLANIFIE");
|
||||
evenement.setParticipantsInscrits(50);
|
||||
assertThat(evenement.isInscriptionsOuvertes()).isFalse();
|
||||
|
||||
// Date limite dépassée
|
||||
evenement.setParticipantsInscrits(30);
|
||||
evenement.setDateLimiteInscription(LocalDate.now().minusDays(1));
|
||||
assertThat(evenement.isInscriptionsOuvertes()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getDureeEnHeures")
|
||||
void testGetDureeEnHeures() {
|
||||
evenement.setHeureDebut(LocalTime.of(9, 0));
|
||||
evenement.setHeureFin(LocalTime.of(17, 0));
|
||||
assertThat(evenement.getDureeEnHeures()).isEqualTo(8);
|
||||
|
||||
evenement.setHeureDebut(null);
|
||||
assertThat(evenement.getDureeEnHeures()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isEvenementMultiJours")
|
||||
void testIsEvenementMultiJours() {
|
||||
LocalDate dateDebut = LocalDate.now();
|
||||
evenement.setDateDebut(dateDebut);
|
||||
evenement.setDateFin(dateDebut.plusDays(2));
|
||||
assertThat(evenement.isEvenementMultiJours()).isTrue();
|
||||
|
||||
evenement.setDateFin(dateDebut);
|
||||
assertThat(evenement.isEvenementMultiJours()).isFalse();
|
||||
|
||||
evenement.setDateFin(null);
|
||||
assertThat(evenement.isEvenementMultiJours()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getTypeEvenementLibelle")
|
||||
void testGetTypeEvenementLibelle() {
|
||||
evenement.setTypeEvenement("ASSEMBLEE_GENERALE");
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Assemblée Générale");
|
||||
|
||||
evenement.setTypeEvenement("FORMATION");
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Formation");
|
||||
|
||||
evenement.setTypeEvenement("ACTIVITE_SOCIALE");
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Activité Sociale");
|
||||
|
||||
evenement.setTypeEvenement("ACTION_CARITATIVE");
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Action Caritative");
|
||||
|
||||
evenement.setTypeEvenement("REUNION_BUREAU");
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Réunion de Bureau");
|
||||
|
||||
evenement.setTypeEvenement("CONFERENCE");
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Conférence");
|
||||
|
||||
evenement.setTypeEvenement("ATELIER");
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Atelier");
|
||||
|
||||
evenement.setTypeEvenement("CEREMONIE");
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Cérémonie");
|
||||
|
||||
evenement.setTypeEvenement("AUTRE");
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Autre");
|
||||
|
||||
evenement.setTypeEvenement("INCONNU");
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("INCONNU");
|
||||
|
||||
evenement.setTypeEvenement(null);
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Non défini");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getStatutLibelle")
|
||||
void testGetStatutLibelle() {
|
||||
evenement.setStatut("PLANIFIE");
|
||||
assertThat(evenement.getStatutLibelle()).isEqualTo("Planifié");
|
||||
|
||||
evenement.setStatut("EN_COURS");
|
||||
assertThat(evenement.getStatutLibelle()).isEqualTo("En cours");
|
||||
|
||||
evenement.setStatut("TERMINE");
|
||||
assertThat(evenement.getStatutLibelle()).isEqualTo("Terminé");
|
||||
|
||||
evenement.setStatut("ANNULE");
|
||||
assertThat(evenement.getStatutLibelle()).isEqualTo("Annulé");
|
||||
|
||||
evenement.setStatut("REPORTE");
|
||||
assertThat(evenement.getStatutLibelle()).isEqualTo("Reporté");
|
||||
|
||||
evenement.setStatut("INCONNU");
|
||||
assertThat(evenement.getStatutLibelle()).isEqualTo("INCONNU");
|
||||
|
||||
evenement.setStatut(null);
|
||||
assertThat(evenement.getStatutLibelle()).isEqualTo("Non défini");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getPrioriteLibelle")
|
||||
void testGetPrioriteLibelle() {
|
||||
evenement.setPriorite("BASSE");
|
||||
assertThat(evenement.getPrioriteLibelle()).isEqualTo("Basse");
|
||||
|
||||
evenement.setPriorite("NORMALE");
|
||||
assertThat(evenement.getPrioriteLibelle()).isEqualTo("Normale");
|
||||
|
||||
evenement.setPriorite("HAUTE");
|
||||
assertThat(evenement.getPrioriteLibelle()).isEqualTo("Haute");
|
||||
|
||||
evenement.setPriorite("CRITIQUE");
|
||||
assertThat(evenement.getPrioriteLibelle()).isEqualTo("Critique");
|
||||
|
||||
evenement.setPriorite("INCONNU");
|
||||
assertThat(evenement.getPrioriteLibelle()).isEqualTo("INCONNU");
|
||||
|
||||
evenement.setPriorite(null);
|
||||
assertThat(evenement.getPrioriteLibelle()).isEqualTo("Normale");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getAdresseComplete")
|
||||
void testGetAdresseComplete() {
|
||||
// Adresse complète
|
||||
evenement.setLieu("Centre de conférence");
|
||||
evenement.setAdresse("123 Avenue de la République");
|
||||
evenement.setVille("Dakar");
|
||||
evenement.setRegion("Dakar");
|
||||
assertThat(evenement.getAdresseComplete())
|
||||
.isEqualTo("Centre de conférence, 123 Avenue de la République, Dakar, Dakar");
|
||||
|
||||
// Adresse partielle
|
||||
evenement.setAdresse(null);
|
||||
evenement.setRegion(null);
|
||||
assertThat(evenement.getAdresseComplete()).isEqualTo("Centre de conférence, Dakar");
|
||||
|
||||
// Lieu seulement
|
||||
evenement.setVille(null);
|
||||
assertThat(evenement.getAdresseComplete()).isEqualTo("Centre de conférence");
|
||||
|
||||
// Aucune information
|
||||
evenement.setLieu(null);
|
||||
assertThat(evenement.getAdresseComplete()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test hasCoordonnees")
|
||||
void testHasCoordonnees() {
|
||||
evenement.setLatitude(new BigDecimal("14.6937"));
|
||||
evenement.setLongitude(new BigDecimal("-17.4441"));
|
||||
assertThat(evenement.hasCoordonnees()).isTrue();
|
||||
|
||||
evenement.setLatitude(null);
|
||||
assertThat(evenement.hasCoordonnees()).isFalse();
|
||||
|
||||
evenement.setLatitude(new BigDecimal("14.6937"));
|
||||
evenement.setLongitude(null);
|
||||
assertThat(evenement.hasCoordonnees()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes budgétaires")
|
||||
void testMethodesBudgetaires() {
|
||||
// Test getEcartBudgetaire - économie
|
||||
evenement.setBudget(new BigDecimal("500000.00"));
|
||||
evenement.setCoutReel(new BigDecimal("450000.00"));
|
||||
assertThat(evenement.getEcartBudgetaire()).isEqualTo(new BigDecimal("50000.00"));
|
||||
assertThat(evenement.isBudgetDepasse()).isFalse();
|
||||
|
||||
// Test getEcartBudgetaire - dépassement
|
||||
evenement.setCoutReel(new BigDecimal("550000.00"));
|
||||
assertThat(evenement.getEcartBudgetaire()).isEqualTo(new BigDecimal("-50000.00"));
|
||||
assertThat(evenement.isBudgetDepasse()).isTrue();
|
||||
|
||||
// Test avec valeurs nulles
|
||||
evenement.setBudget(null);
|
||||
assertThat(evenement.getEcartBudgetaire()).isEqualTo(BigDecimal.ZERO);
|
||||
assertThat(evenement.isBudgetDepasse()).isFalse();
|
||||
|
||||
evenement.setBudget(new BigDecimal("500000.00"));
|
||||
evenement.setCoutReel(null);
|
||||
assertThat(evenement.getEcartBudgetaire()).isEqualTo(BigDecimal.ZERO);
|
||||
assertThat(evenement.isBudgetDepasse()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test toString")
|
||||
void testToString() {
|
||||
evenement.setTitre("Événement test");
|
||||
evenement.setTypeEvenement("FORMATION");
|
||||
evenement.setStatut("PLANIFIE");
|
||||
evenement.setDateDebut(LocalDate.now());
|
||||
evenement.setLieu("Salle de test");
|
||||
evenement.setParticipantsInscrits(10);
|
||||
evenement.setCapaciteMax(50);
|
||||
|
||||
String result = evenement.toString();
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result).contains("EvenementDTO");
|
||||
assertThat(result).contains("titre='Événement test'");
|
||||
assertThat(result).contains("typeEvenement='FORMATION'");
|
||||
assertThat(result).contains("statut='PLANIFIE'");
|
||||
assertThat(result).contains("lieu='Salle de test'");
|
||||
assertThat(result).contains("participantsInscrits=10");
|
||||
assertThat(result).contains("capaciteMax=50");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test branches supplémentaires getPlacesDisponibles")
|
||||
void testBranchesSupplementairesPlacesDisponibles() {
|
||||
// Test avec capaciteMax null
|
||||
evenement.setCapaciteMax(null);
|
||||
evenement.setParticipantsInscrits(10);
|
||||
assertThat(evenement.getPlacesDisponibles()).isEqualTo(0);
|
||||
|
||||
// Test avec participantsInscrits null
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(null);
|
||||
assertThat(evenement.getPlacesDisponibles()).isEqualTo(0);
|
||||
|
||||
// Test avec les deux null
|
||||
evenement.setCapaciteMax(null);
|
||||
evenement.setParticipantsInscrits(null);
|
||||
assertThat(evenement.getPlacesDisponibles()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test branches supplémentaires getTauxRemplissage")
|
||||
void testBranchesSupplementairesTauxRemplissage() {
|
||||
// Test avec capaciteMax null
|
||||
evenement.setCapaciteMax(null);
|
||||
evenement.setParticipantsInscrits(10);
|
||||
assertThat(evenement.getTauxRemplissage()).isEqualTo(0);
|
||||
|
||||
// Test avec capaciteMax zéro
|
||||
evenement.setCapaciteMax(0);
|
||||
evenement.setParticipantsInscrits(10);
|
||||
assertThat(evenement.getTauxRemplissage()).isEqualTo(0);
|
||||
|
||||
// Test avec participantsInscrits null
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(null);
|
||||
assertThat(evenement.getTauxRemplissage()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test branches supplémentaires getTauxPresence")
|
||||
void testBranchesSupplementairesTauxPresence() {
|
||||
// Test avec participantsInscrits null
|
||||
evenement.setParticipantsInscrits(null);
|
||||
evenement.setParticipantsPresents(5);
|
||||
assertThat(evenement.getTauxPresence()).isEqualTo(0);
|
||||
|
||||
// Test avec participantsInscrits zéro
|
||||
evenement.setParticipantsInscrits(0);
|
||||
evenement.setParticipantsPresents(5);
|
||||
assertThat(evenement.getTauxPresence()).isEqualTo(0);
|
||||
|
||||
// Test avec participantsPresents null
|
||||
evenement.setParticipantsInscrits(10);
|
||||
evenement.setParticipantsPresents(null);
|
||||
assertThat(evenement.getTauxPresence()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test branches supplémentaires isInscriptionsOuvertes")
|
||||
void testBranchesSupplementairesInscriptionsOuvertes() {
|
||||
// Test avec événement annulé
|
||||
evenement.setStatut("ANNULE");
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(10);
|
||||
evenement.setDateLimiteInscription(LocalDate.now().plusDays(5));
|
||||
assertThat(evenement.isInscriptionsOuvertes()).isFalse();
|
||||
|
||||
// Test avec événement terminé
|
||||
evenement.setStatut("TERMINE");
|
||||
assertThat(evenement.isInscriptionsOuvertes()).isFalse();
|
||||
|
||||
// Test avec date limite dépassée
|
||||
evenement.setStatut("PLANIFIE");
|
||||
evenement.setDateLimiteInscription(LocalDate.now().minusDays(1));
|
||||
assertThat(evenement.isInscriptionsOuvertes()).isFalse();
|
||||
|
||||
// Test avec événement complet
|
||||
evenement.setDateLimiteInscription(LocalDate.now().plusDays(5));
|
||||
evenement.setCapaciteMax(10);
|
||||
evenement.setParticipantsInscrits(10);
|
||||
assertThat(evenement.isInscriptionsOuvertes()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test branches supplémentaires getDureeEnHeures")
|
||||
void testBranchesSupplementairesDureeEnHeures() {
|
||||
// Test avec heureDebut null
|
||||
evenement.setHeureDebut(null);
|
||||
evenement.setHeureFin(LocalTime.of(17, 0));
|
||||
assertThat(evenement.getDureeEnHeures()).isEqualTo(0);
|
||||
|
||||
// Test avec heureFin null
|
||||
evenement.setHeureDebut(LocalTime.of(9, 0));
|
||||
evenement.setHeureFin(null);
|
||||
assertThat(evenement.getDureeEnHeures()).isEqualTo(0);
|
||||
|
||||
// Test avec les deux null
|
||||
evenement.setHeureDebut(null);
|
||||
evenement.setHeureFin(null);
|
||||
assertThat(evenement.getDureeEnHeures()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test branches supplémentaires getAdresseComplete")
|
||||
void testBranchesSupplementairesAdresseComplete() {
|
||||
// Test avec adresse seulement (sans lieu)
|
||||
evenement.setLieu(null);
|
||||
evenement.setAdresse("123 Avenue Test");
|
||||
evenement.setVille(null);
|
||||
evenement.setRegion(null);
|
||||
assertThat(evenement.getAdresseComplete()).isEqualTo("123 Avenue Test");
|
||||
|
||||
// Test avec ville seulement (sans lieu ni adresse)
|
||||
evenement.setLieu(null);
|
||||
evenement.setAdresse(null);
|
||||
evenement.setVille("Dakar");
|
||||
evenement.setRegion(null);
|
||||
assertThat(evenement.getAdresseComplete()).isEqualTo("Dakar");
|
||||
|
||||
// Test avec région seulement
|
||||
evenement.setLieu(null);
|
||||
evenement.setAdresse(null);
|
||||
evenement.setVille(null);
|
||||
evenement.setRegion("Dakar");
|
||||
assertThat(evenement.getAdresseComplete()).isEqualTo("Dakar");
|
||||
|
||||
// Test avec adresse et ville (sans lieu)
|
||||
evenement.setLieu(null);
|
||||
evenement.setAdresse("123 Avenue Test");
|
||||
evenement.setVille("Dakar");
|
||||
evenement.setRegion(null);
|
||||
assertThat(evenement.getAdresseComplete()).isEqualTo("123 Avenue Test, Dakar");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
package dev.lions.unionflow.server.api.dto.evenement;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.evenement.PrioriteEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.StatutEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.TypeEvenementMetier;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires simples pour EvenementDTO
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@DisplayName("Tests EvenementDTO")
|
||||
class EvenementDTOSimpleTest {
|
||||
|
||||
private EvenementDTO evenement;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
evenement = new EvenementDTO();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test création et getters/setters de base")
|
||||
void testCreationEtGettersSetters() {
|
||||
// Données de test
|
||||
String titre = "Formation Leadership";
|
||||
String description = "Formation sur les techniques de leadership";
|
||||
TypeEvenementMetier typeEvenement = TypeEvenementMetier.FORMATION;
|
||||
StatutEvenement statut = StatutEvenement.PLANIFIE;
|
||||
PrioriteEvenement priorite = PrioriteEvenement.NORMALE;
|
||||
LocalDate dateDebut = LocalDate.now().plusDays(30);
|
||||
LocalDate dateFin = LocalDate.now().plusDays(30);
|
||||
LocalTime heureDebut = LocalTime.of(9, 0);
|
||||
LocalTime heureFin = LocalTime.of(17, 0);
|
||||
String lieu = "Centre de Formation";
|
||||
Integer capaciteMax = 50;
|
||||
BigDecimal budget = new BigDecimal("500000");
|
||||
|
||||
// Test des setters
|
||||
evenement.setTitre(titre);
|
||||
evenement.setDescription(description);
|
||||
evenement.setTypeEvenement(typeEvenement);
|
||||
evenement.setStatut(statut);
|
||||
evenement.setPriorite(priorite);
|
||||
evenement.setDateDebut(dateDebut);
|
||||
evenement.setDateFin(dateFin);
|
||||
evenement.setHeureDebut(heureDebut);
|
||||
evenement.setHeureFin(heureFin);
|
||||
evenement.setLieu(lieu);
|
||||
evenement.setCapaciteMax(capaciteMax);
|
||||
evenement.setBudget(budget);
|
||||
|
||||
// Test des getters
|
||||
assertThat(evenement.getTitre()).isEqualTo(titre);
|
||||
assertThat(evenement.getDescription()).isEqualTo(description);
|
||||
assertThat(evenement.getTypeEvenement()).isEqualTo(typeEvenement);
|
||||
assertThat(evenement.getStatut()).isEqualTo(statut);
|
||||
assertThat(evenement.getPriorite()).isEqualTo(priorite);
|
||||
assertThat(evenement.getDateDebut()).isEqualTo(dateDebut);
|
||||
assertThat(evenement.getDateFin()).isEqualTo(dateFin);
|
||||
assertThat(evenement.getHeureDebut()).isEqualTo(heureDebut);
|
||||
assertThat(evenement.getHeureFin()).isEqualTo(heureFin);
|
||||
assertThat(evenement.getLieu()).isEqualTo(lieu);
|
||||
assertThat(evenement.getCapaciteMax()).isEqualTo(capaciteMax);
|
||||
assertThat(evenement.getBudget()).isEqualTo(budget);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constructeur avec paramètres")
|
||||
void testConstructeurAvecParametres() {
|
||||
String titre = "Assemblée Générale";
|
||||
TypeEvenementMetier type = TypeEvenementMetier.ASSEMBLEE_GENERALE;
|
||||
LocalDate date = LocalDate.now().plusDays(15);
|
||||
String lieu = "Salle de conférence";
|
||||
|
||||
EvenementDTO newEvenement = new EvenementDTO(titre, type, date, lieu);
|
||||
|
||||
assertThat(newEvenement.getTitre()).isEqualTo(titre);
|
||||
assertThat(newEvenement.getTypeEvenement()).isEqualTo(type);
|
||||
assertThat(newEvenement.getDateDebut()).isEqualTo(date);
|
||||
assertThat(newEvenement.getLieu()).isEqualTo(lieu);
|
||||
assertThat(newEvenement.getStatut()).isEqualTo(StatutEvenement.PLANIFIE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes utilitaires existantes")
|
||||
void testMethodesUtilitaires() {
|
||||
// Test des méthodes qui existent réellement
|
||||
evenement.setStatut(StatutEvenement.EN_COURS);
|
||||
assertThat(evenement.estEnCours()).isTrue();
|
||||
|
||||
evenement.setStatut(StatutEvenement.TERMINE);
|
||||
assertThat(evenement.estTermine()).isTrue();
|
||||
|
||||
evenement.setStatut(StatutEvenement.ANNULE);
|
||||
assertThat(evenement.estAnnule()).isTrue();
|
||||
|
||||
// Test capacité
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(25);
|
||||
assertThat(evenement.estComplet()).isFalse();
|
||||
assertThat(evenement.getPlacesDisponibles()).isEqualTo(25);
|
||||
assertThat(evenement.getTauxRemplissage()).isEqualTo(50);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test validation des énumérations")
|
||||
void testValidationEnumerations() {
|
||||
// Test que toutes les énumérations sont bien supportées
|
||||
for (TypeEvenementMetier type : TypeEvenementMetier.values()) {
|
||||
evenement.setTypeEvenement(type);
|
||||
assertThat(evenement.getTypeEvenement()).isEqualTo(type);
|
||||
}
|
||||
|
||||
for (StatutEvenement statut : StatutEvenement.values()) {
|
||||
evenement.setStatut(statut);
|
||||
assertThat(evenement.getStatut()).isEqualTo(statut);
|
||||
}
|
||||
|
||||
for (PrioriteEvenement priorite : PrioriteEvenement.values()) {
|
||||
evenement.setPriorite(priorite);
|
||||
assertThat(evenement.getPriorite()).isEqualTo(priorite);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test héritage BaseDTO")
|
||||
void testHeritageBaseDTO() {
|
||||
assertThat(evenement.getId()).isNotNull();
|
||||
assertThat(evenement.getDateCreation()).isNotNull();
|
||||
assertThat(evenement.isActif()).isTrue();
|
||||
assertThat(evenement.getVersion()).isEqualTo(0L);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
package dev.lions.unionflow.server.api.dto.evenement;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.evenement.PrioriteEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.StatutEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.TypeEvenementMetier;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires pour EvenementDTO
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@DisplayName("Tests EvenementDTO")
|
||||
class EvenementDTOTest {
|
||||
|
||||
private EvenementDTO evenement;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
evenement = new EvenementDTO();
|
||||
evenement.setTitre("Formation Leadership");
|
||||
evenement.setStatut(StatutEvenement.PLANIFIE);
|
||||
evenement.setPriorite(PrioriteEvenement.NORMALE);
|
||||
evenement.setTypeEvenement(TypeEvenementMetier.FORMATION);
|
||||
evenement.setDateDebut(LocalDate.now().plusDays(30));
|
||||
evenement.setDateFin(LocalDate.now().plusDays(30));
|
||||
evenement.setHeureDebut(LocalTime.of(9, 0));
|
||||
evenement.setHeureFin(LocalTime.of(17, 0));
|
||||
evenement.setLieu("Centre de Formation");
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(25);
|
||||
evenement.setBudget(new BigDecimal("500000"));
|
||||
evenement.setCoutReel(new BigDecimal("450000"));
|
||||
evenement.setCodeDevise("XOF");
|
||||
evenement.setAssociationId(UUID.randomUUID());
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests de Construction")
|
||||
class ConstructionTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constructeur par défaut")
|
||||
void testConstructeurParDefaut() {
|
||||
EvenementDTO newEvenement = new EvenementDTO();
|
||||
|
||||
assertThat(newEvenement.getId()).isNotNull();
|
||||
assertThat(newEvenement.getDateCreation()).isNotNull();
|
||||
assertThat(newEvenement.isActif()).isTrue();
|
||||
assertThat(newEvenement.getVersion()).isEqualTo(0L);
|
||||
assertThat(newEvenement.getStatut()).isEqualTo(StatutEvenement.PLANIFIE);
|
||||
assertThat(newEvenement.getPriorite()).isEqualTo(PrioriteEvenement.NORMALE);
|
||||
assertThat(newEvenement.getParticipantsInscrits()).isEqualTo(0);
|
||||
assertThat(newEvenement.getParticipantsPresents()).isEqualTo(0);
|
||||
assertThat(newEvenement.getCodeDevise()).isEqualTo("XOF");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constructeur avec paramètres")
|
||||
void testConstructeurAvecParametres() {
|
||||
String titre = "Assemblée Générale";
|
||||
TypeEvenementMetier type = TypeEvenementMetier.ASSEMBLEE_GENERALE;
|
||||
LocalDate date = LocalDate.now().plusDays(15);
|
||||
|
||||
EvenementDTO newEvenement = new EvenementDTO(titre, type, date, "Lieu par défaut");
|
||||
|
||||
assertThat(newEvenement.getTitre()).isEqualTo(titre);
|
||||
assertThat(newEvenement.getTypeEvenement()).isEqualTo(type);
|
||||
assertThat(newEvenement.getDateDebut()).isEqualTo(date);
|
||||
assertThat(newEvenement.getStatut()).isEqualTo(StatutEvenement.PLANIFIE);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des Méthodes Métier")
|
||||
class MethodesMetierTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test estEnCours")
|
||||
void testEstEnCours() {
|
||||
evenement.setStatut(StatutEvenement.EN_COURS);
|
||||
assertThat(evenement.estEnCours()).isTrue();
|
||||
|
||||
evenement.setStatut(StatutEvenement.PLANIFIE);
|
||||
assertThat(evenement.estEnCours()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test estTermine")
|
||||
void testEstTermine() {
|
||||
evenement.setStatut(StatutEvenement.TERMINE);
|
||||
assertThat(evenement.estTermine()).isTrue();
|
||||
|
||||
evenement.setStatut(StatutEvenement.EN_COURS);
|
||||
assertThat(evenement.estTermine()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test estAnnule")
|
||||
void testEstAnnule() {
|
||||
evenement.setStatut(StatutEvenement.ANNULE);
|
||||
assertThat(evenement.estAnnule()).isTrue();
|
||||
|
||||
evenement.setStatut(StatutEvenement.PLANIFIE);
|
||||
assertThat(evenement.estAnnule()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test estComplet")
|
||||
void testEstComplet() {
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(50);
|
||||
assertThat(evenement.estComplet()).isTrue();
|
||||
|
||||
evenement.setParticipantsInscrits(49);
|
||||
assertThat(evenement.estComplet()).isFalse();
|
||||
|
||||
evenement.setCapaciteMax(null);
|
||||
assertThat(evenement.estComplet()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getPlacesDisponibles")
|
||||
void testGetPlacesDisponibles() {
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(25);
|
||||
assertThat(evenement.getPlacesDisponibles()).isEqualTo(25);
|
||||
|
||||
evenement.setParticipantsInscrits(60); // Plus que la capacité
|
||||
assertThat(evenement.getPlacesDisponibles()).isEqualTo(0);
|
||||
|
||||
evenement.setCapaciteMax(null);
|
||||
assertThat(evenement.getPlacesDisponibles()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getTauxRemplissage")
|
||||
void testGetTauxRemplissage() {
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(25);
|
||||
assertThat(evenement.getTauxRemplissage()).isEqualTo(50);
|
||||
|
||||
evenement.setParticipantsInscrits(50);
|
||||
assertThat(evenement.getTauxRemplissage()).isEqualTo(100);
|
||||
|
||||
evenement.setCapaciteMax(0);
|
||||
assertThat(evenement.getTauxRemplissage()).isEqualTo(0);
|
||||
|
||||
evenement.setCapaciteMax(null);
|
||||
assertThat(evenement.getTauxRemplissage()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test sontInscriptionsOuvertes")
|
||||
void testSontInscriptionsOuvertes() {
|
||||
// Événement normal avec places disponibles
|
||||
evenement.setStatut(StatutEvenement.PLANIFIE);
|
||||
evenement.setCapaciteMax(50);
|
||||
evenement.setParticipantsInscrits(25);
|
||||
evenement.setDateLimiteInscription(LocalDate.now().plusDays(5));
|
||||
assertThat(evenement.sontInscriptionsOuvertes()).isTrue();
|
||||
|
||||
// Événement annulé
|
||||
evenement.setStatut(StatutEvenement.ANNULE);
|
||||
assertThat(evenement.sontInscriptionsOuvertes()).isFalse();
|
||||
|
||||
// Événement terminé
|
||||
evenement.setStatut(StatutEvenement.TERMINE);
|
||||
assertThat(evenement.sontInscriptionsOuvertes()).isFalse();
|
||||
|
||||
// Événement complet
|
||||
evenement.setStatut(StatutEvenement.PLANIFIE);
|
||||
evenement.setParticipantsInscrits(50);
|
||||
assertThat(evenement.sontInscriptionsOuvertes()).isFalse();
|
||||
|
||||
// Date limite dépassée
|
||||
evenement.setParticipantsInscrits(25);
|
||||
evenement.setDateLimiteInscription(LocalDate.now().minusDays(1));
|
||||
assertThat(evenement.sontInscriptionsOuvertes()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test estEvenementMultiJours")
|
||||
void testEstEvenementMultiJours() {
|
||||
evenement.setDateDebut(LocalDate.now().plusDays(1));
|
||||
evenement.setDateFin(LocalDate.now().plusDays(3));
|
||||
assertThat(evenement.estEvenementMultiJours()).isTrue();
|
||||
|
||||
evenement.setDateFin(LocalDate.now().plusDays(1));
|
||||
assertThat(evenement.estEvenementMultiJours()).isFalse();
|
||||
|
||||
evenement.setDateFin(null);
|
||||
assertThat(evenement.estEvenementMultiJours()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test estBudgetDepasse")
|
||||
void testEstBudgetDepasse() {
|
||||
evenement.setBudget(new BigDecimal("500000"));
|
||||
evenement.setCoutReel(new BigDecimal("600000"));
|
||||
assertThat(evenement.estBudgetDepasse()).isTrue();
|
||||
|
||||
evenement.setCoutReel(new BigDecimal("400000"));
|
||||
assertThat(evenement.estBudgetDepasse()).isFalse();
|
||||
|
||||
evenement.setCoutReel(new BigDecimal("500000"));
|
||||
assertThat(evenement.estBudgetDepasse()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des Méthodes Utilitaires")
|
||||
class MethodesUtilitairesTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getStatutLibelle")
|
||||
void testGetStatutLibelle() {
|
||||
evenement.setStatut(StatutEvenement.PLANIFIE);
|
||||
assertThat(evenement.getStatutLibelle()).isEqualTo("Planifié");
|
||||
|
||||
evenement.setStatut(null);
|
||||
assertThat(evenement.getStatutLibelle()).isEqualTo("Non défini");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getPrioriteLibelle")
|
||||
void testGetPrioriteLibelle() {
|
||||
evenement.setPriorite(PrioriteEvenement.HAUTE);
|
||||
assertThat(evenement.getPrioriteLibelle()).isEqualTo("Haute");
|
||||
|
||||
evenement.setPriorite(null);
|
||||
assertThat(evenement.getPrioriteLibelle()).isEqualTo("Normale");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getTypeEvenementLibelle")
|
||||
void testGetTypeEvenementLibelle() {
|
||||
evenement.setTypeEvenement(TypeEvenementMetier.FORMATION);
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Formation");
|
||||
|
||||
evenement.setTypeEvenement(null);
|
||||
assertThat(evenement.getTypeEvenementLibelle()).isEqualTo("Non défini");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getEcartBudgetaire")
|
||||
void testGetEcartBudgetaire() {
|
||||
evenement.setBudget(new BigDecimal("500000"));
|
||||
evenement.setCoutReel(new BigDecimal("450000"));
|
||||
assertThat(evenement.getEcartBudgetaire()).isEqualTo(new BigDecimal("50000"));
|
||||
|
||||
evenement.setCoutReel(new BigDecimal("550000"));
|
||||
assertThat(evenement.getEcartBudgetaire()).isEqualTo(new BigDecimal("-50000"));
|
||||
|
||||
evenement.setBudget(null);
|
||||
assertThat(evenement.getEcartBudgetaire()).isEqualTo(BigDecimal.ZERO);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,8 +121,6 @@ class CotisationDTOBasicTest {
|
||||
assertThat(cotisation.getDatePaiement()).isNotNull();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes métier avancées")
|
||||
void testMethodesMetierAvancees() {
|
||||
@@ -276,7 +274,8 @@ class CotisationDTOBasicTest {
|
||||
BigDecimal montantDu = new BigDecimal("25000.00");
|
||||
LocalDate dateEcheance = LocalDate.of(2025, 1, 31);
|
||||
|
||||
CotisationDTO newCotisation = new CotisationDTO(membreId, typeCotisation, montantDu, dateEcheance);
|
||||
CotisationDTO newCotisation =
|
||||
new CotisationDTO(membreId, typeCotisation, montantDu, dateEcheance);
|
||||
|
||||
assertThat(newCotisation.getMembreId()).isEqualTo(membreId);
|
||||
assertThat(newCotisation.getTypeCotisation()).isEqualTo(typeCotisation);
|
||||
@@ -284,7 +283,8 @@ class CotisationDTOBasicTest {
|
||||
assertThat(newCotisation.getDateEcheance()).isEqualTo(dateEcheance);
|
||||
assertThat(newCotisation.getNumeroReference()).isNotNull();
|
||||
assertThat(newCotisation.getNumeroReference()).startsWith("COT-");
|
||||
assertThat(newCotisation.getNumeroReference()).contains(String.valueOf(LocalDate.now().getYear()));
|
||||
assertThat(newCotisation.getNumeroReference())
|
||||
.contains(String.valueOf(LocalDate.now().getYear()));
|
||||
// Vérifier que les valeurs par défaut sont toujours appliquées
|
||||
assertThat(newCotisation.getMontantPaye()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
assertThat(newCotisation.getCodeDevise()).isEqualTo("XOF");
|
||||
@@ -474,7 +474,8 @@ class CotisationDTOBasicTest {
|
||||
cotisation.setDatePaiement(datePaiementExistante);
|
||||
cotisation.mettreAJourStatut();
|
||||
assertThat(cotisation.getStatut()).isEqualTo("PAYEE");
|
||||
assertThat(cotisation.getDatePaiement()).isEqualTo(datePaiementExistante); // Ne doit pas changer
|
||||
assertThat(cotisation.getDatePaiement())
|
||||
.isEqualTo(datePaiementExistante); // Ne doit pas changer
|
||||
|
||||
// Test avec paiement partiel
|
||||
cotisation.setMontantDu(BigDecimal.valueOf(1000));
|
||||
|
||||
@@ -300,7 +300,8 @@ class FormuleAbonnementDTOBasicTest {
|
||||
formule.setPrixAnnuel(new BigDecimal("100000.00"));
|
||||
BigDecimal economieAttendue = new BigDecimal("20000.00"); // 12*10000 - 100000
|
||||
assertThat(formule.getEconomieAnnuelle()).isEqualTo(economieAttendue);
|
||||
assertThat(formule.getPourcentageEconomieAnnuelle()).isEqualTo(17); // 20000/120000 * 100 = 16.67 arrondi à 17
|
||||
assertThat(formule.getPourcentageEconomieAnnuelle())
|
||||
.isEqualTo(17); // 20000/120000 * 100 = 16.67 arrondi à 17
|
||||
|
||||
// Cas sans économie
|
||||
formule.setPrixMensuel(new BigDecimal("10000.00"));
|
||||
@@ -422,9 +423,9 @@ class FormuleAbonnementDTOBasicTest {
|
||||
assertThat(formule.getScoreFonctionnalites()).isEqualTo(100);
|
||||
|
||||
// Test cas intermédiaire : seulement quelques fonctionnalités
|
||||
formule.setSupportTechnique(true); // +10
|
||||
formule.setSupportTechnique(true); // +10
|
||||
formule.setSauvegardeAutomatique(false);
|
||||
formule.setFonctionnalitesAvancees(true); // +15
|
||||
formule.setFonctionnalitesAvancees(true); // +15
|
||||
formule.setApiAccess(false);
|
||||
formule.setRapportsPersonnalises(false);
|
||||
formule.setIntegrationsTierces(false);
|
||||
@@ -447,7 +448,7 @@ class FormuleAbonnementDTOBasicTest {
|
||||
assertThat(formule.getScoreFonctionnalites()).isEqualTo(0);
|
||||
|
||||
// Test avec un seul élément activé pour vérifier la division
|
||||
formule.setSupportTechnique(true); // score = 10, total = 100
|
||||
formule.setSupportTechnique(true); // score = 10, total = 100
|
||||
formule.setSauvegardeAutomatique(false);
|
||||
formule.setFonctionnalitesAvancees(false);
|
||||
formule.setApiAccess(false);
|
||||
|
||||
@@ -1,442 +0,0 @@
|
||||
package dev.lions.unionflow.server.api.dto.membre;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires complets pour MembreDTO.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-10
|
||||
*/
|
||||
@DisplayName("Tests MembreDTO")
|
||||
class MembreDTOBasicTest {
|
||||
|
||||
private MembreDTO membre;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
membre = new MembreDTO();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Constructeur par défaut - Initialisation correcte")
|
||||
void testConstructeurParDefaut() {
|
||||
MembreDTO newMembre = new MembreDTO();
|
||||
|
||||
assertThat(newMembre.getId()).isNotNull();
|
||||
assertThat(newMembre.getDateCreation()).isNotNull();
|
||||
assertThat(newMembre.isActif()).isTrue();
|
||||
assertThat(newMembre.getVersion()).isEqualTo(0L);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getters/setters principaux")
|
||||
void testGettersSettersPrincipaux() {
|
||||
// Données de test
|
||||
String numeroMembre = "M001";
|
||||
String prenom = "Jean";
|
||||
String nom = "Dupont";
|
||||
String email = "jean.dupont@example.com";
|
||||
String telephone = "+221701234567";
|
||||
LocalDate dateNaissance = LocalDate.of(1980, 5, 15);
|
||||
String adresse = "123 Rue de la Paix";
|
||||
String ville = "Dakar";
|
||||
String profession = "Ingénieur";
|
||||
LocalDate dateAdhesion = LocalDate.now().minusYears(2);
|
||||
String statut = "ACTIF";
|
||||
Long associationId = 123L;
|
||||
String associationNom = "Lions Club Dakar";
|
||||
String region = "Dakar";
|
||||
String quartier = "Plateau";
|
||||
String role = "Membre";
|
||||
Boolean membreBureau = true;
|
||||
Boolean responsable = false;
|
||||
String photoUrl = "https://example.com/photo.jpg";
|
||||
|
||||
// Test des setters
|
||||
membre.setNumeroMembre(numeroMembre);
|
||||
membre.setPrenom(prenom);
|
||||
membre.setNom(nom);
|
||||
membre.setEmail(email);
|
||||
membre.setTelephone(telephone);
|
||||
membre.setDateNaissance(dateNaissance);
|
||||
membre.setAdresse(adresse);
|
||||
membre.setVille(ville);
|
||||
membre.setProfession(profession);
|
||||
membre.setDateAdhesion(dateAdhesion);
|
||||
membre.setStatut(statut);
|
||||
membre.setAssociationId(associationId);
|
||||
membre.setAssociationNom(associationNom);
|
||||
membre.setRegion(region);
|
||||
membre.setQuartier(quartier);
|
||||
membre.setRole(role);
|
||||
membre.setMembreBureau(membreBureau);
|
||||
membre.setResponsable(responsable);
|
||||
membre.setPhotoUrl(photoUrl);
|
||||
|
||||
// Test des getters
|
||||
assertThat(membre.getNumeroMembre()).isEqualTo(numeroMembre);
|
||||
assertThat(membre.getPrenom()).isEqualTo(prenom);
|
||||
assertThat(membre.getNom()).isEqualTo(nom);
|
||||
assertThat(membre.getEmail()).isEqualTo(email);
|
||||
assertThat(membre.getTelephone()).isEqualTo(telephone);
|
||||
assertThat(membre.getDateNaissance()).isEqualTo(dateNaissance);
|
||||
assertThat(membre.getAdresse()).isEqualTo(adresse);
|
||||
assertThat(membre.getVille()).isEqualTo(ville);
|
||||
assertThat(membre.getProfession()).isEqualTo(profession);
|
||||
assertThat(membre.getDateAdhesion()).isEqualTo(dateAdhesion);
|
||||
assertThat(membre.getStatut()).isEqualTo(statut);
|
||||
assertThat(membre.getAssociationId()).isEqualTo(associationId);
|
||||
assertThat(membre.getAssociationNom()).isEqualTo(associationNom);
|
||||
assertThat(membre.getRegion()).isEqualTo(region);
|
||||
assertThat(membre.getQuartier()).isEqualTo(quartier);
|
||||
assertThat(membre.getRole()).isEqualTo(role);
|
||||
assertThat(membre.getMembreBureau()).isEqualTo(membreBureau);
|
||||
assertThat(membre.getResponsable()).isEqualTo(responsable);
|
||||
assertThat(membre.getPhotoUrl()).isEqualTo(photoUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes métier")
|
||||
void testMethodesMetier() {
|
||||
// Test getNomComplet
|
||||
membre.setPrenom("Jean");
|
||||
membre.setNom("Dupont");
|
||||
assertThat(membre.getNomComplet()).isEqualTo("Jean Dupont");
|
||||
|
||||
// Test avec prenom null
|
||||
membre.setPrenom(null);
|
||||
assertThat(membre.getNomComplet()).isEqualTo("Dupont");
|
||||
|
||||
// Test avec nom null
|
||||
membre.setPrenom("Jean");
|
||||
membre.setNom(null);
|
||||
assertThat(membre.getNomComplet()).isEqualTo("Jean");
|
||||
|
||||
// Test getAge
|
||||
membre.setDateNaissance(LocalDate.now().minusYears(30));
|
||||
int age = membre.getAge();
|
||||
assertThat(age).isEqualTo(30);
|
||||
|
||||
// Test avec date null
|
||||
membre.setDateNaissance(null);
|
||||
assertThat(membre.getAge()).isEqualTo(-1);
|
||||
|
||||
// Test isMajeur
|
||||
membre.setDateNaissance(LocalDate.now().minusYears(25));
|
||||
assertThat(membre.isMajeur()).isTrue();
|
||||
|
||||
membre.setDateNaissance(LocalDate.now().minusYears(15));
|
||||
assertThat(membre.isMajeur()).isFalse();
|
||||
|
||||
membre.setDateNaissance(null);
|
||||
assertThat(membre.isMajeur()).isFalse();
|
||||
|
||||
// Test isActif
|
||||
membre.setStatut("ACTIF");
|
||||
assertThat(membre.isActif()).isTrue();
|
||||
|
||||
membre.setStatut("INACTIF");
|
||||
assertThat(membre.isActif()).isFalse();
|
||||
|
||||
// Test hasRoleDirection
|
||||
membre.setMembreBureau(true);
|
||||
membre.setResponsable(false);
|
||||
assertThat(membre.hasRoleDirection()).isTrue();
|
||||
|
||||
membre.setMembreBureau(false);
|
||||
membre.setResponsable(true);
|
||||
assertThat(membre.hasRoleDirection()).isTrue();
|
||||
|
||||
membre.setMembreBureau(false);
|
||||
membre.setResponsable(false);
|
||||
assertThat(membre.hasRoleDirection()).isFalse();
|
||||
|
||||
// Test getStatutLibelle
|
||||
membre.setStatut("ACTIF");
|
||||
assertThat(membre.getStatutLibelle()).isEqualTo("Actif");
|
||||
|
||||
membre.setStatut("INACTIF");
|
||||
assertThat(membre.getStatutLibelle()).isEqualTo("Inactif");
|
||||
|
||||
membre.setStatut("SUSPENDU");
|
||||
assertThat(membre.getStatutLibelle()).isEqualTo("Suspendu");
|
||||
|
||||
membre.setStatut("RADIE");
|
||||
assertThat(membre.getStatutLibelle()).isEqualTo("Radié");
|
||||
|
||||
membre.setStatut(null);
|
||||
assertThat(membre.getStatutLibelle()).isEqualTo("Non défini");
|
||||
|
||||
// Test isDataValid - cas valide (selon l'implémentation réelle)
|
||||
membre.setNumeroMembre("UF-2025-12345678");
|
||||
membre.setNom("Dupont");
|
||||
membre.setPrenom("Jean");
|
||||
membre.setEmail("jean.dupont@example.com");
|
||||
// Vérifier d'abord si la méthode existe et ce qu'elle teste réellement
|
||||
boolean isValid = membre.isDataValid();
|
||||
assertThat(isValid).isNotNull(); // Au moins vérifier qu'elle ne plante pas
|
||||
|
||||
// Test isDataValid - numéro membre null
|
||||
membre.setNumeroMembre(null);
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test isDataValid - numéro membre vide
|
||||
membre.setNumeroMembre("");
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test isDataValid - numéro membre avec espaces
|
||||
membre.setNumeroMembre(" ");
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test isDataValid - nom null
|
||||
membre.setNumeroMembre("UF-2025-12345678");
|
||||
membre.setNom(null);
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test isDataValid - nom vide
|
||||
membre.setNom("");
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test isDataValid - nom avec espaces
|
||||
membre.setNom(" ");
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test isDataValid - prénom null
|
||||
membre.setNom("Dupont");
|
||||
membre.setPrenom(null);
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test isDataValid - prénom vide
|
||||
membre.setPrenom("");
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test isDataValid - prénom avec espaces
|
||||
membre.setPrenom(" ");
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test isDataValid - email null
|
||||
membre.setPrenom("Jean");
|
||||
membre.setEmail(null);
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test isDataValid - email vide
|
||||
membre.setEmail("");
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test isDataValid - email avec espaces
|
||||
membre.setEmail(" ");
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constructeur avec paramètres")
|
||||
void testConstructeurAvecParametres() {
|
||||
String numeroMembre = "UF-2025-001";
|
||||
String nom = "Dupont";
|
||||
String prenom = "Jean";
|
||||
String email = "jean.dupont@example.com";
|
||||
|
||||
MembreDTO nouveauMembre = new MembreDTO(numeroMembre, nom, prenom, email);
|
||||
|
||||
assertThat(nouveauMembre.getNumeroMembre()).isEqualTo(numeroMembre);
|
||||
assertThat(nouveauMembre.getNom()).isEqualTo(nom);
|
||||
assertThat(nouveauMembre.getPrenom()).isEqualTo(prenom);
|
||||
assertThat(nouveauMembre.getEmail()).isEqualTo(email);
|
||||
// Vérifier les valeurs par défaut
|
||||
assertThat(nouveauMembre.getStatut()).isEqualTo("ACTIF");
|
||||
assertThat(nouveauMembre.getDateAdhesion()).isEqualTo(LocalDate.now());
|
||||
assertThat(nouveauMembre.getMembreBureau()).isFalse();
|
||||
assertThat(nouveauMembre.getResponsable()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test tous les statuts")
|
||||
void testTousLesStatuts() {
|
||||
// Test tous les statuts possibles (selon le switch dans la classe)
|
||||
membre.setStatut("EXCLU");
|
||||
assertThat(membre.getStatutLibelle()).isEqualTo("EXCLU"); // Valeur par défaut car non dans le switch
|
||||
|
||||
membre.setStatut("DEMISSIONNAIRE");
|
||||
assertThat(membre.getStatutLibelle()).isEqualTo("DEMISSIONNAIRE"); // Valeur par défaut car non dans le switch
|
||||
|
||||
membre.setStatut("STATUT_INCONNU");
|
||||
assertThat(membre.getStatutLibelle()).isEqualTo("STATUT_INCONNU");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getNomComplet cas limites")
|
||||
void testGetNomCompletCasLimites() {
|
||||
// Test avec les deux null - retourne chaîne vide selon l'implémentation
|
||||
membre.setPrenom(null);
|
||||
membre.setNom(null);
|
||||
assertThat(membre.getNomComplet()).isEqualTo("");
|
||||
|
||||
// Test avec prénom vide - l'implémentation concatène quand même
|
||||
membre.setPrenom("");
|
||||
membre.setNom("Dupont");
|
||||
assertThat(membre.getNomComplet()).isEqualTo(" Dupont");
|
||||
|
||||
// Test avec nom vide - l'implémentation concatène quand même
|
||||
membre.setPrenom("Jean");
|
||||
membre.setNom("");
|
||||
assertThat(membre.getNomComplet()).isEqualTo("Jean ");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test hasRoleDirection cas limites")
|
||||
void testHasRoleDirectionCasLimites() {
|
||||
// Test avec null
|
||||
membre.setMembreBureau(null);
|
||||
membre.setResponsable(null);
|
||||
assertThat(membre.hasRoleDirection()).isFalse();
|
||||
|
||||
// Test avec Boolean.FALSE explicite
|
||||
membre.setMembreBureau(Boolean.FALSE);
|
||||
membre.setResponsable(Boolean.FALSE);
|
||||
assertThat(membre.hasRoleDirection()).isFalse();
|
||||
|
||||
// Test avec Boolean.TRUE explicite
|
||||
membre.setMembreBureau(Boolean.TRUE);
|
||||
membre.setResponsable(Boolean.FALSE);
|
||||
assertThat(membre.hasRoleDirection()).isTrue();
|
||||
|
||||
membre.setMembreBureau(Boolean.FALSE);
|
||||
membre.setResponsable(Boolean.TRUE);
|
||||
assertThat(membre.hasRoleDirection()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test toString complet")
|
||||
void testToStringComplet() {
|
||||
membre.setNumeroMembre("UF-2025-001");
|
||||
membre.setPrenom("Jean");
|
||||
membre.setNom("Dupont");
|
||||
membre.setEmail("jean.dupont@example.com");
|
||||
membre.setStatut("ACTIF");
|
||||
membre.setAssociationId(123L);
|
||||
|
||||
String result = membre.toString();
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result).contains("MembreDTO");
|
||||
assertThat(result).contains("numeroMembre='UF-2025-001'");
|
||||
assertThat(result).contains("nom='Dupont'");
|
||||
assertThat(result).contains("prenom='Jean'");
|
||||
assertThat(result).contains("email='jean.dupont@example.com'");
|
||||
assertThat(result).contains("statut='ACTIF'");
|
||||
assertThat(result).contains("associationId=123");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés supplémentaires")
|
||||
void testProprietesSupplementaires() {
|
||||
// Test des propriétés qui pourraient ne pas être couvertes
|
||||
String statutMatrimonial = "MARIE";
|
||||
String nationalite = "Sénégalaise";
|
||||
String numeroIdentite = "1234567890123";
|
||||
String typeIdentite = "CNI";
|
||||
LocalDate dateAdhesion = LocalDate.of(2020, 1, 15);
|
||||
|
||||
membre.setStatutMatrimonial(statutMatrimonial);
|
||||
membre.setNationalite(nationalite);
|
||||
membre.setNumeroIdentite(numeroIdentite);
|
||||
membre.setTypeIdentite(typeIdentite);
|
||||
membre.setDateAdhesion(dateAdhesion);
|
||||
|
||||
assertThat(membre.getStatutMatrimonial()).isEqualTo(statutMatrimonial);
|
||||
assertThat(membre.getNationalite()).isEqualTo(nationalite);
|
||||
assertThat(membre.getNumeroIdentite()).isEqualTo(numeroIdentite);
|
||||
assertThat(membre.getTypeIdentite()).isEqualTo(typeIdentite);
|
||||
assertThat(membre.getDateAdhesion()).isEqualTo(dateAdhesion);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test branches supplémentaires isDataValid")
|
||||
void testBranchesSupplementairesIsDataValid() {
|
||||
// Test avec tous les champs valides
|
||||
membre.setNumeroMembre("UF-2025-001");
|
||||
membre.setNom("Dupont");
|
||||
membre.setPrenom("Jean");
|
||||
membre.setStatut("ACTIF");
|
||||
membre.setAssociationId(123L);
|
||||
assertThat(membre.isDataValid()).isTrue();
|
||||
|
||||
// Test avec numéro membre avec espaces seulement
|
||||
membre.setNumeroMembre(" ");
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test avec nom avec espaces seulement
|
||||
membre.setNumeroMembre("UF-2025-001");
|
||||
membre.setNom(" ");
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test avec prénom avec espaces seulement
|
||||
membre.setNom("Dupont");
|
||||
membre.setPrenom(" ");
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test avec statut avec espaces seulement
|
||||
membre.setPrenom("Jean");
|
||||
membre.setStatut(" ");
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test avec statut null
|
||||
membre.setStatut(null);
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
|
||||
// Test avec associationId null
|
||||
membre.setStatut("ACTIF");
|
||||
membre.setAssociationId(null);
|
||||
assertThat(membre.isDataValid()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test branches supplémentaires isMajeur")
|
||||
void testBranchesSupplementairesIsMajeur() {
|
||||
// Test avec date exactement 18 ans
|
||||
LocalDate dateExactement18Ans = LocalDate.now().minusYears(18);
|
||||
membre.setDateNaissance(dateExactement18Ans);
|
||||
assertThat(membre.isMajeur()).isTrue();
|
||||
|
||||
// Test avec date plus de 18 ans
|
||||
LocalDate datePlus18Ans = LocalDate.now().minusYears(25);
|
||||
membre.setDateNaissance(datePlus18Ans);
|
||||
assertThat(membre.isMajeur()).isTrue();
|
||||
|
||||
// Test avec date moins de 18 ans
|
||||
LocalDate dateMoins18Ans = LocalDate.now().minusYears(15);
|
||||
membre.setDateNaissance(dateMoins18Ans);
|
||||
assertThat(membre.isMajeur()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test branches supplémentaires hasRoleDirection")
|
||||
void testBranchesSupplementairesHasRoleDirection() {
|
||||
// Test avec membreBureau true et responsable false
|
||||
membre.setMembreBureau(Boolean.TRUE);
|
||||
membre.setResponsable(Boolean.FALSE);
|
||||
assertThat(membre.hasRoleDirection()).isTrue();
|
||||
|
||||
// Test avec membreBureau false et responsable true
|
||||
membre.setMembreBureau(Boolean.FALSE);
|
||||
membre.setResponsable(Boolean.TRUE);
|
||||
assertThat(membre.hasRoleDirection()).isTrue();
|
||||
|
||||
// Test avec les deux false
|
||||
membre.setMembreBureau(Boolean.FALSE);
|
||||
membre.setResponsable(Boolean.FALSE);
|
||||
assertThat(membre.hasRoleDirection()).isFalse();
|
||||
|
||||
// Test avec les deux null
|
||||
membre.setMembreBureau(null);
|
||||
membre.setResponsable(null);
|
||||
assertThat(membre.hasRoleDirection()).isFalse();
|
||||
}
|
||||
}
|
||||
@@ -1,611 +0,0 @@
|
||||
package dev.lions.unionflow.server.api.dto.organisation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.organisation.StatutOrganisation;
|
||||
import dev.lions.unionflow.server.api.enums.organisation.TypeOrganisation;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires complets pour OrganisationDTO.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-10
|
||||
*/
|
||||
@DisplayName("Tests OrganisationDTO")
|
||||
class OrganisationDTOBasicTest {
|
||||
|
||||
private OrganisationDTO organisation;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
organisation = new OrganisationDTO();
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests de Construction")
|
||||
class ConstructionTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Constructeur par défaut - Initialisation correcte")
|
||||
void testConstructeurParDefaut() {
|
||||
OrganisationDTO newOrganisation = new OrganisationDTO();
|
||||
|
||||
assertThat(newOrganisation.getId()).isNotNull();
|
||||
assertThat(newOrganisation.getDateCreation()).isNotNull();
|
||||
assertThat(newOrganisation.isActif()).isTrue();
|
||||
assertThat(newOrganisation.getVersion()).isEqualTo(0L);
|
||||
assertThat(newOrganisation.getStatut()).isEqualTo(StatutOrganisation.ACTIVE);
|
||||
assertThat(newOrganisation.getNombreMembres()).isEqualTo(0);
|
||||
assertThat(newOrganisation.getNombreAdministrateurs()).isEqualTo(0);
|
||||
assertThat(newOrganisation.getBudgetAnnuel()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Constructeur avec paramètres - Initialisation correcte")
|
||||
void testConstructeurAvecParametres() {
|
||||
String nom = "Lions Club Dakar";
|
||||
TypeOrganisation type = TypeOrganisation.LIONS_CLUB;
|
||||
|
||||
OrganisationDTO newOrganisation = new OrganisationDTO(nom, type);
|
||||
|
||||
assertThat(newOrganisation.getNom()).isEqualTo(nom);
|
||||
assertThat(newOrganisation.getTypeOrganisation()).isEqualTo(type);
|
||||
assertThat(newOrganisation.getStatut()).isEqualTo(StatutOrganisation.ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests Getters/Setters")
|
||||
class GettersSettersTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test tous les getters/setters - Partie 1")
|
||||
void testTousLesGettersSettersPart1() {
|
||||
// Données de test
|
||||
String nom = "Lions Club Dakar";
|
||||
String nomCourt = "LCD";
|
||||
TypeOrganisation typeOrganisation = TypeOrganisation.LIONS_CLUB;
|
||||
StatutOrganisation statut = StatutOrganisation.ACTIVE;
|
||||
String numeroEnregistrement = "REG-2025-001";
|
||||
LocalDate dateFondation = LocalDate.of(2020, 1, 15);
|
||||
String description = "Club service Lions de Dakar";
|
||||
String adresse = "123 Avenue Bourguiba";
|
||||
String ville = "Dakar";
|
||||
String region = "Dakar";
|
||||
String pays = "Sénégal";
|
||||
String codePostal = "10000";
|
||||
String telephone = "+221338234567";
|
||||
String email = "contact@lionsclubdakar.sn";
|
||||
String siteWeb = "https://lionsclubdakar.sn";
|
||||
|
||||
// Test des setters
|
||||
organisation.setNom(nom);
|
||||
organisation.setNomCourt(nomCourt);
|
||||
organisation.setTypeOrganisation(typeOrganisation);
|
||||
organisation.setStatut(statut);
|
||||
organisation.setNumeroEnregistrement(numeroEnregistrement);
|
||||
organisation.setDateFondation(dateFondation);
|
||||
organisation.setDescription(description);
|
||||
organisation.setAdresse(adresse);
|
||||
organisation.setVille(ville);
|
||||
organisation.setRegion(region);
|
||||
organisation.setPays(pays);
|
||||
organisation.setCodePostal(codePostal);
|
||||
organisation.setTelephone(telephone);
|
||||
organisation.setEmail(email);
|
||||
organisation.setSiteWeb(siteWeb);
|
||||
|
||||
// Test des getters
|
||||
assertThat(organisation.getNom()).isEqualTo(nom);
|
||||
assertThat(organisation.getNomCourt()).isEqualTo(nomCourt);
|
||||
assertThat(organisation.getTypeOrganisation()).isEqualTo(typeOrganisation);
|
||||
assertThat(organisation.getStatut()).isEqualTo(statut);
|
||||
assertThat(organisation.getNumeroEnregistrement()).isEqualTo(numeroEnregistrement);
|
||||
assertThat(organisation.getDateFondation()).isEqualTo(dateFondation);
|
||||
assertThat(organisation.getDescription()).isEqualTo(description);
|
||||
assertThat(organisation.getAdresse()).isEqualTo(adresse);
|
||||
assertThat(organisation.getVille()).isEqualTo(ville);
|
||||
assertThat(organisation.getRegion()).isEqualTo(region);
|
||||
assertThat(organisation.getPays()).isEqualTo(pays);
|
||||
assertThat(organisation.getCodePostal()).isEqualTo(codePostal);
|
||||
assertThat(organisation.getTelephone()).isEqualTo(telephone);
|
||||
assertThat(organisation.getEmail()).isEqualTo(email);
|
||||
assertThat(organisation.getSiteWeb()).isEqualTo(siteWeb);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getters/setters - Géolocalisation et hiérarchie")
|
||||
void testGettersSettersGeolocalisationHierarchie() {
|
||||
// Données de test
|
||||
BigDecimal latitude = new BigDecimal("14.6937");
|
||||
BigDecimal longitude = new BigDecimal("-17.4441");
|
||||
UUID organisationParenteId = UUID.randomUUID();
|
||||
String nomOrganisationParente = "Lions District 403";
|
||||
Integer niveauHierarchique = 2;
|
||||
Integer nombreMembres = 50;
|
||||
Integer nombreAdministrateurs = 5;
|
||||
BigDecimal budgetAnnuel = new BigDecimal("5000000.00");
|
||||
String devise = "XOF";
|
||||
|
||||
// Test des setters
|
||||
organisation.setLatitude(latitude);
|
||||
organisation.setLongitude(longitude);
|
||||
organisation.setOrganisationParenteId(organisationParenteId);
|
||||
organisation.setNomOrganisationParente(nomOrganisationParente);
|
||||
organisation.setNiveauHierarchique(niveauHierarchique);
|
||||
organisation.setNombreMembres(nombreMembres);
|
||||
organisation.setNombreAdministrateurs(nombreAdministrateurs);
|
||||
organisation.setBudgetAnnuel(budgetAnnuel);
|
||||
organisation.setDevise(devise);
|
||||
|
||||
// Test des getters
|
||||
assertThat(organisation.getLatitude()).isEqualTo(latitude);
|
||||
assertThat(organisation.getLongitude()).isEqualTo(longitude);
|
||||
assertThat(organisation.getOrganisationParenteId()).isEqualTo(organisationParenteId);
|
||||
assertThat(organisation.getNomOrganisationParente()).isEqualTo(nomOrganisationParente);
|
||||
assertThat(organisation.getNiveauHierarchique()).isEqualTo(niveauHierarchique);
|
||||
assertThat(organisation.getNombreMembres()).isEqualTo(nombreMembres);
|
||||
assertThat(organisation.getNombreAdministrateurs()).isEqualTo(nombreAdministrateurs);
|
||||
assertThat(organisation.getBudgetAnnuel()).isEqualTo(budgetAnnuel);
|
||||
assertThat(organisation.getDevise()).isEqualTo(devise);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getters/setters - Informations complémentaires")
|
||||
void testGettersSettersInformationsComplementaires() {
|
||||
// Données de test
|
||||
String objectifs = "Servir la communauté";
|
||||
String activitesPrincipales = "Actions sociales, environnement";
|
||||
String reseauxSociaux = "{\"facebook\":\"@lionsclub\"}";
|
||||
String certifications = "ISO 9001";
|
||||
String partenaires = "UNICEF, Croix-Rouge";
|
||||
String notes = "Notes administratives";
|
||||
Boolean organisationPublique = true;
|
||||
Boolean accepteNouveauxMembres = true;
|
||||
Boolean cotisationObligatoire = true;
|
||||
BigDecimal montantCotisationAnnuelle = new BigDecimal("50000.00");
|
||||
|
||||
// Test des setters
|
||||
organisation.setObjectifs(objectifs);
|
||||
organisation.setActivitesPrincipales(activitesPrincipales);
|
||||
organisation.setReseauxSociaux(reseauxSociaux);
|
||||
organisation.setCertifications(certifications);
|
||||
organisation.setPartenaires(partenaires);
|
||||
organisation.setNotes(notes);
|
||||
organisation.setOrganisationPublique(organisationPublique);
|
||||
organisation.setAccepteNouveauxMembres(accepteNouveauxMembres);
|
||||
organisation.setCotisationObligatoire(cotisationObligatoire);
|
||||
organisation.setMontantCotisationAnnuelle(montantCotisationAnnuelle);
|
||||
|
||||
// Test des getters
|
||||
assertThat(organisation.getObjectifs()).isEqualTo(objectifs);
|
||||
assertThat(organisation.getActivitesPrincipales()).isEqualTo(activitesPrincipales);
|
||||
assertThat(organisation.getReseauxSociaux()).isEqualTo(reseauxSociaux);
|
||||
assertThat(organisation.getCertifications()).isEqualTo(certifications);
|
||||
assertThat(organisation.getPartenaires()).isEqualTo(partenaires);
|
||||
assertThat(organisation.getNotes()).isEqualTo(notes);
|
||||
assertThat(organisation.getOrganisationPublique()).isEqualTo(organisationPublique);
|
||||
assertThat(organisation.getAccepteNouveauxMembres()).isEqualTo(accepteNouveauxMembres);
|
||||
assertThat(organisation.getCotisationObligatoire()).isEqualTo(cotisationObligatoire);
|
||||
assertThat(organisation.getMontantCotisationAnnuelle()).isEqualTo(montantCotisationAnnuelle);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test tous les getters/setters - Partie 2")
|
||||
void testTousLesGettersSettersPart2() {
|
||||
// Données de test
|
||||
UUID organisationParenteId = UUID.randomUUID();
|
||||
String nomOrganisationParente = "Lions District 403";
|
||||
Integer nombreMembres = 45;
|
||||
Integer nombreAdministrateurs = 7;
|
||||
BigDecimal budgetAnnuel = new BigDecimal("5000000.00");
|
||||
String devise = "XOF";
|
||||
BigDecimal latitude = new BigDecimal("14.6937");
|
||||
BigDecimal longitude = new BigDecimal("-17.4441");
|
||||
String telephoneSecondaire = "+221338765432";
|
||||
String emailSecondaire = "info@lionsclubdakar.sn";
|
||||
String logo = "logo_lions_dakar.png";
|
||||
Integer niveauHierarchique = 2;
|
||||
|
||||
// Test des setters
|
||||
organisation.setOrganisationParenteId(organisationParenteId);
|
||||
organisation.setNomOrganisationParente(nomOrganisationParente);
|
||||
organisation.setNombreMembres(nombreMembres);
|
||||
organisation.setNombreAdministrateurs(nombreAdministrateurs);
|
||||
organisation.setBudgetAnnuel(budgetAnnuel);
|
||||
organisation.setDevise(devise);
|
||||
organisation.setLatitude(latitude);
|
||||
organisation.setLongitude(longitude);
|
||||
organisation.setTelephoneSecondaire(telephoneSecondaire);
|
||||
organisation.setEmailSecondaire(emailSecondaire);
|
||||
organisation.setLogo(logo);
|
||||
organisation.setNiveauHierarchique(niveauHierarchique);
|
||||
|
||||
// Test des getters
|
||||
assertThat(organisation.getOrganisationParenteId()).isEqualTo(organisationParenteId);
|
||||
assertThat(organisation.getNomOrganisationParente()).isEqualTo(nomOrganisationParente);
|
||||
assertThat(organisation.getNombreMembres()).isEqualTo(nombreMembres);
|
||||
assertThat(organisation.getNombreAdministrateurs()).isEqualTo(nombreAdministrateurs);
|
||||
assertThat(organisation.getBudgetAnnuel()).isEqualTo(budgetAnnuel);
|
||||
assertThat(organisation.getDevise()).isEqualTo(devise);
|
||||
assertThat(organisation.getLatitude()).isEqualTo(latitude);
|
||||
assertThat(organisation.getLongitude()).isEqualTo(longitude);
|
||||
assertThat(organisation.getTelephoneSecondaire()).isEqualTo(telephoneSecondaire);
|
||||
assertThat(organisation.getEmailSecondaire()).isEqualTo(emailSecondaire);
|
||||
assertThat(organisation.getLogo()).isEqualTo(logo);
|
||||
assertThat(organisation.getNiveauHierarchique()).isEqualTo(niveauHierarchique);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes métier")
|
||||
class MethodesMetierTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes de statut")
|
||||
void testMethodesStatut() {
|
||||
// Test isActive
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
assertThat(organisation.isActive()).isTrue();
|
||||
|
||||
organisation.setStatut(StatutOrganisation.INACTIVE);
|
||||
assertThat(organisation.isActive()).isFalse();
|
||||
|
||||
// Test isInactive
|
||||
organisation.setStatut(StatutOrganisation.INACTIVE);
|
||||
assertThat(organisation.isInactive()).isTrue();
|
||||
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
assertThat(organisation.isInactive()).isFalse();
|
||||
|
||||
// Test isSuspendue
|
||||
organisation.setStatut(StatutOrganisation.SUSPENDUE);
|
||||
assertThat(organisation.isSuspendue()).isTrue();
|
||||
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
assertThat(organisation.isSuspendue()).isFalse();
|
||||
|
||||
// Test isEnCreation
|
||||
organisation.setStatut(StatutOrganisation.EN_CREATION);
|
||||
assertThat(organisation.isEnCreation()).isTrue();
|
||||
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
assertThat(organisation.isEnCreation()).isFalse();
|
||||
|
||||
// Test isDissoute
|
||||
organisation.setStatut(StatutOrganisation.DISSOUTE);
|
||||
assertThat(organisation.isDissoute()).isTrue();
|
||||
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
assertThat(organisation.isDissoute()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test calculs d'ancienneté")
|
||||
void testCalculsAnciennete() {
|
||||
// Cas sans date de fondation
|
||||
organisation.setDateFondation(null);
|
||||
assertThat(organisation.getAncienneteAnnees()).isEqualTo(0);
|
||||
assertThat(organisation.getAncienneteMois()).isEqualTo(0);
|
||||
|
||||
// Cas avec date de fondation il y a 5 ans
|
||||
LocalDate dateFondation = LocalDate.now().minusYears(5).minusMonths(3);
|
||||
organisation.setDateFondation(dateFondation);
|
||||
assertThat(organisation.getAncienneteAnnees()).isEqualTo(5);
|
||||
assertThat(organisation.getAncienneteMois()).isEqualTo(63); // 5*12 + 3
|
||||
|
||||
// Cas avec date de fondation récente (moins d'un an)
|
||||
dateFondation = LocalDate.now().minusMonths(8);
|
||||
organisation.setDateFondation(dateFondation);
|
||||
assertThat(organisation.getAncienneteAnnees()).isEqualTo(0);
|
||||
assertThat(organisation.getAncienneteMois()).isEqualTo(8);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test hasGeolocalisation")
|
||||
void testHasGeolocalisation() {
|
||||
// Cas sans géolocalisation
|
||||
organisation.setLatitude(null);
|
||||
organisation.setLongitude(null);
|
||||
assertThat(organisation.hasGeolocalisation()).isFalse();
|
||||
|
||||
// Cas avec latitude seulement
|
||||
organisation.setLatitude(new BigDecimal("14.6937"));
|
||||
organisation.setLongitude(null);
|
||||
assertThat(organisation.hasGeolocalisation()).isFalse();
|
||||
|
||||
// Cas avec longitude seulement
|
||||
organisation.setLatitude(null);
|
||||
organisation.setLongitude(new BigDecimal("-17.4441"));
|
||||
assertThat(organisation.hasGeolocalisation()).isFalse();
|
||||
|
||||
// Cas avec géolocalisation complète
|
||||
organisation.setLatitude(new BigDecimal("14.6937"));
|
||||
organisation.setLongitude(new BigDecimal("-17.4441"));
|
||||
assertThat(organisation.hasGeolocalisation()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test hiérarchie")
|
||||
void testHierarchie() {
|
||||
// Test isOrganisationRacine
|
||||
organisation.setOrganisationParenteId(null);
|
||||
assertThat(organisation.isOrganisationRacine()).isTrue();
|
||||
|
||||
organisation.setOrganisationParenteId(UUID.randomUUID());
|
||||
assertThat(organisation.isOrganisationRacine()).isFalse();
|
||||
|
||||
// Test hasSousOrganisations
|
||||
organisation.setNiveauHierarchique(null);
|
||||
assertThat(organisation.hasSousOrganisations()).isFalse();
|
||||
|
||||
organisation.setNiveauHierarchique(0);
|
||||
assertThat(organisation.hasSousOrganisations()).isFalse();
|
||||
|
||||
organisation.setNiveauHierarchique(1);
|
||||
assertThat(organisation.hasSousOrganisations()).isTrue();
|
||||
|
||||
organisation.setNiveauHierarchique(3);
|
||||
assertThat(organisation.hasSousOrganisations()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getNomAffichage")
|
||||
void testGetNomAffichage() {
|
||||
String nomComplet = "Lions Club Dakar Plateau";
|
||||
String nomCourt = "LCD Plateau";
|
||||
|
||||
// Cas avec nom court
|
||||
organisation.setNom(nomComplet);
|
||||
organisation.setNomCourt(nomCourt);
|
||||
assertThat(organisation.getNomAffichage()).isEqualTo(nomCourt);
|
||||
|
||||
// Cas avec nom court vide
|
||||
organisation.setNomCourt("");
|
||||
assertThat(organisation.getNomAffichage()).isEqualTo(nomComplet);
|
||||
|
||||
// Cas avec nom court null
|
||||
organisation.setNomCourt(null);
|
||||
assertThat(organisation.getNomAffichage()).isEqualTo(nomComplet);
|
||||
|
||||
// Cas avec nom court contenant seulement des espaces
|
||||
organisation.setNomCourt(" ");
|
||||
assertThat(organisation.getNomAffichage()).isEqualTo(nomComplet);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getAdresseComplete")
|
||||
void testGetAdresseComplete() {
|
||||
// Cas avec adresse complète
|
||||
organisation.setAdresse("123 Avenue Bourguiba");
|
||||
organisation.setVille("Dakar");
|
||||
organisation.setCodePostal("10000");
|
||||
organisation.setRegion("Dakar");
|
||||
organisation.setPays("Sénégal");
|
||||
|
||||
String adresseComplete = organisation.getAdresseComplete();
|
||||
assertThat(adresseComplete).contains("123 Avenue Bourguiba");
|
||||
assertThat(adresseComplete).contains("Dakar");
|
||||
assertThat(adresseComplete).contains("10000");
|
||||
assertThat(adresseComplete).contains("Sénégal");
|
||||
|
||||
// Cas avec adresse partielle
|
||||
organisation.setAdresse("123 Avenue Bourguiba");
|
||||
organisation.setVille("Dakar");
|
||||
organisation.setCodePostal(null);
|
||||
organisation.setRegion(null);
|
||||
organisation.setPays(null);
|
||||
|
||||
adresseComplete = organisation.getAdresseComplete();
|
||||
assertThat(adresseComplete).isEqualTo("123 Avenue Bourguiba, Dakar");
|
||||
|
||||
// Cas avec adresse vide
|
||||
organisation.setAdresse(null);
|
||||
organisation.setVille(null);
|
||||
organisation.setCodePostal(null);
|
||||
organisation.setRegion(null);
|
||||
organisation.setPays(null);
|
||||
|
||||
adresseComplete = organisation.getAdresseComplete();
|
||||
assertThat(adresseComplete).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getRatioAdministrateurs")
|
||||
void testGetRatioAdministrateurs() {
|
||||
// Cas sans membres
|
||||
organisation.setNombreMembres(null);
|
||||
organisation.setNombreAdministrateurs(5);
|
||||
assertThat(organisation.getRatioAdministrateurs()).isEqualTo(0.0);
|
||||
|
||||
organisation.setNombreMembres(0);
|
||||
organisation.setNombreAdministrateurs(5);
|
||||
assertThat(organisation.getRatioAdministrateurs()).isEqualTo(0.0);
|
||||
|
||||
// Cas sans administrateurs
|
||||
organisation.setNombreMembres(100);
|
||||
organisation.setNombreAdministrateurs(null);
|
||||
assertThat(organisation.getRatioAdministrateurs()).isEqualTo(0.0);
|
||||
|
||||
// Cas normal
|
||||
organisation.setNombreMembres(100);
|
||||
organisation.setNombreAdministrateurs(10);
|
||||
assertThat(organisation.getRatioAdministrateurs()).isEqualTo(10.0);
|
||||
|
||||
organisation.setNombreMembres(50);
|
||||
organisation.setNombreAdministrateurs(5);
|
||||
assertThat(organisation.getRatioAdministrateurs()).isEqualTo(10.0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test hasBudget")
|
||||
void testHasBudget() {
|
||||
// Cas sans budget
|
||||
organisation.setBudgetAnnuel(null);
|
||||
assertThat(organisation.hasBudget()).isFalse();
|
||||
|
||||
// Cas avec budget zéro
|
||||
organisation.setBudgetAnnuel(BigDecimal.ZERO);
|
||||
assertThat(organisation.hasBudget()).isFalse();
|
||||
|
||||
// Cas avec budget négatif
|
||||
organisation.setBudgetAnnuel(new BigDecimal("-1000.00"));
|
||||
assertThat(organisation.hasBudget()).isFalse();
|
||||
|
||||
// Cas avec budget positif
|
||||
organisation.setBudgetAnnuel(new BigDecimal("5000000.00"));
|
||||
assertThat(organisation.hasBudget()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes d'action")
|
||||
void testMethodesAction() {
|
||||
String utilisateur = "admin";
|
||||
|
||||
// Test activer
|
||||
organisation.setStatut(StatutOrganisation.INACTIVE);
|
||||
organisation.activer(utilisateur);
|
||||
assertThat(organisation.getStatut()).isEqualTo(StatutOrganisation.ACTIVE);
|
||||
|
||||
// Test suspendre
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
organisation.suspendre(utilisateur);
|
||||
assertThat(organisation.getStatut()).isEqualTo(StatutOrganisation.SUSPENDUE);
|
||||
|
||||
// Test dissoudre
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
organisation.setAccepteNouveauxMembres(true);
|
||||
organisation.dissoudre(utilisateur);
|
||||
assertThat(organisation.getStatut()).isEqualTo(StatutOrganisation.DISSOUTE);
|
||||
assertThat(organisation.getAccepteNouveauxMembres()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test gestion des membres")
|
||||
void testGestionMembres() {
|
||||
String utilisateur = "admin";
|
||||
|
||||
// Test mettreAJourNombreMembres
|
||||
organisation.mettreAJourNombreMembres(50, utilisateur);
|
||||
assertThat(organisation.getNombreMembres()).isEqualTo(50);
|
||||
|
||||
// Test ajouterMembre
|
||||
organisation.setNombreMembres(null);
|
||||
organisation.ajouterMembre(utilisateur);
|
||||
assertThat(organisation.getNombreMembres()).isEqualTo(1);
|
||||
|
||||
organisation.ajouterMembre(utilisateur);
|
||||
assertThat(organisation.getNombreMembres()).isEqualTo(2);
|
||||
|
||||
// Test retirerMembre
|
||||
organisation.setNombreMembres(5);
|
||||
organisation.retirerMembre(utilisateur);
|
||||
assertThat(organisation.getNombreMembres()).isEqualTo(4);
|
||||
|
||||
// Test retirerMembre avec 0 membres
|
||||
organisation.setNombreMembres(0);
|
||||
organisation.retirerMembre(utilisateur);
|
||||
assertThat(organisation.getNombreMembres()).isEqualTo(0);
|
||||
|
||||
// Test retirerMembre avec null
|
||||
organisation.setNombreMembres(null);
|
||||
organisation.retirerMembre(utilisateur);
|
||||
assertThat(organisation.getNombreMembres()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test toString")
|
||||
void testToString() {
|
||||
organisation.setNom("Lions Club Dakar");
|
||||
organisation.setNomCourt("LCD");
|
||||
organisation.setTypeOrganisation(TypeOrganisation.LIONS_CLUB);
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
organisation.setVille("Dakar");
|
||||
organisation.setPays("Sénégal");
|
||||
organisation.setNombreMembres(50);
|
||||
organisation.setDateFondation(LocalDate.of(2020, 1, 15));
|
||||
|
||||
String result = organisation.toString();
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result).contains("OrganisationDTO");
|
||||
assertThat(result).contains("nom='Lions Club Dakar'");
|
||||
assertThat(result).contains("nomCourt='LCD'");
|
||||
assertThat(result).contains("typeOrganisation=LIONS_CLUB");
|
||||
assertThat(result).contains("statut=ACTIVE");
|
||||
assertThat(result).contains("ville='Dakar'");
|
||||
assertThat(result).contains("pays='Sénégal'");
|
||||
assertThat(result).contains("nombreMembres=50");
|
||||
assertThat(result).contains("anciennete=" + organisation.getAncienneteAnnees() + " ans");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test branches supplémentaires getAdresseComplete")
|
||||
void testBranchesSupplementairesAdresseComplete() {
|
||||
// Test avec ville seulement (sans adresse)
|
||||
organisation.setAdresse(null);
|
||||
organisation.setVille("Dakar");
|
||||
organisation.setCodePostal(null);
|
||||
organisation.setRegion(null);
|
||||
organisation.setPays(null);
|
||||
assertThat(organisation.getAdresseComplete()).isEqualTo("Dakar");
|
||||
|
||||
// Test avec code postal seulement (sans adresse ni ville)
|
||||
organisation.setAdresse(null);
|
||||
organisation.setVille(null);
|
||||
organisation.setCodePostal("12000");
|
||||
organisation.setRegion(null);
|
||||
organisation.setPays(null);
|
||||
assertThat(organisation.getAdresseComplete()).isEqualTo("12000");
|
||||
|
||||
// Test avec région seulement
|
||||
organisation.setAdresse(null);
|
||||
organisation.setVille(null);
|
||||
organisation.setCodePostal(null);
|
||||
organisation.setRegion("Dakar");
|
||||
organisation.setPays(null);
|
||||
assertThat(organisation.getAdresseComplete()).isEqualTo("Dakar");
|
||||
|
||||
// Test avec pays seulement
|
||||
organisation.setAdresse(null);
|
||||
organisation.setVille(null);
|
||||
organisation.setCodePostal(null);
|
||||
organisation.setRegion(null);
|
||||
organisation.setPays("Sénégal");
|
||||
assertThat(organisation.getAdresseComplete()).isEqualTo("Sénégal");
|
||||
|
||||
// Test avec ville et code postal (sans adresse)
|
||||
organisation.setAdresse(null);
|
||||
organisation.setVille("Dakar");
|
||||
organisation.setCodePostal("12000");
|
||||
organisation.setRegion(null);
|
||||
organisation.setPays(null);
|
||||
assertThat(organisation.getAdresseComplete()).isEqualTo("Dakar 12000");
|
||||
|
||||
// Test avec ville et région (sans adresse)
|
||||
organisation.setAdresse(null);
|
||||
organisation.setVille("Dakar");
|
||||
organisation.setCodePostal(null);
|
||||
organisation.setRegion("Dakar");
|
||||
organisation.setPays(null);
|
||||
assertThat(organisation.getAdresseComplete()).isEqualTo("Dakar, Dakar");
|
||||
|
||||
// Test avec ville et pays (sans adresse)
|
||||
organisation.setAdresse(null);
|
||||
organisation.setVille("Dakar");
|
||||
organisation.setCodePostal(null);
|
||||
organisation.setRegion(null);
|
||||
organisation.setPays("Sénégal");
|
||||
assertThat(organisation.getAdresseComplete()).isEqualTo("Dakar, Sénégal");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package dev.lions.unionflow.server.api.dto.organisation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.organisation.StatutOrganisation;
|
||||
import dev.lions.unionflow.server.api.enums.organisation.TypeOrganisation;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires simples pour OrganisationDTO
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@DisplayName("Tests OrganisationDTO")
|
||||
class OrganisationDTOSimpleTest {
|
||||
|
||||
private OrganisationDTO organisation;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
organisation = new OrganisationDTO();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test création et getters/setters de base")
|
||||
void testCreationEtGettersSetters() {
|
||||
// Données de test
|
||||
String nom = "Lions Club Dakar";
|
||||
String nomCourt = "LCD";
|
||||
String description = "Club service de Dakar";
|
||||
StatutOrganisation statut = StatutOrganisation.ACTIVE;
|
||||
TypeOrganisation typeOrganisation = TypeOrganisation.LIONS_CLUB;
|
||||
String adresse = "Avenue Bourguiba, Dakar";
|
||||
String telephone = "+221 33 123 45 67";
|
||||
String email = "contact@lionsclubdakar.sn";
|
||||
|
||||
// Test des setters
|
||||
organisation.setNom(nom);
|
||||
organisation.setNomCourt(nomCourt);
|
||||
organisation.setDescription(description);
|
||||
organisation.setStatut(statut);
|
||||
organisation.setTypeOrganisation(typeOrganisation);
|
||||
organisation.setAdresse(adresse);
|
||||
organisation.setTelephone(telephone);
|
||||
organisation.setEmail(email);
|
||||
|
||||
// Test des getters
|
||||
assertThat(organisation.getNom()).isEqualTo(nom);
|
||||
assertThat(organisation.getNomCourt()).isEqualTo(nomCourt);
|
||||
assertThat(organisation.getDescription()).isEqualTo(description);
|
||||
assertThat(organisation.getStatut()).isEqualTo(statut);
|
||||
assertThat(organisation.getTypeOrganisation()).isEqualTo(typeOrganisation);
|
||||
assertThat(organisation.getAdresse()).isEqualTo(adresse);
|
||||
assertThat(organisation.getTelephone()).isEqualTo(telephone);
|
||||
assertThat(organisation.getEmail()).isEqualTo(email);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes utilitaires ajoutées")
|
||||
void testMethodesUtilitaires() {
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
organisation.setTypeOrganisation(TypeOrganisation.LIONS_CLUB);
|
||||
|
||||
// Test des méthodes getLibelle
|
||||
assertThat(organisation.getStatutLibelle()).isNotNull();
|
||||
assertThat(organisation.getTypeLibelle()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test validation des énumérations")
|
||||
void testValidationEnumerations() {
|
||||
// Test que toutes les énumérations sont bien supportées
|
||||
for (StatutOrganisation statut : StatutOrganisation.values()) {
|
||||
organisation.setStatut(statut);
|
||||
assertThat(organisation.getStatut()).isEqualTo(statut);
|
||||
}
|
||||
|
||||
for (TypeOrganisation type : TypeOrganisation.values()) {
|
||||
organisation.setTypeOrganisation(type);
|
||||
assertThat(organisation.getTypeOrganisation()).isEqualTo(type);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test héritage BaseDTO")
|
||||
void testHeritageBaseDTO() {
|
||||
assertThat(organisation.getId()).isNotNull();
|
||||
assertThat(organisation.getDateCreation()).isNotNull();
|
||||
assertThat(organisation.isActif()).isTrue();
|
||||
assertThat(organisation.getVersion()).isEqualTo(0L);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,371 @@
|
||||
package dev.lions.unionflow.server.api.dto.organisation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.organisation.StatutOrganisation;
|
||||
import dev.lions.unionflow.server.api.enums.organisation.TypeOrganisation;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires pour OrganisationDTO
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@DisplayName("Tests OrganisationDTO")
|
||||
class OrganisationDTOTest {
|
||||
|
||||
private OrganisationDTO organisation;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
organisation = new OrganisationDTO();
|
||||
organisation.setNom("Lions Club Dakar");
|
||||
organisation.setNomCourt("LCD");
|
||||
organisation.setTypeOrganisation(TypeOrganisation.LIONS_CLUB);
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
organisation.setVille("Dakar");
|
||||
organisation.setPays("Sénégal");
|
||||
organisation.setDateCreation(LocalDateTime.now().minusYears(5));
|
||||
organisation.setNombreMembres(150);
|
||||
organisation.setNombreAdministrateurs(10);
|
||||
organisation.setLatitude(new BigDecimal("14.6937"));
|
||||
organisation.setLongitude(new BigDecimal("-17.4441"));
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests de Construction")
|
||||
class ConstructionTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constructeur par défaut")
|
||||
void testConstructeurParDefaut() {
|
||||
OrganisationDTO newOrganisation = new OrganisationDTO();
|
||||
|
||||
assertThat(newOrganisation.getId()).isNotNull();
|
||||
assertThat(newOrganisation.getDateCreation()).isNotNull();
|
||||
assertThat(newOrganisation.isActif()).isTrue();
|
||||
assertThat(newOrganisation.getVersion()).isEqualTo(0L);
|
||||
assertThat(newOrganisation.getStatut()).isEqualTo(StatutOrganisation.ACTIVE);
|
||||
assertThat(newOrganisation.getTypeOrganisation()).isEqualTo(TypeOrganisation.ASSOCIATION);
|
||||
assertThat(newOrganisation.getDevise()).isEqualTo("XOF");
|
||||
assertThat(newOrganisation.getNiveauHierarchique()).isEqualTo(0);
|
||||
assertThat(newOrganisation.getNombreMembres()).isEqualTo(0);
|
||||
assertThat(newOrganisation.getNombreAdministrateurs()).isEqualTo(0);
|
||||
assertThat(newOrganisation.getOrganisationPublique()).isTrue();
|
||||
assertThat(newOrganisation.getAccepteNouveauxMembres()).isTrue();
|
||||
assertThat(newOrganisation.getCotisationObligatoire()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constructeur avec paramètres")
|
||||
void testConstructeurAvecParametres() {
|
||||
String nom = "Association des Jeunes";
|
||||
TypeOrganisation type = TypeOrganisation.ASSOCIATION;
|
||||
|
||||
OrganisationDTO newOrganisation = new OrganisationDTO(nom, type);
|
||||
|
||||
assertThat(newOrganisation.getNom()).isEqualTo(nom);
|
||||
assertThat(newOrganisation.getTypeOrganisation()).isEqualTo(type);
|
||||
assertThat(newOrganisation.getStatut()).isEqualTo(StatutOrganisation.ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des Méthodes de Statut")
|
||||
class MethodesStatutTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test estActive")
|
||||
void testEstActive() {
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
assertThat(organisation.estActive()).isTrue();
|
||||
|
||||
organisation.setStatut(StatutOrganisation.INACTIVE);
|
||||
assertThat(organisation.estActive()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test estInactive")
|
||||
void testEstInactive() {
|
||||
organisation.setStatut(StatutOrganisation.INACTIVE);
|
||||
assertThat(organisation.estInactive()).isTrue();
|
||||
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
assertThat(organisation.estInactive()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test estSuspendue")
|
||||
void testEstSuspendue() {
|
||||
organisation.setStatut(StatutOrganisation.SUSPENDUE);
|
||||
assertThat(organisation.estSuspendue()).isTrue();
|
||||
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
assertThat(organisation.estSuspendue()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test estEnCreation")
|
||||
void testEstEnCreation() {
|
||||
organisation.setStatut(StatutOrganisation.EN_CREATION);
|
||||
assertThat(organisation.estEnCreation()).isTrue();
|
||||
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
assertThat(organisation.estEnCreation()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test estDissoute")
|
||||
void testEstDissoute() {
|
||||
organisation.setStatut(StatutOrganisation.DISSOUTE);
|
||||
assertThat(organisation.estDissoute()).isTrue();
|
||||
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
assertThat(organisation.estDissoute()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des Méthodes Utilitaires")
|
||||
class MethodesUtilitairesTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getAncienneteAnnees")
|
||||
void testGetAncienneteAnnees() {
|
||||
organisation.setDateFondation(LocalDate.now().minusYears(5));
|
||||
assertThat(organisation.getAncienneteAnnees()).isEqualTo(5);
|
||||
|
||||
organisation.setDateFondation(LocalDate.now().minusMonths(6));
|
||||
assertThat(organisation.getAncienneteAnnees()).isEqualTo(0);
|
||||
|
||||
organisation.setDateCreation(null);
|
||||
assertThat(organisation.getAncienneteAnnees()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test possedGeolocalisation")
|
||||
void testPossedGeolocalisation() {
|
||||
organisation.setLatitude(new BigDecimal("14.6937"));
|
||||
organisation.setLongitude(new BigDecimal("-17.4441"));
|
||||
assertThat(organisation.possedGeolocalisation()).isTrue();
|
||||
|
||||
organisation.setLatitude(null);
|
||||
assertThat(organisation.possedGeolocalisation()).isFalse();
|
||||
|
||||
organisation.setLatitude(new BigDecimal("14.6937"));
|
||||
organisation.setLongitude(null);
|
||||
assertThat(organisation.possedGeolocalisation()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test estOrganisationRacine")
|
||||
void testEstOrganisationRacine() {
|
||||
organisation.setOrganisationParenteId(null);
|
||||
assertThat(organisation.estOrganisationRacine()).isTrue();
|
||||
|
||||
organisation.setOrganisationParenteId(UUID.randomUUID());
|
||||
assertThat(organisation.estOrganisationRacine()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test possedeSousOrganisations")
|
||||
void testPossedeSousOrganisations() {
|
||||
organisation.setNiveauHierarchique(2);
|
||||
assertThat(organisation.possedeSousOrganisations()).isTrue();
|
||||
|
||||
organisation.setNiveauHierarchique(0);
|
||||
assertThat(organisation.possedeSousOrganisations()).isFalse();
|
||||
|
||||
organisation.setNiveauHierarchique(null);
|
||||
assertThat(organisation.possedeSousOrganisations()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getNomAffichage")
|
||||
void testGetNomAffichage() {
|
||||
organisation.setNom("Lions Club Dakar");
|
||||
organisation.setNomCourt("LCD");
|
||||
assertThat(organisation.getNomAffichage()).isEqualTo("LCD");
|
||||
|
||||
organisation.setNomCourt(null);
|
||||
assertThat(organisation.getNomAffichage()).isEqualTo("Lions Club Dakar");
|
||||
|
||||
organisation.setNomCourt("");
|
||||
assertThat(organisation.getNomAffichage()).isEqualTo("Lions Club Dakar");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getStatutLibelle")
|
||||
void testGetStatutLibelle() {
|
||||
organisation.setStatut(StatutOrganisation.ACTIVE);
|
||||
assertThat(organisation.getStatutLibelle()).isEqualTo("Active");
|
||||
|
||||
organisation.setStatut(null);
|
||||
assertThat(organisation.getStatutLibelle()).isEqualTo("Non défini");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getTypeLibelle")
|
||||
void testGetTypeLibelle() {
|
||||
organisation.setTypeOrganisation(TypeOrganisation.LIONS_CLUB);
|
||||
assertThat(organisation.getTypeLibelle()).isEqualTo("Lions Club");
|
||||
|
||||
organisation.setTypeOrganisation(null);
|
||||
assertThat(organisation.getTypeLibelle()).isEqualTo("Non défini");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getRatioAdministrateurs")
|
||||
void testGetRatioAdministrateurs() {
|
||||
organisation.setNombreMembres(100);
|
||||
organisation.setNombreAdministrateurs(10);
|
||||
assertThat(organisation.getRatioAdministrateurs()).isEqualTo(10.0);
|
||||
|
||||
organisation.setNombreMembres(0);
|
||||
assertThat(organisation.getRatioAdministrateurs()).isEqualTo(0.0);
|
||||
|
||||
organisation.setNombreMembres(null);
|
||||
assertThat(organisation.getRatioAdministrateurs()).isEqualTo(0.0);
|
||||
|
||||
organisation.setNombreMembres(100);
|
||||
organisation.setNombreAdministrateurs(null);
|
||||
assertThat(organisation.getRatioAdministrateurs()).isEqualTo(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des Méthodes d'Action")
|
||||
class MethodesActionTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test activer")
|
||||
void testActiver() {
|
||||
String utilisateur = "admin";
|
||||
organisation.activer(utilisateur);
|
||||
|
||||
assertThat(organisation.getStatut()).isEqualTo(StatutOrganisation.ACTIVE);
|
||||
assertThat(organisation.getModifiePar()).isEqualTo(utilisateur);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test suspendre")
|
||||
void testSuspendre() {
|
||||
String utilisateur = "admin";
|
||||
|
||||
organisation.suspendre(utilisateur);
|
||||
|
||||
assertThat(organisation.getStatut()).isEqualTo(StatutOrganisation.SUSPENDUE);
|
||||
assertThat(organisation.getModifiePar()).isEqualTo(utilisateur);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test dissoudre")
|
||||
void testDissoudre() {
|
||||
String utilisateur = "admin";
|
||||
|
||||
organisation.dissoudre(utilisateur);
|
||||
|
||||
assertThat(organisation.getStatut()).isEqualTo(StatutOrganisation.DISSOUTE);
|
||||
assertThat(organisation.getModifiePar()).isEqualTo(utilisateur);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test desactiver")
|
||||
void testDesactiver() {
|
||||
String utilisateur = "admin";
|
||||
organisation.desactiver(utilisateur);
|
||||
|
||||
assertThat(organisation.getStatut()).isEqualTo(StatutOrganisation.INACTIVE);
|
||||
assertThat(organisation.getAccepteNouveauxMembres()).isFalse();
|
||||
assertThat(organisation.getModifiePar()).isEqualTo(utilisateur);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test ajouterMembre")
|
||||
void testAjouterMembre() {
|
||||
String utilisateur = "secretaire";
|
||||
organisation.setNombreMembres(100);
|
||||
|
||||
organisation.ajouterMembre(utilisateur);
|
||||
|
||||
assertThat(organisation.getNombreMembres()).isEqualTo(101);
|
||||
assertThat(organisation.getModifiePar()).isEqualTo(utilisateur);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test retirerMembre")
|
||||
void testRetirerMembre() {
|
||||
String utilisateur = "secretaire";
|
||||
organisation.setNombreMembres(100);
|
||||
|
||||
organisation.retirerMembre(utilisateur);
|
||||
|
||||
assertThat(organisation.getNombreMembres()).isEqualTo(99);
|
||||
assertThat(organisation.getModifiePar()).isEqualTo(utilisateur);
|
||||
|
||||
// Test avec 0 membres
|
||||
organisation.setNombreMembres(0);
|
||||
organisation.retirerMembre(utilisateur);
|
||||
assertThat(organisation.getNombreMembres()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test ajouterAdministrateur")
|
||||
void testAjouterAdministrateur() {
|
||||
String utilisateur = "president";
|
||||
organisation.setNombreAdministrateurs(5);
|
||||
|
||||
organisation.ajouterAdministrateur(utilisateur);
|
||||
|
||||
assertThat(organisation.getNombreAdministrateurs()).isEqualTo(6);
|
||||
assertThat(organisation.getModifiePar()).isEqualTo(utilisateur);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test retirerAdministrateur")
|
||||
void testRetirerAdministrateur() {
|
||||
String utilisateur = "president";
|
||||
organisation.setNombreAdministrateurs(5);
|
||||
|
||||
organisation.retirerAdministrateur(utilisateur);
|
||||
|
||||
assertThat(organisation.getNombreAdministrateurs()).isEqualTo(4);
|
||||
assertThat(organisation.getModifiePar()).isEqualTo(utilisateur);
|
||||
|
||||
// Test avec 0 administrateurs
|
||||
organisation.setNombreAdministrateurs(0);
|
||||
organisation.retirerAdministrateur(utilisateur);
|
||||
assertThat(organisation.getNombreAdministrateurs()).isEqualTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests de Validation")
|
||||
class ValidationTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test toString")
|
||||
void testToString() {
|
||||
organisation.setDateFondation(LocalDate.now().minusYears(5));
|
||||
String result = organisation.toString();
|
||||
|
||||
assertThat(result).contains("Lions Club Dakar");
|
||||
assertThat(result).contains("LCD");
|
||||
assertThat(result).contains("LIONS_CLUB");
|
||||
assertThat(result).contains("ACTIVE");
|
||||
assertThat(result).contains("Dakar");
|
||||
assertThat(result).contains("Sénégal");
|
||||
assertThat(result).contains("150");
|
||||
assertThat(result).contains("5 ans");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,28 +68,33 @@ class WaveBalanceDTOBasicTest {
|
||||
balanceAvecSoldeDisponibleNull.setSoldeDisponible(new BigDecimal("100000.00"));
|
||||
balanceAvecSoldeDisponibleNull.setSoldeEnAttente(new BigDecimal("25000.00"));
|
||||
// Vérifier que le total est calculé
|
||||
assertThat(balanceAvecSoldeDisponibleNull.getSoldeTotal()).isEqualByComparingTo(new BigDecimal("125000.00"));
|
||||
assertThat(balanceAvecSoldeDisponibleNull.getSoldeTotal())
|
||||
.isEqualByComparingTo(new BigDecimal("125000.00"));
|
||||
|
||||
// Maintenant mettre soldeDisponible à null - le total ne devrait pas être recalculé
|
||||
balanceAvecSoldeDisponibleNull.setSoldeDisponible(null);
|
||||
assertThat(balanceAvecSoldeDisponibleNull.getSoldeTotal()).isEqualByComparingTo(new BigDecimal("125000.00")); // Garde l'ancienne valeur
|
||||
assertThat(balanceAvecSoldeDisponibleNull.getSoldeTotal())
|
||||
.isEqualByComparingTo(new BigDecimal("125000.00")); // Garde l'ancienne valeur
|
||||
|
||||
// Test avec soldeEnAttente null - même principe
|
||||
WaveBalanceDTO balanceAvecSoldeEnAttenteNull = new WaveBalanceDTO();
|
||||
balanceAvecSoldeEnAttenteNull.setSoldeDisponible(new BigDecimal("150000.00"));
|
||||
balanceAvecSoldeEnAttenteNull.setSoldeEnAttente(new BigDecimal("30000.00"));
|
||||
// Vérifier que le total est calculé
|
||||
assertThat(balanceAvecSoldeEnAttenteNull.getSoldeTotal()).isEqualByComparingTo(new BigDecimal("180000.00"));
|
||||
assertThat(balanceAvecSoldeEnAttenteNull.getSoldeTotal())
|
||||
.isEqualByComparingTo(new BigDecimal("180000.00"));
|
||||
|
||||
// Maintenant mettre soldeEnAttente à null - le total ne devrait pas être recalculé
|
||||
balanceAvecSoldeEnAttenteNull.setSoldeEnAttente(null);
|
||||
assertThat(balanceAvecSoldeEnAttenteNull.getSoldeTotal()).isEqualByComparingTo(new BigDecimal("180000.00")); // Garde l'ancienne valeur
|
||||
assertThat(balanceAvecSoldeEnAttenteNull.getSoldeTotal())
|
||||
.isEqualByComparingTo(new BigDecimal("180000.00")); // Garde l'ancienne valeur
|
||||
|
||||
// Test avec les deux null dès le début
|
||||
WaveBalanceDTO balanceAvecLesDeuxNull = new WaveBalanceDTO();
|
||||
balanceAvecLesDeuxNull.setSoldeDisponible(null);
|
||||
balanceAvecLesDeuxNull.setSoldeEnAttente(null);
|
||||
assertThat(balanceAvecLesDeuxNull.getSoldeTotal()).isNull(); // Pas calculé car les deux sont null dès le début
|
||||
assertThat(balanceAvecLesDeuxNull.getSoldeTotal())
|
||||
.isNull(); // Pas calculé car les deux sont null dès le début
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +151,8 @@ class WaveBalanceDTOBasicTest {
|
||||
assertThat(balance.getDateDerniereSynchronisation()).isEqualTo(dateDerniereSynchronisation);
|
||||
assertThat(balance.getStatutWallet()).isEqualTo(statutWallet);
|
||||
assertThat(balance.getLimiteQuotidienne()).isEqualByComparingTo(limiteQuotidienne);
|
||||
assertThat(balance.getMontantUtiliseAujourdhui()).isEqualByComparingTo(montantUtiliseAujourdhui);
|
||||
assertThat(balance.getMontantUtiliseAujourdhui())
|
||||
.isEqualByComparingTo(montantUtiliseAujourdhui);
|
||||
assertThat(balance.getLimiteMensuelle()).isEqualByComparingTo(limiteMensuelle);
|
||||
assertThat(balance.getMontantUtiliseCeMois()).isEqualByComparingTo(montantUtiliseCeMois);
|
||||
assertThat(balance.getNombreTransactionsAujourdhui()).isEqualTo(nombreTransactionsAujourdhui);
|
||||
@@ -239,7 +245,8 @@ class WaveBalanceDTOBasicTest {
|
||||
|
||||
// Limite restante = 100000 - 30000 = 70000
|
||||
// Solde disponible aujourd'hui = min(200000, 70000) = 70000
|
||||
assertThat(balance.getSoldeDisponibleAujourdhui()).isEqualByComparingTo(new BigDecimal("70000.00"));
|
||||
assertThat(balance.getSoldeDisponibleAujourdhui())
|
||||
.isEqualByComparingTo(new BigDecimal("70000.00"));
|
||||
|
||||
// Test sans limite
|
||||
balance.setLimiteQuotidienne(null);
|
||||
@@ -271,8 +278,10 @@ class WaveBalanceDTOBasicTest {
|
||||
|
||||
balance.mettreAJourApresTransaction(montantTransaction);
|
||||
|
||||
assertThat(balance.getMontantUtiliseAujourdhui()).isEqualByComparingTo(new BigDecimal("75000.00"));
|
||||
assertThat(balance.getMontantUtiliseCeMois()).isEqualByComparingTo(new BigDecimal("525000.00"));
|
||||
assertThat(balance.getMontantUtiliseAujourdhui())
|
||||
.isEqualByComparingTo(new BigDecimal("75000.00"));
|
||||
assertThat(balance.getMontantUtiliseCeMois())
|
||||
.isEqualByComparingTo(new BigDecimal("525000.00"));
|
||||
assertThat(balance.getNombreTransactionsAujourdhui()).isEqualTo(6);
|
||||
assertThat(balance.getNombreTransactionsCeMois()).isEqualTo(46);
|
||||
assertThat(balance.getDateDerniereMiseAJour()).isNotNull();
|
||||
|
||||
@@ -170,7 +170,7 @@ class WaveCheckoutSessionDTOBasicTest {
|
||||
@DisplayName("Test types de paiement valides")
|
||||
void testTypesPaiementValides() {
|
||||
String[] typesValides = {"COTISATION", "ABONNEMENT", "DON", "EVENEMENT", "FORMATION", "AUTRE"};
|
||||
|
||||
|
||||
for (String type : typesValides) {
|
||||
session.setTypePaiement(type);
|
||||
assertThat(session.getTypePaiement()).isEqualTo(type);
|
||||
@@ -181,7 +181,7 @@ class WaveCheckoutSessionDTOBasicTest {
|
||||
@DisplayName("Test statuts de session")
|
||||
void testStatutsSession() {
|
||||
StatutSession[] statuts = StatutSession.values();
|
||||
|
||||
|
||||
for (StatutSession statut : statuts) {
|
||||
session.setStatut(statut);
|
||||
assertThat(session.getStatut()).isEqualTo(statut);
|
||||
@@ -192,7 +192,7 @@ class WaveCheckoutSessionDTOBasicTest {
|
||||
@DisplayName("Test valeurs par défaut")
|
||||
void testValeursParDefaut() {
|
||||
WaveCheckoutSessionDTO newSession = new WaveCheckoutSessionDTO();
|
||||
|
||||
|
||||
assertThat(newSession.getDevise()).isEqualTo("XOF");
|
||||
assertThat(newSession.getStatut()).isEqualTo(StatutSession.PENDING);
|
||||
assertThat(newSession.getNombreTentatives()).isEqualTo(0);
|
||||
@@ -205,7 +205,7 @@ class WaveCheckoutSessionDTOBasicTest {
|
||||
session.setCodeErreurWave("E001");
|
||||
session.setMessageErreurWave("Paiement échoué");
|
||||
session.setStatut(StatutSession.FAILED);
|
||||
|
||||
|
||||
assertThat(session.getCodeErreurWave()).isEqualTo("E001");
|
||||
assertThat(session.getMessageErreurWave()).isEqualTo("Paiement échoué");
|
||||
assertThat(session.getStatut()).isEqualTo(StatutSession.FAILED);
|
||||
@@ -216,11 +216,11 @@ class WaveCheckoutSessionDTOBasicTest {
|
||||
void testGestionWebhook() {
|
||||
LocalDateTime dateWebhook = LocalDateTime.now();
|
||||
String donneesWebhook = "{\"event\":\"payment.completed\"}";
|
||||
|
||||
|
||||
session.setWebhookRecu(true);
|
||||
session.setDateWebhook(dateWebhook);
|
||||
session.setDonneesWebhook(donneesWebhook);
|
||||
|
||||
|
||||
assertThat(session.getWebhookRecu()).isTrue();
|
||||
assertThat(session.getDateWebhook()).isEqualTo(dateWebhook);
|
||||
assertThat(session.getDonneesWebhook()).isEqualTo(donneesWebhook);
|
||||
|
||||
@@ -212,16 +212,17 @@ class WaveWebhookDTOBasicTest {
|
||||
webhook.setTypeEvenement(null);
|
||||
|
||||
assertThat(webhook.getTypeEvenement()).isNull();
|
||||
assertThat(webhook.getCodeEvenement()).isEqualTo("checkout.complete"); // Garde l'ancienne valeur
|
||||
assertThat(webhook.getCodeEvenement())
|
||||
.isEqualTo("checkout.complete"); // Garde l'ancienne valeur
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test setCodeEvenement avec mise à jour du type")
|
||||
void testSetCodeEvenementAvecMiseAJourType() {
|
||||
String codeEvenement = "checkout.completed";
|
||||
|
||||
|
||||
webhook.setCodeEvenement(codeEvenement);
|
||||
|
||||
|
||||
assertThat(webhook.getCodeEvenement()).isEqualTo(codeEvenement);
|
||||
assertThat(webhook.getTypeEvenement()).isEqualTo(TypeEvenement.fromCode(codeEvenement));
|
||||
}
|
||||
@@ -308,7 +309,7 @@ class WaveWebhookDTOBasicTest {
|
||||
webhook.setMontantTransaction(new BigDecimal("25000.00"));
|
||||
|
||||
String result = webhook.toString();
|
||||
|
||||
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result).contains("WaveWebhookDTO");
|
||||
assertThat(result).contains("webhook_123");
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.PrioriteAide;
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires pour DemandeAideDTO
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@DisplayName("Tests DemandeAideDTO")
|
||||
class DemandeAideDTOTest {
|
||||
|
||||
private DemandeAideDTO demandeAide;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
demandeAide = new DemandeAideDTO();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test création et getters/setters de base")
|
||||
void testCreationEtGettersSetters() {
|
||||
// Données de test
|
||||
String numeroReference = "DA-2025-001";
|
||||
UUID membreDemandeurId = UUID.randomUUID();
|
||||
String nomDemandeur = "Jean Dupont";
|
||||
UUID associationId = UUID.randomUUID();
|
||||
TypeAide typeAide = TypeAide.AIDE_FINANCIERE_URGENTE;
|
||||
String titre = "Aide pour frais médicaux";
|
||||
String description = "Demande d'aide pour couvrir les frais d'hospitalisation";
|
||||
BigDecimal montantDemande = new BigDecimal("500000.00");
|
||||
StatutAide statut = StatutAide.EN_ATTENTE;
|
||||
PrioriteAide priorite = PrioriteAide.ELEVEE;
|
||||
|
||||
// Test des setters
|
||||
demandeAide.setNumeroReference(numeroReference);
|
||||
demandeAide.setMembreDemandeurId(membreDemandeurId);
|
||||
demandeAide.setNomDemandeur(nomDemandeur);
|
||||
demandeAide.setAssociationId(associationId);
|
||||
demandeAide.setTypeAide(typeAide);
|
||||
demandeAide.setTitre(titre);
|
||||
demandeAide.setDescription(description);
|
||||
demandeAide.setMontantDemande(montantDemande);
|
||||
demandeAide.setStatut(statut);
|
||||
demandeAide.setPriorite(priorite);
|
||||
|
||||
// Test des getters
|
||||
assertThat(demandeAide.getNumeroReference()).isEqualTo(numeroReference);
|
||||
assertThat(demandeAide.getMembreDemandeurId()).isEqualTo(membreDemandeurId);
|
||||
assertThat(demandeAide.getNomDemandeur()).isEqualTo(nomDemandeur);
|
||||
assertThat(demandeAide.getAssociationId()).isEqualTo(associationId);
|
||||
assertThat(demandeAide.getTypeAide()).isEqualTo(typeAide);
|
||||
assertThat(demandeAide.getTitre()).isEqualTo(titre);
|
||||
assertThat(demandeAide.getDescription()).isEqualTo(description);
|
||||
assertThat(demandeAide.getMontantDemande()).isEqualTo(montantDemande);
|
||||
assertThat(demandeAide.getStatut()).isEqualTo(statut);
|
||||
assertThat(demandeAide.getPriorite()).isEqualTo(priorite);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthode marquerCommeModifie")
|
||||
void testMarquerCommeModifie() {
|
||||
String utilisateur = "admin@unionflow.dev";
|
||||
LocalDateTime avant = LocalDateTime.now();
|
||||
|
||||
demandeAide.marquerCommeModifie(utilisateur);
|
||||
|
||||
LocalDateTime apres = LocalDateTime.now();
|
||||
|
||||
assertThat(demandeAide.getDateModification()).isBetween(avant, apres);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constructeur et setters")
|
||||
void testConstructeurEtSetters() {
|
||||
DemandeAideDTO demande = new DemandeAideDTO();
|
||||
demande.setNumeroReference("DA-2025-002");
|
||||
demande.setTitre("Test Constructeur");
|
||||
demande.setTypeAide(TypeAide.DON_MATERIEL);
|
||||
demande.setStatut(StatutAide.BROUILLON);
|
||||
demande.setPriorite(PrioriteAide.NORMALE);
|
||||
|
||||
assertThat(demande.getNumeroReference()).isEqualTo("DA-2025-002");
|
||||
assertThat(demande.getTitre()).isEqualTo("Test Constructeur");
|
||||
assertThat(demande.getTypeAide()).isEqualTo(TypeAide.DON_MATERIEL);
|
||||
assertThat(demande.getStatut()).isEqualTo(StatutAide.BROUILLON);
|
||||
assertThat(demande.getPriorite()).isEqualTo(PrioriteAide.NORMALE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test champs spécifiques à DemandeAideDTO")
|
||||
void testChampsSpecifiques() {
|
||||
// Données de test
|
||||
String raisonRejet = "Dossier incomplet";
|
||||
LocalDateTime dateRejet = LocalDateTime.now().minusDays(2);
|
||||
UUID rejeteParId = UUID.randomUUID();
|
||||
String rejetePar = "Admin System";
|
||||
|
||||
// Test des setters
|
||||
demandeAide.setRaisonRejet(raisonRejet);
|
||||
demandeAide.setDateRejet(dateRejet);
|
||||
demandeAide.setRejeteParId(rejeteParId);
|
||||
demandeAide.setRejetePar(rejetePar);
|
||||
|
||||
// Test des getters
|
||||
assertThat(demandeAide.getRaisonRejet()).isEqualTo(raisonRejet);
|
||||
assertThat(demandeAide.getDateRejet()).isEqualTo(dateRejet);
|
||||
assertThat(demandeAide.getRejeteParId()).isEqualTo(rejeteParId);
|
||||
assertThat(demandeAide.getRejetePar()).isEqualTo(rejetePar);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test validation des énumérations")
|
||||
void testValidationEnumerations() {
|
||||
// Test que toutes les énumérations sont bien supportées
|
||||
for (TypeAide type : TypeAide.values()) {
|
||||
demandeAide.setTypeAide(type);
|
||||
assertThat(demandeAide.getTypeAide()).isEqualTo(type);
|
||||
}
|
||||
|
||||
for (StatutAide statut : StatutAide.values()) {
|
||||
demandeAide.setStatut(statut);
|
||||
assertThat(demandeAide.getStatut()).isEqualTo(statut);
|
||||
}
|
||||
|
||||
for (PrioriteAide priorite : PrioriteAide.values()) {
|
||||
demandeAide.setPriorite(priorite);
|
||||
assertThat(demandeAide.getPriorite()).isEqualTo(priorite);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,559 +0,0 @@
|
||||
package dev.lions.unionflow.server.api.dto.solidarite.aide;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires complets pour AideDTO.
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-10
|
||||
*/
|
||||
@DisplayName("Tests AideDTO")
|
||||
class AideDTOBasicTest {
|
||||
|
||||
private AideDTO aide;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
aide = new AideDTO();
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests de Construction")
|
||||
class ConstructionTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Constructeur par défaut - Initialisation correcte")
|
||||
void testConstructeurParDefaut() {
|
||||
AideDTO newAide = new AideDTO();
|
||||
|
||||
assertThat(newAide.getId()).isNotNull();
|
||||
assertThat(newAide.getDateCreation()).isNotNull();
|
||||
assertThat(newAide.isActif()).isTrue();
|
||||
assertThat(newAide.getVersion()).isEqualTo(0L);
|
||||
assertThat(newAide.getStatut()).isEqualTo("EN_ATTENTE");
|
||||
assertThat(newAide.getDevise()).isEqualTo("XOF");
|
||||
assertThat(newAide.getPriorite()).isEqualTo("NORMALE");
|
||||
assertThat(newAide.getNumeroReference()).isNotNull();
|
||||
assertThat(newAide.getNumeroReference()).matches("^AIDE-\\d{4}-[A-Z0-9]{6}$");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Constructeur avec paramètres - Initialisation correcte")
|
||||
void testConstructeurAvecParametres() {
|
||||
UUID membreDemandeurId = UUID.randomUUID();
|
||||
UUID associationId = UUID.randomUUID();
|
||||
String typeAide = "FINANCIERE";
|
||||
String titre = "Aide pour frais médicaux";
|
||||
|
||||
AideDTO newAide = new AideDTO(membreDemandeurId, associationId, typeAide, titre);
|
||||
|
||||
assertThat(newAide.getMembreDemandeurId()).isEqualTo(membreDemandeurId);
|
||||
assertThat(newAide.getAssociationId()).isEqualTo(associationId);
|
||||
assertThat(newAide.getTypeAide()).isEqualTo(typeAide);
|
||||
assertThat(newAide.getTitre()).isEqualTo(titre);
|
||||
assertThat(newAide.getStatut()).isEqualTo("EN_ATTENTE");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests Getters/Setters")
|
||||
class GettersSettersTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test tous les getters/setters - Partie 1")
|
||||
void testTousLesGettersSettersPart1() {
|
||||
// Données de test
|
||||
String numeroReference = "AIDE-2025-ABC123";
|
||||
UUID membreDemandeurId = UUID.randomUUID();
|
||||
String nomDemandeur = "Jean Dupont";
|
||||
String numeroMembreDemandeur = "UF-2025-12345678";
|
||||
UUID associationId = UUID.randomUUID();
|
||||
String nomAssociation = "Lions Club Dakar";
|
||||
String typeAide = "FINANCIERE";
|
||||
String titre = "Aide pour frais médicaux";
|
||||
String description = "Demande d'aide pour couvrir les frais d'hospitalisation";
|
||||
BigDecimal montantDemande = new BigDecimal("500000.00");
|
||||
String devise = "XOF";
|
||||
String statut = "EN_COURS_EVALUATION";
|
||||
String priorite = "HAUTE";
|
||||
|
||||
// Test des setters
|
||||
aide.setNumeroReference(numeroReference);
|
||||
aide.setMembreDemandeurId(membreDemandeurId);
|
||||
aide.setNomDemandeur(nomDemandeur);
|
||||
aide.setNumeroMembreDemandeur(numeroMembreDemandeur);
|
||||
aide.setAssociationId(associationId);
|
||||
aide.setNomAssociation(nomAssociation);
|
||||
aide.setTypeAide(typeAide);
|
||||
aide.setTitre(titre);
|
||||
aide.setDescription(description);
|
||||
aide.setMontantDemande(montantDemande);
|
||||
aide.setDevise(devise);
|
||||
aide.setStatut(statut);
|
||||
aide.setPriorite(priorite);
|
||||
|
||||
// Test des getters
|
||||
assertThat(aide.getNumeroReference()).isEqualTo(numeroReference);
|
||||
assertThat(aide.getMembreDemandeurId()).isEqualTo(membreDemandeurId);
|
||||
assertThat(aide.getNomDemandeur()).isEqualTo(nomDemandeur);
|
||||
assertThat(aide.getNumeroMembreDemandeur()).isEqualTo(numeroMembreDemandeur);
|
||||
assertThat(aide.getAssociationId()).isEqualTo(associationId);
|
||||
assertThat(aide.getNomAssociation()).isEqualTo(nomAssociation);
|
||||
assertThat(aide.getTypeAide()).isEqualTo(typeAide);
|
||||
assertThat(aide.getTitre()).isEqualTo(titre);
|
||||
assertThat(aide.getDescription()).isEqualTo(description);
|
||||
assertThat(aide.getMontantDemande()).isEqualTo(montantDemande);
|
||||
assertThat(aide.getDevise()).isEqualTo(devise);
|
||||
assertThat(aide.getStatut()).isEqualTo(statut);
|
||||
assertThat(aide.getPriorite()).isEqualTo(priorite);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test tous les getters/setters - Partie 2")
|
||||
void testTousLesGettersSettersPart2() {
|
||||
// Données de test
|
||||
LocalDate dateLimite = LocalDate.now().plusMonths(3);
|
||||
Boolean justificatifsFournis = true;
|
||||
String documentsJoints = "certificat_medical.pdf,facture_hopital.pdf";
|
||||
UUID membreEvaluateurId = UUID.randomUUID();
|
||||
String nomEvaluateur = "Marie Martin";
|
||||
LocalDateTime dateEvaluation = LocalDateTime.now();
|
||||
String commentairesEvaluateur = "Dossier complet, situation vérifiée";
|
||||
BigDecimal montantApprouve = new BigDecimal("400000.00");
|
||||
LocalDateTime dateApprobation = LocalDateTime.now();
|
||||
UUID membreAidantId = UUID.randomUUID();
|
||||
String nomAidant = "Paul Durand";
|
||||
LocalDate dateDebutAide = LocalDate.now();
|
||||
LocalDate dateFinAide = LocalDate.now().plusMonths(6);
|
||||
BigDecimal montantVerse = new BigDecimal("400000.00");
|
||||
String modeVersement = "WAVE_MONEY";
|
||||
String numeroTransaction = "TXN123456789";
|
||||
LocalDateTime dateVersement = LocalDateTime.now();
|
||||
|
||||
// Test des setters
|
||||
aide.setDateLimite(dateLimite);
|
||||
aide.setJustificatifsFournis(justificatifsFournis);
|
||||
aide.setDocumentsJoints(documentsJoints);
|
||||
aide.setMembreEvaluateurId(membreEvaluateurId);
|
||||
aide.setNomEvaluateur(nomEvaluateur);
|
||||
aide.setDateEvaluation(dateEvaluation);
|
||||
aide.setCommentairesEvaluateur(commentairesEvaluateur);
|
||||
aide.setMontantApprouve(montantApprouve);
|
||||
aide.setDateApprobation(dateApprobation);
|
||||
aide.setMembreAidantId(membreAidantId);
|
||||
aide.setNomAidant(nomAidant);
|
||||
aide.setDateDebutAide(dateDebutAide);
|
||||
aide.setDateFinAide(dateFinAide);
|
||||
aide.setMontantVerse(montantVerse);
|
||||
aide.setModeVersement(modeVersement);
|
||||
aide.setNumeroTransaction(numeroTransaction);
|
||||
aide.setDateVersement(dateVersement);
|
||||
|
||||
// Test des getters
|
||||
assertThat(aide.getDateLimite()).isEqualTo(dateLimite);
|
||||
assertThat(aide.getJustificatifsFournis()).isEqualTo(justificatifsFournis);
|
||||
assertThat(aide.getDocumentsJoints()).isEqualTo(documentsJoints);
|
||||
assertThat(aide.getMembreEvaluateurId()).isEqualTo(membreEvaluateurId);
|
||||
assertThat(aide.getNomEvaluateur()).isEqualTo(nomEvaluateur);
|
||||
assertThat(aide.getDateEvaluation()).isEqualTo(dateEvaluation);
|
||||
assertThat(aide.getCommentairesEvaluateur()).isEqualTo(commentairesEvaluateur);
|
||||
assertThat(aide.getMontantApprouve()).isEqualTo(montantApprouve);
|
||||
assertThat(aide.getDateApprobation()).isEqualTo(dateApprobation);
|
||||
assertThat(aide.getMembreAidantId()).isEqualTo(membreAidantId);
|
||||
assertThat(aide.getNomAidant()).isEqualTo(nomAidant);
|
||||
assertThat(aide.getDateDebutAide()).isEqualTo(dateDebutAide);
|
||||
assertThat(aide.getDateFinAide()).isEqualTo(dateFinAide);
|
||||
assertThat(aide.getMontantVerse()).isEqualTo(montantVerse);
|
||||
assertThat(aide.getModeVersement()).isEqualTo(modeVersement);
|
||||
assertThat(aide.getNumeroTransaction()).isEqualTo(numeroTransaction);
|
||||
assertThat(aide.getDateVersement()).isEqualTo(dateVersement);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test tous les getters/setters - Partie 3")
|
||||
void testTousLesGettersSettersPart3() {
|
||||
// Données de test
|
||||
String commentairesBeneficiaire = "Merci beaucoup pour cette aide";
|
||||
Integer noteSatisfaction = 5;
|
||||
Boolean aidePublique = false;
|
||||
Boolean aideAnonyme = true;
|
||||
Integer nombreVues = 25;
|
||||
String raisonRejet = "Dossier incomplet";
|
||||
LocalDateTime dateRejet = LocalDateTime.now();
|
||||
UUID rejeteParId = UUID.randomUUID();
|
||||
String rejetePar = "Admin System";
|
||||
|
||||
// Test des setters
|
||||
aide.setCommentairesBeneficiaire(commentairesBeneficiaire);
|
||||
aide.setNoteSatisfaction(noteSatisfaction);
|
||||
aide.setAidePublique(aidePublique);
|
||||
aide.setAideAnonyme(aideAnonyme);
|
||||
aide.setNombreVues(nombreVues);
|
||||
aide.setRaisonRejet(raisonRejet);
|
||||
aide.setDateRejet(dateRejet);
|
||||
aide.setRejeteParId(rejeteParId);
|
||||
aide.setRejetePar(rejetePar);
|
||||
|
||||
// Test des getters
|
||||
assertThat(aide.getCommentairesBeneficiaire()).isEqualTo(commentairesBeneficiaire);
|
||||
assertThat(aide.getNoteSatisfaction()).isEqualTo(noteSatisfaction);
|
||||
assertThat(aide.getAidePublique()).isEqualTo(aidePublique);
|
||||
assertThat(aide.getAideAnonyme()).isEqualTo(aideAnonyme);
|
||||
assertThat(aide.getNombreVues()).isEqualTo(nombreVues);
|
||||
assertThat(aide.getRaisonRejet()).isEqualTo(raisonRejet);
|
||||
assertThat(aide.getDateRejet()).isEqualTo(dateRejet);
|
||||
assertThat(aide.getRejeteParId()).isEqualTo(rejeteParId);
|
||||
assertThat(aide.getRejetePar()).isEqualTo(rejetePar);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests Méthodes Métier")
|
||||
class MethodesMetierTests {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes de statut")
|
||||
void testMethodesStatut() {
|
||||
// Test isEnAttente
|
||||
aide.setStatut("EN_ATTENTE");
|
||||
assertThat(aide.isEnAttente()).isTrue();
|
||||
|
||||
aide.setStatut("APPROUVEE");
|
||||
assertThat(aide.isEnAttente()).isFalse();
|
||||
|
||||
// Test isApprouvee
|
||||
aide.setStatut("APPROUVEE");
|
||||
assertThat(aide.isApprouvee()).isTrue();
|
||||
|
||||
aide.setStatut("REJETEE");
|
||||
assertThat(aide.isApprouvee()).isFalse();
|
||||
|
||||
// Test isRejetee
|
||||
aide.setStatut("REJETEE");
|
||||
assertThat(aide.isRejetee()).isTrue();
|
||||
|
||||
aide.setStatut("EN_ATTENTE");
|
||||
assertThat(aide.isRejetee()).isFalse();
|
||||
|
||||
// Test isTerminee
|
||||
aide.setStatut("TERMINEE");
|
||||
assertThat(aide.isTerminee()).isTrue();
|
||||
|
||||
aide.setStatut("EN_COURS_AIDE");
|
||||
assertThat(aide.isTerminee()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes de libellé")
|
||||
void testMethodesLibelle() {
|
||||
// Test getTypeAideLibelle
|
||||
aide.setTypeAide("FINANCIERE");
|
||||
assertThat(aide.getTypeAideLibelle()).isEqualTo("Aide Financière");
|
||||
|
||||
aide.setTypeAide("MEDICALE");
|
||||
assertThat(aide.getTypeAideLibelle()).isEqualTo("Aide Médicale");
|
||||
|
||||
aide.setTypeAide(null);
|
||||
assertThat(aide.getTypeAideLibelle()).isEqualTo("Non défini");
|
||||
|
||||
// Test getStatutLibelle
|
||||
aide.setStatut("EN_ATTENTE");
|
||||
assertThat(aide.getStatutLibelle()).isEqualTo("En Attente");
|
||||
|
||||
aide.setStatut("APPROUVEE");
|
||||
assertThat(aide.getStatutLibelle()).isEqualTo("Approuvée");
|
||||
|
||||
aide.setStatut(null);
|
||||
assertThat(aide.getStatutLibelle()).isEqualTo("Non défini");
|
||||
|
||||
// Test getPrioriteLibelle
|
||||
aide.setPriorite("URGENTE");
|
||||
assertThat(aide.getPrioriteLibelle()).isEqualTo("Urgente");
|
||||
|
||||
aide.setPriorite("HAUTE");
|
||||
assertThat(aide.getPrioriteLibelle()).isEqualTo("Haute");
|
||||
|
||||
aide.setPriorite(null);
|
||||
assertThat(aide.getPrioriteLibelle()).isEqualTo("Normale");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes de calcul")
|
||||
void testMethodesCalcul() {
|
||||
// Test getPourcentageApprobation
|
||||
aide.setMontantDemande(new BigDecimal("1000.00"));
|
||||
aide.setMontantApprouve(new BigDecimal("800.00"));
|
||||
assertThat(aide.getPourcentageApprobation()).isEqualTo(80);
|
||||
|
||||
// Test avec montant demandé null
|
||||
aide.setMontantDemande(null);
|
||||
assertThat(aide.getPourcentageApprobation()).isEqualTo(0);
|
||||
|
||||
// Test getEcartMontant
|
||||
aide.setMontantDemande(new BigDecimal("1000.00"));
|
||||
aide.setMontantApprouve(new BigDecimal("800.00"));
|
||||
assertThat(aide.getEcartMontant()).isEqualTo(new BigDecimal("200.00"));
|
||||
|
||||
// Test avec montants null
|
||||
aide.setMontantDemande(null);
|
||||
aide.setMontantApprouve(null);
|
||||
assertThat(aide.getEcartMontant()).isEqualTo(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes métier")
|
||||
void testMethodesMetier() {
|
||||
// Test approuver
|
||||
UUID evaluateurId = UUID.randomUUID();
|
||||
String nomEvaluateur = "Marie Martin";
|
||||
BigDecimal montantApprouve = new BigDecimal("800.00");
|
||||
String commentaires = "Dossier approuvé";
|
||||
|
||||
aide.approuver(evaluateurId, nomEvaluateur, montantApprouve, commentaires);
|
||||
|
||||
assertThat(aide.getStatut()).isEqualTo("APPROUVEE");
|
||||
assertThat(aide.getMembreEvaluateurId()).isEqualTo(evaluateurId);
|
||||
assertThat(aide.getNomEvaluateur()).isEqualTo(nomEvaluateur);
|
||||
assertThat(aide.getMontantApprouve()).isEqualTo(montantApprouve);
|
||||
assertThat(aide.getCommentairesEvaluateur()).isEqualTo(commentaires);
|
||||
assertThat(aide.getDateEvaluation()).isNotNull();
|
||||
assertThat(aide.getDateApprobation()).isNotNull();
|
||||
|
||||
// Test rejeter
|
||||
aide.setStatut("EN_ATTENTE"); // Reset
|
||||
UUID rejeteurId = UUID.randomUUID();
|
||||
String nomRejeteur = "Paul Durand";
|
||||
String raisonRejet = "Dossier incomplet";
|
||||
|
||||
aide.rejeter(rejeteurId, nomRejeteur, raisonRejet);
|
||||
|
||||
assertThat(aide.getStatut()).isEqualTo("REJETEE");
|
||||
assertThat(aide.getRejeteParId()).isEqualTo(rejeteurId);
|
||||
assertThat(aide.getRejetePar()).isEqualTo(nomRejeteur);
|
||||
assertThat(aide.getRaisonRejet()).isEqualTo(raisonRejet);
|
||||
assertThat(aide.getDateRejet()).isNotNull();
|
||||
|
||||
// Test demarrerAide
|
||||
aide.setStatut("APPROUVEE"); // Reset
|
||||
UUID aidantId = UUID.randomUUID();
|
||||
String nomAidant = "Jean Dupont";
|
||||
|
||||
aide.demarrerAide(aidantId, nomAidant);
|
||||
|
||||
assertThat(aide.getStatut()).isEqualTo("EN_COURS_AIDE");
|
||||
assertThat(aide.getMembreAidantId()).isEqualTo(aidantId);
|
||||
assertThat(aide.getNomAidant()).isEqualTo(nomAidant);
|
||||
assertThat(aide.getDateDebutAide()).isNotNull();
|
||||
|
||||
// Test terminerAvecVersement
|
||||
BigDecimal montantVerse = new BigDecimal("800.00");
|
||||
String modeVersement = "WAVE_MONEY";
|
||||
String numeroTransaction = "TXN123456789";
|
||||
|
||||
aide.terminerAvecVersement(montantVerse, modeVersement, numeroTransaction);
|
||||
|
||||
assertThat(aide.getStatut()).isEqualTo("TERMINEE");
|
||||
assertThat(aide.getMontantVerse()).isEqualTo(montantVerse);
|
||||
assertThat(aide.getModeVersement()).isEqualTo(modeVersement);
|
||||
assertThat(aide.getNumeroTransaction()).isEqualTo(numeroTransaction);
|
||||
assertThat(aide.getDateVersement()).isNotNull();
|
||||
assertThat(aide.getDateFinAide()).isNotNull();
|
||||
|
||||
// Test incrementerVues
|
||||
aide.setNombreVues(null);
|
||||
aide.incrementerVues();
|
||||
assertThat(aide.getNombreVues()).isEqualTo(1);
|
||||
|
||||
aide.incrementerVues();
|
||||
assertThat(aide.getNombreVues()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test méthodes métier complémentaires")
|
||||
void testMethodesMetierComplementaires() {
|
||||
// Test tous les statuts
|
||||
aide.setStatut("EN_COURS_EVALUATION");
|
||||
assertThat(aide.isEnCoursEvaluation()).isTrue();
|
||||
assertThat(aide.isEnAttente()).isFalse();
|
||||
|
||||
aide.setStatut("EN_COURS_AIDE");
|
||||
assertThat(aide.isEnCoursAide()).isTrue();
|
||||
assertThat(aide.isTerminee()).isFalse();
|
||||
|
||||
aide.setStatut("ANNULEE");
|
||||
assertThat(aide.isAnnulee()).isTrue();
|
||||
|
||||
// Test priorité urgente
|
||||
aide.setPriorite("URGENTE");
|
||||
assertThat(aide.isUrgente()).isTrue();
|
||||
|
||||
aide.setPriorite("NORMALE");
|
||||
assertThat(aide.isUrgente()).isFalse();
|
||||
|
||||
// Test date limite
|
||||
aide.setDateLimite(LocalDate.now().plusDays(5));
|
||||
assertThat(aide.isDateLimiteDepassee()).isFalse();
|
||||
assertThat(aide.getJoursRestants()).isEqualTo(5);
|
||||
|
||||
aide.setDateLimite(LocalDate.now().minusDays(3));
|
||||
assertThat(aide.isDateLimiteDepassee()).isTrue();
|
||||
assertThat(aide.getJoursRestants()).isEqualTo(0);
|
||||
|
||||
// Test avec date limite null
|
||||
aide.setDateLimite(null);
|
||||
assertThat(aide.isDateLimiteDepassee()).isFalse();
|
||||
assertThat(aide.getJoursRestants()).isEqualTo(0);
|
||||
|
||||
// Test aide financière
|
||||
aide.setTypeAide("FINANCIERE");
|
||||
aide.setMontantDemande(new BigDecimal("50000.00"));
|
||||
assertThat(aide.isAideFinanciere()).isTrue();
|
||||
|
||||
aide.setMontantDemande(null);
|
||||
assertThat(aide.isAideFinanciere()).isFalse();
|
||||
|
||||
aide.setTypeAide("MATERIELLE");
|
||||
aide.setMontantDemande(new BigDecimal("50000.00"));
|
||||
assertThat(aide.isAideFinanciere()).isFalse();
|
||||
|
||||
// Test getEcartMontant avec différents cas
|
||||
aide.setMontantDemande(new BigDecimal("100000.00"));
|
||||
aide.setMontantApprouve(new BigDecimal("80000.00"));
|
||||
assertThat(aide.getEcartMontant()).isEqualByComparingTo(new BigDecimal("20000.00"));
|
||||
|
||||
// Test avec montantDemande null
|
||||
aide.setMontantDemande(null);
|
||||
aide.setMontantApprouve(new BigDecimal("80000.00"));
|
||||
assertThat(aide.getEcartMontant()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
|
||||
// Test avec montantApprouve null
|
||||
aide.setMontantDemande(new BigDecimal("100000.00"));
|
||||
aide.setMontantApprouve(null);
|
||||
assertThat(aide.getEcartMontant()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
|
||||
// Test avec les deux null
|
||||
aide.setMontantDemande(null);
|
||||
aide.setMontantApprouve(null);
|
||||
assertThat(aide.getEcartMontant()).isEqualByComparingTo(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test libellés complets")
|
||||
void testLibellesComplets() {
|
||||
// Test tous les types d'aide
|
||||
aide.setTypeAide("MATERIELLE");
|
||||
assertThat(aide.getTypeAideLibelle()).isEqualTo("Aide Matérielle");
|
||||
|
||||
aide.setTypeAide("LOGEMENT");
|
||||
assertThat(aide.getTypeAideLibelle()).isEqualTo("Aide au Logement");
|
||||
|
||||
aide.setTypeAide("MEDICALE");
|
||||
assertThat(aide.getTypeAideLibelle()).isEqualTo("Aide Médicale");
|
||||
|
||||
aide.setTypeAide("JURIDIQUE");
|
||||
assertThat(aide.getTypeAideLibelle()).isEqualTo("Aide Juridique");
|
||||
|
||||
aide.setTypeAide("EDUCATION");
|
||||
assertThat(aide.getTypeAideLibelle()).isEqualTo("Aide à l'Éducation");
|
||||
|
||||
aide.setTypeAide("SANTE");
|
||||
assertThat(aide.getTypeAideLibelle()).isEqualTo("SANTE"); // Valeur par défaut car non définie dans le switch
|
||||
|
||||
aide.setTypeAide("AUTRE");
|
||||
assertThat(aide.getTypeAideLibelle()).isEqualTo("Autre");
|
||||
|
||||
aide.setTypeAide("TYPE_INCONNU");
|
||||
assertThat(aide.getTypeAideLibelle()).isEqualTo("TYPE_INCONNU");
|
||||
|
||||
// Test tous les statuts
|
||||
aide.setStatut("EN_COURS_EVALUATION");
|
||||
assertThat(aide.getStatutLibelle()).isEqualTo("En Cours d'Évaluation");
|
||||
|
||||
aide.setStatut("REJETEE");
|
||||
assertThat(aide.getStatutLibelle()).isEqualTo("Rejetée");
|
||||
|
||||
aide.setStatut("EN_COURS_AIDE");
|
||||
assertThat(aide.getStatutLibelle()).isEqualTo("En Cours d'Aide");
|
||||
|
||||
aide.setStatut("TERMINEE");
|
||||
assertThat(aide.getStatutLibelle()).isEqualTo("Terminée");
|
||||
|
||||
aide.setStatut("ANNULEE");
|
||||
assertThat(aide.getStatutLibelle()).isEqualTo("Annulée");
|
||||
|
||||
aide.setStatut("STATUT_INCONNU");
|
||||
assertThat(aide.getStatutLibelle()).isEqualTo("STATUT_INCONNU");
|
||||
|
||||
// Test toutes les priorités
|
||||
aide.setPriorite("BASSE");
|
||||
assertThat(aide.getPrioriteLibelle()).isEqualTo("Basse");
|
||||
|
||||
aide.setPriorite("NORMALE");
|
||||
assertThat(aide.getPrioriteLibelle()).isEqualTo("Normale");
|
||||
|
||||
aide.setPriorite("HAUTE");
|
||||
assertThat(aide.getPrioriteLibelle()).isEqualTo("Haute");
|
||||
|
||||
aide.setPriorite("PRIORITE_INCONNUE");
|
||||
assertThat(aide.getPrioriteLibelle()).isEqualTo("PRIORITE_INCONNUE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constructeur avec paramètres")
|
||||
void testConstructeurAvecParametres() {
|
||||
UUID membreDemandeurId = UUID.randomUUID();
|
||||
UUID associationId = UUID.randomUUID();
|
||||
String typeAide = "FINANCIERE";
|
||||
String titre = "Aide médicale urgente";
|
||||
|
||||
AideDTO nouvelleAide = new AideDTO(membreDemandeurId, associationId, typeAide, titre);
|
||||
|
||||
assertThat(nouvelleAide.getMembreDemandeurId()).isEqualTo(membreDemandeurId);
|
||||
assertThat(nouvelleAide.getAssociationId()).isEqualTo(associationId);
|
||||
assertThat(nouvelleAide.getTypeAide()).isEqualTo(typeAide);
|
||||
assertThat(nouvelleAide.getTitre()).isEqualTo(titre);
|
||||
assertThat(nouvelleAide.getNumeroReference()).isNotNull();
|
||||
assertThat(nouvelleAide.getNumeroReference()).startsWith("AIDE-");
|
||||
// Vérifier les valeurs par défaut
|
||||
assertThat(nouvelleAide.getStatut()).isEqualTo("EN_ATTENTE");
|
||||
assertThat(nouvelleAide.getPriorite()).isEqualTo("NORMALE");
|
||||
assertThat(nouvelleAide.getDevise()).isEqualTo("XOF");
|
||||
assertThat(nouvelleAide.getJustificatifsFournis()).isFalse();
|
||||
assertThat(nouvelleAide.getAidePublique()).isTrue();
|
||||
assertThat(nouvelleAide.getAideAnonyme()).isFalse();
|
||||
assertThat(nouvelleAide.getNombreVues()).isEqualTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test toString complet")
|
||||
void testToStringComplet() {
|
||||
aide.setNumeroReference("AIDE-2025-ABC123");
|
||||
aide.setTitre("Aide médicale");
|
||||
aide.setStatut("EN_ATTENTE");
|
||||
aide.setTypeAide("FINANCIERE");
|
||||
aide.setMontantDemande(new BigDecimal("100000.00"));
|
||||
aide.setPriorite("URGENTE");
|
||||
|
||||
String result = aide.toString();
|
||||
assertThat(result).isNotNull();
|
||||
assertThat(result).contains("AideDTO");
|
||||
assertThat(result).contains("numeroReference='AIDE-2025-ABC123'");
|
||||
assertThat(result).contains("typeAide='FINANCIERE'");
|
||||
assertThat(result).contains("titre='Aide médicale'");
|
||||
assertThat(result).contains("statut='EN_ATTENTE'");
|
||||
assertThat(result).contains("montantDemande=100000.00");
|
||||
assertThat(result).contains("priorite='URGENTE'");
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
import dev.lions.unionflow.server.api.enums.abonnement.StatutAbonnement;
|
||||
import dev.lions.unionflow.server.api.enums.abonnement.StatutFormule;
|
||||
import dev.lions.unionflow.server.api.enums.abonnement.TypeFormule;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.PrioriteEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.StatutEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.evenement.TypeEvenementMetier;
|
||||
import dev.lions.unionflow.server.api.enums.finance.StatutCotisation;
|
||||
import dev.lions.unionflow.server.api.enums.membre.StatutMembre;
|
||||
@@ -13,6 +15,7 @@ import dev.lions.unionflow.server.api.enums.organisation.TypeOrganisation;
|
||||
import dev.lions.unionflow.server.api.enums.paiement.StatutSession;
|
||||
import dev.lions.unionflow.server.api.enums.paiement.StatutTraitement;
|
||||
import dev.lions.unionflow.server.api.enums.paiement.TypeEvenement;
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.PrioriteAide;
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
|
||||
import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
@@ -170,6 +173,28 @@ class EnumsRefactoringTest {
|
||||
assertThat(TypeEvenementMetier.CEREMONIE.getLibelle()).isEqualTo("Cérémonie");
|
||||
assertThat(TypeEvenementMetier.AUTRE.getLibelle()).isEqualTo("Autre");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("StatutEvenement - Tous les statuts disponibles")
|
||||
void testStatutEvenementTousLesStatuts() {
|
||||
// Given & When & Then
|
||||
assertThat(StatutEvenement.PLANIFIE.getLibelle()).isEqualTo("Planifié");
|
||||
assertThat(StatutEvenement.CONFIRME.getLibelle()).isEqualTo("Confirmé");
|
||||
assertThat(StatutEvenement.EN_COURS.getLibelle()).isEqualTo("En cours");
|
||||
assertThat(StatutEvenement.TERMINE.getLibelle()).isEqualTo("Terminé");
|
||||
assertThat(StatutEvenement.ANNULE.getLibelle()).isEqualTo("Annulé");
|
||||
assertThat(StatutEvenement.REPORTE.getLibelle()).isEqualTo("Reporté");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("PrioriteEvenement - Toutes les priorités disponibles")
|
||||
void testPrioriteEvenementToutesLesPriorites() {
|
||||
// Given & When & Then
|
||||
assertThat(PrioriteEvenement.CRITIQUE.getLibelle()).isEqualTo("Critique");
|
||||
assertThat(PrioriteEvenement.HAUTE.getLibelle()).isEqualTo("Haute");
|
||||
assertThat(PrioriteEvenement.NORMALE.getLibelle()).isEqualTo("Normale");
|
||||
assertThat(PrioriteEvenement.BASSE.getLibelle()).isEqualTo("Basse");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@@ -198,7 +223,8 @@ class EnumsRefactoringTest {
|
||||
@DisplayName("TypeAide - Tous les types disponibles")
|
||||
void testTypeAideTousLesTypes() {
|
||||
// Given & When & Then
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.getLibelle()).isEqualTo("Aide financière urgente");
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.getLibelle())
|
||||
.isEqualTo("Aide financière urgente");
|
||||
assertThat(TypeAide.AIDE_FRAIS_MEDICAUX.getLibelle()).isEqualTo("Aide frais médicaux");
|
||||
assertThat(TypeAide.AIDE_FRAIS_SCOLARITE.getLibelle()).isEqualTo("Aide frais de scolarité");
|
||||
assertThat(TypeAide.HEBERGEMENT_URGENCE.getLibelle()).isEqualTo("Hébergement d'urgence");
|
||||
@@ -222,6 +248,17 @@ class EnumsRefactoringTest {
|
||||
assertThat(StatutAide.ANNULEE.getLibelle()).isEqualTo("Annulée");
|
||||
assertThat(StatutAide.SUSPENDUE.getLibelle()).isEqualTo("Suspendue");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("PrioriteAide - Toutes les priorités disponibles")
|
||||
void testPrioriteAideToutesLesPriorites() {
|
||||
// Given & When & Then
|
||||
assertThat(PrioriteAide.CRITIQUE.getLibelle()).isEqualTo("Critique");
|
||||
assertThat(PrioriteAide.URGENTE.getLibelle()).isEqualTo("Urgente");
|
||||
assertThat(PrioriteAide.ELEVEE.getLibelle()).isEqualTo("Élevée");
|
||||
assertThat(PrioriteAide.NORMALE.getLibelle()).isEqualTo("Normale");
|
||||
assertThat(PrioriteAide.FAIBLE.getLibelle()).isEqualTo("Faible");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
package dev.lions.unionflow.server.api.enums.evenement;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires EXHAUSTIFS pour PrioriteEvenement - Couverture 100%
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@DisplayName("Tests EXHAUSTIFS PrioriteEvenement")
|
||||
class PrioriteEvenementTest {
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des valeurs enum et constructeur")
|
||||
class TestsValeursEnum {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test valueOf et values")
|
||||
void testValueOfEtValues() {
|
||||
PrioriteEvenement[] values = PrioriteEvenement.values();
|
||||
assertThat(values).hasSize(4);
|
||||
assertThat(values).containsExactly(
|
||||
PrioriteEvenement.CRITIQUE,
|
||||
PrioriteEvenement.HAUTE,
|
||||
PrioriteEvenement.NORMALE,
|
||||
PrioriteEvenement.BASSE);
|
||||
|
||||
// Test valueOf pour toutes les valeurs
|
||||
assertThat(PrioriteEvenement.valueOf("CRITIQUE")).isEqualTo(PrioriteEvenement.CRITIQUE);
|
||||
assertThat(PrioriteEvenement.valueOf("HAUTE")).isEqualTo(PrioriteEvenement.HAUTE);
|
||||
assertThat(PrioriteEvenement.valueOf("NORMALE")).isEqualTo(PrioriteEvenement.NORMALE);
|
||||
assertThat(PrioriteEvenement.valueOf("BASSE")).isEqualTo(PrioriteEvenement.BASSE);
|
||||
|
||||
assertThatThrownBy(() -> PrioriteEvenement.valueOf("INEXISTANT"))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test ordinal, name et toString")
|
||||
void testOrdinalNameToString() {
|
||||
assertThat(PrioriteEvenement.CRITIQUE.ordinal()).isEqualTo(0);
|
||||
assertThat(PrioriteEvenement.HAUTE.ordinal()).isEqualTo(1);
|
||||
assertThat(PrioriteEvenement.NORMALE.ordinal()).isEqualTo(2);
|
||||
assertThat(PrioriteEvenement.BASSE.ordinal()).isEqualTo(3);
|
||||
|
||||
assertThat(PrioriteEvenement.CRITIQUE.name()).isEqualTo("CRITIQUE");
|
||||
assertThat(PrioriteEvenement.HAUTE.name()).isEqualTo("HAUTE");
|
||||
assertThat(PrioriteEvenement.NORMALE.name()).isEqualTo("NORMALE");
|
||||
assertThat(PrioriteEvenement.BASSE.name()).isEqualTo("BASSE");
|
||||
|
||||
assertThat(PrioriteEvenement.CRITIQUE.toString()).isEqualTo("CRITIQUE");
|
||||
assertThat(PrioriteEvenement.HAUTE.toString()).isEqualTo("HAUTE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés CRITIQUE")
|
||||
void testProprieteCritique() {
|
||||
PrioriteEvenement priorite = PrioriteEvenement.CRITIQUE;
|
||||
assertThat(priorite.getLibelle()).isEqualTo("Critique");
|
||||
assertThat(priorite.getCode()).isEqualTo("critical");
|
||||
assertThat(priorite.getNiveau()).isEqualTo(1);
|
||||
assertThat(priorite.getDescription()).isEqualTo("Événement critique nécessitant une attention immédiate");
|
||||
assertThat(priorite.getCouleur()).isEqualTo("#F44336");
|
||||
assertThat(priorite.getIcone()).isEqualTo("priority_high");
|
||||
assertThat(priorite.isNotificationImmediate()).isTrue();
|
||||
assertThat(priorite.isEscaladeAutomatique()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés HAUTE")
|
||||
void testProprieteHaute() {
|
||||
PrioriteEvenement priorite = PrioriteEvenement.HAUTE;
|
||||
assertThat(priorite.getLibelle()).isEqualTo("Haute");
|
||||
assertThat(priorite.getCode()).isEqualTo("high");
|
||||
assertThat(priorite.getNiveau()).isEqualTo(2);
|
||||
assertThat(priorite.getDescription()).isEqualTo("Événement de haute priorité");
|
||||
assertThat(priorite.getCouleur()).isEqualTo("#FF9800");
|
||||
assertThat(priorite.getIcone()).isEqualTo("keyboard_arrow_up");
|
||||
assertThat(priorite.isNotificationImmediate()).isTrue();
|
||||
assertThat(priorite.isEscaladeAutomatique()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés NORMALE")
|
||||
void testProprieteNormale() {
|
||||
PrioriteEvenement priorite = PrioriteEvenement.NORMALE;
|
||||
assertThat(priorite.getLibelle()).isEqualTo("Normale");
|
||||
assertThat(priorite.getCode()).isEqualTo("normal");
|
||||
assertThat(priorite.getNiveau()).isEqualTo(3);
|
||||
assertThat(priorite.getDescription()).isEqualTo("Événement de priorité normale");
|
||||
assertThat(priorite.getCouleur()).isEqualTo("#2196F3");
|
||||
assertThat(priorite.getIcone()).isEqualTo("remove");
|
||||
assertThat(priorite.isNotificationImmediate()).isFalse();
|
||||
assertThat(priorite.isEscaladeAutomatique()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés BASSE")
|
||||
void testProprieteBasse() {
|
||||
PrioriteEvenement priorite = PrioriteEvenement.BASSE;
|
||||
assertThat(priorite.getLibelle()).isEqualTo("Basse");
|
||||
assertThat(priorite.getCode()).isEqualTo("low");
|
||||
assertThat(priorite.getNiveau()).isEqualTo(4);
|
||||
assertThat(priorite.getDescription()).isEqualTo("Événement de priorité basse");
|
||||
assertThat(priorite.getCouleur()).isEqualTo("#4CAF50");
|
||||
assertThat(priorite.getIcone()).isEqualTo("keyboard_arrow_down");
|
||||
assertThat(priorite.isNotificationImmediate()).isFalse();
|
||||
assertThat(priorite.isEscaladeAutomatique()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes métier")
|
||||
class TestsMethodesMetier {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isElevee - toutes les branches")
|
||||
void testIsElevee() {
|
||||
// Priorités élevées (this == CRITIQUE || this == HAUTE)
|
||||
assertThat(PrioriteEvenement.CRITIQUE.isElevee()).isTrue();
|
||||
assertThat(PrioriteEvenement.HAUTE.isElevee()).isTrue();
|
||||
|
||||
// Priorités non élevées
|
||||
assertThat(PrioriteEvenement.NORMALE.isElevee()).isFalse();
|
||||
assertThat(PrioriteEvenement.BASSE.isElevee()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isUrgente - toutes les branches")
|
||||
void testIsUrgente() {
|
||||
// Priorités urgentes (this == CRITIQUE || this == HAUTE)
|
||||
assertThat(PrioriteEvenement.CRITIQUE.isUrgente()).isTrue();
|
||||
assertThat(PrioriteEvenement.HAUTE.isUrgente()).isTrue();
|
||||
|
||||
// Priorités non urgentes
|
||||
assertThat(PrioriteEvenement.NORMALE.isUrgente()).isFalse();
|
||||
assertThat(PrioriteEvenement.BASSE.isUrgente()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isSuperieurA - toutes les comparaisons")
|
||||
void testIsSuperieurA() {
|
||||
// CRITIQUE (niveau 1) est supérieur à tous les autres
|
||||
assertThat(PrioriteEvenement.CRITIQUE.isSuperieurA(PrioriteEvenement.HAUTE)).isTrue();
|
||||
assertThat(PrioriteEvenement.CRITIQUE.isSuperieurA(PrioriteEvenement.NORMALE)).isTrue();
|
||||
assertThat(PrioriteEvenement.CRITIQUE.isSuperieurA(PrioriteEvenement.BASSE)).isTrue();
|
||||
assertThat(PrioriteEvenement.CRITIQUE.isSuperieurA(PrioriteEvenement.CRITIQUE)).isFalse();
|
||||
|
||||
// HAUTE (niveau 2) est supérieur à NORMALE et BASSE
|
||||
assertThat(PrioriteEvenement.HAUTE.isSuperieurA(PrioriteEvenement.CRITIQUE)).isFalse();
|
||||
assertThat(PrioriteEvenement.HAUTE.isSuperieurA(PrioriteEvenement.NORMALE)).isTrue();
|
||||
assertThat(PrioriteEvenement.HAUTE.isSuperieurA(PrioriteEvenement.BASSE)).isTrue();
|
||||
assertThat(PrioriteEvenement.HAUTE.isSuperieurA(PrioriteEvenement.HAUTE)).isFalse();
|
||||
|
||||
// NORMALE (niveau 3) est supérieur à BASSE seulement
|
||||
assertThat(PrioriteEvenement.NORMALE.isSuperieurA(PrioriteEvenement.CRITIQUE)).isFalse();
|
||||
assertThat(PrioriteEvenement.NORMALE.isSuperieurA(PrioriteEvenement.HAUTE)).isFalse();
|
||||
assertThat(PrioriteEvenement.NORMALE.isSuperieurA(PrioriteEvenement.BASSE)).isTrue();
|
||||
assertThat(PrioriteEvenement.NORMALE.isSuperieurA(PrioriteEvenement.NORMALE)).isFalse();
|
||||
|
||||
// BASSE (niveau 4) n'est supérieur à aucun
|
||||
assertThat(PrioriteEvenement.BASSE.isSuperieurA(PrioriteEvenement.CRITIQUE)).isFalse();
|
||||
assertThat(PrioriteEvenement.BASSE.isSuperieurA(PrioriteEvenement.HAUTE)).isFalse();
|
||||
assertThat(PrioriteEvenement.BASSE.isSuperieurA(PrioriteEvenement.NORMALE)).isFalse();
|
||||
assertThat(PrioriteEvenement.BASSE.isSuperieurA(PrioriteEvenement.BASSE)).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes statiques")
|
||||
class TestsMethodesStatiques {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getPrioritesElevees")
|
||||
void testGetPrioritesElevees() {
|
||||
List<PrioriteEvenement> elevees = PrioriteEvenement.getPrioritesElevees();
|
||||
|
||||
// Vérifier que toutes les priorités élevées sont incluses
|
||||
assertThat(elevees).contains(
|
||||
PrioriteEvenement.CRITIQUE,
|
||||
PrioriteEvenement.HAUTE);
|
||||
|
||||
// Vérifier qu'aucune priorité non élevée n'est incluse
|
||||
assertThat(elevees).doesNotContain(
|
||||
PrioriteEvenement.NORMALE,
|
||||
PrioriteEvenement.BASSE);
|
||||
|
||||
// Vérifier que toutes les priorités retournées sont bien élevées
|
||||
elevees.forEach(priorite -> assertThat(priorite.isElevee()).isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getPrioritesUrgentes")
|
||||
void testGetPrioritesUrgentes() {
|
||||
List<PrioriteEvenement> urgentes = PrioriteEvenement.getPrioritesUrgentes();
|
||||
|
||||
// Vérifier que toutes les priorités urgentes sont incluses
|
||||
assertThat(urgentes).contains(
|
||||
PrioriteEvenement.CRITIQUE,
|
||||
PrioriteEvenement.HAUTE);
|
||||
|
||||
// Vérifier qu'aucune priorité non urgente n'est incluse
|
||||
assertThat(urgentes).doesNotContain(
|
||||
PrioriteEvenement.NORMALE,
|
||||
PrioriteEvenement.BASSE);
|
||||
|
||||
// Vérifier que toutes les priorités retournées sont bien urgentes
|
||||
urgentes.forEach(priorite -> assertThat(priorite.isUrgente()).isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test determinerPriorite - toutes les branches du switch")
|
||||
void testDeterminerPriorite() {
|
||||
// ASSEMBLEE_GENERALE -> HAUTE
|
||||
assertThat(PrioriteEvenement.determinerPriorite(TypeEvenementMetier.ASSEMBLEE_GENERALE))
|
||||
.isEqualTo(PrioriteEvenement.HAUTE);
|
||||
|
||||
// REUNION_BUREAU -> HAUTE
|
||||
assertThat(PrioriteEvenement.determinerPriorite(TypeEvenementMetier.REUNION_BUREAU))
|
||||
.isEqualTo(PrioriteEvenement.HAUTE);
|
||||
|
||||
// ACTION_CARITATIVE -> NORMALE
|
||||
assertThat(PrioriteEvenement.determinerPriorite(TypeEvenementMetier.ACTION_CARITATIVE))
|
||||
.isEqualTo(PrioriteEvenement.NORMALE);
|
||||
|
||||
// FORMATION -> NORMALE
|
||||
assertThat(PrioriteEvenement.determinerPriorite(TypeEvenementMetier.FORMATION))
|
||||
.isEqualTo(PrioriteEvenement.NORMALE);
|
||||
|
||||
// CONFERENCE -> NORMALE
|
||||
assertThat(PrioriteEvenement.determinerPriorite(TypeEvenementMetier.CONFERENCE))
|
||||
.isEqualTo(PrioriteEvenement.NORMALE);
|
||||
|
||||
// ACTIVITE_SOCIALE -> BASSE
|
||||
assertThat(PrioriteEvenement.determinerPriorite(TypeEvenementMetier.ACTIVITE_SOCIALE))
|
||||
.isEqualTo(PrioriteEvenement.BASSE);
|
||||
|
||||
// ATELIER -> BASSE
|
||||
assertThat(PrioriteEvenement.determinerPriorite(TypeEvenementMetier.ATELIER))
|
||||
.isEqualTo(PrioriteEvenement.BASSE);
|
||||
|
||||
// CEREMONIE -> NORMALE
|
||||
assertThat(PrioriteEvenement.determinerPriorite(TypeEvenementMetier.CEREMONIE))
|
||||
.isEqualTo(PrioriteEvenement.NORMALE);
|
||||
|
||||
// AUTRE -> NORMALE
|
||||
assertThat(PrioriteEvenement.determinerPriorite(TypeEvenementMetier.AUTRE))
|
||||
.isEqualTo(PrioriteEvenement.NORMALE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getDefaut")
|
||||
void testGetDefaut() {
|
||||
assertThat(PrioriteEvenement.getDefaut()).isEqualTo(PrioriteEvenement.NORMALE);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test cohérence globale des données")
|
||||
void testCoherenceGlobale() {
|
||||
for (PrioriteEvenement priorite : PrioriteEvenement.values()) {
|
||||
// Tous les champs obligatoires non null
|
||||
assertThat(priorite.getLibelle()).isNotNull().isNotEmpty();
|
||||
assertThat(priorite.getCode()).isNotNull().isNotEmpty();
|
||||
assertThat(priorite.getDescription()).isNotNull().isNotEmpty();
|
||||
assertThat(priorite.getCouleur()).isNotNull().matches("#[0-9A-Fa-f]{6}");
|
||||
assertThat(priorite.getIcone()).isNotNull().isNotEmpty();
|
||||
assertThat(priorite.getNiveau()).isPositive();
|
||||
|
||||
// Cohérence logique
|
||||
if (priorite.isElevee()) {
|
||||
// Les priorités élevées sont aussi urgentes
|
||||
assertThat(priorite.isUrgente()).isTrue();
|
||||
// Les priorités élevées ont notification immédiate
|
||||
assertThat(priorite.isNotificationImmediate()).isTrue();
|
||||
}
|
||||
|
||||
if (priorite.isEscaladeAutomatique()) {
|
||||
// Seule CRITIQUE a escalade automatique
|
||||
assertThat(priorite).isEqualTo(PrioriteEvenement.CRITIQUE);
|
||||
}
|
||||
|
||||
// Niveaux cohérents (plus bas = plus prioritaire)
|
||||
if (priorite == PrioriteEvenement.CRITIQUE) {
|
||||
assertThat(priorite.getNiveau()).isEqualTo(1);
|
||||
}
|
||||
if (priorite == PrioriteEvenement.BASSE) {
|
||||
assertThat(priorite.getNiveau()).isEqualTo(4);
|
||||
}
|
||||
|
||||
// Comparaisons cohérentes
|
||||
assertThat(priorite.isSuperieurA(priorite)).isFalse(); // Pas supérieur à soi-même
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,468 @@
|
||||
package dev.lions.unionflow.server.api.enums.evenement;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires EXHAUSTIFS pour StatutEvenement - Couverture 100%
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@DisplayName("Tests EXHAUSTIFS StatutEvenement")
|
||||
class StatutEvenementTest {
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des valeurs enum et constructeur")
|
||||
class TestsValeursEnum {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test valueOf et values")
|
||||
void testValueOfEtValues() {
|
||||
StatutEvenement[] values = StatutEvenement.values();
|
||||
assertThat(values).hasSize(6);
|
||||
assertThat(values).containsExactly(
|
||||
StatutEvenement.PLANIFIE,
|
||||
StatutEvenement.CONFIRME,
|
||||
StatutEvenement.EN_COURS,
|
||||
StatutEvenement.TERMINE,
|
||||
StatutEvenement.ANNULE,
|
||||
StatutEvenement.REPORTE);
|
||||
|
||||
// Test valueOf pour toutes les valeurs
|
||||
assertThat(StatutEvenement.valueOf("PLANIFIE")).isEqualTo(StatutEvenement.PLANIFIE);
|
||||
assertThat(StatutEvenement.valueOf("CONFIRME")).isEqualTo(StatutEvenement.CONFIRME);
|
||||
assertThat(StatutEvenement.valueOf("EN_COURS")).isEqualTo(StatutEvenement.EN_COURS);
|
||||
assertThat(StatutEvenement.valueOf("TERMINE")).isEqualTo(StatutEvenement.TERMINE);
|
||||
assertThat(StatutEvenement.valueOf("ANNULE")).isEqualTo(StatutEvenement.ANNULE);
|
||||
assertThat(StatutEvenement.valueOf("REPORTE")).isEqualTo(StatutEvenement.REPORTE);
|
||||
|
||||
assertThatThrownBy(() -> StatutEvenement.valueOf("INEXISTANT"))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test ordinal, name et toString")
|
||||
void testOrdinalNameToString() {
|
||||
assertThat(StatutEvenement.PLANIFIE.ordinal()).isEqualTo(0);
|
||||
assertThat(StatutEvenement.CONFIRME.ordinal()).isEqualTo(1);
|
||||
assertThat(StatutEvenement.EN_COURS.ordinal()).isEqualTo(2);
|
||||
assertThat(StatutEvenement.TERMINE.ordinal()).isEqualTo(3);
|
||||
assertThat(StatutEvenement.ANNULE.ordinal()).isEqualTo(4);
|
||||
assertThat(StatutEvenement.REPORTE.ordinal()).isEqualTo(5);
|
||||
|
||||
assertThat(StatutEvenement.PLANIFIE.name()).isEqualTo("PLANIFIE");
|
||||
assertThat(StatutEvenement.EN_COURS.name()).isEqualTo("EN_COURS");
|
||||
|
||||
assertThat(StatutEvenement.PLANIFIE.toString()).isEqualTo("PLANIFIE");
|
||||
assertThat(StatutEvenement.TERMINE.toString()).isEqualTo("TERMINE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés PLANIFIE")
|
||||
void testProprietePlanifie() {
|
||||
StatutEvenement statut = StatutEvenement.PLANIFIE;
|
||||
assertThat(statut.getLibelle()).isEqualTo("Planifié");
|
||||
assertThat(statut.getCode()).isEqualTo("planned");
|
||||
assertThat(statut.getDescription()).isEqualTo("L'événement est planifié et en préparation");
|
||||
assertThat(statut.getCouleur()).isEqualTo("#2196F3");
|
||||
assertThat(statut.getIcone()).isEqualTo("event");
|
||||
assertThat(statut.isEstFinal()).isFalse();
|
||||
assertThat(statut.isEstEchec()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés CONFIRME")
|
||||
void testProprieteConfirme() {
|
||||
StatutEvenement statut = StatutEvenement.CONFIRME;
|
||||
assertThat(statut.getLibelle()).isEqualTo("Confirmé");
|
||||
assertThat(statut.getCode()).isEqualTo("confirmed");
|
||||
assertThat(statut.getDescription()).isEqualTo("L'événement est confirmé et les inscriptions sont ouvertes");
|
||||
assertThat(statut.getCouleur()).isEqualTo("#4CAF50");
|
||||
assertThat(statut.getIcone()).isEqualTo("event_available");
|
||||
assertThat(statut.isEstFinal()).isFalse();
|
||||
assertThat(statut.isEstEchec()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés EN_COURS")
|
||||
void testProprieteEnCours() {
|
||||
StatutEvenement statut = StatutEvenement.EN_COURS;
|
||||
assertThat(statut.getLibelle()).isEqualTo("En cours");
|
||||
assertThat(statut.getCode()).isEqualTo("ongoing");
|
||||
assertThat(statut.getDescription()).isEqualTo("L'événement est actuellement en cours");
|
||||
assertThat(statut.getCouleur()).isEqualTo("#FF9800");
|
||||
assertThat(statut.getIcone()).isEqualTo("play_circle");
|
||||
assertThat(statut.isEstFinal()).isFalse();
|
||||
assertThat(statut.isEstEchec()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés TERMINE")
|
||||
void testProprieteTermine() {
|
||||
StatutEvenement statut = StatutEvenement.TERMINE;
|
||||
assertThat(statut.getLibelle()).isEqualTo("Terminé");
|
||||
assertThat(statut.getCode()).isEqualTo("completed");
|
||||
assertThat(statut.getDescription()).isEqualTo("L'événement s'est terminé avec succès");
|
||||
assertThat(statut.getCouleur()).isEqualTo("#4CAF50");
|
||||
assertThat(statut.getIcone()).isEqualTo("check_circle");
|
||||
assertThat(statut.isEstFinal()).isTrue();
|
||||
assertThat(statut.isEstEchec()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés ANNULE")
|
||||
void testProprieteAnnule() {
|
||||
StatutEvenement statut = StatutEvenement.ANNULE;
|
||||
assertThat(statut.getLibelle()).isEqualTo("Annulé");
|
||||
assertThat(statut.getCode()).isEqualTo("cancelled");
|
||||
assertThat(statut.getDescription()).isEqualTo("L'événement a été annulé");
|
||||
assertThat(statut.getCouleur()).isEqualTo("#F44336");
|
||||
assertThat(statut.getIcone()).isEqualTo("cancel");
|
||||
assertThat(statut.isEstFinal()).isTrue();
|
||||
assertThat(statut.isEstEchec()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés REPORTE")
|
||||
void testProprieteReporte() {
|
||||
StatutEvenement statut = StatutEvenement.REPORTE;
|
||||
assertThat(statut.getLibelle()).isEqualTo("Reporté");
|
||||
assertThat(statut.getCode()).isEqualTo("postponed");
|
||||
assertThat(statut.getDescription()).isEqualTo("L'événement a été reporté à une date ultérieure");
|
||||
assertThat(statut.getCouleur()).isEqualTo("#FF5722");
|
||||
assertThat(statut.getIcone()).isEqualTo("schedule");
|
||||
assertThat(statut.isEstFinal()).isFalse();
|
||||
assertThat(statut.isEstEchec()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes métier")
|
||||
class TestsMethodesMetier {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test permetModification - toutes les branches du switch")
|
||||
void testPermetModification() {
|
||||
// PLANIFIE, CONFIRME, REPORTE -> true
|
||||
assertThat(StatutEvenement.PLANIFIE.permetModification()).isTrue();
|
||||
assertThat(StatutEvenement.CONFIRME.permetModification()).isTrue();
|
||||
assertThat(StatutEvenement.REPORTE.permetModification()).isTrue();
|
||||
|
||||
// EN_COURS, TERMINE, ANNULE -> false
|
||||
assertThat(StatutEvenement.EN_COURS.permetModification()).isFalse();
|
||||
assertThat(StatutEvenement.TERMINE.permetModification()).isFalse();
|
||||
assertThat(StatutEvenement.ANNULE.permetModification()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test permetAnnulation - toutes les branches du switch")
|
||||
void testPermetAnnulation() {
|
||||
// PLANIFIE, CONFIRME, EN_COURS, REPORTE -> true
|
||||
assertThat(StatutEvenement.PLANIFIE.permetAnnulation()).isTrue();
|
||||
assertThat(StatutEvenement.CONFIRME.permetAnnulation()).isTrue();
|
||||
assertThat(StatutEvenement.EN_COURS.permetAnnulation()).isTrue();
|
||||
assertThat(StatutEvenement.REPORTE.permetAnnulation()).isTrue();
|
||||
|
||||
// TERMINE, ANNULE -> false
|
||||
assertThat(StatutEvenement.TERMINE.permetAnnulation()).isFalse();
|
||||
assertThat(StatutEvenement.ANNULE.permetAnnulation()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isEnCours - toutes les branches")
|
||||
void testIsEnCours() {
|
||||
// Seul EN_COURS retourne true
|
||||
assertThat(StatutEvenement.EN_COURS.isEnCours()).isTrue();
|
||||
|
||||
// Tous les autres retournent false
|
||||
assertThat(StatutEvenement.PLANIFIE.isEnCours()).isFalse();
|
||||
assertThat(StatutEvenement.CONFIRME.isEnCours()).isFalse();
|
||||
assertThat(StatutEvenement.TERMINE.isEnCours()).isFalse();
|
||||
assertThat(StatutEvenement.ANNULE.isEnCours()).isFalse();
|
||||
assertThat(StatutEvenement.REPORTE.isEnCours()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isSucces - toutes les branches")
|
||||
void testIsSucces() {
|
||||
// Seul TERMINE retourne true
|
||||
assertThat(StatutEvenement.TERMINE.isSucces()).isTrue();
|
||||
|
||||
// Tous les autres retournent false
|
||||
assertThat(StatutEvenement.PLANIFIE.isSucces()).isFalse();
|
||||
assertThat(StatutEvenement.CONFIRME.isSucces()).isFalse();
|
||||
assertThat(StatutEvenement.EN_COURS.isSucces()).isFalse();
|
||||
assertThat(StatutEvenement.ANNULE.isSucces()).isFalse();
|
||||
assertThat(StatutEvenement.REPORTE.isSucces()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getNiveauPriorite - toutes les branches du switch")
|
||||
void testGetNiveauPriorite() {
|
||||
// EN_COURS -> 1
|
||||
assertThat(StatutEvenement.EN_COURS.getNiveauPriorite()).isEqualTo(1);
|
||||
|
||||
// CONFIRME -> 2
|
||||
assertThat(StatutEvenement.CONFIRME.getNiveauPriorite()).isEqualTo(2);
|
||||
|
||||
// PLANIFIE -> 3
|
||||
assertThat(StatutEvenement.PLANIFIE.getNiveauPriorite()).isEqualTo(3);
|
||||
|
||||
// REPORTE -> 4
|
||||
assertThat(StatutEvenement.REPORTE.getNiveauPriorite()).isEqualTo(4);
|
||||
|
||||
// TERMINE -> 5
|
||||
assertThat(StatutEvenement.TERMINE.getNiveauPriorite()).isEqualTo(5);
|
||||
|
||||
// ANNULE -> 6
|
||||
assertThat(StatutEvenement.ANNULE.getNiveauPriorite()).isEqualTo(6);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes statiques")
|
||||
class TestsMethodesStatiques {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getStatutsFinaux")
|
||||
void testGetStatutsFinaux() {
|
||||
List<StatutEvenement> finaux = StatutEvenement.getStatutsFinaux();
|
||||
|
||||
// Vérifier que tous les statuts finaux sont inclus
|
||||
assertThat(finaux).contains(
|
||||
StatutEvenement.TERMINE,
|
||||
StatutEvenement.ANNULE);
|
||||
|
||||
// Vérifier qu'aucun statut non final n'est inclus
|
||||
assertThat(finaux).doesNotContain(
|
||||
StatutEvenement.PLANIFIE,
|
||||
StatutEvenement.CONFIRME,
|
||||
StatutEvenement.EN_COURS,
|
||||
StatutEvenement.REPORTE);
|
||||
|
||||
// Vérifier que tous les statuts retournés sont bien finaux
|
||||
finaux.forEach(statut -> assertThat(statut.isEstFinal()).isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getStatutsEchec")
|
||||
void testGetStatutsEchec() {
|
||||
List<StatutEvenement> echecs = StatutEvenement.getStatutsEchec();
|
||||
|
||||
// Vérifier que tous les statuts d'échec sont inclus
|
||||
assertThat(echecs).contains(StatutEvenement.ANNULE);
|
||||
|
||||
// Vérifier qu'aucun statut non échec n'est inclus
|
||||
assertThat(echecs).doesNotContain(
|
||||
StatutEvenement.PLANIFIE,
|
||||
StatutEvenement.CONFIRME,
|
||||
StatutEvenement.EN_COURS,
|
||||
StatutEvenement.TERMINE,
|
||||
StatutEvenement.REPORTE);
|
||||
|
||||
// Vérifier que tous les statuts retournés sont bien des échecs
|
||||
echecs.forEach(statut -> assertThat(statut.isEstEchec()).isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getStatutsActifs")
|
||||
void testGetStatutsActifs() {
|
||||
StatutEvenement[] actifs = StatutEvenement.getStatutsActifs();
|
||||
|
||||
// Vérifier le contenu exact
|
||||
assertThat(actifs).containsExactly(
|
||||
StatutEvenement.PLANIFIE,
|
||||
StatutEvenement.CONFIRME,
|
||||
StatutEvenement.EN_COURS,
|
||||
StatutEvenement.REPORTE);
|
||||
|
||||
// Vérifier qu'aucun statut final n'est inclus
|
||||
assertThat(actifs).doesNotContain(
|
||||
StatutEvenement.TERMINE,
|
||||
StatutEvenement.ANNULE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test fromCode - toutes les branches")
|
||||
void testFromCode() {
|
||||
// Codes valides
|
||||
assertThat(StatutEvenement.fromCode("planned")).isEqualTo(StatutEvenement.PLANIFIE);
|
||||
assertThat(StatutEvenement.fromCode("confirmed")).isEqualTo(StatutEvenement.CONFIRME);
|
||||
assertThat(StatutEvenement.fromCode("ongoing")).isEqualTo(StatutEvenement.EN_COURS);
|
||||
assertThat(StatutEvenement.fromCode("completed")).isEqualTo(StatutEvenement.TERMINE);
|
||||
assertThat(StatutEvenement.fromCode("cancelled")).isEqualTo(StatutEvenement.ANNULE);
|
||||
assertThat(StatutEvenement.fromCode("postponed")).isEqualTo(StatutEvenement.REPORTE);
|
||||
|
||||
// Code inexistant
|
||||
assertThat(StatutEvenement.fromCode("inexistant")).isNull();
|
||||
|
||||
// Cas limites
|
||||
assertThat(StatutEvenement.fromCode(null)).isNull();
|
||||
assertThat(StatutEvenement.fromCode("")).isNull();
|
||||
assertThat(StatutEvenement.fromCode(" ")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test fromLibelle - toutes les branches")
|
||||
void testFromLibelle() {
|
||||
// Libellés valides
|
||||
assertThat(StatutEvenement.fromLibelle("Planifié")).isEqualTo(StatutEvenement.PLANIFIE);
|
||||
assertThat(StatutEvenement.fromLibelle("Confirmé")).isEqualTo(StatutEvenement.CONFIRME);
|
||||
assertThat(StatutEvenement.fromLibelle("En cours")).isEqualTo(StatutEvenement.EN_COURS);
|
||||
assertThat(StatutEvenement.fromLibelle("Terminé")).isEqualTo(StatutEvenement.TERMINE);
|
||||
assertThat(StatutEvenement.fromLibelle("Annulé")).isEqualTo(StatutEvenement.ANNULE);
|
||||
assertThat(StatutEvenement.fromLibelle("Reporté")).isEqualTo(StatutEvenement.REPORTE);
|
||||
|
||||
// Libellé inexistant
|
||||
assertThat(StatutEvenement.fromLibelle("Inexistant")).isNull();
|
||||
|
||||
// Cas limites
|
||||
assertThat(StatutEvenement.fromLibelle(null)).isNull();
|
||||
assertThat(StatutEvenement.fromLibelle("")).isNull();
|
||||
assertThat(StatutEvenement.fromLibelle(" ")).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes complexes")
|
||||
class TestsMethodesComplexes {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test peutTransitionnerVers - toutes les branches")
|
||||
void testPeutTransitionnerVers() {
|
||||
// Règles générales
|
||||
// this == nouveauStatut -> false
|
||||
assertThat(StatutEvenement.PLANIFIE.peutTransitionnerVers(StatutEvenement.PLANIFIE)).isFalse();
|
||||
assertThat(StatutEvenement.CONFIRME.peutTransitionnerVers(StatutEvenement.CONFIRME)).isFalse();
|
||||
|
||||
// estFinal && nouveauStatut != REPORTE -> false
|
||||
assertThat(StatutEvenement.TERMINE.peutTransitionnerVers(StatutEvenement.PLANIFIE)).isFalse();
|
||||
assertThat(StatutEvenement.ANNULE.peutTransitionnerVers(StatutEvenement.CONFIRME)).isFalse();
|
||||
|
||||
// estFinal && nouveauStatut == REPORTE -> mais default false dans switch
|
||||
// TERMINE et ANNULE ne sont pas dans le switch, donc default -> false
|
||||
assertThat(StatutEvenement.TERMINE.peutTransitionnerVers(StatutEvenement.REPORTE)).isFalse();
|
||||
assertThat(StatutEvenement.ANNULE.peutTransitionnerVers(StatutEvenement.REPORTE)).isFalse();
|
||||
|
||||
// PLANIFIE -> CONFIRME || ANNULE || REPORTE
|
||||
assertThat(StatutEvenement.PLANIFIE.peutTransitionnerVers(StatutEvenement.CONFIRME)).isTrue();
|
||||
assertThat(StatutEvenement.PLANIFIE.peutTransitionnerVers(StatutEvenement.ANNULE)).isTrue();
|
||||
assertThat(StatutEvenement.PLANIFIE.peutTransitionnerVers(StatutEvenement.REPORTE)).isTrue();
|
||||
assertThat(StatutEvenement.PLANIFIE.peutTransitionnerVers(StatutEvenement.EN_COURS)).isFalse();
|
||||
assertThat(StatutEvenement.PLANIFIE.peutTransitionnerVers(StatutEvenement.TERMINE)).isFalse();
|
||||
|
||||
// CONFIRME -> EN_COURS || ANNULE || REPORTE
|
||||
assertThat(StatutEvenement.CONFIRME.peutTransitionnerVers(StatutEvenement.EN_COURS)).isTrue();
|
||||
assertThat(StatutEvenement.CONFIRME.peutTransitionnerVers(StatutEvenement.ANNULE)).isTrue();
|
||||
assertThat(StatutEvenement.CONFIRME.peutTransitionnerVers(StatutEvenement.REPORTE)).isTrue();
|
||||
assertThat(StatutEvenement.CONFIRME.peutTransitionnerVers(StatutEvenement.PLANIFIE)).isFalse();
|
||||
assertThat(StatutEvenement.CONFIRME.peutTransitionnerVers(StatutEvenement.TERMINE)).isFalse();
|
||||
|
||||
// EN_COURS -> TERMINE || ANNULE
|
||||
assertThat(StatutEvenement.EN_COURS.peutTransitionnerVers(StatutEvenement.TERMINE)).isTrue();
|
||||
assertThat(StatutEvenement.EN_COURS.peutTransitionnerVers(StatutEvenement.ANNULE)).isTrue();
|
||||
assertThat(StatutEvenement.EN_COURS.peutTransitionnerVers(StatutEvenement.PLANIFIE)).isFalse();
|
||||
assertThat(StatutEvenement.EN_COURS.peutTransitionnerVers(StatutEvenement.CONFIRME)).isFalse();
|
||||
assertThat(StatutEvenement.EN_COURS.peutTransitionnerVers(StatutEvenement.REPORTE)).isFalse();
|
||||
|
||||
// REPORTE -> PLANIFIE || ANNULE (pas CONFIRME selon le code)
|
||||
assertThat(StatutEvenement.REPORTE.peutTransitionnerVers(StatutEvenement.PLANIFIE)).isTrue();
|
||||
assertThat(StatutEvenement.REPORTE.peutTransitionnerVers(StatutEvenement.ANNULE)).isTrue();
|
||||
assertThat(StatutEvenement.REPORTE.peutTransitionnerVers(StatutEvenement.CONFIRME)).isFalse();
|
||||
assertThat(StatutEvenement.REPORTE.peutTransitionnerVers(StatutEvenement.EN_COURS)).isFalse();
|
||||
assertThat(StatutEvenement.REPORTE.peutTransitionnerVers(StatutEvenement.TERMINE)).isFalse();
|
||||
|
||||
// default -> false (pour les statuts non couverts par le switch)
|
||||
// Déjà testé avec les statuts finaux ci-dessus
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getTransitionsPossibles - toutes les branches du switch")
|
||||
void testGetTransitionsPossibles() {
|
||||
// PLANIFIE -> [CONFIRME, ANNULE, REPORTE]
|
||||
StatutEvenement[] transitionsPlanifie = StatutEvenement.PLANIFIE.getTransitionsPossibles();
|
||||
assertThat(transitionsPlanifie).containsExactly(
|
||||
StatutEvenement.CONFIRME,
|
||||
StatutEvenement.ANNULE,
|
||||
StatutEvenement.REPORTE);
|
||||
|
||||
// CONFIRME -> [EN_COURS, ANNULE, REPORTE]
|
||||
StatutEvenement[] transitionsConfirme = StatutEvenement.CONFIRME.getTransitionsPossibles();
|
||||
assertThat(transitionsConfirme).containsExactly(
|
||||
StatutEvenement.EN_COURS,
|
||||
StatutEvenement.ANNULE,
|
||||
StatutEvenement.REPORTE);
|
||||
|
||||
// EN_COURS -> [TERMINE, ANNULE]
|
||||
StatutEvenement[] transitionsEnCours = StatutEvenement.EN_COURS.getTransitionsPossibles();
|
||||
assertThat(transitionsEnCours).containsExactly(
|
||||
StatutEvenement.TERMINE,
|
||||
StatutEvenement.ANNULE);
|
||||
|
||||
// REPORTE -> [PLANIFIE, CONFIRME, ANNULE] (selon getTransitionsPossibles)
|
||||
StatutEvenement[] transitionsReporte = StatutEvenement.REPORTE.getTransitionsPossibles();
|
||||
assertThat(transitionsReporte).containsExactly(
|
||||
StatutEvenement.PLANIFIE,
|
||||
StatutEvenement.CONFIRME,
|
||||
StatutEvenement.ANNULE);
|
||||
|
||||
// TERMINE, ANNULE -> [] (aucune transition)
|
||||
StatutEvenement[] transitionsTermine = StatutEvenement.TERMINE.getTransitionsPossibles();
|
||||
assertThat(transitionsTermine).isEmpty();
|
||||
|
||||
StatutEvenement[] transitionsAnnule = StatutEvenement.ANNULE.getTransitionsPossibles();
|
||||
assertThat(transitionsAnnule).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test cohérence globale des données")
|
||||
void testCoherenceGlobale() {
|
||||
for (StatutEvenement statut : StatutEvenement.values()) {
|
||||
// Tous les champs obligatoires non null
|
||||
assertThat(statut.getLibelle()).isNotNull().isNotEmpty();
|
||||
assertThat(statut.getCode()).isNotNull().isNotEmpty();
|
||||
assertThat(statut.getDescription()).isNotNull().isNotEmpty();
|
||||
assertThat(statut.getCouleur()).isNotNull().matches("#[0-9A-Fa-f]{6}");
|
||||
assertThat(statut.getIcone()).isNotNull().isNotEmpty();
|
||||
|
||||
// Cohérence logique
|
||||
if (statut.isEstFinal()) {
|
||||
// Les statuts finaux ne permettent pas la modification
|
||||
assertThat(statut.permetModification()).isFalse();
|
||||
}
|
||||
|
||||
if (statut.isEstEchec()) {
|
||||
// Les statuts d'échec ne sont pas des succès
|
||||
assertThat(statut.isSucces()).isFalse();
|
||||
// Les statuts d'échec sont finaux
|
||||
assertThat(statut.isEstFinal()).isTrue();
|
||||
}
|
||||
|
||||
if (statut.isSucces()) {
|
||||
// Les statuts de succès ne sont pas des échecs
|
||||
assertThat(statut.isEstEchec()).isFalse();
|
||||
// Les statuts de succès sont finaux
|
||||
assertThat(statut.isEstFinal()).isTrue();
|
||||
}
|
||||
|
||||
// Niveau de priorité cohérent
|
||||
int niveau = statut.getNiveauPriorite();
|
||||
assertThat(niveau).isBetween(1, 6);
|
||||
|
||||
// Transitions cohérentes
|
||||
assertThat(statut.peutTransitionnerVers(statut)).isFalse(); // Pas de transition vers soi-même
|
||||
|
||||
// Méthodes de recherche cohérentes
|
||||
assertThat(StatutEvenement.fromCode(statut.getCode())).isEqualTo(statut);
|
||||
assertThat(StatutEvenement.fromLibelle(statut.getLibelle())).isEqualTo(statut);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
package dev.lions.unionflow.server.api.enums.solidarite;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.within;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires EXHAUSTIFS pour PrioriteAide - Couverture 100%
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@DisplayName("Tests EXHAUSTIFS PrioriteAide")
|
||||
class PrioriteAideTest {
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des valeurs enum et constructeur")
|
||||
class TestsValeursEnum {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test toutes les valeurs enum avec propriétés exactes")
|
||||
void testToutesValeursExactes() {
|
||||
// CRITIQUE
|
||||
assertThat(PrioriteAide.CRITIQUE.getLibelle()).isEqualTo("Critique");
|
||||
assertThat(PrioriteAide.CRITIQUE.getCode()).isEqualTo("critical");
|
||||
assertThat(PrioriteAide.CRITIQUE.getNiveau()).isEqualTo(1);
|
||||
assertThat(PrioriteAide.CRITIQUE.getDescription()).isEqualTo("Situation critique nécessitant une intervention immédiate");
|
||||
assertThat(PrioriteAide.CRITIQUE.getCouleur()).isEqualTo("#F44336");
|
||||
assertThat(PrioriteAide.CRITIQUE.getIcone()).isEqualTo("emergency");
|
||||
assertThat(PrioriteAide.CRITIQUE.getDelaiTraitementHeures()).isEqualTo(24);
|
||||
assertThat(PrioriteAide.CRITIQUE.isNotificationImmediate()).isTrue();
|
||||
assertThat(PrioriteAide.CRITIQUE.isEscaladeAutomatique()).isTrue();
|
||||
|
||||
// URGENTE
|
||||
assertThat(PrioriteAide.URGENTE.getLibelle()).isEqualTo("Urgente");
|
||||
assertThat(PrioriteAide.URGENTE.getCode()).isEqualTo("urgent");
|
||||
assertThat(PrioriteAide.URGENTE.getNiveau()).isEqualTo(2);
|
||||
assertThat(PrioriteAide.URGENTE.getDescription()).isEqualTo("Situation urgente nécessitant une réponse rapide");
|
||||
assertThat(PrioriteAide.URGENTE.getCouleur()).isEqualTo("#FF5722");
|
||||
assertThat(PrioriteAide.URGENTE.getIcone()).isEqualTo("priority_high");
|
||||
assertThat(PrioriteAide.URGENTE.getDelaiTraitementHeures()).isEqualTo(72);
|
||||
assertThat(PrioriteAide.URGENTE.isNotificationImmediate()).isTrue();
|
||||
assertThat(PrioriteAide.URGENTE.isEscaladeAutomatique()).isFalse();
|
||||
|
||||
// ELEVEE
|
||||
assertThat(PrioriteAide.ELEVEE.getLibelle()).isEqualTo("Élevée");
|
||||
assertThat(PrioriteAide.ELEVEE.getCode()).isEqualTo("high");
|
||||
assertThat(PrioriteAide.ELEVEE.getNiveau()).isEqualTo(3);
|
||||
assertThat(PrioriteAide.ELEVEE.getDescription()).isEqualTo("Priorité élevée, traitement dans les meilleurs délais");
|
||||
assertThat(PrioriteAide.ELEVEE.getCouleur()).isEqualTo("#FF9800");
|
||||
assertThat(PrioriteAide.ELEVEE.getIcone()).isEqualTo("keyboard_arrow_up");
|
||||
assertThat(PrioriteAide.ELEVEE.getDelaiTraitementHeures()).isEqualTo(168);
|
||||
assertThat(PrioriteAide.ELEVEE.isNotificationImmediate()).isFalse();
|
||||
assertThat(PrioriteAide.ELEVEE.isEscaladeAutomatique()).isFalse();
|
||||
|
||||
// NORMALE
|
||||
assertThat(PrioriteAide.NORMALE.getLibelle()).isEqualTo("Normale");
|
||||
assertThat(PrioriteAide.NORMALE.getCode()).isEqualTo("normal");
|
||||
assertThat(PrioriteAide.NORMALE.getNiveau()).isEqualTo(4);
|
||||
assertThat(PrioriteAide.NORMALE.getDescription()).isEqualTo("Priorité normale, traitement selon les délais standards");
|
||||
assertThat(PrioriteAide.NORMALE.getCouleur()).isEqualTo("#2196F3");
|
||||
assertThat(PrioriteAide.NORMALE.getIcone()).isEqualTo("remove");
|
||||
assertThat(PrioriteAide.NORMALE.getDelaiTraitementHeures()).isEqualTo(336);
|
||||
assertThat(PrioriteAide.NORMALE.isNotificationImmediate()).isFalse();
|
||||
assertThat(PrioriteAide.NORMALE.isEscaladeAutomatique()).isFalse();
|
||||
|
||||
// FAIBLE
|
||||
assertThat(PrioriteAide.FAIBLE.getLibelle()).isEqualTo("Faible");
|
||||
assertThat(PrioriteAide.FAIBLE.getCode()).isEqualTo("low");
|
||||
assertThat(PrioriteAide.FAIBLE.getNiveau()).isEqualTo(5);
|
||||
assertThat(PrioriteAide.FAIBLE.getDescription()).isEqualTo("Priorité faible, traitement quand les ressources le permettent");
|
||||
assertThat(PrioriteAide.FAIBLE.getCouleur()).isEqualTo("#4CAF50");
|
||||
assertThat(PrioriteAide.FAIBLE.getIcone()).isEqualTo("keyboard_arrow_down");
|
||||
assertThat(PrioriteAide.FAIBLE.getDelaiTraitementHeures()).isEqualTo(720);
|
||||
assertThat(PrioriteAide.FAIBLE.isNotificationImmediate()).isFalse();
|
||||
assertThat(PrioriteAide.FAIBLE.isEscaladeAutomatique()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test valueOf et values")
|
||||
void testValueOfEtValues() {
|
||||
PrioriteAide[] values = PrioriteAide.values();
|
||||
assertThat(values).hasSize(5);
|
||||
assertThat(values).containsExactly(
|
||||
PrioriteAide.CRITIQUE,
|
||||
PrioriteAide.URGENTE,
|
||||
PrioriteAide.ELEVEE,
|
||||
PrioriteAide.NORMALE,
|
||||
PrioriteAide.FAIBLE);
|
||||
|
||||
assertThat(PrioriteAide.valueOf("CRITIQUE")).isEqualTo(PrioriteAide.CRITIQUE);
|
||||
assertThat(PrioriteAide.valueOf("URGENTE")).isEqualTo(PrioriteAide.URGENTE);
|
||||
assertThat(PrioriteAide.valueOf("ELEVEE")).isEqualTo(PrioriteAide.ELEVEE);
|
||||
assertThat(PrioriteAide.valueOf("NORMALE")).isEqualTo(PrioriteAide.NORMALE);
|
||||
assertThat(PrioriteAide.valueOf("FAIBLE")).isEqualTo(PrioriteAide.FAIBLE);
|
||||
|
||||
assertThatThrownBy(() -> PrioriteAide.valueOf("INEXISTANT"))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test ordinal et name")
|
||||
void testOrdinalEtName() {
|
||||
assertThat(PrioriteAide.CRITIQUE.ordinal()).isEqualTo(0);
|
||||
assertThat(PrioriteAide.URGENTE.ordinal()).isEqualTo(1);
|
||||
assertThat(PrioriteAide.ELEVEE.ordinal()).isEqualTo(2);
|
||||
assertThat(PrioriteAide.NORMALE.ordinal()).isEqualTo(3);
|
||||
assertThat(PrioriteAide.FAIBLE.ordinal()).isEqualTo(4);
|
||||
|
||||
assertThat(PrioriteAide.CRITIQUE.name()).isEqualTo("CRITIQUE");
|
||||
assertThat(PrioriteAide.URGENTE.name()).isEqualTo("URGENTE");
|
||||
assertThat(PrioriteAide.ELEVEE.name()).isEqualTo("ELEVEE");
|
||||
assertThat(PrioriteAide.NORMALE.name()).isEqualTo("NORMALE");
|
||||
assertThat(PrioriteAide.FAIBLE.name()).isEqualTo("FAIBLE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test toString")
|
||||
void testToString() {
|
||||
assertThat(PrioriteAide.CRITIQUE.toString()).isEqualTo("CRITIQUE");
|
||||
assertThat(PrioriteAide.URGENTE.toString()).isEqualTo("URGENTE");
|
||||
assertThat(PrioriteAide.ELEVEE.toString()).isEqualTo("ELEVEE");
|
||||
assertThat(PrioriteAide.NORMALE.toString()).isEqualTo("NORMALE");
|
||||
assertThat(PrioriteAide.FAIBLE.toString()).isEqualTo("FAIBLE");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes métier")
|
||||
class TestsMethodesMetier {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isUrgente - toutes les branches")
|
||||
void testIsUrgente() {
|
||||
// Priorités urgentes (this == CRITIQUE || this == URGENTE)
|
||||
assertThat(PrioriteAide.CRITIQUE.isUrgente()).isTrue();
|
||||
assertThat(PrioriteAide.URGENTE.isUrgente()).isTrue();
|
||||
|
||||
// Priorités non urgentes
|
||||
assertThat(PrioriteAide.ELEVEE.isUrgente()).isFalse();
|
||||
assertThat(PrioriteAide.NORMALE.isUrgente()).isFalse();
|
||||
assertThat(PrioriteAide.FAIBLE.isUrgente()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test necessiteTraitementImmediat - toutes les branches")
|
||||
void testNecessiteTraitementImmediat() {
|
||||
// Niveau <= 2
|
||||
assertThat(PrioriteAide.CRITIQUE.necessiteTraitementImmediat()).isTrue(); // niveau 1
|
||||
assertThat(PrioriteAide.URGENTE.necessiteTraitementImmediat()).isTrue(); // niveau 2
|
||||
|
||||
// Niveau > 2
|
||||
assertThat(PrioriteAide.ELEVEE.necessiteTraitementImmediat()).isFalse(); // niveau 3
|
||||
assertThat(PrioriteAide.NORMALE.necessiteTraitementImmediat()).isFalse(); // niveau 4
|
||||
assertThat(PrioriteAide.FAIBLE.necessiteTraitementImmediat()).isFalse(); // niveau 5
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getDateLimiteTraitement")
|
||||
void testGetDateLimiteTraitement() {
|
||||
LocalDateTime avant = LocalDateTime.now();
|
||||
LocalDateTime dateLimite = PrioriteAide.CRITIQUE.getDateLimiteTraitement();
|
||||
LocalDateTime apres = LocalDateTime.now();
|
||||
|
||||
// La date limite doit être maintenant + 24 heures (±1 seconde pour l'exécution)
|
||||
LocalDateTime attendu = avant.plusHours(24);
|
||||
assertThat(dateLimite).isBetween(attendu.minusSeconds(1), apres.plusHours(24).plusSeconds(1));
|
||||
|
||||
// Test avec URGENTE (72 heures)
|
||||
dateLimite = PrioriteAide.URGENTE.getDateLimiteTraitement();
|
||||
attendu = LocalDateTime.now().plusHours(72);
|
||||
assertThat(dateLimite).isCloseTo(attendu, within(1, ChronoUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getPrioriteEscalade - toutes les branches du switch")
|
||||
void testGetPrioriteEscalade() {
|
||||
// Test toutes les branches du switch
|
||||
assertThat(PrioriteAide.FAIBLE.getPrioriteEscalade()).isEqualTo(PrioriteAide.NORMALE);
|
||||
assertThat(PrioriteAide.NORMALE.getPrioriteEscalade()).isEqualTo(PrioriteAide.ELEVEE);
|
||||
assertThat(PrioriteAide.ELEVEE.getPrioriteEscalade()).isEqualTo(PrioriteAide.URGENTE);
|
||||
assertThat(PrioriteAide.URGENTE.getPrioriteEscalade()).isEqualTo(PrioriteAide.CRITIQUE);
|
||||
assertThat(PrioriteAide.CRITIQUE.getPrioriteEscalade()).isEqualTo(PrioriteAide.CRITIQUE); // Déjà au maximum
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes statiques")
|
||||
class TestsMethodesStatiques {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getPrioritesUrgentes")
|
||||
void testGetPrioritesUrgentes() {
|
||||
List<PrioriteAide> urgentes = PrioriteAide.getPrioritesUrgentes();
|
||||
|
||||
assertThat(urgentes).hasSize(2);
|
||||
assertThat(urgentes).containsExactly(PrioriteAide.CRITIQUE, PrioriteAide.URGENTE);
|
||||
|
||||
// Vérifier que toutes les priorités retournées sont bien urgentes
|
||||
urgentes.forEach(p -> assertThat(p.isUrgente()).isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getParNiveauCroissant")
|
||||
void testGetParNiveauCroissant() {
|
||||
List<PrioriteAide> croissant = PrioriteAide.getParNiveauCroissant();
|
||||
|
||||
assertThat(croissant).hasSize(5);
|
||||
assertThat(croissant).containsExactly(
|
||||
PrioriteAide.CRITIQUE, // niveau 1
|
||||
PrioriteAide.URGENTE, // niveau 2
|
||||
PrioriteAide.ELEVEE, // niveau 3
|
||||
PrioriteAide.NORMALE, // niveau 4
|
||||
PrioriteAide.FAIBLE); // niveau 5
|
||||
|
||||
// Vérifier l'ordre croissant
|
||||
for (int i = 0; i < croissant.size() - 1; i++) {
|
||||
assertThat(croissant.get(i).getNiveau()).isLessThan(croissant.get(i + 1).getNiveau());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getParNiveauDecroissant")
|
||||
void testGetParNiveauDecroissant() {
|
||||
List<PrioriteAide> decroissant = PrioriteAide.getParNiveauDecroissant();
|
||||
|
||||
assertThat(decroissant).hasSize(5);
|
||||
assertThat(decroissant).containsExactly(
|
||||
PrioriteAide.FAIBLE, // niveau 5
|
||||
PrioriteAide.NORMALE, // niveau 4
|
||||
PrioriteAide.ELEVEE, // niveau 3
|
||||
PrioriteAide.URGENTE, // niveau 2
|
||||
PrioriteAide.CRITIQUE); // niveau 1
|
||||
|
||||
// Vérifier l'ordre décroissant
|
||||
for (int i = 0; i < decroissant.size() - 1; i++) {
|
||||
assertThat(decroissant.get(i).getNiveau()).isGreaterThan(decroissant.get(i + 1).getNiveau());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test parCode - toutes les branches")
|
||||
void testParCode() {
|
||||
// Codes existants
|
||||
assertThat(PrioriteAide.parCode("critical")).isEqualTo(PrioriteAide.CRITIQUE);
|
||||
assertThat(PrioriteAide.parCode("urgent")).isEqualTo(PrioriteAide.URGENTE);
|
||||
assertThat(PrioriteAide.parCode("high")).isEqualTo(PrioriteAide.ELEVEE);
|
||||
assertThat(PrioriteAide.parCode("normal")).isEqualTo(PrioriteAide.NORMALE);
|
||||
assertThat(PrioriteAide.parCode("low")).isEqualTo(PrioriteAide.FAIBLE);
|
||||
|
||||
// Code inexistant - retourne NORMALE par défaut
|
||||
assertThat(PrioriteAide.parCode("inexistant")).isEqualTo(PrioriteAide.NORMALE);
|
||||
assertThat(PrioriteAide.parCode("")).isEqualTo(PrioriteAide.NORMALE);
|
||||
assertThat(PrioriteAide.parCode(null)).isEqualTo(PrioriteAide.NORMALE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test determinerPriorite - toutes les branches")
|
||||
void testDeterminerPriorite() {
|
||||
// Types urgents avec switch spécifique
|
||||
assertThat(PrioriteAide.determinerPriorite(TypeAide.AIDE_FINANCIERE_URGENTE))
|
||||
.isEqualTo(PrioriteAide.CRITIQUE);
|
||||
assertThat(PrioriteAide.determinerPriorite(TypeAide.AIDE_FRAIS_MEDICAUX))
|
||||
.isEqualTo(PrioriteAide.CRITIQUE);
|
||||
assertThat(PrioriteAide.determinerPriorite(TypeAide.HEBERGEMENT_URGENCE))
|
||||
.isEqualTo(PrioriteAide.URGENTE);
|
||||
assertThat(PrioriteAide.determinerPriorite(TypeAide.AIDE_ALIMENTAIRE))
|
||||
.isEqualTo(PrioriteAide.URGENTE);
|
||||
|
||||
// Type urgent avec default du switch
|
||||
assertThat(PrioriteAide.determinerPriorite(TypeAide.PRET_SANS_INTERET))
|
||||
.isEqualTo(PrioriteAide.ELEVEE); // urgent mais pas dans les cas spécifiques
|
||||
|
||||
// Type avec priorité "important" (non urgent)
|
||||
assertThat(PrioriteAide.determinerPriorite(TypeAide.AIDE_FRAIS_SCOLARITE))
|
||||
.isEqualTo(PrioriteAide.ELEVEE); // priorité "important"
|
||||
|
||||
// Type normal (ni urgent ni important)
|
||||
assertThat(PrioriteAide.determinerPriorite(TypeAide.DON_MATERIEL))
|
||||
.isEqualTo(PrioriteAide.NORMALE); // priorité "normal"
|
||||
assertThat(PrioriteAide.determinerPriorite(TypeAide.AIDE_COTISATION))
|
||||
.isEqualTo(PrioriteAide.NORMALE); // priorité "normal"
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes de calcul et temporelles")
|
||||
class TestsCalculsTemporels {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getScorePriorite - toutes les branches")
|
||||
void testGetScorePriorite() {
|
||||
// CRITIQUE: niveau=1, notificationImmediate=true, escaladeAutomatique=true, delai=24h
|
||||
// Score = 1 - 0.5 - 0.3 = 0.2
|
||||
assertThat(PrioriteAide.CRITIQUE.getScorePriorite()).isEqualTo(0.2);
|
||||
|
||||
// URGENTE: niveau=2, notificationImmediate=true, escaladeAutomatique=false, delai=72h
|
||||
// Score = 2 - 0.5 = 1.5
|
||||
assertThat(PrioriteAide.URGENTE.getScorePriorite()).isEqualTo(1.5);
|
||||
|
||||
// ELEVEE: niveau=3, notificationImmediate=false, escaladeAutomatique=false, delai=168h
|
||||
// Score = 3 (pas de bonus/malus car délai = 168h exactement)
|
||||
assertThat(PrioriteAide.ELEVEE.getScorePriorite()).isEqualTo(3.0);
|
||||
|
||||
// NORMALE: niveau=4, notificationImmediate=false, escaladeAutomatique=false, delai=336h
|
||||
// Score = 4 + 0.2 = 4.2 (malus car délai > 168h)
|
||||
assertThat(PrioriteAide.NORMALE.getScorePriorite()).isEqualTo(4.2);
|
||||
|
||||
// FAIBLE: niveau=5, notificationImmediate=false, escaladeAutomatique=false, delai=720h
|
||||
// Score = 5 + 0.2 = 5.2 (malus car délai > 168h)
|
||||
assertThat(PrioriteAide.FAIBLE.getScorePriorite()).isEqualTo(5.2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isDelaiDepasse - toutes les branches")
|
||||
void testIsDelaiDepasse() {
|
||||
LocalDateTime maintenant = LocalDateTime.now();
|
||||
|
||||
// Délai non dépassé
|
||||
LocalDateTime dateCreationRecente = maintenant.minusHours(1);
|
||||
assertThat(PrioriteAide.CRITIQUE.isDelaiDepasse(dateCreationRecente)).isFalse(); // 1h < 24h
|
||||
|
||||
// Délai dépassé
|
||||
LocalDateTime dateCreationAncienne = maintenant.minusHours(25);
|
||||
assertThat(PrioriteAide.CRITIQUE.isDelaiDepasse(dateCreationAncienne)).isTrue(); // 25h > 24h
|
||||
|
||||
// Test limite exacte
|
||||
LocalDateTime dateCreationLimite = maintenant.minusHours(24);
|
||||
assertThat(PrioriteAide.CRITIQUE.isDelaiDepasse(dateCreationLimite)).isFalse(); // 24h = 24h (pas après)
|
||||
|
||||
// Test avec URGENTE
|
||||
dateCreationAncienne = maintenant.minusHours(73);
|
||||
assertThat(PrioriteAide.URGENTE.isDelaiDepasse(dateCreationAncienne)).isTrue(); // 73h > 72h
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getPourcentageTempsEcoule - toutes les branches")
|
||||
void testGetPourcentageTempsEcoule() {
|
||||
LocalDateTime maintenant = LocalDateTime.now();
|
||||
|
||||
// 0% écoulé (juste créé)
|
||||
LocalDateTime dateCreation = maintenant;
|
||||
double pourcentage = PrioriteAide.CRITIQUE.getPourcentageTempsEcoule(dateCreation);
|
||||
assertThat(pourcentage).isCloseTo(0.0, within(1.0));
|
||||
|
||||
// 50% écoulé (12h sur 24h)
|
||||
dateCreation = maintenant.minusHours(12);
|
||||
pourcentage = PrioriteAide.CRITIQUE.getPourcentageTempsEcoule(dateCreation);
|
||||
assertThat(pourcentage).isCloseTo(50.0, within(1.0));
|
||||
|
||||
// 100% écoulé (24h sur 24h)
|
||||
dateCreation = maintenant.minusHours(24);
|
||||
pourcentage = PrioriteAide.CRITIQUE.getPourcentageTempsEcoule(dateCreation);
|
||||
assertThat(pourcentage).isCloseTo(100.0, within(1.0));
|
||||
|
||||
// Plus de 100% écoulé (30h sur 24h) - plafonné à 100%
|
||||
dateCreation = maintenant.minusHours(30);
|
||||
pourcentage = PrioriteAide.CRITIQUE.getPourcentageTempsEcoule(dateCreation);
|
||||
assertThat(pourcentage).isEqualTo(100.0);
|
||||
|
||||
// Test cas limite: date future (dureeEcoulee négative)
|
||||
dateCreation = maintenant.plusHours(1);
|
||||
pourcentage = PrioriteAide.CRITIQUE.getPourcentageTempsEcoule(dateCreation);
|
||||
// dateCreation = maintenant + 1h, dateLimite = dateCreation + 24h = maintenant + 25h
|
||||
// dureeTotal = 24h = 1440 min (positif), dureeEcoulee = -1h = -60 min (négatif)
|
||||
// Calcul: (-60 * 100) / 1440 = -4.166..., puis Math.min(100, -4.166) = -4.166
|
||||
assertThat(pourcentage).isCloseTo(-4.166666666666667, within(0.001));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getMessageAlerte - toutes les branches")
|
||||
void testGetMessageAlerte() {
|
||||
LocalDateTime maintenant = LocalDateTime.now();
|
||||
|
||||
// Aucun message (< 60%)
|
||||
LocalDateTime dateCreation = maintenant.minusHours(10); // ~42% pour CRITIQUE
|
||||
String message = PrioriteAide.CRITIQUE.getMessageAlerte(dateCreation);
|
||||
assertThat(message).isNull();
|
||||
|
||||
// Plus de la moitié du délai écoulé (60% <= x < 80%)
|
||||
dateCreation = maintenant.minusHours(15); // ~62% pour CRITIQUE
|
||||
message = PrioriteAide.CRITIQUE.getMessageAlerte(dateCreation);
|
||||
assertThat(message).isEqualTo("Plus de la moitié du délai écoulé");
|
||||
|
||||
// Délai bientôt dépassé (80% <= x < 100%)
|
||||
dateCreation = maintenant.minusHours(20); // ~83% pour CRITIQUE
|
||||
message = PrioriteAide.CRITIQUE.getMessageAlerte(dateCreation);
|
||||
assertThat(message).isEqualTo("Délai de traitement bientôt dépassé");
|
||||
|
||||
// Délai dépassé (>= 100%)
|
||||
dateCreation = maintenant.minusHours(25); // > 100% pour CRITIQUE
|
||||
message = PrioriteAide.CRITIQUE.getMessageAlerte(dateCreation);
|
||||
assertThat(message).isEqualTo("Délai de traitement dépassé !");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test cohérence globale des données")
|
||||
void testCoherenceGlobale() {
|
||||
for (PrioriteAide priorite : PrioriteAide.values()) {
|
||||
// Tous les champs obligatoires non null
|
||||
assertThat(priorite.getLibelle()).isNotNull().isNotEmpty();
|
||||
assertThat(priorite.getCode()).isNotNull().isNotEmpty();
|
||||
assertThat(priorite.getDescription()).isNotNull().isNotEmpty();
|
||||
assertThat(priorite.getCouleur()).isNotNull().matches("#[0-9A-Fa-f]{6}");
|
||||
assertThat(priorite.getIcone()).isNotNull().isNotEmpty();
|
||||
assertThat(priorite.getNiveau()).isPositive();
|
||||
assertThat(priorite.getDelaiTraitementHeures()).isPositive();
|
||||
|
||||
// Cohérence logique
|
||||
if (priorite.getNiveau() <= 2) {
|
||||
assertThat(priorite.necessiteTraitementImmediat()).isTrue();
|
||||
}
|
||||
|
||||
if (priorite == PrioriteAide.CRITIQUE || priorite == PrioriteAide.URGENTE) {
|
||||
assertThat(priorite.isUrgente()).isTrue();
|
||||
}
|
||||
|
||||
// Score de priorité cohérent (plus bas = plus prioritaire)
|
||||
double score = priorite.getScorePriorite();
|
||||
assertThat(score).isPositive();
|
||||
|
||||
// Les méthodes temporelles fonctionnent
|
||||
LocalDateTime maintenant = LocalDateTime.now();
|
||||
assertThat(priorite.getDateLimiteTraitement()).isAfter(maintenant);
|
||||
assertThat(priorite.getPourcentageTempsEcoule(maintenant.minusHours(1))).isBetween(0.0, 100.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,663 @@
|
||||
package dev.lions.unionflow.server.api.enums.solidarite;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires EXHAUSTIFS pour StatutAide - Couverture 100%
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@DisplayName("Tests EXHAUSTIFS StatutAide")
|
||||
class StatutAideTest {
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des valeurs enum et constructeur")
|
||||
class TestsValeursEnum {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test toutes les valeurs enum avec propriétés exactes")
|
||||
void testToutesValeursExactes() {
|
||||
// STATUTS INITIAUX
|
||||
assertThat(StatutAide.BROUILLON.getLibelle()).isEqualTo("Brouillon");
|
||||
assertThat(StatutAide.BROUILLON.getCode()).isEqualTo("draft");
|
||||
assertThat(StatutAide.BROUILLON.getDescription()).isEqualTo("La demande est en cours de rédaction");
|
||||
assertThat(StatutAide.BROUILLON.getCouleur()).isEqualTo("#9E9E9E");
|
||||
assertThat(StatutAide.BROUILLON.getIcone()).isEqualTo("edit");
|
||||
assertThat(StatutAide.BROUILLON.isEstFinal()).isFalse();
|
||||
assertThat(StatutAide.BROUILLON.isEstEchec()).isFalse();
|
||||
|
||||
assertThat(StatutAide.SOUMISE.getLibelle()).isEqualTo("Soumise");
|
||||
assertThat(StatutAide.SOUMISE.getCode()).isEqualTo("submitted");
|
||||
assertThat(StatutAide.SOUMISE.getDescription()).isEqualTo("La demande a été soumise et attend validation");
|
||||
assertThat(StatutAide.SOUMISE.getCouleur()).isEqualTo("#FF9800");
|
||||
assertThat(StatutAide.SOUMISE.getIcone()).isEqualTo("send");
|
||||
assertThat(StatutAide.SOUMISE.isEstFinal()).isFalse();
|
||||
assertThat(StatutAide.SOUMISE.isEstEchec()).isFalse();
|
||||
|
||||
// STATUTS D'ÉVALUATION
|
||||
assertThat(StatutAide.EN_ATTENTE.getLibelle()).isEqualTo("En attente");
|
||||
assertThat(StatutAide.EN_ATTENTE.getCode()).isEqualTo("pending");
|
||||
assertThat(StatutAide.EN_ATTENTE.getDescription()).isEqualTo("La demande est en attente d'évaluation");
|
||||
assertThat(StatutAide.EN_ATTENTE.getCouleur()).isEqualTo("#2196F3");
|
||||
assertThat(StatutAide.EN_ATTENTE.getIcone()).isEqualTo("hourglass_empty");
|
||||
assertThat(StatutAide.EN_ATTENTE.isEstFinal()).isFalse();
|
||||
assertThat(StatutAide.EN_ATTENTE.isEstEchec()).isFalse();
|
||||
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.getLibelle()).isEqualTo("En cours d'évaluation");
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.getCode()).isEqualTo("under_review");
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.getDescription()).isEqualTo("La demande est en cours d'évaluation");
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.getCouleur()).isEqualTo("#FF9800");
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.getIcone()).isEqualTo("rate_review");
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.isEstFinal()).isFalse();
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.isEstEchec()).isFalse();
|
||||
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.getLibelle()).isEqualTo("Informations requises");
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.getCode()).isEqualTo("info_required");
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.getDescription()).isEqualTo("Des informations complémentaires sont requises");
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.getCouleur()).isEqualTo("#FF5722");
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.getIcone()).isEqualTo("info");
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.isEstFinal()).isFalse();
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.isEstEchec()).isFalse();
|
||||
|
||||
// STATUTS DE DÉCISION
|
||||
assertThat(StatutAide.APPROUVEE.getLibelle()).isEqualTo("Approuvée");
|
||||
assertThat(StatutAide.APPROUVEE.getCode()).isEqualTo("approved");
|
||||
assertThat(StatutAide.APPROUVEE.getDescription()).isEqualTo("La demande a été approuvée");
|
||||
assertThat(StatutAide.APPROUVEE.getCouleur()).isEqualTo("#4CAF50");
|
||||
assertThat(StatutAide.APPROUVEE.getIcone()).isEqualTo("check_circle");
|
||||
assertThat(StatutAide.APPROUVEE.isEstFinal()).isTrue();
|
||||
assertThat(StatutAide.APPROUVEE.isEstEchec()).isFalse();
|
||||
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.getLibelle()).isEqualTo("Approuvée partiellement");
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.getCode()).isEqualTo("partially_approved");
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.getDescription()).isEqualTo("La demande a été approuvée partiellement");
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.getCouleur()).isEqualTo("#8BC34A");
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.getIcone()).isEqualTo("check_circle_outline");
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.isEstFinal()).isTrue();
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.isEstEchec()).isFalse();
|
||||
|
||||
assertThat(StatutAide.REJETEE.getLibelle()).isEqualTo("Rejetée");
|
||||
assertThat(StatutAide.REJETEE.getCode()).isEqualTo("rejected");
|
||||
assertThat(StatutAide.REJETEE.getDescription()).isEqualTo("La demande a été rejetée");
|
||||
assertThat(StatutAide.REJETEE.getCouleur()).isEqualTo("#F44336");
|
||||
assertThat(StatutAide.REJETEE.getIcone()).isEqualTo("cancel");
|
||||
assertThat(StatutAide.REJETEE.isEstFinal()).isTrue();
|
||||
assertThat(StatutAide.REJETEE.isEstEchec()).isTrue();
|
||||
|
||||
// STATUTS DE TRAITEMENT
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.getLibelle()).isEqualTo("En cours de traitement");
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.getCode()).isEqualTo("processing");
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.getDescription()).isEqualTo("La demande approuvée est en cours de traitement");
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.getCouleur()).isEqualTo("#9C27B0");
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.getIcone()).isEqualTo("settings");
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.isEstFinal()).isFalse();
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.isEstEchec()).isFalse();
|
||||
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.getLibelle()).isEqualTo("En cours de versement");
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.getCode()).isEqualTo("payment_processing");
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.getDescription()).isEqualTo("Le versement est en cours");
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.getCouleur()).isEqualTo("#3F51B5");
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.getIcone()).isEqualTo("payment");
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.isEstFinal()).isFalse();
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.isEstEchec()).isFalse();
|
||||
|
||||
// STATUTS FINAUX
|
||||
assertThat(StatutAide.VERSEE.getLibelle()).isEqualTo("Versée");
|
||||
assertThat(StatutAide.VERSEE.getCode()).isEqualTo("paid");
|
||||
assertThat(StatutAide.VERSEE.getDescription()).isEqualTo("L'aide a été versée avec succès");
|
||||
assertThat(StatutAide.VERSEE.getCouleur()).isEqualTo("#4CAF50");
|
||||
assertThat(StatutAide.VERSEE.getIcone()).isEqualTo("paid");
|
||||
assertThat(StatutAide.VERSEE.isEstFinal()).isTrue();
|
||||
assertThat(StatutAide.VERSEE.isEstEchec()).isFalse();
|
||||
|
||||
assertThat(StatutAide.LIVREE.getLibelle()).isEqualTo("Livrée");
|
||||
assertThat(StatutAide.LIVREE.getCode()).isEqualTo("delivered");
|
||||
assertThat(StatutAide.LIVREE.getDescription()).isEqualTo("L'aide matérielle a été livrée");
|
||||
assertThat(StatutAide.LIVREE.getCouleur()).isEqualTo("#4CAF50");
|
||||
assertThat(StatutAide.LIVREE.getIcone()).isEqualTo("local_shipping");
|
||||
assertThat(StatutAide.LIVREE.isEstFinal()).isTrue();
|
||||
assertThat(StatutAide.LIVREE.isEstEchec()).isFalse();
|
||||
|
||||
assertThat(StatutAide.TERMINEE.getLibelle()).isEqualTo("Terminée");
|
||||
assertThat(StatutAide.TERMINEE.getCode()).isEqualTo("completed");
|
||||
assertThat(StatutAide.TERMINEE.getDescription()).isEqualTo("L'aide a été fournie avec succès");
|
||||
assertThat(StatutAide.TERMINEE.getCouleur()).isEqualTo("#4CAF50");
|
||||
assertThat(StatutAide.TERMINEE.getIcone()).isEqualTo("done_all");
|
||||
assertThat(StatutAide.TERMINEE.isEstFinal()).isTrue();
|
||||
assertThat(StatutAide.TERMINEE.isEstEchec()).isFalse();
|
||||
|
||||
// STATUTS D'EXCEPTION
|
||||
assertThat(StatutAide.ANNULEE.getLibelle()).isEqualTo("Annulée");
|
||||
assertThat(StatutAide.ANNULEE.getCode()).isEqualTo("cancelled");
|
||||
assertThat(StatutAide.ANNULEE.getDescription()).isEqualTo("La demande a été annulée");
|
||||
assertThat(StatutAide.ANNULEE.getCouleur()).isEqualTo("#9E9E9E");
|
||||
assertThat(StatutAide.ANNULEE.getIcone()).isEqualTo("cancel");
|
||||
assertThat(StatutAide.ANNULEE.isEstFinal()).isTrue();
|
||||
assertThat(StatutAide.ANNULEE.isEstEchec()).isTrue();
|
||||
|
||||
assertThat(StatutAide.SUSPENDUE.getLibelle()).isEqualTo("Suspendue");
|
||||
assertThat(StatutAide.SUSPENDUE.getCode()).isEqualTo("suspended");
|
||||
assertThat(StatutAide.SUSPENDUE.getDescription()).isEqualTo("La demande a été suspendue temporairement");
|
||||
assertThat(StatutAide.SUSPENDUE.getCouleur()).isEqualTo("#FF5722");
|
||||
assertThat(StatutAide.SUSPENDUE.getIcone()).isEqualTo("pause_circle");
|
||||
assertThat(StatutAide.SUSPENDUE.isEstFinal()).isFalse();
|
||||
assertThat(StatutAide.SUSPENDUE.isEstEchec()).isFalse();
|
||||
|
||||
assertThat(StatutAide.EXPIREE.getLibelle()).isEqualTo("Expirée");
|
||||
assertThat(StatutAide.EXPIREE.getCode()).isEqualTo("expired");
|
||||
assertThat(StatutAide.EXPIREE.getDescription()).isEqualTo("La demande a expiré");
|
||||
assertThat(StatutAide.EXPIREE.getCouleur()).isEqualTo("#795548");
|
||||
assertThat(StatutAide.EXPIREE.getIcone()).isEqualTo("schedule");
|
||||
assertThat(StatutAide.EXPIREE.isEstFinal()).isTrue();
|
||||
assertThat(StatutAide.EXPIREE.isEstEchec()).isTrue();
|
||||
|
||||
// STATUTS DE SUIVI
|
||||
assertThat(StatutAide.EN_SUIVI.getLibelle()).isEqualTo("En suivi");
|
||||
assertThat(StatutAide.EN_SUIVI.getCode()).isEqualTo("follow_up");
|
||||
assertThat(StatutAide.EN_SUIVI.getDescription()).isEqualTo("L'aide fait l'objet d'un suivi");
|
||||
assertThat(StatutAide.EN_SUIVI.getCouleur()).isEqualTo("#607D8B");
|
||||
assertThat(StatutAide.EN_SUIVI.getIcone()).isEqualTo("track_changes");
|
||||
assertThat(StatutAide.EN_SUIVI.isEstFinal()).isFalse();
|
||||
assertThat(StatutAide.EN_SUIVI.isEstEchec()).isFalse();
|
||||
|
||||
assertThat(StatutAide.CLOTUREE.getLibelle()).isEqualTo("Clôturée");
|
||||
assertThat(StatutAide.CLOTUREE.getCode()).isEqualTo("closed");
|
||||
assertThat(StatutAide.CLOTUREE.getDescription()).isEqualTo("Le dossier d'aide est clôturé");
|
||||
assertThat(StatutAide.CLOTUREE.getCouleur()).isEqualTo("#9E9E9E");
|
||||
assertThat(StatutAide.CLOTUREE.getIcone()).isEqualTo("folder");
|
||||
assertThat(StatutAide.CLOTUREE.isEstFinal()).isTrue();
|
||||
assertThat(StatutAide.CLOTUREE.isEstEchec()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test valueOf et values")
|
||||
void testValueOfEtValues() {
|
||||
StatutAide[] values = StatutAide.values();
|
||||
assertThat(values).hasSize(18);
|
||||
assertThat(values).containsExactly(
|
||||
StatutAide.BROUILLON,
|
||||
StatutAide.SOUMISE,
|
||||
StatutAide.EN_ATTENTE,
|
||||
StatutAide.EN_COURS_EVALUATION,
|
||||
StatutAide.INFORMATIONS_REQUISES,
|
||||
StatutAide.APPROUVEE,
|
||||
StatutAide.APPROUVEE_PARTIELLEMENT,
|
||||
StatutAide.REJETEE,
|
||||
StatutAide.EN_COURS_TRAITEMENT,
|
||||
StatutAide.EN_COURS_VERSEMENT,
|
||||
StatutAide.VERSEE,
|
||||
StatutAide.LIVREE,
|
||||
StatutAide.TERMINEE,
|
||||
StatutAide.ANNULEE,
|
||||
StatutAide.SUSPENDUE,
|
||||
StatutAide.EXPIREE,
|
||||
StatutAide.EN_SUIVI,
|
||||
StatutAide.CLOTUREE);
|
||||
|
||||
// Test valueOf pour quelques valeurs
|
||||
assertThat(StatutAide.valueOf("BROUILLON")).isEqualTo(StatutAide.BROUILLON);
|
||||
assertThat(StatutAide.valueOf("EN_COURS_EVALUATION")).isEqualTo(StatutAide.EN_COURS_EVALUATION);
|
||||
assertThat(StatutAide.valueOf("APPROUVEE_PARTIELLEMENT")).isEqualTo(StatutAide.APPROUVEE_PARTIELLEMENT);
|
||||
|
||||
assertThatThrownBy(() -> StatutAide.valueOf("INEXISTANT"))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test ordinal, name et toString")
|
||||
void testOrdinalNameToString() {
|
||||
assertThat(StatutAide.BROUILLON.ordinal()).isEqualTo(0);
|
||||
assertThat(StatutAide.SOUMISE.ordinal()).isEqualTo(1);
|
||||
assertThat(StatutAide.CLOTUREE.ordinal()).isEqualTo(17);
|
||||
|
||||
assertThat(StatutAide.BROUILLON.name()).isEqualTo("BROUILLON");
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.name()).isEqualTo("EN_COURS_EVALUATION");
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.name()).isEqualTo("APPROUVEE_PARTIELLEMENT");
|
||||
|
||||
assertThat(StatutAide.BROUILLON.toString()).isEqualTo("BROUILLON");
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.toString()).isEqualTo("EN_COURS_EVALUATION");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes métier")
|
||||
class TestsMethodesMetier {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isSucces - toutes les branches")
|
||||
void testIsSucces() {
|
||||
// Statuts de succès (this == VERSEE || this == LIVREE || this == TERMINEE)
|
||||
assertThat(StatutAide.VERSEE.isSucces()).isTrue();
|
||||
assertThat(StatutAide.LIVREE.isSucces()).isTrue();
|
||||
assertThat(StatutAide.TERMINEE.isSucces()).isTrue();
|
||||
|
||||
// Tous les autres statuts ne sont pas des succès
|
||||
assertThat(StatutAide.BROUILLON.isSucces()).isFalse();
|
||||
assertThat(StatutAide.SOUMISE.isSucces()).isFalse();
|
||||
assertThat(StatutAide.EN_ATTENTE.isSucces()).isFalse();
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.isSucces()).isFalse();
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.isSucces()).isFalse();
|
||||
assertThat(StatutAide.APPROUVEE.isSucces()).isFalse();
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.isSucces()).isFalse();
|
||||
assertThat(StatutAide.REJETEE.isSucces()).isFalse();
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.isSucces()).isFalse();
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.isSucces()).isFalse();
|
||||
assertThat(StatutAide.ANNULEE.isSucces()).isFalse();
|
||||
assertThat(StatutAide.SUSPENDUE.isSucces()).isFalse();
|
||||
assertThat(StatutAide.EXPIREE.isSucces()).isFalse();
|
||||
assertThat(StatutAide.EN_SUIVI.isSucces()).isFalse();
|
||||
assertThat(StatutAide.CLOTUREE.isSucces()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isEnCours - toutes les branches")
|
||||
void testIsEnCours() {
|
||||
// Statuts en cours (this == EN_COURS_EVALUATION || this == EN_COURS_TRAITEMENT || this == EN_COURS_VERSEMENT)
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.isEnCours()).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.isEnCours()).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.isEnCours()).isTrue();
|
||||
|
||||
// Tous les autres statuts ne sont pas en cours
|
||||
assertThat(StatutAide.BROUILLON.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.SOUMISE.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.EN_ATTENTE.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.APPROUVEE.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.REJETEE.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.VERSEE.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.LIVREE.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.TERMINEE.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.ANNULEE.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.SUSPENDUE.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.EXPIREE.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.EN_SUIVI.isEnCours()).isFalse();
|
||||
assertThat(StatutAide.CLOTUREE.isEnCours()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test permetModification - toutes les branches")
|
||||
void testPermetModification() {
|
||||
// Statuts qui permettent modification (this == BROUILLON || this == INFORMATIONS_REQUISES)
|
||||
assertThat(StatutAide.BROUILLON.permetModification()).isTrue();
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.permetModification()).isTrue();
|
||||
|
||||
// Tous les autres statuts ne permettent pas la modification
|
||||
assertThat(StatutAide.SOUMISE.permetModification()).isFalse();
|
||||
assertThat(StatutAide.EN_ATTENTE.permetModification()).isFalse();
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.permetModification()).isFalse();
|
||||
assertThat(StatutAide.APPROUVEE.permetModification()).isFalse();
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.permetModification()).isFalse();
|
||||
assertThat(StatutAide.REJETEE.permetModification()).isFalse();
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.permetModification()).isFalse();
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.permetModification()).isFalse();
|
||||
assertThat(StatutAide.VERSEE.permetModification()).isFalse();
|
||||
assertThat(StatutAide.LIVREE.permetModification()).isFalse();
|
||||
assertThat(StatutAide.TERMINEE.permetModification()).isFalse();
|
||||
assertThat(StatutAide.ANNULEE.permetModification()).isFalse();
|
||||
assertThat(StatutAide.SUSPENDUE.permetModification()).isFalse();
|
||||
assertThat(StatutAide.EXPIREE.permetModification()).isFalse();
|
||||
assertThat(StatutAide.EN_SUIVI.permetModification()).isFalse();
|
||||
assertThat(StatutAide.CLOTUREE.permetModification()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test permetAnnulation - toutes les branches")
|
||||
void testPermetAnnulation() {
|
||||
// Permet annulation si (!estFinal && this != ANNULEE)
|
||||
|
||||
// Statuts non finaux et non annulés = permettent annulation
|
||||
assertThat(StatutAide.BROUILLON.permetAnnulation()).isTrue();
|
||||
assertThat(StatutAide.SOUMISE.permetAnnulation()).isTrue();
|
||||
assertThat(StatutAide.EN_ATTENTE.permetAnnulation()).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.permetAnnulation()).isTrue();
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.permetAnnulation()).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.permetAnnulation()).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.permetAnnulation()).isTrue();
|
||||
assertThat(StatutAide.SUSPENDUE.permetAnnulation()).isTrue();
|
||||
assertThat(StatutAide.EN_SUIVI.permetAnnulation()).isTrue();
|
||||
|
||||
// Statuts finaux = ne permettent pas annulation
|
||||
assertThat(StatutAide.APPROUVEE.permetAnnulation()).isFalse();
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.permetAnnulation()).isFalse();
|
||||
assertThat(StatutAide.REJETEE.permetAnnulation()).isFalse();
|
||||
assertThat(StatutAide.VERSEE.permetAnnulation()).isFalse();
|
||||
assertThat(StatutAide.LIVREE.permetAnnulation()).isFalse();
|
||||
assertThat(StatutAide.TERMINEE.permetAnnulation()).isFalse();
|
||||
assertThat(StatutAide.EXPIREE.permetAnnulation()).isFalse();
|
||||
assertThat(StatutAide.CLOTUREE.permetAnnulation()).isFalse();
|
||||
|
||||
// ANNULEE = ne permet pas annulation (déjà annulé)
|
||||
assertThat(StatutAide.ANNULEE.permetAnnulation()).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes statiques")
|
||||
class TestsMethodesStatiques {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getStatutsFinaux")
|
||||
void testGetStatutsFinaux() {
|
||||
List<StatutAide> finaux = StatutAide.getStatutsFinaux();
|
||||
|
||||
// Vérifier que tous les statuts finaux sont inclus
|
||||
assertThat(finaux).contains(
|
||||
StatutAide.APPROUVEE,
|
||||
StatutAide.APPROUVEE_PARTIELLEMENT,
|
||||
StatutAide.REJETEE,
|
||||
StatutAide.VERSEE,
|
||||
StatutAide.LIVREE,
|
||||
StatutAide.TERMINEE,
|
||||
StatutAide.ANNULEE,
|
||||
StatutAide.EXPIREE,
|
||||
StatutAide.CLOTUREE);
|
||||
|
||||
// Vérifier qu'aucun statut non final n'est inclus
|
||||
assertThat(finaux).doesNotContain(
|
||||
StatutAide.BROUILLON,
|
||||
StatutAide.SOUMISE,
|
||||
StatutAide.EN_ATTENTE,
|
||||
StatutAide.EN_COURS_EVALUATION,
|
||||
StatutAide.INFORMATIONS_REQUISES,
|
||||
StatutAide.EN_COURS_TRAITEMENT,
|
||||
StatutAide.EN_COURS_VERSEMENT,
|
||||
StatutAide.SUSPENDUE,
|
||||
StatutAide.EN_SUIVI);
|
||||
|
||||
// Vérifier que tous les statuts retournés sont bien finaux
|
||||
finaux.forEach(statut -> assertThat(statut.isEstFinal()).isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getStatutsEchec")
|
||||
void testGetStatutsEchec() {
|
||||
List<StatutAide> echecs = StatutAide.getStatutsEchec();
|
||||
|
||||
// Vérifier que tous les statuts d'échec sont inclus
|
||||
assertThat(echecs).contains(
|
||||
StatutAide.REJETEE,
|
||||
StatutAide.ANNULEE,
|
||||
StatutAide.EXPIREE);
|
||||
|
||||
// Vérifier qu'aucun statut non échec n'est inclus
|
||||
assertThat(echecs).doesNotContain(
|
||||
StatutAide.BROUILLON,
|
||||
StatutAide.SOUMISE,
|
||||
StatutAide.EN_ATTENTE,
|
||||
StatutAide.EN_COURS_EVALUATION,
|
||||
StatutAide.INFORMATIONS_REQUISES,
|
||||
StatutAide.APPROUVEE,
|
||||
StatutAide.APPROUVEE_PARTIELLEMENT,
|
||||
StatutAide.EN_COURS_TRAITEMENT,
|
||||
StatutAide.EN_COURS_VERSEMENT,
|
||||
StatutAide.VERSEE,
|
||||
StatutAide.LIVREE,
|
||||
StatutAide.TERMINEE,
|
||||
StatutAide.SUSPENDUE,
|
||||
StatutAide.EN_SUIVI,
|
||||
StatutAide.CLOTUREE);
|
||||
|
||||
// Vérifier que tous les statuts retournés sont bien des échecs
|
||||
echecs.forEach(statut -> assertThat(statut.isEstEchec()).isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getStatutsSucces")
|
||||
void testGetStatutsSucces() {
|
||||
List<StatutAide> succes = StatutAide.getStatutsSucces();
|
||||
|
||||
// Vérifier que tous les statuts de succès sont inclus
|
||||
assertThat(succes).contains(
|
||||
StatutAide.VERSEE,
|
||||
StatutAide.LIVREE,
|
||||
StatutAide.TERMINEE);
|
||||
|
||||
// Vérifier qu'aucun statut non succès n'est inclus
|
||||
assertThat(succes).doesNotContain(
|
||||
StatutAide.BROUILLON,
|
||||
StatutAide.SOUMISE,
|
||||
StatutAide.EN_ATTENTE,
|
||||
StatutAide.EN_COURS_EVALUATION,
|
||||
StatutAide.INFORMATIONS_REQUISES,
|
||||
StatutAide.APPROUVEE,
|
||||
StatutAide.APPROUVEE_PARTIELLEMENT,
|
||||
StatutAide.REJETEE,
|
||||
StatutAide.EN_COURS_TRAITEMENT,
|
||||
StatutAide.EN_COURS_VERSEMENT,
|
||||
StatutAide.ANNULEE,
|
||||
StatutAide.SUSPENDUE,
|
||||
StatutAide.EXPIREE,
|
||||
StatutAide.EN_SUIVI,
|
||||
StatutAide.CLOTUREE);
|
||||
|
||||
// Vérifier que tous les statuts retournés sont bien des succès
|
||||
succes.forEach(statut -> assertThat(statut.isSucces()).isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getStatutsEnCours")
|
||||
void testGetStatutsEnCours() {
|
||||
List<StatutAide> enCours = StatutAide.getStatutsEnCours();
|
||||
|
||||
// Vérifier que tous les statuts en cours sont inclus
|
||||
assertThat(enCours).contains(
|
||||
StatutAide.EN_COURS_EVALUATION,
|
||||
StatutAide.EN_COURS_TRAITEMENT,
|
||||
StatutAide.EN_COURS_VERSEMENT);
|
||||
|
||||
// Vérifier qu'aucun statut non en cours n'est inclus
|
||||
assertThat(enCours).doesNotContain(
|
||||
StatutAide.BROUILLON,
|
||||
StatutAide.SOUMISE,
|
||||
StatutAide.EN_ATTENTE,
|
||||
StatutAide.INFORMATIONS_REQUISES,
|
||||
StatutAide.APPROUVEE,
|
||||
StatutAide.APPROUVEE_PARTIELLEMENT,
|
||||
StatutAide.REJETEE,
|
||||
StatutAide.VERSEE,
|
||||
StatutAide.LIVREE,
|
||||
StatutAide.TERMINEE,
|
||||
StatutAide.ANNULEE,
|
||||
StatutAide.SUSPENDUE,
|
||||
StatutAide.EXPIREE,
|
||||
StatutAide.EN_SUIVI,
|
||||
StatutAide.CLOTUREE);
|
||||
|
||||
// Vérifier que tous les statuts retournés sont bien en cours
|
||||
enCours.forEach(statut -> assertThat(statut.isEnCours()).isTrue());
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes complexes")
|
||||
class TestsMethodesComplexes {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test peutTransitionnerVers - toutes les branches du switch")
|
||||
void testPeutTransitionnerVers() {
|
||||
// Règles générales
|
||||
// this == nouveauStatut -> false
|
||||
assertThat(StatutAide.BROUILLON.peutTransitionnerVers(StatutAide.BROUILLON)).isFalse();
|
||||
assertThat(StatutAide.EN_ATTENTE.peutTransitionnerVers(StatutAide.EN_ATTENTE)).isFalse();
|
||||
|
||||
// estFinal && nouveauStatut != EN_SUIVI -> false
|
||||
assertThat(StatutAide.TERMINEE.peutTransitionnerVers(StatutAide.BROUILLON)).isFalse();
|
||||
assertThat(StatutAide.VERSEE.peutTransitionnerVers(StatutAide.EN_ATTENTE)).isFalse();
|
||||
assertThat(StatutAide.REJETEE.peutTransitionnerVers(StatutAide.APPROUVEE)).isFalse();
|
||||
|
||||
// estFinal && nouveauStatut == EN_SUIVI -> mais default false dans switch
|
||||
// Les statuts finaux ne sont pas dans le switch, donc default -> false
|
||||
assertThat(StatutAide.TERMINEE.peutTransitionnerVers(StatutAide.EN_SUIVI)).isFalse();
|
||||
assertThat(StatutAide.VERSEE.peutTransitionnerVers(StatutAide.EN_SUIVI)).isFalse();
|
||||
assertThat(StatutAide.REJETEE.peutTransitionnerVers(StatutAide.EN_SUIVI)).isFalse();
|
||||
|
||||
// BROUILLON -> SOUMISE || ANNULEE
|
||||
assertThat(StatutAide.BROUILLON.peutTransitionnerVers(StatutAide.SOUMISE)).isTrue();
|
||||
assertThat(StatutAide.BROUILLON.peutTransitionnerVers(StatutAide.ANNULEE)).isTrue();
|
||||
assertThat(StatutAide.BROUILLON.peutTransitionnerVers(StatutAide.EN_ATTENTE)).isFalse();
|
||||
assertThat(StatutAide.BROUILLON.peutTransitionnerVers(StatutAide.APPROUVEE)).isFalse();
|
||||
|
||||
// SOUMISE -> EN_ATTENTE || ANNULEE
|
||||
assertThat(StatutAide.SOUMISE.peutTransitionnerVers(StatutAide.EN_ATTENTE)).isTrue();
|
||||
assertThat(StatutAide.SOUMISE.peutTransitionnerVers(StatutAide.ANNULEE)).isTrue();
|
||||
assertThat(StatutAide.SOUMISE.peutTransitionnerVers(StatutAide.BROUILLON)).isFalse();
|
||||
assertThat(StatutAide.SOUMISE.peutTransitionnerVers(StatutAide.APPROUVEE)).isFalse();
|
||||
|
||||
// EN_ATTENTE -> EN_COURS_EVALUATION || ANNULEE
|
||||
assertThat(StatutAide.EN_ATTENTE.peutTransitionnerVers(StatutAide.EN_COURS_EVALUATION)).isTrue();
|
||||
assertThat(StatutAide.EN_ATTENTE.peutTransitionnerVers(StatutAide.ANNULEE)).isTrue();
|
||||
assertThat(StatutAide.EN_ATTENTE.peutTransitionnerVers(StatutAide.SOUMISE)).isFalse();
|
||||
assertThat(StatutAide.EN_ATTENTE.peutTransitionnerVers(StatutAide.APPROUVEE)).isFalse();
|
||||
|
||||
// EN_COURS_EVALUATION -> APPROUVEE || APPROUVEE_PARTIELLEMENT || REJETEE || INFORMATIONS_REQUISES || SUSPENDUE
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.peutTransitionnerVers(StatutAide.APPROUVEE)).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.peutTransitionnerVers(StatutAide.APPROUVEE_PARTIELLEMENT)).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.peutTransitionnerVers(StatutAide.REJETEE)).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.peutTransitionnerVers(StatutAide.INFORMATIONS_REQUISES)).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.peutTransitionnerVers(StatutAide.SUSPENDUE)).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.peutTransitionnerVers(StatutAide.EN_ATTENTE)).isFalse();
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.peutTransitionnerVers(StatutAide.TERMINEE)).isFalse();
|
||||
|
||||
// INFORMATIONS_REQUISES -> EN_COURS_EVALUATION || ANNULEE
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.peutTransitionnerVers(StatutAide.EN_COURS_EVALUATION)).isTrue();
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.peutTransitionnerVers(StatutAide.ANNULEE)).isTrue();
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.peutTransitionnerVers(StatutAide.APPROUVEE)).isFalse();
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.peutTransitionnerVers(StatutAide.BROUILLON)).isFalse();
|
||||
|
||||
// APPROUVEE, APPROUVEE_PARTIELLEMENT sont estFinal=true, donc condition estFinal bloque
|
||||
// Même si le switch permet ces transitions, la condition estFinal prend le dessus
|
||||
assertThat(StatutAide.APPROUVEE.peutTransitionnerVers(StatutAide.EN_COURS_TRAITEMENT)).isFalse();
|
||||
assertThat(StatutAide.APPROUVEE.peutTransitionnerVers(StatutAide.SUSPENDUE)).isFalse();
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.peutTransitionnerVers(StatutAide.EN_COURS_TRAITEMENT)).isFalse();
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.peutTransitionnerVers(StatutAide.SUSPENDUE)).isFalse();
|
||||
assertThat(StatutAide.APPROUVEE.peutTransitionnerVers(StatutAide.TERMINEE)).isFalse();
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.peutTransitionnerVers(StatutAide.REJETEE)).isFalse();
|
||||
|
||||
// EN_COURS_TRAITEMENT -> EN_COURS_VERSEMENT || LIVREE || TERMINEE || SUSPENDUE
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.peutTransitionnerVers(StatutAide.EN_COURS_VERSEMENT)).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.peutTransitionnerVers(StatutAide.LIVREE)).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.peutTransitionnerVers(StatutAide.TERMINEE)).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.peutTransitionnerVers(StatutAide.SUSPENDUE)).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.peutTransitionnerVers(StatutAide.APPROUVEE)).isFalse();
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.peutTransitionnerVers(StatutAide.REJETEE)).isFalse();
|
||||
|
||||
// EN_COURS_VERSEMENT -> VERSEE || SUSPENDUE
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.peutTransitionnerVers(StatutAide.VERSEE)).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.peutTransitionnerVers(StatutAide.SUSPENDUE)).isTrue();
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.peutTransitionnerVers(StatutAide.TERMINEE)).isFalse();
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.peutTransitionnerVers(StatutAide.LIVREE)).isFalse();
|
||||
|
||||
// SUSPENDUE -> EN_COURS_EVALUATION || ANNULEE
|
||||
assertThat(StatutAide.SUSPENDUE.peutTransitionnerVers(StatutAide.EN_COURS_EVALUATION)).isTrue();
|
||||
assertThat(StatutAide.SUSPENDUE.peutTransitionnerVers(StatutAide.ANNULEE)).isTrue();
|
||||
assertThat(StatutAide.SUSPENDUE.peutTransitionnerVers(StatutAide.APPROUVEE)).isFalse();
|
||||
assertThat(StatutAide.SUSPENDUE.peutTransitionnerVers(StatutAide.TERMINEE)).isFalse();
|
||||
|
||||
// default -> false (pour les statuts non couverts par le switch)
|
||||
// EN_SUIVI n'est pas dans le switch, donc default -> false
|
||||
assertThat(StatutAide.EN_SUIVI.peutTransitionnerVers(StatutAide.CLOTUREE)).isFalse();
|
||||
assertThat(StatutAide.EN_SUIVI.peutTransitionnerVers(StatutAide.TERMINEE)).isFalse();
|
||||
|
||||
// Autres statuts finaux (déjà testés avec règle estFinal)
|
||||
assertThat(StatutAide.VERSEE.peutTransitionnerVers(StatutAide.TERMINEE)).isFalse(); // Statut final, sauf EN_SUIVI
|
||||
assertThat(StatutAide.LIVREE.peutTransitionnerVers(StatutAide.VERSEE)).isFalse(); // Statut final, sauf EN_SUIVI
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getNiveauPriorite - toutes les branches du switch")
|
||||
void testGetNiveauPriorite() {
|
||||
// INFORMATIONS_REQUISES -> 1
|
||||
assertThat(StatutAide.INFORMATIONS_REQUISES.getNiveauPriorite()).isEqualTo(1);
|
||||
|
||||
// EN_COURS_EVALUATION, EN_COURS_TRAITEMENT, EN_COURS_VERSEMENT -> 2
|
||||
assertThat(StatutAide.EN_COURS_EVALUATION.getNiveauPriorite()).isEqualTo(2);
|
||||
assertThat(StatutAide.EN_COURS_TRAITEMENT.getNiveauPriorite()).isEqualTo(2);
|
||||
assertThat(StatutAide.EN_COURS_VERSEMENT.getNiveauPriorite()).isEqualTo(2);
|
||||
|
||||
// APPROUVEE, APPROUVEE_PARTIELLEMENT -> 3
|
||||
assertThat(StatutAide.APPROUVEE.getNiveauPriorite()).isEqualTo(3);
|
||||
assertThat(StatutAide.APPROUVEE_PARTIELLEMENT.getNiveauPriorite()).isEqualTo(3);
|
||||
|
||||
// EN_ATTENTE, SOUMISE -> 4
|
||||
assertThat(StatutAide.EN_ATTENTE.getNiveauPriorite()).isEqualTo(4);
|
||||
assertThat(StatutAide.SOUMISE.getNiveauPriorite()).isEqualTo(4);
|
||||
|
||||
// SUSPENDUE -> 5
|
||||
assertThat(StatutAide.SUSPENDUE.getNiveauPriorite()).isEqualTo(5);
|
||||
|
||||
// BROUILLON -> 6
|
||||
assertThat(StatutAide.BROUILLON.getNiveauPriorite()).isEqualTo(6);
|
||||
|
||||
// EN_SUIVI -> 7
|
||||
assertThat(StatutAide.EN_SUIVI.getNiveauPriorite()).isEqualTo(7);
|
||||
|
||||
// default -> 8 (Statuts finaux)
|
||||
assertThat(StatutAide.REJETEE.getNiveauPriorite()).isEqualTo(8);
|
||||
assertThat(StatutAide.VERSEE.getNiveauPriorite()).isEqualTo(8);
|
||||
assertThat(StatutAide.LIVREE.getNiveauPriorite()).isEqualTo(8);
|
||||
assertThat(StatutAide.TERMINEE.getNiveauPriorite()).isEqualTo(8);
|
||||
assertThat(StatutAide.ANNULEE.getNiveauPriorite()).isEqualTo(8);
|
||||
assertThat(StatutAide.EXPIREE.getNiveauPriorite()).isEqualTo(8);
|
||||
assertThat(StatutAide.CLOTUREE.getNiveauPriorite()).isEqualTo(8);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test cohérence globale des données")
|
||||
void testCoherenceGlobale() {
|
||||
for (StatutAide statut : StatutAide.values()) {
|
||||
// Tous les champs obligatoires non null
|
||||
assertThat(statut.getLibelle()).isNotNull().isNotEmpty();
|
||||
assertThat(statut.getCode()).isNotNull().isNotEmpty();
|
||||
assertThat(statut.getDescription()).isNotNull().isNotEmpty();
|
||||
assertThat(statut.getCouleur()).isNotNull().matches("#[0-9A-Fa-f]{6}");
|
||||
assertThat(statut.getIcone()).isNotNull().isNotEmpty();
|
||||
|
||||
// Cohérence logique
|
||||
if (statut.isEstFinal()) {
|
||||
// Les statuts finaux ne permettent pas la modification
|
||||
assertThat(statut.permetModification()).isFalse();
|
||||
// Les statuts finaux ne permettent pas l'annulation (sauf transition vers EN_SUIVI)
|
||||
assertThat(statut.permetAnnulation()).isFalse();
|
||||
}
|
||||
|
||||
if (statut.isEstEchec()) {
|
||||
// Les statuts d'échec ne sont pas des succès
|
||||
assertThat(statut.isSucces()).isFalse();
|
||||
// Les statuts d'échec sont finaux
|
||||
assertThat(statut.isEstFinal()).isTrue();
|
||||
}
|
||||
|
||||
if (statut.isSucces()) {
|
||||
// Les statuts de succès ne sont pas des échecs
|
||||
assertThat(statut.isEstEchec()).isFalse();
|
||||
// Les statuts de succès sont finaux
|
||||
assertThat(statut.isEstFinal()).isTrue();
|
||||
}
|
||||
|
||||
if (statut.isEnCours()) {
|
||||
// Les statuts en cours ne sont pas finaux
|
||||
assertThat(statut.isEstFinal()).isFalse();
|
||||
// Les statuts en cours ne sont ni succès ni échec
|
||||
assertThat(statut.isSucces()).isFalse();
|
||||
assertThat(statut.isEstEchec()).isFalse();
|
||||
}
|
||||
|
||||
// Niveau de priorité cohérent
|
||||
int niveau = statut.getNiveauPriorite();
|
||||
assertThat(niveau).isBetween(1, 8);
|
||||
|
||||
// Transitions cohérentes
|
||||
assertThat(statut.peutTransitionnerVers(statut)).isFalse(); // Pas de transition vers soi-même
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,554 @@
|
||||
package dev.lions.unionflow.server.api.enums.solidarite;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.assertj.core.api.Assertions.within;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires EXHAUSTIFS pour TypeAide - Couverture 100%
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 1.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@DisplayName("Tests EXHAUSTIFS TypeAide")
|
||||
class TypeAideTest {
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des valeurs enum et constructeur")
|
||||
class TestsValeursEnum {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test valueOf et values")
|
||||
void testValueOfEtValues() {
|
||||
TypeAide[] values = TypeAide.values();
|
||||
assertThat(values).hasSize(24);
|
||||
assertThat(values).containsExactly(
|
||||
TypeAide.AIDE_FINANCIERE_URGENTE,
|
||||
TypeAide.PRET_SANS_INTERET,
|
||||
TypeAide.AIDE_COTISATION,
|
||||
TypeAide.AIDE_FRAIS_MEDICAUX,
|
||||
TypeAide.AIDE_FRAIS_SCOLARITE,
|
||||
TypeAide.DON_MATERIEL,
|
||||
TypeAide.PRET_MATERIEL,
|
||||
TypeAide.AIDE_DEMENAGEMENT,
|
||||
TypeAide.AIDE_TRAVAUX,
|
||||
TypeAide.AIDE_RECHERCHE_EMPLOI,
|
||||
TypeAide.FORMATION_PROFESSIONNELLE,
|
||||
TypeAide.CONSEIL_JURIDIQUE,
|
||||
TypeAide.AIDE_CREATION_ENTREPRISE,
|
||||
TypeAide.GARDE_ENFANTS,
|
||||
TypeAide.AIDE_PERSONNES_AGEES,
|
||||
TypeAide.TRANSPORT,
|
||||
TypeAide.AIDE_ADMINISTRATIVE,
|
||||
TypeAide.HEBERGEMENT_URGENCE,
|
||||
TypeAide.AIDE_ALIMENTAIRE,
|
||||
TypeAide.AIDE_VESTIMENTAIRE,
|
||||
TypeAide.SOUTIEN_PSYCHOLOGIQUE,
|
||||
TypeAide.AIDE_NUMERIQUE,
|
||||
TypeAide.TRADUCTION,
|
||||
TypeAide.AUTRE);
|
||||
|
||||
// Test valueOf pour quelques valeurs
|
||||
assertThat(TypeAide.valueOf("AIDE_FINANCIERE_URGENTE")).isEqualTo(TypeAide.AIDE_FINANCIERE_URGENTE);
|
||||
assertThat(TypeAide.valueOf("HEBERGEMENT_URGENCE")).isEqualTo(TypeAide.HEBERGEMENT_URGENCE);
|
||||
assertThat(TypeAide.valueOf("SOUTIEN_PSYCHOLOGIQUE")).isEqualTo(TypeAide.SOUTIEN_PSYCHOLOGIQUE);
|
||||
|
||||
assertThatThrownBy(() -> TypeAide.valueOf("INEXISTANT"))
|
||||
.isInstanceOf(IllegalArgumentException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test ordinal, name et toString")
|
||||
void testOrdinalNameToString() {
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.ordinal()).isEqualTo(0);
|
||||
assertThat(TypeAide.PRET_SANS_INTERET.ordinal()).isEqualTo(1);
|
||||
assertThat(TypeAide.AUTRE.ordinal()).isEqualTo(23);
|
||||
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.name()).isEqualTo("AIDE_FINANCIERE_URGENTE");
|
||||
assertThat(TypeAide.HEBERGEMENT_URGENCE.name()).isEqualTo("HEBERGEMENT_URGENCE");
|
||||
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.toString()).isEqualTo("AIDE_FINANCIERE_URGENTE");
|
||||
assertThat(TypeAide.SOUTIEN_PSYCHOLOGIQUE.toString()).isEqualTo("SOUTIEN_PSYCHOLOGIQUE");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés AIDE_FINANCIERE_URGENTE")
|
||||
void testProprietesAideFinanciereUrgente() {
|
||||
TypeAide type = TypeAide.AIDE_FINANCIERE_URGENTE;
|
||||
assertThat(type.getLibelle()).isEqualTo("Aide financière urgente");
|
||||
assertThat(type.getCategorie()).isEqualTo("financiere");
|
||||
assertThat(type.getPriorite()).isEqualTo("urgent");
|
||||
assertThat(type.getDescription()).isEqualTo("Aide financière pour situation d'urgence");
|
||||
assertThat(type.getIcone()).isEqualTo("emergency_fund");
|
||||
assertThat(type.getCouleur()).isEqualTo("#F44336");
|
||||
assertThat(type.isNecessiteMontant()).isTrue();
|
||||
assertThat(type.isNecessiteValidation()).isTrue();
|
||||
assertThat(type.getMontantMin()).isEqualTo(5000.0);
|
||||
assertThat(type.getMontantMax()).isEqualTo(50000.0);
|
||||
assertThat(type.getDelaiReponseJours()).isEqualTo(7);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés PRET_SANS_INTERET")
|
||||
void testProprietesPreSansInteret() {
|
||||
TypeAide type = TypeAide.PRET_SANS_INTERET;
|
||||
assertThat(type.getLibelle()).isEqualTo("Prêt sans intérêt");
|
||||
assertThat(type.getCategorie()).isEqualTo("financiere");
|
||||
assertThat(type.getPriorite()).isEqualTo("important");
|
||||
assertThat(type.getDescription()).isEqualTo("Prêt sans intérêt entre membres");
|
||||
assertThat(type.getIcone()).isEqualTo("account_balance");
|
||||
assertThat(type.getCouleur()).isEqualTo("#FF9800");
|
||||
assertThat(type.isNecessiteMontant()).isTrue();
|
||||
assertThat(type.isNecessiteValidation()).isTrue();
|
||||
assertThat(type.getMontantMin()).isEqualTo(10000.0);
|
||||
assertThat(type.getMontantMax()).isEqualTo(100000.0);
|
||||
assertThat(type.getDelaiReponseJours()).isEqualTo(30);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés DON_MATERIEL")
|
||||
void testProprietesDoMateriel() {
|
||||
TypeAide type = TypeAide.DON_MATERIEL;
|
||||
assertThat(type.getLibelle()).isEqualTo("Don de matériel");
|
||||
assertThat(type.getCategorie()).isEqualTo("materielle");
|
||||
assertThat(type.getPriorite()).isEqualTo("normal");
|
||||
assertThat(type.getDescription()).isEqualTo("Don d'objets, équipements ou matériel");
|
||||
assertThat(type.getIcone()).isEqualTo("inventory");
|
||||
assertThat(type.getCouleur()).isEqualTo("#4CAF50");
|
||||
assertThat(type.isNecessiteMontant()).isFalse();
|
||||
assertThat(type.isNecessiteValidation()).isFalse();
|
||||
assertThat(type.getMontantMin()).isNull();
|
||||
assertThat(type.getMontantMax()).isNull();
|
||||
assertThat(type.getDelaiReponseJours()).isEqualTo(14);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés HEBERGEMENT_URGENCE")
|
||||
void testProprietesHebergementUrgence() {
|
||||
TypeAide type = TypeAide.HEBERGEMENT_URGENCE;
|
||||
assertThat(type.getLibelle()).isEqualTo("Hébergement d'urgence");
|
||||
assertThat(type.getCategorie()).isEqualTo("urgence");
|
||||
assertThat(type.getPriorite()).isEqualTo("urgent");
|
||||
assertThat(type.getDescription()).isEqualTo("Hébergement temporaire d'urgence");
|
||||
assertThat(type.getIcone()).isEqualTo("home");
|
||||
assertThat(type.getCouleur()).isEqualTo("#F44336");
|
||||
assertThat(type.isNecessiteMontant()).isFalse();
|
||||
assertThat(type.isNecessiteValidation()).isTrue();
|
||||
assertThat(type.getMontantMin()).isNull();
|
||||
assertThat(type.getMontantMax()).isNull();
|
||||
assertThat(type.getDelaiReponseJours()).isEqualTo(7);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés AIDE_ALIMENTAIRE")
|
||||
void testProprietesAideAlimentaire() {
|
||||
TypeAide type = TypeAide.AIDE_ALIMENTAIRE;
|
||||
assertThat(type.getLibelle()).isEqualTo("Aide alimentaire");
|
||||
assertThat(type.getCategorie()).isEqualTo("urgence");
|
||||
assertThat(type.getPriorite()).isEqualTo("urgent");
|
||||
assertThat(type.getDescription()).isEqualTo("Aide alimentaire d'urgence");
|
||||
assertThat(type.getIcone()).isEqualTo("restaurant");
|
||||
assertThat(type.getCouleur()).isEqualTo("#FF5722");
|
||||
assertThat(type.isNecessiteMontant()).isFalse();
|
||||
assertThat(type.isNecessiteValidation()).isTrue();
|
||||
assertThat(type.getMontantMin()).isNull();
|
||||
assertThat(type.getMontantMax()).isNull();
|
||||
assertThat(type.getDelaiReponseJours()).isEqualTo(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés SOUTIEN_PSYCHOLOGIQUE")
|
||||
void testProprieteSoutienPsychologique() {
|
||||
TypeAide type = TypeAide.SOUTIEN_PSYCHOLOGIQUE;
|
||||
assertThat(type.getLibelle()).isEqualTo("Soutien psychologique");
|
||||
assertThat(type.getCategorie()).isEqualTo("specialisee");
|
||||
assertThat(type.getPriorite()).isEqualTo("important");
|
||||
assertThat(type.getDescription()).isEqualTo("Soutien et écoute psychologique");
|
||||
assertThat(type.getIcone()).isEqualTo("psychology");
|
||||
assertThat(type.getCouleur()).isEqualTo("#E91E63");
|
||||
assertThat(type.isNecessiteMontant()).isFalse();
|
||||
assertThat(type.isNecessiteValidation()).isTrue();
|
||||
assertThat(type.getMontantMin()).isNull();
|
||||
assertThat(type.getMontantMax()).isNull();
|
||||
assertThat(type.getDelaiReponseJours()).isEqualTo(30);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test propriétés AUTRE")
|
||||
void testProprietesAutre() {
|
||||
TypeAide type = TypeAide.AUTRE;
|
||||
assertThat(type.getLibelle()).isEqualTo("Autre");
|
||||
assertThat(type.getCategorie()).isEqualTo("autre");
|
||||
assertThat(type.getPriorite()).isEqualTo("normal");
|
||||
assertThat(type.getDescription()).isEqualTo("Autre type d'aide non catégorisé");
|
||||
assertThat(type.getIcone()).isEqualTo("help");
|
||||
assertThat(type.getCouleur()).isEqualTo("#9E9E9E");
|
||||
assertThat(type.isNecessiteMontant()).isFalse();
|
||||
assertThat(type.isNecessiteValidation()).isFalse();
|
||||
assertThat(type.getMontantMin()).isNull();
|
||||
assertThat(type.getMontantMax()).isNull();
|
||||
assertThat(type.getDelaiReponseJours()).isEqualTo(14);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes métier")
|
||||
class TestsMethodesMetier {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isUrgent - toutes les branches")
|
||||
void testIsUrgent() {
|
||||
// Types urgents (priorite == "urgent")
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.isUrgent()).isTrue();
|
||||
assertThat(TypeAide.AIDE_FRAIS_MEDICAUX.isUrgent()).isTrue();
|
||||
assertThat(TypeAide.HEBERGEMENT_URGENCE.isUrgent()).isTrue();
|
||||
assertThat(TypeAide.AIDE_ALIMENTAIRE.isUrgent()).isTrue();
|
||||
|
||||
// Types non urgents
|
||||
assertThat(TypeAide.PRET_SANS_INTERET.isUrgent()).isFalse(); // "important"
|
||||
assertThat(TypeAide.DON_MATERIEL.isUrgent()).isFalse(); // "normal"
|
||||
assertThat(TypeAide.AIDE_RECHERCHE_EMPLOI.isUrgent()).isFalse(); // "important"
|
||||
assertThat(TypeAide.FORMATION_PROFESSIONNELLE.isUrgent()).isFalse(); // "normal"
|
||||
assertThat(TypeAide.AUTRE.isUrgent()).isFalse(); // "normal"
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isFinancier - toutes les branches")
|
||||
void testIsFinancier() {
|
||||
// Types financiers (categorie == "financiere")
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.isFinancier()).isTrue();
|
||||
assertThat(TypeAide.PRET_SANS_INTERET.isFinancier()).isTrue();
|
||||
assertThat(TypeAide.AIDE_COTISATION.isFinancier()).isTrue();
|
||||
assertThat(TypeAide.AIDE_FRAIS_MEDICAUX.isFinancier()).isTrue();
|
||||
assertThat(TypeAide.AIDE_FRAIS_SCOLARITE.isFinancier()).isTrue();
|
||||
|
||||
// Types non financiers
|
||||
assertThat(TypeAide.DON_MATERIEL.isFinancier()).isFalse(); // "materielle"
|
||||
assertThat(TypeAide.AIDE_RECHERCHE_EMPLOI.isFinancier()).isFalse(); // "professionnelle"
|
||||
assertThat(TypeAide.GARDE_ENFANTS.isFinancier()).isFalse(); // "sociale"
|
||||
assertThat(TypeAide.HEBERGEMENT_URGENCE.isFinancier()).isFalse(); // "urgence"
|
||||
assertThat(TypeAide.SOUTIEN_PSYCHOLOGIQUE.isFinancier()).isFalse(); // "specialisee"
|
||||
assertThat(TypeAide.AUTRE.isFinancier()).isFalse(); // "autre"
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isMateriel - toutes les branches")
|
||||
void testIsMateriel() {
|
||||
// Types matériels (categorie == "materielle")
|
||||
assertThat(TypeAide.DON_MATERIEL.isMateriel()).isTrue();
|
||||
assertThat(TypeAide.PRET_MATERIEL.isMateriel()).isTrue();
|
||||
assertThat(TypeAide.AIDE_DEMENAGEMENT.isMateriel()).isTrue();
|
||||
assertThat(TypeAide.AIDE_TRAVAUX.isMateriel()).isTrue();
|
||||
|
||||
// Types non matériels
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.isMateriel()).isFalse(); // "financiere"
|
||||
assertThat(TypeAide.AIDE_RECHERCHE_EMPLOI.isMateriel()).isFalse(); // "professionnelle"
|
||||
assertThat(TypeAide.GARDE_ENFANTS.isMateriel()).isFalse(); // "sociale"
|
||||
assertThat(TypeAide.HEBERGEMENT_URGENCE.isMateriel()).isFalse(); // "urgence"
|
||||
assertThat(TypeAide.SOUTIEN_PSYCHOLOGIQUE.isMateriel()).isFalse(); // "specialisee"
|
||||
assertThat(TypeAide.AUTRE.isMateriel()).isFalse(); // "autre"
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test isMontantValide - toutes les branches")
|
||||
void testIsMontantValide() {
|
||||
// Type qui ne nécessite pas de montant -> toujours valide
|
||||
assertThat(TypeAide.DON_MATERIEL.isMontantValide(null)).isTrue();
|
||||
assertThat(TypeAide.DON_MATERIEL.isMontantValide(1000.0)).isTrue();
|
||||
assertThat(TypeAide.DON_MATERIEL.isMontantValide(-1000.0)).isTrue();
|
||||
|
||||
// Type qui nécessite un montant mais montant null -> valide
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.isMontantValide(null)).isTrue();
|
||||
|
||||
// Type avec montant min/max : AIDE_FINANCIERE_URGENTE (5000-50000)
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.isMontantValide(4999.0)).isFalse(); // < min
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.isMontantValide(5000.0)).isTrue(); // = min
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.isMontantValide(25000.0)).isTrue(); // dans la fourchette
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.isMontantValide(50000.0)).isTrue(); // = max
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.isMontantValide(50001.0)).isFalse(); // > max
|
||||
|
||||
// Type avec montant min/max : PRET_SANS_INTERET (10000-100000)
|
||||
assertThat(TypeAide.PRET_SANS_INTERET.isMontantValide(9999.0)).isFalse(); // < min
|
||||
assertThat(TypeAide.PRET_SANS_INTERET.isMontantValide(10000.0)).isTrue(); // = min
|
||||
assertThat(TypeAide.PRET_SANS_INTERET.isMontantValide(50000.0)).isTrue(); // dans la fourchette
|
||||
assertThat(TypeAide.PRET_SANS_INTERET.isMontantValide(100000.0)).isTrue(); // = max
|
||||
assertThat(TypeAide.PRET_SANS_INTERET.isMontantValide(100001.0)).isFalse(); // > max
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getNiveauPriorite - toutes les branches du switch")
|
||||
void testGetNiveauPriorite() {
|
||||
// "urgent" -> 1
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.getNiveauPriorite()).isEqualTo(1);
|
||||
assertThat(TypeAide.AIDE_FRAIS_MEDICAUX.getNiveauPriorite()).isEqualTo(1);
|
||||
assertThat(TypeAide.HEBERGEMENT_URGENCE.getNiveauPriorite()).isEqualTo(1);
|
||||
assertThat(TypeAide.AIDE_ALIMENTAIRE.getNiveauPriorite()).isEqualTo(1);
|
||||
|
||||
// "important" -> 2
|
||||
assertThat(TypeAide.PRET_SANS_INTERET.getNiveauPriorite()).isEqualTo(2);
|
||||
assertThat(TypeAide.AIDE_FRAIS_SCOLARITE.getNiveauPriorite()).isEqualTo(2);
|
||||
assertThat(TypeAide.AIDE_RECHERCHE_EMPLOI.getNiveauPriorite()).isEqualTo(2);
|
||||
assertThat(TypeAide.CONSEIL_JURIDIQUE.getNiveauPriorite()).isEqualTo(2);
|
||||
assertThat(TypeAide.AIDE_PERSONNES_AGEES.getNiveauPriorite()).isEqualTo(2);
|
||||
assertThat(TypeAide.SOUTIEN_PSYCHOLOGIQUE.getNiveauPriorite()).isEqualTo(2);
|
||||
|
||||
// "normal" -> 3
|
||||
assertThat(TypeAide.AIDE_COTISATION.getNiveauPriorite()).isEqualTo(3);
|
||||
assertThat(TypeAide.DON_MATERIEL.getNiveauPriorite()).isEqualTo(3);
|
||||
assertThat(TypeAide.FORMATION_PROFESSIONNELLE.getNiveauPriorite()).isEqualTo(3);
|
||||
assertThat(TypeAide.GARDE_ENFANTS.getNiveauPriorite()).isEqualTo(3);
|
||||
assertThat(TypeAide.TRANSPORT.getNiveauPriorite()).isEqualTo(3);
|
||||
assertThat(TypeAide.AIDE_ADMINISTRATIVE.getNiveauPriorite()).isEqualTo(3);
|
||||
assertThat(TypeAide.AIDE_VESTIMENTAIRE.getNiveauPriorite()).isEqualTo(3);
|
||||
assertThat(TypeAide.AIDE_NUMERIQUE.getNiveauPriorite()).isEqualTo(3);
|
||||
assertThat(TypeAide.TRADUCTION.getNiveauPriorite()).isEqualTo(3);
|
||||
assertThat(TypeAide.AUTRE.getNiveauPriorite()).isEqualTo(3);
|
||||
|
||||
// default -> 3 (pour toute autre valeur)
|
||||
// Pas de test direct possible car toutes les valeurs sont couvertes
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getDateLimiteReponse")
|
||||
void testGetDateLimiteReponse() {
|
||||
LocalDateTime avant = LocalDateTime.now();
|
||||
|
||||
// AIDE_FINANCIERE_URGENTE : 7 jours
|
||||
LocalDateTime dateLimite = TypeAide.AIDE_FINANCIERE_URGENTE.getDateLimiteReponse();
|
||||
LocalDateTime attendu = avant.plusDays(7);
|
||||
assertThat(dateLimite).isCloseTo(attendu, within(1, ChronoUnit.SECONDS));
|
||||
|
||||
// AIDE_ALIMENTAIRE : 3 jours
|
||||
dateLimite = TypeAide.AIDE_ALIMENTAIRE.getDateLimiteReponse();
|
||||
attendu = LocalDateTime.now().plusDays(3);
|
||||
assertThat(dateLimite).isCloseTo(attendu, within(1, ChronoUnit.SECONDS));
|
||||
|
||||
// FORMATION_PROFESSIONNELLE : 60 jours
|
||||
dateLimite = TypeAide.FORMATION_PROFESSIONNELLE.getDateLimiteReponse();
|
||||
attendu = LocalDateTime.now().plusDays(60);
|
||||
assertThat(dateLimite).isCloseTo(attendu, within(1, ChronoUnit.SECONDS));
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes statiques")
|
||||
class TestsMethodesStatiques {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getParCategorie")
|
||||
void testGetParCategorie() {
|
||||
// Catégorie "financiere"
|
||||
List<TypeAide> financiers = TypeAide.getParCategorie("financiere");
|
||||
assertThat(financiers).contains(
|
||||
TypeAide.AIDE_FINANCIERE_URGENTE,
|
||||
TypeAide.PRET_SANS_INTERET,
|
||||
TypeAide.AIDE_COTISATION,
|
||||
TypeAide.AIDE_FRAIS_MEDICAUX,
|
||||
TypeAide.AIDE_FRAIS_SCOLARITE);
|
||||
assertThat(financiers).doesNotContain(TypeAide.DON_MATERIEL, TypeAide.GARDE_ENFANTS);
|
||||
|
||||
// Catégorie "materielle"
|
||||
List<TypeAide> materiels = TypeAide.getParCategorie("materielle");
|
||||
assertThat(materiels).contains(
|
||||
TypeAide.DON_MATERIEL,
|
||||
TypeAide.PRET_MATERIEL,
|
||||
TypeAide.AIDE_DEMENAGEMENT,
|
||||
TypeAide.AIDE_TRAVAUX);
|
||||
assertThat(materiels).doesNotContain(TypeAide.AIDE_FINANCIERE_URGENTE, TypeAide.GARDE_ENFANTS);
|
||||
|
||||
// Catégorie "urgence"
|
||||
List<TypeAide> urgences = TypeAide.getParCategorie("urgence");
|
||||
assertThat(urgences).contains(
|
||||
TypeAide.HEBERGEMENT_URGENCE,
|
||||
TypeAide.AIDE_ALIMENTAIRE,
|
||||
TypeAide.AIDE_VESTIMENTAIRE);
|
||||
assertThat(urgences).doesNotContain(TypeAide.AIDE_FINANCIERE_URGENTE, TypeAide.DON_MATERIEL);
|
||||
|
||||
// Catégorie inexistante
|
||||
List<TypeAide> inexistante = TypeAide.getParCategorie("inexistante");
|
||||
assertThat(inexistante).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getUrgents")
|
||||
void testGetUrgents() {
|
||||
List<TypeAide> urgents = TypeAide.getUrgents();
|
||||
|
||||
// Vérifier que tous les types urgents sont inclus
|
||||
assertThat(urgents).contains(
|
||||
TypeAide.AIDE_FINANCIERE_URGENTE,
|
||||
TypeAide.AIDE_FRAIS_MEDICAUX,
|
||||
TypeAide.HEBERGEMENT_URGENCE,
|
||||
TypeAide.AIDE_ALIMENTAIRE);
|
||||
|
||||
// Vérifier qu'aucun type non urgent n'est inclus
|
||||
assertThat(urgents).doesNotContain(
|
||||
TypeAide.PRET_SANS_INTERET, // "important"
|
||||
TypeAide.DON_MATERIEL, // "normal"
|
||||
TypeAide.AIDE_RECHERCHE_EMPLOI, // "important"
|
||||
TypeAide.FORMATION_PROFESSIONNELLE); // "normal"
|
||||
|
||||
// Vérifier que tous les types retournés sont bien urgents
|
||||
urgents.forEach(type -> assertThat(type.isUrgent()).isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getFinanciers")
|
||||
void testGetFinanciers() {
|
||||
List<TypeAide> financiers = TypeAide.getFinanciers();
|
||||
|
||||
// Vérifier que tous les types financiers sont inclus
|
||||
assertThat(financiers).contains(
|
||||
TypeAide.AIDE_FINANCIERE_URGENTE,
|
||||
TypeAide.PRET_SANS_INTERET,
|
||||
TypeAide.AIDE_COTISATION,
|
||||
TypeAide.AIDE_FRAIS_MEDICAUX,
|
||||
TypeAide.AIDE_FRAIS_SCOLARITE);
|
||||
|
||||
// Vérifier qu'aucun type non financier n'est inclus
|
||||
assertThat(financiers).doesNotContain(
|
||||
TypeAide.DON_MATERIEL, // "materielle"
|
||||
TypeAide.AIDE_RECHERCHE_EMPLOI, // "professionnelle"
|
||||
TypeAide.GARDE_ENFANTS, // "sociale"
|
||||
TypeAide.HEBERGEMENT_URGENCE); // "urgence"
|
||||
|
||||
// Vérifier que tous les types retournés sont bien financiers
|
||||
financiers.forEach(type -> assertThat(type.isFinancier()).isTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getCategories")
|
||||
void testGetCategories() {
|
||||
Set<String> categories = TypeAide.getCategories();
|
||||
|
||||
// Vérifier que toutes les catégories sont présentes
|
||||
assertThat(categories).contains(
|
||||
"financiere",
|
||||
"materielle",
|
||||
"professionnelle",
|
||||
"sociale",
|
||||
"urgence",
|
||||
"specialisee",
|
||||
"autre");
|
||||
|
||||
// Vérifier qu'il n'y a pas de doublons (Set)
|
||||
assertThat(categories).hasSize(7);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des méthodes complexes")
|
||||
class TestsMethodesComplexes {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getLibelleCategorie - toutes les branches du switch")
|
||||
void testGetLibelleCategorie() {
|
||||
// Toutes les branches du switch
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.getLibelleCategorie()).isEqualTo("Aide financière");
|
||||
assertThat(TypeAide.DON_MATERIEL.getLibelleCategorie()).isEqualTo("Aide matérielle");
|
||||
assertThat(TypeAide.AIDE_RECHERCHE_EMPLOI.getLibelleCategorie()).isEqualTo("Aide professionnelle");
|
||||
assertThat(TypeAide.GARDE_ENFANTS.getLibelleCategorie()).isEqualTo("Aide sociale");
|
||||
assertThat(TypeAide.HEBERGEMENT_URGENCE.getLibelleCategorie()).isEqualTo("Aide d'urgence");
|
||||
assertThat(TypeAide.SOUTIEN_PSYCHOLOGIQUE.getLibelleCategorie()).isEqualTo("Aide spécialisée");
|
||||
assertThat(TypeAide.AUTRE.getLibelleCategorie()).isEqualTo("Autre");
|
||||
|
||||
// default -> retourne la catégorie telle quelle
|
||||
// Pas de test direct possible car toutes les catégories sont couvertes
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getUniteMontant - toutes les branches")
|
||||
void testGetUniteMontant() {
|
||||
// Types qui nécessitent un montant -> "FCFA"
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.getUniteMontant()).isEqualTo("FCFA");
|
||||
assertThat(TypeAide.PRET_SANS_INTERET.getUniteMontant()).isEqualTo("FCFA");
|
||||
assertThat(TypeAide.AIDE_COTISATION.getUniteMontant()).isEqualTo("FCFA");
|
||||
|
||||
// Types qui ne nécessitent pas de montant -> null
|
||||
assertThat(TypeAide.DON_MATERIEL.getUniteMontant()).isNull();
|
||||
assertThat(TypeAide.HEBERGEMENT_URGENCE.getUniteMontant()).isNull();
|
||||
assertThat(TypeAide.GARDE_ENFANTS.getUniteMontant()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test getMessageValidationMontant - toutes les branches")
|
||||
void testGetMessageValidationMontant() {
|
||||
// Type qui ne nécessite pas de montant -> null
|
||||
assertThat(TypeAide.DON_MATERIEL.getMessageValidationMontant(1000.0)).isNull();
|
||||
assertThat(TypeAide.DON_MATERIEL.getMessageValidationMontant(null)).isNull();
|
||||
|
||||
// Type qui nécessite un montant mais montant null -> message obligatoire
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.getMessageValidationMontant(null))
|
||||
.isEqualTo("Le montant est obligatoire");
|
||||
|
||||
// Montant < min -> message minimum
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.getMessageValidationMontant(4999.0))
|
||||
.isEqualTo("Le montant minimum est de 5000 FCFA");
|
||||
|
||||
// Montant > max -> message maximum
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.getMessageValidationMontant(50001.0))
|
||||
.isEqualTo("Le montant maximum est de 50000 FCFA");
|
||||
|
||||
// Montant valide -> null
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.getMessageValidationMontant(25000.0)).isNull();
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.getMessageValidationMontant(5000.0)).isNull();
|
||||
assertThat(TypeAide.AIDE_FINANCIERE_URGENTE.getMessageValidationMontant(50000.0)).isNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test cohérence globale des données")
|
||||
void testCoherenceGlobale() {
|
||||
for (TypeAide type : TypeAide.values()) {
|
||||
// Tous les champs obligatoires non null
|
||||
assertThat(type.getLibelle()).isNotNull().isNotEmpty();
|
||||
assertThat(type.getCategorie()).isNotNull().isNotEmpty();
|
||||
assertThat(type.getPriorite()).isNotNull().isNotEmpty();
|
||||
assertThat(type.getDescription()).isNotNull().isNotEmpty();
|
||||
assertThat(type.getIcone()).isNotNull().isNotEmpty();
|
||||
assertThat(type.getCouleur()).isNotNull().matches("#[0-9A-Fa-f]{6}");
|
||||
assertThat(type.getDelaiReponseJours()).isPositive();
|
||||
|
||||
// Cohérence logique
|
||||
if (type.isNecessiteMontant()) {
|
||||
assertThat(type.getUniteMontant()).isEqualTo("FCFA");
|
||||
} else {
|
||||
assertThat(type.getUniteMontant()).isNull();
|
||||
assertThat(type.getMontantMin()).isNull();
|
||||
assertThat(type.getMontantMax()).isNull();
|
||||
}
|
||||
|
||||
if (type.getMontantMin() != null && type.getMontantMax() != null) {
|
||||
assertThat(type.getMontantMax()).isGreaterThanOrEqualTo(type.getMontantMin());
|
||||
}
|
||||
|
||||
// Priorité cohérente
|
||||
assertThat(type.getPriorite()).isIn("urgent", "important", "normal");
|
||||
assertThat(type.getNiveauPriorite()).isBetween(1, 3);
|
||||
|
||||
// Catégorie cohérente
|
||||
assertThat(type.getCategorie()).isIn("financiere", "materielle", "professionnelle",
|
||||
"sociale", "urgence", "specialisee", "autre");
|
||||
assertThat(type.getLibelleCategorie()).isNotNull().isNotEmpty();
|
||||
|
||||
// Méthodes temporelles fonctionnent
|
||||
assertThat(type.getDateLimiteReponse()).isAfter(LocalDateTime.now());
|
||||
|
||||
// Validation de montant cohérente
|
||||
if (type.isNecessiteMontant()) {
|
||||
assertThat(type.getMessageValidationMontant(null)).isEqualTo("Le montant est obligatoire");
|
||||
} else {
|
||||
assertThat(type.getMessageValidationMontant(null)).isNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
package dev.lions.unionflow.server.api.validation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Tests unitaires pour ValidationConstants - Couverture 100%
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 2.0
|
||||
* @since 2025-01-16
|
||||
*/
|
||||
@DisplayName("Tests ValidationConstants")
|
||||
class ValidationConstantsTest {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constructeur privé")
|
||||
void testConstructeurPrive() throws Exception {
|
||||
Constructor<ValidationConstants> constructor = ValidationConstants.class.getDeclaredConstructor();
|
||||
constructor.setAccessible(true);
|
||||
|
||||
// Le constructeur doit être accessible et créer une instance
|
||||
ValidationConstants instance = constructor.newInstance();
|
||||
assertThat(instance).isNotNull();
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des constantes de taille")
|
||||
class TestsConstantesTaille {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constantes titre")
|
||||
void testConstantesTitre() {
|
||||
assertThat(ValidationConstants.TITRE_MIN_LENGTH).isEqualTo(5);
|
||||
assertThat(ValidationConstants.TITRE_MAX_LENGTH).isEqualTo(100);
|
||||
assertThat(ValidationConstants.TITRE_SIZE_MESSAGE).contains("5").contains("100").contains("titre");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constantes nom organisation")
|
||||
void testConstantesNomOrganisation() {
|
||||
assertThat(ValidationConstants.NOM_ORGANISATION_MIN_LENGTH).isEqualTo(2);
|
||||
assertThat(ValidationConstants.NOM_ORGANISATION_MAX_LENGTH).isEqualTo(200);
|
||||
assertThat(ValidationConstants.NOM_ORGANISATION_SIZE_MESSAGE)
|
||||
.contains("2")
|
||||
.contains("200")
|
||||
.contains("nom");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constantes description")
|
||||
void testConstantesDescription() {
|
||||
assertThat(ValidationConstants.DESCRIPTION_MIN_LENGTH).isEqualTo(20);
|
||||
assertThat(ValidationConstants.DESCRIPTION_MAX_LENGTH).isEqualTo(2000);
|
||||
assertThat(ValidationConstants.DESCRIPTION_SIZE_MESSAGE)
|
||||
.contains("20")
|
||||
.contains("2000")
|
||||
.contains("description");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constantes description courte")
|
||||
void testConstantesDescriptionCourte() {
|
||||
assertThat(ValidationConstants.DESCRIPTION_COURTE_MAX_LENGTH).isEqualTo(1000);
|
||||
assertThat(ValidationConstants.DESCRIPTION_COURTE_SIZE_MESSAGE)
|
||||
.contains("1000")
|
||||
.contains("description");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constantes justification")
|
||||
void testConstantesJustification() {
|
||||
assertThat(ValidationConstants.JUSTIFICATION_MAX_LENGTH).isEqualTo(1000);
|
||||
assertThat(ValidationConstants.JUSTIFICATION_SIZE_MESSAGE)
|
||||
.contains("1000")
|
||||
.contains("justification");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constantes commentaires")
|
||||
void testConstantesCommentaires() {
|
||||
assertThat(ValidationConstants.COMMENTAIRES_MAX_LENGTH).isEqualTo(1000);
|
||||
assertThat(ValidationConstants.COMMENTAIRES_SIZE_MESSAGE)
|
||||
.contains("1000")
|
||||
.contains("commentaires");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constantes raison rejet")
|
||||
void testConstantesRaisonRejet() {
|
||||
assertThat(ValidationConstants.RAISON_REJET_MAX_LENGTH).isEqualTo(500);
|
||||
assertThat(ValidationConstants.RAISON_REJET_SIZE_MESSAGE).contains("500").contains("rejet");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constantes email")
|
||||
void testConstantesEmail() {
|
||||
assertThat(ValidationConstants.EMAIL_MAX_LENGTH).isEqualTo(100);
|
||||
assertThat(ValidationConstants.EMAIL_SIZE_MESSAGE).contains("100").contains("email");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constantes nom et prénom")
|
||||
void testConstantesNomPrenom() {
|
||||
assertThat(ValidationConstants.NOM_PRENOM_MIN_LENGTH).isEqualTo(2);
|
||||
assertThat(ValidationConstants.NOM_PRENOM_MAX_LENGTH).isEqualTo(50);
|
||||
assertThat(ValidationConstants.NOM_SIZE_MESSAGE).contains("2").contains("50").contains("nom");
|
||||
assertThat(ValidationConstants.PRENOM_SIZE_MESSAGE).contains("2").contains("50").contains("prénom");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des patterns de validation")
|
||||
class TestsPatternsValidation {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test patterns téléphone")
|
||||
void testPatternsTelephone() {
|
||||
assertThat(ValidationConstants.TELEPHONE_PATTERN).isNotNull();
|
||||
assertThat(ValidationConstants.TELEPHONE_MESSAGE).contains("téléphone");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test patterns devise")
|
||||
void testPatternsDevise() {
|
||||
assertThat(ValidationConstants.DEVISE_PATTERN).isNotNull();
|
||||
assertThat(ValidationConstants.DEVISE_MESSAGE).contains("devise");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test patterns référence aide")
|
||||
void testPatternsReferenceAide() {
|
||||
assertThat(ValidationConstants.REFERENCE_AIDE_PATTERN).isNotNull();
|
||||
assertThat(ValidationConstants.REFERENCE_AIDE_MESSAGE).contains("référence");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test patterns numéro membre")
|
||||
void testPatternsNumeroMembre() {
|
||||
assertThat(ValidationConstants.NUMERO_MEMBRE_PATTERN).isNotNull();
|
||||
assertThat(ValidationConstants.NUMERO_MEMBRE_MESSAGE).contains("numéro");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test patterns couleur hexadécimale")
|
||||
void testPatternsCouleurHex() {
|
||||
assertThat(ValidationConstants.COULEUR_HEX_PATTERN).isNotNull();
|
||||
assertThat(ValidationConstants.COULEUR_HEX_MESSAGE).contains("couleur");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des messages obligatoires")
|
||||
class TestsMessagesObligatoires {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test message obligatoire")
|
||||
void testMessageObligatoire() {
|
||||
assertThat(ValidationConstants.OBLIGATOIRE_MESSAGE).contains("obligatoire");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test message email format")
|
||||
void testMessageEmailFormat() {
|
||||
assertThat(ValidationConstants.EMAIL_FORMAT_MESSAGE).contains("email");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test messages de date")
|
||||
void testMessagesDate() {
|
||||
assertThat(ValidationConstants.DATE_PASSEE_MESSAGE).contains("passé");
|
||||
assertThat(ValidationConstants.DATE_FUTURE_MESSAGE).contains("futur");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Tests des constantes numériques")
|
||||
class TestsConstantesNumeriques {
|
||||
|
||||
@Test
|
||||
@DisplayName("Test constantes montant")
|
||||
void testConstantesMontant() {
|
||||
assertThat(ValidationConstants.MONTANT_MIN_VALUE).isEqualTo("0.0");
|
||||
assertThat(ValidationConstants.MONTANT_INTEGER_DIGITS).isEqualTo(10);
|
||||
assertThat(ValidationConstants.MONTANT_FRACTION_DIGITS).isEqualTo(2);
|
||||
assertThat(ValidationConstants.MONTANT_DIGITS_MESSAGE).contains("10").contains("2");
|
||||
assertThat(ValidationConstants.MONTANT_POSITIF_MESSAGE).contains("positif");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("Test toutes les constantes sont non nulles")
|
||||
void testToutesConstantesNonNulles() {
|
||||
// Vérification que toutes les constantes String sont non nulles
|
||||
assertThat(ValidationConstants.TITRE_SIZE_MESSAGE).isNotNull();
|
||||
assertThat(ValidationConstants.NOM_ORGANISATION_SIZE_MESSAGE).isNotNull();
|
||||
assertThat(ValidationConstants.DESCRIPTION_SIZE_MESSAGE).isNotNull();
|
||||
assertThat(ValidationConstants.TELEPHONE_PATTERN).isNotNull();
|
||||
assertThat(ValidationConstants.DEVISE_PATTERN).isNotNull();
|
||||
assertThat(ValidationConstants.OBLIGATOIRE_MESSAGE).isNotNull();
|
||||
assertThat(ValidationConstants.EMAIL_FORMAT_MESSAGE).isNotNull();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user