diff --git a/src/main/java/com/wms/constants/enums/StockStatus.java b/src/main/java/com/wms/constants/enums/StockStatus.java index a6321dd..d2895dd 100644 --- a/src/main/java/com/wms/constants/enums/StockStatus.java +++ b/src/main/java/com/wms/constants/enums/StockStatus.java @@ -1,8 +1,11 @@ package com.wms.constants.enums; +import lombok.Getter; + /** * 库存状态枚举 */ +@Getter public enum StockStatus { OK(0, "库存正常"), OUT(1, "出库中"), @@ -10,6 +13,7 @@ public enum StockStatus { MOVE(3, "移库中"), PICKING(4, "拣选中"), BACK(5, "回库中"), + OUTED(6, "已出库"), LOCK(9, "库存锁定"); private final Integer code; @@ -21,11 +25,4 @@ public enum StockStatus { this.value = value; } - public Integer getCode() { - return code; - } - - public String getValue() { - return value; - } } diff --git a/src/main/java/com/wms/controller/TaskController.java b/src/main/java/com/wms/controller/TaskController.java index 5aa2b29..e939f2c 100644 --- a/src/main/java/com/wms/controller/TaskController.java +++ b/src/main/java/com/wms/controller/TaskController.java @@ -490,8 +490,8 @@ public class TaskController { taskService.remove(new LambdaQueryWrapper().eq(Task::getTaskId, inTask.getTaskId())); // 移除当前料箱所有的拣选任务 pickTaskService.remove(new LambdaQueryWrapper().eq(PickTask::getVehicleId, inTask.getVehicleId())); - // 移除当前料箱所有的outsideVehicles - outsideVehiclesService.remove(new LambdaQueryWrapper().eq(OutsideVehicles::getVehicleId, inTask.getVehicleId())); + // 移除当前料箱所有的outsideVehicles---todo 这张表已经废弃不用 +// outsideVehiclesService.remove(new LambdaQueryWrapper().eq(OutsideVehicles::getVehicleId, inTask.getVehicleId())); // 清除当前料箱的所有盘点任务 inventoryService.remove(new LambdaQueryWrapper().eq(InventoryList::getVehicleId, inTask.getVehicleId())); } @@ -512,7 +512,7 @@ public class TaskController { .set(Vehicle::getVehicleStatus, VehicleStatus.OUT.getCode()) .eq(Vehicle::getVehicleId, outTask.getVehicleId()) .ne(Vehicle::getVehicleStatus, VehicleStatus.OUT.getCode())); - // 当前载具上所有库存状态设置为拣选 + // 当前载具上所有库存状态设置为拣选---todo 是否要更改为outed状态 stockService.update(new LambdaUpdateWrapper() .set(Stock::getStockStatus, StockStatus.PICKING.getCode()) .eq(Stock::getVehicleId, outTask.getVehicleId()) @@ -522,12 +522,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)); + // 设置特殊---todo 此表废弃 +// 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())); @@ -1084,33 +1084,46 @@ public class TaskController { wcsETaskRequest.setOrderId(generateId(workQuery.getGoodsId() + "_")); wcsETaskRequest.setVehicleNo(vehicleId); String sendToWcsETaskUrl = configMap.get(ConfigMapKeyEnum.URL_WCS_E_TASK.getConfigKey()); - if (StringUtils.isEmpty(sendToWcsETaskUrl)) { - // url地址为空 - logger.error("向Wcs发送电子标签亮灯任务的地址为空"); - throw new Exception("向Wcs发送电子标签亮灯任务的地址为空"); - } else { - // 发送信息 - logger.info("发送电子标签亮灯请求:{}", convertJsonString(wcsETaskRequest)); - ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(sendToWcsETaskUrl, convertJsonString(wcsETaskRequest)), ResponseEntity.class); - try { - logService.save(new WmsLog(WmsUtils.generateId("LOG_"), "发送电子标签任务", "eTagTask", convertJsonString(wcsETaskRequest), convertJsonString(result), sendToWcsETaskUrl, LocalDateTime.now(), "WMS")); - } catch (Exception e) { - logger.error("插入日志错误"); - } - if (result == null || !Objects.equals(result.getCode(), ResponseCode.OK.getCode())) { - logger.error("发送电子标签亮灯任务失败:{}", convertJsonString(result)); - throw new Exception("发送电子标签亮灯任务失败"); - } else { - // 更新workFlow数据 - workFlowService.updateBatchById(workFlows); - // 更新亮灯数据 - etagLocationService.update(new LambdaUpdateWrapper() - .set(ETagLocation::getPickStatus, 1) - .set(ETagLocation::getTaskType, wcsETaskRequest.getTaskType()) - .set(ETagLocation::getVehicleNo, wcsETaskRequest.getVehicleNo()) - .in(ETagLocation::getELocationId, eTaskDataList.stream().map(ETaskData::getLocation).collect(Collectors.toList()))); - } - } + + // TODO 这里是模拟的 + // 更新workFlow数据 + workFlowService.updateBatchById(workFlows); + // 更新亮灯数据 + etagLocationService.update(new LambdaUpdateWrapper() + .set(ETagLocation::getPickStatus, 1) + .set(ETagLocation::getTaskType, wcsETaskRequest.getTaskType()) + .set(ETagLocation::getVehicleNo, wcsETaskRequest.getVehicleNo()) + .in(ETagLocation::getELocationId, eTaskDataList.stream().map(ETaskData::getLocation).collect(Collectors.toList()))); + + + // TODO 模拟结束要去掉注释 +// if (StringUtils.isEmpty(sendToWcsETaskUrl)) { +// // url地址为空 +// logger.error("向Wcs发送电子标签亮灯任务的地址为空"); +// throw new Exception("向Wcs发送电子标签亮灯任务的地址为空"); +// } else { +// // 发送信息 +// logger.info("发送电子标签亮灯请求:{}", convertJsonString(wcsETaskRequest)); +// ResponseEntity result = JSON.parseObject(HttpUtils.sendHttpPostWithoutToken(sendToWcsETaskUrl, convertJsonString(wcsETaskRequest)), ResponseEntity.class); +// try { +// logService.save(new WmsLog(WmsUtils.generateId("LOG_"), "发送电子标签任务", "eTagTask", convertJsonString(wcsETaskRequest), convertJsonString(result), sendToWcsETaskUrl, LocalDateTime.now(), "WMS")); +// } catch (Exception e) { +// logger.error("插入日志错误"); +// } +// if (result == null || !Objects.equals(result.getCode(), ResponseCode.OK.getCode())) { +// logger.error("发送电子标签亮灯任务失败:{}", convertJsonString(result)); +// throw new Exception("发送电子标签亮灯任务失败"); +// } else { +// // 更新workFlow数据 +// workFlowService.updateBatchById(workFlows); +// // 更新亮灯数据 +// etagLocationService.update(new LambdaUpdateWrapper() +// .set(ETagLocation::getPickStatus, 1) +// .set(ETagLocation::getTaskType, wcsETaskRequest.getTaskType()) +// .set(ETagLocation::getVehicleNo, wcsETaskRequest.getVehicleNo()) +// .in(ETagLocation::getELocationId, eTaskDataList.stream().map(ETaskData::getLocation).collect(Collectors.toList()))); +// } +// } } // 更新站台数据 standService.update(new LambdaUpdateWrapper() @@ -1399,47 +1412,56 @@ public class TaskController { } // 更新实际拣选数量 workFlow.setPickedNum(workFlow.getPickedNum().add(BigDecimal.valueOf(eTaskFeedbackRequest.getConfirmNum()))); - if (eTaskFeedbackRequest.getConfirmNum().compareTo(eTaskFeedbackRequest.getNeedNum()) < 0) { - int diffNum = eTaskFeedbackRequest.getNeedNum() - eTaskFeedbackRequest.getConfirmNum(); - // 查站台要料表---未分配以及分配但未完全分配 - GoodsToStation goodsToStation = goodsToStationService.getOne(new LambdaQueryWrapper() - .eq(GoodsToStation::getWorkStation, workFlow.getWorkStation()) - .eq(GoodsToStation::getGoodsId, workFlow.getGoodsId()) - .last("limit 1")); - if (goodsToStation != null) { - // 更新站台要料数量 - BigDecimal newDistributeNum = goodsToStation.getDistributedNum().subtract(BigDecimal.valueOf(diffNum)); - goodsToStation.setDistributedNum(newDistributeNum.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : newDistributeNum); - goodsToStation.setDistributeStatus(1); - goodsToStationService.updateById(goodsToStation); - } - // 查询当前站台的拣货任务 - PickTask pickTask = pickTaskService.getOne(new LambdaQueryWrapper() - .eq(PickTask::getStandId, workFlow.getWorkStation()) - .eq(PickTask::getPickStatus, PickTaskStatusEnum.FINISH.getCode()) - .last("limit 1")); - if (pickTask != null) { - // 更新当前的outsideVehicles状态为一个新状态,拉取任务时不拉取它 - List outsideVehiclesList = outsideVehiclesService.list(new LambdaQueryWrapper() - .eq(OutsideVehicles::getVehicleId, pickTask.getVehicleId()) - .eq(OutsideVehicles::getGoodsId, workFlow.getGoodsId())); - for (OutsideVehicles outsideVehicles : outsideVehiclesList) { - outsideVehicles.setOutStatus(2); - } - outsideVehiclesService.updateBatchById(outsideVehiclesList); - } - // 更新workFlow状态 + // todo---下面两张表废弃使用 +// if (eTaskFeedbackRequest.getConfirmNum().compareTo(eTaskFeedbackRequest.getNeedNum()) < 0) { +// int diffNum = eTaskFeedbackRequest.getNeedNum() - eTaskFeedbackRequest.getConfirmNum(); +// // 查站台要料表---未分配以及分配但未完全分配 +// GoodsToStation goodsToStation = goodsToStationService.getOne(new LambdaQueryWrapper() +// .eq(GoodsToStation::getWorkStation, workFlow.getWorkStation()) +// .eq(GoodsToStation::getGoodsId, workFlow.getGoodsId()) +// .last("limit 1")); +// if (goodsToStation != null) { +// // 更新站台要料数量 +// BigDecimal newDistributeNum = goodsToStation.getDistributedNum().subtract(BigDecimal.valueOf(diffNum)); +// goodsToStation.setDistributedNum(newDistributeNum.compareTo(BigDecimal.ZERO) <= 0 ? BigDecimal.ZERO : newDistributeNum); +// goodsToStation.setDistributeStatus(1); +// goodsToStationService.updateById(goodsToStation); +// } +// // 查询当前站台的拣货任务 +// PickTask pickTask = pickTaskService.getOne(new LambdaQueryWrapper() +// .eq(PickTask::getStandId, workFlow.getWorkStation()) +// .eq(PickTask::getPickStatus, PickTaskStatusEnum.FINISH.getCode()) +// .last("limit 1")); +// if (pickTask != null) { +// // 更新当前的outsideVehicles状态为一个新状态,拉取任务时不拉取它 +// List outsideVehiclesList = outsideVehiclesService.list(new LambdaQueryWrapper() +// .eq(OutsideVehicles::getVehicleId, pickTask.getVehicleId()) +// .eq(OutsideVehicles::getGoodsId, workFlow.getGoodsId())); +// for (OutsideVehicles outsideVehicles : outsideVehiclesList) { +// outsideVehicles.setOutStatus(2); +// } +// outsideVehiclesService.updateBatchById(outsideVehiclesList); +// } +// // 更新workFlow状态 +// workFlow.setLightStatus(0);// 未亮灯 +// workFlow.setWorkStatus(1);// 正在做 +// } else { +// if (workFlow.getPickedNum().compareTo(workFlow.getNeedNum()) < 0) { +// // 缺料未完成 +// workFlow.setLightStatus(0);// 未亮灯 +// workFlow.setWorkStatus(1);// 正在做 +// } else { +// workFlow.setLightStatus(2);// 已拍灯 +// workFlow.setWorkStatus(2);// 已完成 +// } +// } + if (workFlow.getPickedNum().compareTo(workFlow.getNeedNum()) < 0) { + // 缺料未完成 workFlow.setLightStatus(0);// 未亮灯 workFlow.setWorkStatus(1);// 正在做 } else { - if (workFlow.getPickedNum().compareTo(workFlow.getNeedNum()) < 0) { - // 缺料未完成 - workFlow.setLightStatus(0);// 未亮灯 - workFlow.setWorkStatus(1);// 正在做 - } else { - workFlow.setLightStatus(2);// 已拍灯 - workFlow.setWorkStatus(2);// 已完成 - } + workFlow.setLightStatus(2);// 已拍灯 + workFlow.setWorkStatus(2);// 已完成 } // 更新workFlow workFlow.setFinishTime(LocalDateTime.now()); @@ -1560,8 +1582,8 @@ public class TaskController { .last("limit 1")); if (pickTask == null) { // 没有拣货任务,直接放行 - // 调用Wcs的放行接口 - wcsService.sendWcsDisposeVehicle(new WcsDisposeVehicleRequest(standId, null)); + // 调用Wcs的放行接口 TODO 测试时注释 +// wcsService.sendWcsDisposeVehicle(new WcsDisposeVehicleRequest(standId, null)); // 更新站台信息 standService.update(new LambdaUpdateWrapper() .set(Stand::getLastUseTime, LocalDateTime.now()) @@ -1587,24 +1609,25 @@ public class TaskController { stockService.updateById(existStock); stockUpdateRecordService.addStockUpdateRecord(originStock, existStock, StockUpdateReasonEnum.CONFIRM_UPDATE.getReason(), workConfirmRequest.getUserName(), quantityBefore); } - OutsideVehicles currentGoodsVehicle = outsideVehiclesService.getOne(new LambdaQueryWrapper() - .eq(OutsideVehicles::getVehicleId, pickTask.getVehicleId()) - .eq(OutsideVehicles::getGoodsId, workConfirmRequest.getGoodsId()) - .last("limit 1")); - if (workConfirmRequest.getRemainNumReal().compareTo(BigDecimal.ZERO) == 0) {// 实际剩余数量为0 - // 更新流转载具表剩余数量 - if (currentGoodsVehicle != null) { - currentGoodsVehicle.setRemainNum(BigDecimal.ZERO); - currentGoodsVehicle.setOutStatus(2); - outsideVehiclesService.updateById(currentGoodsVehicle); - } - } else { - // 更新流转载具表剩余数量 todo - if (currentGoodsVehicle != null) { - currentGoodsVehicle.setRemainNum(currentGoodsVehicle.getRemainNum().add(workConfirmRequest.getRemainNumReal().subtract(workConfirmRequest.getRemainNumOrigin()))); - outsideVehiclesService.updateById(currentGoodsVehicle); - } - } + // todo---此表废弃使用 +// OutsideVehicles currentGoodsVehicle = outsideVehiclesService.getOne(new LambdaQueryWrapper() +// .eq(OutsideVehicles::getVehicleId, pickTask.getVehicleId()) +// .eq(OutsideVehicles::getGoodsId, workConfirmRequest.getGoodsId()) +// .last("limit 1")); +// if (workConfirmRequest.getRemainNumReal().compareTo(BigDecimal.ZERO) == 0) {// 实际剩余数量为0 +// // 更新流转载具表剩余数量 +// if (currentGoodsVehicle != null) { +// currentGoodsVehicle.setRemainNum(BigDecimal.ZERO); +// currentGoodsVehicle.setOutStatus(2); +// outsideVehiclesService.updateById(currentGoodsVehicle); +// } +// } else { +// // 更新流转载具表剩余数量 todo +// if (currentGoodsVehicle != null) { +// currentGoodsVehicle.setRemainNum(currentGoodsVehicle.getRemainNum().add(workConfirmRequest.getRemainNumReal().subtract(workConfirmRequest.getRemainNumOrigin()))); +// outsideVehiclesService.updateById(currentGoodsVehicle); +// } +// } } else { if (existStock != null && existStock.getGoodsRelated() != null) { if (workConfirmRequest.getRemainNumOrigin().compareTo(BigDecimal.ZERO) == 0) { @@ -1615,13 +1638,14 @@ public class TaskController { existStock.setGoodsRelated(goodsDetail); stockService.updateById(existStock); stockUpdateRecordService.addStockUpdateRecord(originStock, existStock, StockUpdateReasonEnum.CONFIRM_UPDATE.getReason(), workConfirmRequest.getUserName(), quantityBefore); - OutsideVehicles currentGoodsVehicle = outsideVehiclesService.getOne(new LambdaQueryWrapper() - .eq(OutsideVehicles::getVehicleId, pickTask.getVehicleId()) - .eq(OutsideVehicles::getGoodsId, workConfirmRequest.getGoodsId()) - .last("limit 1")); - currentGoodsVehicle.setRemainNum(BigDecimal.ZERO); - currentGoodsVehicle.setOutStatus(2); - outsideVehiclesService.updateById(currentGoodsVehicle); + // todo---此表废弃使用 +// OutsideVehicles currentGoodsVehicle = outsideVehiclesService.getOne(new LambdaQueryWrapper() +// .eq(OutsideVehicles::getVehicleId, pickTask.getVehicleId()) +// .eq(OutsideVehicles::getGoodsId, workConfirmRequest.getGoodsId()) +// .last("limit 1")); +// currentGoodsVehicle.setRemainNum(BigDecimal.ZERO); +// currentGoodsVehicle.setOutStatus(2); +// outsideVehiclesService.updateById(currentGoodsVehicle); } } } @@ -1665,8 +1689,8 @@ public class TaskController { pickTaskRecordService.save(pickTaskRecord); // 删除当前拣选任务 pickTaskService.removeById(pickTask); - // 不需要,放行 - wcsService.sendWcsDisposeVehicle(new WcsDisposeVehicleRequest(standId, pickTask.getVehicleId())); + // 不需要,放行 TODO 测试时注释 +// wcsService.sendWcsDisposeVehicle(new WcsDisposeVehicleRequest(standId, pickTask.getVehicleId())); // 判断是不是已经完成工作 if (workFlowService.exists(new LambdaQueryWrapper() .eq(WorkFlow::getWorkStation, standId) @@ -1704,8 +1728,8 @@ public class TaskController { pickTaskRecordService.save(pickTaskRecord); // 删除当前拣选任务 pickTaskService.removeById(pickTask); - // 放行 - wcsService.sendWcsDisposeVehicle(new WcsDisposeVehicleRequest(standId, pickTask.getVehicleId())); + // 放行 TODO 测试时注释 +// wcsService.sendWcsDisposeVehicle(new WcsDisposeVehicleRequest(standId, pickTask.getVehicleId())); // 判断是不是已经完成工作 if (workFlowService.exists(new LambdaQueryWrapper() .eq(WorkFlow::getWorkStation, standId) 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 340fc93..9779382 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 @@ -26,4 +26,8 @@ public class StockDetailInfo { * 入库库存总数 */ private BigDecimal totalNum; + /** + * 可用数量---当回库时设置为和剩余数量一致 + */ + private BigDecimal usableNum; } diff --git a/src/main/java/com/wms/entity/app/vo/WorkFlowVo.java b/src/main/java/com/wms/entity/app/vo/WorkFlowVo.java index 2ea253c..d6311f6 100644 --- a/src/main/java/com/wms/entity/app/vo/WorkFlowVo.java +++ b/src/main/java/com/wms/entity/app/vo/WorkFlowVo.java @@ -54,6 +54,11 @@ public class WorkFlowVo { */ @JsonProperty("needNum") private BigDecimal needNum; + /** + * 需求数量 + */ + @JsonProperty("distributedNum") + private BigDecimal distributedNum; /** * 亮灯状态 * 0:未亮灯 diff --git a/src/main/java/com/wms/entity/table/WorkFlow.java b/src/main/java/com/wms/entity/table/WorkFlow.java index 7f0e48a..09298cd 100644 --- a/src/main/java/com/wms/entity/table/WorkFlow.java +++ b/src/main/java/com/wms/entity/table/WorkFlow.java @@ -104,4 +104,9 @@ public class WorkFlow { */ @TableField("big_box") private String bigBox; + /** + * 已分配数量 + */ + @TableField("distributed_num") + private BigDecimal distributedNum; } diff --git a/src/main/java/com/wms/entity/table/WorkFlowLast.java b/src/main/java/com/wms/entity/table/WorkFlowLast.java index 4445e8c..cb99ae0 100644 --- a/src/main/java/com/wms/entity/table/WorkFlowLast.java +++ b/src/main/java/com/wms/entity/table/WorkFlowLast.java @@ -101,4 +101,9 @@ public class WorkFlowLast { */ @TableField("big_box") private String bigBox; + /** + * 已分配数量 + */ + @TableField("distributed_num") + private BigDecimal distributedNum; } diff --git a/src/main/java/com/wms/quartz/job_executor/KateWorkExecutor.java b/src/main/java/com/wms/quartz/job_executor/KateWorkExecutor.java index d06af78..934c55b 100644 --- a/src/main/java/com/wms/quartz/job_executor/KateWorkExecutor.java +++ b/src/main/java/com/wms/quartz/job_executor/KateWorkExecutor.java @@ -1,8 +1,5 @@ package com.wms.quartz.job_executor; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.wms.constants.enums.ConfigMapKeyEnum; -import com.wms.entity.table.Stand; import com.wms.service.StandService; import com.wms.service.business.IWorkService; import com.wms.utils.StringUtils; @@ -12,7 +9,6 @@ import org.quartz.*; import java.time.LocalDateTime; import java.time.LocalTime; -import java.util.List; import static com.wms.config.InitLocalConfig.configMap; import static com.wms.utils.StringUtils.convertJsonString; @@ -45,6 +41,8 @@ public class KateWorkExecutor implements Job { createWork(); // 执行工作 doWork(); + // 修复工作 + repairWork(); } /** @@ -63,13 +61,13 @@ public class KateWorkExecutor implements Job { try { workService.createTempWorkFlows(); } catch (Exception e) { - log.error("创建当日工作发生错误:{}", e.getMessage()); + log.error("创建当日工作发生异常:{}", convertJsonString(e)); } try { // 分配工作 workService.distributeWorks(); } catch (Exception e) { - log.error("分配工作时发生错误:{}", e.getMessage()); + log.error("分配工作时发生异常:{}", convertJsonString(e)); } } @@ -81,17 +79,33 @@ public class KateWorkExecutor implements Job { if (StringUtils.isEmpty(startWork) || !startWork.equals("1")) { return; } - // 轮询工作站台,判断是否需要下发任务 - List stands = standService.list(new LambdaQueryWrapper() - .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0) - .eq(Stand::getStandType, 2)); - List standIds = stands.stream().map(Stand::getStandId).toList(); - for (String standId : standIds) { - try { - workService.doWork(standId); - } catch (Exception e) { - log.error("执行工作时发生错误:{}", convertJsonString(e.getMessage())); - } + try { + workService.doWorkMethod2(); + } catch (Exception e) { + log.error("执行工作时发生异常:{}", convertJsonString(e)); + } +// // 轮询工作站台,判断是否需要下发任务 +// List stands = standService.list(new LambdaQueryWrapper() +// .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0) +// .eq(Stand::getStandType, 2)); +// List standIds = stands.stream().map(Stand::getStandId).toList(); +// for (String standId : standIds) { +// try { +// workService.doWork(standId); +// } catch (Exception e) { +// log.error("执行工作时发生错误:{}", convertJsonString(e.getMessage())); +// } +// } + } + + /** + * 修复工作 + */ + public void repairWork() { + try { + workService.repairWork(); + } catch (Exception e) { + log.error("修复工作发生异常:{}", convertJsonString(e)); } } } diff --git a/src/main/java/com/wms/service/business/IWorkService.java b/src/main/java/com/wms/service/business/IWorkService.java index 1c850dd..b9087f2 100644 --- a/src/main/java/com/wms/service/business/IWorkService.java +++ b/src/main/java/com/wms/service/business/IWorkService.java @@ -13,6 +13,16 @@ public interface IWorkService { */ void doWork(String workStation) throws Exception; + /** + * 新的执行工作 + */ + void doWorkMethod2(); + + /** + * 修复工作 + */ + void repairWork(); + /** * 完成工作 * @param workStation 工作站台 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 4941176..cbb1e4e 100644 --- a/src/main/java/com/wms/service/business/serviceImplements/WmsJobServiceImplements.java +++ b/src/main/java/com/wms/service/business/serviceImplements/WmsJobServiceImplements.java @@ -14,6 +14,7 @@ import com.wms.entity.app.wcs.WcsTaskRequest; import com.wms.entity.table.*; import com.wms.service.*; import com.wms.service.business.IWmsJobService; +import com.wms.utils.DbTransUtils; import com.wms.utils.HttpUtils; import com.wms.utils.StringUtils; import com.wms.utils.WmsUtils; @@ -65,6 +66,7 @@ public class WmsJobServiceImplements implements IWmsJobService { private final IStockUpdateRecordService iStockUpdateRecordService;// 库存更新记录服务 private final UploadRecordService uploadRecordService;// 文件上传记录服务 private final InventoryHistoryService inventoryHistoryService; + private final DbTransUtils dbTransUtils; /** * 发送正常的任务 @@ -103,12 +105,12 @@ public class WmsJobServiceImplements implements IWmsJobService { continue; } } - if (task.getTaskPriority() == 1) { - if (Objects.equals(task.getTaskType(), TaskType.OUT.getCode()) - && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())) { - continue; - } - } +// if (task.getTaskPriority() == 1) { +// if (Objects.equals(task.getTaskType(), TaskType.OUT.getCode()) +// && task.getIsPicking() == 1 && StringUtils.isNotEmpty(task.getPickStand())) { +// continue; +// } +// } // 创建发送的任务 WcsTaskRequest tempTask = new WcsTaskRequest(); tempTask.setTaskId(task.getTaskGroup()); @@ -127,48 +129,50 @@ public class WmsJobServiceImplements implements IWmsJobService { // 已经发送过的任务组 taskGroupIds.add(task.getTaskGroup()); } - if (request.size() == 0) { + 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())); - } 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发送任务地址为空。"); - } + // 下面这行代码模拟wcs下发成功 + simulateSendPickOutTasks(taskGroupIds, Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); +// // 发送任务 +// 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())); +// } 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)); @@ -572,30 +576,32 @@ public class WmsJobServiceImplements implements IWmsJobService { requestSingle.setRemark("站台拣选任务"); request.add(requestSingle); } - if (!request.isEmpty()) { - // 发送任务 - String url = configMap.get(ConfigMapKeyEnum.URL_WCS_PICK_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发送拣选任务", "setConveyTask", convertJsonString(request), convertJsonString(result), url, LocalDateTime.now(), "WMS")); - } catch (Exception e) { - logger.error("插入日志错误。"); - } - if (result != null && Objects.equals(ResponseCode.OK.getCode(), result.getCode())) { - logger.info("发送拣选任务成功。"); - pickTaskService.update(new LambdaUpdateWrapper() - .set(PickTask::getPickStatus, PickTaskStatusEnum.SEND.getCode()) - .in(PickTask::getVehicleId, vehicleAndStansMap.keySet()) - .eq(PickTask::getPickStatus, PickTaskStatusEnum.NEW.getCode())); - } else { - logger.error("发送拣选任务错误:{}", convertJsonString(result)); - } - } else { - logger.error("WCS发送拣选任务地址为空。"); - } - } + // 下面是模拟发送wcs拣选任务 + simulateSendPickTasks(vehicleAndStansMap.keySet().stream().toList()); +// if (!request.isEmpty()) { +// // 发送任务 +// String url = configMap.get(ConfigMapKeyEnum.URL_WCS_PICK_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发送拣选任务", "setConveyTask", convertJsonString(request), convertJsonString(result), url, LocalDateTime.now(), "WMS")); +// } catch (Exception e) { +// logger.error("插入日志错误。"); +// } +// if (result != null && Objects.equals(ResponseCode.OK.getCode(), result.getCode())) { +// logger.info("发送拣选任务成功。"); +// pickTaskService.update(new LambdaUpdateWrapper() +// .set(PickTask::getPickStatus, PickTaskStatusEnum.SEND.getCode()) +// .in(PickTask::getVehicleId, vehicleAndStansMap.keySet()) +// .eq(PickTask::getPickStatus, PickTaskStatusEnum.NEW.getCode())); +// } else { +// logger.error("发送拣选任务错误:{}", convertJsonString(result)); +// } +// } else { +// logger.error("WCS发送拣选任务地址为空。"); +// } +// } } catch (Exception exception) { logger.error("向WCS发送拣选任务时发生异常:{}", convertJsonString(exception)); throw new Exception("向WCS发送拣选任务时发生异常。"); @@ -1463,13 +1469,13 @@ public class WmsJobServiceImplements implements IWmsJobService { /** * 模拟出库发送成功 - * @param taskGroupIds - * @param pickVehicleIds - * @param needAddStandStackerTasks - * @param needRemoveStandStackerTasks + * @param taskGroupIds 任务组 + * @param pickVehicleIds 拣选料箱id + * @param needAddStandStackerTasks 需要添加的堆垛机站台任务 + * @param needRemoveStandStackerTasks 需要移除的堆垛机站台任务 */ void simulateSendPickOutTasks(List taskGroupIds, List pickVehicleIds, List needAddStandStackerTasks, List needRemoveStandStackerTasks) { - logger.info("发送WCS拣选出库任务成功。"); + logger.info("模拟发送wcs任务。"); taskService.update(new LambdaUpdateWrapper() .set(Task::getTaskStatus, WmsTaskStatus.WAIT.getCode()) .in(Task::getTaskGroup, taskGroupIds) @@ -1481,14 +1487,30 @@ public class WmsJobServiceImplements implements IWmsJobService { .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); + if (!needAddStandStackerTasks.isEmpty()) { + standStackerTaskService.saveBatch(needAddStandStackerTasks); } - standStackerTaskBakService.saveBatch(needSaveRecords); + if (!needRemoveStandStackerTasks.isEmpty()) { + 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); + } + } + + /** + * 模拟发送拣选任务 + * @param vehicleIds 载具号 + */ + void simulateSendPickTasks(List vehicleIds) { + logger.info("模拟发送拣选任务。"); + dbTransUtils.useTran(() -> pickTaskService.update(new LambdaUpdateWrapper() + .set(PickTask::getPickStatus, PickTaskStatusEnum.SEND.getCode()) + .in(PickTask::getVehicleId, vehicleIds) + .eq(PickTask::getPickStatus, PickTaskStatusEnum.NEW.getCode()))); } } diff --git a/src/main/java/com/wms/service/business/serviceImplements/WorkServiceImplements.java b/src/main/java/com/wms/service/business/serviceImplements/WorkServiceImplements.java index fa2750b..88f863e 100644 --- a/src/main/java/com/wms/service/business/serviceImplements/WorkServiceImplements.java +++ b/src/main/java/com/wms/service/business/serviceImplements/WorkServiceImplements.java @@ -6,10 +6,12 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.wms.constants.enums.*; import com.wms.entity.app.dto.WorkCenterAndOrderDto; +import com.wms.entity.app.dto.extend.StockDetailInfo; import com.wms.entity.table.*; import com.wms.service.*; import com.wms.service.business.IWmsTaskService; import com.wms.service.business.IWorkService; +import com.wms.utils.DbTransUtils; import com.wms.utils.StringUtils; import lombok.RequiredArgsConstructor; import org.slf4j.Logger; @@ -57,6 +59,7 @@ public class WorkServiceImplements implements IWorkService { private final WorkFlowLastService workFlowLastService;// 服务 private final List workCreatingStations = new ArrayList<>();// 当前正在创建任务的站台 private final VehicleService vehicleService;// 料箱服务 + private final DbTransUtils dbTransUtils;// 事务事务工具类 //获取配置文件的是否添加了需求时间 @@ -267,6 +270,478 @@ public class WorkServiceImplements implements IWorkService { } } + /** + * 新的执行工作方法 + */ + @Override + public void doWorkMethod2() { + // 查询一些配置信息 + String max_vehicle_nums = configMap.get(ConfigMapKeyEnum.MAX_VEHICLE_NUMS.getConfigKey()); + String max_vehicle_nums_before = configMap.get(ConfigMapKeyEnum.MAX_VEHICLE_BEFORE.getConfigKey()); + String max_vehicle_nums_after = configMap.get(ConfigMapKeyEnum.MAX_VEHICLE_AFTER.getConfigKey()); + String max_stand_vehicle_nums = configMap.get(ConfigMapKeyEnum.MAX_STAND_VEHICLE_NUMS.getConfigKey()); + if (!"1".equals(configMap.get(ConfigMapKeyEnum.SAME_AREA.getConfigKey()))) { + if (StringUtils.isEmpty(max_vehicle_nums) || StringUtils.isEmpty(max_stand_vehicle_nums)) { + logger.info("允许不同区域时配置未生成。"); + return; + } + } else { + if (StringUtils.isEmpty(max_vehicle_nums_before) || StringUtils.isEmpty(max_vehicle_nums_after) || StringUtils.isEmpty(max_stand_vehicle_nums)) { + logger.info("不允许不同区域时配置未生成。"); + return; + } + } + // 查找到未完成的工作 + List unfinishedWorkFlowList = workFlowService.list(new LambdaQueryWrapper() + .notIn(WorkFlow::getWorkStatus, -1, 2)); + if (unfinishedWorkFlowList.isEmpty()) { + // 没有未完成的工作 + logger.info("没有未完成的工作。"); + return; + } + // 查询拣选任务 + List pickTaskList = pickTaskService.list(); + // 本次可以出库的站台 + List thisTimeCanOutStandIds = new ArrayList<>(); + if (!"1".equals(configMap.get(ConfigMapKeyEnum.SAME_AREA.getConfigKey()))) { + List standIdsTotal = List.of("ASRS-#1", "ASRS-#2", "ASRS-#3", "ASRS-#4", "ASRS-#5", "ASRS-#6", "ASRS-#7", "ASRS-#8", "ASRS-#9"); + int maxVehicleNums = Integer.parseInt(max_vehicle_nums);// 线体最大箱子数量 + // 根据载具号map一下 + List outVehicleIdList = pickTaskList.stream().map(PickTask::getVehicleId).distinct().toList(); + if (outVehicleIdList.size() < maxVehicleNums) { + thisTimeCanOutStandIds.addAll(standIdsTotal); + } + } else { + List standIdsBefore = List.of("ASRS-#1", "ASRS-#2", "ASRS-#3", "ASRS-#4", "ASRS-#5"); + List standIdsAfter = List.of("ASRS-#6", "ASRS-#7", "ASRS-#8", "ASRS-#9"); + int maxVehicleNumsBefore = Integer.parseInt(max_vehicle_nums_before);// 前区线体最大箱子数量 + int maxVehicleNumsAfter = Integer.parseInt(max_vehicle_nums_after);// 后区线体最大箱子数量 + Map vehicleMapBefore = new HashMap<>(); + Map vehicleMapAfter = new HashMap<>(); + for (PickTask tempPickTask : pickTaskList) { + // 前区箱子 + if (standIdsBefore.contains(tempPickTask.getStandId()) && !vehicleMapBefore.containsKey(tempPickTask.getVehicleId())) { + vehicleMapBefore.put(tempPickTask.getVehicleId(), 1); + } + // 后区箱子 + if (standIdsAfter.contains(tempPickTask.getStandId()) && !vehicleMapAfter.containsKey(tempPickTask.getVehicleId())) { + vehicleMapAfter.put(tempPickTask.getVehicleId(), 1); + } + } + // 前区可以 + if (vehicleMapBefore.size() < maxVehicleNumsBefore) { + thisTimeCanOutStandIds.addAll(standIdsBefore); + } + // 后区可以 + if (vehicleMapAfter.size() < maxVehicleNumsAfter) { + thisTimeCanOutStandIds.addAll(standIdsAfter); + } + } + if (thisTimeCanOutStandIds.isEmpty()) { + // 没有可出库的站台 + logger.info("本次无可需要出库的站台。"); + return; + } + // 找出所有可用设备 + List stands = standService.list(new LambdaQueryWrapper() + .eq(Stand::getIsLock, 0).eq(Stand::getStandStatus, 0)); + // 备料站台---从9号站台开始 + List canUsePickStands = stands.stream().filter(stand -> stand.getStandType() == 2 && thisTimeCanOutStandIds.contains(stand.getStandId())).sorted(Comparator.comparing(Stand::getStandId).reversed()).toList(); + // 找出所有可用堆垛机---从5号堆垛机开始 + List stackerList = stands.stream().filter(stand -> stand.getStandType() == 3).sorted(Comparator.comparingInt(Stand::getEquipmentId).reversed()).toList(); + if (canUsePickStands.isEmpty() || stackerList.isEmpty()) { + // 没有可用站台或者可用堆垛机 + logger.info("没有可用站台或者可用堆垛机。"); + return; + } + List canUseStandIdList = new ArrayList<>(); + for (Stand canUseStand : canUsePickStands) { + // 查找这个站台已经生成的拣选任务 + List pickTasksOfThisStand = pickTaskList.stream().filter(pickTask -> Objects.equals(pickTask.getStandId(), canUseStand.getStandIp())).distinct().toList(); + if (pickTasksOfThisStand.size() > Integer.parseInt(max_vehicle_nums_before)) { + // 此站台已生成任务超过阈值 + logger.info("站台{}已生成任务数量超过阈值。", canUseStand.getStandId()); + continue; + } + canUseStandIdList.add(canUseStand.getStandId()); + } + // 需要更新的数据 + List thisTimeOutVehicleIds = new ArrayList<>();// 本次出库的载具号 + List needAddTaskList = new ArrayList<>();// 需要添加的任务数据 + Map needAddPickTaskMap = new HashMap<>();// 需要添加的拣选任务数据 + List needUpdateWorkFlowIds = new ArrayList<>();// 需要更新的工作流id + List needUpdateOrderIds = new ArrayList<>();// 需要更新的工单id + List thisTimeCannotOutVehicleIds = new ArrayList<>();// 本次不能出库的载具号 + // 查询出所有的库存 + List allStockList = stockService.list(); + // 第一次循环,分出已经出库的物料。 + Map outedGoodsIdMap = new HashMap<>(); + for (Stock stock : allStockList) { + if (Objects.equals(stock.getStockStatus(), StockStatus.OK.getCode()) || Objects.equals(stock.getStockStatus(), StockStatus.BACK.getCode()) || Objects.equals(stock.getStockStatus(), StockStatus.LOCK.getCode())) { + continue; + } + String goodsId = stock.getGoodsRelated().getGoodsId(); + if (!outedGoodsIdMap.containsKey(goodsId)) { + outedGoodsIdMap.put(goodsId, 1); + } + } + // 查询出当前所有的出库任务(拣选) + List outTaskList = taskService.list(new LambdaQueryWrapper() + .eq(Task::getTaskType, TaskType.OUT.getCode()) + .eq(Task::getTaskPriority, 1) + .eq(Task::getIsPicking, 1)); + // 分出在库的物料 + List onStockStockList = allStockList.stream().filter(stock -> Objects.equals(stock.getStockStatus(), StockStatus.OK.getCode())).sorted(Comparator.comparing(Stock::getCreateTime)).toList(); + for (String standId : canUseStandIdList) { + Map equipVehicleOfThisStandMap = new HashMap<>(); + // 生成这个站台在这个设备出库的箱子 + for (Task task : outTaskList) { + if (StringUtils.isEmpty(task.getPickStand())) { + // 没有站台,那么跳过 + continue; + } + int equipmentId = getStackerIdByLocationId(task.getOrigin()); + if (equipmentId != 0 && !equipVehicleOfThisStandMap.containsKey(equipmentId) && Objects.equals(task.getPickStand(), standId)) { + // 当前设备当前站台的任务 + equipVehicleOfThisStandMap.put(equipmentId, task.getVehicleId()); + } + } + Map thisStandOutVehicleMap = new HashMap<>();// 键为载具号,值为库存id + for (Stock stock : onStockStockList) { + if (!Objects.equals(stock.getStockStatus(), StockStatus.OK.getCode())) { + // 只允许在库库存操作 + continue; + } + // 这个载具本次不允许出库 + if (thisTimeCannotOutVehicleIds.contains(stock.getVehicleId())) { + continue; + } + // 同一物料同一时间只能在外面一个箱子 + if (outedGoodsIdMap.containsKey(stock.getGoodsRelated().getGoodsId())) { + thisTimeCannotOutVehicleIds.add(stock.getVehicleId()); + continue; + } + // 如果载具在本次出库的载具列表中,那么修改库存状态 + if (thisTimeOutVehicleIds.contains(stock.getVehicleId())) { + stock.setStockStatus(StockStatus.OUT.getCode()); + continue; + } + // 获取这条库存的设备号 + int equipmentId = getStackerIdByLocationId(stock.getLocationId()); + if (equipmentId == 0) { + logger.info("载具{},库位{},未查到对应的设备号。", stock.getVehicleId(), stock.getLocationId()); + continue; + } + // 判断这个设备能否出库 + if (equipVehicleOfThisStandMap.containsKey(equipmentId)) { + // 这个站台在这台设备已经生成过任务,不再重复生成 + continue; + } + // 判断这个库存是否被当前站台需要 + BigDecimal originNum = stock.getGoodsRelated().getRemainNum(); + BigDecimal afterNum = stock.getGoodsRelated().getRemainNum(); + for (WorkFlow workFlow : unfinishedWorkFlowList) { + if (afterNum.compareTo(BigDecimal.ZERO) <= 0) { + break; + } + if (Objects.equals(workFlow.getWorkStation(), standId) && Objects.equals(workFlow.getGoodsId(), stock.getGoodsRelated().getGoodsId())) { + BigDecimal needNum = workFlow.getNeedNum().subtract(workFlow.getDistributedNum() == null ? BigDecimal.ZERO : workFlow.getDistributedNum()); + if (needNum.compareTo(BigDecimal.ZERO) <= 0) { + continue; + } + if (afterNum.compareTo(needNum) >= 0) { + afterNum = afterNum.subtract(needNum); + workFlow.setDistributedNum(workFlow.getNeedNum()); + } else { + afterNum = BigDecimal.ZERO; + workFlow.setDistributedNum(workFlow.getDistributedNum() == null ? afterNum : workFlow.getDistributedNum().add(afterNum)); + } + workFlow.setWorkStatus(1); + // 添加需要更新的工作流id + if (!needUpdateWorkFlowIds.contains(workFlow.getWorkFlowId())) { + needUpdateWorkFlowIds.add(workFlow.getWorkFlowId()); + } + // 添加需要更新的工单id + if (!needUpdateOrderIds.contains(workFlow.getOrderId())) { + needUpdateOrderIds.add(workFlow.getOrderId()); + } + } + } + if (afterNum.compareTo(originNum) != 0) { + // 使用过该库存,更新数量 + stock.setStockStatus(StockStatus.OUT.getCode()); + StockDetailInfo goodsRelated = stock.getGoodsRelated(); + goodsRelated.setRemainNum(afterNum); + stock.setGoodsRelated(goodsRelated); + // 创建出库任务 + Task vehicleOutTask = new Task(); + vehicleOutTask.setTaskId(generateId("CK_")); + vehicleOutTask.setTaskType(TaskType.OUT.getCode()); + vehicleOutTask.setTaskGroup(generateId("")); + vehicleOutTask.setTaskStatus(WmsTaskStatus.NEW.getCode()); + vehicleOutTask.setTaskPriority(1); + vehicleOutTask.setVehicleId(stock.getVehicleId()); + vehicleOutTask.setUserName("WMS_AUTO"); + vehicleOutTask.setOrigin(stock.getLocationId()); + vehicleOutTask.setDestination(""); + vehicleOutTask.setCreateTime(LocalDateTime.now()); + vehicleOutTask.setIsPicking(1); + vehicleOutTask.setPickStand(standId); + needAddTaskList.add(vehicleOutTask); + // 创建拣选任务 + String key = stock.getVehicleId() + "_" + standId; + // 此次新建的保存过 + if (needAddPickTaskMap.containsKey(key)) { + continue; + } + // 暂存拣选任务 + PickTask tempPickTask = new PickTask(); + tempPickTask.setPickTaskId(key); + tempPickTask.setVehicleId(stock.getVehicleId()); + tempPickTask.setStandId(standId); + tempPickTask.setPickStatus(PickTaskStatusEnum.TEMP.getCode()); + tempPickTask.setLastUpdateTime(LocalDateTime.now()); + needAddPickTaskMap.put(key, tempPickTask); + // 添加本次出库载具 + thisTimeOutVehicleIds.add(stock.getVehicleId()); + // 添加设备 + equipVehicleOfThisStandMap.put(equipmentId, stock.getVehicleId()); + // 此处是为了将同一个载具尽量在同一个站台捡完 + thisStandOutVehicleMap.put(stock.getVehicleId(), stock.getStockId()); + } + } + for (Stock stock : onStockStockList) { + if (Objects.equals(stock.getStockStatus(), StockStatus.OK.getCode())) { + continue; + } + // 这个站台本次出库的载具 + if (thisStandOutVehicleMap.containsKey(stock.getVehicleId()) && !Objects.equals(thisStandOutVehicleMap.get(stock.getVehicleId()), stock.getStockId())) { + // 判断这个料当前站台需不需要---主要消耗一下数量 + BigDecimal originNum = stock.getGoodsRelated().getRemainNum(); + BigDecimal afterNum = stock.getGoodsRelated().getRemainNum(); + for (WorkFlow workFlow : unfinishedWorkFlowList) { + if (afterNum.compareTo(BigDecimal.ZERO) <= 0) { + break; + } + if (Objects.equals(workFlow.getWorkStation(), standId) && Objects.equals(workFlow.getGoodsId(), stock.getGoodsRelated().getGoodsId())) { + BigDecimal needNum = workFlow.getNeedNum().subtract(workFlow.getDistributedNum() == null ? BigDecimal.ZERO : workFlow.getDistributedNum()); + if (needNum.compareTo(BigDecimal.ZERO) <= 0) { + continue; + } + if (afterNum.compareTo(needNum) >= 0) { + afterNum = afterNum.subtract(needNum); + workFlow.setDistributedNum(workFlow.getNeedNum()); + } else { + afterNum = BigDecimal.ZERO; + workFlow.setDistributedNum(workFlow.getDistributedNum() == null ? afterNum : workFlow.getDistributedNum().add(afterNum)); + } + workFlow.setWorkStatus(1); + // 添加需要更新的工作流id + if (!needUpdateWorkFlowIds.contains(workFlow.getWorkFlowId())) { + needUpdateWorkFlowIds.add(workFlow.getWorkFlowId()); + } + // 添加需要更新的工单id + if (!needUpdateOrderIds.contains(workFlow.getOrderId())) { + needUpdateOrderIds.add(workFlow.getOrderId()); + } + } + } + if (afterNum.compareTo(originNum) != 0) { + // 使用过该库存,更新数量 + stock.setStockStatus(StockStatus.OUT.getCode()); + StockDetailInfo goodsRelated = stock.getGoodsRelated(); + goodsRelated.setRemainNum(afterNum); + stock.setGoodsRelated(goodsRelated); + } + } + } + } + // 再循环一次库存,只判断出库的 + for (Stock stock : onStockStockList) { + if (!Objects.equals(stock.getStockStatus(), StockStatus.OUT.getCode())) { + continue; + } + if (!thisTimeOutVehicleIds.contains(stock.getVehicleId())) { + continue; + } + // 判断这个料当前站台需不需要---主要消耗一下数量 + BigDecimal originNum = stock.getGoodsRelated().getRemainNum(); + BigDecimal afterNum = stock.getGoodsRelated().getRemainNum(); + for (WorkFlow workFlow : unfinishedWorkFlowList) { + if (afterNum.compareTo(BigDecimal.ZERO) <= 0) { + break; + } + if (Objects.equals(workFlow.getGoodsId(), stock.getGoodsRelated().getGoodsId())) { + BigDecimal needNum = workFlow.getNeedNum().subtract(workFlow.getDistributedNum() == null ? BigDecimal.ZERO : workFlow.getDistributedNum()); + if (needNum.compareTo(BigDecimal.ZERO) <= 0) { + continue; + } + if (afterNum.compareTo(needNum) >= 0) { + afterNum = afterNum.subtract(needNum); + workFlow.setDistributedNum(workFlow.getNeedNum()); + } else { + afterNum = BigDecimal.ZERO; + workFlow.setDistributedNum(workFlow.getDistributedNum() == null ? afterNum : workFlow.getDistributedNum().add(afterNum)); + } + workFlow.setWorkStatus(1); + // 添加需要更新的工作流id + if (!needUpdateWorkFlowIds.contains(workFlow.getWorkFlowId())) { + needUpdateWorkFlowIds.add(workFlow.getWorkFlowId()); + } + // 添加需要更新的工单id + if (!needUpdateOrderIds.contains(workFlow.getOrderId())) { + needUpdateOrderIds.add(workFlow.getOrderId()); + } + // 创建拣选任务 + String key = stock.getVehicleId() + "_" + workFlow.getWorkStation(); + // 此次新建的保存过 + if (needAddPickTaskMap.containsKey(key)) { + continue; + } + // 暂存拣选任务 + PickTask tempPickTask = new PickTask(); + tempPickTask.setPickTaskId(key); + tempPickTask.setVehicleId(stock.getVehicleId()); + tempPickTask.setStandId(workFlow.getWorkStation()); + tempPickTask.setPickStatus(PickTaskStatusEnum.TEMP.getCode()); + tempPickTask.setLastUpdateTime(LocalDateTime.now()); + needAddPickTaskMap.put(key, tempPickTask); + } + } + if (afterNum.compareTo(originNum) != 0) { + // 使用过该库存,更新数量 + stock.setStockStatus(StockStatus.OUT.getCode()); + StockDetailInfo goodsRelated = stock.getGoodsRelated(); + goodsRelated.setRemainNum(afterNum); + stock.setGoodsRelated(goodsRelated); + } + } + // 处理需要更新的数据 + List finalUpdateWorkFlowList = unfinishedWorkFlowList.stream().filter(workFlow -> needUpdateWorkFlowIds.contains(workFlow.getWorkFlowId())).toList(); + boolean doTransResult = dbTransUtils.useTran(() -> { + if (!thisTimeOutVehicleIds.isEmpty()) { + vehicleService.update(new LambdaUpdateWrapper() + .set(Vehicle::getVehicleStatus, VehicleStatus.OUT.getCode()) + .in(Vehicle::getVehicleId, thisTimeOutVehicleIds)); + stockService.update(new LambdaUpdateWrapper() + .set(Stock::getStockStatus, StockStatus.OUT.getCode()) + .in(Stock::getVehicleId, thisTimeOutVehicleIds)); + if (!needAddTaskList.isEmpty()) { + taskService.saveBatch(needAddTaskList); + } + if (!needAddPickTaskMap.isEmpty()) { + pickTaskService.saveBatch(needAddPickTaskMap.values()); + } + if (!finalUpdateWorkFlowList.isEmpty()) { + workFlowService.updateBatchById(finalUpdateWorkFlowList); + } + if (!needUpdateOrderIds.isEmpty()) { + kateOrdersService.update(new LambdaUpdateWrapper() + .set(KateOrders::getOrderStatus, 2) + .in(KateOrders::getOrderId, needUpdateOrderIds)); + } + } + }); + if (!doTransResult) { + logger.error("解析工作生成任务时,数据库事务执行错误。"); + } + } + + /** + * 修复工作 + */ + @Override + public void repairWork() { + // 查找到未完成的工作 + List unfinishedWorkFlowList = workFlowService.list(new LambdaQueryWrapper() + .notIn(WorkFlow::getWorkStatus, -1, 2)); + if (unfinishedWorkFlowList.isEmpty()) { + // 没有未完成的工作 + logger.info("没有未完成的待修复的工作。"); + return; + } + // 查找所有的库存 + List stockList = stockService.list(new LambdaQueryWrapper() + .ne(Stock::getStockStatus, StockStatus.LOCK.getCode())); + // 根据在库物料号map一下 + Map> onStockGoodsIdToVehicleIdsMap = new HashMap<>(); + // 根据不在库的物料号map一下 + Map> notOnStockGoodsIdToVehicleIdsMap = new HashMap<>(); + for (Stock stock : stockList) { + String goodsId = stock.getGoodsRelated().getGoodsId(); + if (Objects.equals(stock.getStockStatus(), StockStatus.OK.getCode())) { + if (onStockGoodsIdToVehicleIdsMap.containsKey(goodsId)) { + List oldVehicleList = onStockGoodsIdToVehicleIdsMap.get(goodsId); + oldVehicleList.add(stock.getVehicleId()); + onStockGoodsIdToVehicleIdsMap.put(goodsId, oldVehicleList); + } else { + onStockGoodsIdToVehicleIdsMap.put(goodsId, new ArrayList<>(List.of(stock.getVehicleId()))); + } + } else { + if (notOnStockGoodsIdToVehicleIdsMap.containsKey(goodsId)) { + List oldVehicleList = notOnStockGoodsIdToVehicleIdsMap.get(goodsId); + oldVehicleList.add(stock.getVehicleId()); + notOnStockGoodsIdToVehicleIdsMap.put(goodsId, oldVehicleList); + } else { + notOnStockGoodsIdToVehicleIdsMap.put(goodsId, new ArrayList<>(List.of(stock.getVehicleId()))); + } + } + } + List needUpdateWorkFlowList = new ArrayList<>(); + for (WorkFlow workFlow : unfinishedWorkFlowList) { + if (workFlow.getPickedNum().compareTo(workFlow.getNeedNum()) >= 0) { + // 实际已经完成但未标记为完成的工作流 + workFlow.setDistributedNum(workFlow.getPickedNum()); + workFlow.setWorkStatus(2); + needUpdateWorkFlowList.add(workFlow); + continue; + } + // 需求的数量未全部分配时,查询是否还有库存 + if (!onStockGoodsIdToVehicleIdsMap.containsKey(workFlow.getGoodsId()) && !notOnStockGoodsIdToVehicleIdsMap.containsKey(workFlow.getGoodsId())) { + // 缺料 + workFlow.setWorkStatus(2); + if (StringUtils.isEmpty(workFlow.getOpUser())) { + workFlow.setOpUser("缺料系统自动完成。"); + } else { + workFlow.setOpUser(workFlow.getOpUser() + ";缺料系统自动完成。"); + } + needUpdateWorkFlowList.add(workFlow); + continue; + } + // 有在库数量但是没有非在库数量时 + if (onStockGoodsIdToVehicleIdsMap.containsKey(workFlow.getGoodsId()) && !notOnStockGoodsIdToVehicleIdsMap.containsKey(workFlow.getGoodsId())) { + // 更新已分配数量 + workFlow.setDistributedNum(workFlow.getPickedNum()); + needUpdateWorkFlowList.add(workFlow); + } + } + // 更新工作流 + boolean doTransResult = dbTransUtils.useTran(() -> { + if (!needUpdateWorkFlowList.isEmpty()) { + workFlowService.updateBatchById(needUpdateWorkFlowList); + } + }); + if (!doTransResult) { + logger.error("修复工作流时,执行数据库事务发生错误。"); + } + } + + /** + * 根据库位号获得设备号 + * @param locationId 库位号 + * @return 设备号/堆垛机号 + */ + private int getStackerIdByLocationId(String locationId) { + if (StringUtils.isEmpty(locationId)) { + return 0; + } + Location targetLocation = instantLocationMap.get(locationId); + if (targetLocation == null) { + return 0; + } + return targetLocation.getEquipmentId(); + } + /** * 新版完成工作 * diff --git a/src/main/java/com/wms/service/quartz_job/serviceImpl/JobServiceImpl.java b/src/main/java/com/wms/service/quartz_job/serviceImpl/JobServiceImpl.java index d5b3b01..5d0835f 100644 --- a/src/main/java/com/wms/service/quartz_job/serviceImpl/JobServiceImpl.java +++ b/src/main/java/com/wms/service/quartz_job/serviceImpl/JobServiceImpl.java @@ -93,7 +93,7 @@ public class JobServiceImpl implements IJobService { // 这里写死,五个定时器 jobBeans.add(new JobBean("CommonTaskSender", CommonTaskSender.class, "0/2 * * * * ?", 2000, JobTimerTypeEnums.SIMPLE.getType(), 1)); jobBeans.add(new JobBean("PickTaskSender", PickTaskSender.class, "0/2 * * * * ?", 2000, JobTimerTypeEnums.SIMPLE.getType(), 1)); - jobBeans.add(new JobBean("PickOutTaskSender", PickOutTaskSender.class, "0/2 * * * * ?", 2000, JobTimerTypeEnums.SIMPLE.getType(), 1)); + jobBeans.add(new JobBean("PickOutTaskSender", PickOutTaskSender.class, "0/2 * * * * ?", 2000, JobTimerTypeEnums.SIMPLE.getType(), 0)); // jobBeans.add(new JobBean("KateWorkExecutor", KateWorkExecutor.class, "0/20 * * * * ?", 20000, JobTimerTypeEnums.SIMPLE.getType(), 1)); jobBeans.add(new JobBean("KateWorkExecutor", KateWorkExecutor.class, "0 0 * * * ?", 20000, JobTimerTypeEnums.SIMPLE.getType(), 1)); jobBeans.add(new JobBean("DataClearExecutor", DataClearExecutor.class, "0 0 23 * * ?", 2000, JobTimerTypeEnums.CRON.getType(), 1)); diff --git a/src/main/java/com/wms/utils/DbTransUtils.java b/src/main/java/com/wms/utils/DbTransUtils.java new file mode 100644 index 0000000..4698a8d --- /dev/null +++ b/src/main/java/com/wms/utils/DbTransUtils.java @@ -0,0 +1,33 @@ +package com.wms.utils; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.DefaultTransactionDefinition; + +@Component +@RequiredArgsConstructor +public class DbTransUtils { + private final PlatformTransactionManager transactionManager; + + /** + * 执行一个事务方法 + * @param baseTran 事务类 + * @return 执行结果 + */ + public boolean useTran(Runnable baseTran) { + DefaultTransactionDefinition def = new DefaultTransactionDefinition(); + def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); + TransactionStatus status = transactionManager.getTransaction(def); + try { + baseTran.run(); + transactionManager.commit(status); + return true; + } catch (Exception e) { + transactionManager.rollback(status); + return false; + } + } +}