| | |
| | | if (task.getTaskType().equals(TaskType.TASK_TYPE_IN.type)) { |
| | | //1.入库 |
| | | complateInstock(task, loginUserId); |
| | | } else if (task.getTaskType().equals(TaskType.TASK_TYPE_EMPITY_IN.type)) { |
| | | //10.空托入库 |
| | | complateEmpityInStock(task, loginUserId); |
| | | } else if (task.getTaskType().equals(TaskType.TASK_TYPE_PICK_IN.type) || task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type)) { |
| | | //53.拣料再入库 |
| | | //57.盘点再入库 |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void pubTaskToWcs(List<Task> tasks) { |
| | | WcsTaskParams taskParams = new WcsTaskParams(); |
| | | List<TaskItemParam> items = new ArrayList<>(); |
| | | /**任务下发接口*/ |
| | | String pubTakUrl = rcsApi.getHost() + ":" + rcsApi.getPort() + RcsConstant.pubTask; |
| | | |
| | | // 设置批次编号(使用第一个任务的barcode,如果为null则使用任务编码) |
| | | String batchNo = null; |
| | | if (!tasks.isEmpty()) { |
| | | Task firstTask = tasks.get(0); |
| | | batchNo = StringUtils.isNotBlank(firstTask.getBarcode()) |
| | | ? firstTask.getBarcode() |
| | | : firstTask.getTaskCode(); |
| | | } |
| | | if (StringUtils.isBlank(batchNo)) { |
| | | // 如果批次编号仍为空,生成一个默认值 |
| | | batchNo = "BATCH_" + System.currentTimeMillis(); |
| | | } |
| | | |
| | | taskParams.setBatchNo(batchNo); |
| | | log.info("设置批次编号:{}", batchNo); |
| | | |
| | | tasks.forEach(task -> { |
| | | for (Task task : tasks) { |
| | | WcsTaskParams taskParams = new WcsTaskParams(); |
| | | List<TaskItemParam> items = new ArrayList<>(); |
| | | |
| | | // 设置批次编号(使用当前任务的任务编码) |
| | | String batchNo = task.getTaskCode(); |
| | | if (StringUtils.isBlank(batchNo)) { |
| | | // 如果任务编号为空,生成一个默认值 |
| | | batchNo = "BATCH_" + System.currentTimeMillis(); |
| | | } |
| | | taskParams.setBatchNo(batchNo); |
| | | log.info("任务批次编号:{}", batchNo); |
| | | |
| | | // 构建当前任务的参数 |
| | | TaskItemParam itemParam = new TaskItemParam(); |
| | | //任务编码(对应seqNum) |
| | | itemParam.setTaskNo(task.getTaskCode()); |
| | |
| | | throw new CoolException("当前站点不是F.在库状态!!"); |
| | | } |
| | | } |
| | | if (station.getType().equals(StationTypeEnum.STATION_TYPE_NORMAL.type)) { |
| | | if (!station.getUseStatus().equals(LocStsType.LOC_STS_TYPE_O.type)) { |
| | | // 站点间移库需要获取目标站点 |
| | | BasStation targetStation = basStationService.getOne(new LambdaQueryWrapper<BasStation>().eq(BasStation::getStationName, task.getTargSite())); |
| | | if (Objects.isNull(targetStation)) { |
| | | throw new CoolException("目标站点不存在!!"); |
| | | } |
| | | if (targetStation.getType().equals(StationTypeEnum.STATION_TYPE_NORMAL.type)) { |
| | | if (!targetStation.getUseStatus().equals(LocStsType.LOC_STS_TYPE_O.type)) { |
| | | throw new CoolException("目标站点不是O.空闲状态!!"); |
| | | } |
| | | } |
| | | } |
| | | items.add(itemParam); |
| | | }); |
| | | taskParams.setTasks(items); |
| | | /**任务下发接口*/ |
| | | String pubTakUrl = rcsApi.getHost() + ":" + rcsApi.getPort() + RcsConstant.pubTask; |
| | | /**RCS基础配置链接*/ |
| | | log.info("========== 开始下发任务到RCS =========="); |
| | | log.info("RCS请求地址:{}", pubTakUrl); |
| | | log.info("批次编号:{}", batchNo); |
| | | log.info("任务数量:{}", tasks.size()); |
| | | log.info("任务列表详情:"); |
| | | tasks.forEach(task -> { |
| | | log.info(" - 任务编码:{},任务类型:{},源库位:{},目标库位:{},源站点:{},目标站点:{}", |
| | | taskParams.setTasks(items); |
| | | |
| | | // 记录当前任务信息 |
| | | log.info(" RCS- 任务编码:{},任务类型:{},源库位:{},目标库位:{},源站点:{},目标站点:{}", |
| | | task.getTaskCode(), task.getTaskType(), task.getOrgLoc(), |
| | | task.getTargLoc(), task.getOrgSite(), task.getTargSite()); |
| | | }); |
| | | log.info("请求参数:{}", JSONObject.toJSONString(taskParams)); |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | headers.add("Content-Type", "application/json"); |
| | | headers.add("api-version", "v2.0"); |
| | | HttpEntity httpEntity = new HttpEntity(taskParams, headers); |
| | | long startTime = System.currentTimeMillis(); |
| | | ResponseEntity<String> exchange = restTemplate.exchange(pubTakUrl, HttpMethod.POST, httpEntity, String.class); |
| | | long endTime = System.currentTimeMillis(); |
| | | log.info("RCS响应耗时:{}ms", (endTime - startTime)); |
| | | log.info("RCS响应状态码:{}", exchange.getStatusCode()); |
| | | log.info("RCS响应头:{}", exchange.getHeaders()); |
| | | log.info("RCS响应体:{}", exchange.getBody()); |
| | | if (Objects.isNull(exchange.getBody())) { |
| | | log.error("========== RCS任务下发失败 =========="); |
| | | log.error("RCS响应体为空,无法解析响应结果"); |
| | | log.error("请求地址:{}", pubTakUrl); |
| | | log.error("请求参数:{}", JSONObject.toJSONString(taskParams)); |
| | | throw new CoolException("任务下发失败,RCS响应体为空!!"); |
| | | } else { |
| | | log.info("RCS-请求参数:{}", JSONObject.toJSONString(taskParams)); |
| | | |
| | | // 发送当前任务 |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | headers.add("Content-Type", "application/json"); |
| | | headers.add("api-version", "v2.0"); |
| | | HttpEntity httpEntity = new HttpEntity(taskParams, headers); |
| | | |
| | | /**RCS基础配置链接*/ |
| | | log.info("========== 开始下发任务到RCS =========="); |
| | | log.info("请求RCS-地址:{}", pubTakUrl); |
| | | log.info("请求RCS-参数:{}", JSONObject.toJSONString(taskParams)); |
| | | long startTime = System.currentTimeMillis(); |
| | | ResponseEntity<String> exchange = null; |
| | | try { |
| | | ObjectMapper objectMapper = new ObjectMapper(); |
| | | objectMapper.coercionConfigDefaults() |
| | | .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty); |
| | | CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class); |
| | | log.info("RCS响应解析结果 - code:{},msg:{},data:{}", |
| | | result.getCode(), result.getMsg(), result.getData()); |
| | | if (result.getCode() == 200) { |
| | | log.info("RCS任务下发成功,开始更新任务状态"); |
| | | tasks.forEach(task -> { |
| | | log.info("更新任务状态 - 任务编码:{},任务类型:{}", task.getTaskCode(), task.getTaskType()); |
| | | exchange = restTemplate.exchange(pubTakUrl, HttpMethod.POST, httpEntity, String.class); |
| | | long endTime = System.currentTimeMillis(); |
| | | log.info("RCS响应耗时:{}ms", (endTime - startTime)); |
| | | log.info("RCS响应状态码:{}", exchange.getStatusCode()); |
| | | log.info("RCS响应头:{}", exchange.getHeaders()); |
| | | log.info("RCS响应体:{}", exchange.getBody()); |
| | | } catch (org.springframework.web.client.ResourceAccessException e) { |
| | | long endTime = System.currentTimeMillis(); |
| | | log.error("========== RCS任务下发资源访问异常 =========="); |
| | | log.error("请求RCS-资源访问异常(可能包含连接超时),耗时:{}ms,任务编码:{}", (endTime - startTime), task.getTaskCode(), e); |
| | | log.error("请求RCS-请求地址:{}", pubTakUrl); |
| | | log.error("请求RCS-请求参数:{}", JSONObject.toJSONString(taskParams)); |
| | | // 检查是否是连接超时异常 |
| | | Throwable cause = e.getCause(); |
| | | String errorMsg = e.getMessage(); |
| | | if (cause instanceof java.net.SocketTimeoutException || |
| | | (cause instanceof java.net.ConnectException && cause.getMessage() != null && cause.getMessage().contains("timed out")) || |
| | | (errorMsg != null && (errorMsg.contains("Connection timed out") || errorMsg.contains("timed out") || errorMsg.contains("timeout")))) { |
| | | throw new CoolException("RCS连接超时,任务下发失败!任务编码:" + task.getTaskCode() + ",错误信息:" + errorMsg); |
| | | } |
| | | throw new CoolException("RCS资源访问异常,任务下发失败!任务编码:" + task.getTaskCode() + ",错误信息:" + errorMsg); |
| | | } catch (Exception e) { |
| | | long endTime = System.currentTimeMillis(); |
| | | log.error("========== RCS任务下发异常 =========="); |
| | | log.error("请求RCS-异常,耗时:{}ms,任务编码:{}", (endTime - startTime), task.getTaskCode(), e); |
| | | log.error("请求RCS-地址:{}", pubTakUrl); |
| | | log.error("请求RCS-参数:{}", JSONObject.toJSONString(taskParams)); |
| | | String errorMsg = e.getMessage(); |
| | | // 检查是否是连接超时相关的异常 |
| | | if (errorMsg != null && (errorMsg.contains("Connection timed out") || errorMsg.contains("timed out") || errorMsg.contains("timeout"))) { |
| | | throw new CoolException("RCS连接超时,任务下发失败!任务编码:" + task.getTaskCode() + ",错误信息:" + errorMsg); |
| | | } |
| | | throw new CoolException("RCS任务下发异常!任务编码:" + task.getTaskCode() + ",错误信息:" + errorMsg); |
| | | } |
| | | |
| | | if (Objects.isNull(exchange) || Objects.isNull(exchange.getBody())) { |
| | | log.error("========== RCS任务下发失败 =========="); |
| | | log.error("请求RCS-RCS响应体为空,无法解析响应结果"); |
| | | log.error("请求RCS-地址:{}", pubTakUrl); |
| | | log.error("请求RCS-参数:{}", JSONObject.toJSONString(taskParams)); |
| | | log.error("请求RCS-失败的任务编码:{}", task.getTaskCode()); |
| | | throw new CoolException("任务下发失败,RCS响应体为空!!任务编码:" + task.getTaskCode()); |
| | | } else { |
| | | try { |
| | | ObjectMapper objectMapper = new ObjectMapper(); |
| | | objectMapper.coercionConfigDefaults() |
| | | .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty); |
| | | CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class); |
| | | log.info("RCS响应解析结果 - code:{},msg:{},data:{}", |
| | | result.getCode(), result.getMsg(), result.getData()); |
| | | if (result.getCode() == 200) { |
| | | log.info("RCS任务下发成功,开始更新任务状态 - 任务编码:{}", task.getTaskCode()); |
| | | if (task.getTaskType().equals(TaskType.TASK_TYPE_IN.type) |
| | | || task.getTaskType().equals(TaskType.TASK_TYPE_PICK_IN.type) |
| | | || task.getTaskType().equals(TaskType.TASK_TYPE_CHECK_IN.type) |
| | |
| | | } |
| | | } |
| | | } |
| | | }); |
| | | log.info("========== RCS任务下发完成,共{}个任务状态已更新 ==========", tasks.size()); |
| | | } else { |
| | | log.error("========== RCS任务下发失败 =========="); |
| | | log.error("RCS返回错误 - code:{},msg:{},data:{}", |
| | | result.getCode(), result.getMsg(), result.getData()); |
| | | log.error("失败的任务列表:"); |
| | | tasks.forEach(task -> { |
| | | log.error(" - 任务编码:{},任务类型:{}", task.getTaskCode(), task.getTaskType()); |
| | | }); |
| | | // throw new CoolException("任务下发失败!!"); |
| | | } else { |
| | | log.error("========== RCS任务下发失败 =========="); |
| | | log.error("RCS返回错误 - code:{},msg:{},data:{}", |
| | | result.getCode(), result.getMsg(), result.getData()); |
| | | log.error("失败的任务编码:{},任务类型:{}", task.getTaskCode(), task.getTaskType()); |
| | | throw new CoolException("任务下发失败!!任务编码:" + task.getTaskCode()); |
| | | } |
| | | } catch (JsonProcessingException e) { |
| | | log.error("========== RCS任务下发异常 =========="); |
| | | log.error("解析RCS响应失败,响应体:{},任务编码:{}", exchange.getBody(), task.getTaskCode(), e); |
| | | throw new CoolException("解析RCS响应失败:" + e.getMessage() + ",任务编码:" + task.getTaskCode()); |
| | | } catch (Exception e) { |
| | | log.error("========== RCS任务下发异常 =========="); |
| | | log.error("任务下发过程中发生异常,任务编码:{}", task.getTaskCode(), e); |
| | | throw e; |
| | | } |
| | | } catch (JsonProcessingException e) { |
| | | log.error("========== RCS任务下发异常 =========="); |
| | | log.error("解析RCS响应失败,响应体:{}", exchange.getBody(), e); |
| | | throw new CoolException("解析RCS响应失败:" + e.getMessage()); |
| | | } catch (Exception e) { |
| | | log.error("========== RCS任务下发异常 =========="); |
| | | log.error("任务下发过程中发生异常", e); |
| | | throw e; |
| | | } |
| | | } |
| | | log.info("========== RCS任务下发完成,共{}个任务已处理 ==========", tasks.size()); |
| | | }/** |
| | | |
| | | |
| | |
| | | .set(WaitPakin::getUpdateBy, loginUserId) |
| | | .in(WaitPakin::getId, pakinIds))) { |
| | | throw new CoolException("组拖状态修改失败!!"); |
| | | } |
| | | |
| | | /**修改库位状态为F.在库*/ |
| | | if (!locService.update(new LambdaUpdateWrapper<Loc>().set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_F.type).eq(Loc::getCode, task.getTargLoc()))) { |
| | | throw new CoolException("库位状态修改失败!!"); |
| | | } |
| | | if (!this.update(new LambdaUpdateWrapper<Task>().eq(Task::getId, task.getId()).set(Task::getTaskStatus, TaskStsType.UPDATED_IN.id))) { |
| | | throw new CoolException("任务状态修改失败!!"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 空托入库完成 |
| | | * |
| | | * @param task |
| | | * @param loginUserId |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public synchronized void complateEmpityInStock(Task task, Long loginUserId) { |
| | | if (Objects.isNull(task)) { |
| | | return; |
| | | } |
| | | |
| | | Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getCode, task.getTargLoc())); |
| | | if (Objects.isNull(loc)) { |
| | | throw new CoolException("目标库位不存在!"); |
| | | } |
| | | |
| | | if (!loc.getUseStatus().equals(LocStsType.LOC_STS_TYPE_S.type)) { |
| | | throw new CoolException("当前库位状态不处于S.入库预约,不可执行入库操作!"); |
| | | } |
| | | |
| | | List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId())); |
| | | if (taskItems.isEmpty()) { |
| | | throw new CoolException("任务明细不存在!!"); |
| | | } |
| | | |
| | | //更新库位明细 |
| | | saveLocItem(taskItems, task.getId(), loginUserId); |
| | | |
| | | //空托入库不校验组托信息,直接处理任务明细 |
| | | //如果有任务明细关联了组托,也需要保存入出库明细和移出收货区库存 |
| | | Map<Long, List<TaskItem>> orderMap = taskItems.stream().collect(Collectors.groupingBy(TaskItem::getSource)); |
| | | orderMap.keySet().forEach(key -> { |
| | | // 如果source不为空,说明有关联的组托明细,需要处理 |
| | | if (key != null && key > 0) { |
| | | WaitPakinItem pakinItem = waitPakinItemService.getById(key); |
| | | if (!Objects.isNull(pakinItem)) { |
| | | List<TaskItem> items = orderMap.get(key); |
| | | //保存入出库明细 |
| | | saveStockItems(items, task, pakinItem.getId(), pakinItem.getAsnCode(), pakinItem.getWkType(), pakinItem.getType(), loginUserId); |
| | | //移出收货区库存, 修改组托状态 |
| | | removeReceiptStock(pakinItem, loginUserId); |
| | | } |
| | | } |
| | | }); |
| | | |
| | | // 处理组托状态(如果有组托关联) |
| | | Set<Long> pkinItemIds = taskItems.stream() |
| | | .map(TaskItem::getSource) |
| | | .filter(source -> source != null && source > 0) |
| | | .collect(Collectors.toSet()); |
| | | |
| | | if (!pkinItemIds.isEmpty()) { |
| | | List<WaitPakinItem> pakinItems = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().in(WaitPakinItem::getId, pkinItemIds)); |
| | | if (!pakinItems.isEmpty()) { |
| | | Set<Long> pakinIds = pakinItems.stream().map(WaitPakinItem::getPakinId).collect(Collectors.toSet()); |
| | | if (!waitPakinService.update(new LambdaUpdateWrapper<WaitPakin>() |
| | | .set(WaitPakin::getIoStatus, PakinIOStatus.PAKIN_IO_STATUS_TASK_DONE.val) |
| | | .set(WaitPakin::getUpdateBy, loginUserId) |
| | | .in(WaitPakin::getId, pakinIds))) { |
| | | throw new CoolException("组拖状态修改失败!!"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /**修改库位状态为F.在库*/ |