| | |
| | | ) |
| | | } |
| | | |
| | | /** 拣料/盘点出库:仅 RCS 执行中(<198)可取消;199、198 不可取消 */ |
| | | const canCancelPickOrCheckOut = (record) => { |
| | | if (record?.taskType != 103 && record?.taskType != 107) return false; |
| | | const s = record.taskStatus; |
| | | return s < 198; |
| | | }; |
| | | |
| | | /** 普通入出库、空板、移库等:创建态可取消;199 不可取消 */ |
| | | const canCancelLegacy = (record) => { |
| | | const t = record?.taskType; |
| | | const s = record?.taskStatus; |
| | | if (t != 1 && t != 101 && t != 10 && t != 11) return false; |
| | | return s == 1 || s == 101; |
| | | }; |
| | | |
| | | /** |
| | | * 取消按钮 |
| | | * @returns |
| | |
| | | notify(msg); |
| | | } |
| | | } |
| | | const showCancel = canCancelPickOrCheckOut(record) || canCancelLegacy(record); |
| | | return ( |
| | | (record.taskStatus == 1 || record.taskStatus == 101 || record.taskStatus == 199) && (record.taskType == 1 || record.taskType == 101 || record.taskType == 10 || record.taskType == 107 || record.taskType == 103 || record.taskType == 11) ? |
| | | showCancel ? |
| | | <ConfirmButton |
| | | onConfirm={clickCancel} |
| | | startIcon={<CancelIcon />} |
| | |
| | | |
| | | //取消RCS任务 |
| | | public static String cancelTask = "/api/open/task/cancel"; |
| | | |
| | | /** 任务状态反向通知 RCS(POST body: taskNo, status) */ |
| | | public static String TASK_STATUS_NOTICE = "/api/open/bus/notice"; |
| | | } |
| New file |
| | |
| | | package com.vincent.rsf.server.api.service; |
| | | |
| | | /** |
| | | * 管理后台对工作档点「完成」时反向通知 RCS:POST /api/open/bus/notice。 |
| | | * 「取消」仅通过 RCS 取消接口(/api/open/task/cancel);PDA、RCS 回调、定时任务等不调此处。 |
| | | */ |
| | | public interface RcsBusTaskNoticeService { |
| | | |
| | | /** |
| | | * @param taskNo 工作档任务编码 |
| | | * @param status {@link com.vincent.rsf.server.manager.enums.TaskStsType} 的 id(完成 98/198/200);取消走 RCS 取消接口,不用本接口 |
| | | */ |
| | | void notifyTaskStatus(String taskNo, Integer status); |
| | | } |
| | |
| | | } |
| | | if (first.getTaskType().equals(TaskType.TASK_TYPE_OUT.type)) { |
| | | for (Task task : tasks) { |
| | | taskService.completeFullOutStock(task.getId(), loginUserId); |
| | | taskService.completeFullOutStock(task.getId(), loginUserId, false); |
| | | } |
| | | return R.ok("确认成功,全版出库已完成"); |
| | | } |
| New file |
| | |
| | | package com.vincent.rsf.server.api.service.impl; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import com.fasterxml.jackson.databind.cfg.CoercionAction; |
| | | import com.fasterxml.jackson.databind.cfg.CoercionInputShape; |
| | | import com.vincent.rsf.server.api.config.RemotesInfoProperties; |
| | | import com.vincent.rsf.server.api.entity.CommonResponse; |
| | | import com.vincent.rsf.server.api.entity.constant.RcsConstant; |
| | | import com.vincent.rsf.server.api.service.RcsBusTaskNoticeService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.http.HttpEntity; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.HttpMethod; |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** 管理后台工作档完成/取消时通知 RCS */ |
| | | @Slf4j |
| | | @Service |
| | | public class RcsBusTaskNoticeServiceImpl implements RcsBusTaskNoticeService { |
| | | |
| | | @Autowired(required = false) |
| | | private RemotesInfoProperties.RcsApi rcsApi; |
| | | @Autowired(required = false) |
| | | private RestTemplate restTemplate; |
| | | |
| | | @Override |
| | | public void notifyTaskStatus(String taskNo, Integer status) { |
| | | if (StringUtils.isBlank(taskNo) || status == null) { |
| | | return; |
| | | } |
| | | if (rcsApi == null || StringUtils.isBlank(rcsApi.getHost()) || StringUtils.isBlank(rcsApi.getPort())) { |
| | | log.debug("跳过 RCS 任务状态通知:未配置 platform.rcs"); |
| | | return; |
| | | } |
| | | if (restTemplate == null) { |
| | | log.warn("跳过 RCS 任务状态通知:RestTemplate 未注入"); |
| | | return; |
| | | } |
| | | String url = rcsApi.getHost() + ":" + rcsApi.getPort() + RcsConstant.TASK_STATUS_NOTICE; |
| | | Map<String, String> body = new HashMap<>(2); |
| | | body.put("taskNo", taskNo); |
| | | body.put("status", String.valueOf(status)); |
| | | try { |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | headers.add("Content-Type", "application/json"); |
| | | headers.add("api-version", "v2.0"); |
| | | HttpEntity<Map<String, String>> entity = new HttpEntity<>(body, headers); |
| | | log.info("RCS 任务状态通知 POST {} body={}", url, JSONObject.toJSONString(body)); |
| | | ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.POST, entity, String.class); |
| | | if (exchange.getBody() == null) { |
| | | log.warn("RCS 任务状态通知响应体为空 taskNo={}", taskNo); |
| | | return; |
| | | } |
| | | ObjectMapper om = new ObjectMapper(); |
| | | om.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty); |
| | | CommonResponse res = om.readValue(exchange.getBody(), CommonResponse.class); |
| | | if (res.getCode() != null && res.getCode() == 200) { |
| | | log.info("RCS 任务状态通知成功 taskNo={} status={}", taskNo, status); |
| | | } else { |
| | | log.warn("RCS 任务状态通知非成功 taskNo={} status={} code={} msg={}", |
| | | taskNo, status, res.getCode(), res.getMsg()); |
| | | } |
| | | } catch (Exception e) { |
| | | log.warn("RCS 任务状态通知异常 taskNo={} status={}:{}", taskNo, status, e.getMessage()); |
| | | } |
| | | } |
| | | } |
| | |
| | | private WarehouseAreasItemService warehouseAreasItemService; |
| | | @Autowired |
| | | private ConfigService configService; |
| | | @Autowired |
| | | private TaskItemService taskItemService; |
| | | @Autowired |
| | | private TaskService taskService; |
| | | |
| | | /** |
| | | * 云仓改单/取消前:任务明细已关联该单据且主任务未逻辑删除则不允许 |
| | | */ |
| | | private void assertWkOrderNoLinkedTask(Long wkOrderId) { |
| | | if (wkOrderId == null) { |
| | | return; |
| | | } |
| | | List<TaskItem> links = taskItemService.list(new LambdaQueryWrapper<TaskItem>() |
| | | .select(TaskItem::getTaskId) |
| | | .and(w -> w.eq(TaskItem::getOrderId, wkOrderId) |
| | | .or(o -> o.eq(TaskItem::getSourceId, wkOrderId) |
| | | .eq(TaskItem::getOrderType, OrderType.ORDER_OUT.type)))); |
| | | if (links.isEmpty()) { |
| | | return; |
| | | } |
| | | Set<Long> taskIds = links.stream().map(TaskItem::getTaskId).filter(Objects::nonNull).collect(Collectors.toSet()); |
| | | if (taskIds.isEmpty()) { |
| | | return; |
| | | } |
| | | if (taskService.count(new LambdaQueryWrapper<Task>().in(Task::getId, taskIds)) > 0) { |
| | | throw new CoolException("该单据已生成任务,不可修改、取消或删除!!"); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * @author Ryan |
| | |
| | | WkOrder order = asnOrderService.getOne(new LambdaQueryWrapper<WkOrder>() |
| | | .eq(WkOrder::getPoCode, syncOrder.getOrderInternalCode())); |
| | | if (!Objects.isNull(order)) { |
| | | assertWkOrderNoLinkedTask(order.getId()); |
| | | // 仅未执行状态可被 order/add 修改(入库未执行、出库任务初始) |
| | | List<Short> editableStatus = Arrays.asList(AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val |
| | | ,AsnExceStatus.ASN_EXCE_STATUS_UN_EXCE.val |
| | |
| | | if (Objects.isNull(wkOrder)) { |
| | | throw new CoolException("请确认单据:" + order.getOrderNo() + "是否已经执行或是否同步!!"); |
| | | } |
| | | assertWkOrderNoLinkedTask(wkOrder.getId()); |
| | | order.getOrderItems().forEach(orderItem -> { |
| | | WkOrderItem wkOrderItem = asnOrderItemService.getOne(new LambdaUpdateWrapper<WkOrderItem>() |
| | | .eq(WkOrderItem::getMatnrCode, orderItem.getMatnr()) |
| | |
| | | throw new CoolException("单据不存在,无法取消!!请提供单据内码(orderInternalCode)或单号(orderNo)。"); |
| | | } |
| | | final WkOrder finalWkOrder = wkOrder; |
| | | assertWkOrderNoLinkedTask(finalWkOrder.getId()); |
| | | // 已组托不可取消 |
| | | long pakinCount = waitPakinItemService.count(new LambdaQueryWrapper<WaitPakinItem>() |
| | | .eq(WaitPakinItem::getAsnId, finalWkOrder.getId())); |
| | |
| | | if (Cools.isEmpty(id)) { |
| | | throw new CoolException("参数不能为空!!"); |
| | | } |
| | | return R.ok("全版出库完结成功").add(taskService.completeFullOutStock(id, getLoginUserId())); |
| | | return R.ok("全版出库完结成功").add(taskService.completeFullOutStock(id, getLoginUserId(), true)); |
| | | } |
| | | |
| | | /** |
| | |
| | | package com.vincent.rsf.server.manager.enums;
|
| | |
|
| | | public enum TaskStsType {
|
| | | //任务状态
|
| | | GENERATE_IN("1", "创建入库任务"),
|
| | | WCS_EXECUTE_IN("2", "RCS任务已下发"),
|
| | | WCS_CONTAINER_RECEIVE("3", "RCS容器到达"),
|
| | | WCS_CONVEYOR_START("4", "RCS容器流动任务已下发"),
|
| | | WCS_TOTE_LOAD("5", "RCS取箱完成"),
|
| | | WCS_TOTE_UNLOAD("6", "RCS放箱完成"),
|
| | | WCS_PUTAWAY_SUCESS("7", "RCS任务完成"),
|
| | |
|
| | | // WCS_PUTAWAY_FAILED(11L, "任务失败"),
|
| | | //
|
| | | // WCS_PUTAWAY_CANCEL(12L, "任务取消"),
|
| | | //
|
| | | // WCS_PUTAWAY_SUSPEND(13L, "入库任务挂起"),
|
| | |
|
| | | COMPLETE_IN("98", "入库完成"),
|
| | |
|
| | | REPORT_IN("99", "上报完成"),
|
| | |
|
| | | UPDATED_IN("100", "库存更新完成"),
|
| | |
|
| | | GENERATE_OUT("101", "创建出库任务"),
|
| | |
|
| | | WCS_EXECUTE_OUT("102", "RCS出库任务已下发"),
|
| | |
|
| | | WCS_EXECUTE_OUT_TOTE_LOAD("103", "RCS取箱完成"),
|
| | |
|
| | | WCS_EXECUTE_OUT_TOTE_UNLOAD("104", "RCS放箱完成"),
|
| | |
|
| | | WCS_EXECUTE_OUT_TASK_DONE("105", "RCS任务完成"),
|
| | |
|
| | | WCS_EXECUTE_OUT_ARRIVED("106", "RCS容器已到达"),
|
| | |
|
| | | WCS_EXECUTE_OUT_CONVEYOR("107", "RCS容器流动任务已下发"),
|
| | |
|
| | | AWAIT("196","等待确认"),
|
| | |
|
| | | GENERATE_WAVE_SEED("197", "等待容器到达"),
|
| | |
|
| | | COMPLETE_OUT("198", "出库完成"),
|
| | |
|
| | | WAVE_SEED("199", "播种中/盘点中/待确认"),
|
| | |
|
| | | UPDATED_OUT("200", "库存更新完成"),
|
| | | ;
|
| | |
|
| | | public Integer id;
|
| | | public String desc;
|
| | |
|
| | | TaskStsType(String id, String desc) {
|
| | | this.id = Integer.parseInt(id);
|
| | | this.desc = desc;
|
| | | }
|
| | |
|
| | | }
|
| | | package com.vincent.rsf.server.manager.enums; |
| | | |
| | | public enum TaskStsType { |
| | | //任务状态 |
| | | GENERATE_IN("1", "创建入库任务"), |
| | | WCS_EXECUTE_IN("2", "RCS任务已下发"), |
| | | WCS_CONTAINER_RECEIVE("3", "RCS容器到达"), |
| | | WCS_CONVEYOR_START("4", "RCS容器流动任务已下发"), |
| | | WCS_TOTE_LOAD("5", "RCS取箱完成"), |
| | | WCS_TOTE_UNLOAD("6", "RCS放箱完成"), |
| | | WCS_PUTAWAY_SUCESS("7", "RCS任务完成"), |
| | | |
| | | // WCS_PUTAWAY_FAILED(11L, "任务失败"), |
| | | // |
| | | // WCS_PUTAWAY_CANCEL(12L, "任务取消"), |
| | | // |
| | | // WCS_PUTAWAY_SUSPEND(13L, "入库任务挂起"), |
| | | |
| | | COMPLETE_IN("98", "入库完成"), |
| | | |
| | | REPORT_IN("99", "上报完成"), |
| | | |
| | | UPDATED_IN("100", "库存更新完成"), |
| | | |
| | | GENERATE_OUT("101", "创建出库任务"), |
| | | |
| | | WCS_EXECUTE_OUT("102", "RCS出库任务已下发"), |
| | | |
| | | WCS_EXECUTE_OUT_TOTE_LOAD("103", "RCS取箱完成"), |
| | | |
| | | WCS_EXECUTE_OUT_TOTE_UNLOAD("104", "RCS放箱完成"), |
| | | |
| | | WCS_EXECUTE_OUT_TASK_DONE("105", "RCS任务完成"), |
| | | |
| | | WCS_EXECUTE_OUT_ARRIVED("106", "RCS容器已到达"), |
| | | |
| | | WCS_EXECUTE_OUT_CONVEYOR("107", "RCS容器流动任务已下发"), |
| | | |
| | | AWAIT("196","等待确认"), |
| | | |
| | | GENERATE_WAVE_SEED("197", "等待容器到达"), |
| | | |
| | | COMPLETE_OUT("198", "出库完成"), |
| | | |
| | | WAVE_SEED("199", "播种中/盘点中/待确认"), |
| | | |
| | | UPDATED_OUT("200", "库存更新完成"), |
| | | ; |
| | | |
| | | public Integer id; |
| | | public String desc; |
| | | |
| | | TaskStsType(String id, String desc) { |
| | | this.id = Integer.parseInt(id); |
| | | this.desc = desc; |
| | | } |
| | | |
| | | } |
| | |
| | | continue; |
| | | } |
| | | try { |
| | | taskService.completeFullOutStock(task.getId(), SYSTEM_USER_ID); |
| | | taskService.completeFullOutStock(task.getId(), SYSTEM_USER_ID, false); |
| | | log.info("[自动拣货完成] 任务: {}, 料箱: {}, 物料: {} 已自动确认出库并更新库存", task.getTaskCode(), task.getBarcode(), matnrCode); |
| | | } catch (Exception e) { |
| | | log.warn("[自动拣货完成] 任务: {} 处理失败: {}", task.getTaskCode(), e.getMessage()); |
| | |
| | | |
| | | Task operateComplete(Long id, Long loginUserId); |
| | | |
| | | Task completeFullOutStock(Long id, Long loginUserId); |
| | | /** |
| | | * @param notifyRcsFromAdmin true:管理后台「全版出库完结」接口调用时通知 RCS;false:定时/PDA 等同源不通知 |
| | | */ |
| | | Task completeFullOutStock(Long id, Long loginUserId, boolean notifyRcsFromAdmin); |
| | | |
| | | void moveToDeep(Long loginUserId, String curLoc) throws Exception; |
| | | |
| | |
| | | import com.vincent.rsf.server.api.config.RemotesInfoProperties; |
| | | import com.vincent.rsf.server.api.controller.erp.params.InOutResultReportParam; |
| | | import com.vincent.rsf.server.api.controller.erp.params.TaskInParam; |
| | | import com.vincent.rsf.server.api.service.RcsBusTaskNoticeService; |
| | | import com.vincent.rsf.server.api.entity.CommonResponse; |
| | | import com.vincent.rsf.server.api.entity.constant.RcsConstant; |
| | | import com.vincent.rsf.server.api.entity.dto.InTaskMsgDto; |
| | |
| | | private CloudWmsNotifyLogService cloudWmsNotifyLogService; |
| | | @Autowired |
| | | private WarehouseService warehouseService; |
| | | @Autowired |
| | | private RcsBusTaskNoticeService rcsBusTaskNoticeService; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | } |
| | | |
| | | /** |
| | | * 手动完成任务 |
| | | * 手动完成任务:入库类置 98、出库类置 198,库位/单据扣减与上报由对应定时任务执行 |
| | | * |
| | | * @param id |
| | | * @param loginUserId |
| | |
| | | } |
| | | |
| | | modiftyTaskSort(task, loginUserId); |
| | | |
| | | // 如果任务状态已经是AWAIT (196),再次点击完结时,直接完成 |
| | | if (task.getTaskStatus().equals(TaskStsType.AWAIT.id)) { |
| | | // AWAIT状态的任务再次完结,直接设置为出库完成 |
| | | |
| | | // 入库:->98,出库:-> 198,由 complateOutStock 定时任务 更新库存 |
| | | if (task.getTaskType() < 100) { |
| | | task.setTaskStatus(TaskStsType.COMPLETE_IN.id); |
| | | if (StringUtils.isNotBlank(task.getOrgSite())) { |
| | | BasStation station = basStationService.getOne(new LambdaQueryWrapper<BasStation>() |
| | | .eq(BasStation::getStationName, task.getOrgSite())); |
| | | if (Objects.nonNull(station) && station.getType().equals(StationTypeEnum.STATION_TYPE_NORMAL.type)) { |
| | | station.setUseStatus(LocStsType.LOC_STS_TYPE_O.type); |
| | | if (!basStationService.updateById(station)) { |
| | | throw new CoolException("入库站点状态修改失败!!"); |
| | | } |
| | | } |
| | | } |
| | | } else { |
| | | task.setTaskStatus(TaskStsType.COMPLETE_OUT.id); |
| | | |
| | | // 更新出库站点状态(与RCS通知完结保持一致) |
| | | if (task.getTaskType() >= TaskType.TASK_TYPE_OUT.type && StringUtils.isNotBlank(task.getTargSite())) { |
| | | BasStation station = basStationService.getOne(new LambdaQueryWrapper<BasStation>() |
| | | .eq(BasStation::getStationName, task.getTargSite())); |
| | |
| | | } |
| | | } |
| | | } |
| | | } else { |
| | | // 其他情况按原有逻辑处理 |
| | | // 入库任务(taskType < 100):设置为入库完成 |
| | | // 出库任务(taskType >= 100):设置为等待确认 |
| | | Integer newStatus = task.getTaskType() < 100 ? TaskStsType.COMPLETE_IN.id : TaskStsType.AWAIT.id; |
| | | task.setTaskStatus(newStatus); |
| | | |
| | | // 如果是入库任务完成,更新入库站点状态(与RCS通知完结保持一致) |
| | | if (newStatus.equals(TaskStsType.COMPLETE_IN.id) && StringUtils.isNotBlank(task.getOrgSite())) { |
| | | BasStation station = basStationService.getOne(new LambdaQueryWrapper<BasStation>() |
| | | .eq(BasStation::getStationName, task.getOrgSite())); |
| | | if (Objects.nonNull(station) && station.getType().equals(StationTypeEnum.STATION_TYPE_NORMAL.type)) { |
| | | station.setUseStatus(LocStsType.LOC_STS_TYPE_O.type); |
| | | if (!basStationService.updateById(station)) { |
| | | throw new CoolException("入库站点状态修改失败!!"); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | // 原:196 时再点一次才置 198;出库首次点击曾置 196(AWAIT) |
| | | // if (task.getTaskStatus().equals(TaskStsType.AWAIT.id)) { task.setTaskStatus(TaskStsType.COMPLETE_OUT.id); ... } |
| | | // else { Integer newStatus = task.getTaskType() < 100 ? COMPLETE_IN.id : AWAIT.id; ... } |
| | | |
| | | if (!this.updateById(task)) { |
| | | throw new CoolException("完成任务失败"); |
| | | } |
| | | // 管理后台「完成任务」通知 RCS |
| | | if (StringUtils.isNotBlank(task.getTaskCode())) { |
| | | rcsBusTaskNoticeService.notifyTaskStatus(task.getTaskCode(), task.getTaskStatus()); |
| | | } |
| | | return task; |
| | | } |
| | |
| | | * |
| | | * @param id 任务ID |
| | | * @param loginUserId 登录用户ID |
| | | * @param notifyRcsFromAdmin 管理后台全版出库完结接口为 true 时通知 RCS;定时/PDA 等为 false |
| | | * @return 任务对象 |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Task completeFullOutStock(Long id, Long loginUserId) { |
| | | public Task completeFullOutStock(Long id, Long loginUserId, boolean notifyRcsFromAdmin) { |
| | | // 查询任务 |
| | | Task task = taskService.getOne(new LambdaQueryWrapper<Task>() |
| | | .eq(Task::getId, id)); |
| | |
| | | |
| | | if (!this.updateById(task)) { |
| | | throw new CoolException("任务状态更新失败!!"); |
| | | } |
| | | if (notifyRcsFromAdmin && StringUtils.isNotBlank(task.getTaskCode())) { |
| | | rcsBusTaskNoticeService.notifyTaskStatus(task.getTaskCode(), TaskStsType.UPDATED_OUT.id); |
| | | } |
| | | |
| | | return task; |
| | |
| | | } |
| | | } |
| | | |
| | | // 如果有任务已下发到RCS,先调用RCS取消接口 |
| | | // 已下发 RCS 的工作档:必须先调 RCS 取消接口成功,否则不允许取消工作档 |
| | | boolean rcsCancelSuccess = false; |
| | | if (!rcsTaskCodes.isEmpty()) { |
| | | // 检查 RCS API 配置是否有效 |
| | | if (rcsApi == null || StringUtils.isBlank(rcsApi.getHost()) || StringUtils.isBlank(rcsApi.getPort())) { |
| | | log.error("========== RCS任务取消失败 =========="); |
| | | log.error("RCS API 配置无效!host: {}, port: {}", |
| | | rcsApi != null ? rcsApi.getHost() : "null", |
| | | rcsApi != null ? rcsApi.getPort() : "null"); |
| | | // 即使配置无效,也继续执行任务删除操作 |
| | | } else { |
| | | try { |
| | | log.info("========== 开始取消RCS任务 =========="); |
| | | log.info("需要取消的RCS任务编号:{}", rcsTaskCodes); |
| | | String rcsUrl = rcsApi.getHost() + ":" + rcsApi.getPort() + RcsConstant.cancelTask; |
| | | log.info("RCS取消任务请求地址:{}", rcsUrl); |
| | | |
| | | // 如果没有批次编号,使用第一个任务编号作为批次编号 |
| | | if (StringUtils.isBlank(batchNo) && !rcsTaskCodes.isEmpty()) { |
| | | throw new CoolException("任务已下发RCS,但未配置RCS地址,无法取消!!"); |
| | | } |
| | | if (restTemplate == null) { |
| | | throw new CoolException("任务已下发RCS,但无法调用RCS取消接口,无法取消!!"); |
| | | } |
| | | try { |
| | | log.info("========== 开始取消RCS任务 =========="); |
| | | log.info("需要取消的RCS任务编号:{}", rcsTaskCodes); |
| | | String rcsUrl = rcsApi.getHost() + ":" + rcsApi.getPort() + RcsConstant.cancelTask; |
| | | log.info("RCS取消任务请求地址:{}", rcsUrl); |
| | | |
| | | if (StringUtils.isBlank(batchNo)) { |
| | | batchNo = rcsTaskCodes.get(0); |
| | | } |
| | | |
| | | |
| | | Map<String, Object> cancelParams = new HashMap<>(); |
| | | cancelParams.put("tasks", rcsTaskCodes); |
| | | if (StringUtils.isNotBlank(batchNo)) { |
| | | cancelParams.put("batchNo", batchNo); |
| | | } |
| | | |
| | | |
| | | log.info("RCS取消任务请求参数:{}", JSONObject.toJSONString(cancelParams)); |
| | | |
| | | |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | headers.add("Content-Type", "application/json"); |
| | | headers.add("api-version", "v2.0"); |
| | | HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(cancelParams, headers); |
| | | |
| | | |
| | | long startTime = System.currentTimeMillis(); |
| | | ResponseEntity<String> exchange = restTemplate.exchange(rcsUrl, HttpMethod.POST, httpEntity, String.class); |
| | | long endTime = System.currentTimeMillis(); |
| | | |
| | | |
| | | log.info("RCS取消任务响应耗时:{}ms", (endTime - startTime)); |
| | | log.info("RCS取消任务响应状态码:{}", exchange.getStatusCode()); |
| | | log.info("RCS取消任务响应体:{}", exchange.getBody()); |
| | | |
| | | |
| | | if (Objects.isNull(exchange.getBody())) { |
| | | log.error("RCS取消任务失败:响应体为空"); |
| | | throw new CoolException("RCS取消任务失败:响应体为空"); |
| | | } |
| | | |
| | | |
| | | ObjectMapper objectMapper = new ObjectMapper(); |
| | | objectMapper.coercionConfigDefaults() |
| | | .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty); |
| | | CommonResponse result = objectMapper.readValue(exchange.getBody(), CommonResponse.class); |
| | | |
| | | |
| | | if (result.getCode() == 200) { |
| | | log.info("========== RCS任务取消成功 =========="); |
| | | log.info("成功取消的RCS任务编号:{}", rcsTaskCodes); |
| | |
| | | log.error("RCS取消任务失败:{}", result.getMsg()); |
| | | throw new CoolException("RCS取消任务失败:" + result.getMsg()); |
| | | } |
| | | } catch (JsonProcessingException e) { |
| | | log.error("RCS取消任务响应解析失败:{}", e.getMessage(), e); |
| | | throw new CoolException("RCS取消任务响应解析失败:" + e.getMessage()); |
| | | } catch (Exception e) { |
| | | log.error("RCS取消任务异常:{}", e.getMessage(), e); |
| | | throw new CoolException("RCS取消任务异常:" + e.getMessage()); |
| | | } |
| | | } catch (CoolException e) { |
| | | throw e; |
| | | } catch (JsonProcessingException e) { |
| | | log.error("RCS取消任务响应解析失败:{}", e.getMessage(), e); |
| | | throw new CoolException("RCS取消任务响应解析失败:" + e.getMessage()); |
| | | } catch (Exception e) { |
| | | log.error("RCS取消任务异常:{}", e.getMessage(), e); |
| | | throw new CoolException("RCS取消任务异常:" + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | // 查询符合取消条件的任务(状态为1、101、199) |
| | | List<Integer> allowedStatuses = Arrays.asList(TaskStsType.GENERATE_IN.id, TaskStsType.GENERATE_OUT.id, TaskStsType.WAVE_SEED.id); |
| | | // 可取消状态:原 1/101(不含 199);拣料/盘点出库 RCS 执行中(<198);拣料/盘点再入库(53/57)不支持取消 |
| | | List<Task> tasks = this.list(new LambdaQueryWrapper<Task>() |
| | | .in(Task::getTaskType, list) |
| | | .in(Task::getId, (Object[]) ids) |
| | | .in(Task::getTaskStatus, allowedStatuses)); |
| | | .and(w -> w |
| | | .in(Task::getTaskStatus, Arrays.asList( |
| | | TaskStsType.GENERATE_IN.id, |
| | | TaskStsType.GENERATE_OUT.id)) |
| | | .or(w2 -> w2 |
| | | .in(Task::getTaskType, TaskType.TASK_TYPE_PICK_AGAIN_OUT.type, TaskType.TASK_TYPE_CHECK_OUT.type) |
| | | .lt(Task::getTaskStatus, TaskStsType.COMPLETE_OUT.id)))); |
| | | |
| | | // 如果符合取消条件的任务为空,但RCS取消成功,允许继续(可能是任务状态已变更) |
| | | if (tasks.isEmpty() && !rcsCancelSuccess) { |