1. 添加入库单检查业务逻辑

2. 添加入库单检查接口, 入库出库回调接口
This commit is contained in:
李宇奇 2025-04-02 00:35:01 +08:00
parent 71bea7af06
commit 38387baa09
11 changed files with 332 additions and 1 deletions

View File

@ -17,7 +17,10 @@ public enum AppConfigKeyEnums {
IMAGE_IP("ImageIp", "图片存放ip"),
EMPTY_BACK("EmptyBack", "空载具是否回库"),
STOCK_WARNING_QTY("StockWarningQty", "库存预警数量"),
MES_GET_GOODS_URL("MesGetGoodsUrl", "获取物料信息地址");
MES_GET_GOODS_URL("MesGetGoodsUrl", "获取物料信息地址"),
ERP_GET_VEHICLENO_DATA("ErpGetVehicleNoData", "根据托盘号查询简单生产入库单"),
WMS_MANAGE_CALLBACK("WmsManageCallback", "场内WMS接受的入库出库执行后回调地址");
private final String key;
private final String desc;
}

View File

@ -0,0 +1,18 @@
package com.wms_main.constant.enums.ycwms;
import lombok.Getter;
@Getter
public enum OrderStatusEnum {
RUNNING(1, "执行中"),
COMPLETE(2, "任务完成"),
EXCEPTION(3, "执行异常");
private Integer code;
private String desc;
OrderStatusEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
}

View File

@ -0,0 +1,24 @@
package com.wms_main.model.bo.erp;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.poi.hpsf.Decimal;
import java.math.BigDecimal;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ErpGoodsDetail {
private String goodsId;
private String goodsName;
private String batch;
private String goodsType;
private Integer specification;
private BigDecimal quantity;
private String goodsDesc;
private String xsfbillno;
private String xsfseq;
private String neibubianhao;
}

View File

@ -0,0 +1,16 @@
package com.wms_main.model.bo.erp;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.*;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ErpVehicleNoResp {
@JsonProperty("vehicleNo")
private String vehicleNo;
@JsonProperty("goodsDetail")
private List<ErpGoodsDetail> goodsDetail;
}

View File

@ -0,0 +1,18 @@
package com.wms_main.model.bo.ycwms;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class YCWmsApiResponse {
@JsonProperty("state")
private String state;
@JsonProperty("message")
private String message;
@JsonProperty("data")
private Object data;
}

View File

@ -0,0 +1,15 @@
package com.wms_main.model.dto.request.ycwms;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderInCBReq {
String orderId;
String vehicleNo;
Integer orderStatus;
String message;
}

View File

@ -0,0 +1,16 @@
package com.wms_main.model.dto.request.ycwms;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderOutCBReq {
String orderId;
String vehicleNo;
Integer orderStatus;
String outStand;
String message;
}

View File

