feat: migration complète vers WebSockets Next + Kafka pour temps réel

- Migration de Jakarta WebSocket vers Quarkus WebSockets Next
- Implémentation de l'architecture Kafka pour événements temps réel
- Ajout des DTOs d'événements (NotificationEvent, ChatMessageEvent, ReactionEvent, PresenceEvent)
- Création des bridges Kafka → WebSocket (NotificationKafkaBridge, ChatKafkaBridge, ReactionKafkaBridge)
- Mise à jour des services pour publier dans Kafka au lieu d'appeler directement WebSocket
- Suppression des classes obsolètes (ChatWebSocket, NotificationWebSocket)
- Correction de l'injection des paramètres path dans WebSockets Next (utilisation de connection.pathParam)
- Ajout des migrations DB pour bookings, promotions, business hours, amenities, reviews
- Mise à jour de la configuration application.properties pour Kafka et WebSockets Next
- Mise à jour .gitignore pour ignorer les fichiers de logs
This commit is contained in:
dahoud
2026-01-21 13:46:16 +00:00
parent 7dd0969799
commit 93c63fd600
78 changed files with 5019 additions and 1113 deletions

View File

@@ -109,46 +109,9 @@ public class EstablishmentRatingResource {
}
}
/**
* Récupère la note d'un utilisateur pour un établissement.
*/
@GET
@Path("/users/{userId}")
@Operation(summary = "Récupérer la note d'un utilisateur",
description = "Récupère la note donnée par un utilisateur spécifique pour un établissement")
public Response getUserRating(
@PathParam("establishmentId") String establishmentId,
@PathParam("userId") String userIdStr) {
LOG.info("Récupération de la note de l'utilisateur " + userIdStr + " pour l'établissement " + establishmentId);
try {
UUID id = UUID.fromString(establishmentId);
UUID userId = UUID.fromString(userIdStr);
EstablishmentRating rating = ratingService.getUserRating(id, userId);
if (rating == null) {
return Response.status(Response.Status.NOT_FOUND)
.entity("Note non trouvée")
.build();
}
EstablishmentRatingResponseDTO responseDTO = new EstablishmentRatingResponseDTO(rating);
return Response.ok(responseDTO).build();
} catch (IllegalArgumentException e) {
LOG.error("ID invalide : " + e.getMessage());
return Response.status(Response.Status.BAD_REQUEST)
.entity("ID invalide : " + e.getMessage())
.build();
} catch (Exception e) {
LOG.error("Erreur inattendue lors de la récupération de la note", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération de la note")
.build();
}
}
/**
* Récupère les statistiques de notation d'un établissement.
* Doit être déclaré avant les endpoints génériques GET pour la résolution correcte par JAX-RS.
*/
@GET
@Path("/stats")
@@ -179,5 +142,92 @@ public class EstablishmentRatingResource {
.build();
}
}
/**
* Récupère la note d'un utilisateur pour un établissement (via path parameter).
* Endpoint alternatif pour compatibilité.
*/
@GET
@Path("/users/{userId}")
@Operation(summary = "Récupérer la note d'un utilisateur (path parameter)",
description = "Récupère la note donnée par un utilisateur spécifique pour un établissement (via path parameter)")
public Response getUserRatingByPath(
@PathParam("establishmentId") String establishmentId,
@PathParam("userId") String userIdStr) {
LOG.info("Récupération de la note de l'utilisateur " + userIdStr + " pour l'établissement " + establishmentId);
try {
UUID id = UUID.fromString(establishmentId);
UUID userId = UUID.fromString(userIdStr);
EstablishmentRating rating = ratingService.getUserRating(id, userId);
if (rating == null) {
return Response.status(Response.Status.NOT_FOUND)
.entity("Note non trouvée")
.build();
}
EstablishmentRatingResponseDTO responseDTO = new EstablishmentRatingResponseDTO(rating);
return Response.ok(responseDTO).build();
} catch (IllegalArgumentException e) {
LOG.error("ID invalide : " + e.getMessage(), e);
return Response.status(Response.Status.BAD_REQUEST)
.entity("ID invalide : " + e.getMessage())
.build();
} catch (Exception e) {
LOG.error("Erreur inattendue lors de la récupération de la note", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération de la note")
.build();
}
}
/**
* Récupère la note d'un utilisateur pour un établissement (via query parameter).
* Endpoint utilisé par le frontend Flutter.
* Doit être déclaré en dernier car c'est l'endpoint le plus générique.
*/
@GET
@Operation(summary = "Récupérer la note d'un utilisateur",
description = "Récupère la note donnée par un utilisateur spécifique pour un établissement (via query parameter userId)")
public Response getUserRatingByQuery(
@PathParam("establishmentId") String establishmentId,
@QueryParam("userId") String userIdStr) {
LOG.info("Récupération de la note de l'utilisateur " + userIdStr + " pour l'établissement " + establishmentId);
// Si userId n'est pas fourni, retourner une erreur
if (userIdStr == null || userIdStr.isEmpty()) {
LOG.warn("userId manquant dans la requête");
return Response.status(Response.Status.BAD_REQUEST)
.entity("Le paramètre userId est requis")
.build();
}
try {
UUID id = UUID.fromString(establishmentId);
UUID userId = UUID.fromString(userIdStr);
EstablishmentRating rating = ratingService.getUserRating(id, userId);
if (rating == null) {
// Retourner 404 si la note n'existe pas
return Response.status(Response.Status.NOT_FOUND)
.entity("Note non trouvée")
.build();
}
EstablishmentRatingResponseDTO responseDTO = new EstablishmentRatingResponseDTO(rating);
return Response.ok(responseDTO).build();
} catch (IllegalArgumentException e) {
LOG.error("ID invalide : " + e.getMessage(), e);
return Response.status(Response.Status.BAD_REQUEST)
.entity("ID invalide : " + e.getMessage())
.build();
} catch (Exception e) {
LOG.error("Erreur inattendue lors de la récupération de la note", e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("Erreur lors de la récupération de la note")
.build();
}
}
}