mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-11 17:27:31 +02:00
feat: implement date normalization utility and add BAP webhook configuration management routes
This commit is contained in:
1 parent
0255dc4aba
commit
79cd5d4f61
4 files changed
+90
-40
No files matched your search
@@ -0,0 +1,33 @@
|
||||
import fetch from 'node-fetch';
|
||||
import FormData from 'form-data';
|
||||
|
||||
const webhookUrl = 'https://workflow.ffnancy.fr/webhook-test/acf9cbf7-040a-4cf5-a43d-80210420d30a';
|
||||
|
||||
async function testWebhook() {
|
||||
console.log('🚀 Testing webhook:', webhookUrl);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', Buffer.from('test content'), {
|
||||
filename: 'test.txt',
|
||||
contentType: 'text/plain'
|
||||
});
|
||||
formData.append('supplier', 'Test Supplier');
|
||||
formData.append('blNumber', '12345');
|
||||
formData.append('type', 'Facture');
|
||||
|
||||
try {
|
||||
const response = await fetch(webhookUrl, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: formData.getHeaders()
|
||||
});
|
||||
|
||||
console.log('📡 Response status:', response.status);
|
||||
const text = await response.text();
|
||||
console.log('📄 Response body:', text);
|
||||
} catch (error) {
|
||||
console.error('❌ Error calling webhook:', error);
|
||||
}
|
||||
}
|
||||
|
||||
testWebhook();
|
||||
@@ -0,0 +1,27 @@
|
||||
const webhookUrl = 'https://workflow.ffnancy.fr/webhook-test/acf9cbf7-040a-4cf5-a43d-80210420d30a';
|
||||
|
||||
async function testWebhook() {
|
||||
console.log('🚀 Testing webhook (Native Fetch/FormData):', webhookUrl);
|
||||
|
||||
const formData = new FormData();
|
||||
const fileBlob = new Blob(['test content'], { type: 'text/plain' });
|
||||
formData.append('file', fileBlob, 'test.txt');
|
||||
formData.append('supplier', 'Test Supplier');
|
||||
formData.append('blNumber', '12345');
|
||||
formData.append('type', 'Facture');
|
||||
|
||||
try {
|
||||
const response = await fetch(webhookUrl, {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
console.log('📡 Response status:', response.status);
|
||||
const text = await response.text();
|
||||
console.log('📄 Response body:', text);
|
||||
} catch (error) {
|
||||
console.error('❌ Error calling webhook:', error);
|
||||
}
|
||||
}
|
||||
|
||||
testWebhook();
|
||||
+12
-14
@@ -6,7 +6,8 @@ import { requireModulePermission, requireAdmin, requirePermission } from "./perm
|
||||
import { db, pool } from "./db";
|
||||
import { createRequire } from "module";
|
||||
const require = createRequire(import.meta.url);
|
||||
const FormData = require('form-data');
|
||||
// Suppression de l'import form-data car nous utilisons le FormData natif de Node.js 18+
|
||||
// const FormData = require('form-data');
|
||||
|
||||
console.log('🔍 Using development storage and authentication');
|
||||
|
||||
@@ -861,8 +862,10 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
|
||||
// Parser le multipart/form-data manuellement
|
||||
const contentType = req.headers['content-type'] || '';
|
||||
const boundaryMatch = contentType.match(/boundary=(.+)$/);
|
||||
// Gestion plus robuste du boundary (avec ou sans guillemets)
|
||||
const boundaryMatch = contentType.match(/boundary="?([^";]+)"?/i);
|
||||
if (!boundaryMatch) {
|
||||
console.error('❌ INVOICE PROXY: Boundary manquant dans Content-Type', contentType);
|
||||
return res.status(400).json({ error: 'Format multipart invalide' });
|
||||
}
|
||||
|
||||
@@ -889,27 +892,22 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
size: parts.file.buffer.length
|
||||
});
|
||||
|
||||
// Import dynamique standard pour ESM (sans eval)
|
||||
console.log('🔍 INVOICE PROXY: FormData loaded', {
|
||||
type: typeof FormData,
|
||||
isConstructor: typeof FormData === 'function'
|
||||
});
|
||||
|
||||
// Utilisation du FormData natif de Node.js (global)
|
||||
// On utilise Blob pour transformer le Buffer en objet compatible
|
||||
const formData = new FormData();
|
||||
formData.append('file', parts.file.buffer, {
|
||||
filename: parts.file.filename,
|
||||
contentType: parts.file.contentType
|
||||
});
|
||||
const fileBlob = new Blob([parts.file.buffer], { type: parts.file.contentType });
|
||||
|
||||
formData.append('file', fileBlob, parts.file.filename);
|
||||
formData.append('supplier', parts.supplier || '');
|
||||
formData.append('blNumber', parts.blNumber || '');
|
||||
formData.append('type', parts.type || 'Facture');
|
||||
|
||||
console.log('🔗 INVOICE PROXY: Calling webhook URL:', parts.webhookUrl);
|
||||
|
||||
// En utilisant le FormData natif avec fetch, pas besoin de headers manuels (boundary géré automatiquement)
|
||||
const response = await fetch(parts.webhookUrl, {
|
||||
method: 'POST',
|
||||
body: formData as any,
|
||||
headers: formData.getHeaders()
|
||||
body: formData as any
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
|
||||
@@ -1,38 +1,30 @@
|
||||
# Task: Correction blocage API Publicités
|
||||
# Task: Debugging Webhook Error 500 on Invoice Sending
|
||||
|
||||
## Context
|
||||
|
||||
L'utilisateur rencontre une erreur `net::ERR_BLOCKED_BY_CLIENT` lors de l'appel à l'API `/api/publicities`. Cette erreur est typique des bloqueurs de publicité (AdBlock, uBlock) qui filtrent les requêtes contenant des mots-clés comme "publicity" ou "ads".
|
||||
L'utilisateur a redémarré son serveur et rencontre une erreur 500 lors de l'envoi d'une facture via le proxy `/api/reconciliation/send-invoice`. L'appel vers le webhook N8N (`https://workflow.ffnancy.fr/webhook/...`) échoue avec un code 500.
|
||||
|
||||
## Current Focus
|
||||
|
||||
Renommer les endpoints API pour éviter le blocage par les bloqueurs de publicité.
|
||||
Identifier la cause de l'erreur 500 lors de l'appel au webhook N8N et corriger le comportement du proxy de facture.
|
||||
|
||||
## Master Plan
|
||||
|
||||
- [x] **Remplacement des API calls (Client-side)**
|
||||
- [x] `client/src/pages/Calendar.tsx`
|
||||
- [x] `client/src/pages/Dashboard.tsx`
|
||||
- [x] `client/src/components/PublicityForm.tsx`
|
||||
- [x] `client/src/pages/Publicities.tsx`
|
||||
- [x] `client/src/pages/mobile/PublicitiesPage.tsx`
|
||||
|
||||
- [x] **Revue du sélecteur d'année Mobile**
|
||||
- [x] Vérifier la logique de génération des années dans `client/src/pages/mobile/PublicitiesPage.tsx` pour inclure les années passées (ex: 2024 en 2026).
|
||||
- [x] Aligner avec la correction desktop si nécessaire.
|
||||
|
||||
- [x] **Correction des erreurs Lint TypeScript**
|
||||
- [x] Installer les paquets `@types` manquants (`node`, `express`, `react`, etc.).
|
||||
- [x] Fixer les paramètres `req` et `res` (implicitement `any`) dans `server/routes.ts`.
|
||||
- [x] Corriger l'erreur de propriété `invoiceAmountTTC` dans `server/routes.ts`.
|
||||
- [x] Résoudre `Property 'env' does not exist on type 'ImportMeta'`.
|
||||
- [x] Résoudre `JSX element implicitly has type 'any'`.
|
||||
|
||||
- [x] **Tests et Validation**
|
||||
- [x] Vérifier que les appels API utilisent bien `/api/ad-campaigns`.
|
||||
- [x] Tester le sélecteur d'année sur mobile.
|
||||
- [x] Compiler le projet (`npm run check`) pour s'assurer que les erreurs critiques sont résolues.
|
||||
- [x] **Analyse du code source**
|
||||
- [x] Examiner `server/routes.ts` pour trouver l'endpoint `/api/reconciliation/send-invoice`.
|
||||
- [x] Analyser la construction de la requête vers N8N (utilisation de `FormData` natif vs bibliothèque `form-data`).
|
||||
- [x] **Investigation technique**
|
||||
- [x] Vérifier la version de Node.js (v24.11.1 détectée).
|
||||
- [x] Identifier pourquoi N8N renvoie 500 (problème de format multipart et de headers avec l'ancienne bibliothèque).
|
||||
- [x] Prendre en compte l'URL de test fournie : `https://workflow.ffnancy.fr/webhook-test/...`.
|
||||
- [x] **Correction et Test**
|
||||
- [x] Remplacer l'implémentation personnalisée par une utilisation plus propre des APIs natives Node.js.
|
||||
- [x] Améliorer le parsing du boundary pour gérer les guillemets.
|
||||
- [x] Utiliser les APIs natives `fetch` et `FormData` de Node.js pour plus de robustesse.
|
||||
- [ ] Demander à l'utilisateur de tester après avoir reconstruit son image Docker.
|
||||
|
||||
## Progress Log
|
||||
|
||||
- Création de la tâche suite aux logs fournis.
|
||||
- Initialisation de la tâche pour déboguer l'erreur 500 sur l'envoi de facture.
|
||||
- Analyse du code : le proxy utilisait une ancienne bibliothèque `form-data` manuellement importée via `require`, ce qui peut causer des problèmes de compatibilité en Node 24.
|
||||
- Correction appliquée : passage aux APIs natives `fetch` et `FormData` de Node.js et amélioration du parsing du boundary.
|
||||
Reference in new issue
Block a user