优化
This commit is contained in:
+6
-1
@@ -28,9 +28,14 @@ class LoadingFulfillmentCompletionMapperContractTest {
|
||||
.contains("target.process_status='LOADED'")
|
||||
.contains("target.version=#{expectedSourceVersion}");
|
||||
assertThat(aggregateRoot)
|
||||
.contains("LEFT JOIN fl_inbound_order remainder")
|
||||
.contains("LEFT JOIN fl_inbound_order loaded")
|
||||
.contains("remainder.split_purpose='REMAINDER'")
|
||||
.contains("remainder.split_status='NOT_SPLIT'")
|
||||
.contains("loaded.split_purpose='LOADED'")
|
||||
.contains("loaded.process_status<>'LOADED'");
|
||||
.contains("loaded.process_status<>'LOADED'")
|
||||
.contains("remainder.id IS NULL AND loaded.id IS NULL")
|
||||
.doesNotContain("NOT EXISTS")
|
||||
.doesNotContain("SELECT 1 FROM fl_inbound_order");
|
||||
}
|
||||
}
|
||||
|
||||
+67
@@ -9,6 +9,7 @@ import com.baiyue.firstleg.loading.dto.LoadingRequests.UpsertEvidenceRequest;
|
||||
import com.baiyue.firstleg.loading.dto.LoadingRequests.VoidEvidenceRequest;
|
||||
import com.baiyue.firstleg.loading.dto.LoadingResponses.LoadingActionResponse;
|
||||
import com.baiyue.firstleg.loading.entity.LoadingEvidenceEntity;
|
||||
import com.baiyue.firstleg.loading.entity.LoadingOperationEntity;
|
||||
import com.baiyue.firstleg.loading.mapper.LoadingInboundMapper.Snapshot;
|
||||
import com.baiyue.firstleg.loading.mapper.LoadingInboundMapper.CompletionTarget;
|
||||
import com.baiyue.firstleg.loading.bridge.service.LoadingModelBridgeService;
|
||||
@@ -25,6 +26,8 @@ import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
@@ -118,6 +121,62 @@ class LoadingDeliveryServiceTest {
|
||||
verify(repository, never()).completeLoading(anyLong(), anyLong(), anyLong(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
void completesSingleRemainderSourceOnceAndReplaysSameKeyWithoutRepeatingSideEffects() {
|
||||
AtomicInteger claims = new AtomicInteger();
|
||||
AtomicReference<String> requestHash = new AtomicReference<>();
|
||||
AtomicReference<String> resultJson = new AtomicReference<>();
|
||||
when(repository.claimOperation(eq(10L), eq(20L), eq(7L), eq("COMPLETE_LOADING"),
|
||||
eq("slice-replay"), anyString())).thenAnswer(invocation -> {
|
||||
requestHash.set(invocation.getArgument(5));
|
||||
return claims.getAndIncrement() == 0;
|
||||
});
|
||||
doAnswer(invocation -> {
|
||||
resultJson.set(invocation.getArgument(5));
|
||||
return null;
|
||||
}).when(repository).completeOperation(eq(10L), eq(20L), eq(7L), eq("COMPLETE_LOADING"),
|
||||
eq("slice-replay"), anyString());
|
||||
when(repository.findOperation(10L, 20L, 7L, "COMPLETE_LOADING", "slice-replay"))
|
||||
.thenAnswer(invocation -> successfulOperation(requestHash.get(), resultJson.get()));
|
||||
when(repository.findInbound(10, 20)).thenReturn(new Snapshot(20L, 10L, "LOADING", 5));
|
||||
when(repository.completionTarget(10, 20)).thenReturn(new CompletionTarget(
|
||||
20L, null, 10L, "LOADING", 5, "LOADING", 5));
|
||||
LoadingPickItemMapper.InboundProgress progress = mock(LoadingPickItemMapper.InboundProgress.class);
|
||||
when(progress.getExpectedCount()).thenReturn(5);
|
||||
when(progress.getPickedCount()).thenReturn(5);
|
||||
when(progress.getTaskCount()).thenReturn(1);
|
||||
when(progress.getCompletedTaskCount()).thenReturn(1);
|
||||
when(progress.getUnresolvedCount()).thenReturn(0);
|
||||
when(loadingPicks.inboundProgress(10, 20)).thenReturn(progress);
|
||||
when(repository.listEvidence(10, 20)).thenReturn(List.of(
|
||||
evidence("PHOTO_STEP_1", 1L, null), evidence("PHOTO_STEP_2", 2L, null),
|
||||
evidence("PHOTO_STEP_3", 3L, null), evidence("PHOTO_STEP_4", 4L, null),
|
||||
evidence("SEAL", 5L, "LOCK-001")));
|
||||
when(files.validate(eq("token"), eq(10L), eq(20L), anyLong())).thenAnswer(invocation -> {
|
||||
long fileId = invocation.getArgument(3);
|
||||
String type = fileId == 5L ? "SEAL" : "PHOTO_STEP_" + fileId;
|
||||
return ApiResponse.success(new LoadingEvidenceFileClient.FileMetadata(
|
||||
fileId, type.toLowerCase() + ".png", "LOADING_" + type, "image/png"));
|
||||
});
|
||||
when(repository.completeLoadedChild(10, 20, 7, 5)).thenReturn(1);
|
||||
|
||||
LoadingActionResponse first = service.completeLoading(10, 20, 7, "admin", "slice-replay",
|
||||
new CompleteLoadingRequest(5, "完成"));
|
||||
LoadingActionResponse replay = service.completeLoading(10, 20, 7, "admin", "slice-replay",
|
||||
new CompleteLoadingRequest(5, "完成"));
|
||||
|
||||
assertThat(first.mainStatus()).isEqualTo("LOADED");
|
||||
assertThat(replay).isEqualTo(first);
|
||||
verify(repository, times(2)).claimOperation(eq(10L), eq(20L), eq(7L), eq("COMPLETE_LOADING"),
|
||||
eq("slice-replay"), anyString());
|
||||
verify(repository).completeLoadedChild(10, 20, 7, 5);
|
||||
verify(repository).aggregateRootLoaded(10, 10, 7);
|
||||
verify(loadingModelBridge).requireCompleted(10, 20);
|
||||
verify(completionGate).requireBookingTransportAndCustoms(10, 20);
|
||||
verify(histories).insert(any(InboundStatusHistoryEntity.class));
|
||||
verify(repository).completeOperation(10L, 20L, 7L, "COMPLETE_LOADING", "slice-replay", resultJson.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
void keepsHistoricalLoadedChildAsCompletionTarget() {
|
||||
CompletionTarget historical = new CompletionTarget(
|
||||
@@ -241,4 +300,12 @@ class LoadingDeliveryServiceTest {
|
||||
value.setEvidenceType(type); value.setFileId(fileId); value.setSealNo(sealNo);
|
||||
return value;
|
||||
}
|
||||
|
||||
private static LoadingOperationEntity successfulOperation(String requestHash, String resultJson) {
|
||||
LoadingOperationEntity value = new LoadingOperationEntity();
|
||||
value.setRequestHash(requestHash);
|
||||
value.setStatus("SUCCESS");
|
||||
value.setResultJson(resultJson);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user