修复历史项目导入解环与流水查询SQL

This commit is contained in:
wkc
2026-03-30 13:46:04 +08:00
parent 0a3c03dcf9
commit d582a65978
11 changed files with 330 additions and 23 deletions

View File

@@ -0,0 +1,38 @@
package com.ruoyi.ccdi.project.domain.event;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectImportHistoryDTO;
/**
* 历史项目导入提交事件
*/
public class CcdiProjectHistoryImportSubmittedEvent {
private final Long targetProjectId;
private final Integer targetLsfxProjectId;
private final CcdiProjectImportHistoryDTO dto;
private final String operator;
public CcdiProjectHistoryImportSubmittedEvent(Long targetProjectId, Integer targetLsfxProjectId,
CcdiProjectImportHistoryDTO dto, String operator) {
this.targetProjectId = targetProjectId;
this.targetLsfxProjectId = targetLsfxProjectId;
this.dto = dto;
this.operator = operator;
}
public Long getTargetProjectId() {
return targetProjectId;
}
public Integer getTargetLsfxProjectId() {
return targetLsfxProjectId;
}
public CcdiProjectImportHistoryDTO getDto() {
return dto;
}
public String getOperator() {
return operator;
}
}

View File

@@ -0,0 +1,27 @@
package com.ruoyi.ccdi.project.service.impl;
import com.ruoyi.ccdi.project.domain.event.CcdiProjectHistoryImportSubmittedEvent;
import com.ruoyi.ccdi.project.service.ICcdiProjectHistoryImportService;
import jakarta.annotation.Resource;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
/**
* 历史项目导入事件监听器
*/
@Component
public class CcdiProjectHistoryImportEventListener {
@Resource
private ICcdiProjectHistoryImportService historyImportService;
@EventListener
public void onSubmitted(CcdiProjectHistoryImportSubmittedEvent event) {
historyImportService.submitImport(
event.getTargetProjectId(),
event.getTargetLsfxProjectId(),
event.getDto(),
event.getOperator()
);
}
}

View File

@@ -7,11 +7,11 @@ import com.ruoyi.ccdi.project.domain.CcdiProject;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectImportHistoryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectSaveDTO;
import com.ruoyi.ccdi.project.domain.event.CcdiProjectHistoryImportSubmittedEvent;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectHistoryListItemVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectStatusCountsVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectVO;
import com.ruoyi.ccdi.project.mapper.CcdiProjectMapper;
import com.ruoyi.ccdi.project.service.ICcdiProjectHistoryImportService;
import com.ruoyi.ccdi.project.service.ICcdiProjectService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.lsfx.client.LsfxAnalysisClient;
@@ -20,6 +20,7 @@ import com.ruoyi.lsfx.domain.response.GetTokenResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
@@ -46,7 +47,7 @@ public class CcdiProjectServiceImpl implements ICcdiProjectService {
private LsfxAnalysisClient lsfxAnalysisClient;
@Resource
private ICcdiProjectHistoryImportService historyImportService;
private ApplicationEventPublisher applicationEventPublisher;
@Override
@Transactional(rollbackFor = Exception.class)
@@ -139,7 +140,9 @@ public class CcdiProjectServiceImpl implements ICcdiProjectService {
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
historyImportService.submitImport(project.getProjectId(), project.getLsfxProjectId(), dto, operator);
applicationEventPublisher.publishEvent(
new CcdiProjectHistoryImportSubmittedEvent(project.getProjectId(), project.getLsfxProjectId(), dto, operator)
);
}
});
return project;

View File

