From 4d6cf92e30c2c7f81f8cc31dfb7559a745782ec1 Mon Sep 17 00:00:00 2001
From: lyh <925863403@qq.com>
Date: 星期一, 23 六月 2025 13:24:07 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/FullHierarchyTraceService.java |  213 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 213 insertions(+), 0 deletions(-)

diff --git a/lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/FullHierarchyTraceService.java b/lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/FullHierarchyTraceService.java
new file mode 100644
index 0000000..1180bdf
--- /dev/null
+++ b/lxzn-module-dnc/src/main/java/org/jeecg/modules/dnc/service/impl/FullHierarchyTraceService.java
@@ -0,0 +1,213 @@
+package org.jeecg.modules.dnc.service.impl;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import org.jeecg.modules.dnc.constant.DocAttributionTypeEnum;
+import org.jeecg.modules.dnc.dto.ComponentHierarchy;
+import org.jeecg.modules.dnc.dto.ProcessTraceChain;
+import org.jeecg.modules.dnc.entity.*;
+import org.jeecg.modules.dnc.mapper.*;
+import org.jeecg.modules.dnc.service.IPermissionStreamNewService;
+import org.jeecg.modules.system.service.IMdcProductionService;
+import org.jeecg.modules.system.service.ISysUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+@Service
+public class FullHierarchyTraceService {
+    @Autowired
+    private ProductMixMapper productMixMapper;
+    @Autowired
+    private ProductInfoMapper productMapper;
+    @Autowired
+    private ComponentInfoMapper componentMapper;
+    @Autowired
+    private PartsInfoMapper partsMapper;
+    @Autowired
+    private ProcessSpecVersionMapper psvMapper;
+    @Autowired
+    private ProcessStreamMapper processMapper;
+    @Autowired
+    private WorkStepMapper workStepMapper;
+    @Autowired
+    private DeviceTypeMapper deviceTypeMapper;
+    @Autowired
+    private DeviceManagementMapper deviceManagementMapper;
+    @Autowired
+    private DocInfoMapper docInfoMapper;
+    @Autowired
+    private DocFileMapper docFileMapper;
+    @Autowired
+    private CutterMapper cutterMapper;
+    @Autowired
+    private GuideCardBatchMapper guideCardBatchMapper;
+
+    public ProcessTraceChain traceFromProcess(DocRelative docRelative) {
+        ProcessTraceChain chain = initChainWithDocInfo(docRelative);
+        DeviceType deviceType = deviceTypeMapper.selectById(docRelative.getAttributionId());
+        chain.setDeviceType(deviceType);
+
+        if (isProcessType(deviceType)) {
+            chain.setDeviceManagement(deviceManagementMapper.selectById(deviceType.getDeviceManagementId()));
+            traceProcessChain(chain, deviceType.getAttributionId());
+        }
+
+        completeChainWithProductInfo(chain);
+        List<ProductMix> productMixList=buildFullTreePath(chain);
+        chain.setTreePath(productMixList);
+        return chain;
+    }
+
+    public ProcessTraceChain traceFromWorkStep(DocRelative docRelative) {
+        ProcessTraceChain chain = initChainWithDocInfo(docRelative);
+        DeviceType deviceType = deviceTypeMapper.selectById(docRelative.getAttributionId());
+        chain.setDeviceType(deviceType);
+
+        if (isWorkSiteType(deviceType)) {
+            chain.setDeviceManagement(deviceManagementMapper.selectById(deviceType.getDeviceManagementId()));
+            traceWorkStepChain(chain, deviceType.getAttributionId());
+        }
+
+        completeChainWithProductInfo(chain);
+        List<ProductMix> productMixList=buildFullTreePath(chain);
+        chain.setTreePath(productMixList);
+        return chain;
+    }
+
+    private ProcessTraceChain initChainWithDocInfo(DocRelative docRelative) {
+        ProcessTraceChain chain = ProcessTraceChain.builder().docRelative(docRelative).build();
+        Optional.ofNullable(docInfoMapper.selectById(docRelative.getDocId()))
+                .ifPresent(doc -> {
+                    chain.setDocInfo(doc);
+                    chain.setDocFile(docFileMapper.selectById(doc.getPublishFileId()));
+                    chain.setCutterList(getCuttersByDocId(doc.getDocId()));
+                    getLatestGuideCardBatch(doc.getDocId()).ifPresent(chain::setGuideCardBatch);
+                });
+        return chain;
+    }
+
+    private List<Cutter> getCuttersByDocId(String docId) {
+        return cutterMapper.selectList(new QueryWrapper<Cutter>().eq("doc_id", docId));
+    }
+
+    private Optional<GuideCardBatch> getLatestGuideCardBatch(String docId) {
+        List<GuideCardBatch> batches = guideCardBatchMapper.selectList(
+                new QueryWrapper<GuideCardBatch>()
+                        .eq("doc_id", docId)
+                        .orderByDesc("SUBSTRING(serial_number, LEN(serial_number)-3, 4)"));
+        return CollectionUtils.isEmpty(batches) ? Optional.empty() : Optional.of(batches.get(0));
+    }
+
+    private boolean isProcessType(DeviceType deviceType) {
+        return deviceType != null &&
+                Objects.equals(deviceType.getAttributionType(), DocAttributionTypeEnum.PROCESS.getCode());
+    }
+
+    private boolean isWorkSiteType(DeviceType deviceType) {
+        return deviceType != null &&
+                Objects.equals(deviceType.getAttributionType(), DocAttributionTypeEnum.WORKSITE.getCode());
+    }
+
+    private void traceProcessChain(ProcessTraceChain chain, String processId) {
+        ProcessStream process = processMapper.selectById(processId);
+        if (process == null) return;
+
+        chain.setProcess(process);
+        if (process.getPsvId() != null) {
+            ProcessSpecVersion psv = psvMapper.selectById(process.getPsvId());
+            chain.setProcessSpec(psv);
+            if (psv != null && psv.getPartsId() != null) {
+                PartsInfo parts = partsMapper.selectById(psv.getPartsId());
+                chain.setParts(parts);
+                if (parts != null && parts.getComponentId() != null) {
+                    chain.setComponentHierarchy(traceComponentHierarchy(parts.getComponentId()));
+                }
+            }
+        } else if (process.getComponentId() != null) {
+            chain.setComponentHierarchy(traceComponentHierarchy(process.getComponentId()));
+        }
+    }
+
+    private void traceWorkStepChain(ProcessTraceChain chain, String workStepId) {
+        WorkStep workStep = workStepMapper.selectById(workStepId);
+        if (workStep == null) return;
+
+        chain.setWorkStep(workStep);
+        traceProcessChain(chain, workStep.getProcessId());
+    }
+
+    private ComponentHierarchy traceComponentHierarchy(String componentId) {
+        ComponentHierarchy hierarchy = new ComponentHierarchy();
+        ComponentInfo current = componentMapper.selectById(componentId);
+
+        while (current != null) {
+            hierarchy.addComponentToTop(current);
+
+            if (current.getParentId() == null || current.getParentId().isEmpty()) {
+                Optional.ofNullable(current.getProductId())
+                        .map(productMapper::selectById)
+                        .ifPresent(hierarchy::setRootProduct);
+                break;
+            }
+
+            current = componentMapper.selectById(current.getParentId());
+        }
+
+        return hierarchy;
+    }
+
+    private void completeChainWithProductInfo(ProcessTraceChain chain) {
+        Optional.ofNullable(chain.getComponentHierarchy())
+                .map(ComponentHierarchy::getComponents)
+                .filter(components -> !components.isEmpty())
+                .map(components -> components.get(0))
+                .map(ComponentInfo::getProductId)
+                .map(productMapper::selectById)
+                .ifPresent(chain::setProduct);
+    }
+
+    private List<ProductMix> buildFullTreePath(ProcessTraceChain chain) {
+        List<ProductMix> path = new ArrayList<>();
+
+        Optional.ofNullable(chain.getProduct())
+                .map(ProductInfo::getProductId)
+                .map(productMixMapper::findByProductId)
+                .ifPresent(path::add);
+
+        Optional.ofNullable(chain.getComponentHierarchy())
+                .map(ComponentHierarchy::getComponentsFromTop)
+                .ifPresent(components -> components.stream()
+                        .map(ComponentInfo::getComponentId)
+                        .map(productMixMapper::findByComponentId)
+                        .filter(Objects::nonNull)
+                        .forEach(path::add));
+
+        Optional.ofNullable(chain.getParts())
+                .map(PartsInfo::getPartsId)
+                .map(productMixMapper::findByPartsId)
+                .ifPresent(path::add);
+
+        Optional.ofNullable(chain.getProcessSpec())
+                .map(ProcessSpecVersion::getId)
+                .map(productMixMapper::findByOperationId)
+                .ifPresent(path::add);
+
+        Optional.ofNullable(chain.getProcess())
+                .map(ProcessStream::getProcessId)
+                .map(productMixMapper::findByProcessId)
+                .ifPresent(path::add);
+
+        Optional.ofNullable(chain.getWorkStep())
+                .map(WorkStep::getId)
+                .map(productMixMapper::findByWorksiteId)
+                .ifPresent(path::add);
+
+        return path;
+    }
+
+}

--
Gitblit v1.9.3