支持拉取行内和金综流水

This commit is contained in:
wjj
2026-07-20 13:07:49 +08:00
parent dd424cca50
commit 17628486ae
13 changed files with 283 additions and 30 deletions

View File

@@ -14,6 +14,7 @@ import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.page.TableSupport;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.lsfx.constants.LsfxConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
@@ -103,10 +104,10 @@ public class CcdiFileUploadController extends BaseController {
}
/**
* 提交拉取本行信息任务
* 提交拉取行内/金综流水任务
*/
@PostMapping("/pull-bank-info")
@Operation(summary = "拉取本行信息", description = "身份证号批量提交拉取本行信息任务")
@Operation(summary = "拉取行内/金综流水", description = "证件号码批量提交拉取行内/金综流水任务")
@PreAuthorize("@ss.hasPermi('ccdi:project:edit')")
public AjaxResult pullBankInfo(@RequestBody CcdiPullBankInfoSubmitDTO dto) {
if (dto == null || dto.getProjectId() == null) {
@@ -116,7 +117,16 @@ public class CcdiFileUploadController extends BaseController {
if (CollectionUtils.isEmpty(dto.getIdCards())) {
return AjaxResult.error("身份证号不能为空");
}
if (!StringUtils.hasText(dto.getStartDate()) || !StringUtils.hasText(dto.getEndDate())) {
if (!StringUtils.hasText(dto.getDataChannelCode())) {
return AjaxResult.error("流水来源不能为空");
}
String dataChannelCode = dto.getDataChannelCode().trim().toUpperCase();
if (!LsfxConstants.DATA_CHANNEL_ZJRCU.equals(dataChannelCode)
&& !LsfxConstants.DATA_CHANNEL_JZL.equals(dataChannelCode)) {
return AjaxResult.error("流水来源不支持");
}
if (LsfxConstants.DATA_CHANNEL_ZJRCU.equals(dataChannelCode)
&& (!StringUtils.hasText(dto.getStartDate()) || !StringUtils.hasText(dto.getEndDate()))) {
return AjaxResult.error("开始日期和结束日期不能为空");
}
@@ -125,6 +135,7 @@ public class CcdiFileUploadController extends BaseController {
String batchId = fileUploadService.submitPullBankInfo(
dto.getProjectId(),
dto.getIdCards(),
dataChannelCode,
dto.getStartDate(),
dto.getEndDate(),
userId,

View File

@@ -5,7 +5,7 @@ import lombok.Data;
import java.util.List;
/**
* 拉取本行信息提交参数
* 拉取行内/金综流水提交参数
*/
@Data
public class CcdiPullBankInfoSubmitDTO {
@@ -16,6 +16,9 @@ public class CcdiPullBankInfoSubmitDTO {
/** 身份证号列表 */
private List<String> idCards;
/** 数据渠道编码ZJRCU-行内JZL-金综 */
private String dataChannelCode;
/** 开始日期 */
private String startDate;

View File

@@ -35,10 +35,11 @@ public interface ICcdiFileUploadService {
List<String> parseIdCardFile(MultipartFile file);
/**
* 提交拉取本行信息任务
* 提交拉取行内/金综流水任务
*
* @param projectId 项目ID
* @param idCards 身份证号列表
* @param dataChannelCode 数据渠道编码
* @param startDate 开始日期
* @param endDate 结束日期
* @param userId 当前登录用户ID
@@ -47,6 +48,7 @@ public interface ICcdiFileUploadService {
*/
String submitPullBankInfo(Long projectId,
List<String> idCards,
String dataChannelCode,
String startDate,
String endDate,
Long userId,

View File

@@ -154,6 +154,7 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
@Override
public String submitPullBankInfo(Long projectId,
List<String> idCards,
String dataChannelCode,
String startDate,
String endDate,
Long userId,
@@ -161,17 +162,20 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
if (projectId == null) {
throw new IllegalArgumentException("项目ID不能为空");
}
if (!StringUtils.hasText(startDate) || !StringUtils.hasText(endDate)) {
throw new IllegalArgumentException("开始日期和结束日期不能为空");
}
if (idCards == null || idCards.isEmpty()) {
throw new IllegalArgumentException("身份证号不能为空");
}
String normalizedDataChannelCode = normalizePullBankInfoDataChannelCode(dataChannelCode);
LocalDate start = LocalDate.parse(startDate);
LocalDate end = LocalDate.parse(endDate);
if (start.isAfter(end)) {
throw new IllegalArgumentException("开始日期不能晚于结束日期");
if (LsfxConstants.DATA_CHANNEL_ZJRCU.equals(normalizedDataChannelCode)) {
if (!StringUtils.hasText(startDate) || !StringUtils.hasText(endDate)) {
throw new IllegalArgumentException("开始日期和结束日期不能为空");
}
LocalDate start = LocalDate.parse(startDate);
LocalDate end = LocalDate.parse(endDate);
if (start.isAfter(end)) {
throw new IllegalArgumentException("开始日期不能晚于结束日期");
}
}
projectService.ensureProjectNotArchived(projectId, "已归档项目暂不允许上传或拉取数据");
@@ -218,13 +222,26 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
@Override
public void afterCommit() {
CompletableFuture.runAsync(() -> submitPullBankInfoTasks(
projectId, lsfxProjectId, records, normalizedIdCards, startDate, endDate, batchId
projectId, lsfxProjectId, records, normalizedIdCards,
normalizedDataChannelCode, startDate, endDate, batchId
));
}
});
return batchId;
}
private String normalizePullBankInfoDataChannelCode(String dataChannelCode) {
if (!StringUtils.hasText(dataChannelCode)) {
throw new IllegalArgumentException("流水来源不能为空");
}
String normalized = dataChannelCode.trim().toUpperCase();
if (!LsfxConstants.DATA_CHANNEL_ZJRCU.equals(normalized)
&& !LsfxConstants.DATA_CHANNEL_JZL.equals(normalized)) {
throw new IllegalArgumentException("流水来源不支持");
}
return normalized;
}
@Override
public String deleteFileUploadRecord(Long id, Long operatorUserId) {
CcdiFileUploadRecord record = recordMapper.selectById(id);
@@ -580,6 +597,7 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
Integer lsfxProjectId,
List<CcdiFileUploadRecord> records,
List<String> idCards,
String dataChannelCode,
String startDate,
String endDate,
String batchId) {
@@ -601,7 +619,7 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
while (!submitted && retryCount < 2) {
try {
CompletableFuture<Boolean> future = CompletableFuture.supplyAsync(
() -> processPullBankInfoAsync(projectId, lsfxProjectId, record, idCard, startDate, endDate),
() -> processPullBankInfoAsync(projectId, lsfxProjectId, record, idCard, dataChannelCode, startDate, endDate),
fileUploadExecutor
);
futures.add(future);
@@ -640,16 +658,23 @@ public class CcdiFileUploadServiceImpl implements ICcdiFileUploadService {
Integer lsfxProjectId,
CcdiFileUploadRecord record,
String idCard,
String dataChannelCode,
String startDate,
String endDate ) {
try {
String normalizedDataChannelCode = normalizePullBankInfoDataChannelCode(dataChannelCode);
FetchInnerFlowRequest request = new FetchInnerFlowRequest();
request.setGroupId(lsfxProjectId);
request.setCustomerNo(idCard);
request.setDataChannelCode(LsfxConstants.DEFAULT_DATA_CHANNEL_CODE);
request.setDataChannelCode(normalizedDataChannelCode);
request.setRequestDateId(Integer.parseInt(LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE)));
request.setDataStartDateId(Integer.parseInt(startDate.replace("-", "")));
request.setDataEndDateId(Integer.parseInt(endDate.replace("-", "")));
if (LsfxConstants.DATA_CHANNEL_JZL.equals(normalizedDataChannelCode)) {
request.setDataStartDateId(0);
request.setDataEndDateId(0);
} else {
request.setDataStartDateId(Integer.parseInt(startDate.replace("-", "")));
request.setDataEndDateId(Integer.parseInt(endDate.replace("-", "")));
}
request.setUploadUserId(LsfxConstants.DEFAULT_USER_ID);
FetchInnerFlowResponse response = lsfxClient.fetchInnerFlow(request);

View File

@@ -88,11 +88,12 @@ class CcdiFileUploadControllerTest {
CcdiPullBankInfoSubmitDTO dto = new CcdiPullBankInfoSubmitDTO();
dto.setProjectId(PROJECT_ID);
dto.setIdCards(List.of("110101199001018888"));
dto.setDataChannelCode("ZJRCU");
dto.setStartDate("2026-03-01");
dto.setEndDate("2026-03-10");
setLoginUser(9527L, "admin");
when(fileUploadService.submitPullBankInfo(PROJECT_ID, dto.getIdCards(), "2026-03-01", "2026-03-10", 9527L, "admin"))
when(fileUploadService.submitPullBankInfo(PROJECT_ID, dto.getIdCards(), "ZJRCU", "2026-03-01", "2026-03-10", 9527L, "admin"))
.thenReturn("batch-1");
AjaxResult result = controller.pullBankInfo(dto);
@@ -100,6 +101,35 @@ class CcdiFileUploadControllerTest {
assertEquals(200, result.get("code"));
}
@Test
void pullBankInfo_shouldAllowJzlWithoutDateRange() {
CcdiPullBankInfoSubmitDTO dto = new CcdiPullBankInfoSubmitDTO();
dto.setProjectId(PROJECT_ID);
dto.setIdCards(List.of("110101199001018888"));
dto.setDataChannelCode("JZL");
setLoginUser(9527L, "admin");
when(fileUploadService.submitPullBankInfo(PROJECT_ID, dto.getIdCards(), "JZL", null, null, 9527L, "admin"))
.thenReturn("batch-1");
AjaxResult result = controller.pullBankInfo(dto);
assertEquals(200, result.get("code"));
}
@Test
void pullBankInfo_shouldRejectUnsupportedDataChannelCode() {
CcdiPullBankInfoSubmitDTO dto = new CcdiPullBankInfoSubmitDTO();
dto.setProjectId(PROJECT_ID);
dto.setIdCards(List.of("110101199001018888"));
dto.setDataChannelCode("OTHER");
AjaxResult result = controller.pullBankInfo(dto);
assertEquals(500, result.get("code"));
assertEquals("流水来源不支持", result.get("msg"));
}
@Test
void deleteFile_shouldUseCurrentLoginUserId() {
setLoginUser(9527L, "admin");

View File

@@ -16,6 +16,8 @@ import com.ruoyi.ccdi.project.service.ICcdiBankTagService;
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;
import com.ruoyi.lsfx.domain.request.GetBankStatementRequest;
import com.ruoyi.lsfx.domain.response.CheckParseStatusResponse;
import com.ruoyi.lsfx.domain.response.DeleteFilesResponse;
@@ -144,6 +146,7 @@ class CcdiFileUploadServiceImplTest {
String batchId = service.submitPullBankInfo(
PROJECT_ID,
List.of("110101199001018888", "110101199001019999"),
LsfxConstants.DATA_CHANNEL_ZJRCU,
"2026-03-01",
"2026-03-10",
9527L,
@@ -171,6 +174,7 @@ class CcdiFileUploadServiceImplTest {
() -> service.submitPullBankInfo(
PROJECT_ID,
List.of("3301"),
LsfxConstants.DATA_CHANNEL_ZJRCU,
"2026-01-01",
"2026-01-31",
1L,
@@ -438,6 +442,7 @@ class CcdiFileUploadServiceImplTest {
LSFX_PROJECT_ID,
record,
"110101199001018888",
LsfxConstants.DATA_CHANNEL_ZJRCU,
"2026-03-01",
"2026-03-10"
);
@@ -450,6 +455,34 @@ class CcdiFileUploadServiceImplTest {
);
}
@Test
void processPullBankInfoAsync_shouldFetchJzlWithZeroDateRange() {
when(lsfxClient.fetchInnerFlow(any())).thenReturn(buildFetchInnerFlowResponse(LOG_ID));
when(lsfxClient.checkParseStatus(LSFX_PROJECT_ID, String.valueOf(LOG_ID)))
.thenReturn(buildCheckParseStatusResponse(false));
when(lsfxClient.getFileUploadStatus(any())).thenReturn(buildParsedSuccessStatusResponse());
when(lsfxClient.getBankStatement(any(GetBankStatementRequest.class)))
.thenReturn(buildEmptyBankStatementResponse());
CcdiFileUploadRecord record = buildRecord();
service.processPullBankInfoAsync(
PROJECT_ID,
LSFX_PROJECT_ID,
record,
"110101199001018888",
LsfxConstants.DATA_CHANNEL_JZL,
null,
null
);
verify(lsfxClient).fetchInnerFlow(argThat((FetchInnerFlowRequest request) ->
LsfxConstants.DATA_CHANNEL_JZL.equals(request.getDataChannelCode())
&& Integer.valueOf(0).equals(request.getDataStartDateId())
&& Integer.valueOf(0).equals(request.getDataEndDateId())
));
}
@Test
void processFileAsync_shouldUploadToLsfxWithOriginalRecordFileName() throws IOException {
when(lsfxClient.uploadFile(eq(LSFX_PROJECT_ID), any(), eq("原始流水.xlsx")))