feat: Système complet de gestion des établissements (backend) - Entités JPA pour Establishment, EstablishmentMedia, EstablishmentRating - DTOs pour création, mise à jour et réponses - Repositories Panache pour accès aux données - Services avec logique métier et validation - Resources REST avec tous les endpoints CRUD - Gestion des médias (photos/vidéos) - Système de notation avec statistiques

This commit is contained in:
dahoud
2026-01-13 20:45:13 +00:00
parent c0b1863467
commit 56d0aad6a6
20 changed files with 1886 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
package com.lions.dev.service;
import com.lions.dev.entity.establishment.Establishment;
import com.lions.dev.entity.establishment.EstablishmentMedia;
import com.lions.dev.entity.establishment.MediaType;
import com.lions.dev.entity.users.Users;
import com.lions.dev.repository.EstablishmentMediaRepository;
import com.lions.dev.repository.EstablishmentRepository;
import com.lions.dev.repository.UsersRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import org.jboss.logging.Logger;
import java.util.List;
import java.util.UUID;
/**
* Service de gestion des médias d'établissements.
* Ce service contient la logique métier pour l'upload, la récupération et la suppression des médias.
*/
@ApplicationScoped
public class EstablishmentMediaService {
@Inject
EstablishmentMediaRepository mediaRepository;
@Inject
EstablishmentRepository establishmentRepository;
@Inject
UsersRepository usersRepository;
private static final Logger LOG = Logger.getLogger(EstablishmentMediaService.class);
/**
* Récupère tous les médias d'un établissement.
*
* @param establishmentId L'ID de l'établissement
* @return Liste des médias de l'établissement
*/
public List<EstablishmentMedia> getMediaByEstablishmentId(UUID establishmentId) {
LOG.info("Récupération des médias pour l'établissement : " + establishmentId);
return mediaRepository.findByEstablishmentId(establishmentId);
}
/**
* Upload un nouveau média pour un établissement.
*
* @param establishmentId L'ID de l'établissement
* @param mediaUrl L'URL du média
* @param mediaType Le type de média (PHOTO ou VIDEO)
* @param uploadedByUserId L'ID de l'utilisateur qui upload
* @param thumbnailUrl L'URL de la miniature (optionnel, pour les vidéos)
* @return Le média créé
*/
@Transactional
public EstablishmentMedia uploadMedia(UUID establishmentId, String mediaUrl, MediaType mediaType, UUID uploadedByUserId, String thumbnailUrl) {
LOG.info("Upload d'un média pour l'établissement : " + establishmentId);
// Vérifier que l'établissement existe
Establishment establishment = establishmentRepository.findById(establishmentId);
if (establishment == null) {
LOG.error("Établissement non trouvé avec l'ID : " + establishmentId);
throw new RuntimeException("Établissement non trouvé");
}
// Vérifier que l'utilisateur existe
Users uploadedBy = usersRepository.findById(uploadedByUserId);
if (uploadedBy == null) {
LOG.error("Utilisateur non trouvé avec l'ID : " + uploadedByUserId);
throw new RuntimeException("Utilisateur non trouvé");
}
// Créer le média
EstablishmentMedia media = new EstablishmentMedia(establishment, mediaUrl, mediaType, uploadedBy);
media.setThumbnailUrl(thumbnailUrl);
// Déterminer l'ordre d'affichage (dernier média = ordre le plus élevé)
List<EstablishmentMedia> existingMedia = mediaRepository.findByEstablishmentId(establishmentId);
int maxOrder = existingMedia.stream()
.mapToInt(EstablishmentMedia::getDisplayOrder)
.max()
.orElse(-1);
media.setDisplayOrder(maxOrder + 1);
mediaRepository.persist(media);
LOG.info("Média uploadé avec succès : " + media.getId());
return media;
}
/**
* Supprime un média d'un établissement.
*
* @param establishmentId L'ID de l'établissement
* @param mediaId L'ID du média à supprimer
*/
@Transactional
public void deleteMedia(UUID establishmentId, UUID mediaId) {
LOG.info("Suppression du média " + mediaId + " de l'établissement " + establishmentId);
EstablishmentMedia media = mediaRepository.findById(mediaId);
if (media == null) {
LOG.error("Média non trouvé avec l'ID : " + mediaId);
throw new RuntimeException("Média non trouvé");
}
// Vérifier que le média appartient à l'établissement
if (!media.getEstablishment().getId().equals(establishmentId)) {
LOG.error("Le média " + mediaId + " n'appartient pas à l'établissement " + establishmentId);
throw new RuntimeException("Le média n'appartient pas à cet établissement");
}
mediaRepository.delete(media);
LOG.info("Média supprimé avec succès : " + mediaId);
}
}

