fix(oms,wms): 出库单下发WMS失败被静默吞掉,修复WMS出库拣货不显示OMS单据

- OMS建单/下发前校验明细数量>0且已关联库存
- OMS检查WMS自动分配/生成拣货单返回值,失败即报错回滚
- WMS自动分配各类失败场景抛带单号的明确异常,替代NPE
- WMS接单幂等保护,失败重试不产生重复数据
This commit is contained in:
rcx
2026-09-02 14:32:13 +08:00
parent 72cb1d8c07
commit 434348f972
3 changed files with 107 additions and 6 deletions
@@ -146,6 +146,8 @@ public class ExecutionStockOutOrderDomainService {
*/
@Transactional(rollbackFor = Exception.class)
public Boolean insert(ExecutionStockOutOrderDO stockOutOrderDO) {
//建单校验:明细数量必须大于0(0数量单下发WMS后自动分配必失败,出库单会卡死在已审核状态)
validateMaterialDetailQuantity(stockOutOrderDO.getMaterialDetailList());
//设置单号
Long warehouseId = stockOutOrderDO.getWarehouseId();
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(warehouseId);
@@ -252,6 +254,8 @@ public class ExecutionStockOutOrderDomainService {
stockOutOrderDO.setBusinessOrderNo(prefix + seq);
}
//设置物料信息
//建单校验:明细数量必须大于0(0数量单下发WMS后自动分配必失败,出库单会卡死在已审核状态)
validateMaterialDetailQuantity(stockOutOrderDO.getMaterialDetailList());
setMaterialDetailInfo(stockOutOrderDO);
//统计种类
stockOutOrderDO.setMaterialQuantity(stockOutOrderDO.getMaterialDetailList().size());
@@ -493,10 +497,20 @@ public class ExecutionStockOutOrderDomainService {
.set(ExecutionStockOutOrder::getUpdateTime, new Date())
.in(ExecutionStockOutOrder::getOutOrderId, stockOutOrderDO.getOutOrderIds()));
//todo下发推送到wms
//下发前统一校验所有单据:全部通过后再推送WMS,避免部分单据推送成功、部分失败造成两边数据不一致
List<Long> inOrderIds = stockOutOrderDO.getOutOrderIds();
List<ExecutionStockOutOrder> issueOrderList = new ArrayList<>();
for (Long inOrderId : inOrderIds) {
ExecutionStockOutOrder byId = stockOutOrderService.getById(inOrderId);
if (byId == null) {
throw new ServiceException("出库单不存在,outOrderId=" + inOrderId);
}
validateIssueOrderDetail(byId);
issueOrderList.add(byId);
}
//下发推送到wms
for (ExecutionStockOutOrder byId : issueOrderList) {
StockOutOrder stockOutOrder = new StockOutOrder();
BeanUtils.copyProperties(byId, stockOutOrder,"outOrderId");
Long warehouseId = stockOutOrder.getWarehouseId();
@@ -535,13 +549,64 @@ public class ExecutionStockOutOrderDomainService {
String outOrderNumber = byId.getOutOrderNumber();
com.mhd.system.api.domain.StockOutOrderDTO stockOutOrderDTO = new com.mhd.system.api.domain.StockOutOrderDTO();
stockOutOrderDTO.setOutOrderNumber(outOrderNumber);
wmsServiceFeign.execution(stockOutOrderDTO);
//WMS自动分配:校验返回值。此前不校验时,WMS侧分配失败被Feign降级吞掉,OMS显示成功但出库单卡死在WMS"已审核"状态,拣货单永远不生成
AjaxResult executionResult = wmsServiceFeign.execution(stockOutOrderDTO);
if (executionResult == null || !"200".equals(String.valueOf(executionResult.get("code")))) {
throw new ServiceException("出库单[" + outOrderNumber + "]WMS自动分配失败:"
+ (executionResult == null ? "WMS服务不可用或已降级" : executionResult.get("msg")));
}
wmsServiceFeign.genPickingOrderByOms(stockOutOrderDTO);
//WMS生成拣货单:同样校验返回值,失败即中断并回滚,让用户能感知到错误
AjaxResult genPickingResult = wmsServiceFeign.genPickingOrderByOms(stockOutOrderDTO);
if (genPickingResult == null || !"200".equals(String.valueOf(genPickingResult.get("code")))) {
throw new ServiceException("出库单[" + outOrderNumber + "]WMS生成拣货单失败:"
+ (genPickingResult == null ? "WMS服务不可用或已降级" : genPickingResult.get("msg")));
}
}
return update;
}
/**
* 建单校验:出库明细数量必须大于0
* 历史缺陷:0数量明细的单下发到WMS后自动分配必然失败,且异常被吞,出库单卡死在"已审核"状态无法生成拣货单
*/
private void validateMaterialDetailQuantity(List<ExecutionOutMaterialDetailDO> materialDetailList) {
if (CollectionUtils.isEmpty(materialDetailList)) {
throw new ServiceException("出库单明细不能为空");
}
for (ExecutionOutMaterialDetailDO detail : materialDetailList) {
if (detail.getQuantity() == null || detail.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
throw new ServiceException("出库明细数量必须大于0,物料:"
+ (detail.getMaterialCode() != null ? detail.getMaterialCode() : detail.getMaterialName()));
}
}
}
/**
* 下发前校验出库单明细:
* 1.必须有物料明细,且数量大于0;
* 2.明细必须已关联库存(materialInventoryId),否则WMS按库存ID自动分配会空指针;
* 校验放在推送WMS之前,失败直接报错回滚,避免出库单卡死在WMS"已审核"状态
*/
private void validateIssueOrderDetail(ExecutionStockOutOrder order) {
String outOrderNumber = order.getOutOrderNumber();
List<ExecutionOutMaterialDetail> detailList = outMaterialDetailService.list(new QueryWrapper<ExecutionOutMaterialDetail>().lambda()
.eq(ExecutionOutMaterialDetail::getOutOrderNumber, outOrderNumber));
if (CollectionUtils.isEmpty(detailList)) {
throw new ServiceException("出库单[" + outOrderNumber + "]没有物料明细,无法下发");
}
for (ExecutionOutMaterialDetail detail : detailList) {
String materialDesc = detail.getMaterialCode() != null ? detail.getMaterialCode()
: (detail.getMaterialName() != null ? detail.getMaterialName() : String.valueOf(detail.getMaterialDetailId()));
if (detail.getQuantity() == null || detail.getQuantity().compareTo(BigDecimal.ZERO) <= 0) {
throw new ServiceException("出库单[" + outOrderNumber + "]物料[" + materialDesc + "]数量为0,无法下发");
}
if (detail.getMaterialInventoryId() == null || detail.getMaterialInventoryId() <= 0) {
throw new ServiceException("出库单[" + outOrderNumber + "]物料[" + materialDesc + "]未关联库存,无法下发");
}
}
}
/**
* @description 修改出库单
* @author ZhouGY