feat: PHASE 1 - Adresses et Rôles/Permissions
PHASE 1.1 - Entité Adresse: - Création entité Adresse avec types (SIEGE_SOCIAL, BUREAU, DOMICILE, AUTRE) - Relations flexibles: Organisation, Membre, Evenement - Enum TypeAdresse dans module API (DRY/WOU) - Repository et Service AdresseService - Relations bidirectionnelles mises à jour PHASE 1.2 - Système Rôles et Permissions: - Entité Role avec types (SYSTEME, ORGANISATION, PERSONNALISE) - Entité Permission avec structure MODULE > RESSOURCE > ACTION - Tables de liaison MembreRole et RolePermission - Repositories pour toutes les entités - Services RoleService et PermissionService - Relations bidirectionnelles dans Membre Respect strict DRY/WOU: - Enums dans module API réutilisables - Patterns de service cohérents - Relations JPA standardisées
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import dev.lions.unionflow.server.api.enums.adresse.TypeAdresse;
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Entité Adresse pour la gestion des adresses des organisations, membres et événements
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@Entity
|
||||
@Table(
|
||||
name = "adresses",
|
||||
indexes = {
|
||||
@Index(name = "idx_adresse_ville", columnList = "ville"),
|
||||
@Index(name = "idx_adresse_pays", columnList = "pays"),
|
||||
@Index(name = "idx_adresse_type", columnList = "type_adresse"),
|
||||
@Index(name = "idx_adresse_organisation", columnList = "organisation_id"),
|
||||
@Index(name = "idx_adresse_membre", columnList = "membre_id"),
|
||||
@Index(name = "idx_adresse_evenement", columnList = "evenement_id")
|
||||
})
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Adresse extends BaseEntity {
|
||||
|
||||
/** Type d'adresse */
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "type_adresse", nullable = false, length = 50)
|
||||
private dev.lions.unionflow.server.api.enums.adresse.TypeAdresse typeAdresse;
|
||||
|
||||
/** Adresse complète */
|
||||
@Column(name = "adresse", length = 500)
|
||||
private String adresse;
|
||||
|
||||
/** Complément d'adresse */
|
||||
@Column(name = "complement_adresse", length = 200)
|
||||
private String complementAdresse;
|
||||
|
||||
/** Code postal */
|
||||
@Column(name = "code_postal", length = 20)
|
||||
private String codePostal;
|
||||
|
||||
/** Ville */
|
||||
@Column(name = "ville", length = 100)
|
||||
private String ville;
|
||||
|
||||
/** Région */
|
||||
@Column(name = "region", length = 100)
|
||||
private String region;
|
||||
|
||||
/** Pays */
|
||||
@Column(name = "pays", length = 100)
|
||||
private String pays;
|
||||
|
||||
/** Coordonnées géographiques - Latitude */
|
||||
@DecimalMin(value = "-90.0", message = "La latitude doit être comprise entre -90 et 90")
|
||||
@DecimalMax(value = "90.0", message = "La latitude doit être comprise entre -90 et 90")
|
||||
@Digits(integer = 3, fraction = 6)
|
||||
@Column(name = "latitude", precision = 9, scale = 6)
|
||||
private BigDecimal latitude;
|
||||
|
||||
/** Coordonnées géographiques - Longitude */
|
||||
@DecimalMin(value = "-180.0", message = "La longitude doit être comprise entre -180 et 180")
|
||||
@DecimalMax(value = "180.0", message = "La longitude doit être comprise entre -180 et 180")
|
||||
@Digits(integer = 3, fraction = 6)
|
||||
@Column(name = "longitude", precision = 9, scale = 6)
|
||||
private BigDecimal longitude;
|
||||
|
||||
/** Adresse principale (une seule par entité) */
|
||||
@Builder.Default
|
||||
@Column(name = "principale", nullable = false)
|
||||
private Boolean principale = false;
|
||||
|
||||
/** Libellé personnalisé */
|
||||
@Column(name = "libelle", length = 100)
|
||||
private String libelle;
|
||||
|
||||
/** Notes et commentaires */
|
||||
@Column(name = "notes", length = 500)
|
||||
private String notes;
|
||||
|
||||
// Relations
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "organisation_id")
|
||||
private Organisation organisation;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "membre_id")
|
||||
private Membre membre;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "evenement_id")
|
||||
private Evenement evenement;
|
||||
|
||||
/** Méthode métier pour obtenir l'adresse complète formatée */
|
||||
public String getAdresseComplete() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (adresse != null && !adresse.isEmpty()) {
|
||||
sb.append(adresse);
|
||||
}
|
||||
if (complementAdresse != null && !complementAdresse.isEmpty()) {
|
||||
if (sb.length() > 0) sb.append(", ");
|
||||
sb.append(complementAdresse);
|
||||
}
|
||||
if (codePostal != null && !codePostal.isEmpty()) {
|
||||
if (sb.length() > 0) sb.append(", ");
|
||||
sb.append(codePostal);
|
||||
}
|
||||
if (ville != null && !ville.isEmpty()) {
|
||||
if (sb.length() > 0) sb.append(" ");
|
||||
sb.append(ville);
|
||||
}
|
||||
if (region != null && !region.isEmpty()) {
|
||||
if (sb.length() > 0) sb.append(", ");
|
||||
sb.append(region);
|
||||
}
|
||||
if (pays != null && !pays.isEmpty()) {
|
||||
if (sb.length() > 0) sb.append(", ");
|
||||
sb.append(pays);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/** Méthode métier pour vérifier si l'adresse a des coordonnées GPS */
|
||||
public boolean hasCoordinates() {
|
||||
return latitude != null && longitude != null;
|
||||
}
|
||||
|
||||
/** Callback JPA avant la persistance */
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
super.onCreate(); // Appelle le onCreate de BaseEntity
|
||||
if (typeAdresse == null) {
|
||||
typeAdresse = dev.lions.unionflow.server.api.enums.adresse.TypeAdresse.AUTRE;
|
||||
}
|
||||
if (principale == null) {
|
||||
principale = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,10 @@ public class Evenement extends BaseEntity {
|
||||
@Builder.Default
|
||||
private List<InscriptionEvenement> inscriptions = new ArrayList<>();
|
||||
|
||||
@OneToMany(mappedBy = "evenement", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
@Builder.Default
|
||||
private List<Adresse> adresses = new ArrayList<>();
|
||||
|
||||
/** Types d'événements */
|
||||
public enum TypeEvenement {
|
||||
ASSEMBLEE_GENERALE("Assemblée Générale"),
|
||||
|
||||
@@ -5,6 +5,8 @@ import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
@@ -67,6 +69,14 @@ public class Membre extends BaseEntity {
|
||||
@JoinColumn(name = "organisation_id")
|
||||
private Organisation organisation;
|
||||
|
||||
@OneToMany(mappedBy = "membre", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
@Builder.Default
|
||||
private List<Adresse> adresses = new ArrayList<>();
|
||||
|
||||
@OneToMany(mappedBy = "membre", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
@Builder.Default
|
||||
private List<MembreRole> roles = new ArrayList<>();
|
||||
|
||||
/** Méthode métier pour obtenir le nom complet */
|
||||
public String getNomComplet() {
|
||||
return prenom + " " + nom;
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.time.LocalDate;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Table de liaison entre Membre et Role
|
||||
* Permet à un membre d'avoir plusieurs rôles avec dates de début/fin
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@Entity
|
||||
@Table(
|
||||
name = "membres_roles",
|
||||
indexes = {
|
||||
@Index(name = "idx_membre_role_membre", columnList = "membre_id"),
|
||||
@Index(name = "idx_membre_role_role", columnList = "role_id"),
|
||||
@Index(name = "idx_membre_role_actif", columnList = "actif")
|
||||
},
|
||||
uniqueConstraints = {
|
||||
@UniqueConstraint(
|
||||
name = "uk_membre_role",
|
||||
columnNames = {"membre_id", "role_id"})
|
||||
})
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class MembreRole extends BaseEntity {
|
||||
|
||||
/** Membre */
|
||||
@NotNull
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "membre_id", nullable = false)
|
||||
private Membre membre;
|
||||
|
||||
/** Rôle */
|
||||
@NotNull
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "role_id", nullable = false)
|
||||
private Role role;
|
||||
|
||||
/** Date de début d'attribution */
|
||||
@Column(name = "date_debut")
|
||||
private LocalDate dateDebut;
|
||||
|
||||
/** Date de fin d'attribution (null = permanent) */
|
||||
@Column(name = "date_fin")
|
||||
private LocalDate dateFin;
|
||||
|
||||
/** Commentaire sur l'attribution */
|
||||
@Column(name = "commentaire", length = 500)
|
||||
private String commentaire;
|
||||
|
||||
/** Méthode métier pour vérifier si l'attribution est active */
|
||||
public boolean isActif() {
|
||||
if (!Boolean.TRUE.equals(getActif())) {
|
||||
return false;
|
||||
}
|
||||
LocalDate aujourdhui = LocalDate.now();
|
||||
if (dateDebut != null && aujourdhui.isBefore(dateDebut)) {
|
||||
return false;
|
||||
}
|
||||
if (dateFin != null && aujourdhui.isAfter(dateFin)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Callback JPA avant la persistance */
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
super.onCreate();
|
||||
if (dateDebut == null) {
|
||||
dateDebut = LocalDate.now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,6 +191,10 @@ public class Organisation extends BaseEntity {
|
||||
@Builder.Default
|
||||
private List<Membre> membres = new ArrayList<>();
|
||||
|
||||
@OneToMany(mappedBy = "organisation", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
@Builder.Default
|
||||
private List<Adresse> adresses = new ArrayList<>();
|
||||
|
||||
/** Méthode métier pour obtenir le nom complet avec sigle */
|
||||
public String getNomComplet() {
|
||||
if (nomCourt != null && !nomCourt.isEmpty()) {
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Entité Permission pour la gestion des permissions granulaires
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@Entity
|
||||
@Table(
|
||||
name = "permissions",
|
||||
indexes = {
|
||||
@Index(name = "idx_permission_code", columnList = "code", unique = true),
|
||||
@Index(name = "idx_permission_module", columnList = "module"),
|
||||
@Index(name = "idx_permission_ressource", columnList = "ressource")
|
||||
})
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Permission extends BaseEntity {
|
||||
|
||||
/** Code unique de la permission (format: MODULE > RESSOURCE > ACTION) */
|
||||
@NotBlank
|
||||
@Column(name = "code", unique = true, nullable = false, length = 100)
|
||||
private String code;
|
||||
|
||||
/** Module (ex: ORGANISATION, MEMBRE, COTISATION) */
|
||||
@NotBlank
|
||||
@Column(name = "module", nullable = false, length = 50)
|
||||
private String module;
|
||||
|
||||
/** Ressource (ex: MEMBRE, COTISATION, ADHESION) */
|
||||
@NotBlank
|
||||
@Column(name = "ressource", nullable = false, length = 50)
|
||||
private String ressource;
|
||||
|
||||
/** Action (ex: CREATE, READ, UPDATE, DELETE, VALIDATE) */
|
||||
@NotBlank
|
||||
@Column(name = "action", nullable = false, length = 50)
|
||||
private String action;
|
||||
|
||||
/** Libellé de la permission */
|
||||
@Column(name = "libelle", length = 200)
|
||||
private String libelle;
|
||||
|
||||
/** Description de la permission */
|
||||
@Column(name = "description", length = 500)
|
||||
private String description;
|
||||
|
||||
/** Rôles associés */
|
||||
@OneToMany(mappedBy = "permission", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
@Builder.Default
|
||||
private List<RolePermission> roles = new ArrayList<>();
|
||||
|
||||
/** Méthode métier pour générer le code à partir des composants */
|
||||
public static String genererCode(String module, String ressource, String action) {
|
||||
return String.format("%s > %s > %s", module.toUpperCase(), ressource.toUpperCase(), action.toUpperCase());
|
||||
}
|
||||
|
||||
/** Méthode métier pour vérifier si le code est valide */
|
||||
public boolean isCodeValide() {
|
||||
return code != null && code.contains(" > ") && code.split(" > ").length == 3;
|
||||
}
|
||||
|
||||
/** Callback JPA avant la persistance */
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
super.onCreate();
|
||||
// Générer le code si non fourni
|
||||
if (code == null || code.isEmpty()) {
|
||||
if (module != null && ressource != null && action != null) {
|
||||
code = genererCode(module, ressource, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Entité Role pour la gestion des rôles dans le système
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@Entity
|
||||
@Table(
|
||||
name = "roles",
|
||||
indexes = {
|
||||
@Index(name = "idx_role_code", columnList = "code", unique = true),
|
||||
@Index(name = "idx_role_actif", columnList = "actif"),
|
||||
@Index(name = "idx_role_niveau", columnList = "niveau_hierarchique")
|
||||
})
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Role extends BaseEntity {
|
||||
|
||||
/** Code unique du rôle */
|
||||
@NotBlank
|
||||
@Column(name = "code", unique = true, nullable = false, length = 50)
|
||||
private String code;
|
||||
|
||||
/** Libellé du rôle */
|
||||
@NotBlank
|
||||
@Column(name = "libelle", nullable = false, length = 100)
|
||||
private String libelle;
|
||||
|
||||
/** Description du rôle */
|
||||
@Column(name = "description", length = 500)
|
||||
private String description;
|
||||
|
||||
/** Niveau hiérarchique (plus bas = plus prioritaire) */
|
||||
@NotNull
|
||||
@Builder.Default
|
||||
@Column(name = "niveau_hierarchique", nullable = false)
|
||||
private Integer niveauHierarchique = 100;
|
||||
|
||||
/** Type de rôle */
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "type_role", nullable = false, length = 50)
|
||||
private TypeRole typeRole;
|
||||
|
||||
/** Organisation propriétaire (null pour rôles système) */
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "organisation_id")
|
||||
private Organisation organisation;
|
||||
|
||||
/** Permissions associées */
|
||||
@OneToMany(mappedBy = "role", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||
@Builder.Default
|
||||
private List<RolePermission> permissions = new ArrayList<>();
|
||||
|
||||
/** Énumération des types de rôle */
|
||||
public enum TypeRole {
|
||||
SYSTEME("Rôle Système"),
|
||||
ORGANISATION("Rôle Organisation"),
|
||||
PERSONNALISE("Rôle Personnalisé");
|
||||
|
||||
private final String libelle;
|
||||
|
||||
TypeRole(String libelle) {
|
||||
this.libelle = libelle;
|
||||
}
|
||||
|
||||
public String getLibelle() {
|
||||
return libelle;
|
||||
}
|
||||
}
|
||||
|
||||
/** Méthode métier pour vérifier si c'est un rôle système */
|
||||
public boolean isRoleSysteme() {
|
||||
return TypeRole.SYSTEME.equals(typeRole);
|
||||
}
|
||||
|
||||
/** Callback JPA avant la persistance */
|
||||
@PrePersist
|
||||
protected void onCreate() {
|
||||
super.onCreate();
|
||||
if (typeRole == null) {
|
||||
typeRole = TypeRole.PERSONNALISE;
|
||||
}
|
||||
if (niveauHierarchique == null) {
|
||||
niveauHierarchique = 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package dev.lions.unionflow.server.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* Table de liaison entre Role et Permission
|
||||
* Permet à un rôle d'avoir plusieurs permissions
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@Entity
|
||||
@Table(
|
||||
name = "roles_permissions",
|
||||
indexes = {
|
||||
@Index(name = "idx_role_permission_role", columnList = "role_id"),
|
||||
@Index(name = "idx_role_permission_permission", columnList = "permission_id")
|
||||
},
|
||||
uniqueConstraints = {
|
||||
@UniqueConstraint(
|
||||
name = "uk_role_permission",
|
||||
columnNames = {"role_id", "permission_id"})
|
||||
})
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RolePermission extends BaseEntity {
|
||||
|
||||
/** Rôle */
|
||||
@NotNull
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "role_id", nullable = false)
|
||||
private Role role;
|
||||
|
||||
/** Permission */
|
||||
@NotNull
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "permission_id", nullable = false)
|
||||
private Permission permission;
|
||||
|
||||
/** Commentaire sur l'association */
|
||||
@Column(name = "commentaire", length = 500)
|
||||
private String commentaire;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package dev.lions.unionflow.server.repository;
|
||||
|
||||
import dev.lions.unionflow.server.entity.Adresse;
|
||||
import dev.lions.unionflow.server.entity.Adresse.TypeAdresse;
|
||||
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Repository pour l'entité Adresse
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class AdresseRepository implements PanacheRepository<Adresse> {
|
||||
|
||||
/**
|
||||
* Trouve toutes les adresses d'une organisation
|
||||
*
|
||||
* @param organisationId ID de l'organisation
|
||||
* @return Liste des adresses
|
||||
*/
|
||||
public List<Adresse> findByOrganisationId(UUID organisationId) {
|
||||
return find("organisation.id", organisationId).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve l'adresse principale d'une organisation
|
||||
*
|
||||
* @param organisationId ID de l'organisation
|
||||
* @return Adresse principale ou Optional.empty()
|
||||
*/
|
||||
public Optional<Adresse> findPrincipaleByOrganisationId(UUID organisationId) {
|
||||
return find("organisation.id = ?1 AND principale = true", organisationId).firstResultOptional();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve toutes les adresses d'un membre
|
||||
*
|
||||
* @param membreId ID du membre
|
||||
* @return Liste des adresses
|
||||
*/
|
||||
public List<Adresse> findByMembreId(UUID membreId) {
|
||||
return find("membre.id", membreId).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve l'adresse principale d'un membre
|
||||
*
|
||||
* @param membreId ID du membre
|
||||
* @return Adresse principale ou Optional.empty()
|
||||
*/
|
||||
public Optional<Adresse> findPrincipaleByMembreId(UUID membreId) {
|
||||
return find("membre.id = ?1 AND principale = true", membreId).firstResultOptional();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve l'adresse d'un événement
|
||||
*
|
||||
* @param evenementId ID de l'événement
|
||||
* @return Adresse ou Optional.empty()
|
||||
*/
|
||||
public Optional<Adresse> findByEvenementId(UUID evenementId) {
|
||||
return find("evenement.id", evenementId).firstResultOptional();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve les adresses par type
|
||||
*
|
||||
* @param typeAdresse Type d'adresse
|
||||
* @return Liste des adresses
|
||||
*/
|
||||
public List<Adresse> findByType(TypeAdresse typeAdresse) {
|
||||
return find("typeAdresse", typeAdresse).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve les adresses par ville
|
||||
*
|
||||
* @param ville Nom de la ville
|
||||
* @return Liste des adresses
|
||||
*/
|
||||
public List<Adresse> findByVille(String ville) {
|
||||
return find("LOWER(ville) = LOWER(?1)", ville).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve les adresses par pays
|
||||
*
|
||||
* @param pays Nom du pays
|
||||
* @return Liste des adresses
|
||||
*/
|
||||
public List<Adresse> findByPays(String pays) {
|
||||
return find("LOWER(pays) = LOWER(?1)", pays).list();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package dev.lions.unionflow.server.repository;
|
||||
|
||||
import dev.lions.unionflow.server.entity.MembreRole;
|
||||
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Repository pour l'entité MembreRole
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class MembreRoleRepository implements PanacheRepository<MembreRole> {
|
||||
|
||||
/**
|
||||
* Trouve tous les rôles d'un membre
|
||||
*
|
||||
* @param membreId ID du membre
|
||||
* @return Liste des attributions de rôles
|
||||
*/
|
||||
public List<MembreRole> findByMembreId(UUID membreId) {
|
||||
return find("membre.id = ?1 AND actif = true", membreId).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve tous les rôles actifs d'un membre (dans la période valide)
|
||||
*
|
||||
* @param membreId ID du membre
|
||||
* @return Liste des attributions de rôles actives
|
||||
*/
|
||||
public List<MembreRole> findActifsByMembreId(UUID membreId) {
|
||||
LocalDate aujourdhui = LocalDate.now();
|
||||
return find(
|
||||
"membre.id = ?1 AND actif = true AND (dateDebut IS NULL OR dateDebut <= ?2) AND (dateFin IS NULL OR dateFin >= ?2)",
|
||||
membreId,
|
||||
aujourdhui)
|
||||
.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve tous les membres ayant un rôle spécifique
|
||||
*
|
||||
* @param roleId ID du rôle
|
||||
* @return Liste des attributions de rôles
|
||||
*/
|
||||
public List<MembreRole> findByRoleId(UUID roleId) {
|
||||
return find("role.id = ?1 AND actif = true", roleId).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve une attribution spécifique membre-role
|
||||
*
|
||||
* @param membreId ID du membre
|
||||
* @param roleId ID du rôle
|
||||
* @return Attribution ou null
|
||||
*/
|
||||
public MembreRole findByMembreAndRole(UUID membreId, UUID roleId) {
|
||||
return find("membre.id = ?1 AND role.id = ?2", membreId, roleId).firstResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package dev.lions.unionflow.server.repository;
|
||||
|
||||
import dev.lions.unionflow.server.entity.Permission;
|
||||
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Repository pour l'entité Permission
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class PermissionRepository implements PanacheRepository<Permission> {
|
||||
|
||||
/**
|
||||
* Trouve une permission par son code
|
||||
*
|
||||
* @param code Code de la permission
|
||||
* @return Permission ou Optional.empty()
|
||||
*/
|
||||
public Optional<Permission> findByCode(String code) {
|
||||
return find("code", code).firstResultOptional();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve les permissions par module
|
||||
*
|
||||
* @param module Nom du module
|
||||
* @return Liste des permissions
|
||||
*/
|
||||
public List<Permission> findByModule(String module) {
|
||||
return find("LOWER(module) = LOWER(?1) AND actif = true", module).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve les permissions par ressource
|
||||
*
|
||||
* @param ressource Nom de la ressource
|
||||
* @return Liste des permissions
|
||||
*/
|
||||
public List<Permission> findByRessource(String ressource) {
|
||||
return find("LOWER(ressource) = LOWER(?1) AND actif = true", ressource).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve les permissions par module et ressource
|
||||
*
|
||||
* @param module Nom du module
|
||||
* @param ressource Nom de la ressource
|
||||
* @return Liste des permissions
|
||||
*/
|
||||
public List<Permission> findByModuleAndRessource(String module, String ressource) {
|
||||
return find(
|
||||
"LOWER(module) = LOWER(?1) AND LOWER(ressource) = LOWER(?2) AND actif = true",
|
||||
module,
|
||||
ressource)
|
||||
.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve toutes les permissions actives
|
||||
*
|
||||
* @return Liste des permissions actives
|
||||
*/
|
||||
public List<Permission> findAllActives() {
|
||||
return find("actif = true").order("module ASC, ressource ASC, action ASC").list();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package dev.lions.unionflow.server.repository;
|
||||
|
||||
import dev.lions.unionflow.server.entity.RolePermission;
|
||||
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Repository pour l'entité RolePermission
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class RolePermissionRepository implements PanacheRepository<RolePermission> {
|
||||
|
||||
/**
|
||||
* Trouve toutes les permissions d'un rôle
|
||||
*
|
||||
* @param roleId ID du rôle
|
||||
* @return Liste des associations rôle-permission
|
||||
*/
|
||||
public List<RolePermission> findByRoleId(UUID roleId) {
|
||||
return find("role.id = ?1 AND actif = true", roleId).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve tous les rôles ayant une permission spécifique
|
||||
*
|
||||
* @param permissionId ID de la permission
|
||||
* @return Liste des associations rôle-permission
|
||||
*/
|
||||
public List<RolePermission> findByPermissionId(UUID permissionId) {
|
||||
return find("permission.id = ?1 AND actif = true", permissionId).list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve une association spécifique rôle-permission
|
||||
*
|
||||
* @param roleId ID du rôle
|
||||
* @param permissionId ID de la permission
|
||||
* @return Association ou null
|
||||
*/
|
||||
public RolePermission findByRoleAndPermission(UUID roleId, UUID permissionId) {
|
||||
return find("role.id = ?1 AND permission.id = ?2", roleId, permissionId).firstResult();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package dev.lions.unionflow.server.repository;
|
||||
|
||||
import dev.lions.unionflow.server.entity.Role;
|
||||
import dev.lions.unionflow.server.entity.Role.TypeRole;
|
||||
import io.quarkus.hibernate.orm.panache.PanacheRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Repository pour l'entité Role
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class RoleRepository implements PanacheRepository<Role> {
|
||||
|
||||
/**
|
||||
* Trouve un rôle par son code
|
||||
*
|
||||
* @param code Code du rôle
|
||||
* @return Rôle ou Optional.empty()
|
||||
*/
|
||||
public Optional<Role> findByCode(String code) {
|
||||
return find("code", code).firstResultOptional();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve tous les rôles système
|
||||
*
|
||||
* @return Liste des rôles système
|
||||
*/
|
||||
public List<Role> findRolesSysteme() {
|
||||
return find("typeRole = ?1 AND actif = true", TypeRole.SYSTEME)
|
||||
.order("niveauHierarchique ASC")
|
||||
.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve tous les rôles d'une organisation
|
||||
*
|
||||
* @param organisationId ID de l'organisation
|
||||
* @return Liste des rôles
|
||||
*/
|
||||
public List<Role> findByOrganisationId(UUID organisationId) {
|
||||
return find("organisation.id = ?1 AND actif = true", organisationId)
|
||||
.order("niveauHierarchique ASC")
|
||||
.list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve tous les rôles actifs
|
||||
*
|
||||
* @return Liste des rôles actifs
|
||||
*/
|
||||
public List<Role> findAllActifs() {
|
||||
return find("actif = true").order("niveauHierarchique ASC").list();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve les rôles par type
|
||||
*
|
||||
* @param typeRole Type de rôle
|
||||
* @return Liste des rôles
|
||||
*/
|
||||
public List<Role> findByType(TypeRole typeRole) {
|
||||
return find("typeRole = ?1 AND actif = true", typeRole)
|
||||
.order("niveauHierarchique ASC")
|
||||
.list();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
package dev.lions.unionflow.server.service;
|
||||
|
||||
import dev.lions.unionflow.server.api.dto.adresse.AdresseDTO;
|
||||
import dev.lions.unionflow.server.api.enums.adresse.TypeAdresse;
|
||||
import dev.lions.unionflow.server.entity.Adresse;
|
||||
import dev.lions.unionflow.server.entity.Evenement;
|
||||
import dev.lions.unionflow.server.entity.Membre;
|
||||
import dev.lions.unionflow.server.entity.Organisation;
|
||||
import dev.lions.unionflow.server.repository.AdresseRepository;
|
||||
import dev.lions.unionflow.server.repository.EvenementRepository;
|
||||
import dev.lions.unionflow.server.repository.MembreRepository;
|
||||
import dev.lions.unionflow.server.repository.OrganisationRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Service métier pour la gestion des adresses
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class AdresseService {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(AdresseService.class);
|
||||
|
||||
@Inject AdresseRepository adresseRepository;
|
||||
|
||||
@Inject OrganisationRepository organisationRepository;
|
||||
|
||||
@Inject MembreRepository membreRepository;
|
||||
|
||||
@Inject EvenementRepository evenementRepository;
|
||||
|
||||
/**
|
||||
* Crée une nouvelle adresse
|
||||
*
|
||||
* @param adresseDTO DTO de l'adresse à créer
|
||||
* @return DTO de l'adresse créée
|
||||
*/
|
||||
@Transactional
|
||||
public AdresseDTO creerAdresse(AdresseDTO adresseDTO) {
|
||||
LOG.infof("Création d'une nouvelle adresse de type: %s", adresseDTO.getTypeAdresse());
|
||||
|
||||
Adresse adresse = convertToEntity(adresseDTO);
|
||||
|
||||
// Gestion de l'adresse principale
|
||||
if (Boolean.TRUE.equals(adresseDTO.getPrincipale())) {
|
||||
desactiverAutresPrincipales(adresseDTO);
|
||||
}
|
||||
|
||||
adresseRepository.persist(adresse);
|
||||
LOG.infof("Adresse créée avec succès: ID=%s", adresse.getId());
|
||||
|
||||
return convertToDTO(adresse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour une adresse existante
|
||||
*
|
||||
* @param id ID de l'adresse
|
||||
* @param adresseDTO DTO avec les nouvelles données
|
||||
* @return DTO de l'adresse mise à jour
|
||||
*/
|
||||
@Transactional
|
||||
public AdresseDTO mettreAJourAdresse(UUID id, AdresseDTO adresseDTO) {
|
||||
LOG.infof("Mise à jour de l'adresse ID: %s", id);
|
||||
|
||||
Adresse adresse =
|
||||
adresseRepository
|
||||
.findByIdOptional(id)
|
||||
.orElseThrow(() -> new NotFoundException("Adresse non trouvée avec l'ID: " + id));
|
||||
|
||||
// Mise à jour des champs
|
||||
updateFromDTO(adresse, adresseDTO);
|
||||
|
||||
// Gestion de l'adresse principale
|
||||
if (Boolean.TRUE.equals(adresseDTO.getPrincipale())) {
|
||||
desactiverAutresPrincipales(adresseDTO);
|
||||
}
|
||||
|
||||
adresseRepository.persist(adresse);
|
||||
LOG.infof("Adresse mise à jour avec succès: ID=%s", id);
|
||||
|
||||
return convertToDTO(adresse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime une adresse
|
||||
*
|
||||
* @param id ID de l'adresse
|
||||
*/
|
||||
@Transactional
|
||||
public void supprimerAdresse(UUID id) {
|
||||
LOG.infof("Suppression de l'adresse ID: %s", id);
|
||||
|
||||
Adresse adresse =
|
||||
adresseRepository
|
||||
.findByIdOptional(id)
|
||||
.orElseThrow(() -> new NotFoundException("Adresse non trouvée avec l'ID: " + id));
|
||||
|
||||
adresseRepository.delete(adresse);
|
||||
LOG.infof("Adresse supprimée avec succès: ID=%s", id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve une adresse par son ID
|
||||
*
|
||||
* @param id ID de l'adresse
|
||||
* @return DTO de l'adresse
|
||||
*/
|
||||
public AdresseDTO trouverParId(UUID id) {
|
||||
return adresseRepository
|
||||
.findByIdOptional(id)
|
||||
.map(this::convertToDTO)
|
||||
.orElseThrow(() -> new NotFoundException("Adresse non trouvée avec l'ID: " + id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve toutes les adresses d'une organisation
|
||||
*
|
||||
* @param organisationId ID de l'organisation
|
||||
* @return Liste des adresses
|
||||
*/
|
||||
public List<AdresseDTO> trouverParOrganisation(UUID organisationId) {
|
||||
return adresseRepository.findByOrganisationId(organisationId).stream()
|
||||
.map(this::convertToDTO)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve toutes les adresses d'un membre
|
||||
*
|
||||
* @param membreId ID du membre
|
||||
* @return Liste des adresses
|
||||
*/
|
||||
public List<AdresseDTO> trouverParMembre(UUID membreId) {
|
||||
return adresseRepository.findByMembreId(membreId).stream()
|
||||
.map(this::convertToDTO)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve l'adresse d'un événement
|
||||
*
|
||||
* @param evenementId ID de l'événement
|
||||
* @return DTO de l'adresse ou null
|
||||
*/
|
||||
public AdresseDTO trouverParEvenement(UUID evenementId) {
|
||||
return adresseRepository
|
||||
.findByEvenementId(evenementId)
|
||||
.map(this::convertToDTO)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve l'adresse principale d'une organisation
|
||||
*
|
||||
* @param organisationId ID de l'organisation
|
||||
* @return DTO de l'adresse principale ou null
|
||||
*/
|
||||
public AdresseDTO trouverPrincipaleParOrganisation(UUID organisationId) {
|
||||
return adresseRepository
|
||||
.findPrincipaleByOrganisationId(organisationId)
|
||||
.map(this::convertToDTO)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve l'adresse principale d'un membre
|
||||
*
|
||||
* @param membreId ID du membre
|
||||
* @return DTO de l'adresse principale ou null
|
||||
*/
|
||||
public AdresseDTO trouverPrincipaleParMembre(UUID membreId) {
|
||||
return adresseRepository
|
||||
.findPrincipaleByMembreId(membreId)
|
||||
.map(this::convertToDTO)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// MÉTHODES PRIVÉES
|
||||
// ========================================
|
||||
|
||||
/** Désactive les autres adresses principales pour la même entité */
|
||||
private void desactiverAutresPrincipales(AdresseDTO adresseDTO) {
|
||||
List<Adresse> autresPrincipales;
|
||||
|
||||
if (adresseDTO.getOrganisationId() != null) {
|
||||
autresPrincipales =
|
||||
adresseRepository
|
||||
.find("organisation.id = ?1 AND principale = true", adresseDTO.getOrganisationId())
|
||||
.list();
|
||||
} else if (adresseDTO.getMembreId() != null) {
|
||||
autresPrincipales =
|
||||
adresseRepository
|
||||
.find("membre.id = ?1 AND principale = true", adresseDTO.getMembreId())
|
||||
.list();
|
||||
} else {
|
||||
return; // Pas d'entité associée
|
||||
}
|
||||
|
||||
autresPrincipales.forEach(adr -> adr.setPrincipale(false));
|
||||
}
|
||||
|
||||
/** Convertit une entité en DTO */
|
||||
private AdresseDTO convertToDTO(Adresse adresse) {
|
||||
if (adresse == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
AdresseDTO dto = new AdresseDTO();
|
||||
dto.setId(adresse.getId());
|
||||
dto.setTypeAdresse(convertTypeAdresse(adresse.getTypeAdresse()));
|
||||
dto.setAdresse(adresse.getAdresse());
|
||||
dto.setComplementAdresse(adresse.getComplementAdresse());
|
||||
dto.setCodePostal(adresse.getCodePostal());
|
||||
dto.setVille(adresse.getVille());
|
||||
dto.setRegion(adresse.getRegion());
|
||||
dto.setPays(adresse.getPays());
|
||||
dto.setLatitude(adresse.getLatitude());
|
||||
dto.setLongitude(adresse.getLongitude());
|
||||
dto.setPrincipale(adresse.getPrincipale());
|
||||
dto.setLibelle(adresse.getLibelle());
|
||||
dto.setNotes(adresse.getNotes());
|
||||
|
||||
if (adresse.getOrganisation() != null) {
|
||||
dto.setOrganisationId(adresse.getOrganisation().getId());
|
||||
}
|
||||
if (adresse.getMembre() != null) {
|
||||
dto.setMembreId(adresse.getMembre().getId());
|
||||
}
|
||||
if (adresse.getEvenement() != null) {
|
||||
dto.setEvenementId(adresse.getEvenement().getId());
|
||||
}
|
||||
|
||||
dto.setAdresseComplete(adresse.getAdresseComplete());
|
||||
dto.setDateCreation(adresse.getDateCreation());
|
||||
dto.setDateModification(adresse.getDateModification());
|
||||
dto.setActif(adresse.getActif());
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
/** Convertit un DTO en entité */
|
||||
private Adresse convertToEntity(AdresseDTO dto) {
|
||||
if (dto == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Adresse adresse = new Adresse();
|
||||
adresse.setTypeAdresse(convertTypeAdresse(dto.getTypeAdresse()));
|
||||
adresse.setAdresse(dto.getAdresse());
|
||||
adresse.setComplementAdresse(dto.getComplementAdresse());
|
||||
adresse.setCodePostal(dto.getCodePostal());
|
||||
adresse.setVille(dto.getVille());
|
||||
adresse.setRegion(dto.getRegion());
|
||||
adresse.setPays(dto.getPays());
|
||||
adresse.setLatitude(dto.getLatitude());
|
||||
adresse.setLongitude(dto.getLongitude());
|
||||
adresse.setPrincipale(dto.getPrincipale() != null ? dto.getPrincipale() : false);
|
||||
adresse.setLibelle(dto.getLibelle());
|
||||
adresse.setNotes(dto.getNotes());
|
||||
|
||||
// Relations
|
||||
if (dto.getOrganisationId() != null) {
|
||||
Organisation org =
|
||||
organisationRepository
|
||||
.findByIdOptional(dto.getOrganisationId())
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new NotFoundException(
|
||||
"Organisation non trouvée avec l'ID: " + dto.getOrganisationId()));
|
||||
adresse.setOrganisation(org);
|
||||
}
|
||||
|
||||
if (dto.getMembreId() != null) {
|
||||
Membre membre =
|
||||
membreRepository
|
||||
.findByIdOptional(dto.getMembreId())
|
||||
.orElseThrow(
|
||||
() -> new NotFoundException("Membre non trouvé avec l'ID: " + dto.getMembreId()));
|
||||
adresse.setMembre(membre);
|
||||
}
|
||||
|
||||
if (dto.getEvenementId() != null) {
|
||||
Evenement evenement =
|
||||
evenementRepository
|
||||
.findByIdOptional(dto.getEvenementId())
|
||||
.orElseThrow(
|
||||
() ->
|
||||
new NotFoundException(
|
||||
"Événement non trouvé avec l'ID: " + dto.getEvenementId()));
|
||||
adresse.setEvenement(evenement);
|
||||
}
|
||||
|
||||
return adresse;
|
||||
}
|
||||
|
||||
/** Met à jour une entité à partir d'un DTO */
|
||||
private void updateFromDTO(Adresse adresse, AdresseDTO dto) {
|
||||
if (dto.getTypeAdresse() != null) {
|
||||
adresse.setTypeAdresse(convertTypeAdresse(dto.getTypeAdresse()));
|
||||
}
|
||||
if (dto.getAdresse() != null) {
|
||||
adresse.setAdresse(dto.getAdresse());
|
||||
}
|
||||
if (dto.getComplementAdresse() != null) {
|
||||
adresse.setComplementAdresse(dto.getComplementAdresse());
|
||||
}
|
||||
if (dto.getCodePostal() != null) {
|
||||
adresse.setCodePostal(dto.getCodePostal());
|
||||
}
|
||||
if (dto.getVille() != null) {
|
||||
adresse.setVille(dto.getVille());
|
||||
}
|
||||
if (dto.getRegion() != null) {
|
||||
adresse.setRegion(dto.getRegion());
|
||||
}
|
||||
if (dto.getPays() != null) {
|
||||
adresse.setPays(dto.getPays());
|
||||
}
|
||||
if (dto.getLatitude() != null) {
|
||||
adresse.setLatitude(dto.getLatitude());
|
||||
}
|
||||
if (dto.getLongitude() != null) {
|
||||
adresse.setLongitude(dto.getLongitude());
|
||||
}
|
||||
if (dto.getPrincipale() != null) {
|
||||
adresse.setPrincipale(dto.getPrincipale());
|
||||
}
|
||||
if (dto.getLibelle() != null) {
|
||||
adresse.setLibelle(dto.getLibelle());
|
||||
}
|
||||
if (dto.getNotes() != null) {
|
||||
adresse.setNotes(dto.getNotes());
|
||||
}
|
||||
}
|
||||
|
||||
/** Convertit TypeAdresse (entité) vers TypeAdresse (DTO) - même enum, pas de conversion nécessaire */
|
||||
private TypeAdresse convertTypeAdresse(TypeAdresse type) {
|
||||
return type; // Même enum, pas de conversion nécessaire
|
||||
}
|
||||
|
||||
/** Convertit TypeAdresse (DTO) vers TypeAdresse (entité) - même enum, pas de conversion nécessaire */
|
||||
private TypeAdresse convertTypeAdresse(TypeAdresse type) {
|
||||
return type != null ? type : TypeAdresse.AUTRE; // Même enum, valeur par défaut si null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
package dev.lions.unionflow.server.service;
|
||||
|
||||
import dev.lions.unionflow.server.entity.Permission;
|
||||
import dev.lions.unionflow.server.repository.PermissionRepository;
|
||||
import dev.lions.unionflow.server.service.KeycloakService;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Service métier pour la gestion des permissions
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class PermissionService {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(PermissionService.class);
|
||||
|
||||
@Inject PermissionRepository permissionRepository;
|
||||
|
||||
@Inject KeycloakService keycloakService;
|
||||
|
||||
/**
|
||||
* Crée une nouvelle permission
|
||||
*
|
||||
* @param permission Permission à créer
|
||||
* @return Permission créée
|
||||
*/
|
||||
@Transactional
|
||||
public Permission creerPermission(Permission permission) {
|
||||
LOG.infof("Création d'une nouvelle permission: %s", permission.getCode());
|
||||
|
||||
// Vérifier l'unicité du code
|
||||
if (permissionRepository.findByCode(permission.getCode()).isPresent()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Une permission avec ce code existe déjà: " + permission.getCode());
|
||||
}
|
||||
|
||||
// Générer le code si non fourni
|
||||
if (permission.getCode() == null || permission.getCode().isEmpty()) {
|
||||
permission.setCode(
|
||||
Permission.genererCode(
|
||||
permission.getModule(), permission.getRessource(), permission.getAction()));
|
||||
}
|
||||
|
||||
// Métadonnées
|
||||
permission.setCreePar(keycloakService.getCurrentUserEmail());
|
||||
|
||||
permissionRepository.persist(permission);
|
||||
LOG.infof(
|
||||
"Permission créée avec succès: ID=%s, Code=%s",
|
||||
permission.getId(), permission.getCode());
|
||||
|
||||
return permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour une permission existante
|
||||
*
|
||||
* @param id ID de la permission
|
||||
* @param permissionModifiee Permission avec les modifications
|
||||
* @return Permission mise à jour
|
||||
*/
|
||||
@Transactional
|
||||
public Permission mettreAJourPermission(UUID id, Permission permissionModifiee) {
|
||||
LOG.infof("Mise à jour de la permission ID: %s", id);
|
||||
|
||||
Permission permission =
|
||||
permissionRepository
|
||||
.findByIdOptional(id)
|
||||
.orElseThrow(() -> new NotFoundException("Permission non trouvée avec l'ID: " + id));
|
||||
|
||||
// Mise à jour
|
||||
permission.setCode(permissionModifiee.getCode());
|
||||
permission.setModule(permissionModifiee.getModule());
|
||||
permission.setRessource(permissionModifiee.getRessource());
|
||||
permission.setAction(permissionModifiee.getAction());
|
||||
permission.setLibelle(permissionModifiee.getLibelle());
|
||||
permission.setDescription(permissionModifiee.getDescription());
|
||||
permission.setModifiePar(keycloakService.getCurrentUserEmail());
|
||||
|
||||
permissionRepository.persist(permission);
|
||||
LOG.infof("Permission mise à jour avec succès: ID=%s", id);
|
||||
|
||||
return permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve une permission par son ID
|
||||
*
|
||||
* @param id ID de la permission
|
||||
* @return Permission ou null
|
||||
*/
|
||||
public Permission trouverParId(UUID id) {
|
||||
return permissionRepository.findByIdOptional(id).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve une permission par son code
|
||||
*
|
||||
* @param code Code de la permission
|
||||
* @return Permission ou null
|
||||
*/
|
||||
public Permission trouverParCode(String code) {
|
||||
return permissionRepository.findByCode(code).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Liste les permissions par module
|
||||
*
|
||||
* @param module Nom du module
|
||||
* @return Liste des permissions
|
||||
*/
|
||||
public List<Permission> listerParModule(String module) {
|
||||
return permissionRepository.findByModule(module);
|
||||
}
|
||||
|
||||
/**
|
||||
* Liste les permissions par ressource
|
||||
*
|
||||
* @param ressource Nom de la ressource
|
||||
* @return Liste des permissions
|
||||
*/
|
||||
public List<Permission> listerParRessource(String ressource) {
|
||||
return permissionRepository.findByRessource(ressource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Liste toutes les permissions actives
|
||||
*
|
||||
* @return Liste des permissions actives
|
||||
*/
|
||||
public List<Permission> listerToutesActives() {
|
||||
return permissionRepository.findAllActives();
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime (désactive) une permission
|
||||
*
|
||||
* @param id ID de la permission
|
||||
*/
|
||||
@Transactional
|
||||
public void supprimerPermission(UUID id) {
|
||||
LOG.infof("Suppression de la permission ID: %s", id);
|
||||
|
||||
Permission permission =
|
||||
permissionRepository
|
||||
.findByIdOptional(id)
|
||||
.orElseThrow(() -> new NotFoundException("Permission non trouvée avec l'ID: " + id));
|
||||
|
||||
permission.setActif(false);
|
||||
permission.setModifiePar(keycloakService.getCurrentUserEmail());
|
||||
|
||||
permissionRepository.persist(permission);
|
||||
LOG.infof("Permission supprimée avec succès: ID=%s", id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
package dev.lions.unionflow.server.service;
|
||||
|
||||
import dev.lions.unionflow.server.entity.Organisation;
|
||||
import dev.lions.unionflow.server.entity.Role;
|
||||
import dev.lions.unionflow.server.entity.Role.TypeRole;
|
||||
import dev.lions.unionflow.server.repository.OrganisationRepository;
|
||||
import dev.lions.unionflow.server.repository.RoleRepository;
|
||||
import dev.lions.unionflow.server.service.KeycloakService;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* Service métier pour la gestion des rôles
|
||||
*
|
||||
* @author UnionFlow Team
|
||||
* @version 3.0
|
||||
* @since 2025-01-29
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class RoleService {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(RoleService.class);
|
||||
|
||||
@Inject RoleRepository roleRepository;
|
||||
|
||||
@Inject OrganisationRepository organisationRepository;
|
||||
|
||||
@Inject KeycloakService keycloakService;
|
||||
|
||||
/**
|
||||
* Crée un nouveau rôle
|
||||
*
|
||||
* @param role Rôle à créer
|
||||
* @return Rôle créé
|
||||
*/
|
||||
@Transactional
|
||||
public Role creerRole(Role role) {
|
||||
LOG.infof("Création d'un nouveau rôle: %s", role.getCode());
|
||||
|
||||
// Vérifier l'unicité du code
|
||||
if (roleRepository.findByCode(role.getCode()).isPresent()) {
|
||||
throw new IllegalArgumentException("Un rôle avec ce code existe déjà: " + role.getCode());
|
||||
}
|
||||
|
||||
// Métadonnées
|
||||
role.setCreePar(keycloakService.getCurrentUserEmail());
|
||||
|
||||
roleRepository.persist(role);
|
||||
LOG.infof("Rôle créé avec succès: ID=%s, Code=%s", role.getId(), role.getCode());
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour un rôle existant
|
||||
*
|
||||
* @param id ID du rôle
|
||||
* @param roleModifie Rôle avec les modifications
|
||||
* @return Rôle mis à jour
|
||||
*/
|
||||
@Transactional
|
||||
public Role mettreAJourRole(UUID id, Role roleModifie) {
|
||||
LOG.infof("Mise à jour du rôle ID: %s", id);
|
||||
|
||||
Role role =
|
||||
roleRepository
|
||||
.findByIdOptional(id)
|
||||
.orElseThrow(() -> new NotFoundException("Rôle non trouvé avec l'ID: " + id));
|
||||
|
||||
// Vérifier l'unicité du code si modifié
|
||||
if (!role.getCode().equals(roleModifie.getCode())) {
|
||||
if (roleRepository.findByCode(roleModifie.getCode()).isPresent()) {
|
||||
throw new IllegalArgumentException("Un rôle avec ce code existe déjà: " + roleModifie.getCode());
|
||||
}
|
||||
}
|
||||
|
||||
// Mise à jour
|
||||
role.setCode(roleModifie.getCode());
|
||||
role.setLibelle(roleModifie.getLibelle());
|
||||
role.setDescription(roleModifie.getDescription());
|
||||
role.setNiveauHierarchique(roleModifie.getNiveauHierarchique());
|
||||
role.setTypeRole(roleModifie.getTypeRole());
|
||||
role.setOrganisation(roleModifie.getOrganisation());
|
||||
role.setModifiePar(keycloakService.getCurrentUserEmail());
|
||||
|
||||
roleRepository.persist(role);
|
||||
LOG.infof("Rôle mis à jour avec succès: ID=%s", id);
|
||||
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve un rôle par son ID
|
||||
*
|
||||
* @param id ID du rôle
|
||||
* @return Rôle ou null
|
||||
*/
|
||||
public Role trouverParId(UUID id) {
|
||||
return roleRepository.findByIdOptional(id).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve un rôle par son code
|
||||
*
|
||||
* @param code Code du rôle
|
||||
* @return Rôle ou null
|
||||
*/
|
||||
public Role trouverParCode(String code) {
|
||||
return roleRepository.findByCode(code).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Liste tous les rôles système
|
||||
*
|
||||
* @return Liste des rôles système
|
||||
*/
|
||||
public List<Role> listerRolesSysteme() {
|
||||
return roleRepository.findRolesSysteme();
|
||||
}
|
||||
|
||||
/**
|
||||
* Liste tous les rôles d'une organisation
|
||||
*
|
||||
* @param organisationId ID de l'organisation
|
||||
* @return Liste des rôles
|
||||
*/
|
||||
public List<Role> listerParOrganisation(UUID organisationId) {
|
||||
return roleRepository.findByOrganisationId(organisationId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Liste tous les rôles actifs
|
||||
*
|
||||
* @return Liste des rôles actifs
|
||||
*/
|
||||
public List<Role> listerTousActifs() {
|
||||
return roleRepository.findAllActifs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime (désactive) un rôle
|
||||
*
|
||||
* @param id ID du rôle
|
||||
*/
|
||||
@Transactional
|
||||
public void supprimerRole(UUID id) {
|
||||
LOG.infof("Suppression du rôle ID: %s", id);
|
||||
|
||||
Role role =
|
||||
roleRepository
|
||||
.findByIdOptional(id)
|
||||
.orElseThrow(() -> new NotFoundException("Rôle non trouvé avec l'ID: " + id));
|
||||
|
||||
// Vérifier si c'est un rôle système
|
||||
if (role.isRoleSysteme()) {
|
||||
throw new IllegalStateException("Impossible de supprimer un rôle système");
|
||||
}
|
||||
|
||||
role.setActif(false);
|
||||
role.setModifiePar(keycloakService.getCurrentUserEmail());
|
||||
|
||||
roleRepository.persist(role);
|
||||
LOG.infof("Rôle supprimé avec succès: ID=%s", id);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user