@@ -49,16 +49,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<sql id="selectCcdiBankStatementVo">
select bank_statement_id, project_id, LE_ID, ACCOUNT_ID, group_id,
LE_ACCOUNT_NAME, LE_ACCOUNT_NO, ACCOUNTING_DATE_ID, ACCOUNTING_DATE,
TRX_DATE, CURRENCY, AMOUNT_DR, AMOUNT_CR, AMOUNT_BALANCE,
CASH_TYPE, CUSTOMER_LE_ID, CUSTOMER_ACCOUNT_NAME, CUSTOMER_ACCOUNT_NO,
customer_bank, customer_reference, customer_cert_no, customer_social_credit_code, USER_MEMO, BANK_COMMENTS,
BANK_TRX_NUMBER, BANK, TRX_FLAG, TRX_TYPE, EXCEPTION_TYPE,
internal_flag, batch_id, batch_sequence, CREATE_DATE, created_by,
meta_json, no_balance, begin_balance, end_balance,
override_bs_id, payment_method, cret_no
from ccdi_bank_statement
bank_statement_id, project_id, LE_ID, ACCOUNT_ID, group_id,
LE_ACCOUNT_NAME, LE_ACCOUNT_NO, ACCOUNTING_DATE_ID, ACCOUNTING_DATE,
TRX_DATE, CURRENCY, AMOUNT_DR, AMOUNT_CR, AMOUNT_BALANCE,
CASH_TYPE, CUSTOMER_LE_ID, CUSTOMER_ACCOUNT_NAME, CUSTOMER_ACCOUNT_NO,
customer_bank, customer_reference, customer_cert_no, customer_social_credit_code, USER_MEMO, BANK_COMMENTS,
BANK_TRX_NUMBER, BANK, TRX_FLAG, TRX_TYPE, EXCEPTION_TYPE,
internal_flag, batch_id, batch_sequence, CREATE_DATE, created_by,
meta_json, no_balance, begin_balance, end_balance,
override_bs_id, payment_method, cret_no
</sql>
<resultMap id="CcdiBankStatementListVOResultMap" type="com.ruoyi.ccdi.project.domain.vo.CcdiBankStatementListVO">
@@ -304,8 +303,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectCcdiBankStatementVo"/>
FROM ccdi_bank_statement bs
<where>
bs.project_id = #{projectId}
AND bs.batch_id = #{batchId}
(bs.project_id = #{projectId})
AND (bs.batch_id = #{batchId})
<if test="startDate != null and startDate != ''">
AND (<include refid="parsedTrxDateExpr"/>) <![CDATA[ >= ]]>
CASE

View File

@@ -16,6 +16,7 @@ import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -172,6 +173,27 @@ class CcdiBankStatementMapperXmlTest {
}
}
@Test
void selectStatementsForHistoryImport_shouldNotGenerateDuplicatedSelectKeyword() throws Exception {
MappedStatement mappedStatement = loadMappedStatement(
"com.ruoyi.ccdi.project.mapper.CcdiBankStatementMapper.selectStatementsForHistoryImport");
Map<String, Object> params = new HashMap<>();
params.put("projectId", 48L);
params.put("batchId", 17094);
params.put("startDate", "2026-03-17");
params.put("endDate", "2026-03-18");
BoundSql boundSql = mappedStatement.getBoundSql(params);
String sql = boundSql.getSql().replaceAll("\\s+", " ").trim();
assertFalse(sql.startsWith("SELECT select"), sql);
assertTrue(sql.startsWith("SELECT bank_statement_id"), sql);
assertFalse(sql.contains("FROM ccdi_bank_statement FROM ccdi_bank_statement"), sql);
assertFalse(sql.contains("?AND"), sql);
assertTrue(sql.contains("WHERE (bs.project_id = ?) AND (bs.batch_id = ?) AND ( CASE"), sql);
}
@Test
void insertBatch_shouldAvoidUpdatingAutoIncrementPrimaryKeyInDuplicateBranch() throws Exception {
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(RESOURCE)) {

View File

@@ -7,20 +7,22 @@ import com.ruoyi.ccdi.project.domain.CcdiProject;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectImportHistoryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectQueryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectSaveDTO;
import com.ruoyi.ccdi.project.domain.event.CcdiProjectHistoryImportSubmittedEvent;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectHistoryListItemVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectStatusCountsVO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectVO;
import com.ruoyi.ccdi.project.mapper.CcdiProjectMapper;
import com.ruoyi.ccdi.project.service.ICcdiProjectHistoryImportService;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.lsfx.client.LsfxAnalysisClient;
import com.ruoyi.lsfx.domain.response.GetTokenResponse;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.util.List;
@@ -31,7 +33,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -50,7 +51,7 @@ class CcdiProjectServiceImplTest {
private LsfxAnalysisClient lsfxAnalysisClient;
@Mock
private ICcdiProjectHistoryImportService historyImportService;
private ApplicationEventPublisher applicationEventPublisher;
@Test
void shouldCountTaggingProjectsSeparately() {
@@ -143,7 +144,7 @@ class CcdiProjectServiceImplTest {
}
@Test
void shouldCreateProjectThenSubmitHistoryImportAfterCommit() {
void shouldCreateProjectThenPublishHistoryImportEventAfterCommit() {
CcdiProjectImportHistoryDTO dto = new CcdiProjectImportHistoryDTO();
dto.setProjectName("新项目");
dto.setDescription("从历史导入");
@@ -165,11 +166,18 @@ class CcdiProjectServiceImplTest {
assertNotNull(project);
assertEquals(90L, project.getProjectId());
assertEquals(1, TransactionSynchronizationManager.getSynchronizations().size());
verify(historyImportService, never()).submitImport(any(), any(), any(), anyString());
verify(applicationEventPublisher, never()).publishEvent(any());
TransactionSynchronizationManager.getSynchronizations().forEach(sync -> sync.afterCommit());
verify(historyImportService).submitImport(90L, 3001, dto, "tester");
ArgumentCaptor<Object> eventCaptor = ArgumentCaptor.forClass(Object.class);
verify(applicationEventPublisher).publishEvent(eventCaptor.capture());
CcdiProjectHistoryImportSubmittedEvent event =
(CcdiProjectHistoryImportSubmittedEvent) eventCaptor.getValue();
assertEquals(90L, event.getTargetProjectId());
assertEquals(3001, event.getTargetLsfxProjectId());
assertEquals("tester", event.getOperator());
assertEquals(dto, event.getDto());
} finally {
TransactionSynchronizationManager.clearSynchronization();
}