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>
|
<version>${jakarta.ws.rs.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Jakarta Annotation (for @RolesAllowed) -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.annotation</groupId>
|
||||||
|
<artifactId>jakarta.annotation-api</artifactId>
|
||||||
|
<version>2.1.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Jackson Annotations -->
|
<!-- Jackson Annotations -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
@@ -70,26 +77,7 @@
|
|||||||
<version>3.11.0</version>
|
<version>3.11.0</version>
|
||||||
</plugin>
|
</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>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@@ -1,72 +1,148 @@
|
|||||||
package com.gbcm.server.api.dto.auth;
|
package com.gbcm.server.api.dto.auth;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.Email;
|
import jakarta.validation.constraints.Email;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.Size;
|
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 {
|
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")
|
@JsonProperty("email")
|
||||||
@NotBlank(message = "L'email est obligatoire")
|
@NotBlank(message = "L'email est obligatoire")
|
||||||
@Email(message = "Format d'email invalide")
|
@Email(message = "Format d'email invalide")
|
||||||
private String email;
|
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")
|
@JsonProperty("password")
|
||||||
@NotBlank(message = "Le mot de passe est obligatoire")
|
@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")
|
@Size(min = 6, max = 100, message = "Le mot de passe doit contenir entre 6 et 100 caractères")
|
||||||
private String password;
|
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")
|
@JsonProperty("rememberMe")
|
||||||
private boolean rememberMe = false;
|
private boolean rememberMe = false;
|
||||||
|
|
||||||
// Constructeurs
|
/**
|
||||||
|
* Constructeur par défaut.
|
||||||
|
*/
|
||||||
public LoginRequestDTO() {}
|
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) {
|
public LoginRequestDTO(String email, String password) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.password = password;
|
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) {
|
public LoginRequestDTO(String email, String password, boolean rememberMe) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.password = password;
|
this.password = password;
|
||||||
this.rememberMe = rememberMe;
|
this.rememberMe = rememberMe;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Getters et Setters
|
/**
|
||||||
|
* Retourne l'adresse email de l'utilisateur.
|
||||||
|
*
|
||||||
|
* @return l'adresse email
|
||||||
|
*/
|
||||||
public String getEmail() {
|
public String getEmail() {
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit l'adresse email de l'utilisateur.
|
||||||
|
*
|
||||||
|
* @param email l'adresse email à définir
|
||||||
|
*/
|
||||||
public void setEmail(String email) {
|
public void setEmail(String email) {
|
||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retourne le mot de passe de l'utilisateur.
|
||||||
|
*
|
||||||
|
* @return le mot de passe
|
||||||
|
*/
|
||||||
public String getPassword() {
|
public String getPassword() {
|
||||||
return password;
|
return password;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit le mot de passe de l'utilisateur.
|
||||||
|
*
|
||||||
|
* @param password le mot de passe à définir
|
||||||
|
*/
|
||||||
public void setPassword(String password) {
|
public void setPassword(String password) {
|
||||||
this.password = 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() {
|
public boolean isRememberMe() {
|
||||||
return rememberMe;
|
return rememberMe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Définit l'option "se souvenir de moi".
|
||||||
|
*
|
||||||
|
* @param rememberMe true pour activer l'option, false sinon
|
||||||
|
*/
|
||||||
public void setRememberMe(boolean rememberMe) {
|
public void setRememberMe(boolean rememberMe) {
|
||||||
this.rememberMe = 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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "LoginRequestDTO{" +
|
return "LoginRequestDTO{" +
|
||||||
|
|||||||
@@ -1,49 +1,100 @@
|
|||||||
package com.gbcm.server.api.dto.auth;
|
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 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 {
|
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")
|
@JsonProperty("success")
|
||||||
private boolean 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")
|
@JsonProperty("message")
|
||||||
private String 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")
|
@JsonProperty("token")
|
||||||
private String 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")
|
@JsonProperty("expiresAt")
|
||||||
private LocalDateTime 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")
|
@Schema(description = "Informations utilisateur")
|
||||||
@JsonProperty("user")
|
@JsonProperty("user")
|
||||||
private UserDTO 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")
|
@JsonProperty("refreshToken")
|
||||||
private String refreshToken;
|
private String refreshToken;
|
||||||
|
|
||||||
// Constructeurs
|
/**
|
||||||
|
* Constructeur par défaut.
|
||||||
|
*/
|
||||||
public LoginResponseDTO() {}
|
public LoginResponseDTO() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur avec succès et message.
|
||||||
|
*
|
||||||
|
* @param success indicateur de succès
|
||||||
|
* @param message message descriptif
|
||||||
|
*/
|
||||||
public LoginResponseDTO(boolean success, String message) {
|
public LoginResponseDTO(boolean success, String message) {
|
||||||
this.success = success;
|
this.success = success;
|
||||||
this.message = message;
|
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) {
|
public static LoginResponseDTO success(String token, LocalDateTime expiresAt, UserDTO user) {
|
||||||
LoginResponseDTO response = new LoginResponseDTO(true, "Connexion réussie");
|
LoginResponseDTO response = new LoginResponseDTO(true, "Connexion réussie");
|
||||||
response.setToken(token);
|
response.setToken(token);
|
||||||
@@ -52,6 +103,27 @@ public class LoginResponseDTO {
|
|||||||
return response;
|
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) {
|
public static LoginResponseDTO failure(String message) {
|
||||||
return new LoginResponseDTO(false, 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;
|
package com.gbcm.server.api.dto.user;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.gbcm.server.api.enums.UserRole;
|
import com.gbcm.server.api.enums.UserRole;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.Email;
|
import jakarta.validation.constraints.Email;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
import jakarta.validation.constraints.NotNull;
|
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 {
|
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")
|
@JsonProperty("id")
|
||||||
private Long 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")
|
@JsonProperty("firstName")
|
||||||
@NotBlank(message = "Le prénom est obligatoire")
|
@NotBlank(message = "Le prénom est obligatoire")
|
||||||
private String firstName;
|
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")
|
@JsonProperty("lastName")
|
||||||
@NotBlank(message = "Le nom est obligatoire")
|
@NotBlank(message = "Le nom est obligatoire")
|
||||||
private String lastName;
|
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")
|
@JsonProperty("email")
|
||||||
@NotBlank(message = "L'email est obligatoire")
|
@NotBlank(message = "L'email est obligatoire")
|
||||||
@Email(message = "Format d'email invalide")
|
@Email(message = "Format d'email invalide")
|
||||||
private String email;
|
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")
|
@JsonProperty("phone")
|
||||||
private String 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")
|
@JsonProperty("role")
|
||||||
@NotNull(message = "Le rôle est obligatoire")
|
@NotNull(message = "Le rôle est obligatoire")
|
||||||
private UserRole role;
|
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")
|
@JsonProperty("active")
|
||||||
private boolean active = true;
|
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")
|
@JsonProperty("createdAt")
|
||||||
private LocalDateTime 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")
|
@JsonProperty("updatedAt")
|
||||||
private LocalDateTime 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")
|
@JsonProperty("lastLoginAt")
|
||||||
private LocalDateTime 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.LoginRequestDTO;
|
||||||
import com.gbcm.server.api.dto.auth.LoginResponseDTO;
|
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.dto.user.UserDTO;
|
||||||
import com.gbcm.server.api.exceptions.AuthenticationException;
|
import com.gbcm.server.api.exceptions.AuthenticationException;
|
||||||
import com.gbcm.server.api.exceptions.GBCMException;
|
import com.gbcm.server.api.exceptions.GBCMException;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import jakarta.ws.rs.*;
|
import jakarta.ws.rs.*;
|
||||||
import jakarta.ws.rs.core.MediaType;
|
import jakarta.ws.rs.core.MediaType;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
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.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")
|
@Path("/auth")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@Consumes(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 {
|
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