diff --git a/src/main/java/com/wms/controller/JobComponent.java b/src/main/java/com/wms/controller/JobComponent.java index 0d2429e..8962983 100644 --- a/src/main/java/com/wms/controller/JobComponent.java +++ b/src/main/java/com/wms/controller/JobComponent.java @@ -141,7 +141,7 @@ public class JobComponent { * 每2秒执行一次 */ // @Scheduled(fixedDelay = 2000) - @Async("myThreadPool") +// @Async("myThreadPool") @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) public void solveDuplicateTask() { String sendTask = configMap.get(ConfigMapKeyEnum.SEND_TASK.getConfigKey()); diff --git a/src/main/java/com/wms/controller/StandController.java b/src/main/java/com/wms/controller/StandController.java index edeed26..d844a0b 100644 --- a/src/main/java/com/wms/controller/StandController.java +++ b/src/main/java/com/wms/controller/StandController.java @@ -111,6 +111,7 @@ public class StandController { .set(request.getStandStatus() != null, Stand::getStandStatus, request.getStandStatus()) .set(request.getLastUseTime() != null, Stand::getLastUseTime, request.getLastUseTime()) .set(request.getPickVehicleCount() != null, Stand::getPickVehicleCount, request.getPickVehicleCount()) + .set(request.getAllowNoPlan() != null, Stand::getAllowNoPlan, request.getAllowNoPlan()) .eq(Stand::getStandId, request.getStandId()); if (standService.update(lambdaUpdateWrapper)) { logger.info("更新站台信息成功。"); diff --git a/src/main/java/com/wms/controller/TaskController.java b/src/main/java/com/wms/controller/TaskController.java index 055187e..f441f83 100644 --- a/src/main/java/com/wms/controller/TaskController.java +++ b/src/main/java/com/wms/controller/TaskController.java @@ -163,6 +163,7 @@ public class TaskController { */ private final IWorkService workService; private final WorkFlowLastService workFlowLastService;// 服务 + private final StandStackerTaskService standStackerTaskService;// 特殊服务 /** * 接收入库任务请求 @@ -487,6 +488,12 @@ public class TaskController { .set(PickTask::getPickStatus, PickTaskStatusEnum.NEW.getCode()) .eq(PickTask::getVehicleId, outTask.getVehicleId()) .eq(PickTask::getPickStatus, PickTaskStatusEnum.TEMP.getCode())); + // 设置特殊 + standStackerTaskService.update(new LambdaUpdateWrapper() + .set(StandStackerTask::getTaskStatus, 1) + .set(StandStackerTask::getFinishTime, LocalDateTime.now()) + .eq(StandStackerTask::getVehicleId, outTask.getVehicleId()) + .ne(StandStackerTask::getTaskStatus, 1)); } else {// 代表整出 // 删除当前载具上所有库存 List removeStocks = stockService.list(new LambdaQueryWrapper().eq(Stock::getVehicleId, outTask.getVehicleId())); 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 b921f2d..d167ee0 100644 --- a/src/main/java/com/wms/entity/app/request/StandQuery.java +++ b/src/main/java/com/wms/entity/app/request/StandQuery.java @@ -94,4 +94,9 @@ public class StandQuery extends PageQuery { */ @JsonProperty("pickVehicleCount") private Integer pickVehicleCount; + /** + * 是否允许非计划 + */ + @JsonProperty("allowNoPlan") + private Integer allowNoPlan; } 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 7569247..df5f8b0 100644 --- a/src/main/java/com/wms/entity/app/vo/StandVo.java +++ b/src/main/java/com/wms/entity/app/vo/StandVo.java @@ -92,4 +92,9 @@ public class StandVo { */ @JsonProperty("pickVehicleCount") private Integer pickVehicleCount; + /** + * 是否允许非计划 + */ + @JsonProperty("allowNoPlan") + private Integer allowNoPlan; } diff --git a/src/main/java/com/wms/entity/table/InventoryHistory.java b/src/main/java/com/wms/entity/table/InventoryHistory.java index 878dfaa..6fc3a3e 100644 --- a/src/main/java/com/wms/entity/table/InventoryHistory.java +++ b/src/main/java/com/wms/entity/table/InventoryHistory.java @@ -8,21 +8,50 @@ import lombok.Data; import java.math.BigDecimal; import java.time.LocalDateTime; +/** + * 盘点记录 + */ @Data @TableName(value = "tbl_app_inventory_history", autoResultMap = true) public class InventoryHistory { + /** + * 盘点id + */ @TableId("inventory_id") private String inventoryId; + /** + * 料号 + */ @TableField("goods_id") private String goodsId; + /** + * 库存数量 + */ @TableField("stock_num") private BigDecimal stockNum; + /** + * 实际数量 + */ @TableField("real_num") private BigDecimal realNum; + /** + * 盘点状态 + */ @TableField("inventory_status") private Integer inventoryStatus; + /** + * 盘点用户 + */ @TableField("inventory_user") private String inventoryUser; + /** + * 盘点日期 + */ @TableField("inventory_date") private LocalDateTime inventoryDate; + /** + * 箱号 + */ + @TableField("vehicle_id") + private String vehicleId; } diff --git a/src/main/java/com/wms/entity/table/InventoryList.java b/src/main/java/com/wms/entity/table/InventoryList.java index 694ec9b..e04ed6d 100644 --- a/src/main/java/com/wms/entity/table/InventoryList.java +++ b/src/main/java/com/wms/entity/table/InventoryList.java @@ -50,8 +50,8 @@ public class InventoryList { @TableField("inventory_date") private LocalDateTime inventoryDate; /** - * 清单id + * 箱号 */ - @TableField("list_id") - private String listId; + @TableField("vehicle_id") + private String vehicleId; } diff --git a/src/main/java/com/wms/entity/table/StandStackerTask.java b/src/main/java/com/wms/entity/table/StandStackerTask.java new file mode 100644 index 0000000..df6c455 --- /dev/null +++ b/src/main/java/com/wms/entity/table/StandStackerTask.java @@ -0,0 +1,59 @@ +package com.wms.entity.table; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +@TableName(value = "tbl_app_stand_stacker_task", autoResultMap = true) +public class StandStackerTask { + /** + * 料箱号 + */ + @TableId("vehicle_id") + private String vehicleId; + /** + * 堆垛机号 + */ + @TableField("stacker_id") + private Integer stackerId; + /** + * 站台号 + */ + @TableField("stand_id") + private String standId; + /** + * 任务类型 + * 1:定额 + * 2:超额 + */ + @TableField("task_type") + private Integer taskType; + /** + * 上次数量类型 + * 1:去站台最少 + * 2:去站台最多 + */ + @TableField("last_qty_type") + private Integer lastQtyType; + /** + * 创建时间 + */ + @TableField("create_time") + private LocalDateTime createTime; + /** + * 任务状态 + * 0:初始 + * 1:完成 + */ + @TableField("task_status") + private Integer taskStatus; + /** + * 完成时间 + */ + @TableField("finish_time") + private LocalDateTime finishTime; +} diff --git a/src/main/java/com/wms/entity/table/StandStackerTaskBak.java b/src/main/java/com/wms/entity/table/StandStackerTaskBak.java new file mode 100644 index 0000000..9c5291f --- /dev/null +++ b/src/main/java/com/wms/entity/table/StandStackerTaskBak.java @@ -0,0 +1,64 @@ +package com.wms.entity.table; + +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +@TableName(value = "tbl_app_stand_stacker_task_bak", autoResultMap = true) +public class StandStackerTaskBak { + /** + * 主键 + */ + @TableId("record_id") + private String recordId; + /** + * 料箱号 + */ + @TableField("vehicle_id") + private String vehicleId; + /** + * 堆垛机号 + */ + @TableField("stacker_id") + private Integer stackerId; + /** + * 站台号 + */ + @TableField("stand_id") + private String standId; + /** + * 任务类型 + * 1:定额 + * 2:超额 + */ + @TableField("task_type") + private Integer taskType; + /** + * 上次数量类型 + * 1:去站台最少 + * 2:去站台最多 + */ + @TableField("last_qty_type") + private Integer lastQtyType; + /** + * 创建时间 + */ + @TableField("create_time") + private LocalDateTime createTime; + /** + * 任务状态 + * 0:初始 + * 1:完成 + */ + @TableField("task_status") + private Integer taskStatus; + /** + * 完成时间 + */ + @TableField("finish_time") + private LocalDateTime finishTime; +} diff --git a/src/main/java/com/wms/mapper/StandStackerTaskBakMapper.java b/src/main/java/com/wms/mapper/StandStackerTaskBakMapper.java new file mode 100644 index 0000000..d5a39bf --- /dev/null +++ b/src/main/java/com/wms/mapper/StandStackerTaskBakMapper.java @@ -0,0 +1,11 @@ +package com.wms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.wms.entity.table.StandStackerTask; +import com.wms.entity.table.StandStackerTaskBak; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface StandStackerTaskBakMapper extends BaseMapper { + +} diff --git a/src/main/java/com/wms/mapper/StandStackerTaskMapper.java b/src/main/java/com/wms/mapper/StandStackerTaskMapper.java new file mode 100644 index 0000000..e8e2681 --- /dev/null +++ b/src/main/java/com/wms/mapper/StandStackerTaskMapper.java @@ -0,0 +1,10 @@ +package com.wms.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.wms.entity.table.StandStackerTask; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface StandStackerTaskMapper extends BaseMapper { + +} diff --git a/src/main/java/com/wms/service/StandStackerTaskBakService.java b/src/main/java/com/wms/service/StandStackerTaskBakService.java new file mode 100644 index 0000000..58db446 --- /dev/null +++ b/src/main/java/com/wms/service/StandStackerTaskBakService.java @@ -0,0 +1,8 @@ +package com.wms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.wms.entity.table.StandStackerTask; +import com.wms.entity.table.StandStackerTaskBak; + +public interface StandStackerTaskBakService extends IService { +} diff --git a/src/main/java/com/wms/service/StandStackerTaskService.java b/src/main/java/com/wms/service/StandStackerTaskService.java new file mode 100644 index 0000000..75f215e --- /dev/null +++ b/src/main/java/com/wms/service/StandStackerTaskService.java @@ -0,0 +1,7 @@ +package com.wms.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.wms.entity.table.StandStackerTask; + +public interface StandStackerTaskService extends IService { +} diff --git a/src/main/java/com/wms/service/business/serviceImplements/WmsJobServiceImplements.java b/src/main/java/com/wms/service/business/serviceImplements/WmsJobServiceImplements.java index f3ff0a4..34dc55f 100644 --- a/src/main/java/com/wms/service/business/serviceImplements/WmsJobServiceImplements.java +++ b/src/main/java/com/wms/service/business/serviceImplements/WmsJobServiceImplements.java @@ -1,5 +1,6 @@ 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; @@ -25,6 +26,7 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport; import java.time.LocalDateTime; import java.util.*; +import java.util.stream.Collectors; import static com.wms.config.InitLocalConfig.configMap; import static com.wms.config.InitLocalConfig.instantLocationMap; @@ -42,6 +44,8 @@ public class WmsJobServiceImplements implements IWmsJobService { private final PickTaskService pickTaskService;// 拣选任务服务 private final OutsideVehiclesService outsideVehiclesService;// 流转中箱子服务 private final StandService standService;// 站台服务 + private final StandStackerTaskService standStackerTaskService;// 特殊服务 + private final StandStackerTaskBakService standStackerTaskBakService;// 特殊记录服务 /** * 发送正常的任务 @@ -157,357 +161,357 @@ public class WmsJobServiceImplements implements IWmsJobService { * 发送PickOut任务 * @throws Exception 异常 */ - @Override - public void sendPickOutTasks() throws Exception { - try { - // 检索任务表---新建未下发的任务 - LambdaQueryWrapper waitForDistributeTaskQuery = new LambdaQueryWrapper() - .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode()) - .eq(Task::getTaskType, TaskType.OUT.getCode()) - .eq(Task::getTaskPriority, 1); - List allTasks = taskService.list(waitForDistributeTaskQuery); - if (!allTasks.isEmpty()) { - String max_vehicle_nums = configMap.get(ConfigMapKeyEnum.MAX_VEHICLE_NUMS.getConfigKey()); - String max_wcs_accept_nums = configMap.get(ConfigMapKeyEnum.MAX_WCS_ACCEPT_NUMS.getConfigKey()); - String max_stand_vehicle_nums = configMap.get(ConfigMapKeyEnum.MAX_STAND_VEHICLE_NUMS.getConfigKey()); - if (StringUtils.isEmpty(max_vehicle_nums) || StringUtils.isEmpty(max_wcs_accept_nums) || StringUtils.isEmpty(max_stand_vehicle_nums)) { - logger.error("配置未生成"); - return; - } - int maxVehicleNums = Integer.parseInt(max_vehicle_nums);// 线体最大箱子数量 - int maxWcsAcceptNums = Integer.parseInt(max_wcs_accept_nums);// wcs最大一次性可接受任务数量 - int maxStandVehicleNums = Integer.parseInt(max_stand_vehicle_nums);// 每个站台最大箱子数量 - List outsideVehicles = outsideVehiclesService.selectDistinctVehicles(); - if (outsideVehicles == null || outsideVehicles.isEmpty()) { - outsideVehicles = Collections.emptyList(); - } - int remainVehicleNums = maxVehicleNums - outsideVehicles.size();// 线体剩余箱子数量 - if (remainVehicleNums <= 0) { - return; - } - - // 需要发送给wcs的任务列表 - List request = new ArrayList<>(); - // 已经下发的任务组列表 - List taskGroupIds = new ArrayList<>(); - // 本次生成的箱子 - List pickVehicleIds = new ArrayList<>(); - // 本次跳过的箱子 - List skipVehicleIds = new ArrayList<>(); - // 查找所有站台拣选任务 - List standPickTasks = pickTaskService.list(); - // 生成一个Map,计算每个站台已经出库的拣选任务 - Map outPickTaskMap = new HashMap<>(); - Map updatedOutPickTaskMap = new HashMap<>(); - // 轮询工作站台,判断是否需要下发任务 - List stands = standService.list(new LambdaQueryWrapper() - .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0) - .eq(Stand::getStandType, 2)); - for (Stand workStation : stands) { - outPickTaskMap.put(workStation.getStandId(), workStation.getPickVehicleCount()); - updatedOutPickTaskMap.put(workStation.getStandId(), workStation.getPickVehicleCount()); - } - // 轮询堆垛机状态 - List stackerList = standService.list(new LambdaQueryWrapper() - .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0) - .eq(Stand::getStandType, 3)); - List stackRunningTasks = taskService.list(new LambdaQueryWrapper() - .eq(Task::getTaskType, TaskType.OUT.getCode()) - .and(wrapper -> wrapper.eq(Task::getTaskStatus, WmsTaskStatus.WAIT.getCode()) - .or().eq(Task::getTaskStatus, WmsTaskStatus.RUN.getCode()))); - Map runningTaskNumToEquipmentMap = new HashMap<>(); - for (Stand stacker : stackerList) { - // 找这台堆垛机正在执行的拣选出库任务数量 - runningTaskNumToEquipmentMap.put(stacker.getEquipmentId(), 0); - } - // 生成堆垛机可用列表 - for (Task tempStackRunningTask : stackRunningTasks) { - if (instantLocationMap.containsKey(tempStackRunningTask.getOrigin())) { - int key = instantLocationMap.get(tempStackRunningTask.getOrigin()).getEquipmentId(); - if (runningTaskNumToEquipmentMap.isEmpty()) { - // 没有可用堆垛机 - break; - } - if (runningTaskNumToEquipmentMap.containsKey(key)) { - if (runningTaskNumToEquipmentMap.get(key) >= 3) { - runningTaskNumToEquipmentMap.remove(key); - } else { - runningTaskNumToEquipmentMap.replace(key, runningTaskNumToEquipmentMap.get(key) + 1); - } - } - } - } - if (runningTaskNumToEquipmentMap.isEmpty()) { - // 没有可用堆垛机 - return; - } - // 还有可用堆垛机 - while(!runningTaskNumToEquipmentMap.isEmpty()) { - if (request.size() >= maxWcsAcceptNums || remainVehicleNums <= 0) { - // 超过wcs一次可接受数量 - break; - } - if (outPickTaskMap.isEmpty()) { - // 没有站台可以使用 - break; - } - // 先找出目前数量最少的站台 - String standId = outPickTaskMap.entrySet().stream() - .min(Comparator.comparingInt(Map.Entry::getValue)) - .map(Map.Entry::getKey) - .orElse(""); - List vehicleIds; - if (StringUtils.isNotEmpty(standId)) { - // 如果这个站台箱子数量超过最大每个站台的箱子数量,则跳过 - if (outPickTaskMap.get(standId) >= maxStandVehicleNums) { - outPickTaskMap.remove(standId); - continue; - } - // 查找这个站台未下发的料箱 - vehicleIds = standPickTasks.stream() - .filter(pickTask -> pickTask.getStandId().equals(standId) && pickTask.getPickStatus().equals(PickTaskStatusEnum.TEMP.getCode()) - && !pickVehicleIds.contains(pickTask.getVehicleId()) - && !skipVehicleIds.contains(pickTask.getVehicleId())) - .map(PickTask::getVehicleId) - .distinct() - .toList(); - if (vehicleIds.isEmpty()) { - outPickTaskMap.remove(standId); - continue; - } - } else { - vehicleIds = standPickTasks.stream() - .filter(pickTask -> pickTask.getPickStatus().equals(PickTaskStatusEnum.TEMP.getCode()) - && !pickVehicleIds.contains(pickTask.getVehicleId()) - && !skipVehicleIds.contains(pickTask.getVehicleId())) - .map(PickTask::getVehicleId) - .distinct() - .toList(); - if (vehicleIds.isEmpty()) { - break; - } - } - // 生成箱子-站台数量的Map - Map vehicleStandsMap = new HashMap<>(); - standPickTasks.forEach(pickTask -> { - if (vehicleIds.contains(pickTask.getVehicleId())) { - vehicleStandsMap.put(pickTask.getVehicleId(), - vehicleStandsMap.getOrDefault(pickTask.getVehicleId(), 0) + 1); - } - }); - // 最多使用的箱子 - String maxVehicleId = vehicleStandsMap.entrySet().stream() - .max(Comparator.comparingInt(Map.Entry::getValue)) - .map(Map.Entry::getKey) - .orElse(""); - if (!StringUtils.isEmpty(maxVehicleId)) { - // 找到这个箱子的任务 - List outPickTasks = allTasks.stream().filter(task -> task.getVehicleId().equals(maxVehicleId) && !pickVehicleIds.contains(task.getVehicleId()) - && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())).toList(); - if (!outPickTasks.isEmpty()) { - // 更新每个站台的拣选箱数量 - List maxStandIds = standPickTasks.stream() - .filter(pickTask -> pickTask.getVehicleId().equals(maxVehicleId)) - .map(PickTask::getStandId) - .distinct() - .toList(); - // 给当前设备号+1 - int equipmentId = instantLocationMap.get(outPickTasks.get(0).getOrigin()).getEquipmentId(); - if (runningTaskNumToEquipmentMap.containsKey(equipmentId)) { - boolean flag = false; - for (Task task : outPickTasks) { - if (taskGroupIds.contains(task.getTaskGroup())) { - // 该任务组已经下发 - continue; - } - if (StringUtils.isNotEmpty(task.getPreTask())) {// 当前任务具有前置任务 - // 查询一下前置的任务有没有存在,存在则不下发 - if (taskService.exists(new LambdaQueryWrapper().eq(Task::getTaskId, task.getPreTask()))) { - continue; - } - } - // 创建发送的任务 - WcsTaskRequest tempTask = new WcsTaskRequest(); - tempTask.setTaskId(task.getTaskGroup()); - tempTask.setTaskType(task.getTaskType()); - tempTask.setOrigin(task.getOrigin()); - tempTask.setDestination(task.getDestination()); - tempTask.setVehicleNo(task.getVehicleId()); - tempTask.setVehicleSize(task.getVehicleSize()); - tempTask.setWeight(task.getWeight()); - tempTask.setPriority(task.getTaskPriority()); - request.add(tempTask); - // 已经发送过的任务组 - taskGroupIds.add(task.getTaskGroup()); - flag = true; - } - if (flag) { - if (!maxStandIds.isEmpty()) { - maxStandIds.forEach(tempStandId -> { - outPickTaskMap.put(tempStandId, outPickTaskMap.getOrDefault(tempStandId, 0) + 1); - updatedOutPickTaskMap.put(tempStandId, updatedOutPickTaskMap.getOrDefault(tempStandId, 0) + 1); - }); - } - runningTaskNumToEquipmentMap.replace(equipmentId, runningTaskNumToEquipmentMap.get(equipmentId) + 1); - // 已经发送过的vehicleId - pickVehicleIds.add(maxVehicleId); - vehicleStandsMap.remove(maxVehicleId); - // 剩余线体可继续出库料箱数量 - remainVehicleNums--; - } - } else { - if (!skipVehicleIds.contains(maxVehicleId)) { - skipVehicleIds.add(maxVehicleId); - } - } - } else { - if (!skipVehicleIds.contains(maxVehicleId)) { - skipVehicleIds.add(maxVehicleId); - } - } - } - // 最少使用的箱子 - String minVehicleId = vehicleStandsMap.entrySet().stream() - .min(Comparator.comparingInt(Map.Entry::getValue)) - .map(Map.Entry::getKey) - .orElse(""); - if (!StringUtils.isEmpty(minVehicleId)) { - // 找到这个箱子的任务 - List outPickTasks = allTasks.stream().filter(task -> task.getVehicleId().equals(minVehicleId) && !pickVehicleIds.contains(task.getVehicleId()) - && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())).toList(); - if (!outPickTasks.isEmpty()) { - // 更新每个站台的拣选箱数量 - List minStandIds = standPickTasks.stream() - .filter(pickTask -> pickTask.getVehicleId().equals(minVehicleId)) - .map(PickTask::getStandId) - .distinct() - .toList(); - // 给当前设备号+1 - int equipmentId = instantLocationMap.get(outPickTasks.get(0).getOrigin()).getEquipmentId(); - if (runningTaskNumToEquipmentMap.containsKey(equipmentId)) { - boolean flag = false; - for (Task task : outPickTasks) { - if (taskGroupIds.contains(task.getTaskGroup())) { - // 该任务组已经下发 - continue; - } - if (StringUtils.isNotEmpty(task.getPreTask())) {// 当前任务具有前置任务 - // 查询一下前置的任务有没有存在,存在则不下发 - if (taskService.exists(new LambdaQueryWrapper().eq(Task::getTaskId, task.getPreTask()))) { - continue; - } - } - // 创建发送的任务 - WcsTaskRequest tempTask = new WcsTaskRequest(); - tempTask.setTaskId(task.getTaskGroup()); - tempTask.setTaskType(task.getTaskType()); - tempTask.setOrigin(task.getOrigin()); - tempTask.setDestination(task.getDestination()); - tempTask.setVehicleNo(task.getVehicleId()); - tempTask.setVehicleSize(task.getVehicleSize()); - tempTask.setWeight(task.getWeight()); - tempTask.setPriority(task.getTaskPriority()); - request.add(tempTask); - // 已经发送过的任务组 - taskGroupIds.add(task.getTaskGroup()); - flag = true; - } - if (flag) { - if (!minStandIds.isEmpty()) { - minStandIds.forEach(tempStandId -> { - outPickTaskMap.put(tempStandId, outPickTaskMap.getOrDefault(tempStandId, 0) + 1); - updatedOutPickTaskMap.put(tempStandId, updatedOutPickTaskMap.getOrDefault(tempStandId, 0) + 1); - }); - } - runningTaskNumToEquipmentMap.replace(equipmentId, runningTaskNumToEquipmentMap.get(equipmentId) + 1); - // 已经发送过的vehicleId - pickVehicleIds.add(minVehicleId); - vehicleStandsMap.remove(minVehicleId); - // 剩余线体可继续出库料箱数量 - remainVehicleNums--; - } - } else { - if (!skipVehicleIds.contains(minVehicleId)) { - skipVehicleIds.add(minVehicleId); - } - } - } else { - if (!skipVehicleIds.contains(minVehicleId)) { - skipVehicleIds.add(minVehicleId); - } - } - } - List removeKeys = new ArrayList<>(runningTaskNumToEquipmentMap.keySet().stream().toList()); - for (int equipmentId : removeKeys) { - // 剩余任务有没有这台堆垛机的 - List remainTasks = allTasks.stream().filter(task -> !skipVehicleIds.contains(task.getVehicleId()) && !pickVehicleIds.contains(task.getVehicleId()) - && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())).toList(); - if (remainTasks.isEmpty() || runningTaskNumToEquipmentMap.get(equipmentId) >= 3) { - runningTaskNumToEquipmentMap.remove(equipmentId); - } - } - } - - if (request.size() == 0) { - // 没有新任务发送 - return; - } - // 发送任务 - String url = configMap.get(ConfigMapKeyEnum.URL_WCS_TASK.getConfigKey()); - if (url != null) { - logger.info("向WCS发送拣选出库任务,地址:{},请求详情:{}", url, convertJsonString(request)); - ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(url, convertJsonString(request)), ResponseEntity.class); - try { - logService.save(new WmsLog(WmsUtils.generateId("LOG_"), "向WCS发送任务", "SetStackerTask", JSON.toJSONString(request), JSON.toJSONString(result), url, LocalDateTime.now(), "WMS")); - } catch (Exception e) { - logger.error("插入日志错误。"); - } - if (result == null) { - logger.error("发送拣选出库任务异常。"); - } else { - if (Objects.equals(ResponseCode.OK.getCode(), result.getCode())) { - logger.info("发送WCS拣选出库任务成功。"); - taskService.update(new LambdaUpdateWrapper() - .set(Task::getTaskStatus, WmsTaskStatus.WAIT.getCode()) - .in(Task::getTaskGroup, taskGroupIds) - .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode())); - // 流转载具状态变更 - if (!pickVehicleIds.isEmpty()) { - outsideVehiclesService.update(new LambdaUpdateWrapper() - .set(OutsideVehicles::getOutStatus, 1) - .in(OutsideVehicles::getVehicleId, pickVehicleIds)); - // 更新站台拣选箱数 - for (String tempStandId : updatedOutPickTaskMap.keySet()) { - standService.update(new LambdaUpdateWrapper() - .set(Stand::getPickVehicleCount, updatedOutPickTaskMap.get(tempStandId)) - .eq(Stand::getStandId, tempStandId)); - } - } - } else { - // 判断returnData的数据 - if (result.getReturnData() != null) { - List errorTasks = JSON.parseArray(result.getReturnData().toString(), WcsTaskRequest.class); - if (!errorTasks.isEmpty()) { - List failedTaskIds = errorTasks.stream().map(WcsTaskRequest::getTaskId).distinct().toList(); - // 更新任务状态为异常 - taskService.update(new LambdaUpdateWrapper() - .set(Task::getTaskStatus, WmsTaskStatus.EXCEPTION.getCode()) - .in(Task::getTaskGroup, failedTaskIds) - .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode())); - } - } - logger.error("发送拣选出库任务错误:{}", convertJsonString(result)); - } - } - } else { - logger.error("WCS发送任务地址为空。"); - } - } - } catch (Exception exception) { - logger.error("向WCS发送拣选出库任务时发生异常:{}", convertJsonString(exception)); - throw new Exception("向WCS发送拣选出库任务时发生异常。"); - } - } +// @Override +// public void sendPickOutTasks() throws Exception { +// try { +// // 检索任务表---新建未下发的任务 +// LambdaQueryWrapper waitForDistributeTaskQuery = new LambdaQueryWrapper() +// .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode()) +// .eq(Task::getTaskType, TaskType.OUT.getCode()) +// .eq(Task::getTaskPriority, 1); +// List allTasks = taskService.list(waitForDistributeTaskQuery); +// if (!allTasks.isEmpty()) { +// String max_vehicle_nums = configMap.get(ConfigMapKeyEnum.MAX_VEHICLE_NUMS.getConfigKey()); +// String max_wcs_accept_nums = configMap.get(ConfigMapKeyEnum.MAX_WCS_ACCEPT_NUMS.getConfigKey()); +// String max_stand_vehicle_nums = configMap.get(ConfigMapKeyEnum.MAX_STAND_VEHICLE_NUMS.getConfigKey()); +// if (StringUtils.isEmpty(max_vehicle_nums) || StringUtils.isEmpty(max_wcs_accept_nums) || StringUtils.isEmpty(max_stand_vehicle_nums)) { +// logger.error("配置未生成"); +// return; +// } +// int maxVehicleNums = Integer.parseInt(max_vehicle_nums);// 线体最大箱子数量 +// int maxWcsAcceptNums = Integer.parseInt(max_wcs_accept_nums);// wcs最大一次性可接受任务数量 +// int maxStandVehicleNums = Integer.parseInt(max_stand_vehicle_nums);// 每个站台最大箱子数量 +// List outsideVehicles = outsideVehiclesService.selectDistinctVehicles(); +// if (outsideVehicles == null || outsideVehicles.isEmpty()) { +// outsideVehicles = Collections.emptyList(); +// } +// int remainVehicleNums = maxVehicleNums - outsideVehicles.size();// 线体剩余箱子数量 +// if (remainVehicleNums <= 0) { +// return; +// } +// +// // 需要发送给wcs的任务列表 +// List request = new ArrayList<>(); +// // 已经下发的任务组列表 +// List taskGroupIds = new ArrayList<>(); +// // 本次生成的箱子 +// List pickVehicleIds = new ArrayList<>(); +// // 本次跳过的箱子 +// List skipVehicleIds = new ArrayList<>(); +// // 查找所有站台拣选任务 +// List standPickTasks = pickTaskService.list(); +// // 生成一个Map,计算每个站台已经出库的拣选任务 +// Map outPickTaskMap = new HashMap<>(); +// Map updatedOutPickTaskMap = new HashMap<>(); +// // 轮询工作站台,判断是否需要下发任务 +// List stands = standService.list(new LambdaQueryWrapper() +// .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0) +// .eq(Stand::getStandType, 2)); +// for (Stand workStation : stands) { +// outPickTaskMap.put(workStation.getStandId(), workStation.getPickVehicleCount()); +// updatedOutPickTaskMap.put(workStation.getStandId(), workStation.getPickVehicleCount()); +// } +// // 轮询堆垛机状态 +// List stackerList = standService.list(new LambdaQueryWrapper() +// .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0) +// .eq(Stand::getStandType, 3)); +// List stackRunningTasks = taskService.list(new LambdaQueryWrapper() +// .eq(Task::getTaskType, TaskType.OUT.getCode()) +// .and(wrapper -> wrapper.eq(Task::getTaskStatus, WmsTaskStatus.WAIT.getCode()) +// .or().eq(Task::getTaskStatus, WmsTaskStatus.RUN.getCode()))); +// Map runningTaskNumToEquipmentMap = new HashMap<>(); +// for (Stand stacker : stackerList) { +// // 找这台堆垛机正在执行的拣选出库任务数量 +// runningTaskNumToEquipmentMap.put(stacker.getEquipmentId(), 0); +// } +// // 生成堆垛机可用列表 +// for (Task tempStackRunningTask : stackRunningTasks) { +// if (instantLocationMap.containsKey(tempStackRunningTask.getOrigin())) { +// int key = instantLocationMap.get(tempStackRunningTask.getOrigin()).getEquipmentId(); +// if (runningTaskNumToEquipmentMap.isEmpty()) { +// // 没有可用堆垛机 +// break; +// } +// if (runningTaskNumToEquipmentMap.containsKey(key)) { +// if (runningTaskNumToEquipmentMap.get(key) >= 3) { +// runningTaskNumToEquipmentMap.remove(key); +// } else { +// runningTaskNumToEquipmentMap.replace(key, runningTaskNumToEquipmentMap.get(key) + 1); +// } +// } +// } +// } +// if (runningTaskNumToEquipmentMap.isEmpty()) { +// // 没有可用堆垛机 +// return; +// } +// // 还有可用堆垛机 +// while(!runningTaskNumToEquipmentMap.isEmpty()) { +// if (request.size() >= maxWcsAcceptNums || remainVehicleNums <= 0) { +// // 超过wcs一次可接受数量 +// break; +// } +// if (outPickTaskMap.isEmpty()) { +// // 没有站台可以使用 +// break; +// } +// // 先找出目前数量最少的站台 +// String standId = outPickTaskMap.entrySet().stream() +// .min(Comparator.comparingInt(Map.Entry::getValue)) +// .map(Map.Entry::getKey) +// .orElse(""); +// List vehicleIds; +// if (StringUtils.isNotEmpty(standId)) { +// // 如果这个站台箱子数量超过最大每个站台的箱子数量,则跳过 +// if (outPickTaskMap.get(standId) >= maxStandVehicleNums) { +// outPickTaskMap.remove(standId); +// continue; +// } +// // 查找这个站台未下发的料箱 +// vehicleIds = standPickTasks.stream() +// .filter(pickTask -> pickTask.getStandId().equals(standId) && pickTask.getPickStatus().equals(PickTaskStatusEnum.TEMP.getCode()) +// && !pickVehicleIds.contains(pickTask.getVehicleId()) +// && !skipVehicleIds.contains(pickTask.getVehicleId())) +// .map(PickTask::getVehicleId) +// .distinct() +// .toList(); +// if (vehicleIds.isEmpty()) { +// outPickTaskMap.remove(standId); +// continue; +// } +// } else { +// vehicleIds = standPickTasks.stream() +// .filter(pickTask -> pickTask.getPickStatus().equals(PickTaskStatusEnum.TEMP.getCode()) +// && !pickVehicleIds.contains(pickTask.getVehicleId()) +// && !skipVehicleIds.contains(pickTask.getVehicleId())) +// .map(PickTask::getVehicleId) +// .distinct() +// .toList(); +// if (vehicleIds.isEmpty()) { +// break; +// } +// } +// // 生成箱子-站台数量的Map +// Map vehicleStandsMap = new HashMap<>(); +// standPickTasks.forEach(pickTask -> { +// if (vehicleIds.contains(pickTask.getVehicleId())) { +// vehicleStandsMap.put(pickTask.getVehicleId(), +// vehicleStandsMap.getOrDefault(pickTask.getVehicleId(), 0) + 1); +// } +// }); +// // 最多使用的箱子 +// String maxVehicleId = vehicleStandsMap.entrySet().stream() +// .max(Comparator.comparingInt(Map.Entry::getValue)) +// .map(Map.Entry::getKey) +// .orElse(""); +// if (!StringUtils.isEmpty(maxVehicleId)) { +// // 找到这个箱子的任务 +// List outPickTasks = allTasks.stream().filter(task -> task.getVehicleId().equals(maxVehicleId) && !pickVehicleIds.contains(task.getVehicleId()) +// && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())).toList(); +// if (!outPickTasks.isEmpty()) { +// // 更新每个站台的拣选箱数量 +// List maxStandIds = standPickTasks.stream() +// .filter(pickTask -> pickTask.getVehicleId().equals(maxVehicleId)) +// .map(PickTask::getStandId) +// .distinct() +// .toList(); +// // 给当前设备号+1 +// int equipmentId = instantLocationMap.get(outPickTasks.get(0).getOrigin()).getEquipmentId(); +// if (runningTaskNumToEquipmentMap.containsKey(equipmentId)) { +// boolean flag = false; +// for (Task task : outPickTasks) { +// if (taskGroupIds.contains(task.getTaskGroup())) { +// // 该任务组已经下发 +// continue; +// } +// if (StringUtils.isNotEmpty(task.getPreTask())) {// 当前任务具有前置任务 +// // 查询一下前置的任务有没有存在,存在则不下发 +// if (taskService.exists(new LambdaQueryWrapper().eq(Task::getTaskId, task.getPreTask()))) { +// continue; +// } +// } +// // 创建发送的任务 +// WcsTaskRequest tempTask = new WcsTaskRequest(); +// tempTask.setTaskId(task.getTaskGroup()); +// tempTask.setTaskType(task.getTaskType()); +// tempTask.setOrigin(task.getOrigin()); +// tempTask.setDestination(task.getDestination()); +// tempTask.setVehicleNo(task.getVehicleId()); +// tempTask.setVehicleSize(task.getVehicleSize()); +// tempTask.setWeight(task.getWeight()); +// tempTask.setPriority(task.getTaskPriority()); +// request.add(tempTask); +// // 已经发送过的任务组 +// taskGroupIds.add(task.getTaskGroup()); +// flag = true; +// } +// if (flag) { +// if (!maxStandIds.isEmpty()) { +// maxStandIds.forEach(tempStandId -> { +// outPickTaskMap.put(tempStandId, outPickTaskMap.getOrDefault(tempStandId, 0) + 1); +// updatedOutPickTaskMap.put(tempStandId, updatedOutPickTaskMap.getOrDefault(tempStandId, 0) + 1); +// }); +// } +// runningTaskNumToEquipmentMap.replace(equipmentId, runningTaskNumToEquipmentMap.get(equipmentId) + 1); +// // 已经发送过的vehicleId +// pickVehicleIds.add(maxVehicleId); +// vehicleStandsMap.remove(maxVehicleId); +// // 剩余线体可继续出库料箱数量 +// remainVehicleNums--; +// } +// } else { +// if (!skipVehicleIds.contains(maxVehicleId)) { +// skipVehicleIds.add(maxVehicleId); +// } +// } +// } else { +// if (!skipVehicleIds.contains(maxVehicleId)) { +// skipVehicleIds.add(maxVehicleId); +// } +// } +// } +// // 最少使用的箱子 +// String minVehicleId = vehicleStandsMap.entrySet().stream() +// .min(Comparator.comparingInt(Map.Entry::getValue)) +// .map(Map.Entry::getKey) +// .orElse(""); +// if (!StringUtils.isEmpty(minVehicleId)) { +// // 找到这个箱子的任务 +// List outPickTasks = allTasks.stream().filter(task -> task.getVehicleId().equals(minVehicleId) && !pickVehicleIds.contains(task.getVehicleId()) +// && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())).toList(); +// if (!outPickTasks.isEmpty()) { +// // 更新每个站台的拣选箱数量 +// List minStandIds = standPickTasks.stream() +// .filter(pickTask -> pickTask.getVehicleId().equals(minVehicleId)) +// .map(PickTask::getStandId) +// .distinct() +// .toList(); +// // 给当前设备号+1 +// int equipmentId = instantLocationMap.get(outPickTasks.get(0).getOrigin()).getEquipmentId(); +// if (runningTaskNumToEquipmentMap.containsKey(equipmentId)) { +// boolean flag = false; +// for (Task task : outPickTasks) { +// if (taskGroupIds.contains(task.getTaskGroup())) { +// // 该任务组已经下发 +// continue; +// } +// if (StringUtils.isNotEmpty(task.getPreTask())) {// 当前任务具有前置任务 +// // 查询一下前置的任务有没有存在,存在则不下发 +// if (taskService.exists(new LambdaQueryWrapper().eq(Task::getTaskId, task.getPreTask()))) { +// continue; +// } +// } +// // 创建发送的任务 +// WcsTaskRequest tempTask = new WcsTaskRequest(); +// tempTask.setTaskId(task.getTaskGroup()); +// tempTask.setTaskType(task.getTaskType()); +// tempTask.setOrigin(task.getOrigin()); +// tempTask.setDestination(task.getDestination()); +// tempTask.setVehicleNo(task.getVehicleId()); +// tempTask.setVehicleSize(task.getVehicleSize()); +// tempTask.setWeight(task.getWeight()); +// tempTask.setPriority(task.getTaskPriority()); +// request.add(tempTask); +// // 已经发送过的任务组 +// taskGroupIds.add(task.getTaskGroup()); +// flag = true; +// } +// if (flag) { +// if (!minStandIds.isEmpty()) { +// minStandIds.forEach(tempStandId -> { +// outPickTaskMap.put(tempStandId, outPickTaskMap.getOrDefault(tempStandId, 0) + 1); +// updatedOutPickTaskMap.put(tempStandId, updatedOutPickTaskMap.getOrDefault(tempStandId, 0) + 1); +// }); +// } +// runningTaskNumToEquipmentMap.replace(equipmentId, runningTaskNumToEquipmentMap.get(equipmentId) + 1); +// // 已经发送过的vehicleId +// pickVehicleIds.add(minVehicleId); +// vehicleStandsMap.remove(minVehicleId); +// // 剩余线体可继续出库料箱数量 +// remainVehicleNums--; +// } +// } else { +// if (!skipVehicleIds.contains(minVehicleId)) { +// skipVehicleIds.add(minVehicleId); +// } +// } +// } else { +// if (!skipVehicleIds.contains(minVehicleId)) { +// skipVehicleIds.add(minVehicleId); +// } +// } +// } +// List removeKeys = new ArrayList<>(runningTaskNumToEquipmentMap.keySet().stream().toList()); +// for (int equipmentId : removeKeys) { +// // 剩余任务有没有这台堆垛机的 +// List remainTasks = allTasks.stream().filter(task -> !skipVehicleIds.contains(task.getVehicleId()) && !pickVehicleIds.contains(task.getVehicleId()) +// && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())).toList(); +// if (remainTasks.isEmpty() || runningTaskNumToEquipmentMap.get(equipmentId) >= 3) { +// runningTaskNumToEquipmentMap.remove(equipmentId); +// } +// } +// } +// +// if (request.size() == 0) { +// // 没有新任务发送 +// return; +// } +// // 发送任务 +// String url = configMap.get(ConfigMapKeyEnum.URL_WCS_TASK.getConfigKey()); +// if (url != null) { +// logger.info("向WCS发送拣选出库任务,地址:{},请求详情:{}", url, convertJsonString(request)); +// ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(url, convertJsonString(request)), ResponseEntity.class); +// try { +// logService.save(new WmsLog(WmsUtils.generateId("LOG_"), "向WCS发送任务", "SetStackerTask", JSON.toJSONString(request), JSON.toJSONString(result), url, LocalDateTime.now(), "WMS")); +// } catch (Exception e) { +// logger.error("插入日志错误。"); +// } +// if (result == null) { +// logger.error("发送拣选出库任务异常。"); +// } else { +// if (Objects.equals(ResponseCode.OK.getCode(), result.getCode())) { +// logger.info("发送WCS拣选出库任务成功。"); +// taskService.update(new LambdaUpdateWrapper() +// .set(Task::getTaskStatus, WmsTaskStatus.WAIT.getCode()) +// .in(Task::getTaskGroup, taskGroupIds) +// .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode())); +// // 流转载具状态变更 +// if (!pickVehicleIds.isEmpty()) { +// outsideVehiclesService.update(new LambdaUpdateWrapper() +// .set(OutsideVehicles::getOutStatus, 1) +// .in(OutsideVehicles::getVehicleId, pickVehicleIds)); +// // 更新站台拣选箱数 +// for (String tempStandId : updatedOutPickTaskMap.keySet()) { +// standService.update(new LambdaUpdateWrapper() +// .set(Stand::getPickVehicleCount, updatedOutPickTaskMap.get(tempStandId)) +// .eq(Stand::getStandId, tempStandId)); +// } +// } +// } else { +// // 判断returnData的数据 +// if (result.getReturnData() != null) { +// List errorTasks = JSON.parseArray(result.getReturnData().toString(), WcsTaskRequest.class); +// if (!errorTasks.isEmpty()) { +// List failedTaskIds = errorTasks.stream().map(WcsTaskRequest::getTaskId).distinct().toList(); +// // 更新任务状态为异常 +// taskService.update(new LambdaUpdateWrapper() +// .set(Task::getTaskStatus, WmsTaskStatus.EXCEPTION.getCode()) +// .in(Task::getTaskGroup, failedTaskIds) +// .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode())); +// } +// } +// logger.error("发送拣选出库任务错误:{}", convertJsonString(result)); +// } +// } +// } else { +// logger.error("WCS发送任务地址为空。"); +// } +// } +// } catch (Exception exception) { +// logger.error("向WCS发送拣选出库任务时发生异常:{}", convertJsonString(exception)); +// throw new Exception("向WCS发送拣选出库任务时发生异常。"); +// } +// } /** * 发送拣选任务 @@ -696,4 +700,350 @@ public class WmsJobServiceImplements implements IWmsJobService { TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } } + + /** + * 发送PickOut任务 + * @throws Exception 异常 + */ + @Override + public void sendPickOutTasks() throws Exception { + try { + // 检索任务表---新建未下发的任务 + LambdaQueryWrapper waitForDistributeTaskQuery = new LambdaQueryWrapper() + .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode()) + .eq(Task::getTaskType, TaskType.OUT.getCode()) + .eq(Task::getTaskPriority, 1); + List allTasks = taskService.list(waitForDistributeTaskQuery); + if (!allTasks.isEmpty()) { + String max_vehicle_nums = configMap.get(ConfigMapKeyEnum.MAX_VEHICLE_NUMS.getConfigKey()); + String max_wcs_accept_nums = configMap.get(ConfigMapKeyEnum.MAX_WCS_ACCEPT_NUMS.getConfigKey()); + String max_stand_vehicle_nums = configMap.get(ConfigMapKeyEnum.MAX_STAND_VEHICLE_NUMS.getConfigKey()); + if (StringUtils.isEmpty(max_vehicle_nums) || StringUtils.isEmpty(max_wcs_accept_nums) || StringUtils.isEmpty(max_stand_vehicle_nums)) { + logger.error("配置未生成"); + return; + } + int maxVehicleNums = Integer.parseInt(max_vehicle_nums);// 线体最大箱子数量 + List outsideVehicles = outsideVehiclesService.selectDistinctVehicles(); + if (outsideVehicles == null || outsideVehicles.isEmpty()) { + outsideVehicles = Collections.emptyList(); + } + int remainVehicleNums = maxVehicleNums - outsideVehicles.size();// 线体剩余箱子数量 + if (remainVehicleNums <= 0) { + return; + } + // 需要发送给wcs的任务列表 + List request = new ArrayList<>(); + // 已经下发的任务组列表 + List taskGroupIds = new ArrayList<>(); + // 本次生成的箱子 + List pickVehicleIds = new ArrayList<>(); + // 查找所有站台拣选任务 + List standPickTasks = pickTaskService.list(); + // 找出所有可用设备 + List stands = standService.list(new LambdaQueryWrapper() + .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0)); + // 备料站台---从9号站台开始 + List allPickStands = stands.stream().filter(stand -> stand.getStandType() == 2).sorted(Comparator.comparing(Stand::getStandId).reversed()).toList(); + // 找出所有可用堆垛机---从5号堆垛机开始 + List stackerList = stands.stream().filter(stand -> stand.getStandType() == 3).sorted(Comparator.comparingInt(Stand::getEquipmentId).reversed()).toList(); + // 查询特殊表 + List standStackerTasks = standStackerTaskService.list(); + // 需要添加的站台任务 + List needAddStandStackerTasks = new ArrayList<>(); + // 需要移除的 + List needRemoveStandStackerTasks = new ArrayList<>(); + // 能够用的站体的列表 + List pickStands = new ArrayList<>(); + // 判断哪些站台暂时不能下发任务 + for (Stand pickStand : allPickStands) { + // 查询这个站台有多少已下发的拣选任务 + List thisStandPickCounts = standPickTasks.stream().filter(pickTask -> pickTask.getStandId().equals(pickStand.getStandId()) && pickTask.getPickStatus() >= PickTaskStatusEnum.NEW.getCode()).toList(); + if (thisStandPickCounts.size() < Integer.parseInt(max_stand_vehicle_nums)) { + pickStands.add(pickStand); + } + } + // 处理数据 + for(Stand pickStand : pickStands) { + // 找到未完成定额的站台任务 + List currentStandTasks = standStackerTasks.stream().filter(standStackerTask -> standStackerTask.getStandId().equals(pickStand.getStandId()) && standStackerTask.getTaskType() == 1 && standStackerTask.getTaskStatus() == 0).toList(); + if (currentStandTasks.isEmpty()) { + // 需要下发这个站台的任务了,找空闲堆垛机 + for (Stand stacker : stackerList) { + List currentStackerTasks = standStackerTasks.stream().filter(standStackerTask -> standStackerTask.getStackerId().equals(stacker.getEquipmentId()) && standStackerTask.getTaskStatus() == 0).toList(); + if (currentStackerTasks.size() < 2) { + // 说明当前堆垛机仍然可以下发任务 + int thisQtyType = 1; + // 找到之前完成的 + List currentStandFinishedTasks = standStackerTasks.stream().filter(standStackerTask -> standStackerTask.getStandId().equals(pickStand.getStandId()) && standStackerTask.getTaskType() == 1 && standStackerTask.getTaskStatus() == 1).toList(); + if (!currentStandFinishedTasks.isEmpty()) { + thisQtyType = currentStandFinishedTasks.get(0).getLastQtyType() == 1 ? 2 : 1; + } + // 设置分配策略 + StandStackerTask newStandStackerTask = new StandStackerTask(); + newStandStackerTask.setLastQtyType(thisQtyType); + // 查询这个这台堆垛机的料箱号 + List thisStackerVehicleIds = new ArrayList<>(); + for (Task task : allTasks) { + int equipmentId = instantLocationMap.get(task.getOrigin()).getEquipmentId(); + if (!pickVehicleIds.contains(task.getVehicleId()) && equipmentId == stacker.getEquipmentId() && !thisStackerVehicleIds.contains(task.getVehicleId())) { + thisStackerVehicleIds.add(task.getVehicleId()); + } + } + // 查找这个站台未下发的料箱 + List vehicleIds = standPickTasks.stream() + .filter(pickTask -> pickTask.getStandId().equals(pickStand.getStandId()) && pickTask.getPickStatus().equals(PickTaskStatusEnum.TEMP.getCode()) + && thisStackerVehicleIds.contains(pickTask.getVehicleId())) + .map(PickTask::getVehicleId) + .distinct() + .toList(); + if (vehicleIds.isEmpty()) { + continue; + } + // 生成箱子-站台数量的Map + Map vehicleStandsMap = new HashMap<>(); + standPickTasks.forEach(pickTask -> { + if (vehicleIds.contains(pickTask.getVehicleId())) { + vehicleStandsMap.put(pickTask.getVehicleId(), + vehicleStandsMap.getOrDefault(pickTask.getVehicleId(), 0) + 1); + } + }); + String vehicleId; + if (thisQtyType == 1) { + // 最少使用的箱子 + vehicleId = vehicleStandsMap.entrySet().stream() + .min(Comparator.comparingInt(Map.Entry::getValue)) + .map(Map.Entry::getKey) + .orElse(""); + } else { + // 找最多的 + vehicleId = vehicleStandsMap.entrySet().stream() + .max(Comparator.comparingInt(Map.Entry::getValue)) + .map(Map.Entry::getKey) + .orElse(""); + } + if (!StringUtils.isEmpty(vehicleId)) { + // 找到这个箱子的任务 + List outPickTasks = allTasks.stream().filter(task -> task.getVehicleId().equals(vehicleId) && !pickVehicleIds.contains(task.getVehicleId()) + && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())).toList(); + if (!outPickTasks.isEmpty()) { + boolean flag = false; + for (Task task : outPickTasks) { + if (taskGroupIds.contains(task.getTaskGroup())) { + // 该任务组已经下发 + continue; + } + if (StringUtils.isNotEmpty(task.getPreTask())) {// 当前任务具有前置任务 + // 查询一下前置的任务有没有存在,存在则不下发 + if (taskService.exists(new LambdaQueryWrapper().eq(Task::getTaskId, task.getPreTask()))) { + continue; + } + } + // 创建需要发送的任务 + WcsTaskRequest tempTask = new WcsTaskRequest(); + tempTask.setTaskId(task.getTaskGroup()); + tempTask.setTaskType(task.getTaskType()); + tempTask.setOrigin(task.getOrigin()); + tempTask.setDestination(task.getDestination()); + tempTask.setVehicleNo(task.getVehicleId()); + tempTask.setVehicleSize(task.getVehicleSize()); + tempTask.setWeight(task.getWeight()); + tempTask.setPriority(task.getTaskPriority()); + request.add(tempTask); + // 已经发送过的任务组 + taskGroupIds.add(task.getTaskGroup()); + flag = true; + // 添加特殊任务 + newStandStackerTask.setVehicleId(task.getVehicleId()); + newStandStackerTask.setStackerId(stacker.getEquipmentId()); + newStandStackerTask.setStandId(pickStand.getStandId()); + newStandStackerTask.setTaskType(1); + newStandStackerTask.setTaskStatus(0); + newStandStackerTask.setCreateTime(LocalDateTime.now()); + standStackerTasks.add(newStandStackerTask); + needAddStandStackerTasks.add(newStandStackerTask);// 需要更新的表 + needRemoveStandStackerTasks.addAll(currentStandFinishedTasks);// 需要移除的 + } + if (flag) { + // 已经发送过的vehicleId + pickVehicleIds.add(vehicleId); + break; + } + } + } + } + } + } + } + // 可以下发超额任务,找空闲堆垛机 + for (Stand stacker : stackerList) { + List currentStackerTasks = standStackerTasks.stream().filter(standStackerTask -> standStackerTask.getStackerId().equals(stacker.getEquipmentId()) && standStackerTask.getTaskStatus() == 0).toList(); + int availNum = 2 - currentStackerTasks.size(); + while (availNum > 0) { + // 设置分配策略 + StandStackerTask newStandStackerTask = new StandStackerTask(); + newStandStackerTask.setLastQtyType(1);// 超额固定为1 + // 查询这个这台堆垛机的料箱号 + List thisStackerVehicleIds = new ArrayList<>(); + for (Task task : allTasks) { + int equipmentId = instantLocationMap.get(task.getOrigin()).getEquipmentId(); + if (!pickVehicleIds.contains(task.getVehicleId()) && equipmentId == stacker.getEquipmentId() && !thisStackerVehicleIds.contains(task.getVehicleId())) { + thisStackerVehicleIds.add(task.getVehicleId()); + } + } + if (thisStackerVehicleIds.isEmpty()) { + // 查看下一台堆垛机 + break; + } + // 找到暂存拣选任务最多的站台 + Map pickTaskNumsOfStandsMap = new HashMap<>(); + for(Stand pickStand : pickStands) { + standPickTasks.forEach(pickTask -> { + if (Objects.equals(pickTask.getPickStatus(), PickTaskStatusEnum.TEMP.getCode()) + && thisStackerVehicleIds.contains(pickTask.getVehicleId()) + && pickStand.getStandId().equals(pickTask.getStandId())) { + pickTaskNumsOfStandsMap.put(pickTask.getStandId(), pickTaskNumsOfStandsMap.getOrDefault(pickTask.getStandId(), 0) + 1); + } + }); + } + String standId = pickTaskNumsOfStandsMap.entrySet().stream() + .max(Comparator.comparingInt(Map.Entry::getValue)) + .map(Map.Entry::getKey) + .orElse(""); + // 查找这个站台未下发的料箱 + List vehicleIds = standPickTasks.stream() + .filter(pickTask -> pickTask.getPickStatus().equals(PickTaskStatusEnum.TEMP.getCode()) + && thisStackerVehicleIds.contains(pickTask.getVehicleId()) && standId.equals(pickTask.getStandId())) + .map(PickTask::getVehicleId) + .distinct() + .toList(); + if (vehicleIds.isEmpty()) { + break; + } + // 生成箱子-站台数量的Map + Map vehicleStandsMap = new HashMap<>(); + standPickTasks.forEach(pickTask -> { + if (vehicleIds.contains(pickTask.getVehicleId())) { + vehicleStandsMap.put(pickTask.getVehicleId(), + vehicleStandsMap.getOrDefault(pickTask.getVehicleId(), 0) + 1); + } + }); + String vehicleId = vehicleStandsMap.entrySet().stream() + .min(Comparator.comparingInt(Map.Entry::getValue)) + .map(Map.Entry::getKey) + .orElse(""); + if (!StringUtils.isEmpty(vehicleId)) { + // 找到这个箱子的任务 + List outPickTasks = allTasks.stream().filter(task -> task.getVehicleId().equals(vehicleId) && !pickVehicleIds.contains(task.getVehicleId()) + && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())).toList(); + if (!outPickTasks.isEmpty()) { + boolean flag = false; + for (Task task : outPickTasks) { + if (taskGroupIds.contains(task.getTaskGroup())) { + // 该任务组已经下发 + continue; + } + if (StringUtils.isNotEmpty(task.getPreTask())) {// 当前任务具有前置任务 + // 查询一下前置的任务有没有存在,存在则不下发 + if (taskService.exists(new LambdaQueryWrapper().eq(Task::getTaskId, task.getPreTask()))) { + continue; + } + } + // 创建需要发送的任务 + WcsTaskRequest tempTask = new WcsTaskRequest(); + tempTask.setTaskId(task.getTaskGroup()); + tempTask.setTaskType(task.getTaskType()); + tempTask.setOrigin(task.getOrigin()); + tempTask.setDestination(task.getDestination()); + tempTask.setVehicleNo(task.getVehicleId()); + tempTask.setVehicleSize(task.getVehicleSize()); + tempTask.setWeight(task.getWeight()); + tempTask.setPriority(task.getTaskPriority()); + request.add(tempTask); + // 已经发送过的任务组 + taskGroupIds.add(task.getTaskGroup()); + flag = true; + // 添加特殊任务 + newStandStackerTask.setVehicleId(task.getVehicleId()); + newStandStackerTask.setStackerId(stacker.getEquipmentId()); + newStandStackerTask.setStandId(standId); + newStandStackerTask.setTaskType(2); + newStandStackerTask.setTaskStatus(0); + newStandStackerTask.setCreateTime(LocalDateTime.now()); + standStackerTasks.add(newStandStackerTask); + needAddStandStackerTasks.add(newStandStackerTask);// 需要更新的表 + needRemoveStandStackerTasks.addAll(standStackerTasks.stream().filter(standStackerTask -> standStackerTask.getTaskType() == 2 && standStackerTask.getTaskStatus() == 1).toList()); + } + if (flag) { + // 已经发送过的vehicleId + pickVehicleIds.add(vehicleId); + availNum--; + } + } + } + } + } + if (request.isEmpty()) { + // 没有新任务发送 + return; + } + // 发送任务 + String url = configMap.get(ConfigMapKeyEnum.URL_WCS_TASK.getConfigKey()); + if (url != null) { + logger.info("向WCS发送拣选出库任务,地址:{},请求详情:{}", url, convertJsonString(request)); + ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(url, convertJsonString(request)), ResponseEntity.class); + try { + logService.save(new WmsLog(WmsUtils.generateId("LOG_"), "向WCS发送任务", "SetStackerTask", JSON.toJSONString(request), JSON.toJSONString(result), url, LocalDateTime.now(), "WMS")); + } catch (Exception e) { + logger.error("插入日志错误。"); + } + if (result == null) { + logger.error("发送拣选出库任务异常。"); + } else { + if (Objects.equals(ResponseCode.OK.getCode(), result.getCode())) { + logger.info("发送WCS拣选出库任务成功。"); + taskService.update(new LambdaUpdateWrapper() + .set(Task::getTaskStatus, WmsTaskStatus.WAIT.getCode()) + .in(Task::getTaskGroup, taskGroupIds) + .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode())); + // 流转载具状态变更 + if (!pickVehicleIds.isEmpty()) { + outsideVehiclesService.update(new LambdaUpdateWrapper() + .set(OutsideVehicles::getOutStatus, 1) + .in(OutsideVehicles::getVehicleId, pickVehicleIds)); + } + // 更新特殊信息 + standStackerTaskService.saveBatch(needAddStandStackerTasks); + standStackerTaskService.removeBatchByIds(needRemoveStandStackerTasks); + List needSaveRecords = new ArrayList<>(); + for (StandStackerTask standStackerTask : needRemoveStandStackerTasks) { + StandStackerTaskBak standStackerTaskBak = BeanUtil.copyProperties(standStackerTask, StandStackerTaskBak.class); + standStackerTaskBak.setRecordId(WmsUtils.generateId("STAND_STACKER_TASK_BAK_")); + needSaveRecords.add(standStackerTaskBak); + } + standStackerTaskBakService.saveBatch(needSaveRecords); + } else { + // 判断returnData的数据 + if (result.getReturnData() != null) { + List errorTasks = JSON.parseArray(result.getReturnData().toString(), WcsTaskRequest.class); + if (!errorTasks.isEmpty()) { + List failedTaskIds = errorTasks.stream().map(WcsTaskRequest::getTaskId).distinct().toList(); + // 更新任务状态为异常 + taskService.update(new LambdaUpdateWrapper() + .set(Task::getTaskStatus, WmsTaskStatus.EXCEPTION.getCode()) + .in(Task::getTaskGroup, failedTaskIds) + .eq(Task::getTaskStatus, WmsTaskStatus.NEW.getCode())); + } + } + logger.error("发送拣选出库任务错误:{}", convertJsonString(result)); + } + } + } else { + logger.error("WCS发送任务地址为空。"); + } + } + } catch (Exception exception) { + logger.error("向WCS发送拣选出库任务时发生异常:{}", convertJsonString(exception)); + throw new Exception("向WCS发送拣选出库任务时发生异常。"); + } + } } diff --git a/src/main/java/com/wms/service/serviceImplements/StandStackerTaskBakServiceImpl.java b/src/main/java/com/wms/service/serviceImplements/StandStackerTaskBakServiceImpl.java new file mode 100644 index 0000000..131c3cb --- /dev/null +++ b/src/main/java/com/wms/service/serviceImplements/StandStackerTaskBakServiceImpl.java @@ -0,0 +1,14 @@ +package com.wms.service.serviceImplements; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.wms.entity.table.StandStackerTask; +import com.wms.entity.table.StandStackerTaskBak; +import com.wms.mapper.StandStackerTaskBakMapper; +import com.wms.mapper.StandStackerTaskMapper; +import com.wms.service.StandStackerTaskBakService; +import com.wms.service.StandStackerTaskService; +import org.springframework.stereotype.Service; + +@Service +public class StandStackerTaskBakServiceImpl extends ServiceImpl implements StandStackerTaskBakService { +} diff --git a/src/main/java/com/wms/service/serviceImplements/StandStackerTaskServiceImpl.java b/src/main/java/com/wms/service/serviceImplements/StandStackerTaskServiceImpl.java new file mode 100644 index 0000000..fa14b34 --- /dev/null +++ b/src/main/java/com/wms/service/serviceImplements/StandStackerTaskServiceImpl.java @@ -0,0 +1,11 @@ +package com.wms.service.serviceImplements; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.wms.entity.table.StandStackerTask; +import com.wms.mapper.StandStackerTaskMapper; +import com.wms.service.StandStackerTaskService; +import org.springframework.stereotype.Service; + +@Service +public class StandStackerTaskServiceImpl extends ServiceImpl implements StandStackerTaskService { +} diff --git a/src/main/resources/mapper/StandStackerTaskMapper.xml b/src/main/resources/mapper/StandStackerTaskMapper.xml new file mode 100644 index 0000000..e3cf335 --- /dev/null +++ b/src/main/resources/mapper/StandStackerTaskMapper.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/StandStackerTaskMapperBak.xml b/src/main/resources/mapper/StandStackerTaskMapperBak.xml new file mode 100644 index 0000000..c234717 --- /dev/null +++ b/src/main/resources/mapper/StandStackerTaskMapperBak.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/src/main/resources/sql/wms_kate_suzhou.sql b/src/main/resources/sql/wms_kate_suzhou.sql index 3eb25b6..a654f57 100644 Binary files a/src/main/resources/sql/wms_kate_suzhou.sql and b/src/main/resources/sql/wms_kate_suzhou.sql differ