Task 1.1 - DTOs et Interfaces API de base
- Création de tous les DTOs d'authentification (LoginRequestDTO, LoginResponseDTO, TokenDTO, PasswordResetDTO) - Création des DTOs utilisateur (UserDTO, CreateUserDTO, UpdateUserDTO) - Création des DTOs communs (PagedResultDTO, ErrorResponseDTO, SuccessResponseDTO) - Création de toutes les classes d'exception (GBCMException, AuthenticationException, AuthorizationException, ValidationException, ResourceNotFoundException, BusinessRuleException) - Création des enums métier (ServiceType, WorkshopPackage, PaymentStatus, SessionStatus, InvoiceStatus) - Amélioration de l'interface AuthService avec documentation complète - Création de l'interface UserService avec tous les endpoints CRUD - Documentation Javadoc complète en français sur toutes les classes - Annotations OpenAPI/Swagger sur toutes les interfaces - Validation Jakarta sur tous les DTOs - Compilation réussie du module API
This commit is contained in:
28
pom.xml
28
pom.xml
@@ -39,6 +39,13 @@
|
||||
<version>${jakarta.ws.rs.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jakarta Annotation (for @RolesAllowed) -->
|
||||
<dependency>
|
||||
<groupId>jakarta.annotation</groupId>
|
||||
<artifactId>jakarta.annotation-api</artifactId>
|
||||
<version>2.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Jackson Annotations -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
@@ -70,26 +77,7 @@
|
||||
<version>3.11.0</version>
|
||||
</plugin>
|
||||
|
||||
<!-- OpenAPI Generator Plugin -->
|
||||
<plugin>
|
||||
<groupId>org.openapitools</groupId>
|
||||
<artifactId>openapi-generator-maven-plugin</artifactId>
|
||||
<version>7.0.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>generate</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<inputSpec>${project.basedir}/src/main/resources/META-INF/openapi.yaml</inputSpec>
|
||||
<generatorName>java</generatorName>
|
||||
<configOptions>
|
||||
<sourceFolder>src/gen/java/main</sourceFolder>
|
||||
</configOptions>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -1,72 +1,148 @@
|
||||
package com.gbcm.server.api.dto.auth;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* DTO pour les requêtes de connexion
|
||||
* DTO pour les requêtes de connexion utilisateur.
|
||||
* Contient les informations d'authentification nécessaires pour se connecter à la plateforme GBCM.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Schema(description = "Requête de connexion utilisateur")
|
||||
@Schema(description = "Requête de connexion utilisateur à la plateforme GBCM")
|
||||
public class LoginRequestDTO {
|
||||
|
||||
@Schema(description = "Adresse email de l'utilisateur", example = "user@gbcm.com")
|
||||
/**
|
||||
* Adresse email de l'utilisateur.
|
||||
* Doit être un email valide et non vide.
|
||||
*/
|
||||
@Schema(description = "Adresse email de l'utilisateur",
|
||||
example = "john.doe@gbcm.com",
|
||||
required = true,
|
||||
maxLength = 255)
|
||||
@JsonProperty("email")
|
||||
@NotBlank(message = "L'email est obligatoire")
|
||||
@Email(message = "Format d'email invalide")
|
||||
private String email;
|
||||
|
||||
@Schema(description = "Mot de passe", example = "password123")
|
||||
/**
|
||||
* Mot de passe de l'utilisateur.
|
||||
* Doit contenir entre 6 et 100 caractères.
|
||||
*/
|
||||
@Schema(description = "Mot de passe de l'utilisateur",
|
||||
example = "motdepasse123",
|
||||
required = true,
|
||||
minLength = 6,
|
||||
maxLength = 100)
|
||||
@JsonProperty("password")
|
||||
@NotBlank(message = "Le mot de passe est obligatoire")
|
||||
@Size(min = 6, max = 100, message = "Le mot de passe doit contenir entre 6 et 100 caractères")
|
||||
private String password;
|
||||
|
||||
@Schema(description = "Se souvenir de moi", example = "true")
|
||||
/**
|
||||
* Indicateur pour maintenir la session active plus longtemps.
|
||||
* Si true, le token JWT aura une durée de vie étendue.
|
||||
*/
|
||||
@Schema(description = "Se souvenir de moi pour une session prolongée",
|
||||
example = "false",
|
||||
defaultValue = "false")
|
||||
@JsonProperty("rememberMe")
|
||||
private boolean rememberMe = false;
|
||||
|
||||
// Constructeurs
|
||||
/**
|
||||
* Constructeur par défaut.
|
||||
*/
|
||||
public LoginRequestDTO() {}
|
||||
|
||||
/**
|
||||
* Constructeur avec email et mot de passe.
|
||||
*
|
||||
* @param email l'adresse email de l'utilisateur
|
||||
* @param password le mot de passe de l'utilisateur
|
||||
*/
|
||||
public LoginRequestDTO(String email, String password) {
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur complet.
|
||||
*
|
||||
* @param email l'adresse email de l'utilisateur
|
||||
* @param password le mot de passe de l'utilisateur
|
||||
* @param rememberMe indicateur pour session prolongée
|
||||
*/
|
||||
public LoginRequestDTO(String email, String password, boolean rememberMe) {
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
this.rememberMe = rememberMe;
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
/**
|
||||
* Retourne l'adresse email de l'utilisateur.
|
||||
*
|
||||
* @return l'adresse email
|
||||
*/
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit l'adresse email de l'utilisateur.
|
||||
*
|
||||
* @param email l'adresse email à définir
|
||||
*/
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le mot de passe de l'utilisateur.
|
||||
*
|
||||
* @return le mot de passe
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le mot de passe de l'utilisateur.
|
||||
*
|
||||
* @param password le mot de passe à définir
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indique si l'option "se souvenir de moi" est activée.
|
||||
*
|
||||
* @return true si l'option est activée, false sinon
|
||||
*/
|
||||
public boolean isRememberMe() {
|
||||
return rememberMe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit l'option "se souvenir de moi".
|
||||
*
|
||||
* @param rememberMe true pour activer l'option, false sinon
|
||||
*/
|
||||
public void setRememberMe(boolean rememberMe) {
|
||||
this.rememberMe = rememberMe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'objet (sans le mot de passe pour la sécurité).
|
||||
*
|
||||
* @return une chaîne représentant l'objet
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LoginRequestDTO{" +
|
||||
|
||||
@@ -1,49 +1,100 @@
|
||||
package com.gbcm.server.api.dto.auth;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.gbcm.server.api.dto.user.UserDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.gbcm.server.api.dto.user.UserDTO;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* DTO pour les réponses de connexion
|
||||
* DTO pour les réponses de connexion utilisateur.
|
||||
* Contient le résultat de l'authentification avec les tokens et informations utilisateur.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Schema(description = "Réponse de connexion utilisateur")
|
||||
@Schema(description = "Réponse de connexion utilisateur à la plateforme GBCM")
|
||||
public class LoginResponseDTO {
|
||||
|
||||
@Schema(description = "Succès de la connexion", example = "true")
|
||||
/**
|
||||
* Indicateur de succès de la connexion.
|
||||
*/
|
||||
@Schema(description = "Succès de la connexion",
|
||||
example = "true",
|
||||
required = true)
|
||||
@JsonProperty("success")
|
||||
private boolean success;
|
||||
|
||||
@Schema(description = "Message de réponse", example = "Connexion réussie")
|
||||
/**
|
||||
* Message descriptif du résultat de la connexion.
|
||||
*/
|
||||
@Schema(description = "Message de réponse",
|
||||
example = "Connexion réussie",
|
||||
required = true)
|
||||
@JsonProperty("message")
|
||||
private String message;
|
||||
|
||||
@Schema(description = "Token d'authentification JWT")
|
||||
/**
|
||||
* Token JWT pour l'authentification des requêtes API.
|
||||
* Présent seulement en cas de connexion réussie.
|
||||
*/
|
||||
@Schema(description = "Token d'authentification JWT",
|
||||
example = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...")
|
||||
@JsonProperty("token")
|
||||
private String token;
|
||||
|
||||
@Schema(description = "Date d'expiration du token")
|
||||
/**
|
||||
* Date et heure d'expiration du token.
|
||||
* Présent seulement en cas de connexion réussie.
|
||||
*/
|
||||
@Schema(description = "Date d'expiration du token",
|
||||
example = "2024-12-31T23:59:59")
|
||||
@JsonProperty("expiresAt")
|
||||
private LocalDateTime expiresAt;
|
||||
|
||||
/**
|
||||
* Informations détaillées de l'utilisateur connecté.
|
||||
* Présent seulement en cas de connexion réussie.
|
||||
*/
|
||||
@Schema(description = "Informations utilisateur")
|
||||
@JsonProperty("user")
|
||||
private UserDTO user;
|
||||
|
||||
@Schema(description = "Token de rafraîchissement")
|
||||
/**
|
||||
* Token de rafraîchissement pour renouveler le token principal.
|
||||
* Présent seulement si "rememberMe" était activé.
|
||||
*/
|
||||
@Schema(description = "Token de rafraîchissement",
|
||||
example = "refresh_token_abc123")
|
||||
@JsonProperty("refreshToken")
|
||||
private String refreshToken;
|
||||
|
||||
// Constructeurs
|
||||
/**
|
||||
* Constructeur par défaut.
|
||||
*/
|
||||
public LoginResponseDTO() {}
|
||||
|
||||
/**
|
||||
* Constructeur avec succès et message.
|
||||
*
|
||||
* @param success indicateur de succès
|
||||
* @param message message descriptif
|
||||
*/
|
||||
public LoginResponseDTO(boolean success, String message) {
|
||||
this.success = success;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse de connexion réussie avec token et utilisateur.
|
||||
*
|
||||
* @param token le token JWT généré
|
||||
* @param expiresAt la date d'expiration du token
|
||||
* @param user les informations de l'utilisateur connecté
|
||||
* @return une réponse de succès configurée
|
||||
*/
|
||||
public static LoginResponseDTO success(String token, LocalDateTime expiresAt, UserDTO user) {
|
||||
LoginResponseDTO response = new LoginResponseDTO(true, "Connexion réussie");
|
||||
response.setToken(token);
|
||||
@@ -52,6 +103,27 @@ public class LoginResponseDTO {
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse de connexion réussie avec token, utilisateur et refresh token.
|
||||
*
|
||||
* @param token le token JWT généré
|
||||
* @param expiresAt la date d'expiration du token
|
||||
* @param user les informations de l'utilisateur connecté
|
||||
* @param refreshToken le token de rafraîchissement
|
||||
* @return une réponse de succès configurée
|
||||
*/
|
||||
public static LoginResponseDTO success(String token, LocalDateTime expiresAt, UserDTO user, String refreshToken) {
|
||||
LoginResponseDTO response = success(token, expiresAt, user);
|
||||
response.setRefreshToken(refreshToken);
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse d'échec de connexion.
|
||||
*
|
||||
* @param message le message d'erreur
|
||||
* @return une réponse d'échec configurée
|
||||
*/
|
||||
public static LoginResponseDTO failure(String message) {
|
||||
return new LoginResponseDTO(false, message);
|
||||
}
|
||||
|
||||
214
src/main/java/com/gbcm/server/api/dto/auth/PasswordResetDTO.java
Normal file
214
src/main/java/com/gbcm/server/api/dto/auth/PasswordResetDTO.java
Normal file
@@ -0,0 +1,214 @@
|
||||
package com.gbcm.server.api.dto.auth;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* DTO pour les demandes de réinitialisation de mot de passe.
|
||||
* Utilisé pour les étapes de demande et de confirmation de réinitialisation.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Schema(description = "Demande de réinitialisation de mot de passe")
|
||||
public class PasswordResetDTO {
|
||||
|
||||
/**
|
||||
* Adresse email de l'utilisateur demandant la réinitialisation.
|
||||
* Obligatoire pour la demande initiale.
|
||||
*/
|
||||
@Schema(description = "Adresse email de l'utilisateur",
|
||||
example = "john.doe@gbcm.com")
|
||||
@JsonProperty("email")
|
||||
@Email(message = "Format d'email invalide")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* Token de réinitialisation reçu par email.
|
||||
* Obligatoire pour confirmer la réinitialisation.
|
||||
*/
|
||||
@Schema(description = "Token de réinitialisation reçu par email",
|
||||
example = "abc123def456")
|
||||
@JsonProperty("resetToken")
|
||||
private String resetToken;
|
||||
|
||||
/**
|
||||
* Nouveau mot de passe choisi par l'utilisateur.
|
||||
* Obligatoire pour confirmer la réinitialisation.
|
||||
*/
|
||||
@Schema(description = "Nouveau mot de passe",
|
||||
example = "nouveauMotDePasse123")
|
||||
@JsonProperty("newPassword")
|
||||
@Size(min = 6, max = 100, message = "Le mot de passe doit contenir entre 6 et 100 caractères")
|
||||
private String newPassword;
|
||||
|
||||
/**
|
||||
* Confirmation du nouveau mot de passe.
|
||||
* Doit être identique au nouveau mot de passe.
|
||||
*/
|
||||
@Schema(description = "Confirmation du nouveau mot de passe",
|
||||
example = "nouveauMotDePasse123")
|
||||
@JsonProperty("confirmPassword")
|
||||
@Size(min = 6, max = 100, message = "La confirmation doit contenir entre 6 et 100 caractères")
|
||||
private String confirmPassword;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut.
|
||||
*/
|
||||
public PasswordResetDTO() {}
|
||||
|
||||
/**
|
||||
* Constructeur pour demande de réinitialisation.
|
||||
*
|
||||
* @param email l'adresse email de l'utilisateur
|
||||
*/
|
||||
public PasswordResetDTO(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur pour confirmation de réinitialisation.
|
||||
*
|
||||
* @param resetToken le token de réinitialisation
|
||||
* @param newPassword le nouveau mot de passe
|
||||
* @param confirmPassword la confirmation du mot de passe
|
||||
*/
|
||||
public PasswordResetDTO(String resetToken, String newPassword, String confirmPassword) {
|
||||
this.resetToken = resetToken;
|
||||
this.newPassword = newPassword;
|
||||
this.confirmPassword = confirmPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur complet.
|
||||
*
|
||||
* @param email l'adresse email
|
||||
* @param resetToken le token de réinitialisation
|
||||
* @param newPassword le nouveau mot de passe
|
||||
* @param confirmPassword la confirmation du mot de passe
|
||||
*/
|
||||
public PasswordResetDTO(String email, String resetToken, String newPassword, String confirmPassword) {
|
||||
this.email = email;
|
||||
this.resetToken = resetToken;
|
||||
this.newPassword = newPassword;
|
||||
this.confirmPassword = confirmPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'adresse email de l'utilisateur.
|
||||
*
|
||||
* @return l'adresse email
|
||||
*/
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit l'adresse email de l'utilisateur.
|
||||
*
|
||||
* @param email l'adresse email à définir
|
||||
*/
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le token de réinitialisation.
|
||||
*
|
||||
* @return le token de réinitialisation
|
||||
*/
|
||||
public String getResetToken() {
|
||||
return resetToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le token de réinitialisation.
|
||||
*
|
||||
* @param resetToken le token de réinitialisation à définir
|
||||
*/
|
||||
public void setResetToken(String resetToken) {
|
||||
this.resetToken = resetToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nouveau mot de passe.
|
||||
*
|
||||
* @return le nouveau mot de passe
|
||||
*/
|
||||
public String getNewPassword() {
|
||||
return newPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le nouveau mot de passe.
|
||||
*
|
||||
* @param newPassword le nouveau mot de passe à définir
|
||||
*/
|
||||
public void setNewPassword(String newPassword) {
|
||||
this.newPassword = newPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la confirmation du mot de passe.
|
||||
*
|
||||
* @return la confirmation du mot de passe
|
||||
*/
|
||||
public String getConfirmPassword() {
|
||||
return confirmPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit la confirmation du mot de passe.
|
||||
*
|
||||
* @param confirmPassword la confirmation à définir
|
||||
*/
|
||||
public void setConfirmPassword(String confirmPassword) {
|
||||
this.confirmPassword = confirmPassword;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si les mots de passe correspondent.
|
||||
*
|
||||
* @return true si les mots de passe correspondent, false sinon
|
||||
*/
|
||||
public boolean isPasswordConfirmed() {
|
||||
return newPassword != null && newPassword.equals(confirmPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si c'est une demande de réinitialisation (email seulement).
|
||||
*
|
||||
* @return true si c'est une demande, false sinon
|
||||
*/
|
||||
public boolean isResetRequest() {
|
||||
return email != null && resetToken == null && newPassword == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si c'est une confirmation de réinitialisation (avec token et mot de passe).
|
||||
*
|
||||
* @return true si c'est une confirmation, false sinon
|
||||
*/
|
||||
public boolean isResetConfirmation() {
|
||||
return resetToken != null && newPassword != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'objet (sans les mots de passe pour la sécurité).
|
||||
*
|
||||
* @return une chaîne représentant l'objet
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PasswordResetDTO{" +
|
||||
"email='" + email + '\'' +
|
||||
", hasResetToken=" + (resetToken != null) +
|
||||
", hasNewPassword=" + (newPassword != null) +
|
||||
", hasConfirmPassword=" + (confirmPassword != null) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
229
src/main/java/com/gbcm/server/api/dto/auth/TokenDTO.java
Normal file
229
src/main/java/com/gbcm/server/api/dto/auth/TokenDTO.java
Normal file
@@ -0,0 +1,229 @@
|
||||
package com.gbcm.server.api.dto.auth;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* DTO représentant un token JWT avec ses métadonnées.
|
||||
* Utilisé pour transporter les informations de token entre le client et le serveur.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Schema(description = "Token JWT avec ses métadonnées")
|
||||
public class TokenDTO {
|
||||
|
||||
/**
|
||||
* Le token JWT lui-même.
|
||||
* Utilisé pour l'authentification des requêtes API.
|
||||
*/
|
||||
@Schema(description = "Token JWT pour l'authentification",
|
||||
example = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
required = true)
|
||||
@JsonProperty("token")
|
||||
@NotBlank(message = "Le token ne peut pas être vide")
|
||||
private String token;
|
||||
|
||||
/**
|
||||
* Type du token (généralement "Bearer").
|
||||
*/
|
||||
@Schema(description = "Type du token",
|
||||
example = "Bearer",
|
||||
required = true)
|
||||
@JsonProperty("tokenType")
|
||||
@NotBlank(message = "Le type de token ne peut pas être vide")
|
||||
private String tokenType = "Bearer";
|
||||
|
||||
/**
|
||||
* Date et heure d'expiration du token.
|
||||
*/
|
||||
@Schema(description = "Date et heure d'expiration du token",
|
||||
example = "2024-12-31T23:59:59",
|
||||
required = true)
|
||||
@JsonProperty("expiresAt")
|
||||
@NotNull(message = "La date d'expiration est obligatoire")
|
||||
private LocalDateTime expiresAt;
|
||||
|
||||
/**
|
||||
* Token de rafraîchissement pour renouveler le token principal.
|
||||
* Optionnel, présent seulement si "rememberMe" était activé.
|
||||
*/
|
||||
@Schema(description = "Token de rafraîchissement",
|
||||
example = "refresh_token_abc123")
|
||||
@JsonProperty("refreshToken")
|
||||
private String refreshToken;
|
||||
|
||||
/**
|
||||
* Durée de vie du token en secondes.
|
||||
*/
|
||||
@Schema(description = "Durée de vie du token en secondes",
|
||||
example = "3600")
|
||||
@JsonProperty("expiresIn")
|
||||
private Long expiresIn;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut.
|
||||
*/
|
||||
public TokenDTO() {}
|
||||
|
||||
/**
|
||||
* Constructeur avec token et expiration.
|
||||
*
|
||||
* @param token le token JWT
|
||||
* @param expiresAt la date d'expiration
|
||||
*/
|
||||
public TokenDTO(String token, LocalDateTime expiresAt) {
|
||||
this.token = token;
|
||||
this.expiresAt = expiresAt;
|
||||
this.expiresIn = calculateExpiresIn(expiresAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur complet.
|
||||
*
|
||||
* @param token le token JWT
|
||||
* @param tokenType le type de token
|
||||
* @param expiresAt la date d'expiration
|
||||
* @param refreshToken le token de rafraîchissement
|
||||
*/
|
||||
public TokenDTO(String token, String tokenType, LocalDateTime expiresAt, String refreshToken) {
|
||||
this.token = token;
|
||||
this.tokenType = tokenType;
|
||||
this.expiresAt = expiresAt;
|
||||
this.refreshToken = refreshToken;
|
||||
this.expiresIn = calculateExpiresIn(expiresAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule la durée de vie en secondes jusqu'à l'expiration.
|
||||
*
|
||||
* @param expiresAt la date d'expiration
|
||||
* @return la durée en secondes, ou null si expiresAt est null
|
||||
*/
|
||||
private Long calculateExpiresIn(LocalDateTime expiresAt) {
|
||||
if (expiresAt == null) {
|
||||
return null;
|
||||
}
|
||||
return java.time.Duration.between(LocalDateTime.now(), expiresAt).getSeconds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le token JWT.
|
||||
*
|
||||
* @return le token JWT
|
||||
*/
|
||||
public String getToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le token JWT.
|
||||
*
|
||||
* @param token le token JWT à définir
|
||||
*/
|
||||
public void setToken(String token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le type de token.
|
||||
*
|
||||
* @return le type de token
|
||||
*/
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le type de token.
|
||||
*
|
||||
* @param tokenType le type de token à définir
|
||||
*/
|
||||
public void setTokenType(String tokenType) {
|
||||
this.tokenType = tokenType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la date d'expiration du token.
|
||||
*
|
||||
* @return la date d'expiration
|
||||
*/
|
||||
public LocalDateTime getExpiresAt() {
|
||||
return expiresAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit la date d'expiration du token.
|
||||
*
|
||||
* @param expiresAt la date d'expiration à définir
|
||||
*/
|
||||
public void setExpiresAt(LocalDateTime expiresAt) {
|
||||
this.expiresAt = expiresAt;
|
||||
this.expiresIn = calculateExpiresIn(expiresAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le token de rafraîchissement.
|
||||
*
|
||||
* @return le token de rafraîchissement
|
||||
*/
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le token de rafraîchissement.
|
||||
*
|
||||
* @param refreshToken le token de rafraîchissement à définir
|
||||
*/
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la durée de vie du token en secondes.
|
||||
*
|
||||
* @return la durée de vie en secondes
|
||||
*/
|
||||
public Long getExpiresIn() {
|
||||
return expiresIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit la durée de vie du token en secondes.
|
||||
*
|
||||
* @param expiresIn la durée de vie en secondes
|
||||
*/
|
||||
public void setExpiresIn(Long expiresIn) {
|
||||
this.expiresIn = expiresIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le token est expiré.
|
||||
*
|
||||
* @return true si le token est expiré, false sinon
|
||||
*/
|
||||
public boolean isExpired() {
|
||||
return expiresAt != null && LocalDateTime.now().isAfter(expiresAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'objet (sans les tokens pour la sécurité).
|
||||
*
|
||||
* @return une chaîne représentant l'objet
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TokenDTO{" +
|
||||
"tokenType='" + tokenType + '\'' +
|
||||
", expiresAt=" + expiresAt +
|
||||
", expiresIn=" + expiresIn +
|
||||
", hasRefreshToken=" + (refreshToken != null) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
package com.gbcm.server.api.dto.common;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* DTO pour les réponses d'erreur standardisées.
|
||||
* Utilisé pour retourner des informations d'erreur cohérentes à travers toute l'API.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Schema(description = "Réponse d'erreur standardisée de l'API GBCM")
|
||||
public class ErrorResponseDTO {
|
||||
|
||||
/**
|
||||
* Code d'erreur unique pour identifier le type d'erreur.
|
||||
*/
|
||||
@Schema(description = "Code d'erreur unique",
|
||||
example = "VALIDATION_ERROR",
|
||||
required = true)
|
||||
@JsonProperty("errorCode")
|
||||
@NotBlank(message = "Le code d'erreur est obligatoire")
|
||||
private String errorCode;
|
||||
|
||||
/**
|
||||
* Message d'erreur principal en français.
|
||||
*/
|
||||
@Schema(description = "Message d'erreur principal",
|
||||
example = "Les données fournies ne sont pas valides",
|
||||
required = true)
|
||||
@JsonProperty("message")
|
||||
@NotBlank(message = "Le message d'erreur est obligatoire")
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* Description détaillée de l'erreur.
|
||||
*/
|
||||
@Schema(description = "Description détaillée de l'erreur",
|
||||
example = "Le champ 'email' doit être une adresse email valide")
|
||||
@JsonProperty("details")
|
||||
private String details;
|
||||
|
||||
/**
|
||||
* Timestamp de l'erreur.
|
||||
*/
|
||||
@Schema(description = "Timestamp de l'erreur",
|
||||
example = "2024-01-25T10:30:00",
|
||||
required = true)
|
||||
@JsonProperty("timestamp")
|
||||
@NotNull(message = "Le timestamp est obligatoire")
|
||||
private LocalDateTime timestamp;
|
||||
|
||||
/**
|
||||
* Chemin de la requête qui a causé l'erreur.
|
||||
*/
|
||||
@Schema(description = "Chemin de la requête",
|
||||
example = "/api/v1/users")
|
||||
@JsonProperty("path")
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* Code de statut HTTP.
|
||||
*/
|
||||
@Schema(description = "Code de statut HTTP",
|
||||
example = "400")
|
||||
@JsonProperty("status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* Liste des erreurs de validation spécifiques.
|
||||
*/
|
||||
@Schema(description = "Liste des erreurs de validation")
|
||||
@JsonProperty("validationErrors")
|
||||
private List<ValidationErrorDTO> validationErrors;
|
||||
|
||||
/**
|
||||
* Métadonnées additionnelles sur l'erreur.
|
||||
*/
|
||||
@Schema(description = "Métadonnées additionnelles")
|
||||
@JsonProperty("metadata")
|
||||
private Map<String, Object> metadata;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut.
|
||||
*/
|
||||
public ErrorResponseDTO() {
|
||||
this.timestamp = LocalDateTime.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec code d'erreur et message.
|
||||
*
|
||||
* @param errorCode le code d'erreur
|
||||
* @param message le message d'erreur
|
||||
*/
|
||||
public ErrorResponseDTO(String errorCode, String message) {
|
||||
this();
|
||||
this.errorCode = errorCode;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur complet.
|
||||
*
|
||||
* @param errorCode le code d'erreur
|
||||
* @param message le message d'erreur
|
||||
* @param details les détails de l'erreur
|
||||
* @param path le chemin de la requête
|
||||
* @param status le code de statut HTTP
|
||||
*/
|
||||
public ErrorResponseDTO(String errorCode, String message, String details, String path, Integer status) {
|
||||
this(errorCode, message);
|
||||
this.details = details;
|
||||
this.path = path;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse d'erreur de validation.
|
||||
*
|
||||
* @param message le message d'erreur principal
|
||||
* @param validationErrors la liste des erreurs de validation
|
||||
* @return une réponse d'erreur de validation
|
||||
*/
|
||||
public static ErrorResponseDTO validationError(String message, List<ValidationErrorDTO> validationErrors) {
|
||||
ErrorResponseDTO error = new ErrorResponseDTO("VALIDATION_ERROR", message);
|
||||
error.setValidationErrors(validationErrors);
|
||||
error.setStatus(400);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse d'erreur d'authentification.
|
||||
*
|
||||
* @param message le message d'erreur
|
||||
* @return une réponse d'erreur d'authentification
|
||||
*/
|
||||
public static ErrorResponseDTO authenticationError(String message) {
|
||||
ErrorResponseDTO error = new ErrorResponseDTO("AUTHENTICATION_ERROR", message);
|
||||
error.setStatus(401);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse d'erreur d'autorisation.
|
||||
*
|
||||
* @param message le message d'erreur
|
||||
* @return une réponse d'erreur d'autorisation
|
||||
*/
|
||||
public static ErrorResponseDTO authorizationError(String message) {
|
||||
ErrorResponseDTO error = new ErrorResponseDTO("AUTHORIZATION_ERROR", message);
|
||||
error.setStatus(403);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse d'erreur de ressource non trouvée.
|
||||
*
|
||||
* @param message le message d'erreur
|
||||
* @return une réponse d'erreur de ressource non trouvée
|
||||
*/
|
||||
public static ErrorResponseDTO notFoundError(String message) {
|
||||
ErrorResponseDTO error = new ErrorResponseDTO("RESOURCE_NOT_FOUND", message);
|
||||
error.setStatus(404);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse d'erreur interne du serveur.
|
||||
*
|
||||
* @param message le message d'erreur
|
||||
* @return une réponse d'erreur interne
|
||||
*/
|
||||
public static ErrorResponseDTO internalError(String message) {
|
||||
ErrorResponseDTO error = new ErrorResponseDTO("INTERNAL_ERROR", message);
|
||||
error.setStatus(500);
|
||||
return error;
|
||||
}
|
||||
|
||||
// Getters et Setters
|
||||
|
||||
public String getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
public void setErrorCode(String errorCode) {
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
public void setDetails(String details) {
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
public LocalDateTime getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(LocalDateTime timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public List<ValidationErrorDTO> getValidationErrors() {
|
||||
return validationErrors;
|
||||
}
|
||||
|
||||
public void setValidationErrors(List<ValidationErrorDTO> validationErrors) {
|
||||
this.validationErrors = validationErrors;
|
||||
}
|
||||
|
||||
public Map<String, Object> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
public void setMetadata(Map<String, Object> metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ErrorResponseDTO{" +
|
||||
"errorCode='" + errorCode + '\'' +
|
||||
", message='" + message + '\'' +
|
||||
", timestamp=" + timestamp +
|
||||
", path='" + path + '\'' +
|
||||
", status=" + status +
|
||||
'}';
|
||||
}
|
||||
|
||||
/**
|
||||
* DTO pour les erreurs de validation spécifiques.
|
||||
*/
|
||||
@Schema(description = "Erreur de validation spécifique")
|
||||
public static class ValidationErrorDTO {
|
||||
|
||||
/**
|
||||
* Nom du champ en erreur.
|
||||
*/
|
||||
@Schema(description = "Nom du champ en erreur", example = "email")
|
||||
@JsonProperty("field")
|
||||
private String field;
|
||||
|
||||
/**
|
||||
* Valeur rejetée.
|
||||
*/
|
||||
@Schema(description = "Valeur rejetée", example = "invalid-email")
|
||||
@JsonProperty("rejectedValue")
|
||||
private Object rejectedValue;
|
||||
|
||||
/**
|
||||
* Message d'erreur pour ce champ.
|
||||
*/
|
||||
@Schema(description = "Message d'erreur pour ce champ", example = "Format d'email invalide")
|
||||
@JsonProperty("message")
|
||||
private String message;
|
||||
|
||||
public ValidationErrorDTO() {}
|
||||
|
||||
public ValidationErrorDTO(String field, Object rejectedValue, String message) {
|
||||
this.field = field;
|
||||
this.rejectedValue = rejectedValue;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public void setField(String field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public Object getRejectedValue() {
|
||||
return rejectedValue;
|
||||
}
|
||||
|
||||
public void setRejectedValue(Object rejectedValue) {
|
||||
this.rejectedValue = rejectedValue;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ValidationErrorDTO{" +
|
||||
"field='" + field + '\'' +
|
||||
", rejectedValue=" + rejectedValue +
|
||||
", message='" + message + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
339
src/main/java/com/gbcm/server/api/dto/common/PagedResultDTO.java
Normal file
339
src/main/java/com/gbcm/server/api/dto/common/PagedResultDTO.java
Normal file
@@ -0,0 +1,339 @@
|
||||
package com.gbcm.server.api.dto.common;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* DTO générique pour les résultats paginés.
|
||||
* Encapsule une liste d'éléments avec les métadonnées de pagination.
|
||||
*
|
||||
* @param <T> le type des éléments contenus dans la page
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Schema(description = "Résultat paginé contenant une liste d'éléments et les métadonnées de pagination")
|
||||
public class PagedResultDTO<T> {
|
||||
|
||||
/**
|
||||
* Liste des éléments de la page courante.
|
||||
*/
|
||||
@Schema(description = "Liste des éléments de la page courante",
|
||||
required = true)
|
||||
@JsonProperty("content")
|
||||
@NotNull(message = "Le contenu ne peut pas être null")
|
||||
private List<T> content;
|
||||
|
||||
/**
|
||||
* Numéro de la page courante (commence à 0).
|
||||
*/
|
||||
@Schema(description = "Numéro de la page courante (commence à 0)",
|
||||
example = "0",
|
||||
required = true)
|
||||
@JsonProperty("page")
|
||||
@Min(value = 0, message = "Le numéro de page doit être >= 0")
|
||||
private int page;
|
||||
|
||||
/**
|
||||
* Taille de la page (nombre d'éléments par page).
|
||||
*/
|
||||
@Schema(description = "Taille de la page (nombre d'éléments par page)",
|
||||
example = "20",
|
||||
required = true)
|
||||
@JsonProperty("size")
|
||||
@Min(value = 1, message = "La taille de page doit être >= 1")
|
||||
private int size;
|
||||
|
||||
/**
|
||||
* Nombre total d'éléments disponibles.
|
||||
*/
|
||||
@Schema(description = "Nombre total d'éléments disponibles",
|
||||
example = "150",
|
||||
required = true)
|
||||
@JsonProperty("totalElements")
|
||||
@Min(value = 0, message = "Le nombre total d'éléments doit être >= 0")
|
||||
private long totalElements;
|
||||
|
||||
/**
|
||||
* Nombre total de pages disponibles.
|
||||
*/
|
||||
@Schema(description = "Nombre total de pages disponibles",
|
||||
example = "8",
|
||||
required = true)
|
||||
@JsonProperty("totalPages")
|
||||
@Min(value = 0, message = "Le nombre total de pages doit être >= 0")
|
||||
private int totalPages;
|
||||
|
||||
/**
|
||||
* Indique si c'est la première page.
|
||||
*/
|
||||
@Schema(description = "Indique si c'est la première page",
|
||||
example = "true")
|
||||
@JsonProperty("first")
|
||||
private boolean first;
|
||||
|
||||
/**
|
||||
* Indique si c'est la dernière page.
|
||||
*/
|
||||
@Schema(description = "Indique si c'est la dernière page",
|
||||
example = "false")
|
||||
@JsonProperty("last")
|
||||
private boolean last;
|
||||
|
||||
/**
|
||||
* Nombre d'éléments dans la page courante.
|
||||
*/
|
||||
@Schema(description = "Nombre d'éléments dans la page courante",
|
||||
example = "20")
|
||||
@JsonProperty("numberOfElements")
|
||||
private int numberOfElements;
|
||||
|
||||
/**
|
||||
* Indique si la page est vide.
|
||||
*/
|
||||
@Schema(description = "Indique si la page est vide",
|
||||
example = "false")
|
||||
@JsonProperty("empty")
|
||||
private boolean empty;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut.
|
||||
*/
|
||||
public PagedResultDTO() {}
|
||||
|
||||
/**
|
||||
* Constructeur avec tous les paramètres.
|
||||
*
|
||||
* @param content la liste des éléments
|
||||
* @param page le numéro de page
|
||||
* @param size la taille de page
|
||||
* @param totalElements le nombre total d'éléments
|
||||
*/
|
||||
public PagedResultDTO(List<T> content, int page, int size, long totalElements) {
|
||||
this.content = content;
|
||||
this.page = page;
|
||||
this.size = size;
|
||||
this.totalElements = totalElements;
|
||||
this.numberOfElements = content != null ? content.size() : 0;
|
||||
this.empty = this.numberOfElements == 0;
|
||||
this.totalPages = size > 0 ? (int) Math.ceil((double) totalElements / size) : 0;
|
||||
this.first = page == 0;
|
||||
this.last = page >= totalPages - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un résultat paginé vide.
|
||||
*
|
||||
* @param <T> le type des éléments
|
||||
* @return un résultat paginé vide
|
||||
*/
|
||||
public static <T> PagedResultDTO<T> empty() {
|
||||
return new PagedResultDTO<>(List.of(), 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un résultat paginé avec une seule page.
|
||||
*
|
||||
* @param content la liste des éléments
|
||||
* @param <T> le type des éléments
|
||||
* @return un résultat paginé avec une seule page
|
||||
*/
|
||||
public static <T> PagedResultDTO<T> of(List<T> content) {
|
||||
return new PagedResultDTO<>(content, 0, content.size(), content.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la liste des éléments de la page courante.
|
||||
*
|
||||
* @return la liste des éléments
|
||||
*/
|
||||
public List<T> getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit la liste des éléments de la page courante.
|
||||
*
|
||||
* @param content la liste des éléments à définir
|
||||
*/
|
||||
public void setContent(List<T> content) {
|
||||
this.content = content;
|
||||
this.numberOfElements = content != null ? content.size() : 0;
|
||||
this.empty = this.numberOfElements == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le numéro de la page courante.
|
||||
*
|
||||
* @return le numéro de page
|
||||
*/
|
||||
public int getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le numéro de la page courante.
|
||||
*
|
||||
* @param page le numéro de page à définir
|
||||
*/
|
||||
public void setPage(int page) {
|
||||
this.page = page;
|
||||
this.first = page == 0;
|
||||
this.last = page >= totalPages - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la taille de la page.
|
||||
*
|
||||
* @return la taille de page
|
||||
*/
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit la taille de la page.
|
||||
*
|
||||
* @param size la taille de page à définir
|
||||
*/
|
||||
public void setSize(int size) {
|
||||
this.size = size;
|
||||
this.totalPages = size > 0 ? (int) Math.ceil((double) totalElements / size) : 0;
|
||||
this.last = page >= totalPages - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nombre total d'éléments.
|
||||
*
|
||||
* @return le nombre total d'éléments
|
||||
*/
|
||||
public long getTotalElements() {
|
||||
return totalElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le nombre total d'éléments.
|
||||
*
|
||||
* @param totalElements le nombre total d'éléments à définir
|
||||
*/
|
||||
public void setTotalElements(long totalElements) {
|
||||
this.totalElements = totalElements;
|
||||
this.totalPages = size > 0 ? (int) Math.ceil((double) totalElements / size) : 0;
|
||||
this.last = page >= totalPages - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nombre total de pages.
|
||||
*
|
||||
* @return le nombre total de pages
|
||||
*/
|
||||
public int getTotalPages() {
|
||||
return totalPages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le nombre total de pages.
|
||||
*
|
||||
* @param totalPages le nombre total de pages à définir
|
||||
*/
|
||||
public void setTotalPages(int totalPages) {
|
||||
this.totalPages = totalPages;
|
||||
this.last = page >= totalPages - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indique si c'est la première page.
|
||||
*
|
||||
* @return true si c'est la première page, false sinon
|
||||
*/
|
||||
public boolean isFirst() {
|
||||
return first;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit si c'est la première page.
|
||||
*
|
||||
* @param first true si c'est la première page, false sinon
|
||||
*/
|
||||
public void setFirst(boolean first) {
|
||||
this.first = first;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indique si c'est la dernière page.
|
||||
*
|
||||
* @return true si c'est la dernière page, false sinon
|
||||
*/
|
||||
public boolean isLast() {
|
||||
return last;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit si c'est la dernière page.
|
||||
*
|
||||
* @param last true si c'est la dernière page, false sinon
|
||||
*/
|
||||
public void setLast(boolean last) {
|
||||
this.last = last;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nombre d'éléments dans la page courante.
|
||||
*
|
||||
* @return le nombre d'éléments dans la page courante
|
||||
*/
|
||||
public int getNumberOfElements() {
|
||||
return numberOfElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le nombre d'éléments dans la page courante.
|
||||
*
|
||||
* @param numberOfElements le nombre d'éléments à définir
|
||||
*/
|
||||
public void setNumberOfElements(int numberOfElements) {
|
||||
this.numberOfElements = numberOfElements;
|
||||
this.empty = numberOfElements == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indique si la page est vide.
|
||||
*
|
||||
* @return true si la page est vide, false sinon
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit si la page est vide.
|
||||
*
|
||||
* @param empty true si la page est vide, false sinon
|
||||
*/
|
||||
public void setEmpty(boolean empty) {
|
||||
this.empty = empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'objet.
|
||||
*
|
||||
* @return une chaîne représentant l'objet
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PagedResultDTO{" +
|
||||
"page=" + page +
|
||||
", size=" + size +
|
||||
", totalElements=" + totalElements +
|
||||
", totalPages=" + totalPages +
|
||||
", numberOfElements=" + numberOfElements +
|
||||
", first=" + first +
|
||||
", last=" + last +
|
||||
", empty=" + empty +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
package com.gbcm.server.api.dto.common;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* DTO pour les réponses de succès standardisées.
|
||||
* Utilisé pour retourner des confirmations d'opérations réussies avec des données optionnelles.
|
||||
*
|
||||
* @param <T> le type des données retournées
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Schema(description = "Réponse de succès standardisée de l'API GBCM")
|
||||
public class SuccessResponseDTO<T> {
|
||||
|
||||
/**
|
||||
* Indicateur de succès (toujours true pour cette classe).
|
||||
*/
|
||||
@Schema(description = "Indicateur de succès",
|
||||
example = "true",
|
||||
required = true)
|
||||
@JsonProperty("success")
|
||||
@NotNull(message = "L'indicateur de succès est obligatoire")
|
||||
private boolean success = true;
|
||||
|
||||
/**
|
||||
* Message de succès en français.
|
||||
*/
|
||||
@Schema(description = "Message de succès",
|
||||
example = "Opération réalisée avec succès",
|
||||
required = true)
|
||||
@JsonProperty("message")
|
||||
@NotBlank(message = "Le message de succès est obligatoire")
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* Données retournées par l'opération.
|
||||
*/
|
||||
@Schema(description = "Données retournées par l'opération")
|
||||
@JsonProperty("data")
|
||||
private T data;
|
||||
|
||||
/**
|
||||
* Timestamp de la réponse.
|
||||
*/
|
||||
@Schema(description = "Timestamp de la réponse",
|
||||
example = "2024-01-25T10:30:00",
|
||||
required = true)
|
||||
@JsonProperty("timestamp")
|
||||
@NotNull(message = "Le timestamp est obligatoire")
|
||||
private LocalDateTime timestamp;
|
||||
|
||||
/**
|
||||
* Code de statut HTTP.
|
||||
*/
|
||||
@Schema(description = "Code de statut HTTP",
|
||||
example = "200")
|
||||
@JsonProperty("status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* Métadonnées additionnelles.
|
||||
*/
|
||||
@Schema(description = "Métadonnées additionnelles")
|
||||
@JsonProperty("metadata")
|
||||
private Map<String, Object> metadata;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut.
|
||||
*/
|
||||
public SuccessResponseDTO() {
|
||||
this.timestamp = LocalDateTime.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message.
|
||||
*
|
||||
* @param message le message de succès
|
||||
*/
|
||||
public SuccessResponseDTO(String message) {
|
||||
this();
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message et données.
|
||||
*
|
||||
* @param message le message de succès
|
||||
* @param data les données à retourner
|
||||
*/
|
||||
public SuccessResponseDTO(String message, T data) {
|
||||
this(message);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur complet.
|
||||
*
|
||||
* @param message le message de succès
|
||||
* @param data les données à retourner
|
||||
* @param status le code de statut HTTP
|
||||
*/
|
||||
public SuccessResponseDTO(String message, T data, Integer status) {
|
||||
this(message, data);
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse de succès simple.
|
||||
*
|
||||
* @param message le message de succès
|
||||
* @param <T> le type des données
|
||||
* @return une réponse de succès
|
||||
*/
|
||||
public static <T> SuccessResponseDTO<T> of(String message) {
|
||||
return new SuccessResponseDTO<>(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse de succès avec données.
|
||||
*
|
||||
* @param message le message de succès
|
||||
* @param data les données à retourner
|
||||
* @param <T> le type des données
|
||||
* @return une réponse de succès avec données
|
||||
*/
|
||||
public static <T> SuccessResponseDTO<T> of(String message, T data) {
|
||||
return new SuccessResponseDTO<>(message, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse de création réussie (201).
|
||||
*
|
||||
* @param message le message de succès
|
||||
* @param data les données créées
|
||||
* @param <T> le type des données
|
||||
* @return une réponse de création réussie
|
||||
*/
|
||||
public static <T> SuccessResponseDTO<T> created(String message, T data) {
|
||||
return new SuccessResponseDTO<>(message, data, 201);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse de mise à jour réussie.
|
||||
*
|
||||
* @param message le message de succès
|
||||
* @param data les données mises à jour
|
||||
* @param <T> le type des données
|
||||
* @return une réponse de mise à jour réussie
|
||||
*/
|
||||
public static <T> SuccessResponseDTO<T> updated(String message, T data) {
|
||||
return new SuccessResponseDTO<>(message, data, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse de suppression réussie.
|
||||
*
|
||||
* @param message le message de succès
|
||||
* @return une réponse de suppression réussie
|
||||
*/
|
||||
public static SuccessResponseDTO<Void> deleted(String message) {
|
||||
return new SuccessResponseDTO<>(message, null, 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une réponse sans contenu (204).
|
||||
*
|
||||
* @param message le message de succès
|
||||
* @return une réponse sans contenu
|
||||
*/
|
||||
public static SuccessResponseDTO<Void> noContent(String message) {
|
||||
return new SuccessResponseDTO<>(message, null, 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'indicateur de succès.
|
||||
*
|
||||
* @return true (toujours pour cette classe)
|
||||
*/
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit l'indicateur de succès.
|
||||
*
|
||||
* @param success l'indicateur de succès
|
||||
*/
|
||||
public void setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le message de succès.
|
||||
*
|
||||
* @return le message de succès
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le message de succès.
|
||||
*
|
||||
* @param message le message de succès à définir
|
||||
*/
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les données de la réponse.
|
||||
*
|
||||
* @return les données
|
||||
*/
|
||||
public T getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit les données de la réponse.
|
||||
*
|
||||
* @param data les données à définir
|
||||
*/
|
||||
public void setData(T data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le timestamp de la réponse.
|
||||
*
|
||||
* @return le timestamp
|
||||
*/
|
||||
public LocalDateTime getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le timestamp de la réponse.
|
||||
*
|
||||
* @param timestamp le timestamp à définir
|
||||
*/
|
||||
public void setTimestamp(LocalDateTime timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le code de statut HTTP.
|
||||
*
|
||||
* @return le code de statut
|
||||
*/
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le code de statut HTTP.
|
||||
*
|
||||
* @param status le code de statut à définir
|
||||
*/
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les métadonnées additionnelles.
|
||||
*
|
||||
* @return les métadonnées
|
||||
*/
|
||||
public Map<String, Object> getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit les métadonnées additionnelles.
|
||||
*
|
||||
* @param metadata les métadonnées à définir
|
||||
*/
|
||||
public void setMetadata(Map<String, Object> metadata) {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'objet.
|
||||
*
|
||||
* @return une chaîne représentant l'objet
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SuccessResponseDTO{" +
|
||||
"success=" + success +
|
||||
", message='" + message + '\'' +
|
||||
", timestamp=" + timestamp +
|
||||
", status=" + status +
|
||||
", hasData=" + (data != null) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
278
src/main/java/com/gbcm/server/api/dto/user/CreateUserDTO.java
Normal file
278
src/main/java/com/gbcm/server/api/dto/user/CreateUserDTO.java
Normal file
@@ -0,0 +1,278 @@
|
||||
package com.gbcm.server.api.dto.user;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.gbcm.server.api.enums.UserRole;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* DTO pour la création d'un nouvel utilisateur.
|
||||
* Contient toutes les informations nécessaires pour créer un compte utilisateur.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Schema(description = "Données pour la création d'un nouvel utilisateur")
|
||||
public class CreateUserDTO {
|
||||
|
||||
/**
|
||||
* Prénom de l'utilisateur.
|
||||
*/
|
||||
@Schema(description = "Prénom de l'utilisateur",
|
||||
example = "John",
|
||||
required = true,
|
||||
maxLength = 50)
|
||||
@JsonProperty("firstName")
|
||||
@NotBlank(message = "Le prénom est obligatoire")
|
||||
@Size(max = 50, message = "Le prénom ne peut pas dépasser 50 caractères")
|
||||
private String firstName;
|
||||
|
||||
/**
|
||||
* Nom de famille de l'utilisateur.
|
||||
*/
|
||||
@Schema(description = "Nom de famille de l'utilisateur",
|
||||
example = "Doe",
|
||||
required = true,
|
||||
maxLength = 50)
|
||||
@JsonProperty("lastName")
|
||||
@NotBlank(message = "Le nom est obligatoire")
|
||||
@Size(max = 50, message = "Le nom ne peut pas dépasser 50 caractères")
|
||||
private String lastName;
|
||||
|
||||
/**
|
||||
* Adresse email unique de l'utilisateur.
|
||||
* Sera utilisée pour l'authentification.
|
||||
*/
|
||||
@Schema(description = "Adresse email unique de l'utilisateur",
|
||||
example = "john.doe@gbcm.com",
|
||||
required = true,
|
||||
maxLength = 255)
|
||||
@JsonProperty("email")
|
||||
@NotBlank(message = "L'email est obligatoire")
|
||||
@Email(message = "Format d'email invalide")
|
||||
@Size(max = 255, message = "L'email ne peut pas dépasser 255 caractères")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* Mot de passe initial de l'utilisateur.
|
||||
* Sera haché avant stockage en base.
|
||||
*/
|
||||
@Schema(description = "Mot de passe initial de l'utilisateur",
|
||||
example = "motdepasse123",
|
||||
required = true,
|
||||
minLength = 6,
|
||||
maxLength = 100)
|
||||
@JsonProperty("password")
|
||||
@NotBlank(message = "Le mot de passe est obligatoire")
|
||||
@Size(min = 6, max = 100, message = "Le mot de passe doit contenir entre 6 et 100 caractères")
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Numéro de téléphone de l'utilisateur.
|
||||
* Format international recommandé.
|
||||
*/
|
||||
@Schema(description = "Numéro de téléphone de l'utilisateur",
|
||||
example = "+1-404-555-0123",
|
||||
maxLength = 20)
|
||||
@JsonProperty("phone")
|
||||
@Size(max = 20, message = "Le téléphone ne peut pas dépasser 20 caractères")
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* Rôle de l'utilisateur dans le système.
|
||||
* Détermine les permissions initiales.
|
||||
*/
|
||||
@Schema(description = "Rôle de l'utilisateur dans le système",
|
||||
required = true)
|
||||
@JsonProperty("role")
|
||||
@NotNull(message = "Le rôle est obligatoire")
|
||||
private UserRole role;
|
||||
|
||||
/**
|
||||
* Statut d'activation initial du compte.
|
||||
* Par défaut, les comptes sont créés actifs.
|
||||
*/
|
||||
@Schema(description = "Statut d'activation initial du compte",
|
||||
example = "true",
|
||||
defaultValue = "true")
|
||||
@JsonProperty("active")
|
||||
private boolean active = true;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut.
|
||||
*/
|
||||
public CreateUserDTO() {}
|
||||
|
||||
/**
|
||||
* Constructeur avec les champs obligatoires.
|
||||
*
|
||||
* @param firstName le prénom de l'utilisateur
|
||||
* @param lastName le nom de famille de l'utilisateur
|
||||
* @param email l'adresse email de l'utilisateur
|
||||
* @param password le mot de passe initial
|
||||
* @param role le rôle de l'utilisateur
|
||||
*/
|
||||
public CreateUserDTO(String firstName, String lastName, String email, String password, UserRole role) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.email = email;
|
||||
this.password = password;
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le prénom de l'utilisateur.
|
||||
*
|
||||
* @return le prénom
|
||||
*/
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le prénom de l'utilisateur.
|
||||
*
|
||||
* @param firstName le prénom à définir
|
||||
*/
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nom de famille de l'utilisateur.
|
||||
*
|
||||
* @return le nom de famille
|
||||
*/
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le nom de famille de l'utilisateur.
|
||||
*
|
||||
* @param lastName le nom de famille à définir
|
||||
*/
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'adresse email de l'utilisateur.
|
||||
*
|
||||
* @return l'adresse email
|
||||
*/
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit l'adresse email de l'utilisateur.
|
||||
*
|
||||
* @param email l'adresse email à définir
|
||||
*/
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le mot de passe de l'utilisateur.
|
||||
*
|
||||
* @return le mot de passe
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le mot de passe de l'utilisateur.
|
||||
*
|
||||
* @param password le mot de passe à définir
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le numéro de téléphone de l'utilisateur.
|
||||
*
|
||||
* @return le numéro de téléphone
|
||||
*/
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le numéro de téléphone de l'utilisateur.
|
||||
*
|
||||
* @param phone le numéro de téléphone à définir
|
||||
*/
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le rôle de l'utilisateur.
|
||||
*
|
||||
* @return le rôle
|
||||
*/
|
||||
public UserRole getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le rôle de l'utilisateur.
|
||||
*
|
||||
* @param role le rôle à définir
|
||||
*/
|
||||
public void setRole(UserRole role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indique si le compte est actif.
|
||||
*
|
||||
* @return true si le compte est actif, false sinon
|
||||
*/
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le statut d'activation du compte.
|
||||
*
|
||||
* @param active true pour activer le compte, false sinon
|
||||
*/
|
||||
public void setActive(boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nom complet de l'utilisateur.
|
||||
*
|
||||
* @return le nom complet (prénom + nom)
|
||||
*/
|
||||
public String getFullName() {
|
||||
return firstName + " " + lastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'objet (sans le mot de passe pour la sécurité).
|
||||
*
|
||||
* @return une chaîne représentant l'objet
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CreateUserDTO{" +
|
||||
"firstName='" + firstName + '\'' +
|
||||
", lastName='" + lastName + '\'' +
|
||||
", email='" + email + '\'' +
|
||||
", phone='" + phone + '\'' +
|
||||
", role=" + role +
|
||||
", active=" + active +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
245
src/main/java/com/gbcm/server/api/dto/user/UpdateUserDTO.java
Normal file
245
src/main/java/com/gbcm/server/api/dto/user/UpdateUserDTO.java
Normal file
@@ -0,0 +1,245 @@
|
||||
package com.gbcm.server.api.dto.user;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.gbcm.server.api.enums.UserRole;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
* DTO pour la mise à jour d'un utilisateur existant.
|
||||
* Tous les champs sont optionnels, seuls les champs fournis seront mis à jour.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Schema(description = "Données pour la mise à jour d'un utilisateur existant")
|
||||
public class UpdateUserDTO {
|
||||
|
||||
/**
|
||||
* Nouveau prénom de l'utilisateur.
|
||||
* Optionnel - si fourni, remplace le prénom existant.
|
||||
*/
|
||||
@Schema(description = "Nouveau prénom de l'utilisateur",
|
||||
example = "John",
|
||||
maxLength = 50)
|
||||
@JsonProperty("firstName")
|
||||
@Size(max = 50, message = "Le prénom ne peut pas dépasser 50 caractères")
|
||||
private String firstName;
|
||||
|
||||
/**
|
||||
* Nouveau nom de famille de l'utilisateur.
|
||||
* Optionnel - si fourni, remplace le nom existant.
|
||||
*/
|
||||
@Schema(description = "Nouveau nom de famille de l'utilisateur",
|
||||
example = "Doe",
|
||||
maxLength = 50)
|
||||
@JsonProperty("lastName")
|
||||
@Size(max = 50, message = "Le nom ne peut pas dépasser 50 caractères")
|
||||
private String lastName;
|
||||
|
||||
/**
|
||||
* Nouvelle adresse email de l'utilisateur.
|
||||
* Optionnel - si fourni, doit être unique dans le système.
|
||||
*/
|
||||
@Schema(description = "Nouvelle adresse email de l'utilisateur",
|
||||
example = "john.doe@gbcm.com",
|
||||
maxLength = 255)
|
||||
@JsonProperty("email")
|
||||
@Email(message = "Format d'email invalide")
|
||||
@Size(max = 255, message = "L'email ne peut pas dépasser 255 caractères")
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* Nouveau numéro de téléphone de l'utilisateur.
|
||||
* Optionnel - format international recommandé.
|
||||
*/
|
||||
@Schema(description = "Nouveau numéro de téléphone de l'utilisateur",
|
||||
example = "+1-404-555-0123",
|
||||
maxLength = 20)
|
||||
@JsonProperty("phone")
|
||||
@Size(max = 20, message = "Le téléphone ne peut pas dépasser 20 caractères")
|
||||
private String phone;
|
||||
|
||||
/**
|
||||
* Nouveau rôle de l'utilisateur dans le système.
|
||||
* Optionnel - modifie les permissions de l'utilisateur.
|
||||
*/
|
||||
@Schema(description = "Nouveau rôle de l'utilisateur dans le système")
|
||||
@JsonProperty("role")
|
||||
private UserRole role;
|
||||
|
||||
/**
|
||||
* Nouveau statut d'activation du compte.
|
||||
* Optionnel - permet d'activer/désactiver le compte.
|
||||
*/
|
||||
@Schema(description = "Nouveau statut d'activation du compte",
|
||||
example = "true")
|
||||
@JsonProperty("active")
|
||||
private Boolean active;
|
||||
|
||||
/**
|
||||
* Constructeur par défaut.
|
||||
*/
|
||||
public UpdateUserDTO() {}
|
||||
|
||||
/**
|
||||
* Constructeur avec prénom et nom.
|
||||
*
|
||||
* @param firstName le nouveau prénom
|
||||
* @param lastName le nouveau nom de famille
|
||||
*/
|
||||
public UpdateUserDTO(String firstName, String lastName) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nouveau prénom de l'utilisateur.
|
||||
*
|
||||
* @return le nouveau prénom, ou null si non modifié
|
||||
*/
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le nouveau prénom de l'utilisateur.
|
||||
*
|
||||
* @param firstName le nouveau prénom à définir
|
||||
*/
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nouveau nom de famille de l'utilisateur.
|
||||
*
|
||||
* @return le nouveau nom de famille, ou null si non modifié
|
||||
*/
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le nouveau nom de famille de l'utilisateur.
|
||||
*
|
||||
* @param lastName le nouveau nom de famille à définir
|
||||
*/
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la nouvelle adresse email de l'utilisateur.
|
||||
*
|
||||
* @return la nouvelle adresse email, ou null si non modifiée
|
||||
*/
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit la nouvelle adresse email de l'utilisateur.
|
||||
*
|
||||
* @param email la nouvelle adresse email à définir
|
||||
*/
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nouveau numéro de téléphone de l'utilisateur.
|
||||
*
|
||||
* @return le nouveau numéro de téléphone, ou null si non modifié
|
||||
*/
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le nouveau numéro de téléphone de l'utilisateur.
|
||||
*
|
||||
* @param phone le nouveau numéro de téléphone à définir
|
||||
*/
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nouveau rôle de l'utilisateur.
|
||||
*
|
||||
* @return le nouveau rôle, ou null si non modifié
|
||||
*/
|
||||
public UserRole getRole() {
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le nouveau rôle de l'utilisateur.
|
||||
*
|
||||
* @param role le nouveau rôle à définir
|
||||
*/
|
||||
public void setRole(UserRole role) {
|
||||
this.role = role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nouveau statut d'activation du compte.
|
||||
*
|
||||
* @return le nouveau statut, ou null si non modifié
|
||||
*/
|
||||
public Boolean getActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit le nouveau statut d'activation du compte.
|
||||
*
|
||||
* @param active le nouveau statut à définir
|
||||
*/
|
||||
public void setActive(Boolean active) {
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si au moins un champ est fourni pour la mise à jour.
|
||||
*
|
||||
* @return true si au moins un champ est non null, false sinon
|
||||
*/
|
||||
public boolean hasUpdates() {
|
||||
return firstName != null || lastName != null || email != null ||
|
||||
phone != null || role != null || active != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nom complet si prénom et nom sont fournis.
|
||||
*
|
||||
* @return le nom complet, ou null si prénom ou nom manquant
|
||||
*/
|
||||
public String getFullName() {
|
||||
if (firstName != null && lastName != null) {
|
||||
return firstName + " " + lastName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'objet.
|
||||
*
|
||||
* @return une chaîne représentant l'objet
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UpdateUserDTO{" +
|
||||
"firstName='" + firstName + '\'' +
|
||||
", lastName='" + lastName + '\'' +
|
||||
", email='" + email + '\'' +
|
||||
", phone='" + phone + '\'' +
|
||||
", role=" + role +
|
||||
", active=" + active +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -1,62 +1,124 @@
|
||||
package com.gbcm.server.api.dto.user;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.gbcm.server.api.enums.UserRole;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* DTO pour les informations utilisateur
|
||||
* DTO pour les informations utilisateur de la plateforme GBCM.
|
||||
* Contient toutes les données nécessaires pour représenter un utilisateur côté client.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Schema(description = "Informations utilisateur")
|
||||
@Schema(description = "Informations utilisateur de la plateforme GBCM")
|
||||
public class UserDTO {
|
||||
|
||||
@Schema(description = "Identifiant unique", example = "1")
|
||||
/**
|
||||
* Identifiant unique de l'utilisateur.
|
||||
*/
|
||||
@Schema(description = "Identifiant unique de l'utilisateur",
|
||||
example = "1",
|
||||
accessMode = Schema.AccessMode.READ_ONLY)
|
||||
@JsonProperty("id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "Prénom", example = "John")
|
||||
/**
|
||||
* Prénom de l'utilisateur.
|
||||
*/
|
||||
@Schema(description = "Prénom de l'utilisateur",
|
||||
example = "John",
|
||||
required = true,
|
||||
maxLength = 50)
|
||||
@JsonProperty("firstName")
|
||||
@NotBlank(message = "Le prénom est obligatoire")
|
||||
private String firstName;
|
||||
|
||||
@Schema(description = "Nom de famille", example = "Doe")
|
||||
/**
|
||||
* Nom de famille de l'utilisateur.
|
||||
*/
|
||||
@Schema(description = "Nom de famille de l'utilisateur",
|
||||
example = "Doe",
|
||||
required = true,
|
||||
maxLength = 50)
|
||||
@JsonProperty("lastName")
|
||||
@NotBlank(message = "Le nom est obligatoire")
|
||||
private String lastName;
|
||||
|
||||
@Schema(description = "Adresse email", example = "john.doe@gbcm.com")
|
||||
/**
|
||||
* Adresse email unique de l'utilisateur.
|
||||
* Utilisée pour l'authentification et les communications.
|
||||
*/
|
||||
@Schema(description = "Adresse email unique de l'utilisateur",
|
||||
example = "john.doe@gbcm.com",
|
||||
required = true,
|
||||
maxLength = 255)
|
||||
@JsonProperty("email")
|
||||
@NotBlank(message = "L'email est obligatoire")
|
||||
@Email(message = "Format d'email invalide")
|
||||
private String email;
|
||||
|
||||
@Schema(description = "Numéro de téléphone", example = "+1234567890")
|
||||
/**
|
||||
* Numéro de téléphone de l'utilisateur.
|
||||
* Format international recommandé.
|
||||
*/
|
||||
@Schema(description = "Numéro de téléphone de l'utilisateur",
|
||||
example = "+1-404-555-0123",
|
||||
maxLength = 20)
|
||||
@JsonProperty("phone")
|
||||
private String phone;
|
||||
|
||||
@Schema(description = "Rôle utilisateur")
|
||||
/**
|
||||
* Rôle de l'utilisateur dans le système.
|
||||
* Détermine les permissions et l'accès aux fonctionnalités.
|
||||
*/
|
||||
@Schema(description = "Rôle de l'utilisateur dans le système",
|
||||
required = true)
|
||||
@JsonProperty("role")
|
||||
@NotNull(message = "Le rôle est obligatoire")
|
||||
private UserRole role;
|
||||
|
||||
@Schema(description = "Statut actif", example = "true")
|
||||
/**
|
||||
* Statut d'activation du compte utilisateur.
|
||||
* Les comptes inactifs ne peuvent pas se connecter.
|
||||
*/
|
||||
@Schema(description = "Statut d'activation du compte",
|
||||
example = "true",
|
||||
defaultValue = "true")
|
||||
@JsonProperty("active")
|
||||
private boolean active = true;
|
||||
|
||||
@Schema(description = "Date de création")
|
||||
/**
|
||||
* Date et heure de création du compte.
|
||||
*/
|
||||
@Schema(description = "Date et heure de création du compte",
|
||||
example = "2024-01-15T10:30:00",
|
||||
accessMode = Schema.AccessMode.READ_ONLY)
|
||||
@JsonProperty("createdAt")
|
||||
private LocalDateTime createdAt;
|
||||
|
||||
@Schema(description = "Date de dernière modification")
|
||||
/**
|
||||
* Date et heure de dernière modification du profil.
|
||||
*/
|
||||
@Schema(description = "Date et heure de dernière modification",
|
||||
example = "2024-01-20T14:45:00",
|
||||
accessMode = Schema.AccessMode.READ_ONLY)
|
||||
@JsonProperty("updatedAt")
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@Schema(description = "Date de dernière connexion")
|
||||
/**
|
||||
* Date et heure de dernière connexion réussie.
|
||||
*/
|
||||
@Schema(description = "Date et heure de dernière connexion",
|
||||
example = "2024-01-25T09:15:00",
|
||||
accessMode = Schema.AccessMode.READ_ONLY)
|
||||
@JsonProperty("lastLoginAt")
|
||||
private LocalDateTime lastLoginAt;
|
||||
|
||||
|
||||
236
src/main/java/com/gbcm/server/api/enums/InvoiceStatus.java
Normal file
236
src/main/java/com/gbcm/server/api/enums/InvoiceStatus.java
Normal file
@@ -0,0 +1,236 @@
|
||||
package com.gbcm.server.api.enums;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
/**
|
||||
* Énumération des statuts de facture dans le système GBCM.
|
||||
* Définit les différents états possibles d'une facture.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public enum InvoiceStatus {
|
||||
|
||||
/**
|
||||
* Facture en brouillon, pas encore envoyée.
|
||||
*/
|
||||
DRAFT("draft", "Brouillon", "La facture est en cours de préparation"),
|
||||
|
||||
/**
|
||||
* Facture envoyée au client.
|
||||
*/
|
||||
SENT("sent", "Envoyée", "La facture a été envoyée au client"),
|
||||
|
||||
/**
|
||||
* Facture payée intégralement.
|
||||
*/
|
||||
PAID("paid", "Payée", "La facture a été payée intégralement"),
|
||||
|
||||
/**
|
||||
* Facture partiellement payée.
|
||||
*/
|
||||
PARTIALLY_PAID("partially_paid", "Partiellement payée",
|
||||
"La facture a été partiellement payée"),
|
||||
|
||||
/**
|
||||
* Facture en retard (dépassé la date d'échéance).
|
||||
*/
|
||||
OVERDUE("overdue", "En retard", "La facture a dépassé la date d'échéance"),
|
||||
|
||||
/**
|
||||
* Facture annulée.
|
||||
*/
|
||||
CANCELLED("cancelled", "Annulée", "La facture a été annulée"),
|
||||
|
||||
/**
|
||||
* Facture remboursée.
|
||||
*/
|
||||
REFUNDED("refunded", "Remboursée", "La facture a été remboursée"),
|
||||
|
||||
/**
|
||||
* Facture en litige.
|
||||
*/
|
||||
DISPUTED("disputed", "En litige", "La facture fait l'objet d'un litige");
|
||||
|
||||
/**
|
||||
* Code unique du statut de facture.
|
||||
*/
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* Nom d'affichage du statut.
|
||||
*/
|
||||
private final String displayName;
|
||||
|
||||
/**
|
||||
* Description détaillée du statut.
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération.
|
||||
*
|
||||
* @param code le code unique du statut
|
||||
* @param displayName le nom d'affichage
|
||||
* @param description la description détaillée
|
||||
*/
|
||||
InvoiceStatus(String code, String displayName, String description) {
|
||||
this.code = code;
|
||||
this.displayName = displayName;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le code unique du statut de facture.
|
||||
*
|
||||
* @return le code du statut
|
||||
*/
|
||||
@JsonValue
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nom d'affichage du statut.
|
||||
*
|
||||
* @return le nom d'affichage
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la description détaillée du statut.
|
||||
*
|
||||
* @return la description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve un statut de facture par son code.
|
||||
*
|
||||
* @param code le code à rechercher
|
||||
* @return le statut correspondant
|
||||
* @throws IllegalArgumentException si le code n'est pas trouvé
|
||||
*/
|
||||
public static InvoiceStatus fromCode(String code) {
|
||||
if (code == null) {
|
||||
throw new IllegalArgumentException("Le code ne peut pas être null");
|
||||
}
|
||||
|
||||
for (InvoiceStatus status : values()) {
|
||||
if (status.code.equals(code)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Statut de facture non trouvé pour le code: " + code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la facture est en brouillon.
|
||||
*
|
||||
* @return true si la facture est en brouillon, false sinon
|
||||
*/
|
||||
public boolean isDraft() {
|
||||
return this == DRAFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la facture est finalisée (envoyée ou plus).
|
||||
*
|
||||
* @return true si la facture est finalisée, false sinon
|
||||
*/
|
||||
public boolean isFinalized() {
|
||||
return this != DRAFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la facture est payée (intégralement ou partiellement).
|
||||
*
|
||||
* @return true si la facture est payée, false sinon
|
||||
*/
|
||||
public boolean isPaid() {
|
||||
return this == PAID || this == PARTIALLY_PAID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la facture est entièrement payée.
|
||||
*
|
||||
* @return true si la facture est entièrement payée, false sinon
|
||||
*/
|
||||
public boolean isFullyPaid() {
|
||||
return this == PAID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la facture est en attente de paiement.
|
||||
*
|
||||
* @return true si la facture est en attente de paiement, false sinon
|
||||
*/
|
||||
public boolean isPendingPayment() {
|
||||
return this == SENT || this == PARTIALLY_PAID || this == OVERDUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la facture peut être modifiée.
|
||||
*
|
||||
* @return true si la facture peut être modifiée, false sinon
|
||||
*/
|
||||
public boolean canBeModified() {
|
||||
return this == DRAFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la facture peut être annulée.
|
||||
*
|
||||
* @return true si la facture peut être annulée, false sinon
|
||||
*/
|
||||
public boolean canBeCancelled() {
|
||||
return this == DRAFT || this == SENT || this == OVERDUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la facture peut être remboursée.
|
||||
*
|
||||
* @return true si la facture peut être remboursée, false sinon
|
||||
*/
|
||||
public boolean canBeRefunded() {
|
||||
return this == PAID || this == PARTIALLY_PAID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la facture nécessite une action urgente.
|
||||
*
|
||||
* @return true si une action urgente est nécessaire, false sinon
|
||||
*/
|
||||
public boolean requiresUrgentAction() {
|
||||
return this == OVERDUE || this == DISPUTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la facture génère des revenus.
|
||||
*
|
||||
* @return true si la facture génère des revenus, false sinon
|
||||
*/
|
||||
public boolean generatesRevenue() {
|
||||
return this == PAID || this == PARTIALLY_PAID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'énumération.
|
||||
*
|
||||
* @return une chaîne représentant le statut de facture
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InvoiceStatus{" +
|
||||
"code='" + code + '\'' +
|
||||
", displayName='" + displayName + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
196
src/main/java/com/gbcm/server/api/enums/PaymentStatus.java
Normal file
196
src/main/java/com/gbcm/server/api/enums/PaymentStatus.java
Normal file
@@ -0,0 +1,196 @@
|
||||
package com.gbcm.server.api.enums;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
/**
|
||||
* Énumération des statuts de paiement dans le système GBCM.
|
||||
* Définit les différents états possibles d'un paiement.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public enum PaymentStatus {
|
||||
|
||||
/**
|
||||
* Paiement en attente de traitement.
|
||||
*/
|
||||
PENDING("pending", "En attente", "Le paiement est en cours de traitement"),
|
||||
|
||||
/**
|
||||
* Paiement effectué avec succès.
|
||||
*/
|
||||
PAID("paid", "Payé", "Le paiement a été effectué avec succès"),
|
||||
|
||||
/**
|
||||
* Paiement en retard (dépassé la date d'échéance).
|
||||
*/
|
||||
OVERDUE("overdue", "En retard", "Le paiement a dépassé la date d'échéance"),
|
||||
|
||||
/**
|
||||
* Paiement annulé.
|
||||
*/
|
||||
CANCELLED("cancelled", "Annulé", "Le paiement a été annulé"),
|
||||
|
||||
/**
|
||||
* Paiement échoué.
|
||||
*/
|
||||
FAILED("failed", "Échoué", "Le paiement a échoué lors du traitement"),
|
||||
|
||||
/**
|
||||
* Paiement remboursé.
|
||||
*/
|
||||
REFUNDED("refunded", "Remboursé", "Le paiement a été remboursé"),
|
||||
|
||||
/**
|
||||
* Paiement partiellement remboursé.
|
||||
*/
|
||||
PARTIALLY_REFUNDED("partially_refunded", "Partiellement remboursé",
|
||||
"Le paiement a été partiellement remboursé");
|
||||
|
||||
/**
|
||||
* Code unique du statut de paiement.
|
||||
*/
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* Nom d'affichage du statut.
|
||||
*/
|
||||
private final String displayName;
|
||||
|
||||
/**
|
||||
* Description détaillée du statut.
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération.
|
||||
*
|
||||
* @param code le code unique du statut
|
||||
* @param displayName le nom d'affichage
|
||||
* @param description la description détaillée
|
||||
*/
|
||||
PaymentStatus(String code, String displayName, String description) {
|
||||
this.code = code;
|
||||
this.displayName = displayName;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le code unique du statut de paiement.
|
||||
*
|
||||
* @return le code du statut
|
||||
*/
|
||||
@JsonValue
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nom d'affichage du statut.
|
||||
*
|
||||
* @return le nom d'affichage
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la description détaillée du statut.
|
||||
*
|
||||
* @return la description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve un statut de paiement par son code.
|
||||
*
|
||||
* @param code le code à rechercher
|
||||
* @return le statut correspondant
|
||||
* @throws IllegalArgumentException si le code n'est pas trouvé
|
||||
*/
|
||||
public static PaymentStatus fromCode(String code) {
|
||||
if (code == null) {
|
||||
throw new IllegalArgumentException("Le code ne peut pas être null");
|
||||
}
|
||||
|
||||
for (PaymentStatus status : values()) {
|
||||
if (status.code.equals(code)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Statut de paiement non trouvé pour le code: " + code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le paiement est finalisé (succès ou échec définitif).
|
||||
*
|
||||
* @return true si le paiement est finalisé, false sinon
|
||||
*/
|
||||
public boolean isFinal() {
|
||||
return this == PAID || this == CANCELLED || this == FAILED ||
|
||||
this == REFUNDED || this == PARTIALLY_REFUNDED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le paiement est en cours de traitement.
|
||||
*
|
||||
* @return true si le paiement est en cours, false sinon
|
||||
*/
|
||||
public boolean isPending() {
|
||||
return this == PENDING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le paiement est réussi.
|
||||
*
|
||||
* @return true si le paiement est réussi, false sinon
|
||||
*/
|
||||
public boolean isSuccessful() {
|
||||
return this == PAID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le paiement a échoué.
|
||||
*
|
||||
* @return true si le paiement a échoué, false sinon
|
||||
*/
|
||||
public boolean isFailed() {
|
||||
return this == FAILED || this == CANCELLED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le paiement nécessite une action.
|
||||
*
|
||||
* @return true si une action est nécessaire, false sinon
|
||||
*/
|
||||
public boolean requiresAction() {
|
||||
return this == PENDING || this == OVERDUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le paiement peut être remboursé.
|
||||
*
|
||||
* @return true si le paiement peut être remboursé, false sinon
|
||||
*/
|
||||
public boolean canBeRefunded() {
|
||||
return this == PAID || this == PARTIALLY_REFUNDED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'énumération.
|
||||
*
|
||||
* @return une chaîne représentant le statut de paiement
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PaymentStatus{" +
|
||||
"code='" + code + '\'' +
|
||||
", displayName='" + displayName + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
156
src/main/java/com/gbcm/server/api/enums/ServiceType.java
Normal file
156
src/main/java/com/gbcm/server/api/enums/ServiceType.java
Normal file
@@ -0,0 +1,156 @@
|
||||
package com.gbcm.server.api.enums;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
/**
|
||||
* Énumération des types de services offerts par GBCM.
|
||||
* Définit les différents services disponibles sur la plateforme.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public enum ServiceType {
|
||||
|
||||
/**
|
||||
* Ateliers stratégiques - Programmes de 2 ans avec différents niveaux.
|
||||
*/
|
||||
STRATEGIC_WORKSHOP("strategic_workshop", "Atelier Stratégique",
|
||||
"Programme de développement stratégique sur 2 ans"),
|
||||
|
||||
/**
|
||||
* Coaching individuel - Sessions one-on-one avec un coach.
|
||||
*/
|
||||
ONE_ON_ONE_COACHING("one_on_one_coaching", "Coaching Individuel",
|
||||
"Sessions de coaching personnalisées en tête-à-tête"),
|
||||
|
||||
/**
|
||||
* Coaching à la demande - Abonnement mensuel pour coaching flexible.
|
||||
*/
|
||||
ON_DEMAND_COACHING("on_demand_coaching", "Coaching à la Demande",
|
||||
"Abonnement mensuel pour coaching flexible"),
|
||||
|
||||
/**
|
||||
* Projets spéciaux - Consulting personnalisé pour besoins spécifiques.
|
||||
*/
|
||||
SPECIAL_PROJECT("special_project", "Projet Spécial",
|
||||
"Consulting personnalisé pour besoins spécifiques");
|
||||
|
||||
/**
|
||||
* Code unique du type de service.
|
||||
*/
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* Nom d'affichage du type de service.
|
||||
*/
|
||||
private final String displayName;
|
||||
|
||||
/**
|
||||
* Description détaillée du type de service.
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération.
|
||||
*
|
||||
* @param code le code unique du service
|
||||
* @param displayName le nom d'affichage
|
||||
* @param description la description détaillée
|
||||
*/
|
||||
ServiceType(String code, String displayName, String description) {
|
||||
this.code = code;
|
||||
this.displayName = displayName;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le code unique du type de service.
|
||||
*
|
||||
* @return le code du service
|
||||
*/
|
||||
@JsonValue
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nom d'affichage du type de service.
|
||||
*
|
||||
* @return le nom d'affichage
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la description détaillée du type de service.
|
||||
*
|
||||
* @return la description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve un type de service par son code.
|
||||
*
|
||||
* @param code le code à rechercher
|
||||
* @return le type de service correspondant
|
||||
* @throws IllegalArgumentException si le code n'est pas trouvé
|
||||
*/
|
||||
public static ServiceType fromCode(String code) {
|
||||
if (code == null) {
|
||||
throw new IllegalArgumentException("Le code ne peut pas être null");
|
||||
}
|
||||
|
||||
for (ServiceType type : values()) {
|
||||
if (type.code.equals(code)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Type de service non trouvé pour le code: " + code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le service nécessite un abonnement.
|
||||
*
|
||||
* @return true si le service nécessite un abonnement, false sinon
|
||||
*/
|
||||
public boolean requiresSubscription() {
|
||||
return this == ON_DEMAND_COACHING || this == STRATEGIC_WORKSHOP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le service est facturable à l'heure.
|
||||
*
|
||||
* @return true si le service est facturable à l'heure, false sinon
|
||||
*/
|
||||
public boolean isHourlyBilling() {
|
||||
return this == ONE_ON_ONE_COACHING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le service a un prix fixe.
|
||||
*
|
||||
* @return true si le service a un prix fixe, false sinon
|
||||
*/
|
||||
public boolean hasFixedPrice() {
|
||||
return this == STRATEGIC_WORKSHOP || this == ON_DEMAND_COACHING;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'énumération.
|
||||
*
|
||||
* @return une chaîne représentant le type de service
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ServiceType{" +
|
||||
"code='" + code + '\'' +
|
||||
", displayName='" + displayName + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
213
src/main/java/com/gbcm/server/api/enums/SessionStatus.java
Normal file
213
src/main/java/com/gbcm/server/api/enums/SessionStatus.java
Normal file
@@ -0,0 +1,213 @@
|
||||
package com.gbcm.server.api.enums;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
/**
|
||||
* Énumération des statuts de session de coaching dans le système GBCM.
|
||||
* Définit les différents états possibles d'une session de coaching.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public enum SessionStatus {
|
||||
|
||||
/**
|
||||
* Session programmée mais pas encore commencée.
|
||||
*/
|
||||
SCHEDULED("scheduled", "Programmée", "La session est programmée et confirmée"),
|
||||
|
||||
/**
|
||||
* Session en cours.
|
||||
*/
|
||||
IN_PROGRESS("in_progress", "En cours", "La session est actuellement en cours"),
|
||||
|
||||
/**
|
||||
* Session terminée avec succès.
|
||||
*/
|
||||
COMPLETED("completed", "Terminée", "La session s'est terminée avec succès"),
|
||||
|
||||
/**
|
||||
* Session annulée par le client ou le coach.
|
||||
*/
|
||||
CANCELLED("cancelled", "Annulée", "La session a été annulée"),
|
||||
|
||||
/**
|
||||
* Client absent à la session (no-show).
|
||||
*/
|
||||
NO_SHOW("no_show", "Absence", "Le client ne s'est pas présenté à la session"),
|
||||
|
||||
/**
|
||||
* Session reportée à une date ultérieure.
|
||||
*/
|
||||
RESCHEDULED("rescheduled", "Reportée", "La session a été reportée"),
|
||||
|
||||
/**
|
||||
* Session en attente de confirmation.
|
||||
*/
|
||||
PENDING_CONFIRMATION("pending_confirmation", "En attente de confirmation",
|
||||
"La session est en attente de confirmation");
|
||||
|
||||
/**
|
||||
* Code unique du statut de session.
|
||||
*/
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* Nom d'affichage du statut.
|
||||
*/
|
||||
private final String displayName;
|
||||
|
||||
/**
|
||||
* Description détaillée du statut.
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération.
|
||||
*
|
||||
* @param code le code unique du statut
|
||||
* @param displayName le nom d'affichage
|
||||
* @param description la description détaillée
|
||||
*/
|
||||
SessionStatus(String code, String displayName, String description) {
|
||||
this.code = code;
|
||||
this.displayName = displayName;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le code unique du statut de session.
|
||||
*
|
||||
* @return le code du statut
|
||||
*/
|
||||
@JsonValue
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nom d'affichage du statut.
|
||||
*
|
||||
* @return le nom d'affichage
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la description détaillée du statut.
|
||||
*
|
||||
* @return la description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve un statut de session par son code.
|
||||
*
|
||||
* @param code le code à rechercher
|
||||
* @return le statut correspondant
|
||||
* @throws IllegalArgumentException si le code n'est pas trouvé
|
||||
*/
|
||||
public static SessionStatus fromCode(String code) {
|
||||
if (code == null) {
|
||||
throw new IllegalArgumentException("Le code ne peut pas être null");
|
||||
}
|
||||
|
||||
for (SessionStatus status : values()) {
|
||||
if (status.code.equals(code)) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Statut de session non trouvé pour le code: " + code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la session est active (programmée ou en cours).
|
||||
*
|
||||
* @return true si la session est active, false sinon
|
||||
*/
|
||||
public boolean isActive() {
|
||||
return this == SCHEDULED || this == IN_PROGRESS || this == PENDING_CONFIRMATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la session est terminée (complétée, annulée, ou no-show).
|
||||
*
|
||||
* @return true si la session est terminée, false sinon
|
||||
*/
|
||||
public boolean isFinished() {
|
||||
return this == COMPLETED || this == CANCELLED || this == NO_SHOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la session peut être modifiée.
|
||||
*
|
||||
* @return true si la session peut être modifiée, false sinon
|
||||
*/
|
||||
public boolean canBeModified() {
|
||||
return this == SCHEDULED || this == PENDING_CONFIRMATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la session peut être annulée.
|
||||
*
|
||||
* @return true si la session peut être annulée, false sinon
|
||||
*/
|
||||
public boolean canBeCancelled() {
|
||||
return this == SCHEDULED || this == PENDING_CONFIRMATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la session peut être reportée.
|
||||
*
|
||||
* @return true si la session peut être reportée, false sinon
|
||||
*/
|
||||
public boolean canBeRescheduled() {
|
||||
return this == SCHEDULED || this == PENDING_CONFIRMATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la session nécessite une confirmation.
|
||||
*
|
||||
* @return true si une confirmation est nécessaire, false sinon
|
||||
*/
|
||||
public boolean requiresConfirmation() {
|
||||
return this == PENDING_CONFIRMATION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la session est facturable.
|
||||
*
|
||||
* @return true si la session est facturable, false sinon
|
||||
*/
|
||||
public boolean isBillable() {
|
||||
return this == COMPLETED || this == NO_SHOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la session compte comme réalisée pour les statistiques.
|
||||
*
|
||||
* @return true si la session compte comme réalisée, false sinon
|
||||
*/
|
||||
public boolean countsAsCompleted() {
|
||||
return this == COMPLETED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'énumération.
|
||||
*
|
||||
* @return une chaîne représentant le statut de session
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SessionStatus{" +
|
||||
"code='" + code + '\'' +
|
||||
", displayName='" + displayName + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
224
src/main/java/com/gbcm/server/api/enums/WorkshopPackage.java
Normal file
224
src/main/java/com/gbcm/server/api/enums/WorkshopPackage.java
Normal file
@@ -0,0 +1,224 @@
|
||||
package com.gbcm.server.api.enums;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
/**
|
||||
* Énumération des packages d'ateliers stratégiques GBCM.
|
||||
* Définit les trois niveaux de packages avec leurs prix et caractéristiques.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public enum WorkshopPackage {
|
||||
|
||||
/**
|
||||
* Package Silver - Niveau de base.
|
||||
* Prix: $3,000 pour 2 ans
|
||||
*/
|
||||
SILVER("silver", "Silver", "Package de base pour les ateliers stratégiques",
|
||||
new BigDecimal("3000.00"), 24, "Accès aux ateliers de base et ressources essentielles"),
|
||||
|
||||
/**
|
||||
* Package Gold - Niveau intermédiaire.
|
||||
* Prix: $4,000 pour 2 ans
|
||||
*/
|
||||
GOLD("gold", "Gold", "Package intermédiaire avec services étendus",
|
||||
new BigDecimal("4000.00"), 24, "Accès complet aux ateliers + sessions de coaching mensuelles"),
|
||||
|
||||
/**
|
||||
* Package Platinum - Niveau premium.
|
||||
* Prix: $5,000 pour 2 ans
|
||||
*/
|
||||
PLATINUM("platinum", "Platinum", "Package premium avec tous les services",
|
||||
new BigDecimal("5000.00"), 24, "Accès VIP complet + coaching illimité + support prioritaire");
|
||||
|
||||
/**
|
||||
* Code unique du package.
|
||||
*/
|
||||
private final String code;
|
||||
|
||||
/**
|
||||
* Nom d'affichage du package.
|
||||
*/
|
||||
private final String displayName;
|
||||
|
||||
/**
|
||||
* Description courte du package.
|
||||
*/
|
||||
private final String description;
|
||||
|
||||
/**
|
||||
* Prix total du package en USD.
|
||||
*/
|
||||
private final BigDecimal price;
|
||||
|
||||
/**
|
||||
* Durée du package en mois.
|
||||
*/
|
||||
private final int durationMonths;
|
||||
|
||||
/**
|
||||
* Description détaillée des services inclus.
|
||||
*/
|
||||
private final String features;
|
||||
|
||||
/**
|
||||
* Constructeur de l'énumération.
|
||||
*
|
||||
* @param code le code unique du package
|
||||
* @param displayName le nom d'affichage
|
||||
* @param description la description courte
|
||||
* @param price le prix total
|
||||
* @param durationMonths la durée en mois
|
||||
* @param features la description des services inclus
|
||||
*/
|
||||
WorkshopPackage(String code, String displayName, String description,
|
||||
BigDecimal price, int durationMonths, String features) {
|
||||
this.code = code;
|
||||
this.displayName = displayName;
|
||||
this.description = description;
|
||||
this.price = price;
|
||||
this.durationMonths = durationMonths;
|
||||
this.features = features;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le code unique du package.
|
||||
*
|
||||
* @return le code du package
|
||||
*/
|
||||
@JsonValue
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nom d'affichage du package.
|
||||
*
|
||||
* @return le nom d'affichage
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la description courte du package.
|
||||
*
|
||||
* @return la description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le prix total du package.
|
||||
*
|
||||
* @return le prix en USD
|
||||
*/
|
||||
public BigDecimal getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la durée du package en mois.
|
||||
*
|
||||
* @return la durée en mois
|
||||
*/
|
||||
public int getDurationMonths() {
|
||||
return durationMonths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la description des services inclus.
|
||||
*
|
||||
* @return la description des services
|
||||
*/
|
||||
public String getFeatures() {
|
||||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calcule le prix mensuel du package.
|
||||
*
|
||||
* @return le prix mensuel en USD
|
||||
*/
|
||||
public BigDecimal getMonthlyPrice() {
|
||||
return price.divide(new BigDecimal(durationMonths), 2, java.math.RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trouve un package par son code.
|
||||
*
|
||||
* @param code le code à rechercher
|
||||
* @return le package correspondant
|
||||
* @throws IllegalArgumentException si le code n'est pas trouvé
|
||||
*/
|
||||
public static WorkshopPackage fromCode(String code) {
|
||||
if (code == null) {
|
||||
throw new IllegalArgumentException("Le code ne peut pas être null");
|
||||
}
|
||||
|
||||
for (WorkshopPackage pkg : values()) {
|
||||
if (pkg.code.equalsIgnoreCase(code)) {
|
||||
return pkg;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Package non trouvé pour le code: " + code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si c'est un package premium.
|
||||
*
|
||||
* @return true si c'est le package Platinum, false sinon
|
||||
*/
|
||||
public boolean isPremium() {
|
||||
return this == PLATINUM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le package inclut du coaching.
|
||||
*
|
||||
* @return true si le package inclut du coaching, false sinon
|
||||
*/
|
||||
public boolean includesCoaching() {
|
||||
return this == GOLD || this == PLATINUM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le package inclut un support prioritaire.
|
||||
*
|
||||
* @return true si le package inclut un support prioritaire, false sinon
|
||||
*/
|
||||
public boolean hasPrioritySupport() {
|
||||
return this == PLATINUM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare les packages par prix (ordre croissant).
|
||||
*
|
||||
* @param other l'autre package à comparer
|
||||
* @return résultat de la comparaison (-1, 0, 1)
|
||||
*/
|
||||
public int compareByPrice(WorkshopPackage other) {
|
||||
return this.price.compareTo(other.price);
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'énumération.
|
||||
*
|
||||
* @return une chaîne représentant le package
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WorkshopPackage{" +
|
||||
"code='" + code + '\'' +
|
||||
", displayName='" + displayName + '\'' +
|
||||
", price=" + price +
|
||||
", durationMonths=" + durationMonths +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.gbcm.server.api.exceptions;
|
||||
|
||||
/**
|
||||
* Exception levée lors d'erreurs d'authentification.
|
||||
* Utilisée pour les cas d'identifiants invalides, tokens expirés, etc.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public class AuthenticationException extends GBCMException {
|
||||
|
||||
/**
|
||||
* Constructeur avec message.
|
||||
*
|
||||
* @param message le message d'erreur d'authentification
|
||||
*/
|
||||
public AuthenticationException(String message) {
|
||||
super(message, "AUTHENTICATION_ERROR");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message et cause.
|
||||
*
|
||||
* @param message le message d'erreur d'authentification
|
||||
* @param cause la cause de l'exception
|
||||
*/
|
||||
public AuthenticationException(String message, Throwable cause) {
|
||||
super(message, "AUTHENTICATION_ERROR", cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message et code d'erreur spécifique.
|
||||
*
|
||||
* @param message le message d'erreur d'authentification
|
||||
* @param errorCode le code d'erreur spécifique
|
||||
*/
|
||||
public AuthenticationException(String message, String errorCode) {
|
||||
super(message, errorCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur complet.
|
||||
*
|
||||
* @param message le message d'erreur d'authentification
|
||||
* @param errorCode le code d'erreur spécifique
|
||||
* @param cause la cause de l'exception
|
||||
*/
|
||||
public AuthenticationException(String message, String errorCode, Throwable cause) {
|
||||
super(message, errorCode, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.gbcm.server.api.exceptions;
|
||||
|
||||
/**
|
||||
* Exception levée lors d'erreurs d'autorisation.
|
||||
* Utilisée quand un utilisateur authentifié n'a pas les permissions nécessaires.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public class AuthorizationException extends GBCMException {
|
||||
|
||||
/**
|
||||
* Constructeur avec message.
|
||||
*
|
||||
* @param message le message d'erreur d'autorisation
|
||||
*/
|
||||
public AuthorizationException(String message) {
|
||||
super(message, "AUTHORIZATION_ERROR");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message et cause.
|
||||
*
|
||||
* @param message le message d'erreur d'autorisation
|
||||
* @param cause la cause de l'exception
|
||||
*/
|
||||
public AuthorizationException(String message, Throwable cause) {
|
||||
super(message, "AUTHORIZATION_ERROR", cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message et code d'erreur spécifique.
|
||||
*
|
||||
* @param message le message d'erreur d'autorisation
|
||||
* @param errorCode le code d'erreur spécifique
|
||||
*/
|
||||
public AuthorizationException(String message, String errorCode) {
|
||||
super(message, errorCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur complet.
|
||||
*
|
||||
* @param message le message d'erreur d'autorisation
|
||||
* @param errorCode le code d'erreur spécifique
|
||||
* @param cause la cause de l'exception
|
||||
*/
|
||||
public AuthorizationException(String message, String errorCode, Throwable cause) {
|
||||
super(message, errorCode, cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.gbcm.server.api.exceptions;
|
||||
|
||||
/**
|
||||
* Exception levée lors de violations des règles métier GBCM.
|
||||
* Utilisée pour les cas où une opération viole une règle business spécifique.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public class BusinessRuleException extends GBCMException {
|
||||
|
||||
/**
|
||||
* Nom de la règle métier violée.
|
||||
*/
|
||||
private final String ruleName;
|
||||
|
||||
/**
|
||||
* Constructeur avec message.
|
||||
*
|
||||
* @param message le message d'erreur de règle métier
|
||||
*/
|
||||
public BusinessRuleException(String message) {
|
||||
super(message, "BUSINESS_RULE_VIOLATION");
|
||||
this.ruleName = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message et nom de règle.
|
||||
*
|
||||
* @param message le message d'erreur de règle métier
|
||||
* @param ruleName le nom de la règle violée
|
||||
*/
|
||||
public BusinessRuleException(String message, String ruleName) {
|
||||
super(message, "BUSINESS_RULE_VIOLATION");
|
||||
this.ruleName = ruleName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message, nom de règle et cause.
|
||||
*
|
||||
* @param message le message d'erreur de règle métier
|
||||
* @param ruleName le nom de la règle violée
|
||||
* @param cause la cause de l'exception
|
||||
*/
|
||||
public BusinessRuleException(String message, String ruleName, Throwable cause) {
|
||||
super(message, "BUSINESS_RULE_VIOLATION", cause);
|
||||
this.ruleName = ruleName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le nom de la règle métier violée.
|
||||
*
|
||||
* @return le nom de la règle
|
||||
*/
|
||||
public String getRuleName() {
|
||||
return ruleName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'exception.
|
||||
*
|
||||
* @return une chaîne représentant l'exception
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BusinessRuleException{" +
|
||||
"errorCode='" + getErrorCode() + '\'' +
|
||||
", message='" + getMessage() + '\'' +
|
||||
", ruleName='" + ruleName + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package com.gbcm.server.api.exceptions;
|
||||
|
||||
/**
|
||||
* Exception de base pour toutes les exceptions métier de la plateforme GBCM.
|
||||
* Toutes les autres exceptions spécifiques héritent de cette classe.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public class GBCMException extends Exception {
|
||||
|
||||
/**
|
||||
* Code d'erreur unique pour identifier le type d'exception.
|
||||
*/
|
||||
private final String errorCode;
|
||||
|
||||
/**
|
||||
* Constructeur avec message.
|
||||
*
|
||||
* @param message le message d'erreur
|
||||
*/
|
||||
public GBCMException(String message) {
|
||||
super(message);
|
||||
this.errorCode = "GBCM_ERROR";
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message et code d'erreur.
|
||||
*
|
||||
* @param message le message d'erreur
|
||||
* @param errorCode le code d'erreur unique
|
||||
*/
|
||||
public GBCMException(String message, String errorCode) {
|
||||
super(message);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message et cause.
|
||||
*
|
||||
* @param message le message d'erreur
|
||||
* @param cause la cause de l'exception
|
||||
*/
|
||||
public GBCMException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.errorCode = "GBCM_ERROR";
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur complet.
|
||||
*
|
||||
* @param message le message d'erreur
|
||||
* @param errorCode le code d'erreur unique
|
||||
* @param cause la cause de l'exception
|
||||
*/
|
||||
public GBCMException(String message, String errorCode, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.errorCode = errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le code d'erreur unique.
|
||||
*
|
||||
* @return le code d'erreur
|
||||
*/
|
||||
public String getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'exception.
|
||||
*
|
||||
* @return une chaîne représentant l'exception
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GBCMException{" +
|
||||
"errorCode='" + errorCode + '\'' +
|
||||
", message='" + getMessage() + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.gbcm.server.api.exceptions;
|
||||
|
||||
/**
|
||||
* Exception levée quand une ressource demandée n'est pas trouvée.
|
||||
* Utilisée pour les cas où un utilisateur, client, session, etc. n'existe pas.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public class ResourceNotFoundException extends GBCMException {
|
||||
|
||||
/**
|
||||
* Type de ressource non trouvée.
|
||||
*/
|
||||
private final String resourceType;
|
||||
|
||||
/**
|
||||
* Identifiant de la ressource non trouvée.
|
||||
*/
|
||||
private final Object resourceId;
|
||||
|
||||
/**
|
||||
* Constructeur avec message.
|
||||
*
|
||||
* @param message le message d'erreur
|
||||
*/
|
||||
public ResourceNotFoundException(String message) {
|
||||
super(message, "RESOURCE_NOT_FOUND");
|
||||
this.resourceType = null;
|
||||
this.resourceId = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec type et identifiant de ressource.
|
||||
*
|
||||
* @param resourceType le type de ressource (ex: "User", "Client")
|
||||
* @param resourceId l'identifiant de la ressource
|
||||
*/
|
||||
public ResourceNotFoundException(String resourceType, Object resourceId) {
|
||||
super(String.format("%s avec l'identifiant '%s' non trouvé", resourceType, resourceId),
|
||||
"RESOURCE_NOT_FOUND");
|
||||
this.resourceType = resourceType;
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message, type et identifiant.
|
||||
*
|
||||
* @param message le message d'erreur personnalisé
|
||||
* @param resourceType le type de ressource
|
||||
* @param resourceId l'identifiant de la ressource
|
||||
*/
|
||||
public ResourceNotFoundException(String message, String resourceType, Object resourceId) {
|
||||
super(message, "RESOURCE_NOT_FOUND");
|
||||
this.resourceType = resourceType;
|
||||
this.resourceId = resourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message et cause.
|
||||
*
|
||||
* @param message le message d'erreur
|
||||
* @param cause la cause de l'exception
|
||||
*/
|
||||
public ResourceNotFoundException(String message, Throwable cause) {
|
||||
super(message, "RESOURCE_NOT_FOUND", cause);
|
||||
this.resourceType = null;
|
||||
this.resourceId = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le type de ressource non trouvée.
|
||||
*
|
||||
* @return le type de ressource
|
||||
*/
|
||||
public String getResourceType() {
|
||||
return resourceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne l'identifiant de la ressource non trouvée.
|
||||
*
|
||||
* @return l'identifiant de la ressource
|
||||
*/
|
||||
public Object getResourceId() {
|
||||
return resourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'exception.
|
||||
*
|
||||
* @return une chaîne représentant l'exception
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ResourceNotFoundException{" +
|
||||
"errorCode='" + getErrorCode() + '\'' +
|
||||
", message='" + getMessage() + '\'' +
|
||||
", resourceType='" + resourceType + '\'' +
|
||||
", resourceId=" + resourceId +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.gbcm.server.api.exceptions;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Exception levée lors d'erreurs de validation des données.
|
||||
* Contient des détails sur les champs en erreur et leurs messages.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
public class ValidationException extends GBCMException {
|
||||
|
||||
/**
|
||||
* Map des erreurs de validation par champ.
|
||||
*/
|
||||
private final Map<String, List<String>> fieldErrors;
|
||||
|
||||
/**
|
||||
* Constructeur avec message.
|
||||
*
|
||||
* @param message le message d'erreur de validation
|
||||
*/
|
||||
public ValidationException(String message) {
|
||||
super(message, "VALIDATION_ERROR");
|
||||
this.fieldErrors = Map.of();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message et erreurs de champs.
|
||||
*
|
||||
* @param message le message d'erreur de validation
|
||||
* @param fieldErrors les erreurs par champ
|
||||
*/
|
||||
public ValidationException(String message, Map<String, List<String>> fieldErrors) {
|
||||
super(message, "VALIDATION_ERROR");
|
||||
this.fieldErrors = fieldErrors != null ? fieldErrors : Map.of();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructeur avec message, erreurs de champs et cause.
|
||||
*
|
||||
* @param message le message d'erreur de validation
|
||||
* @param fieldErrors les erreurs par champ
|
||||
* @param cause la cause de l'exception
|
||||
*/
|
||||
public ValidationException(String message, Map<String, List<String>> fieldErrors, Throwable cause) {
|
||||
super(message, "VALIDATION_ERROR", cause);
|
||||
this.fieldErrors = fieldErrors != null ? fieldErrors : Map.of();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les erreurs de validation par champ.
|
||||
*
|
||||
* @return une map des erreurs par champ
|
||||
*/
|
||||
public Map<String, List<String>> getFieldErrors() {
|
||||
return fieldErrors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'exception contient des erreurs de champs.
|
||||
*
|
||||
* @return true si des erreurs de champs sont présentes, false sinon
|
||||
*/
|
||||
public boolean hasFieldErrors() {
|
||||
return !fieldErrors.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les erreurs pour un champ spécifique.
|
||||
*
|
||||
* @param fieldName le nom du champ
|
||||
* @return la liste des erreurs pour ce champ, ou une liste vide
|
||||
*/
|
||||
public List<String> getFieldErrors(String fieldName) {
|
||||
return fieldErrors.getOrDefault(fieldName, List.of());
|
||||
}
|
||||
|
||||
/**
|
||||
* Représentation textuelle de l'exception.
|
||||
*
|
||||
* @return une chaîne représentant l'exception
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ValidationException{" +
|
||||
"errorCode='" + getErrorCode() + '\'' +
|
||||
", message='" + getMessage() + '\'' +
|
||||
", fieldErrorsCount=" + fieldErrors.size() +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -2,24 +2,36 @@ package com.gbcm.server.api.interfaces;
|
||||
|
||||
import com.gbcm.server.api.dto.auth.LoginRequestDTO;
|
||||
import com.gbcm.server.api.dto.auth.LoginResponseDTO;
|
||||
import com.gbcm.server.api.dto.auth.PasswordResetDTO;
|
||||
import com.gbcm.server.api.dto.common.SuccessResponseDTO;
|
||||
import com.gbcm.server.api.dto.user.UserDTO;
|
||||
import com.gbcm.server.api.exceptions.AuthenticationException;
|
||||
import com.gbcm.server.api.exceptions.GBCMException;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* Interface de service pour l'authentification
|
||||
* Interface de service pour l'authentification et l'autorisation.
|
||||
* Fournit tous les endpoints nécessaires pour la gestion des sessions utilisateur,
|
||||
* l'authentification JWT et la réinitialisation des mots de passe.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Path("/auth")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Tag(name = "Authentication", description = "Services d'authentification et autorisation")
|
||||
@Tag(name = "Authentication", description = "Services d'authentification et autorisation GBCM")
|
||||
public interface AuthService {
|
||||
|
||||
/**
|
||||
|
||||
263
src/main/java/com/gbcm/server/api/interfaces/UserService.java
Normal file
263
src/main/java/com/gbcm/server/api/interfaces/UserService.java
Normal file
@@ -0,0 +1,263 @@
|
||||
package com.gbcm.server.api.interfaces;
|
||||
|
||||
import com.gbcm.server.api.dto.common.PagedResultDTO;
|
||||
import com.gbcm.server.api.dto.common.SuccessResponseDTO;
|
||||
import com.gbcm.server.api.dto.user.CreateUserDTO;
|
||||
import com.gbcm.server.api.dto.user.UpdateUserDTO;
|
||||
import com.gbcm.server.api.dto.user.UserDTO;
|
||||
import com.gbcm.server.api.enums.UserRole;
|
||||
import com.gbcm.server.api.exceptions.AuthorizationException;
|
||||
import com.gbcm.server.api.exceptions.GBCMException;
|
||||
import com.gbcm.server.api.exceptions.ResourceNotFoundException;
|
||||
import com.gbcm.server.api.exceptions.ValidationException;
|
||||
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
/**
|
||||
* Interface de service pour la gestion des utilisateurs.
|
||||
* Fournit tous les endpoints CRUD pour les utilisateurs de la plateforme GBCM.
|
||||
*
|
||||
* @author GBCM Development Team
|
||||
* @version 1.0
|
||||
* @since 1.0
|
||||
*/
|
||||
@Path("/users")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Tag(name = "Users", description = "Gestion des utilisateurs GBCM")
|
||||
public interface UserService {
|
||||
|
||||
/**
|
||||
* Récupère la liste paginée des utilisateurs.
|
||||
*/
|
||||
@GET
|
||||
@RolesAllowed({"ADMIN", "MANAGER"})
|
||||
@Operation(
|
||||
summary = "Liste des utilisateurs",
|
||||
description = "Récupère la liste paginée des utilisateurs avec filtres optionnels"
|
||||
)
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "Liste récupérée avec succès",
|
||||
content = @Content(schema = @Schema(implementation = PagedResultDTO.class))),
|
||||
@ApiResponse(responseCode = "401", description = "Non authentifié"),
|
||||
@ApiResponse(responseCode = "403", description = "Accès refusé - permissions insuffisantes")
|
||||
})
|
||||
PagedResultDTO<UserDTO> getUsers(
|
||||
@Parameter(description = "Numéro de page (commence à 0)", example = "0")
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
|
||||
@Parameter(description = "Taille de page", example = "20")
|
||||
@QueryParam("size") @DefaultValue("20") int size,
|
||||
|
||||
@Parameter(description = "Tri (ex: firstName,asc ou email,desc)")
|
||||
@QueryParam("sort") String sort,
|
||||
|
||||
@Parameter(description = "Filtre par rôle")
|
||||
@QueryParam("role") UserRole role,
|
||||
|
||||
@Parameter(description = "Filtre par statut actif")
|
||||
@QueryParam("active") Boolean active,
|
||||
|
||||
@Parameter(description = "Recherche par nom ou email")
|
||||
@QueryParam("search") String search
|
||||
) throws AuthorizationException;
|
||||
|
||||
/**
|
||||
* Récupère un utilisateur par son ID.
|
||||
*/
|
||||
@GET
|
||||
@Path("/{id}")
|
||||
@RolesAllowed({"ADMIN", "MANAGER", "COACH"})
|
||||
@Operation(
|
||||
summary = "Utilisateur par ID",
|
||||
description = "Récupère les détails d'un utilisateur par son identifiant"
|
||||
)
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "Utilisateur trouvé",
|
||||
content = @Content(schema = @Schema(implementation = UserDTO.class))),
|
||||
@ApiResponse(responseCode = "404", description = "Utilisateur non trouvé"),
|
||||
@ApiResponse(responseCode = "401", description = "Non authentifié"),
|
||||
@ApiResponse(responseCode = "403", description = "Accès refusé")
|
||||
})
|
||||
UserDTO getUserById(
|
||||
@Parameter(description = "ID de l'utilisateur", required = true, example = "1")
|
||||
@PathParam("id") Long id
|
||||
) throws ResourceNotFoundException, AuthorizationException;
|
||||
|
||||
/**
|
||||
* Crée un nouvel utilisateur.
|
||||
*/
|
||||
@POST
|
||||
@RolesAllowed({"ADMIN"})
|
||||
@Operation(
|
||||
summary = "Créer un utilisateur",
|
||||
description = "Crée un nouvel utilisateur dans le système"
|
||||
)
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "201", description = "Utilisateur créé avec succès",
|
||||
content = @Content(schema = @Schema(implementation = UserDTO.class))),
|
||||
@ApiResponse(responseCode = "400", description = "Données invalides"),
|
||||
@ApiResponse(responseCode = "409", description = "Email déjà utilisé"),
|
||||
@ApiResponse(responseCode = "401", description = "Non authentifié"),
|
||||
@ApiResponse(responseCode = "403", description = "Accès refusé - seuls les admins peuvent créer des utilisateurs")
|
||||
})
|
||||
UserDTO createUser(
|
||||
@Parameter(description = "Données du nouvel utilisateur", required = true)
|
||||
@Valid CreateUserDTO createUserDTO
|
||||
) throws ValidationException, GBCMException, AuthorizationException;
|
||||
|
||||
/**
|
||||
* Met à jour un utilisateur existant.
|
||||
*/
|
||||
@PUT
|
||||
@Path("/{id}")
|
||||
@RolesAllowed({"ADMIN", "MANAGER"})
|
||||
@Operation(
|
||||
summary = "Mettre à jour un utilisateur",
|
||||
description = "Met à jour les informations d'un utilisateur existant"
|
||||
)
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "Utilisateur mis à jour avec succès",
|
||||
content = @Content(schema = @Schema(implementation = UserDTO.class))),
|
||||
@ApiResponse(responseCode = "404", description = "Utilisateur non trouvé"),
|
||||
@ApiResponse(responseCode = "400", description = "Données invalides"),
|
||||
@ApiResponse(responseCode = "409", description = "Email déjà utilisé par un autre utilisateur"),
|
||||
@ApiResponse(responseCode = "401", description = "Non authentifié"),
|
||||
@ApiResponse(responseCode = "403", description = "Accès refusé")
|
||||
})
|
||||
UserDTO updateUser(
|
||||
@Parameter(description = "ID de l'utilisateur", required = true, example = "1")
|
||||
@PathParam("id") Long id,
|
||||
|
||||
@Parameter(description = "Données de mise à jour", required = true)
|
||||
@Valid UpdateUserDTO updateUserDTO
|
||||
) throws ResourceNotFoundException, ValidationException, GBCMException, AuthorizationException;
|
||||
|
||||
/**
|
||||
* Supprime un utilisateur (soft delete).
|
||||
*/
|
||||
@DELETE
|
||||
@Path("/{id}")
|
||||
@RolesAllowed({"ADMIN"})
|
||||
@Operation(
|
||||
summary = "Supprimer un utilisateur",
|
||||
description = "Supprime un utilisateur du système (soft delete)"
|
||||
)
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "Utilisateur supprimé avec succès"),
|
||||
@ApiResponse(responseCode = "404", description = "Utilisateur non trouvé"),
|
||||
@ApiResponse(responseCode = "401", description = "Non authentifié"),
|
||||
@ApiResponse(responseCode = "403", description = "Accès refusé - seuls les admins peuvent supprimer des utilisateurs")
|
||||
})
|
||||
SuccessResponseDTO<Void> deleteUser(
|
||||
@Parameter(description = "ID de l'utilisateur", required = true, example = "1")
|
||||
@PathParam("id") Long id
|
||||
) throws ResourceNotFoundException, AuthorizationException;
|
||||
|
||||
/**
|
||||
* Active ou désactive un utilisateur.
|
||||
*/
|
||||
@PUT
|
||||
@Path("/{id}/status")
|
||||
@RolesAllowed({"ADMIN", "MANAGER"})
|
||||
@Operation(
|
||||
summary = "Changer le statut d'un utilisateur",
|
||||
description = "Active ou désactive un compte utilisateur"
|
||||
)
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "Statut modifié avec succès",
|
||||
content = @Content(schema = @Schema(implementation = UserDTO.class))),
|
||||
@ApiResponse(responseCode = "404", description = "Utilisateur non trouvé"),
|
||||
@ApiResponse(responseCode = "401", description = "Non authentifié"),
|
||||
@ApiResponse(responseCode = "403", description = "Accès refusé")
|
||||
})
|
||||
UserDTO changeUserStatus(
|
||||
@Parameter(description = "ID de l'utilisateur", required = true, example = "1")
|
||||
@PathParam("id") Long id,
|
||||
|
||||
@Parameter(description = "Nouveau statut", required = true, example = "true")
|
||||
@FormParam("active") boolean active
|
||||
) throws ResourceNotFoundException, AuthorizationException;
|
||||
|
||||
/**
|
||||
* Récupère le profil de l'utilisateur connecté.
|
||||
*/
|
||||
@GET
|
||||
@Path("/profile")
|
||||
@RolesAllowed({"ADMIN", "MANAGER", "COACH", "CLIENT", "PROSPECT"})
|
||||
@Operation(
|
||||
summary = "Profil utilisateur",
|
||||
description = "Récupère le profil de l'utilisateur actuellement connecté"
|
||||
)
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "Profil récupéré avec succès",
|
||||
content = @Content(schema = @Schema(implementation = UserDTO.class))),
|
||||
@ApiResponse(responseCode = "401", description = "Non authentifié")
|
||||
})
|
||||
UserDTO getCurrentUserProfile(
|
||||
@Parameter(description = "Token d'authentification", required = true)
|
||||
@HeaderParam("Authorization") String authToken
|
||||
) throws AuthorizationException;
|
||||
|
||||
/**
|
||||
* Met à jour le profil de l'utilisateur connecté.
|
||||
*/
|
||||
@PUT
|
||||
@Path("/profile")
|
||||
@RolesAllowed({"ADMIN", "MANAGER", "COACH", "CLIENT", "PROSPECT"})
|
||||
@Operation(
|
||||
summary = "Mettre à jour le profil",
|
||||
description = "Met à jour le profil de l'utilisateur actuellement connecté"
|
||||
)
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "Profil mis à jour avec succès",
|
||||
content = @Content(schema = @Schema(implementation = UserDTO.class))),
|
||||
@ApiResponse(responseCode = "400", description = "Données invalides"),
|
||||
@ApiResponse(responseCode = "409", description = "Email déjà utilisé"),
|
||||
@ApiResponse(responseCode = "401", description = "Non authentifié")
|
||||
})
|
||||
UserDTO updateCurrentUserProfile(
|
||||
@Parameter(description = "Token d'authentification", required = true)
|
||||
@HeaderParam("Authorization") String authToken,
|
||||
|
||||
@Parameter(description = "Données de mise à jour du profil", required = true)
|
||||
@Valid UpdateUserDTO updateUserDTO
|
||||
) throws ValidationException, GBCMException, AuthorizationException;
|
||||
|
||||
/**
|
||||
* Recherche d'utilisateurs par critères.
|
||||
*/
|
||||
@GET
|
||||
@Path("/search")
|
||||
@RolesAllowed({"ADMIN", "MANAGER", "COACH"})
|
||||
@Operation(
|
||||
summary = "Rechercher des utilisateurs",
|
||||
description = "Recherche d'utilisateurs par différents critères"
|
||||
)
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "Résultats de recherche",
|
||||
content = @Content(schema = @Schema(implementation = PagedResultDTO.class))),
|
||||
@ApiResponse(responseCode = "401", description = "Non authentifié"),
|
||||
@ApiResponse(responseCode = "403", description = "Accès refusé")
|
||||
})
|
||||
PagedResultDTO<UserDTO> searchUsers(
|
||||
@Parameter(description = "Terme de recherche", required = true)
|
||||
@QueryParam("q") String query,
|
||||
|
||||
@Parameter(description = "Numéro de page", example = "0")
|
||||
@QueryParam("page") @DefaultValue("0") int page,
|
||||
|
||||
@Parameter(description = "Taille de page", example = "20")
|
||||
@QueryParam("size") @DefaultValue("20") int size
|
||||
) throws AuthorizationException;
|
||||
}
|
||||
Reference in New Issue
Block a user