package com.dy.pmsProduct.process; 
 | 
  
 | 
import com.dy.common.webFilter.UserTokenContext; 
 | 
import com.dy.common.webUtil.QueryResultVo; 
 | 
import com.dy.pmsGlobal.daoOth.OthFileMapper; 
 | 
import com.dy.pmsGlobal.daoPr.PrAssemblyPlanMapper; 
 | 
import com.dy.pmsGlobal.daoPr.PrProductionNodeMapper; 
 | 
import com.dy.pmsGlobal.daoPr.PrProductionProcessMapper; 
 | 
import com.dy.pmsGlobal.daoPr.PrWorkingInstructionMapper; 
 | 
import com.dy.pmsGlobal.dyFile.FileOperate; 
 | 
import com.dy.pmsGlobal.dyFile.FileRestVo; 
 | 
import com.dy.pmsGlobal.pojoBa.BaUser; 
 | 
import com.dy.pmsGlobal.pojoOth.OthFile; 
 | 
import com.dy.pmsGlobal.pojoPr.PrAssemblyPlan; 
 | 
import com.dy.pmsGlobal.pojoPr.PrProductionNode; 
 | 
import com.dy.pmsGlobal.pojoPr.PrProductionProcess; 
 | 
import com.dy.pmsGlobal.pojoPr.PrWorkingInstruction; 
 | 
import com.dy.pmsGlobal.util.UserUtil; 
 | 
import com.dy.pmsProduct.taskPlan.PlanStatusEnum; 
 | 
import lombok.extern.slf4j.Slf4j; 
 | 
import org.apache.commons.collections4.CollectionUtils; 
 | 
import org.apache.dubbo.common.utils.PojoUtils; 
 | 
import org.springframework.beans.factory.annotation.Autowired; 
 | 
import org.springframework.beans.factory.annotation.Value; 
 | 
import org.springframework.dao.DuplicateKeyException; 
 | 
import org.springframework.stereotype.Service; 
 | 
import org.springframework.transaction.annotation.Transactional; 
 | 
  
 | 
import java.util.ArrayList; 
 | 
import java.util.List; 
 | 
import java.util.Map; 
 | 
import java.util.stream.Collectors; 
 | 
  
 | 
@Slf4j 
 | 
@Service 
 | 
public class ProcessSv { 
 | 
    private PrAssemblyPlanMapper assemblyDao; 
 | 
    private PrProductionProcessMapper processDao; 
 | 
    private PrProductionNodeMapper nodeDao; 
 | 
    private PrWorkingInstructionMapper workDao; 
 | 
    private UserUtil userUtil; 
 | 
    private FileOperate fileOperate; 
 | 
    private OthFileMapper othFileMapper; 
 | 
    @Value("${dy.webFile.fmUrl}") 
 | 
    private String fmUrl; 
 | 
  
 | 
    @Autowired 
 | 
    public void setAssemblyDao(PrAssemblyPlanMapper assemblyDao) { 
 | 
        this.assemblyDao = assemblyDao; 
 | 
    } 
 | 
  
 | 
    @Autowired 
 | 
    public void setProcessDao(PrProductionProcessMapper dao) { 
 | 
        processDao = dao; 
 | 
    } 
 | 
  
 | 
    @Autowired 
 | 
    public void setNodeDao(PrProductionNodeMapper dao) { 
 | 
        nodeDao = dao; 
 | 
    } 
 | 
  
 | 
    @Autowired 
 | 
    public void setWorkDao(PrWorkingInstructionMapper dao) { 
 | 
        workDao = dao; 
 | 
    } 
 | 
  
 | 
    @Autowired 
 | 
    public void setUserUtil(UserUtil userUtil) { 
 | 
        this.userUtil = userUtil; 
 | 
    } 
 | 
  
 | 
    @Autowired 
 | 
    public void setFileOperate(FileOperate fileOperate) { 
 | 
        this.fileOperate = fileOperate; 
 | 
    } 
 | 
  
 | 
    @Autowired 
 | 
    public void setOthFileMapper(OthFileMapper othFileMapper) { 
 | 
        this.othFileMapper = othFileMapper; 
 | 
    } 
 | 
  
