企业 Sign 开发

Odoo 企业版 Sign 发起签署为什么不是“建个 request 发邮件”而已:角色项生成、提醒重发与完成归档主链路讲透

Sign 的真正复杂度不在 PDF 盖章,而在模板项复制、签署人展开、提醒重发、状态推进与完成归档这一整条请求链。

Odoo 开发 企业
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 5 阅读

Sign 最容易被误解成“上传 PDF、填几个签署人、发出去就行”。但从源码看,真正的系统价值在于:模板怎么变成请求、请求里的签署项如何按角色落到具体人、状态如何推进、完成后又如何生成最终文档与日志。这四件事连在一起,才构成企业版 Sign 的主链路。

主要参考:

  • enterprise/sign/models/sign_request.py
  • enterprise/sign/models/sign_request_item.py
  • enterprise/sign/models/sign_template.py
  • enterprise/sign/models/sign_log.py

一、请求不是空壳记录,而是模板运行后的结果

sign.request 并不是一条单纯的“待签单据”。创建请求时,后端首先拿 sign.template 上的角色、签署项、常量项和附件信息做一次展开,把“模板定义”转成“本次请求的实例数据”。

这一步最重要的不是复制字段,而是把模板里的抽象责任人变成请求里的具体签署上下文。模板上说的是“客户签”“公司签”“见证人签”,请求里才会绑定到具体 partner、mail、短信验证方式和访问 token。

二、请求项的核心不是字段值,而是责任归属

真正驱动流程推进的是 sign.request.item。它代表“某个签署角色在某次请求中的一份待办”。一旦 item 生成,系统才知道:

  • 谁需要收到邮件或短信
  • 谁已经打开过签署链接
  • 谁还处于 sentcompleted
  • 请求是否能从部分完成推进到整体完成

很多二开会误把请求状态直接挂在 sign.request 上自己算,结果常常和官方行为不一致。更稳的做法是把 item 当成事实来源,再让 request 汇总整体状态。

三、发送与提醒不是简单重发邮件,而是状态过滤后的再次投递

提醒逻辑看起来像“再发一次提醒邮件”,实际上前提条件很多。系统只会对仍然有效、仍然待签、且访问条件没有被拒签或过期打断的项做提醒。也就是说,提醒不是无差别广播,而是一次对剩余待签 item 的再投递

这也是为什么你在做自动催签时,不要只按 request 找 state='sent' 就群发。正确判断应该至少覆盖:请求整体状态、item 自身状态、签署链接是否仍可访问、以及是否已经有日志记录表明该签署人完成或拒绝。

四、完成动作的重点在“收口”而不是“最后一个人点了确认”

很多人以为最后一个签署人提交后,请求就算结束。源码层面并不是这么简单。完成阶段至少会做几件事:

  1. 汇总所有签署项是否都已完成
  2. 生成最终签署后的文件版本
  3. 写入签署日志,确保审计链完整
  4. 更新 request / item 的最终状态
  5. 触发后续通知、附件回写或业务对象关联

所以 Sign 的“完成”本质上是一次归档收口操作。它要把之前分散在多个 signer、多个 token、多个签署项上的过程数据,压成一个可审计的结果文件和结果状态。

五、最容易踩坑的地方:把模板、请求、请求项混成一层

开发时最常见的误区有三个:

  • 把模板项当成请求项直接改,导致历史请求被污染
  • 只更新 request,不更新 item,结果界面和统计不一致
  • 只发邮件,不经过官方发送/提醒链路,导致日志、到期与访问校验失真

经验上,模板负责定义,request 负责一次业务实例,request item 负责单个签署人的执行事实。这三层拆清楚,很多 bug 会少一大半。

六、实战建议

如果你要做 Sign 二开,比如自动发起合同、定时催签、签完回写 CRM 或销售订单,建议遵守三条原则:

  • 不要跳过官方的 request / item 生成逻辑
  • 不要自己发明“完成状态”,尽量复用官方汇总
  • 把日志与最终附件当成审计产物,而不是顺手生成的副产物

Sign 的价值并不只是“能签”,而是签署过程可追踪、结果可复核、异常可解释。这一点,恰恰来自它比表面复杂得多的请求主链路。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。