- Ajout du type 'contract-note-added' dans le système email universel v2 - Email automatique envoyé à paie@odentas.fr quand un client ajoute une note - Fonctionne pour tous les types de contrats (CDDU mono, multi, RG) - Email contient: organisation, code employeur, n° contrat, utilisateur, contenu note - Lien direct vers le contrat dans l'interface staff - Gestion des erreurs: note créée même si email échoue - Documentation complète dans NOTIFICATION_NOTES_CONTRAT.md
126 lines
No EOL
4.6 KiB
TypeScript
126 lines
No EOL
4.6 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { createSbServer } from "@/lib/supabaseServer";
|
|
import { sendUniversalEmailV2 } from "@/lib/emailTemplateService";
|
|
|
|
export async function GET(req: Request, ctx: { params: { id: string } }) {
|
|
const { id } = ctx.params;
|
|
try {
|
|
const sb = createSbServer();
|
|
|
|
// Try to get organization id from header if present
|
|
const activeOrg = req.headers.get("x-active-org-id") || undefined;
|
|
|
|
// Query Supabase notes table (no ordering here, we'll sort in JS)
|
|
let q = sb.from("notes").select("*");
|
|
q = q.eq("contract_id", id);
|
|
if (activeOrg) q = q.eq("organization_id", activeOrg);
|
|
|
|
// Execute query
|
|
const { data, error } = await q;
|
|
|
|
if (error) {
|
|
return NextResponse.json({ error: "supabase_error", message: error.message }, { status: 502 });
|
|
}
|
|
|
|
// Sort notes by the most relevant date:
|
|
// - For Airtable imports: use source_created_at
|
|
// - For new notes: use created_at
|
|
// Sort in descending order (newest first)
|
|
const sortedData = Array.isArray(data) ? data.sort((a, b) => {
|
|
const dateA = a.source_created_at || a.created_at;
|
|
const dateB = b.source_created_at || b.created_at;
|
|
|
|
if (!dateA && !dateB) return 0;
|
|
if (!dateA) return 1; // dateA null goes after
|
|
if (!dateB) return -1; // dateB null goes after
|
|
|
|
// Descending order: most recent first
|
|
return new Date(dateB).getTime() - new Date(dateA).getTime();
|
|
}) : [];
|
|
|
|
return NextResponse.json({ items: sortedData }, { status: 200 });
|
|
} catch (e: any) {
|
|
return NextResponse.json({ error: "internal_error", message: e?.message || String(e) }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
export async function POST(req: Request, ctx: { params: { id: string } }) {
|
|
const { id } = ctx.params;
|
|
try {
|
|
const body = await req.json().catch(() => ({}));
|
|
const content: string = (body && body.content) || "";
|
|
const source: string = (body && body.source) || "Client";
|
|
|
|
if (!content || !content.trim()) {
|
|
return NextResponse.json({ error: "invalid_input", message: "content required" }, { status: 400 });
|
|
}
|
|
|
|
const sb = createSbServer();
|
|
|
|
// Récupérer le contrat avec son org_id et numéro
|
|
const { data: contract, error: contractError } = await sb
|
|
.from("cddu_contracts")
|
|
.select("org_id, numero")
|
|
.eq("id", id)
|
|
.single();
|
|
|
|
if (contractError || !contract) {
|
|
return NextResponse.json({ error: "contract_not_found", message: "Contrat non trouvé" }, { status: 404 });
|
|
}
|
|
|
|
const author = req.headers.get("x-company-name") || undefined;
|
|
|
|
const insertPayload: any = {
|
|
contract_id: id,
|
|
content: content.trim(),
|
|
source,
|
|
organization_id: contract.org_id,
|
|
};
|
|
if (author) insertPayload.author = author;
|
|
|
|
const { data, error } = await sb.from("notes").insert([insertPayload]).select();
|
|
if (error) {
|
|
return NextResponse.json({ error: "supabase_error", message: error.message }, { status: 502 });
|
|
}
|
|
|
|
// Envoyer un email à paie@odentas.fr pour notifier l'ajout de la note
|
|
try {
|
|
// Récupérer les informations de l'organisation
|
|
const { data: organization, error: orgError } = await sb
|
|
.from("organizations")
|
|
.select("name, api_name")
|
|
.eq("id", contract.org_id)
|
|
.single();
|
|
|
|
if (!orgError && organization) {
|
|
// Récupérer le nom de l'utilisateur depuis les headers
|
|
const userName = req.headers.get("x-user-name") || author || "Utilisateur inconnu";
|
|
|
|
await sendUniversalEmailV2({
|
|
type: 'contract-note-added',
|
|
toEmail: 'paie@odentas.fr',
|
|
data: {
|
|
organizationName: organization.name,
|
|
employerCode: organization.api_name,
|
|
contractNumber: contract.numero || id,
|
|
userName: userName,
|
|
noteContent: content.trim(),
|
|
contractId: id,
|
|
ctaUrl: `https://espace-paie.odentas.fr/staff/contrats/${id}`,
|
|
},
|
|
});
|
|
|
|
console.log('✅ Email de notification envoyé pour la note ajoutée au contrat:', id);
|
|
} else {
|
|
console.warn('⚠️ Impossible de récupérer les informations de l\'organisation pour l\'email de notification');
|
|
}
|
|
} catch (emailError) {
|
|
console.error('❌ Erreur lors de l\'envoi de l\'email de notification:', emailError);
|
|
// On ne fait pas échouer la requête si l'email ne peut pas être envoyé
|
|
}
|
|
|
|
return NextResponse.json({ items: Array.isArray(data) ? data : [] }, { status: 201 });
|
|
} catch (e: any) {
|
|
return NextResponse.json({ error: "internal_error", message: e?.message || String(e) }, { status: 500 });
|
|
}
|
|
} |