198 lines
6.4 KiB
TypeScript
198 lines
6.4 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
|
|
import { cookies } from "next/headers";
|
|
import { sendUniversalEmailV2 } from "@/lib/emailTemplateService";
|
|
|
|
export async function POST(
|
|
request: NextRequest,
|
|
{ params }: { params: { id: string } }
|
|
) {
|
|
try {
|
|
const supabase = createRouteHandlerClient({ cookies });
|
|
|
|
// 1) Authentification
|
|
const {
|
|
data: { session },
|
|
error: sessionError,
|
|
} = await supabase.auth.getSession();
|
|
|
|
if (sessionError || !session) {
|
|
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
|
|
}
|
|
|
|
const user = session.user;
|
|
|
|
// 2) Vérifier que l'utilisateur est staff
|
|
const { data: staffData } = await supabase
|
|
.from("staff_users")
|
|
.select("is_staff")
|
|
.eq("user_id", user.id)
|
|
.maybeSingle();
|
|
|
|
const isStaff = staffData?.is_staff || false;
|
|
|
|
if (!isStaff) {
|
|
return NextResponse.json(
|
|
{ error: "Accès refusé : réservé au staff" },
|
|
{ status: 403 }
|
|
);
|
|
}
|
|
|
|
// 3) Récupérer le virement de salaire
|
|
const { data: salaryTransfer, error: stError } = await supabase
|
|
.from("salary_transfers")
|
|
.select("*")
|
|
.eq("id", params.id)
|
|
.single();
|
|
|
|
if (stError || !salaryTransfer) {
|
|
return NextResponse.json(
|
|
{ error: "Virement de salaire introuvable" },
|
|
{ status: 404 }
|
|
);
|
|
}
|
|
|
|
// 4) Récupérer l'organisation et ses détails
|
|
const { data: organization, error: orgError } = await supabase
|
|
.from("organizations")
|
|
.select("*")
|
|
.eq("id", salaryTransfer.org_id)
|
|
.single();
|
|
|
|
if (orgError || !organization) {
|
|
return NextResponse.json(
|
|
{ error: "Organisation introuvable" },
|
|
{ status: 404 }
|
|
);
|
|
}
|
|
|
|
const { data: orgDetails, error: orgDetailsError } = await supabase
|
|
.from("organization_details")
|
|
.select("*")
|
|
.eq("org_id", salaryTransfer.org_id)
|
|
.single();
|
|
|
|
if (orgDetailsError || !orgDetails) {
|
|
return NextResponse.json(
|
|
{ error: "Détails de l'organisation introuvables" },
|
|
{ status: 404 }
|
|
);
|
|
}
|
|
|
|
// 5) Vérifier les emails de notification
|
|
const cleanEmail = (email: string | null | undefined): string | undefined => {
|
|
if (!email) return undefined;
|
|
// Supprimer tous les espaces, retours à la ligne, tabulations, etc.
|
|
const cleaned = email.replace(/\s+/g, '').trim();
|
|
if (cleaned.length === 0) return undefined;
|
|
return cleaned;
|
|
};
|
|
|
|
const isValidEmail = (email: string | null | undefined): boolean => {
|
|
if (!email) return false;
|
|
const cleaned = cleanEmail(email);
|
|
if (!cleaned) return false;
|
|
// Vérifier le format basique d'un email
|
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
return emailRegex.test(cleaned);
|
|
};
|
|
|
|
const emailNotifs = cleanEmail(orgDetails.email_notifs);
|
|
const emailNotifsCC = cleanEmail(orgDetails.email_notifs_cc);
|
|
|
|
console.log("[notify-client] Email brut:", JSON.stringify(orgDetails.email_notifs));
|
|
console.log("[notify-client] Email nettoyé:", emailNotifs);
|
|
console.log("[notify-client] CC brut:", JSON.stringify(orgDetails.email_notifs_cc));
|
|
console.log("[notify-client] CC nettoyé:", emailNotifsCC);
|
|
|
|
if (!emailNotifs || !isValidEmail(emailNotifs)) {
|
|
return NextResponse.json(
|
|
{ error: "Email de notification non configuré ou invalide pour cette organisation" },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Valider l'email CC s'il existe (rejeter les chaînes vides ou invalides)
|
|
const validatedCcEmail = (emailNotifsCC && isValidEmail(emailNotifsCC)) ? emailNotifsCC : undefined;
|
|
|
|
// 6) Récupérer le prénom du contact depuis organization_details
|
|
const firstName = orgDetails.prenom_contact || "Cher client";
|
|
|
|
// 7) Formater les données pour l'email
|
|
const formatDate = (dateStr: string | null) => {
|
|
if (!dateStr) return "—";
|
|
const date = new Date(dateStr);
|
|
return date.toLocaleDateString("fr-FR", {
|
|
day: "2-digit",
|
|
month: "long",
|
|
year: "numeric"
|
|
});
|
|
};
|
|
|
|
const formatAmount = (amount: number | null) => {
|
|
if (amount === null || amount === undefined) return "0,00 €";
|
|
return amount.toLocaleString("fr-FR", {
|
|
minimumFractionDigits: 2,
|
|
maximumFractionDigits: 2
|
|
}) + " €";
|
|
};
|
|
|
|
// Construire la référence du virement
|
|
const codeEmployeur = orgDetails.code_employeur || "UNKNOWN";
|
|
const numAppel = salaryTransfer.num_appel || "00000";
|
|
const transferReference = `AV-${codeEmployeur}-${numAppel}`;
|
|
|
|
// 8) Préparer les données du template
|
|
const templateData = {
|
|
firstName,
|
|
organizationName: organization.name,
|
|
employerCode: codeEmployeur,
|
|
handlerName: "Renaud BREVIERE-ABRAHAM",
|
|
totalAmount: formatAmount(salaryTransfer.total_net),
|
|
periodLabel: salaryTransfer.period_label || formatDate(salaryTransfer.period_month),
|
|
deadline: formatDate(salaryTransfer.deadline),
|
|
transferReference,
|
|
showBankInfo: 'true', // Pour afficher la carte bancaire
|
|
};
|
|
|
|
// 9) Envoyer l'email via le système universel V2
|
|
console.log("[notify-client] Envoi de l'email à:", emailNotifs);
|
|
console.log("[notify-client] CC:", validatedCcEmail || "Aucun");
|
|
|
|
await sendUniversalEmailV2({
|
|
type: 'salary-transfer-notification',
|
|
toEmail: emailNotifs!,
|
|
ccEmail: validatedCcEmail,
|
|
data: templateData
|
|
});
|
|
|
|
// 10) Mettre à jour le virement pour indiquer que la notification a été envoyée
|
|
const { error: updateError } = await supabase
|
|
.from("salary_transfers")
|
|
.update({
|
|
notification_sent: true,
|
|
notification_ok: true,
|
|
updated_at: new Date().toISOString()
|
|
})
|
|
.eq("id", params.id);
|
|
|
|
if (updateError) {
|
|
console.error("[notify-client] Erreur lors de la mise à jour:", updateError);
|
|
// On ne retourne pas d'erreur car l'email a été envoyé
|
|
}
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
message: "Notification envoyée avec succès",
|
|
emailSentTo: emailNotifs,
|
|
emailCc: validatedCcEmail || null
|
|
});
|
|
|
|
} catch (error: any) {
|
|
console.error("[notify-client] Erreur:", error);
|
|
return NextResponse.json(
|
|
{ error: "Erreur lors de l'envoi de la notification", details: error.message },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|