View File

@@ -0,0 +1,167 @@
package com.lions.dev.service;
import com.lions.dev.dto.request.establishment.EstablishmentRatingRequestDTO;
import com.lions.dev.entity.establishment.Establishment;
import com.lions.dev.entity.establishment.EstablishmentRating;
import com.lions.dev.entity.users.Users;
import com.lions.dev.repository.EstablishmentRatingRepository;
import com.lions.dev.repository.EstablishmentRepository;
import com.lions.dev.repository.UsersRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import org.jboss.logging.Logger;
import java.util.Map;
import java.util.UUID;
/**
* Service de gestion des notations d'établissements.
* Ce service contient la logique métier pour soumettre, modifier et récupérer les notes.
*/
@ApplicationScoped
public class EstablishmentRatingService {
@Inject
EstablishmentRatingRepository ratingRepository;
@Inject
EstablishmentRepository establishmentRepository;
@Inject
UsersRepository usersRepository;
private static final Logger LOG = Logger.getLogger(EstablishmentRatingService.class);
/**
* Soumet une nouvelle note pour un établissement.
*
* @param establishmentId L'ID de l'établissement
* @param userId L'ID de l'utilisateur
* @param requestDTO Le DTO contenant la note et le commentaire
* @return La note créée
*/
@Transactional
public EstablishmentRating submitRating(UUID establishmentId, UUID userId, EstablishmentRatingRequestDTO requestDTO) {
LOG.info("Soumission d'une note pour l'établissement " + establishmentId + " par l'utilisateur " + userId);
// Vérifier que l'établissement existe
Establishment establishment = establishmentRepository.findById(establishmentId);
if (establishment == null) {
LOG.error("Établissement non trouvé avec l'ID : " + establishmentId);
throw new RuntimeException("Établissement non trouvé");
}
// Vérifier que l'utilisateur existe
Users user = usersRepository.findById(userId);
if (user == null) {
LOG.error("Utilisateur non trouvé avec l'ID : " + userId);
throw new RuntimeException("Utilisateur non trouvé");
}
// Vérifier qu'il n'y a pas déjà une note de cet utilisateur
EstablishmentRating existingRating = ratingRepository.findByEstablishmentIdAndUserId(establishmentId, userId);
if (existingRating != null) {
LOG.error("L'utilisateur " + userId + " a déjà noté l'établissement " + establishmentId);
throw new RuntimeException("Vous avez déjà noté cet établissement. Utilisez la mise à jour pour modifier votre note.");
}
// Créer la note
EstablishmentRating rating = new EstablishmentRating(establishment, user, requestDTO.getRating());
rating.setComment(requestDTO.getComment());
ratingRepository.persist(rating);
// Mettre à jour les statistiques de l'établissement
updateEstablishmentRatingStats(establishmentId);
LOG.info("Note soumise avec succès : " + rating.getId());
return rating;
}
/**
* Met à jour une note existante.
*
* @param establishmentId L'ID de l'établissement
* @param userId L'ID de l'utilisateur
* @param requestDTO Le DTO contenant la nouvelle note et le commentaire
* @return La note mise à jour
*/
@Transactional
public EstablishmentRating updateRating(UUID establishmentId, UUID userId, EstablishmentRatingRequestDTO requestDTO) {
LOG.info("Mise à jour de la note pour l'établissement " + establishmentId + " par l'utilisateur " + userId);
// Récupérer la note existante
EstablishmentRating rating = ratingRepository.findByEstablishmentIdAndUserId(establishmentId, userId);
if (rating == null) {
LOG.error("Note non trouvée pour l'établissement " + establishmentId + " et l'utilisateur " + userId);
throw new RuntimeException("Note non trouvée. Utilisez la soumission pour créer une nouvelle note.");
}
// Mettre à jour la note
rating.updateRating(requestDTO.getRating(), requestDTO.getComment());
ratingRepository.persist(rating);
// Mettre à jour les statistiques de l'établissement
updateEstablishmentRatingStats(establishmentId);
LOG.info("Note mise à jour avec succès : " + rating.getId());
return rating;
}
/**
* Récupère la note d'un utilisateur pour un établissement.
*
* @param establishmentId L'ID de l'établissement
* @param userId L'ID de l'utilisateur
* @return La note de l'utilisateur ou null si pas encore noté
*/
public EstablishmentRating getUserRating(UUID establishmentId, UUID userId) {
LOG.info("Récupération de la note de l'utilisateur " + userId + " pour l'établissement " + establishmentId);
return ratingRepository.findByEstablishmentIdAndUserId(establishmentId, userId);
}
/**
* Récupère les statistiques de notation d'un établissement.
*
* @param establishmentId L'ID de l'établissement
* @return Map contenant averageRating, totalRatings et distribution
*/
public Map<String, Object> getRatingStats(UUID establishmentId) {
LOG.info("Récupération des statistiques de notation pour l'établissement " + establishmentId);
Double averageRating = ratingRepository.calculateAverageRating(establishmentId);
Long totalRatings = ratingRepository.countByEstablishmentId(establishmentId);
Map<Integer, Integer> distribution = ratingRepository.calculateRatingDistribution(establishmentId);
return Map.of(
"averageRating", averageRating,
"totalRatingsCount", totalRatings.intValue(),
"ratingDistribution", distribution
);
}
/**
* Met à jour les statistiques de notation d'un établissement.
* Cette méthode est appelée après chaque création/modification de note.
* Note: Cette méthode est appelée depuis des méthodes déjà transactionnelles,
* donc pas besoin de l'annotation @Transactional ici.
*
* @param establishmentId L'ID de l'établissement
*/
private void updateEstablishmentRatingStats(UUID establishmentId) {
Establishment establishment = establishmentRepository.findById(establishmentId);
if (establishment == null) {
return;
}
Double averageRating = ratingRepository.calculateAverageRating(establishmentId);
Long totalRatings = ratingRepository.countByEstablishmentId(establishmentId);
establishment.setAverageRating(averageRating);
establishment.setTotalRatingsCount(totalRatings.intValue());
establishmentRepository.persist(establishment);
LOG.info("Statistiques mises à jour pour l'établissement " + establishmentId + " : moyenne = " + averageRating + ", total = " + totalRatings);
}
}

