+ 21
+ ${java.version}
+ ${java.version}
+ ${java.version}
UTF-8
- 3.20.0
+ 3.27.3
+ 1.18.38
2.18.2
3.0.2
3.1.1
diff --git a/script/publish-api.bat b/script/publish-api.bat
index e8f77fc..a07f728 100644
--- a/script/publish-api.bat
+++ b/script/publish-api.bat
@@ -1,30 +1,30 @@
-@echo off
-REM Publie le parent pom + server-api sur le Gitea Package Registry
-REM Usage : script\publish-api.bat
-REM Depuis : n'importe où dans le repo server-api
-REM Prérequis: credentials dans %USERPROFILE%\.m2\settings.xml (server id: gitea-lionsdev)
-
-set REGISTRY_URL=https://git.lions.dev/api/packages/lionsdev/maven
-set REGISTRY_ID=gitea-lionsdev
-
-cd /d "%~dp0\.."
-
-echo.
-echo [1/2] Publication du parent pom...
-call mvn deploy:deploy-file ^
- -DgroupId=dev.lions.unionflow ^
- -DartifactId=unionflow-parent ^
- -Dversion=1.0.0 ^
- -Dpackaging=pom ^
- -Dfile=parent-pom.xml ^
- -DrepositoryId=%REGISTRY_ID% ^
- -Durl=%REGISTRY_URL%
-if errorlevel 409 echo [WARN] Parent pom deja publie pour cette version, on continue.
-
-echo.
-echo [2/2] Publication du server-api...
-call mvn deploy -DskipTests
-if errorlevel 409 echo [WARN] Server-api deja publie - incrementer la version pour republier.
-
-echo.
-echo Done -- https://git.lions.dev/lionsdev/-/packages
+@echo off
+REM Publie le parent pom + server-api sur le Gitea Package Registry
+REM Usage : script\publish-api.bat
+REM Depuis : n'importe où dans le repo server-api
+REM Prérequis: credentials dans %USERPROFILE%\.m2\settings.xml (server id: gitea-lionsdev)
+
+set REGISTRY_URL=https://git.lions.dev/api/packages/lionsdev/maven
+set REGISTRY_ID=gitea-lionsdev
+
+cd /d "%~dp0\.."
+
+echo.
+echo [1/2] Publication du parent pom...
+call mvn deploy:deploy-file ^
+ -DgroupId=dev.lions.unionflow ^
+ -DartifactId=unionflow-parent ^
+ -Dversion=1.0.0 ^
+ -Dpackaging=pom ^
+ -Dfile=parent-pom.xml ^
+ -DrepositoryId=%REGISTRY_ID% ^
+ -Durl=%REGISTRY_URL%
+if errorlevel 409 echo [WARN] Parent pom deja publie pour cette version, on continue.
+
+echo.
+echo [2/2] Publication du server-api...
+call mvn deploy -DskipTests
+if errorlevel 409 echo [WARN] Server-api deja publie - incrementer la version pour republier.
+
+echo.
+echo Done -- https://git.lions.dev/lionsdev/-/packages
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/abonnement/request/CreateAbonnementRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/abonnement/request/CreateAbonnementRequest.java
index 996d745..3cc4123 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/abonnement/request/CreateAbonnementRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/abonnement/request/CreateAbonnementRequest.java
@@ -1,82 +1,82 @@
-package dev.lions.unionflow.server.api.dto.abonnement.request;
-
-import dev.lions.unionflow.server.api.enums.abonnement.StatutAbonnement;
-import dev.lions.unionflow.server.api.enums.abonnement.TypePeriodeAbonnement;
-import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
-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.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de création d'un abonnement.
- */
-@Builder
-public record CreateAbonnementRequest(
- @NotBlank(message = "Le numéro de référence est obligatoire") @Pattern(regexp = "^ABO-\\d{4}-[A-Z0-9]{8}$", message = "Format de référence invalide (ABO-YYYY-XXXXXXXX)") String numeroReference,
-
- @NotNull(message = "L'identifiant de l'organisation est obligatoire") UUID organisationId,
-
- String nomOrganisation,
-
- @NotNull(message = "L'identifiant de la formule est obligatoire") UUID formulaireId,
-
- String codeFormule,
- String nomFormule,
- TypeFormule typeFormule,
-
- @NotNull(message = "Le statut est obligatoire") StatutAbonnement statut,
-
- @NotNull(message = "Le type d'abonnement est obligatoire") TypePeriodeAbonnement typeAbonnement,
-
- @NotNull(message = "La date de début est obligatoire") LocalDate dateDebut,
-
- @Future(message = "La date de fin doit être dans le futur") LocalDate dateFin,
-
- LocalDate dateProchainePeriode,
-
- @NotNull(message = "Le montant est obligatoire") @DecimalMin(value = "0.0", inclusive = false, message = "Le montant doit être positif") @Digits(integer = 10, fraction = 2, message = "Le montant ne peut avoir plus de 10 chiffres entiers et 2 décimales") BigDecimal montant,
-
- @NotBlank(message = "La devise est obligatoire") @Pattern(regexp = "^[A-Z]{3}$", message = "La devise doit être un code ISO à 3 lettres") String devise,
-
- @DecimalMin(value = "0.0", message = "La remise doit être positive") @DecimalMin(value = "100.0", message = "La remise ne peut pas dépasser 100%") BigDecimal remise,
-
- @DecimalMin(value = "0.0", message = "Le montant final doit être positif") @Digits(integer = 10, fraction = 2, message = "Le montant ne peut avoir plus de 10 chiffres entiers et 2 décimales") BigDecimal montantFinal,
-
- Boolean renouvellementAutomatique,
- Boolean periodeEssaiUtilisee,
- LocalDate dateFinEssai,
- Integer maxMembres,
- Integer nombreMembresActuels,
- BigDecimal espaceStockageGB,
- BigDecimal espaceStockageUtilise,
- Boolean supportTechnique,
- String niveauSupport,
- Boolean fonctionnalitesAvancees,
- Boolean apiAccess,
- Boolean rapportsPersonnalises,
- Boolean integrationsTierces,
- UUID responsableId,
- String nomResponsable,
- String emailResponsable,
- String telephoneResponsable,
-
- @Pattern(regexp = "^(WAVE_MONEY|ORANGE_MONEY|FREE_MONEY|VIREMENT|CHEQUE|AUTRE)$", message = "Mode de paiement invalide") String modePaiementPrefere,
-
- @Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Format de numéro de téléphone invalide") String numeroPaiementMobile,
-
- @Size(max = 5000, message = "L'historique ne peut pas dépasser 5000 caractères") String historiquePaiements,
-
- @Size(max = 1000, message = "Les notes ne peuvent pas dépasser 1000 caractères") String notes,
-
- Boolean alertesActivees,
- Boolean notificationsEmail,
- Boolean notificationsSMS) {
-}
+package dev.lions.unionflow.server.api.dto.abonnement.request;
+
+import dev.lions.unionflow.server.api.enums.abonnement.StatutAbonnement;
+import dev.lions.unionflow.server.api.enums.abonnement.TypePeriodeAbonnement;
+import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
+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.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de création d'un abonnement.
+ */
+@Builder
+public record CreateAbonnementRequest(
+ @NotBlank(message = "Le numéro de référence est obligatoire") @Pattern(regexp = "^ABO-\\d{4}-[A-Z0-9]{8}$", message = "Format de référence invalide (ABO-YYYY-XXXXXXXX)") String numeroReference,
+
+ @NotNull(message = "L'identifiant de l'organisation est obligatoire") UUID organisationId,
+
+ String nomOrganisation,
+
+ @NotNull(message = "L'identifiant de la formule est obligatoire") UUID formulaireId,
+
+ String codeFormule,
+ String nomFormule,
+ TypeFormule typeFormule,
+
+ @NotNull(message = "Le statut est obligatoire") StatutAbonnement statut,
+
+ @NotNull(message = "Le type d'abonnement est obligatoire") TypePeriodeAbonnement typeAbonnement,
+
+ @NotNull(message = "La date de début est obligatoire") LocalDate dateDebut,
+
+ @Future(message = "La date de fin doit être dans le futur") LocalDate dateFin,
+
+ LocalDate dateProchainePeriode,
+
+ @NotNull(message = "Le montant est obligatoire") @DecimalMin(value = "0.0", inclusive = false, message = "Le montant doit être positif") @Digits(integer = 10, fraction = 2, message = "Le montant ne peut avoir plus de 10 chiffres entiers et 2 décimales") BigDecimal montant,
+
+ @NotBlank(message = "La devise est obligatoire") @Pattern(regexp = "^[A-Z]{3}$", message = "La devise doit être un code ISO à 3 lettres") String devise,
+
+ @DecimalMin(value = "0.0", message = "La remise doit être positive") @DecimalMin(value = "100.0", message = "La remise ne peut pas dépasser 100%") BigDecimal remise,
+
+ @DecimalMin(value = "0.0", message = "Le montant final doit être positif") @Digits(integer = 10, fraction = 2, message = "Le montant ne peut avoir plus de 10 chiffres entiers et 2 décimales") BigDecimal montantFinal,
+
+ Boolean renouvellementAutomatique,
+ Boolean periodeEssaiUtilisee,
+ LocalDate dateFinEssai,
+ Integer maxMembres,
+ Integer nombreMembresActuels,
+ BigDecimal espaceStockageGB,
+ BigDecimal espaceStockageUtilise,
+ Boolean supportTechnique,
+ String niveauSupport,
+ Boolean fonctionnalitesAvancees,
+ Boolean apiAccess,
+ Boolean rapportsPersonnalises,
+ Boolean integrationsTierces,
+ UUID responsableId,
+ String nomResponsable,
+ String emailResponsable,
+ String telephoneResponsable,
+
+ @Pattern(regexp = "^(WAVE_MONEY|ORANGE_MONEY|FREE_MONEY|VIREMENT|CHEQUE|AUTRE)$", message = "Mode de paiement invalide") String modePaiementPrefere,
+
+ @Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Format de numéro de téléphone invalide") String numeroPaiementMobile,
+
+ @Size(max = 5000, message = "L'historique ne peut pas dépasser 5000 caractères") String historiquePaiements,
+
+ @Size(max = 1000, message = "Les notes ne peuvent pas dépasser 1000 caractères") String notes,
+
+ Boolean alertesActivees,
+ Boolean notificationsEmail,
+ Boolean notificationsSMS) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/abonnement/request/UpdateAbonnementRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/abonnement/request/UpdateAbonnementRequest.java
index a959b81..14046c2 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/abonnement/request/UpdateAbonnementRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/abonnement/request/UpdateAbonnementRequest.java
@@ -1,77 +1,77 @@
-package dev.lions.unionflow.server.api.dto.abonnement.request;
-
-import dev.lions.unionflow.server.api.enums.abonnement.StatutAbonnement;
-import dev.lions.unionflow.server.api.enums.abonnement.TypePeriodeAbonnement;
-import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Digits;
-import jakarta.validation.constraints.Future;
-import jakarta.validation.constraints.Pattern;
-import jakarta.validation.constraints.Size;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'un abonnement.
- */
-@Builder
-public record UpdateAbonnementRequest(
- @Pattern(regexp = "^ABO-\\d{4}-[A-Z0-9]{8}$", message = "Format de référence invalide (ABO-YYYY-XXXXXXXX)") String numeroReference,
-
- UUID organisationId,
- String nomOrganisation,
- UUID formulaireId,
-
- String codeFormule,
- String nomFormule,
- TypeFormule typeFormule,
-
- StatutAbonnement statut,
- TypePeriodeAbonnement typeAbonnement,
-
- LocalDate dateDebut,
-
- @Future(message = "La date de fin doit être dans le futur") LocalDate dateFin,
-
- LocalDate dateProchainePeriode,
-
- @DecimalMin(value = "0.0", inclusive = false, message = "Le montant doit être positif") @Digits(integer = 10, fraction = 2, message = "Le montant ne peut avoir plus de 10 chiffres entiers et 2 décimales") BigDecimal montant,
-
- @Pattern(regexp = "^[A-Z]{3}$", message = "La devise doit être un code ISO à 3 lettres") String devise,
-
- @DecimalMin(value = "0.0", message = "La remise doit être positive") @DecimalMin(value = "100.0", message = "La remise ne peut pas dépasser 100%") BigDecimal remise,
-
- @DecimalMin(value = "0.0", message = "Le montant final doit être positif") @Digits(integer = 10, fraction = 2, message = "Le montant ne peut avoir plus de 10 chiffres entiers et 2 décimales") BigDecimal montantFinal,
-
- Boolean renouvellementAutomatique,
- Boolean periodeEssaiUtilisee,
- LocalDate dateFinEssai,
- Integer maxMembres,
- Integer nombreMembresActuels,
- BigDecimal espaceStockageGB,
- BigDecimal espaceStockageUtilise,
- Boolean supportTechnique,
- String niveauSupport,
- Boolean fonctionnalitesAvancees,
- Boolean apiAccess,
- Boolean rapportsPersonnalises,
- Boolean integrationsTierces,
- UUID responsableId,
- String nomResponsable,
- String emailResponsable,
- String telephoneResponsable,
-
- @Pattern(regexp = "^(WAVE_MONEY|ORANGE_MONEY|FREE_MONEY|VIREMENT|CHEQUE|AUTRE)$", message = "Mode de paiement invalide") String modePaiementPrefere,
-
- @Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Format de numéro de téléphone invalide") String numeroPaiementMobile,
-
- @Size(max = 5000, message = "L'historique ne peut pas dépasser 5000 caractères") String historiquePaiements,
-
- @Size(max = 1000, message = "Les notes ne peuvent pas dépasser 1000 caractères") String notes,
-
- Boolean alertesActivees,
- Boolean notificationsEmail,
- Boolean notificationsSMS) {
-}
+package dev.lions.unionflow.server.api.dto.abonnement.request;
+
+import dev.lions.unionflow.server.api.enums.abonnement.StatutAbonnement;
+import dev.lions.unionflow.server.api.enums.abonnement.TypePeriodeAbonnement;
+import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Digits;
+import jakarta.validation.constraints.Future;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'un abonnement.
+ */
+@Builder
+public record UpdateAbonnementRequest(
+ @Pattern(regexp = "^ABO-\\d{4}-[A-Z0-9]{8}$", message = "Format de référence invalide (ABO-YYYY-XXXXXXXX)") String numeroReference,
+
+ UUID organisationId,
+ String nomOrganisation,
+ UUID formulaireId,
+
+ String codeFormule,
+ String nomFormule,
+ TypeFormule typeFormule,
+
+ StatutAbonnement statut,
+ TypePeriodeAbonnement typeAbonnement,
+
+ LocalDate dateDebut,
+
+ @Future(message = "La date de fin doit être dans le futur") LocalDate dateFin,
+
+ LocalDate dateProchainePeriode,
+
+ @DecimalMin(value = "0.0", inclusive = false, message = "Le montant doit être positif") @Digits(integer = 10, fraction = 2, message = "Le montant ne peut avoir plus de 10 chiffres entiers et 2 décimales") BigDecimal montant,
+
+ @Pattern(regexp = "^[A-Z]{3}$", message = "La devise doit être un code ISO à 3 lettres") String devise,
+
+ @DecimalMin(value = "0.0", message = "La remise doit être positive") @DecimalMin(value = "100.0", message = "La remise ne peut pas dépasser 100%") BigDecimal remise,
+
+ @DecimalMin(value = "0.0", message = "Le montant final doit être positif") @Digits(integer = 10, fraction = 2, message = "Le montant ne peut avoir plus de 10 chiffres entiers et 2 décimales") BigDecimal montantFinal,
+
+ Boolean renouvellementAutomatique,
+ Boolean periodeEssaiUtilisee,
+ LocalDate dateFinEssai,
+ Integer maxMembres,
+ Integer nombreMembresActuels,
+ BigDecimal espaceStockageGB,
+ BigDecimal espaceStockageUtilise,
+ Boolean supportTechnique,
+ String niveauSupport,
+ Boolean fonctionnalitesAvancees,
+ Boolean apiAccess,
+ Boolean rapportsPersonnalises,
+ Boolean integrationsTierces,
+ UUID responsableId,
+ String nomResponsable,
+ String emailResponsable,
+ String telephoneResponsable,
+
+ @Pattern(regexp = "^(WAVE_MONEY|ORANGE_MONEY|FREE_MONEY|VIREMENT|CHEQUE|AUTRE)$", message = "Mode de paiement invalide") String modePaiementPrefere,
+
+ @Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Format de numéro de téléphone invalide") String numeroPaiementMobile,
+
+ @Size(max = 5000, message = "L'historique ne peut pas dépasser 5000 caractères") String historiquePaiements,
+
+ @Size(max = 1000, message = "Les notes ne peuvent pas dépasser 1000 caractères") String notes,
+
+ Boolean alertesActivees,
+ Boolean notificationsEmail,
+ Boolean notificationsSMS) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/abonnement/response/AbonnementResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/abonnement/response/AbonnementResponse.java
index 3381980..9d9b7a4 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/abonnement/response/AbonnementResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/abonnement/response/AbonnementResponse.java
@@ -1,133 +1,133 @@
-package dev.lions.unionflow.server.api.dto.abonnement.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import dev.lions.unionflow.server.api.enums.abonnement.StatutAbonnement;
-import dev.lions.unionflow.server.api.enums.abonnement.TypePeriodeAbonnement;
-import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse détaillée pour un abonnement.
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class AbonnementResponse extends BaseResponse {
-
- private String numeroReference;
- private UUID organisationId;
- private String nomOrganisation;
- private UUID formulaireId;
- private String codeFormule;
- private String nomFormule;
- private TypeFormule typeFormule;
- private StatutAbonnement statut;
- private TypePeriodeAbonnement typeAbonnement;
- private LocalDate dateDebut;
- private LocalDate dateFin;
- private LocalDate dateProchainePeriode;
- private BigDecimal montant;
- private String devise;
- private BigDecimal remise;
- private BigDecimal montantFinal;
- private Boolean renouvellementAutomatique;
- private Boolean periodeEssaiUtilisee;
- private LocalDate dateFinEssai;
- private Integer maxMembres;
- private Integer nombreMembresActuels;
- private BigDecimal espaceStockageGB;
- private BigDecimal espaceStockageUtilise;
- private Boolean supportTechnique;
- private String niveauSupport;
- private Boolean fonctionnalitesAvancees;
- private Boolean apiAccess;
- private Boolean rapportsPersonnalises;
- private Boolean integrationsTierces;
- private LocalDateTime dateDerniereUtilisation;
- private Integer connexionsCeMois;
- private UUID responsableId;
- private String nomResponsable;
- private String emailResponsable;
- private String telephoneResponsable;
-
- private String modePaiementPrefere;
- private String numeroPaiementMobile;
- private String historiquePaiements;
- private String notes;
-
- private Boolean alertesActivees;
- private Boolean notificationsEmail;
- private Boolean notificationsSMS;
-
- private LocalDateTime dateSuspension;
-
- private String raisonSuspension;
-
- private LocalDateTime dateAnnulation;
-
- private String raisonAnnulation;
-
- // === MÉTHODES UTILITAIRES ===
-
- public boolean isActive() {
- return StatutAbonnement.ACTIF.equals(statut);
- }
-
- public boolean isExpire() {
- return StatutAbonnement.EXPIRE.equals(statut) ||
- (dateFin != null && dateFin.isBefore(LocalDate.now()));
- }
-
- public boolean isSuspendu() {
- return StatutAbonnement.SUSPENDU.equals(statut);
- }
-
- public int getMembresRestants() {
- if (maxMembres == null) return 0;
- int actuels = nombreMembresActuels != null ? nombreMembresActuels : 0;
- return Math.max(0, maxMembres - actuels);
- }
-
- public boolean isQuotaAtteint() {
- if (maxMembres == null) return false;
- int actuels = nombreMembresActuels != null ? nombreMembresActuels : 0;
- return actuels >= maxMembres;
- }
-
- public int getPourcentageUtilisation() {
- if (maxMembres == null || maxMembres == 0) return 0;
- int actuels = nombreMembresActuels != null ? nombreMembresActuels : 0;
- return (actuels * 100) / maxMembres;
- }
-
- public long getJoursRestants() {
- if (dateFin == null) return -1;
- LocalDate maintenant = LocalDate.now();
- if (maintenant.isAfter(dateFin)) return 0;
- return java.time.temporal.ChronoUnit.DAYS.between(maintenant, dateFin);
- }
-
- public boolean isExpirationProche() {
- long joursRestants = getJoursRestants();
- return joursRestants >= 0 && joursRestants <= 30;
- }
-
- public boolean peutEtreRenouvele() {
- return Boolean.TRUE.equals(renouvellementAutomatique) && !isExpire();
- }
-
- public String getStatutLibelle() {
- return statut != null ? statut.name() : "INCONNU";
- }
-}
+package dev.lions.unionflow.server.api.dto.abonnement.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import dev.lions.unionflow.server.api.enums.abonnement.StatutAbonnement;
+import dev.lions.unionflow.server.api.enums.abonnement.TypePeriodeAbonnement;
+import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse détaillée pour un abonnement.
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AbonnementResponse extends BaseResponse {
+
+ private String numeroReference;
+ private UUID organisationId;
+ private String nomOrganisation;
+ private UUID formulaireId;
+ private String codeFormule;
+ private String nomFormule;
+ private TypeFormule typeFormule;
+ private StatutAbonnement statut;
+ private TypePeriodeAbonnement typeAbonnement;
+ private LocalDate dateDebut;
+ private LocalDate dateFin;
+ private LocalDate dateProchainePeriode;
+ private BigDecimal montant;
+ private String devise;
+ private BigDecimal remise;
+ private BigDecimal montantFinal;
+ private Boolean renouvellementAutomatique;
+ private Boolean periodeEssaiUtilisee;
+ private LocalDate dateFinEssai;
+ private Integer maxMembres;
+ private Integer nombreMembresActuels;
+ private BigDecimal espaceStockageGB;
+ private BigDecimal espaceStockageUtilise;
+ private Boolean supportTechnique;
+ private String niveauSupport;
+ private Boolean fonctionnalitesAvancees;
+ private Boolean apiAccess;
+ private Boolean rapportsPersonnalises;
+ private Boolean integrationsTierces;
+ private LocalDateTime dateDerniereUtilisation;
+ private Integer connexionsCeMois;
+ private UUID responsableId;
+ private String nomResponsable;
+ private String emailResponsable;
+ private String telephoneResponsable;
+
+ private String modePaiementPrefere;
+ private String numeroPaiementMobile;
+ private String historiquePaiements;
+ private String notes;
+
+ private Boolean alertesActivees;
+ private Boolean notificationsEmail;
+ private Boolean notificationsSMS;
+
+ private LocalDateTime dateSuspension;
+
+ private String raisonSuspension;
+
+ private LocalDateTime dateAnnulation;
+
+ private String raisonAnnulation;
+
+ // === MÉTHODES UTILITAIRES ===
+
+ public boolean isActive() {
+ return StatutAbonnement.ACTIF.equals(statut);
+ }
+
+ public boolean isExpire() {
+ return StatutAbonnement.EXPIRE.equals(statut) ||
+ (dateFin != null && dateFin.isBefore(LocalDate.now()));
+ }
+
+ public boolean isSuspendu() {
+ return StatutAbonnement.SUSPENDU.equals(statut);
+ }
+
+ public int getMembresRestants() {
+ if (maxMembres == null) return 0;
+ int actuels = nombreMembresActuels != null ? nombreMembresActuels : 0;
+ return Math.max(0, maxMembres - actuels);
+ }
+
+ public boolean isQuotaAtteint() {
+ if (maxMembres == null) return false;
+ int actuels = nombreMembresActuels != null ? nombreMembresActuels : 0;
+ return actuels >= maxMembres;
+ }
+
+ public int getPourcentageUtilisation() {
+ if (maxMembres == null || maxMembres == 0) return 0;
+ int actuels = nombreMembresActuels != null ? nombreMembresActuels : 0;
+ return (actuels * 100) / maxMembres;
+ }
+
+ public long getJoursRestants() {
+ if (dateFin == null) return -1;
+ LocalDate maintenant = LocalDate.now();
+ if (maintenant.isAfter(dateFin)) return 0;
+ return java.time.temporal.ChronoUnit.DAYS.between(maintenant, dateFin);
+ }
+
+ public boolean isExpirationProche() {
+ long joursRestants = getJoursRestants();
+ return joursRestants >= 0 && joursRestants <= 30;
+ }
+
+ public boolean peutEtreRenouvele() {
+ return Boolean.TRUE.equals(renouvellementAutomatique) && !isExpire();
+ }
+
+ public String getStatutLibelle() {
+ return statut != null ? statut.name() : "INCONNU";
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/admin/request/CreateAuditLogRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/admin/request/CreateAuditLogRequest.java
index 4393028..abd6b8a 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/admin/request/CreateAuditLogRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/admin/request/CreateAuditLogRequest.java
@@ -1,29 +1,29 @@
-package dev.lions.unionflow.server.api.dto.admin.request;
-
-import java.time.LocalDateTime;
-import lombok.Builder;
-
-/**
- * Requête de création d'un log d'audit.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record CreateAuditLogRequest(
- String typeAction,
- String severite,
- String utilisateur,
- String role,
- String module,
- String description,
- String details,
- String ipAddress,
- String userAgent,
- String sessionId,
- LocalDateTime dateHeure,
- String donneesAvant,
- String donneesApres,
- String entiteId,
- String entiteType) {
-}
+package dev.lions.unionflow.server.api.dto.admin.request;
+
+import java.time.LocalDateTime;
+import lombok.Builder;
+
+/**
+ * Requête de création d'un log d'audit.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record CreateAuditLogRequest(
+ String typeAction,
+ String severite,
+ String utilisateur,
+ String role,
+ String module,
+ String description,
+ String details,
+ String ipAddress,
+ String userAgent,
+ String sessionId,
+ LocalDateTime dateHeure,
+ String donneesAvant,
+ String donneesApres,
+ String entiteId,
+ String entiteType) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/admin/response/AuditLogResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/admin/response/AuditLogResponse.java
index a1b9248..15c95d3 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/admin/response/AuditLogResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/admin/response/AuditLogResponse.java
@@ -1,33 +1,33 @@
-package dev.lions.unionflow.server.api.dto.admin.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.time.LocalDateTime;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * Réponse pour les logs d'audit.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Getter
-@Setter
-public class AuditLogResponse extends BaseResponse {
-
- private String typeAction;
- private String severite;
- private String utilisateur;
- private String role;
- private String module;
- private String description;
- private String details;
- private String ipAddress;
- private String userAgent;
- private String sessionId;
- private LocalDateTime dateHeure;
- private String donneesAvant;
- private String donneesApres;
- private String entiteId;
- private String entiteType;
-}
+package dev.lions.unionflow.server.api.dto.admin.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.time.LocalDateTime;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Réponse pour les logs d'audit.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Getter
+@Setter
+public class AuditLogResponse extends BaseResponse {
+
+ private String typeAction;
+ private String severite;
+ private String utilisateur;
+ private String role;
+ private String module;
+ private String description;
+ private String details;
+ private String ipAddress;
+ private String userAgent;
+ private String sessionId;
+ private LocalDateTime dateHeure;
+ private String donneesAvant;
+ private String donneesApres;
+ private String entiteId;
+ private String entiteType;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/adresse/request/CreateAdresseRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/adresse/request/CreateAdresseRequest.java
index d774aec..ef88245 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/adresse/request/CreateAdresseRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/adresse/request/CreateAdresseRequest.java
@@ -1,43 +1,43 @@
-package dev.lions.unionflow.server.api.dto.adresse.request;
-
-import jakarta.validation.constraints.DecimalMax;
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Digits;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import java.math.BigDecimal;
-import java.util.UUID;
-
-/**
- * Requete de création d'une adresse.
- *
- * @author UnionFlow Team
- * @version 3.0
- */
-public record CreateAdresseRequest(
- @NotBlank(message = "Le type d'adresse est obligatoire") String typeAdresse, // Code depuis types_reference
-
- @NotBlank(message = "L'adresse est obligatoire") String adresse,
-
- String complementAdresse,
- String codePostal,
-
- @NotBlank(message = "La ville est obligatoire") String ville,
-
- String region,
-
- @NotBlank(message = "Le pays est obligatoire") String pays,
-
- @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") @Digits(integer = 3, fraction = 6) BigDecimal latitude, // Optionnel
-
- @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") @Digits(integer = 3, fraction = 6) BigDecimal longitude, // Optionnel
-
- @NotNull(message = "L'indicateur principale est obligatoire") Boolean principale,
-
- String libelle,
- String notes,
-
- UUID organisationId, // Exclusive: soit organisationId, soit membreId, soit evenementId
- UUID membreId,
- UUID evenementId) {
-}
+package dev.lions.unionflow.server.api.dto.adresse.request;
+
+import jakarta.validation.constraints.DecimalMax;
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Digits;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.UUID;
+
+/**
+ * Requete de création d'une adresse.
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ */
+public record CreateAdresseRequest(
+ @NotBlank(message = "Le type d'adresse est obligatoire") String typeAdresse, // Code depuis types_reference
+
+ @NotBlank(message = "L'adresse est obligatoire") String adresse,
+
+ String complementAdresse,
+ String codePostal,
+
+ @NotBlank(message = "La ville est obligatoire") String ville,
+
+ String region,
+
+ @NotBlank(message = "Le pays est obligatoire") String pays,
+
+ @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") @Digits(integer = 3, fraction = 6) BigDecimal latitude, // Optionnel
+
+ @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") @Digits(integer = 3, fraction = 6) BigDecimal longitude, // Optionnel
+
+ @NotNull(message = "L'indicateur principale est obligatoire") Boolean principale,
+
+ String libelle,
+ String notes,
+
+ UUID organisationId, // Exclusive: soit organisationId, soit membreId, soit evenementId
+ UUID membreId,
+ UUID evenementId) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/adresse/request/UpdateAdresseRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/adresse/request/UpdateAdresseRequest.java
index 7460e5a..af39fec 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/adresse/request/UpdateAdresseRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/adresse/request/UpdateAdresseRequest.java
@@ -1,36 +1,36 @@
-package dev.lions.unionflow.server.api.dto.adresse.request;
-
-import jakarta.validation.constraints.DecimalMax;
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Digits;
-import java.math.BigDecimal;
-import java.util.UUID;
-
-/**
- * Requete de mise à jour d'une adresse.
- * Tous les champs sont optionnels pour permettre des mises à jour partielles.
- *
- * @author UnionFlow Team
- * @version 3.0
- */
-public record UpdateAdresseRequest(
- String typeAdresse, // Code depuis types_reference
- String adresse,
- String complementAdresse,
- String codePostal,
- String ville,
- String region,
- String pays,
-
- @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") @Digits(integer = 3, fraction = 6) BigDecimal latitude,
-
- @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") @Digits(integer = 3, fraction = 6) BigDecimal longitude,
-
- Boolean principale,
- String libelle,
- String notes,
-
- UUID organisationId,
- UUID membreId,
- UUID evenementId) {
-}
+package dev.lions.unionflow.server.api.dto.adresse.request;
+
+import jakarta.validation.constraints.DecimalMax;
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Digits;
+import java.math.BigDecimal;
+import java.util.UUID;
+
+/**
+ * Requete de mise à jour d'une adresse.
+ * Tous les champs sont optionnels pour permettre des mises à jour partielles.
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ */
+public record UpdateAdresseRequest(
+ String typeAdresse, // Code depuis types_reference
+ String adresse,
+ String complementAdresse,
+ String codePostal,
+ String ville,
+ String region,
+ String pays,
+
+ @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") @Digits(integer = 3, fraction = 6) BigDecimal latitude,
+
+ @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") @Digits(integer = 3, fraction = 6) BigDecimal longitude,
+
+ Boolean principale,
+ String libelle,
+ String notes,
+
+ UUID organisationId,
+ UUID membreId,
+ UUID evenementId) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/adresse/response/AdresseResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/adresse/response/AdresseResponse.java
index eef7bf8..0cc0ac0 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/adresse/response/AdresseResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/adresse/response/AdresseResponse.java
@@ -1,42 +1,42 @@
-package dev.lions.unionflow.server.api.dto.adresse.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.math.BigDecimal;
-import java.util.UUID;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * DTO de réponse détaillée pour une adresse.
- *
- * @author UnionFlow Team
- * @version 3.0
- */
-@Getter
-@Setter
-public class AdresseResponse extends BaseResponse {
-
- private String typeAdresse; // Code
- private String typeAdresseLibelle; // Depuis types_reference
- private String typeAdresseIcone;
-
- private String adresse;
- private String complementAdresse;
- private String codePostal;
- private String ville;
- private String region;
- private String pays;
-
- private BigDecimal latitude;
- private BigDecimal longitude;
-
- private Boolean principale;
- private String libelle;
- private String notes;
-
- private UUID organisationId;
- private UUID membreId;
- private UUID evenementId;
-
- private String adresseComplete;
-}
+package dev.lions.unionflow.server.api.dto.adresse.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.math.BigDecimal;
+import java.util.UUID;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * DTO de réponse détaillée pour une adresse.
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ */
+@Getter
+@Setter
+public class AdresseResponse extends BaseResponse {
+
+ private String typeAdresse; // Code
+ private String typeAdresseLibelle; // Depuis types_reference
+ private String typeAdresseIcone;
+
+ private String adresse;
+ private String complementAdresse;
+ private String codePostal;
+ private String ville;
+ private String region;
+ private String pays;
+
+ private BigDecimal latitude;
+ private BigDecimal longitude;
+
+ private Boolean principale;
+ private String libelle;
+ private String notes;
+
+ private UUID organisationId;
+ private UUID membreId;
+ private UUID evenementId;
+
+ private String adresseComplete;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/agricole/CampagneAgricoleDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/agricole/CampagneAgricoleDTO.java
index c889af6..5985a51 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/agricole/CampagneAgricoleDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/agricole/CampagneAgricoleDTO.java
@@ -1,35 +1,35 @@
-package dev.lions.unionflow.server.api.dto.agricole;
-
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.agricole.StatutCampagneAgricole;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-
-import java.math.BigDecimal;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class CampagneAgricoleDTO extends BaseDTO {
-
- private String organisationCoopId;
-
- // Exemple : "Campagne d'Arachide 2025/2026"
- private String designation;
-
- private String typeCulturePrincipale;
-
- // Nombre d'hectares au total couvert par les membres de la coop
- private BigDecimal surfaceTotaleEstimeeHectares;
-
- // Tonnes récoltées attendues vs réelles
- private BigDecimal volumePrevisionnelTonnes;
- private BigDecimal volumeReelTonnes;
-
- private StatutCampagneAgricole statut;
-}
+package dev.lions.unionflow.server.api.dto.agricole;
+
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.agricole.StatutCampagneAgricole;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class CampagneAgricoleDTO extends BaseDTO {
+
+ private String organisationCoopId;
+
+ // Exemple : "Campagne d'Arachide 2025/2026"
+ private String designation;
+
+ private String typeCulturePrincipale;
+
+ // Nombre d'hectares au total couvert par les membres de la coop
+ private BigDecimal surfaceTotaleEstimeeHectares;
+
+ // Tonnes récoltées attendues vs réelles
+ private BigDecimal volumePrevisionnelTonnes;
+ private BigDecimal volumeReelTonnes;
+
+ private StatutCampagneAgricole statut;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/analytics/AnalyticsDataResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/analytics/AnalyticsDataResponse.java
index d90f17e..b12801d 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/analytics/AnalyticsDataResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/analytics/AnalyticsDataResponse.java
@@ -1,265 +1,265 @@
-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.PeriodeAnalyse;
-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 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.
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-16
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class AnalyticsDataResponse 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 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 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 AnalyticsDataResponse(
- 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
- }
-}
+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.PeriodeAnalyse;
+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 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.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2025-01-16
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AnalyticsDataResponse 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 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 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 AnalyticsDataResponse(
+ 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
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/analytics/DashboardWidgetResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/analytics/DashboardWidgetResponse.java
index 528989d..6dfe8e3 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/analytics/DashboardWidgetResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/analytics/DashboardWidgetResponse.java
@@ -1,350 +1,350 @@
-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.PeriodeAnalyse;
-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 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.
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-16
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class DashboardWidgetResponse 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 configurationFiltres;
-
- /** Configuration des alertes */
- private Map 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 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;
- }
- 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
- */
- /** Indique si la fréquence est en temps réel (pour couverture branches). */
- private boolean isFrequenceTempsReel() {
- if (frequenceMiseAJourSecondes == null) return false;
- return frequenceMiseAJourSecondes <= 60;
- }
-
- public boolean isTempsReel() {
- return isFrequenceTempsReel();
- }
-
- /**
- * 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"
- */
- /** Indique si le taux d'erreur déclenche le statut maintenance (pour couverture branches). */
- private boolean isTauxErreurMaintenance() {
- if (tauxErreur == null) return false;
- return tauxErreur > 10.0;
- }
-
- public String getStatutWidget() {
- if (hasErreursRecentes()) return "erreur";
- if (!visible) return "inactif";
- if (isTauxErreurMaintenance()) return "maintenance";
- return "actif";
- }
-}
+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.PeriodeAnalyse;
+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 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.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2025-01-16
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DashboardWidgetResponse 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 configurationFiltres;
+
+ /** Configuration des alertes */
+ private Map 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 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;
+ }
+ 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
+ */
+ /** Indique si la fréquence est en temps réel (pour couverture branches). */
+ private boolean isFrequenceTempsReel() {
+ if (frequenceMiseAJourSecondes == null) return false;
+ return frequenceMiseAJourSecondes <= 60;
+ }
+
+ public boolean isTempsReel() {
+ return isFrequenceTempsReel();
+ }
+
+ /**
+ * 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"
+ */
+ /** Indique si le taux d'erreur déclenche le statut maintenance (pour couverture branches). */
+ private boolean isTauxErreurMaintenance() {
+ if (tauxErreur == null) return false;
+ return tauxErreur > 10.0;
+ }
+
+ public String getStatutWidget() {
+ if (hasErreursRecentes()) return "erreur";
+ if (!visible) return "inactif";
+ if (isTauxErreurMaintenance()) return "maintenance";
+ return "actif";
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/analytics/KPITrendResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/analytics/KPITrendResponse.java
index a0b2c6b..358f426 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/analytics/KPITrendResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/analytics/KPITrendResponse.java
@@ -1,309 +1,309 @@
-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.PeriodeAnalyse;
-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 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.
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-16
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class KPITrendResponse 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")
- @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 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(point -> Boolean.TRUE.equals(point.getAnomalie()));
- }
-}
+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.PeriodeAnalyse;
+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 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.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2025-01-16
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class KPITrendResponse 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")
+ @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 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(point -> Boolean.TRUE.equals(point.getAnomalie()));
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/analytics/ReportConfigDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/analytics/ReportConfigDTO.java
index cdc2060..01598ba 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/analytics/ReportConfigDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/analytics/ReportConfigDTO.java
@@ -1,333 +1,333 @@
-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.FormatExport;
-import dev.lions.unionflow.server.api.enums.analytics.PeriodeAnalyse;
-import dev.lions.unionflow.server.api.enums.analytics.TypeMetrique;
-import jakarta.validation.Valid;
-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.
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-16
- */
-@Getter
-@Setter
-@Builder
-@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 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 metriques;
-
- /** Sections du rapport */
- @Valid private List 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 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 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 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 parametresFiltrage;
-
- /** Tags pour catégoriser le rapport */
- private List 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 seuilsAlerte;
-
- /** Filtres spécifiques à cette métrique */
- private Map 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 metriquesIncluses;
-
- /** Configuration spécifique de la section */
- private Map 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
- */
- /** Indique si le niveau de confidentialité est élevé (pour couverture branches). */
- private boolean isNiveauConfidentiel() {
- if (niveauConfidentialite == null) return false;
- return niveauConfidentialite >= 4;
- }
-
- public boolean isConfidentiel() {
- return isNiveauConfidentiel();
- }
-
- /**
- * 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";
- };
- }
-}
+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.FormatExport;
+import dev.lions.unionflow.server.api.enums.analytics.PeriodeAnalyse;
+import dev.lions.unionflow.server.api.enums.analytics.TypeMetrique;
+import jakarta.validation.Valid;
+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.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2025-01-16
+ */
+@Getter
+@Setter
+@Builder
+@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 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 metriques;
+
+ /** Sections du rapport */
+ @Valid private List 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 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 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 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 parametresFiltrage;
+
+ /** Tags pour catégoriser le rapport */
+ private List 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 seuilsAlerte;
+
+ /** Filtres spécifiques à cette métrique */
+ private Map 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 metriquesIncluses;
+
+ /** Configuration spécifique de la section */
+ private Map 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
+ */
+ /** Indique si le niveau de confidentialité est élevé (pour couverture branches). */
+ private boolean isNiveauConfidentiel() {
+ if (niveauConfidentialite == null) return false;
+ return niveauConfidentialite >= 4;
+ }
+
+ public boolean isConfidentiel() {
+ return isNiveauConfidentiel();
+ }
+
+ /**
+ * 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";
+ };
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/auth/request/LoginRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/auth/request/LoginRequest.java
index 0f64271..b6cc298 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/auth/request/LoginRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/auth/request/LoginRequest.java
@@ -1,32 +1,32 @@
-package dev.lions.unionflow.server.api.dto.auth.request;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Size;
-import lombok.Builder;
-
-/**
- * Requête d'authentification utilisateur.
- *
- * @param username Email ou nom d'utilisateur
- * @param password Mot de passe
- * @param typeCompte Type de compte (MEMBRE, ADMIN, etc.)
- * @param rememberMe Se souvenir de moi
- * @author UnionFlow Team
- * @version 2.0
- * @since 2026-02-28
- */
-@Builder
-public record LoginRequest(
- @NotBlank(message = "L'email ou nom d'utilisateur est requis")
- @Size(min = 3, max = 100, message = "L'email ou nom d'utilisateur doit contenir entre 3 et 100 caractères")
- String username,
-
- @NotBlank(message = "Le mot de passe est requis")
- @Size(min = 6, message = "Le mot de passe doit contenir au moins 6 caractères")
- String password,
-
- @NotBlank(message = "Le type de compte est requis")
- String typeCompte,
-
- Boolean rememberMe) {
-}
+package dev.lions.unionflow.server.api.dto.auth.request;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import lombok.Builder;
+
+/**
+ * Requête d'authentification utilisateur.
+ *
+ * @param username Email ou nom d'utilisateur
+ * @param password Mot de passe
+ * @param typeCompte Type de compte (MEMBRE, ADMIN, etc.)
+ * @param rememberMe Se souvenir de moi
+ * @author UnionFlow Team
+ * @version 2.0
+ * @since 2026-02-28
+ */
+@Builder
+public record LoginRequest(
+ @NotBlank(message = "L'email ou nom d'utilisateur est requis")
+ @Size(min = 3, max = 100, message = "L'email ou nom d'utilisateur doit contenir entre 3 et 100 caractères")
+ String username,
+
+ @NotBlank(message = "Le mot de passe est requis")
+ @Size(min = 6, message = "Le mot de passe doit contenir au moins 6 caractères")
+ String password,
+
+ @NotBlank(message = "Le type de compte est requis")
+ String typeCompte,
+
+ Boolean rememberMe) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/auth/response/LoginResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/auth/response/LoginResponse.java
index e23e6f4..d1b048a 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/auth/response/LoginResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/auth/response/LoginResponse.java
@@ -1,90 +1,90 @@
-package dev.lions.unionflow.server.api.dto.auth.response;
-
-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;
-
-/**
- * Réponse d'authentification contenant le token JWT et les informations utilisateur.
- *
- * @author UnionFlow Team
- * @version 2.0
- * @since 2026-02-28
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class LoginResponse {
-
- private String accessToken;
- private String refreshToken;
- @Builder.Default
- private String tokenType = "Bearer";
- private Long expiresIn;
- private LocalDateTime expirationDate;
- private UserInfo user;
-
- /**
- * Vérifie si le token est expiré.
- *
- * @return true si le token est expiré
- */
- public boolean isExpired() {
- return expirationDate != null && LocalDateTime.now().isAfter(expirationDate);
- }
-
- /**
- * Informations de l'utilisateur connecté.
- */
- @Getter
- @Setter
- @Builder
- @NoArgsConstructor
- @AllArgsConstructor
- public static class UserInfo {
- private UUID id;
- private String nom;
- private String prenom;
- private String email;
- private String username;
- private String typeCompte;
- private List roles;
- private List permissions;
- private EntiteInfo entite;
-
- /**
- * Retourne le nom complet de l'utilisateur.
- *
- * @return Prénom + Nom ou nom d'utilisateur si absent
- */
- public String getNomComplet() {
- if (prenom != null && nom != null) {
- return prenom + " " + nom;
- }
- return nom != null ? nom : username;
- }
- }
-
- /**
- * Informations sur l'entité (organisation/membre) de l'utilisateur.
- */
- @Getter
- @Setter
- @Builder
- @NoArgsConstructor
- @AllArgsConstructor
- public static class EntiteInfo {
- private UUID id;
- private String nom;
- private String type;
- private String pays;
- private String ville;
- }
-}
+package dev.lions.unionflow.server.api.dto.auth.response;
+
+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;
+
+/**
+ * Réponse d'authentification contenant le token JWT et les informations utilisateur.
+ *
+ * @author UnionFlow Team
+ * @version 2.0
+ * @since 2026-02-28
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class LoginResponse {
+
+ private String accessToken;
+ private String refreshToken;
+ @Builder.Default
+ private String tokenType = "Bearer";
+ private Long expiresIn;
+ private LocalDateTime expirationDate;
+ private UserInfo user;
+
+ /**
+ * Vérifie si le token est expiré.
+ *
+ * @return true si le token est expiré
+ */
+ public boolean isExpired() {
+ return expirationDate != null && LocalDateTime.now().isAfter(expirationDate);
+ }
+
+ /**
+ * Informations de l'utilisateur connecté.
+ */
+ @Getter
+ @Setter
+ @Builder
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class UserInfo {
+ private UUID id;
+ private String nom;
+ private String prenom;
+ private String email;
+ private String username;
+ private String typeCompte;
+ private List roles;
+ private List permissions;
+ private EntiteInfo entite;
+
+ /**
+ * Retourne le nom complet de l'utilisateur.
+ *
+ * @return Prénom + Nom ou nom d'utilisateur si absent
+ */
+ public String getNomComplet() {
+ if (prenom != null && nom != null) {
+ return prenom + " " + nom;
+ }
+ return nom != null ? nom : username;
+ }
+ }
+
+ /**
+ * Informations sur l'entité (organisation/membre) de l'utilisateur.
+ */
+ @Getter
+ @Setter
+ @Builder
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class EntiteInfo {
+ private UUID id;
+ private String nom;
+ private String type;
+ private String pays;
+ private String ville;
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/ayantdroit/AyantDroitRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/ayantdroit/AyantDroitRequest.java
index a13ee1b..96eaf7e 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/ayantdroit/AyantDroitRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/ayantdroit/AyantDroitRequest.java
@@ -1,42 +1,42 @@
-package dev.lions.unionflow.server.api.dto.ayantdroit;
-
-import dev.lions.unionflow.server.api.enums.ayantdroit.LienParente;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Past;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDate;
-
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class AyantDroitRequest {
-
- @NotBlank(message = "L'Id du membre principal rattaché est obligatoire")
- private String membrePrincipalId;
-
- @NotBlank(message = "Le prénom est obligatoire")
- private String prenom;
-
- @NotBlank(message = "Le nom est obligatoire")
- private String nom;
-
- @NotNull(message = "La date de naissance est obligatoire pour l'âge limite")
- @Past(message = "La date de naissance doit être dans le passé")
- private LocalDate dateNaissance;
-
- private String sexe;
-
- private String pieceIdentite;
-
- @NotNull(message = "Le lien de parenté / bénéfice est requis")
- private LienParente lienParente;
-
- // Id document du livret de famille ou certificat médical / scolaire
- private String justificatifLienId;
-}
+package dev.lions.unionflow.server.api.dto.ayantdroit;
+
+import dev.lions.unionflow.server.api.enums.ayantdroit.LienParente;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Past;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDate;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class AyantDroitRequest {
+
+ @NotBlank(message = "L'Id du membre principal rattaché est obligatoire")
+ private String membrePrincipalId;
+
+ @NotBlank(message = "Le prénom est obligatoire")
+ private String prenom;
+
+ @NotBlank(message = "Le nom est obligatoire")
+ private String nom;
+
+ @NotNull(message = "La date de naissance est obligatoire pour l'âge limite")
+ @Past(message = "La date de naissance doit être dans le passé")
+ private LocalDate dateNaissance;
+
+ private String sexe;
+
+ private String pieceIdentite;
+
+ @NotNull(message = "Le lien de parenté / bénéfice est requis")
+ private LienParente lienParente;
+
+ // Id document du livret de famille ou certificat médical / scolaire
+ private String justificatifLienId;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/ayantdroit/AyantDroitResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/ayantdroit/AyantDroitResponse.java
index 6f5feb7..30654a9 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/ayantdroit/AyantDroitResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/ayantdroit/AyantDroitResponse.java
@@ -1,40 +1,40 @@
-package dev.lions.unionflow.server.api.dto.ayantdroit;
-
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.ayantdroit.LienParente;
-import dev.lions.unionflow.server.api.enums.ayantdroit.StatutAyantDroit;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDate;
-import java.math.BigDecimal;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class AyantDroitResponse extends BaseDTO {
-
- private String membrePrincipalId;
-
- private String numeroCarteBeneficiaire;
-
- private String prenom;
- private String nom;
-
- private LocalDate dateNaissance;
- private Integer ageActuel;
- private String sexe;
- private String pieceIdentite;
-
- private LienParente lienParente;
-
- // Prise en charge (%) par rapport à la couverture du Membre Principal
- private BigDecimal pourcentageCouvertureSante;
-
- private StatutAyantDroit statut;
-}
+package dev.lions.unionflow.server.api.dto.ayantdroit;
+
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.ayantdroit.LienParente;
+import dev.lions.unionflow.server.api.enums.ayantdroit.StatutAyantDroit;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDate;
+import java.math.BigDecimal;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class AyantDroitResponse extends BaseDTO {
+
+ private String membrePrincipalId;
+
+ private String numeroCarteBeneficiaire;
+
+ private String prenom;
+ private String nom;
+
+ private LocalDate dateNaissance;
+ private Integer ageActuel;
+ private String sexe;
+ private String pieceIdentite;
+
+ private LienParente lienParente;
+
+ // Prise en charge (%) par rapport à la couverture du Membre Principal
+ private BigDecimal pourcentageCouvertureSante;
+
+ private StatutAyantDroit statut;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/backup/request/CreateBackupRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/backup/request/CreateBackupRequest.java
index b73f7d7..05f3539 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/backup/request/CreateBackupRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/backup/request/CreateBackupRequest.java
@@ -1,28 +1,28 @@
-package dev.lions.unionflow.server.api.dto.backup.request;
-
-import jakarta.validation.constraints.NotBlank;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * Request pour créer une sauvegarde
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class CreateBackupRequest {
-
- @NotBlank(message = "Le nom de la sauvegarde est requis")
- private String name;
-
- private String description;
-
- private String type; // AUTO, MANUAL, RESTORE_POINT
-
- private Boolean includeDatabase;
- private Boolean includeFiles;
- private Boolean includeConfiguration;
-}
+package dev.lions.unionflow.server.api.dto.backup.request;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * Request pour créer une sauvegarde
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CreateBackupRequest {
+
+ @NotBlank(message = "Le nom de la sauvegarde est requis")
+ private String name;
+
+ private String description;
+
+ private String type; // AUTO, MANUAL, RESTORE_POINT
+
+ private Boolean includeDatabase;
+ private Boolean includeFiles;
+ private Boolean includeConfiguration;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/backup/request/RestoreBackupRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/backup/request/RestoreBackupRequest.java
index 910df17..914c059 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/backup/request/RestoreBackupRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/backup/request/RestoreBackupRequest.java
@@ -1,28 +1,28 @@
-package dev.lions.unionflow.server.api.dto.backup.request;
-
-import jakarta.validation.constraints.NotNull;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.UUID;
-
-/**
- * Request pour restaurer une sauvegarde
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class RestoreBackupRequest {
-
- @NotNull(message = "L'ID de la sauvegarde est requis")
- private UUID backupId;
-
- private Boolean restoreDatabase;
- private Boolean restoreFiles;
- private Boolean restoreConfiguration;
-
- private Boolean createRestorePoint; // Créer un point de restauration avant
-}
+package dev.lions.unionflow.server.api.dto.backup.request;
+
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.UUID;
+
+/**
+ * Request pour restaurer une sauvegarde
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RestoreBackupRequest {
+
+ @NotNull(message = "L'ID de la sauvegarde est requis")
+ private UUID backupId;
+
+ private Boolean restoreDatabase;
+ private Boolean restoreFiles;
+ private Boolean restoreConfiguration;
+
+ private Boolean createRestorePoint; // Créer un point de restauration avant
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/backup/request/UpdateBackupConfigRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/backup/request/UpdateBackupConfigRequest.java
index 69770e6..c7e3b35 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/backup/request/UpdateBackupConfigRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/backup/request/UpdateBackupConfigRequest.java
@@ -1,25 +1,25 @@
-package dev.lions.unionflow.server.api.dto.backup.request;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * Request pour mettre à jour la configuration des sauvegardes automatiques
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class UpdateBackupConfigRequest {
-
- private Boolean autoBackupEnabled;
- private String frequency; // HOURLY, DAILY, WEEKLY
- private String retention; // "7 jours", "30 jours", "90 jours", "1 an"
- private Integer retentionDays;
- private String backupTime; // Format HH:mm pour sauvegarde quotidienne
- private Boolean includeDatabase;
- private Boolean includeFiles;
- private Boolean includeConfiguration;
-}
+package dev.lions.unionflow.server.api.dto.backup.request;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * Request pour mettre à jour la configuration des sauvegardes automatiques
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class UpdateBackupConfigRequest {
+
+ private Boolean autoBackupEnabled;
+ private String frequency; // HOURLY, DAILY, WEEKLY
+ private String retention; // "7 jours", "30 jours", "90 jours", "1 an"
+ private Integer retentionDays;
+ private String backupTime; // Format HH:mm pour sauvegarde quotidienne
+ private Boolean includeDatabase;
+ private Boolean includeFiles;
+ private Boolean includeConfiguration;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/backup/response/BackupConfigResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/backup/response/BackupConfigResponse.java
index 3a5ab98..424acb7 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/backup/response/BackupConfigResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/backup/response/BackupConfigResponse.java
@@ -1,33 +1,33 @@
-package dev.lions.unionflow.server.api.dto.backup.response;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-
-/**
- * Response contenant la configuration des sauvegardes automatiques
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class BackupConfigResponse {
-
- private Boolean autoBackupEnabled;
- private String frequency; // HOURLY, DAILY, WEEKLY
- private String retention; // "7 jours", "30 jours", etc.
- private Integer retentionDays;
- private String backupTime; // HH:mm
- private Boolean includeDatabase;
- private Boolean includeFiles;
- private Boolean includeConfiguration;
-
- private LocalDateTime lastBackup;
- private LocalDateTime nextScheduledBackup;
- private Integer totalBackups;
- private Long totalSizeBytes;
- private String totalSizeFormatted;
-}
+package dev.lions.unionflow.server.api.dto.backup.response;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+/**
+ * Response contenant la configuration des sauvegardes automatiques
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BackupConfigResponse {
+
+ private Boolean autoBackupEnabled;
+ private String frequency; // HOURLY, DAILY, WEEKLY
+ private String retention; // "7 jours", "30 jours", etc.
+ private Integer retentionDays;
+ private String backupTime; // HH:mm
+ private Boolean includeDatabase;
+ private Boolean includeFiles;
+ private Boolean includeConfiguration;
+
+ private LocalDateTime lastBackup;
+ private LocalDateTime nextScheduledBackup;
+ private Integer totalBackups;
+ private Long totalSizeBytes;
+ private String totalSizeFormatted;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/backup/response/BackupResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/backup/response/BackupResponse.java
index 44d8d2c..98ba4f7 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/backup/response/BackupResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/backup/response/BackupResponse.java
@@ -1,37 +1,37 @@
-package dev.lions.unionflow.server.api.dto.backup.response;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-import java.util.UUID;
-
-/**
- * Response représentant une sauvegarde
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class BackupResponse {
-
- private UUID id;
- private String name;
- private String description;
- private String type; // AUTO, MANUAL, RESTORE_POINT
- private Long sizeBytes;
- private String sizeFormatted; // ex: "2.3 GB"
- private String status; // PENDING, IN_PROGRESS, COMPLETED, FAILED
- private LocalDateTime createdAt;
- private LocalDateTime completedAt;
- private String createdBy;
-
- private Boolean includesDatabase;
- private Boolean includesFiles;
- private Boolean includesConfiguration;
-
- private String filePath;
- private String errorMessage; // Si status = FAILED
-}
+package dev.lions.unionflow.server.api.dto.backup.response;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+/**
+ * Response représentant une sauvegarde
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class BackupResponse {
+
+ private UUID id;
+ private String name;
+ private String description;
+ private String type; // AUTO, MANUAL, RESTORE_POINT
+ private Long sizeBytes;
+ private String sizeFormatted; // ex: "2.3 GB"
+ private String status; // PENDING, IN_PROGRESS, COMPLETED, FAILED
+ private LocalDateTime createdAt;
+ private LocalDateTime completedAt;
+ private String createdBy;
+
+ private Boolean includesDatabase;
+ private Boolean includesFiles;
+ private Boolean includesConfiguration;
+
+ private String filePath;
+ private String errorMessage; // Si status = FAILED
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/base/BaseDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/base/BaseDTO.java
index 8741e88..f72a6ff 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/base/BaseDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/base/BaseDTO.java
@@ -1,164 +1,164 @@
-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;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * Classe de base pour tous les DTOs UnionFlow Fournit les propriétés communes
- * d'audit et de gestion
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-10
- */
-@Getter
-@Setter
-public abstract class BaseDTO implements Serializable {
-
- @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")
- public LocalDateTime dateCreation;
-
- /** Date de dernière modification */
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- public LocalDateTime dateModification;
-
- /** Utilisateur qui a créé l'enregistrement */
- private String creePar;
-
- /** Utilisateur qui a modifié l'enregistrement en dernier */
- private String modifiePar;
-
- /** Version pour gestion de la concurrence optimiste */
- private Long version;
-
- /** Indicateur si l'enregistrement est actif */
- private Boolean actif;
-
- // Constructeur par défaut
- public BaseDTO() {
- this.dateCreation = LocalDateTime.now();
- this.actif = true;
- this.version = 0L;
- }
-
- // Getters et Setters générés automatiquement par Lombok @Getter/@Setter
-
- // Méthodes utilitaires
-
- /**
- * Marque l'entité comme nouvellement créée
- *
- * @param utilisateur L'utilisateur qui crée l'entité
- */
- public void marquerCommeNouveau(String utilisateur) {
- LocalDateTime maintenant = LocalDateTime.now();
- this.dateCreation = maintenant;
- this.dateModification = maintenant;
- this.creePar = utilisateur;
- this.modifiePar = utilisateur;
- this.version = 0L;
- this.actif = true;
- }
-
- /**
- * Marque l'entité comme modifiée
- *
- * @param utilisateur L'utilisateur qui modifie l'entité
- */
- public void marquerCommeModifie(String utilisateur) {
- this.dateModification = LocalDateTime.now();
- this.modifiePar = utilisateur;
- if (this.version != null) {
- this.version++;
- }
- }
-
- /**
- * Désactive l'entité (soft delete)
- *
- * @param utilisateur L'utilisateur qui désactive l'entité
- */
- public void desactiver(String utilisateur) {
- this.actif = false;
- marquerCommeModifie(utilisateur);
- }
-
- /**
- * Réactive l'entité
- *
- * @param utilisateur L'utilisateur qui réactive l'entité
- */
- public void reactiver(String utilisateur) {
- this.actif = true;
- marquerCommeModifie(utilisateur);
- }
-
- /**
- * Vérifie si l'entité est nouvelle (pas encore persistée)
- *
- * @return true si l'entité est nouvelle
- */
- public boolean isNouveau() {
- return id == null;
- }
-
- /**
- * Vérifie si l'entité est active
- *
- * @return true si l'entité est active
- */
- public boolean isActif() {
- return Boolean.TRUE.equals(actif);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null || getClass() != obj.getClass())
- return false;
-
- BaseDTO baseDTO = (BaseDTO) obj;
- return id != null && id.equals(baseDTO.id);
- }
-
- @Override
- public int hashCode() {
- return id != null ? id.hashCode() : 0;
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName()
- + "{"
- + "id="
- + id
- + ", dateCreation="
- + dateCreation
- + ", dateModification="
- + dateModification
- + ", creePar='"
- + creePar
- + '\''
- + ", modifiePar='"
- + modifiePar
- + '\''
- + ", version="
- + version
- + ", actif="
- + actif
- + '}';
- }
-}
+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;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Classe de base pour tous les DTOs UnionFlow Fournit les propriétés communes
+ * d'audit et de gestion
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2025-01-10
+ */
+@Getter
+@Setter
+public abstract class BaseDTO implements Serializable {
+
+ @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")
+ public LocalDateTime dateCreation;
+
+ /** Date de dernière modification */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ public LocalDateTime dateModification;
+
+ /** Utilisateur qui a créé l'enregistrement */
+ private String creePar;
+
+ /** Utilisateur qui a modifié l'enregistrement en dernier */
+ private String modifiePar;
+
+ /** Version pour gestion de la concurrence optimiste */
+ private Long version;
+
+ /** Indicateur si l'enregistrement est actif */
+ private Boolean actif;
+
+ // Constructeur par défaut
+ public BaseDTO() {
+ this.dateCreation = LocalDateTime.now();
+ this.actif = true;
+ this.version = 0L;
+ }
+
+ // Getters et Setters générés automatiquement par Lombok @Getter/@Setter
+
+ // Méthodes utilitaires
+
+ /**
+ * Marque l'entité comme nouvellement créée
+ *
+ * @param utilisateur L'utilisateur qui crée l'entité
+ */
+ public void marquerCommeNouveau(String utilisateur) {
+ LocalDateTime maintenant = LocalDateTime.now();
+ this.dateCreation = maintenant;
+ this.dateModification = maintenant;
+ this.creePar = utilisateur;
+ this.modifiePar = utilisateur;
+ this.version = 0L;
+ this.actif = true;
+ }
+
+ /**
+ * Marque l'entité comme modifiée
+ *
+ * @param utilisateur L'utilisateur qui modifie l'entité
+ */
+ public void marquerCommeModifie(String utilisateur) {
+ this.dateModification = LocalDateTime.now();
+ this.modifiePar = utilisateur;
+ if (this.version != null) {
+ this.version++;
+ }
+ }
+
+ /**
+ * Désactive l'entité (soft delete)
+ *
+ * @param utilisateur L'utilisateur qui désactive l'entité
+ */
+ public void desactiver(String utilisateur) {
+ this.actif = false;
+ marquerCommeModifie(utilisateur);
+ }
+
+ /**
+ * Réactive l'entité
+ *
+ * @param utilisateur L'utilisateur qui réactive l'entité
+ */
+ public void reactiver(String utilisateur) {
+ this.actif = true;
+ marquerCommeModifie(utilisateur);
+ }
+
+ /**
+ * Vérifie si l'entité est nouvelle (pas encore persistée)
+ *
+ * @return true si l'entité est nouvelle
+ */
+ public boolean isNouveau() {
+ return id == null;
+ }
+
+ /**
+ * Vérifie si l'entité est active
+ *
+ * @return true si l'entité est active
+ */
+ public boolean isActif() {
+ return Boolean.TRUE.equals(actif);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null || getClass() != obj.getClass())
+ return false;
+
+ BaseDTO baseDTO = (BaseDTO) obj;
+ return id != null && id.equals(baseDTO.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return id != null ? id.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName()
+ + "{"
+ + "id="
+ + id
+ + ", dateCreation="
+ + dateCreation
+ + ", dateModification="
+ + dateModification
+ + ", creePar='"
+ + creePar
+ + '\''
+ + ", modifiePar='"
+ + modifiePar
+ + '\''
+ + ", version="
+ + version
+ + ", actif="
+ + actif
+ + '}';
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/base/BaseResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/base/BaseResponse.java
index 8a58f95..c3e8306 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/base/BaseResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/base/BaseResponse.java
@@ -1,79 +1,79 @@
-package dev.lions.unionflow.server.api.dto.base;
-
-import java.time.LocalDateTime;
-import java.util.UUID;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * Classe de base pour les DTOs de réponse.
- *
- *
- * Contient les champs d'audit communs à toutes
- * les réponses : identifiant, dates de
- * création/modification, créateur, et version.
- *
- *
- * Les DTOs de type Request ne doivent
- * pas hériter de cette classe (utiliser
- * des {@code record} sans héritage).
- *
- * @author UnionFlow Team
- * @version 3.0
- * @since 2026-02-21
- */
-@Getter
-@Setter
-public abstract class BaseResponse {
-
- /** Identifiant unique de l'entité. */
- private UUID id;
-
- /** Date de création de l'entité. */
- private LocalDateTime dateCreation;
-
- /** Date de dernière modification. */
- private LocalDateTime dateModification;
-
- /** Email du créateur. */
- private String creePar;
-
- /** Email du dernier modificateur. */
- private String modifiePar;
-
- /** Version pour l'optimistic locking. */
- private Long version;
-
- /** État actif/inactif (soft-delete). */
- private Boolean actif;
-
- /**
- * Comparaison basée sur l'ID.
- * Deux BaseResponse sont égaux si leurs IDs sont égaux et non null.
- *
- * @param obj Objet à comparer
- * @return true si les objets ont le même ID
- */
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null || getClass() != obj.getClass()) {
- return false;
- }
-
- BaseResponse that = (BaseResponse) obj;
- return id != null && id.equals(that.id);
- }
-
- /**
- * Hash code basé sur l'ID.
- *
- * @return Hash code de l'ID, ou 0 si ID null
- */
- @Override
- public int hashCode() {
- return id != null ? id.hashCode() : 0;
- }
-}
+package dev.lions.unionflow.server.api.dto.base;
+
+import java.time.LocalDateTime;
+import java.util.UUID;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * Classe de base pour les DTOs de réponse.
+ *
+ *
+ * Contient les champs d'audit communs à toutes
+ * les réponses : identifiant, dates de
+ * création/modification, créateur, et version.
+ *
+ *
+ * Les DTOs de type Request ne doivent
+ * pas hériter de cette classe (utiliser
+ * des {@code record} sans héritage).
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ * @since 2026-02-21
+ */
+@Getter
+@Setter
+public abstract class BaseResponse {
+
+ /** Identifiant unique de l'entité. */
+ private UUID id;
+
+ /** Date de création de l'entité. */
+ private LocalDateTime dateCreation;
+
+ /** Date de dernière modification. */
+ private LocalDateTime dateModification;
+
+ /** Email du créateur. */
+ private String creePar;
+
+ /** Email du dernier modificateur. */
+ private String modifiePar;
+
+ /** Version pour l'optimistic locking. */
+ private Long version;
+
+ /** État actif/inactif (soft-delete). */
+ private Boolean actif;
+
+ /**
+ * Comparaison basée sur l'ID.
+ * Deux BaseResponse sont égaux si leurs IDs sont égaux et non null.
+ *
+ * @param obj Objet à comparer
+ * @return true si les objets ont le même ID
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+
+ BaseResponse that = (BaseResponse) obj;
+ return id != null && id.equals(that.id);
+ }
+
+ /**
+ * Hash code basé sur l'ID.
+ *
+ * @return Hash code de l'ID, ou 0 si ID null
+ */
+ @Override
+ public int hashCode() {
+ return id != null ? id.hashCode() : 0;
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/base/PageResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/base/PageResponse.java
index f676656..01cc98b 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/base/PageResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/base/PageResponse.java
@@ -1,59 +1,59 @@
-package dev.lions.unionflow.server.api.dto.base;
-
-import java.util.List;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-
-/**
- * Réponse paginée générique.
- *
- *
- * Encapsule une liste d'éléments avec les
- * métadonnées de pagination (page, taille,
- * total). Utilisable pour tout type de réponse
- * paginée.
- *
- * @param type des éléments de la page
- * @author UnionFlow Team
- * @version 3.0
- * @since 2026-02-21
- */
-@Getter
-@AllArgsConstructor
-public class PageResponse {
-
- /** Éléments de la page courante. */
- private final List contenu;
-
- /** Numéro de page courant (0-indexed). */
- private final int page;
-
- /** Taille de la page demandée. */
- private final int taille;
-
- /** Nombre total d'éléments. */
- private final long totalElements;
-
- /** Nombre total de pages. */
- private final int totalPages;
-
- /**
- * Indique s'il existe une page suivante.
- *
- * @return {@code true} si une page suivante
- * existe
- */
- public boolean hasNext() {
- return page < totalPages - 1;
- }
-
- /**
- * Indique s'il existe une page précédente.
- *
- * @return {@code true} si une page précédente
- * existe
- */
- public boolean hasPrevious() {
- return page > 0;
- }
-}
+package dev.lions.unionflow.server.api.dto.base;
+
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * Réponse paginée générique.
+ *
+ *
+ * Encapsule une liste d'éléments avec les
+ * métadonnées de pagination (page, taille,
+ * total). Utilisable pour tout type de réponse
+ * paginée.
+ *
+ * @param type des éléments de la page
+ * @author UnionFlow Team
+ * @version 3.0
+ * @since 2026-02-21
+ */
+@Getter
+@AllArgsConstructor
+public class PageResponse {
+
+ /** Éléments de la page courante. */
+ private final List contenu;
+
+ /** Numéro de page courant (0-indexed). */
+ private final int page;
+
+ /** Taille de la page demandée. */
+ private final int taille;
+
+ /** Nombre total d'éléments. */
+ private final long totalElements;
+
+ /** Nombre total de pages. */
+ private final int totalPages;
+
+ /**
+ * Indique s'il existe une page suivante.
+ *
+ * @return {@code true} si une page suivante
+ * existe
+ */
+ public boolean hasNext() {
+ return page < totalPages - 1;
+ }
+
+ /**
+ * Indique s'il existe une page précédente.
+ *
+ * @return {@code true} si une page précédente
+ * existe
+ */
+ public boolean hasPrevious() {
+ return page > 0;
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/collectefonds/CampagneCollecteResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/collectefonds/CampagneCollecteResponse.java
index 99b32a7..297f7f0 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/collectefonds/CampagneCollecteResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/collectefonds/CampagneCollecteResponse.java
@@ -1,45 +1,45 @@
-package dev.lions.unionflow.server.api.dto.collectefonds;
-
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.collectefonds.StatutCampagneCollecte;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-@Schema(description = "Campagne de levée de fonds (Crowdfunding / ONG)")
-public class CampagneCollecteResponse extends BaseDTO {
-
- private String organisationId;
-
- private String titre;
- private String courteDescription;
- private String htmlDescriptionComplete;
- private String imageBanniereUrl;
-
- @Schema(description = "Objectif monétaire escompté")
- private BigDecimal objectifFinancier;
-
- @Schema(description = "Somme totale déjà récoltée sur cette campagne")
- private BigDecimal montantCollecteActuel;
-
- private Integer nombreDonateurs;
-
- private StatutCampagneCollecte statut;
-
- private LocalDateTime dateOuverture;
- private LocalDateTime dateCloturePrevue;
-
- // Si la page est visible pour les non-membres (donateurs externes)
- private Boolean estPublique;
-}
+package dev.lions.unionflow.server.api.dto.collectefonds;
+
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.collectefonds.StatutCampagneCollecte;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@Schema(description = "Campagne de levée de fonds (Crowdfunding / ONG)")
+public class CampagneCollecteResponse extends BaseDTO {
+
+ private String organisationId;
+
+ private String titre;
+ private String courteDescription;
+ private String htmlDescriptionComplete;
+ private String imageBanniereUrl;
+
+ @Schema(description = "Objectif monétaire escompté")
+ private BigDecimal objectifFinancier;
+
+ @Schema(description = "Somme totale déjà récoltée sur cette campagne")
+ private BigDecimal montantCollecteActuel;
+
+ private Integer nombreDonateurs;
+
+ private StatutCampagneCollecte statut;
+
+ private LocalDateTime dateOuverture;
+ private LocalDateTime dateCloturePrevue;
+
+ // Si la page est visible pour les non-membres (donateurs externes)
+ private Boolean estPublique;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/collectefonds/ContributionCollecteDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/collectefonds/ContributionCollecteDTO.java
index 7d2989f..41a973b 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/collectefonds/ContributionCollecteDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/collectefonds/ContributionCollecteDTO.java
@@ -1,42 +1,42 @@
-package dev.lions.unionflow.server.api.dto.collectefonds;
-
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.wave.StatutTransactionWave;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-@Schema(description = "Don transactionnel reçu pour une campagne de collecte")
-public class ContributionCollecteDTO extends BaseDTO {
-
- private String campagneId;
-
- @Schema(description = "Id du membre (Null si le don est public/externe)")
- private String membreDonateurId;
-
- @Schema(description = "Nom affiché si don public ou pour le mur de contributeurs")
- private String aliasDonateur;
-
- private Boolean estAnonyme;
-
- private BigDecimal montantSoutien;
-
- private String messageSoutien;
-
- private LocalDateTime dateContribution;
-
- // Lien avec la passerelle de paiement
- private String transactionPaiementId;
- private StatutTransactionWave statutPaiement;
-}
+package dev.lions.unionflow.server.api.dto.collectefonds;
+
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.wave.StatutTransactionWave;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@Schema(description = "Don transactionnel reçu pour une campagne de collecte")
+public class ContributionCollecteDTO extends BaseDTO {
+
+ private String campagneId;
+
+ @Schema(description = "Id du membre (Null si le don est public/externe)")
+ private String membreDonateurId;
+
+ @Schema(description = "Nom affiché si don public ou pour le mur de contributeurs")
+ private String aliasDonateur;
+
+ private Boolean estAnonyme;
+
+ private BigDecimal montantSoutien;
+
+ private String messageSoutien;
+
+ private LocalDateTime dateContribution;
+
+ // Lien avec la passerelle de paiement
+ private String transactionPaiementId;
+ private StatutTransactionWave statutPaiement;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/common/PagedResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/common/PagedResponse.java
index c6f2b17..1f5c77f 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/common/PagedResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/common/PagedResponse.java
@@ -1,125 +1,125 @@
-package dev.lions.unionflow.server.api.dto.common;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.List;
-
-/**
- * DTO générique pour les réponses paginées de l'API.
- * Utilisé par tous les endpoints REST qui renvoient des données paginées.
- *
- * @param Type des éléments dans la liste
- * @author UnionFlow Team
- * @version 2.0
- */
-public class PagedResponse {
-
- @JsonProperty("data")
- private List data;
-
- @JsonProperty("total")
- private Long total;
-
- @JsonProperty("page")
- private Integer page;
-
- @JsonProperty("size")
- private Integer size;
-
- @JsonProperty("totalPages")
- private Integer totalPages;
-
- // Constructeurs
- public PagedResponse() {
- }
-
- public PagedResponse(List data, Long total, Integer page, Integer size) {
- this.data = data;
- this.total = total;
- this.page = page;
- this.size = size;
- this.totalPages = calculateTotalPages(total, size);
- }
-
- public PagedResponse(List data, Long total, Integer page, Integer size, Integer totalPages) {
- this.data = data;
- this.total = total;
- this.page = page;
- this.size = size;
- this.totalPages = totalPages;
- }
-
- // Méthode utilitaire pour calculer le nombre de pages
- private Integer calculateTotalPages(Long total, Integer size) {
- if (size == null || size == 0 || total == null) {
- return 0;
- }
- return (int) Math.ceil((double) total / size);
- }
-
- // Getters et setters
- public List getData() {
- return data;
- }
-
- public void setData(List data) {
- this.data = data;
- }
-
- public Long getTotal() {
- return total;
- }
-
- public void setTotal(Long total) {
- this.total = total;
- this.totalPages = calculateTotalPages(total, this.size);
- }
-
- public Integer getPage() {
- return page;
- }
-
- public void setPage(Integer page) {
- this.page = page;
- }
-
- public Integer getSize() {
- return size;
- }
-
- public void setSize(Integer size) {
- this.size = size;
- this.totalPages = calculateTotalPages(this.total, size);
- }
-
- public Integer getTotalPages() {
- return totalPages;
- }
-
- public void setTotalPages(Integer totalPages) {
- this.totalPages = totalPages;
- }
-
- // Méthodes utilitaires
- public boolean hasNext() {
- return page != null && totalPages != null && page < totalPages - 1;
- }
-
- public boolean hasPrevious() {
- return page != null && page > 0;
- }
-
- public boolean isEmpty() {
- return data == null || data.isEmpty();
- }
-
- @Override
- public String toString() {
- return "PagedResponse{" +
- "total=" + total +
- ", page=" + page +
- ", size=" + size +
- ", totalPages=" + totalPages +
- ", itemsCount=" + (data != null ? data.size() : 0) +
- '}';
- }
-}
+package dev.lions.unionflow.server.api.dto.common;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+
+/**
+ * DTO générique pour les réponses paginées de l'API.
+ * Utilisé par tous les endpoints REST qui renvoient des données paginées.
+ *
+ * @param Type des éléments dans la liste
+ * @author UnionFlow Team
+ * @version 2.0
+ */
+public class PagedResponse {
+
+ @JsonProperty("data")
+ private List data;
+
+ @JsonProperty("total")
+ private Long total;
+
+ @JsonProperty("page")
+ private Integer page;
+
+ @JsonProperty("size")
+ private Integer size;
+
+ @JsonProperty("totalPages")
+ private Integer totalPages;
+
+ // Constructeurs
+ public PagedResponse() {
+ }
+
+ public PagedResponse(List data, Long total, Integer page, Integer size) {
+ this.data = data;
+ this.total = total;
+ this.page = page;
+ this.size = size;
+ this.totalPages = calculateTotalPages(total, size);
+ }
+
+ public PagedResponse(List data, Long total, Integer page, Integer size, Integer totalPages) {
+ this.data = data;
+ this.total = total;
+ this.page = page;
+ this.size = size;
+ this.totalPages = totalPages;
+ }
+
+ // Méthode utilitaire pour calculer le nombre de pages
+ private Integer calculateTotalPages(Long total, Integer size) {
+ if (size == null || size == 0 || total == null) {
+ return 0;
+ }
+ return (int) Math.ceil((double) total / size);
+ }
+
+ // Getters et setters
+ public List getData() {
+ return data;
+ }
+
+ public void setData(List data) {
+ this.data = data;
+ }
+
+ public Long getTotal() {
+ return total;
+ }
+
+ public void setTotal(Long total) {
+ this.total = total;
+ this.totalPages = calculateTotalPages(total, this.size);
+ }
+
+ public Integer getPage() {
+ return page;
+ }
+
+ public void setPage(Integer page) {
+ this.page = page;
+ }
+
+ public Integer getSize() {
+ return size;
+ }
+
+ public void setSize(Integer size) {
+ this.size = size;
+ this.totalPages = calculateTotalPages(this.total, size);
+ }
+
+ public Integer getTotalPages() {
+ return totalPages;
+ }
+
+ public void setTotalPages(Integer totalPages) {
+ this.totalPages = totalPages;
+ }
+
+ // Méthodes utilitaires
+ public boolean hasNext() {
+ return page != null && totalPages != null && page < totalPages - 1;
+ }
+
+ public boolean hasPrevious() {
+ return page != null && page > 0;
+ }
+
+ public boolean isEmpty() {
+ return data == null || data.isEmpty();
+ }
+
+ @Override
+ public String toString() {
+ return "PagedResponse{" +
+ "total=" + total +
+ ", page=" + page +
+ ", size=" + size +
+ ", totalPages=" + totalPages +
+ ", itemsCount=" + (data != null ? data.size() : 0) +
+ '}';
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/communication/request/CreateConversationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/communication/request/CreateConversationRequest.java
index 7dabd92..a67dd5d 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/communication/request/CreateConversationRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/communication/request/CreateConversationRequest.java
@@ -1,27 +1,27 @@
-package dev.lions.unionflow.server.api.dto.communication.request;
-
-import dev.lions.unionflow.server.api.enums.communication.ConversationType;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import lombok.Builder;
-
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Request DTO pour créer une conversation
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-03-16
- */
-@Builder
-public record CreateConversationRequest(
- @NotBlank @Size(max = 255) String name,
- @Size(max = 1000) String description,
- @NotNull ConversationType type,
- @NotEmpty List participantIds,
- UUID organisationId
-) {}
+package dev.lions.unionflow.server.api.dto.communication.request;
+
+import dev.lions.unionflow.server.api.enums.communication.ConversationType;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Builder;
+
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Request DTO pour créer une conversation
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-03-16
+ */
+@Builder
+public record CreateConversationRequest(
+ @NotBlank @Size(max = 255) String name,
+ @Size(max = 1000) String description,
+ @NotNull ConversationType type,
+ @NotEmpty List participantIds,
+ UUID organisationId
+) {}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/communication/request/SendMessageRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/communication/request/SendMessageRequest.java
index c98f7f5..c25094a 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/communication/request/SendMessageRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/communication/request/SendMessageRequest.java
@@ -1,29 +1,29 @@
-package dev.lions.unionflow.server.api.dto.communication.request;
-
-import dev.lions.unionflow.server.api.enums.communication.MessagePriority;
-import dev.lions.unionflow.server.api.enums.communication.MessageType;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import lombok.Builder;
-
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Request DTO pour envoyer un message
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-03-16
- */
-@Builder
-public record SendMessageRequest(
- @NotNull UUID conversationId,
- @NotBlank @Size(max = 10000) String content,
- MessageType type,
- MessagePriority priority,
- List recipientIds,
- List recipientRoles,
- List attachments
-) {}
+package dev.lions.unionflow.server.api.dto.communication.request;
+
+import dev.lions.unionflow.server.api.enums.communication.MessagePriority;
+import dev.lions.unionflow.server.api.enums.communication.MessageType;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Builder;
+
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Request DTO pour envoyer un message
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-03-16
+ */
+@Builder
+public record SendMessageRequest(
+ @NotNull UUID conversationId,
+ @NotBlank @Size(max = 10000) String content,
+ MessageType type,
+ MessagePriority priority,
+ List recipientIds,
+ List recipientRoles,
+ List attachments
+) {}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateCompteComptableRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateCompteComptableRequest.java
index 7cb68b2..45f4782 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateCompteComptableRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateCompteComptableRequest.java
@@ -1,28 +1,28 @@
-package dev.lions.unionflow.server.api.dto.comptabilite.request;
-
-import dev.lions.unionflow.server.api.enums.comptabilite.TypeCompteComptable;
-import jakarta.validation.constraints.Max;
-import jakarta.validation.constraints.Min;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import java.math.BigDecimal;
-import lombok.Builder;
-
-/**
- * Requête de création d'un compte comptable.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record CreateCompteComptableRequest(
- @NotBlank(message = "Le numéro de compte est obligatoire") String numeroCompte,
- @NotBlank(message = "Le libellé est obligatoire") String libelle,
- @NotNull(message = "Le type de compte est obligatoire") TypeCompteComptable typeCompte,
- @NotNull(message = "La classe comptable est obligatoire") @Min(value = 1, message = "La classe comptable doit être entre 1 et 7") @Max(value = 7, message = "La classe comptable doit être entre 1 et 7") Integer classeComptable,
- BigDecimal soldeInitial,
- BigDecimal soldeActuel,
- Boolean compteCollectif,
- Boolean compteAnalytique,
- String description) {
-}
+package dev.lions.unionflow.server.api.dto.comptabilite.request;
+
+import dev.lions.unionflow.server.api.enums.comptabilite.TypeCompteComptable;
+import jakarta.validation.constraints.Max;
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import lombok.Builder;
+
+/**
+ * Requête de création d'un compte comptable.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record CreateCompteComptableRequest(
+ @NotBlank(message = "Le numéro de compte est obligatoire") String numeroCompte,
+ @NotBlank(message = "Le libellé est obligatoire") String libelle,
+ @NotNull(message = "Le type de compte est obligatoire") TypeCompteComptable typeCompte,
+ @NotNull(message = "La classe comptable est obligatoire") @Min(value = 1, message = "La classe comptable doit être entre 1 et 7") @Max(value = 7, message = "La classe comptable doit être entre 1 et 7") Integer classeComptable,
+ BigDecimal soldeInitial,
+ BigDecimal soldeActuel,
+ Boolean compteCollectif,
+ Boolean compteAnalytique,
+ String description) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateEcritureComptableRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateEcritureComptableRequest.java
index ddd15cc..1575c7d 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateEcritureComptableRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateEcritureComptableRequest.java
@@ -1,41 +1,41 @@
-package dev.lions.unionflow.server.api.dto.comptabilite.request;
-
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Digits;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.List;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de création d'une écriture comptable.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record CreateEcritureComptableRequest(
- @NotBlank(message = "Le numéro de pièce est obligatoire") String numeroPiece,
-
- @NotNull(message = "La date de l'écriture est obligatoire") LocalDate dateEcriture,
-
- @NotBlank(message = "Le libellé est obligatoire") String libelle,
-
- String reference,
- String lettrage,
- Boolean pointe,
-
- @DecimalMin(value = "0.0") @Digits(integer = 12, fraction = 2) BigDecimal montantDebit,
- @DecimalMin(value = "0.0") @Digits(integer = 12, fraction = 2) BigDecimal montantCredit,
-
- String commentaire,
-
- @NotNull(message = "Le journal est obligatoire") UUID journalId,
- UUID organisationId,
- UUID paiementId,
-
- List lignes) {
-}
+package dev.lions.unionflow.server.api.dto.comptabilite.request;
+
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Digits;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de création d'une écriture comptable.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record CreateEcritureComptableRequest(
+ @NotBlank(message = "Le numéro de pièce est obligatoire") String numeroPiece,
+
+ @NotNull(message = "La date de l'écriture est obligatoire") LocalDate dateEcriture,
+
+ @NotBlank(message = "Le libellé est obligatoire") String libelle,
+
+ String reference,
+ String lettrage,
+ Boolean pointe,
+
+ @DecimalMin(value = "0.0") @Digits(integer = 12, fraction = 2) BigDecimal montantDebit,
+ @DecimalMin(value = "0.0") @Digits(integer = 12, fraction = 2) BigDecimal montantCredit,
+
+ String commentaire,
+
+ @NotNull(message = "Le journal est obligatoire") UUID journalId,
+ UUID organisationId,
+ UUID paiementId,
+
+ List lignes) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateJournalComptableRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateJournalComptableRequest.java
index 5bef23d..b23dd59 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateJournalComptableRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateJournalComptableRequest.java
@@ -1,24 +1,24 @@
-package dev.lions.unionflow.server.api.dto.comptabilite.request;
-
-import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import java.time.LocalDate;
-import lombok.Builder;
-
-/**
- * Requête de création d'un journal comptable.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record CreateJournalComptableRequest(
- @NotBlank(message = "Le code du journal est obligatoire") String code,
- @NotBlank(message = "Le libellé est obligatoire") String libelle,
- @NotNull(message = "Le type de journal est obligatoire") TypeJournalComptable typeJournal,
- LocalDate dateDebut,
- LocalDate dateFin,
- String statut,
- String description) {
-}
+package dev.lions.unionflow.server.api.dto.comptabilite.request;
+
+import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.time.LocalDate;
+import lombok.Builder;
+
+/**
+ * Requête de création d'un journal comptable.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record CreateJournalComptableRequest(
+ @NotBlank(message = "Le code du journal est obligatoire") String code,
+ @NotBlank(message = "Le libellé est obligatoire") String libelle,
+ @NotNull(message = "Le type de journal est obligatoire") TypeJournalComptable typeJournal,
+ LocalDate dateDebut,
+ LocalDate dateFin,
+ String statut,
+ String description) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateLigneEcritureRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateLigneEcritureRequest.java
index f097a19..376c073 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateLigneEcritureRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/CreateLigneEcritureRequest.java
@@ -1,30 +1,30 @@
-package dev.lions.unionflow.server.api.dto.comptabilite.request;
-
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Digits;
-import jakarta.validation.constraints.Min;
-import jakarta.validation.constraints.NotNull;
-import java.math.BigDecimal;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de création d'une ligne d'écriture comptable.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record CreateLigneEcritureRequest(
- @NotNull(message = "Le numéro de ligne est obligatoire") @Min(value = 1, message = "Le numéro de ligne doit être positif") Integer numeroLigne,
-
- @DecimalMin(value = "0.0", message = "Le montant débit doit être positif ou nul") @Digits(integer = 12, fraction = 2) BigDecimal montantDebit,
-
- @DecimalMin(value = "0.0", message = "Le montant crédit doit être positif ou nul") @Digits(integer = 12, fraction = 2) BigDecimal montantCredit,
-
- String libelle,
- String reference,
-
- @NotNull(message = "L'écriture est obligatoire") UUID ecritureId,
- @NotNull(message = "Le compte comptable est obligatoire") UUID compteComptableId) {
-}
+package dev.lions.unionflow.server.api.dto.comptabilite.request;
+
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Digits;
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de création d'une ligne d'écriture comptable.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record CreateLigneEcritureRequest(
+ @NotNull(message = "Le numéro de ligne est obligatoire") @Min(value = 1, message = "Le numéro de ligne doit être positif") Integer numeroLigne,
+
+ @DecimalMin(value = "0.0", message = "Le montant débit doit être positif ou nul") @Digits(integer = 12, fraction = 2) BigDecimal montantDebit,
+
+ @DecimalMin(value = "0.0", message = "Le montant crédit doit être positif ou nul") @Digits(integer = 12, fraction = 2) BigDecimal montantCredit,
+
+ String libelle,
+ String reference,
+
+ @NotNull(message = "L'écriture est obligatoire") UUID ecritureId,
+ @NotNull(message = "Le compte comptable est obligatoire") UUID compteComptableId) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateCompteComptableRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateCompteComptableRequest.java
index 0ecc684..3f271fc 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateCompteComptableRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateCompteComptableRequest.java
@@ -1,26 +1,26 @@
-package dev.lions.unionflow.server.api.dto.comptabilite.request;
-
-import dev.lions.unionflow.server.api.enums.comptabilite.TypeCompteComptable;
-import jakarta.validation.constraints.Max;
-import jakarta.validation.constraints.Min;
-import java.math.BigDecimal;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'un compte comptable.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record UpdateCompteComptableRequest(
- String numeroCompte,
- String libelle,
- TypeCompteComptable typeCompte,
- @Min(value = 1, message = "La classe comptable doit être entre 1 et 7") @Max(value = 7, message = "La classe comptable doit être entre 1 et 7") Integer classeComptable,
- BigDecimal soldeInitial,
- BigDecimal soldeActuel,
- Boolean compteCollectif,
- Boolean compteAnalytique,
- String description) {
-}
+package dev.lions.unionflow.server.api.dto.comptabilite.request;
+
+import dev.lions.unionflow.server.api.enums.comptabilite.TypeCompteComptable;
+import jakarta.validation.constraints.Max;
+import jakarta.validation.constraints.Min;
+import java.math.BigDecimal;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'un compte comptable.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record UpdateCompteComptableRequest(
+ String numeroCompte,
+ String libelle,
+ TypeCompteComptable typeCompte,
+ @Min(value = 1, message = "La classe comptable doit être entre 1 et 7") @Max(value = 7, message = "La classe comptable doit être entre 1 et 7") Integer classeComptable,
+ BigDecimal soldeInitial,
+ BigDecimal soldeActuel,
+ Boolean compteCollectif,
+ Boolean compteAnalytique,
+ String description) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateEcritureComptableRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateEcritureComptableRequest.java
index 322a388..e572bed 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateEcritureComptableRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateEcritureComptableRequest.java
@@ -1,34 +1,34 @@
-package dev.lions.unionflow.server.api.dto.comptabilite.request;
-
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Digits;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.List;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'une écriture comptable.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record UpdateEcritureComptableRequest(
- String numeroPiece,
- LocalDate dateEcriture,
- String libelle,
- String reference,
- String lettrage,
- Boolean pointe,
-
- @DecimalMin(value = "0.0") @Digits(integer = 12, fraction = 2) BigDecimal montantDebit,
- @DecimalMin(value = "0.0") @Digits(integer = 12, fraction = 2) BigDecimal montantCredit,
-
- String commentaire,
- UUID journalId,
- UUID paiementId,
-
- List lignes) {
-}
+package dev.lions.unionflow.server.api.dto.comptabilite.request;
+
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Digits;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'une écriture comptable.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record UpdateEcritureComptableRequest(
+ String numeroPiece,
+ LocalDate dateEcriture,
+ String libelle,
+ String reference,
+ String lettrage,
+ Boolean pointe,
+
+ @DecimalMin(value = "0.0") @Digits(integer = 12, fraction = 2) BigDecimal montantDebit,
+ @DecimalMin(value = "0.0") @Digits(integer = 12, fraction = 2) BigDecimal montantCredit,
+
+ String commentaire,
+ UUID journalId,
+ UUID paiementId,
+
+ List lignes) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateJournalComptableRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateJournalComptableRequest.java
index ea96aaf..4c16c41 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateJournalComptableRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateJournalComptableRequest.java
@@ -1,21 +1,21 @@
-package dev.lions.unionflow.server.api.dto.comptabilite.request;
-
-import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable;
-import java.time.LocalDate;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'un journal comptable.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record UpdateJournalComptableRequest(
- String libelle,
- TypeJournalComptable typeJournal,
- LocalDate dateDebut,
- LocalDate dateFin,
- String statut,
- String description) {
-}
+package dev.lions.unionflow.server.api.dto.comptabilite.request;
+
+import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable;
+import java.time.LocalDate;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'un journal comptable.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record UpdateJournalComptableRequest(
+ String libelle,
+ TypeJournalComptable typeJournal,
+ LocalDate dateDebut,
+ LocalDate dateFin,
+ String statut,
+ String description) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateLigneEcritureRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateLigneEcritureRequest.java
index 8d74a42..78c2df3 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateLigneEcritureRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/request/UpdateLigneEcritureRequest.java
@@ -1,24 +1,24 @@
-package dev.lions.unionflow.server.api.dto.comptabilite.request;
-
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Digits;
-import jakarta.validation.constraints.Min;
-import java.math.BigDecimal;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'une ligne d'écriture comptable.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record UpdateLigneEcritureRequest(
- @Min(value = 1, message = "Le numéro de ligne doit être positif") Integer numeroLigne,
- @DecimalMin(value = "0.0", message = "Le montant débit doit être positif ou nul") @Digits(integer = 12, fraction = 2) BigDecimal montantDebit,
- @DecimalMin(value = "0.0", message = "Le montant crédit doit être positif ou nul") @Digits(integer = 12, fraction = 2) BigDecimal montantCredit,
- String libelle,
- String reference,
- UUID compteComptableId) {
-}
+package dev.lions.unionflow.server.api.dto.comptabilite.request;
+
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Digits;
+import jakarta.validation.constraints.Min;
+import java.math.BigDecimal;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'une ligne d'écriture comptable.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record UpdateLigneEcritureRequest(
+ @Min(value = 1, message = "Le numéro de ligne doit être positif") Integer numeroLigne,
+ @DecimalMin(value = "0.0", message = "Le montant débit doit être positif ou nul") @Digits(integer = 12, fraction = 2) BigDecimal montantDebit,
+ @DecimalMin(value = "0.0", message = "Le montant crédit doit être positif ou nul") @Digits(integer = 12, fraction = 2) BigDecimal montantCredit,
+ String libelle,
+ String reference,
+ UUID compteComptableId) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/CompteComptableResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/CompteComptableResponse.java
index a7aa558..9ce1ff6 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/CompteComptableResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/CompteComptableResponse.java
@@ -1,35 +1,35 @@
-package dev.lions.unionflow.server.api.dto.comptabilite.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import dev.lions.unionflow.server.api.enums.comptabilite.TypeCompteComptable;
-import java.math.BigDecimal;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse détaillée d'un compte comptable.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class CompteComptableResponse extends BaseResponse {
-
- private String numeroCompte;
- private String libelle;
- private TypeCompteComptable typeCompte;
- private Integer classeComptable;
- private BigDecimal soldeInitial;
- private BigDecimal soldeActuel;
- private Boolean compteCollectif;
- private Boolean compteAnalytique;
- private String description;
-}
+package dev.lions.unionflow.server.api.dto.comptabilite.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import dev.lions.unionflow.server.api.enums.comptabilite.TypeCompteComptable;
+import java.math.BigDecimal;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse détaillée d'un compte comptable.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CompteComptableResponse extends BaseResponse {
+
+ private String numeroCompte;
+ private String libelle;
+ private TypeCompteComptable typeCompte;
+ private Integer classeComptable;
+ private BigDecimal soldeInitial;
+ private BigDecimal soldeActuel;
+ private Boolean compteCollectif;
+ private Boolean compteAnalytique;
+ private String description;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/EcritureComptableResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/EcritureComptableResponse.java
index df50568..0cf7fb9 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/EcritureComptableResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/EcritureComptableResponse.java
@@ -1,41 +1,41 @@
-package dev.lions.unionflow.server.api.dto.comptabilite.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.List;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse détaillée d'une écriture comptable.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class EcritureComptableResponse extends BaseResponse {
-
- private String numeroPiece;
- private LocalDate dateEcriture;
- private String libelle;
- private String reference;
- private String lettrage;
- private Boolean pointe;
- private BigDecimal montantDebit;
- private BigDecimal montantCredit;
- private String commentaire;
- private UUID journalId;
- private UUID organisationId;
- private UUID paiementId;
- private List lignes;
-}
+package dev.lions.unionflow.server.api.dto.comptabilite.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse détaillée d'une écriture comptable.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class EcritureComptableResponse extends BaseResponse {
+
+ private String numeroPiece;
+ private LocalDate dateEcriture;
+ private String libelle;
+ private String reference;
+ private String lettrage;
+ private Boolean pointe;
+ private BigDecimal montantDebit;
+ private BigDecimal montantCredit;
+ private String commentaire;
+ private UUID journalId;
+ private UUID organisationId;
+ private UUID paiementId;
+ private List lignes;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/JournalComptableResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/JournalComptableResponse.java
index c075576..24ca32a 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/JournalComptableResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/JournalComptableResponse.java
@@ -1,33 +1,33 @@
-package dev.lions.unionflow.server.api.dto.comptabilite.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable;
-import java.time.LocalDate;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse détaillée d'un journal comptable.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class JournalComptableResponse extends BaseResponse {
-
- private String code;
- private String libelle;
- private TypeJournalComptable typeJournal;
- private LocalDate dateDebut;
- private LocalDate dateFin;
- private String statut;
- private String description;
-}
+package dev.lions.unionflow.server.api.dto.comptabilite.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import dev.lions.unionflow.server.api.enums.comptabilite.TypeJournalComptable;
+import java.time.LocalDate;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse détaillée d'un journal comptable.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class JournalComptableResponse extends BaseResponse {
+
+ private String code;
+ private String libelle;
+ private TypeJournalComptable typeJournal;
+ private LocalDate dateDebut;
+ private LocalDate dateFin;
+ private String statut;
+ private String description;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/LigneEcritureResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/LigneEcritureResponse.java
index e6bab58..33175bf 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/LigneEcritureResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/comptabilite/response/LigneEcritureResponse.java
@@ -1,33 +1,33 @@
-package dev.lions.unionflow.server.api.dto.comptabilite.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.math.BigDecimal;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse détaillée d'une ligne d'écriture comptable.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class LigneEcritureResponse extends BaseResponse {
-
- private Integer numeroLigne;
- private BigDecimal montantDebit;
- private BigDecimal montantCredit;
- private String libelle;
- private String reference;
- private UUID ecritureId;
- private UUID compteComptableId;
-}
+package dev.lions.unionflow.server.api.dto.comptabilite.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.math.BigDecimal;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse détaillée d'une ligne d'écriture comptable.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class LigneEcritureResponse extends BaseResponse {
+
+ private Integer numeroLigne;
+ private BigDecimal montantDebit;
+ private BigDecimal montantCredit;
+ private String libelle;
+ private String reference;
+ private UUID ecritureId;
+ private UUID compteComptableId;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/config/request/CreateConfigurationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/config/request/CreateConfigurationRequest.java
index cd71862..8375d44 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/config/request/CreateConfigurationRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/config/request/CreateConfigurationRequest.java
@@ -1,22 +1,22 @@
-package dev.lions.unionflow.server.api.dto.config.request;
-
-import java.util.Map;
-import lombok.Builder;
-
-/**
- * Requête de création d'une configuration.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record CreateConfigurationRequest(
- String cle,
- String valeur,
- String type,
- String categorie,
- String description,
- Boolean modifiable,
- Boolean visible,
- Map metadonnees) {
-}
+package dev.lions.unionflow.server.api.dto.config.request;
+
+import java.util.Map;
+import lombok.Builder;
+
+/**
+ * Requête de création d'une configuration.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record CreateConfigurationRequest(
+ String cle,
+ String valeur,
+ String type,
+ String categorie,
+ String description,
+ Boolean modifiable,
+ Boolean visible,
+ Map metadonnees) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/config/request/ParametresLcbFtRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/config/request/ParametresLcbFtRequest.java
index 3df99f5..a59335b 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/config/request/ParametresLcbFtRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/config/request/ParametresLcbFtRequest.java
@@ -1,50 +1,50 @@
-package dev.lions.unionflow.server.api.dto.config.request;
-
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.math.BigDecimal;
-
-/**
- * Requête de création/mise à jour des paramètres LCB-FT (Lutte contre le Blanchiment et le Financement du Terrorisme).
- * Définit les seuils au-dessus desquels les justifications d'origine des fonds sont obligatoires.
- *
- * @author lions dev Team
- * @version 1.0
- * @since 2026-03-13
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-@Schema(description = "Paramètres LCB-FT (seuils de vigilance)")
-public class ParametresLcbFtRequest {
-
- @Schema(description = "ID de l'organisation (null pour paramètres plateforme)")
- private String organisationId;
-
- @NotNull(message = "Le montant seuil de justification est obligatoire")
- @DecimalMin(value = "0", message = "Le montant doit être positif ou nul")
- @Schema(description = "Montant au-dessus duquel l'origine des fonds est obligatoire (ex. 500000 XOF)", example = "500000")
- private BigDecimal montantSeuilJustification;
-
- @NotNull(message = "Le montant seuil de validation manuelle est obligatoire")
- @DecimalMin(value = "0", message = "Le montant doit être positif ou nul")
- @Schema(description = "Montant au-dessus duquel une validation manuelle est requise (ex. 1000000 XOF)", example = "1000000")
- private BigDecimal montantSeuilValidationManuelle;
-
- @NotBlank(message = "Le code devise est obligatoire")
- @Size(max = 3, message = "Le code devise doit faire 3 caractères (ISO 4217)")
- @Schema(description = "Code devise ISO 4217 (ex. XOF, EUR, USD)", example = "XOF")
- private String codeDevise;
-
- @Schema(description = "Notes ou commentaires sur la configuration")
- private String notes;
-}
+package dev.lions.unionflow.server.api.dto.config.request;
+
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.math.BigDecimal;
+
+/**
+ * Requête de création/mise à jour des paramètres LCB-FT (Lutte contre le Blanchiment et le Financement du Terrorisme).
+ * Définit les seuils au-dessus desquels les justifications d'origine des fonds sont obligatoires.
+ *
+ * @author lions dev Team
+ * @version 1.0
+ * @since 2026-03-13
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@Schema(description = "Paramètres LCB-FT (seuils de vigilance)")
+public class ParametresLcbFtRequest {
+
+ @Schema(description = "ID de l'organisation (null pour paramètres plateforme)")
+ private String organisationId;
+
+ @NotNull(message = "Le montant seuil de justification est obligatoire")
+ @DecimalMin(value = "0", message = "Le montant doit être positif ou nul")
+ @Schema(description = "Montant au-dessus duquel l'origine des fonds est obligatoire (ex. 500000 XOF)", example = "500000")
+ private BigDecimal montantSeuilJustification;
+
+ @NotNull(message = "Le montant seuil de validation manuelle est obligatoire")
+ @DecimalMin(value = "0", message = "Le montant doit être positif ou nul")
+ @Schema(description = "Montant au-dessus duquel une validation manuelle est requise (ex. 1000000 XOF)", example = "1000000")
+ private BigDecimal montantSeuilValidationManuelle;
+
+ @NotBlank(message = "Le code devise est obligatoire")
+ @Size(max = 3, message = "Le code devise doit faire 3 caractères (ISO 4217)")
+ @Schema(description = "Code devise ISO 4217 (ex. XOF, EUR, USD)", example = "XOF")
+ private String codeDevise;
+
+ @Schema(description = "Notes ou commentaires sur la configuration")
+ private String notes;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/config/request/UpdateConfigurationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/config/request/UpdateConfigurationRequest.java
index 5c89627..cb7d6a2 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/config/request/UpdateConfigurationRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/config/request/UpdateConfigurationRequest.java
@@ -1,22 +1,22 @@
-package dev.lions.unionflow.server.api.dto.config.request;
-
-import java.util.Map;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'une configuration.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record UpdateConfigurationRequest(
- String cle,
- String valeur,
- String type,
- String categorie,
- String description,
- Boolean modifiable,
- Boolean visible,
- Map metadonnees) {
-}
+package dev.lions.unionflow.server.api.dto.config.request;
+
+import java.util.Map;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'une configuration.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record UpdateConfigurationRequest(
+ String cle,
+ String valeur,
+ String type,
+ String categorie,
+ String description,
+ Boolean modifiable,
+ Boolean visible,
+ Map metadonnees) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/config/response/ConfigurationResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/config/response/ConfigurationResponse.java
index 70805c1..46305d2 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/config/response/ConfigurationResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/config/response/ConfigurationResponse.java
@@ -1,33 +1,33 @@
-package dev.lions.unionflow.server.api.dto.config.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.util.Map;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse contenant les données d'une configuration.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class ConfigurationResponse extends BaseResponse {
-
- private String cle;
- private String valeur;
- private String type;
- private String categorie;
- private String description;
- private Boolean modifiable;
- private Boolean visible;
- private Map metadonnees;
-}
+package dev.lions.unionflow.server.api.dto.config.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.util.Map;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse contenant les données d'une configuration.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ConfigurationResponse extends BaseResponse {
+
+ private String cle;
+ private String valeur;
+ private String type;
+ private String categorie;
+ private String description;
+ private Boolean modifiable;
+ private Boolean visible;
+ private Map metadonnees;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/config/response/ParametresLcbFtResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/config/response/ParametresLcbFtResponse.java
index 96adda7..04d4cd6 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/config/response/ParametresLcbFtResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/config/response/ParametresLcbFtResponse.java
@@ -1,49 +1,49 @@
-package dev.lions.unionflow.server.api.dto.config.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.math.BigDecimal;
-
-/**
- * Réponse contenant les paramètres LCB-FT (Lutte contre le Blanchiment et le Financement du Terrorisme).
- * Retourne les seuils configurés pour une organisation ou la plateforme.
- *
- * @author lions dev Team
- * @version 1.0
- * @since 2026-03-13
- */
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-@Schema(description = "Paramètres LCB-FT avec seuils de vigilance")
-public class ParametresLcbFtResponse extends BaseResponse {
-
- @Schema(description = "ID de l'organisation (null si paramètres plateforme)")
- private String organisationId;
-
- @Schema(description = "Nom de l'organisation (null si paramètres plateforme)")
- private String organisationNom;
-
- @Schema(description = "Montant au-dessus duquel l'origine des fonds est obligatoire", example = "500000")
- private BigDecimal montantSeuilJustification;
-
- @Schema(description = "Montant au-dessus duquel une validation manuelle est requise", example = "1000000")
- private BigDecimal montantSeuilValidationManuelle;
-
- @Schema(description = "Code devise ISO 4217", example = "XOF")
- private String codeDevise;
-
- @Schema(description = "Notes ou commentaires sur la configuration")
- private String notes;
-
- @Schema(description = "Indique si ces paramètres s'appliquent à toute la plateforme")
- private Boolean estParametrePlateforme;
-}
+package dev.lions.unionflow.server.api.dto.config.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.math.BigDecimal;
+
+/**
+ * Réponse contenant les paramètres LCB-FT (Lutte contre le Blanchiment et le Financement du Terrorisme).
+ * Retourne les seuils configurés pour une organisation ou la plateforme.
+ *
+ * @author lions dev Team
+ * @version 1.0
+ * @since 2026-03-13
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@Schema(description = "Paramètres LCB-FT avec seuils de vigilance")
+public class ParametresLcbFtResponse extends BaseResponse {
+
+ @Schema(description = "ID de l'organisation (null si paramètres plateforme)")
+ private String organisationId;
+
+ @Schema(description = "Nom de l'organisation (null si paramètres plateforme)")
+ private String organisationNom;
+
+ @Schema(description = "Montant au-dessus duquel l'origine des fonds est obligatoire", example = "500000")
+ private BigDecimal montantSeuilJustification;
+
+ @Schema(description = "Montant au-dessus duquel une validation manuelle est requise", example = "1000000")
+ private BigDecimal montantSeuilValidationManuelle;
+
+ @Schema(description = "Code devise ISO 4217", example = "XOF")
+ private String codeDevise;
+
+ @Schema(description = "Notes ou commentaires sur la configuration")
+ private String notes;
+
+ @Schema(description = "Indique si ces paramètres s'appliquent à toute la plateforme")
+ private Boolean estParametrePlateforme;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/cotisation/request/CreateCotisationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/cotisation/request/CreateCotisationRequest.java
index 9a161d1..c7eae8b 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/cotisation/request/CreateCotisationRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/cotisation/request/CreateCotisationRequest.java
@@ -1,62 +1,62 @@
-package dev.lions.unionflow.server.api.dto.cotisation.request;
-
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Digits;
-import jakarta.validation.constraints.Max;
-import jakarta.validation.constraints.Min;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.UUID;
-
-import lombok.Builder;
-
-/**
- * Requête de création d'une nouvelle cotisation.
- *
- * @param membreId Identifiant du membre concerné.
- * @param typeCotisation Type de cotisation (MENSUELLE, etc.).
- * @param libelle Libellé de la cotisation.
- * @param description Description détaillée.
- * @param montantDu Montant total à payer.
- * @param codeDevise Code ISO de la devise (par défaut XOF).
- * @param dateEcheance Date limite de paiement.
- * @param periode Période concernée (ex: Janvier 2025).
- * @param annee Année de référence.
- * @param mois Mois de référence (1-12, optionnel).
- * @param recurrente Indique si la cotisation est récurrente.
- * @param observations Commentaires libres.
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-02-22
- */
-@Builder
-public record CreateCotisationRequest(
- @NotNull(message = "L'identifiant du membre est obligatoire") UUID membreId,
-
- @NotNull(message = "L'identifiant de l'organisation est obligatoire") UUID organisationId,
-
- @NotBlank(message = "Le type de cotisation est obligatoire") String typeCotisation,
-
- @NotBlank(message = "Le libellé est obligatoire") @Size(max = 100) String libelle,
-
- @Size(max = 500) String description,
-
- @NotNull(message = "Le montant dû est obligatoire") @DecimalMin(value = "0.0", inclusive = false) @Digits(integer = 10, fraction = 2) BigDecimal montantDu,
-
- @Size(min = 3, max = 3) String codeDevise,
-
- @NotNull(message = "La date d'échéance est obligatoire") LocalDate dateEcheance,
-
- @Size(max = 50) String periode,
-
- @Min(2020) @Max(2100) Integer annee,
-
- @Min(1) @Max(12) Integer mois,
-
- Boolean recurrente,
-
- @Size(max = 1000) String observations) {
-}
+package dev.lions.unionflow.server.api.dto.cotisation.request;
+
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Digits;
+import jakarta.validation.constraints.Max;
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.UUID;
+
+import lombok.Builder;
+
+/**
+ * Requête de création d'une nouvelle cotisation.
+ *
+ * @param membreId Identifiant du membre concerné.
+ * @param typeCotisation Type de cotisation (MENSUELLE, etc.).
+ * @param libelle Libellé de la cotisation.
+ * @param description Description détaillée.
+ * @param montantDu Montant total à payer.
+ * @param codeDevise Code ISO de la devise (par défaut XOF).
+ * @param dateEcheance Date limite de paiement.
+ * @param periode Période concernée (ex: Janvier 2025).
+ * @param annee Année de référence.
+ * @param mois Mois de référence (1-12, optionnel).
+ * @param recurrente Indique si la cotisation est récurrente.
+ * @param observations Commentaires libres.
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-02-22
+ */
+@Builder
+public record CreateCotisationRequest(
+ @NotNull(message = "L'identifiant du membre est obligatoire") UUID membreId,
+
+ @NotNull(message = "L'identifiant de l'organisation est obligatoire") UUID organisationId,
+
+ @NotBlank(message = "Le type de cotisation est obligatoire") String typeCotisation,
+
+ @NotBlank(message = "Le libellé est obligatoire") @Size(max = 100) String libelle,
+
+ @Size(max = 500) String description,
+
+ @NotNull(message = "Le montant dû est obligatoire") @DecimalMin(value = "0.0", inclusive = false) @Digits(integer = 10, fraction = 2) BigDecimal montantDu,
+
+ @Size(min = 3, max = 3) String codeDevise,
+
+ @NotNull(message = "La date d'échéance est obligatoire") LocalDate dateEcheance,
+
+ @Size(max = 50) String periode,
+
+ @Min(2020) @Max(2100) Integer annee,
+
+ @Min(1) @Max(12) Integer mois,
+
+ Boolean recurrente,
+
+ @Size(max = 1000) String observations) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/cotisation/request/UpdateCotisationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/cotisation/request/UpdateCotisationRequest.java
index a3cfbd1..00627db 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/cotisation/request/UpdateCotisationRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/cotisation/request/UpdateCotisationRequest.java
@@ -1,48 +1,48 @@
-package dev.lions.unionflow.server.api.dto.cotisation.request;
-
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Digits;
-import jakarta.validation.constraints.Max;
-import jakarta.validation.constraints.Min;
-import jakarta.validation.constraints.Size;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'une cotisation existante.
- *
- * @param libelle Nouveau libellé.
- * @param description Nouvelle description.
- * @param montantDu Nouveau montant dû (si non payé).
- * @param dateEcheance Nouvelle date d'échéance.
- * @param observations Nouvelles observations.
- * @param statut Nouveau statut (validation métier requise).
- * @param annee Année de référence.
- * @param mois Mois de référence.
- * @param recurrente État de récurrence.
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-02-22
- */
-@Builder
-public record UpdateCotisationRequest(
- @Size(max = 100) String libelle,
-
- @Size(max = 500) String description,
-
- @DecimalMin(value = "0.0", inclusive = false) @Digits(integer = 10, fraction = 2) BigDecimal montantDu,
-
- LocalDate dateEcheance,
-
- @Size(max = 1000) String observations,
-
- String statut,
-
- @Min(2020) @Max(2100) Integer annee,
-
- @Min(1) @Max(12) Integer mois,
-
- Boolean recurrente) {
-}
+package dev.lions.unionflow.server.api.dto.cotisation.request;
+
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Digits;
+import jakarta.validation.constraints.Max;
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.Size;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'une cotisation existante.
+ *
+ * @param libelle Nouveau libellé.
+ * @param description Nouvelle description.
+ * @param montantDu Nouveau montant dû (si non payé).
+ * @param dateEcheance Nouvelle date d'échéance.
+ * @param observations Nouvelles observations.
+ * @param statut Nouveau statut (validation métier requise).
+ * @param annee Année de référence.
+ * @param mois Mois de référence.
+ * @param recurrente État de récurrence.
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-02-22
+ */
+@Builder
+public record UpdateCotisationRequest(
+ @Size(max = 100) String libelle,
+
+ @Size(max = 500) String description,
+
+ @DecimalMin(value = "0.0", inclusive = false) @Digits(integer = 10, fraction = 2) BigDecimal montantDu,
+
+ LocalDate dateEcheance,
+
+ @Size(max = 1000) String observations,
+
+ String statut,
+
+ @Min(2020) @Max(2100) Integer annee,
+
+ @Min(1) @Max(12) Integer mois,
+
+ Boolean recurrente) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/cotisation/response/CotisationResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/cotisation/response/CotisationResponse.java
index 4e55c55..49220e4 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/cotisation/response/CotisationResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/cotisation/response/CotisationResponse.java
@@ -1,129 +1,129 @@
-package dev.lions.unionflow.server.api.dto.cotisation.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse détaillée pour une cotisation.
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-02-22
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class CotisationResponse extends BaseResponse {
-
- private String numeroReference;
- private UUID membreId;
- private String nomMembre;
- /** Nom complet (prénom + nom) pour affichage */
- private String nomCompletMembre;
- private String numeroMembre;
- /** Initiales du membre (ex: JD pour Jean Dupont) */
- private String initialesMembre;
- /** Type / statut du membre (ex: Actif, En attente) */
- private String typeMembre;
- private UUID organisationId;
- private String nomOrganisation;
- /** Région de l'organisation (affichage liste) */
- private String regionOrganisation;
- /** Classe CSS icône PrimeFaces pour l'organisation (ex: pi-building) */
- private String iconeOrganisation;
- private String typeCotisation;
- /** Alias pour tri/filtre (type de cotisation) */
- private String type;
- private String typeCotisationLibelle;
- /** Libellé du type pour affichage (alias typeCotisationLibelle) */
- private String typeLibelle;
- /** Sévérité PrimeFaces pour le tag type (info, success, warn, error, secondary) */
- private String typeSeverity;
- /** Classe icône PrimeFaces pour le type (ex: pi-calendar) */
- private String typeIcon;
- private String libelle;
- private String description;
- private BigDecimal montantDu;
- /** Alias pour tri/filtre (montant du) */
- private BigDecimal montant;
- /** Montant formaté pour affichage (ex: "5 000") */
- private String montantFormatte;
- private BigDecimal montantPaye;
- private BigDecimal montantRestant;
- private String codeDevise;
- private String statut;
- private String statutLibelle;
- /** Sévérité PrimeFaces pour le tag statut */
- private String statutSeverity;
- /** Classe icône PrimeFaces pour le statut (ex: pi-check) */
- private String statutIcon;
- private LocalDate dateEcheance;
- /** Date d'échéance formatée pour affichage */
- private String dateEcheanceFormattee;
- /** Classe CSS couleur pour le retard (ex: text-red-500) */
- private String retardCouleur;
- /** Texte affiché pour le retard (ex: "X jours de retard") */
- private String retardTexte;
- /** Date de paiement formatée pour affichage */
- private String datePaiementFormattee;
- /** Icône PrimeFaces pour le mode de paiement */
- private String modePaiementIcon;
- /** Libellé du mode de paiement */
- private String modePaiementLibelle;
- private LocalDateTime datePaiement;
- private String periode;
- private Integer annee;
- private Integer mois;
- private String observations;
- private Boolean recurrente;
- private Integer nombreRappels;
- private LocalDateTime dateDernierRappel;
- private UUID valideParId;
- private String nomValidateur;
- private LocalDateTime dateValidation;
- private Integer pourcentagePaiement;
- private Long joursRetard;
- private Boolean enRetard;
-
- // === MÉTHODES DE FORMATAGE ===
-
- public String getMontantDuFormatte() {
- if (montantDu == null) return "0 FCFA";
- return String.format(java.util.Locale.US, "%,.0f %s", montantDu, codeDevise != null ? codeDevise : "FCFA");
- }
-
- public String getMontantPayeFormatte() {
- if (montantPaye == null) return "0 FCFA";
- return String.format(java.util.Locale.US, "%,.0f %s", montantPaye, codeDevise != null ? codeDevise : "FCFA");
- }
-
- public String getMontantRestantFormatte() {
- if (montantRestant == null) return "0 FCFA";
- return String.format(java.util.Locale.US, "%,.0f %s", montantRestant, codeDevise != null ? codeDevise : "FCFA");
- }
-
- public boolean isMontantRestantPositif() {
- return montantRestant != null && montantRestant.signum() > 0;
- }
-
- /** Alias de {@link #modePaiementLibelle} pour #{cotisation.methodePaiementLibelle}. */
- public String getMethodePaiementLibelle() {
- return modePaiementLibelle;
- }
-
- // Informations de paiement
- private String methodePaiement; // WAVE_MONEY, VIREMENT, ESPECES, CARTE, MOBILE_MONEY
- private String referencePaiement; // Référence externe du paiement
- private String waveSessionId; // ID de session Wave Money pour prélèvements
-}
+package dev.lions.unionflow.server.api.dto.cotisation.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse détaillée pour une cotisation.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-02-22
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CotisationResponse extends BaseResponse {
+
+ private String numeroReference;
+ private UUID membreId;
+ private String nomMembre;
+ /** Nom complet (prénom + nom) pour affichage */
+ private String nomCompletMembre;
+ private String numeroMembre;
+ /** Initiales du membre (ex: JD pour Jean Dupont) */
+ private String initialesMembre;
+ /** Type / statut du membre (ex: Actif, En attente) */
+ private String typeMembre;
+ private UUID organisationId;
+ private String nomOrganisation;
+ /** Région de l'organisation (affichage liste) */
+ private String regionOrganisation;
+ /** Classe CSS icône PrimeFaces pour l'organisation (ex: pi-building) */
+ private String iconeOrganisation;
+ private String typeCotisation;
+ /** Alias pour tri/filtre (type de cotisation) */
+ private String type;
+ private String typeCotisationLibelle;
+ /** Libellé du type pour affichage (alias typeCotisationLibelle) */
+ private String typeLibelle;
+ /** Sévérité PrimeFaces pour le tag type (info, success, warn, error, secondary) */
+ private String typeSeverity;
+ /** Classe icône PrimeFaces pour le type (ex: pi-calendar) */
+ private String typeIcon;
+ private String libelle;
+ private String description;
+ private BigDecimal montantDu;
+ /** Alias pour tri/filtre (montant du) */
+ private BigDecimal montant;
+ /** Montant formaté pour affichage (ex: "5 000") */
+ private String montantFormatte;
+ private BigDecimal montantPaye;
+ private BigDecimal montantRestant;
+ private String codeDevise;
+ private String statut;
+ private String statutLibelle;
+ /** Sévérité PrimeFaces pour le tag statut */
+ private String statutSeverity;
+ /** Classe icône PrimeFaces pour le statut (ex: pi-check) */
+ private String statutIcon;
+ private LocalDate dateEcheance;
+ /** Date d'échéance formatée pour affichage */
+ private String dateEcheanceFormattee;
+ /** Classe CSS couleur pour le retard (ex: text-red-500) */
+ private String retardCouleur;
+ /** Texte affiché pour le retard (ex: "X jours de retard") */
+ private String retardTexte;
+ /** Date de paiement formatée pour affichage */
+ private String datePaiementFormattee;
+ /** Icône PrimeFaces pour le mode de paiement */
+ private String modePaiementIcon;
+ /** Libellé du mode de paiement */
+ private String modePaiementLibelle;
+ private LocalDateTime datePaiement;
+ private String periode;
+ private Integer annee;
+ private Integer mois;
+ private String observations;
+ private Boolean recurrente;
+ private Integer nombreRappels;
+ private LocalDateTime dateDernierRappel;
+ private UUID valideParId;
+ private String nomValidateur;
+ private LocalDateTime dateValidation;
+ private Integer pourcentagePaiement;
+ private Long joursRetard;
+ private Boolean enRetard;
+
+ // === MÉTHODES DE FORMATAGE ===
+
+ public String getMontantDuFormatte() {
+ if (montantDu == null) return "0 FCFA";
+ return String.format(java.util.Locale.US, "%,.0f %s", montantDu, codeDevise != null ? codeDevise : "FCFA");
+ }
+
+ public String getMontantPayeFormatte() {
+ if (montantPaye == null) return "0 FCFA";
+ return String.format(java.util.Locale.US, "%,.0f %s", montantPaye, codeDevise != null ? codeDevise : "FCFA");
+ }
+
+ public String getMontantRestantFormatte() {
+ if (montantRestant == null) return "0 FCFA";
+ return String.format(java.util.Locale.US, "%,.0f %s", montantRestant, codeDevise != null ? codeDevise : "FCFA");
+ }
+
+ public boolean isMontantRestantPositif() {
+ return montantRestant != null && montantRestant.signum() > 0;
+ }
+
+ /** Alias de {@link #modePaiementLibelle} pour #{cotisation.methodePaiementLibelle}. */
+ public String getMethodePaiementLibelle() {
+ return modePaiementLibelle;
+ }
+
+ // Informations de paiement
+ private String methodePaiement; // WAVE_MONEY, VIREMENT, ESPECES, CARTE, MOBILE_MONEY
+ private String referencePaiement; // Référence externe du paiement
+ private String waveSessionId; // ID de session Wave Money pour prélèvements
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/culte/DonReligieuxDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/culte/DonReligieuxDTO.java
index 897482a..593faff 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/culte/DonReligieuxDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/culte/DonReligieuxDTO.java
@@ -1,33 +1,33 @@
-package dev.lions.unionflow.server.api.dto.culte;
-
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.culte.TypeDonReligieux;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class DonReligieuxDTO extends BaseDTO {
-
- private String institutionId; // Mosquée, Église, Paroisse...
-
- // Si relié spécifiquement à un fidèle enregistré
- private String fideleId;
-
- private TypeDonReligieux typeDon;
-
- private BigDecimal montant;
- private LocalDateTime dateEncaissement;
-
- // Utile pour la zakat (Nissab de l'année concernée) ou la dîme périodique
- private String periodeOuNatureAssociee;
-}
+package dev.lions.unionflow.server.api.dto.culte;
+
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.culte.TypeDonReligieux;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class DonReligieuxDTO extends BaseDTO {
+
+ private String institutionId; // Mosquée, Église, Paroisse...
+
+ // Si relié spécifiquement à un fidèle enregistré
+ private String fideleId;
+
+ private TypeDonReligieux typeDon;
+
+ private BigDecimal montant;
+ private LocalDateTime dateEncaissement;
+
+ // Utile pour la zakat (Nissab de l'année concernée) ou la dîme périodique
+ private String periodeOuNatureAssociee;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/DashboardDataResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/DashboardDataResponse.java
index 427b8e9..5cf4d09 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/DashboardDataResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/DashboardDataResponse.java
@@ -1,122 +1,122 @@
-package dev.lions.unionflow.server.api.dto.dashboard;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * DTO principal pour toutes les données du dashboard
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class DashboardDataResponse {
-
- @JsonProperty("stats")
- private DashboardStatsResponse stats;
-
- @JsonProperty("recentActivities")
- private List recentActivities;
-
- @JsonProperty("upcomingEvents")
- private List upcomingEvents;
-
- @JsonProperty("userPreferences")
- private Map userPreferences;
-
- @JsonProperty("organizationId")
- private String organizationId;
-
- @JsonProperty("userId")
- private String userId;
-
- // Méthodes utilitaires
- public Integer getTodayEventsCount() {
- if (upcomingEvents == null) {
- return 0;
- }
-
- return (int) upcomingEvents.stream()
- .filter(event -> event.getIsToday() != null && event.getIsToday())
- .count();
- }
-
- public Integer getTomorrowEventsCount() {
- if (upcomingEvents == null) {
- return 0;
- }
-
- return (int) upcomingEvents.stream()
- .filter(event -> event.getIsTomorrow() != null && event.getIsTomorrow())
- .count();
- }
-
- public Integer getRecentActivitiesCount() {
- if (recentActivities == null) {
- return 0;
- }
-
- return (int) recentActivities.stream()
- .filter(activity -> activity.getIsRecent() != null && activity.getIsRecent())
- .count();
- }
-
- public Integer getTodayActivitiesCount() {
- if (recentActivities == null) {
- return 0;
- }
-
- return (int) recentActivities.stream()
- .filter(activity -> activity.getIsToday() != null && activity.getIsToday())
- .count();
- }
-
- public Boolean getHasUpcomingEvents() {
- return upcomingEvents != null && !upcomingEvents.isEmpty();
- }
-
- public Boolean getHasRecentActivities() {
- return recentActivities != null && !recentActivities.isEmpty();
- }
-
- public String getThemePreference() {
- if (userPreferences == null) {
- return "royal_teal";
- }
- return (String) userPreferences.getOrDefault("theme", "royal_teal");
- }
-
- public String getLanguagePreference() {
- if (userPreferences == null) {
- return "fr";
- }
- return (String) userPreferences.getOrDefault("language", "fr");
- }
-
- public Boolean getNotificationsEnabled() {
- if (userPreferences == null) {
- return true;
- }
- return (Boolean) userPreferences.getOrDefault("notifications", true);
- }
-
- public Boolean getAutoRefreshEnabled() {
- if (userPreferences == null) {
- return true;
- }
- return (Boolean) userPreferences.getOrDefault("autoRefresh", true);
- }
-
- public Integer getRefreshInterval() {
- if (userPreferences == null) {
- return 300; // 5 minutes par défaut
- }
- return (Integer) userPreferences.getOrDefault("refreshInterval", 300);
- }
-}
+package dev.lions.unionflow.server.api.dto.dashboard;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * DTO principal pour toutes les données du dashboard
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DashboardDataResponse {
+
+ @JsonProperty("stats")
+ private DashboardStatsResponse stats;
+
+ @JsonProperty("recentActivities")
+ private List recentActivities;
+
+ @JsonProperty("upcomingEvents")
+ private List upcomingEvents;
+
+ @JsonProperty("userPreferences")
+ private Map userPreferences;
+
+ @JsonProperty("organizationId")
+ private String organizationId;
+
+ @JsonProperty("userId")
+ private String userId;
+
+ // Méthodes utilitaires
+ public Integer getTodayEventsCount() {
+ if (upcomingEvents == null) {
+ return 0;
+ }
+
+ return (int) upcomingEvents.stream()
+ .filter(event -> event.getIsToday() != null && event.getIsToday())
+ .count();
+ }
+
+ public Integer getTomorrowEventsCount() {
+ if (upcomingEvents == null) {
+ return 0;
+ }
+
+ return (int) upcomingEvents.stream()
+ .filter(event -> event.getIsTomorrow() != null && event.getIsTomorrow())
+ .count();
+ }
+
+ public Integer getRecentActivitiesCount() {
+ if (recentActivities == null) {
+ return 0;
+ }
+
+ return (int) recentActivities.stream()
+ .filter(activity -> activity.getIsRecent() != null && activity.getIsRecent())
+ .count();
+ }
+
+ public Integer getTodayActivitiesCount() {
+ if (recentActivities == null) {
+ return 0;
+ }
+
+ return (int) recentActivities.stream()
+ .filter(activity -> activity.getIsToday() != null && activity.getIsToday())
+ .count();
+ }
+
+ public Boolean getHasUpcomingEvents() {
+ return upcomingEvents != null && !upcomingEvents.isEmpty();
+ }
+
+ public Boolean getHasRecentActivities() {
+ return recentActivities != null && !recentActivities.isEmpty();
+ }
+
+ public String getThemePreference() {
+ if (userPreferences == null) {
+ return "royal_teal";
+ }
+ return (String) userPreferences.getOrDefault("theme", "royal_teal");
+ }
+
+ public String getLanguagePreference() {
+ if (userPreferences == null) {
+ return "fr";
+ }
+ return (String) userPreferences.getOrDefault("language", "fr");
+ }
+
+ public Boolean getNotificationsEnabled() {
+ if (userPreferences == null) {
+ return true;
+ }
+ return (Boolean) userPreferences.getOrDefault("notifications", true);
+ }
+
+ public Boolean getAutoRefreshEnabled() {
+ if (userPreferences == null) {
+ return true;
+ }
+ return (Boolean) userPreferences.getOrDefault("autoRefresh", true);
+ }
+
+ public Integer getRefreshInterval() {
+ if (userPreferences == null) {
+ return 300; // 5 minutes par défaut
+ }
+ return (Integer) userPreferences.getOrDefault("refreshInterval", 300);
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/DashboardStatsResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/DashboardStatsResponse.java
index 3bfbe3d..904e1e6 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/DashboardStatsResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/DashboardStatsResponse.java
@@ -1,119 +1,119 @@
-package dev.lions.unionflow.server.api.dto.dashboard;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Map;
-
-/**
- * DTO pour les statistiques du dashboard
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class DashboardStatsResponse {
-
- @JsonProperty("totalMembers")
- private Integer totalMembers;
-
- @JsonProperty("activeMembers")
- private Integer activeMembers;
-
- @JsonProperty("totalEvents")
- private Integer totalEvents;
-
- @JsonProperty("upcomingEvents")
- private Integer upcomingEvents;
-
- @JsonProperty("totalContributions")
- private Integer totalContributions;
-
- @JsonProperty("totalContributionAmount")
- private Double totalContributionAmount;
-
- @JsonProperty("pendingRequests")
- private Integer pendingRequests;
-
- @JsonProperty("completedProjects")
- private Integer completedProjects;
-
- @JsonProperty("monthlyGrowth")
- private Double monthlyGrowth;
-
- @JsonProperty("engagementRate")
- private Double engagementRate;
-
- @JsonProperty("lastUpdated")
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime lastUpdated;
-
- /**
- * Nombre total d'organisations dans le système (SuperAdmin uniquement)
- */
- @JsonProperty("totalOrganizations")
- private Integer totalOrganizations;
-
- /**
- * Répartition des organisations par type
- * Exemple: {"Mutuelle": 15, "Coopérative": 8, "Tontine": 5, "Autre": 3}
- */
- @JsonProperty("organizationTypeDistribution")
- private Map organizationTypeDistribution;
-
- /**
- * Données historiques mensuelles pour les graphiques (12 derniers mois)
- */
- @JsonProperty("monthlyHistoricalData")
- private List monthlyHistoricalData;
-
- // Méthodes utilitaires
- public String getFormattedContributionAmount() {
- if (totalContributionAmount == null) {
- return "0";
- }
-
- if (totalContributionAmount >= 1_000_000) {
- return String.format("%.1fM", totalContributionAmount / 1_000_000);
- } else if (totalContributionAmount >= 1_000) {
- return String.format("%.0fK", totalContributionAmount / 1_000);
- } else {
- return String.format("%.0f", totalContributionAmount);
- }
- }
-
- public Boolean getHasGrowth() {
- return monthlyGrowth != null && monthlyGrowth > 0;
- }
-
- public Boolean getIsHighEngagement() {
- return engagementRate != null && engagementRate > 0.7;
- }
-
- public Double getInactiveMembers() {
- if (totalMembers == null || activeMembers == null) {
- return 0.0;
- }
- return (double) (totalMembers - activeMembers);
- }
-
- public Double getActiveMemberPercentage() {
- if (totalMembers == null || activeMembers == null || totalMembers == 0) {
- return 0.0;
- }
- return (double) activeMembers / totalMembers * 100;
- }
-
- public Double getEngagementPercentage() {
- if (engagementRate == null) {
- return 0.0;
- }
- return engagementRate * 100;
- }
-}
+package dev.lions.unionflow.server.api.dto.dashboard;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * DTO pour les statistiques du dashboard
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DashboardStatsResponse {
+
+ @JsonProperty("totalMembers")
+ private Integer totalMembers;
+
+ @JsonProperty("activeMembers")
+ private Integer activeMembers;
+
+ @JsonProperty("totalEvents")
+ private Integer totalEvents;
+
+ @JsonProperty("upcomingEvents")
+ private Integer upcomingEvents;
+
+ @JsonProperty("totalContributions")
+ private Integer totalContributions;
+
+ @JsonProperty("totalContributionAmount")
+ private Double totalContributionAmount;
+
+ @JsonProperty("pendingRequests")
+ private Integer pendingRequests;
+
+ @JsonProperty("completedProjects")
+ private Integer completedProjects;
+
+ @JsonProperty("monthlyGrowth")
+ private Double monthlyGrowth;
+
+ @JsonProperty("engagementRate")
+ private Double engagementRate;
+
+ @JsonProperty("lastUpdated")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime lastUpdated;
+
+ /**
+ * Nombre total d'organisations dans le système (SuperAdmin uniquement)
+ */
+ @JsonProperty("totalOrganizations")
+ private Integer totalOrganizations;
+
+ /**
+ * Répartition des organisations par type
+ * Exemple: {"Mutuelle": 15, "Coopérative": 8, "Tontine": 5, "Autre": 3}
+ */
+ @JsonProperty("organizationTypeDistribution")
+ private Map organizationTypeDistribution;
+
+ /**
+ * Données historiques mensuelles pour les graphiques (12 derniers mois)
+ */
+ @JsonProperty("monthlyHistoricalData")
+ private List monthlyHistoricalData;
+
+ // Méthodes utilitaires
+ public String getFormattedContributionAmount() {
+ if (totalContributionAmount == null) {
+ return "0";
+ }
+
+ if (totalContributionAmount >= 1_000_000) {
+ return String.format("%.1fM", totalContributionAmount / 1_000_000);
+ } else if (totalContributionAmount >= 1_000) {
+ return String.format("%.0fK", totalContributionAmount / 1_000);
+ } else {
+ return String.format("%.0f", totalContributionAmount);
+ }
+ }
+
+ public Boolean getHasGrowth() {
+ return monthlyGrowth != null && monthlyGrowth > 0;
+ }
+
+ public Boolean getIsHighEngagement() {
+ return engagementRate != null && engagementRate > 0.7;
+ }
+
+ public Double getInactiveMembers() {
+ if (totalMembers == null || activeMembers == null) {
+ return 0.0;
+ }
+ return (double) (totalMembers - activeMembers);
+ }
+
+ public Double getActiveMemberPercentage() {
+ if (totalMembers == null || activeMembers == null || totalMembers == 0) {
+ return 0.0;
+ }
+ return (double) activeMembers / totalMembers * 100;
+ }
+
+ public Double getEngagementPercentage() {
+ if (engagementRate == null) {
+ return 0.0;
+ }
+ return engagementRate * 100;
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/MonthlyStatDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/MonthlyStatDTO.java
index 5681248..7002f2b 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/MonthlyStatDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/MonthlyStatDTO.java
@@ -1,70 +1,70 @@
-package dev.lions.unionflow.server.api.dto.dashboard;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * DTO pour les statistiques mensuelles historiques
- * Utilisé pour générer des graphiques de croissance sur 12 mois
- *
- * @author UnionFlow Team
- * @version 2.0
- * @since 2026-03-07
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class MonthlyStatDTO {
-
- /**
- * Mois au format "2026-01", "2026-02", etc.
- */
- @JsonProperty("month")
- private String month;
-
- /**
- * Nombre de membres ce mois-là
- */
- @JsonProperty("totalMembers")
- private Integer totalMembers;
-
- /**
- * Nombre de membres actifs ce mois-là
- */
- @JsonProperty("activeMembers")
- private Integer activeMembers;
-
- /**
- * Montant total des contributions ce mois-là
- */
- @JsonProperty("contributionAmount")
- private Double contributionAmount;
-
- /**
- * Nombre d'événements organisés ce mois-là
- */
- @JsonProperty("eventsCount")
- private Integer eventsCount;
-
- /**
- * Taux d'engagement ce mois-là
- */
- @JsonProperty("engagementRate")
- private Double engagementRate;
-
- /**
- * Nombre de nouveaux membres ce mois-là
- */
- @JsonProperty("newMembers")
- private Integer newMembers;
-
- /**
- * Nombre de cotisations payées ce mois-là
- */
- @JsonProperty("contributionsCount")
- private Integer contributionsCount;
-}
+package dev.lions.unionflow.server.api.dto.dashboard;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * DTO pour les statistiques mensuelles historiques
+ * Utilisé pour générer des graphiques de croissance sur 12 mois
+ *
+ * @author UnionFlow Team
+ * @version 2.0
+ * @since 2026-03-07
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MonthlyStatDTO {
+
+ /**
+ * Mois au format "2026-01", "2026-02", etc.
+ */
+ @JsonProperty("month")
+ private String month;
+
+ /**
+ * Nombre de membres ce mois-là
+ */
+ @JsonProperty("totalMembers")
+ private Integer totalMembers;
+
+ /**
+ * Nombre de membres actifs ce mois-là
+ */
+ @JsonProperty("activeMembers")
+ private Integer activeMembers;
+
+ /**
+ * Montant total des contributions ce mois-là
+ */
+ @JsonProperty("contributionAmount")
+ private Double contributionAmount;
+
+ /**
+ * Nombre d'événements organisés ce mois-là
+ */
+ @JsonProperty("eventsCount")
+ private Integer eventsCount;
+
+ /**
+ * Taux d'engagement ce mois-là
+ */
+ @JsonProperty("engagementRate")
+ private Double engagementRate;
+
+ /**
+ * Nombre de nouveaux membres ce mois-là
+ */
+ @JsonProperty("newMembers")
+ private Integer newMembers;
+
+ /**
+ * Nombre de cotisations payées ce mois-là
+ */
+ @JsonProperty("contributionsCount")
+ private Integer contributionsCount;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/RecentActivityResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/RecentActivityResponse.java
index ddf2296..63152c3 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/RecentActivityResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/RecentActivityResponse.java
@@ -1,130 +1,130 @@
-package dev.lions.unionflow.server.api.dto.dashboard;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-import java.time.temporal.ChronoUnit;
-
-/**
- * DTO pour les activités récentes du dashboard
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class RecentActivityResponse {
-
- @JsonProperty("id")
- private String id;
-
- @JsonProperty("type")
- private String type;
-
- @JsonProperty("title")
- private String title;
-
- @JsonProperty("description")
- private String description;
-
- @JsonProperty("userName")
- private String userName;
-
- @JsonProperty("timestamp")
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime timestamp;
-
- @JsonProperty("userAvatar")
- private String userAvatar;
-
- @JsonProperty("actionUrl")
- private String actionUrl;
-
- // Méthodes utilitaires
- public String getTimeAgo() {
- if (timestamp == null) {
- return "";
- }
-
- LocalDateTime now = LocalDateTime.now();
- long minutes = ChronoUnit.MINUTES.between(timestamp, now);
- long hours = ChronoUnit.HOURS.between(timestamp, now);
- long days = ChronoUnit.DAYS.between(timestamp, now);
-
- if (minutes < 60) {
- return minutes + "min";
- } else if (hours < 24) {
- return hours + "h";
- } else if (days < 7) {
- return days + "j";
- } else {
- long weeks = days / 7;
- return weeks + "sem";
- }
- }
-
- public String getActivityIcon() {
- if (type == null) {
- return "help_outline";
- }
-
- switch (type.toLowerCase()) {
- case "member":
- return "person";
- case "event":
- return "event";
- case "contribution":
- return "payment";
- case "organization":
- return "business";
- case "system":
- return "settings";
- default:
- return "info";
- }
- }
-
- public String getActivityColor() {
- if (type == null) {
- return "#6B7280"; // grey
- }
-
- switch (type.toLowerCase()) {
- case "member":
- return "#10B981"; // success
- case "event":
- return "#3B82F6"; // info
- case "contribution":
- return "#008B8B"; // teal blue
- case "organization":
- return "#4169E1"; // royal blue
- case "system":
- return "#6B7280"; // grey
- default:
- return "#6B7280"; // grey
- }
- }
-
- public Boolean getIsRecent() {
- if (timestamp == null) {
- return false;
- }
-
- LocalDateTime now = LocalDateTime.now();
- long hours = ChronoUnit.HOURS.between(timestamp, now);
- return hours < 24;
- }
-
- public Boolean getIsToday() {
- if (timestamp == null) {
- return false;
- }
-
- LocalDateTime now = LocalDateTime.now();
- return timestamp.toLocalDate().equals(now.toLocalDate());
- }
-}
+package dev.lions.unionflow.server.api.dto.dashboard;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
+
+/**
+ * DTO pour les activités récentes du dashboard
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RecentActivityResponse {
+
+ @JsonProperty("id")
+ private String id;
+
+ @JsonProperty("type")
+ private String type;
+
+ @JsonProperty("title")
+ private String title;
+
+ @JsonProperty("description")
+ private String description;
+
+ @JsonProperty("userName")
+ private String userName;
+
+ @JsonProperty("timestamp")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime timestamp;
+
+ @JsonProperty("userAvatar")
+ private String userAvatar;
+
+ @JsonProperty("actionUrl")
+ private String actionUrl;
+
+ // Méthodes utilitaires
+ public String getTimeAgo() {
+ if (timestamp == null) {
+ return "";
+ }
+
+ LocalDateTime now = LocalDateTime.now();
+ long minutes = ChronoUnit.MINUTES.between(timestamp, now);
+ long hours = ChronoUnit.HOURS.between(timestamp, now);
+ long days = ChronoUnit.DAYS.between(timestamp, now);
+
+ if (minutes < 60) {
+ return minutes + "min";
+ } else if (hours < 24) {
+ return hours + "h";
+ } else if (days < 7) {
+ return days + "j";
+ } else {
+ long weeks = days / 7;
+ return weeks + "sem";
+ }
+ }
+
+ public String getActivityIcon() {
+ if (type == null) {
+ return "help_outline";
+ }
+
+ switch (type.toLowerCase()) {
+ case "member":
+ return "person";
+ case "event":
+ return "event";
+ case "contribution":
+ return "payment";
+ case "organization":
+ return "business";
+ case "system":
+ return "settings";
+ default:
+ return "info";
+ }
+ }
+
+ public String getActivityColor() {
+ if (type == null) {
+ return "#6B7280"; // grey
+ }
+
+ switch (type.toLowerCase()) {
+ case "member":
+ return "#10B981"; // success
+ case "event":
+ return "#3B82F6"; // info
+ case "contribution":
+ return "#008B8B"; // teal blue
+ case "organization":
+ return "#4169E1"; // royal blue
+ case "system":
+ return "#6B7280"; // grey
+ default:
+ return "#6B7280"; // grey
+ }
+ }
+
+ public Boolean getIsRecent() {
+ if (timestamp == null) {
+ return false;
+ }
+
+ LocalDateTime now = LocalDateTime.now();
+ long hours = ChronoUnit.HOURS.between(timestamp, now);
+ return hours < 24;
+ }
+
+ public Boolean getIsToday() {
+ if (timestamp == null) {
+ return false;
+ }
+
+ LocalDateTime now = LocalDateTime.now();
+ return timestamp.toLocalDate().equals(now.toLocalDate());
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/UpcomingEventResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/UpcomingEventResponse.java
index e446e97..77eb664 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/UpcomingEventResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/dashboard/UpcomingEventResponse.java
@@ -1,183 +1,183 @@
-package dev.lions.unionflow.server.api.dto.dashboard;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDateTime;
-import java.time.temporal.ChronoUnit;
-import java.util.List;
-
-/**
- * DTO pour les événements à venir du dashboard
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class UpcomingEventResponse {
-
- @JsonProperty("id")
- private String id;
-
- @JsonProperty("title")
- private String title;
-
- @JsonProperty("description")
- private String description;
-
- @JsonProperty("startDate")
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime startDate;
-
- @JsonProperty("endDate")
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime endDate;
-
- @JsonProperty("location")
- private String location;
-
- @JsonProperty("maxParticipants")
- private Integer maxParticipants;
-
- @JsonProperty("currentParticipants")
- private Integer currentParticipants;
-
- @JsonProperty("status")
- private String status;
-
- @JsonProperty("imageUrl")
- private String imageUrl;
-
- @JsonProperty("tags")
- private List tags;
-
- // Méthodes utilitaires
- public String getDaysUntilEvent() {
- return getDaysUntilEvent(LocalDateTime.now());
- }
-
- /**
- * Version testable avec une date de référence fixe (même package).
- */
- String getDaysUntilEvent(LocalDateTime now) {
- if (startDate == null) {
- return "";
- }
- long days = ChronoUnit.DAYS.between(now.toLocalDate(), startDate.toLocalDate());
- long hours = ChronoUnit.HOURS.between(now, startDate);
-
- if (days < 0) {
- return "En cours";
- }
- if (days == 0) {
- // Vérifier si l'événement est déjà passé (même si moins d'1h)
- if (startDate.isBefore(now)) {
- return "En cours";
- } else if (hours < 2) {
- return "Bientôt";
- } else {
- return "Aujourd'hui";
- }
- } else if (days == 1) {
- return "Demain";
- } else if (days < 7) {
- return "Dans " + days + " jours";
- } else {
- long weeks = days / 7;
- return "Dans " + weeks + " semaine" + (weeks > 1 ? "s" : "");
- }
- }
-
- public Double getFillPercentage() {
- if (maxParticipants == null || currentParticipants == null || maxParticipants == 0) {
- return 0.0;
- }
- return (double) currentParticipants / maxParticipants * 100;
- }
-
- public Boolean getIsFull() {
- if (maxParticipants == null || currentParticipants == null) {
- return false;
- }
- return currentParticipants >= maxParticipants;
- }
-
- public Boolean getIsAlmostFull() {
- Double fillPercentage = getFillPercentage();
- return fillPercentage >= 80.0 && fillPercentage < 100.0;
- }
-
- public Boolean getIsToday() {
- if (startDate == null) {
- return false;
- }
-
- LocalDateTime now = LocalDateTime.now();
- return startDate.toLocalDate().equals(now.toLocalDate());
- }
-
- public Boolean getIsTomorrow() {
- if (startDate == null) {
- return false;
- }
-
- LocalDateTime now = LocalDateTime.now();
- return startDate.toLocalDate().equals(now.toLocalDate().plusDays(1));
- }
-
- public String getStatusColor() {
- if (status == null) {
- return "#6B7280"; // grey
- }
-
- switch (status.toLowerCase()) {
- case "confirmed":
- return "#10B981"; // success
- case "open":
- return "#3B82F6"; // info
- case "cancelled":
- return "#EF4444"; // error
- case "postponed":
- return "#F59E0B"; // warning
- default:
- return "#6B7280"; // grey
- }
- }
-
- public String getStatusLabel() {
- if (status == null) {
- return "Inconnu";
- }
-
- switch (status.toLowerCase()) {
- case "confirmed":
- return "Confirmé";
- case "open":
- return "Ouvert";
- case "cancelled":
- return "Annulé";
- case "postponed":
- return "Reporté";
- default:
- return status;
- }
- }
-
- public Integer getAvailableSpots() {
- if (maxParticipants == null || currentParticipants == null) {
- return 0;
- }
- return Math.max(0, maxParticipants - currentParticipants);
- }
-
- public String getParticipationSummary() {
- if (maxParticipants == null || currentParticipants == null) {
- return "0/0 participants";
- }
- return currentParticipants + "/" + maxParticipants + " participants";
- }
-}
+package dev.lions.unionflow.server.api.dto.dashboard;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoUnit;
+import java.util.List;
+
+/**
+ * DTO pour les événements à venir du dashboard
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class UpcomingEventResponse {
+
+ @JsonProperty("id")
+ private String id;
+
+ @JsonProperty("title")
+ private String title;
+
+ @JsonProperty("description")
+ private String description;
+
+ @JsonProperty("startDate")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime startDate;
+
+ @JsonProperty("endDate")
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime endDate;
+
+ @JsonProperty("location")
+ private String location;
+
+ @JsonProperty("maxParticipants")
+ private Integer maxParticipants;
+
+ @JsonProperty("currentParticipants")
+ private Integer currentParticipants;
+
+ @JsonProperty("status")
+ private String status;
+
+ @JsonProperty("imageUrl")
+ private String imageUrl;
+
+ @JsonProperty("tags")
+ private List tags;
+
+ // Méthodes utilitaires
+ public String getDaysUntilEvent() {
+ return getDaysUntilEvent(LocalDateTime.now());
+ }
+
+ /**
+ * Version testable avec une date de référence fixe (même package).
+ */
+ String getDaysUntilEvent(LocalDateTime now) {
+ if (startDate == null) {
+ return "";
+ }
+ long days = ChronoUnit.DAYS.between(now.toLocalDate(), startDate.toLocalDate());
+ long hours = ChronoUnit.HOURS.between(now, startDate);
+
+ if (days < 0) {
+ return "En cours";
+ }
+ if (days == 0) {
+ // Vérifier si l'événement est déjà passé (même si moins d'1h)
+ if (startDate.isBefore(now)) {
+ return "En cours";
+ } else if (hours < 2) {
+ return "Bientôt";
+ } else {
+ return "Aujourd'hui";
+ }
+ } else if (days == 1) {
+ return "Demain";
+ } else if (days < 7) {
+ return "Dans " + days + " jours";
+ } else {
+ long weeks = days / 7;
+ return "Dans " + weeks + " semaine" + (weeks > 1 ? "s" : "");
+ }
+ }
+
+ public Double getFillPercentage() {
+ if (maxParticipants == null || currentParticipants == null || maxParticipants == 0) {
+ return 0.0;
+ }
+ return (double) currentParticipants / maxParticipants * 100;
+ }
+
+ public Boolean getIsFull() {
+ if (maxParticipants == null || currentParticipants == null) {
+ return false;
+ }
+ return currentParticipants >= maxParticipants;
+ }
+
+ public Boolean getIsAlmostFull() {
+ Double fillPercentage = getFillPercentage();
+ return fillPercentage >= 80.0 && fillPercentage < 100.0;
+ }
+
+ public Boolean getIsToday() {
+ if (startDate == null) {
+ return false;
+ }
+
+ LocalDateTime now = LocalDateTime.now();
+ return startDate.toLocalDate().equals(now.toLocalDate());
+ }
+
+ public Boolean getIsTomorrow() {
+ if (startDate == null) {
+ return false;
+ }
+
+ LocalDateTime now = LocalDateTime.now();
+ return startDate.toLocalDate().equals(now.toLocalDate().plusDays(1));
+ }
+
+ public String getStatusColor() {
+ if (status == null) {
+ return "#6B7280"; // grey
+ }
+
+ switch (status.toLowerCase()) {
+ case "confirmed":
+ return "#10B981"; // success
+ case "open":
+ return "#3B82F6"; // info
+ case "cancelled":
+ return "#EF4444"; // error
+ case "postponed":
+ return "#F59E0B"; // warning
+ default:
+ return "#6B7280"; // grey
+ }
+ }
+
+ public String getStatusLabel() {
+ if (status == null) {
+ return "Inconnu";
+ }
+
+ switch (status.toLowerCase()) {
+ case "confirmed":
+ return "Confirmé";
+ case "open":
+ return "Ouvert";
+ case "cancelled":
+ return "Annulé";
+ case "postponed":
+ return "Reporté";
+ default:
+ return status;
+ }
+ }
+
+ public Integer getAvailableSpots() {
+ if (maxParticipants == null || currentParticipants == null) {
+ return 0;
+ }
+ return Math.max(0, maxParticipants - currentParticipants);
+ }
+
+ public String getParticipationSummary() {
+ if (maxParticipants == null || currentParticipants == null) {
+ return "0/0 participants";
+ }
+ return currentParticipants + "/" + maxParticipants + " participants";
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/document/request/CreateDocumentRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/document/request/CreateDocumentRequest.java
index 07667d6..a215d04 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/document/request/CreateDocumentRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/document/request/CreateDocumentRequest.java
@@ -1,26 +1,26 @@
-package dev.lions.unionflow.server.api.dto.document.request;
-
-import dev.lions.unionflow.server.api.enums.document.TypeDocument;
-import jakarta.validation.constraints.Min;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import lombok.Builder;
-
-/**
- * Requête de création d'un document.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record CreateDocumentRequest(
- @NotBlank(message = "Le nom du fichier est obligatoire") String nomFichier,
- String nomOriginal,
- @NotBlank(message = "Le chemin de stockage est obligatoire") String cheminStockage,
- String typeMime,
- @NotNull(message = "La taille est obligatoire") @Min(value = 0, message = "La taille doit être positive") Long tailleOctets,
- TypeDocument typeDocument,
- String hashMd5,
- String hashSha256,
- String description) {
-}
+package dev.lions.unionflow.server.api.dto.document.request;
+
+import dev.lions.unionflow.server.api.enums.document.TypeDocument;
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Builder;
+
+/**
+ * Requête de création d'un document.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record CreateDocumentRequest(
+ @NotBlank(message = "Le nom du fichier est obligatoire") String nomFichier,
+ String nomOriginal,
+ @NotBlank(message = "Le chemin de stockage est obligatoire") String cheminStockage,
+ String typeMime,
+ @NotNull(message = "La taille est obligatoire") @Min(value = 0, message = "La taille doit être positive") Long tailleOctets,
+ TypeDocument typeDocument,
+ String hashMd5,
+ String hashSha256,
+ String description) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/document/request/CreatePieceJointeRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/document/request/CreatePieceJointeRequest.java
index 30f5770..3d2fbd3 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/document/request/CreatePieceJointeRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/document/request/CreatePieceJointeRequest.java
@@ -1,22 +1,22 @@
-package dev.lions.unionflow.server.api.dto.document.request;
-
-import jakarta.validation.constraints.Min;
-import jakarta.validation.constraints.NotNull;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de création d'une pièce jointe.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record CreatePieceJointeRequest(
- @NotNull(message = "L'ordre est obligatoire") @Min(value = 1, message = "L'ordre doit être positif") Integer ordre,
- String libelle,
- String commentaire,
- @NotNull(message = "Le document est obligatoire") UUID documentId,
- @NotNull(message = "Le type entité est obligatoire") String typeEntiteRattachee,
- @NotNull(message = "L'ID entité est obligatoire") UUID entiteRattacheeId) {
-}
+package dev.lions.unionflow.server.api.dto.document.request;
+
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotNull;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de création d'une pièce jointe.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record CreatePieceJointeRequest(
+ @NotNull(message = "L'ordre est obligatoire") @Min(value = 1, message = "L'ordre doit être positif") Integer ordre,
+ String libelle,
+ String commentaire,
+ @NotNull(message = "Le document est obligatoire") UUID documentId,
+ @NotNull(message = "Le type entité est obligatoire") String typeEntiteRattachee,
+ @NotNull(message = "L'ID entité est obligatoire") UUID entiteRattacheeId) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/document/request/UpdateDocumentRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/document/request/UpdateDocumentRequest.java
index e449926..955ec65 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/document/request/UpdateDocumentRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/document/request/UpdateDocumentRequest.java
@@ -1,18 +1,18 @@
-package dev.lions.unionflow.server.api.dto.document.request;
-
-import dev.lions.unionflow.server.api.enums.document.TypeDocument;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'un document.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record UpdateDocumentRequest(
- String nomFichier,
- String nomOriginal,
- TypeDocument typeDocument,
- String description) {
-}
+package dev.lions.unionflow.server.api.dto.document.request;
+
+import dev.lions.unionflow.server.api.enums.document.TypeDocument;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'un document.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record UpdateDocumentRequest(
+ String nomFichier,
+ String nomOriginal,
+ TypeDocument typeDocument,
+ String description) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/document/request/UpdatePieceJointeRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/document/request/UpdatePieceJointeRequest.java
index 294a3de..7c510e0 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/document/request/UpdatePieceJointeRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/document/request/UpdatePieceJointeRequest.java
@@ -1,17 +1,17 @@
-package dev.lions.unionflow.server.api.dto.document.request;
-
-import jakarta.validation.constraints.Min;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'une pièce jointe.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record UpdatePieceJointeRequest(
- @Min(value = 1, message = "L'ordre doit être positif") Integer ordre,
- String libelle,
- String commentaire) {
-}
+package dev.lions.unionflow.server.api.dto.document.request;
+
+import jakarta.validation.constraints.Min;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'une pièce jointe.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record UpdatePieceJointeRequest(
+ @Min(value = 1, message = "L'ordre doit être positif") Integer ordre,
+ String libelle,
+ String commentaire) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/document/response/DocumentResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/document/response/DocumentResponse.java
index 014081b..b56562d 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/document/response/DocumentResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/document/response/DocumentResponse.java
@@ -1,36 +1,36 @@
-package dev.lions.unionflow.server.api.dto.document.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import dev.lions.unionflow.server.api.enums.document.TypeDocument;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse détaillée d'un document.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class DocumentResponse extends BaseResponse {
-
- private String nomFichier;
- private String nomOriginal;
- private String cheminStockage;
- private String typeMime;
- private Long tailleOctets;
- private TypeDocument typeDocument;
- private String hashMd5;
- private String hashSha256;
- private String description;
- private Integer nombreTelechargements;
- private String tailleFormatee;
-}
+package dev.lions.unionflow.server.api.dto.document.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import dev.lions.unionflow.server.api.enums.document.TypeDocument;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse détaillée d'un document.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DocumentResponse extends BaseResponse {
+
+ private String nomFichier;
+ private String nomOriginal;
+ private String cheminStockage;
+ private String typeMime;
+ private Long tailleOctets;
+ private TypeDocument typeDocument;
+ private String hashMd5;
+ private String hashSha256;
+ private String description;
+ private Integer nombreTelechargements;
+ private String tailleFormatee;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/document/response/PieceJointeResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/document/response/PieceJointeResponse.java
index 7c48af2..347ef96 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/document/response/PieceJointeResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/document/response/PieceJointeResponse.java
@@ -1,31 +1,31 @@
-package dev.lions.unionflow.server.api.dto.document.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse contenant les données d'une pièce jointe.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class PieceJointeResponse extends BaseResponse {
-
- private Integer ordre;
- private String libelle;
- private String commentaire;
- private UUID documentId;
- private String typeEntiteRattachee;
- private UUID entiteRattacheeId;
-}
+package dev.lions.unionflow.server.api.dto.document.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse contenant les données d'une pièce jointe.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class PieceJointeResponse extends BaseResponse {
+
+ private Integer ordre;
+ private String libelle;
+ private String commentaire;
+ private UUID documentId;
+ private String typeEntiteRattachee;
+ private UUID entiteRattacheeId;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/evenement/request/CreateEvenementRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/evenement/request/CreateEvenementRequest.java
index 0855135..bb5d36e 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/evenement/request/CreateEvenementRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/evenement/request/CreateEvenementRequest.java
@@ -1,70 +1,70 @@
-package dev.lions.unionflow.server.api.dto.evenement.request;
-
-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;
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.FutureOrPresent;
-import jakarta.validation.constraints.Max;
-import jakarta.validation.constraints.Min;
-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.LocalTime;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de création d'un événement.
- */
-@Builder
-public record CreateEvenementRequest(
- @NotBlank(message = "Le titre"
- + ValidationConstants.OBLIGATOIRE_MESSAGE) @Size(min = ValidationConstants.TITRE_MIN_LENGTH, max = ValidationConstants.TITRE_MAX_LENGTH, message = ValidationConstants.TITRE_SIZE_MESSAGE) String titre,
-
- @Size(max = ValidationConstants.DESCRIPTION_COURTE_MAX_LENGTH, message = ValidationConstants.DESCRIPTION_COURTE_SIZE_MESSAGE) String description,
-
- @NotNull(message = "Le type d'événement est obligatoire") TypeEvenementMetier typeEvenement,
-
- @NotNull(message = "Le statut est obligatoire") StatutEvenement statut,
-
- PrioriteEvenement priorite,
- @NotNull(message = "La date de début est obligatoire") @FutureOrPresent(message = "La date de début ne peut pas être dans le passé") LocalDate dateDebut,
- LocalDate dateFin,
- LocalTime heureDebut,
- LocalTime heureFin,
- @NotBlank(message = "Le lieu est obligatoire") @Size(max = 100) String lieu,
- @Size(max = 200) String adresse,
- @Size(max = 50) String ville,
- @Size(max = 50) String region,
- @DecimalMin(value = "-90.0") @DecimalMax(value = "90.0") BigDecimal latitude,
- @DecimalMin(value = "-180.0") @DecimalMax(value = "180.0") BigDecimal longitude,
- @NotNull(message = "L'association organisatrice est obligatoire") UUID associationId,
- @Size(max = 100) String organisateur,
- @Email(message = "Format d'email invalide") @Size(max = 100) String emailOrganisateur,
- @Pattern(regexp = "^\\+?[0-9\\s\\-\\(\\)]{8,20}$") String telephoneOrganisateur,
- @Min(value = 1) @Max(value = 10000) Integer capaciteMax,
- @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) BigDecimal budget,
-
- @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) BigDecimal coutReel,
-
- @Pattern(regexp = ValidationConstants.DEVISE_PATTERN, message = ValidationConstants.DEVISE_MESSAGE) String codeDevise,
- Boolean inscriptionObligatoire,
- LocalDate dateLimiteInscription,
- Boolean evenementPublic,
- Boolean recurrent,
- String frequenceRecurrence,
- @Size(max = 500) String instructions,
- @Size(max = 500) String materielNecessaire,
- @Size(max = 100) String conditionsMeteo,
- @Size(max = 255) String imageUrl,
- @Pattern(regexp = "^#[0-9A-Fa-f]{6}$") String couleurTheme) {
-}
+package dev.lions.unionflow.server.api.dto.evenement.request;
+
+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;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.FutureOrPresent;
+import jakarta.validation.constraints.Max;
+import jakarta.validation.constraints.Min;
+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.LocalTime;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de création d'un événement.
+ */
+@Builder
+public record CreateEvenementRequest(
+ @NotBlank(message = "Le titre"
+ + ValidationConstants.OBLIGATOIRE_MESSAGE) @Size(min = ValidationConstants.TITRE_MIN_LENGTH, max = ValidationConstants.TITRE_MAX_LENGTH, message = ValidationConstants.TITRE_SIZE_MESSAGE) String titre,
+
+ @Size(max = ValidationConstants.DESCRIPTION_COURTE_MAX_LENGTH, message = ValidationConstants.DESCRIPTION_COURTE_SIZE_MESSAGE) String description,
+
+ @NotNull(message = "Le type d'événement est obligatoire") TypeEvenementMetier typeEvenement,
+
+ @NotNull(message = "Le statut est obligatoire") StatutEvenement statut,
+
+ PrioriteEvenement priorite,
+ @NotNull(message = "La date de début est obligatoire") @FutureOrPresent(message = "La date de début ne peut pas être dans le passé") LocalDate dateDebut,
+ LocalDate dateFin,
+ LocalTime heureDebut,
+ LocalTime heureFin,
+ @NotBlank(message = "Le lieu est obligatoire") @Size(max = 100) String lieu,
+ @Size(max = 200) String adresse,
+ @Size(max = 50) String ville,
+ @Size(max = 50) String region,
+ @DecimalMin(value = "-90.0") @DecimalMax(value = "90.0") BigDecimal latitude,
+ @DecimalMin(value = "-180.0") @DecimalMax(value = "180.0") BigDecimal longitude,
+ @NotNull(message = "L'association organisatrice est obligatoire") UUID associationId,
+ @Size(max = 100) String organisateur,
+ @Email(message = "Format d'email invalide") @Size(max = 100) String emailOrganisateur,
+ @Pattern(regexp = "^\\+?[0-9\\s\\-\\(\\)]{8,20}$") String telephoneOrganisateur,
+ @Min(value = 1) @Max(value = 10000) Integer capaciteMax,
+ @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) BigDecimal budget,
+
+ @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) BigDecimal coutReel,
+
+ @Pattern(regexp = ValidationConstants.DEVISE_PATTERN, message = ValidationConstants.DEVISE_MESSAGE) String codeDevise,
+ Boolean inscriptionObligatoire,
+ LocalDate dateLimiteInscription,
+ Boolean evenementPublic,
+ Boolean recurrent,
+ String frequenceRecurrence,
+ @Size(max = 500) String instructions,
+ @Size(max = 500) String materielNecessaire,
+ @Size(max = 100) String conditionsMeteo,
+ @Size(max = 255) String imageUrl,
+ @Pattern(regexp = "^#[0-9A-Fa-f]{6}$") String couleurTheme) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/evenement/request/UpdateEvenementRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/evenement/request/UpdateEvenementRequest.java
index 58a6c21..d8b2053 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/evenement/request/UpdateEvenementRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/evenement/request/UpdateEvenementRequest.java
@@ -1,65 +1,65 @@
-package dev.lions.unionflow.server.api.dto.evenement.request;
-
-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;
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.Max;
-import jakarta.validation.constraints.Min;
-import jakarta.validation.constraints.NotBlank;
-
-import jakarta.validation.constraints.Pattern;
-import jakarta.validation.constraints.Size;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalTime;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'un événement.
- */
-@Builder
-public record UpdateEvenementRequest(
- @Size(min = ValidationConstants.TITRE_MIN_LENGTH, max = ValidationConstants.TITRE_MAX_LENGTH, message = ValidationConstants.TITRE_SIZE_MESSAGE) String titre,
-
- @Size(max = ValidationConstants.DESCRIPTION_COURTE_MAX_LENGTH, message = ValidationConstants.DESCRIPTION_COURTE_SIZE_MESSAGE) String description,
-
- TypeEvenementMetier typeEvenement,
- StatutEvenement statut,
- PrioriteEvenement priorite,
-
- LocalDate dateDebut,
- LocalDate dateFin,
- LocalTime heureDebut,
- LocalTime heureFin,
- @NotBlank(message = "Le lieu est obligatoire") @Size(max = 100) String lieu,
- @Size(max = 200) String adresse,
- @Size(max = 50) String ville,
- @Size(max = 50) String region,
- @DecimalMin(value = "-90.0") @DecimalMax(value = "90.0") BigDecimal latitude,
- @DecimalMin(value = "-180.0") @DecimalMax(value = "180.0") BigDecimal longitude,
- @Size(max = 100) String organisateur,
- @Email(message = "Format d'email invalide") @Size(max = 100) String emailOrganisateur,
- @Pattern(regexp = "^\\+?[0-9\\s\\-\\(\\)]{8,20}$") String telephoneOrganisateur,
- @Min(value = 1) @Max(value = 10000) Integer capaciteMax,
- @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) BigDecimal budget,
-
- @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) BigDecimal coutReel,
-
- @Pattern(regexp = ValidationConstants.DEVISE_PATTERN, message = ValidationConstants.DEVISE_MESSAGE) String codeDevise,
- Boolean inscriptionObligatoire,
- LocalDate dateLimiteInscription,
- Boolean evenementPublic,
- Boolean recurrent,
- String frequenceRecurrence,
- @Size(max = 500) String instructions,
- @Size(max = 500) String materielNecessaire,
- @Size(max = 100) String conditionsMeteo,
- @Size(max = 255) String imageUrl,
- @Pattern(regexp = "^#[0-9A-Fa-f]{6}$") String couleurTheme) {
-}
+package dev.lions.unionflow.server.api.dto.evenement.request;
+
+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;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.Max;
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotBlank;
+
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'un événement.
+ */
+@Builder
+public record UpdateEvenementRequest(
+ @Size(min = ValidationConstants.TITRE_MIN_LENGTH, max = ValidationConstants.TITRE_MAX_LENGTH, message = ValidationConstants.TITRE_SIZE_MESSAGE) String titre,
+
+ @Size(max = ValidationConstants.DESCRIPTION_COURTE_MAX_LENGTH, message = ValidationConstants.DESCRIPTION_COURTE_SIZE_MESSAGE) String description,
+
+ TypeEvenementMetier typeEvenement,
+ StatutEvenement statut,
+ PrioriteEvenement priorite,
+
+ LocalDate dateDebut,
+ LocalDate dateFin,
+ LocalTime heureDebut,
+ LocalTime heureFin,
+ @NotBlank(message = "Le lieu est obligatoire") @Size(max = 100) String lieu,
+ @Size(max = 200) String adresse,
+ @Size(max = 50) String ville,
+ @Size(max = 50) String region,
+ @DecimalMin(value = "-90.0") @DecimalMax(value = "90.0") BigDecimal latitude,
+ @DecimalMin(value = "-180.0") @DecimalMax(value = "180.0") BigDecimal longitude,
+ @Size(max = 100) String organisateur,
+ @Email(message = "Format d'email invalide") @Size(max = 100) String emailOrganisateur,
+ @Pattern(regexp = "^\\+?[0-9\\s\\-\\(\\)]{8,20}$") String telephoneOrganisateur,
+ @Min(value = 1) @Max(value = 10000) Integer capaciteMax,
+ @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) BigDecimal budget,
+
+ @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) BigDecimal coutReel,
+
+ @Pattern(regexp = ValidationConstants.DEVISE_PATTERN, message = ValidationConstants.DEVISE_MESSAGE) String codeDevise,
+ Boolean inscriptionObligatoire,
+ LocalDate dateLimiteInscription,
+ Boolean evenementPublic,
+ Boolean recurrent,
+ String frequenceRecurrence,
+ @Size(max = 500) String instructions,
+ @Size(max = 500) String materielNecessaire,
+ @Size(max = 100) String conditionsMeteo,
+ @Size(max = 255) String imageUrl,
+ @Pattern(regexp = "^#[0-9A-Fa-f]{6}$") String couleurTheme) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/evenement/response/EvenementResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/evenement/response/EvenementResponse.java
index c2cddb8..ee9567d 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/evenement/response/EvenementResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/evenement/response/EvenementResponse.java
@@ -1,277 +1,277 @@
-package dev.lions.unionflow.server.api.dto.evenement.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.format.DateTimeFormatter;
-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.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse détaillée pour un événement.
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class EvenementResponse extends BaseResponse {
-
- private String titre;
- private String description;
- private TypeEvenementMetier typeEvenement;
- private StatutEvenement statut;
- private PrioriteEvenement priorite;
-
- // Décommenter si l'on a besoin du @JsonFormat, sinon on garde le standard
- // @JsonFormat(pattern = "yyyy-MM-dd")
- private LocalDate dateDebut;
-
- // @JsonFormat(pattern = "yyyy-MM-dd")
- private LocalDate dateFin;
-
- // @JsonFormat(pattern = "HH:mm")
- private LocalTime heureDebut;
-
- // @JsonFormat(pattern = "HH:mm")
- private LocalTime heureFin;
- private String lieu;
- private String adresse;
- private String ville;
- private String region;
- private BigDecimal latitude;
- private BigDecimal longitude;
- private UUID associationId;
- private String nomAssociation;
- private String organisateur;
- private String emailOrganisateur;
- private String telephoneOrganisateur;
- private Integer capaciteMax;
- private Integer participantsInscrits;
- private Integer participantsPresents;
- private BigDecimal budget;
- private BigDecimal coutReel;
- private String codeDevise;
- private Boolean inscriptionObligatoire;
-
- // @JsonFormat(pattern = "yyyy-MM-dd")
- private LocalDate dateLimiteInscription;
-
- private Boolean evenementPublic;
- private Boolean recurrent;
- private String frequenceRecurrence;
- private String instructions;
- private String materielNecessaire;
- private String conditionsMeteo;
- private String imageUrl;
- private String couleurTheme;
-
- // @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- private LocalDateTime dateAnnulation;
- private String raisonAnnulation;
- private String nomAnnulateur;
- private Long annulePar;
-
- // === METHODES UTILITAIRES ===
-
- public boolean estEnCours() {
- return StatutEvenement.EN_COURS.equals(statut);
- }
-
- public boolean estTermine() {
- return StatutEvenement.TERMINE.equals(statut);
- }
-
- public boolean estAnnule() {
- return StatutEvenement.ANNULE.equals(statut);
- }
-
- public boolean estComplet() {
- return capaciteMax != null
- && participantsInscrits != null
- && participantsInscrits >= capaciteMax;
- }
-
- public int getPlacesDisponibles() {
- if (capaciteMax == null || participantsInscrits == null) {
- return 0;
- }
- return Math.max(0, capaciteMax - participantsInscrits);
- }
-
- public int getTauxRemplissage() {
- if (capaciteMax == null || capaciteMax == 0 || participantsInscrits == null) {
- return 0;
- }
- return (participantsInscrits * 100) / capaciteMax;
- }
-
- public int getTauxPresence() {
- if (participantsInscrits == null || participantsInscrits == 0 || participantsPresents == null) {
- return 0;
- }
- return (participantsPresents * 100) / participantsInscrits;
- }
-
- public boolean sontInscriptionsOuvertes() {
- if (estAnnule() || estTermine()) {
- return false;
- }
-
- if (dateLimiteInscription != null && LocalDate.now().isAfter(dateLimiteInscription)) {
- return false;
- }
-
- return !estComplet();
- }
-
- public long getDureeEnHeures() {
- if (heureDebut == null || heureFin == null) {
- return 0;
- }
-
- return heureDebut.until(heureFin, java.time.temporal.ChronoUnit.HOURS);
- }
-
- public boolean estEvenementMultiJours() {
- return dateFin != null && !dateDebut.equals(dateFin);
- }
-
- public String getTypeEvenementLibelle() {
- return typeEvenement != null ? typeEvenement.getLibelle() : "Non défini";
- }
-
- public String getTypeEvenementIcon() {
- if (typeEvenement == null) return "pi pi-calendar";
- return switch (typeEvenement) {
- case ASSEMBLEE_GENERALE -> "pi pi-building";
- case FORMATION -> "pi pi-book";
- case REUNION_BUREAU -> "pi pi-users";
- case CONFERENCE -> "pi pi-microphone";
- case ATELIER -> "pi pi-wrench";
- case CEREMONIE -> "pi pi-flag";
- case ACTIVITE_SOCIALE, ACTION_CARITATIVE, AUTRE -> "pi pi-calendar";
- };
- }
-
- public String getTypeEvenementSeverity() {
- if (typeEvenement == null) return "secondary";
- return switch (typeEvenement) {
- case ASSEMBLEE_GENERALE -> "warning";
- case FORMATION -> "info";
- case ACTIVITE_SOCIALE, ACTION_CARITATIVE, REUNION_BUREAU, CONFERENCE, ATELIER, CEREMONIE, AUTRE -> "secondary";
- };
- }
-
- public String getStatutLibelle() {
- return statut != null ? statut.getLibelle() : "Non défini";
- }
-
- public String getStatutSeverity() {
- if (statut == null) return "secondary";
- return switch (statut) {
- case PLANIFIE -> "info";
- case EN_COURS -> "success";
- case TERMINE, CONFIRME -> "secondary";
- case ANNULE -> "danger";
- case REPORTE -> "warning";
- };
- }
-
- public String getDateDebutFormatee() {
- return dateDebut != null ? dateDebut.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")) : "—";
- }
-
- public String getHeureDebutFormatee() {
- return heureDebut != null ? heureDebut.format(DateTimeFormatter.ofPattern("HH:mm")) : "—";
- }
-
- public String getHeureFinFormatee() {
- return heureFin != null ? heureFin.format(DateTimeFormatter.ofPattern("HH:mm")) : "—";
- }
-
- public String getStatutIcon() {
- if (statut == null) return "pi pi-question";
- return switch (statut) {
- case PLANIFIE -> "pi pi-clock";
- case CONFIRME -> "pi pi-check-circle";
- case EN_COURS -> "pi pi-play";
- case TERMINE -> "pi pi-check";
- case ANNULE -> "pi pi-times";
- case REPORTE -> "pi pi-refresh";
- };
- }
-
- public String getPrioriteSeverity() {
- if (priorite == null) return "secondary";
- return switch (priorite) {
- case CRITIQUE -> "danger";
- case HAUTE -> "warning";
- case NORMALE -> "info";
- case BASSE -> "secondary";
- };
- }
-
- public String getBudgetFormate() {
- if (budget == null) return "—";
- return String.format(java.util.Locale.US, "%,.0f %s", budget, codeDevise != null ? codeDevise : "FCFA");
- }
-
- public String getPrioriteLibelle() {
- return priorite != null ? priorite.getLibelle() : "Normale";
- }
-
- public String getAdresseComplete() {
- StringBuilder adresseComplete = new StringBuilder();
-
- if (lieu != null && !lieu.trim().isEmpty()) {
- adresseComplete.append(lieu);
- }
-
- if (adresse != null && !adresse.trim().isEmpty()) {
- if (adresseComplete.length() > 0)
- adresseComplete.append(", ");
- adresseComplete.append(adresse);
- }
-
- if (ville != null && !ville.trim().isEmpty()) {
- if (adresseComplete.length() > 0)
- adresseComplete.append(", ");
- adresseComplete.append(ville);
- }
-
- if (region != null && !region.trim().isEmpty()) {
- if (adresseComplete.length() > 0)
- adresseComplete.append(", ");
- adresseComplete.append(region);
- }
-
- return adresseComplete.toString();
- }
-
- public boolean hasCoordonnees() {
- return latitude != null && longitude != null;
- }
-
- public BigDecimal getEcartBudgetaire() {
- if (budget == null || coutReel == null) {
- return BigDecimal.ZERO;
- }
- return budget.subtract(coutReel);
- }
-
- public boolean estBudgetDepasse() {
- return getEcartBudgetaire().compareTo(BigDecimal.ZERO) < 0;
- }
-}
+package dev.lions.unionflow.server.api.dto.evenement.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+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.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse détaillée pour un événement.
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class EvenementResponse extends BaseResponse {
+
+ private String titre;
+ private String description;
+ private TypeEvenementMetier typeEvenement;
+ private StatutEvenement statut;
+ private PrioriteEvenement priorite;
+
+ // Décommenter si l'on a besoin du @JsonFormat, sinon on garde le standard
+ // @JsonFormat(pattern = "yyyy-MM-dd")
+ private LocalDate dateDebut;
+
+ // @JsonFormat(pattern = "yyyy-MM-dd")
+ private LocalDate dateFin;
+
+ // @JsonFormat(pattern = "HH:mm")
+ private LocalTime heureDebut;
+
+ // @JsonFormat(pattern = "HH:mm")
+ private LocalTime heureFin;
+ private String lieu;
+ private String adresse;
+ private String ville;
+ private String region;
+ private BigDecimal latitude;
+ private BigDecimal longitude;
+ private UUID associationId;
+ private String nomAssociation;
+ private String organisateur;
+ private String emailOrganisateur;
+ private String telephoneOrganisateur;
+ private Integer capaciteMax;
+ private Integer participantsInscrits;
+ private Integer participantsPresents;
+ private BigDecimal budget;
+ private BigDecimal coutReel;
+ private String codeDevise;
+ private Boolean inscriptionObligatoire;
+
+ // @JsonFormat(pattern = "yyyy-MM-dd")
+ private LocalDate dateLimiteInscription;
+
+ private Boolean evenementPublic;
+ private Boolean recurrent;
+ private String frequenceRecurrence;
+ private String instructions;
+ private String materielNecessaire;
+ private String conditionsMeteo;
+ private String imageUrl;
+ private String couleurTheme;
+
+ // @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime dateAnnulation;
+ private String raisonAnnulation;
+ private String nomAnnulateur;
+ private Long annulePar;
+
+ // === METHODES UTILITAIRES ===
+
+ public boolean estEnCours() {
+ return StatutEvenement.EN_COURS.equals(statut);
+ }
+
+ public boolean estTermine() {
+ return StatutEvenement.TERMINE.equals(statut);
+ }
+
+ public boolean estAnnule() {
+ return StatutEvenement.ANNULE.equals(statut);
+ }
+
+ public boolean estComplet() {
+ return capaciteMax != null
+ && participantsInscrits != null
+ && participantsInscrits >= capaciteMax;
+ }
+
+ public int getPlacesDisponibles() {
+ if (capaciteMax == null || participantsInscrits == null) {
+ return 0;
+ }
+ return Math.max(0, capaciteMax - participantsInscrits);
+ }
+
+ public int getTauxRemplissage() {
+ if (capaciteMax == null || capaciteMax == 0 || participantsInscrits == null) {
+ return 0;
+ }
+ return (participantsInscrits * 100) / capaciteMax;
+ }
+
+ public int getTauxPresence() {
+ if (participantsInscrits == null || participantsInscrits == 0 || participantsPresents == null) {
+ return 0;
+ }
+ return (participantsPresents * 100) / participantsInscrits;
+ }
+
+ public boolean sontInscriptionsOuvertes() {
+ if (estAnnule() || estTermine()) {
+ return false;
+ }
+
+ if (dateLimiteInscription != null && LocalDate.now().isAfter(dateLimiteInscription)) {
+ return false;
+ }
+
+ return !estComplet();
+ }
+
+ public long getDureeEnHeures() {
+ if (heureDebut == null || heureFin == null) {
+ return 0;
+ }
+
+ return heureDebut.until(heureFin, java.time.temporal.ChronoUnit.HOURS);
+ }
+
+ public boolean estEvenementMultiJours() {
+ return dateFin != null && !dateDebut.equals(dateFin);
+ }
+
+ public String getTypeEvenementLibelle() {
+ return typeEvenement != null ? typeEvenement.getLibelle() : "Non défini";
+ }
+
+ public String getTypeEvenementIcon() {
+ if (typeEvenement == null) return "pi pi-calendar";
+ return switch (typeEvenement) {
+ case ASSEMBLEE_GENERALE -> "pi pi-building";
+ case FORMATION -> "pi pi-book";
+ case REUNION_BUREAU -> "pi pi-users";
+ case CONFERENCE -> "pi pi-microphone";
+ case ATELIER -> "pi pi-wrench";
+ case CEREMONIE -> "pi pi-flag";
+ case ACTIVITE_SOCIALE, ACTION_CARITATIVE, AUTRE -> "pi pi-calendar";
+ };
+ }
+
+ public String getTypeEvenementSeverity() {
+ if (typeEvenement == null) return "secondary";
+ return switch (typeEvenement) {
+ case ASSEMBLEE_GENERALE -> "warning";
+ case FORMATION -> "info";
+ case ACTIVITE_SOCIALE, ACTION_CARITATIVE, REUNION_BUREAU, CONFERENCE, ATELIER, CEREMONIE, AUTRE -> "secondary";
+ };
+ }
+
+ public String getStatutLibelle() {
+ return statut != null ? statut.getLibelle() : "Non défini";
+ }
+
+ public String getStatutSeverity() {
+ if (statut == null) return "secondary";
+ return switch (statut) {
+ case PLANIFIE -> "info";
+ case EN_COURS -> "success";
+ case TERMINE, CONFIRME -> "secondary";
+ case ANNULE -> "danger";
+ case REPORTE -> "warning";
+ };
+ }
+
+ public String getDateDebutFormatee() {
+ return dateDebut != null ? dateDebut.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")) : "—";
+ }
+
+ public String getHeureDebutFormatee() {
+ return heureDebut != null ? heureDebut.format(DateTimeFormatter.ofPattern("HH:mm")) : "—";
+ }
+
+ public String getHeureFinFormatee() {
+ return heureFin != null ? heureFin.format(DateTimeFormatter.ofPattern("HH:mm")) : "—";
+ }
+
+ public String getStatutIcon() {
+ if (statut == null) return "pi pi-question";
+ return switch (statut) {
+ case PLANIFIE -> "pi pi-clock";
+ case CONFIRME -> "pi pi-check-circle";
+ case EN_COURS -> "pi pi-play";
+ case TERMINE -> "pi pi-check";
+ case ANNULE -> "pi pi-times";
+ case REPORTE -> "pi pi-refresh";
+ };
+ }
+
+ public String getPrioriteSeverity() {
+ if (priorite == null) return "secondary";
+ return switch (priorite) {
+ case CRITIQUE -> "danger";
+ case HAUTE -> "warning";
+ case NORMALE -> "info";
+ case BASSE -> "secondary";
+ };
+ }
+
+ public String getBudgetFormate() {
+ if (budget == null) return "—";
+ return String.format(java.util.Locale.US, "%,.0f %s", budget, codeDevise != null ? codeDevise : "FCFA");
+ }
+
+ public String getPrioriteLibelle() {
+ return priorite != null ? priorite.getLibelle() : "Normale";
+ }
+
+ public String getAdresseComplete() {
+ StringBuilder adresseComplete = new StringBuilder();
+
+ if (lieu != null && !lieu.trim().isEmpty()) {
+ adresseComplete.append(lieu);
+ }
+
+ if (adresse != null && !adresse.trim().isEmpty()) {
+ if (adresseComplete.length() > 0)
+ adresseComplete.append(", ");
+ adresseComplete.append(adresse);
+ }
+
+ if (ville != null && !ville.trim().isEmpty()) {
+ if (adresseComplete.length() > 0)
+ adresseComplete.append(", ");
+ adresseComplete.append(ville);
+ }
+
+ if (region != null && !region.trim().isEmpty()) {
+ if (adresseComplete.length() > 0)
+ adresseComplete.append(", ");
+ adresseComplete.append(region);
+ }
+
+ return adresseComplete.toString();
+ }
+
+ public boolean hasCoordonnees() {
+ return latitude != null && longitude != null;
+ }
+
+ public BigDecimal getEcartBudgetaire() {
+ if (budget == null || coutReel == null) {
+ return BigDecimal.ZERO;
+ }
+ return budget.subtract(coutReel);
+ }
+
+ public boolean estBudgetDepasse() {
+ return getEcartBudgetaire().compareTo(BigDecimal.ZERO) < 0;
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/favoris/request/CreateFavoriRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/favoris/request/CreateFavoriRequest.java
index 450df8c..de177d2 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/favoris/request/CreateFavoriRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/favoris/request/CreateFavoriRequest.java
@@ -1,26 +1,26 @@
-package dev.lions.unionflow.server.api.dto.favoris.request;
-
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de création d'un favori.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record CreateFavoriRequest(
- UUID utilisateurId,
- String typeFavori,
- String titre,
- String description,
- String url,
- String icon,
- String couleur,
- String categorie,
- Integer ordre,
- Integer nbVisites,
- String derniereVisite,
- Boolean estPlusUtilise) {
-}
+package dev.lions.unionflow.server.api.dto.favoris.request;
+
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de création d'un favori.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record CreateFavoriRequest(
+ UUID utilisateurId,
+ String typeFavori,
+ String titre,
+ String description,
+ String url,
+ String icon,
+ String couleur,
+ String categorie,
+ Integer ordre,
+ Integer nbVisites,
+ String derniereVisite,
+ Boolean estPlusUtilise) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/favoris/response/FavoriResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/favoris/response/FavoriResponse.java
index c409747..bd1f5c2 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/favoris/response/FavoriResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/favoris/response/FavoriResponse.java
@@ -1,37 +1,37 @@
-package dev.lions.unionflow.server.api.dto.favoris.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.util.UUID;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.Builder;
-import lombok.NoArgsConstructor;
-import lombok.AllArgsConstructor;
-import lombok.EqualsAndHashCode;
-
-/**
- * Réponse pour un favori utilisateur.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class FavoriResponse extends BaseResponse {
-
- private UUID utilisateurId;
- private String typeFavori;
- private String titre;
- private String description;
- private String url;
- private String icon;
- private String couleur;
- private String categorie;
- private Integer ordre;
- private Integer nbVisites;
- private String derniereVisite;
- private Boolean estPlusUtilise;
-}
+package dev.lions.unionflow.server.api.dto.favoris.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.util.UUID;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.Builder;
+import lombok.NoArgsConstructor;
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+
+/**
+ * Réponse pour un favori utilisateur.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class FavoriResponse extends BaseResponse {
+
+ private UUID utilisateurId;
+ private String typeFavori;
+ private String titre;
+ private String description;
+ private String url;
+ private String icon;
+ private String couleur;
+ private String categorie;
+ private Integer ordre;
+ private Integer nbVisites;
+ private String derniereVisite;
+ private Boolean estPlusUtilise;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/finance/request/CreateAdhesionRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/finance/request/CreateAdhesionRequest.java
index 6bbcd72..90dc835 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/finance/request/CreateAdhesionRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/finance/request/CreateAdhesionRequest.java
@@ -1,33 +1,33 @@
-package dev.lions.unionflow.server.api.dto.finance.request;
-
-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.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de création d'une adhésion.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record CreateAdhesionRequest(
- @NotBlank(message = "Le numéro de référence est obligatoire") @Size(max = 50, message = "Le numéro de référence ne peut pas dépasser 50 caractères") String numeroReference,
-
- @NotNull(message = "L'identifiant du membre est obligatoire") UUID membreId,
- @NotNull(message = "L'identifiant de l'organisation est obligatoire") UUID organisationId,
- @NotNull(message = "La date de demande est obligatoire") LocalDate dateDemande,
-
- @NotNull(message = "Les frais d'adhésion sont obligatoires") @DecimalMin(value = "0.0", inclusive = false, message = "Les frais d'adhésion doivent être positifs") @Digits(integer = 10, fraction = 2, message = "Format de montant invalide") BigDecimal fraisAdhesion,
-
- @NotBlank(message = "Le code devise est obligatoire") @Pattern(regexp = "^[A-Z]{3}$", message = "Le code devise doit être un code ISO à 3 lettres") String codeDevise,
-
- @Size(max = 1000, message = "Les observations ne peuvent pas dépasser 1000 caractères") String observations) {
-}
+package dev.lions.unionflow.server.api.dto.finance.request;
+
+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.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de création d'une adhésion.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record CreateAdhesionRequest(
+ @NotBlank(message = "Le numéro de référence est obligatoire") @Size(max = 50, message = "Le numéro de référence ne peut pas dépasser 50 caractères") String numeroReference,
+
+ @NotNull(message = "L'identifiant du membre est obligatoire") UUID membreId,
+ @NotNull(message = "L'identifiant de l'organisation est obligatoire") UUID organisationId,
+ @NotNull(message = "La date de demande est obligatoire") LocalDate dateDemande,
+
+ @NotNull(message = "Les frais d'adhésion sont obligatoires") @DecimalMin(value = "0.0", inclusive = false, message = "Les frais d'adhésion doivent être positifs") @Digits(integer = 10, fraction = 2, message = "Format de montant invalide") BigDecimal fraisAdhesion,
+
+ @NotBlank(message = "Le code devise est obligatoire") @Pattern(regexp = "^[A-Z]{3}$", message = "Le code devise doit être un code ISO à 3 lettres") String codeDevise,
+
+ @Size(max = 1000, message = "Les observations ne peuvent pas dépasser 1000 caractères") String observations) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/finance/request/UpdateAdhesionRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/finance/request/UpdateAdhesionRequest.java
index a277eb0..aa02a89 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/finance/request/UpdateAdhesionRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/finance/request/UpdateAdhesionRequest.java
@@ -1,38 +1,38 @@
-package dev.lions.unionflow.server.api.dto.finance.request;
-
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Digits;
-import jakarta.validation.constraints.Pattern;
-import jakarta.validation.constraints.Size;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'une adhésion.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record UpdateAdhesionRequest(
- @DecimalMin(value = "0.0", message = "Le montant payé ne peut pas être négatif") @Digits(integer = 10, fraction = 2, message = "Format de montant invalide") BigDecimal montantPaye,
-
- @Pattern(regexp = "^(EN_ATTENTE|APPROUVEE|REJETEE|ANNULEE|EN_PAIEMENT|PAYEE)$", message = "Statut invalide") String statut,
-
- LocalDate dateApprobation,
- LocalDateTime datePaiement,
-
- @Pattern(regexp = "^(ESPECES|VIREMENT|CHEQUE|WAVE_MONEY|ORANGE_MONEY|FREE_MONEY|CARTE_BANCAIRE)$", message = "Méthode de paiement invalide") String methodePaiement,
-
- @Size(max = 100, message = "La référence de paiement ne peut pas dépasser 100 caractères") String referencePaiement,
-
- @Size(max = 1000, message = "Le motif de rejet ne peut pas dépasser 1000 caractères") String motifRejet,
-
- @Size(max = 1000, message = "Les observations ne peuvent pas dépasser 1000 caractères") String observations,
-
- @Size(max = 255, message = "Le nom de l'approbateur ne peut pas dépasser 255 caractères") String approuvePar,
-
- LocalDate dateValidation) {
-}
+package dev.lions.unionflow.server.api.dto.finance.request;
+
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Digits;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'une adhésion.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record UpdateAdhesionRequest(
+ @DecimalMin(value = "0.0", message = "Le montant payé ne peut pas être négatif") @Digits(integer = 10, fraction = 2, message = "Format de montant invalide") BigDecimal montantPaye,
+
+ @Pattern(regexp = "^(EN_ATTENTE|APPROUVEE|REJETEE|ANNULEE|EN_PAIEMENT|PAYEE)$", message = "Statut invalide") String statut,
+
+ LocalDate dateApprobation,
+ LocalDateTime datePaiement,
+
+ @Pattern(regexp = "^(ESPECES|VIREMENT|CHEQUE|WAVE_MONEY|ORANGE_MONEY|FREE_MONEY|CARTE_BANCAIRE)$", message = "Méthode de paiement invalide") String methodePaiement,
+
+ @Size(max = 100, message = "La référence de paiement ne peut pas dépasser 100 caractères") String referencePaiement,
+
+ @Size(max = 1000, message = "Le motif de rejet ne peut pas dépasser 1000 caractères") String motifRejet,
+
+ @Size(max = 1000, message = "Les observations ne peuvent pas dépasser 1000 caractères") String observations,
+
+ @Size(max = 255, message = "Le nom de l'approbateur ne peut pas dépasser 255 caractères") String approuvePar,
+
+ LocalDate dateValidation) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/finance/response/AdhesionResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/finance/response/AdhesionResponse.java
index bfe3d04..090cd79 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/finance/response/AdhesionResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/finance/response/AdhesionResponse.java
@@ -1,171 +1,171 @@
-package dev.lions.unionflow.server.api.dto.finance.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.temporal.ChronoUnit;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse contenant les données d'une adhésion.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class AdhesionResponse extends BaseResponse {
-
- private String numeroReference;
- private UUID membreId;
- private String numeroMembre;
- private String nomMembre;
- private String emailMembre;
- private UUID organisationId;
- private String nomOrganisation;
- private LocalDate dateDemande;
- private BigDecimal fraisAdhesion;
- private BigDecimal montantPaye;
- private String codeDevise;
- private String statut;
- private LocalDate dateApprobation;
- private LocalDateTime datePaiement;
- private String methodePaiement;
- private String referencePaiement;
- private String motifRejet;
- private String observations;
- private String approuvePar;
- private LocalDate dateValidation;
-
- // Méthodes utilitaires héritées de l'ancien DTO
- public boolean isPayeeIntegralement() {
- return montantPaye != null && fraisAdhesion != null && montantPaye.compareTo(fraisAdhesion) >= 0;
- }
-
- public boolean isEnAttentePaiement() {
- return "APPROUVEE".equals(statut) && !isPayeeIntegralement();
- }
-
- public BigDecimal getMontantRestant() {
- if (fraisAdhesion == null)
- return BigDecimal.ZERO;
- if (montantPaye == null)
- return fraisAdhesion;
- BigDecimal restant = fraisAdhesion.subtract(montantPaye);
- return restant.compareTo(BigDecimal.ZERO) > 0 ? restant : BigDecimal.ZERO;
- }
-
- public int getPourcentagePaiement() {
- if (fraisAdhesion == null || fraisAdhesion.compareTo(BigDecimal.ZERO) == 0)
- return 0;
- if (montantPaye == null)
- return 0;
- return montantPaye.multiply(BigDecimal.valueOf(100)).divide(fraisAdhesion, 0, java.math.RoundingMode.HALF_UP)
- .intValue();
- }
-
- public long getJoursDepuisDemande() {
- if (dateDemande == null)
- return 0;
- return ChronoUnit.DAYS.between(dateDemande, LocalDate.now());
- }
-
- public String getStatutLibelle() {
- if (statut == null)
- return "Non défini";
- return switch (statut) {
- case "EN_ATTENTE" -> "En attente";
- case "APPROUVEE" -> "Approuvée";
- case "REJETEE" -> "Rejetée";
- case "ANNULEE" -> "Annulée";
- case "EN_PAIEMENT" -> "En paiement";
- case "PAYEE" -> "Payée";
- default -> statut;
- };
- }
-
- public String getStatutSeverity() {
- if (statut == null)
- return "secondary";
- return switch (statut) {
- case "APPROUVEE", "PAYEE" -> "success";
- case "EN_ATTENTE", "EN_PAIEMENT" -> "warning";
- case "REJETEE" -> "danger";
- case "ANNULEE" -> "secondary";
- default -> "secondary";
- };
- }
-
- public String getStatutIcon() {
- if (statut == null)
- return "pi-circle";
- return switch (statut) {
- case "APPROUVEE", "PAYEE" -> "pi-check";
- case "EN_ATTENTE" -> "pi-clock";
- case "EN_PAIEMENT" -> "pi-credit-card";
- case "REJETEE" -> "pi-times";
- case "ANNULEE" -> "pi-ban";
- default -> "pi-circle";
- };
- }
-
- public String getMethodePaiementLibelle() {
- if (methodePaiement == null)
- return "Non défini";
- return switch (methodePaiement) {
- case "ESPECES" -> "Espèces";
- case "VIREMENT" -> "Virement bancaire";
- case "CHEQUE" -> "Chèque";
- case "WAVE_MONEY" -> "Wave Money";
- case "ORANGE_MONEY" -> "Orange Money";
- case "FREE_MONEY" -> "Free Money";
- case "CARTE_BANCAIRE" -> "Carte bancaire";
- default -> methodePaiement;
- };
- }
-
- public String getDateDemandeFormatee() {
- if (dateDemande == null)
- return "";
- return dateDemande.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
- }
-
- public String getDateApprobationFormatee() {
- if (dateApprobation == null)
- return "";
- return dateApprobation.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
- }
-
- public String getDatePaiementFormatee() {
- if (datePaiement == null)
- return "";
- return datePaiement.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"));
- }
-
- public String getFraisAdhesionFormatte() {
- if (fraisAdhesion == null)
- return "0 FCFA";
- return String.format("%,.0f FCFA", fraisAdhesion.doubleValue());
- }
-
- public String getMontantPayeFormatte() {
- if (montantPaye == null)
- return "0 FCFA";
- return String.format("%,.0f FCFA", montantPaye.doubleValue());
- }
-
- public String getMontantRestantFormatte() {
- return String.format("%,.0f FCFA", getMontantRestant().doubleValue());
- }
-}
+package dev.lions.unionflow.server.api.dto.finance.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse contenant les données d'une adhésion.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AdhesionResponse extends BaseResponse {
+
+ private String numeroReference;
+ private UUID membreId;
+ private String numeroMembre;
+ private String nomMembre;
+ private String emailMembre;
+ private UUID organisationId;
+ private String nomOrganisation;
+ private LocalDate dateDemande;
+ private BigDecimal fraisAdhesion;
+ private BigDecimal montantPaye;
+ private String codeDevise;
+ private String statut;
+ private LocalDate dateApprobation;
+ private LocalDateTime datePaiement;
+ private String methodePaiement;
+ private String referencePaiement;
+ private String motifRejet;
+ private String observations;
+ private String approuvePar;
+ private LocalDate dateValidation;
+
+ // Méthodes utilitaires héritées de l'ancien DTO
+ public boolean isPayeeIntegralement() {
+ return montantPaye != null && fraisAdhesion != null && montantPaye.compareTo(fraisAdhesion) >= 0;
+ }
+
+ public boolean isEnAttentePaiement() {
+ return "APPROUVEE".equals(statut) && !isPayeeIntegralement();
+ }
+
+ public BigDecimal getMontantRestant() {
+ if (fraisAdhesion == null)
+ return BigDecimal.ZERO;
+ if (montantPaye == null)
+ return fraisAdhesion;
+ BigDecimal restant = fraisAdhesion.subtract(montantPaye);
+ return restant.compareTo(BigDecimal.ZERO) > 0 ? restant : BigDecimal.ZERO;
+ }
+
+ public int getPourcentagePaiement() {
+ if (fraisAdhesion == null || fraisAdhesion.compareTo(BigDecimal.ZERO) == 0)
+ return 0;
+ if (montantPaye == null)
+ return 0;
+ return montantPaye.multiply(BigDecimal.valueOf(100)).divide(fraisAdhesion, 0, java.math.RoundingMode.HALF_UP)
+ .intValue();
+ }
+
+ public long getJoursDepuisDemande() {
+ if (dateDemande == null)
+ return 0;
+ return ChronoUnit.DAYS.between(dateDemande, LocalDate.now());
+ }
+
+ public String getStatutLibelle() {
+ if (statut == null)
+ return "Non défini";
+ return switch (statut) {
+ case "EN_ATTENTE" -> "En attente";
+ case "APPROUVEE" -> "Approuvée";
+ case "REJETEE" -> "Rejetée";
+ case "ANNULEE" -> "Annulée";
+ case "EN_PAIEMENT" -> "En paiement";
+ case "PAYEE" -> "Payée";
+ default -> statut;
+ };
+ }
+
+ public String getStatutSeverity() {
+ if (statut == null)
+ return "secondary";
+ return switch (statut) {
+ case "APPROUVEE", "PAYEE" -> "success";
+ case "EN_ATTENTE", "EN_PAIEMENT" -> "warning";
+ case "REJETEE" -> "danger";
+ case "ANNULEE" -> "secondary";
+ default -> "secondary";
+ };
+ }
+
+ public String getStatutIcon() {
+ if (statut == null)
+ return "pi-circle";
+ return switch (statut) {
+ case "APPROUVEE", "PAYEE" -> "pi-check";
+ case "EN_ATTENTE" -> "pi-clock";
+ case "EN_PAIEMENT" -> "pi-credit-card";
+ case "REJETEE" -> "pi-times";
+ case "ANNULEE" -> "pi-ban";
+ default -> "pi-circle";
+ };
+ }
+
+ public String getMethodePaiementLibelle() {
+ if (methodePaiement == null)
+ return "Non défini";
+ return switch (methodePaiement) {
+ case "ESPECES" -> "Espèces";
+ case "VIREMENT" -> "Virement bancaire";
+ case "CHEQUE" -> "Chèque";
+ case "WAVE_MONEY" -> "Wave Money";
+ case "ORANGE_MONEY" -> "Orange Money";
+ case "FREE_MONEY" -> "Free Money";
+ case "CARTE_BANCAIRE" -> "Carte bancaire";
+ default -> methodePaiement;
+ };
+ }
+
+ public String getDateDemandeFormatee() {
+ if (dateDemande == null)
+ return "";
+ return dateDemande.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
+ }
+
+ public String getDateApprobationFormatee() {
+ if (dateApprobation == null)
+ return "";
+ return dateApprobation.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
+ }
+
+ public String getDatePaiementFormatee() {
+ if (datePaiement == null)
+ return "";
+ return datePaiement.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm"));
+ }
+
+ public String getFraisAdhesionFormatte() {
+ if (fraisAdhesion == null)
+ return "0 FCFA";
+ return String.format("%,.0f FCFA", fraisAdhesion.doubleValue());
+ }
+
+ public String getMontantPayeFormatte() {
+ if (montantPaye == null)
+ return "0 FCFA";
+ return String.format("%,.0f FCFA", montantPaye.doubleValue());
+ }
+
+ public String getMontantRestantFormatte() {
+ return String.format("%,.0f FCFA", getMontantRestant().doubleValue());
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/ApproveTransactionRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/ApproveTransactionRequest.java
index 0d53ad8..4ec19fc 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/ApproveTransactionRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/ApproveTransactionRequest.java
@@ -1,24 +1,24 @@
-package dev.lions.unionflow.server.api.dto.finance_workflow.request;
-
-import jakarta.validation.constraints.Size;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * DTO de requête pour approuver une transaction
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-03-13
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class ApproveTransactionRequest {
-
- @Size(max = 1000, message = "Le commentaire ne peut pas dépasser 1000 caractères")
- private String comment;
-}
+package dev.lions.unionflow.server.api.dto.finance_workflow.request;
+
+import jakarta.validation.constraints.Size;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * DTO de requête pour approuver une transaction
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-03-13
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class ApproveTransactionRequest {
+
+ @Size(max = 1000, message = "Le commentaire ne peut pas dépasser 1000 caractères")
+ private String comment;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/CreateBudgetLineRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/CreateBudgetLineRequest.java
index a8c310b..2364fee 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/CreateBudgetLineRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/CreateBudgetLineRequest.java
@@ -1,42 +1,42 @@
-package dev.lions.unionflow.server.api.dto.finance_workflow.request;
-
-import jakarta.validation.constraints.*;
-import java.math.BigDecimal;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * DTO de requête pour créer une ligne budgétaire
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-03-13
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class CreateBudgetLineRequest {
-
- @NotBlank(message = "La catégorie est requise")
- @Pattern(regexp = "^(CONTRIBUTIONS|SAVINGS|SOLIDARITY|EVENTS|OPERATIONAL|INVESTMENTS|OTHER)$",
- message = "Catégorie invalide")
- private String category;
-
- @NotBlank(message = "Le nom est requis")
- @Size(max = 200, message = "Le nom ne peut pas dépasser 200 caractères")
- private String name;
-
- @Size(max = 500, message = "La description ne peut pas dépasser 500 caractères")
- private String description;
-
- @NotNull(message = "Le montant prévu est requis")
- @DecimalMin(value = "0.0", message = "Le montant prévu doit être positif")
- @Digits(integer = 14, fraction = 2, message = "Format du montant invalide")
- private BigDecimal amountPlanned;
-
- @Size(max = 1000, message = "Les notes ne peuvent pas dépasser 1000 caractères")
- private String notes;
-}
+package dev.lions.unionflow.server.api.dto.finance_workflow.request;
+
+import jakarta.validation.constraints.*;
+import java.math.BigDecimal;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * DTO de requête pour créer une ligne budgétaire
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-03-13
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class CreateBudgetLineRequest {
+
+ @NotBlank(message = "La catégorie est requise")
+ @Pattern(regexp = "^(CONTRIBUTIONS|SAVINGS|SOLIDARITY|EVENTS|OPERATIONAL|INVESTMENTS|OTHER)$",
+ message = "Catégorie invalide")
+ private String category;
+
+ @NotBlank(message = "Le nom est requis")
+ @Size(max = 200, message = "Le nom ne peut pas dépasser 200 caractères")
+ private String name;
+
+ @Size(max = 500, message = "La description ne peut pas dépasser 500 caractères")
+ private String description;
+
+ @NotNull(message = "Le montant prévu est requis")
+ @DecimalMin(value = "0.0", message = "Le montant prévu doit être positif")
+ @Digits(integer = 14, fraction = 2, message = "Format du montant invalide")
+ private BigDecimal amountPlanned;
+
+ @Size(max = 1000, message = "Les notes ne peuvent pas dépasser 1000 caractères")
+ private String notes;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/CreateBudgetRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/CreateBudgetRequest.java
index a634781..ed7afa4 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/CreateBudgetRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/CreateBudgetRequest.java
@@ -1,58 +1,58 @@
-package dev.lions.unionflow.server.api.dto.finance_workflow.request;
-
-import jakarta.validation.Valid;
-import jakarta.validation.constraints.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * DTO de requête pour créer un budget
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-03-13
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class CreateBudgetRequest {
-
- @NotBlank(message = "Le nom est requis")
- @Size(max = 200, message = "Le nom ne peut pas dépasser 200 caractères")
- private String name;
-
- @Size(max = 1000, message = "La description ne peut pas dépasser 1000 caractères")
- private String description;
-
- @NotNull(message = "L'ID de l'organisation est requis")
- private UUID organizationId;
-
- @NotBlank(message = "La période est requise")
- @Pattern(regexp = "^(MONTHLY|QUARTERLY|SEMIANNUAL|ANNUAL)$",
- message = "Période invalide")
- private String period;
-
- @NotNull(message = "L'année est requise")
- @Min(value = 2020, message = "L'année doit être >= 2020")
- @Max(value = 2100, message = "L'année doit être <= 2100")
- private Integer year;
-
- @Min(value = 1, message = "Le mois doit être entre 1 et 12")
- @Max(value = 12, message = "Le mois doit être entre 1 et 12")
- private Integer month;
-
- @NotNull(message = "Au moins une ligne budgétaire est requise")
- @Size(min = 1, message = "Au moins une ligne budgétaire est requise")
- @Valid
- @Builder.Default
- private List lines = new ArrayList<>();
-
- @Pattern(regexp = "^[A-Z]{3}$", message = "Code devise invalide (doit être ISO 3 lettres)")
- private String currency; // Optionnel, défaut XOF
-}
+package dev.lions.unionflow.server.api.dto.finance_workflow.request;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * DTO de requête pour créer un budget
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-03-13
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class CreateBudgetRequest {
+
+ @NotBlank(message = "Le nom est requis")
+ @Size(max = 200, message = "Le nom ne peut pas dépasser 200 caractères")
+ private String name;
+
+ @Size(max = 1000, message = "La description ne peut pas dépasser 1000 caractères")
+ private String description;
+
+ @NotNull(message = "L'ID de l'organisation est requis")
+ private UUID organizationId;
+
+ @NotBlank(message = "La période est requise")
+ @Pattern(regexp = "^(MONTHLY|QUARTERLY|SEMIANNUAL|ANNUAL)$",
+ message = "Période invalide")
+ private String period;
+
+ @NotNull(message = "L'année est requise")
+ @Min(value = 2020, message = "L'année doit être >= 2020")
+ @Max(value = 2100, message = "L'année doit être <= 2100")
+ private Integer year;
+
+ @Min(value = 1, message = "Le mois doit être entre 1 et 12")
+ @Max(value = 12, message = "Le mois doit être entre 1 et 12")
+ private Integer month;
+
+ @NotNull(message = "Au moins une ligne budgétaire est requise")
+ @Size(min = 1, message = "Au moins une ligne budgétaire est requise")
+ @Valid
+ @Builder.Default
+ private List lines = new ArrayList<>();
+
+ @Pattern(regexp = "^[A-Z]{3}$", message = "Code devise invalide (doit être ISO 3 lettres)")
+ private String currency; // Optionnel, défaut XOF
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/RejectTransactionRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/RejectTransactionRequest.java
index 3d52701..6eff748 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/RejectTransactionRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/request/RejectTransactionRequest.java
@@ -1,26 +1,26 @@
-package dev.lions.unionflow.server.api.dto.finance_workflow.request;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Size;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * DTO de requête pour rejeter une transaction
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-03-13
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class RejectTransactionRequest {
-
- @NotBlank(message = "La raison du rejet est requise")
- @Size(min = 10, max = 1000, message = "La raison doit contenir entre 10 et 1000 caractères")
- private String reason;
-}
+package dev.lions.unionflow.server.api.dto.finance_workflow.request;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * DTO de requête pour rejeter une transaction
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-03-13
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class RejectTransactionRequest {
+
+ @NotBlank(message = "La raison du rejet est requise")
+ @Size(min = 10, max = 1000, message = "La raison doit contenir entre 10 et 1000 caractères")
+ private String reason;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/ApproverActionResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/ApproverActionResponse.java
index d75f69e..4cf7f31 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/ApproverActionResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/ApproverActionResponse.java
@@ -1,44 +1,44 @@
-package dev.lions.unionflow.server.api.dto.finance_workflow.response;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import java.time.LocalDateTime;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * DTO de réponse pour une action d'approbateur
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-03-13
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class ApproverActionResponse {
-
- private UUID id;
-
- @NotNull
- private UUID approverId;
-
- @NotBlank
- private String approverName;
-
- @NotBlank
- private String approverRole;
-
- @NotBlank
- private String decision; // PENDING, APPROVED, REJECTED
-
- private String comment;
-
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime decidedAt;
-}
+package dev.lions.unionflow.server.api.dto.finance_workflow.response;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * DTO de réponse pour une action d'approbateur
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-03-13
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class ApproverActionResponse {
+
+ private UUID id;
+
+ @NotNull
+ private UUID approverId;
+
+ @NotBlank
+ private String approverName;
+
+ @NotBlank
+ private String approverRole;
+
+ @NotBlank
+ private String decision; // PENDING, APPROVED, REJECTED
+
+ private String comment;
+
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime decidedAt;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/BudgetLineResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/BudgetLineResponse.java
index bddbbee..b06c97a 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/BudgetLineResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/BudgetLineResponse.java
@@ -1,47 +1,47 @@
-package dev.lions.unionflow.server.api.dto.finance_workflow.response;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import java.math.BigDecimal;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * DTO de réponse pour une ligne budgétaire
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-03-13
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class BudgetLineResponse {
-
- private UUID id;
-
- @NotBlank
- private String category; // CONTRIBUTIONS, SAVINGS, SOLIDARITY, etc.
-
- @NotBlank
- private String name;
-
- private String description;
-
- @NotNull
- private BigDecimal amountPlanned;
-
- @NotNull
- private BigDecimal amountRealized;
-
- private String notes;
-
- // Champs calculés
- private Double realizationRate;
- private BigDecimal variance;
- private Boolean isOverBudget;
-}
+package dev.lions.unionflow.server.api.dto.finance_workflow.response;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * DTO de réponse pour une ligne budgétaire
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-03-13
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class BudgetLineResponse {
+
+ private UUID id;
+
+ @NotBlank
+ private String category; // CONTRIBUTIONS, SAVINGS, SOLIDARITY, etc.
+
+ @NotBlank
+ private String name;
+
+ private String description;
+
+ @NotNull
+ private BigDecimal amountPlanned;
+
+ @NotNull
+ private BigDecimal amountRealized;
+
+ private String notes;
+
+ // Champs calculés
+ private Double realizationRate;
+ private BigDecimal variance;
+ private Boolean isOverBudget;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/BudgetResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/BudgetResponse.java
index 31d8f80..3628132 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/BudgetResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/BudgetResponse.java
@@ -1,92 +1,92 @@
-package dev.lions.unionflow.server.api.dto.finance_workflow.response;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * DTO de réponse pour un budget
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-03-13
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class BudgetResponse {
-
- private UUID id;
-
- @NotBlank
- private String name;
-
- private String description;
-
- @NotNull
- private UUID organizationId;
-
- @NotBlank
- private String period; // MONTHLY, QUARTERLY, SEMIANNUAL, ANNUAL
-
- @NotNull
- private Integer year;
-
- private Integer month;
-
- @NotBlank
- private String status; // DRAFT, ACTIVE, CLOSED, CANCELLED
-
- @Builder.Default
- private List lines = new ArrayList<>();
-
- @NotNull
- private BigDecimal totalPlanned;
-
- @NotNull
- private BigDecimal totalRealized;
-
- @NotBlank
- private String currency;
-
- @NotNull
- private UUID createdById;
-
- @NotNull
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime createdAt;
-
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime approvedAt;
-
- private UUID approvedById;
-
- @NotNull
- @JsonFormat(pattern = "yyyy-MM-dd")
- private LocalDate startDate;
-
- @NotNull
- @JsonFormat(pattern = "yyyy-MM-dd")
- private LocalDate endDate;
-
- private String metadata;
-
- // Champs calculés
- private Double realizationRate;
- private BigDecimal variance;
- private Double varianceRate;
- private Boolean isOverBudget;
- private Boolean isActive;
- private Boolean isCurrentPeriod;
-}
+package dev.lions.unionflow.server.api.dto.finance_workflow.response;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * DTO de réponse pour un budget
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-03-13
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class BudgetResponse {
+
+ private UUID id;
+
+ @NotBlank
+ private String name;
+
+ private String description;
+
+ @NotNull
+ private UUID organizationId;
+
+ @NotBlank
+ private String period; // MONTHLY, QUARTERLY, SEMIANNUAL, ANNUAL
+
+ @NotNull
+ private Integer year;
+
+ private Integer month;
+
+ @NotBlank
+ private String status; // DRAFT, ACTIVE, CLOSED, CANCELLED
+
+ @Builder.Default
+ private List lines = new ArrayList<>();
+
+ @NotNull
+ private BigDecimal totalPlanned;
+
+ @NotNull
+ private BigDecimal totalRealized;
+
+ @NotBlank
+ private String currency;
+
+ @NotNull
+ private UUID createdById;
+
+ @NotNull
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime createdAt;
+
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime approvedAt;
+
+ private UUID approvedById;
+
+ @NotNull
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ private LocalDate startDate;
+
+ @NotNull
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ private LocalDate endDate;
+
+ private String metadata;
+
+ // Champs calculés
+ private Double realizationRate;
+ private BigDecimal variance;
+ private Double varianceRate;
+ private Boolean isOverBudget;
+ private Boolean isActive;
+ private Boolean isCurrentPeriod;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/TransactionApprovalResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/TransactionApprovalResponse.java
index a5a9802..6a2a63a 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/TransactionApprovalResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/finance_workflow/response/TransactionApprovalResponse.java
@@ -1,81 +1,81 @@
-package dev.lions.unionflow.server.api.dto.finance_workflow.response;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-/**
- * DTO de réponse pour une approbation de transaction
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-03-13
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class TransactionApprovalResponse {
-
- private UUID id;
-
- @NotNull
- private UUID transactionId;
-
- @NotBlank
- private String transactionType; // CONTRIBUTION, DEPOSIT, WITHDRAWAL, etc.
-
- @NotNull
- private BigDecimal amount;
-
- @NotBlank
- private String currency;
-
- @NotNull
- private UUID requesterId;
-
- @NotBlank
- private String requesterName;
-
- private UUID organizationId;
-
- @NotBlank
- private String requiredLevel; // NONE, LEVEL1, LEVEL2, LEVEL3
-
- @NotBlank
- private String status; // PENDING, APPROVED, VALIDATED, REJECTED, EXPIRED, CANCELLED
-
- @Builder.Default
- private List approvers = new ArrayList<>();
-
- private String rejectionReason;
-
- @NotNull
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime createdAt;
-
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime expiresAt;
-
- @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
- private LocalDateTime completedAt;
-
- private String metadata;
-
- // Champs calculés
- private Integer approvalCount;
- private Integer requiredApprovals;
- private Boolean hasAllApprovals;
- private Boolean isExpired;
- private Boolean isPending;
- private Boolean isCompleted;
-}
+package dev.lions.unionflow.server.api.dto.finance_workflow.response;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * DTO de réponse pour une approbation de transaction
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-03-13
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class TransactionApprovalResponse {
+
+ private UUID id;
+
+ @NotNull
+ private UUID transactionId;
+
+ @NotBlank
+ private String transactionType; // CONTRIBUTION, DEPOSIT, WITHDRAWAL, etc.
+
+ @NotNull
+ private BigDecimal amount;
+
+ @NotBlank
+ private String currency;
+
+ @NotNull
+ private UUID requesterId;
+
+ @NotBlank
+ private String requesterName;
+
+ private UUID organizationId;
+
+ @NotBlank
+ private String requiredLevel; // NONE, LEVEL1, LEVEL2, LEVEL3
+
+ @NotBlank
+ private String status; // PENDING, APPROVED, VALIDATED, REJECTED, EXPIRED, CANCELLED
+
+ @Builder.Default
+ private List approvers = new ArrayList<>();
+
+ private String rejectionReason;
+
+ @NotNull
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime createdAt;
+
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime expiresAt;
+
+ @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
+ private LocalDateTime completedAt;
+
+ private String metadata;
+
+ // Champs calculés
+ private Integer approvalCount;
+ private Integer requiredApprovals;
+ private Boolean hasAllApprovals;
+ private Boolean isExpired;
+ private Boolean isPending;
+ private Boolean isCompleted;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/formuleabonnement/request/CreateFormuleAbonnementRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/formuleabonnement/request/CreateFormuleAbonnementRequest.java
index a42cfa3..e38ab04 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/formuleabonnement/request/CreateFormuleAbonnementRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/formuleabonnement/request/CreateFormuleAbonnementRequest.java
@@ -1,51 +1,51 @@
-package dev.lions.unionflow.server.api.dto.formuleabonnement.request;
-
-import dev.lions.unionflow.server.api.enums.formuleabonnement.StatutFormule;
-import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
-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 lombok.Builder;
-
-/**
- * Requête de création d'une formule d'abonnement.
- */
-@Builder
-public record CreateFormuleAbonnementRequest(
- @NotBlank(message = "Le nom de la formule est obligatoire") @Size(min = 2, max = 100, message = "Le nom de la formule doit contenir entre 2 et 100 caractères") String nom,
- @NotBlank(message = "Le code de la formule est obligatoire") @Pattern(regexp = "^[A-Z_]{2,20}$", message = "Le code doit contenir uniquement des lettres majuscules et underscores") String code,
- @Size(max = 1000, message = "La description ne peut pas dépasser 1000 caractères") String description,
- @NotNull(message = "Le type de formule est obligatoire") TypeFormule type,
- @NotNull(message = "Le statut est obligatoire") StatutFormule statut,
- @NotNull(message = "Le prix mensuel est obligatoire") @DecimalMin(value = "0.0", inclusive = false) @Digits(integer = 10, fraction = 2) BigDecimal prixMensuel,
- @DecimalMin(value = "0.0", inclusive = false) @Digits(integer = 10, fraction = 2) BigDecimal prixAnnuel,
- @NotBlank(message = "La devise est obligatoire") @Pattern(regexp = "^[A-Z]{3}$") String devise,
- @NotNull(message = "Le nombre maximum de membres est obligatoire") Integer maxMembres,
- @NotNull(message = "Le nombre maximum d'administrateurs est obligatoire") Integer maxAdministrateurs,
- @NotNull(message = "L'espace de stockage est obligatoire") @DecimalMin(value = "0.1", message = "L'espace de stockage doit être d'au moins 0.1 GB") BigDecimal espaceStockageGB,
- @NotNull(message = "Le support technique doit être spécifié") Boolean supportTechnique,
- @Pattern(regexp = "^(EMAIL|CHAT|TELEPHONE|PREMIUM)$", message = "Le niveau de support doit être EMAIL, CHAT, TELEPHONE ou PREMIUM") String niveauSupport,
- Boolean fonctionnalitesAvancees,
- Boolean apiAccess,
- Boolean rapportsPersonnalises,
- Boolean integrationsTierces,
- Boolean sauvegardeAutomatique,
- Boolean multiLangues,
- Boolean personnalisationInterface,
- Boolean formationIncluse,
- Integer heuresFormation,
- Boolean populaire,
- Boolean recommandee,
- Integer periodeEssaiJours,
- LocalDate dateDebutValidite,
- LocalDate dateFinValidite,
- Integer ordreAffichage,
- @Pattern(regexp = "^#[0-9A-Fa-f]{6}$", message = "La couleur doit être un code hexadécimal valide") String couleur,
- @Size(max = 50, message = "Le nom de l'icône ne peut pas dépasser 50 caractères") String icone,
- @Size(max = 500, message = "Les notes ne peuvent pas dépasser 500 caractères") String notes) {
-}
+package dev.lions.unionflow.server.api.dto.formuleabonnement.request;
+
+import dev.lions.unionflow.server.api.enums.formuleabonnement.StatutFormule;
+import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
+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 lombok.Builder;
+
+/**
+ * Requête de création d'une formule d'abonnement.
+ */
+@Builder
+public record CreateFormuleAbonnementRequest(
+ @NotBlank(message = "Le nom de la formule est obligatoire") @Size(min = 2, max = 100, message = "Le nom de la formule doit contenir entre 2 et 100 caractères") String nom,
+ @NotBlank(message = "Le code de la formule est obligatoire") @Pattern(regexp = "^[A-Z_]{2,20}$", message = "Le code doit contenir uniquement des lettres majuscules et underscores") String code,
+ @Size(max = 1000, message = "La description ne peut pas dépasser 1000 caractères") String description,
+ @NotNull(message = "Le type de formule est obligatoire") TypeFormule type,
+ @NotNull(message = "Le statut est obligatoire") StatutFormule statut,
+ @NotNull(message = "Le prix mensuel est obligatoire") @DecimalMin(value = "0.0", inclusive = false) @Digits(integer = 10, fraction = 2) BigDecimal prixMensuel,
+ @DecimalMin(value = "0.0", inclusive = false) @Digits(integer = 10, fraction = 2) BigDecimal prixAnnuel,
+ @NotBlank(message = "La devise est obligatoire") @Pattern(regexp = "^[A-Z]{3}$") String devise,
+ @NotNull(message = "Le nombre maximum de membres est obligatoire") Integer maxMembres,
+ @NotNull(message = "Le nombre maximum d'administrateurs est obligatoire") Integer maxAdministrateurs,
+ @NotNull(message = "L'espace de stockage est obligatoire") @DecimalMin(value = "0.1", message = "L'espace de stockage doit être d'au moins 0.1 GB") BigDecimal espaceStockageGB,
+ @NotNull(message = "Le support technique doit être spécifié") Boolean supportTechnique,
+ @Pattern(regexp = "^(EMAIL|CHAT|TELEPHONE|PREMIUM)$", message = "Le niveau de support doit être EMAIL, CHAT, TELEPHONE ou PREMIUM") String niveauSupport,
+ Boolean fonctionnalitesAvancees,
+ Boolean apiAccess,
+ Boolean rapportsPersonnalises,
+ Boolean integrationsTierces,
+ Boolean sauvegardeAutomatique,
+ Boolean multiLangues,
+ Boolean personnalisationInterface,
+ Boolean formationIncluse,
+ Integer heuresFormation,
+ Boolean populaire,
+ Boolean recommandee,
+ Integer periodeEssaiJours,
+ LocalDate dateDebutValidite,
+ LocalDate dateFinValidite,
+ Integer ordreAffichage,
+ @Pattern(regexp = "^#[0-9A-Fa-f]{6}$", message = "La couleur doit être un code hexadécimal valide") String couleur,
+ @Size(max = 50, message = "Le nom de l'icône ne peut pas dépasser 50 caractères") String icone,
+ @Size(max = 500, message = "Les notes ne peuvent pas dépasser 500 caractères") String notes) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/formuleabonnement/request/UpdateFormuleAbonnementRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/formuleabonnement/request/UpdateFormuleAbonnementRequest.java
index 2db879b..6d8aa56 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/formuleabonnement/request/UpdateFormuleAbonnementRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/formuleabonnement/request/UpdateFormuleAbonnementRequest.java
@@ -1,49 +1,49 @@
-package dev.lions.unionflow.server.api.dto.formuleabonnement.request;
-
-import dev.lions.unionflow.server.api.enums.formuleabonnement.StatutFormule;
-import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Digits;
-import jakarta.validation.constraints.Pattern;
-import jakarta.validation.constraints.Size;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'une formule d'abonnement.
- */
-@Builder
-public record UpdateFormuleAbonnementRequest(
- @Size(min = 2, max = 100, message = "Le nom de la formule doit contenir entre 2 et 100 caractères") String nom,
- @Pattern(regexp = "^[A-Z_]{2,20}$", message = "Le code doit contenir uniquement des lettres majuscules et underscores") String code,
- @Size(max = 1000, message = "La description ne peut pas dépasser 1000 caractères") String description,
- TypeFormule type,
- StatutFormule statut,
- @DecimalMin(value = "0.0", inclusive = false, message = "Le prix mensuel doit être positif") @Digits(integer = 10, fraction = 2) BigDecimal prixMensuel,
- @DecimalMin(value = "0.0", inclusive = false, message = "Le prix annuel doit être positif") @Digits(integer = 10, fraction = 2) BigDecimal prixAnnuel,
- @Pattern(regexp = "^[A-Z]{3}$") String devise,
- Integer maxMembres,
- Integer maxAdministrateurs,
- @DecimalMin(value = "0.1", message = "L'espace de stockage doit être d'au moins 0.1 GB") BigDecimal espaceStockageGB,
- Boolean supportTechnique,
- @Pattern(regexp = "^(EMAIL|CHAT|TELEPHONE|PREMIUM)$", message = "Le niveau de support doit être EMAIL, CHAT, TELEPHONE ou PREMIUM") String niveauSupport,
- Boolean fonctionnalitesAvancees,
- Boolean apiAccess,
- Boolean rapportsPersonnalises,
- Boolean integrationsTierces,
- Boolean sauvegardeAutomatique,
- Boolean multiLangues,
- Boolean personnalisationInterface,
- Boolean formationIncluse,
- Integer heuresFormation,
- Boolean populaire,
- Boolean recommandee,
- Integer periodeEssaiJours,
- LocalDate dateDebutValidite,
- LocalDate dateFinValidite,
- Integer ordreAffichage,
- @Pattern(regexp = "^#[0-9A-Fa-f]{6}$", message = "La couleur doit être un code hexadécimal valide") String couleur,
- @Size(max = 50, message = "Le nom de l'icône ne peut pas dépasser 50 caractères") String icone,
- @Size(max = 500, message = "Les notes ne peuvent pas dépasser 500 caractères") String notes) {
-}
+package dev.lions.unionflow.server.api.dto.formuleabonnement.request;
+
+import dev.lions.unionflow.server.api.enums.formuleabonnement.StatutFormule;
+import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Digits;
+import jakarta.validation.constraints.Pattern;
+import jakarta.validation.constraints.Size;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'une formule d'abonnement.
+ */
+@Builder
+public record UpdateFormuleAbonnementRequest(
+ @Size(min = 2, max = 100, message = "Le nom de la formule doit contenir entre 2 et 100 caractères") String nom,
+ @Pattern(regexp = "^[A-Z_]{2,20}$", message = "Le code doit contenir uniquement des lettres majuscules et underscores") String code,
+ @Size(max = 1000, message = "La description ne peut pas dépasser 1000 caractères") String description,
+ TypeFormule type,
+ StatutFormule statut,
+ @DecimalMin(value = "0.0", inclusive = false, message = "Le prix mensuel doit être positif") @Digits(integer = 10, fraction = 2) BigDecimal prixMensuel,
+ @DecimalMin(value = "0.0", inclusive = false, message = "Le prix annuel doit être positif") @Digits(integer = 10, fraction = 2) BigDecimal prixAnnuel,
+ @Pattern(regexp = "^[A-Z]{3}$") String devise,
+ Integer maxMembres,
+ Integer maxAdministrateurs,
+ @DecimalMin(value = "0.1", message = "L'espace de stockage doit être d'au moins 0.1 GB") BigDecimal espaceStockageGB,
+ Boolean supportTechnique,
+ @Pattern(regexp = "^(EMAIL|CHAT|TELEPHONE|PREMIUM)$", message = "Le niveau de support doit être EMAIL, CHAT, TELEPHONE ou PREMIUM") String niveauSupport,
+ Boolean fonctionnalitesAvancees,
+ Boolean apiAccess,
+ Boolean rapportsPersonnalises,
+ Boolean integrationsTierces,
+ Boolean sauvegardeAutomatique,
+ Boolean multiLangues,
+ Boolean personnalisationInterface,
+ Boolean formationIncluse,
+ Integer heuresFormation,
+ Boolean populaire,
+ Boolean recommandee,
+ Integer periodeEssaiJours,
+ LocalDate dateDebutValidite,
+ LocalDate dateFinValidite,
+ Integer ordreAffichage,
+ @Pattern(regexp = "^#[0-9A-Fa-f]{6}$", message = "La couleur doit être un code hexadécimal valide") String couleur,
+ @Size(max = 50, message = "Le nom de l'icône ne peut pas dépasser 50 caractères") String icone,
+ @Size(max = 500, message = "Les notes ne peuvent pas dépasser 500 caractères") String notes) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/formuleabonnement/response/FormuleAbonnementResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/formuleabonnement/response/FormuleAbonnementResponse.java
index 8fc05a9..bb8ce7d 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/formuleabonnement/response/FormuleAbonnementResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/formuleabonnement/response/FormuleAbonnementResponse.java
@@ -1,161 +1,161 @@
-package dev.lions.unionflow.server.api.dto.formuleabonnement.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import dev.lions.unionflow.server.api.enums.formuleabonnement.StatutFormule;
-import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse détaillée pour une formule d'abonnement.
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class FormuleAbonnementResponse extends BaseResponse {
-
- private String nom;
- private String code;
- private String description;
- private TypeFormule type;
- private StatutFormule statut;
- private BigDecimal prixMensuel;
- private BigDecimal prixAnnuel;
- @Builder.Default
- private String devise = "XOF";
- private Integer maxMembres;
- private Integer maxAdministrateurs;
- private BigDecimal espaceStockageGB;
- private Boolean supportTechnique;
- private String niveauSupport;
- private Boolean fonctionnalitesAvancees;
- private Boolean apiAccess;
- private Boolean rapportsPersonnalises;
- private Boolean integrationsTierces;
- private Boolean sauvegardeAutomatique;
- private Boolean multiLangues;
- private Boolean personnalisationInterface;
- private Boolean formationIncluse;
- private Integer heuresFormation;
- private Boolean populaire;
- private Boolean recommandee;
- private Integer periodeEssaiJours;
- private LocalDate dateDebutValidite;
- private LocalDate dateFinValidite;
- private Integer ordreAffichage;
- private String couleur;
- private String icone;
- private String notes;
-
- public boolean isActive() {
- return StatutFormule.ACTIVE.equals(statut);
- }
-
- public boolean isInactive() {
- return StatutFormule.INACTIVE.equals(statut);
- }
-
- public boolean isArchivee() {
- return StatutFormule.ARCHIVEE.equals(statut);
- }
-
- public boolean isValide() {
- if (!isActive())
- return false;
-
- LocalDate aujourd = LocalDate.now();
- if (dateDebutValidite != null && aujourd.isBefore(dateDebutValidite))
- return false;
- if (dateFinValidite != null && aujourd.isAfter(dateFinValidite))
- return false;
- return true;
- }
-
- public BigDecimal getEconomieAnnuelle() {
- if (prixMensuel == null || prixAnnuel == null)
- return BigDecimal.ZERO;
- BigDecimal coutMensuelAnnuel = prixMensuel.multiply(BigDecimal.valueOf(12));
- return coutMensuelAnnuel.subtract(prixAnnuel);
- }
-
- public int getPourcentageEconomieAnnuelle() {
- if (prixMensuel == null || prixAnnuel == null)
- return 0;
- BigDecimal coutMensuelAnnuel = prixMensuel.multiply(BigDecimal.valueOf(12));
- if (coutMensuelAnnuel.compareTo(BigDecimal.ZERO) > 0) {
- return getEconomieAnnuelle()
- .multiply(BigDecimal.valueOf(100))
- .divide(coutMensuelAnnuel, 0, java.math.RoundingMode.HALF_UP)
- .intValue();
- }
- return 0;
- }
-
- public boolean hasPeriodeEssai() {
- return periodeEssaiJours != null && periodeEssaiJours > 0;
- }
-
- public boolean hasFormation() {
- return Boolean.TRUE.equals(formationIncluse) && heuresFormation != null && heuresFormation > 0;
- }
-
- public boolean isMiseEnAvant() {
- return Boolean.TRUE.equals(populaire) || Boolean.TRUE.equals(recommandee);
- }
-
- public String getBadge() {
- if (Boolean.TRUE.equals(populaire))
- return "POPULAIRE";
- if (Boolean.TRUE.equals(recommandee))
- return "RECOMMANDÉE";
- if (hasPeriodeEssai())
- return "ESSAI GRATUIT";
- return null;
- }
-
- public int getScoreFonctionnalites() {
- if (supportTechnique == null && sauvegardeAutomatique == null && fonctionnalitesAvancees == null
- && apiAccess == null && rapportsPersonnalises == null && integrationsTierces == null
- && multiLangues == null && personnalisationInterface == null) {
- return 0;
- }
- int score = 0;
- int total = 0;
- if (Boolean.TRUE.equals(supportTechnique)) score += 10;
- total += 10;
- if (Boolean.TRUE.equals(sauvegardeAutomatique)) score += 10;
- total += 10;
- if (Boolean.TRUE.equals(fonctionnalitesAvancees)) score += 15;
- total += 15;
- if (Boolean.TRUE.equals(apiAccess)) score += 15;
- total += 15;
- if (Boolean.TRUE.equals(rapportsPersonnalises)) score += 15;
- total += 15;
- if (Boolean.TRUE.equals(integrationsTierces)) score += 15;
- total += 15;
- if (Boolean.TRUE.equals(multiLangues)) score += 10;
- total += 10;
- if (Boolean.TRUE.equals(personnalisationInterface)) score += 10;
- total += 10;
- return (score * 100) / total;
- }
-
- public String getCssClass() {
- if (type == null)
- return "formule-default";
- return switch (type) {
- case BASIC -> "formule-basic";
- case STANDARD -> "formule-standard";
- case PREMIUM -> "formule-premium";
- case ENTERPRISE -> "formule-enterprise";
- };
- }
-}
+package dev.lions.unionflow.server.api.dto.formuleabonnement.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import dev.lions.unionflow.server.api.enums.formuleabonnement.StatutFormule;
+import dev.lions.unionflow.server.api.enums.formuleabonnement.TypeFormule;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse détaillée pour une formule d'abonnement.
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class FormuleAbonnementResponse extends BaseResponse {
+
+ private String nom;
+ private String code;
+ private String description;
+ private TypeFormule type;
+ private StatutFormule statut;
+ private BigDecimal prixMensuel;
+ private BigDecimal prixAnnuel;
+ @Builder.Default
+ private String devise = "XOF";
+ private Integer maxMembres;
+ private Integer maxAdministrateurs;
+ private BigDecimal espaceStockageGB;
+ private Boolean supportTechnique;
+ private String niveauSupport;
+ private Boolean fonctionnalitesAvancees;
+ private Boolean apiAccess;
+ private Boolean rapportsPersonnalises;
+ private Boolean integrationsTierces;
+ private Boolean sauvegardeAutomatique;
+ private Boolean multiLangues;
+ private Boolean personnalisationInterface;
+ private Boolean formationIncluse;
+ private Integer heuresFormation;
+ private Boolean populaire;
+ private Boolean recommandee;
+ private Integer periodeEssaiJours;
+ private LocalDate dateDebutValidite;
+ private LocalDate dateFinValidite;
+ private Integer ordreAffichage;
+ private String couleur;
+ private String icone;
+ private String notes;
+
+ public boolean isActive() {
+ return StatutFormule.ACTIVE.equals(statut);
+ }
+
+ public boolean isInactive() {
+ return StatutFormule.INACTIVE.equals(statut);
+ }
+
+ public boolean isArchivee() {
+ return StatutFormule.ARCHIVEE.equals(statut);
+ }
+
+ public boolean isValide() {
+ if (!isActive())
+ return false;
+
+ LocalDate aujourd = LocalDate.now();
+ if (dateDebutValidite != null && aujourd.isBefore(dateDebutValidite))
+ return false;
+ if (dateFinValidite != null && aujourd.isAfter(dateFinValidite))
+ return false;
+ return true;
+ }
+
+ public BigDecimal getEconomieAnnuelle() {
+ if (prixMensuel == null || prixAnnuel == null)
+ return BigDecimal.ZERO;
+ BigDecimal coutMensuelAnnuel = prixMensuel.multiply(BigDecimal.valueOf(12));
+ return coutMensuelAnnuel.subtract(prixAnnuel);
+ }
+
+ public int getPourcentageEconomieAnnuelle() {
+ if (prixMensuel == null || prixAnnuel == null)
+ return 0;
+ BigDecimal coutMensuelAnnuel = prixMensuel.multiply(BigDecimal.valueOf(12));
+ if (coutMensuelAnnuel.compareTo(BigDecimal.ZERO) > 0) {
+ return getEconomieAnnuelle()
+ .multiply(BigDecimal.valueOf(100))
+ .divide(coutMensuelAnnuel, 0, java.math.RoundingMode.HALF_UP)
+ .intValue();
+ }
+ return 0;
+ }
+
+ public boolean hasPeriodeEssai() {
+ return periodeEssaiJours != null && periodeEssaiJours > 0;
+ }
+
+ public boolean hasFormation() {
+ return Boolean.TRUE.equals(formationIncluse) && heuresFormation != null && heuresFormation > 0;
+ }
+
+ public boolean isMiseEnAvant() {
+ return Boolean.TRUE.equals(populaire) || Boolean.TRUE.equals(recommandee);
+ }
+
+ public String getBadge() {
+ if (Boolean.TRUE.equals(populaire))
+ return "POPULAIRE";
+ if (Boolean.TRUE.equals(recommandee))
+ return "RECOMMANDÉE";
+ if (hasPeriodeEssai())
+ return "ESSAI GRATUIT";
+ return null;
+ }
+
+ public int getScoreFonctionnalites() {
+ if (supportTechnique == null && sauvegardeAutomatique == null && fonctionnalitesAvancees == null
+ && apiAccess == null && rapportsPersonnalises == null && integrationsTierces == null
+ && multiLangues == null && personnalisationInterface == null) {
+ return 0;
+ }
+ int score = 0;
+ int total = 0;
+ if (Boolean.TRUE.equals(supportTechnique)) score += 10;
+ total += 10;
+ if (Boolean.TRUE.equals(sauvegardeAutomatique)) score += 10;
+ total += 10;
+ if (Boolean.TRUE.equals(fonctionnalitesAvancees)) score += 15;
+ total += 15;
+ if (Boolean.TRUE.equals(apiAccess)) score += 15;
+ total += 15;
+ if (Boolean.TRUE.equals(rapportsPersonnalises)) score += 15;
+ total += 15;
+ if (Boolean.TRUE.equals(integrationsTierces)) score += 15;
+ total += 15;
+ if (Boolean.TRUE.equals(multiLangues)) score += 10;
+ total += 10;
+ if (Boolean.TRUE.equals(personnalisationInterface)) score += 10;
+ total += 10;
+ return (score * 100) / total;
+ }
+
+ public String getCssClass() {
+ if (type == null)
+ return "formule-default";
+ return switch (type) {
+ case BASIC -> "formule-basic";
+ case STANDARD -> "formule-standard";
+ case PREMIUM -> "formule-premium";
+ case ENTERPRISE -> "formule-enterprise";
+ };
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/gouvernance/EchelonOrganigrammeDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/gouvernance/EchelonOrganigrammeDTO.java
index f33a349..14c0ce1 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/gouvernance/EchelonOrganigrammeDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/gouvernance/EchelonOrganigrammeDTO.java
@@ -1,29 +1,29 @@
-package dev.lions.unionflow.server.api.dto.gouvernance;
-
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.gouvernance.NiveauEchelon;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class EchelonOrganigrammeDTO extends BaseDTO {
-
- // L'Id physique de l'organisation dans le système (une organisation == un
- // échelon)
- private String organisationId;
-
- // L'organisation mère / chapeau de cet échelon
- private String echelonParentId;
-
- private NiveauEchelon niveau;
-
- private String designation;
- private String zoneGeographiqueOuDelegation;
-}
+package dev.lions.unionflow.server.api.dto.gouvernance;
+
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.gouvernance.NiveauEchelon;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class EchelonOrganigrammeDTO extends BaseDTO {
+
+ // L'Id physique de l'organisation dans le système (une organisation == un
+ // échelon)
+ private String organisationId;
+
+ // L'organisation mère / chapeau de cet échelon
+ private String echelonParentId;
+
+ private NiveauEchelon niveau;
+
+ private String designation;
+ private String zoneGeographiqueOuDelegation;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/lcbft/AlerteLcbFtResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/lcbft/AlerteLcbFtResponse.java
index bea07e0..9147320 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/lcbft/AlerteLcbFtResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/lcbft/AlerteLcbFtResponse.java
@@ -1,42 +1,42 @@
-package dev.lions.unionflow.server.api.dto.lcbft;
-
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-/**
- * DTO de réponse pour une alerte LCB-FT.
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2026-03-15
- */
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class AlerteLcbFtResponse {
-
- private String id;
- private String organisationId;
- private String organisationNom;
- private String membreId;
- private String membreNomComplet;
- private String typeAlerte;
- private LocalDateTime dateAlerte;
- private String description;
- private String details;
- private BigDecimal montant;
- private BigDecimal seuil;
- private String typeOperation;
- private String transactionRef;
- private String severite;
- private Boolean traitee;
- private LocalDateTime dateTraitement;
- private String traitePar;
- private String commentaireTraitement;
-}
+package dev.lions.unionflow.server.api.dto.lcbft;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * DTO de réponse pour une alerte LCB-FT.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2026-03-15
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class AlerteLcbFtResponse {
+
+ private String id;
+ private String organisationId;
+ private String organisationNom;
+ private String membreId;
+ private String membreNomComplet;
+ private String typeAlerte;
+ private LocalDateTime dateAlerte;
+ private String description;
+ private String details;
+ private BigDecimal montant;
+ private BigDecimal seuil;
+ private String typeOperation;
+ private String transactionRef;
+ private String severite;
+ private Boolean traitee;
+ private LocalDateTime dateTraitement;
+ private String traitePar;
+ private String commentaireTraitement;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/membre/MembreSearchCriteria.java b/src/main/java/dev/lions/unionflow/server/api/dto/membre/MembreSearchCriteria.java
index b6dfd4e..5ac4613 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/membre/MembreSearchCriteria.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/membre/MembreSearchCriteria.java
@@ -1,226 +1,226 @@
-package dev.lions.unionflow.server.api.dto.membre;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-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;
-
-/**
- * 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
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-@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;
-
- /** 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 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;
-
- /** Liste des IDs d'organisations */
- @Schema(description = "Liste des IDs d'organisations à inclure")
- private List organisationIds;
-
- /** Liste des rôles à rechercher */
- @Schema(description = "Liste des rôles à rechercher", example = "[\"PRESIDENT\", \"SECRETAIRE\"]")
- private List 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;
-
- /** 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;
-
- /** Â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;
-
- /** 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 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 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;
-
- /** 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;
- }
-
- /**
- * 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;
- }
-
- /** 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);
- }
-
- 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();
- }
-}
+package dev.lions.unionflow.server.api.dto.membre;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+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;
+
+/**
+ * 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
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@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;
+
+ /** 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 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;
+
+ /** Liste des IDs d'organisations */
+ @Schema(description = "Liste des IDs d'organisations à inclure")
+ private List organisationIds;
+
+ /** Liste des rôles à rechercher */
+ @Schema(description = "Liste des rôles à rechercher", example = "[\"PRESIDENT\", \"SECRETAIRE\"]")
+ private List 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;
+
+ /** 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;
+
+ /** Â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;
+
+ /** 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 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 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;
+
+ /** 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;
+ }
+
+ /**
+ * 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;
+ }
+
+ /** 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);
+ }
+
+ 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();
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/membre/MembreSearchResultDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/membre/MembreSearchResultDTO.java
index 14b9ecf..f5219bf 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/membre/MembreSearchResultDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/membre/MembreSearchResultDTO.java
@@ -1,227 +1,227 @@
-package dev.lions.unionflow.server.api.dto.membre;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import dev.lions.unionflow.server.api.dto.membre.response.MembreSummaryResponse;
-import java.util.List;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-/**
- * 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
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-@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 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 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;
-
- /** 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;
-
- /** 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 si c'est la première page */
- @Schema(description = "Indique si c'est la première page")
- @JsonProperty("isFirst")
- private boolean isFirst;
-
- /** Indique si c'est la dernière page */
- @Schema(description = "Indique si c'est la dernière page")
- @JsonProperty("isLast")
- private boolean isLast;
-
- /** 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;
-
- /** 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;
- }
-
- /** 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é";
- }
-
- 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 empty(criteria, 20, 0);
- }
-
- /**
- * Factory method pour créer un résultat vide avec pageSize spécifique
- *
- * @param criteria Critères de recherche
- * @param pageSize Taille de la page
- * @param currentPage Page actuelle
- * @return Résultat vide
- */
- public static MembreSearchResultDTO empty(MembreSearchCriteria criteria, int pageSize, int currentPage) {
- MembreSearchResultDTO result = new MembreSearchResultDTO();
- result.setMembres(List.of());
- result.setTotalElements(0L);
- result.setTotalPages(0);
- result.setCurrentPage(currentPage);
- result.setPageSize(pageSize);
- result.setNumberOfElements(0);
- result.setHasNext(false);
- result.setHasPrevious(false);
- result.isFirst = true; // Assignation directe pour éviter les problèmes avec les setters Lombok
- result.isLast = true; // Assignation directe pour éviter les problèmes avec les setters Lombok
- result.setCriteria(criteria);
- result.setExecutionTimeMs(0L);
- // Initialiser statistics avec des valeurs vides
- result.setStatistics(SearchStatistics.builder()
- .membresActifs(0)
- .membresInactifs(0)
- .ageMoyen(0.0)
- .ageMin(0)
- .ageMax(0)
- .nombreOrganisations(0)
- .nombreRegions(0)
- .ancienneteMoyenne(0.0)
- .build());
- return result;
- }
-}
+package dev.lions.unionflow.server.api.dto.membre;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import dev.lions.unionflow.server.api.dto.membre.response.MembreSummaryResponse;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+/**
+ * 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
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@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 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 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;
+
+ /** 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;
+
+ /** 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 si c'est la première page */
+ @Schema(description = "Indique si c'est la première page")
+ @JsonProperty("isFirst")
+ private boolean isFirst;
+
+ /** Indique si c'est la dernière page */
+ @Schema(description = "Indique si c'est la dernière page")
+ @JsonProperty("isLast")
+ private boolean isLast;
+
+ /** 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;
+
+ /** 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;
+ }
+
+ /** 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é";
+ }
+
+ 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 empty(criteria, 20, 0);
+ }
+
+ /**
+ * Factory method pour créer un résultat vide avec pageSize spécifique
+ *
+ * @param criteria Critères de recherche
+ * @param pageSize Taille de la page
+ * @param currentPage Page actuelle
+ * @return Résultat vide
+ */
+ public static MembreSearchResultDTO empty(MembreSearchCriteria criteria, int pageSize, int currentPage) {
+ MembreSearchResultDTO result = new MembreSearchResultDTO();
+ result.setMembres(List.of());
+ result.setTotalElements(0L);
+ result.setTotalPages(0);
+ result.setCurrentPage(currentPage);
+ result.setPageSize(pageSize);
+ result.setNumberOfElements(0);
+ result.setHasNext(false);
+ result.setHasPrevious(false);
+ result.isFirst = true; // Assignation directe pour éviter les problèmes avec les setters Lombok
+ result.isLast = true; // Assignation directe pour éviter les problèmes avec les setters Lombok
+ result.setCriteria(criteria);
+ result.setExecutionTimeMs(0L);
+ // Initialiser statistics avec des valeurs vides
+ result.setStatistics(SearchStatistics.builder()
+ .membresActifs(0)
+ .membresInactifs(0)
+ .ageMoyen(0.0)
+ .ageMin(0)
+ .ageMax(0)
+ .nombreOrganisations(0)
+ .nombreRegions(0)
+ .ancienneteMoyenne(0.0)
+ .build());
+ return result;
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/membre/request/CreateMembreRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/membre/request/CreateMembreRequest.java
index 1a57671..b182062 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/membre/request/CreateMembreRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/membre/request/CreateMembreRequest.java
@@ -1,52 +1,52 @@
-package dev.lions.unionflow.server.api.dto.membre.request;
-
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import java.time.LocalDate;
-import java.util.UUID;
-
-import lombok.Builder;
-
-/**
- * Requête de création d'un membre.
- *
- *
- * Immutable via {@code record}. Exclut l'ID,
- * les champs d'audit, et le numéroMembre
- * (généré côté serveur).
- *
- * @author UnionFlow Team
- * @version 3.0
- * @since 2026-02-21
- * @param prenom prénom
- * @param nom nom de famille
- * @param email email
- * @param telephone téléphone
- * @param telephoneWave numéro Wave
- * @param dateNaissance date de naissance
- * @param profession profession
- * @param photoUrl URL de la photo
- * @param statutMatrimonial statut matrimonial
- * @param nationalite nationalité
- * @param typeIdentite type pièce d'identité
- * @param numeroIdentite numéro d'identité
- * @param organisationId ID de l'organisation (obligatoire pour ADMIN_ORGANISATION)
- */
-@Builder
-public record CreateMembreRequest(
- @NotBlank @Size(max = 100) String prenom,
- @NotBlank @Size(max = 100) String nom,
- @NotBlank @Email @Size(max = 255) String email,
- @Size(max = 20) String telephone,
- @Size(max = 20) String telephoneWave,
- @NotNull LocalDate dateNaissance,
- @Size(max = 100) String profession,
- @Size(max = 500) String photoUrl,
- @Size(max = 50) String statutMatrimonial,
- @Size(max = 100) String nationalite,
- @Size(max = 50) String typeIdentite,
- @Size(max = 100) String numeroIdentite,
- UUID organisationId) {
-}
+package dev.lions.unionflow.server.api.dto.membre.request;
+
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import java.time.LocalDate;
+import java.util.UUID;
+
+import lombok.Builder;
+
+/**
+ * Requête de création d'un membre.
+ *
+ *
+ * Immutable via {@code record}. Exclut l'ID,
+ * les champs d'audit, et le numéroMembre
+ * (généré côté serveur).
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ * @since 2026-02-21
+ * @param prenom prénom
+ * @param nom nom de famille
+ * @param email email
+ * @param telephone téléphone
+ * @param telephoneWave numéro Wave
+ * @param dateNaissance date de naissance
+ * @param profession profession
+ * @param photoUrl URL de la photo
+ * @param statutMatrimonial statut matrimonial
+ * @param nationalite nationalité
+ * @param typeIdentite type pièce d'identité
+ * @param numeroIdentite numéro d'identité
+ * @param organisationId ID de l'organisation (obligatoire pour ADMIN_ORGANISATION)
+ */
+@Builder
+public record CreateMembreRequest(
+ @NotBlank @Size(max = 100) String prenom,
+ @NotBlank @Size(max = 100) String nom,
+ @NotBlank @Email @Size(max = 255) String email,
+ @Size(max = 20) String telephone,
+ @Size(max = 20) String telephoneWave,
+ @NotNull LocalDate dateNaissance,
+ @Size(max = 100) String profession,
+ @Size(max = 500) String photoUrl,
+ @Size(max = 50) String statutMatrimonial,
+ @Size(max = 100) String nationalite,
+ @Size(max = 50) String typeIdentite,
+ @Size(max = 100) String numeroIdentite,
+ UUID organisationId) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/membre/request/UpdateMembreRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/membre/request/UpdateMembreRequest.java
index 59f2c70..9e39633 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/membre/request/UpdateMembreRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/membre/request/UpdateMembreRequest.java
@@ -1,26 +1,26 @@
-package dev.lions.unionflow.server.api.dto.membre.request;
-
-import jakarta.validation.constraints.*;
-import java.time.LocalDate;
-
-import lombok.Builder;
-
-/**
- * Requête pour mettre à jour un membre existant.
- */
-@Builder
-public record UpdateMembreRequest(
- @NotBlank @Size(max = 100) String prenom,
- @NotBlank @Size(max = 100) String nom,
- @NotBlank @Email @Size(max = 255) String email,
- @Size(max = 20) String telephone,
- @Size(max = 20) String telephoneWave,
- @NotNull LocalDate dateNaissance,
- @Size(max = 100) String profession,
- @Size(max = 500) String photoUrl,
- @Size(max = 50) String statutMatrimonial,
- @Size(max = 100) String nationalite,
- @Size(max = 50) String typeIdentite,
- @Size(max = 100) String numeroIdentite,
- Boolean actif) {
-}
+package dev.lions.unionflow.server.api.dto.membre.request;
+
+import jakarta.validation.constraints.*;
+import java.time.LocalDate;
+
+import lombok.Builder;
+
+/**
+ * Requête pour mettre à jour un membre existant.
+ */
+@Builder
+public record UpdateMembreRequest(
+ @NotBlank @Size(max = 100) String prenom,
+ @NotBlank @Size(max = 100) String nom,
+ @NotBlank @Email @Size(max = 255) String email,
+ @Size(max = 20) String telephone,
+ @Size(max = 20) String telephoneWave,
+ @NotNull LocalDate dateNaissance,
+ @Size(max = 100) String profession,
+ @Size(max = 500) String photoUrl,
+ @Size(max = 50) String statutMatrimonial,
+ @Size(max = 100) String nationalite,
+ @Size(max = 50) String typeIdentite,
+ @Size(max = 100) String numeroIdentite,
+ Boolean actif) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/membre/response/MembreResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/membre/response/MembreResponse.java
index ae38058..e57904f 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/membre/response/MembreResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/membre/response/MembreResponse.java
@@ -1,136 +1,136 @@
-package dev.lions.unionflow.server.api.dto.membre.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
-import java.util.UUID;
-import java.util.List;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse contenant les données d'un membre.
- *
- *
- * Classe Lombok (getters/setters) pour la
- * compatibilité avec les frameworks d'affichage
- * (PrimeFaces, etc.).
- *
- * @author UnionFlow Team
- * @version 3.0
- * @since 2026-02-21
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class MembreResponse extends BaseResponse {
-
- // ── Identité ───────────────────────────────
- private String numeroMembre;
- private UUID keycloakId;
- private String prenom;
- private String nom;
- private String nomComplet;
- private String email;
- private String telephone;
- private String telephoneWave;
- private LocalDate dateNaissance;
- private int age;
-
- // ── Personnel ──────────────────────────────
- private String profession;
- private String photoUrl;
- private String statutMatrimonial;
- private String statutMatrimonialLibelle;
- private String nationalite;
- private String typeIdentite;
- private String typeIdentiteLibelle;
- private String numeroIdentite;
-
- // ── KYC / LCB-FT ───────────────────────────
- private String niveauVigilanceKyc;
- private String statutKyc;
- private LocalDate dateVerificationIdentite;
-
- // ── Statut ─────────────────────────────────
- private String statutCompte;
- private String statutCompteLibelle;
- private String statutCompteSeverity;
- private List roles;
-
- // ── Adhésion (contexte organisation) ───────
- private UUID organisationId;
- private String organisationNom;
- private LocalDate dateAdhesion;
-
- // ── Adresse principale ─────────────────────
- private String adresse;
- private String ville;
- private String codePostal;
-
- // ── Notes / biographie ─────────────────────
- private String notes;
-
- // ── Statistiques ───────────────────────────
- private int nombreEvenementsParticipes;
-
- // ── Provisionnement (retourné une seule fois à la création) ────
- /** Mot de passe temporaire généré lors du provisionnement Keycloak.
- * Null pour toutes les autres opérations. L'utilisateur devra le changer à la première connexion. */
- private String motDePasseTemporaire;
-
- // ── Méthodes calculées pour la compatibilité JSF EL ────────────
-
- /** Initiales (première lettre prénom + première lettre nom) pour les avatars JSF. */
- public String getInitiales() {
- String p = (prenom != null && !prenom.isEmpty()) ? prenom.substring(0, 1).toUpperCase() : "";
- String n = (nom != null && !nom.isEmpty()) ? nom.substring(0, 1).toUpperCase() : "";
- return p + n;
- }
-
- /** Date d'adhésion formatée "dd/MM/yyyy" pour #{membre.dateAdhesionFormatee}. */
- public String getDateAdhesionFormatee() {
- if (dateAdhesion == null) return null;
- return dateAdhesion.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
- }
-
- /** Alias de statutCompte pour #{membre.statut}. */
- public String getStatut() {
- return statutCompte;
- }
-
- /** Alias de statutCompteSeverity pour #{membre.statutSeverity}. */
- public String getStatutSeverity() {
- return statutCompteSeverity;
- }
-
- /** Libellé du rôle principal calculé depuis les rôles. */
- public String getTypeMembre() {
- if (roles == null || roles.isEmpty()) return "Membre";
- if (roles.contains("PRESIDENT")) return "Président";
- if (roles.contains("VICE_PRESIDENT")) return "Vice-Président";
- if (roles.contains("SECRETAIRE")) return "Secrétaire";
- if (roles.contains("TRESORIER")) return "Trésorier";
- if (roles.contains("ADMIN_ORGANISATION")) return "Administrateur";
- if (roles.contains("MODERATEUR")) return "Modérateur";
- return "Membre";
- }
-
- /** Severity PrimeUI calculée depuis les rôles. */
- public String getTypeSeverity() {
- if (roles == null || roles.isEmpty()) return "secondary";
- if (roles.contains("PRESIDENT")) return "primary";
- if (roles.contains("VICE_PRESIDENT")) return "primary";
- if (roles.contains("SECRETAIRE")) return "info";
- if (roles.contains("TRESORIER")) return "warning";
- if (roles.contains("ADMIN_ORGANISATION")) return "danger";
- if (roles.contains("MODERATEUR")) return "warning";
- return "secondary";
- }
-}
+package dev.lions.unionflow.server.api.dto.membre.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.UUID;
+import java.util.List;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse contenant les données d'un membre.
+ *
+ *
+ * Classe Lombok (getters/setters) pour la
+ * compatibilité avec les frameworks d'affichage
+ * (PrimeFaces, etc.).
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ * @since 2026-02-21
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class MembreResponse extends BaseResponse {
+
+ // ── Identité ───────────────────────────────
+ private String numeroMembre;
+ private UUID keycloakId;
+ private String prenom;
+ private String nom;
+ private String nomComplet;
+ private String email;
+ private String telephone;
+ private String telephoneWave;
+ private LocalDate dateNaissance;
+ private int age;
+
+ // ── Personnel ──────────────────────────────
+ private String profession;
+ private String photoUrl;
+ private String statutMatrimonial;
+ private String statutMatrimonialLibelle;
+ private String nationalite;
+ private String typeIdentite;
+ private String typeIdentiteLibelle;
+ private String numeroIdentite;
+
+ // ── KYC / LCB-FT ───────────────────────────
+ private String niveauVigilanceKyc;
+ private String statutKyc;
+ private LocalDate dateVerificationIdentite;
+
+ // ── Statut ─────────────────────────────────
+ private String statutCompte;
+ private String statutCompteLibelle;
+ private String statutCompteSeverity;
+ private List roles;
+
+ // ── Adhésion (contexte organisation) ───────
+ private UUID organisationId;
+ private String organisationNom;
+ private LocalDate dateAdhesion;
+
+ // ── Adresse principale ─────────────────────
+ private String adresse;
+ private String ville;
+ private String codePostal;
+
+ // ── Notes / biographie ─────────────────────
+ private String notes;
+
+ // ── Statistiques ───────────────────────────
+ private int nombreEvenementsParticipes;
+
+ // ── Provisionnement (retourné une seule fois à la création) ────
+ /** Mot de passe temporaire généré lors du provisionnement Keycloak.
+ * Null pour toutes les autres opérations. L'utilisateur devra le changer à la première connexion. */
+ private String motDePasseTemporaire;
+
+ // ── Méthodes calculées pour la compatibilité JSF EL ────────────
+
+ /** Initiales (première lettre prénom + première lettre nom) pour les avatars JSF. */
+ public String getInitiales() {
+ String p = (prenom != null && !prenom.isEmpty()) ? prenom.substring(0, 1).toUpperCase() : "";
+ String n = (nom != null && !nom.isEmpty()) ? nom.substring(0, 1).toUpperCase() : "";
+ return p + n;
+ }
+
+ /** Date d'adhésion formatée "dd/MM/yyyy" pour #{membre.dateAdhesionFormatee}. */
+ public String getDateAdhesionFormatee() {
+ if (dateAdhesion == null) return null;
+ return dateAdhesion.format(DateTimeFormatter.ofPattern("dd/MM/yyyy"));
+ }
+
+ /** Alias de statutCompte pour #{membre.statut}. */
+ public String getStatut() {
+ return statutCompte;
+ }
+
+ /** Alias de statutCompteSeverity pour #{membre.statutSeverity}. */
+ public String getStatutSeverity() {
+ return statutCompteSeverity;
+ }
+
+ /** Libellé du rôle principal calculé depuis les rôles. */
+ public String getTypeMembre() {
+ if (roles == null || roles.isEmpty()) return "Membre";
+ if (roles.contains("PRESIDENT")) return "Président";
+ if (roles.contains("VICE_PRESIDENT")) return "Vice-Président";
+ if (roles.contains("SECRETAIRE")) return "Secrétaire";
+ if (roles.contains("TRESORIER")) return "Trésorier";
+ if (roles.contains("ADMIN_ORGANISATION")) return "Administrateur";
+ if (roles.contains("MODERATEUR")) return "Modérateur";
+ return "Membre";
+ }
+
+ /** Severity PrimeUI calculée depuis les rôles. */
+ public String getTypeSeverity() {
+ if (roles == null || roles.isEmpty()) return "secondary";
+ if (roles.contains("PRESIDENT")) return "primary";
+ if (roles.contains("VICE_PRESIDENT")) return "primary";
+ if (roles.contains("SECRETAIRE")) return "info";
+ if (roles.contains("TRESORIER")) return "warning";
+ if (roles.contains("ADMIN_ORGANISATION")) return "danger";
+ if (roles.contains("MODERATEUR")) return "warning";
+ return "secondary";
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/DemandeCreditRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/DemandeCreditRequest.java
index 9574795..50ddfe8 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/DemandeCreditRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/DemandeCreditRequest.java
@@ -1,49 +1,49 @@
-package dev.lions.unionflow.server.api.dto.mutuelle.credit;
-
-import dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeCredit;
-import dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeGarantie;
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Min;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-@Schema(description = "Requête initiale pour une demande de financement (Crédit)")
-public class DemandeCreditRequest {
-
- @NotBlank(message = "L'ID du demandeur est obligatoire")
- private String membreId;
-
- @NotNull(message = "Le type de crédit est obligatoire")
- private TypeCredit typeCredit;
-
- @NotNull(message = "Le montant demandé est obligatoire")
- @DecimalMin(value = "1.0", message = "Le montant demandé doit être positif")
- private BigDecimal montantDemande;
-
- @Min(value = 1, message = "La durée (en mois) doit être au moins de 1 mois")
- private Integer dureeMois;
-
- @Schema(description = "Compte épargne adossé (si remboursement automatique ou nantissement)")
- private String compteLieId;
-
- @NotBlank(message = "Le motif détaillé du financement est requis (Plan d'affaires, usage...)")
- private String justificationDetaillee;
-
- @Schema(description = "Liste des IDs de documents justificatifs attachés au dossier")
- private List documentIds;
-
- @Schema(description = "Liste des garanties proposées avec la demande")
- private List garantiesProposees;
-}
+package dev.lions.unionflow.server.api.dto.mutuelle.credit;
+
+import dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeCredit;
+import dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeGarantie;
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Min;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@Schema(description = "Requête initiale pour une demande de financement (Crédit)")
+public class DemandeCreditRequest {
+
+ @NotBlank(message = "L'ID du demandeur est obligatoire")
+ private String membreId;
+
+ @NotNull(message = "Le type de crédit est obligatoire")
+ private TypeCredit typeCredit;
+
+ @NotNull(message = "Le montant demandé est obligatoire")
+ @DecimalMin(value = "1.0", message = "Le montant demandé doit être positif")
+ private BigDecimal montantDemande;
+
+ @Min(value = 1, message = "La durée (en mois) doit être au moins de 1 mois")
+ private Integer dureeMois;
+
+ @Schema(description = "Compte épargne adossé (si remboursement automatique ou nantissement)")
+ private String compteLieId;
+
+ @NotBlank(message = "Le motif détaillé du financement est requis (Plan d'affaires, usage...)")
+ private String justificationDetaillee;
+
+ @Schema(description = "Liste des IDs de documents justificatifs attachés au dossier")
+ private List documentIds;
+
+ @Schema(description = "Liste des garanties proposées avec la demande")
+ private List garantiesProposees;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/DemandeCreditResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/DemandeCreditResponse.java
index b306201..6cd32f4 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/DemandeCreditResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/DemandeCreditResponse.java
@@ -1,48 +1,48 @@
-package dev.lions.unionflow.server.api.dto.mutuelle.credit;
-
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.mutuelle.credit.StatutDemandeCredit;
-import dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeCredit;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.List;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-@Schema(description = "Réponse avec le tableau de bord résumé d'un dossier de crédit")
-public class DemandeCreditResponse extends BaseDTO {
-
- private String numeroDossier;
- private String membreId;
- private TypeCredit typeCredit;
- private String compteLieId;
-
- private BigDecimal montantDemande;
- private Integer dureeMoisDemande;
-
- // Conditions actées par le comité de crédit (peuvent différer de la demande)
- private BigDecimal montantApprouve;
- private Integer dureeMoisApprouvee;
- private BigDecimal tauxInteretAnnuel; // Pourcentage
- private BigDecimal coutTotalCredit; // Total Intérêts
-
- private StatutDemandeCredit statut;
- private String notesComite;
-
- private LocalDate dateSoumission;
- private LocalDate dateValidation;
- private LocalDate datePremierEcheance;
-
- @Schema(description = "Aperçu des échéances générées pour le tableau d'amortissement")
- private List echeancier;
-}
+package dev.lions.unionflow.server.api.dto.mutuelle.credit;
+
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.mutuelle.credit.StatutDemandeCredit;
+import dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeCredit;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@Schema(description = "Réponse avec le tableau de bord résumé d'un dossier de crédit")
+public class DemandeCreditResponse extends BaseDTO {
+
+ private String numeroDossier;
+ private String membreId;
+ private TypeCredit typeCredit;
+ private String compteLieId;
+
+ private BigDecimal montantDemande;
+ private Integer dureeMoisDemande;
+
+ // Conditions actées par le comité de crédit (peuvent différer de la demande)
+ private BigDecimal montantApprouve;
+ private Integer dureeMoisApprouvee;
+ private BigDecimal tauxInteretAnnuel; // Pourcentage
+ private BigDecimal coutTotalCredit; // Total Intérêts
+
+ private StatutDemandeCredit statut;
+ private String notesComite;
+
+ private LocalDate dateSoumission;
+ private LocalDate dateValidation;
+ private LocalDate datePremierEcheance;
+
+ @Schema(description = "Aperçu des échéances générées pour le tableau d'amortissement")
+ private List echeancier;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/EcheanceCreditDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/EcheanceCreditDTO.java
index 3461bba..b54d223 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/EcheanceCreditDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/EcheanceCreditDTO.java
@@ -1,44 +1,44 @@
-package dev.lions.unionflow.server.api.dto.mutuelle.credit;
-
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.mutuelle.credit.StatutEcheanceCredit;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-@Schema(description = "Représente une ligne unique du tableau d'amortissement d'un crédit")
-public class EcheanceCreditDTO extends BaseDTO {
-
- private String demandeCreditId;
-
- @Schema(description = "Indice de l'échéance (ex: mois 1, 2, 3...)")
- private Integer ordre;
-
- private LocalDate dateEcheancePrevue;
- private LocalDate datePaiementEffectif;
-
- private BigDecimal capitalAmorti;
- private BigDecimal interetsDeLaPeriode;
- private BigDecimal montantTotalExigible;
-
- private BigDecimal capitalRestantDu;
-
- // Pénalités éventuelles additionnelles liées au retard
- private BigDecimal penalitesRetard;
-
- // Somme physiquement encaissée pour cette traite à l'instant T
- private BigDecimal montantRegle;
-
- private StatutEcheanceCredit statut;
-}
+package dev.lions.unionflow.server.api.dto.mutuelle.credit;
+
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.mutuelle.credit.StatutEcheanceCredit;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@Schema(description = "Représente une ligne unique du tableau d'amortissement d'un crédit")
+public class EcheanceCreditDTO extends BaseDTO {
+
+ private String demandeCreditId;
+
+ @Schema(description = "Indice de l'échéance (ex: mois 1, 2, 3...)")
+ private Integer ordre;
+
+ private LocalDate dateEcheancePrevue;
+ private LocalDate datePaiementEffectif;
+
+ private BigDecimal capitalAmorti;
+ private BigDecimal interetsDeLaPeriode;
+ private BigDecimal montantTotalExigible;
+
+ private BigDecimal capitalRestantDu;
+
+ // Pénalités éventuelles additionnelles liées au retard
+ private BigDecimal penalitesRetard;
+
+ // Somme physiquement encaissée pour cette traite à l'instant T
+ private BigDecimal montantRegle;
+
+ private StatutEcheanceCredit statut;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/GarantieDemandeDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/GarantieDemandeDTO.java
index 108fa61..87cb2b5 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/GarantieDemandeDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/credit/GarantieDemandeDTO.java
@@ -1,28 +1,28 @@
-package dev.lions.unionflow.server.api.dto.mutuelle.credit;
-
-import dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeGarantie;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.math.BigDecimal;
-
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class GarantieDemandeDTO {
-
- @NotNull(message = "Le type de garantie est requis")
- private TypeGarantie typeGarantie;
-
- private BigDecimal valeurEstimee;
-
- @NotBlank(message = "Description ou référence requise (Id Membre Caution, SN du Véhicule, Titre Foncier...)")
- private String referenceOuDescription;
-
- private String documentPreuveId;
-}
+package dev.lions.unionflow.server.api.dto.mutuelle.credit;
+
+import dev.lions.unionflow.server.api.enums.mutuelle.credit.TypeGarantie;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class GarantieDemandeDTO {
+
+ @NotNull(message = "Le type de garantie est requis")
+ private TypeGarantie typeGarantie;
+
+ private BigDecimal valeurEstimee;
+
+ @NotBlank(message = "Description ou référence requise (Id Membre Caution, SN du Véhicule, Titre Foncier...)")
+ private String referenceOuDescription;
+
+ private String documentPreuveId;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/CompteEpargneRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/CompteEpargneRequest.java
index 76284da..c53ef2c 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/CompteEpargneRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/CompteEpargneRequest.java
@@ -1,33 +1,33 @@
-package dev.lions.unionflow.server.api.dto.mutuelle.epargne;
-
-import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeCompteEpargne;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-@Schema(description = "Requête d'ouverture d'un compte d'épargne")
-public class CompteEpargneRequest {
-
- @NotBlank(message = "L'ID du membre propriétaire est obligatoire")
- @Schema(description = "ID UUID du Membre détenteur")
- private String membreId;
-
- @NotBlank(message = "L'ID de l'organisation est obligatoire")
- @Schema(description = "ID UUID de l'Organisation / Mutuelle")
- private String organisationId;
-
- @NotNull(message = "Le type de compte est obligatoire")
- @Schema(description = "Le type du compte d'épargne demandé")
- private TypeCompteEpargne typeCompte;
-
- @Schema(description = "Notes ou détails éventuels lors de l'ouverture")
- private String notesOuverture;
-}
+package dev.lions.unionflow.server.api.dto.mutuelle.epargne;
+
+import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeCompteEpargne;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@Schema(description = "Requête d'ouverture d'un compte d'épargne")
+public class CompteEpargneRequest {
+
+ @NotBlank(message = "L'ID du membre propriétaire est obligatoire")
+ @Schema(description = "ID UUID du Membre détenteur")
+ private String membreId;
+
+ @NotBlank(message = "L'ID de l'organisation est obligatoire")
+ @Schema(description = "ID UUID de l'Organisation / Mutuelle")
+ private String organisationId;
+
+ @NotNull(message = "Le type de compte est obligatoire")
+ @Schema(description = "Le type du compte d'épargne demandé")
+ private TypeCompteEpargne typeCompte;
+
+ @Schema(description = "Notes ou détails éventuels lors de l'ouverture")
+ private String notesOuverture;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/CompteEpargneResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/CompteEpargneResponse.java
index f04d8de..d57ffab 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/CompteEpargneResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/CompteEpargneResponse.java
@@ -1,42 +1,42 @@
-package dev.lions.unionflow.server.api.dto.mutuelle.epargne;
-
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.mutuelle.epargne.StatutCompteEpargne;
-import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeCompteEpargne;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-@Schema(description = "Réponse des informations d'un compte épargne")
-public class CompteEpargneResponse extends BaseDTO {
-
- private String membreId;
- private String organisationId;
-
- @Schema(description = "Numéro de compte généré de manière unique (ex: MEC-00123)")
- private String numeroCompte;
-
- private TypeCompteEpargne typeCompte;
-
- @Schema(description = "Solde principal disponible")
- private BigDecimal soldeActuel;
-
- @Schema(description = "Fonds gelés pour garantie de crédits")
- private BigDecimal soldeBloque;
-
- private StatutCompteEpargne statut;
- private LocalDate dateOuverture;
- private LocalDate dateDerniereTransaction;
- private String description;
-}
+package dev.lions.unionflow.server.api.dto.mutuelle.epargne;
+
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.mutuelle.epargne.StatutCompteEpargne;
+import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeCompteEpargne;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@Schema(description = "Réponse des informations d'un compte épargne")
+public class CompteEpargneResponse extends BaseDTO {
+
+ private String membreId;
+ private String organisationId;
+
+ @Schema(description = "Numéro de compte généré de manière unique (ex: MEC-00123)")
+ private String numeroCompte;
+
+ private TypeCompteEpargne typeCompte;
+
+ @Schema(description = "Solde principal disponible")
+ private BigDecimal soldeActuel;
+
+ @Schema(description = "Fonds gelés pour garantie de crédits")
+ private BigDecimal soldeBloque;
+
+ private StatutCompteEpargne statut;
+ private LocalDate dateOuverture;
+ private LocalDate dateDerniereTransaction;
+ private String description;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/TransactionEpargneRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/TransactionEpargneRequest.java
index 9942adc..ec0badd 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/TransactionEpargneRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/TransactionEpargneRequest.java
@@ -1,43 +1,43 @@
-package dev.lions.unionflow.server.api.dto.mutuelle.epargne;
-
-import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeTransactionEpargne;
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-import org.eclipse.microprofile.openapi.annotations.media.Schema;
-
-import java.math.BigDecimal;
-
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-@Schema(description = "Requête d'initialisation d'une transaction sur un compte d'épargne")
-public class TransactionEpargneRequest {
-
- @NotBlank(message = "L'ID du compte épargne cible est obligatoire")
- private String compteId;
-
- @NotNull(message = "Le type de transaction est requis")
- private TypeTransactionEpargne typeTransaction;
-
- @NotNull(message = "Le montant est obligatoire")
- @DecimalMin(value = "0.01", message = "Le montant doit être supérieur à 0")
- private BigDecimal montant;
-
- @Schema(description = "ID d'un compte de destination en cas de transfert interne")
- private String compteDestinationId;
-
- @Schema(description = "Motif, libellé ou preuve de dépôt")
- private String motif;
-
- @Schema(description = "Origine des fonds (LCB-FT) — obligatoire au-dessus du seuil configuré (ex. Salaire, Vente, Héritage)")
- private String origineFonds;
-
- @Schema(description = "ID de la pièce justificative (document) — requis au-dessus du seuil LCB-FT")
- private String pieceJustificativeId;
-}
+package dev.lions.unionflow.server.api.dto.mutuelle.epargne;
+
+import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeTransactionEpargne;
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.eclipse.microprofile.openapi.annotations.media.Schema;
+
+import java.math.BigDecimal;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+@Schema(description = "Requête d'initialisation d'une transaction sur un compte d'épargne")
+public class TransactionEpargneRequest {
+
+ @NotBlank(message = "L'ID du compte épargne cible est obligatoire")
+ private String compteId;
+
+ @NotNull(message = "Le type de transaction est requis")
+ private TypeTransactionEpargne typeTransaction;
+
+ @NotNull(message = "Le montant est obligatoire")
+ @DecimalMin(value = "0.01", message = "Le montant doit être supérieur à 0")
+ private BigDecimal montant;
+
+ @Schema(description = "ID d'un compte de destination en cas de transfert interne")
+ private String compteDestinationId;
+
+ @Schema(description = "Motif, libellé ou preuve de dépôt")
+ private String motif;
+
+ @Schema(description = "Origine des fonds (LCB-FT) — obligatoire au-dessus du seuil configuré (ex. Salaire, Vente, Héritage)")
+ private String origineFonds;
+
+ @Schema(description = "ID de la pièce justificative (document) — requis au-dessus du seuil LCB-FT")
+ private String pieceJustificativeId;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/TransactionEpargneResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/TransactionEpargneResponse.java
index bbd45b9..5ae0a56 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/TransactionEpargneResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/mutuelle/epargne/TransactionEpargneResponse.java
@@ -1,44 +1,44 @@
-package dev.lions.unionflow.server.api.dto.mutuelle.epargne;
-
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeTransactionEpargne;
-import dev.lions.unionflow.server.api.enums.wave.StatutTransactionWave;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class TransactionEpargneResponse extends BaseDTO {
-
- private String compteId;
- private TypeTransactionEpargne type;
- private BigDecimal montant;
-
- // Pour assurer un audit et les principes de comptabilité double entrée
- private BigDecimal soldeAvant;
- private BigDecimal soldeApres;
-
- private String motif;
- private LocalDateTime dateTransaction;
- private String operateurId;
-
- private String referenceExterne;
-
- // Status général d'une transaction (Validée, Rejetée, En traitement Wave)
- private StatutTransactionWave statutExecution;
-
- /** Origine des fonds déclarée (LCB-FT) */
- private String origineFonds;
-
- /** Référence pièce justificative (LCB-FT) */
- private String pieceJustificativeId;
-}
+package dev.lions.unionflow.server.api.dto.mutuelle.epargne;
+
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.mutuelle.epargne.TypeTransactionEpargne;
+import dev.lions.unionflow.server.api.enums.wave.StatutTransactionWave;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class TransactionEpargneResponse extends BaseDTO {
+
+ private String compteId;
+ private TypeTransactionEpargne type;
+ private BigDecimal montant;
+
+ // Pour assurer un audit et les principes de comptabilité double entrée
+ private BigDecimal soldeAvant;
+ private BigDecimal soldeApres;
+
+ private String motif;
+ private LocalDateTime dateTransaction;
+ private String operateurId;
+
+ private String referenceExterne;
+
+ // Status général d'une transaction (Validée, Rejetée, En traitement Wave)
+ private StatutTransactionWave statutExecution;
+
+ /** Origine des fonds déclarée (LCB-FT) */
+ private String origineFonds;
+
+ /** Référence pièce justificative (LCB-FT) */
+ private String pieceJustificativeId;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/notification/ActionNotificationDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/notification/ActionNotificationDTO.java
index e246178..776da9e 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/notification/ActionNotificationDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/notification/ActionNotificationDTO.java
@@ -1,477 +1,477 @@
-package dev.lions.unionflow.server.api.dto.notification;
-
-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.
- *
- * @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 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 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 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 getParametres() {
- return parametres;
- }
-
- public void setParametres(Map 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 getDonneesPersonnalisees() {
- return donneesPersonnalisees;
- }
-
- public void setDonneesPersonnalisees(Map 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;
- }
- }
- 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;
- }
- }
- 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);
- }
-}
+package dev.lions.unionflow.server.api.dto.notification;
+
+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.
+ *
+ * @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 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 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 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 getParametres() {
+ return parametres;
+ }
+
+ public void setParametres(Map 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 getDonneesPersonnalisees() {
+ return donneesPersonnalisees;
+ }
+
+ public void setDonneesPersonnalisees(Map 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;
+ }
+ }
+ 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;
+ }
+ }
+ 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);
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/notification/PreferenceCanalNotificationDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/notification/PreferenceCanalNotificationDTO.java
index 0c77dba..738f0c5 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/notification/PreferenceCanalNotificationDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/notification/PreferenceCanalNotificationDTO.java
@@ -1,119 +1,119 @@
-package dev.lions.unionflow.server.api.dto.notification;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-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;
- }
-}
+package dev.lions.unionflow.server.api.dto.notification;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+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;
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/notification/PreferenceTypeNotificationDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/notification/PreferenceTypeNotificationDTO.java
index c251838..9c13ab1 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/notification/PreferenceTypeNotificationDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/notification/PreferenceTypeNotificationDTO.java
@@ -1,132 +1,132 @@
-package dev.lions.unionflow.server.api.dto.notification;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-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;
- }
-}
+package dev.lions.unionflow.server.api.dto.notification;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+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;
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/notification/PreferencesNotificationDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/notification/PreferencesNotificationDTO.java
index a15ffc4..7770304 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/notification/PreferencesNotificationDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/notification/PreferencesNotificationDTO.java
@@ -1,636 +1,636 @@
-package dev.lions.unionflow.server.api.dto.notification;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import dev.lions.unionflow.server.api.enums.notification.CanalNotification;
-import dev.lions.unionflow.server.api.enums.notification.TypeNotification;
-import jakarta.validation.constraints.*;
-import java.time.LocalTime;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * DTO pour les préférences de notification d'un utilisateur
- *
- * Ce DTO représente les préférences personnalisées d'un utilisateur concernant la réception et
- * l'affichage des notifications.
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-16
- */
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class PreferencesNotificationDTO {
-
- /** Identifiant unique des préférences */
- private String id;
-
- /** Identifiant de l'utilisateur */
- @NotBlank(message = "L'identifiant utilisateur est obligatoire")
- private String utilisateurId;
-
- /** Identifiant de l'organisation */
- private String organisationId;
-
- /** Indique si les notifications sont activées globalement */
- @NotNull(message = "L'activation globale des notifications est obligatoire")
- private Boolean notificationsActivees;
-
- /** Indique si les notifications push sont activées */
- private Boolean pushActivees;
-
- /** Indique si les notifications par email sont activées */
- private Boolean emailActivees;
-
- /** Indique si les notifications SMS sont activées */
- private Boolean smsActivees;
-
- /** Indique si les notifications in-app sont activées */
- private Boolean inAppActivees;
-
- /** Types de notifications activés */
- private Set typesActives;
-
- /** Types de notifications désactivés */
- private Set typesDesactivees;
-
- /** Canaux de notification activés */
- private Set canauxActifs;
-
- /** Canaux de notification désactivés */
- private Set canauxDesactives;
-
- /** Mode Ne Pas Déranger activé */
- private Boolean modeSilencieux;
-
- /** Heure de début du mode silencieux */
- @JsonFormat(pattern = "HH:mm")
- private LocalTime heureDebutSilencieux;
-
- /** Heure de fin du mode silencieux */
- @JsonFormat(pattern = "HH:mm")
- private LocalTime heureFinSilencieux;
-
- /** Jours de la semaine pour le mode silencieux (1=Lundi, 7=Dimanche) */
- private Set joursSilencieux;
-
- /** Indique si les notifications urgentes passent outre le mode silencieux */
- private Boolean urgentesIgnorentSilencieux;
-
- /** Fréquence de regroupement des notifications (minutes) */
- @Min(value = 0, message = "La fréquence de regroupement doit être positive")
- @Max(value = 1440, message = "La fréquence de regroupement ne peut pas dépasser 24h")
- private Integer frequenceRegroupementMinutes;
-
- /** Nombre maximum de notifications affichées simultanément */
- @Min(value = 1, message = "Le nombre maximum de notifications doit être au moins 1")
- @Max(value = 50, message = "Le nombre maximum de notifications ne peut pas dépasser 50")
- private Integer maxNotificationsSimultanees;
-
- /** Durée d'affichage par défaut des notifications (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 doivent vibrer */
- private Boolean vibrationActivee;
-
- /** Indique si les notifications doivent émettre un son */
- private Boolean sonActive;
-
- /** Indique si la LED doit s'allumer */
- private Boolean ledActivee;
-
- /** Son personnalisé pour les notifications */
- private String sonPersonnalise;
-
- /** Pattern de vibration personnalisé */
- private long[] patternVibrationPersonnalise;
-
- /** Couleur de LED personnalisée */
- private String couleurLEDPersonnalisee;
-
- /** Indique si les aperçus de contenu sont affichés sur l'écran de verrouillage */
- private Boolean apercuEcranVerrouillage;
-
- /** Indique si les notifications sont affichées dans l'historique */
- private Boolean affichageHistorique;
-
- /** Durée de conservation dans l'historique (jours) */
- @Min(value = 1, message = "La durée de conservation doit être au moins 1 jour")
- @Max(value = 365, message = "La durée de conservation ne peut pas dépasser 1 an")
- private Integer dureeConservationJours;
-
- /** Indique si les notifications sont automatiquement marquées comme lues */
- private Boolean marquageLectureAutomatique;
-
- /** Délai avant marquage automatique comme lu (secondes) */
- private Integer delaiMarquageLectureSecondes;
-
- /** Indique si les notifications sont automatiquement archivées */
- private Boolean archivageAutomatique;
-
- /** Délai avant archivage automatique (heures) */
- private Integer delaiArchivageHeures;
-
- /** Préférences par type de notification */
- private Map preferencesParType;
-
- /** Préférences par canal de notification */
- private Map preferencesParCanal;
-
- /** Mots-clés pour filtrage automatique */
- private Set motsClesFiltre;
-
- /** Expéditeurs bloqués */
- private Set expediteursBloqués;
-
- /** Expéditeurs prioritaires */
- private Set expediteursPrioritaires;
-
- /** Indique si les notifications de test sont activées */
- private Boolean notificationsTestActivees;
-
- /** Niveau de log pour les notifications (DEBUG, INFO, WARN, ERROR) */
- private String niveauLog;
-
- /** Token FCM pour les notifications push */
- private String tokenFCM;
-
- /** Plateforme de l'appareil (android, ios, web) */
- private String plateforme;
-
- /** Version de l'application */
- private String versionApp;
-
- /** Langue préférée pour les notifications */
- private String langue;
-
- /** Fuseau horaire de l'utilisateur */
- private String fuseauHoraire;
-
- /** Métadonnées personnalisées */
- private Map metadonnees;
-
- // === CONSTRUCTEURS ===
-
- /** Constructeur par défaut avec valeurs par défaut */
- public PreferencesNotificationDTO() {
- this.notificationsActivees = true;
- this.pushActivees = true;
- this.emailActivees = true;
- this.smsActivees = false;
- this.inAppActivees = true;
- this.modeSilencieux = false;
- this.urgentesIgnorentSilencieux = true;
- this.frequenceRegroupementMinutes = 5;
- this.maxNotificationsSimultanees = 10;
- this.dureeAffichageSecondes = 10;
- this.vibrationActivee = true;
- this.sonActive = true;
- this.ledActivee = true;
- this.apercuEcranVerrouillage = true;
- this.affichageHistorique = true;
- this.dureeConservationJours = 30;
- this.marquageLectureAutomatique = false;
- this.archivageAutomatique = true;
- this.delaiArchivageHeures = 168; // 1 semaine
- this.notificationsTestActivees = false;
- this.niveauLog = "INFO";
- this.langue = "fr";
- }
-
- /** Constructeur avec utilisateur */
- public PreferencesNotificationDTO(String utilisateurId) {
- this();
- this.utilisateurId = utilisateurId;
- }
-
- // === GETTERS ET SETTERS ===
-
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public String getUtilisateurId() {
- return utilisateurId;
- }
-
- public void setUtilisateurId(String utilisateurId) {
- this.utilisateurId = utilisateurId;
- }
-
- public String getOrganisationId() {
- return organisationId;
- }
-
- public void setOrganisationId(String organisationId) {
- this.organisationId = organisationId;
- }
-
- public Boolean getNotificationsActivees() {
- return notificationsActivees;
- }
-
- public void setNotificationsActivees(Boolean notificationsActivees) {
- this.notificationsActivees = notificationsActivees;
- }
-
- public Boolean getPushActivees() {
- return pushActivees;
- }
-
- public void setPushActivees(Boolean pushActivees) {
- this.pushActivees = pushActivees;
- }
-
- public Boolean getEmailActivees() {
- return emailActivees;
- }
-
- public void setEmailActivees(Boolean emailActivees) {
- this.emailActivees = emailActivees;
- }
-
- public Boolean getSmsActivees() {
- return smsActivees;
- }
-
- public void setSmsActivees(Boolean smsActivees) {
- this.smsActivees = smsActivees;
- }
-
- public Boolean getInAppActivees() {
- return inAppActivees;
- }
-
- public void setInAppActivees(Boolean inAppActivees) {
- this.inAppActivees = inAppActivees;
- }
-
- public Set getTypesActives() {
- return typesActives;
- }
-
- public void setTypesActives(Set typesActives) {
- this.typesActives = typesActives;
- }
-
- public Set getTypesDesactivees() {
- return typesDesactivees;
- }
-
- public void setTypesDesactivees(Set typesDesactivees) {
- this.typesDesactivees = typesDesactivees;
- }
-
- public Set getCanauxActifs() {
- return canauxActifs;
- }
-
- public void setCanauxActifs(Set canauxActifs) {
- this.canauxActifs = canauxActifs;
- }
-
- public Set getCanauxDesactives() {
- return canauxDesactives;
- }
-
- public void setCanauxDesactives(Set canauxDesactives) {
- this.canauxDesactives = canauxDesactives;
- }
-
- public Boolean getModeSilencieux() {
- return modeSilencieux;
- }
-
- public void setModeSilencieux(Boolean modeSilencieux) {
- this.modeSilencieux = modeSilencieux;
- }
-
- public LocalTime getHeureDebutSilencieux() {
- return heureDebutSilencieux;
- }
-
- public void setHeureDebutSilencieux(LocalTime heureDebutSilencieux) {
- this.heureDebutSilencieux = heureDebutSilencieux;
- }
-
- public LocalTime getHeureFinSilencieux() {
- return heureFinSilencieux;
- }
-
- public void setHeureFinSilencieux(LocalTime heureFinSilencieux) {
- this.heureFinSilencieux = heureFinSilencieux;
- }
-
- public Set getJoursSilencieux() {
- return joursSilencieux;
- }
-
- public void setJoursSilencieux(Set joursSilencieux) {
- this.joursSilencieux = joursSilencieux;
- }
-
- public Boolean getUrgentesIgnorentSilencieux() {
- return urgentesIgnorentSilencieux;
- }
-
- public void setUrgentesIgnorentSilencieux(Boolean urgentesIgnorentSilencieux) {
- this.urgentesIgnorentSilencieux = urgentesIgnorentSilencieux;
- }
-
- public Integer getFrequenceRegroupementMinutes() {
- return frequenceRegroupementMinutes;
- }
-
- public void setFrequenceRegroupementMinutes(Integer frequenceRegroupementMinutes) {
- this.frequenceRegroupementMinutes = frequenceRegroupementMinutes;
- }
-
- public Integer getMaxNotificationsSimultanees() {
- return maxNotificationsSimultanees;
- }
-
- public void setMaxNotificationsSimultanees(Integer maxNotificationsSimultanees) {
- this.maxNotificationsSimultanees = maxNotificationsSimultanees;
- }
-
- public Integer getDureeAffichageSecondes() {
- return dureeAffichageSecondes;
- }
-
- public void setDureeAffichageSecondes(Integer dureeAffichageSecondes) {
- this.dureeAffichageSecondes = dureeAffichageSecondes;
- }
-
- public Boolean getVibrationActivee() {
- return vibrationActivee;
- }
-
- public void setVibrationActivee(Boolean vibrationActivee) {
- this.vibrationActivee = vibrationActivee;
- }
-
- public Boolean getSonActive() {
- return sonActive;
- }
-
- public void setSonActive(Boolean sonActive) {
- this.sonActive = sonActive;
- }
-
- public Boolean getLedActivee() {
- return ledActivee;
- }
-
- public void setLedActivee(Boolean ledActivee) {
- this.ledActivee = ledActivee;
- }
-
- public String getSonPersonnalise() {
- return sonPersonnalise;
- }
-
- public void setSonPersonnalise(String sonPersonnalise) {
- this.sonPersonnalise = sonPersonnalise;
- }
-
- public long[] getPatternVibrationPersonnalise() {
- return patternVibrationPersonnalise;
- }
-
- public void setPatternVibrationPersonnalise(long[] patternVibrationPersonnalise) {
- this.patternVibrationPersonnalise = patternVibrationPersonnalise;
- }
-
- public String getCouleurLEDPersonnalisee() {
- return couleurLEDPersonnalisee;
- }
-
- public void setCouleurLEDPersonnalisee(String couleurLEDPersonnalisee) {
- this.couleurLEDPersonnalisee = couleurLEDPersonnalisee;
- }
-
- public Boolean getApercuEcranVerrouillage() {
- return apercuEcranVerrouillage;
- }
-
- public void setApercuEcranVerrouillage(Boolean apercuEcranVerrouillage) {
- this.apercuEcranVerrouillage = apercuEcranVerrouillage;
- }
-
- public Boolean getAffichageHistorique() {
- return affichageHistorique;
- }
-
- public void setAffichageHistorique(Boolean affichageHistorique) {
- this.affichageHistorique = affichageHistorique;
- }
-
- public Integer getDureeConservationJours() {
- return dureeConservationJours;
- }
-
- public void setDureeConservationJours(Integer dureeConservationJours) {
- this.dureeConservationJours = dureeConservationJours;
- }
-
- public Boolean getMarquageLectureAutomatique() {
- return marquageLectureAutomatique;
- }
-
- public void setMarquageLectureAutomatique(Boolean marquageLectureAutomatique) {
- this.marquageLectureAutomatique = marquageLectureAutomatique;
- }
-
- public Integer getDelaiMarquageLectureSecondes() {
- return delaiMarquageLectureSecondes;
- }
-
- public void setDelaiMarquageLectureSecondes(Integer delaiMarquageLectureSecondes) {
- this.delaiMarquageLectureSecondes = delaiMarquageLectureSecondes;
- }
-
- public Boolean getArchivageAutomatique() {
- return archivageAutomatique;
- }
-
- public void setArchivageAutomatique(Boolean archivageAutomatique) {
- this.archivageAutomatique = archivageAutomatique;
- }
-
- public Integer getDelaiArchivageHeures() {
- return delaiArchivageHeures;
- }
-
- public void setDelaiArchivageHeures(Integer delaiArchivageHeures) {
- this.delaiArchivageHeures = delaiArchivageHeures;
- }
-
- public Map getPreferencesParType() {
- return preferencesParType;
- }
-
- public void setPreferencesParType(
- Map preferencesParType) {
- this.preferencesParType = preferencesParType;
- }
-
- public Map getPreferencesParCanal() {
- return preferencesParCanal;
- }
-
- public void setPreferencesParCanal(
- Map preferencesParCanal) {
- this.preferencesParCanal = preferencesParCanal;
- }
-
- public Set getMotsClesFiltre() {
- return motsClesFiltre;
- }
-
- public void setMotsClesFiltre(Set motsClesFiltre) {
- this.motsClesFiltre = motsClesFiltre;
- }
-
- public Set getExpediteursBloques() {
- return expediteursBloqués;
- }
-
- public void setExpediteursBloques(Set expediteursBloqués) {
- this.expediteursBloqués = expediteursBloqués;
- }
-
- public Set getExpediteursPrioritaires() {
- return expediteursPrioritaires;
- }
-
- public void setExpediteursPrioritaires(Set expediteursPrioritaires) {
- this.expediteursPrioritaires = expediteursPrioritaires;
- }
-
- public Boolean getNotificationsTestActivees() {
- return notificationsTestActivees;
- }
-
- public void setNotificationsTestActivees(Boolean notificationsTestActivees) {
- this.notificationsTestActivees = notificationsTestActivees;
- }
-
- public String getNiveauLog() {
- return niveauLog;
- }
-
- public void setNiveauLog(String niveauLog) {
- this.niveauLog = niveauLog;
- }
-
- public String getTokenFCM() {
- return tokenFCM;
- }
-
- public void setTokenFCM(String tokenFCM) {
- this.tokenFCM = tokenFCM;
- }
-
- public String getPlateforme() {
- return plateforme;
- }
-
- public void setPlateforme(String plateforme) {
- this.plateforme = plateforme;
- }
-
- public String getVersionApp() {
- return versionApp;
- }
-
- public void setVersionApp(String versionApp) {
- this.versionApp = versionApp;
- }
-
- public String getLangue() {
- return langue;
- }
-
- public void setLangue(String langue) {
- this.langue = langue;
- }
-
- public String getFuseauHoraire() {
- return fuseauHoraire;
- }
-
- public void setFuseauHoraire(String fuseauHoraire) {
- this.fuseauHoraire = fuseauHoraire;
- }
-
- public Map getMetadonnees() {
- return metadonnees;
- }
-
- public void setMetadonnees(Map metadonnees) {
- this.metadonnees = metadonnees;
- }
-
- // === MÉTHODES UTILITAIRES ===
-
- /** Vérifie si un type de notification est activé */
- public boolean isTypeActive(TypeNotification type) {
- if (!notificationsActivees) return false;
- if (typesDesactivees != null && typesDesactivees.contains(type)) return false;
- if (typesActives != null) return typesActives.contains(type);
- return type.isActiveeParDefaut();
- }
-
- /** Vérifie si un canal de notification est activé */
- public boolean isCanalActif(CanalNotification canal) {
- if (!notificationsActivees) return false;
- if (canauxDesactives != null && canauxDesactives.contains(canal)) return false;
- if (canauxActifs != null) return canauxActifs.contains(canal);
- return true;
- }
-
- /**
- * Version de test de isEnModeSilencieux avec une heure fixe
- * Permet de tester toutes les branches sans dépendre de l'heure actuelle
- */
- boolean isEnModeSilencieux(LocalTime heureActuelle) {
- if (!modeSilencieux) return false;
- if (heureDebutSilencieux == null || heureFinSilencieux == null) return false;
-
- // Gestion du cas où la période traverse minuit
- if (heureDebutSilencieux.isAfter(heureFinSilencieux)) {
- return heureActuelle.isAfter(heureDebutSilencieux) || heureActuelle.isBefore(heureFinSilencieux);
- } else {
- return heureActuelle.isAfter(heureDebutSilencieux) && heureActuelle.isBefore(heureFinSilencieux);
- }
- }
-
- /** Vérifie si on est en mode silencieux actuellement */
- public boolean isEnModeSilencieux() {
- return isEnModeSilencieux(LocalTime.now());
- }
-
- /** Vérifie si un expéditeur est bloqué */
- public boolean isExpediteurBloque(String expediteurId) {
- return expediteursBloqués != null && expediteursBloqués.contains(expediteurId);
- }
-
- /** Vérifie si un expéditeur est prioritaire */
- public boolean isExpediteurPrioritaire(String expediteurId) {
- return expediteursPrioritaires != null && expediteursPrioritaires.contains(expediteurId);
- }
-
- @Override
- public String toString() {
- return String.format(
- "PreferencesNotificationDTO{utilisateurId='%s', notificationsActivees=%s}",
- utilisateurId, notificationsActivees);
- }
-}
+package dev.lions.unionflow.server.api.dto.notification;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import dev.lions.unionflow.server.api.enums.notification.CanalNotification;
+import dev.lions.unionflow.server.api.enums.notification.TypeNotification;
+import jakarta.validation.constraints.*;
+import java.time.LocalTime;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * DTO pour les préférences de notification d'un utilisateur
+ *
+ * Ce DTO représente les préférences personnalisées d'un utilisateur concernant la réception et
+ * l'affichage des notifications.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2025-01-16
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PreferencesNotificationDTO {
+
+ /** Identifiant unique des préférences */
+ private String id;
+
+ /** Identifiant de l'utilisateur */
+ @NotBlank(message = "L'identifiant utilisateur est obligatoire")
+ private String utilisateurId;
+
+ /** Identifiant de l'organisation */
+ private String organisationId;
+
+ /** Indique si les notifications sont activées globalement */
+ @NotNull(message = "L'activation globale des notifications est obligatoire")
+ private Boolean notificationsActivees;
+
+ /** Indique si les notifications push sont activées */
+ private Boolean pushActivees;
+
+ /** Indique si les notifications par email sont activées */
+ private Boolean emailActivees;
+
+ /** Indique si les notifications SMS sont activées */
+ private Boolean smsActivees;
+
+ /** Indique si les notifications in-app sont activées */
+ private Boolean inAppActivees;
+
+ /** Types de notifications activés */
+ private Set typesActives;
+
+ /** Types de notifications désactivés */
+ private Set typesDesactivees;
+
+ /** Canaux de notification activés */
+ private Set canauxActifs;
+
+ /** Canaux de notification désactivés */
+ private Set canauxDesactives;
+
+ /** Mode Ne Pas Déranger activé */
+ private Boolean modeSilencieux;
+
+ /** Heure de début du mode silencieux */
+ @JsonFormat(pattern = "HH:mm")
+ private LocalTime heureDebutSilencieux;
+
+ /** Heure de fin du mode silencieux */
+ @JsonFormat(pattern = "HH:mm")
+ private LocalTime heureFinSilencieux;
+
+ /** Jours de la semaine pour le mode silencieux (1=Lundi, 7=Dimanche) */
+ private Set joursSilencieux;
+
+ /** Indique si les notifications urgentes passent outre le mode silencieux */
+ private Boolean urgentesIgnorentSilencieux;
+
+ /** Fréquence de regroupement des notifications (minutes) */
+ @Min(value = 0, message = "La fréquence de regroupement doit être positive")
+ @Max(value = 1440, message = "La fréquence de regroupement ne peut pas dépasser 24h")
+ private Integer frequenceRegroupementMinutes;
+
+ /** Nombre maximum de notifications affichées simultanément */
+ @Min(value = 1, message = "Le nombre maximum de notifications doit être au moins 1")
+ @Max(value = 50, message = "Le nombre maximum de notifications ne peut pas dépasser 50")
+ private Integer maxNotificationsSimultanees;
+
+ /** Durée d'affichage par défaut des notifications (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 doivent vibrer */
+ private Boolean vibrationActivee;
+
+ /** Indique si les notifications doivent émettre un son */
+ private Boolean sonActive;
+
+ /** Indique si la LED doit s'allumer */
+ private Boolean ledActivee;
+
+ /** Son personnalisé pour les notifications */
+ private String sonPersonnalise;
+
+ /** Pattern de vibration personnalisé */
+ private long[] patternVibrationPersonnalise;
+
+ /** Couleur de LED personnalisée */
+ private String couleurLEDPersonnalisee;
+
+ /** Indique si les aperçus de contenu sont affichés sur l'écran de verrouillage */
+ private Boolean apercuEcranVerrouillage;
+
+ /** Indique si les notifications sont affichées dans l'historique */
+ private Boolean affichageHistorique;
+
+ /** Durée de conservation dans l'historique (jours) */
+ @Min(value = 1, message = "La durée de conservation doit être au moins 1 jour")
+ @Max(value = 365, message = "La durée de conservation ne peut pas dépasser 1 an")
+ private Integer dureeConservationJours;
+
+ /** Indique si les notifications sont automatiquement marquées comme lues */
+ private Boolean marquageLectureAutomatique;
+
+ /** Délai avant marquage automatique comme lu (secondes) */
+ private Integer delaiMarquageLectureSecondes;
+
+ /** Indique si les notifications sont automatiquement archivées */
+ private Boolean archivageAutomatique;
+
+ /** Délai avant archivage automatique (heures) */
+ private Integer delaiArchivageHeures;
+
+ /** Préférences par type de notification */
+ private Map preferencesParType;
+
+ /** Préférences par canal de notification */
+ private Map preferencesParCanal;
+
+ /** Mots-clés pour filtrage automatique */
+ private Set motsClesFiltre;
+
+ /** Expéditeurs bloqués */
+ private Set expediteursBloqués;
+
+ /** Expéditeurs prioritaires */
+ private Set expediteursPrioritaires;
+
+ /** Indique si les notifications de test sont activées */
+ private Boolean notificationsTestActivees;
+
+ /** Niveau de log pour les notifications (DEBUG, INFO, WARN, ERROR) */
+ private String niveauLog;
+
+ /** Token FCM pour les notifications push */
+ private String tokenFCM;
+
+ /** Plateforme de l'appareil (android, ios, web) */
+ private String plateforme;
+
+ /** Version de l'application */
+ private String versionApp;
+
+ /** Langue préférée pour les notifications */
+ private String langue;
+
+ /** Fuseau horaire de l'utilisateur */
+ private String fuseauHoraire;
+
+ /** Métadonnées personnalisées */
+ private Map metadonnees;
+
+ // === CONSTRUCTEURS ===
+
+ /** Constructeur par défaut avec valeurs par défaut */
+ public PreferencesNotificationDTO() {
+ this.notificationsActivees = true;
+ this.pushActivees = true;
+ this.emailActivees = true;
+ this.smsActivees = false;
+ this.inAppActivees = true;
+ this.modeSilencieux = false;
+ this.urgentesIgnorentSilencieux = true;
+ this.frequenceRegroupementMinutes = 5;
+ this.maxNotificationsSimultanees = 10;
+ this.dureeAffichageSecondes = 10;
+ this.vibrationActivee = true;
+ this.sonActive = true;
+ this.ledActivee = true;
+ this.apercuEcranVerrouillage = true;
+ this.affichageHistorique = true;
+ this.dureeConservationJours = 30;
+ this.marquageLectureAutomatique = false;
+ this.archivageAutomatique = true;
+ this.delaiArchivageHeures = 168; // 1 semaine
+ this.notificationsTestActivees = false;
+ this.niveauLog = "INFO";
+ this.langue = "fr";
+ }
+
+ /** Constructeur avec utilisateur */
+ public PreferencesNotificationDTO(String utilisateurId) {
+ this();
+ this.utilisateurId = utilisateurId;
+ }
+
+ // === GETTERS ET SETTERS ===
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getUtilisateurId() {
+ return utilisateurId;
+ }
+
+ public void setUtilisateurId(String utilisateurId) {
+ this.utilisateurId = utilisateurId;
+ }
+
+ public String getOrganisationId() {
+ return organisationId;
+ }
+
+ public void setOrganisationId(String organisationId) {
+ this.organisationId = organisationId;
+ }
+
+ public Boolean getNotificationsActivees() {
+ return notificationsActivees;
+ }
+
+ public void setNotificationsActivees(Boolean notificationsActivees) {
+ this.notificationsActivees = notificationsActivees;
+ }
+
+ public Boolean getPushActivees() {
+ return pushActivees;
+ }
+
+ public void setPushActivees(Boolean pushActivees) {
+ this.pushActivees = pushActivees;
+ }
+
+ public Boolean getEmailActivees() {
+ return emailActivees;
+ }
+
+ public void setEmailActivees(Boolean emailActivees) {
+ this.emailActivees = emailActivees;
+ }
+
+ public Boolean getSmsActivees() {
+ return smsActivees;
+ }
+
+ public void setSmsActivees(Boolean smsActivees) {
+ this.smsActivees = smsActivees;
+ }
+
+ public Boolean getInAppActivees() {
+ return inAppActivees;
+ }
+
+ public void setInAppActivees(Boolean inAppActivees) {
+ this.inAppActivees = inAppActivees;
+ }
+
+ public Set getTypesActives() {
+ return typesActives;
+ }
+
+ public void setTypesActives(Set typesActives) {
+ this.typesActives = typesActives;
+ }
+
+ public Set getTypesDesactivees() {
+ return typesDesactivees;
+ }
+
+ public void setTypesDesactivees(Set typesDesactivees) {
+ this.typesDesactivees = typesDesactivees;
+ }
+
+ public Set getCanauxActifs() {
+ return canauxActifs;
+ }
+
+ public void setCanauxActifs(Set canauxActifs) {
+ this.canauxActifs = canauxActifs;
+ }
+
+ public Set getCanauxDesactives() {
+ return canauxDesactives;
+ }
+
+ public void setCanauxDesactives(Set canauxDesactives) {
+ this.canauxDesactives = canauxDesactives;
+ }
+
+ public Boolean getModeSilencieux() {
+ return modeSilencieux;
+ }
+
+ public void setModeSilencieux(Boolean modeSilencieux) {
+ this.modeSilencieux = modeSilencieux;
+ }
+
+ public LocalTime getHeureDebutSilencieux() {
+ return heureDebutSilencieux;
+ }
+
+ public void setHeureDebutSilencieux(LocalTime heureDebutSilencieux) {
+ this.heureDebutSilencieux = heureDebutSilencieux;
+ }
+
+ public LocalTime getHeureFinSilencieux() {
+ return heureFinSilencieux;
+ }
+
+ public void setHeureFinSilencieux(LocalTime heureFinSilencieux) {
+ this.heureFinSilencieux = heureFinSilencieux;
+ }
+
+ public Set getJoursSilencieux() {
+ return joursSilencieux;
+ }
+
+ public void setJoursSilencieux(Set joursSilencieux) {
+ this.joursSilencieux = joursSilencieux;
+ }
+
+ public Boolean getUrgentesIgnorentSilencieux() {
+ return urgentesIgnorentSilencieux;
+ }
+
+ public void setUrgentesIgnorentSilencieux(Boolean urgentesIgnorentSilencieux) {
+ this.urgentesIgnorentSilencieux = urgentesIgnorentSilencieux;
+ }
+
+ public Integer getFrequenceRegroupementMinutes() {
+ return frequenceRegroupementMinutes;
+ }
+
+ public void setFrequenceRegroupementMinutes(Integer frequenceRegroupementMinutes) {
+ this.frequenceRegroupementMinutes = frequenceRegroupementMinutes;
+ }
+
+ public Integer getMaxNotificationsSimultanees() {
+ return maxNotificationsSimultanees;
+ }
+
+ public void setMaxNotificationsSimultanees(Integer maxNotificationsSimultanees) {
+ this.maxNotificationsSimultanees = maxNotificationsSimultanees;
+ }
+
+ public Integer getDureeAffichageSecondes() {
+ return dureeAffichageSecondes;
+ }
+
+ public void setDureeAffichageSecondes(Integer dureeAffichageSecondes) {
+ this.dureeAffichageSecondes = dureeAffichageSecondes;
+ }
+
+ public Boolean getVibrationActivee() {
+ return vibrationActivee;
+ }
+
+ public void setVibrationActivee(Boolean vibrationActivee) {
+ this.vibrationActivee = vibrationActivee;
+ }
+
+ public Boolean getSonActive() {
+ return sonActive;
+ }
+
+ public void setSonActive(Boolean sonActive) {
+ this.sonActive = sonActive;
+ }
+
+ public Boolean getLedActivee() {
+ return ledActivee;
+ }
+
+ public void setLedActivee(Boolean ledActivee) {
+ this.ledActivee = ledActivee;
+ }
+
+ public String getSonPersonnalise() {
+ return sonPersonnalise;
+ }
+
+ public void setSonPersonnalise(String sonPersonnalise) {
+ this.sonPersonnalise = sonPersonnalise;
+ }
+
+ public long[] getPatternVibrationPersonnalise() {
+ return patternVibrationPersonnalise;
+ }
+
+ public void setPatternVibrationPersonnalise(long[] patternVibrationPersonnalise) {
+ this.patternVibrationPersonnalise = patternVibrationPersonnalise;
+ }
+
+ public String getCouleurLEDPersonnalisee() {
+ return couleurLEDPersonnalisee;
+ }
+
+ public void setCouleurLEDPersonnalisee(String couleurLEDPersonnalisee) {
+ this.couleurLEDPersonnalisee = couleurLEDPersonnalisee;
+ }
+
+ public Boolean getApercuEcranVerrouillage() {
+ return apercuEcranVerrouillage;
+ }
+
+ public void setApercuEcranVerrouillage(Boolean apercuEcranVerrouillage) {
+ this.apercuEcranVerrouillage = apercuEcranVerrouillage;
+ }
+
+ public Boolean getAffichageHistorique() {
+ return affichageHistorique;
+ }
+
+ public void setAffichageHistorique(Boolean affichageHistorique) {
+ this.affichageHistorique = affichageHistorique;
+ }
+
+ public Integer getDureeConservationJours() {
+ return dureeConservationJours;
+ }
+
+ public void setDureeConservationJours(Integer dureeConservationJours) {
+ this.dureeConservationJours = dureeConservationJours;
+ }
+
+ public Boolean getMarquageLectureAutomatique() {
+ return marquageLectureAutomatique;
+ }
+
+ public void setMarquageLectureAutomatique(Boolean marquageLectureAutomatique) {
+ this.marquageLectureAutomatique = marquageLectureAutomatique;
+ }
+
+ public Integer getDelaiMarquageLectureSecondes() {
+ return delaiMarquageLectureSecondes;
+ }
+
+ public void setDelaiMarquageLectureSecondes(Integer delaiMarquageLectureSecondes) {
+ this.delaiMarquageLectureSecondes = delaiMarquageLectureSecondes;
+ }
+
+ public Boolean getArchivageAutomatique() {
+ return archivageAutomatique;
+ }
+
+ public void setArchivageAutomatique(Boolean archivageAutomatique) {
+ this.archivageAutomatique = archivageAutomatique;
+ }
+
+ public Integer getDelaiArchivageHeures() {
+ return delaiArchivageHeures;
+ }
+
+ public void setDelaiArchivageHeures(Integer delaiArchivageHeures) {
+ this.delaiArchivageHeures = delaiArchivageHeures;
+ }
+
+ public Map getPreferencesParType() {
+ return preferencesParType;
+ }
+
+ public void setPreferencesParType(
+ Map preferencesParType) {
+ this.preferencesParType = preferencesParType;
+ }
+
+ public Map getPreferencesParCanal() {
+ return preferencesParCanal;
+ }
+
+ public void setPreferencesParCanal(
+ Map preferencesParCanal) {
+ this.preferencesParCanal = preferencesParCanal;
+ }
+
+ public Set getMotsClesFiltre() {
+ return motsClesFiltre;
+ }
+
+ public void setMotsClesFiltre(Set motsClesFiltre) {
+ this.motsClesFiltre = motsClesFiltre;
+ }
+
+ public Set getExpediteursBloques() {
+ return expediteursBloqués;
+ }
+
+ public void setExpediteursBloques(Set expediteursBloqués) {
+ this.expediteursBloqués = expediteursBloqués;
+ }
+
+ public Set getExpediteursPrioritaires() {
+ return expediteursPrioritaires;
+ }
+
+ public void setExpediteursPrioritaires(Set expediteursPrioritaires) {
+ this.expediteursPrioritaires = expediteursPrioritaires;
+ }
+
+ public Boolean getNotificationsTestActivees() {
+ return notificationsTestActivees;
+ }
+
+ public void setNotificationsTestActivees(Boolean notificationsTestActivees) {
+ this.notificationsTestActivees = notificationsTestActivees;
+ }
+
+ public String getNiveauLog() {
+ return niveauLog;
+ }
+
+ public void setNiveauLog(String niveauLog) {
+ this.niveauLog = niveauLog;
+ }
+
+ public String getTokenFCM() {
+ return tokenFCM;
+ }
+
+ public void setTokenFCM(String tokenFCM) {
+ this.tokenFCM = tokenFCM;
+ }
+
+ public String getPlateforme() {
+ return plateforme;
+ }
+
+ public void setPlateforme(String plateforme) {
+ this.plateforme = plateforme;
+ }
+
+ public String getVersionApp() {
+ return versionApp;
+ }
+
+ public void setVersionApp(String versionApp) {
+ this.versionApp = versionApp;
+ }
+
+ public String getLangue() {
+ return langue;
+ }
+
+ public void setLangue(String langue) {
+ this.langue = langue;
+ }
+
+ public String getFuseauHoraire() {
+ return fuseauHoraire;
+ }
+
+ public void setFuseauHoraire(String fuseauHoraire) {
+ this.fuseauHoraire = fuseauHoraire;
+ }
+
+ public Map getMetadonnees() {
+ return metadonnees;
+ }
+
+ public void setMetadonnees(Map metadonnees) {
+ this.metadonnees = metadonnees;
+ }
+
+ // === MÉTHODES UTILITAIRES ===
+
+ /** Vérifie si un type de notification est activé */
+ public boolean isTypeActive(TypeNotification type) {
+ if (!notificationsActivees) return false;
+ if (typesDesactivees != null && typesDesactivees.contains(type)) return false;
+ if (typesActives != null) return typesActives.contains(type);
+ return type.isActiveeParDefaut();
+ }
+
+ /** Vérifie si un canal de notification est activé */
+ public boolean isCanalActif(CanalNotification canal) {
+ if (!notificationsActivees) return false;
+ if (canauxDesactives != null && canauxDesactives.contains(canal)) return false;
+ if (canauxActifs != null) return canauxActifs.contains(canal);
+ return true;
+ }
+
+ /**
+ * Version de test de isEnModeSilencieux avec une heure fixe
+ * Permet de tester toutes les branches sans dépendre de l'heure actuelle
+ */
+ boolean isEnModeSilencieux(LocalTime heureActuelle) {
+ if (!modeSilencieux) return false;
+ if (heureDebutSilencieux == null || heureFinSilencieux == null) return false;
+
+ // Gestion du cas où la période traverse minuit
+ if (heureDebutSilencieux.isAfter(heureFinSilencieux)) {
+ return heureActuelle.isAfter(heureDebutSilencieux) || heureActuelle.isBefore(heureFinSilencieux);
+ } else {
+ return heureActuelle.isAfter(heureDebutSilencieux) && heureActuelle.isBefore(heureFinSilencieux);
+ }
+ }
+
+ /** Vérifie si on est en mode silencieux actuellement */
+ public boolean isEnModeSilencieux() {
+ return isEnModeSilencieux(LocalTime.now());
+ }
+
+ /** Vérifie si un expéditeur est bloqué */
+ public boolean isExpediteurBloque(String expediteurId) {
+ return expediteursBloqués != null && expediteursBloqués.contains(expediteurId);
+ }
+
+ /** Vérifie si un expéditeur est prioritaire */
+ public boolean isExpediteurPrioritaire(String expediteurId) {
+ return expediteursPrioritaires != null && expediteursPrioritaires.contains(expediteurId);
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ "PreferencesNotificationDTO{utilisateurId='%s', notificationsActivees=%s}",
+ utilisateurId, notificationsActivees);
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/CreateNotificationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/CreateNotificationRequest.java
index 5f55866..03834a1 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/CreateNotificationRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/CreateNotificationRequest.java
@@ -1,25 +1,25 @@
-package dev.lions.unionflow.server.api.dto.notification.request;
-
-import jakarta.validation.constraints.NotNull;
-import java.time.LocalDateTime;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de création d'une notification.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record CreateNotificationRequest(
- @NotNull(message = "Le type de notification est obligatoire") String typeNotification,
- String priorite,
- String sujet,
- String corps,
- LocalDateTime dateEnvoiPrevue,
- String donneesAdditionnelles,
- UUID membreId,
- UUID organisationId,
- UUID templateId) {
-}
+package dev.lions.unionflow.server.api.dto.notification.request;
+
+import jakarta.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de création d'une notification.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record CreateNotificationRequest(
+ @NotNull(message = "Le type de notification est obligatoire") String typeNotification,
+ String priorite,
+ String sujet,
+ String corps,
+ LocalDateTime dateEnvoiPrevue,
+ String donneesAdditionnelles,
+ UUID membreId,
+ UUID organisationId,
+ UUID templateId) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/CreateTemplateNotificationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/CreateTemplateNotificationRequest.java
index 55d0ff2..6c3a848 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/CreateTemplateNotificationRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/CreateTemplateNotificationRequest.java
@@ -1,22 +1,22 @@
-package dev.lions.unionflow.server.api.dto.notification.request;
-
-import jakarta.validation.constraints.NotBlank;
-import lombok.Builder;
-
-/**
- * Requête de création d'un template de notification.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record CreateTemplateNotificationRequest(
- @NotBlank(message = "Le code est obligatoire") String code,
- String sujet,
- String corpsTexte,
- String corpsHtml,
- String variablesDisponibles,
- String canauxSupportes,
- String langue,
- String description) {
-}
+package dev.lions.unionflow.server.api.dto.notification.request;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Builder;
+
+/**
+ * Requête de création d'un template de notification.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record CreateTemplateNotificationRequest(
+ @NotBlank(message = "Le code est obligatoire") String code,
+ String sujet,
+ String corpsTexte,
+ String corpsHtml,
+ String variablesDisponibles,
+ String canauxSupportes,
+ String langue,
+ String description) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/UpdateNotificationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/UpdateNotificationRequest.java
index 2ef77e3..280f961 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/UpdateNotificationRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/UpdateNotificationRequest.java
@@ -1,18 +1,18 @@
-package dev.lions.unionflow.server.api.dto.notification.request;
-
-import java.time.LocalDateTime;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'une notification.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record UpdateNotificationRequest(
- String statut,
- LocalDateTime dateLecture,
- Integer nombreTentatives,
- String messageErreur) {
-}
+package dev.lions.unionflow.server.api.dto.notification.request;
+
+import java.time.LocalDateTime;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'une notification.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record UpdateNotificationRequest(
+ String statut,
+ LocalDateTime dateLecture,
+ Integer nombreTentatives,
+ String messageErreur) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/UpdateTemplateNotificationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/UpdateTemplateNotificationRequest.java
index 53939d8..27d404e 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/UpdateTemplateNotificationRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/notification/request/UpdateTemplateNotificationRequest.java
@@ -1,22 +1,22 @@
-package dev.lions.unionflow.server.api.dto.notification.request;
-
-import jakarta.validation.constraints.NotBlank;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'un template de notification.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Builder
-public record UpdateTemplateNotificationRequest(
- @NotBlank(message = "Le code est obligatoire") String code,
- String sujet,
- String corpsTexte,
- String corpsHtml,
- String variablesDisponibles,
- String canauxSupportes,
- String langue,
- String description) {
-}
+package dev.lions.unionflow.server.api.dto.notification.request;
+
+import jakarta.validation.constraints.NotBlank;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'un template de notification.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Builder
+public record UpdateTemplateNotificationRequest(
+ @NotBlank(message = "Le code est obligatoire") String code,
+ String sujet,
+ String corpsTexte,
+ String corpsHtml,
+ String variablesDisponibles,
+ String canauxSupportes,
+ String langue,
+ String description) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/notification/response/NotificationResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/notification/response/NotificationResponse.java
index 74ce59a..7d2f75b 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/notification/response/NotificationResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/notification/response/NotificationResponse.java
@@ -1,40 +1,40 @@
-package dev.lions.unionflow.server.api.dto.notification.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.time.LocalDateTime;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse contenant les données d'une notification.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class NotificationResponse extends BaseResponse {
-
- private String typeNotification;
- private String priorite;
- private String statut;
- private String sujet;
- private String corps;
- private LocalDateTime dateEnvoiPrevue;
- private LocalDateTime dateEnvoi;
- private LocalDateTime dateLecture;
- private Integer nombreTentatives;
- private String messageErreur;
- private String donneesAdditionnelles;
- private UUID membreId;
- private UUID organisationId;
- private UUID templateId;
-}
+package dev.lions.unionflow.server.api.dto.notification.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.time.LocalDateTime;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse contenant les données d'une notification.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class NotificationResponse extends BaseResponse {
+
+ private String typeNotification;
+ private String priorite;
+ private String statut;
+ private String sujet;
+ private String corps;
+ private LocalDateTime dateEnvoiPrevue;
+ private LocalDateTime dateEnvoi;
+ private LocalDateTime dateLecture;
+ private Integer nombreTentatives;
+ private String messageErreur;
+ private String donneesAdditionnelles;
+ private UUID membreId;
+ private UUID organisationId;
+ private UUID templateId;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/notification/response/TemplateNotificationResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/notification/response/TemplateNotificationResponse.java
index 1c3b726..012f069 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/notification/response/TemplateNotificationResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/notification/response/TemplateNotificationResponse.java
@@ -1,32 +1,32 @@
-package dev.lions.unionflow.server.api.dto.notification.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse contenant les données d'un template de notification.
- *
- * @author UnionFlow Team
- * @version 1.0
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class TemplateNotificationResponse extends BaseResponse {
-
- private String code;
- private String sujet;
- private String corpsTexte;
- private String corpsHtml;
- private String variablesDisponibles;
- private String canauxSupportes;
- private String langue;
- private String description;
-}
+package dev.lions.unionflow.server.api.dto.notification.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse contenant les données d'un template de notification.
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TemplateNotificationResponse extends BaseResponse {
+
+ private String code;
+ private String sujet;
+ private String corpsTexte;
+ private String corpsHtml;
+ private String variablesDisponibles;
+ private String canauxSupportes;
+ private String langue;
+ private String description;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/ong/ProjetOngDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/ong/ProjetOngDTO.java
index 4c4c876..e471797 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/ong/ProjetOngDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/ong/ProjetOngDTO.java
@@ -1,35 +1,35 @@
-package dev.lions.unionflow.server.api.dto.ong;
-
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.ong.StatutProjetOng;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-
-import java.math.BigDecimal;
-import java.time.LocalDate;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class ProjetOngDTO extends BaseDTO {
-
- private String organisationId;
-
- private String nomProjet;
- private String descriptionMandat;
-
- private String zoneGeographiqueIntervention;
-
- private BigDecimal budgetPrevisionnel;
- private BigDecimal depensesReelles;
-
- private LocalDate dateLancement;
- private LocalDate dateFinEstimee;
-
- private StatutProjetOng statut;
-}
+package dev.lions.unionflow.server.api.dto.ong;
+
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.ong.StatutProjetOng;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class ProjetOngDTO extends BaseDTO {
+
+ private String organisationId;
+
+ private String nomProjet;
+ private String descriptionMandat;
+
+ private String zoneGeographiqueIntervention;
+
+ private BigDecimal budgetPrevisionnel;
+ private BigDecimal depensesReelles;
+
+ private LocalDate dateLancement;
+ private LocalDate dateFinEstimee;
+
+ private StatutProjetOng statut;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/organisation/request/CreateOrganisationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/organisation/request/CreateOrganisationRequest.java
index a15745e..c24fafe 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/organisation/request/CreateOrganisationRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/organisation/request/CreateOrganisationRequest.java
@@ -1,81 +1,81 @@
-package dev.lions.unionflow.server.api.dto.organisation.request;
-
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Size;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-
-import lombok.Builder;
-
-/**
- * Requête de création d'une organisation.
- *
- *
- * Immutable via {@code record}. Exclut les
- * champs d'audit et l'ID (générés côté serveur).
- *
- * @author UnionFlow Team
- * @version 3.0
- * @since 2026-02-21
- * @param nom nom officiel
- * @param nomCourt sigle
- * @param description description
- * @param email email principal
- * @param telephone téléphone
- * @param telephoneSecondaire téléphone 2
- * @param emailSecondaire email 2
- * @param siteWeb site web
- * @param logo URL du logo
- * @param reseauxSociaux réseaux sociaux
- * @param typeOrganisation type (types_reference)
- * @param statut statut initial
- * @param dateFondation date de fondation
- * @param numeroEnregistrement numéro légal
- * @param devise code devise
- * @param budgetAnnuel budget annuel
- * @param cotisationObligatoire cotisation requise
- * @param montantCotisationAnnuelle montant annuel
- * @param objectifs objectifs
- * @param activitesPrincipales activités
- * @param certifications certifications
- * @param partenaires partenaires
- * @param notes notes internes
- * @param latitude latitude GPS
- * @param longitude longitude GPS
- */
-@Builder
-public record CreateOrganisationRequest(
- @NotBlank @Size(max = 255) String nom,
- @Size(max = 50) String nomCourt,
- @Size(max = 2000) String description,
- @NotBlank @Email @Size(max = 255) String email,
- @Size(max = 20) String telephone,
- @Size(max = 20) String telephoneSecondaire,
- @Email @Size(max = 255) String emailSecondaire,
- @Size(max = 500) String siteWeb,
- @Size(max = 500) String logo,
- @Size(max = 1000) String reseauxSociaux,
- @Size(max = 50) String typeOrganisation,
- @Size(max = 30) String statut,
- LocalDate dateFondation,
- @Size(max = 100) String numeroEnregistrement,
- @Size(max = 3) String devise,
- BigDecimal budgetAnnuel,
- Boolean cotisationObligatoire,
- BigDecimal montantCotisationAnnuelle,
- @Size(max = 2000) String objectifs,
- @Size(max = 2000) String activitesPrincipales,
- @Size(max = 500) String certifications,
- @Size(max = 1000) String partenaires,
- @Size(max = 1000) String notes,
- BigDecimal latitude,
- BigDecimal longitude,
- @Size(max = 500) String adresse,
- @Size(max = 100) String ville,
- @Size(max = 100) String region,
- @Size(max = 100) String pays,
- @Size(max = 20) String codePostal,
- Boolean organisationPublique,
- Boolean accepteNouveauxMembres) {
-}
+package dev.lions.unionflow.server.api.dto.organisation.request;
+
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+import lombok.Builder;
+
+/**
+ * Requête de création d'une organisation.
+ *
+ *
+ * Immutable via {@code record}. Exclut les
+ * champs d'audit et l'ID (générés côté serveur).
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ * @since 2026-02-21
+ * @param nom nom officiel
+ * @param nomCourt sigle
+ * @param description description
+ * @param email email principal
+ * @param telephone téléphone
+ * @param telephoneSecondaire téléphone 2
+ * @param emailSecondaire email 2
+ * @param siteWeb site web
+ * @param logo URL du logo
+ * @param reseauxSociaux réseaux sociaux
+ * @param typeOrganisation type (types_reference)
+ * @param statut statut initial
+ * @param dateFondation date de fondation
+ * @param numeroEnregistrement numéro légal
+ * @param devise code devise
+ * @param budgetAnnuel budget annuel
+ * @param cotisationObligatoire cotisation requise
+ * @param montantCotisationAnnuelle montant annuel
+ * @param objectifs objectifs
+ * @param activitesPrincipales activités
+ * @param certifications certifications
+ * @param partenaires partenaires
+ * @param notes notes internes
+ * @param latitude latitude GPS
+ * @param longitude longitude GPS
+ */
+@Builder
+public record CreateOrganisationRequest(
+ @NotBlank @Size(max = 255) String nom,
+ @Size(max = 50) String nomCourt,
+ @Size(max = 2000) String description,
+ @NotBlank @Email @Size(max = 255) String email,
+ @Size(max = 20) String telephone,
+ @Size(max = 20) String telephoneSecondaire,
+ @Email @Size(max = 255) String emailSecondaire,
+ @Size(max = 500) String siteWeb,
+ @Size(max = 500) String logo,
+ @Size(max = 1000) String reseauxSociaux,
+ @Size(max = 50) String typeOrganisation,
+ @Size(max = 30) String statut,
+ LocalDate dateFondation,
+ @Size(max = 100) String numeroEnregistrement,
+ @Size(max = 3) String devise,
+ BigDecimal budgetAnnuel,
+ Boolean cotisationObligatoire,
+ BigDecimal montantCotisationAnnuelle,
+ @Size(max = 2000) String objectifs,
+ @Size(max = 2000) String activitesPrincipales,
+ @Size(max = 500) String certifications,
+ @Size(max = 1000) String partenaires,
+ @Size(max = 1000) String notes,
+ BigDecimal latitude,
+ BigDecimal longitude,
+ @Size(max = 500) String adresse,
+ @Size(max = 100) String ville,
+ @Size(max = 100) String region,
+ @Size(max = 100) String pays,
+ @Size(max = 20) String codePostal,
+ Boolean organisationPublique,
+ Boolean accepteNouveauxMembres) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/organisation/request/UpdateOrganisationRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/organisation/request/UpdateOrganisationRequest.java
index feda188..0701594 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/organisation/request/UpdateOrganisationRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/organisation/request/UpdateOrganisationRequest.java
@@ -1,55 +1,55 @@
-package dev.lions.unionflow.server.api.dto.organisation.request;
-
-import jakarta.validation.constraints.Email;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Size;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'une organisation.
- *
- *
- * ID passé dans le path de l'URL.
- *
- * @author UnionFlow Team
- * @version 3.0
- * @since 2026-02-22
- */
-@Builder
-public record UpdateOrganisationRequest(
- @NotBlank @Size(max = 255) String nom,
- @Size(max = 50) String nomCourt,
- @Size(max = 2000) String description,
- @NotBlank @Email @Size(max = 255) String email,
- @Size(max = 20) String telephone,
- @Size(max = 20) String telephoneSecondaire,
- @Email @Size(max = 255) String emailSecondaire,
- @Size(max = 500) String siteWeb,
- @Size(max = 500) String logo,
- @Size(max = 1000) String reseauxSociaux,
- @Size(max = 50) String typeOrganisation,
- @Size(max = 30) String statut,
- LocalDate dateFondation,
- @Size(max = 100) String numeroEnregistrement,
- @Size(max = 3) String devise,
- BigDecimal budgetAnnuel,
- Boolean cotisationObligatoire,
- BigDecimal montantCotisationAnnuelle,
- @Size(max = 2000) String objectifs,
- @Size(max = 2000) String activitesPrincipales,
- @Size(max = 500) String certifications,
- @Size(max = 1000) String partenaires,
- @Size(max = 1000) String notes,
- BigDecimal latitude,
- BigDecimal longitude,
- @Size(max = 500) String adresse,
- @Size(max = 100) String ville,
- @Size(max = 100) String region,
- @Size(max = 100) String pays,
- @Size(max = 20) String codePostal,
- Boolean organisationPublique,
- Boolean accepteNouveauxMembres) {
-}
+package dev.lions.unionflow.server.api.dto.organisation.request;
+
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'une organisation.
+ *
+ *
+ * ID passé dans le path de l'URL.
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ * @since 2026-02-22
+ */
+@Builder
+public record UpdateOrganisationRequest(
+ @NotBlank @Size(max = 255) String nom,
+ @Size(max = 50) String nomCourt,
+ @Size(max = 2000) String description,
+ @NotBlank @Email @Size(max = 255) String email,
+ @Size(max = 20) String telephone,
+ @Size(max = 20) String telephoneSecondaire,
+ @Email @Size(max = 255) String emailSecondaire,
+ @Size(max = 500) String siteWeb,
+ @Size(max = 500) String logo,
+ @Size(max = 1000) String reseauxSociaux,
+ @Size(max = 50) String typeOrganisation,
+ @Size(max = 30) String statut,
+ LocalDate dateFondation,
+ @Size(max = 100) String numeroEnregistrement,
+ @Size(max = 3) String devise,
+ BigDecimal budgetAnnuel,
+ Boolean cotisationObligatoire,
+ BigDecimal montantCotisationAnnuelle,
+ @Size(max = 2000) String objectifs,
+ @Size(max = 2000) String activitesPrincipales,
+ @Size(max = 500) String certifications,
+ @Size(max = 1000) String partenaires,
+ @Size(max = 1000) String notes,
+ BigDecimal latitude,
+ BigDecimal longitude,
+ @Size(max = 500) String adresse,
+ @Size(max = 100) String ville,
+ @Size(max = 100) String region,
+ @Size(max = 100) String pays,
+ @Size(max = 20) String codePostal,
+ Boolean organisationPublique,
+ Boolean accepteNouveauxMembres) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/organisation/response/OrganisationResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/organisation/response/OrganisationResponse.java
index eb7cf19..9d95704 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/organisation/response/OrganisationResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/organisation/response/OrganisationResponse.java
@@ -1,94 +1,94 @@
-package dev.lions.unionflow.server.api.dto.organisation.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse contenant les données d'une organisation.
- *
- *
- * Classe Lombok (getters/setters) pour la
- * compatibilité avec les frameworks d'affichage
- * (PrimeFaces, etc.).
- *
- * @author UnionFlow Team
- * @version 3.0
- * @since 2026-02-21
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class OrganisationResponse extends BaseResponse {
-
- // ── Identité ───────────────────────────────
- private String nom;
- private String nomCourt;
- private String description;
- private String email;
- private String telephone;
- private String telephoneSecondaire;
- private String emailSecondaire;
-
- // ── Web ────────────────────────────────────
- private String siteWeb;
- private String logo;
- private String reseauxSociaux;
-
- // ── Classification ─────────────────────────
- private String typeOrganisation;
- private String typeOrganisationLibelle;
- private String statut;
- private String statutLibelle;
- private String statutSeverity;
- private LocalDate dateFondation;
- private String numeroEnregistrement;
-
- // ── Géographie ─────────────────────────────
- private String adresse;
- private String quartier;
- private String ville;
- private String region;
- private String pays;
- private String codePostal;
- private BigDecimal latitude;
- private BigDecimal longitude;
-
- // ── Hiérarchie ─────────────────────────────
- private UUID organisationParenteId;
- private String organisationParenteNom;
- private Integer niveauHierarchique;
- private Boolean estOrganisationRacine;
-
- // ── Finances ───────────────────────────────
- private String devise;
- private BigDecimal budgetAnnuel;
- private Boolean cotisationObligatoire;
- private BigDecimal montantCotisationAnnuelle;
-
- // ── Statistiques ───────────────────────────
- private Integer nombreMembres;
- private Integer nombreAdministrateurs;
- /** Nombre d'événements (actifs) de l'organisation. */
- private Integer nombreEvenements;
-
- // ── Contenu ────────────────────────────────
- private String objectifs;
- private String activitesPrincipales;
- private String certifications;
- private String partenaires;
- private String notes;
-
- // ── Paramètres ─────────────────────────────
- private Boolean organisationPublique;
- private Boolean accepteNouveauxMembres;
-}
+package dev.lions.unionflow.server.api.dto.organisation.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse contenant les données d'une organisation.
+ *
+ *
+ * Classe Lombok (getters/setters) pour la
+ * compatibilité avec les frameworks d'affichage
+ * (PrimeFaces, etc.).
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ * @since 2026-02-21
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrganisationResponse extends BaseResponse {
+
+ // ── Identité ───────────────────────────────
+ private String nom;
+ private String nomCourt;
+ private String description;
+ private String email;
+ private String telephone;
+ private String telephoneSecondaire;
+ private String emailSecondaire;
+
+ // ── Web ────────────────────────────────────
+ private String siteWeb;
+ private String logo;
+ private String reseauxSociaux;
+
+ // ── Classification ─────────────────────────
+ private String typeOrganisation;
+ private String typeOrganisationLibelle;
+ private String statut;
+ private String statutLibelle;
+ private String statutSeverity;
+ private LocalDate dateFondation;
+ private String numeroEnregistrement;
+
+ // ── Géographie ─────────────────────────────
+ private String adresse;
+ private String quartier;
+ private String ville;
+ private String region;
+ private String pays;
+ private String codePostal;
+ private BigDecimal latitude;
+ private BigDecimal longitude;
+
+ // ── Hiérarchie ─────────────────────────────
+ private UUID organisationParenteId;
+ private String organisationParenteNom;
+ private Integer niveauHierarchique;
+ private Boolean estOrganisationRacine;
+
+ // ── Finances ───────────────────────────────
+ private String devise;
+ private BigDecimal budgetAnnuel;
+ private Boolean cotisationObligatoire;
+ private BigDecimal montantCotisationAnnuelle;
+
+ // ── Statistiques ───────────────────────────
+ private Integer nombreMembres;
+ private Integer nombreAdministrateurs;
+ /** Nombre d'événements (actifs) de l'organisation. */
+ private Integer nombreEvenements;
+
+ // ── Contenu ────────────────────────────────
+ private String objectifs;
+ private String activitesPrincipales;
+ private String certifications;
+ private String partenaires;
+ private String notes;
+
+ // ── Paramètres ─────────────────────────────
+ private Boolean organisationPublique;
+ private Boolean accepteNouveauxMembres;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/organisation/response/OrganisationSummaryResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/organisation/response/OrganisationSummaryResponse.java
index b9122c4..05f33e8 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/organisation/response/OrganisationSummaryResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/organisation/response/OrganisationSummaryResponse.java
@@ -1,33 +1,33 @@
-package dev.lions.unionflow.server.api.dto.organisation.response;
-
-import lombok.AllArgsConstructor;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import java.util.UUID;
-
-/**
- * Résumé d'une organisation pour les listes.
- * Classe JavaBean (pas un record) pour compatibilité JSF/EL (getNom() requis).
- *
- * @author UnionFlow Team
- * @version 3.1
- * @since 2026-02-22
- */
-@Data
-@NoArgsConstructor
-@AllArgsConstructor
-public class OrganisationSummaryResponse {
- private UUID id;
- private String nom;
- private String nomCourt;
- private String typeOrganisation;
- private String typeOrganisationLibelle;
- private String statut;
- private String statutLibelle;
- private String statutSeverity;
- private Integer nombreMembres;
- private Boolean actif;
- private String ville;
- private String pays;
-}
+package dev.lions.unionflow.server.api.dto.organisation.response;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.UUID;
+
+/**
+ * Résumé d'une organisation pour les listes.
+ * Classe JavaBean (pas un record) pour compatibilité JSF/EL (getNom() requis).
+ *
+ * @author UnionFlow Team
+ * @version 3.1
+ * @since 2026-02-22
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class OrganisationSummaryResponse {
+ private UUID id;
+ private String nom;
+ private String nomCourt;
+ private String typeOrganisation;
+ private String typeOrganisationLibelle;
+ private String statut;
+ private String statutLibelle;
+ private String statutSeverity;
+ private Integer nombreMembres;
+ private Boolean actif;
+ private String ville;
+ private String pays;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/paiement/WaveBalanceDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/paiement/WaveBalanceDTO.java
index 4054b73..bc518d3 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/paiement/WaveBalanceDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/paiement/WaveBalanceDTO.java
@@ -1,363 +1,363 @@
-package dev.lions.unionflow.server.api.dto.paiement;
-
-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.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Pattern;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * DTO pour la consultation du solde Wave Money (Balance API) Représente le solde d'un wallet Wave
- * Business
- *
- *
Basé sur l'API officielle Wave : https://docs.wave.com/business#balance-api
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-10
- */
-@Getter
-@Setter
-public class WaveBalanceDTO extends BaseDTO {
-
- private static final long serialVersionUID = 1L;
-
- /** Solde disponible */
- @NotNull(message = "Le solde disponible est obligatoire")
- @DecimalMin(value = "0.0", message = "Le solde doit être positif ou nul")
- @Digits(
- integer = 12,
- fraction = 2,
- message = "Le solde ne peut avoir plus de 12 chiffres entiers et 2 décimales")
- private BigDecimal soldeDisponible;
-
- /** Solde en attente (transactions en cours) */
- @DecimalMin(value = "0.0", message = "Le solde en attente doit être positif ou nul")
- @Digits(
- integer = 12,
- fraction = 2,
- message = "Le solde ne peut avoir plus de 12 chiffres entiers et 2 décimales")
- private BigDecimal soldeEnAttente;
-
- /** Solde total (disponible + en attente) */
- @DecimalMin(value = "0.0", message = "Le solde total doit être positif ou nul")
- @Digits(
- integer = 12,
- fraction = 2,
- message = "Le solde ne peut avoir plus de 12 chiffres entiers et 2 décimales")
- private BigDecimal soldeTotal;
-
- /** Devise du wallet */
- @NotBlank(message = "La devise est obligatoire")
- @Pattern(regexp = "^[A-Z]{3}$", message = "La devise doit être un code ISO à 3 lettres")
- private String devise = "XOF";
-
- /** Numéro du wallet Wave */
- @NotBlank(message = "Le numéro de wallet est obligatoire")
- private String numeroWallet;
-
- /** Nom du business associé au wallet */
- private String nomBusiness;
-
- /** Date de dernière mise à jour du solde */
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- private LocalDateTime dateDerniereMiseAJour;
-
- /** Date de dernière synchronisation avec Wave */
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- private LocalDateTime dateDerniereSynchronisation;
-
- /** Statut du wallet */
- @Pattern(
- regexp = "^(ACTIVE|INACTIVE|SUSPENDED|BLOCKED)$",
- message = "Le statut doit être ACTIVE, INACTIVE, SUSPENDED ou BLOCKED")
- private String statutWallet;
-
- /** Limite de transaction quotidienne */
- @DecimalMin(value = "0.0", message = "La limite doit être positive ou nulle")
- @Digits(
- integer = 12,
- fraction = 2,
- message = "La limite ne peut avoir plus de 12 chiffres entiers et 2 décimales")
- private BigDecimal limiteQuotidienne;
-
- /** Montant déjà utilisé aujourd'hui */
- @DecimalMin(value = "0.0", message = "Le montant utilisé doit être positif ou nul")
- @Digits(
- integer = 12,
- fraction = 2,
- message = "Le montant ne peut avoir plus de 12 chiffres entiers et 2 décimales")
- private BigDecimal montantUtiliseAujourdhui;
-
- /** Limite mensuelle */
- @DecimalMin(value = "0.0", message = "La limite doit être positive ou nulle")
- @Digits(
- integer = 12,
- fraction = 2,
- message = "La limite ne peut avoir plus de 12 chiffres entiers et 2 décimales")
- private BigDecimal limiteMensuelle;
-
- /** Montant utilisé ce mois */
- @DecimalMin(value = "0.0", message = "Le montant utilisé doit être positif ou nul")
- @Digits(
- integer = 12,
- fraction = 2,
- message = "Le montant ne peut avoir plus de 12 chiffres entiers et 2 décimales")
- private BigDecimal montantUtiliseCeMois;
-
- /** Nombre de transactions aujourd'hui */
- private Integer nombreTransactionsAujourdhui;
-
- /** Nombre de transactions ce mois */
- private Integer nombreTransactionsCeMois;
-
- /** Dernière erreur de synchronisation */
- private String derniereErreur;
-
- /** Code de la dernière erreur */
- private String codeDerniereErreur;
-
- // Constructeurs
- public WaveBalanceDTO() {
- super();
- this.devise = "XOF";
- this.statutWallet = "ACTIVE";
- this.soldeEnAttente = BigDecimal.ZERO;
- this.montantUtiliseAujourdhui = BigDecimal.ZERO;
- this.montantUtiliseCeMois = BigDecimal.ZERO;
- this.nombreTransactionsAujourdhui = 0;
- this.nombreTransactionsCeMois = 0;
- }
-
- public WaveBalanceDTO(String numeroWallet, BigDecimal soldeDisponible) {
- this();
- this.numeroWallet = numeroWallet;
- this.soldeDisponible = soldeDisponible;
- this.soldeTotal = soldeDisponible;
- }
-
- // Getters et Setters
- public BigDecimal getSoldeDisponible() {
- return soldeDisponible;
- }
-
- public void setSoldeDisponible(BigDecimal soldeDisponible) {
- this.soldeDisponible = soldeDisponible;
- calculerSoldeTotal();
- }
-
- public BigDecimal getSoldeEnAttente() {
- return soldeEnAttente;
- }
-
- public void setSoldeEnAttente(BigDecimal soldeEnAttente) {
- this.soldeEnAttente = soldeEnAttente;
- calculerSoldeTotal();
- }
-
- public BigDecimal getSoldeTotal() {
- return soldeTotal;
- }
-
- public void setSoldeTotal(BigDecimal soldeTotal) {
- this.soldeTotal = soldeTotal;
- }
-
- public String getDevise() {
- return devise;
- }
-
- public void setDevise(String devise) {
- this.devise = devise;
- }
-
- public String getNumeroWallet() {
- return numeroWallet;
- }
-
- public void setNumeroWallet(String numeroWallet) {
- this.numeroWallet = numeroWallet;
- }
-
- public String getNomBusiness() {
- return nomBusiness;
- }
-
- public void setNomBusiness(String nomBusiness) {
- this.nomBusiness = nomBusiness;
- }
-
- public LocalDateTime getDateDerniereMiseAJour() {
- return dateDerniereMiseAJour;
- }
-
- public void setDateDerniereMiseAJour(LocalDateTime dateDerniereMiseAJour) {
- this.dateDerniereMiseAJour = dateDerniereMiseAJour;
- }
-
- public LocalDateTime getDateDerniereSynchronisation() {
- return dateDerniereSynchronisation;
- }
-
- public void setDateDerniereSynchronisation(LocalDateTime dateDerniereSynchronisation) {
- this.dateDerniereSynchronisation = dateDerniereSynchronisation;
- }
-
- public String getStatutWallet() {
- return statutWallet;
- }
-
- public void setStatutWallet(String statutWallet) {
- this.statutWallet = statutWallet;
- }
-
- public BigDecimal getLimiteQuotidienne() {
- return limiteQuotidienne;
- }
-
- public void setLimiteQuotidienne(BigDecimal limiteQuotidienne) {
- this.limiteQuotidienne = limiteQuotidienne;
- }
-
- public BigDecimal getMontantUtiliseAujourdhui() {
- return montantUtiliseAujourdhui;
- }
-
- public void setMontantUtiliseAujourdhui(BigDecimal montantUtiliseAujourdhui) {
- this.montantUtiliseAujourdhui = montantUtiliseAujourdhui;
- }
-
- public BigDecimal getLimiteMensuelle() {
- return limiteMensuelle;
- }
-
- public void setLimiteMensuelle(BigDecimal limiteMensuelle) {
- this.limiteMensuelle = limiteMensuelle;
- }
-
- public BigDecimal getMontantUtiliseCeMois() {
- return montantUtiliseCeMois;
- }
-
- public void setMontantUtiliseCeMois(BigDecimal montantUtiliseCeMois) {
- this.montantUtiliseCeMois = montantUtiliseCeMois;
- }
-
- public Integer getNombreTransactionsAujourdhui() {
- return nombreTransactionsAujourdhui;
- }
-
- public void setNombreTransactionsAujourdhui(Integer nombreTransactionsAujourdhui) {
- this.nombreTransactionsAujourdhui = nombreTransactionsAujourdhui;
- }
-
- public Integer getNombreTransactionsCeMois() {
- return nombreTransactionsCeMois;
- }
-
- public void setNombreTransactionsCeMois(Integer nombreTransactionsCeMois) {
- this.nombreTransactionsCeMois = nombreTransactionsCeMois;
- }
-
- public String getDerniereErreur() {
- return derniereErreur;
- }
-
- public void setDerniereErreur(String derniereErreur) {
- this.derniereErreur = derniereErreur;
- }
-
- public String getCodeDerniereErreur() {
- return codeDerniereErreur;
- }
-
- public void setCodeDerniereErreur(String codeDerniereErreur) {
- this.codeDerniereErreur = codeDerniereErreur;
- }
-
- // Méthodes utilitaires
-
- /** Calcule le solde total */
- private void calculerSoldeTotal() {
- if (soldeDisponible != null && soldeEnAttente != null) {
- this.soldeTotal = soldeDisponible.add(soldeEnAttente);
- }
- }
-
- /**
- * Vérifie si le wallet est actif
- *
- * @return true si le wallet est actif
- */
- public boolean isWalletActif() {
- return "ACTIVE".equals(statutWallet);
- }
-
- /**
- * Vérifie si le solde est suffisant pour un montant donné
- *
- * @param montant Le montant à vérifier
- * @return true si le solde est suffisant
- */
- public boolean isSoldeSuffisant(BigDecimal montant) {
- return soldeDisponible != null && soldeDisponible.compareTo(montant) >= 0;
- }
-
- /**
- * Calcule le solde disponible restant pour aujourd'hui
- *
- * @return Le montant encore disponible aujourd'hui
- */
- public BigDecimal getSoldeDisponibleAujourdhui() {
- if (soldeDisponible == null || limiteQuotidienne == null || montantUtiliseAujourdhui == null) {
- return soldeDisponible;
- }
-
- BigDecimal limiteRestante = limiteQuotidienne.subtract(montantUtiliseAujourdhui);
- return soldeDisponible.min(limiteRestante);
- }
-
- /**
- * Met à jour les statistiques après une transaction
- *
- * @param montant Le montant de la transaction
- */
- public void mettreAJourApresTransaction(BigDecimal montant) {
- if (montantUtiliseAujourdhui == null) montantUtiliseAujourdhui = BigDecimal.ZERO;
- if (montantUtiliseCeMois == null) montantUtiliseCeMois = BigDecimal.ZERO;
- if (nombreTransactionsAujourdhui == null) nombreTransactionsAujourdhui = 0;
- if (nombreTransactionsCeMois == null) nombreTransactionsCeMois = 0;
-
- this.montantUtiliseAujourdhui = montantUtiliseAujourdhui.add(montant);
- this.montantUtiliseCeMois = montantUtiliseCeMois.add(montant);
- this.nombreTransactionsAujourdhui++;
- this.nombreTransactionsCeMois++;
- this.dateDerniereMiseAJour = LocalDateTime.now();
- }
-
- @Override
- public String toString() {
- return "WaveBalanceDTO{"
- + "numeroWallet='"
- + numeroWallet
- + '\''
- + ", soldeDisponible="
- + soldeDisponible
- + ", soldeTotal="
- + soldeTotal
- + ", devise='"
- + devise
- + '\''
- + ", statutWallet='"
- + statutWallet
- + '\''
- + "} "
- + super.toString();
- }
-}
+package dev.lions.unionflow.server.api.dto.paiement;
+
+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.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Pattern;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * DTO pour la consultation du solde Wave Money (Balance API) Représente le solde d'un wallet Wave
+ * Business
+ *
+ *
Basé sur l'API officielle Wave : https://docs.wave.com/business#balance-api
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2025-01-10
+ */
+@Getter
+@Setter
+public class WaveBalanceDTO extends BaseDTO {
+
+ private static final long serialVersionUID = 1L;
+
+ /** Solde disponible */
+ @NotNull(message = "Le solde disponible est obligatoire")
+ @DecimalMin(value = "0.0", message = "Le solde doit être positif ou nul")
+ @Digits(
+ integer = 12,
+ fraction = 2,
+ message = "Le solde ne peut avoir plus de 12 chiffres entiers et 2 décimales")
+ private BigDecimal soldeDisponible;
+
+ /** Solde en attente (transactions en cours) */
+ @DecimalMin(value = "0.0", message = "Le solde en attente doit être positif ou nul")
+ @Digits(
+ integer = 12,
+ fraction = 2,
+ message = "Le solde ne peut avoir plus de 12 chiffres entiers et 2 décimales")
+ private BigDecimal soldeEnAttente;
+
+ /** Solde total (disponible + en attente) */
+ @DecimalMin(value = "0.0", message = "Le solde total doit être positif ou nul")
+ @Digits(
+ integer = 12,
+ fraction = 2,
+ message = "Le solde ne peut avoir plus de 12 chiffres entiers et 2 décimales")
+ private BigDecimal soldeTotal;
+
+ /** Devise du wallet */
+ @NotBlank(message = "La devise est obligatoire")
+ @Pattern(regexp = "^[A-Z]{3}$", message = "La devise doit être un code ISO à 3 lettres")
+ private String devise = "XOF";
+
+ /** Numéro du wallet Wave */
+ @NotBlank(message = "Le numéro de wallet est obligatoire")
+ private String numeroWallet;
+
+ /** Nom du business associé au wallet */
+ private String nomBusiness;
+
+ /** Date de dernière mise à jour du solde */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime dateDerniereMiseAJour;
+
+ /** Date de dernière synchronisation avec Wave */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime dateDerniereSynchronisation;
+
+ /** Statut du wallet */
+ @Pattern(
+ regexp = "^(ACTIVE|INACTIVE|SUSPENDED|BLOCKED)$",
+ message = "Le statut doit être ACTIVE, INACTIVE, SUSPENDED ou BLOCKED")
+ private String statutWallet;
+
+ /** Limite de transaction quotidienne */
+ @DecimalMin(value = "0.0", message = "La limite doit être positive ou nulle")
+ @Digits(
+ integer = 12,
+ fraction = 2,
+ message = "La limite ne peut avoir plus de 12 chiffres entiers et 2 décimales")
+ private BigDecimal limiteQuotidienne;
+
+ /** Montant déjà utilisé aujourd'hui */
+ @DecimalMin(value = "0.0", message = "Le montant utilisé doit être positif ou nul")
+ @Digits(
+ integer = 12,
+ fraction = 2,
+ message = "Le montant ne peut avoir plus de 12 chiffres entiers et 2 décimales")
+ private BigDecimal montantUtiliseAujourdhui;
+
+ /** Limite mensuelle */
+ @DecimalMin(value = "0.0", message = "La limite doit être positive ou nulle")
+ @Digits(
+ integer = 12,
+ fraction = 2,
+ message = "La limite ne peut avoir plus de 12 chiffres entiers et 2 décimales")
+ private BigDecimal limiteMensuelle;
+
+ /** Montant utilisé ce mois */
+ @DecimalMin(value = "0.0", message = "Le montant utilisé doit être positif ou nul")
+ @Digits(
+ integer = 12,
+ fraction = 2,
+ message = "Le montant ne peut avoir plus de 12 chiffres entiers et 2 décimales")
+ private BigDecimal montantUtiliseCeMois;
+
+ /** Nombre de transactions aujourd'hui */
+ private Integer nombreTransactionsAujourdhui;
+
+ /** Nombre de transactions ce mois */
+ private Integer nombreTransactionsCeMois;
+
+ /** Dernière erreur de synchronisation */
+ private String derniereErreur;
+
+ /** Code de la dernière erreur */
+ private String codeDerniereErreur;
+
+ // Constructeurs
+ public WaveBalanceDTO() {
+ super();
+ this.devise = "XOF";
+ this.statutWallet = "ACTIVE";
+ this.soldeEnAttente = BigDecimal.ZERO;
+ this.montantUtiliseAujourdhui = BigDecimal.ZERO;
+ this.montantUtiliseCeMois = BigDecimal.ZERO;
+ this.nombreTransactionsAujourdhui = 0;
+ this.nombreTransactionsCeMois = 0;
+ }
+
+ public WaveBalanceDTO(String numeroWallet, BigDecimal soldeDisponible) {
+ this();
+ this.numeroWallet = numeroWallet;
+ this.soldeDisponible = soldeDisponible;
+ this.soldeTotal = soldeDisponible;
+ }
+
+ // Getters et Setters
+ public BigDecimal getSoldeDisponible() {
+ return soldeDisponible;
+ }
+
+ public void setSoldeDisponible(BigDecimal soldeDisponible) {
+ this.soldeDisponible = soldeDisponible;
+ calculerSoldeTotal();
+ }
+
+ public BigDecimal getSoldeEnAttente() {
+ return soldeEnAttente;
+ }
+
+ public void setSoldeEnAttente(BigDecimal soldeEnAttente) {
+ this.soldeEnAttente = soldeEnAttente;
+ calculerSoldeTotal();
+ }
+
+ public BigDecimal getSoldeTotal() {
+ return soldeTotal;
+ }
+
+ public void setSoldeTotal(BigDecimal soldeTotal) {
+ this.soldeTotal = soldeTotal;
+ }
+
+ public String getDevise() {
+ return devise;
+ }
+
+ public void setDevise(String devise) {
+ this.devise = devise;
+ }
+
+ public String getNumeroWallet() {
+ return numeroWallet;
+ }
+
+ public void setNumeroWallet(String numeroWallet) {
+ this.numeroWallet = numeroWallet;
+ }
+
+ public String getNomBusiness() {
+ return nomBusiness;
+ }
+
+ public void setNomBusiness(String nomBusiness) {
+ this.nomBusiness = nomBusiness;
+ }
+
+ public LocalDateTime getDateDerniereMiseAJour() {
+ return dateDerniereMiseAJour;
+ }
+
+ public void setDateDerniereMiseAJour(LocalDateTime dateDerniereMiseAJour) {
+ this.dateDerniereMiseAJour = dateDerniereMiseAJour;
+ }
+
+ public LocalDateTime getDateDerniereSynchronisation() {
+ return dateDerniereSynchronisation;
+ }
+
+ public void setDateDerniereSynchronisation(LocalDateTime dateDerniereSynchronisation) {
+ this.dateDerniereSynchronisation = dateDerniereSynchronisation;
+ }
+
+ public String getStatutWallet() {
+ return statutWallet;
+ }
+
+ public void setStatutWallet(String statutWallet) {
+ this.statutWallet = statutWallet;
+ }
+
+ public BigDecimal getLimiteQuotidienne() {
+ return limiteQuotidienne;
+ }
+
+ public void setLimiteQuotidienne(BigDecimal limiteQuotidienne) {
+ this.limiteQuotidienne = limiteQuotidienne;
+ }
+
+ public BigDecimal getMontantUtiliseAujourdhui() {
+ return montantUtiliseAujourdhui;
+ }
+
+ public void setMontantUtiliseAujourdhui(BigDecimal montantUtiliseAujourdhui) {
+ this.montantUtiliseAujourdhui = montantUtiliseAujourdhui;
+ }
+
+ public BigDecimal getLimiteMensuelle() {
+ return limiteMensuelle;
+ }
+
+ public void setLimiteMensuelle(BigDecimal limiteMensuelle) {
+ this.limiteMensuelle = limiteMensuelle;
+ }
+
+ public BigDecimal getMontantUtiliseCeMois() {
+ return montantUtiliseCeMois;
+ }
+
+ public void setMontantUtiliseCeMois(BigDecimal montantUtiliseCeMois) {
+ this.montantUtiliseCeMois = montantUtiliseCeMois;
+ }
+
+ public Integer getNombreTransactionsAujourdhui() {
+ return nombreTransactionsAujourdhui;
+ }
+
+ public void setNombreTransactionsAujourdhui(Integer nombreTransactionsAujourdhui) {
+ this.nombreTransactionsAujourdhui = nombreTransactionsAujourdhui;
+ }
+
+ public Integer getNombreTransactionsCeMois() {
+ return nombreTransactionsCeMois;
+ }
+
+ public void setNombreTransactionsCeMois(Integer nombreTransactionsCeMois) {
+ this.nombreTransactionsCeMois = nombreTransactionsCeMois;
+ }
+
+ public String getDerniereErreur() {
+ return derniereErreur;
+ }
+
+ public void setDerniereErreur(String derniereErreur) {
+ this.derniereErreur = derniereErreur;
+ }
+
+ public String getCodeDerniereErreur() {
+ return codeDerniereErreur;
+ }
+
+ public void setCodeDerniereErreur(String codeDerniereErreur) {
+ this.codeDerniereErreur = codeDerniereErreur;
+ }
+
+ // Méthodes utilitaires
+
+ /** Calcule le solde total */
+ private void calculerSoldeTotal() {
+ if (soldeDisponible != null && soldeEnAttente != null) {
+ this.soldeTotal = soldeDisponible.add(soldeEnAttente);
+ }
+ }
+
+ /**
+ * Vérifie si le wallet est actif
+ *
+ * @return true si le wallet est actif
+ */
+ public boolean isWalletActif() {
+ return "ACTIVE".equals(statutWallet);
+ }
+
+ /**
+ * Vérifie si le solde est suffisant pour un montant donné
+ *
+ * @param montant Le montant à vérifier
+ * @return true si le solde est suffisant
+ */
+ public boolean isSoldeSuffisant(BigDecimal montant) {
+ return soldeDisponible != null && soldeDisponible.compareTo(montant) >= 0;
+ }
+
+ /**
+ * Calcule le solde disponible restant pour aujourd'hui
+ *
+ * @return Le montant encore disponible aujourd'hui
+ */
+ public BigDecimal getSoldeDisponibleAujourdhui() {
+ if (soldeDisponible == null || limiteQuotidienne == null || montantUtiliseAujourdhui == null) {
+ return soldeDisponible;
+ }
+
+ BigDecimal limiteRestante = limiteQuotidienne.subtract(montantUtiliseAujourdhui);
+ return soldeDisponible.min(limiteRestante);
+ }
+
+ /**
+ * Met à jour les statistiques après une transaction
+ *
+ * @param montant Le montant de la transaction
+ */
+ public void mettreAJourApresTransaction(BigDecimal montant) {
+ if (montantUtiliseAujourdhui == null) montantUtiliseAujourdhui = BigDecimal.ZERO;
+ if (montantUtiliseCeMois == null) montantUtiliseCeMois = BigDecimal.ZERO;
+ if (nombreTransactionsAujourdhui == null) nombreTransactionsAujourdhui = 0;
+ if (nombreTransactionsCeMois == null) nombreTransactionsCeMois = 0;
+
+ this.montantUtiliseAujourdhui = montantUtiliseAujourdhui.add(montant);
+ this.montantUtiliseCeMois = montantUtiliseCeMois.add(montant);
+ this.nombreTransactionsAujourdhui++;
+ this.nombreTransactionsCeMois++;
+ this.dateDerniereMiseAJour = LocalDateTime.now();
+ }
+
+ @Override
+ public String toString() {
+ return "WaveBalanceDTO{"
+ + "numeroWallet='"
+ + numeroWallet
+ + '\''
+ + ", soldeDisponible="
+ + soldeDisponible
+ + ", soldeTotal="
+ + soldeTotal
+ + ", devise='"
+ + devise
+ + '\''
+ + ", statutWallet='"
+ + statutWallet
+ + '\''
+ + "} "
+ + super.toString();
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/paiement/WaveCheckoutSessionDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/paiement/WaveCheckoutSessionDTO.java
index 0969c33..4493763 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/paiement/WaveCheckoutSessionDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/paiement/WaveCheckoutSessionDTO.java
@@ -1,168 +1,168 @@
-package dev.lions.unionflow.server.api.dto.paiement;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.paiement.StatutSession;
-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.LocalDateTime;
-import java.util.UUID;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * DTO pour les sessions de paiement Wave Money (Checkout API) Représente une session de paiement
- * créée via l'API Wave Checkout
- *
- *
Basé sur l'API officielle Wave : https://docs.wave.com/business#checkout-api
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-10
- */
-@Getter
-@Setter
-public class WaveCheckoutSessionDTO extends BaseDTO {
-
- private static final long serialVersionUID = 1L;
-
- /** ID de la session Wave (retourné par l'API) */
- @NotBlank(message = "L'ID de session Wave est obligatoire")
- private String waveSessionId;
-
- /** URL de la session de paiement Wave (générée par l'API Wave) */
- @Size(max = 500, message = "L'URL ne peut pas dépasser 500 caractères")
- private String waveUrl;
-
- /** Montant du paiement */
- @NotNull(message = "Le montant est obligatoire")
- @DecimalMin(value = "0.01", message = "Le montant 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 montant;
-
- /** Devise (XOF pour le Sénégal) */
- @NotBlank(message = "La devise est obligatoire")
- @Pattern(regexp = "^[A-Z]{3}$", message = "La devise doit être un code ISO à 3 lettres")
- private String devise = "XOF";
-
- /** URL de succès (redirection après paiement réussi) */
- @NotBlank(message = "L'URL de succès est obligatoire")
- @Size(max = 500, message = "L'URL de succès ne peut pas dépasser 500 caractères")
- private String successUrl;
-
- /** URL d'erreur (redirection après échec) */
- @NotBlank(message = "L'URL d'erreur est obligatoire")
- @Size(max = 500, message = "L'URL d'erreur ne peut pas dépasser 500 caractères")
- private String errorUrl;
-
- /** Statut de la session */
- @NotNull(message = "Le statut est obligatoire")
- private StatutSession statut;
-
- /** ID de l'organisation qui effectue le paiement */
- private UUID organisationId;
-
- /** Nom de l'organisation */
- private String nomOrganisation;
-
- /** ID du membre qui effectue le paiement */
- private UUID membreId;
-
- /** Nom du membre */
- private String nomMembre;
-
- /** Type de paiement (COTISATION, ABONNEMENT, DON, AUTRE) */
- @Pattern(
- regexp = "^(COTISATION|ABONNEMENT|DON|EVENEMENT|FORMATION|AUTRE)$",
- message = "Type de paiement invalide")
- private String typePaiement;
-
- /** Référence du paiement dans UnionFlow */
- @Size(max = 100, message = "La référence ne peut pas dépasser 100 caractères")
- private String referenceUnionFlow;
-
- /** Description du paiement */
- @Size(max = 500, message = "La description ne peut pas dépasser 500 caractères")
- private String description;
-
- /** Nom du business affiché (override_business_name) */
- @Size(max = 100, message = "Le nom du business ne peut pas dépasser 100 caractères")
- private String nomBusinessAffiche;
-
- /** ID du marchand agrégé (si applicable) */
- private String aggregatedMerchantId;
-
- /** Date d'expiration de la session */
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- private LocalDateTime dateExpiration;
-
- /** Date de completion du paiement */
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- private LocalDateTime dateCompletion;
-
- /** Numéro de téléphone du payeur (si fourni) */
- @Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Format de numéro de téléphone invalide")
- private String telephonePayeur;
-
- /** Email du payeur (si fourni) */
- @Pattern(regexp = "^[A-Za-z0-9+_.-]+@(.+)$", message = "Format d'email invalide")
- private String emailPayeur;
-
- /** Adresse IP du client */
- private String adresseIpClient;
-
- /** User Agent du navigateur */
- @Size(max = 500, message = "Le User Agent ne peut pas dépasser 500 caractères")
- private String userAgent;
-
- /** Données de callback reçues de Wave */
- @Size(max = 2000, message = "Les données callback ne peuvent pas dépasser 2000 caractères")
- private String callbackData;
-
- /** Code d'erreur Wave (si échec) */
- private String codeErreurWave;
-
- /** Message d'erreur Wave (si échec) */
- @Size(max = 500, message = "Le message d'erreur ne peut pas dépasser 500 caractères")
- private String messageErreurWave;
-
- /** Nombre de tentatives de paiement */
- private Integer nombreTentatives;
-
- /** Session liée à un webhook */
- private Boolean webhookRecu;
-
- /** Date de réception du webhook */
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- private LocalDateTime dateWebhook;
-
- /** Données du webhook reçu */
- @Size(max = 2000, message = "Les données webhook ne peuvent pas dépasser 2000 caractères")
- private String donneesWebhook;
-
- // Constructeurs
- public WaveCheckoutSessionDTO() {
- super();
- this.devise = "XOF";
- this.statut = StatutSession.PENDING;
- this.nombreTentatives = 0;
- this.webhookRecu = false;
- }
-
- public WaveCheckoutSessionDTO(BigDecimal montant, String successUrl, String errorUrl) {
- this();
- this.montant = montant;
- this.successUrl = successUrl;
- this.errorUrl = errorUrl;
- }
-
- // Getters et Setters générés automatiquement par Lombok @Getter/@Setter
-}
+package dev.lions.unionflow.server.api.dto.paiement;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.paiement.StatutSession;
+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.LocalDateTime;
+import java.util.UUID;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * DTO pour les sessions de paiement Wave Money (Checkout API) Représente une session de paiement
+ * créée via l'API Wave Checkout
+ *
+ *
Basé sur l'API officielle Wave : https://docs.wave.com/business#checkout-api
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2025-01-10
+ */
+@Getter
+@Setter
+public class WaveCheckoutSessionDTO extends BaseDTO {
+
+ private static final long serialVersionUID = 1L;
+
+ /** ID de la session Wave (retourné par l'API) */
+ @NotBlank(message = "L'ID de session Wave est obligatoire")
+ private String waveSessionId;
+
+ /** URL de la session de paiement Wave (générée par l'API Wave) */
+ @Size(max = 500, message = "L'URL ne peut pas dépasser 500 caractères")
+ private String waveUrl;
+
+ /** Montant du paiement */
+ @NotNull(message = "Le montant est obligatoire")
+ @DecimalMin(value = "0.01", message = "Le montant 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 montant;
+
+ /** Devise (XOF pour le Sénégal) */
+ @NotBlank(message = "La devise est obligatoire")
+ @Pattern(regexp = "^[A-Z]{3}$", message = "La devise doit être un code ISO à 3 lettres")
+ private String devise = "XOF";
+
+ /** URL de succès (redirection après paiement réussi) */
+ @NotBlank(message = "L'URL de succès est obligatoire")
+ @Size(max = 500, message = "L'URL de succès ne peut pas dépasser 500 caractères")
+ private String successUrl;
+
+ /** URL d'erreur (redirection après échec) */
+ @NotBlank(message = "L'URL d'erreur est obligatoire")
+ @Size(max = 500, message = "L'URL d'erreur ne peut pas dépasser 500 caractères")
+ private String errorUrl;
+
+ /** Statut de la session */
+ @NotNull(message = "Le statut est obligatoire")
+ private StatutSession statut;
+
+ /** ID de l'organisation qui effectue le paiement */
+ private UUID organisationId;
+
+ /** Nom de l'organisation */
+ private String nomOrganisation;
+
+ /** ID du membre qui effectue le paiement */
+ private UUID membreId;
+
+ /** Nom du membre */
+ private String nomMembre;
+
+ /** Type de paiement (COTISATION, ABONNEMENT, DON, AUTRE) */
+ @Pattern(
+ regexp = "^(COTISATION|ABONNEMENT|DON|EVENEMENT|FORMATION|AUTRE)$",
+ message = "Type de paiement invalide")
+ private String typePaiement;
+
+ /** Référence du paiement dans UnionFlow */
+ @Size(max = 100, message = "La référence ne peut pas dépasser 100 caractères")
+ private String referenceUnionFlow;
+
+ /** Description du paiement */
+ @Size(max = 500, message = "La description ne peut pas dépasser 500 caractères")
+ private String description;
+
+ /** Nom du business affiché (override_business_name) */
+ @Size(max = 100, message = "Le nom du business ne peut pas dépasser 100 caractères")
+ private String nomBusinessAffiche;
+
+ /** ID du marchand agrégé (si applicable) */
+ private String aggregatedMerchantId;
+
+ /** Date d'expiration de la session */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime dateExpiration;
+
+ /** Date de completion du paiement */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime dateCompletion;
+
+ /** Numéro de téléphone du payeur (si fourni) */
+ @Pattern(regexp = "^\\+?[0-9]{8,15}$", message = "Format de numéro de téléphone invalide")
+ private String telephonePayeur;
+
+ /** Email du payeur (si fourni) */
+ @Pattern(regexp = "^[A-Za-z0-9+_.-]+@(.+)$", message = "Format d'email invalide")
+ private String emailPayeur;
+
+ /** Adresse IP du client */
+ private String adresseIpClient;
+
+ /** User Agent du navigateur */
+ @Size(max = 500, message = "Le User Agent ne peut pas dépasser 500 caractères")
+ private String userAgent;
+
+ /** Données de callback reçues de Wave */
+ @Size(max = 2000, message = "Les données callback ne peuvent pas dépasser 2000 caractères")
+ private String callbackData;
+
+ /** Code d'erreur Wave (si échec) */
+ private String codeErreurWave;
+
+ /** Message d'erreur Wave (si échec) */
+ @Size(max = 500, message = "Le message d'erreur ne peut pas dépasser 500 caractères")
+ private String messageErreurWave;
+
+ /** Nombre de tentatives de paiement */
+ private Integer nombreTentatives;
+
+ /** Session liée à un webhook */
+ private Boolean webhookRecu;
+
+ /** Date de réception du webhook */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime dateWebhook;
+
+ /** Données du webhook reçu */
+ @Size(max = 2000, message = "Les données webhook ne peuvent pas dépasser 2000 caractères")
+ private String donneesWebhook;
+
+ // Constructeurs
+ public WaveCheckoutSessionDTO() {
+ super();
+ this.devise = "XOF";
+ this.statut = StatutSession.PENDING;
+ this.nombreTentatives = 0;
+ this.webhookRecu = false;
+ }
+
+ public WaveCheckoutSessionDTO(BigDecimal montant, String successUrl, String errorUrl) {
+ this();
+ this.montant = montant;
+ this.successUrl = successUrl;
+ this.errorUrl = errorUrl;
+ }
+
+ // Getters et Setters générés automatiquement par Lombok @Getter/@Setter
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/paiement/WaveWebhookDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/paiement/WaveWebhookDTO.java
index 73cb9e0..69fcc6a 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/paiement/WaveWebhookDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/paiement/WaveWebhookDTO.java
@@ -1,464 +1,464 @@
-package dev.lions.unionflow.server.api.dto.paiement;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.paiement.StatutTraitement;
-import dev.lions.unionflow.server.api.enums.paiement.TypeEvenement;
-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.LocalDateTime;
-import java.util.UUID;
-import lombok.Getter;
-import lombok.Setter;
-
-/**
- * DTO pour les webhooks Wave Money Représente les notifications reçues de Wave lors d'événements
- *
- *
Basé sur l'API officielle Wave : https://docs.wave.com/business#webhooks
- *
- * @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-10
- */
-@Getter
-@Setter
-public class WaveWebhookDTO extends BaseDTO {
-
- private static final long serialVersionUID = 1L;
-
- /** ID unique du webhook Wave */
- @NotBlank(message = "L'ID du webhook est obligatoire")
- private String webhookId;
-
- /** Type d'événement */
- @NotNull(message = "Le type d'événement est obligatoire")
- private TypeEvenement typeEvenement;
-
- /** Code de l'événement tel que reçu de Wave */
- @NotBlank(message = "Le code événement est obligatoire")
- private String codeEvenement;
-
- /** Statut de traitement du webhook */
- @NotNull(message = "Le statut de traitement est obligatoire")
- private StatutTraitement statutTraitement;
-
- /** Payload JSON complet reçu de Wave */
- @NotBlank(message = "Le payload est obligatoire")
- @Size(max = 5000, message = "Le payload ne peut pas dépasser 5000 caractères")
- private String payloadJson;
-
- /** Headers HTTP reçus */
- @Size(max = 2000, message = "Les headers ne peuvent pas dépasser 2000 caractères")
- private String headersHttp;
-
- /** Signature Wave pour vérification */
- private String signatureWave;
-
- /** Date de réception du webhook */
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- private LocalDateTime dateReception;
-
- /** Date de traitement du webhook */
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- private LocalDateTime dateTraitement;
-
- /** ID de la session checkout concernée (si applicable) */
- private String sessionCheckoutId;
-
- /** ID de la transaction Wave concernée */
- private String transactionWaveId;
-
- /** Montant de la transaction (si applicable) */
- private BigDecimal montantTransaction;
-
- /** Devise de la transaction */
- @Pattern(regexp = "^[A-Z]{3}$", message = "La devise doit être un code ISO à 3 lettres")
- private String deviseTransaction;
-
- /** Statut de la transaction Wave */
- private String statutTransactionWave;
-
- /** ID de l'organisation UnionFlow concernée */
- private UUID organisationId;
-
- /** ID du membre UnionFlow concerné */
- private UUID membreId;
-
- /** Référence UnionFlow liée */
- private String referenceUnionFlow;
-
- /** Type de paiement UnionFlow */
- @Pattern(
- regexp = "^(COTISATION|ABONNEMENT|DON|EVENEMENT|FORMATION|AUTRE)$",
- message = "Type de paiement invalide")
- private String typePaiementUnionFlow;
-
- /** Adresse IP source du webhook */
- private String adresseIpSource;
-
- /** User Agent du webhook */
- @Size(max = 500, message = "Le User Agent ne peut pas dépasser 500 caractères")
- private String userAgentSource;
-
- /** Nombre de tentatives de traitement */
- private Integer nombreTentativesTraitement;
-
- /** Message d'erreur de traitement (si échec) */
- @Size(max = 1000, message = "Le message d'erreur ne peut pas dépasser 1000 caractères")
- private String messageErreurTraitement;
-
- /** Code d'erreur de traitement (si échec) */
- private String codeErreurTraitement;
-
- /** Stack trace de l'erreur (si échec) */
- @Size(max = 3000, message = "La stack trace ne peut pas dépasser 3000 caractères")
- private String stackTraceErreur;
-
- /** Webhook traité automatiquement */
- private Boolean traitementAutomatique;
-
- /** Webhook nécessitant une intervention manuelle */
- private Boolean interventionManuelleRequise;
-
- /** Notes de traitement manuel */
- @Size(max = 1000, message = "Les notes ne peuvent pas dépasser 1000 caractères")
- private String notesTraitementManuel;
-
- /** Utilisateur ayant traité manuellement */
- private String utilisateurTraitementManuel;
-
- /** Date du traitement manuel */
- @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
- private LocalDateTime dateTraitementManuel;
-
- // Constructeurs
- public WaveWebhookDTO() {
- super();
- this.statutTraitement = StatutTraitement.RECU;
- this.dateReception = LocalDateTime.now();
- this.nombreTentativesTraitement = 0;
- this.traitementAutomatique = true;
- this.interventionManuelleRequise = false;
- }
-
- public WaveWebhookDTO(String webhookId, TypeEvenement typeEvenement, String payloadJson) {
- this();
- this.webhookId = webhookId;
- this.typeEvenement = typeEvenement;
- this.codeEvenement = typeEvenement.getCodeWave();
- this.payloadJson = payloadJson;
- }
-
- // Getters et Setters
- public String getWebhookId() {
- return webhookId;
- }
-
- public void setWebhookId(String webhookId) {
- this.webhookId = webhookId;
- }
-
- public TypeEvenement getTypeEvenement() {
- return typeEvenement;
- }
-
- public void setTypeEvenement(TypeEvenement typeEvenement) {
- this.typeEvenement = typeEvenement;
- if (typeEvenement != null) {
- this.codeEvenement = typeEvenement.getCodeWave();
- }
- }
-
- public String getCodeEvenement() {
- return codeEvenement;
- }
-
- public void setCodeEvenement(String codeEvenement) {
- this.codeEvenement = codeEvenement;
- this.typeEvenement = TypeEvenement.fromCode(codeEvenement);
- }
-
- public StatutTraitement getStatutTraitement() {
- return statutTraitement;
- }
-
- public void setStatutTraitement(StatutTraitement statutTraitement) {
- this.statutTraitement = statutTraitement;
- }
-
- public String getPayloadJson() {
- return payloadJson;
- }
-
- public void setPayloadJson(String payloadJson) {
- this.payloadJson = payloadJson;
- }
-
- public String getHeadersHttp() {
- return headersHttp;
- }
-
- public void setHeadersHttp(String headersHttp) {
- this.headersHttp = headersHttp;
- }
-
- public String getSignatureWave() {
- return signatureWave;
- }
-
- public void setSignatureWave(String signatureWave) {
- this.signatureWave = signatureWave;
- }
-
- public LocalDateTime getDateReception() {
- return dateReception;
- }
-
- public void setDateReception(LocalDateTime dateReception) {
- this.dateReception = dateReception;
- }
-
- public LocalDateTime getDateTraitement() {
- return dateTraitement;
- }
-
- public void setDateTraitement(LocalDateTime dateTraitement) {
- this.dateTraitement = dateTraitement;
- }
-
- public String getSessionCheckoutId() {
- return sessionCheckoutId;
- }
-
- public void setSessionCheckoutId(String sessionCheckoutId) {
- this.sessionCheckoutId = sessionCheckoutId;
- }
-
- public String getTransactionWaveId() {
- return transactionWaveId;
- }
-
- public void setTransactionWaveId(String transactionWaveId) {
- this.transactionWaveId = transactionWaveId;
- }
-
- public BigDecimal getMontantTransaction() {
- return montantTransaction;
- }
-
- public void setMontantTransaction(BigDecimal montantTransaction) {
- this.montantTransaction = montantTransaction;
- }
-
- public String getDeviseTransaction() {
- return deviseTransaction;
- }
-
- public void setDeviseTransaction(String deviseTransaction) {
- this.deviseTransaction = deviseTransaction;
- }
-
- public String getStatutTransactionWave() {
- return statutTransactionWave;
- }
-
- public void setStatutTransactionWave(String statutTransactionWave) {
- this.statutTransactionWave = statutTransactionWave;
- }
-
- public UUID getOrganisationId() {
- return organisationId;
- }
-
- public void setOrganisationId(UUID organisationId) {
- this.organisationId = organisationId;
- }
-
- public UUID getMembreId() {
- return membreId;
- }
-
- public void setMembreId(UUID membreId) {
- this.membreId = membreId;
- }
-
- public String getReferenceUnionFlow() {
- return referenceUnionFlow;
- }
-
- public void setReferenceUnionFlow(String referenceUnionFlow) {
- this.referenceUnionFlow = referenceUnionFlow;
- }
-
- public String getTypePaiementUnionFlow() {
- return typePaiementUnionFlow;
- }
-
- public void setTypePaiementUnionFlow(String typePaiementUnionFlow) {
- this.typePaiementUnionFlow = typePaiementUnionFlow;
- }
-
- public String getAdresseIpSource() {
- return adresseIpSource;
- }
-
- public void setAdresseIpSource(String adresseIpSource) {
- this.adresseIpSource = adresseIpSource;
- }
-
- public String getUserAgentSource() {
- return userAgentSource;
- }
-
- public void setUserAgentSource(String userAgentSource) {
- this.userAgentSource = userAgentSource;
- }
-
- public Integer getNombreTentativesTraitement() {
- return nombreTentativesTraitement;
- }
-
- public void setNombreTentativesTraitement(Integer nombreTentativesTraitement) {
- this.nombreTentativesTraitement = nombreTentativesTraitement;
- }
-
- public String getMessageErreurTraitement() {
- return messageErreurTraitement;
- }
-
- public void setMessageErreurTraitement(String messageErreurTraitement) {
- this.messageErreurTraitement = messageErreurTraitement;
- }
-
- public String getCodeErreurTraitement() {
- return codeErreurTraitement;
- }
-
- public void setCodeErreurTraitement(String codeErreurTraitement) {
- this.codeErreurTraitement = codeErreurTraitement;
- }
-
- public String getStackTraceErreur() {
- return stackTraceErreur;
- }
-
- public void setStackTraceErreur(String stackTraceErreur) {
- this.stackTraceErreur = stackTraceErreur;
- }
-
- public Boolean getTraitementAutomatique() {
- return traitementAutomatique;
- }
-
- public void setTraitementAutomatique(Boolean traitementAutomatique) {
- this.traitementAutomatique = traitementAutomatique;
- }
-
- public Boolean getInterventionManuelleRequise() {
- return interventionManuelleRequise;
- }
-
- public void setInterventionManuelleRequise(Boolean interventionManuelleRequise) {
- this.interventionManuelleRequise = interventionManuelleRequise;
- }
-
- public String getNotesTraitementManuel() {
- return notesTraitementManuel;
- }
-
- public void setNotesTraitementManuel(String notesTraitementManuel) {
- this.notesTraitementManuel = notesTraitementManuel;
- }
-
- public String getUtilisateurTraitementManuel() {
- return utilisateurTraitementManuel;
- }
-
- public void setUtilisateurTraitementManuel(String utilisateurTraitementManuel) {
- this.utilisateurTraitementManuel = utilisateurTraitementManuel;
- }
-
- public LocalDateTime getDateTraitementManuel() {
- return dateTraitementManuel;
- }
-
- public void setDateTraitementManuel(LocalDateTime dateTraitementManuel) {
- this.dateTraitementManuel = dateTraitementManuel;
- }
-
- // Méthodes utilitaires
-
- /**
- * Vérifie si le webhook concerne un checkout
- *
- * @return true si c'est un événement de checkout
- */
- public boolean isEvenementCheckout() {
- return typeEvenement == TypeEvenement.CHECKOUT_COMPLETE
- || typeEvenement == TypeEvenement.CHECKOUT_CANCELLED
- || typeEvenement == TypeEvenement.CHECKOUT_EXPIRED;
- }
-
- /**
- * Vérifie si le webhook concerne un payout
- *
- * @return true si c'est un événement de payout
- */
- public boolean isEvenementPayout() {
- return typeEvenement == TypeEvenement.PAYOUT_COMPLETE
- || typeEvenement == TypeEvenement.PAYOUT_FAILED;
- }
-
- /** Marque le webhook comme traité avec succès */
- public void marquerCommeTraite() {
- this.statutTraitement = StatutTraitement.TRAITE;
- this.dateTraitement = LocalDateTime.now();
- marquerCommeModifie("SYSTEM");
- }
-
- /**
- * Marque le webhook comme échoué
- *
- * @param messageErreur Le message d'erreur
- * @param codeErreur Le code d'erreur
- */
- public void marquerCommeEchec(String messageErreur, String codeErreur) {
- this.statutTraitement = StatutTraitement.ECHEC;
- this.messageErreurTraitement = messageErreur;
- this.codeErreurTraitement = codeErreur;
- this.nombreTentativesTraitement++;
- this.dateTraitement = LocalDateTime.now();
- marquerCommeModifie("SYSTEM");
- }
-
- /** Démarre le traitement du webhook */
- public void demarrerTraitement() {
- this.statutTraitement = StatutTraitement.EN_COURS;
- this.nombreTentativesTraitement++;
- marquerCommeModifie("SYSTEM");
- }
-
- @Override
- public String toString() {
- return "WaveWebhookDTO{"
- + "webhookId='"
- + webhookId
- + '\''
- + ", typeEvenement="
- + typeEvenement
- + ", statutTraitement="
- + statutTraitement
- + ", dateReception="
- + dateReception
- + ", sessionCheckoutId='"
- + sessionCheckoutId
- + '\''
- + ", montantTransaction="
- + montantTransaction
- + "} "
- + super.toString();
- }
-}
+package dev.lions.unionflow.server.api.dto.paiement;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.paiement.StatutTraitement;
+import dev.lions.unionflow.server.api.enums.paiement.TypeEvenement;
+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.LocalDateTime;
+import java.util.UUID;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * DTO pour les webhooks Wave Money Représente les notifications reçues de Wave lors d'événements
+ *
+ *
Basé sur l'API officielle Wave : https://docs.wave.com/business#webhooks
+ *
+ * @author UnionFlow Team
+ * @version 1.0
+ * @since 2025-01-10
+ */
+@Getter
+@Setter
+public class WaveWebhookDTO extends BaseDTO {
+
+ private static final long serialVersionUID = 1L;
+
+ /** ID unique du webhook Wave */
+ @NotBlank(message = "L'ID du webhook est obligatoire")
+ private String webhookId;
+
+ /** Type d'événement */
+ @NotNull(message = "Le type d'événement est obligatoire")
+ private TypeEvenement typeEvenement;
+
+ /** Code de l'événement tel que reçu de Wave */
+ @NotBlank(message = "Le code événement est obligatoire")
+ private String codeEvenement;
+
+ /** Statut de traitement du webhook */
+ @NotNull(message = "Le statut de traitement est obligatoire")
+ private StatutTraitement statutTraitement;
+
+ /** Payload JSON complet reçu de Wave */
+ @NotBlank(message = "Le payload est obligatoire")
+ @Size(max = 5000, message = "Le payload ne peut pas dépasser 5000 caractères")
+ private String payloadJson;
+
+ /** Headers HTTP reçus */
+ @Size(max = 2000, message = "Les headers ne peuvent pas dépasser 2000 caractères")
+ private String headersHttp;
+
+ /** Signature Wave pour vérification */
+ private String signatureWave;
+
+ /** Date de réception du webhook */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime dateReception;
+
+ /** Date de traitement du webhook */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime dateTraitement;
+
+ /** ID de la session checkout concernée (si applicable) */
+ private String sessionCheckoutId;
+
+ /** ID de la transaction Wave concernée */
+ private String transactionWaveId;
+
+ /** Montant de la transaction (si applicable) */
+ private BigDecimal montantTransaction;
+
+ /** Devise de la transaction */
+ @Pattern(regexp = "^[A-Z]{3}$", message = "La devise doit être un code ISO à 3 lettres")
+ private String deviseTransaction;
+
+ /** Statut de la transaction Wave */
+ private String statutTransactionWave;
+
+ /** ID de l'organisation UnionFlow concernée */
+ private UUID organisationId;
+
+ /** ID du membre UnionFlow concerné */
+ private UUID membreId;
+
+ /** Référence UnionFlow liée */
+ private String referenceUnionFlow;
+
+ /** Type de paiement UnionFlow */
+ @Pattern(
+ regexp = "^(COTISATION|ABONNEMENT|DON|EVENEMENT|FORMATION|AUTRE)$",
+ message = "Type de paiement invalide")
+ private String typePaiementUnionFlow;
+
+ /** Adresse IP source du webhook */
+ private String adresseIpSource;
+
+ /** User Agent du webhook */
+ @Size(max = 500, message = "Le User Agent ne peut pas dépasser 500 caractères")
+ private String userAgentSource;
+
+ /** Nombre de tentatives de traitement */
+ private Integer nombreTentativesTraitement;
+
+ /** Message d'erreur de traitement (si échec) */
+ @Size(max = 1000, message = "Le message d'erreur ne peut pas dépasser 1000 caractères")
+ private String messageErreurTraitement;
+
+ /** Code d'erreur de traitement (si échec) */
+ private String codeErreurTraitement;
+
+ /** Stack trace de l'erreur (si échec) */
+ @Size(max = 3000, message = "La stack trace ne peut pas dépasser 3000 caractères")
+ private String stackTraceErreur;
+
+ /** Webhook traité automatiquement */
+ private Boolean traitementAutomatique;
+
+ /** Webhook nécessitant une intervention manuelle */
+ private Boolean interventionManuelleRequise;
+
+ /** Notes de traitement manuel */
+ @Size(max = 1000, message = "Les notes ne peuvent pas dépasser 1000 caractères")
+ private String notesTraitementManuel;
+
+ /** Utilisateur ayant traité manuellement */
+ private String utilisateurTraitementManuel;
+
+ /** Date du traitement manuel */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime dateTraitementManuel;
+
+ // Constructeurs
+ public WaveWebhookDTO() {
+ super();
+ this.statutTraitement = StatutTraitement.RECU;
+ this.dateReception = LocalDateTime.now();
+ this.nombreTentativesTraitement = 0;
+ this.traitementAutomatique = true;
+ this.interventionManuelleRequise = false;
+ }
+
+ public WaveWebhookDTO(String webhookId, TypeEvenement typeEvenement, String payloadJson) {
+ this();
+ this.webhookId = webhookId;
+ this.typeEvenement = typeEvenement;
+ this.codeEvenement = typeEvenement.getCodeWave();
+ this.payloadJson = payloadJson;
+ }
+
+ // Getters et Setters
+ public String getWebhookId() {
+ return webhookId;
+ }
+
+ public void setWebhookId(String webhookId) {
+ this.webhookId = webhookId;
+ }
+
+ public TypeEvenement getTypeEvenement() {
+ return typeEvenement;
+ }
+
+ public void setTypeEvenement(TypeEvenement typeEvenement) {
+ this.typeEvenement = typeEvenement;
+ if (typeEvenement != null) {
+ this.codeEvenement = typeEvenement.getCodeWave();
+ }
+ }
+
+ public String getCodeEvenement() {
+ return codeEvenement;
+ }
+
+ public void setCodeEvenement(String codeEvenement) {
+ this.codeEvenement = codeEvenement;
+ this.typeEvenement = TypeEvenement.fromCode(codeEvenement);
+ }
+
+ public StatutTraitement getStatutTraitement() {
+ return statutTraitement;
+ }
+
+ public void setStatutTraitement(StatutTraitement statutTraitement) {
+ this.statutTraitement = statutTraitement;
+ }
+
+ public String getPayloadJson() {
+ return payloadJson;
+ }
+
+ public void setPayloadJson(String payloadJson) {
+ this.payloadJson = payloadJson;
+ }
+
+ public String getHeadersHttp() {
+ return headersHttp;
+ }
+
+ public void setHeadersHttp(String headersHttp) {
+ this.headersHttp = headersHttp;
+ }
+
+ public String getSignatureWave() {
+ return signatureWave;
+ }
+
+ public void setSignatureWave(String signatureWave) {
+ this.signatureWave = signatureWave;
+ }
+
+ public LocalDateTime getDateReception() {
+ return dateReception;
+ }
+
+ public void setDateReception(LocalDateTime dateReception) {
+ this.dateReception = dateReception;
+ }
+
+ public LocalDateTime getDateTraitement() {
+ return dateTraitement;
+ }
+
+ public void setDateTraitement(LocalDateTime dateTraitement) {
+ this.dateTraitement = dateTraitement;
+ }
+
+ public String getSessionCheckoutId() {
+ return sessionCheckoutId;
+ }
+
+ public void setSessionCheckoutId(String sessionCheckoutId) {
+ this.sessionCheckoutId = sessionCheckoutId;
+ }
+
+ public String getTransactionWaveId() {
+ return transactionWaveId;
+ }
+
+ public void setTransactionWaveId(String transactionWaveId) {
+ this.transactionWaveId = transactionWaveId;
+ }
+
+ public BigDecimal getMontantTransaction() {
+ return montantTransaction;
+ }
+
+ public void setMontantTransaction(BigDecimal montantTransaction) {
+ this.montantTransaction = montantTransaction;
+ }
+
+ public String getDeviseTransaction() {
+ return deviseTransaction;
+ }
+
+ public void setDeviseTransaction(String deviseTransaction) {
+ this.deviseTransaction = deviseTransaction;
+ }
+
+ public String getStatutTransactionWave() {
+ return statutTransactionWave;
+ }
+
+ public void setStatutTransactionWave(String statutTransactionWave) {
+ this.statutTransactionWave = statutTransactionWave;
+ }
+
+ public UUID getOrganisationId() {
+ return organisationId;
+ }
+
+ public void setOrganisationId(UUID organisationId) {
+ this.organisationId = organisationId;
+ }
+
+ public UUID getMembreId() {
+ return membreId;
+ }
+
+ public void setMembreId(UUID membreId) {
+ this.membreId = membreId;
+ }
+
+ public String getReferenceUnionFlow() {
+ return referenceUnionFlow;
+ }
+
+ public void setReferenceUnionFlow(String referenceUnionFlow) {
+ this.referenceUnionFlow = referenceUnionFlow;
+ }
+
+ public String getTypePaiementUnionFlow() {
+ return typePaiementUnionFlow;
+ }
+
+ public void setTypePaiementUnionFlow(String typePaiementUnionFlow) {
+ this.typePaiementUnionFlow = typePaiementUnionFlow;
+ }
+
+ public String getAdresseIpSource() {
+ return adresseIpSource;
+ }
+
+ public void setAdresseIpSource(String adresseIpSource) {
+ this.adresseIpSource = adresseIpSource;
+ }
+
+ public String getUserAgentSource() {
+ return userAgentSource;
+ }
+
+ public void setUserAgentSource(String userAgentSource) {
+ this.userAgentSource = userAgentSource;
+ }
+
+ public Integer getNombreTentativesTraitement() {
+ return nombreTentativesTraitement;
+ }
+
+ public void setNombreTentativesTraitement(Integer nombreTentativesTraitement) {
+ this.nombreTentativesTraitement = nombreTentativesTraitement;
+ }
+
+ public String getMessageErreurTraitement() {
+ return messageErreurTraitement;
+ }
+
+ public void setMessageErreurTraitement(String messageErreurTraitement) {
+ this.messageErreurTraitement = messageErreurTraitement;
+ }
+
+ public String getCodeErreurTraitement() {
+ return codeErreurTraitement;
+ }
+
+ public void setCodeErreurTraitement(String codeErreurTraitement) {
+ this.codeErreurTraitement = codeErreurTraitement;
+ }
+
+ public String getStackTraceErreur() {
+ return stackTraceErreur;
+ }
+
+ public void setStackTraceErreur(String stackTraceErreur) {
+ this.stackTraceErreur = stackTraceErreur;
+ }
+
+ public Boolean getTraitementAutomatique() {
+ return traitementAutomatique;
+ }
+
+ public void setTraitementAutomatique(Boolean traitementAutomatique) {
+ this.traitementAutomatique = traitementAutomatique;
+ }
+
+ public Boolean getInterventionManuelleRequise() {
+ return interventionManuelleRequise;
+ }
+
+ public void setInterventionManuelleRequise(Boolean interventionManuelleRequise) {
+ this.interventionManuelleRequise = interventionManuelleRequise;
+ }
+
+ public String getNotesTraitementManuel() {
+ return notesTraitementManuel;
+ }
+
+ public void setNotesTraitementManuel(String notesTraitementManuel) {
+ this.notesTraitementManuel = notesTraitementManuel;
+ }
+
+ public String getUtilisateurTraitementManuel() {
+ return utilisateurTraitementManuel;
+ }
+
+ public void setUtilisateurTraitementManuel(String utilisateurTraitementManuel) {
+ this.utilisateurTraitementManuel = utilisateurTraitementManuel;
+ }
+
+ public LocalDateTime getDateTraitementManuel() {
+ return dateTraitementManuel;
+ }
+
+ public void setDateTraitementManuel(LocalDateTime dateTraitementManuel) {
+ this.dateTraitementManuel = dateTraitementManuel;
+ }
+
+ // Méthodes utilitaires
+
+ /**
+ * Vérifie si le webhook concerne un checkout
+ *
+ * @return true si c'est un événement de checkout
+ */
+ public boolean isEvenementCheckout() {
+ return typeEvenement == TypeEvenement.CHECKOUT_COMPLETE
+ || typeEvenement == TypeEvenement.CHECKOUT_CANCELLED
+ || typeEvenement == TypeEvenement.CHECKOUT_EXPIRED;
+ }
+
+ /**
+ * Vérifie si le webhook concerne un payout
+ *
+ * @return true si c'est un événement de payout
+ */
+ public boolean isEvenementPayout() {
+ return typeEvenement == TypeEvenement.PAYOUT_COMPLETE
+ || typeEvenement == TypeEvenement.PAYOUT_FAILED;
+ }
+
+ /** Marque le webhook comme traité avec succès */
+ public void marquerCommeTraite() {
+ this.statutTraitement = StatutTraitement.TRAITE;
+ this.dateTraitement = LocalDateTime.now();
+ marquerCommeModifie("SYSTEM");
+ }
+
+ /**
+ * Marque le webhook comme échoué
+ *
+ * @param messageErreur Le message d'erreur
+ * @param codeErreur Le code d'erreur
+ */
+ public void marquerCommeEchec(String messageErreur, String codeErreur) {
+ this.statutTraitement = StatutTraitement.ECHEC;
+ this.messageErreurTraitement = messageErreur;
+ this.codeErreurTraitement = codeErreur;
+ this.nombreTentativesTraitement++;
+ this.dateTraitement = LocalDateTime.now();
+ marquerCommeModifie("SYSTEM");
+ }
+
+ /** Démarre le traitement du webhook */
+ public void demarrerTraitement() {
+ this.statutTraitement = StatutTraitement.EN_COURS;
+ this.nombreTentativesTraitement++;
+ marquerCommeModifie("SYSTEM");
+ }
+
+ @Override
+ public String toString() {
+ return "WaveWebhookDTO{"
+ + "webhookId='"
+ + webhookId
+ + '\''
+ + ", typeEvenement="
+ + typeEvenement
+ + ", statutTraitement="
+ + statutTraitement
+ + ", dateReception="
+ + dateReception
+ + ", sessionCheckoutId='"
+ + sessionCheckoutId
+ + '\''
+ + ", montantTransaction="
+ + montantTransaction
+ + "} "
+ + super.toString();
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/paiement/request/InitierDepotEpargneRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/paiement/request/InitierDepotEpargneRequest.java
index 4b1a82a..e686936 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/paiement/request/InitierDepotEpargneRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/paiement/request/InitierDepotEpargneRequest.java
@@ -1,38 +1,38 @@
-package dev.lions.unionflow.server.api.dto.paiement.request;
-
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Pattern;
-import java.math.BigDecimal;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête pour initier un dépôt sur compte épargne via Wave (mobile money).
- * Réutilise le même flux que les cotisations : Wave Checkout → redirection → deep link.
- *
- * @param compteId ID du compte épargne à créditer
- * @param montant Montant du dépôt (XOF)
- * @param numeroTelephone Numéro Wave du membre (9 chiffres)
- * @param origineFonds Origine des fonds (LCB-FT) — obligatoire au-dessus du seuil configuré
- * @param justificationLcbFt Justification complémentaire LCB-FT si nécessaire
- */
-@Builder
-public record InitierDepotEpargneRequest(
- @NotNull(message = "L'ID du compte épargne est obligatoire")
- UUID compteId,
-
- @NotNull(message = "Le montant est obligatoire")
- @DecimalMin(value = "1", message = "Le montant doit être strictement positif")
- BigDecimal montant,
-
- @NotBlank(message = "Le numéro de téléphone Wave est obligatoire")
- @Pattern(regexp = "^\\d{9,15}$", message = "Numéro de téléphone invalide (9-15 chiffres)")
- String numeroTelephone,
-
- String origineFonds,
-
- String justificationLcbFt
-) {
-}
+package dev.lions.unionflow.server.api.dto.paiement.request;
+
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Pattern;
+import java.math.BigDecimal;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête pour initier un dépôt sur compte épargne via Wave (mobile money).
+ * Réutilise le même flux que les cotisations : Wave Checkout → redirection → deep link.
+ *
+ * @param compteId ID du compte épargne à créditer
+ * @param montant Montant du dépôt (XOF)
+ * @param numeroTelephone Numéro Wave du membre (9 chiffres)
+ * @param origineFonds Origine des fonds (LCB-FT) — obligatoire au-dessus du seuil configuré
+ * @param justificationLcbFt Justification complémentaire LCB-FT si nécessaire
+ */
+@Builder
+public record InitierDepotEpargneRequest(
+ @NotNull(message = "L'ID du compte épargne est obligatoire")
+ UUID compteId,
+
+ @NotNull(message = "Le montant est obligatoire")
+ @DecimalMin(value = "1", message = "Le montant doit être strictement positif")
+ BigDecimal montant,
+
+ @NotBlank(message = "Le numéro de téléphone Wave est obligatoire")
+ @Pattern(regexp = "^\\d{9,15}$", message = "Numéro de téléphone invalide (9-15 chiffres)")
+ String numeroTelephone,
+
+ String origineFonds,
+
+ String justificationLcbFt
+) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/reference/request/CreateTypeReferenceRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/reference/request/CreateTypeReferenceRequest.java
index b8ad671..8b099b3 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/reference/request/CreateTypeReferenceRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/reference/request/CreateTypeReferenceRequest.java
@@ -1,68 +1,68 @@
-package dev.lions.unionflow.server.api.dto.reference.request;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Size;
-import java.util.UUID;
-
-import lombok.Builder;
-
-/**
- * Requête de création d'une donnée de référence.
- *
- *
- * Utilisé pour ajouter une nouvelle valeur dans
- * un domaine existant de la table
- * {@code types_reference}.
- *
- * @author UnionFlow Team
- * @version 3.0
- * @since 2026-02-21
- */
-@Builder
-public record CreateTypeReferenceRequest(
-
- /** Domaine fonctionnel (ex: STATUT_ORGANISATION). */
- @NotBlank @Size(max = 50) String domaine,
-
- /** Code technique unique dans le domaine. */
- @NotBlank @Size(max = 50) String code,
-
- /** Libellé affiché dans l'interface. */
- @NotBlank @Size(max = 200) String libelle,
-
- /** Description longue optionnelle. */
- @Size(max = 1000) String description,
-
- /** Classe d'icône PrimeFaces (ex: pi-check). */
- @Size(max = 100) String icone,
-
- /** Code couleur hexadécimal (ex: #22C55E). */
- @Size(max = 50) String couleur,
-
- /** Sévérité PrimeFaces (success, warning...). */
- @Size(max = 20) String severity,
-
- /** Ordre d'affichage dans les listes. */
- Integer ordreAffichage,
-
- /** Valeur par défaut pour ce domaine. */
- Boolean estDefaut,
-
- /** Protégée contre la suppression admin. */
- Boolean estSysteme,
-
- /** UUID de l'organisation (null = global). */
- UUID organisationId,
-
- /**
- * Catégorie fonctionnelle (ex: FINANCIER_SOLIDAIRE).
- * Obligatoire pour domaine=TYPE_ORGANISATION.
- */
- @Size(max = 50) String categorie,
-
- /**
- * Modules métier CSV (ex: "MEMBRES,COTISATIONS,TONTINE,FINANCE").
- * Obligatoire pour domaine=TYPE_ORGANISATION.
- */
- String modulesRequis) {
-}
+package dev.lions.unionflow.server.api.dto.reference.request;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import java.util.UUID;
+
+import lombok.Builder;
+
+/**
+ * Requête de création d'une donnée de référence.
+ *
+ *
+ * Utilisé pour ajouter une nouvelle valeur dans
+ * un domaine existant de la table
+ * {@code types_reference}.
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ * @since 2026-02-21
+ */
+@Builder
+public record CreateTypeReferenceRequest(
+
+ /** Domaine fonctionnel (ex: STATUT_ORGANISATION). */
+ @NotBlank @Size(max = 50) String domaine,
+
+ /** Code technique unique dans le domaine. */
+ @NotBlank @Size(max = 50) String code,
+
+ /** Libellé affiché dans l'interface. */
+ @NotBlank @Size(max = 200) String libelle,
+
+ /** Description longue optionnelle. */
+ @Size(max = 1000) String description,
+
+ /** Classe d'icône PrimeFaces (ex: pi-check). */
+ @Size(max = 100) String icone,
+
+ /** Code couleur hexadécimal (ex: #22C55E). */
+ @Size(max = 50) String couleur,
+
+ /** Sévérité PrimeFaces (success, warning...). */
+ @Size(max = 20) String severity,
+
+ /** Ordre d'affichage dans les listes. */
+ Integer ordreAffichage,
+
+ /** Valeur par défaut pour ce domaine. */
+ Boolean estDefaut,
+
+ /** Protégée contre la suppression admin. */
+ Boolean estSysteme,
+
+ /** UUID de l'organisation (null = global). */
+ UUID organisationId,
+
+ /**
+ * Catégorie fonctionnelle (ex: FINANCIER_SOLIDAIRE).
+ * Obligatoire pour domaine=TYPE_ORGANISATION.
+ */
+ @Size(max = 50) String categorie,
+
+ /**
+ * Modules métier CSV (ex: "MEMBRES,COTISATIONS,TONTINE,FINANCE").
+ * Obligatoire pour domaine=TYPE_ORGANISATION.
+ */
+ String modulesRequis) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/reference/request/UpdateTypeReferenceRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/reference/request/UpdateTypeReferenceRequest.java
index d06dd37..d52a131 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/reference/request/UpdateTypeReferenceRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/reference/request/UpdateTypeReferenceRequest.java
@@ -1,51 +1,51 @@
-package dev.lions.unionflow.server.api.dto.reference.request;
-
-import jakarta.validation.constraints.Size;
-
-/**
- * Requête de mise à jour d'une donnée de référence.
- *
- *
- * Tous les champs sont optionnels : seuls les
- * champs renseignés seront mis à jour (patch
- * partiel).
- *
- * @author UnionFlow Team
- * @version 3.0
- * @since 2026-02-21
- */
-public record UpdateTypeReferenceRequest(
-
- /** Nouveau code (optionnel). */
- @Size(max = 50) String code,
-
- /** Nouveau libellé (optionnel). */
- @Size(max = 200) String libelle,
-
- /** Nouvelle description (optionnel). */
- @Size(max = 1000) String description,
-
- /** Nouvelle icône (optionnel). */
- @Size(max = 100) String icone,
-
- /** Nouvelle couleur (optionnel). */
- @Size(max = 50) String couleur,
-
- /** Nouvelle sévérité (optionnel). */
- @Size(max = 20) String severity,
-
- /** Nouvel ordre d'affichage (optionnel). */
- Integer ordreAffichage,
-
- /** Nouveau flag par défaut (optionnel). */
- Boolean estDefaut,
-
- /** Nouvel état actif/inactif (optionnel). */
- Boolean actif,
-
- /** Nouvelle catégorie fonctionnelle (optionnel). */
- @Size(max = 50) String categorie,
-
- /** Nouveaux modules requis CSV (optionnel). */
- String modulesRequis) {
-}
+package dev.lions.unionflow.server.api.dto.reference.request;
+
+import jakarta.validation.constraints.Size;
+
+/**
+ * Requête de mise à jour d'une donnée de référence.
+ *
+ *
+ * Tous les champs sont optionnels : seuls les
+ * champs renseignés seront mis à jour (patch
+ * partiel).
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ * @since 2026-02-21
+ */
+public record UpdateTypeReferenceRequest(
+
+ /** Nouveau code (optionnel). */
+ @Size(max = 50) String code,
+
+ /** Nouveau libellé (optionnel). */
+ @Size(max = 200) String libelle,
+
+ /** Nouvelle description (optionnel). */
+ @Size(max = 1000) String description,
+
+ /** Nouvelle icône (optionnel). */
+ @Size(max = 100) String icone,
+
+ /** Nouvelle couleur (optionnel). */
+ @Size(max = 50) String couleur,
+
+ /** Nouvelle sévérité (optionnel). */
+ @Size(max = 20) String severity,
+
+ /** Nouvel ordre d'affichage (optionnel). */
+ Integer ordreAffichage,
+
+ /** Nouveau flag par défaut (optionnel). */
+ Boolean estDefaut,
+
+ /** Nouvel état actif/inactif (optionnel). */
+ Boolean actif,
+
+ /** Nouvelle catégorie fonctionnelle (optionnel). */
+ @Size(max = 50) String categorie,
+
+ /** Nouveaux modules requis CSV (optionnel). */
+ String modulesRequis) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/reference/response/TypeReferenceResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/reference/response/TypeReferenceResponse.java
index 607b00a..4ea4cb7 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/reference/response/TypeReferenceResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/reference/response/TypeReferenceResponse.java
@@ -1,78 +1,78 @@
-package dev.lions.unionflow.server.api.dto.reference.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse complète d'une donnée de référence.
- *
- *
- * Inclut les champs d'audit (id, dates, version)
- * et toutes les métadonnées UI (icône, couleur,
- * sévérité).
- *
- * @author UnionFlow Team
- * @version 3.0
- * @since 2026-02-21
- */
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class TypeReferenceResponse extends BaseResponse {
-
- /** Domaine fonctionnel. */
- private String domaine;
-
- /** Code technique. */
- private String code;
-
- /** Libellé affiché. */
- private String libelle;
-
- /** Description longue. */
- private String description;
-
- /** Classe d'icône PrimeFaces. */
- private String icone;
-
- /** Code couleur hexadécimal. */
- private String couleur;
-
- /** Sévérité PrimeFaces. */
- private String severity;
-
- /** Ordre d'affichage. */
- private Integer ordreAffichage;
-
- /** Valeur par défaut du domaine. */
- private Boolean estDefaut;
-
- /** Protégée contre la suppression. */
- private Boolean estSysteme;
-
- /** UUID de l'organisation (null = global). */
- private UUID organisationId;
-
- /**
- * Catégorie fonctionnelle du type d'organisation.
- * Valeurs: ASSOCIATIF, FINANCIER_SOLIDAIRE, RELIGIEUX, PROFESSIONNEL, RESEAU_FEDERATION.
- * Uniquement pertinent pour domaine=TYPE_ORGANISATION.
- */
- private String categorie;
-
- /**
- * Modules métier activés pour ce type d'organisation (CSV).
- * Exemple: "MEMBRES,COTISATIONS,TONTINE,FINANCE"
- * Utilisé pour initialiser Organisation.modulesActifs à la création.
- * Uniquement pertinent pour domaine=TYPE_ORGANISATION.
- */
- private String modulesRequis;
-}
+package dev.lions.unionflow.server.api.dto.reference.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse complète d'une donnée de référence.
+ *
+ *
+ * Inclut les champs d'audit (id, dates, version)
+ * et toutes les métadonnées UI (icône, couleur,
+ * sévérité).
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ * @since 2026-02-21
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class TypeReferenceResponse extends BaseResponse {
+
+ /** Domaine fonctionnel. */
+ private String domaine;
+
+ /** Code technique. */
+ private String code;
+
+ /** Libellé affiché. */
+ private String libelle;
+
+ /** Description longue. */
+ private String description;
+
+ /** Classe d'icône PrimeFaces. */
+ private String icone;
+
+ /** Code couleur hexadécimal. */
+ private String couleur;
+
+ /** Sévérité PrimeFaces. */
+ private String severity;
+
+ /** Ordre d'affichage. */
+ private Integer ordreAffichage;
+
+ /** Valeur par défaut du domaine. */
+ private Boolean estDefaut;
+
+ /** Protégée contre la suppression. */
+ private Boolean estSysteme;
+
+ /** UUID de l'organisation (null = global). */
+ private UUID organisationId;
+
+ /**
+ * Catégorie fonctionnelle du type d'organisation.
+ * Valeurs: ASSOCIATIF, FINANCIER_SOLIDAIRE, RELIGIEUX, PROFESSIONNEL, RESEAU_FEDERATION.
+ * Uniquement pertinent pour domaine=TYPE_ORGANISATION.
+ */
+ private String categorie;
+
+ /**
+ * Modules métier activés pour ce type d'organisation (CSV).
+ * Exemple: "MEMBRES,COTISATIONS,TONTINE,FINANCE"
+ * Utilisé pour initialiser Organisation.modulesActifs à la création.
+ * Uniquement pertinent pour domaine=TYPE_ORGANISATION.
+ */
+ private String modulesRequis;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/registre/AgrementProfessionnelDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/registre/AgrementProfessionnelDTO.java
index 90e227a..60a0af0 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/registre/AgrementProfessionnelDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/registre/AgrementProfessionnelDTO.java
@@ -1,33 +1,33 @@
-package dev.lions.unionflow.server.api.dto.registre;
-
-import dev.lions.unionflow.server.api.dto.base.BaseDTO;
-import dev.lions.unionflow.server.api.enums.registre.StatutAgrement;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-
-import java.time.LocalDate;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-@Builder
-public class AgrementProfessionnelDTO extends BaseDTO {
-
- private String membreId;
- private String organisationId;
-
- // Métier, Ordre (Médecins, Avocats, Artisans...)
- private String secteurOuOrdre;
-
- private String numeroLicenceOuRegistre;
- private String categorieClassement;
-
- private LocalDate dateDelivrance;
- private LocalDate dateExpiration;
-
- private StatutAgrement statut;
-}
+package dev.lions.unionflow.server.api.dto.registre;
+
+import dev.lions.unionflow.server.api.dto.base.BaseDTO;
+import dev.lions.unionflow.server.api.enums.registre.StatutAgrement;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDate;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
+public class AgrementProfessionnelDTO extends BaseDTO {
+
+ private String membreId;
+ private String organisationId;
+
+ // Métier, Ordre (Médecins, Avocats, Artisans...)
+ private String secteurOuOrdre;
+
+ private String numeroLicenceOuRegistre;
+ private String categorieClassement;
+
+ private LocalDate dateDelivrance;
+ private LocalDate dateExpiration;
+
+ private StatutAgrement statut;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/role/request/CreateRoleRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/role/request/CreateRoleRequest.java
index a826217..f58ec31 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/role/request/CreateRoleRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/role/request/CreateRoleRequest.java
@@ -1,20 +1,20 @@
-package dev.lions.unionflow.server.api.dto.role.request;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de création d'un rôle.
- */
-@Builder
-public record CreateRoleRequest(
- @NotBlank(message = "Le code est obligatoire") @Size(max = 50) String code,
- @NotBlank(message = "Le libellé est obligatoire") @Size(max = 100) String libelle,
- @Size(max = 500) String description,
- @NotBlank(message = "Le type de rôle est obligatoire") String typeRole,
- @NotNull(message = "Le niveau hiérarchique est obligatoire") Integer niveauHierarchique,
- UUID organisationId) {
-}
+package dev.lions.unionflow.server.api.dto.role.request;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de création d'un rôle.
+ */
+@Builder
+public record CreateRoleRequest(
+ @NotBlank(message = "Le code est obligatoire") @Size(max = 50) String code,
+ @NotBlank(message = "Le libellé est obligatoire") @Size(max = 100) String libelle,
+ @Size(max = 500) String description,
+ @NotBlank(message = "Le type de rôle est obligatoire") String typeRole,
+ @NotNull(message = "Le niveau hiérarchique est obligatoire") Integer niveauHierarchique,
+ UUID organisationId) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/role/request/UpdateRoleRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/role/request/UpdateRoleRequest.java
index e076fbb..9b6761f 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/role/request/UpdateRoleRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/role/request/UpdateRoleRequest.java
@@ -1,17 +1,17 @@
-package dev.lions.unionflow.server.api.dto.role.request;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'un rôle.
- */
-@Builder
-public record UpdateRoleRequest(
- @NotBlank(message = "Le libellé est obligatoire") @Size(max = 100) String libelle,
- @Size(max = 500) String description,
- @NotNull(message = "Le niveau hiérarchique est obligatoire") Integer niveauHierarchique,
- Boolean actif) {
-}
+package dev.lions.unionflow.server.api.dto.role.request;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'un rôle.
+ */
+@Builder
+public record UpdateRoleRequest(
+ @NotBlank(message = "Le libellé est obligatoire") @Size(max = 100) String libelle,
+ @Size(max = 500) String description,
+ @NotNull(message = "Le niveau hiérarchique est obligatoire") Integer niveauHierarchique,
+ Boolean actif) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/role/response/PermissionResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/role/response/PermissionResponse.java
index 6ead6e5..a271fcf 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/role/response/PermissionResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/role/response/PermissionResponse.java
@@ -1,28 +1,28 @@
-package dev.lions.unionflow.server.api.dto.role.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Getter;
-import lombok.Setter;
-import lombok.NoArgsConstructor;
-
-/**
- * Réponse contenant les données d'une permission.
- *
- * @author UnionFlow Team
- * @version 3.0
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class PermissionResponse extends BaseResponse {
- private String code;
- private String module;
- private String ressource;
- private String action;
- private String libelle;
- private String description;
-}
+package dev.lions.unionflow.server.api.dto.role.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.NoArgsConstructor;
+
+/**
+ * Réponse contenant les données d'une permission.
+ *
+ * @author UnionFlow Team
+ * @version 3.0
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class PermissionResponse extends BaseResponse {
+ private String code;
+ private String module;
+ private String ressource;
+ private String action;
+ private String libelle;
+ private String description;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/role/response/RoleResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/role/response/RoleResponse.java
index c504e73..3d10346 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/role/response/RoleResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/role/response/RoleResponse.java
@@ -1,29 +1,29 @@
-package dev.lions.unionflow.server.api.dto.role.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse détaillée pour un rôle.
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class RoleResponse extends BaseResponse {
-
- private String code;
- private String libelle;
- private String description;
- private String typeRole;
- private Integer niveauHierarchique;
- private UUID organisationId;
- private String nomOrganisation;
-}
+package dev.lions.unionflow.server.api.dto.role.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse détaillée pour un rôle.
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RoleResponse extends BaseResponse {
+
+ private String code;
+ private String libelle;
+ private String description;
+ private String typeRole;
+ private Integer niveauHierarchique;
+ private UUID organisationId;
+ private String nomOrganisation;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/BeneficiaireAideDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/BeneficiaireAideDTO.java
index 0d9cab5..3c37d23 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/BeneficiaireAideDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/BeneficiaireAideDTO.java
@@ -1,71 +1,71 @@
-package dev.lions.unionflow.server.api.dto.solidarite;
-
-import jakarta.validation.constraints.*;
-import java.time.LocalDate;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-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
- */
-@Data
-@NoArgsConstructor
-@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;
-}
+package dev.lions.unionflow.server.api.dto.solidarite;
+
+import jakarta.validation.constraints.*;
+import java.time.LocalDate;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+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
+ */
+@Data
+@NoArgsConstructor
+@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;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/ContactProposantDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/ContactProposantDTO.java
index 3918e43..25aab99 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/ContactProposantDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/ContactProposantDTO.java
@@ -1,77 +1,77 @@
-package dev.lions.unionflow.server.api.dto.solidarite;
-
-import jakarta.validation.constraints.*;
-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
- */
-@Data
-@NoArgsConstructor
-@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 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 languesPreferees;
-
- /** Instructions spéciales pour le contact */
- @Size(max = 300, message = "Les instructions ne peuvent pas dépasser 300 caractères")
- private String instructionsSpeciales;
-}
+package dev.lions.unionflow.server.api.dto.solidarite;
+
+import jakarta.validation.constraints.*;
+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
+ */
+@Data
+@NoArgsConstructor
+@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 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 languesPreferees;
+
+ /** Instructions spéciales pour le contact */
+ @Size(max = 300, message = "Les instructions ne peuvent pas dépasser 300 caractères")
+ private String instructionsSpeciales;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/ContactUrgenceDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/ContactUrgenceDTO.java
index 6d8e088..99bc383 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/ContactUrgenceDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/ContactUrgenceDTO.java
@@ -1,64 +1,64 @@
-package dev.lions.unionflow.server.api.dto.solidarite;
-
-import jakarta.validation.constraints.*;
-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
- */
-@Data
-@NoArgsConstructor
-@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;
-}
+package dev.lions.unionflow.server.api.dto.solidarite;
+
+import jakarta.validation.constraints.*;
+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
+ */
+@Data
+@NoArgsConstructor
+@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;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/CreneauDisponibiliteDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/CreneauDisponibiliteDTO.java
index f84ba30..467b836 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/CreneauDisponibiliteDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/CreneauDisponibiliteDTO.java
@@ -1,139 +1,139 @@
-package dev.lions.unionflow.server.api.dto.solidarite;
-
-import jakarta.validation.constraints.*;
-import java.time.DayOfWeek;
-import java.time.LocalDate;
-import java.time.LocalTime;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-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
- */
-@Data
-@NoArgsConstructor
-@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;
- }
- }
-
- // === 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();
-
- boolean recurrentAvecJour = type == TypeCreneau.RECURRENT && jourSemaine != null;
- boolean ponctuelAvecDate = type == TypeCreneau.PONCTUEL && dateSpecifique != null;
- if (recurrentAvecJour) {
- sb.append(jourSemaine.name()).append(" ");
- } else if (ponctuelAvecDate) {
- sb.append(dateSpecifique.toString()).append(" ");
- }
-
- sb.append(heureDebut.toString()).append(" - ").append(heureFin.toString());
-
- return sb.toString();
- }
-}
+package dev.lions.unionflow.server.api.dto.solidarite;
+
+import jakarta.validation.constraints.*;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+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
+ */
+@Data
+@NoArgsConstructor
+@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;
+ }
+ }
+
+ // === 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();
+
+ boolean recurrentAvecJour = type == TypeCreneau.RECURRENT && jourSemaine != null;
+ boolean ponctuelAvecDate = type == TypeCreneau.PONCTUEL && dateSpecifique != null;
+ if (recurrentAvecJour) {
+ sb.append(jourSemaine.name()).append(" ");
+ } else if (ponctuelAvecDate) {
+ sb.append(dateSpecifique.toString()).append(" ");
+ }
+
+ sb.append(heureDebut.toString()).append(" - ").append(heureFin.toString());
+
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/CritereSelectionDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/CritereSelectionDTO.java
index c8b89ac..379a4fc 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/CritereSelectionDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/CritereSelectionDTO.java
@@ -1,54 +1,54 @@
-package dev.lions.unionflow.server.api.dto.solidarite;
-
-import jakarta.validation.constraints.*;
-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
- */
-@Data
-@NoArgsConstructor
-@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;
-}
+package dev.lions.unionflow.server.api.dto.solidarite;
+
+import jakarta.validation.constraints.*;
+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
+ */
+@Data
+@NoArgsConstructor
+@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;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/HistoriqueStatutDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/HistoriqueStatutDTO.java
index 84c8dc5..cb90aa0 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/HistoriqueStatutDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/HistoriqueStatutDTO.java
@@ -1,62 +1,62 @@
-package dev.lions.unionflow.server.api.dto.solidarite;
-
-import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
-import jakarta.validation.constraints.*;
-import java.time.LocalDateTime;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-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
- */
-@Data
-@NoArgsConstructor
-@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 donneesAdditionnelles;
-}
+package dev.lions.unionflow.server.api.dto.solidarite;
+
+import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
+import jakarta.validation.constraints.*;
+import java.time.LocalDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+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
+ */
+@Data
+@NoArgsConstructor
+@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 donneesAdditionnelles;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/LocalisationDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/LocalisationDTO.java
index fb972b7..c8f9442 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/LocalisationDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/LocalisationDTO.java
@@ -1,58 +1,58 @@
-package dev.lions.unionflow.server.api.dto.solidarite;
-
-import jakarta.validation.constraints.*;
-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
- */
-@Data
-@NoArgsConstructor
-@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;
-}
+package dev.lions.unionflow.server.api.dto.solidarite;
+
+import jakarta.validation.constraints.*;
+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
+ */
+@Data
+@NoArgsConstructor
+@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;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/PieceJustificativeDTO.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/PieceJustificativeDTO.java
index 3681531..9376710 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/PieceJustificativeDTO.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/PieceJustificativeDTO.java
@@ -1,68 +1,68 @@
-package dev.lions.unionflow.server.api.dto.solidarite;
-
-import jakarta.validation.constraints.*;
-import java.time.LocalDateTime;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-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
- */
-@Data
-@NoArgsConstructor
-@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;
-}
+package dev.lions.unionflow.server.api.dto.solidarite;
+
+import jakarta.validation.constraints.*;
+import java.time.LocalDateTime;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+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
+ */
+@Data
+@NoArgsConstructor
+@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;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreateCommentaireAideRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreateCommentaireAideRequest.java
index e418a07..e1557ef 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreateCommentaireAideRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreateCommentaireAideRequest.java
@@ -1,25 +1,25 @@
-package dev.lions.unionflow.server.api.dto.solidarite.request;
-
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import java.util.List;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de création d'un commentaire sur une aide.
- */
-@Builder
-public record CreateCommentaireAideRequest(
- @NotBlank(message = "Le contenu du commentaire est obligatoire") @Size(min = 5, max = 2000, message = "Le commentaire doit contenir entre 5 et 2000 caractères") String contenu,
-
- @NotBlank(message = "Le type de commentaire est obligatoire") String typeCommentaire,
-
- @NotNull(message = "L'identifiant de l'auteur est obligatoire") UUID auteurId,
-
- Boolean estPrive,
- Boolean estImportant,
- UUID commentaireParentId,
- List mentionsUtilisateurs) {
-}
+package dev.lions.unionflow.server.api.dto.solidarite.request;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import java.util.List;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de création d'un commentaire sur une aide.
+ */
+@Builder
+public record CreateCommentaireAideRequest(
+ @NotBlank(message = "Le contenu du commentaire est obligatoire") @Size(min = 5, max = 2000, message = "Le commentaire doit contenir entre 5 et 2000 caractères") String contenu,
+
+ @NotBlank(message = "Le type de commentaire est obligatoire") String typeCommentaire,
+
+ @NotNull(message = "L'identifiant de l'auteur est obligatoire") UUID auteurId,
+
+ Boolean estPrive,
+ Boolean estImportant,
+ UUID commentaireParentId,
+ List mentionsUtilisateurs) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreateDemandeAideRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreateDemandeAideRequest.java
index ded684a..43196be 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreateDemandeAideRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreateDemandeAideRequest.java
@@ -1,46 +1,46 @@
-package dev.lions.unionflow.server.api.dto.solidarite.request;
-
-import dev.lions.unionflow.server.api.dto.solidarite.BeneficiaireAideDTO;
-import dev.lions.unionflow.server.api.dto.solidarite.ContactUrgenceDTO;
-import dev.lions.unionflow.server.api.dto.solidarite.LocalisationDTO;
-import dev.lions.unionflow.server.api.dto.solidarite.PieceJustificativeDTO;
-import dev.lions.unionflow.server.api.enums.solidarite.PrioriteAide;
-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.util.List;
-import java.util.Map;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de création d'une demande d'aide.
- */
-@Builder
-public record CreateDemandeAideRequest(
- @NotNull(message = "Le type d'aide est obligatoire.") TypeAide typeAide,
- @NotBlank(message = "Le titre" + ValidationConstants.OBLIGATOIRE_MESSAGE) @Size(max = 200) String titre,
- @NotBlank(message = "La description"
- + ValidationConstants.OBLIGATOIRE_MESSAGE) @Size(max = 2000) String description,
- @Size(max = 1000) String justification,
- @DecimalMin(value = "0", inclusive = false) @Digits(integer = 12, fraction = 2) BigDecimal montantDemande,
- @Pattern(regexp = "^[A-Z]{3}$") String devise,
- @NotNull(message = "L'identifiant du demandeur est obligatoire") UUID membreDemandeurId,
- @NotNull(message = "L'identifiant de l'organisation est obligatoire") UUID associationId,
- PrioriteAide priorite,
- List piecesJustificatives,
- List beneficiaires,
- Map donneesPersonnalisees,
- List tags,
- Boolean estConfidentielle,
- LocalisationDTO localisation,
- ContactUrgenceDTO contactUrgence,
- LocalDate dateLimite) {
-}
+package dev.lions.unionflow.server.api.dto.solidarite.request;
+
+import dev.lions.unionflow.server.api.dto.solidarite.BeneficiaireAideDTO;
+import dev.lions.unionflow.server.api.dto.solidarite.ContactUrgenceDTO;
+import dev.lions.unionflow.server.api.dto.solidarite.LocalisationDTO;
+import dev.lions.unionflow.server.api.dto.solidarite.PieceJustificativeDTO;
+import dev.lions.unionflow.server.api.enums.solidarite.PrioriteAide;
+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.util.List;
+import java.util.Map;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de création d'une demande d'aide.
+ */
+@Builder
+public record CreateDemandeAideRequest(
+ @NotNull(message = "Le type d'aide est obligatoire.") TypeAide typeAide,
+ @NotBlank(message = "Le titre" + ValidationConstants.OBLIGATOIRE_MESSAGE) @Size(max = 200) String titre,
+ @NotBlank(message = "La description"
+ + ValidationConstants.OBLIGATOIRE_MESSAGE) @Size(max = 2000) String description,
+ @Size(max = 1000) String justification,
+ @DecimalMin(value = "0", inclusive = false) @Digits(integer = 12, fraction = 2) BigDecimal montantDemande,
+ @Pattern(regexp = "^[A-Z]{3}$") String devise,
+ @NotNull(message = "L'identifiant du demandeur est obligatoire") UUID membreDemandeurId,
+ @NotNull(message = "L'identifiant de l'organisation est obligatoire") UUID associationId,
+ PrioriteAide priorite,
+ List piecesJustificatives,
+ List beneficiaires,
+ Map donneesPersonnalisees,
+ List tags,
+ Boolean estConfidentielle,
+ LocalisationDTO localisation,
+ ContactUrgenceDTO contactUrgence,
+ LocalDate dateLimite) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreateEvaluationAideRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreateEvaluationAideRequest.java
index 3e0fb5b..c34e18e 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreateEvaluationAideRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreateEvaluationAideRequest.java
@@ -1,45 +1,45 @@
-package dev.lions.unionflow.server.api.dto.solidarite.request;
-
-import dev.lions.unionflow.server.api.enums.solidarite.TypeEvaluation;
-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.util.Map;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de création d'une évaluation d'aide.
- */
-@Builder
-public record CreateEvaluationAideRequest(
- @NotNull(message = "L'identifiant de la demande d'aide est obligatoire") UUID demandeAideId,
-
- UUID propositionAideId,
-
- @NotNull(message = "L'identifiant de l'évaluateur est obligatoire") UUID evaluateurId,
-
- @NotBlank(message = "Le rôle de l'évaluateur est obligatoire") String roleEvaluateur,
-
- @NotNull(message = "Le type d'évaluation est obligatoire") TypeEvaluation typeEvaluation,
-
- @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") Double noteGlobale,
-
- Map notesDetaillees,
-
- @NotBlank(message = "Le commentaire est obligatoire") @Size(min = 10, max = 1000, message = "Le commentaire doit contenir entre 10 et 1000 caractères") String commentairePrincipal,
-
- String pointsPositifs,
- String pointsAmelioration,
- String recommandations,
- Boolean recommande,
- Boolean aideUtile,
- Boolean problemeResolu,
- Double noteDelaiReponse,
- Double noteCommunication,
- Double noteProfessionnalisme,
- Double noteRespectEngagements,
- Boolean estAnonyme) {
-}
+package dev.lions.unionflow.server.api.dto.solidarite.request;
+
+import dev.lions.unionflow.server.api.enums.solidarite.TypeEvaluation;
+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.util.Map;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de création d'une évaluation d'aide.
+ */
+@Builder
+public record CreateEvaluationAideRequest(
+ @NotNull(message = "L'identifiant de la demande d'aide est obligatoire") UUID demandeAideId,
+
+ UUID propositionAideId,
+
+ @NotNull(message = "L'identifiant de l'évaluateur est obligatoire") UUID evaluateurId,
+
+ @NotBlank(message = "Le rôle de l'évaluateur est obligatoire") String roleEvaluateur,
+
+ @NotNull(message = "Le type d'évaluation est obligatoire") TypeEvaluation typeEvaluation,
+
+ @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") Double noteGlobale,
+
+ Map notesDetaillees,
+
+ @NotBlank(message = "Le commentaire est obligatoire") @Size(min = 10, max = 1000, message = "Le commentaire doit contenir entre 10 et 1000 caractères") String commentairePrincipal,
+
+ String pointsPositifs,
+ String pointsAmelioration,
+ String recommandations,
+ Boolean recommande,
+ Boolean aideUtile,
+ Boolean problemeResolu,
+ Double noteDelaiReponse,
+ Double noteCommunication,
+ Double noteProfessionnalisme,
+ Double noteRespectEngagements,
+ Boolean estAnonyme) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreatePropositionAideRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreatePropositionAideRequest.java
index eb62239..d514dfd 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreatePropositionAideRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/CreatePropositionAideRequest.java
@@ -1,25 +1,25 @@
-package dev.lions.unionflow.server.api.dto.solidarite.request;
-
-import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-import lombok.Builder;
-
-/**
- * Requête de création d'une proposition d'aide.
- */
-@Builder
-public record CreatePropositionAideRequest(
- TypeAide typeAide,
- String titre,
- String description,
- String conditions,
- BigDecimal montantMaximum,
- Integer nombreMaxBeneficiaires,
- String devise,
- String proposantId,
- String organisationId,
- String demandeAideId,
- LocalDateTime dateExpiration,
- Integer delaiReponseHeures) {
-}
+package dev.lions.unionflow.server.api.dto.solidarite.request;
+
+import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import lombok.Builder;
+
+/**
+ * Requête de création d'une proposition d'aide.
+ */
+@Builder
+public record CreatePropositionAideRequest(
+ TypeAide typeAide,
+ String titre,
+ String description,
+ String conditions,
+ BigDecimal montantMaximum,
+ Integer nombreMaxBeneficiaires,
+ String devise,
+ String proposantId,
+ String organisationId,
+ String demandeAideId,
+ LocalDateTime dateExpiration,
+ Integer delaiReponseHeures) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdateCommentaireAideRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdateCommentaireAideRequest.java
index 6ea383f..d3da651 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdateCommentaireAideRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdateCommentaireAideRequest.java
@@ -1,18 +1,18 @@
-package dev.lions.unionflow.server.api.dto.solidarite.request;
-
-import jakarta.validation.constraints.Size;
-import java.util.UUID;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'un commentaire sur une aide.
- */
-@Builder
-public record UpdateCommentaireAideRequest(
- @Size(min = 5, max = 2000, message = "Le commentaire doit contenir entre 5 et 2000 caractères") String contenu,
-
- Boolean estPrive,
- Boolean estImportant,
- Boolean estResolu,
- UUID resoluteurId) {
-}
+package dev.lions.unionflow.server.api.dto.solidarite.request;
+
+import jakarta.validation.constraints.Size;
+import java.util.UUID;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'un commentaire sur une aide.
+ */
+@Builder
+public record UpdateCommentaireAideRequest(
+ @Size(min = 5, max = 2000, message = "Le commentaire doit contenir entre 5 et 2000 caractères") String contenu,
+
+ Boolean estPrive,
+ Boolean estImportant,
+ Boolean estResolu,
+ UUID resoluteurId) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdateDemandeAideRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdateDemandeAideRequest.java
index f80bfec..e231602 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdateDemandeAideRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdateDemandeAideRequest.java
@@ -1,44 +1,44 @@
-package dev.lions.unionflow.server.api.dto.solidarite.request;
-
-import dev.lions.unionflow.server.api.dto.solidarite.BeneficiaireAideDTO;
-import dev.lions.unionflow.server.api.dto.solidarite.ContactUrgenceDTO;
-import dev.lions.unionflow.server.api.dto.solidarite.LocalisationDTO;
-import dev.lions.unionflow.server.api.dto.solidarite.PieceJustificativeDTO;
-import dev.lions.unionflow.server.api.enums.solidarite.PrioriteAide;
-import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
-import jakarta.validation.constraints.Size;
-import java.math.BigDecimal;
-import java.time.LocalDate;
-import java.util.List;
-import java.util.Map;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'une demande d'aide.
- */
-@Builder
-public record UpdateDemandeAideRequest(
- TypeAide typeAide,
- @Size(max = 200) String titre,
- @Size(max = 2000) String description,
- @Size(max = 1000) String justification,
- BigDecimal montantDemande,
- String devise,
- PrioriteAide priorite,
- List piecesJustificatives,
- List beneficiaires,
- Map donneesPersonnalisees,
- List tags,
- Boolean estConfidentielle,
- Boolean necessiteSuivi,
- LocalisationDTO localisation,
- ContactUrgenceDTO contactUrgence,
- LocalDate dateLimite,
- dev.lions.unionflow.server.api.enums.solidarite.StatutAide statut,
- BigDecimal montantApprouve,
- String commentairesEvaluateur,
- String documentsJoints,
- java.time.LocalDateTime dateSoumission,
- java.time.LocalDateTime dateEvaluation,
- java.time.LocalDateTime dateVersement) {
-}
+package dev.lions.unionflow.server.api.dto.solidarite.request;
+
+import dev.lions.unionflow.server.api.dto.solidarite.BeneficiaireAideDTO;
+import dev.lions.unionflow.server.api.dto.solidarite.ContactUrgenceDTO;
+import dev.lions.unionflow.server.api.dto.solidarite.LocalisationDTO;
+import dev.lions.unionflow.server.api.dto.solidarite.PieceJustificativeDTO;
+import dev.lions.unionflow.server.api.enums.solidarite.PrioriteAide;
+import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
+import jakarta.validation.constraints.Size;
+import java.math.BigDecimal;
+import java.time.LocalDate;
+import java.util.List;
+import java.util.Map;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'une demande d'aide.
+ */
+@Builder
+public record UpdateDemandeAideRequest(
+ TypeAide typeAide,
+ @Size(max = 200) String titre,
+ @Size(max = 2000) String description,
+ @Size(max = 1000) String justification,
+ BigDecimal montantDemande,
+ String devise,
+ PrioriteAide priorite,
+ List piecesJustificatives,
+ List beneficiaires,
+ Map donneesPersonnalisees,
+ List tags,
+ Boolean estConfidentielle,
+ Boolean necessiteSuivi,
+ LocalisationDTO localisation,
+ ContactUrgenceDTO contactUrgence,
+ LocalDate dateLimite,
+ dev.lions.unionflow.server.api.enums.solidarite.StatutAide statut,
+ BigDecimal montantApprouve,
+ String commentairesEvaluateur,
+ String documentsJoints,
+ java.time.LocalDateTime dateSoumission,
+ java.time.LocalDateTime dateEvaluation,
+ java.time.LocalDateTime dateVersement) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdateEvaluationAideRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdateEvaluationAideRequest.java
index ffb71db..c4245fb 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdateEvaluationAideRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdateEvaluationAideRequest.java
@@ -1,34 +1,34 @@
-package dev.lions.unionflow.server.api.dto.solidarite.request;
-
-import dev.lions.unionflow.server.api.enums.solidarite.StatutEvaluation;
-import jakarta.validation.constraints.DecimalMax;
-import jakarta.validation.constraints.DecimalMin;
-import jakarta.validation.constraints.Size;
-import java.util.Map;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'une évaluation d'aide.
- */
-@Builder
-public record UpdateEvaluationAideRequest(
- @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") Double noteGlobale,
-
- Map notesDetaillees,
-
- @Size(min = 10, max = 1000, message = "Le commentaire doit contenir entre 10 et 1000 caractères") String commentairePrincipal,
-
- String pointsPositifs,
- String pointsAmelioration,
- String recommandations,
- Boolean recommande,
- Boolean aideUtile,
- Boolean problemeResolu,
- Double noteDelaiReponse,
- Double noteCommunication,
- Double noteProfessionnalisme,
- Double noteRespectEngagements,
- Boolean estPublique,
- Boolean estAnonyme,
- StatutEvaluation statut) {
-}
+package dev.lions.unionflow.server.api.dto.solidarite.request;
+
+import dev.lions.unionflow.server.api.enums.solidarite.StatutEvaluation;
+import jakarta.validation.constraints.DecimalMax;
+import jakarta.validation.constraints.DecimalMin;
+import jakarta.validation.constraints.Size;
+import java.util.Map;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'une évaluation d'aide.
+ */
+@Builder
+public record UpdateEvaluationAideRequest(
+ @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") Double noteGlobale,
+
+ Map notesDetaillees,
+
+ @Size(min = 10, max = 1000, message = "Le commentaire doit contenir entre 10 et 1000 caractères") String commentairePrincipal,
+
+ String pointsPositifs,
+ String pointsAmelioration,
+ String recommandations,
+ Boolean recommande,
+ Boolean aideUtile,
+ Boolean problemeResolu,
+ Double noteDelaiReponse,
+ Double noteCommunication,
+ Double noteProfessionnalisme,
+ Double noteRespectEngagements,
+ Boolean estPublique,
+ Boolean estAnonyme,
+ StatutEvaluation statut) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdatePropositionAideRequest.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdatePropositionAideRequest.java
index e69c8cf..1885db3 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdatePropositionAideRequest.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/request/UpdatePropositionAideRequest.java
@@ -1,27 +1,27 @@
-package dev.lions.unionflow.server.api.dto.solidarite.request;
-
-import dev.lions.unionflow.server.api.enums.solidarite.StatutProposition;
-import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
-import lombok.Builder;
-
-/**
- * Requête de mise à jour d'une proposition d'aide.
- */
-@Builder
-public record UpdatePropositionAideRequest(
- TypeAide typeAide,
- String titre,
- String description,
- String conditions,
- BigDecimal montantMaximum,
- Integer nombreMaxBeneficiaires,
- String devise,
- StatutProposition statut,
- Boolean estDisponible,
- Boolean estRecurrente,
- String frequenceRecurrence,
- LocalDateTime dateExpiration,
- Integer delaiReponseHeures) {
-}
+package dev.lions.unionflow.server.api.dto.solidarite.request;
+
+import dev.lions.unionflow.server.api.enums.solidarite.StatutProposition;
+import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import lombok.Builder;
+
+/**
+ * Requête de mise à jour d'une proposition d'aide.
+ */
+@Builder
+public record UpdatePropositionAideRequest(
+ TypeAide typeAide,
+ String titre,
+ String description,
+ String conditions,
+ BigDecimal montantMaximum,
+ Integer nombreMaxBeneficiaires,
+ String devise,
+ StatutProposition statut,
+ Boolean estDisponible,
+ Boolean estRecurrente,
+ String frequenceRecurrence,
+ LocalDateTime dateExpiration,
+ Integer delaiReponseHeures) {
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/response/CommentaireAideResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/response/CommentaireAideResponse.java
index fa9de5c..5c114cd 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/response/CommentaireAideResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/response/CommentaireAideResponse.java
@@ -1,41 +1,41 @@
-package dev.lions.unionflow.server.api.dto.solidarite.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import dev.lions.unionflow.server.api.dto.solidarite.PieceJustificativeDTO;
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse pour un commentaire sur une aide.
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class CommentaireAideResponse extends BaseResponse {
-
- private String contenu;
- private String typeCommentaire;
- private UUID auteurId;
- private String auteurNom;
- private String auteurRole;
- private Boolean estPrive;
- private Boolean estImportant;
- private UUID commentaireParentId;
- private List reponses;
- private List piecesJointes;
- private List mentionsUtilisateurs;
- private Boolean estModifie;
- private Integer nombreReactions;
- private Boolean estResolu;
- private LocalDateTime dateResolution;
- private UUID resoluteurId;
-}
+package dev.lions.unionflow.server.api.dto.solidarite.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import dev.lions.unionflow.server.api.dto.solidarite.PieceJustificativeDTO;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse pour un commentaire sur une aide.
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class CommentaireAideResponse extends BaseResponse {
+
+ private String contenu;
+ private String typeCommentaire;
+ private UUID auteurId;
+ private String auteurNom;
+ private String auteurRole;
+ private Boolean estPrive;
+ private Boolean estImportant;
+ private UUID commentaireParentId;
+ private List reponses;
+ private List piecesJointes;
+ private List mentionsUtilisateurs;
+ private Boolean estModifie;
+ private Integer nombreReactions;
+ private Boolean estResolu;
+ private LocalDateTime dateResolution;
+ private UUID resoluteurId;
+}
diff --git a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/response/DemandeAideResponse.java b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/response/DemandeAideResponse.java
index 9605c36..a53b271 100644
--- a/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/response/DemandeAideResponse.java
+++ b/src/main/java/dev/lions/unionflow/server/api/dto/solidarite/response/DemandeAideResponse.java
@@ -1,171 +1,171 @@
-package dev.lions.unionflow.server.api.dto.solidarite.response;
-
-import dev.lions.unionflow.server.api.dto.base.BaseResponse;
-import dev.lions.unionflow.server.api.dto.solidarite.BeneficiaireAideDTO;
-import dev.lions.unionflow.server.api.dto.solidarite.response.CommentaireAideResponse;
-import dev.lions.unionflow.server.api.dto.solidarite.ContactUrgenceDTO;
-import dev.lions.unionflow.server.api.dto.solidarite.HistoriqueStatutDTO;
-import dev.lions.unionflow.server.api.dto.solidarite.LocalisationDTO;
-import dev.lions.unionflow.server.api.dto.solidarite.PieceJustificativeDTO;
-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.LocalDate;
-import java.time.LocalDateTime;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.EqualsAndHashCode;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-
-/**
- * Réponse détaillée pour une demande d'aide.
- */
-@Getter
-@Setter
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class DemandeAideResponse extends BaseResponse {
-
- private String numeroReference;
- private TypeAide typeAide;
- private String titre;
- private String description;
- private String justification;
-
- private BigDecimal montantDemande;
- private BigDecimal montantApprouve;
- private BigDecimal montantVerse;
- private String devise;
-
- private UUID membreDemandeurId;
- private String nomDemandeur;
- private String numeroMembreDemandeur;
-
- private String evaluateurId;
- private String evaluateurNom;
- private String approvateurId;
- private String approvateurNom;
-
- private UUID associationId;
- private String nomAssociation;
-
- private StatutAide statut;
- private PrioriteAide priorite;
-
- private String motifRejet;
- private String commentairesEvaluateur;
-
- private LocalDateTime dateSoumission;
- private LocalDateTime dateLimiteTraitement;
- private LocalDateTime dateEvaluation;
- private LocalDateTime dateApprobation;
- private LocalDateTime dateVersement;
- private LocalDateTime dateCloture;
-
- private List piecesJustificatives;
- private List beneficiaires;
- private List historiqueStatuts;
- private List commentaires;
- private Map donneesPersonnalisees;
- private List tags;
-
- private Boolean estConfidentielle;
- private Boolean necessiteSuivi;
- private Double scorePriorite;
- private Integer nombreVues;
-
- private LocalisationDTO localisation;
- private ContactUrgenceDTO contactUrgence;
-
- private LocalDate dateLimite;
- private Boolean justificatifsFournis;
- private String documentsJoints;
- private LocalDate dateDebutAide;
- private LocalDate dateFinAide;
-
- private UUID membreAidantId;
- private String nomAidant;
- private String modeVersement;
- private String numeroTransaction;
-
- private UUID rejeteParId;
- private String rejetePar;
- private LocalDateTime dateRejet;
- private String raisonRejet;
-
- // === MÉTHODES UTILITAIRES ===
-
- public boolean estModifiable() {
- return statut != null && statut.permetModification();
- }
-
- public boolean peutEtreAnnulee() {
- return statut != null && statut.permetAnnulation();
- }
-
- public boolean estUrgente() {
- return priorite != null && priorite.isUrgente();
- }
-
- public boolean estTerminee() {
- return statut != null && statut.isEstFinal();
- }
-
- public boolean estEnSucces() {
- return statut != null && statut.isSucces();
- }
-
- 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;
- };
- }
-
- 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();
- }
-
- public boolean estDelaiDepasse() {
- return getDelaiRestantHeures() == 0;
- }
-
- public String getStatutLibelle() {
- return statut != null ? statut.getLibelle() : "Non défini";
- }
-
- public String getPrioriteLibelle() {
- return priorite != null ? priorite.getLibelle() : "Normale";
- }
-}
+package dev.lions.unionflow.server.api.dto.solidarite.response;
+
+import dev.lions.unionflow.server.api.dto.base.BaseResponse;
+import dev.lions.unionflow.server.api.dto.solidarite.BeneficiaireAideDTO;
+import dev.lions.unionflow.server.api.dto.solidarite.response.CommentaireAideResponse;
+import dev.lions.unionflow.server.api.dto.solidarite.ContactUrgenceDTO;
+import dev.lions.unionflow.server.api.dto.solidarite.HistoriqueStatutDTO;
+import dev.lions.unionflow.server.api.dto.solidarite.LocalisationDTO;
+import dev.lions.unionflow.server.api.dto.solidarite.PieceJustificativeDTO;
+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.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Réponse détaillée pour une demande d'aide.
+ */
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DemandeAideResponse extends BaseResponse {
+
+ private String numeroReference;
+ private TypeAide typeAide;
+ private String titre;
+ private String description;
+ private String justification;
+
+ private BigDecimal montantDemande;
+ private BigDecimal montantApprouve;
+ private BigDecimal montantVerse;
+ private String devise;
+
+ private UUID membreDemandeurId;
+ private String nomDemandeur;
+ private String numeroMembreDemandeur;
+
+ private String evaluateurId;
+ private String evaluateurNom;
+ private String approvateurId;
+ private String approvateurNom;
+
+ private UUID associationId;
+ private String nomAssociation;
+
+ private StatutAide statut;
+ private PrioriteAide priorite;
+
+ private String motifRejet;
+ private String commentairesEvaluateur;
+
+ private LocalDateTime dateSoumission;
+ private LocalDateTime dateLimiteTraitement;
+ private LocalDateTime dateEvaluation;
+ private LocalDateTime dateApprobation;
+ private LocalDateTime dateVersement;
+ private LocalDateTime dateCloture;
+
+ private List