Bon checkpoint + Refactoring

This commit is contained in:
DahoudG
2024-11-08 20:30:39 +00:00
parent 841789f8c2
commit 588984aa9c
13 changed files with 1048 additions and 478 deletions

View File

@@ -0,0 +1,22 @@
package com.lions.dev.dto.request.events;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* DTO de requête pour obtenir les événements créés par un utilisateur spécifique.
* Permet l'ajout futur de critères de filtre si nécessaire.
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class EventReadManyByIdRequestDTO {
private UUID userId; // Identifiant de l'utilisateur pour lequel on souhaite obtenir les événements
// Ajoutez ici d'autres critères de filtre si besoin, comme une plage de dates, un statut, etc.
}

View File

@@ -0,0 +1,71 @@
package com.lions.dev.dto.response.comments;
import com.lions.dev.entity.comment.Comment; // Import de l'entité Comment
import lombok.Getter;
import lombok.Setter;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import java.util.UUID;
/**
* DTO (Data Transfer Object) pour le commentaire.
* <p>
* Cette classe est utilisée pour représenter un commentaire d'un événement dans les réponses de l'API.
* Elle permet de transférer les informations du commentaire sans exposer des données sensibles ou non nécessaires.
* </p>
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class CommentResponseDTO {
/**
* Identifiant unique du commentaire.
* C'est un UUID généré de manière unique pour chaque commentaire.
*/
private UUID id;
/**
* Texte du commentaire.
* Contient le contenu écrit par l'utilisateur pour un événement donné.
*/
private String texte;
/**
* Identifiant de l'utilisateur qui a écrit le commentaire.
* Il permet d'identifier l'auteur du commentaire sans exposer d'autres informations sensibles.
*/
private UUID userId;
/**
* Nom de l'utilisateur ayant écrit le commentaire.
* Le nom est inclus pour permettre une identification facile de l'auteur du commentaire.
*/
private String userNom;
/**
* Prénom de l'utilisateur ayant écrit le commentaire.
* Prénom associé à l'auteur du commentaire.
*/
private String userPrenoms;
/**
* Constructeur de DTO à partir d'une entité Comment.
* <p>
* Ce constructeur permet de convertir l'entité {@link Comment} en un DTO simple qui peut être retourné dans les réponses API.
* </p>
*
* @param comment L'entité {@link Comment} dont les informations sont extraites pour le DTO.
*/
public CommentResponseDTO(Comment comment) {
if (comment != null) {
this.id = comment.getId(); // Identifiant unique du commentaire
this.texte = comment.getText(); // Texte du commentaire
this.userId = comment.getUser().getId(); // Identifiant de l'utilisateur (auteur du commentaire)
this.userNom = comment.getUser().getNom(); // Nom de l'utilisateur
this.userPrenoms = comment.getUser().getPrenoms(); // Prénom de l'utilisateur
}
}
}

View File

@@ -0,0 +1,42 @@
package com.lions.dev.dto.response.events;
import com.lions.dev.entity.events.Events;
import java.time.LocalDateTime;
import lombok.Getter;
/**
* DTO pour renvoyer les informations des événements créés par un utilisateur spécifique.
* Ce DTO est utilisé pour structurer les données retournées dans la réponse.
*/
@Getter
public class EventReadManyByIdResponseDTO {
private String id; // Identifiant de l'événement
private String title; // Titre de l'événement
private String description; // Description de l'événement
private LocalDateTime startDate; // Date de début de l'événement
private LocalDateTime endDate; // Date de fin de l'événement
private String location; // Lieu de l'événement
private String category; // Catégorie de l'événement
private String link; // Lien vers plus d'informations
private String imageUrl; // URL de l'image de l'événement
private String status; // Statut de l'événement
/**
* Constructeur qui transforme une entité Events en DTO de réponse.
*
* @param event L'événement à convertir en DTO.
*/
public EventReadManyByIdResponseDTO(Events event) {
this.id = event.getId().toString();
this.title = event.getTitle();
this.description = event.getDescription();
this.startDate = event.getStartDate();
this.endDate = event.getEndDate();
this.location = event.getLocation();
this.category = event.getCategory();
this.link = event.getLink();
this.imageUrl = event.getImageUrl();
this.status = event.getStatus();
}
}

View File

