|
@@ -21,6 +21,8 @@ import com.lframework.starter.web.core.utils.*; |
|
@@ -21,6 +21,8 @@ import com.lframework.starter.web.core.utils.*; |
|
21
|
import com.lframework.starter.web.inner.components.oplog.OtherOpLogType;
|
21
|
import com.lframework.starter.web.inner.components.oplog.OtherOpLogType;
|
|
22
|
import com.lframework.starter.web.inner.entity.SysRole;
|
22
|
import com.lframework.starter.web.inner.entity.SysRole;
|
|
23
|
import com.lframework.starter.web.inner.service.system.SysRoleService;
|
23
|
import com.lframework.starter.web.inner.service.system.SysRoleService;
|
|
|
|
24
|
+import com.lframework.xingyun.basedata.entity.Workshop;
|
|
|
|
25
|
+import com.lframework.xingyun.basedata.service.workshop.WorkshopService;
|
|
24
|
import com.lframework.xingyun.sc.bo.procurement.GetProcurementPlanChangeBo;
|
26
|
import com.lframework.xingyun.sc.bo.procurement.GetProcurementPlanChangeBo;
|
|
25
|
import com.lframework.xingyun.sc.bo.procurement.GetProcurementPlanChangeLineBo;
|
27
|
import com.lframework.xingyun.sc.bo.procurement.GetProcurementPlanChangeLineBo;
|
|
26
|
import com.lframework.xingyun.sc.procurement.entity.ProcurementPlan;
|
28
|
import com.lframework.xingyun.sc.procurement.entity.ProcurementPlan;
|
|
@@ -40,6 +42,9 @@ import com.lframework.xingyun.sc.procurement.vo.change.CreateProcurementPlanChan |
|
@@ -40,6 +42,9 @@ import com.lframework.xingyun.sc.procurement.vo.change.CreateProcurementPlanChan |
|
40
|
import com.lframework.xingyun.sc.procurement.vo.change.QueryProcurementPlanChangeVo;
|
42
|
import com.lframework.xingyun.sc.procurement.vo.change.QueryProcurementPlanChangeVo;
|
|
41
|
import com.lframework.xingyun.sc.procurement.vo.change.UpdateProcurementPlanChangeLineVo;
|
43
|
import com.lframework.xingyun.sc.procurement.vo.change.UpdateProcurementPlanChangeLineVo;
|
|
42
|
import com.lframework.xingyun.sc.procurement.vo.change.UpdateProcurementPlanChangeVo;
|
44
|
import com.lframework.xingyun.sc.procurement.vo.change.UpdateProcurementPlanChangeVo;
|
|
|
|
45
|
+import com.lframework.xingyun.sc.procurement.vo.plan.CreateProcurementPlanVo;
|
|
|
|
46
|
+import com.lframework.xingyun.sc.procurement.vo.plan.ProcurementPlanLineVo;
|
|
|
|
47
|
+import java.math.BigDecimal;
|
|
43
|
import java.util.*;
|
48
|
import java.util.*;
|
|
44
|
import java.util.stream.Collectors;
|
49
|
import java.util.stream.Collectors;
|
|
45
|
import javax.annotation.Resource;
|
50
|
import javax.annotation.Resource;
|
|
@@ -67,6 +72,8 @@ public class ProcurementPlanChangeServiceImpl extends |
|
@@ -67,6 +72,8 @@ public class ProcurementPlanChangeServiceImpl extends |
|
67
|
private ProcurementPlanLineService procurementPlanLineService;
|
72
|
private ProcurementPlanLineService procurementPlanLineService;
|
|
68
|
@Resource
|
73
|
@Resource
|
|
69
|
private ProcurementBuyoutApplyService procurementBuyoutApplyService;
|
74
|
private ProcurementBuyoutApplyService procurementBuyoutApplyService;
|
|
|
|
75
|
+ @Resource
|
|
|
|
76
|
+ private WorkshopService workshopService;
|
|
70
|
|
77
|
|
|
71
|
|
78
|
|
|
72
|
private static final List<String> PROCESS_STATUSES = Arrays.asList(
|
79
|
private static final List<String> PROCESS_STATUSES = Arrays.asList(
|
|
@@ -404,11 +411,173 @@ public class ProcurementPlanChangeServiceImpl extends |
|
@@ -404,11 +411,173 @@ public class ProcurementPlanChangeServiceImpl extends |
|
404
|
.eq(ProcurementPlanChange::getId, id);
|
411
|
.eq(ProcurementPlanChange::getId, id);
|
|
405
|
getBaseMapper().update(updateWrapper);
|
412
|
getBaseMapper().update(updateWrapper);
|
|
406
|
|
413
|
|
|
407
|
- Wrapper<ProcurementPlan> parentWrapper = Wrappers.lambdaUpdate(ProcurementPlan.class)
|
414
|
+ // 变更审核通过流程
|
|
|
|
415
|
+ String planId = entity.getProcurementPlanId();
|
|
|
|
416
|
+ // 原主计划(不带deleted筛选,因为归档/已有的都要读)
|
|
|
|
417
|
+ ProcurementPlan mainPlan = procurementPlanService.getById(planId);
|
|
|
|
418
|
+ if (mainPlan == null) {
|
|
|
|
419
|
+ throw new DefaultClientException("原采购计划不存在!");
|
|
|
|
420
|
+ }
|
|
|
|
421
|
+
|
|
|
|
422
|
+ // 1) 第一次变更时:将"原主计划+原始子计划"复制一份到 deleted=true(只保留一次,多次变更仅第一次归档)
|
|
|
|
423
|
+ int existDeletedCount = procurementPlanService.count(Wrappers.lambdaQuery(ProcurementPlan.class)
|
|
|
|
424
|
+ .eq(ProcurementPlan::getCode, mainPlan.getCode() + "_HIST")
|
|
|
|
425
|
+ .eq(ProcurementPlan::getDeleted, Boolean.TRUE));
|
|
|
|
426
|
+ if (existDeletedCount == 0L) {
|
|
|
|
427
|
+ // 归档主计划(ID新生成,deleted=true,保持原code以区分,加后缀_HIST避免唯一索引冲突)
|
|
|
|
428
|
+ ProcurementPlan archivedMain = BeanUtil.copyProperties(mainPlan, ProcurementPlan.class);
|
|
|
|
429
|
+ archivedMain.setId(IdUtil.getId());
|
|
|
|
430
|
+ archivedMain.setCode(mainPlan.getCode() + "_HIST");
|
|
|
|
431
|
+ archivedMain.setDeleted(Boolean.TRUE);
|
|
|
|
432
|
+ procurementPlanService.save(archivedMain);
|
|
|
|
433
|
+ // 原主计划子表也复制一份
|
|
|
|
434
|
+ List<ProcurementPlanLine> mainLines = procurementPlanLineService.getByProcurementPlanId(planId);
|
|
|
|
435
|
+ if (CollectionUtil.isNotEmpty(mainLines)) {
|
|
|
|
436
|
+ List<ProcurementPlanLine> archivedMainLines = new ArrayList<>();
|
|
|
|
437
|
+ for (ProcurementPlanLine line : mainLines) {
|
|
|
|
438
|
+ ProcurementPlanLine nLine = BeanUtil.copyProperties(line, ProcurementPlanLine.class);
|
|
|
|
439
|
+ nLine.setId(IdUtil.getId());
|
|
|
|
440
|
+ nLine.setProcurementPlanId(archivedMain.getId());
|
|
|
|
441
|
+ archivedMainLines.add(nLine);
|
|
|
|
442
|
+ }
|
|
|
|
443
|
+ procurementPlanLineService.saveBatch(archivedMainLines);
|
|
|
|
444
|
+ }
|
|
|
|
445
|
+ }
|
|
|
|
446
|
+ // 2) 冻结现有子计划(_01 _02)
|
|
|
|
447
|
+ List<ProcurementPlan> existSubList = procurementPlanService.listSubPlan(planId);
|
|
|
|
448
|
+ if (CollectionUtil.isNotEmpty(existSubList)) {
|
|
|
|
449
|
+ // 子计划批量设 frozen=true
|
|
|
|
450
|
+ List<String> existSubIds = existSubList.stream().map(ProcurementPlan::getId).collect(Collectors.toList());
|
|
|
|
451
|
+ procurementPlanService.update(Wrappers.lambdaUpdate(ProcurementPlan.class)
|
|
|
|
452
|
+ .set(ProcurementPlan::getFrozen, Boolean.TRUE)
|
|
|
|
453
|
+ .in(ProcurementPlan::getId, existSubIds));
|
|
|
|
454
|
+ }
|
|
|
|
455
|
+
|
|
|
|
456
|
+ // 3) 同步变更内容到主计划(主计划本身字段+明细行)
|
|
|
|
457
|
+ // 3.1 主计划主表字段:从变更单拷贝(除id/code/procurementPlanId外)
|
|
|
|
458
|
+ ProcurementPlan updatedMain = new ProcurementPlan();
|
|
|
|
459
|
+ BeanUtil.copyProperties(entity, updatedMain, "id", "code", "procurementPlanId", "processStatus", "processNode",
|
|
|
|
460
|
+ "approvalStatus", "changeReason", "changeStatus", "planType", "deleted", "frozen",
|
|
|
|
461
|
+ "createById", "createBy", "createTime", "updateById", "updateBy", "updateTime");
|
|
|
|
462
|
+ // 重新计算明细合计数量
|
|
|
|
463
|
+ List<ProcurementPlanChangeLine> changeLines = procurementPlanChangeLineService.getByChangeId(id);
|
|
|
|
464
|
+ BigDecimal totalQuantity = BigDecimal.ZERO;
|
|
|
|
465
|
+ if (CollectionUtil.isNotEmpty(changeLines)) {
|
|
|
|
466
|
+ for (ProcurementPlanChangeLine cl : changeLines) {
|
|
|
|
467
|
+ if (cl.getQuantity() != null) {
|
|
|
|
468
|
+ totalQuantity = totalQuantity.add(cl.getQuantity());
|
|
|
|
469
|
+ }
|
|
|
|
470
|
+ }
|
|
|
|
471
|
+ }
|
|
|
|
472
|
+ updatedMain.setTotalQuantity(totalQuantity);
|
|
|
|
473
|
+ // 变更完成状态
|
|
|
|
474
|
+ updatedMain.setChangeStatus("CHANGED");
|
|
|
|
475
|
+ updatedMain.setProcessNode(null);
|
|
|
|
476
|
+ procurementPlanService.update(Wrappers.lambdaUpdate(ProcurementPlan.class)
|
|
|
|
477
|
+ .setEntity(updatedMain)
|
|
|
|
478
|
+ .eq(ProcurementPlan::getId, planId));
|
|
|
|
479
|
+
|
|
|
|
480
|
+ // 3.2 主计划明细:先删后插(保留历史deleted=true的不管)
|
|
|
|
481
|
+ procurementPlanLineService.remove(Wrappers.lambdaQuery(ProcurementPlanLine.class)
|
|
|
|
482
|
+ .eq(ProcurementPlanLine::getProcurementPlanId, planId));
|
|
|
|
483
|
+ if (CollectionUtil.isNotEmpty(changeLines)) {
|
|
|
|
484
|
+ List<ProcurementPlanLine> newLines = new ArrayList<>();
|
|
|
|
485
|
+ for (ProcurementPlanChangeLine cl : changeLines) {
|
|
|
|
486
|
+ ProcurementPlanLine nl = BeanUtil.copyProperties(cl, ProcurementPlanLine.class);
|
|
|
|
487
|
+ nl.setId(IdUtil.getId());
|
|
|
|
488
|
+ nl.setProcurementPlanId(planId);
|
|
|
|
489
|
+ newLines.add(nl);
|
|
|
|
490
|
+ }
|
|
|
|
491
|
+ procurementPlanLineService.saveBatch(newLines);
|
|
|
|
492
|
+ }
|
|
|
|
493
|
+
|
|
|
|
494
|
+ // 4) 根据变更后明细的分厂分组,从_(N+1)开始生成新子计划
|
|
|
|
495
|
+ // 确定下一个子计划后缀:现有最大编号 +1
|
|
|
|
496
|
+ int nextSuffix = 1;
|
|
|
|
497
|
+ if (CollectionUtil.isNotEmpty(existSubList)) {
|
|
|
|
498
|
+ int maxSuf = 0;
|
|
|
|
499
|
+ for (ProcurementPlan s : existSubList) {
|
|
|
|
500
|
+ String c = s.getCode();
|
|
|
|
501
|
+ if (c != null && c.contains("_")) {
|
|
|
|
502
|
+ String suf = c.substring(c.lastIndexOf("_") + 1);
|
|
|
|
503
|
+ try {
|
|
|
|
504
|
+ maxSuf = Math.max(maxSuf, Integer.parseInt(suf));
|
|
|
|
505
|
+ } catch (Exception ignore) {
|
|
|
|
506
|
+ // 忽略非数字后缀
|
|
|
|
507
|
+ }
|
|
|
|
508
|
+ }
|
|
|
|
509
|
+ }
|
|
|
|
510
|
+ nextSuffix = maxSuf + 1;
|
|
|
|
511
|
+ }
|
|
|
|
512
|
+
|
|
|
|
513
|
+ // 按分厂分组明细
|
|
|
|
514
|
+ if (CollectionUtil.isNotEmpty(changeLines)) {
|
|
|
|
515
|
+ // workshopId -> workshop code
|
|
|
|
516
|
+ List<String> allWorkshopIds = changeLines.stream()
|
|
|
|
517
|
+ .map(ProcurementPlanChangeLine::getWorkshopId)
|
|
|
|
518
|
+ .filter(StringUtil::isNotBlank)
|
|
|
|
519
|
+ .distinct()
|
|
|
|
520
|
+ .collect(Collectors.toList());
|
|
|
|
521
|
+ Map<String, String> workshop2Code = new HashMap<>();
|
|
|
|
522
|
+ if (CollectionUtil.isNotEmpty(allWorkshopIds)) {
|
|
|
|
523
|
+ List<Workshop> workshopList = workshopService.listByIds(allWorkshopIds);
|
|
|
|
524
|
+ if (CollectionUtil.isNotEmpty(workshopList)) {
|
|
|
|
525
|
+ workshop2Code = workshopList.stream()
|
|
|
|
526
|
+ .filter(w -> StringUtil.isNotBlank(w.getCode()))
|
|
|
|
527
|
+ .collect(Collectors.toMap(Workshop::getId, Workshop::getCode, (v1, v2) -> v1));
|
|
|
|
528
|
+ }
|
|
|
|
529
|
+ }
|
|
|
|
530
|
+ // 分厂顺序
|
|
|
|
531
|
+ Map<String, Integer> workOrderMap = new LinkedHashMap<>();
|
|
|
|
532
|
+ workOrderMap.put("yfc", 1);
|
|
|
|
533
|
+ workOrderMap.put("efc", 2);
|
|
|
|
534
|
+ workOrderMap.put("sfc", 3);
|
|
|
|
535
|
+ workOrderMap.put("ztfc", 4);
|
|
|
|
536
|
+ Map<String, List<ProcurementPlanChangeLine>> workshopLines = new LinkedHashMap<>();
|
|
|
|
537
|
+ for (ProcurementPlanChangeLine cl : changeLines) {
|
|
|
|
538
|
+ String code = workshop2Code.getOrDefault(cl.getWorkshopId(), "");
|
|
|
|
539
|
+ workshopLines.computeIfAbsent(code, k -> new ArrayList<>()).add(cl);
|
|
|
|
540
|
+ }
|
|
|
|
541
|
+ List<Map.Entry<String, List<ProcurementPlanChangeLine>>> sortedEntries = workshopLines.entrySet().stream()
|
|
|
|
542
|
+ .sorted(Comparator.comparingInt(e -> workOrderMap.getOrDefault(e.getKey(), Integer.MAX_VALUE)))
|
|
|
|
543
|
+ .collect(Collectors.toList());
|
|
|
|
544
|
+
|
|
|
|
545
|
+ for (Map.Entry<String, List<ProcurementPlanChangeLine>> entry : sortedEntries) {
|
|
|
|
546
|
+ List<ProcurementPlanChangeLine> wLines = entry.getValue();
|
|
|
|
547
|
+ if (CollectionUtil.isEmpty(wLines)) {
|
|
|
|
548
|
+ continue;
|
|
|
|
549
|
+ }
|
|
|
|
550
|
+ String suffixStr = String.format("%02d", nextSuffix);
|
|
|
|
551
|
+ String subCode = mainPlan.getCode() + "_" + suffixStr;
|
|
|
|
552
|
+ nextSuffix++;
|
|
|
|
553
|
+
|
|
|
|
554
|
+ CreateProcurementPlanVo subVo = BeanUtil.copyProperties(entity, CreateProcurementPlanVo.class);
|
|
|
|
555
|
+ subVo.setCode(subCode);
|
|
|
|
556
|
+ subVo.setParentId(planId);
|
|
|
|
557
|
+ subVo.setProcessStatus("COMPLETED");
|
|
|
|
558
|
+ subVo.setProcessNode(null);
|
|
|
|
559
|
+ subVo.setWorkshopId(CollectionUtil.isNotEmpty(wLines) ? wLines.get(0).getWorkshopId() : null);
|
|
|
|
560
|
+
|
|
|
|
561
|
+ List<ProcurementPlanLineVo> subLineVos = new ArrayList<>();
|
|
|
|
562
|
+ for (ProcurementPlanChangeLine cl : wLines) {
|
|
|
|
563
|
+ ProcurementPlanLineVo lv = BeanUtil.copyProperties(cl, ProcurementPlanLineVo.class);
|
|
|
|
564
|
+ subLineVos.add(lv);
|
|
|
|
565
|
+ }
|
|
|
|
566
|
+ subVo.setProcurementPlanLineList(subLineVos);
|
|
|
|
567
|
+ // createSubPlan 内部会保存主表+明细+自动生成买断申请单
|
|
|
|
568
|
+ procurementPlanService.createSubPlan(subVo);
|
|
|
|
569
|
+ }
|
|
|
|
570
|
+ }
|
|
|
|
571
|
+
|
|
|
|
572
|
+ // 5) 主计划标记冻结
|
|
|
|
573
|
+ procurementPlanService.update(Wrappers.lambdaUpdate(ProcurementPlan.class)
|
|
|
|
574
|
+ .set(ProcurementPlan::getFrozen, Boolean.TRUE)
|
|
408
|
.set(ProcurementPlan::getChangeStatus, "CHANGED")
|
575
|
.set(ProcurementPlan::getChangeStatus, "CHANGED")
|
|
409
|
- .eq(ProcurementPlan::getId, entity.getProcurementPlanId());
|
|
|
|
410
|
- procurementPlanService.update(parentWrapper);
|
|
|
|
411
|
- //todo 拆分分厂、生产买断操作申请单、生成合同,生成一份原始的计划数据(第一次变更)
|
576
|
+ .set(ProcurementPlan::getProcessStatus, "COMPLETED")
|
|
|
|
577
|
+ .set(ProcurementPlan::getProcessNode, null)
|
|
|
|
578
|
+ .eq(ProcurementPlan::getId, planId));
|
|
|
|
579
|
+
|
|
|
|
580
|
+ //todo 废弃原合同;生成新合同
|
|
412
|
} else if ("REFUSE".equals(approvalStatus)) {
|
581
|
} else if ("REFUSE".equals(approvalStatus)) {
|
|
413
|
List<SysRole> roles = sysRoleService.getByUserId(entity.getCreateById());
|
582
|
List<SysRole> roles = sysRoleService.getByUserId(entity.getCreateById());
|
|
414
|
List<String> roleCodes = CollectionUtil.isEmpty(roles) ? new java.util.ArrayList<>()
|
583
|
List<String> roleCodes = CollectionUtil.isEmpty(roles) ? new java.util.ArrayList<>()
|