补充历史项目导入接口契约

This commit is contained in:
wkc
2026-03-29 09:47:43 +08:00
parent 36576fab78
commit eb0d896114
8 changed files with 183 additions and 0 deletions

View File

@@ -6,8 +6,10 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.PageDomain;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.page.TableSupport;
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.service.ICcdiProjectService;
@@ -19,6 +21,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 纪检初核项目管理Controller
*
@@ -100,6 +104,28 @@ public class CcdiProjectController extends BaseController {
return getDataTable(result.getRecords(), result.getTotal());
}
/**
* 查询历史项目列表
*/
@GetMapping("/history")
@Operation(summary = "查询历史项目列表")
@PreAuthorize("@ss.hasPermi('ccdi:project:list')")
public AjaxResult listHistoryProjects(CcdiProjectQueryDTO queryDTO) {
List<CcdiProjectHistoryListItemVO> result = projectService.listHistoryProjects(queryDTO);
return AjaxResult.success(result);
}
/**
* 从历史项目导入
*/
@PostMapping("/import")
@Operation(summary = "导入历史项目")
@PreAuthorize("@ss.hasPermi('ccdi:project:add')")
public AjaxResult importFromHistory(@Validated @RequestBody CcdiProjectImportHistoryDTO dto) {
CcdiProjectVO vo = projectService.importFromHistory(dto, SecurityUtils.getUsername());
return AjaxResult.success("项目创建成功", vo);
}
/**
* 查询项目状态统计
*/

View File

@@ -0,0 +1,36 @@
package com.ruoyi.ccdi.project.domain.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import java.util.List;
/**
* 历史项目导入DTO
*
* @author ruoyi
*/
@Data
public class CcdiProjectImportHistoryDTO {
/** 新项目名称 */
@NotBlank(message = "项目名称不能为空")
@Length(max = 200, message = "项目名称长度不能超过200个字符")
private String projectName;
/** 项目描述 */
@Length(max = 500, message = "项目描述长度不能超过500个字符")
private String description;
/** 来源项目ID列表 */
@NotEmpty(message = "来源项目不能为空")
private List<Long> sourceProjectIds;
/** 流水起始日期 */
private String startDate;
/** 流水结束日期 */
private String endDate;
}

View File

@@ -0,0 +1,32 @@
package com.ruoyi.ccdi.project.domain.vo;
import lombok.Data;
import java.util.Date;
/**
* 历史项目列表项VO
*
* @author ruoyi
*/
@Data
public class CcdiProjectHistoryListItemVO {
/** 项目ID */
private Long projectId;
/** 项目名称 */
private String projectName;
/** 项目描述 */
private String description;
/** 项目状态 */
private String status;
/** 是否归档 */
private Integer isArchived;
/** 创建时间 */
private Date createTime;
}

View File