@@ -0,0 +1,69 @@
package com.lions.dev.dto;
import com.lions.dev.entity.users.Users; // Import de l'entité Users
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
/**
* DTO (Data Transfer Object) pour l'utilisateur.
* <p>
* Cette classe sert de représentation simplifiée d'un utilisateur, avec un ensemble d'informations nécessaires à
* la réponse de l'API. Elle est utilisée pour transférer des données entre le backend (serveur) et le frontend (client)
* tout en excluant les informations sensibles comme le mot de passe.
* </p>
*/
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class UserResponseDTO {
/**
* Identifiant unique de l'utilisateur. Il s'agit d'un UUID généré de manière unique.
*/
private UUID id;
/**
* Nom de famille de l'utilisateur. C'est une donnée importante pour l'affichage du profil.
*/
private String nom;
/**
* Prénom(s) de l'utilisateur. Représente le ou les prénoms associés à l'utilisateur.
*/
private String prenoms;
/**
* Adresse email de l'utilisateur. C'est une donnée souvent utilisée pour les communications.
*/
private String email;
/**
* URL de l'image de profil de l'utilisateur. Si l'utilisateur a une image de profil, cette URL
* pointe vers l'emplacement de l'image.
*/
private String profileImageUrl;
/**
* Constructeur de DTO à partir d'une entité Users.
* <p>
* Ce constructeur prend une entité {@link Users} et extrait les données nécessaires pour
* peupler les champs du DTO. Cette transformation permet de transférer des données sans exposer
* des informations sensibles.
* </p>
*
* @param user L'entité {@link Users} dont les données sont extraites.
*/
public UserResponseDTO(Users user) {
if (user != null) {
this.id = user.getId(); // Identifiant unique de l'utilisateur
this.nom = user.getNom(); // Nom de famille
this.prenoms = user.getPrenoms(); // Prénom(s)
this.email = user.getEmail(); // Email
this.profileImageUrl = user.getProfileImageUrl(); // URL de l'image de profil
}
}
}

View File

@@ -1,22 +1,21 @@
package com.lions.dev.entity.comment; package com.lions.dev.entity.comment;
import com.lions.dev.entity.BaseEntity; import com.lions.dev.entity.BaseEntity;
import com.lions.dev.entity.users.Users;
import com.lions.dev.entity.events.Events; import com.lions.dev.entity.events.Events;
import com.lions.dev.entity.users.Users;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.time.LocalDateTime;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
import lombok.ToString; import lombok.ToString;
import java.time.LocalDateTime;
/** /**
* Entité représentant un commentaire d'un utilisateur sur un événement dans le système AfterWork. * Entité représentant un commentaire d'un utilisateur sur un événement dans le système AfterWork.
* Chaque commentaire est lié à un utilisateur et à un événement, et contient le texte du commentaire * Chaque commentaire est lié à un utilisateur et à un événement, et contient le texte du
* ainsi que la date de création. * commentaire ainsi que la date de création.
* *
* Des logs et des commentaires sont inclus pour assurer une traçabilité claire. * <p>L'entité gère la relation entre les commentaires, les utilisateurs et les événements.
*/ */
@Entity @Entity
@Table(name = "comments") @Table(name = "comments")
@@ -30,7 +29,7 @@ public class Comment extends BaseEntity {
private String text; // Le texte du commentaire private String text; // Le texte du commentaire
@Column(name = "comment_date", nullable = false) @Column(name = "comment_date", nullable = false)
private LocalDateTime commentDate; // La date à laquelle le commentaire a été publié private LocalDateTime commentDate; // La date de création du commentaire
@ManyToOne(fetch = FetchType.LAZY) @ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false) @JoinColumn(name = "user_id", nullable = false)
@@ -43,26 +42,45 @@ public class Comment extends BaseEntity {
/** /**
* Constructeur pour créer un nouveau commentaire. * Constructeur pour créer un nouveau commentaire.
* *
* @param user L'utilisateur qui commente. * <p>Le constructeur initialise un commentaire avec l'utilisateur, l'événement et le texte
* @param event L'événement commenté. * fournis. Il définit également la date de création du commentaire.
*
* @param user L'utilisateur qui fait le commentaire.
* @param event L'événement auquel ce commentaire est lié.
* @param text Le texte du commentaire. * @param text Le texte du commentaire.
*/ */
public Comment(Users user, Events event, String text) { public Comment(Users user, Events event, String text) {
this.user = user; this.user = user;
this.event = event; this.event = event;
this.text = text; this.text = text;
this.commentDate = LocalDateTime.now(); // Définit automatiquement la date actuelle this.commentDate =
System.out.println("[LOG] Nouveau commentaire ajouté par " + user.getEmail() + " sur l'événement : " + event.getTitle() + " - Texte : " + text); LocalDateTime.now(); // La date est définie automatiquement lors de la création
System.out.println(
"[LOG] Nouveau commentaire ajouté par "
+ user.getEmail()
+ " sur l'événement : "
+ event.getTitle()
+ " - Texte : "
+ text);
} }
/** /**
* Modifie le texte du commentaire. * Modifie le texte du commentaire.
* *
* <p>Cette méthode permet de mettre à jour le texte d'un commentaire existant et de mettre à jour
* la date du commentaire pour refléter le changement.
*
* @param newText Le nouveau texte du commentaire. * @param newText Le nouveau texte du commentaire.
*/ */
public void updateComment(String newText) { public void updateComment(String newText) {
System.out.println("[LOG] Modification du commentaire de " + user.getEmail() + " sur l'événement : " + event.getTitle() + " - Nouveau texte : " + newText); System.out.println(
"[LOG] Modification du commentaire de "
+ user.getEmail()
+ " sur l'événement : "
+ event.getTitle()
+ " - Nouveau texte : "
+ newText);
this.text = newText; this.text = newText;
this.commentDate = LocalDateTime.now(); // Met à jour la date de modification this.commentDate = LocalDateTime.now(); // Mise à jour de la date de modification
} }
} }

