Files
got-gaming/services/events/event-registration.service.ts

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();