From 79d393f414a9dcb4f6f4cf8d9d593aafbc787891 Mon Sep 17 00:00:00 2001 From: xs Date: Fri, 16 May 2025 18:05:37 +0800 Subject: [PATCH] =?UTF-8?q?1.3.3=EF=BC=9A=20=E5=90=8E=E7=AB=AF=EF=BC=9A?= =?UTF-8?q?=E7=89=A9=E6=96=99bom=E5=AE=8C=E5=96=84=EF=BC=8C=E6=A0=91?= =?UTF-8?q?=E4=B8=8D=E6=A0=B9=E6=8D=AEbom=E7=89=88=E6=9C=AC=E9=80=92?= =?UTF-8?q?=E5=BD=92=EF=BC=8C=E5=A2=9E=E5=8A=A0=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/constant/HwMomMesConstants.java | 3 + .../controller/ProdMaterialBomController.java | 24 + .../controller/ProdPlanInfoController.java | 12 + .../mes/domain/vo/ProdMaterialBomVo.java | 4 + .../dromara/mes/domain/vo/ProdPlanInfoVo.java | 5 +- .../org/dromara/mes/domain/vo/TreeSelect.java | 46 ++ .../mes/mapper/ProdMaterialBomMapper.java | 11 + .../mes/service/IProdMaterialBomService.java | 17 + .../mes/service/IProdPlanInfoService.java | 5 + .../impl/ProdMaterialBomServiceImpl.java | 489 +++++++++++++++--- .../service/impl/ProdPlanInfoServiceImpl.java | 85 ++- .../mapper/mes/ProdMaterialBomMapper.xml | 90 +++- 12 files changed, 708 insertions(+), 83 deletions(-) diff --git a/ruoyi-common/hwmom-common-mom/src/main/java/org/dromara/common/constant/HwMomMesConstants.java b/ruoyi-common/hwmom-common-mom/src/main/java/org/dromara/common/constant/HwMomMesConstants.java index c44bccf..4d62621 100644 --- a/ruoyi-common/hwmom-common-mom/src/main/java/org/dromara/common/constant/HwMomMesConstants.java +++ b/ruoyi-common/hwmom-common-mom/src/main/java/org/dromara/common/constant/HwMomMesConstants.java @@ -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";//设计中 } diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/controller/ProdMaterialBomController.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/controller/ProdMaterialBomController.java index fd87905..ab81121 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/controller/ProdMaterialBomController.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/controller/ProdMaterialBomController.java @@ -135,6 +135,19 @@ public class ProdMaterialBomController extends BaseController { return R.ok(list); } + + /** + * 查询物料BOM信息列表 + */ + @SaCheckPermission("mes:materialBom:add") + @GetMapping("/selectNextMaterialBomVersion/{parentId}") + public R selectNextMaterialBomVersion(@NotNull(message = "不能为空") + @PathVariable Long parentId) { + String nextMaterialBomVersion = prodMaterialBomService.selectNextMaterialBomVersion(parentId); + return R.ok("success",nextMaterialBomVersion); + } + + /** * 根据结构BOM批量插入物料清单BOM。 */ @@ -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 publish(@RequestBody ProdMaterialBomBo bo) { + return toAjax(prodMaterialBomService.publishByBo(bo)); + } } diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/controller/ProdPlanInfoController.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/controller/ProdPlanInfoController.java index a6fa6f5..3a1b610 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/controller/ProdPlanInfoController.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/controller/ProdPlanInfoController.java @@ -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); + } } diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/ProdMaterialBomVo.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/ProdMaterialBomVo.java index ff9cdf2..3b08627 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/ProdMaterialBomVo.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/ProdMaterialBomVo.java @@ -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; + } } diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/ProdPlanInfoVo.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/ProdPlanInfoVo.java index 597a1bb..0e9471c 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/ProdPlanInfoVo.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/ProdPlanInfoVo.java @@ -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; /** diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/TreeSelect.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/TreeSelect.java index 21001a1..675de65 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/TreeSelect.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/domain/vo/TreeSelect.java @@ -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; + } } diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/mapper/ProdMaterialBomMapper.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/mapper/ProdMaterialBomMapper.java index 0b67d90..0799e7d 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/mapper/ProdMaterialBomMapper.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/mapper/ProdMaterialBomMapper.java @@ -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 materialBomBos); + /** + * 根据父级物料ID获取下一个版本号 + * @param parentId + * @return + */ + public String selectNextMaterialBomVersion(Long parentId); + /** * 根据结构BOM批量插入物料清单BOM。 * @param boList 需要插入的物料清单BOM列表。 diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/IProdPlanInfoService.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/IProdPlanInfoService.java index c5b3cc0..2dcaa96 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/IProdPlanInfoService.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/IProdPlanInfoService.java @@ -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 queryMoritorList(ProdPlanInfoBo bo); + + + public boolean sendEvent(Long planId, PlanEventEnum event); + } diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdMaterialBomServiceImpl.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdMaterialBomServiceImpl.java index 99257c5..5d9fcbf 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdMaterialBomServiceImpl.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdMaterialBomServiceImpl.java @@ -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 allVosByParentId = this.queryList(bo); + if (allVosByParentId == null || allVosByParentId.isEmpty()) { + throw new ServiceException("数据已删除"); + } + + //再过滤出当前要发布的版本信息 + List 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 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 materialBomBos) { Collection 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 lqw = buildPlanQueryWrapper(queryBo); - - /** - * 查询半制品计划、成型计划、硫化计划中有没有使用此bom - */ - List semiFinishedPlanInfoVos = prodPlanInfoMapper.selectProdPlanInfoList(semiFinishedTableName, lqw); - if (semiFinishedPlanInfoVos != null && !semiFinishedPlanInfoVos.isEmpty()) { - List 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 modelingPlanInfoVos = prodPlanInfoMapper.selectProdPlanInfoList(modelingTableName, lqw); - if (modelingPlanInfoVos != null && !modelingPlanInfoVos.isEmpty()) { - List planCodes = modelingPlanInfoVos.stream() - .map(ProdPlanInfoVo::getPlanCode) - .toList(); - - throw new ServiceException("成型计划中计划编号[" + planCodes.toString() + "]已经使用此bom,不能修改"); - } - - List vulcanizingPlanInfoVos = prodPlanInfoMapper.selectProdPlanInfoList(vulcanizingTableName, lqw); - if (vulcanizingPlanInfoVos != null && !vulcanizingPlanInfoVos.isEmpty()) { - List 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 lqw = buildPlanQueryWrapper(queryBo); +// +// /** +// * 查询半制品计划、成型计划、硫化计划中有没有使用此bom +// */ +// List semiFinishedPlanInfoVos = prodPlanInfoMapper.selectProdPlanInfoList(semiFinishedTableName, lqw); +// if (semiFinishedPlanInfoVos != null && !semiFinishedPlanInfoVos.isEmpty()) { +// List planCodes = semiFinishedPlanInfoVos.stream() +// .map(ProdPlanInfoVo::getPlanCode) +// .toList(); +// +// throw new ServiceException("半制品计划中计划编号[" + planCodes.toString() + "]已经使用此bom,不能修改"); +// } +// +// List modelingPlanInfoVos = prodPlanInfoMapper.selectProdPlanInfoList(modelingTableName, lqw); +// if (modelingPlanInfoVos != null && !modelingPlanInfoVos.isEmpty()) { +// List planCodes = modelingPlanInfoVos.stream() +// .map(ProdPlanInfoVo::getPlanCode) +// .toList(); +// +// throw new ServiceException("成型计划中计划编号[" + planCodes.toString() + "]已经使用此bom,不能修改"); +// } +// +// List vulcanizingPlanInfoVos = prodPlanInfoMapper.selectProdPlanInfoList(vulcanizingTableName, lqw); +// if (vulcanizingPlanInfoVos != null && !vulcanizingPlanInfoVos.isEmpty()) { +// List 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; + } + + /** * 根据结构BOM批量插入物料清单BOM。 * @@ -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 selectMaterialBomTreeList(ProdMaterialBomBo bo) { List prodMaterialBomVos = baseMapper.selectMaterialBomJoinList(bo); - return buildMaterialBomTreeSelect(prodMaterialBomVos); + return buildMaterialBomTree(prodMaterialBomVos); } - /** * 构建前端所需要树结构 * + * @param bomList 生产bom结构树列表 + * @return 下拉树结构列表 + */ + private List buildMaterialBomTree(List bomList) { + // 1. 建立索引 + Map> parentVersionGroup = new HashMap<>(); + Map> materialVersions = new HashMap<>(); + Map materialNameMap = new HashMap<>(); + Map materialTypeIdMap = new HashMap<>(); + Map materialTypeNameMap = new HashMap<>(); + Map 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 topLevelParentIds = bomList.stream() + .map(ProdMaterialBomVo::getParentId) + .filter(parentId -> !materialVersions.containsKey(parentId)) + .collect(Collectors.toSet()); + + // 3. 构建树结构 + List tree = new ArrayList<>(); + + for (Long topParentId : topLevelParentIds) { + // 获取该顶级节点的所有版本 + Set 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 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 materialNameMap, Map 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 materialNameMap,Map materialTypeIdMap,Map 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> parentVersionGroup, + Map materialNameMap,Map materialTypeIdMap,Map 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 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 buildChildren(Long currentParentId,List items, + Map>> parentVersionMap) { + List 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> 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> 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 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 buildMaterialBomTree(List prodMaterialBomVos) { +// // 用于存储所有节点 +// Map nodeMap = new HashMap<>(); +// // 用于存储根节点 +// List rootNodes = new ArrayList<>(); +// // 用于识别哪些materialId是父节点 +// Map 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 buildMaterialBomTree(List prodMaterialBomVos) { + private List buildMaterialBomTreeNodesDiscard(List prodMaterialBomVos) { List returnList = new ArrayList(); /** * 由于顶级节点的parent没有父级对象,需要虚拟新增一个 @@ -334,10 +697,10 @@ public class ProdMaterialBomServiceImpl implements IProdMaterialBomService { .toList(); - //2、过滤出parentId相同的 + //2、过滤出parentId-materialBomVersion相同的 List 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 buildMaterialBomTreeSelect(List prodMaterialBomVos) { - // 根据物料bom版本号group,不能的版本是不同的树。使用 groupingBy 将 List 转换为 Map> - Map> prodMaterialBomVoMap = prodMaterialBomVos.stream() - .collect(Collectors.groupingBy(ProdMaterialBomVo::getMaterialBomVersion)); - - List allMaterialBomTrees = new ArrayList<>(); - // 根据物料版本号build树 - prodMaterialBomVoMap.forEach((materialBomVersion, vos) -> { - List 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 list, ProdMaterialBomVo parent) { // 获取子节点 List 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); } } diff --git a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdPlanInfoServiceImpl.java b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdPlanInfoServiceImpl.java index d66cb76..a8011b4 100644 --- a/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdPlanInfoServiceImpl.java +++ b/ruoyi-modules/hwmom-mes/src/main/java/org/dromara/mes/service/impl/ProdPlanInfoServiceImpl.java @@ -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 dynamicBaseSqlMapper; + + @Autowired + private StateMachineFactory 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 sm = build(add); + + Message 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 build(ProdPlanInfo plan) { + StateMachine 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; + } + } diff --git a/ruoyi-modules/hwmom-mes/src/main/resources/mapper/mes/ProdMaterialBomMapper.xml b/ruoyi-modules/hwmom-mes/src/main/resources/mapper/mes/ProdMaterialBomMapper.xml index 7f12ae4..ea467c7 100644 --- a/ruoyi-modules/hwmom-mes/src/main/resources/mapper/mes/ProdMaterialBomMapper.xml +++ b/ruoyi-modules/hwmom-mes/src/main/resources/mapper/mes/ProdMaterialBomMapper.xml @@ -4,43 +4,103 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +