装柜修改

This commit is contained in:
2026-08-11 14:24:05 +08:00
parent bf7c214908
commit cb30839945
24 changed files with 242 additions and 48 deletions
@@ -35,6 +35,7 @@ class ContainerControllerContractTest {
.contains("/api/platform/v1/containers/{id}/transport:")
.contains("platform:firstleg:container:list")
.contains("EDITING")
.contains("WAIT_LOADING")
.contains("LOADING")
.contains("COMPLETED")
.doesNotContain("tenantId")
@@ -24,7 +24,10 @@ class ContainerBookingMapperContractTest {
assertThat(select)
.contains("fl_loading_plan")
.contains("p.id AS plan_id")
.contains("CASE WHEN p.id IS NULL THEN 'WAIT_LOADING'")
.contains("plan_status")
.contains("p.plan_status != 'COMPLETED'")
.doesNotContain("<>")
.doesNotContain("tenant_id")
.doesNotContain("account_id");
}
@@ -34,7 +34,9 @@ class LoadingListQueryMapperContractTest {
.contains("FROM fl_loading_plan p")
.contains("JOIN fl_container_booking b")
.contains("LEFT JOIN fl_loading_plan_item i")
.contains("p.plan_status = 'LOADING'")
.contains("p.preload_pushed_at IS NOT NULL")
.contains("p.plan_status IN ('EDITING', 'LOADING')")
.contains("active_item.deleted = 0")
.contains("b.warehouse_id = #{query.warehouseId}")
.doesNotContain("query.accountId")
.doesNotContain("PRELOAD_PUSHED");
@@ -110,6 +110,8 @@ class SmartLoadingSqlContractTest {
.contains("CHECK (plan_status IN ('EDITING', 'LOADING', 'COMPLETED'))")
.contains("OLD.plan_status = 'EDITING' AND NEW.plan_status IN ('EDITING', 'LOADING')")
.contains("NEW.plan_status IN ('LOADING', 'COMPLETED')")
.contains("OLD.plan_status = 'LOADING' AND NEW.plan_status = 'EDITING'")
.contains("旧版本在推送预装时即写入 LOADING")
.contains("SET MESSAGE_TEXT = '装柜状态只允许单向推进'")
.contains("IF OLD.plan_status = 'EDITING' AND NEW.plan_status = 'LOADING' THEN")
.contains("ELSEIF OLD.plan_status = 'LOADING' AND NEW.plan_status = 'COMPLETED' THEN")
@@ -56,7 +56,7 @@ class ContainerServiceTest {
assertThat(saved.getWarehouseName()).isEqualTo("上海中转仓");
assertThat(saved.getDeparturePortCode()).isEqualTo("CNSHA");
assertThat(saved.getCapacityCbm()).isEqualByComparingTo("68.0000");
assertThat(saved.getPlanStatus()).isEqualTo("EDITING");
assertThat(saved.getPlanStatus()).isEqualTo("WAIT_LOADING");
}
@Test
@@ -73,6 +73,20 @@ class ContainerServiceTest {
verify(repository).updateDraft(current, 2, 9L, "admin");
}
@Test
@DisplayName("待装柜阶段允许完整编辑")
void updatesAllFieldsWhileWaitingForLoading() {
ContainerBookingEntity current = booking("WAIT_LOADING", 2);
when(repository.find(11L)).thenReturn(current);
when(repository.updateDraft(any(), org.mockito.ArgumentMatchers.eq(2),
org.mockito.ArgumentMatchers.eq(9L), org.mockito.ArgumentMatchers.eq("admin"))).thenReturn(1);
service.updateDraft(11L, 9L, "admin", new FullUpdateRequest(2, request("柜 NEW")));
assertThat(current.getCabinetNo()).isEqualTo("柜 NEW");
verify(repository).updateDraft(current, 2, 9L, "admin");
}
@Test
@DisplayName("进入预装柜中后拒绝完整编辑")
void rejectsFullUpdateAfterPreloadPush() {
@@ -50,13 +50,12 @@ class LoadingListServiceTest {
}
@Test
void shouldRejectEditingStatusFromPreloadList() {
void shouldAcceptEditingStatusFromPreloadList() {
PreloadQuery query = new PreloadQuery(null, "EDITING", 100L, null, null, 1, 20);
assertThatThrownBy(() -> service.preloadPage(query))
.isInstanceOf(BizException.class)
.extracting(error -> ((BizException) error).getResultCode())
.isEqualTo(ResultCode.BAD_REQUEST);
service.preloadPage(query);
verify(repository).preloadPage(query);
}
@Test
@@ -13,6 +13,7 @@ import com.baiyue.firstleg.entity.LoadingPickItemEntity;
import com.baiyue.firstleg.entity.LoadingPickOperationEntity;
import com.baiyue.firstleg.entity.LoadingPickTaskEntity;
import com.baiyue.firstleg.repository.LoadingPickRepository;
import com.baiyue.firstleg.repository.SmartLoadingRepository;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.mockito.InOrder;
@@ -36,6 +37,8 @@ class LoadingPickServiceTest {
@MockBean
private LoadingPickRepository repository;
@MockBean
private SmartLoadingRepository smartLoadingRepository;
@MockBean
private LoadingListService loadingListService;
@MockBean
private PdaPickSettlementService settlementService;
@@ -75,6 +78,20 @@ class LoadingPickServiceTest {
verify(repository).insert(any(LoadingPickHistoryEntity.class));
}
@Test
void startsLoadingOnlyAfterTheFirstActualPick() {
LoadingPickTaskEntity task = task();
LoadingPickItemEntity item = item();
preparePick(task, item, "pick-start-loading");
when(smartLoadingRepository.startPicking(10L, 9L, "operator")).thenReturn(1);
service.pick(20L, 30L, new PickRequest(101L, 2, List.of(), 0, "pick-start-loading"),
9L, "operator");
verify(smartLoadingRepository).startPicking(10L, 9L, "operator");
verify(smartLoadingRepository).insert(any(com.baiyue.firstleg.entity.LoadingPlanHistoryEntity.class));
}
@Test
void touchesTaskBeforeCompletingLastPartialItem() {
LoadingPickTaskEntity task = task();
@@ -202,6 +202,28 @@ class SmartLoadingServiceTest {
assertThat(captor.getValue().getProductQuantity()).isEqualTo(67);
}
@Test
void recyclesLegacyLoadingPlanBeforeAddingFirstItem() {
LoadingPlanEntity stale = plan("LOADING", 5);
LoadingPlanEntity after = plan("EDITING", 7);
when(repository.plan(1)).thenReturn(stale, after);
when(repository.booking(99)).thenReturn(booking());
when(repository.recycleUnpicked(1, 5, 7, "u")).thenReturn(1);
when(repository.touch(1, 6, 7, "u")).thenReturn(1);
when(repository.items(1)).thenReturn(List.of());
when(repository.candidate(100, 10, 20)).thenReturn(candidate(10));
when(repository.activeItem(1L, 9L, 20L)).thenReturn(null);
when(cargoClient.detail(anyString(), anyLong(), anyLong(), anyLong())).thenReturn(ApiResponse.success(
new OrderCargoClient.CargoBinding(20L, 30L, 1, "货物", 1,
BigDecimal.ONE, BigDecimal.ONE, null, null, null, null, null, null)));
Plan result = service.assign(1, new AssignRequest(10L, 20L, 1, 5, "assign-recycle"), 7, "u");
assertThat(result.status()).isEqualTo("EDITING");
verify(repository).recycleUnpicked(1, 5, 7, "u");
verify(repository).touch(1, 6, 7, "u");
}
@Test
void replaysBeforeVersionCheck() {
AssignRequest request = new AssignRequest(10L, 20L, 2, 0, "assign-replay");
@@ -335,7 +357,7 @@ class SmartLoadingServiceTest {
@Test
void pushesIdempotently() {
LoadingPlanEntity editing = plan("EDITING", 3);
LoadingPlanEntity pushed = plan("LOADING", 4);
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)));
@@ -344,7 +366,7 @@ class SmartLoadingServiceTest {
Plan result = service.pushPreload(1, "key", new PushRequest(3), 7, "u");
assertThat(result.status()).isEqualTo("LOADING");
assertThat(result.status()).isEqualTo("EDITING");
verify(repository).push(1, "key", 3, 7, "u");
}
@@ -373,7 +395,7 @@ class SmartLoadingServiceTest {
@Test
void pushesWithoutContainerNumberWhenCapacityIsWithinLimit() {
LoadingPlanEntity editing = plan("EDITING", 1);
LoadingPlanEntity pushed = plan("LOADING", 2);
LoadingPlanEntity pushed = plan("EDITING", 2);
ContainerBookingEntity booking = booking();
booking.setContainerNo(null);
when(repository.plan(1)).thenReturn(editing, pushed);
@@ -383,7 +405,7 @@ class SmartLoadingServiceTest {
Plan result = service.pushPreload(1, "no-container-key", new PushRequest(1), 7, "u");
assertThat(result.status()).isEqualTo("LOADING");
assertThat(result.status()).isEqualTo("EDITING");
verify(repository).push(1, "no-container-key", 1, 7, "u");
verify(loadingPickService, never()).begin(anyLong(), any(), anyLong(), anyString(), anyList());
}
@@ -8,9 +8,11 @@ import static org.assertj.core.api.Assertions.assertThat;
class SmartLoadingStatusTest {
@Test
void statusCanOnlyAdvanceOneWay() {
assertThat(SmartLoadingStatus.WAIT_LOADING.canAdvanceTo(SmartLoadingStatus.EDITING)).isTrue();
assertThat(SmartLoadingStatus.EDITING.canAdvanceTo(SmartLoadingStatus.LOADING)).isTrue();
assertThat(SmartLoadingStatus.LOADING.canAdvanceTo(SmartLoadingStatus.COMPLETED)).isTrue();
assertThat(SmartLoadingStatus.COMPLETED.canAdvanceTo(SmartLoadingStatus.LOADING)).isFalse();
assertThat(SmartLoadingStatus.WAIT_LOADING.mutable()).isTrue();
assertThat(SmartLoadingStatus.EDITING.mutable()).isTrue();
assertThat(SmartLoadingStatus.LOADING.mutable()).isTrue();
assertThat(SmartLoadingStatus.LOADING.allowsTransportUpdate()).isTrue();