Files
MAD-Platform/app/api/budget/route.ts

162 lines
5.9 KiB
TypeScript
Raw Normal View History

2026-02-15 15:05:59 +01:00
import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';
import { getCurrentUser } from '@/lib/auth';
// GET - Liste tous les prescripteurs avec budgets, consommé et restant
// PATCH - Met à jour le budget d'un prescripteur (body: { prescripteurValue, montant })
export async function GET() {
try {
const user = await getCurrentUser();
if (!user) {
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
}
const [prescripteurs, budgets, participations] = await Promise.all([
prisma.adherentOption.findMany({
where: { type: 'prescripteur' },
orderBy: [{ order: 'asc' }, { value: 'asc' }],
}),
prisma.prescripteurBudget.findMany(),
prisma.participationFinanciere.findMany({
include: {
adherent: { select: { prescripteur: true, prenom: true, nom: true } },
trajet: { select: { date: true } },
},
orderBy: { createdAt: 'desc' },
}),
]);
const consomméMap = new Map<string, number>();
const historiqueMap = new Map<string, Array<{ id: string; date: string; adherentNom: string; montant: number }>>();
for (const p of participations) {
const prescripteur = p.adherent.prescripteur;
if (!prescripteur) continue;
const montant = p.montant ?? 0;
if (['envoye', 'paye'].includes(p.statut)) {
consomméMap.set(prescripteur, (consomméMap.get(prescripteur) ?? 0) + montant);
}
const hist = historiqueMap.get(prescripteur) ?? [];
hist.push({
id: p.id,
date: p.trajet.date.toISOString(),
adherentNom: `${p.adherent.prenom} ${p.adherent.nom}`,
montant,
});
historiqueMap.set(prescripteur, hist);
}
const budgetMap = new Map(budgets.map((b) => [b.prescripteurValue, { montant: b.montant, ajustementConsomme: b.ajustementConsomme ?? 0 }]));
const items = prescripteurs.map((p) => {
const budgetData = budgetMap.get(p.value);
const montant = budgetData?.montant ?? 0;
const ajustementConsomme = budgetData?.ajustementConsomme ?? 0;
const consomméCalculé = consomméMap.get(p.value) ?? 0;
const consommé = consomméCalculé + ajustementConsomme;
const restant = Math.max(0, montant - consommé);
const historique = (historiqueMap.get(p.value) ?? []).sort(
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
);
return {
id: p.id,
value: p.value,
montant,
consommé,
restant,
ajustementConsomme,
historique,
};
});
const totalAlloue = items.reduce((s, i) => s + i.montant, 0);
const totalConsomme = items.reduce((s, i) => s + i.consommé, 0);
const totalRestant = Math.max(0, totalAlloue - totalConsomme);
return NextResponse.json({
global: { totalAlloue, totalConsomme, totalRestant },
prescripteurs: items,
});
} catch (error) {
console.error('Erreur lors de la récupération des budgets:', error);
return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 });
}
}
export async function PATCH(request: NextRequest) {
try {
const user = await getCurrentUser();
if (!user) {
return NextResponse.json({ error: 'Non autorisé' }, { status: 401 });
}
const body = await request.json();
const { prescripteurValue, montant: montantRaw, montantToAdd, rectifier, ajustementConsomme: ajRaw } = body;
if (!prescripteurValue || typeof prescripteurValue !== 'string') {
return NextResponse.json({ error: 'Prescripteur requis' }, { status: 400 });
}
const exists = await prisma.adherentOption.findFirst({
where: { type: 'prescripteur', value: prescripteurValue },
});
if (!exists) {
return NextResponse.json({ error: 'Prescripteur non trouvé' }, { status: 404 });
}
const existing = await prisma.prescripteurBudget.findUnique({
where: { prescripteurValue },
});
let montantFinal: number;
let ajustementFinal: number | undefined;
if (rectifier) {
const montant = typeof montantRaw === 'number' ? montantRaw : parseFloat(String(montantRaw ?? 0).replace(',', '.'));
if (isNaN(montant) || montant < 0) {
return NextResponse.json({ error: 'Budget invalide' }, { status: 400 });
}
montantFinal = montant;
const aj = typeof ajRaw === 'number' ? ajRaw : parseFloat(String(ajRaw ?? 0).replace(',', '.'));
ajustementFinal = isNaN(aj) ? 0 : aj;
} else if (montantToAdd !== undefined && montantToAdd !== null) {
const toAdd = typeof montantToAdd === 'number' ? montantToAdd : parseFloat(String(montantToAdd).replace(',', '.'));
if (isNaN(toAdd) || toAdd <= 0) {
return NextResponse.json({ error: 'Montant à ajouter invalide' }, { status: 400 });
}
montantFinal = (existing?.montant ?? 0) + toAdd;
} else {
const montant = typeof montantRaw === 'number' ? montantRaw : parseFloat(String(montantRaw ?? 0).replace(',', '.'));
if (isNaN(montant) || montant < 0) {
return NextResponse.json({ error: 'Montant invalide' }, { status: 400 });
}
montantFinal = montant;
}
const updateData: { montant: number; ajustementConsomme?: number } = { montant: montantFinal };
if (ajustementFinal !== undefined) {
updateData.ajustementConsomme = ajustementFinal;
}
const createData: { prescripteurValue: string; montant: number; ajustementConsomme?: number } = {
prescripteurValue,
montant: montantFinal,
};
if (ajustementFinal !== undefined) {
createData.ajustementConsomme = ajustementFinal;
}
const budget = await prisma.prescripteurBudget.upsert({
where: { prescripteurValue },
update: updateData,
create: createData,
});
return NextResponse.json(budget);
} catch (error) {
console.error('Erreur lors de la mise à jour du budget:', error);
return NextResponse.json({ error: 'Erreur serveur' }, { status: 500 });
}
}