diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/manager/package-info.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/manager/package-info.java new file mode 100644 index 0000000..ff34d43 --- /dev/null +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/manager/package-info.java @@ -0,0 +1,6 @@ +/** + * 封装处理类包 + * @Author: liyongde + * @Date: 2026/7/30 13:22 + */ +package org.nl.extInterface.manager; \ No newline at end of file diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/data/req/TaskIssueReqVO.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/data/req/TaskIssueReqVO.java index 8b94281..5023cd2 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/data/req/TaskIssueReqVO.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/data/req/TaskIssueReqVO.java @@ -62,7 +62,7 @@ public class TaskIssueReqVO extends AcsBaseReqVO { */ private String remark; /** - * 扩展参数 + * 扩展参数,不在设置其他字段,所有业务所需的字段统一存放在这 */ private Map payload; /** diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/data/resp/TaskIssueResultRespVO.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/data/resp/TaskIssueResultRespVO.java index 83b94fb..9cee1f1 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/data/resp/TaskIssueResultRespVO.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/data/resp/TaskIssueResultRespVO.java @@ -23,7 +23,8 @@ public class TaskIssueResultRespVO { public static class FailedTask { /** - * 任务标识 + * 任务标识(LMS的任务id) + * 对应acs任务表中的ext_task_id */ private Long taskId; diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/impl/WmsToAcsServiceImpl.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/impl/WmsToAcsServiceImpl.java index 2bc87d0..ecbbd14 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/impl/WmsToAcsServiceImpl.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/impl/WmsToAcsServiceImpl.java @@ -1,7 +1,16 @@ package org.nl.extInterface.wms.service.impl; -import lombok.RequiredArgsConstructor; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import lombok.extern.slf4j.Slf4j; +import org.nl.acs.device.storageMgt.service.entity.StorageCell; +import org.nl.acs.device.storageMgt.service.mapper.StorageCellMapper; +import org.nl.acs.task.task.service.TaskService; +import org.nl.acs.task.task.service.dto.TaskDto; import org.nl.extInterface.wms.data.req.OperateCheckReqVO; import org.nl.extInterface.wms.data.req.TaskIssueReqVO; import org.nl.extInterface.wms.data.resp.OperateCheckRespVO; @@ -9,21 +18,218 @@ import org.nl.extInterface.wms.data.resp.TaskIssueResultRespVO; import org.nl.extInterface.wms.service.WmsToAcsService; import org.springframework.stereotype.Service; +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; @Service -@RequiredArgsConstructor @Slf4j public class WmsToAcsServiceImpl implements WmsToAcsService { + private static final String DEFAULT_TASK_TYPE = "1"; + private static final String DEFAULT_ROUTE_PLAN_CODE = "normal"; + + @Resource + private TaskService taskService; + + @Resource + private StorageCellMapper storageCellMapper; @Override public TaskIssueResultRespVO issueTask(List tasks) { - // todo + log.info("接受WMS下发的任务:{}", JSONObject.toJSONString(tasks)); TaskIssueResultRespVO response = new TaskIssueResultRespVO(); + List failedTasks = new ArrayList<>(); + + if (CollUtil.isEmpty(tasks)) { + response.setFailedTasks(failedTasks); + return response; + } + + for (TaskIssueReqVO task : tasks) { + TaskIssueResultRespVO.FailedTask failedTask = issueSingleTask(task); + if (failedTask != null) { + failedTasks.add(failedTask); + } + } + + response.setFailedTasks(failedTasks); return response; } + private TaskIssueResultRespVO.FailedTask issueSingleTask(TaskIssueReqVO task) { + try { + validateRequired(task); + ensureTaskNotExists(task); + + TaskLocation startLocation = resolveLocation(task.getStartDeviceCode()); + TaskLocation nextLocation = resolveLocation(task.getNextDeviceCode()); + TaskLocation startLocation2 = resolveOptionalLocation(task.getStartDeviceCode2()); + TaskLocation nextLocation2 = resolveOptionalLocation(task.getNextDeviceCode2()); + + TaskDto taskDto = buildTaskDto(task, startLocation, nextLocation, startLocation2, nextLocation2); + extendBeforeCreate(task, taskDto); + taskService.create(taskDto); + return null; + } catch (Exception e) { + log.warn("WMS任务下发失败, taskId={}, taskCode={}", getTaskId(task), getTaskCode(task), e); + return failedTask(getTaskId(task), e.getMessage()); + } + } + + private void validateRequired(TaskIssueReqVO task) { + if (task == null) { + throw new IllegalArgumentException("任务不能为空"); + } + if (StrUtil.isBlank(task.getTaskCode())) { + throw new IllegalArgumentException("任务编码不能为空"); + } + if (StrUtil.isBlank(task.getStartDeviceCode())) { + throw new IllegalArgumentException("起点不能为空"); + } + if (StrUtil.isBlank(task.getNextDeviceCode())) { + throw new IllegalArgumentException("终点不能为空"); + } + } + + private void ensureTaskNotExists(TaskIssueReqVO task) { + TaskDto cachedTask = taskService.findByCodeFromCache(task.getTaskCode()); + if (cachedTask != null) { + throw new IllegalArgumentException("存在相同的任务编码:" + task.getTaskCode()); + } + TaskDto dbTask = taskService.findByCode(task.getTaskCode()); + if (dbTask != null) { + throw new IllegalArgumentException("存在相同的任务编码:" + task.getTaskCode()); + } + if (StrUtil.isNotBlank(task.getVehicleCode())) { + TaskDto vehicleTask = taskService.findByContainer(task.getVehicleCode()); + if (vehicleTask != null) { + throw new IllegalArgumentException("载具" + task.getVehicleCode() + "已存在任务:" + vehicleTask.getTask_code()); + } + } + } + + private TaskLocation resolveLocation(String storageCode) { + TaskLocation location = resolveOptionalLocation(storageCode); + if (StrUtil.isBlank(location.getPointCode())) { + throw new IllegalArgumentException(storageCode + " 未找到对应点位"); + } + return location; + } + + private TaskLocation resolveOptionalLocation(String storageCode) { + if (StrUtil.isBlank(storageCode)) { + return TaskLocation.empty(); + } + StorageCell storageCell = new LambdaQueryChainWrapper<>(storageCellMapper) + .eq(StorageCell::getStorage_code, storageCode) + .one(); + if (storageCell == null) { + return TaskLocation.empty(); + } + String pointCode = StrUtil.isBlank(storageCell.getParent_storage_code()) + ? storageCode + : storageCell.getStorage_code(); + return new TaskLocation(pointCode, getDeviceCode(pointCode)); + } + + private TaskDto buildTaskDto(TaskIssueReqVO task, + TaskLocation startLocation, + TaskLocation nextLocation, + TaskLocation startLocation2, + TaskLocation nextLocation2) { + TaskDto taskDto = new TaskDto(); + taskDto.setTask_id(IdUtil.simpleUUID()); + taskDto.setExt_task_id(task.getTaskId() == null ? null : String.valueOf(task.getTaskId())); + taskDto.setTask_code(task.getTaskCode()); + taskDto.setStart_point_code(startLocation.getPointCode()); + taskDto.setStart_device_code(startLocation.getDeviceCode()); + taskDto.setNext_point_code(nextLocation.getPointCode()); + taskDto.setNext_device_code(nextLocation.getDeviceCode()); + taskDto.setStart_point_code2(startLocation2.getPointCode()); + taskDto.setStart_device_code2(startLocation2.getDeviceCode()); + taskDto.setNext_point_code2(nextLocation2.getPointCode()); + taskDto.setNext_device_code2(nextLocation2.getDeviceCode()); + taskDto.setPriority(task.getPriority()); + taskDto.setVehicle_code(task.getVehicleCode()); + taskDto.setVehicle_code2(task.getVehicleCode2()); + taskDto.setTask_type(StrUtil.blankToDefault(task.getTaskType(), DEFAULT_TASK_TYPE)); + taskDto.setRoute_plan_code(DEFAULT_ROUTE_PLAN_CODE); + taskDto.setRemark(task.getRemark()); + taskDto.setParamJson(new JSONObject(buildTaskParam(task))); + return taskDto; + } + + private Map buildTaskParam(TaskIssueReqVO task) { + Map param = new LinkedHashMap<>(); + if (ObjectUtil.isNotEmpty(task.getPayload())) { + param.putAll(task.getPayload()); + } + putIfNotBlank(param, "agvSystemType", task.getAgvSystemType()); + putIfNotBlank(param, "productArea", task.getProductArea()); + putIfNotBlank(param, "traceId", task.getTraceId()); + if (task.getTimestamp() != null) { + param.put("timestamp", task.getTimestamp()); + } + return param; + } + + private void extendBeforeCreate(TaskIssueReqVO task, TaskDto taskDto) { + // todo Extend project-specific validation or conversion by taskType/agvSystemType/payload. + } + + private void putIfNotBlank(Map param, String key, String value) { + if (StrUtil.isNotBlank(value)) { + param.put(key, value); + } + } + + private String getDeviceCode(String pointCode) { + if (StrUtil.isBlank(pointCode)) { + return pointCode; + } + return pointCode.contains("-") ? StrUtil.subBefore(pointCode, "-", false) : pointCode; + } + + private TaskIssueResultRespVO.FailedTask failedTask(Long taskId, String errorMessage) { + TaskIssueResultRespVO.FailedTask failedTask = new TaskIssueResultRespVO.FailedTask(); + failedTask.setTaskId(taskId); + failedTask.setErrorMessage(StrUtil.blankToDefault(errorMessage, "任务下发失败")); + return failedTask; + } + + private Long getTaskId(TaskIssueReqVO task) { + return task == null ? null : task.getTaskId(); + } + + private String getTaskCode(TaskIssueReqVO task) { + return task == null ? null : task.getTaskCode(); + } + + private static class TaskLocation { + private final String pointCode; + private final String deviceCode; + + private TaskLocation(String pointCode, String deviceCode) { + this.pointCode = pointCode; + this.deviceCode = deviceCode; + } + + private static TaskLocation empty() { + return new TaskLocation(null, null); + } + + private String getPointCode() { + return pointCode; + } + + private String getDeviceCode() { + return deviceCode; + } + } + @Override public OperateCheckRespVO checkEnableOperate(OperateCheckReqVO task) { // todo 检测任务能否取消或者完成,取消和完成判断逻辑一样,不需要管他,先判断指令是否存在,存在则显示不允许操作,