优化
This commit is contained in:
@@ -18,7 +18,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
|
|||||||
"com.baiyue.firstleg.outbound.dispatch.mapper",
|
"com.baiyue.firstleg.outbound.dispatch.mapper",
|
||||||
"com.baiyue.firstleg.portschedule.mapper",
|
"com.baiyue.firstleg.portschedule.mapper",
|
||||||
"com.baiyue.firstleg.customs.mapper",
|
"com.baiyue.firstleg.customs.mapper",
|
||||||
"com.baiyue.firstleg.customerstatistics.mapper"
|
"com.baiyue.firstleg.customerstatistics.adapter.out.persistence"
|
||||||
})
|
})
|
||||||
@EnableFeignClients(basePackages = "com.baiyue.firstleg")
|
@EnableFeignClients(basePackages = "com.baiyue.firstleg")
|
||||||
@EnableScheduling
|
@EnableScheduling
|
||||||
|
|||||||
+3
-3
@@ -1,9 +1,9 @@
|
|||||||
package com.baiyue.firstleg.customerstatistics.controller;
|
package com.baiyue.firstleg.customerstatistics.adapter.in.web;
|
||||||
|
|
||||||
import com.baiyue.common.core.api.ApiResponse;
|
import com.baiyue.common.core.api.ApiResponse;
|
||||||
import com.baiyue.common.security.AuthenticatedUser;
|
import com.baiyue.common.security.AuthenticatedUser;
|
||||||
import com.baiyue.firstleg.customerstatistics.dto.CustomerTransitStatisticsDtos.TransitSummary;
|
import com.baiyue.firstleg.customerstatistics.application.CustomerTransitStatisticsService;
|
||||||
import com.baiyue.firstleg.customerstatistics.service.CustomerTransitStatisticsService;
|
import com.baiyue.firstleg.customerstatistics.application.model.CustomerTransitStatisticsDtos.TransitSummary;
|
||||||
import com.baiyue.firstleg.service.FirstlegScopeGuard;
|
import com.baiyue.firstleg.service.FirstlegScopeGuard;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.validation.constraints.Positive;
|
import jakarta.validation.constraints.Positive;
|
||||||
+5
-9
@@ -1,14 +1,13 @@
|
|||||||
package com.baiyue.firstleg.customerstatistics.mapper;
|
package com.baiyue.firstleg.customerstatistics.adapter.out.persistence;
|
||||||
|
|
||||||
|
import com.baiyue.firstleg.customerstatistics.application.port.out.CustomerTransitStatisticsReader;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface CustomerTransitStatisticsMapper {
|
public interface CustomerTransitStatisticsMapper extends CustomerTransitStatisticsReader {
|
||||||
|
@Override
|
||||||
@Select("""
|
@Select("""
|
||||||
SELECT #{customerId} AS customerId,
|
SELECT #{customerId} AS customerId,
|
||||||
COUNT(*) AS containerCount,
|
COUNT(*) AS containerCount,
|
||||||
@@ -49,8 +48,5 @@ public interface CustomerTransitStatisticsMapper {
|
|||||||
WHERE x.customer_id = #{customerId}
|
WHERE x.customer_id = #{customerId}
|
||||||
) scoped
|
) scoped
|
||||||
""")
|
""")
|
||||||
SummaryRow summarize(@Param("customerId") long customerId);
|
SummaryProjection summarize(@Param("customerId") long customerId);
|
||||||
|
|
||||||
record SummaryRow(Long customerId, Long containerCount, BigDecimal totalTeu,
|
|
||||||
Long unknownContainerCount, LocalDateTime asOf) {}
|
|
||||||
}
|
}
|
||||||
+5
-5
@@ -1,9 +1,9 @@
|
|||||||
package com.baiyue.firstleg.customerstatistics.service;
|
package com.baiyue.firstleg.customerstatistics.application;
|
||||||
|
|
||||||
import com.baiyue.common.core.api.ResultCode;
|
import com.baiyue.common.core.api.ResultCode;
|
||||||
import com.baiyue.common.core.exception.BizException;
|
import com.baiyue.common.core.exception.BizException;
|
||||||
import com.baiyue.firstleg.customerstatistics.dto.CustomerTransitStatisticsDtos.TransitSummary;
|
import com.baiyue.firstleg.customerstatistics.application.model.CustomerTransitStatisticsDtos.TransitSummary;
|
||||||
import com.baiyue.firstleg.customerstatistics.mapper.CustomerTransitStatisticsMapper;
|
import com.baiyue.firstleg.customerstatistics.application.port.out.CustomerTransitStatisticsReader;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -12,11 +12,11 @@ import java.math.BigDecimal;
|
|||||||
@Service
|
@Service
|
||||||
public class CustomerTransitStatisticsService {
|
public class CustomerTransitStatisticsService {
|
||||||
private static final String DEFINITION = "actual_sailing_at IS NOT NULL 且 actual_warehouse_arrival_at IS NULL;排除取消/失败订舱;客户+containerBookingId去重;拼柜按active LoadingPlanItem.accountId归属,整柜按OceanBooking.customerId归属。TEU:20*=1,40*=2,45*=2.25,未知箱型不计totalTeu。";
|
private static final String DEFINITION = "actual_sailing_at IS NOT NULL 且 actual_warehouse_arrival_at IS NULL;排除取消/失败订舱;客户+containerBookingId去重;拼柜按active LoadingPlanItem.accountId归属,整柜按OceanBooking.customerId归属。TEU:20*=1,40*=2,45*=2.25,未知箱型不计totalTeu。";
|
||||||
@Resource private CustomerTransitStatisticsMapper mapper;
|
@Resource private CustomerTransitStatisticsReader reader;
|
||||||
|
|
||||||
public TransitSummary summarize(long customerId) {
|
public TransitSummary summarize(long customerId) {
|
||||||
if (customerId <= 0) throw new BizException(ResultCode.BAD_REQUEST, "customerId必须为正数");
|
if (customerId <= 0) throw new BizException(ResultCode.BAD_REQUEST, "customerId必须为正数");
|
||||||
var row = mapper.summarize(customerId);
|
var row = reader.summarize(customerId);
|
||||||
return new TransitSummary(customerId,
|
return new TransitSummary(customerId,
|
||||||
value(row == null ? null : row.containerCount()),
|
value(row == null ? null : row.containerCount()),
|
||||||
row == null || row.totalTeu() == null ? BigDecimal.ZERO : row.totalTeu(),
|
row == null || row.totalTeu() == null ? BigDecimal.ZERO : row.totalTeu(),
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.baiyue.firstleg.customerstatistics.dto;
|
package com.baiyue.firstleg.customerstatistics.application.model;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
package com.baiyue.firstleg.customerstatistics.application.port.out;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
public interface CustomerTransitStatisticsReader {
|
||||||
|
SummaryProjection summarize(long customerId);
|
||||||
|
|
||||||
|
record SummaryProjection(Long customerId, Long containerCount, BigDecimal totalTeu,
|
||||||
|
Long unknownContainerCount, LocalDateTime asOf) {}
|
||||||
|
}
|
||||||
+2
-1
@@ -20,7 +20,8 @@ class BaiyueFirstlegApplicationContractTest {
|
|||||||
.contains("com.baiyue.firstleg.outbound.dispatch.mapper")
|
.contains("com.baiyue.firstleg.outbound.dispatch.mapper")
|
||||||
.contains("com.baiyue.firstleg.portschedule.mapper")
|
.contains("com.baiyue.firstleg.portschedule.mapper")
|
||||||
.contains("com.baiyue.firstleg.customs.mapper")
|
.contains("com.baiyue.firstleg.customs.mapper")
|
||||||
.contains("com.baiyue.firstleg.customerstatistics.mapper");
|
.contains("com.baiyue.firstleg.customerstatistics.adapter.out.persistence")
|
||||||
|
.doesNotContain("com.baiyue.firstleg.customerstatistics.mapper");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+3
-3
@@ -1,8 +1,8 @@
|
|||||||
package com.baiyue.firstleg.customerstatistics;
|
package com.baiyue.firstleg.customerstatistics;
|
||||||
|
|
||||||
import com.baiyue.firstleg.customerstatistics.controller.PlatformCustomerTransitStatisticsController;
|
import com.baiyue.firstleg.customerstatistics.adapter.in.web.PlatformCustomerTransitStatisticsController;
|
||||||
import com.baiyue.firstleg.customerstatistics.mapper.CustomerTransitStatisticsMapper;
|
import com.baiyue.firstleg.customerstatistics.adapter.out.persistence.CustomerTransitStatisticsMapper;
|
||||||
import com.baiyue.firstleg.customerstatistics.service.CustomerTransitStatisticsService;
|
import com.baiyue.firstleg.customerstatistics.application.CustomerTransitStatisticsService;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
|||||||
+5
-5
@@ -1,8 +1,8 @@
|
|||||||
package com.baiyue.firstleg.customerstatistics;
|
package com.baiyue.firstleg.customerstatistics;
|
||||||
|
|
||||||
import com.baiyue.common.core.exception.BizException;
|
import com.baiyue.common.core.exception.BizException;
|
||||||
import com.baiyue.firstleg.customerstatistics.mapper.CustomerTransitStatisticsMapper;
|
import com.baiyue.firstleg.customerstatistics.application.CustomerTransitStatisticsService;
|
||||||
import com.baiyue.firstleg.customerstatistics.service.CustomerTransitStatisticsService;
|
import com.baiyue.firstleg.customerstatistics.application.port.out.CustomerTransitStatisticsReader;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
@@ -19,12 +19,12 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class CustomerTransitStatisticsServiceTest {
|
class CustomerTransitStatisticsServiceTest {
|
||||||
@Mock CustomerTransitStatisticsMapper mapper;
|
@Mock CustomerTransitStatisticsReader reader;
|
||||||
@InjectMocks CustomerTransitStatisticsService service;
|
@InjectMocks CustomerTransitStatisticsService service;
|
||||||
|
|
||||||
@Test void preservesDecimalTeuAndUnknownCount() {
|
@Test void preservesDecimalTeuAndUnknownCount() {
|
||||||
var asOf = LocalDateTime.of(2026, 8, 13, 12, 0);
|
var asOf = LocalDateTime.of(2026, 8, 13, 12, 0);
|
||||||
when(mapper.summarize(88L)).thenReturn(new CustomerTransitStatisticsMapper.SummaryRow(
|
when(reader.summarize(88L)).thenReturn(new CustomerTransitStatisticsReader.SummaryProjection(
|
||||||
88L, 4L, new BigDecimal("6.25"), 1L, asOf));
|
88L, 4L, new BigDecimal("6.25"), 1L, asOf));
|
||||||
|
|
||||||
var result = service.summarize(88L);
|
var result = service.summarize(88L);
|
||||||
@@ -35,7 +35,7 @@ class CustomerTransitStatisticsServiceTest {
|
|||||||
assertThat(result.unknownContainerCount()).isEqualTo(1);
|
assertThat(result.unknownContainerCount()).isEqualTo(1);
|
||||||
assertThat(result.asOf()).isEqualTo(asOf);
|
assertThat(result.asOf()).isEqualTo(asOf);
|
||||||
assertThat(result.definition()).contains("20*=1", "40*=2", "45*=2.25", "未知箱型");
|
assertThat(result.definition()).contains("20*=1", "40*=2", "45*=2.25", "未知箱型");
|
||||||
verify(mapper).summarize(88L);
|
verify(reader).summarize(88L);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test void rejectsInvalidCustomerBeforeQuery() {
|
@Test void rejectsInvalidCustomerBeforeQuery() {
|
||||||
|
|||||||
Reference in New Issue
Block a user