diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/service/InboundPlanService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/service/InboundPlanService.java index 7fe420dee..761e892bb 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/service/InboundPlanService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/inboundplan/service/InboundPlanService.java @@ -533,7 +533,9 @@ public class InboundPlanService { wholePallets.add(sourcePallets); List standardNos = "ONE_CLICK_DROPSHIP".equals(ref.orderType()) ? List.of() : sourcePalletMapper.palletNos(ref.customerId(), ref.orderId()); - if (sourcePallets == null && standardNos.isEmpty()) throw new ResponseStatusException( + boolean standardFba = sourcePallets == null && orders.stream() + .anyMatch(order -> trimToNull(order.fbaWarehouseCode()) != null); + if (standardFba && standardNos.isEmpty()) throw new ResponseStatusException( HttpStatus.CONFLICT, "散货订单缺少头程托盘码快照"); standardPalletNos.add(standardNos); } diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/InboundPlanServiceTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/InboundPlanServiceTest.java index 5e9c7725d..b6b616fe4 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/InboundPlanServiceTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/inboundplan/service/InboundPlanServiceTest.java @@ -478,6 +478,41 @@ class InboundPlanServiceTest { .map(InboundPlanPalletAllocation::getPlannedPackageCount).toList()); } + @Test + void standardOverseasContainerConversionAllowsMissingSourcePalletSnapshot() { + when(orderMapper.lockContainerOrders("BOOKING-1")).thenReturn(List.of( + new InboundPlanOrderMapper.ContainerOrderRef("100", 1L, "PENDING_ASSIGNMENT", + "MSCU6639870", "STANDARD"))); + when(orderMapper.lockOrder("100", 1L)).thenReturn(List.of(order("100", 1L, "RK-1", "WH-A"))); + when(sourcePalletMapper.palletNos("100", 1L)).thenReturn(List.of()); + when(orderMapper.markPlanned(any(), any(), any(), org.mockito.ArgumentMatchers.anyInt(), any())) + .thenReturn(1); + + var result = service.convertContainer("BOOKING-1"); + + assertEquals(1, result.size()); + verify(planMapper).insert(any(InboundPlan.class)); + } + + @Test + void standardFbaContainerConversionStillRequiresSourcePalletSnapshot() { + when(orderMapper.lockContainerOrders("BOOKING-1")).thenReturn(List.of( + new InboundPlanOrderMapper.ContainerOrderRef("100", 1L, "PENDING_ASSIGNMENT", + "MSCU6639870", "STANDARD"))); + SourceOrderSnapshot fba = new SourceOrderSnapshot(1L, "100", "MSCU6639870", "RK-1", + "PENDING_ASSIGNMENT", null, BigDecimal.ONE, 10, 1, + "193000000000200003", "US-LAX-01", "洛杉矶仓", "ABE3", + "FBA-1", "ABE3", "ABE3", 1, 0); + when(orderMapper.lockOrder("100", 1L)).thenReturn(List.of(fba)); + when(sourcePalletMapper.palletNos("100", 1L)).thenReturn(List.of()); + + ResponseStatusException error = assertThrows(ResponseStatusException.class, + () -> service.convertContainer("BOOKING-1")); + + assertEquals("散货订单缺少头程托盘码快照", error.getReason()); + verify(planMapper, never()).insert(any(InboundPlan.class)); + } + @Test void invalidLaterOrderCausesNoWritesBecauseWholeContainerIsPrevalidated() { when(orderMapper.lockContainerOrders("BOOKING-1")).thenReturn(List.of(