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,588 @@
package dev.lions.btpxpress.presentation.controller;
import dev.lions.btpxpress.application.service.BonCommandeService;
import dev.lions.btpxpress.domain.core.entity.BonCommande;
import dev.lions.btpxpress.domain.core.entity.PrioriteBonCommande;
import dev.lions.btpxpress.domain.core.entity.StatutBonCommande;
import dev.lions.btpxpress.domain.core.entity.TypeBonCommande;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Controller REST pour la gestion des bons de commande */
@Path("/api/v1/bons-commande")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Bons de Commande", description = "Gestion des bons de commande")
public class BonCommandeController {
private static final Logger logger = LoggerFactory.getLogger(BonCommandeController.class);
@Inject BonCommandeService bonCommandeService;
/** Récupère tous les bons de commande */
@GET
public Response getAllBonsCommande() {
try {
List<BonCommande> bonsCommande = bonCommandeService.findAll();
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des bons de commande", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Récupère un bon de commande par son ID */
@GET
@Path("/{id}")
public Response getBonCommandeById(@PathParam("id") UUID id) {
try {
BonCommande bonCommande = bonCommandeService.findById(id);
return Response.ok(bonCommande).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du bon de commande: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du bon de commande"))
.build();
}
}
/** Récupère un bon de commande par son numéro */
@GET
@Path("/numero/{numero}")
public Response getBonCommandeByNumero(@PathParam("numero") String numero) {
try {
BonCommande bonCommande = bonCommandeService.findByNumero(numero);
if (bonCommande == null) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", "Bon de commande non trouvé"))
.build();
}
return Response.ok(bonCommande).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du bon de commande par numéro: " + numero, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du bon de commande"))
.build();
}
}
/** Récupère les bons de commande par statut */
@GET
@Path("/statut/{statut}")
public Response getBonsCommandeByStatut(@PathParam("statut") StatutBonCommande statut) {
try {
List<BonCommande> bonsCommande = bonCommandeService.findByStatut(statut);
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des bons de commande par statut: " + statut, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Récupère les bons de commande par fournisseur */
@GET
@Path("/fournisseur/{fournisseurId}")
public Response getBonsCommandeByFournisseur(@PathParam("fournisseurId") UUID fournisseurId) {
try {
List<BonCommande> bonsCommande = bonCommandeService.findByFournisseur(fournisseurId);
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des bons de commande du fournisseur: " + fournisseurId,
e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Récupère les bons de commande par chantier */
@GET
@Path("/chantier/{chantierId}")
public Response getBonsCommandeByChantier(@PathParam("chantierId") UUID chantierId) {
try {
List<BonCommande> bonsCommande = bonCommandeService.findByChantier(chantierId);
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des bons de commande du chantier: " + chantierId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Récupère les bons de commande par demandeur */
@GET
@Path("/demandeur/{demandeurId}")
public Response getBonsCommandeByDemandeur(@PathParam("demandeurId") UUID demandeurId) {
try {
List<BonCommande> bonsCommande = bonCommandeService.findByDemandeur(demandeurId);
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des bons de commande du demandeur: " + demandeurId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Récupère les bons de commande par priorité */
@GET
@Path("/priorite/{priorite}")
public Response getBonsCommandeByPriorite(@PathParam("priorite") PrioriteBonCommande priorite) {
try {
List<BonCommande> bonsCommande = bonCommandeService.findByPriorite(priorite);
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des bons de commande par priorité: " + priorite, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Récupère les bons de commande urgents */
@GET
@Path("/urgents")
public Response getBonsCommandeUrgents() {
try {
List<BonCommande> bonsCommande = bonCommandeService.findUrgents();
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des bons de commande urgents", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Récupère les bons de commande par type */
@GET
@Path("/type/{type}")
public Response getBonsCommandeByType(@PathParam("type") TypeBonCommande type) {
try {
List<BonCommande> bonsCommande = bonCommandeService.findByType(type);
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des bons de commande par type: " + type, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Récupère les bons de commande en cours */
@GET
@Path("/en-cours")
public Response getBonsCommandeEnCours() {
try {
List<BonCommande> bonsCommande = bonCommandeService.findEnCours();
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des bons de commande en cours", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Récupère les bons de commande en retard */
@GET
@Path("/en-retard")
public Response getBonsCommandeEnRetard() {
try {
List<BonCommande> bonsCommande = bonCommandeService.findCommandesEnRetard();
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des bons de commande en retard", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Récupère les bons de commande à livrer prochainement */
@GET
@Path("/livraisons-prochaines")
public Response getLivraisonsProchaines(@QueryParam("nbJours") @DefaultValue("7") int nbJours) {
try {
List<BonCommande> bonsCommande = bonCommandeService.findLivraisonsProchainess(nbJours);
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des livraisons prochaines", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Récupère les bons de commande en attente de validation */
@GET
@Path("/attente-validation")
public Response getBonsCommandeAttenteValidation() {
try {
List<BonCommande> bonsCommande = bonCommandeService.findEnAttenteValidation();
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des bons de commande en attente", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Récupère les bons de commande validés non envoyés */
@GET
@Path("/valides-non-envoyes")
public Response getBonsCommandeValidesNonEnvoyes() {
try {
List<BonCommande> bonsCommande = bonCommandeService.findValideesNonEnvoyees();
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des bons de commande validés non envoyés", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des bons de commande"))
.build();
}
}
/** Crée un nouveau bon de commande */
@POST
public Response createBonCommande(@Valid BonCommande bonCommande) {
try {
BonCommande nouveauBonCommande = bonCommandeService.create(bonCommande);
return Response.status(Response.Status.CREATED).entity(nouveauBonCommande).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la création du bon de commande", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la création du bon de commande"))
.build();
}
}
/** Met à jour un bon de commande */
@PUT
@Path("/{id}")
public Response updateBonCommande(@PathParam("id") UUID id, @Valid BonCommande bonCommandeData) {
try {
BonCommande bonCommande = bonCommandeService.update(id, bonCommandeData);
return Response.ok(bonCommande).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour du bon de commande: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la mise à jour du bon de commande"))
.build();
}
}
/** Valide un bon de commande */
@POST
@Path("/{id}/valider")
public Response validerBonCommande(@PathParam("id") UUID id, Map<String, String> payload) {
try {
String commentaires = payload != null ? payload.get("commentaires") : null;
BonCommande bonCommande = bonCommandeService.validerBonCommande(id, commentaires);
return Response.ok(bonCommande).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la validation du bon de commande: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la validation du bon de commande"))
.build();
}
}
/** Rejette un bon de commande */
@POST
@Path("/{id}/rejeter")
public Response rejeterBonCommande(@PathParam("id") UUID id, Map<String, String> payload) {
try {
String motif = payload != null ? payload.get("motif") : null;
BonCommande bonCommande = bonCommandeService.rejeterBonCommande(id, motif);
return Response.ok(bonCommande).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors du rejet du bon de commande: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors du rejet du bon de commande"))
.build();
}
}
/** Envoie un bon de commande */
@POST
@Path("/{id}/envoyer")
public Response envoyerBonCommande(@PathParam("id") UUID id) {
try {
BonCommande bonCommande = bonCommandeService.envoyerBonCommande(id);
return Response.ok(bonCommande).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'envoi du bon de commande: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de l'envoi du bon de commande"))
.build();
}
}
/** Confirme la réception d'un accusé de réception */
@POST
@Path("/{id}/accuse-reception")
public Response confirmerAccuseReception(@PathParam("id") UUID id) {
try {
BonCommande bonCommande = bonCommandeService.confirmerAccuseReception(id);
return Response.ok(bonCommande).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la confirmation d'accusé de réception: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la confirmation d'accusé de réception"))
.build();
}
}
/** Marque un bon de commande comme livré */
@POST
@Path("/{id}/livrer")
public Response livrerBonCommande(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
LocalDate dateLivraison =
payload != null && payload.get("dateLivraison") != null
? LocalDate.parse(payload.get("dateLivraison").toString())
: LocalDate.now();
String commentaires =
payload != null && payload.get("commentaires") != null
? payload.get("commentaires").toString()
: null;
BonCommande bonCommande =
bonCommandeService.livrerBonCommande(id, dateLivraison, commentaires);
return Response.ok(bonCommande).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la livraison du bon de commande: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la livraison du bon de commande"))
.build();
}
}
/** Annule un bon de commande */
@POST
@Path("/{id}/annuler")
public Response annulerBonCommande(@PathParam("id") UUID id, Map<String, String> payload) {
try {
String motif = payload != null ? payload.get("motif") : null;
BonCommande bonCommande = bonCommandeService.annulerBonCommande(id, motif);
return Response.ok(bonCommande).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'annulation du bon de commande: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de l'annulation du bon de commande"))
.build();
}
}
/** Clôture un bon de commande */
@POST
@Path("/{id}/cloturer")
public Response cloturerBonCommande(@PathParam("id") UUID id, Map<String, String> payload) {
try {
String commentaires = payload != null ? payload.get("commentaires") : null;
BonCommande bonCommande = bonCommandeService.cloturerBonCommande(id, commentaires);
return Response.ok(bonCommande).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la clôture du bon de commande: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la clôture du bon de commande"))
.build();
}
}
/** Supprime un bon de commande */
@DELETE
@Path("/{id}")
public Response deleteBonCommande(@PathParam("id") UUID id) {
try {
bonCommandeService.delete(id);
return Response.noContent().build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la suppression du bon de commande: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la suppression du bon de commande"))
.build();
}
}
/** Recherche de bons de commande par multiple critères */
@GET
@Path("/search")
public Response searchBonsCommande(@QueryParam("term") String searchTerm) {
try {
if (searchTerm == null || searchTerm.trim().isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Terme de recherche requis"))
.build();
}
List<BonCommande> bonsCommande = bonCommandeService.searchCommandes(searchTerm);
return Response.ok(bonsCommande).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche de bons de commande: " + searchTerm, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la recherche"))
.build();
}
}
/** Récupère les statistiques des bons de commande */
@GET
@Path("/statistiques")
public Response getStatistiques() {
try {
Map<String, Object> stats = bonCommandeService.getStatistiques();
return Response.ok(stats).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des statistiques"))
.build();
}
}
/** Génère le prochain numéro de commande */
@GET
@Path("/numero-suivant")
public Response getProchainNumero(@QueryParam("prefixe") @DefaultValue("BC") String prefixe) {
try {
String numeroSuivant = bonCommandeService.genererProchainNumero(prefixe);
return Response.ok(Map.of("numeroSuivant", numeroSuivant)).build();
} catch (Exception e) {
logger.error("Erreur lors de la génération du numéro suivant", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la génération du numéro"))
.build();
}
}
/** Récupère les top fournisseurs par montant de commandes */
@GET
@Path("/top-fournisseurs")
public Response getTopFournisseurs(@QueryParam("limit") @DefaultValue("10") int limit) {
try {
List<Object[]> topFournisseurs = bonCommandeService.findTopFournisseursByMontant(limit);
return Response.ok(topFournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des top fournisseurs", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des top fournisseurs"))
.build();
}
}
/** Récupère les statistiques mensuelles */
@GET
@Path("/statistiques/mensuelles/{annee}")
public Response getStatistiquesMensuelles(@PathParam("annee") int annee) {
try {
List<Object[]> stats = bonCommandeService.findStatistiquesMensuelles(annee);
return Response.ok(stats).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des statistiques mensuelles", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des statistiques"))
.build();
}
}
}

View File

@@ -0,0 +1,411 @@
package dev.lions.btpxpress.presentation.controller;
import dev.lions.btpxpress.application.service.ChantierService;
import dev.lions.btpxpress.domain.core.entity.Chantier;
import dev.lions.btpxpress.domain.core.entity.StatutChantier;
import dev.lions.btpxpress.domain.shared.dto.ChantierCreateDTO;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Controller REST pour la gestion des chantiers */
@Path("/api/v1/chantiers-controller") // Contrôleur alternatif pour éviter conflit
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Chantiers", description = "Gestion des chantiers BTP")
public class ChantierController {
private static final Logger logger = LoggerFactory.getLogger(ChantierController.class);
@Inject ChantierService chantierService;
/** Récupère tous les chantiers */
@GET
public Response getAllChantiers() {
try {
List<Chantier> chantiers = chantierService.findAll();
return Response.ok(chantiers).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des chantiers", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des chantiers"))
.build();
}
}
/** Récupère un chantier par son ID */
@GET
@Path("/{id}")
public Response getChantierById(@PathParam("id") UUID id) {
try {
Optional<Chantier> chantierOpt = chantierService.findById(id);
if (chantierOpt.isEmpty()) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", "Chantier non trouvé"))
.build();
}
return Response.ok(chantierOpt.get()).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du chantier: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du chantier"))
.build();
}
}
/** Récupère les chantiers par statut */
@GET
@Path("/statut/{statut}")
public Response getChantiersByStatut(@PathParam("statut") StatutChantier statut) {
try {
List<Chantier> chantiers = chantierService.findByStatut(statut);
return Response.ok(chantiers).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des chantiers par statut: " + statut, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des chantiers"))
.build();
}
}
/** Récupère les chantiers actifs */
@GET
@Path("/actifs")
public Response getChantiersActifs() {
try {
List<Chantier> chantiers = chantierService.findActifs();
return Response.ok(chantiers).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des chantiers actifs", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des chantiers"))
.build();
}
}
/** Récupère les chantiers par client */
@GET
@Path("/client/{clientId}")
public Response getChantiersByClient(@PathParam("clientId") UUID clientId) {
try {
List<Chantier> chantiers = chantierService.findByClient(clientId);
return Response.ok(chantiers).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des chantiers du client: " + clientId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des chantiers"))
.build();
}
}
/** Récupère les chantiers par chef de chantier */
@GET
@Path("/chef-chantier/{chefId}")
public Response getChantiersByChefChantier(@PathParam("chefId") UUID chefId) {
try {
List<Chantier> chantiers = chantierService.findByChefChantier(chefId);
return Response.ok(chantiers).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des chantiers du chef: " + chefId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des chantiers"))
.build();
}
}
/** Récupère les chantiers en retard */
@GET
@Path("/en-retard")
public Response getChantiersEnRetard() {
try {
List<Chantier> chantiers = chantierService.findChantiersEnRetard();
return Response.ok(chantiers).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des chantiers en retard", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des chantiers"))
.build();
}
}
/** Récupère les chantiers à démarrer prochainement */
@GET
@Path("/prochains-demarrages")
public Response getProchainsDemarrages(@QueryParam("nbJours") @DefaultValue("30") int nbJours) {
try {
List<Chantier> chantiers = chantierService.findProchainsDemarrages(nbJours);
return Response.ok(chantiers).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des prochains démarrages", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des chantiers"))
.build();
}
}
/** Récupère les chantiers par ville */
@GET
@Path("/ville/{ville}")
public Response getChantiersByVille(@PathParam("ville") String ville) {
try {
List<Chantier> chantiers = chantierService.findByVille(ville);
return Response.ok(chantiers).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des chantiers par ville: " + ville, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des chantiers"))
.build();
}
}
/** Crée un nouveau chantier */
@POST
public Response createChantier(@Valid ChantierCreateDTO chantierDto) {
try {
Chantier nouveauChantier = chantierService.create(chantierDto);
return Response.status(Response.Status.CREATED).entity(nouveauChantier).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la création du chantier", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la création du chantier"))
.build();
}
}
/** Met à jour un chantier */
@PUT
@Path("/{id}")
public Response updateChantier(@PathParam("id") UUID id, @Valid ChantierCreateDTO chantierDto) {
try {
Chantier chantier = chantierService.update(id, chantierDto);
return Response.ok(chantier).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour du chantier: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la mise à jour du chantier"))
.build();
}
}
/** Démarre un chantier */
@POST
@Path("/{id}/demarrer")
public Response demarrerChantier(@PathParam("id") UUID id) {
try {
Chantier chantier = chantierService.demarrerChantier(id);
return Response.ok(chantier).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors du démarrage du chantier: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors du démarrage du chantier"))
.build();
}
}
/** Suspend un chantier */
@POST
@Path("/{id}/suspendre")
public Response suspendreChantier(@PathParam("id") UUID id, Map<String, String> payload) {
try {
String motif = payload != null ? payload.get("motif") : null;
Chantier chantier = chantierService.suspendreChantier(id, motif);
return Response.ok(chantier).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la suspension du chantier: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la suspension du chantier"))
.build();
}
}
/** Termine un chantier */
@POST
@Path("/{id}/terminer")
public Response terminerChantier(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
LocalDate dateFinReelle =
payload != null && payload.get("dateFinReelle") != null
? LocalDate.parse(payload.get("dateFinReelle").toString())
: LocalDate.now();
String commentaires =
payload != null && payload.get("commentaires") != null
? payload.get("commentaires").toString()
: null;
Chantier chantier = chantierService.terminerChantier(id, dateFinReelle, commentaires);
return Response.ok(chantier).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la terminaison du chantier: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la terminaison du chantier"))
.build();
}
}
/** Met à jour l'avancement global du chantier */
@POST
@Path("/{id}/avancement")
public Response updateAvancementGlobal(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
BigDecimal pourcentage = new BigDecimal(payload.get("pourcentage").toString());
Chantier chantier = chantierService.updateAvancementGlobal(id, pourcentage);
return Response.ok(chantier).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Pourcentage invalide"))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour de l'avancement: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la mise à jour de l'avancement"))
.build();
}
}
/** Supprime un chantier */
@DELETE
@Path("/{id}")
public Response deleteChantier(@PathParam("id") UUID id) {
try {
chantierService.delete(id);
return Response.noContent().build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la suppression du chantier: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la suppression du chantier"))
.build();
}
}
/** Recherche de chantiers par multiple critères */
@GET
@Path("/search")
public Response searchChantiers(@QueryParam("term") String searchTerm) {
try {
if (searchTerm == null || searchTerm.trim().isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Terme de recherche requis"))
.build();
}
List<Chantier> chantiers = chantierService.searchChantiers(searchTerm);
return Response.ok(chantiers).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche de chantiers: " + searchTerm, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la recherche"))
.build();
}
}
/** Récupère les statistiques des chantiers */
@GET
@Path("/statistiques")
public Response getStatistiques() {
try {
Map<String, Object> stats = chantierService.getStatistiques();
return Response.ok(stats).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des statistiques"))
.build();
}
}
/** Calcule le chiffre d'affaires total des chantiers */
@GET
@Path("/chiffre-affaires")
public Response getChiffreAffaires(@QueryParam("annee") Integer annee) {
try {
Map<String, Object> ca = chantierService.calculerChiffreAffaires(annee);
return Response.ok(Map.of("chiffreAffaires", ca)).build();
} catch (Exception e) {
logger.error("Erreur lors du calcul du chiffre d'affaires", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors du calcul du chiffre d'affaires"))
.build();
}
}
/** Récupère le tableau de bord du chantier */
@GET
@Path("/{id}/dashboard")
public Response getDashboardChantier(@PathParam("id") UUID id) {
try {
Map<String, Object> dashboard = chantierService.getDashboardChantier(id);
return Response.ok(dashboard).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du dashboard: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du dashboard"))
.build();
}
}
}

View File

@@ -0,0 +1,423 @@
package dev.lions.btpxpress.presentation.controller;
import dev.lions.btpxpress.application.service.EmployeService;
import dev.lions.btpxpress.domain.core.entity.Employe;
import dev.lions.btpxpress.domain.core.entity.StatutEmploye;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Controller REST pour la gestion des employés */
@Path("/api/employes")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Employés", description = "Gestion des employés")
public class EmployeController {
private static final Logger logger = LoggerFactory.getLogger(EmployeController.class);
@Inject EmployeService employeService;
/** Récupère tous les employés */
@GET
public Response getAllEmployes() {
try {
List<Employe> employes = employeService.findAll();
return Response.ok(employes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des employés", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des employés"))
.build();
}
}
/** Récupère un employé par son ID */
@GET
@Path("/{id}")
public Response getEmployeById(@PathParam("id") UUID id) {
try {
Optional<Employe> employeOpt = employeService.findById(id);
if (employeOpt.isEmpty()) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", "Employé non trouvé"))
.build();
}
return Response.ok(employeOpt.get()).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération de l'employé: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération de l'employé"))
.build();
}
}
/** Récupère les employés par statut */
@GET
@Path("/statut/{statut}")
public Response getEmployesByStatut(@PathParam("statut") StatutEmploye statut) {
try {
List<Employe> employes = employeService.findByStatut(statut);
return Response.ok(employes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des employés par statut: " + statut, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des employés"))
.build();
}
}
/** Récupère les employés actifs */
@GET
@Path("/actifs")
public Response getEmployesActifs() {
try {
List<Employe> employes = employeService.findActifs();
return Response.ok(employes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des employés actifs", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des employés"))
.build();
}
}
/** Récupère un employé par email */
@GET
@Path("/email/{email}")
public Response getEmployeByEmail(@PathParam("email") String email) {
try {
Optional<Employe> employeOpt = employeService.findByEmail(email);
if (employeOpt.isEmpty()) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", "Employé non trouvé"))
.build();
}
return Response.ok(employeOpt.get()).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération de l'employé par email: " + email, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération de l'employé"))
.build();
}
}
/** Recherche des employés par nom ou prénom */
@GET
@Path("/search/nom")
public Response searchEmployesByNom(@QueryParam("nom") String searchTerm) {
try {
if (searchTerm == null || searchTerm.trim().isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Terme de recherche requis"))
.build();
}
List<Employe> employes = employeService.searchByNom(searchTerm);
return Response.ok(employes).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche par nom: " + searchTerm, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la recherche"))
.build();
}
}
/** Récupère les employés par métier */
@GET
@Path("/metier/{metier}")
public Response getEmployesByMetier(@PathParam("metier") String metier) {
try {
List<Employe> employes = employeService.findByMetier(metier);
return Response.ok(employes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des employés par métier: " + metier, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des employés"))
.build();
}
}
/** Récupère les employés par équipe */
@GET
@Path("/equipe/{equipeId}")
public Response getEmployesByEquipe(@PathParam("equipeId") UUID equipeId) {
try {
List<Employe> employes = employeService.findByEquipe(equipeId);
return Response.ok(employes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des employés par équipe: " + equipeId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des employés"))
.build();
}
}
/** Récupère les employés disponibles pour une période */
@GET
@Path("/disponibles")
public Response getEmployesDisponibles(
@QueryParam("dateDebut") String dateDebut, @QueryParam("dateFin") String dateFin) {
try {
List<Employe> employes = employeService.findDisponibles(dateDebut, dateFin);
return Response.ok(employes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des employés disponibles", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des employés"))
.build();
}
}
/** Récupère les employés avec certifications */
@GET
@Path("/avec-certifications")
public Response getEmployesAvecCertifications() {
try {
List<Employe> employes = employeService.findAvecCertifications();
return Response.ok(employes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des employés avec certifications", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des employés"))
.build();
}
}
/** Récupère les employés par niveau d'expérience */
@GET
@Path("/experience/{niveau}")
public Response getEmployesByExperience(@PathParam("niveau") String niveau) {
try {
List<Employe> employes = employeService.findByNiveauExperience(niveau);
return Response.ok(employes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des employés par expérience: " + niveau, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des employés"))
.build();
}
}
/** Crée un nouveau employé */
@POST
public Response createEmploye(@Valid Employe employe) {
try {
Employe nouvelEmploye = employeService.create(employe);
return Response.status(Response.Status.CREATED).entity(nouvelEmploye).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la création de l'employé", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la création de l'employé"))
.build();
}
}
/** Met à jour un employé */
@PUT
@Path("/{id}")
public Response updateEmploye(@PathParam("id") UUID id, @Valid Employe employeData) {
try {
Employe employe = employeService.update(id, employeData);
return Response.ok(employe).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour de l'employé: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la mise à jour de l'employé"))
.build();
}
}
/** Active un employé */
@POST
@Path("/{id}/activer")
public Response activerEmploye(@PathParam("id") UUID id) {
try {
Employe employe = employeService.activerEmploye(id);
return Response.ok(employe).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'activation de l'employé: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de l'activation de l'employé"))
.build();
}
}
/** Désactive un employé */
@POST
@Path("/{id}/desactiver")
public Response desactiverEmploye(@PathParam("id") UUID id, Map<String, String> payload) {
try {
String motif = payload != null ? payload.get("motif") : null;
Employe employe = employeService.desactiverEmploye(id, motif);
return Response.ok(employe).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la désactivation de l'employé: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la désactivation de l'employé"))
.build();
}
}
/** Affecte un employé à une équipe */
@POST
@Path("/{id}/affecter-equipe")
public Response affecterEquipe(@PathParam("id") UUID employeId, Map<String, Object> payload) {
try {
UUID equipeId =
payload.get("equipeId") != null
? UUID.fromString(payload.get("equipeId").toString())
: null;
Employe employe = employeService.affecterEquipe(employeId, equipeId);
return Response.ok(employe).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'affectation d'équipe: " + employeId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de l'affectation d'équipe"))
.build();
}
}
/** Supprime un employé */
@DELETE
@Path("/{id}")
public Response deleteEmploye(@PathParam("id") UUID id) {
try {
employeService.delete(id);
return Response.noContent().build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la suppression de l'employé: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la suppression de l'employé"))
.build();
}
}
/** Recherche d'employés par multiple critères */
@GET
@Path("/search")
public Response searchEmployes(@QueryParam("term") String searchTerm) {
try {
if (searchTerm == null || searchTerm.trim().isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Terme de recherche requis"))
.build();
}
List<Employe> employes = employeService.searchEmployes(searchTerm);
return Response.ok(employes).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche d'employés: " + searchTerm, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la recherche"))
.build();
}
}
/** Récupère les statistiques des employés */
@GET
@Path("/statistiques")
public Response getStatistiques() {
try {
Map<String, Object> stats = employeService.getStatistiques();
return Response.ok(stats).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des statistiques"))
.build();
}
}
/** Récupère le planning d'un employé */
@GET
@Path("/{id}/planning")
public Response getPlanningEmploye(
@PathParam("id") UUID id,
@QueryParam("dateDebut") String dateDebut,
@QueryParam("dateFin") String dateFin) {
try {
LocalDate debut = LocalDate.parse(dateDebut);
LocalDate fin = LocalDate.parse(dateFin);
List<Object> planning = employeService.getPlanningEmploye(id, debut, fin);
return Response.ok(planning).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du planning: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du planning"))
.build();
}
}
/** Récupère les compétences d'un employé */
@GET
@Path("/{id}/competences")
public Response getCompetencesEmploye(@PathParam("id") UUID id) {
try {
List<Object> competences = employeService.getCompetencesEmploye(id);
return Response.ok(competences).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des compétences: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des compétences"))
.build();
}
}
}

View File

@@ -0,0 +1,452 @@
package dev.lions.btpxpress.presentation.controller;
import dev.lions.btpxpress.application.service.EquipeService;
import dev.lions.btpxpress.domain.core.entity.Equipe;
import dev.lions.btpxpress.domain.core.entity.StatutEquipe;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Controller REST pour la gestion des équipes */
@Path("/api/v1/equipes-controller")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Équipes", description = "Gestion des équipes de travail BTP")
public class EquipeController {
private static final Logger logger = LoggerFactory.getLogger(EquipeController.class);
@Inject EquipeService equipeService;
/** Récupère toutes les équipes */
@GET
public Response getAllEquipes() {
try {
List<Equipe> equipes = equipeService.findAll();
return Response.ok(equipes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des équipes", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des équipes"))
.build();
}
}
/** Récupère une équipe par son ID */
@GET
@Path("/{id}")
public Response getEquipeById(@PathParam("id") UUID id) {
try {
Optional<Equipe> equipeOpt = equipeService.findById(id);
if (equipeOpt.isEmpty()) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", "Équipe non trouvée"))
.build();
}
return Response.ok(equipeOpt.get()).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération de l'équipe: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération de l'équipe"))
.build();
}
}
/** Récupère les équipes par statut */
@GET
@Path("/statut/{statut}")
public Response getEquipesByStatut(@PathParam("statut") StatutEquipe statut) {
try {
List<Equipe> equipes = equipeService.findByStatut(statut);
return Response.ok(equipes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des équipes par statut: " + statut, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des équipes"))
.build();
}
}
/** Récupère les équipes actives */
@GET
@Path("/actives")
public Response getEquipesActives() {
try {
List<Equipe> equipes = equipeService.findActives();
return Response.ok(equipes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des équipes actives", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des équipes"))
.build();
}
}
/** Récupère les équipes par chef d'équipe */
@GET
@Path("/chef/{chefId}")
public Response getEquipesByChef(@PathParam("chefId") UUID chefId) {
try {
List<Equipe> equipes = equipeService.findByChef(chefId);
return Response.ok(equipes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des équipes du chef: " + chefId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des équipes"))
.build();
}
}
/** Récupère les équipes par spécialité */
@GET
@Path("/specialite/{specialite}")
public Response getEquipesBySpecialite(@PathParam("specialite") String specialite) {
try {
List<Equipe> equipes = equipeService.findBySpecialite(specialite);
return Response.ok(equipes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des équipes par spécialité: " + specialite, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des équipes"))
.build();
}
}
/** Récupère les équipes disponibles pour une période */
@GET
@Path("/disponibles")
public Response getEquipesDisponibles(
@QueryParam("dateDebut") String dateDebut, @QueryParam("dateFin") String dateFin) {
try {
LocalDate debut = LocalDate.parse(dateDebut);
LocalDate fin = LocalDate.parse(dateFin);
List<Equipe> equipes = equipeService.findDisponibles(debut, fin);
return Response.ok(equipes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des équipes disponibles", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des équipes"))
.build();
}
}
/** Récupère les équipes par taille minimum */
@GET
@Path("/taille-minimum/{taille}")
public Response getEquipesByTailleMinimum(@PathParam("taille") int taille) {
try {
List<Equipe> equipes = equipeService.findByTailleMinimum(taille);
return Response.ok(equipes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des équipes par taille: " + taille, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des équipes"))
.build();
}
}
/** Récupère les équipes par niveau d'expérience */
@GET
@Path("/experience/{niveau}")
public Response getEquipesByExperience(@PathParam("niveau") String niveau) {
try {
List<Equipe> equipes = equipeService.findByNiveauExperience(niveau);
return Response.ok(equipes).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des équipes par expérience: " + niveau, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des équipes"))
.build();
}
}
/** Crée une nouvelle équipe */
@POST
public Response createEquipe(@Valid Equipe equipe) {
try {
Equipe nouvelleEquipe = equipeService.create(equipe);
return Response.status(Response.Status.CREATED).entity(nouvelleEquipe).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la création de l'équipe", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la création de l'équipe"))
.build();
}
}
/** Met à jour une équipe */
@PUT
@Path("/{id}")
public Response updateEquipe(@PathParam("id") UUID id, @Valid Equipe equipeData) {
try {
Equipe equipe = equipeService.update(id, equipeData);
return Response.ok(equipe).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour de l'équipe: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la mise à jour de l'équipe"))
.build();
}
}
/** Active une équipe */
@POST
@Path("/{id}/activer")
public Response activerEquipe(@PathParam("id") UUID id) {
try {
Equipe equipe = equipeService.activerEquipe(id);
return Response.ok(equipe).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'activation de l'équipe: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de l'activation de l'équipe"))
.build();
}
}
/** Désactive une équipe */
@POST
@Path("/{id}/desactiver")
public Response desactiverEquipe(@PathParam("id") UUID id, Map<String, String> payload) {
try {
String motif = payload != null ? payload.get("motif") : null;
Equipe equipe = equipeService.desactiverEquipe(id, motif);
return Response.ok(equipe).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la désactivation de l'équipe: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la désactivation de l'équipe"))
.build();
}
}
/** Ajoute un membre à l'équipe */
@POST
@Path("/{id}/ajouter-membre")
public Response ajouterMembre(@PathParam("id") UUID equipeId, Map<String, Object> payload) {
try {
UUID employeId = UUID.fromString(payload.get("employeId").toString());
String role = payload.get("role") != null ? payload.get("role").toString() : null;
Equipe equipe = equipeService.ajouterMembre(equipeId, employeId, role);
return Response.ok(equipe).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'ajout de membre: " + equipeId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de l'ajout de membre"))
.build();
}
}
/** Retire un membre de l'équipe */
@POST
@Path("/{id}/retirer-membre")
public Response retirerMembre(@PathParam("id") UUID equipeId, Map<String, Object> payload) {
try {
UUID employeId = UUID.fromString(payload.get("employeId").toString());
Equipe equipe = equipeService.retirerMembre(equipeId, employeId);
return Response.ok(equipe).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors du retrait de membre: " + equipeId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors du retrait de membre"))
.build();
}
}
/** Change le chef d'équipe */
@POST
@Path("/{id}/changer-chef")
public Response changerChef(@PathParam("id") UUID equipeId, Map<String, Object> payload) {
try {
UUID nouveauChefId = UUID.fromString(payload.get("nouveauChefId").toString());
Equipe equipe = equipeService.changerChef(equipeId, nouveauChefId);
return Response.ok(equipe).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors du changement de chef: " + equipeId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors du changement de chef"))
.build();
}
}
/** Supprime une équipe */
@DELETE
@Path("/{id}")
public Response deleteEquipe(@PathParam("id") UUID id) {
try {
equipeService.delete(id);
return Response.noContent().build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la suppression de l'équipe: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la suppression de l'équipe"))
.build();
}
}
/** Recherche d'équipes par multiple critères */
@GET
@Path("/search")
public Response searchEquipes(@QueryParam("term") String searchTerm) {
try {
if (searchTerm == null || searchTerm.trim().isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Terme de recherche requis"))
.build();
}
List<Equipe> equipes = equipeService.searchEquipes(searchTerm);
return Response.ok(equipes).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche d'équipes: " + searchTerm, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la recherche"))
.build();
}
}
/** Récupère les statistiques des équipes */
@GET
@Path("/statistiques")
public Response getStatistiques() {
try {
Map<String, Object> stats = equipeService.getStatistiques();
return Response.ok(stats).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des statistiques"))
.build();
}
}
/** Récupère les membres d'une équipe */
@GET
@Path("/{id}/membres")
public Response getMembresEquipe(@PathParam("id") UUID id) {
try {
List<Object> membres = equipeService.getMembresEquipe(id);
return Response.ok(membres).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des membres: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des membres"))
.build();
}
}
/** Récupère le planning d'une équipe */
@GET
@Path("/{id}/planning")
public Response getPlanningEquipe(
@PathParam("id") UUID id,
@QueryParam("dateDebut") String dateDebut,
@QueryParam("dateFin") String dateFin) {
try {
LocalDate debut = LocalDate.parse(dateDebut);
LocalDate fin = LocalDate.parse(dateFin);
List<Object> planning = equipeService.getPlanningEquipe(id, debut, fin);
return Response.ok(planning).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du planning: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du planning"))
.build();
}
}
/** Récupère les performances d'une équipe */
@GET
@Path("/{id}/performances")
public Response getPerformancesEquipe(@PathParam("id") UUID id) {
try {
Map<String, Object> performances = equipeService.getPerformancesEquipe(id);
return Response.ok(performances).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des performances: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des performances"))
.build();
}
}
}

View File

