搭建结果总览详情服务骨架

This commit is contained in:
wkc
2026-03-25 15:07:43 +08:00
parent 8df9dbacd8
commit 717f836190
4 changed files with 194 additions and 3 deletions

View File

@@ -1,11 +1,14 @@
package com.ruoyi.ccdi.project.mapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskModelPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.CcdiProject;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectRiskModelPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectEmployeeRiskAggregateVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskModelCardVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisBasicInfoVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisObjectRecordVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskHitTagVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskModelCardVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskModelPeopleItemVO;
import java.util.List;
import java.util.Map;
@@ -76,6 +79,42 @@ public interface CcdiProjectOverviewMapper {
@Param("selectedModelCodes") String selectedModelCodes
);
/**
* 查询项目分析基础信息
*
* @param projectId 项目ID
* @param staffIdCard 员工身份证号
* @return 项目分析基础信息
*/
CcdiProjectPersonAnalysisBasicInfoVO selectPersonAnalysisBasicInfo(
@Param("projectId") Long projectId,
@Param("staffIdCard") String staffIdCard
);
/**
* 查询项目分析流水异常明细
*
* @param projectId 项目ID
* @param staffIdCard 员工身份证号
* @return 流水异常明细
*/
List<CcdiBankStatementListVO> selectPersonAnalysisStatementRows(
@Param("projectId") Long projectId,
@Param("staffIdCard") String staffIdCard
);
/**
* 查询项目分析对象型异常记录
*
* @param projectId 项目ID
* @param staffIdCard 员工身份证号
* @return 对象型异常记录
*/
List<CcdiProjectPersonAnalysisObjectRecordVO> selectPersonAnalysisObjectRows(
@Param("projectId") Long projectId,
@Param("staffIdCard") String staffIdCard
);
/**
* 查询项目风险人数汇总
*

View File

@@ -5,7 +5,12 @@ import com.ruoyi.ccdi.project.domain.CcdiProject;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectPersonAnalysisDetailQueryDTO;
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.CcdiProjectPersonAnalysisDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisAbnormalDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisAbnormalGroupVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisBasicInfoVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisObjectRecordVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectEmployeeRiskAggregateVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectOverviewDashboardVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectOverviewEmployeeHitRowVO;
@@ -23,6 +28,7 @@ import com.ruoyi.ccdi.project.mapper.CcdiProjectOverviewMapper;
import com.ruoyi.ccdi.project.service.ICcdiProjectOverviewService;
import com.ruoyi.common.exception.ServiceException;
import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
@@ -105,7 +111,24 @@ public class CcdiProjectOverviewServiceImpl implements ICcdiProjectOverviewServi
@Override
public CcdiProjectPersonAnalysisDetailVO getPersonAnalysisDetail(CcdiProjectPersonAnalysisDetailQueryDTO queryDTO) {
ensureProjectExists(queryDTO.getProjectId());
return new CcdiProjectPersonAnalysisDetailVO();
CcdiProjectPersonAnalysisBasicInfoVO basicInfo = overviewMapper.selectPersonAnalysisBasicInfo(
queryDTO.getProjectId(),
queryDTO.getStaffIdCard()
);
List<CcdiBankStatementListVO> statementRows = defaultList(overviewMapper.selectPersonAnalysisStatementRows(
queryDTO.getProjectId(),
queryDTO.getStaffIdCard()
));
List<CcdiProjectPersonAnalysisObjectRecordVO> objectRows = defaultList(overviewMapper.selectPersonAnalysisObjectRows(
queryDTO.getProjectId(),
queryDTO.getStaffIdCard()
));
CcdiProjectPersonAnalysisDetailVO detail = new CcdiProjectPersonAnalysisDetailVO();
detail.setBasicInfo(basicInfo == null ? new CcdiProjectPersonAnalysisBasicInfoVO() : basicInfo);
detail.setAbnormalDetail(buildAbnormalDetail(statementRows, objectRows));
return detail;
}
@Override
@@ -261,6 +284,36 @@ public class CcdiProjectOverviewServiceImpl implements ICcdiProjectOverviewServi
return value == null ? List.of() : value;
}
private CcdiProjectPersonAnalysisAbnormalDetailVO buildAbnormalDetail(
List<CcdiBankStatementListVO> statementRows,
List<CcdiProjectPersonAnalysisObjectRecordVO> objectRows
) {
List<CcdiProjectPersonAnalysisAbnormalGroupVO> groups = new ArrayList<>();
if (!statementRows.isEmpty()) {
groups.add(buildAbnormalGroup("BANK_STATEMENT", "流水异常明细", "BANK_STATEMENT", statementRows));
}
if (!objectRows.isEmpty()) {
groups.add(buildAbnormalGroup("RELATED_OBJECT", "异常对象摘要", "OBJECT", objectRows));
}
CcdiProjectPersonAnalysisAbnormalDetailVO abnormalDetail = new CcdiProjectPersonAnalysisAbnormalDetailVO();
abnormalDetail.setGroups(groups);
return abnormalDetail;
}
private CcdiProjectPersonAnalysisAbnormalGroupVO buildAbnormalGroup(
String groupCode,
String groupName,
String groupType,
List<?> records
) {
CcdiProjectPersonAnalysisAbnormalGroupVO group = new CcdiProjectPersonAnalysisAbnormalGroupVO();
group.setGroupCode(groupCode);
group.setGroupName(groupName);
group.setGroupType(groupType);
group.setRecords(records);
return group;
}
private CcdiProject getRequiredProject(Long projectId) {
CcdiProject project = projectMapper.selectById(projectId);
if (project == null) {

View File

@@ -1,6 +1,9 @@
package com.ruoyi.ccdi.project.controller;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectPersonAnalysisDetailQueryDTO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectOverviewDashboardVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisBasicInfoVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskHitTagVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskPeopleOverviewItemVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskPeopleOverviewVO;
@@ -110,4 +113,38 @@ class CcdiProjectOverviewControllerTest {
assertNotNull(preAuthorize);
assertEquals("@ss.hasPermi('ccdi:project:query')", preAuthorize.value());
}
@Test
void shouldExposePersonAnalysisDetailEndpoint() throws Exception {
CcdiProjectPersonAnalysisDetailQueryDTO queryDTO = new CcdiProjectPersonAnalysisDetailQueryDTO();
queryDTO.setProjectId(40L);
queryDTO.setStaffIdCard("330000000000000001");
CcdiProjectPersonAnalysisBasicInfoVO basicInfo = new CcdiProjectPersonAnalysisBasicInfoVO();
basicInfo.setName("李四");
CcdiProjectPersonAnalysisDetailVO detail = new CcdiProjectPersonAnalysisDetailVO();
detail.setBasicInfo(basicInfo);
when(overviewService.getPersonAnalysisDetail(queryDTO)).thenReturn(detail);
AjaxResult result = controller.getPersonAnalysisDetail(queryDTO);
assertEquals(200, result.get("code"));
CcdiProjectPersonAnalysisDetailVO data = (CcdiProjectPersonAnalysisDetailVO) result.get("data");
assertEquals("李四", data.getBasicInfo().getName());
verify(overviewService).getPersonAnalysisDetail(queryDTO);
Method method = CcdiProjectOverviewController.class.getMethod(
"getPersonAnalysisDetail",
CcdiProjectPersonAnalysisDetailQueryDTO.class
);
GetMapping getMapping = method.getAnnotation(GetMapping.class);
PreAuthorize preAuthorize = method.getAnnotation(PreAuthorize.class);
Operation operation = method.getAnnotation(Operation.class);
assertNotNull(getMapping);
assertEquals("/person-analysis/detail", getMapping.value()[0]);
assertNotNull(preAuthorize);
assertEquals("@ss.hasPermi('ccdi:project:query')", preAuthorize.value());
assertNotNull(operation);
}
}

View File

@@ -2,11 +2,16 @@ 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.CcdiProjectRiskModelPeopleQueryDTO;
import com.ruoyi.ccdi.project.domain.entity.CcdiProjectOverviewEmployeeResult;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectEmployeeRiskAggregateVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectOverviewDashboardVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectOverviewEmployeeHitRowVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisDetailVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisBasicInfoVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectPersonAnalysisObjectRecordVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskModelCardVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskModelCardsVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskHitTagVO;
@@ -136,6 +141,56 @@ class CcdiProjectOverviewServiceImplTest {
assertThrows(ServiceException.class, () -> service.getTopRiskPeople(99L));
assertThrows(ServiceException.class, () -> service.getRiskModelCards(99L));
assertThrows(ServiceException.class, () -> service.getRiskModelPeople(buildRiskModelPeopleQuery(99L)));
assertThrows(ServiceException.class, () -> service.getPersonAnalysisDetail(buildPersonAnalysisDetailQuery(99L)));
}
@Test
void shouldReturnPersonAnalysisDetailWithBasicInfoAndGroupedAbnormalDetail() {
CcdiProject project = new CcdiProject();
project.setProjectId(40L);
when(projectMapper.selectById(40L)).thenReturn(project);
CcdiProjectPersonAnalysisBasicInfoVO basicInfo = new CcdiProjectPersonAnalysisBasicInfoVO();
basicInfo.setName("李四");
basicInfo.setIdNo("330000000000000001");
basicInfo.setStaffCode("10001");
basicInfo.setDepartment("信息二部");
basicInfo.setPhone("13800000000");
basicInfo.setRiskLevel("高风险");
basicInfo.setProjectName("测试项目");
when(overviewMapper.selectPersonAnalysisBasicInfo(40L, "330000000000000001")).thenReturn(basicInfo);
CcdiBankStatementListVO statementRow = new CcdiBankStatementListVO();
statementRow.setBankStatementId(1L);
statementRow.setTrxDate("2026-03-01 10:00:00");
statementRow.setLeAccountNo("62220001");
statementRow.setLeAccountName("李四");
statementRow.setCustomerAccountName("张三");
statementRow.setCustomerAccountNo("62220002");
statementRow.setUserMemo("转账");
statementRow.setCashType("转账汇款");
statementRow.setDisplayAmount(new BigDecimal("1000.00"));
when(overviewMapper.selectPersonAnalysisStatementRows(40L, "330000000000000001"))
.thenReturn(List.of(statementRow));
CcdiProjectPersonAnalysisObjectRecordVO objectRow = new CcdiProjectPersonAnalysisObjectRecordVO();
objectRow.setTitle("张三");
objectRow.setSubtitle("关联人员");
objectRow.setRiskTags(List.of("频繁往来"));
objectRow.setSummary("与项目关键人员存在异常资金往来");
when(overviewMapper.selectPersonAnalysisObjectRows(40L, "330000000000000001"))
.thenReturn(List.of(objectRow));
CcdiProjectPersonAnalysisDetailVO result = service.getPersonAnalysisDetail(buildPersonAnalysisDetailQuery(40L));
assertNotNull(result.getBasicInfo());
assertEquals("李四", result.getBasicInfo().getName());
assertEquals("高风险", result.getBasicInfo().getRiskLevel());
assertNotNull(result.getAbnormalDetail());
assertNotNull(result.getAbnormalDetail().getGroups());
assertEquals(2, result.getAbnormalDetail().getGroups().size());
assertEquals("BANK_STATEMENT", result.getAbnormalDetail().getGroups().get(0).getGroupType());
assertEquals("OBJECT", result.getAbnormalDetail().getGroups().get(1).getGroupType());
}
@Test
@@ -282,6 +337,13 @@ class CcdiProjectOverviewServiceImplTest {
return queryDTO;
}
private CcdiProjectPersonAnalysisDetailQueryDTO buildPersonAnalysisDetailQuery(Long projectId) {
CcdiProjectPersonAnalysisDetailQueryDTO queryDTO = new CcdiProjectPersonAnalysisDetailQueryDTO();
queryDTO.setProjectId(projectId);
queryDTO.setStaffIdCard("330000000000000001");
return queryDTO;
}
private CcdiProjectOverviewEmployeeResult buildEmployeeResult(String riskLevelCode) {
CcdiProjectOverviewEmployeeResult result = new CcdiProjectOverviewEmployeeResult();
result.setRiskLevelCode(riskLevelCode);