diff --git a/src/main/java/com/wms/controller/JobComponent.java b/src/main/java/com/wms/controller/JobComponent.java deleted file mode 100644 index 427e4d1..0000000 --- a/src/main/java/com/wms/controller/JobComponent.java +++ /dev/null @@ -1,234 +0,0 @@ -package com.wms.controller; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.wms.constants.enums.ConfigMapKeyEnum; -import com.wms.entity.table.Stand; -import com.wms.service.*; -import com.wms.service.business.IWmsJobService; -import com.wms.service.business.IWorkService; -import com.wms.utils.StringUtils; -import lombok.RequiredArgsConstructor; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.scheduling.annotation.Async; -import org.springframework.scheduling.annotation.EnableAsync; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Isolation; -import org.springframework.transaction.annotation.Propagation; -import org.springframework.transaction.annotation.Transactional; -import org.springframework.transaction.interceptor.TransactionAspectSupport; - -import static com.wms.config.InitLocalConfig.configMap; -import static com.wms.utils.StringUtils.convertJsonString; - -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.util.*; - -/** - * 定期任务类 - */ -@Component -@RequiredArgsConstructor(onConstructor = @__(@Autowired)) -public class JobComponent { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - /** - * WMS定时任务服务 - */ - private final IWmsJobService wmsJobService; - /** - * 站台服务 - */ - private final StandService standService; - /** - * 工作服务 - */ - private final IWorkService workService; - - private boolean isSendingCommonTask = false; - private boolean isSendingPickOutTask = false; - private boolean isSendingPickTask = false; - - /** - * 向Wcs下发任务 - * 每2秒执行一次 - */ -// @Scheduled(fixedDelay = 2000) - @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) - public void sendCommonTasks() { - if (isSendingCommonTask) { - // 正在执行下发任务操作 - return; - } else { - isSendingCommonTask = true; - } - try { - String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey()); - if (StringUtils.isEmpty(sendTask) || !sendTask.equals("1")) { - return; - } - // 发送正常任务 - wmsJobService.sendCommonTasks(); - } catch (Exception e) { - // 回滚事务 - TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); - } finally { - isSendingCommonTask = false; - } - } - - /** - * 向Wcs下发站台拣选出库任务 - * 每2秒执行一次 - */ -// @Scheduled(fixedDelay = 2000) - @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) - public void sendPickOutTasks() { - if (isSendingPickOutTask) { - return; - } else { - isSendingPickOutTask = true; - } - try { - String sendTask = configMap.get(ConfigMapKeyEnum.SEND_PICK_OUT_TASK.getConfigKey()); - if (StringUtils.isEmpty(sendTask) || !sendTask.equals("1")) { - return; - } - // 发送站台拣选出库任务 - wmsJobService.sendPickOutTasks(); - } catch (Exception e) { - // 回滚事务 - TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); - } finally { - isSendingPickOutTask = false; - } - } - - /** - * 拣选任务 - * 每2秒执行一次 - */ -// @Scheduled(fixedDelay = 2000) - @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) - public void sendPickTasks() { - if (isSendingPickTask) { - return; - } else { - isSendingPickTask = true; - } - try { - String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey()); - if (StringUtils.isEmpty(sendTask) || !sendTask.equals("1")) { - return; - } - // 发送拣选任务 - wmsJobService.sendPickTasks(); - } catch (Exception e) { - // 回滚事务 - TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); - } finally { - isSendingPickTask = false; - } - } - - /** - * 重复入库任务 - * 每2秒执行一次 - */ -// @Scheduled(fixedDelay = 2000) -// @Async("myThreadPool") - @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) - public void solveDuplicateTask() { - String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey()); - if (StringUtils.isEmpty(sendTask) || !sendTask.equals("1")) { - return; - } - try { - // 针对重复入库的任务,发送新的目的地 - wmsJobService.solveDuplicateTask(); - } catch (Exception e) { - // 回滚事务 - TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); - } - } - - /** - * 创建工作 - */ -// @Scheduled(fixedDelay = 20000) - public void createWork() { - String createWork = configMap.get(ConfigMapKeyEnum.CREATE_WORK.getConfigKey()); - if (StringUtils.isEmpty(createWork) || !createWork.equals("1")) { - return; - } - // 判断当前时间是否在7:40到23:40之间 - LocalDateTime now = LocalDateTime.now(); - if (now.isBefore(LocalDateTime.of(now.toLocalDate(), LocalTime.of(7, 40))) || now.isAfter(LocalDateTime.of(now.toLocalDate(), LocalTime.of(23, 40)))) { - return; - } - try { - workService.createTempWorkFlows(); - } catch (Exception e) { - logger.error("创建当日工作发生错误:{}", e.getMessage()); - } - // 轮询工作站台,判断是否需要下发任务 - List stands = standService.list(new LambdaQueryWrapper() - .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0) - .eq(Stand::getStandType, 2).orderByAsc(Stand::getStandId)); - for (Stand workStation : stands) { - try { - // 创建工作 -// workService.createWork(workStation.getStandId()); - // 分配工作 - workService.distributeWorks(workStation.getStandId()); - } catch (Exception e) { -// logger.error("创建工作时发生错误:{}", e.getMessage()); - logger.error("分配工作时发生错误:{}", e.getMessage()); - } - } - } - - /** - * 执行工作 - */ -// @Scheduled(fixedDelay = 20000) - public void doWork() { - String startWork = configMap.get(ConfigMapKeyEnum.START_WORK.getConfigKey()); - if (StringUtils.isEmpty(startWork) || !startWork.equals("1")) { - return; - } - // 轮询工作站台,判断是否需要下发任务 - List stands = standService.list(new LambdaQueryWrapper() - .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0) - .eq(Stand::getStandType, 2)); - List standIds = stands.stream().map(Stand::getStandId).toList(); - for (String standId : standIds) { - try { - workService.doWork(standId); - } catch (Exception e) { - logger.error("执行工作时发生错误:{}", convertJsonString(e.getMessage())); - } - - } -// try { -// // 执行工作 -// workService.doWorkNew(standIds); -// } catch (Exception e) { -// logger.error("执行工作时发生错误:{}", convertJsonString(e.getMessage())); -// } - } - - /** - * 每天查询一次是否有过期记录 - * 每天晚上10点执行一次 - */ -// @Scheduled(cron = "0 0 22 * * ?") - public void deleteOutOfDateData() { - // 删除日志数据 - wmsJobService.deleteLogsRegularly(); - // 删除记录数据 - wmsJobService.deleteRecordsRegularly(); - } -} diff --git a/src/main/java/com/wms/quartz/job_executor/KateWorkExecutor.java b/src/main/java/com/wms/quartz/job_executor/KateWorkExecutor.java index 2fed638..d06af78 100644 --- a/src/main/java/com/wms/quartz/job_executor/KateWorkExecutor.java +++ b/src/main/java/com/wms/quartz/job_executor/KateWorkExecutor.java @@ -65,17 +65,11 @@ public class KateWorkExecutor implements Job { } catch (Exception e) { log.error("创建当日工作发生错误:{}", e.getMessage()); } - // 轮询工作站台,判断是否需要下发任务 - List stands = standService.list(new LambdaQueryWrapper() - .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0) - .eq(Stand::getStandType, 2).orderByAsc(Stand::getStandId)); - for (Stand workStation : stands) { - try { - // 分配工作 - workService.distributeWorks(workStation.getStandId()); - } catch (Exception e) { - log.error("分配工作时发生错误:{}", e.getMessage()); - } + try { + // 分配工作 + workService.distributeWorks(); + } catch (Exception e) { + log.error("分配工作时发生错误:{}", e.getMessage()); } } diff --git a/src/main/java/com/wms/service/business/IWorkService.java b/src/main/java/com/wms/service/business/IWorkService.java index 9edf480..9b4a485 100644 --- a/src/main/java/com/wms/service/business/IWorkService.java +++ b/src/main/java/com/wms/service/business/IWorkService.java @@ -21,14 +21,11 @@ public interface IWorkService { /** * 创建暂存工作 - * @throws Exception 异常 */ - void createTempWorkFlows() throws Exception; + void createTempWorkFlows(); /** * 分配工作 - * @param workStation 站台号 - * @throws Exception 异常 */ - void distributeWorks(String workStation) throws Exception; + void distributeWorks(); } 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 21ab088..0051721 100644 --- a/src/main/java/com/wms/service/business/serviceImplements/WorkServiceImplements.java +++ b/src/main/java/com/wms/service/business/serviceImplements/WorkServiceImplements.java @@ -10,7 +10,6 @@ import com.wms.service.*; import com.wms.service.business.IWmsTaskService; import com.wms.service.business.IWorkService; import com.wms.utils.StringUtils; -import com.wms.utils.WmsUtils; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,7 +25,6 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; -import java.util.stream.Stream; import static com.wms.config.InitLocalConfig.*; import static com.wms.constants.WmsConstants.MYSQL_JSON_CI; @@ -458,7 +456,7 @@ public class WorkServiceImplements implements IWorkService { for (KateOrders tempOrder : kateWorkOrderList) { // 生成workFlow WorkFlow tempWorkFlow = new WorkFlow(); - tempWorkFlow.setWorkFlowId(WmsUtils.generateId("WORKFLOW_")); + tempWorkFlow.setWorkFlowId(generateId("WORKFLOW_")); tempWorkFlow.setOrderId(tempOrder.getOrderId()); tempWorkFlow.setWorkStation(workStation); tempWorkFlow.setWorkOrder(tempOrder.getWorkOrder()); @@ -567,7 +565,6 @@ public class WorkServiceImplements implements IWorkService { allFlows.addAll(thisDayMWLWorks); } } - } else { List oldMgWorkFlows = allOldWorkFlows.stream().filter(workFlow -> workFlow.getMachineType() == 2).toList(); if (oldMgWorkFlows.isEmpty()) { @@ -665,124 +662,102 @@ public class WorkServiceImplements implements IWorkService { } /** - * 分配任务 - * - * @param workStation 站台号 + * 分配工作 + * 重构 */ @Override @Transactional(rollbackFor = Exception.class) - public void distributeWorks(String workStation) { - if (StringUtils.isEmpty(workStation)) { - // 站台号为空 - logger.error("站台号为空===》》》》》》"); - return; - } + public void distributeWorks() { 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("站台未全部释放,不执行分配。"); + } + // 映射出站台号 + List standIds = usablePickStands.stream().map(Stand::getStandId).distinct().toList(); + // 查询出所有的工作流 + 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; + } + } + if (haveDistributedWorks) { + logger.info("有站台进行过分配,不执行分配。"); + return; + } // 获取工作优先级 String workPriority = configMap.get(ConfigMapKeyEnum.WORK_PRIORITY.getConfigKey()); List needDistributeWorks = new ArrayList<>(); - List commonMwlWorks = workFlowService.list(new LambdaQueryWrapper<>()); int currentWorkType; - List doingWorks = filterWorkFlow(commonMwlWorks, workStation, 0, -1, -1); - if (!doingWorks.isEmpty()) { - // 当前站台还有正在做的工作,不允许再分配新工作 - return; - } if (!StringUtils.isEmpty(workPriority) && workPriority.equals("1")) { // 当前工作优先级为先平地机后装载机 - List oldWorkFlows = filterWorkFlow(commonMwlWorks, null, 2, -1, 0); - if (oldWorkFlows.isEmpty()) { - // 判断下是否有平地机任务还未生成 - List notCreatedMGWorks = new ArrayList<>(); - findWorks("", notCreatedMGWorks, "NOT_MWL", getCurrentWorkDate()); - if (!notCreatedMGWorks.isEmpty()) { - // 仍有未生成的平地机任务,跳过 - return; - } - //过滤commonMwlWorks 根据machineType=2,workStatus=-1 和workStation=1 - List doingMgWorkFlows = filterWorkFlow(commonMwlWorks, workStation, 2, -1, -1); - if (!doingMgWorkFlows.isEmpty()) { - // 当前站台平地机正在做 - return; - } - // 查询装载机 - //过滤commonMwlWorks 根据machineType=1,workStatus=-1 - List mwlWorks = filterWorkFlow(commonMwlWorks, null, 1, -1, 0); - if (mwlWorks.isEmpty()) { - // 没有装载机任务,跳过 - return; - } - needDistributeWorks.addAll(mwlWorks); - currentWorkType = 1;// 装载机 - } else { - needDistributeWorks.addAll(oldWorkFlows); + 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; + } } } else { // 默认优先级为先装载机后平地机 - List oldWorkFlows = filterWorkFlow(commonMwlWorks, null, 1, -1, 0); - if (oldWorkFlows.isEmpty()) { - // 判断下是否有装载机任务还未生成 - List notCreatedMWLWorks = new ArrayList<>(); - findWorks("", notCreatedMWLWorks, "MWL", getCurrentWorkDate()); - if (!notCreatedMWLWorks.isEmpty()) { - // 仍有未生成的装载机任务,跳过 - return; - } - List doingMwlWorkFlows = filterWorkFlow(commonMwlWorks, workStation, 1, -1, -1); - if (!doingMwlWorkFlows.isEmpty()) { - // 当前站台装载机正在做 - return; - } - // 查询平地机 - List mgWorks = filterWorkFlow(commonMwlWorks, null, 2, -1, 0); - if (mgWorks.isEmpty()) { - // 没有平地机任务,跳过 - return; - } - needDistributeWorks.addAll(mgWorks); - currentWorkType = 2;// 平地机 - } else { - needDistributeWorks.addAll(oldWorkFlows); + List needDistributeMwlWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 1 && workFlow.getWorkStatus() == -1).toList(); + if (!needDistributeMwlWorks.isEmpty()) { + needDistributeWorks.addAll(needDistributeMwlWorks); currentWorkType = 1;// 装载机 + } 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; + } } } // 最终需要存储的数据 - List finalGoodsToStations;// 物料分配 + List finalGoodsToStations = new ArrayList<>();// 物料分配 List finalELocationConfigs = new ArrayList<>();// 标签库位分配 - // 获取当前站台所有可用的电子标签库位 - List thisStandELocations = eTagLocationService.list(new LambdaQueryWrapper() - .eq(ETagLocation::getWorkStation, workStation) + // 获取所有可用的电子标签位 + List allELocations = eTagLocationService.list(new LambdaQueryWrapper() .eq(ETagLocation::getELocationStatus, 0) .orderByAsc(ETagLocation::getSequenceId)); // 获取已经添加的电子标签库位分配 - List allELocationConfigs = eLocationConfigService.list(); - // 筛选出剩余可用的电子标签库位 - List usedELocationIds = allELocationConfigs.stream().map(ELocationConfig::getELocationId).distinct().toList(); - List remainELocationIds = new ArrayList<>(); - for (ETagLocation eTagLocation : thisStandELocations) { - if (usedELocationIds.contains(eTagLocation.getELocationId())) { - continue; - } - remainELocationIds.add(eTagLocation.getELocationId()); - } - if (remainELocationIds.isEmpty()) { - // 当前站台没有可用电子标签库位分配了,跳过 + List oldELocationConfigs = eLocationConfigService.list(); + if (oldELocationConfigs != null && !oldELocationConfigs.isEmpty()) { + logger.info("存在旧的标签配置,不执行分配。"); return; } - // 然后获取大盒子-订单的map - Map> workFlowsByBigBoxMap = new HashMap<>(); // 获取工站配置 LambdaQueryWrapper wsConfigQueryWrapper = new LambdaQueryWrapper<>(); if (currentWorkType == 1) { // 当前是装载机工作,装载机要区分站台 - wsConfigQueryWrapper.eq(WorkStationConfig::getWorkStation, workStation) + wsConfigQueryWrapper .eq(WorkStationConfig::getModel, "MWL"); } else { // 当前是平地机工作 wsConfigQueryWrapper.ne(WorkStationConfig::getModel, "MWL"); } List workStationConfigs = workStationConfigService.list(wsConfigQueryWrapper); + // 然后获取大盒子-订单的map + Map> workFlowsByBigBoxMap = new HashMap<>(); // 根据小盒子号生成map Map smallBoxToBigBoxConfigMap = workStationConfigs.stream().collect(Collectors.toMap(WorkStationConfig::getSmallBox, WorkStationConfig::getBigBox)); for (WorkFlow workFlow : needDistributeWorks) { @@ -797,192 +772,228 @@ public class WorkServiceImplements implements IWorkService { } } } - // 根据订单量,对大盒子号进行一个排序 - List bigBoxes = workFlowsByBigBoxMap.keySet().stream().sorted(Comparator.comparingInt(o -> workFlowsByBigBoxMap.get(o).size())).toList(); - // 对已有的大盒子进行一个配置 - Map stationOfBigBoxMap = new HashMap<>(); - // 针对此站台的料盒号(工单@工作中心)生成一个map - Map eLocationIdOfBoxMap = new HashMap<>(); - for (ELocationConfig oldELocationConfig : allELocationConfigs) { - // 默认大盒子 = 小盒子 - String bigBox = oldELocationConfig.getWorkCenter(); - if (smallBoxToBigBoxConfigMap.containsKey(oldELocationConfig.getWorkCenter())) { - // 设置为实际的大盒子 - bigBox = smallBoxToBigBoxConfigMap.get(oldELocationConfig.getWorkCenter()); - } - // 判断这个大盒子是否分配了站台 - if (!stationOfBigBoxMap.containsKey(bigBox)) { - stationOfBigBoxMap.put(bigBox, oldELocationConfig.getWorkStation()); - } - // 更新料盒号-电子标签库位Map - if (!eLocationIdOfBoxMap.containsKey(oldELocationConfig.getOrderBoxNo())) { - eLocationIdOfBoxMap.put(oldELocationConfig.getOrderBoxNo(), oldELocationConfig.getELocationId()); - } + // 生成每个大盒子的物料种类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); } - // 开始分配电子标签库位 - List thisTimeDistributeWorkFlows = new ArrayList<>(); + // 根据物料种类数量对大盒子进行排序 + 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<>(); + // 每个站台的剩余电子标签 + Map> stationToRemainELocationMap = new HashMap<>(); + for (String standId : standIds) { + 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 = 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 : bigBoxes) { - if (remainELocationIds.isEmpty()) { - // 当前站台没有剩余电子标签位置可以分配了 - break; - } - // 判断这个大盒子是否分配了站台 - if (stationOfBigBoxMap.containsKey(bigBox) && !stationOfBigBoxMap.get(bigBox).equals(workStation)) { - continue; - } - // 获取到这个大盒子下面的所有工作流 - List thisBigBoxWorks = workFlowsByBigBoxMap.get(bigBox); - if (thisBigBoxWorks.isEmpty()) { + for (String bigBox : sortedBoxedByGoodsTypeQty) { + // 找出这个站台下的工作流 + List thisBoxWorkFlows = workFlowsByBigBoxMap.get(bigBox); + if (thisBoxWorkFlows.isEmpty()) { // 当前大盒子没有工作流,跳过 continue; } -// List thisBigBoxSortedWorks = thisBigBoxWorks.stream() -// .sorted(Comparator.comparing(WorkFlow::getWorkCenter)) -// .sorted(Comparator.comparingInt(workFlow -> workOrderToSequenceMap.get(workFlow.getWorkOrder()))) -// .toList(); + // 获取这个大盒子下面的物料列表 + List goodsIds = thisBoxWorkFlows.stream().map(WorkFlow::getGoodsId).distinct().toList(); // 未分配的工作流,按照boxNo分组 Map> notDistributeYetWorksByBoxMap = new HashMap<>(); - for (WorkFlow workFlow : thisBigBoxWorks) { + for (WorkFlow workFlow : thisBoxWorkFlows) { String boxNo = workFlow.getWorkOrder() + "@" + workFlow.getWorkCenter(); - if (!eLocationIdOfBoxMap.containsKey(boxNo)) { - 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.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; } - // 判断电子标签库位是否足够 - if (notDistributeYetWorksByBoxMap.size() > remainELocationIds.size()) { - // 这个大盒子的位置不够了,整个大盒子都不分配。 + String targetStandId = ""; + if (currentWorkType == 1) { + // 装载机使用固定配置 + List thisBigBoxConfigs = workStationConfigs.stream().filter(workStationConfig -> workStationConfig.getBigBox().equals(bigBox)).toList(); + if (!thisBigBoxConfigs.isEmpty()) { + targetStandId = thisBigBoxConfigs.get(0).getWorkStation(); + } + } else { + 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 thisStandELocationConfigs = stationToELocationConfigsMap.getOrDefault(targetStandId, new ArrayList<>()); for (String boxNo : sortedKeyString) { - if (eLocationIdOfBoxMap.containsKey(boxNo)) { - continue; - } // 获取一个电子标签库位 - String eLocationId = remainELocationIds.get(0); + String eLocationId = thisStandRemainELocationIds.get(0); ELocationConfig eLocationConfig = new ELocationConfig(); eLocationConfig.setWorkOrder(boxNo.split("@")[0]); eLocationConfig.setWorkCenter(boxNo.split("@")[1]); - eLocationConfig.setWorkStation(workStation); + eLocationConfig.setWorkStation(targetStandId); eLocationConfig.setELocationId(eLocationId); eLocationConfig.setOrderBoxNo(boxNo); // 添加配置 - finalELocationConfigs.add(eLocationConfig); - eLocationIdOfBoxMap.put(boxNo, eLocationId); - // 添加此次分配列表 - thisTimeDistributeWorkFlows.addAll(notDistributeYetWorksByBoxMap.get(boxNo)); + thisStandELocationConfigs.add(eLocationConfig); // 移除这个库位 - remainELocationIds.remove(eLocationId); + thisStandRemainELocationIds.remove(eLocationId); } - } - if (thisTimeDistributeWorkFlows.isEmpty()) { - return; + // 更新电子标签剩余库位 + stationToRemainELocationMap.replace(targetStandId, thisStandRemainELocationIds); + // 更新电子标签配置 + stationToELocationConfigsMap.put(targetStandId, thisStandELocationConfigs); + // 已经分配完的大盒子 + bigBoxToStandIdMap.put(bigBox, targetStandId); } // 处理分配 - List oldGoodsStations = goodsToStationService.list( - new LambdaQueryWrapper().eq(GoodsToStation::getWorkStation, workStation) - ); - // 根据料号Map一下 - Map oldGoodsStationsMap = oldGoodsStations.stream().collect(Collectors.toMap(GoodsToStation::getGoodsId, goodsToStation -> goodsToStation)); - // 新增 - Map newGoodsToStationMap = new HashMap<>(); - for (WorkFlow workFlow : thisTimeDistributeWorkFlows) { - if (newGoodsToStationMap.containsKey(workFlow.getGoodsId())) { - // 更新totalNum,并把状态改成分配中 - GoodsToStation goodsToStation = newGoodsToStationMap.get(workFlow.getGoodsId()); - goodsToStation.setTotalNum(goodsToStation.getTotalNum().add(workFlow.getNeedNum())); - newGoodsToStationMap.replace(workFlow.getGoodsId(), goodsToStation); - } else { - GoodsToStation newGoodsToStation = new GoodsToStation(); + 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与状态 - newGoodsToStation.setConfigId(oldGoodsStationsMap.get(workFlow.getGoodsId()).getConfigId()); - newGoodsToStation.setTotalNum(oldGoodsStationsMap.get(workFlow.getGoodsId()).getTotalNum().add(workFlow.getNeedNum())); - newGoodsToStation.setDistributeStatus(1); + // 更新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(workStation); + newGoodsToStation.setWorkStation(thisStandId); newGoodsToStation.setDistributeStatus(0); newGoodsToStation.setDistributedNum(BigDecimal.ZERO); newGoodsToStation.setTotalNum(workFlow.getNeedNum()); + oldGoodsStationsMap.put(workFlow.getGoodsId(), newGoodsToStation); } - newGoodsToStationMap.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()) { + finalGoodsToStations.addAll(stationToGoodsToStationsMap.get(standId)); } - finalGoodsToStations = newGoodsToStationMap.values().stream().toList(); - // 以下开始更新数据 if (!finalGoodsToStations.isEmpty()) { goodsToStationService.saveOrUpdateBatch(finalGoodsToStations); } - // 添加电子标签库位分配数据 + // 以下更新电子标签配置 + for (String standId : stationToELocationConfigsMap.keySet()) { + finalELocationConfigs.addAll(stationToELocationConfigsMap.get(standId)); + } if (!finalELocationConfigs.isEmpty()) { // 添加电子标签库位配置 eLocationConfigService.saveBatch(finalELocationConfigs); } // 更新工作流数据 - List flowIds = thisTimeDistributeWorkFlows.stream().map(WorkFlow::getWorkFlowId).toList(); - if (!flowIds.isEmpty()) { - workFlowService.update(new LambdaUpdateWrapper() - .set(WorkFlow::getWorkStatus, 0) - .set(WorkFlow::getWorkStation, workStation) - .in(WorkFlow::getWorkFlowId, flowIds)); + if (!thisTimeDistributeWorkFlows.isEmpty()) { + workFlowService.updateBatchById(thisTimeDistributeWorkFlows); } - logger.info("分配站台{}工作完成", workStation); + logger.info("分配工作完成"); } catch (Exception e) { - logger.error("分配站台:{}工作发生异常:{}", workStation, convertJsonString(e)); + logger.error("分配工作发生异常:{}", convertJsonString(e)); // 回滚事务 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } } /** - * 过滤工作流 + * 获取最小差距的站台(加上新数量后离平均值) * - * @param workFlows 工作流 - * @param workStation 工作站台 - * @param machineType 机型 - * @param workStatus 工作状态 - * @param flag 0: eq -1:ne - * @return 过滤后的数据 + * @param goodsIdsToStandMap 目前的每个站台物料种类 + * @param goodsIdsThisTime 本次需要增加的物料种类 + * @param avgQty 平均值 + * @param needELocationQty 需要的电子标签数量 + * @param stationToRemainELocationMap 站台与剩余电子标签数量 + * @return 站台号 */ - private List filterWorkFlow(List workFlows, String workStation, int machineType, int workStatus, int flag) { - Stream stream = workFlows.stream(); - - if (StringUtils.isNotEmpty(workStation)) { - stream = stream.filter(workFlow -> workFlow.getWorkStation().equals(workStation)); - } - - if (machineType > 0) { - stream = stream.filter(workFlow -> workFlow.getMachineType().equals(machineType)); - } - - if (workStatus != 0) { - if (flag == 0) { - stream = stream.filter(workFlow -> workFlow.getWorkStatus().equals(workStatus)); - } else { - stream = stream.filter(workFlow -> !workFlow.getWorkStatus().equals(workStatus)); + private String getMinGapStandToAvgAfterAddABox(Map> goodsIdsToStandMap, List goodsIdsThisTime, int avgQty, int needELocationQty, Map> stationToRemainELocationMap) { + int minGap = Integer.MAX_VALUE; + String targetStandId = ""; + // 这里对站台好排序一下,从前到后 + List sortedStandIds = goodsIdsToStandMap.keySet().stream().sorted(Comparator.comparing(o -> o)).toList(); + // 筛选新增加的物料数量 + List thisTimeAddGoodsIds = new ArrayList<>(); + for (String standId : sortedStandIds) { + if (needELocationQty > stationToRemainELocationMap.get(standId).size()) { + // 标签个数不够 + continue; + } + List thisStandGoodsId = goodsIdsToStandMap.get(standId); + // 筛选新增加的物料数量 + List thisTimeAddGoodsIdsOfThisStand = new ArrayList<>(); + for (String goodsId : goodsIdsThisTime) { + if (thisStandGoodsId.stream().filter(goodsId1 -> goodsId1.equals(goodsId)).toList().isEmpty()) thisTimeAddGoodsIdsOfThisStand.add(goodsId); + } + // 判断偏差值 + int gap = thisStandGoodsId.size() + thisTimeAddGoodsIdsOfThisStand.size() - avgQty; + if (gap < minGap) { + minGap = gap; + targetStandId = standId; + thisTimeAddGoodsIds = thisTimeAddGoodsIdsOfThisStand; } } - - return stream.collect(Collectors.toList()); + if (StringUtils.isNotEmpty(targetStandId)) { + List thisStandGoodsId = goodsIdsToStandMap.get(targetStandId); + thisStandGoodsId.addAll(thisTimeAddGoodsIds); + goodsIdsToStandMap.put(targetStandId, thisStandGoodsId); + } + return targetStandId; } }