Merge remote-tracking branch 'origin/test' into dev
This commit is contained in:
+8
@@ -78,5 +78,13 @@ class PlatformSmartLoadingControllerContractTest {
|
||||
.contains("回到 IN_PROGRESS")
|
||||
.contains("COMPLETED 永久拒绝增量");
|
||||
}
|
||||
@Test void planContractEmbedsColoadGroupsWithoutPerInboundFanout() throws Exception {
|
||||
String yaml=java.nio.file.Files.readString(java.nio.file.Path.of("src/main/resources/openapi/firstleg-v1.yaml"));
|
||||
assertThat(yaml)
|
||||
.contains("required: [id, planNo, status, bookingId, version, canAssign, canEdit, finalCompletionStatus, coLoadGroups, items]")
|
||||
.contains("SmartLoadingPlanCoLoadGroup:")
|
||||
.contains("required: [groupId, groupNo, lockedPlanId, memberOrderCount, inboundFragmentCount, fullPackageCount, memberInboundIds]")
|
||||
.contains("调用方不得按 inboundId 扇出重建");
|
||||
}
|
||||
private void authority(String method,String permission,Class<?>...types)throws Exception{Method m=PlatformSmartLoadingController.class.getDeclaredMethod(method,types);assertThat(m.getAnnotation(PreAuthorize.class).value()).isEqualTo("hasAuthority('"+permission+"')");}
|
||||
}
|
||||
|
||||
+60
-1
@@ -14,6 +14,8 @@ import com.baiyue.firstleg.dto.SmartLoadingDtos.WorkbenchContainerQuery;
|
||||
import com.baiyue.firstleg.dto.SmartLoadingDtos.InboundCandidateQuery;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -98,6 +100,39 @@ class SmartLoadingCandidateMapperContractTest {
|
||||
.doesNotContain("fl_container_booking");
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalCandidateDateFilterUsesTheSameRepresentativeArrivalAsTheReturnedUnit() throws Exception {
|
||||
Method units = SmartLoadingCandidateMapper.class.getDeclaredMethod("globalCandidateUnits",
|
||||
Page.class, InboundCandidateQuery.class, Set.class);
|
||||
String sql = String.join(" ", units.getAnnotation(Select.class).value());
|
||||
|
||||
assertThat(sql)
|
||||
.contains("MIN(eligible.expectedArrivalAt) sortArrivalAt")
|
||||
.contains("MIN(eligible.expectedArrivalAt) IS NOT NULL")
|
||||
.contains("DATE(MIN(eligible.expectedArrivalAt))>=#{query.expectedArrivalStart}")
|
||||
.contains("DATE(MIN(eligible.expectedArrivalAt))<=#{query.expectedArrivalEnd}")
|
||||
.doesNotContain("SUM(CASE WHEN eligible.expectedArrivalAt IS NOT NULL");
|
||||
}
|
||||
|
||||
@Test
|
||||
void representativeArrivalControlsWhetherTheWholeGroupMatchesTheClosedDateRange() {
|
||||
List<LocalDateTime> groupArrivals = List.of(
|
||||
LocalDateTime.parse("2026-09-01T09:00:00"),
|
||||
LocalDateTime.parse("2026-09-10T09:00:00"));
|
||||
|
||||
LocalDate representative = groupArrivals.stream().min(LocalDateTime::compareTo)
|
||||
.orElseThrow().toLocalDate();
|
||||
|
||||
assertThat(matchesClosedRange(representative,
|
||||
LocalDate.parse("2026-09-10"), LocalDate.parse("2026-09-10")))
|
||||
.as("another member matching must not admit a group whose MIN arrival is outside")
|
||||
.isFalse();
|
||||
assertThat(matchesClosedRange(representative,
|
||||
LocalDate.parse("2026-09-01"), LocalDate.parse("2026-09-01")))
|
||||
.as("a matching MIN arrival admits the whole group")
|
||||
.isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void globalCandidateDynamicSqlRendersForStandaloneAndGroupedUnits() throws Exception {
|
||||
Configuration configuration = new Configuration();
|
||||
@@ -110,7 +145,10 @@ class SmartLoadingCandidateMapperContractTest {
|
||||
null, 1, 20);
|
||||
String renderedUnits = driver.createSqlSource(configuration, unitScript, Map.class)
|
||||
.getBoundSql(Map.of("query", query, "actualChannels", Set.of("MATSON_CLX_TRUCK"))).getSql();
|
||||
assertThat(renderedUnits).contains("o.channel_code IN", "DATE(eligible.expectedArrivalAt)");
|
||||
assertThat(renderedUnits)
|
||||
.contains("o.channel_code IN", "MIN(eligible.expectedArrivalAt) IS NOT NULL")
|
||||
.contains("DATE(MIN(eligible.expectedArrivalAt))>=", "DATE(MIN(eligible.expectedArrivalAt))<=")
|
||||
.doesNotContain("SUM(CASE WHEN eligible.expectedArrivalAt IS NOT NULL");
|
||||
|
||||
Method details = SmartLoadingCandidateMapper.class.getDeclaredMethod(
|
||||
"globalCandidatesByUnits", List.class);
|
||||
@@ -190,4 +228,25 @@ class SmartLoadingCandidateMapperContractTest {
|
||||
.contains("GROUP BY b.channel_code")
|
||||
.doesNotContain("'COMPLETED'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void planColoadSnapshotUsesOnePlanScopedBatchQuery() throws Exception {
|
||||
Method method=SmartLoadingCandidateMapper.class.getDeclaredMethod("planColoadMembers",long.class);
|
||||
String sql=String.join(" ",method.getAnnotation(Select.class).value());
|
||||
|
||||
assertThat(sql)
|
||||
.contains("plan_item.loading_plan_id=#{planId}")
|
||||
.contains("plan_item.deleted=0")
|
||||
.contains("member.tenant_id=plan_item.account_id")
|
||||
.contains("member.inbound_id=plan_item.inbound_id")
|
||||
.contains("member.active_flag=1")
|
||||
.contains("group_row.locked_plan_id=#{planId}")
|
||||
.contains("group_row.group_status IN ('LOCKED','CONSUMED')")
|
||||
.contains("SELECT DISTINCT")
|
||||
.doesNotContain("WHERE member.inbound_id=#{inboundId}");
|
||||
}
|
||||
|
||||
private static boolean matchesClosedRange(LocalDate arrival, LocalDate start, LocalDate end) {
|
||||
return arrival != null && !arrival.isBefore(start) && !arrival.isAfter(end);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ class ContainerServiceTest {
|
||||
when(smartLoadingService.createForContainer(anyLong(), anyLong(), anyString())).thenAnswer(invocation ->
|
||||
new com.baiyue.firstleg.dto.SmartLoadingDtos.Plan(501L, "LP-260818-0001", "EDITING",
|
||||
invocation.getArgument(0, Long.class), null, null, 0, true, true, null,
|
||||
"NOT_STARTED", null, null, null, List.of()));
|
||||
"NOT_STARTED", null, null, null, List.of(), List.of()));
|
||||
when(warehouses.active(anyString(), anyLong(), anyLong())).thenAnswer(invocation ->
|
||||
activeWarehouse(invocation.getArgument(2, Long.class), "DOMESTIC", "上海中转仓"));
|
||||
when(suppliers.trucking(202L, "拖车公司A"))
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.baiyue.firstleg.pricebookquery.application.model.PriceBookQueryRows.C
|
||||
import com.baiyue.firstleg.pricebookquery.application.port.in.PriceBookQueryUseCase;
|
||||
import com.baiyue.firstleg.mapper.SmartLoadingCandidateMapper.ChannelContainerCountRow;
|
||||
import com.baiyue.firstleg.mapper.SmartLoadingCandidateMapper.CandidateUnit;
|
||||
import com.baiyue.firstleg.mapper.SmartLoadingCandidateMapper.PlanColoadMemberRow;
|
||||
import com.baiyue.firstleg.split.service.SplitPreloadService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import feign.FeignException;
|
||||
@@ -116,6 +117,32 @@ class SmartLoadingServiceTest {
|
||||
assertThat(service.detail(1L).bookingId()).isEqualTo(99L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnsPlanColoadGroupsWithOneBatchLookup() {
|
||||
LoadingPlanEntity plan = plan("EDITING", 2);
|
||||
when(repository.plan(1L)).thenReturn(plan);
|
||||
when(repository.booking(99L)).thenReturn(booking());
|
||||
when(repository.items(1L)).thenReturn(List.of());
|
||||
when(repository.planColoadMembers(1L)).thenReturn(List.of(
|
||||
new PlanColoadMemberRow(700L,"CLG-700",1L,30L,10L,4),
|
||||
new PlanColoadMemberRow(700L,"CLG-700",1L,30L,11L,6),
|
||||
new PlanColoadMemberRow(700L,"CLG-700",1L,31L,12L,5)));
|
||||
|
||||
Plan result=service.detail(1L);
|
||||
|
||||
assertThat(result.coLoadGroups()).singleElement().satisfies(group->{
|
||||
assertThat(group.groupId()).isEqualTo(700L);
|
||||
assertThat(group.groupNo()).isEqualTo("CLG-700");
|
||||
assertThat(group.lockedPlanId()).isEqualTo(1L);
|
||||
assertThat(group.memberOrderCount()).isEqualTo(2);
|
||||
assertThat(group.inboundFragmentCount()).isEqualTo(3);
|
||||
assertThat(group.fullPackageCount()).isEqualTo(15);
|
||||
assertThat(group.memberInboundIds()).containsExactly(10L,11L,12L);
|
||||
});
|
||||
verify(repository).planColoadMembers(1L);
|
||||
verify(coloadGroups,never()).findByInbound(anyLong(),anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
void restoresLoadingPlanForContinuedAssignment() {
|
||||
LoadingPlanEntity plan = plan("LOADING", 3);
|
||||
@@ -208,8 +235,8 @@ class SmartLoadingServiceTest {
|
||||
Candidate second = withGroup(withArrival(withChannel(candidate(19L, 11L, 21L, 31L, 6),
|
||||
"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-10"),
|
||||
LocalDate.parse("2026-09-10"), null, 1, 1);
|
||||
List.of("MATSON_CLX"), 100L, null, null, LocalDate.parse("2026-09-01"),
|
||||
LocalDate.parse("2026-09-01"), null, 1, 1);
|
||||
CandidateUnit unit = new CandidateUnit(700L, null, null,
|
||||
LocalDateTime.parse("2026-09-01T09:00:00"), 10L);
|
||||
when(repository.globalCandidateUnits(eq(query), anySet()))
|
||||
|
||||
Reference in New Issue
Block a user