This commit is contained in:
2026-08-15 11:51:15 +08:00
parent 46cb95db15
commit 08187363a1
16 changed files with 203 additions and 39 deletions
@@ -4,6 +4,8 @@ import com.baiyue.firstleg.loading.bridge.dto.LoadingModelBridgeDtos.BindRequest
import com.baiyue.firstleg.loading.bridge.dto.LoadingModelBridgeDtos.Link;
import com.baiyue.firstleg.loading.bridge.mapper.LoadingModelBridgeMapper.LoadingPlanSnapshot;
import com.baiyue.firstleg.loading.bridge.mapper.LoadingModelBridgeMapper.PreloadSnapshot;
import com.baiyue.firstleg.loading.bridge.mapper.LoadingModelBridgeMapper.AllocationScope;
import com.baiyue.firstleg.loading.bridge.entity.PreloadLoadingPlanLinkEntity;
import com.baiyue.firstleg.loading.bridge.repository.LoadingModelBridgeRepository;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -42,6 +44,53 @@ class LoadingModelBridgeServiceTest {
verify(repository).touchLoadingPlan(40, 3, 7, "admin");
}
@Test
void bindsEveryAllocatedInboundBeforeLoadingStarts() {
when(repository.loadingPlan(40)).thenReturn(new LoadingPlanSnapshot(40L, 50L, "C1", "EDITING", 3));
when(repository.allocatedScopes(40)).thenReturn(List.of(new AllocationScope(10L, 20L, 8)));
when(repository.preload(10, 20)).thenReturn(new PreloadSnapshot(30L, 10L, 20L, "PENDING", 2));
when(repository.allocatedPackages(10, 20, 40)).thenReturn(8);
when(repository.touchPreload(30, 10, 20, 2, 7, "admin")).thenReturn(1);
when(repository.touchLoadingPlan(40, 3, 7, "admin")).thenReturn(1);
Link linked = link("PENDING", 3, "EDITING", 4, 8);
when(repository.byInbound(10, 20)).thenReturn(List.of(linked));
when(repository.byLoadingPlan(40)).thenReturn(List.of(linked));
List<Link> result = service.bindAllocatedBeforeLoading(40, 7, "admin", "push-1");
assertThat(result).containsExactly(linked);
verify(repository).insert(any());
verify(repository).touchPreload(30, 10, 20, 2, 7, "admin");
verify(repository).touchLoadingPlan(40, 3, 7, "admin");
}
@Test
void refusesPostHocBindingAfterLoadingStarts() {
when(repository.loadingPlan(40)).thenReturn(new LoadingPlanSnapshot(40L, 50L, "C1", "LOADING", 4));
when(repository.allocatedScopes(40)).thenReturn(List.of(new AllocationScope(10L, 20L, 8)));
assertThatThrownBy(() -> service.bindAllocatedBeforeLoading(40, 7, "admin", "push-1"))
.hasMessageContaining("禁止在LOADING后补关联");
verify(repository, never()).insert(any());
}
@Test
void loadingReplayOnlyReadsAlreadyCompleteLinks() {
when(repository.loadingPlan(40)).thenReturn(new LoadingPlanSnapshot(40L, 50L, "C1", "LOADING", 4));
when(repository.allocatedScopes(40)).thenReturn(List.of(new AllocationScope(10L, 20L, 8)));
PreloadLoadingPlanLinkEntity existing = new PreloadLoadingPlanLinkEntity();
when(repository.byPair(10, 20, 40)).thenReturn(existing);
Link linked = link("PENDING", 3, "LOADING", 4, 8);
when(repository.byLoadingPlan(40)).thenReturn(List.of(linked));
assertThat(service.bindAllocatedBeforeLoading(40, 7, "admin", "push-1"))
.containsExactly(linked);
verify(repository, never()).insert(any());
verify(repository, never()).touchLoadingPlan(anyLong(), anyInt(), anyLong(), anyString());
}
@Test
void secondVersionConflictDoesNotProceedAsSuccess() {
when(repository.preload(10, 20)).thenReturn(new PreloadSnapshot(30L, 10L, 20L, "PENDING", 2));
@@ -15,6 +15,7 @@ import com.baiyue.firstleg.entity.LoadingPlanEntity;
import com.baiyue.firstleg.entity.LoadingPlanHistoryEntity;
import com.baiyue.firstleg.entity.LoadingPlanItemEntity;
import com.baiyue.firstleg.repository.SmartLoadingRepository;
import com.baiyue.firstleg.loading.bridge.service.LoadingModelBridgeService;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.FeignException;
import jakarta.annotation.Resource;
@@ -41,6 +42,8 @@ import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -51,6 +54,7 @@ class SmartLoadingServiceTest {
@MockBean private SmartLoadingRepository repository;
@MockBean private OrderCargoClient cargoClient;
@MockBean private LoadingPickService loadingPickService;
@MockBean private LoadingModelBridgeService loadingModelBridge;
@Resource private SmartLoadingService service;
@TestConfiguration
@@ -384,6 +388,29 @@ class SmartLoadingServiceTest {
assertThat(result.status()).isEqualTo("EDITING");
verify(repository).push(1, "key", 3, 7, "u");
var ordered = inOrder(loadingModelBridge, loadingPickService);
ordered.verify(loadingModelBridge).bindAllocatedBeforeLoading(1, 7, "u", "key");
ordered.verify(loadingPickService).beginIfReady(99, 7, "u");
}
@Test
void rollsBackPushOrchestrationBeforePdaWhenBindingFails() {
LoadingPlanEntity editing = plan("EDITING", 3);
LoadingPlanEntity pushed = plan("EDITING", 4);
pushed.setPushIdempotencyKey("key");
when(repository.plan(1)).thenReturn(editing, pushed);
when(repository.items(1)).thenReturn(List.of(item(8, 9, 20, 1)));
when(repository.booking(99)).thenReturn(booking());
when(repository.push(1, "key", 3, 7, "u")).thenReturn(1);
doThrow(new BizException(ResultCode.CONFLICT, "预装计划不存在"))
.when(loadingModelBridge).bindAllocatedBeforeLoading(1, 7, "u", "key");
BizException error = catchThrowableOfType(
() -> service.pushPreload(1, "key", new PushRequest(3), 7, "u"), BizException.class);
assertThat(error.getMessage()).contains("预装计划不存在");
verify(repository).push(1, "key", 3, 7, "u");
verify(loadingPickService, never()).beginIfReady(anyLong(), anyLong(), anyString());
}
@Test