import { prisma } from "../database"; import type { EventRegistration } from "@/prisma/generated/prisma/client"; import { ValidationError, NotFoundError, ConflictError } from "../errors"; import { eventService } from "./event.service"; import { calculateEventStatus } from "@/lib/eventStatus"; import { sitePreferencesService } from "../preferences/site-preferences.service"; /** * Service de gestion des inscriptions aux événements */ export class EventRegistrationService { /** * Inscrit un utilisateur à un événement */ async registerUserToEvent( userId: string, eventId: string ): Promise { return prisma.eventRegistration.create({ data: { userId, eventId, }, }); } /** * Désinscrit un utilisateur d'un événement et retire les points attribués */ async unregisterUserFromEvent( userId: string, eventId: string ): Promise { // Vérifier que l'utilisateur est bien inscrit avant de retirer les points const isRegistered = await this.checkUserRegistration(userId, eventId); if (!isRegistered) { return; // Pas d'inscription, rien à faire } // Récupérer les points à retirer depuis les préférences du site const sitePreferences = await sitePreferencesService.getOrCreateSitePreferences(); const pointsToRemove = sitePreferences.eventRegistrationPoints || 100; // Supprimer l'inscription et retirer les points en parallèle await Promise.all([ prisma.eventRegistration.deleteMany({ where: { userId, eventId, }, }), prisma.user.update({ where: { id: userId }, data: { score: { decrement: pointsToRemove, }, }, }), ]); } /** * Vérifie si un utilisateur est inscrit à un événement */ async checkUserRegistration( userId: string, eventId: string ): Promise { const registration = await prisma.eventRegistration.findUnique({ where: { userId_eventId: { userId, eventId, }, }, }); return !!registration; } /** * Récupère l'inscription d'un utilisateur à un événement */ async getUserRegistration( userId: string, eventId: string ): Promise { return prisma.eventRegistration.findUnique({ where: { userId_eventId: { userId, eventId, }, }, }); } /** * Récupère toutes les inscriptions d'un utilisateur */ async getUserRegistrations(userId: string): Promise { return prisma.eventRegistration.findMany({ where: { userId, }, }); } /** * Récupère le nombre d'inscriptions pour un événement */ async getEventRegistrationsCount(eventId: string): Promise { const count = await prisma.eventRegistration.count({ where: { eventId, }, }); return count; } /** * Valide et inscrit un utilisateur à un événement avec toutes les règles métier */ async validateAndRegisterUser( userId: string, eventId: string ): Promise { // Vérifier que l'événement existe const event = await eventService.getEventById(eventId); if (!event) { throw new NotFoundError("Événement"); } // Vérifier que l'événement est à venir const eventStatus = calculateEventStatus(event.date); if (eventStatus !== "UPCOMING") { throw new ValidationError( "Vous ne pouvez vous inscrire qu'aux événements à venir" ); } // Vérifier si l'utilisateur est déjà inscrit const isRegistered = await this.checkUserRegistration(userId, eventId); if (isRegistered) { throw new ConflictError("Vous êtes déjà inscrit à cet événement"); } // Récupérer les points à attribuer depuis les préférences du site const sitePreferences = await sitePreferencesService.getOrCreateSitePreferences(); const pointsToAward = sitePreferences.eventRegistrationPoints || 100; // Créer l'inscription et attribuer les points en parallèle const [registration] = await Promise.all([ this.registerUserToEvent(userId, eventId), prisma.user.update({ where: { id: userId }, data: { score: { increment: pointsToAward, }, }, }), ]); return registration; } } export const eventRegistrationService = new EventRegistrationService();