实现历史项目流水复制后端逻辑
This commit is contained in:
@@ -30,6 +30,11 @@ public interface CcdiBankStatementMapper extends BaseMapper<CcdiBankStatement> {
|
||||
int deleteByProjectIdAndBatchId(@Param("projectId") Long projectId,
|
||||
@Param("batchId") Integer batchId);
|
||||
|
||||
List<CcdiBankStatement> selectStatementsForHistoryImport(@Param("projectId") Long projectId,
|
||||
@Param("batchId") Integer batchId,
|
||||
@Param("startDate") String startDate,
|
||||
@Param("endDate") String endDate);
|
||||
|
||||
Page<CcdiBankStatementListVO> selectStatementPage(Page<CcdiBankStatementListVO> page,
|
||||
@Param("query") CcdiBankStatementQueryDTO query);
|
||||
|
||||
|
||||
@@ -25,6 +25,14 @@ public interface CcdiFileUploadRecordMapper extends BaseMapper<CcdiFileUploadRec
|
||||
*/
|
||||
int insertBatch(@Param("list") List<CcdiFileUploadRecord> records);
|
||||
|
||||
/**
|
||||
* 查询来源项目中解析成功且具备logId的文件记录
|
||||
*
|
||||
* @param projectIds 来源项目ID列表
|
||||
* @return 文件记录列表
|
||||
*/
|
||||
List<CcdiFileUploadRecord> selectSuccessfulRecordsByProjectIds(@Param("projectIds") List<Long> projectIds);
|
||||
|
||||
/**
|
||||
* 统计各状态文件数量
|
||||
*
|
||||
|
||||
@@ -1,11 +1,27 @@
|
||||
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.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.ICcdiProjectHistoryImportService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 历史项目导入服务实现
|
||||
@@ -16,12 +32,154 @@ import java.util.concurrent.CompletableFuture;
|
||||
@Service
|
||||
public class CcdiProjectHistoryImportServiceImpl implements ICcdiProjectHistoryImportService {
|
||||
|
||||
private static final AtomicInteger HISTORY_IMPORT_BATCH_ID = new AtomicInteger(1_000_000);
|
||||
|
||||
@Resource
|
||||
private CcdiBankStatementMapper bankStatementMapper;
|
||||
|
||||
@Resource
|
||||
private CcdiFileUploadRecordMapper recordMapper;
|
||||
|
||||
@Resource
|
||||
private CcdiProjectMapper projectMapper;
|
||||
|
||||
@Resource
|
||||
@Qualifier("fileUploadExecutor")
|
||||
private Executor fileUploadExecutor;
|
||||
|
||||
@Override
|
||||
public void submitImport(Long targetProjectId, Integer targetLsfxProjectId,
|
||||
CcdiProjectImportHistoryDTO dto, String operator) {
|
||||
CompletableFuture.runAsync(() -> log.info(
|
||||
"【项目历史导入】任务已提交: projectId={}, lsfxProjectId={}, sourceProjectIds={}, operator={}",
|
||||
targetProjectId, targetLsfxProjectId, dto.getSourceProjectIds(), operator
|
||||
));
|
||||
fileUploadExecutor.execute(() -> executeImport(targetProjectId, targetLsfxProjectId, dto, operator));
|
||||
}
|
||||
|
||||
private void executeImport(Long targetProjectId, Integer targetLsfxProjectId,
|
||||
CcdiProjectImportHistoryDTO dto, String operator) {
|
||||
List<CcdiFileUploadRecord> sourceRecords = recordMapper.selectSuccessfulRecordsByProjectIds(dto.getSourceProjectIds());
|
||||
if (sourceRecords == null || sourceRecords.isEmpty()) {
|
||||
log.info("【项目历史导入】无可复制的来源批次: projectId={}, sourceProjectIds={}",
|
||||
targetProjectId, dto.getSourceProjectIds());
|
||||
return;
|
||||
}
|
||||
|
||||
List<CcdiBankStatement> statementsToInsert = new ArrayList<>();
|
||||
List<CcdiFileUploadRecord> recordsToInsert = new ArrayList<>();
|
||||
Set<String> dedupKeys = new HashSet<>();
|
||||
|
||||
for (CcdiFileUploadRecord sourceRecord : sourceRecords) {
|
||||
List<CcdiBankStatement> sourceStatements = bankStatementMapper.selectStatementsForHistoryImport(
|
||||
sourceRecord.getProjectId(), sourceRecord.getLogId(), dto.getStartDate(), dto.getEndDate()
|
||||
);
|
||||
if (sourceStatements == null || sourceStatements.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Integer newBatchId = HISTORY_IMPORT_BATCH_ID.incrementAndGet();
|
||||
int sizeBefore = statementsToInsert.size();
|
||||
|
||||
for (CcdiBankStatement sourceStatement : sourceStatements) {
|
||||
CcdiBankStatement targetStatement = copyStatement(sourceStatement, targetProjectId, targetLsfxProjectId, newBatchId);
|
||||
if (dedupKeys.add(buildDedupKey(targetStatement))) {
|
||||
statementsToInsert.add(targetStatement);
|
||||
}
|
||||
}
|
||||
|
||||
if (statementsToInsert.size() > sizeBefore) {
|
||||
recordsToInsert.add(buildHistoryImportRecord(
|
||||
sourceRecord, targetProjectId, targetLsfxProjectId, newBatchId, resolveSourceProjectName(sourceRecord.getProjectId()), operator
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (!statementsToInsert.isEmpty()) {
|
||||
bankStatementMapper.insertBatch(statementsToInsert);
|
||||
}
|
||||
if (!recordsToInsert.isEmpty()) {
|
||||
recordMapper.insertBatch(recordsToInsert);
|
||||
}
|
||||
}
|
||||
|
||||
private CcdiBankStatement copyStatement(CcdiBankStatement sourceStatement, Long targetProjectId,
|
||||
Integer targetLsfxProjectId, Integer newBatchId) {
|
||||
CcdiBankStatement targetStatement = new CcdiBankStatement();
|
||||
BeanUtils.copyProperties(sourceStatement, targetStatement);
|
||||
targetStatement.setBankStatementId(null);
|
||||
targetStatement.setProjectId(targetProjectId);
|
||||
targetStatement.setGroupId(targetLsfxProjectId);
|
||||
targetStatement.setBatchId(newBatchId);
|
||||
normalizeDedupFields(targetStatement);
|
||||
return targetStatement;
|
||||
}
|
||||
|
||||
private CcdiFileUploadRecord buildHistoryImportRecord(CcdiFileUploadRecord sourceRecord, Long targetProjectId,
|
||||
Integer targetLsfxProjectId, Integer newBatchId,
|
||||
String sourceProjectName, String operator) {
|
||||
CcdiFileUploadRecord record = new CcdiFileUploadRecord();
|
||||
record.setProjectId(targetProjectId);
|
||||
record.setLsfxProjectId(targetLsfxProjectId);
|
||||
record.setLogId(newBatchId);
|
||||
record.setFileName(sourceRecord.getFileName());
|
||||
record.setFileSize(sourceRecord.getFileSize());
|
||||
record.setFileStatus("parsed_success");
|
||||
record.setEnterpriseNames(sourceRecord.getEnterpriseNames());
|
||||
record.setAccountNos(sourceRecord.getAccountNos());
|
||||
record.setUploadTime(new Date());
|
||||
record.setUploadUser(operator);
|
||||
record.setSourceType("HISTORY_IMPORT");
|
||||
record.setSourceProjectId(sourceRecord.getProjectId());
|
||||
record.setSourceProjectName(sourceProjectName);
|
||||
return record;
|
||||
}
|
||||
|
||||
private String resolveSourceProjectName(Long sourceProjectId) {
|
||||
CcdiProject sourceProject = projectMapper.selectById(sourceProjectId);
|
||||
return sourceProject == null ? null : sourceProject.getProjectName();
|
||||
}
|
||||
|
||||
private void normalizeDedupFields(CcdiBankStatement statement) {
|
||||
statement.setLeAccountNo(trimToNull(statement.getLeAccountNo()));
|
||||
}
|
||||
|
||||
private String trimToNull(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
String trimmed = value.trim();
|
||||
return trimmed.isEmpty() ? null : trimmed;
|
||||
}
|
||||
|
||||
private String buildDedupKey(CcdiBankStatement statement) {
|
||||
return String.join("|",
|
||||
valueOf(statement.getTrxDate()),
|
||||
valueOf(statement.getCurrency()),
|
||||
valueOf(statement.getLeAccountNo()),
|
||||
valueOf(statement.getLeAccountName()),
|
||||
valueOf(statement.getAccountId()),
|
||||
valueOf(statement.getCustomerAccountName()),
|
||||
valueOf(statement.getCustomerAccountNo()),
|
||||
valueOf(statement.getCustomerBank()),
|
||||
valueOf(statement.getCustomerReference()),
|
||||
valueOf(statement.getCustomerCertNo()),
|
||||
valueOf(statement.getCustomerSocialCreditCode()),
|
||||
valueOf(statement.getAmountDr()),
|
||||
valueOf(statement.getAmountCr()),
|
||||
valueOf(statement.getAmountBalance()),
|
||||
valueOf(statement.getCashType()),
|
||||
valueOf(statement.getUserMemo()),
|
||||
valueOf(statement.getBankComments()),
|
||||
valueOf(statement.getBankTrxNumber()),
|
||||
valueOf(statement.getBank()),
|
||||
valueOf(statement.getTrxFlag()),
|
||||
valueOf(statement.getTrxType()),
|
||||
valueOf(statement.getExceptionType()),
|
||||
valueOf(statement.getInternalFlag()),
|
||||
valueOf(statement.getCreateDate()),
|
||||
valueOf(statement.getPaymentMethod()),
|
||||
valueOf(statement.getCretNo())
|
||||
);
|
||||
}
|
||||
|
||||
private String valueOf(Object value) {
|
||||
return Objects.toString(value, "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,6 +299,33 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<include refid="statementOrderBy"/>
|
||||
</select>
|
||||
|
||||
<select id="selectStatementsForHistoryImport" resultMap="CcdiBankStatementResult">
|
||||
SELECT
|
||||
<include refid="selectCcdiBankStatementVo"/>
|
||||
FROM ccdi_bank_statement bs
|
||||
<where>
|
||||
bs.project_id = #{projectId}
|
||||
AND bs.batch_id = #{batchId}
|
||||
<if test="startDate != null and startDate != ''">
|
||||
AND (<include refid="parsedTrxDateExpr"/>) <![CDATA[ >= ]]>
|
||||
CASE
|
||||
WHEN LENGTH(TRIM(#{startDate})) = 10
|
||||
THEN STR_TO_DATE(CONCAT(TRIM(#{startDate}), ' 00:00:00'), '%Y-%m-%d %H:%i:%s')
|
||||
ELSE STR_TO_DATE(TRIM(#{startDate}), '%Y-%m-%d %H:%i:%s')
|
||||
END
|
||||
</if>
|
||||
<if test="endDate != null and endDate != ''">
|
||||
AND (<include refid="parsedTrxDateExpr"/>) <![CDATA[ <= ]]>
|
||||
CASE
|
||||
WHEN LENGTH(TRIM(#{endDate})) = 10
|
||||
THEN STR_TO_DATE(CONCAT(TRIM(#{endDate}), ' 23:59:59'), '%Y-%m-%d %H:%i:%s')
|
||||
ELSE STR_TO_DATE(TRIM(#{endDate}), '%Y-%m-%d %H:%i:%s')
|
||||
END
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY bs.batch_sequence ASC, bs.bank_statement_id ASC
|
||||
</select>
|
||||
|
||||
<select id="selectStatementDetailById" resultMap="CcdiBankStatementDetailVOResultMap">
|
||||
SELECT
|
||||
bs.bank_statement_id AS bankStatementId,
|
||||
|
||||
@@ -32,13 +32,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<!-- 批量插入 -->
|
||||
<insert id="insertBatch" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into ccdi_file_upload_record (
|
||||
project_id, lsfx_project_id, file_name, file_size, file_status,
|
||||
project_id, lsfx_project_id, log_id, file_name, file_size, file_status,
|
||||
source_type, source_project_id, source_project_name,
|
||||
enterprise_names, account_nos, upload_time, upload_user
|
||||
) values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(
|
||||
#{item.projectId}, #{item.lsfxProjectId}, #{item.fileName},
|
||||
#{item.projectId}, #{item.lsfxProjectId}, #{item.logId}, #{item.fileName},
|
||||
#{item.fileSize}, #{item.fileStatus}, #{item.sourceType},
|
||||
#{item.sourceProjectId}, #{item.sourceProjectName},
|
||||
#{item.enterpriseNames}, #{item.accountNos}, #{item.uploadTime}, #{item.uploadUser}
|
||||
@@ -46,6 +46,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<select id="selectSuccessfulRecordsByProjectIds" resultMap="CcdiFileUploadRecordResult">
|
||||
<include refid="selectCcdiFileUploadRecordVo"/>
|
||||
where project_id in
|
||||
<foreach collection="projectIds" item="projectId" open="(" separator="," close=")">
|
||||
#{projectId}
|
||||
</foreach>
|
||||
and file_status = 'parsed_success'
|
||||
and log_id is not null
|
||||
order by project_id asc, log_id asc, id asc
|
||||
</select>
|
||||
|
||||
<!-- 统计各状态文件数量 -->
|
||||
<select id="countByStatus" resultType="java.util.Map">
|
||||
select file_status as `status`, count(*) as count
|
||||
|
||||
Reference in New Issue
Block a user