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外部服务)。
* 定位: 出库单.businessNumber(货源单号) + business_delivery_details_link.invoiceNumber=出库单号(orderId/拆单subOrderId);
* 反审联动软删运输链路(编辑"是否运输"=是 且审核通过后生成的链), 真实层级:
* 运输业务单-主单(splicingOrderType=4, business_document_order)
* -> 审核运输业务单按配送明细生成子单(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无数据, 幂等空操作), 失败抛异常整批回滚;
* 本地软删执行单/运输业务单及其货品/地址明细/配送明细链; 无关联运输单时直接跳过。
* 本地软删执行单/主单及子单及其货品/地址明细/配送明细链; 无关联运输单时直接跳过。
*/
private void reverseTransportChain(ReservationStockOutOrder byId) {
String outOrderNumber = byId.getOutOrderNumber();
Set<Long> transportOrderIds = new HashSet<>();
if (StringUtils.isNotBlank(byId.getBusinessNumber())) {
businessDocumentOrderMapper.selectList(new LambdaQueryWrapper<BusinessDocumentOrder>()
.eq(BusinessDocumentOrder::getGoodsNumber, byId.getBusinessNumber())
.eq(BusinessDocumentOrder::getDelFlag, 1))
.eq(BusinessDocumentOrder::getGoodsNumber, byId.getBusinessNumber()))
.forEach(order -> transportOrderIds.add(order.getId()));
}
for (BusinessDeliveryDetailsLink link : businessDeliveryDetailsLinkService.list(new LambdaQueryWrapper<BusinessDeliveryDetailsLink>()
.eq(BusinessDeliveryDetailsLink::getInvoiceNumber, outOrderNumber)
.eq(BusinessDeliveryDetailsLink::getDelFlag, 1))) {
if (link.getOrderId() != null) {
transportOrderIds.add(link.getOrderId());
}
if (StringUtils.isNotBlank(link.getSubOrderId())) {
try {
transportOrderIds.add(Long.valueOf(link.getSubOrderId()));
} catch (NumberFormatException ignore) {
//拆单子单id非纯数字的历史脏数据, 忽略
}
}
}
businessDocumentOrderMapper.selectList(new LambdaQueryWrapper<BusinessDocumentOrder>()
.eq(BusinessDocumentOrder::getInOrderNumber, outOrderNumber))
.forEach(order -> transportOrderIds.add(order.getId()));
if (transportOrderIds.isEmpty()) {
return;
}
@@ -563,11 +556,17 @@ public class ReservationStockOutOrderDomainService {
if (transportOrder == null) {
continue;
}
// 1. 执行单: 先软删TMS侧整链(货源单->运单->作业单), 再软删本地执行单
// (运输业务单已被手工删除时其执行单/TMS链可能仍存活, 同样需要清理)
// 0. 拆单主单自身无执行单: 收集主单+全部子单id, 执行单/货品/地址明细按全量id清理
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>()
.eq(ExecuteOrder::getBusinessDocumentId, transportOrderId)
.eq(ExecuteOrder::getDelFlag, 1));
.in(ExecuteOrder::getBusinessDocumentId, chainDocIds));
for (ExecuteOrder executeOrder : executeOrders) {
if (StringUtils.isNotBlank(executeOrder.getGoodsNumber())) {
AjaxResult tmsResult = wlhyServiceFeign.deleteChainByExecuteOrderNumber(executeOrder.getGoodsNumber());
@@ -577,30 +576,34 @@ public class ReservationStockOutOrderDomainService {
+ (tmsResult == null ? "TMS服务不可用" : tmsResult.get("msg")));
}
}
if (!Integer.valueOf(2).equals(executeOrder.getDelFlag())) {
executeOrder.setDelFlag(2);
executeOrderMapper.updateById(executeOrder);
}
// 2. 软删运输业务单及其货品/地址明细(已软删的跳过更新)
}
// 2. 软删运输业务单(主单+子单)及其货品/地址明细(主单已软删的只补清理子单/明细, 不重复更新主单)
if (!Integer.valueOf(2).equals(transportOrder.getDelFlag())) {
transportOrder.setDelFlag(2);
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>()
.set(BusinessDocumentCargoMulti::getDelFlag, 2)
.eq(BusinessDocumentCargoMulti::getOrderId, String.valueOf(transportOrderId))
.in(BusinessDocumentCargoMulti::getOrderId, chainDocIdStrings)
.eq(BusinessDocumentCargoMulti::getDelFlag, 1));
businessDocumentAddressMultiMapper.update(null, new LambdaUpdateWrapper<BusinessDocumentAddressMulti>()
.set(BusinessDocumentAddressMulti::getDelFlag, 2)
.eq(BusinessDocumentAddressMulti::getOrderId, String.valueOf(transportOrderId))
.in(BusinessDocumentAddressMulti::getOrderId, chainDocIdStrings)
.eq(BusinessDocumentAddressMulti::getDelFlag, 1));
}
}
// 3. 配送明细链软删(仅限指向本次删除的运输业务单, 保留指向其他运输单的链路)
List<String> transportOrderIdStrings = transportOrderIds.stream().map(String::valueOf).collect(Collectors.toList());
// 3. 配送明细链软删: 链的orderId固定指向运输业务单-主单, 按本次命中的主单id清理(含历史周期残留链)
businessDeliveryDetailsLinkService.update(null, new LambdaUpdateWrapper<BusinessDeliveryDetailsLink>()
.set(BusinessDeliveryDetailsLink::getDelFlag, 2)
.eq(BusinessDeliveryDetailsLink::getInvoiceNumber, outOrderNumber)
.and(wrapper -> wrapper.in(BusinessDeliveryDetailsLink::getOrderId, transportOrderIds)
.or().in(BusinessDeliveryDetailsLink::getSubOrderId, transportOrderIdStrings))
.in(BusinessDeliveryDetailsLink::getOrderId, transportOrderIds)
.eq(BusinessDeliveryDetailsLink::getDelFlag, 1));
}
@@ -42,6 +42,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<sql id="selectExecuteOrderPo1">
<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">
and eo.CREATE_TIME &gt;= #{createStartTime}
</if>