Refactor event handling and user management: Replace direct database calls with service layer methods for events, user profiles, and preferences, enhancing code organization and maintainability. Update API routes to utilize new services for event registration, feedback, and user statistics, ensuring a consistent approach across the application.
This commit is contained in:
179
services/events/event-feedback.service.ts
Normal file
179
services/events/event-feedback.service.ts
Normal file
@@ -0,0 +1,179 @@
|
||||
import { prisma } from "../database";
|
||||
import type { EventFeedback, Prisma } from "@/prisma/generated/prisma/client";
|
||||
import { ValidationError, NotFoundError } from "../errors";
|
||||
import { eventService } from "./event.service";
|
||||
|
||||
export interface CreateOrUpdateFeedbackInput {
|
||||
rating: number;
|
||||
comment?: string | null;
|
||||
}
|
||||
|
||||
export interface FeedbackStatistics {
|
||||
eventId: string;
|
||||
eventName: string;
|
||||
eventDate: Date | null;
|
||||
eventType: string | null;
|
||||
averageRating: number;
|
||||
feedbackCount: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service de gestion des feedbacks sur les événements
|
||||
*/
|
||||
export class EventFeedbackService {
|
||||
/**
|
||||
* Crée ou met à jour un feedback
|
||||
*/
|
||||
async createOrUpdateFeedback(
|
||||
userId: string,
|
||||
eventId: string,
|
||||
data: CreateOrUpdateFeedbackInput
|
||||
): Promise<EventFeedback> {
|
||||
return prisma.eventFeedback.upsert({
|
||||
where: {
|
||||
userId_eventId: {
|
||||
userId,
|
||||
eventId,
|
||||
},
|
||||
},
|
||||
update: {
|
||||
rating: data.rating,
|
||||
comment: data.comment || null,
|
||||
},
|
||||
create: {
|
||||
userId,
|
||||
eventId,
|
||||
rating: data.rating,
|
||||
comment: data.comment || null,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le feedback d'un utilisateur pour un événement
|
||||
*/
|
||||
async getUserFeedback(
|
||||
userId: string,
|
||||
eventId: string
|
||||
): Promise<EventFeedback | null> {
|
||||
return prisma.eventFeedback.findUnique({
|
||||
where: {
|
||||
userId_eventId: {
|
||||
userId,
|
||||
eventId,
|
||||
},
|
||||
},
|
||||
include: {
|
||||
event: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
date: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère tous les feedbacks (pour admin)
|
||||
*/
|
||||
async getAllFeedbacks(options?: {
|
||||
include?: Prisma.EventFeedbackInclude;
|
||||
orderBy?: Prisma.EventFeedbackOrderByWithRelationInput;
|
||||
}): Promise<EventFeedback[]> {
|
||||
return prisma.eventFeedback.findMany({
|
||||
include: options?.include || {
|
||||
event: {
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
date: true,
|
||||
type: true,
|
||||
},
|
||||
},
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: options?.orderBy || { createdAt: "desc" },
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère les statistiques de feedback par événement
|
||||
*/
|
||||
async getFeedbackStatistics(): Promise<FeedbackStatistics[]> {
|
||||
// Calculer les statistiques par événement
|
||||
const eventStats = await prisma.eventFeedback.groupBy({
|
||||
by: ["eventId"],
|
||||
_avg: {
|
||||
rating: true,
|
||||
},
|
||||
_count: {
|
||||
id: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Récupérer les détails des événements pour les stats
|
||||
const eventIds = eventStats.map((stat) => stat.eventId);
|
||||
const events = await prisma.event.findMany({
|
||||
where: {
|
||||
id: {
|
||||
in: eventIds,
|
||||
},
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
name: true,
|
||||
date: true,
|
||||
type: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Combiner les stats avec les détails des événements
|
||||
return eventStats.map((stat) => {
|
||||
const event = events.find((e) => e.id === stat.eventId);
|
||||
return {
|
||||
eventId: stat.eventId,
|
||||
eventName: event?.name || "Événement supprimé",
|
||||
eventDate: event?.date || null,
|
||||
eventType: event?.type || null,
|
||||
averageRating: stat._avg.rating || 0,
|
||||
feedbackCount: stat._count.id,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide et crée/met à jour un feedback avec toutes les règles métier
|
||||
*/
|
||||
async validateAndCreateFeedback(
|
||||
userId: string,
|
||||
eventId: string,
|
||||
data: { rating: number; comment?: string | null }
|
||||
): Promise<EventFeedback> {
|
||||
// Valider la note (1-5)
|
||||
if (!data.rating || data.rating < 1 || data.rating > 5) {
|
||||
throw new ValidationError("La note doit être entre 1 et 5", "rating");
|
||||
}
|
||||
|
||||
// Vérifier que l'événement existe
|
||||
const event = await eventService.getEventById(eventId);
|
||||
if (!event) {
|
||||
throw new NotFoundError("Événement");
|
||||
}
|
||||
|
||||
// Créer ou mettre à jour le feedback
|
||||
return this.createOrUpdateFeedback(userId, eventId, {
|
||||
rating: data.rating,
|
||||
comment: data.comment || null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const eventFeedbackService = new EventFeedbackService();
|
||||
Reference in New Issue
Block a user