fix(ccdi-project): delay parse success until bank statements saved

This commit is contained in:
wkc
2026-03-09 16:31:04 +08:00
parent e5116d000b
commit 3e0eb38f15
4 changed files with 359 additions and 78 deletions

View File

@@ -21,4 +21,7 @@ public interface CcdiBankStatementMapper extends BaseMapper<CcdiBankStatement> {
* @return 插入记录数
*/
int insertBatch(@Param("list") List<CcdiBankStatement> list);
int deleteByProjectIdAndBatchId(@Param("projectId") Long projectId,
@Param("batchId") Integer batchId);
}

View File

@@ -17,6 +17,7 @@ import com.ruoyi.lsfx.domain.request.GetBankStatementRequest;
import com.ruoyi.lsfx.domain.request.GetFileUploadStatusRequest;
import com.ruoyi.lsfx.domain.response.*;
import jakarta.annotation.Resource;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
@@ -49,6 +50,14 @@ import java.util.concurrent.RejectedExecutionException;
@Service
public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
@Data
private static class FetchBankStatementResult {
private boolean success;
private int totalCount;
private int savedCount;
private String errorMessage;
}
/**
* 若依框架文件上传路径
*/
@@ -426,17 +435,26 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
String enterpriseNamesStr = enterpriseNames != null ? String.join(",", enterpriseNames) : "";
String accountNosStr = accountNos != null ? String.join(",", accountNos) : "";
record.setFileStatus("parsed_success");
record.setEnterpriseNames(enterpriseNamesStr);
record.setAccountNos(accountNosStr);
recordMapper.updateById(record);
log.info("【文件上传】主体信息已保存: enterpriseNames={}, accountNos={}",
enterpriseNamesStr, accountNosStr);
// 步骤7:获取流水数据并保存
log.info("【文件上传】步骤7: 获取流水数据");
fetchAndSaveBankStatements(projectId, lsfxProjectId, logId);
FetchBankStatementResult fetchResult =
fetchAndSaveBankStatements(projectId, lsfxProjectId, logId);
if (!fetchResult.isSuccess()) {
record.setFileStatus("parsed_failed");
record.setErrorMessage(fetchResult.getErrorMessage());
recordMapper.updateById(record);
return;
}
record.setFileStatus("parsed_success");
record.setEnterpriseNames(enterpriseNamesStr);
record.setAccountNos(accountNosStr);
record.setErrorMessage(null);
recordMapper.updateById(record);
} else {
// 解析失败
@@ -524,97 +542,112 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
* @param groupId 流水分析平台项目ID
* @param logId 文件ID
*/
private void fetchAndSaveBankStatements(Long projectId, Integer groupId, Integer logId) {
private FetchBankStatementResult fetchAndSaveBankStatements(Long projectId, Integer groupId,
Integer logId) {
log.info("【文件上传】开始获取流水数据: projectId={}, groupId={}, logId={}",
projectId, groupId, logId);
// 步骤1: 先调用一次接口获取 totalCount
GetBankStatementRequest firstRequest = new GetBankStatementRequest();
firstRequest.setGroupId(groupId);
firstRequest.setLogId(logId);
firstRequest.setPageNow(1);
firstRequest.setPageSize(1); // 只获取1条用于获取总数
FetchBankStatementResult result = new FetchBankStatementResult();
GetBankStatementResponse firstResponse = lsfxClient.getBankStatement(firstRequest);
try {
GetBankStatementRequest firstRequest = new GetBankStatementRequest();
firstRequest.setGroupId(groupId);
firstRequest.setLogId(logId);
firstRequest.setPageNow(1);
firstRequest.setPageSize(1);
if (firstResponse == null || firstResponse.getData() == null) {
log.warn("【文件上传】获取流水数据失败: 响应数据为空");
return;
}
GetBankStatementResponse firstResponse = lsfxClient.getBankStatement(firstRequest);
if (firstResponse == null || firstResponse.getData() == null) {
result.setSuccess(false);
result.setErrorMessage("获取流水数据失败: 响应数据为空");
cleanupBankStatements(projectId, logId);
return result;
}
Integer totalCount = firstResponse.getData().getTotalCount();
if (totalCount == null || totalCount <= 0) {
log.warn("【文件上传】无流水数据需要保存: totalCount={}", totalCount);
return;
}
Integer totalCount = firstResponse.getData().getTotalCount();
result.setTotalCount(totalCount == null ? 0 : totalCount);
if (totalCount == null || totalCount <= 0) {
log.warn("【文件上传】无流水数据需要保存: totalCount={}", totalCount);
result.setSuccess(true);
result.setSavedCount(0);
return result;
}
log.info("【文件上传】获取到总数: totalCount={}", totalCount);
int pageSize = 1000;
int batchSize = 1000;
int totalPages = (int) Math.ceil((double) totalCount / pageSize);
int totalSaved = 0;
List<CcdiBankStatement> batchList = new ArrayList<>(batchSize);
// 步骤2: 计算分页信息
int pageSize = 1000; // 每页1000条
int batchSize = 1000; // 批量插入每批1000条与pageSize保持一致
int totalPages = (int) Math.ceil((double) totalCount / pageSize);
log.info("【文件上传】获取到总数: totalCount={}", totalCount);
log.info("【文件上传】分页信息: 每页{}条, 共{}页", pageSize, totalPages);
log.info("【文件上传】分页信息: 每页{}条, 共{}页", pageSize, totalPages);
for (int pageNow = 1; pageNow <= totalPages; pageNow++) {
try {
GetBankStatementRequest request = new GetBankStatementRequest();
request.setGroupId(groupId);
request.setLogId(logId);
request.setPageNow(pageNow);
request.setPageSize(pageSize);
List<CcdiBankStatement> batchList = new ArrayList<>(batchSize);
int totalSaved = 0;
GetBankStatementResponse response = lsfxClient.getBankStatement(request);
if (response == null || response.getData() == null
|| response.getData().getBankStatementList() == null) {
result.setSuccess(false);
result.setErrorMessage("获取流水数据失败: 第 " + pageNow + " 页响应异常");
cleanupBankStatements(projectId, logId);
return result;
}
// 步骤3: 循环分页获取所有数据
for (int pageNow = 1; pageNow <= totalPages; pageNow++) {
try {
// 构建请求参数
GetBankStatementRequest request = new GetBankStatementRequest();
request.setGroupId(groupId);
request.setLogId(logId);
request.setPageNow(pageNow);
request.setPageSize(pageSize);
List<GetBankStatementResponse.BankStatementItem> items =
response.getData().getBankStatementList();
log.debug("【文件上传】获取第{}页数据: {}条", pageNow, items.size());
// 获取流水数据
GetBankStatementResponse response = lsfxClient.getBankStatement(request);
for (GetBankStatementResponse.BankStatementItem item : items) {
CcdiBankStatement statement = CcdiBankStatement.fromResponse(item);
if (statement != null) {
statement.setBatchId(logId);
statement.setProjectId(projectId);
batchList.add(statement);
if (response == null || response.getData() == null
|| response.getData().getBankStatementList() == null) {
log.warn("【文件上传】获取流水数据为空: pageNow={}", pageNow);
continue;
}
List<GetBankStatementResponse.BankStatementItem> items =
response.getData().getBankStatementList();
log.debug("【文件上传】获取第{}页数据: {}条", pageNow, items.size());
// 转换并收集到批量列表
for (GetBankStatementResponse.BankStatementItem item : items) {
CcdiBankStatement statement = CcdiBankStatement.fromResponse(item);
if (statement != null) {
statement.setProjectId(projectId); // 设置业务项目ID
batchList.add(statement);
// 达到批量插入阈值1000条执行插入
if (batchList.size() >= batchSize) {
bankStatementMapper.insertBatch(batchList);
totalSaved += batchList.size();
log.debug("【文件上传】批量插入流水: {}条, 累计{}条",
batchList.size(), totalSaved);
batchList.clear();
if (batchList.size() >= batchSize) {
bankStatementMapper.insertBatch(batchList);
totalSaved += batchList.size();
log.debug("【文件上传】批量插入流水 {}条, 累计{}条",
batchList.size(), totalSaved);
batchList.clear();
}
}
}
} catch (Exception e) {
log.error("【文件上传】获取或保存流水数据失败: pageNow={}", pageNow, e);
result.setSuccess(false);
result.setErrorMessage("获取或保存流水数据失败: " + e.getMessage());
cleanupBankStatements(projectId, logId);
return result;
}
} catch (Exception e) {
log.error("【文件上传】获取或保存流水数据失败: pageNow={}", pageNow, e);
// 继续处理下一页,不中断整个流程
}
}
// 步骤4: 保存剩余的数据
if (!batchList.isEmpty()) {
bankStatementMapper.insertBatch(batchList);
totalSaved += batchList.size();
log.debug("【文件上传】批量插入剩余流水: {}条", batchList.size());
}
if (!batchList.isEmpty()) {
bankStatementMapper.insertBatch(batchList);
totalSaved += batchList.size();
log.debug("【文件上传】批量插入剩余流水 {}条", batchList.size());
}
log.info("【文件上传】流水数据保存完成: 总共保存{}条", totalSaved);
log.info("【文件上传】流水数据保存完成: 总共保存{}条", totalSaved);
result.setSuccess(true);
result.setSavedCount(totalSaved);
return result;
} catch (Exception e) {
log.error("【文件上传】获取或保存流水数据失败: logId={}", logId, e);
result.setSuccess(false);
result.setErrorMessage("获取或保存流水数据失败: " + e.getMessage());
cleanupBankStatements(projectId, logId);
return result;
}
}
private void cleanupBankStatements(Long projectId, Integer logId) {
bankStatementMapper.deleteByProjectIdAndBatchId(projectId, logId);
}
}

View File

@@ -86,4 +86,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach>
</insert>
<delete id="deleteByProjectIdAndBatchId">
delete from ccdi_bank_statement
where project_id = #{projectId}
and batch_id = #{batchId}
</delete>
</mapper>