Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yanxuan-qc-change-system
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
yx-qc-change-flow
yanxuan-qc-change-system
Commits
d467bfc5
Commit
d467bfc5
authored
Dec 04, 2025
by
王志超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 行动工单流程流转
parent
5cb06801
Pipeline
#86538
passed with stages
in 1 minute 29 seconds
Changes
1
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
82 additions
and
55 deletions
+82
-55
ChangeSubFlowBiz.java
...netease/mail/yanxuan/change/biz/biz/ChangeSubFlowBiz.java
+82
-55
No files found.
yanxuan-qc-change-system-biz/src/main/java/com/netease/mail/yanxuan/change/biz/biz/ChangeSubFlowBiz.java
View file @
d467bfc5
...
@@ -58,7 +58,6 @@ import org.springframework.beans.BeanUtils;
...
@@ -58,7 +58,6 @@ import org.springframework.beans.BeanUtils;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.Assert
;
import
org.springframework.util.Assert
;
import
javax.validation.Valid
;
import
java.util.*
;
import
java.util.*
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
...
@@ -221,19 +220,26 @@ public class ChangeSubFlowBiz {
...
@@ -221,19 +220,26 @@ public class ChangeSubFlowBiz {
subFlowRecord
.
getChangeRecordId
(),
changeExecProjectList
,
subFlowId
,
subFlowRecord
.
getId
());
subFlowRecord
.
getChangeRecordId
(),
changeExecProjectList
,
subFlowId
,
subFlowRecord
.
getId
());
newExecRecords
.
forEach
(
changeFlowExecService:
:
saveRecord
);
newExecRecords
.
forEach
(
changeFlowExecService:
:
saveRecord
);
// 提交到下一节点
// 检查是否需要审批,通过paramMap控制流转方向
String
nextNodeId
=
flowService
.
submitFlow
(
subFlowId
,
flowDataDTO
,
uid
,
Map
<
String
,
Object
>
paramMap
=
new
HashMap
<>();
ChangeFlowEnum
.
CHANGE_SUB_FLOW
.
getTopoId
(),
JSON
.
toJSONString
(
content
),
true
,
String
nextNodeId
;
FlowxOperationEnum
.
SUBMIT
.
getName
(),
"提交工单"
,
subFlowRecord
.
getCreateTime
());
// 检查是否需要审批
if
(
needApprove
(
expectedDepartment
))
{
if
(
needApprove
(
expectedDepartment
))
{
// 需要审批:流转到审批行动方案节点,设置上级领导为审批人
log
.
info
(
"[CHANGE_SUB_FLOW_START] 部门[{}]需要审批,等待上级审批"
,
expectedDepartment
);
log
.
info
(
"[CHANGE_SUB_FLOW_START] 部门[{}]需要审批,等待上级审批"
,
expectedDepartment
);
// 需要审批:设置上级领导为审批人,停留在审批节点
paramMap
.
put
(
"type"
,
1
);
// 提交到审批行动方案节点
nextNodeId
=
flowService
.
submitFlowWithParamMap
(
subFlowId
,
flowDataDTO
,
uid
,
ChangeFlowEnum
.
CHANGE_SUB_FLOW
.
getTopoId
(),
JSON
.
toJSONString
(
content
),
paramMap
,
FlowxOperationEnum
.
SUBMIT
.
getName
(),
"提交工单"
,
subFlowRecord
.
getCreateTime
());
// 更新子单记录
subFlowRecord
.
setSubFlowNode
(
nextNodeId
);
subFlowRecord
.
setSubFlowNode
(
nextNodeId
);
subFlowRecord
.
setStatus
(
ChangeSubFlowStatusEnum
.
WAIT_APPROVE_ACTION_PLAN
.
getStatus
());
subFlowRecord
.
setStatus
(
ChangeSubFlowStatusEnum
.
WAIT_APPROVE_ACTION_PLAN
.
getStatus
());
subFlowRecord
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
subFlowRecord
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
// 获取上级领导并设置为审批人
String
execUserEmail
=
subFlowRecord
.
getChangeExecUserEmail
();
String
execUserEmail
=
subFlowRecord
.
getChangeExecUserEmail
();
if
(
StringUtils
.
isBlank
(
execUserEmail
))
{
if
(
StringUtils
.
isBlank
(
execUserEmail
))
{
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
"行动人邮箱不能为空"
);
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
"行动人邮箱不能为空"
);
...
@@ -243,39 +249,33 @@ public class ChangeSubFlowBiz {
...
@@ -243,39 +249,33 @@ public class ChangeSubFlowBiz {
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
String
.
format
(
"行动人[%s]的部门上级领导不存在"
,
execUserEmail
));
String
.
format
(
"行动人[%s]的部门上级领导不存在"
,
execUserEmail
));
}
}
// 设置审批人为上级领导(JSON 数组格式)
subFlowRecord
.
setApprover
(
JSON
.
toJSONString
(
Collections
.
singletonList
(
leaderEmail
)));
subFlowRecord
.
setApprover
(
JSON
.
toJSONString
(
Collections
.
singletonList
(
leaderEmail
)));
changeSubFlowRecordService
.
update
(
subFlowRecord
);
log
.
info
(
"[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 原节点:{}-{}, 新节点:{}-审批行动方案"
,
log
.
info
(
"[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 原节点:{}-{}, 新节点:{}-审批行动方案"
,
subFlowId
,
oldNodeId
,
oldNodeName
,
nextNodeId
);
subFlowId
,
oldNodeId
,
oldNodeName
,
nextNodeId
);
return
nextNodeId
;
}
else
{
}
else
{
// 不需要审批
,自动提交到下一节点(审批人保持为行动人自己)
// 不需要审批
:直接跳到审批变更方案节点,审批人保持为行动人自己
log
.
info
(
"[CHANGE_SUB_FLOW_START] 部门[{}]不需要审批,自动跳过审批"
,
expectedDepartment
);
log
.
info
(
"[CHANGE_SUB_FLOW_START] 部门[{}]不需要审批,自动跳过审批"
,
expectedDepartment
);
paramMap
.
put
(
"type"
,
2
);
// 重新查询最新的flowDataDTO,因为第一次submitFlow已经改变了flow状态
// 提交到审批变更方案节点
FlowDataDTO
latestFlowDataDTO
=
flowService
.
flowDetail
(
subFlowId
);
nextNodeId
=
flowService
.
submitFlowWithParamMap
(
subFlowId
,
flowDataDTO
,
uid
,
if
(
latestFlowDataDTO
==
null
)
{
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
DETAIL_FLOW_ERROR
,
"子流程工单查询错误,不存在"
);
}
// 使用paramMap控制流转方向(type=1表示审批通过)
Map
<
String
,
Object
>
paramMap
=
new
HashMap
<>();
paramMap
.
put
(
"type"
,
1
);
String
autoNextNodeId
=
flowService
.
submitFlowWithParamMap
(
subFlowId
,
latestFlowDataDTO
,
uid
,
ChangeFlowEnum
.
CHANGE_SUB_FLOW
.
getTopoId
(),
JSON
.
toJSONString
(
content
),
paramMap
,
ChangeFlowEnum
.
CHANGE_SUB_FLOW
.
getTopoId
(),
JSON
.
toJSONString
(
content
),
paramMap
,
FlowxOperationEnum
.
SUBMIT
.
getName
(),
"自动审批通过"
,
subFlowRecord
.
getCreateTime
());
FlowxOperationEnum
.
SUBMIT
.
getName
(),
"提交工单"
,
subFlowRecord
.
getCreateTime
());
subFlowRecord
.
setSubFlowNode
(
autoNextNodeId
);
// 更新子单记录
subFlowRecord
.
setSubFlowNode
(
nextNodeId
);
subFlowRecord
.
setStatus
(
ChangeSubFlowStatusEnum
.
WAIT_APPROVE_CHANGE_PLAN
.
getStatus
());
subFlowRecord
.
setStatus
(
ChangeSubFlowStatusEnum
.
WAIT_APPROVE_CHANGE_PLAN
.
getStatus
());
subFlowRecord
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
subFlowRecord
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
changeSubFlowRecordService
.
update
(
subFlowRecord
);
// todo:非名单中部门无需审批,行动人确认提交后邮件同步负责人上级对应变更信息
// todo:非名单中部门无需审批,行动人确认提交后邮件同步负责人上级对应变更信息
log
.
info
(
"[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 原节点:{}-{}, 新节点:{}-审批变更方案 (自动跳过审批)"
,
log
.
info
(
"[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 原节点:{}-{}, 新节点:{}-审批变更方案 (自动跳过审批)"
,
subFlowId
,
oldNodeId
,
oldNodeName
,
autoNextNodeId
);
subFlowId
,
oldNodeId
,
oldNodeName
,
nextNodeId
);
return
autoNextNodeId
;
}
}
changeSubFlowRecordService
.
update
(
subFlowRecord
);
return
nextNodeId
;
case
CHANGE_SUB_FLOW_SUBMIT:
case
CHANGE_SUB_FLOW_SUBMIT:
// 审批行动方案节点
// 审批行动方案节点
Boolean
approved
=
changeSubFlowSubmitReq
.
getApproved
();
Boolean
approved
=
changeSubFlowSubmitReq
.
getApproved
();
...
@@ -293,10 +293,13 @@ public class ChangeSubFlowBiz {
...
@@ -293,10 +293,13 @@ public class ChangeSubFlowBiz {
log
.
info
(
"[CHANGE_SUB_FLOW_SUBMIT] 审批不通过,subFlowId:{}, rejectReason:{}"
,
subFlowId
,
rejectReason
);
log
.
info
(
"[CHANGE_SUB_FLOW_SUBMIT] 审批不通过,subFlowId:{}, rejectReason:{}"
,
subFlowId
,
rejectReason
);
}
}
// 提交工单(根据审批结果流转到不同节点)
// 使用paramMap控制流转方向(type=1通过,type=2不通过)
Map
<
String
,
Object
>
approveParamMap
=
new
HashMap
<>();
approveParamMap
.
put
(
"type"
,
approved
?
1
:
2
);
String
remark
=
approved
?
"审批通过"
:
"审批不通过"
;
String
remark
=
approved
?
"审批通过"
:
"审批不通过"
;
String
approveNodeId
=
flowService
.
submitFlow
(
subFlowId
,
flowDataDTO
,
uid
,
String
approveNodeId
=
flowService
.
submitFlow
WithParamMap
(
subFlowId
,
flowDataDTO
,
uid
,
ChangeFlowEnum
.
CHANGE_SUB_FLOW
.
getTopoId
(),
JSON
.
toJSONString
(
content
),
approve
d
,
ChangeFlowEnum
.
CHANGE_SUB_FLOW
.
getTopoId
(),
JSON
.
toJSONString
(
content
),
approve
ParamMap
,
FlowxOperationEnum
.
SUBMIT
.
getName
(),
remark
,
subFlowRecord
.
getCreateTime
());
FlowxOperationEnum
.
SUBMIT
.
getName
(),
remark
,
subFlowRecord
.
getCreateTime
());
// 更新行动工单
// 更新行动工单
...
@@ -318,36 +321,60 @@ public class ChangeSubFlowBiz {
...
@@ -318,36 +321,60 @@ public class ChangeSubFlowBiz {
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
"审批结果不能为空"
);
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
"审批结果不能为空"
);
}
}
if
(!
execApproved
)
{
// 使用paramMap控制流转方向
// 审批不通过,拒绝原因必填
Map
<
String
,
Object
>
execParamMap
=
new
HashMap
<>();
String
execNodeId
;
if
(
execApproved
)
{
// 审批通过:流转到提交执行结果节点
log
.
info
(
"[CHANGE_SUB_FLOW_EXE] 审批通过,subFlowId:{}"
,
subFlowId
);
execParamMap
.
put
(
"type"
,
1
);
// 提交到提交执行结果节点
execNodeId
=
flowService
.
submitFlowWithParamMap
(
subFlowId
,
flowDataDTO
,
uid
,
ChangeFlowEnum
.
CHANGE_SUB_FLOW
.
getTopoId
(),
JSON
.
toJSONString
(
content
),
execParamMap
,
FlowxOperationEnum
.
SUBMIT
.
getName
(),
"审批通过"
,
subFlowRecord
.
getCreateTime
());
// 更新子单记录
subFlowRecord
.
setSubFlowNode
(
execNodeId
);
subFlowRecord
.
setStatus
(
ChangeSubFlowStatusEnum
.
WAIT_SUBMIT_RESULT
.
getStatus
());
subFlowRecord
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
changeSubFlowRecordService
.
update
(
subFlowRecord
);
log
.
info
(
"[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 原节点:{}-{}, 新节点:{}-提交执行结果, 审批结果:通过"
,
subFlowId
,
oldNodeId
,
oldNodeName
,
execNodeId
);
// 检查所有子单是否都已到达提交执行结果节点,如果是则流转主工单
if
(
checkAllSubFlowsApproved
(
subFlowRecord
.
getChangeRecordId
()))
{
changeFlowBiz
.
submitMainFlowAfterAllSubFlowsApproved
(
subFlowRecord
.
getChangeRecordId
());
log
.
info
(
"[CHANGE_SUB_FLOW_EXE] 所有子单均已到达提交执行结果节点,主工单已流转"
);
}
}
else
{
// 审批不通过:回退到确认行动方案节点,拒绝原因必填
String
execRejectReason
=
changeSubFlowSubmitReq
.
getRejectReason
();
String
execRejectReason
=
changeSubFlowSubmitReq
.
getRejectReason
();
if
(
StringUtils
.
isBlank
(
execRejectReason
))
{
if
(
StringUtils
.
isBlank
(
execRejectReason
))
{
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
"拒绝原因不能为空"
);
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
"拒绝原因不能为空"
);
}
}
subFlowRecord
.
setChangePlanApproved
(
false
);
subFlowRecord
.
setRejectReason
(
execRejectReason
);
subFlowRecord
.
setRejectReason
(
execRejectReason
);
subFlowRecord
.
setStatus
(
ChangeSubFlowStatusEnum
.
CANCELLED
.
getStatus
());
subFlowRecord
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
changeSubFlowRecordService
.
update
(
subFlowRecord
);
log
.
info
(
"[CHANGE_SUB_FLOW_EXE] 审批不通过,subFlowId:{}, rejectReason:{}"
,
subFlowId
,
execRejectReason
);
log
.
info
(
"[CHANGE_SUB_FLOW_EXE] 审批不通过,subFlowId:{}, rejectReason:{}"
,
subFlowId
,
execRejectReason
);
}
else
{
execParamMap
.
put
(
"type"
,
2
);
// 审批通过,只标记 changePlanApproved=true,子单不流转
subFlowRecord
.
setChangePlanApproved
(
true
);
// 提交到确认行动方案节点
execNodeId
=
flowService
.
submitFlowWithParamMap
(
subFlowId
,
flowDataDTO
,
uid
,
ChangeFlowEnum
.
CHANGE_SUB_FLOW
.
getTopoId
(),
JSON
.
toJSONString
(
content
),
execParamMap
,
FlowxOperationEnum
.
SUBMIT
.
getName
(),
"审批不通过"
,
subFlowRecord
.
getCreateTime
());
// 更新子单记录
subFlowRecord
.
setSubFlowNode
(
execNodeId
);
subFlowRecord
.
setStatus
(
ChangeSubFlowStatusEnum
.
CANCELLED
.
getStatus
());
subFlowRecord
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
subFlowRecord
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
changeSubFlowRecordService
.
update
(
subFlowRecord
);
changeSubFlowRecordService
.
update
(
subFlowRecord
);
log
.
info
(
"[CHANGE_SUB_FLOW_EXE] 审批通过,subFlowId:{}, 标记changePlanApproved=true"
,
subFlowId
);
// 检查该主工单下所有子单是否都已审批通过
log
.
info
(
"[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 原节点:{}-{}, 新节点:{}-确认行动方案, 审批结果:不通过"
,
if
(
checkAllSubFlowsApproved
(
subFlowRecord
.
getChangeRecordId
()))
{
subFlowId
,
oldNodeId
,
oldNodeName
,
execNodeId
);
// 所有子单都通过,流转主工单
changeFlowBiz
.
submitMainFlowAfterAllSubFlowsApproved
(
subFlowRecord
.
getChangeRecordId
());
log
.
info
(
"[CHANGE_SUB_FLOW_EXE] 所有子单均已审批通过,主工单已流转"
);
}
}
}
log
.
info
(
"[checkUpdateAndSubmit] 子单流转完成 <<< subFlowId:{}, 节点保持:{}-{}, 审批结果:{}"
,
return
execNodeId
;
subFlowId
,
oldNodeId
,
oldNodeName
,
execApproved
?
"通过"
:
"不通过"
);
return
subFlowRecord
.
getSubFlowNode
();
case
CHANGE_SUB_FLOW_CONFIRM:
case
CHANGE_SUB_FLOW_CONFIRM:
// 提交执行结果节点,填写变更结论
// 提交执行结果节点,填写变更结论
...
@@ -543,11 +570,11 @@ public class ChangeSubFlowBiz {
...
@@ -543,11 +570,11 @@ public class ChangeSubFlowBiz {
}
}
/**
/**
* 检查主工单下所有子单是否都已
审批通过
* 检查主工单下所有子单是否都已
到达提交执行结果节点
* 条件:
节点是 CHANGE_SUB_FLOW_EXE 且 changePlanApproved=true
* 条件:
status = WAIT_SUBMIT_RESULT 且 subFlowNode = CHANGE_SUB_FLOW_CONFIRM
*
*
* @param changeRecordId 主工单ID
* @param changeRecordId 主工单ID
* @return true 表示所有子单都已
审批通过
* @return true 表示所有子单都已
到达提交执行结果节点
*/
*/
private
boolean
checkAllSubFlowsApproved
(
Long
changeRecordId
)
{
private
boolean
checkAllSubFlowsApproved
(
Long
changeRecordId
)
{
// 查询该主工单下所有子单
// 查询该主工单下所有子单
...
@@ -556,10 +583,10 @@ public class ChangeSubFlowBiz {
...
@@ -556,10 +583,10 @@ public class ChangeSubFlowBiz {
return
false
;
return
false
;
}
}
// 检查是否所有子单都满足条件:
节点是 CHANGE_SUB_FLOW_EXE 且 changePlanApproved=true
// 检查是否所有子单都满足条件:
status = WAIT_SUBMIT_RESULT 且 subFlowNode = CHANGE_SUB_FLOW_CONFIRM
return
allSubFlows
.
stream
().
allMatch
(
subFlow
->
return
allSubFlows
.
stream
().
allMatch
(
subFlow
->
Change
FlowEnum
.
CHANGE_SUB_FLOW_EXE
.
getNodeId
().
equals
(
subFlow
.
getSubFlowNode
())
Change
SubFlowStatusEnum
.
WAIT_SUBMIT_RESULT
.
getStatus
().
equals
(
subFlow
.
getStatus
())
&&
Boolean
.
TRUE
.
equals
(
subFlow
.
getChangePlanApproved
())
&&
ChangeFlowEnum
.
CHANGE_SUB_FLOW_CONFIRM
.
getNodeId
().
equals
(
subFlow
.
getSubFlowNode
())
);
);
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment