From 6d0965f3f3d81ed7f9273c88667cc447a2bd5459 Mon Sep 17 00:00:00 2001 From: liangzhou <594755172@qq.com> Date: Mon, 24 Jun 2024 16:58:27 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/TaskOutValidationEnum.java | 25 ++ .../com/wms/controller/TaskController.java | 247 +++++++++++++++++- .../java/com/wms/entity/app/dto/TaskDto.java | 12 + .../com/wms/entity/app/dto/TaskRecordDto.java | 12 + .../entity/app/request/TaskOutRequest.java | 28 ++ src/main/java/com/wms/entity/table/Task.java | 15 ++ .../java/com/wms/entity/table/TaskRecord.java | 15 ++ .../java/com/wms/service/LocationService.java | 6 +- .../java/com/wms/service/TaskService.java | 11 +- .../LocationServiceImplements.java | 179 ++++++++----- .../StandServiceImplements.java | 5 +- .../TaskServiceImplements.java | 38 ++- 12 files changed, 512 insertions(+), 81 deletions(-) create mode 100644 src/main/java/com/wms/constants/enums/TaskOutValidationEnum.java create mode 100644 src/main/java/com/wms/entity/app/request/TaskOutRequest.java diff --git a/src/main/java/com/wms/constants/enums/TaskOutValidationEnum.java b/src/main/java/com/wms/constants/enums/TaskOutValidationEnum.java new file mode 100644 index 0000000..c56d4e8 --- /dev/null +++ b/src/main/java/com/wms/constants/enums/TaskOutValidationEnum.java @@ -0,0 +1,25 @@ +package com.wms.constants.enums; + +/** + * 入库验证信息枚举 + */ +public enum TaskOutValidationEnum { + OK(""), + NO_REQUEST_BODY("请求参数为空"), + LACK_REQUIRED_PARAM("缺少必须参数:物料、载具、起始库位至少需要一个"), + ERROR_VEHICLE_ID("不存在的载具号"), + ERROR_ORIGIN_POINT("错误的起始库位"), + ERROR_DESTINATION_POINT("错误的终点站台"), + NO_PICK_STAND("拣选任务无拣选站台"), + ERROR_PICK_STAND("错误的拣选站台"), + NO_STOCK("请求的物料无库存"), + ERROR_GOODS_NUM("错误的出库数量"); + + private final String errorMessage; + TaskOutValidationEnum(String errorMessage) { + this.errorMessage = errorMessage; + } + public String getErrorMessage() { + return errorMessage; + } +} diff --git a/src/main/java/com/wms/controller/TaskController.java b/src/main/java/com/wms/controller/TaskController.java index 4e5f356..b285363 100644 --- a/src/main/java/com/wms/controller/TaskController.java +++ b/src/main/java/com/wms/controller/TaskController.java @@ -1,14 +1,23 @@ package com.wms.controller; import com.alibaba.fastjson2.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.wms.annotation.MyLog; import com.wms.constants.enums.*; import com.wms.entity.app.*; +import com.wms.entity.app.dto.extend.TaskDetailInfo; import com.wms.entity.app.request.GoodsInRequest; import com.wms.entity.app.request.TaskInRequest; +import com.wms.entity.app.request.TaskOutRequest; +import com.wms.entity.table.Location; +import com.wms.entity.table.Stock; +import com.wms.entity.table.Task; +import com.wms.entity.table.Vehicle; import com.wms.service.*; import com.wms.utils.HttpUtils; import com.wms.utils.StringUtils; +import com.wms.utils.WmsUtils; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; @@ -22,10 +31,12 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport; import org.springframework.web.bind.annotation.*; import java.math.BigDecimal; -import java.util.Objects; +import java.time.LocalDateTime; +import java.util.*; import static com.wms.config.InitLocalConfig.configMap; import static com.wms.utils.StringUtils.convertJsonString; +import static com.wms.utils.WmsUtils.generateId; /** * WMS任务控制类 @@ -62,7 +73,11 @@ public class TaskController { /** * 物料服务 */ - private GoodsService goodsService; + private final GoodsService goodsService; + /** + * 载具服务 + */ + private final VehicleService vehicleService; /** * 请求头部信息 */ @@ -95,12 +110,39 @@ public class TaskController { response.setMessage("入库请求验证错误!" + validationInfo); return convertJsonString(response); } - // 请求可用库位---悲观锁 + Map nextLocationMap = new HashMap<>(); + // 请求可用库位 + for (int i = 0; i < locationService.count(new LambdaQueryWrapper().eq(Location::getLocationStatus, LocationStatus.EMPTY.getCode())); i++) { + nextLocationMap = locationService.getOneLocation(taskInRequest.getOriginPoint(), null); + if (nextLocationMap == null || nextLocationMap.isEmpty() || !nextLocationMap.containsKey("nextLocationId")) { + logger.error("暂无可用库位"); + response.setCode(ResponseCode.ERROR.getCode()); + response.setMessage("入库请求验证错误!" + validationInfo); + return convertJsonString(response); + } else { + Location nextLocation = locationService.getOne(new LambdaQueryWrapper().eq(Location::getLocationId, nextLocationMap.get("nextLocationId"))); + LambdaUpdateWrapper updateLocationWrapper = new LambdaUpdateWrapper() + .set(Location::getLocationStatus, LocationStatus.OCCUPY.getCode()) + .eq(Location::getLocationId, nextLocation.getLocationId()) + .eq(Location::getLocationStatus, LocationStatus.EMPTY.getCode()); + if (locationService.update(updateLocationWrapper)) { + break; + } + } + } // 生成入库任务 + String saveTaskResult = ""; if (taskInRequest.getGoodsList().isEmpty()) {// 空托入库 - + saveTaskResult = genEmptyInTask(taskInRequest, nextLocationMap.get("nextLocationId"), nextLocationMap.get("preTaskId")); } else {// 带料入库 - + saveTaskResult = genGoodsInTask(taskInRequest, nextLocationMap.get("nextLocationId"), nextLocationMap.get("preTaskId")); + } + if (!saveTaskResult.equals("")) { + // 回退库位锁定 + locationService.update(new LambdaUpdateWrapper() + .set(Location::getLocationStatus, LocationStatus.EMPTY.getCode()) + .eq(Location::getLocationId, nextLocationMap.get("nextLocationId")) + .eq(Location::getLocationStatus, LocationStatus.OCCUPY.getCode())); } logger.info("接收入库请求成功!"); @@ -118,6 +160,87 @@ public class TaskController { } } + /** + * 添加空入库任务 + * @param taskInRequest 入库请求 + * @param locationId 库位id + * @param preTaskId 前置任务 + * @return 添加结果 + */ + private String genEmptyInTask (TaskInRequest taskInRequest, String locationId, String preTaskId) { + String result = ""; + Task tempInTask = new Task(); + tempInTask.setTaskId(generateId("RK_")); + tempInTask.setTaskType(TaskType.IN.getCode()); + tempInTask.setTaskStatus(WmsTaskStatus.NEW.getCode()); + tempInTask.setTaskGroup(generateId("")); + tempInTask.setTaskPriority(1); + tempInTask.setVehicleId(taskInRequest.getVehicleId()); + tempInTask.setOrigin(taskInRequest.getOriginPoint()); + tempInTask.setDestination(locationId); + tempInTask.setVehicleSize(1); + tempInTask.setWeight(taskInRequest.getTotalWeight()); + tempInTask.setCreateTime(LocalDateTime.now()); + tempInTask.setUserName(taskInRequest.getUserName()); + tempInTask.setPreTask(preTaskId); + try { + if (!taskService.save(tempInTask)) { + return "添加空入库任务失败"; + } + } catch (Exception e) { + logger.error("添加空入库任务异常:{}", convertJsonString(e)); + return "添加空入库任务失败"; + } + return result; + } + + /** + * 添加入库任务 + * @param taskInRequest 入库请求 + * @param locationId 库位号 + * @param preTaskId 前置任务 + * @return 添加结果 + */ + private String genGoodsInTask (TaskInRequest taskInRequest, String locationId, String preTaskId) { + String result = ""; + String taskGroupId = generateId(""); + List tempTasks = new ArrayList<>(); + for (GoodsInRequest goodsInRequest : taskInRequest.getGoodsList()) { + Task tempInTask = new Task(); + tempInTask.setTaskId(generateId("RK_")); + tempInTask.setTaskType(TaskType.IN.getCode()); + tempInTask.setTaskStatus(WmsTaskStatus.NEW.getCode()); + tempInTask.setTaskGroup(taskGroupId); + tempInTask.setTaskPriority(1); + tempInTask.setVehicleId(taskInRequest.getVehicleId()); + tempInTask.setOrigin(taskInRequest.getOriginPoint()); + tempInTask.setDestination(locationId); + tempInTask.setVehicleSize(1); + tempInTask.setWeight(taskInRequest.getTotalWeight()); + tempInTask.setCreateTime(LocalDateTime.now()); + tempInTask.setUserName(taskInRequest.getUserName()); + tempInTask.setPreTask(preTaskId); + // 物料相关信息 + TaskDetailInfo goodsRelatedInfo = new TaskDetailInfo(); + // TODO 物料信息需要完善 + goodsRelatedInfo.setGoodsId(goodsInRequest.getGoodsId()); + goodsRelatedInfo.setGoodsName(""); + tempInTask.setGoodsRelated(goodsRelatedInfo); + + tempTasks.add(tempInTask); + } + + try { + if (!taskService.saveBatch(tempTasks)) { + return "添加入库任务失败"; + } + } catch (Exception e) { + logger.error("添加入库任务异常:{}", convertJsonString(e)); + return "添加入库任务失败"; + } + return result; + } + /** * 验证入库请求 * @param taskInRequest 入库请求 @@ -133,7 +256,7 @@ public class TaskController { return TaskInValidationEnum.NO_VEHICLE_ID.getErrorMessage(); } // 验证载具号是否重复入库 - + // TODO // 验证重量 if (taskInRequest.getTotalWeight() == null) { return TaskInValidationEnum.NO_WEIGHT.getErrorMessage(); @@ -175,4 +298,116 @@ public class TaskController { } return TaskInValidationEnum.OK.getErrorMessage(); } + + /** + * 接收出库任务请求 + * + * @param taskOutRequest 出库任务 + * @return 结果 + */ + @PostMapping("/requestOut") + @ResponseBody + @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) + @MyLog(logTitle = "出库请求", logMethod = "requestOut") + public String receiveTaskOutRequest(@RequestBody TaskOutRequest taskOutRequest) { + logger.info("接收到出库请求:{},ip地址:{}", JSON.toJSONString(taskOutRequest), HttpUtils.getIpAddr(servletRequest)); + // 创建响应信息 + ResponseEntity response = new ResponseEntity(); + try { + // 验证出库请求 + String validationInfo = validateTaskOutRequest(taskOutRequest); + if (!Objects.equals(validationInfo, TaskInValidationEnum.OK.getErrorMessage())) { + logger.error("出库请求验证错误!{}", validationInfo); + response.setCode(ResponseCode.ERROR.getCode()); + response.setMessage("出库请求验证错误!" + validationInfo); + return convertJsonString(response); + } + // 没有物料,单纯载具或者库位出库 + if (StringUtils.isEmpty(taskOutRequest.getGoodsId())) { + // 生成载具出库任务 + + } + // 查询库存 + LambdaQueryWrapper stockLambdaQueryWrapper = new LambdaQueryWrapper() + .eq(Stock::getGoodsId, taskOutRequest.getGoodsId()); + // 生成出库任务 + + logger.info("接收入库请求成功!"); + response.setCode(ResponseCode.OK.getCode()); + response.setMessage("接收入库请求成功!"); + return convertJsonString(response); + } catch (Exception e) { + // 回滚事务 + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + logger.error("发生异常:{}", e.getMessage()); + // 返回其他异常 + response.setCode(ResponseCode.ERROR.getCode()); + response.setMessage("发生意料之外的错误"); + return convertJsonString(response); + } + } + + + /** + * 生成载具或库位出库任务 + * @param taskOutRequest 出库请求 + * @return 结果 + */ + private String genVehicleLocationOutTask(TaskOutRequest taskOutRequest) { + + } + + /** + * 验证出库请求 + * @param taskOutRequest 出库请求 + * @return 验证结果---空为验证通过,否则输出错误信息 + */ + private String validateTaskOutRequest(TaskOutRequest taskOutRequest) { + // 验证任务 + if (taskOutRequest == null) { + return TaskOutValidationEnum.NO_REQUEST_BODY.getErrorMessage(); + } + // 验证是否包含请求信息 + if (StringUtils.isEmpty(taskOutRequest.getGoodsId()) + && StringUtils.isEmpty(taskOutRequest.getVehicleId()) + && StringUtils.isEmpty(taskOutRequest.getOriginPoint())) { + return TaskOutValidationEnum.LACK_REQUIRED_PARAM.getErrorMessage(); + } + // 验证载具号 + if (StringUtils.isNotEmpty(taskOutRequest.getVehicleId()) + && vehicleService.exists(new LambdaQueryWrapper().eq(Vehicle::getVehicleId, taskOutRequest.getVehicleId()))) { + return TaskOutValidationEnum.ERROR_VEHICLE_ID.getErrorMessage(); + } + // 验证库位 + if (StringUtils.isNotEmpty(taskOutRequest.getOriginPoint()) + && locationService.exists(new LambdaQueryWrapper().eq(Location::getLocationId, taskOutRequest.getOriginPoint()))) { + return TaskOutValidationEnum.ERROR_ORIGIN_POINT.getErrorMessage(); + } + // 验证终点站台 + if (taskOutRequest.getIsPicking() == 0) {// 出库 + if (standService.validateStand(taskOutRequest.getDestinationPoint(), 2)) { + return TaskOutValidationEnum.ERROR_DESTINATION_POINT.getErrorMessage(); + } + } else {// 拣选出库 + if (standService.validateStand(taskOutRequest.getDestinationPoint(), 3)) { + return TaskOutValidationEnum.ERROR_PICK_STAND.getErrorMessage(); + } + } + // 验证物料信息 + if (StringUtils.isNotEmpty(taskOutRequest.getGoodsId())) { + if (taskOutRequest.getGoodsNum() == null || taskOutRequest.getGoodsNum().compareTo(BigDecimal.ZERO) <= 0) { + return TaskOutValidationEnum.ERROR_GOODS_NUM.getErrorMessage(); + } + // 查询库存信息 + LambdaQueryWrapper stockQueryWrapper = new LambdaQueryWrapper() + .apply("goods_related -> '$.goodsId' = {0}", taskOutRequest.getGoodsId()) + .apply("goods_related -> '$.remainNum' > 0") + .eq(StringUtils.isNotEmpty(taskOutRequest.getVehicleId()), Stock::getVehicleId, taskOutRequest.getVehicleId()) + .eq(StringUtils.isNotEmpty(taskOutRequest.getOriginPoint()), Stock::getLocationId, taskOutRequest.getOriginPoint()); + if (!stockService.exists(stockQueryWrapper)) { + return TaskOutValidationEnum.NO_STOCK.getErrorMessage(); + } + } + return TaskOutValidationEnum.OK.getErrorMessage(); + } } \ No newline at end of file diff --git a/src/main/java/com/wms/entity/app/dto/TaskDto.java b/src/main/java/com/wms/entity/app/dto/TaskDto.java index c1bb74b..fb82ef7 100644 --- a/src/main/java/com/wms/entity/app/dto/TaskDto.java +++ b/src/main/java/com/wms/entity/app/dto/TaskDto.java @@ -67,4 +67,16 @@ public class TaskDto { * 物料相关信息 */ private TaskDetailInfo goodsRelated; + /** + * 前置任务号 + */ + private String preTask; + /** + * 是否拣选 + */ + private Integer isPicking; + /** + * 拣选站台 + */ + private String pickStand; } diff --git a/src/main/java/com/wms/entity/app/dto/TaskRecordDto.java b/src/main/java/com/wms/entity/app/dto/TaskRecordDto.java index 4365cbd..df58e5c 100644 --- a/src/main/java/com/wms/entity/app/dto/TaskRecordDto.java +++ b/src/main/java/com/wms/entity/app/dto/TaskRecordDto.java @@ -64,4 +64,16 @@ public class TaskRecordDto { * 物料相关 */ private TaskDetailInfo goodsRelated; + /** + * 前置任务号 + */ + private String preTask; + /** + * 是否拣选 + */ + private Integer isPicking; + /** + * 拣选站台 + */ + private String pickStand; } diff --git a/src/main/java/com/wms/entity/app/request/TaskOutRequest.java b/src/main/java/com/wms/entity/app/request/TaskOutRequest.java new file mode 100644 index 0000000..97cd8b0 --- /dev/null +++ b/src/main/java/com/wms/entity/app/request/TaskOutRequest.java @@ -0,0 +1,28 @@ +package com.wms.entity.app.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +@ApiModel(value = "出库请求") +public class TaskOutRequest { + @ApiModelProperty(value ="物料编号") + private String goodsId; + @ApiModelProperty(value ="数量") + private BigDecimal goodsNum; + @ApiModelProperty(value ="载具号") + private String vehicleId; + @ApiModelProperty(value ="起始库位") + private String originPoint; + @ApiModelProperty(value ="终点站台") + private String destinationPoint; + @ApiModelProperty(value ="用户名") + private String userName; + @ApiModelProperty(value ="是否拣选") + private Integer isPicking; + @ApiModelProperty(value ="拣选站台") + private String pickStand; +} diff --git a/src/main/java/com/wms/entity/table/Task.java b/src/main/java/com/wms/entity/table/Task.java index 82e659a..6212bd8 100644 --- a/src/main/java/com/wms/entity/table/Task.java +++ b/src/main/java/com/wms/entity/table/Task.java @@ -86,4 +86,19 @@ public class Task { */ @TableField(value = "goods_related", typeHandler = Fastjson2TypeHandler.class) private TaskDetailInfo goodsRelated; + /** + * 前置任务 + */ + @TableField(value = "pre_task") + private String preTask; + /** + * 是否拣选 + */ + @TableField(value = "is_picking") + private Integer isPicking; + /** + * 拣选站台 + */ + @TableField(value = "pick_stand") + private String pickStand; } diff --git a/src/main/java/com/wms/entity/table/TaskRecord.java b/src/main/java/com/wms/entity/table/TaskRecord.java index 4163ac7..8dd63cb 100644 --- a/src/main/java/com/wms/entity/table/TaskRecord.java +++ b/src/main/java/com/wms/entity/table/TaskRecord.java @@ -83,4 +83,19 @@ public class TaskRecord { */ @TableField(value = "goods_related", typeHandler = Fastjson2TypeHandler.class) private TaskDetailInfo goodsRelated; + /** + * 前置任务 + */ + @TableField(value = "pre_task") + private String preTask; + /** + * 是否拣选 + */ + @TableField(value = "is_picking") + private Integer isPicking; + /** + * 拣选站台 + */ + @TableField(value = "pick_stand") + private String pickStand; } diff --git a/src/main/java/com/wms/service/LocationService.java b/src/main/java/com/wms/service/LocationService.java index 7f6e46c..177448f 100644 --- a/src/main/java/com/wms/service/LocationService.java +++ b/src/main/java/com/wms/service/LocationService.java @@ -12,8 +12,8 @@ public interface LocationService extends IService { /** * 查找一个可用库位 * @param inPoint 入库站点 - * @return 结果 - * nextLocationId, preTaskId + * @param goodsId 物料编号--可选 + * @return 结果 nextLocationId, preTaskId */ - Map getOneLocation(String inPoint); + Map getOneLocation(String inPoint, String goodsId); } diff --git a/src/main/java/com/wms/service/TaskService.java b/src/main/java/com/wms/service/TaskService.java index 1477833..3a84cc5 100644 --- a/src/main/java/com/wms/service/TaskService.java +++ b/src/main/java/com/wms/service/TaskService.java @@ -1,8 +1,17 @@ package com.wms.service; import com.baomidou.mybatisplus.extension.service.IService; +import com.wms.entity.app.dto.TaskDto; import com.wms.entity.table.Task; +/** + * 任务服务 + */ public interface TaskService extends IService { - + /** + * 生成移库任务 + * @param locationId 要出库的库位号 + * @return 深度-1的移库任务 + */ + TaskDto genMoveTask(String locationId); } diff --git a/src/main/java/com/wms/service/serviceImplements/LocationServiceImplements.java b/src/main/java/com/wms/service/serviceImplements/LocationServiceImplements.java index 59513e0..3fdf4f2 100644 --- a/src/main/java/com/wms/service/serviceImplements/LocationServiceImplements.java +++ b/src/main/java/com/wms/service/serviceImplements/LocationServiceImplements.java @@ -2,22 +2,22 @@ package com.wms.service.serviceImplements; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.wms.constants.enums.StockStatus; import com.wms.entity.table.Location; import com.wms.entity.table.Stand; +import com.wms.entity.table.Stock; import com.wms.entity.table.Task; import com.wms.mapper.LocationMapper; import com.wms.service.LocationService; import com.wms.service.StandService; +import com.wms.service.StockService; import com.wms.service.TaskService; import com.wms.utils.StringUtils; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; @Service @RequiredArgsConstructor(onConstructor = @__(@Autowired)) @@ -34,15 +34,20 @@ public class LocationServiceImplements extends ServiceImpl getOneLocation(String inPoint) { + public Map getOneLocation(String inPoint, String goodsId) { Map resultMap = new HashMap<>(); // 查找对应站台 LambdaQueryWrapper locationQueryWrapper = new LambdaQueryWrapper() @@ -60,85 +65,127 @@ public class LocationServiceImplements extends ServiceImpl availableLocations = locationMapper.selectList(locationQueryWrapper); - for (Location oneAvailableLocation : availableLocations) { - LambdaQueryWrapper haveTaskQueryWrapper = new LambdaQueryWrapper() - .select(Location::getLocationId) - .eq(Location::getWRow, oneAvailableLocation.getWRow()) - .eq(Location::getWCol, oneAvailableLocation.getWCol()) - .eq(Location::getWLayer, oneAvailableLocation.getWLayer()); - List haveTaskLocations = locationMapper.selectList(haveTaskQueryWrapper); - // 判断当前排列层的库位是否有出库或者移库任务 - for (Location havaTaskLocation : haveTaskLocations) { - LambdaQueryWrapper taskQueryWrapper = new LambdaQueryWrapper() - .select(Task::getTaskId) - .eq(Task::getOrigin, havaTaskLocation.getLocationId()); - if (taskService.count(taskQueryWrapper) > 0) { - return null; - } - } - // 判断是否深度+1有入库任务 - haveTaskQueryWrapper.clear(); - LambdaQueryWrapper plusOneDepthLocationQueryWrapper = new LambdaQueryWrapper() - .select(Location::getLocationId) - .eq(Location::getWDepth, oneAvailableLocation.getWDepth() + 1) - .eq(Location::getWRow, oneAvailableLocation.getWRow()) - .eq(Location::getWCol, oneAvailableLocation.getWCol()) - .eq(Location::getWLayer, oneAvailableLocation.getWLayer()); - Location plusOneDepthLocation = locationMapper.selectOne(plusOneDepthLocationQueryWrapper); - if (plusOneDepthLocation == null) { - resultMap.put("nextLocationId", oneAvailableLocation.getLocationId()); - return resultMap; - } else { - LambdaQueryWrapper taskQueryWrapper = new LambdaQueryWrapper() - .select(Task::getTaskId) - .eq(Task::getDestination, plusOneDepthLocation.getLocationId()); - Task plusOneDepthTask = taskService.getOne(taskQueryWrapper); - if (plusOneDepthTask != null) { - resultMap.put("nextLocationId", oneAvailableLocation.getLocationId()); - resultMap.put("preTaskId", plusOneDepthTask.getTaskId()); - return resultMap; - } - } - } + return getOneLocationByEquipmentId(resultMap, locationQueryWrapper, equipmentId); } else {// 未指定设备号 // TODO // 选择最近未使用的设备 - LambdaQueryWrapper standQueryWrapper = new LambdaQueryWrapper() + LambdaQueryWrapper LRUStandQueryWrapper = new LambdaQueryWrapper() .select(Stand::getStandId, Stand::getEquipmentId) .eq(Stand::getStandStatus, 0) .eq(Stand::getIsLock, 0) .eq(Stand::getStandType, 3) .orderByAsc(Stand::getLastUseTime); - Stand queryStand = standService.getOne(standQueryWrapper); - if (queryStand != null && queryStand.getEquipmentId() != null) { - locationQueryWrapper.eq(Location::getEquipmentId, queryStand.getEquipmentId()); + List LRUStands = standService.list(LRUStandQueryWrapper); + if (LRUStands.isEmpty()) { + return null; } else { - locationQueryWrapper.eq(Location::getEquipmentId, 1); + if (StringUtils.isNotEmpty(goodsId)) {// 需要根据物料编号做出区分 + equipmentId = selectEquipmentByLRUAndGoods(LRUStands, goodsId); + } else { + equipmentId = LRUStands.get(0).getEquipmentId(); + } + return getOneLocationByEquipmentId(resultMap, locationQueryWrapper, equipmentId); } } + } + + /** + * 根据设备号查找库位 + * @param resultMap 结果集 + * @param locationQueryWrapper 查询条件 + * @param equipmentId 设备号 + * @return 查询结果 + */ + private Map getOneLocationByEquipmentId(Map resultMap, LambdaQueryWrapper locationQueryWrapper, int equipmentId) { + locationQueryWrapper.eq(Location::getEquipmentId, equipmentId); locationQueryWrapper.orderByDesc(Location::getWDepth) .orderByAsc(List.of(Location::getWCol, Location::getWLayer, Location::getWRow)); - - Location oneAvailableLocation = locationMapper.selectOne(locationQueryWrapper); - if (oneAvailableLocation != null) { - - } else { - + List availableLocations = locationMapper.selectList(locationQueryWrapper); + for (Location oneAvailableLocation : availableLocations) { + LambdaQueryWrapper haveTaskQueryWrapper = new LambdaQueryWrapper() + .select(Location::getLocationId) + .eq(Location::getWRow, oneAvailableLocation.getWRow()) + .eq(Location::getWCol, oneAvailableLocation.getWCol()) + .eq(Location::getWLayer, oneAvailableLocation.getWLayer()); + List haveTaskLocations = locationMapper.selectList(haveTaskQueryWrapper); + // 判断当前排列层的库位是否有出库或者移库任务 + for (Location havaTaskLocation : haveTaskLocations) { + LambdaQueryWrapper taskQueryWrapper = new LambdaQueryWrapper() + .select(Task::getTaskId) + .eq(Task::getOrigin, havaTaskLocation.getLocationId()); + if (taskService.count(taskQueryWrapper) > 0) { + return null; + } + } + // 判断是否深度+1有入库任务 + haveTaskQueryWrapper.clear(); + LambdaQueryWrapper plusOneDepthLocationQueryWrapper = new LambdaQueryWrapper() + .select(Location::getLocationId) + .eq(Location::getWDepth, oneAvailableLocation.getWDepth() + 1) + .eq(Location::getWRow, oneAvailableLocation.getWRow()) + .eq(Location::getWCol, oneAvailableLocation.getWCol()) + .eq(Location::getWLayer, oneAvailableLocation.getWLayer()); + Location plusOneDepthLocation = locationMapper.selectOne(plusOneDepthLocationQueryWrapper); + if (plusOneDepthLocation == null) { + resultMap.put("nextLocationId", oneAvailableLocation.getLocationId()); + return resultMap; + } else { + LambdaQueryWrapper taskQueryWrapper = new LambdaQueryWrapper() + .select(Task::getTaskId) + .eq(Task::getDestination, plusOneDepthLocation.getLocationId()); + Task plusOneDepthTask = taskService.getOne(taskQueryWrapper); + if (plusOneDepthTask != null) { + resultMap.put("nextLocationId", oneAvailableLocation.getLocationId()); + resultMap.put("preTaskId", plusOneDepthTask.getTaskId()); + return resultMap; + } + } } - // 查找低一个深度的库位 - - - - return null; } + + /** + * 根据最近最久未使用加物料来判断应该使用哪个设备 + * @param LRUStands 符合的设备 + * @param goodsId 物料编号 + * @return 设备号 + */ + private int selectEquipmentByLRUAndGoods(List LRUStands, String goodsId) { + int equipmentId = -1; + List equipmentIds = new ArrayList<>(); + List tasks = taskService.list(new LambdaQueryWrapper() + .select(Task::getDestination) + .apply("goods_related -> '$.goods_id' = {0}", goodsId) + .eq(Task::getTaskType, 1)); + for (Task task : tasks) { + Location tempLocation = locationMapper.selectOne(new LambdaQueryWrapper().eq(Location::getLocationId, task.getDestination())); + if (tempLocation != null && !equipmentIds.contains(tempLocation.getEquipmentId())) { + equipmentIds.add(tempLocation.getEquipmentId()); + } + } + List stocks = stockService.list(new LambdaQueryWrapper() + .select(Stock::getLocationId) + .apply("goods_related -> '$.goods_id' = {0}", goodsId) + .eq(Stock::getStockStatus, StockStatus.OK.getCode())); + for (Stock stock : stocks) { + Location tempLocation = locationMapper.selectOne(new LambdaQueryWrapper().eq(Location::getLocationId, stock.getLocationId())); + if (tempLocation != null && !equipmentIds.contains(tempLocation.getEquipmentId())) { + equipmentIds.add(tempLocation.getEquipmentId()); + } + } + for (Stand lruStand : LRUStands) { + if (!equipmentIds.contains(lruStand.getEquipmentId())) { + equipmentId = lruStand.getEquipmentId(); + break; + } + } + if (equipmentId == -1) { + equipmentId = LRUStands.get(0).getEquipmentId(); + } + return equipmentId; + } } diff --git a/src/main/java/com/wms/service/serviceImplements/StandServiceImplements.java b/src/main/java/com/wms/service/serviceImplements/StandServiceImplements.java index eb21d86..e791f95 100644 --- a/src/main/java/com/wms/service/serviceImplements/StandServiceImplements.java +++ b/src/main/java/com/wms/service/serviceImplements/StandServiceImplements.java @@ -35,10 +35,7 @@ public class StandServiceImplements extends ServiceImpl impl lambdaQueryWrapper.eq(Stand::getAllowIn, 1);// 入库 } else if (taskType == 2) {// 出库 lambdaQueryWrapper.eq(Stand::getAllowOut, 1);// 出库 - } else if (taskType == 4) {// 盘点 - lambdaQueryWrapper.eq(Stand::getAllowIn, 1);// 入库 - lambdaQueryWrapper.eq(Stand::getAllowOut, 1);// 出库 - } else if (taskType == 3) {// 拣选 + } else if (taskType == 3 || taskType == 4) {// 拣选或者盘点 lambdaQueryWrapper.eq(Stand::getStandType, 2); } else { return false; diff --git a/src/main/java/com/wms/service/serviceImplements/TaskServiceImplements.java b/src/main/java/com/wms/service/serviceImplements/TaskServiceImplements.java index 8fc4807..185ee0a 100644 --- a/src/main/java/com/wms/service/serviceImplements/TaskServiceImplements.java +++ b/src/main/java/com/wms/service/serviceImplements/TaskServiceImplements.java @@ -1,16 +1,52 @@ package com.wms.service.serviceImplements; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.wms.entity.app.dto.TaskDto; +import com.wms.entity.table.Location; import com.wms.entity.table.Task; import com.wms.mapper.TaskMapper; +import com.wms.service.LocationService; import com.wms.service.TaskService; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +/** + * 任务服务的实现类 + */ @Service @RequiredArgsConstructor(onConstructor = @__(@Autowired)) public class TaskServiceImplements extends ServiceImpl implements TaskService { - + /** + * 任务mapper + */ private final TaskMapper taskMapper; + /** + * 库位服务 + */ + private final LocationService locationService; + + @Override + public TaskDto genMoveTask(String locationId) { + Location outLocation = locationService.getOne(new LambdaQueryWrapper().eq(Location::getLocationId, locationId)); + if (outLocation != null) { + if (outLocation.getWDepth() == 1) { + return null; + } else { + // 生成当前深度-1的库位的移库任务 + Location depthMinus1Location = locationService.getOne(new LambdaQueryWrapper().eq(Location::getLocationId, outLocation.getLocationId())); + // 查询这个位置 + // 生成当前深度-2的库位的移库任务,即当前深度-1的库位作为参数 + genMoveTask(depthMinus1Location.getLocationId()); + } + } + + + + + + + return null; + } }