优化
This commit is contained in:
+50
@@ -0,0 +1,50 @@
|
||||
package com.baiyue.firstleg.customerstatistics;
|
||||
|
||||
import com.baiyue.firstleg.customerstatistics.controller.PlatformCustomerTransitStatisticsController;
|
||||
import com.baiyue.firstleg.customerstatistics.mapper.CustomerTransitStatisticsMapper;
|
||||
import com.baiyue.firstleg.customerstatistics.service.CustomerTransitStatisticsService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class CustomerTransitStatisticsContractTest {
|
||||
@Test void exposesPlatformCustomerSummaryWithStablePermission() throws Exception {
|
||||
assertThat(PlatformCustomerTransitStatisticsController.class.getAnnotation(RequestMapping.class).value())
|
||||
.containsExactly("/api/platform/v1/customers");
|
||||
var method = PlatformCustomerTransitStatisticsController.class.getDeclaredMethod(
|
||||
"summary", com.baiyue.common.security.AuthenticatedUser.class, long.class);
|
||||
assertThat(method.getAnnotation(GetMapping.class).value()).containsExactly("/{customerId}/container-transit-summary");
|
||||
assertThat(method.getAnnotation(PreAuthorize.class).value())
|
||||
.isEqualTo("hasAuthority('platform:firstleg:container:list')");
|
||||
}
|
||||
|
||||
@Test void queryEnforcesTransitScopeOwnershipDedupAndTeuRules() throws Exception {
|
||||
var sql = Arrays.stream(CustomerTransitStatisticsMapper.class.getDeclaredMethods())
|
||||
.findFirst().orElseThrow().getAnnotation(org.apache.ibatis.annotations.Select.class).value();
|
||||
var statement = String.join("\n", sql);
|
||||
assertThat(statement).contains("actual_sailing_at IS NOT NULL", "actual_warehouse_arrival_at IS NULL",
|
||||
"status NOT IN ('CANCELLED', 'FAILED')", "DISTINCT x.customer_id, x.container_booking_id",
|
||||
"b.customer_id", "i.account_id", "i.deleted = 0", "NOT EXISTS",
|
||||
"x.customer_id = #{customerId}", "LIKE '20%'", "THEN 1.0",
|
||||
"LIKE '40%'", "THEN 2.0", "LIKE '45%'", "THEN 2.25", "ELSE NULL");
|
||||
}
|
||||
|
||||
@Test void schemaAddsTransitSummaryIndexAndDefinition() throws Exception {
|
||||
var schema = new ClassPathResource("db/phase3-smart-loading-schema.sql")
|
||||
.getContentAsString(StandardCharsets.UTF_8);
|
||||
assertThat(schema).contains("idx_container_booking_transit_summary");
|
||||
var openApi = new ClassPathResource("openapi/customer-statistics-v1.yaml")
|
||||
.getContentAsString(StandardCharsets.UTF_8);
|
||||
assertThat(openApi).contains("containerCount:", "format: int64", "totalTeu:",
|
||||
"multipleOf: 0.01", "unknownContainerCount:", "format: date-time", "definition:");
|
||||
var service = CustomerTransitStatisticsService.class;
|
||||
assertThat(service.getDeclaredFields()).anyMatch(f -> f.getName().equals("DEFINITION"));
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.baiyue.firstleg.customerstatistics;
|
||||
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import com.baiyue.firstleg.customerstatistics.mapper.CustomerTransitStatisticsMapper;
|
||||
import com.baiyue.firstleg.customerstatistics.service.CustomerTransitStatisticsService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CustomerTransitStatisticsServiceTest {
|
||||
@Mock CustomerTransitStatisticsMapper mapper;
|
||||
@InjectMocks CustomerTransitStatisticsService service;
|
||||
|
||||
@Test void preservesDecimalTeuAndUnknownCount() {
|
||||
var asOf = LocalDateTime.of(2026, 8, 13, 12, 0);
|
||||
when(mapper.summarize(88L)).thenReturn(new CustomerTransitStatisticsMapper.SummaryRow(
|
||||
88L, 4L, new BigDecimal("6.25"), 1L, asOf));
|
||||
|
||||
var result = service.summarize(88L);
|
||||
|
||||
assertThat(result.customerId()).isEqualTo(88L);
|
||||
assertThat(result.containerCount()).isEqualTo(4);
|
||||
assertThat(result.totalTeu()).isEqualByComparingTo("6.25");
|
||||
assertThat(result.unknownContainerCount()).isEqualTo(1);
|
||||
assertThat(result.asOf()).isEqualTo(asOf);
|
||||
assertThat(result.definition()).contains("20*=1", "40*=2", "45*=2.25", "未知箱型");
|
||||
verify(mapper).summarize(88L);
|
||||
}
|
||||
|
||||
@Test void rejectsInvalidCustomerBeforeQuery() {
|
||||
assertThatThrownBy(() -> service.summarize(0)).isInstanceOf(BizException.class);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user