新增未提交账户风险明细

This commit is contained in:
wjj
2026-07-20 14:26:29 +08:00
parent 17628486ae
commit 7fec8e21be
16 changed files with 513 additions and 35 deletions

View File

@@ -26,6 +26,7 @@ import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskModelPeopleVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskPeopleOverviewVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectSuspiciousTransactionPageVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectTopRiskPeopleVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectUnsubmittedAccountFlowVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectUnsubmittedAccountVO;
import com.ruoyi.ccdi.project.service.CcdiProjectAccessService;
import com.ruoyi.ccdi.project.service.ICcdiProjectOverviewService;
@@ -241,6 +242,18 @@ public class CcdiProjectOverviewController extends BaseController {
return AjaxResult.success(result);
}
/**
* 查询未提交账户流水
*/
@GetMapping("/unsubmitted-accounts/flows")
@Operation(summary = "查询未提交账户流水")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public AjaxResult getUnsubmittedAccountFlows(CcdiProjectUnsubmittedAccountQueryDTO queryDTO) {
projectAccessService.assertCanRead(queryDTO.getProjectId());
List<CcdiProjectUnsubmittedAccountFlowVO> rows = overviewService.getUnsubmittedAccountFlows(queryDTO);
return AjaxResult.success(rows);
}
/**
* 导出涉疑交易明细
*/
@@ -323,9 +336,12 @@ public class CcdiProjectOverviewController extends BaseController {
@PostMapping("/unsubmitted-accounts/export")
@Operation(summary = "导出未提交账户流水")
@PreAuthorize("@ss.hasPermi('ccdi:project:query')")
public void exportUnsubmittedAccountFlows(HttpServletResponse response, Long projectId) {
projectAccessService.assertCanRead(projectId);
List<CcdiProjectUnsubmittedAccountFlowExcel> rows = overviewService.exportUnsubmittedAccountFlows(projectId);
public void exportUnsubmittedAccountFlows(
HttpServletResponse response,
CcdiProjectUnsubmittedAccountQueryDTO queryDTO
) {
projectAccessService.assertCanRead(queryDTO.getProjectId());
List<CcdiProjectUnsubmittedAccountFlowExcel> rows = overviewService.exportUnsubmittedAccountFlows(queryDTO);
ExcelUtil<CcdiProjectUnsubmittedAccountFlowExcel> util =
new ExcelUtil<>(CcdiProjectUnsubmittedAccountFlowExcel.class);
util.exportExcel(response, rows, "未提交账户流水");

View File

@@ -12,4 +12,14 @@ public class CcdiProjectUnsubmittedAccountQueryDTO {
* 项目ID
*/
private Long projectId;
/**
* 主体名称
*/
private String subjectName;
/**
* 未提交账号
*/
private String accountNo;
}

View File

@@ -35,9 +35,9 @@ public class CcdiProjectSuspiciousTransactionExcel {
@Excel(name = "交易类型")
private String cashType;
@Excel(name = "异常标签")
private String hitTags;
@Excel(name = "交易金额")
private BigDecimal displayAmount;
@Excel(name = "异常标签")
private String hitTags;
}

View File

@@ -9,6 +9,8 @@ import lombok.Data;
@Data
public class CcdiProjectUnsubmittedAccountFlowVO {
private Long bankStatementId;
private String subjectName;
private String accountNo;

View File

@@ -275,10 +275,12 @@ public interface CcdiProjectOverviewMapper {
/**
* 查询未提交账户流水
*
* @param projectId 项目ID
* @param query 查询条件
* @return 未提交账户流水
*/
List<CcdiProjectUnsubmittedAccountFlowVO> selectUnsubmittedAccountFlowList(@Param("projectId") Long projectId);
List<CcdiProjectUnsubmittedAccountFlowVO> selectUnsubmittedAccountFlowList(
@Param("query") CcdiProjectUnsubmittedAccountQueryDTO query
);
/**
* 查询项目员工负面征信导出列表

View File

@@ -28,6 +28,7 @@ import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskModelPeopleVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectRiskPeopleOverviewVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectSuspiciousTransactionPageVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectTopRiskPeopleVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectUnsubmittedAccountFlowVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectUnsubmittedAccountVO;
import jakarta.servlet.http.HttpServletResponse;
@@ -293,6 +294,18 @@ public interface ICcdiProjectOverviewService {
return new CcdiProjectUnsubmittedAccountVO();
}
/**
* 查询未提交账户流水
*
* @param queryDTO 查询条件
* @return 未提交账户流水
*/
default List<CcdiProjectUnsubmittedAccountFlowVO> getUnsubmittedAccountFlows(
CcdiProjectUnsubmittedAccountQueryDTO queryDTO
) {
return List.of();
}
/**
* 导出未提交账户流水
*
@@ -303,6 +316,18 @@ public interface ICcdiProjectOverviewService {
return List.of();
}
/**
* 导出未提交账户流水
*
* @param queryDTO 查询条件
* @return 导出列表
*/
default List<CcdiProjectUnsubmittedAccountFlowExcel> exportUnsubmittedAccountFlows(
CcdiProjectUnsubmittedAccountQueryDTO queryDTO
) {
return List.of();
}
/**
* 重算结果总览员工结果并同步项目风险人数
*

View File

@@ -506,10 +506,28 @@ public class CcdiProjectOverviewServiceImpl implements ICcdiProjectOverviewServi
}
@Override
public List<CcdiProjectUnsubmittedAccountFlowExcel> exportUnsubmittedAccountFlows(Long projectId) {
ensureProjectExists(projectId);
public List<CcdiProjectUnsubmittedAccountFlowVO> getUnsubmittedAccountFlows(
CcdiProjectUnsubmittedAccountQueryDTO queryDTO
) {
ensureProjectExists(queryDTO.getProjectId());
return defaultList(overviewMapper.selectUnsubmittedAccountFlowList(projectId)).stream()
return defaultList(overviewMapper.selectUnsubmittedAccountFlowList(queryDTO));
}
@Override
public List<CcdiProjectUnsubmittedAccountFlowExcel> exportUnsubmittedAccountFlows(Long projectId) {
CcdiProjectUnsubmittedAccountQueryDTO queryDTO = new CcdiProjectUnsubmittedAccountQueryDTO();
queryDTO.setProjectId(projectId);
return exportUnsubmittedAccountFlows(queryDTO);
}
@Override
public List<CcdiProjectUnsubmittedAccountFlowExcel> exportUnsubmittedAccountFlows(
CcdiProjectUnsubmittedAccountQueryDTO queryDTO
) {
ensureProjectExists(queryDTO.getProjectId());
return defaultList(overviewMapper.selectUnsubmittedAccountFlowList(queryDTO)).stream()
.map(this::buildUnsubmittedAccountFlowExcelRow)
.toList();
}

View File

@@ -56,8 +56,8 @@ public class CcdiProjectRiskDetailWorkbookExporter {
"关联员工",
"摘要",
"交易类型",
"异常标签",
"交易金额"
"交易金额",
"异常标签"
};
writeHeader(header, headers);
@@ -72,8 +72,8 @@ public class CcdiProjectRiskDetailWorkbookExporter {
row.createCell(5).setCellValue(safeText(item.getRelatedStaffDisplay()));
row.createCell(6).setCellValue(safeText(item.getUserMemo()));
row.createCell(7).setCellValue(safeText(item.getCashType()));
row.createCell(8).setCellValue(safeText(item.getHitTags()));
row.createCell(9).setCellValue(safeNumber(item.getDisplayAmount()));
row.createCell(8).setCellValue(safeNumber(item.getDisplayAmount()));
row.createCell(9).setCellValue(safeText(item.getHitTags()));
}
}

View File

@@ -111,6 +111,7 @@
</resultMap>
<resultMap id="UnsubmittedAccountFlowResultMap" type="com.ruoyi.ccdi.project.domain.vo.CcdiProjectUnsubmittedAccountFlowVO">
<result property="bankStatementId" column="bankStatementId"/>
<result property="subjectName" column="subjectName"/>
<result property="accountNo" column="accountNo"/>
<result property="trxDate" column="trxDate"/>
@@ -1729,8 +1730,9 @@
</select>
<select id="selectUnsubmittedAccountFlowList" resultMap="UnsubmittedAccountFlowResultMap">
<bind name="unsubmittedProjectId" value="projectId"/>
<bind name="unsubmittedProjectId" value="query.projectId"/>
select
candidate.bankStatementId,
candidate.subjectName,
candidate.accountNo,
candidate.trxDate,
@@ -1749,6 +1751,16 @@
<include refid="unsubmittedAccountAggregateSql"/>
) agg on agg.subjectName = candidate.subjectName
and agg.accountNo = candidate.accountNo
<where>
<if test="query.subjectName != null and query.subjectName != ''">
and replace(replace(trim(candidate.subjectName), '', '('), '', ')')
= replace(replace(trim(#{query.subjectName}), '', '('), '', ')')
</if>
<if test="query.accountNo != null and query.accountNo != ''">
and candidate.accountNo
= replace(replace(replace(trim(#{query.accountNo}), '-', ''), char(9), ''), ' ', '')
</if>
</where>
order by candidate.subjectName asc, candidate.accountNo asc, candidate.trxDate asc, candidate.bankStatementId asc
</select>

View File

@@ -251,6 +251,11 @@ class CcdiProjectOverviewMapperSqlTest {
assertTrue(accountSql.contains("unsubmittedAccountSubjectTotalSql"), accountSql);
assertTrue(flowSql.contains("unsubmittedAccountCandidateRowSql"), flowSql);
assertTrue(flowSql.contains("unsubmittedAccountAggregateSql"), flowSql);
assertTrue(flowSql.contains("query.projectId"), flowSql);
assertTrue(flowSql.contains("query.subjectName"), flowSql);
assertTrue(flowSql.contains("query.accountNo"), flowSql);
assertTrue(flowSql.contains("candidate.subjectName"), flowSql);
assertTrue(flowSql.contains("candidate.accountNo"), flowSql);
assertTrue(candidateSql.contains("bs.project_id = #{unsubmittedProjectId}"), candidateSql);
assertTrue(candidateSql.contains("bs.CUSTOMER_ACCOUNT_NAME"), candidateSql);
assertTrue(candidateSql.contains("bs.LE_ACCOUNT_NAME"), candidateSql);

View File

@@ -9,6 +9,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.mock.web.MockHttpServletResponse;
import java.io.ByteArrayInputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.List;
@@ -91,11 +92,12 @@ class CcdiProjectRiskDetailWorkbookExporterTest {
assertEquals("关联员工", workbook.getSheetAt(0).getRow(0).getCell(5).getStringCellValue());
assertEquals("摘要", workbook.getSheetAt(0).getRow(0).getCell(6).getStringCellValue());
assertEquals("交易类型", workbook.getSheetAt(0).getRow(0).getCell(7).getStringCellValue());
assertEquals("异常标签", workbook.getSheetAt(0).getRow(0).getCell(8).getStringCellValue());
assertEquals("交易金额", workbook.getSheetAt(0).getRow(0).getCell(9).getStringCellValue());
assertEquals("交易金额", workbook.getSheetAt(0).getRow(0).getCell(8).getStringCellValue());
assertEquals("异常标签", workbook.getSheetAt(0).getRow(0).getCell(9).getStringCellValue());
assertEquals("测试对手方", workbook.getSheetAt(0).getRow(1).getCell(3).getStringCellValue());
assertEquals("6222000000000001", workbook.getSheetAt(0).getRow(1).getCell(4).getStringCellValue());
assertEquals("异常标签", workbook.getSheetAt(0).getRow(1).getCell(8).getStringCellValue());
assertEquals(100D, workbook.getSheetAt(0).getRow(1).getCell(8).getNumericCellValue());
assertEquals("异常标签", workbook.getSheetAt(0).getRow(1).getCell(9).getStringCellValue());
assertEquals("账号", workbook.getSheetAt(2).getRow(0).getCell(0).getStringCellValue());
assertEquals("开户人", workbook.getSheetAt(2).getRow(0).getCell(1).getStringCellValue());
assertEquals("银行", workbook.getSheetAt(2).getRow(0).getCell(2).getStringCellValue());
@@ -122,4 +124,25 @@ class CcdiProjectRiskDetailWorkbookExporterTest {
assertEquals(30000D, workbook.getSheetAt(3).getRow(1).getCell(9).getNumericCellValue());
}
}
@Test
void shouldKeepSuspiciousTransactionExcelAmountBeforeHitTags() {
Field[] fields = CcdiProjectSuspiciousTransactionExcel.class.getDeclaredFields();
int amountIndex = findFieldIndex(fields, "displayAmount");
int hitTagsIndex = findFieldIndex(fields, "hitTags");
assertTrue(amountIndex >= 0);
assertTrue(hitTagsIndex >= 0);
assertTrue(amountIndex < hitTagsIndex);
}
private int findFieldIndex(Field[] fields, String fieldName) {
for (int i = 0; i < fields.length; i++) {
if (fieldName.equals(fields[i].getName())) {
return i;
}
}
return -1;
}
}