三方匹配自动化:用于应付挂起的表与工作流
通过实用表设计与可视化工作流学习三方匹配自动化——在 PO、收货与发票的数量与价格一致前阻止付款。

三方匹配实际解决了什么问题
三方匹配自动化很直白:只有当发票与您下的订单以及实际收到的货物相符时才付款。三个要比对的单据是采购订单(PO)、收货记录(receipt)和供应商发票。
如果没有这个核对,财务可能会基于单一且有误或不完整的凭证付款。供应商可能为未交付的更多数量开票、使用与约定不同的价格,或发送一个在邮件线程中看起来是新的重复发票。
这些错误通常在第一天并不显眼。它们表现为小漏损:某一行被重复计费、某次发货短少几个单位、未经批准的价格上涨,或不该计入的运费。时间久了,这些小错误会累成真金白银的损失。
重点不是“审批发票”。重点是阻止付款,直到你选定的关键字段(通常是数量、单价和总额)在 PO、收货和发票之间一致。若不一致,发票不应消失在邮件里,而应进入异常队列,附带明确的原因代码和具体不一致的字段。
三方匹配也把团队职能划清:采购负责下单(条款与价格),收货确认实际到货(数量与日期),财务控制付款(发票复核与放行)。
早点设好预期:这是一个流程与数据问题,而非一个“批准”按钮。如果 PO 行描述模糊、未记录收货或无法把发票关联到 PO 行,自动化无法替你解决这些基础问题。
单据与角色:PO、收货、发票及责任归属
三方匹配只有在每份单据都有明确负责人时才能发挥作用。如果“谁更新什么”不清晰,系统要么阻止了很多正常的付款,要么放行了有问题的付款。
一个实用的责任模型是:
- 申请人(Requester)创建采购申请并确认需求。
- 采购(Procurement)创建并维护 PO(供应商、价格、条款)。
- 仓库/收货人员(或服务负责人)登记收货或验收。
- AP/财务记录发票并控制付款。
每份单据还需要一组最小字段,才能让匹配不是凭猜测。
PO(采购订单) 需要供应商 ID、PO 编号、行项目(SKU 或服务)、订购数量、单价、币种、税务规则和付款条款。
收货 需要 PO 参考、收货日期、按 PO 行的接收数量以及接收人。服务类则视为验收并记录审批人。
发票 需要供应商发票号、发票日期、PO 引用(或能可靠查到 PO 的方式)、行明细(数量、单价)、税金/运费和发票总额。
还要决定何时触发匹配。它不应只是一次性事件。每当现实发生变化时都应触发:
- 发票被捕获时(立即决定付款或挂起)。
- 收货被登记时(使挂起的发票有机会变为可付)。
- PO 被更改时(对未结发票重新校验)。
部分收货和多次开票是常态。PO 行可能分三次到货并分两张发票开票。你的逻辑应对每个 PO 行计算累计已收与累计已开票,而不是只比对单张单据。
在开始建表或设计流程前要先决定的规则
在动手建表或设计流程前,先就驱动整个系统的规则达成一致。模糊的规则会带来可预见的失败:系统要么阻塞过多,导致被绕过;要么阻塞过少,坏发票仍被付款。
选择匹配级别。 仅头部(header)级匹配检查单据层面的总额,听起来简单,但面对部分交付、缺货、运费行或混合税率时很快会出问题。行级匹配虽然设置耗时,但更安全:你将同一条 PO 行的数量和单价与收货与发票逐项比对。
定义硬阻断与警告。 硬阻断(hard block)表示必须解决问题才能付款;警告(warning)表示发票可继续流转,但需要有人确认风险。
典型起点:
- 硬阻断:开票数量超过已收数量(针对实物)。
- 硬阻断:单价超过 PO 价格且超出容差。
- 警告:小额四舍五入差异。
- 警告:预期并单独编码的税或运费差异。
明确容差规则。 定义方法(百分比、绝对金额或两者取较高者)以及谁有权限调整。例如:每行允许 +/-1% 或 +/-$5 的差异,且仅允许财务更改容差并需留审计说明。
使用一组小且共享的状态。 避免各团队自定义状态。一个清晰的集合通常足够:Matched(已匹配)、Hold(挂起)、Exception(异常)、Approved(已批准)。“Hold”表示付款被阻止。“Exception”表示需要人工复核。“Approved”表示某人已命名接受该不一致并记录原因。
数据模型:你需要的表(及原因)
三方匹配自动化只有在你的数据模型能把 PO 行、收货和开票对齐时才有效。每个发票行都应能匹配到具体的 PO 行(或明确标记为非 PO),每个收货行应减少该 PO 行的剩余数量。
从核心采购表开始:
- Vendors:每个供应商一行(名称、条款、税务信息)。
- ItemsServices:可选,但有助于一致性(SKU、描述、计量单位)。
- PurchaseOrders:PO 头(vendor_id、currency、requested_by、status)。
- PO_Lines:匹配锚点(po_id、item_id/描述、ordered_qty、unit_price)。
收货需要单独记录,即使“收货”只是一次确认。把收货和发票分开存,以便证明何时、何物到达:
- Receipts:收货头(vendor_id、received_date、location、status)。
- Receipt_Lines:每行引用 PO 行(receipt_id、po_line_id、received_qty、备注)。
开票与收货对应。保存供应商按行计费的内容并把它连接到应覆盖的 PO 行:
- Invoices:发票头(vendor_id、invoice_number、invoice_date、due_date、status)。
- Invoice_Lines:(invoice_id、当适用时的 po_line_id、invoiced_qty、unit_price、tax、line_total)。
最后,创建一个面向付款且工作流能阻止的记录。有些团队称之为 bill、payment request 或 pay run item:
- PaymentRequests(或 Bills):关联 invoice_id,包含 payment_hold(true/false)以及 hold_reason。
为审计与清晰的异常处理,在头表(PO、收货、发票、付款)上加入一致的生命周期字段:status、created_at/created_by、approved_at/approved_by、posted_at,以及(可选)用于导入的 source_document_id。
让匹配可靠的关键字段与关系
当每份单据都能追溯到相同的行项目时,匹配才最好。这意味着稳定的 ID、清晰的关联以及能从行重新计算的总额。
确保每张表既有稳定的内部 ID,也有用户常用的外部编号:
- PO 头:po_id、po_number、vendor_id、currency、status、po_date
- PO 行:po_line_id、po_id、item_id 或 描述、ordered_qty、unit_price、tax_rate、line_total
- 收货:receipt_id、receipt_number、vendor_id、received_date;receipt_line_id、receipt_id、po_line_id、received_qty
- 发票:invoice_id、vendor_id、vendor_invoice_number、invoice_date、currency、subtotal、tax_total、total;invoice_line_id、invoice_id、po_line_id、qty、unit_price、tax_amount、line_total
- 供应商与物料:vendor_id、payment_terms、default_currency;item_id、uom、tax_code
最重要的关联是行级的:
- invoice_line.po_line_id 应指向 PO 行。
- receipt_line.po_line_id 应指向同一 PO 行。
这使你能在不猜测的情况下比较数量与价格。
为处理部分收货,按 PO 行计算运行累计值:received_qty(收货行之和)和 invoiced_qty(发票行之和)。然后计算 remaining_qty = ordered_qty - received_qty 与 open_to_invoice_qty = received_qty - invoiced_qty。这些值能清晰显示发票是提前、滞后还是超开。
当 PO 更改时不要覆写历史。存储 PO 修订号,并保留旧 PO 行(带 active 标志)或写变更日志(谁何时改了什么、旧值与新值)。
加入基本的防护以防止重复和错误关联:
- 唯一约束 (vendor_id, vendor_invoice_number)
- 唯一 receipt_number 与 po_number
- currency、数量和 unit_price 不可为空
- 检查约束如 qty >= 0 和 unit_price >= 0
- 从 invoice_line 与 receipt_line 到 po_line 的外键
逐步工作流:从发票接收到账款挂起
三方匹配自动化通常有三个入口:发票到达(邮件、上传、EDI)、收货登记,或 PO 被更改(价格、数量、状态)。工作流应对任一入口做出反应,以便发票在缺失环节补全后能离开挂起状态。
-
先验证发票基础信息。确认供应商有效、PO 存在、币种与 PO 一致且总额内部一致(行总和、税额合理、没有负数量除非支持贷项)。若校验失败,将发票直接置为 Hold 并给出明确原因。
-
按行匹配,而不是只看头部。对每个发票行,找到相关的 PO 行与当前的收货累计并比较:
- 开票数量 vs 已收数量(或已收减去已开票的数量)
- 开票单价 vs PO 单价
- 容差规则
- PO 行是否仍可开票
- 设置状态并执行阻断。常见模式:
- Matched:所有行通过检查,无未决异常。
- Hold:至少一行失败或必需数据缺失。
当设置为 Hold 时,创建一个付款挂起记录,付款运行必须遵守该记录。把挂起与发票分开,以便在不重写发票历史的情况下添加、释放或替换挂起。
- 记录财务可信赖的原因代码。避免仅仅自由文本的挂起。使用诸如 PRICE_OVER_TOLERANCE、QTY_NOT_RECEIVED、PO_CLOSED、VENDOR_MISMATCH 或 CURRENCY_MISMATCH 之类的代码,并附加简短说明。
给财务的异常队列设计(要存什么,展示什么)
异常队列是匹配变得可用的地方,而不仅仅是严苛的规则集合。财务应只看到需要决策的发票,并附带足够的上下文以快速决策与留下清晰审计轨迹。
一种常见做法是使用专门的表比如 ExceptionCases。每行代表一个被阻止的发票(或发票行),并指回发票、PO 与收货记录。匹配引擎在这里保持只读,队列用于决策与记录。
在 ExceptionCases 中要存的内容
保存出错类型、差额大小、负责人与下一步信息:
- 类型(缺失收货、价格差异、数量差异、未找到 PO、重复发票)
- 严重性(info、warning、block)以及可读的原因说明
- 负责人(人或团队)与状态(open、waiting on vendor、waiting on warehouse、resolved、overridden)
- 差异快照作为可排序数字(发票金额、匹配金额、价格差额、数量差额)
- SLA 字段(到期日、升级标志、reassigned_at、reassignment_reason)
还要保存协作与审计数据:评论(作者、时间戳)和附件元数据(文件名、类型、uploaded_by、uploaded_at)。即使文件实际存放在别处,元数据也应保存在案例中以保持历史完整。
财务应看到并能做的操作
队列视图应是一个精简的工作清单:供应商、发票号、异常类型、严重性、金额、到期日、负责人以及清晰的“为什么被阻止”信息。
打开案例应显示并列摘要:PO 行、收货数量、发票行以及具体失败的字段。
把可用操作保持有限且安全:
- 请求收货(发给收货方,状态设为 waiting)
- 请求贷项(发给供应商,记录预期调整)
- 批准覆盖(需要理由,记录审批人和时间戳)
- 重新指派(更新负责人并保留指派历史)
- 标注已解决并关闭(仅在变更使匹配通过后)
示例:发票因计费 8 个单位但仅收到 6 个而被阻止。财务可以请求更正发票,或为已收的 6 个单位批准覆盖,把剩余 2 个单位继续挂起。
现实例子:部分收货与不匹配的发票
采购人员为 A 品订购 100 个,单价 $10.00,总额 $1,000。两天后仓库登记收到 80 个。
随后收到一张 100 个、单价 $10.00 的发票。匹配应将发票行与已收数量对比,而不是只看订购数量。
该行:
- 订购:100
- 已收:80
- 开票:100
- 匹配数量:min(已收, 开票) = 80
- 不匹配数量:开票 - 匹配 = 20
因有 20 个单位没有收货,发票被置为“挂起”。财务会看到一个案例,注明原因(数量差异:+20)并并列关键数字。
通知应发给能最快解决的人:通常是收货方(确认是否漏登收货)和采购(跟进是否确实短货)。
当剩余 20 个到货并由仓库登记第二次收货后,系统重跑匹配:已收变为 100、不匹配变为 0、发票转为 Matched,挂起被释放。
再加上价格差异的情形:如果供应商为 100 个开票但单价为 $10.50(而非 $10.00),数量匹配但价格不一致。预期结果:保持挂起并以“价格差异:每单位 +$0.50(共 +$50)”之类的原因路由处理。
常见会破坏三方匹配工作流的错误
大多数匹配失败并不是数学问题,而是数据关联薄弱和对已发布单据的控制不足。
仅对发票总额匹配。 头部看起来正常,但某一行可能超价或缺货。做行级匹配,并明确哪些项目可不同(通常是运费)以及哪些不可不同(已收数量和单价)。
假设一张收货对应一张发票。 真实采购包含拆单和分次开票。支持多个收货与多张发票对同一 PO 行,并追踪每行的剩余可开量。
允许在无痕迹情况下编辑已发布的收货或发票。 若有人能悄悄改数量,匹配就不再有证据效力。锁定已发布记录,通过保留历史的调整凭证来更正。
缺少重复防控。 同一供应商发票号可能被录入两次,或同一 PDF 被不同人再次上传。尽早加入唯一性校验(供应商 + 发票号,或附加日期/金额),并在检测到疑似重复时提示清晰信息。
模糊的异常原因。 财务不应猜测原因。使用能清晰路由的原因代码:price mismatch、quantity mismatch、missing receipt、duplicate suspected、PO not found、vendor mismatch。
在打开付款阻断前的快速核查清单
付款阻断是匹配从报告变为控制的节点。如果基础不稳,会给财务带来噪音并导致供应商被延迟付款。
测试一小批各类发票:一张干净匹配、一次部分收货、一项价格变更和一项税务差异。若有任何一类不能被清晰匹配,先修正数据与规则。
清单:
- 参考完整性: 每张发票都有供应商与 PO 引用,每个发票行能映射到具体 PO 行(而不只是“PO 总额”)。决定当供应商只给出 PO 头编号时如何处理。
- 计算一致性: 数量、单价与总额的重算方式一致。明确税、运费、折扣和四舍五入的处理(例如按行四舍五入还是只在发票总额上四舍五入)。
- 状态应足够提前阻断: 在创建任何付款请求或支付记录前就把发票设为“挂起”。
- 结构化异常: 每个挂起都存原因代码与负责人(AP、采购、收货)。加入到期日以防挂起无限期滞留。
- 真实的审计轨迹: 覆盖记录谁在何时批准了什么以及批准内容(含原始值)。若允许编辑,记录编辑前后的值。
下一步:先做试点并可视化构建
把三方匹配自动化当作任何控制来对待:先在小范围内验证可行,再逐步推广。
从一个易于监控的试点开始。选择一个事业部、一组发票干净的供应商,或单一商品类别。起初把规则设严格(精确数量与价格匹配),让数据质量问题迅速显现。
用简单的财务视图衡量成功:每周挂起数量、主要原因代码、从挂起到释放的时间、有多少挂起是真实不匹配、以及哪些供应商持续产生异常。
如果想快速原型,可使用无代码平台来建模表、匹配规则与路由,而无需写代码。例如,在 AppMaster (appmaster.io) 中你可以构建 PO、收货、发票与异常表,然后在可视化业务流程中连接挂起逻辑,使相同规则在每个触发点运行。
使用试点组的真实发票进行测试,包括部分收货与常见的供应商错误。预期会调整匹配键并仅在观察到模式后添加小的容差。当挂起变得合理且解决时间改善后,扩大范围并加入更复杂的规则(税与运费处理、计量单位换算、拆分发货),但不要丢失核心控制:匹配通过前不放行付款。


