完成项目详情风险人员分页改造

This commit is contained in:
wkc
2026-03-29 18:44:07 +08:00
parent dd3aa5bbae
commit 0a3c03dcf9
25 changed files with 609 additions and 58 deletions

View File

@@ -3,6 +3,7 @@ package com.ruoyi.ccdi.project.controller;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectEmployeeCreditNegativeQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectPersonAnalysisDetailQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskModelPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectSuspiciousTransactionQueryDTO;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectSuspiciousTransactionExcel;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectEmployeeCreditNegativePageVO;
@@ -57,8 +58,8 @@ public class CcdiProjectOverviewController extends BaseController {
@GetMapping("/risk-people")
@Operation(summary = "查询风险人员总览")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult getRiskPeople(Long projectId) {
CcdiProjectRiskPeopleOverviewVO overview = overviewService.getRiskPeopleOverview(projectId);
public AjaxResult getRiskPeople(CcdiProjectRiskPeopleQueryDTO queryDTO) {
CcdiProjectRiskPeopleOverviewVO overview = overviewService.getRiskPeopleOverview(queryDTO);
return AjaxResult.success(overview);
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.ccdi.project.domain.dto;
import lombok.Data;
/**
* 风险人员总览查询 DTO
*/
@Data
public class CcdiProjectRiskPeopleQueryDTO {
private Long projectId;
private Integer pageNum;
private Integer pageSize;
}

View File

@@ -9,5 +9,11 @@ import lombok.Data;
@Data
public class CcdiProjectRiskPeopleOverviewVO {
private List<CcdiProjectRiskPeopleOverviewItemVO> overviewList;
private List<CcdiProjectRiskPeopleOverviewItemVO> rows;
private Long total;
private Long pageNum;
private Long pageSize;
}

View File

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.ccdi.project.domain.CcdiProject;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectEmployeeCreditNegativeQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskModelPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectSuspiciousTransactionQueryDTO;
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectEmployeeCreditNegativeItemVO;
@@ -36,10 +37,14 @@ public interface CcdiProjectOverviewMapper {
/**
* 查询风险人员总览
*
* @param projectId 项目ID
* @return 风险人员聚合列表
* @param page 分页参数
* @param query 查询条件
* @return 风险人员聚合分页结果
*/
List<CcdiProjectEmployeeRiskAggregateVO> selectRiskPeopleOverviewByProjectId(@Param("projectId") Long projectId);
Page<CcdiProjectEmployeeRiskAggregateVO> selectRiskPeopleOverviewPage(
Page<CcdiProjectEmployeeRiskAggregateVO> page,
@Param("query") CcdiProjectRiskPeopleQueryDTO query
);
/**
* 查询中高风险TOP10

View File

@@ -3,6 +3,7 @@ package com.ruoyi.ccdi.project.service;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectEmployeeCreditNegativeQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectPersonAnalysisDetailQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskModelPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectSuspiciousTransactionQueryDTO;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectSuspiciousTransactionExcel;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectEmployeeCreditNegativePageVO;
@@ -32,10 +33,10 @@ public interface ICcdiProjectOverviewService {
/**
* 查询风险人员总览
*
* @param projectId 项目ID
* @param queryDTO 查询条件
* @return 风险人员总览
*/
CcdiProjectRiskPeopleOverviewVO getRiskPeopleOverview(Long projectId);
CcdiProjectRiskPeopleOverviewVO getRiskPeopleOverview(CcdiProjectRiskPeopleQueryDTO queryDTO);
/**
* 查询中高风险人员TOP10

View File

@@ -5,6 +5,7 @@ import com.ruoyi.ccdi.project.domain.CcdiProject;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectEmployeeCreditNegativeQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectPersonAnalysisDetailQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskModelPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectSuspiciousTransactionQueryDTO;
import com.ruoyi.ccdi.project.domain.excel.CcdiProjectSuspiciousTransactionExcel;
import com.ruoyi.ccdi.project.domain.entity.CcdiProjectOverviewEmployeeResult;
@@ -96,16 +97,26 @@ public class CcdiProjectOverviewServiceImpl implements ICcdiProjectOverviewServi
}
@Override
public CcdiProjectRiskPeopleOverviewVO getRiskPeopleOverview(Long projectId) {
public CcdiProjectRiskPeopleOverviewVO getRiskPeopleOverview(CcdiProjectRiskPeopleQueryDTO queryDTO) {
Long projectId = queryDTO.getProjectId();
ensureProjectExists(projectId);
List<CcdiProjectRiskPeopleOverviewItemVO> overviewList = overviewMapper.selectRiskPeopleOverviewByProjectId(projectId)
Page<CcdiProjectEmployeeRiskAggregateVO> page = new Page<>(
defaultRiskPeoplePageNum(queryDTO.getPageNum()),
defaultRiskPeoplePageSize(queryDTO.getPageSize())
);
Page<CcdiProjectEmployeeRiskAggregateVO> resultPage = overviewMapper.selectRiskPeopleOverviewPage(page, queryDTO);
List<CcdiProjectRiskPeopleOverviewItemVO> rows = defaultList(resultPage == null ? null : resultPage.getRecords())
.stream()
.map(aggregate -> buildRiskPeopleItem(projectId, aggregate))
.toList();
CcdiProjectRiskPeopleOverviewVO overview = new CcdiProjectRiskPeopleOverviewVO();
overview.setOverviewList(overviewList);
overview.setRows(rows);
overview.setTotal(resultPage == null ? 0L : resultPage.getTotal());
overview.setPageNum(page.getCurrent());
overview.setPageSize(page.getSize());
return overview;
}
@@ -348,6 +359,14 @@ public class CcdiProjectOverviewServiceImpl implements ICcdiProjectOverviewServi
return value == null ? 0 : value;
}
private long defaultRiskPeoplePageNum(Integer pageNum) {
return pageNum == null || pageNum <= 0 ? 1L : pageNum.longValue();
}
private long defaultRiskPeoplePageSize(Integer pageSize) {
return pageSize == null || pageSize <= 0 ? 5L : pageSize.longValue();
}
private long defaultPageNum(Integer pageNum) {
return pageNum == null || pageNum < 1 ? 1L : pageNum.longValue();
}

View File

@@ -223,7 +223,7 @@
and del_flag = '0'
</select>
<select id="selectRiskPeopleOverviewByProjectId" resultMap="EmployeeRiskAggregateResultMap">
<select id="selectRiskPeopleOverviewPage" resultMap="EmployeeRiskAggregateResultMap">
select
result.staff_id_card,
result.staff_name,
@@ -247,7 +247,7 @@
else 3
end as risk_level_sort
from ccdi_project_overview_employee_result result
where result.project_id = #{projectId}
where result.project_id = #{query.projectId}
order by risk_level_sort asc, result.model_count desc, result.rule_count desc, result.staff_id_card asc
</select>

View File

@@ -83,20 +83,31 @@ class CcdiProjectOverviewControllerTest {
riskPointTag.setRuleName("多工资转入");
item.setRiskPointTagList(List.of(riskPointTag));
CcdiProjectRiskPeopleOverviewVO overview = new CcdiProjectRiskPeopleOverviewVO();
overview.setOverviewList(List.of(item));
when(overviewService.getRiskPeopleOverview(40L)).thenReturn(overview);
Method setRowsMethod = CcdiProjectRiskPeopleOverviewVO.class.getMethod("setRows", List.class);
Method setTotalMethod = CcdiProjectRiskPeopleOverviewVO.class.getMethod("setTotal", Long.class);
Method setPageNumMethod = CcdiProjectRiskPeopleOverviewVO.class.getMethod("setPageNum", Long.class);
Method setPageSizeMethod = CcdiProjectRiskPeopleOverviewVO.class.getMethod("setPageSize", Long.class);
Method getRowsMethod = CcdiProjectRiskPeopleOverviewVO.class.getMethod("getRows");
Method getTotalMethod = CcdiProjectRiskPeopleOverviewVO.class.getMethod("getTotal");
Method getPageNumMethod = CcdiProjectRiskPeopleOverviewVO.class.getMethod("getPageNum");
Method getPageSizeMethod = CcdiProjectRiskPeopleOverviewVO.class.getMethod("getPageSize");
setRowsMethod.invoke(overview, List.of(item));
setTotalMethod.invoke(overview, 1L);
setPageNumMethod.invoke(overview, 1L);
setPageSizeMethod.invoke(overview, 5L);
AjaxResult result = controller.getRiskPeople(40L);
assertEquals("中风险", ((List<CcdiProjectRiskPeopleOverviewItemVO>) getRowsMethod.invoke(overview)).getFirst().getRiskLevel());
assertEquals("warning", ((List<CcdiProjectRiskPeopleOverviewItemVO>) getRowsMethod.invoke(overview)).getFirst().getRiskLevelType());
assertEquals(4, ((List<CcdiProjectRiskPeopleOverviewItemVO>) getRowsMethod.invoke(overview)).getFirst().getModelCount());
assertEquals("SALARY", ((List<CcdiProjectRiskPeopleOverviewItemVO>) getRowsMethod.invoke(overview)).getFirst().getRiskPointTagList().getFirst().getModelCode());
assertEquals(1L, getTotalMethod.invoke(overview));
assertEquals(1L, getPageNumMethod.invoke(overview));
assertEquals(5L, getPageSizeMethod.invoke(overview));
assertEquals(200, result.get("code"));
CcdiProjectRiskPeopleOverviewVO data = (CcdiProjectRiskPeopleOverviewVO) result.get("data");
assertEquals("中风险", data.getOverviewList().getFirst().getRiskLevel());
assertEquals("warning", data.getOverviewList().getFirst().getRiskLevelType());
assertEquals(4, data.getOverviewList().getFirst().getModelCount());
assertEquals("SALARY", data.getOverviewList().getFirst().getRiskPointTagList().getFirst().getModelCode());
verify(overviewService).getRiskPeopleOverview(40L);
Method method = CcdiProjectOverviewController.class.getMethod("getRiskPeople", Long.class);
Method method = CcdiProjectOverviewController.class.getMethod(
"getRiskPeople",
Class.forName("com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskPeopleQueryDTO")
);
GetMapping getMapping = method.getAnnotation(GetMapping.class);
PreAuthorize preAuthorize = method.getAnnotation(PreAuthorize.class);

View File

@@ -13,15 +13,20 @@ class CcdiProjectOverviewMapperSqlTest {
@Test
void shouldReadOverviewQueriesFromEmployeeResultTable() throws Exception {
String xml = Files.readString(Path.of("src/main/resources/mapper/ccdi/project/CcdiProjectOverviewMapper.xml"));
String riskPeopleSql = extractSelect(xml, "selectRiskPeopleOverviewByProjectId");
String riskPeopleSql = extractSelect(xml, "selectRiskPeopleOverviewPage");
String topRiskPeopleSql = extractSelect(xml, "selectTopRiskPeopleByProjectId");
String riskModelCardsSql = extractSelect(xml, "selectRiskModelCardsByProjectId");
String riskModelPeopleSql = extractSelect(xml, "selectRiskModelPeoplePage");
assertTrue(riskPeopleSql.contains("from ccdi_project_overview_employee_result"));
assertTrue(riskPeopleSql.contains("risk_level_code"));
assertTrue(riskPeopleSql.contains("model_count"));
assertTrue(riskPeopleSql.contains("risk_point"));
assertTrue(riskPeopleSql.contains("result.project_id = #{query.projectId}"), riskPeopleSql);
assertTrue(
riskPeopleSql.contains(
"order by risk_level_sort asc, result.model_count desc, result.rule_count desc, result.staff_id_card asc"
),
riskPeopleSql
);
assertFalse(riskPeopleSql.contains("limit 10"), riskPeopleSql);
assertFalse(riskPeopleSql.contains("resolvedEmployeeRiskBaseSql"));
assertTrue(topRiskPeopleSql.contains("from ccdi_project_overview_employee_result"));

View File

@@ -11,7 +11,10 @@ class CcdiProjectOverviewServiceStructureTest {
Class<?> clazz = Class.forName("com.ruoyi.ccdi.project.service.ICcdiProjectOverviewService");
assertNotNull(clazz.getMethod("getDashboard", Long.class));
assertNotNull(clazz.getMethod("getRiskPeopleOverview", Long.class));
assertNotNull(clazz.getMethod(
"getRiskPeopleOverview",
Class.forName("com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskPeopleQueryDTO")
));
assertNotNull(clazz.getMethod("getTopRiskPeople", Long.class));
assertNotNull(clazz.getMethod(
"getPersonAnalysisDetail",

View File

@@ -3,9 +3,10 @@ package com.ruoyi.ccdi.project.service.impl;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.ccdi.project.domain.CcdiProject;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectPersonAnalysisDetailQueryDTO;
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskModelPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.entity.CcdiProjectOverviewEmployeeResult;
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectEmployeeRiskAggregateVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectOverviewDashboardVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectOverviewEmployeeHitRowVO;
@@ -39,6 +40,8 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -85,6 +88,7 @@ class CcdiProjectOverviewServiceImplTest {
CcdiProject project = new CcdiProject();
project.setProjectId(40L);
when(projectMapper.selectById(40L)).thenReturn(project);
CcdiProjectRiskPeopleQueryDTO queryDTO = buildRiskPeopleQuery(40L);
CcdiProjectEmployeeRiskAggregateVO aggregate = new CcdiProjectEmployeeRiskAggregateVO();
aggregate.setStaffName("李四");
@@ -95,24 +99,70 @@ class CcdiProjectOverviewServiceImplTest {
aggregate.setRiskLevelCode("HIGH");
aggregate.setModelCount(3);
aggregate.setRiskPoint("大额单笔收入、疑似兼职");
when(overviewMapper.selectRiskPeopleOverviewByProjectId(40L)).thenReturn(List.of(aggregate));
Page<CcdiProjectEmployeeRiskAggregateVO> resultPage = new Page<>(1, 5);
resultPage.setRecords(List.of(aggregate));
resultPage.setTotal(1L);
when(overviewMapper.selectRiskPeopleOverviewPage(any(Page.class), any(CcdiProjectRiskPeopleQueryDTO.class)))
.thenReturn(resultPage);
when(overviewMapper.selectRiskHitTagsByScope(40L, "330000000000000001", null)).thenReturn(List.of(
buildHitTag("LARGE_TRANSACTION", "大额交易模型", "RULE_A", "大额单笔收入", "HIGH"),
buildHitTag("PART_TIME", "兼职取酬模型", "RULE_B", "疑似兼职", "MEDIUM")
));
CcdiProjectRiskPeopleOverviewVO overview = service.getRiskPeopleOverview(40L);
CcdiProjectRiskPeopleOverviewVO overview = service.getRiskPeopleOverview(queryDTO);
assertEquals(1, overview.getOverviewList().size());
assertEquals(8, overview.getOverviewList().getFirst().getRiskCount());
assertEquals("高风险", overview.getOverviewList().getFirst().getRiskLevel());
assertEquals("danger", overview.getOverviewList().getFirst().getRiskLevelType());
assertEquals(3, overview.getOverviewList().getFirst().getModelCount());
assertEquals(2, overview.getOverviewList().getFirst().getRiskPointTagList().size());
assertEquals("LARGE_TRANSACTION", overview.getOverviewList().getFirst().getRiskPointTagList().getFirst().getModelCode());
assertEquals("大额交易模型", overview.getOverviewList().getFirst().getRiskPointTagList().getFirst().getModelName());
assertEquals("大额单笔收入、疑似兼职", overview.getOverviewList().getFirst().getRiskPoint());
assertEquals("查看详情", overview.getOverviewList().getFirst().getActionLabel());
assertEquals(1, overview.getRows().size());
assertEquals(1L, overview.getTotal());
assertEquals(1L, overview.getPageNum());
assertEquals(5L, overview.getPageSize());
assertEquals(8, overview.getRows().getFirst().getRiskCount());
assertEquals("高风险", overview.getRows().getFirst().getRiskLevel());
assertEquals("danger", overview.getRows().getFirst().getRiskLevelType());
assertEquals(3, overview.getRows().getFirst().getModelCount());
assertEquals(2, overview.getRows().getFirst().getRiskPointTagList().size());
assertEquals("LARGE_TRANSACTION", overview.getRows().getFirst().getRiskPointTagList().getFirst().getModelCode());
assertEquals("大额交易模型", overview.getRows().getFirst().getRiskPointTagList().getFirst().getModelName());
assertEquals("大额单笔收入、疑似兼职", overview.getRows().getFirst().getRiskPoint());
assertEquals("查看详情", overview.getRows().getFirst().getActionLabel());
verify(overviewMapper).selectRiskPeopleOverviewPage(
argThat(page -> page.getCurrent() == 1L && page.getSize() == 5L),
argThat(query -> query.getProjectId().equals(40L))
);
}
@Test
void shouldDefaultRiskPeoplePageNumAndPageSizeToOneAndFive() {
CcdiProject project = new CcdiProject();
project.setProjectId(40L);
when(projectMapper.selectById(40L)).thenReturn(project);
Page<CcdiProjectEmployeeRiskAggregateVO> emptyPage = new Page<>(1, 5);
emptyPage.setRecords(List.of());
emptyPage.setTotal(0L);
when(overviewMapper.selectRiskPeopleOverviewPage(any(Page.class), any(CcdiProjectRiskPeopleQueryDTO.class)))
.thenReturn(emptyPage);
CcdiProjectRiskPeopleQueryDTO queryDTO = new CcdiProjectRiskPeopleQueryDTO();
queryDTO.setProjectId(40L);
service.getRiskPeopleOverview(queryDTO);
verify(overviewMapper).selectRiskPeopleOverviewPage(
argThat(page -> page.getCurrent() == 1L && page.getSize() == 5L),
any(CcdiProjectRiskPeopleQueryDTO.class)
);
clearInvocations(overviewMapper);
CcdiProjectRiskPeopleQueryDTO invalidQuery = new CcdiProjectRiskPeopleQueryDTO();
invalidQuery.setProjectId(40L);
invalidQuery.setPageNum(0);
invalidQuery.setPageSize(-1);
service.getRiskPeopleOverview(invalidQuery);
verify(overviewMapper, times(1)).selectRiskPeopleOverviewPage(
argThat(page -> page.getCurrent() == 1L && page.getSize() == 5L),
any(CcdiProjectRiskPeopleQueryDTO.class)
);
}
@Test
@@ -141,7 +191,7 @@ class CcdiProjectOverviewServiceImplTest {
void shouldThrowWhenProjectDoesNotExist() {
when(projectMapper.selectById(99L)).thenReturn(null);
assertThrows(ServiceException.class, () -> service.getRiskPeopleOverview(99L));
assertThrows(ServiceException.class, () -> service.getRiskPeopleOverview(buildRiskPeopleQuery(99L)));
assertThrows(ServiceException.class, () -> service.getTopRiskPeople(99L));
assertThrows(ServiceException.class, () -> service.getRiskModelCards(99L));
assertThrows(ServiceException.class, () -> service.getRiskModelPeople(buildRiskModelPeopleQuery(99L)));
@@ -358,6 +408,14 @@ class CcdiProjectOverviewServiceImplTest {
);
}
private CcdiProjectRiskPeopleQueryDTO buildRiskPeopleQuery(Long projectId) {
CcdiProjectRiskPeopleQueryDTO queryDTO = new CcdiProjectRiskPeopleQueryDTO();
queryDTO.setProjectId(projectId);
queryDTO.setPageNum(1);
queryDTO.setPageSize(5);
return queryDTO;
}
private CcdiProjectRiskModelPeopleQueryDTO buildRiskModelPeopleQuery(Long projectId) {
CcdiProjectRiskModelPeopleQueryDTO queryDTO = new CcdiProjectRiskModelPeopleQueryDTO();
queryDTO.setProjectId(projectId);