From 980c1d880cfe2453785344559ff2c3832cef6c54 Mon Sep 17 00:00:00 2001 From: javami888 <53815784+javami888@users.noreply.github.com> Date: Fri, 24 Apr 2026 13:20:45 +0800 Subject: [PATCH] add core code --- .../StandardInspectSiteDeviceDriver.java | 35 +++++- .../StandardOrdinarySiteDeviceDriver.java | 33 +++++ .../main/java/org/nl/acs/task/TaskConfig.java | 3 + .../service/impl/InstructionServiceImpl.java | 24 ++-- .../task/service/impl/TaskServiceImpl.java | 37 +++--- .../service/impl/KitToAcsServiceImpl.java | 89 +++++-------- .../wms/controller/WmsToAcsController.java | 22 +++- .../wms/service/AcsToWmsService.java | 19 ++- .../wms/service/WmsToAcsService.java | 6 + .../service/enums/WmsFeedbackStatusEnum.java | 39 ++++++ .../wms/service/impl/AcsToWmsServiceImpl.java | 117 ++++++++++++++++++ .../wms/service/impl/WmsToAcsServiceImpl.java | 44 +++++++ .../service/impl/AcsToWmsServiceImplTest.java | 95 ++++++++++++++ .../service/impl/WmsToAcsServiceImplTest.java | 81 ++++++++++++ 14 files changed, 546 insertions(+), 98 deletions(-) create mode 100644 acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/enums/WmsFeedbackStatusEnum.java create mode 100644 acs2/nladmin-system/nlsso-server/src/test/java/org/nl/extInterface/wms/service/impl/AcsToWmsServiceImplTest.java create mode 100644 acs2/nladmin-system/nlsso-server/src/test/java/org/nl/extInterface/wms/service/impl/WmsToAcsServiceImplTest.java diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/device/deviceDriver/service/defination/opcDefination/standardInspectSite/StandardInspectSiteDeviceDriver.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/device/deviceDriver/service/defination/opcDefination/standardInspectSite/StandardInspectSiteDeviceDriver.java index b387af0..2c2d2e7 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/device/deviceDriver/service/defination/opcDefination/standardInspectSite/StandardInspectSiteDeviceDriver.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/device/deviceDriver/service/defination/opcDefination/standardInspectSite/StandardInspectSiteDeviceDriver.java @@ -21,6 +21,8 @@ import org.nl.config.SpringContextHolder; import org.nl.config.language.LangProcess; import org.nl.config.lucene.service.LuceneExecuteLogService; import org.nl.extInterface.agvKit.service.AcsToKitService; +import org.nl.extInterface.wms.service.AcsToWmsService; +import org.nl.extInterface.wms.service.enums.WmsFeedbackStatusEnum; import java.util.Date; import java.util.HashMap; @@ -41,6 +43,7 @@ public class StandardInspectSiteDeviceDriver extends AbstractOpcDeviceDriver { private final TaskService taskService = SpringContextHolder.getBean(TaskService.class); private final AcsToKitService acsToKitService = SpringContextHolder.getBean(AcsToKitService.class); private final DeviceAppService deviceAppService = SpringContextHolder.getBean(DeviceAppService.class); + private final AcsToWmsService acsToWmsService = SpringContextHolder.getBean(AcsToWmsService.class); private volatile int agvphase = 0; /** @@ -157,6 +160,7 @@ public class StandardInspectSiteDeviceDriver extends AbstractOpcDeviceDriver { Thread.sleep(2000); this.devicecode = this.getDevice().getDevice_code(); if (this.reqTakeRequireSuccess && ObjectUtil.isNotEmpty(this.reqTakeInstCode)) { + // 驱动按周期执行,当前直接 return 就会停留在等待态,下一轮继续请求 WMS 许可。 Instruction instruction = instructionService.findByCodeFromCache(this.reqTakeInstCode); //取货申请 log.info("点位上报状态,{},{}",instruction.getTask_code(),agvphase); @@ -179,7 +183,11 @@ public class StandardInspectSiteDeviceDriver extends AbstractOpcDeviceDriver { } else { resetInstTask(agvphase); } - } else { + } else + { + if (!requestPermission(task, instruction, WmsFeedbackStatusEnum.APPLY_TAKE.getValue(), WmsFeedbackStatusEnum.TAKING.getValue())) { + return; + } HttpResponse result1 = acsToKitService.genAgvSchedulingTask(instruction, 10); if (ObjectUtils.isEmpty(result1) || result1.getStatus() != 200) { return; @@ -191,7 +199,7 @@ public class StandardInspectSiteDeviceDriver extends AbstractOpcDeviceDriver { if (agvphase == 2) { TaskService taskService = SpringContextHolder.getBean("taskServiceImpl"); TaskDto task = taskService.findByCode(instruction.getTask_code()); - + acsToWmsService.feedbackTask(task, resolveCard(task, instruction), WmsFeedbackStatusEnum.TAKE_FINISH.getValue()); if ((StrUtil.startWith(task.getTask_code(), "-"))) { log.info("定点任务下发agv允许取货信号"); StorageCellDto dto = StorageCellServiceImpl.Storage_Cache_Map.get(instruction.getStart_point_code()); @@ -222,6 +230,9 @@ public class StandardInspectSiteDeviceDriver extends AbstractOpcDeviceDriver { if (agvphase == 3) { TaskService taskService = SpringContextHolder.getBean("taskServiceImpl"); TaskDto task = taskService.findByCode(instruction.getTask_code()); + if (!requestPermission(task, instruction, WmsFeedbackStatusEnum.APPLY_PUT.getValue(), WmsFeedbackStatusEnum.PUTTING.getValue())) { + return; + } if ((StrUtil.startWith(task.getTask_code(), "-"))) { log.info("定点任务下发agv允许取货信号"); StorageCellDto dto = StorageCellServiceImpl.Storage_Cache_Map.get(instruction.getNext_point_code()); @@ -249,6 +260,7 @@ public class StandardInspectSiteDeviceDriver extends AbstractOpcDeviceDriver { if (agvphase == 4) { TaskService taskService = SpringContextHolder.getBean("taskServiceImpl"); TaskDto task = taskService.findByCode(instruction.getTask_code()); + acsToWmsService.feedbackTask(task, resolveCard(task, instruction), WmsFeedbackStatusEnum.PUT_FINISH.getValue()); if ((StrUtil.startWith(task.getTask_code(), "-"))) { log.info("定点任务下发agv允许取货信号"); StorageCellDto dto = StorageCellServiceImpl.Storage_Cache_Map.get(instruction.getNext_point_code()); @@ -387,7 +399,7 @@ public class StandardInspectSiteDeviceDriver extends AbstractOpcDeviceDriver { return; } // 设置新任务 -// this.agvPhase = Integer.valueOf(innerParamss.get("agvphase")); + this.agvphase = Integer.valueOf(innerParamss.get("agvphase")); this.reqTakeInstCode = taskId; this.reqTakeRequireSuccess = true; } @@ -406,4 +418,21 @@ public class StandardInspectSiteDeviceDriver extends AbstractOpcDeviceDriver { this.agvphase = 0; } } + + private boolean requestPermission(TaskDto task, Instruction instruction, String permissionStatus, String progressStatus) { + boolean allowed = acsToWmsService.feedbackTask(task, resolveCard(task, instruction), permissionStatus); + if (allowed && task != null) { + // WMS 放行后,先把外部状态推进到执行中,再继续给 AGV 下发动作。 + acsToWmsService.feedbackTask(task, resolveCard(task, instruction), progressStatus); + } + return allowed; + } + + private String resolveCard(TaskDto task, Instruction instruction) { + // 优先取任务上已绑定的车号,没有时再回退到当前指令上的车号。 + if (task != null && StrUtil.isNotBlank(task.getCarno())) { + return task.getCarno(); + } + return instruction == null ? "" : StrUtil.blankToDefault(instruction.getCarno(), ""); + } } diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/device/deviceDriver/service/defination/ordinaryDefination/standardOrdinarySite/StandardOrdinarySiteDeviceDriver.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/device/deviceDriver/service/defination/ordinaryDefination/standardOrdinarySite/StandardOrdinarySiteDeviceDriver.java index 5954109..6d3b61d 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/device/deviceDriver/service/defination/ordinaryDefination/standardOrdinarySite/StandardOrdinarySiteDeviceDriver.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/device/deviceDriver/service/defination/ordinaryDefination/standardOrdinarySite/StandardOrdinarySiteDeviceDriver.java @@ -18,6 +18,8 @@ import org.nl.acs.task.task.service.TaskService; import org.nl.acs.task.task.service.dto.TaskDto; import org.nl.config.SpringContextHolder; import org.nl.extInterface.agvKit.service.AcsToKitService; +import org.nl.extInterface.wms.service.AcsToWmsService; +import org.nl.extInterface.wms.service.enums.WmsFeedbackStatusEnum; import java.util.Map; @@ -32,6 +34,7 @@ public class StandardOrdinarySiteDeviceDriver extends AbstractStandardDeviceDriv private final InstructionService instructionService = SpringContextHolder.getBean(InstructionService.class); private final DeviceAppService deviceAppService = SpringContextHolder.getBean(DeviceAppService.class); private final AcsToKitService acsToKitService = SpringContextHolder.getBean(AcsToKitService.class); + private final AcsToWmsService acsToWmsService = SpringContextHolder.getBean(AcsToWmsService.class); private int flag; @@ -73,12 +76,18 @@ public class StandardOrdinarySiteDeviceDriver extends AbstractStandardDeviceDriv try { Thread.sleep(2000); if (this.reqTakeRequireSuccess && ObjectUtil.isNotEmpty(this.reqTakeInstCode)) { + // 驱动按周期执行,当前直接 return 就会停留在等待态,下一轮继续请求 WMS 许可。 Instruction instruction = instructionService.findByCodeFromCache(this.reqTakeInstCode); //取货申请F log.info("点位上报状态,{},{}", instruction.getTask_code(), agvPhase); if (ObjectUtil.isNotEmpty(instruction) && StrUtil.equals(instruction.getStart_point_code(), this.deviceCode)) { if (agvPhase == 1) { + TaskService taskService = SpringContextHolder.getBean("taskServiceImpl"); + TaskDto task = taskService.findByCode(instruction.getTask_code()); + if (!requestPermission(task, instruction, WmsFeedbackStatusEnum.APPLY_TAKE.getValue(), WmsFeedbackStatusEnum.TAKING.getValue())) { + return; + } // device = deviceAppService.findDeviceByCode(this.deviceCode); StorageCellDto dto = StorageCellServiceImpl.Storage_Cache_Map.get(instruction.getStart_point_code()); if (dto == null) { @@ -97,6 +106,7 @@ public class StandardOrdinarySiteDeviceDriver extends AbstractStandardDeviceDriv if (agvPhase == 2) { TaskService taskService = SpringContextHolder.getBean("taskServiceImpl"); TaskDto task = taskService.findByCode(instruction.getTask_code()); + acsToWmsService.feedbackTask(task, resolveCard(task, instruction), WmsFeedbackStatusEnum.TAKE_FINISH.getValue()); StorageCellDto dto = StorageCellServiceImpl.Storage_Cache_Map.get(instruction.getStart_point_code()); if (dto == null) { log.error(instruction.getStart_point_code() + "Storage_Cache_Map数据不存在"); @@ -125,6 +135,11 @@ public class StandardOrdinarySiteDeviceDriver extends AbstractStandardDeviceDriv //放货申请 else if (ObjectUtil.isNotEmpty(instruction) && StrUtil.equals(instruction.getNext_point_code(), this.deviceCode)) { if (agvPhase == 3) { + TaskService taskService = SpringContextHolder.getBean("taskServiceImpl"); + TaskDto task = taskService.findByCode(instruction.getTask_code()); + if (!requestPermission(task, instruction, WmsFeedbackStatusEnum.APPLY_PUT.getValue(), WmsFeedbackStatusEnum.PUTTING.getValue())) { + return; + } StorageCellDto dto = StorageCellServiceImpl.Storage_Cache_Map.get(instruction.getNext_point_code()); if (dto == null) { log.error(instruction.getStart_point_code() + "Storage_Cache_Map数据不存在"); @@ -142,6 +157,7 @@ public class StandardOrdinarySiteDeviceDriver extends AbstractStandardDeviceDriv if (agvPhase == 4) { TaskService taskService = SpringContextHolder.getBean("taskServiceImpl"); TaskDto task = taskService.findByCode(instruction.getTask_code()); + acsToWmsService.feedbackTask(task, resolveCard(task, instruction), WmsFeedbackStatusEnum.PUT_FINISH.getValue()); StorageCellDto dto = StorageCellServiceImpl.Storage_Cache_Map.get(instruction.getNext_point_code()); if (dto == null) { log.error(instruction.getStart_point_code() + "Storage_Cache_Map数据不存在"); @@ -226,5 +242,22 @@ public class StandardOrdinarySiteDeviceDriver extends AbstractStandardDeviceDriv this.agvPhase = 0; } } + + private boolean requestPermission(TaskDto task, Instruction instruction, String permissionStatus, String progressStatus) { + boolean allowed = acsToWmsService.feedbackTask(task, resolveCard(task, instruction), permissionStatus); + if (allowed && task != null) { + // WMS 放行后,先把外部状态推进到执行中,再继续给 AGV 下发动作。 + acsToWmsService.feedbackTask(task, resolveCard(task, instruction), progressStatus); + } + return allowed; + } + + private String resolveCard(TaskDto task, Instruction instruction) { + // 优先取任务上已绑定的车号,没有时再回退到当前指令上的车号。 + if (task != null && StrUtil.isNotBlank(task.getCarno())) { + return task.getCarno(); + } + return instruction == null ? "" : StrUtil.blankToDefault(instruction.getCarno(), ""); + } } diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/task/TaskConfig.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/task/TaskConfig.java index d73dcb2..a05bae4 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/task/TaskConfig.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/task/TaskConfig.java @@ -65,6 +65,9 @@ public class TaskConfig { * WMS系统接口地址 */ public static String WMSURL = "wmsurl"; + public static String WMS_HOUSE_CODE = "wmsHouseCode"; + public static String WMS_SYSTEM_CODE = "wmsSystemCode"; + public static String WMS_FEEDBACK_RETRY_MS = "wmsFeedbackRetryMs"; /** * WCS系统接口地址 */ diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/task/instruction/service/impl/InstructionServiceImpl.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/task/instruction/service/impl/InstructionServiceImpl.java index 4fe4c5c..1dd2931 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/task/instruction/service/impl/InstructionServiceImpl.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/acs/task/instruction/service/impl/InstructionServiceImpl.java @@ -7,6 +7,7 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpResponse; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -56,6 +57,7 @@ import org.nl.config.language.LangProcess; import org.nl.config.lucene.enums.LogLevelEnum; import org.nl.config.lucene.service.LuceneExecuteLogService; import org.nl.config.lucene.service.dto.LuceneLogDto; +import org.nl.extInterface.agvKit.service.AcsToKitService; import org.nl.system.service.param.ISysParamService; import org.nl.common.utils.CodeUtil; import org.nl.config.SpringContextHolder; @@ -67,6 +69,7 @@ import org.springframework.data.domain.Pageable; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.net.InetSocketAddress; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.regex.Pattern; @@ -94,6 +97,8 @@ public class InstructionServiceImpl extends CommonServiceImpl impleme this.addTaskToCache(dto); //反馈上位系统任务状态 - this.feedWmsTaskStatus(entity); + this.feedWmsTaskStatus(dto); } @@ -1763,29 +1764,19 @@ public class TaskServiceImpl extends CommonServiceImpl impleme * * @param taskDto */ + /** + * 这里只处理任务终态回传。 + * 取货、放货等中间阶段由站点驱动结合 AGV 回调直接回传 WMS。 + */ private void feedWmsTaskStatus(TaskDto taskDto) { - // 判断是否为WMS下发的任务,如果是反馈任务状态给WMS - TaskDto entity = this.findById(taskDto.getTask_id()); - String hasWms = paramService.findByCode(TaskConfig.HASWMS).getValue(); - if (!StrUtil.startWith(taskDto.getTask_code(), CommonFinalParam.HYPHEN_) && StrUtil.equals(hasWms, CommonFinalParam.ONE)) { -// FeedBackTaskStatusRequest request = new FeedBackTaskStatusRequest(); -// request.setTask_id(taskDto.getExt_task_id()); -// request.setTask_code(taskDto.getTask_code()); -// request.setTask_status(taskDto.getTask_status()); -// request.setRequest_medthod_code(RequestMethodEnum.feedback_task_status.getCode()); -// request.setRequest_medthod_name(RequestMethodEnum.feedback_task_status.getName()); - JSONObject feed_jo = new JSONObject(); - feed_jo.put("task_id", entity.getExt_task_id()); - feed_jo.put("task_code", entity.getTask_code()); - feed_jo.put("task_status", entity.getTask_status()); - if (ObjectUtil.isNotEmpty(entity.getWeight())) { - feed_jo.put("weight", entity.getWeight()); - } - if (ObjectUtil.isNotEmpty(entity.getCarno())) { - feed_jo.put("car_no", entity.getCarno()); - } - JSONArray ja = new JSONArray(); - ja.add(feed_jo); + if (!acstowmsService.isWmsTask(taskDto)) { + return; + } + if (StrUtil.equals(taskDto.getTask_status(), TaskStatusEnum.CANCEL.getIndex())) { + acstowmsService.deprecateTask(taskDto, taskDto.getRemark()); + } else if (StrUtil.equals(taskDto.getTask_status(), TaskStatusEnum.ERROR.getIndex()) + || StrUtil.equals(taskDto.getTask_status(), TaskStatusEnum.FORCED_COMPLETION.getIndex())) { + acstowmsService.feedbackTask(taskDto, taskDto.getCarno(), WmsFeedbackStatusEnum.ERROR_FINISH.getValue()); } } } diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/agvKit/service/impl/KitToAcsServiceImpl.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/agvKit/service/impl/KitToAcsServiceImpl.java index 10335d4..9e53a27 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/agvKit/service/impl/KitToAcsServiceImpl.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/agvKit/service/impl/KitToAcsServiceImpl.java @@ -6,14 +6,14 @@ import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSONObject; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.nl.acs.device.device.service.DeviceAppService; import org.nl.acs.device.device.service.entity.Device; import org.nl.acs.device.deviceDriver.service.driver.DeviceDriver; +import org.nl.acs.device.storageMgt.service.StorageCellService; import org.nl.acs.device.storageMgt.service.entity.StorageCell; import org.nl.acs.task.instruction.domain.Instruction; import org.nl.acs.task.instruction.enums.InstructionStatusEnum; import org.nl.acs.task.instruction.service.InstructionService; -import org.nl.acs.device.device.service.DeviceAppService; -import org.nl.acs.device.storageMgt.service.StorageCellService; import org.nl.config.MapOf; import org.nl.extInterface.agvKit.service.KitToAcsService; import org.nl.extInterface.agvKit.service.enums.MsgTypeEnum; @@ -35,19 +35,19 @@ public class KitToAcsServiceImpl implements KitToAcsService { @Override public JSONObject agvCallback(JSONObject requestParam) throws Exception{ + // AGV 回调只负责推进 ACS 内部状态,后续是否继续执行由站点驱动结合 WMS 许可决定。 JSONObject resp = new JSONObject(); Integer type = requestParam.getInteger("type"); JSONObject params = requestParam.getJSONObject("params"); - //任务状态上报 if (MsgTypeEnum.TASK_STATE_RPT.getValue().equals(type)) { String instTaskId = params.getString("taskId"); String taskPhase = params.getString("taskPhase"); String taskState = params.getString("taskState"); - String taskPoint = params.getString("taskPoint");//请求进入/离开需要上报站点号 + String taskPoint = params.getString("taskPoint"); if (StrUtil.isEmpty(taskPhase)){ resp.put("code", "400"); resp.put("message", "taskPhase参数异常"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; } Instruction instruction = instructionService.findByCodeFromCache(instTaskId); @@ -56,20 +56,20 @@ public class KitToAcsServiceImpl implements KitToAcsService { if (ObjectUtil.isEmpty(instruction)){ resp.put("code", "400"); resp.put("message", "请求失败,任务信息不存在,指令号:" + instTaskId); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; } instructionService.reload(); } - //taskPhase 任务取消 if (TaskStateEnum.CANCELED.getValue().equals(taskState)){ instructionService.cancel(instruction.getInstruction_id()); resp.put("code", "200"); resp.put("message", "取消任务成功"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; } + Device device = null; TaskPhaseEnum taskPhaseEnum = TaskPhaseEnum.fromPhase(taskPhase); switch (taskPhaseEnum){ @@ -79,14 +79,14 @@ public class KitToAcsServiceImpl implements KitToAcsService { if (ObjectUtil.isEmpty(storageCellDto)) { resp.put("code", "400"); resp.put("message", "请求失败,点位信息不存在,点位站点号:" + taskPoint); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; } device = deviceAppService.findDeviceByCode(storageCellDto.getStorage_code()); if (ObjectUtil.isEmpty(device)) { resp.put("code", "400"); - resp.put("message", "请求失败,请求位置编号不存在!"); - log.info("---响应kit请求---"+resp.toString()); + resp.put("message", "请求失败,请求位置编码不存在"); + log.info("---kit响应请求---{}", resp); return resp; } DeviceDriver deviceDriver = device.getDeviceDriver(); @@ -96,17 +96,18 @@ public class KitToAcsServiceImpl implements KitToAcsService { case PICKUP_COMPLETE: case RELEASE_REQUEST_OR_RESPONSE: case RELEASE_COMPLETE: - if (TaskPhaseEnum.PICKUP_REQUEST_OR_RESPONSE.getValue().equals(taskPhase) || TaskPhaseEnum.PICKUP_COMPLETE.getValue().equals(taskPhase)){ + if (TaskPhaseEnum.PICKUP_REQUEST_OR_RESPONSE.getValue().equals(taskPhase) + || TaskPhaseEnum.PICKUP_COMPLETE.getValue().equals(taskPhase)){ device = deviceAppService.findDeviceByCode(instruction.getStart_point_code()); } - //taskPhase 请求放货上报,放货完成上报 - if (TaskPhaseEnum.RELEASE_REQUEST_OR_RESPONSE.getValue().equals(taskPhase)||TaskPhaseEnum.RELEASE_COMPLETE.getValue().equals(taskPhase)){ + if (TaskPhaseEnum.RELEASE_REQUEST_OR_RESPONSE.getValue().equals(taskPhase) + || TaskPhaseEnum.RELEASE_COMPLETE.getValue().equals(taskPhase)){ device = deviceAppService.findDeviceByCode(instruction.getNext_point_code()); } if (device == null){ resp.put("code", "400"); resp.put("message", "点位驱动不存在"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; } device.getDeviceDriver().setDeviceInnerParam(MapOf.of("taskId",instTaskId,"agvphase",taskPhase)); @@ -114,102 +115,80 @@ public class KitToAcsServiceImpl implements KitToAcsService { instruction.setExecute_status(taskPhase); instructionService.update(instruction); } - //taskPhase 任务完成 if (TaskStateEnum.COMPLETED.getValue().equals(taskState)){ resp.put("code", "200"); resp.put("message", "完成任务成功"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); } break; default: resp.put("code", "400"); resp.put("message", "taskPhase值不存在"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; } resp.put("code", "200"); resp.put("message", taskPhaseEnum.getDescription()+"处理完毕"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; - } - //任务分配车辆上报 - else if (MsgTypeEnum.AGV_ID_RPT.getValue().equals(type)){ + } else if (MsgTypeEnum.AGV_ID_RPT.getValue().equals(type)){ String taskId = params.getString("taskId"); String agvId = params.getString("agvId"); Instruction instruction = instructionService.findByCodeFromCache(taskId); if (ObjectUtil.isEmpty(instruction)) { resp.put("code", "400"); resp.put("message", "请求失败,任务信息不存在,指令号:" + taskId); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; } - //更新车号 instruction.setCarno(agvId); instruction.setInstruction_status(InstructionStatusEnum.BUSY.getCode()); instruction.setUpdate_time(DateUtil.now()); instructionService.update(instruction); resp.put("code", "200"); resp.put("message", "更新车号成功"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; - } - else if (MsgTypeEnum.TASK_RUN_RPT.getValue().equals(type)){ - System.out.println("------"); + } else if (MsgTypeEnum.TASK_RUN_RPT.getValue().equals(type)){ resp.put("code", "200"); resp.put("message", "更新车号成功"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; - } - //车辆任务生成上报 - else if (MsgTypeEnum.TASK_INDEX_RPT.getValue().equals(type)){ + } else if (MsgTypeEnum.TASK_INDEX_RPT.getValue().equals(type)){ String taskId = params.getString("taskId"); Instruction instruction = instructionService.findByCodeFromCache(taskId); if (ObjectUtil.isEmpty(instruction)) { resp.put("code", "400"); resp.put("message", "请求失败,任务信息不存在,指令号:" + taskId); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; } - //修改指令状态执行中 instruction.setInstruction_status(InstructionStatusEnum.BUSY.getCode()); instruction.setUpdate_time(DateUtil.now()); instructionService.update(instruction); resp.put("code", "200"); resp.put("message", "更新指令执行中成功"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; - } - else if (MsgTypeEnum.AGV_POWER_RPT.getValue().equals(type)){ - int agvId = params.getIntValue("agvId"); - int stateValue = params.getIntValue("stateValue"); + } else if (MsgTypeEnum.AGV_POWER_RPT.getValue().equals(type)){ resp.put("code", "200"); resp.put("message", "更新指令执行中成功"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; - } - else if (MsgTypeEnum.AGV_STATE_RPT.getValue().equals(type)){ - int agvId = params.getIntValue("agvId"); - int stateValue = params.getIntValue("stateValue"); - int xLocation = params.getIntValue("xLocation"); - int yLocation = params.getIntValue("yLocation"); - int angle = params.getIntValue("angle"); - int speed = params.getIntValue("speed"); + } else if (MsgTypeEnum.AGV_STATE_RPT.getValue().equals(type)){ resp.put("code", "200"); resp.put("message", "更新指令执行中成功"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; - } - else if (MsgTypeEnum.AGV_ERROR_RPT.getValue().equals(type)){ - int agvId = params.getIntValue("agvId"); - int errorCode = params.getIntValue("errState"); + } else if (MsgTypeEnum.AGV_ERROR_RPT.getValue().equals(type)){ resp.put("code", "200"); resp.put("message", "更新指令执行中成功"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; } resp.put("code", "400"); resp.put("message", type+"type类型未定义"); - log.info("---响应kit请求---"+resp.toString()); + log.info("---kit响应请求---{}", resp); return resp; } } diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/controller/WmsToAcsController.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/controller/WmsToAcsController.java index 3531ce4..53bad58 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/controller/WmsToAcsController.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/controller/WmsToAcsController.java @@ -1,8 +1,15 @@ - package org.nl.extInterface.wms.controller; +import cn.dev33.satoken.annotation.SaIgnore; +import io.swagger.annotations.Api; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.nl.extInterface.wms.service.WmsToAcsService; +import org.nl.extInterface.wms.service.dto.CreateTaskRequest; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -12,7 +19,18 @@ import org.springframework.web.bind.annotation.RestController; **/ @RestController @RequiredArgsConstructor -@RequestMapping("/api/wms") +@Api(tags = "wms->ACS") +@RequestMapping({"/api/wms", "/restful/api/v3"}) @Slf4j public class WmsToAcsController { + private final WmsToAcsService wmsToAcsService; + + @SaIgnore + @PostMapping("/createTask") + public ResponseEntity createTask(@RequestBody CreateTaskRequest request) { + // 控制层只做协议接入,字段映射和业务处理统一下沉到 service。 + return new ResponseEntity<>(wmsToAcsService.createTask(request), HttpStatus.OK); + } + + } diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/AcsToWmsService.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/AcsToWmsService.java index ff5dac7..9f6f920 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/AcsToWmsService.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/AcsToWmsService.java @@ -1,5 +1,22 @@ package org.nl.extInterface.wms.service; -public interface AcsToWmsService { +import com.alibaba.fastjson.JSONObject; +import org.nl.acs.task.task.service.dto.TaskDto; +public interface AcsToWmsService { + /** + * 复用 WMS 的 feedbackTask 接口,同时承担阶段反馈和取放货许可判断。 + */ + boolean feedbackTask(TaskDto taskDto, String card, String feedbackStatus); + + boolean deprecateTask(TaskDto taskDto, String reason); + + JSONObject taskRedirection(String taskCode, String currLocation); + + boolean deviceStatusUpdate(String deviceCode, Integer status, String statusDescription); + + /** + * 判断任务是否需要进入 WMS 回传链路,避免本地任务误回传。 + */ + boolean isWmsTask(TaskDto taskDto); } diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/WmsToAcsService.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/WmsToAcsService.java index fe9a1c7..28dbdad 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/WmsToAcsService.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/WmsToAcsService.java @@ -1,7 +1,13 @@ package org.nl.extInterface.wms.service; +import com.alibaba.fastjson.JSONObject; +import org.nl.extInterface.wms.service.dto.CreateTaskRequest; public interface WmsToAcsService { + /** + * 接收 WMS 的 createTask 报文,并映射到现有 ACS 任务流程。 + */ + JSONObject createTask(CreateTaskRequest request); } diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/enums/WmsFeedbackStatusEnum.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/enums/WmsFeedbackStatusEnum.java new file mode 100644 index 0000000..5bbe7f8 --- /dev/null +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/enums/WmsFeedbackStatusEnum.java @@ -0,0 +1,39 @@ +package org.nl.extInterface.wms.service.enums; + + +/** + * WMS feedbackTask 接口使用的任务阶段状态枚举。 + */ +public enum WmsFeedbackStatusEnum { + /** 取货执行中。 */ + TAKING("taking"), + /** 请求 WMS 允许取货。 */ + APPLY_TAKE("applyTake"), + /** 取货完成。 */ + TAKE_FINISH("takeFinish"), + /** 放货执行中。 */ + PUTTING("putting"), + /** 请求 WMS 允许放货。 */ + APPLY_PUT("applyPut"), + /** 放货完成。 */ + PUT_FINISH("putFinish"), + /** 无目标点放货完成。 */ + NO_TARGET_PUT_FINISH("NoTargetPutFinish"), + /** 异常完成。 */ + ERROR_FINISH("errorFinish"), + /** 运行异常。 */ + EXCEPTION("exception"), + /** 任务作废。 */ + DEPRECATE("deprecate"); + + /** 对外回传给 WMS 的状态值。 */ + private final String value; + + WmsFeedbackStatusEnum(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/impl/AcsToWmsServiceImpl.java b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/impl/AcsToWmsServiceImpl.java index 4cf1749..5d7b384 100644 --- a/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/impl/AcsToWmsServiceImpl.java +++ b/acs2/nladmin-system/nlsso-server/src/main/java/org/nl/extInterface/wms/service/impl/AcsToWmsServiceImpl.java @@ -1,13 +1,130 @@ package org.nl.extInterface.wms.service.impl; +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpRequest; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.nl.acs.task.TaskConfig; +import org.nl.acs.task.task.service.dto.TaskDto; +import org.nl.common.db.CommonFinalParam; import org.nl.extInterface.wms.service.AcsToWmsService; +import org.nl.system.service.param.ISysParamService; +import org.nl.system.service.param.dao.Param; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor @Slf4j public class AcsToWmsServiceImpl implements AcsToWmsService { + private static final String FEEDBACK_TASK_PATH = "/restful/api/v3/system_car/feedbackTask"; + private static final String DEPRECATE_TASK_PATH = "/restful/api/v3/system_car/deprecateTask"; + private static final String TASK_REDIRECTION_PATH = "/restful/api/v3/system_car/taskRedirection"; + private static final String DEVICE_STATUS_PATH = "/restful/api/v3/system_car/deviceStatusUpdate"; + private final ISysParamService paramService; + + @Override + public boolean feedbackTask(TaskDto taskDto, String card, String feedbackStatus) { + if (!isWmsTask(taskDto)) { + return true; + } + // 当前项目复用 feedbackTask 作为统一出口,既回传阶段,也做取放货许可判断。 + JSONObject body = baseBody(); + body.put("taskCode", getExternalTaskCode(taskDto)); + body.put("card", StrUtil.blankToDefault(card, "")); + body.put("taskType", StrUtil.blankToDefault(taskDto.getTask_type(), "")); + body.put("feedbackStatus", feedbackStatus); + JSONObject response = postJson(buildUrl(FEEDBACK_TASK_PATH), body); + return isSuccess(response); + } + + @Override + public boolean deprecateTask(TaskDto taskDto, String reason) { + if (!isWmsTask(taskDto)) { + return true; + } + JSONObject body = baseBody(); + body.put("taskCode", getExternalTaskCode(taskDto)); + body.put("reason", StrUtil.blankToDefault(reason, "")); + JSONObject response = postJson(buildUrl(DEPRECATE_TASK_PATH), body); + return isSuccess(response); + } + + @Override + public JSONObject taskRedirection(String taskCode, String currLocation) { + JSONObject body = baseBody(); + body.put("taskCode", taskCode); + body.put("currLocation", currLocation); + return postJson(buildUrl(TASK_REDIRECTION_PATH), body); + } + + @Override + public boolean deviceStatusUpdate(String deviceCode, Integer status, String statusDescription) { + JSONObject body = baseBody(); + body.put("deviceCode", deviceCode); + body.put("status", status); + body.put("statusDescription", statusDescription); + JSONObject response = postJson(buildUrl(DEVICE_STATUS_PATH), body); + return isSuccess(response); + } + + @Override + public boolean isWmsTask(TaskDto taskDto) { + // 当前通过任务号规则和总开关共同判断,避免历史 ACS 本地任务进入 WMS 流程。 + return taskDto != null + && StrUtil.isNotBlank(taskDto.getTask_code()) + && !StrUtil.startWith(taskDto.getTask_code(), CommonFinalParam.HYPHEN_) + && StrUtil.equals("1", getParam(TaskConfig.HASWMS, "0")); + } + + protected JSONObject postJson(String url, JSONObject body) { + try { + String result = HttpRequest.post(url) + .header("Content-Type", "application/json") + .body(body.toJSONString()) + .timeout(8000) + .execute() + .body(); + return JSON.parseObject(result); + } catch (Exception ex) { + // 统一包装成失败响应,调用方可以按 WMS 拒绝的同一套逻辑处理。 + log.error("postJson failed, url={}, body={}", url, body, ex); + JSONObject error = new JSONObject(); + error.put("responseCode", 1); + error.put("responseMessage", ex.getMessage()); + return error; + } + } + + private JSONObject baseBody() { + JSONObject body = new JSONObject(); + body.put("houseCode", getParam(TaskConfig.WMS_HOUSE_CODE, "")); + body.put("systemCode", getParam(TaskConfig.WMS_SYSTEM_CODE, "")); + // 协议预留了扩展参数对象,即使当前流程没有额外字段也保持结构一致。 + body.put("parameters", new JSONObject()); + return body; + } + + private String buildUrl(String path) { + String baseUrl = getParam(TaskConfig.WMSURL, ""); + if (StrUtil.endWith(baseUrl, "/")) { + baseUrl = StrUtil.removeSuffix(baseUrl, "/"); + } + return baseUrl + path; + } + + private String getExternalTaskCode(TaskDto taskDto) { + return StrUtil.isNotBlank(taskDto.getExt_task_id()) ? taskDto.getExt_task_id() : taskDto.getTask_code(); + } + + private boolean isSuccess(JSONObject response) { + return response != null && Integer.valueOf(0).equals(response.getInteger("responseCode")); + } + + private String getParam(String code, String defaultValue) { + Param param = paramService.findByCode(code); + return param == null || StrUtil.isBlank(param.getValue()) ? defaultValue : param.getValue(); + } } 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 f32a4df..dacab8d 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,13 +1,57 @@ package org.nl.extInterface.wms.service.impl; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.nl.acs.task.task.service.TaskService; +import org.nl.acs.task.task.service.dto.TaskDto; import org.nl.extInterface.wms.service.WmsToAcsService; +import org.nl.extInterface.wms.service.dto.CreateTaskRequest; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor @Slf4j public class WmsToAcsServiceImpl implements WmsToAcsService { + private final TaskService taskService; + @Override + public JSONObject createTask(CreateTaskRequest request) { + JSONObject response = new JSONObject(); + try { + // 将 WMS 协议报文转换成现有 ACS 任务 DTO,复用已有建单和调度链路。 + TaskDto dto = new TaskDto(); + dto.setTask_code(request.getTaskCode()); + dto.setExt_task_id(request.getTaskCode()); + dto.setTask_type(StrUtil.blankToDefault(request.getTaskType(), "1")); + dto.setVehicle_code(request.getContainerCode()); + dto.setVehicle_type(request.getContainerType()); + dto.setStart_point_code(request.getLocationFrom()); + dto.setStart_device_code(request.getLocationFrom()); + dto.setNext_point_code(request.getLocationTo()); + dto.setNext_device_code(request.getLocationTo()); + dto.setPriority(request.getPriority() == null ? null : String.valueOf(request.getPriority())); + dto.setQuantity("1"); + dto.setRoute_plan_code("normal"); + dto.setCompound_task("0"); + dto.setCreate_type("WMS"); + dto.setFinish_type("WMS"); + // 当前任务模型没有完整承载 WMS 扩展字段的结构化列,先放入 remark 保留。 + JSONObject extInfo = new JSONObject(); + extInfo.put("houseCode", request.getHouseCode()); + extInfo.put("systemCode", request.getSystemCode()); + extInfo.put("taskCreateDateTime", request.getTaskCreateDateTime()); + extInfo.put("parameters", request.getParameters()); + dto.setRemark(extInfo.toJSONString()); + taskService.create(dto); + response.put("responseCode", 0); + response.put("responseMessage", "success"); + } catch (Exception ex) { + log.error("createTask failed, taskCode={}", request.getTaskCode(), ex); + response.put("responseCode", 1); + response.put("responseMessage", ex.getMessage()); + } + return response; + } } diff --git a/acs2/nladmin-system/nlsso-server/src/test/java/org/nl/extInterface/wms/service/impl/AcsToWmsServiceImplTest.java b/acs2/nladmin-system/nlsso-server/src/test/java/org/nl/extInterface/wms/service/impl/AcsToWmsServiceImplTest.java new file mode 100644 index 0000000..da3591a --- /dev/null +++ b/acs2/nladmin-system/nlsso-server/src/test/java/org/nl/extInterface/wms/service/impl/AcsToWmsServiceImplTest.java @@ -0,0 +1,95 @@ +package org.nl.extInterface.wms.service.impl; + +import com.alibaba.fastjson.JSONObject; +import org.junit.Test; +import org.nl.acs.task.TaskConfig; +import org.nl.acs.task.task.service.dto.TaskDto; +import org.nl.system.service.param.ISysParamService; +import org.nl.system.service.param.dao.Param; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class AcsToWmsServiceImplTest { + + @Test + public void feedbackTaskTreatsZeroResponseCodeAsAllowed() { + ISysParamService paramService = mock(ISysParamService.class); + when(paramService.findByCode(TaskConfig.WMSURL)).thenReturn(param(TaskConfig.WMSURL, "http://wms")); + when(paramService.findByCode(TaskConfig.HASWMS)).thenReturn(param(TaskConfig.HASWMS, "1")); + when(paramService.findByCode(TaskConfig.WMS_HOUSE_CODE)).thenReturn(param(TaskConfig.WMS_HOUSE_CODE, "H1")); + when(paramService.findByCode(TaskConfig.WMS_SYSTEM_CODE)).thenReturn(param(TaskConfig.WMS_SYSTEM_CODE, "WMS")); + + TestableAcsToWmsServiceImpl service = new TestableAcsToWmsServiceImpl(paramService); + service.nextResponse = jsonResponse(0, "ok"); + + TaskDto task = new TaskDto(); + task.setTask_code("TASK-1"); + task.setTask_type("MOVE"); + + boolean allowed = service.feedbackTask(task, "AGV-01", "applyTake"); + + assertTrue(allowed); + assertEquals("http://wms/restful/api/v3/system_car/feedbackTask", service.lastUrl); + assertEquals("TASK-1", service.lastBody.getString("taskCode")); + assertEquals("AGV-01", service.lastBody.getString("card")); + assertEquals("MOVE", service.lastBody.getString("taskType")); + assertEquals("applyTake", service.lastBody.getString("feedbackStatus")); + assertEquals("H1", service.lastBody.getString("houseCode")); + assertEquals("WMS", service.lastBody.getString("systemCode")); + } + + @Test + public void feedbackTaskTreatsNonZeroResponseCodeAsRejected() { + ISysParamService paramService = mock(ISysParamService.class); + when(paramService.findByCode(TaskConfig.WMSURL)).thenReturn(param(TaskConfig.WMSURL, "http://wms")); + when(paramService.findByCode(TaskConfig.HASWMS)).thenReturn(param(TaskConfig.HASWMS, "1")); + when(paramService.findByCode(TaskConfig.WMS_HOUSE_CODE)).thenReturn(param(TaskConfig.WMS_HOUSE_CODE, "H1")); + when(paramService.findByCode(TaskConfig.WMS_SYSTEM_CODE)).thenReturn(param(TaskConfig.WMS_SYSTEM_CODE, "WMS")); + + TestableAcsToWmsServiceImpl service = new TestableAcsToWmsServiceImpl(paramService); + service.nextResponse = jsonResponse(2, "denied"); + + TaskDto task = new TaskDto(); + task.setTask_code("TASK-2"); + task.setTask_type("MOVE"); + + boolean allowed = service.feedbackTask(task, "AGV-02", "applyPut"); + + assertFalse(allowed); + } + + private static Param param(String code, String value) { + Param param = new Param(); + param.setCode(code); + param.setValue(value); + return param; + } + + private static JSONObject jsonResponse(int code, String message) { + JSONObject json = new JSONObject(); + json.put("responseCode", code); + json.put("responseMessage", message); + return json; + } + + private static class TestableAcsToWmsServiceImpl extends AcsToWmsServiceImpl { + private JSONObject nextResponse; + private String lastUrl; + private JSONObject lastBody; + + private TestableAcsToWmsServiceImpl(ISysParamService paramService) { + super(paramService); + } + + @Override + protected JSONObject postJson(String url, JSONObject body) { + this.lastUrl = url; + this.lastBody = body; + return nextResponse; + } + } +} diff --git a/acs2/nladmin-system/nlsso-server/src/test/java/org/nl/extInterface/wms/service/impl/WmsToAcsServiceImplTest.java b/acs2/nladmin-system/nlsso-server/src/test/java/org/nl/extInterface/wms/service/impl/WmsToAcsServiceImplTest.java new file mode 100644 index 0000000..d3a5bd8 --- /dev/null +++ b/acs2/nladmin-system/nlsso-server/src/test/java/org/nl/extInterface/wms/service/impl/WmsToAcsServiceImplTest.java @@ -0,0 +1,81 @@ +package org.nl.extInterface.wms.service.impl; + +import com.alibaba.fastjson.JSONObject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.nl.acs.task.task.service.TaskService; +import org.nl.acs.task.task.service.dto.TaskDto; +import org.nl.extInterface.wms.service.dto.CreateTaskRequest; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.verify; + +@RunWith(MockitoJUnitRunner.class) +public class WmsToAcsServiceImplTest { + + @Mock + private TaskService taskService; + + @InjectMocks + private WmsToAcsServiceImpl service; + + @Test + public void createTaskMapsRequestToTaskDto() throws Exception { + CreateTaskRequest request = new CreateTaskRequest(); + request.setTaskCode("TASK-001"); + request.setTaskType("MOVE"); + request.setContainerCode("PALLET-1"); + request.setContainerType("PALLET"); + request.setLocationFrom("A01"); + request.setLocationTo("B01"); + request.setPriority(5); + request.setHouseCode("H1"); + request.setSystemCode("WMS"); + JSONObject parameters = new JSONObject(); + parameters.put("batch", "B1"); + request.setParameters(parameters); + + JSONObject response = service.createTask(request); + + ArgumentCaptor captor = ArgumentCaptor.forClass(TaskDto.class); + verify(taskService).create(captor.capture()); + TaskDto dto = captor.getValue(); + assertEquals("TASK-001", dto.getTask_code()); + assertEquals("TASK-001", dto.getExt_task_id()); + assertEquals("MOVE", dto.getTask_type()); + assertEquals("PALLET-1", dto.getVehicle_code()); + assertEquals("PALLET", dto.getVehicle_type()); + assertEquals("A01", dto.getStart_point_code()); + assertEquals("A01", dto.getStart_device_code()); + assertEquals("B01", dto.getNext_point_code()); + assertEquals("B01", dto.getNext_device_code()); + assertEquals("5", dto.getPriority()); + assertEquals("1", dto.getQuantity()); + assertTrue(dto.getRemark().contains("\"houseCode\":\"H1\"")); + assertTrue(dto.getRemark().contains("\"systemCode\":\"WMS\"")); + assertEquals(Integer.valueOf(0), response.getInteger("responseCode")); + } + + @Test + public void createTaskReturnsErrorWhenTaskCreationFails() throws Exception { + CreateTaskRequest request = new CreateTaskRequest(); + request.setTaskCode("TASK-ERR"); + request.setContainerCode("PALLET-ERR"); + request.setLocationFrom("A01"); + request.setLocationTo("B01"); + + doThrow(new IllegalStateException("duplicate task")).when(taskService).create(any(TaskDto.class)); + + JSONObject response = service.createTask(request); + + assertEquals(Integer.valueOf(1), response.getInteger("responseCode")); + assertEquals("duplicate task", response.getString("responseMessage")); + } +}