先说结论
Odoo 报销里“同收据”和“重复报销”不是一个提示拆成两种文案,而是两套不同的风险检测。
/home/ubuntu/odoo-temp/addons/hr_expense/models/hr_expense.py 里至少有两条主线:
_compute_same_receipt_expense_ids():按附件checksum找“同一张收据图片/文件”_compute_duplicate_expense_ids():按员工、产品、日期、金额、公司、币种找“疑似重复申报”
所以系统真正想表达的是:
你可能用了同一张凭证,也可能没复用附件,但业务上仍像在报第二次。
第一层:同收据检测拦的是“同一份证据被复用”
_compute_same_receipt_expense_ids() 的核心思路是:
- 找有附件的报销单
- 读取附件 checksum
- 看有没有别的 expense 也引用了相同 checksum 的附件
这意味着它关心的是 证据文件层面的复用。
典型场景:
- 一张发票被拆成两张报销
- 同一张照片被重复上传到不同单据
- OCR 导入后重复生成了明细
这套检测和金额对不对没关系。哪怕你改了标题、产品、备注,只要收据文件本体一样,它都会提示你要小心。
第二层:疑似重复检测拦的是“业务含义上的第二次申报”
_compute_duplicate_expense_ids() 用 SQL 做的匹配条件是:
- 同员工
- 同产品
- 同日期
- 同金额
- 同公司
- 同币种
这说明它关注的是业务语义重叠,而不是附件是否一样。
也就是说,即使员工:
- 重新拍了一张照片
- 没上传任何附件
- 或附件因压缩导致 checksum 不同
只要申报特征高度一致,它仍会被认为是疑似重复。
第三层:为什么官方要故意保留两套提示,而不是合并成一个风险分
因为这两套提示服务的处理动作不一样。
同收据
你应该先查:
- 是否真的同一张发票被重复用
- 是否是一张收据拆多笔合理分摊
- 是否 split expense 流程带来的合理复制
疑似重复
你应该先查:
- 这是不是同一次消费被二次录入
- 是否员工重复提交
- 是否同一天同类消费确实发生两次
一个偏“证据复用”,一个偏“业务重复”。不能混着审。
第四层:为什么 split_expense_origin_id 会被特别照顾
源码在同收据逻辑里会排除某些 split 场景,意思很明确:
- 系统知道合理拆分报销时,附件可能天然复用
- 这不应一律被当成舞弊
这一步很重要,因为真正成熟的风控不是“多报就报警”,而是:
- 先识别什么是业务上允许的重复结构
- 再把异常和合理拆分分开
第五层:为什么重复检测不直接阻止保存
这些字段更多是提示和审阅辅助,而不是绝对禁止创建。
因为官方知道:
- 同一天同金额的两次打车不是不可能
- 同一张大票拆分到不同成本对象也可能合理
- 附件重复有时只是员工重复上传同一张证明
所以 Odoo 在这里的态度是“把风险抬给审核人”,而不是在录入环节一刀切拦死。
第六层:真正要建立的是审核顺序,而不是只看一个红点
我更推荐把审核顺序固定成:
- 先看有没有 同收据
- 再看有没有 疑似重复业务
- 然后结合报销说明、费用产品、分析分配、项目/部门归属判断是否合理
因为如果顺序反过来,审核人容易被金额相同误导,却漏掉真正危险的“同一张票重复报”。
最容易踩的 4 个坑
1)把 same receipt 和 duplicate expense 当同义词
它们不是同一个问题。
2)看到重复提示就直接拒绝
先判断是不是合理拆分。
3)只盯附件,不盯业务字段
没复用附件,不代表没重复申报。
4)只盯金额,不看附件
金额碰巧相同,不一定真是同一次消费。
排错/审核顺序
- 查附件 checksum 是否复用
- 查员工、产品、日期、金额、公司、币种是否完全匹配
- 查是否来自 split expense 或合理拆分
- 查审批说明与成本归属
- 最后决定是放行、合并还是退回补充说明
最后一句话
Odoo 报销里的“同收据”和“疑似重复”分别在防证据复用和业务重复,两者都重要,但审核动作不一样。把这两层分开看,才能既控风险,又不误伤正常报销。
DISCUSSION
评论区