 | 
    @Transactional 
 | 
    public int save(PrProductionProcess process) { 
 | 
        //流程名称不能重复 
 | 
        if (processDao.exists(process.name, process.id)) { 
 | 
            throw new RuntimeException("流程名称不能重复"); 
 | 
        } 
 | 
        prepareProcess(process); 
 | 
        int count = processDao.insertSelective(process); 
 | 
        saveNodesAndInstructions(process); 
 | 
        return count; 
 | 
    } 
 | 
  
 | 
    @Transactional 
 | 
    public int update(PrProductionProcess process) { 
 | 
        //流程名称不能重复 
 | 
        if (processDao.exists(process.name, process.id)) { 
 | 
            throw new RuntimeException("流程名称不能重复"); 
 | 
        } 
 | 
        PrProductionProcess originProductionProcess = processDao.selectByPrimaryKey(process.id); 
 | 
        //如果已经绑定组装任务计划(目前不包括暂停\结束状态 投入数为0的任务 以外的 所有任务),产品\节点id不能删除不能修改 
 | 
        PrAssemblyPlan params = new PrAssemblyPlan(); 
 | 
        params.setProcessId(process.id); 
 | 
        List<PrAssemblyPlan> planList = assemblyDao.selectAssyPlanSimplify(params); 
 | 
        List<PrAssemblyPlan> onlinePlanList = planList.stream().filter(plan -> plan.getStatus() == PlanStatusEnum.NORMAL.getCode()).collect(Collectors.toList()); 
 | 
        if (CollectionUtils.isNotEmpty(planList)) { 
 | 
            if (planList.stream().anyMatch(plan -> plan.getInputNumber() > 0)) { //存在任务已经投入生产 
 | 
                if (!originProductionProcess.getProId().equals(process.getProId())) { 
 | 
                    throw new RuntimeException("存在已经投入生产绑定的任务,产品不能修改"); 
 | 
                } 
 | 
                //节点id不能删除 
 | 
                if (!originProductionProcess.getNodes().stream().allMatch(node -> process.getNodes().stream().anyMatch(newNode ->  node.getId().equals(newNode.getId())))) { 
 | 
                    throw new RuntimeException("存在已经投入生产绑定的任务,节点不能删除"); 
 | 
                } 
 | 
            } else if (CollectionUtils.isNotEmpty(onlinePlanList)) { 
 | 
                //先将组装任务置为暂停状态 
 | 
                onlinePlanList.forEach(plan -> { 
 | 
                    plan.status = PlanStatusEnum.PAUSE.getCode(); 
 | 
                    assemblyDao.updateByPrimaryKeySelective(plan); 
 | 
                }); 
 | 
            } 
 | 
        } 
 | 
        prepareProcess(process); 
 | 
        int count = processDao.updateByPrimaryKeySelective(process); 
 | 
        // 优化:只有当节点有变更时    根据ID更新内容 没有匹配到的ID 删除  多余的ID 新增 
 | 
  
 | 
        List<Long> nodeIdsToDelete = originProductionProcess.getNodes().stream() 
 | 
                .filter(node -> process.nodes.stream().filter(newNode ->  node.getId().equals(newNode.getId())).count() == 0) 
 | 
                .map(PrProductionNode::getId) // 映射节点到其ID 
 | 
                .collect(Collectors.toList()); 
 | 
        if (CollectionUtils.isNotEmpty(nodeIdsToDelete)) { 
 | 
            nodeDao.deleteByNodeId(nodeIdsToDelete); 
 | 
        } 
 | 
        //原来节点的SOP全部删除 
 | 
        List<Long> originNodeIds = originProductionProcess.getNodes().stream() 
 | 
                .map(PrProductionNode::getId) // 映射节点到其ID 
 | 
                .collect(Collectors.toList()); 
 | 
        if (CollectionUtils.isNotEmpty(originNodeIds)) { 
 | 
            workDao.deleteByNodeId(originNodeIds); 
 | 
        } 
 | 
        saveNodesAndInstructions(process); 
 | 
        return count; 
 | 
    } 
 | 
  
 | 
    // 提取共通逻辑到单独方法以减少代码重复 
 | 
    private void prepareProcess(PrProductionProcess process) { 
 | 
        process.disabled = false; 
 | 
        process.deleted = false; 
 | 
        BaUser loginUser = userUtil.getUser(UserTokenContext.get()); 
 | 
        if (loginUser != null) { 
 | 
            process.creator = loginUser.id; 
 | 
        } 
 | 
        process.nodes.forEach(node -> { 
 | 
            node.processId = process.id; 
 | 
            node.deleted = false; 
 | 
        }); 
 | 
    } 
 | 
  
