فهرست منبع

Merge remote-tracking branch 'origin/master'

lipenghui 2 ماه پیش
والد
کامیت
77a8fc706d

+ 4 - 1
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotdeviceallotlog/vo/IotDeviceAllotSaveReqVO.java

@@ -17,7 +17,10 @@ public class IotDeviceAllotSaveReqVO {
     @NotNull(message = "设备id不能为空")
     private Long deviceId;
 
-    @Schema(description = "设备调拨前部门", example = "4801")
+    @Schema(description = "设备调拨前部门id", example = "4801")
+    private Long oldDeptId;
+
+    @Schema(description = "设备调拨后部门id", example = "4801")
     private Long deptId;
 
     @Schema(description = "调拨原因", example = "项目要求")

+ 7 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/iotmainworkorderbommaterial/vo/IotMainWorkOrderBomMaterialPageReqVO.java

@@ -9,6 +9,7 @@ import org.springframework.format.annotation.DateTimeFormat;
 
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
+import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
 
@@ -112,4 +113,10 @@ public class IotMainWorkOrderBomMaterialPageReqVO extends PageParam {
 
     @Schema(description = "设备id", example = "21957")
     private Long deviceId;
+
+    @Schema(description = "保养工单id集合", example = "21957")
+    private List<Long> workOrderIds;
+
+    @Schema(description = "保养工单明细bom节点id集合", example = "21957")
+    private List<Long> bomNodeIds;
 }

+ 1 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/IotDeviceMapper.java

@@ -61,6 +61,7 @@ public interface IotDeviceMapper extends BaseMapperX<IotDeviceDO> {
 
     default List<IotDeviceDO> selectList(IotDevicePageReqVO reqVO) {
         return selectList(new LambdaQueryWrapperX<IotDeviceDO>()
+                .inIfPresent(IotDeviceDO::getDeptId, reqVO.getDeviceIds())
                 .likeIfPresent(IotDeviceDO::getDeviceCode, reqVO.getDeviceCode())
                 .likeIfPresent(IotDeviceDO::getDeviceName, reqVO.getDeviceName())
                 .eqIfPresent(IotDeviceDO::getBrand, reqVO.getBrand())

+ 5 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmainworkorderbom/IotMainWorkOrderBomMapper.java

@@ -1,11 +1,13 @@
 package cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorderbom;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo.IotMainWorkOrderBomPageReqVO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbom.IotMainWorkOrderBomDO;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 
@@ -109,4 +111,7 @@ public interface IotMainWorkOrderBomMapper extends BaseMapperX<IotMainWorkOrderB
                 .betweenIfPresent(IotMainWorkOrderBomDO::getCreateTime, reqVO.getCreateTime()));
     }
 
+    @DataPermission(enable = false)
+    List<IotMainWorkOrderBomDO> historyWorkOrderBomS(@Param("deptIds") List<Long> deptIds, @Param("deviceIds") List<Long> deviceIds);
+
 }

+ 32 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/dal/mysql/iotmainworkorderbommaterial/IotMainWorkOrderBomMaterialMapper.java

@@ -53,6 +53,38 @@ public interface IotMainWorkOrderBomMaterialMapper extends BaseMapperX<IotMainWo
                 .orderByDesc(IotMainWorkOrderBomMaterialDO::getId));
     }
 
