fix(lastleg): resolve exceptions by inbound relation

This commit is contained in:
2026-09-02 16:48:45 +08:00
parent a8c71fef12
commit e06c12c263
2 changed files with 22 additions and 3 deletions
@@ -128,7 +128,11 @@ public class ExceptionOrderService {
if (!StringUtils.hasText(inbound) && !StringUtils.hasText(tailNo)) {
throw badRequest("入仓码和尾程订单号至少填写一个");
}
LastlegOrder tail = StringUtils.hasText(tailNo) ? uniqueTail(customerId, tailNo) : null;
// A tail-order number is not a globally unique business key. When the
// caller also supplies an inbound code (the normal exception/return
// workflow does), resolve the pair together rather than rejecting a
// valid relation because another order has reused the tail number.
LastlegOrder tail = StringUtils.hasText(tailNo) ? uniqueTail(customerId, tailNo, inbound) : null;
LastlegInboundOrder inboundOrder = StringUtils.hasText(inbound) ? uniqueInbound(customerId, inbound) : null;
if (tail != null && inboundOrder != null && !Objects.equals(tail.getInboundCode(), inboundOrder.getInboundCode())) {
throw conflict("尾程订单与入仓单不是同一关联关系");
@@ -182,10 +186,12 @@ public class ExceptionOrderService {
return new ExceptionOrderResponses.Created(value.getId(), value.getExceptionNo(), value.getStatus());
}
private LastlegOrder uniqueTail(String customerId, String orderNo) {
private LastlegOrder uniqueTail(String customerId, String orderNo, String inboundCode) {
List<LastlegOrder> values = lastMileOrders.selectList(new LambdaQueryWrapper<LastlegOrder>()
.eq(StringUtils.hasText(customerId), LastlegOrder::getCustomerId, customerId)
.eq(LastlegOrder::getOrderNo, orderNo).last("LIMIT 2"));
.eq(LastlegOrder::getOrderNo, orderNo)
.eq(StringUtils.hasText(inboundCode), LastlegOrder::getInboundCode, inboundCode)
.last("LIMIT 2"));
if (values.isEmpty()) throw notFound("尾程订单不存在");
if (values.size() > 1) throw conflict("尾程订单号不唯一,请先选择客户");
return values.get(0);
@@ -59,6 +59,19 @@ class ExceptionOrderServiceTest {
.hasMessageContaining("不是同一关联关系");
}
@Test
void resolvesTheExactInboundWhenTailOrderNumberIsReused() {
LastlegOrder selected = tail("LM-1", "IN-2");
selected.setId(22L);
when(lastMileOrders.selectList(any())).thenReturn(List.of(selected));
when(inboundOrders.selectList(any())).thenReturn(List.of(inbound("IN-2")));
var relation = service.resolve(null, null, "IN-2", "LM-1");
assertThat(relation.lastMileOrderId()).isEqualTo(22L);
assertThat(relation.inboundCode()).isEqualTo("IN-2");
}
private LastlegOrder tail(String orderNo, String inboundCode) {
LastlegOrder value = new LastlegOrder();
value.setId(12L); value.setCustomerId("1001"); value.setOrderNo(orderNo); value.setInboundCode(inboundCode);