diff --git a/firstleg/src/main/java/com/baiyue/firstleg/service/InboundMeasurementService.java b/firstleg/src/main/java/com/baiyue/firstleg/service/InboundMeasurementService.java index c280a3bea..f11199c15 100644 --- a/firstleg/src/main/java/com/baiyue/firstleg/service/InboundMeasurementService.java +++ b/firstleg/src/main/java/com/baiyue/firstleg/service/InboundMeasurementService.java @@ -466,6 +466,10 @@ public class InboundMeasurementService { } return response.data(); } catch (FeignException exception) { + if (exception.status() == 400) { + throw new BizException(ResultCode.SERVICE_UNAVAILABLE, + "订单服务申报快照契约未就绪,请同步部署 order-service 与 firstleg-service"); + } throw new BizException(ResultCode.SERVICE_UNAVAILABLE, "订单服务暂不可用,无法读取客户申报数据"); } } diff --git a/firstleg/src/test/java/com/baiyue/firstleg/service/InboundMeasurementServiceTest.java b/firstleg/src/test/java/com/baiyue/firstleg/service/InboundMeasurementServiceTest.java index 3d5b1cba3..0e6a09758 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/service/InboundMeasurementServiceTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/service/InboundMeasurementServiceTest.java @@ -29,6 +29,8 @@ import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; +import feign.FeignException; + import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.tuple; @@ -147,6 +149,27 @@ class InboundMeasurementServiceTest { verify(repository, never()).updateInbound(any()); } + @Test + void detailReportsOrderContractNotReadyInsteadOfExposingDownstreamBadRequest() { + InboundOrderEntity inbound = inbound("MEASURE_PENDING"); + InboundMeasurementEntity measurement = new InboundMeasurementEntity(); + measurement.setId(30L); + when(repository.findInbound(1L, 10L)).thenReturn(inbound); + when(repository.findLatestMeasurement(1L, 10L)).thenReturn(measurement); + FeignException downstreamBadRequest = mock(FeignException.class); + when(downstreamBadRequest.status()).thenReturn(400); + when(orderCargoClient.measurementDeclaration("internal-token", 1L, 80L)) + .thenThrow(downstreamBadRequest); + + assertThatThrownBy(() -> service.detail(1L, 10L)) + .isInstanceOfSatisfying(BizException.class, exception -> { + assertThat(exception.getResultCode().code()).isEqualTo("S0503"); + assertThat(exception).hasMessageContaining("申报快照契约未就绪") + .hasMessageContaining("order-service") + .hasMessageContaining("firstleg-service"); + }); + } + @Test void detailKeepsDimensionAndWeightEvidenceOnTheirStableBusinessRecords() { InboundOrderEntity inbound = inbound("MEASURE_PENDING"); diff --git a/order/src/test/java/com/baiyue/order/controller/InternalOrderCargoControllerTest.java b/order/src/test/java/com/baiyue/order/controller/InternalOrderCargoControllerTest.java index d75be5c6f..8877beb4c 100644 --- a/order/src/test/java/com/baiyue/order/controller/InternalOrderCargoControllerTest.java +++ b/order/src/test/java/com/baiyue/order/controller/InternalOrderCargoControllerTest.java @@ -18,8 +18,11 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import java.math.BigDecimal; +import java.lang.reflect.Method; import java.util.List; +import org.springframework.web.bind.annotation.GetMapping; + @SpringJUnitConfig(InternalOrderCargoController.class) @TestPropertySource(properties = "baiyue.security.internal-service-token=internal-token") class InternalOrderCargoControllerTest { @@ -149,6 +152,21 @@ class InternalOrderCargoControllerTest { assertThat(result.defaultActualGoodsName()).isEqualTo("品名A、品名B"); } + @Test + void measurementDeclarationHasAnExplicitStaticRouteBesideNumericCargoDetail() throws Exception { + Method declaration = InternalOrderCargoController.class.getMethod( + "measurementDeclaration", String.class, long.class, long.class); + Method cargoDetail = InternalOrderCargoController.class.getMethod( + "detail", String.class, long.class, long.class, long.class); + + assertThat(declaration.getAnnotation(GetMapping.class).value()) + .containsExactly("/{tenantId}/{orderId}/measurement-declaration"); + assertThat(cargoDetail.getAnnotation(GetMapping.class).value()) + .containsExactly("/{tenantId}/{orderId}/{cargoId}"); + assertThat(declaration.getParameterCount()).isEqualTo(3); + assertThat(cargoDetail.getParameterCount()).isEqualTo(4); + } + @Test void splitChildWithoutDirectCargoDoesNotCopyRootDeclarationTotals() { OrderEntity child = new OrderEntity();