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:
@@ -92,11 +92,11 @@ public interface WmsServiceFeign {
|
||||
|
||||
|
||||
/**
|
||||
* oms下发单保存
|
||||
* oms下发单保存(返回执行结果,失败时OMS据此回滚下发标记,避免"OMS已下发/WMS无数据"的阻断)
|
||||
*/
|
||||
@ApiOperation("oms下发单保存")
|
||||
@PostMapping(value = "/stockInOrderApi/omsInOrderAdd")
|
||||
public void omsInOrderAdd(@RequestBody StockInOrder stockInOrder);
|
||||
public AjaxResult omsInOrderAdd(@RequestBody StockInOrder stockInOrder);
|
||||
|
||||
@ApiOperation("oms取消下发单保存")
|
||||
@PostMapping(value = "/stockOutOrderApi/cancelExecutionOrder")
|
||||
@@ -119,11 +119,19 @@ public interface WmsServiceFeign {
|
||||
public AjaxResult checkOmsAssignInventory(@RequestBody List<OutMaterialDetail> outMaterialDetails);
|
||||
|
||||
/**
|
||||
* oms下发单明细保存
|
||||
* oms下发单明细保存(返回执行结果,明细保存含自动审核链路,失败时OMS据此回滚)
|
||||
*/
|
||||
@ApiOperation("oms下发单明细保存")
|
||||
@PostMapping(value = "/stockInOrderApi/omsInOrderAddDetail")
|
||||
public void omsInOrderAddDetail(@RequestBody List<InMaterialDetail> inMaterialDetails);
|
||||
public AjaxResult omsInOrderAddDetail(@RequestBody List<InMaterialDetail> inMaterialDetails);
|
||||
|
||||
/**
|
||||
* oms取消下发入库执行单:WMS侧一个事务内逻辑删除下发链路产生的全部数据
|
||||
* (入库单/明细、收货单/明细、收货任务、收货作业单/明细、质检单),已开始收货则报错拦截
|
||||
*/
|
||||
@ApiOperation("oms取消下发入库单清理")
|
||||
@PostMapping(value = "/stockInOrderApi/omsCancelInOrder")
|
||||
public AjaxResult omsCancelInOrder(@RequestBody StockInOrder stockInOrder);
|
||||
|
||||
@ApiOperation("oms查询物料列表")
|
||||
@GetMapping("/materialBaseInfoApi/queryList")
|
||||
|
||||
+13
-2
@@ -70,7 +70,10 @@ public class RemoteWmsFallbackFactory implements FallbackFactory<WmsServiceFeign
|
||||
}
|
||||
|
||||
@Override
|
||||
public void omsInOrderAdd(StockInOrder stockInOrder) {
|
||||
public AjaxResult omsInOrderAdd(StockInOrder stockInOrder) {
|
||||
//返回错误而非静默成功:下发主单保存失败必须让OMS感知并回滚下发标记,
|
||||
//否则OMS显示已下发、WMS无数据,下游收货流程无从进行(流程阻断)
|
||||
return AjaxResult.error("WMS入库单保存失败(服务降级):" + cause.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,7 +99,15 @@ public class RemoteWmsFallbackFactory implements FallbackFactory<WmsServiceFeign
|
||||
}
|
||||
|
||||
@Override
|
||||
public void omsInOrderAddDetail(List<InMaterialDetail> inMaterialDetails) {
|
||||
public AjaxResult omsInOrderAddDetail(List<InMaterialDetail> inMaterialDetails) {
|
||||
//返回错误而非静默成功:明细保存(含自动审核)失败必须让OMS感知并回滚下发标记
|
||||
return AjaxResult.error("WMS入库单明细保存失败(服务降级):" + cause.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AjaxResult omsCancelInOrder(StockInOrder stockInOrder) {
|
||||
//返回错误而非静默成功,让OMS侧取消下发能感知清理失败并整体回滚(取消下发可重试,WMS清理幂等)
|
||||
return AjaxResult.error("WMS取消下发清理失败:" + cause.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+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 有值表示已下发/执行过。
|
||||
|
||||
+8
@@ -947,6 +947,14 @@ public class StockInOrderApplicationService {
|
||||
stockInOrderDomainService.omsOrderAddDetail(inMaterialDetails);
|
||||
}
|
||||
|
||||
/**
|
||||
* OMS取消下发入库执行单:清理WMS侧下发链路产生的全部数据
|
||||
* (入库单/明细、收货单/明细、收货任务、收货作业单/明细、质检单),已开始收货则报错拦截
|
||||
*/
|
||||
public void omsCancelInOrder(StockInOrder stockInOrder){
|
||||
stockInOrderDomainService.cancelExecutionOrder(stockInOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 取消入库单
|
||||
* @author ZhouGY
|
||||
|
||||
+123
@@ -23,6 +23,8 @@ import com.mhd.system.api.domain.ElectronicSignatureSyncDTO;
|
||||
import com.mhd.system.api.domain.PackDetailFeignPO;
|
||||
import com.mhd.system.api.domain.WarehouseFeignPO;
|
||||
import com.mhd.system.api.model.LoginUser;
|
||||
import com.mhd.wms.domain.deliveTask.entity.DeliveTask;
|
||||
import com.mhd.wms.domain.deliveTask.repository.facade.IDeliveTaskService;
|
||||
import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail;
|
||||
import com.mhd.wms.domain.inMaterialDetail.repository.facade.IInMaterialDetailService;
|
||||
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO;
|
||||
@@ -49,6 +51,8 @@ import com.mhd.wms.domain.stockInOrder.repository.facade.IStockInOrderService;
|
||||
import com.mhd.wms.domain.stockInOrder.repository.mapper.StockInOrderMapper;
|
||||
import com.mhd.wms.domain.stockInOrder.repository.po.StockInOrderPO;
|
||||
import com.mhd.wms.domain.stockInOrder.repository.todo.StockInOrderDO;
|
||||
import com.mhd.wms.domain.stockInTaskOrder.entity.StockInTaskOrder;
|
||||
import com.mhd.wms.domain.stockInTaskOrder.repository.facade.IStockInTaskOrderService;
|
||||
import com.mhd.wms.domain.stockReceiptOrder.entity.StockReceiptOrder;
|
||||
import com.mhd.wms.domain.stockReceiptOrder.repository.facade.IStockReceiptOrderService;
|
||||
import com.mhd.wms.domain.stockReceiptOrder.repository.po.StockReceiptOrderPO;
|
||||
@@ -59,6 +63,8 @@ import com.mhd.wms.domain.stockShelfOrder.repository.facade.IStockShelfOrderServ
|
||||
import com.mhd.wms.domain.stockShelfOrder.repository.po.StockShelfOrderPO;
|
||||
import com.mhd.wms.domain.stockShelfOrder.repository.todo.StockShelfOrderDO;
|
||||
import com.mhd.wms.domain.stockShelfOrder.service.StockShelfOrderDomainService;
|
||||
import com.mhd.wms.domain.taskReceiptMaterialDetail.entity.TaskReceiptMaterialDetail;
|
||||
import com.mhd.wms.domain.taskReceiptMaterialDetail.repository.facade.ITaskReceiptMaterialDetailService;
|
||||
import com.mhd.wms.interfaces.dto.stockInOrder.StockInOrderDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -115,6 +121,12 @@ public class StockInOrderDomainService {
|
||||
@Autowired
|
||||
private IStockShelfOrderService stockShelfOrderService;
|
||||
@Autowired
|
||||
private IDeliveTaskService deliveTaskService;
|
||||
@Autowired
|
||||
private IStockInTaskOrderService stockInTaskOrderService;
|
||||
@Autowired
|
||||
private ITaskReceiptMaterialDetailService taskReceiptMaterialDetailService;
|
||||
@Autowired
|
||||
private IdGenerator idGenerator;
|
||||
|
||||
/**
|
||||
@@ -721,6 +733,117 @@ public class StockInOrderDomainService {
|
||||
autoAuditOmsInOrder(inMaterialDetails.get(0).getInOrderNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* OMS取消下发入库执行单:WMS侧补偿清理(与下发链路 omsOrderAdd→omsOrderAddDetail→自动审核→生成收货单/任务 对称)
|
||||
* <p>下发链路在WMS落库的表(按清理顺序):</p>
|
||||
* <ul>
|
||||
* <li>task_receipt_material_detail 收货作业单明细(按收货作业单号)</li>
|
||||
* <li>stock_in_task_order 收货作业单(按入库单号)</li>
|
||||
* <li>delive_task 收货任务(按收货单号 tracking_number)</li>
|
||||
* <li>quality_inspection 质检单(按入库单号)</li>
|
||||
* <li>receipt_material_detail 收货单明细(按收货单号)</li>
|
||||
* <li>stock_receipt_order 收货单(按入库单号)</li>
|
||||
* <li>in_material_detail 入库单明细(按入库单号)</li>
|
||||
* <li>stock_in_order 入库单(按入库单号)</li>
|
||||
* </ul>
|
||||
* <p>历史缺陷:OMS侧只跨库删除4张表,收货任务/收货作业单/质检单残留;且按单号取收货单号
|
||||
* 在重复下发产生多张同号收货单时会 TooManyResultsException,取消下发整体失败(流程阻断)。</p>
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void cancelExecutionOrder(StockInOrder stockInOrder) {
|
||||
String inOrderNumber = stockInOrder.getInOrderNumber();
|
||||
if (StringUtils.isEmpty(inOrderNumber)) {
|
||||
throw new ServiceException("取消下发失败:入库单号为空");
|
||||
}
|
||||
List<StockInOrder> stockInOrders = stockInOrderService.list(new LambdaQueryWrapper<StockInOrder>()
|
||||
.eq(StockInOrder::getInOrderNumber, inOrderNumber)
|
||||
.eq(StockInOrder::getDelFlag, 1));
|
||||
if (CollectionUtils.isEmpty(stockInOrders)) {
|
||||
//幂等:WMS无该单数据(从未下发成功或已清理过),直接成功,保证OMS取消下发可重试
|
||||
return;
|
||||
}
|
||||
//收货进度拦截:已开始收货(3)/上架中(4)/已入库(5)的数据不允许取消,否则会删掉真实收货与库存依据
|
||||
for (StockInOrder order : stockInOrders) {
|
||||
if (order.getStatus() != null && order.getStatus() >= 3) {
|
||||
throw new ServiceException("入库单[" + inOrderNumber + "]已在WMS开始收货/上架,无法取消下发");
|
||||
}
|
||||
}
|
||||
//收货单(含历史重复下发产生的多张同号收货单,全部查出统一清理,避免按单号取一条漏删/报错)
|
||||
List<StockReceiptOrder> receiptOrders = stockReceiptOrderService.list(new LambdaQueryWrapper<StockReceiptOrder>()
|
||||
.eq(StockReceiptOrder::getInOrderNumber, inOrderNumber)
|
||||
.eq(StockReceiptOrder::getDelFlag, 1));
|
||||
List<String> receiptOrderNumbers = receiptOrders.stream()
|
||||
.map(StockReceiptOrder::getReceiptOrderNumber)
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
for (StockReceiptOrder receiptOrder : receiptOrders) {
|
||||
if (receiptOrder.getStatus() != null && receiptOrder.getStatus() > 2) {
|
||||
throw new ServiceException("入库单[" + inOrderNumber + "]对应收货单已完成收货,无法取消下发");
|
||||
}
|
||||
}
|
||||
//收货作业单(type=1收货,入库单号关联),先记下任务号用于删作业单明细
|
||||
List<StockInTaskOrder> taskOrders = stockInTaskOrderService.list(new LambdaQueryWrapper<StockInTaskOrder>()
|
||||
.eq(StockInTaskOrder::getInOrderNumber, inOrderNumber)
|
||||
.eq(StockInTaskOrder::getDelFlag, 1));
|
||||
List<String> taskNumbers = taskOrders.stream()
|
||||
.map(StockInTaskOrder::getTaskNumber)
|
||||
.filter(StringUtils::isNotEmpty)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
//1.收货作业单明细
|
||||
if (!taskNumbers.isEmpty()) {
|
||||
taskReceiptMaterialDetailService.update(new UpdateWrapper<TaskReceiptMaterialDetail>().lambda()
|
||||
.set(TaskReceiptMaterialDetail::getDelFlag, 2)
|
||||
.in(TaskReceiptMaterialDetail::getTaskNumber, taskNumbers)
|
||||
.eq(TaskReceiptMaterialDetail::getDelFlag, 1));
|
||||
}
|
||||
//2.收货作业单
|
||||
if (!taskOrders.isEmpty()) {
|
||||
stockInTaskOrderService.update(new UpdateWrapper<StockInTaskOrder>().lambda()
|
||||
.set(StockInTaskOrder::getDelFlag, 2)
|
||||
.eq(StockInTaskOrder::getInOrderNumber, inOrderNumber)
|
||||
.eq(StockInTaskOrder::getDelFlag, 1));
|
||||
}
|
||||
//3.收货任务(tracking_number=收货单号;补"RV-"+入库单号兜底历史同号收货单)
|
||||
if (!receiptOrderNumbers.isEmpty()) {
|
||||
Set<String> trackingNumbers = new HashSet<>(receiptOrderNumbers);
|
||||
trackingNumbers.add("RV-" + inOrderNumber);
|
||||
deliveTaskService.update(new UpdateWrapper<DeliveTask>().lambda()
|
||||
.set(DeliveTask::getDelFlag, 2)
|
||||
.in(DeliveTask::getTrackingNumber, trackingNumbers)
|
||||
.eq(DeliveTask::getTaskType, 1)
|
||||
.eq(DeliveTask::getDelFlag, 1));
|
||||
}
|
||||
//4.质检单
|
||||
qualityInspectionService.update(new UpdateWrapper<com.mhd.wms.domain.qualityInspection.entity.QualityInspection>().lambda()
|
||||
.set(com.mhd.wms.domain.qualityInspection.entity.QualityInspection::getDelFlag, 2)
|
||||
.eq(com.mhd.wms.domain.qualityInspection.entity.QualityInspection::getInOrderNumber, inOrderNumber)
|
||||
.eq(com.mhd.wms.domain.qualityInspection.entity.QualityInspection::getDelFlag, 1));
|
||||
//5.收货单明细
|
||||
if (!receiptOrderNumbers.isEmpty()) {
|
||||
receiptMaterialDetailService.update(new UpdateWrapper<ReceiptMaterialDetail>().lambda()
|
||||
.set(ReceiptMaterialDetail::getDelFlag, 2)
|
||||
.in(ReceiptMaterialDetail::getReceiptOrderNumber, receiptOrderNumbers)
|
||||
.eq(ReceiptMaterialDetail::getDelFlag, 1));
|
||||
}
|
||||
//6.收货单
|
||||
stockReceiptOrderService.update(new UpdateWrapper<StockReceiptOrder>().lambda()
|
||||
.set(StockReceiptOrder::getDelFlag, 2)
|
||||
.eq(StockReceiptOrder::getInOrderNumber, inOrderNumber)
|
||||
.eq(StockReceiptOrder::getDelFlag, 1));
|
||||
//7.入库单明细
|
||||
materialDetailService.update(new UpdateWrapper<InMaterialDetail>().lambda()
|
||||
.set(InMaterialDetail::getDelFlag, 2)
|
||||
.eq(InMaterialDetail::getInOrderNumber, inOrderNumber)
|
||||
.eq(InMaterialDetail::getDelFlag, 1));
|
||||
//8.入库单
|
||||
stockInOrderService.update(new UpdateWrapper<StockInOrder>().lambda()
|
||||
.set(StockInOrder::getDelFlag, 2)
|
||||
.eq(StockInOrder::getInOrderNumber, inOrderNumber)
|
||||
.eq(StockInOrder::getDelFlag, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* OMS下发入库单明细保存后自动审核通过(生成收货单并更新审核状态)
|
||||
*/
|
||||
|
||||
+16
-2
@@ -199,8 +199,10 @@ public class StockInOrderApi extends BaseController {
|
||||
*/
|
||||
@ApiOperation("oms下发单保存")
|
||||
@PostMapping(value = "/omsInOrderAdd")
|
||||
public void omsInOrderAdd(@RequestBody StockInOrder stockInOrder) {
|
||||
public AjaxResult omsInOrderAdd(@RequestBody StockInOrder stockInOrder) {
|
||||
//返回执行结果而非void:OMS侧需感知保存失败(此前Feign降级被静默吞掉,OMS显示下发成功但WMS无数据,流程阻断)
|
||||
stockInOrderApplicationService.omsOrderAdd(stockInOrder);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -311,8 +313,20 @@ public class StockInOrderApi extends BaseController {
|
||||
*/
|
||||
@ApiOperation("oms下发单明细保存")
|
||||
@PostMapping(value = "/omsInOrderAddDetail")
|
||||
public void omsInOrderAddDetail(@RequestBody List<InMaterialDetail> inMaterialDetails) {
|
||||
public AjaxResult omsInOrderAddDetail(@RequestBody List<InMaterialDetail> inMaterialDetails) {
|
||||
//返回执行结果而非void:明细保存含自动审核链路,失败必须让OMS感知并回滚下发标记
|
||||
stockInOrderApplicationService.omsOrderAddDetail(inMaterialDetails);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
/**
|
||||
* oms取消下发入库执行单:清理WMS侧下发生成的入库单及下游收货链路数据(逻辑删除)
|
||||
*/
|
||||
@ApiOperation("oms取消下发入库单清理")
|
||||
@PostMapping(value = "/omsCancelInOrder")
|
||||
public AjaxResult omsCancelInOrder(@RequestBody StockInOrder stockInOrder) {
|
||||
stockInOrderApplicationService.omsCancelInOrder(stockInOrder);
|
||||
return AjaxResult.success();
|
||||
}
|
||||
|
||||
@ApiOperation("查询入库信息(通过入库单号)")
|
||||
|
||||
Reference in New Issue
Block a user