This commit is contained in:
2026-09-04 18:47:57 +08:00
parent 7c5ed85a36
commit 77817b4c94
20 changed files with 240 additions and 92 deletions
@@ -36,13 +36,13 @@ class PlatformSmartLoadingControllerContractTest {
.contains("name: warehouseId")
.contains("name: createdStart")
.contains("name: createdEnd")
.contains("name: expectedArrivalStart")
.contains("name: expectedArrivalEnd")
.contains("name: orderStatuses")
.contains("maxItems: 4")
.contains("PENDING_REVIEW, WAIT_MEASURE, WAIT_SPLIT, LOADING")
.contains("SmartLoadingInboundCandidatePageEnvelope")
.doesNotContain("name: orderStatus,")
.doesNotContain("name: expectedArrivalStart")
.doesNotContain("name: expectedArrivalEnd")
.doesNotContain("name: bookingId");
assertThat(yaml).contains("canAssign: {type: boolean, description: 当前是否可加入柜次");
}
@@ -85,8 +85,8 @@ class PlatformSmartLoadingControllerContractTest {
.contains("items[].version 是递增后的 itemVersion")
.contains("数量调整或动态增量不会覆盖已有 warehouseRemark")
.contains("柜内总容积和总重量分别允许达到柜型额定值的150%")
.contains("人工分配不限制订单渠道与柜次渠道一致")
.contains("渠道只约束智能推荐")
.contains("人工分配不限制订单国内仓及渠道与柜次一致")
.contains("智能推荐允许跨国内仓,但仍只选择柜次渠道")
.contains("canAssign: {type: boolean}")
.contains("canEdit: {type: boolean}")
.contains("pickedPackageCount: {type: integer, minimum: 0}")
@@ -39,7 +39,7 @@ class SmartLoadingCandidateMapperContractTest {
@Test
void selectsLatestApprovedBatch() throws Exception {
Method list = SmartLoadingCandidateMapper.class.getDeclaredMethod("candidates", long.class);
Method list = SmartLoadingCandidateMapper.class.getDeclaredMethod("candidates", Long.class);
String sql = String.join(" ", list.getAnnotation(Select.class).value());
assertThat(sql)
@@ -106,7 +106,7 @@ class SmartLoadingCandidateMapperContractTest {
}
@Test
void globalCandidateDateFilterUsesTheRepresentativeOrderCreationDate() throws Exception {
void globalCandidateDateFiltersUseRepresentativeCreationAndExpectedArrivalDates() throws Exception {
Method units = SmartLoadingCandidateMapper.class.getDeclaredMethod("globalCandidateUnits",
Page.class, InboundCandidateQuery.class, Set.class);
String sql = String.join(" ", units.getAnnotation(Select.class).value());
@@ -115,7 +115,8 @@ class SmartLoadingCandidateMapperContractTest {
.contains("o.created_at createdAt")
.contains("MIN(eligible.createdAt)>=#{query.createdStart}")
.contains("MIN(eligible.createdAt)<DATE_ADD(#{query.createdEnd},INTERVAL 1 DAY)")
.doesNotContain("query.expectedArrivalStart", "query.expectedArrivalEnd");
.contains("MIN(eligible.expectedArrivalAt)>=#{query.expectedArrivalStart}")
.contains("MIN(eligible.expectedArrivalAt)<DATE_ADD(#{query.expectedArrivalEnd},INTERVAL 1 DAY)");
}
@Test
@@ -146,6 +147,7 @@ class SmartLoadingCandidateMapperContractTest {
String unitScript = String.join(" ", units.getAnnotation(Select.class).value());
var query = new InboundCandidateQuery(List.of("MATSON_CLX"), 100L, 9L, "IN-",
java.time.LocalDate.parse("2026-09-01"), java.time.LocalDate.parse("2026-09-30"),
java.time.LocalDate.parse("2026-09-05"), java.time.LocalDate.parse("2026-10-05"),
List.of(com.baiyue.firstleg.dto.SmartLoadingDtos.CandidateOrderStatus.WAIT_MEASURE,
com.baiyue.firstleg.dto.SmartLoadingDtos.CandidateOrderStatus.WAIT_SPLIT), 1, 20);
String renderedUnits = driver.createSqlSource(configuration, unitScript, Map.class)
@@ -153,6 +155,7 @@ class SmartLoadingCandidateMapperContractTest {
assertThat(renderedUnits)
.contains("o.channel_code IN")
.contains("MIN(eligible.createdAt)>=", "MIN(eligible.createdAt)<DATE_ADD")
.contains("MIN(eligible.expectedArrivalAt)>=", "MIN(eligible.expectedArrivalAt)<DATE_ADD")
.contains("eligible.candidateStatus='WAIT_MEASURE'")
.contains("eligible.candidateStatus='WAIT_SPLIT'")
.contains("MAX(CASE WHEN LOWER(eligible.inboundCode)")
@@ -188,9 +191,9 @@ class SmartLoadingCandidateMapperContractTest {
}
@Test
void detailUsesSameBatchRule() throws Exception {
void detailUsesSameBatchRuleWithoutRestrictingTheCabinetWarehouse() throws Exception {
Method detail = SmartLoadingCandidateMapper.class.getDeclaredMethod(
"candidate", long.class, long.class, long.class, long.class);
"candidate", long.class, long.class, long.class);
String sql = String.join(" ", detail.getAnnotation(Select.class).value());
assertThat(sql)
@@ -199,7 +202,7 @@ class SmartLoadingCandidateMapperContractTest {
.contains("o.expected_arrival_at expectedArrivalAt")
.contains("m.status='APPROVED'")
.contains("SELECT MAX(m2.id)")
.contains("o.warehouse_id=#{warehouseId}")
.doesNotContain("o.warehouse_id=#{warehouseId}")
.contains("o.process_status='WAIT_SPLIT'")
.contains("o.process_status='LOADING'")
.contains("same_plan_item.loading_plan_id=#{planId}")
@@ -196,6 +196,7 @@ class SmartLoadingServiceTest {
"MATSON_MAX_TRUCK", "美森加班海卡");
InboundCandidateQuery query = new InboundCandidateQuery(
List.of("MATSON_CLX"), null, null, null, null, null,
null, null,
List.of(CandidateOrderStatus.WAIT_SPLIT), 1, 20);
CandidateUnit unit = new CandidateUnit(null, 9L, 10L, null, 10L);
when(repository.globalCandidateUnits(eq(query), anySet()))
@@ -219,14 +220,14 @@ class SmartLoadingServiceTest {
@Test
void combinesAllUnfinishedStatusesBeforeReturningTheRequestedPage() {
InboundCandidateQuery query = new InboundCandidateQuery(
List.of("EXX"), null, null, null, null, null, List.of(), 1, 20);
List.of("EXX"), null, null, null, null, null, null, null, List.of(), 1, 20);
var pending = new PendingReviewOrderClient.Row(31L, "O31", "I31", 9L, "客户",
100L, "EXX_TRUCK", "EXX海卡", 3, LocalDateTime.parse("2026-09-01T09:00:00"),
"PENDING_REVIEW");
LocalDateTime.parse("2026-09-08T09:00:00"), "PENDING_REVIEW");
when(pendingReviewOrders.page(anyString(), anyList(), isNull(), isNull(), isNull(),
isNull(), isNull(), anyList(), anyLong(), anyLong())).thenAnswer(invocation -> {
long page = invocation.getArgument(8);
long size = invocation.getArgument(9);
isNull(), isNull(), isNull(), isNull(), anyList(), anyLong(), anyLong())).thenAnswer(invocation -> {
long page = invocation.getArgument(10);
long size = invocation.getArgument(11);
return ApiResponse.success(new PageResult<>(page == 1 ? List.of(pending) : List.of(),
page, size, 1, 1));
});
@@ -256,13 +257,14 @@ class SmartLoadingServiceTest {
CandidateOrderStatus.WAIT_MEASURE, CandidateOrderStatus.WAIT_SPLIT,
CandidateOrderStatus.LOADING));
verify(pendingReviewOrders).page(anyString(), anyList(), isNull(), isNull(), isNull(),
isNull(), isNull(), anyList(), eq(1L), eq(20L));
isNull(), isNull(), isNull(), isNull(), anyList(), eq(1L), eq(20L));
}
@Test
void statusDoesNotBlockAssignmentButAnActiveContainerOccupationDoes() {
InboundCandidateQuery query = new InboundCandidateQuery(List.of("EXX"), null, null, null,
null, null, List.of(CandidateOrderStatus.WAIT_MEASURE, CandidateOrderStatus.LOADING), 1, 20);
null, null, null, null,
List.of(CandidateOrderStatus.WAIT_MEASURE, CandidateOrderStatus.LOADING), 1, 20);
Candidate waiting = withStatus(candidate(9L, 10L, 20L, 30L, 4), "WAIT_MEASURE", false);
Candidate loading = withStatus(candidate(19L, 11L, 21L, 31L, 0), "LOADING", true);
List<CandidateUnit> units = List.of(new CandidateUnit(null, 9L, 10L, null, 10L),
@@ -285,7 +287,7 @@ class SmartLoadingServiceTest {
@Test
void keepsAnOccupiedLoadingGroupAsOneNonAssignablePagingUnit() {
InboundCandidateQuery query = new InboundCandidateQuery(List.of("EXX"), null, null, null,
null, null, List.of(CandidateOrderStatus.LOADING), 1, 20);
null, null, null, null, List.of(CandidateOrderStatus.LOADING), 1, 20);
Candidate first = withStatus(withGroup(candidate(9L, 10L, 20L, 30L, 0), 2, 10),
"LOADING", true);
Candidate second = withStatus(withGroup(candidate(19L, 11L, 21L, 31L, 0), 2, 10),
@@ -310,15 +312,17 @@ class SmartLoadingServiceTest {
InboundCandidateQuery query = new InboundCandidateQuery(
List.of("EXX"), 193000000000200002L, null, "EXXHK2609020361",
LocalDate.parse("2026-09-02"), LocalDate.parse("2026-09-02"),
LocalDate.parse("2026-09-08"), LocalDate.parse("2026-09-09"),
List.of(CandidateOrderStatus.PENDING_REVIEW), 1, 20);
var row = new PendingReviewOrderClient.Row(2095052002489335810L, "FL-361",
"EXXHK2609020361", 2092797167699816450L, "客户", 193000000000200002L,
"EXX_TRUCK", "EXX海卡", 100, LocalDateTime.parse("2026-09-02T15:31:36"),
"PENDING_REVIEW");
LocalDateTime.parse("2026-09-08T10:00:00"), "PENDING_REVIEW");
when(repository.occupiedOrderIds(eq(query), anySet())).thenReturn(List.of(998L));
when(pendingReviewOrders.page(anyString(), anyList(), eq(193000000000200002L),
isNull(), eq("EXXHK2609020361"), eq("2026-09-02"),
eq("2026-09-02"), eq(List.of(998L)), eq(1L), eq(20L)))
eq("2026-09-02"), eq("2026-09-08"), eq("2026-09-09"),
eq(List.of(998L)), eq(1L), eq(20L)))
.thenReturn(ApiResponse.success(new PageResult<>(List.of(row), 1, 20, 1, 1)));
var result = service.inboundCandidates(query);
@@ -331,6 +335,7 @@ class SmartLoadingServiceTest {
assertThat(candidate.canAssign()).isTrue();
assertThat(candidate.blockReason()).isNull();
assertThat(candidate.availablePackageCount()).isEqualTo(100);
assertThat(candidate.expectedArrivalAt()).isEqualTo(LocalDateTime.parse("2026-09-08T10:00:00"));
});
verify(repository, never()).globalCandidateUnits(any(), anySet());
verify(repository, never()).globalCandidatesByUnits(anyList());
@@ -344,7 +349,7 @@ class SmartLoadingServiceTest {
String inboundCode = "EXXHK2609020361";
var pending = new PendingReviewOrderClient.Row(orderId, "FL-361", inboundCode,
customerId, "客户", 100L, "SLOW", "慢船", 5,
LocalDateTime.parse("2026-09-02T15:31:36"), "PENDING_REVIEW");
LocalDateTime.parse("2026-09-02T15:31:36"), null, "PENDING_REVIEW");
var snapshot = new com.baiyue.firstleg.dto.OrderApprovedInboundCommand(
customerId, orderId, "FL-361", inboundCode, customerId, "客户", 100L, "义乌仓",
null, null, null, "FIRST_LEG", "SLOW", "慢船", null, null, null,
@@ -354,7 +359,7 @@ class SmartLoadingServiceTest {
var cargo = new OrderCargoClient.CargoBinding(20L, orderId, 1, "货物", 5,
new BigDecimal("50"), new BigDecimal("2.5"));
when(pendingReviewOrders.page(anyString(), isNull(), isNull(), eq(customerId),
eq(inboundCode), isNull(), isNull(), isNull(), eq(1L), eq(2L)))
eq(inboundCode), isNull(), isNull(), isNull(), isNull(), isNull(), eq(1L), eq(2L)))
.thenReturn(ApiResponse.success(new PageResult<>(List.of(pending), 1, 2, 1, 1)));
when(cargoClient.inboundSnapshot(anyString(), eq(customerId), eq(orderId)))
.thenReturn(ApiResponse.success(snapshot));
@@ -430,19 +435,75 @@ class SmartLoadingServiceTest {
7L, "u", "wait-measure-1");
}
@Test
void assignsWaitSplitInboundToCabinetFromAnotherDomesticWarehouse() {
Candidate crossWarehouse = withWarehouse(candidate(1), 101L);
InboundOrderEntity projection = new InboundOrderEntity();
projection.setId(10L);
projection.setTenantId(9L);
projection.setWarehouseId(101L);
projection.setProcessStatus("WAIT_SPLIT");
AtomicInteger version = new AtomicInteger();
List<LoadingPlanItemEntity> saved = new ArrayList<>();
when(repository.inbound(10L)).thenReturn(projection);
when(repository.plan(1L)).thenAnswer(invocation -> plan("EDITING", version.get()));
when(repository.booking(99L)).thenReturn(booking());
when(repository.candidates(null)).thenReturn(List.of(crossWarehouse));
when(repository.candidate(1L, 10L, 20L)).thenReturn(crossWarehouse);
when(repository.activeItemsByInbound(1L, 9L, 10L)).thenReturn(List.of());
when(repository.activeItem(1L, 9L, 20L)).thenReturn(null);
when(repository.items(1L)).thenAnswer(invocation -> List.copyOf(saved));
when(repository.touch(eq(1L), anyInt(), eq(7L), eq("u"))).thenAnswer(invocation -> {
int expected = invocation.getArgument(1);
if (expected != version.get()) return 0;
version.incrementAndGet();
return 1;
});
doAnswer(invocation -> {
LoadingPlanItemEntity item = invocation.getArgument(0);
item.setId(800L);
saved.add(item);
return null;
}).when(repository).insert(any(LoadingPlanItemEntity.class));
Plan result = service.assignInbound(1L,
new AssignInboundRequest(10L, 1, 0, "assign-inbound-cross-warehouse"), 7L, "u");
assertThat(result.version()).isEqualTo(1);
assertThat(saved).singleElement().satisfies(item -> {
assertThat(item.getInboundId()).isEqualTo(10L);
assertThat(item.getPackageCount()).isEqualTo(1);
});
verify(repository).candidates(null);
}
@Test
void failsClosedWhenPendingReviewOrderSourceIsUnavailable() {
InboundCandidateQuery query = new InboundCandidateQuery(
List.of("EXX"), null, null, null, null, null,
null, null,
List.of(CandidateOrderStatus.PENDING_REVIEW), 1, 20);
when(pendingReviewOrders.page(anyString(), anyList(), isNull(), isNull(), isNull(),
isNull(), isNull(), anyList(), eq(1L), eq(20L))).thenThrow(new RuntimeException("offline"));
isNull(), isNull(), isNull(), isNull(), anyList(), eq(1L), eq(20L))).thenThrow(new RuntimeException("offline"));
assertThatThrownBy(() -> service.inboundCandidates(query))
.isInstanceOf(BizException.class)
.hasMessage("待审核订单服务暂时不可用");
}
@Test
void rejectsReversedExpectedArrivalRangeBeforeQueryingCandidates() {
InboundCandidateQuery query = new InboundCandidateQuery(
List.of("EXX"), null, null, null, null, null,
LocalDate.parse("2026-09-10"), LocalDate.parse("2026-09-09"),
List.of(CandidateOrderStatus.WAIT_SPLIT), 1, 20);
assertThatThrownBy(() -> service.inboundCandidates(query))
.isInstanceOf(BizException.class)
.hasMessage("预计到货开始日期不能晚于结束日期");
verify(repository, never()).globalCandidateUnits(any(), anySet());
}
@Test
void pagesWorkbenchContainersWithTheSameGlobalFilters() {
WorkbenchContainer container = new WorkbenchContainer(99L, "CB-1", "CAB-1", null,
@@ -473,7 +534,8 @@ class SmartLoadingServiceTest {
"MATSON_CLX_TRUCK", "美森正班海卡"), "2026-09-10T09:00:00"), 2, 10);
InboundCandidateQuery query = new InboundCandidateQuery(
List.of("MATSON_CLX"), 100L, null, null, LocalDate.parse("2026-09-01"),
LocalDate.parse("2026-09-01"), List.of(CandidateOrderStatus.WAIT_SPLIT), 1, 1);
LocalDate.parse("2026-09-01"), null, null,
List.of(CandidateOrderStatus.WAIT_SPLIT), 1, 1);
CandidateUnit unit = new CandidateUnit(700L, null, null,
LocalDateTime.parse("2026-09-01T09:00:00"), 10L);
when(repository.globalCandidateUnits(eq(query), anySet()))
@@ -495,6 +557,7 @@ class SmartLoadingServiceTest {
void excludesIncompleteColoadGroupInsteadOfPublishingPartialMember() {
InboundCandidateQuery query = new InboundCandidateQuery(
List.of("MATSON_CLX"), 100L, null, null, null, null,
null, null,
List.of(CandidateOrderStatus.WAIT_SPLIT), 1, 20);
when(repository.globalCandidateUnits(eq(query), anySet()))
.thenReturn(new PageResult<>(List.of(), 1, 20, 0, 0));
@@ -593,9 +656,9 @@ class SmartLoadingServiceTest {
when(repository.planByBooking(99L)).thenAnswer(invocation -> plan("EDITING", version.get()));
when(repository.booking(99L)).thenReturn(booking());
when(repository.inbound(10L)).thenReturn(inbound(9L, 10L));
when(repository.candidates(100L)).thenReturn(List.of(first, second));
when(repository.candidate(1L, 100L, 10L, 20L)).thenReturn(first);
when(repository.candidate(1L, 100L, 11L, 21L)).thenReturn(second);
when(repository.candidates(null)).thenReturn(List.of(first, second));
when(repository.candidate(1L, 10L, 20L)).thenReturn(first);
when(repository.candidate(1L, 11L, 21L)).thenReturn(second);
when(repository.items(1L)).thenAnswer(invocation -> List.copyOf(saved));
when(repository.activeItemsByInbound(anyLong(), anyLong())).thenReturn(List.of());
when(repository.activeItemsByInbound(anyLong(), anyLong(), anyLong())).thenReturn(List.of());
@@ -636,7 +699,7 @@ class SmartLoadingServiceTest {
org.mockito.ArgumentMatchers.startsWith("LOCK-"), eq(7L), eq("u"));
verify(loadingModelBridge, times(2)).bindIncrementalAllocation(eq(1L), anyLong(), anyLong(),
eq(7L), eq("u"), anyString());
verify(repository, times(1)).candidates(100L);
verify(repository, times(1)).candidates(null);
}
@Test
@@ -654,7 +717,7 @@ class SmartLoadingServiceTest {
when(repository.planByBooking(99L)).thenReturn(plan);
when(repository.booking(99L)).thenReturn(small);
when(repository.items(1L)).thenReturn(List.of());
when(repository.candidates(100L)).thenReturn(List.of(first, second, third));
when(repository.candidates(null)).thenReturn(List.of(first, second, third));
when(coloadGroups.findByInbound(anyLong(), anyLong())).thenReturn(group);
Plan result = service.recommend(1L, new RecommendRequest(0, "recommend-group-too-large"), 7L, "u");
@@ -681,9 +744,9 @@ class SmartLoadingServiceTest {
when(repository.planByBooking(99L)).thenAnswer(invocation -> plan("EDITING", version.get()));
when(repository.booking(99L)).thenReturn(small);
when(repository.items(1L)).thenAnswer(invocation -> List.copyOf(saved));
when(repository.candidates(100L)).thenReturn(List.of(ordinary, groupFirst, groupSecond, later));
when(repository.candidate(1L, 100L, 10L, 20L)).thenReturn(ordinary);
when(repository.candidate(1L, 100L, 13L, 23L)).thenReturn(later);
when(repository.candidates(null)).thenReturn(List.of(ordinary, groupFirst, groupSecond, later));
when(repository.candidate(1L, 10L, 20L)).thenReturn(ordinary);
when(repository.candidate(1L, 13L, 23L)).thenReturn(later);
when(repository.activeItemsByInbound(anyLong(), anyLong(), anyLong())).thenReturn(List.of());
when(repository.activeItem(anyLong(), anyLong(), anyLong())).thenReturn(null);
when(repository.touch(eq(1L), anyInt(), eq(7L), eq("u"))).thenAnswer(invocation -> {
@@ -732,7 +795,7 @@ class SmartLoadingServiceTest {
when(repository.booking(99L)).thenReturn(small);
when(repository.inbound(11L)).thenReturn(inbound(9L, 11L));
when(repository.items(1L)).thenReturn(List.of());
when(repository.candidates(100L)).thenReturn(List.of(first, second));
when(repository.candidates(null)).thenReturn(List.of(first, second));
when(repository.activeItemsByInbound(anyLong(), anyLong())).thenReturn(List.of());
when(coloadGroups.findByInbound(9L, 11L)).thenReturn(group);
when(coloadGroups.findByInbound(9L, 12L)).thenReturn(group);
@@ -1006,7 +1069,7 @@ class SmartLoadingServiceTest {
LoadingPlanEntity plan = plan("EDITING", 0);
when(repository.plan(1)).thenReturn(plan);
when(repository.booking(99L)).thenReturn(booking());
when(repository.candidate(1, 100, 10, 20)).thenReturn(candidate(5));
when(repository.candidate(1, 10, 20)).thenReturn(candidate(5));
when(repository.activeItem(1L, 9L, 20L)).thenReturn(item(7, 9, 20, 4));
BizException error = catchThrowableOfType(() -> service.assign(1,
@@ -1023,7 +1086,7 @@ class SmartLoadingServiceTest {
linked.setCustomerId(88L);
when(repository.plan(1L)).thenReturn(plan);
when(repository.booking(99L)).thenReturn(linked);
when(repository.candidate(1L, 100L, 10L, 20L)).thenReturn(candidate(5));
when(repository.candidate(1L, 10L, 20L)).thenReturn(candidate(5));
BizException error = catchThrowableOfType(() -> service.assign(1L,
new AssignRequest(10L, 20L, 1, 0, "assign-customer-mismatch"), 7L, "u"), BizException.class);
@@ -1032,6 +1095,20 @@ class SmartLoadingServiceTest {
verify(repository, never()).touch(anyLong(), anyInt(), anyLong(), any());
}
@Test
void manuallyAssignsCargoFromAnotherDomesticWarehouse() {
stubAssignment();
when(repository.candidate(1L, 10L, 20L)).thenReturn(
withWarehouse(candidate(10), 101L));
Plan result = service.assign(1L,
new AssignRequest(10L, 20L, 1, 0, "assign-cross-warehouse"), 7L, "u");
assertThat(result.version()).isEqualTo(1);
verify(repository).insert(any(LoadingPlanItemEntity.class));
verify(repository).touch(1L, 0, 7L, "u");
}
@Test
void allowsVolumeAndWeightWithinOneHundredFiftyPercent() {
stubAssignment();
@@ -1121,7 +1198,7 @@ class SmartLoadingServiceTest {
when(repository.booking(99)).thenReturn(booking());
when(repository.touch(1, 5, 7, "u")).thenReturn(1);
when(repository.items(1)).thenReturn(List.of());
when(repository.candidate(1, 100, 10, 20)).thenReturn(candidate(10));
when(repository.candidate(1, 10, 20)).thenReturn(candidate(10));
when(repository.activeItem(1L, 9L, 20L)).thenReturn(null);
when(loadingPickService.mutationSnapshot(1L)).thenReturn(
new LoadingPickService.MutationSnapshot(77L, "LOADING", 6, Map.of()));
@@ -1132,7 +1209,7 @@ class SmartLoadingServiceTest {
Plan result = service.assign(1, new AssignRequest(10L, 20L, 1, 5, "assign-loading"), 7, "u");
assertThat(result.status()).isEqualTo("LOADING");
verify(repository).candidate(1L, 100L, 10L, 20L);
verify(repository).candidate(1L, 10L, 20L);
var order = inOrder(loadingPickService, splitPreloadService, repository, loadingModelBridge);
order.verify(loadingPickService).lockMutable(1L);
order.verify(splitPreloadService).ensureForRunningLoadingAllocation(9L, 10L, 7L, "u");
@@ -1152,7 +1229,7 @@ class SmartLoadingServiceTest {
when(repository.booking(99)).thenReturn(booking());
when(repository.touch(1, 5, 7, "u")).thenReturn(1);
when(repository.items(1)).thenReturn(List.of());
when(repository.candidate(1, 100, 10, 20)).thenReturn(candidate(10));
when(repository.candidate(1, 10, 20)).thenReturn(candidate(10));
when(repository.activeItem(1L, 9L, 20L)).thenReturn(null);
when(loadingPickService.mutationSnapshot(1L)).thenReturn(
new LoadingPickService.MutationSnapshot(77L, "LOADING", 6, Map.of()));
@@ -1182,7 +1259,7 @@ class SmartLoadingServiceTest {
Plan result = service.assign(1, request, 7, "u");
assertThat(result.status()).isEqualTo("LOADING");
verify(repository, never()).candidate(anyLong(), anyLong(), anyLong(), anyLong());
verify(repository, never()).candidate(anyLong(), anyLong(), anyLong());
verify(cargoClient, never()).detail(anyString(), anyLong(), anyLong(), anyLong());
}
@@ -1401,7 +1478,7 @@ class SmartLoadingServiceTest {
when(repository.plan(1L)).thenReturn(plan, plan("LOADING", 3));
when(repository.item(1L, 8L)).thenReturn(line);
when(repository.booking(99L)).thenReturn(booking());
when(repository.candidate(1L, 100L, 10L, 20L)).thenReturn(candidate(10));
when(repository.candidate(1L, 10L, 20L)).thenReturn(candidate(10));
when(repository.items(1L)).thenReturn(List.of(line));
when(repository.touch(1L, 2, 7L, "u")).thenReturn(1);
when(repository.update(line)).thenReturn(1);
@@ -1420,7 +1497,7 @@ class SmartLoadingServiceTest {
when(repository.plan(1L)).thenReturn(plan, plan("LOADING", 94));
when(repository.item(1L, 8L)).thenReturn(line);
when(repository.booking(99L)).thenReturn(booking());
when(repository.candidate(1L, 100L, 10L, 20L)).thenReturn(candidate(-25));
when(repository.candidate(1L, 10L, 20L)).thenReturn(candidate(-25));
when(repository.items(1L)).thenReturn(List.of(line));
when(repository.touch(1L, 93, 7L, "u")).thenReturn(1);
when(repository.update(line)).thenReturn(1);
@@ -1439,7 +1516,7 @@ class SmartLoadingServiceTest {
when(repository.plan(1L)).thenReturn(plan, plan("LOADING", 3));
when(repository.item(1L, 8L)).thenReturn(line);
when(repository.booking(99L)).thenReturn(booking());
when(repository.candidate(1L, 100L, 10L, 20L)).thenReturn(candidate(10));
when(repository.candidate(1L, 10L, 20L)).thenReturn(candidate(10));
when(repository.items(1L)).thenReturn(List.of(line));
when(repository.touch(1L, 2, 7L, "u")).thenReturn(1);
when(repository.update(line)).thenReturn(1);
@@ -1462,7 +1539,7 @@ class SmartLoadingServiceTest {
when(repository.plan(1L)).thenReturn(plan);
when(repository.item(1L, 8L)).thenReturn(line);
when(repository.booking(99L)).thenReturn(booking());
when(repository.candidate(1L, 100L, 10L, 20L)).thenReturn(candidate(10));
when(repository.candidate(1L, 10L, 20L)).thenReturn(candidate(10));
when(repository.items(1L)).thenReturn(List.of(line));
Plan result = service.adjust(1L, 8L,
@@ -1488,7 +1565,7 @@ class SmartLoadingServiceTest {
new AdjustRequest(1, 2, 0, "adjust-picked"), 7L, "u"))
.hasMessageContaining("不能低于已拣货箱数");
verify(repository, never()).candidate(anyLong(), anyLong(), anyLong(), anyLong());
verify(repository, never()).candidate(anyLong(), anyLong(), anyLong());
verify(repository, never()).touch(anyLong(), anyInt(), anyLong(), anyString());
}
@@ -1550,7 +1627,7 @@ class SmartLoadingServiceTest {
when(repository.plan(1)).thenReturn(plan, plan("EDITING", 1));
when(repository.booking(99)).thenReturn(booking());
when(repository.items(1)).thenReturn(List.of());
when(repository.candidate(1, 100, 10, 20)).thenReturn(candidate(10));
when(repository.candidate(1, 10, 20)).thenReturn(candidate(10));
when(repository.activeItem(1L, 9L, 20L)).thenReturn(null);
when(repository.touch(1, 0, 7, "u")).thenReturn(1);
}
@@ -1622,6 +1699,16 @@ class SmartLoadingServiceTest {
value.orderStatusSnapshot(), value.expectedArrivalAt());
}
private static Candidate withWarehouse(Candidate value, long warehouseId) {
return new Candidate(value.accountId(), value.inboundId(), value.inboundDetailId(), value.orderId(),
value.orderNo(), value.inboundCode(), warehouseId, value.channelCode(), value.channelName(),
value.destinationWarehouseId(), value.destinationWarehouseCode(), value.destinationWarehouseName(),
value.customerName(), value.goodsName(), value.availablePackageCount(), value.unitGrossWeightKg(),
value.unitNetWeightKg(), value.unitVolumeCbm(), value.coLoadGroupId(), value.groupNo(),
value.memberCount(), value.groupTotalBoxes(), value.locked(), value.blockReason(),
value.orderStatusSnapshot(), value.expectedArrivalAt());
}
private static Candidate withArrival(Candidate value, String expectedArrivalAt) {
return new Candidate(value.accountId(), value.inboundId(), value.inboundDetailId(), value.orderId(),
value.orderNo(), value.inboundCode(), value.warehouseId(), value.channelCode(), value.channelName(),