diff --git a/src/main/java/com/wms/controller/StandController.java b/src/main/java/com/wms/controller/StandController.java index d844a0b..5af5369 100644 --- a/src/main/java/com/wms/controller/StandController.java +++ b/src/main/java/com/wms/controller/StandController.java @@ -8,7 +8,6 @@ import com.wms.annotation.MyLog; import com.wms.constants.enums.ResponseCode; import com.wms.entity.app.ResponseEntity; import com.wms.entity.app.dto.PageDto; -import com.wms.entity.app.dto.StandDto; import com.wms.entity.app.request.StandQuery; import com.wms.entity.app.vo.StandVo; import com.wms.entity.app.wcs.DdjStatusChangeRequest; @@ -66,7 +65,9 @@ public class StandController { .like(StringUtils.isNotEmpty(standQuery.getStandId()), Stand::getStandId, standQuery.getStandId()) .eq(standQuery.getStandStatus() != null, Stand::getStandStatus, standQuery.getStandStatus()) .eq(standQuery.getIsLock() != null, Stand::getIsLock, standQuery.getIsLock()) - .eq(standQuery.getStandType() != null, Stand::getStandType, standQuery.getStandType()); + .eq(standQuery.getStandType() != null, Stand::getStandType, standQuery.getStandType()) + .eq(standQuery.getAllowMwl() != null, Stand::getAllowMwl, standQuery.getAllowMwl()) + .eq(standQuery.getAllowMg() != null, Stand::getAllowMg, standQuery.getAllowMg()); Page standPage = standService.page(page, lambdaQueryWrapper); PageDto pageDto = PageDto.of(standPage, stand -> BeanUtil.copyProperties(stand, StandVo.class)); @@ -112,6 +113,8 @@ public class StandController { .set(request.getLastUseTime() != null, Stand::getLastUseTime, request.getLastUseTime()) .set(request.getPickVehicleCount() != null, Stand::getPickVehicleCount, request.getPickVehicleCount()) .set(request.getAllowNoPlan() != null, Stand::getAllowNoPlan, request.getAllowNoPlan()) + .set(request.getAllowMwl() != null, Stand::getAllowMwl, request.getAllowMwl()) + .set(request.getAllowMg() != null, Stand::getAllowMg, request.getAllowMg()) .eq(Stand::getStandId, request.getStandId()); if (standService.update(lambdaUpdateWrapper)) { logger.info("更新站台信息成功。"); diff --git a/src/main/java/com/wms/entity/app/request/StandQuery.java b/src/main/java/com/wms/entity/app/request/StandQuery.java index d167ee0..d8bf5c8 100644 --- a/src/main/java/com/wms/entity/app/request/StandQuery.java +++ b/src/main/java/com/wms/entity/app/request/StandQuery.java @@ -99,4 +99,14 @@ public class StandQuery extends PageQuery { */ @JsonProperty("allowNoPlan") private Integer allowNoPlan; + /** + * 允许做装载机 + */ + @JsonProperty("allowMwl") + private Integer allowMwl; + /** + * 允许做平地机 + */ + @JsonProperty("allowMg") + private Integer allowMg; } diff --git a/src/main/java/com/wms/entity/app/vo/StandVo.java b/src/main/java/com/wms/entity/app/vo/StandVo.java index df5f8b0..9bf3f4c 100644 --- a/src/main/java/com/wms/entity/app/vo/StandVo.java +++ b/src/main/java/com/wms/entity/app/vo/StandVo.java @@ -97,4 +97,14 @@ public class StandVo { */ @JsonProperty("allowNoPlan") private Integer allowNoPlan; + /** + * 允许做装载机 + */ + @JsonProperty("allowMwl") + private Integer allowMwl; + /** + * 允许做平地机 + */ + @JsonProperty("allowMg") + private Integer allowMg; } diff --git a/src/main/java/com/wms/entity/table/Stand.java b/src/main/java/com/wms/entity/table/Stand.java index 059f7a6..16911ba 100644 --- a/src/main/java/com/wms/entity/table/Stand.java +++ b/src/main/java/com/wms/entity/table/Stand.java @@ -96,4 +96,14 @@ public class Stand { */ @TableField("allow_no_plan") private Integer allowNoPlan; + /** + * 允许做装载机 + */ + @TableField("allow_mwl") + private Integer allowMwl; + /** + * 允许做平地机 + */ + @TableField("allow_mg") + private Integer allowMg; } diff --git a/src/main/java/com/wms/service/business/IWorkService.java b/src/main/java/com/wms/service/business/IWorkService.java index 9b4a485..1c850dd 100644 --- a/src/main/java/com/wms/service/business/IWorkService.java +++ b/src/main/java/com/wms/service/business/IWorkService.java @@ -28,4 +28,6 @@ public interface IWorkService { * 分配工作 */ void distributeWorks(); + + void distributeWorksMethod2(); } diff --git a/src/main/java/com/wms/service/business/serviceImplements/WorkServiceImplements.java b/src/main/java/com/wms/service/business/serviceImplements/WorkServiceImplements.java index 9d40566..b74f015 100644 --- a/src/main/java/com/wms/service/business/serviceImplements/WorkServiceImplements.java +++ b/src/main/java/com/wms/service/business/serviceImplements/WorkServiceImplements.java @@ -1,6 +1,7 @@ package com.wms.service.business.serviceImplements; import cn.hutool.core.bean.BeanUtil; +import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.wms.constants.enums.*; @@ -380,9 +381,10 @@ public class WorkServiceImplements implements IWorkService { * @param model 机型 */ private void findWorks(String workStation, List workFlows, String model, LocalDate currentWorkDate) { + String modelStr = Objects.equals(model, "MWL") ? "装载机" : "平地机"; //开始时间: LocalDateTime startTime = LocalDateTime.now(); - System.out.println("开始时间:" + startTime); + System.out.println("分析当日" + modelStr + "工作流,开始时间:" + startTime); // 查到当前站台所有的小工位 LambdaQueryWrapper stationConfigQueryWrapper = new LambdaQueryWrapper() .eq(StringUtils.isNotEmpty(workStation), WorkStationConfig::getWorkStation, workStation); @@ -429,9 +431,9 @@ public class WorkServiceImplements implements IWorkService { if (kateDBS == null || StringUtils.isEmpty(kateDBS.getWorkOrder())) {// 不存在对应的工单计划 continue; } - if(!isAddReqmtsDate) { + if (!isAddReqmtsDate) { localDateTime = kateDBS.getPlanStartDate(); - }else{ + } else { localDateTime = kateWorkOrder.getPlanStartDate().atStartOfDay(); } // 判断是否是当天开工 @@ -495,9 +497,10 @@ public class WorkServiceImplements implements IWorkService { } //结束时间 LocalDateTime endTime = LocalDateTime.now(); + System.out.println("分析当日" + modelStr + "工作流,结束时间:" + endTime); // 用时 long duration = Duration.between(startTime, endTime).toMillis(); - logger.info("生成当天工作流耗时:{}ms", duration); + logger.info("分析当日{}工作流耗时:{}ms", modelStr, duration); } @@ -537,8 +540,20 @@ public class WorkServiceImplements implements IWorkService { public void createTempWorkFlows() { LocalDate currentWorkDate = getCurrentWorkDate(); if (!localWorkDateList.contains(currentWorkDate)) { + logger.info("非工作日,不创建工作流。"); return; } + // 查找所有未锁定的拣选站台 + List usableStands = standService.list(new LambdaQueryWrapper() + .eq(Stand::getStandType, 2) + .eq(Stand::getIsLock, 0)); + for (Stand stand : usableStands) { + if (stand.getStandStatus() == 0) { + // 存在站台处于可用状态,不创建工作流 + logger.info("存在站台处于可用状态,不创建工作流。"); + return; + } + } // 添加进总汇总数据 List allFlows = new ArrayList<>(); // 获取当天所有的装载机工作 @@ -547,98 +562,28 @@ public class WorkServiceImplements implements IWorkService { List thisDayMGWorks = new ArrayList<>(); // 需要合并第二天的平地机工作 List nextDayMGWorks = new ArrayList<>(); - // 获取工作优先级 - String workPriority = configMap.get(ConfigMapKeyEnum.WORK_PRIORITY.getConfigKey()); - // 获取目前已经存在的工作流 - List allOldWorkFlows = workFlowService.list(); - if (!StringUtils.isEmpty(workPriority) && workPriority.equals("1")) { - List oldMwlWorkFlows = allOldWorkFlows.stream().filter(workFlow -> workFlow.getMachineType() == 1).toList(); - if (oldMwlWorkFlows.isEmpty()) { - // 先平地机再装载机 - findWorks("", thisDayMGWorks, "NOT_MWL", currentWorkDate); - if (!thisDayMGWorks.isEmpty()) { - allFlows.addAll(thisDayMGWorks); - // 查询配置是否需要合并第二天的配置 - String ifMergeTomorrow = configMap.get(ConfigMapKeyEnum.IF_MERGE_TOMORROW.getConfigKey()); - if (!StringUtils.isEmpty(ifMergeTomorrow) && ifMergeTomorrow.equals("1")) { - // 获取下一个工作日 - LocalDate nextWorkDate = nextWorkDate(currentWorkDate); - if (nextWorkDate != null && nextWorkDate.isAfter(currentWorkDate)) { - findWorks("", nextDayMGWorks, "NOT_MWL", nextWorkDate); - } - if (!nextDayMGWorks.isEmpty()) { - // 添加第二天的平地机工作进汇总 - allFlows.addAll(nextDayMGWorks); - } - } - } else { - List oldMgWorkFlows = allOldWorkFlows.stream().filter(workFlow -> workFlow.getMachineType() == 2).toList(); - if (oldMgWorkFlows.isEmpty()) { - // 装载机 - findWorks("", thisDayMWLWorks, "MWL", currentWorkDate); - if (!thisDayMWLWorks.isEmpty()) { - allFlows.addAll(thisDayMWLWorks); - } - } + // 生成装载机工作流 + findWorks("", thisDayMWLWorks, "MWL", currentWorkDate); + if (!thisDayMWLWorks.isEmpty()) { + allFlows.addAll(thisDayMWLWorks); + } + // 生成当天平地机工作流 + findWorks("", thisDayMGWorks, "NOT_MWL", currentWorkDate); + if (!thisDayMGWorks.isEmpty()) { + allFlows.addAll(thisDayMGWorks); + // 查询配置是否需要合并第二天的配置 + String ifMergeTomorrow = configMap.get(ConfigMapKeyEnum.IF_MERGE_TOMORROW.getConfigKey()); + if (!StringUtils.isEmpty(ifMergeTomorrow) && ifMergeTomorrow.equals("1")) { + // 获取下一个工作日 + LocalDate nextWorkDate = nextWorkDate(currentWorkDate); + if (nextWorkDate != null && nextWorkDate.isAfter(currentWorkDate)) { + findWorks("", nextDayMGWorks, "NOT_MWL", nextWorkDate); } - } else { - // 装载机 - findWorks("", thisDayMWLWorks, "MWL", currentWorkDate); - if (!thisDayMWLWorks.isEmpty()) { - allFlows.addAll(thisDayMWLWorks); + if (!nextDayMGWorks.isEmpty()) { + // 添加第二天的平地机工作进汇总 + allFlows.addAll(nextDayMGWorks); } } - } else { - List oldMgWorkFlows = allOldWorkFlows.stream().filter(workFlow -> workFlow.getMachineType() == 2).toList(); - if (oldMgWorkFlows.isEmpty()) { - // 先装载机再平地机 - findWorks("", thisDayMWLWorks, "MWL", currentWorkDate); - if (!thisDayMWLWorks.isEmpty()) { - allFlows.addAll(thisDayMWLWorks); - } else { - List oldMwlWorkFlows = allOldWorkFlows.stream().filter(workFlow -> workFlow.getMachineType() == 1).toList(); - if (oldMwlWorkFlows.isEmpty()) { - // 平地机 - findWorks("", thisDayMGWorks, "NOT_MWL", currentWorkDate); - if (!thisDayMGWorks.isEmpty()) { - allFlows.addAll(thisDayMGWorks); - // 查询配置是否需要合并第二天的配置 - String ifMergeTomorrow = configMap.get(ConfigMapKeyEnum.IF_MERGE_TOMORROW.getConfigKey()); - if (!StringUtils.isEmpty(ifMergeTomorrow) && ifMergeTomorrow.equals("1")) { - // 获取下一个工作日 - LocalDate nextWorkDate = nextWorkDate(currentWorkDate); - if (nextWorkDate != null && nextWorkDate.isAfter(currentWorkDate)) { - findWorks("", nextDayMGWorks, "NOT_MWL", nextWorkDate); - } - if (!nextDayMGWorks.isEmpty()) { - // 添加第二天的平地机工作进汇总 - allFlows.addAll(nextDayMGWorks); - } - } - } - } - } - } else { - // 平地机 - findWorks("", thisDayMGWorks, "NOT_MWL", currentWorkDate); - if (!thisDayMGWorks.isEmpty()) { - allFlows.addAll(thisDayMGWorks); - // 查询配置是否需要合并第二天的配置 - String ifMergeTomorrow = configMap.get(ConfigMapKeyEnum.IF_MERGE_TOMORROW.getConfigKey()); - if (!StringUtils.isEmpty(ifMergeTomorrow) && ifMergeTomorrow.equals("1")) { - // 获取下一个工作日 - LocalDate nextWorkDate = nextWorkDate(currentWorkDate); - if (nextWorkDate != null && nextWorkDate.isAfter(currentWorkDate)) { - findWorks("", nextDayMGWorks, "NOT_MWL", nextWorkDate); - } - if (!nextDayMGWorks.isEmpty()) { - // 添加第二天的平地机工作进汇总 - allFlows.addAll(nextDayMGWorks); - } - } - } - } - } if (!allFlows.isEmpty()) { // 处理这些工作流 @@ -676,10 +621,10 @@ public class WorkServiceImplements implements IWorkService { .in(KateDBS::getWorkOrder, workOrderList) .eq(KateDBS::getDbsStatus, 0)); } - logger.info("createTempWorkFlows 成功"); + logger.info("创建工作流成功,此次创建{}条。", finalWorkFlows.size()); } } else { - logger.info("createTempWorkFlows 为空"); + logger.info("未创建新的工作流。"); } } @@ -725,44 +670,56 @@ public class WorkServiceImplements implements IWorkService { } // 获取工作优先级 String workPriority = configMap.get(ConfigMapKeyEnum.WORK_PRIORITY.getConfigKey()); - List needDistributeWorks = new ArrayList<>(); - int currentWorkType; + // 获取优先的工作类型 + int firstWorkType;// 1为装载机,2为平地机 if (!StringUtils.isEmpty(workPriority) && workPriority.equals("1")) { - // 当前工作优先级为先平地机后装载机 - List needDistributeMgWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 2 && workFlow.getWorkStatus() == -1).toList(); - if (!needDistributeMgWorks.isEmpty()) { - needDistributeWorks.addAll(needDistributeMgWorks); - currentWorkType = 2;// 平地机 - } else { - List needDistributeMwlWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 1 && workFlow.getWorkStatus() == -1).toList(); - if (!needDistributeMwlWorks.isEmpty()) { - needDistributeWorks.addAll(needDistributeMwlWorks); - currentWorkType = 1;// 装载机 - } else { - logger.info("当前没有未分配的工作,优先级:平地机优先。"); - return; - } - } + firstWorkType = 2; } else { - // 默认优先级为先装载机后平地机 - List needDistributeMwlWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 1 && workFlow.getWorkStatus() == -1).toList(); - if (!needDistributeMwlWorks.isEmpty()) { - needDistributeWorks.addAll(needDistributeMwlWorks); - currentWorkType = 1;// 装载机 + firstWorkType = 1; + } + // 需要分配的平地机工作流 + List needDistributeMgWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 2 && workFlow.getWorkStatus() == -1).toList(); + // 需要分配的装载机工作流 + List needDistributeMwlWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 1 && workFlow.getWorkStatus() == -1).toList(); + // 方案1:装载机与平地机分开分配,且优先分配的工作的物料类对次选工作存在影响 + List needDistributeWorksOfFirst = new ArrayList<>(); + List needDistributeWorksOfNext = new ArrayList<>(); + if (firstWorkType == 1) { + needDistributeWorksOfFirst.addAll(needDistributeMwlWorks); + needDistributeWorksOfNext.addAll(needDistributeMgWorks); + } else { + needDistributeWorksOfFirst.addAll(needDistributeMgWorks); + needDistributeWorksOfNext.addAll(needDistributeMwlWorks); + } + // 首选工作的工作站台 + List firstWorkStandIds = new ArrayList<>(); + // 次选工作的站台 + List nextWorkStandIds = new ArrayList<>(); + for (Stand stand : usablePickStands) { + if (firstWorkType == 2) { + // 优先做平地机 + if (!needDistributeMgWorks.isEmpty() && stand.getAllowMg() == 1) { + // 当前站台做平地机 + firstWorkStandIds.add(stand.getStandId()); + continue; + } + if (!needDistributeMwlWorks.isEmpty() && stand.getAllowMwl() == 1) { + // 当前站台可以继续做装载机 + nextWorkStandIds.add(stand.getStandId()); + } } else { - List needDistributeMgWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 2 && workFlow.getWorkStatus() == -1).toList(); - if (!needDistributeMgWorks.isEmpty()) { - needDistributeWorks.addAll(needDistributeMgWorks); - currentWorkType = 2;// 平地机 - } else { - logger.info("当前没有未分配的工作,优先级:装载机优先。"); - return; + // 优先做装载机 + if (!needDistributeMwlWorks.isEmpty() && stand.getAllowMwl() == 1) { + // 当前站台做装载机 + firstWorkStandIds.add(stand.getStandId()); + continue; + } + if (!needDistributeMgWorks.isEmpty() && stand.getAllowMg() == 1) { + // 当前站台可以继续做平地机 + nextWorkStandIds.add(stand.getStandId()); } } } - // 最终需要存储的数据 - List finalGoodsToStations = new ArrayList<>();// 物料分配 - List finalELocationConfigs = new ArrayList<>();// 标签库位分配 // 获取所有可用的电子标签位 List allELocations = eTagLocationService.list(new LambdaQueryWrapper() .eq(ETagLocation::getELocationStatus, 0) @@ -774,43 +731,475 @@ public class WorkServiceImplements implements IWorkService { logger.info("存在旧的标签配置,不执行分配。"); return; } - // 获取工站配置 - LambdaQueryWrapper wsConfigQueryWrapper = new LambdaQueryWrapper<>(); - if (currentWorkType == 1) { - // 当前是装载机工作,装载机要区分站台 - wsConfigQueryWrapper - .eq(WorkStationConfig::getModel, "MWL"); - } else { - // 当前是平地机工作 - wsConfigQueryWrapper.ne(WorkStationConfig::getModel, "MWL"); - } - List workStationConfigs = workStationConfigService.list(wsConfigQueryWrapper); - // 然后获取大盒子-订单的map - Map> workFlowsByBigBoxMap = new HashMap<>(); + // 本次分配的工作 + List thisTimeDistributeWorkFlows = new ArrayList<>(); + // 查询出所有的工站配置 + List workStationConfigs = workStationConfigService.list(); // 根据小盒子号生成map Map smallBoxToBigBoxConfigMap = workStationConfigs.stream().collect(Collectors.toMap(WorkStationConfig::getSmallBox, WorkStationConfig::getBigBox)); - for (WorkFlow workFlow : needDistributeWorks) { - if (smallBoxToBigBoxConfigMap.containsKey(workFlow.getWorkCenter())) { - String bigbox = smallBoxToBigBoxConfigMap.get(workFlow.getWorkCenter()); - workFlowsByBigBoxMap.computeIfAbsent(bigbox, k -> new ArrayList<>()) - .add(workFlow); + // 首选工作存储的信息 + List finalGoodsToStationsOfFirst = new ArrayList<>();// 物料分配 + List finalELocationConfigsOfFirst = new ArrayList<>();// 标签库位分配 + // 下面开始分配首选工作 + if (!needDistributeWorksOfFirst.isEmpty() && !firstWorkStandIds.isEmpty()) { + logger.info("开始分配首选机型。"); + // 获取大盒子-订单的map + Map> workFlowsByBigBoxMapOfFirst = new HashMap<>(); + for (WorkFlow workFlow : needDistributeWorksOfFirst) { + if (smallBoxToBigBoxConfigMap.containsKey(workFlow.getWorkCenter())) { + String bigBox = smallBoxToBigBoxConfigMap.get(workFlow.getWorkCenter()); + workFlowsByBigBoxMapOfFirst.computeIfAbsent(bigBox, k -> new ArrayList<>()) + .add(workFlow); + } + } + // 生成每个大盒子的物料种类map + Map bigBoxToGoodsTypeQtyMap = new HashMap<>(); + for (String bigBox : workFlowsByBigBoxMapOfFirst.keySet()) { + List thisBoxWorkFlows = workFlowsByBigBoxMapOfFirst.get(bigBox); + int goodsTypeQty = thisBoxWorkFlows.stream().map(WorkFlow::getGoodsId).distinct().toList().size(); + bigBoxToGoodsTypeQtyMap.put(bigBox, goodsTypeQty); + } + // 根据物料种类数量对大盒子进行排序 + List sortedBoxesByGoodsTypeQty = bigBoxToGoodsTypeQtyMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(Map.Entry::getKey).toList(); + // 每个站台包含的物料种类数量 + Map> stationToGoodsTypeQtyMap = new HashMap<>(); + // 每个站台分配的电子标签 + Map> stationToELocationConfigsMap = new HashMap<>(); + // 每个站台的物料需求 + Map> stationToGoodsToStationsMap = new HashMap<>(); + // 每个站台的剩余电子标签 + Map> stationToRemainELocationMap = new HashMap<>(); + for (String standId : firstWorkStandIds) { + List thisStandELocations = allELocations.stream().filter(eTagLocation -> eTagLocation.getWorkStation().equals(standId)).toList(); + if (thisStandELocations.isEmpty()) { + // 当前站台没有可用电子标签位 + stationToRemainELocationMap.put(standId, Collections.emptyList()); + continue; + } + // 排序 + List thisStandELocationIds = thisStandELocations.stream().sorted(Comparator.comparingInt(ETagLocation::getSequenceId)).map(ETagLocation::getELocationId).toList(); + stationToRemainELocationMap.put(standId, thisStandELocationIds); + // 每个站台物料分配种类 + stationToGoodsTypeQtyMap.put(standId, new ArrayList<>()); + } + // 决定每个大盒子的站台分配 + Map bigBoxToStandIdMap = new HashMap<>(); + // 物料种类总数---这里存在一个分歧,大盒子之间的共通物料种类是否需要重复计算---CONFUSION + int totalGoodsTypeQty = needDistributeWorksOfFirst.stream().map(WorkFlow::getGoodsId).distinct().toList().size(); + // 物料种类数量平均值 + int goodsTypeQtyAverage = (int) Math.ceil(totalGoodsTypeQty / (double) firstWorkStandIds.size()); + // 查询出需要分配的工单的dbs + List kateDBSS = kateDBSService.list(new LambdaQueryWrapper() + .in(KateDBS::getWorkOrder, needDistributeWorksOfFirst.stream().map(WorkFlow::getWorkOrder).distinct().toList())); + // 将这个工单的顺序号进行一个map + Map workOrderToSequenceMap = kateDBSS.stream().collect(Collectors.toMap(KateDBS::getWorkOrder, KateDBS::getWorkSequence)); + for (String bigBox : sortedBoxesByGoodsTypeQty) { + // 找出这个大盒子下的工作流 + List thisBoxWorkFlows = workFlowsByBigBoxMapOfFirst.get(bigBox); + if (thisBoxWorkFlows.isEmpty()) { + // 当前大盒子没有工作流,跳过 + continue; + } + // 获取这个大盒子下面的物料列表 + List goodsIds = thisBoxWorkFlows.stream().map(WorkFlow::getGoodsId).distinct().toList(); + // 未分配的工作流,按照boxNo分组 + Map> notDistributeYetWorksByBoxMap = new HashMap<>(); + for (WorkFlow workFlow : thisBoxWorkFlows) { + String boxNo = workFlow.getWorkOrder() + "@" + workFlow.getWorkCenter(); + notDistributeYetWorksByBoxMap.computeIfAbsent(boxNo, k -> new ArrayList<>()) + .add(workFlow); + } + if (notDistributeYetWorksByBoxMap.isEmpty()) { + // 当前大盒子全部分配完毕 + continue; + } + String targetStandId = ""; + targetStandId = getMinGapStandToAvgAfterAddABox(stationToGoodsTypeQtyMap, goodsIds, goodsTypeQtyAverage, notDistributeYetWorksByBoxMap.size(), stationToRemainELocationMap); + if (StringUtils.isEmpty(targetStandId)) { + // 没有站台能够分配 + continue; + } + // 判断这个站台是否还包含剩余标签位 + List thisStandRemainELocationIds = new ArrayList<>(stationToRemainELocationMap.get(targetStandId)); + if (thisStandRemainELocationIds.size() < notDistributeYetWorksByBoxMap.size()) { + // 标签不够,此处的判断主要用于装载机 + continue; + } + // 排序后的key + List sortedKeyString = notDistributeYetWorksByBoxMap.keySet().stream() + .sorted( + Comparator.comparing((String o) -> workOrderToSequenceMap.get(o.split("@")[0])) + .thenComparing(o -> o.split("@")[1]) + ) + .toList(); + // 本次生成的电子标签配置 + List thisStandELocationConfigs = stationToELocationConfigsMap.getOrDefault(targetStandId, new ArrayList<>()); + for (String boxNo : sortedKeyString) { + // 获取一个电子标签库位 + String eLocationId = thisStandRemainELocationIds.get(0); + ELocationConfig eLocationConfig = new ELocationConfig(); + eLocationConfig.setWorkOrder(boxNo.split("@")[0]); + eLocationConfig.setWorkCenter(boxNo.split("@")[1]); + eLocationConfig.setWorkStation(targetStandId); + eLocationConfig.setELocationId(eLocationId); + eLocationConfig.setOrderBoxNo(boxNo); + // 添加配置 + thisStandELocationConfigs.add(eLocationConfig); + // 移除这个库位 + thisStandRemainELocationIds.remove(eLocationId); + } + // 更新电子标签剩余库位 + stationToRemainELocationMap.replace(targetStandId, thisStandRemainELocationIds); + // 更新电子标签配置 + stationToELocationConfigsMap.put(targetStandId, thisStandELocationConfigs); + // 已经分配完的大盒子 + bigBoxToStandIdMap.put(bigBox, targetStandId); + } + // 处理分配 + List oldGoodsStations = goodsToStationService.list(); + if (oldGoodsStations != null && !oldGoodsStations.isEmpty()) { + // 按照站台分组 + stationToGoodsToStationsMap = oldGoodsStations.stream().collect(Collectors.groupingBy(GoodsToStation::getWorkStation)); + } + // 更新数据 + for (String bigBox : bigBoxToStandIdMap.keySet()) { + String thisStandId = bigBoxToStandIdMap.get(bigBox); + // 当前站台的旧的goodsToStation + List thisStandOldGoodsToStationList = stationToGoodsToStationsMap.getOrDefault(thisStandId, new ArrayList<>()); + // 根据料号Map一下 + Map oldGoodsStationsMap = thisStandOldGoodsToStationList.stream().collect(Collectors.toMap(GoodsToStation::getGoodsId, goodsToStation -> goodsToStation)); + List thisBigBoxWorks = workFlowsByBigBoxMapOfFirst.get(bigBox); + for (WorkFlow workFlow : thisBigBoxWorks) { + if (oldGoodsStationsMap.containsKey(workFlow.getGoodsId())) { + // 更新totalNum,并把状态改成分配中 + GoodsToStation goodsToStation = oldGoodsStationsMap.get(workFlow.getGoodsId()); + goodsToStation.setTotalNum(goodsToStation.getTotalNum().add(workFlow.getNeedNum())); + oldGoodsStationsMap.replace(workFlow.getGoodsId(), goodsToStation); + } else { + GoodsToStation newGoodsToStation = new GoodsToStation(); + newGoodsToStation.setConfigId(generateId("")); + newGoodsToStation.setGoodsId(workFlow.getGoodsId()); + newGoodsToStation.setWorkStation(thisStandId); + newGoodsToStation.setDistributeStatus(0); + newGoodsToStation.setDistributedNum(BigDecimal.ZERO); + newGoodsToStation.setTotalNum(workFlow.getNeedNum()); + oldGoodsStationsMap.put(workFlow.getGoodsId(), newGoodsToStation); + } + WorkFlow onlyForUpdateTemp = new WorkFlow(); + onlyForUpdateTemp.setWorkFlowId(workFlow.getWorkFlowId()); + onlyForUpdateTemp.setWorkStatus(0); + onlyForUpdateTemp.setWorkStation(thisStandId); + thisTimeDistributeWorkFlows.add(onlyForUpdateTemp); + } + // 替换 + stationToGoodsToStationsMap.put(thisStandId, oldGoodsStationsMap.values().stream().toList()); + } + // 以下更新物料需求 + for (String standId : stationToGoodsToStationsMap.keySet()) { + finalGoodsToStationsOfFirst.addAll(stationToGoodsToStationsMap.get(standId)); + } + // 以下更新电子标签配置 + for (String standId : stationToELocationConfigsMap.keySet()) { + finalELocationConfigsOfFirst.addAll(stationToELocationConfigsMap.get(standId)); + } + } else { + logger.info("无法分配首选机型,可能是没有工作流或可用站台。"); + } + // 次选工作存储的信息 + List finalGoodsToStationsOfNext = new ArrayList<>();// 物料分配 + List finalELocationConfigsOfNext = new ArrayList<>();// 标签库位分配 + // 处理次选工作 TODO 需要考虑一下优先分配和首选工作存在相同物料种类的大盒子 + if (!needDistributeWorksOfNext.isEmpty() && !nextWorkStandIds.isEmpty()) { + logger.info("开始分配次选机型。"); + // 获取大盒子-订单的map + Map> workFlowsByBigBoxMapOfNext = new HashMap<>(); + for (WorkFlow workFlow : needDistributeWorksOfNext) { + if (smallBoxToBigBoxConfigMap.containsKey(workFlow.getWorkCenter())) { + String bigBox = smallBoxToBigBoxConfigMap.get(workFlow.getWorkCenter()); + workFlowsByBigBoxMapOfNext.computeIfAbsent(bigBox, k -> new ArrayList<>()) + .add(workFlow); + } + } + // 生成每个大盒子的物料种类map + Map bigBoxToGoodsTypeQtyMap = new HashMap<>(); + for (String bigBox : workFlowsByBigBoxMapOfNext.keySet()) { + List thisBoxWorkFlows = workFlowsByBigBoxMapOfNext.get(bigBox); + int goodsTypeQty = thisBoxWorkFlows.stream().map(WorkFlow::getGoodsId).distinct().toList().size(); + bigBoxToGoodsTypeQtyMap.put(bigBox, goodsTypeQty); + } + // 根据物料种类数量对大盒子进行排序 + List sortedBoxesByGoodsTypeQty = bigBoxToGoodsTypeQtyMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(Map.Entry::getKey).toList(); + // 每个站台包含的物料种类数量 + Map> stationToGoodsTypeQtyMap = new HashMap<>(); + // 每个站台分配的电子标签 + Map> stationToELocationConfigsMap = new HashMap<>(); + // 每个站台的物料需求 + Map> stationToGoodsToStationsMap = new HashMap<>(); + // 每个站台的剩余电子标签 + Map> stationToRemainELocationMap = new HashMap<>(); + for (String standId : nextWorkStandIds) { + List thisStandELocations = allELocations.stream().filter(eTagLocation -> eTagLocation.getWorkStation().equals(standId)).toList(); + if (thisStandELocations.isEmpty()) { + // 当前站台没有可用电子标签位 + stationToRemainELocationMap.put(standId, Collections.emptyList()); + continue; + } + // 排序 + List thisStandELocationIds = thisStandELocations.stream().sorted(Comparator.comparingInt(ETagLocation::getSequenceId)).map(ETagLocation::getELocationId).toList(); + stationToRemainELocationMap.put(standId, thisStandELocationIds); + // 每个站台物料分配种类 + stationToGoodsTypeQtyMap.put(standId, new ArrayList<>()); + } + // 决定每个大盒子的站台分配 + Map bigBoxToStandIdMap = new HashMap<>(); + // 物料种类总数---这里存在一个分歧,大盒子之间的共通物料种类是否需要重复计算---CONFUSION + int totalGoodsTypeQty = needDistributeWorksOfNext.stream().map(WorkFlow::getGoodsId).distinct().toList().size(); + // 物料种类数量平均值 + int goodsTypeQtyAverage = (int) Math.ceil(totalGoodsTypeQty / (double) nextWorkStandIds.size()); + // 查询出需要分配的工单的dbs + List kateDBSS = kateDBSService.list(new LambdaQueryWrapper() + .in(KateDBS::getWorkOrder, needDistributeWorksOfNext.stream().map(WorkFlow::getWorkOrder).distinct().toList())); + // 将这个工单的顺序号进行一个map + Map workOrderToSequenceMap = kateDBSS.stream().collect(Collectors.toMap(KateDBS::getWorkOrder, KateDBS::getWorkSequence)); + for (String bigBox : sortedBoxesByGoodsTypeQty) { + // 找出这个大盒子下的工作流 + List thisBoxWorkFlows = workFlowsByBigBoxMapOfNext.get(bigBox); + if (thisBoxWorkFlows.isEmpty()) { + // 当前大盒子没有工作流,跳过 + continue; + } + // 获取这个大盒子下面的物料列表 + List goodsIds = thisBoxWorkFlows.stream().map(WorkFlow::getGoodsId).distinct().toList(); + // 未分配的工作流,按照boxNo分组 + Map> notDistributeYetWorksByBoxMap = new HashMap<>(); + for (WorkFlow workFlow : thisBoxWorkFlows) { + String boxNo = workFlow.getWorkOrder() + "@" + workFlow.getWorkCenter(); + notDistributeYetWorksByBoxMap.computeIfAbsent(boxNo, k -> new ArrayList<>()) + .add(workFlow); + } + if (notDistributeYetWorksByBoxMap.isEmpty()) { + // 当前大盒子全部分配完毕 + continue; + } + String targetStandId = ""; + targetStandId = getMinGapStandToAvgAfterAddABox(stationToGoodsTypeQtyMap, goodsIds, goodsTypeQtyAverage, notDistributeYetWorksByBoxMap.size(), stationToRemainELocationMap); + if (StringUtils.isEmpty(targetStandId)) { + // 没有站台能够分配 + continue; + } + // 判断这个站台是否还包含剩余标签位 + List thisStandRemainELocationIds = new ArrayList<>(stationToRemainELocationMap.get(targetStandId)); + if (thisStandRemainELocationIds.size() < notDistributeYetWorksByBoxMap.size()) { + // 标签不够,此处的判断主要用于装载机 + continue; + } + // 排序后的key + List sortedKeyString = notDistributeYetWorksByBoxMap.keySet().stream() + .sorted( + Comparator.comparing((String o) -> workOrderToSequenceMap.get(o.split("@")[0])) + .thenComparing(o -> o.split("@")[1]) + ) + .toList(); + // 本次生成的电子标签配置 + List thisStandELocationConfigs = stationToELocationConfigsMap.getOrDefault(targetStandId, new ArrayList<>()); + for (String boxNo : sortedKeyString) { + // 获取一个电子标签库位 + String eLocationId = thisStandRemainELocationIds.get(0); + ELocationConfig eLocationConfig = new ELocationConfig(); + eLocationConfig.setWorkOrder(boxNo.split("@")[0]); + eLocationConfig.setWorkCenter(boxNo.split("@")[1]); + eLocationConfig.setWorkStation(targetStandId); + eLocationConfig.setELocationId(eLocationId); + eLocationConfig.setOrderBoxNo(boxNo); + // 添加配置 + thisStandELocationConfigs.add(eLocationConfig); + // 移除这个库位 + thisStandRemainELocationIds.remove(eLocationId); + } + // 更新电子标签剩余库位 + stationToRemainELocationMap.replace(targetStandId, thisStandRemainELocationIds); + // 更新电子标签配置 + stationToELocationConfigsMap.put(targetStandId, thisStandELocationConfigs); + // 已经分配完的大盒子 + bigBoxToStandIdMap.put(bigBox, targetStandId); + } + // 处理分配 + List oldGoodsStations = goodsToStationService.list(); + if (oldGoodsStations != null && !oldGoodsStations.isEmpty()) { + // 按照站台分组 + stationToGoodsToStationsMap = oldGoodsStations.stream().collect(Collectors.groupingBy(GoodsToStation::getWorkStation)); + } + // 更新数据 + for (String bigBox : bigBoxToStandIdMap.keySet()) { + String thisStandId = bigBoxToStandIdMap.get(bigBox); + // 当前站台的旧的goodsToStation + List thisStandOldGoodsToStationList = stationToGoodsToStationsMap.getOrDefault(thisStandId, new ArrayList<>()); + // 根据料号Map一下 + Map oldGoodsStationsMap = thisStandOldGoodsToStationList.stream().collect(Collectors.toMap(GoodsToStation::getGoodsId, goodsToStation -> goodsToStation)); + List thisBigBoxWorks = workFlowsByBigBoxMapOfNext.get(bigBox); + for (WorkFlow workFlow : thisBigBoxWorks) { + if (oldGoodsStationsMap.containsKey(workFlow.getGoodsId())) { + // 更新totalNum,并把状态改成分配中 + GoodsToStation goodsToStation = oldGoodsStationsMap.get(workFlow.getGoodsId()); + goodsToStation.setTotalNum(goodsToStation.getTotalNum().add(workFlow.getNeedNum())); + oldGoodsStationsMap.replace(workFlow.getGoodsId(), goodsToStation); + } else { + GoodsToStation newGoodsToStation = new GoodsToStation(); + newGoodsToStation.setConfigId(generateId("")); + newGoodsToStation.setGoodsId(workFlow.getGoodsId()); + newGoodsToStation.setWorkStation(thisStandId); + newGoodsToStation.setDistributeStatus(0); + newGoodsToStation.setDistributedNum(BigDecimal.ZERO); + newGoodsToStation.setTotalNum(workFlow.getNeedNum()); + oldGoodsStationsMap.put(workFlow.getGoodsId(), newGoodsToStation); + } + WorkFlow onlyForUpdateTemp = new WorkFlow(); + onlyForUpdateTemp.setWorkFlowId(workFlow.getWorkFlowId()); + onlyForUpdateTemp.setWorkStatus(0); + onlyForUpdateTemp.setWorkStation(thisStandId); + thisTimeDistributeWorkFlows.add(onlyForUpdateTemp); + } + // 替换 + stationToGoodsToStationsMap.put(thisStandId, oldGoodsStationsMap.values().stream().toList()); + } + // 以下更新物料需求 + for (String standId : stationToGoodsToStationsMap.keySet()) { + finalGoodsToStationsOfNext.addAll(stationToGoodsToStationsMap.get(standId)); + } + // 以下更新电子标签配置 + for (String standId : stationToELocationConfigsMap.keySet()) { + finalELocationConfigsOfNext.addAll(stationToELocationConfigsMap.get(standId)); + } + } else { + logger.info("无法分配次选机型,可能是没有工作流或可用站台。"); + } + + // 最终存储数据 + List finalGoodsToStations = new ArrayList<>();// 物料分配 + List finalELocationConfigs = new ArrayList<>();// 标签库位分配 + // 物料需求 + if (!finalGoodsToStationsOfFirst.isEmpty()) { + finalGoodsToStations.addAll(finalGoodsToStationsOfFirst); + } + if (!finalGoodsToStationsOfNext.isEmpty()) { + finalGoodsToStations.addAll(finalGoodsToStationsOfNext); + } + // 更新物料需求数据库 + if (!finalGoodsToStations.isEmpty()) { + goodsToStationService.saveOrUpdateBatch(finalGoodsToStations); + logger.info("添加新的站台物料需求成功。"); + } else { + logger.info("没有新的站台物料需求。"); + } + // 电子标签配置 + if (!finalELocationConfigsOfFirst.isEmpty()) { + finalELocationConfigs.addAll(finalELocationConfigsOfFirst); + } + if (!finalELocationConfigsOfNext.isEmpty()) { + finalELocationConfigs.addAll(finalELocationConfigsOfNext); + } + // 添加标签配置数据库 + if (!finalELocationConfigs.isEmpty()) { + eLocationConfigService.saveBatch(finalELocationConfigs); + logger.info("添加新的灯光配置成功。"); + } else { + logger.info("没有新的灯光配置。"); + } + // 更新工作流数据 + if (!thisTimeDistributeWorkFlows.isEmpty()) { + workFlowService.updateBatchById(thisTimeDistributeWorkFlows); + logger.info("分配工作完成,此次分配{}条。", thisTimeDistributeWorkFlows.size()); + } else { + logger.info("此次未执行分配。"); + } + } catch (Exception e) { + logger.error("分配工作发生异常:{}", JSON.toJSONString(e)); + // 回滚事务 + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + } + } + + /** + * 分配工作的第二种方法 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public void distributeWorksMethod2() { + try { + // 查询所有的拣选站台 + List allPickStands = standService.list(new LambdaQueryWrapper() + .eq(Stand::getStandType, 2).eq(Stand::getIsLock, 0) + .orderByAsc(Stand::getStandId)); + // 找出可用的站台 + List usablePickStands = allPickStands.stream().filter(stand -> stand.getStandStatus() == 0).toList(); + if (usablePickStands.size() != allPickStands.size()) { + logger.info("站台未全部释放,不执行分配。"); + return; + } + // 映射出站台号 + List standIds = usablePickStands.stream().map(Stand::getStandId).distinct().toList(); + if (standIds.isEmpty()) { + logger.info("没有站台能够分配,不执行分配。"); + return; + } + // 查询出所有的工作流 + List allCurrentWorks = workFlowService.list(); + // 查询这些站台是否已经分配了工作 + boolean haveDistributedWorks = false; + for (String standId : standIds) { + List distributedWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getWorkStation().equals(standId)).toList(); + if (!distributedWorks.isEmpty()) { + haveDistributedWorks = true; + break; } } - // 生成每个大盒子的物料种类map - Map bigBoxToGoodsTypeQtyMap = new HashMap<>(); - for (String bigBox : workFlowsByBigBoxMap.keySet()) { - List thisBoxWorkFlows = workFlowsByBigBoxMap.get(bigBox); - int goodsTypeQty = thisBoxWorkFlows.stream().map(WorkFlow::getGoodsId).distinct().toList().size(); - bigBoxToGoodsTypeQtyMap.put(bigBox, goodsTypeQty); + if (haveDistributedWorks) { + logger.info("有站台进行过分配,不执行分配。"); + return; } - // 根据物料种类数量对大盒子进行排序 - List sortedBoxedByGoodsTypeQty = bigBoxToGoodsTypeQtyMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(Map.Entry::getKey).toList(); - // 每个站台包含的物料种类数量 - Map> stationToGoodsTypeQtyMap = new HashMap<>(); - // 每个站台分配的电子标签 - Map> stationToELocationConfigsMap = new HashMap<>(); - // 每个站台的物料需求 - Map> stationToGoodsToStationsMap = new HashMap<>(); + // 获取工作优先级 + String workPriority = configMap.get(ConfigMapKeyEnum.WORK_PRIORITY.getConfigKey()); + // 获取优先的工作类型 + int firstWorkType;// 1为装载机,2为平地机 + if (!StringUtils.isEmpty(workPriority) && workPriority.equals("1")) { + firstWorkType = 2; + } else { + firstWorkType = 1; + } + // 需要分配的平地机工作流 + List needDistributeMgWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 2 && workFlow.getWorkStatus() == -1).toList(); + // 需要分配的装载机工作流 + List needDistributeMwlWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 1 && workFlow.getWorkStatus() == -1).toList(); + // 方案1:装载机与平地机分开分配,且优先分配的工作的物料类对次选工作存在影响 + List needDistributeWorksOfFirst = new ArrayList<>(); + List needDistributeWorksOfNext = new ArrayList<>(); + if (firstWorkType == 1) { + needDistributeWorksOfFirst.addAll(needDistributeMwlWorks); + needDistributeWorksOfNext.addAll(needDistributeMgWorks); + } else { + needDistributeWorksOfFirst.addAll(needDistributeMgWorks); + needDistributeWorksOfNext.addAll(needDistributeMwlWorks); + } + // 获取所有可用的电子标签位 + List allELocations = eTagLocationService.list(new LambdaQueryWrapper() + .eq(ETagLocation::getELocationStatus, 0) + .orderByAsc(ETagLocation::getSequenceId)); + // 获取已经添加的电子标签库位分配 + List oldELocationConfigs = eLocationConfigService.list(new LambdaQueryWrapper() + .in(ELocationConfig::getWorkStation, standIds)); + if (oldELocationConfigs != null && !oldELocationConfigs.isEmpty()) { + logger.info("存在旧的标签配置,不执行分配。"); + return; + } + // 本次分配的工作 + List thisTimeDistributeWorkFlows = new ArrayList<>(); + // 查询出所有的工站配置 + List workStationConfigs = workStationConfigService.list(); + // 根据小盒子号生成map + Map smallBoxToBigBoxConfigMap = workStationConfigs.stream().collect(Collectors.toMap(WorkStationConfig::getSmallBox, WorkStationConfig::getBigBox)); + // 首选工作存储的信息 + List finalGoodsToStationsOfFirst = new ArrayList<>();// 物料分配 + List finalELocationConfigsOfFirst = new ArrayList<>();// 标签库位分配 // 每个站台的剩余电子标签 Map> stationToRemainELocationMap = new HashMap<>(); for (String standId : standIds) { @@ -823,164 +1212,362 @@ public class WorkServiceImplements implements IWorkService { // 排序 List thisStandELocationIds = thisStandELocations.stream().sorted(Comparator.comparingInt(ETagLocation::getSequenceId)).map(ETagLocation::getELocationId).toList(); stationToRemainELocationMap.put(standId, thisStandELocationIds); - // 每个站台物料分配种类 - stationToGoodsTypeQtyMap.put(standId, new ArrayList<>()); } - // 决定每个大盒子的站台分配 - Map bigBoxToStandIdMap = new HashMap<>(); - // 物料种类总数---这里存在一个分歧,大盒子之间的共通物料种类是否需要重复计算---CONFUSION - int totalGoodsTypeQty = needDistributeWorks.stream().map(WorkFlow::getGoodsId).distinct().toList().size(); - // 物料种类数量平均值 - int goodsTypeQtyAverage = (int) Math.ceil(totalGoodsTypeQty / (double) standIds.size()); - // 查询出需要分配的工单的dbs - List kateDBSS = kateDBSService.list(new LambdaQueryWrapper() - .in(KateDBS::getWorkOrder, needDistributeWorks.stream().map(WorkFlow::getWorkOrder).distinct().toList())); - // 将这个工单的顺序号进行一个map - Map workOrderToSequenceMap = kateDBSS.stream().collect(Collectors.toMap(KateDBS::getWorkOrder, KateDBS::getWorkSequence)); - for (String bigBox : sortedBoxedByGoodsTypeQty) { - // 找出这个站台下的工作流 - List thisBoxWorkFlows = workFlowsByBigBoxMap.get(bigBox); - if (thisBoxWorkFlows.isEmpty()) { - // 当前大盒子没有工作流,跳过 - continue; - } - // 获取这个大盒子下面的物料列表 - List goodsIds = thisBoxWorkFlows.stream().map(WorkFlow::getGoodsId).distinct().toList(); - // 未分配的工作流,按照boxNo分组 - Map> notDistributeYetWorksByBoxMap = new HashMap<>(); - for (WorkFlow workFlow : thisBoxWorkFlows) { - String boxNo = workFlow.getWorkOrder() + "@" + workFlow.getWorkCenter(); - notDistributeYetWorksByBoxMap.computeIfAbsent(boxNo, k -> new ArrayList<>()) - .add(workFlow); -// if (notDistributeYetWorksByBoxMap.containsKey(boxNo)) { -// List thisBoxNotDistributeYetWorks = new ArrayList<>(notDistributeYetWorksByBoxMap.get(boxNo)); -// thisBoxNotDistributeYetWorks.add(workFlow); -// notDistributeYetWorksByBoxMap.replace(boxNo, thisBoxNotDistributeYetWorks); -// } else { -// notDistributeYetWorksByBoxMap.put(boxNo, List.of(workFlow)); -// } - } - if (notDistributeYetWorksByBoxMap.isEmpty()) { - // 当前大盒子全部分配完毕 - continue; - } - String targetStandId = ""; - if (currentWorkType == 1) { - // 装载机使用固定配置 - List thisBigBoxConfigs = workStationConfigs.stream().filter(workStationConfig -> workStationConfig.getBigBox().equals(bigBox)).toList(); - if (!thisBigBoxConfigs.isEmpty()) { - targetStandId = thisBigBoxConfigs.get(0).getWorkStation(); + // 每个站台做的机型 + Map standToMachineTypeMap = new HashMap<>(); + // 下面开始分配首选工作 + if (!needDistributeWorksOfFirst.isEmpty()) { + logger.info("开始分配首选机型。"); + // 获取大盒子-订单的map + Map> workFlowsByBigBoxMapOfFirst = new HashMap<>(); + for (WorkFlow workFlow : needDistributeWorksOfFirst) { + if (smallBoxToBigBoxConfigMap.containsKey(workFlow.getWorkCenter())) { + String bigBox = smallBoxToBigBoxConfigMap.get(workFlow.getWorkCenter()); + workFlowsByBigBoxMapOfFirst.computeIfAbsent(bigBox, k -> new ArrayList<>()) + .add(workFlow); } - } else { + } + // 根据订单量,对大盒子号进行一个排序 + List bigBoxes = workFlowsByBigBoxMapOfFirst.keySet().stream().sorted(Comparator.comparingInt(o -> workFlowsByBigBoxMapOfFirst.get(o).size())).toList(); + // 每个站台分配的电子标签 + Map> stationToELocationConfigsMap = new HashMap<>(); + // 每个站台的物料需求 + Map> stationToGoodsToStationsMap = new HashMap<>(); + // 决定每个大盒子的站台分配 + Map bigBoxToStandIdMap = new HashMap<>(); + // 查询出需要分配的工单的dbs + List kateDBSS = kateDBSService.list(new LambdaQueryWrapper() + .in(KateDBS::getWorkOrder, needDistributeWorksOfFirst.stream().map(WorkFlow::getWorkOrder).distinct().toList())); + // 将这个工单的顺序号进行一个map + Map workOrderToSequenceMap = kateDBSS.stream().collect(Collectors.toMap(KateDBS::getWorkOrder, KateDBS::getWorkSequence)); + // 轮询站台 + for (String targetStandId : standIds) { + if (stationToRemainELocationMap.get(targetStandId) == null || stationToRemainELocationMap.get(targetStandId).isEmpty()) { + // 当前站台没有可用的电子标签库位 + continue; + } + // 轮询大盒子,找到可以分配的 + for (String bigBox : bigBoxes) { + if (bigBoxToStandIdMap.containsKey(bigBox)) { + // 当前大盒子已经被分配过站台 + continue; + } + // 找出这个大盒子下的工作流 + List thisBoxWorkFlows = workFlowsByBigBoxMapOfFirst.get(bigBox); + if (thisBoxWorkFlows.isEmpty()) { + // 当前大盒子没有工作流,跳过 + continue; + } + // 未分配的工作流,按照boxNo分组 + Map> notDistributeYetWorksByBoxMap = new HashMap<>(); + for (WorkFlow workFlow : thisBoxWorkFlows) { + String boxNo = workFlow.getWorkOrder() + "@" + workFlow.getWorkCenter(); + notDistributeYetWorksByBoxMap.computeIfAbsent(boxNo, k -> new ArrayList<>()) + .add(workFlow); + } + if (notDistributeYetWorksByBoxMap.isEmpty()) { + // 当前大盒子全部分配完毕 + continue; + } + if (notDistributeYetWorksByBoxMap.size() > stationToRemainELocationMap.get(targetStandId).size()) { + // 标签个数不够 + continue; + } + // 判断这个站台是否还包含剩余标签位 + List thisStandRemainELocationIds = new ArrayList<>(stationToRemainELocationMap.get(targetStandId)); + if (thisStandRemainELocationIds.size() < notDistributeYetWorksByBoxMap.size()) { + // 标签不够,此处的判断主要用于装载机 + continue; + } + // 排序后的key + List sortedKeyString = notDistributeYetWorksByBoxMap.keySet().stream() + .sorted( + Comparator.comparing((String o) -> workOrderToSequenceMap.get(o.split("@")[0])) + .thenComparing(o -> o.split("@")[1]) + ) + .toList(); + // 本次生成的电子标签配置 + List thisStandELocationConfigs = stationToELocationConfigsMap.getOrDefault(targetStandId, new ArrayList<>()); + for (String boxNo : sortedKeyString) { + // 获取一个电子标签库位 + String eLocationId = thisStandRemainELocationIds.get(0); + ELocationConfig eLocationConfig = new ELocationConfig(); + eLocationConfig.setWorkOrder(boxNo.split("@")[0]); + eLocationConfig.setWorkCenter(boxNo.split("@")[1]); + eLocationConfig.setWorkStation(targetStandId); + eLocationConfig.setELocationId(eLocationId); + eLocationConfig.setOrderBoxNo(boxNo); + // 添加配置 + thisStandELocationConfigs.add(eLocationConfig); + // 移除这个库位 + thisStandRemainELocationIds.remove(eLocationId); + } + // 更新电子标签剩余库位 + stationToRemainELocationMap.replace(targetStandId, thisStandRemainELocationIds); + // 更新电子标签配置 + stationToELocationConfigsMap.put(targetStandId, thisStandELocationConfigs); + // 已经分配完的大盒子 + bigBoxToStandIdMap.put(bigBox, targetStandId); + // 制定当前站台已经在做的工作类型 + standToMachineTypeMap.put(targetStandId, firstWorkType); + } + } + // 处理分配 + List oldGoodsStations = goodsToStationService.list(); + if (oldGoodsStations != null && !oldGoodsStations.isEmpty()) { + // 按照站台分组 + stationToGoodsToStationsMap = oldGoodsStations.stream().collect(Collectors.groupingBy(GoodsToStation::getWorkStation)); + } + // 更新数据 + for (String bigBox : bigBoxToStandIdMap.keySet()) { + String thisStandId = bigBoxToStandIdMap.get(bigBox); + // 当前站台的旧的goodsToStation + List thisStandOldGoodsToStationList = stationToGoodsToStationsMap.getOrDefault(thisStandId, new ArrayList<>()); + // 根据料号Map一下 + Map oldGoodsStationsMap = thisStandOldGoodsToStationList.stream().collect(Collectors.toMap(GoodsToStation::getGoodsId, goodsToStation -> goodsToStation)); + List thisBigBoxWorks = workFlowsByBigBoxMapOfFirst.get(bigBox); + for (WorkFlow workFlow : thisBigBoxWorks) { + if (oldGoodsStationsMap.containsKey(workFlow.getGoodsId())) { + // 更新totalNum,并把状态改成分配中 + GoodsToStation goodsToStation = oldGoodsStationsMap.get(workFlow.getGoodsId()); + goodsToStation.setTotalNum(goodsToStation.getTotalNum().add(workFlow.getNeedNum())); + oldGoodsStationsMap.replace(workFlow.getGoodsId(), goodsToStation); + } else { + GoodsToStation newGoodsToStation = new GoodsToStation(); + newGoodsToStation.setConfigId(generateId("")); + newGoodsToStation.setGoodsId(workFlow.getGoodsId()); + newGoodsToStation.setWorkStation(thisStandId); + newGoodsToStation.setDistributeStatus(0); + newGoodsToStation.setDistributedNum(BigDecimal.ZERO); + newGoodsToStation.setTotalNum(workFlow.getNeedNum()); + oldGoodsStationsMap.put(workFlow.getGoodsId(), newGoodsToStation); + } + WorkFlow onlyForUpdateTemp = new WorkFlow(); + onlyForUpdateTemp.setWorkFlowId(workFlow.getWorkFlowId()); + onlyForUpdateTemp.setWorkStatus(0); + onlyForUpdateTemp.setWorkStation(thisStandId); + thisTimeDistributeWorkFlows.add(onlyForUpdateTemp); + } + // 替换 + stationToGoodsToStationsMap.put(thisStandId, oldGoodsStationsMap.values().stream().toList()); + } + // 以下更新物料需求 + for (String standId : stationToGoodsToStationsMap.keySet()) { + finalGoodsToStationsOfFirst.addAll(stationToGoodsToStationsMap.get(standId)); + } + // 以下更新电子标签配置 + for (String standId : stationToELocationConfigsMap.keySet()) { + finalELocationConfigsOfFirst.addAll(stationToELocationConfigsMap.get(standId)); + } + } else { + logger.info("无法分配首选机型,可能是没有工作流或可用站台。"); + } + // 筛选次选工作还有哪些站台可用 + List nextWorkStandIds = new ArrayList<>(); + for (String standId : standIds) { + if (standToMachineTypeMap.containsKey(standId)) { + continue; + } + nextWorkStandIds.add(standId); + } + // 次选工作存储的信息 + List finalGoodsToStationsOfNext = new ArrayList<>();// 物料分配 + List finalELocationConfigsOfNext = new ArrayList<>();// 标签库位分配 + // 处理次选工作 TODO 需要考虑一下优先分配和首选工作存在相同物料种类的大盒子 + if (!needDistributeWorksOfNext.isEmpty() && !nextWorkStandIds.isEmpty()) { + logger.info("开始分配次选机型。"); + // 获取大盒子-订单的map + Map> workFlowsByBigBoxMapOfNext = new HashMap<>(); + for (WorkFlow workFlow : needDistributeWorksOfNext) { + if (smallBoxToBigBoxConfigMap.containsKey(workFlow.getWorkCenter())) { + String bigBox = smallBoxToBigBoxConfigMap.get(workFlow.getWorkCenter()); + workFlowsByBigBoxMapOfNext.computeIfAbsent(bigBox, k -> new ArrayList<>()) + .add(workFlow); + } + } + // 生成每个大盒子的物料种类map + Map bigBoxToGoodsTypeQtyMap = new HashMap<>(); + for (String bigBox : workFlowsByBigBoxMapOfNext.keySet()) { + List thisBoxWorkFlows = workFlowsByBigBoxMapOfNext.get(bigBox); + int goodsTypeQty = thisBoxWorkFlows.stream().map(WorkFlow::getGoodsId).distinct().toList().size(); + bigBoxToGoodsTypeQtyMap.put(bigBox, goodsTypeQty); + } + // 根据物料种类数量对大盒子进行排序 + List sortedBoxesByGoodsTypeQty = bigBoxToGoodsTypeQtyMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(Map.Entry::getKey).toList(); + // 每个站台包含的物料种类数量 + Map> stationToGoodsTypeQtyMap = new HashMap<>(); + for (String standId : nextWorkStandIds) { + // 每个站台物料分配种类 + stationToGoodsTypeQtyMap.put(standId, new ArrayList<>()); + } + // 每个站台分配的电子标签 + Map> stationToELocationConfigsMap = new HashMap<>(); + // 每个站台的物料需求 + Map> stationToGoodsToStationsMap = new HashMap<>(); + // 决定每个大盒子的站台分配 + Map bigBoxToStandIdMap = new HashMap<>(); + // 物料种类总数---这里存在一个分歧,大盒子之间的共通物料种类是否需要重复计算---CONFUSION + int totalGoodsTypeQty = needDistributeWorksOfNext.stream().map(WorkFlow::getGoodsId).distinct().toList().size(); + // 物料种类数量平均值 + int goodsTypeQtyAverage = (int) Math.ceil(totalGoodsTypeQty / (double) nextWorkStandIds.size()); + // 查询出需要分配的工单的dbs + List kateDBSS = kateDBSService.list(new LambdaQueryWrapper() + .in(KateDBS::getWorkOrder, needDistributeWorksOfNext.stream().map(WorkFlow::getWorkOrder).distinct().toList())); + // 将这个工单的顺序号进行一个map + Map workOrderToSequenceMap = kateDBSS.stream().collect(Collectors.toMap(KateDBS::getWorkOrder, KateDBS::getWorkSequence)); + for (String bigBox : sortedBoxesByGoodsTypeQty) { + // 找出这个大盒子下的工作流 + List thisBoxWorkFlows = workFlowsByBigBoxMapOfNext.get(bigBox); + if (thisBoxWorkFlows.isEmpty()) { + // 当前大盒子没有工作流,跳过 + continue; + } + // 获取这个大盒子下面的物料列表 + List goodsIds = thisBoxWorkFlows.stream().map(WorkFlow::getGoodsId).distinct().toList(); + // 未分配的工作流,按照boxNo分组 + Map> notDistributeYetWorksByBoxMap = new HashMap<>(); + for (WorkFlow workFlow : thisBoxWorkFlows) { + String boxNo = workFlow.getWorkOrder() + "@" + workFlow.getWorkCenter(); + notDistributeYetWorksByBoxMap.computeIfAbsent(boxNo, k -> new ArrayList<>()) + .add(workFlow); + } + if (notDistributeYetWorksByBoxMap.isEmpty()) { + // 当前大盒子全部分配完毕 + continue; + } + String targetStandId = ""; targetStandId = getMinGapStandToAvgAfterAddABox(stationToGoodsTypeQtyMap, goodsIds, goodsTypeQtyAverage, notDistributeYetWorksByBoxMap.size(), stationToRemainELocationMap); - } - if (StringUtils.isEmpty(targetStandId)) { - // 没有站台能够分配 - continue; - } - // 判断这个站台是否还包含剩余标签位 - List thisStandRemainELocationIds = new ArrayList<>(stationToRemainELocationMap.get(targetStandId)); - if (thisStandRemainELocationIds.size() < notDistributeYetWorksByBoxMap.size()) { - // 标签不够,此处的判断主要用于装载机 - continue; - } - // 排序后的key -// List sortedKeyString = notDistributeYetWorksByBoxMap.keySet().stream() -// .sorted(Comparator.comparing(o -> workOrderToSequenceMap.get(o.split("@")[0]))) -// .sorted(Comparator.comparing(o -> o.split("@")[1])) -// .toList(); - List sortedKeyString = notDistributeYetWorksByBoxMap.keySet().stream() - .sorted( - Comparator.comparing((String o) -> workOrderToSequenceMap.get(o.split("@")[0])) - .thenComparing(o -> o.split("@")[1]) - ) - .toList(); - // 本次生成的电子标签配置 - List thisStandELocationConfigs = stationToELocationConfigsMap.getOrDefault(targetStandId, new ArrayList<>()); - for (String boxNo : sortedKeyString) { - // 获取一个电子标签库位 - String eLocationId = thisStandRemainELocationIds.get(0); - ELocationConfig eLocationConfig = new ELocationConfig(); - eLocationConfig.setWorkOrder(boxNo.split("@")[0]); - eLocationConfig.setWorkCenter(boxNo.split("@")[1]); - eLocationConfig.setWorkStation(targetStandId); - eLocationConfig.setELocationId(eLocationId); - eLocationConfig.setOrderBoxNo(boxNo); - // 添加配置 - thisStandELocationConfigs.add(eLocationConfig); - // 移除这个库位 - thisStandRemainELocationIds.remove(eLocationId); - } - // 更新电子标签剩余库位 - stationToRemainELocationMap.replace(targetStandId, thisStandRemainELocationIds); - // 更新电子标签配置 - stationToELocationConfigsMap.put(targetStandId, thisStandELocationConfigs); - // 已经分配完的大盒子 - bigBoxToStandIdMap.put(bigBox, targetStandId); - } - // 处理分配 - List oldGoodsStations = goodsToStationService.list(); - if (oldGoodsStations != null && !oldGoodsStations.isEmpty()) { - // 按照站台分组 - stationToGoodsToStationsMap = oldGoodsStations.stream().collect(Collectors.groupingBy(GoodsToStation::getWorkStation)); - } - // 处理物料的需求分配 - List thisTimeDistributeWorkFlows = new ArrayList<>(); - for (String bigBox : bigBoxToStandIdMap.keySet()) { - String thisStandId = bigBoxToStandIdMap.get(bigBox); - // 当前站台的旧的goodsToStation - List thisStandOldGoodsToStationList = stationToGoodsToStationsMap.getOrDefault(thisStandId, new ArrayList<>()); - // 根据料号Map一下 - Map oldGoodsStationsMap = thisStandOldGoodsToStationList.stream().collect(Collectors.toMap(GoodsToStation::getGoodsId, goodsToStation -> goodsToStation)); - List thisBigBoxWorks = workFlowsByBigBoxMap.get(bigBox); - for (WorkFlow workFlow : thisBigBoxWorks) { - if (oldGoodsStationsMap.containsKey(workFlow.getGoodsId())) { - // 更新totalNum,并把状态改成分配中 - GoodsToStation goodsToStation = oldGoodsStationsMap.get(workFlow.getGoodsId()); - goodsToStation.setTotalNum(goodsToStation.getTotalNum().add(workFlow.getNeedNum())); - oldGoodsStationsMap.replace(workFlow.getGoodsId(), goodsToStation); - } else { - GoodsToStation newGoodsToStation = new GoodsToStation(); - newGoodsToStation.setConfigId(generateId("")); - newGoodsToStation.setGoodsId(workFlow.getGoodsId()); - newGoodsToStation.setWorkStation(thisStandId); - newGoodsToStation.setDistributeStatus(0); - newGoodsToStation.setDistributedNum(BigDecimal.ZERO); - newGoodsToStation.setTotalNum(workFlow.getNeedNum()); - oldGoodsStationsMap.put(workFlow.getGoodsId(), newGoodsToStation); + if (StringUtils.isEmpty(targetStandId)) { + // 没有站台能够分配 + continue; } - WorkFlow onlyForUpdateTemp = new WorkFlow(); - onlyForUpdateTemp.setWorkFlowId(workFlow.getWorkFlowId()); - onlyForUpdateTemp.setWorkStatus(0); - onlyForUpdateTemp.setWorkStation(thisStandId); - thisTimeDistributeWorkFlows.add(onlyForUpdateTemp); + // 判断这个站台是否还包含剩余标签位 + List thisStandRemainELocationIds = new ArrayList<>(stationToRemainELocationMap.get(targetStandId)); + if (thisStandRemainELocationIds.size() < notDistributeYetWorksByBoxMap.size()) { + // 标签不够,此处的判断主要用于装载机 + continue; + } + // 排序后的key + List sortedKeyString = notDistributeYetWorksByBoxMap.keySet().stream() + .sorted( + Comparator.comparing((String o) -> workOrderToSequenceMap.get(o.split("@")[0])) + .thenComparing(o -> o.split("@")[1]) + ) + .toList(); + // 本次生成的电子标签配置 + List thisStandELocationConfigs = stationToELocationConfigsMap.getOrDefault(targetStandId, new ArrayList<>()); + for (String boxNo : sortedKeyString) { + // 获取一个电子标签库位 + String eLocationId = thisStandRemainELocationIds.get(0); + ELocationConfig eLocationConfig = new ELocationConfig(); + eLocationConfig.setWorkOrder(boxNo.split("@")[0]); + eLocationConfig.setWorkCenter(boxNo.split("@")[1]); + eLocationConfig.setWorkStation(targetStandId); + eLocationConfig.setELocationId(eLocationId); + eLocationConfig.setOrderBoxNo(boxNo); + // 添加配置 + thisStandELocationConfigs.add(eLocationConfig); + // 移除这个库位 + thisStandRemainELocationIds.remove(eLocationId); + } + // 更新电子标签剩余库位 + stationToRemainELocationMap.replace(targetStandId, thisStandRemainELocationIds); + // 更新电子标签配置 + stationToELocationConfigsMap.put(targetStandId, thisStandELocationConfigs); + // 已经分配完的大盒子 + bigBoxToStandIdMap.put(bigBox, targetStandId); } - // 替换 - stationToGoodsToStationsMap.put(thisStandId, oldGoodsStationsMap.values().stream().toList()); + // 处理分配 + List oldGoodsStations = goodsToStationService.list(); + if (oldGoodsStations != null && !oldGoodsStations.isEmpty()) { + // 按照站台分组 + stationToGoodsToStationsMap = oldGoodsStations.stream().collect(Collectors.groupingBy(GoodsToStation::getWorkStation)); + } + // 更新数据 + for (String bigBox : bigBoxToStandIdMap.keySet()) { + String thisStandId = bigBoxToStandIdMap.get(bigBox); + // 当前站台的旧的goodsToStation + List thisStandOldGoodsToStationList = stationToGoodsToStationsMap.getOrDefault(thisStandId, new ArrayList<>()); + // 根据料号Map一下 + Map oldGoodsStationsMap = thisStandOldGoodsToStationList.stream().collect(Collectors.toMap(GoodsToStation::getGoodsId, goodsToStation -> goodsToStation)); + List thisBigBoxWorks = workFlowsByBigBoxMapOfNext.get(bigBox); + for (WorkFlow workFlow : thisBigBoxWorks) { + if (oldGoodsStationsMap.containsKey(workFlow.getGoodsId())) { + // 更新totalNum,并把状态改成分配中 + GoodsToStation goodsToStation = oldGoodsStationsMap.get(workFlow.getGoodsId()); + goodsToStation.setTotalNum(goodsToStation.getTotalNum().add(workFlow.getNeedNum())); + oldGoodsStationsMap.replace(workFlow.getGoodsId(), goodsToStation); + } else { + GoodsToStation newGoodsToStation = new GoodsToStation(); + newGoodsToStation.setConfigId(generateId("")); + newGoodsToStation.setGoodsId(workFlow.getGoodsId()); + newGoodsToStation.setWorkStation(thisStandId); + newGoodsToStation.setDistributeStatus(0); + newGoodsToStation.setDistributedNum(BigDecimal.ZERO); + newGoodsToStation.setTotalNum(workFlow.getNeedNum()); + oldGoodsStationsMap.put(workFlow.getGoodsId(), newGoodsToStation); + } + WorkFlow onlyForUpdateTemp = new WorkFlow(); + onlyForUpdateTemp.setWorkFlowId(workFlow.getWorkFlowId()); + onlyForUpdateTemp.setWorkStatus(0); + onlyForUpdateTemp.setWorkStation(thisStandId); + thisTimeDistributeWorkFlows.add(onlyForUpdateTemp); + } + // 替换 + stationToGoodsToStationsMap.put(thisStandId, oldGoodsStationsMap.values().stream().toList()); + } + // 以下更新物料需求 + for (String standId : stationToGoodsToStationsMap.keySet()) { + finalGoodsToStationsOfNext.addAll(stationToGoodsToStationsMap.get(standId)); + } + // 以下更新电子标签配置 + for (String standId : stationToELocationConfigsMap.keySet()) { + finalELocationConfigsOfNext.addAll(stationToELocationConfigsMap.get(standId)); + } + } else { + logger.info("无法分配次选机型,可能是没有工作流或可用站台。"); } - // 以下更新物料需求 - for (String standId : stationToGoodsToStationsMap.keySet()) { - finalGoodsToStations.addAll(stationToGoodsToStationsMap.get(standId)); + + // 最终存储数据 + List finalGoodsToStations = new ArrayList<>();// 物料分配 + List finalELocationConfigs = new ArrayList<>();// 标签库位分配 + // 物料需求 + if (!finalGoodsToStationsOfFirst.isEmpty()) { + finalGoodsToStations.addAll(finalGoodsToStationsOfFirst); } + if (!finalGoodsToStationsOfNext.isEmpty()) { + finalGoodsToStations.addAll(finalGoodsToStationsOfNext); + } + // 更新物料需求数据库 if (!finalGoodsToStations.isEmpty()) { goodsToStationService.saveOrUpdateBatch(finalGoodsToStations); + logger.info("添加新的站台物料需求成功。"); + } else { + logger.info("没有新的站台物料需求。"); } - // 以下更新电子标签配置 - for (String standId : stationToELocationConfigsMap.keySet()) { - finalELocationConfigs.addAll(stationToELocationConfigsMap.get(standId)); + // 电子标签配置 + if (!finalELocationConfigsOfFirst.isEmpty()) { + finalELocationConfigs.addAll(finalELocationConfigsOfFirst); } + if (!finalELocationConfigsOfNext.isEmpty()) { + finalELocationConfigs.addAll(finalELocationConfigsOfNext); + } + // 添加标签配置数据库 if (!finalELocationConfigs.isEmpty()) { - // 添加电子标签库位配置 eLocationConfigService.saveBatch(finalELocationConfigs); + logger.info("添加新的灯光配置成功。"); + } else { + logger.info("没有新的灯光配置。"); } // 更新工作流数据 if (!thisTimeDistributeWorkFlows.isEmpty()) { workFlowService.updateBatchById(thisTimeDistributeWorkFlows); + logger.info("分配工作完成,此次分配{}条。", thisTimeDistributeWorkFlows.size()); + } else { + logger.info("此次未执行分配。"); } - logger.info("分配工作完成"); } catch (Exception e) { - e.printStackTrace(); - logger.error("分配工作发生异常:{}", e.getMessage()); + logger.error("分配工作发生异常:{}", JSON.toJSONString(e)); // 回滚事务 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } @@ -1002,7 +1589,7 @@ public class WorkServiceImplements implements IWorkService { // 这里对站台好排序一下,从前到后 List sortedStandIds = goodsIdsToStandMap.keySet().stream().sorted(Comparator.comparing(o -> o)).toList(); // 筛选新增加的物料数量 - List thisTimeAddGoodsIds = new ArrayList<>(); + List thisTimeAddGoodsIds = new ArrayList<>(); for (String standId : sortedStandIds) { if (needELocationQty > stationToRemainELocationMap.get(standId).size()) { // 标签个数不够 @@ -1010,9 +1597,10 @@ public class WorkServiceImplements implements IWorkService { } List thisStandGoodsId = goodsIdsToStandMap.get(standId); // 筛选新增加的物料数量 - List thisTimeAddGoodsIdsOfThisStand = new ArrayList<>(); + List thisTimeAddGoodsIdsOfThisStand = new ArrayList<>(); for (String goodsId : goodsIdsThisTime) { - if (thisStandGoodsId.stream().filter(goodsId1 -> goodsId1.equals(goodsId)).toList().isEmpty()) thisTimeAddGoodsIdsOfThisStand.add(goodsId); + if (thisStandGoodsId.stream().filter(goodsId1 -> goodsId1.equals(goodsId)).toList().isEmpty()) + thisTimeAddGoodsIdsOfThisStand.add(goodsId); } // 判断偏差值 int gap = thisStandGoodsId.size() + thisTimeAddGoodsIdsOfThisStand.size() - avgQty;