接通历史项目导入后端闭环
This commit is contained in:
@@ -16,6 +16,7 @@ import com.ruoyi.ccdi.project.mapper.CcdiProjectMapper;
|
||||
import com.ruoyi.ccdi.project.service.ICcdiBankTagService;
|
||||
import com.ruoyi.ccdi.project.service.ICcdiFileUploadService;
|
||||
import com.ruoyi.ccdi.project.service.ICcdiProjectService;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.lsfx.client.LsfxAnalysisClient;
|
||||
import com.ruoyi.lsfx.constants.LsfxConstants;
|
||||
import com.ruoyi.lsfx.domain.request.FetchInnerFlowRequest;
|
||||
@@ -964,6 +965,9 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
|
||||
if (record == null) {
|
||||
throw new RuntimeException("上传记录不存在");
|
||||
}
|
||||
if ("HISTORY_IMPORT".equals(record.getSourceType())) {
|
||||
throw new ServiceException("历史导入文件不支持删除");
|
||||
}
|
||||
if (!"parsed_success".equals(record.getFileStatus())) {
|
||||
if ("deleted".equals(record.getFileStatus())) {
|
||||
throw new RuntimeException("文件已删除,请勿重复操作");
|
||||
|
||||
@@ -2,11 +2,13 @@ package com.ruoyi.ccdi.project.service.impl;
|
||||
|
||||
import com.ruoyi.ccdi.project.domain.CcdiProject;
|
||||
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectImportHistoryDTO;
|
||||
import com.ruoyi.ccdi.project.domain.enums.TriggerType;
|
||||
import com.ruoyi.ccdi.project.domain.entity.CcdiBankStatement;
|
||||
import com.ruoyi.ccdi.project.domain.entity.CcdiFileUploadRecord;
|
||||
import com.ruoyi.ccdi.project.mapper.CcdiBankStatementMapper;
|
||||
import com.ruoyi.ccdi.project.mapper.CcdiFileUploadRecordMapper;
|
||||
import com.ruoyi.ccdi.project.mapper.CcdiProjectMapper;
|
||||
import com.ruoyi.ccdi.project.service.ICcdiBankTagService;
|
||||
import com.ruoyi.ccdi.project.service.ICcdiProjectHistoryImportService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -47,6 +49,9 @@ public class CcdiProjectHistoryImportServiceImpl implements ICcdiProjectHistoryI
|
||||
@Qualifier("fileUploadExecutor")
|
||||
private Executor fileUploadExecutor;
|
||||
|
||||
@Resource
|
||||
private ICcdiBankTagService bankTagService;
|
||||
|
||||
@Override
|
||||
public void submitImport(Long targetProjectId, Integer targetLsfxProjectId,
|
||||
CcdiProjectImportHistoryDTO dto, String operator) {
|
||||
@@ -97,6 +102,10 @@ public class CcdiProjectHistoryImportServiceImpl implements ICcdiProjectHistoryI
|
||||
if (!recordsToInsert.isEmpty()) {
|
||||
recordMapper.insertBatch(recordsToInsert);
|
||||
}
|
||||
if (!statementsToInsert.isEmpty()) {
|
||||
refreshProjectTargetCount(targetProjectId);
|
||||
bankTagService.submitAutoRebuild(targetProjectId, TriggerType.AUTO_BATCH_UPLOAD);
|
||||
}
|
||||
}
|
||||
|
||||
private CcdiBankStatement copyStatement(CcdiBankStatement sourceStatement, Long targetProjectId,
|
||||
@@ -136,6 +145,17 @@ public class CcdiProjectHistoryImportServiceImpl implements ICcdiProjectHistoryI
|
||||
return sourceProject == null ? null : sourceProject.getProjectName();
|
||||
}
|
||||
|
||||
private void refreshProjectTargetCount(Long targetProjectId) {
|
||||
CcdiProject targetProject = projectMapper.selectById(targetProjectId);
|
||||
if (targetProject == null) {
|
||||
log.warn("【项目历史导入】刷新目标人数时项目不存在: projectId={}", targetProjectId);
|
||||
return;
|
||||
}
|
||||
int targetCount = bankStatementMapper.countMatchedStaffCountByProjectId(targetProjectId);
|
||||
targetProject.setTargetCount(targetCount);
|
||||
projectMapper.updateById(targetProject);
|
||||
}
|
||||
|
||||
private void normalizeDedupFields(CcdiBankStatement statement) {
|
||||
statement.setLeAccountNo(trimToNull(statement.getLeAccountNo()));
|
||||
}
|
||||
|
||||
@@ -411,6 +411,20 @@ class CcdiFileUploadServiceImplTest {
|
||||
assertTrue(exception.getMessage().contains("仅支持删除解析成功文件"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteFileUploadRecord_shouldRejectHistoryImportRecord() {
|
||||
CcdiFileUploadRecord record = buildRecord();
|
||||
record.setFileStatus("parsed_success");
|
||||
record.setSourceType("HISTORY_IMPORT");
|
||||
when(recordMapper.selectById(RECORD_ID)).thenReturn(record);
|
||||
|
||||
ServiceException exception = assertThrows(ServiceException.class,
|
||||
() -> service.deleteFileUploadRecord(RECORD_ID, 9527L));
|
||||
|
||||
assertTrue(exception.getMessage().contains("历史导入文件不支持删除"));
|
||||
verify(lsfxClient, never()).deleteFiles(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteFileUploadRecord_shouldStopWhenLsfxDeleteFails() {
|
||||
CcdiFileUploadRecord record = buildRecord();
|
||||
|
||||
@@ -2,11 +2,13 @@ package com.ruoyi.ccdi.project.service.impl;
|
||||
|
||||
import com.ruoyi.ccdi.project.domain.CcdiProject;
|
||||
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectImportHistoryDTO;
|
||||
import com.ruoyi.ccdi.project.domain.enums.TriggerType;
|
||||
import com.ruoyi.ccdi.project.domain.entity.CcdiBankStatement;
|
||||
import com.ruoyi.ccdi.project.domain.entity.CcdiFileUploadRecord;
|
||||
import com.ruoyi.ccdi.project.mapper.CcdiBankStatementMapper;
|
||||
import com.ruoyi.ccdi.project.mapper.CcdiFileUploadRecordMapper;
|
||||
import com.ruoyi.ccdi.project.mapper.CcdiProjectMapper;
|
||||
import com.ruoyi.ccdi.project.service.ICcdiBankTagService;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
@@ -23,6 +25,7 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyList;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -46,6 +49,9 @@ class CcdiProjectHistoryImportServiceImplTest {
|
||||
@Mock
|
||||
private Executor fileUploadExecutor;
|
||||
|
||||
@Mock
|
||||
private ICcdiBankTagService bankTagService;
|
||||
|
||||
@Test
|
||||
void shouldFilterStatementsByTrxDateAndDeduplicateAcrossSourceProjects() {
|
||||
CcdiProjectImportHistoryDTO dto = buildImportDto();
|
||||
@@ -126,6 +132,30 @@ class CcdiProjectHistoryImportServiceImplTest {
|
||||
assertNotEquals(sourceRecord.getLogId(), insertedRecords.get().get(0).getLogId());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRefreshTargetCountAndSubmitAutoRebuildAfterImport() {
|
||||
CcdiProjectImportHistoryDTO dto = buildImportDto();
|
||||
when(recordMapper.selectSuccessfulRecordsByProjectIds(dto.getSourceProjectIds()))
|
||||
.thenReturn(List.of(buildSourceRecord(11L, 101, "批次A")));
|
||||
when(bankStatementMapper.selectStatementsForHistoryImport(11L, 101, "2026-01-01", "2026-01-31"))
|
||||
.thenReturn(List.of(buildStatement("2026-01-12", "6444", "300.00", "备注C")));
|
||||
doAnswer(invocation -> {
|
||||
Runnable runnable = invocation.getArgument(0);
|
||||
runnable.run();
|
||||
return null;
|
||||
}).when(fileUploadExecutor).execute(any(Runnable.class));
|
||||
when(projectMapper.selectById(11L)).thenReturn(buildProject(11L, "历史项目A"));
|
||||
when(projectMapper.selectById(90L)).thenReturn(buildProject(90L, "新项目"));
|
||||
when(bankStatementMapper.countMatchedStaffCountByProjectId(90L)).thenReturn(3);
|
||||
|
||||
service.submitImport(90L, 3001, dto, "tester");
|
||||
|
||||
verify(projectMapper).updateById(org.mockito.ArgumentMatchers.<CcdiProject>argThat(project ->
|
||||
Long.valueOf(90L).equals(project.getProjectId()) && Integer.valueOf(3).equals(project.getTargetCount())
|
||||
));
|
||||
verify(bankTagService).submitAutoRebuild(90L, TriggerType.AUTO_BATCH_UPLOAD);
|
||||
}
|
||||
|
||||
private CcdiProjectImportHistoryDTO buildImportDto() {
|
||||
CcdiProjectImportHistoryDTO dto = new CcdiProjectImportHistoryDTO();
|
||||
dto.setProjectName("新项目");
|
||||
|
||||
@@ -50,3 +50,10 @@
|
||||
- 将 `CcdiProjectHistoryImportServiceImpl` 扩展为真实异步复制链路:读取成功批次、按新批次号重建目标流水、按来源字段生成历史导入文件记录,并在导入前做内存去重
|
||||
- 新增 `CcdiProjectHistoryImportServiceImplTest` 与 XML 断言,验证日期范围传递、跨来源批次去重、新批次号生成及来源标识写入
|
||||
- 验证命令:`mvn -pl ccdi-project -am -Dtest=CcdiProjectHistoryImportServiceImplTest,CcdiFileUploadServiceImplTest,CcdiBankStatementMapperXmlTest -Dsurefire.failIfNoSpecifiedTests=false test`
|
||||
|
||||
### 2026-03-29 Task 5 后端自动打标与删除拦截收口
|
||||
|
||||
- 在 `CcdiProjectHistoryImportServiceImpl` 中补齐目标人数刷新与 `bankTagService.submitAutoRebuild(targetProjectId, TriggerType.AUTO_BATCH_UPLOAD)` 调用
|
||||
- 在 `CcdiFileUploadServiceImpl#validateDeleteRecord` 中优先拦截 `sourceType = HISTORY_IMPORT` 的记录,返回“历史导入文件不支持删除”
|
||||
- 扩展历史导入服务测试与文件删除测试,锁定自动重算与禁删行为
|
||||
- 完成后端回归验证:`mvn -pl ccdi-project -am -Dtest=CcdiProjectControllerTest,CcdiProjectControllerContractTest,CcdiProjectServiceImplTest,CcdiProjectHistoryImportServiceImplTest,CcdiFileUploadServiceImplTest,CcdiBankStatementMapperXmlTest -Dsurefire.failIfNoSpecifiedTests=false test`
|
||||
|
||||
Reference in New Issue
Block a user