zy-asrs-wms/src/main/java/com/zy/asrs/wms/apis/wcs/controller/OutStockController.java
@@ -2,7 +2,9 @@ import com.zy.asrs.framework.common.R; import com.zy.asrs.framework.exception.CoolException; import com.zy.asrs.wms.apis.wcs.entity.request.ContainerArrivedParam; import com.zy.asrs.wms.apis.wcs.entity.request.RfidSingalRequest; import com.zy.asrs.wms.apis.wcs.entity.request.TasksStatusCallbackParam; import com.zy.asrs.wms.apis.wcs.services.WcsApiService; import com.zy.asrs.wms.system.controller.BaseController; @@ -10,6 +12,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.Map; import java.util.Objects; @Slf4j @RestController @@ -61,7 +66,10 @@ } /** * 容器流动通知 * 容器流动通知(当前物料播种完成) * //fixme 此接口将不再单独调用 * 1. 更新当前任务物料信息 * 2. * @param code 容器编码 * @return */ @@ -70,9 +78,54 @@ if (StringUtil.isNullOrEmpty(code)) { return R.error("容器编码不能为空!!!"); } return wcsApiService.containerConveryor(code); } /** * 发送命令给电子标签,可以控制电子标签亮灯颜色及灭灯等。 * * 1. 判断当前容器是否还有物料未拣,未拣完闪灯,拣完通知容器流动,并灭灯 * 2. 容器流动判断,如果料箱没有物料 code传200, 有物料传100 执行回库任务, IOTYP = 4 * * @param request * @return */ @PostMapping("/slap/light") public R slapLightLogic(@RequestBody Map<String, Object> request) { if (Objects.isNull(request)) { throw new CoolException("参数不能为空!!"); } if (Objects.isNull(request.get("taskNo"))) { throw new CoolException("任务号不能为空!!"); } if (Objects.isNull(request.get("orderNO"))){ throw new CoolException("当前任务订单号不能为空!!"); } wcsApiService.slapLightLogic(request); return R.ok(); } /** * 信号回传接口,回传电子标签状态变化内容给上游系统。 * 当人为操作(比如拍灯,更改数字,放箱等)导致电子标签的状态和信号等发生变化、或设备本身发生异常时,ESS接收到信号后,通过该接口将信号回传给上游系统。 * * RFID回调接口 * * @param request * @return */ public R rfidCallback(@RequestBody RfidSingalRequest request) { if (Objects.isNull(request)) { throw new CoolException("参数不能为空!!"); } return wcsApiService.rfidCallback(request); } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/apis/wcs/controller/WaveManagentController.java
@@ -135,17 +135,6 @@ } /** * 信号回传接口,回传电子标签状态变化内容给上游系统。 * 当人为操作(比如拍灯,更改数字,放箱等)导致电子标签的状态和信号等发生变化、或设备本身发生异常时,ESS接收到信号后,通过该接口将信号回传给上游系统。 * @param request * @return */ @PostMapping("/") public R rfidCallback(@RequestBody RfidSingalRequest request) { return R.ok(); } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/apis/wcs/entity/domain/SystemProperties.java
@@ -1,6 +1,7 @@ package com.zy.asrs.wms.apis.wcs.entity.domain; import com.zy.asrs.wms.system.entity.Host; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @@ -21,5 +22,7 @@ public static String CONVEYOR_START = HOST + "/conveyor/moveContainer"; public static String SLAP_LIGHT = HOST + "/expand/api/equipment/ptl/sendCommand"; } zy-asrs-wms/src/main/java/com/zy/asrs/wms/apis/wcs/entity/request/SlapLightControlParam.java
New file @@ -0,0 +1,47 @@ package com.zy.asrs.wms.apis.wcs.entity.request; import lombok.Data; import lombok.experimental.Accessors; import java.io.Serializable; @Data @Accessors(chain = true) public class SlapLightControlParam implements Serializable { /** * 控制器code,需要与控制器配置ptlController里的code对应。 */ private String controllerCode; /** * 电子标签序号,需要与电子标签ptlTag里的index对应。 */ private String index; /** * 电子标签编号,需要与电子标签ptlTag里的code对应 */ private String tagCode; /** * 颜色: * RED * GREEN * BLUE */ private String color; /** * 工作模式: * LIGHT:亮灯 * DARK:灭灯 * FLASH:闪灯 */ private String mode; /** * 常用于显示数字,支持3位数。 */ private String display; } zy-asrs-wms/src/main/java/com/zy/asrs/wms/apis/wcs/services/Impl/WcsApiServiceImpl.java
@@ -1,25 +1,37 @@ package com.zy.asrs.wms.apis.wcs.services.Impl; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.zy.asrs.framework.common.R; import com.zy.asrs.framework.exception.CoolException; import com.zy.asrs.wms.apis.wcs.entity.domain.SystemProperties; import com.zy.asrs.wms.apis.wcs.entity.enums.EssTaskStatus; import com.zy.asrs.wms.apis.wcs.entity.request.*; import com.zy.asrs.wms.apis.wcs.entity.response.CommonReponse; import com.zy.asrs.wms.apis.wcs.services.WcsApiService; import com.zy.asrs.wms.asrs.entity.Task; import com.zy.asrs.wms.asrs.entity.TaskDetl; import com.zy.asrs.wms.asrs.entity.WaveSeed; import com.zy.asrs.wms.asrs.entity.enums.TaskStsType; import com.zy.asrs.wms.asrs.service.TaskService; import com.zy.asrs.wms.asrs.service.WaitPakinService; import com.zy.asrs.wms.asrs.service.WorkService; import com.zy.asrs.wms.asrs.service.*; import io.jsonwebtoken.lang.Collections; import lombok.extern.slf4j.Slf4j; 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.transaction.annotation.Transactional; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; @Slf4j @Service @@ -31,7 +43,14 @@ private WorkService workService; @Autowired private TaskService taskService; @Autowired private TaskDetlService taskDetlService; @Autowired private WaveSeedService waveSeedService; @Autowired private RestTemplate restTemplate; /** @@ -78,6 +97,13 @@ return R.success("success"); } /** * 容器执行状态上报 * * @param callbackParam * @param stockType * @param hostId */ @Override @Transactional(rollbackFor = Exception.class) public void receiveTaskStatus(TasksStatusCallbackParam callbackParam, String stockType, Long hostId) { @@ -86,87 +112,89 @@ .eq(Task::getTaskNo, callbackParam.getTaskCode())); if (!Collections.isEmpty(list)) { list.forEach(task -> { TaskStsType taskStsType = null; if (stockType.equals("inStock")) { //入库任务 if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_TOTE_LOAD.event)) { //上报取箱状态 if (task.getTaskSts() == TaskStsType.WCS_CONVEYOR_START.id) { taskStsType = TaskStsType.WCS_TOTE_LOAD; } else { String errMsg = "任务编号:" + task.getTaskNo() + "状态为不匹配," + "不能执行:" + TaskStsType.WCS_TOTE_LOAD.desc + "任务"; log.error(errMsg); throw new CoolException(errMsg); } } else if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_TOTE_UNLOAD.event)) { //上报放箱状态 if (task.getTaskSts() == TaskStsType.WCS_TOTE_LOAD.id) { taskStsType = TaskStsType.WCS_TOTE_UNLOAD; } else { String errMsg = "任务编号:" + task.getTaskNo() + "状态为不匹配," + "不能执行:" + TaskStsType.WCS_TOTE_UNLOAD.desc + "任务"; log.error(errMsg); throw new CoolException(errMsg); } } else if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_STATUS.event)) { //TODO 需确认上报任务中,任务完成是哪个事件,目前暂定task事件 if (task.getTaskSts() == TaskStsType.WCS_TOTE_UNLOAD.id) { taskStsType = TaskStsType.WCS_PUTAWAY_SUCESS; } else { String errMsg = "任务编号:" + task.getTaskNo() + "状态为不匹配," + "不能执行:" + TaskStsType.WCS_PUTAWAY_SUCESS.desc + "任务"; log.error(errMsg); throw new CoolException(errMsg); } TaskStsType taskStsType = null; if (stockType.equals("inStock")) { //入库任务 if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_TOTE_LOAD.event)) { //上报取箱状态 if (task.getTaskSts() == TaskStsType.WCS_CONVEYOR_START.id) { taskStsType = TaskStsType.WCS_TOTE_LOAD; } else { String errMsg = "任务编号:" + task.getTaskNo() + "状态为不匹配," + "不能执行:" + TaskStsType.WCS_TOTE_LOAD.desc + "任务"; log.error(errMsg); throw new CoolException(errMsg); } boolean result = taskService.update(new LambdaUpdateWrapper<Task>() .set(Task::getRobotCode, callbackParam.getRobotCode()) .set(Task::getSysTaskCode, callbackParam.getSysTaskCode()) .set(Task::getTaskSts, taskStsType.id) .set(Task::getExcudeStatus, callbackParam.getStatus()) .set(Task::getTaskDesc, callbackParam.getMessage()) .eq(Task::getBarcode, callbackParam.getContainerCode()) .eq(Task::getTaskNo, callbackParam.getTaskCode())); if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_STATUS.event) && result) { workService.completeTask(task.getId()); } else if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_TOTE_UNLOAD.event)) { //上报放箱状态 if (task.getTaskSts() == TaskStsType.WCS_TOTE_LOAD.id) { taskStsType = TaskStsType.WCS_TOTE_UNLOAD; } else { String errMsg = "任务编号:" + task.getTaskNo() + "状态为不匹配," + "不能执行:" + TaskStsType.WCS_TOTE_UNLOAD.desc + "任务"; log.error(errMsg); throw new CoolException(errMsg); } } else { //出库任务 if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_TOTE_LOAD.event)) { //上报取箱状态 //TODO 定时器开启后,要删除 || task.getTaskType() == TaskStsType.GENERATE_OUT.id if (task.getTaskSts() == TaskStsType.WCS_EXECUTE_OUT.id || task.getTaskSts() == TaskStsType.GENERATE_OUT.id) { taskStsType = TaskStsType.WCS_EXECUTE_OUT_TOTE_LOAD; } else { String errMsg = "任务编号:" + task.getTaskNo() + "状态为不匹配," + "不能执行:" + TaskStsType.WCS_EXECUTE_OUT_TOTE_LOAD.desc + "任务"; log.error(errMsg); throw new CoolException(errMsg); } } else if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_TOTE_UNLOAD.event)) { //上报放箱状态 if (task.getTaskSts() == TaskStsType.WCS_EXECUTE_OUT_TOTE_LOAD.id) { taskStsType = TaskStsType.WCS_EXECUTE_OUT_TOTE_UNLOAD; } else { String errMsg = "任务编号:" + task.getTaskNo() + "状态为不匹配," + "不能执行:" + TaskStsType.WCS_EXECUTE_OUT_TOTE_UNLOAD.desc + "任务"; log.error(errMsg); throw new CoolException(errMsg); } } else if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_STATUS.event)) { //上报完成状态 if (task.getTaskSts() == TaskStsType.WCS_EXECUTE_OUT_TOTE_UNLOAD.id || task.getTaskSts() == TaskStsType.WCS_EXECUTE_OUT_TASK_DONE.id) { //出库任务完成,修改状态为容器到达,定时任务生成播种波次 taskStsType = TaskStsType.WCS_EXECUTE_OUT_TASK_DONE; } else { String errMsg = "任务编号:" + task.getTaskNo() + "状态为不匹配," + "不能执行:" + TaskStsType.WCS_EXECUTE_OUT_TASK_DONE.desc + "任务"; log.error(errMsg); throw new CoolException(errMsg); } } else if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_STATUS.event)) { //TODO 需确认上报任务中,任务完成是哪个事件,目前暂定task事件 if (task.getTaskSts() == TaskStsType.WCS_TOTE_UNLOAD.id) { taskStsType = TaskStsType.WCS_PUTAWAY_SUCESS; } else { String errMsg = "任务编号:" + task.getTaskNo() + "状态为不匹配," + "不能执行:" + TaskStsType.WCS_PUTAWAY_SUCESS.desc + "任务"; log.error(errMsg); throw new CoolException(errMsg); } } boolean result = taskService.update(new LambdaUpdateWrapper<Task>() .set(Task::getRobotCode, callbackParam.getRobotCode()) .set(Task::getSysTaskCode, callbackParam.getSysTaskCode()) .set(Task::getTaskSts, taskStsType.id) .set(Task::getExcudeStatus, callbackParam.getStatus()) .set(Task::getTaskDesc, callbackParam.getMessage()) .eq(Task::getBarcode, callbackParam.getContainerCode()) .eq(Task::getTaskNo, callbackParam.getTaskCode())); //更新出库状态及相关字段 taskService.update(new LambdaUpdateWrapper<Task>() .set(Task::getRobotCode, callbackParam.getRobotCode()) .set(Task::getSysTaskCode, callbackParam.getSysTaskCode()) .set(Task::getTaskSts, taskStsType.id) .set(Task::getExcudeStatus, callbackParam.getStatus()) .set(Task::getTaskDesc, callbackParam.getMessage()) .eq(Task::getBarcode, callbackParam.getContainerCode()) .eq(Task::getTaskNo, callbackParam.getTaskCode())); //event事件为task,表明任务上报完成状态 if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_STATUS.event) && result) { //任务状态修改为 99 入库完成 workService.completeTask(task.getId()); } } else { //出库任务 if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_TOTE_LOAD.event)) { //上报取箱状态 //TODO 定时器开启后,要删除 || task.getTaskType() == TaskStsType.GENERATE_OUT.id if (task.getTaskSts() == TaskStsType.WCS_EXECUTE_OUT.id || task.getTaskSts() == TaskStsType.GENERATE_OUT.id) { taskStsType = TaskStsType.WCS_EXECUTE_OUT_TOTE_LOAD; } else { String errMsg = "任务编号:" + task.getTaskNo() + "状态为不匹配," + "不能执行:" + TaskStsType.WCS_EXECUTE_OUT_TOTE_LOAD.desc + "任务"; log.error(errMsg); throw new CoolException(errMsg); } } else if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_TOTE_UNLOAD.event)) { //上报放箱状态 if (task.getTaskSts() == TaskStsType.WCS_EXECUTE_OUT_TOTE_LOAD.id) { taskStsType = TaskStsType.WCS_EXECUTE_OUT_TOTE_UNLOAD; } else { String errMsg = "任务编号:" + task.getTaskNo() + "状态为不匹配," + "不能执行:" + TaskStsType.WCS_EXECUTE_OUT_TOTE_UNLOAD.desc + "任务"; log.error(errMsg); throw new CoolException(errMsg); } } else if (callbackParam.getEventType().equals(EssTaskStatus.TASK_EVENT_STATUS.event)) { //上报完成状态 if (task.getTaskSts() == TaskStsType.WCS_EXECUTE_OUT_TOTE_UNLOAD.id || task.getTaskSts() == TaskStsType.WCS_EXECUTE_OUT_TASK_DONE.id) { //出库任务完成,修改状态为容器到达,定时任务生成播种波次 taskStsType = TaskStsType.WCS_EXECUTE_OUT_TASK_DONE; } else { String errMsg = "任务编号:" + task.getTaskNo() + "状态为不匹配," + "不能执行:" + TaskStsType.WCS_EXECUTE_OUT_TASK_DONE.desc + "任务"; log.error(errMsg); throw new CoolException(errMsg); } } }); //更新出库状态及相关字段 taskService.update(new LambdaUpdateWrapper<Task>() .set(Task::getRobotCode, callbackParam.getRobotCode()) .set(Task::getSysTaskCode, callbackParam.getSysTaskCode()) .set(Task::getTaskSts, taskStsType.id) .set(Task::getExcudeStatus, callbackParam.getStatus()) .set(Task::getTaskDesc, callbackParam.getMessage()) .eq(Task::getBarcode, callbackParam.getContainerCode()) .eq(Task::getTaskNo, callbackParam.getTaskCode())); } }); } else { throw new CoolException("更新内容不存在!!"); } @@ -174,15 +202,16 @@ /** * 容器流动通知 * * @param code * @return */ @Override public R containerConveryor(String code) { public synchronized R containerConveryor(String code) { List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, code)); if (tasks.isEmpty()) { return R.error("容器码任务不存在!!"); } else if (tasks.size() > 1){ } else if (tasks.size() > 1) { return R.error("容器码任务错误!!"); } tasks.forEach(task -> { @@ -214,6 +243,8 @@ //流动通知下发完成后,修改任务状态为输送线流动中。。 //TODO 判断任务是否为103拣料出库,103拣料流动后修改为4(RCS容器流动任务已下发) if (task.getTaskType() == 103) { //TODO 需找海柔确认是否需要重新调用入库接口 //更新库存信息,修改任务状态为4 (RCS容器流动任务已下发) workService.pickTask(task.getId()); // taskService.update(new LambdaUpdateWrapper<Task>().eq(Task::getId, task.getId()).set(Task::getTaskSts, TaskStsType.WCS_CONVEYOR_START)) } else { @@ -238,4 +269,99 @@ return R.ok(); } @Override public R rfidCallback(RfidSingalRequest request) { return null; } /** * 拍灯拣料逻辑,详细说明见接口调用说明 * * @param request */ @Override public void slapLightLogic(Map<String, Object> request) { String taskNo = request.get("taskNo").toString(); String orderNo = request.get("orderNo").toString(); //* 1. 判断当前容器是否还有物料未拣,未拣完闪灯,拣完通知容器流动,并灭灯 SlapLightControlParam slapParam = new SlapLightControlParam(); MultiValueMap<String, Object> params = new LinkedMultiValueMap<>(); //默认流动 boolean converyor = false; //判断是否还有物料未拣 if (!checked(orderNo, taskNo)) { //调用三方接口,闪灯不做操作 // 设置请求参数 params.add("params", JSONObject.toJSONString(slapParam)); log.info("请求地址:{},请求参数:{}", SystemProperties.SLAP_LIGHT, JSONObject.toJSONString(slapParam)); } else { //调用三方接口,来灯通知容器流动, 传灭灯参数 params.add("params", JSONObject.toJSONString(slapParam)); log.info("请求地址:{},请求参数:{}", SystemProperties.SLAP_LIGHT, JSONObject.toJSONString(slapParam)); } HttpHeaders headers = new HttpHeaders(); headers.add("Content-Type", "application/json"); HttpEntity httpEntity = new HttpEntity<>(params, headers); // 请求 ResponseEntity<CommonReponse> exchange = restTemplate.exchange(SystemProperties.CONVEYOR_START, HttpMethod.POST, httpEntity, CommonReponse.class); log.info("下发流动通知 返回结果:{}", exchange); if (exchange.getBody() == null) { throw new CoolException("下发流动通知失败!!"); } else { CommonReponse response = exchange.getBody(); if (response.getCode() == 0) { if (!converyor) { //* 2. 容器流动判断,如果料箱没有物料 code传200, 有物料传100 执行回库任务,修改任务状态为 调用containerConveryor(taskNo)方法 containerConveryor(request.get("taskNo").toString()); } } } } /** * 判断当前任务下,订单是否已完成拣货 * * @param orderNo * @param taskNo * @return */ public synchronized boolean checked(String orderNo, String taskNo) { if (Objects.isNull(orderNo)) { throw new CoolException("订单编码不能为空!!"); } if (Objects.isNull(taskNo)) { throw new CoolException("任务编码不能为空!!"); } List<TaskDetl> taskDetls = taskDetlService.list(new LambdaQueryWrapper<TaskDetl>().eq(TaskDetl::getTaskNo, taskNo)); if (taskDetls.isEmpty()) { throw new CoolException("订单明细不存在!!"); } List<Long> detlIds = taskDetls.stream().map(TaskDetl::getId).collect(Collectors.toList()); double taskNum = taskDetls.stream().mapToDouble(TaskDetl::getAnfme).sum(); List<WaveSeed> seeds = waveSeedService.list(new LambdaQueryWrapper<WaveSeed>().in(WaveSeed::getTaskDetlId, detlIds)); if (seeds.isEmpty()) { throw new CoolException("播种信息不存在!!!"); } double seedNum = seeds.stream().mapToDouble(WaveSeed::getWorkQty).sum(); //判断任务需求总量是否等播种总数量 if (taskNum == seedNum) { return true; } else { return false; } } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/apis/wcs/services/WcsApiService.java
@@ -2,7 +2,10 @@ import com.zy.asrs.framework.common.R; import com.zy.asrs.wms.apis.wcs.entity.request.ContainerArrivedParam; import com.zy.asrs.wms.apis.wcs.entity.request.RfidSingalRequest; import com.zy.asrs.wms.apis.wcs.entity.request.TasksStatusCallbackParam; import java.util.Map; public interface WcsApiService { @@ -11,4 +14,8 @@ void receiveTaskStatus(TasksStatusCallbackParam callbackParam, String stockType, Long hostId); R containerConveryor(String code); void slapLightLogic(Map<String, Object> request); R rfidCallback(RfidSingalRequest request); } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/controller/MobileController.java
@@ -16,6 +16,7 @@ import com.zy.asrs.wms.asrs.entity.WaitPakin; import com.zy.asrs.wms.asrs.entity.dto.OrderInfoDto; import com.zy.asrs.wms.asrs.entity.dto.PickSheetDetlDto; import com.zy.asrs.wms.asrs.entity.dto.ShippingOrderDetlDto; import com.zy.asrs.wms.asrs.entity.param.BatchMergeOrdersParam; import com.zy.asrs.wms.asrs.entity.param.PageRequest; import com.zy.asrs.wms.asrs.entity.param.PakinOnShelvesParams; @@ -258,4 +259,31 @@ } } /** * 获取发货订单明细 * @return */ @PostMapping("/shipping/order/detl") public R getOrderDetl(@RequestBody Map<String, Object> params) { if (Objects.isNull(params)) { throw new CoolException("参数不能为空!!"); } return mobileService.selectShippingDetl(params); } /** * 确认发货单明细 * @return */ @PostMapping("/shipping/confirm") public R confirmShipping(@RequestBody List<ShippingOrderDetlDto> params) { if (params.isEmpty()) { throw new CoolException("发货单明细不能为空!!"); } return mobileService.confirmShippingDetl(params); } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/entity/dto/ShippingOrderDetlDto.java
New file @@ -0,0 +1,42 @@ package com.zy.asrs.wms.asrs.entity.dto; import lombok.Data; import java.io.Serializable; @Data public class ShippingOrderDetlDto implements Serializable { /** * 订单编码 */ private String orderNo; /** * 订单明细标识 */ private String id; /** * 波次号 */ private String waveNo; /** * 订单需求量 */ private Double anfme; /** * 批次 */ private String batch; /** * 站点 */ private String siteNo; /** * 实际拣货量 */ private Double workQty; /** * 备注 */ private String memo; } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/mapper/WaveSeedMapper.java
@@ -6,6 +6,7 @@ import com.zy.asrs.wms.apis.wcs.entity.response.SowSeeds; import com.zy.asrs.wms.asrs.entity.WaveSeed; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.zy.asrs.wms.asrs.entity.dto.ShippingOrderDetlDto; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; @@ -18,4 +19,5 @@ List<SowSeeds> getSeedsList(@Param(Constants.WRAPPER) LambdaQueryWrapper<WaveSeed> ew); List<ShippingOrderDetlDto> selectShippingOrderDtel(@Param("orderNo") String orderNo); } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/MobileService.java
@@ -1,7 +1,9 @@ package com.zy.asrs.wms.asrs.service; import com.zy.asrs.framework.common.R; import com.zy.asrs.wms.asrs.entity.CacheSite; import com.zy.asrs.wms.asrs.entity.dto.PickSheetDetlDto; import com.zy.asrs.wms.asrs.entity.dto.ShippingOrderDetlDto; import com.zy.asrs.wms.asrs.entity.param.BatchMergeOrdersParam; import com.zy.asrs.wms.asrs.entity.param.PakinOnShelvesParams; import com.zy.asrs.wms.system.entity.Host; @@ -25,4 +27,8 @@ List<CacheSite> getSeedLocs(); boolean bindOrderBySite(Map<String, Object> param); R selectShippingDetl(Map<String, Object> params); R confirmShippingDetl(List<ShippingOrderDetlDto> params); } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/CacheSiteServiceImpl.java
@@ -71,15 +71,7 @@ List<WaveSeed> waveSeeds = waveSeedService.list(new LambdaQueryWrapper<WaveSeed>().eq(WaveSeed::getOrderId, orderId)); //fixme 校验当前订单是否完成播种,需要获取当前波次所有任务中A物料的执行数量是否等于订单的总量-已完成数量(anfme - qty) 或者 任务中已执行数量是否等订单中的执行数量 workQty = workQty List<OrderDetl> orderDetls = orderDetlService.getOrderDetlByOrderId(orderId); //获取订单A所有明细物料 // if (orderDetls.isEmpty()) { // throw new CoolException("订单明细不存在!!"); // } // List<Long> matnrs = orderDetls.stream().map(OrderDetl::getMatId).collect(Collectors.toList()); // orderDetls.forEach(orderDetl -> { // // }); // List<WaveSeed> waveSeeds = waveSeedService.list(new LambdaQueryWrapper<WaveSeed>().eq(WaveSeed::getWaveId, order.getWaveId())); for (WaveSeed waveSeed : waveSeeds) { Double anfme = stockMap.get(waveSeed.getOrderDetlId()); if (anfme == null) { @@ -89,7 +81,6 @@ stockMap.put(waveSeed.getOrderDetlId(), anfme); } // List<OrderDetl> orderDetls = orderDetlService.getOrderDetlByOrderId(orderId); boolean check = true; for (OrderDetl orderDetl : orderDetls) { Double anfme = Optional.of(orderDetl.getAnfme() - orderDetl.getQty()).orElse(0.0D); @@ -135,6 +126,7 @@ Long waveId = order.getWaveId(); boolean check = this.seedCompletePreview(param); if (!check) {//订单未处理完成 List<Long> taskIds = new ArrayList<>(); List<TaskDetl> taskDetls = taskDetlService.list(new LambdaQueryWrapper<TaskDetl>().eq(TaskDetl::getWaveId, waveId)); zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/MobileServiceImpl.java
@@ -2,18 +2,17 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.zy.asrs.framework.common.R; import com.zy.asrs.framework.exception.CoolException; import com.zy.asrs.wms.asrs.entity.*; import com.zy.asrs.wms.asrs.entity.dto.PickSheetDetlDto; import com.zy.asrs.wms.asrs.entity.dto.ShippingOrderDetlDto; import com.zy.asrs.wms.asrs.entity.enums.*; import com.zy.asrs.wms.asrs.entity.enums.OrderType; import com.zy.asrs.wms.asrs.entity.param.BatchMergeOrdersParam; import com.zy.asrs.wms.asrs.entity.param.GeneratePakInParam; import com.zy.asrs.wms.asrs.entity.param.PakinOnShelvesParams; import com.zy.asrs.wms.asrs.mapper.CacheSiteMapper; import com.zy.asrs.wms.asrs.mapper.OrderDetlLogMapper; import com.zy.asrs.wms.asrs.mapper.OrderDetlMapper; import com.zy.asrs.wms.asrs.mapper.SeedSitesMapper; import com.zy.asrs.wms.asrs.mapper.*; import com.zy.asrs.wms.asrs.service.*; import com.zy.asrs.wms.system.entity.Host; import com.zy.asrs.wms.system.service.HostService; @@ -69,9 +68,13 @@ private SeedSitesMapper seedSitesMapper; @Autowired private OrderDetlMapper orderDetlMapper; @Autowired private WaveSeedMapper waveSeedMapper; @Autowired private WaveSeedLogService waveSeedLogService; @Autowired private OrderDetlLogService orderDetlLogService; @Override @Transactional(rollbackFor = Exception.class) @@ -389,4 +392,94 @@ return true; } @Override public R selectShippingDetl(Map<String, Object> params) { //判断订单是否为空 if (StringUtil.isNullOrEmpty((String) params.get("orderNo"))) { throw new CoolException("订单编码号不能为空!!"); } String orderId = params.get("orderNo").toString(); List<ShippingOrderDetlDto> waveSeeds = waveSeedMapper.selectShippingOrderDtel(orderId); return R.ok(waveSeeds); } /** * 发货单明细确认 * 1. 出库修改订单完成状态,判断订单是否完成,完成加入历史档,未完成修改订单已完成数量 * 2. 删除订单已完成播种明细信息 * 3. 清除集货区绑定数据 * @param params * @return */ @Override @Transactional(rollbackFor = Exception.class) public R confirmShippingDetl(List<ShippingOrderDetlDto> params) { if (params.isEmpty()) { throw new CoolException("发货单据明细为空,不可执行发货操作!!"); } params.forEach(order -> { //删除出库订单及明细,加入订单历史档 if (order.getAnfme() == order.getWorkQty()) { //完全拣货 OrderDetl byId = orderDetlService.getById(order.getId()); OrderDetlLog orderDetlLog = new OrderDetlLog(); BeanUtils.copyProperties(orderDetlLog, byId); orderDetlLog.setQty(order.getWorkQty()); orderDetlLog.setWorkQty(0.0); if (!orderDetlLogService.save(orderDetlLog)) { throw new CoolException("订单明细转历史档失败!!"); } if (!orderDetlService.removeById(byId)) { throw new CoolException("订单明细不存在!!"); } //查询当前订单下否还有明细存在 List<OrderDetl> orders = orderDetlService.list(new LambdaQueryWrapper<OrderDetl>().eq(OrderDetl::getOrderNo, order.getOrderNo())); if (orders.isEmpty()) { Order one = orderService.getOne(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, order.getOrderNo())); if (Objects.isNull(one)) { throw new CoolException("订单不存在!!"); } OrderLog orderLog = new OrderLog(); BeanUtils.copyProperties(one, orderLog); if (!orderLogService.save(orderLog)) { throw new CoolException("原始订单转历史档失败!!"); } if (!orderService.remove(new LambdaQueryWrapper<Order>().eq(Order::getOrderNo, order.getOrderNo()))) { throw new CoolException("原始订单删除失败!!"); } } } else { //todo 删除已完成明细,保留原始主单及未完成明细 } List<WaveSeed> waveSeeds = waveSeedMapper.selectList(new LambdaQueryWrapper<WaveSeed>().eq(WaveSeed::getOrderDetlId, order.getId())); //fixme 订单明细未播种,默认可发货 if (!waveSeeds.isEmpty()) { ArrayList<WaveSeedLog> waveSeedLogs = new ArrayList<>(); waveSeeds.forEach(seed -> { WaveSeedLog waveSeedLog = new WaveSeedLog(); BeanUtils.copyProperties(waveSeedLog, seed); waveSeedLog.setId(null); waveSeedLogs.add(waveSeedLog); }); if (waveSeedLogService.saveBatch(waveSeedLogs)) { throw new CoolException("波明历史档保存失败!!"); } } //删除播种明细信息 if (waveSeedMapper.deleteByIds(waveSeeds) < 1) { throw new CoolException("播种明细删除携程!!"); } }); return null; } } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/service/impl/WorkServiceImpl.java
@@ -673,8 +673,9 @@ } TaskDetl taskDetl = taskDetls.get(0); //生成库位 //生成新的库位 !important Loc loc = this.generateLoc(taskType, taskDetl.getMatId(), taskDetl.getBatch(), taskDetl.getUniqueField(), locTypeHeightType.id); if(loc == null) { throw new CoolException("没有空库位"); } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/timer/TaskTimer.java
@@ -327,7 +327,6 @@ Long hostId = task.getHostId(); //fixme 将任务当前 Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getLocNo, task.getTargetLoc()).eq(Loc::getHostId, hostId)); // Loc loc = locService.getOne(new LambdaQueryWrapper<Loc>().eq(Loc::getLocNo, task.getTargetLoc())); if (loc == null) { throw new CoolException("库位不存在"); } @@ -339,6 +338,7 @@ loc.setLocStsId(LocStsType.F.val()); loc.setUpdateTime(new Date()); loc.setBarcode(task.getBarcode()); if (!locService.updateById(loc)) { throw new CoolException("库位状态更新失败"); } zy-asrs-wms/src/main/java/com/zy/asrs/wms/asrs/timer/TaskWaveTimer.java
@@ -44,8 +44,8 @@ /** * modifty: * original : fetch datasource of task type on WAVE_SEED * now: Fetch datasource of task type on WCS_EXECUTE_OUT_ARRIVED, After completing the task and for setting the task type equal to WAVE_SEED * original : fetch datasource of task type on WCS_EXECUTE_OUT_TASK_DONE * now: Fetch datasource of task type on WCS_EXECUTE_OUT_ARRIVED, After completing the task and for setting the task type equal to GENERATE_WAVE_SEED */ @Scheduled(cron = "0/15 * * * * ? ") @Transactional(rollbackFor = Exception.class) @@ -60,7 +60,7 @@ if (!autoCreateWaveSeed.equals("true")) { return; } //查询状态为容器到达状态所有任务单据 //查询状态为RCS任务完成所有任务单据 // List<Task> taskList = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTaskSts, TaskStsType.WAVE_SEED.id)); List<Task> taskList = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getTaskSts, TaskStsType.WCS_EXECUTE_OUT_TASK_DONE.id)); HashSet<String> sycMatnrs = new HashSet<>(); zy-asrs-wms/src/main/resources/mapper/asrs/WaveSeedMapper.xml
@@ -11,4 +11,28 @@ ( SELECT id, site_id, site_no, order_no, anfme, work_qty, matnr, batch, create_time, `status`, create_by, memo, deleted FROM man_wave_seed ) t ${ew.customSqlSegment} </select> <select id="selectShippingOrderDtel" resultType="com.zy.asrs.wms.asrs.entity.dto.ShippingOrderDetlDto"> SELECT mo.order_no, mo.id, wcs.wave_no, mo.anfme, mo.batch, wcs.site_no, wcs.work_qty, wcs.memo FROM man_order_detl mo LEFT JOIN (SELECT wave_no, order_detl_id , site_no, order_no, SUM(anfme) anfme, SUM(work_qty) work_qty, memo, batch, matnr FROM man_wave_seed GROUP BY order_id, matnr, batch) wcs ON mo.id = wcs.order_detl_id <where> 1 = 1 <if test="orderNo != null and orderNo != ''"> AND mo.order_no = #{orderNo} </if> </where> </select> </mapper>