指纹用什么字段
最常用的组合是发票代码、发票号码、开票日期、金额(不含税或价税合计)。这四个字段的组合在绝大多数情况下足以区分不同发票。
但只靠这四个字段会有两个漏洞。第一,数电票没有传统意义上的发票代码,号码本身为 20 位且全国唯一,此时号码加金额加日期即可,代码字段留空不要参与计算,否则同一张票在不同渠道采集时可能生成不同指纹。第二,机动车销售统一发票、二手车销售统一发票等特殊票种,票面要素与传统发票有差异,需要单独定义指纹规则。
建议的指纹构成
- 通用发票:发票代码 + 发票号码 + 开票日期 + 价税合计
- 数电发票:发票号码 + 开票日期 + 价税合计(代码字段不参与)
- 特殊票种:按票面实际存在的唯一要素组合,单独配置
- 所有票种均附加销方纳税人识别号,进一步降低碰撞概率
查重的范围和时间点
查重发生得越早,处理成本越低。员工提交时拦截,只需要解释一句;等到付款后再发现,就要走退款或冲销流程。因此查重的第一道关口应该放在采集环节——拍照或接收结构化数据的瞬间。
第二道关口放在提交环节,因为从采集到提交之间可能间隔数天,期间同一张票可能被其他方式重复采集。第三道放在入账前,作为最后一道校验。三道关口的检查范围不同:第一道查同一用户的历史记录,第二道查全库,第三道再次全库校验并锁定。
跨年度和跨组织怎么办
跨年度查重的常见争议是要不要查。严格来说应该查——如果去年已报销的发票在今年再次提交,仍然是重复。但要注意设置合理的时间窗口,例如只回溯三年以内,避免历史数据量过大影响性能,也避免把完全无关的历史记录拿来提示。
跨组织查重在多法人、多分支机构场景下尤为重要。如果各组织使用独立的系统实例,A 公司报销过的发票在 B 公司无法被识别,重复报销的空间就存在了。这也是集中部署的一个实际优势:全集团数据在同一库中,查重范围天然完整。
如果确实需要多实例部署,则需要建立指纹同步机制——各实例把发票指纹上传到统一的校验库,采集时向校验库发起查询。这个方案会引入额外的架构复杂度,需要在部署方案设计阶段就考虑进去。
拦不住的情况怎么处理
任何校验机制都会有例外。有几类情况需要人工处理:发票作废后重开(号码不同但业务相同)、红冲后重新开具、以及确实因为系统故障导致同一张票被采集两次。
系统应该做的是把这类情况集中到异常清单,要求填写理由并留痕,而不是简单放行。理由字段建议做成结构化的选项加备注,便于后续统计——如果某个理由长期高频出现,说明流程或规则需要调整。
一个补充手段
除了查重,还建议同时做查验。查重防的是重复报销,查验防的是虚假或异常发票。两者在采集环节可以合并完成:先验真确认真实存在,再查重确认未被使用。合并之后对员工而言只是一次提交,体验上没有额外负担。