1. 分配工作逻辑修改
This commit is contained in:
parent
5e095d8f74
commit
7a3090d752
|
|
@ -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<Stand> stands = standService.list(new LambdaQueryWrapper<Stand>()
|
||||
.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<Stand> stands = standService.list(new LambdaQueryWrapper<Stand>()
|
||||
.eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0)
|
||||
.eq(Stand::getStandType, 2));
|
||||
List<String> 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();
|
||||
}
|
||||
}
|
||||
|
|
@ -65,19 +65,13 @@ public class KateWorkExecutor implements Job {
|
|||
} catch (Exception e) {
|
||||
log.error("创建当日工作发生错误:{}", e.getMessage());
|
||||
}
|
||||
// 轮询工作站台,判断是否需要下发任务
|
||||
List<Stand> stands = standService.list(new LambdaQueryWrapper<Stand>()
|
||||
.eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0)
|
||||
.eq(Stand::getStandType, 2).orderByAsc(Stand::getStandId));
|
||||
for (Stand workStation : stands) {
|
||||
try {
|
||||
// 分配工作
|
||||
workService.distributeWorks(workStation.getStandId());
|
||||
workService.distributeWorks();
|
||||
} catch (Exception e) {
|
||||
log.error("分配工作时发生错误:{}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行工作
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<WorkFlow> 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("站台号为空===》》》》》》");
|
||||
public void distributeWorks() {
|
||||
try {
|
||||
// 查询所有的拣选站台
|
||||
List<Stand> allPickStands = standService.list(new LambdaQueryWrapper<Stand>()
|
||||
.eq(Stand::getStandType, 2).eq(Stand::getIsLock, 0)
|
||||
.orderByAsc(Stand::getStandId));
|
||||
// 找出可用的站台
|
||||
List<Stand> usablePickStands = allPickStands.stream().filter(stand -> stand.getStandStatus() == 0).toList();
|
||||
if (usablePickStands.size() != allPickStands.size()) {
|
||||
logger.info("站台未全部释放,不执行分配。");
|
||||
}
|
||||
// 映射出站台号
|
||||
List<String> standIds = usablePickStands.stream().map(Stand::getStandId).distinct().toList();
|
||||
// 查询出所有的工作流
|
||||
List<WorkFlow> allCurrentWorks = workFlowService.list();
|
||||
// 查询这些站台是否已经分配了工作
|
||||
boolean haveDistributedWorks = false;
|
||||
for (String standId : standIds) {
|
||||
List<WorkFlow> distributedWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getWorkStation().equals(standId)).toList();
|
||||
if (!distributedWorks.isEmpty()) {
|
||||
haveDistributedWorks = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (haveDistributedWorks) {
|
||||
logger.info("有站台进行过分配,不执行分配。");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// 获取工作优先级
|
||||
String workPriority = configMap.get(ConfigMapKeyEnum.WORK_PRIORITY.getConfigKey());
|
||||
List<WorkFlow> needDistributeWorks = new ArrayList<>();
|
||||
List<WorkFlow> commonMwlWorks = workFlowService.list(new LambdaQueryWrapper<>());
|
||||
int currentWorkType;
|
||||
List<WorkFlow> doingWorks = filterWorkFlow(commonMwlWorks, workStation, 0, -1, -1);
|
||||
if (!doingWorks.isEmpty()) {
|
||||
// 当前站台还有正在做的工作,不允许再分配新工作
|
||||
return;
|
||||
}
|
||||
if (!StringUtils.isEmpty(workPriority) && workPriority.equals("1")) {
|
||||
// 当前工作优先级为先平地机后装载机
|
||||
List<WorkFlow> oldWorkFlows = filterWorkFlow(commonMwlWorks, null, 2, -1, 0);
|
||||
if (oldWorkFlows.isEmpty()) {
|
||||
// 判断下是否有平地机任务还未生成
|
||||
List<WorkFlow> notCreatedMGWorks = new ArrayList<>();
|
||||
findWorks("", notCreatedMGWorks, "NOT_MWL", getCurrentWorkDate());
|
||||
if (!notCreatedMGWorks.isEmpty()) {
|
||||
// 仍有未生成的平地机任务,跳过
|
||||
return;
|
||||
}
|
||||
//过滤commonMwlWorks 根据machineType=2,workStatus=-1 和workStation=1
|
||||
List<WorkFlow> doingMgWorkFlows = filterWorkFlow(commonMwlWorks, workStation, 2, -1, -1);
|
||||
if (!doingMgWorkFlows.isEmpty()) {
|
||||
// 当前站台平地机正在做
|
||||
return;
|
||||
}
|
||||
// 查询装载机
|
||||
//过滤commonMwlWorks 根据machineType=1,workStatus=-1
|
||||
List<WorkFlow> mwlWorks = filterWorkFlow(commonMwlWorks, null, 1, -1, 0);
|
||||
if (mwlWorks.isEmpty()) {
|
||||
// 没有装载机任务,跳过
|
||||
return;
|
||||
}
|
||||
needDistributeWorks.addAll(mwlWorks);
|
||||
List<WorkFlow> needDistributeMgWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 2 && workFlow.getWorkStatus() == -1).toList();
|
||||
if (!needDistributeMgWorks.isEmpty()) {
|
||||
needDistributeWorks.addAll(needDistributeMgWorks);
|
||||
currentWorkType = 2;// 平地机
|
||||
} else {
|
||||
List<WorkFlow> needDistributeMwlWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 1 && workFlow.getWorkStatus() == -1).toList();
|
||||
if (!needDistributeMwlWorks.isEmpty()) {
|
||||
needDistributeWorks.addAll(needDistributeMwlWorks);
|
||||
currentWorkType = 1;// 装载机
|
||||
} else {
|
||||
needDistributeWorks.addAll(oldWorkFlows);
|
||||
currentWorkType = 2;// 平地机
|
||||
logger.info("当前没有未分配的工作,优先级:平地机优先。");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 默认优先级为先装载机后平地机
|
||||
List<WorkFlow> oldWorkFlows = filterWorkFlow(commonMwlWorks, null, 1, -1, 0);
|
||||
if (oldWorkFlows.isEmpty()) {
|
||||
// 判断下是否有装载机任务还未生成
|
||||
List<WorkFlow> notCreatedMWLWorks = new ArrayList<>();
|
||||
findWorks("", notCreatedMWLWorks, "MWL", getCurrentWorkDate());
|
||||
if (!notCreatedMWLWorks.isEmpty()) {
|
||||
// 仍有未生成的装载机任务,跳过
|
||||
return;
|
||||
}
|
||||
List<WorkFlow> doingMwlWorkFlows = filterWorkFlow(commonMwlWorks, workStation, 1, -1, -1);
|
||||
if (!doingMwlWorkFlows.isEmpty()) {
|
||||
// 当前站台装载机正在做
|
||||
return;
|
||||
}
|
||||
// 查询平地机
|
||||
List<WorkFlow> mgWorks = filterWorkFlow(commonMwlWorks, null, 2, -1, 0);
|
||||
if (mgWorks.isEmpty()) {
|
||||
// 没有平地机任务,跳过
|
||||
return;
|
||||
}
|
||||
needDistributeWorks.addAll(mgWorks);
|
||||
List<WorkFlow> needDistributeMwlWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 1 && workFlow.getWorkStatus() == -1).toList();
|
||||
if (!needDistributeMwlWorks.isEmpty()) {
|
||||
needDistributeWorks.addAll(needDistributeMwlWorks);
|
||||
currentWorkType = 1;// 装载机
|
||||
} else {
|
||||
List<WorkFlow> needDistributeMgWorks = allCurrentWorks.stream().filter(workFlow -> workFlow.getMachineType() == 2 && workFlow.getWorkStatus() == -1).toList();
|
||||
if (!needDistributeMgWorks.isEmpty()) {
|
||||
needDistributeWorks.addAll(needDistributeMgWorks);
|
||||
currentWorkType = 2;// 平地机
|
||||
} else {
|
||||
needDistributeWorks.addAll(oldWorkFlows);
|
||||
currentWorkType = 1;// 装载机
|
||||
logger.info("当前没有未分配的工作,优先级:装载机优先。");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 最终需要存储的数据
|
||||
List<GoodsToStation> finalGoodsToStations;// 物料分配
|
||||
List<GoodsToStation> finalGoodsToStations = new ArrayList<>();// 物料分配
|
||||
List<ELocationConfig> finalELocationConfigs = new ArrayList<>();// 标签库位分配
|
||||
// 获取当前站台所有可用的电子标签库位
|
||||
List<ETagLocation> thisStandELocations = eTagLocationService.list(new LambdaQueryWrapper<ETagLocation>()
|
||||
.eq(ETagLocation::getWorkStation, workStation)
|
||||
// 获取所有可用的电子标签位
|
||||
List<ETagLocation> allELocations = eTagLocationService.list(new LambdaQueryWrapper<ETagLocation>()
|
||||
.eq(ETagLocation::getELocationStatus, 0)
|
||||
.orderByAsc(ETagLocation::getSequenceId));
|
||||
// 获取已经添加的电子标签库位分配
|
||||
List<ELocationConfig> allELocationConfigs = eLocationConfigService.list();
|
||||
// 筛选出剩余可用的电子标签库位
|
||||
List<String> usedELocationIds = allELocationConfigs.stream().map(ELocationConfig::getELocationId).distinct().toList();
|
||||
List<String> remainELocationIds = new ArrayList<>();
|
||||
for (ETagLocation eTagLocation : thisStandELocations) {
|
||||
if (usedELocationIds.contains(eTagLocation.getELocationId())) {
|
||||
continue;
|
||||
}
|
||||
remainELocationIds.add(eTagLocation.getELocationId());
|
||||
}
|
||||
if (remainELocationIds.isEmpty()) {
|
||||
// 当前站台没有可用电子标签库位分配了,跳过
|
||||
List<ELocationConfig> oldELocationConfigs = eLocationConfigService.list();
|
||||
if (oldELocationConfigs != null && !oldELocationConfigs.isEmpty()) {
|
||||
logger.info("存在旧的标签配置,不执行分配。");
|
||||
return;
|
||||
}
|
||||
// 然后获取大盒子-订单的map
|
||||
Map<String, List<WorkFlow>> workFlowsByBigBoxMap = new HashMap<>();
|
||||
// 获取工站配置
|
||||
LambdaQueryWrapper<WorkStationConfig> wsConfigQueryWrapper = new LambdaQueryWrapper<>();
|
||||
if (currentWorkType == 1) {
|
||||
// 当前是装载机工作,装载机要区分站台
|
||||
wsConfigQueryWrapper.eq(WorkStationConfig::getWorkStation, workStation)
|
||||
wsConfigQueryWrapper
|
||||
.eq(WorkStationConfig::getModel, "MWL");
|
||||
} else {
|
||||
// 当前是平地机工作
|
||||
wsConfigQueryWrapper.ne(WorkStationConfig::getModel, "MWL");
|
||||
}
|
||||
List<WorkStationConfig> workStationConfigs = workStationConfigService.list(wsConfigQueryWrapper);
|
||||
// 然后获取大盒子-订单的map
|
||||
Map<String, List<WorkFlow>> workFlowsByBigBoxMap = new HashMap<>();
|
||||
// 根据小盒子号生成map
|
||||
Map<String, String> smallBoxToBigBoxConfigMap = workStationConfigs.stream().collect(Collectors.toMap(WorkStationConfig::getSmallBox, WorkStationConfig::getBigBox));
|
||||
for (WorkFlow workFlow : needDistributeWorks) {
|
||||
|
|
@ -797,59 +772,60 @@ public class WorkServiceImplements implements IWorkService {
|
|||
}
|
||||
}
|
||||
}
|
||||
// 根据订单量,对大盒子号进行一个排序
|
||||
List<String> bigBoxes = workFlowsByBigBoxMap.keySet().stream().sorted(Comparator.comparingInt(o -> workFlowsByBigBoxMap.get(o).size())).toList();
|
||||
// 对已有的大盒子进行一个配置
|
||||
Map<String, String> stationOfBigBoxMap = new HashMap<>();
|
||||
// 针对此站台的料盒号(工单@工作中心)生成一个map
|
||||
Map<String, String> eLocationIdOfBoxMap = new HashMap<>();
|
||||
for (ELocationConfig oldELocationConfig : allELocationConfigs) {
|
||||
// 默认大盒子 = 小盒子
|
||||
String bigBox = oldELocationConfig.getWorkCenter();
|
||||
if (smallBoxToBigBoxConfigMap.containsKey(oldELocationConfig.getWorkCenter())) {
|
||||
// 设置为实际的大盒子
|
||||
bigBox = smallBoxToBigBoxConfigMap.get(oldELocationConfig.getWorkCenter());
|
||||
// 生成每个大盒子的物料种类map
|
||||
Map<String, Integer> bigBoxToGoodsTypeQtyMap = new HashMap<>();
|
||||
for (String bigBox : workFlowsByBigBoxMap.keySet()) {
|
||||
List<WorkFlow> thisBoxWorkFlows = workFlowsByBigBoxMap.get(bigBox);
|
||||
int goodsTypeQty = thisBoxWorkFlows.stream().map(WorkFlow::getGoodsId).distinct().toList().size();
|
||||
bigBoxToGoodsTypeQtyMap.put(bigBox, goodsTypeQty);
|
||||
}
|
||||
// 判断这个大盒子是否分配了站台
|
||||
if (!stationOfBigBoxMap.containsKey(bigBox)) {
|
||||
stationOfBigBoxMap.put(bigBox, oldELocationConfig.getWorkStation());
|
||||
// 根据物料种类数量对大盒子进行排序
|
||||
List<String> sortedBoxedByGoodsTypeQty = bigBoxToGoodsTypeQtyMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).map(Map.Entry::getKey).toList();
|
||||
// 每个站台包含的物料种类数量
|
||||
Map<String, List<String>> stationToGoodsTypeQtyMap = new HashMap<>();
|
||||
// 每个站台分配的电子标签
|
||||
Map<String, List<ELocationConfig>> stationToELocationConfigsMap = new HashMap<>();
|
||||
// 每个站台的物料需求
|
||||
Map<String, List<GoodsToStation>> stationToGoodsToStationsMap = new HashMap<>();
|
||||
// 每个站台的剩余电子标签
|
||||
Map<String, List<String>> stationToRemainELocationMap = new HashMap<>();
|
||||
for (String standId : standIds) {
|
||||
List<ETagLocation> thisStandELocations = allELocations.stream().filter(eTagLocation -> eTagLocation.getWorkStation().equals(standId)).toList();
|
||||
if (thisStandELocations.isEmpty()) {
|
||||
// 当前站台没有可用电子标签位
|
||||
stationToRemainELocationMap.put(standId, Collections.emptyList());
|
||||
continue;
|
||||
}
|
||||
// 更新料盒号-电子标签库位Map
|
||||
if (!eLocationIdOfBoxMap.containsKey(oldELocationConfig.getOrderBoxNo())) {
|
||||
eLocationIdOfBoxMap.put(oldELocationConfig.getOrderBoxNo(), oldELocationConfig.getELocationId());
|
||||
// 排序
|
||||
List<String> thisStandELocationIds = thisStandELocations.stream().sorted(Comparator.comparingInt(ETagLocation::getSequenceId)).map(ETagLocation::getELocationId).toList();
|
||||
stationToRemainELocationMap.put(standId, thisStandELocationIds);
|
||||
// 每个站台物料分配种类
|
||||
stationToGoodsTypeQtyMap.put(standId, new ArrayList<>());
|
||||
}
|
||||
}
|
||||
// 开始分配电子标签库位
|
||||
List<WorkFlow> thisTimeDistributeWorkFlows = new ArrayList<>();
|
||||
// 决定每个大盒子的站台分配
|
||||
Map<String, String> 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<KateDBS> kateDBSS = kateDBSService.list(new LambdaQueryWrapper<KateDBS>()
|
||||
.in(KateDBS::getWorkOrder, needDistributeWorks.stream().map(WorkFlow::getWorkOrder).distinct().toList()));
|
||||
// 将这个工单的顺序号进行一个map
|
||||
Map<String, Integer> 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<WorkFlow> thisBigBoxWorks = workFlowsByBigBoxMap.get(bigBox);
|
||||
if (thisBigBoxWorks.isEmpty()) {
|
||||
for (String bigBox : sortedBoxedByGoodsTypeQty) {
|
||||
// 找出这个站台下的工作流
|
||||
List<WorkFlow> thisBoxWorkFlows = workFlowsByBigBoxMap.get(bigBox);
|
||||
if (thisBoxWorkFlows.isEmpty()) {
|
||||
// 当前大盒子没有工作流,跳过
|
||||
continue;
|
||||
}
|
||||
// List<WorkFlow> thisBigBoxSortedWorks = thisBigBoxWorks.stream()
|
||||
// .sorted(Comparator.comparing(WorkFlow::getWorkCenter))
|
||||
// .sorted(Comparator.comparingInt(workFlow -> workOrderToSequenceMap.get(workFlow.getWorkOrder())))
|
||||
// .toList();
|
||||
// 获取这个大盒子下面的物料列表
|
||||
List<String> goodsIds = thisBoxWorkFlows.stream().map(WorkFlow::getGoodsId).distinct().toList();
|
||||
// 未分配的工作流,按照boxNo分组
|
||||
Map<String, List<WorkFlow>> 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<WorkFlow> thisBoxNotDistributeYetWorks = new ArrayList<>(notDistributeYetWorksByBoxMap.get(boxNo));
|
||||
thisBoxNotDistributeYetWorks.add(workFlow);
|
||||
|
|
@ -858,131 +834,166 @@ public class WorkServiceImplements implements IWorkService {
|
|||
notDistributeYetWorksByBoxMap.put(boxNo, List.of(workFlow));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (notDistributeYetWorksByBoxMap.isEmpty()) {
|
||||
// 当前大盒子全部分配完毕
|
||||
continue;
|
||||
}
|
||||
// 判断电子标签库位是否足够
|
||||
if (notDistributeYetWorksByBoxMap.size() > remainELocationIds.size()) {
|
||||
// 这个大盒子的位置不够了,整个大盒子都不分配。
|
||||
String targetStandId = "";
|
||||
if (currentWorkType == 1) {
|
||||
// 装载机使用固定配置
|
||||
List<WorkStationConfig> 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<String> thisStandRemainELocationIds = new ArrayList<>(stationToRemainELocationMap.get(targetStandId));
|
||||
if (thisStandRemainELocationIds.size() < notDistributeYetWorksByBoxMap.size()) {
|
||||
// 标签不够,此处的判断主要用于装载机
|
||||
continue;
|
||||
}
|
||||
// 排序后的key
|
||||
List<String> sortedKeyString = notDistributeYetWorksByBoxMap.keySet().stream()
|
||||
.sorted(Comparator.comparing(o -> workOrderToSequenceMap.get(o.split("@")[0])))
|
||||
.sorted(Comparator.comparing(o -> o.split("@")[1]))
|
||||
.toList();
|
||||
// 本次生成的电子标签配置
|
||||
List<ELocationConfig> 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<GoodsToStation> oldGoodsStations = goodsToStationService.list(
|
||||
new LambdaQueryWrapper<GoodsToStation>().eq(GoodsToStation::getWorkStation, workStation)
|
||||
);
|
||||
List<GoodsToStation> oldGoodsStations = goodsToStationService.list();
|
||||
if (oldGoodsStations != null && !oldGoodsStations.isEmpty()) {
|
||||
// 按照站台分组
|
||||
stationToGoodsToStationsMap = oldGoodsStations.stream().collect(Collectors.groupingBy(GoodsToStation::getWorkStation));
|
||||
}
|
||||
// 处理物料的需求分配
|
||||
List<WorkFlow> thisTimeDistributeWorkFlows = new ArrayList<>();
|
||||
for (String bigBox : bigBoxToStandIdMap.keySet()) {
|
||||
String thisStandId = bigBoxToStandIdMap.get(bigBox);
|
||||
// 当前站台的旧的goodsToStation
|
||||
List<GoodsToStation> thisStandOldGoodsToStationList = stationToGoodsToStationsMap.getOrDefault(thisStandId, new ArrayList<>());
|
||||
// 根据料号Map一下
|
||||
Map<String, GoodsToStation> oldGoodsStationsMap = oldGoodsStations.stream().collect(Collectors.toMap(GoodsToStation::getGoodsId, goodsToStation -> goodsToStation));
|
||||
// 新增
|
||||
Map<String, GoodsToStation> newGoodsToStationMap = new HashMap<>();
|
||||
for (WorkFlow workFlow : thisTimeDistributeWorkFlows) {
|
||||
if (newGoodsToStationMap.containsKey(workFlow.getGoodsId())) {
|
||||
Map<String, GoodsToStation> oldGoodsStationsMap = thisStandOldGoodsToStationList.stream().collect(Collectors.toMap(GoodsToStation::getGoodsId, goodsToStation -> goodsToStation));
|
||||
List<WorkFlow> thisBigBoxWorks = workFlowsByBigBoxMap.get(bigBox);
|
||||
for (WorkFlow workFlow : thisBigBoxWorks) {
|
||||
if (oldGoodsStationsMap.containsKey(workFlow.getGoodsId())) {
|
||||
// 更新totalNum,并把状态改成分配中
|
||||
GoodsToStation goodsToStation = newGoodsToStationMap.get(workFlow.getGoodsId());
|
||||
GoodsToStation goodsToStation = oldGoodsStationsMap.get(workFlow.getGoodsId());
|
||||
goodsToStation.setTotalNum(goodsToStation.getTotalNum().add(workFlow.getNeedNum()));
|
||||
newGoodsToStationMap.replace(workFlow.getGoodsId(), goodsToStation);
|
||||
oldGoodsStationsMap.replace(workFlow.getGoodsId(), goodsToStation);
|
||||
} else {
|
||||
GoodsToStation newGoodsToStation = new GoodsToStation();
|
||||
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);
|
||||
} else {
|
||||
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<String> flowIds = thisTimeDistributeWorkFlows.stream().map(WorkFlow::getWorkFlowId).toList();
|
||||
if (!flowIds.isEmpty()) {
|
||||
workFlowService.update(new LambdaUpdateWrapper<WorkFlow>()
|
||||
.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<WorkFlow> filterWorkFlow(List<WorkFlow> workFlows, String workStation, int machineType, int workStatus, int flag) {
|
||||
Stream<WorkFlow> stream = workFlows.stream();
|
||||
|
||||
if (StringUtils.isNotEmpty(workStation)) {
|
||||
stream = stream.filter(workFlow -> workFlow.getWorkStation().equals(workStation));
|
||||
private String getMinGapStandToAvgAfterAddABox(Map<String, List<String>> goodsIdsToStandMap, List<String> goodsIdsThisTime, int avgQty, int needELocationQty, Map<String, List<String>> stationToRemainELocationMap) {
|
||||
int minGap = Integer.MAX_VALUE;
|
||||
String targetStandId = "";
|
||||
// 这里对站台好排序一下,从前到后
|
||||
List<String> sortedStandIds = goodsIdsToStandMap.keySet().stream().sorted(Comparator.comparing(o -> o)).toList();
|
||||
// 筛选新增加的物料数量
|
||||
List<String> thisTimeAddGoodsIds = new ArrayList<>();
|
||||
for (String standId : sortedStandIds) {
|
||||
if (needELocationQty > stationToRemainELocationMap.get(standId).size()) {
|
||||
// 标签个数不够
|
||||
continue;
|
||||
}
|
||||
|
||||
if (machineType > 0) {
|
||||
stream = stream.filter(workFlow -> workFlow.getMachineType().equals(machineType));
|
||||
List<String> thisStandGoodsId = goodsIdsToStandMap.get(standId);
|
||||
// 筛选新增加的物料数量
|
||||
List<String> thisTimeAddGoodsIdsOfThisStand = new ArrayList<>();
|
||||
for (String goodsId : goodsIdsThisTime) {
|
||||
if (thisStandGoodsId.stream().filter(goodsId1 -> goodsId1.equals(goodsId)).toList().isEmpty()) thisTimeAddGoodsIdsOfThisStand.add(goodsId);
|
||||
}
|
||||
|
||||
if (workStatus != 0) {
|
||||
if (flag == 0) {
|
||||
stream = stream.filter(workFlow -> workFlow.getWorkStatus().equals(workStatus));
|
||||
} else {
|
||||
stream = stream.filter(workFlow -> !workFlow.getWorkStatus().equals(workStatus));
|
||||
// 判断偏差值
|
||||
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<String> thisStandGoodsId = goodsIdsToStandMap.get(targetStandId);
|
||||
thisStandGoodsId.addAll(thisTimeAddGoodsIds);
|
||||
goodsIdsToStandMap.put(targetStandId, thisStandGoodsId);
|
||||
}
|
||||
return targetStandId;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user