2026-09-01 · 原文发布日
供应商发票自动对单,对不上就起草询问邮件
每10分钟检查Gmail里带发票标签的未读邮件,下载PDF附件后提取文本,用OpenAI抠出发票号、供应商、PO号、币种、金额和明细,再与n8n数据表里的未结采购单和已见发票比对:查重复、币种不符、金额超容差、明细合计对不上。通过的记入数据表标记cleared,扣住的自动生成简短问询草稿挂在原邮件线程里。容差参数可调。
原文要点
原模板发布于n8n模板库(工作流18954,免费),定时每10分钟扫描Gmail指定标签下的未读发票邮件,下载附件并只保留PDF,提取文本后用OpenAI抠出发票号、供应商、PO号、币种、总额与明细行;再从n8n Data Tables读取未结采购单与已见发票,按PO号或供应商加最接近金额匹配,检查重复、币种不符、金额超容差、明细合计与总额不一致。通过的写入invoices_seen并标记cleared,扣住的由OpenAI起草简短问询、记录原因并在原邮件线程创建Gmail草稿回复。容差由Settings里的tolerance_percent与tolerance_amount控制,两者取较大者生效。
这次做成什么
在n8n中导入该免费模板并配好Gmail标签、两张Data Table和OpenAI凭据,跑通一条“供应商发票自动核对、异常自动生成问询草稿”的链路;本站另设计一套合成数据练习,用3张虚构发票验证通过、超容差、明细不符三种分支。
准备什么
- 一个可用的n8n实例(云端或自托管,版本需支持Data Tables功能)
- Gmail账号及n8n Gmail OAuth2凭据,发票邮件会带指定标签且含PDF附件
- OpenAI或兼容接口的API Key(模型调用会产生费用,具体价格以官方为准)
- 用于练习的合成采购单与发票数据,不要使用真实供应商信息
具体怎么做
导入模板并连接Gmail触发器
在n8n模板库打开工作流18954页面,点Use workflow导入到自己的实例。打开Gmail触发节点,选择你的Gmail OAuth2凭据,把Label设置为发票邮件实际使用的标签名(如INVOICES),确认触发器启用了附件下载,轮询间隔保持默认的每10分钟。
创建两张Data Table并填入练习数据
按模板要求新建Data Table purchase_orders,列依次为po_number、vendor、amount、currency、status,手工录入下方练习材料中的3行合成采购单。再建invoices_seen,列为invoice_key、invoice_number、vendor、amount、currency、po_number、status、reason、seen_on,先留空,用于接收核对结果。
配置OpenAI凭据与容差参数
在提取和起草问询的OpenAI节点上选择你的API凭据。打开Settings步骤,把tolerance_percent设为2、tolerance_amount设为5作为练习起点;按原作者说明,两个容差取较大者判定,小额绝对值能保护小单不受四舍五入误伤。
发送三封合成测试邮件并观察分支
用另一个邮箱向Gmail收件箱发三封各带一个PDF附件的邮件并打上INVOICES标签:INV-1001金额1000.00 USD匹配PO-5001(应通过);INV-1002金额1080.00 USD对应PO-5002的1000.00 USD(超容差,应扣住);INV-1003明细合计与总额差60元(应扣住)。等触发器轮询后查看执行日志。
核对结果表与Gmail草稿
打开invoices_seen表:INV-1001应为status=cleared且reason为空;另两条应为held并写明原因(金额超容差、明细合计不符)。再到Gmail草稿箱,确认两封扣住邮件的原线程里各有一封简短英文问询草稿,草稿不自动发送,由你人工检查后发出。
可直接复制的材料
purchase_orders合成练习数据(CSV)
本站设计的合成练习数据,供应商为虚构名称,直接粘贴进Data Table导入或手工录入
po_number,vendor,amount,currency,status
PO-5001,Acme Office Supplies,1000.00,USD,open
PO-5002,BluePeak Logistics,1000.00,USD,open
PO-5003,GreenLeaf Packaging,2500.00,USD,open发票字段提取提示词(供OpenAI提取节点参考改写)
本站独立编写的示例提示词,需按模板实际节点的输出字段名对齐后再替换使用;{{ $json.pdf_text }}为示意变量名,以模板实际表达式为准
你是发票信息提取器。从下面的发票PDF文本中只提取事实字段,不要推测缺失信息。
以严格JSON输出,不要输出多余文字:
{"invoice_number":"发票号","vendor":"供应商名称","po_reference":"采购单号,无则null","currency":"三字母币种代码","total":数字,"line_items":[{"description":"品名","quantity":数字,"unit_price":数字,"line_total":数字}]}
要求:金额去掉千分位和币种符号转为数字;无法识别的字段填null。
发票文本:
{{ $json.pdf_text }}容差与判定练习配置(JSON)
本站整理的理解示例,tolerance逻辑以模板Settings节点的实际表达式为准,导入后请先核对
{
"tolerance_percent": 2,
"tolerance_amount": 5,
"判定口径": "允许偏差 = max(采购单金额 × tolerance_percent / 100, tolerance_amount),两者取较大者",
"示例": {
"PO-5001金额1000": "max(20, 5) = 20,1000.00与1000.00差0,通过",
"PO-5002金额1000": "max(20, 5) = 20,1080.00与1000.00差80,超过20,扣住"
}
}输入与输出示例
本站虚构演示,非模板实际运行结果;reason字段具体措辞以模板实际输出为准
输入
练习邮件二:附件PDF为虚构发票INV-1002,供应商BluePeak Logistics,PO号PO-5002,币种USD,发票总额1080.00,明细两行(运费900.00、燃油附加费180.00,合计1080.00),Data Table中PO-5002金额为1000.00 USD、状态open。对应输出
核对结果:按PO-5002精确匹配到采购单;无重复记录;币种一致;允许偏差=max(1000×2%,5)=20,实际差额80>20,判定金额超容差,明细合计与总额一致不影响扣住结论。invoices_seen写入一行:invoice_key=BluePeak Logistics|INV-1002,status=held,reason=amount mismatch: invoice 1080.00 vs PO 1000.00 (tolerance 20.00)。Gmail原线程生成英文问询草稿,大意为请供应商确认发票1080.00与采购单1000.00之间80.00差额的原因。做完检查这些
- purchase_orders与invoices_seen两张表的列名与模板要求完全一致,且purchase_orders已预填open状态采购单
- 发送带PDF的测试邮件后一个轮询周期内触发器执行,无PDF的邮件被过滤停止处理
- 金额匹配的发票在invoices_seen中出现status=cleared的记录
- 超容差或明细不符的发票status为held且reason非空,并能在Gmail草稿箱找到挂在原线程的问询草稿
- 调整tolerance_amount后重新测试,判定结果随之变化,说明容差参数生效
容易卡住的地方
- 模板只读取Data Table不会自动创建,两张表必须手工建好且列名拼写一致,否则读取失败
- Gmail触发器未启用附件下载或标签名写错时流程收不到发票PDF
- OpenAI提取是概率性的,PDF为扫描图片时提取文本可能为空,需另配OCR,模板本身不含OCR环节
- OpenAI调用按用量计费,具体费用以服务商页面为准,本站不作免费承诺
- 按供应商加最接近金额兜底匹配可能错配同供应商多张相似发票,建议优先确保发票含PO号
- 问询仅生成草稿不会自动发送,需要人工在Gmail草稿箱确认
本站借助AI整理来源事实,独立编写中文操作指南与示例。示例不代表实际运行结果;来源效果尚未由本站独立复现。付费模板与模型、服务费用分别计算。
- 原文标题
- Match supplier invoices to purchase orders with Gmail, OpenAI, and Data Tables
- 原作者
- Daniel Shashko
- 原始发布日期
- 2026-08-31T17:41:49.621Z
- 来源
- https://n8n.io/workflows/18954