Files
lionsdev-client-impl-quarkus/src/main/java/dev/lions/services/ProjectService.java

241 lines
7.0 KiB
Java

package dev.lions.services;
import dev.lions.events.ProjectUpdateEvent;
import dev.lions.exceptions.BusinessException;
import dev.lions.models.Project;
import dev.lions.models.Testimonial;
import dev.lions.repositories.ProjectRepository;
import dev.lions.utils.ImageProcessor;
import dev.lions.config.ApplicationConfig;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Event;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.util.Set;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.Optional;
import java.time.LocalDateTime;
/**
* Service gérant la logique métier des projets.
* Cette classe assure la gestion complète du cycle de vie des projets,
* incluant leur création, mise à jour, recherche et validation.
*/
@Slf4j
@ApplicationScoped
@Builder
public class ProjectService {
@Inject
ProjectRepository projectRepository;
@Inject
ImageProcessor imageProcessor;
@Inject
ApplicationConfig config;
@Inject
Event<ProjectUpdateEvent> projectUpdateEvent;
/**
* Crée un nouveau projet avec son image associée.
*
* @param project Données du projet
* @param imageData Image du projet en bytes
* @return Projet créé
*/
@Transactional
public Project createProject(@Valid @NotNull Project project, byte[] imageData) {
log.info("Création d'un nouveau projet : {}", project.getTitle());
try {
validateProject(project);
processProjectImage(project, imageData);
Project savedProject = projectRepository.save(project);
notifyProjectCreation(savedProject);
log.info("Projet créé avec succès - ID: {}", savedProject.getId());
return savedProject;
} catch (BusinessException be) {
log.warn("Validation échouée pour le projet", be);
throw be;
} catch (Exception e) {
log.error("Erreur lors de la création du projet", e);
throw new BusinessException("Impossible de créer le projet", e);
}
}
/**
* Met à jour un projet existant.
*
* @param project Projet à mettre à jour
* @param imageData Nouvelle image optionnelle
* @return Projet mis à jour
*/
@Transactional
public Project updateProject(@Valid @NotNull Project project, byte[] imageData) {
log.info("Mise à jour du projet : {}", project.getId());
try {
validateProject(project);
if (imageData != null) {
processProjectImage(project, imageData);
}
Project updatedProject = projectRepository.update(project);
notifyProjectUpdate(updatedProject);
log.info("Projet mis à jour avec succès - ID: {}", updatedProject.getId());
return updatedProject;
} catch (Exception e) {
log.error("Erreur lors de la mise à jour du projet", e);
throw new BusinessException("Impossible de mettre à jour le projet", e);
}
}
/**
* Traite et stocke l'image du projet.
*/
private void processProjectImage(Project project, byte[] imageData) {
if (imageData == null || imageData.length == 0) {
throw new BusinessException("L'image du projet est requise");
}
String imageUrl = imageProcessor.processAndStoreProjectImage(
imageData,
project.getTitle(),
config.getImageStoragePath()
);
project.setImageUrl(imageUrl);
}
/**
* Récupère un projet par son identifiant.
*/
public Optional<Project> findById(@NotNull String projectId) {
log.debug("Recherche du projet : {}", projectId);
return projectRepository.findById(projectId);
}
/**
* Vérifie l'existence d'un projet.
*/
public boolean existsById(@NotNull String projectId) {
return projectRepository.existsById(projectId);
}
/**
* Récupère les projets filtrés par tag.
*/
public List<Project> getFilteredProjects(String filter) {
log.debug("Filtrage des projets avec le critère : {}", filter);
if ("all".equalsIgnoreCase(filter)) {
return projectRepository.findAll();
}
return projectRepository.findByTags(Set.of(filter.toLowerCase()));
}
/**
* Récupère les projets mis en avant.
*/
public List<Project> getFeaturedProjects() {
log.debug("Récupération des projets mis en avant");
return projectRepository.findByFeatured(true);
}
/**
* Récupère les projets récents.
*/
public List<Project> getRecentProjects(int limit) {
log.debug("Récupération des {} projets les plus récents", limit);
return projectRepository.findRecentProjects(limit);
}
/**
* Récupère le nombre total de projets.
*/
public long getProjectCount() {
log.debug("Récupération du nombre total de projets");
return projectRepository.count();
}
/**
* Récupère les témoignages mis en avant.
*/
public List<Testimonial> getFeaturedTestimonials() {
log.debug("Récupération des témoignages mis en avant");
return projectRepository.findByFeatured(true).stream()
.filter(project -> !project.getTestimonials().isEmpty())
.map(this::createTestimonialFromProject)
.limit(3)
.toList();
}
/**
* Valide les données d'un projet.
*/
private void validateProject(Project project) {
if (project.getTitle() == null || project.getTitle().trim().isEmpty()) {
throw new BusinessException("Le titre du projet est requis");
}
if (project.getDescription() == null || project.getDescription().trim().isEmpty()) {
throw new BusinessException("La description du projet est requise");
}
if (project.getShortDescription() == null ||
project.getShortDescription().trim().isEmpty()) {
throw new BusinessException("La description courte du projet est requise");
}
}
/**
* Crée un témoignage à partir d'un projet.
*/
private Testimonial createTestimonialFromProject(Project project) {
return Testimonial.builder()
.clientName(project.getClientName())
.content(project.getTestimonials().get(0))
.projectTitle(project.getTitle())
.date(project.getCompletionDate())
.build();
}
/**
* Notifie la création d'un projet.
*/
private void notifyProjectCreation(Project project) {
projectUpdateEvent.fire(new ProjectUpdateEvent(
project.getId(),
"CREATE",
LocalDateTime.now()
));
}
/**
* Notifie la mise à jour d'un projet.
*/
private void notifyProjectUpdate(Project project) {
projectUpdateEvent.fire(new ProjectUpdateEvent(
project.getId(),
"UPDATE",
LocalDateTime.now()
));
}
}