8
n8n 中文网amn8n.com

现金核对

中级

这是一个Content Creation, Multimodal AI领域的自动化工作流,包含 15 个节点。主要使用 Code, MistralAi, ManualTrigger, MicrosoftExcel, Agent 等节点。 通过 Mistral AI 和 OpenAI GPT-4 实现发票与银行对账单核对的自动化

前置要求
  • OpenAI API Key
工作流预览
可视化展示节点连接关系,支持缩放和平移
导出工作流
复制以下 JSON 配置到 n8n 导入,即可使用此工作流
{
  "id": "n4bNr0cnmlkuN8fy",
  "meta": {
    "instanceId": "db1715da5f21adba44ce4ea3b08abb06cd1771e876f5ad2751fcafd78c5eb9dc",
    "templateCredsSetupCompleted": true
  },
  "name": "现金核对",
  "tags": [
    {
      "id": "7Hqs1zOnO1KyMmlS",
      "name": "Cashreconciliation",
      "createdAt": "2025-09-25T22:03:57.474Z",
      "updatedAt": "2025-09-25T22:03:57.474Z"
    },
    {
      "id": "HdENOIIKDc5O1stL",
      "name": "Accountant",
      "createdAt": "2025-09-25T22:04:06.515Z",
      "updatedAt": "2025-09-25T22:04:06.515Z"
    },
    {
      "id": "kAdvJMsTQvyVnrF9",
      "name": "AccountReceivable",
      "createdAt": "2025-09-25T22:04:25.528Z",
      "updatedAt": "2025-09-25T22:04:25.528Z"
    },
    {
      "id": "lsoR6uHgfiOrR6C6",
      "name": "OrdertoCash",
      "createdAt": "2025-09-25T22:04:29.775Z",
      "updatedAt": "2025-09-25T22:04:29.775Z"
    },
    {
      "id": "uKun50piys98JE3C",
      "name": "Invoices",
      "createdAt": "2025-09-18T00:47:51.695Z",
      "updatedAt": "2025-09-18T00:47:51.695Z"
    }
  ],
  "nodes": [
    {
      "id": "451c356d-2215-4c59-8f92-40678b080c2b",
      "name": "点击\"执行工作流\"时",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        224,
        0
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "8e42332e-f1cb-41f8-a0e1-f37b6ab3e75a",
      "name": "提取文本",
      "type": "n8n-nodes-base.mistralAi",
      "position": [
        1344,
        0
      ],
      "parameters": {
        "options": {
          "batch": false
        },
        "binaryProperty": "Data"
      },
      "credentials": {
        "mistralCloudApi": {
          "id": "<Mistral OCR API KEY>",
          "name": "Mistral Cloud account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a8014539-db77-4ade-97c5-d42077119291",
      "name": "获取银行对账单",
      "type": "n8n-nodes-base.microsoftOneDrive",
      "position": [
        896,
        0
      ],
      "parameters": {
        "fileId": "01WVQSKIIAS4II25G37JGK6QHSYCDROS76",
        "operation": "get"
      },
      "credentials": {
        "microsoftOneDriveOAuth2Api": {
          "id": "<Microsoft One Drive API KEY>",
          "name": "Microsoft Drive account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "822968f4-1066-417d-9521-d1064f511bb7",
      "name": "JavaScript 代码",
      "type": "n8n-nodes-base.code",
      "position": [
        672,
        0
      ],
      "parameters": {
        "jsCode": "// n8n Code node\n// Input: 1 item that contains `json.data` array\n// Output: one item with a single JSON array erpLedger\n\nconst data = items[0].json.data;   // all rows live here\n\nconst ledger = data\n  .map(d => {\n    const row = d.values?.[0];     // [\"Ansys\", 1, \"08-15-2025\", 5096.96]\n    if (!row || row.length < 4) return null;\n\n    return {\n      CustomerName: row[0],              // first column\n      invoice_number: row[1],            // second column\n      invoice_due_date: row[2],          // third column\n      amount: Number(row[3]),            // fourth column\n      id: String(row[1])                 // use invoice number as ID\n    };\n  })\n  .filter(r => r !== null);\n\nreturn [\n  {\n    json: {\n      erpLedger: ledger\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "3a9cc7b1-aeeb-4f5f-b61f-db5fe3dfc402",
      "name": "OpenAI 聊天模型1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1568,
        224
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {
          "temperature": 0
        }
      },
      "credentials": {
        "openAiApi": {
          "id": "<OPENAI API KEY>",
          "name": "OpenAi account 2"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "99f88b81-4e58-4a5d-a47a-67f6ba0771a4",
      "name": "获取交易、匹配项、摘要",
      "type": "n8n-nodes-base.code",
      "position": [
        1920,
        0
      ],
      "parameters": {
        "jsCode": "// n8n Code node\n// Input: one item with .json.output (string containing transactions, matches, summary)\n// Output: multiple items (one per row in the reconciliation table)\n\nconst raw = $input.first().json.output;\n\n// ---------- Step 1: Parse safely ----------\nlet transactions = [];\nlet matches = [];\nlet summary = {};\n\ntry {\n  // Normalize separators: replace triple dashes with blank lines\n  const normalized = raw.replace(/---/g, \"\\n\\n\");\n\n  // Split into JSON blocks\n  const blocks = normalized\n    .split(/\\n\\s*\\n/)\n    .map(b => b.trim())\n    .filter(Boolean);\n\n  if (blocks[0]) {\n    transactions = JSON.parse(blocks[0]);\n  }\n  if (blocks[1]) {\n    matches = JSON.parse(blocks[1]);\n  }\n  if (blocks[2]) {\n    summary = JSON.parse(blocks[2]);\n  }\n} catch (e) {\n  return [{\n    json: { error: \"Parse failed\", message: e.message, rawStart: raw.substring(0, 200) }\n  }];\n}\n\n// ---------- Step 2: Index matches by transaction_id ----------\nconst matchMap = {};\nfor (const m of matches) {\n  matchMap[m.transaction_id] = {\n    ...m,\n    // Normalize classification fields\n    unmatched_classification: m.unmatched_classification || m.classification || null\n  };\n}\n\n// ---------- Step 3: Build reconciliation rows ----------\nconst rows = [];\n\nfor (const txn of transactions) {\n  const m = matchMap[txn.transaction_id];\n\n  if (m && Array.isArray(m.matches) && m.matches.length > 0) {\n    // Matched transaction (can have multiple invoices)\n    for (const match of m.matches) {\n      rows.push({\n        \"Bank Transaction Date\": new Date(txn.date).toLocaleDateString(\"en-US\"),\n        \"Bank Transaction Description\": txn.description,\n        \"Bank Amount\": txn.amount,\n        \"ERP Invoice Number(s)\": match.invoice_number || null,\n        \"ERP Customer Name(s)\": \"N/A\",  // not provided in your JSON\n        \"ERP Amount(s)\": txn.amount,\n        \"Match Status\": \"Matched\",\n        \"Confidence Score\": match.confidence || null,\n        \"Reason\": match.reason || \"\"\n      });\n    }\n  } else {\n    // Unmatched transaction\n    rows.push({\n      \"Bank Transaction Date\": new Date(txn.date).toLocaleDateString(\"en-US\"),\n      \"Bank Transaction Description\": txn.description,\n      \"Bank Amount\": txn.amount,\n      \"ERP Invoice Number(s)\": null,\n      \"ERP Customer Name(s)\": \"N/A\",\n      \"ERP Amount(s)\": null,\n      \"Match Status\": m?.unmatched_classification || \"Unapplied\",\n      \"Confidence Score\": null,\n      \"Reason\": m?.reason || \"No match\"\n    });\n  }\n}\n\n// ---------- Step 4: Return as n8n items ----------\nreturn rows.map(r => ({ json: r }));\n"
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "b9395a80-9e22-4e11-8e8e-85f558cc618f",
      "name": "从非结构化文件中提取数据",
      "type": "n8n-nodes-base.microsoftOneDrive",
      "position": [
        1120,
        0
      ],
      "parameters": {
        "fileId": "={{ $json.id }}",
        "operation": "download",
        "binaryPropertyName": "=Data"
      },
      "credentials": {
        "microsoftOneDriveOAuth2Api": {
          "id": "<Microsoft One Drive API KEY>",
          "name": "Microsoft Drive account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "464d6980-ee91-4509-b433-012adb2bcf88",
      "name": "处理发票与银行对账单数据",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1568,
        0
      ],
      "parameters": {
        "text": "=You are a cash reconciliation specialist.\n\nINPUT DATA:\n- Bank transactions (raw text): {{ $json.extractedText }}\n- ERP ledger entries (JSON): {{ JSON.stringify($('Code in JavaScript').item.json.erpLedger) }}\n\nTASKS\n1) Parse bank text into JSON rows with fields:\n   [{\"date\":\"YYYY-MM-DD\",\"description\":\"string\",\"amount\":number,\"currency\":\"string\",\"transaction_id\":\"string\"}]\n2) Match each bank transaction to one or more ERP entries (keys: exact amount, date ±2 days, reference similarity).\n3) Unmatched items: classify as \"unapplied\", \"suspense\", or \"needs_review\" with reasons.\n4) For partial/one-to-many matches, propose splits with allocation amounts.\n5) Provide a summary: total_txns, total_matched, total_unmatched, reconciliation_rate_pct.\n6) Add a confidence score (0–1) and a short reason for each match/split.\n\nCONSTRAINTS\n- Return JSON ONLY. No prose, no markdown.\n- Limit candidates to top 3 per transaction by confidence.\n- If best confidence < 0.6, treat as unmatched.\n- Use transaction_id and invoice numbers from the inputs.\n\nI want the output in Tabular format\n",
        "options": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "84487907-0767-4877-89cf-d8ce56a9ac39",
      "name": "便签",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        -432
      ],
      "parameters": {
        "color": 4,
        "width": 2080,
        "height": 272,
        "content": "## **问题陈述**"
      },
      "typeVersion": 1
    },
    {
      "id": "f02dc91c-34e1-48b5-8aca-51ad5c3001db",
      "name": "便签1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        -64
      ],
      "parameters": {
        "color": 6,
        "width": 736,
        "height": 288,
        "content": "## **价值**:"
      },
      "typeVersion": 1
    },
    {
      "id": "5e1cd291-8e85-4869-ad70-f8a3958ac55b",
      "name": "便签2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        208,
        176
      ],
      "parameters": {
        "color": 4,
        "width": 1312,
        "height": 176,
        "content": "## ***输入***:"
      },
      "typeVersion": 1
    },
    {
      "id": "a45de2dd-7ee6-4fa9-a167-d22ceab156e2",
      "name": "便签3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1712,
        240
      ],
      "parameters": {
        "color": 4,
        "width": 784,
        "height": 240,
        "content": "## ***AI 处理***:"
      },
      "typeVersion": 1
    },
    {
      "id": "123cec6b-f238-4a07-a75f-2646c3ce0106",
      "name": "便签4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        208,
        368
      ],
      "parameters": {
        "color": 4,
        "width": 1328,
        "height": 496,
        "content": "## ***后处理***:"
      },
      "typeVersion": 1
    },
    {
      "id": "38449472-1724-44cc-aa6b-af80c8eaeb6b",
      "name": "获取发票数据",
      "type": "n8n-nodes-base.microsoftExcel",
      "position": [
        448,
        0
      ],
      "parameters": {
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "{6220E30B-55BD-614F-AA73-5C275D263361}",
          "cachedResultUrl": "https://netorg17303936x-my.sharepoint.com/personal/vinay_optinext_ca/_layouts/15/Doc.aspx?sourcedoc=%7B3B366271-85B1-4FF7-9FE1-BDD145027E90%7D&file=CashARData.xlsx&action=default&mobileredirect=true&DefaultItemOpen=1&activeCell=Sheet1!A1:D51",
          "cachedResultName": "Table1"
        },
        "filters": {},
        "rawData": true,
        "resource": "table",
        "workbook": {
          "__rl": true,
          "mode": "list",
          "value": "01WVQSKILRMI3DXMMF65HZ7YN52FCQE7UQ",
          "cachedResultUrl": "https://netorg17303936x-my.sharepoint.com/personal/vinay_optinext_ca/_layouts/15/Doc.aspx?sourcedoc=%7B3B366271-85B1-4FF7-9FE1-BDD145027E90%7D&file=CashARData.xlsx&action=default&mobileredirect=true&DefaultItemOpen=1",
          "cachedResultName": "CashARData"
        },
        "operation": "getRows",
        "returnAll": true,
        "worksheet": {
          "__rl": true,
          "mode": "list",
          "value": "{A31DAD5C-F7E0-2A4B-B868-E4B2444E9398}",
          "cachedResultUrl": "https://netorg17303936x-my.sharepoint.com/personal/vinay_optinext_ca/_layouts/15/Doc.aspx?sourcedoc=%7B3B366271-85B1-4FF7-9FE1-BDD145027E90%7D&file=CashARData.xlsx&action=default&mobileredirect=true&DefaultItemOpen=1&activeCell=Sheet1!A1",
          "cachedResultName": "Sheet1"
        }
      },
      "credentials": {
        "microsoftExcelOAuth2Api": {
          "id": "<Microsoft Account API KEY>",
          "name": "Microsoft Excel account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "7c23ec26-e63b-4dfe-b82b-79b5a892c91d",
      "name": "便签5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -560,
        272
      ],
      "parameters": {
        "color": 2,
        "width": 704,
        "height": 176,
        "content": "***可能的增强***:"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "983d50ae-2007-4b12-9645-838649f3db28",
  "connections": {
    "Extract text": {
      "main": [
        [
          {
            "node": "Process the Invoice Vs Bank Statement Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Invoice Data": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Get Bank Statement",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Bank Statement": {
      "main": [
        [
          {
            "node": "Extract the Data from Unstructured File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "Process the Invoice Vs Bank Statement Data",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Get Transaction, Matches, Summary": {
      "main": [
        []
      ]
    },
    "When clicking ‘Execute workflow’": {
      "main": [
        [
          {
            "node": "Get Invoice Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract the Data from Unstructured File": {
      "main": [
        [
          {
            "node": "Extract text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process the Invoice Vs Bank Statement Data": {
      "main": [
        [
          {
            "node": "Get Transaction, Matches, Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
常见问题

如何使用这个工作流?

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

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

中级 - 内容创作, 多模态 AI

需要付费吗?

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

工作流信息
难度等级
中级
节点数量15
分类2
节点类型8
难度说明

适合有一定经验的用户,包含 6-15 个节点的中等复杂度工作流

外部链接
在 n8n.io 查看

分享此工作流