diff --git a/unionflow-server-impl-quarkus/pom.xml b/unionflow-server-impl-quarkus/pom.xml
index 8aa2be9..c5a8076 100644
--- a/unionflow-server-impl-quarkus/pom.xml
+++ b/unionflow-server-impl-quarkus/pom.xml
@@ -177,6 +177,13 @@
17
17
UTF-8
+
+
+ org.projectlombok
+ lombok
+ 1.18.30
+
+
diff --git a/unionflow-server-impl-quarkus/src/main/java/de/lions/unionflow/server/auth/AuthCallbackResource.java b/unionflow-server-impl-quarkus/src/main/java/de/lions/unionflow/server/auth/AuthCallbackResource.java
index 6227f47..e77af23 100644
--- a/unionflow-server-impl-quarkus/src/main/java/de/lions/unionflow/server/auth/AuthCallbackResource.java
+++ b/unionflow-server-impl-quarkus/src/main/java/de/lions/unionflow/server/auth/AuthCallbackResource.java
@@ -4,6 +4,7 @@ import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Response;
+import org.jboss.logging.Logger;
/**
* Resource temporaire pour gérer les callbacks d'authentification OAuth2/OIDC depuis l'application
@@ -12,6 +13,8 @@ import jakarta.ws.rs.core.Response;
@Path("/auth")
public class AuthCallbackResource {
+ private static final Logger log = Logger.getLogger(AuthCallbackResource.class);
+
/**
* Endpoint de callback pour l'authentification OAuth2/OIDC. Redirige vers l'application mobile
* avec les paramètres reçus.
@@ -27,12 +30,8 @@ public class AuthCallbackResource {
try {
// Log des paramètres reçus pour debug
- System.out.println("=== CALLBACK DEBUG ===");
- System.out.println("Code: " + code);
- System.out.println("State: " + state);
- System.out.println("Session State: " + sessionState);
- System.out.println("Error: " + error);
- System.out.println("Error Description: " + errorDescription);
+ log.infof("=== CALLBACK DEBUG === Code: %s, State: %s, Session State: %s, Error: %s, Error Description: %s",
+ code, state, sessionState, error, errorDescription);
// URL de redirection simple vers l'application mobile
String redirectUrl = "dev.lions.unionflow-mobile://callback";
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/dto/EvenementMobileDTO.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/dto/EvenementMobileDTO.java
index 2a5147b..26b4157 100644
--- a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/dto/EvenementMobileDTO.java
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/dto/EvenementMobileDTO.java
@@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import dev.lions.unionflow.server.entity.Evenement;
import java.math.BigDecimal;
import java.time.LocalDateTime;
+import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -14,8 +15,8 @@ import lombok.NoArgsConstructor;
* l'application mobile Flutter
*
* @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-15
+ * @version 2.0
+ * @since 2025-01-16
*/
@Data
@NoArgsConstructor
@@ -24,7 +25,7 @@ import lombok.NoArgsConstructor;
@JsonIgnoreProperties(ignoreUnknown = true)
public class EvenementMobileDTO {
- private Long id;
+ private UUID id;
private String titre;
private String description;
private LocalDateTime dateDebut;
@@ -47,9 +48,9 @@ public class EvenementMobileDTO {
private Integer participantsActuels;
// IDs et noms pour les relations
- private Long organisateurId;
+ private UUID organisateurId;
private String organisateurNom;
- private Long organisationId;
+ private UUID organisationId;
private String organisationNom;
// Priorité (à ajouter dans l'entité si nécessaire)
@@ -96,7 +97,7 @@ public class EvenementMobileDTO {
}
return EvenementMobileDTO.builder()
- .id(evenement.id) // PanacheEntity utilise un champ public id
+ .id(evenement.getId()) // Utilise getId() depuis BaseEntity
.titre(evenement.getTitre())
.description(evenement.getDescription())
.dateDebut(evenement.getDateDebut())
@@ -110,12 +111,12 @@ public class EvenementMobileDTO {
.statut(evenement.getStatut() != null ? evenement.getStatut().name() : "PLANIFIE")
// Mapping des champs renommés
.maxParticipants(evenement.getCapaciteMax())
- .participantsActuels(0) // TODO: Calculer depuis les inscriptions si nécessaire
+ .participantsActuels(evenement.getNombreInscrits())
// Relations (gestion sécurisée des lazy loading)
- .organisateurId(null) // TODO: Charger si nécessaire
- .organisateurNom(null) // TODO: Charger si nécessaire
- .organisationId(null) // TODO: Charger si nécessaire
- .organisationNom(null) // TODO: Charger si nécessaire
+ .organisateurId(evenement.getOrganisateur() != null ? evenement.getOrganisateur().getId() : null)
+ .organisateurNom(evenement.getOrganisateur() != null ? evenement.getOrganisateur().getNomComplet() : null)
+ .organisationId(evenement.getOrganisation() != null ? evenement.getOrganisation().getId() : null)
+ .organisationNom(evenement.getOrganisation() != null ? evenement.getOrganisation().getNom() : null)
// Priorité (valeur par défaut)
.priorite("MOYENNE")
// Mapping booléens
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/BaseEntity.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/BaseEntity.java
new file mode 100644
index 0000000..5a1ef42
--- /dev/null
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/BaseEntity.java
@@ -0,0 +1,141 @@
+package dev.lions.unionflow.server.entity;
+
+import jakarta.persistence.*;
+import java.time.LocalDateTime;
+import java.util.UUID;
+
+/**
+ * Classe de base pour les entités UnionFlow utilisant UUID comme identifiant
+ *
+ *
Remplace PanacheEntity pour utiliser UUID au lieu de Long comme ID.
+ * Fournit les fonctionnalités de base de Panache avec UUID.
+ *
+ * @author UnionFlow Team
+ * @version 2.0
+ * @since 2025-01-16
+ */
+@MappedSuperclass
+public abstract class BaseEntity {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.UUID)
+ @Column(name = "id", updatable = false, nullable = false)
+ private UUID id;
+
+ @Column(name = "date_creation", nullable = false, updatable = false)
+ protected LocalDateTime dateCreation;
+
+ @Column(name = "date_modification")
+ protected LocalDateTime dateModification;
+
+ @Column(name = "cree_par", length = 255)
+ protected String creePar;
+
+ @Column(name = "modifie_par", length = 255)
+ protected String modifiePar;
+
+ @Version
+ @Column(name = "version")
+ protected Long version;
+
+ @Column(name = "actif", nullable = false)
+ protected Boolean actif = true;
+
+ // Constructeur par défaut
+ public BaseEntity() {
+ this.dateCreation = LocalDateTime.now();
+ this.actif = true;
+ this.version = 0L;
+ }
+
+ // Getters et Setters
+ public UUID getId() {
+ return id;
+ }
+
+ public void setId(UUID id) {
+ this.id = id;
+ }
+
+ public LocalDateTime getDateCreation() {
+ return dateCreation;
+ }
+
+ public void setDateCreation(LocalDateTime dateCreation) {
+ this.dateCreation = dateCreation;
+ }
+
+ public LocalDateTime getDateModification() {
+ return dateModification;
+ }
+
+ public void setDateModification(LocalDateTime dateModification) {
+ this.dateModification = dateModification;
+ }
+
+ public String getCreePar() {
+ return creePar;
+ }
+
+ public void setCreePar(String creePar) {
+ this.creePar = creePar;
+ }
+
+ public String getModifiePar() {
+ return modifiePar;
+ }
+
+ public void setModifiePar(String modifiePar) {
+ this.modifiePar = modifiePar;
+ }
+
+ public Long getVersion() {
+ return version;
+ }
+
+ public void setVersion(Long version) {
+ this.version = version;
+ }
+
+ public Boolean getActif() {
+ return actif;
+ }
+
+ public void setActif(Boolean actif) {
+ this.actif = actif;
+ }
+
+ // Callbacks JPA
+ @PrePersist
+ protected void onCreate() {
+ if (this.dateCreation == null) {
+ this.dateCreation = LocalDateTime.now();
+ }
+ if (this.actif == null) {
+ this.actif = true;
+ }
+ if (this.version == null) {
+ this.version = 0L;
+ }
+ }
+
+ @PreUpdate
+ protected void onUpdate() {
+ this.dateModification = LocalDateTime.now();
+ }
+
+ // Méthodes utilitaires Panache-like
+ public void persist() {
+ // Cette méthode sera implémentée par les repositories ou services
+ // Pour l'instant, elle est là pour compatibilité avec le code existant
+ throw new UnsupportedOperationException(
+ "Utilisez le repository approprié pour persister cette entité");
+ }
+
+ public static T findById(UUID id) {
+ // Cette méthode sera implémentée par les repositories
+ throw new UnsupportedOperationException(
+ "Utilisez le repository approprié pour rechercher par ID");
+ }
+}
+
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Cotisation.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Cotisation.java
index fb79272..a157083 100644
--- a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Cotisation.java
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Cotisation.java
@@ -1,11 +1,11 @@
package dev.lions.unionflow.server.entity;
-import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@@ -13,11 +13,11 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
- * Entité Cotisation avec Lombok Représente une cotisation d'un membre à son organisation
+ * Entité Cotisation avec UUID Représente une cotisation d'un membre à son organisation
*
* @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-15
+ * @version 2.0
+ * @since 2025-01-16
*/
@Entity
@Table(
@@ -34,8 +34,8 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Builder
-@EqualsAndHashCode(callSuper = false)
-public class Cotisation extends PanacheEntity {
+@EqualsAndHashCode(callSuper = true)
+public class Cotisation extends BaseEntity {
@NotBlank
@Column(name = "numero_reference", unique = true, nullable = false, length = 50)
@@ -115,7 +115,7 @@ public class Cotisation extends PanacheEntity {
private LocalDateTime dateDernierRappel;
@Column(name = "valide_par_id")
- private Long valideParId;
+ private UUID valideParId;
@Size(max = 100)
@Column(name = "nom_validateur", length = 100)
@@ -132,13 +132,6 @@ public class Cotisation extends PanacheEntity {
@Column(name = "reference_paiement", length = 100)
private String referencePaiement;
- @Builder.Default
- @Column(name = "date_creation", nullable = false)
- private LocalDateTime dateCreation = LocalDateTime.now();
-
- @Column(name = "date_modification")
- private LocalDateTime dateModification;
-
/** Méthode métier pour calculer le montant restant à payer */
public BigDecimal getMontantRestant() {
if (montantDu == null || montantPaye == null) {
@@ -168,12 +161,10 @@ public class Cotisation extends PanacheEntity {
/** Callback JPA avant la persistance */
@PrePersist
protected void onCreate() {
+ super.onCreate(); // Appelle le onCreate de BaseEntity
if (numeroReference == null || numeroReference.isEmpty()) {
numeroReference = genererNumeroReference();
}
- if (dateCreation == null) {
- dateCreation = LocalDateTime.now();
- }
if (codeDevise == null) {
codeDevise = "XOF";
}
@@ -190,10 +181,4 @@ public class Cotisation extends PanacheEntity {
recurrente = false;
}
}
-
- /** Callback JPA avant la mise à jour */
- @PreUpdate
- protected void onUpdate() {
- dateModification = LocalDateTime.now();
- }
}
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/DemandeAide.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/DemandeAide.java
index 75ed3ce..5e6994c 100644
--- a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/DemandeAide.java
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/DemandeAide.java
@@ -2,7 +2,6 @@ package dev.lions.unionflow.server.entity;
import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
-import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
@@ -20,8 +19,8 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Builder
-@EqualsAndHashCode(callSuper = false)
-public class DemandeAide extends PanacheEntity {
+@EqualsAndHashCode(callSuper = true)
+public class DemandeAide extends BaseEntity {
@Column(name = "titre", nullable = false, length = 200)
private String titre;
@@ -79,6 +78,7 @@ public class DemandeAide extends PanacheEntity {
@PrePersist
protected void onCreate() {
+ super.onCreate(); // Appelle le onCreate de BaseEntity
if (dateDemande == null) {
dateDemande = LocalDateTime.now();
}
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Evenement.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Evenement.java
index ffa7b58..b8d1d10 100644
--- a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Evenement.java
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Evenement.java
@@ -1,22 +1,20 @@
package dev.lions.unionflow.server.entity;
-import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
+import java.util.UUID;
import lombok.*;
-import org.hibernate.annotations.CreationTimestamp;
-import org.hibernate.annotations.UpdateTimestamp;
/**
* Entité Événement pour la gestion des événements de l'union
*
* @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-15
+ * @version 2.0
+ * @since 2025-01-16
*/
@Entity
@Table(
@@ -31,8 +29,8 @@ import org.hibernate.annotations.UpdateTimestamp;
@NoArgsConstructor
@AllArgsConstructor
@Builder
-@EqualsAndHashCode(callSuper = false)
-public class Evenement extends PanacheEntity {
+@EqualsAndHashCode(callSuper = true)
+public class Evenement extends BaseEntity {
@NotBlank
@Size(min = 3, max = 200)
@@ -120,21 +118,6 @@ public class Evenement extends PanacheEntity {
@Builder.Default
private List inscriptions = new ArrayList<>();
- // Métadonnées
- @CreationTimestamp
- @Column(name = "date_creation", nullable = false, updatable = false)
- private LocalDateTime dateCreation;
-
- @UpdateTimestamp
- @Column(name = "date_modification")
- private LocalDateTime dateModification;
-
- @Column(name = "cree_par", length = 100)
- private String creePar;
-
- @Column(name = "modifie_par", length = 100)
- private String modifiePar;
-
/** Types d'événements */
public enum TypeEvenement {
ASSEMBLEE_GENERALE("Assemblée Générale"),
@@ -259,12 +242,12 @@ public class Evenement extends PanacheEntity {
}
/** Vérifie si un membre est inscrit à l'événement */
- public boolean isMemberInscrit(Long membreId) {
+ public boolean isMemberInscrit(UUID membreId) {
return inscriptions != null
&& inscriptions.stream()
.anyMatch(
inscription ->
- inscription.getMembre().id.equals(membreId)
+ inscription.getMembre().getId().equals(membreId)
&& inscription.getStatut()
== InscriptionEvenement.StatutInscription.CONFIRMEE);
}
@@ -277,16 +260,4 @@ public class Evenement extends PanacheEntity {
return (double) getNombreInscrits() / capaciteMax * 100;
}
-
- @PrePersist
- public void prePersist() {
- if (dateCreation == null) {
- dateCreation = LocalDateTime.now();
- }
- }
-
- @PreUpdate
- public void preUpdate() {
- dateModification = LocalDateTime.now();
- }
}
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/InscriptionEvenement.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/InscriptionEvenement.java
index acbde28..0cec9c7 100644
--- a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/InscriptionEvenement.java
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/InscriptionEvenement.java
@@ -1,6 +1,5 @@
package dev.lions.unionflow.server.entity;
-import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
@@ -10,8 +9,8 @@ import lombok.*;
* Entité InscriptionEvenement représentant l'inscription d'un membre à un événement
*
* @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-15
+ * @version 2.0
+ * @since 2025-01-16
*/
@Entity
@Table(
@@ -25,8 +24,8 @@ import lombok.*;
@NoArgsConstructor
@AllArgsConstructor
@Builder
-@EqualsAndHashCode(callSuper = false)
-public class InscriptionEvenement extends PanacheEntity {
+@EqualsAndHashCode(callSuper = true)
+public class InscriptionEvenement extends BaseEntity {
@NotNull
@ManyToOne(fetch = FetchType.LAZY)
@@ -50,13 +49,6 @@ public class InscriptionEvenement extends PanacheEntity {
@Column(name = "commentaire", length = 500)
private String commentaire;
- @Builder.Default
- @Column(name = "date_creation", nullable = false)
- private LocalDateTime dateCreation = LocalDateTime.now();
-
- @Column(name = "date_modification")
- private LocalDateTime dateModification;
-
/** Énumération des statuts d'inscription */
public enum StatutInscription {
CONFIRMEE("Confirmée"),
@@ -147,14 +139,15 @@ public class InscriptionEvenement extends PanacheEntity {
@PreUpdate
public void preUpdate() {
+ super.onUpdate(); // Appelle le onUpdate de BaseEntity
this.dateModification = LocalDateTime.now();
}
@Override
public String toString() {
return String.format(
- "InscriptionEvenement{id=%d, membre=%s, evenement=%s, statut=%s, dateInscription=%s}",
- id,
+ "InscriptionEvenement{id=%s, membre=%s, evenement=%s, statut=%s, dateInscription=%s}",
+ getId(),
membre != null ? membre.getEmail() : "null",
evenement != null ? evenement.getTitre() : "null",
statut,
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Membre.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Membre.java
index 501de4d..12c46cd 100644
--- a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Membre.java
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Membre.java
@@ -1,19 +1,18 @@
package dev.lions.unionflow.server.entity;
-import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.*;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;
-import java.time.LocalDateTime;
+import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
-/** Entité Membre avec Lombok */
+/** Entité Membre avec UUID */
@Entity
@Table(
name = "membres",
@@ -26,8 +25,8 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Builder
-@EqualsAndHashCode(callSuper = false)
-public class Membre extends PanacheEntity {
+@EqualsAndHashCode(callSuper = true)
+public class Membre extends BaseEntity {
@NotBlank
@Column(name = "numero_membre", unique = true, nullable = false, length = 20)
@@ -63,17 +62,6 @@ public class Membre extends PanacheEntity {
@Column(name = "roles", length = 500)
private String roles;
- @Builder.Default
- @Column(name = "actif", nullable = false)
- private Boolean actif = true;
-
- @Builder.Default
- @Column(name = "date_creation", nullable = false)
- private LocalDateTime dateCreation = LocalDateTime.now();
-
- @Column(name = "date_modification")
- private LocalDateTime dateModification;
-
// Relations
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "organisation_id")
@@ -93,9 +81,4 @@ public class Membre extends PanacheEntity {
public int getAge() {
return LocalDate.now().getYear() - dateNaissance.getYear();
}
-
- @PreUpdate
- public void preUpdate() {
- this.dateModification = LocalDateTime.now();
- }
}
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Organisation.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Organisation.java
index fb55269..a230f11 100644
--- a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Organisation.java
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/entity/Organisation.java
@@ -1,6 +1,5 @@
package dev.lions.unionflow.server.entity;
-import io.quarkus.hibernate.orm.panache.PanacheEntity;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
import java.math.BigDecimal;
@@ -17,12 +16,12 @@ import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
- * Entité Organisation avec Lombok Représente une organisation (Lions Club, Association,
+ * Entité Organisation avec UUID Représente une organisation (Lions Club, Association,
* Coopérative, etc.)
*
* @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-15
+ * @version 2.0
+ * @since 2025-01-16
*/
@Entity
@Table(
@@ -44,8 +43,8 @@ import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
@Builder
-@EqualsAndHashCode(callSuper = false)
-public class Organisation extends PanacheEntity {
+@EqualsAndHashCode(callSuper = true)
+public class Organisation extends BaseEntity {
@NotBlank
@Column(name = "nom", nullable = false, length = 200)
@@ -187,28 +186,6 @@ public class Organisation extends PanacheEntity {
@Column(name = "accepte_nouveaux_membres", nullable = false)
private Boolean accepteNouveauxMembres = true;
- // Métadonnées
- @Builder.Default
- @Column(name = "actif", nullable = false)
- private Boolean actif = true;
-
- @Builder.Default
- @Column(name = "date_creation", nullable = false)
- private LocalDateTime dateCreation = LocalDateTime.now();
-
- @Column(name = "date_modification")
- private LocalDateTime dateModification;
-
- @Column(name = "cree_par", length = 100)
- private String creePar;
-
- @Column(name = "modifie_par", length = 100)
- private String modifiePar;
-
- @Builder.Default
- @Column(name = "version", nullable = false)
- private Long version = 0L;
-
// Relations
@OneToMany(mappedBy = "organisation", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@Builder.Default
@@ -237,7 +214,7 @@ public class Organisation extends PanacheEntity {
/** Méthode métier pour vérifier si l'organisation est active */
public boolean isActive() {
- return "ACTIVE".equals(statut) && actif;
+ return "ACTIVE".equals(statut) && Boolean.TRUE.equals(getActif());
}
/** Méthode métier pour ajouter un membre */
@@ -258,7 +235,7 @@ public class Organisation extends PanacheEntity {
/** Méthode métier pour activer l'organisation */
public void activer(String utilisateur) {
this.statut = "ACTIVE";
- this.actif = true;
+ this.setActif(true);
marquerCommeModifie(utilisateur);
}
@@ -272,24 +249,26 @@ public class Organisation extends PanacheEntity {
/** Méthode métier pour dissoudre l'organisation */
public void dissoudre(String utilisateur) {
this.statut = "DISSOUTE";
- this.actif = false;
+ this.setActif(false);
this.accepteNouveauxMembres = false;
marquerCommeModifie(utilisateur);
}
/** Marque l'entité comme modifiée */
public void marquerCommeModifie(String utilisateur) {
- this.dateModification = LocalDateTime.now();
- this.modifiePar = utilisateur;
- this.version++;
+ this.setDateModification(LocalDateTime.now());
+ this.setModifiePar(utilisateur);
+ if (this.getVersion() != null) {
+ this.setVersion(this.getVersion() + 1);
+ } else {
+ this.setVersion(1L);
+ }
}
/** Callback JPA avant la persistance */
@PrePersist
protected void onCreate() {
- if (dateCreation == null) {
- dateCreation = LocalDateTime.now();
- }
+ super.onCreate(); // Appelle le onCreate de BaseEntity
if (statut == null) {
statut = "ACTIVE";
}
@@ -317,17 +296,5 @@ public class Organisation extends PanacheEntity {
if (cotisationObligatoire == null) {
cotisationObligatoire = false;
}
- if (actif == null) {
- actif = true;
- }
- if (version == null) {
- version = 0L;
- }
- }
-
- /** Callback JPA avant la mise à jour */
- @PreUpdate
- protected void onUpdate() {
- dateModification = LocalDateTime.now();
}
}
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/BaseRepository.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/BaseRepository.java
new file mode 100644
index 0000000..18a34b5
--- /dev/null
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/BaseRepository.java
@@ -0,0 +1,140 @@
+package dev.lions.unionflow.server.repository;
+
+import dev.lions.unionflow.server.entity.BaseEntity;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.transaction.Transactional;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+/**
+ * Repository de base pour les entités utilisant UUID comme identifiant
+ *
+ * Remplace PanacheRepository pour utiliser UUID au lieu de Long.
+ * Fournit les fonctionnalités de base de Panache avec UUID.
+ *
+ * @param Le type d'entité qui étend BaseEntity
+ * @author UnionFlow Team
+ * @version 2.0
+ * @since 2025-01-16
+ */
+public abstract class BaseRepository {
+
+ @PersistenceContext
+ protected EntityManager entityManager;
+
+ protected final Class entityClass;
+
+ protected BaseRepository(Class entityClass) {
+ this.entityClass = entityClass;
+ }
+
+ /**
+ * Trouve une entité par son UUID
+ *
+ * @param id L'UUID de l'entité
+ * @return L'entité trouvée ou null
+ */
+ public T findById(UUID id) {
+ return entityManager.find(entityClass, id);
+ }
+
+ /**
+ * Trouve une entité par son UUID (retourne Optional)
+ *
+ * @param id L'UUID de l'entité
+ * @return Optional contenant l'entité si trouvée
+ */
+ public Optional findByIdOptional(UUID id) {
+ return Optional.ofNullable(findById(id));
+ }
+
+ /**
+ * Persiste une entité
+ *
+ * @param entity L'entité à persister
+ */
+ @Transactional
+ public void persist(T entity) {
+ entityManager.persist(entity);
+ }
+
+ /**
+ * Met à jour une entité
+ *
+ * @param entity L'entité à mettre à jour
+ * @return L'entité mise à jour
+ */
+ @Transactional
+ public T update(T entity) {
+ return entityManager.merge(entity);
+ }
+
+ /**
+ * Supprime une entité
+ *
+ * @param entity L'entité à supprimer
+ */
+ @Transactional
+ public void delete(T entity) {
+ entityManager.remove(entity);
+ }
+
+ /**
+ * Supprime une entité par son UUID
+ *
+ * @param id L'UUID de l'entité à supprimer
+ */
+ @Transactional
+ public boolean deleteById(UUID id) {
+ T entity = findById(id);
+ if (entity != null) {
+ delete(entity);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Liste toutes les entités
+ *
+ * @return La liste de toutes les entités
+ */
+ public List listAll() {
+ return entityManager.createQuery(
+ "SELECT e FROM " + entityClass.getSimpleName() + " e", entityClass)
+ .getResultList();
+ }
+
+ /**
+ * Compte toutes les entités
+ *
+ * @return Le nombre total d'entités
+ */
+ public long count() {
+ return entityManager.createQuery(
+ "SELECT COUNT(e) FROM " + entityClass.getSimpleName() + " e", Long.class)
+ .getSingleResult();
+ }
+
+ /**
+ * Vérifie si une entité existe par son UUID
+ *
+ * @param id L'UUID de l'entité
+ * @return true si l'entité existe
+ */
+ public boolean existsById(UUID id) {
+ return findById(id) != null;
+ }
+
+ /**
+ * Obtient l'EntityManager (pour les requêtes avancées)
+ *
+ * @return L'EntityManager
+ */
+ public EntityManager getEntityManager() {
+ return entityManager;
+ }
+}
+
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/CotisationRepository.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/CotisationRepository.java
index 17b923c..9aa750f 100644
--- a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/CotisationRepository.java
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/CotisationRepository.java
@@ -1,285 +1,392 @@
package dev.lions.unionflow.server.repository;
import dev.lions.unionflow.server.entity.Cotisation;
-import io.quarkus.hibernate.orm.panache.PanacheRepository;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Sort;
import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.persistence.TypedQuery;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.UUID;
/**
- * Repository pour la gestion des cotisations Utilise Panache pour simplifier les opérations JPA
+ * Repository pour la gestion des cotisations avec UUID
*
* @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-15
+ * @version 2.0
+ * @since 2025-01-16
*/
@ApplicationScoped
-public class CotisationRepository implements PanacheRepository {
+public class CotisationRepository extends BaseRepository {
- /**
- * Trouve une cotisation par son numéro de référence
- *
- * @param numeroReference le numéro de référence unique
- * @return Optional contenant la cotisation si trouvée
- */
- public Optional findByNumeroReference(String numeroReference) {
- return find("numeroReference = ?1", numeroReference).firstResultOptional();
- }
-
- /**
- * Trouve toutes les cotisations d'un membre
- *
- * @param membreId l'identifiant du membre
- * @param page pagination
- * @param sort tri
- * @return liste paginée des cotisations
- */
- public List findByMembreId(Long membreId, Page page, Sort sort) {
- return find("membre.id = ?1", membreId).page(page).list();
- }
-
- /**
- * Trouve les cotisations par statut
- *
- * @param statut le statut recherché
- * @param page pagination
- * @return liste paginée des cotisations
- */
- public List findByStatut(String statut, Page page) {
- return find("statut = ?1", Sort.by("dateEcheance").descending(), statut).page(page).list();
- }
-
- /**
- * Trouve les cotisations en retard
- *
- * @param dateReference date de référence (généralement aujourd'hui)
- * @param page pagination
- * @return liste des cotisations en retard
- */
- public List findCotisationsEnRetard(LocalDate dateReference, Page page) {
- return find(
- "dateEcheance < ?1 and statut != 'PAYEE' and statut != 'ANNULEE'",
- Sort.by("dateEcheance").ascending(),
- dateReference)
- .page(page)
- .list();
- }
-
- /**
- * Trouve les cotisations par période (année/mois)
- *
- * @param annee l'année
- * @param mois le mois (optionnel)
- * @param page pagination
- * @return liste des cotisations de la période
- */
- public List findByPeriode(Integer annee, Integer mois, Page page) {
- if (mois != null) {
- return find("annee = ?1 and mois = ?2", Sort.by("dateEcheance").descending(), annee, mois)
- .page(page)
- .list();
- } else {
- return find("annee = ?1", Sort.by("mois", "dateEcheance").descending(), annee)
- .page(page)
- .list();
- }
- }
-
- /**
- * Trouve les cotisations par type
- *
- * @param typeCotisation le type de cotisation
- * @param page pagination
- * @return liste des cotisations du type spécifié
- */
- public List findByType(String typeCotisation, Page page) {
- return find("typeCotisation = ?1", Sort.by("dateEcheance").descending(), typeCotisation)
- .page(page)
- .list();
- }
-
- /**
- * Recherche avancée avec filtres multiples
- *
- * @param membreId identifiant du membre (optionnel)
- * @param statut statut (optionnel)
- * @param typeCotisation type (optionnel)
- * @param annee année (optionnel)
- * @param mois mois (optionnel)
- * @param page pagination
- * @return liste filtrée des cotisations
- */
- public List rechercheAvancee(
- Long membreId, String statut, String typeCotisation, Integer annee, Integer mois, Page page) {
- StringBuilder query = new StringBuilder("1=1");
- Map params = new java.util.HashMap<>();
-
- if (membreId != null) {
- query.append(" and membre.id = :membreId");
- params.put("membreId", membreId);
+ public CotisationRepository() {
+ super(Cotisation.class);
}
- if (statut != null && !statut.isEmpty()) {
- query.append(" and statut = :statut");
- params.put("statut", statut);
+ /**
+ * Trouve une cotisation par son numéro de référence
+ *
+ * @param numeroReference le numéro de référence unique
+ * @return Optional contenant la cotisation si trouvée
+ */
+ public Optional findByNumeroReference(String numeroReference) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT c FROM Cotisation c WHERE c.numeroReference = :numeroReference",
+ Cotisation.class);
+ query.setParameter("numeroReference", numeroReference);
+ return query.getResultStream().findFirst();
}
- if (typeCotisation != null && !typeCotisation.isEmpty()) {
- query.append(" and typeCotisation = :typeCotisation");
- params.put("typeCotisation", typeCotisation);
+ /**
+ * Trouve toutes les cotisations d'un membre
+ *
+ * @param membreId l'UUID du membre
+ * @param page pagination
+ * @param sort tri
+ * @return liste paginée des cotisations
+ */
+ public List findByMembreId(UUID membreId, Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT c FROM Cotisation c WHERE c.membre.id = :membreId" + orderBy,
+ Cotisation.class);
+ query.setParameter("membreId", membreId);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
}
- if (annee != null) {
- query.append(" and annee = :annee");
- params.put("annee", annee);
+ /**
+ * Trouve les cotisations par statut
+ *
+ * @param statut le statut recherché
+ * @param page pagination
+ * @return liste paginée des cotisations
+ */
+ public List findByStatut(String statut, Page page) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT c FROM Cotisation c WHERE c.statut = :statut ORDER BY c.dateEcheance DESC",
+ Cotisation.class);
+ query.setParameter("statut", statut);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
}
- if (mois != null) {
- query.append(" and mois = :mois");
- params.put("mois", mois);
+ /**
+ * Trouve les cotisations en retard
+ *
+ * @param dateReference date de référence (généralement aujourd'hui)
+ * @param page pagination
+ * @return liste des cotisations en retard
+ */
+ public List findCotisationsEnRetard(LocalDate dateReference, Page page) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT c FROM Cotisation c WHERE c.dateEcheance < :dateReference AND c.statut != 'PAYEE' AND c.statut != 'ANNULEE' ORDER BY c.dateEcheance ASC",
+ Cotisation.class);
+ query.setParameter("dateReference", dateReference);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
}
- return find(query.toString(), Sort.by("dateEcheance").descending(), params).page(page).list();
- }
+ /**
+ * Trouve les cotisations par période (année/mois)
+ *
+ * @param annee l'année
+ * @param mois le mois (optionnel)
+ * @param page pagination
+ * @return liste des cotisations de la période
+ */
+ public List findByPeriode(Integer annee, Integer mois, Page page) {
+ TypedQuery query;
+ if (mois != null) {
+ query = entityManager.createQuery(
+ "SELECT c FROM Cotisation c WHERE c.annee = :annee AND c.mois = :mois ORDER BY c.dateEcheance DESC",
+ Cotisation.class);
+ query.setParameter("annee", annee);
+ query.setParameter("mois", mois);
+ } else {
+ query = entityManager.createQuery(
+ "SELECT c FROM Cotisation c WHERE c.annee = :annee ORDER BY c.mois DESC, c.dateEcheance DESC",
+ Cotisation.class);
+ query.setParameter("annee", annee);
+ }
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
+ }
- /**
- * Calcule le total des montants dus pour un membre
- *
- * @param membreId identifiant du membre
- * @return montant total dû
- */
- public BigDecimal calculerTotalMontantDu(Long membreId) {
- return find("select sum(c.montantDu) from Cotisation c where c.membre.id = ?1", membreId)
- .project(BigDecimal.class)
- .firstResult();
- }
+ /**
+ * Trouve les cotisations par type
+ *
+ * @param typeCotisation le type de cotisation
+ * @param page pagination
+ * @return liste des cotisations du type spécifié
+ */
+ public List findByType(String typeCotisation, Page page) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT c FROM Cotisation c WHERE c.typeCotisation = :typeCotisation ORDER BY c.dateEcheance DESC",
+ Cotisation.class);
+ query.setParameter("typeCotisation", typeCotisation);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
+ }
- /**
- * Calcule le total des montants payés pour un membre
- *
- * @param membreId identifiant du membre
- * @return montant total payé
- */
- public BigDecimal calculerTotalMontantPaye(Long membreId) {
- return find("select sum(c.montantPaye) from Cotisation c where c.membre.id = ?1", membreId)
- .project(BigDecimal.class)
- .firstResult();
- }
+ /**
+ * Recherche avancée avec filtres multiples
+ *
+ * @param membreId UUID du membre (optionnel)
+ * @param statut statut (optionnel)
+ * @param typeCotisation type (optionnel)
+ * @param annee année (optionnel)
+ * @param mois mois (optionnel)
+ * @param page pagination
+ * @return liste filtrée des cotisations
+ */
+ public List rechercheAvancee(
+ UUID membreId, String statut, String typeCotisation, Integer annee, Integer mois, Page page) {
+ StringBuilder jpql = new StringBuilder("SELECT c FROM Cotisation c WHERE 1=1");
+ Map params = new HashMap<>();
- /**
- * Compte les cotisations par statut
- *
- * @param statut le statut
- * @return nombre de cotisations
- */
- public long compterParStatut(String statut) {
- return count("statut = ?1", statut);
- }
+ if (membreId != null) {
+ jpql.append(" AND c.membre.id = :membreId");
+ params.put("membreId", membreId);
+ }
- /**
- * Trouve les cotisations nécessitant un rappel
- *
- * @param joursAvantEcheance nombre de jours avant échéance
- * @param nombreMaxRappels nombre maximum de rappels déjà envoyés
- * @return liste des cotisations à rappeler
- */
- public List findCotisationsAuRappel(int joursAvantEcheance, int nombreMaxRappels) {
- LocalDate dateRappel = LocalDate.now().plusDays(joursAvantEcheance);
- return find(
- "dateEcheance <= ?1 and statut != 'PAYEE' and statut != 'ANNULEE' and nombreRappels <"
- + " ?2",
- Sort.by("dateEcheance").ascending(),
- dateRappel,
- nombreMaxRappels)
- .list();
- }
+ if (statut != null && !statut.isEmpty()) {
+ jpql.append(" AND c.statut = :statut");
+ params.put("statut", statut);
+ }
- /**
- * Met à jour le nombre de rappels pour une cotisation
- *
- * @param cotisationId identifiant de la cotisation
- * @return nombre de lignes mises à jour
- */
- public int incrementerNombreRappels(Long cotisationId) {
- return update(
- "nombreRappels = nombreRappels + 1, dateDernierRappel = ?1 where id = ?2",
- LocalDateTime.now(),
- cotisationId);
- }
+ if (typeCotisation != null && !typeCotisation.isEmpty()) {
+ jpql.append(" AND c.typeCotisation = :typeCotisation");
+ params.put("typeCotisation", typeCotisation);
+ }
- /**
- * Statistiques des cotisations par période
- *
- * @param annee l'année
- * @param mois le mois (optionnel)
- * @return map avec les statistiques
- */
- public Map getStatistiquesPeriode(Integer annee, Integer mois) {
- String baseQuery =
- mois != null
- ? "from Cotisation c where c.annee = ?1 and c.mois = ?2"
- : "from Cotisation c where c.annee = ?1";
+ if (annee != null) {
+ jpql.append(" AND c.annee = :annee");
+ params.put("annee", annee);
+ }
- Object[] params = mois != null ? new Object[] {annee, mois} : new Object[] {annee};
+ if (mois != null) {
+ jpql.append(" AND c.mois = :mois");
+ params.put("mois", mois);
+ }
- Long totalCotisations =
- mois != null ? count("annee = ?1 and mois = ?2", params) : count("annee = ?1", params);
+ jpql.append(" ORDER BY c.dateEcheance DESC");
- BigDecimal montantTotal =
- find("select sum(c.montantDu) " + baseQuery, params)
- .project(BigDecimal.class)
- .firstResult();
+ TypedQuery query = entityManager.createQuery(jpql.toString(), Cotisation.class);
+ for (Map.Entry param : params.entrySet()) {
+ query.setParameter(param.getKey(), param.getValue());
+ }
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
+ }
- BigDecimal montantPaye =
- find("select sum(c.montantPaye) " + baseQuery, params)
- .project(BigDecimal.class)
- .firstResult();
+ /**
+ * Calcule le total des montants dus pour un membre
+ *
+ * @param membreId UUID du membre
+ * @return montant total dû
+ */
+ public BigDecimal calculerTotalMontantDu(UUID membreId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COALESCE(SUM(c.montantDu), 0) FROM Cotisation c WHERE c.membre.id = :membreId",
+ BigDecimal.class);
+ query.setParameter("membreId", membreId);
+ BigDecimal result = query.getSingleResult();
+ return result != null ? result : BigDecimal.ZERO;
+ }
- Long cotisationsPayees =
- mois != null
- ? count("annee = ?1 and mois = ?2 and statut = 'PAYEE'", annee, mois)
- : count("annee = ?1 and statut = 'PAYEE'", annee);
+ /**
+ * Calcule le total des montants payés pour un membre
+ *
+ * @param membreId UUID du membre
+ * @return montant total payé
+ */
+ public BigDecimal calculerTotalMontantPaye(UUID membreId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COALESCE(SUM(c.montantPaye), 0) FROM Cotisation c WHERE c.membre.id = :membreId",
+ BigDecimal.class);
+ query.setParameter("membreId", membreId);
+ BigDecimal result = query.getSingleResult();
+ return result != null ? result : BigDecimal.ZERO;
+ }
- return Map.of(
- "totalCotisations", totalCotisations != null ? totalCotisations : 0L,
- "montantTotal", montantTotal != null ? montantTotal : BigDecimal.ZERO,
- "montantPaye", montantPaye != null ? montantPaye : BigDecimal.ZERO,
- "cotisationsPayees", cotisationsPayees != null ? cotisationsPayees : 0L,
- "tauxPaiement",
- totalCotisations != null && totalCotisations > 0
- ? (cotisationsPayees != null ? cotisationsPayees : 0L) * 100.0 / totalCotisations
- : 0.0);
- }
+ /**
+ * Compte les cotisations par statut
+ *
+ * @param statut le statut
+ * @return nombre de cotisations
+ */
+ public long compterParStatut(String statut) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COUNT(c) FROM Cotisation c WHERE c.statut = :statut", Long.class);
+ query.setParameter("statut", statut);
+ return query.getSingleResult();
+ }
- /** Somme des montants payés dans une période */
- public BigDecimal sumMontantsPayes(
- java.util.UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
- return find(
- "SELECT COALESCE(SUM(c.montant), 0) FROM Cotisation c WHERE c.organisation.id = ?1 and"
- + " c.statut = 'PAYEE' and c.datePaiement between ?2 and ?3",
- organisationId,
- debut,
- fin)
- .project(BigDecimal.class)
- .firstResult();
- }
+ /**
+ * Trouve les cotisations nécessitant un rappel
+ *
+ * @param joursAvantEcheance nombre de jours avant échéance
+ * @param nombreMaxRappels nombre maximum de rappels déjà envoyés
+ * @return liste des cotisations à rappeler
+ */
+ public List findCotisationsAuRappel(int joursAvantEcheance, int nombreMaxRappels) {
+ LocalDate dateRappel = LocalDate.now().plusDays(joursAvantEcheance);
+ TypedQuery query = entityManager.createQuery(
+ "SELECT c FROM Cotisation c WHERE c.dateEcheance <= :dateRappel AND c.statut != 'PAYEE' AND c.statut != 'ANNULEE' AND c.nombreRappels < :nombreMaxRappels ORDER BY c.dateEcheance ASC",
+ Cotisation.class);
+ query.setParameter("dateRappel", dateRappel);
+ query.setParameter("nombreMaxRappels", nombreMaxRappels);
+ return query.getResultList();
+ }
- /** Somme des montants en attente dans une période */
- public BigDecimal sumMontantsEnAttente(
- java.util.UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
- return find(
- "SELECT COALESCE(SUM(c.montant), 0) FROM Cotisation c WHERE c.organisation.id = ?1 and"
- + " c.statut = 'EN_ATTENTE' and c.dateCreation between ?2 and ?3",
- organisationId,
- debut,
- fin)
- .project(BigDecimal.class)
- .firstResult();
- }
+ /**
+ * Met à jour le nombre de rappels pour une cotisation
+ *
+ * @param cotisationId UUID de la cotisation
+ * @return true si mise à jour réussie
+ */
+ public boolean incrementerNombreRappels(UUID cotisationId) {
+ Cotisation cotisation = findById(cotisationId);
+ if (cotisation != null) {
+ cotisation.setNombreRappels(
+ cotisation.getNombreRappels() != null ? cotisation.getNombreRappels() + 1 : 1);
+ cotisation.setDateDernierRappel(LocalDateTime.now());
+ update(cotisation);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Statistiques des cotisations par période
+ *
+ * @param annee l'année
+ * @param mois le mois (optionnel)
+ * @return map avec les statistiques
+ */
+ public Map getStatistiquesPeriode(Integer annee, Integer mois) {
+ String baseQuery = mois != null
+ ? "SELECT c FROM Cotisation c WHERE c.annee = :annee AND c.mois = :mois"
+ : "SELECT c FROM Cotisation c WHERE c.annee = :annee";
+
+ TypedQuery countQuery;
+ TypedQuery montantTotalQuery;
+ TypedQuery montantPayeQuery;
+ TypedQuery payeesQuery;
+
+ if (mois != null) {
+ countQuery = entityManager.createQuery(
+ "SELECT COUNT(c) FROM Cotisation c WHERE c.annee = :annee AND c.mois = :mois",
+ Long.class);
+ montantTotalQuery = entityManager.createQuery(
+ "SELECT COALESCE(SUM(c.montantDu), 0) FROM Cotisation c WHERE c.annee = :annee AND c.mois = :mois",
+ BigDecimal.class);
+ montantPayeQuery = entityManager.createQuery(
+ "SELECT COALESCE(SUM(c.montantPaye), 0) FROM Cotisation c WHERE c.annee = :annee AND c.mois = :mois",
+ BigDecimal.class);
+ payeesQuery = entityManager.createQuery(
+ "SELECT COUNT(c) FROM Cotisation c WHERE c.annee = :annee AND c.mois = :mois AND c.statut = 'PAYEE'",
+ Long.class);
+
+ countQuery.setParameter("annee", annee);
+ countQuery.setParameter("mois", mois);
+ montantTotalQuery.setParameter("annee", annee);
+ montantTotalQuery.setParameter("mois", mois);
+ montantPayeQuery.setParameter("annee", annee);
+ montantPayeQuery.setParameter("mois", mois);
+ payeesQuery.setParameter("annee", annee);
+ payeesQuery.setParameter("mois", mois);
+ } else {
+ countQuery = entityManager.createQuery(
+ "SELECT COUNT(c) FROM Cotisation c WHERE c.annee = :annee", Long.class);
+ montantTotalQuery = entityManager.createQuery(
+ "SELECT COALESCE(SUM(c.montantDu), 0) FROM Cotisation c WHERE c.annee = :annee",
+ BigDecimal.class);
+ montantPayeQuery = entityManager.createQuery(
+ "SELECT COALESCE(SUM(c.montantPaye), 0) FROM Cotisation c WHERE c.annee = :annee",
+ BigDecimal.class);
+ payeesQuery = entityManager.createQuery(
+ "SELECT COUNT(c) FROM Cotisation c WHERE c.annee = :annee AND c.statut = 'PAYEE'",
+ Long.class);
+
+ countQuery.setParameter("annee", annee);
+ montantTotalQuery.setParameter("annee", annee);
+ montantPayeQuery.setParameter("annee", annee);
+ payeesQuery.setParameter("annee", annee);
+ }
+
+ Long totalCotisations = countQuery.getSingleResult();
+ BigDecimal montantTotal = montantTotalQuery.getSingleResult();
+ BigDecimal montantPaye = montantPayeQuery.getSingleResult();
+ Long cotisationsPayees = payeesQuery.getSingleResult();
+
+ return Map.of(
+ "totalCotisations", totalCotisations != null ? totalCotisations : 0L,
+ "montantTotal", montantTotal != null ? montantTotal : BigDecimal.ZERO,
+ "montantPaye", montantPaye != null ? montantPaye : BigDecimal.ZERO,
+ "cotisationsPayees", cotisationsPayees != null ? cotisationsPayees : 0L,
+ "tauxPaiement",
+ totalCotisations != null && totalCotisations > 0
+ ? (cotisationsPayees != null ? cotisationsPayees : 0L) * 100.0 / totalCotisations
+ : 0.0);
+ }
+
+ /** Somme des montants payés dans une période */
+ public BigDecimal sumMontantsPayes(
+ UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COALESCE(SUM(c.montantPaye), 0) FROM Cotisation c WHERE c.membre.organisation.id = :organisationId AND c.statut = 'PAYEE' AND c.datePaiement BETWEEN :debut AND :fin",
+ BigDecimal.class);
+ query.setParameter("organisationId", organisationId);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ BigDecimal result = query.getSingleResult();
+ return result != null ? result : BigDecimal.ZERO;
+ }
+
+ /** Somme des montants en attente dans une période */
+ public BigDecimal sumMontantsEnAttente(
+ UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COALESCE(SUM(c.montantDu), 0) FROM Cotisation c WHERE c.membre.organisation.id = :organisationId AND c.statut = 'EN_ATTENTE' AND c.dateCreation BETWEEN :debut AND :fin",
+ BigDecimal.class);
+ query.setParameter("organisationId", organisationId);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ BigDecimal result = query.getSingleResult();
+ return result != null ? result : BigDecimal.ZERO;
+ }
+
+ /** Construit la clause ORDER BY Ã partir d'un Sort */
+ private String buildOrderBy(Sort sort) {
+ if (sort == null || sort.getColumns().isEmpty()) {
+ return "c.dateEcheance DESC";
+ }
+ StringBuilder orderBy = new StringBuilder();
+ for (int i = 0; i < sort.getColumns().size(); i++) {
+ if (i > 0) {
+ orderBy.append(", ");
+ }
+ Sort.Column column = sort.getColumns().get(i);
+ orderBy.append("c.").append(column.getName());
+ if (column.getDirection() == Sort.Direction.Descending) {
+ orderBy.append(" DESC");
+ } else {
+ orderBy.append(" ASC");
+ }
+ }
+ return orderBy.toString();
+ }
}
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/DemandeAideRepository.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/DemandeAideRepository.java
index 0a71c79..d44bf34 100644
--- a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/DemandeAideRepository.java
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/DemandeAideRepository.java
@@ -3,167 +3,273 @@ package dev.lions.unionflow.server.repository;
import dev.lions.unionflow.server.api.enums.solidarite.StatutAide;
import dev.lions.unionflow.server.api.enums.solidarite.TypeAide;
import dev.lions.unionflow.server.entity.DemandeAide;
-import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Sort;
import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.persistence.TypedQuery;
import java.math.BigDecimal;
import java.time.LocalDateTime;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.UUID;
-/** Repository pour les demandes d'aide */
+/** Repository pour les demandes d'aide avec UUID */
@ApplicationScoped
-public class DemandeAideRepository implements PanacheRepositoryBase {
+public class DemandeAideRepository extends BaseRepository {
- /** Trouve toutes les demandes d'aide par organisation */
- public List findByOrganisationId(UUID organisationId) {
- return find("organisation.id", organisationId).list();
- }
+ public DemandeAideRepository() {
+ super(DemandeAide.class);
+ }
- /** Trouve toutes les demandes d'aide par organisation avec pagination */
- public List findByOrganisationId(UUID organisationId, Page page, Sort sort) {
- return find("organisation.id = ?1 ORDER BY dateDemande DESC", organisationId).page(page).list();
- }
+ /** Trouve toutes les demandes d'aide par organisation */
+ public List findByOrganisationId(UUID organisationId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.organisation.id = :organisationId",
+ DemandeAide.class);
+ query.setParameter("organisationId", organisationId);
+ return query.getResultList();
+ }
- /** Trouve toutes les demandes d'aide par demandeur */
- public List findByDemandeurId(UUID demandeurId) {
- return find("demandeur.id", demandeurId).list();
- }
+ /** Trouve toutes les demandes d'aide par organisation avec pagination */
+ public List findByOrganisationId(UUID organisationId, Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : " ORDER BY d.dateDemande DESC";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.organisation.id = :organisationId" + orderBy,
+ DemandeAide.class);
+ query.setParameter("organisationId", organisationId);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
+ }
- /** Trouve toutes les demandes d'aide par statut */
- public List findByStatut(StatutAide statut) {
- return find("statut", statut).list();
- }
+ /** Trouve toutes les demandes d'aide par demandeur */
+ public List findByDemandeurId(UUID demandeurId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.demandeur.id = :demandeurId",
+ DemandeAide.class);
+ query.setParameter("demandeurId", demandeurId);
+ return query.getResultList();
+ }
- /** Trouve toutes les demandes d'aide par statut et organisation */
- public List findByStatutAndOrganisationId(StatutAide statut, UUID organisationId) {
- return find("statut = ?1 and organisation.id = ?2", statut, organisationId).list();
- }
+ /** Trouve toutes les demandes d'aide par statut */
+ public List findByStatut(StatutAide statut) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.statut = :statut",
+ DemandeAide.class);
+ query.setParameter("statut", statut);
+ return query.getResultList();
+ }
- /** Trouve toutes les demandes d'aide par type */
- public List findByTypeAide(TypeAide typeAide) {
- return find("typeAide", typeAide).list();
- }
+ /** Trouve toutes les demandes d'aide par statut et organisation */
+ public List findByStatutAndOrganisationId(StatutAide statut, UUID organisationId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.statut = :statut AND d.organisation.id = :organisationId",
+ DemandeAide.class);
+ query.setParameter("statut", statut);
+ query.setParameter("organisationId", organisationId);
+ return query.getResultList();
+ }
- /** Trouve toutes les demandes d'aide urgentes */
- public List findUrgentes() {
- return find("urgence", true).list();
- }
+ /** Trouve toutes les demandes d'aide par type */
+ public List findByTypeAide(TypeAide typeAide) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.typeAide = :typeAide",
+ DemandeAide.class);
+ query.setParameter("typeAide", typeAide);
+ return query.getResultList();
+ }
- /** Trouve toutes les demandes d'aide urgentes par organisation */
- public List findUrgentesByOrganisationId(UUID organisationId) {
- return find("urgence = true and organisation.id = ?1", organisationId).list();
- }
+ /** Trouve toutes les demandes d'aide urgentes */
+ public List findUrgentes() {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.urgence = true",
+ DemandeAide.class);
+ return query.getResultList();
+ }
- /** Trouve toutes les demandes d'aide dans une période */
- public List findByPeriode(LocalDateTime debut, LocalDateTime fin) {
- return find("dateDemande >= ?1 and dateDemande <= ?2", debut, fin).list();
- }
+ /** Trouve toutes les demandes d'aide urgentes par organisation */
+ public List findUrgentesByOrganisationId(UUID organisationId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.urgence = true AND d.organisation.id = :organisationId",
+ DemandeAide.class);
+ query.setParameter("organisationId", organisationId);
+ return query.getResultList();
+ }
- /** Trouve toutes les demandes d'aide dans une période pour une organisation */
- public List findByPeriodeAndOrganisationId(
- LocalDateTime debut, LocalDateTime fin, UUID organisationId) {
- return find(
- "dateDemande >= ?1 and dateDemande <= ?2 and organisation.id = ?3",
- debut,
- fin,
- organisationId)
- .list();
- }
+ /** Trouve toutes les demandes d'aide dans une période */
+ public List findByPeriode(LocalDateTime debut, LocalDateTime fin) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.dateDemande >= :debut AND d.dateDemande <= :fin",
+ DemandeAide.class);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ return query.getResultList();
+ }
- /** Compte le nombre de demandes par statut */
- public long countByStatut(StatutAide statut) {
- return count("statut", statut);
- }
+ /** Trouve toutes les demandes d'aide dans une période pour une organisation */
+ public List findByPeriodeAndOrganisationId(
+ LocalDateTime debut, LocalDateTime fin, UUID organisationId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.dateDemande >= :debut AND d.dateDemande <= :fin AND d.organisation.id = :organisationId",
+ DemandeAide.class);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ query.setParameter("organisationId", organisationId);
+ return query.getResultList();
+ }
- /** Compte le nombre de demandes par statut et organisation */
- public long countByStatutAndOrganisationId(StatutAide statut, UUID organisationId) {
- return count("statut = ?1 and organisation.id = ?2", statut, organisationId);
- }
+ /** Compte le nombre de demandes par statut */
+ public long countByStatut(StatutAide statut) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COUNT(d) FROM DemandeAide d WHERE d.statut = :statut",
+ Long.class);
+ query.setParameter("statut", statut);
+ return query.getSingleResult();
+ }
- /** Calcule le montant total demandé par organisation */
- public Optional sumMontantDemandeByOrganisationId(UUID organisationId) {
- return find(
- "SELECT SUM(d.montantDemande) FROM DemandeAide d WHERE d.organisation.id = ?1",
- organisationId)
- .project(BigDecimal.class)
- .firstResultOptional();
- }
+ /** Compte le nombre de demandes par statut et organisation */
+ public long countByStatutAndOrganisationId(StatutAide statut, UUID organisationId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COUNT(d) FROM DemandeAide d WHERE d.statut = :statut AND d.organisation.id = :organisationId",
+ Long.class);
+ query.setParameter("statut", statut);
+ query.setParameter("organisationId", organisationId);
+ return query.getSingleResult();
+ }
- /** Calcule le montant total approuvé par organisation */
- public Optional sumMontantApprouveByOrganisationId(UUID organisationId) {
- return find(
- "SELECT SUM(d.montantApprouve) FROM DemandeAide d WHERE d.organisation.id = ?1 AND"
- + " d.statut = ?2",
- organisationId,
- StatutAide.APPROUVEE)
- .project(BigDecimal.class)
- .firstResultOptional();
- }
+ /** Calcule le montant total demandé par organisation */
+ public Optional sumMontantDemandeByOrganisationId(UUID organisationId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COALESCE(SUM(d.montantDemande), 0) FROM DemandeAide d WHERE d.organisation.id = :organisationId",
+ BigDecimal.class);
+ query.setParameter("organisationId", organisationId);
+ BigDecimal result = query.getSingleResult();
+ return result != null && result.compareTo(BigDecimal.ZERO) > 0
+ ? Optional.of(result)
+ : Optional.empty();
+ }
- /** Trouve les demandes d'aide récentes (dernières 30 jours) */
- public List findRecentes() {
- LocalDateTime il30Jours = LocalDateTime.now().minusDays(30);
- return find("dateDemande >= ?1", Sort.by("dateDemande").descending(), il30Jours).list();
- }
+ /** Calcule le montant total approuvé par organisation */
+ public Optional sumMontantApprouveByOrganisationId(UUID organisationId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COALESCE(SUM(d.montantApprouve), 0) FROM DemandeAide d WHERE d.organisation.id = :organisationId AND d.statut = :statut",
+ BigDecimal.class);
+ query.setParameter("organisationId", organisationId);
+ query.setParameter("statut", StatutAide.APPROUVEE);
+ BigDecimal result = query.getSingleResult();
+ return result != null && result.compareTo(BigDecimal.ZERO) > 0
+ ? Optional.of(result)
+ : Optional.empty();
+ }
- /** Trouve les demandes d'aide récentes par organisation */
- public List findRecentesByOrganisationId(UUID organisationId) {
- LocalDateTime il30Jours = LocalDateTime.now().minusDays(30);
- return find(
- "dateDemande >= ?1 and organisation.id = ?2",
- Sort.by("dateDemande").descending(),
- il30Jours,
- organisationId)
- .list();
- }
+ /** Trouve les demandes d'aide récentes (dernières 30 jours) */
+ public List findRecentes() {
+ LocalDateTime il30Jours = LocalDateTime.now().minusDays(30);
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.dateDemande >= :il30Jours ORDER BY d.dateDemande DESC",
+ DemandeAide.class);
+ query.setParameter("il30Jours", il30Jours);
+ return query.getResultList();
+ }
- /** Trouve les demandes d'aide en attente depuis plus de X jours */
- public List findEnAttenteDepuis(int nombreJours) {
- LocalDateTime dateLimit = LocalDateTime.now().minusDays(nombreJours);
- return find("statut = ?1 and dateDemande <= ?2", StatutAide.EN_ATTENTE, dateLimit).list();
- }
+ /** Trouve les demandes d'aide récentes par organisation */
+ public List findRecentesByOrganisationId(UUID organisationId) {
+ LocalDateTime il30Jours = LocalDateTime.now().minusDays(30);
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.dateDemande >= :il30Jours AND d.organisation.id = :organisationId ORDER BY d.dateDemande DESC",
+ DemandeAide.class);
+ query.setParameter("il30Jours", il30Jours);
+ query.setParameter("organisationId", organisationId);
+ return query.getResultList();
+ }
- /** Trouve les demandes d'aide par évaluateur */
- public List findByEvaluateurId(UUID evaluateurId) {
- return find("evaluateur.id", evaluateurId).list();
- }
+ /** Trouve les demandes d'aide en attente depuis plus de X jours */
+ public List findEnAttenteDepuis(int nombreJours) {
+ LocalDateTime dateLimit = LocalDateTime.now().minusDays(nombreJours);
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.statut = :statut AND d.dateDemande <= :dateLimit",
+ DemandeAide.class);
+ query.setParameter("statut", StatutAide.EN_ATTENTE);
+ query.setParameter("dateLimit", dateLimit);
+ return query.getResultList();
+ }
- /** Trouve les demandes d'aide en cours d'évaluation par évaluateur */
- public List findEnCoursEvaluationByEvaluateurId(UUID evaluateurId) {
- return find("evaluateur.id = ?1 and statut = ?2", evaluateurId, StatutAide.EN_COURS_EVALUATION)
- .list();
- }
+ /** Trouve les demandes d'aide par évaluateur */
+ public List findByEvaluateurId(UUID evaluateurId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.evaluateur.id = :evaluateurId",
+ DemandeAide.class);
+ query.setParameter("evaluateurId", evaluateurId);
+ return query.getResultList();
+ }
- /** Compte les demandes approuvées dans une période */
- public long countDemandesApprouvees(UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
- return count(
- "organisation.id = ?1 and statut = ?2 and dateCreation between ?3 and ?4",
- organisationId,
- StatutAide.APPROUVEE,
- debut,
- fin);
- }
+ /** Trouve les demandes d'aide en cours d'évaluation par évaluateur */
+ public List findEnCoursEvaluationByEvaluateurId(UUID evaluateurId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT d FROM DemandeAide d WHERE d.evaluateur.id = :evaluateurId AND d.statut = :statut",
+ DemandeAide.class);
+ query.setParameter("evaluateurId", evaluateurId);
+ query.setParameter("statut", StatutAide.EN_COURS_EVALUATION);
+ return query.getResultList();
+ }
- /** Compte toutes les demandes dans une période */
- public long countDemandes(UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
- return count(
- "organisation.id = ?1 and dateCreation between ?2 and ?3", organisationId, debut, fin);
- }
+ /** Compte les demandes approuvées dans une période */
+ public long countDemandesApprouvees(UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COUNT(d) FROM DemandeAide d WHERE d.organisation.id = :organisationId AND d.statut = :statut AND d.dateCreation BETWEEN :debut AND :fin",
+ Long.class);
+ query.setParameter("organisationId", organisationId);
+ query.setParameter("statut", StatutAide.APPROUVEE);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ return query.getSingleResult();
+ }
- /** Somme des montants accordés dans une période */
- public BigDecimal sumMontantsAccordes(
- UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
- return find(
- "SELECT COALESCE(SUM(d.montantAccorde), 0) FROM DemandeAide d WHERE d.organisation.id ="
- + " ?1 and d.statut = ?2 and d.dateCreation between ?3 and ?4",
- organisationId,
- StatutAide.APPROUVEE,
- debut,
- fin)
- .project(BigDecimal.class)
- .firstResult();
- }
+ /** Compte toutes les demandes dans une période */
+ public long countDemandes(UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COUNT(d) FROM DemandeAide d WHERE d.organisation.id = :organisationId AND d.dateCreation BETWEEN :debut AND :fin",
+ Long.class);
+ query.setParameter("organisationId", organisationId);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ return query.getSingleResult();
+ }
+
+ /** Somme des montants accordés dans une période */
+ public BigDecimal sumMontantsAccordes(
+ UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COALESCE(SUM(d.montantApprouve), 0) FROM DemandeAide d WHERE d.organisation.id = :organisationId AND d.statut = :statut AND d.dateCreation BETWEEN :debut AND :fin",
+ BigDecimal.class);
+ query.setParameter("organisationId", organisationId);
+ query.setParameter("statut", StatutAide.APPROUVEE);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ BigDecimal result = query.getSingleResult();
+ return result != null ? result : BigDecimal.ZERO;
+ }
+
+ /** Construit la clause ORDER BY Ã partir d'un Sort */
+ private String buildOrderBy(Sort sort) {
+ if (sort == null || sort.getColumns().isEmpty()) {
+ return "d.dateDemande DESC";
+ }
+ StringBuilder orderBy = new StringBuilder();
+ for (int i = 0; i < sort.getColumns().size(); i++) {
+ if (i > 0) {
+ orderBy.append(", ");
+ }
+ Sort.Column column = sort.getColumns().get(i);
+ orderBy.append("d.").append(column.getName());
+ if (column.getDirection() == Sort.Direction.Descending) {
+ orderBy.append(" DESC");
+ } else {
+ orderBy.append(" ASC");
+ }
+ }
+ return orderBy.toString();
+ }
}
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/EvenementRepository.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/EvenementRepository.java
index bff5e37..62496b5 100644
--- a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/EvenementRepository.java
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/EvenementRepository.java
@@ -3,551 +3,461 @@ package dev.lions.unionflow.server.repository;
import dev.lions.unionflow.server.entity.Evenement;
import dev.lions.unionflow.server.entity.Evenement.StatutEvenement;
import dev.lions.unionflow.server.entity.Evenement.TypeEvenement;
-import io.quarkus.hibernate.orm.panache.PanacheRepository;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Sort;
import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.persistence.TypedQuery;
import java.time.LocalDateTime;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.UUID;
/**
- * Repository pour l'entité Événement
+ * Repository pour l'entité Événement avec UUID
*
* Fournit les méthodes d'accès aux données pour la gestion des événements avec des
* fonctionnalités de recherche avancées et de filtrage.
*
* @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-15
+ * @version 2.0
+ * @since 2025-01-16
*/
@ApplicationScoped
-public class EvenementRepository implements PanacheRepository {
+public class EvenementRepository extends BaseRepository {
- /**
- * Trouve un événement par son titre (recherche exacte)
- *
- * @param titre le titre de l'événement
- * @return l'événement trouvé ou Optional.empty()
- */
- public Optional findByTitre(String titre) {
- return find("titre", titre).firstResultOptional();
- }
-
- /**
- * Trouve tous les événements actifs
- *
- * @return la liste des événements actifs
- */
- public List findAllActifs() {
- return find("actif", true).list();
- }
-
- /**
- * Trouve tous les événements actifs avec pagination et tri
- *
- * @param page la page demandée
- * @param sort le tri à appliquer
- * @return la liste paginée des événements actifs
- */
- public List findAllActifs(Page page, Sort sort) {
- return find("actif", sort, true).page(page).list();
- }
-
- /**
- * Compte le nombre d'événements actifs
- *
- * @return le nombre d'événements actifs
- */
- public long countActifs() {
- return count("actif", true);
- }
-
- /**
- * Trouve les événements par statut
- *
- * @param statut le statut recherché
- * @return la liste des événements avec ce statut
- */
- public List findByStatut(StatutEvenement statut) {
- return find("statut", statut).list();
- }
-
- /**
- * Trouve les événements par statut avec pagination et tri
- *
- * @param statut le statut recherché
- * @param page la page demandée
- * @param sort le tri à appliquer
- * @return la liste paginée des événements avec ce statut
- */
- public List findByStatut(StatutEvenement statut, Page page, Sort sort) {
- return find("statut", sort, statut).page(page).list();
- }
-
- /**
- * Trouve les événements par type
- *
- * @param type le type d'événement recherché
- * @return la liste des événements de ce type
- */
- public List findByType(TypeEvenement type) {
- return find("typeEvenement", type).list();
- }
-
- /**
- * Trouve les événements par type avec pagination et tri
- *
- * @param type le type d'événement recherché
- * @param page la page demandée
- * @param sort le tri à appliquer
- * @return la liste paginée des événements de ce type
- */
- public List findByType(TypeEvenement type, Page page, Sort sort) {
- return find("typeEvenement", sort, type).page(page).list();
- }
-
- /**
- * Trouve les événements par organisation
- *
- * @param organisationId l'ID de l'organisation
- * @return la liste des événements de cette organisation
- */
- public List findByOrganisation(Long organisationId) {
- return find("organisation.id", organisationId).list();
- }
-
- /**
- * Trouve les événements par organisation avec pagination et tri
- *
- * @param organisationId l'ID de l'organisation
- * @param page la page demandée
- * @param sort le tri à appliquer
- * @return la liste paginée des événements de cette organisation
- */
- public List findByOrganisation(Long organisationId, Page page, Sort sort) {
- return find("organisation.id", sort, organisationId).page(page).list();
- }
-
- /**
- * Trouve les événements par organisateur
- *
- * @param organisateurId l'ID de l'organisateur
- * @return la liste des événements organisés par ce membre
- */
- public List findByOrganisateur(Long organisateurId) {
- return find("organisateur.id", organisateurId).list();
- }
-
- /**
- * Trouve les événements dans une période donnée
- *
- * @param dateDebut la date de début de la période
- * @param dateFin la date de fin de la période
- * @return la liste des événements dans cette période
- */
- public List findByPeriode(LocalDateTime dateDebut, LocalDateTime dateFin) {
- return find("dateDebut >= ?1 and dateDebut <= ?2", dateDebut, dateFin).list();
- }
-
- /**
- * Trouve les événements dans une période donnée avec pagination et tri
- *
- * @param dateDebut la date de début de la période
- * @param dateFin la date de fin de la période
- * @param page la page demandée
- * @param sort le tri à appliquer
- * @return la liste paginée des événements dans cette période
- */
- public List findByPeriode(
- LocalDateTime dateDebut, LocalDateTime dateFin, Page page, Sort sort) {
- return find("dateDebut >= ?1 and dateDebut <= ?2", sort, dateDebut, dateFin).page(page).list();
- }
-
- /**
- * Trouve les événements à venir (date de début future)
- *
- * @return la liste des événements à venir
- */
- public List findEvenementsAVenir() {
- return find("dateDebut > ?1 and actif = true", LocalDateTime.now()).list();
- }
-
- /**
- * Trouve les événements à venir avec pagination et tri
- *
- * @param page la page demandée
- * @param sort le tri à appliquer
- * @return la liste paginée des événements à venir
- */
- public List findEvenementsAVenir(Page page, Sort sort) {
- return find("dateDebut > ?1 and actif = true", sort, LocalDateTime.now()).page(page).list();
- }
-
- /**
- * Trouve les événements en cours
- *
- * @return la liste des événements en cours
- */
- public List findEvenementsEnCours() {
- LocalDateTime maintenant = LocalDateTime.now();
- return find(
- "dateDebut <= ?1 and (dateFin is null or dateFin >= ?1) and actif = true", maintenant)
- .list();
- }
-
- /**
- * Trouve les événements passés
- *
- * @return la liste des événements passés
- */
- public List findEvenementsPasses() {
- return find(
- "(dateFin < ?1 or (dateFin is null and dateDebut < ?1)) and actif = true",
- LocalDateTime.now())
- .list();
- }
-
- /**
- * Trouve les événements passés avec pagination et tri
- *
- * @param page la page demandée
- * @param sort le tri à appliquer
- * @return la liste paginée des événements passés
- */
- public List findEvenementsPasses(Page page, Sort sort) {
- return find(
- "(dateFin < ?1 or (dateFin is null and dateDebut < ?1)) and actif = true",
- sort,
- LocalDateTime.now())
- .page(page)
- .list();
- }
-
- /**
- * Trouve les événements visibles au public
- *
- * @return la liste des événements publics
- */
- public List findEvenementsPublics() {
- return find("visiblePublic = true and actif = true").list();
- }
-
- /**
- * Trouve les événements visibles au public avec pagination et tri
- *
- * @param page la page demandée
- * @param sort le tri à appliquer
- * @return la liste paginée des événements publics
- */
- public List findEvenementsPublics(Page page, Sort sort) {
- return find("visiblePublic = true and actif = true", sort).page(page).list();
- }
-
- /**
- * Trouve les événements ouverts aux inscriptions
- *
- * @return la liste des événements ouverts aux inscriptions
- */
- public List findEvenementsOuvertsInscription() {
- LocalDateTime maintenant = LocalDateTime.now();
- return find(
- "inscriptionRequise = true and actif = true and dateDebut > ?1 and "
- + "(dateLimiteInscription is null or dateLimiteInscription > ?1) and "
- + "(statut = 'PLANIFIE' or statut = 'CONFIRME')",
- maintenant)
- .list();
- }
-
- /**
- * Recherche d'événements par titre ou description (recherche partielle)
- *
- * @param recherche le terme de recherche
- * @return la liste des événements correspondants
- */
- public List findByTitreOrDescription(String recherche) {
- return find(
- "lower(titre) like ?1 or lower(description) like ?1",
- "%" + recherche.toLowerCase() + "%")
- .list();
- }
-
- /**
- * Recherche d'événements par titre ou description avec pagination et tri
- *
- * @param recherche le terme de recherche
- * @param page la page demandée
- * @param sort le tri à appliquer
- * @return la liste paginée des événements correspondants
- */
- public List findByTitreOrDescription(String recherche, Page page, Sort sort) {
- return find(
- "lower(titre) like ?1 or lower(description) like ?1",
- sort,
- "%" + recherche.toLowerCase() + "%")
- .page(page)
- .list();
- }
-
- /**
- * Compte les événements créés depuis une date donnée
- *
- * @param depuis la date de référence
- * @return le nombre d'événements créés depuis cette date
- */
- public long countNouveauxEvenements(LocalDateTime depuis) {
- return count("dateCreation >= ?1", depuis);
- }
-
- /**
- * Trouve les événements nécessitant une inscription avec places disponibles
- *
- * @return la liste des événements avec places disponibles
- */
- public List findEvenementsAvecPlacesDisponibles() {
- LocalDateTime maintenant = LocalDateTime.now();
- return find(
- "inscriptionRequise = true and actif = true and dateDebut > ?1 and"
- + " (dateLimiteInscription is null or dateLimiteInscription > ?1) and (capaciteMax"
- + " is null or (select count(i) from InscriptionEvenement i where i.evenement ="
- + " this and i.statut = 'CONFIRMEE') < capaciteMax)",
- maintenant)
- .list();
- }
-
- /**
- * Recherche avancée d'événements avec filtres multiples
- *
- * @param recherche terme de recherche (titre, description)
- * @param statut statut de l'événement (optionnel)
- * @param type type d'événement (optionnel)
- * @param organisationId ID de l'organisation (optionnel)
- * @param organisateurId ID de l'organisateur (optionnel)
- * @param dateDebutMin date de début minimum (optionnel)
- * @param dateDebutMax date de début maximum (optionnel)
- * @param visiblePublic visibilité publique (optionnel)
- * @param inscriptionRequise inscription requise (optionnel)
- * @param actif statut actif (optionnel)
- * @param page pagination
- * @param sort tri
- * @return la liste paginée des événements correspondants aux critères
- */
- public List rechercheAvancee(
- String recherche,
- StatutEvenement statut,
- TypeEvenement type,
- Long organisationId,
- Long organisateurId,
- LocalDateTime dateDebutMin,
- LocalDateTime dateDebutMax,
- Boolean visiblePublic,
- Boolean inscriptionRequise,
- Boolean actif,
- Page page,
- Sort sort) {
- StringBuilder query = new StringBuilder("1=1");
- Map params = new java.util.HashMap<>();
-
- if (recherche != null && !recherche.trim().isEmpty()) {
- query.append(
- " and (lower(titre) like :recherche or lower(description) like :recherche or lower(lieu)"
- + " like :recherche)");
- params.put("recherche", "%" + recherche.toLowerCase() + "%");
+ public EvenementRepository() {
+ super(Evenement.class);
}
- if (statut != null) {
- query.append(" and statut = :statut");
- params.put("statut", statut);
+ /**
+ * Trouve un événement par son titre (recherche exacte)
+ *
+ * @param titre le titre de l'événement
+ * @return l'événement trouvé ou Optional.empty()
+ */
+ public Optional findByTitre(String titre) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.titre = :titre", Evenement.class);
+ query.setParameter("titre", titre);
+ return query.getResultStream().findFirst();
}
- if (type != null) {
- query.append(" and typeEvenement = :type");
- params.put("type", type);
+ /**
+ * Trouve tous les événements actifs
+ *
+ * @return la liste des événements actifs
+ */
+ public List findAllActifs() {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.actif = true", Evenement.class);
+ return query.getResultList();
}
- if (organisationId != null) {
- query.append(" and organisation.id = :organisationId");
- params.put("organisationId", organisationId);
+ /**
+ * Trouve tous les événements actifs avec pagination et tri
+ *
+ * @param page la page demandée
+ * @param sort le tri à appliquer
+ * @return la liste paginée des événements actifs
+ */
+ public List findAllActifs(Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.actif = true" + orderBy, Evenement.class);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
}
- if (organisateurId != null) {
- query.append(" and organisateur.id = :organisateurId");
- params.put("organisateurId", organisateurId);
+ /**
+ * Compte le nombre d'événements actifs
+ *
+ * @return le nombre d'événements actifs
+ */
+ public long countActifs() {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COUNT(e) FROM Evenement e WHERE e.actif = true", Long.class);
+ return query.getSingleResult();
}
- if (dateDebutMin != null) {
- query.append(" and dateDebut >= :dateDebutMin");
- params.put("dateDebutMin", dateDebutMin);
+ /**
+ * Trouve les événements par statut
+ *
+ * @param statut le statut recherché
+ * @return la liste des événements avec ce statut
+ */
+ public List findByStatut(StatutEvenement statut) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.statut = :statut", Evenement.class);
+ query.setParameter("statut", statut);
+ return query.getResultList();
}
- if (dateDebutMax != null) {
- query.append(" and dateDebut <= :dateDebutMax");
- params.put("dateDebutMax", dateDebutMax);
+ /**
+ * Trouve les événements par statut avec pagination et tri
+ *
+ * @param statut le statut recherché
+ * @param page la page demandée
+ * @param sort le tri à appliquer
+ * @return la liste paginée des événements avec ce statut
+ */
+ public List findByStatut(StatutEvenement statut, Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.statut = :statut" + orderBy, Evenement.class);
+ query.setParameter("statut", statut);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
}
- if (visiblePublic != null) {
- query.append(" and visiblePublic = :visiblePublic");
- params.put("visiblePublic", visiblePublic);
+ /**
+ * Trouve les événements par type
+ *
+ * @param type le type d'événement recherché
+ * @return la liste des événements de ce type
+ */
+ public List findByType(TypeEvenement type) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.typeEvenement = :type", Evenement.class);
+ query.setParameter("type", type);
+ return query.getResultList();
}
- if (inscriptionRequise != null) {
- query.append(" and inscriptionRequise = :inscriptionRequise");
- params.put("inscriptionRequise", inscriptionRequise);
+ /**
+ * Trouve les événements par type avec pagination et tri
+ *
+ * @param type le type d'événement recherché
+ * @param page la page demandée
+ * @param sort le tri à appliquer
+ * @return la liste paginée des événements de ce type
+ */
+ public List findByType(TypeEvenement type, Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.typeEvenement = :type" + orderBy, Evenement.class);
+ query.setParameter("type", type);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
}
- if (actif != null) {
- query.append(" and actif = :actif");
- params.put("actif", actif);
+ /**
+ * Trouve les événements par organisation
+ *
+ * @param organisationId l'UUID de l'organisation
+ * @return la liste des événements de cette organisation
+ */
+ public List findByOrganisation(UUID organisationId) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.organisation.id = :organisationId", Evenement.class);
+ query.setParameter("organisationId", organisationId);
+ return query.getResultList();
}
- return find(query.toString(), sort, params).page(page).list();
- }
-
- /**
- * Compte les résultats de la recherche avancée
- *
- * @param recherche terme de recherche (titre, description)
- * @param statut statut de l'événement (optionnel)
- * @param type type d'événement (optionnel)
- * @param organisationId ID de l'organisation (optionnel)
- * @param organisateurId ID de l'organisateur (optionnel)
- * @param dateDebutMin date de début minimum (optionnel)
- * @param dateDebutMax date de début maximum (optionnel)
- * @param visiblePublic visibilité publique (optionnel)
- * @param inscriptionRequise inscription requise (optionnel)
- * @param actif statut actif (optionnel)
- * @return le nombre d'événements correspondants aux critères
- */
- public long countRechercheAvancee(
- String recherche,
- StatutEvenement statut,
- TypeEvenement type,
- Long organisationId,
- Long organisateurId,
- LocalDateTime dateDebutMin,
- LocalDateTime dateDebutMax,
- Boolean visiblePublic,
- Boolean inscriptionRequise,
- Boolean actif) {
- StringBuilder query = new StringBuilder("1=1");
- Map params = new java.util.HashMap<>();
-
- if (recherche != null && !recherche.trim().isEmpty()) {
- query.append(
- " and (lower(titre) like :recherche or lower(description) like :recherche or lower(lieu)"
- + " like :recherche)");
- params.put("recherche", "%" + recherche.toLowerCase() + "%");
+ /**
+ * Trouve les événements par organisation avec pagination et tri
+ *
+ * @param organisationId l'UUID de l'organisation
+ * @param page la page demandée
+ * @param sort le tri à appliquer
+ * @return la liste paginée des événements de cette organisation
+ */
+ public List findByOrganisation(UUID organisationId, Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.organisation.id = :organisationId" + orderBy,
+ Evenement.class);
+ query.setParameter("organisationId", organisationId);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
}
- if (statut != null) {
- query.append(" and statut = :statut");
- params.put("statut", statut);
+ /**
+ * Trouve les événements à venir (date de début future)
+ *
+ * @return la liste des événements à venir
+ */
+ public List findEvenementsAVenir() {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.dateDebut > :maintenant AND e.actif = true",
+ Evenement.class);
+ query.setParameter("maintenant", LocalDateTime.now());
+ return query.getResultList();
}
- if (type != null) {
- query.append(" and typeEvenement = :type");
- params.put("type", type);
+ /**
+ * Trouve les événements à venir avec pagination et tri
+ *
+ * @param page la page demandée
+ * @param sort le tri à appliquer
+ * @return la liste paginée des événements à venir
+ */
+ public List findEvenementsAVenir(Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.dateDebut > :maintenant AND e.actif = true" + orderBy,
+ Evenement.class);
+ query.setParameter("maintenant", LocalDateTime.now());
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
}
- if (organisationId != null) {
- query.append(" and organisation.id = :organisationId");
- params.put("organisationId", organisationId);
+ /**
+ * Trouve les événements visibles au public
+ *
+ * @return la liste des événements publics
+ */
+ public List findEvenementsPublics() {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.visiblePublic = true AND e.actif = true",
+ Evenement.class);
+ return query.getResultList();
}
- if (organisateurId != null) {
- query.append(" and organisateur.id = :organisateurId");
- params.put("organisateurId", organisateurId);
+ /**
+ * Trouve les événements visibles au public avec pagination et tri
+ *
+ * @param page la page demandée
+ * @param sort le tri à appliquer
+ * @return la liste paginée des événements publics
+ */
+ public List findEvenementsPublics(Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT e FROM Evenement e WHERE e.visiblePublic = true AND e.actif = true" + orderBy,
+ Evenement.class);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
}
- if (dateDebutMin != null) {
- query.append(" and dateDebut >= :dateDebutMin");
- params.put("dateDebutMin", dateDebutMin);
+ /**
+ * Recherche avancée d'événements avec filtres multiples
+ *
+ * @param recherche terme de recherche (titre, description)
+ * @param statut statut de l'événement (optionnel)
+ * @param type type d'événement (optionnel)
+ * @param organisationId UUID de l'organisation (optionnel)
+ * @param organisateurId UUID de l'organisateur (optionnel)
+ * @param dateDebutMin date de début minimum (optionnel)
+ * @param dateDebutMax date de début maximum (optionnel)
+ * @param visiblePublic visibilité publique (optionnel)
+ * @param inscriptionRequise inscription requise (optionnel)
+ * @param actif statut actif (optionnel)
+ * @param page pagination
+ * @param sort tri
+ * @return la liste paginée des événements correspondants aux critères
+ */
+ public List rechercheAvancee(
+ String recherche,
+ StatutEvenement statut,
+ TypeEvenement type,
+ UUID organisationId,
+ UUID organisateurId,
+ LocalDateTime dateDebutMin,
+ LocalDateTime dateDebutMax,
+ Boolean visiblePublic,
+ Boolean inscriptionRequise,
+ Boolean actif,
+ Page page,
+ Sort sort) {
+ StringBuilder jpql = new StringBuilder("SELECT e FROM Evenement e WHERE 1=1");
+ Map params = new HashMap<>();
+
+ if (recherche != null && !recherche.trim().isEmpty()) {
+ jpql.append(
+ " AND (LOWER(e.titre) LIKE LOWER(:recherche) OR LOWER(e.description) LIKE LOWER(:recherche) OR LOWER(e.lieu) LIKE LOWER(:recherche))");
+ params.put("recherche", "%" + recherche.toLowerCase() + "%");
+ }
+
+ if (statut != null) {
+ jpql.append(" AND e.statut = :statut");
+ params.put("statut", statut);
+ }
+
+ if (type != null) {
+ jpql.append(" AND e.typeEvenement = :type");
+ params.put("type", type);
+ }
+
+ if (organisationId != null) {
+ jpql.append(" AND e.organisation.id = :organisationId");
+ params.put("organisationId", organisationId);
+ }
+
+ if (organisateurId != null) {
+ jpql.append(" AND e.organisateur.id = :organisateurId");
+ params.put("organisateurId", organisateurId);
+ }
+
+ if (dateDebutMin != null) {
+ jpql.append(" AND e.dateDebut >= :dateDebutMin");
+ params.put("dateDebutMin", dateDebutMin);
+ }
+
+ if (dateDebutMax != null) {
+ jpql.append(" AND e.dateDebut <= :dateDebutMax");
+ params.put("dateDebutMax", dateDebutMax);
+ }
+
+ if (visiblePublic != null) {
+ jpql.append(" AND e.visiblePublic = :visiblePublic");
+ params.put("visiblePublic", visiblePublic);
+ }
+
+ if (inscriptionRequise != null) {
+ jpql.append(" AND e.inscriptionRequise = :inscriptionRequise");
+ params.put("inscriptionRequise", inscriptionRequise);
+ }
+
+ if (actif != null) {
+ jpql.append(" AND e.actif = :actif");
+ params.put("actif", actif);
+ }
+
+ if (sort != null) {
+ jpql.append(" ORDER BY ").append(buildOrderBy(sort));
+ }
+
+ TypedQuery query = entityManager.createQuery(jpql.toString(), Evenement.class);
+ for (Map.Entry param : params.entrySet()) {
+ query.setParameter(param.getKey(), param.getValue());
+ }
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
}
- if (dateDebutMax != null) {
- query.append(" and dateDebut <= :dateDebutMax");
- params.put("dateDebutMax", dateDebutMax);
+ /**
+ * Obtient les statistiques des événements
+ *
+ * @return une map contenant les statistiques
+ */
+ public Map getStatistiques() {
+ Map stats = new HashMap<>();
+ LocalDateTime maintenant = LocalDateTime.now();
+
+ TypedQuery totalQuery = entityManager.createQuery(
+ "SELECT COUNT(e) FROM Evenement e", Long.class);
+ stats.put("total", totalQuery.getSingleResult());
+
+ TypedQuery actifsQuery = entityManager.createQuery(
+ "SELECT COUNT(e) FROM Evenement e WHERE e.actif = true", Long.class);
+ stats.put("actifs", actifsQuery.getSingleResult());
+
+ TypedQuery inactifsQuery = entityManager.createQuery(
+ "SELECT COUNT(e) FROM Evenement e WHERE e.actif = false", Long.class);
+ stats.put("inactifs", inactifsQuery.getSingleResult());
+
+ TypedQuery aVenirQuery = entityManager.createQuery(
+ "SELECT COUNT(e) FROM Evenement e WHERE e.dateDebut > :maintenant AND e.actif = true",
+ Long.class);
+ aVenirQuery.setParameter("maintenant", maintenant);
+ stats.put("aVenir", aVenirQuery.getSingleResult());
+
+ TypedQuery enCoursQuery = entityManager.createQuery(
+ "SELECT COUNT(e) FROM Evenement e WHERE e.dateDebut <= :maintenant AND (e.dateFin IS NULL OR e.dateFin >= :maintenant) AND e.actif = true",
+ Long.class);
+ enCoursQuery.setParameter("maintenant", maintenant);
+ stats.put("enCours", enCoursQuery.getSingleResult());
+
+ TypedQuery passesQuery = entityManager.createQuery(
+ "SELECT COUNT(e) FROM Evenement e WHERE (e.dateFin < :maintenant OR (e.dateFin IS NULL AND e.dateDebut < :maintenant)) AND e.actif = true",
+ Long.class);
+ passesQuery.setParameter("maintenant", maintenant);
+ stats.put("passes", passesQuery.getSingleResult());
+
+ TypedQuery publicsQuery = entityManager.createQuery(
+ "SELECT COUNT(e) FROM Evenement e WHERE e.visiblePublic = true AND e.actif = true",
+ Long.class);
+ stats.put("publics", publicsQuery.getSingleResult());
+
+ TypedQuery avecInscriptionQuery = entityManager.createQuery(
+ "SELECT COUNT(e) FROM Evenement e WHERE e.inscriptionRequise = true AND e.actif = true",
+ Long.class);
+ stats.put("avecInscription", avecInscriptionQuery.getSingleResult());
+
+ return stats;
}
- if (visiblePublic != null) {
- query.append(" and visiblePublic = :visiblePublic");
- params.put("visiblePublic", visiblePublic);
+ /**
+ * Compte les événements dans une période et organisation
+ *
+ * @param organisationId UUID de l'organisation
+ * @param debut date de début
+ * @param fin date de fin
+ * @return nombre d'événements
+ */
+ public long countEvenements(UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COUNT(e) FROM Evenement e WHERE e.organisation.id = :organisationId AND e.dateDebut BETWEEN :debut AND :fin",
+ Long.class);
+ query.setParameter("organisationId", organisationId);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ return query.getSingleResult();
}
- if (inscriptionRequise != null) {
- query.append(" and inscriptionRequise = :inscriptionRequise");
- params.put("inscriptionRequise", inscriptionRequise);
+ /**
+ * Calcule la moyenne de participants dans une période et organisation
+ *
+ * @param organisationId UUID de l'organisation
+ * @param debut date de début
+ * @param fin date de fin
+ * @return moyenne de participants ou null
+ */
+ public Double calculerMoyenneParticipants(UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT AVG(e.nombreParticipants) FROM Evenement e WHERE e.organisation.id = :organisationId AND e.dateDebut BETWEEN :debut AND :fin",
+ Double.class);
+ query.setParameter("organisationId", organisationId);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ return query.getSingleResult();
}
- if (actif != null) {
- query.append(" and actif = :actif");
- params.put("actif", actif);
+ /**
+ * Compte le total des participations dans une période et organisation
+ *
+ * @param organisationId UUID de l'organisation
+ * @param debut date de début
+ * @param fin date de fin
+ * @return total des participations
+ */
+ public Long countTotalParticipations(UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COALESCE(SUM(e.nombreParticipants), 0) FROM Evenement e WHERE e.organisation.id = :organisationId AND e.dateDebut BETWEEN :debut AND :fin",
+ Long.class);
+ query.setParameter("organisationId", organisationId);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ Long result = query.getSingleResult();
+ return result != null ? result : 0L;
}
- return count(query.toString(), params);
- }
-
- /**
- * Obtient les statistiques des événements
- *
- * @return une map contenant les statistiques
- */
- public Map getStatistiques() {
- Map stats = new java.util.HashMap<>();
-
- stats.put("total", count());
- stats.put("actifs", count("actif", true));
- stats.put("inactifs", count("actif", false));
- stats.put("aVenir", count("dateDebut > ?1 and actif = true", LocalDateTime.now()));
- stats.put(
- "enCours",
- count(
- "dateDebut <= ?1 and (dateFin is null or dateFin >= ?1) and actif = true",
- LocalDateTime.now()));
- stats.put(
- "passes",
- count(
- "(dateFin < ?1 or (dateFin is null and dateDebut < ?1)) and actif = true",
- LocalDateTime.now()));
- stats.put("publics", count("visiblePublic = true and actif = true"));
- stats.put("avecInscription", count("inscriptionRequise = true and actif = true"));
-
- return stats;
- }
-
- /** Compte les événements dans une période et organisation */
- public long countEvenements(
- java.util.UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
- return count(
- "organisation.id = ?1 and dateDebut between ?2 and ?3", organisationId, debut, fin);
- }
-
- /** Calcule la moyenne de participants dans une période et organisation */
- public Double calculerMoyenneParticipants(
- java.util.UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
- return find(
- "SELECT AVG(e.nombreParticipants) FROM Evenement e WHERE e.organisation.id = ?1 and"
- + " e.dateDebut between ?2 and ?3",
- organisationId,
- debut,
- fin)
- .project(Double.class)
- .firstResult();
- }
-
- /** Compte le total des participations dans une période et organisation */
- public long countTotalParticipations(
- java.util.UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
- Long result =
- find(
- "SELECT COALESCE(SUM(e.nombreParticipants), 0) FROM Evenement e WHERE"
- + " e.organisation.id = ?1 and e.dateDebut between ?2 and ?3",
- organisationId,
- debut,
- fin)
- .project(Long.class)
- .firstResult();
- return result != null ? result : 0L;
- }
+ /** Construit la clause ORDER BY Ã partir d'un Sort */
+ private String buildOrderBy(Sort sort) {
+ if (sort == null || sort.getColumns().isEmpty()) {
+ return "e.dateDebut";
+ }
+ StringBuilder orderBy = new StringBuilder();
+ for (int i = 0; i < sort.getColumns().size(); i++) {
+ if (i > 0) {
+ orderBy.append(", ");
+ }
+ Sort.Column column = sort.getColumns().get(i);
+ orderBy.append("e.").append(column.getName());
+ if (column.getDirection() == Sort.Direction.Descending) {
+ orderBy.append(" DESC");
+ } else {
+ orderBy.append(" ASC");
+ }
+ }
+ return orderBy.toString();
+ }
}
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/MembreRepository.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/MembreRepository.java
index 7599a4c..0161854 100644
--- a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/MembreRepository.java
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/MembreRepository.java
@@ -1,145 +1,238 @@
package dev.lions.unionflow.server.repository;
import dev.lions.unionflow.server.entity.Membre;
-import io.quarkus.hibernate.orm.panache.PanacheRepository;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Sort;
import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.persistence.TypedQuery;
import java.time.LocalDate;
+import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
+import java.util.UUID;
-/** Repository pour l'entité Membre */
+/** Repository pour l'entité Membre avec UUID */
@ApplicationScoped
-public class MembreRepository implements PanacheRepository {
+public class MembreRepository extends BaseRepository {
- /** Trouve un membre par son email */
- public Optional findByEmail(String email) {
- return find("email", email).firstResultOptional();
- }
-
- /** Trouve un membre par son numéro */
- public Optional findByNumeroMembre(String numeroMembre) {
- return find("numeroMembre", numeroMembre).firstResultOptional();
- }
-
- /** Trouve tous les membres actifs */
- public List findAllActifs() {
- return find("actif", true).list();
- }
-
- /** Compte le nombre de membres actifs */
- public long countActifs() {
- return count("actif", true);
- }
-
- /** Trouve les membres par nom ou prénom (recherche partielle) */
- public List findByNomOrPrenom(String recherche) {
- return find("lower(nom) like ?1 or lower(prenom) like ?1", "%" + recherche.toLowerCase() + "%")
- .list();
- }
-
- /** Trouve tous les membres actifs avec pagination et tri */
- public List findAllActifs(Page page, Sort sort) {
- return find("actif", sort, true).page(page).list();
- }
-
- /** Trouve les membres par nom ou prénom avec pagination et tri */
- public List findByNomOrPrenom(String recherche, Page page, Sort sort) {
- return find(
- "lower(nom) like ?1 or lower(prenom) like ?1",
- sort,
- "%" + recherche.toLowerCase() + "%")
- .page(page)
- .list();
- }
-
- /** Compte les nouveaux membres depuis une date donnée */
- public long countNouveauxMembres(LocalDate depuis) {
- return count("dateAdhesion >= ?1", depuis);
- }
-
- /** Trouve les membres par statut avec pagination */
- public List findByStatut(boolean actif, Page page, Sort sort) {
- return find("actif", sort, actif).page(page).list();
- }
-
- /** Trouve les membres par tranche d'âge */
- public List findByTrancheAge(int ageMin, int ageMax, Page page, Sort sort) {
- LocalDate dateNaissanceMax = LocalDate.now().minusYears(ageMin);
- LocalDate dateNaissanceMin = LocalDate.now().minusYears(ageMax + 1);
-
- return find("dateNaissance between ?1 and ?2", sort, dateNaissanceMin, dateNaissanceMax)
- .page(page)
- .list();
- }
-
- /** Recherche avancée avec filtres multiples */
- public List rechercheAvancee(
- String recherche,
- Boolean actif,
- LocalDate dateAdhesionMin,
- LocalDate dateAdhesionMax,
- Page page,
- Sort sort) {
- StringBuilder query = new StringBuilder("1=1");
- java.util.Map params = new java.util.HashMap<>();
-
- if (recherche != null && !recherche.trim().isEmpty()) {
- query.append(
- " and (lower(nom) like :recherche or lower(prenom) like :recherche or lower(email) like"
- + " :recherche)");
- params.put("recherche", "%" + recherche.toLowerCase() + "%");
+ public MembreRepository() {
+ super(Membre.class);
}
- if (actif != null) {
- query.append(" and actif = :actif");
- params.put("actif", actif);
+ /** Trouve un membre par son email */
+ public Optional findByEmail(String email) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT m FROM Membre m WHERE m.email = :email", Membre.class);
+ query.setParameter("email", email);
+ return query.getResultStream().findFirst();
}
- if (dateAdhesionMin != null) {
- query.append(" and dateAdhesion >= :dateAdhesionMin");
- params.put("dateAdhesionMin", dateAdhesionMin);
+ /** Trouve un membre par son numéro */
+ public Optional findByNumeroMembre(String numeroMembre) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT m FROM Membre m WHERE m.numeroMembre = :numeroMembre", Membre.class);
+ query.setParameter("numeroMembre", numeroMembre);
+ return query.getResultStream().findFirst();
}
- if (dateAdhesionMax != null) {
- query.append(" and dateAdhesion <= :dateAdhesionMax");
- params.put("dateAdhesionMax", dateAdhesionMax);
+ /** Trouve tous les membres actifs */
+ public List findAllActifs() {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT m FROM Membre m WHERE m.actif = true", Membre.class);
+ return query.getResultList();
}
- return find(query.toString(), sort, params).page(page).list();
- }
+ /** Compte le nombre de membres actifs */
+ public long countActifs() {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COUNT(m) FROM Membre m WHERE m.actif = true", Long.class);
+ return query.getSingleResult();
+ }
- /** Compte les membres actifs dans une période et organisation */
- public long countMembresActifs(
- java.util.UUID organisationId, java.time.LocalDateTime debut, java.time.LocalDateTime fin) {
- return count(
- "organisation.id = ?1 and actif = true and dateAdhesion between ?2 and ?3",
- organisationId,
- debut,
- fin);
- }
+ /** Trouve les membres par nom ou prénom (recherche partielle) */
+ public List findByNomOrPrenom(String recherche) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT m FROM Membre m WHERE LOWER(m.nom) LIKE LOWER(:recherche) OR LOWER(m.prenom) LIKE LOWER(:recherche)",
+ Membre.class);
+ query.setParameter("recherche", "%" + recherche + "%");
+ return query.getResultList();
+ }
- /** Compte les membres inactifs dans une période et organisation */
- public long countMembresInactifs(
- java.util.UUID organisationId, java.time.LocalDateTime debut, java.time.LocalDateTime fin) {
- return count(
- "organisation.id = ?1 and actif = false and dateAdhesion between ?2 and ?3",
- organisationId,
- debut,
- fin);
- }
+ /** Trouve tous les membres actifs avec pagination et tri */
+ public List findAllActifs(Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT m FROM Membre m WHERE m.actif = true" + orderBy, Membre.class);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
+ }
- /** Calcule la moyenne d'âge des membres dans une période et organisation */
- public Double calculerMoyenneAge(
- java.util.UUID organisationId, java.time.LocalDateTime debut, java.time.LocalDateTime fin) {
- return find(
- "SELECT AVG(YEAR(CURRENT_DATE) - YEAR(m.dateNaissance)) FROM Membre m WHERE"
- + " m.organisation.id = ?1 and m.dateAdhesion between ?2 and ?3",
- organisationId,
- debut,
- fin)
- .project(Double.class)
- .firstResult();
- }
+ /** Trouve les membres par nom ou prénom avec pagination et tri */
+ public List findByNomOrPrenom(String recherche, Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT m FROM Membre m WHERE LOWER(m.nom) LIKE LOWER(:recherche) OR LOWER(m.prenom) LIKE LOWER(:recherche)" + orderBy,
+ Membre.class);
+ query.setParameter("recherche", "%" + recherche + "%");
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
+ }
+
+ /** Compte les nouveaux membres depuis une date donnée */
+ public long countNouveauxMembres(LocalDate depuis) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COUNT(m) FROM Membre m WHERE m.dateAdhesion >= :depuis", Long.class);
+ query.setParameter("depuis", depuis);
+ return query.getSingleResult();
+ }
+
+ /** Trouve les membres par statut avec pagination */
+ public List findByStatut(boolean actif, Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT m FROM Membre m WHERE m.actif = :actif" + orderBy, Membre.class);
+ query.setParameter("actif", actif);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
+ }
+
+ /** Trouve les membres par tranche d'âge */
+ public List findByTrancheAge(int ageMin, int ageMax, Page page, Sort sort) {
+ LocalDate dateNaissanceMax = LocalDate.now().minusYears(ageMin);
+ LocalDate dateNaissanceMin = LocalDate.now().minusYears(ageMax + 1);
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT m FROM Membre m WHERE m.dateNaissance BETWEEN :dateMin AND :dateMax" + orderBy,
+ Membre.class);
+ query.setParameter("dateMin", dateNaissanceMin);
+ query.setParameter("dateMax", dateNaissanceMax);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
+ }
+
+ /** Recherche avancée de membres */
+ public List rechercheAvancee(
+ String recherche,
+ Boolean actif,
+ LocalDate dateAdhesionMin,
+ LocalDate dateAdhesionMax,
+ Page page,
+ Sort sort) {
+ StringBuilder jpql = new StringBuilder("SELECT m FROM Membre m WHERE 1=1");
+
+ if (recherche != null && !recherche.isEmpty()) {
+ jpql.append(" AND (LOWER(m.nom) LIKE LOWER(:recherche) OR LOWER(m.prenom) LIKE LOWER(:recherche) OR LOWER(m.email) LIKE LOWER(:recherche))");
+ }
+ if (actif != null) {
+ jpql.append(" AND m.actif = :actif");
+ }
+ if (dateAdhesionMin != null) {
+ jpql.append(" AND m.dateAdhesion >= :dateAdhesionMin");
+ }
+ if (dateAdhesionMax != null) {
+ jpql.append(" AND m.dateAdhesion <= :dateAdhesionMax");
+ }
+
+ if (sort != null) {
+ jpql.append(" ORDER BY ").append(buildOrderBy(sort));
+ }
+
+ TypedQuery query = entityManager.createQuery(jpql.toString(), Membre.class);
+
+ if (recherche != null && !recherche.isEmpty()) {
+ query.setParameter("recherche", "%" + recherche + "%");
+ }
+ if (actif != null) {
+ query.setParameter("actif", actif);
+ }
+ if (dateAdhesionMin != null) {
+ query.setParameter("dateAdhesionMin", dateAdhesionMin);
+ }
+ if (dateAdhesionMax != null) {
+ query.setParameter("dateAdhesionMax", dateAdhesionMax);
+ }
+
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
+ }
+
+ /** Construit la clause ORDER BY Ã partir d'un Sort */
+ private String buildOrderBy(Sort sort) {
+ if (sort == null || sort.getColumns().isEmpty()) {
+ return "m.id";
+ }
+ StringBuilder orderBy = new StringBuilder();
+ for (int i = 0; i < sort.getColumns().size(); i++) {
+ if (i > 0) {
+ orderBy.append(", ");
+ }
+ Sort.Column column = sort.getColumns().get(i);
+ orderBy.append("m.").append(column.getName());
+ if (column.getDirection() == Sort.Direction.Descending) {
+ orderBy.append(" DESC");
+ } else {
+ orderBy.append(" ASC");
+ }
+ }
+ return orderBy.toString();
+ }
+
+ /**
+ * Compte les membres actifs dans une période et organisation
+ *
+ * @param organisationId UUID de l'organisation
+ * @param debut Date de début
+ * @param fin Date de fin
+ * @return Nombre de membres actifs
+ */
+ public Long countMembresActifs(UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COUNT(m) FROM Membre m WHERE m.organisation.id = :organisationId AND m.actif = true AND m.dateAdhesion BETWEEN :debut AND :fin",
+ Long.class);
+ query.setParameter("organisationId", organisationId);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ return query.getSingleResult();
+ }
+
+ /**
+ * Compte les membres inactifs dans une période et organisation
+ *
+ * @param organisationId UUID de l'organisation
+ * @param debut Date de début
+ * @param fin Date de fin
+ * @return Nombre de membres inactifs
+ */
+ public Long countMembresInactifs(UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COUNT(m) FROM Membre m WHERE m.organisation.id = :organisationId AND m.actif = false AND m.dateAdhesion BETWEEN :debut AND :fin",
+ Long.class);
+ query.setParameter("organisationId", organisationId);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ return query.getSingleResult();
+ }
+
+ /**
+ * Calcule la moyenne d'âge des membres dans une période et organisation
+ *
+ * @param organisationId UUID de l'organisation
+ * @param debut Date de début
+ * @param fin Date de fin
+ * @return Moyenne d'âge ou null si aucun membre
+ */
+ public Double calculerMoyenneAge(UUID organisationId, LocalDateTime debut, LocalDateTime fin) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT AVG(YEAR(CURRENT_DATE) - YEAR(m.dateNaissance)) FROM Membre m WHERE m.organisation.id = :organisationId AND m.dateAdhesion BETWEEN :debut AND :fin",
+ Double.class);
+ query.setParameter("organisationId", organisationId);
+ query.setParameter("debut", debut);
+ query.setParameter("fin", fin);
+ return query.getSingleResult();
+ }
}
diff --git a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/OrganisationRepository.java b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/OrganisationRepository.java
index 66e6f88..e935553 100644
--- a/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/OrganisationRepository.java
+++ b/unionflow-server-impl-quarkus/src/main/java/dev/lions/unionflow/server/repository/OrganisationRepository.java
@@ -1,10 +1,10 @@
package dev.lions.unionflow.server.repository;
import dev.lions.unionflow.server.entity.Organisation;
-import io.quarkus.hibernate.orm.panache.PanacheRepository;
import io.quarkus.panache.common.Page;
import io.quarkus.panache.common.Sort;
import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.persistence.TypedQuery;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
@@ -13,280 +13,412 @@ import java.util.Optional;
import java.util.UUID;
/**
- * Repository pour l'entité Organisation Utilise Panache pour simplifier les opérations JPA
+ * Repository pour l'entité Organisation avec UUID
*
* @author UnionFlow Team
- * @version 1.0
- * @since 2025-01-15
+ * @version 2.0
+ * @since 2025-01-16
*/
@ApplicationScoped
-public class OrganisationRepository implements PanacheRepository {
+public class OrganisationRepository extends BaseRepository {
- /**
- * Trouve une organisation par son email
- *
- * @param email l'email de l'organisation
- * @return Optional contenant l'organisation si trouvée
- */
- public Optional findByEmail(String email) {
- return find("email = ?1", email).firstResultOptional();
- }
-
- /**
- * Trouve une organisation par son nom
- *
- * @param nom le nom de l'organisation
- * @return Optional contenant l'organisation si trouvée
- */
- public Optional findByNom(String nom) {
- return find("nom = ?1", nom).firstResultOptional();
- }
-
- /**
- * Trouve une organisation par son numéro d'enregistrement
- *
- * @param numeroEnregistrement le numéro d'enregistrement officiel
- * @return Optional contenant l'organisation si trouvée
- */
- public Optional findByNumeroEnregistrement(String numeroEnregistrement) {
- return find("numeroEnregistrement = ?1", numeroEnregistrement).firstResultOptional();
- }
-
- /**
- * Trouve toutes les organisations actives
- *
- * @return liste des organisations actives
- */
- public List findAllActives() {
- return find("statut = 'ACTIVE' and actif = true").list();
- }
-
- /**
- * Trouve toutes les organisations actives avec pagination
- *
- * @param page pagination
- * @param sort tri
- * @return liste paginée des organisations actives
- */
- public List findAllActives(Page page, Sort sort) {
- return find("statut = 'ACTIVE' and actif = true", sort).page(page).list();
- }
-
- /**
- * Compte le nombre d'organisations actives
- *
- * @return nombre d'organisations actives
- */
- public long countActives() {
- return count("statut = 'ACTIVE' and actif = true");
- }
-
- /**
- * Trouve les organisations par statut
- *
- * @param statut le statut recherché
- * @param page pagination
- * @param sort tri
- * @return liste paginée des organisations avec le statut spécifié
- */
- public List findByStatut(String statut, Page page, Sort sort) {
- return find("statut = ?1", sort, statut).page(page).list();
- }
-
- /**
- * Trouve les organisations par type
- *
- * @param typeOrganisation le type d'organisation
- * @param page pagination
- * @param sort tri
- * @return liste paginée des organisations du type spécifié
- */
- public List findByType(String typeOrganisation, Page page, Sort sort) {
- return find("typeOrganisation = ?1", sort, typeOrganisation).page(page).list();
- }
-
- /**
- * Trouve les organisations par ville
- *
- * @param ville la ville
- * @param page pagination
- * @param sort tri
- * @return liste paginée des organisations de la ville spécifiée
- */
- public List findByVille(String ville, Page page, Sort sort) {
- return find("ville = ?1", sort, ville).page(page).list();
- }
-
- /**
- * Trouve les organisations par pays
- *
- * @param pays le pays
- * @param page pagination
- * @param sort tri
- * @return liste paginée des organisations du pays spécifié
- */
- public List findByPays(String pays, Page page, Sort sort) {
- return find("pays = ?1", sort, pays).page(page).list();
- }
-
- /**
- * Trouve les organisations par région
- *
- * @param region la région
- * @param page pagination
- * @param sort tri
- * @return liste paginée des organisations de la région spécifiée
- */
- public List findByRegion(String region, Page page, Sort sort) {
- return find("region = ?1", sort, region).page(page).list();
- }
-
- /**
- * Trouve les organisations filles d'une organisation parente
- *
- * @param organisationParenteId l'ID de l'organisation parente
- * @param page pagination
- * @param sort tri
- * @return liste paginée des organisations filles
- */
- public List findByOrganisationParente(
- UUID organisationParenteId, Page page, Sort sort) {
- return find("organisationParenteId = ?1", sort, organisationParenteId).page(page).list();
- }
-
- /**
- * Trouve les organisations racines (sans parent)
- *
- * @param page pagination
- * @param sort tri
- * @return liste paginée des organisations racines
- */
- public List findOrganisationsRacines(Page page, Sort sort) {
- return find("organisationParenteId is null", sort).page(page).list();
- }
-
- /**
- * Recherche d'organisations par nom ou nom court
- *
- * @param recherche terme de recherche
- * @param page pagination
- * @param sort tri
- * @return liste paginée des organisations correspondantes
- */
- public List findByNomOrNomCourt(String recherche, Page page, Sort sort) {
- String pattern = "%" + recherche.toLowerCase() + "%";
- return find("lower(nom) like ?1 or lower(nomCourt) like ?1", sort, pattern).page(page).list();
- }
-
- /**
- * Recherche avancée d'organisations
- *
- * @param nom nom (optionnel)
- * @param typeOrganisation type (optionnel)
- * @param statut statut (optionnel)
- * @param ville ville (optionnel)
- * @param region région (optionnel)
- * @param pays pays (optionnel)
- * @param page pagination
- * @return liste filtrée des organisations
- */
- public List rechercheAvancee(
- String nom,
- String typeOrganisation,
- String statut,
- String ville,
- String region,
- String pays,
- Page page) {
- StringBuilder query = new StringBuilder("1=1");
- Map parameters = new HashMap<>();
-
- if (nom != null && !nom.isEmpty()) {
- query.append(" and (lower(nom) like :nom or lower(nomCourt) like :nom)");
- parameters.put("nom", "%" + nom.toLowerCase() + "%");
+ public OrganisationRepository() {
+ super(Organisation.class);
}
- if (typeOrganisation != null && !typeOrganisation.isEmpty()) {
- query.append(" and typeOrganisation = :typeOrganisation");
- parameters.put("typeOrganisation", typeOrganisation);
+ /**
+ * Trouve une organisation par son email
+ *
+ * @param email l'email de l'organisation
+ * @return Optional contenant l'organisation si trouvée
+ */
+ public Optional findByEmail(String email) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT o FROM Organisation o WHERE o.email = :email", Organisation.class);
+ query.setParameter("email", email);
+ return query.getResultStream().findFirst();
}
- if (statut != null && !statut.isEmpty()) {
- query.append(" and statut = :statut");
- parameters.put("statut", statut);
+ /**
+ * Trouve une organisation par son nom
+ *
+ * @param nom le nom de l'organisation
+ * @return Optional contenant l'organisation si trouvée
+ */
+ public Optional findByNom(String nom) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT o FROM Organisation o WHERE o.nom = :nom", Organisation.class);
+ query.setParameter("nom", nom);
+ return query.getResultStream().findFirst();
}
- if (ville != null && !ville.isEmpty()) {
- query.append(" and lower(ville) like :ville");
- parameters.put("ville", "%" + ville.toLowerCase() + "%");
+ /**
+ * Trouve une organisation par son numéro d'enregistrement
+ *
+ * @param numeroEnregistrement le numéro d'enregistrement officiel
+ * @return Optional contenant l'organisation si trouvée
+ */
+ public Optional findByNumeroEnregistrement(String numeroEnregistrement) {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT o FROM Organisation o WHERE o.numeroEnregistrement = :numeroEnregistrement",
+ Organisation.class);
+ query.setParameter("numeroEnregistrement", numeroEnregistrement);
+ return query.getResultStream().findFirst();
}
- if (region != null && !region.isEmpty()) {
- query.append(" and lower(region) like :region");
- parameters.put("region", "%" + region.toLowerCase() + "%");
+ /**
+ * Trouve toutes les organisations actives
+ *
+ * @return liste des organisations actives
+ */
+ public List findAllActives() {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT o FROM Organisation o WHERE o.statut = 'ACTIVE' AND o.actif = true",
+ Organisation.class);
+ return query.getResultList();
}
- if (pays != null && !pays.isEmpty()) {
- query.append(" and lower(pays) like :pays");
- parameters.put("pays", "%" + pays.toLowerCase() + "%");
+ /**
+ * Trouve toutes les organisations actives avec pagination
+ *
+ * @param page pagination
+ * @param sort tri
+ * @return liste paginée des organisations actives
+ */
+ public List findAllActives(Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT o FROM Organisation o WHERE o.statut = 'ACTIVE' AND o.actif = true" + orderBy,
+ Organisation.class);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
}
- return find(query.toString(), Sort.by("nom").ascending(), parameters).page(page).list();
- }
+ /**
+ * Compte le nombre d'organisations actives
+ *
+ * @return nombre d'organisations actives
+ */
+ public long countActives() {
+ TypedQuery query = entityManager.createQuery(
+ "SELECT COUNT(o) FROM Organisation o WHERE o.statut = 'ACTIVE' AND o.actif = true",
+ Long.class);
+ return query.getSingleResult();
+ }
- /**
- * Compte les nouvelles organisations depuis une date donnée
- *
- * @param depuis date de référence
- * @return nombre de nouvelles organisations
- */
- public long countNouvellesOrganisations(LocalDate depuis) {
- return count("dateCreation >= ?1", depuis.atStartOfDay());
- }
+ /**
+ * Trouve les organisations par statut
+ *
+ * @param statut le statut recherché
+ * @param page pagination
+ * @param sort tri
+ * @return liste paginée des organisations avec le statut spécifié
+ */
+ public List findByStatut(String statut, Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT o FROM Organisation o WHERE o.statut = :statut" + orderBy,
+ Organisation.class);
+ query.setParameter("statut", statut);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
+ }
- /**
- * Trouve les organisations publiques (visibles dans l'annuaire)
- *
- * @param page pagination
- * @param sort tri
- * @return liste paginée des organisations publiques
- */
- public List findOrganisationsPubliques(Page page, Sort sort) {
- return find("organisationPublique = true and statut = 'ACTIVE' and actif = true", sort)
- .page(page)
- .list();
- }
+ /**
+ * Trouve les organisations par type
+ *
+ * @param typeOrganisation le type d'organisation
+ * @param page pagination
+ * @param sort tri
+ * @return liste paginée des organisations du type spécifié
+ */
+ public List findByType(String typeOrganisation, Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery query = entityManager.createQuery(
+ "SELECT o FROM Organisation o WHERE o.typeOrganisation = :typeOrganisation" + orderBy,
+ Organisation.class);
+ query.setParameter("typeOrganisation", typeOrganisation);
+ query.setFirstResult(page.index * page.size);
+ query.setMaxResults(page.size);
+ return query.getResultList();
+ }
- /**
- * Trouve les organisations acceptant de nouveaux membres
- *
- * @param page pagination
- * @param sort tri
- * @return liste paginée des organisations acceptant de nouveaux membres
- */
- public List findOrganisationsOuvertes(Page page, Sort sort) {
- return find("accepteNouveauxMembres = true and statut = 'ACTIVE' and actif = true", sort)
- .page(page)
- .list();
- }
+ /**
+ * Trouve les organisations par ville
+ *
+ * @param ville la ville
+ * @param page pagination
+ * @param sort tri
+ * @return liste paginée des organisations de la ville spécifiée
+ */
+ public List findByVille(String ville, Page page, Sort sort) {
+ String orderBy = sort != null ? " ORDER BY " + buildOrderBy(sort) : "";
+ TypedQuery