 | 
    // 将节点和工作指示的保存逻辑封装到一个方法中 
 | 
    private void saveNodesAndInstructions(PrProductionProcess process) { 
 | 
        List<PrProductionNode> haveIdList = new ArrayList<>(); 
 | 
        List<PrProductionNode> noIdList = new ArrayList<>(); 
 | 
  
 | 
        process.nodes.forEach(node -> { 
 | 
            node.processId = process.id; 
 | 
            if (node.getId() != null && node.getId() != 0) { 
 | 
                haveIdList.add(node); 
 | 
            } else { 
 | 
                noIdList.add(node); 
 | 
            } 
 | 
        }); 
 | 
        try { 
 | 
            if (haveIdList.size() > 0) { 
 | 
                for (int i = 0; i < haveIdList.size(); i++) { 
 | 
                    nodeDao.updateByPrimaryKeySelective(haveIdList.get(i)); 
 | 
                } 
 | 
            } 
 | 
            if (noIdList.size() > 0) {//CollectionUtils.isNotEmpty(noIdList) 
 | 
                nodeDao.insertMany(noIdList); 
 | 
            } 
 | 
        } catch (DuplicateKeyException e) { 
 | 
            throw new RuntimeException("节点顺序重复"); 
 | 
        } 
 | 
        List<PrWorkingInstruction> workList = process.nodes.stream().map(node -> { 
 | 
            if (node.instruction != null) { 
 | 
                node.instruction.nodeId = node.id; 
 | 
                return node.instruction; 
 | 
            } 
 | 
            return null; 
 | 
        }).filter(work -> work != null).toList(); 
 | 
        if (CollectionUtils.isNotEmpty(workList)) { 
 | 
            workDao.insertMany(workList); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    public int delete(Long id) { 
 | 
        return processDao.deleteLogicById(id); 
 | 
    } 
 | 
  
 | 
    public PrProductionProcess selectById(Long id) { 
 | 
        PrProductionProcess process = processDao.selectByPrimaryKey(id); 
 | 
        if (process != null) { 
 | 
            process.nodes.forEach(node -> { 
 | 
                if (node.instruction != null) { 
 | 
                    addUrl(node.instruction); 
 | 
                } 
 | 
            }); 
 | 
        } 
 | 
        return process; 
 | 
    } 
 | 
  
 | 
    public QueryResultVo<List<PrProductionProcess>> selectSome(QueryVo queryVo) { 
 | 
        Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(queryVo); 
 | 
  
 | 
        //查询符合条件的记录总数 
 | 
        Long itemTotal = processDao.selectSomeCount(params); 
 | 
  
 | 
        QueryResultVo<List<PrProductionProcess>> rsVo = new QueryResultVo<>(queryVo.pageSize, queryVo.pageCurr); 
 | 
        //计算分页等信息 
 | 
        rsVo.calculateAndSet(itemTotal, params); 
 | 
  
 | 
        //查询符合条件的记录 
 | 
        rsVo.obj = processDao.selectSome(params); 
 | 
        rsVo.obj.stream().forEach(process -> { 
 | 
            process.nodes.forEach(node -> { 
 | 
                if (node.instruction != null) { 
 | 
                    addUrl(node.instruction); 
 | 
                } 
 | 
            }); 
 | 
        }); 
 | 
        return rsVo; 
 | 
    } 
 | 
  
 | 
    public List<Map<String, String>> queryAll(Long proId) { 
 | 
        return processDao.queryAll(proId); 
 | 
    } 
 | 
  
 | 
    private void addUrl(PrWorkingInstruction ins) { 
 | 
        if (ins == null || ins.fileId == null) { 
 | 
            return; 
 | 
        } 
 | 
        OthFile file = othFileMapper.selectByPrimaryKey(ins.fileId); 
 | 
        if (file == null) { 
 | 
            return; 
 | 
        } 
 | 
        FileRestVo fileRestVo = fileOperate.parseHashcode(fmUrl, file.hash); 
 | 
        ins.webUrl = fileRestVo.fileSysRestUrl + fileRestVo.fileWebDownloadPath + ins.fileId; 
 | 
        ins.orgName = file.orgName; 
 | 
        ins.extName = file.extName; 
 | 
    } 
 | 
} 
 |