fix(firstleg): avoid phase-three reads in phase-two queries
This commit is contained in:
@@ -57,20 +57,30 @@ public class UnifiedInboundQueryService {
|
|||||||
InboundOrderEntity inbound = inbounds.findByOrderId(tenantId, orderId);
|
InboundOrderEntity inbound = inbounds.findByOrderId(tenantId, orderId);
|
||||||
if (inbound == null) return null;
|
if (inbound == null) return null;
|
||||||
InboundOrderDetail detail = inbounds.detail(tenantId, inbound);
|
InboundOrderDetail detail = inbounds.detail(tenantId, inbound);
|
||||||
|
String mainStatus = mainStatus(inbound.getProcessStatus());
|
||||||
|
boolean includePhaseThree = requiresPhaseThreeSummary(mainStatus);
|
||||||
List<UnifiedInboundDetail.TimelineEvent> timeline = detail.statusHistory().stream()
|
List<UnifiedInboundDetail.TimelineEvent> timeline = detail.statusHistory().stream()
|
||||||
.map(item -> new UnifiedInboundDetail.TimelineEvent(
|
.map(item -> new UnifiedInboundDetail.TimelineEvent(
|
||||||
"FIRSTLEG", "STATUS", item.fromStatus(), item.toStatus(), item.action(), item.reason(),
|
"FIRSTLEG", "STATUS", item.fromStatus(), item.toStatus(), item.action(), item.reason(),
|
||||||
item.operatorId(), item.operatorName(), item.occurredAt()))
|
item.operatorId(), item.operatorName(), item.occurredAt()))
|
||||||
.toList();
|
.toList();
|
||||||
return new UnifiedInboundDetail(summary(inbound, detail,
|
// Phase-three tables are optional during the phase-two measurement workflow.
|
||||||
operations.findPreload(tenantId, inbound.getId()), operations.findPick(tenantId, inbound.getId()),
|
com.baiyue.firstleg.split.entity.PreloadPlanEntity preload = null;
|
||||||
operations.findEvidence(tenantId, inbound.getId()), deliveryAt(detail.statusHistory()),
|
com.baiyue.firstleg.loading.entity.InboundLoadingPickTaskEntity pick = null;
|
||||||
operations.findTransport(tenantId, inbound.getId())), timeline);
|
List<LoadingEvidenceEntity> 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<UnifiedInboundSummary> summaries(List<InboundOrderEntity> records) {
|
private List<UnifiedInboundSummary> summaries(List<InboundOrderEntity> records) {
|
||||||
Map<Long, Long> owners = records.stream().collect(Collectors.toMap(
|
|
||||||
InboundOrderEntity::getId, InboundOrderEntity::getTenantId, (left, right) -> left));
|
|
||||||
Map<Long, Long> phaseThreeOwners = records.stream()
|
Map<Long, Long> phaseThreeOwners = records.stream()
|
||||||
.filter(inbound -> requiresPhaseThreeSummary(mainStatus(inbound.getProcessStatus())))
|
.filter(inbound -> requiresPhaseThreeSummary(mainStatus(inbound.getProcessStatus())))
|
||||||
.collect(Collectors.toMap(
|
.collect(Collectors.toMap(
|
||||||
@@ -79,7 +89,7 @@ public class UnifiedInboundQueryService {
|
|||||||
var picks = operations.findPicks(phaseThreeOwners);
|
var picks = operations.findPicks(phaseThreeOwners);
|
||||||
var evidences = operations.findEvidence(phaseThreeOwners);
|
var evidences = operations.findEvidence(phaseThreeOwners);
|
||||||
var deliveries = operations.findDeliveryHistory(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()),
|
return records.stream().map(inbound -> summary(inbound, null, preloads.get(inbound.getId()),
|
||||||
picks.get(inbound.getId()), evidences.getOrDefault(inbound.getId(), List.of()),
|
picks.get(inbound.getId()), evidences.getOrDefault(inbound.getId(), List.of()),
|
||||||
deliveries.get(inbound.getId()) == null ? null : deliveries.get(inbound.getId()).getOccurredAt(),
|
deliveries.get(inbound.getId()) == null ? null : deliveries.get(inbound.getId()).getOccurredAt(),
|
||||||
|
|||||||
+38
@@ -1,8 +1,22 @@
|
|||||||
package com.baiyue.firstleg.service;
|
package com.baiyue.firstleg.service;
|
||||||
|
|
||||||
import com.baiyue.common.core.exception.BizException;
|
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.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.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.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
@@ -65,6 +79,30 @@ class UnifiedInboundQueryServiceTest {
|
|||||||
assertThat(UnifiedInboundQueryService.requiresPhaseThreeSummary("DELIVERED")).isTrue();
|
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
|
@Test
|
||||||
void rejectsUnknownReviewStatusBeforeRepositoryQuery() {
|
void rejectsUnknownReviewStatusBeforeRepositoryQuery() {
|
||||||
UnifiedInboundQuery query = new UnifiedInboundQuery(
|
UnifiedInboundQuery query = new UnifiedInboundQuery(
|
||||||
|
|||||||
Reference in New Issue
Block a user