实现历史项目导入任务提交流程
This commit is contained in:
@@ -4,10 +4,13 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ruoyi.ccdi.project.domain.CcdiProject;
|
||||
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectQueryDTO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectHistoryListItemVO;
|
||||
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectVO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 项目Mapper接口
|
||||
*
|
||||
@@ -24,6 +27,14 @@ public interface CcdiProjectMapper extends BaseMapper<CcdiProject> {
|
||||
*/
|
||||
Page<CcdiProjectVO> selectProjectPage(Page<CcdiProjectVO> page, @Param("queryDTO") CcdiProjectQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 查询历史项目列表
|
||||
*
|
||||
* @param queryDTO 查询条件
|
||||
* @return 历史项目列表
|
||||
*/
|
||||
List<CcdiProjectHistoryListItemVO> selectHistoryProjects(@Param("queryDTO") CcdiProjectQueryDTO queryDTO);
|
||||
|
||||
/**
|
||||
* 更新项目风险人数
|
||||
*
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ruoyi.ccdi.project.service;
|
||||
|
||||
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectImportHistoryDTO;
|
||||
|
||||
/**
|
||||
* 历史项目导入服务
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
public interface ICcdiProjectHistoryImportService {
|
||||
|
||||
/**
|
||||
* 提交历史项目导入任务
|
||||
*
|
||||
* @param targetProjectId 目标项目ID
|
||||
* @param targetLsfxProjectId 目标流水分析项目ID
|
||||
* @param dto 导入参数
|
||||
* @param operator 操作人
|
||||
*/
|
||||
void submitImport(Long targetProjectId, Integer targetLsfxProjectId,
|
||||
CcdiProjectImportHistoryDTO dto, String operator);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.ruoyi.ccdi.project.service.impl;
|
||||
|
||||
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectImportHistoryDTO;
|
||||
import com.ruoyi.ccdi.project.service.ICcdiProjectHistoryImportService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* 历史项目导入服务实现
|
||||
*
|
||||
* @author ruoyi
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class CcdiProjectHistoryImportServiceImpl implements ICcdiProjectHistoryImportService {
|
||||
|
||||
@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
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ 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;
|
||||
@@ -21,9 +22,10 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.support.TransactionSynchronization;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@@ -43,6 +45,9 @@ public class CcdiProjectServiceImpl implements ICcdiProjectService {
|
||||
@Resource
|
||||
private LsfxAnalysisClient lsfxAnalysisClient;
|
||||
|
||||
@Resource
|
||||
private ICcdiProjectHistoryImportService historyImportService;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public CcdiProjectVO createProject(CcdiProjectSaveDTO dto) {
|
||||
@@ -120,16 +125,24 @@ public class CcdiProjectServiceImpl implements ICcdiProjectService {
|
||||
|
||||
@Override
|
||||
public List<CcdiProjectHistoryListItemVO> listHistoryProjects(CcdiProjectQueryDTO queryDTO) {
|
||||
return Collections.emptyList();
|
||||
return projectMapper.selectHistoryProjects(queryDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public CcdiProjectVO importFromHistory(CcdiProjectImportHistoryDTO dto, String operator) {
|
||||
CcdiProjectSaveDTO saveDTO = new CcdiProjectSaveDTO();
|
||||
saveDTO.setProjectName(dto.getProjectName());
|
||||
saveDTO.setDescription(dto.getDescription());
|
||||
saveDTO.setConfigType("default");
|
||||
return createProject(saveDTO);
|
||||
CcdiProjectVO project = createProject(saveDTO);
|
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||
@Override
|
||||
public void afterCommit() {
|
||||
historyImportService.submitImport(project.getProjectId(), project.getLsfxProjectId(), dto, operator);
|
||||
}
|
||||
});
|
||||
return project;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,6 +19,15 @@
|
||||
<result property="createByName" column="create_by_name"/>
|
||||
</resultMap>
|
||||
|
||||
<resultMap id="ProjectHistoryListItemResultMap" type="com.ruoyi.ccdi.project.domain.vo.CcdiProjectHistoryListItemVO">
|
||||
<id property="projectId" column="project_id"/>
|
||||
<result property="projectName" column="project_name"/>
|
||||
<result property="description" column="description"/>
|
||||
<result property="status" column="status"/>
|
||||
<result property="isArchived" column="is_archived"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
</resultMap>
|
||||
|
||||
<!-- 分页查询项目列表 -->
|
||||
<select id="selectProjectPage" resultMap="ProjectVOResultMap">
|
||||
SELECT
|
||||
@@ -41,6 +50,24 @@
|
||||
ORDER BY p.update_time DESC
|
||||
</select>
|
||||
|
||||
<select id="selectHistoryProjects" resultMap="ProjectHistoryListItemResultMap">
|
||||
SELECT
|
||||
p.project_id,
|
||||
p.project_name,
|
||||
p.description,
|
||||
p.status,
|
||||
p.is_archived,
|
||||
p.create_time
|
||||
FROM ccdi_project p
|
||||
<where>
|
||||
p.status in ('1', '2')
|
||||
<if test="queryDTO.projectName != null and queryDTO.projectName != ''">
|
||||
AND p.project_name LIKE CONCAT('%', #{queryDTO.projectName}, '%')
|
||||
</if>
|
||||
</where>
|
||||
ORDER BY p.update_time DESC
|
||||
</select>
|
||||
|
||||
<update id="updateRiskCountsByProjectId">
|
||||
update ccdi_project
|
||||
set high_risk_count = #{highRiskCount},
|
||||
|
||||
@@ -4,9 +4,14 @@ import ch.qos.logback.classic.Logger;
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.read.ListAppender;
|
||||
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.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;
|
||||
@@ -16,13 +21,19 @@ import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
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;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -38,6 +49,9 @@ class CcdiProjectServiceImplTest {
|
||||
@Mock
|
||||
private LsfxAnalysisClient lsfxAnalysisClient;
|
||||
|
||||
@Mock
|
||||
private ICcdiProjectHistoryImportService historyImportService;
|
||||
|
||||
@Test
|
||||
void shouldCountTaggingProjectsSeparately() {
|
||||
when(projectMapper.selectCount(any())).thenReturn(10L, 3L, 4L, 2L, 1L);
|
||||
@@ -106,6 +120,61 @@ class CcdiProjectServiceImplTest {
|
||||
() -> service.ensureProjectNotArchived(42L, "已归档项目暂不允许修改参数"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldOnlyReturnCompletedAndArchivedHistoryProjects() {
|
||||
CcdiProjectQueryDTO queryDTO = new CcdiProjectQueryDTO();
|
||||
queryDTO.setProjectName("历史");
|
||||
|
||||
CcdiProjectHistoryListItemVO completed = new CcdiProjectHistoryListItemVO();
|
||||
completed.setProjectId(1L);
|
||||
completed.setStatus("1");
|
||||
|
||||
CcdiProjectHistoryListItemVO archived = new CcdiProjectHistoryListItemVO();
|
||||
archived.setProjectId(2L);
|
||||
archived.setStatus("2");
|
||||
|
||||
when(projectMapper.selectHistoryProjects(queryDTO)).thenReturn(List.of(completed, archived));
|
||||
|
||||
List<CcdiProjectHistoryListItemVO> result = service.listHistoryProjects(queryDTO);
|
||||
|
||||
assertEquals(2, result.size());
|
||||
assertEquals(List.of(completed, archived), result);
|
||||
verify(projectMapper).selectHistoryProjects(queryDTO);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateProjectThenSubmitHistoryImportAfterCommit() {
|
||||
CcdiProjectImportHistoryDTO dto = new CcdiProjectImportHistoryDTO();
|
||||
dto.setProjectName("新项目");
|
||||
dto.setDescription("从历史导入");
|
||||
dto.setSourceProjectIds(List.of(11L, 12L));
|
||||
dto.setStartDate("2026-01-01");
|
||||
dto.setEndDate("2026-01-31");
|
||||
|
||||
when(lsfxAnalysisClient.getToken(any())).thenReturn(buildTokenResponse(3001));
|
||||
doAnswer(invocation -> {
|
||||
CcdiProject project = invocation.getArgument(0);
|
||||
project.setProjectId(90L);
|
||||
return 1;
|
||||
}).when(projectMapper).insert(any(CcdiProject.class));
|
||||
|
||||
TransactionSynchronizationManager.initSynchronization();
|
||||
try {
|
||||
CcdiProjectVO project = service.importFromHistory(dto, "tester");
|
||||
|
||||
assertNotNull(project);
|
||||
assertEquals(90L, project.getProjectId());
|
||||
assertEquals(1, TransactionSynchronizationManager.getSynchronizations().size());
|
||||
verify(historyImportService, never()).submitImport(any(), any(), any(), anyString());
|
||||
|
||||
TransactionSynchronizationManager.getSynchronizations().forEach(sync -> sync.afterCommit());
|
||||
|
||||
verify(historyImportService).submitImport(90L, 3001, dto, "tester");
|
||||
} finally {
|
||||
TransactionSynchronizationManager.clearSynchronization();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldLogProjectInitialStatusWhenProjectIsCreated() {
|
||||
CcdiProjectSaveDTO dto = new CcdiProjectSaveDTO();
|
||||
|
||||
Reference in New Issue
Block a user