From d622ddd37f519b99f60ef90b62e9acc162267ecc Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Mon, 7 Sep 2026 16:06:08 +0800 Subject: [PATCH] fix: isolate invalid receiving candidates --- .../service/ReceivingContainerService.java | 16 +++++++------- ...ReceivingContainerServiceBehaviorTest.java | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/service/ReceivingContainerService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/service/ReceivingContainerService.java index fcf292c0a..38dd06617 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/service/ReceivingContainerService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/pda/service/ReceivingContainerService.java @@ -443,13 +443,13 @@ public class ReceivingContainerService { try { assignedWarehouses.add(Long.valueOf(value)); } catch (NumberFormatException ignored) { assignedWarehouses.add(Long.MIN_VALUE); } }); - if (assignedWarehouses.size() > 1) throw conflict("柜内接柜仓分配不一致"); + if (assignedWarehouses.size() > 1) return null; if (assignedWarehouses.size() != 1 || !assignedWarehouses.contains(overseasWarehouseId)) return null; Set warehouseCodes = orderFacts.stream().map(LastlegOrder::getOverseasWarehouseCode) .map(ReceivingContainerService::trim).filter(Objects::nonNull).collect(Collectors.toSet()); Set warehouseNames = orderFacts.stream().map(LastlegOrder::getOverseasWarehouseName) .map(ReceivingContainerService::trim).filter(Objects::nonNull).collect(Collectors.toSet()); - if (warehouseCodes.size() != 1 || warehouseNames.size() != 1) throw conflict("柜内接柜仓业务快照不一致"); + boolean warehouseSnapshotConsistent = warehouseCodes.size() == 1 && warehouseNames.size() == 1; Set customers = orderFacts.stream().map(LastlegOrder::getCustomerId).collect(Collectors.toSet()); String containerNo = orderFacts.stream().map(LastlegOrder::getContainerNo).filter(Objects::nonNull).findFirst().orElse(null); int totalOrders = orderFacts.size(); @@ -468,10 +468,11 @@ public class ReceivingContainerService { && containerPlans.stream().allMatch(plan -> "COMPLETED".equals(plan.getStatus())); String customerId = customers.size() == 1 ? customers.iterator().next() : null; boolean shippingReady = customerId != null && shippingGates.receivingAvailable(customerId, containerNo) == 1; - boolean operable = allPlansReady && shippingReady; + boolean operable = allPlansReady && shippingReady && warehouseSnapshotConsistent; int pending = Math.max(0, totalOrders - plannedOrders); - String blockReason = operable ? null : (!allPlansReady - ? plannedOrders + "个入仓码已生成计划," + pending + "个订单未操作/缺入仓码" + String blockReason = operable ? null : (!warehouseSnapshotConsistent + ? "柜内接柜仓业务快照不一致" + : !allPlansReady ? plannedOrders + "个入仓码已生成计划," + pending + "个订单未操作/缺入仓码" : "柜号尚未达到海外收货可操作节点"); LocalDateTime arrival = orderFacts.stream().map(LastlegOrder::getEstimatedWarehouseAt) .filter(Objects::nonNull).min(LocalDateTime::compareTo).orElse(null); @@ -492,8 +493,9 @@ public class ReceivingContainerService { inboundValues.stream().mapToInt(ReceivingContainerResponses.Inbound::plannedPalletCount).sum(), inboundValues.stream().mapToInt(ReceivingContainerResponses.Inbound::totalPackages).sum(), inboundValues.stream().mapToInt(ReceivingContainerResponses.Inbound::receivedPackages).sum()); - return new ContainerReadiness(sourceContainerBookingId, containerNo, warehouseCodes.iterator().next(), - warehouseNames.iterator().next(), totalOrders, inboundCodes, + return new ContainerReadiness(sourceContainerBookingId, containerNo, + warehouseCodes.size() == 1 ? warehouseCodes.iterator().next() : null, + warehouseNames.size() == 1 ? warehouseNames.iterator().next() : null, totalOrders, inboundCodes, totalOrders - inboundCodes, planCount, plannedOrders, pending, allPlansReady, allPlansCompleted, shippingReady, operable, blockReason, arrival, factHash, totals); } diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/pda/service/ReceivingContainerServiceBehaviorTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/pda/service/ReceivingContainerServiceBehaviorTest.java index 33fb051ad..8452b51d5 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/pda/service/ReceivingContainerServiceBehaviorTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/pda/service/ReceivingContainerServiceBehaviorTest.java @@ -176,6 +176,27 @@ class ReceivingContainerServiceBehaviorTest { .containsExactly("CONT-EARLY", "CONT-LATE", "CONT-NULL", "CONT-BLOCKED"); } + @Test + void invalidWarehouseSnapshotOnlyBlocksItsContainerWithoutFailingHealthyCandidates() { + InboundPlan brokenPlan = plan("CONT-BROKEN"); + InboundPlan healthyPlan = plan("CONT-HEALTHY"); healthyPlan.setId(3L); + InboundPlanLine brokenLine = line("FBA"); + InboundPlanLine healthyLine = line("FBA"); healthyLine.setId(11L); healthyLine.setOrderId(2L); healthyLine.setPlanId(3L); + LastlegOrder broken = containerOrder(1L, "100", "CONT-BROKEN", "BOOKING-A", "IN-1"); + broken.setOverseasWarehouseCode(null); + LastlegOrder healthy = containerOrder(2L, "100", "CONT-HEALTHY", "BOOKING-B", "IN-2"); + when(plans.selectList(any())).thenReturn(List.of(brokenPlan, healthyPlan)); + when(lines.selectList(any())).thenReturn(List.of(brokenLine, healthyLine)); + when(orders.selectList(any())).thenReturn(List.of(broken, healthy)); + + var result = service.candidates("7", 100L); + + assertThat(result).extracting("containerNo").containsExactly("CONT-HEALTHY", "CONT-BROKEN"); + assertThat(result.get(0).operable()).isTrue(); + assertThat(result.get(1).operable()).isFalse(); + assertThat(result.get(1).blockReason()).isEqualTo("柜内接柜仓业务快照不一致"); + } + @Test void candidatesIncludeUnassignedAndSameWarehouseButHideOtherWarehouse() { InboundPlan unassigned = plan("CONT-A");