@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.bpm.service.task;
import cn.hutool.core.collection.CollUtil ;
import cn.hutool.core.util.ArrayUtil ;
import cn.hutool.core.util.IdUtil ;
import cn.hutool.core.util.ObjectUtil ;
import cn.hutool.core.util.StrUtil ;
import cn.iocoder.yudao.framework.common.enums.SymbolConstant ;
import cn.iocoder.yudao.framework.common.pojo.PageResult ;
import cn.iocoder.yudao.framework.common.util.date.DateUtils ;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils ;
@ -15,7 +15,10 @@ import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*;
import cn.iocoder.yudao.module.bpm.convert.task.BpmTaskConvert ;
import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO ;
import cn.iocoder.yudao.module.bpm.dal.mysql.task.BpmTaskExtMapper ;
import cn.iocoder.yudao.module.bpm.enums.task.* ;
import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum ;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum ;
import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum ;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskAddSignTypeEnum ;
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService ;
import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService ;
import cn.iocoder.yudao.module.system.api.dept.DeptApi ;
@ -222,8 +225,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
// 情况二:后加签的任务
if ( BpmTaskAddSignTypeEnum . AFTER . getType ( ) . equals ( task . getScopeType ( ) ) ) {
// 后加签处理
// TODO @海洋:这个是不是 approveAfterSignTask
handleAfterSignTask ( task , reqVO ) ;
approveAfterSignTask( task , reqVO ) ;
return ;
}
@ -240,13 +242,13 @@ public class BpmTaskServiceImpl implements BpmTaskService {
/**
* 审批通过存在“后加签”的任务。
*
* <p>
* 注意: 该任务不能马上完成, 需要一个中间状态( ADD_SIGN_AFTER) , 并激活剩余所有子任务( PROCESS) 为可审批处理
*
* @param task 当前任务
* @param task 当前任务
* @param reqVO 前端请求参数
*/
private void handl eAfterSignTask( Task task , BpmTaskApproveReqVO reqVO ) {
private void approv eAfterSignTask( Task task , BpmTaskApproveReqVO reqVO ) {
// 1. 有向后加签,则该任务状态临时设置为 ADD_SIGN_AFTER 状态
taskExtMapper . updateByTaskId (
new BpmTaskExtDO ( ) . setTaskId ( task . getId ( ) ) . setResult ( BpmProcessInstanceResultEnum . ADD_SIGN_AFTER . getResult ( ) )
@ -257,7 +259,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
for ( String childrenTaskId : childrenTaskIdList ) {
taskService . resolveTask ( childrenTaskId ) ;
}
// 更新任务扩展表中子任务为进行中
// 2.1 更新任务扩展表中子任务为进行中
taskExtMapper . updateBatchByTaskIdList ( childrenTaskIdList ,
new BpmTaskExtDO ( ) . setResult ( BpmProcessInstanceResultEnum . PROCESS . getResult ( ) ) ) ;
}
@ -269,106 +271,108 @@ public class BpmTaskServiceImpl implements BpmTaskService {
*/
private void handleParentTask ( Task task ) {
String parentTaskId = task . getParentTaskId ( ) ;
// TODO @ 海: if return 原则
if ( StrUtil . isBlank ( parentTaskId ) ) {
return ;
}
if ( StrUtil . isNotBlank ( parentTaskId ) ) {
// 1. 判断当前任务的父任务是否还有子任务
l ong sub TaskCount = getSub TaskCount ( parentTaskId ) ;
// TODO @ 海: if >= 0 return; 这样括号又可以少一层;
if ( subTaskCount = = 0 ) {
// 2. 获取父任务
Task parentTask = validateTaskExist ( parentTaskId ) ;
// 3. 情况一:处理向前加签
String scopeType = parentTask . getScopeType ( ) ;
if ( BpmTaskAddSignTypeEnum . BEFORE . getType ( ) . equals ( scopeType ) ) {
// 3.1 如果是向前加签的任务,则调用 resolveTask 指派父任务,将 owner 重新赋值给父任务的 assignee
taskService . resolveTask ( parentTaskId ) ;
// 3.2 更新任务拓展表为处理中
taskExtMapper . updateByTaskId (
new BpmTaskExtDO ( ) . setTaskId ( parentTask . getId ( ) ) . setResult ( BpmProcessInstanceResultEnum . PROCESS . getResult ( ) ) ) ;
} else if ( BpmTaskAddSignTypeEnum . AFTER . getType ( ) . equals ( scopeType ) ) {
// 3. 情况二:处理向后加签
handleAfterSign ( parentTask ) ;
}
// 4. 子任务已处理完成,清空 scopeType 字段,修改 parentTask 信息,方便后续可以继续向前后向后加签
// 再查询一次的原因是避免报错: Task was updated by another transaction concurrently
// 因为前面处理后可能会导致 parentTask rev 字段被修改,需要重新获取最新的
parentTask = getTask ( parentTaskId ) ;
// TODO @ 海: if return 原则;
if ( parentTask ! = null ) {
// 为空的情况是:已经通过 handleAfterSign 方法将任务完成了,所以 ru_task 表会查不到数据
clearTaskScopeTypeAndSave ( parentTask ) ;
}
L ong children TaskCount = getChildren TaskCount ( parentTaskId ) ;
if ( childrenTaskCount > 0 ) {
return ;
}
// 2. 获取父任务
Task parentTask = validateTaskExist ( parentTaskId ) ;
// 3. 情况一:处理向前加签
String scopeType = parentTask . getScopeType ( ) ;
if ( BpmTaskAddSignTypeEnum . BEFORE . getType ( ) . equals ( scopeType ) ) {
// 3.1 如果是向前加签的任务,则调用 resolveTask 指派父任务,将 owner 重新赋值给父任务的 assignee
taskService . resolveTask ( parentTaskId ) ;
// 3.2 更新任务拓展表为处理中
taskExtMapper . updateByTaskId (
new BpmTaskExtDO ( ) . setTaskId ( parentTask . getId ( ) ) . setResult ( BpmProcessInstanceResultEnum . PROCESS . getResult ( ) ) ) ;
} else if ( BpmTaskAddSignTypeEnum . AFTER . getType ( ) . equals ( scopeType ) ) {
// 3. 情况二:处理向后加签
handleAfterSign ( parentTask ) ;
}
// 4. 子任务已处理完成,清空 scopeType 字段,修改 parentTask 信息,方便后续可以继续向前后向后加签
// 再查询一次的原因是避免报错: Task was updated by another transaction concurrently
// 因为前面处理后可能会导致 parentTask rev 字段被修改,需要重新获取最新的
parentTask = getTask ( parentTaskId ) ;
if ( parentTask = = null ) {
// 为空的情况是:已经通过 handleAfterSign 方法将任务完成了,所以 ru_task 表会查不到数据
return ;
}
clearTaskScopeTypeAndSave ( parentTask ) ;
}
}
// TODO @海:这个方法的 4.1 从 1 开始计数哈;另外;看看能不能用 if return 进一步简化代码的层级;
/**
* 处理后加签任务
*
* @param parentTask 当前审批任务的父任务
* @param parentTask 当前审批任务的父任务
*/
private void handleAfterSign ( Task parentTask ) {
// TODO @海:这个方法在注释下。感觉整体是,先完成自己;然后递归处理父节点;但是完成机子被放到了 5.1,就感觉上有点割裂;
String parentTaskId = parentTask . getId ( ) ;
//4. 1 更新 parentTask 的任务拓展表为通过
//1. 更新 parentTask 的任务拓展表为通过,并调用 complete 完成自己
BpmTaskExtDO currentTaskExt = taskExtMapper . selectByTaskId ( parentTask . getId ( ) ) ;
BpmTaskExtDO currentTaskUpdateEntity = new BpmTaskExtDO ( ) . setTaskId ( parentTask . getId ( ) )
. setResult ( BpmProcessInstanceResultEnum . APPROVE . getResult ( ) ) ;
if ( currentTaskExt . getEndTime ( ) = = null ) {
// 有这个判断是因为
// 4.2 以前没设置过结束时间,才去设置
// 1.1 有这个判断是因为,以前没设置过结束时间,才去设置
currentTaskUpdateEntity . setEndTime ( LocalDateTime . now ( ) ) ;
}
// 1.2 完成自己
taskExtMapper . updateByTaskId ( currentTaskUpdateEntity ) ;
// 5. 继续往上处理,父任务继续往上查询
// 5.1 先完成自己
taskService . complete ( parentTaskId ) ;
// 5.2 如果有父级,递归查询上级任务是否都已经完成
// 2. 如果有父级,递归查询上级任务是否都已经完成
if ( StrUtil . isEmpty ( parentTask . getParentTaskId ( ) ) ) {
return ;
}
// TODO @海:这块待讨论,脑子略乱;感觉 handleAfterSign 的后半段,和 handleParentTask 有点重叠???
if ( StrUtil . isNotEmpty ( parentTask . getParentTaskId ( ) ) ) {
// 判断整条链路的任务是否完成
// 例如从 A 任务加签了一个 B 任务, B 任务又加签了一个 C 任务, C 任务加签了 D 任务
// 此时, D 任务完成,要一直往上找到祖先任务 A调用 complete 方法完成 A 任务
boolean allChild renTaskFinish = true ;
while ( StrUtil . isNotBlank ( parentTask . getParentTaskId ( ) ) ) {
parentTask = validateTaskExist ( parentTask . getParentTask Id ( ) ) ;
BpmTaskExtDO bpmTaskExtDO = taskExtMapper . selectByTaskId ( parentTask . getId ( ) ) ;
if ( bpmTaskExtDO = = null ) {
break ;
}
boolean currentTaskFinish = BpmProcessInstanceResultEnum . isEndResult ( bpmTaskExtDO . getResult ( ) ) ;
// 5.3 如果 allChildrenTaskFinish 已经被赋值为 false ,则不会再赋值为 true, 因为整个链路没有完成
if ( allChildrenTaskFinish ) {
allChildrenTaskFinish = currentTaskFinish ;
}
if ( ! currentTaskFinish ) {
// 6 处理非完成状态的任务
// 6.1 判断当前任务的父任务是否还有子任务
Long subTaskCount = getSubTaskCount ( bpmTaskExtDO . getTaskId ( ) ) ;
if ( subTaskCount = = 0 ) {
// 6.2 没有子任务,判断当前任务状态是否为 ADD_SIGN_BEFORE 待前加签任务完成
if ( BpmProcessInstanceResultEnum . ADD_SIGN_BEFORE . getResult ( ) . equals ( bpmTaskExtDO . getResult ( ) ) ) {
// 6.3 需要修改该任务状态为处理中
taskService . resolveTask ( bpmTaskExtDO . getTaskId ( ) ) ;
bpmTaskExtDO . setResult ( BpmProcessInstanceResultEnum . PROCESS . getResult ( ) ) ;
taskExtMapper . updateByTaskId ( bpmTaskExtDO ) ;
}
// 6.4 清空 scopeType 字段,用于任务没有子任务时使用该方法,方便任务可以再次被不同的方式加签
parentTask = getTask ( bpmTaskExtDO . getTaskId ( ) ) ;
if ( parentTask ! = null ) {
clearTaskScopeTypeAndSave ( parentTask ) ;
}
}
}
// 2.1 判断整条链路的任务是否完成
// 例如从 A 任务加签了一个 B 任务, B 任务又加签了一个 C 任务, C 任务加签了 D 任务
// 此时, D 任务完成,要一直往上找到祖先任务 A调用 complete 方法完成 A 任务
boolean allChildrenTaskFinish = true ;
while ( StrUtil . isNotBlank ( pa rent Task. getParentTaskId ( ) ) ) {
parentTask = validateTaskExist ( parentTask . getParentTaskId ( ) ) ;
BpmTaskExtDO bpmTaskExtDO = taskExtMapper . selectByTaskId ( parentTask . getId ( ) ) ;
if ( bpmTaskExtDO = = null ) {
break ;
}
boolean currentTaskFinish = BpmProcessInstanceResultEnum . isEndResult ( bpmTaskExtDO . getResult ( ) ) ;
// 2.2 如果 allChildrenTaskFinish 已经被赋值为 false ,则不会再赋值为 true, 因为整个链路没有完成
if ( allChildrenTaskFinish ) {
// 7. 完成最后的顶级祖先任务
taskService . complete ( parentTask . getId ( ) ) ;
allChildrenTaskFinish = currentTaskFinish ;
}
// 2.3 任务已完成则不处理
if ( currentTaskFinish ) {
continue ;
}
// 3 处理非完成状态的任务
// 3.1 判断当前任务的父任务是否还有子任务
Long childrenTaskCount = getChildrenTaskCount ( bpmTaskExtDO . getTaskId ( ) ) ;
if ( childrenTaskCount > 0 ) {
continue ;
}
// 3.2 没有子任务,判断当前任务状态是否为 ADD_SIGN_BEFORE 待前加签任务完成
if ( BpmProcessInstanceResultEnum . ADD_SIGN_BEFORE . getResult ( ) . equals ( bpmTaskExtDO . getResult ( ) ) ) {
// 3.3 需要修改该任务状态为处理中
taskService . resolveTask ( bpmTaskExtDO . getTaskId ( ) ) ;
bpmTaskExtDO . setResult ( BpmProcessInstanceResultEnum . PROCESS . getResult ( ) ) ;
taskExtMapper . updateByTaskId ( bpmTaskExtDO ) ;
}
// 3.4 清空 scopeType 字段,用于任务没有子任务时使用该方法,方便任务可以再次被不同的方式加签
parentTask = validateTaskExist ( bpmTaskExtDO . getTaskId ( ) ) ;
clearTaskScopeTypeAndSave ( parentTask ) ;
}
// 4. 完成最后的顶级祖先任务
if ( allChildrenTaskFinish ) {
taskService . complete ( parentTask . getId ( ) ) ;
}
}
@ -383,14 +387,14 @@ public class BpmTaskServiceImpl implements BpmTaskService {
taskService . saveTask ( task ) ;
}
// TODO @海: Sub 还有 Child 感觉整体用词不是很统一;是不是要统一下;然后 Sub 还可以指的减签;看看是不是名词确实得一致哈;
/**
* 获取子任务个数
*
* @param parentTaskId 父任务 ID
* @return 剩余子任务个数
*/
private Long getSub TaskCount ( String parentTaskId ) {
private Long getChildren TaskCount ( String parentTaskId ) {
String tableName = managementService . getTableName ( TaskEntity . class ) ;
String sql = " SELECT COUNT(1) from " + tableName + " WHERE PARENT_TASK_ID_=#{parentTaskId} " ;
return taskService . createNativeTaskQuery ( ) . sql ( sql ) . parameter ( " parentTaskId " , parentTaskId ) . count ( ) ;
@ -410,7 +414,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
String comment = StrUtil . format ( " [{}]完成委派任务,任务重新回到[{}]手中,审批意见为:{} " , currentUser . getNickname ( ) ,
sourceApproveUser . getNickname ( ) , reqVO . getReason ( ) ) ;
taskService . addComment ( reqVO . getId ( ) , task . getProcessInstanceId ( ) ,
BpmCommentTypeEnum . DELEGATE . getResult ( ) . toString ( ) , comment ) ;
BpmCommentTypeEnum . DELEGATE . getType ( ) . toString ( ) , comment ) ;
// 2.1 调用 resolveTask 完成任务。
// 底层调用 TaskHelper.changeTaskAssignee(task, task.getOwner()):将 owner 设置为 assignee
@ -528,7 +532,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
TransactionSynchronizationManager . registerSynchronization ( new TransactionSynchronization ( ) {
@Override
public void afterCommit ( ) {
if ( StrUtil . isNotEmpty ( task . getAssignee ( ) ) ) {
if ( StrUtil . isNotEmpty ( task . getAssignee ( ) ) ) {
ProcessInstance processInstance =
processInstanceService . getProcessInstance ( task . getProcessInstanceId ( ) ) ;
AdminUserRespDTO startUser = adminUserApi . getUser ( Long . valueOf ( processInstance . getStartUserId ( ) ) ) ;
@ -539,8 +543,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
} ) ;
}
private Task validateTaskExist ( String id ) {
Task task = taskService . createTaskQuery ( ) . taskId ( id ) . singleResult ( ) ;
private Task validateTaskExist ( String id ) {
Task task = getTask ( id ) ;
if ( task = = null ) {
throw exception ( TASK_NOT_EXISTS ) ;
}
@ -646,7 +650,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
return ;
}
taskService . addComment ( task . getId ( ) , currentTask . getProcessInstanceId ( ) ,
BpmCommentTypeEnum . BACK . getResult ( ) . toString ( ) , reqVO . getReason ( ) ) ;
BpmCommentTypeEnum . BACK . getType ( ) . toString ( ) , reqVO . getReason ( ) ) ;
} ) ;
// 3. 执行驳回
@ -659,7 +663,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
@Override
@Transactional ( rollbackFor = Exception . class )
public void delegateTask ( BpmTaskDelegateReqVO reqVO , Long userId ) {
public void delegateTask ( Long userId , BpmTaskDelegateReqVO reqVO ) {
// 1.1 校验任务
Task task = validateTaskCanDelegate ( userId , reqVO ) ;
// 1.2 校验目标用户存在
@ -674,7 +678,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
delegateUser . getNickname ( ) , reqVO . getReason ( ) ) ;
String taskId = reqVO . getId ( ) ;
taskService . addComment ( taskId , task . getProcessInstanceId ( ) ,
BpmCommentTypeEnum . DELEGATE . getResult ( ) . toString ( ) , comment ) ;
BpmCommentTypeEnum . DELEGATE . getType ( ) . toString ( ) , comment ) ;
// 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee)
taskService . setOwner ( taskId , task . getAssignee ( ) ) ;
@ -705,23 +709,18 @@ public class BpmTaskServiceImpl implements BpmTaskService {
@Override
@Transactional ( rollbackFor = Exception . class )
public void addSign ( BpmTaskAddSignReqVO reqVO , Long userId ) {
// TODO @海:// 后面要有个空格;中英文之间,也要有空格;例如说:// 1. 获取和校验任务
//1.获取和校验任务
public void addSignTask ( Long userId , BpmTaskAddSignReqVO reqVO ) {
// 1. 获取和校验任务
TaskEntityImpl taskEntity = validateAddSign ( userId , reqVO ) ;
// TODO @海:每个变量,以及相关逻辑,一定要和自己的逻辑块呆在一起。例如说这里的 currentUser 获取,应该在 4. 那块
AdminUserRespDTO currentUser = adminUserApi . getUser ( userId ) ;
List < AdminUserRespDTO > userList = adminUserApi . getUserList ( reqVO . getUserIdList ( ) ) ;
if ( CollUtil . isEmpty ( userList ) ) {
throw exception ( TASK_ADD_SIGN_USER_NOT_EXIST ) ;
}
// TODO @海:大的逻辑块之间,最好有一个空格。这样的目的,是避免逻辑堆砌在一起,方便流量;
// 2.处理当前任务
// 2.1 开启计数功能 // TODO @海:这个目的可以写下;
// 2. 处理当前任务
// 2.1 开启计数功能,主要用于为了让表 ACT_RU_TASK 中的 SUB_TASK_COUNT_ 字段记录下总共有多少子任务,后续可能有用
taskEntity . setCountEnabled ( true ) ;
// TODO @海:可以直接 if, 不搞一个变量哈
boolean addSignToBefore = reqVO . getType ( ) . equals ( BpmTaskAddSignTypeEnum . BEFORE . getType ( ) ) ;
if ( addSignToBefore ) {
if ( reqVO . getType ( ) . equals ( BpmTaskAddSignTypeEnum . BEFORE . getType ( ) ) ) {
// 2.2 向前加签,设置 owner, 置空 assign。等子任务都完成后, 再调用 resolveTask 重新将 owner 设置为 assign
// 原因是:不能和向前加签的子任务一起审批,需要等前面的子任务都完成才能审批
taskEntity . setOwner ( taskEntity . getAssignee ( ) ) ;
@ -738,20 +737,20 @@ public class BpmTaskServiceImpl implements BpmTaskService {
taskService . saveTask ( taskEntity ) ;
// 3. 创建加签任务
createSignSub Tasks ( convertList ( reqVO . getUserIdList ( ) , String : : valueOf ) , taskEntity ) ;
createAdd SignChildren Tasks ( convertList ( reqVO . getUserIdList ( ) , String : : valueOf ) , taskEntity ) ;
// 4. 记录加签 comment, 拼接结果为: [当前用户]向前加签/向后加签给了[多个用户], 理由为: reason
// TODO @海: BpmCommentTypeEnum 可以加一个 comment 字段,作为评论模版,统一管理;
String comment = StrUtil . format ( " [{}]{}给了[{}],理由为:{} " , currentUser . getNickname ( ) , BpmTaskAddSignTypeEnum . formatDesc ( reqVO . getType ( ) ) ,
String . join ( SymbolConstant . D , convertList ( userList , AdminUserRespDTO : : getNickname ) ) , reqVO . getReason ( ) ) ;
AdminUserRespDTO currentUser = adminUserApi . getUser ( userId ) ;
String comment = StrUtil . format ( BpmCommentTypeEnum . ADD_SIGN . getTemplateComment ( ) , currentUser . getNickname ( ) , BpmTaskAddSignTypeEnum . formatDesc ( reqVO . getType ( ) ) ,
String . join ( " , " , convertList ( userList , AdminUserRespDTO : : getNickname ) ) , reqVO . getReason ( ) ) ;
taskService . addComment ( reqVO . getId ( ) , taskEntity . getProcessInstanceId ( ) ,
BpmCommentTypeEnum . ADD_SIGN . getResult ( ) . toString ( ) , comment ) ;
BpmCommentTypeEnum . ADD_SIGN . getType ( ) . toString ( ) , comment ) ;
}
/**
* 校验任务的加签是否一致
*
* <p>
* 1. 如果存在“向前加签”的任务,则不能“向后加签”
* 2. 如果存在“向后加签”的任务,则不能“向前加签”
*
@ -763,25 +762,20 @@ public class BpmTaskServiceImpl implements BpmTaskService {
TaskEntityImpl taskEntity = ( TaskEntityImpl ) validateTask ( userId , reqVO . getId ( ) ) ;
// 向前加签和向后加签不能同时存在
if ( StrUtil . isNotBlank ( taskEntity . getScopeType ( ) )
& & ! BpmTaskAddSignTypeEnum . AFTER_CHILDREN_TASK . getDesc ( ) . equals ( taskEntity . getScopeType ( ) ) ) {
// TODO @海:下面这个判断,是不是可以写上面这个判断后面?
// TODO @海:一个小技巧,如果写不等于的时候,一般可以用 ObjectUtil.notEquals, 这样少一层取反, 理解起来简单点;
if ( ! taskEntity . getScopeType ( ) . equals ( reqVO . getType ( ) ) ) {
throw exception ( TASK_ADD_SIGN_TYPE_ERROR ,
BpmTaskAddSignTypeEnum . formatDesc ( taskEntity . getScopeType ( ) ) , BpmTaskAddSignTypeEnum . formatDesc ( reqVO . getType ( ) ) ) ;
}
& & ObjectUtil . notEqual ( BpmTaskAddSignTypeEnum . AFTER_CHILDREN_TASK . getType ( ) , taskEntity . getScopeType ( ) )
& & ObjectUtil . notEqual ( taskEntity . getScopeType ( ) , reqVO . getType ( ) ) ) {
throw exception ( TASK_ADD_SIGN_TYPE_ERROR ,
BpmTaskAddSignTypeEnum . formatDesc ( taskEntity . getScopeType ( ) ) , BpmTaskAddSignTypeEnum . formatDesc ( reqVO . getType ( ) ) ) ;
}
// 同一个 key 的任务,审批人不重复
List < Task > taskList = taskService . createTaskQuery ( ) . processInstanceId ( taskEntity . getProcessInstanceId ( ) )
. taskDefinitionKey ( taskEntity . getTaskDefinitionKey ( ) ) . list ( ) ;
// TODO @海:这里是不是 Task::getAssignee 解析成 List<Long> 下面会更简洁一点?
List < String > currentAssigneeList = convertList ( taskList , Task : : getAssignee ) ;
// TODO @海: frontAssigneeList 改成 addAssigneeList, 新增的; 避免和 front 前端这样界面耦合的名词哈;
List < String > frontAssigneeList = convertList ( reqVO . getUserIdList ( ) , String : : valueOf ) ;
currentAssigneeList . retainAll ( frontAssigneeList ) ;
List < Long > currentAssigneeList = convertList ( taskList , task - > NumberUtils . parseLong ( task . getAssignee ( ) ) ) ;
// 保留交集在 currentAssigneeList 中
currentAssigneeList . retainAll ( reqVO . getUserIdList ( ) ) ;
if ( CollUtil . isNotEmpty ( currentAssigneeList ) ) {
List < AdminUserRespDTO > userList = adminUserApi . getUserList ( convertList ( currentAssigneeList, NumberUtils : : parseLong ) );
throw exception ( TASK_ADD_SIGN_USER_REPEAT , String . join ( SymbolConstant . D , convertList ( userList , AdminUserRespDTO : : getNickname ) ) ) ;
List < AdminUserRespDTO > userList = adminUserApi . getUserList ( currentAssigneeList ) ;
throw exception ( TASK_ADD_SIGN_USER_REPEAT , String . join ( " , " , convertList ( userList , AdminUserRespDTO : : getNickname ) ) ) ;
}
return taskEntity ;
}
@ -792,19 +786,19 @@ public class BpmTaskServiceImpl implements BpmTaskService {
* @param addSingUserIdList 被加签的用户 ID
* @param taskEntity 被加签的任务
*/
private void createSignSub Tasks ( List < String > addSingUserIdList , TaskEntityImpl taskEntity ) {
// TODO @海:可以 if return; 这样括号层级少一点; 下面的 if (StrUtil.isNotBlank(addSignId)) { 也是类似;
if ( CollUtil . isNotEmpty ( addSingUserIdList ) ) {
// 创建加签人的新任务,全部基于 taskEntity 为父任务来创建
addSingUserIdList . forEach ( addSignId - > {
if ( StrUtil . isNotBlank ( addSignId ) ) {
createSubTask ( taskEntity , addSignId ) ;
}
} ) ;
private void createAdd SignChildren Tasks ( List < String > addSingUserIdList , TaskEntityImpl taskEntity ) {
if ( CollUtil . isEmpty ( addSingUserIdList ) ) {
return ;
}
// 创建加签人的新任务,全部基于 taskEntity 为父任务来创建
for ( String addSignId : addSingUserIdList ) {
if ( StrUtil . isBlank ( addSignId ) ) {
continue ;
}
createChildrenTask ( taskEntity , addSignId ) ;
}
}
// TODO @海:这个是不是命名上,要和 createSignSubTasks 保持一致?
/**
* 创建子任务
*
@ -812,10 +806,10 @@ public class BpmTaskServiceImpl implements BpmTaskService {
* @param assignee 子任务的执行人
* @return
*/
private void createSub Task ( TaskEntityImpl parentTask , String assignee ) {
private void createChildren Task ( TaskEntityImpl parentTask , String assignee ) {
// 1. 生成子任务
TaskEntityImpl task = ( TaskEntityImpl ) taskService . newTask ( IdUtil . fastSimpleUUID ( ) ) ;
task = BpmTaskConvert . INSTANCE . convert ( task , parentTask ) ;
task = BpmTaskConvert . INSTANCE . convert ( task , parentTask ) ;
if ( BpmTaskAddSignTypeEnum . BEFORE . getType ( ) . equals ( parentTask . getScopeType ( ) ) ) {
// 2.1 前加签,才设置审批人,否则设置 owner
task . setAssignee ( assignee ) ;
@ -831,28 +825,28 @@ public class BpmTaskServiceImpl implements BpmTaskService {
@Override
@Transactional ( rollbackFor = Exception . class )
public void subSign ( BpmTaskSubSignReqVO reqVO , Long userId ) {
public void subSignTask ( Long userId , BpmTaskSubSignReqVO reqVO ) {
Task task = validateSubSign ( reqVO . getId ( ) ) ;
AdminUserRespDTO user = adminUserApi . getUser ( userId ) ;
AdminUserRespDTO cancelUser = null ;
if ( StrUtil . isNotBlank ( task . getAssignee ( ) ) ) {
if ( StrUtil . isNotBlank ( task . getAssignee ( ) ) ) {
cancelUser = adminUserApi . getUser ( NumberUtils . parseLong ( task . getAssignee ( ) ) ) ;
}
if ( cancelUser = = null & & StrUtil . isNotBlank ( task . getOwner ( ) ) ) {
if ( cancelUser = = null & & StrUtil . isNotBlank ( task . getOwner ( ) ) ) {
cancelUser = adminUserApi . getUser ( NumberUtils . parseLong ( task . getOwner ( ) ) ) ;
}
Assert . notNull ( cancelUser , " 任务中没有所有者和审批人,数据错误 " ) ;
Assert . notNull ( cancelUser , " 任务中没有所有者和审批人,数据错误 " ) ;
//1. 获取所有需要删除的任务 ID ,包含当前任务和所有子任务
List < String > allTaskIdList = getAllChildTaskIds ( task . getId ( ) ) ;
//2. 删除任务和所有子任务
taskService . deleteTasks ( allTaskIdList ) ;
//3. 修改扩展表状态为取消
taskExtMapper . updateBatchByTaskIdList ( allTaskIdList , new BpmTaskExtDO ( ) . setResult ( BpmProcessInstanceResultEnum . CANCEL . getResult ( ) )
. setReason ( StrUtil . format ( " 由于{}操作[减签],任务被取消 " , user . getNickname ( ) ) ) ) ;
taskExtMapper . updateBatchByTaskIdList ( allTaskIdList , new BpmTaskExtDO ( ) . setResult ( BpmProcessInstanceResultEnum . CANCEL . getResult ( ) )
. setReason ( StrUtil . format ( " 由于{}操作[减签],任务被取消 " , user . getNickname ( ) ) ) ) ;
//4.记录日志到父任务中 先记录日志是因为,通过 handleParentTask 方法之后,任务可能被完成了,并且不存在了,会报异常,所以先记录
String comment = StrUtil . format ( " {}操作了【减签】,审批人{}的任务被取消 " , user . getNickname ( ) , cancelUser . getNickname ( ) ) ;
taskService . addComment ( task . getParentTaskId ( ) , task . getProcessInstanceId ( ) ,
BpmCommentTypeEnum . SUB_SIGN . getResult ( ) . toString ( ) , comment ) ;
String comment = StrUtil . format ( BpmCommentTypeEnum . SUB_SIGN . getTemplateComment ( ) , user . getNickname ( ) , cancelUser . getNickname ( ) ) ;
taskService . addComment ( task . getParentTaskId ( ) , task . getProcessInstanceId ( ) ,
BpmCommentTypeEnum . SUB_SIGN . getType ( ) . toString ( ) , comment ) ;
//5. 处理当前任务的父任务
this . handleParentTask ( task ) ;
@ -860,13 +854,14 @@ public class BpmTaskServiceImpl implements BpmTaskService {
/**
* 校验任务是否能被减签
*
* @param id 任务ID
* @return 任务信息
*/
private Task validateSubSign ( String id ) {
Task task = validateTaskExist ( id ) ;
//必须有parentId
if ( StrUtil . isEmpty ( task . getParentTaskId ( ) ) ) {
if ( StrUtil . isEmpty ( task . getParentTaskId ( ) ) ) {
throw exception ( TASK_SUB_SIGN_NO_PARENT ) ;
}
return task ;
@ -874,6 +869,7 @@ public class BpmTaskServiceImpl implements BpmTaskService {
/**
* 获取所有要被取消的删除的任务 ID 集合
*
* @param parentTaskId 父级任务ID
* @return 所有任务ID
*/
@ -888,7 +884,8 @@ public class BpmTaskServiceImpl implements BpmTaskService {
/**
* 递归处理子级任务
* @param taskId 当前任务ID
*
* @param taskId 当前任务ID
* @param taskIds 结果
*/
private void recursiveGetChildTaskIds ( String taskId , List < String > taskIds ) {
@ -901,10 +898,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
/**
* 获取指定父级任务的所有子任务 ID 集合
*
* @param parentTaskId 父任务 ID
* @return 所有子任务的 ID 集合
*/
private List < String > getChildrenTaskIdList ( String parentTaskId ) {
private List < String > getChildrenTaskIdList ( String parentTaskId ) {
String tableName = managementService . getTableName ( TaskEntity . class ) ;
String sql = " select ID_ from " + tableName + " where PARENT_TASK_ID_=#{parentTaskId} " ;
List < Task > childrenTaskList = taskService . createNativeTaskQuery ( ) . sql ( sql ) . parameter ( " parentTaskId " , parentTaskId ) . list ( ) ;
@ -912,9 +910,9 @@ public class BpmTaskServiceImpl implements BpmTaskService {
}
@Override
public List < BpmTaskSubSignRespVO > getChildrenTaskList ( String taskId ) {
public List < BpmTaskSubSignRespVO > getChildrenTaskList ( String taskId ) {
List < String > childrenTaskIdList = getChildrenTaskIdList ( taskId ) ;
if ( CollUtil . isEmpty ( childrenTaskIdList ) ) {
if ( CollUtil . isEmpty ( childrenTaskIdList ) ) {
return Collections . emptyList ( ) ;
}
//1. 只查询进行中的任务
@ -926,11 +924,11 @@ public class BpmTaskServiceImpl implements BpmTaskService {
List < Long > userIds = taskList . stream ( )
. flatMap ( control - >
Stream . of ( control . getAssignee ( ) , control . getOwner ( ) )
. filter ( Objects : : nonNull ) )
. filter ( Objects : : nonNull ) )
. distinct ( )
. map ( NumberUtils : : parseLong )
. collect ( Collectors . toList ( ) ) ;
Map < Long , AdminUserRespDTO > userMap = adminUserApi . getUserMap ( userIds ) ;
return BpmTaskConvert . INSTANCE . convertList ( bpmTaskExtDOList , userMap , idTaskMap ) ;
return BpmTaskConvert . INSTANCE . convertList ( bpmTaskExtDOList , userMap , idTaskMap ) ;
}
}