Refactoring

This commit is contained in:
dahoud
2026-01-31 16:54:46 +00:00
parent ce89face73
commit 9dc9ca591c
85 changed files with 2643 additions and 381 deletions

View File

@@ -0,0 +1,171 @@
package com.lions.dev.config;
import com.lions.dev.entity.events.Events;
import com.lions.dev.entity.establishment.Establishment;
import com.lions.dev.entity.establishment.EstablishmentSubscription;
import com.lions.dev.entity.users.Users;
import com.lions.dev.repository.EstablishmentRepository;
import com.lions.dev.repository.EstablishmentSubscriptionRepository;
import com.lions.dev.repository.EventsRepository;
import com.lions.dev.repository.PasswordResetTokenRepository;
import com.lions.dev.repository.StoryRepository;
import com.lions.dev.service.EmailService;
import com.lions.dev.service.NotificationService;
import io.quarkus.scheduler.Scheduled;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import org.jboss.logging.Logger;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Set;
/**
* Jobs planifiés (Quarkus Scheduler) pour :
* - Nettoyage des stories expirées (24h)
* - Nettoyage des tokens de reset password expirés
* - Expiration des abonnements établissements
* - Désactivation des établissements non payés
* - Rappels d'événements (J-1, H-1)
*/
@ApplicationScoped
public class ScheduledJobs {
private static final Logger LOG = Logger.getLogger(ScheduledJobs.class);
@Inject
StoryRepository storyRepository;
@Inject
PasswordResetTokenRepository passwordResetTokenRepository;
@Inject
EstablishmentSubscriptionRepository subscriptionRepository;
@Inject
EstablishmentRepository establishmentRepository;
@Inject
EventsRepository eventsRepository;
@Inject
NotificationService notificationService;
@Inject
EmailService emailService;
/** Nettoyage des stories expirées : toutes les heures. */
@Scheduled(cron = "0 0 * * * ?")
@Transactional
public void deactivateExpiredStories() {
int count = storyRepository.deactivateExpiredStories();
if (count > 0) {
LOG.info("[ScheduledJobs] Stories expirées désactivées : " + count);
}
}
/** Nettoyage des tokens de reset password expirés : tous les jours à 3h. */
@Scheduled(cron = "0 0 3 * * ?")
@Transactional
public void deleteExpiredPasswordResetTokens() {
long count = passwordResetTokenRepository.deleteExpiredTokens();
if (count > 0) {
LOG.info("[ScheduledJobs] Tokens de reset password supprimés : " + count);
}
}
/** Expiration des abonnements et désactivation des établissements non payés : toutes les heures. */
@Scheduled(cron = "0 5 * * * ?")
@Transactional
public void expireSubscriptionsAndDisableEstablishments() {
List<EstablishmentSubscription> expired = subscriptionRepository.findExpiredActiveSubscriptions();
for (EstablishmentSubscription sub : expired) {
sub.setStatus(EstablishmentSubscription.STATUS_EXPIRED);
subscriptionRepository.persist(sub);
Establishment est = establishmentRepository.findById(sub.getEstablishmentId());
if (est != null && Boolean.TRUE.equals(est.getIsActive())) {
est.setIsActive(false);
establishmentRepository.persist(est);
LOG.info("[ScheduledJobs] Établissement désactivé (abonnement expiré) : " + est.getId());
}
}
if (!expired.isEmpty()) {
LOG.info("[ScheduledJobs] Abonnements expirés traités : " + expired.size());
}
}
/** Rappels d'événements J-1 (dans ~24h) et H-1 (dans ~1h) : toutes les 15 minutes. */
@Scheduled(cron = "0 */15 * * * ?")
@Transactional
public void sendEventReminders() {
LocalDateTime now = LocalDateTime.now();
// Fenêtre J-1 : début entre 23h30 et 24h30
LocalDateTime j1From = now.plus(23, ChronoUnit.HOURS).plus(30, ChronoUnit.MINUTES);
LocalDateTime j1To = now.plus(24, ChronoUnit.HOURS).plus(30, ChronoUnit.MINUTES);
List<Events> eventsJ1 = eventsRepository.findEventsStartingBetween(j1From, j1To);
for (Events event : eventsJ1) {
sendReminderToParticipants(event, "J-1", "demain");
}
// Fenêtre H-1 : début entre 50 min et 1h10
LocalDateTime h1From = now.plus(50, ChronoUnit.MINUTES);
LocalDateTime h1To = now.plus(70, ChronoUnit.MINUTES);
List<Events> eventsH1 = eventsRepository.findEventsStartingBetween(h1From, h1To);
for (Events event : eventsH1) {
sendReminderToParticipants(event, "H-1", "dans 1 heure");
}
}
/** Avertissement expiration abonnement (J-3) : email au manager. */
@Scheduled(cron = "0 0 9 * * ?")
@Transactional
public void sendSubscriptionExpirationWarningEmails() {
LocalDateTime now = LocalDateTime.now();
LocalDateTime in3DaysStart = now.plusDays(3);
LocalDateTime in3DaysEnd = now.plusDays(3).plusHours(23).plusMinutes(59);
List<EstablishmentSubscription> expiring = subscriptionRepository.findActiveSubscriptionsExpiringBetween(in3DaysStart, in3DaysEnd);
for (EstablishmentSubscription sub : expiring) {
Establishment est = establishmentRepository.findById(sub.getEstablishmentId());
if (est == null) continue;
Users manager = est.getManager();
if (manager == null || manager.getEmail() == null) continue;
try {
emailService.sendSubscriptionExpirationWarningEmail(
manager.getEmail(),
manager.getFirstName(),
est.getName(),
sub.getExpiresAt()
);
} catch (Exception e) {
LOG.warn("[ScheduledJobs] Email expiration abonnement échoué pour " + est.getId() + ": " + e.getMessage());
}
}
if (!expiring.isEmpty()) {
LOG.info("[ScheduledJobs] Emails avertissement expiration envoyés : " + expiring.size());
}
}
private void sendReminderToParticipants(Events event, String reminderType, String whenText) {
Set<Users> participants = event.getParticipants();
if (participants == null) return;
Users creator = event.getCreator();
String title = "Rappel événement " + reminderType + " : " + event.getTitle();
String message = "L'événement « " + event.getTitle() + " » commence " + whenText + ".";
for (Users participant : participants) {
if (participant == null || participant.getId() == null) continue;
try {
notificationService.createNotification(title, message, "reminder", participant.getId(), event.getId());
} catch (Exception e) {
LOG.warn("[ScheduledJobs] Impossible de créer rappel pour participant " + participant.getId() + ": " + e.getMessage());
}
}
if (creator != null && creator.getId() != null && (participants.isEmpty() || !participants.stream().anyMatch(p -> p.getId().equals(creator.getId())))) {
try {
notificationService.createNotification(title, message, "reminder", creator.getId(), event.getId());
} catch (Exception e) {
LOG.warn("[ScheduledJobs] Impossible de créer rappel pour créateur: " + e.getMessage());
}
}
}
}