View File

@@ -0,0 +1,194 @@
package com.lions.dev.service;
import com.lions.dev.entity.establishment.Establishment;
import com.lions.dev.entity.users.Users;
import com.lions.dev.repository.EstablishmentRepository;
import com.lions.dev.repository.UsersRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import java.util.List;
import java.util.UUID;
import org.jboss.logging.Logger;
/**
* Service de gestion des établissements.
* Ce service contient la logique métier pour la création, récupération,
* mise à jour et suppression des établissements.
* Seuls les responsables d'établissement peuvent créer et gérer des établissements.
*/
@ApplicationScoped
public class EstablishmentService {
@Inject
EstablishmentRepository establishmentRepository;
@Inject
UsersRepository usersRepository;
private static final Logger LOG = Logger.getLogger(EstablishmentService.class);
/**
* Crée un nouvel établissement.
*
* @param establishment L'établissement à créer.
* @param managerId L'ID du responsable de l'établissement.
* @return L'établissement créé.
*/
@Transactional
public Establishment createEstablishment(Establishment establishment, UUID managerId) {
LOG.info("[LOG] Création d'un nouvel établissement : " + establishment.getName());
// Vérifier que le manager existe
Users manager = usersRepository.findById(managerId);
if (manager == null) {
LOG.error("[ERROR] Responsable non trouvé avec l'ID : " + managerId);
throw new RuntimeException("Responsable non trouvé avec l'ID fourni");
}
// Vérifier que l'utilisateur a le rôle de responsable d'établissement
String role = manager.getRole() != null ? manager.getRole().toUpperCase() : "";
if (!role.equals("ESTABLISHMENT_MANAGER") &&
!role.equals("MANAGER") &&
!role.equals("ADMIN")) {
LOG.error("[ERROR] L'utilisateur " + managerId + " n'a pas les droits pour créer un établissement. Rôle : " + role);
throw new RuntimeException("Seuls les responsables d'établissement peuvent créer des établissements");
}
establishment.setManager(manager);
establishmentRepository.persist(establishment);
LOG.info("[LOG] Établissement créé avec succès : " + establishment.getName());
return establishment;
}
/**
* Récupère tous les établissements.
*
* @return Une liste de tous les établissements.
*/
public List<Establishment> getAllEstablishments() {
LOG.info("[LOG] Récupération de tous les établissements");
List<Establishment> establishments = establishmentRepository.listAll();
LOG.info("[LOG] Nombre d'établissements trouvés : " + establishments.size());
return establishments;
}
/**
* Récupère un établissement par son ID.
*
* @param id L'ID de l'établissement.
* @return L'établissement trouvé.
*/
public Establishment getEstablishmentById(UUID id) {
LOG.info("[LOG] Récupération de l'établissement avec l'ID : " + id);
Establishment establishment = establishmentRepository.findById(id);
if (establishment == null) {
LOG.warn("[WARN] Établissement non trouvé avec l'ID : " + id);
throw new RuntimeException("Établissement non trouvé avec l'ID : " + id);
}
return establishment;
}
/**
* Met à jour un établissement existant.
*
* @param id L'ID de l'établissement à mettre à jour.
* @param updatedEstablishment L'établissement avec les nouvelles données.
* @return L'établissement mis à jour.
*/
@Transactional
public Establishment updateEstablishment(UUID id, Establishment updatedEstablishment) {
LOG.info("[LOG] Mise à jour de l'établissement avec l'ID : " + id);
Establishment establishment = establishmentRepository.findById(id);
if (establishment == null) {
LOG.error("[ERROR] Établissement non trouvé avec l'ID : " + id);
throw new RuntimeException("Établissement non trouvé avec l'ID : " + id);
}
// Mettre à jour les champs
establishment.setName(updatedEstablishment.getName());
establishment.setType(updatedEstablishment.getType());
establishment.setAddress(updatedEstablishment.getAddress());
establishment.setCity(updatedEstablishment.getCity());
establishment.setPostalCode(updatedEstablishment.getPostalCode());
establishment.setDescription(updatedEstablishment.getDescription());
establishment.setPhoneNumber(updatedEstablishment.getPhoneNumber());
establishment.setEmail(updatedEstablishment.getEmail());
establishment.setWebsite(updatedEstablishment.getWebsite());
establishment.setImageUrl(updatedEstablishment.getImageUrl());
establishment.setRating(updatedEstablishment.getRating());
establishment.setPriceRange(updatedEstablishment.getPriceRange());
establishment.setCapacity(updatedEstablishment.getCapacity());
establishment.setAmenities(updatedEstablishment.getAmenities());
establishment.setOpeningHours(updatedEstablishment.getOpeningHours());
establishment.setLatitude(updatedEstablishment.getLatitude());
establishment.setLongitude(updatedEstablishment.getLongitude());
establishmentRepository.persist(establishment);
LOG.info("[LOG] Établissement mis à jour avec succès : " + establishment.getName());
return establishment;
}
/**
* Supprime un établissement.
*
* @param id L'ID de l'établissement à supprimer.
*/
@Transactional
public void deleteEstablishment(UUID id) {
LOG.info("[LOG] Suppression de l'établissement avec l'ID : " + id);
Establishment establishment = establishmentRepository.findById(id);
if (establishment == null) {
LOG.error("[ERROR] Établissement non trouvé avec l'ID : " + id);
throw new RuntimeException("Établissement non trouvé avec l'ID : " + id);
}
establishmentRepository.delete(establishment);
LOG.info("[LOG] Établissement supprimé avec succès : " + establishment.getName());
}
/**
* Récupère les établissements gérés par un responsable.
*
* @param managerId L'ID du responsable.
* @return Une liste d'établissements gérés par ce responsable.
*/
public List<Establishment> getEstablishmentsByManager(UUID managerId) {
LOG.info("[LOG] Récupération des établissements du responsable : " + managerId);
List<Establishment> establishments = establishmentRepository.findByManagerId(managerId);
LOG.info("[LOG] Nombre d'établissements trouvés : " + establishments.size());
return establishments;
}
/**
* Recherche des établissements par nom ou ville.
*
* @param query Le terme de recherche.
* @return Une liste d'établissements correspondant à la recherche.
*/
public List<Establishment> searchEstablishments(String query) {
LOG.info("[LOG] Recherche d'établissements avec la requête : " + query);
List<Establishment> establishments = establishmentRepository.searchByNameOrCity(query);
LOG.info("[LOG] Nombre d'établissements trouvés : " + establishments.size());
return establishments;
}
/**
* Filtre les établissements par type, fourchette de prix et/ou ville.
*
* @param type Le type d'établissement (optionnel).
* @param priceRange La fourchette de prix (optionnel).
* @param city La ville (optionnel).
* @return Une liste d'établissements correspondant aux filtres.
*/
public List<Establishment> filterEstablishments(String type, String priceRange, String city) {
LOG.info("[LOG] Filtrage des établissements : type=" + type + ", priceRange=" + priceRange + ", city=" + city);
List<Establishment> allEstablishments = establishmentRepository.listAll();
return allEstablishments.stream()
.filter(e -> type == null || e.getType().equalsIgnoreCase(type))
.filter(e -> priceRange == null || (e.getPriceRange() != null && e.getPriceRange().equalsIgnoreCase(priceRange)))
.filter(e -> city == null || e.getCity().equalsIgnoreCase(city))
.toList();
}
}