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;
|
}
|
}
|