@@ -1,11 +1,15 @@
package com.ruoyi.ccdi.project.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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 java.util.List;
/**
* 项目Service接口
*
@@ -53,6 +57,23 @@ public interface ICcdiProjectService {
*/
Page<CcdiProjectVO> selectProjectPage(Page<CcdiProjectVO> page, CcdiProjectQueryDTO queryDTO);
/**
* 查询历史项目列表
*
* @param queryDTO 查询条件
* @return 历史项目列表
*/
List<CcdiProjectHistoryListItemVO> listHistoryProjects(CcdiProjectQueryDTO queryDTO);
/**
* 从历史项目导入
*
* @param dto 导入参数
* @param operator 操作人
* @return 新建项目
*/
CcdiProjectVO importFromHistory(CcdiProjectImportHistoryDTO dto, String operator);
/**
* 查询各状态的项目总数(不受搜索条件影响)
*

View File

@@ -4,8 +4,10 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.ccdi.project.constants.CcdiProjectStatusConstants;
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;
@@ -21,7 +23,9 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
/**
@@ -114,6 +118,20 @@ public class CcdiProjectServiceImpl implements ICcdiProjectService {
return projectMapper.selectProjectPage(page, queryDTO);
}
@Override
public List<CcdiProjectHistoryListItemVO> listHistoryProjects(CcdiProjectQueryDTO queryDTO) {
return Collections.emptyList();
}
@Override
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);
}
@Override
public CcdiProjectStatusCountsVO getStatusCounts() {
CcdiProjectStatusCountsVO vo = new CcdiProjectStatusCountsVO();

View File

@@ -1,8 +1,11 @@
package com.ruoyi.ccdi.project.controller;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectImportHistoryDTO;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectQueryDTO;
import io.swagger.v3.oas.annotations.Operation;
import org.junit.jupiter.api.Test;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -30,4 +33,17 @@ class CcdiProjectControllerContractTest {
assertNotNull(operation);
assertEquals("归档项目", operation.summary());
}
@Test
void shouldExposeHistoryImportEndpointContracts() throws Exception {
Method history = CcdiProjectController.class.getMethod("listHistoryProjects", CcdiProjectQueryDTO.class);
GetMapping historyMapping = history.getAnnotation(GetMapping.class);
assertNotNull(historyMapping);
assertEquals("/history", historyMapping.value()[0]);
Method importing = CcdiProjectController.class.getMethod("importFromHistory", CcdiProjectImportHistoryDTO.class);
PostMapping importMapping = importing.getAnnotation(PostMapping.class);
assertNotNull(importMapping);
assertEquals("/import", importMapping.value()[0]);
}
}

View File

@@ -1,5 +1,7 @@
package com.ruoyi.ccdi.project.controller;
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectImportHistoryDTO;
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectVO;
import com.ruoyi.ccdi.project.service.ICcdiProjectService;
import com.ruoyi.common.core.domain.AjaxResult;
import io.swagger.v3.oas.annotations.Operation;
@@ -16,7 +18,10 @@ import java.lang.reflect.Method;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
@ExtendWith(MockitoExtension.class)
@@ -52,4 +57,26 @@ class CcdiProjectControllerTest {
assertNotNull(operation);
assertEquals("归档项目", operation.summary());
}
@Test
void shouldImportFromHistoryAndReturnCreatedProject() {
CcdiProjectImportHistoryDTO dto = new CcdiProjectImportHistoryDTO();
dto.setProjectName("新建项目");
CcdiProjectVO project = new CcdiProjectVO();
project.setProjectId(88L);
project.setProjectName("新建项目");
when(projectService.importFromHistory(eq(dto), eq("tester"))).thenReturn(project);
try (MockedStatic<com.ruoyi.common.utils.SecurityUtils> mocked = mockStatic(com.ruoyi.common.utils.SecurityUtils.class)) {
mocked.when(com.ruoyi.common.utils.SecurityUtils::getUsername).thenReturn("tester");
AjaxResult result = controller.importFromHistory(dto);
assertEquals(200, result.get("code"));
assertEquals("项目创建成功", result.get("msg"));
assertSame(project, result.get("data"));
verify(projectService).importFromHistory(dto, "tester");
}
}
}

View File

@@ -27,3 +27,10 @@
- 调整 `CcdiBankStatementMapper.xml` 详情查询,补充 `fur.source_project_name` 查询痕迹,为后续历史导入来源展示预留字段
- 新增 `CcdiBankStatementMapperXmlTest` 断言,先验证缺少来源字段时失败,再验证补齐后通过
- 验证命令:`mvn -pl ccdi-project -am -Dtest=CcdiBankStatementMapperXmlTest -Dsurefire.failIfNoSpecifiedTests=false test`
### 2026-03-29 Task 2 后端接口契约落地
- 新增 `CcdiProjectImportHistoryDTO``CcdiProjectHistoryListItemVO`,明确历史导入入参与历史项目列表返回结构
- 扩展 `ICcdiProjectService``CcdiProjectController``CcdiProjectServiceImpl`,补齐 `/ccdi/project/history``/ccdi/project/import` 最小接口骨架
- 新增控制器契约测试与导入返回结构测试,锁定真实接口路径和“项目创建成功”返回数据
- 验证命令:`mvn -pl ccdi-project -am -Dtest=CcdiProjectControllerContractTest,CcdiProjectControllerTest -Dsurefire.failIfNoSpecifiedTests=false test`