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
479f9a08
Commit
479f9a08
authored
Dec 03, 2025
by
王志超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 子工单分批审核,所有到达待审批时,自动流转到待提交工单,主工单流转到待负责人审批
parent
498a3295
Pipeline
#86446
passed with stages
in 1 minute 26 seconds
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
137 additions
and
11 deletions
+137
-11
ChangeFlowBiz.java
...om/netease/mail/yanxuan/change/biz/biz/ChangeFlowBiz.java
+44
-0
ChangeSubFlowBiz.java
...netease/mail/yanxuan/change/biz/biz/ChangeSubFlowBiz.java
+86
-10
ChangeSubFlowRecord.java
...e/mail/yanxuan/change/dal/entity/ChangeSubFlowRecord.java
+5
-0
ChangeSubFlowRecordMapper.xml
...in/resources/mybatis/mapper/ChangeSubFlowRecordMapper.xml
+2
-1
No files found.
yanxuan-qc-change-system-biz/src/main/java/com/netease/mail/yanxuan/change/biz/biz/ChangeFlowBiz.java
View file @
479f9a08
...
@@ -58,6 +58,7 @@ import com.netease.mail.yanxuan.change.dal.entity.ChangeRecord;
...
@@ -58,6 +58,7 @@ import com.netease.mail.yanxuan.change.dal.entity.ChangeRecord;
import
com.netease.mail.yanxuan.change.dal.entity.ChangeSubFlowRecord
;
import
com.netease.mail.yanxuan.change.dal.entity.ChangeSubFlowRecord
;
import
com.netease.mail.yanxuan.change.dal.entity.ChangeType
;
import
com.netease.mail.yanxuan.change.dal.entity.ChangeType
;
import
com.netease.mail.yanxuan.change.dal.mapper.ChangeRecordMapper
;
import
com.netease.mail.yanxuan.change.dal.mapper.ChangeRecordMapper
;
import
com.netease.mail.yanxuan.change.dal.mapper.ChangeSubFlowRecordMapper
;
import
com.netease.mail.yanxuan.change.dal.meta.model.po.ChangeCommanderPO
;
import
com.netease.mail.yanxuan.change.dal.meta.model.po.ChangeCommanderPO
;
import
com.netease.mail.yanxuan.change.dal.meta.model.po.ChangeConfigPo
;
import
com.netease.mail.yanxuan.change.dal.meta.model.po.ChangeConfigPo
;
import
com.netease.mail.yanxuan.change.dal.meta.model.po.ChangeGoodsPrincipalPO
;
import
com.netease.mail.yanxuan.change.dal.meta.model.po.ChangeGoodsPrincipalPO
;
...
@@ -131,6 +132,9 @@ public class ChangeFlowBiz {
...
@@ -131,6 +132,9 @@ public class ChangeFlowBiz {
private
ChangeRecordMapper
changeRecordMapper
;
private
ChangeRecordMapper
changeRecordMapper
;
@Autowired
@Autowired
private
ChangeSubFlowRecordMapper
changeSubFlowRecordMapper
;
@Autowired
private
ItemService
itemService
;
private
ItemService
itemService
;
@Autowired
@Autowired
...
@@ -699,6 +703,24 @@ public class ChangeFlowBiz {
...
@@ -699,6 +703,24 @@ public class ChangeFlowBiz {
createAndBindSubFlows
(
changeRecord
,
flowName
);
createAndBindSubFlows
(
changeRecord
,
flowName
);
buildAndSendEmail
.
buildAndSendEmailSubmit
(
changeRecord
,
changeExecRecords
);
buildAndSendEmail
.
buildAndSendEmailSubmit
(
changeRecord
,
changeExecRecords
);
return
submitNode
;
return
submitNode
;
case
NEW_CHANGE_FLOW_CONFIRM_EXEC_PLAN:
// 确认变更方案节点:检查所有子单是否都已审批通过
if
(!
checkAllSubFlowsApprovedForMainFlow
(
changeRecord
.
getId
()))
{
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
"存在子单未审批通过,无法流转主工单"
);
}
// 所有子单都已审批通过,流转主工单到部门负责人审批节点
String
ownerApproveNodeId
=
flowService
.
submitFlow
(
flowId
.
toString
(),
flowDataDTO
,
uid
,
ChangeFlowEnum
.
NEW_CHANGE_FLOW
.
getTopoId
(),
JSON
.
toJSONString
(
content
),
true
,
FlowxOperationEnum
.
SUBMIT
.
getName
(),
"所有子单审批通过,主工单流转"
,
changeRecord
.
getCreateTime
());
changeRecord
.
setFlowNode
(
ownerApproveNodeId
);
changeRecord
.
setState
(
ChangeStatusEnum
.
WAIT_DEPT_LEADER_APPROVE
.
getStatus
());
changeRecord
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
changeFlowService
.
updateRecord
(
changeRecord
);
log
.
info
(
"[NEW_CHANGE_FLOW_CONFIRM_EXEC_PLAN] 主工单流转成功,flowId:{}, nextNodeId:{}"
,
flowId
,
ownerApproveNodeId
);
return
ownerApproveNodeId
;
case
CHANGE_FLOW_CONFIRM:
case
CHANGE_FLOW_CONFIRM:
Integer
changeResult
=
changeFlowSubmitReq
.
getChangeResult
();
Integer
changeResult
=
changeFlowSubmitReq
.
getChangeResult
();
ChangeResultEnum
changeResultStatus
=
ChangeResultEnum
.
getByStatus
(
changeResult
);
ChangeResultEnum
changeResultStatus
=
ChangeResultEnum
.
getByStatus
(
changeResult
);
...
@@ -1688,4 +1710,26 @@ public class ChangeFlowBiz {
...
@@ -1688,4 +1710,26 @@ public class ChangeFlowBiz {
changeExecUserEmail
,
changeExecDepartment
);
changeExecUserEmail
,
changeExecDepartment
);
}
}
}
}
/**
* 检查主工单下所有子单是否都已审批通过(供主工单流转时调用)
* 条件:节点是 CHANGE_SUB_FLOW_EXE 且 changePlanApproved=true
*
* @param changeRecordId 主工单ID
* @return true 表示所有子单都已审批通过
*/
public
boolean
checkAllSubFlowsApprovedForMainFlow
(
Long
changeRecordId
)
{
// 查询该主工单下所有子单
List
<
ChangeSubFlowRecord
>
allSubFlows
=
changeSubFlowRecordMapper
.
selectByChangeRecordId
(
changeRecordId
);
if
(
CollectionUtils
.
isEmpty
(
allSubFlows
))
{
return
false
;
}
// 检查是否所有子单都满足条件:节点是 CHANGE_SUB_FLOW_EXE 且 changePlanApproved=true
return
allSubFlows
.
stream
().
allMatch
(
subFlow
->
ChangeFlowEnum
.
CHANGE_SUB_FLOW_EXE
.
getNodeId
().
equals
(
subFlow
.
getSubFlowNode
())
&&
Boolean
.
TRUE
.
equals
(
subFlow
.
getChangePlanApproved
())
);
}
}
}
yanxuan-qc-change-system-biz/src/main/java/com/netease/mail/yanxuan/change/biz/biz/ChangeSubFlowBiz.java
View file @
479f9a08
...
@@ -28,6 +28,7 @@ import com.netease.mail.yanxuan.change.dal.mapper.ChangeRecordMapper;
...
@@ -28,6 +28,7 @@ import com.netease.mail.yanxuan.change.dal.mapper.ChangeRecordMapper;
import
com.netease.mail.yanxuan.change.dal.mapper.ChangeSubFlowRecordMapper
;
import
com.netease.mail.yanxuan.change.dal.mapper.ChangeSubFlowRecordMapper
;
import
com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeExecConfigReq
;
import
com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeExecConfigReq
;
import
com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeFlowListQueryReq
;
import
com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeFlowListQueryReq
;
import
com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeFlowSubmitReq
;
import
com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeSubFlowCreateReq
;
import
com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeSubFlowCreateReq
;
import
com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeSubFlowListQueryReq
;
import
com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeSubFlowListQueryReq
;
import
com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeSubFlowSubmitReq
;
import
com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeSubFlowSubmitReq
;
...
@@ -261,6 +262,7 @@ public class ChangeSubFlowBiz {
...
@@ -261,6 +262,7 @@ public class ChangeSubFlowBiz {
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
);
changeSubFlowRecordService
.
update
(
subFlowRecord
);
// todo:非名单中部门无需审批,行动人确认提交后邮件同步负责人上级对应变更信息
return
autoNextNodeId
;
return
autoNextNodeId
;
case
CHANGE_SUB_FLOW_SUBMIT:
case
CHANGE_SUB_FLOW_SUBMIT:
...
@@ -296,16 +298,51 @@ public class ChangeSubFlowBiz {
...
@@ -296,16 +298,51 @@ public class ChangeSubFlowBiz {
return
approveNodeId
;
return
approveNodeId
;
case
CHANGE_SUB_FLOW_EXE:
case
CHANGE_SUB_FLOW_EXE:
// 执行行动方案节点,直接提交到提交执行结果节点
// 审批变更方案节点
String
confirmNodeId
=
flowService
.
submitFlow
(
subFlowId
,
flowDataDTO
,
uid
,
Boolean
execApproved
=
changeSubFlowSubmitReq
.
getApproved
();
ChangeFlowEnum
.
CHANGE_SUB_FLOW
.
getTopoId
(),
JSON
.
toJSONString
(
content
),
true
,
if
(
execApproved
==
null
)
{
FlowxOperationEnum
.
SUBMIT
.
getName
(),
"提交工单"
,
subFlowRecord
.
getCreateTime
());
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
"审批结果不能为空"
);
// 更新行动工单节点ID
}
subFlowRecord
.
setSubFlowNode
(
confirmNodeId
);
// TODO: 根据业务逻辑设置状态 subFlowRecord.setStatus(...)
if
(!
execApproved
)
{
subFlowRecord
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
// 审批不通过,拒绝原因必填
changeSubFlowRecordService
.
update
(
subFlowRecord
);
String
execRejectReason
=
changeSubFlowSubmitReq
.
getRejectReason
();
return
confirmNodeId
;
if
(
StringUtils
.
isBlank
(
execRejectReason
))
{
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
"拒绝原因不能为空"
);
}
subFlowRecord
.
setChangePlanApproved
(
false
);
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
);
}
else
{
// 审批通过,只标记 changePlanApproved=true,暂不更新状态和流转工单
subFlowRecord
.
setChangePlanApproved
(
true
);
subFlowRecord
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
changeSubFlowRecordService
.
update
(
subFlowRecord
);
log
.
info
(
"[CHANGE_SUB_FLOW_EXE] 审批通过,subFlowId:{}, 标记changePlanApproved=true"
,
subFlowId
);
// 检查该主工单下所有子单是否都已审批通过
if
(
changeFlowBiz
.
checkAllSubFlowsApprovedForMainFlow
(
subFlowRecord
.
getChangeRecordId
()))
{
// 所有子单都通过,批量流转所有子单并更新状态
batchSubmitAllSubFlows
(
subFlowRecord
.
getChangeRecordId
(),
flowDataDTO
,
uid
,
content
);
log
.
info
(
"[CHANGE_SUB_FLOW_EXE] 所有子单均已审批通过,批量流转子单到下一节点"
);
// 所有子单流转完成后,流转主工单
ChangeRecord
mainRecord
=
changeRecordMapper
.
selectByPrimaryKey
(
subFlowRecord
.
getChangeRecordId
());
if
(
mainRecord
!=
null
)
{
ChangeFlowSubmitReq
mainFlowSubmitReq
=
new
ChangeFlowSubmitReq
();
mainFlowSubmitReq
.
setFlowId
(
mainRecord
.
getFlowId
());
mainFlowSubmitReq
.
setCurrentNodeId
(
mainRecord
.
getFlowNode
());
changeFlowBiz
.
submit
(
mainFlowSubmitReq
);
log
.
info
(
"[CHANGE_SUB_FLOW_EXE] 主工单流转成功,changeRecordId:{}, flowId:{}"
,
subFlowRecord
.
getChangeRecordId
(),
mainRecord
.
getFlowId
());
}
}
}
return
subFlowRecord
.
getSubFlowNode
();
case
CHANGE_SUB_FLOW_CONFIRM:
case
CHANGE_SUB_FLOW_CONFIRM:
// 提交执行结果节点,需要填写完成时间和完成情况
// 提交执行结果节点,需要填写完成时间和完成情况
...
@@ -382,6 +419,45 @@ public class ChangeSubFlowBiz {
...
@@ -382,6 +419,45 @@ public class ChangeSubFlowBiz {
}
}
/**
/**
* 批量流转所有子单到下一节点,并流转主工单
*
* @param changeRecordId 主工单ID
* @param flowDataDTO 流程数据
* @param uid 操作人
* @param content 内容
*/
private
void
batchSubmitAllSubFlows
(
Long
changeRecordId
,
FlowDataDTO
flowDataDTO
,
String
uid
,
Object
content
)
{
// 查询该主工单下所有子单
List
<
ChangeSubFlowRecord
>
allSubFlows
=
changeSubFlowRecordMapper
.
selectByChangeRecordId
(
changeRecordId
);
if
(
CollectionUtils
.
isEmpty
(
allSubFlows
))
{
return
;
}
// 批量流转所有子单
for
(
ChangeSubFlowRecord
subFlow
:
allSubFlows
)
{
try
{
// 提交子单流程到下一节点
String
nextNodeId
=
flowService
.
submitFlow
(
subFlow
.
getSubFlowId
(),
flowDataDTO
,
uid
,
ChangeFlowEnum
.
CHANGE_SUB_FLOW
.
getTopoId
(),
JSON
.
toJSONString
(
content
),
true
,
FlowxOperationEnum
.
SUBMIT
.
getName
(),
"所有子单审批通过,自动流转"
,
subFlow
.
getCreateTime
());
// 更新子单节点和状态
subFlow
.
setSubFlowNode
(
nextNodeId
);
subFlow
.
setStatus
(
ChangeSubFlowStatusEnum
.
WAIT_SUBMIT_RESULT
.
getStatus
());
subFlow
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
changeSubFlowRecordService
.
update
(
subFlow
);
log
.
info
(
"[batchSubmitAllSubFlows] 子单流转成功,subFlowId:{}, nextNodeId:{}"
,
subFlow
.
getSubFlowId
(),
nextNodeId
);
}
catch
(
Exception
e
)
{
log
.
error
(
"[batchSubmitAllSubFlows] 子单流转失败,subFlowId:{}"
,
subFlow
.
getSubFlowId
(),
e
);
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
String
.
format
(
"子单[%s]流转失败:%s"
,
subFlow
.
getSubFlowId
(),
e
.
getMessage
()));
}
}
}
/**
* 根据变更行动工单ID查询详情
* 根据变更行动工单ID查询详情
* 说明:展示内容和主单的detail一样,但行动项只展示该变更行动工单下绑定的行动项
* 说明:展示内容和主单的detail一样,但行动项只展示该变更行动工单下绑定的行动项
*
*
...
...
yanxuan-qc-change-system-dal/src/main/java/com/netease/mail/yanxuan/change/dal/entity/ChangeSubFlowRecord.java
View file @
479f9a08
...
@@ -79,6 +79,11 @@ public class ChangeSubFlowRecord {
...
@@ -79,6 +79,11 @@ public class ChangeSubFlowRecord {
private
String
changeCommander
;
private
String
changeCommander
;
/**
/**
* 变更方案是否审批通过(仅在审批变更方案节点使用)
*/
private
Boolean
changePlanApproved
;
/**
* 拒绝原因(审批不通过时填写)
* 拒绝原因(审批不通过时填写)
*/
*/
private
String
rejectReason
;
private
String
rejectReason
;
...
...
yanxuan-qc-change-system-dal/src/main/resources/mybatis/mapper/ChangeSubFlowRecordMapper.xml
View file @
479f9a08
...
@@ -11,13 +11,14 @@
...
@@ -11,13 +11,14 @@
<result
column=
"change_exec_user_email"
jdbcType=
"VARCHAR"
property=
"changeExecUserEmail"
/>
<result
column=
"change_exec_user_email"
jdbcType=
"VARCHAR"
property=
"changeExecUserEmail"
/>
<result
column=
"change_exec_department"
jdbcType=
"VARCHAR"
property=
"changeExecDepartment"
/>
<result
column=
"change_exec_department"
jdbcType=
"VARCHAR"
property=
"changeExecDepartment"
/>
<result
column=
"change_commander"
jdbcType=
"VARCHAR"
property=
"changeCommander"
/>
<result
column=
"change_commander"
jdbcType=
"VARCHAR"
property=
"changeCommander"
/>
<result
column=
"change_plan_approved"
jdbcType=
"TINYINT"
property=
"changePlanApproved"
/>
<result
column=
"reject_reason"
jdbcType=
"VARCHAR"
property=
"rejectReason"
/>
<result
column=
"reject_reason"
jdbcType=
"VARCHAR"
property=
"rejectReason"
/>
<result
column=
"create_time"
jdbcType=
"BIGINT"
property=
"createTime"
/>
<result
column=
"create_time"
jdbcType=
"BIGINT"
property=
"createTime"
/>
<result
column=
"update_time"
jdbcType=
"BIGINT"
property=
"updateTime"
/>
<result
column=
"update_time"
jdbcType=
"BIGINT"
property=
"updateTime"
/>
</resultMap>
</resultMap>
<sql
id=
"Base_Column_List"
>
<sql
id=
"Base_Column_List"
>
id, change_record_id, sub_flow_id, sub_flow_node, status, approver, change_exec_user_email, change_exec_department, change_commander, reject_reason, create_time, update_time
id, change_record_id, sub_flow_id, sub_flow_node, status, approver, change_exec_user_email, change_exec_department, change_commander,
change_plan_approved,
reject_reason, create_time, update_time
</sql>
</sql>
<select
id=
"selectByCondition"
resultMap=
"BaseResultMap"
parameterType=
"com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeSubFlowListQueryReq"
>
<select
id=
"selectByCondition"
resultMap=
"BaseResultMap"
parameterType=
"com.netease.mail.yanxuan.change.dal.meta.model.req.ChangeSubFlowListQueryReq"
>
...
...
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