+    default List<IotMainWorkOrderBomMaterialDO> selectList(IotMainWorkOrderBomMaterialPageReqVO reqVO) {
+        return selectList(new LambdaQueryWrapperX<IotMainWorkOrderBomMaterialDO>()
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getMainPlanId, reqVO.getMainPlanId())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getWorkOrderId, reqVO.getWorkOrderId())
+                .inIfPresent(IotMainWorkOrderBomMaterialDO::getWorkOrderId, reqVO.getWorkOrderIds())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getMainWorkOrderDetailId, reqVO.getMainWorkOrderDetailId())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getDeviceCategoryId, reqVO.getDeviceCategoryId())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getBomNodeId, reqVO.getBomNodeId())
+                .inIfPresent(IotMainWorkOrderBomMaterialDO::getBomNodeId, reqVO.getBomNodeIds())
+                .likeIfPresent(IotMainWorkOrderBomMaterialDO::getName, reqVO.getName())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getCode, reqVO.getCode())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getMaterialId, reqVO.getMaterialId())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getMaterialCode, reqVO.getMaterialCode())
+                .likeIfPresent(IotMainWorkOrderBomMaterialDO::getMaterialName, reqVO.getMaterialName())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getQuantity, reqVO.getQuantity())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getUnit, reqVO.getUnit())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getUnitPrice, reqVO.getUnitPrice())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getTotalPrice, reqVO.getTotalPrice())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getKilometerCycle, reqVO.getKilometerCycle())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getKiloCycleLead, reqVO.getKiloCycleLead())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getTimePeriod, reqVO.getTimePeriod())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getTimePeriodLead, reqVO.getTimePeriodLead())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getNaturalDatePeriod, reqVO.getNaturalDatePeriod())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getNaturalDatePeriodLead, reqVO.getNaturalDatePeriodLead())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getMaterialSource, reqVO.getMaterialSource())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getInventoryAddress, reqVO.getInventoryAddress())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getSort, reqVO.getSort())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getStatus, reqVO.getStatus())
+                .eqIfPresent(IotMainWorkOrderBomMaterialDO::getRemark, reqVO.getRemark())
+                .betweenIfPresent(IotMainWorkOrderBomMaterialDO::getCreateTime, reqVO.getCreateTime()));
+    }
+
     @DataPermission(enable = false)
     IPage<IotMainWorkOrderBomMaterialRespVO> selectMaterialsBySapOrg(IPage<IotMainWorkOrderBomMaterialRespVO> page,
                                                                    @Param("parentDept") Long parentDept, @Param("materialCodes") List<String> materialCodes,

+ 28 - 20
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/sap/service/IotSapServiceImpl.java

@@ -414,7 +414,7 @@ public class IotSapServiceImpl implements IotSapService {
 
     @Override
     public void processSapStock(String factoryCode, List<IotSapStockVO> sapStocks) {
-        // 查询出所有工厂 对应的 deptId 新增本地库存时 可以匹配
+        // 查询出所有库存地点 对应的 deptId 新增本地库存时 可以匹配  工厂+库存地点 确定唯一值 因为 不同工厂的库存地点code可能重复
         List<SapOrgRespDTO> storageLocations = TenantUtils.execute(1L, () -> sapOrgApi.getSapOrgByType(3));
         // 查询所有工厂
         List<SapOrgRespDTO> factories = TenantUtils.execute(1L, () -> sapOrgApi.getSapOrgByType(1));
@@ -437,9 +437,14 @@ public class IotSapServiceImpl implements IotSapService {
         });
         // 库存地点集合
         storageLocations.forEach(location -> {
-            stockLocationCodeIdPair.put(location.getId(), location.getStorageLocationCode());
-            storageLocationIdPair.put(location.getStorageLocationCode(), location.getId());
-            stockLocationNamePair.put(location.getStorageLocationCode(), location.getStorageLocationName());
+            System.out.println("当前库存地点信息:" + location.getFactoryCode() + " - " + location.getStorageLocationCode());
+            String uniqueKey = StrUtil.join("-", location.getFactoryCode(), location.getStorageLocationCode());
+            // stockLocationCodeIdPair.put(location.getId(), location.getStorageLocationCode());
+            stockLocationCodeIdPair.put(location.getId(), uniqueKey);
+            // storageLocationIdPair.put(location.getStorageLocationCode(), location.getId());
+            storageLocationIdPair.put(uniqueKey, location.getId());
+            // stockLocationNamePair.put(location.getStorageLocationCode(), location.getStorageLocationName());
+            stockLocationNamePair.put(uniqueKey, location.getStorageLocationName());
         });
         // 查询所有部门
         List<DeptRespDTO> depts = TenantUtils.execute(1L, () -> deptApi.getDeptList());
@@ -448,11 +453,11 @@ public class IotSapServiceImpl implements IotSapService {
             Set<Long> stockLocationIds = dept.getStockLocationIds();
             // 循环遍历 stockLocationIds
             if (CollUtil.isNotEmpty(stockLocationIds)) {
-                stockLocationIds.forEach(location -> {
-                    if (stockLocationCodeIdPair.containsKey(location)) {
-                        // 当前部门设置的 库存地点
-                        String locationCode = stockLocationCodeIdPair.get(location);
-                        locationCodeDeptIdPair.put(locationCode, dept.getId());
+                stockLocationIds.forEach(locationId -> {
+                    if (stockLocationCodeIdPair.containsKey(locationId)) {
+                        // 当前部门设置的 库存地点 uniqueKey = 工厂编码+库存地点编码
+                        String uniqueKey = stockLocationCodeIdPair.get(locationId);
+                        locationCodeDeptIdPair.put(uniqueKey, dept.getId());
                     }
                 });
             }
@@ -462,7 +467,8 @@ public class IotSapServiceImpl implements IotSapService {
         List<IotSapStockDO> existStocks = TenantUtils.execute(1L, () -> iotSapStockMapper.selectList());
         if (CollUtil.isNotEmpty(existStocks)) {
             existStockKeys = existStocks.stream()
-                    .filter(stk -> ObjUtil.isNotEmpty(stk) && StrUtil.isNotBlank(stk.getMaterialCode()) && ObjUtil.isNotEmpty(stk.getStorageLocationId()))  // 过滤非空对象和非空code
+                    // 过滤非空对象和非空code
+                    .filter(stk -> ObjUtil.isNotEmpty(stk) && StrUtil.isNotBlank(stk.getMaterialCode()) && ObjUtil.isNotEmpty(stk.getStorageLocationId()))
                     .map(stk -> StrUtil.join("-", String.valueOf(stk.getStorageLocationId()), stk.getMaterialCode()))
                     .collect(Collectors.toSet());
         }
@@ -483,12 +489,12 @@ public class IotSapServiceImpl implements IotSapService {
         Set<String> finalExistStockKeys = existStockKeys;
         List<IotSapStockVO> newStocks = sapStocks.stream()
                 .filter(stk -> StrUtil.isNotBlank(stk.getMATNR()) && StrUtil.isNotBlank(stk.getLGORT())
-                        && storageLocationIdPair.containsKey(stk.getLGORT()))
+                        && storageLocationIdPair.containsKey(StrUtil.join("-", stk.getWERKS(), stk.getLGORT())))
                 .filter(stk -> {
                     // 处理前导零:移除MATNR前的 00000000
                     String processedCode = stk.getMATNR().replaceFirst("^0+", "");
                     // 本地已经配置过库存地点 包含SAP库存接口返回的库存地点
-                    Long storageLocationId = storageLocationIdPair.get(stk.getLGORT());
+                    Long storageLocationId = storageLocationIdPair.get(StrUtil.join("-", stk.getWERKS(), stk.getLGORT()));
                     return !finalExistStockKeys.contains(StrUtil.join("-", storageLocationId, processedCode));
                 })
                 .collect(Collectors.toList());
@@ -498,10 +504,11 @@ public class IotSapServiceImpl implements IotSapService {
         if (CollUtil.isNotEmpty(newStocks)) {
             newStocks.forEach(stock -> {
                 // 只保存pms维护过库存地点的数据
-                if (locationCodeDeptIdPair.containsKey(stock.getLGORT())) {
+                String uniqueKey = StrUtil.join("-", stock.getWERKS(), stock.getLGORT());
+                if (locationCodeDeptIdPair.containsKey(uniqueKey)) {
                     IotSapStockDO sapStock = new IotSapStockDO();
                     // 部门id
-                    sapStock.setDeptId(locationCodeDeptIdPair.get(stock.getLGORT()));
+                    sapStock.setDeptId(locationCodeDeptIdPair.get(uniqueKey));
                     // 工厂id
                     if (factoryIdPair.containsKey(stock.getWERKS())) {
                         sapStock.setFactoryId(factoryIdPair.get(stock.getWERKS()));
@@ -511,12 +518,12 @@ public class IotSapServiceImpl implements IotSapService {
                         sapStock.setFactory(factoryNamePair.get(stock.getWERKS()));
                     }
                     // 库存地点id
-                    if (storageLocationIdPair.containsKey(stock.getLGORT())) {
-                        sapStock.setStorageLocationId(storageLocationIdPair.get(stock.getLGORT()));
+                    if (storageLocationIdPair.containsKey(uniqueKey)) {
+                        sapStock.setStorageLocationId(storageLocationIdPair.get(uniqueKey));
                     }
                     // 库存地点名称
-                    if (stockLocationNamePair.containsKey(stock.getLGORT())) {
-                        sapStock.setProjectDepartment(stockLocationNamePair.get(stock.getLGORT()));
+                    if (stockLocationNamePair.containsKey(uniqueKey)) {
+                        sapStock.setProjectDepartment(stockLocationNamePair.get(uniqueKey));
                     }
                     // 物料编码 需要去掉前缀 00000000
                     sapStock.setMaterialCode(stock.getMATNR().replaceFirst("^0+", ""));
@@ -638,12 +645,13 @@ public class IotSapServiceImpl implements IotSapService {
     private Map<String, IotSapStockVO> createExistStockMap(List<IotSapStockVO> sapStocks, Set<String> existStockKeys, Map<String, Long> storageLocationIdPair) {
         return sapStocks.stream()
                 .filter(sapStock -> StrUtil.isNotBlank(sapStock.getMATNR()) &&
-                        ObjUtil.isNotEmpty(sapStock.getLGORT()) && storageLocationIdPair.containsKey(sapStock.getLGORT()))
+                        ObjUtil.isNotEmpty(sapStock.getLGORT()) &&
+                        storageLocationIdPair.containsKey(StrUtil.join("-", sapStock.getWERKS(), sapStock.getLGORT())))
                 .map(sapStock -> {
                     // 处理前导零:移除MATNR前的 00000000
                     String processedCode = sapStock.getMATNR().replaceFirst("^0+", "");
                     // 本地已经配置过库存地点 包含SAP库存接口返回的库存地点
-                    Long storageLocationId = storageLocationIdPair.get(sapStock.getLGORT());
+                    Long storageLocationId = storageLocationIdPair.get(StrUtil.join("-", sapStock.getWERKS(), sapStock.getLGORT()));
                     return new AbstractMap.SimpleEntry<>(StrUtil.join("-", storageLocationId, processedCode), sapStock);
                 })
                 .filter(entry -> existStockKeys.contains(entry.getKey()))

+ 54 - 28
yudao-module-pms/yudao-module-pms-biz/src/main/java/cn/iocoder/yudao/module/pms/service/iotmainworkorder/IotMainWorkOrderServiceImpl.java

@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@@ -17,8 +18,11 @@ import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorder.vo.IotMainW
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo.IotMainWorkOrderBomPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo.IotMainWorkOrderBomRespVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbom.vo.IotMainWorkOrderBomSaveReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo.IotMainWorkOrderBomMaterialPageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.iotmainworkorderbommaterial.vo.IotMainWorkOrderBomMaterialSaveReqVO;
+import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDevicePageReqVO;
 import cn.iocoder.yudao.module.pms.controller.admin.vo.IotDeviceRespVO;
+import cn.iocoder.yudao.module.pms.dal.dataobject.IotDeviceDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotlockstock.IotLockStockDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotmaintenancebom.IotMaintenanceBomDO;
 import cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorder.IotMainWorkOrderDO;
@@ -381,29 +385,6 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
      * @return
      */
     private List<Long> sortByNumericValue(Map<Long, String> map) {
-        /* return map.entrySet().stream()
-                // 转换数值并保留原始entry
-                .map(entry -> {
-                    try {
-                        // 移除所有字母后缀并转换为double
-                        String cleanValue = entry.getValue()
-                                .replaceAll("[A-Za-z]+$", "");
-                        double numericValue = Double.parseDouble(cleanValue);
-                        return new AbstractMap.SimpleEntry<>(entry.getKey(), numericValue);
-                    } catch (NumberFormatException e) {
-                        // 数值转换失败处理(返回最大值确保排在最后)
-                        return new AbstractMap.SimpleEntry<>(entry.getKey(), Double.MAX_VALUE);
-                    }
-                })
-                // 双级排序:先按数值升序,数值相同再按key升序
-                // 显式指定泛型类型
-                .sorted(Comparator
-                        .<AbstractMap.SimpleEntry<Long, Double>>comparingDouble(AbstractMap.SimpleEntry::getValue)
-                        .thenComparingLong(AbstractMap.SimpleEntry::getKey)
-                )
-                // 提取排序后的key
-                .map(AbstractMap.SimpleEntry::getKey)
-                .collect(Collectors.toList()); */
         return map.entrySet().stream()
                 .map(entry -> {
                     String[] parts = entry.getValue().split("\\s+");
@@ -902,17 +883,27 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
         if (CollUtil.isEmpty(deviceIds) || CollUtil.isEmpty(personIds)) {
             return;
         }
+        // 查询设备集合修改前的部门
+        IotDevicePageReqVO deviceReqVO = new IotDevicePageReqVO();
+        deviceReqVO.setDeviceIds(deviceIds);
+        List<IotDeviceDO> devices = iotDeviceMapper.selectList(deviceReqVO);
+        Set<Long> deviceDeptIds = devices.stream()
+                .map(IotDeviceDO::getDeptId)    // 提取deptId属性
+                .collect(Collectors.toSet());   // 收集为Set以保证唯一性
+
         // 查询当前设备对应的 责任人 前端页面已经统一设置了相同的责任人(有可能多个 多个责任人时随机取1个)
         Long personId = personIds.get(0);
         // 查询当前设备集合的所有历史保养工单 如果历史工单明细中包含2个设备A,B,但是只调拨了1个设备A,此时 只复制设备A明细生成一个 执行完成的保养工单
         IotMainWorkOrderBomPageReqVO reqVO = new IotMainWorkOrderBomPageReqVO();
         reqVO.setDeviceIds(deviceIds);
         reqVO.setStatus(1);     // 查询已经保养完成的工单
-        List<IotMainWorkOrderBomDO> workOrderBomS = iotMainWorkOrderBomMapper.selectList(reqVO);
+        // List<IotMainWorkOrderBomDO> workOrderBomS = iotMainWorkOrderBomMapper.selectList(reqVO);
+        List<IotMainWorkOrderBomDO> workOrderBomS = iotMainWorkOrderBomMapper.historyWorkOrderBomS(new ArrayList<>(deviceDeptIds), deviceIds);
         // 以 工单id+设备id+设备负责人 为维度组成 工单BOM集合
         Map<Long, List<IotMainWorkOrderBomDO>> workOrderBomPair = new HashMap<>();
         Map<Long, IotMainWorkOrderDO> workOrderPair = new HashMap<>();
         Set<Long> workOrderIds = new HashSet<>();
+        Set<Long> bomNodeIds = new HashSet<>();
         // 需要新增的保养工单集合 (历史工单)
         List<IotMainWorkOrderDO> tobeAddedOrders = new ArrayList<>();
         // 需要新增的保养工单明细集合 (历史工单)
@@ -931,7 +922,28 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
                     workOrderBomPair.put(bom.getWorkOrderId(), tempBomS);
                 }
                 workOrderIds.add(bom.getWorkOrderId());
+                bomNodeIds.add(bom.getBomNodeId());
             });
+            // 查询 指定保养工单集合内 bomNodeId集合内 的挂载的物料集合
+            Map<String, List<IotMainWorkOrderBomMaterialDO>> workOrderMaterialPair = new HashMap<>();
+            IotMainWorkOrderBomMaterialPageReqVO materialReqVO = new IotMainWorkOrderBomMaterialPageReqVO();
+            materialReqVO.setWorkOrderIds(new ArrayList<>(workOrderIds));
+            materialReqVO.setBomNodeIds(new ArrayList<>(bomNodeIds));
+            List<IotMainWorkOrderBomMaterialDO> historyBomMaterials = iotMainWorkOrderBomMaterialMapper.selectList(materialReqVO);
+            if (CollUtil.isNotEmpty(historyBomMaterials)) {
+                historyBomMaterials.forEach(material -> {
+                    String uniqueKey = StrUtil.join("-", material.getWorkOrderId(), material.getBomNodeId());
+                    if (workOrderMaterialPair.containsKey(uniqueKey)) {
+                        List<IotMainWorkOrderBomMaterialDO> tempMaterials = workOrderMaterialPair.get(uniqueKey);
+                        tempMaterials.add(material);
+                        workOrderMaterialPair.put(uniqueKey, tempMaterials);
+                    } else {
+                        List<IotMainWorkOrderBomMaterialDO> tempMaterials = new ArrayList<>();
+                        tempMaterials.add(material);
+                        workOrderMaterialPair.put(uniqueKey, tempMaterials);
+                    }
+                });
+            }
             // 查询所有保养工单明细对应的保养工单主表集合
             IotMainWorkOrderPageReqVO orderReqVO = new IotMainWorkOrderPageReqVO();
             orderReqVO.setWorkOrderIds(new ArrayList<>(workOrderIds));
@@ -952,7 +964,7 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
                 workOrder.setId(theMaxId.get());
                 workOrder.setDeptId(deptId);
                 if (workOrderPair.containsKey(k)) {
-                    workOrder.setName(workOrderPair.get(k).getName());
+                    workOrder.setName(workOrderPair.get(k).getName() + " 历史");
                     workOrder.setPlanId(workOrderPair.get(k).getPlanId());
                     workOrder.setType(workOrderPair.get(k).getType());
                     workOrder.setCost(workOrderPair.get(k).getCost());
@@ -975,14 +987,28 @@ public class IotMainWorkOrderServiceImpl implements IotMainWorkOrderService {
                     tempBom.setId(null);
                     tempBom.setWorkOrderId(workOrderId);
                     tobeAddedOrderBomS.add(tempBom);
-                    System.out.println("当前保养明细名称:" + bom.getName());
+                    // 3. 处理BOM明细关联的物料
+                    String uniqueKey = StrUtil.join("-", k, bom.getBomNodeId());
+                    if (workOrderMaterialPair.containsKey(uniqueKey)) {
+                        List<IotMainWorkOrderBomMaterialDO> bomMaterials = workOrderMaterialPair.get(uniqueKey);
+                        bomMaterials.forEach(material -> {
+                            IotMainWorkOrderBomMaterialDO tempMaterial = new IotMainWorkOrderBomMaterialDO();
+                            BeanUtils.copyProperties(material, tempMaterial);
+                            tempMaterial.setId(null);
+                            tempMaterial.setWorkOrderId(workOrderId);
+                            tobeAddedOrderBomMaterialS.add(tempMaterial);
+                        });
+                    }
                 });
             });
-            // todo 还要处理保养项已经关联的物料
+            // 插入 保养工单 保养工单明细 保养工单明细关联的物料
             if (CollUtil.isNotEmpty(tobeAddedOrders) && CollUtil.isNotEmpty(tobeAddedOrderBomS)) {
                 iotMainWorkOrderMapper.insertBatch(tobeAddedOrders);
                 iotMainWorkOrderBomMapper.insertBatch(tobeAddedOrderBomS);
-                System.out.println("保养工单明细集合数量:" + tobeAddedOrderBomS.size());
+            }
+            // 插入 保养工单明细关联的物料
+            if (CollUtil.isNotEmpty(tobeAddedOrderBomMaterialS)) {
+                iotMainWorkOrderBomMaterialMapper.insertBatch(tobeAddedOrderBomMaterialS);
             }
         }
     }

+ 25 - 0
yudao-module-pms/yudao-module-pms-biz/src/main/resources/mapper/static/IotMainWorkOrderBomMapper.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="cn.iocoder.yudao.module.pms.dal.mysql.iotmainworkorderbom.IotMainWorkOrderBomMapper">
+
+    <select id="historyWorkOrderBomS" resultType="cn.iocoder.yudao.module.pms.dal.dataobject.iotmainworkorderbom.IotMainWorkOrderBomDO">
+        SELECT *
+        FROM rq_iot_main_work_order_bom mwob
+        LEFT JOIN rq_iot_main_work_order mwo ON mwo.id = mwob.work_order_id
+        WHERE mwob.`status` = 1
+          AND mwo.result = 2
+        <if test="deptIds != null and deptIds.size &gt; 0">
+            AND mwo.dept_id IN
+            <foreach collection="deptIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+        <if test="deviceIds != null and deviceIds.size &gt; 0">
+            AND mwob.device_id IN
+            <foreach collection="deviceIds" index="index" item="key" open="(" separator="," close=")">
+                #{key}
+            </foreach>
+        </if>
+    </select>
+
+</mapper>