@@ -0,0 +1,515 @@
package dev.lions.btpxpress.presentation.controller;
import dev.lions.btpxpress.application.service.FournisseurService;
import dev.lions.btpxpress.domain.core.entity.Fournisseur;
import dev.lions.btpxpress.domain.core.entity.SpecialiteFournisseur;
import dev.lions.btpxpress.domain.core.entity.StatutFournisseur;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Contrôleur REST pour la gestion des fournisseurs Gère toutes les opérations CRUD et métier liées
* aux fournisseurs
*/
@Path("/api/v1/fournisseurs")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Fournisseurs", description = "Gestion des fournisseurs et partenaires BTP")
public class FournisseurController {
private static final Logger logger = LoggerFactory.getLogger(FournisseurController.class);
@Inject FournisseurService fournisseurService;
/** Récupère tous les fournisseurs */
@GET
public Response getAllFournisseurs() {
try {
List<Fournisseur> fournisseurs = fournisseurService.findAll();
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des fournisseurs", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Récupère un fournisseur par son ID */
@GET
@Path("/{id}")
public Response getFournisseurById(@PathParam("id") UUID id) {
try {
Fournisseur fournisseur = fournisseurService.findById(id);
return Response.ok(fournisseur).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du fournisseur: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du fournisseur"))
.build();
}
}
/** Récupère tous les fournisseurs actifs */
@GET
@Path("/actifs")
public Response getFournisseursActifs() {
try {
List<Fournisseur> fournisseurs = fournisseurService.findActifs();
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des fournisseurs actifs", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Récupère les fournisseurs par statut */
@GET
@Path("/statut/{statut}")
public Response getFournisseursByStatut(@PathParam("statut") StatutFournisseur statut) {
try {
List<Fournisseur> fournisseurs = fournisseurService.findByStatut(statut);
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des fournisseurs par statut: " + statut, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Récupère les fournisseurs par spécialité */
@GET
@Path("/specialite/{specialite}")
public Response getFournisseursBySpecialite(
@PathParam("specialite") SpecialiteFournisseur specialite) {
try {
List<Fournisseur> fournisseurs = fournisseurService.findBySpecialite(specialite);
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des fournisseurs par spécialité: " + specialite, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Récupère un fournisseur par SIRET */
@GET
@Path("/siret/{siret}")
public Response getFournisseurBySiret(@PathParam("siret") String siret) {
try {
Fournisseur fournisseur = fournisseurService.findBySiret(siret);
if (fournisseur == null) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", "Fournisseur non trouvé"))
.build();
}
return Response.ok(fournisseur).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du fournisseur par SIRET: " + siret, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du fournisseur"))
.build();
}
}
/** Récupère un fournisseur par numéro de TVA */
@GET
@Path("/tva/{numeroTVA}")
public Response getFournisseurByNumeroTVA(@PathParam("numeroTVA") String numeroTVA) {
try {
Fournisseur fournisseur = fournisseurService.findByNumeroTVA(numeroTVA);
if (fournisseur == null) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", "Fournisseur non trouvé"))
.build();
}
return Response.ok(fournisseur).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du fournisseur par TVA: " + numeroTVA, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du fournisseur"))
.build();
}
}
/** Recherche de fournisseurs par nom ou raison sociale */
@GET
@Path("/search/nom")
public Response searchFournisseursByNom(@QueryParam("nom") String searchTerm) {
try {
if (searchTerm == null || searchTerm.trim().isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Terme de recherche requis"))
.build();
}
List<Fournisseur> fournisseurs = fournisseurService.searchByNom(searchTerm);
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche par nom: " + searchTerm, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la recherche"))
.build();
}
}
/** Récupère les fournisseurs préférés */
@GET
@Path("/preferes")
public Response getFournisseursPreferes() {
try {
List<Fournisseur> fournisseurs = fournisseurService.findPreferes();
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des fournisseurs préférés", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Récupère les fournisseurs avec assurance RC professionnelle */
@GET
@Path("/avec-assurance")
public Response getFournisseursAvecAssurance() {
try {
List<Fournisseur> fournisseurs = fournisseurService.findAvecAssuranceRC();
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des fournisseurs avec assurance", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Récupère les fournisseurs avec assurance expirée ou proche de l'expiration */
@GET
@Path("/assurance-expire")
public Response getFournisseursAssuranceExpiree(
@QueryParam("nbJours") @DefaultValue("30") int nbJours) {
try {
List<Fournisseur> fournisseurs = fournisseurService.findAssuranceExpireeOuProche(nbJours);
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des fournisseurs assurance expirée", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Récupère les fournisseurs par ville */
@GET
@Path("/ville/{ville}")
public Response getFournisseursByVille(@PathParam("ville") String ville) {
try {
List<Fournisseur> fournisseurs = fournisseurService.findByVille(ville);
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des fournisseurs par ville: " + ville, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Récupère les fournisseurs par code postal */
@GET
@Path("/code-postal/{codePostal}")
public Response getFournisseursByCodePostal(@PathParam("codePostal") String codePostal) {
try {
List<Fournisseur> fournisseurs = fournisseurService.findByCodePostal(codePostal);
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des fournisseurs par code postal: " + codePostal, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Récupère les fournisseurs dans une zone géographique */
@GET
@Path("/zone/{prefixeCodePostal}")
public Response getFournisseursByZone(@PathParam("prefixeCodePostal") String prefixeCodePostal) {
try {
List<Fournisseur> fournisseurs = fournisseurService.findByZoneGeographique(prefixeCodePostal);
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des fournisseurs par zone: " + prefixeCodePostal, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Récupère les fournisseurs sans commande depuis X jours */
@GET
@Path("/sans-commande")
public Response getFournisseursSansCommande(
@QueryParam("nbJours") @DefaultValue("90") int nbJours) {
try {
List<Fournisseur> fournisseurs = fournisseurService.findSansCommandeDepuis(nbJours);
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des fournisseurs sans commande", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Récupère les top fournisseurs par montant d'achats */
@GET
@Path("/top-montant")
public Response getTopFournisseursByMontant(@QueryParam("limit") @DefaultValue("10") int limit) {
try {
List<Fournisseur> fournisseurs = fournisseurService.findTopFournisseursByMontant(limit);
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des top fournisseurs par montant", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Récupère les top fournisseurs par nombre de commandes */
@GET
@Path("/top-commandes")
public Response getTopFournisseursByNombreCommandes(
@QueryParam("limit") @DefaultValue("10") int limit) {
try {
List<Fournisseur> fournisseurs =
fournisseurService.findTopFournisseursByNombreCommandes(limit);
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des top fournisseurs par commandes", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des fournisseurs"))
.build();
}
}
/** Crée un nouveau fournisseur */
@POST
public Response createFournisseur(@Valid Fournisseur fournisseur) {
try {
Fournisseur nouveauFournisseur = fournisseurService.create(fournisseur);
return Response.status(Response.Status.CREATED).entity(nouveauFournisseur).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la création du fournisseur", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la création du fournisseur"))
.build();
}
}
/** Met à jour un fournisseur */
@PUT
@Path("/{id}")
public Response updateFournisseur(@PathParam("id") UUID id, @Valid Fournisseur fournisseurData) {
try {
Fournisseur fournisseur = fournisseurService.update(id, fournisseurData);
return Response.ok(fournisseur).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour du fournisseur: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la mise à jour du fournisseur"))
.build();
}
}
/** Active un fournisseur */
@POST
@Path("/{id}/activer")
public Response activerFournisseur(@PathParam("id") UUID id) {
try {
Fournisseur fournisseur = fournisseurService.activerFournisseur(id);
return Response.ok(fournisseur).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'activation du fournisseur: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de l'activation du fournisseur"))
.build();
}
}
/** Désactive un fournisseur */
@POST
@Path("/{id}/desactiver")
public Response desactiverFournisseur(@PathParam("id") UUID id, Map<String, String> payload) {
try {
String motif = payload != null ? payload.get("motif") : null;
Fournisseur fournisseur = fournisseurService.desactiverFournisseur(id, motif);
return Response.ok(fournisseur).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la désactivation du fournisseur: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la désactivation du fournisseur"))
.build();
}
}
/** Met à jour les notes d'évaluation d'un fournisseur */
@POST
@Path("/{id}/evaluation")
public Response evaluerFournisseur(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
BigDecimal noteQualite =
payload.get("noteQualite") != null
? new BigDecimal(payload.get("noteQualite").toString())
: null;
BigDecimal noteDelai =
payload.get("noteDelai") != null
? new BigDecimal(payload.get("noteDelai").toString())
: null;
BigDecimal notePrix =
payload.get("notePrix") != null
? new BigDecimal(payload.get("notePrix").toString())
: null;
String commentaires =
payload.get("commentaires") != null ? payload.get("commentaires").toString() : null;
Fournisseur fournisseur =
fournisseurService.evaluerFournisseur(id, noteQualite, noteDelai, notePrix, commentaires);
return Response.ok(fournisseur).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Notes d'évaluation invalides"))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'évaluation du fournisseur: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de l'évaluation du fournisseur"))
.build();
}
}
/** Marque un fournisseur comme préféré */
@POST
@Path("/{id}/prefere")
public Response marquerPrefere(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
boolean prefere =
payload != null && payload.get("prefere") != null
? Boolean.parseBoolean(payload.get("prefere").toString())
: true;
Fournisseur fournisseur = fournisseurService.marquerPrefere(id, prefere);
return Response.ok(fournisseur).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors du marquage préféré du fournisseur: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors du marquage du fournisseur"))
.build();
}
}
/** Supprime un fournisseur */
@DELETE
@Path("/{id}")
public Response deleteFournisseur(@PathParam("id") UUID id) {
try {
fournisseurService.delete(id);
return Response.noContent().build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la suppression du fournisseur: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la suppression du fournisseur"))
.build();
}
}
/** Récupère les statistiques des fournisseurs */
@GET
@Path("/statistiques")
public Response getStatistiques() {
try {
Map<String, Object> stats = fournisseurService.getStatistiques();
return Response.ok(stats).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des statistiques"))
.build();
}
}
/** Recherche de fournisseurs par multiple critères */
@GET
@Path("/search")
public Response searchFournisseurs(@QueryParam("term") String searchTerm) {
try {
if (searchTerm == null || searchTerm.trim().isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Terme de recherche requis"))
.build();
}
List<Fournisseur> fournisseurs = fournisseurService.searchFournisseurs(searchTerm);
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche de fournisseurs: " + searchTerm, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la recherche"))
.build();
}
}
}

View File

@@ -0,0 +1,479 @@
package dev.lions.btpxpress.presentation.controller;
import dev.lions.btpxpress.application.service.MaterielService;
import dev.lions.btpxpress.domain.core.entity.Materiel;
import dev.lions.btpxpress.domain.core.entity.StatutMateriel;
import dev.lions.btpxpress.domain.core.entity.TypeMateriel;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Controller REST pour la gestion du matériel */
@Path("/api/materiel")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Matériels", description = "Gestion des matériels et équipements")
public class MaterielController {
private static final Logger logger = LoggerFactory.getLogger(MaterielController.class);
@Inject MaterielService materielService;
/** Récupère tout le matériel */
@GET
public Response getAllMateriel() {
try {
List<Materiel> materiel = materielService.findAll();
return Response.ok(materiel).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du matériel", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du matériel"))
.build();
}
}
/** Récupère un matériel par son ID */
@GET
@Path("/{id}")
public Response getMaterielById(@PathParam("id") UUID id) {
try {
Optional<Materiel> materielOpt = materielService.findById(id);
if (materielOpt.isEmpty()) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", "Matériel non trouvé"))
.build();
}
return Response.ok(materielOpt.get()).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du matériel: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du matériel"))
.build();
}
}
/** Récupère le matériel par statut */
@GET
@Path("/statut/{statut}")
public Response getMaterielByStatut(@PathParam("statut") StatutMateriel statut) {
try {
List<Materiel> materiel = materielService.findByStatut(statut);
return Response.ok(materiel).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du matériel par statut: " + statut, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du matériel"))
.build();
}
}
/** Récupère le matériel disponible */
@GET
@Path("/disponible")
public Response getMaterielDisponible() {
try {
List<Materiel> materiel = materielService.findDisponible();
return Response.ok(materiel).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du matériel disponible", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du matériel"))
.build();
}
}
/** Récupère le matériel par type */
@GET
@Path("/type/{type}")
public Response getMaterielByType(@PathParam("type") String type) {
try {
TypeMateriel typeMateriel = TypeMateriel.valueOf(type.toUpperCase());
List<Materiel> materiel = materielService.findByType(typeMateriel);
return Response.ok(materiel).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du matériel par type: " + type, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du matériel"))
.build();
}
}
/** Récupère le matériel par chantier */
@GET
@Path("/chantier/{chantierId}")
public Response getMaterielByChantier(@PathParam("chantierId") UUID chantierId) {
try {
List<Materiel> materiel = materielService.findByChantier(chantierId);
return Response.ok(materiel).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du matériel du chantier: " + chantierId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du matériel"))
.build();
}
}
/** Récupère le matériel par marque */
@GET
@Path("/marque/{marque}")
public Response getMaterielByMarque(@PathParam("marque") String marque) {
try {
List<Materiel> materiel = materielService.findByMarque(marque);
return Response.ok(materiel).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du matériel par marque: " + marque, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du matériel"))
.build();
}
}
/** Récupère le matériel nécessitant une maintenance */
@GET
@Path("/maintenance-requise")
public Response getMaterielMaintenanceRequise() {
try {
List<Materiel> materiel = materielService.findMaintenanceRequise();
return Response.ok(materiel).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du matériel nécessitant maintenance", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du matériel"))
.build();
}
}
/** Récupère le matériel en panne */
@GET
@Path("/en-panne")
public Response getMaterielEnPanne() {
try {
List<Materiel> materiel = materielService.findEnPanne();
return Response.ok(materiel).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du matériel en panne", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du matériel"))
.build();
}
}
/** Récupère le matériel disponible pour une période */
@GET
@Path("/disponible-periode")
public Response getMaterielDisponiblePeriode(
@QueryParam("dateDebut") String dateDebut, @QueryParam("dateFin") String dateFin) {
try {
LocalDate debut = LocalDate.parse(dateDebut);
LocalDate fin = LocalDate.parse(dateFin);
List<Materiel> materiel = materielService.findDisponiblePeriode(debut, fin);
return Response.ok(materiel).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du matériel disponible pour la période", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du matériel"))
.build();
}
}
/** Crée un nouveau matériel */
@POST
public Response createMateriel(@Valid Materiel materiel) {
try {
Materiel nouveauMateriel = materielService.create(materiel);
return Response.status(Response.Status.CREATED).entity(nouveauMateriel).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la création du matériel", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la création du matériel"))
.build();
}
}
/** Met à jour un matériel */
@PUT
@Path("/{id}")
public Response updateMateriel(@PathParam("id") UUID id, @Valid Materiel materielData) {
try {
Materiel materiel = materielService.update(id, materielData);
return Response.ok(materiel).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour du matériel: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la mise à jour du matériel"))
.build();
}
}
/** Affecte un matériel à un chantier */
@POST
@Path("/{id}/affecter-chantier")
public Response affecterChantier(@PathParam("id") UUID materielId, Map<String, Object> payload) {
try {
UUID chantierId = UUID.fromString(payload.get("chantierId").toString());
LocalDate dateDebut = LocalDate.parse(payload.get("dateDebut").toString());
LocalDate dateFin =
payload.get("dateFin") != null
? LocalDate.parse(payload.get("dateFin").toString())
: null;
Materiel materiel =
materielService.affecterChantier(materielId, chantierId, dateDebut, dateFin);
return Response.ok(materiel).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'affectation au chantier: " + materielId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de l'affectation au chantier"))
.build();
}
}
/** Libère un matériel du chantier */
@POST
@Path("/{id}/liberer-chantier")
public Response libererChantier(@PathParam("id") UUID materielId) {
try {
Materiel materiel = materielService.libererChantier(materielId);
return Response.ok(materiel).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la libération du chantier: " + materielId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la libération du chantier"))
.build();
}
}
/** Marque un matériel en maintenance */
@POST
@Path("/{id}/maintenance")
public Response marquerMaintenance(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
String description =
payload.get("description") != null ? payload.get("description").toString() : null;
LocalDate datePrevue =
payload.get("datePrevue") != null
? LocalDate.parse(payload.get("datePrevue").toString())
: null;
Materiel materiel = materielService.marquerMaintenance(id, description, datePrevue);
return Response.ok(materiel).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors du marquage en maintenance: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors du marquage en maintenance"))
.build();
}
}
/** Marque un matériel en panne */
@POST
@Path("/{id}/panne")
public Response marquerPanne(@PathParam("id") UUID id, Map<String, String> payload) {
try {
String description = payload != null ? payload.get("description") : null;
Materiel materiel = materielService.marquerPanne(id, description);
return Response.ok(materiel).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors du marquage en panne: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors du marquage en panne"))
.build();
}
}
/** Répare un matériel */
@POST
@Path("/{id}/reparer")
public Response reparerMateriel(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
String description =
payload != null && payload.get("description") != null
? payload.get("description").toString()
: null;
LocalDate dateReparation =
payload != null && payload.get("dateReparation") != null
? LocalDate.parse(payload.get("dateReparation").toString())
: LocalDate.now();
Materiel materiel = materielService.reparer(id, description, dateReparation);
return Response.ok(materiel).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la réparation: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la réparation"))
.build();
}
}
/** Retire définitivement un matériel */
@POST
@Path("/{id}/retirer")
public Response retirerMateriel(@PathParam("id") UUID id, Map<String, String> payload) {
try {
String motif = payload != null ? payload.get("motif") : null;
Materiel materiel = materielService.retirerDefinitivement(id, motif);
return Response.ok(materiel).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors du retrait définitif: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors du retrait définitif"))
.build();
}
}
/** Supprime un matériel */
@DELETE
@Path("/{id}")
public Response deleteMateriel(@PathParam("id") UUID id) {
try {
materielService.delete(id);
return Response.noContent().build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la suppression du matériel: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la suppression du matériel"))
.build();
}
}
/** Recherche de matériel par multiple critères */
@GET
@Path("/search")
public Response searchMateriel(@QueryParam("term") String searchTerm) {
try {
if (searchTerm == null || searchTerm.trim().isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Terme de recherche requis"))
.build();
}
List<Materiel> materiel = materielService.searchMateriel(searchTerm);
return Response.ok(materiel).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche de matériel: " + searchTerm, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la recherche"))
.build();
}
}
/** Récupère les statistiques du matériel */
@GET
@Path("/statistiques")
public Response getStatistiques() {
try {
Map<String, Object> stats = materielService.getStatistiques();
return Response.ok(stats).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des statistiques"))
.build();
}
}
/** Récupère l'historique d'utilisation d'un matériel */
@GET
@Path("/{id}/historique")
public Response getHistoriqueUtilisation(@PathParam("id") UUID id) {
try {
List<Object> historique = materielService.getHistoriqueUtilisation(id);
return Response.ok(historique).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération de l'historique: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération de l'historique"))
.build();
}
}
/** Récupère le planning d'utilisation d'un matériel */
@GET
@Path("/{id}/planning")
public Response getPlanningMateriel(
@PathParam("id") UUID id,
@QueryParam("dateDebut") String dateDebut,
@QueryParam("dateFin") String dateFin) {
try {
LocalDate debut = LocalDate.parse(dateDebut);
LocalDate fin = LocalDate.parse(dateFin);
List<Object> planning = materielService.getPlanningMateriel(id, debut, fin);
return Response.ok(planning).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du planning: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du planning"))
.build();
}
}
}

