|
@@ -5,7 +5,9 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper; |
|
@@ -5,7 +5,9 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper; |
|
5
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
5
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
|
6
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
6
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
7
|
import com.github.pagehelper.PageInfo;
|
7
|
import com.github.pagehelper.PageInfo;
|
|
|
|
8
|
+import com.lframework.starter.bpm.entity.FlowInstanceWrapper;
|
|
8
|
import com.lframework.starter.bpm.service.FlowInstanceWrapperService;
|
9
|
import com.lframework.starter.bpm.service.FlowInstanceWrapperService;
|
|
|
|
10
|
+import com.lframework.starter.bpm.service.FlowTaskWrapperService;
|
|
9
|
import com.lframework.starter.common.exceptions.impl.DefaultClientException;
|
11
|
import com.lframework.starter.common.exceptions.impl.DefaultClientException;
|
|
10
|
import com.lframework.starter.common.exceptions.impl.InputErrorException;
|
12
|
import com.lframework.starter.common.exceptions.impl.InputErrorException;
|
|
11
|
import com.lframework.starter.common.utils.Assert;
|
13
|
import com.lframework.starter.common.utils.Assert;
|
|
@@ -63,6 +65,8 @@ public class ProcurementPlanServiceImpl extends BaseMpServiceImpl<ProcurementPla |
|
@@ -63,6 +65,8 @@ public class ProcurementPlanServiceImpl extends BaseMpServiceImpl<ProcurementPla |
|
63
|
private WorkshopService workshopService;
|
65
|
private WorkshopService workshopService;
|
|
64
|
@Resource
|
66
|
@Resource
|
|
65
|
private FlowInstanceWrapperService flowInstanceWrapperService;
|
67
|
private FlowInstanceWrapperService flowInstanceWrapperService;
|
|
|
|
68
|
+ @Resource
|
|
|
|
69
|
+ private FlowTaskWrapperService flowTaskWrapperService;
|
|
66
|
|
70
|
|
|
67
|
@Override
|
71
|
@Override
|
|
68
|
public PageResult<ProcurementPlan> query(Integer pageIndex, Integer pageSize,
|
72
|
public PageResult<ProcurementPlan> query(Integer pageIndex, Integer pageSize,
|
|
@@ -425,6 +429,107 @@ public class ProcurementPlanServiceImpl extends BaseMpServiceImpl<ProcurementPla |
|
@@ -425,6 +429,107 @@ public class ProcurementPlanServiceImpl extends BaseMpServiceImpl<ProcurementPla |
|
425
|
}
|
429
|
}
|
|
426
|
|
430
|
|
|
427
|
/**
|
431
|
/**
|
|
|
|
432
|
+ * 中止采购计划
|
|
|
|
433
|
+ * 规则:
|
|
|
|
434
|
+ * 1. 选择分厂后的任意环节可发起中止
|
|
|
|
435
|
+ * 2. 子计划发起中止 → 对应主计划下所有子计划全部中止
|
|
|
|
436
|
+ * 3. 主计划下只要有1个已完成(COMPLETED)子计划,不允许中止
|
|
|
|
437
|
+ * 4. 审核中(AUDIT)的计划需要终止工作流
|
|
|
|
438
|
+ *
|
|
|
|
439
|
+ * @param id 采购计划ID(可以是主计划ID或任意子计划ID)
|
|
|
|
440
|
+ */
|
|
|
|
441
|
+ @OpLog(type = OtherOpLogType.class, name = "中止采购计划,ID:{}", params = {"#id"})
|
|
|
|
442
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
|
443
|
+ @Override
|
|
|
|
444
|
+ public void abort(String id) {
|
|
|
|
445
|
+ if (StringUtil.isBlank(id)) {
|
|
|
|
446
|
+ throw new InputErrorException("ID不能为空!");
|
|
|
|
447
|
+ }
|
|
|
|
448
|
+
|
|
|
|
449
|
+ //查询当前计划
|
|
|
|
450
|
+ ProcurementPlan currentPlan = getBaseMapper().findById(id);
|
|
|
|
451
|
+ if (currentPlan == null) {
|
|
|
|
452
|
+ throw new DefaultClientException("采购计划不存在!");
|
|
|
|
453
|
+ }
|
|
|
|
454
|
+
|
|
|
|
455
|
+ //确定主计划ID,并收集所有需要中止的子计划列表
|
|
|
|
456
|
+ String mainPlanId;
|
|
|
|
457
|
+ List<ProcurementPlan> allSubPlans;
|
|
|
|
458
|
+ if (StringUtil.isBlank(currentPlan.getParentId())) {
|
|
|
|
459
|
+ //当前是主计划
|
|
|
|
460
|
+ mainPlanId = currentPlan.getId();
|
|
|
|
461
|
+ } else {
|
|
|
|
462
|
+ //当前是子计划,向上追溯到主计划
|
|
|
|
463
|
+ mainPlanId = currentPlan.getParentId();
|
|
|
|
464
|
+ }
|
|
|
|
465
|
+ //查询主计划下的所有子计划(非冻结的)
|
|
|
|
466
|
+ allSubPlans = getBaseMapper().selectList(
|
|
|
|
467
|
+ Wrappers.lambdaQuery(ProcurementPlan.class)
|
|
|
|
468
|
+ .eq(ProcurementPlan::getFrozen, false)
|
|
|
|
469
|
+ .eq(ProcurementPlan::getParentId, mainPlanId)
|
|
|
|
470
|
+ );
|
|
|
|
471
|
+ //如果没有子计划(单分厂,没有拆分过,当前就是一个计划),把当前计划加入列表
|
|
|
|
472
|
+ if (CollectionUtil.isEmpty(allSubPlans)) {
|
|
|
|
473
|
+ allSubPlans = new ArrayList<>();
|
|
|
|
474
|
+ allSubPlans.add(currentPlan);
|
|
|
|
475
|
+ }
|
|
|
|
476
|
+
|
|
|
|
477
|
+
|
|
|
|
478
|
+ //前置校验:存在任意"已完成"子计划则不允许中止
|
|
|
|
479
|
+ long completedCount = allSubPlans.stream()
|
|
|
|
480
|
+ .filter(p -> "COMPLETED".equals(p.getProcessStatus()))
|
|
|
|
481
|
+ .count();
|
|
|
|
482
|
+ if (completedCount > 0) {
|
|
|
|
483
|
+ throw new DefaultClientException("存在已完成的计划(子计划),不允许发起中止!");
|
|
|
|
484
|
+ }
|
|
|
|
485
|
+
|
|
|
|
486
|
+ //收集所有需要中止的计划ID(用于批量查流程实例)
|
|
|
|
487
|
+ List<String> planIdsToAbort = allSubPlans.stream()
|
|
|
|
488
|
+ .map(ProcurementPlan::getId)
|
|
|
|
489
|
+ .collect(Collectors.toList());
|
|
|
|
490
|
+
|
|
|
|
491
|
+ //批量查询这些计划关联的流程实例(用于审核中的计划终止工作流)
|
|
|
|
492
|
+ List<FlowInstanceWrapper> flowList = flowInstanceWrapperService.getFlowByBusinessIdList(planIdsToAbort);
|
|
|
|
493
|
+ // businessId -> FlowInstanceWrapper
|
|
|
|
494
|
+ Map<String, FlowInstanceWrapper> flowMap = CollectionUtil.isEmpty(flowList)
|
|
|
|
495
|
+ ? new HashMap<>()
|
|
|
|
496
|
+ : flowList.stream()
|
|
|
|
497
|
+ .filter(f -> StringUtil.isNotBlank(f.getBusinessId()))
|
|
|
|
498
|
+ .collect(Collectors.toMap(FlowInstanceWrapper::getBusinessId, f -> f, (v1, v2) -> v1));
|
|
|
|
499
|
+
|
|
|
|
500
|
+ //逐个处理子计划:过滤掉已中止的,其余更新状态为ABORTED,审核中的同时终止工作流
|
|
|
|
501
|
+ for (ProcurementPlan subPlan : allSubPlans) {
|
|
|
|
502
|
+ String status = subPlan.getProcessStatus();
|
|
|
|
503
|
+ // 已中止:幂等跳过
|
|
|
|
504
|
+ if ("ABORTED".equals(status)) {
|
|
|
|
505
|
+ continue;
|
|
|
|
506
|
+ }
|
|
|
|
507
|
+ // 已完成:理论上前面已经校验,这里再兜底
|
|
|
|
508
|
+ if ("COMPLETED".equals(status)) {
|
|
|
|
509
|
+ throw new DefaultClientException(String.format("计划[%s]已完成,不允许中止!", subPlan.getCode()));
|
|
|
|
510
|
+ }
|
|
|
|
511
|
+
|
|
|
|
512
|
+ // 审核中(AUDIT)需要先终止工作流
|
|
|
|
513
|
+ if ("AUDIT".equals(status)) {
|
|
|
|
514
|
+ FlowInstanceWrapper flow = flowMap.get(subPlan.getId());
|
|
|
|
515
|
+ if (flow != null && flow.getId() != null) {
|
|
|
|
516
|
+ flowTaskWrapperService.termination(flow.getId());
|
|
|
|
517
|
+ }
|
|
|
|
518
|
+ }
|
|
|
|
519
|
+
|
|
|
|
520
|
+ // 更新计划状态为"已中止"
|
|
|
|
521
|
+ LambdaUpdateWrapper<ProcurementPlan> updateWrapper = Wrappers.lambdaUpdate(ProcurementPlan.class)
|
|
|
|
522
|
+ .set(ProcurementPlan::getProcessStatus, "ABORTED")
|
|
|
|
523
|
+ .set(ProcurementPlan::getProcessNode, null)
|
|
|
|
524
|
+ .eq(ProcurementPlan::getId, subPlan.getId());
|
|
|
|
525
|
+ getBaseMapper().update(updateWrapper);
|
|
|
|
526
|
+ }
|
|
|
|
527
|
+
|
|
|
|
528
|
+ OpLogUtil.setVariable("id", id);
|
|
|
|
529
|
+ OpLogUtil.setExtra(currentPlan);
|
|
|
|
530
|
+ }
|
|
|
|
531
|
+
|
|
|
|
532
|
+ /**
|
|
428
|
* 子计划创建:与 create() 逻辑一致,但不重新 buildPlanCode(因为子计划编号已按父code+后缀生成)
|
533
|
* 子计划创建:与 create() 逻辑一致,但不重新 buildPlanCode(因为子计划编号已按父code+后缀生成)
|
|
429
|
*/
|
534
|
*/
|
|
430
|
@Transactional(rollbackFor = Exception.class)
|
535
|
@Transactional(rollbackFor = Exception.class)
|