ButtonUtil.java 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. package jnpf.flowable.util;
  2. import cn.hutool.core.collection.CollectionUtil;
  3. import cn.hutool.core.util.ObjectUtil;
  4. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  5. import com.google.common.collect.ImmutableList;
  6. import jnpf.base.UserInfo;
  7. import jnpf.base.model.base.SystemBaeModel;
  8. import jnpf.base.model.systemconfig.SysConfigModel;
  9. import jnpf.constant.MsgCode;
  10. import jnpf.exception.WorkFlowException;
  11. import jnpf.flowable.entity.*;
  12. import jnpf.flowable.enums.*;
  13. import jnpf.flowable.model.flowable.FlowAbleUrl;
  14. import jnpf.flowable.model.flowable.FlowableNodeModel;
  15. import jnpf.flowable.model.flowable.NextOrPrevFo;
  16. import jnpf.flowable.model.operator.AddSignModel;
  17. import jnpf.flowable.model.task.FlowMethod;
  18. import jnpf.flowable.model.task.FlowModel;
  19. import jnpf.flowable.model.templatenode.ButtonModel;
  20. import jnpf.flowable.model.templatenode.TaskNodeModel;
  21. import jnpf.flowable.model.templatenode.nodejson.FileConfig;
  22. import jnpf.flowable.model.templatenode.nodejson.NodeModel;
  23. import jnpf.flowable.model.templatenode.nodejson.PrintConfig;
  24. import jnpf.flowable.model.templatenode.nodejson.ProperCond;
  25. import jnpf.flowable.model.util.FlowNature;
  26. import jnpf.flowable.service.*;
  27. import jnpf.permission.model.authorize.AuthorizeVO;
  28. import jnpf.util.JsonUtil;
  29. import jnpf.util.StringUtil;
  30. import jnpf.util.UserProvider;
  31. import org.springframework.beans.factory.annotation.Autowired;
  32. import org.springframework.stereotype.Component;
  33. import java.util.*;
  34. import java.util.stream.Collectors;
  35. /**
  36. * 类的描述
  37. *
  38. * @author JNPF@YinMai Info. Co., Ltd
  39. * @version 5.0.x
  40. * @since 2024/5/16 17:35
  41. */
  42. @Component
  43. public class ButtonUtil {
  44. @Autowired
  45. private OperatorService operatorService;
  46. @Autowired
  47. private FlowAbleUrl flowAbleUrl;
  48. @Autowired
  49. private ServiceUtil serviceUtil;
  50. @Autowired
  51. private OperatorUtil operatorUtil;
  52. @Autowired
  53. private TaskService taskService;
  54. @Autowired
  55. private RevokeService revokeService;
  56. @Autowired
  57. private DelegateService delegateService;
  58. @Autowired
  59. private EventLogService eventLogService;
  60. @Autowired
  61. private TriggerRecordService triggerRecordService;
  62. @Autowired
  63. private RecordService recordService;
  64. @Autowired
  65. private TemplateService templateService;
  66. /**
  67. * 按钮控制
  68. *
  69. * @param flowModel 参数
  70. */
  71. public ButtonModel handleButton(FlowModel flowModel) throws WorkFlowException {
  72. String opType = flowModel.getOpType();
  73. TaskEntity taskEntity = flowModel.getTaskEntity();
  74. OperatorEntity operatorEntity = flowModel.getOperatorEntity();
  75. RecordEntity recordEntity = flowModel.getRecordEntity();
  76. Map<String, Object> formData = flowModel.getFormData();
  77. List<TaskNodeModel> nodeList = flowModel.getNodeList();
  78. TemplateEntity template = flowModel.getTemplateEntity();
  79. UserInfo userInfo = flowModel.getUserInfo() == null ? UserProvider.getUser() : flowModel.getUserInfo();
  80. String userId = userInfo.getUserId();
  81. List<TemplateNodeEntity> nodeEntityList = flowModel.getNodeEntityList();
  82. Map<String, NodeModel> nodes = new HashMap<>();
  83. for (TemplateNodeEntity nodeEntity : nodeEntityList) {
  84. nodes.put(nodeEntity.getNodeCode(), JsonUtil.getJsonToBean(nodeEntity.getNodeJson(), NodeModel.class));
  85. }
  86. flowModel.setNodes(nodes);
  87. RevokeEntity revokeEntity = revokeService.getRevokeTask(taskEntity.getId());
  88. // 全局节点
  89. NodeModel global = nodes.get(NodeEnum.global.getType());
  90. ButtonModel model = new ButtonModel();
  91. FlowMethod flowMethod = new FlowMethod();
  92. flowMethod.setNodes(nodes);
  93. flowMethod.setTaskEntity(taskEntity);
  94. flowMethod.setFormData(formData);
  95. flowMethod.setPrintNodeList(nodeList);
  96. OpTypeEnum type = OpTypeEnum.getType(opType);
  97. switch (type) {
  98. case LaunchCreate: // 我发起的新建/编辑
  99. // List<Integer> templateStatus = ImmutableList.of(1, 2);
  100. // if (!templateStatus.contains(template.getStatus())) {
  101. // break;
  102. // }
  103. // 是否是退回撤回的任务
  104. List<Integer> taskStatus = ImmutableList.of(TaskStatusEnum.BACKED.getCode(), TaskStatusEnum.RECALL.getCode());
  105. boolean isBack = taskStatus.contains(taskEntity.getStatus());
  106. if (isBack) {
  107. // 是否是委托的任务
  108. boolean isDelegate = StringUtil.isNotBlank(taskEntity.getDelegateUserId());
  109. if (isDelegate) {
  110. if (ObjectUtil.equals(taskEntity.getParentId(), FlowNature.ParentId)) {
  111. model.setHasDelegateSubmitBtn(this.checkDelegateSubmit(userId, template));
  112. }
  113. }
  114. } else {
  115. // 委托发起
  116. if (null == taskEntity.getId()) {
  117. model.setHasDelegateSubmitBtn(this.checkDelegateSubmit(userId, template));
  118. } else {
  119. if (ObjectUtil.equals(taskEntity.getParentId(), FlowNature.ParentId)) {
  120. model.setHasDelegateSubmitBtn(this.checkDelegateSubmit(userId, template));
  121. }
  122. }
  123. }
  124. //暂存和发起按钮
  125. boolean commonUser = serviceUtil.isCommonUser(userId);
  126. if (commonUser) {
  127. if (null == taskEntity.getId() || ObjectUtil.equals(taskEntity.getParentId(), FlowNature.ParentId)) {
  128. AuthorizeVO authorizeByUser = serviceUtil.getAuthorizeByUser();
  129. List<String> systemIdList = authorizeByUser.getSystemList().stream().filter(t -> !Objects.equals(t.getIsMain(), 1)).map(SystemBaeModel::getId).collect(Collectors.toList());
  130. if (!systemIdList.isEmpty()) {
  131. QueryWrapper<TemplateEntity> queryWrapper = new QueryWrapper<>();
  132. queryWrapper.lambda().in(TemplateEntity::getSystemId, systemIdList)
  133. .eq(TemplateEntity::getVisibleType, FlowNature.All);
  134. queryWrapper.lambda().select(TemplateEntity::getId);
  135. List<TemplateEntity> list = templateService.list(queryWrapper);
  136. List<String> permissionList = list.stream().map(TemplateEntity::getId).collect(Collectors.toList());
  137. permissionList.addAll(authorizeByUser.getFlowIdList());
  138. if (permissionList.contains(template.getId())) {
  139. model.setHasSubmitBtn(true);
  140. model.setHasSaveBtn(true);
  141. }
  142. }
  143. } else {
  144. model.setHasSubmitBtn(true);
  145. model.setHasSaveBtn(true);
  146. }
  147. } else {
  148. model.setHasSubmitBtn(true);
  149. model.setHasSaveBtn(true);
  150. }
  151. break;
  152. case LaunchDetail: // 我发起的详情
  153. // 打印
  154. TemplateNodeEntity start = nodeEntityList.stream().filter(e -> e.getNodeType().equals(NodeEnum.start.getType())).findFirst().orElse(null);
  155. if (null != start) {
  156. NodeModel startNode = JsonUtil.getJsonToBean(start.getNodeJson(), NodeModel.class);
  157. flowMethod.setNodeModel(startNode);
  158. model.setHasPrintBtn(this.checkPrint(flowMethod));
  159. }
  160. // 催办
  161. List<Integer> statusList = ImmutableList.of(TaskStatusEnum.RUNNING.getCode(), TaskStatusEnum.REVOKING.getCode());
  162. if (global.getHasInitiatorPressOverdueNode() && statusList.contains(taskEntity.getStatus())) {
  163. QueryWrapper<OperatorEntity> queryWrapper = new QueryWrapper<>();
  164. queryWrapper.lambda().eq(OperatorEntity::getTaskId, taskEntity.getId()).eq(OperatorEntity::getCompletion, FlowNature.Normal)
  165. .ne(OperatorEntity::getStatus, OperatorStateEnum.Futility.getCode())
  166. .isNull(OperatorEntity::getHandleStatus).isNotNull(OperatorEntity::getDuedate);
  167. List<OperatorEntity> operatorList = operatorService.list(queryWrapper);
  168. if (!operatorList.isEmpty()) {
  169. model.setHasPressBtn(true);
  170. }
  171. }
  172. // 撤回
  173. if (null == revokeEntity) {
  174. flowModel.setFlag(FlowNature.InitiateFlag);
  175. if (this.checkRecall(flowModel)) {
  176. model.setHasRecallLaunchBtn(true);
  177. }
  178. }
  179. // 撤销,全局属性开启 且 同意状态的任务才能撤销 且不是子流程
  180. if (global.getHasRevoke() && Objects.equals(taskEntity.getStatus(), TaskStatusEnum.PASSED.getCode())
  181. && Objects.equals(taskEntity.getParentId(), FlowNature.ParentId)) {
  182. Boolean isExist = revokeService.checkExist(taskEntity.getId());
  183. if (null == revokeEntity && isExist) {
  184. model.setHasRevokeBtn(true);
  185. }
  186. }
  187. break;
  188. case Sign: // 待签事宜
  189. if (Objects.equals(taskEntity.getStatus(), TaskStatusEnum.PAUSED.getCode())) {
  190. break;
  191. }
  192. model.setHasSignBtn(true);
  193. if (null != operatorEntity) {
  194. model.setProxyMark(!ObjectUtil.equals(operatorEntity.getHandleId(), userId));
  195. NodeModel nodeModel = nodes.get(operatorEntity.getNodeCode());
  196. if (this.checkViewStartForm(global, nodeModel)) {
  197. model.setHasViewStartFormBtn(true);
  198. }
  199. }
  200. break;
  201. case Todo: // 待办事宜
  202. if (Objects.equals(taskEntity.getStatus(), TaskStatusEnum.PAUSED.getCode())) {
  203. break;
  204. }
  205. if (global.getHasSignFor()) {
  206. model.setHasReduceSignBtn(true);
  207. }
  208. model.setHasTransactBtn(true);
  209. if (null != operatorEntity) {
  210. NodeModel nodeModel = nodes.get(operatorEntity.getNodeCode());
  211. if (this.checkViewStartForm(global, nodeModel)) {
  212. model.setHasViewStartFormBtn(true);
  213. }
  214. }
  215. break;
  216. case Doing: // 在办事宜
  217. if (Objects.equals(taskEntity.getStatus(), TaskStatusEnum.PAUSED.getCode())) {
  218. break;
  219. }
  220. if (null == operatorEntity) {
  221. break;
  222. }
  223. // 待办的opType传的也是3,所以待办的代理标识需要再在办判断
  224. model.setProxyMark(!ObjectUtil.equals(operatorEntity.getHandleId(), userId));
  225. if (null != revokeEntity) {
  226. model.setHasAuditBtn(true);
  227. model.setHasRejectBtn(true);
  228. break;
  229. }
  230. NodeModel nodeModel = nodes.get(operatorEntity.getNodeCode());
  231. if (null == nodeModel) {
  232. break;
  233. }
  234. if (this.checkViewStartForm(global, nodeModel)) {
  235. model.setHasViewStartFormBtn(true);
  236. }
  237. // 协办状态的经办 只有协办保存按钮
  238. if (OperatorStateEnum.Assist.getCode().equals(operatorEntity.getStatus())) {
  239. model.setHasAssistSaveBtn(true);
  240. break;
  241. }
  242. // 打印
  243. flowMethod.setNodeModel(nodeModel);
  244. model.setHasPrintBtn(this.checkPrint(flowMethod));
  245. if (nodeModel.getHasAuditBtn()) {
  246. model.setHasAuditBtn(true);
  247. }
  248. if (nodeModel.getHasRejectBtn() && ObjectUtil.equals(operatorEntity.getIsProcessing(), FlowNature.NotProcessing)) {
  249. model.setHasRejectBtn(true);
  250. }
  251. if (nodeModel.getHasBackBtn() && taskEntity.getRejectDataId() == null) {
  252. model.setHasBackBtn(true);
  253. }
  254. if (nodeModel.getHasSaveAuditBtn()) {
  255. model.setHasSaveAuditBtn(true);
  256. }
  257. List<Integer> operatorState = ImmutableList.of(OperatorStateEnum.AddSign.getCode(), OperatorStateEnum.Transfer.getCode());
  258. if (nodeModel.getHasFreeApproverBtn()) {
  259. if (!ObjectUtil.equals(operatorEntity.getStatus(), OperatorStateEnum.Transfer.getCode())) {
  260. model.setHasFreeApproverBtn(this.checkAddSign(operatorEntity, null, false));
  261. }
  262. }
  263. if (nodeModel.getHasTransferBtn()) {
  264. if (!operatorState.contains(operatorEntity.getStatus()) && ObjectUtil.equals(operatorEntity.getParentId(), FlowNature.ParentId)) {
  265. model.setHasTransferBtn(true);
  266. }
  267. }
  268. if (nodeModel.getHasAssistBtn()) {
  269. model.setHasAssistBtn(true);
  270. }
  271. break;
  272. case Done: // 已办事宜
  273. if (null == operatorEntity || operatorEntity.getId() == null) {
  274. break;
  275. }
  276. // 减签
  277. NodeModel node = nodes.get(operatorEntity.getNodeCode());
  278. // 节点属性开启、经办存在加签信息、记录是加签操作
  279. if (node != null) {
  280. if (null != recordEntity) {
  281. if (node.getHasReduceApproverBtn() && null != operatorEntity.getHandleParameter()
  282. && recordEntity.getHandleType().equals(RecordEnum.addSign.getCode())) {
  283. QueryWrapper<OperatorEntity> queryWrapper = new QueryWrapper<>();
  284. queryWrapper.lambda().eq(OperatorEntity::getTaskId, operatorEntity.getTaskId())
  285. .eq(OperatorEntity::getParentId, operatorEntity.getId())
  286. .ne(OperatorEntity::getStatus, OperatorStateEnum.Futility.getCode())
  287. .ne(OperatorEntity::getStatus, OperatorStateEnum.Assist.getCode())
  288. .eq(OperatorEntity::getCompletion, FlowNature.Normal).isNull(OperatorEntity::getHandleStatus);
  289. List<OperatorEntity> list = operatorService.list(queryWrapper);
  290. if (CollectionUtil.isNotEmpty(list)) {
  291. model.setHasReduceApproverBtn(true);
  292. }
  293. }
  294. // 审批撤回
  295. List<Integer> handleTypes = ImmutableList.of(RecordEnum.audit.getCode(), RecordEnum.reject.getCode());
  296. if (handleTypes.contains(recordEntity.getHandleType())) {
  297. flowModel.setFlag(FlowNature.ApprovalFlag);
  298. if (this.checkRecall(flowModel)) {
  299. model.setHasRecallAuditBtn(true);
  300. }
  301. }
  302. }
  303. flowMethod.setNodeModel(node);
  304. // 打印
  305. model.setHasPrintBtn(this.checkPrint(flowMethod));
  306. if (this.checkViewStartForm(global, node)) {
  307. model.setHasViewStartFormBtn(true);
  308. }
  309. }
  310. break;
  311. case Circulate: // 抄送事宜
  312. if (null != operatorEntity) {
  313. NodeModel node1 = nodes.get(operatorEntity.getNodeCode());
  314. if (this.checkViewStartForm(global, node1)) {
  315. model.setHasViewStartFormBtn(true);
  316. }
  317. }
  318. break;
  319. case Monitor: // 流程监控
  320. // 终止状态下只有复活
  321. if (ObjectUtil.equals(taskEntity.getStatus(), TaskStatusEnum.CANCEL.getCode())
  322. && ObjectUtil.equals(taskEntity.getParentId(), FlowNature.ParentId) && ObjectUtil.equals(template.getStatus(), TemplateStatueEnum.up.getCode())) {
  323. List<TriggerRecordEntity> triggerRecordList = triggerRecordService.getListByTaskId(taskEntity.getId());
  324. long count = triggerRecordList.stream().filter(e -> ObjectUtil.equals(e.getStatus(), TriggerRecordEnum.EXCEPTION.getCode())).count();
  325. if (count == 0) {
  326. model.setHasActivateBtn(true);
  327. }
  328. }
  329. // 挂起状态下只有恢复
  330. if (ObjectUtil.equals(taskEntity.getStatus(), TaskStatusEnum.PAUSED.getCode())) {
  331. if (!ObjectUtil.equals(taskEntity.getIsRestore(), FlowNature.NotRestore)) {
  332. model.setHasRebootBtn(true);
  333. }
  334. }
  335. // 运行状态下,终止、挂起
  336. if (ObjectUtil.equals(taskEntity.getStatus(), TaskStatusEnum.RUNNING.getCode())) {
  337. // 子流程不允许终止
  338. if (ObjectUtil.equals(taskEntity.getParentId(), FlowNature.ParentId)) {
  339. model.setHasCancelBtn(true);
  340. }
  341. model.setHasPauseBtn(true);
  342. if (this.checkAssign(taskEntity, nodes)) {
  343. model.setHasAssignBtn(true);
  344. }
  345. }
  346. // 归档按钮
  347. FileConfig config = global.getFileConfig();
  348. if (config.getOn() && StringUtil.isNotBlank(config.getTemplateId())) {
  349. if (ObjectUtil.isNotEmpty(taskEntity.getEndTime()) || ObjectUtil.equals(taskEntity.getStatus(), TaskStatusEnum.CANCEL.getCode())) {
  350. if (serviceUtil.checkFlowFile(taskEntity.getId())) {
  351. model.setHasFileBtn(true);
  352. }
  353. }
  354. }
  355. break;
  356. }
  357. return model;
  358. }
  359. // 判断指派,当前节点全是子流程,就隐藏
  360. public boolean checkAssign(TaskEntity taskEntity, Map<String, NodeModel> nodes) {
  361. String currentNodeCode = taskEntity.getCurrentNodeCode();
  362. if (StringUtil.isNotBlank(currentNodeCode)) {
  363. List<String> currentNodeList = Arrays.stream(currentNodeCode.split(",")).collect(Collectors.toList());
  364. for (String nodeCode : currentNodeList) {
  365. NodeModel nodeModel = nodes.get(nodeCode);
  366. if (null != nodeModel && !Objects.equals(nodeModel.getType(), NodeEnum.subFlow.getType())) {
  367. return true;
  368. }
  369. }
  370. }
  371. return false;
  372. }
  373. // 委托发起按钮
  374. public boolean checkDelegateSubmit(String userId, TemplateEntity template) {
  375. List<DelegateEntity> delegateList = delegateService.getByToUserId(userId, 0);
  376. if (CollectionUtil.isNotEmpty(delegateList) && ObjectUtil.equals(template.getStatus(), TemplateStatueEnum.up.getCode())) {
  377. for (DelegateEntity delegateEntity : delegateList) {
  378. String flowId = delegateEntity.getFlowId();
  379. if (StringUtil.isNotBlank(flowId)) {
  380. if (flowId.contains(template.getId())) {
  381. if (ObjectUtil.equals(template.getVisibleType(), FlowNature.All)) {
  382. return true;
  383. }
  384. List<String> launchPermission = serviceUtil.getPermission(delegateEntity.getUserId());
  385. if (launchPermission.contains(template.getId())) {
  386. return true;
  387. }
  388. }
  389. } else {
  390. // 全部流程
  391. if (ObjectUtil.equals(template.getVisibleType(), FlowNature.All)) {
  392. return true;
  393. }
  394. List<String> launchPermission = serviceUtil.getPermission(delegateEntity.getUserId());
  395. if (launchPermission.contains(template.getId())) {
  396. return true;
  397. }
  398. }
  399. }
  400. }
  401. return false;
  402. }
  403. /**
  404. * 查看发起表单
  405. */
  406. public boolean checkViewStartForm(NodeModel global, NodeModel nodeModel) {
  407. if (null != nodeModel) {
  408. if (global.getHasAloneConfigureForms() && StringUtil.isNotBlank(nodeModel.getFormId())) {
  409. return true;
  410. }
  411. }
  412. return false;
  413. }
  414. /**
  415. * 判断撤回
  416. *
  417. * @param flowModel 参数
  418. */
  419. public boolean checkRecall(FlowModel flowModel) throws WorkFlowException {
  420. String deploymentId = flowModel.getDeploymentId();
  421. String currentNodeCode = flowModel.getNodeEntity().getNodeCode();
  422. TaskEntity taskEntity = flowModel.getTaskEntity();
  423. RecordEntity recordEntity = flowModel.getRecordEntity();
  424. Map<String, NodeModel> nodes = flowModel.getNodes();
  425. // 判断撤回的标识 1.发起撤回 2.审批撤回
  426. int flag = flowModel.getFlag();
  427. boolean isException = flowModel.getIsException();
  428. NodeModel global = nodes.get(NodeEnum.global.getType());
  429. Integer recallRule = global.getRecallRule();
  430. // 全局撤回配置为1 直接不允许撤回 (流程撤回规则 1: 不允许撤回 2: 发起节点允许撤回 3:所有节点允许撤回)
  431. if (recallRule == null || Objects.equals(recallRule, FlowNature.NotAllowed)) {
  432. return false;
  433. }
  434. // 不是进行中的任务、存在退回冻结数据
  435. if (!Objects.equals(TaskStatusEnum.RUNNING.getCode(), taskEntity.getStatus()) || null != taskEntity.getRejectDataId()) {
  436. if (isException) {
  437. throw new WorkFlowException(MsgCode.WF036.get());
  438. }
  439. return false;
  440. }
  441. // 经办未审批 说明是已撤回的,不允许撤回
  442. OperatorEntity operator = operatorService.getInfo(recordEntity.getOperatorId());
  443. if (null != operator) {
  444. if (!ObjectUtil.equals(operator.getParentId(), FlowNature.ParentId)) {
  445. if (isException) {
  446. throw new WorkFlowException(MsgCode.WF077.get());
  447. }
  448. return false;
  449. }
  450. // 判断依次审批
  451. boolean inTurn = this.checkInTurn(operator, isException);
  452. if (!inTurn && !isException) {
  453. return false;
  454. }
  455. //判断逐级审批
  456. boolean inStep = this.checkStep(operator, isException);
  457. if (!inStep && !isException) {
  458. return false;
  459. }
  460. if (operator.getHandleStatus() == null) {
  461. if (isException) {
  462. throw new WorkFlowException(MsgCode.WF006.get());
  463. }
  464. return false;
  465. } else if (null == operator.getHandleTime()) {
  466. // 后加签的同意未真正审批,不允许撤回
  467. List<OperatorEntity> childList = operatorUtil.getChildList(operator.getId());
  468. if (CollectionUtil.isNotEmpty(childList)) {
  469. if (isException) {
  470. throw new WorkFlowException(MsgCode.WF006.get());
  471. }
  472. return false;
  473. }
  474. }
  475. } else {
  476. // 发起撤回的校验
  477. QueryWrapper<RecordEntity> recordWrapper = new QueryWrapper<>();
  478. recordWrapper.lambda().eq(RecordEntity::getTaskId, taskEntity.getId()).ne(RecordEntity::getStatus, FlowNature.Invalid);
  479. List<RecordEntity> recordList = recordService.list(recordWrapper);
  480. if (CollectionUtil.isNotEmpty(recordList)) {
  481. RecordEntity submit = recordList.stream().filter(e -> ObjectUtil.equals(e.getHandleType(), RecordEnum.submit.getCode())).findFirst().orElse(null);
  482. if (null != submit) {
  483. recordList = recordList.stream().filter(e -> !ObjectUtil.equals(e.getNodeCode(), submit.getNodeCode())).collect(Collectors.toList());
  484. }
  485. if (!recordList.isEmpty()) {
  486. if (isException) {
  487. throw new WorkFlowException(MsgCode.WF006.get());
  488. }
  489. return false;
  490. }
  491. }
  492. //外部节点
  493. List<EventLogEntity> eventLogList = eventLogService.getList(taskEntity.getId()).stream().filter(e -> Objects.equals(FlowNature.Success, e.getStatus())).collect(Collectors.toList());
  494. if (CollectionUtil.isNotEmpty(eventLogList)) {
  495. if (!eventLogList.isEmpty()) {
  496. if (isException) {
  497. throw new WorkFlowException(MsgCode.WF006.get());
  498. }
  499. return false;
  500. }
  501. }
  502. }
  503. // 获取节点的下一级节点,判断撤回
  504. NextOrPrevFo fo = new NextOrPrevFo();
  505. fo.setDeploymentId(deploymentId);
  506. fo.setTaskKey(currentNodeCode);
  507. List<FlowableNodeModel> nextModels = flowAbleUrl.getNext(fo);
  508. List<String> nextCodes = nextModels.stream().map(FlowableNodeModel::getId).collect(Collectors.toList());
  509. // 审批撤回需要用到下一级节点
  510. flowModel.setNextCodes(nextCodes);
  511. if (CollectionUtil.isNotEmpty(nextCodes)) {
  512. QueryWrapper<TaskEntity> queryWrapper = new QueryWrapper<>();
  513. queryWrapper.lambda().eq(TaskEntity::getParentId, taskEntity.getId())
  514. .in(TaskEntity::getSubCode, nextCodes);
  515. List<TaskEntity> list = taskService.list(queryWrapper);
  516. if (CollectionUtil.isNotEmpty(list)) {
  517. // 异步子流程,不允许撤回
  518. long asyncCount = list.stream().filter(e -> Objects.equals(e.getIsAsync(), FlowNature.ChildAsync)).count();
  519. if (asyncCount > 0) {
  520. return false;
  521. }
  522. long count = list.stream().filter(e -> !Objects.equals(e.getStatus(), TaskStatusEnum.TO_BE_SUBMIT.getCode())).count();
  523. if (count > 0) {
  524. if (isException) {
  525. throw new WorkFlowException(MsgCode.WF036.get());
  526. }
  527. return false;
  528. }
  529. }
  530. //外部节点只要有成功数据,不允许撤回
  531. List<EventLogEntity> eventLogList = eventLogService.getList(taskEntity.getId(), nextCodes).stream().filter(e -> Objects.equals(FlowNature.Success, e.getStatus())).collect(Collectors.toList());
  532. if (CollectionUtil.isNotEmpty(eventLogList)) {
  533. if (!eventLogList.isEmpty()) {
  534. if (isException) {
  535. throw new WorkFlowException(MsgCode.WF006.get());
  536. }
  537. return false;
  538. }
  539. }
  540. }
  541. if (Objects.equals(flag, FlowNature.ApprovalFlag) && Objects.equals(recallRule, FlowNature.StartAllowed)) {
  542. return false;
  543. }
  544. if (CollectionUtil.isEmpty(nextCodes)) {
  545. return true;
  546. }
  547. // 存在已办理的经办,撤回后可以重新提交(下个审批节点只进行了签收 此时还可以撤回)
  548. QueryWrapper<OperatorEntity> wrapper = new QueryWrapper<>();
  549. wrapper.lambda().eq(OperatorEntity::getTaskId, taskEntity.getId());
  550. if (CollectionUtil.isNotEmpty(nextCodes)) {
  551. wrapper.lambda().in(OperatorEntity::getNodeCode, nextCodes);
  552. }
  553. wrapper.lambda().orderByDesc(OperatorEntity::getCreatorTime);
  554. List<OperatorEntity> list = operatorService.list(wrapper);
  555. boolean mark = this.checkDraftAndRecord(list);
  556. if (mark) {
  557. if (isException) {
  558. throw new WorkFlowException(MsgCode.WF077.get());
  559. }
  560. return false;
  561. }
  562. //todo 2025-01-23 加签和被加签人不能撤回
  563. if (operator != null) {
  564. if (!Objects.equals(operator.getParentId(), FlowNature.ParentId)) {
  565. return false;
  566. }
  567. if (StringUtil.isNotEmpty(operator.getHandleParameter())) {
  568. return false;
  569. }
  570. }
  571. return true;
  572. }
  573. // 依次审批的撤回判断
  574. public boolean checkInTurn(OperatorEntity operator, boolean isException) throws WorkFlowException {
  575. if (StringUtil.isNotBlank(operator.getHandleAll())) {
  576. List<String> handleIds = Arrays.stream(operator.getHandleAll().split(",")).collect(Collectors.toList());
  577. int index = handleIds.indexOf(operator.getHandleId());
  578. if (index != -1 && index < handleIds.size() - 1) {
  579. String nextHandleId = handleIds.get(index + 1);
  580. QueryWrapper<OperatorEntity> queryWrapper = new QueryWrapper<>();
  581. queryWrapper.lambda().eq(OperatorEntity::getHandleId, nextHandleId).eq(OperatorEntity::getParentId, operator.getParentId())
  582. .eq(OperatorEntity::getNodeId, operator.getNodeId()).orderByDesc(OperatorEntity::getCreatorTime);
  583. List<OperatorEntity> list = operatorService.list(queryWrapper);
  584. if (CollectionUtil.isNotEmpty(list)) {
  585. OperatorEntity nextOperator = list.get(0);
  586. if (StringUtil.isNotEmpty(nextOperator.getDraftData())) {
  587. if (isException) {
  588. throw new WorkFlowException(MsgCode.WF036.get());
  589. }
  590. return false;
  591. }
  592. QueryWrapper<RecordEntity> recordWrapper = new QueryWrapper<>();
  593. recordWrapper.lambda().eq(RecordEntity::getOperatorId, nextOperator.getId()).ne(RecordEntity::getStatus, FlowNature.Invalid);
  594. List<RecordEntity> recordList = recordService.list(recordWrapper);
  595. if (CollectionUtil.isNotEmpty(recordList)) {
  596. if (isException) {
  597. throw new WorkFlowException(MsgCode.WF036.get());
  598. }
  599. return false;
  600. }
  601. }
  602. }
  603. }
  604. return true;
  605. }
  606. // 逐级审批的撤回判断
  607. public boolean checkStep(OperatorEntity operator, boolean isException) throws WorkFlowException {
  608. QueryWrapper<OperatorEntity> queryWrapper = new QueryWrapper<>();
  609. queryWrapper.lambda().eq(OperatorEntity::getHandleAll, operator.getId())
  610. .eq(OperatorEntity::getTaskId, operator.getTaskId());
  611. List<OperatorEntity> list = operatorService.list(queryWrapper);
  612. if (CollectionUtil.isNotEmpty(list)) {
  613. OperatorEntity nextOperator = list.get(0);
  614. if (StringUtil.isNotEmpty(nextOperator.getDraftData())) {
  615. if (isException) {
  616. throw new WorkFlowException(MsgCode.WF036.get());
  617. }
  618. return false;
  619. }
  620. QueryWrapper<RecordEntity> recordWrapper = new QueryWrapper<>();
  621. recordWrapper.lambda().eq(RecordEntity::getOperatorId, nextOperator.getId()).ne(RecordEntity::getStatus, FlowNature.Invalid);
  622. List<RecordEntity> recordList = recordService.list(recordWrapper);
  623. if (CollectionUtil.isNotEmpty(recordList)) {
  624. if (isException) {
  625. throw new WorkFlowException(MsgCode.WF036.get());
  626. }
  627. return false;
  628. }
  629. }
  630. return true;
  631. }
  632. public boolean checkDraftAndRecord(List<OperatorEntity> list) {
  633. return this.checkDraftAndRecord(list, false);
  634. }
  635. // 判断草稿、操作记录
  636. public boolean checkDraftAndRecord(List<OperatorEntity> list, boolean filterAddSign) {
  637. list = list.stream().filter(e -> !ObjectUtil.equals(e.getStatus(), OperatorStateEnum.Futility.getCode())).collect(Collectors.toList());
  638. if (CollectionUtil.isEmpty(list)) {
  639. return false;
  640. }
  641. // if (CollectionUtil.isNotEmpty(list)) {
  642. // // 回流的处理
  643. // OperatorEntity first = list.get(0);
  644. // list = list.stream().filter(e -> ObjectUtil.equals(first.getNodeId(), e.getNodeId())).collect(Collectors.toList());
  645. // }
  646. // 只要有操作就不让撤回,草稿数据(暂存)
  647. long draftCount = list.stream().filter(e -> StringUtil.isNotEmpty(e.getDraftData())).count();
  648. boolean mark = false;
  649. // 不存在草稿数据,继续根据记录判断
  650. if (draftCount == 0) {
  651. List<String> collect = list.stream().map(OperatorEntity::getId).collect(Collectors.toList());
  652. if (CollectionUtil.isNotEmpty(collect)) {
  653. QueryWrapper<RecordEntity> recordWrapper = new QueryWrapper<>();
  654. recordWrapper.lambda().in(RecordEntity::getOperatorId, collect).ne(RecordEntity::getStatus, FlowNature.Invalid);
  655. List<RecordEntity> recordList = recordService.list(recordWrapper);
  656. if (filterAddSign) {
  657. List<Integer> status = ImmutableList.of(RecordEnum.addSign.getCode(), RecordEnum.subtractSign.getCode());
  658. recordList = recordList.stream().filter(e -> !status.contains(e.getHandleType())).collect(Collectors.toList());
  659. }
  660. mark = !recordList.isEmpty();
  661. }
  662. } else {
  663. mark = true;
  664. }
  665. return mark;
  666. }
  667. /**
  668. * 判断打印
  669. */
  670. public boolean checkPrint(FlowMethod flowMethod) {
  671. NodeModel nodeModel = flowMethod.getNodeModel();
  672. TaskEntity taskEntity = flowMethod.getTaskEntity();
  673. Map<String, Object> formData = flowMethod.getFormData();
  674. List<TaskNodeModel> nodeList = flowMethod.getPrintNodeList();
  675. // 发起除了草稿状态都显示
  676. if (Objects.equals(taskEntity.getStatus(), TaskStatusEnum.TO_BE_SUBMIT.getCode())) {
  677. return false;
  678. }
  679. PrintConfig printConfig = nodeModel.getPrintConfig();
  680. if (printConfig.getOn()) {
  681. // 打印没有选择模版,按钮不显示
  682. if (CollectionUtil.isEmpty(printConfig.getPrintIds())) {
  683. return false;
  684. }
  685. switch (PrintEnum.getPrint(printConfig.getConditionType())) {
  686. case none:
  687. // 不限制
  688. return true;
  689. case nodeEnd:
  690. // 节点结束
  691. // 开始节点直接返回true,除草稿状态
  692. if (nodeModel.getType().equals(NodeEnum.start.getType())
  693. && !taskEntity.getStatus().equals(TaskStatusEnum.TO_BE_SUBMIT.getCode())) {
  694. return true;
  695. }
  696. TaskNodeModel taskNode = nodeList.stream().filter(e -> e.getNodeCode().equals(nodeModel.getNodeId())).findFirst().orElse(null);
  697. if (null != taskNode && taskNode.getType().equals(NodeTypeEnum.pass.getType())) {
  698. return true;
  699. }
  700. break;
  701. case flowEnd:
  702. // 流程结束
  703. List<Integer> status = ImmutableList.of(TaskStatusEnum.PASSED.getCode(), TaskStatusEnum.REJECTED.getCode());
  704. if (status.contains(taskEntity.getStatus())) {
  705. return true;
  706. }
  707. break;
  708. case conditions:
  709. // 条件设置
  710. List<ProperCond> conditions = printConfig.getConditions();
  711. String matchLogic = printConfig.getMatchLogic();
  712. UserInfo userInfo = UserProvider.getUser();
  713. flowMethod.setUserInfo(userInfo);
  714. flowMethod.setUserEntity(serviceUtil.getUserInfo(userInfo.getUserId()));
  715. flowMethod.setConditions(conditions);
  716. flowMethod.setMatchLogic(matchLogic);
  717. if (FlowJsonUtil.nodeConditionDecide(flowMethod)) {
  718. return true;
  719. }
  720. break;
  721. }
  722. }
  723. return false;
  724. }
  725. /**
  726. * 判断加签
  727. */
  728. public void checkAddSign(OperatorEntity operator, AddSignModel parameter) throws WorkFlowException {
  729. this.checkAddSign(operator, parameter, true);
  730. }
  731. public boolean checkAddSign(OperatorEntity operator, AddSignModel parameter, Boolean isException) throws WorkFlowException {
  732. int level = 1;
  733. if (!ObjectUtil.equals(operator.getParentId(), FlowNature.ParentId)) {
  734. OperatorEntity parent = operatorService.getById(operator.getParentId());
  735. if (null != parent) {
  736. String handleParameter = parent.getHandleParameter() == null ? operator.getHandleParameter() : parent.getHandleParameter();
  737. AddSignModel jsonToBean = JsonUtil.getJsonToBean(handleParameter, AddSignModel.class);
  738. level = jsonToBean.getLevel() + 1;
  739. }
  740. }
  741. SysConfigModel sysConfig = serviceUtil.getSysConfig();
  742. Integer addSignLevel = sysConfig.getAddSignLevel();
  743. if (level > addSignLevel) {
  744. if (isException) {
  745. throw new WorkFlowException(MsgCode.WF143.get());
  746. }
  747. return false;
  748. }
  749. if (null != parameter) {
  750. parameter.setLevel(level);
  751. }
  752. return true;
  753. }
  754. }