@ -3,10 +3,12 @@ package com.wms_main.model.dto.response.ycwms;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class YcwmsResponse<T> {
@JsonProperty("code")

View File

@ -0,0 +1,16 @@
package com.wms_main.service.api;
import com.wms_main.model.bo.erp.ErpVehicleNoResp;
import com.wms_main.model.bo.ycwms.YCWmsApiResponse;
import com.wms_main.model.dto.request.ycwms.OrderInCBReq;
import com.wms_main.model.dto.request.ycwms.OrderOutCBReq;
import com.wms_main.model.dto.response.wms.WmsApiResponse;
import com.wms_main.model.dto.response.ycwms.YcwmsResponse;
public interface IExternalApiService {
YcwmsResponse<ErpVehicleNoResp> getVehicleNoData(String vehicleNo);
YCWmsApiResponse invokeOrderInCB(OrderInCBReq request);
YCWmsApiResponse invokeOrderOutCB(OrderOutCBReq request);
}

View File

@ -0,0 +1,116 @@
package com.wms_main.service.api.serviceImpl;
import com.wms_main.app.AppCommon;
import com.wms_main.constant.enums.wms.AppConfigKeyEnums;
import com.wms_main.model.bo.erp.ErpGoodsDetail;
import com.wms_main.model.bo.erp.ErpVehicleNoResp;
import com.wms_main.model.bo.ycwms.YCWmsApiResponse;
import com.wms_main.model.dto.request.ycwms.OrderInCBReq;
import com.wms_main.model.dto.request.ycwms.OrderOutCBReq;
import com.wms_main.model.dto.response.wms.WmsApiResponse;
import com.wms_main.model.dto.response.ycwms.YcwmsResponse;
import com.wms_main.repository.http.HttpClient;
import com.wms_main.repository.http.entity.HttpRequest;
import com.wms_main.repository.http.entity.HttpResponse;
import com.wms_main.service.api.IExternalApiService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
@RequiredArgsConstructor
@Slf4j
public class ExternalApiServiceImpl implements IExternalApiService {
private final HttpClient httpClient;// http客户端
private final AppCommon appCommon;// 应用共通
@Override
public YcwmsResponse<ErpVehicleNoResp> getVehicleNoData(String vehicleNo) {
Map<String, String> request = new HashMap<>();
request.put("vehicleNo", vehicleNo);
HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.ERP_GET_VEHICLENO_DATA.getKey()), request);
HttpResponse httpResponse = httpClient.httpPost(httpRequest);
if (httpResponse != null && httpResponse.isSuccess()) {
try {
String responseMessage = httpResponse.getResponseMessage();
// 使用Map接收基本响应避免泛型问题
Map<String, Object> baseResponseMap = JSON.parseObject(responseMessage, Map.class);
// 创建最终返回的对象
YcwmsResponse<ErpVehicleNoResp> finalResponse = new YcwmsResponse<>();
finalResponse.setCode((Integer) baseResponseMap.get("code"));
finalResponse.setMessage((String) baseResponseMap.get("message"));
// 处理returnData部分
if (baseResponseMap.containsKey("returnData") && baseResponseMap.get("returnData") != null) {
// 转换returnData部分
Map<String, Object> returnDataMap = (Map<String, Object>) baseResponseMap.get("returnData");
// 创建ErpVehicleNoResp对象
ErpVehicleNoResp vehicleData = new ErpVehicleNoResp();
vehicleData.setVehicleNo((String) returnDataMap.get("vehicleNo"));
// 处理goodsDetail数组
List<Map<String, Object>> goodsDetailList = (List<Map<String, Object>>) returnDataMap.get("goodsDetail");
List<ErpGoodsDetail> erpsGoodsDetails = new ArrayList<>();
if (goodsDetailList != null) {
for (Map<String, Object> detail : goodsDetailList) {
ErpGoodsDetail goodsDetail = new ErpGoodsDetail();
goodsDetail.setGoodsId((String) detail.get("goodsId"));
goodsDetail.setGoodsName((String) detail.get("goodsName"));
goodsDetail.setBatch((String) detail.get("batch"));
goodsDetail.setGoodsType((String) detail.get("goodsType"));
goodsDetail.setSpecification(Integer.parseInt(detail.get("specification").toString()));
goodsDetail.setQuantity(new java.math.BigDecimal(detail.get("quantity").toString()));
goodsDetail.setGoodsDesc((String) detail.get("goodsDesc"));
goodsDetail.setXsfbillno((String) detail.get("xsfbillno"));
goodsDetail.setXsfseq((String) detail.get("xsfseq"));
goodsDetail.setNeibubianhao((String) detail.get("neibubianhao"));
erpsGoodsDetails.add(goodsDetail);
}
}
vehicleData.setGoodsDetail(erpsGoodsDetails);
finalResponse.setReturnData(vehicleData);
}
return finalResponse;
} catch (Exception e) {
return YcwmsResponse.error("解析响应数据失败: " + e.getMessage(), null);
}
}
return YcwmsResponse.error("请求未获得响应信息。", null);
}
@Override
public YCWmsApiResponse invokeOrderInCB(OrderInCBReq request) {
HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WMS_MANAGE_CALLBACK.getKey()), request);
HttpResponse httpResponse = httpClient.httpPost(httpRequest);
if (httpResponse != null && httpResponse.isSuccess()) {
YCWmsApiResponse response = new YCWmsApiResponse();
response = httpResponse.getData(response.getClass().asSubclass(YCWmsApiResponse.class));
return response;
}
return new YCWmsApiResponse("error", "操作失败!", null);
}
@Override
public YCWmsApiResponse invokeOrderOutCB(OrderOutCBReq request) {
HttpRequest httpRequest = HttpRequest.postInstanceOf(appCommon.getConfigByKey(AppConfigKeyEnums.WMS_MANAGE_CALLBACK.getKey()), request);
HttpResponse httpResponse = httpClient.httpPost(httpRequest);
if (httpResponse != null && httpResponse.isSuccess()) {
YCWmsApiResponse response = new YCWmsApiResponse();
response = httpResponse.getData(response.getClass().asSubclass(YCWmsApiResponse.class));
return response;
}
return new YCWmsApiResponse("error", "操作失败!", null);
}
}

