补充历史项目导入接口契约
This commit is contained in:
@@ -6,8 +6,10 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
|||||||
import com.ruoyi.common.core.page.PageDomain;
|
import com.ruoyi.common.core.page.PageDomain;
|
||||||
import com.ruoyi.common.core.page.TableDataInfo;
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
import com.ruoyi.common.core.page.TableSupport;
|
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.CcdiProjectQueryDTO;
|
||||||
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectSaveDTO;
|
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.CcdiProjectStatusCountsVO;
|
||||||
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectVO;
|
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectVO;
|
||||||
import com.ruoyi.ccdi.project.service.ICcdiProjectService;
|
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.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 纪检初核项目管理Controller
|
* 纪检初核项目管理Controller
|
||||||
*
|
*
|
||||||
@@ -100,6 +104,28 @@ public class CcdiProjectController extends BaseController {
|
|||||||
return getDataTable(result.getRecords(), result.getTotal());
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询项目状态统计
|
* 查询项目状态统计
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -1,11 +1,15 @@
|
|||||||
package com.ruoyi.ccdi.project.service;
|
package com.ruoyi.ccdi.project.service;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
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.CcdiProjectQueryDTO;
|
||||||
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectSaveDTO;
|
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.CcdiProjectStatusCountsVO;
|
||||||
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectVO;
|
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectVO;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 项目Service接口
|
* 项目Service接口
|
||||||
*
|
*
|
||||||
@@ -53,6 +57,23 @@ public interface ICcdiProjectService {
|
|||||||
*/
|
*/
|
||||||
Page<CcdiProjectVO> selectProjectPage(Page<CcdiProjectVO> page, CcdiProjectQueryDTO queryDTO);
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询各状态的项目总数(不受搜索条件影响)
|
* 查询各状态的项目总数(不受搜索条件影响)
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.ruoyi.ccdi.project.constants.CcdiProjectStatusConstants;
|
import com.ruoyi.ccdi.project.constants.CcdiProjectStatusConstants;
|
||||||
import com.ruoyi.ccdi.project.domain.CcdiProject;
|
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.CcdiProjectQueryDTO;
|
||||||
import com.ruoyi.ccdi.project.domain.dto.CcdiProjectSaveDTO;
|
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.CcdiProjectStatusCountsVO;
|
||||||
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectVO;
|
import com.ruoyi.ccdi.project.domain.vo.CcdiProjectVO;
|
||||||
import com.ruoyi.ccdi.project.mapper.CcdiProjectMapper;
|
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.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,6 +118,20 @@ public class CcdiProjectServiceImpl implements ICcdiProjectService {
|
|||||||
return projectMapper.selectProjectPage(page, queryDTO);
|
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
|
@Override
|
||||||
public CcdiProjectStatusCountsVO getStatusCounts() {
|
public CcdiProjectStatusCountsVO getStatusCounts() {
|
||||||
CcdiProjectStatusCountsVO vo = new CcdiProjectStatusCountsVO();
|
CcdiProjectStatusCountsVO vo = new CcdiProjectStatusCountsVO();
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package com.ruoyi.ccdi.project.controller;
|
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 io.swagger.v3.oas.annotations.Operation;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
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.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
@@ -30,4 +33,17 @@ class CcdiProjectControllerContractTest {
|
|||||||
assertNotNull(operation);
|
assertNotNull(operation);
|
||||||
assertEquals("归档项目", operation.summary());
|
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]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.ruoyi.ccdi.project.controller;
|
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.ccdi.project.service.ICcdiProjectService;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
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.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
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.mockStatic;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
@@ -52,4 +57,26 @@ class CcdiProjectControllerTest {
|
|||||||
assertNotNull(operation);
|
assertNotNull(operation);
|
||||||
assertEquals("归档项目", operation.summary());
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,3 +27,10 @@
|
|||||||
- 调整 `CcdiBankStatementMapper.xml` 详情查询,补充 `fur.source_project_name` 查询痕迹,为后续历史导入来源展示预留字段
|
- 调整 `CcdiBankStatementMapper.xml` 详情查询,补充 `fur.source_project_name` 查询痕迹,为后续历史导入来源展示预留字段
|
||||||
- 新增 `CcdiBankStatementMapperXmlTest` 断言,先验证缺少来源字段时失败,再验证补齐后通过
|
- 新增 `CcdiBankStatementMapperXmlTest` 断言,先验证缺少来源字段时失败,再验证补齐后通过
|
||||||
- 验证命令:`mvn -pl ccdi-project -am -Dtest=CcdiBankStatementMapperXmlTest -Dsurefire.failIfNoSpecifiedTests=false test`
|
- 验证命令:`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`
|
||||||
|
|||||||
Reference in New Issue
Block a user