test: cover loading reassignment and PDA completion gates
This commit is contained in:
+55
@@ -18,6 +18,10 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
@@ -328,6 +332,57 @@ class LoadingModelBridgeServiceTest {
|
||||
anyInt(), anyLong(), anyString());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(ints = {1, 3})
|
||||
void reassignAfterOneOrRepeatedFullRemovalsCanComplete(int removals) {
|
||||
Map<Long, PreloadLoadingPlanLinkEntity> links = new LinkedHashMap<>();
|
||||
Map<Long, Integer> quantities = new LinkedHashMap<>();
|
||||
Map<Long, String> statuses = new LinkedHashMap<>();
|
||||
when(repository.byPair(eq(10L), eq(20L), anyLong()))
|
||||
.thenAnswer(call -> links.get(call.getArgument(2, Long.class)));
|
||||
when(repository.allocatedPackages(eq(10L), eq(20L), anyLong()))
|
||||
.thenAnswer(call -> quantities.get(call.getArgument(2, Long.class)));
|
||||
when(repository.loadingPlan(anyLong())).thenAnswer(call -> {
|
||||
long plan = call.getArgument(0);
|
||||
return new LoadingPlanSnapshot(plan, plan + 100, "C" + plan, statuses.get(plan), 1);
|
||||
});
|
||||
when(repository.preload(10L, 20L)).thenReturn(new PreloadSnapshot(30L, 10L, 20L, "CONFIRMED", 1));
|
||||
doAnswer(call -> {
|
||||
PreloadLoadingPlanLinkEntity link = call.getArgument(0);
|
||||
links.put(link.getLoadingPlanId(), link);
|
||||
return null;
|
||||
}).when(repository).insert(any());
|
||||
doAnswer(call -> {
|
||||
PreloadLoadingPlanLinkEntity link = call.getArgument(0);
|
||||
links.remove(link.getLoadingPlanId());
|
||||
return null;
|
||||
}).when(repository).delete(any());
|
||||
when(repository.byInbound(10L, 20L)).thenAnswer(call -> links.keySet().stream()
|
||||
.map(plan -> new Link(plan, 10L, 20L, 30L, "CONFIRMED", 1, plan, plan + 100,
|
||||
"C" + plan, statuses.get(plan), 1, quantities.get(plan), LocalDateTime.now())).toList());
|
||||
|
||||
for (long plan = 40; plan < 40 + removals; plan++) {
|
||||
quantities.put(plan, 8);
|
||||
statuses.put(plan, "EDITING");
|
||||
service.bindIncrementalAllocation(plan, 10L, 20L, 7L, "admin", "assign-" + plan);
|
||||
assertThat(links).containsKey(plan);
|
||||
quantities.put(plan, 3);
|
||||
service.removeIfUnallocated(plan, 10L, 20L);
|
||||
assertThat(links).containsKey(plan);
|
||||
quantities.put(plan, 0);
|
||||
service.removeIfUnallocated(plan, 10L, 20L);
|
||||
assertThat(links).isEmpty();
|
||||
}
|
||||
quantities.put(90L, 8);
|
||||
statuses.put(90L, "LOADING");
|
||||
service.bindIncrementalAllocation(90L, 10L, 20L, 7L, "admin", "assign-final");
|
||||
service.requireStarted(10L, 20L);
|
||||
statuses.put(90L, "COMPLETED");
|
||||
service.requireCompleted(10L, 20L);
|
||||
assertThat(links).containsOnlyKeys(90L);
|
||||
verify(repository, times(removals)).delete(any());
|
||||
}
|
||||
|
||||
private static Link link(String preloadStatus, int preloadVersion, String loadingStatus,
|
||||
int loadingVersion, int packages) {
|
||||
return new Link(1L, 10L, 20L, 30L, preloadStatus, preloadVersion, 40L, 50L, "C1",
|
||||
|
||||
+35
@@ -55,6 +55,7 @@ class LoadingDeliveryServiceTest {
|
||||
|
||||
@Test
|
||||
void pdaFinalizeUsesSourceVersionIncrementedByFullSettlement() throws Exception {
|
||||
useRealBridgeWithRemovedAndCurrentAllocations(0);
|
||||
Snapshot refreshed = new Snapshot(20L, 10L, "LOADING", 8);
|
||||
when(repository.completionTarget(10L, 20L)).thenReturn(null);
|
||||
when(repository.findInboundForUpdate(10L, 20L)).thenReturn(refreshed);
|
||||
@@ -66,11 +67,45 @@ class LoadingDeliveryServiceTest {
|
||||
when(repository.completeLoading(10L, 20L, 9L, 8)).thenReturn(1);
|
||||
when(objectMapper.writeValueAsString(org.mockito.ArgumentMatchers.any())).thenReturn("result");
|
||||
|
||||
service.requirePdaCompletionReady(10L, 20L);
|
||||
service.completeAfterPdaSettlement(10L, 20L, 9L, "operator", "pda-full", "done");
|
||||
|
||||
verify(repository).completeLoading(10L, 20L, 9L, 8);
|
||||
}
|
||||
|
||||
@Test
|
||||
void pdaPreflightBlocksAnUnstartedContainerWithRealAllocationBeforeAnyCompletionWrite() {
|
||||
useRealBridgeWithRemovedAndCurrentAllocations(3);
|
||||
when(repository.findInbound(10L, 20L)).thenReturn(new Snapshot(20L, 10L, "LOADING", 8));
|
||||
|
||||
assertThatThrownBy(() -> service.requirePdaCompletionReady(10L, 20L))
|
||||
.hasMessageContaining("关联柜次尚未全部开始装柜");
|
||||
|
||||
verify(repository, never()).completeLoading(
|
||||
org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyLong(),
|
||||
org.mockito.ArgumentMatchers.anyLong(), org.mockito.ArgumentMatchers.anyInt());
|
||||
verify(completionGate, never()).requireReleasedBooking(10L, 20L);
|
||||
}
|
||||
|
||||
/** Exercise the production bridge gate, rather than mocking its decision. */
|
||||
private void useRealBridgeWithRemovedAndCurrentAllocations(int oldContainerPackages) {
|
||||
var bridgeRepository = org.mockito.Mockito.mock(
|
||||
com.baiyue.firstleg.loading.bridge.repository.LoadingModelBridgeRepository.class);
|
||||
var realBridge = new LoadingModelBridgeService();
|
||||
org.springframework.test.util.ReflectionTestUtils.setField(realBridge, "repository", bridgeRepository);
|
||||
when(bridgeRepository.byInbound(10L, 20L)).thenReturn(java.util.List.of(
|
||||
new com.baiyue.firstleg.loading.bridge.dto.LoadingModelBridgeDtos.Link(
|
||||
1L, 10L, 20L, 30L, "CONFIRMED", 1, 40L, 50L, null,
|
||||
"EDITING", 1, oldContainerPackages, java.time.LocalDateTime.now()),
|
||||
new com.baiyue.firstleg.loading.bridge.dto.LoadingModelBridgeDtos.Link(
|
||||
2L, 10L, 20L, 30L, "CONFIRMED", 1, 41L, 99L, "C1",
|
||||
"LOADING", 1, 2, java.time.LocalDateTime.now())));
|
||||
org.mockito.Mockito.doAnswer(call -> {
|
||||
realBridge.requireStarted(10L, 20L);
|
||||
return null;
|
||||
}).when(loadingModelBridge).requireStarted(10L, 20L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void pdaFinalizeLocksAndUsesLoadedSliceVersionAfterPartialSettlement() throws Exception {
|
||||
var target = new com.baiyue.firstleg.loading.mapper.LoadingInboundMapper.CompletionTarget(
|
||||
|
||||
Reference in New Issue
Block a user