Mon flux de travail 2

Avancé

Ceci est unInvoice Processing, AI Summarizationworkflow d'automatisation du domainecontenant 18 nœuds.Utilise principalement des nœuds comme Code, Switch, Webhook, Telegram, HttpRequest. Flux de travail d'extraction et d'approbation de données de factures basé sur l'IA, intégrant ScrapeGraphAI et Telegram

Prérequis
  • Point de terminaison HTTP Webhook (généré automatiquement par n8n)
  • Token Bot Telegram
  • Peut nécessiter les informations d'identification d'authentification de l'API cible
Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "id": "VhEwspDqzu7ssFVE",
  "meta": {
    "instanceId": "f4b0efaa33080e7774e0d9285c40c7abcd2c6f7cf1a8b901fa7106170dd4cda3",
    "templateCredsSetupCompleted": true
  },
  "name": "My workflow 2",
  "tags": [
    {
      "id": "DxXGubfBzRKh6L8T",
      "name": "Revenue Optimization",
      "createdAt": "2025-07-25T16:24:30.370Z",
      "updatedAt": "2025-07-25T16:24:30.370Z"
    },
    {
      "id": "IxkcJ2IpYIxivoHV",
      "name": "Content Strategy",
      "createdAt": "2025-07-25T12:57:37.677Z",
      "updatedAt": "2025-07-25T12:57:37.677Z"
    },
    {
      "id": "PAKIJ2Mm9EvRcR3u",
      "name": "Trend Monitoring",
      "createdAt": "2025-07-25T12:57:37.670Z",
      "updatedAt": "2025-07-25T12:57:37.670Z"
    },
    {
      "id": "YtfXmaZk44MYedPO",
      "name": "Dynamic Pricing",
      "createdAt": "2025-07-25T16:24:30.369Z",
      "updatedAt": "2025-07-25T16:24:30.369Z"
    },
    {
      "id": "wJ30mjhtrposO8Qt",
      "name": "Simple RAG",
      "createdAt": "2025-07-28T12:55:14.424Z",
      "updatedAt": "2025-07-28T12:55:14.424Z"
    }
  ],
  "nodes": [
    {
      "id": "4d24fd12-5442-4112-b997-2e6b9ece768c",
      "name": "Déclencheur Email",
      "type": "n8n-nodes-base.emailReadImap",
      "position": [
        1120,
        832
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 2
    },
    {
      "id": "b32637a8-8941-4fea-b6cb-b2272d25eaa4",
      "name": "Téléchargement de fichier Webhook",
      "type": "n8n-nodes-base.webhook",
      "position": [
        1120,
        1008
      ],
      "webhookId": "9588f200-20c0-4f26-81e0-73726abc889a",
      "parameters": {
        "path": "/invoice-upload",
        "options": {
          "rawBody": true
        },
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "4197b894-434f-42b6-a728-b6773af9b54a",
      "name": "Processeur de fichiers",
      "type": "n8n-nodes-base.code",
      "position": [
        1424,
        896
      ],
      "parameters": {
        "jsCode": "// Process incoming data from either email or webhook\nconst inputData = $input.all()[0];\nlet invoiceFiles = [];\n\n// Handle email attachments\nif (inputData.json.attachments) {\n  invoiceFiles = inputData.json.attachments\n    .filter(attachment => {\n      const fileName = attachment.filename.toLowerCase();\n      return fileName.endsWith('.pdf') || \n             fileName.endsWith('.png') || \n             fileName.endsWith('.jpg') || \n             fileName.endsWith('.jpeg') ||\n             fileName.endsWith('.tiff') ||\n             fileName.endsWith('.bmp');\n    })\n    .map(attachment => ({\n      filename: attachment.filename,\n      content: attachment.content,\n      contentType: attachment.contentType,\n      source: 'email',\n      sender: inputData.json.from?.text || 'unknown',\n      subject: inputData.json.subject || 'No subject',\n      receivedDate: inputData.json.date || new Date().toISOString()\n    }));\n}\n// Handle direct file uploads\nelse if (inputData.binary) {\n  Object.keys(inputData.binary).forEach(key => {\n    const file = inputData.binary[key];\n    invoiceFiles.push({\n      filename: file.fileName || `upload_${key}`,\n      content: file.data,\n      contentType: file.mimeType,\n      source: 'upload',\n      uploadedDate: new Date().toISOString()\n    });\n  });\n}\n\n// Return each file as separate execution\nreturn invoiceFiles.map((file, index) => ({\n  json: {\n    invoice_id: `INV_${Date.now()}_${index}`,\n    filename: file.filename,\n    source: file.source,\n    sender: file.sender || null,\n    subject: file.subject || null,\n    received_date: file.receivedDate || file.uploadedDate,\n    content_type: file.contentType,\n    processing_status: 'pending',\n    created_at: new Date().toISOString()\n  },\n  binary: {\n    invoice_file: {\n      data: file.content,\n      mimeType: file.contentType,\n      fileName: file.filename\n    }\n  }\n}));"
      },
      "typeVersion": 2
    },
    {
      "id": "44e738e0-652a-40ff-8a9b-d4d8381771ef",
      "name": "ScrapeGraphAI - Extracteur de factures",
      "type": "n8n-nodes-scrapegraphai.scrapegraphAi",
      "position": [
        1744,
        880
      ],
      "parameters": {
        "resource": "scrapeSmartScraper"
      },
      "typeVersion": 1
    },
    {
      "id": "c891bcd4-df84-4fde-930d-e1eba7f679d0",
      "name": "Extracteur et nettoyeur de données",
      "type": "n8n-nodes-base.code",
      "position": [
        2080,
        912
      ],
      "parameters": {
        "jsCode": "// Enhanced data extraction and cleaning\nconst inputData = $input.all()[0];\nconst extractedData = inputData.json.result?.invoice_data || {};\nconst originalMetadata = inputData.json;\n\nfunction cleanAndValidateData(data) {\n  // Clean and standardize extracted data\n  const cleaned = {\n    // Basic invoice info\n    invoice_number: cleanString(data.invoice_number),\n    invoice_date: standardizeDate(data.invoice_date),\n    due_date: standardizeDate(data.due_date),\n    \n    // Vendor information\n    vendor: {\n      name: cleanString(data.vendor_name),\n      address: cleanString(data.vendor_address),\n      tax_id: cleanString(data.vendor_tax_id || data.vendor_vat || data.tax_id),\n      email: cleanEmail(data.vendor_email),\n      phone: cleanPhone(data.vendor_phone)\n    },\n    \n    // Bill to information\n    bill_to: {\n      name: cleanString(data.bill_to_name),\n      address: cleanString(data.bill_to_address)\n    },\n    \n    // Financial data\n    currency: (data.currency || 'USD').toUpperCase(),\n    amounts: {\n      subtotal: parseAmount(data.subtotal),\n      tax_total: parseAmount(data.tax_total),\n      discount_amount: parseAmount(data.discount_amount || '0'),\n      shipping_amount: parseAmount(data.shipping_amount || '0'),\n      total_amount: parseAmount(data.total_amount)\n    },\n    \n    // Line items\n    line_items: cleanLineItems(data.line_items || []),\n    \n    // Additional info\n    payment_terms: cleanString(data.payment_terms),\n    purchase_order: cleanString(data.purchase_order),\n    notes: cleanString(data.notes),\n    \n    // Processing metadata\n    processing_info: {\n      extracted_at: new Date().toISOString(),\n      confidence_score: calculateConfidenceScore(data),\n      data_completeness: calculateCompleteness(data)\n    }\n  };\n  \n  return cleaned;\n}\n\nfunction cleanString(str) {\n  if (!str || str === 'null' || str === 'undefined') return null;\n  return str.toString().trim().replace(/\\s+/g, ' ');\n}\n\nfunction standardizeDate(dateStr) {\n  if (!dateStr || dateStr === 'null') return null;\n  try {\n    const date = new Date(dateStr);\n    return date.toISOString().split('T')[0]; // Return YYYY-MM-DD format\n  } catch {\n    return dateStr; // Return original if parsing fails\n  }\n}\n\nfunction cleanEmail(email) {\n  if (!email || email === 'null') return null;\n  const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n  return emailRegex.test(email) ? email.toLowerCase() : null;\n}\n\nfunction cleanPhone(phone) {\n  if (!phone || phone === 'null') return null;\n  return phone.replace(/[^\\d+\\-\\(\\)\\s]/g, '').trim();\n}\n\nfunction parseAmount(amount) {\n  if (!amount || amount === 'null') return 0;\n  const cleaned = amount.toString().replace(/[^\\d.-]/g, '');\n  return parseFloat(cleaned) || 0;\n}\n\nfunction cleanLineItems(items) {\n  if (!Array.isArray(items)) return [];\n  \n  return items.map(item => ({\n    description: cleanString(item.description),\n    quantity: parseFloat(item.quantity) || 1,\n    unit_price: parseAmount(item.unit_price),\n    total: parseAmount(item.total),\n    tax_rate: cleanString(item.tax_rate),\n    tax_amount: parseAmount(item.tax_amount || '0')\n  })).filter(item => item.description); // Remove items without description\n}\n\nfunction calculateConfidenceScore(data) {\n  let score = 0;\n  const requiredFields = ['invoice_number', 'vendor_name', 'total_amount', 'invoice_date'];\n  \n  requiredFields.forEach(field => {\n    if (data[field] && data[field] !== 'null') score += 25;\n  });\n  \n  return score;\n}\n\nfunction calculateCompleteness(data) {\n  const allFields = [\n    'invoice_number', 'invoice_date', 'due_date', 'vendor_name', \n    'vendor_address', 'total_amount', 'subtotal', 'line_items'\n  ];\n  \n  const completedFields = allFields.filter(field => \n    data[field] && data[field] !== 'null' && \n    (Array.isArray(data[field]) ? data[field].length > 0 : true)\n  ).length;\n  \n  return Math.round((completedFields / allFields.length) * 100);\n}\n\nconst cleanedData = cleanAndValidateData(extractedData);\n\nreturn [{\n  json: {\n    ...originalMetadata,\n    extracted_invoice_data: cleanedData,\n    processing_status: 'extracted',\n    updated_at: new Date().toISOString()\n  },\n  binary: inputData.binary // Preserve binary data for potential reprocessing\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "cc08bf61-cb49-4cb5-be64-a9068c7c0486",
      "name": "Moteur de règles de validation",
      "type": "n8n-nodes-base.code",
      "position": [
        2400,
        944
      ],
      "parameters": {
        "jsCode": "// Comprehensive validation rules for invoice data\nconst inputData = $input.all()[0];\nconst invoiceData = inputData.json.extracted_invoice_data;\nconst validationResults = {\n  is_valid: true,\n  errors: [],\n  warnings: [],\n  validation_score: 0,\n  business_rules: {\n    duplicate_check: 'pending',\n    amount_threshold: 'pending',\n    vendor_verification: 'pending',\n    date_validation: 'pending'\n  }\n};\n\n// Required field validation\nconst requiredFields = [\n  { field: 'invoice_number', message: 'Invoice number is required' },\n  { field: 'vendor.name', message: 'Vendor name is required' },\n  { field: 'amounts.total_amount', message: 'Total amount is required' },\n  { field: 'invoice_date', message: 'Invoice date is required' }\n];\n\nrequiredFields.forEach(({ field, message }) => {\n  const value = getNestedValue(invoiceData, field);\n  if (!value || value === 0) {\n    validationResults.errors.push(message);\n    validationResults.is_valid = false;\n  } else {\n    validationResults.validation_score += 20;\n  }\n});\n\n// Date validation\nif (invoiceData.invoice_date && invoiceData.due_date) {\n  const invoiceDate = new Date(invoiceData.invoice_date);\n  const dueDate = new Date(invoiceData.due_date);\n  \n  if (dueDate < invoiceDate) {\n    validationResults.errors.push('Due date cannot be before invoice date');\n    validationResults.is_valid = false;\n  } else {\n    validationResults.business_rules.date_validation = 'passed';\n  }\n} else {\n  validationResults.business_rules.date_validation = 'failed';\n}\n\n// Amount validation\nconst amounts = invoiceData.amounts;\nif (amounts) {\n  // Check if total matches calculation\n  const calculatedTotal = amounts.subtotal + amounts.tax_total + amounts.shipping_amount - amounts.discount_amount;\n  const totalDifference = Math.abs(calculatedTotal - amounts.total_amount);\n  \n  if (totalDifference > 0.01) {\n    validationResults.warnings.push(`Total amount mismatch: Expected ${calculatedTotal.toFixed(2)}, got ${amounts.total_amount.toFixed(2)}`);\n  }\n  \n  // Amount threshold check (configurable)\n  const amountThreshold = 10000; // $10,000\n  if (amounts.total_amount > amountThreshold) {\n    validationResults.business_rules.amount_threshold = 'requires_approval';\n    validationResults.warnings.push(`High amount invoice requires additional approval: $${amounts.total_amount}`);\n  } else {\n    validationResults.business_rules.amount_threshold = 'passed';\n  }\n} else {\n  validationResults.errors.push('Amount information is missing');\n  validationResults.is_valid = false;\n}\n\n// Vendor validation\nif (invoiceData.vendor && invoiceData.vendor.name) {\n  // Simulate vendor verification (in real scenario, check against approved vendor list)\n  const approvedVendors = [\n    'ABC Company Ltd', 'XYZ Corporation', 'Tech Solutions Inc', \n    'Office Supplies Co', 'Consulting Partners LLC'\n  ];\n  \n  const isApprovedVendor = approvedVendors.some(vendor => \n    vendor.toLowerCase().includes(invoiceData.vendor.name.toLowerCase()) ||\n    invoiceData.vendor.name.toLowerCase().includes(vendor.toLowerCase())\n  );\n  \n  if (isApprovedVendor) {\n    validationResults.business_rules.vendor_verification = 'approved';\n    validationResults.validation_score += 15;\n  } else {\n    validationResults.business_rules.vendor_verification = 'new_vendor';\n    validationResults.warnings.push('Vendor not in approved list - requires verification');\n  }\n}\n\n// Line items validation\nif (invoiceData.line_items && invoiceData.line_items.length > 0) {\n  let lineItemErrors = [];\n  \n  invoiceData.line_items.forEach((item, index) => {\n    if (!item.description) {\n      lineItemErrors.push(`Line item ${index + 1}: Missing description`);\n    }\n    if (item.quantity <= 0) {\n      lineItemErrors.push(`Line item ${index + 1}: Invalid quantity`);\n    }\n    if (item.unit_price <= 0) {\n      lineItemErrors.push(`Line item ${index + 1}: Invalid unit price`);\n    }\n    \n    // Check line total calculation\n    const expectedTotal = item.quantity * item.unit_price;\n    if (Math.abs(expectedTotal - item.total) > 0.01) {\n      lineItemErrors.push(`Line item ${index + 1}: Total calculation error`);\n    }\n  });\n  \n  if (lineItemErrors.length > 0) {\n    validationResults.warnings.push(...lineItemErrors);\n  } else {\n    validationResults.validation_score += 10;\n  }\n} else {\n  validationResults.warnings.push('No line items found');\n}\n\n// Duplicate invoice check (simulate database lookup)\nif (invoiceData.invoice_number) {\n  // In real scenario, check against database\n  const existingInvoices = ['INV-001', 'INV-002', 'INV-003']; // Mock data\n  \n  if (existingInvoices.includes(invoiceData.invoice_number)) {\n    validationResults.errors.push('Duplicate invoice number detected');\n    validationResults.business_rules.duplicate_check = 'duplicate';\n    validationResults.is_valid = false;\n  } else {\n    validationResults.business_rules.duplicate_check = 'unique';\n    validationResults.validation_score += 15;\n  }\n}\n\n// Calculate confidence level\nlet confidenceLevel = 'low';\nif (validationResults.validation_score >= 80) confidenceLevel = 'high';\nelse if (validationResults.validation_score >= 60) confidenceLevel = 'medium';\n\n// Determine approval requirements\nlet requiresApproval = false;\nlet approvalReason = [];\n\nif (validationResults.business_rules.amount_threshold === 'requires_approval') {\n  requiresApproval = true;\n  approvalReason.push('High amount');\n}\n\nif (validationResults.business_rules.vendor_verification === 'new_vendor') {\n  requiresApproval = true;\n  approvalReason.push('New vendor');\n}\n\nif (validationResults.errors.length > 0) {\n  requiresApproval = true;\n  approvalReason.push('Validation errors');\n}\n\nfunction getNestedValue(obj, path) {\n  return path.split('.').reduce((current, key) => current?.[key], obj);\n}\n\nreturn [{\n  json: {\n    ...inputData.json,\n    validation_results: validationResults,\n    confidence_level: confidenceLevel,\n    requires_approval: requiresApproval,\n    approval_reasons: approvalReason,\n    processing_status: validationResults.is_valid ? 'validated' : 'validation_failed',\n    validated_at: new Date().toISOString()\n  },\n  binary: inputData.binary // Preserve binary data\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "7980050d-408f-4b3a-8e10-fad41c143eff",
      "name": "Approbation requise ?",
      "type": "n8n-nodes-base.switch",
      "position": [
        2704,
        928
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "",
                    "rightValue": ""
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "8d543b5f-9d0a-48b0-9589-d9c9c5a0adb1",
      "name": "Générateur de flux d'approbation",
      "type": "n8n-nodes-base.code",
      "position": [
        3008,
        976
      ],
      "parameters": {
        "jsCode": "// Generate approval request with comprehensive details\nconst inputData = $input.all()[0];\nconst invoiceData = inputData.json.extracted_invoice_data;\nconst validation = inputData.json.validation_results;\n\n// Create approval request\nconst approvalRequest = {\n  approval_id: `APPR_${inputData.json.invoice_id}_${Date.now()}`,\n  invoice_id: inputData.json.invoice_id,\n  request_type: 'invoice_approval',\n  priority: determinePriority(inputData.json.approval_reasons),\n  \n  // Invoice summary\n  invoice_summary: {\n    invoice_number: invoiceData.invoice_number,\n    vendor_name: invoiceData.vendor ? invoiceData.vendor.name : 'Unknown',\n    total_amount: invoiceData.amounts ? invoiceData.amounts.total_amount : 0,\n    currency: invoiceData.currency,\n    invoice_date: invoiceData.invoice_date,\n    due_date: invoiceData.due_date\n  },\n  \n  // Approval details\n  approval_reasons: inputData.json.approval_reasons,\n  validation_score: validation.validation_score,\n  confidence_level: inputData.json.confidence_level,\n  \n  // Issues requiring attention\n  attention_required: {\n    errors: validation.errors,\n    warnings: validation.warnings,\n    business_rule_flags: Object.entries(validation.business_rules)\n      .filter(([key, value]) => value === 'requires_approval' || value === 'failed')\n      .map(([key, value]) => ({ rule: key, status: value }))\n  },\n  \n  // Approval workflow\n  workflow_steps: generateApprovalSteps(inputData.json.approval_reasons, invoiceData.amounts ? invoiceData.amounts.total_amount : 0),\n  \n  // Request metadata\n  requested_at: new Date().toISOString(),\n  requested_by: 'system',\n  status: 'pending_approval',\n  \n  // Generate approval message\n  approval_message: generateApprovalMessage(invoiceData, validation, inputData.json.approval_reasons)\n};\n\nfunction determinePriority(reasons) {\n  if (reasons.includes('Validation errors')) return 'high';\n  if (reasons.includes('High amount')) return 'medium';\n  return 'normal';\n}\n\nfunction generateApprovalSteps(reasons, amount) {\n  const steps = [];\n  \n  // Finance team review for high amounts\n  if (amount > 10000) {\n    steps.push({\n      step: 1,\n      approver_role: 'finance_manager',\n      required: true,\n      description: 'Finance manager approval for high-value invoice'\n    });\n  }\n  \n  // Procurement review for new vendors\n  if (reasons.includes('New vendor')) {\n    steps.push({\n      step: steps.length + 1,\n      approver_role: 'procurement_manager',\n      required: true,\n      description: 'Procurement verification for new vendor'\n    });\n  }\n  \n  // Department head approval\n  steps.push({\n    step: steps.length + 1,\n    approver_role: 'department_head',\n    required: true,\n    description: 'Department head final approval'\n  });\n  \n  return steps;\n}\n\nfunction generateApprovalMessage(invoiceData, validation, reasons) {\n  let message = `🧾 **INVOICE APPROVAL REQUEST**\\n\\n`;\n  message += `📋 **Invoice:** ${invoiceData.invoice_number || 'N/A'}\\n`;\n  message += `🏢 **Vendor:** ${invoiceData.vendor ? invoiceData.vendor.name : 'Unknown'}\\n`;\n  \n  const amount = invoiceData.amounts ? invoiceData.amounts.total_amount : 0;\n  const currency = invoiceData.currency || 'USD';\n  message += `💰 **Amount:** ${currency} ${amount.toLocaleString()}\\n`;\n  message += `📅 **Date:** ${invoiceData.invoice_date || 'N/A'}\\n`;\n  message += `⏰ **Due:** ${invoiceData.due_date || 'N/A'}\\n\\n`;\n  \n  message += `🚨 **Approval Required For:**\\n`;\n  reasons.forEach(reason => {\n    message += `• ${reason}\\n`;\n  });\n  \n  if (validation.errors.length > 0) {\n    message += `\\n❌ **Errors:**\\n`;\n    validation.errors.forEach(error => {\n      message += `• ${error}\\n`;\n    });\n  }\n  \n  if (validation.warnings.length > 0) {\n    message += `\\n⚠️ **Warnings:**\\n`;\n    validation.warnings.forEach(warning => {\n      message += `• ${warning}\\n`;\n    });\n  }\n  \n  message += `\\n📊 **Validation Score:** ${validation.validation_score}/100\\n`;\n  message += `🎯 **Confidence:** ${inputData.json.confidence_level.toUpperCase()}\\n\\n`;\n  message += `Please review and approve/reject this invoice.`;\n  \n  return message;\n}\n\nreturn [{\n  json: {\n    ...inputData.json,\n    approval_request: approvalRequest,\n    processing_status: 'pending_approval',\n    updated_at: new Date().toISOString()\n  },\n  binary: inputData.binary // Preserve binary data\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "92ee2ffa-df6f-447c-bc74-bc78a40e90bf",
      "name": "Notification d'approbation",
      "type": "n8n-nodes-base.telegram",
      "position": [
        3360,
        912
      ],
      "webhookId": "5075a6ac-bc09-446d-898e-f5bf9b55d10f",
      "parameters": {
        "text": "={{ $json.approval_request.approval_message }}",
        "chatId": "@invoice_approvals",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e2f6f5d5-a8b8-41df-8113-f45242fa2c9f",
      "name": "Intégration au système comptable",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3584,
        912
      ],
      "parameters": {
        "url": "https://your-accounting-system.com/api/invoices",
        "options": {},
        "sendBody": true,
        "sendHeaders": true,
        "authentication": "predefinedCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "invoice_data",
              "value": "={{ JSON.stringify($json.extracted_invoice_data) }}"
            },
            {
              "name": "validation_results",
              "value": "={{ JSON.stringify($json.validation_results) }}"
            },
            {
              "name": "processing_metadata",
              "value": "={{ JSON.stringify({ invoice_id: $json.invoice_id, source: $json.source, processed_at: $json.updated_at }) }}"
            }
          ]
        },
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "httpHeaderAuth"
      },
      "typeVersion": 4.2
    },
    {
      "id": "ffadff50-4b5e-4cf0-ad78-3f43b3ab9237",
      "name": "Note autocollante - Déclencheurs",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1024,
        -32
      ],
      "parameters": {
        "color": 2,
        "width": 320,
        "height": 1202,
        "content": "# Step 1: Multi-Input Triggers 📧📁\n\n**Flexible Invoice Reception**\n\nTwo trigger options for maximum flexibility:\n\n## Email Trigger:\n- **Purpose**: Automatic processing of emailed invoices\n- **Supported**: PDF, PNG, JPG, JPEG, TIFF, BMP\n- **Features**: Attachment filtering, sender tracking\n- **Polling**: Every 30 seconds\n\n## File Upload Webhook:\n- **Purpose**: Direct file upload processing\n- **Endpoint**: `/invoice-upload`\n- **Method**: POST with file data\n- **Use Case**: Manual uploads, API integrations\n\n## Benefits:\n- Multiple intake channels\n- Automatic file type detection\n- Metadata preservation\n- Source tracking for audit trails"
      },
      "typeVersion": 1
    },
    {
      "id": "3a13dfe2-a654-434f-b8e0-91ddb685b7c3",
      "name": "Note autocollante - Processeur de fichiers",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1344,
        -32
      ],
      "parameters": {
        "color": 3,
        "width": 320,
        "height": 1202,
        "content": "# Step 2: File Processing 🔄\n\n**Smart File Handler**\n\nProcesses incoming files from multiple sources with intelligent routing.\n\n## Key Features:\n- **Multi-source Support**: Email attachments + direct uploads\n- **File Type Validation**: PDF, images only\n- **Metadata Extraction**: Sender, subject, timestamps\n- **Unique ID Generation**: Trackable invoice IDs\n\n## Processing Logic:\n- Filters supported file types\n- Extracts source information\n- Creates processing metadata\n- Prepares for AI extraction\n\n## Output:\n- Clean file objects\n- Processing metadata\n- Binary file data for AI analysis"
      },
      "typeVersion": 1
    },
    {
      "id": "74fde2b5-236f-4e42-a98b-d1a7c43bc9ae",
      "name": "Note autocollante - Extraction IA",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1664,
        -32
      ],
      "parameters": {
        "color": 4,
        "width": 320,
        "height": 1202,
        "content": "# Step 3: AI Invoice Extraction 🤖\n\n**ScrapeGraphAI-Powered Data Extraction**\n\nAdvanced AI extraction of invoice data from PDFs and images.\n\n## Extraction Capabilities:\n- **Basic Info**: Invoice #, dates, amounts\n- **Vendor Details**: Name, address, contact info\n- **Line Items**: Description, qty, price, tax\n- **Financial Data**: Subtotals, taxes, totals\n- **Additional**: PO numbers, terms, notes\n\n## AI Features:\n- Multi-format support (PDF, images)\n- OCR for scanned documents\n- Structured JSON output\n- High accuracy extraction\n\n## Benefits:\n- Eliminates manual data entry\n- Handles various invoice formats\n- Consistent data structure\n- Scalable processing"
      },
      "typeVersion": 1
    },
    {
      "id": "6f42014e-fe4b-4424-9a29-e73f1fc4575f",
      "name": "Note autocollante - Nettoyage des données",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1984,
        -32
      ],
      "parameters": {
        "color": 5,
        "width": 320,
        "height": 1202,
        "content": "# Step 4: Data Cleaning & Enhancement 🧹\n\n**Advanced Data Processing**\n\nCleans and standardizes extracted data for business use.\n\n## Data Cleaning:\n- **Format Standardization**: Dates, amounts, text\n- **Validation**: Email formats, phone numbers\n- **Null Handling**: Missing data management\n- **Type Conversion**: String to numeric conversion\n\n## Enhancement Features:\n- **Confidence Scoring**: Data quality assessment\n- **Completeness Analysis**: Missing field detection\n- **Line Item Processing**: Individual item validation\n- **Metadata Addition**: Processing timestamps\n\n## Quality Assurance:\n- Removes invalid entries\n- Standardizes formats\n- Calculates data reliability\n- Prepares for validation"
      },
      "typeVersion": 1
    },
    {
      "id": "3950a900-13c8-4aa5-b128-e9397220ab52",
      "name": "Note autocollante - Validation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2304,
        -32
      ],
      "parameters": {
        "color": 6,
        "width": 320,
        "height": 1202,
        "content": "# Step 5: Business Rules Validation ✅\n\n**Comprehensive Validation Engine**\n\nApplies business rules and validation logic to ensure data quality.\n\n## Validation Types:\n- **Required Fields**: Critical data presence\n- **Data Integrity**: Amount calculations, date logic\n- **Business Rules**: Vendor approval, amount thresholds\n- **Duplicate Detection**: Invoice number uniqueness\n\n## Validation Results:\n- **Errors**: Critical issues blocking processing\n- **Warnings**: Non-critical issues requiring attention\n- **Scores**: Overall validation quality (0-100)\n- **Business Flags**: Rule-specific status\n\n## Advanced Features:\n- Configurable thresholds\n- Vendor whitelist checking\n- Amount calculation verification\n- Approval requirement detection"
      },
      "typeVersion": 1
    },
    {
      "id": "daf3f597-b104-4c4c-abaf-5363f982a7a0",
      "name": "Note autocollante - Routage d'approbation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2624,
        -32
      ],
      "parameters": {
        "color": 7,
        "width": 320,
        "height": 1202,
        "content": "# Step 6: Approval Routing 🔀\n\n**Intelligent Decision Engine**\n\nRoutes invoices based on validation results and business rules.\n\n## Routing Logic:\n- **Auto-Process**: Clean invoices → Direct to accounting\n- **Approval Required**: Flagged invoices → Approval workflow\n- **Error Handling**: Invalid invoices → Manual review\n\n## Approval Triggers:\n- High amount thresholds\n- New/unverified vendors\n- Validation errors/warnings\n- Data quality issues\n\n## Benefits:\n- Automated decision making\n- Exception handling\n- Compliance enforcement\n- Workflow optimization\n\n## Efficiency:\n- Reduces manual review\n- Focuses attention on exceptions\n- Maintains audit trails\n- Ensures policy compliance"
      },
      "typeVersion": 1
    },
    {
      "id": "b0e3beae-27ec-4543-8be6-b68b3c8ef89d",
      "name": "Note autocollante - Flux d'approbation",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2944,
        -32
      ],
      "parameters": {
        "width": 320,
        "height": 1202,
        "content": "# Step 7: Approval Workflow 👥\n\n**Multi-Stage Approval Process**\n\nGenerates structured approval requests with comprehensive details.\n\n## Approval Features:\n- **Priority Classification**: High/Medium/Normal\n- **Multi-stage Workflow**: Role-based approvals\n- **Detailed Context**: All validation results\n- **Interactive Notifications**: Telegram with buttons\n\n## Approval Stages:\n1. **Finance Manager**: High-value invoices\n2. **Procurement**: New vendor verification\n3. **Department Head**: Final approval\n\n## Rich Context:\n- Invoice summary\n- Validation issues\n- Business rule flags\n- Approval reasoning\n\n## User Experience:\n- Clear approval messages\n- One-click approve/reject\n- Detailed invoice preview\n- Audit trail maintenance"
      },
      "typeVersion": 1
    },
    {
      "id": "cd228530-faa8-4685-a2dd-505ca1d2d2ff",
      "name": "Note autocollante - Intégration système",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3264,
        -32
      ],
      "parameters": {
        "color": 4,
        "width": 544,
        "height": 1202,
        "content": "# Step 8: System Integration 🔗\n\n**Seamless Accounting Integration**\n\nDirect integration with accounting systems for automated processing.\n\n## Integration Features:\n- **API-Based**: RESTful API integration\n- **Structured Data**: Clean JSON payload\n- **Metadata Included**: Processing context\n- **Error Handling**: Retry logic and logging\n\n## Data Payload:\n- Complete invoice data\n- Validation results\n- Processing metadata\n- Audit information\n\n## Supported Systems:\n- QuickBooks\n- SAP\n- NetSuite\n- Xero\n- Custom ERP systems\n\n## Benefits:\n- Eliminates double entry\n- Real-time processing\n- Data consistency\n- Automated reconciliation\n- Audit trail preservation"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "7e6fed6c-3ee0-42af-988e-fb8c404015b5",
  "connections": {
    "4d24fd12-5442-4112-b997-2e6b9ece768c": {
      "main": [
        [
          {
            "node": "4197b894-434f-42b6-a728-b6773af9b54a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4197b894-434f-42b6-a728-b6773af9b54a": {
      "main": [
        [
          {
            "node": "44e738e0-652a-40ff-8a9b-d4d8381771ef",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "7980050d-408f-4b3a-8e10-fad41c143eff": {
      "main": [
        [
          {
            "node": "8d543b5f-9d0a-48b0-9589-d9c9c5a0adb1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b32637a8-8941-4fea-b6cb-b2272d25eaa4": {
      "main": [
        [
          {
            "node": "4197b894-434f-42b6-a728-b6773af9b54a",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "92ee2ffa-df6f-447c-bc74-bc78a40e90bf": {
      "main": [
        [
          {
            "node": "e2f6f5d5-a8b8-41df-8113-f45242fa2c9f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "cc08bf61-cb49-4cb5-be64-a9068c7c0486": {
      "main": [
        [
          {
            "node": "7980050d-408f-4b3a-8e10-fad41c143eff",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c891bcd4-df84-4fde-930d-e1eba7f679d0": {
      "main": [
        [
          {
            "node": "cc08bf61-cb49-4cb5-be64-a9068c7c0486",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8d543b5f-9d0a-48b0-9589-d9c9c5a0adb1": {
      "main": [
        [
          {
            "node": "92ee2ffa-df6f-447c-bc74-bc78a40e90bf",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "44e738e0-652a-40ff-8a9b-d4d8381771ef": {
      "main": [
        [
          {
            "node": "c891bcd4-df84-4fde-930d-e1eba7f679d0",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Avancé - Traitement des factures, Résumé IA

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Informations sur le workflow
Niveau de difficulté
Avancé
Nombre de nœuds18
Catégorie2
Types de nœuds8
Description de la difficulté

Adapté aux utilisateurs avancés, avec des workflows complexes contenant 16+ nœuds

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34