View File

@@ -0,0 +1,406 @@
package dev.lions.btpxpress.presentation.controller;
import dev.lions.btpxpress.application.service.PhaseChantierService;
import dev.lions.btpxpress.domain.core.entity.PhaseChantier;
import dev.lions.btpxpress.domain.core.entity.StatutPhaseChantier;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Contrôleur REST pour la gestion des phases de chantier Permet de suivre l'avancement détaillé de
* chaque phase d'un chantier
*/
@Path("/api/v1/phases")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Phases de Chantier", description = "Gestion des phases et jalons de chantiers BTP")
public class PhaseChantierController {
private static final Logger logger = LoggerFactory.getLogger(PhaseChantierController.class);
@Inject PhaseChantierService phaseChantierService;
/** Récupère toutes les phases */
@GET
public Response getAllPhases() {
try {
List<PhaseChantier> phases = phaseChantierService.findAll();
return Response.ok(phases).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des phases", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des phases"))
.build();
}
}
/** Récupère une phase par son ID */
@GET
@Path("/{id}")
public Response getPhaseById(@PathParam("id") UUID id) {
try {
PhaseChantier phase = phaseChantierService.findById(id);
return Response.ok(phase).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération de la phase: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération de la phase"))
.build();
}
}
/** Récupère les phases d'un chantier */
@GET
@Path("/chantier/{chantierId}")
public Response getPhasesByChantier(@PathParam("chantierId") UUID chantierId) {
try {
List<PhaseChantier> phases = phaseChantierService.findByChantier(chantierId);
return Response.ok(phases).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des phases du chantier: " + chantierId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des phases"))
.build();
}
}
/** Récupère les phases par statut */
@GET
@Path("/statut/{statut}")
public Response getPhasesByStatut(@PathParam("statut") StatutPhaseChantier statut) {
try {
List<PhaseChantier> phases = phaseChantierService.findByStatut(statut);
return Response.ok(phases).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des phases par statut: " + statut, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des phases"))
.build();
}
}
/** Récupère les phases en retard */
@GET
@Path("/en-retard")
public Response getPhasesEnRetard() {
try {
List<PhaseChantier> phases = phaseChantierService.findPhasesEnRetard();
return Response.ok(phases).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des phases en retard", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des phases"))
.build();
}
}
/** Récupère les phases en cours */
@GET
@Path("/en-cours")
public Response getPhasesEnCours() {
try {
List<PhaseChantier> phases = phaseChantierService.findPhasesEnCours();
return Response.ok(phases).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des phases en cours", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des phases"))
.build();
}
}
/** Récupère les phases critiques */
@GET
@Path("/critiques")
public Response getPhasesCritiques() {
try {
List<PhaseChantier> phases = phaseChantierService.findPhasesCritiques();
return Response.ok(phases).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des phases critiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des phases"))
.build();
}
}
/** Récupère les phases nécessitant une attention */
@GET
@Path("/attention")
public Response getPhasesNecessitantAttention() {
try {
List<PhaseChantier> phases = phaseChantierService.findPhasesNecessitantAttention();
return Response.ok(phases).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des phases nécessitant attention", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des phases"))
.build();
}
}
/** Crée une nouvelle phase */
@POST
public Response createPhase(@Valid PhaseChantier phase) {
try {
PhaseChantier nouvellephase = phaseChantierService.create(phase);
return Response.status(Response.Status.CREATED).entity(nouvellephase).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la création de la phase", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la création de la phase"))
.build();
}
}
/** Met à jour une phase */
@PUT
@Path("/{id}")
public Response updatePhase(@PathParam("id") UUID id, @Valid PhaseChantier phaseData) {
try {
PhaseChantier phase = phaseChantierService.update(id, phaseData);
return Response.ok(phase).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour de la phase: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la mise à jour de la phase"))
.build();
}
}
/** Démarre une phase */
@POST
@Path("/{id}/demarrer")
public Response demarrerPhase(@PathParam("id") UUID id) {
try {
PhaseChantier phase = phaseChantierService.demarrerPhase(id);
return Response.ok(phase).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors du démarrage de la phase: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors du démarrage de la phase"))
.build();
}
}
/** Termine une phase */
@POST
@Path("/{id}/terminer")
public Response terminerPhase(@PathParam("id") UUID id) {
try {
PhaseChantier phase = phaseChantierService.terminerPhase(id);
return Response.ok(phase).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la terminaison de la phase: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la terminaison de la phase"))
.build();
}
}
/** Suspend une phase */
@POST
@Path("/{id}/suspendre")
public Response suspendrePhase(@PathParam("id") UUID id, Map<String, String> payload) {
try {
String motif = payload.get("motif");
PhaseChantier phase = phaseChantierService.suspendrPhase(id, motif);
return Response.ok(phase).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la suspension de la phase: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la suspension de la phase"))
.build();
}
}
/** Reprend une phase suspendue */
@POST
@Path("/{id}/reprendre")
public Response reprendrePhase(@PathParam("id") UUID id) {
try {
PhaseChantier phase = phaseChantierService.reprendrePhase(id);
return Response.ok(phase).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la reprise de la phase: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la reprise de la phase"))
.build();
}
}
/** Met à jour l'avancement d'une phase */
@POST
@Path("/{id}/avancement")
public Response updateAvancement(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
BigDecimal pourcentage = new BigDecimal(payload.get("pourcentage").toString());
PhaseChantier phase = phaseChantierService.updateAvancement(id, pourcentage);
return Response.ok(phase).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Pourcentage invalide"))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour de l'avancement: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la mise à jour de l'avancement"))
.build();
}
}
/** Affecte une équipe à une phase */
@POST
@Path("/{id}/affecter-equipe")
public Response affecterEquipe(@PathParam("id") UUID phaseId, Map<String, Object> payload) {
try {
UUID equipeId =
payload.get("equipeId") != null
? UUID.fromString(payload.get("equipeId").toString())
: null;
UUID chefEquipeId =
payload.get("chefEquipeId") != null
? UUID.fromString(payload.get("chefEquipeId").toString())
: null;
PhaseChantier phase = phaseChantierService.affecterEquipe(phaseId, equipeId, chefEquipeId);
return Response.ok(phase).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'affectation d'équipe: " + phaseId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de l'affectation d'équipe"))
.build();
}
}
/** Planifie automatiquement les phases d'un chantier */
@POST
@Path("/chantier/{chantierId}/planifier")
public Response planifierPhasesAutomatique(
@PathParam("chantierId") UUID chantierId, Map<String, String> payload) {
try {
LocalDate dateDebut = LocalDate.parse(payload.get("dateDebut"));
List<PhaseChantier> phases =
phaseChantierService.planifierPhasesAutomatique(chantierId, dateDebut);
return Response.ok(phases).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Date de début invalide"))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la planification automatique: " + chantierId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la planification automatique"))
.build();
}
}
/** Supprime une phase */
@DELETE
@Path("/{id}")
public Response deletePhase(@PathParam("id") UUID id) {
try {
phaseChantierService.delete(id);
return Response.noContent().build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la suppression de la phase: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la suppression de la phase"))
.build();
}
}
/** Récupère les statistiques des phases */
@GET
@Path("/statistiques")
public Response getStatistiques() {
try {
Map<String, Object> stats = phaseChantierService.getStatistiques();
return Response.ok(stats).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des statistiques"))
.build();
}
}
}

View File

