159 lines
5.2 KiB
TypeScript
159 lines
5.2 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { createSbServer } from "@/lib/supabaseServer";
|
|
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
const s3Client = new S3Client({
|
|
region: process.env.AWS_REGION || "eu-west-3",
|
|
credentials: {
|
|
accessKeyId: process.env.AWS_ACCESS_KEY_ID || "",
|
|
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY || "",
|
|
},
|
|
});
|
|
|
|
const BUCKET_NAME = (process.env.AWS_S3_BUCKET || "odentas-docs").trim();
|
|
|
|
export async function POST(req: NextRequest) {
|
|
try {
|
|
const sb = createSbServer();
|
|
|
|
// Vérifier que l'utilisateur est staff
|
|
const { data: { user } } = await sb.auth.getUser();
|
|
if (!user) {
|
|
return NextResponse.json({ error: "Non authentifié" }, { status: 401 });
|
|
}
|
|
|
|
const { data: staffUser } = await sb
|
|
.from("staff_users")
|
|
.select("is_staff")
|
|
.eq("user_id", user.id)
|
|
.single();
|
|
|
|
if (!staffUser?.is_staff) {
|
|
return NextResponse.json({ error: "Accès refusé" }, { status: 403 });
|
|
}
|
|
|
|
// Parser le form data
|
|
const formData = await req.formData();
|
|
const file = formData.get('file') as File;
|
|
const contractId = formData.get('contract_id') as string;
|
|
const payslipId = formData.get('payslip_id') as string;
|
|
|
|
if (!file || !contractId || !payslipId) {
|
|
return NextResponse.json({ error: "Paramètres manquants" }, { status: 400 });
|
|
}
|
|
|
|
// Vérifier que c'est bien un PDF
|
|
if (file.type !== 'application/pdf') {
|
|
return NextResponse.json({ error: "Seuls les fichiers PDF sont acceptés" }, { status: 400 });
|
|
}
|
|
|
|
// Récupérer les informations du contrat pour construire le chemin S3
|
|
const { data: contract, error: contractError } = await sb
|
|
.from("cddu_contracts")
|
|
.select("contract_number, org_id, employee_name")
|
|
.eq("id", contractId)
|
|
.single();
|
|
|
|
if (contractError || !contract) {
|
|
console.error('❌ [Payslip Upload] Erreur chargement contrat:', contractError);
|
|
return NextResponse.json({ error: "Contrat introuvable" }, { status: 404 });
|
|
}
|
|
|
|
// Récupérer les informations de la paie
|
|
const { data: payslip, error: payslipError } = await sb
|
|
.from("payslips")
|
|
.select("pay_number")
|
|
.eq("id", payslipId)
|
|
.single();
|
|
|
|
if (payslipError || !payslip) {
|
|
console.error('❌ [Payslip Upload] Erreur chargement payslip:', payslipError);
|
|
return NextResponse.json({ error: "Paie introuvable" }, { status: 404 });
|
|
}
|
|
|
|
// Utiliser org_id du contrat
|
|
const orgId = contract.org_id;
|
|
|
|
if (!orgId) {
|
|
console.error('❌ [Payslip Upload] Aucun org_id trouvé sur le contrat:', contract);
|
|
return NextResponse.json({ error: "Organisation introuvable sur le contrat" }, { status: 404 });
|
|
}
|
|
|
|
// Récupérer l'organization pour avoir le nom et le slugifier
|
|
const { data: org, error: orgError } = await sb
|
|
.from("organizations")
|
|
.select("name")
|
|
.eq("id", orgId)
|
|
.single();
|
|
|
|
if (orgError || !org?.name) {
|
|
console.error('❌ [Payslip Upload] Erreur chargement organisation:', orgError, 'orgId:', orgId);
|
|
return NextResponse.json({ error: "Organisation introuvable" }, { status: 404 });
|
|
}
|
|
|
|
// Slugifier le nom de l'organisation
|
|
const orgSlug = org.name
|
|
.toLowerCase()
|
|
.normalize('NFD')
|
|
.replace(/[\u0300-\u036f]/g, '')
|
|
.replace(/[^a-z0-9]+/g, '-')
|
|
.replace(/^-+|-+$/g, '');
|
|
|
|
// Générer le chemin S3: bulletins/{org_slug}/contrat_{contract_number}/bulletin_paie_{pay_number}_{uuid}.pdf
|
|
const uniqueId = uuidv4().replace(/-/g, '').substring(0, 8);
|
|
const contractNumber = contract.contract_number || contractId.substring(0, 8);
|
|
const payNumber = payslip.pay_number || 'unknown';
|
|
const filename = `bulletin_paie_${payNumber}_${uniqueId}.pdf`;
|
|
const s3Key = `bulletins/${orgSlug}/contrat_${contractNumber}/${filename}`;
|
|
|
|
console.log('📄 [Payslip Upload] Uploading to S3:', {
|
|
contractId,
|
|
payslipId,
|
|
contractNumber,
|
|
payNumber,
|
|
s3Key,
|
|
fileSize: file.size
|
|
});
|
|
|
|
// Upload vers S3
|
|
const buffer = Buffer.from(await file.arrayBuffer());
|
|
const uploadCommand = new PutObjectCommand({
|
|
Bucket: BUCKET_NAME,
|
|
Key: s3Key,
|
|
Body: buffer,
|
|
ContentType: 'application/pdf',
|
|
});
|
|
|
|
await s3Client.send(uploadCommand);
|
|
|
|
// Mettre à jour la paie dans Supabase avec le chemin S3
|
|
const { error: updateError } = await sb
|
|
.from('payslips')
|
|
.update({
|
|
storage_path: s3Key,
|
|
})
|
|
.eq('id', payslipId);
|
|
|
|
if (updateError) {
|
|
console.error('❌ [Payslip Upload] Erreur mise à jour Supabase:', updateError);
|
|
return NextResponse.json({ error: "Erreur lors de la mise à jour de la base de données" }, { status: 500 });
|
|
}
|
|
|
|
console.log('✅ [Payslip Upload] Upload réussi:', s3Key);
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
s3_key: s3Key,
|
|
filename: filename,
|
|
message: "Bulletin de paie uploadé avec succès"
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('❌ [Payslip Upload] Erreur:', error);
|
|
return NextResponse.json(
|
|
{ error: error instanceof Error ? error.message : "Erreur serveur" },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|