8
n8n 中文网amn8n.com

AI驱动的发票提取与自动化系统

高级

这是一个Invoice Processing, AI Summarization领域的自动化工作流,包含 32 个节点。主要使用 If, Set, Code, Gmail, GoogleDrive 等节点。 使用Gemini AI、Google Sheets和Gmail通知提取和处理发票

前置要求
  • Google 账号和 Gmail API 凭证
  • Google Drive API 凭证
  • Google Sheets API 凭证
  • Google Gemini API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "EFHIQBQltrt7yPxS",
  "meta": {
    "instanceId": "3caab7a077d6a24bf913833250143556c3033c05ff2ea30885e13d0164c0cec2",
    "templateCredsSetupCompleted": true
  },
  "name": "AI驱动的发票提取与自动化系统",
  "tags": [],
  "nodes": [
    {
      "id": "a6a71e48-04d8-4a73-af89-dc5ab7720788",
      "name": "当收到聊天消息时",
      "type": "@n8n/n8n-nodes-langchain.chatTrigger",
      "position": [
        -256,
        672
      ],
      "webhookId": "8c5b49b9-7491-497f-9cd5-22515ea25ba0",
      "parameters": {
        "options": {
          "allowFileUploads": true,
          "allowedFilesMimeTypes": " image/*, text/*, application/pdf"
        }
      },
      "executeOnce": false,
      "typeVersion": 1.3
    },
    {
      "id": "1f5025c5-043e-4934-8ba9-9964becf178c",
      "name": "分析图片1",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        128,
        672
      ],
      "parameters": {
        "text": "What's in this image? Extract all the data And give a very formatted. Output Which has Differently listed Things of invoice",
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-1.5-flash",
          "cachedResultName": "models/gemini-1.5-flash"
        },
        "options": {},
        "resource": "image",
        "inputType": "binary",
        "operation": "analyze",
        "binaryPropertyName": "data0"
      },
      "credentials": {
        "googlePalmApi": {
          "id": "sSV7NS6JXz0qjL2i",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f504934f-3551-4399-a610-f9f8ec1cd246",
      "name": "AI Agent1",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        448,
        672
      ],
      "parameters": {
        "text": "=Here is the invoice data - {{ $json.content.parts[0].text }}",
        "options": {
          "systemMessage": "=You have invoice data.  \nYour task is to structure that data strictly in JSON.  \n\nRules:   \n- Do not add \\n or \\ in the output.  \n\nOutput format:\n\n{\n  \"invoice_id\": \"\",\n  \"shop_name\": \"\",\n  \"date\": \"\",\n  \"Total\": \"\",\n  \"items\": [\n    {\n      \"Item_Name\": \"\",\n      \"Quantity\": \"\",\n      \"Unit_Price\": \"\",\n      \"Currency\": \"\"\n    }\n  ],\n  \"optional_fields\": {\n    \"Entry_ID\": \"\",\n    \"Time\": \"\",\n    \"Type\": \"\",\n    \"Category\": \"\",\n    \"Subcategory\": \"\",\n    \"Description\": \"\",\n    \"Shop_Address\": \"\",\n    \"Payment_Method\": \"\",\n    \"GST_Rate\": \"\",\n    \"GST_Amount\": \"\",\n    \"Receipt_Link\": \"\",\n    \"Receipt_Number\": \"\",\n    \"Remarks\": \"\",\n    \"Tags\": \"\",\n    \"Created_Date\": \"\",\n    \"Modified_Date\": \"\",\n    \"Status\": \"\",\n    \"Duplicate_Check\": \"\"\n  }\n}\n"
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "f0999a88-8eb2-407f-8d50-6ca4118bb3df",
      "name": "Google Gemini聊天模型1",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        512,
        928
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "id": "sSV7NS6JXz0qjL2i",
          "name": "Google Gemini(PaLM) Api account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0ee67ef8-d38c-4a78-9267-5e482ef7b7fd",
      "name": "获取数据",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1280,
        672
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{ $json.output.invoice_id }}",
              "lookupColumn": "Entry_ID"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1240712847,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1T1oFlLqrauskPHAHbRixnIbx4wSK7pY3J5EGlpFzZTQ/edit#gid=1240712847",
          "cachedResultName": "Expense_Tracker"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1T1oFlLqrauskPHAHbRixnIbx4wSK7pY3J5EGlpFzZTQ",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1T1oFlLqrauskPHAHbRixnIbx4wSK7pY3J5EGlpFzZTQ/edit?usp=drivesdk",
          "cachedResultName": "expense_tracker_n8n"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "2cLBwxQBfcaJ1DCN",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.7,
      "alwaysOutputData": true
    },
    {
      "id": "6c465765-d7ca-4f09-9720-8799132ec5d0",
      "name": "将数据转换为JSON结构格式",
      "type": "n8n-nodes-base.set",
      "position": [
        912,
        672
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "9f859c68-cdaa-41d0-bc15-a6ab7db24906",
              "name": "output",
              "type": "object",
              "value": "={{ $json.output }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c25a3bdb-deef-4d9f-a2e3-2471bc1107fa",
      "name": "检查表中数据是否存在",
      "type": "n8n-nodes-base.if",
      "position": [
        1680,
        672
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "3a5e1594-1d46-4a0c-81c9-dcdc5243931c",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ Object.keys($items(\"Get data\")[0].json).length === 0 }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0997e665-a8c5-4bdb-90f5-5d5304a0f355",
      "name": "上传发票到Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        80,
        912
      ],
      "parameters": {
        "name": "=invoice_data",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "root",
          "cachedResultUrl": "https://drive.google.com/drive",
          "cachedResultName": "/ (Root folder)"
        },
        "inputDataFieldName": "data0"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "dpqimR5rZMDgJjvs",
          "name": "Google Drive account"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "65f8bf39-6813-4def-8cac-274eb5db6c9e",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -384,
        352
      ],
      "parameters": {
        "width": 368,
        "height": 496,
        "content": "## 节点1:**当收到聊天消息时**"
      },
      "typeVersion": 1
    },
    {
      "id": "bb06ce88-cbc3-4003-a2a8-3fb9b576d371",
      "name": "无缺失字段 - 使用payload 2添加新数据",
      "type": "n8n-nodes-base.code",
      "position": [
        3152,
        480
      ],
      "parameters": {
        "jsCode": "// Function Item node\n// Ensures you only pass through the payload JSON if status = \"ok\"\n\n// 1. Get current item\nconst input = $json;\n\n// 2. Check status\nif (input.status && input.status === \"ok\") {\n  // ✅ Status is ok → use the payload JSON\n  // 🔽 PLACEHOLDER: replace this with the node where your invoice payload lives\n  const payload = $('Make data in json structure format').first().json.output;\n\n  return payload;\n\n} else {\n  // ❌ Status not ok → return error message\n  return {\n    status: \"error\",\n    message: \"Missing Mandatory field(s) or status not ok\"\n  };\n}\n"
      },
      "typeVersion": 2
    },
    {
      "id": "070e102e-3fd3-4caf-81b6-82eae65a3b00",
      "name": "如果 - 检查缺失字段",
      "type": "n8n-nodes-base.if",
      "position": [
        2768,
        496
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "6b4e00d8-0504-44a0-bf5b-5d5dd867138e",
              "operator": {
                "name": "filter.operator.equals",
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "ok"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "84f5c157-36a7-491c-ba9e-52e5d3b08039",
      "name": "通过邮件发送缺失字段错误",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3440,
        976
      ],
      "webhookId": "acbee7e7-047d-404b-a6c1-c09861fc3c67",
      "parameters": {
        "sendTo": "xyz@gmail.com",
        "message": "=Missing filed - {{ $json.missing_fields.map(field => field).join(', ') }}\n",
        "options": {},
        "subject": "Missing filed error"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "zystIXitEOECXALa",
          "name": "Gmail account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "c33ae480-922e-4596-bd5a-dcd3a6b4aa93",
      "name": "重复条目发送邮件",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2080,
        992
      ],
      "webhookId": "6ef65cb6-499f-4893-9739-b5f277bd8931",
      "parameters": {
        "sendTo": "xyz@gmail.com",
        "message": "=<html>\n  <body style=\"font-family: Arial, sans-serif; color: #333;\">\n    <h2 style=\"color:#d9534f;\">⚠ Invoice Already Exists</h2>\n    <p>Hello,</p>\n    <p>The invoice you attempted to add already exists in the Google Sheet. Here are the details:</p>\n\n    <table style=\"border-collapse: collapse; width: 100%; margin: 16px 0;\">\n      <tr>\n        <td style=\"border: 1px solid #ccc; padding: 8px;\"><strong>Invoice ID</strong></td>\n        <td style=\"border: 1px solid #ccc; padding: 8px;\">{{ $json.invoice_id }}</td>\n      </tr>\n      <tr>\n        <td style=\"border: 1px solid #ccc; padding: 8px;\"><strong>Company Name</strong></td>\n        <td style=\"border: 1px solid #ccc; padding: 8px;\">{{ $json.Shop_Name }}</td>\n      </tr>\n      <tr>\n        <td style=\"border: 1px solid #ccc; padding: 8px;\"><strong>Date</strong></td>\n        <td style=\"border: 1px solid #ccc; padding: 8px;\"> {{ $json.Date }} </td>\n      </tr>\n      <tr>\n        <td style=\"border: 1px solid #ccc; padding: 8px;\"><strong>Total</strong></td>\n        <td style=\"border: 1px solid #ccc; padding: 8px;\">{{ $json.Total_Amount }}</td>\n      </tr>\n      <tr>\n        <td style=\"border: 1px solid #ccc; padding: 8px;\"><strong>Items</strong></td>\n        <td style=\"border: 1px solid #ccc; padding: 8px;\">{{ $json.Item_Name }}</td>\n      </tr>\n    </table>\n\n    <p style=\"margin-top:16px;\">✅ No changes were made to your sheet, since this record already exists.</p>\n    <p>Kind regards,<br>Your Automated Invoice System</p>\n  </body>\n</html>\n",
        "options": {},
        "subject": "=Invoice Already Exists – {{ $json.invoice_id }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "zystIXitEOECXALa",
          "name": "Gmail account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "444d68a3-9a32-4caf-a930-2b4b83cc92d9",
      "name": "使用payload添加新数据",
      "type": "n8n-nodes-base.code",
      "position": [
        2064,
        496
      ],
      "parameters": {
        "jsCode": "// Function Item node\n// This makes sure you always get the invoice JSON payload, even if Get data is empty.\n\n// 1. Get what Google Sheets returned\nconst sheetItem = $items(\"Get data\") && $items(\"Get data\")[0] \n  ? $items(\"Get data\")[0].json \n  : {};\n\n// 2. Check if it's empty\nconst sheetEmpty = Object.keys(sheetItem).length === 0;\n\n// 3. If empty → use your original invoice JSON instead\n//    >>> REPLACE the placeholder below with the node that has your invoice JSON <<<\n// Example: $items(\"Edit Fields\")[0].json OR paste your raw invoice object\nconst invoicePayload = sheetEmpty \n  ? (\n      // 🔽 PLACEHOLDER: replace this line with your real JSON source\n      $('Make data in json structure format').first().json.output\n    )\n  : sheetItem;\n\n// 4. Return only the payload JSON\nreturn invoicePayload;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "5f78f6aa-9b9a-46b5-8d92-5b2d8cc89be2",
      "name": "将数据追加到表格",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3568,
        480
      ],
      "parameters": {
        "columns": {
          "value": {
            "Date": "={{ $json.date }}",
            "Time": "=",
            "Type": "=",
            "Status": "={{ $json.optional_fields.Status }}",
            "Category": "=",
            "Currency": "={{ $json.items[3].Currency }}",
            "Entry_ID": "={{ $json.payload.invoice_id }}",
            "GST_Rate": "={{ $json.optional_fields.GST_Rate }}",
            "Quantity": "={{ $json.items.map(item => item.Quantity).join(', ') }}",
            "Item_Name": "={{ $json.items.map(item => item.Item_Name).join(', ') }}",
            "Shop_Name": "={{ $json.shop_name }}",
            "GST_Amount": "={{ $json.optional_fields.GST_Amount }}",
            "Unit_Price": "={{ $json.items.map(item => item.Unit_Price).join(', ') }}\n",
            "invoice_id": "={{ $json.invoice_id }}",
            "Description": "={{ $json.optional_fields.Description }}",
            "Subcategory": "=",
            "Created_Date": "={{ $json.date }}",
            "Shop_Address": "={{ $json.optional_fields.Shop_Address }}",
            "Total_Amount": "={{ $json.Total }}",
            "Modified_Date": "={{ $json.optional_fields.Created_Date }}",
            "Payment_Method": "={{ $json.optional_fields.Payment_Method }}"
          },
          "schema": [
            {
              "id": "Entry_ID",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Entry_ID",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Time",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Category",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Subcategory",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Subcategory",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Item_Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Item_Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Description",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Description",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Quantity",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Quantity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Unit",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Unit",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Unit_Price",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Unit_Price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Total_Amount",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Total_Amount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Currency",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Currency",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Shop_Name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Shop_Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Shop_Address",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Shop_Address",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Payment_Method",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Payment_Method",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "GST_Rate",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "GST_Rate",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "GST_Amount",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "GST_Amount",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Receipt_Link",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Receipt_Link",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Receipt_Number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Receipt_Number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Remarks",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Remarks",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Tags",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Tags",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Created_Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Created_Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Modified_Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Modified_Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Duplicate_Check",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Duplicate_Check",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "invoice_id",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "invoice_id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "shop_name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "shop_name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "date",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Total",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Total",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "items",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "items",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "optional_fields",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "optional_fields",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Entry_ID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1240712847,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1T1oFlLqrauskPHAHbRixnIbx4wSK7pY3J5EGlpFzZTQ/edit#gid=1240712847",
          "cachedResultName": "Expense_Tracker"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1T1oFlLqrauskPHAHbRixnIbx4wSK7pY3J5EGlpFzZTQ",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1T1oFlLqrauskPHAHbRixnIbx4wSK7pY3J5EGlpFzZTQ/edit?usp=drivesdk",
          "cachedResultName": "expense_tracker_n8n"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "2cLBwxQBfcaJ1DCN",
          "name": "Google Sheets account"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "5042aa5c-5d27-4e91-bb34-48adbb466148",
      "name": "检查必填字段",
      "type": "n8n-nodes-base.code",
      "position": [
        2400,
        496
      ],
      "parameters": {
        "jsCode": "// Function Item node\n// Check if mandatory fields are present before appending to Google Sheet\n\n// 1. Get the invoice payload (replace with your correct source node if needed)\nconst payload = $('Make data in json structure format').first().json.output;\n\n// 2. Define mandatory fields\nconst mandatoryFields = [\"invoice_id\", \"shop_name\", \"date\", \"Total\", \"items\"];\n\n// 3. Check missing fields\nconst missing = mandatoryFields.filter(f => {\n  if (f === \"items\") {\n    return !payload.items || !Array.isArray(payload.items) || payload.items.length === 0;\n  }\n  return !payload[f] || payload[f].toString().trim() === \"\";\n});\n\n// 4. If missing → return error\nif (missing.length > 0) {\n  return {\n    json: {\n      status: \"error\",\n      message: \"Missing Mandatory field(s)\",\n      missing_fields: missing\n    }\n  };\n}\n\n// 5. If all present → return full payload\nreturn {\n  json: {\n    status: \"ok\",\n    payload // 🔽 This is the invoice JSON you’ll pass to Google Sheets\n  }\n};\n"
      },
      "typeVersion": 2
    },
    {
      "id": "e9f03e55-74ba-4576-8807-0b34490a809f",
      "name": "发送成功邮件",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3968,
        480
      ],
      "webhookId": "6ef65cb6-499f-4893-9739-b5f277bd8931",
      "parameters": {
        "sendTo": "xyz@gmail.com",
        "message": "=<!doctype html>\n<html>\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\" />\n<style>\n  /* Basic reset for email */\n  body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }\n  table { border-collapse: collapse !important; }\n  img { border: 0; height: auto; line-height: 100%; outline: none; text-decoration: none; display: block; }\n  body { margin: 0; padding: 0; width: 100% !important; font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif; background-color: #f4f6fb; color: #222; }\n\n  /* Container */\n  .email-wrap {\n    width: 100%;\n    padding: 28px 16px;\n    background: linear-gradient(180deg, #f7f9ff 0%, #f4f6fb 100%);\n  }\n  .card {\n    max-width: 680px;\n    margin: 0 auto;\n    background: #ffffff;\n    border-radius: 14px;\n    box-shadow: 0 10px 30px rgba(29,41,81,0.08);\n    overflow: hidden;\n    border: 1px solid rgba(29,41,81,0.04);\n  }\n  .card-header {\n    padding: 28px 28px 18px 28px;\n    background: linear-gradient(90deg,#5b8cff,#2d6df6);\n    color: #fff;\n  }\n  .logo {\n    font-weight: 700;\n    letter-spacing: -0.2px;\n    font-size: 18px;\n  }\n  .title {\n    margin: 8px 0 0 0;\n    font-size: 20px;\n    font-weight: 700;\n  }\n  .card-body {\n    padding: 22px 28px;\n  }\n\n  /* Info block */\n  .info {\n    display: flex;\n    gap: 14px;\n    flex-wrap: wrap;\n    margin-bottom: 18px;\n  }\n  .info .info-item {\n    flex: 1 1 240px;\n    background: linear-gradient(180deg,#fbfdff,#f7f9ff);\n    border-radius: 10px;\n    padding: 12px 14px;\n    border: 1px solid rgba(13,34,84,0.04);\n  }\n  .info .label {\n    display: block;\n    font-size: 12px;\n    color: #5b6b8a;\n    margin-bottom: 6px;\n  }\n  .info .value {\n    font-weight: 600;\n    color: #17233d;\n    font-size: 15px;\n  }\n\n  /* Items & totals */\n  .items {\n    width: 100%;\n    border-collapse: collapse;\n    margin-top: 8px;\n    margin-bottom: 14px;\n    font-size: 14px;\n  }\n  .items th {\n    text-align: left;\n    font-size: 12px;\n    font-weight: 700;\n    color: #4b5b7a;\n    padding: 8px 0;\n    border-bottom: 1px solid rgba(72,84,112,0.06);\n  }\n  .items td {\n    padding: 10px 0;\n    color: #243142;\n    vertical-align: top;\n  }\n  .items .muted { color: #73809a; font-weight: 500; font-size: 13px; }\n\n  .total-row {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    padding-top: 14px;\n    border-top: 1px dashed rgba(29,41,81,0.06);\n    margin-top: 10px;\n  }\n  .total-label { color: #5b6b8a; font-weight: 600; }\n  .total-value {\n    background: linear-gradient(90deg,#fff0f6,#fff);\n    color: #d6336c;\n    font-weight: 800;\n    font-size: 18px;\n    padding: 8px 14px;\n    border-radius: 8px;\n    border: 1px solid rgba(214,51,108,0.08);\n  }\n\n  /* Footer */\n  .footer {\n    padding: 18px 28px;\n    font-size: 13px;\n    color: #627089;\n    background: #fbfdff;\n    border-top: 1px solid rgba(29,41,81,0.02);\n  }\n  .cta {\n    display:inline-block;\n    margin-top: 10px;\n    padding: 8px 14px;\n    border-radius: 10px;\n    font-weight: 700;\n    text-decoration: none;\n    color: #fff;\n    background: linear-gradient(90deg,#2d6df6,#5b8cff);\n  }\n\n  /* Responsive */\n  @media (max-width:480px) {\n    .card-header { padding: 20px; }\n    .card-body { padding: 16px; }\n    .info { gap: 8px; }\n    .info .info-item { flex-basis: 100%; }\n  }\n</style>\n</head>\n<body>\n  <div class=\"email-wrap\" role=\"article\" aria-label=\"Invoice notification\">\n    <div class=\"card\" role=\"article\">\n      <div class=\"card-header\">\n        <div class=\"logo\">Invoice Bot</div>\n        <div class=\"title\">New Invoice Added</div>\n      </div>\n\n      <div class=\"card-body\">\n        <!-- Basic info -->\n        <div class=\"info\" aria-hidden=\"false\">\n          <div class=\"info-item\" role=\"group\" aria-label=\"Invoice ID\">\n            <span class=\"label\">Invoice ID</span>\n            <div class=\"value\">New INVOICE - {{ $json.invoice_id }}</div>\n          </div>\n\n          <div class=\"info-item\" role=\"group\" aria-label=\"Company name\">\n            <span class=\"label\">Company</span>\n            <div class=\"value\">{{ $json.Shop_Name }}</div>\n          </div>\n\n          <div class=\"info-item\" role=\"group\" aria-label=\"Date\">\n            <span class=\"label\">Date</span>\n            <div class=\"value\">{{ $json.Date }}</div>\n          </div>\n        </div>\n\n        <!-- Items table -->\n        <table class=\"items\" role=\"table\" aria-label=\"Invoice items\">\n          <thead>\n            <tr>\n              <th>Items</th>\n              <th style=\"text-align:right\">Price</th>\n            </tr>\n          </thead>\n          <tbody>\n            <tr>\n              <td class=\"muted\">{{ $json.Item_Name }}</td>\n              <td style=\"text-align:right;\" class=\"muted\">{{ $json.Total_Amount }}</td>\n            </tr>\n          </tbody>\n        </table>\n\n        <!-- Total -->\n        <div class=\"total-row\" role=\"note\" aria-live=\"polite\">\n          <div class=\"total-label\">Total</div>\n          <div class=\"total-value\">{{ $json.Total_Amount }}</div>\n        </div>\n\n        <!-- Call to action / small note -->\n        <div style=\"margin-top:16px; font-size:13px; color:#5b6b8a;\">\n          Saved to your sheet and Drive. <a href=\"#\" class=\"cta\">Open Dashboard</a>\n        </div>\n      </div>\n\n      <div class=\"footer\">\n        <div>Auto-synced by your Invoice System • <strong>{{ $json.invoice_id }}</strong></div>\n        <div style=\"margin-top:8px;\">If something looks off, check the original file in your Drive or open the dashboard to edit.</div>\n      </div>\n    </div>\n  </div>\n</body>\n</html>\n",
        "options": {},
        "subject": "=New invoice - {{ $json.invoice_id }}  added in the sheet. "
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "zystIXitEOECXALa",
          "name": "Gmail account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "3a1e1818-7feb-4a7a-9d9d-a98b7bbb3c77",
      "name": "便签2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        352
      ],
      "parameters": {
        "color": 5,
        "width": 384,
        "height": 512,
        "content": "# 节点3:AI Agent1"
      },
      "typeVersion": 1
    },
    {
      "id": "016dec77-8044-4bf1-91e2-04347f01b81e",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        0,
        352
      ],
      "parameters": {
        "color": 3,
        "width": 352,
        "height": 496,
        "content": "## 节点2:**分析图片1**"
      },
      "typeVersion": 1
    },
    {
      "id": "d04bddae-b8e8-4bdb-a12b-4cad195b739f",
      "name": "便签3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        368,
        880
      ],
      "parameters": {
        "color": 6,
        "width": 384,
        "height": 544,
        "content": ""
      },
      "typeVersion": 1
    },
    {
      "id": "7e2078a0-b8ee-48dc-9649-06695fa7b10b",
      "name": "便签4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1152,
        352
      ],
      "parameters": {
        "width": 368,
        "height": 512,
        "content": "## 节点6:**获取数据**"
      },
      "typeVersion": 1
    },
    {
      "id": "b147bb54-67f2-41fd-9f58-e68f58e82dfc",
      "name": "便签5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        768,
        352
      ],
      "parameters": {
        "color": 2,
        "width": 368,
        "height": 512,
        "content": "## 节点5:**将数据转换为JSON结构格式**"
      },
      "typeVersion": 1
    },
    {
      "id": "4fe6abc8-d092-4ae5-aab9-76b31d157e65",
      "name": "便签6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1936,
        160
      ],
      "parameters": {
        "color": 4,
        "width": 336,
        "height": 496,
        "content": "## 节点8:**使用payload添加新数据**"
      },
      "typeVersion": 1
    },
    {
      "id": "65ff906c-24b0-43fb-af3a-ed8b2382057f",
      "name": "便签7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2288,
        160
      ],
      "parameters": {
        "color": 3,
        "width": 336,
        "height": 496,
        "content": "## 节点9:**检查必填字段**"
      },
      "typeVersion": 1
    },
    {
      "id": "257b48c4-2f8d-4ead-9d45-37b5130151a6",
      "name": "便签8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2640,
        160
      ],
      "parameters": {
        "color": 5,
        "width": 352,
        "height": 496,
        "content": "## 节点10:**如果 – 检查缺失字段**"
      },
      "typeVersion": 1
    },
    {
      "id": "d36fab00-4dc9-44e9-b071-e77500233c3c",
      "name": "便签9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3008,
        160
      ],
      "parameters": {
        "width": 400,
        "height": 496,
        "content": "## 节点11:**无缺失字段 – 使用payload 2添加新数据**"
      },
      "typeVersion": 1
    },
    {
      "id": "c1e60d32-3270-4440-ab23-dd8f0a3fe778",
      "name": "便签 10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3424,
        160
      ],
      "parameters": {
        "color": 5,
        "width": 384,
        "height": 496,
        "content": "## 节点12:**将数据追加到表格**"
      },
      "typeVersion": 1
    },
    {
      "id": "7641cc35-64e1-439d-84bb-4631737d7dd8",
      "name": "便签 11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3824,
        160
      ],
      "parameters": {
        "width": 384,
        "height": 496,
        "content": "## 节点13:**发送成功邮件**"
      },
      "typeVersion": 1
    },
    {
      "id": "89bd82ca-4f6b-42eb-8899-517915dfb83e",
      "name": "便签12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1536,
        352
      ],
      "parameters": {
        "color": 3,
        "width": 384,
        "height": 512,
        "content": "## 节点7:**检查表中数据是否存在**"
      },
      "typeVersion": 1
    },
    {
      "id": "6b96884c-eefe-4ec5-a5ce-e148e2130901",
      "name": "便签13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1936,
        672
      ],
      "parameters": {
        "width": 400,
        "height": 512,
        "content": "## 节点8.1:**重复条目发送邮件**"
      },
      "typeVersion": 1
    },
    {
      "id": "9b5aeb91-0f7f-465a-b774-bb1f5fed0869",
      "name": "便签14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3264,
        672
      ],
      "parameters": {
        "color": 3,
        "width": 448,
        "height": 496,
        "content": "## 节点11.1:**通过邮件发送缺失字段错误**"
      },
      "typeVersion": 1
    },
    {
      "id": "374ea423-b33d-4e4e-9a3e-ec3adbffbbbe",
      "name": "便签15",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -96,
        864
      ],
      "parameters": {
        "color": 5,
        "width": 448,
        "height": 480,
        "content": ""
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "d48a8383-b848-421a-885c-6a06a77392e2",
  "connections": {
    "Get data": {
      "main": [
        [
          {
            "node": "check if Data exist or not in table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent1": {
      "main": [
        [
          {
            "node": "Make data in json structure format",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Analyze image1": {
      "main": [
        [
          {
            "node": "AI Agent1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append data to sheet": {
      "main": [
        [
          {
            "node": "Send successful email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Mandatory fields": {
      "main": [
        [
          {
            "node": "If -  check missing field",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload invoice to drive": {
      "main": [
        []
      ]
    },
    "Google Gemini Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent1",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "If -  check missing field": {
      "main": [
        [
          {
            "node": "no missing field - new data add using payload 2 ",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send missing field error on mail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New data add using payload": {
      "main": [
        [
          {
            "node": "Check Mandatory fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When chat message received": {
      "main": [
        [
          {
            "node": "Analyze image1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Upload invoice to drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Make data in json structure format": {
      "main": [
        [
          {
            "node": "Get data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "check if Data exist or not in table": {
      "main": [
        [
          {
            "node": "New data add using payload",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Duplicate entry send mail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "no missing field - new data add using payload 2 ": {
      "main": [
        [
          {
            "node": "Append data to sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

复制上方的 JSON 配置代码,在您的 n8n 实例中创建新工作流并选择「从 JSON 导入」,粘贴配置后根据需要修改凭证设置即可。

这个工作流适合什么场景?

高级 - 发票处理, AI 摘要总结

需要付费吗?

本工作流完全免费,您可以直接导入使用。但请注意,工作流中使用的第三方服务(如 OpenAI API)可能需要您自行付费。

工作流信息
难度等级
高级
节点数量32
分类2
节点类型11
难度说明

适合高级用户,包含 16+ 个节点的复杂工作流

作者
Yashraj singh sisodiya

Yashraj singh sisodiya

@theyashsisodiya

an AI automation enthusiast.

外部链接
在 n8n.io 查看

分享此工作流