后端:物料bom完善,树不根据bom版本递归,增加状态
master
xs 1 month ago
parent 489bf79700
commit 79d393f414

@ -21,4 +21,7 @@ public interface HwMomMesConstants {
*/
public static final String REDIS_KEY_DEVICE_INFO = "hw_device_info";
public static final String MES_MATERIAL_BOM_ACTIVE_FLAG_ACTIVE = "1";//启用
public static final String MES_MATERIAL_BOM_ACTIVE_FLAG_HISTORY = "2";//历史
public static final String MES_MATERIAL_BOM_ACTIVE_FLAG_DESIGN = "3";//设计中
}

@ -135,6 +135,19 @@ public class ProdMaterialBomController extends BaseController {
return R.ok(list);
}
/**
* BOM
*/
@SaCheckPermission("mes:materialBom:add")
@GetMapping("/selectNextMaterialBomVersion/{parentId}")
public R<String> selectNextMaterialBomVersion(@NotNull(message = "不能为空")
@PathVariable Long parentId) {
String nextMaterialBomVersion = prodMaterialBomService.selectNextMaterialBomVersion(parentId);
return R.ok("success",nextMaterialBomVersion);
}
/**
* BOMBOM
*/
@ -203,4 +216,15 @@ public class ProdMaterialBomController extends BaseController {
return R.ok(list);
}
/**
*
*/
@SaCheckPermission("mes:materialBom:publish")
@Log(title = "物料BOM信息", businessType = BusinessType.PUBLISH)
@RepeatSubmit()
@PostMapping("/publish")
public R<Void> publish(@RequestBody ProdMaterialBomBo bo) {
return toAjax(prodMaterialBomService.publishByBo(bo));
}
}

@ -20,6 +20,7 @@ import org.dromara.mes.domain.bo.ProdMaterialBomBo;
import org.dromara.mes.domain.bo.ProdMaterialBomVersionBo;
import org.dromara.mes.domain.bo.ProdPlanInfoBo;
import org.dromara.mes.domain.vo.*;
import org.dromara.mes.enums.PlanEventEnum;
import org.dromara.mes.service.IProdBaseRouteProcessService;
import org.dromara.mes.service.IProdMaterialBomService;
import org.dromara.mes.service.IProdMaterialBomVersionService;
@ -210,4 +211,15 @@ public class ProdPlanInfoController extends BaseController {
return R.ok(prodMaterialBomVersionService.queryList(prodMaterialBomBo));
}
/**
* planstatus
* @param planId
* @param event
* @return
*/
@PostMapping("/{planId}/events")
public boolean triggerEvent(@PathVariable Long planId, @RequestParam PlanEventEnum event) {
return prodPlanInfoService.sendEvent(planId, event);
}
}

@ -213,4 +213,8 @@ public class ProdMaterialBomVo implements Serializable {
&& Objects.equals(parentMaterialTypeId, o.getParentMaterialTypeId()) && Objects.equals(materialBomVersion, o.getMaterialBomVersion())
&& standardAmount.compareTo(o.getStandardAmount())==0;
}
public String getKey(){
return this.parentId+"-"+this.materialBomVersion;
}
}

@ -11,11 +11,13 @@ import org.dromara.common.excel.annotation.ExcelDictFormat;
import org.dromara.common.excel.convert.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data;
import org.dromara.mes.enums.PlanStatusEnum;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
/**
@ -182,6 +184,7 @@ public class ProdPlanInfoVo implements Serializable {
*/
@ExcelProperty(value = "工单计划状态", converter = ExcelDictConvert.class)
@ExcelDictFormat(dictType = "mes_plan_status")
// @Enumerated(EnumType.ORDINAL)
private String planStatus;
/**

@ -52,6 +52,10 @@ public class TreeSelect implements Serializable {
private String treeKey;//作为树的唯一键使用
private String activeFlag;//状态
private boolean isRoot;
public TreeSelect() {
}
@ -79,6 +83,27 @@ public class TreeSelect implements Serializable {
this.materialTypeId = prodMaterialBomVo.getMaterialTypeId();
this.materialTypeName = prodMaterialBomVo.getMaterialTypeName();
this.materialBomVersion = prodMaterialBomVo.getMaterialBomVersion();
this.activeFlag = prodMaterialBomVo.getActiveFlag();
}
public TreeSelect(ProdMaterialBomVo prodMaterialBomVo,boolean isRoot) {
this.id = prodMaterialBomVo.getMaterialBomId();//树的唯一键,有可能为空所以不能作为树的ID
this.treeKey = prodMaterialBomVo.getMaterialId() + "-" + prodMaterialBomVo.getMaterialBomVersion();
if (prodMaterialBomVo.getParentId() == null) {
this.label = prodMaterialBomVo.getMaterialName();
} else {
this.label = "[" + prodMaterialBomVo.getMaterialBomVersion() + "][" + prodMaterialBomVo.getMaterialTypeName() + "]" +
prodMaterialBomVo.getMaterialName();
}
this.parentId = prodMaterialBomVo.getParentId();
this.materialId = prodMaterialBomVo.getMaterialId();
this.children = prodMaterialBomVo.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
this.materialName = prodMaterialBomVo.getMaterialName();
this.materialTypeId = prodMaterialBomVo.getMaterialTypeId();
this.materialTypeName = prodMaterialBomVo.getMaterialTypeName();
this.materialBomVersion = prodMaterialBomVo.getMaterialBomVersion();
this.activeFlag = prodMaterialBomVo.getActiveFlag();
this.isRoot = isRoot;
}
public Long getId() {
@ -160,4 +185,25 @@ public class TreeSelect implements Serializable {
public void setTreeKey(String treeKey) {
this.treeKey = treeKey;
}
public String getActiveFlag() {
return activeFlag;
}
public void setActiveFlag(String activeFlag) {
this.activeFlag = activeFlag;
}
public boolean isRoot() {
return isRoot;
}
public void setRoot(boolean root) {
isRoot = root;
}
// 唯一标识
public String getUniqueKey() {
return parentId + "|" + materialId + "|" + materialBomVersion;
}
}

@ -1,5 +1,6 @@
package org.dromara.mes.mapper;
import org.apache.ibatis.annotations.Select;
import org.dromara.mes.domain.ProdMaterialBom;
import org.dromara.mes.domain.bo.ProdMaterialBomBo;
import org.dromara.mes.domain.vo.ProdMaterialBomVo;
@ -57,4 +58,14 @@ public interface ProdMaterialBomMapper extends BaseMapperPlus<ProdMaterialBom, P
* @return bom
*/
ProdMaterialBomVo selectParentMaterialBomJoin(ProdMaterialBomBo podMaterialBomBo);
@Select("SELECT NEXT VALUE FOR material_bom_id_sequence")
long getNextMaterialBomIdSequence();
/**
* parentId(+1)
* @param parentId
* @return
*/
String selectNextMaterialBomVersion(Long parentId);
}

@ -4,6 +4,7 @@ import org.dromara.mes.domain.ProdMaterialBom;
import org.dromara.mes.domain.vo.ProdMaterialBomVo;
import org.dromara.mes.domain.bo.ProdMaterialBomBo;
import org.dromara.mes.domain.vo.TreeSelect;
import org.springframework.transaction.annotation.Transactional;
import java.util.Collection;
import java.util.List;
@ -49,6 +50,15 @@ public interface IProdMaterialBomService {
*/
Boolean updateByBo(ProdMaterialBomBo bo);
/**
* BOM
*
* @param bo BOM
* @return
*/
public Boolean publishByBo(ProdMaterialBomBo bo);
/**
* BOM
*
@ -65,6 +75,13 @@ public interface IProdMaterialBomService {
*/
public Boolean deleteMaterialBoms(List<ProdMaterialBomBo> materialBomBos);
/**
* ID
* @param parentId
* @return
*/
public String selectNextMaterialBomVersion(Long parentId);
/**
* BOMBOM
* @param boList BOM

@ -6,6 +6,7 @@ import org.dromara.mes.domain.vo.ProdPlanInfoVo;
import org.dromara.mes.domain.bo.ProdPlanInfoBo;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.mes.enums.PlanEventEnum;
import java.util.Collection;
import java.util.List;
@ -107,4 +108,8 @@ public interface IProdPlanInfoService {
* @return
*/
List<PlanMonitorVo> queryMoritorList(ProdPlanInfoBo bo);
public boolean sendEvent(Long planId, PlanEventEnum event);
}

