espace-paie-odentas/app/api/staff/amendments/create/route.ts
odentas 90d9f6b56f feat: Ajouter support des avenants d'annulation avec envoi à PDFMonkey
- Modifier NouvelAvenantPageClient pour gérer type_avenant annulation
- Désactiver la sélection d'éléments pour les annulations
- Ajouter message d'information pour les avenants d'annulation
- Adapter l'API generate-pdf pour envoyer annulation: Oui à PDFMonkey
- Modifier l'API create pour accepter les annulations sans éléments requis
- Ne pas mettre à jour le contrat pour les annulations
2025-10-24 19:50:30 +02:00

203 lines
6.6 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
export const dynamic = "force-dynamic";
export async function POST(request: NextRequest) {
try {
const supabase = createRouteHandlerClient({ cookies });
// Vérifier l'authentification
const { data: { user }, error: authError } = await supabase.auth.getUser();
if (authError || !user) {
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
}
// Vérifier que l'utilisateur est staff
const { data: staffUser } = await supabase
.from("staff_users")
.select("is_staff")
.eq("user_id", user.id)
.maybeSingle();
if (!staffUser?.is_staff) {
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
}
// Récupérer les données de l'avenant
const body = await request.json();
const {
contract_id,
date_effet,
date_signature,
type_avenant = "modification",
motif_avenant,
elements_avenantes,
objet_data,
duree_data,
lieu_horaire_data,
remuneration_data,
pdf_url,
pdf_s3_key,
} = body;
if (!contract_id || !date_effet) {
return NextResponse.json(
{ error: "Données manquantes" },
{ status: 400 }
);
}
// Pour les modifications, au moins un élément doit être sélectionné
// Pour les annulations, aucun élément n'est requis
if (type_avenant === "modification" && (!elements_avenantes || elements_avenantes.length === 0)) {
return NextResponse.json(
{ error: "Au moins un élément doit être sélectionné pour une modification" },
{ status: 400 }
);
}
// Récupérer le contrat pour validation et numérotation
const { data: contract, error: contractError } = await supabase
.from("cddu_contracts")
.select("id, contract_number, org_id")
.eq("id", contract_id)
.single();
if (contractError || !contract) {
return NextResponse.json(
{ error: "Contrat non trouvé" },
{ status: 404 }
);
}
// Compter le nombre d'avenants existants pour cette organisation
// pour avoir une numérotation par client
const { count } = await supabase
.from("avenants")
.select("contract_id, cddu_contracts!inner(org_id)", { count: "exact", head: true })
.eq("cddu_contracts.org_id", contract.org_id);
const numeroAvenant = `AVE-${String((count || 0) + 1).padStart(3, "0")}`;
// Créer l'avenant
const { data: avenant, error: avenantError } = await supabase
.from("avenants")
.insert({
contract_id,
numero_avenant: numeroAvenant,
date_avenant: date_signature || date_effet,
date_effet,
type_avenant,
motif_avenant: motif_avenant || null,
elements_avenantes: elements_avenantes || [],
objet_data: objet_data || null,
duree_data: duree_data || null,
lieu_horaire_data: lieu_horaire_data || null,
remuneration_data: remuneration_data || null,
pdf_url: pdf_url || null,
pdf_s3_key: pdf_s3_key || null,
statut: "draft",
created_by: user.id,
})
.select()
.single();
if (avenantError) {
console.error("Erreur création avenant:", avenantError);
return NextResponse.json(
{ error: "Erreur lors de la création de l'avenant" },
{ status: 500 }
);
}
// Mettre à jour le contrat avec les nouvelles données
// Pour les annulations, on ne met pas à jour le contrat
const updateData: any = {};
if (type_avenant === "modification") {
if (elements_avenantes.includes("objet") && objet_data) {
if (objet_data.profession_code && objet_data.profession_label) {
updateData.profession = `${objet_data.profession_code} - ${objet_data.profession_label}`;
}
if (objet_data.production_name) {
updateData.production_name = objet_data.production_name;
}
if (objet_data.production_numero_objet) {
updateData.numero_objet = objet_data.production_numero_objet;
}
}
if (elements_avenantes.includes("duree") && duree_data) {
if (duree_data.date_debut) {
updateData.start_date = duree_data.date_debut;
}
if (duree_data.date_fin) {
updateData.end_date = duree_data.date_fin;
}
if (duree_data.nb_representations !== undefined) {
updateData.cachets_representations = duree_data.nb_representations;
}
if (duree_data.nb_repetitions !== undefined) {
updateData.services_repetitions = duree_data.nb_repetitions;
}
if (duree_data.nb_heures !== undefined) {
updateData.nombre_d_heures = duree_data.nb_heures;
}
if (duree_data.dates_representations) {
updateData.jours_representations = duree_data.dates_representations;
}
if (duree_data.dates_repetitions) {
updateData.jours_repetitions = duree_data.dates_repetitions;
}
if (duree_data.jours_travail) {
updateData.jours_travail = duree_data.jours_travail;
}
}
if (elements_avenantes.includes("lieu_horaire") && lieu_horaire_data) {
if (lieu_horaire_data.lieu) {
updateData.lieu_travail = lieu_horaire_data.lieu;
}
}
if (elements_avenantes.includes("remuneration") && remuneration_data) {
if (remuneration_data.gross_pay !== undefined) {
updateData.gross_pay = remuneration_data.gross_pay;
}
if (remuneration_data.precisions_salaire) {
updateData.precisions_salaire = remuneration_data.precisions_salaire;
}
if (remuneration_data.type_salaire) {
updateData.type_salaire = remuneration_data.type_salaire;
}
}
} // Fin du if (type_avenant === "modification")
// Mettre à jour le contrat si des données ont été modifiées
if (Object.keys(updateData).length > 0) {
const { error: updateError } = await supabase
.from("cddu_contracts")
.update(updateData)
.eq("id", contract_id);
if (updateError) {
console.error("Erreur mise à jour contrat:", updateError);
// On ne renvoie pas d'erreur car l'avenant est créé
}
}
return NextResponse.json({
success: true,
avenant,
message: "Avenant créé avec succès",
});
} catch (error) {
console.error("Erreur API create amendment:", error);
return NextResponse.json(
{ error: "Erreur serveur" },
{ status: 500 }
);
}
}