|
|
|
@ -1,10 +1,15 @@
|
|
|
|
|
package org.dromara.mes.service.impl;
|
|
|
|
|
|
|
|
|
|
import com.alibaba.csp.sentinel.util.StringUtil;
|
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
|
|
import org.dromara.common.core.utils.MapstructUtils;
|
|
|
|
|
import org.dromara.common.core.utils.StringUtils;
|
|
|
|
|
import com.github.yulichang.toolkit.JoinWrappers;
|
|
|
|
|
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
|
|
|
import org.dromara.mes.domain.BaseStructureBom;
|
|
|
|
|
import org.dromara.mes.domain.vo.BaseStructureBomVo;
|
|
|
|
|
import org.dromara.mes.domain.vo.TreeSelect;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.dromara.mes.domain.bo.ProdMaterialBomBo;
|
|
|
|
|
import org.dromara.mes.domain.vo.ProdMaterialBomVo;
|
|
|
|
@ -12,12 +17,8 @@ import org.dromara.mes.domain.ProdMaterialBom;
|
|
|
|
|
import org.dromara.mes.mapper.ProdMaterialBomMapper;
|
|
|
|
|
import org.dromara.mes.service.IProdMaterialBomService;
|
|
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Collection;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
|
@ -43,7 +44,7 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
|
|
|
|
|
* @return 物料BOM信息
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public ProdMaterialBomVo queryById(Long materialBomId){
|
|
|
|
|
public ProdMaterialBomVo queryById(Long materialBomId) {
|
|
|
|
|
return baseMapper.selectVoById(materialBomId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -63,23 +64,23 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
|
|
|
|
|
private MPJLambdaWrapper<ProdMaterialBom> buildQueryWrapper(ProdMaterialBomBo bo) {
|
|
|
|
|
Map<String, Object> params = bo.getParams();
|
|
|
|
|
MPJLambdaWrapper<ProdMaterialBom> lqw = JoinWrappers.lambda(ProdMaterialBom.class)
|
|
|
|
|
.selectAll(ProdMaterialBom.class)
|
|
|
|
|
.eq(bo.getMaterialBomId() != null, ProdMaterialBom::getMaterialBomId, bo.getMaterialBomId())
|
|
|
|
|
.eq(bo.getParentId() != null, ProdMaterialBom::getParentId, bo.getParentId())
|
|
|
|
|
.eq(bo.getMaterialId() != null, ProdMaterialBom::getMaterialId, bo.getMaterialId())
|
|
|
|
|
.like(StringUtils.isNotBlank(bo.getMaterialName()), ProdMaterialBom::getMaterialName, bo.getMaterialName())
|
|
|
|
|
.like(StringUtils.isNotBlank(bo.getMaterialBomDesc()), ProdMaterialBom::getMaterialBomDesc, bo.getMaterialBomDesc())
|
|
|
|
|
.like(StringUtils.isNotBlank(bo.getMaterialBomVersion()), ProdMaterialBom::getMaterialBomVersion, bo.getMaterialBomVersion())
|
|
|
|
|
.like(StringUtils.isNotBlank(bo.getAncestors()), ProdMaterialBom::getAncestors, bo.getAncestors())
|
|
|
|
|
.eq(bo.getStandardAmount() != null, ProdMaterialBom::getStandardAmount, bo.getStandardAmount())
|
|
|
|
|
.eq(bo.getTopFlag() != null, ProdMaterialBom::getTopFlag, bo.getTopFlag())
|
|
|
|
|
.eq(StringUtils.isNotBlank(bo.getCheckType()), ProdMaterialBom::getCheckType, bo.getCheckType())
|
|
|
|
|
.eq(bo.getProjectId() != null, ProdMaterialBom::getProjectId, bo.getProjectId())
|
|
|
|
|
.eq(bo.getAssembleTime() != null, ProdMaterialBom::getAssembleTime, bo.getAssembleTime())
|
|
|
|
|
.eq(StringUtils.isNotBlank(bo.getMaterialClassfication()), ProdMaterialBom::getMaterialClassfication, bo.getMaterialClassfication())
|
|
|
|
|
.eq(StringUtils.isNotBlank(bo.getAttachId()), ProdMaterialBom::getAttachId, bo.getAttachId())
|
|
|
|
|
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ProdMaterialBom::getActiveFlag, bo.getActiveFlag())
|
|
|
|
|
.orderByAsc(ProdMaterialBom::getCreateTime);
|
|
|
|
|
.selectAll(ProdMaterialBom.class)
|
|
|
|
|
.eq(bo.getMaterialBomId() != null, ProdMaterialBom::getMaterialBomId, bo.getMaterialBomId())
|
|
|
|
|
.eq(bo.getParentId() != null, ProdMaterialBom::getParentId, bo.getParentId())
|
|
|
|
|
.eq(bo.getMaterialId() != null, ProdMaterialBom::getMaterialId, bo.getMaterialId())
|
|
|
|
|
.like(StringUtils.isNotBlank(bo.getMaterialName()), ProdMaterialBom::getMaterialName, bo.getMaterialName())
|
|
|
|
|
.like(StringUtils.isNotBlank(bo.getMaterialBomDesc()), ProdMaterialBom::getMaterialBomDesc, bo.getMaterialBomDesc())
|
|
|
|
|
.like(StringUtils.isNotBlank(bo.getMaterialBomVersion()), ProdMaterialBom::getMaterialBomVersion, bo.getMaterialBomVersion())
|
|
|
|
|
.like(StringUtils.isNotBlank(bo.getAncestors()), ProdMaterialBom::getAncestors, bo.getAncestors())
|
|
|
|
|
.eq(bo.getStandardAmount() != null, ProdMaterialBom::getStandardAmount, bo.getStandardAmount())
|
|
|
|
|
.eq(bo.getTopFlag() != null, ProdMaterialBom::getTopFlag, bo.getTopFlag())
|
|
|
|
|
.eq(StringUtils.isNotBlank(bo.getCheckType()), ProdMaterialBom::getCheckType, bo.getCheckType())
|
|
|
|
|
.eq(bo.getProjectId() != null, ProdMaterialBom::getProjectId, bo.getProjectId())
|
|
|
|
|
.eq(bo.getAssembleTime() != null, ProdMaterialBom::getAssembleTime, bo.getAssembleTime())
|
|
|
|
|
.eq(StringUtils.isNotBlank(bo.getMaterialClassfication()), ProdMaterialBom::getMaterialClassfication, bo.getMaterialClassfication())
|
|
|
|
|
.eq(StringUtils.isNotBlank(bo.getAttachId()), ProdMaterialBom::getAttachId, bo.getAttachId())
|
|
|
|
|
.eq(StringUtils.isNotBlank(bo.getActiveFlag()), ProdMaterialBom::getActiveFlag, bo.getActiveFlag())
|
|
|
|
|
.orderByAsc(ProdMaterialBom::getCreateTime);
|
|
|
|
|
return lqw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -115,11 +116,6 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public Boolean updateByBo(ProdMaterialBomBo bo) {
|
|
|
|
|
isTopFlag(bo);
|
|
|
|
|
ProdMaterialBomVo info = baseMapper.selectVoById(bo.getParentId());
|
|
|
|
|
if (StringUtils.isNotNull(info)) {
|
|
|
|
|
bo.setAncestors(info.getAncestors() + "," + bo.getParentId());
|
|
|
|
|
}
|
|
|
|
|
ProdMaterialBom update = MapstructUtils.convert(bo, ProdMaterialBom.class);
|
|
|
|
|
validEntityBeforeSave(update);
|
|
|
|
|
return baseMapper.updateById(update) > 0;
|
|
|
|
@ -128,7 +124,7 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
|
|
|
|
|
/**
|
|
|
|
|
* 保存前的数据校验
|
|
|
|
|
*/
|
|
|
|
|
private void validEntityBeforeSave(ProdMaterialBom entity){
|
|
|
|
|
private void validEntityBeforeSave(ProdMaterialBom entity) {
|
|
|
|
|
//TODO 做一些数据校验,如唯一约束
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -141,8 +137,15 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
|
|
|
|
if(isValid){
|
|
|
|
|
//TODO 做一些业务上的校验,判断是否需要校验
|
|
|
|
|
if (isValid) {
|
|
|
|
|
ids.forEach(materialBomId -> {
|
|
|
|
|
//判断是否有子级物料
|
|
|
|
|
ProdMaterialBom query = new ProdMaterialBom();
|
|
|
|
|
query.setParentId(materialBomId);
|
|
|
|
|
if (baseMapper.selectCount(Wrappers.lambdaQuery(query)) > 0) {
|
|
|
|
|
throw new ServiceException("生产BOM编号为[" + materialBomId + "]有子级物料,不能删除");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return baseMapper.deleteByIds(ids) > 0;
|
|
|
|
|
}
|
|
|
|
@ -163,9 +166,9 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 根据结构BOM批量插入物料清单BOM。
|
|
|
|
|
*
|
|
|
|
|
* @param boList 需要插入的物料清单BOM列表。
|
|
|
|
|
* @return 如果所有节点都成功插入,返回true;否则抛出异常。
|
|
|
|
|
*/
|
|
|
|
@ -175,76 +178,129 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
|
|
|
|
|
if (CollUtil.isEmpty(boList)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 按层级分组(根据parentId分组)
|
|
|
|
|
Map<Long, List<ProdMaterialBomBo>> levelMap = new HashMap<>();
|
|
|
|
|
// 1. 首先找出所有顶级节点
|
|
|
|
|
List<ProdMaterialBomBo> topNodes = boList.stream()
|
|
|
|
|
.filter(bo -> bo.getParentId() == null || bo.getParentId() == 0)
|
|
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
// 2. 其他节点按parentId分组
|
|
|
|
|
Map<Long, List<ProdMaterialBomBo>> childrenMap = boList.stream()
|
|
|
|
|
.filter(bo -> bo.getParentId() != null && bo.getParentId() != 0)
|
|
|
|
|
.collect(Collectors.groupingBy(bo -> Math.abs(bo.getParentId())));
|
|
|
|
|
// 存储临时ID到实际ID的映射
|
|
|
|
|
Map<Long, Long> idMapping = new HashMap<>();
|
|
|
|
|
// 3. 优先处理顶级节点,设置基础数据并插入
|
|
|
|
|
for (ProdMaterialBomBo topNode : topNodes) {
|
|
|
|
|
Long tempId = Math.abs(topNode.getMaterialBomId());
|
|
|
|
|
topNode.setMaterialBomId(null); // 清除临时ID
|
|
|
|
|
topNode.setParentId(0L); // 确保顶级节点parentId为0
|
|
|
|
|
topNode.setAncestors("0"); // 顶级节点的ancestors为"0"
|
|
|
|
|
topNode.setTopFlag(1L); // 设置顶级节点的topFlag为1
|
|
|
|
|
// 插入顶级节点
|
|
|
|
|
ProdMaterialBom add = MapstructUtils.convert(topNode, ProdMaterialBom.class);
|
|
|
|
|
if (baseMapper.insert(add) <= 0) {
|
|
|
|
|
throw new ServiceException("插入顶级节点失败");
|
|
|
|
|
}
|
|
|
|
|
// 记录映射关系
|
|
|
|
|
idMapping.put(tempId, add.getMaterialBomId());
|
|
|
|
|
}
|
|
|
|
|
// 4. 处理子节点,直到所有节点都处理完
|
|
|
|
|
while (!childrenMap.isEmpty()) {
|
|
|
|
|
// 找出当前可以处理的节点(父节点已经在idMapping中的节点)
|
|
|
|
|
List<Long> processableParentIds = new ArrayList<>(childrenMap.keySet());
|
|
|
|
|
boolean processed = false;// 标记本轮是否有节点被处理
|
|
|
|
|
for (Long parentTempId : processableParentIds) {
|
|
|
|
|
// 检查父节点是否已处理
|
|
|
|
|
if (idMapping.containsKey(parentTempId)) {
|
|
|
|
|
List<ProdMaterialBomBo> children = childrenMap.remove(parentTempId);
|
|
|
|
|
// 处理同一父节点的所有子节点
|
|
|
|
|
for (ProdMaterialBomBo child : children) {
|
|
|
|
|
Long childTempId = Math.abs(child.getMaterialBomId());
|
|
|
|
|
// 设置实际的父节点ID
|
|
|
|
|
child.setMaterialBomId(null);// 清除临时ID
|
|
|
|
|
child.setTopFlag(0L); // 设置非顶级节点的topFlag为0
|
|
|
|
|
Long actualParentId = idMapping.get(parentTempId);
|
|
|
|
|
child.setParentId(actualParentId);
|
|
|
|
|
// 设置祖级列表
|
|
|
|
|
ProdMaterialBom parent = baseMapper.selectById(actualParentId);
|
|
|
|
|
child.setAncestors(parent.getAncestors() + "," + actualParentId);
|
|
|
|
|
|
|
|
|
|
// 插入子节点
|
|
|
|
|
ProdMaterialBom add = MapstructUtils.convert(child, ProdMaterialBom.class);
|
|
|
|
|
if (baseMapper.insert(add) <= 0) {
|
|
|
|
|
throw new ServiceException("插入子节点失败");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 记录映射关系
|
|
|
|
|
idMapping.put(childTempId, add.getMaterialBomId());
|
|
|
|
|
}
|
|
|
|
|
processed = true;
|
|
|
|
|
//获取materialbomid不为空的更新,获取materialbomid为空materialid不为空的保存
|
|
|
|
|
for (ProdMaterialBomBo prodMaterialBomBo : boList) {
|
|
|
|
|
if (prodMaterialBomBo.getMaterialBomId() == null) {
|
|
|
|
|
if (prodMaterialBomBo.getMaterialId() != null) {
|
|
|
|
|
if (!insertByBo(prodMaterialBomBo)) {
|
|
|
|
|
throw new ServiceException("保存失败");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 如果一轮循环没有处理任何节点,说明数据有问题
|
|
|
|
|
if (!processed && !childrenMap.isEmpty()) {
|
|
|
|
|
throw new ServiceException("存在无法处理的节点,可能是父节点丢失");
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
if (!updateByBo(prodMaterialBomBo)) {
|
|
|
|
|
throw new ServiceException("保存失败");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
throw new ServiceException("批量插入失败: " + e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 查询符合条件的物料BOM信息列表,join materialtype,material,structurebom
|
|
|
|
|
*
|
|
|
|
|
* @param bo 查询条件
|
|
|
|
|
* @return 物料BOM信息列表
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public List<ProdMaterialBomVo> queryJoinStructureList(ProdMaterialBomBo bo) {
|
|
|
|
|
return baseMapper.selectMaterialBomJoinStructureList(bo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 查询生产bom信息
|
|
|
|
|
*
|
|
|
|
|
* @param bo 生产bom信息
|
|
|
|
|
* @return 生产bom信息集合
|
|
|
|
|
*/
|
|
|
|
|
@Override
|
|
|
|
|
public List<TreeSelect> selectMaterialBomTreeList(ProdMaterialBomBo bo) {
|
|
|
|
|
List<ProdMaterialBomVo> prodMaterialBomVos = baseMapper.selectMaterialBomJoinList(bo);
|
|
|
|
|
return buildMaterialBomTreeSelect(prodMaterialBomVos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 构建前端所需要树结构
|
|
|
|
|
*
|
|
|
|
|
* @param prodMaterialBomVos 部门列表
|
|
|
|
|
* @return 树结构列表
|
|
|
|
|
*/
|
|
|
|
|
private List<ProdMaterialBomVo> buildMaterialBomTree(List<ProdMaterialBomVo> prodMaterialBomVos) {
|
|
|
|
|
List<ProdMaterialBomVo> returnList = new ArrayList<ProdMaterialBomVo>();
|
|
|
|
|
ProdMaterialBomVo topProdMaterialBomVo = new ProdMaterialBomVo();
|
|
|
|
|
topProdMaterialBomVo.setMaterialBomId(0L);
|
|
|
|
|
topProdMaterialBomVo.setMaterialName("生产BOM");
|
|
|
|
|
topProdMaterialBomVo.setMaterialTypeId(-1L);
|
|
|
|
|
prodMaterialBomVos.add(topProdMaterialBomVo);
|
|
|
|
|
|
|
|
|
|
List<Long> tempList = prodMaterialBomVos.stream().map(ProdMaterialBomVo::getMaterialBomId).collect(Collectors.toList());
|
|
|
|
|
for (ProdMaterialBomVo prodMaterialBomVo : prodMaterialBomVos) {
|
|
|
|
|
// 如果是顶级节点, 遍历该父节点的所有子节点
|
|
|
|
|
if (!tempList.contains(prodMaterialBomVo.getParentId())) {
|
|
|
|
|
recursionFn(prodMaterialBomVos, prodMaterialBomVo);
|
|
|
|
|
returnList.add(prodMaterialBomVo);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (returnList.isEmpty()) {
|
|
|
|
|
returnList = prodMaterialBomVos;
|
|
|
|
|
}
|
|
|
|
|
return returnList;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 构建前端所需要下拉树结构
|
|
|
|
|
*
|
|
|
|
|
* @param prodMaterialBomVos 生产bom结构树列表
|
|
|
|
|
* @return 下拉树结构列表
|
|
|
|
|
*/
|
|
|
|
|
private List<TreeSelect> buildMaterialBomTreeSelect(List<ProdMaterialBomVo> prodMaterialBomVos) {
|
|
|
|
|
List<ProdMaterialBomVo> materialBomTrees = buildMaterialBomTree(prodMaterialBomVos);
|
|
|
|
|
return materialBomTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 递归列表
|
|
|
|
|
*/
|
|
|
|
|
private void recursionFn(List<ProdMaterialBomVo> list, ProdMaterialBomVo t) {
|
|
|
|
|
// 得到子节点列表
|
|
|
|
|
List<ProdMaterialBomVo> childList = getChildList(list, t);
|
|
|
|
|
t.setChildren(childList);
|
|
|
|
|
for (ProdMaterialBomVo tChild : childList) {
|
|
|
|
|
if (hasChild(list, tChild)) {
|
|
|
|
|
recursionFn(list, tChild);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 得到子节点列表
|
|
|
|
|
*/
|
|
|
|
|
private List<ProdMaterialBomVo> getChildList(List<ProdMaterialBomVo> list, ProdMaterialBomVo t) {
|
|
|
|
|
List<ProdMaterialBomVo> tlist = new ArrayList<ProdMaterialBomVo>();
|
|
|
|
|
Iterator<ProdMaterialBomVo> it = list.iterator();
|
|
|
|
|
while (it.hasNext()) {
|
|
|
|
|
ProdMaterialBomVo n = (ProdMaterialBomVo) it.next();
|
|
|
|
|
if(StringUtils.isNotBlank(t.getMaterialBomVersion())){
|
|
|
|
|
n.setMaterialBomVersion(t.getMaterialBomVersion());
|
|
|
|
|
}
|
|
|
|
|
if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getMaterialBomId().longValue()) {
|
|
|
|
|
tlist.add(n);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return tlist;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 判断是否有子节点
|
|
|
|
|
*/
|
|
|
|
|
private boolean hasChild(List<ProdMaterialBomVo> list, ProdMaterialBomVo t) {
|
|
|
|
|
return getChildList(list, t).size() > 0 ? true : false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|