View File

@ -0,0 +1,87 @@
package com.wms_main.service.quartz_job.job_executor;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.wms_main.constant.enums.wms.OrderStatusEnum;
import com.wms_main.constant.enums.wms.WmsApiResponseCodeEnums;
import com.wms_main.dao.ITAppOrderInService;
import com.wms_main.dao.ITAppWcsTaskService;
import com.wms_main.model.bo.erp.ErpGoodsDetail;
import com.wms_main.model.bo.erp.ErpVehicleNoResp;
import com.wms_main.model.dto.response.ycwms.YcwmsResponse;
import com.wms_main.model.po.TAppOrderIn;
import com.wms_main.model.po.TAppWcsTask;
import com.wms_main.service.api.IExternalApiService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@PersistJobDataAfterExecution
// 以下注解用于实现fixed_delay
@DisallowConcurrentExecution
@RequiredArgsConstructor
public class OrderInCheckor implements Job {
private final ITAppOrderInService orderInService;
private final ITAppWcsTaskService wcsTaskService;
private final IExternalApiService externalApiService;
@Override
public void execute(JobExecutionContext jobExecutionContext) {
List<TAppOrderIn> inOrdersToCheck = orderInService.list(
new LambdaQueryWrapper<TAppOrderIn>()
.eq(TAppOrderIn::getOrderStatus, OrderStatusEnum.CREATE.getCode()));
// 根据载具号map一下
Map<String, List<TAppOrderIn>> vehicleIdToTaskMap = inOrdersToCheck.stream()
.filter(orderIn -> Objects.equals(orderIn.getOrderStatus(), OrderStatusEnum.CREATE.getCode()))
.filter(orderIn -> !(orderIn.getGoodsId().equals("0")))
.collect(Collectors.groupingBy(TAppOrderIn::getVehicleNo));
for (String vehicleNo : vehicleIdToTaskMap.keySet()) {
ErpGoodsDetail goods = new ErpGoodsDetail();
goods.setGoodsId("test");
goods.setGoodsName("test");
goods.setGoodsType("test");
List<ErpGoodsDetail> goodsDetails = new ArrayList<>();
goodsDetails.add(goods);
try {
YcwmsResponse<ErpVehicleNoResp> erpResp = externalApiService.getVehicleNoData(vehicleNo);
if (erpResp != null && WmsApiResponseCodeEnums.SUCCESS.getCode() == erpResp.getCode() && !erpResp.getReturnData().getGoodsDetail().isEmpty()) {
goodsDetails = erpResp.getReturnData().getGoodsDetail();
} else {
log.warn("获取载具[{}]数据失败,响应:{}", vehicleNo, erpResp);
}
} catch (Exception e) {
log.error("处理载具[{}]数据时发生异常:", vehicleNo, e);
}
List<TAppOrderIn> inTasks = vehicleIdToTaskMap.get(vehicleNo);
// 对比inTasks和goodsDetails
Iterator<ErpGoodsDetail> iterator = goodsDetails.iterator();
while (iterator.hasNext()) {
ErpGoodsDetail goodsDetail = iterator.next();
boolean matchFound = inTasks.stream().anyMatch(task ->
task.getGoodsId().equals(goodsDetail.getGoodsId()) &&
task.getBatch().equals(goodsDetail.getBatch()) &&
task.getGoodsType().equals(goodsDetail.getGoodsType()) &&
Objects.equals(task.getSpecification(), goodsDetail.getSpecification())
);
if (matchFound) {
// 找到匹配的任务删除该 goodsDetail
iterator.remove();
}
}
if (!goodsDetails.isEmpty()) {
orderInService.remove(new LambdaUpdateWrapper<TAppOrderIn>()
.eq(TAppOrderIn::getVehicleNo, vehicleNo));
wcsTaskService.remove(new LambdaUpdateWrapper<TAppWcsTask>()
.eq(TAppWcsTask::getVehicleId, vehicleNo));
} else {
log.error("MES校验入库单失败, 载具[{}]", vehicleNo);
}
}
}
}