修复PDA稳定柜次查询契约

This commit is contained in:
2026-08-12 18:20:11 +08:00
parent 5a1cd862c9
commit bac46a0f54
9 changed files with 113 additions and 3 deletions
@@ -12,7 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat;
class PlatformLoadingPdaControllerContractTest {
@Test
void exposesAssignmentWorkAndReviewWithDedicatedAuthorities() throws Exception {
authority("task", "platform:firstleg:pda:view", AuthenticatedUser.class, String.class, long.class);
authority("task", "platform:firstleg:pda:view", AuthenticatedUser.class, String.class, String.class, Long.class, long.class);
authority("pendingTasks", "platform:firstleg:pda:view", AuthenticatedUser.class, String.class);
authority("inventorySnapshot", "platform:firstleg:pda:view", AuthenticatedUser.class, long.class, long.class);
authority("claim", "platform:firstleg:pda:work", AuthenticatedUser.class, long.class, ClaimRequest.class);
@@ -10,7 +10,14 @@ import static org.assertj.core.api.Assertions.assertThat;
class PlatformSmartLoadingControllerContractTest {
@Test void draftQueriesUseListPermission() throws Exception {
authority("draftByBooking","platform:firstleg:smart-loading:list",AuthenticatedUser.class,long.class);
authority("detail","platform:firstleg:smart-loading:list",AuthenticatedUser.class,long.class);
authority("detail","platform:firstleg:smart-loading:list",AuthenticatedUser.class,long.class);
authority("candidates","platform:firstleg:smart-loading:list",AuthenticatedUser.class,long.class,long.class);
}
@Test void openApiRequiresBookingAndWarehouseForCandidates() throws Exception {
String yaml=java.nio.file.Files.readString(java.nio.file.Path.of("src/main/resources/openapi/firstleg-v1.yaml"));
assertThat(yaml).contains("/api/platform/v1/first-leg/smart-loading/candidates:")
.contains("name: bookingId, in: query, required: true")
.contains("name: warehouseId, in: query, required: true");
}
@Test void everyMutationDeclaresDedicatedPermission() throws Exception {
authority("assign","platform:firstleg:smart-loading:assign",AuthenticatedUser.class,long.class,AssignRequest.class);
@@ -0,0 +1,21 @@
package com.baiyue.firstleg.repository;
import com.baiyue.firstleg.mapper.LoadingPickTaskMapper;
import org.apache.ibatis.annotations.Select;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class LoadingPickStableLookupContractTest {
@Test void stableLookupsUseCabinetOrPlanAndNotMutableContainerIdentity() throws Exception {
String cabinet = LoadingPickTaskMapper.class.getMethod("selectLoadingByCabinet", String.class, long.class)
.getAnnotation(Select.class).value()[0];
String plan = LoadingPickTaskMapper.class.getMethod("selectLoadingByPlan", long.class, long.class)
.getAnnotation(Select.class).value()[0];
String legacy = LoadingPickTaskMapper.class.getMethod("selectLoadingByContainerAndAccount", String.class, long.class)
.getAnnotation(Select.class).value()[0];
assertThat(cabinet).contains("booking.cabinet_no=#{cabinetNo}").doesNotContain("task.container_no");
assertThat(plan).contains("task.loading_plan_id=#{loadingPlanId}").doesNotContain("task.container_no");
assertThat(legacy).contains("booking.container_no = #{containerNo}").doesNotContain("task.container_no =");
}
}
@@ -36,6 +36,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.times;
import static org.assertj.core.api.Assertions.assertThat;
@SpringJUnitConfig(LoadingPickService.class)
class LoadingPickServiceTest {
@@ -52,6 +53,49 @@ class LoadingPickServiceTest {
@Resource
private LoadingPickService service;
@Test
void stableCabinetAndPlanQueriesReturnSameTaskWithCurrentContainerNumber() {
LoadingPickTaskEntity task = task();
task.setContainerBookingId(40L); task.setCabinetNo("CAB-001");
var booking = new com.baiyue.firstleg.entity.ContainerBookingEntity();
booking.setId(40L); booking.setContainerNo("MSCU-NEW");
when(repository.taskByCabinet("CAB-001", 101L)).thenReturn(task);
when(repository.taskByPlan(10L, 101L)).thenReturn(task);
when(smartLoadingRepository.booking(40L)).thenReturn(booking);
when(repository.items(20L, 101L)).thenReturn(List.of());
when(repository.cartonLabels(20L)).thenReturn(List.of());
var byCabinet = service.task(null, "CAB-001", null, 101L);
var byPlan = service.task(null, null, 10L, 101L);
assertThat(byCabinet.id()).isEqualTo(20L);
assertThat(byPlan.id()).isEqualTo(20L);
assertThat(byCabinet.currentContainerNo()).isEqualTo("MSCU-NEW");
}
@Test
void rejectsMissingOrConflictingCompatibilitySelectors() {
assertThatThrownBy(() -> service.task(null, null, null, 101L))
.isInstanceOf(BizException.class).hasMessageContaining("必须且只能提供一个");
assertThatThrownBy(() -> service.task("MSCU", "CAB", null, 101L))
.isInstanceOf(BizException.class).hasMessageContaining("必须且只能提供一个");
}
@Test
void legacyContainerLookupReturnsCurrentTransportDisplayWithoutChangingIdentity() {
LoadingPickTaskEntity task = task(); task.setContainerBookingId(40L); task.setCabinetNo("CAB-001");
var booking = new com.baiyue.firstleg.entity.ContainerBookingEntity();
booking.setId(40L); booking.setContainerNo("MSCU-CURRENT");
when(repository.taskByContainer("MSCU-CURRENT", 101L)).thenReturn(task);
when(smartLoadingRepository.booking(40L)).thenReturn(booking);
when(repository.items(20L, 101L)).thenReturn(List.of());
when(repository.cartonLabels(20L)).thenReturn(List.of());
var result = service.task("MSCU-CURRENT", null, null, 101L);
assertThat(result.id()).isEqualTo(20L);
assertThat(result.loadingPlanId()).isEqualTo(10L);
assertThat(result.currentContainerNo()).isEqualTo("MSCU-CURRENT");
}
@Test
void keepsPlanLoadingWhenItemsRemain() {
LoadingPickTaskEntity task = task();