127 lines
No EOL
4.1 KiB
TypeScript
127 lines
No EOL
4.1 KiB
TypeScript
// app/api/contrats/generate-batch-pdf/route.ts
|
|
import { NextRequest, NextResponse } from "next/server";
|
|
import { createSbServer } from "@/lib/supabaseServer";
|
|
|
|
export async function POST(request: NextRequest) {
|
|
try {
|
|
const sb = createSbServer();
|
|
|
|
// Vérification de l'authentification et du staff
|
|
const { data: { user }, error: authError } = await sb.auth.getUser();
|
|
if (authError || !user) {
|
|
return NextResponse.json(
|
|
{ error: "Authentification requise" },
|
|
{ status: 401 }
|
|
);
|
|
}
|
|
|
|
const { data: staffUser } = await sb
|
|
.from("staff_users")
|
|
.select("is_staff")
|
|
.eq("user_id", user.id)
|
|
.maybeSingle();
|
|
|
|
if (!staffUser?.is_staff) {
|
|
return NextResponse.json(
|
|
{ error: "Accès refusé - réservé au staff" },
|
|
{ status: 403 }
|
|
);
|
|
}
|
|
|
|
// Parse du body pour récupérer les IDs des contrats
|
|
const { contractIds }: { contractIds: string[] } = await request.json();
|
|
|
|
if (!contractIds || !Array.isArray(contractIds) || contractIds.length === 0) {
|
|
return NextResponse.json(
|
|
{ error: "Liste des contrats requise" },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Limiter le nombre de contrats à traiter en une fois pour éviter les timeouts (30s réels)
|
|
// Estimation : ~2-3s par PDF + délai réduit = ~2-3s par contrat
|
|
// Avec 30s de timeout réel, on peut traiter 10-12 contrats maximum
|
|
if (contractIds.length > 10) {
|
|
return NextResponse.json(
|
|
{ error: "Maximum 10 contrats peuvent être traités en une fois à cause du timeout de 30s. Les contrats supplémentaires seront traités automatiquement par groupes." },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
const results = [];
|
|
const errors = [];
|
|
|
|
// Traiter chaque contrat séquentiellement pour éviter de surcharger les APIs externes
|
|
for (const contractId of contractIds) {
|
|
try {
|
|
console.log(`[BATCH PDF] Traitement du contrat ${contractId}`);
|
|
|
|
// Appeler l'endpoint individuel pour chaque contrat
|
|
const response = await fetch(`${request.nextUrl.origin}/api/contrats/${contractId}/generate-pdf`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
// Forward les cookies pour l'authentification
|
|
'Cookie': request.headers.get('cookie') || '',
|
|
},
|
|
});
|
|
|
|
if (response.ok) {
|
|
const result = await response.json();
|
|
results.push({
|
|
contractId,
|
|
success: true,
|
|
filename: result.filename,
|
|
message: result.message
|
|
});
|
|
console.log(`[BATCH PDF] ✅ Succès pour le contrat ${contractId}`);
|
|
} else {
|
|
const errorData = await response.json();
|
|
errors.push({
|
|
contractId,
|
|
success: false,
|
|
error: errorData.error || `Erreur ${response.status}`
|
|
});
|
|
console.log(`[BATCH PDF] ❌ Erreur pour le contrat ${contractId}: ${errorData.error}`);
|
|
}
|
|
} catch (error) {
|
|
errors.push({
|
|
contractId,
|
|
success: false,
|
|
error: error instanceof Error ? error.message : "Erreur inconnue"
|
|
});
|
|
console.log(`[BATCH PDF] ❌ Exception pour le contrat ${contractId}:`, error);
|
|
}
|
|
|
|
// Réduire le délai entre les traitements pour optimiser le temps dans la limite de 30s
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
}
|
|
|
|
// Résumé des résultats
|
|
const totalProcessed = contractIds.length;
|
|
const successCount = results.length;
|
|
const errorCount = errors.length;
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
message: `Traitement terminé: ${successCount}/${totalProcessed} PDFs créés avec succès`,
|
|
summary: {
|
|
totalProcessed,
|
|
successCount,
|
|
errorCount
|
|
},
|
|
results,
|
|
errors
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error("Erreur lors de la génération batch de PDFs:", error);
|
|
return NextResponse.json(
|
|
{
|
|
error: "Erreur interne du serveur",
|
|
details: error instanceof Error ? error.message : String(error)
|
|
},
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
} |