fix(oms,wms): 入库执行单取消下发完整回退WMS数据,修复重复下发数据致取消阻断
一、取消下发回退不完整/阻断:原OMS跨库仅软删4张表,收货任务/收货作业单/质检单/电子签名残留;且getWShOrder在重复下发产生多张同号收货单时抛TooManyResultsException,取消下发整体回滚失败。WMS新增/stockInOrderApi/omsCancelInOrder:单事务软删下发链路全部8张表(入库单/明细、收货单/明细、收货任务、收货作业单/明细、质检单),幂等可重试,已开始收货报错拦截;OMS执行单取消下发改调该接口并清理待签名电子签名;预约单取消下发补齐WMS清理 二、下发失败被静默吞掉:omsInOrderAdd/omsInOrderAddDetail原返回void、Feign降级静默,OMS已下发但WMS无数据。改返回AjaxResult、fallback报错,执行单/预约单下发逐一校验返回值,失败回滚下发标记(WMS侧幂等,重下发安全) 三、下发防重原子化:issueOrder下发标记改条件更新(issue_time IS NULL)+影响行数校验,关闭并发/双击重复推送WMS的窗口
This commit is contained in:
+68
-12
@@ -19,6 +19,9 @@ import com.mhd.oms.domain.executionInMaterialDetail.repository.po.ExecutionInMat
|
||||
import com.mhd.oms.domain.executionInMaterialDetail.repository.todo.ExecutionInMaterialDetailBaseDO;
|
||||
import com.mhd.oms.domain.executionInMaterialDetail.repository.todo.ExecutionInMaterialDetailDO;
|
||||
import com.mhd.oms.domain.executionInMaterialDetail.repository.todo.InventoryAdjustmentRecordPO;
|
||||
import com.mhd.oms.domain.electronicSignature.entity.ElectronicSignature;
|
||||
import com.mhd.oms.domain.electronicSignature.repository.facade.IElectronicSignatureMaterialDetailService;
|
||||
import com.mhd.oms.domain.electronicSignature.repository.facade.IElectronicSignatureService;
|
||||
import com.mhd.oms.domain.executionStockInOrder.entity.ExecutionStockInOrder;
|
||||
import com.mhd.oms.domain.executionStockInOrder.repository.facade.IExecutionStockInOrderService;
|
||||
import com.mhd.oms.domain.executionStockInOrder.repository.mapper.ExecutionStockInOrderMapper;
|
||||
@@ -94,6 +97,10 @@ public class ExecutionStockInOrderDomainService {
|
||||
private ReservationStockInOrderMapper stockInOrderMapper;
|
||||
@Autowired
|
||||
private ReserveStockInOrderMapper reserveStockInOrderMapper;
|
||||
@Autowired
|
||||
private IElectronicSignatureService electronicSignatureService;
|
||||
@Autowired
|
||||
private IElectronicSignatureMaterialDetailService electronicSignatureMaterialDetailService;
|
||||
/**
|
||||
* 分页查询入库单列表
|
||||
*/
|
||||
@@ -523,25 +530,34 @@ public class ExecutionStockInOrderDomainService {
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean cancelAuditState(ExecutionStockInOrderDO stockInOrderDO) {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
Integer issueStatus = stockInOrderDO.getIssueStatus();
|
||||
// 获取用户姓名(优先从UserPo获取,如果为空则使用realname,最后使用username作为兜底)
|
||||
String userRealName = loginUser.getUserPo() != null && loginUser.getUserPo().getUserName() != null
|
||||
? loginUser.getUserPo().getUserName()
|
||||
: (loginUser.getRealname() != null ? loginUser.getRealname() : loginUser.getUsername());
|
||||
|
||||
//逻辑删除w入库单信息
|
||||
//回退下发在WMS产生的数据:调用WMS清理接口,与下发链路(omsInOrderAdd→omsInOrderAddDetail→自动审核
|
||||
//生成收货单/收货任务/收货作业单/质检单/电子签名)对称,WMS侧一个事务内逻辑删除全部数据。
|
||||
//此前OMS直接跨库UPDATE仅清理入库单/明细/收货单/收货明细4张表,收货任务、收货作业单、质检单、
|
||||
//电子签名记录残留;且按入库单号取收货单号(getWShOrder返回String)在重复下发产生多张同号收货单时
|
||||
//抛TooManyResultsException,取消下发整体回滚失败——正是"下发产生2条数据后取消下发阻断"的直接原因。
|
||||
//清理失败时抛错整体回滚(OMS保持已下发状态),WMS清理幂等,取消下发可安全重试
|
||||
List<Long> inOrderIds = stockInOrderDO.getInOrderIds();
|
||||
if (inOrderIds != null && !inOrderIds.isEmpty()) {
|
||||
for (Long inOrderId : inOrderIds) {
|
||||
ExecutionStockInOrder executionStockInOrder = reservationStockInOrderMapper.selectById(inOrderId);
|
||||
if (executionStockInOrder != null) {
|
||||
String inOrderNumber = executionStockInOrder.getInOrderNumber();
|
||||
reservationStockInOrderMapper.delWOrder(inOrderNumber);
|
||||
reservationStockInOrderMapper.delWOrderDetail(inOrderNumber);
|
||||
String wShOrder = reservationStockInOrderMapper.getWShOrder(inOrderNumber);
|
||||
reservationStockInOrderMapper.delWShOrder(inOrderNumber);
|
||||
reservationStockInOrderMapper.delWShOrderDetail(wShOrder);
|
||||
if (executionStockInOrder == null) {
|
||||
continue;
|
||||
}
|
||||
String inOrderNumber = executionStockInOrder.getInOrderNumber();
|
||||
StockInOrder cancelParam = new StockInOrder();
|
||||
cancelParam.setInOrderNumber(inOrderNumber);
|
||||
AjaxResult cancelResult = wmsServiceFeign.omsCancelInOrder(cancelParam);
|
||||
if (cancelResult == null || !"200".equals(String.valueOf(cancelResult.get("code")))) {
|
||||
throw new ServiceException("取消下发失败:入库单[" + inOrderNumber + "]WMS数据清理失败:"
|
||||
+ (cancelResult == null ? "WMS服务不可用或已降级" : cancelResult.get("msg")));
|
||||
}
|
||||
//清理下发自动审核时生成的待签名电子签名记录(已签名记录保留作凭证,不阻断主流程)
|
||||
cancelPendingSignature(inOrderNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -556,6 +572,29 @@ public class ExecutionStockInOrderDomainService {
|
||||
.in(ExecutionStockInOrder::getInOrderId, stockInOrderDO.getInOrderIds()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消下发时清理下发自动审核生成的待签名电子签名记录(signatureStatus=1)及其明细
|
||||
*/
|
||||
private void cancelPendingSignature(String inOrderNumber) {
|
||||
try {
|
||||
List<ElectronicSignature> signatures = electronicSignatureService.list(
|
||||
new LambdaQueryWrapper<ElectronicSignature>()
|
||||
.eq(ElectronicSignature::getOrderNumber, inOrderNumber)
|
||||
.eq(ElectronicSignature::getOrderType, "IN")
|
||||
.eq(ElectronicSignature::getSignatureStatus, 1)
|
||||
.eq(ElectronicSignature::getDelFlag, 1));
|
||||
for (ElectronicSignature signature : signatures) {
|
||||
electronicSignatureMaterialDetailService.deleteBySignatureId(signature.getSignatureId());
|
||||
electronicSignatureService.update(new UpdateWrapper<ElectronicSignature>().lambda()
|
||||
.set(ElectronicSignature::getDelFlag, 2)
|
||||
.eq(ElectronicSignature::getSignatureId, signature.getSignatureId()));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//WMS数据已清理成功,签名属附属记录,清理失败仅记日志,不回滚取消下发主流程
|
||||
log.error("取消下发清理电子签名记录失败,入库单号:{}", inOrderNumber, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 审核入库单
|
||||
* @author ZhouGY
|
||||
@@ -589,6 +628,9 @@ public class ExecutionStockInOrderDomainService {
|
||||
String userRealName = loginUser.getUserPo() != null && loginUser.getUserPo().getUserName() != null
|
||||
? loginUser.getUserPo().getUserName()
|
||||
: (loginUser.getRealname() != null ? loginUser.getRealname() : loginUser.getUsername());
|
||||
//下发标记改为条件更新(issue_time IS NULL):前置list校验与update之间存在并发窗口,
|
||||
//双击/并发请求会同时通过校验各自推一遍WMS(WMS侧同号入库单/明细翻倍的根源之一);
|
||||
//加上条件后,后到的事务影响行数为0,在此拦截,保证同一执行单只会推送WMS一次
|
||||
boolean update = stockInOrderService.update(null, new UpdateWrapper<ExecutionStockInOrder>().lambda()
|
||||
.set(ExecutionStockInOrder::getIssueId, loginUser.getUserid())
|
||||
.set(ExecutionStockInOrder::getIssueName, userRealName)
|
||||
@@ -597,7 +639,11 @@ public class ExecutionStockInOrderDomainService {
|
||||
.set(ExecutionStockInOrder::getUpdateBy, loginUser.getUserid())
|
||||
.set(ExecutionStockInOrder::getUpdateByName, userRealName)
|
||||
.set(ExecutionStockInOrder::getUpdateTime, new Date())
|
||||
.in(ExecutionStockInOrder::getInOrderId, distinctInOrderIds));
|
||||
.in(ExecutionStockInOrder::getInOrderId, distinctInOrderIds)
|
||||
.isNull(ExecutionStockInOrder::getIssueTime));
|
||||
if (!update) {
|
||||
throw new ServiceException("下发失败:单据已被并发下发,请刷新后查看");
|
||||
}
|
||||
|
||||
//todo下发推送到wms
|
||||
for (Long inOrderId : distinctInOrderIds) {
|
||||
@@ -612,7 +658,13 @@ public class ExecutionStockInOrderDomainService {
|
||||
stockInOrder.setOrganizationId(orgId);
|
||||
stockInOrder.setOrganizationName(orgName);
|
||||
stockInOrder.setTopOrganizationId(topOrgId);
|
||||
wmsServiceFeign.omsInOrderAdd(stockInOrder);
|
||||
//WMS保存结果必须校验:此前接口返回void、Feign降级被静默吞掉,OMS标记已下发但WMS无数据/缺明细,
|
||||
//收货流程无从进行(流程阻断);失败抛错回滚下发标记,WMS侧幂等(主单/明细判重),重下发安全
|
||||
AjaxResult addResult = wmsServiceFeign.omsInOrderAdd(stockInOrder);
|
||||
if (addResult == null || !"200".equals(String.valueOf(addResult.get("code")))) {
|
||||
throw new ServiceException("下发失败:入库单[" + stockInOrder.getInOrderNumber() + "]推送WMS保存主单失败:"
|
||||
+ (addResult == null ? "WMS服务不可用或已降级" : addResult.get("msg")));
|
||||
}
|
||||
String inOrderNumber = stockInOrder.getInOrderNumber();
|
||||
// 只推有效明细(del_flag=1),软删旧行不推WMS,防止WMS侧计划数量虚高
|
||||
List<ExecutionInMaterialDetail> materialDetailList = materialDetailService.list(new QueryWrapper<ExecutionInMaterialDetail>().lambda()
|
||||
@@ -633,7 +685,11 @@ public class ExecutionStockInOrderDomainService {
|
||||
}
|
||||
inMaterialDetailList.add(inMaterialDetail);
|
||||
}
|
||||
wmsServiceFeign.omsInOrderAddDetail(inMaterialDetailList);
|
||||
AjaxResult detailResult = wmsServiceFeign.omsInOrderAddDetail(inMaterialDetailList);
|
||||
if (detailResult == null || !"200".equals(String.valueOf(detailResult.get("code")))) {
|
||||
throw new ServiceException("下发失败:入库单[" + inOrderNumber + "]推送WMS保存明细失败:"
|
||||
+ (detailResult == null ? "WMS服务不可用或已降级" : detailResult.get("msg")));
|
||||
}
|
||||
}
|
||||
return update;
|
||||
}
|
||||
|
||||
+32
-2
@@ -568,7 +568,13 @@ public class ReservationStockInOrderDomainService {
|
||||
stockInOrder.setOmsStockInOrderId(String.valueOf(byId.getInOrderId()));
|
||||
|
||||
try {
|
||||
wmsServiceFeign.omsInOrderAdd(stockInOrder); // 推主单
|
||||
//WMS保存结果必须校验:此前接口返回void、Feign降级被静默吞掉,OMS标记已下发但WMS无数据/缺明细,
|
||||
//收货流程无从进行(流程阻断);失败抛错回滚下发标记,WMS侧幂等(主单/明细判重),重下发安全
|
||||
AjaxResult addResult = wmsServiceFeign.omsInOrderAdd(stockInOrder); // 推主单
|
||||
if (addResult == null || !"200".equals(String.valueOf(addResult.get("code")))) {
|
||||
throw new ServiceException("下发到WMS失败:入库单[" + stockInOrder.getInOrderNumber() + "]保存主单失败:"
|
||||
+ (addResult == null ? "WMS服务不可用或已降级" : addResult.get("msg")));
|
||||
}
|
||||
|
||||
String inOrderNumber = stockInOrder.getInOrderNumber();
|
||||
List<ReservationInMaterialDetail> materialDetailList = materialDetailService.list(
|
||||
@@ -587,7 +593,11 @@ public class ReservationStockInOrderDomainService {
|
||||
}
|
||||
inMaterialDetailList.add(inMaterialDetail);
|
||||
}
|
||||
wmsServiceFeign.omsInOrderAddDetail(inMaterialDetailList); // 推明细(会触发WMS自动审核)
|
||||
AjaxResult detailResult = wmsServiceFeign.omsInOrderAddDetail(inMaterialDetailList); // 推明细(会触发WMS自动审核)
|
||||
if (detailResult == null || !"200".equals(String.valueOf(detailResult.get("code")))) {
|
||||
throw new ServiceException("下发到WMS失败:入库单[" + inOrderNumber + "]保存明细失败:"
|
||||
+ (detailResult == null ? "WMS服务不可用或已降级" : detailResult.get("msg")));
|
||||
}
|
||||
log.info("下发到WMS成功,单据号:{}", byId.getInOrderNumber());
|
||||
} catch (Exception e) {
|
||||
log.error("下发到WMS失败,单据号:{}", byId.getInOrderNumber(), e);
|
||||
@@ -741,11 +751,17 @@ public class ReservationStockInOrderDomainService {
|
||||
for (Long inOrderId : inOrderIds) {
|
||||
ReservationStockInOrder byId = stockInOrderService.getById(inOrderId);
|
||||
String inOrderNumber = byId.getInOrderNumber();
|
||||
//清理预约单自身下发到WMS的数据(下发时omsInOrderAdd推过主单/明细并自动审核生成收货链路)
|
||||
cancelWmsInOrder(inOrderNumber);
|
||||
List<ExecutionStockInOrder> list = executionStockInOrderService.list(new QueryWrapper<ExecutionStockInOrder>().lambda()
|
||||
.eq(ExecutionStockInOrder::getBusinessInOrderNumber, inOrderNumber)
|
||||
.eq(ExecutionStockInOrder::getDelFlag, 1));
|
||||
for (ExecutionStockInOrder executionStockInOrder : list) {
|
||||
String inOrderNumber1 = executionStockInOrder.getInOrderNumber();
|
||||
//已下发的执行单同步清理WMS侧数据(与执行单取消下发同一清理接口,未下发则WMS无数据幂等跳过)
|
||||
if (executionStockInOrder.getIssueTime() != null) {
|
||||
cancelWmsInOrder(inOrderNumber1);
|
||||
}
|
||||
List<ExecutionInMaterialDetail> materialDetails = executionInMaterialDetailService.list(new QueryWrapper<ExecutionInMaterialDetail>().lambda()
|
||||
.eq(ExecutionInMaterialDetail::getInOrderNumber, inOrderNumber1)
|
||||
.eq(ExecutionInMaterialDetail::getDelFlag, 1));
|
||||
@@ -763,6 +779,20 @@ public class ReservationStockInOrderDomainService {
|
||||
return update;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用WMS清理接口回退下发产生的数据(入库单/明细、收货单/明细、收货任务、收货作业单/明细、质检单),
|
||||
* WMS侧已开始收货会返回错误在此抛出,保证不会误删真实收货数据
|
||||
*/
|
||||
private void cancelWmsInOrder(String inOrderNumber) {
|
||||
StockInOrder cancelParam = new StockInOrder();
|
||||
cancelParam.setInOrderNumber(inOrderNumber);
|
||||
AjaxResult cancelResult = wmsServiceFeign.omsCancelInOrder(cancelParam);
|
||||
if (cancelResult == null || !"200".equals(String.valueOf(cancelResult.get("code")))) {
|
||||
throw new ServiceException("取消下发失败:入库单[" + inOrderNumber + "]WMS数据清理失败:"
|
||||
+ (cancelResult == null ? "WMS服务不可用或已降级" : cancelResult.get("msg")));
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean executeAndIssue(ReservationStockInOrderDO stockInOrderDO) {
|
||||
// 防重复执行校验(与 issueOrder 的防重逻辑对齐):issueTime 有值表示已下发/执行过。
|
||||
|
||||
Reference in New Issue
Block a user