修正风险仪表盘总人数员工匹配口径
This commit is contained in:
@@ -38,4 +38,6 @@ public interface CcdiBankStatementMapper extends BaseMapper<CcdiBankStatement> {
|
||||
CcdiBankStatementDetailVO selectStatementDetailById(@Param("bankStatementId") Long bankStatementId);
|
||||
|
||||
CcdiBankStatementFilterOptionsVO selectFilterOptions(@Param("projectId") Long projectId);
|
||||
|
||||
Integer countMatchedStaffCountByProjectId(@Param("projectId") Long projectId);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.ruoyi.ccdi.project.service.impl;
|
||||
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.ccdi.project.domain.CcdiProject;
|
||||
import com.ruoyi.ccdi.project.domain.enums.TriggerType;
|
||||
@@ -954,13 +953,7 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
|
||||
return;
|
||||
}
|
||||
|
||||
QueryWrapper<CcdiBankStatement> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.select("DISTINCT TRIM(cret_no)");
|
||||
queryWrapper.eq("project_id", projectId);
|
||||
queryWrapper.isNotNull("cret_no");
|
||||
queryWrapper.apply("TRIM(cret_no) <> ''");
|
||||
|
||||
int targetCount = bankStatementMapper.selectObjs(queryWrapper).size();
|
||||
int targetCount = bankStatementMapper.countMatchedStaffCountByProjectId(projectId);
|
||||
project.setTargetCount(targetCount);
|
||||
projectMapper.updateById(project);
|
||||
}
|
||||
|
||||
@@ -115,6 +115,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
select="selectOurAccountOptions"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="countMatchedStaffCountByProjectId" resultType="java.lang.Integer">
|
||||
select count(distinct trim(bs.cret_no))
|
||||
from ccdi_bank_statement bs
|
||||
inner join ccdi_base_staff staff on staff.id_card = bs.cret_no
|
||||
where bs.project_id = #{projectId}
|
||||
and bs.cret_no is not null
|
||||
and trim(bs.cret_no) != ''
|
||||
</select>
|
||||
|
||||
<sql id="parsedTrxDateExpr">
|
||||
CASE
|
||||
WHEN bs.TRX_DATE IS NULL OR TRIM(bs.TRX_DATE) = '' THEN NULL
|
||||
|
||||
@@ -287,7 +287,7 @@ class CcdiFileUploadServiceImplTest {
|
||||
CcdiProject project = new CcdiProject();
|
||||
project.setProjectId(PROJECT_ID);
|
||||
when(projectMapper.selectById(PROJECT_ID)).thenReturn(project);
|
||||
when(bankStatementMapper.selectObjs(any())).thenReturn(List.of("110101199001018888"));
|
||||
when(bankStatementMapper.countMatchedStaffCountByProjectId(PROJECT_ID)).thenReturn(1);
|
||||
|
||||
when(lsfxClient.uploadFile(eq(LSFX_PROJECT_ID), any())).thenReturn(buildUploadResponse());
|
||||
when(lsfxClient.checkParseStatus(LSFX_PROJECT_ID, String.valueOf(LOG_ID)))
|
||||
@@ -375,7 +375,7 @@ class CcdiFileUploadServiceImplTest {
|
||||
when(recordMapper.selectById(RECORD_ID)).thenReturn(record);
|
||||
when(lsfxClient.deleteFiles(any())).thenReturn(buildDeleteFilesResponse());
|
||||
when(projectMapper.selectById(PROJECT_ID)).thenReturn(project);
|
||||
when(bankStatementMapper.selectObjs(any())).thenReturn(List.of("110101199001018888", "110101199001019999"));
|
||||
when(bankStatementMapper.countMatchedStaffCountByProjectId(PROJECT_ID)).thenReturn(2);
|
||||
when(recordMapper.updateById(any(CcdiFileUploadRecord.class))).thenReturn(1);
|
||||
|
||||
String result = service.deleteFileUploadRecord(RECORD_ID, 9527L);
|
||||
@@ -562,14 +562,11 @@ class CcdiFileUploadServiceImplTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void refreshProjectTargetCount_shouldUpdateProjectWithDistinctIdCardCount() {
|
||||
void refreshProjectTargetCount_shouldUseMatchedStaffCountOnly() {
|
||||
CcdiProject project = new CcdiProject();
|
||||
project.setProjectId(PROJECT_ID);
|
||||
when(projectMapper.selectById(PROJECT_ID)).thenReturn(project);
|
||||
when(bankStatementMapper.selectObjs(any())).thenReturn(List.of(
|
||||
"110101199001018888",
|
||||
"110101199001019999"
|
||||
));
|
||||
when(bankStatementMapper.countMatchedStaffCountByProjectId(PROJECT_ID)).thenReturn(2);
|
||||
|
||||
ReflectionTestUtils.invokeMethod(service, "refreshProjectTargetCount", PROJECT_ID);
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# 风险仪表盘总人数员工匹配口径修正记录
|
||||
|
||||
**日期**: 2026-03-19
|
||||
**范围**: 后端
|
||||
|
||||
## 口径修正
|
||||
|
||||
- 原修复将 `target_count` 按项目流水中全部去重身份证号回写
|
||||
- 用户确认后的正确口径为:
|
||||
- 统计 `ccdi_bank_statement.cret_no`
|
||||
- 仅保留能匹配 `ccdi_base_staff.id_card` 的记录
|
||||
- 再按去重身份证号数量回写 `ccdi_project.target_count`
|
||||
|
||||
## 本次修改
|
||||
|
||||
1. 在 `CcdiBankStatementMapper` 新增“按项目统计匹配员工主数据后的去重身份证号人数”查询
|
||||
2. 在 `CcdiFileUploadServiceImpl.refreshProjectTargetCount` 中改为调用该查询
|
||||
3. 保持导入成功、删除成功后的目标人数刷新时机不变,仅修正统计口径
|
||||
4. 新增增量脚本 `sql/migration/2026-03-19-fix-project-target-count-match-staff.sql`,用于修正已错误回填的项目人数
|
||||
5. 调整单元测试,锁定“只统计能匹配员工主数据的人数”这一行为
|
||||
|
||||
## 验证
|
||||
|
||||
- 执行:`mvn -pl ccdi-project -Dtest=CcdiFileUploadServiceImplTest test`
|
||||
- 结果:通过
|
||||
@@ -0,0 +1,19 @@
|
||||
-- 修正项目目标人数口径
|
||||
-- 正确口径:银行流水中的身份证号在员工主数据中存在时,按去重身份证号数量回写 ccdi_project.target_count
|
||||
|
||||
UPDATE ccdi_project project
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
bs.project_id,
|
||||
COUNT(DISTINCT TRIM(bs.cret_no)) AS target_count
|
||||
FROM ccdi_bank_statement bs
|
||||
INNER JOIN ccdi_base_staff staff
|
||||
ON staff.id_card = bs.cret_no
|
||||
WHERE bs.cret_no IS NOT NULL
|
||||
AND TRIM(bs.cret_no) <> ''
|
||||
GROUP BY bs.project_id
|
||||
) stats ON stats.project_id = project.project_id
|
||||
SET project.target_count = COALESCE(stats.target_count, 0),
|
||||
project.update_by = 'system',
|
||||
project.update_time = NOW()
|
||||
WHERE project.del_flag = '0';
|
||||
Reference in New Issue
Block a user