fix(oms,wms): 出库反审补全——重新下发自愈/仓库信息本地兜底/运输链路反审联动/归档查询修复

- 反审后 issueStatus 置 3-已驳回(与入库侧同口径), 清空执行单号/货源单号
- 反审/取消下发软删执行明细时置空 uniqueId, 修复重新下发撞唯一约束
- 新增 WarehouseInfoApplicationService(Feign优先+本地跨库兜底), 出库侧8处调用点接入
- 反审联动软删运输链路: 运输业务单/执行单本地软删 + TMS deleteChainByExecuteOrderNumber
- WMS归档查询修复: 交接归档详情丢行/拣货归档数量恒0/复核列表归档汇总/OMS执行单已反审tab
This commit is contained in:
rcx
2026-09-11 11:42:42 +08:00
parent a65cca1cfa
commit 788bae9a16
18 changed files with 151 additions and 39 deletions
@@ -0,0 +1,58 @@
package com.mhd.oms.application.service;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.oms.domain.reservationStockInOrder.repository.mapper.ReservationStockInOrderMapper;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.domain.WarehouseFeignPO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 仓库信息获取(带本地兜底): 下发/下单冻结/保存等流程原先直接 Feign 调 system 服务取仓库信息,
* system 服务未启动/降级/返回非200时整个流程被"获取仓库信息失败"阻断。
* 本组件统一收口: 优先 Feign, 失败时回退本地跨库直查 "NGWL_TEST_SYSTEM".WAREHOUSE(与 Feign 同库同表, OMS 库账号可读),
* 两侧都取不到才抛错并带出 Feign 真实返回原因。
*
* @date 2026/9/11
*/
@Slf4j
@Service
public class WarehouseInfoApplicationService {
@Autowired
private SystemServiceFeign systemServiceFeign;
@Autowired
private ReservationStockInOrderMapper reservationStockInOrderMapper;
/**
* 获取仓库信息: Feign 优先, 失败走本地兜底; 两边都取不到抛 ServiceException
*
* @param warehouseId 仓库id
* @return 仓库信息(含编码/名称/单号生成规则/库存锁定模式等)
*/
public WarehouseFeignPO getWarehouseInfo(Long warehouseId) {
if (warehouseId == null) {
throw new ServiceException("仓库ID不能为空");
}
AjaxResult ajaxResult = null;
try {
ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(warehouseId);
} catch (Exception e) {
log.warn("获取仓库信息Feign调用异常, 走本地兜底查询, warehouseId={}, error={}", warehouseId, e.getMessage());
}
if (ajaxResult != null && "200".equals(String.valueOf(ajaxResult.get("code"))) && ajaxResult.get("data") != null) {
return com.alibaba.fastjson.JSON.parseObject(
com.alibaba.fastjson2.JSONObject.toJSONString(ajaxResult.get("data")), WarehouseFeignPO.class);
}
String remoteMsg = ajaxResult == null ? "Feign调用异常" : String.valueOf(ajaxResult.get("msg"));
log.warn("获取仓库信息Feign失败(返回: {}), 走本地兜底查询, warehouseId={}", remoteMsg, warehouseId);
WarehouseFeignPO local = reservationStockInOrderMapper.getWarehouseInfoFallback(warehouseId);
if (local == null) {
throw new ServiceException("获取仓库信息失败(Feign返回:" + remoteMsg + "), 且本地未查到仓库[warehouseId="
+ warehouseId + "], 请检查仓库是否存在/已启用");
}
return local;
}
}
@@ -46,6 +46,9 @@ public class OutEntrustOrderApplicationService {
@Resource
private SystemServiceFeign systemServiceFeign;
@Resource
private com.mhd.oms.application.service.WarehouseInfoApplicationService warehouseInfoApplicationService;
@Resource
private WmsServiceFeign wmsServiceFeign;
@@ -352,14 +355,10 @@ public class OutEntrustOrderApplicationService {
}
/**
* 仓库信息校验并回填编码/名称
* 仓库信息校验并回填编码/名称 (Feign失败走本地跨库兜底)
*/
private void setWarehouseInfo(OutEntrustOrderDO outEntrustOrderDO) {
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(outEntrustOrderDO.getWarehouseId());
if (ajaxResult == null || !"200".equals(String.valueOf(ajaxResult.get("code")))) {
throw new ServiceException("获取仓库信息失败,请检查仓库是否有效");
}
WarehouseFeignPO warehouseFeignPO = JSONUtil.toBean(JSONUtil.toJsonStr(ajaxResult.get("data")), WarehouseFeignPO.class);
WarehouseFeignPO warehouseFeignPO = warehouseInfoApplicationService.getWarehouseInfo(outEntrustOrderDO.getWarehouseId());
if (warehouseFeignPO == null || Objects.isNull(warehouseFeignPO.getWarehouseId())) {
throw new ServiceException("仓库不存在,请重新选择");
}
@@ -29,6 +29,8 @@ public class ExecutionStockOutOrderPO extends BaseVOEntity {
@ApiModelProperty("出库单id")
private Long outOrderId;
@ApiModelProperty("反审标记: 1-已反审(反审软删归档, 【已反审】tab按 delFlag=2+reverseFlag=1 查询)")
private Integer reverseFlag;
@ApiModelProperty("总价")
@Excel(name = "总价")
private BigDecimal amount;
@@ -29,6 +29,9 @@ public class ExecutionStockOutOrderDO extends BaseVOEntity {
@ApiModelProperty("出库单id")
private Long outOrderId;
@ApiModelProperty("反审标记查询: 1-已反审(与delFlag=2成对传, 查【已反审】tab归档数据)")
private Integer reverseFlag;
@ApiModelProperty("组织表ID")
@Excel(name = "组织表ID")
private Long organizationId;
@@ -27,6 +27,9 @@ public class ExecutionStockOutOrderDTO extends ExecutionStockOutOrderBaseDTO {
@ApiModelProperty("出库单id")
private Long outOrderId;
@ApiModelProperty("反审标记查询: 1-已反审(与delFlag=2成对传, 查【已反审】tab归档数据)")
private Integer reverseFlag;
@ApiModelProperty("组织表ID")
@Excel(name = "组织表ID")
private Long organizationId;
@@ -66,6 +66,8 @@ import java.util.stream.Collectors;
public class ExecutionStockOutOrderApplicationService {
@Autowired
private ExecutionStockOutOrderDomainService stockOutOrderDomainService;
@Autowired
private com.mhd.oms.application.service.WarehouseInfoApplicationService warehouseInfoApplicationService;
// @Autowired
// private ExecutionOutMaterialDetailDomainService outMaterialDetailDomainService;
// @Autowired
@@ -862,11 +864,8 @@ public class ExecutionStockOutOrderApplicationService {
if (stockOutOrderDO.getWarehouseId() == null) {
throw new ServiceException("仓库ID不能为空");
}
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(stockOutOrderDO.getWarehouseId());
if(!"200".equals(String.valueOf(ajaxResult.get("code")))){
throw new ServiceException("获取仓库信息失败");
}
WarehouseFeignPO warehouseFeignPO = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), WarehouseFeignPO.class);
// Feign失败走本地跨库兜底, 避免保存被"获取仓库信息失败"阻断
WarehouseFeignPO warehouseFeignPO = warehouseInfoApplicationService.getWarehouseInfo(stockOutOrderDO.getWarehouseId());
stockOutOrderDO.setWarehouseCode(warehouseFeignPO.getWarehouseCode());
stockOutOrderDO.setWarehouseName(warehouseFeignPO.getWarehouseName());
}
@@ -71,6 +71,8 @@ public class ExecutionStockOutOrderDomainService {
@Autowired
private IExecutionStockOutOrderService stockOutOrderService;
@Autowired
private com.mhd.oms.application.service.WarehouseInfoApplicationService warehouseInfoApplicationService;
@Autowired
private IExecutionOutMaterialDetailService outMaterialDetailService;
@Autowired
private IReservationDeliveryDetailsLinkService deliveryDetailsLinkService;
@@ -148,14 +150,9 @@ public class ExecutionStockOutOrderDomainService {
public Boolean insert(ExecutionStockOutOrderDO stockOutOrderDO) {
//建单校验:明细数量必须大于0(0数量单下发WMS后自动分配必失败,出库单会卡死在已审核状态)
validateMaterialDetailQuantity(stockOutOrderDO.getMaterialDetailList());
//设置单号
//设置单号(仓库信息: Feign优先, system服务失败/降级时本地跨库兜底)
Long warehouseId = stockOutOrderDO.getWarehouseId();
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(warehouseId);
if (!"200".equals(String.valueOf(ajaxResult.get("code")))) {
throw new ServiceException("获取仓库信息失败");
}
//仓库信息
WarehouseFeignPO warehouseFeignPO = com.alibaba.fastjson.JSON.parseObject(com.alibaba.fastjson2.JSONObject.toJSONString(ajaxResult.get("data")), WarehouseFeignPO.class);
WarehouseFeignPO warehouseFeignPO = warehouseInfoApplicationService.getWarehouseInfo(warehouseId);
String orderNoGenerateRule = warehouseFeignPO.getOrderNoGenerateRule();
String prefix = warehouseFeignPO.getOutOrderNoPrefix();
if ("yang_pin_chu_ku".equals(stockOutOrderDO.getBusinessType())) {
@@ -218,14 +215,9 @@ public class ExecutionStockOutOrderDomainService {
@Transactional(rollbackFor = Exception.class)
public Boolean batchInsert(List<ExecutionStockOutOrderDO> stockOutOrderDOList) {
for (ExecutionStockOutOrderDO stockOutOrderDO : stockOutOrderDOList){
//设置单号
//设置单号(仓库信息: Feign优先, system服务失败/降级时本地跨库兜底)
Long warehouseId = stockOutOrderDO.getWarehouseId();
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(warehouseId);
if (!"200".equals(String.valueOf(ajaxResult.get("code")))) {
throw new ServiceException("获取仓库信息失败");
}
//仓库信息
WarehouseFeignPO warehouseFeignPO = com.alibaba.fastjson.JSON.parseObject(com.alibaba.fastjson2.JSONObject.toJSONString(ajaxResult.get("data")), WarehouseFeignPO.class);
WarehouseFeignPO warehouseFeignPO = warehouseInfoApplicationService.getWarehouseInfo(warehouseId);
String orderNoGenerateRule = warehouseFeignPO.getOrderNoGenerateRule();
String prefix = warehouseFeignPO.getOutOrderNoPrefix();
if ("yang_pin_chu_ku".equals(stockOutOrderDO.getBusinessType())) {
@@ -54,6 +54,12 @@ public interface ReservationStockInOrderMapper extends BaseMapper<ReservationSto
public String getWarehouseName(@Param("id") Long id);
/**
* 本地跨库直查仓库信息(编码/名称/单号规则/库存锁定模式),
* 供下发等流程在 system 服务 Feign 失败/降级时兜底, 与 getWarehouseInfoByWarehouseId Feign 接口同数据源
*/
public com.mhd.system.api.domain.WarehouseFeignPO getWarehouseInfoFallback(@Param("id") Long id);
List<ReservationStockInOrderPO> queryNoticePrint(ReservationStockInOrderDO stockInOrderDO);
List<ReservationInMaterialDetailPO> queryNoticePrintDetail(ReservationStockInOrderDO stockInOrderDO);
public void updateByTransportationNumber(@Param("transportationNumber") String transportationNumber);
@@ -85,6 +85,8 @@ import java.util.stream.Collectors;
public class ReservationStockOutOrderApplicationService {
@Autowired
private ReservationStockOutOrderDomainService stockOutOrderDomainService;
@Autowired
private com.mhd.oms.application.service.WarehouseInfoApplicationService warehouseInfoApplicationService;
// @Autowired
// private ReservationOutMaterialDetailDomainService outMaterialDetailDomainService;
// @Autowired
@@ -913,11 +915,8 @@ public class ReservationStockOutOrderApplicationService {
if (stockOutOrderDO.getWarehouseId() == null) {
throw new ServiceException("仓库ID不能为空");
}
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(stockOutOrderDO.getWarehouseId());
if(!"200".equals(String.valueOf(ajaxResult.get("code")))){
throw new ServiceException("获取仓库信息失败");
}
WarehouseFeignPO warehouseFeignPO = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), WarehouseFeignPO.class);
// Feign失败走本地跨库兜底, 避免新增/编辑保存被"获取仓库信息失败"阻断
WarehouseFeignPO warehouseFeignPO = warehouseInfoApplicationService.getWarehouseInfo(stockOutOrderDO.getWarehouseId());
stockOutOrderDO.setWarehouseCode(warehouseFeignPO.getWarehouseCode());
stockOutOrderDO.setWarehouseName(warehouseFeignPO.getWarehouseName());
}
@@ -68,6 +68,8 @@ import java.util.concurrent.ThreadLocalRandom;
public class ReserveStockOutOrderApplicationService {
@Autowired
private ReserveStockOutOrderDomainService stockOutOrderDomainService;
@Autowired
private com.mhd.oms.application.service.WarehouseInfoApplicationService warehouseInfoApplicationService;
// @Autowired
// private ReserveOutMaterialDetailDomainService outMaterialDetailDomainService;
// @Autowired
@@ -895,11 +897,8 @@ public class ReserveStockOutOrderApplicationService {
if (stockOutOrderDO.getWarehouseId() == null) {
throw new ServiceException("仓库ID不能为空");
}
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(stockOutOrderDO.getWarehouseId());
if(!"200".equals(String.valueOf(ajaxResult.get("code")))){
throw new ServiceException("获取仓库信息失败");
}
WarehouseFeignPO warehouseFeignPO = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), WarehouseFeignPO.class);
// Feign失败走本地跨库兜底, 避免保存被"获取仓库信息失败"阻断
WarehouseFeignPO warehouseFeignPO = warehouseInfoApplicationService.getWarehouseInfo(stockOutOrderDO.getWarehouseId());
stockOutOrderDO.setWarehouseCode(warehouseFeignPO.getWarehouseCode());
stockOutOrderDO.setWarehouseName(warehouseFeignPO.getWarehouseName());
}
@@ -52,6 +52,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateBy" column="update_by" />
<result property="updateByName" column="update_by_name" />
<result property="delFlag" column="del_flag" />
<result property="reverseFlag" column="reverse_flag" />
<result property="overStockId" column="over_stock_id" />
<result property="overStockStatus" column="over_stock_status" />
<result property="overStockType" column="over_stock_type" />
@@ -127,7 +128,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
a.cancel_time, a.close_order, a.close_remark, a.close_by, a.close_by_name, a.close_time, a.check_status,a.BUSINESS_ORDER_NO,
a.check_task_distribution, a.check_task_distribution_time, a.check_operators_by, a.check_operators_name, a.mobilize_code,
a.remark, a.create_time, a.create_by, a.create_by_name,a.business_number,a.train_no,a.amount,a.business_out_order_number,
a.update_time, a.update_by, a.update_by_name, a.del_flag, a.over_stock_id, a.over_stock_status, a.over_stock_type,a."TO",
a.update_time, a.update_by, a.update_by_name, a.del_flag, a.reverse_flag, a.over_stock_id, a.over_stock_status, a.over_stock_type,a."TO",
a.CONTACT_PERSON,a.VEHICLE_MODEL_PLATE,a.ENTRUST_NO,a.TEL,a.DRIVER_SIGN,a.FAX,a.DECLARE_CUSTOMS,a.MANUFACTURER,
a.CUSTOMS_DECLARER_INFO,a.DELIVERY_ADDR,a.ENTRY_EXIT_CUSTOMS,a.DEPARTURE_ARRIVAL_COUNTRY,a.CARRIER,a.CONTAINER_NO,a.CONTAINER_NO_NAME,a.OUTBOUND_DATE,
a.COMPLETE_TIME,a.ORDER_DATE,a.TRANSPORT_MODE_CODE,a.TRANSPORT_MODE_NAME,a.SUPERVISION_MODE_CODE,a.SUPERVISION_MODE_NAME,
@@ -401,6 +402,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<when test="delFlag != null"> and a.del_flag = #{delFlag} </when>
<otherwise> and a.del_flag = 1 </otherwise>
</choose>
<!-- 反审标记查询: OMS执行单【已反审】tab 前端传 delFlag=2 + reverseFlag=1 (与WMS四列表同口径, 两参数须成对传) -->
<if test="reverseFlag != null"> and a.reverse_flag = #{reverseFlag} </if>
</sql>
<select id="queryList" parameterType="com.mhd.oms.domain.executionStockOutOrder.repository.todo.ExecutionStockOutOrderDO" resultMap="StockOutOrderResult">
@@ -592,6 +592,18 @@
select WAREHOUSE_CODE from "NGWL_TEST_SYSTEM".WAREHOUSE where 1 = 1 and DEL_FLAG = 1 and WAREHOUSE_ID = #{id} limit 1
</select>
<!-- 本地跨库直查仓库信息: 下发/下单冻结等流程 Feign 获取仓库信息失败/降级时兜底(与 system 服务同库同表) -->
<select id="getWarehouseInfoFallback" parameterType="java.lang.Long" resultType="com.mhd.system.api.domain.WarehouseFeignPO">
select WAREHOUSE_CODE as warehouseCode,
WAREHOUSE_NAME as warehouseName,
ORDER_NO_GENERATE_RULE as orderNoGenerateRule,
OUT_ORDER_NO_PREFIX as outOrderNoPrefix,
SAMPLE_OUT_ORDER_NO_PREFIX as sampleOutOrderNoPrefix,
STOCK_LOCK_MODE as stockLockMode
from "NGWL_TEST_SYSTEM".WAREHOUSE
where 1 = 1 and DEL_FLAG = 1 and WAREHOUSE_ID = #{id} limit 1
</select>
<!-- 入仓通知单打印-表头查询 -->
<select id="queryNoticePrint" resultMap="StockInOrderResult">