@ -134,6 +134,60 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
}
/**
* BOM
*
* @param bo BOM
* @return
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean publishByBo(ProdMaterialBomBo bo) {
String materialBomVersion = bo.getMaterialBomVersion();
bo.setDeleteFlag(HwMomMesConstants.DELETE_FLAG_NO);
bo.setMaterialBomVersion(null);
//先获取parentid所有的物料bom信息
List<ProdMaterialBomVo> allVosByParentId = this.queryList(bo);
if (allVosByParentId == null || allVosByParentId.isEmpty()) {
throw new ServiceException("数据已删除");
}
//再过滤出当前要发布的版本信息
List<ProdMaterialBomVo> toPublishVos = allVosByParentId.stream().
filter(e -> e.getMaterialBomVersion().equals(materialBomVersion) &&
!e.getActiveFlag().equals(HwMomMesConstants.MES_MATERIAL_BOM_ACTIVE_FLAG_ACTIVE))
.collect(Collectors.toList());
if (toPublishVos == null && toPublishVos.isEmpty()) {
throw new ServiceException("无可发布数据,或已发布");
}
//再过滤出其他激活版本,需要改为历史版本的数据
List<ProdMaterialBomVo> toHistoryVos = allVosByParentId.stream().
filter(e -> !e.getMaterialBomVersion().equals(materialBomVersion) &&
e.getActiveFlag().equals(HwMomMesConstants.MES_MATERIAL_BOM_ACTIVE_FLAG_ACTIVE))
.collect(Collectors.toList());
//发布
for (ProdMaterialBomVo toPublishVo : toPublishVos) {
ProdMaterialBom toPublishMaterialBom = MapstructUtils.convert(toPublishVo, ProdMaterialBom.class);
toPublishMaterialBom.setActiveFlag(HwMomMesConstants.MES_MATERIAL_BOM_ACTIVE_FLAG_ACTIVE);
baseMapper.updateById(toPublishMaterialBom);
}
//改为历史版本
if (toHistoryVos != null && !toHistoryVos.isEmpty()) {
for (ProdMaterialBomVo toHistoryVo : toHistoryVos) {
ProdMaterialBom toHistoryMaterialBom = MapstructUtils.convert(toHistoryVo, ProdMaterialBom.class);
toHistoryMaterialBom.setActiveFlag(HwMomMesConstants.MES_MATERIAL_BOM_ACTIVE_FLAG_HISTORY);
baseMapper.updateById(toHistoryMaterialBom);
}
}
return true;
}
/**
* BOM
*
@ -163,7 +217,7 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
* @description BOM
*/
@Override
@Transactional (rollbackFor = Exception.class)
@Transactional(rollbackFor = Exception.class)
public Boolean deleteMaterialBoms(List<ProdMaterialBomBo> materialBomBos) {
Collection<Long> ids = new ArrayList<>();
materialBomBos.forEach(materialBomBo -> {
@ -181,51 +235,65 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
*
*/
private void validEntityUsed(@NotNull ProdMaterialBomBo entity) {
Long semiFinishedId = mesProperties.getSemiFinishedId();
Long modelingId = mesProperties.getModelingId();
Long vulcanizingId = mesProperties.getVulcanizingId();
String semiFinishedTableName = DatabaseConstants.TABLE_NAME_PROD_PLAN_INFO_PREFIX + "_" + semiFinishedId;
String modelingTableName = DatabaseConstants.TABLE_NAME_PROD_PLAN_INFO_PREFIX + "_" + modelingId;
String vulcanizingTableName = DatabaseConstants.TABLE_NAME_PROD_PLAN_INFO_PREFIX + "_" + vulcanizingId;
ProdPlanInfoBo queryBo = new ProdPlanInfoBo();
queryBo.setMaterialId(entity.getParentId());
queryBo.setMaterialBomVersion(entity.getMaterialBomVersion());
MPJLambdaWrapper<ProdPlanInfo> lqw = buildPlanQueryWrapper(queryBo);
/**
* 使bom
*/
List<ProdPlanInfoVo> semiFinishedPlanInfoVos = prodPlanInfoMapper.selectProdPlanInfoList(semiFinishedTableName, lqw);
if (semiFinishedPlanInfoVos != null && !semiFinishedPlanInfoVos.isEmpty()) {
List<String> planCodes = semiFinishedPlanInfoVos.stream()
.map(ProdPlanInfoVo::getPlanCode)
.toList();
throw new ServiceException("半制品计划中计划编号[" + planCodes.toString() + "]已经使用此bom不能修改");
if(entity.getActiveFlag().equals(HwMomMesConstants.MES_MATERIAL_BOM_ACTIVE_FLAG_ACTIVE)){
throw new ServiceException("此物料bom已经发布不能修改");
}
List<ProdPlanInfoVo> modelingPlanInfoVos = prodPlanInfoMapper.selectProdPlanInfoList(modelingTableName, lqw);
if (modelingPlanInfoVos != null && !modelingPlanInfoVos.isEmpty()) {
List<String> planCodes = modelingPlanInfoVos.stream()
.map(ProdPlanInfoVo::getPlanCode)
.toList();
throw new ServiceException("成型计划中计划编号[" + planCodes.toString() + "]已经使用此bom不能修改");
}
List<ProdPlanInfoVo> vulcanizingPlanInfoVos = prodPlanInfoMapper.selectProdPlanInfoList(vulcanizingTableName, lqw);
if (vulcanizingPlanInfoVos != null && !vulcanizingPlanInfoVos.isEmpty()) {
List<String> planCodes = vulcanizingPlanInfoVos.stream()
.map(ProdPlanInfoVo::getPlanCode)
.toList();
throw new ServiceException("硫化计划中计划编号已经使用[" + planCodes.toString() + "已经使用此bom不能修改");
if(entity.getActiveFlag().equals(HwMomMesConstants.MES_MATERIAL_BOM_ACTIVE_FLAG_HISTORY)){
throw new ServiceException("此物料bom为历史版本不能修改");
}
}
// /**
// * 更新前的数据校验
// */
// private void validEntityUsed(@NotNull ProdMaterialBomBo entity) {
// Long semiFinishedId = mesProperties.getSemiFinishedId();
// Long modelingId = mesProperties.getModelingId();
// Long vulcanizingId = mesProperties.getVulcanizingId();
//
// String semiFinishedTableName = DatabaseConstants.TABLE_NAME_PROD_PLAN_INFO_PREFIX + "_" + semiFinishedId;
// String modelingTableName = DatabaseConstants.TABLE_NAME_PROD_PLAN_INFO_PREFIX + "_" + modelingId;
// String vulcanizingTableName = DatabaseConstants.TABLE_NAME_PROD_PLAN_INFO_PREFIX + "_" + vulcanizingId;
//
// ProdPlanInfoBo queryBo = new ProdPlanInfoBo();
// queryBo.setMaterialId(entity.getParentId());
// queryBo.setMaterialBomVersion(entity.getMaterialBomVersion());
// MPJLambdaWrapper<ProdPlanInfo> lqw = buildPlanQueryWrapper(queryBo);
//
// /**
// * 查询半制品计划、成型计划、硫化计划中有没有使用此bom
// */
// List<ProdPlanInfoVo> semiFinishedPlanInfoVos = prodPlanInfoMapper.selectProdPlanInfoList(semiFinishedTableName, lqw);
// if (semiFinishedPlanInfoVos != null && !semiFinishedPlanInfoVos.isEmpty()) {
// List<String> planCodes = semiFinishedPlanInfoVos.stream()
// .map(ProdPlanInfoVo::getPlanCode)
// .toList();
//
// throw new ServiceException("半制品计划中计划编号[" + planCodes.toString() + "]已经使用此bom不能修改");
// }
//
// List<ProdPlanInfoVo> modelingPlanInfoVos = prodPlanInfoMapper.selectProdPlanInfoList(modelingTableName, lqw);
// if (modelingPlanInfoVos != null && !modelingPlanInfoVos.isEmpty()) {
// List<String> planCodes = modelingPlanInfoVos.stream()
// .map(ProdPlanInfoVo::getPlanCode)
// .toList();
//
// throw new ServiceException("成型计划中计划编号[" + planCodes.toString() + "]已经使用此bom不能修改");
// }
//
// List<ProdPlanInfoVo> vulcanizingPlanInfoVos = prodPlanInfoMapper.selectProdPlanInfoList(vulcanizingTableName, lqw);
// if (vulcanizingPlanInfoVos != null && !vulcanizingPlanInfoVos.isEmpty()) {
// List<String> planCodes = vulcanizingPlanInfoVos.stream()
// .map(ProdPlanInfoVo::getPlanCode)
// .toList();
//
// throw new ServiceException("硫化计划中计划编号已经使用[" + planCodes.toString() + "已经使用此bom不能修改");
// }
//
// }
/**
@ -244,6 +312,20 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
}
/**
* ID
*
* @param parentId
* @return
*/
@Override
public String selectNextMaterialBomVersion(Long parentId) {
String nextMaterialBomVersion = baseMapper.selectNextMaterialBomVersion(parentId);
System.out.println("nnn:" + nextMaterialBomVersion);
return nextMaterialBomVersion;
}
/**
* BOMBOM
*
@ -257,6 +339,9 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
return false;
}
// long materialBomId = baseMapper.getNextMaterialBomIdSequence();
// System.out.println("matbomid:"+materialBomId);
//判断在新建子级时是否存在在此颗树的父级节点存在此子级节点根据bom版本找(可以先不加此判断,主要原因是物料类型已经限制了)
//获取materialbomid不为空的更新获取materialbomid为空materialid不为空的保存
for (ProdMaterialBomBo prodMaterialBomBo : boList) {
@ -311,17 +396,295 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
@Override
public List<TreeSelect> selectMaterialBomTreeList(ProdMaterialBomBo bo) {
List<ProdMaterialBomVo> prodMaterialBomVos = baseMapper.selectMaterialBomJoinList(bo);
return buildMaterialBomTreeSelect(prodMaterialBomVos);
return buildMaterialBomTree(prodMaterialBomVos);
}
/**
*
*
* @param bomList bom
* @return
*/
private List<TreeSelect> buildMaterialBomTree(List<ProdMaterialBomVo> bomList) {
// 1. 建立索引
Map<String, List<ProdMaterialBomVo>> parentVersionGroup = new HashMap<>();
Map<Long, Set<String>> materialVersions = new HashMap<>();
Map<Long, String> materialNameMap = new HashMap<>();
Map<Long, Long> materialTypeIdMap = new HashMap<>();
Map<Long, String> materialTypeNameMap = new HashMap<>();
Map<String, String> versionActiveFlagMap = new HashMap<>(); // 新增:存储版本状态
for (ProdMaterialBomVo item : bomList) {
// 按parentId+version分组
String parentKey = item.getParentId() + "_" + item.getMaterialBomVersion();
parentVersionGroup.computeIfAbsent(parentKey, k -> new ArrayList<>()).add(item);
// 记录每个material的所有版本
materialVersions.computeIfAbsent(item.getMaterialId(), k -> new HashSet<>())
.add(item.getMaterialBomVersion());
// 记录物料名称
if (item.getMaterialName() != null) {
materialNameMap.putIfAbsent(item.getMaterialId(), item.getMaterialName());
}
if (item.getParentMaterialName() != null) {
materialNameMap.putIfAbsent(item.getParentId(), item.getParentMaterialName());
}
// 记录物料类型ID和物料类型名称
if (item.getMaterialTypeId() != null) {
materialTypeIdMap.putIfAbsent(item.getMaterialId(), item.getMaterialTypeId());
materialTypeNameMap.putIfAbsent(item.getMaterialId(), item.getMaterialTypeName());
}
if (item.getParentMaterialTypeId() != null) {
materialTypeIdMap.putIfAbsent(item.getParentId(), item.getParentMaterialTypeId());
materialTypeNameMap.putIfAbsent(item.getParentId(), item.getParentMaterialTypeName());
}
// 记录版本状态(新增)
String versionKey = item.getParentId() + "_" + item.getMaterialBomVersion();
versionActiveFlagMap.putIfAbsent(versionKey, item.getActiveFlag()); // 假设activeFlag是boolean类型
}
// 2. 找出顶级节点
Set<Long> topLevelParentIds = bomList.stream()
.map(ProdMaterialBomVo::getParentId)
.filter(parentId -> !materialVersions.containsKey(parentId))
.collect(Collectors.toSet());
// 3. 构建树结构
List<TreeSelect> tree = new ArrayList<>();
for (Long topParentId : topLevelParentIds) {
// 获取该顶级节点的所有版本
Set<String> parentVersions = bomList.stream()
.filter(item -> item.getParentId().equals(topParentId))
.map(ProdMaterialBomVo::getMaterialBomVersion)
.collect(Collectors.toSet());
for (String version : parentVersions) {
String versionKey = topParentId + "_" + version;
String activeFlag = versionActiveFlagMap.get(versionKey);
TreeSelect versionNode = new TreeSelect();
versionNode.setTreeKey(versionKey);
versionNode.setLabel(buildLabel(topParentId, version, materialNameMap,materialTypeNameMap));
versionNode.setMaterialBomVersion(version);
versionNode.setMaterialId(topParentId);
versionNode.setMaterialTypeId(materialTypeIdMap.getOrDefault(topParentId, 0L));
versionNode.setMaterialTypeName(materialTypeNameMap.getOrDefault(topParentId, ""));
versionNode.setActiveFlag(activeFlag);
versionNode.setChildren(new ArrayList<>());
String parentKey = topParentId + "_" + version;
if (parentVersionGroup.containsKey(parentKey)) {
// 获取该父节点下的所有materialId
Set<Long> childMaterialIds = parentVersionGroup.get(parentKey).stream()
.map(ProdMaterialBomVo::getMaterialId)
.collect(Collectors.toSet());
for (Long materialId : childMaterialIds) {
// 添加无版本号的基础节点
versionNode.getChildren().add(createBasicNode(materialId,materialNameMap,materialTypeIdMap,materialTypeNameMap));
// 动态添加该material的有子节点的版本
if (materialVersions.containsKey(materialId)) {
for (String childVersion : materialVersions.get(materialId)) {
TreeSelect versionedNode = createVersionNodeIfHasChildren(
materialId, childVersion, activeFlag,parentVersionGroup,materialNameMap,materialTypeIdMap,materialTypeNameMap);
if (versionedNode != null) {
versionNode.getChildren().add(versionedNode);
}
}
}
}
}
// 只有当有子节点时才添加父节点
if (!versionNode.getChildren().isEmpty()) {
tree.add(versionNode);
}
}
}
return tree;
// return topLevelNodes;
// return rootNodes.stream().map(TreeSelect::new).collect(Collectors.toList());
}
private static String buildLabel(Long materialId, String version, Map<Long, String> materialNameMap, Map<Long, String> materialTypeNameMap) {
String materialName = materialNameMap.getOrDefault(materialId, "");
String materialTypeName = materialTypeNameMap.getOrDefault(materialId, "");
return String.format("[%s][%s]%s",
version,
materialTypeName.isEmpty() ? "" : materialTypeName,
materialName.isEmpty() ? "" : materialName);
}
private static TreeSelect createBasicNode(Long materialId,
Map<Long, String> materialNameMap,Map<Long, Long> materialTypeIdMap,Map<Long, String> materialTypeNameMap) {
// this.parentId = prodMaterialBomVo.getParentId();
TreeSelect node = new TreeSelect();
node.setTreeKey(materialId.toString());
String materialName = materialNameMap.getOrDefault(materialId, "");
String materialTypeName = materialTypeNameMap.getOrDefault(materialId, "");
String label = String.format("[%s]%s",
materialTypeName.isEmpty() ? "" : materialTypeName,
materialName.isEmpty() ? "" : materialName);
node.setLabel(label);
node.setMaterialId(materialId);
node.setMaterialTypeId(materialTypeIdMap.getOrDefault(materialId, 0L));
node.setMaterialTypeName(materialTypeNameMap.getOrDefault(materialId, ""));
node.setMaterialBomVersion(null);
node.setActiveFlag(null);
return node;
}
private static TreeSelect createVersionNodeIfHasChildren(Long materialId, String version,String activeFlag,
Map<String, List<ProdMaterialBomVo>> parentVersionGroup,
Map<Long, String> materialNameMap,Map<Long, Long> materialTypeIdMap,Map<Long, String> materialTypeNameMap) {
String key = materialId + "_" + version;
// 只有当该版本有子节点时才创建
if (parentVersionGroup.containsKey(key)) {
TreeSelect node = new TreeSelect();
node.setTreeKey(key);
node.setLabel(buildLabel(materialId, version, materialNameMap,materialTypeNameMap));
node.setMaterialBomVersion(version);
node.setMaterialBomVersion(version);
node.setMaterialId(materialId);
node.setMaterialTypeId(materialTypeIdMap.getOrDefault(materialId, 0L));
node.setMaterialTypeName(materialTypeNameMap.getOrDefault(materialId, ""));
node.setActiveFlag(activeFlag);
node.setChildren(new ArrayList<>());
// 添加子节点
Set<Long> childIds = parentVersionGroup.get(key).stream()
.map(ProdMaterialBomVo::getMaterialId)
.collect(Collectors.toSet());
for (Long childId : childIds) {
node.getChildren().add(createBasicNode(childId,materialNameMap,materialTypeIdMap,materialTypeNameMap));
}
return node;
}
return null;
}
private static List<TreeSelect> buildChildren(Long currentParentId,List<ProdMaterialBomVo> items,
Map<Long, Map<String, List<ProdMaterialBomVo>>> parentVersionMap) {
List<TreeSelect> children = new ArrayList<>();
for (ProdMaterialBomVo item : items) {
// 确保当前item的parentId匹配currentParentId
if (!item.getParentId().equals(currentParentId)) {
continue;
}
TreeSelect childNode = new TreeSelect();
childNode.setTreeKey(item.getMaterialId().toString());
// 检查是否有子节点
if (parentVersionMap.containsKey(item.getMaterialId())) {
// 有子节点,需要处理每个版本
Map<String, List<ProdMaterialBomVo>> versionMap = parentVersionMap.get(item.getMaterialId());
if (versionMap.size() == 1) {
// 只有一个版本
String version = versionMap.keySet().iterator().next();
childNode.setLabel(item.getMaterialId() + " (v" + version + ")");
childNode.setMaterialBomVersion(version);
childNode.setChildren(buildChildren(item.getMaterialId(), versionMap.get(version), parentVersionMap));
} else {
// 多个版本,需要创建中间节点
childNode.setLabel(item.getMaterialId().toString());
childNode.setChildren(new ArrayList<>());
for (Map.Entry<String, List<ProdMaterialBomVo>> versionEntry : versionMap.entrySet()) {
String version = versionEntry.getKey();
TreeSelect versionNode = new TreeSelect();
versionNode.setTreeKey(item.getMaterialId() + "_" + version);
versionNode.setLabel(item.getMaterialId() + " (v" + version + ")");
versionNode.setMaterialBomVersion(version);
versionNode.setChildren(buildChildren(item.getMaterialId(), versionEntry.getValue(), parentVersionMap));
childNode.getChildren().add(versionNode);
}
}
} else {
// 没有子节点,直接创建
childNode.setLabel(item.getMaterialId().toString());
}
children.add(childNode);
}
return children;
}
// private static void printTree(List<ProdMaterialBomVo> nodes, int indent) {
// for (ProdMaterialBomVo node : nodes) {
// System.out.println(" ".repeat(indent) + node.getParentMaterialName()+"["+node.getMaterialBomVersion()+"]"+node.getMaterialName());
// printTree(node.getChildren(), indent + 1);
// }
// }
// private List<TreeSelect> buildMaterialBomTree(List<ProdMaterialBomVo> prodMaterialBomVos) {
// // 用于存储所有节点
// Map<String, TreeSelect> nodeMap = new HashMap<>();
// // 用于存储根节点
// List<TreeSelect> rootNodes = new ArrayList<>();
// // 用于识别哪些materialId是父节点
// Map<String, Boolean> isParentMap = new HashMap<>();
//
// // 第一次遍历:创建所有节点并识别父节点
// for (ProdMaterialBomVo bom : prodMaterialBomVos) {
// // 创建节点
// TreeSelect node = new TreeSelect(bom);
// String nodeKey = bom.getMaterialId() + "|" + bom.getMaterialBomVersion();
// nodeMap.put(nodeKey, node);
//
// // 标记此materialId是某个节点的parentId
// isParentMap.put(bom.getParentId(), true);
// }
//
// // 第二次遍历:建立父子关系
// for (ProdMaterialBomVo bom : prodMaterialBomVos) {
// String nodeKey = bom.getMaterialId() + "|" + bom.getMaterialBomVersion();
// String parentKey = bom.getParentId() + "|" + bom.getMaterialBomVersion();
//
// TreeSelect currentNode = nodeMap.get(nodeKey);
// TreeSelect parentNode = nodeMap.get(parentKey);
//
// if (parentNode != null) {
// // 添加到父节点的子列表
// parentNode.addChild(currentNode);
// } else if (!isParentMap.containsKey(bom.getMaterialId())) {
// // 如果当前节点的materialId从未作为parentId出现过则是根节点
// rootNodes.add(currentNode);
// }
// }
//
// return rootNodes;
// }
/**
*
*
* @param prodMaterialBomVos
* @return
*/
private List<ProdMaterialBomVo> buildMaterialBomTree(List<ProdMaterialBomVo> prodMaterialBomVos) {
private List<ProdMaterialBomVo> buildMaterialBomTreeNodesDiscard(List<ProdMaterialBomVo> prodMaterialBomVos) {
List<ProdMaterialBomVo> returnList = new ArrayList<ProdMaterialBomVo>();
/**
* parent
@ -334,10 +697,10 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
.toList();
//2、过滤出parentId相同的
//2、过滤出parentId-materialBomVersion相同的
List<ProdMaterialBomVo> distinctParentIdVoList = topMaterialBomVos.stream()
.collect(Collectors.toMap(
ProdMaterialBomVo::getParentId, // 以parentId作为key
ProdMaterialBomVo::getKey, // 以parentId-materialBomVersion作为key
Function.identity(), // 以对象本身作为value
(existing, replacement) -> existing // 如果遇到重复的key保留已有的对象
))
@ -355,6 +718,7 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
topProdMaterialBomVo.setMaterialTypeName(prodMaterialBomVo.getParentMaterialTypeName());//设置parent的物料类型名称
topProdMaterialBomVo.setMaterialName(prodMaterialBomVo.getParentMaterialName());//设置parent的物料名称
topProdMaterialBomVo.setMaterialBomVersion(prodMaterialBomVo.getMaterialBomVersion());
topProdMaterialBomVo.setActiveFlag(prodMaterialBomVo.getActiveFlag());
prodMaterialBomVos.add(topProdMaterialBomVo);
recursionFn(prodMaterialBomVos, topProdMaterialBomVo);
@ -379,30 +743,10 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
returnList = prodMaterialBomVos;
}
return returnList;
}
/**
*
*
* @param prodMaterialBomVos bom
* @return
*/
private List<TreeSelect> buildMaterialBomTreeSelect(List<ProdMaterialBomVo> prodMaterialBomVos) {
// 根据物料bom版本号group不能的版本是不同的树。使用 groupingBy 将 List 转换为 Map<String, List<ProdMaterialBomVo>>
Map<String, List<ProdMaterialBomVo>> prodMaterialBomVoMap = prodMaterialBomVos.stream()
.collect(Collectors.groupingBy(ProdMaterialBomVo::getMaterialBomVersion));
List<ProdMaterialBomVo> allMaterialBomTrees = new ArrayList<>();
// 根据物料版本号build树
prodMaterialBomVoMap.forEach((materialBomVersion, vos) -> {
List<ProdMaterialBomVo> materialBomTrees = buildMaterialBomTree(vos);
allMaterialBomTrees.addAll(materialBomTrees);
});
return allMaterialBomTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
}
/**
*
@ -410,14 +754,21 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService {
private void recursionFn(List<ProdMaterialBomVo> list, ProdMaterialBomVo parent) {
// 获取子节点
List<ProdMaterialBomVo> childList = getChildList(list, parent);
if(childList == null || childList.isEmpty()){
System.out.println(parent.getMaterialBomId()+"----");
// parent.setMaterialBomVersion("");
}else{
System.out.println(parent.getMaterialBomId()+"****"+childList.get(0).getMaterialBomVersion());
// parent.setMaterialBomVersion(childList.get(0).getMaterialBomVersion());
}
parent.setChildren(childList);
// 递归处理子节点
for (ProdMaterialBomVo child : childList) {
// 确保子节点继承 BOM 版本信息
if (StringUtils.isBlank(child.getMaterialBomVersion()) && StringUtils.isNotBlank(parent.getMaterialBomVersion())) {
child.setMaterialBomVersion(parent.getMaterialBomVersion());
}
// 父节点显示bom版本信息一个父子记录的信息的bom版本确保子节点继承 BOM 版本信息
// if (StringUtils.isNotBlank(child.getMaterialBomVersion())) {
// parent.setMaterialBomVersion(child.getMaterialBomVersion());
// }
recursionFn(list, child);
}
}

@ -17,9 +17,14 @@ import org.dromara.mes.domain.bo.ProdPlanInfoBo;
import org.dromara.mes.domain.vo.MesProductPlanEditVo;
import org.dromara.mes.domain.vo.PlanMonitorVo;
import org.dromara.mes.domain.vo.ProdPlanInfoVo;
import org.dromara.mes.enums.PlanEventEnum;
import org.dromara.mes.enums.PlanStatusEnum;
import org.dromara.mes.mapper.ProdPlanInfoMapper;
import org.dromara.mes.service.IProdPlanInfoService;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
@ -27,6 +32,15 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.stereotype.Service;
import org.springframework.statemachine.support.DefaultStateMachineContext;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.service.StateMachineService;
/**
* Service
*
@ -37,10 +51,20 @@ import java.util.Map;
@Service
public class ProdPlanInfoServiceImpl implements IProdPlanInfoService {
private final Logger log = LoggerFactory.getLogger(ProdPlanInfoServiceImpl.class);
private static final String PLAN_ID_HEADER = "planId";
private final ProdPlanInfoMapper baseMapper;
private final DynamicBaseSqlMapper<ProdPlanInfo> dynamicBaseSqlMapper;
@Autowired
private StateMachineFactory<PlanStatusEnum, PlanEventEnum> stateMachineFactory;
/**
*
*
@ -104,7 +128,7 @@ public class ProdPlanInfoServiceImpl implements IProdPlanInfoService {
.eq(bo.getPlanAmount() != null, ProdPlanInfo::getPlanAmount, bo.getPlanAmount())
.eq(bo.getDispatchAmount() != null, ProdPlanInfo::getDispatchAmount, bo.getDispatchAmount())
.eq(bo.getCompleteAmount() != null, ProdPlanInfo::getCompleteAmount, bo.getCompleteAmount())
.between(StringUtils.isNotNull(bo.getPlanBeginTime()) && StringUtils.isNotNull(bo.getPlanEndTime()),
.between(StringUtils.isNotNull(bo.getPlanBeginTime()) && StringUtils.isNotNull(bo.getPlanEndTime()),
ProdPlanInfo::getPlanBeginTime, bo.getPlanBeginTime(), bo.getPlanEndTime())
.eq(bo.getRealBeginTime() != null, ProdPlanInfo::getRealBeginTime, bo.getRealBeginTime())
.eq(bo.getRealEndTime() != null, ProdPlanInfo::getRealEndTime, bo.getRealEndTime())
@ -344,4 +368,61 @@ public class ProdPlanInfoServiceImpl implements IProdPlanInfoService {
return lqw;
}
private PlanEventEnum determineEvent(PlanStatusEnum currentStatus, PlanStatusEnum targetStatus) {
// 根据当前状态和目标状态确定需要触发的事件
if (currentStatus == PlanStatusEnum.CREATED && targetStatus == PlanStatusEnum.PLANNED) {
return PlanEventEnum.PLAN;
}
if (currentStatus == PlanStatusEnum.PLANNED && targetStatus == PlanStatusEnum.IN_PROGRESS) {
return PlanEventEnum.START;
}
// ... 其他状态转换逻辑
throw new IllegalStateException("No valid event for transition from " +
currentStatus + " to " + targetStatus);
}
public boolean sendEvent(Long planId, PlanEventEnum event) {
ProdPlanInfoVo plan = baseMapper.selectVoById(planId);
ProdPlanInfo add = MapstructUtils.convert(plan, ProdPlanInfo.class);
StateMachine<PlanStatusEnum, PlanEventEnum> sm = build(add);
Message<PlanEventEnum> message = MessageBuilder.withPayload(event)
.setHeader("planId", planId)
.build();
boolean result = sm.sendEvent(message);
if (result) {
// 保存字符串状态码到数据库
plan.setPlanStatus(sm.getState().getId().getCode());
baseMapper.updateById(add);
log.info("Plan {} status changed to {} after event {}",
planId, sm.getState().getId(), event);
}
return result;
}
private StateMachine<PlanStatusEnum, PlanEventEnum> build(ProdPlanInfo plan) {
StateMachine<PlanStatusEnum, PlanEventEnum> sm = stateMachineFactory.getStateMachine(String.valueOf(plan.getPlanId()));
sm.stop();
sm.getStateMachineAccessor()
.doWithAllRegions(sma -> {
sma.resetStateMachine(new DefaultStateMachineContext<>(
PlanStatusEnum.fromCode(plan.getPlanStatus()), null, null, null));
});
sm.start();
return sm;
}
}

@ -4,43 +4,103 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.mes.mapper.ProdMaterialBomMapper">
<select id="selectMaterialBomJoinList" parameterType="ProdMaterialBomBo" resultType="ProdMaterialBomVo">
select
pmb.material_bom_id,
pmb.material_id,
pmb.parent_id,
pmb.material_type_id,
pmb.material_bom_version,
pmb.parent_material_type_id,
pmb.parent_standard_amount,
pmb.parent_unit_id,
pmb.top_flag,
pmb.material_bom_version,
pmb.active_flag,
bmi.material_name,
bmt.matrial_type_name as material_type_name,
bmip.material_name as parent_material_name,
bmt.matrial_type_name as material_type_name,
bmtp.matrial_type_name as parent_material_type_name
from prod_material_bom pmb
left join base_material_info bmi on pmb.material_id=bmi.material_id
left join base_material_type bmt on pmb.material_type_id = bmt.matrial_type_id
left join base_material_info bmip on pmb.parent_id=bmip.material_id
left join base_material_type bmt on bmi.material_type_id = bmt.matrial_type_id
left join base_material_type bmtp on pmb.parent_material_type_id = bmtp.matrial_type_id
<where>
and pmb.delete_flag='0'
<if test="materialTypeCode != null and materialTypeCode != ''">and bmt.matrial_type_code like concat('%', #{materialTypeCode},
'%')
</if>
<if test="materialTypeName != null and materialTypeName != ''">and bmt.matrial_type_name like concat('%', #{materialTypeName},
'%')
</if>
<if test="materialBomVersion != null and materialBomVersion != ''">and pmb.material_bom_version = #{materialBomVersion}
</if>
<if test="parentId != null ">and pmb.parent_id = #{parentId}</if>
</where>
order by pmb.material_bom_id, pmb.material_bom_version desc
order by pmb.material_bom_id desc
</select>
<!-- <select id="selectMaterialBomJoinList" parameterType="ProdMaterialBomBo" resultType="ProdMaterialBomVo">-->
<!-- WITH BomCTE AS (-->
<!-- SELECT-->
<!-- b.parent_id,-->
<!-- b.material_id,-->
<!-- b.material_bom_version,-->
<!-- b.parent_unit_id,-->
<!-- b.active_flag,-->
<!-- b.parent_standard_amount,-->
<!-- b.material_type_id,-->
<!-- b.parent_material_type_id,-->
<!-- b.tenant_id ,-->
<!-- m_parent.material_name AS parent_material_name,-->
<!-- m_parent.material_code AS parent_material_code,-->
<!-- m_child.material_name,-->
<!-- m_child.material_code,-->
<!-- bmt_parent.matrial_type_name as parent_material_type_name,-->
<!-- bmt_child.matrial_type_name as material_type_name,-->
<!-- 1 AS level,-->
<!-- CAST(m_parent.material_name + '[' + b.material_bom_version + ']' + ' > ' + m_child.material_name AS VARCHAR(500)) AS path-->
<!-- FROM prod_material_bom b-->
<!-- JOIN base_material_info m_parent ON b.parent_id = m_parent.material_id-->
<!-- JOIN base_material_info m_child ON b.material_id = m_child.material_id-->
<!-- JOIN base_material_type bmt_parent ON b.parent_material_type_id = bmt_parent.matrial_type_id-->
<!-- JOIN base_material_type bmt_child ON b.material_type_id = bmt_child.matrial_type_id-->
<!-- <where>-->
<!-- b.delete_flag='0'-->
<!-- <if test="parentId != null and parentId != ''">-->
<!-- AND b.parent_id = #{parentId}-->
<!-- </if>-->
<!-- AND b.material_bom_desc LIKE '%测%'-->
<!-- </where>-->
<!-- UNION ALL-->
<!-- SELECT-->
<!-- b.parent_id,-->
<!-- b.material_id,-->
<!-- b.material_bom_version,-->
<!-- b.parent_unit_id,-->
<!-- b.active_flag,-->
<!-- b.parent_standard_amount,-->
<!-- b.material_type_id,-->
<!-- b.parent_material_type_id,-->
<!-- b.tenant_id ,-->
<!-- m_parent.material_name AS parent_material_name,-->
<!-- m_parent.material_code AS parent_material_code,-->
<!-- m_child.material_name,-->
<!-- m_child.material_code,-->
<!-- bmt_parent.matrial_type_name as parent_material_type_name,-->
<!-- bmt_child.matrial_type_name as material_type_name,-->
<!-- c.level + 1,-->
<!-- CAST(c.path + '[' + b.material_bom_version + ']' + ' > ' + m_child.material_name AS VARCHAR(500)) AS path-->
<!-- FROM BomCTE c-->
<!-- JOIN prod_material_bom b ON c.material_id = b.parent_id-->
<!-- JOIN base_material_info m_parent ON b.parent_id = m_parent.material_id-->
<!-- JOIN base_material_info m_child ON b.material_id = m_child.material_id-->
<!-- JOIN base_material_type bmt_parent ON b.parent_material_type_id = bmt_parent.matrial_type_id-->
<!-- JOIN base_material_type bmt_child ON b.material_type_id = bmt_child.matrial_type_id-->
<!-- WHERE c.level &lt; 100-->
<!-- AND b.delete_flag='0'-->
<!-- )-->
<!-- SELECT * FROM BomCTE ORDER BY level, path-->
<!-- </select>-->
<select id="selectParentMaterialBomJoin" parameterType="ProdMaterialBomBo" resultType="ProdMaterialBomVo">
select
top 1
@ -51,6 +111,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
pmb.parent_material_type_id,
pmb.parent_standard_amount,
pmb.parent_unit_id,
pmb.active_flag,
pmb.material_bom_desc,
bmt.matrial_type_name as parent_material_type_name
from base_material_info bmi
left join prod_material_bom pmb on pmb.parent_id=bmi.material_id and pmb.material_bom_version = #{materialBomVersion} and pmb.delete_flag='0'
@ -117,4 +179,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="selectNextMaterialBomVersion" parameterType="Long" resultType="String">
SELECT RIGHT('0' + CAST(ISNULL(MAX(CAST(material_bom_version AS INT)), 0) + 1 AS VARCHAR), 2)
FROM prod_material_bom where parent_id = #{parentId}
</select>
</mapper>

Loading…
Cancel
Save