View File

@@ -1,8 +1,10 @@
package com.lions.dev.entity.events; package com.lions.dev.entity.events;
import com.lions.dev.entity.BaseEntity; import com.lions.dev.entity.BaseEntity;
import com.lions.dev.entity.comment.Comment;
import com.lions.dev.entity.users.Users; import com.lions.dev.entity.users.Users;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.util.List;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
@@ -109,4 +111,17 @@ public class Events extends BaseEntity {
System.out.println("[LOG] Statut de l'événement mis à jour : " + this.title + " - " + this.status); System.out.println("[LOG] Statut de l'événement mis à jour : " + this.title + " - " + this.status);
} }
@OneToMany(fetch = FetchType.LAZY, mappedBy = "event")
private List<Comment> comments; // Liste des commentaires associés à l'événement
/**
* Retourne la liste des commentaires associés à cet événement.
*
* @return Une liste de commentaires.
*/
public List<Comment> getComments() {
System.out.println("[LOG] Récupération des commentaires pour l'événement : " + this.title);
return comments;
}
} }

View File

@@ -1,7 +1,10 @@
package com.lions.dev.entity.users; package com.lions.dev.entity.users;
import com.lions.dev.entity.BaseEntity; import com.lions.dev.entity.BaseEntity;
import com.lions.dev.entity.events.Events;
import jakarta.persistence.*; import jakarta.persistence.*;
import java.util.HashSet;
import java.util.Set;
import lombok.Getter; import lombok.Getter;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.Setter; import lombok.Setter;
@@ -41,6 +44,9 @@ public class Users extends BaseEntity {
@Column(name = "profile_image_url") @Column(name = "profile_image_url")
private String profileImageUrl; // L'URL de l'image de profil de l'utilisateur private String profileImageUrl; // L'URL de l'image de profil de l'utilisateur
@Column(name = "preferred_category")
private String preferredCategory; // La catégorie préférée de l'utilisateur
// Utilisation de BCrypt pour hacher les mots de passe de manière sécurisée // Utilisation de BCrypt pour hacher les mots de passe de manière sécurisée
private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); private static final BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
@@ -76,4 +82,49 @@ public class Users extends BaseEntity {
System.out.println("[LOG] Vérification du rôle ADMIN pour l'utilisateur : " + this.email + " - Résultat : " + isAdmin); System.out.println("[LOG] Vérification du rôle ADMIN pour l'utilisateur : " + this.email + " - Résultat : " + isAdmin);
return isAdmin; return isAdmin;
} }
@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "favorite_events")
private Set<Events> favoriteEvents = new HashSet<>(); // Liste des événements favoris
/**
* Ajoute un événement aux favoris de l'utilisateur.
*
* @param event L'événement à ajouter.
*/
public void addFavoriteEvent(Events event) {
favoriteEvents.add(event);
System.out.println("[LOG] Événement ajouté aux favoris pour l'utilisateur : " + this.email);
}
/**
* Retourne la liste des événements favoris de l'utilisateur.
*
* @return Une liste d'événements favoris.
*/
public Set<Events> getFavoriteEvents() {
System.out.println("[LOG] Récupération des événements favoris pour l'utilisateur : " + this.email);
return favoriteEvents;
}
/**
* Retourne la catégorie préférée de l'utilisateur.
*
* @return La catégorie préférée de l'utilisateur.
*/
public String getPreferredCategory() {
System.out.println("[LOG] Récupération de la catégorie préférée pour l'utilisateur : " + this.email);
return preferredCategory;
}
/**
* Définit la catégorie préférée de l'utilisateur.
*
* @param category La catégorie à définir.
*/
public void setPreferredCategory(String category) {
this.preferredCategory = category;
System.out.println("[LOG] Catégorie préférée définie pour l'utilisateur : " + this.email + " - Catégorie : " + category);
}
} }

View File

