Refactor: Standardisation complète de l'architecture REST

🔧 RESTRUCTURATION
- UserResource déplacé de adapter.http vers application.rest
- FournisseurResource déplacé vers application.rest
- Suppression des contrôleurs obsolètes (presentation.controller)
- Suppression de MaterielFournisseurService en doublon

📝 STANDARDISATION DOCUMENTATION
- Annotations OpenAPI uniformes (@Operation, @APIResponse, @Parameter)
- Descriptions concises et cohérentes pour tous les endpoints
- Codes de réponse HTTP standards (200, 201, 400, 404, 500)

🛠️ ENDPOINTS USERS STANDARDISÉS
- GET /api/v1/users - Liste tous les utilisateurs
- GET /api/v1/users/{id} - Détails d'un utilisateur
- GET /api/v1/users/stats - Statistiques globales
- GET /api/v1/users/count - Comptage
- GET /api/v1/users/pending - Utilisateurs en attente
- POST /api/v1/users - Création
- PUT /api/v1/users/{id} - Mise à jour
- DELETE /api/v1/users/{id} - Suppression
- POST /api/v1/users/{id}/approve - Approbation
- POST /api/v1/users/{id}/reject - Rejet
- PUT /api/v1/users/{id}/status - Changement de statut
- PUT /api/v1/users/{id}/role - Changement de rôle

⚠️ GESTION D'ERREURS
- Format uniforme: Map.of("error", "message")
- Codes HTTP cohérents avec les autres ressources
- Validation des entrées standardisée

 VALIDATION
- Compilation réussie: mvn clean compile -DskipTests
- Pattern conforme aux autres ressources (PhaseTemplate, Fournisseur)
- Documentation OpenAPI/Swagger complète et cohérente
This commit is contained in:
dahoud
2025-10-23 10:43:32 +00:00
parent de943a4a29
commit fba7666268
19 changed files with 1445 additions and 2651 deletions

View File

@@ -1,515 +0,0 @@
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

@@ -1,309 +0,0 @@
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;
}
}