This commit is contained in:
2026-08-21 17:07:34 +08:00
parent 34fb91baf6
commit 598749d8e4
7 changed files with 204 additions and 0 deletions
@@ -12,6 +12,7 @@ class PlatformSmartLoadingControllerContractTest {
authority("draftByBooking","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);
authority("inboundCandidates","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"));
@@ -21,6 +22,7 @@ class PlatformSmartLoadingControllerContractTest {
}
@Test void everyMutationDeclaresDedicatedPermission() throws Exception {
authority("assign","platform:firstleg:smart-loading:assign",AuthenticatedUser.class,long.class,AssignRequest.class);
authority("assignInbound","platform:firstleg:smart-loading:assign",AuthenticatedUser.class,long.class,AssignInboundRequest.class);
authority("recommend","platform:firstleg:smart-loading:assign",AuthenticatedUser.class,long.class,RecommendRequest.class);
authority("adjust","platform:firstleg:smart-loading:assign",AuthenticatedUser.class,long.class,long.class,AdjustRequest.class);
authority("warehouseRemark","platform:firstleg:preload:edit",AuthenticatedUser.class,long.class,long.class,WarehouseRemarkRequest.class);
@@ -41,6 +43,8 @@ class PlatformSmartLoadingControllerContractTest {
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/plans/{planId}/assignments:")
.contains("/api/platform/v1/first-leg/smart-loading/plans/{planId}/inbound-assignments:")
.contains("SmartLoadingInboundAssignRequest:")
.contains("/api/platform/v1/first-leg/smart-loading/plans/{planId}/items/{itemId}:")
.contains("SmartLoadingAssignRequest:")
.contains("SmartLoadingAdjustRequest:")
@@ -104,6 +104,49 @@ class SmartLoadingServiceTest {
assertThat(service.draftByBooking(99L).status()).isEqualTo("LOADING");
}
@Test
void groupsCandidateSpecificationsByInboundCodeForQuantityOnlyPlanning() {
Candidate first = new Candidate(9L, 10L, 20L, 30L, "O", "I", 100L,
"FBA", "FBA渠道", 200L, "FBA1", "FBA仓", "客户", "服装", 3,
new BigDecimal("2"), new BigDecimal("1.5"), new BigDecimal("0.2"));
Candidate second = new Candidate(9L, 10L, 21L, 30L, "O", "I", 100L,
"FBA", "FBA渠道", 200L, "FBA1", "FBA仓", "客户", "鞋类", 7,
new BigDecimal("2"), new BigDecimal("1.5"), new BigDecimal("0.5"));
when(repository.booking(99L)).thenReturn(booking());
when(repository.candidates(100L)).thenReturn(List.of(first, second));
var result = service.inboundCandidates(99L, 100L);
assertThat(result).singleElement().satisfies(candidate -> {
assertThat(candidate.inboundCode()).isEqualTo("I");
assertThat(candidate.goodsSummary()).isEqualTo("服装、鞋类");
assertThat(candidate.availablePackageCount()).isEqualTo(10);
assertThat(candidate.averageUnitVolumeCbm()).isEqualByComparingTo("0.410000");
assertThat(candidate.availableVolumeCbm()).isEqualByComparingTo("4.1000");
assertThat(candidate.unitGrossWeightKg()).isEqualByComparingTo("2");
});
}
@Test
void proportionallyDistributesInboundQuantityWithoutLosingCartons() {
Candidate first = new Candidate(9L, 10L, 20L, 30L, "O", "I", 100L,
"FBA", "FBA渠道", 200L, "FBA1", "FBA仓", "客户", "A", 30,
new BigDecimal("2"), new BigDecimal("1.5"), new BigDecimal("0.2"));
Candidate second = new Candidate(9L, 10L, 21L, 30L, "O", "I", 100L,
"FBA", "FBA渠道", 200L, "FBA1", "FBA仓", "客户", "B", 40,
new BigDecimal("2"), new BigDecimal("1.5"), new BigDecimal("0.5"));
Candidate third = new Candidate(9L, 10L, 22L, 30L, "O", "I", 100L,
"FBA", "FBA渠道", 200L, "FBA1", "FBA仓", "客户", "C", 30,
new BigDecimal("2"), new BigDecimal("1.5"), new BigDecimal("0.8"));
var result = service.proportionalAllocations(List.of(first, second, third), 60);
assertThat(result).extracting(SmartLoadingService.InboundAllocation::packageCount)
.containsExactly(18, 24, 18);
assertThat(result).extracting(SmartLoadingService.InboundAllocation::candidate)
.extracting(Candidate::inboundDetailId).containsExactly(20L, 21L, 22L);
}
@Test
void exposesPickedMinimumAndItemCapabilitiesForRunningTask() {
LoadingPlanEntity plan = plan("LOADING", 3);