Files
2026-04-18 22:10:19 +02:00

116 lines
3.8 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import prisma from '@/lib/prisma';
export async function POST(
req: NextRequest,
context: { params: Promise<{ id: string }> }
) {
const { id: paramId } = await context.params;
const userId = req.headers.get('x-user-id');
if (!userId) {
return NextResponse.json({ error: 'Utilisateur non identifié' }, { status: 401 });
}
try {
const { value, comment } = await req.json();
if (!value || value < 1 || value > 5) {
return NextResponse.json({ error: 'Valeur de note invalide (1-5)' }, { status: 400 });
}
// 1. Resolve actual Business UUID if paramId is a slug
const business = await prisma.business.findFirst({
where: {
OR: [
{ id: paramId },
{ slug: paramId }
]
},
select: { id: true }
});
if (!business) {
return NextResponse.json({ error: "Les données de démonstration ne peuvent pas recevoir d'avis. Veuillez créer votre propre entreprise pour tester." }, { status: 403 });
}
const businessId = business.id;
const ownerId = (business as any).ownerId;
// 2. Security: Don't allow owner to rate themselves
if (userId === ownerId) {
return NextResponse.json({ error: "Vous ne pouvez pas noter votre propre entreprise." }, { status: 403 });
}
// 3. Fetch existing rating to check rules
const existingRating = await prisma.rating.findUnique({
where: {
userId_businessId: {
userId,
businessId
}
}
});
if (existingRating) {
// Rule: Score can only be re-evaluated UPWARDS
if (value < existingRating.value) {
return NextResponse.json({
error: `La note ne peut être réévaluée qu'à la hausse. Votre note actuelle est de ${existingRating.value} étoiles.`
}, { status: 400 });
}
// Rule: Comment is IMMUTABLE once set
// We only update the value. If the comment was empty, we can set it once.
await prisma.rating.update({
where: { id: existingRating.id },
data: {
value,
comment: existingRating.comment ? undefined : comment, // Only set if it was null
status: 'PENDING' // Reset to pending for re-moderation
}
});
} else {
// 4. Create new rating
await prisma.rating.create({
data: {
value,
comment,
userId,
businessId,
status: 'PENDING'
}
});
}
// 3. Aggregate all ratings for this business
const stats = await prisma.rating.aggregate({
where: { businessId },
_avg: { value: true },
_count: { value: true }
});
const newRating = stats._avg.value || 0;
const newRatingCount = stats._count.value || 0;
// 4. Update the business
const updatedBusiness = await prisma.business.update({
where: { id: businessId },
data: {
rating: newRating,
ratingCount: newRatingCount
}
});
return NextResponse.json({
rating: updatedBusiness.rating,
ratingCount: updatedBusiness.ratingCount,
message: 'Vote enregistré avec succès'
});
} catch (error: any) {
console.error('Error rating business:', error);
return NextResponse.json({ error: 'Erreur serveur lors du vote' }, { status: 500 });
}
}