diff --git a/firstleg/src/main/java/com/baiyue/firstleg/service/UnifiedInboundQueryService.java b/firstleg/src/main/java/com/baiyue/firstleg/service/UnifiedInboundQueryService.java index acd292bed..3264091bb 100644 --- a/firstleg/src/main/java/com/baiyue/firstleg/service/UnifiedInboundQueryService.java +++ b/firstleg/src/main/java/com/baiyue/firstleg/service/UnifiedInboundQueryService.java @@ -57,20 +57,30 @@ public class UnifiedInboundQueryService { InboundOrderEntity inbound = inbounds.findByOrderId(tenantId, orderId); if (inbound == null) return null; InboundOrderDetail detail = inbounds.detail(tenantId, inbound); + String mainStatus = mainStatus(inbound.getProcessStatus()); + boolean includePhaseThree = requiresPhaseThreeSummary(mainStatus); List timeline = detail.statusHistory().stream() .map(item -> new UnifiedInboundDetail.TimelineEvent( "FIRSTLEG", "STATUS", item.fromStatus(), item.toStatus(), item.action(), item.reason(), item.operatorId(), item.operatorName(), item.occurredAt())) .toList(); - return new UnifiedInboundDetail(summary(inbound, detail, - operations.findPreload(tenantId, inbound.getId()), operations.findPick(tenantId, inbound.getId()), - operations.findEvidence(tenantId, inbound.getId()), deliveryAt(detail.statusHistory()), - operations.findTransport(tenantId, inbound.getId())), timeline); + // Phase-three tables are optional during the phase-two measurement workflow. + com.baiyue.firstleg.split.entity.PreloadPlanEntity preload = null; + com.baiyue.firstleg.loading.entity.InboundLoadingPickTaskEntity pick = null; + List evidence = List.of(); + LocalDateTime deliveryAt = null; + if (includePhaseThree) { + preload = operations.findPreload(tenantId, inbound.getId()); + pick = operations.findPick(tenantId, inbound.getId()); + evidence = operations.findEvidence(tenantId, inbound.getId()); + deliveryAt = deliveryAt(detail.statusHistory()); + } + InboundTransportSnapshotEntity transport = includePhaseThree + ? operations.findTransport(tenantId, inbound.getId()) : null; + return new UnifiedInboundDetail(summary(inbound, detail, preload, pick, evidence, deliveryAt, transport), timeline); } private List summaries(List records) { - Map owners = records.stream().collect(Collectors.toMap( - InboundOrderEntity::getId, InboundOrderEntity::getTenantId, (left, right) -> left)); Map phaseThreeOwners = records.stream() .filter(inbound -> requiresPhaseThreeSummary(mainStatus(inbound.getProcessStatus()))) .collect(Collectors.toMap( @@ -79,7 +89,7 @@ public class UnifiedInboundQueryService { var picks = operations.findPicks(phaseThreeOwners); var evidences = operations.findEvidence(phaseThreeOwners); var deliveries = operations.findDeliveryHistory(phaseThreeOwners); - var transports = operations.findTransports(owners); + var transports = operations.findTransports(phaseThreeOwners); return records.stream().map(inbound -> summary(inbound, null, preloads.get(inbound.getId()), picks.get(inbound.getId()), evidences.getOrDefault(inbound.getId(), List.of()), deliveries.get(inbound.getId()) == null ? null : deliveries.get(inbound.getId()).getOccurredAt(), diff --git a/firstleg/src/test/java/com/baiyue/firstleg/service/UnifiedInboundQueryServiceTest.java b/firstleg/src/test/java/com/baiyue/firstleg/service/UnifiedInboundQueryServiceTest.java index 52be6ba08..9a6d6d84f 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/service/UnifiedInboundQueryServiceTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/service/UnifiedInboundQueryServiceTest.java @@ -1,8 +1,22 @@ package com.baiyue.firstleg.service; import com.baiyue.common.core.exception.BizException; +import com.baiyue.firstleg.dto.InboundOrderDetail; +import com.baiyue.firstleg.dto.UnifiedInboundDetail; import com.baiyue.firstleg.dto.UnifiedInboundQuery; +import com.baiyue.firstleg.entity.InboundOrderEntity; +import com.baiyue.firstleg.repository.InboundOrderRepository; +import com.baiyue.firstleg.repository.UnifiedInboundReadRepository; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.List; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.when; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -65,6 +79,30 @@ class UnifiedInboundQueryServiceTest { assertThat(UnifiedInboundQueryService.requiresPhaseThreeSummary("DELIVERED")).isTrue(); } + @ParameterizedTest + @ValueSource(strings = {"WAIT_MEASURE", "INBOUNDED", "WAIT_SPLIT"}) + void phaseTwoDetailDoesNotQueryPhaseThreeTables(String processStatus) { + InboundOrderRepository inbounds = mock(InboundOrderRepository.class); + UnifiedInboundReadRepository operations = mock(UnifiedInboundReadRepository.class); + UnifiedInboundQueryService service = new UnifiedInboundQueryService(); + ReflectionTestUtils.setField(service, "inbounds", inbounds); + ReflectionTestUtils.setField(service, "operations", operations); + + InboundOrderEntity inbound = new InboundOrderEntity(); + inbound.setId(88L); + inbound.setOrderId(99L); + inbound.setTenantId(10001L); + inbound.setProcessStatus(processStatus); + InboundOrderDetail detail = new InboundOrderDetail(null, null, null, null, null, List.of()); + when(inbounds.findByOrderId(10001L, 99L)).thenReturn(inbound); + when(inbounds.detail(10001L, inbound)).thenReturn(detail); + + UnifiedInboundDetail result = service.detail(10001L, 99L); + + assertThat(result).isNotNull(); + verifyNoInteractions(operations); + } + @Test void rejectsUnknownReviewStatusBeforeRepositoryQuery() { UnifiedInboundQuery query = new UnifiedInboundQuery(