合同审批流程节点设计
生成日期:2026-03-30 模块名称:yudao-module-contract 文档用途:定义 contract_approve 和 contract_change 两个流程的审批节点拓扑、候选人策略、条件分支规则,供在 BPM 流程设计器中配置
一、流程概览
合同模块包含两个独立的审批流程,对应 ContractBillTypeEnum 枚举中的两个值:
| 流程 Key | typeCode | 名称 | 适用场景 |
|---|---|---|---|
contract_approve | 201 | 合同审批 | 新合同创建后提交审批,包含按金额分级审批 |
contract_change | 202 | 合同变更审批 | 已生效合同发起变更(金额、期限、条款等),走固定审批链 |
二、前置条件:新增岗位
流程节点中需要用到"合同专员"岗位,系统中尚未定义,需先执行以下 SQL:
INSERT INTO `system_post` (`id`, `code`, `name`, `sort`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`)
VALUES (13, 'CONTRACT_SPECIALIST', '合同专员', 1, 0, '合同审批流程中负责合同审核/法务审核', '1', NOW(), '1', NOW(), b'0', 1);SQL 文件位置:
ruoyi-office-db/20260330_update/add_contract_specialist_post.sql
执行后需在系统管理 -> 岗位管理中为相关用户分配"合同专员"岗位。
三、涉及的系统数据
3.1 岗位清单(system_post)
| id | code | name | 流程中用途 |
|---|---|---|---|
| 10 | subLeader | 分管领导 | 小额合同终审 / 变更终审 |
| 11 | mainLeader | 主要领导 | 大额合同终审 |
| 13 | CONTRACT_SPECIALIST | 合同专员 | 合同内容审核 / 法务合规审核 |
3.2 候选人策略枚举(BpmTaskCandidateStrategyEnum)
| strategy | 枚举名 | 说明 | 本流程使用 |
|---|---|---|---|
| 22 | POST | 岗位 | 合同专员、分管领导、主要领导节点 |
| 37 | START_USER_DEPT_LEADER | 发起人部门负责人 | 部门负责人审批节点 |
3.3 节点类型枚举(BpmSimpleModelNodeTypeEnum)
| type | 含义 | 本流程使用 |
|---|---|---|
| 10 | 发起人 | 流程起始节点 |
| 11 | 审批人 | 各审批节点 |
| 50 | 条件支路 | 金额条件分支的子路径 |
| 51 | 条件分支 | 按合同金额分流 |
| 1 | 结束 | 流程终止 |
四、合同审批流程(contract_approve)
4.1 流程拓扑图
发起人 ──→ 部门负责人审批 ──→ 合同专员审核 ──→ [条件分支:按合同金额]
│
┌──────────────┴──────────────┐
│ │
金额 ≤ 10万 金额 > 10万
│ │
分管领导审批 主要领导审批
│ │
└──────────────┬──────────────┘
│
结束4.2 节点详细配置
节点 1:发起人
| 配置项 | 值 |
|---|---|
| id | StartUserNode |
| type | 10(发起人) |
| name | 发起人 |
| buttonsSetting | 提交=启用, 其余=禁用 |
节点 2:部门负责人审批
| 配置项 | 值 |
|---|---|
| type | 11(审批人) |
| name | 部门负责人审批 |
| candidateStrategy | 37(发起人部门负责人) |
| candidateParam | 无需填写(自动获取发起人所在部门负责人) |
| approveType | 1(人工审批) |
| approveMethod | 4(或签,任一人审批即可) |
| rejectHandler.type | 1(驳回到发起人) |
| buttonsSetting | 通过、拒绝、转办、退回 = 启用 |
| assignStartUserHandlerType | 1(发起人自己是审批人时自动通过) |
节点 3:合同专员审核
| 配置项 | 值 |
|---|---|
| type | 11(审批人) |
| name | 合同专员审核 |
| candidateStrategy | 22(岗位) |
| candidateParam | "13"(合同专员岗位 id) |
| approveType | 1(人工审批) |
| approveMethod | 4(或签) |
| rejectHandler.type | 1(驳回到发起人) |
| buttonsSetting | 通过、拒绝、转办、退回 = 启用 |
合同专员负责审核合同条款完整性、金额准确性、法务合规性。
节点 4:条件分支
| 配置项 | 值 |
|---|---|
| type | 51(条件分支) |
| name | 金额分级审批 |
| conditionNodes | 2 个条件支路(见下) |
条件支路 A:小额合同
| 配置项 | 值 |
|---|---|
| type | 50(条件支路) |
| name | 小额合同(≤10万) |
| conditionSetting.conditionType | 2(规则组) |
| conditionSetting.conditionGroups | 字段 contractAmount ≤ 100000 |
| childNode | → 分管领导审批 |
条件表达式配置:
{
"conditionType": 2,
"conditionGroups": [
{
"conditions": [
{
"fieldName": "contractAmount",
"operator": "<=",
"value": "100000"
}
]
}
]
}条件支路 B:大额合同(默认分支)
| 配置项 | 值 |
|---|---|
| type | 50(条件支路) |
| name | 大额合同(>10万) |
| defaultFlow | true |
| childNode | → 主要领导审批 |
节点 5a:分管领导审批(小额合同路径)
| 配置项 | 值 |
|---|---|
| type | 11(审批人) |
| name | 分管领导审批 |
| candidateStrategy | 22(岗位) |
| candidateParam | "10"(分管领导岗位 id) |
| approveType | 1(人工审批) |
| approveMethod | 4(或签) |
| rejectHandler.type | 1(驳回到发起人) |
| buttonsSetting | 通过、拒绝、转办、退回 = 启用 |
节点 5b:主要领导审批(大额合同路径)
| 配置项 | 值 |
|---|---|
| type | 11(审批人) |
| name | 主要领导审批 |
| candidateStrategy | 22(岗位) |
| candidateParam | "11"(主要领导岗位 id) |
| approveType | 1(人工审批) |
| approveMethod | 4(或签) |
| rejectHandler.type | 1(驳回到发起人) |
| buttonsSetting | 通过、拒绝、转办、退回 = 启用 |
节点 6:结束
| 配置项 | 值 |
|---|---|
| id | EndEvent |
| type | 1(结束) |
| name | 结束 |
4.3 simple_model JSON 参考
以下 JSON 可直接用于理解 simple_model 数据结构,也可作为通过 API 创建流程时的参考:
{
"id": "StartUserNode",
"type": 10,
"name": "发起人",
"showText": "已设置",
"childNode": {
"id": "Activity_dept_leader",
"type": 11,
"name": "部门负责人审批",
"showText": "发起人部门负责人",
"candidateStrategy": 37,
"approveType": 1,
"approveMethod": 4,
"fieldsPermission": [],
"buttonsSetting": [
{"id": 1, "displayName": "通过", "enable": true},
{"id": 2, "displayName": "拒绝", "enable": true},
{"id": 3, "displayName": "转办", "enable": true},
{"id": 4, "displayName": "委派", "enable": true},
{"id": 5, "displayName": "加签", "enable": true},
{"id": 6, "displayName": "退回", "enable": true}
],
"signEnable": false,
"reasonRequire": false,
"rejectHandler": {"type": 1, "returnNodeId": null},
"timeoutHandler": {"enable": false, "type": null, "timeDuration": null, "maxRemindCount": null},
"assignStartUserHandlerType": 1,
"assignEmptyHandler": {"type": 1, "userIds": null},
"childNode": {
"id": "Activity_contract_spec",
"type": 11,
"name": "合同专员审核",
"showText": "指定岗位: 合同专员",
"candidateStrategy": 22,
"candidateParam": "13",
"approveType": 1,
"approveMethod": 4,
"fieldsPermission": [],
"buttonsSetting": [
{"id": 1, "displayName": "通过", "enable": true},
{"id": 2, "displayName": "拒绝", "enable": true},
{"id": 3, "displayName": "转办", "enable": true},
{"id": 4, "displayName": "委派", "enable": true},
{"id": 5, "displayName": "加签", "enable": true},
{"id": 6, "displayName": "退回", "enable": true}
],
"signEnable": false,
"reasonRequire": false,
"rejectHandler": {"type": 1, "returnNodeId": null},
"timeoutHandler": {"enable": false, "type": null, "timeDuration": null, "maxRemindCount": null},
"assignStartUserHandlerType": 1,
"assignEmptyHandler": {"type": 1, "userIds": null},
"childNode": {
"id": "GatewayNode_amount_branch",
"type": 51,
"name": "金额分级审批",
"conditionNodes": [
{
"id": "CondNode_small_amount",
"type": 50,
"name": "小额合同(≤10万)",
"conditionSetting": {
"conditionType": 2,
"defaultFlow": false,
"conditionGroups": [
{
"conditions": [
{
"fieldName": "contractAmount",
"operator": "<=",
"value": "100000"
}
]
}
]
},
"childNode": {
"id": "Activity_sub_leader",
"type": 11,
"name": "分管领导审批",
"showText": "指定岗位: 分管领导",
"candidateStrategy": 22,
"candidateParam": "10",
"approveType": 1,
"approveMethod": 4,
"fieldsPermission": [],
"buttonsSetting": [
{"id": 1, "displayName": "通过", "enable": true},
{"id": 2, "displayName": "拒绝", "enable": true},
{"id": 3, "displayName": "转办", "enable": true},
{"id": 4, "displayName": "委派", "enable": true},
{"id": 5, "displayName": "加签", "enable": true},
{"id": 6, "displayName": "退回", "enable": true}
],
"signEnable": false,
"reasonRequire": false,
"rejectHandler": {"type": 1, "returnNodeId": null},
"timeoutHandler": {"enable": false, "type": null, "timeDuration": null, "maxRemindCount": null},
"assignStartUserHandlerType": 1,
"assignEmptyHandler": {"type": 1, "userIds": null},
"childNode": {"id": "EndEvent", "type": 1, "name": "结束"}
}
},
{
"id": "CondNode_large_amount",
"type": 50,
"name": "大额合同(>10万)",
"conditionSetting": {
"conditionType": 2,
"defaultFlow": true
},
"childNode": {
"id": "Activity_main_leader",
"type": 11,
"name": "主要领导审批",
"showText": "指定岗位: 主要领导",
"candidateStrategy": 22,
"candidateParam": "11",
"approveType": 1,
"approveMethod": 4,
"fieldsPermission": [],
"buttonsSetting": [
{"id": 1, "displayName": "通过", "enable": true},
{"id": 2, "displayName": "拒绝", "enable": true},
{"id": 3, "displayName": "转办", "enable": true},
{"id": 4, "displayName": "委派", "enable": true},
{"id": 5, "displayName": "加签", "enable": true},
{"id": 6, "displayName": "退回", "enable": true}
],
"signEnable": false,
"reasonRequire": false,
"rejectHandler": {"type": 1, "returnNodeId": null},
"timeoutHandler": {"enable": false, "type": null, "timeDuration": null, "maxRemindCount": null},
"assignStartUserHandlerType": 1,
"assignEmptyHandler": {"type": 1, "userIds": null},
"childNode": {"id": "EndEvent", "type": 1, "name": "结束"}
}
}
],
"childNode": {"id": "EndEvent", "type": 1, "name": "结束"}
}
}
},
"fieldsPermission": [],
"buttonsSetting": [
{"id": 1, "displayName": "提交", "enable": true},
{"id": 2, "displayName": "拒绝", "enable": false},
{"id": 3, "displayName": "转办", "enable": false},
{"id": 4, "displayName": "委派", "enable": false},
{"id": 5, "displayName": "加签", "enable": false},
{"id": 6, "displayName": "退回", "enable": false}
]
}五、合同变更审批流程(contract_change)
5.1 流程拓扑图
发起人 ──→ 部门负责人审批 ──→ 合同专员审核 ──→ 分管领导审批 ──→ 结束变更流程采用固定链式审批,不按金额分流。原因:变更是在已审批合同基础上的调整,已经过一次完整审批,变更审批侧重于合规确认。
5.2 节点详细配置
节点 1:发起人
| 配置项 | 值 |
|---|---|
| id | StartUserNode |
| type | 10(发起人) |
| name | 发起人 |
| buttonsSetting | 提交=启用, 其余=禁用 |
节点 2:部门负责人审批
| 配置项 | 值 |
|---|---|
| type | 11(审批人) |
| name | 部门负责人审批 |
| candidateStrategy | 37(发起人部门负责人) |
| approveType | 1(人工审批) |
| approveMethod | 4(或签) |
| rejectHandler.type | 1(驳回到发起人) |
| assignStartUserHandlerType | 1(发起人即审批人时自动通过) |
节点 3:合同专员审核
| 配置项 | 值 |
|---|---|
| type | 11(审批人) |
| name | 合同专员审核 |
| candidateStrategy | 22(岗位) |
| candidateParam | "13"(合同专员岗位 id) |
| approveType | 1(人工审批) |
| approveMethod | 4(或签) |
| rejectHandler.type | 1(驳回到发起人) |
节点 4:分管领导审批
| 配置项 | 值 |
|---|---|
| type | 11(审批人) |
| name | 分管领导审批 |
| candidateStrategy | 22(岗位) |
| candidateParam | "10"(分管领导岗位 id) |
| approveType | 1(人工审批) |
| approveMethod | 4(或签) |
| rejectHandler.type | 1(驳回到发起人) |
节点 5:结束
| 配置项 | 值 |
|---|---|
| id | EndEvent |
| type | 1(结束) |
| name | 结束 |
5.3 simple_model JSON 参考
{
"id": "StartUserNode",
"type": 10,
"name": "发起人",
"showText": "已设置",
"childNode": {
"id": "Activity_dept_leader",
"type": 11,
"name": "部门负责人审批",
"showText": "发起人部门负责人",
"candidateStrategy": 37,
"approveType": 1,
"approveMethod": 4,
"fieldsPermission": [],
"buttonsSetting": [
{"id": 1, "displayName": "通过", "enable": true},
{"id": 2, "displayName": "拒绝", "enable": true},
{"id": 3, "displayName": "转办", "enable": true},
{"id": 4, "displayName": "委派", "enable": true},
{"id": 5, "displayName": "加签", "enable": true},
{"id": 6, "displayName": "退回", "enable": true}
],
"signEnable": false,
"reasonRequire": false,
"rejectHandler": {"type": 1, "returnNodeId": null},
"timeoutHandler": {"enable": false, "type": null, "timeDuration": null, "maxRemindCount": null},
"assignStartUserHandlerType": 1,
"assignEmptyHandler": {"type": 1, "userIds": null},
"childNode": {
"id": "Activity_contract_spec",
"type": 11,
"name": "合同专员审核",
"showText": "指定岗位: 合同专员",
"candidateStrategy": 22,
"candidateParam": "13",
"approveType": 1,
"approveMethod": 4,
"fieldsPermission": [],
"buttonsSetting": [
{"id": 1, "displayName": "通过", "enable": true},
{"id": 2, "displayName": "拒绝", "enable": true},
{"id": 3, "displayName": "转办", "enable": true},
{"id": 4, "displayName": "委派", "enable": true},
{"id": 5, "displayName": "加签", "enable": true},
{"id": 6, "displayName": "退回", "enable": true}
],
"signEnable": false,
"reasonRequire": false,
"rejectHandler": {"type": 1, "returnNodeId": null},
"timeoutHandler": {"enable": false, "type": null, "timeDuration": null, "maxRemindCount": null},
"assignStartUserHandlerType": 1,
"assignEmptyHandler": {"type": 1, "userIds": null},
"childNode": {
"id": "Activity_sub_leader",
"type": 11,
"name": "分管领导审批",
"showText": "指定岗位: 分管领导",
"candidateStrategy": 22,
"candidateParam": "10",
"approveType": 1,
"approveMethod": 4,
"fieldsPermission": [],
"buttonsSetting": [
{"id": 1, "displayName": "通过", "enable": true},
{"id": 2, "displayName": "拒绝", "enable": true},
{"id": 3, "displayName": "转办", "enable": true},
{"id": 4, "displayName": "委派", "enable": true},
{"id": 5, "displayName": "加签", "enable": true},
{"id": 6, "displayName": "退回", "enable": true}
],
"signEnable": false,
"reasonRequire": false,
"rejectHandler": {"type": 1, "returnNodeId": null},
"timeoutHandler": {"enable": false, "type": null, "timeDuration": null, "maxRemindCount": null},
"assignStartUserHandlerType": 1,
"assignEmptyHandler": {"type": 1, "userIds": null},
"childNode": {"id": "EndEvent", "type": 1, "name": "结束"}
}
}
},
"fieldsPermission": [],
"buttonsSetting": [
{"id": 1, "displayName": "提交", "enable": true},
{"id": 2, "displayName": "拒绝", "enable": false},
{"id": 3, "displayName": "转办", "enable": false},
{"id": 4, "displayName": "委派", "enable": false},
{"id": 5, "displayName": "加签", "enable": false},
{"id": 6, "displayName": "退回", "enable": false}
]
}六、BPM 设计器配置步骤
6.1 前置准备
- 执行岗位 SQL,新增"合同专员"岗位(id=13)
- 在系统管理 -> 岗位管理中,为相关用户分配岗位:
- 将合同审核人员分配"合同专员"岗位
- 确认"分管领导"、"主要领导"岗位已分配给对应用户
6.2 创建合同审批流程模型(contract_approve)
步骤 1:新建流程模型
进入 流程管理 -> 流程模型 页面,点击"新建流程":
| 字段 | 填写值 |
|---|---|
| 流程标识(Key) | contract_approve |
| 流程名称 | 合同审批 |
| 流程分类 | 选择或新建"合同管理"分类 |
| 流程图类型 | 选择"仿钉钉设计" |
步骤 2:配置表单
| 字段 | 填写值 |
|---|---|
| 表单类型 | 业务表单(formType=20) |
| 创建路径(formCustomCreatePath) | /contract/contract-info-detail |
| 详情路径(formCustomViewPath) | /contract/contract-info-detail |
| 流程管理员 | 选择管理员用户 |
步骤 3:设计审批链
在仿钉钉流程设计器中,按以下顺序添加节点:
发起人(默认已有)
- 按钮设置:仅启用"提交"
点击"+"添加 审批人 节点 → 命名为"部门负责人审批"
- 审批方式:人工审批
- 候选人策略:选择 发起人部门负责人(strategy=37)
- 多人审批方式:或签
- 拒绝策略:驳回到发起人
- 当发起人是审批人时:自动通过
点击"+"添加 审批人 节点 → 命名为"合同专员审核"
- 候选人策略:选择 岗位(strategy=22)
- 岗位选择:合同专员(id=13)
- 多人审批方式:或签
- 拒绝策略:驳回到发起人
点击"+"添加 条件分支 节点 → 命名为"金额分级审批"
- 条件 1:小额合同(≤10万)
- 条件类型:规则
- 字段:
contractAmount(合同金额) - 运算符:≤
- 值:
100000 - 子节点:添加审批人"分管领导审批"
- 候选人策略:岗位 → 分管领导(id=10)
- 多人审批方式:或签
- 拒绝策略:驳回到发起人
- 条件 2(默认分支):大额合同(>10万)
- 设为默认分支
- 子节点:添加审批人"主要领导审批"
- 候选人策略:岗位 → 主要领导(id=11)
- 多人审批方式:或签
- 拒绝策略:驳回到发起人
- 条件 1:小额合同(≤10万)
步骤 4:发布流程
确认节点配置无误后,点击"发布"按钮完成流程部署。
6.3 创建合同变更审批流程模型(contract_change)
步骤 1:新建流程模型
| 字段 | 填写值 |
|---|---|
| 流程标识(Key) | contract_change |
| 流程名称 | 合同变更审批 |
| 流程分类 | 选择"合同管理"分类 |
| 流程图类型 | 选择"仿钉钉设计" |
步骤 2:配置表单
| 字段 | 填写值 |
|---|---|
| 表单类型 | 业务表单(formType=20) |
| 创建路径(formCustomCreatePath) | /contract/contract-change |
| 详情路径(formCustomViewPath) | /contract/contract-change |
| 流程管理员 | 选择管理员用户 |
步骤 3:设计审批链
发起人(默认已有)
- 按钮设置:仅启用"提交"
添加 审批人 节点 → "部门负责人审批"
- 候选人策略:发起人部门负责人(strategy=37)
- 多人审批方式:或签
- 拒绝策略:驳回到发起人
- 当发起人是审批人时:自动通过
添加 审批人 节点 → "合同专员审核"
- 候选人策略:岗位(strategy=22)→ 合同专员(id=13)
- 多人审批方式:或签
- 拒绝策略:驳回到发起人
添加 审批人 节点 → "分管领导审批"
- 候选人策略:岗位(strategy=22)→ 分管领导(id=10)
- 多人审批方式:或签
- 拒绝策略:驳回到发起人
步骤 4:发布流程
确认节点配置无误后,点击"发布"按钮。
七、流程与代码的关联说明
7.1 代码侧已就绪的部分
| 组件 | 文件 | 说明 |
|---|---|---|
| 单据类型枚举 | ContractBillTypeEnum.java | CONTRACT_APPROVE("201", "合同审批", "contract_approve") / CONTRACT_CHANGE("202", "合同变更审批", "contract_change") |
| 合同提交审批 | ContractInfoServiceImpl.submitContractInfo() | 调用 processInstanceApi.submitProcessInstance() 传入 contract_approve |
| 变更提交审批 | ContractChangeServiceImpl.submitChange() | 调用 processInstanceApi.submitProcessInstance() 传入 contract_change |
| 流程工厂 | ContractFlowBillServiceFactory | 注册全部 ContractBillTypeEnum |
| 流程回调(MQ) | ContractMqNotificationConsumer | 接收审批结果,更新合同状态 |
| 流程回调(本地) | ContractLocalNotificationListener | 本地事件模式的审批结果回调 |
| 流程回调(Feign) | ContractFeignNotificationController | 微服务模式的审批结果回调 |
| 系统枚举 | SystemEnum.CONTRACT("CT", "合同管理系统") | 三通道回调路由标识 |
7.2 配置完流程后的验证步骤
- 岗位分配验证:确认"合同专员"、"分管领导"、"主要领导"岗位下均有用户
- 流程发布验证:在流程模型列表确认
contract_approve、contract_change状态为"已部署" - 合同提交测试:创建合同 → 提交审批 → 确认流程实例创建成功,审批状态变更为"审批中"
- 审批链测试:登录各节点审批人账号 → 依次审批 → 确认合同状态最终变为"已审批"
- 条件分支测试:分别创建金额 ≤10万和 >10万的合同,验证分别流转到分管领导和主要领导
- 变更流程测试:对已生效合同发起变更 → 提交审批 → 依次通过三级审批 → 确认变更生效
八、条件分支中 contractAmount 字段说明
条件分支依赖流程变量 contractAmount,该变量在合同提交审批时通过 BpmProcessVariableUtils.buildBillVariables() 自动提取。
确认 contract_info 表中的 contract_amount 字段(decimal(18,2))会被映射为流程变量。如果自动提取不包含该字段,需在 ContractInfoServiceImpl.submitContractInfo() 中手动添加:
Map<String, Object> variables = BpmProcessVariableUtils.buildBillVariables(saveReqVO);
variables.put("contractAmount", contractInfo.getContractAmount());附录:审批策略对照表
| 审批场景 | 候选人策略 | candidateParam | 说明 |
|---|---|---|---|
| 发起人的直属领导审批 | 37(发起人部门负责人) | 无 | 自动获取发起人所属部门负责人 |
| 合同内容审核 | 22(岗位) | "13"(合同专员) | 需先创建岗位并分配用户 |
| 小额终审 | 22(岗位) | "10"(分管领导) | 金额 ≤ 10万 |
| 大额终审 | 22(岗位) | "11"(主要领导) | 金额 > 10万 |
