diff --git a/firstleg/src/main/java/com/baiyue/firstleg/terminaldrayage/service/ContainerWorkbenchService.java b/firstleg/src/main/java/com/baiyue/firstleg/terminaldrayage/service/ContainerWorkbenchService.java index 018f20be1..8c2fc4b0d 100644 --- a/firstleg/src/main/java/com/baiyue/firstleg/terminaldrayage/service/ContainerWorkbenchService.java +++ b/firstleg/src/main/java/com/baiyue/firstleg/terminaldrayage/service/ContainerWorkbenchService.java @@ -38,7 +38,6 @@ public class ContainerWorkbenchService { public WorkbenchItem domesticDetail(long id, Set permissions) { ContainerBookingEntity value = required(id); - if (repository.departed(id)) throw new BizException(ResultCode.NOT_FOUND, "国内工作台货柜不存在"); ContainerActualFacts facts = actualFacts(List.of(id)).get(id); return item("DOMESTIC", value, facts, null, permissions); } diff --git a/firstleg/src/main/resources/openapi/firstleg-v1.yaml b/firstleg/src/main/resources/openapi/firstleg-v1.yaml index 9701d1057..c2b48e20c 100644 --- a/firstleg/src/main/resources/openapi/firstleg-v1.yaml +++ b/firstleg/src/main/resources/openapi/firstleg-v1.yaml @@ -445,7 +445,7 @@ paths: /api/platform/v1/containers/domestic/{id}: get: summary: 查询国内货柜工作台详情 - description: 需要 platform:firstleg:container:list;装柜清单只返回唯一loadingPlanId/planNo/planStatus关联 + description: 需要 platform:firstleg:container:list;国内ACTIVE与HISTORY共用该只读详情,已真实离仓柜仍可打开;装柜清单只返回唯一loadingPlanId/planNo/planStatus关联 parameters: [{$ref: '#/components/parameters/ContainerBookingId'}] responses: {'200': {description: 成功, content: {application/json: {schema: {$ref: '#/components/schemas/ContainerWorkbenchEnvelope'}}}}} /api/platform/v1/containers/overseas/{id}: diff --git a/firstleg/src/test/java/com/baiyue/firstleg/controller/ContainerControllerContractTest.java b/firstleg/src/test/java/com/baiyue/firstleg/controller/ContainerControllerContractTest.java index e89e1e424..c272ef9e4 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/controller/ContainerControllerContractTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/controller/ContainerControllerContractTest.java @@ -66,6 +66,7 @@ class ContainerControllerContractTest { .contains("/api/platform/v1/containers/{id}/ocean-booking-link:") .contains("/api/platform/v1/containers/domestic:") .contains("/api/platform/v1/containers/overseas:") + .contains("国内ACTIVE与HISTORY共用该只读详情,已真实离仓柜仍可打开") .contains("scope, in: query, required: true") .contains("首次关联允许 WAIT_LOADING 或已有预排货的 EDITING 模拟柜") .contains("RELEASED oceanBookingId") diff --git a/firstleg/src/test/java/com/baiyue/firstleg/terminaldrayage/service/ContainerWorkbenchServiceTest.java b/firstleg/src/test/java/com/baiyue/firstleg/terminaldrayage/service/ContainerWorkbenchServiceTest.java index 89bdb28b8..0216d1caf 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/terminaldrayage/service/ContainerWorkbenchServiceTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/terminaldrayage/service/ContainerWorkbenchServiceTest.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; @@ -83,6 +84,35 @@ class ContainerWorkbenchServiceTest { verifyNoInteractions(carrierSchedules); } + @Test + void domesticHistoryDetailKeepsTheDepartedContainerAndItsUniqueLoadingPlan() { + ContainerBookingEntity container = container(); + container.setOutboundConfirmedAt(LocalDateTime.of(2026, 9, 8, 10, 0)); + when(repository.find(11L)).thenReturn(container); + when(repository.departed(11L)).thenReturn(true); + when(carrierSchedules.containerActualFacts(List.of(11L))).thenReturn(List.of(facts("DEPARTED_WAREHOUSE"))); + + var result = service.domesticDetail(11L, Set.of("platform:firstleg:container:list")); + + assertThat(result.workbenchStage()).isEqualTo("DEPARTED_WAREHOUSE"); + assertThat(result.container().getPlanId()).isEqualTo(31L); + assertThat(result.container().getPlanNo()).isEqualTo("LP-260908-0001"); + assertThat(result.allowedActions()).isEmpty(); + verify(repository, never()).departed(11L); + verifyNoInteractions(terminalDrayages); + } + + @Test + void domesticDetailStillRejectsContainersOutsideTheActiveMasterSet() { + when(repository.find(404L)).thenReturn(null); + + assertThatThrownBy(() -> service.domesticDetail(404L, Set.of("platform:firstleg:container:list"))) + .isInstanceOf(com.baiyue.common.core.exception.BizException.class) + .hasMessage("货柜不存在"); + + verifyNoInteractions(carrierSchedules, terminalDrayages); + } + private static Query query(WorkbenchScope scope) { return new Query(null, null, null, null, null, null, null, null, null, null, null, null, null, null, scope, 1, 20);