227 lines
8.4 KiB
TypeScript
227 lines
8.4 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { createSbServer, createSbServiceRole } from "@/lib/supabaseServer";
|
|
import { sendSupportReplyEmail, sendInternalTicketReplyEmail } from "@/lib/emailMigrationHelpers";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export async function GET(_: Request, { params }: { params: { id: string } }) {
|
|
const sb = createSbServer();
|
|
|
|
// Récupérer les messages
|
|
const { data: messages, error } = await sb
|
|
.from("ticket_messages")
|
|
.select("id, ticket_id, author_id, body, internal, via, created_at")
|
|
.eq("ticket_id", params.id)
|
|
.order("created_at", { ascending: true });
|
|
|
|
if (error) return NextResponse.json({ error: error.message }, { status: 400 });
|
|
|
|
if (!messages || messages.length === 0) {
|
|
return NextResponse.json({ items: [] });
|
|
}
|
|
|
|
// Récupérer les informations staff pour tous les auteurs
|
|
const authorIds = [...new Set(messages.map(m => m.author_id))];
|
|
const { data: staffUsers } = await sb
|
|
.from("staff_users")
|
|
.select("user_id, is_staff")
|
|
.in("user_id", authorIds);
|
|
|
|
// Créer un map pour faciliter la recherche
|
|
const staffMap = new Map((staffUsers || []).map(s => [s.user_id, s.is_staff]));
|
|
|
|
// Enrichir les messages avec les informations staff
|
|
const enrichedMessages = messages.map(msg => ({
|
|
...msg,
|
|
is_staff: staffMap.get(msg.author_id) === true
|
|
}));
|
|
|
|
return NextResponse.json({ items: enrichedMessages });
|
|
}
|
|
|
|
export async function POST(req: Request, { params }: { params: { id: string } }) {
|
|
const sb = createSbServer();
|
|
const { data: { user } } = await sb.auth.getUser();
|
|
if (!user) return new NextResponse("Unauthorized", { status: 401 });
|
|
|
|
const body = await req.json().catch(() => ({}));
|
|
const text = String(body.body || "").trim();
|
|
const internal = body.internal === true;
|
|
if (!text) return NextResponse.json({ error: "Message vide" }, { status: 400 });
|
|
|
|
// Vérifier si l'utilisateur est staff
|
|
const { data: staffUser } = await sb
|
|
.from("staff_users")
|
|
.select("is_staff")
|
|
.eq("user_id", user.id)
|
|
.maybeSingle();
|
|
|
|
const isStaff = staffUser?.is_staff === true;
|
|
const via = isStaff ? "staff" : "web";
|
|
|
|
const { error } = await sb
|
|
.from("ticket_messages")
|
|
.insert({
|
|
ticket_id: params.id,
|
|
author_id: user.id,
|
|
body: text,
|
|
internal,
|
|
via
|
|
});
|
|
if (error) return NextResponse.json({ error: error.message }, { status: 400 });
|
|
|
|
// Si c'est un message du staff et qu'il n'est pas interne, envoyer une notification par email
|
|
if (isStaff && !internal) {
|
|
try {
|
|
console.log('📧 [POST messages] Envoi de notification email...');
|
|
|
|
// Récupérer les informations du ticket
|
|
const { data: ticket } = await sb
|
|
.from("tickets")
|
|
.select("id, subject, created_by, org_id")
|
|
.eq("id", params.id)
|
|
.single();
|
|
|
|
console.log('📧 [POST messages] Ticket:', { id: ticket?.id, created_by: ticket?.created_by, org_id: ticket?.org_id });
|
|
|
|
if (ticket && ticket.created_by) {
|
|
// Récupérer les informations de l'organisation
|
|
const { data: organization } = await sb
|
|
.from("organizations")
|
|
.select("name, structure_api")
|
|
.eq("id", ticket.org_id)
|
|
.single();
|
|
|
|
console.log('📧 [POST messages] Organization:', { name: organization?.name, structure_api: organization?.structure_api });
|
|
|
|
// Récupérer le code employeur depuis organization_details
|
|
const { data: orgDetails } = await sb
|
|
.from("organization_details")
|
|
.select("code_employeur")
|
|
.eq("org_id", ticket.org_id)
|
|
.maybeSingle();
|
|
|
|
console.log('📧 [POST messages] Org details:', { code_employeur: orgDetails?.code_employeur });
|
|
|
|
// Utiliser le service role pour accéder aux données auth
|
|
const sbAdmin = createSbServiceRole();
|
|
|
|
// Récupérer l'email et le prénom du créateur du ticket
|
|
const { data: creatorUser, error: creatorError } = await sbAdmin.auth.admin.getUserById(ticket.created_by);
|
|
console.log('📧 [POST messages] Creator user:', {
|
|
hasData: !!creatorUser,
|
|
email: creatorUser?.user?.email,
|
|
error: creatorError
|
|
});
|
|
|
|
// Récupérer le nom du staff qui répond
|
|
const { data: staffProfile, error: staffError } = await sbAdmin.auth.admin.getUserById(user.id);
|
|
console.log('📧 [POST messages] Staff profile:', {
|
|
hasData: !!staffProfile,
|
|
email: staffProfile?.user?.email,
|
|
error: staffError
|
|
});
|
|
|
|
if (creatorUser?.user?.email) {
|
|
// Récupérer le prénom depuis user_metadata
|
|
const firstName = creatorUser.user.user_metadata?.display_name ||
|
|
creatorUser.user.user_metadata?.first_name ||
|
|
undefined;
|
|
|
|
// Récupérer le nom du staff depuis user_metadata
|
|
const staffName = staffProfile?.user?.user_metadata?.display_name ||
|
|
staffProfile?.user?.user_metadata?.first_name ||
|
|
staffProfile?.user?.email?.split('@')[0] ||
|
|
'L\'équipe support';
|
|
|
|
console.log('📧 [POST messages] Envoi vers:', creatorUser.user.email);
|
|
console.log('📧 [POST messages] Données email:', {
|
|
firstName,
|
|
staffName,
|
|
ticketId: ticket.id,
|
|
ticketSubject: ticket.subject,
|
|
organizationName: organization?.name,
|
|
employerCode: orgDetails?.code_employeur
|
|
});
|
|
|
|
// Utiliser le helper pour envoyer l'email
|
|
await sendSupportReplyEmail(creatorUser.user.email, {
|
|
firstName,
|
|
ticketId: ticket.id,
|
|
ticketSubject: ticket.subject,
|
|
staffName,
|
|
staffMessage: text,
|
|
organizationName: organization?.name,
|
|
employerCode: orgDetails?.code_employeur,
|
|
});
|
|
|
|
console.log(`✅ [POST messages] Notification email envoyée à ${creatorUser.user.email} pour le ticket ${ticket.id}`);
|
|
} else {
|
|
console.error('❌ [POST messages] Email du créateur introuvable');
|
|
}
|
|
} else {
|
|
console.error('❌ [POST messages] Ticket ou created_by introuvable');
|
|
}
|
|
} catch (emailError) {
|
|
// On ne fait pas échouer la requête si l'email échoue
|
|
console.error('❌ [POST messages] Erreur lors de l\'envoi de la notification email:', emailError);
|
|
}
|
|
}
|
|
|
|
// Si c'est un message d'un utilisateur (non-staff), envoyer une notification interne
|
|
if (!isStaff) {
|
|
try {
|
|
console.log('📧 [POST messages] Envoi de notification interne...');
|
|
|
|
// Récupérer les informations du ticket
|
|
const { data: ticket } = await sb
|
|
.from("tickets")
|
|
.select("id, subject, status, org_id")
|
|
.eq("id", params.id)
|
|
.single();
|
|
|
|
if (ticket) {
|
|
// Récupérer les informations de l'organisation
|
|
const { data: organization } = await sb
|
|
.from("organizations")
|
|
.select("name")
|
|
.eq("id", ticket.org_id)
|
|
.single();
|
|
|
|
// Récupérer le code employeur depuis organization_details
|
|
const { data: orgDetails } = await sb
|
|
.from("organization_details")
|
|
.select("code_employeur")
|
|
.eq("org_id", ticket.org_id)
|
|
.maybeSingle();
|
|
|
|
// Utiliser le service role pour accéder aux données auth
|
|
const sbAdmin = createSbServiceRole();
|
|
|
|
// Récupérer les infos de l'utilisateur qui répond
|
|
const { data: userData } = await sbAdmin.auth.admin.getUserById(user.id);
|
|
const userName = userData?.user?.user_metadata?.display_name
|
|
|| userData?.user?.user_metadata?.first_name
|
|
|| 'Utilisateur inconnu';
|
|
|
|
await sendInternalTicketReplyEmail({
|
|
ticketId: ticket.id,
|
|
ticketSubject: ticket.subject,
|
|
ticketStatus: ticket.status,
|
|
userMessage: text,
|
|
userName,
|
|
userEmail: user.email || 'Email non disponible',
|
|
organizationName: organization?.name,
|
|
employerCode: orgDetails?.code_employeur,
|
|
});
|
|
|
|
console.log(`✅ [POST messages] Notification interne envoyée pour le ticket ${ticket.id}`);
|
|
}
|
|
} catch (emailError) {
|
|
console.error('❌ [POST messages] Erreur lors de l\'envoi de la notification interne:', emailError);
|
|
}
|
|
}
|
|
|
|
return NextResponse.json({ ok: true }, { status: 201 });
|
|
}
|
|
|