Initial commit

This commit is contained in:
dahoud
2025-10-01 01:37:34 +00:00
commit f2bb633142
310 changed files with 86051 additions and 0 deletions

View File

@@ -0,0 +1,436 @@
package dev.lions.btpxpress.adapter.http;
import dev.lions.btpxpress.application.service.DisponibiliteService;
import dev.lions.btpxpress.domain.core.entity.Disponibilite;
import dev.lions.btpxpress.domain.core.entity.TypeDisponibilite;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Resource REST pour la gestion des disponibilités - Architecture 2025 RH: API complète de gestion
* des disponibilités employés
*/
@Path("/api/v1/disponibilites")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Disponibilités", description = "Gestion des disponibilités et absences des employés")
public class DisponibiliteResource {
private static final Logger logger = LoggerFactory.getLogger(DisponibiliteResource.class);
@Inject DisponibiliteService disponibiliteService;
// === ENDPOINTS DE CONSULTATION ===
@GET
@Operation(
summary = "Lister toutes les disponibilités",
description =
"Récupère la liste paginée de toutes les disponibilités avec filtres optionnels")
@APIResponse(
responseCode = "200",
description = "Liste des disponibilités récupérée avec succès",
content = @Content(schema = @Schema(implementation = Disponibilite.class)))
public Response getAllDisponibilites(
@Parameter(description = "Numéro de page (0-indexé)", example = "0")
@QueryParam("page")
@DefaultValue("0")
int page,
@Parameter(description = "Taille de page", example = "20")
@QueryParam("size")
@DefaultValue("20")
int size,
@Parameter(description = "Filtrer par employé (UUID)") @QueryParam("employeId")
UUID employeId,
@Parameter(description = "Filtrer par type de disponibilité") @QueryParam("type") String type,
@Parameter(description = "Filtrer par statut d'approbation") @QueryParam("approuvee")
Boolean approuvee) {
logger.debug("Récupération des disponibilités - page: {}, taille: {}", page, size);
List<Disponibilite> disponibilites;
if (employeId != null) {
disponibilites = disponibiliteService.findByEmployeId(employeId);
} else if (type != null) {
TypeDisponibilite typeEnum = TypeDisponibilite.valueOf(type.toUpperCase());
disponibilites = disponibiliteService.findByType(typeEnum);
} else if (approuvee != null && !approuvee) {
disponibilites = disponibiliteService.findEnAttente();
} else if (approuvee != null && approuvee) {
disponibilites = disponibiliteService.findApprouvees();
} else {
disponibilites = disponibiliteService.findAll(page, size);
}
return Response.ok(disponibilites).build();
}
@GET
@Path("/{id}")
@Operation(
summary = "Récupérer une disponibilité par ID",
description = "Récupère les détails d'une disponibilité spécifique")
@APIResponse(
responseCode = "200",
description = "Disponibilité trouvée",
content = @Content(schema = @Schema(implementation = Disponibilite.class)))
@APIResponse(responseCode = "404", description = "Disponibilité non trouvée")
public Response getDisponibiliteById(
@Parameter(description = "Identifiant unique de la disponibilité", required = true)
@PathParam("id")
UUID id) {
logger.debug("Récupération de la disponibilité avec l'ID: {}", id);
return disponibiliteService
.findById(id)
.map(disponibilite -> Response.ok(disponibilite).build())
.orElse(Response.status(Response.Status.NOT_FOUND).build());
}
@GET
@Path("/actuelles")
@Operation(
summary = "Lister les disponibilités actuelles",
description = "Récupère toutes les disponibilités actuellement actives")
@APIResponse(
responseCode = "200",
description = "Disponibilités actuelles récupérées",
content = @Content(schema = @Schema(implementation = Disponibilite.class)))
public Response getDisponibilitesActuelles() {
logger.debug("Récupération des disponibilités actuelles");
List<Disponibilite> disponibilites = disponibiliteService.findActuelles();
return Response.ok(disponibilites).build();
}
@GET
@Path("/futures")
@Operation(
summary = "Lister les disponibilités futures",
description = "Récupère toutes les disponibilités programmées pour le futur")
@APIResponse(
responseCode = "200",
description = "Disponibilités futures récupérées",
content = @Content(schema = @Schema(implementation = Disponibilite.class)))
public Response getDisponibilitesFutures() {
logger.debug("Récupération des disponibilités futures");
List<Disponibilite> disponibilites = disponibiliteService.findFutures();
return Response.ok(disponibilites).build();
}
@GET
@Path("/en-attente")
@Operation(
summary = "Lister les demandes en attente",
description = "Récupère toutes les demandes de disponibilité en attente d'approbation")
@APIResponse(
responseCode = "200",
description = "Demandes en attente récupérées",
content = @Content(schema = @Schema(implementation = Disponibilite.class)))
public Response getDemandesEnAttente() {
logger.debug("Récupération des demandes en attente");
List<Disponibilite> disponibilites = disponibiliteService.findEnAttente();
return Response.ok(disponibilites).build();
}
@GET
@Path("/periode")
@Operation(
summary = "Lister les disponibilités pour une période",
description = "Récupère toutes les disponibilités dans une période donnée")
@APIResponse(
responseCode = "200",
description = "Disponibilités de la période récupérées",
content = @Content(schema = @Schema(implementation = Disponibilite.class)))
public Response getDisponibilitesPourPeriode(
@Parameter(description = "Date de début (yyyy-mm-dd)", required = true)
@QueryParam("dateDebut")
@NotNull
LocalDate dateDebut,
@Parameter(description = "Date de fin (yyyy-mm-dd)", required = true)
@QueryParam("dateFin")
@NotNull
LocalDate dateFin) {
logger.debug("Récupération des disponibilités pour la période {} - {}", dateDebut, dateFin);
List<Disponibilite> disponibilites = disponibiliteService.findPourPeriode(dateDebut, dateFin);
return Response.ok(disponibilites).build();
}
// === ENDPOINTS DE GESTION CRUD ===
@POST
@Operation(
summary = "Créer une nouvelle disponibilité",
description = "Créé une nouvelle demande de disponibilité pour un employé")
@APIResponse(
responseCode = "201",
description = "Disponibilité créée avec succès",
content = @Content(schema = @Schema(implementation = Disponibilite.class)))
@APIResponse(responseCode = "400", description = "Données invalides ou conflit détecté")
public Response createDisponibilite(@Valid @NotNull CreateDisponibiliteRequest request) {
logger.info("Création d'une nouvelle disponibilité pour l'employé: {}", request.employeId);
Disponibilite disponibilite =
disponibiliteService.createDisponibilite(
request.employeId, request.dateDebut, request.dateFin, request.type, request.motif);
return Response.status(Response.Status.CREATED).entity(disponibilite).build();
}
@PUT
@Path("/{id}")
@Operation(
summary = "Mettre à jour une disponibilité",
description = "Met à jour les informations d'une disponibilité existante")
@APIResponse(
responseCode = "200",
description = "Disponibilité mise à jour avec succès",
content = @Content(schema = @Schema(implementation = Disponibilite.class)))
@APIResponse(responseCode = "404", description = "Disponibilité non trouvée")
@APIResponse(responseCode = "400", description = "Données invalides")
public Response updateDisponibilite(
@Parameter(description = "Identifiant de la disponibilité", required = true) @PathParam("id")
UUID id,
@Valid @NotNull UpdateDisponibiliteRequest request) {
logger.info("Mise à jour de la disponibilité: {}", id);
Disponibilite disponibilite =
disponibiliteService.updateDisponibilite(
id, request.dateDebut, request.dateFin, request.motif);
return Response.ok(disponibilite).build();
}
@POST
@Path("/{id}/approuver")
@Operation(
summary = "Approuver une demande de disponibilité",
description = "Approuve une demande de disponibilité en attente")
@APIResponse(
responseCode = "200",
description = "Disponibilité approuvée avec succès",
content = @Content(schema = @Schema(implementation = Disponibilite.class)))
@APIResponse(responseCode = "404", description = "Disponibilité non trouvée")
@APIResponse(responseCode = "400", description = "Disponibilité déjà approuvée")
public Response approuverDisponibilite(
@Parameter(description = "Identifiant de la disponibilité", required = true) @PathParam("id")
UUID id) {
logger.info("Approbation de la disponibilité: {}", id);
Disponibilite disponibilite = disponibiliteService.approuverDisponibilite(id);
return Response.ok(disponibilite).build();
}
@POST
@Path("/{id}/rejeter")
@Operation(
summary = "Rejeter une demande de disponibilité",
description = "Rejette une demande de disponibilité avec une raison")
@APIResponse(
responseCode = "200",
description = "Disponibilité rejetée avec succès",
content = @Content(schema = @Schema(implementation = Disponibilite.class)))
@APIResponse(responseCode = "404", description = "Disponibilité non trouvée")
@APIResponse(responseCode = "400", description = "Impossible de rejeter")
public Response rejeterDisponibilite(
@Parameter(description = "Identifiant de la disponibilité", required = true) @PathParam("id")
UUID id,
@Valid @NotNull RejetDisponibiliteRequest request) {
logger.info("Rejet de la disponibilité: {}", id);
Disponibilite disponibilite =
disponibiliteService.rejeterDisponibilite(id, request.raisonRejet);
return Response.ok(disponibilite).build();
}
@DELETE
@Path("/{id}")
@Operation(
summary = "Supprimer une disponibilité",
description = "Supprime définitivement une disponibilité")
@APIResponse(responseCode = "204", description = "Disponibilité supprimée avec succès")
@APIResponse(responseCode = "404", description = "Disponibilité non trouvée")
@APIResponse(responseCode = "400", description = "Impossible de supprimer")
public Response deleteDisponibilite(
@Parameter(description = "Identifiant de la disponibilité", required = true) @PathParam("id")
UUID id) {
logger.info("Suppression de la disponibilité: {}", id);
disponibiliteService.deleteDisponibilite(id);
return Response.noContent().build();
}
// === ENDPOINTS DE VALIDATION ===
@GET
@Path("/employe/{employeId}/disponible")
@Operation(
summary = "Vérifier la disponibilité d'un employé",
description = "Vérifie si un employé est disponible pour une période donnée")
@APIResponse(responseCode = "200", description = "Statut de disponibilité retourné")
public Response checkEmployeDisponibilite(
@Parameter(description = "Identifiant de l'employé", required = true) @PathParam("employeId")
UUID employeId,
@Parameter(description = "Date/heure de début", required = true)
@QueryParam("dateDebut")
@NotNull
LocalDateTime dateDebut,
@Parameter(description = "Date/heure de fin", required = true) @QueryParam("dateFin") @NotNull
LocalDateTime dateFin) {
logger.debug("Vérification de disponibilité pour l'employé {}", employeId);
boolean estDisponible = disponibiliteService.isEmployeDisponible(employeId, dateDebut, dateFin);
return Response.ok(
new Object() {
public final boolean disponible = estDisponible;
public final String message =
estDisponible
? "Employé disponible pour cette période"
: "Employé indisponible pour cette période";
})
.build();
}
@GET
@Path("/employe/{employeId}/conflits")
@Operation(
summary = "Rechercher les conflits de disponibilité",
description = "Trouve les conflits de disponibilité pour un employé et une période")
@APIResponse(
responseCode = "200",
description = "Conflits trouvés",
content = @Content(schema = @Schema(implementation = Disponibilite.class)))
public Response getConflits(
@Parameter(description = "Identifiant de l'employé", required = true) @PathParam("employeId")
UUID employeId,
@Parameter(description = "Date/heure de début", required = true)
@QueryParam("dateDebut")
@NotNull
LocalDateTime dateDebut,
@Parameter(description = "Date/heure de fin", required = true) @QueryParam("dateFin") @NotNull
LocalDateTime dateFin,
@Parameter(description = "ID à exclure de la recherche") @QueryParam("excludeId")
UUID excludeId) {
logger.debug("Recherche de conflits pour l'employé {}", employeId);
List<Disponibilite> conflits =
disponibiliteService.getConflicts(employeId, dateDebut, dateFin, excludeId);
return Response.ok(conflits).build();
}
// === ENDPOINTS STATISTIQUES ===
@GET
@Path("/statistiques")
@Operation(
summary = "Obtenir les statistiques des disponibilités",
description = "Récupère les statistiques globales des disponibilités")
@APIResponse(responseCode = "200", description = "Statistiques récupérées avec succès")
public Response getStatistiques() {
logger.debug("Récupération des statistiques des disponibilités");
Object statistiques = disponibiliteService.getStatistics();
return Response.ok(statistiques).build();
}
@GET
@Path("/statistiques/par-type")
@Operation(
summary = "Statistiques par type de disponibilité",
description = "Récupère les statistiques détaillées par type")
@APIResponse(responseCode = "200", description = "Statistiques par type récupérées")
public Response getStatistiquesParType() {
logger.debug("Récupération des statistiques par type");
List<Object[]> stats = disponibiliteService.getStatsByType();
return Response.ok(stats).build();
}
@GET
@Path("/statistiques/par-employe")
@Operation(
summary = "Statistiques par employé",
description = "Récupère les statistiques de disponibilité par employé")
@APIResponse(responseCode = "200", description = "Statistiques par employé récupérées")
public Response getStatistiquesParEmploye() {
logger.debug("Récupération des statistiques par employé");
List<Object[]> stats = disponibiliteService.getStatsByEmployee();
return Response.ok(stats).build();
}
// === CLASSES DE REQUÊTE ===
public static class CreateDisponibiliteRequest {
@Schema(description = "Identifiant unique de l'employé", required = true)
public UUID employeId;
@Schema(
description = "Date et heure de début de la disponibilité",
required = true,
example = "2024-03-15T08:00:00")
public LocalDateTime dateDebut;
@Schema(
description = "Date et heure de fin de la disponibilité",
required = true,
example = "2024-03-20T18:00:00")
public LocalDateTime dateFin;
@Schema(
description = "Type de disponibilité",
required = true,
enumeration = {
"CONGE_PAYE",
"CONGE_SANS_SOLDE",
"ARRET_MALADIE",
"FORMATION",
"ABSENCE",
"HORAIRE_REDUIT"
})
public String type;
@Schema(description = "Motif ou raison de la disponibilité", example = "Congés annuels")
public String motif;
}
public static class UpdateDisponibiliteRequest {
@Schema(description = "Nouvelle date de début")
public LocalDateTime dateDebut;
@Schema(description = "Nouvelle date de fin")
public LocalDateTime dateFin;
@Schema(description = "Nouveau motif")
public String motif;
}
public static class RejetDisponibiliteRequest {
@Schema(description = "Raison du rejet de la demande", required = true)
public String raisonRejet;
}
}