diff --git a/mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/WmsServiceFeign.java b/mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/WmsServiceFeign.java index 22be78474..b25ecbef5 100644 --- a/mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/WmsServiceFeign.java +++ b/mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/WmsServiceFeign.java @@ -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 outMaterialDetails); /** - * oms下发单明细保存 + * oms下发单明细保存(返回执行结果,明细保存含自动审核链路,失败时OMS据此回滚) */ @ApiOperation("oms下发单明细保存") @PostMapping(value = "/stockInOrderApi/omsInOrderAddDetail") - public void omsInOrderAddDetail(@RequestBody List inMaterialDetails); + public AjaxResult omsInOrderAddDetail(@RequestBody List inMaterialDetails); + + /** + * oms取消下发入库执行单:WMS侧一个事务内逻辑删除下发链路产生的全部数据 + * (入库单/明细、收货单/明细、收货任务、收货作业单/明细、质检单),已开始收货则报错拦截 + */ + @ApiOperation("oms取消下发入库单清理") + @PostMapping(value = "/stockInOrderApi/omsCancelInOrder") + public AjaxResult omsCancelInOrder(@RequestBody StockInOrder stockInOrder); @ApiOperation("oms查询物料列表") @GetMapping("/materialBaseInfoApi/queryList") diff --git a/mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/factory/RemoteWmsFallbackFactory.java b/mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/factory/RemoteWmsFallbackFactory.java index aabf37512..daddb00ab 100644 --- a/mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/factory/RemoteWmsFallbackFactory.java +++ b/mhd-api/mhd-api-system/src/main/java/com/mhd/system/api/factory/RemoteWmsFallbackFactory.java @@ -70,7 +70,10 @@ public class RemoteWmsFallbackFactory implements FallbackFactory inMaterialDetails) { + public AjaxResult omsInOrderAddDetail(List inMaterialDetails) { + //返回错误而非静默成功:明细保存(含自动审核)失败必须让OMS感知并回滚下发标记 + return AjaxResult.error("WMS入库单明细保存失败(服务降级):" + cause.getMessage()); + } + + @Override + public AjaxResult omsCancelInOrder(StockInOrder stockInOrder) { + //返回错误而非静默成功,让OMS侧取消下发能感知清理失败并整体回滚(取消下发可重试,WMS清理幂等) + return AjaxResult.error("WMS取消下发清理失败:" + cause.getMessage()); } @Override diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/executionStockInOrder/service/ExecutionStockInOrderDomainService.java b/mhd_oms/src/main/java/com/mhd/oms/domain/executionStockInOrder/service/ExecutionStockInOrderDomainService.java index 0a18e0d0f..2264a05da 100644 --- a/mhd_oms/src/main/java/com/mhd/oms/domain/executionStockInOrder/service/ExecutionStockInOrderDomainService.java +++ b/mhd_oms/src/main/java/com/mhd/oms/domain/executionStockInOrder/service/ExecutionStockInOrderDomainService.java @@ -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 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 signatures = electronicSignatureService.list( + new LambdaQueryWrapper() + .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().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().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 materialDetailList = materialDetailService.list(new QueryWrapper().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; } diff --git a/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockInOrder/service/ReservationStockInOrderDomainService.java b/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockInOrder/service/ReservationStockInOrderDomainService.java index bd8852799..f3c7c3bf3 100644 --- a/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockInOrder/service/ReservationStockInOrderDomainService.java +++ b/mhd_oms/src/main/java/com/mhd/oms/domain/reservationStockInOrder/service/ReservationStockInOrderDomainService.java @@ -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 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 list = executionStockInOrderService.list(new QueryWrapper().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 materialDetails = executionInMaterialDetailService.list(new QueryWrapper().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 有值表示已下发/执行过。 diff --git a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java index 898f94e6d..03d02de33 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/application/service/stockInOrder/StockInOrderApplicationService.java @@ -947,6 +947,14 @@ public class StockInOrderApplicationService { stockInOrderDomainService.omsOrderAddDetail(inMaterialDetails); } + /** + * OMS取消下发入库执行单:清理WMS侧下发链路产生的全部数据 + * (入库单/明细、收货单/明细、收货任务、收货作业单/明细、质检单),已开始收货则报错拦截 + */ + public void omsCancelInOrder(StockInOrder stockInOrder){ + stockInOrderDomainService.cancelExecutionOrder(stockInOrder); + } + /** * @description 取消入库单 * @author ZhouGY diff --git a/mhd_wms/src/main/java/com/mhd/wms/domain/stockInOrder/service/StockInOrderDomainService.java b/mhd_wms/src/main/java/com/mhd/wms/domain/stockInOrder/service/StockInOrderDomainService.java index d18095675..f73870e64 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/domain/stockInOrder/service/StockInOrderDomainService.java +++ b/mhd_wms/src/main/java/com/mhd/wms/domain/stockInOrder/service/StockInOrderDomainService.java @@ -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→自动审核→生成收货单/任务 对称) + *

下发链路在WMS落库的表(按清理顺序):

+ *
    + *
  • task_receipt_material_detail 收货作业单明细(按收货作业单号)
  • + *
  • stock_in_task_order 收货作业单(按入库单号)
  • + *
  • delive_task 收货任务(按收货单号 tracking_number)
  • + *
  • quality_inspection 质检单(按入库单号)
  • + *
  • receipt_material_detail 收货单明细(按收货单号)
  • + *
  • stock_receipt_order 收货单(按入库单号)
  • + *
  • in_material_detail 入库单明细(按入库单号)
  • + *
  • stock_in_order 入库单(按入库单号)
  • + *
+ *

历史缺陷:OMS侧只跨库删除4张表,收货任务/收货作业单/质检单残留;且按单号取收货单号 + * 在重复下发产生多张同号收货单时会 TooManyResultsException,取消下发整体失败(流程阻断)。

+ */ + @Transactional(rollbackFor = Exception.class) + public void cancelExecutionOrder(StockInOrder stockInOrder) { + String inOrderNumber = stockInOrder.getInOrderNumber(); + if (StringUtils.isEmpty(inOrderNumber)) { + throw new ServiceException("取消下发失败:入库单号为空"); + } + List stockInOrders = stockInOrderService.list(new LambdaQueryWrapper() + .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 receiptOrders = stockReceiptOrderService.list(new LambdaQueryWrapper() + .eq(StockReceiptOrder::getInOrderNumber, inOrderNumber) + .eq(StockReceiptOrder::getDelFlag, 1)); + List 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 taskOrders = stockInTaskOrderService.list(new LambdaQueryWrapper() + .eq(StockInTaskOrder::getInOrderNumber, inOrderNumber) + .eq(StockInTaskOrder::getDelFlag, 1)); + List taskNumbers = taskOrders.stream() + .map(StockInTaskOrder::getTaskNumber) + .filter(StringUtils::isNotEmpty) + .distinct() + .collect(Collectors.toList()); + //1.收货作业单明细 + if (!taskNumbers.isEmpty()) { + taskReceiptMaterialDetailService.update(new UpdateWrapper().lambda() + .set(TaskReceiptMaterialDetail::getDelFlag, 2) + .in(TaskReceiptMaterialDetail::getTaskNumber, taskNumbers) + .eq(TaskReceiptMaterialDetail::getDelFlag, 1)); + } + //2.收货作业单 + if (!taskOrders.isEmpty()) { + stockInTaskOrderService.update(new UpdateWrapper().lambda() + .set(StockInTaskOrder::getDelFlag, 2) + .eq(StockInTaskOrder::getInOrderNumber, inOrderNumber) + .eq(StockInTaskOrder::getDelFlag, 1)); + } + //3.收货任务(tracking_number=收货单号;补"RV-"+入库单号兜底历史同号收货单) + if (!receiptOrderNumbers.isEmpty()) { + Set trackingNumbers = new HashSet<>(receiptOrderNumbers); + trackingNumbers.add("RV-" + inOrderNumber); + deliveTaskService.update(new UpdateWrapper().lambda() + .set(DeliveTask::getDelFlag, 2) + .in(DeliveTask::getTrackingNumber, trackingNumbers) + .eq(DeliveTask::getTaskType, 1) + .eq(DeliveTask::getDelFlag, 1)); + } + //4.质检单 + qualityInspectionService.update(new UpdateWrapper().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().lambda() + .set(ReceiptMaterialDetail::getDelFlag, 2) + .in(ReceiptMaterialDetail::getReceiptOrderNumber, receiptOrderNumbers) + .eq(ReceiptMaterialDetail::getDelFlag, 1)); + } + //6.收货单 + stockReceiptOrderService.update(new UpdateWrapper().lambda() + .set(StockReceiptOrder::getDelFlag, 2) + .eq(StockReceiptOrder::getInOrderNumber, inOrderNumber) + .eq(StockReceiptOrder::getDelFlag, 1)); + //7.入库单明细 + materialDetailService.update(new UpdateWrapper().lambda() + .set(InMaterialDetail::getDelFlag, 2) + .eq(InMaterialDetail::getInOrderNumber, inOrderNumber) + .eq(InMaterialDetail::getDelFlag, 1)); + //8.入库单 + stockInOrderService.update(new UpdateWrapper().lambda() + .set(StockInOrder::getDelFlag, 2) + .eq(StockInOrder::getInOrderNumber, inOrderNumber) + .eq(StockInOrder::getDelFlag, 1)); + } + /** * OMS下发入库单明细保存后自动审核通过(生成收货单并更新审核状态) */ diff --git a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockInOrder/StockInOrderApi.java b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockInOrder/StockInOrderApi.java index 795e9782e..860c279dd 100644 --- a/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockInOrder/StockInOrderApi.java +++ b/mhd_wms/src/main/java/com/mhd/wms/interfaces/facadeApi/stockInOrder/StockInOrderApi.java @@ -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 inMaterialDetails) { + public AjaxResult omsInOrderAddDetail(@RequestBody List 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("查询入库信息(通过入库单号)")