mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-11 17:27:31 +02:00
Update invoice sending to use Multer for file uploads
Replace Busboy with Multer for handling multipart/form-data uploads for the invoice sending API endpoint in `server/routes.ts`. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 06ccc22f-0202-44ef-842e-1398da8ca1f8 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 57dda692-8f64-40f3-b873-418a8c7efa67 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/06ccc22f-0202-44ef-842e-1398da8ca1f8/leGOKHM
This commit is contained in:
1 parent
1b34e274b9
commit
881a747ebc
1 file changed
+19
-38
+19
-38
@@ -4,7 +4,7 @@ import { storage } from "./storage";
|
|||||||
import { setupLocalAuth, requireAuth } from "./localAuth";
|
import { setupLocalAuth, requireAuth } from "./localAuth";
|
||||||
import { requireModulePermission, requireAdmin, requirePermission } from "./permissions";
|
import { requireModulePermission, requireAdmin, requirePermission } from "./permissions";
|
||||||
import { db, pool } from "./db";
|
import { db, pool } from "./db";
|
||||||
import Busboy from "busboy";
|
import multer from "multer";
|
||||||
|
|
||||||
console.log('🔍 Using development storage and authentication');
|
console.log('🔍 Using development storage and authentication');
|
||||||
|
|
||||||
@@ -789,8 +789,14 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Configuration multer pour envoi de factures
|
||||||
|
const invoiceUpload = multer({
|
||||||
|
storage: multer.memoryStorage(),
|
||||||
|
limits: { fileSize: 10 * 1024 * 1024 } // 10MB max
|
||||||
|
});
|
||||||
|
|
||||||
// Route proxy SIMPLE pour envoi de factures (admin + directeur)
|
// Route proxy SIMPLE pour envoi de factures (admin + directeur)
|
||||||
app.post('/api/reconciliation/send-invoice', isAuthenticated, async (req: any, res) => {
|
app.post('/api/reconciliation/send-invoice', isAuthenticated, invoiceUpload.single('file'), async (req: any, res) => {
|
||||||
try {
|
try {
|
||||||
const userId = req.user?.claims?.sub || req.user?.id;
|
const userId = req.user?.claims?.sub || req.user?.id;
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
@@ -802,43 +808,15 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
return res.status(403).json({ error: 'Accès refusé' });
|
return res.status(403).json({ error: 'Accès refusé' });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utiliser busboy pour parser le multipart/form-data
|
if (!req.file || !req.body.webhookUrl) {
|
||||||
const busboy = Busboy({ headers: req.headers });
|
|
||||||
const fields: any = {};
|
|
||||||
let fileBuffer: Buffer | null = null;
|
|
||||||
let fileName = '';
|
|
||||||
let mimeType = '';
|
|
||||||
|
|
||||||
busboy.on('file', (fieldname, file, info) => {
|
|
||||||
const chunks: Buffer[] = [];
|
|
||||||
fileName = info.filename;
|
|
||||||
mimeType = info.mimeType;
|
|
||||||
|
|
||||||
file.on('data', (chunk) => chunks.push(chunk));
|
|
||||||
file.on('end', () => {
|
|
||||||
fileBuffer = Buffer.concat(chunks);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
busboy.on('field', (fieldname, value) => {
|
|
||||||
fields[fieldname] = value;
|
|
||||||
});
|
|
||||||
|
|
||||||
await new Promise((resolve, reject) => {
|
|
||||||
busboy.on('finish', resolve);
|
|
||||||
busboy.on('error', reject);
|
|
||||||
req.pipe(busboy);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!fileBuffer || !fields.webhookUrl) {
|
|
||||||
return res.status(400).json({ error: 'Fichier ou webhook manquant' });
|
return res.status(400).json({ error: 'Fichier ou webhook manquant' });
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('📤 INVOICE PROXY: Envoi facture', {
|
console.log('📤 INVOICE PROXY: Envoi facture', {
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
role: user.role,
|
role: user.role,
|
||||||
fileName,
|
fileName: req.file.originalname,
|
||||||
size: fileBuffer.length
|
size: req.file.size
|
||||||
});
|
});
|
||||||
|
|
||||||
// Importer form-data dynamiquement avec eval pour ESM
|
// Importer form-data dynamiquement avec eval pour ESM
|
||||||
@@ -846,12 +824,15 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
|||||||
const FormData = FormDataModule.default;
|
const FormData = FormDataModule.default;
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', fileBuffer, { filename: fileName, contentType: mimeType });
|
formData.append('file', req.file.buffer, {
|
||||||
formData.append('supplier', fields.supplier || '');
|
filename: req.file.originalname,
|
||||||
formData.append('blNumber', fields.blNumber || '');
|
contentType: req.file.mimetype
|
||||||
formData.append('type', fields.type || 'Facture');
|
});
|
||||||
|
formData.append('supplier', req.body.supplier || '');
|
||||||
|
formData.append('blNumber', req.body.blNumber || '');
|
||||||
|
formData.append('type', req.body.type || 'Facture');
|
||||||
|
|
||||||
const response = await fetch(fields.webhookUrl, {
|
const response = await fetch(req.body.webhookUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: formData as any,
|
body: formData as any,
|
||||||
headers: formData.getHeaders()
|
headers: formData.getHeaders()
|
||||||
|
|||||||
Reference in new issue
Block a user