001/*
002 *    Copyright 2024-2025, Warm-Flow (290631660@qq.com).
003 *
004 *    Licensed under the Apache License, Version 2.0 (the "License");
005 *    you may not use this file except in compliance with the License.
006 *    You may obtain a copy of the License at
007 *
008 *       https://www.apache.org/licenses/LICENSE-2.0
009 *
010 *    Unless required by applicable law or agreed to in writing, software
011 *    distributed under the License is distributed on an "AS IS" BASIS,
012 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *    See the License for the specific language governing permissions and
014 *    limitations under the License.
015 */
016package org.dromara.warm.flow.core.service.impl;
017
018import org.dromara.warm.flow.core.FlowFactory;
019import org.dromara.warm.flow.core.constant.ExceptionCons;
020import org.dromara.warm.flow.core.dao.FlowTaskDao;
021import org.dromara.warm.flow.core.dto.FlowParams;
022import org.dromara.warm.flow.core.dto.ModifyHandler;
023import org.dromara.warm.flow.core.entity.*;
024import org.dromara.warm.flow.core.enums.*;
025import org.dromara.warm.flow.core.listener.Listener;
026import org.dromara.warm.flow.core.listener.ListenerVariable;
027import org.dromara.warm.flow.core.orm.service.impl.WarmServiceImpl;
028import org.dromara.warm.flow.core.service.TaskService;
029import org.dromara.warm.flow.core.utils.*;
030
031import java.math.BigDecimal;
032import java.math.RoundingMode;
033import java.util.*;
034
035/**
036 * 待办任务Service业务层处理
037 *
038 * @author warm
039 * @since 2023-03-29
040 */
041public class TaskServiceImpl extends WarmServiceImpl<FlowTaskDao<Task>, Task> implements TaskService {
042
043    @Override
044    public TaskService setDao(FlowTaskDao<Task> warmDao) {
045        this.warmDao = warmDao;
046        return this;
047    }
048
049    @Override
050    public Instance skip(Long taskId, FlowParams flowParams) {
051        AssertUtil.isTrue(StringUtils.isNotEmpty(flowParams.getMessage())
052                && flowParams.getMessage().length() > 500, ExceptionCons.MSG_OVER_LENGTH);
053        // 获取待办任务
054        Task task = getById(taskId);
055        return skip(flowParams, task);
056    }
057
058    @Override
059    public Instance skip(FlowParams flowParams, Task task) {
060        // TODO min 后续考虑并发问题,待办任务和实例表不同步,可给待办任务id加锁,抽取所接口,方便后续兼容分布式锁
061        // 流程开启前正确性校验
062        R r = getAndCheck(task);
063
064        // 非第一个记得跳转类型必传
065        if (!NodeType.isStart(task.getNodeType())) {
066            AssertUtil.isFalse(StringUtils.isNotEmpty(flowParams.getSkipType()), ExceptionCons.NULL_CONDITIONVALUE);
067        }
068
069        // 执行开始监听器
070        task.setUserList(FlowFactory.userService().listByAssociatedAndTypes(task.getId()));
071        ListenerUtil.executeListener(new ListenerVariable(r.definition, r.instance, r.nowNode, flowParams.getVariable()
072                , task).setFlowParams(flowParams), Listener.LISTENER_START);
073
074        // 如果是受托人在处理任务,需要处理一条委派记录,并且更新委托人,回到计划审批人,然后直接返回流程实例
075        if (handleDepute(task, flowParams)) {
076            return r.instance;
077        }
078
079        // 判断当前处理人是否有权限处理
080        checkAuth(r.nowNode, task, flowParams);
081
082        //或签、会签、票签逻辑处理
083        if (cooperate(r.nowNode, task, flowParams)) {
084            return r.instance;
085        }
086
087        // 获取关联的节点,判断当前处理人是否有权限处理
088        Node nextNode = FlowFactory.nodeService().getNextNode(task.getDefinitionId(), r.nowNode.getNodeCode()
089                , flowParams.getNodeCode(), flowParams.getSkipType());
090
091        // 如果是网关节点,则重新获取后续节点
092        List<Node> nextNodes = FlowFactory.nodeService().getNextByCheckGateway(flowParams.getVariable(), nextNode);
093
094        // 不能退回,未完成过任务
095        if (SkipType.isReject(flowParams.getSkipType())) {
096            List<HisTask> rejectHisTasks = FlowFactory.hisTaskService()
097                    .getByInsAndNodeCodes(task.getInstanceId(), StreamUtils.toList(nextNodes, Node::getNodeCode));
098            AssertUtil.isEmpty(rejectHisTasks, ExceptionCons.BACK_TASK_NOT_EXECUTED);
099        }
100
101        // 判断下一结点是否有权限监听器,有执行权限监听器nextNode.setPermissionFlag,无走数据库的权限标识符
102        ListenerUtil.executeGetNodePermission(new ListenerVariable(r.definition, r.instance, r.nowNode
103                , flowParams.getVariable(), task, nextNodes).setFlowParams(flowParams));
104
105        // 构建增待办任务和设置结束任务历史记录
106        List<Task> addTasks = buildAddTasks(flowParams, task, r.instance, nextNodes, nextNode, r.definition);
107
108        // 办理人变量替换
109        if (CollUtil.isNotEmpty(addTasks)) {
110            addTasks.forEach(addTask -> addTask.getPermissionList().replaceAll(s -> VariableUtil.eval(s, flowParams.getVariable())));
111        }
112        // 执行分派监听器
113        ListenerUtil.executeListener(new ListenerVariable(r.definition, r.instance, r.nowNode, flowParams.getVariable()
114                , task, nextNodes, addTasks).setFlowParams(flowParams), Listener.LISTENER_ASSIGNMENT);
115
116        // 更新流程信息
117        updateFlowInfo(task, r.instance, addTasks, flowParams, nextNodes);
118
119        // 一票否决(谨慎使用),如果退回,退回指向节点后还存在其他正在执行的待办任务,转历史任务,状态都为失效,重走流程。
120        oneVoteVeto(task, flowParams, nextNode.getNodeCode());
121
122        // 处理未完成的任务,当流程完成,还存在待办任务未完成,转历史任务,状态完成。
123        handUndoneTask(r.instance, flowParams);
124
125        // 最后判断是否存在节点监听器,存在执行节点监听器
126        ListenerUtil.endCreateListener(new ListenerVariable(r.definition, r.instance, r.nowNode
127                , flowParams.getVariable(), task, nextNodes, addTasks).setFlowParams(flowParams));
128
129        return r.instance;
130    }
131
132    @Override
133    public Instance termination(Long taskId, FlowParams flowParams) {
134        return termination(getById(taskId), flowParams);
135    }
136
137    @Override
138    public Instance termination(Task task, FlowParams flowParams) {
139        R r = getAndCheck(task);
140        ListenerUtil.executeListener(new ListenerVariable(r.definition, r.instance, r.nowNode, flowParams.getVariable()
141                , task).setFlowParams(flowParams), Listener.LISTENER_START);
142
143        // 判断当前处理人是否有权限处理
144        task.setUserList(FlowFactory.userService().listByAssociatedAndTypes(task.getId()));
145        checkAuth(r.nowNode, task, flowParams);
146
147        // 所有待办转历史
148        Node endNode = FlowFactory.nodeService().getOne(FlowFactory.newNode()
149                .setDefinitionId(r.instance.getDefinitionId()).setNodeType(NodeType.END.getKey()));
150
151        // 流程实例完成
152        r.instance.setNodeType(endNode.getNodeType())
153                .setNodeCode(endNode.getNodeCode())
154                .setNodeName(endNode.getNodeName())
155                .setFlowStatus(ObjectUtil.isNotNull(flowParams.getFlowStatus()) ? flowParams.getFlowStatus()
156                        : FlowStatus.TERMINATE.getKey());
157
158        // 待办任务转历史
159        flowParams.setSkipType(SkipType.PASS.getKey()).flowStatus(r.instance.getFlowStatus());
160        List<HisTask> insHisList = FlowFactory.hisTaskService().setSkipInsHis(task, Collections.singletonList(endNode)
161                , flowParams);
162        FlowFactory.hisTaskService().saveBatch(insHisList);
163        FlowFactory.insService().updateById(r.instance);
164
165        // 删除流程相关办理人
166        FlowFactory.userService().deleteByTaskIds(Collections.singletonList(task.getId()));
167        // 处理未完成的任务,当流程完成,还存在待办任务未完成,转历史任务,状态完成。
168        handUndoneTask(r.instance, flowParams);
169        // 最后判断是否存在节点监听器,存在执行节点监听器
170        ListenerUtil.executeListener(new ListenerVariable(r.definition, r.instance, r.nowNode, flowParams.getVariable()
171                , task), Listener.LISTENER_END);
172        return r.instance;
173    }
174
175    @Override
176    public boolean deleteByInsIds(List<Long> instanceIds) {
177        List<Instance> instanceList = FlowFactory.insService().getByIds(instanceIds);
178        Definition definition;
179        for (Instance instance : instanceList) {
180            definition = FlowFactory.defService().getById(instance.getDefinitionId());
181            AssertUtil.isFalse(judgeActivityStatus(definition, instance), ExceptionCons.NOT_ACTIVITY);
182        }
183        return SqlHelper.retBool(getDao().deleteByInsIds(instanceIds));
184    }
185
186    @Override
187    public boolean transfer(Long taskId, FlowParams flowParams) {
188        List<User> users = FlowFactory.userService().getByProcessedBys(taskId, flowParams.getAddHandlers(), UserType.TRANSFER.getKey());
189        AssertUtil.isNotEmpty(users, ExceptionCons.IS_ALREADY_TRANSFER);
190        flowParams.cooperateType(CooperateType.TRANSFER.getKey())
191                .reductionHandlers(Collections.singletonList(flowParams.getHandler()));
192
193        return updateHandler(taskId, flowParams);
194    }
195
196    @Override
197    public boolean transfer(Long taskId, String curUser, List<String> permissionFlag, List<String> addHandlers, String message) {
198        List<User> users = FlowFactory.userService().getByProcessedBys(taskId, addHandlers, UserType.TRANSFER.getKey());
199        AssertUtil.isNotEmpty(users, ExceptionCons.IS_ALREADY_TRANSFER);
200
201        ModifyHandler modifyHandler = ModifyHandler.build()
202                .taskId(taskId)
203                .addHandlers(addHandlers)
204                .reductionHandlers(Collections.singletonList(curUser))
205                .permissionFlag(permissionFlag)
206                .cooperateType(CooperateType.TRANSFER.getKey())
207                .message(message)
208                .curUser(curUser)
209                .ignore(false);
210        return updateHandler(modifyHandler);
211    }
212    @Override
213    public boolean depute(Long taskId, FlowParams flowParams) {
214        List<User> users = FlowFactory.userService().getByProcessedBys(taskId, flowParams.getAddHandlers(), UserType.DEPUTE.getKey());
215        AssertUtil.isNotEmpty(users, ExceptionCons.IS_ALREADY_DEPUTE);
216        flowParams.cooperateType(CooperateType.DEPUTE.getKey())
217                .reductionHandlers(Collections.singletonList(flowParams.getHandler()));
218
219        return updateHandler(taskId, flowParams);
220    }
221
222    @Override
223    public boolean depute(Long taskId, String curUser, List<String> permissionFlag, List<String> addHandlers, String message) {
224        List<User> users = FlowFactory.userService().getByProcessedBys(taskId, addHandlers, UserType.DEPUTE.getKey());
225        AssertUtil.isNotEmpty(users, ExceptionCons.IS_ALREADY_DEPUTE);
226
227        ModifyHandler modifyHandler = ModifyHandler.build()
228                .taskId(taskId)
229                .addHandlers(addHandlers)
230                .reductionHandlers(Collections.singletonList(curUser))
231                .permissionFlag(permissionFlag)
232                .cooperateType(CooperateType.DEPUTE.getKey())
233                .message(message)
234                .curUser(curUser)
235                .ignore(false);
236        return updateHandler(modifyHandler);
237    }
238
239    @Override
240    public boolean addSignature(Long taskId, FlowParams flowParams) {
241        List<User> users = FlowFactory.userService().getByProcessedBys(taskId, flowParams.getAddHandlers(), UserType.APPROVAL.getKey());
242        AssertUtil.isNotEmpty(users, ExceptionCons.IS_ALREADY_SIGN);
243        flowParams.cooperateType(CooperateType.ADD_SIGNATURE.getKey());
244
245        return updateHandler(taskId, flowParams);
246    }
247
248    @Override
249    public boolean addSignature(Long taskId, String curUser, List<String> permissionFlag, List<String> addHandlers, String message) {
250        List<User> users = FlowFactory.userService().getByProcessedBys(taskId, addHandlers, UserType.APPROVAL.getKey());
251        AssertUtil.isNotEmpty(users, ExceptionCons.IS_ALREADY_SIGN);
252
253        ModifyHandler modifyHandler = ModifyHandler.build()
254                .taskId(taskId)
255                .addHandlers(addHandlers)
256                .permissionFlag(permissionFlag)
257                .cooperateType(CooperateType.ADD_SIGNATURE.getKey())
258                .message(message)
259                .curUser(curUser)
260                .ignore(false);
261        return updateHandler(modifyHandler);
262    }
263
264    @Override
265    public boolean reductionSignature(Long taskId, FlowParams flowParams) {
266        List<User> users = FlowFactory.userService().list(FlowFactory.newUser().setAssociated(taskId)
267                .setType(UserType.APPROVAL.getKey()));
268        AssertUtil.isTrue(CollUtil.isEmpty(users) || users.size() == 1, ExceptionCons.REDUCTION_SIGN_ONE_ERROR);
269        flowParams.cooperateType(CooperateType.REDUCTION_SIGNATURE.getKey());
270
271        return updateHandler(taskId, flowParams);
272    }
273
274    @Override
275    public boolean reductionSignature(Long taskId, String curUser, List<String> permissionFlag, List<String> reductionHandlers, String message) {
276        List<User> users = FlowFactory.userService().list(FlowFactory.newUser().setAssociated(taskId)
277                .setType(UserType.APPROVAL.getKey()));
278
279        AssertUtil.isTrue(CollUtil.isEmpty(users) || users.size() == 1, ExceptionCons.REDUCTION_SIGN_ONE_ERROR);
280        ModifyHandler modifyHandler = ModifyHandler.build()
281                .taskId(taskId)
282                .reductionHandlers(reductionHandlers)
283                .permissionFlag(permissionFlag)
284                .cooperateType(CooperateType.REDUCTION_SIGNATURE.getKey())
285                .message(message)
286                .curUser(curUser)
287                .ignore(false);
288        return updateHandler(modifyHandler);
289    }
290
291    @Override
292    public boolean updateHandler(Long taskId, FlowParams flowParams) {
293        // 获取待办任务
294        R r = getAndCheck(taskId);
295        // 执行开始监听器
296        ListenerUtil.executeListener(new ListenerVariable(r.definition, r.instance, r.nowNode, null, r.task)
297                , Listener.LISTENER_START);
298
299        // 获取给谁的权限
300        if (!flowParams.isIgnore()) {
301            // 判断当前处理人是否有权限,获取当前办理人的权限
302            List<String> permissions = flowParams.getPermissionFlag();
303            // 获取任务权限人
304            List<String> taskPermissions = FlowFactory.userService().getPermission(taskId
305                    , UserType.APPROVAL.getKey(), UserType.TRANSFER.getKey(), UserType.DEPUTE.getKey());
306            AssertUtil.isTrue(CollUtil.isNotEmpty(taskPermissions) && (CollUtil.isEmpty(permissions)
307                    || CollUtil.notContainsAny(permissions, taskPermissions)), ExceptionCons.NOT_AUTHORITY);
308        }
309        // 留存历史记录
310        flowParams.skipType(SkipType.NONE.getKey());
311        List<HisTask> hisTasks = null;
312        // 删除对应的操作人
313        if (CollUtil.isNotEmpty(flowParams.getReductionHandlers())) {
314            for (String reductionHandler : flowParams.getReductionHandlers()) {
315                FlowFactory.userService().remove(FlowFactory.newUser().setAssociated(taskId)
316                        .setProcessedBy(reductionHandler));
317            }
318            hisTasks = FlowFactory.hisTaskService().setCooperateHis(r.task, r.nowNode
319                    , flowParams, flowParams.getReductionHandlers());
320        }
321
322        // 新增权限人
323        if (CollUtil.isNotEmpty(flowParams.getAddHandlers())) {
324            String type;
325            if (CooperateType.TRANSFER.getKey().equals(flowParams.getCooperateType())) {
326                type = UserType.TRANSFER.getKey();
327            } else if (CooperateType.DEPUTE.getKey().equals(flowParams.getCooperateType())) {
328                type = UserType.DEPUTE.getKey();
329            } else {
330                type = UserType.APPROVAL.getKey();
331            }
332            FlowFactory.userService().saveBatch(StreamUtils.toList(flowParams.getAddHandlers(), permission ->
333                    FlowFactory.userService().structureUser(taskId, permission
334                            , type, flowParams.getHandler())));
335            hisTasks = FlowFactory.hisTaskService().setCooperateHis(r.task, r.nowNode
336                    , flowParams, flowParams.getAddHandlers());
337        }
338        if (CollUtil.isNotEmpty(hisTasks)) {
339            FlowFactory.hisTaskService().saveBatch(hisTasks);
340        }
341        // 最后判断是否存在节点监听器,存在执行节点监听器
342        ListenerUtil.executeListener(new ListenerVariable(r.definition, r.instance, r.nowNode, flowParams.getVariable()
343                , r.task), Listener.LISTENER_END);
344        return true;
345    }
346    @Override
347    public boolean updateHandler(ModifyHandler modifyHandler) {
348        return updateHandler(modifyHandler.getTaskId(), new FlowParams()
349                .handler(modifyHandler.getCurUser())
350                .permissionFlag(modifyHandler.getPermissionFlag())
351                .addHandlers(modifyHandler.getAddHandlers())
352                .reductionHandlers(modifyHandler.getReductionHandlers())
353                .cooperateType(modifyHandler.getCooperateType())
354                .message(modifyHandler.getMessage())
355                .ignore(modifyHandler.isIgnore()));
356    }
357
358    @Override
359    public Instance retrieve(Long instanceId, FlowParams flowParams) {
360        Instance instance = FlowFactory.insService().getById(instanceId);
361        AssertUtil.isNull(instance, ExceptionCons.NOT_FOUNT_INSTANCE);
362        // 验证权限是不是当前任务的发起人
363        AssertUtil.isFalse(instance.getCreateBy().equals(flowParams.getHandler())
364                , ExceptionCons.NOT_DEF_PROMOTER_NOT_RETRIEVE);
365        // 如果没传nodeCode,则默认跳转开始节点
366        if (StringUtils.isEmpty(flowParams.getNodeCode())) {
367            flowParams.nodeCode(FlowFactory.nodeService().getOne(FlowFactory.newNode()
368                    .setDefinitionId(instance.getDefinitionId())
369                    .setNodeType(NodeType.START.getKey())).getNodeCode());
370        }
371        // TODO warm 监听器
372        Definition definition = FlowFactory.defService().getById(instance.getDefinitionId());
373        AssertUtil.isFalse(judgeActivityStatus(definition, instance), ExceptionCons.NOT_ACTIVITY);
374        AssertUtil.isTrue(NodeType.isEnd(instance.getNodeType()), ExceptionCons.FLOW_FINISH);
375
376        AssertUtil.isTrue(StringUtils.isNotEmpty(flowParams.getMessage())
377                && flowParams.getMessage().length() > 500, ExceptionCons.MSG_OVER_LENGTH);
378        // 查询目标节点信息
379        Node nextNode = FlowFactory.nodeService().getOne(FlowFactory.newNode()
380                .setNodeCode(flowParams.getNodeCode()).setDefinitionId(instance.getDefinitionId()));
381        AssertUtil.isNull(nextNode, ExceptionCons.LOST_DEST_NODE);
382        // 回退到的节点是否为结束节点,结束节点是不能回退
383        AssertUtil.isTrue(NodeType.isEnd(nextNode.getNodeType()), ExceptionCons.NODE_IS_END);
384
385        // 查询任务,如果前一个节点是并行网关,可能任务表有多个任务,增加查询和判断
386        List<Task> curTaskList = list(FlowFactory.newTask().setInstanceId(instance.getId()));
387        AssertUtil.isEmpty(curTaskList, ExceptionCons.NOT_FOUND_FLOW_TASK);
388
389        // 给回退到的那个节点赋权限-给当前处理人权限
390        Task nextTask = addTask(nextNode, instance, definition, flowParams);
391        // 流程参数
392        flowParams.setSkipType(SkipType.REJECT.getKey());
393        // 删除待办任务,保存历史,删除所有代办任务的权限人
394        if (StringUtils.isNotEmpty(flowParams.getFlowStatus())) {
395            flowParams.flowStatus(FlowStatus.RETRIEVE.getKey());
396        }
397        removeByIds(StreamUtils.toList(curTaskList, Task::getId));
398        // 删除所有待办任务的权限人,处理人保存
399        FlowFactory.userService().deleteByTaskIds(StreamUtils.toList(curTaskList, Task::getId));
400        FlowFactory.hisTaskService().saveBatch(StreamUtils.toList(curTaskList,
401                task -> FlowFactory.hisTaskService().setSkipHisTask(task, nextNode, flowParams)));
402
403        // 设置任务完成后的实例相关信息
404        setInsFinishInfo(instance, CollUtil.toList(nextTask), flowParams);
405        FlowFactory.insService().updateById(instance);
406        // 保存待办任务
407        List<User> users = FlowFactory.userService().taskAddUsers(CollUtil.toList(nextTask));
408        FlowFactory.userService().saveBatch(users);
409        save(nextTask);
410        return instance;
411    }
412
413    @Override
414    public Task addTask(Node node, Instance instance, Definition definition, FlowParams flowParams) {
415        Task addTask = FlowFactory.newTask();
416        FlowFactory.dataFillHandler().idFill(addTask);
417        addTask.setDefinitionId(instance.getDefinitionId())
418                .setInstanceId(instance.getId())
419                .setNodeCode(node.getNodeCode())
420                .setNodeName(node.getNodeName())
421                .setNodeType(node.getNodeType())
422                .setCreateTime(new Date())
423                .setPermissionList(CollUtil.isNotEmpty(node.getDynamicPermissionFlagList())
424                        ? node.getDynamicPermissionFlagList(): StringUtils.str2List(node.getPermissionFlag(), ","));
425
426        if (StringUtils.isNotEmpty(node.getFormCustom()) && StringUtils.isNotEmpty(node.getFormPath())) {
427            // 节点有自定义表单则使用
428            addTask.setFormCustom(node.getFormCustom()).setFormPath(node.getFormPath());
429        } else {
430            addTask.setFormCustom(definition.getFormCustom()).setFormPath(definition.getFormPath());
431        }
432
433        return addTask;
434    }
435
436    @Override
437    public String setFlowStatus(Integer nodeType, String skipType) {
438        // 根据审批动作确定流程状态
439        if (NodeType.isStart(nodeType)) {
440            return FlowStatus.TOBESUBMIT.getKey();
441        } else if (NodeType.isEnd(nodeType)) {
442            return FlowStatus.FINISHED.getKey();
443        } else if (SkipType.isReject(skipType)) {
444            return FlowStatus.REJECT.getKey();
445        } else {
446            return FlowStatus.APPROVAL.getKey();
447        }
448    }
449
450    @Override
451    public Task getNextTask(List<Task> tasks) {
452        if (tasks.size() == 1) {
453            return tasks.get(0);
454        }
455        for (Task task : tasks) {
456            if (NodeType.isEnd(task.getNodeType())) {
457                return task;
458            }
459        }
460        return tasks.stream().max(Comparator.comparingLong(Task::getId)).orElse(null);
461    }
462
463    private R getAndCheck(Long taskId) {
464        return getAndCheck(getById(taskId));
465    }
466
467    private R getAndCheck(Task task) {
468        AssertUtil.isNull(task, ExceptionCons.NOT_FOUNT_TASK);
469        Instance instance = FlowFactory.insService().getById(task.getInstanceId());
470        AssertUtil.isNull(instance, ExceptionCons.NOT_FOUNT_INSTANCE);
471        Definition definition = FlowFactory.defService().getById(instance.getDefinitionId());
472        AssertUtil.isFalse(judgeActivityStatus(definition, instance), ExceptionCons.NOT_ACTIVITY);
473        AssertUtil.isTrue(NodeType.isEnd(instance.getNodeType()), ExceptionCons.FLOW_FINISH);
474        Node nowNode = FlowFactory.nodeService().getOne(FlowFactory.newNode().setNodeCode(task.getNodeCode())
475                .setDefinitionId(task.getDefinitionId()));
476        AssertUtil.isNull(nowNode, ExceptionCons.LOST_CUR_NODE);
477        return new R(instance, definition, nowNode, task);
478    }
479
480    private static class R {
481        public final Instance instance;
482        public final Definition definition;
483        public final Node nowNode;
484        public final Task task;
485
486        public R(Instance instance, Definition definition, Node nowNode, Task task) {
487            this.instance = instance;
488            this.definition = definition;
489            this.nowNode = nowNode;
490            this.task = task;
491        }
492    }
493
494    private boolean handleDepute(Task task, FlowParams flowParams) {
495        // 获取受托人
496        User entrustedUser = FlowFactory.userService().getOne(FlowFactory.newUser().setAssociated(task.getId())
497                .setProcessedBy(flowParams.getHandler()).setType(UserType.DEPUTE.getKey()));
498        if (ObjectUtil.isNull(entrustedUser)) {
499            return false;
500        }
501
502        // 记录受托人处理任务记录
503        HisTask hisTask = FlowFactory.hisTaskService().setDeputeHisTask(task, flowParams, entrustedUser);
504        FlowFactory.hisTaskService().save(hisTask);
505        FlowFactory.userService().removeById(entrustedUser.getId());
506
507        // 查询委托人,如果在flow_user不存在,则给委托人新增待办记录
508        User deputeUser = FlowFactory.userService().getOne(FlowFactory.newUser().setAssociated(task.getId())
509                .setProcessedBy(entrustedUser.getCreateBy()).setType(UserType.APPROVAL.getKey()));
510        if (ObjectUtil.isNull(deputeUser)) {
511            User newUser = FlowFactory.userService().structureUser(entrustedUser.getAssociated()
512                    , entrustedUser.getCreateBy()
513                    , UserType.APPROVAL.getKey(), entrustedUser.getProcessedBy());
514            FlowFactory.userService().save(newUser);
515        }
516
517        return true;
518    }
519
520    /**
521     * 会签,票签,协作处理,返回true;或签或者会签、票签结束返回false
522     *
523     * @param nowNode 当前节点
524     * @param task 任务
525     * @param flowParams 流程参数
526     * @return boolean
527     */
528    private boolean cooperate(Node nowNode, Task task, FlowParams flowParams) {
529        BigDecimal nodeRatio = nowNode.getNodeRatio();
530        // 或签,直接返回
531        if (CooperateType.isOrSign(nodeRatio)) {
532            return false;
533        }
534
535        // 办理人和转办人列表
536        List<User> todoList = FlowFactory.userService().listByAssociatedAndTypes(task.getId()
537                , UserType.APPROVAL.getKey(), UserType.TRANSFER.getKey(), UserType.DEPUTE.getKey());
538
539        // 判断办理人是否有办理权限
540        AssertUtil.isEmpty(flowParams.getHandler(), ExceptionCons.SIGN_NULL_HANDLER);
541        User todoUser = CollUtil.getOne(StreamUtils.filter(todoList, u -> Objects.equals(u.getProcessedBy(), flowParams.getHandler())));
542        AssertUtil.isNull(todoUser, ExceptionCons.NOT_AUTHORITY);
543
544        // 当只剩一位待办用户时,由当前用户决定走向
545        if (todoList.size() == 1) {
546            return false;
547        }
548
549        // 除当前办理人外剩余办理人列表
550        List<User> restList = StreamUtils.filter(todoList, u -> !Objects.equals(u.getProcessedBy(), flowParams.getHandler()));
551
552        // 会签并且当前人驳回直接返回
553        if (CooperateType.isCountersign(nodeRatio) && SkipType.isReject(flowParams.getSkipType())) {
554            FlowFactory.userService().removeByIds(StreamUtils.toList(restList, User::getId));
555            return false;
556        }
557
558        // 查询会签票签已办列表
559
560        List<HisTask> doneList = FlowFactory.hisTaskService().listByTaskIdAndCooperateTypes(task.getId()
561                , CooperateType.isCountersign(nodeRatio) ? CooperateType.COUNTERSIGN.getKey() : CooperateType.VOTE.getKey());
562        doneList = CollUtil.emptyDefault(doneList, Collections.emptyList());
563
564        // TODO 这里处理 cooperation handler 获取下面的 passRatio rejectRatio all 值,能获取使用 handler的值,不能获取使用以下全自动计算代码
565
566        // 所有人
567        BigDecimal all = BigDecimal.ZERO.add(BigDecimal.valueOf(todoList.size())).add(BigDecimal.valueOf(doneList.size()));
568
569        List<HisTask> donePassList = StreamUtils.filter(doneList
570                , hisTask -> Objects.equals(hisTask.getSkipType(), SkipType.PASS.getKey()));
571
572        List<HisTask> doneRejectList = StreamUtils.filter(doneList
573                , hisTask -> Objects.equals(hisTask.getSkipType(), SkipType.REJECT.getKey()));
574
575        boolean isPass = SkipType.isPass(flowParams.getSkipType());
576
577        // 计算通过率
578        BigDecimal passRatio = (isPass ? BigDecimal.ONE : BigDecimal.ZERO)
579                .add(BigDecimal.valueOf(donePassList.size()))
580                .divide(all, 4, RoundingMode.HALF_UP).multiply(CooperateType.ONE_HUNDRED);
581
582        // 计算驳回率
583        BigDecimal rejectRatio = (isPass ? BigDecimal.ZERO : BigDecimal.ONE)
584                .add(BigDecimal.valueOf(doneRejectList.size()))
585                .divide(all, 4, RoundingMode.HALF_UP).multiply(CooperateType.ONE_HUNDRED);
586
587        if (!isPass && rejectRatio.compareTo(CooperateType.ONE_HUNDRED.subtract(nodeRatio)) > 0) {
588            // 驳回,并且当前是驳回
589            FlowFactory.userService().removeByIds(StreamUtils.toList(restList, User::getId));
590            return false;
591        }
592
593        if (passRatio.compareTo(nodeRatio) >= 0) {
594            // 大于等于 nodeRatio 设置值结束任务
595            FlowFactory.userService().removeByIds(StreamUtils.toList(restList, User::getId));
596            return false;
597        }
598
599        // 添加历史任务
600        HisTask hisTask = FlowFactory.hisTaskService().setSignHisTask(task, flowParams, nodeRatio, isPass);
601        FlowFactory.hisTaskService().save(hisTask);
602
603        // 删掉待办用户
604        FlowFactory.userService().removeById(todoUser.getId());
605        return true;
606    }
607
608    /**
609     * 构建增待办任务
610     *
611     * @param flowParams 流程参数
612     * @param task 待办任务
613     * @param instance 实例
614     * @param nextNode 下个节点
615     * @return List<Task>
616     */
617    private List<Task> buildAddTasks(FlowParams flowParams, Task task, Instance instance
618            , List<Node> nextNodes, Node nextNode, Definition definition) {
619        boolean buildFlag = false;
620        // 下个节点非并行网关节点,可以直接生成下一个待办任务
621        if (!NodeType.isGateWayParallel(nextNode.getNodeType())) {
622            buildFlag = true;
623        } else {
624            // 下个节点是并行网关节点,判断前置节点是否都完成
625            if (gateWayParallelIsFinish(task, instance, nextNode.getNodeCode())) {
626                buildFlag = true;
627            }
628        }
629
630        if (buildFlag) {
631            List<Task> addTasks = new ArrayList<>();
632            for (Node node : nextNodes) {
633                addTasks.add(addTask(node, instance, definition, flowParams));
634            }
635            return addTasks;
636        }
637        return null;
638    }
639
640    /**
641     * 判断并行网关节点前置任务是否都完成
642     * 多条线路汇聚到并行网关,必须所有任务都完成,才能继续。 根据并行网关节点,查询前面的节点是否都完成,
643     * 判断规则,获取网关所有前置节点,并且查询是否有历史任务记录,前前置节点完成时间是否早于前置节点
644     *
645     * @param task 待办任务
646     * @param instance 实例
647     * @param nextNodeCode 下个节点编码
648     * @return boolean
649     */
650    private boolean gateWayParallelIsFinish(Task task, Instance instance, String nextNodeCode) {
651        List<Skip> allSkips = FlowFactory.skipService().list(FlowFactory.newSkip()
652                .setDefinitionId(instance.getDefinitionId()));
653        Map<String, List<Skip>> skipNextMap = StreamUtils.groupByKeyFilter(skip -> !task.getNodeCode()
654                        .equals(skip.getNowNodeCode()) || !nextNodeCode.equals(skip.getNextNodeCode())
655                , allSkips, Skip::getNextNodeCode);
656        List<Skip> oneLastSkips = skipNextMap.get(nextNodeCode);
657        // 说明没有其他前置节点,那可以完成往下执行
658        if (CollUtil.isEmpty(oneLastSkips)) {
659            return true;
660        }
661        List<HisTask> hisTaskList = FlowFactory.hisTaskService().getNoReject(instance.getId());
662        int wayParallelIsFinish = 0;
663        if (CollUtil.isNotEmpty(oneLastSkips)) {
664            for (Skip oneLastSkip : oneLastSkips) {
665                HisTask oneLastHisTask = FlowFactory.hisTaskService()
666                        .getNoReject(oneLastSkip.getNowNodeCode(), null, hisTaskList);
667                // 查询前置节点是否有完成记录
668                if (ObjectUtil.isNull(oneLastHisTask)) {
669                    return false;
670                }
671                List<Skip> twoLastSkips = skipNextMap.get(oneLastSkip.getNowNodeCode());
672                for (Skip twoLastSkip : twoLastSkips) {
673                    if (NodeType.isStart(twoLastSkip.getNowNodeType())) {
674                        wayParallelIsFinish++;
675                    } else if (NodeType.isGateWay(twoLastSkip.getNowNodeType())) {
676                        // 如果前前置节点是网关,那网关前任意一个任务完成就算完成
677                        List<Skip> threeLastSkips = skipNextMap.get(twoLastSkip.getNowNodeCode());
678                        for (Skip threeLastSkip : threeLastSkips) {
679                            HisTask threeLastHisTask = FlowFactory.hisTaskService()
680                                    .getNoReject(threeLastSkip.getNowNodeCode(), null, hisTaskList);
681                            if (ObjectUtil.isNotNull(threeLastHisTask) && (threeLastHisTask.getUpdateTime()
682                                    .before(oneLastHisTask.getUpdateTime()) || threeLastHisTask.getUpdateTime()
683                                    .equals(oneLastHisTask.getUpdateTime()))) {
684                                wayParallelIsFinish++;
685                            }
686                        }
687                    } else {
688                        HisTask twoLastHisTask = FlowFactory.hisTaskService()
689                                .getNoReject(twoLastSkip.getNowNodeCode(), null, hisTaskList);
690                        // 前前置节点完成时间是否早于前置节点,如果是串行网关,那前前置节点必须只有一个完成,如果是并行网关都要完成
691                        if (ObjectUtil.isNotNull(twoLastHisTask) && (twoLastHisTask.getUpdateTime()
692                                .before(oneLastHisTask.getUpdateTime()) || twoLastHisTask.getUpdateTime()
693                                .equals(oneLastHisTask.getUpdateTime()))) {
694                            wayParallelIsFinish++;
695                        }
696                    }
697                }
698            }
699        }
700        return wayParallelIsFinish == oneLastSkips.size();
701    }
702
703    /**
704     * 判断当前处理人是否有权限处理
705     *
706     * @param NowNode         当前节点权限(动态权限)
707     * @param task            当前任务(任务id)
708     * @param flowParams:包含流程相关参数的对象
709     */
710    private void checkAuth(Node NowNode, Task task, FlowParams flowParams) {
711        if (flowParams.isIgnore()) {
712            return;
713        }
714        // 如果有动态权限标识,则优先使用动态权限标识
715        List<String> permissions;
716        if (CollUtil.isNotEmpty(NowNode.getDynamicPermissionFlagList())) {
717            permissions = NowNode.getDynamicPermissionFlagList();
718        } else {
719            // 查询审批人和转办人
720            permissions = StreamUtils.toList(task.getUserList(), User::getProcessedBy);
721        }
722        // 当前节点
723        AssertUtil.isTrue(CollUtil.isNotEmpty(permissions) && (CollUtil.isEmpty(flowParams.getPermissionFlag())
724                || CollUtil.notContainsAny(flowParams.getPermissionFlag(), permissions)), ExceptionCons.NULL_ROLE_NODE);
725    }
726
727    // 设置任务完成后的实例相关信息
728    private void setInsFinishInfo(Instance instance, List<Task> addTasks, FlowParams flowParams) {
729        instance.setUpdateTime(new Date());
730        Map<String, Object> variable = flowParams.getVariable();
731        if (MapUtil.isNotEmpty(variable)) {
732            String variableStr = instance.getVariable();
733            Map<String, Object> deserialize = FlowFactory.jsonConvert.strToMap(variableStr);
734            deserialize.putAll(variable);
735            instance.setVariable(FlowFactory.jsonConvert.mapToStr(deserialize));
736        }
737        if (CollUtil.isNotEmpty(addTasks)) {
738            addTasks.removeIf(addTask -> {
739                if (NodeType.isEnd(addTask.getNodeType())) {
740                        instance.setNodeType(addTask.getNodeType())
741                                .setNodeCode(addTask.getNodeCode())
742                                .setNodeName(addTask.getNodeName())
743                                .setFlowStatus(ObjectUtil.isNotNull(flowParams.getFlowStatus())
744                                        ? flowParams.getFlowStatus() : FlowStatus.FINISHED.getKey());
745                    return true;
746                }
747                return false;
748            });
749        }
750        if (CollUtil.isNotEmpty(addTasks) && !NodeType.isEnd(instance.getNodeType())) {
751            Task nextTask = getNextTask(addTasks);
752                instance.setNodeType(nextTask.getNodeType())
753                        .setNodeCode(nextTask.getNodeCode())
754                        .setNodeName(nextTask.getNodeName())
755                        .setFlowStatus(ObjectUtil.isNotNull(flowParams.getFlowStatus()) ? flowParams.getFlowStatus()
756                                : setFlowStatus(nextTask.getNodeType(), flowParams.getSkipType()));
757        }
758    }
759
760    /**
761     * 一票否决(谨慎使用),如果退回,退回指向节点后还存在其他正在执行的待办任务,转历史任务,状态都为退回,重走流程。
762     *
763     * @param task 当前任务
764     * @param flowParams 包含流程相关参数的对象
765     * @param nextNodeCode 下一个节点编码
766     */
767    private void oneVoteVeto(Task task, FlowParams flowParams, String nextNodeCode) {
768        // 一票否决(谨慎使用),如果退回,退回指向节点后还存在其他正在执行的待办任务,转历史任务,状态失效,重走流程。
769        if (SkipType.isReject(flowParams.getSkipType())) {
770            List<Task> tasks = list(FlowFactory.newTask().setInstanceId(task.getInstanceId()));
771            List<Skip> allSkips = FlowFactory.skipService().list(FlowFactory.newSkip()
772                    .setDefinitionId(task.getDefinitionId()));
773            // 排除执行当前节点的流程跳转
774            Map<String, List<Skip>> skipMap = StreamUtils.groupByKeyFilter(skip ->
775                    !task.getNodeCode().equals(skip.getNextNodeCode()), allSkips, Skip::getNextNodeCode);
776            // 属于退回指向节点的后置未完成的任务
777            List<Task> noDoneTasks = new ArrayList<>();
778            for (Task flowTask : tasks) {
779                if (!task.getNodeCode().equals(flowTask.getNodeCode())) {
780                    List<Skip> lastSkips = skipMap.get(flowTask.getNodeCode());
781                    if (judgeReject(nextNodeCode, lastSkips, skipMap)) {
782                        noDoneTasks.add(flowTask);
783                    }
784                }
785            }
786            if (CollUtil.isNotEmpty(noDoneTasks)) {
787                convertHisTask(noDoneTasks, flowParams, FlowStatus.INVALID.getKey());
788            }
789        }
790    }
791
792
793    /**
794     * 判断是否属于退回指向节点的后置未完成的任务
795     *
796     * @param nextNodeCode 下一个节点编码
797     * @param lastSkips 上一个跳转集合
798     * @param skipMap 跳转map
799     * @return boolean
800     */
801    private boolean judgeReject(String nextNodeCode, List<Skip> lastSkips
802            , Map<String, List<Skip>> skipMap) {
803        if (CollUtil.isNotEmpty(lastSkips)) {
804            for (Skip lastSkip : lastSkips) {
805                if (nextNodeCode.equals(lastSkip.getNowNodeCode())) {
806                    return true;
807                }
808                List<Skip> lastLastSkips = skipMap.get(lastSkip.getNowNodeCode());
809                return judgeReject(nextNodeCode, lastLastSkips, skipMap);
810            }
811        }
812        return false;
813    }
814
815    /**
816     * 处理未完成的任务,当流程完成,还存在待办任务未完成,转历史任务,状态完成。
817     *
818     * @param instance 流程实例
819     */
820    private void handUndoneTask(Instance instance, FlowParams flowParams) {
821        if (NodeType.isEnd(instance.getNodeType())) {
822            List<Task> taskList = list(FlowFactory.newTask().setInstanceId(instance.getId()));
823            if (CollUtil.isNotEmpty(taskList)) {
824                convertHisTask(taskList, flowParams, FlowStatus.AUTO_PASS.getKey());
825            }
826        }
827    }
828
829    /**
830     * 待办任务转历史任务。
831     */
832    private void convertHisTask(List<Task> taskList, FlowParams flowParams, String flowStatus) {
833        List<HisTask> insHisList = new ArrayList<>();
834        for (Task task : taskList) {
835            List<User> userList = FlowFactory.userService().listByAssociatedAndTypes(task.getId());
836            List<HisTask> hisTasks = FlowFactory.hisTaskService().autoHisTask(flowParams, flowStatus, task, userList, CooperateType.APPROVAL.getKey());
837            // 设置每个HisTask的ext字段
838            hisTasks.forEach(hisTask -> hisTask.setExt(flowParams.getHisTaskExt()));
839            insHisList.addAll(hisTasks);
840        }
841        removeByIds(StreamUtils.toList(taskList, Task::getId));
842        FlowFactory.hisTaskService().saveBatch(insHisList);
843        // 删除所有待办任务的权限人
844        FlowFactory.userService().deleteByTaskIds(StreamUtils.toList(taskList, Task::getId));
845    }
846
847    /**
848     * 更新流程信息
849     *
850     * @param task 当前任务
851     * @param instance 流程实例
852     * @param addTasks 新增待办任务
853     * @param flowParams 包含流程相关参数的对象
854     * @param nextNodes 下一个节点集合
855     */
856    private void updateFlowInfo(Task task, Instance instance, List<Task> addTasks, FlowParams flowParams
857            , List<Node> nextNodes) {
858        // 设置流程历史任务信息
859        List<HisTask> insHisList = FlowFactory.hisTaskService().setSkipInsHis(task, nextNodes, flowParams);
860        FlowFactory.hisTaskService().saveBatch(insHisList);
861        // 待办任务设置处理人
862        List<User> users = FlowFactory.userService().setSkipUser(addTasks, task.getId());
863        removeById(task.getId());
864
865        // 设置任务完成后的实例相关信息
866        setInsFinishInfo(instance, addTasks, flowParams);
867        if (CollUtil.isNotEmpty(addTasks)) {
868            saveBatch(addTasks);
869        }
870        FlowFactory.insService().updateById(instance);
871        // 保存下一个待办任务的权限人和历史任务的处理人
872        FlowFactory.userService().saveBatch(users);
873    }
874
875    private boolean judgeActivityStatus(Definition definition, Instance instance) {
876        return Objects.equals(definition.getActivityStatus(), ActivityStatus.ACTIVITY.getKey())
877                && Objects.equals(instance.getActivityStatus(), ActivityStatus.ACTIVITY.getKey());
878    }
879}