¶Ô±ÈÐÂÎļþ |
| | |
| | | package org.dromara.workflow.service.impl; |
| | | |
| | | import cn.hutool.core.bean.BeanUtil; |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.convert.Convert; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.dromara.common.core.domain.dto.UserDTO; |
| | | import org.dromara.common.core.enums.BusinessStatusEnum; |
| | | import org.dromara.common.core.exception.ServiceException; |
| | | import org.dromara.common.core.utils.StreamUtils; |
| | | import org.dromara.common.core.utils.StringUtils; |
| | | import org.dromara.common.mybatis.core.page.PageQuery; |
| | | import org.dromara.common.mybatis.core.page.TableDataInfo; |
| | | import org.dromara.common.satoken.utils.LoginHelper; |
| | | import org.dromara.warm.flow.core.FlowEngine; |
| | | import org.dromara.warm.flow.core.constant.ExceptionCons; |
| | | import org.dromara.warm.flow.core.dto.FlowParams; |
| | | import org.dromara.warm.flow.core.entity.Definition; |
| | | import org.dromara.warm.flow.core.entity.Instance; |
| | | import org.dromara.warm.flow.core.entity.Task; |
| | | import org.dromara.warm.flow.core.enums.NodeType; |
| | | import org.dromara.warm.flow.core.service.ChartService; |
| | | import org.dromara.warm.flow.core.service.DefService; |
| | | import org.dromara.warm.flow.core.service.InsService; |
| | | import org.dromara.warm.flow.core.service.TaskService; |
| | | import org.dromara.warm.flow.orm.entity.FlowHisTask; |
| | | import org.dromara.warm.flow.orm.entity.FlowInstance; |
| | | import org.dromara.warm.flow.orm.entity.FlowTask; |
| | | import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; |
| | | import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper; |
| | | import org.dromara.workflow.common.ConditionalOnEnable; |
| | | import org.dromara.workflow.common.enums.TaskStatusEnum; |
| | | import org.dromara.workflow.domain.bo.FlowCancelBo; |
| | | import org.dromara.workflow.domain.bo.FlowInstanceBo; |
| | | import org.dromara.workflow.domain.bo.FlowInvalidBo; |
| | | import org.dromara.workflow.domain.vo.FlowHisTaskVo; |
| | | import org.dromara.workflow.domain.vo.FlowInstanceVo; |
| | | import org.dromara.workflow.domain.vo.FlowVariableVo; |
| | | import org.dromara.workflow.handler.FlowProcessEventHandler; |
| | | import org.dromara.workflow.mapper.FlwCategoryMapper; |
| | | import org.dromara.workflow.mapper.FlwInstanceMapper; |
| | | import org.dromara.workflow.service.IFlwInstanceService; |
| | | import org.dromara.workflow.service.IFlwTaskService; |
| | | import org.dromara.workflow.utils.WorkflowUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * æµç¨å®ä¾ æå¡å±å®ç° |
| | | * |
| | | * @author may |
| | | */ |
| | | @ConditionalOnEnable |
| | | @Slf4j |
| | | @RequiredArgsConstructor |
| | | @Service |
| | | public class FlwInstanceServiceImpl implements IFlwInstanceService { |
| | | |
| | | private final InsService insService; |
| | | private final DefService defService; |
| | | private final ChartService chartService; |
| | | private final TaskService taskService; |
| | | private final FlowHisTaskMapper flowHisTaskMapper; |
| | | private final FlowInstanceMapper flowInstanceMapper; |
| | | private final FlowProcessEventHandler flowProcessEventHandler; |
| | | private final IFlwTaskService flwTaskService; |
| | | private final FlwInstanceMapper flwInstanceMapper; |
| | | private final FlwCategoryMapper flwCategoryMapper; |
| | | |
| | | /** |
| | | * å页æ¥è¯¢æ£å¨è¿è¡çæµç¨å®ä¾ |
| | | * |
| | | * @param flowInstanceBo æµç¨å®ä¾ |
| | | * @param pageQuery å页 |
| | | */ |
| | | @Override |
| | | public TableDataInfo<FlowInstanceVo> selectRunningInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) { |
| | | QueryWrapper<FlowInstanceBo> queryWrapper = buildQueryWrapper(flowInstanceBo); |
| | | queryWrapper.in("fi.flow_status", BusinessStatusEnum.runningStatus()); |
| | | Page<FlowInstanceVo> page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | | /** |
| | | * å页æ¥è¯¢å·²ç»æçæµç¨å®ä¾ |
| | | * |
| | | * @param flowInstanceBo æµç¨å®ä¾ |
| | | * @param pageQuery å页 |
| | | */ |
| | | @Override |
| | | public TableDataInfo<FlowInstanceVo> selectFinishInstanceList(FlowInstanceBo flowInstanceBo, PageQuery pageQuery) { |
| | | QueryWrapper<FlowInstanceBo> queryWrapper = buildQueryWrapper(flowInstanceBo); |
| | | queryWrapper.in("fi.flow_status", BusinessStatusEnum.finishStatus()); |
| | | Page<FlowInstanceVo> page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®ä¸å¡idæ¥è¯¢æµç¨å®ä¾è¯¦ç»ä¿¡æ¯ |
| | | * |
| | | * @param businessId ä¸å¡id |
| | | * @return ç»æ |
| | | */ |
| | | @Override |
| | | public FlowInstanceVo queryByBusinessId(Long businessId) { |
| | | FlowInstance instance = this.selectInstByBusinessId(String.valueOf(businessId)); |
| | | FlowInstanceVo instanceVo = BeanUtil.toBean(instance, FlowInstanceVo.class); |
| | | Definition definition = defService.getById(instanceVo.getDefinitionId()); |
| | | instanceVo.setFlowName(definition.getFlowName()); |
| | | instanceVo.setFlowCode(definition.getFlowCode()); |
| | | instanceVo.setVersion(definition.getVersion()); |
| | | instanceVo.setFormCustom(definition.getFormCustom()); |
| | | instanceVo.setFormPath(definition.getFormPath()); |
| | | instanceVo.setCategory(definition.getCategory()); |
| | | return instanceVo; |
| | | } |
| | | |
| | | /** |
| | | * éç¨æ¥è¯¢æ¡ä»¶ |
| | | * |
| | | * @param flowInstanceBo æ¥è¯¢æ¡ä»¶ |
| | | * @return æ¥è¯¢æ¡ä»¶æé æ¹æ³ |
| | | */ |
| | | private QueryWrapper<FlowInstanceBo> buildQueryWrapper(FlowInstanceBo flowInstanceBo) { |
| | | QueryWrapper<FlowInstanceBo> queryWrapper = Wrappers.query(); |
| | | queryWrapper.like(StringUtils.isNotBlank(flowInstanceBo.getNodeName()), "fi.node_name", flowInstanceBo.getNodeName()); |
| | | queryWrapper.like(StringUtils.isNotBlank(flowInstanceBo.getFlowName()), "fd.flow_name", flowInstanceBo.getFlowName()); |
| | | queryWrapper.like(StringUtils.isNotBlank(flowInstanceBo.getFlowCode()), "fd.flow_code", flowInstanceBo.getFlowCode()); |
| | | if (StringUtils.isNotBlank(flowInstanceBo.getCategory())) { |
| | | List<Long> categoryIds = flwCategoryMapper.selectCategoryIdsByParentId(Convert.toLong(flowInstanceBo.getCategory())); |
| | | queryWrapper.in("fd.category", categoryIds); |
| | | } |
| | | queryWrapper.eq(StringUtils.isNotBlank(flowInstanceBo.getBusinessId()), "fi.business_id", flowInstanceBo.getBusinessId()); |
| | | queryWrapper.in(CollUtil.isNotEmpty(flowInstanceBo.getCreateByIds()), "fi.create_by", flowInstanceBo.getCreateByIds()); |
| | | queryWrapper.eq("fi.del_flag", "0"); |
| | | queryWrapper.orderByDesc("fi.create_time"); |
| | | return queryWrapper; |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®ä¸å¡idæ¥è¯¢æµç¨å®ä¾ |
| | | * |
| | | * @param businessId ä¸å¡id |
| | | */ |
| | | @Override |
| | | public FlowInstance selectInstByBusinessId(String businessId) { |
| | | return flowInstanceMapper.selectOne(new LambdaQueryWrapper<FlowInstance>().eq(FlowInstance::getBusinessId, businessId)); |
| | | } |
| | | |
| | | /** |
| | | * æç
§å®ä¾idæ¥è¯¢æµç¨å®ä¾ |
| | | * |
| | | * @param instanceId å®ä¾id |
| | | */ |
| | | @Override |
| | | public FlowInstance selectInstById(Long instanceId) { |
| | | return flowInstanceMapper.selectById(instanceId); |
| | | } |
| | | |
| | | /** |
| | | * æç
§å®ä¾idæ¥è¯¢æµç¨å®ä¾ |
| | | * |
| | | * @param instanceIds å®ä¾id |
| | | */ |
| | | @Override |
| | | public List<FlowInstance> selectInstListByIdList(List<Long> instanceIds) { |
| | | return flowInstanceMapper.selectByIds(instanceIds); |
| | | } |
| | | |
| | | /** |
| | | * æç
§ä¸å¡idå 餿µç¨å®ä¾ |
| | | * |
| | | * @param businessIds ä¸å¡id |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean deleteByBusinessIds(List<Long> businessIds) { |
| | | List<FlowInstance> flowInstances = flowInstanceMapper.selectList(new LambdaQueryWrapper<FlowInstance>().in(FlowInstance::getBusinessId, businessIds)); |
| | | if (CollUtil.isEmpty(flowInstances)) { |
| | | log.warn("æªæ¾å°å¯¹åºçæµç¨å®ä¾ä¿¡æ¯ï¼æ æ³æ§è¡å 餿ä½ã"); |
| | | return false; |
| | | } |
| | | return insService.remove(StreamUtils.toList(flowInstances, FlowInstance::getId)); |
| | | } |
| | | |
| | | /** |
| | | * æç
§å®ä¾idå 餿µç¨å®ä¾ |
| | | * |
| | | * @param instanceIds å®ä¾id |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean deleteByInstanceIds(List<Long> instanceIds) { |
| | | // è·åå®ä¾ä¿¡æ¯ |
| | | List<Instance> instances = insService.getByIds(instanceIds); |
| | | if (CollUtil.isEmpty(instances)) { |
| | | log.warn("æªæ¾å°å¯¹åºçæµç¨å®ä¾ä¿¡æ¯ï¼æ æ³æ§è¡å 餿ä½ã"); |
| | | return false; |
| | | } |
| | | // è·åå®ä¹ä¿¡æ¯ |
| | | Map<Long, Definition> definitionMap = defService.getByIds( |
| | | StreamUtils.toList(instances, Instance::getDefinitionId) |
| | | ).stream().collect(Collectors.toMap(Definition::getId, definition -> definition)); |
| | | |
| | | // éä¸è§¦åå é¤äºä»¶ |
| | | instances.forEach(instance -> { |
| | | Definition definition = definitionMap.get(instance.getDefinitionId()); |
| | | if (ObjectUtil.isNull(definition)) { |
| | | log.warn("å®ä¾ ID: {} 对åºçæµç¨å®ä¹ä¿¡æ¯æªæ¾å°ï¼è·³è¿å é¤äºä»¶è§¦åã", instance.getId()); |
| | | return; |
| | | } |
| | | flowProcessEventHandler.processDeleteHandler(definition.getFlowCode(), instance.getBusinessId()); |
| | | }); |
| | | |
| | | // å é¤å®ä¾ |
| | | return insService.remove(instanceIds); |
| | | } |
| | | |
| | | /** |
| | | * æ¤éæµç¨ |
| | | * |
| | | * @param bo åæ° |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean cancelProcessApply(FlowCancelBo bo) { |
| | | try { |
| | | Instance instance = selectInstByBusinessId(bo.getBusinessId()); |
| | | if (instance == null) { |
| | | throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE); |
| | | } |
| | | Definition definition = defService.getById(instance.getDefinitionId()); |
| | | if (definition == null) { |
| | | throw new ServiceException(ExceptionCons.NOT_FOUNT_DEF); |
| | | } |
| | | String message = bo.getMessage(); |
| | | BusinessStatusEnum.checkCancelStatus(instance.getFlowStatus()); |
| | | String applyNodeCode = WorkflowUtils.applyNodeCode(definition.getId()); |
| | | //æ¤é |
| | | WorkflowUtils.backTask(message, instance.getId(), applyNodeCode, BusinessStatusEnum.CANCEL.getStatus(), BusinessStatusEnum.CANCEL.getStatus()); |
| | | //夿æç¾èç¹æ¯å¦æå¤ä¸ªï¼åªä¿çä¸ä¸ª |
| | | List<Task> currentTaskList = taskService.list(FlowEngine.newTask().setInstanceId(instance.getId())); |
| | | if (CollUtil.isNotEmpty(currentTaskList)) { |
| | | if (currentTaskList.size() > 1) { |
| | | currentTaskList.remove(0); |
| | | WorkflowUtils.deleteRunTask(StreamUtils.toList(currentTaskList, Task::getId)); |
| | | } |
| | | } |
| | | |
| | | } catch (Exception e) { |
| | | log.error("æ¤é失败: {}", e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * è·åå½åç»é人åèµ·çæµç¨å®ä¾ |
| | | * |
| | | * @param instanceBo æµç¨å®ä¾ |
| | | * @param pageQuery å页 |
| | | */ |
| | | @Override |
| | | public TableDataInfo<FlowInstanceVo> selectCurrentInstanceList(FlowInstanceBo instanceBo, PageQuery pageQuery) { |
| | | QueryWrapper<FlowInstanceBo> queryWrapper = buildQueryWrapper(instanceBo); |
| | | queryWrapper.eq("fi.create_by", LoginHelper.getUserIdStr()); |
| | | Page<FlowInstanceVo> page = flwInstanceMapper.selectInstanceList(pageQuery.build(), queryWrapper); |
| | | return TableDataInfo.build(page); |
| | | } |
| | | |
| | | /** |
| | | * è·åæµç¨å¾,æµç¨è®°å½ |
| | | * |
| | | * @param businessId ä¸å¡id |
| | | */ |
| | | @Override |
| | | public Map<String, Object> flowImage(String businessId) { |
| | | FlowInstance flowInstance = this.selectInstByBusinessId(businessId); |
| | | if (ObjectUtil.isNull(flowInstance)) { |
| | | throw new ServiceException(ExceptionCons.NOT_FOUNT_INSTANCE); |
| | | } |
| | | Long instanceId = flowInstance.getId(); |
| | | //è¿è¡ä¸çä»»å¡ |
| | | List<FlowHisTaskVo> list = new ArrayList<>(); |
| | | List<FlowTask> flowTaskList = flwTaskService.selectByInstId(instanceId); |
| | | if (CollUtil.isNotEmpty(flowTaskList)) { |
| | | List<FlowHisTaskVo> flowHisTaskVos = BeanUtil.copyToList(flowTaskList, FlowHisTaskVo.class); |
| | | for (FlowHisTaskVo flowHisTaskVo : flowHisTaskVos) { |
| | | flowHisTaskVo.setFlowStatus(TaskStatusEnum.WAITING.getStatus()); |
| | | flowHisTaskVo.setUpdateTime(null); |
| | | flowHisTaskVo.setRunDuration(null); |
| | | List<UserDTO> allUser = flwTaskService.currentTaskAllUser(flowHisTaskVo.getId()); |
| | | if (CollUtil.isNotEmpty(allUser)) { |
| | | String join = StreamUtils.join(allUser, e -> String.valueOf(e.getUserId())); |
| | | flowHisTaskVo.setApprover(join); |
| | | } |
| | | if (BusinessStatusEnum.isDraftOrCancelOrBack(flowInstance.getFlowStatus())) { |
| | | flowHisTaskVo.setApprover(LoginHelper.getUserIdStr()); |
| | | flowHisTaskVo.setApproveName(LoginHelper.getLoginUser().getNickname()); |
| | | } |
| | | } |
| | | list.addAll(flowHisTaskVos); |
| | | } |
| | | //åå²ä»»å¡ |
| | | LambdaQueryWrapper<FlowHisTask> wrapper = Wrappers.lambdaQuery(); |
| | | wrapper.eq(FlowHisTask::getInstanceId, instanceId); |
| | | wrapper.eq(FlowHisTask::getNodeType, NodeType.BETWEEN.getKey()); |
| | | wrapper.orderByDesc(FlowHisTask::getCreateTime).orderByDesc(FlowHisTask::getUpdateTime); |
| | | List<FlowHisTask> flowHisTasks = flowHisTaskMapper.selectList(wrapper); |
| | | if (CollUtil.isNotEmpty(flowHisTasks)) { |
| | | list.addAll(BeanUtil.copyToList(flowHisTasks, FlowHisTaskVo.class)); |
| | | } |
| | | String flowChart = chartService.chartIns(instanceId); |
| | | return Map.of("list", list, "image", flowChart); |
| | | } |
| | | |
| | | /** |
| | | * æç
§å®ä¾idæ´æ°ç¶æ |
| | | * |
| | | * @param instanceId å®ä¾id |
| | | * @param status ç¶æ |
| | | */ |
| | | @Override |
| | | public void updateStatus(Long instanceId, String status) { |
| | | LambdaUpdateWrapper<FlowInstance> wrapper = new LambdaUpdateWrapper<>(); |
| | | wrapper.set(FlowInstance::getFlowStatus, status); |
| | | wrapper.eq(FlowInstance::getId, instanceId); |
| | | flowInstanceMapper.update(wrapper); |
| | | } |
| | | |
| | | /** |
| | | * è·åæµç¨åé |
| | | * |
| | | * @param instanceId å®ä¾id |
| | | */ |
| | | @Override |
| | | public Map<String, Object> instanceVariable(String instanceId) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | FlowInstance flowInstance = flowInstanceMapper.selectById(instanceId); |
| | | Map<String, Object> variableMap = flowInstance.getVariableMap(); |
| | | List<FlowVariableVo> list = new ArrayList<>(); |
| | | if (CollUtil.isNotEmpty(variableMap)) { |
| | | for (Map.Entry<String, Object> entry : variableMap.entrySet()) { |
| | | FlowVariableVo flowVariableVo = new FlowVariableVo(); |
| | | flowVariableVo.setKey(entry.getKey()); |
| | | flowVariableVo.setValue(entry.getValue().toString()); |
| | | list.add(flowVariableVo); |
| | | } |
| | | } |
| | | map.put("variableList", list); |
| | | map.put("variable", flowInstance.getVariable()); |
| | | return map; |
| | | } |
| | | |
| | | /** |
| | | * 设置æµç¨åé |
| | | * |
| | | * @param instanceId å®ä¾id |
| | | * @param variable æµç¨åé |
| | | */ |
| | | @Override |
| | | public void setVariable(Long instanceId, Map<String, Object> variable) { |
| | | Instance instance = insService.getById(instanceId); |
| | | if (instance != null) { |
| | | taskService.mergeVariable(instance, variable); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æä»»å¡idæ¥è¯¢å®ä¾ |
| | | * |
| | | * @param taskId ä»»å¡id |
| | | */ |
| | | @Override |
| | | public FlowInstance selectByTaskId(Long taskId) { |
| | | Task task = taskService.getById(taskId); |
| | | if (task == null) { |
| | | FlowHisTask flowHisTask = flwTaskService.selectHisTaskById(taskId); |
| | | if (flowHisTask != null) { |
| | | return this.selectInstById(flowHisTask.getInstanceId()); |
| | | } |
| | | } else { |
| | | return this.selectInstById(task.getInstanceId()); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * æä»»å¡idæ¥è¯¢å®ä¾ |
| | | * |
| | | * @param taskIdList ä»»å¡id |
| | | */ |
| | | @Override |
| | | public List<FlowInstance> selectByTaskIdList(List<Long> taskIdList) { |
| | | if (CollUtil.isEmpty(taskIdList)) { |
| | | return Collections.emptyList(); |
| | | } |
| | | Set<Long> instanceIds = new HashSet<>(); |
| | | List<FlowTask> flowTaskList = flwTaskService.selectByIdList(taskIdList); |
| | | for (FlowTask flowTask : flowTaskList) { |
| | | instanceIds.add(flowTask.getInstanceId()); |
| | | } |
| | | List<FlowHisTask> flowHisTaskList = flwTaskService.selectHisTaskByIdList(taskIdList); |
| | | for (FlowHisTask flowHisTask : flowHisTaskList) { |
| | | instanceIds.add(flowHisTask.getInstanceId()); |
| | | } |
| | | if (!instanceIds.isEmpty()) { |
| | | return this.selectInstListByIdList(new ArrayList<>(instanceIds)); |
| | | } |
| | | return Collections.emptyList(); |
| | | } |
| | | |
| | | /** |
| | | * ä½åºæµç¨ |
| | | * |
| | | * @param bo åæ° |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean processInvalid(FlowInvalidBo bo) { |
| | | try { |
| | | Instance instance = insService.getById(bo.getId()); |
| | | if (instance != null) { |
| | | BusinessStatusEnum.checkInvalidStatus(instance.getFlowStatus()); |
| | | } |
| | | List<FlowTask> flowTaskList = flwTaskService.selectByInstId(bo.getId()); |
| | | for (FlowTask flowTask : flowTaskList) { |
| | | FlowParams flowParams = new FlowParams(); |
| | | flowParams.message(bo.getComment()); |
| | | flowParams.flowStatus(BusinessStatusEnum.INVALID.getStatus()) |
| | | .hisStatus(TaskStatusEnum.INVALID.getStatus()); |
| | | flowParams.ignore(true); |
| | | taskService.termination(flowTask.getId(), flowParams); |
| | | } |
| | | return true; |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | throw new ServiceException(e.getMessage()); |
| | | } |
| | | } |
| | | } |