|
|
@@ -38,16 +38,13 @@ import com.srm.bpm.logic.dto.UserInfoDTO;
|
|
38
|
38
|
import com.srm.bpm.logic.dto.UserOrgDTO;
|
|
39
|
39
|
import com.srm.bpm.logic.dto.UserPositionDTO;
|
|
40
|
40
|
import com.srm.bpm.logic.error.BillCode;
|
|
41
|
|
-import com.srm.bpm.logic.service.BillBpmnLogic;
|
|
42
|
|
-import com.srm.bpm.logic.service.BillItemLogic;
|
|
43
|
|
-import com.srm.bpm.logic.service.CallBackLogic;
|
|
44
|
|
-import com.srm.bpm.logic.service.FlowMsgLogic;
|
|
45
|
|
-import com.srm.bpm.logic.service.UserCenterlogic;
|
|
|
41
|
+import com.srm.bpm.logic.service.*;
|
|
46
|
42
|
import com.srm.bpm.logic.vo.FormPermissionVO;
|
|
47
|
43
|
import com.srm.bpm.logic.constant.FormConst;
|
|
48
|
44
|
import com.srm.common.data.exception.RbException;
|
|
49
|
45
|
import com.srm.common.util.datetime.DateTimeUtil;
|
|
50
|
46
|
|
|
|
47
|
+import com.srm.config.SpringContextHolder;
|
|
51
|
48
|
import org.activiti.bpmn.model.BpmnModel;
|
|
52
|
49
|
import org.activiti.bpmn.model.FlowElement;
|
|
53
|
50
|
import org.activiti.bpmn.model.FlowNode;
|
|
|
@@ -484,7 +481,7 @@ public class BillBpmnLogicImpl implements BillBpmnLogic {
|
|
484
|
481
|
// if (task == null) {
|
|
485
|
482
|
// throw new RbException(BillCode.TASK_NOT_FOUND);
|
|
486
|
483
|
// }
|
|
487
|
|
- Map<String, Object> variables = Maps.newHashMap();
|
|
|
484
|
+ /*Map<String, Object> variables = Maps.newHashMap();
|
|
488
|
485
|
variables.put(BpmnConst.VAR_OPINION, opinion);
|
|
489
|
486
|
variables.put(BpmnConst.VAR_APPROVER_EMPLOYEE, userCode);
|
|
490
|
487
|
variables.put(BpmnConst.VAR_ACTION, BillAction.agree.name());
|
|
|
@@ -493,10 +490,265 @@ public class BillBpmnLogicImpl implements BillBpmnLogic {
|
|
493
|
490
|
variables.put(BpmnConst.VAR_LAST_TASK_ID, lastTaskId);
|
|
494
|
491
|
variables.put(BpmnConst.VAR_AGREE_DATA, JSON.parseObject(formData, Map.class));
|
|
495
|
492
|
taskService.complete(taskId, variables);
|
|
496
|
|
- return true;
|
|
|
493
|
+ return true;*/
|
|
|
494
|
+
|
|
|
495
|
+ // 先检查运行时任务是否存在
|
|
|
496
|
+ final Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
|
|
|
497
|
+ if (task == null) {
|
|
|
498
|
+ // 检查历史任务,看是否已经完成
|
|
|
499
|
+ final org.activiti.engine.history.HistoricTaskInstance historicTask = historyService
|
|
|
500
|
+ .createHistoricTaskInstanceQuery()
|
|
|
501
|
+ .taskId(taskId)
|
|
|
502
|
+ .singleResult();
|
|
|
503
|
+ if (historicTask != null) {
|
|
|
504
|
+ log.warn("任务已经完成,跳过完成操作。taskId: {}, billId: {}, 完成时间: {}",
|
|
|
505
|
+ taskId, bill != null ? bill.getId() : null, historicTask.getEndTime());
|
|
|
506
|
+ // 检查归档条件并触发回调
|
|
|
507
|
+ checkAndTriggerArchiveCallback(bill, taskId);
|
|
|
508
|
+ // 检查流程是否应该结束
|
|
|
509
|
+ checkAndCompleteBillIfNeeded(bill);
|
|
|
510
|
+ return true;
|
|
|
511
|
+ } else {
|
|
|
512
|
+ log.warn("Activiti任务不存在,可能已经被删除。taskId: {}, billId: {},跳过完成操作。业务数据已更新。",
|
|
|
513
|
+ taskId, bill != null ? bill.getId() : null);
|
|
|
514
|
+ // 检查归档条件并触发回调
|
|
|
515
|
+ checkAndTriggerArchiveCallback(bill, taskId);
|
|
|
516
|
+ // 检查流程是否应该结束
|
|
|
517
|
+ checkAndCompleteBillIfNeeded(bill);
|
|
|
518
|
+ return true; // 业务数据已更新,返回成功
|
|
|
519
|
+ }
|
|
|
520
|
+ }
|
|
|
521
|
+
|
|
|
522
|
+ Map<String, Object> variables = Maps.newHashMap();
|
|
|
523
|
+ variables.put(BpmnConst.VAR_OPINION, opinion);
|
|
|
524
|
+ variables.put(BpmnConst.VAR_APPROVER_EMPLOYEE, userCode);
|
|
|
525
|
+ variables.put(BpmnConst.VAR_ACTION, BillAction.agree.name());
|
|
|
526
|
+ variables.put(BpmnConst.VAR_NEXT_APPROVER, nextApprover);
|
|
|
527
|
+ variables.put(BpmnConst.VAR_LAST_NODE_KEY, lastTaskNodeId);
|
|
|
528
|
+ variables.put(BpmnConst.VAR_LAST_TASK_ID, lastTaskId);
|
|
|
529
|
+ // 安全处理 formData,避免空值或 null 导致解析失败
|
|
|
530
|
+ if (!Strings.isNullOrEmpty(formData) && !"null".equals(formData) && !"{}".equals(formData)) {
|
|
|
531
|
+ try {
|
|
|
532
|
+ variables.put(BpmnConst.VAR_AGREE_DATA, JSON.parseObject(formData, Map.class));
|
|
|
533
|
+ } catch (Exception e) {
|
|
|
534
|
+ log.warn("解析 formData 失败,使用空 Map。billId: {}, taskId: {}, formData: {}",
|
|
|
535
|
+ bill != null ? bill.getId() : null, taskId, formData);
|
|
|
536
|
+ variables.put(BpmnConst.VAR_AGREE_DATA, Maps.newHashMap());
|
|
|
537
|
+ }
|
|
|
538
|
+ } else {
|
|
|
539
|
+ variables.put(BpmnConst.VAR_AGREE_DATA, Maps.newHashMap());
|
|
|
540
|
+ }
|
|
|
541
|
+
|
|
|
542
|
+ try {
|
|
|
543
|
+ taskService.complete(taskId, variables);
|
|
|
544
|
+
|
|
|
545
|
+ // 任务完成后,先检查归档条件并触发回调
|
|
|
546
|
+ checkAndTriggerArchiveCallback(bill, taskId);
|
|
|
547
|
+
|
|
|
548
|
+ // 任务完成后,立即检查流程是否结束,如果结束则触发回调
|
|
|
549
|
+ if (bill != null && bill.getId() != null) {
|
|
|
550
|
+ final String processInstanceId = bill.getProcessInstanceId();
|
|
|
551
|
+ if (!Strings.isNullOrEmpty(processInstanceId)) {
|
|
|
552
|
+ // 先检查运行时流程实例是否还有待办任务
|
|
|
553
|
+ final List<Task> activeTasks = taskService.createTaskQuery()
|
|
|
554
|
+ .processInstanceId(processInstanceId)
|
|
|
555
|
+ .active()
|
|
|
556
|
+ .list();
|
|
|
557
|
+
|
|
|
558
|
+ // 如果没有待办任务,检查流程是否已结束
|
|
|
559
|
+ if (CollectionUtil.isEmpty(activeTasks)) {
|
|
|
560
|
+ // 检查历史流程实例是否已结束
|
|
|
561
|
+ final org.activiti.engine.history.HistoricProcessInstance historicProcessInstance = historyService
|
|
|
562
|
+ .createHistoricProcessInstanceQuery()
|
|
|
563
|
+ .processInstanceId(processInstanceId)
|
|
|
564
|
+ .singleResult();
|
|
|
565
|
+
|
|
|
566
|
+ if (historicProcessInstance != null && historicProcessInstance.getEndTime() != null) {
|
|
|
567
|
+ // 流程已结束,立即触发完成逻辑和回调
|
|
|
568
|
+ log.info("任务完成后,检测到流程已结束(没有待办任务且历史流程实例已结束)。立即触发审批单完成逻辑和回调。billId: {}, taskId: {}",
|
|
|
569
|
+ bill.getId(), taskId);
|
|
|
570
|
+ triggerBillCompleteCallback(bill);
|
|
|
571
|
+ return true;
|
|
|
572
|
+ }
|
|
|
573
|
+ }
|
|
|
574
|
+ }
|
|
|
575
|
+ }
|
|
|
576
|
+
|
|
|
577
|
+ // 如果流程未结束,检查是否应该结束(用于处理没有Activiti任务但业务任务已完成的情况)
|
|
|
578
|
+ checkAndCompleteBillIfNeeded(bill);
|
|
|
579
|
+ return true;
|
|
|
580
|
+ } catch (org.activiti.engine.ActivitiObjectNotFoundException e) {
|
|
|
581
|
+ log.warn("完成Activiti任务时发生异常,任务可能已被删除。taskId: {}, billId: {}, 错误: {}",
|
|
|
582
|
+ taskId, bill != null ? bill.getId() : null, e.getMessage());
|
|
|
583
|
+ // 检查归档条件并触发回调
|
|
|
584
|
+ checkAndTriggerArchiveCallback(bill, taskId);
|
|
|
585
|
+ // 业务数据已更新,检查流程是否应该结束
|
|
|
586
|
+ checkAndCompleteBillIfNeeded(bill);
|
|
|
587
|
+ return true;
|
|
|
588
|
+ }
|
|
|
589
|
+
|
|
497
|
590
|
}
|
|
498
|
591
|
|
|
499
|
592
|
/**
|
|
|
593
|
+ * 检查归档条件并触发回调
|
|
|
594
|
+ * 如果 toa_bill 的 status 为 1(审批中)且 bill_task 的最后一个节点审批状态为 2(已同意),则触发回调
|
|
|
595
|
+ *
|
|
|
596
|
+ * @param bill 审批单实体
|
|
|
597
|
+ * @param taskId 任务ID
|
|
|
598
|
+ */
|
|
|
599
|
+ private void checkAndTriggerArchiveCallback(ToaBillEntity bill, String taskId) {
|
|
|
600
|
+ if (bill == null || bill.getId() == null) {
|
|
|
601
|
+ return;
|
|
|
602
|
+ }
|
|
|
603
|
+
|
|
|
604
|
+ try {
|
|
|
605
|
+ // 重新查询最新的bill数据,确保使用最新状态
|
|
|
606
|
+ final ToaBillEntity latestBill = billService.getById(bill.getId());
|
|
|
607
|
+ if (latestBill == null) {
|
|
|
608
|
+ return;
|
|
|
609
|
+ }
|
|
|
610
|
+
|
|
|
611
|
+ // 检查 toa_bill 的 status 是否为 1(审批中)
|
|
|
612
|
+ if (latestBill.getStatus() != BillStatus.APPROVAL.getStatus()) {
|
|
|
613
|
+ return;
|
|
|
614
|
+ }
|
|
|
615
|
+
|
|
|
616
|
+ // 查找最后一个节点的 bill_task,按 sort 降序排列取第一个
|
|
|
617
|
+ final List<BillTaskEntity> billTasks = billTaskService.list(
|
|
|
618
|
+ com.baomidou.mybatisplus.core.toolkit.Wrappers.lambdaQuery(BillTaskEntity.class)
|
|
|
619
|
+ .eq(BillTaskEntity::getBillId, latestBill.getId())
|
|
|
620
|
+ .eq(BillTaskEntity::getIsDeleted, 0)
|
|
|
621
|
+ .orderByDesc(BillTaskEntity::getSort)
|
|
|
622
|
+ .last("LIMIT 1")
|
|
|
623
|
+ );
|
|
|
624
|
+
|
|
|
625
|
+ if (CollectionUtil.isEmpty(billTasks)) {
|
|
|
626
|
+ return;
|
|
|
627
|
+ }
|
|
|
628
|
+
|
|
|
629
|
+ final BillTaskEntity lastTask = billTasks.get(0);
|
|
|
630
|
+
|
|
|
631
|
+ // 检查最后一个节点的审批状态是否为 2(已同意)
|
|
|
632
|
+ if (lastTask.getNodeStatus() == BillTaskStatus.AGREE.getStatus()) {
|
|
|
633
|
+ // 检查最后一个任务是否是归档节点
|
|
|
634
|
+ final Long processId = latestBill.getProcessId();
|
|
|
635
|
+ if (processId != null && !Strings.isNullOrEmpty(lastTask.getTaskNodeKey())) {
|
|
|
636
|
+ final Optional<ProcessNodeExtendEntity> nodeExtendOpt = nodeExtendService
|
|
|
637
|
+ .findByNodeIdAndProcessId(processId, lastTask.getTaskNodeKey());
|
|
|
638
|
+
|
|
|
639
|
+ if (nodeExtendOpt.isPresent()) {
|
|
|
640
|
+ final ProcessNodeExtendEntity nodeExtend = nodeExtendOpt.get();
|
|
|
641
|
+ final String linkType = nodeExtend.getLinkType();
|
|
|
642
|
+
|
|
|
643
|
+ // 如果是归档节点,触发回调
|
|
|
644
|
+ if (NodeLinkType.archive.name().equals(linkType)) {
|
|
|
645
|
+ log.info("检测到归档节点且满足条件:toa_bill status=1(审批中),最后一个节点 status=2(已同意)。触发回调。billId: {}, taskId: {}, lastTaskNodeKey: {}",
|
|
|
646
|
+ latestBill.getId(), taskId, lastTask.getTaskNodeKey());
|
|
|
647
|
+ triggerBillCompleteCallback(latestBill);
|
|
|
648
|
+ }
|
|
|
649
|
+ }
|
|
|
650
|
+ }
|
|
|
651
|
+ }
|
|
|
652
|
+ } catch (Exception e) {
|
|
|
653
|
+ log.error("检查归档条件并触发回调时发生异常。billId: {}, taskId: {}, 错误: {}",
|
|
|
654
|
+ bill != null ? bill.getId() : null, taskId, e.getMessage(), e);
|
|
|
655
|
+ }
|
|
|
656
|
+ }
|
|
|
657
|
+
|
|
|
658
|
+ /**
|
|
|
659
|
+ * 触发审批单完成逻辑和回调
|
|
|
660
|
+ *
|
|
|
661
|
+ * @param bill 审批单实体
|
|
|
662
|
+ */
|
|
|
663
|
+ private void triggerBillCompleteCallback(ToaBillEntity bill) {
|
|
|
664
|
+ if (bill == null || bill.getId() == null) {
|
|
|
665
|
+ return;
|
|
|
666
|
+ }
|
|
|
667
|
+
|
|
|
668
|
+ try {
|
|
|
669
|
+ log.info("触发审批单完成逻辑和回调。billId: {}", bill.getId());
|
|
|
670
|
+ final BillLogic billLogic = SpringContextHolder.getBean(BillLogic.class);
|
|
|
671
|
+ // 重新查询最新的bill数据,确保使用最新状态
|
|
|
672
|
+ final ToaBillEntity latestBill = billService.getById(bill.getId());
|
|
|
673
|
+ if (latestBill != null && latestBill.getStatus() != BillStatus.COMPLETE.getStatus()) {
|
|
|
674
|
+ billLogic.complete(latestBill, BillAction.agree.name());
|
|
|
675
|
+ log.info("已成功触发审批单完成逻辑和回调。billId: {}", bill.getId());
|
|
|
676
|
+ } else if (latestBill != null && latestBill.getStatus() == BillStatus.COMPLETE.getStatus()) {
|
|
|
677
|
+ log.debug("审批单已完成,无需再次触发。billId: {}", bill.getId());
|
|
|
678
|
+ }
|
|
|
679
|
+ } catch (Exception e) {
|
|
|
680
|
+ log.error("触发审批单完成逻辑和回调时发生异常。billId: {}, 错误: {}", bill.getId(), e.getMessage(), e);
|
|
|
681
|
+ }
|
|
|
682
|
+ }
|
|
|
683
|
+
|
|
|
684
|
+ /**
|
|
|
685
|
+ * 检查审批单是否应该完成,如果是最后一个节点且没有待审批任务,则完成审批单
|
|
|
686
|
+ *
|
|
|
687
|
+ * @param bill 审批单实体
|
|
|
688
|
+ */
|
|
|
689
|
+ public void checkAndCompleteBillIfNeeded(ToaBillEntity bill) {
|
|
|
690
|
+ if (bill == null || bill.getId() == null) {
|
|
|
691
|
+ return;
|
|
|
692
|
+ }
|
|
|
693
|
+
|
|
|
694
|
+ try {
|
|
|
695
|
+ // 先检查是否有待审批的bill_task
|
|
|
696
|
+ final List<BillTaskEntity> approvalTasks = billTaskService.list(
|
|
|
697
|
+ com.baomidou.mybatisplus.core.toolkit.Wrappers.lambdaQuery(BillTaskEntity.class)
|
|
|
698
|
+ .eq(BillTaskEntity::getBillId, bill.getId())
|
|
|
699
|
+ .eq(BillTaskEntity::getNodeStatus, BillTaskStatus.APPROVAL.getStatus())
|
|
|
700
|
+ .eq(BillTaskEntity::getIsDeleted, 0)
|
|
|
701
|
+ );
|
|
|
702
|
+
|
|
|
703
|
+ // 如果没有待审批任务,说明所有任务都已完成
|
|
|
704
|
+ if (CollectionUtil.isEmpty(approvalTasks)) {
|
|
|
705
|
+ // 检查流程实例状态
|
|
|
706
|
+ final String processInstanceId = bill.getProcessInstanceId();
|
|
|
707
|
+ boolean shouldComplete = false;
|
|
|
708
|
+
|
|
|
709
|
+ if (!Strings.isNullOrEmpty(processInstanceId)) {
|
|
|
710
|
+ // 检查运行时流程实例是否还有待办任务
|
|
|
711
|
+ final List<Task> activeTasks = taskService.createTaskQuery()
|
|
|
712
|
+ .processInstanceId(processInstanceId)
|
|
|
713
|
+ .active()
|
|
|
714
|
+ .list();
|
|
|
715
|
+
|
|
|
716
|
+ if (CollectionUtil.isEmpty(activeTasks)) {
|
|
|
717
|
+ // 没有运行时待办任务,检查历史流程实例是否已结束
|
|
|
718
|
+ final org.activiti.engine.history.HistoricProcessInstance historicProcessInstance = historyService
|
|
|
719
|
+ .createHistoricProcessInstanceQuery()
|
|
|
720
|
+ .processInstanceId(processInstanceId)
|
|
|
721
|
+ .singleResult();
|
|
|
722
|
+
|
|
|
723
|
+ if (historicProcessInstance != null && historicProcessInstance.getEndTime() != null) {
|
|
|
724
|
+ // 流程已结束
|
|
|
725
|
+ log.info("流程实例已结束,但审批单状态未更新。billId: {}, processInstanceId: {}", bill.getId(), processInstanceId);
|
|
|
726
|
+ shouldComplete = true;
|
|
|
727
|
+ } else {
|
|
|
728
|
+ // 流程实例不存在或未结束,但也没有待办任务和待审批任务,应该完成
|
|
|
729
|
+ log.info("没有待办任务和待审批任务,流程应该结束。billId: {}, processInstanceId: {}", bill.getId(), processInstanceId);
|
|
|
730
|
+ shouldComplete = true;
|
|
|
731
|
+ }
|
|
|
732
|
+ }
|
|
|
733
|
+ } else {
|
|
|
734
|
+ // 流程实例ID为空,但所有bill_task都已完成,应该完成审批单
|
|
|
735
|
+ log.info("流程实例ID为空,但所有任务都已完成,应该完成审批单。billId: {}", bill.getId());
|
|
|
736
|
+ shouldComplete = true;
|
|
|
737
|
+ }
|
|
|
738
|
+
|
|
|
739
|
+ if (shouldComplete && bill.getStatus() != BillStatus.COMPLETE.getStatus()) {
|
|
|
740
|
+ // 审批单状态不是完成,需要触发完成逻辑和回调
|
|
|
741
|
+ log.info("检测到流程应该结束,但审批单状态未更新。手动触发审批单完成逻辑和回调。billId: {}, 当前状态: {}",
|
|
|
742
|
+ bill.getId(), bill.getStatus());
|
|
|
743
|
+ triggerBillCompleteCallback(bill);
|
|
|
744
|
+ }
|
|
|
745
|
+ }
|
|
|
746
|
+ } catch (Exception e) {
|
|
|
747
|
+ log.error("检查审批单完成状态时发生异常。billId: {}, 错误: {}", bill.getId(), e.getMessage(), e);
|
|
|
748
|
+ }
|
|
|
749
|
+ }
|
|
|
750
|
+
|
|
|
751
|
+ /**
|
|
500
|
752
|
* 审批拒绝接口
|
|
501
|
753
|
*
|
|
502
|
754
|
* @param taskId 审批任务
|