fix(oms): 反审运输链路按拆单子单全量软删——执行单挂子单下(businessDocumentId=子单id), 主单+子单+执行单+TMS链全删; 执行单列表默认过滤归档行

This commit is contained in:
rcx
2026-09-12 09:53:13 +08:00
parent b86ab75dcf
commit da76816533
2 changed files with 48 additions and 40 deletions
@@ -526,35 +526,28 @@ public class ReservationStockOutOrderDomainService {
} }
/** /**
* 反审联动软删运输链路(编辑"是否运输"=是 且审核通过后生成的链): * 反审联动软删运输链路(编辑"是否运输"=是 且审核通过后生成的链), 真实层级:
* 运输业务单(business_document_order) -> 运输执行单(execute_order) -> TMS货源单/运单/运输作业单(wlhy外部服务)。 * 运输业务单-主单(splicingOrderType=4, business_document_order)
* 定位: 出库单.businessNumber(货源单号) + business_delivery_details_link.invoiceNumber=出库单号(orderId/拆单subOrderId); * -> 审核运输业务单按配送明细生成子单(splicingOrderType=3, mainOrderId=主单id, 每明细一单)
* -> 下发每个子单各生成一个运输执行单(execute_order.businessDocumentId=【子单id】, goodsNumber=子单货源号, 主单下无直接执行单)
* -> 每个执行单各推一单TMS(tms_order.execute_order_number=执行单货源号) -> TMS运单/运输作业单(wlhy外部服务)。
* 定位运输业务单: ①出库单.businessNumber(创建运输业务单时回填的货源单号) ②inOrderNumber=出库单号兜底
* (businessNumber缺失/已清空场景); 均不滤del_flag——此前被旧版反审漏删或手工删过的主单,
* 其子单/执行单/TMS链可能仍存活, 同样要清理(幂等)。配送明细链的invoiceNumber存的是送货单号而非出库单号, 不能作为定位条件。
* 执行单逐个调 TMS deleteChainByExecuteOrderNumber 软删TMS侧整链(未下发过则TMS无数据, 幂等空操作), 失败抛异常整批回滚; * 执行单逐个调 TMS deleteChainByExecuteOrderNumber 软删TMS侧整链(未下发过则TMS无数据, 幂等空操作), 失败抛异常整批回滚;
* 本地软删执行单/运输业务单及其货品/地址明细/配送明细链; 无关联运输单时直接跳过。 * 本地软删执行单/主单及子单及其货品/地址明细/配送明细链; 无关联运输单时直接跳过。
*/ */
private void reverseTransportChain(ReservationStockOutOrder byId) { private void reverseTransportChain(ReservationStockOutOrder byId) {
String outOrderNumber = byId.getOutOrderNumber(); String outOrderNumber = byId.getOutOrderNumber();
Set<Long> transportOrderIds = new HashSet<>(); Set<Long> transportOrderIds = new HashSet<>();
if (StringUtils.isNotBlank(byId.getBusinessNumber())) { if (StringUtils.isNotBlank(byId.getBusinessNumber())) {
businessDocumentOrderMapper.selectList(new LambdaQueryWrapper<BusinessDocumentOrder>() businessDocumentOrderMapper.selectList(new LambdaQueryWrapper<BusinessDocumentOrder>()
.eq(BusinessDocumentOrder::getGoodsNumber, byId.getBusinessNumber()) .eq(BusinessDocumentOrder::getGoodsNumber, byId.getBusinessNumber()))
.eq(BusinessDocumentOrder::getDelFlag, 1))
.forEach(order -> transportOrderIds.add(order.getId())); .forEach(order -> transportOrderIds.add(order.getId()));
} }
for (BusinessDeliveryDetailsLink link : businessDeliveryDetailsLinkService.list(new LambdaQueryWrapper<BusinessDeliveryDetailsLink>() businessDocumentOrderMapper.selectList(new LambdaQueryWrapper<BusinessDocumentOrder>()
.eq(BusinessDeliveryDetailsLink::getInvoiceNumber, outOrderNumber) .eq(BusinessDocumentOrder::getInOrderNumber, outOrderNumber))
.eq(BusinessDeliveryDetailsLink::getDelFlag, 1))) { .forEach(order -> transportOrderIds.add(order.getId()));
if (link.getOrderId() != null) {
transportOrderIds.add(link.getOrderId());
}
if (StringUtils.isNotBlank(link.getSubOrderId())) {
try {
transportOrderIds.add(Long.valueOf(link.getSubOrderId()));
} catch (NumberFormatException ignore) {
//拆单子单id非纯数字的历史脏数据, 忽略
}
}
}
if (transportOrderIds.isEmpty()) { if (transportOrderIds.isEmpty()) {
return; return;
} }
@@ -563,11 +556,17 @@ public class ReservationStockOutOrderDomainService {
if (transportOrder == null) { if (transportOrder == null) {
continue; continue;
} }
// 1. 执行单: 先软删TMS侧整链(货源单->运单->作业单), 再软删本地执行单 // 0. 拆单主单自身无执行单: 收集主单+全部子单id, 执行单/货品/地址明细按全量id清理
// (运输业务单已被手工删除时其执行单/TMS链可能仍存活, 同样需要清理) List<BusinessDocumentOrder> subOrders = businessDocumentOrderMapper.selectList(new LambdaQueryWrapper<BusinessDocumentOrder>()
.eq(BusinessDocumentOrder::getMainOrderId, String.valueOf(transportOrderId))
.eq(BusinessDocumentOrder::getDelFlag, 1));
Set<Long> chainDocIds = new HashSet<>();
chainDocIds.add(transportOrderId);
subOrders.forEach(subOrder -> chainDocIds.add(subOrder.getId()));
// 1. 执行单: 不滤del_flag——历史周期已归档执行单的TMS链也幂等补清(防"执行单已删TMS残留"),
// 先逐个软删TMS侧整链(货源单->运单->作业单), 再软删本地执行单(已归档的跳过更新)
List<ExecuteOrder> executeOrders = executeOrderMapper.selectList(new LambdaQueryWrapper<ExecuteOrder>() List<ExecuteOrder> executeOrders = executeOrderMapper.selectList(new LambdaQueryWrapper<ExecuteOrder>()
.eq(ExecuteOrder::getBusinessDocumentId, transportOrderId) .in(ExecuteOrder::getBusinessDocumentId, chainDocIds));
.eq(ExecuteOrder::getDelFlag, 1));
for (ExecuteOrder executeOrder : executeOrders) { for (ExecuteOrder executeOrder : executeOrders) {
if (StringUtils.isNotBlank(executeOrder.getGoodsNumber())) { if (StringUtils.isNotBlank(executeOrder.getGoodsNumber())) {
AjaxResult tmsResult = wlhyServiceFeign.deleteChainByExecuteOrderNumber(executeOrder.getGoodsNumber()); AjaxResult tmsResult = wlhyServiceFeign.deleteChainByExecuteOrderNumber(executeOrder.getGoodsNumber());
@@ -577,30 +576,34 @@ public class ReservationStockOutOrderDomainService {
+ (tmsResult == null ? "TMS服务不可用" : tmsResult.get("msg"))); + (tmsResult == null ? "TMS服务不可用" : tmsResult.get("msg")));
} }
} }
if (!Integer.valueOf(2).equals(executeOrder.getDelFlag())) {
executeOrder.setDelFlag(2); executeOrder.setDelFlag(2);
executeOrderMapper.updateById(executeOrder); executeOrderMapper.updateById(executeOrder);
} }
// 2. 软删运输业务单及其货品/地址明细(已软删的跳过更新) }
// 2. 软删运输业务单(主单+子单)及其货品/地址明细(主单已软删的只补清理子单/明细, 不重复更新主单)
if (!Integer.valueOf(2).equals(transportOrder.getDelFlag())) { if (!Integer.valueOf(2).equals(transportOrder.getDelFlag())) {
transportOrder.setDelFlag(2); transportOrder.setDelFlag(2);
businessDocumentOrderMapper.updateById(transportOrder); businessDocumentOrderMapper.updateById(transportOrder);
}
for (BusinessDocumentOrder subOrder : subOrders) {
subOrder.setDelFlag(2);
businessDocumentOrderMapper.updateById(subOrder);
}
List<String> chainDocIdStrings = chainDocIds.stream().map(String::valueOf).collect(Collectors.toList());
businessDocumentCargoMultiMapper.update(null, new LambdaUpdateWrapper<BusinessDocumentCargoMulti>() businessDocumentCargoMultiMapper.update(null, new LambdaUpdateWrapper<BusinessDocumentCargoMulti>()
.set(BusinessDocumentCargoMulti::getDelFlag, 2) .set(BusinessDocumentCargoMulti::getDelFlag, 2)
.eq(BusinessDocumentCargoMulti::getOrderId, String.valueOf(transportOrderId)) .in(BusinessDocumentCargoMulti::getOrderId, chainDocIdStrings)
.eq(BusinessDocumentCargoMulti::getDelFlag, 1)); .eq(BusinessDocumentCargoMulti::getDelFlag, 1));
businessDocumentAddressMultiMapper.update(null, new LambdaUpdateWrapper<BusinessDocumentAddressMulti>() businessDocumentAddressMultiMapper.update(null, new LambdaUpdateWrapper<BusinessDocumentAddressMulti>()
.set(BusinessDocumentAddressMulti::getDelFlag, 2) .set(BusinessDocumentAddressMulti::getDelFlag, 2)
.eq(BusinessDocumentAddressMulti::getOrderId, String.valueOf(transportOrderId)) .in(BusinessDocumentAddressMulti::getOrderId, chainDocIdStrings)
.eq(BusinessDocumentAddressMulti::getDelFlag, 1)); .eq(BusinessDocumentAddressMulti::getDelFlag, 1));
} }
} // 3. 配送明细链软删: 链的orderId固定指向运输业务单-主单, 按本次命中的主单id清理(含历史周期残留链)
// 3. 配送明细链软删(仅限指向本次删除的运输业务单, 保留指向其他运输单的链路)
List<String> transportOrderIdStrings = transportOrderIds.stream().map(String::valueOf).collect(Collectors.toList());
businessDeliveryDetailsLinkService.update(null, new LambdaUpdateWrapper<BusinessDeliveryDetailsLink>() businessDeliveryDetailsLinkService.update(null, new LambdaUpdateWrapper<BusinessDeliveryDetailsLink>()
.set(BusinessDeliveryDetailsLink::getDelFlag, 2) .set(BusinessDeliveryDetailsLink::getDelFlag, 2)
.eq(BusinessDeliveryDetailsLink::getInvoiceNumber, outOrderNumber) .in(BusinessDeliveryDetailsLink::getOrderId, transportOrderIds)
.and(wrapper -> wrapper.in(BusinessDeliveryDetailsLink::getOrderId, transportOrderIds)
.or().in(BusinessDeliveryDetailsLink::getSubOrderId, transportOrderIdStrings))
.eq(BusinessDeliveryDetailsLink::getDelFlag, 1)); .eq(BusinessDeliveryDetailsLink::getDelFlag, 1));
} }
@@ -42,6 +42,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectExecuteOrderPo1"> <sql id="selectExecuteOrderPo1">
<where> <where>
<!-- 默认只查正常单(del_flag=1); 反审/删除的归档行需显式传delFlag=2(已反审tab) -->
<choose>
<when test="delFlag != null">and eo.DEL_FLAG = #{delFlag}</when>
<otherwise>and eo.DEL_FLAG = 1</otherwise>
</choose>
<if test="createStartTime != null"> <if test="createStartTime != null">
and eo.CREATE_TIME &gt;= #{createStartTime} and eo.CREATE_TIME &gt;= #{createStartTime}
</if> </if>