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
5b9a9e28
Commit
5b9a9e28
authored
Dec 11, 2025
by
王志超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 确认变更结果
parent
ffc569e6
Pipeline
#86802
passed with stages
in 1 minute 28 seconds
Changes
3
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
196 additions
and
8 deletions
+196
-8
ChangeFlowBiz.java
...om/netease/mail/yanxuan/change/biz/biz/ChangeFlowBiz.java
+70
-8
BuildAndSendEmail.java
...se/mail/yanxuan/change/biz/service/BuildAndSendEmail.java
+20
-0
BuildAndSendEmailImpl.java
...anxuan/change/biz/service/impl/BuildAndSendEmailImpl.java
+106
-0
No files found.
yanxuan-qc-change-system-biz/src/main/java/com/netease/mail/yanxuan/change/biz/biz/ChangeFlowBiz.java
View file @
5b9a9e28
...
...
@@ -627,9 +627,7 @@ public class ChangeFlowBiz {
log
.
debug
(
"[checkUpdateAndSubmit] flowId:{}, nodeEnum:{}, changeFlowSubmitReq:{}"
,
flowId
,
node
,
JSON
.
toJSONString
(
changeFlowSubmitReq
));
// 工单流传
Map
<
String
,
Object
>
content
=
new
HashMap
<>(
CommonConstants
.
INIT_HASH_MAP_SIZE
);
content
.
put
(
"updateTime"
,
System
.
currentTimeMillis
());
content
.
put
(
CommonConstants
.
FLOW_OPERATION_KEY
,
FlowOperationTypeEnum
.
PASS
.
getValue
());
Map
<
String
,
Object
>
content
=
buildFlowContent
(
FlowOperationTypeEnum
.
PASS
);
switch
(
node
)
{
// 提交变更申请节点,可以修改数据,以新的数据为准
case
NEW_CHANGE_FLOW_START:
...
...
@@ -762,14 +760,80 @@ public class ChangeFlowBiz {
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
"该节点不允许主动提交,需等待所有行动工单执行变更方案后自动流转"
);
case
NEW_CHANGE_FLOW_CONFIRM:
// todo: 确认变更结果节点待实现
return
null
;
// 确认变更结果节点:由变更负责人进行确认,支持「确认」和「取消」
// 校验操作人必须是变更负责人
String
changeCommander
=
changeRecord
.
getChangeCommander
();
if
(!
uid
.
equals
(
changeCommander
))
{
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
NO_AUTH
,
"只有变更负责人可以确认变更结果"
);
}
// 校验审批结果
Boolean
confirmed
=
changeFlowSubmitReq
.
getApproved
();
if
(
confirmed
==
null
)
{
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
BAD_REQUEST
,
"确认结果不能为空"
);
}
// 构建提交内容(不管确认还是取消,都流转到结束节点)
Map
<
String
,
Object
>
confirmContent
=
buildFlowContent
(
confirmed
?
FlowOperationTypeEnum
.
PASS
:
FlowOperationTypeEnum
.
REFUSE
);
String
operationDesc
=
confirmed
?
"确认变更结果"
:
"取消变更结果"
;
// 流转到结束节点(确认和取消都走到结束节点)
String
endNodeId
=
flowService
.
submitFlow
(
flowId
.
toString
(),
flowDataDTO
,
uid
,
ChangeFlowEnum
.
NEW_CHANGE_FLOW
.
getTopoId
(),
JSON
.
toJSONString
(
confirmContent
),
true
,
FlowxOperationEnum
.
SUBMIT
.
getName
(),
operationDesc
,
changeRecord
.
getCreateTime
());
// 更新主工单节点和状态
changeRecord
.
setFlowNode
(
endNodeId
);
changeRecord
.
setUpdateTime
(
DateUtils
.
getCurrentTime
());
if
(
confirmed
)
{
// 点击「确认」:状态更新为"已完结"
changeRecord
.
setState
(
ChangeStatusEnum
.
FINISHED
.
getStatus
());
log
.
info
(
"[NEW_CHANGE_FLOW_CONFIRM] 主工单确认变更结果完成,flowId:{}, endNodeId:{}, state:{}"
,
flowId
,
endNodeId
,
ChangeStatusEnum
.
FINISHED
.
getStatus
());
// todo: 发送完结邮件通知(待业务确认邮件内容)
// buildAndSendEmail.sendConfirmResultFinishEmail(changeRecord);
}
else
{
// 点击「取消」:状态更新为"已取消"
changeRecord
.
setState
(
ChangeStatusEnum
.
CANCELLED
.
getStatus
());
// 如果有取消原因,保存;没有则不保存
if
(
StringUtils
.
isNotBlank
(
changeFlowSubmitReq
.
getCancelReason
()))
{
changeRecord
.
setCancelReason
(
changeFlowSubmitReq
.
getCancelReason
());
}
log
.
info
(
"[NEW_CHANGE_FLOW_CONFIRM] 主工单取消变更结果,flowId:{}, endNodeId:{}, state:{}"
,
flowId
,
endNodeId
,
ChangeStatusEnum
.
CANCELLED
.
getStatus
());
// todo: 发送取消邮件通知(待业务确认邮件内容)
// buildAndSendEmail.sendConfirmResultCancelEmail(changeRecord, changeFlowSubmitReq.getCancelReason());
}
changeFlowService
.
updateRecord
(
changeRecord
);
return
endNodeId
;
default
:
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
NODE_ERROR
,
"不可提交节点:"
+
currentNode
);
}
}
/**
* 构建工单提交内容(包含 updateTime 和 FLOW_OPERATION_KEY)
*
* @param operationType 操作类型(PASS 或 REFUSE),如果为 null 则不设置 FLOW_OPERATION_KEY
* @return 工单提交内容 Map
*/
private
Map
<
String
,
Object
>
buildFlowContent
(
FlowOperationTypeEnum
operationType
)
{
Map
<
String
,
Object
>
content
=
new
HashMap
<>(
CommonConstants
.
INIT_HASH_MAP_SIZE
);
content
.
put
(
"updateTime"
,
System
.
currentTimeMillis
());
if
(
operationType
!=
null
)
{
content
.
put
(
CommonConstants
.
FLOW_OPERATION_KEY
,
operationType
.
getValue
());
}
return
content
;
}
private
ChangeRecord
getFlowInfo
(
Long
flowId
)
{
ChangeRecord
changeRecord
=
changeFlowService
.
getByFlowId
(
flowId
);
if
(
changeRecord
==
null
)
{
...
...
@@ -804,9 +868,7 @@ public class ChangeFlowBiz {
throw
ExceptionFactory
.
createBiz
(
ResponseCode
.
DETAIL_FLOW_ERROR
,
"工单查询错误,不存在"
);
}
// 工单流转
Map
<
String
,
Object
>
content
=
new
HashMap
<>(
CommonConstants
.
INIT_HASH_MAP_SIZE
);
content
.
put
(
"updateTime"
,
System
.
currentTimeMillis
());
content
.
put
(
CommonConstants
.
FLOW_OPERATION_KEY
,
FlowOperationTypeEnum
.
REFUSE
.
getValue
());
Map
<
String
,
Object
>
content
=
buildFlowContent
(
FlowOperationTypeEnum
.
REFUSE
);
String
nextNodeId
=
flowService
.
submitFlow
(
String
.
valueOf
(
flowId
),
flowDataDTO
,
uid
,
ChangeFlowEnum
.
CHANGE_FLOW_SUBMIT
.
getTopoId
(),
JSON
.
toJSONString
(
content
),
false
,
FlowxOperationEnum
.
APPROVE_FAIL
.
getName
(),
"取消工单"
,
changeRecord
.
getCreateTime
());
...
...
yanxuan-qc-change-system-biz/src/main/java/com/netease/mail/yanxuan/change/biz/service/BuildAndSendEmail.java
View file @
5b9a9e28
...
...
@@ -34,4 +34,23 @@ public interface BuildAndSendEmail {
* @param changeExecRecords
*/
void
buildAndSendEmailSubmit
(
ChangeRecord
changeRecord
,
List
<
ChangeExecRecord
>
changeExecRecords
);
/**
* 发送确认变更结果完成邮件通知
* 接收人:变更行动人、变更行动人上一级主管、变更供应商、变更管理QA群组
* todo: 待业务确认邮件模板和内容参数
*
* @param changeRecord 变更记录
*/
void
sendConfirmResultFinishEmail
(
ChangeRecord
changeRecord
);
/**
* 发送确认变更结果取消邮件通知
* 接收人:变更行动人、变更行动人上一级主管、变更供应商、变更管理QA群组
* todo: 待业务确认邮件模板和内容参数
*
* @param changeRecord 变更记录
* @param cancelReason 取消原因
*/
void
sendConfirmResultCancelEmail
(
ChangeRecord
changeRecord
,
String
cancelReason
);
}
\ No newline at end of file
yanxuan-qc-change-system-biz/src/main/java/com/netease/mail/yanxuan/change/biz/service/impl/BuildAndSendEmailImpl.java
View file @
5b9a9e28
...
...
@@ -7,6 +7,7 @@
package
com
.
netease
.
mail
.
yanxuan
.
change
.
biz
.
service
.
impl
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Optional
;
...
...
@@ -214,4 +215,108 @@ public class BuildAndSendEmailImpl implements BuildAndSendEmail {
EmailTemplateEnum
.
YX_QC_CHANGE_EXECUTE
,
param
);
}
}
@Override
@Async
(
"asyncBuild"
)
public
void
sendConfirmResultFinishEmail
(
ChangeRecord
changeRecord
)
{
try
{
// 构建邮件参数(todo: 邮件内容参数待业务确认)
HashMap
<
String
,
Object
>
finishMap
=
new
HashMap
<>();
finishMap
.
put
(
"changeId"
,
changeRecord
.
getFlowId
());
finishMap
.
put
(
"changeSubject"
,
ChangeSubjectEnum
.
getChangeSubjectEnum
(
changeRecord
.
getChangeSubject
()).
getDesc
());
finishMap
.
put
(
"changeContent"
,
changeRecord
.
getChangeContent
());
IusUserInfoRsp
user
=
iusService
.
queryUserInfo
(
changeRecord
.
getChangeCommander
());
finishMap
.
put
(
"changeCommander"
,
user
==
null
?
changeRecord
.
getChangeCommander
()
:
user
.
getName
());
// todo: 其他邮件内容参数待业务补充
String
finishSubjectParam
=
changeRecord
.
getFlowId
().
toString
();
// 收件人:变更负责人、变更行动人
List
<
String
>
receiver
=
new
ArrayList
<>(
Collections
.
singletonList
(
changeRecord
.
getChangeCommander
()));
List
<
ChangeFlowExecVO
>
execRecord
=
changeFlowExecService
.
getChangeFlowExecRecord
(
changeRecord
.
getId
());
List
<
String
>
userEmailList
=
execRecord
.
stream
()
.
map
(
ChangeFlowExecVO:
:
getChangeExecUserEmail
)
.
filter
(
email
->
StringUtils
.
isNotBlank
(
email
))
.
collect
(
Collectors
.
toList
());
receiver
.
addAll
(
userEmailList
);
// 抄送人:变更行动人上一级主管、变更管理QA群组
userEmailList
.
addAll
(
receiver
);
List
<
String
>
ccList
=
departmentLeaderBiz
.
getDepartmentLeaders
(
userEmailList
);
ccList
.
add
(
appConfig
.
getChangeManageQM
());
// 发送邮件(todo: 邮件模板待业务确认)
changeFlowBiz
.
qcSendEmail
(
receiver
,
ccList
,
finishSubjectParam
,
EmailTemplateEnum
.
YX_QC_CHANGE_FINISH
,
finishMap
);
// 如果是供应商变更,发送供应商邮件
if
(
changeRecord
.
getCreateSource
().
equals
(
CreateSourceEnum
.
TONG_ZHOU
.
getType
()))
{
sendSupplierEmail
.
sendSupplierEmail
(
changeRecord
.
getCreateSupplier
(),
finishSubjectParam
,
EmailTemplateEnum
.
YX_QC_CHANGE_FINISH
,
finishMap
);
}
// 如果是其他端发起但是是供应商变更,发送供应商邮件
if
(!
changeRecord
.
getCreateSource
().
equals
(
CreateSourceEnum
.
TONG_ZHOU
.
getType
())
&&
ChangeSubjectEnum
.
SUPPLIER
.
getType
().
equals
(
changeRecord
.
getChangeSubject
()))
{
sendSupplierEmail
.
sendSupplierEmail
(
changeRecord
.
getChangeSupplier
(),
finishSubjectParam
,
EmailTemplateEnum
.
YX_QC_CHANGE_FINISH
,
finishMap
);
}
log
.
info
(
"[sendConfirmResultFinishEmail] 确认变更结果完成邮件已发送,flowId:{}"
,
changeRecord
.
getFlowId
());
}
catch
(
Exception
e
)
{
log
.
error
(
"[sendConfirmResultFinishEmail] 发送确认变更结果完成邮件失败,flowId:{}, error:{}"
,
changeRecord
.
getFlowId
(),
e
.
getMessage
(),
e
);
}
}
@Override
@Async
(
"asyncBuild"
)
public
void
sendConfirmResultCancelEmail
(
ChangeRecord
changeRecord
,
String
cancelReason
)
{
try
{
// 构建邮件参数(todo: 邮件内容参数待业务确认)
HashMap
<
String
,
Object
>
cancelMap
=
new
HashMap
<>();
cancelMap
.
put
(
"changeId"
,
changeRecord
.
getFlowId
());
cancelMap
.
put
(
"changeSubject"
,
ChangeSubjectEnum
.
getChangeSubjectEnum
(
changeRecord
.
getChangeSubject
()).
getDesc
());
cancelMap
.
put
(
"changeContent"
,
changeRecord
.
getChangeContent
());
IusUserInfoRsp
user
=
iusService
.
queryUserInfo
(
changeRecord
.
getChangeCommander
());
cancelMap
.
put
(
"changeCommander"
,
user
==
null
?
changeRecord
.
getChangeCommander
()
:
user
.
getName
());
cancelMap
.
put
(
"cancelReason"
,
cancelReason
);
// todo: 其他邮件内容参数待业务补充
String
cancelSubjectParam
=
changeRecord
.
getFlowId
().
toString
();
// 收件人:变更负责人、变更行动人
List
<
String
>
receiver
=
new
ArrayList
<>(
Collections
.
singletonList
(
changeRecord
.
getChangeCommander
()));
List
<
ChangeFlowExecVO
>
execRecord
=
changeFlowExecService
.
getChangeFlowExecRecord
(
changeRecord
.
getId
());
List
<
String
>
userEmailList
=
execRecord
.
stream
()
.
map
(
ChangeFlowExecVO:
:
getChangeExecUserEmail
)
.
filter
(
email
->
StringUtils
.
isNotBlank
(
email
))
.
collect
(
Collectors
.
toList
());
receiver
.
addAll
(
userEmailList
);
// 抄送人:变更行动人上一级主管、变更管理QA群组
userEmailList
.
addAll
(
receiver
);
List
<
String
>
ccList
=
departmentLeaderBiz
.
getDepartmentLeaders
(
userEmailList
);
ccList
.
add
(
appConfig
.
getChangeManageQM
());
// 发送邮件(todo: 邮件模板待业务确认)
changeFlowBiz
.
qcSendEmail
(
receiver
,
ccList
,
cancelSubjectParam
,
EmailTemplateEnum
.
YX_QC_CHANGE_SUBMIT_CANCEL
,
cancelMap
);
// 如果是供应商变更,发送供应商邮件
if
(
changeRecord
.
getCreateSource
().
equals
(
CreateSourceEnum
.
TONG_ZHOU
.
getType
()))
{
sendSupplierEmail
.
sendSupplierEmail
(
changeRecord
.
getCreateSupplier
(),
cancelSubjectParam
,
EmailTemplateEnum
.
YX_QC_CHANGE_SUBMIT_CANCEL
,
cancelMap
);
}
// 如果是其他端发起但是是供应商变更,发送供应商邮件
if
(!
changeRecord
.
getCreateSource
().
equals
(
CreateSourceEnum
.
TONG_ZHOU
.
getType
())
&&
ChangeSubjectEnum
.
SUPPLIER
.
getType
().
equals
(
changeRecord
.
getChangeSubject
()))
{
sendSupplierEmail
.
sendSupplierEmail
(
changeRecord
.
getChangeSupplier
(),
cancelSubjectParam
,
EmailTemplateEnum
.
YX_QC_CHANGE_SUBMIT_CANCEL
,
cancelMap
);
}
log
.
info
(
"[sendConfirmResultCancelEmail] 确认变更结果取消邮件已发送,flowId:{}, cancelReason:{}"
,
changeRecord
.
getFlowId
(),
cancelReason
);
}
catch
(
Exception
e
)
{
log
.
error
(
"[sendConfirmResultCancelEmail] 发送确认变更结果取消邮件失败,flowId:{}, error:{}"
,
changeRecord
.
getFlowId
(),
e
.
getMessage
(),
e
);
}
}
}
\ No newline at end of file
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