201 lines
5.1 KiB
TypeScript
201 lines
5.1 KiB
TypeScript
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<EventRegistration> {
|
|
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<void> {
|
|
// 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<boolean> {
|
|
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<EventRegistration | null> {
|
|
return prisma.eventRegistration.findUnique({
|
|
where: {
|
|
userId_eventId: {
|
|
userId,
|
|
eventId,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Récupère toutes les inscriptions d'un utilisateur
|
|
*/
|
|
async getUserRegistrations(userId: string): Promise<EventRegistration[]> {
|
|
return prisma.eventRegistration.findMany({
|
|
where: {
|
|
userId,
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Récupère le nombre d'inscriptions pour un événement
|
|
*/
|
|
async getEventRegistrationsCount(eventId: string): Promise<number> {
|
|
const count = await prisma.eventRegistration.count({
|
|
where: {
|
|
eventId,
|
|
},
|
|
});
|
|
return count;
|
|
}
|
|
|
|
/**
|
|
* Récupère tous les inscrits d'un événement avec leurs informations
|
|
*/
|
|
async getEventRegistrations(eventId: string) {
|
|
return prisma.eventRegistration.findMany({
|
|
where: {
|
|
eventId,
|
|
},
|
|
include: {
|
|
user: {
|
|
select: {
|
|
id: true,
|
|
username: true,
|
|
avatar: true,
|
|
score: true,
|
|
level: true,
|
|
hp: true,
|
|
maxHp: true,
|
|
xp: true,
|
|
maxXp: true,
|
|
},
|
|
},
|
|
},
|
|
orderBy: {
|
|
createdAt: "asc",
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Valide et inscrit un utilisateur à un événement avec toutes les règles métier
|
|
*/
|
|
async validateAndRegisterUser(
|
|
userId: string,
|
|
eventId: string
|
|
): Promise<EventRegistration> {
|
|
// 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();
|