@@ -0,0 +1,564 @@
package dev.lions.btpxpress.presentation.controller;
import dev.lions.btpxpress.application.service.StockService;
import dev.lions.btpxpress.domain.core.entity.CategorieStock;
import dev.lions.btpxpress.domain.core.entity.StatutStock;
import dev.lions.btpxpress.domain.core.entity.Stock;
import jakarta.inject.Inject;
import jakarta.validation.Valid;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Contrôleur REST pour la gestion des stocks et inventaires Permet de gérer les entrées, sorties,
* réservations et suivi des stocks BTP
*/
@Path("/api/v1/stocks")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Stocks", description = "Gestion des stocks et inventaires BTP")
public class StockController {
private static final Logger logger = LoggerFactory.getLogger(StockController.class);
@Inject StockService stockService;
/** Récupère tous les stocks */
@GET
public Response getAllStocks() {
try {
List<Stock> stocks = stockService.findAll();
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère un stock par son ID */
@GET
@Path("/{id}")
public Response getStockById(@PathParam("id") UUID id) {
try {
Stock stock = stockService.findById(id);
return Response.ok(stock).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du stock: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du stock"))
.build();
}
}
/** Récupère un stock par sa référence */
@GET
@Path("/reference/{reference}")
public Response getStockByReference(@PathParam("reference") String reference) {
try {
Stock stock = stockService.findByReference(reference);
if (stock == null) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", "Stock non trouvé"))
.build();
}
return Response.ok(stock).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du stock par référence: " + reference, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération du stock"))
.build();
}
}
/** Recherche des stocks par désignation */
@GET
@Path("/search/designation")
public Response searchByDesignation(@QueryParam("designation") String designation) {
try {
if (designation == null || designation.trim().isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Désignation requise"))
.build();
}
List<Stock> stocks = stockService.searchByDesignation(designation);
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche par désignation: " + designation, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la recherche"))
.build();
}
}
/** Récupère les stocks par catégorie */
@GET
@Path("/categorie/{categorie}")
public Response getStocksByCategorie(@PathParam("categorie") CategorieStock categorie) {
try {
List<Stock> stocks = stockService.findByCategorie(categorie);
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks par catégorie: " + categorie, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère les stocks par statut */
@GET
@Path("/statut/{statut}")
public Response getStocksByStatut(@PathParam("statut") StatutStock statut) {
try {
List<Stock> stocks = stockService.findByStatut(statut);
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks par statut: " + statut, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère les stocks actifs */
@GET
@Path("/actifs")
public Response getStocksActifs() {
try {
List<Stock> stocks = stockService.findActifs();
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks actifs", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère les stocks par fournisseur */
@GET
@Path("/fournisseur/{fournisseurId}")
public Response getStocksByFournisseur(@PathParam("fournisseurId") UUID fournisseurId) {
try {
List<Stock> stocks = stockService.findByFournisseur(fournisseurId);
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks du fournisseur: " + fournisseurId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère les stocks par chantier */
@GET
@Path("/chantier/{chantierId}")
public Response getStocksByChantier(@PathParam("chantierId") UUID chantierId) {
try {
List<Stock> stocks = stockService.findByChantier(chantierId);
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks du chantier: " + chantierId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère les stocks en rupture */
@GET
@Path("/rupture")
public Response getStocksEnRupture() {
try {
List<Stock> stocks = stockService.findStocksEnRupture();
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks en rupture", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère les stocks sous quantité minimum */
@GET
@Path("/sous-minimum")
public Response getStocksSousQuantiteMinimum() {
try {
List<Stock> stocks = stockService.findStocksSousQuantiteMinimum();
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks sous minimum", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère les stocks sous quantité de sécurité */
@GET
@Path("/sous-securite")
public Response getStocksSousQuantiteSecurite() {
try {
List<Stock> stocks = stockService.findStocksSousQuantiteSecurite();
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks sous sécurité", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère les stocks à commander */
@GET
@Path("/a-commander")
public Response getStocksACommander() {
try {
List<Stock> stocks = stockService.findStocksACommander();
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks à commander", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère les stocks périmés */
@GET
@Path("/perimes")
public Response getStocksPerimes() {
try {
List<Stock> stocks = stockService.findStocksPerimes();
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks périmés", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère les stocks proches de la péremption */
@GET
@Path("/proches-peremption")
public Response getStocksProchesPeremption(
@QueryParam("nbJours") @DefaultValue("30") int nbJours) {
try {
List<Stock> stocks = stockService.findStocksProchesPeremption(nbJours);
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks proches péremption", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère les stocks avec réservations */
@GET
@Path("/avec-reservations")
public Response getStocksAvecReservations() {
try {
List<Stock> stocks = stockService.findStocksAvecReservations();
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des stocks avec réservations", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Crée un nouveau stock */
@POST
public Response createStock(@Valid Stock stock) {
try {
Stock nouveauStock = stockService.create(stock);
return Response.status(Response.Status.CREATED).entity(nouveauStock).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la création du stock", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la création du stock"))
.build();
}
}
/** Met à jour un stock */
@PUT
@Path("/{id}")
public Response updateStock(@PathParam("id") UUID id, @Valid Stock stockData) {
try {
Stock stock = stockService.update(id, stockData);
return Response.ok(stock).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour du stock: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la mise à jour du stock"))
.build();
}
}
/** Entrée de stock */
@POST
@Path("/{id}/entree")
public Response entreeStock(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
BigDecimal quantite = new BigDecimal(payload.get("quantite").toString());
String motif = payload.get("motif") != null ? payload.get("motif").toString() : null;
String numeroDocument =
payload.get("numeroDocument") != null ? payload.get("numeroDocument").toString() : null;
Stock stock = stockService.entreeStock(id, quantite, motif, numeroDocument);
return Response.ok(stock).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Quantité ou données invalides"))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'entrée de stock: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de l'entrée de stock"))
.build();
}
}
/** Sortie de stock */
@POST
@Path("/{id}/sortie")
public Response sortieStock(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
BigDecimal quantite = new BigDecimal(payload.get("quantite").toString());
String motif = payload.get("motif") != null ? payload.get("motif").toString() : null;
String numeroDocument =
payload.get("numeroDocument") != null ? payload.get("numeroDocument").toString() : null;
Stock stock = stockService.sortieStock(id, quantite, motif, numeroDocument);
return Response.ok(stock).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Quantité insuffisante ou données invalides"))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la sortie de stock: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la sortie de stock"))
.build();
}
}
/** Réservation de stock */
@POST
@Path("/{id}/reserver")
public Response reserverStock(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
BigDecimal quantite = new BigDecimal(payload.get("quantite").toString());
String motif = payload.get("motif") != null ? payload.get("motif").toString() : null;
Stock stock = stockService.reserverStock(id, quantite, motif);
return Response.ok(stock).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Quantité insuffisante ou données invalides"))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la réservation de stock: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la réservation de stock"))
.build();
}
}
/** Libération de réservation */
@POST
@Path("/{id}/liberer-reservation")
public Response libererReservation(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
BigDecimal quantite = new BigDecimal(payload.get("quantite").toString());
Stock stock = stockService.libererReservation(id, quantite);
return Response.ok(stock).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Quantité invalide"))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la libération de réservation: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la libération de réservation"))
.build();
}
}
/** Inventaire d'un stock */
@POST
@Path("/{id}/inventaire")
public Response inventaireStock(@PathParam("id") UUID id, Map<String, Object> payload) {
try {
BigDecimal quantiteReelle = new BigDecimal(payload.get("quantiteReelle").toString());
String motif = payload.get("motif") != null ? payload.get("motif").toString() : "Inventaire";
Stock stock = stockService.inventaireStock(id, quantiteReelle, motif);
return Response.ok(stock).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Quantité invalide"))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'inventaire du stock: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de l'inventaire du stock"))
.build();
}
}
/** Supprime un stock */
@DELETE
@Path("/{id}")
public Response deleteStock(@PathParam("id") UUID id) {
try {
stockService.delete(id);
return Response.noContent().build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (IllegalStateException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", e.getMessage()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la suppression du stock: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la suppression du stock"))
.build();
}
}
/** Recherche de stocks par multiple critères */
@GET
@Path("/search")
public Response searchStocks(@QueryParam("term") String searchTerm) {
try {
if (searchTerm == null || searchTerm.trim().isEmpty()) {
return Response.status(Response.Status.BAD_REQUEST)
.entity(Map.of("error", "Terme de recherche requis"))
.build();
}
List<Stock> stocks = stockService.searchStocks(searchTerm);
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche de stocks: " + searchTerm, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la recherche"))
.build();
}
}
/** Récupère les statistiques des stocks */
@GET
@Path("/statistiques")
public Response getStatistiques() {
try {
Map<String, Object> stats = stockService.getStatistiques();
return Response.ok(stats).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des statistiques"))
.build();
}
}
/** Calcule la valeur totale du stock */
@GET
@Path("/valeur-totale")
public Response getValeurTotaleStock() {
try {
BigDecimal valeurTotale = stockService.calculateValeurTotaleStock();
return Response.ok(Map.of("valeurTotale", valeurTotale)).build();
} catch (Exception e) {
logger.error("Erreur lors du calcul de la valeur totale", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors du calcul de la valeur totale"))
.build();
}
}
/** Récupère les top stocks par valeur */
@GET
@Path("/top-valeur")
public Response getTopStocksByValeur(@QueryParam("limit") @DefaultValue("10") int limit) {
try {
List<Stock> stocks = stockService.findTopStocksByValeur(limit);
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des top stocks par valeur", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
/** Récupère les top stocks par quantité */
@GET
@Path("/top-quantite")
public Response getTopStocksByQuantite(@QueryParam("limit") @DefaultValue("10") int limit) {
try {
List<Stock> stocks = stockService.findTopStocksByQuantite(limit);
return Response.ok(stocks).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des top stocks par quantité", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity(Map.of("error", "Erreur lors de la récupération des stocks"))
.build();
}
}
}

View File

@@ -0,0 +1,519 @@
package dev.lions.btpxpress.presentation.rest;
import dev.lions.btpxpress.application.service.ComparaisonFournisseurService;
import dev.lions.btpxpress.domain.core.entity.*;
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.math.BigDecimal;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* API REST pour la comparaison des fournisseurs EXPOSITION: Endpoints pour l'aide à la décision et
* l'optimisation des achats BTP
*/
@Path("/api/v1/comparaisons-fournisseurs")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ComparaisonFournisseurResource {
private static final Logger logger =
LoggerFactory.getLogger(ComparaisonFournisseurResource.class);
@Inject ComparaisonFournisseurService comparaisonService;
// === ENDPOINTS DE CONSULTATION ===
@GET
@Path("/")
public Response findAll(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("50") int size) {
try {
logger.debug("GET /api/comparaisons-fournisseurs/ - page: {}, size: {}", page, size);
List<ComparaisonFournisseur> comparaisons;
if (page > 0 || size < 1000) {
comparaisons = comparaisonService.findAll(page, size);
} else {
comparaisons = comparaisonService.findAll();
}
return Response.ok(comparaisons).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des comparaisons", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des comparaisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/{id}")
public Response findById(@PathParam("id") UUID id) {
try {
logger.debug("GET /api/comparaisons-fournisseurs/{}", id);
ComparaisonFournisseur comparaison = comparaisonService.findByIdRequired(id);
return Response.ok(comparaison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération de la comparaison: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération de la comparaison: " + e.getMessage())
.build();
}
}
@GET
@Path("/materiel/{materielId}")
public Response findByMateriel(@PathParam("materielId") UUID materielId) {
try {
logger.debug("GET /api/comparaisons-fournisseurs/materiel/{}", materielId);
List<ComparaisonFournisseur> comparaisons = comparaisonService.findByMateriel(materielId);
return Response.ok(comparaisons).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des comparaisons pour matériel: " + materielId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des comparaisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/fournisseur/{fournisseurId}")
public Response findByFournisseur(@PathParam("fournisseurId") UUID fournisseurId) {
try {
logger.debug("GET /api/comparaisons-fournisseurs/fournisseur/{}", fournisseurId);
List<ComparaisonFournisseur> comparaisons =
comparaisonService.findByFournisseur(fournisseurId);
return Response.ok(comparaisons).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des comparaisons pour fournisseur: " + fournisseurId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des comparaisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/session/{sessionId}")
public Response findBySession(@PathParam("sessionId") String sessionId) {
try {
logger.debug("GET /api/comparaisons-fournisseurs/session/{}", sessionId);
List<ComparaisonFournisseur> comparaisons = comparaisonService.findBySession(sessionId);
return Response.ok(comparaisons).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des comparaisons pour session: " + sessionId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des comparaisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/search")
public Response search(@QueryParam("terme") String terme) {
try {
logger.debug("GET /api/comparaisons-fournisseurs/search?terme={}", terme);
List<ComparaisonFournisseur> resultats = comparaisonService.search(terme);
return Response.ok(resultats).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche avec terme: " + terme, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la recherche: " + e.getMessage())
.build();
}
}
// === ENDPOINTS MÉTIER SPÉCIALISÉS ===
@GET
@Path("/meilleures-offres/{materielId}")
public Response findMeilleuresOffres(
@PathParam("materielId") UUID materielId,
@QueryParam("limite") @DefaultValue("5") int limite) {
try {
logger.debug("GET /api/comparaisons-fournisseurs/meilleures-offres/{}", materielId);
List<ComparaisonFournisseur> meilleures =
comparaisonService.findMeilleuresOffres(materielId, limite);
return Response.ok(meilleures).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des meilleures offres: " + materielId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des meilleures offres: " + e.getMessage())
.build();
}
}
@GET
@Path("/recommandees")
public Response findOffresRecommandees() {
try {
logger.debug("GET /api/comparaisons-fournisseurs/recommandees");
List<ComparaisonFournisseur> recommandees = comparaisonService.findOffresRecommandees();
return Response.ok(recommandees).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des offres recommandées", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des offres recommandées: " + e.getMessage())
.build();
}
}
@GET
@Path("/gamme-prix")
public Response findByGammePrix(
@QueryParam("prixMin") @NotNull BigDecimal prixMin,
@QueryParam("prixMax") @NotNull BigDecimal prixMax) {
try {
logger.debug(
"GET /api/comparaisons-fournisseurs/gamme-prix?prixMin={}&prixMax={}", prixMin, prixMax);
List<ComparaisonFournisseur> comparaisons =
comparaisonService.findByGammePrix(prixMin, prixMax);
return Response.ok(comparaisons).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche par gamme de prix", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la recherche par gamme de prix: " + e.getMessage())
.build();
}
}
@GET
@Path("/disponibles-delai")
public Response findDisponiblesDansDelai(
@QueryParam("maxJours") @DefaultValue("30") int maxJours) {
try {
logger.debug("GET /api/comparaisons-fournisseurs/disponibles-delai?maxJours={}", maxJours);
List<ComparaisonFournisseur> disponibles =
comparaisonService.findDisponiblesDansDelai(maxJours);
return Response.ok(disponibles).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche par délai", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la recherche par délai: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE CRÉATION ET GESTION ===
@POST
@Path("/lancer-comparaison")
public Response lancerComparaison(@Valid LancerComparaisonRequest request) {
try {
logger.info("POST /api/comparaisons-fournisseurs/lancer-comparaison");
String sessionId =
comparaisonService.lancerComparaison(
request.materielId,
request.quantiteDemandee,
request.uniteDemandee,
request.dateDebutSouhaitee,
request.dateFinSouhaitee,
request.lieuLivraison,
request.evaluateur);
return Response.status(Response.Status.CREATED)
.entity(Map.of("sessionId", sessionId))
.build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du lancement de la comparaison", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du lancement de la comparaison: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}")
public Response updateComparaison(
@PathParam("id") UUID id, @Valid UpdateComparaisonRequest request) {
try {
logger.info("PUT /api/comparaisons-fournisseurs/{}", id);
ComparaisonFournisseurService.ComparaisonUpdateRequest updateRequest =
mapToServiceRequest(request);
ComparaisonFournisseur comparaison = comparaisonService.updateComparaison(id, updateRequest);
return Response.ok(comparaison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour de la comparaison: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la mise à jour de la comparaison: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/calculer-scores")
public Response calculerScores(@PathParam("id") UUID id, @Valid CalculerScoresRequest request) {
try {
logger.info("PUT /api/comparaisons-fournisseurs/{}/calculer-scores", id);
ComparaisonFournisseur comparaison = comparaisonService.findByIdRequired(id);
comparaisonService.calculerScores(comparaison, request.poidsCriteres);
return Response.ok(comparaison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du calcul des scores: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du calcul des scores: " + e.getMessage())
.build();
}
}
@PUT
@Path("/session/{sessionId}/classer")
public Response classerComparaisons(@PathParam("sessionId") String sessionId) {
try {
logger.info("PUT /api/comparaisons-fournisseurs/session/{}/classer", sessionId);
comparaisonService.classerComparaisons(sessionId);
List<ComparaisonFournisseur> comparaisons = comparaisonService.findBySession(sessionId);
return Response.ok(
Map.of("message", "Classement effectué avec succès", "comparaisons", comparaisons))
.build();
} catch (Exception e) {
logger.error("Erreur lors du classement des comparaisons: " + sessionId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du classement des comparaisons: " + e.getMessage())
.build();
}
}
// === ENDPOINTS D'ANALYSE ET RAPPORTS ===
@GET
@Path("/statistiques")
public Response getStatistiques() {
try {
logger.debug("GET /api/comparaisons-fournisseurs/statistiques");
Map<String, Object> statistiques = comparaisonService.getStatistiques();
return Response.ok(statistiques).build();
} catch (Exception e) {
logger.error("Erreur lors de la génération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la génération des statistiques: " + e.getMessage())
.build();
}
}
@GET
@Path("/evolution-prix/{materielId}")
public Response analyserEvolutionPrix(
@PathParam("materielId") UUID materielId,
@QueryParam("dateDebut") @NotNull LocalDate dateDebut,
@QueryParam("dateFin") @NotNull LocalDate dateFin) {
try {
logger.debug("GET /api/comparaisons-fournisseurs/evolution-prix/{}", materielId);
List<Object> evolution =
comparaisonService.analyserEvolutionPrix(materielId, dateDebut, dateFin);
return Response.ok(evolution).build();
} catch (Exception e) {
logger.error("Erreur lors de l'analyse d'évolution des prix: " + materielId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'analyse d'évolution des prix: " + e.getMessage())
.build();
}
}
@GET
@Path("/delais-fournisseurs")
public Response analyserDelaisFournisseurs() {
try {
logger.debug("GET /api/comparaisons-fournisseurs/delais-fournisseurs");
List<Object> delais = comparaisonService.analyserDelaisFournisseurs();
return Response.ok(delais).build();
} catch (Exception e) {
logger.error("Erreur lors de l'analyse des délais fournisseurs", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'analyse des délais fournisseurs: " + e.getMessage())
.build();
}
}
@GET
@Path("/rapport/{sessionId}")
public Response genererRapportComparaison(@PathParam("sessionId") String sessionId) {
try {
logger.debug("GET /api/comparaisons-fournisseurs/rapport/{}", sessionId);
Map<String, Object> rapport = comparaisonService.genererRapportComparaison(sessionId);
return Response.ok(rapport).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la génération du rapport: " + sessionId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la génération du rapport: " + e.getMessage())
.build();
}
}
// === ENDPOINTS UTILITAIRES ===
@GET
@Path("/criteres-comparaison")
public Response getCriteresComparaison() {
try {
CritereComparaison[] criteres = CritereComparaison.values();
List<Map<String, Object>> criteresInfo =
Arrays.stream(criteres)
.map(
critere -> {
Map<String, Object> map = new HashMap<>();
map.put("code", critere.name());
map.put("libelle", critere.getLibelle());
map.put("description", critere.getDescription());
map.put("poidsDefaut", critere.getPoidsDefaut());
map.put("uniteMesure", critere.getUniteMesure());
map.put("icone", critere.getIcone());
map.put("couleur", critere.getCouleur());
return map;
})
.collect(Collectors.toList());
return Response.ok(criteresInfo).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des critères", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des critères: " + e.getMessage())
.build();
}
}
// === MÉTHODES UTILITAIRES ===
private ComparaisonFournisseurService.ComparaisonUpdateRequest mapToServiceRequest(
UpdateComparaisonRequest request) {
ComparaisonFournisseurService.ComparaisonUpdateRequest serviceRequest =
new ComparaisonFournisseurService.ComparaisonUpdateRequest();
serviceRequest.disponible = request.disponible;
serviceRequest.quantiteDisponible = request.quantiteDisponible;
serviceRequest.dateDisponibilite = request.dateDisponibilite;
serviceRequest.delaiLivraisonJours = request.delaiLivraisonJours;
serviceRequest.prixUnitaireHT = request.prixUnitaireHT;
serviceRequest.fraisLivraison = request.fraisLivraison;
serviceRequest.fraisInstallation = request.fraisInstallation;
serviceRequest.fraisMaintenance = request.fraisMaintenance;
serviceRequest.cautionDemandee = request.cautionDemandee;
serviceRequest.remiseAppliquee = request.remiseAppliquee;
serviceRequest.dureeValiditeOffre = request.dureeValiditeOffre;
serviceRequest.delaiPaiement = request.delaiPaiement;
serviceRequest.garantieMois = request.garantieMois;
serviceRequest.maintenanceIncluse = request.maintenanceIncluse;
serviceRequest.formationIncluse = request.formationIncluse;
serviceRequest.noteQualite = request.noteQualite;
serviceRequest.noteFiabilite = request.noteFiabilite;
serviceRequest.distanceKm = request.distanceKm;
serviceRequest.conditionsParticulieres = request.conditionsParticulieres;
serviceRequest.avantages = request.avantages;
serviceRequest.inconvenients = request.inconvenients;
serviceRequest.commentairesEvaluateur = request.commentairesEvaluateur;
serviceRequest.recommandations = request.recommandations;
serviceRequest.poidsCriteres = request.poidsCriteres;
return serviceRequest;
}
// === CLASSES DE REQUÊTE ===
public static class LancerComparaisonRequest {
@NotNull public UUID materielId;
@NotNull public BigDecimal quantiteDemandee;
public String uniteDemandee;
public LocalDate dateDebutSouhaitee;
public LocalDate dateFinSouhaitee;
public String lieuLivraison;
public String evaluateur;
}
public static class UpdateComparaisonRequest {
public Boolean disponible;
public BigDecimal quantiteDisponible;
public LocalDate dateDisponibilite;
public Integer delaiLivraisonJours;
public BigDecimal prixUnitaireHT;
public BigDecimal fraisLivraison;
public BigDecimal fraisInstallation;
public BigDecimal fraisMaintenance;
public BigDecimal cautionDemandee;
public BigDecimal remiseAppliquee;
public Integer dureeValiditeOffre;
public Integer delaiPaiement;
public Integer garantieMois;
public Boolean maintenanceIncluse;
public Boolean formationIncluse;
public BigDecimal noteQualite;
public BigDecimal noteFiabilite;
public BigDecimal distanceKm;
public String conditionsParticulieres;
public String avantages;
public String inconvenients;
public String commentairesEvaluateur;
public String recommandations;
public Map<CritereComparaison, Integer> poidsCriteres;
}
public static class CalculerScoresRequest {
public Map<CritereComparaison, Integer> poidsCriteres;
}
}

View File

@@ -0,0 +1,849 @@
package dev.lions.btpxpress.presentation.rest;
import dev.lions.btpxpress.application.service.LivraisonMaterielService;
import dev.lions.btpxpress.domain.core.entity.*;
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.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* API REST pour la gestion des livraisons de matériel EXPOSITION: Endpoints pour la logistique et
* le suivi des livraisons BTP
*/
@Path("/api/v1/livraisons-materiel")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class LivraisonMaterielResource {
private static final Logger logger = LoggerFactory.getLogger(LivraisonMaterielResource.class);
@Inject LivraisonMaterielService livraisonService;
// === ENDPOINTS DE CONSULTATION ===
@GET
@Path("/")
public Response findAll(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("50") int size) {
try {
logger.debug("GET /api/livraisons-materiel/ - page: {}, size: {}", page, size);
List<LivraisonMateriel> livraisons;
if (page > 0 || size < 1000) {
livraisons = livraisonService.findAll(page, size);
} else {
livraisons = livraisonService.findAll();
}
return Response.ok(livraisons).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des livraisons", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des livraisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/{id}")
public Response findById(@PathParam("id") UUID id) {
try {
logger.debug("GET /api/livraisons-materiel/{}", id);
LivraisonMateriel livraison = livraisonService.findByIdRequired(id);
return Response.ok(livraison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération de la livraison: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération de la livraison: " + e.getMessage())
.build();
}
}
@GET
@Path("/numero/{numero}")
public Response findByNumero(@PathParam("numero") String numeroLivraison) {
try {
logger.debug("GET /api/livraisons-materiel/numero/{}", numeroLivraison);
return livraisonService
.findByNumero(numeroLivraison)
.map(livraison -> Response.ok(livraison).build())
.orElse(
Response.status(Response.Status.NOT_FOUND)
.entity("Livraison non trouvée avec le numéro: " + numeroLivraison)
.build());
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération de la livraison par numéro: " + numeroLivraison, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération de la livraison: " + e.getMessage())
.build();
}
}
@GET
@Path("/reservation/{reservationId}")
public Response findByReservation(@PathParam("reservationId") UUID reservationId) {
try {
logger.debug("GET /api/livraisons-materiel/reservation/{}", reservationId);
List<LivraisonMateriel> livraisons = livraisonService.findByReservation(reservationId);
return Response.ok(livraisons).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des livraisons pour réservation: " + reservationId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des livraisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/chantier/{chantierId}")
public Response findByChantier(@PathParam("chantierId") UUID chantierId) {
try {
logger.debug("GET /api/livraisons-materiel/chantier/{}", chantierId);
List<LivraisonMateriel> livraisons = livraisonService.findByChantier(chantierId);
return Response.ok(livraisons).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des livraisons pour chantier: " + chantierId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des livraisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/statut/{statut}")
public Response findByStatut(@PathParam("statut") String statutStr) {
try {
logger.debug("GET /api/livraisons-materiel/statut/{}", statutStr);
StatutLivraison statut = StatutLivraison.fromString(statutStr);
List<LivraisonMateriel> livraisons = livraisonService.findByStatut(statut);
return Response.ok(livraisons).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des livraisons par statut: " + statutStr, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des livraisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/transporteur/{transporteur}")
public Response findByTransporteur(@PathParam("transporteur") String transporteur) {
try {
logger.debug("GET /api/livraisons-materiel/transporteur/{}", transporteur);
List<LivraisonMateriel> livraisons = livraisonService.findByTransporteur(transporteur);
return Response.ok(livraisons).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des livraisons pour transporteur: " + transporteur, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des livraisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/search")
public Response search(@QueryParam("terme") String terme) {
try {
logger.debug("GET /api/livraisons-materiel/search?terme={}", terme);
List<LivraisonMateriel> resultats = livraisonService.search(terme);
return Response.ok(resultats).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche avec terme: " + terme, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la recherche: " + e.getMessage())
.build();
}
}
// === ENDPOINTS MÉTIER SPÉCIALISÉS ===
@GET
@Path("/du-jour")
public Response findLivraisonsDuJour() {
try {
logger.debug("GET /api/livraisons-materiel/du-jour");
List<LivraisonMateriel> livraisons = livraisonService.findLivraisonsDuJour();
return Response.ok(livraisons).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des livraisons du jour", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des livraisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/en-cours")
public Response findLivraisonsEnCours() {
try {
logger.debug("GET /api/livraisons-materiel/en-cours");
List<LivraisonMateriel> livraisons = livraisonService.findLivraisonsEnCours();
return Response.ok(livraisons).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des livraisons en cours", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des livraisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/en-retard")
public Response findLivraisonsEnRetard() {
try {
logger.debug("GET /api/livraisons-materiel/en-retard");
List<LivraisonMateriel> livraisons = livraisonService.findLivraisonsEnRetard();
return Response.ok(livraisons).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des livraisons en retard", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des livraisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/avec-incidents")
public Response findAvecIncidents() {
try {
logger.debug("GET /api/livraisons-materiel/avec-incidents");
List<LivraisonMateriel> livraisons = livraisonService.findAvecIncidents();
return Response.ok(livraisons).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des livraisons avec incidents", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des livraisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/prioritaires")
public Response findLivraisonsPrioritaires() {
try {
logger.debug("GET /api/livraisons-materiel/prioritaires");
List<LivraisonMateriel> livraisons = livraisonService.findLivraisonsPrioritaires();
return Response.ok(livraisons).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des livraisons prioritaires", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des livraisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/tracking-actif")
public Response findAvecTrackingActif() {
try {
logger.debug("GET /api/livraisons-materiel/tracking-actif");
List<LivraisonMateriel> livraisons = livraisonService.findAvecTrackingActif();
return Response.ok(livraisons).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des livraisons avec tracking", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des livraisons: " + e.getMessage())
.build();
}
}
@GET
@Path("/necessitant-action")
public Response findNecessitantAction() {
try {
logger.debug("GET /api/livraisons-materiel/necessitant-action");
List<LivraisonMateriel> livraisons = livraisonService.findNecessitantAction();
return Response.ok(livraisons).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des livraisons nécessitant action", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des livraisons: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE CRÉATION ET MODIFICATION ===
@POST
@Path("/")
public Response creerLivraison(@Valid CreerLivraisonRequest request) {
try {
logger.info("POST /api/livraisons-materiel/ - création livraison");
LivraisonMateriel livraison =
livraisonService.creerLivraison(
request.reservationId,
request.typeTransport,
request.dateLivraisonPrevue,
request.heureLivraisonPrevue,
request.transporteur,
request.planificateur);
return Response.status(Response.Status.CREATED).entity(livraison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la création de la livraison", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la création de la livraison: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}")
public Response updateLivraison(@PathParam("id") UUID id, @Valid UpdateLivraisonRequest request) {
try {
logger.info("PUT /api/livraisons-materiel/{}", id);
LivraisonMaterielService.LivraisonUpdateRequest updateRequest = mapToServiceRequest(request);
LivraisonMateriel livraison = livraisonService.updateLivraison(id, updateRequest);
return Response.ok(livraison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour de la livraison: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la mise à jour de la livraison: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE GESTION DU WORKFLOW ===
@PUT
@Path("/{id}/demarrer-preparation")
public Response demarrerPreparation(@PathParam("id") UUID id, @Valid OperateurRequest request) {
try {
logger.info("PUT /api/livraisons-materiel/{}/demarrer-preparation", id);
LivraisonMateriel livraison = livraisonService.demarrerPreparation(id, request.operateur);
return Response.ok(livraison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du démarrage de la préparation: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du démarrage de la préparation: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/marquer-prete")
public Response marquerPrete(@PathParam("id") UUID id, @Valid MarquerPreteRequest request) {
try {
logger.info("PUT /api/livraisons-materiel/{}/marquer-prete", id);
LivraisonMateriel livraison =
livraisonService.marquerPrete(id, request.operateur, request.observations);
return Response.ok(livraison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du marquage prêt: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du marquage prêt: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/demarrer-transit")
public Response demarrerTransit(@PathParam("id") UUID id, @Valid DemarrerTransitRequest request) {
try {
logger.info("PUT /api/livraisons-materiel/{}/demarrer-transit", id);
LivraisonMateriel livraison =
livraisonService.demarrerTransit(id, request.chauffeur, request.heureDepart);
return Response.ok(livraison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du démarrage du transit: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du démarrage du transit: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/signaler-arrivee")
public Response signalerArrivee(@PathParam("id") UUID id, @Valid SignalerArriveeRequest request) {
try {
logger.info("PUT /api/livraisons-materiel/{}/signaler-arrivee", id);
LivraisonMateriel livraison =
livraisonService.signalerArrivee(
id, request.chauffeur, request.heureArrivee, request.latitude, request.longitude);
return Response.ok(livraison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du signalement d'arrivée: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du signalement d'arrivée: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/commencer-dechargement")
public Response commencerDechargement(@PathParam("id") UUID id, @Valid OperateurRequest request) {
try {
logger.info("PUT /api/livraisons-materiel/{}/commencer-dechargement", id);
LivraisonMateriel livraison = livraisonService.commencerDechargement(id, request.operateur);
return Response.ok(livraison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du début de déchargement: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du début de déchargement: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/finaliser")
public Response finaliserLivraison(@PathParam("id") UUID id, @Valid FinalisationRequest request) {
try {
logger.info("PUT /api/livraisons-materiel/{}/finaliser", id);
LivraisonMaterielService.FinalisationLivraisonRequest finalisationRequest =
mapToFinalisationRequest(request);
LivraisonMateriel livraison = livraisonService.finaliserLivraison(id, finalisationRequest);
return Response.ok(livraison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la finalisation: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la finalisation: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/signaler-incident")
public Response signalerIncident(
@PathParam("id") UUID id, @Valid SignalerIncidentRequest request) {
try {
logger.info("PUT /api/livraisons-materiel/{}/signaler-incident", id);
LivraisonMaterielService.IncidentRequest incidentRequest = mapToIncidentRequest(request);
LivraisonMateriel livraison = livraisonService.signalerIncident(id, incidentRequest);
return Response.ok(livraison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du signalement d'incident: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du signalement d'incident: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/retarder")
public Response retarderLivraison(
@PathParam("id") UUID id, @Valid RetarderLivraisonRequest request) {
try {
logger.info("PUT /api/livraisons-materiel/{}/retarder", id);
LivraisonMateriel livraison =
livraisonService.retarderLivraison(
id,
request.nouvelleDatePrevue,
request.nouvelleHeurePrevue,
request.motif,
request.operateur);
return Response.ok(livraison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du retard de livraison: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du retard de livraison: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/annuler")
public Response annulerLivraison(
@PathParam("id") UUID id, @Valid AnnulerLivraisonRequest request) {
try {
logger.info("PUT /api/livraisons-materiel/{}/annuler", id);
LivraisonMateriel livraison =
livraisonService.annulerLivraison(id, request.motifAnnulation, request.operateur);
return Response.ok(livraison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de l'annulation de livraison: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'annulation de livraison: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE SUIVI ET TRACKING ===
@PUT
@Path("/{id}/position-gps")
public Response mettreAJourPositionGPS(
@PathParam("id") UUID id, @Valid PositionGPSRequest request) {
try {
livraisonService.mettreAJourPositionGPS(
id, request.latitude, request.longitude, request.vitesseKmh);
return Response.ok(Map.of("message", "Position mise à jour")).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour GPS: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la mise à jour GPS: " + e.getMessage())
.build();
}
}
@GET
@Path("/{id}/eta")
public Response calculerETA(@PathParam("id") UUID id) {
try {
logger.debug("GET /api/livraisons-materiel/{}/eta", id);
Map<String, Object> eta = livraisonService.calculerETA(id);
return Response.ok(eta).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du calcul ETA: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du calcul ETA: " + e.getMessage())
.build();
}
}
// === ENDPOINTS D'OPTIMISATION ===
@POST
@Path("/optimiser-itineraires")
public Response optimiserItineraires(@Valid OptimiserItinerairesRequest request) {
try {
logger.info("POST /api/livraisons-materiel/optimiser-itineraires");
List<LivraisonMateriel> itineraireOptimise =
livraisonService.optimiserItineraires(request.date, request.transporteur);
return Response.ok(
Map.of(
"itineraireOptimise",
itineraireOptimise,
"nombreLivraisons",
itineraireOptimise.size()))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'optimisation des itinéraires", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'optimisation des itinéraires: " + e.getMessage())
.build();
}
}
// === ENDPOINTS STATISTIQUES ===
@GET
@Path("/statistiques")
public Response getStatistiques() {
try {
logger.debug("GET /api/livraisons-materiel/statistiques");
Map<String, Object> statistiques = livraisonService.getStatistiques();
return Response.ok(statistiques).build();
} catch (Exception e) {
logger.error("Erreur lors de la génération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la génération des statistiques: " + e.getMessage())
.build();
}
}
@GET
@Path("/tableau-bord")
public Response getTableauBordLogistique() {
try {
logger.debug("GET /api/livraisons-materiel/tableau-bord");
Map<String, Object> tableauBord = livraisonService.getTableauBordLogistique();
return Response.ok(tableauBord).build();
} catch (Exception e) {
logger.error("Erreur lors de la génération du tableau de bord", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la génération du tableau de bord: " + e.getMessage())
.build();
}
}
@GET
@Path("/performance-transporteurs")
public Response analyserPerformanceTransporteurs() {
try {
logger.debug("GET /api/livraisons-materiel/performance-transporteurs");
List<Object> performance = livraisonService.analyserPerformanceTransporteurs();
return Response.ok(performance).build();
} catch (Exception e) {
logger.error("Erreur lors de l'analyse des performances", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'analyse des performances: " + e.getMessage())
.build();
}
}
// === MÉTHODES UTILITAIRES ===
private LivraisonMaterielService.LivraisonUpdateRequest mapToServiceRequest(
UpdateLivraisonRequest request) {
LivraisonMaterielService.LivraisonUpdateRequest serviceRequest =
new LivraisonMaterielService.LivraisonUpdateRequest();
serviceRequest.dateLivraisonPrevue = request.dateLivraisonPrevue;
serviceRequest.heureLivraisonPrevue = request.heureLivraisonPrevue;
serviceRequest.transporteur = request.transporteur;
serviceRequest.chauffeur = request.chauffeur;
serviceRequest.telephoneChauffeur = request.telephoneChauffeur;
serviceRequest.immatriculation = request.immatriculation;
serviceRequest.contactReception = request.contactReception;
serviceRequest.telephoneContact = request.telephoneContact;
serviceRequest.instructionsSpeciales = request.instructionsSpeciales;
serviceRequest.accesChantier = request.accesChantier;
serviceRequest.modifiePar = request.modifiePar;
return serviceRequest;
}
private LivraisonMaterielService.FinalisationLivraisonRequest mapToFinalisationRequest(
FinalisationRequest request) {
LivraisonMaterielService.FinalisationLivraisonRequest finalisationRequest =
new LivraisonMaterielService.FinalisationLivraisonRequest();
finalisationRequest.quantiteLivree = request.quantiteLivree;
finalisationRequest.etatMateriel = request.etatMateriel;
finalisationRequest.observations = request.observations;
finalisationRequest.receptionnaire = request.receptionnaire;
finalisationRequest.conforme = request.conforme;
finalisationRequest.photoLivraison = request.photoLivraison;
return finalisationRequest;
}
private LivraisonMaterielService.IncidentRequest mapToIncidentRequest(
SignalerIncidentRequest request) {
LivraisonMaterielService.IncidentRequest incidentRequest =
new LivraisonMaterielService.IncidentRequest();
incidentRequest.typeIncident = request.typeIncident;
incidentRequest.description = request.description;
incidentRequest.impact = request.impact;
incidentRequest.actionsCorrectives = request.actionsCorrectives;
incidentRequest.declarant = request.declarant;
return incidentRequest;
}
// === CLASSES DE REQUÊTE ===
public static class CreerLivraisonRequest {
@NotNull public UUID reservationId;
@NotNull public TypeTransport typeTransport;
@NotNull public LocalDate dateLivraisonPrevue;
public LocalTime heureLivraisonPrevue;
public String transporteur;
public String planificateur;
}
public static class UpdateLivraisonRequest {
public LocalDate dateLivraisonPrevue;
public LocalTime heureLivraisonPrevue;
public String transporteur;
public String chauffeur;
public String telephoneChauffeur;
public String immatriculation;
public String contactReception;
public String telephoneContact;
public String instructionsSpeciales;
public String accesChantier;
public String modifiePar;
}
public static class OperateurRequest {
@NotNull public String operateur;
}
public static class MarquerPreteRequest {
@NotNull public String operateur;
public String observations;
}
public static class DemarrerTransitRequest {
@NotNull public String chauffeur;
public LocalTime heureDepart;
}
public static class SignalerArriveeRequest {
@NotNull public String chauffeur;
public LocalTime heureArrivee;
public BigDecimal latitude;
public BigDecimal longitude;
}
public static class FinalisationRequest {
@NotNull public BigDecimal quantiteLivree;
public String etatMateriel;
public String observations;
@NotNull public String receptionnaire;
public Boolean conforme;
public String photoLivraison;
}
public static class SignalerIncidentRequest {
@NotNull public String typeIncident;
@NotNull public String description;
public String impact;
public String actionsCorrectives;
@NotNull public String declarant;
}
public static class RetarderLivraisonRequest {
@NotNull public LocalDate nouvelleDatePrevue;
public LocalTime nouvelleHeurePrevue;
@NotNull public String motif;
@NotNull public String operateur;
}
public static class AnnulerLivraisonRequest {
@NotNull public String motifAnnulation;
@NotNull public String operateur;
}
public static class PositionGPSRequest {
@NotNull public BigDecimal latitude;
@NotNull public BigDecimal longitude;
public Integer vitesseKmh;
}
public static class OptimiserItinerairesRequest {
@NotNull public LocalDate date;
public String transporteur;
}
}

View File

@@ -0,0 +1,309 @@
package dev.lions.btpxpress.presentation.rest;
import dev.lions.btpxpress.application.service.MaterielFournisseurService;
import dev.lions.btpxpress.domain.core.entity.*;
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.math.BigDecimal;
import java.util.List;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* API REST pour la gestion intégrée matériel-fournisseur EXPOSITION: Endpoints pour l'orchestration
* matériel-fournisseur-catalogue
*/
@Path("/api/v1/materiel-fournisseur")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class MaterielFournisseurResource {
private static final Logger logger = LoggerFactory.getLogger(MaterielFournisseurResource.class);
@Inject MaterielFournisseurService materielFournisseurService;
// === ENDPOINTS DE CONSULTATION INTÉGRÉE ===
@GET
@Path("/materiels-avec-fournisseurs")
public Response findMaterielsAvecFournisseurs() {
try {
logger.debug("GET /api/materiel-fournisseur/materiels-avec-fournisseurs");
List<Object> materiels = materielFournisseurService.findMaterielsAvecFournisseurs();
return Response.ok(materiels).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des matériels avec fournisseurs", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des matériels: " + e.getMessage())
.build();
}
}
@GET
@Path("/materiel/{materielId}/avec-offres")
public Response findMaterielAvecOffres(@PathParam("materielId") UUID materielId) {
try {
logger.debug("GET /api/materiel-fournisseur/materiel/{}/avec-offres", materielId);
Object materielAvecOffres = materielFournisseurService.findMaterielAvecOffres(materielId);
return Response.ok(materielAvecOffres).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du matériel avec offres: " + materielId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération du matériel: " + e.getMessage())
.build();
}
}
@GET
@Path("/fournisseurs-avec-materiels")
public Response findFournisseursAvecMateriels() {
try {
logger.debug("GET /api/materiel-fournisseur/fournisseurs-avec-materiels");
List<Object> fournisseurs = materielFournisseurService.findFournisseursAvecMateriels();
return Response.ok(fournisseurs).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des fournisseurs avec matériels", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des fournisseurs: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE CRÉATION INTÉGRÉE ===
@POST
@Path("/materiel-avec-fournisseur")
public Response createMaterielAvecFournisseur(
@Valid CreateMaterielAvecFournisseurRequest request) {
try {
logger.info("POST /api/materiel-fournisseur/materiel-avec-fournisseur");
Materiel materiel =
materielFournisseurService.createMaterielAvecFournisseur(
request.nom,
request.marque,
request.modele,
request.numeroSerie,
request.type,
request.description,
request.propriete,
request.fournisseurId,
request.valeurAchat,
request.localisation);
return Response.status(Response.Status.CREATED).entity(materiel).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la création du matériel avec fournisseur", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la création du matériel: " + e.getMessage())
.build();
}
}
@POST
@Path("/ajouter-au-catalogue")
public Response ajouterMaterielAuCatalogue(@Valid AjouterMaterielCatalogueRequest request) {
try {
logger.info("POST /api/materiel-fournisseur/ajouter-au-catalogue");
CatalogueFournisseur entree =
materielFournisseurService.ajouterMaterielAuCatalogue(
request.materielId,
request.fournisseurId,
request.referenceFournisseur,
request.prixUnitaire,
request.unitePrix,
request.delaiLivraisonJours);
return Response.status(Response.Status.CREATED).entity(entree).build();
} catch (BadRequestException | NotFoundException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de l'ajout du matériel au catalogue", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'ajout au catalogue: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE RECHERCHE AVANCÉE ===
@GET
@Path("/search")
public Response searchMaterielsAvecFournisseurs(
@QueryParam("terme") String terme,
@QueryParam("propriete") String proprieteStr,
@QueryParam("prixMax") BigDecimal prixMax,
@QueryParam("delaiMax") Integer delaiMax) {
try {
logger.debug(
"GET /api/materiel-fournisseur/search?terme={}&propriete={}&prixMax={}&delaiMax={}",
terme,
proprieteStr,
prixMax,
delaiMax);
ProprieteMateriel propriete = null;
if (proprieteStr != null && !proprieteStr.trim().isEmpty()) {
try {
propriete = ProprieteMateriel.valueOf(proprieteStr.toUpperCase());
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Propriété matériel invalide: " + proprieteStr)
.build();
}
}
List<Object> resultats =
materielFournisseurService.searchMaterielsAvecFournisseurs(
terme, propriete, prixMax, delaiMax);
return Response.ok(resultats).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche avancée", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la recherche: " + e.getMessage())
.build();
}
}
@GET
@Path("/comparer-prix/{materielId}")
public Response comparerPrixFournisseurs(@PathParam("materielId") UUID materielId) {
try {
logger.debug("GET /api/materiel-fournisseur/comparer-prix/{}", materielId);
Object comparaison = materielFournisseurService.comparerPrixFournisseurs(materielId);
return Response.ok(comparaison).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la comparaison des prix pour: " + materielId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la comparaison des prix: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE GESTION ===
@PUT
@Path("/materiel/{materielId}/changer-fournisseur")
public Response changerFournisseurMateriel(
@PathParam("materielId") UUID materielId, @Valid ChangerFournisseurRequest request) {
try {
logger.info("PUT /api/materiel-fournisseur/materiel/{}/changer-fournisseur", materielId);
Materiel materiel =
materielFournisseurService.changerFournisseurMateriel(
materielId, request.nouveauFournisseurId, request.nouvellePropriete);
return Response.ok(materiel).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du changement de fournisseur: " + materielId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du changement de fournisseur: " + e.getMessage())
.build();
}
}
// === ENDPOINTS STATISTIQUES ===
@GET
@Path("/statistiques-propriete")
public Response getStatistiquesMaterielsParPropriete() {
try {
logger.debug("GET /api/materiel-fournisseur/statistiques-propriete");
Object statistiques = materielFournisseurService.getStatistiquesMaterielsParPropriete();
return Response.ok(statistiques).build();
} catch (Exception e) {
logger.error("Erreur lors de la génération des statistiques par propriété", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la génération des statistiques: " + e.getMessage())
.build();
}
}
@GET
@Path("/tableau-bord")
public Response getTableauBordMaterielFournisseur() {
try {
logger.debug("GET /api/materiel-fournisseur/tableau-bord");
Object tableauBord = materielFournisseurService.getTableauBordMaterielFournisseur();
return Response.ok(tableauBord).build();
} catch (Exception e) {
logger.error("Erreur lors de la génération du tableau de bord", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la génération du tableau de bord: " + e.getMessage())
.build();
}
}
// === CLASSES DE REQUÊTE ===
public static class CreateMaterielAvecFournisseurRequest {
@NotNull public String nom;
public String marque;
public String modele;
public String numeroSerie;
@NotNull public TypeMateriel type;
public String description;
@NotNull public ProprieteMateriel propriete;
public UUID fournisseurId;
public BigDecimal valeurAchat;
public String localisation;
}
public static class AjouterMaterielCatalogueRequest {
@NotNull public UUID materielId;
@NotNull public UUID fournisseurId;
@NotNull public String referenceFournisseur;
@NotNull public BigDecimal prixUnitaire;
@NotNull public UnitePrix unitePrix;
public Integer delaiLivraisonJours;
}
public static class ChangerFournisseurRequest {
public UUID nouveauFournisseurId;
@NotNull public ProprieteMateriel nouvellePropriete;
}
}

View File

@@ -0,0 +1,354 @@
package dev.lions.btpxpress.presentation.rest;
import dev.lions.btpxpress.application.service.PermissionService;
import dev.lions.btpxpress.domain.core.entity.Permission;
import dev.lions.btpxpress.domain.core.entity.Permission.PermissionCategory;
import dev.lions.btpxpress.domain.core.entity.UserRole;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* API REST pour la gestion des permissions EXPOSITION: Consultation des droits d'accès et
* permissions par rôle
*/
@Path("/api/permissions")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class PermissionResource {
private static final Logger logger = LoggerFactory.getLogger(PermissionResource.class);
@Inject PermissionService permissionService;
// === ENDPOINTS DE CONSULTATION ===
/** Récupère toutes les permissions disponibles */
@GET
@Path("/all")
public Response getAllPermissions() {
try {
logger.debug("GET /api/permissions/all");
List<Object> permissions =
Arrays.stream(Permission.values())
.map(
p ->
Map.of(
"code", p.getCode(),
"description", p.getDescription(),
"category", p.getCategory().name(),
"categoryDisplay", p.getCategory().getDisplayName()))
.collect(Collectors.toList());
return Response.ok(permissions).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des permissions", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des permissions: " + e.getMessage())
.build();
}
}
/** Récupère les permissions par catégorie */
@GET
@Path("/categories")
public Response getPermissionsByCategory() {
try {
logger.debug("GET /api/permissions/categories");
Map<String, Object> result =
Arrays.stream(PermissionCategory.values())
.collect(
Collectors.toMap(
category -> category.name(),
category ->
Map.of(
"displayName", category.getDisplayName(),
"permissions",
Permission.getByCategory(category).stream()
.map(
p ->
Map.of(
"code", p.getCode(),
"description", p.getDescription()))
.collect(Collectors.toList()))));
return Response.ok(result).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des permissions par catégorie", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des permissions: " + e.getMessage())
.build();
}
}
/** Récupère les permissions d'un rôle spécifique */
@GET
@Path("/role/{role}")
public Response getPermissionsByRole(@PathParam("role") String roleStr) {
try {
logger.debug("GET /api/permissions/role/{}", roleStr);
UserRole role = UserRole.valueOf(roleStr.toUpperCase());
Map<String, Object> summary = permissionService.getPermissionSummary(role);
return Response.ok(summary).build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Rôle invalide: " + roleStr)
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des permissions pour le rôle: " + roleStr, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des permissions: " + e.getMessage())
.build();
}
}
/** Vérifie si un rôle a une permission spécifique */
@GET
@Path("/check/{role}/{permission}")
public Response checkPermission(
@PathParam("role") String roleStr, @PathParam("permission") String permissionCode) {
try {
logger.debug("GET /api/permissions/check/{}/{}", roleStr, permissionCode);
UserRole role = UserRole.valueOf(roleStr.toUpperCase());
boolean hasPermission = permissionService.hasPermission(role, permissionCode);
return Response.ok(
Map.of(
"role", role.getDisplayName(),
"permission", permissionCode,
"hasPermission", hasPermission))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Rôle invalide: " + roleStr)
.build();
} catch (Exception e) {
logger.error("Erreur lors de la vérification de permission", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la vérification de permission: " + e.getMessage())
.build();
}
}
/** Récupère tous les rôles avec leurs permissions */
@GET
@Path("/roles")
public Response getAllRolesWithPermissions() {
try {
logger.debug("GET /api/permissions/roles");
Map<String, Object> result =
Arrays.stream(UserRole.values())
.collect(
Collectors.toMap(
role -> role.name(),
role ->
Map.of(
"displayName", role.getDisplayName(),
"description", role.getDescription(),
"hierarchyLevel", role.getHierarchyLevel(),
"isManagementRole", role.isManagementRole(),
"isFieldRole", role.isFieldRole(),
"isAdministrativeRole", role.isAdministrativeRole(),
"permissions",
permissionService.getPermissions(role).stream()
.map(Permission::getCode)
.collect(Collectors.toList()),
"permissionCount", permissionService.getPermissions(role).size())));
return Response.ok(result).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des rôles et permissions", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des rôles: " + e.getMessage())
.build();
}
}
/** Compare les permissions entre deux rôles */
@GET
@Path("/compare/{role1}/{role2}")
public Response compareRoles(
@PathParam("role1") String role1Str, @PathParam("role2") String role2Str) {
try {
logger.debug("GET /api/permissions/compare/{}/{}", role1Str, role2Str);
UserRole role1 = UserRole.valueOf(role1Str.toUpperCase());
UserRole role2 = UserRole.valueOf(role2Str.toUpperCase());
Set<Permission> permissions1 = permissionService.getPermissions(role1);
Set<Permission> permissions2 = permissionService.getPermissions(role2);
Set<Permission> missing1to2 = permissionService.getMissingPermissions(role1, role2);
Set<Permission> missing2to1 = permissionService.getMissingPermissions(role2, role1);
Set<Permission> common =
permissions1.stream().filter(permissions2::contains).collect(Collectors.toSet());
return Response.ok(
Map.of(
"role1",
Map.of(
"name", role1.getDisplayName(),
"permissionCount", permissions1.size(),
"permissions",
permissions1.stream()
.map(Permission::getCode)
.collect(Collectors.toList())),
"role2",
Map.of(
"name", role2.getDisplayName(),
"permissionCount", permissions2.size(),
"permissions",
permissions2.stream()
.map(Permission::getCode)
.collect(Collectors.toList())),
"common",
Map.of(
"count", common.size(),
"permissions",
common.stream()
.map(Permission::getCode)
.collect(Collectors.toList())),
"onlyInRole1",
Map.of(
"count", missing2to1.size(),
"permissions",
missing2to1.stream()
.map(Permission::getCode)
.collect(Collectors.toList())),
"onlyInRole2",
Map.of(
"count", missing1to2.size(),
"permissions",
missing1to2.stream()
.map(Permission::getCode)
.collect(Collectors.toList()))))
.build();
} catch (IllegalArgumentException e) {
return Response.status(Response.Status.BAD_REQUEST).entity("Rôle invalide").build();
} catch (Exception e) {
logger.error("Erreur lors de la comparaison des rôles", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la comparaison: " + e.getMessage())
.build();
}
}
/** Récupère les permissions spécifiques au gestionnaire de projet */
@GET
@Path("/gestionnaire")
public Response getGestionnairePermissions() {
try {
logger.debug("GET /api/permissions/gestionnaire");
UserRole gestionnaireRole = UserRole.GESTIONNAIRE_PROJET;
Map<String, Object> summary = permissionService.getPermissionSummary(gestionnaireRole);
// Ajout d'informations spécifiques au gestionnaire
Map<PermissionCategory, List<Permission>> byCategory =
permissionService.getPermissionsByCategory(gestionnaireRole);
return Response.ok(
Map.of(
"role", gestionnaireRole.getDisplayName(),
"description", gestionnaireRole.getDescription(),
"summary", summary,
"specificities",
Map.of(
"clientManagement", "Gestion limitée aux clients assignés",
"projectScope", "Chantiers et projets sous sa responsabilité uniquement",
"budgetAccess", "Consultation et planification budgétaire",
"materialReservation", "Réservation de matériel pour ses chantiers",
"reportingLevel", "Rapports et statistiques de ses projets"),
"categoriesDetails",
byCategory.entrySet().stream()
.collect(
Collectors.toMap(
entry -> entry.getKey().getDisplayName(),
entry ->
entry.getValue().stream()
.map(
p ->
Map.of(
"code", p.getCode(),
"description", p.getDescription()))
.collect(Collectors.toList())))))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des permissions gestionnaire", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des permissions: " + e.getMessage())
.build();
}
}
/** Valide les permissions requises pour une fonctionnalité */
@POST
@Path("/validate")
public Response validatePermissions(ValidationRequest request) {
try {
logger.debug("POST /api/permissions/validate");
UserRole role = UserRole.valueOf(request.role.toUpperCase());
Set<Permission> requiredPermissions =
request.requiredPermissions.stream()
.map(Permission::fromCode)
.collect(Collectors.toSet());
boolean hasMinimum = permissionService.hasMinimumPermissions(role, requiredPermissions);
Map<String, Boolean> permissionChecks =
request.requiredPermissions.stream()
.collect(
Collectors.toMap(
code -> code, code -> permissionService.hasPermission(role, code)));
return Response.ok(
Map.of(
"role",
role.getDisplayName(),
"hasMinimumPermissions",
hasMinimum,
"permissionChecks",
permissionChecks,
"missingPermissions",
request.requiredPermissions.stream()
.filter(code -> !permissionService.hasPermission(role, code))
.collect(Collectors.toList())))
.build();
} catch (Exception e) {
logger.error("Erreur lors de la validation des permissions", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la validation: " + e.getMessage())
.build();
}
}
// === CLASSES DE REQUÊTE ===
public static class ValidationRequest {
public String role;
public List<String> requiredPermissions;
}
}

View File

@@ -0,0 +1,626 @@
package dev.lions.btpxpress.presentation.rest;
import dev.lions.btpxpress.application.service.PlanningMaterielService;
import dev.lions.btpxpress.domain.core.entity.*;
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.util.List;
import java.util.Map;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* API REST pour la gestion des plannings matériel EXPOSITION: Endpoints pour planification et
* visualisation graphique
*/
@Path("/api/v1/plannings-materiel")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class PlanningMaterielResource {
private static final Logger logger = LoggerFactory.getLogger(PlanningMaterielResource.class);
@Inject PlanningMaterielService planningService;
// === ENDPOINTS DE CONSULTATION ===
@GET
@Path("/")
public Response findAll(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("50") int size) {
try {
logger.debug("GET /api/plannings-materiel/ - page: {}, size: {}", page, size);
List<PlanningMateriel> plannings;
if (page > 0 || size < 1000) {
plannings = planningService.findAll(page, size);
} else {
plannings = planningService.findAll();
}
return Response.ok(plannings).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des plannings", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des plannings: " + e.getMessage())
.build();
}
}
@GET
@Path("/{id}")
public Response findById(@PathParam("id") UUID id) {
try {
logger.debug("GET /api/plannings-materiel/{}", id);
PlanningMateriel planning = planningService.findByIdRequired(id);
return Response.ok(planning).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération du planning: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération du planning: " + e.getMessage())
.build();
}
}
@GET
@Path("/materiel/{materielId}")
public Response findByMateriel(@PathParam("materielId") UUID materielId) {
try {
logger.debug("GET /api/plannings-materiel/materiel/{}", materielId);
List<PlanningMateriel> plannings = planningService.findByMateriel(materielId);
return Response.ok(plannings).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des plannings pour matériel: " + materielId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des plannings: " + e.getMessage())
.build();
}
}
@GET
@Path("/periode")
public Response findByPeriode(
@QueryParam("dateDebut") LocalDate dateDebut, @QueryParam("dateFin") LocalDate dateFin) {
try {
logger.debug(
"GET /api/plannings-materiel/periode?dateDebut={}&dateFin={}", dateDebut, dateFin);
if (dateDebut == null || dateFin == null) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Les paramètres dateDebut et dateFin sont obligatoires")
.build();
}
List<PlanningMateriel> plannings = planningService.findByPeriode(dateDebut, dateFin);
return Response.ok(plannings).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des plannings par période", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des plannings: " + e.getMessage())
.build();
}
}
@GET
@Path("/statut/{statut}")
public Response findByStatut(@PathParam("statut") String statutStr) {
try {
logger.debug("GET /api/plannings-materiel/statut/{}", statutStr);
StatutPlanning statut = StatutPlanning.fromString(statutStr);
List<PlanningMateriel> plannings = planningService.findByStatut(statut);
return Response.ok(plannings).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des plannings par statut: " + statutStr, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des plannings: " + e.getMessage())
.build();
}
}
@GET
@Path("/type/{type}")
public Response findByType(@PathParam("type") String typeStr) {
try {
logger.debug("GET /api/plannings-materiel/type/{}", typeStr);
TypePlanning type = TypePlanning.fromString(typeStr);
List<PlanningMateriel> plannings = planningService.findByType(type);
return Response.ok(plannings).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des plannings par type: " + typeStr, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des plannings: " + e.getMessage())
.build();
}
}
@GET
@Path("/search")
public Response search(@QueryParam("terme") String terme) {
try {
logger.debug("GET /api/plannings-materiel/search?terme={}", terme);
List<PlanningMateriel> resultats = planningService.search(terme);
return Response.ok(resultats).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche avec terme: " + terme, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la recherche: " + e.getMessage())
.build();
}
}
// === ENDPOINTS MÉTIER SPÉCIALISÉS ===
@GET
@Path("/avec-conflits")
public Response findAvecConflits() {
try {
logger.debug("GET /api/plannings-materiel/avec-conflits");
List<PlanningMateriel> plannings = planningService.findAvecConflits();
return Response.ok(plannings).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des plannings avec conflits", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des plannings: " + e.getMessage())
.build();
}
}
@GET
@Path("/necessitant-attention")
public Response findNecessitantAttention() {
try {
logger.debug("GET /api/plannings-materiel/necessitant-attention");
List<PlanningMateriel> plannings = planningService.findNecessitantAttention();
return Response.ok(plannings).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des plannings nécessitant attention", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des plannings: " + e.getMessage())
.build();
}
}
@GET
@Path("/en-retard-validation")
public Response findEnRetardValidation() {
try {
logger.debug("GET /api/plannings-materiel/en-retard-validation");
List<PlanningMateriel> plannings = planningService.findEnRetardValidation();
return Response.ok(plannings).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des plannings en retard", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des plannings: " + e.getMessage())
.build();
}
}
@GET
@Path("/prioritaires")
public Response findPrioritaires() {
try {
logger.debug("GET /api/plannings-materiel/prioritaires");
List<PlanningMateriel> plannings = planningService.findPrioritaires();
return Response.ok(plannings).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des plannings prioritaires", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des plannings: " + e.getMessage())
.build();
}
}
@GET
@Path("/en-cours")
public Response findEnCours() {
try {
logger.debug("GET /api/plannings-materiel/en-cours");
List<PlanningMateriel> plannings = planningService.findEnCours();
return Response.ok(plannings).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des plannings en cours", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des plannings: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE CRÉATION ET MODIFICATION ===
@POST
@Path("/")
public Response createPlanning(@Valid CreatePlanningRequest request) {
try {
logger.info("POST /api/plannings-materiel/ - création planning");
PlanningMateriel planning =
planningService.createPlanning(
request.materielId,
request.nomPlanning,
request.descriptionPlanning,
request.dateDebut,
request.dateFin,
request.typePlanning,
request.planificateur);
return Response.status(Response.Status.CREATED).entity(planning).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la création du planning", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la création du planning: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}")
public Response updatePlanning(@PathParam("id") UUID id, @Valid UpdatePlanningRequest request) {
try {
logger.info("PUT /api/plannings-materiel/{}", id);
PlanningMateriel planning =
planningService.updatePlanning(
id,
request.nomPlanning,
request.descriptionPlanning,
request.dateDebut,
request.dateFin,
request.modifiePar);
return Response.ok(planning).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour du planning: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la mise à jour du planning: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE GESTION DU WORKFLOW ===
@PUT
@Path("/{id}/valider")
public Response validerPlanning(@PathParam("id") UUID id, @Valid ValiderPlanningRequest request) {
try {
logger.info("PUT /api/plannings-materiel/{}/valider", id);
PlanningMateriel planning =
planningService.validerPlanning(id, request.valideur, request.commentaires);
return Response.ok(planning).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la validation du planning: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la validation du planning: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/mettre-en-revision")
public Response mettreEnRevision(
@PathParam("id") UUID id, @Valid RevisionPlanningRequest request) {
try {
logger.info("PUT /api/plannings-materiel/{}/mettre-en-revision", id);
PlanningMateriel planning = planningService.mettreEnRevision(id, request.motif);
return Response.ok(planning).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la mise en révision du planning: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la mise en révision du planning: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/archiver")
public Response archiverPlanning(@PathParam("id") UUID id) {
try {
logger.info("PUT /api/plannings-materiel/{}/archiver", id);
PlanningMateriel planning = planningService.archiverPlanning(id);
return Response.ok(planning).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de l'archivage du planning: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'archivage du planning: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/suspendre")
public Response suspendrePlanning(@PathParam("id") UUID id) {
try {
logger.info("PUT /api/plannings-materiel/{}/suspendre", id);
PlanningMateriel planning = planningService.suspendrePlanning(id);
return Response.ok(planning).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la suspension du planning: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la suspension du planning: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/reactiver")
public Response reactiverPlanning(@PathParam("id") UUID id) {
try {
logger.info("PUT /api/plannings-materiel/{}/reactiver", id);
PlanningMateriel planning = planningService.reactiverPlanning(id);
return Response.ok(planning).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la réactivation du planning: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la réactivation du planning: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE VÉRIFICATION ET ANALYSE ===
@GET
@Path("/check-conflits")
public Response checkConflits(
@QueryParam("materielId") @NotNull UUID materielId,
@QueryParam("dateDebut") @NotNull LocalDate dateDebut,
@QueryParam("dateFin") @NotNull LocalDate dateFin,
@QueryParam("excludeId") UUID excludeId) {
try {
logger.debug("GET /api/plannings-materiel/check-conflits");
List<PlanningMateriel> conflitsList =
planningService.checkConflits(materielId, dateDebut, dateFin, excludeId);
return Response.ok(
new Object() {
public boolean disponible = conflitsList.isEmpty();
public int nombreConflits = conflitsList.size();
public List<PlanningMateriel> conflits = conflitsList;
})
.build();
} catch (Exception e) {
logger.error("Erreur lors de la vérification des conflits", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la vérification des conflits: " + e.getMessage())
.build();
}
}
@GET
@Path("/disponibilite/{materielId}")
public Response analyserDisponibilite(
@PathParam("materielId") UUID materielId,
@QueryParam("dateDebut") @NotNull LocalDate dateDebut,
@QueryParam("dateFin") @NotNull LocalDate dateFin) {
try {
logger.debug("GET /api/plannings-materiel/disponibilite/{}", materielId);
Map<String, Object> disponibilite =
planningService.analyserDisponibilite(materielId, dateDebut, dateFin);
return Response.ok(disponibilite).build();
} catch (Exception e) {
logger.error("Erreur lors de l'analyse de disponibilité: " + materielId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'analyse de disponibilité: " + e.getMessage())
.build();
}
}
// === ENDPOINTS D'OPTIMISATION ===
@POST
@Path("/optimiser")
public Response optimiserPlannings() {
try {
logger.info("POST /api/plannings-materiel/optimiser");
List<PlanningMateriel> optimises = planningService.optimiserPlannings();
return Response.ok(Map.of("nombreOptimises", optimises.size(), "plannings", optimises))
.build();
} catch (Exception e) {
logger.error("Erreur lors de l'optimisation des plannings", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'optimisation: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/optimiser")
public Response optimiserPlanning(@PathParam("id") UUID id) {
try {
logger.info("PUT /api/plannings-materiel/{}/optimiser", id);
PlanningMateriel planning = planningService.findByIdRequired(id);
planningService.optimiserPlanning(planning);
return Response.ok(planning).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de l'optimisation du planning: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'optimisation du planning: " + e.getMessage())
.build();
}
}
// === ENDPOINTS STATISTIQUES ===
@GET
@Path("/statistiques")
public Response getStatistiques() {
try {
logger.debug("GET /api/plannings-materiel/statistiques");
Map<String, Object> statistiques = planningService.getStatistiques();
return Response.ok(statistiques).build();
} catch (Exception e) {
logger.error("Erreur lors de la génération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la génération des statistiques: " + e.getMessage())
.build();
}
}
@GET
@Path("/tableau-bord")
public Response getTableauBord() {
try {
logger.debug("GET /api/plannings-materiel/tableau-bord");
Map<String, Object> tableauBord = planningService.getTableauBordPlannings();
return Response.ok(tableauBord).build();
} catch (Exception e) {
logger.error("Erreur lors de la génération du tableau de bord", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la génération du tableau de bord: " + e.getMessage())
.build();
}
}
@GET
@Path("/taux-utilisation")
public Response analyserTauxUtilisation(
@QueryParam("dateDebut") @NotNull LocalDate dateDebut,
@QueryParam("dateFin") @NotNull LocalDate dateFin) {
try {
logger.debug("GET /api/plannings-materiel/taux-utilisation");
List<Object> analyse = planningService.analyserTauxUtilisation(dateDebut, dateFin);
return Response.ok(analyse).build();
} catch (Exception e) {
logger.error("Erreur lors de l'analyse des taux d'utilisation", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'analyse: " + e.getMessage())
.build();
}
}
// === MAINTENANCE AUTOMATIQUE ===
@POST
@Path("/verifier-conflits")
public Response verifierTousConflits() {
try {
logger.info("POST /api/plannings-materiel/verifier-conflits");
planningService.verifierTousConflits();
return Response.ok(Map.of("message", "Vérification des conflits terminée")).build();
} catch (Exception e) {
logger.error("Erreur lors de la vérification des conflits", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la vérification des conflits: " + e.getMessage())
.build();
}
}
// === CLASSES DE REQUÊTE ===
public static class CreatePlanningRequest {
@NotNull public UUID materielId;
@NotNull public String nomPlanning;
public String descriptionPlanning;
@NotNull public LocalDate dateDebut;
@NotNull public LocalDate dateFin;
@NotNull public TypePlanning typePlanning;
public String planificateur;
}
public static class UpdatePlanningRequest {
public String nomPlanning;
public String descriptionPlanning;
public LocalDate dateDebut;
public LocalDate dateFin;
public String modifiePar;
}
public static class ValiderPlanningRequest {
@NotNull public String valideur;
public String commentaires;
}
public static class RevisionPlanningRequest {
@NotNull public String motif;
}
}

View File

@@ -0,0 +1,574 @@
package dev.lions.btpxpress.presentation.rest;
import dev.lions.btpxpress.application.service.ReservationMaterielService;
import dev.lions.btpxpress.domain.core.entity.*;
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.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* API REST pour la gestion des réservations matériel EXPOSITION: Endpoints pour l'affectation et
* planification matériel/chantier
*/
@Path("/api/v1/reservations-materiel")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ReservationMaterielResource {
private static final Logger logger = LoggerFactory.getLogger(ReservationMaterielResource.class);
@Inject ReservationMaterielService reservationService;
// === ENDPOINTS DE CONSULTATION ===
@GET
@Path("/")
public Response findAll(
@QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("50") int size) {
try {
logger.debug("GET /api/reservations-materiel/ - page: {}, size: {}", page, size);
List<ReservationMateriel> reservations;
if (page > 0 || size < 1000) {
reservations = reservationService.findAll(page, size);
} else {
reservations = reservationService.findAll();
}
return Response.ok(reservations).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des réservations", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des réservations: " + e.getMessage())
.build();
}
}
@GET
@Path("/{id}")
public Response findById(@PathParam("id") UUID id) {
try {
logger.debug("GET /api/reservations-materiel/{}", id);
ReservationMateriel reservation = reservationService.findByIdRequired(id);
return Response.ok(reservation).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération de la réservation: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération de la réservation: " + e.getMessage())
.build();
}
}
@GET
@Path("/reference/{reference}")
public Response findByReference(@PathParam("reference") String reference) {
try {
logger.debug("GET /api/reservations-materiel/reference/{}", reference);
return reservationService
.findByReference(reference)
.map(reservation -> Response.ok(reservation).build())
.orElse(
Response.status(Response.Status.NOT_FOUND)
.entity("Réservation non trouvée avec la référence: " + reference)
.build());
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération de la réservation par référence: " + reference, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération de la réservation: " + e.getMessage())
.build();
}
}
@GET
@Path("/materiel/{materielId}")
public Response findByMateriel(@PathParam("materielId") UUID materielId) {
try {
logger.debug("GET /api/reservations-materiel/materiel/{}", materielId);
List<ReservationMateriel> reservations = reservationService.findByMateriel(materielId);
return Response.ok(reservations).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des réservations pour matériel: " + materielId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des réservations: " + e.getMessage())
.build();
}
}
@GET
@Path("/chantier/{chantierId}")
public Response findByChantier(@PathParam("chantierId") UUID chantierId) {
try {
logger.debug("GET /api/reservations-materiel/chantier/{}", chantierId);
List<ReservationMateriel> reservations = reservationService.findByChantier(chantierId);
return Response.ok(reservations).build();
} catch (Exception e) {
logger.error(
"Erreur lors de la récupération des réservations pour chantier: " + chantierId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des réservations: " + e.getMessage())
.build();
}
}
@GET
@Path("/statut/{statut}")
public Response findByStatut(@PathParam("statut") String statutStr) {
try {
logger.debug("GET /api/reservations-materiel/statut/{}", statutStr);
StatutReservationMateriel statut = StatutReservationMateriel.fromString(statutStr);
List<ReservationMateriel> reservations = reservationService.findByStatut(statut);
return Response.ok(reservations).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des réservations par statut: " + statutStr, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des réservations: " + e.getMessage())
.build();
}
}
@GET
@Path("/periode")
public Response findByPeriode(
@QueryParam("dateDebut") LocalDate dateDebut, @QueryParam("dateFin") LocalDate dateFin) {
try {
logger.debug(
"GET /api/reservations-materiel/periode?dateDebut={}&dateFin={}", dateDebut, dateFin);
if (dateDebut == null || dateFin == null) {
return Response.status(Response.Status.BAD_REQUEST)
.entity("Les paramètres dateDebut et dateFin sont obligatoires")
.build();
}
List<ReservationMateriel> reservations = reservationService.findByPeriode(dateDebut, dateFin);
return Response.ok(reservations).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des réservations par période", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des réservations: " + e.getMessage())
.build();
}
}
// === ENDPOINTS MÉTIER SPÉCIALISÉS ===
@GET
@Path("/en-attente-validation")
public Response findEnAttenteValidation() {
try {
logger.debug("GET /api/reservations-materiel/en-attente-validation");
List<ReservationMateriel> reservations = reservationService.findEnAttenteValidation();
return Response.ok(reservations).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des réservations en attente", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des réservations: " + e.getMessage())
.build();
}
}
@GET
@Path("/en-retard")
public Response findEnRetard() {
try {
logger.debug("GET /api/reservations-materiel/en-retard");
List<ReservationMateriel> reservations = reservationService.findEnRetard();
return Response.ok(reservations).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des réservations en retard", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des réservations: " + e.getMessage())
.build();
}
}
@GET
@Path("/prioritaires")
public Response findPrioritaires() {
try {
logger.debug("GET /api/reservations-materiel/prioritaires");
List<ReservationMateriel> reservations = reservationService.findPrioritaires();
return Response.ok(reservations).build();
} catch (Exception e) {
logger.error("Erreur lors de la récupération des réservations prioritaires", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération des réservations: " + e.getMessage())
.build();
}
}
@GET
@Path("/search")
public Response search(@QueryParam("terme") String terme) {
try {
logger.debug("GET /api/reservations-materiel/search?terme={}", terme);
List<ReservationMateriel> resultats = reservationService.search(terme);
return Response.ok(resultats).build();
} catch (Exception e) {
logger.error("Erreur lors de la recherche avec terme: " + terme, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la recherche: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE CRÉATION ET MODIFICATION ===
@POST
@Path("/")
public Response createReservation(@Valid CreateReservationRequest request) {
try {
logger.info("POST /api/reservations-materiel/ - création réservation");
ReservationMateriel reservation =
reservationService.createReservation(
request.materielId,
request.chantierId,
request.phaseId,
request.dateDebut,
request.dateFin,
request.quantite,
request.unite,
request.demandeur,
request.lieuLivraison);
return Response.status(Response.Status.CREATED).entity(reservation).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la création de la réservation", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la création de la réservation: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}")
public Response updateReservation(
@PathParam("id") UUID id, @Valid UpdateReservationRequest request) {
try {
logger.info("PUT /api/reservations-materiel/{}", id);
ReservationMateriel reservation =
reservationService.updateReservation(
id,
request.dateDebut,
request.dateFin,
request.quantite,
request.lieuLivraison,
request.instructionsLivraison,
request.priorite);
return Response.ok(reservation).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la mise à jour de la réservation: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la mise à jour de la réservation: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE GESTION DU WORKFLOW ===
@PUT
@Path("/{id}/valider")
public Response validerReservation(
@PathParam("id") UUID id, @Valid ValiderReservationRequest request) {
try {
logger.info("PUT /api/reservations-materiel/{}/valider", id);
ReservationMateriel reservation = reservationService.validerReservation(id, request.valideur);
return Response.ok(reservation).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la validation de la réservation: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la validation de la réservation: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/refuser")
public Response refuserReservation(
@PathParam("id") UUID id, @Valid RefuserReservationRequest request) {
try {
logger.info("PUT /api/reservations-materiel/{}/refuser", id);
ReservationMateriel reservation =
reservationService.refuserReservation(id, request.valideur, request.motifRefus);
return Response.ok(reservation).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du refus de la réservation: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du refus de la réservation: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/livrer")
public Response livrerMateriel(@PathParam("id") UUID id, @Valid LivrerMaterielRequest request) {
try {
logger.info("PUT /api/reservations-materiel/{}/livrer", id);
ReservationMateriel reservation =
reservationService.livrerMateriel(
id, request.dateLivraison, request.observations, request.etatMateriel);
return Response.ok(reservation).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de la livraison du matériel: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la livraison du matériel: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/retourner")
public Response retournerMateriel(
@PathParam("id") UUID id, @Valid RetournerMaterielRequest request) {
try {
logger.info("PUT /api/reservations-materiel/{}/retourner", id);
ReservationMateriel reservation =
reservationService.retournerMateriel(
id, request.dateRetour, request.observations, request.etatMateriel, request.prixReel);
return Response.ok(reservation).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors du retour du matériel: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors du retour du matériel: " + e.getMessage())
.build();
}
}
@PUT
@Path("/{id}/annuler")
public Response annulerReservation(
@PathParam("id") UUID id, @Valid AnnulerReservationRequest request) {
try {
logger.info("PUT /api/reservations-materiel/{}/annuler", id);
ReservationMateriel reservation =
reservationService.annulerReservation(id, request.motifAnnulation);
return Response.ok(reservation).build();
} catch (NotFoundException e) {
return Response.status(Response.Status.NOT_FOUND).entity(e.getMessage()).build();
} catch (BadRequestException e) {
return Response.status(Response.Status.BAD_REQUEST).entity(e.getMessage()).build();
} catch (Exception e) {
logger.error("Erreur lors de l'annulation de la réservation: " + id, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'annulation de la réservation: " + e.getMessage())
.build();
}
}
// === ENDPOINTS DE VÉRIFICATION ===
@GET
@Path("/check-conflits")
public Response checkConflits(
@QueryParam("materielId") @NotNull UUID materielId,
@QueryParam("dateDebut") @NotNull LocalDate dateDebut,
@QueryParam("dateFin") @NotNull LocalDate dateFin,
@QueryParam("excludeId") UUID excludeId) {
try {
logger.debug("GET /api/reservations-materiel/check-conflits");
List<ReservationMateriel> conflitsList =
reservationService.checkConflits(materielId, dateDebut, dateFin, excludeId);
return Response.ok(
new Object() {
public boolean disponible = conflitsList.isEmpty();
public int nombreConflits = conflitsList.size();
public List<ReservationMateriel> conflits = conflitsList;
})
.build();
} catch (Exception e) {
logger.error("Erreur lors de la vérification des conflits", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la vérification des conflits: " + e.getMessage())
.build();
}
}
@GET
@Path("/disponibilite/{materielId}")
public Response getDisponibiliteMateriel(
@PathParam("materielId") UUID materielId,
@QueryParam("dateDebut") @NotNull LocalDate dateDebut,
@QueryParam("dateFin") @NotNull LocalDate dateFin) {
try {
logger.debug("GET /api/reservations-materiel/disponibilite/{}", materielId);
Map<String, Object> disponibilite =
reservationService.getDisponibiliteMateriel(materielId, dateDebut, dateFin);
return Response.ok(disponibilite).build();
} catch (Exception e) {
logger.error("Erreur lors de l'analyse de disponibilité: " + materielId, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de l'analyse de disponibilité: " + e.getMessage())
.build();
}
}
// === ENDPOINTS STATISTIQUES ===
@GET
@Path("/statistiques")
public Response getStatistiques() {
try {
logger.debug("GET /api/reservations-materiel/statistiques");
Object statistiques = reservationService.getStatistiques();
return Response.ok(statistiques).build();
} catch (Exception e) {
logger.error("Erreur lors de la génération des statistiques", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la génération des statistiques: " + e.getMessage())
.build();
}
}
@GET
@Path("/tableau-bord")
public Response getTableauBord() {
try {
logger.debug("GET /api/reservations-materiel/tableau-bord");
Object tableauBord = reservationService.getTableauBordReservations();
return Response.ok(tableauBord).build();
} catch (Exception e) {
logger.error("Erreur lors de la génération du tableau de bord", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la génération du tableau de bord: " + e.getMessage())
.build();
}
}
// === CLASSES DE REQUÊTE ===
public static class CreateReservationRequest {
@NotNull public UUID materielId;
@NotNull public UUID chantierId;
public UUID phaseId;
@NotNull public LocalDate dateDebut;
@NotNull public LocalDate dateFin;
@NotNull public BigDecimal quantite;
public String unite;
public String demandeur;
public String lieuLivraison;
}
public static class UpdateReservationRequest {
public LocalDate dateDebut;
public LocalDate dateFin;
public BigDecimal quantite;
public String lieuLivraison;
public String instructionsLivraison;
public PrioriteReservation priorite;
}
public static class ValiderReservationRequest {
@NotNull public String valideur;
}
public static class RefuserReservationRequest {
@NotNull public String valideur;
@NotNull public String motifRefus;
}
public static class LivrerMaterielRequest {
public LocalDate dateLivraison;
public String observations;
public String etatMateriel;
}
public static class RetournerMaterielRequest {
public LocalDate dateRetour;
public String observations;
public String etatMateriel;
public BigDecimal prixReel;
}
public static class AnnulerReservationRequest {
@NotNull public String motifAnnulation;
}
}