diff --git a/src/main/java/com/wms/constants/enums/TaskOutValidationEnum.java b/src/main/java/com/wms/constants/enums/TaskOutValidationEnum.java index c56d4e8..9d793df 100644 --- a/src/main/java/com/wms/constants/enums/TaskOutValidationEnum.java +++ b/src/main/java/com/wms/constants/enums/TaskOutValidationEnum.java @@ -8,7 +8,10 @@ public enum TaskOutValidationEnum { NO_REQUEST_BODY("请求参数为空"), LACK_REQUIRED_PARAM("缺少必须参数:物料、载具、起始库位至少需要一个"), ERROR_VEHICLE_ID("不存在的载具号"), + ERROR_VEHICLE_STATUS("载具不是在库状态,不可出库"), ERROR_ORIGIN_POINT("错误的起始库位"), + LOCKED_LOCATION("库位锁定,无法出库"), + ERROR_ORIGIN_POINT_STATUS("起始库位无货,不允许出库"), ERROR_DESTINATION_POINT("错误的终点站台"), NO_PICK_STAND("拣选任务无拣选站台"), ERROR_PICK_STAND("错误的拣选站台"), diff --git a/src/main/java/com/wms/constants/enums/TaskResultValidationEnum.java b/src/main/java/com/wms/constants/enums/TaskResultValidationEnum.java new file mode 100644 index 0000000..d2b7d04 --- /dev/null +++ b/src/main/java/com/wms/constants/enums/TaskResultValidationEnum.java @@ -0,0 +1,20 @@ +package com.wms.constants.enums; + +/** + * 任务结果反馈验证信息枚举 + */ +public enum TaskResultValidationEnum { + OK(""), + NO_REQUEST_BODY("请求参数为空。"), + LACK_REQUIRED_PARAM("缺少必须参数:任务号、载具号、任务状态。"), + ERROR_TASK_GROUP("反馈的任务号错误,查询不到对应任务"), + ERROR_TASK_STATUS("反馈的任务状态错误"); + + private final String errorMessage; + TaskResultValidationEnum(String errorMessage) { + this.errorMessage = errorMessage; + } + public String getErrorMessage() { + return errorMessage; + } +} diff --git a/src/main/java/com/wms/constants/enums/TaskType.java b/src/main/java/com/wms/constants/enums/TaskType.java index c6d126a..4da6a10 100644 --- a/src/main/java/com/wms/constants/enums/TaskType.java +++ b/src/main/java/com/wms/constants/enums/TaskType.java @@ -6,7 +6,7 @@ package com.wms.constants.enums; public enum TaskType { IN(1, "入库"), OUT(2, "出库"), - INVENTORY(3, "盘点"), + INVENTORY(10, "盘点"), MOVE(9, "移库"); private final Integer code; diff --git a/src/main/java/com/wms/constants/enums/VehicleStatus.java b/src/main/java/com/wms/constants/enums/VehicleStatus.java index 7a17731..b670b86 100644 --- a/src/main/java/com/wms/constants/enums/VehicleStatus.java +++ b/src/main/java/com/wms/constants/enums/VehicleStatus.java @@ -6,7 +6,8 @@ package com.wms.constants.enums; public enum VehicleStatus { IN(1, "入库中"), ON(2, "在库中"), - OUT(3, "出库中"); + OUT(3, "出库中"), + MOVE(4, "移库中"); private final Integer code; diff --git a/src/main/java/com/wms/constants/enums/WmsTaskStatus.java b/src/main/java/com/wms/constants/enums/WmsTaskStatus.java index f48b134..bf00db3 100644 --- a/src/main/java/com/wms/constants/enums/WmsTaskStatus.java +++ b/src/main/java/com/wms/constants/enums/WmsTaskStatus.java @@ -8,7 +8,10 @@ public enum WmsTaskStatus { NEW(0, "任务新建,待下发"), WAIT(1, "任务已下发"), RUN(2, "任务开始执行"), - INVENTORY(8, "盘点中"), + OUT_FINISHED(3, "出库完成"), + TRANS(4, "环线运输"), + PICKING(8, "键选中"), + INVENTORY(9, "盘点中"), FINISH(100, "任务完成"), CANCEL(998, "任务取消"), EXCEPTION(999, "任务异常"); diff --git a/src/main/java/com/wms/controller/LocationController.java b/src/main/java/com/wms/controller/LocationController.java index c2f86dd..fa97cfe 100644 --- a/src/main/java/com/wms/controller/LocationController.java +++ b/src/main/java/com/wms/controller/LocationController.java @@ -53,7 +53,7 @@ public class LocationController { /** * 料箱服务 */ - private final VehicleService vehicleService; + private final VehicleService vehicleService; /** * 请求头部信息 */ diff --git a/src/main/java/com/wms/controller/TaskController.java b/src/main/java/com/wms/controller/TaskController.java index b285363..39b28b9 100644 --- a/src/main/java/com/wms/controller/TaskController.java +++ b/src/main/java/com/wms/controller/TaskController.java @@ -1,19 +1,20 @@ package com.wms.controller; +import cn.hutool.core.bean.BeanUtil; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.wms.annotation.MyLog; import com.wms.constants.enums.*; import com.wms.entity.app.*; +import com.wms.entity.app.dto.TaskDto; import com.wms.entity.app.dto.extend.TaskDetailInfo; +import com.wms.entity.app.dto.extend.VehicleDetailInfo; 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.entity.app.request.WcsTaskResultRequest; +import com.wms.entity.table.*; import com.wms.service.*; import com.wms.utils.HttpUtils; import com.wms.utils.StringUtils; @@ -22,6 +23,7 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Isolation; @@ -113,23 +115,31 @@ public class TaskController { 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")) { + Map resultMap = locationService.getOneLocation(taskInRequest.getOriginPoint(), null); + if (resultMap.isEmpty() || !resultMap.containsKey("nextLocationId")) { logger.error("暂无可用库位"); response.setCode(ResponseCode.ERROR.getCode()); - response.setMessage("入库请求验证错误!" + validationInfo); + response.setMessage("暂无可用库位!"); return convertJsonString(response); } else { - Location nextLocation = locationService.getOne(new LambdaQueryWrapper().eq(Location::getLocationId, nextLocationMap.get("nextLocationId"))); + Location nextLocation = locationService.getOne(new LambdaQueryWrapper().eq(Location::getLocationId, resultMap.get("nextLocationId"))); LambdaUpdateWrapper updateLocationWrapper = new LambdaUpdateWrapper() .set(Location::getLocationStatus, LocationStatus.OCCUPY.getCode()) + .set(Location::getVehicleId, taskInRequest.getVehicleId()) .eq(Location::getLocationId, nextLocation.getLocationId()) .eq(Location::getLocationStatus, LocationStatus.EMPTY.getCode()); if (locationService.update(updateLocationWrapper)) { + nextLocationMap = resultMap; break; } } } + if (nextLocationMap.isEmpty() || !nextLocationMap.containsKey("nextLocationId")) { + logger.error("暂无可用库位"); + response.setCode(ResponseCode.ERROR.getCode()); + response.setMessage("暂无可用库位!"); + return convertJsonString(response); + } // 生成入库任务 String saveTaskResult = ""; if (taskInRequest.getGoodsList().isEmpty()) {// 空托入库 @@ -141,6 +151,7 @@ public class TaskController { // 回退库位锁定 locationService.update(new LambdaUpdateWrapper() .set(Location::getLocationStatus, LocationStatus.EMPTY.getCode()) + .set(Location::getVehicleId, "") .eq(Location::getLocationId, nextLocationMap.get("nextLocationId")) .eq(Location::getLocationStatus, LocationStatus.OCCUPY.getCode())); } @@ -162,12 +173,13 @@ public class TaskController { /** * 添加空入库任务 + * * @param taskInRequest 入库请求 - * @param locationId 库位id - * @param preTaskId 前置任务 + * @param locationId 库位id + * @param preTaskId 前置任务 * @return 添加结果 */ - private String genEmptyInTask (TaskInRequest taskInRequest, String locationId, String preTaskId) { + private String genEmptyInTask(TaskInRequest taskInRequest, String locationId, String preTaskId) { String result = ""; Task tempInTask = new Task(); tempInTask.setTaskId(generateId("RK_")); @@ -196,12 +208,13 @@ public class TaskController { /** * 添加入库任务 + * * @param taskInRequest 入库请求 - * @param locationId 库位号 - * @param preTaskId 前置任务 + * @param locationId 库位号 + * @param preTaskId 前置任务 * @return 添加结果 */ - private String genGoodsInTask (TaskInRequest taskInRequest, String locationId, String preTaskId) { + private String genGoodsInTask(TaskInRequest taskInRequest, String locationId, String preTaskId) { String result = ""; String taskGroupId = generateId(""); List tempTasks = new ArrayList<>(); @@ -225,6 +238,8 @@ public class TaskController { // TODO 物料信息需要完善 goodsRelatedInfo.setGoodsId(goodsInRequest.getGoodsId()); goodsRelatedInfo.setGoodsName(""); + goodsRelatedInfo.setOpNum(goodsInRequest.getGoodsNum()); + goodsRelatedInfo.setOriginNum(BigDecimal.ZERO); tempInTask.setGoodsRelated(goodsRelatedInfo); tempTasks.add(tempInTask); @@ -243,6 +258,7 @@ public class TaskController { /** * 验证入库请求 + * * @param taskInRequest 入库请求 * @return 验证结果---空为验证通过,否则输出错误信息 */ @@ -319,27 +335,36 @@ public class TaskController { if (!Objects.equals(validationInfo, TaskInValidationEnum.OK.getErrorMessage())) { logger.error("出库请求验证错误!{}", validationInfo); response.setCode(ResponseCode.ERROR.getCode()); - response.setMessage("出库请求验证错误!" + validationInfo); + response.setMessage("出库请求验证错误:" + validationInfo); return convertJsonString(response); } // 没有物料,单纯载具或者库位出库 if (StringUtils.isEmpty(taskOutRequest.getGoodsId())) { - // 生成载具出库任务 - + String genResult = genVehicleLocationOutTask(taskOutRequest); + if (!genResult.equals("")) { + logger.error("出库错误!{}", genResult); + response.setCode(ResponseCode.ERROR.getCode()); + response.setMessage("出库错误:" + genResult); + return convertJsonString(response); + } + } else { + String genResult = genGoodsOutTask(taskOutRequest); + if (!genResult.equals("")) { + logger.error("出库错误!{}", genResult); + response.setCode(ResponseCode.ERROR.getCode()); + response.setMessage("出库错误:" + genResult); + return convertJsonString(response); + } } - // 查询库存 - LambdaQueryWrapper stockLambdaQueryWrapper = new LambdaQueryWrapper() - .eq(Stock::getGoodsId, taskOutRequest.getGoodsId()); - // 生成出库任务 - logger.info("接收入库请求成功!"); + logger.info("处理出库请求成功!"); response.setCode(ResponseCode.OK.getCode()); - response.setMessage("接收入库请求成功!"); + response.setMessage("处理出库请求成功!"); return convertJsonString(response); } catch (Exception e) { // 回滚事务 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); - logger.error("发生异常:{}", e.getMessage()); + logger.error("发生异常:{}", convertJsonString(e)); // 返回其他异常 response.setCode(ResponseCode.ERROR.getCode()); response.setMessage("发生意料之外的错误"); @@ -350,15 +375,207 @@ public class TaskController { /** * 生成载具或库位出库任务 + * * @param taskOutRequest 出库请求 * @return 结果 */ private String genVehicleLocationOutTask(TaskOutRequest taskOutRequest) { + // 查询对应载具 + if (StringUtils.isNotEmpty(taskOutRequest.getVehicleId())) { + Vehicle currentVehicle = vehicleService.getOne(new LambdaQueryWrapper().eq(Vehicle::getVehicleId, taskOutRequest.getVehicleId())); + // 创建空出库任务 + Task vehicleOutTask = new Task(); + vehicleOutTask.setTaskId(generateId("CK_")); + vehicleOutTask.setTaskType(TaskType.OUT.getCode()); + vehicleOutTask.setTaskGroup(generateId("")); + vehicleOutTask.setTaskStatus(WmsTaskStatus.NEW.getCode()); + vehicleOutTask.setTaskPriority(1); + TaskDto moveTask = taskService.genMoveTask(currentVehicle.getCurrentLocation()); + if (moveTask != null) { + if (moveTask.getTaskId().equals("LOCKED")) { + return "外层库位上锁,无法出库"; + } + vehicleOutTask.setPreTask(moveTask.getTaskId()); + } + vehicleOutTask.setVehicleId(taskOutRequest.getVehicleId()); + vehicleOutTask.setUserName(taskOutRequest.getUserName()); + vehicleOutTask.setOrigin(currentVehicle.getCurrentLocation()); + vehicleOutTask.setDestination(taskOutRequest.getDestinationPoint()); + vehicleOutTask.setIsPicking(taskOutRequest.getIsPicking()); + vehicleOutTask.setPickStand(taskOutRequest.getPickStand()); + vehicleOutTask.setCreateTime(LocalDateTime.now()); + taskService.save(vehicleOutTask); + // 对应载具所有库存上锁 + stockService.update(new LambdaUpdateWrapper() + .set(Stock::getStockStatus, StockStatus.OUT.getCode()) + .eq(Stock::getVehicleId, taskOutRequest.getVehicleId())); + // 对应载具状态设置 + vehicleService.update(new LambdaUpdateWrapper() + .set(Vehicle::getVehicleStatus, VehicleStatus.OUT.getCode()) + .eq(Vehicle::getVehicleId, taskOutRequest.getVehicleId())); + } else { + // 查找对应库位 + Location currentLocation = locationService.getOne(new LambdaQueryWrapper().eq(Location::getLocationId, taskOutRequest.getOriginPoint())); + // 创建空出库任务 + Task vehicleOutTask = new Task(); + vehicleOutTask.setTaskId(generateId("CK_")); + vehicleOutTask.setTaskType(TaskType.OUT.getCode()); + vehicleOutTask.setTaskGroup(generateId("")); + vehicleOutTask.setTaskStatus(WmsTaskStatus.NEW.getCode()); + vehicleOutTask.setTaskPriority(1); + TaskDto moveTask = taskService.genMoveTask(currentLocation.getLocationId()); + if (moveTask != null) { + if (moveTask.getTaskId().equals("LOCKED")) { + return "外层库位上锁,无法出库"; + } + vehicleOutTask.setPreTask(moveTask.getTaskId()); + } + vehicleOutTask.setVehicleId(currentLocation.getVehicleId()); + vehicleOutTask.setUserName(taskOutRequest.getUserName()); + vehicleOutTask.setOrigin(currentLocation.getLocationId()); + vehicleOutTask.setDestination(taskOutRequest.getDestinationPoint()); + vehicleOutTask.setIsPicking(taskOutRequest.getIsPicking()); + vehicleOutTask.setPickStand(taskOutRequest.getPickStand()); + vehicleOutTask.setCreateTime(LocalDateTime.now()); + taskService.save(vehicleOutTask); + // 对应库位所有库存上锁 + stockService.update(new LambdaUpdateWrapper() + .set(Stock::getStockStatus, StockStatus.OUT.getCode()) + .eq(Stock::getLocationId, taskOutRequest.getOriginPoint())); + // 对应库位状态设置 + vehicleService.update(new LambdaUpdateWrapper() + .set(Vehicle::getVehicleStatus, VehicleStatus.OUT.getCode()) + .eq(Vehicle::getCurrentLocation, taskOutRequest.getOriginPoint())); + } + return ""; + } + /** + * 生成物料出库任务 + * + * @param taskOutRequest 出库请求 + * @return 结果 + */ + private String genGoodsOutTask(TaskOutRequest taskOutRequest) { + // 查询库存 + 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()); + List stocks = stockService.list(stockQueryWrapper); + List goodsOutTasks = new ArrayList<>(); + BigDecimal needNum = taskOutRequest.getGoodsNum(); + for (Stock stock : stocks) { + if (Objects.equals(stock.getStockStatus(), StockStatus.OK.getCode())) {// 库存状态正常的情况 + // 悲观锁,锁定库存状态---同一载具下的库存 + boolean lockStocksFlag = stockService.update(new LambdaUpdateWrapper() + .set(Stock::getStockStatus, StockStatus.OUT.getCode()) + .eq(Stock::getVehicleId, stock.getVehicleId()) + .eq(Stock::getStockStatus, StockStatus.OK.getCode())); + + // 锁定载具状态 + boolean lockVehicleFlag = vehicleService.update(new LambdaUpdateWrapper() + .set(Vehicle::getVehicleStatus, VehicleStatus.OUT.getCode()) + .eq(Vehicle::getVehicleId, stock.getVehicleId()) + .eq(Vehicle::getVehicleStatus, VehicleStatus.ON)); + if (!lockStocksFlag || !lockVehicleFlag) { + // 释放锁 + stockService.update(new LambdaUpdateWrapper() + .set(Stock::getStockStatus, StockStatus.OK.getCode()) + .eq(Stock::getVehicleId, stock.getVehicleId()) + .eq(Stock::getStockStatus, StockStatus.OK.getCode())); + vehicleService.update(new LambdaUpdateWrapper() + .set(Vehicle::getVehicleStatus, VehicleStatus.ON.getCode()) + .eq(Vehicle::getVehicleId, stock.getVehicleId())); + continue; + } + // 创建出库任务 + Task vehicleOutTask = new Task(); + vehicleOutTask.setTaskId(generateId("CK_")); + vehicleOutTask.setTaskType(TaskType.OUT.getCode()); + vehicleOutTask.setTaskGroup(generateId("")); + vehicleOutTask.setTaskStatus(WmsTaskStatus.NEW.getCode()); + vehicleOutTask.setTaskPriority(1); + TaskDto moveTask = taskService.genMoveTask(stock.getLocationId()); + if (moveTask != null) { + if (moveTask.getTaskId().equals("LOCKED")) { + continue; + } + vehicleOutTask.setPreTask(moveTask.getTaskId()); + } + vehicleOutTask.setVehicleId(stock.getVehicleId()); + vehicleOutTask.setUserName(taskOutRequest.getUserName()); + vehicleOutTask.setOrigin(stock.getLocationId()); + vehicleOutTask.setDestination(taskOutRequest.getDestinationPoint()); + vehicleOutTask.setIsPicking(taskOutRequest.getIsPicking()); + vehicleOutTask.setPickStand(taskOutRequest.getPickStand()); + vehicleOutTask.setCreateTime(LocalDateTime.now()); + // TODO 设定物料相关信息 需要完善 + TaskDetailInfo taskDetailInfo = new TaskDetailInfo(); + taskDetailInfo.setGoodsId(stock.getGoodsRelated().getGoodsId()); + taskDetailInfo.setGoodsName(stock.getGoodsRelated().getGoodsName()); + taskDetailInfo.setOpNum(needNum.compareTo(stock.getGoodsRelated().getRemainNum()) > 0 ? stock.getGoodsRelated().getRemainNum() : needNum); + taskDetailInfo.setOriginNum(stock.getGoodsRelated().getRemainNum()); + vehicleOutTask.setGoodsRelated(taskDetailInfo); + goodsOutTasks.add(vehicleOutTask); + needNum = needNum.subtract(stock.getGoodsRelated().getRemainNum()); + } else if (Objects.equals(stock.getStockStatus(), StockStatus.OUT.getCode())) { + // 查询到当前当前载具对应的任务,并同步 + Task sameVehicleTask = taskService.getOne(new LambdaQueryWrapper() + .eq(Task::getVehicleId, stock.getVehicleId())); + // 创建出库任务 + Task vehicleOutTask = new Task(); + vehicleOutTask.setTaskId(generateId("CK_")); + vehicleOutTask.setTaskType(TaskType.OUT.getCode()); + if (sameVehicleTask != null) { + vehicleOutTask.setTaskGroup(sameVehicleTask.getTaskGroup()); + vehicleOutTask.setTaskStatus(sameVehicleTask.getTaskStatus()); + vehicleOutTask.setTaskPriority(sameVehicleTask.getTaskPriority()); + vehicleOutTask.setPreTask(sameVehicleTask.getPreTask()); + } else { + vehicleOutTask.setTaskGroup(generateId("")); + vehicleOutTask.setTaskStatus(WmsTaskStatus.NEW.getCode()); + vehicleOutTask.setTaskPriority(1); + TaskDto moveTask = taskService.genMoveTask(stock.getLocationId()); + if (moveTask != null) { + if (moveTask.getTaskId().equals("LOCKED")) { + continue; + } + vehicleOutTask.setPreTask(moveTask.getTaskId()); + } + } + vehicleOutTask.setVehicleId(stock.getVehicleId()); + vehicleOutTask.setUserName(taskOutRequest.getUserName()); + vehicleOutTask.setOrigin(stock.getLocationId()); + vehicleOutTask.setDestination(taskOutRequest.getDestinationPoint()); + vehicleOutTask.setIsPicking(taskOutRequest.getIsPicking()); + vehicleOutTask.setPickStand(taskOutRequest.getPickStand()); + vehicleOutTask.setCreateTime(LocalDateTime.now()); + // TODO 设定物料相关信息 需要完善 + TaskDetailInfo taskDetailInfo = new TaskDetailInfo(); + taskDetailInfo.setGoodsId(stock.getGoodsRelated().getGoodsId()); + taskDetailInfo.setGoodsName(stock.getGoodsRelated().getGoodsName()); + taskDetailInfo.setOpNum(needNum.compareTo(stock.getGoodsRelated().getRemainNum()) > 0 ? stock.getGoodsRelated().getRemainNum() : needNum); + taskDetailInfo.setOriginNum(stock.getGoodsRelated().getRemainNum()); + vehicleOutTask.setGoodsRelated(taskDetailInfo); + goodsOutTasks.add(vehicleOutTask); + needNum = needNum.subtract(stock.getGoodsRelated().getRemainNum()); + } + // 盘点,移库,锁定状态不可使用 + if (needNum.compareTo(BigDecimal.ZERO) <= 0) { + // 库存足够,跳出循环 + break; + } + } + // 添加任务记录表 + taskService.saveBatch(goodsOutTasks); + return ""; } /** * 验证出库请求 + * * @param taskOutRequest 出库请求 * @return 验证结果---空为验证通过,否则输出错误信息 */ @@ -407,7 +624,224 @@ public class TaskController { if (!stockService.exists(stockQueryWrapper)) { return TaskOutValidationEnum.NO_STOCK.getErrorMessage(); } + } else { + if (StringUtils.isNotEmpty(taskOutRequest.getVehicleId())) { + Vehicle currentVehicle = vehicleService.getOne(new LambdaQueryWrapper().eq(Vehicle::getVehicleId, taskOutRequest.getVehicleId())); + Location currentLocation = locationService.getOne(new LambdaQueryWrapper().eq(Location::getLocationId, currentVehicle.getCurrentLocation())); + if (!Objects.equals(currentVehicle.getVehicleStatus(), VehicleStatus.ON.getCode())) { + return TaskOutValidationEnum.ERROR_VEHICLE_STATUS.getErrorMessage(); + } + if (!Objects.equals(currentLocation.getIsLock(), 1)) { + return TaskOutValidationEnum.LOCKED_LOCATION.getErrorMessage(); + } + } else { + Location currentLocation = locationService.getOne(new LambdaQueryWrapper().eq(Location::getLocationId, taskOutRequest.getOriginPoint())); + if (!Objects.equals(currentLocation.getIsLock(), 1)) { + return TaskOutValidationEnum.LOCKED_LOCATION.getErrorMessage(); + } + if (!Objects.equals(currentLocation.getLocationStatus(), LocationStatus.OCCUPY.getCode())) { + return TaskOutValidationEnum.ERROR_ORIGIN_POINT_STATUS.getErrorMessage(); + } + } } return TaskOutValidationEnum.OK.getErrorMessage(); } + + /** + * 接收任务反馈 + * + * @param wcsTaskResultRequest wcs任务反馈请求 + * @return 结果 + */ + @PostMapping("/sendTaskResult") + @ResponseBody + @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) + @MyLog(logTitle = "Wcs任务反馈", logMethod = "sendTaskResult") + public String receiveTaskResult(@RequestBody WcsTaskResultRequest wcsTaskResultRequest) { + logger.info("接收到任务反馈:{},ip地址:{}", JSON.toJSONString(wcsTaskResultRequest), HttpUtils.getIpAddr(servletRequest)); + // 创建响应信息 + ResponseEntity response = new ResponseEntity(); + try { + String validateInfo = validateTaskResult(wcsTaskResultRequest); + if (!Objects.equals(validateInfo, TaskResultValidationEnum.OK.getErrorMessage())) { + logger.error("任务反馈请求验证失败:{}", validateInfo); + // 返回其他异常 + response.setCode(ResponseCode.ERROR.getCode()); + response.setMessage("任务反馈请求验证失败:" + validateInfo); + return convertJsonString(response); + } + // 解析任务号 + List feedBackTasks = taskService.list(new LambdaQueryWrapper().eq(Task::getTaskGroup, wcsTaskResultRequest.getTaskId())); + // 任务状态 + int taskType = feedBackTasks.get(0).getTaskType(); + // 任务状态 + int taskStatus = wcsTaskResultRequest.getTaskStatus(); + // 判断任务状态 + if (taskStatus == WcsTaskStatus.FINISH.getCode()) {// 任务完成 + // TODO 入库任务完成 + if (taskType == TaskType.IN.getCode()) { + // 对所有任务组里面的移库任务进行处理 + for (Task inTask : feedBackTasks) { + if (!Objects.equals(inTask.getTaskType(), TaskType.IN.getCode())) { + // 非入库任务跳过 + continue; + } + // + // 更新库存 + LambdaUpdateWrapper lambdaUpdateWrapperOfStock = new LambdaUpdateWrapper() + .set(Stock::getLocationId, moveTask.getDestination()) + .set(Stock::getStockStatus, StockStatus.OK.getCode()) + .set(Stock::getLastUpdateTime, LocalDateTime.now()) + .set(Stock::getLastUpdateUser, moveTask.getUserName()) + .eq(Stock::getVehicleId, moveTask.getVehicleId()) + .eq(Stock::getStockStatus, StockStatus.MOVE.getCode()); + stockService.update(lambdaUpdateWrapperOfStock); + // 更新载具 + LambdaUpdateWrapper lambdaUpdateWrapperOfVehicle = new LambdaUpdateWrapper() + .set(Vehicle::getVehicleStatus, VehicleStatus.ON.getCode()) + .set(Vehicle::getCurrentLocation, moveTask.getDestination()) + .eq(Vehicle::getVehicleId, moveTask.getVehicleId()) + .eq(Vehicle::getVehicleStatus, VehicleStatus.MOVE.getCode()); + vehicleService.update(lambdaUpdateWrapperOfVehicle); + // 释放原来的库位 + LambdaUpdateWrapper lambdaUpdateWrapperOfLocation = new LambdaUpdateWrapper() + .set(Location::getLocationStatus, LocationStatus.EMPTY.getCode()) + .set(Location::getVehicleId, "") + .eq(Location::getLocationId, moveTask.getOrigin()) + .eq(Location::getLocationStatus, LocationStatus.OCCUPY.getCode()); + locationService.update(lambdaUpdateWrapperOfLocation); + // 添加任务记录 + moveTask.setTaskStatus(WmsTaskStatus.FINISH.getCode()); + moveTask.setFinishTime(LocalDateTime.now()); + taskRecordService.save(BeanUtil.copyProperties(moveTask, TaskRecord.class)); + // 删除移库任务 + taskService.remove(new LambdaQueryWrapper().eq(Task::getTaskId, moveTask.getTaskId())); + } + } + // TODO 出库任务完成 + if (taskType == TaskType.OUT.getCode()) { + // 对所有任务组里面的移库任务进行处理 + for (Task outTask : feedBackTasks) { + if (!Objects.equals(moveTask.getTaskType(), TaskType.MOVE.getCode())) { + // 非移库任务跳过 + continue; + } + // 更新库存 + LambdaUpdateWrapper lambdaUpdateWrapperOfStock = new LambdaUpdateWrapper() + .set(Stock::getLocationId, moveTask.getDestination()) + .set(Stock::getStockStatus, StockStatus.OK.getCode()) + .set(Stock::getLastUpdateTime, LocalDateTime.now()) + .set(Stock::getLastUpdateUser, moveTask.getUserName()) + .eq(Stock::getVehicleId, moveTask.getVehicleId()) + .eq(Stock::getStockStatus, StockStatus.MOVE.getCode()); + stockService.update(lambdaUpdateWrapperOfStock); + // 更新载具 + LambdaUpdateWrapper lambdaUpdateWrapperOfVehicle = new LambdaUpdateWrapper() + .set(Vehicle::getVehicleStatus, VehicleStatus.ON.getCode()) + .set(Vehicle::getCurrentLocation, moveTask.getDestination()) + .eq(Vehicle::getVehicleId, moveTask.getVehicleId()) + .eq(Vehicle::getVehicleStatus, VehicleStatus.MOVE.getCode()); + vehicleService.update(lambdaUpdateWrapperOfVehicle); + // 释放原来的库位 + LambdaUpdateWrapper lambdaUpdateWrapperOfLocation = new LambdaUpdateWrapper() + .set(Location::getLocationStatus, LocationStatus.EMPTY.getCode()) + .set(Location::getVehicleId, "") + .eq(Location::getLocationId, moveTask.getOrigin()) + .eq(Location::getLocationStatus, LocationStatus.OCCUPY.getCode()); + locationService.update(lambdaUpdateWrapperOfLocation); + // 添加任务记录 + moveTask.setTaskStatus(WmsTaskStatus.FINISH.getCode()); + moveTask.setFinishTime(LocalDateTime.now()); + taskRecordService.save(BeanUtil.copyProperties(moveTask, TaskRecord.class)); + // 删除移库任务 + taskService.remove(new LambdaQueryWrapper().eq(Task::getTaskId, moveTask.getTaskId())); + } + } + // 移库任务完成 + if (taskType == TaskType.MOVE.getCode()) { + // 对所有任务组里面的移库任务进行处理 + for (Task moveTask : feedBackTasks) { + if (!Objects.equals(moveTask.getTaskType(), TaskType.MOVE.getCode())) { + // 非移库任务跳过 + continue; + } + // 更新库存 + LambdaUpdateWrapper lambdaUpdateWrapperOfStock = new LambdaUpdateWrapper() + .set(Stock::getLocationId, moveTask.getDestination()) + .set(Stock::getStockStatus, StockStatus.OK.getCode()) + .set(Stock::getLastUpdateTime, LocalDateTime.now()) + .set(Stock::getLastUpdateUser, moveTask.getUserName()) + .eq(Stock::getVehicleId, moveTask.getVehicleId()) + .eq(Stock::getStockStatus, StockStatus.MOVE.getCode()); + stockService.update(lambdaUpdateWrapperOfStock); + // 更新载具 + LambdaUpdateWrapper lambdaUpdateWrapperOfVehicle = new LambdaUpdateWrapper() + .set(Vehicle::getVehicleStatus, VehicleStatus.ON.getCode()) + .set(Vehicle::getCurrentLocation, moveTask.getDestination()) + .eq(Vehicle::getVehicleId, moveTask.getVehicleId()) + .eq(Vehicle::getVehicleStatus, VehicleStatus.MOVE.getCode()); + vehicleService.update(lambdaUpdateWrapperOfVehicle); + // 释放原来的库位 + LambdaUpdateWrapper lambdaUpdateWrapperOfLocation = new LambdaUpdateWrapper() + .set(Location::getLocationStatus, LocationStatus.EMPTY.getCode()) + .set(Location::getVehicleId, "") + .eq(Location::getLocationId, moveTask.getOrigin()) + .eq(Location::getLocationStatus, LocationStatus.OCCUPY.getCode()); + locationService.update(lambdaUpdateWrapperOfLocation); + // 添加任务记录 + moveTask.setTaskStatus(WmsTaskStatus.FINISH.getCode()); + moveTask.setFinishTime(LocalDateTime.now()); + taskRecordService.save(BeanUtil.copyProperties(moveTask, TaskRecord.class)); + // 删除移库任务 + taskService.remove(new LambdaQueryWrapper().eq(Task::getTaskId, moveTask.getTaskId())); + } + } + } + + + + return convertJsonString(response); + } catch (Exception e) { + // 回滚事务 + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + logger.error("发生异常:{}", convertJsonString(e)); + // 返回其他异常 + response.setCode(ResponseCode.ERROR.getCode()); + response.setMessage("任务反馈发生异常"); + return convertJsonString(response); + } + } + + /** + * 验证任务反馈的请求信息 + * @param wcsTaskResultRequest 任务反馈的请求 + * @return 验证结果 + */ + private String validateTaskResult(WcsTaskResultRequest wcsTaskResultRequest) { + // 验证请求体是否为空 + if (wcsTaskResultRequest == null) { + return TaskResultValidationEnum.NO_REQUEST_BODY.getErrorMessage(); + } + // 验证是否缺少必须信息 + if (StringUtils.isEmpty(wcsTaskResultRequest.getTaskId()) || StringUtils.isEmpty(wcsTaskResultRequest.getVehicleId()) + || wcsTaskResultRequest.getTaskStatus() == null) { + return TaskResultValidationEnum.LACK_REQUIRED_PARAM.getErrorMessage(); + } + // 验证反馈的任务号是否正确 + if (!taskService.exists(new LambdaQueryWrapper().eq(Task::getTaskGroup, wcsTaskResultRequest.getTaskId()))) { + return TaskResultValidationEnum.ERROR_TASK_GROUP.getErrorMessage(); + } + // 验证反馈的任务状态枚举是否正确 + boolean isValidWcsTaskStatus = false; + for (WcsTaskStatus wcsTaskStatus : WcsTaskStatus.values()){ + if (Objects.equals(wcsTaskStatus.getCode(), wcsTaskResultRequest.getTaskStatus())) { + isValidWcsTaskStatus = true; + break; + } + } + if (!isValidWcsTaskStatus) { + return TaskResultValidationEnum.ERROR_TASK_STATUS.getErrorMessage(); + } + return TaskResultValidationEnum.OK.getErrorMessage(); + } } \ No newline at end of file diff --git a/src/main/java/com/wms/controller/TaskDealController.java b/src/main/java/com/wms/controller/TaskDealController.java deleted file mode 100644 index a7fe901..0000000 --- a/src/main/java/com/wms/controller/TaskDealController.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.wms.controller; - -import com.alibaba.fastjson2.JSON; -import com.wms.constants.enums.*; -import com.wms.entity.app.ResponseEntity; -import com.wms.entity.table.LocationDto; -import com.wms.entity.table.TaskDto; -import com.wms.entity.table.WmsLogDto; -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; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -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 org.springframework.web.bind.annotation.*; - -import java.util.Date; -import java.util.List; -import java.util.Objects; - -import static com.wms.config.InitLocalConfig.configMap; - -/** - * 这个类处理任务反馈信息 - */ -@Controller -@CrossOrigin -@RequiredArgsConstructor(onConstructor = @__(@Autowired)) -@RequestMapping(value = "/wms/taskDeal") -public class TaskDealController { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - private final TaskService taskService; - private final HttpServletRequest servletRequest; - private final TaskController taskController; - private final StockService stockService; - private final LocationService locationService; - private final ConfigService configService; - private final LogService logService; - - /** - * 更改任务状态 - * - * @param request 请求参数 - * @return 结果 - */ - @PostMapping("/changeTaskStatus") - @ResponseBody - @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) - public String changeTaskStatus(@RequestBody TaskDto request) { - logger.info("用户请求更改任务状态,用户名:{},ip地址:{}", request.getUserName(), HttpUtils.getIpAddr(servletRequest)); - logger.info("请求详细:{}", JSON.toJSONString(request)); - ResponseEntity response = new ResponseEntity(); - try { - if (request.getTaskStatus() == null) { - logger.error("请选择任务状态"); - response.setCode(ResponseCode.ERROR.getCode()); - response.setMessage("请选择任务状态"); - return JSON.toJSONString(response); - } - // 更改后的任务状态 - int taskStatusRequest = request.getTaskStatus(); - int wcsTaskStatusAfter = 0; - // 查询任务 - TaskDto taskQuery = new TaskDto(); - taskQuery.setTaskId(request.getTaskId()); - List tasks = taskService.selTasks(taskQuery); - if (tasks.size() == 0) { - logger.error("当前任务不存在"); - response.setCode(ResponseCode.ERROR.getCode()); - response.setMessage("当前任务不存在"); - return JSON.toJSONString(response); - } - TaskDto currentTask = tasks.get(0); - String newDestination = ""; - if (Objects.equals(currentTask.getTaskType(), TaskType.IN.getCode()) && StringUtils.isNotEmpty(request.getDestination()) && !Objects.equals(request.getDestination(), currentTask.getDestination())) {// 入库任务库位变更 - if (taskStatusRequest != 0) { - logger.error("更改库位必须重置任务"); - response.setCode(ResponseCode.ERROR.getCode()); - response.setMessage("更改库位必须重置任务"); - return JSON.toJSONString(response); - } - newDestination = request.getDestination(); - } - String taskGroupId = currentTask.getTaskGroup(); - if (taskStatusRequest == 0) {// 重置任务 - logger.info("任务重置"); - // 将当前taskGroup的所有任务都设置为新建状态 - TaskDto taskQuery2 = new TaskDto(); - taskQuery2.setTaskGroup(taskGroupId); - List tasks2 = taskService.selTasks(taskQuery2); - for (TaskDto task2 : tasks2) { - if (StringUtils.isNotEmpty(newDestination)) { - task2.setDestination(newDestination); - } - task2.setTaskStatus(WmsTaskStatus.NEW.getCode()); - task2.setUserName(request.getUserName()); - taskService.executeTask(task2); - } - // 如果更新了任务,那么该库位信息也要变更 - if (Objects.equals(currentTask.getTaskType(), TaskType.IN.getCode()) && StringUtils.isNotEmpty(newDestination)) { - LocationDto newLocationQuery = new LocationDto(newDestination); - List newLocations = locationService.selLocations(newLocationQuery); - for (LocationDto newLocation : newLocations) { - newLocation.setLocationStatus(LocationStatus.EMPTY.getCode()); - locationService.modifyLocation(newLocation); - break; - } - } - // WCS取消任务 - } else if (taskStatusRequest == 1) {// 取消任务 - logger.info("任务取消"); - WmsReceiveTaskResultEntity sendToWmsRequest = new WmsReceiveTaskResultEntity(); - sendToWmsRequest.setTaskId(taskGroupId); - sendToWmsRequest.setTaskStatus(WcsTaskStatus.CANCEL.getCode()); - sendToWmsRequest.setVehicleNo(currentTask.getVehicleNo()); - sendToWmsRequest.setDestination(currentTask.getDestination()); - taskController.receiveTaskResult(sendToWmsRequest); - wcsTaskStatusAfter = 999; - } else if (taskStatusRequest == 2) {// 完成任务 - logger.info("任务完成"); - WmsReceiveTaskResultEntity sendToWmsRequest = new WmsReceiveTaskResultEntity(); - sendToWmsRequest.setTaskId(taskGroupId); - sendToWmsRequest.setTaskStatus(WcsTaskStatus.FINISH.getCode()); - sendToWmsRequest.setVehicleNo(currentTask.getVehicleNo()); - sendToWmsRequest.setDestination(currentTask.getDestination()); - taskController.receiveTaskResult(sendToWmsRequest); - wcsTaskStatusAfter = 3; - } - // 向WCS反馈 - WmsReceiveTaskResultEntity sendToWcsRequest = new WmsReceiveTaskResultEntity(); - sendToWcsRequest.setTaskId(taskGroupId); - sendToWcsRequest.setTaskStatus(wcsTaskStatusAfter); - if (StringUtils.isNotEmpty(newDestination)) { - sendToWcsRequest.setDestination(newDestination); - } - ResponseEntity response1; - for (int i = 0; i < 5; i++) { - // 发送请求 - String url = configMap.get("WCS_TASK_CHANGE") ; - response1 = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(url, JSON.toJSONString(sendToWcsRequest)), ResponseEntity.class); - try { - logService.addWmsLog(new WmsLogDto(WmsUtils.generateId("LOG_"), "向WCS请求更改任务状态", "ChangeTaskStatus", JSON.toJSONString(sendToWcsRequest), JSON.toJSONString(response1), url, new Date(), "WMS")); - } catch (Exception e) { - logger.error("插入日志错误"); - } - logger.info("向WCS反馈任务状态变更"); - if (Objects.equals(response1.getCode(), 0)) {// 发送成功,则不再发送;不成功,一共尝试发送5次 - break; - } - } - logger.info("更新任务状态成功"); - response.setCode(ResponseCode.OK.getCode()); - response.setMessage("更新任务状态成功"); - return JSON.toJSONString(response); - } catch (Exception e) { - // 回滚事务 - TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); - logger.error("发生异常{}", e.getMessage()); - response.setCode(ResponseCode.ERROR.getCode()); - response.setMessage("发生异常" + e.getMessage()); - return JSON.toJSONString(response); - } - } -} diff --git a/src/main/java/com/wms/controller/TestController.java b/src/main/java/com/wms/controller/TestController.java deleted file mode 100644 index b509b88..0000000 --- a/src/main/java/com/wms/controller/TestController.java +++ /dev/null @@ -1,221 +0,0 @@ -package com.wms.controller; - -import com.alibaba.fastjson2.JSON; -import com.wms.constants.enums.LocationStatus; -import com.wms.constants.enums.ResponseCode; -import com.wms.constants.enums.VehicleStatus; -import com.wms.entity.app.ResponseEntity; -import com.wms.entity.table.LocationDto; -import com.wms.entity.table.UserDto; -import com.wms.entity.table.VehicleDto; -import com.wms.entity.test.ExcelTest; -import com.wms.service.LocationService; -import com.wms.service.VehicleService; -import com.wms.utils.MyPassword; -import com.wms.utils.excel.ExcelUtils; -import jakarta.servlet.http.HttpServletResponse; -import lombok.RequiredArgsConstructor; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -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 org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; - -import java.util.ArrayList; -import java.util.List; - -/** - * 测试控制类 - */ -@Controller -@CrossOrigin -@RequestMapping(value = "/wms/test") -@RequiredArgsConstructor(onConstructor = @__(@Autowired)) -public class TestController { - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - /** - * 库位服务 - */ - private final LocationService locationService; - private final VehicleService vehicleService; - - @PostMapping("/genLocations") - @ResponseBody - public String genLocations() { - // 巷道1 一共2排45列12层 - for (int i = 1; i <= 18; i++) {// 列 - for (int j = 1; j <= 11; j++) {// 层 - // 1排 - int markDepth1 = 1; - for (int m = 3; m >= 1; m--) { - String locationId = StringUtils.leftPad(String.valueOf(1), 2, "0") + StringUtils.leftPad(String.valueOf(i), 2, "0") + StringUtils.leftPad(String.valueOf(j), 2, "0") + "-" + StringUtils.leftPad(String.valueOf(m), 2, "0"); - LocationDto tempLocation = new LocationDto(); - tempLocation.setLocationId(locationId); - tempLocation.setAreaId(1); - tempLocation.setTunnelId(1); - tempLocation.setEquipmentId(1); - tempLocation.setLocationType(0); - tempLocation.setQueue(1); - tempLocation.setLine(i); - tempLocation.setLayer(j); - tempLocation.setDepth(m); - tempLocation.setIsLock(0); - tempLocation.setLocationStatus(0); - tempLocation.setMarkDepth(markDepth1); - if (locationService.selLocations(tempLocation).size() == 0) { - locationService.addLocation(tempLocation); - markDepth1++; - } - } - // 2排 - int markDepth2 = 4; - for (int m = 1; m <= 3; m++) { - String locationId = StringUtils.leftPad(String.valueOf(2), 2, "0") + StringUtils.leftPad(String.valueOf(i), 2, "0") + StringUtils.leftPad(String.valueOf(j), 2, "0") + "-" + StringUtils.leftPad(String.valueOf(m), 2, "0"); - LocationDto tempLocation = new LocationDto(); - tempLocation.setLocationId(locationId); - tempLocation.setAreaId(1); - tempLocation.setTunnelId(1); - tempLocation.setEquipmentId(1); - tempLocation.setLocationType(0); - tempLocation.setQueue(2); - tempLocation.setLine(i); - tempLocation.setLayer(j); - tempLocation.setDepth(m); - tempLocation.setIsLock(0); - tempLocation.setLocationStatus(0); - tempLocation.setMarkDepth(markDepth2); - if (locationService.selLocations(tempLocation).size() == 0) { - locationService.addLocation(tempLocation); - markDepth2++; - } - } - // 3排 - int markDepth3 = 4; - for (int m = 1; m <= 3; m++) { - String locationId = StringUtils.leftPad(String.valueOf(3), 2, "0") + StringUtils.leftPad(String.valueOf(i), 2, "0") + StringUtils.leftPad(String.valueOf(j), 2, "0") + "-" + StringUtils.leftPad(String.valueOf(m), 2, "0"); - LocationDto tempLocation = new LocationDto(); - tempLocation.setLocationId(locationId); - tempLocation.setAreaId(1); - tempLocation.setTunnelId(2); - tempLocation.setEquipmentId(2); - tempLocation.setLocationType(0); - tempLocation.setQueue(3); - tempLocation.setLine(i); - tempLocation.setLayer(j); - tempLocation.setDepth(m); - tempLocation.setIsLock(0); - tempLocation.setLocationStatus(0); - tempLocation.setMarkDepth(markDepth3); - if (locationService.selLocations(tempLocation).size() == 0) { - locationService.addLocation(tempLocation); - markDepth3++; - } - } - // 4排 - int markDepth4 = 1; - for (int m = 3; m >= 1; m--) { - String locationId = StringUtils.leftPad(String.valueOf(4), 2, "0") + StringUtils.leftPad(String.valueOf(i), 2, "0") + StringUtils.leftPad(String.valueOf(j), 2, "0") + "-" + StringUtils.leftPad(String.valueOf(m), 2, "0"); - LocationDto tempLocation = new LocationDto(); - tempLocation.setLocationId(locationId); - tempLocation.setAreaId(1); - tempLocation.setTunnelId(2); - tempLocation.setEquipmentId(2); - tempLocation.setLocationType(0); - tempLocation.setQueue(4); - tempLocation.setLine(i); - tempLocation.setLayer(j); - tempLocation.setDepth(m); - tempLocation.setIsLock(0); - tempLocation.setLocationStatus(0); - tempLocation.setMarkDepth(markDepth4); - if (locationService.selLocations(tempLocation).size() == 0) { - locationService.addLocation(tempLocation); - markDepth4++; - } - } - } - } - return "success"; - } - - /** - * 测试导入 - * - * @param file 文件 - * @return 导入结果 - */ - @PostMapping("/testExcelImport") - @ResponseBody - @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) - public String testExcelImport(@RequestPart("file") MultipartFile file) { - ResponseEntity response = new ResponseEntity(); - try { - List tests = ExcelUtils.readMultipartFile(file, ExcelTest.class); - for (ExcelTest test : tests) { - // 更新库位 - LocationDto locationQuery = new LocationDto(); - locationQuery.setLocationId(test.getLocationId()); - List locations = locationService.selLocations(locationQuery); - if (locations.size() > 0) { - LocationDto currentLocation = locations.get(0); - currentLocation.setLocationStatus(LocationStatus.OCCUPY.getCode()); - locationService.modifyLocation(currentLocation); - // 添加载具 - VehicleDto vehicle = new VehicleDto(); - vehicle.setVehicleId("XZBK" + StringUtils.leftPad(test.getVehicleId().trim(), 4, "0")); - vehicle.setCurrentLocation(test.getLocationId()); - vehicle.setVehicleStatus(VehicleStatus.ON.getCode()); - vehicle.setIsEmpty(1); - if (vehicleService.selVehicleById(test.getVehicleId()) == null) { - vehicleService.addVehicle(vehicle); - } else { - vehicleService.modifyVehicle(vehicle); - } - } - } - response.setCode(ResponseCode.OK.getCode()); - response.setMessage("导入excel成功"); - response.setReturnData(tests); - } catch (Exception e) { - // 回滚事务 - TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); - response.setCode(ResponseCode.ERROR.getCode()); - response.setMessage("导入excel发生错误"); - } - logger.info(JSON.toJSONString(response)); - return JSON.toJSONString(response); - } - - /** - * 测试导出 - * - * @param response 请求 - */ - @GetMapping("/testExcelExport") - @ResponseBody - public void testExcelExport(HttpServletResponse response) { - List tests = new ArrayList<>(); - ExcelTest temp1 = new ExcelTest("010101", "XZBK0001"); - ExcelTest temp2 = new ExcelTest("020101", "XZBK0002"); - tests.add(temp1); - tests.add(temp2); - ExcelUtils.export(response, "测试导出", tests, ExcelTest.class); - } - - @PostMapping("/genPassword") - @ResponseBody - @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) - public String genPassword(@RequestBody UserDto user) { - ResponseEntity response = new ResponseEntity(); - response.setCode(ResponseCode.OK.getCode()); - response.setMessage("创建密码成功"); - response.setReturnData(MyPassword.encrypt(user.getLoginPassword())); - return JSON.toJSONString(response); - } -} diff --git a/src/main/java/com/wms/controller/WmsLogController.java b/src/main/java/com/wms/controller/WmsLogController.java index 75f9789..2136f14 100644 --- a/src/main/java/com/wms/controller/WmsLogController.java +++ b/src/main/java/com/wms/controller/WmsLogController.java @@ -7,6 +7,7 @@ import com.wms.constants.enums.ResponseCode; import com.wms.entity.page.PageDomain; import com.wms.entity.page.TableRequest; import com.wms.entity.page.TableResponse; +import com.wms.entity.table.WmsLog; import com.wms.entity.table.WmsLogDto; import com.wms.service.LogService; import com.wms.utils.HttpUtils; @@ -47,15 +48,15 @@ public class WmsLogController { @PostMapping("/queryWmsLog") @ResponseBody @Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED) - public String queryLogs(@RequestBody TableRequest tableRequest) { + public String queryLogs(@RequestBody TableRequest tableRequest) { logger.info("查询日志,ip地址:{}, 用户名:{}", HttpUtils.getIpAddr(servletRequest), tableRequest.getParam().getLogUser()); TableResponse tblResp = new TableResponse(); try { // 处理分页信息 PageDomain pageRequest = tableRequest.getPage(); PageHelper.startPage(pageRequest.getPageNum(), pageRequest.getPageSize()); - List logList = logService.selWmsLogs(tableRequest.getParam().getLogRequest()); - PageInfo logListPage = new PageInfo<>(logList); + List logList = logService.selWmsLogs(tableRequest.getParam().getLogRequest()); + PageInfo logListPage = new PageInfo<>(logList); tblResp.setCode(ResponseCode.OK.getCode()); tblResp.setMessage("查询日志成功!"); tblResp.setRows(logListPage.getList()); diff --git a/src/main/java/com/wms/entity/app/dto/LocationDto.java b/src/main/java/com/wms/entity/app/dto/LocationDto.java index 865c8a9..3770f08 100644 --- a/src/main/java/com/wms/entity/app/dto/LocationDto.java +++ b/src/main/java/com/wms/entity/app/dto/LocationDto.java @@ -47,4 +47,8 @@ public class LocationDto { * 库位状态 */ private Integer locationStatus; + /** + * 载具号 + */ + private String vehicleId; } diff --git a/src/main/java/com/wms/entity/app/dto/extend/StockDetailInfo.java b/src/main/java/com/wms/entity/app/dto/extend/StockDetailInfo.java index 49a583f..340fc93 100644 --- a/src/main/java/com/wms/entity/app/dto/extend/StockDetailInfo.java +++ b/src/main/java/com/wms/entity/app/dto/extend/StockDetailInfo.java @@ -2,6 +2,8 @@ package com.wms.entity.app.dto.extend; import lombok.Data; +import java.math.BigDecimal; + @Data public class StockDetailInfo { /** @@ -16,4 +18,12 @@ public class StockDetailInfo { * 物料状态 */ private Integer goodsStatus; + /** + * 剩余数量 + */ + private BigDecimal remainNum; + /** + * 入库库存总数 + */ + private BigDecimal totalNum; } diff --git a/src/main/java/com/wms/entity/app/dto/extend/TaskDetailInfo.java b/src/main/java/com/wms/entity/app/dto/extend/TaskDetailInfo.java index 3519b93..20a63c6 100644 --- a/src/main/java/com/wms/entity/app/dto/extend/TaskDetailInfo.java +++ b/src/main/java/com/wms/entity/app/dto/extend/TaskDetailInfo.java @@ -2,6 +2,8 @@ package com.wms.entity.app.dto.extend; import lombok.Data; +import java.math.BigDecimal; + @Data public class TaskDetailInfo { /** @@ -12,4 +14,12 @@ public class TaskDetailInfo { * 物料名称 */ private String goodsName; + /** + * 操作数量 + */ + private BigDecimal opNum; + /** + * 原库存剩余数量 + */ + private BigDecimal originNum; } diff --git a/src/main/java/com/wms/entity/app/request/WcsTaskResultRequest.java b/src/main/java/com/wms/entity/app/request/WcsTaskResultRequest.java new file mode 100644 index 0000000..c07c927 --- /dev/null +++ b/src/main/java/com/wms/entity/app/request/WcsTaskResultRequest.java @@ -0,0 +1,35 @@ +package com.wms.entity.app.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(value = "WCS任务结果反馈请求") +public class WcsTaskResultRequest { + /** + * 任务id----对应wms的taskGroup + */ + @ApiModelProperty(value = "任务id---对应wms的taskGroup") + private String taskId; + /** + * 载具号 + */ + @ApiModelProperty(value = "载具号") + private String vehicleId; + /** + * 任务状态 + */ + @ApiModelProperty(value = "任务状态") + private Integer taskStatus; + /** + * 任务终点 + */ + @ApiModelProperty(value = "任务终点") + private String destination; + /** + * 任务信息 + */ + @ApiModelProperty(value = "任务信息") + private String message; +} diff --git a/src/main/java/com/wms/entity/table/Location.java b/src/main/java/com/wms/entity/table/Location.java index b15c1a5..32c5343 100644 --- a/src/main/java/com/wms/entity/table/Location.java +++ b/src/main/java/com/wms/entity/table/Location.java @@ -61,4 +61,9 @@ public class Location { */ @TableField(value = "location_status") private Integer locationStatus; + /** + * 载具号 + */ + @TableField(value = "vehicle_id") + private String vehicleId; } diff --git a/src/main/java/com/wms/service/StandService.java b/src/main/java/com/wms/service/StandService.java index b6e5b5d..bd4b37a 100644 --- a/src/main/java/com/wms/service/StandService.java +++ b/src/main/java/com/wms/service/StandService.java @@ -10,7 +10,7 @@ public interface StandService extends IService { /** * 验证站台正确性 * @param standId 待验证站台 - * @param taskType 任务类型---1:入库,2:出库,3:拣选,4:盘点 + * @param taskType 任务类型---1:入库,2:出库,4:盘点 * @return 验证结果 */ boolean validateStand(String standId, Integer taskType); diff --git a/src/main/java/com/wms/service/TaskRecordService.java b/src/main/java/com/wms/service/TaskRecordService.java index a5e2188..897a26c 100644 --- a/src/main/java/com/wms/service/TaskRecordService.java +++ b/src/main/java/com/wms/service/TaskRecordService.java @@ -25,6 +25,7 @@ public interface TaskRecordService extends IService { * @return 查询结果 */ List selectInventoryTaskRecord(TaskRecord query); + /** * 查找任务记录 * @param query 查询参数 diff --git a/src/main/java/com/wms/service/serviceImplements/LocationServiceImplements.java b/src/main/java/com/wms/service/serviceImplements/LocationServiceImplements.java index 3fdf4f2..3e723af 100644 --- a/src/main/java/com/wms/service/serviceImplements/LocationServiceImplements.java +++ b/src/main/java/com/wms/service/serviceImplements/LocationServiceImplements.java @@ -71,7 +71,6 @@ public class LocationServiceImplements extends ServiceImpl LRUStandQueryWrapper = new LambdaQueryWrapper() .select(Stand::getStandId, Stand::getEquipmentId) @@ -81,14 +80,25 @@ public class LocationServiceImplements extends ServiceImpl LRUStands = standService.list(LRUStandQueryWrapper); if (LRUStands.isEmpty()) { - return null; + return resultMap; } else { if (StringUtils.isNotEmpty(goodsId)) {// 需要根据物料编号做出区分 equipmentId = selectEquipmentByLRUAndGoods(LRUStands, goodsId); - } else { - equipmentId = LRUStands.get(0).getEquipmentId(); + if (equipmentId != -1) { + getOneLocationByEquipmentId(resultMap, locationQueryWrapper, equipmentId); + } + } + if (resultMap.isEmpty()) {// 结果集为空 + for (Stand lruStand : LRUStands) { + getOneLocationByEquipmentId(resultMap, locationQueryWrapper, lruStand.getEquipmentId()); + if (!resultMap.isEmpty()) { + break; + } + } + return resultMap; + } else { + return resultMap; } - return getOneLocationByEquipmentId(resultMap, locationQueryWrapper, equipmentId); } } } @@ -101,6 +111,7 @@ public class LocationServiceImplements extends ServiceImpl getOneLocationByEquipmentId(Map resultMap, LambdaQueryWrapper locationQueryWrapper, int equipmentId) { + resultMap.clear(); locationQueryWrapper.eq(Location::getEquipmentId, equipmentId); locationQueryWrapper.orderByDesc(Location::getWDepth) .orderByAsc(List.of(Location::getWCol, Location::getWLayer, Location::getWRow)); @@ -113,14 +124,17 @@ public class LocationServiceImplements extends ServiceImpl haveTaskLocations = locationMapper.selectList(haveTaskQueryWrapper); // 判断当前排列层的库位是否有出库或者移库任务 + boolean hasTasksFlag = false; for (Location havaTaskLocation : haveTaskLocations) { LambdaQueryWrapper taskQueryWrapper = new LambdaQueryWrapper() .select(Task::getTaskId) .eq(Task::getOrigin, havaTaskLocation.getLocationId()); if (taskService.count(taskQueryWrapper) > 0) { - return null; + hasTasksFlag = true; + break; } } + if (hasTasksFlag) continue; // 判断是否深度+1有入库任务 haveTaskQueryWrapper.clear(); LambdaQueryWrapper plusOneDepthLocationQueryWrapper = new LambdaQueryWrapper() @@ -145,7 +159,7 @@ public class LocationServiceImplements extends ServiceImpl impl /** * 验证站台正确性 * @param standId 待验证站台 - * @param taskType 任务类型---1:入库,2:出库,3:拣选,4:盘点 + * @param taskType 任务类型---1:入库,2:出库,4:盘点 * @return 验证结果 */ public boolean validateStand(String standId, Integer taskType) { @@ -31,11 +32,11 @@ public class StandServiceImplements extends ServiceImpl impl .eq(Stand::getStandId, standId) .eq(Stand::getStandStatus, 0)// 是否可用 .eq(Stand::getIsLock, 0);// 是否锁定 - if (taskType == 1) {// 入库 + if (taskType.equals(TaskType.IN.getCode())) {// 入库 lambdaQueryWrapper.eq(Stand::getAllowIn, 1);// 入库 - } else if (taskType == 2) {// 出库 + } else if (taskType.equals(TaskType.OUT.getCode())) {// 出库 lambdaQueryWrapper.eq(Stand::getAllowOut, 1);// 出库 - } else if (taskType == 3 || taskType == 4) {// 拣选或者盘点 + } else if (taskType.equals(TaskType.INVENTORY.getCode())) {// 拣选或者盘点 lambdaQueryWrapper.eq(Stand::getStandType, 2); } else { return false; diff --git a/src/main/java/com/wms/service/serviceImplements/TaskRecordServiceImplements.java b/src/main/java/com/wms/service/serviceImplements/TaskRecordServiceImplements.java index 35f429a..9358a36 100644 --- a/src/main/java/com/wms/service/serviceImplements/TaskRecordServiceImplements.java +++ b/src/main/java/com/wms/service/serviceImplements/TaskRecordServiceImplements.java @@ -5,7 +5,6 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.wms.constants.enums.TaskType; import com.wms.entity.app.dto.TaskRecordDto; -import com.wms.entity.app.dto.extend.TaskDetailInfo; import com.wms.entity.table.TaskRecord; import com.wms.mapper.TaskRecordMapper; import com.wms.service.TaskRecordService; diff --git a/src/main/java/com/wms/service/serviceImplements/TaskServiceImplements.java b/src/main/java/com/wms/service/serviceImplements/TaskServiceImplements.java index 185ee0a..fd7f40b 100644 --- a/src/main/java/com/wms/service/serviceImplements/TaskServiceImplements.java +++ b/src/main/java/com/wms/service/serviceImplements/TaskServiceImplements.java @@ -1,17 +1,29 @@ package com.wms.service.serviceImplements; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.wms.constants.enums.*; import com.wms.entity.app.dto.TaskDto; 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.mapper.TaskMapper; import com.wms.service.LocationService; +import com.wms.service.StockService; import com.wms.service.TaskService; +import com.wms.service.VehicleService; +import com.wms.utils.StringUtils; +import com.wms.utils.WmsUtils; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; + /** * 任务服务的实现类 */ @@ -26,6 +38,14 @@ public class TaskServiceImplements extends ServiceImpl impleme * 库位服务 */ private final LocationService locationService; + /** + * 库存服务 + */ + private final StockService stockService; + /** + * 载具服务 + */ + private final VehicleService vehicleService; @Override public TaskDto genMoveTask(String locationId) { @@ -35,18 +55,136 @@ public class TaskServiceImplements extends ServiceImpl impleme return null; } else { // 生成当前深度-1的库位的移库任务 + TaskDto depthMinus1MoveTask = new TaskDto(); Location depthMinus1Location = locationService.getOne(new LambdaQueryWrapper().eq(Location::getLocationId, outLocation.getLocationId())); - // 查询这个位置 - // 生成当前深度-2的库位的移库任务,即当前深度-1的库位作为参数 - genMoveTask(depthMinus1Location.getLocationId()); + if (depthMinus1Location.getIsLock() == 1) {// 外层库位锁定 + depthMinus1MoveTask.setTaskId("LOCKED"); + return depthMinus1MoveTask; + } + // 判断是否有货 + if (Objects.equals(depthMinus1Location.getLocationStatus(), LocationStatus.OCCUPY.getCode())) { + // 查看这个库位是否有入库任务 + Task depthMinusIn1Task = taskMapper.selectOne(new LambdaQueryWrapper() + .eq(Task::getTaskType, TaskType.IN.getCode()) + .eq(Task::getDestination, depthMinus1Location.getLocationId())); + if (depthMinusIn1Task != null) { + // 生成移库任务,并把移库任务的前置任务设置为该入库任务 + Task moveTask = genMoveTask(depthMinus1Location); + moveTask.setPreTask(depthMinusIn1Task.getTaskId()); + taskMapper.insert(moveTask); + // 对应载具所有库存上锁 + stockService.update(new LambdaUpdateWrapper() + .set(Stock::getStockStatus, StockStatus.MOVE.getCode()) + .eq(Stock::getLocationId, depthMinus1Location.getLocationId())); + // 对应载具状态设置 + vehicleService.update(new LambdaUpdateWrapper() + .set(Vehicle::getVehicleStatus, VehicleStatus.MOVE.getCode()) + .eq(Vehicle::getCurrentLocation, depthMinus1Location.getLocationId())); + depthMinus1MoveTask.setTaskId(moveTask.getTaskId()); + return depthMinus1MoveTask; + } else { + // 判断是否有出库、移库、盘点、拣选等任务 + Task depthMinusOut1Task = taskMapper.selectOne(new LambdaQueryWrapper() + .eq(Task::getOrigin, depthMinus1Location.getLocationId())); + if (depthMinusOut1Task != null) { + depthMinus1MoveTask.setTaskId(depthMinusOut1Task.getTaskId()); + } else { + // 生成移库任务,并把移库任务的前置任务设置为该入库任务 + Task moveTask = genMoveTask(depthMinus1Location); + // 判断当前深度-2的库位是否有移库任务 + TaskDto depthMinus2MoveTask = genMoveTask(depthMinus1Location.getLocationId()); + if (depthMinus2MoveTask.getTaskId().equals("LOCKED")) { + depthMinus1MoveTask.setTaskId("LOCKED"); + return depthMinus1MoveTask; + } + moveTask.setPreTask(depthMinus2MoveTask.getTaskId()); + taskMapper.insert(moveTask); + // 对应载具所有库存上锁 + stockService.update(new LambdaUpdateWrapper() + .set(Stock::getStockStatus, StockStatus.MOVE.getCode()) + .eq(Stock::getLocationId, depthMinus1Location.getLocationId())); + // 对应载具状态设置 + vehicleService.update(new LambdaUpdateWrapper() + .set(Vehicle::getVehicleStatus, VehicleStatus.MOVE.getCode()) + .eq(Vehicle::getCurrentLocation, depthMinus1Location.getLocationId())); + depthMinus1MoveTask.setTaskId(moveTask.getTaskId()); + } + return depthMinus1MoveTask; + } + } else { + // 生成当前深度-2的库位的移库任务,即当前深度-1的库位作为参数 + TaskDto depthMinus2MoveTask = genMoveTask(depthMinus1Location.getLocationId()); + return StringUtils.isNotEmpty(depthMinus1MoveTask.getTaskId()) ? depthMinus1MoveTask : depthMinus2MoveTask; + } } } - - - - - - return null; } + + /** + * 生成一个移库任务 + * @param originLocation 原库位 + * @return 生成的移库任务 + */ + private Task genMoveTask(Location originLocation) { + Task moveTask = new Task(); + // 先找一个新库位,同一个设备号,但是不同的排列层 + Location newLocation = new Location(); + List availableLocations = locationService.list(new LambdaQueryWrapper() + .eq(Location::getEquipmentId, originLocation.getEquipmentId()) + .eq(Location::getLocationType, originLocation.getLocationType()) + .eq(Location::getIsLock, 0) + .eq(Location::getLocationStatus, LocationStatus.EMPTY.getCode()) + .ne(Location::getWRow, originLocation.getWRow()) + .ne(Location::getWCol, originLocation.getWCol()) + .ne(Location::getWLayer, originLocation.getWLayer())); + 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 = locationService.list(haveTaskQueryWrapper); + // 判断当前排列层的库位是否有出库或者移库任务 + boolean hasTasksFlag = false; + for (Location havaTaskLocation : haveTaskLocations) { + LambdaQueryWrapper taskOutQueryWrapper = new LambdaQueryWrapper() + .select(Task::getTaskId) + .eq(Task::getOrigin, havaTaskLocation.getLocationId()); + LambdaQueryWrapper taskInQueryWrapper = new LambdaQueryWrapper() + .select(Task::getTaskId) + .eq(Task::getDestination, havaTaskLocation.getLocationId()); + if (super.count(taskOutQueryWrapper) > 0 || super.count(taskInQueryWrapper) > 0) { + hasTasksFlag = true; + break; + } + } + if (hasTasksFlag) continue; + // 锁定库位 + LambdaUpdateWrapper updateLocationWrapper = new LambdaUpdateWrapper() + .set(Location::getLocationStatus, LocationStatus.OCCUPY.getCode()) + .set(Location::getVehicleId, originLocation.getVehicleId()) + .eq(Location::getLocationId, oneAvailableLocation.getLocationId()) + .eq(Location::getLocationStatus, LocationStatus.EMPTY.getCode()); + if (locationService.update(updateLocationWrapper)) { + newLocation = oneAvailableLocation; + break; + } + } + if (StringUtils.isNotEmpty(newLocation.getLocationId())) { + // 生成移库任务 + moveTask.setTaskId(WmsUtils.generateId("MOVE_")); + moveTask.setTaskType(TaskType.MOVE.getCode()); + moveTask.setTaskPriority(1); + moveTask.setTaskGroup(WmsUtils.generateId("")); + moveTask.setVehicleId(originLocation.getVehicleId()); + moveTask.setOrigin(originLocation.getLocationId()); + moveTask.setDestination(newLocation.getLocationId()); + moveTask.setUserName("WMS"); + moveTask.setCreateTime(LocalDateTime.now()); + moveTask.setTaskStatus(WmsTaskStatus.NEW.getCode()); + } + + return moveTask; + } } diff --git a/src/main/java/com/wms/utils/WmsUtils.java b/src/main/java/com/wms/utils/WmsUtils.java index cc5a234..f389261 100644 --- a/src/main/java/com/wms/utils/WmsUtils.java +++ b/src/main/java/com/wms/utils/WmsUtils.java @@ -1,12 +1,12 @@ package com.wms.utils; -import org.apache.commons.lang3.StringUtils; +import com.wms.constants.enums.WcsTaskStatus; +import com.wms.constants.enums.WmsTaskStatus; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; -import java.util.UUID; /** * WMS工具类