@@ -5,7 +5,6 @@ import com.lions.dev.entity.friends.FriendshipStatus;
import com.lions.dev.entity.users.Users; import com.lions.dev.entity.users.Users;
import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase; import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@@ -37,9 +36,15 @@ public class FriendshipRepository implements PanacheRepositoryBase<Friendship, U
* @return Une liste paginée de relations d'amitié acceptées. * @return Une liste paginée de relations d'amitié acceptées.
*/ */
public List<Friendship> findFriendsByUser(Users user, int page, int size) { public List<Friendship> findFriendsByUser(Users user, int page, int size) {
return find("(user = ?1 or friend = ?1) and status = ?2", user, FriendshipStatus.ACCEPTED) System.out.println("**************************************************************" + user.getId());
// Utiliser une requête basée sur les IDs pour éviter les duplications
return find("(user.id = ?1 OR friend.id = ?1) AND status = ?2", user.getId(),
FriendshipStatus.ACCEPTED)
.page(page, size) .page(page, size)
.list(); .stream()
// .filter(friendship -> !friendship.getUser().equals(friendship.getFriend())) // Exclure les relations dupliquées
// .distinct() // Appliquer distinct sur le flux pour éviter tout doublon supplémentaire
.toList();
} }
/** /**

File diff suppressed because it is too large Load Diff

View File

@@ -6,6 +6,7 @@ import com.lions.dev.dto.request.friends.FriendshipReadStatusRequestDTO;
import com.lions.dev.dto.response.friends.FriendshipCreateOneResponseDTO; import com.lions.dev.dto.response.friends.FriendshipCreateOneResponseDTO;
import com.lions.dev.dto.response.friends.FriendshipReadFriendDetailsResponseDTO; import com.lions.dev.dto.response.friends.FriendshipReadFriendDetailsResponseDTO;
import com.lions.dev.dto.response.friends.FriendshipReadStatusResponseDTO; import com.lions.dev.dto.response.friends.FriendshipReadStatusResponseDTO;
import com.lions.dev.exception.UserNotFoundException;
import com.lions.dev.service.FriendshipService; import com.lions.dev.service.FriendshipService;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.validation.Valid; import jakarta.validation.Valid;
@@ -215,35 +216,39 @@ public class FriendshipResource {
summary = "Récupérer la liste des amis", summary = "Récupérer la liste des amis",
description = "Retourne la liste des amis d'un utilisateur avec pagination") description = "Retourne la liste des amis d'un utilisateur avec pagination")
@APIResponses({ @APIResponses({
@APIResponse( @APIResponse(
responseCode = "200", responseCode = "200",
description = "Liste des amis récupérée avec succès", description = "Liste des amis récupérée avec succès",
content = content = @Content(
@Content( mediaType = MediaType.APPLICATION_JSON,
mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = FriendshipReadFriendDetailsResponseDTO.class))),
schema = @Schema(implementation = FriendshipReadFriendDetailsResponseDTO.class))), @APIResponse(responseCode = "404", description = "Utilisateur non trouvé"),
@APIResponse(responseCode = "404", description = "Utilisateur non trouvé"), @APIResponse(responseCode = "500", description = "Erreur lors de la récupération des amis")
@APIResponse(responseCode = "500", description = "Erreur lors de la récupération des amis")
}) })
public Response listFriends( public Response listFriends(
@PathParam("userId") UUID userId, @PathParam("userId") UUID userId,
@QueryParam("page") @DefaultValue("0") int page, @QueryParam("page") @DefaultValue("0") int page,
@QueryParam("size") @DefaultValue("10") int size) { @QueryParam("size") @DefaultValue("10") int size) {
logger.info( logger.info("[LOG] Reçu une demande pour récupérer la liste des amis de l'utilisateur avec l'ID : " + userId);
"[LOG] Reçu une demande pour récupérer la liste des amis de l'utilisateur avec l'ID : "
+ userId);
try { try {
List<FriendshipReadFriendDetailsResponseDTO> friendships = List<FriendshipReadFriendDetailsResponseDTO> friendships = friendshipService.listFriends(userId, page, size)
friendshipService.listFriends(userId, page, size); .stream()
logger.info("[LOG] Liste des amis récupérée avec succès."); .distinct() // Assure qu'il n'y a pas de doublons
.toList();
logger.info("[LOG] Liste des amis récupérée avec succès, nombre d'amis : " + friendships.size());
return Response.ok(friendships).build(); return Response.ok(friendships).build();
} catch (UserNotFoundException e) {
logger.error("[ERROR] Utilisateur non trouvé : " + e.getMessage());
return Response.status(Response.Status.NOT_FOUND)
.entity("{\"message\": \"Utilisateur non trouvé.\"}")
.build();
} catch (Exception e) { } catch (Exception e) {
logger.error( logger.error("[ERROR] Erreur lors de la récupération de la liste des amis : " + e.getMessage(), e);
"[ERROR] Erreur lors de la récupération de la liste des amis : " + e.getMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR) return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("{\"message\": \"Erreur lors de la récupération des amis.\"}") .entity("{\"message\": \"Erreur lors de la récupération des amis.\"}")
.build(); .build();
} }
} }

View File

@@ -16,7 +16,8 @@ import java.util.UUID;
/** /**
* Service de gestion des événements. * Service de gestion des événements.
* Ce service contient la logique métier pour la création, récupération et suppression des événements. * Ce service contient la logique métier pour la création, récupération, mise à jour et suppression des événements.
* Chaque méthode est loguée pour assurer une traçabilité exhaustive des actions effectuées.
*/ */
@ApplicationScoped @ApplicationScoped
public class EventService { public class EventService {
@@ -34,6 +35,7 @@ public class EventService {
* @return L'événement créé. * @return L'événement créé.
*/ */
public Events createEvent(EventCreateRequestDTO eventCreateRequestDTO, Users creator) { public Events createEvent(EventCreateRequestDTO eventCreateRequestDTO, Users creator) {
// Initialisation de l'entité Event avec les détails fournis
Events event = new Events(); Events event = new Events();
event.setTitle(eventCreateRequestDTO.getTitle()); event.setTitle(eventCreateRequestDTO.getTitle());
event.setDescription(eventCreateRequestDTO.getDescription()); event.setDescription(eventCreateRequestDTO.getDescription());
@@ -46,8 +48,9 @@ public class EventService {
event.setCreator(creator); event.setCreator(creator);
event.setStatus("ouvert"); event.setStatus("ouvert");
// Persiste l'événement dans la base de données
eventsRepository.persist(event); eventsRepository.persist(event);
logger.info("[LOG] Événement créé avec succès : {}", event.getTitle()); logger.info("[logger] Événement créé avec succès : {}", event.getTitle());
return event; return event;
} }
@@ -59,24 +62,28 @@ public class EventService {
* @throws EventNotFoundException Si l'événement n'est pas trouvé. * @throws EventNotFoundException Si l'événement n'est pas trouvé.
*/ */
public Events getEventById(UUID id) { public Events getEventById(UUID id) {
logger.info("[logger] Tentative de récupération de l'événement avec l'ID : {}", id);
Events event = eventsRepository.findById(id); Events event = eventsRepository.findById(id);
if (event == null) { if (event == null) {
logger.error("[ERROR] Événement non trouvé avec l'ID : {}", id); logger.error("[ERROR] Événement non trouvé avec l'ID : {}", id);
throw new EventNotFoundException(id); throw new EventNotFoundException(id);
} }
logger.info("[LOG] Événement trouvé avec l'ID : {}", id); logger.info("[logger] Événement trouvé avec l'ID : {}", id);
return event; return event;
} }
/** /**
* Récupère tous les événements après une date donnée. * Récupère tous les événements après une date donnée.
* *
* @param startDate La date de début de filtre. * @param startDate La date de début pour filtrer les événements.
* @return Une liste d'événements. * @return Une liste d'événements après cette date.
*/ */
public List<Events> getEventsAfterDate(LocalDateTime startDate) { public List<Events> getEventsAfterDate(LocalDateTime startDate) {
logger.info("[logger] Récupération des événements après la date : {}", startDate);
List<Events> events = eventsRepository.findEventsAfterDate(startDate); List<Events> events = eventsRepository.findEventsAfterDate(startDate);
logger.info("[LOG] Nombre d'événements trouvés après la date {} : {}", startDate, events.size()); logger.info("[logger] Nombre d'événements trouvés après la date {} : {}", startDate, events.size());
return events; return events;
} }
@@ -85,16 +92,17 @@ public class EventService {
* *
* @param id L'ID de l'événement à supprimer. * @param id L'ID de l'événement à supprimer.
* @return true si l'événement a été supprimé, false sinon. * @return true si l'événement a été supprimé, false sinon.
* @throws EventNotFoundException Si l'événement n'est pas trouvé.
*/ */
@Transactional @Transactional
public boolean deleteEvent(UUID id) { public boolean deleteEvent(UUID id) {
logger.info("[LOG] Tentative de suppression de l'événement avec l'ID : {}", id); logger.info("[logger] Tentative de suppression de l'événement avec l'ID : {}", id);
boolean deleted = eventsRepository.deleteById(id); boolean deleted = eventsRepository.deleteById(id);
if (deleted) { if (deleted) {
logger.info("[LOG] Événement avec l'ID {} supprimé avec succès.", id); logger.info("[logger] Événement avec l'ID {} supprimé avec succès.", id);
} else { } else {
logger.warn("[LOG] Échec de la suppression : événement avec l'ID {} introuvable.", id); logger.warn("[logger] Échec de la suppression : événement avec l'ID {} introuvable.", id);
throw new EventNotFoundException(id); throw new EventNotFoundException(id);
} }
return deleted; return deleted;
@@ -103,11 +111,14 @@ public class EventService {
/** /**
* Met à jour un événement dans le système. * Met à jour un événement dans le système.
* *
* @param event L'événement à mettre à jour. * @param event L'événement contenant les détails mis à jour.
* @return L'événement mis à jour. * @return L'événement mis à jour.
* @throws EventNotFoundException Si l'événement n'est pas trouvé.
*/ */
@Transactional @Transactional
public Events updateEvent(Events event) { public Events updateEvent(Events event) {
logger.info("[logger] Tentative de mise à jour de l'événement avec l'ID : {}", event.getId());
Events existingEvent = eventsRepository.findById(event.getId()); Events existingEvent = eventsRepository.findById(event.getId());
if (existingEvent == null) { if (existingEvent == null) {
logger.error("[ERROR] Événement non trouvé avec l'ID : {}", event.getId()); logger.error("[ERROR] Événement non trouvé avec l'ID : {}", event.getId());
@@ -125,8 +136,9 @@ public class EventService {
existingEvent.setImageUrl(event.getImageUrl()); existingEvent.setImageUrl(event.getImageUrl());
existingEvent.setStatus(event.getStatus()); existingEvent.setStatus(event.getStatus());
// Persiste les modifications dans la base de données
eventsRepository.persist(existingEvent); eventsRepository.persist(existingEvent);
logger.info("[LOG] Événement mis à jour avec succès : {}", existingEvent.getTitle()); logger.info("[logger] Événement mis à jour avec succès : {}", existingEvent.getTitle());
return existingEvent; return existingEvent;
} }
@@ -137,27 +149,36 @@ public class EventService {
* @return La liste des événements dans cette catégorie. * @return La liste des événements dans cette catégorie.
*/ */
public List<Events> findEventsByCategory(String category) { public List<Events> findEventsByCategory(String category) {
return eventsRepository.find("category", category).list(); logger.info("[logger] Récupération des événements dans la catégorie : {}", category);
List<Events> events = eventsRepository.find("category", category).list();
logger.info("[logger] Nombre d'événements trouvés dans la catégorie '{}' : {}", category, events.size());
return events;
} }
/** /**
* Recherche des événements par mot-clé. * Recherche des événements par mot-clé dans le titre ou la description.
* *
* @param keyword Le mot-clé à rechercher. * @param keyword Le mot-clé à rechercher.
* @return La liste des événements correspondant au mot-clé. * @return La liste des événements correspondant au mot-clé.
*/ */
public List<Events> searchEvents(String keyword) { public List<Events> searchEvents(String keyword) {
return eventsRepository.find("title like ?1 or description like ?1", "%" + keyword + "%").list(); logger.info("[logger] Recherche d'événements avec le mot-clé : {}", keyword);
List<Events> events = eventsRepository.find("title like ?1 or description like ?1", "%" + keyword + "%").list();
logger.info("[logger] Nombre d'événements trouvés pour le mot-clé '{}' : {}", keyword, events.size());
return events;
} }
/** /**
* Récupère les événements d'un utilisateur. * Récupère les événements auxquels un utilisateur participe.
* *
* @param user L'utilisateur pour lequel récupérer les événements. * @param user L'utilisateur pour lequel récupérer les événements.
* @return La liste des événements auxquels l'utilisateur participe. * @return La liste des événements auxquels l'utilisateur participe.
*/ */
public List<Events> findEventsByUser(Users user) { public List<Events> findEventsByUser(Users user) {
return eventsRepository.find("participants", user).list(); logger.info("[logger] Récupération des événements pour l'utilisateur avec l'ID : {}", user.getId());
List<Events> events = eventsRepository.find("participants", user).list();
logger.info("[logger] Nombre d'événements pour l'utilisateur avec l'ID {} : {}", user.getId(), events.size());
return events;
} }
/** /**
@@ -167,17 +188,98 @@ public class EventService {
* @return La liste des événements ayant ce statut. * @return La liste des événements ayant ce statut.
*/ */
public List<Events> findEventsByStatus(String status) { public List<Events> findEventsByStatus(String status) {
return eventsRepository.find("status", status).list(); logger.info("[logger] Récupération des événements avec le statut : {}", status);
List<Events> events = eventsRepository.find("status", status).list();
logger.info("[logger] Nombre d'événements avec le statut '{}' : {}", status, events.size());
return events;
} }
/** /**
* Récupère les événements entre deux dates. * Récupère les événements qui se déroulent entre deux dates spécifiques.
* *
* @param startDate La date de début. * @param startDate La date de début.
* @param endDate La date de fin. * @param endDate La date de fin.
* @return La liste des événements entre ces deux dates. * @return La liste des événements entre ces deux dates.
*/ */
public List<Events> findEventsBetweenDates(LocalDateTime startDate, LocalDateTime endDate) { public List<Events> findEventsBetweenDates(LocalDateTime startDate, LocalDateTime endDate) {
return eventsRepository.findEventsBetweenDates(startDate, endDate); logger.info("[logger] Récupération des événements entre les dates : {} et {}", startDate, endDate);
// Vérifie la validité des dates fournies
if (startDate == null || endDate == null || endDate.isBefore(startDate)) {
logger.error("[ERROR] Dates invalides fournies : startDate={}, endDate={}", startDate, endDate);
throw new IllegalArgumentException("Les dates sont invalides ou mal formatées.");
}
List<Events> events = eventsRepository.findEventsBetweenDates(startDate, endDate);
logger.info("[logger] Nombre d'événements trouvés entre les dates : {}", events.size());
return events;
}
/**
* Récupère les événements futurs.
*
* @return Une liste d'événements à venir.
*/
public List<Events> findUpcomingEvents() {
logger.info("[logger] Récupération des événements futurs.");
LocalDateTime now = LocalDateTime.now();
List<Events> events = eventsRepository.find("startDate > ?1", now).list();
logger.info("[logger] Nombre d'événements futurs trouvés : " + events.size());
return events;
}
/**
* Récupère les événements passés.
*
* @return Une liste d'événements passés.
*/
public List<Events> findPastEvents() {
logger.info("[logger] Récupération des événements passés.");
LocalDateTime now = LocalDateTime.now();
List<Events> events = eventsRepository.find("endDate < ?1", now).list();
logger.info("[logger] Nombre d'événements passés trouvés : " + events.size());
return events;
}
/**
* Récupère les événements par localisation.
*
* @param location La localisation des événements.
* @return La liste des événements situés à cette localisation.
*/
public List<Events> findEventsByLocation(String location) {
logger.info("[logger] Récupération des événements pour la localisation : " + location);
List<Events> events = eventsRepository.find("location", location).list();
logger.info("[logger] Nombre d'événements trouvés pour la localisation '" + location + "' : " + events.size());
return events;
}
/**
* Récupère les événements populaires en fonction du nombre de participants.
*
* @return Une liste d'événements populaires.
*/
public List<Events> findPopularEvents() {
logger.info("[logger] Récupération des événements populaires.");
List<Events> events = eventsRepository.listAll().stream()
.sorted((e1, e2) -> Integer.compare(e2.getNumberOfParticipants(), e1.getNumberOfParticipants()))
.limit(10)
.toList();
logger.info("[logger] Nombre d'événements populaires trouvés : " + events.size());
return events;
}
/**
* Recommande des événements pour un utilisateur spécifique.
*
* @param user L'utilisateur pour lequel recommander des événements.
* @return La liste des événements recommandés.
*/
public List<Events> recommendEventsForUser(Users user) {
logger.info("[logger] Recommandation d'événements pour l'utilisateur : " + user.getEmail());
List<Events> events = eventsRepository.find("category", user.getPreferredCategory()).list();
logger.info("[logger] Nombre d'événements recommandés pour l'utilisateur : " + events.size());
return events;
} }
} }

View File

@@ -1,23 +1,32 @@
package com.lions.dev.service; package com.lions.dev.service;
import org.jboss.logging.Logger; import com.lions.dev.repository.EventsRepository;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.io.IOException; import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import org.jboss.logging.Logger;
/** /**
* Service pour la gestion des fichiers uploadés. * Service pour la gestion des fichiers uploadés.
* Ce service permet de sauvegarder et gérer les fichiers uploadés sur le serveur. * Ce service permet de sauvegarder et gérer les fichiers uploadés sur le serveur.
*
* <p>Toutes les actions sont loguées pour assurer une traçabilité complète.
*/ */
@ApplicationScoped @ApplicationScoped
public class FileService { public class FileService {
private static final Logger LOG = Logger.getLogger(FileService.class); private static final Logger LOG = Logger.getLogger(FileService.class);
@Inject
EventsRepository eventsRepository;
/** /**
* Sauvegarde le fichier uploadé sur le serveur. * Sauvegarde le fichier uploadé sur le serveur, avec création du répertoire de destination
* si nécessaire et gestion des erreurs de manière contrôlée.
* *
* @param uploadedFilePath Le chemin temporaire du fichier uploadé. * @param uploadedFilePath Le chemin temporaire du fichier uploadé.
* @param destinationDir Le répertoire de destination où sauvegarder le fichier. * @param destinationDir Le répertoire de destination où sauvegarder le fichier.
@@ -26,10 +35,34 @@ public class FileService {
* @throws IOException Si une erreur survient lors de la sauvegarde. * @throws IOException Si une erreur survient lors de la sauvegarde.
*/ */
public Path saveFile(Path uploadedFilePath, String destinationDir, String fileName) throws IOException { public Path saveFile(Path uploadedFilePath, String destinationDir, String fileName) throws IOException {
Path destination = Paths.get(destinationDir, fileName); Path destinationPath = Paths.get(destinationDir, fileName);
Files.createDirectories(Paths.get(destinationDir)); // Crée le répertoire s'il n'existe pas LOG.info("[LOG] Tentative de sauvegarde du fichier vers : " + destinationPath);
Files.copy(uploadedFilePath, destination); // Copie le fichier vers sa destination
LOG.info("Fichier sauvegardé avec succès : " + destination); if (Files.notExists(uploadedFilePath)) {
return destination; LOG.error("[ERROR] Le fichier uploadé n'existe pas : " + uploadedFilePath);
throw new IOException("Le fichier uploadé n'existe pas : " + uploadedFilePath);
}
try {
Files.createDirectories(Paths.get(destinationDir));
LOG.info("[LOG] Répertoire de destination créé ou déjà existant : " + destinationDir);
} catch (IOException e) {
LOG.error("[ERROR] Impossible de créer le répertoire de destination : " + destinationDir, e);
throw new IOException("Impossible de créer le répertoire de destination : " + destinationDir, e);
}
try {
Files.copy(uploadedFilePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);
LOG.info("[LOG] Fichier sauvegardé avec succès à l'emplacement : " + destinationPath);
} catch (FileAlreadyExistsException e) {
LOG.warn("[WARNING] Le fichier existe déjà, il sera remplacé : " + destinationPath);
Files.copy(uploadedFilePath, destinationPath, StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
LOG.error("[ERROR] Erreur lors de la copie du fichier vers : " + destinationPath, e);
throw new IOException("Erreur lors de la sauvegarde du fichier : " + destinationPath, e);
}
return destinationPath;
} }
} }

View File

@@ -16,11 +16,11 @@ import com.lions.dev.repository.UsersRepository;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import jakarta.transaction.Transactional; import jakarta.transaction.Transactional;
import org.jboss.logging.Logger; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import org.jboss.logging.Logger;
/** /**
* Service pour gérer les relations d'amitié. * Service pour gérer les relations d'amitié.
@@ -196,25 +196,29 @@ public class FriendshipService {
throw new UserNotFoundException("Utilisateur introuvable."); throw new UserNotFoundException("Utilisateur introuvable.");
} }
// Récupérer les amitiés acceptées
List<Friendship> friendships = friendshipRepository.findFriendsByUser(user, page, size); List<Friendship> friendships = friendshipRepository.findFriendsByUser(user, page, size);
logger.info("[LOG] " + friendships.size() + " amis récupérés."); logger.info("[LOG] " + friendships.size() + " amis récupérés (avant filtrage des doublons).");
// Ajouter un log pour chaque amitié récupérée // Utilisation d'un ensemble pour stocker des clés uniques basées sur les IDs des amis
friendships.forEach(friendship -> logger.info("[LOG] Ami : " + friendship.getFriend().getEmail())); Set<String> uniqueFriendKeys = new HashSet<>();
return friendships.stream() return friendships.stream()
.map(friendship -> new FriendshipReadFriendDetailsResponseDTO( .map(friendship -> {
friendship.getUser().getId(), Users friend = friendship.getUser().equals(user) ? friendship.getFriend() : friendship.getUser();
friendship.getFriend().getId(), return new FriendshipReadFriendDetailsResponseDTO(
friendship.getFriend().getNom(), user.getId(),
friendship.getFriend().getPrenoms(), friend.getId(),
friendship.getFriend().getEmail(), friend.getNom(),
friendship.getStatus(), friend.getPrenoms(),
friendship.getCreatedAt(), friend.getEmail(),
friendship.getUpdatedAt() friendship.getStatus(),
)) friendship.getCreatedAt(),
.collect(Collectors.toList()); friendship.getUpdatedAt()
);
})
.filter(dto -> uniqueFriendKeys.add(dto.getUserId().toString() + "-" + dto.getFriendId().toString()))
.limit(size) // Limite la taille au paramètre 'size' requis
.toList();
} }
/** /**
@@ -234,6 +238,6 @@ public class FriendshipService {
List<Friendship> friendships = friendshipRepository.findByUserAndStatus(user, request.getStatus(), request.getPage() - 1, request.getSize()); List<Friendship> friendships = friendshipRepository.findByUserAndStatus(user, request.getStatus(), request.getPage() - 1, request.getSize());
logger.info("[LOG] " + friendships.size() + " demandes d'amitié récupérées."); logger.info("[LOG] " + friendships.size() + " demandes d'amitié récupérées.");
return friendships.stream().map(FriendshipReadStatusResponseDTO::new).collect(Collectors.toList()); return friendships.stream().map(FriendshipReadStatusResponseDTO::new).toList();
} }
} }