feat(firstleg): expose smart-loading channel directory
This commit is contained in:
+4
-1
@@ -12,11 +12,14 @@ 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);
|
||||
authority("inboundCandidates","platform:firstleg:smart-loading:list",AuthenticatedUser.class,long.class,long.class);
|
||||
authority("channels","platform:firstleg:smart-loading:list",AuthenticatedUser.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("/api/platform/v1/first-leg/smart-loading/channels:")
|
||||
.contains("零候选或零可用柜次的有效渠道仍返回")
|
||||
.contains("name: bookingId, in: query, required: true")
|
||||
.contains("name: warehouseId, in: query, required: true");
|
||||
}
|
||||
|
||||
+15
@@ -69,4 +69,19 @@ class SmartLoadingCandidateMapperContractTest {
|
||||
.contains("GROUP BY tenant_id,measurement_id,inbound_detail_id")
|
||||
.contains("FOR UPDATE");
|
||||
}
|
||||
|
||||
@Test
|
||||
void channelContainerStatisticsCountOnlyActiveOrchestratableContainers() throws Exception {
|
||||
Method method = SmartLoadingCandidateMapper.class.getDeclaredMethod(
|
||||
"channelContainerCounts", long.class);
|
||||
String sql = String.join(" ", method.getAnnotation(Select.class).value());
|
||||
|
||||
assertThat(sql)
|
||||
.contains("b.record_status='ACTIVE'")
|
||||
.contains("b.warehouse_id=#{warehouseId}")
|
||||
.contains("p.id IS NULL OR p.plan_status IN ('EDITING','LOADING')")
|
||||
.contains("COUNT(DISTINCT b.id) availableContainerCount")
|
||||
.contains("GROUP BY b.channel_code")
|
||||
.doesNotContain("'COMPLETED'");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ import com.baiyue.firstleg.loading.bridge.service.LoadingModelBridgeService;
|
||||
import com.baiyue.firstleg.loading.coload.port.ColoadGroupAssignmentPort;
|
||||
import com.baiyue.firstleg.loading.coload.model.ColoadGroupModels.GroupSnapshot;
|
||||
import com.baiyue.firstleg.loading.coload.model.ColoadGroupModels.Member;
|
||||
import com.baiyue.firstleg.pricebookquery.application.model.PriceBookQueryRows.ChannelRow;
|
||||
import com.baiyue.firstleg.pricebookquery.application.port.in.PriceBookQueryUseCase;
|
||||
import com.baiyue.firstleg.mapper.SmartLoadingCandidateMapper.ChannelContainerCountRow;
|
||||
import com.baiyue.firstleg.split.service.SplitPreloadService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import feign.FeignException;
|
||||
@@ -73,6 +76,7 @@ class SmartLoadingServiceTest {
|
||||
@MockBean private LoadingModelBridgeService loadingModelBridge;
|
||||
@MockBean private SplitPreloadService splitPreloadService;
|
||||
@MockBean private ColoadGroupAssignmentPort coloadGroups;
|
||||
@MockBean private PriceBookQueryUseCase priceBooks;
|
||||
@MockBean private FirstlegDocumentNumberGenerator documentNumbers;
|
||||
@Resource private SmartLoadingService service;
|
||||
|
||||
@@ -139,6 +143,40 @@ class SmartLoadingServiceTest {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void channelDirectoryKeepsActiveZeroStatChannelAndAggregatesCandidateAndContainerFacts() {
|
||||
ChannelRow maxTruck = channel("MATSON_MAX_TRUCK", "美森加班海卡");
|
||||
ChannelRow clxTruck = channel("MATSON_CLX_TRUCK", "美森正班海卡");
|
||||
Candidate first = candidate(9L, 10L, 20L, 30L, 4);
|
||||
Candidate secondDetail = candidate(9L, 10L, 21L, 30L, 6);
|
||||
Candidate secondInbound = candidate(19L, 11L, 22L, 31L, 5);
|
||||
first = withChannel(first, "MATSON_MAX_TRUCK", "旧渠道快照名称");
|
||||
secondDetail = withChannel(secondDetail, "MATSON_MAX_TRUCK", "旧渠道快照名称");
|
||||
secondInbound = withChannel(secondInbound, "MATSON_MAX_TRUCK", "旧渠道快照名称");
|
||||
ChannelContainerCountRow count = new ChannelContainerCountRow();
|
||||
count.setChannelCode("MATSON_MAX_TRUCK"); count.setAvailableContainerCount(2L);
|
||||
when(priceBooks.activeVersionId()).thenReturn(88L);
|
||||
when(priceBooks.channels(88L, 100L)).thenReturn(List.of(maxTruck, clxTruck));
|
||||
when(repository.candidates(100L)).thenReturn(List.of(first, secondDetail, secondInbound));
|
||||
when(repository.channelContainerCounts(100L)).thenReturn(List.of(count));
|
||||
|
||||
var result = service.channels(100L);
|
||||
|
||||
assertThat(result).hasSize(2);
|
||||
assertThat(result.get(0)).satisfies(channel -> {
|
||||
assertThat(channel.channelName()).isEqualTo("美森加班海卡");
|
||||
assertThat(channel.candidateInboundCount()).isEqualTo(2);
|
||||
assertThat(channel.availablePackageCount()).isEqualTo(15);
|
||||
assertThat(channel.availableContainerCount()).isEqualTo(2);
|
||||
});
|
||||
assertThat(result.get(1)).satisfies(channel -> {
|
||||
assertThat(channel.channelCode()).isEqualTo("MATSON_CLX_TRUCK");
|
||||
assertThat(channel.candidateInboundCount()).isZero();
|
||||
assertThat(channel.availablePackageCount()).isZero();
|
||||
assertThat(channel.availableContainerCount()).isZero();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void exposesWholeColoadGroupFactsOnEveryMemberCandidate() {
|
||||
Candidate first = candidate(9L, 10L, 20L, 30L, 4);
|
||||
@@ -1297,6 +1335,21 @@ class SmartLoadingServiceTest {
|
||||
new BigDecimal("0.5"), null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
private static Candidate withChannel(Candidate value, String channelCode, String channelName) {
|
||||
return new Candidate(value.accountId(), value.inboundId(), value.inboundDetailId(), value.orderId(),
|
||||
value.orderNo(), value.inboundCode(), value.warehouseId(), channelCode, 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());
|
||||
}
|
||||
|
||||
private static ChannelRow channel(String channelCode, String channelName) {
|
||||
ChannelRow value = new ChannelRow();
|
||||
value.setChannelCode(channelCode); value.setChannelName(channelName);
|
||||
return value;
|
||||
}
|
||||
|
||||
private static GroupSnapshot group(String status, Long lockedPlanId, Member... members) {
|
||||
GroupSnapshot group = mock(GroupSnapshot.class);
|
||||
when(group.groupId()).thenReturn(700L);
|
||||
|
||||
Reference in New Issue
Block a user