feat: export manuel (exportToPdf) supporte maintenant SharePoint en plus du dossier local

This commit is contained in:
Manus
2026-05-06 12:12:38 -04:00
parent 41ae95737b
commit 4086227df7

View File

@@ -1136,6 +1136,8 @@ export const appRouter = router({
// Get export folder from settings // Get export folder from settings
const settings = await getImportSettingsByUser(ctx.user.id); const settings = await getImportSettingsByUser(ctx.user.id);
const exportFolder = settings?.exportFolder; const exportFolder = settings?.exportFolder;
const exportFolderType = (settings as any)?.exportFolderType || 'local';
const isSharePoint = exportFolderType === 'sharepoint';
// Load service→signature associations // Load service→signature associations
const serviceAssociations = await getServiceSignaturesByUser(ctx.user.id); const serviceAssociations = await getServiceSignaturesByUser(ctx.user.id);
@@ -1163,18 +1165,22 @@ export const appRouter = router({
}); });
} }
// Create export folder if it doesn't exist // Create export folder if not SharePoint
try { if (!isSharePoint) {
await fs.mkdir(exportFolder, { recursive: true }); try {
} catch (error) { await fs.mkdir(exportFolder, { recursive: true });
console.error('Error creating export folder:', error); } catch (error) {
throw new TRPCError({ console.error('Error creating export folder:', error);
code: "INTERNAL_SERVER_ERROR", throw new TRPCError({
message: `Impossible de créer le dossier d'export: ${exportFolder}` code: "INTERNAL_SERVER_ERROR",
}); message: `Impossible de créer le dossier d'export: ${exportFolder}`
});
}
} }
// Copy PDFs to export folder console.log(`[exportToPdf] Mode: ${exportFolderType}, dossier: ${exportFolder}, ${invoices.length} facture(s)`);
// Copy/upload PDFs to export folder
const copiedFiles: string[] = []; const copiedFiles: string[] = [];
const errors: string[] = []; const errors: string[] = [];
const STORAGE_BASE_PATH = process.env.STORAGE_BASE_PATH || path.join(process.cwd(), "storage"); const STORAGE_BASE_PATH = process.env.STORAGE_BASE_PATH || path.join(process.cwd(), "storage");
@@ -1261,38 +1267,88 @@ export const appRouter = router({
}); });
const signedPdfBytes = await pdfDoc.save(); const signedPdfBytes = await pdfDoc.save();
await fs.writeFile(destPath, signedPdfBytes);
copiedFiles.push(destPath);
console.log(`[Export] Signature apposée pour ${serviceName} sur ${filename}`); console.log(`[Export] Signature apposée pour ${serviceName} sur ${filename}`);
if (isSharePoint) {
const { uploadToSharePoint } = await import('./sharepoint');
console.log(`[exportToPdf] Upload SharePoint: ${filename}`);
const spResult = await uploadToSharePoint(
{ tenantId: (settings as any)?.azureTenantId || '', clientId: (settings as any)?.azureClientId || '', clientSecret: (settings as any)?.azureClientSecret || '', sharepointUrl: exportFolder },
Buffer.from(signedPdfBytes), filename
);
if (!spResult.success) throw new Error(`SharePoint: ${spResult.error}`);
console.log(`[exportToPdf] Upload SharePoint réussi: ${spResult.webUrl}`);
copiedFiles.push(spResult.webUrl || filename);
} else {
await fs.writeFile(destPath, signedPdfBytes);
copiedFiles.push(destPath);
}
} else { } else {
// Signature not found, copy without signature // Signature not found, upload/copy without signature
try { await fs.copyFile(sourcePath, destPath); } catch (_) { let pdfBuf: Buffer;
try { pdfBuf = await fs.readFile(sourcePath); } catch (_) {
const fu = invoice!.fileUrl; if (!fu) throw new Error('PDF introuvable'); const fu = invoice!.fileUrl; if (!fu) throw new Error('PDF introuvable');
const au = fu.startsWith('/') ? `${process.env.APP_BASE_URL||`http://localhost:${process.env.PORT||3000}`}${fu}` : fu; const au = fu.startsWith('/') ? `${process.env.APP_BASE_URL||`http://localhost:${process.env.PORT||3000}`}${fu}` : fu;
const rb = await fetch(au); if (!rb.ok) throw new Error(`HTTP ${rb.status}`); const rb = await fetch(au); if (!rb.ok) throw new Error(`HTTP ${rb.status}`);
await fs.writeFile(destPath, Buffer.from(await rb.arrayBuffer())); pdfBuf = Buffer.from(await rb.arrayBuffer());
}
if (isSharePoint) {
const { uploadToSharePoint } = await import('./sharepoint');
const spResult = await uploadToSharePoint(
{ tenantId: (settings as any)?.azureTenantId || '', clientId: (settings as any)?.azureClientId || '', clientSecret: (settings as any)?.azureClientSecret || '', sharepointUrl: exportFolder },
pdfBuf, filename
);
if (!spResult.success) throw new Error(`SharePoint: ${spResult.error}`);
copiedFiles.push(spResult.webUrl || filename);
} else {
try { await fs.copyFile(sourcePath, destPath); } catch (_) { await fs.writeFile(destPath, pdfBuf); }
copiedFiles.push(destPath);
} }
copiedFiles.push(destPath);
} }
} catch (sigError: any) { } catch (sigError: any) {
console.warn(`[Export] Impossible d'apposer la signature: ${sigError.message}. Copie sans signature.`); console.warn(`[Export] Impossible d'apposer la signature: ${sigError.message}. Copie sans signature.`);
try { await fs.copyFile(sourcePath, destPath); } catch (_) { let pdfBuf: Buffer;
try { pdfBuf = await fs.readFile(sourcePath); } catch (_) {
const fu = invoice!.fileUrl; if (!fu) throw new Error('PDF introuvable'); const fu = invoice!.fileUrl; if (!fu) throw new Error('PDF introuvable');
const au = fu.startsWith('/') ? `${process.env.APP_BASE_URL||`http://localhost:${process.env.PORT||3000}`}${fu}` : fu; const au = fu.startsWith('/') ? `${process.env.APP_BASE_URL||`http://localhost:${process.env.PORT||3000}`}${fu}` : fu;
const rb = await fetch(au); if (!rb.ok) throw new Error(`HTTP ${rb.status}`); const rb = await fetch(au); if (!rb.ok) throw new Error(`HTTP ${rb.status}`);
await fs.writeFile(destPath, Buffer.from(await rb.arrayBuffer())); pdfBuf = Buffer.from(await rb.arrayBuffer());
}
if (isSharePoint) {
const { uploadToSharePoint } = await import('./sharepoint');
const spResult = await uploadToSharePoint(
{ tenantId: (settings as any)?.azureTenantId || '', clientId: (settings as any)?.azureClientId || '', clientSecret: (settings as any)?.azureClientSecret || '', sharepointUrl: exportFolder },
pdfBuf, filename
);
if (!spResult.success) throw new Error(`SharePoint: ${spResult.error}`);
copiedFiles.push(spResult.webUrl || filename);
} else {
try { await fs.copyFile(sourcePath, destPath); } catch (_) { await fs.writeFile(destPath, pdfBuf); }
copiedFiles.push(destPath);
} }
copiedFiles.push(destPath);
} }
} else { } else {
// No signature association, copy as-is // No signature association, upload/copy as-is
try { await fs.copyFile(sourcePath, destPath); } catch (_) { let pdfBuf: Buffer;
try { pdfBuf = await fs.readFile(sourcePath); } catch (_) {
const fu = invoice!.fileUrl; if (!fu) throw new Error('PDF introuvable'); const fu = invoice!.fileUrl; if (!fu) throw new Error('PDF introuvable');
const au = fu.startsWith('/') ? `${process.env.APP_BASE_URL||`http://localhost:${process.env.PORT||3000}`}${fu}` : fu; const au = fu.startsWith('/') ? `${process.env.APP_BASE_URL||`http://localhost:${process.env.PORT||3000}`}${fu}` : fu;
const rb = await fetch(au); if (!rb.ok) throw new Error(`HTTP ${rb.status}`); const rb = await fetch(au); if (!rb.ok) throw new Error(`HTTP ${rb.status}`);
await fs.writeFile(destPath, Buffer.from(await rb.arrayBuffer())); pdfBuf = Buffer.from(await rb.arrayBuffer());
}
if (isSharePoint) {
const { uploadToSharePoint } = await import('./sharepoint');
console.log(`[exportToPdf] Upload SharePoint sans signature: ${filename}`);
const spResult = await uploadToSharePoint(
{ tenantId: (settings as any)?.azureTenantId || '', clientId: (settings as any)?.azureClientId || '', clientSecret: (settings as any)?.azureClientSecret || '', sharepointUrl: exportFolder },
pdfBuf, filename
);
if (!spResult.success) throw new Error(`SharePoint: ${spResult.error}`);
console.log(`[exportToPdf] Upload SharePoint réussi: ${spResult.webUrl}`);
copiedFiles.push(spResult.webUrl || filename);
} else {
try { await fs.copyFile(sourcePath, destPath); } catch (_) { await fs.writeFile(destPath, pdfBuf); }
copiedFiles.push(destPath);
} }
copiedFiles.push(destPath);
} }
// Update export status // Update export status