feat(firstleg): expose batch carrier actual facts
This commit is contained in:
+12
@@ -14,6 +14,18 @@ class CarrierScheduleQueryOpenApiContractTest {
|
||||
.getContentAsString(StandardCharsets.UTF_8);
|
||||
assertThat(yaml)
|
||||
.contains("/api/platform/v1/carrier-schedule-queries:")
|
||||
.contains("/api/platform/v1/carrier-schedule-queries/container-actual-facts:")
|
||||
.contains("name: containerBookingIds")
|
||||
.contains("maxItems: 200")
|
||||
.contains("uniqueItems: true")
|
||||
.contains("ContainerActualFacts:")
|
||||
.contains("departedWarehouseAt:")
|
||||
.contains("departedOriginPortAt:")
|
||||
.contains("arrivedDestinationPortAt:")
|
||||
.contains("pickupReadyAt:")
|
||||
.contains("pickedUpAt:")
|
||||
.contains("emptyReturnedAt:")
|
||||
.contains("Estimated facts are never returned or inferred")
|
||||
.contains("/api/platform/v1/carrier-schedule-queries/{queryId}/manual-results:")
|
||||
.contains("/api/platform/v1/carrier-schedule-queries/{queryId}/manual-nodes:")
|
||||
.contains("x-permission: platform:firstleg:port-schedule-query:manual")
|
||||
|
||||
+1
@@ -18,6 +18,7 @@ class PlatformCarrierScheduleQueryControllerContractTest {
|
||||
.containsExactly("/api/platform/v1/carrier-schedule-queries");
|
||||
Map<String, String> permissions = Map.of(
|
||||
"carriers", "platform:firstleg:port-schedule-query:list",
|
||||
"containerActualFacts", "platform:firstleg:port-schedule-query:list",
|
||||
"page", "platform:firstleg:port-schedule-query:list",
|
||||
"detail", "platform:firstleg:port-schedule-query:list",
|
||||
"history", "platform:firstleg:port-schedule-query:list",
|
||||
|
||||
+25
@@ -9,10 +9,31 @@ import org.springframework.core.io.ClassPathResource;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class CarrierScheduleQuerySqlContractTest {
|
||||
@Test
|
||||
void batchesActualContainerFactsWithoutEstimatedOrPerNodeQueries() throws Exception {
|
||||
String sql = String.join("\n", CarrierScheduleQueryMapper.class
|
||||
.getMethod("selectContainerActualFacts", List.class)
|
||||
.getAnnotation(Select.class).value());
|
||||
|
||||
assertThat(sql)
|
||||
.contains("container_booking_id IN")
|
||||
.contains("f.actual_at IS NOT NULL")
|
||||
.contains("MAX(CASE WHEN f.standard_node='DEPARTED_WAREHOUSE'")
|
||||
.contains("MAX(CASE WHEN f.standard_node='DEPARTED_ORIGIN_PORT'")
|
||||
.contains("MAX(CASE WHEN f.standard_node='ARRIVED_DESTINATION_PORT'")
|
||||
.contains("MAX(CASE WHEN f.standard_node='PICKUP_READY'")
|
||||
.contains("MAX(CASE WHEN f.standard_node='PICKED_UP'")
|
||||
.contains("MAX(CASE WHEN f.standard_node='EMPTY_RETURNED'")
|
||||
.contains("ORDER BY q.container_booking_id")
|
||||
.doesNotContain("estimated_at");
|
||||
assertThat(count(sql, "fl_carrier_schedule_node_fact")).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void annotationSqlUsesExecutableComparisonOperators() throws Exception {
|
||||
String selectDue = String.join("\n", CarrierScheduleQueryMapper.class
|
||||
@@ -149,4 +170,8 @@ class CarrierScheduleQuerySqlContractTest {
|
||||
return new ClassPathResource("db/phase3-carrier-schedule-query-schema.sql")
|
||||
.getContentAsString(StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static int count(String source, String needle) {
|
||||
return source.split(java.util.regex.Pattern.quote(needle), -1).length - 1;
|
||||
}
|
||||
}
|
||||
|
||||
+30
@@ -4,6 +4,7 @@ import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.firstleg.oceanbooking.entity.OceanBookingContainerAllocationEntity;
|
||||
import com.baiyue.firstleg.oceanbooking.entity.OceanBookingEntity;
|
||||
import com.baiyue.firstleg.portschedule.dto.CarrierScheduleQueryDtos.CreateRequest;
|
||||
import com.baiyue.firstleg.portschedule.dto.CarrierScheduleQueryDtos.ContainerActualFacts;
|
||||
import com.baiyue.firstleg.portschedule.dto.CarrierScheduleQueryDtos.ManualResultRequest;
|
||||
import com.baiyue.firstleg.portschedule.dto.CarrierScheduleQueryDtos.ManualNodeRequest;
|
||||
import com.baiyue.firstleg.portschedule.dto.CarrierScheduleQueryDtos.ProviderObservationRequest;
|
||||
@@ -72,6 +73,35 @@ class CarrierScheduleQueryServiceTest {
|
||||
when(portSchedules.containerBooking(20L)).thenReturn(container);
|
||||
}
|
||||
|
||||
@Test
|
||||
void returnsBatchActualFactsFromOneRepositoryCall() {
|
||||
ContainerActualFacts facts = new ContainerActualFacts(20L, 30L, 2, "READY",
|
||||
"PICKUP_READY", NOW, NOW.minusDays(12), NOW.minusDays(10), NOW.minusDays(2),
|
||||
NOW, null, null);
|
||||
when(repository.containerActualFacts(List.of(20L, 21L))).thenReturn(List.of(facts));
|
||||
|
||||
assertThat(service.containerActualFacts(List.of(20L, 21L))).containsExactly(facts);
|
||||
verify(repository).containerActualFacts(List.of(20L, 21L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsInvalidActualFactBatchBeforeRepositoryAccess() {
|
||||
assertThatThrownBy(() -> service.containerActualFacts(null))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("1到200");
|
||||
assertThatThrownBy(() -> service.containerActualFacts(List.of()))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("1到200");
|
||||
assertThatThrownBy(() -> service.containerActualFacts(java.util.Collections.nCopies(201, 1L)))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("1到200");
|
||||
assertThatThrownBy(() -> service.containerActualFacts(java.util.Arrays.asList(1L, null)))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("正数");
|
||||
assertThatThrownBy(() -> service.containerActualFacts(List.of(1L, 0L)))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("正数");
|
||||
assertThatThrownBy(() -> service.containerActualFacts(List.of(1L, 1L)))
|
||||
.isInstanceOf(BizException.class).hasMessageContaining("重复");
|
||||
|
||||
verify(repository, never()).containerActualFacts(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void createsTaskOnlyForBookingCustomerAndAllocatedContainer() {
|
||||
OceanBookingEntity booking = new OceanBookingEntity(); booking.setCustomerId(10001L);
|
||||
|
||||
Reference in New Issue
Block a user