Merge remote-tracking branch 'upstream/product_refact' into product_refact_stat

# Conflicts:
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/dashboard/controller/PmsDashboardController.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/product/mapper/PmsProductRequirementMapper.java
#	microservices-modules/microservices-modules-pms/src/main/java/com/microservices/pms/product/service/IPmsProductRequirementService.java
This commit is contained in:
liuhuazhong 2024-12-12 09:57:32 +08:00
commit ffbe18645c
33 changed files with 498 additions and 95 deletions

View File

@ -5,6 +5,7 @@ import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.constant.Constants;
import com.microservices.common.core.constant.HttpStatus;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.httpClient.domain.CustomHttpDelete;
import com.microservices.system.api.domain.SysFileBytes;
import org.apache.commons.collections4.MapUtils;
@ -281,6 +282,9 @@ public class HttpAPIService {
long length = httpEntity.getContentLength();
if (length != 0L) {
String result = EntityUtils.toString(httpEntity);
if (!JSON.isValid(result)) {
throw new ServiceException("平台接口响应格式异常");
}
Object resultObj = JSON.parse(result);
if (resultObj instanceof JSONArray) {
JSONObject jsonObject = new JSONObject();

View File

@ -263,7 +263,7 @@ public class SysFileInfoServiceImpl implements ISysFileInfoService {
@Override
public void fileDownloadByIdentifier(String fileIdentifier, HttpServletResponse response, HttpServletRequest request) {
SysFileInfo sysFileInfo = selectSysFileInfoByFileIdentifier(fileIdentifier);
if (StringUtils.isEmpty(sysFileInfo.getFilePath()) || !sysFileInfo.getFilePath().contains("/zone-identifier")) {
if (StringUtils.isEmpty(sysFileInfo.getFilePath())) {
throw new ServiceException("当前文件无法下载");
}
fileDownload(sysFileInfo, response);

View File

@ -10,6 +10,7 @@ import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.pms.dashboard.domain.vo.MyDashboardVo;
import com.microservices.pms.dashboard.domain.vo.MyProjectIssuesSearchVo;
import com.microservices.pms.dashboard.domain.vo.MyTodoProjectIssuesSearchVo;
import com.microservices.pms.product.domain.PmsProduct;
import com.microservices.pms.product.domain.PmsProductRequirement;
import com.microservices.pms.product.domain.PmsProductStatus;
@ -24,11 +25,9 @@ import com.microservices.pms.project.domain.vo.*;
import com.microservices.pms.project.service.IPmsProjectService;
import com.microservices.pms.project.service.IPmsProjectSprintService;
import com.microservices.pms.project.service.PmsProjectIssuesService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@ -99,16 +98,13 @@ public class PmsDashboardController extends BaseController {
@GetMapping("/myProjectIssues")
@ApiOperation(value = "我的工作项")
public AjaxResult myProjectIssues(MyProjectIssuesSearchVo myProjectIssuesSearchVo) {
PmsProjectIssuesSearchVo pmsProjectIssuesSearchVo = new PmsProjectIssuesSearchVo();
BeanUtils.copyProperties(myProjectIssuesSearchVo, pmsProjectIssuesSearchVo);
List<PmsProject> projectList = pmsProjectService.selectPmsProjectList(new PmsProject());
if(projectList.isEmpty()){
return success();
}
pmsProjectIssuesSearchVo.setPmProjectIds(StringUtils.join(projectList.stream().map(PmsProject::getId).toArray(), ","));
// 不包含周报
pmsProjectIssuesSearchVo.setPmIssueTypes("1,2,3");
JSONObject result = pmsProjectIssuesService.selectPmsProjectIssuesList(pmsProjectIssuesSearchVo);
myProjectIssuesSearchVo.setPmProjectIds(StringUtils.join(projectList.stream().map(PmsProject::getId).toArray(), ","));
JSONObject result = pmsProjectIssuesService.selectMyPmsProjectIssuesList(myProjectIssuesSearchVo);
return success(result);
}
@ -122,6 +118,24 @@ public class PmsDashboardController extends BaseController {
return pmsProjectService.selectPmsProjectList(pmsProjectSearchVo);
}
/**
* 我的项目-项目情况统计
*/
@ApiOperation(value = "我的项目-项目统计")
@GetMapping("/myProjects/statistics")
public AjaxResult myProjectStatistics(@ApiParam("项目id") @RequestParam Long pmProjectId) {
return success(pmsProjectService.getMyProjectStatistics(pmProjectId));
}
/**
* 我的仓库-仓库情况统计
*/
@ApiOperation(value = "我的仓库-仓库情况统计")
@GetMapping("/myRepositories/statistics")
public AjaxResult myRepositoriesStatistics(@ApiParam("仓库id") @RequestParam Long repositoryId) {
return success(pmsProjectService.getMyRepositoriesStatistics(repositoryId));
}
/**
* 我的迭代
@ -143,6 +157,21 @@ public class PmsDashboardController extends BaseController {
return pmsProjectSprintService.selectAllPmsProjectSprintList(pmsProjectSprintSearchVo);
}
/**
* 我的待办
*/
@GetMapping("/todo")
@ApiOperation(value = "我的待办")
public AjaxResult todoProjectIssues(MyTodoProjectIssuesSearchVo todoProjectIssuesSearchVo) {
List<PmsProject> projectList = pmsProjectService.selectPmsProjectList(new PmsProject());
if(projectList.isEmpty()){
return success();
}
todoProjectIssuesSearchVo.setPmProjectIds(StringUtils.join(projectList.stream().map(PmsProject::getId).toArray(), ","));
JSONObject result = pmsProjectIssuesService.selectMyTodoPmsProjectIssuesList(todoProjectIssuesSearchVo);
return success(result);
}
/**
* 我的产品
*/

View File

@ -8,10 +8,10 @@ import lombok.Data;
@ApiModel("我的工作项搜索对象")
public class MyProjectIssuesSearchVo {
@ApiModelProperty(value = "疑修类型all 全部 opened 开启中 closed 已关闭", required = true)
@ApiModelProperty(value = "疑修类型all 全部 opened 开启中 closed 已关闭")
private String category;
@ApiModelProperty(value = "参与类型all 全部 aboutme 关于我的 authoredme 我创建的 assignedme 我负责的 atme @我的", required = true)
@ApiModelProperty(value = "参与类型all 全部 aboutme 关于我的 authoredme 我创建的 assignedme 我负责的 atme @我的")
private String participantCategory;
@ApiModelProperty(value = "工作项名称搜索关键词")
@ -30,6 +30,9 @@ public class MyProjectIssuesSearchVo {
private String limit;
@ApiModelProperty(value = "按pmProjectId集合查询,逗号隔开", hidden = true)
private String pmsProjectIds;
private String pmProjectIds;
@ApiModelProperty(value = "工作项类型计划1 任务2 缺陷3多个用逗号隔开", required = true)
private String pmIssueTypes;
}

View File

@ -0,0 +1,35 @@
package com.microservices.pms.dashboard.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("我的待办工作项搜索对象")
public class MyTodoProjectIssuesSearchVo {
@ApiModelProperty(value = "日期格式yyyy-MM-dd示例值:2024-12-11")
private String date;
@ApiModelProperty(value = "工作项名称搜索关键词")
private String keyword;
@ApiModelProperty(value = "排序方式: issues.updated_on 更新时间 issues.created_on 创建时间 issue_priorities.position 优先级")
private String sortBy;
@ApiModelProperty(value = "排序方向:asc 正序 desc 倒序")
private String sortDirection;
@ApiModelProperty(value = "页码", required = true)
private String page;
@ApiModelProperty(value = "分页数", required = true)
private String limit;
@ApiModelProperty(value = "按pmProjectId集合查询,逗号隔开", hidden = true)
private String pmProjectIds;
@ApiModelProperty(value = "工作项类型计划1 任务2 缺陷3多个用逗号隔开")
private String pmIssueTypes;
}

View File

@ -9,6 +9,7 @@ import com.microservices.common.log.enums.BusinessType;
import com.microservices.common.security.annotation.RequiresPermissions;
import com.microservices.pms.product.domain.vo.*;
import com.microservices.pms.product.service.IPmsProductRequirementService;
import com.microservices.pms.project.domain.PmsProject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@ -123,6 +124,16 @@ public class ProductReqSpecsController extends BaseController {
return toAjax(pmsProductRequirementService.activePlan(productReqSpecsActivePlanVo));
}
/**
* 纳入计划时可选择项目列表
*/
@ApiOperation(value = "纳入计划时可选择项目列表")
@RequiresPermissions("pms:pmsProduct:show")
@GetMapping("/{productIdentifier}/projectList")
public List<PmsProject> projectList(@PathVariable("productIdentifier") String productIdentifier) {
return pmsProductRequirementService.selectReqSpecsProjectList(productIdentifier);
}
/**
* 查询需求规格状态列表
*/

View File

@ -32,7 +32,7 @@ public enum ProductReqOperationType {
throw new ServiceException("需求操作记录类型错误");
}
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String operationTimeStr = formatter.format(record.getOperatingTime());
String operationTimeStr = formatter.format(record.getCreateTime());
switch (type) {
case CONTENT_MODIFY:
return String.format("%s由【%s】%s",

View File

@ -64,6 +64,7 @@ public class ProductReqReviewVo {
JSONObject contentJson = new JSONObject();
contentJson.put("reviewUser", reviewUser);
contentJson.put("reviewContent", reviewContent);
contentJson.put("reviewTime", reviewTime);
record.setContent(contentJson.toJSONString());
return record;
}

View File

@ -1,9 +1,12 @@
package com.microservices.pms.product.domain.vo;
import com.microservices.pms.enums.ProjectIssuePriority;
import com.microservices.pms.enums.ProjectIssueStatus;
import com.microservices.pms.product.domain.PmsProductReqOperationRecord;
import com.microservices.pms.product.domain.PmsProductRequirement;
import com.microservices.pms.product.domain.enums.ProductReqOperationType;
import com.microservices.pms.project.domain.vo.PmsProjectIssuesInputVo;
import com.microservices.pms.utils.PmsConstants;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -32,9 +35,9 @@ public class ProductReqSpecsActivePlanVo {
PmsProjectIssuesInputVo issue = new PmsProjectIssuesInputVo();
issue.setSubject(reqSpecs.getTitle());
issue.setPmProjectId(projectId);
issue.setStatusId(1);
issue.setPmIssueType(1);
issue.setPriorityId(2);
issue.setStatusId(ProjectIssueStatus.RESOLVING.getId());
issue.setPmIssueType(Integer.valueOf(PmsConstants.PROJECT_ISSUE_TYPE_REQUIREMENT));
issue.setPriorityId(ProjectIssuePriority.NORMAL.getId());
issue.setDescription(reqSpecs.getContent());
issue.setAttachmentIds(forgeFileIdentifierList);
return issue;

View File

@ -36,9 +36,12 @@ public class ProductReqSpecsSearchVo {
@ApiModelProperty(value = "关联产品模块ID传0查询不属于任何模块的需求")
private Long pmsProductModuleId;
@ApiModelProperty(value = "产品需求状态(全部状态请传空)")
@ApiModelProperty(value = "产品需求状态(全部状态请传空)(可通过逗号分割传多个状态)")
private String status;
@ApiModelProperty(value = "产品需求状态(数组)", hidden = true)
private String[] statusList;
@ApiModelProperty(value = "产品需求类型")
private String type;

View File

@ -116,4 +116,6 @@ public interface PmsProductRequirementMapper
Integer countByIdentifierAndStatus(@Param("pmsProductIdentifier") String pmsProductIdentifier, @Param("statusList") List<String> statusList);
List<ReqStatusStatVo> selectReqCountGroupByStatus(@Param("pmsProductIdentifier") String pmsProductIdentifier, @Param("statusList") List<String> statusList);
PmsProductRequirement selectReqSpecsByProjectReqId(@Param("projectReqId") Long projectReqId);
}

View File

@ -3,7 +3,9 @@ package com.microservices.pms.product.service;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
import com.microservices.pms.product.domain.PmsProductRequirement;
import com.microservices.pms.product.domain.enums.ProductReqStatus;
import com.microservices.pms.product.domain.vo.*;
import com.microservices.pms.project.domain.PmsProject;
import java.util.List;
@ -134,4 +136,8 @@ public interface IPmsProductRequirementService
* @return List<ReqStatusStatVo>
*/
List<ReqStatusStatVo> selectReqCountGroupByStatus(String pmsProductIdentifier, List<String> statusList);
void updateReqSpecsStatusByProjectReqId(Long projectReqId, ProductReqStatus productReqStatus);
List<PmsProject> selectReqSpecsProjectList(String productIdentifier);
}

View File

@ -132,10 +132,14 @@ public class PmsProductReqOperationRecordServiceImpl implements IPmsProductReqOp
// 根据需求规格id和fromId查询需求规格相关的所有需求规格相关的变更记录列表
PmsProductReqOperationRecord recordSearch = new PmsProductReqOperationRecord();
List<PmsProductReqOperationRecord> recordList = new ArrayList<>();
while (reqSpecs.getFromId() != null && !ProductReqStatus.isUserReqStatus(reqSpecs.getStatus())) {
while (reqSpecs != null && !ProductReqStatus.isUserReqStatus(reqSpecs.getStatus())) {
recordSearch.setProductRequirementId(reqSpecs.getId());
recordList.addAll(pmsProductReqOperationRecordMapper.selectPmsProductReqOperationRecordList(recordSearch));
reqSpecs = pmsProductRequirementService.selectPmsProductRequirementById(reqSpecs.getFromId(), false);
if (reqSpecs.getFromId() != null) {
reqSpecs = pmsProductRequirementService.selectPmsProductRequirementById(reqSpecs.getFromId(), false);
} else {
reqSpecs = null;
}
}
return getRecordDataList(recordList);

View File

@ -334,6 +334,7 @@ public class PmsProductRequirementServiceImpl implements IPmsProductRequirementS
issue.setDescription(reqSpecs.getContent());
issue.setAttachmentIds(forgeFileIdentifierList);
issue.setPmProjectId(fromReqSpecs.getPmsProjectId());
issue.setIsProductReqSpecsChange(true);
pmsProjectIssuesService.updatePmsProjectIssues(fromReqSpecs.getProjectReqId(), issue);
}
// 变更中的需求规格通过评审后设置状态为原需规状态
@ -358,7 +359,7 @@ public class PmsProductRequirementServiceImpl implements IPmsProductRequirementS
// 原需规记录评审意见
PmsProductReqOperationRecord oldReqSpecsRecord
= productReqReviewVo.toReqSpecsRecord(SecurityUtils.getUsername());
oldReqSpecsRecord.setId(fromReqSpecs.getId());
oldReqSpecsRecord.setProductRequirementId(fromReqSpecs.getId());
pmsProductReqOperationRecordService.insertPmsProductReqOperationRecord(oldReqSpecsRecord);
} else {
reqSpecs.setStatus(ProductReqStatus.REJECTED_REQ_SPECS.getKey());
@ -393,6 +394,9 @@ public class PmsProductRequirementServiceImpl implements IPmsProductRequirementS
List<Long> moduleIdList = pmsProductModuleService.selectChildrenPmsProductModuleIdList(productReqSpecsSearchVo.getPmsProductModuleId());
productReqSpecsSearchVo.setChildrenModuleIdList(moduleIdList);
}
if (StringUtils.isNotEmpty(productReqSpecsSearchVo.getStatus())) {
productReqSpecsSearchVo.setStatusList(productReqSpecsSearchVo.getStatus().split(","));
}
startPage();
List<PmsProductRequirement> userReqList = pmsProductRequirementMapper.selectReqSpecsList(productReqSpecsSearchVo);
HashMap<String, Object> hashMap = new HashMap<>();
@ -534,7 +538,11 @@ public class PmsProductRequirementServiceImpl implements IPmsProductRequirementS
if (!ProductReqStatus.REVIEWED_REQ_SPECS.getKey().equals(reqSpecs.getStatus())) {
throw new ServiceException("仅已评审状态的需求规格才能纳入计划");
}
PmsProject project = pmsProjectService.selectAndCheckPmsProjectById(productReqSpecsActivePlanVo.getProjectId());
List<PmsProject> pmsProjectList = selectReqSpecsProjectList(reqSpecs.getPmsProductIdentifier());
if (pmsProjectList == null
|| pmsProjectList.stream().noneMatch(x -> x.getId().equals(productReqSpecsActivePlanVo.getProjectId()))) {
throw new ServiceException("需求规格纳入计划时请选择关联了当前产品的项目");
}
List<String> forgeFileIdentifierList = null;
if (StringUtils.isNotEmpty(reqSpecs.getFileIdentifiers())) {
// 需求规格文件上传至forge
@ -545,7 +553,7 @@ public class PmsProductRequirementServiceImpl implements IPmsProductRequirementS
PmsProjectIssuesInputVo pmsProjectIssuesInputVo = productReqSpecsActivePlanVo.toPmsProjectIssuesInputVo(reqSpecs, forgeFileIdentifierList);
JSONObject projectIssue = pmsProjectIssuesService.insertPmsProjectIssues(pmsProjectIssuesInputVo);
reqSpecs.setPmsProjectId(project.getId());
reqSpecs.setPmsProjectId(productReqSpecsActivePlanVo.getId());
reqSpecs.setProjectReqId(projectIssue.getLong("id"));
reqSpecs.setStatus(ProductReqStatus.PLANNED_REQ_SPECS.getKey());
int success = updateRequirement(reqSpecs, reqSpecs.getPmsProductIdentifier());
@ -581,6 +589,32 @@ public class PmsProductRequirementServiceImpl implements IPmsProductRequirementS
);
}
@Override
public void updateReqSpecsStatusByProjectReqId(Long projectReqId, ProductReqStatus productReqStatus) {
PmsProductRequirement pmsProductRequirement = pmsProductRequirementMapper.selectReqSpecsByProjectReqId(projectReqId);
if (pmsProductRequirement == null) {
throw new ServiceException("项目计划关联的需求规格不存在");
}
if (productReqStatus.getKey().equals(pmsProductRequirement.getStatus())) {
return;
}
if (ProductReqStatus.COMPLETED_REQ_SPECS.getKey().equals(productReqStatus.getKey())) {
if (ProductReqStatus.CHANGING_REQ_SPECS.getKey().equals(pmsProductRequirement.getStatus())) {
throw new ServiceException("需求规格变更中,项目计划不能调整为已完成或已关闭状态");
}
}
pmsProductRequirement.setStatus(productReqStatus.getKey());
updateRequirement(pmsProductRequirement, pmsProductRequirement.getPmsProductIdentifier());
}
@Override
public List<PmsProject> selectReqSpecsProjectList(String productIdentifier) {
PmsProduct pmsProduct = pmsProductService.selectPmsProductByIdentifier(productIdentifier);
PmsProject pmsProjectSearch = new PmsProject();
pmsProjectSearch.setPmsProductId(pmsProduct.getId());
return pmsProjectService.selectPmsProjectList(pmsProjectSearch);
}
private ProductReqSpecsDetailVo toProductReqSpecsDetailVo(PmsProductRequirement pmsProductRequirement) {
ProductReqSpecsDataVo productReqSpecsDataVo = toProductReqSpecsDataVo(pmsProductRequirement, null);
ProductReqSpecsDetailVo productReqSpecsDetailVo = productReqSpecsDataVo.toProductReqSpecsDetailVo();

View File

@ -165,4 +165,14 @@ public class PmsProjectController extends BaseController
return success(pmsProjectService.getPmsProjectPolyline(pmProjectId));
}
/**
* 获取项目概览-动态
*/
@RequiresPermissions(value = {"pms:pmsProject:show", "pms:pmsProject:showMe"}, logical = Logical.OR)
@GetMapping(value = "/statistics/dynamics")
@ApiOperation(value = "项目概览-动态")
public AjaxResult getDynamics(@ApiParam("项目id") @RequestParam Long pmProjectId) {
return success(pmsProjectService.getPmsProjectDynamics(pmProjectId));
}
}

View File

@ -2,6 +2,7 @@ package com.microservices.pms.project.controller;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.exception.ServiceException;
import com.microservices.common.core.web.controller.BaseController;
import com.microservices.common.core.web.domain.AjaxResult;
import com.microservices.common.core.web.page.GenericsTableDataInfo;
@ -10,6 +11,7 @@ import com.microservices.common.security.annotation.RequiresPermissions;
import com.microservices.pms.project.domain.vo.*;
import com.microservices.pms.project.service.IPmsProjectTestsheetIssuesService;
import com.microservices.pms.project.service.PmsProjectIssuesService;
import com.microservices.pms.utils.PmsConstants;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@ -30,7 +32,7 @@ import javax.servlet.http.HttpServletResponse;
@ApiImplicitParams({
@ApiImplicitParam(name = "enterpriseIdentifier", value = "企业标识", paramType = "path", dataType = "String")
})
public class PmsProjectIssuesController extends BaseController {
public class PmsProjectIssuesController extends BaseController {
@Autowired
private PmsProjectIssuesService pmsProjectIssuesService;
@ -44,8 +46,7 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions(value = {"pms:pmsProject:show", "pms:pmsProject:showMe", "pms:pmsProjectTestsheet:edit"}, logical = Logical.OR)
@GetMapping("/list")
@ApiOperation(value = "项目工作项列表")
public AjaxResult list(PmsProjectIssuesSearchVo pmsProjectIssuesSearchVo)
{
public AjaxResult list(PmsProjectIssuesSearchVo pmsProjectIssuesSearchVo) {
JSONObject result = pmsProjectIssuesService.selectPmsProjectIssuesList(pmsProjectIssuesSearchVo);
return success(result);
}
@ -56,8 +57,11 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions("pms:pmsProjectIssues:add")
@PostMapping("/add")
@ApiOperation(value = "新增项目工作项")
public AjaxResult add(@RequestBody PmsProjectIssuesInputVo pmsProjectIssuesInputVo)
{
public AjaxResult add(@RequestBody PmsProjectIssuesInputVo pmsProjectIssuesInputVo) {
if (PmsConstants.PROJECT_ISSUE_TYPE_REQUIREMENT.equals(String.valueOf(pmsProjectIssuesInputVo.getPmIssueType()))
&& pmsProjectIssuesInputVo.getRootId() == null) {
throw new ServiceException("项目计划仅能基于产品需求规格创建");
}
JSONObject result = pmsProjectIssuesService.insertPmsProjectIssues(pmsProjectIssuesInputVo);
return success(result);
}
@ -68,8 +72,7 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions("pms:pmsProjectIssues:edit")
@PostMapping("/edit/{id}")
@ApiOperation(value = "编辑项目工作项")
public AjaxResult edit(@PathVariable("id") Long id, @RequestBody PmsProjectIssuesInputVo pmsProjectIssuesInputVo)
{
public AjaxResult edit(@PathVariable("id") Long id, @RequestBody PmsProjectIssuesInputVo pmsProjectIssuesInputVo) {
JSONObject result = pmsProjectIssuesService.updatePmsProjectIssues(id, pmsProjectIssuesInputVo);
return success(result);
}
@ -80,10 +83,8 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions("pms:pmsProjectIssues:edit")
@PutMapping("/edit/batch")
@ApiOperation(value = "批量修改项目工作项")
public AjaxResult batchUpdate(@ApiParam( "项目Id") @RequestParam(name= "pmProjectId") Long pmProjectId,
@RequestBody PmsProjectIssuesBatchUpdateVo pmsProjectIssuesUpdateVo)
{
public AjaxResult batchUpdate(@ApiParam("项目Id") @RequestParam(name = "pmProjectId") Long pmProjectId,
@RequestBody PmsProjectIssuesBatchUpdateVo pmsProjectIssuesUpdateVo) {
JSONObject result = pmsProjectIssuesService.batchUpdatePmsProjectIssues(pmProjectId, pmsProjectIssuesUpdateVo);
return success(result);
}
@ -93,8 +94,7 @@ public class PmsProjectIssuesController extends BaseController {
*/
@RequiresPermissions(value = {"pms:pmsProject:show", "pms:pmsProject:showMe"}, logical = Logical.OR)
@GetMapping("/{id}")
public AjaxResult query(@PathVariable("id") Long id, @ApiParam( "项目Id")@RequestParam(name = "pmProjectId") Long pmProjectId)
{
public AjaxResult query(@PathVariable("id") Long id, @ApiParam("项目Id") @RequestParam(name = "pmProjectId") Long pmProjectId) {
JSONObject result = pmsProjectIssuesService.selectPmsProjectIssueById(id, pmProjectId);
return success(result);
@ -105,9 +105,7 @@ public class PmsProjectIssuesController extends BaseController {
*/
@RequiresPermissions("pms:pmsProjectIssues:remove")
@DeleteMapping("/{ids}")
public AjaxResult remove(@ApiParam( "工作项id数组为-1时删除全部")@PathVariable Long[] ids, @ApiParam( "项目Id")@RequestParam(name = "pmProjectId") Long pmProjectId)
{
public AjaxResult remove(@ApiParam("工作项id数组为-1时删除全部") @PathVariable Long[] ids, @ApiParam("项目Id") @RequestParam(name = "pmProjectId") Long pmProjectId) {
JSONObject result = pmsProjectIssuesService.deletePmsProjectIssueByIds(ids, pmProjectId);
return success(result);
}
@ -118,8 +116,7 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions(value = {"pms:pmsProject:show", "pms:pmsProject:showMe"}, logical = Logical.OR)
@GetMapping("/issueStatus")
@ApiOperation(value = "查询项目工作项状态列表")
public AjaxResult issueStatus()
{
public AjaxResult issueStatus() {
JSONObject result = pmsProjectIssuesService.selectPmsProjectIssueStatus();
return success(result);
@ -131,8 +128,7 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions(value = {"pms:pmsProject:show", "pms:pmsProject:showMe"}, logical = Logical.OR)
@GetMapping("/issuePriorities")
@ApiOperation(value = "查询项目工作项优先级列表")
public AjaxResult issuePriorities()
{
public AjaxResult issuePriorities() {
JSONObject result = pmsProjectIssuesService.selectPmsProjectIssuePriorities();
return success(result);
@ -145,8 +141,7 @@ public class PmsProjectIssuesController extends BaseController {
@GetMapping("/issueTags")
@ApiOperation(value = "查询初始的项目工作项标记列表")
public AjaxResult issueTags(@ApiParam(name = "pmProjectId", value = "项目Id") Long pmProjectId,
@ApiParam(name = "repositoryId", value = "仓库") Long repositoryId)
{
@ApiParam(name = "repositoryId", value = "仓库") Long repositoryId) {
JSONObject result = pmsProjectIssuesService.selectPmsProjectIssueTags(pmProjectId, repositoryId);
return success(result);
@ -158,8 +153,7 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions(value = {"pms:pmsProject:show", "pms:pmsProject:showMe", "pms:pmsProjectIssuesTag:manage"}, logical = Logical.OR)
@GetMapping("/enterpriseIssueTags")
@ApiOperation(value = "查询企业下项目工作项标记列表")
public AjaxResult getEnterpriseIssueTags(PmsEnterpriseIssueTagsSearchVo pmsEnterpriseIssueTagsSearchVo)
{
public AjaxResult getEnterpriseIssueTags(PmsEnterpriseIssueTagsSearchVo pmsEnterpriseIssueTagsSearchVo) {
JSONObject result = pmsProjectIssuesService.selectPmsEnterpriseIssueTags(pmsEnterpriseIssueTagsSearchVo);
return success(result);
@ -171,8 +165,7 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions("pms:pmsProjectIssuesTag:manage")
@PostMapping("/enterpriseIssueTags")
@ApiOperation(value = "创建企业下项目工作项标记")
public AjaxResult createEnterpriseIssueTag(@RequestBody PmsEnterpriseIssueTagInputVo pmsEnterpriseIssueTagInputVo)
{
public AjaxResult createEnterpriseIssueTag(@RequestBody PmsEnterpriseIssueTagInputVo pmsEnterpriseIssueTagInputVo) {
JSONObject result = pmsProjectIssuesService.createPmsEnterpriseIssueTag(pmsEnterpriseIssueTagInputVo);
return success(result);
@ -184,8 +177,7 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions("pms:pmsProjectIssuesTag:manage")
@PutMapping("/enterpriseIssueTags/{tagId}")
@ApiOperation(value = "更新企业下项目工作项标记")
public AjaxResult editEnterpriseIssueTag(@PathVariable("tagId") Long tagId, @RequestBody PmsEnterpriseIssueTagUpdateVo pmsEnterpriseIssueTagUpdateVo)
{
public AjaxResult editEnterpriseIssueTag(@PathVariable("tagId") Long tagId, @RequestBody PmsEnterpriseIssueTagUpdateVo pmsEnterpriseIssueTagUpdateVo) {
JSONObject result = pmsProjectIssuesService.editPmsEnterpriseIssueTag(tagId, pmsEnterpriseIssueTagUpdateVo);
return success(result);
@ -197,8 +189,7 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions("pms:pmsProjectIssuesTag:manage")
@DeleteMapping("/enterpriseIssueTags/{tagId}")
@ApiOperation(value = "删除企业下项目工作项标记")
public AjaxResult deleteEnterpriseIssueTag(@PathVariable("tagId") Long tagId)
{
public AjaxResult deleteEnterpriseIssueTag(@PathVariable("tagId") Long tagId) {
JSONObject result = pmsProjectIssuesService.deletePmsEnterpriseIssueTag(tagId);
return success(result);
@ -210,8 +201,7 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions(value = {"pms:pmsProject:show", "pms:pmsProject:showMe"}, logical = Logical.OR)
@GetMapping("{repositoryId}/repoBranches")
@ApiOperation(value = "查询仓库下分支列表")
public AjaxResult repoBranches(@PathVariable Long repositoryId)
{
public AjaxResult repoBranches(@PathVariable Long repositoryId) {
JSONArray result = pmsProjectIssuesService.selectPmsProjectRepoBranches(repositoryId);
return success(result);
@ -223,8 +213,7 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions(value = {"pms:pmsProjectIssues:edit", "pms:pmsProjectIssues:add"}, logical = Logical.OR)
@PostMapping("/attachments")
@ApiOperation(value = "上传工作项中的附件")
public AjaxResult uploadAttachments(@RequestPart("file") MultipartFile file)
{
public AjaxResult uploadAttachments(@RequestPart("file") MultipartFile file) {
JSONObject result = pmsProjectIssuesService.uploadAttachment(file);
return success(result);
}
@ -235,8 +224,7 @@ public class PmsProjectIssuesController extends BaseController {
@RequiresPermissions(value = {"pms:pmsProjectIssues:edit", "pms:pmsProjectIssues:add", "pms:pmsProjectIssues:remove"}, logical = Logical.OR)
@DeleteMapping("/attachments/{id}")
@ApiOperation(value = "删除工作项中的附件")
public AjaxResult deleteAttachments(@PathVariable Long id)
{
public AjaxResult deleteAttachments(@PathVariable Long id) {
JSONObject result = pmsProjectIssuesService.deleteAttachment(id);
return success(result);
@ -249,8 +237,7 @@ public class PmsProjectIssuesController extends BaseController {
@PostMapping("/link/{issueId}")
@ApiOperation(value = "添加项目工作项关联")
public AjaxResult addIssueLinks(@ApiParam("工作项id") @PathVariable Long issueId,
@RequestBody PmsProjectIssuesLinkVo pmsProjectIssuesLinkVo)
{
@RequestBody PmsProjectIssuesLinkVo pmsProjectIssuesLinkVo) {
JSONObject result = pmsProjectIssuesService.addPmsProjectIssueLink(issueId, pmsProjectIssuesLinkVo);
return success(result);
@ -263,8 +250,7 @@ public class PmsProjectIssuesController extends BaseController {
@GetMapping("/link/{issueId}")
@ApiOperation(value = "查看项目工作项关联")
public AjaxResult getIssueLinks(@ApiParam("工作项id") @PathVariable Long issueId,
@ApiParam( "项目Id")@RequestParam(name = "pmProjectId") Long pmProjectId)
{
@ApiParam("项目Id") @RequestParam(name = "pmProjectId") Long pmProjectId) {
JSONObject result = pmsProjectIssuesService.getPmsProjectIssueLink(issueId, pmProjectId);
return success(result);
@ -294,12 +280,12 @@ public class PmsProjectIssuesController extends BaseController {
@GetMapping("/optionalParentIssue/{issueId}")
@ApiOperation(value = "可选择的父工作项列表")
public AjaxResult getOptionalParentIssueList(
@ApiParam("页码") Integer pageNum,
@ApiParam("页数") Integer pageSize,
@ApiParam("工作项id") @PathVariable Long issueId,
@ApiParam("需求1 任务2 缺陷3") @RequestParam(name = "pmIssueType") String pmIssueType,
@ApiParam("项目id") @RequestParam(name = "pmProjectId") String pmProjectId,
@ApiParam("搜索关键词") @RequestParam(name = "keyword", required = false) String keyword
@ApiParam("页码") Integer pageNum,
@ApiParam("页数") Integer pageSize,
@ApiParam("工作项id") @PathVariable Long issueId,
@ApiParam("需求1 任务2 缺陷3") @RequestParam(name = "pmIssueType") String pmIssueType,
@ApiParam("项目id") @RequestParam(name = "pmProjectId") String pmProjectId,
@ApiParam("搜索关键词") @RequestParam(name = "keyword", required = false) String keyword
) {
@ -315,8 +301,7 @@ public class PmsProjectIssuesController extends BaseController {
@ApiOperation(value = "删除项目工作项关联")
public AjaxResult removeIssueLinks(@ApiParam("当前工作项id") @PathVariable Long issueId,
@ApiParam("关联工作项id") @PathVariable String linkIssueId,
@ApiParam( "项目Id")@RequestParam(name = "pmProjectId") Long pmProjectId)
{
@ApiParam("项目Id") @RequestParam(name = "pmProjectId") Long pmProjectId) {
JSONObject result = pmsProjectIssuesService.deletePmsProjectIssueLink(issueId, linkIssueId, pmProjectId);
return success(result);
@ -328,8 +313,7 @@ public class PmsProjectIssuesController extends BaseController {
@PostMapping("/journals/{issueId}")
@ApiOperation(value = "新增工作项评论")
public AjaxResult addJournals(@ApiParam("工作项id") @PathVariable Long issueId,
@RequestBody PmsProjectIssueJournalInputVo pmsProjectIssueJournalInputVo)
{
@RequestBody PmsProjectIssueJournalInputVo pmsProjectIssueJournalInputVo) {
JSONObject result = pmsProjectIssuesService.addPmsProjectIssueJournals(issueId, pmsProjectIssueJournalInputVo);
return success(result);
}
@ -341,10 +325,9 @@ public class PmsProjectIssuesController extends BaseController {
@ApiOperation(value = "删除工作项评论")
public AjaxResult removeJournals(@ApiParam("工作项id") @PathVariable Long issueId,
@ApiParam("评论id") @PathVariable Long journalId,
@ApiParam( "项目Id")@RequestParam(name = "pmProjectId") Long pmProjectId,
@ApiParam( "工作项关联的仓库id")@RequestParam(name = "pmProjectRepositoryId", required = false) Long pmProjectRepositoryId
)
{
@ApiParam("项目Id") @RequestParam(name = "pmProjectId") Long pmProjectId,
@ApiParam("工作项关联的仓库id") @RequestParam(name = "pmProjectRepositoryId", required = false) Long pmProjectRepositoryId
) {
JSONObject result = pmsProjectIssuesService.removePmsProjectIssueJournals(issueId, journalId, pmProjectId, pmProjectRepositoryId);
return success(result);
}

View File

@ -11,10 +11,7 @@ import com.microservices.common.security.annotation.Logical;
import com.microservices.common.security.annotation.RequiresPermissions;
import com.microservices.pms.product.service.IPmsProductModuleService;
import com.microservices.pms.project.domain.PmsProjectTestcase;
import com.microservices.pms.project.domain.vo.PmsProjectTestcaseDataVo;
import com.microservices.pms.project.domain.vo.PmsProjectTestcaseInputVo;
import com.microservices.pms.project.domain.vo.PmsProjectTestcaseSearchVo;
import com.microservices.pms.project.domain.vo.PmsProjectTestcaseUpdateVo;
import com.microservices.pms.project.domain.vo.*;
import com.microservices.pms.project.service.IPmsProjectTestcaseService;
import io.swagger.annotations.*;
import org.springframework.beans.factory.annotation.Autowired;
@ -68,8 +65,8 @@ public class PmsProjectTestcaseController extends BaseController {
@RequiresPermissions(value = {"pms:pmsProject:show", "pms:pmsProject:showMe"}, logical = Logical.OR)
@GetMapping(value = "/{id}")
@ApiOperation(value = "获取测试用例详细信息")
public GenericsAjaxResult<PmsProjectTestcaseDataVo> getInfo(@PathVariable("id") Long id) {
return genericsSuccess(pmsProjectTestcaseService.selectPmsProjectTestcaseDataVoById(id));
public GenericsAjaxResult<PmsProjectTestcaseDetailVo> getInfo(@PathVariable("id") Long id) {
return genericsSuccess(pmsProjectTestcaseService.selectPmsProjectTestcaseDetailVoById(id));
}
/**
@ -83,6 +80,17 @@ public class PmsProjectTestcaseController extends BaseController {
return success(pmsProjectTestcaseService.insertPmsProjectTestcase(pmsProjectTestcaseInputVo.toPmsProjectTestcase()));
}
/**
* 复制测试用例
*/
@RequiresPermissions("pms:pmsProjectTestcase:add")
@Log(title = "测试用例管理", businessType = BusinessType.INSERT)
@PostMapping("{testcaseId}/copy")
@ApiOperation(value = "复制测试用例")
public AjaxResult copy(@PathVariable("testcaseId") Long testcaseId) {
return success(pmsProjectTestcaseService.copyPmsProjectTestcase(testcaseId));
}
/**
* 修改测试用例管理
*/

View File

@ -1,5 +1,7 @@
package com.microservices.pms.project.domain.vo;
import com.alibaba.fastjson2.JSONObject;
import com.microservices.common.core.utils.StringUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -70,4 +72,20 @@ public class PmsProjectIssuesInputVo {
@ApiModelProperty(value = "关联工作项id")
private Long linkAbleId;
@ApiModelProperty(value = "是否为需规调整", hidden = true)
private Boolean isProductReqSpecsChange = false;
public boolean isChangeContent(JSONObject issueJson) {
if (isProductReqSpecsChange) {
return false;
}
if (StringUtils.isNotEmpty(subject) && !issueJson.getString("subject").equals(subject)) {
return true;
}
if (StringUtils.isNotEmpty(description) && !issueJson.getString("description").equals(description)) {
return true;
}
return attachmentIds != null;
}
}

View File

@ -33,6 +33,9 @@ public class PmsProjectSprintDetailVo {
@ApiModelProperty(value = "工时规模")
private Long timeScale;
@ApiModelProperty(value = "关联测试用例数")
private Integer linkedTestsheetCount;
@ApiModelProperty(value = "状态 0待开始 1进行中 2已关闭")
private String status;

View File

@ -0,0 +1,17 @@
package com.microservices.pms.project.domain.vo;
import lombok.Data;
@Data
public class PmsProjectSprintStatisticsVo {
// 总数
private Integer all_sprint_count;
// 待开始
private Integer todo_sprint_count;
// 进行中
private Integer doing_sprint_count;
// 已关闭
private Integer closed_sprint_count;
}

View File

@ -2,6 +2,7 @@ package com.microservices.pms.project.mapper;
import com.microservices.pms.project.domain.PmsProjectSprint;
import com.microservices.pms.project.domain.vo.PmsProjectSprintSearchVo;
import com.microservices.pms.project.domain.vo.PmsProjectSprintStatisticsVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@ -73,4 +74,10 @@ public interface PmsProjectSprintMapper
int deletePmsProjectSprintByProjectId(@Param("projectId") Long projectId);
PmsProjectSprint selectLatestSprintByProjectIdAndNameAndAssigneeId(@Param("pmsProjectId") Long pmsProjectId, @Param("sprintName") String sprintName, @Param("sprintAssigneeId") Long sprintAssigneeId);
Integer selectOpeningSprintCount(@Param("pmProjectId") Long pmProjectId);
Integer selectOpeningSprintLastWeekIterationCount(@Param("pmProjectId") Long pmProjectId);
PmsProjectSprintStatisticsVo selectPmsProjectSprintStatisticsByProjectId(@Param("pmProjectId") Long pmProjectId);
}

View File

@ -66,4 +66,6 @@ public interface PmsProjectTestsheetMapper
List<PmsProjectTestsheet> selectPmsProjectTestsheetByIds(@Param("pmsProjectTestSheetIds") String pmsProjectTestSheetIds);
int deletePmsProjectTestsheetByProjectId(@Param("projectId") Long projectId);
Integer selectCountBySprintId(@Param("sprintId") Long sprintId);
}

View File

@ -92,4 +92,10 @@ public interface IPmsProjectService
* @param productId 产品Id
*/
void clearPmsProjectAndProductAssociations(Long productId);
JSONObject getPmsProjectDynamics(Long pmProjectId);
JSONObject getMyProjectStatistics(Long pmProjectId);
JSONObject getMyRepositoriesStatistics(Long repositoryId);
}

View File

@ -78,7 +78,7 @@ public interface IPmsProjectTestcaseService {
* @param id 测试用例ID
* @return 测试用例详情
*/
PmsProjectTestcaseDataVo selectPmsProjectTestcaseDataVoById(Long id);
PmsProjectTestcaseDetailVo selectPmsProjectTestcaseDetailVoById(Long id);
/**
* 根据模块ID删除测试用例与模块的关联关系
@ -116,4 +116,6 @@ public interface IPmsProjectTestcaseService {
List<PmsProjectTestcase> selectPmsProjectTestcaseList(PmsProjectTestcase pmsProjectTestcaseSearch);
List<ProductReqSpecsAssociatedTestcaseDataVo> selectReqSpecsAssociatedTestcaseList(Long reqSpecsId);
PmsProjectTestcase copyPmsProjectTestcase(Long testcaseId);
}

View File

@ -7,8 +7,13 @@ import com.microservices.common.core.utils.DateUtils;
import com.microservices.common.httpClient.util.GitLinkRequestHelper;
import com.microservices.common.security.utils.SecurityUtils;
import com.microservices.pms.common.service.IPmsCommonService;
import com.microservices.pms.dashboard.domain.vo.MyProjectIssuesSearchVo;
import com.microservices.pms.dashboard.domain.vo.MyTodoProjectIssuesSearchVo;
import com.microservices.pms.enterprise.domain.PmsEnterprise;
import com.microservices.pms.enterprise.service.IPmsEnterpriseService;
import com.microservices.pms.enums.ProjectIssueStatus;
import com.microservices.pms.product.domain.enums.ProductReqStatus;
import com.microservices.pms.product.service.IPmsProductRequirementService;
import com.microservices.pms.project.domain.PmsProject;
import com.microservices.pms.project.domain.SimpleRepository;
import com.microservices.pms.project.domain.vo.*;
@ -23,6 +28,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
@ -53,6 +59,10 @@ public class PmsProjectIssuesService {
@Lazy
private IPmsProjectService pmsProjectService;
@Autowired
@Lazy
private IPmsProductRequirementService pmsProductRequirementService;
@Autowired
@Lazy
private IPmsProjectTestsheetIssuesService pmsProjectTestsheetIssuesService;
@ -95,6 +105,7 @@ public class PmsProjectIssuesService {
return gitLinkRequestHelper.doPost(PmsGitLinkRequestUrl.CREATE_ISSUE(), issueInput);
}
@Transactional(rollbackFor = Exception.class)
public JSONObject updatePmsProjectIssues(Long id, PmsProjectIssuesInputVo pmsProjectIssuesInputVo) {
pmsProjectService.selectAndCheckPmsProjectById(pmsProjectIssuesInputVo.getPmProjectId());
JSONObject updatedIssue;
@ -102,6 +113,35 @@ public class PmsProjectIssuesService {
updatedIssue = gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_ISSUE(id, pmsProjectIssuesInputVo.getPmProjectId()));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
// 项目计划不允许编辑标题正文和附件
if (PmsConstants.PROJECT_ISSUE_TYPE_REQUIREMENT.equals(updatedIssue.getString("pm_issue_type"))
&& updatedIssue.getString("root_id") == null) {
if (pmsProjectIssuesInputVo.isChangeContent(updatedIssue)) {
throw new ServiceException("项目计划不允许编辑标题、正文和附件");
}
if (ProjectIssueStatus.REFUSE.getId().equals(pmsProjectIssuesInputVo.getStatusId())
|| ProjectIssueStatus.NEW.getId().equals(pmsProjectIssuesInputVo.getStatusId())) {
throw new ServiceException("项目计划状态值选择错误");
}
// 如果状态发生变更需同步产品需规的状态变更
if (pmsProjectIssuesInputVo.getStatusId() != null) {
JSONObject statusJson = updatedIssue.getJSONObject("status");
if (!statusJson.getString("id").equals(String.valueOf(pmsProjectIssuesInputVo.getStatusId()))) {
// 项目计划修改为进行中将需规调整为已计划
if (ProjectIssueStatus.RESOLVING.getId().equals(pmsProjectIssuesInputVo.getStatusId())) {
pmsProductRequirementService.updateReqSpecsStatusByProjectReqId(id, ProductReqStatus.PLANNED_REQ_SPECS);
}
// 项目计划修改为已完成或已关闭将需规调整为已完成
if (ProjectIssueStatus.RESOLVED.getId().equals(pmsProjectIssuesInputVo.getStatusId())
|| ProjectIssueStatus.CLOSE.getId().equals(pmsProjectIssuesInputVo.getStatusId())) {
pmsProductRequirementService.updateReqSpecsStatusByProjectReqId(id, ProductReqStatus.COMPLETED_REQ_SPECS);
}
}
}
}
if (PmsConstants.PROJECT_ISSUE_TYPE_WEEKLY_REPORT.equals(updatedIssue.getString("pm_issue_type"))
&& updatedIssue.getString("root_id") != null
@ -493,4 +533,25 @@ public class PmsProjectIssuesService {
throw new ServiceException("导出工作项失败");
}
}
public JSONObject selectMyPmsProjectIssuesList(MyProjectIssuesSearchVo myProjectIssuesSearchVo) {
JSONObject issueSearch = new JSONObject();
convertObjectToJSONObject(myProjectIssuesSearchVo, issueSearch, null);
try {
return setProjectIssueListUserState(gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_MY_ISSUE_LIST(issueSearch)));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
public JSONObject selectMyTodoPmsProjectIssuesList(MyTodoProjectIssuesSearchVo todoProjectIssuesSearchVo) {
JSONObject issueSearch = new JSONObject();
convertObjectToJSONObject(todoProjectIssuesSearchVo, issueSearch, null);
try {
return setProjectIssueListUserState(gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_MY_TODO_ISSUE_LIST(issueSearch)));
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -148,6 +148,31 @@ public class PmsProjectServiceImpl implements IPmsProjectService
return toPage(pmsProjectList, pmsProject -> buildPmsProjectDetailVo(pmsProject, finalProjectTotalCount));
}
@Override
public JSONObject getMyProjectStatistics(Long pmProjectId) {
selectAndCheckPmsProjectById(pmProjectId);
JSONObject result = gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_MY_PROJECT_STATISTICS(pmProjectId));
JSONObject data = result.getJSONObject(DATA_KEY);
if (data != null) {
fillSprintStatisticsData(pmProjectId, data);
}
return data;
}
@Override
public JSONObject getMyRepositoriesStatistics(Long repositoryId) {
return gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_MY_REPOSITORY_STATISTICS(repositoryId));
}
private void fillSprintStatisticsData(Long pmProjectId, JSONObject data) {
PmsProjectSprintStatisticsVo pmsProjectSprintStatisticsVo = pmsProjectSprintMapper.selectPmsProjectSprintStatisticsByProjectId(pmProjectId);
data.put("all_sprint_count", pmsProjectSprintStatisticsVo.getAll_sprint_count());
data.put("todo_sprint_count", pmsProjectSprintStatisticsVo.getTodo_sprint_count());
data.put("doing_sprint_count", pmsProjectSprintStatisticsVo.getDoing_sprint_count());
data.put("closed_sprint_count", pmsProjectSprintStatisticsVo.getClosed_sprint_count());
}
private PmsProjectDetailVo buildPmsProjectDetailVo(PmsProject pmsProject, JSONObject projectTotalCount) {
PmsProjectDetailVo pmsProjectDetailVo = new PmsProjectDetailVo();
@ -430,13 +455,36 @@ public class PmsProjectServiceImpl implements IPmsProjectService
}
}
@Override
public JSONObject getPmsProjectDynamics(Long pmProjectId) {
// 校验数据权限
selectAndCheckPmsProjectById(pmProjectId);
JSONObject result = gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_OPERATE_JOURNALS(pmProjectId));
//todo 获取项目其他模块操作记录和项目动态合并取top10
return result.getJSONObject(DATA_KEY);
}
@Override
public JSONObject getPmsProjectStatistics(Long pmProjectId) {
// 校验数据权限
selectAndCheckPmsProjectById(pmProjectId);
JSONObject result = gitLinkRequestHelper.doGet(PmsGitLinkRequestUrl.GET_PROJECT_STATISTICS(pmProjectId));
return result.getJSONObject(DATA_KEY);
JSONObject dataObj = result.getJSONObject(DATA_KEY);
if (dataObj.containsKey("open_data")) {
// 获取 open_data 对象
JSONObject openData = dataObj.getJSONObject("open_data");
Integer openSprintCount = pmsProjectSprintMapper.selectOpeningSprintCount(pmProjectId);
// 添加新的键值对
openData.put("0", openSprintCount); // 新增开启中的迭代
dataObj.put("open_data", openData);
}
if (dataObj.containsKey("last_week_close_data")) {
JSONObject lastWeekCloseData = dataObj.getJSONObject("last_week_close_data");
Integer openLastWeekIterationCount = pmsProjectSprintMapper.selectOpeningSprintLastWeekIterationCount(pmProjectId);
lastWeekCloseData.put("0", openLastWeekIterationCount); //近一周新增
dataObj.put("last_week_close_data", lastWeekCloseData);
}
return dataObj;
}
@Override

View File

@ -11,6 +11,7 @@ import com.microservices.pms.common.service.IPmsCommonService;
import com.microservices.pms.project.domain.PmsProjectSprint;
import com.microservices.pms.project.domain.vo.*;
import com.microservices.pms.project.mapper.PmsProjectSprintMapper;
import com.microservices.pms.project.mapper.PmsProjectTestsheetMapper;
import com.microservices.pms.project.service.IPmsProjectService;
import com.microservices.pms.project.service.IPmsProjectSprintService;
import com.microservices.pms.project.service.PmsProjectIssuesService;
@ -58,6 +59,9 @@ public class PmsProjectSprintServiceImpl implements IPmsProjectSprintService
@Lazy
private PmsProjectIssuesService pmsProjectIssuesService;
@Resource
private PmsProjectTestsheetMapper pmsProjectTestsheetMapper;
/**
* 查询项目迭代
@ -138,6 +142,7 @@ public class PmsProjectSprintServiceImpl implements IPmsProjectSprintService
BeanUtils.copyProperties(pmsProjectSprint, pmsProjectSprintDetailVo);
pmsProjectSprintDetailVo.setSprintAssignee(pmsCommonService.getSimpleSysUserByGitlinkUserId(pmsProjectSprint.getSprintAssigneeId()));
pmsProjectSprintDetailVo.setSprintIssuesStatistics(sprintIssuesStatistics.getJSONObject(String.valueOf(pmsProjectSprint.getId())));
pmsProjectSprintDetailVo.setLinkedTestsheetCount(pmsProjectTestsheetMapper.selectCountBySprintId(pmsProjectSprint.getId()));
return pmsProjectSprintDetailVo;
}

View File

@ -22,6 +22,7 @@ import com.microservices.pms.project.domain.*;
import com.microservices.pms.project.domain.vo.PmsProjectTestcaseBatchUpdateVo;
import com.microservices.pms.project.domain.vo.PmsProjectTestcaseDataVo;
import com.microservices.pms.project.domain.vo.PmsProjectTestcaseDetailVo;
import com.microservices.pms.project.domain.vo.PmsProjectTestcaseStepDataVo;
import com.microservices.pms.project.mapper.PmsProjectTestcaseMapper;
import com.microservices.pms.project.mapper.PmsProjectTestsheetCasesMapper;
import com.microservices.pms.project.service.IPmsProjectService;
@ -37,6 +38,7 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import static com.microservices.common.core.utils.PageUtils.startPage;
@ -220,6 +222,26 @@ public class PmsProjectTestcaseServiceImpl implements IPmsProjectTestcaseService
return reqSpecsTestcaseDataVoList;
}
@Override
public PmsProjectTestcase copyPmsProjectTestcase(Long testcaseId) {
PmsProjectTestcase pmsProjectTestcase = selectPmsProjectTestcaseById(testcaseId);
pmsProjectTestcase.setId(null);
pmsProjectTestcase.setTags(pmsProjectTestcase.getTagIds());
PmsProjectTestcaseStep pmsProjectTestcaseStepSearch = new PmsProjectTestcaseStep();
pmsProjectTestcaseStepSearch.setPmsTestcaseId(testcaseId);
List<PmsProjectTestcaseStepDataVo> selectPmsProjectTestcaseStepList = pmsProjectTestcaseStepService.selectPmsProjectTestcaseStepList(pmsProjectTestcaseStepSearch);
List<PmsProjectTestcaseStep> pmsProjectTestcaseStepList = selectPmsProjectTestcaseStepList.stream()
.map(x -> {
PmsProjectTestcaseStep pmsProjectTestcaseStep = new PmsProjectTestcaseStep();
BeanUtils.copyProperties(x, pmsProjectTestcaseStep);
pmsProjectTestcaseStep.setId(null);
return pmsProjectTestcaseStep;
}).collect(Collectors.toList());
pmsProjectTestcase.setTestcaseStepList(pmsProjectTestcaseStepList);
insertPmsProjectTestcase(pmsProjectTestcase);
return pmsProjectTestcase;
}
/**
* 新增测试用例管理
*
@ -364,7 +386,7 @@ public class PmsProjectTestcaseServiceImpl implements IPmsProjectTestcaseService
}
@Override
public PmsProjectTestcaseDataVo selectPmsProjectTestcaseDataVoById(Long id) {
public PmsProjectTestcaseDetailVo selectPmsProjectTestcaseDetailVoById(Long id) {
return toPmsProjectTestcaseDetailVo(selectPmsProjectTestcaseById(id));
}

View File

@ -366,4 +366,29 @@ public class PmsGitLinkRequestUrl extends GitLinkRequestUrl {
public static GitLinkRequestUrl GET_REQ_SPECS_LINK_ISSUES(Long reqSpecsIssueId, Long projectId) {
return getGitLinkRequestUrl(String.format("/api/pm/issues/%d/link_issues?pm_project_id=%d", reqSpecsIssueId, projectId));
}
public static GitLinkRequestUrl GET_MY_ISSUE_LIST(JSONObject params) throws URISyntaxException {
return getGitLinkRequestUrl(
buildUri("/api/pm/dashboards/my_issues", params));
}
public static GitLinkRequestUrl GET_MY_TODO_ISSUE_LIST(JSONObject params) throws URISyntaxException {
return getGitLinkRequestUrl(
buildUri("/api/pm/dashboards/todo", params));
}
public static GitLinkRequestUrl GET_MY_PROJECT_STATISTICS(Long pmProjectId){
return getGitLinkRequestUrl(
String.format("/api/pm/dashboards/my_pm_projects?pm_project_id=%d", pmProjectId));
}
public static GitLinkRequestUrl GET_MY_REPOSITORY_STATISTICS(Long repositoryId) {
return getGitLinkRequestUrl(
String.format("/api/pm/dashboards/my_projects?project_id=%d", repositoryId));
}
public static GitLinkRequestUrl GET_OPERATE_JOURNALS(Long pmProjectId) {
return getGitLinkRequestUrl(
String.format("/api/pm/dashboards/my_operate_journals?pm_project_id=%d&page=1&limit=10", pmProjectId));
}
}

View File

@ -57,7 +57,7 @@
<if test="reservedField2 != null and reservedField2 != ''">and reserved_field_2 = #{reservedField2}</if>
<if test="reservedField3 != null and reservedField3 != ''">and reserved_field_3 = #{reservedField3}</if>
<if test="reservedField4 != null and reservedField4 != ''">and reserved_field_4 = #{reservedField4}</if>
order by operating_time desc
order by create_time desc
</where>
</select>
@ -69,9 +69,9 @@
<select id="selectUserReqLatestReviewRecord" parameterType="Long"
resultMap="PmsProductReqOperationRecordResult">
<include refid="selectPmsProductReqOperationRecordVo"/>
where type = 'reviewUserReq'
where type = 'reviewUserReq' and operation = 'pass'
and product_requirement_id=#{reqId}
order by operating_time desc
order by create_time desc
limit 1
</select>
<select id="selectReqSpecsLatestChangeRecord"
@ -80,15 +80,15 @@
where type = 'contentModify'
and operation = 'changingReq'
and product_requirement_id=#{reqId}
order by operating_time desc
order by create_time desc
limit 1
</select>
<select id="selectReqSpecsLatestReviewRecord" parameterType="Long"
resultMap="PmsProductReqOperationRecordResult">
<include refid="selectPmsProductReqOperationRecordVo"/>
where type = 'reviewReqSpecs'
where type = 'reviewReqSpecs' and operation = 'pass'
and product_requirement_id=#{reqId}
order by operating_time desc
order by create_time desc
limit 1
</select>

View File

@ -99,9 +99,10 @@
record.review_time,
record.content as review_content
from pms_product_requirement as ppr
left join (select product_requirement_id, MAX(operating_time) as review_time, content
left join (select product_requirement_id, MAX(create_time) as review_time, content
from pms_product_req_operation_record
where type = 'reviewUserReq'
and operation = 'pass'
group by product_requirement_id, content) as record
on record.product_requirement_id = ppr.id
</sql>
@ -204,7 +205,11 @@
<where>
<if test="title != null and title != ''">and title like concat('%', #{title}, '%')</if>
<if test="pmsProductIdentifier != null ">and pms_product_identifier = #{pmsProductIdentifier}</if>
<if test="status != null and status != ''">and `status` = #{status}</if>
<if test="status != null and status != ''">and `status` in
<foreach item="item" collection="statusList" open="(" separator="," close=")">
#{item}
</foreach>
</if>
<if test="type != null and type != ''">and `type` = #{type}</if>
<choose>
<when test="childrenModuleIdList != null">
@ -233,6 +238,12 @@
from pms_product_requirement
where identifier = #{identifier}
</select>
<select id="selectReqSpecsByProjectReqId" resultMap="PmsProductRequirementResult">
<include refid="selectPmsProductRequirementVo"/>
where project_req_id = #{projectReqId}
and (`status`= 'pendingReviewReqSpecs' or `status`= 'plannedReqSpecs' or `status` = 'rejectedReqSpecs' or
`status` = 'reviewedReqSpecs' or `status` = 'completedReqSpecs' or `status` = 'changingReqSpecs')
</select>
<insert id="insertPmsProductRequirement" parameterType="PmsProductRequirement" useGeneratedKeys="true"
keyProperty="id">

View File

@ -184,4 +184,41 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
order by id desc
limit 1
</select>
<select id="selectOpeningSprintCount" resultType="java.lang.Integer">
select count(*)
from pms_project_sprint
where pms_project_id = #{pmProjectId}
and status IN ('0', '1')
</select>
<select id="selectOpeningSprintLastWeekIterationCount" resultType="java.lang.Integer">
select count(*)
from pms_project_sprint
where pms_project_id = #{pmProjectId}
and status IN ('0', '1')
and start_time >= DATE_SUB(NOW(), INTERVAL 1 WEEK)
</select>
<select id="selectPmsProjectSprintStatisticsByProjectId"
resultType="com.microservices.pms.project.domain.vo.PmsProjectSprintStatisticsVo">
SELECT
(
SELECT COUNT(*)
FROM pms_project_sprint
WHERE pms_project_id = #{pmProjectId}
) AS all_sprint_count,
(
SELECT COUNT(*)
FROM pms_project_sprint
WHERE pms_project_id = #{pmProjectId} AND status = 0
) AS `todo_sprint_count`,
(
SELECT COUNT(*)
FROM pms_project_sprint
WHERE pms_project_id = #{pmProjectId} AND status = 1
) AS `doing_sprint_count`,
(
SELECT COUNT(*)
FROM pms_project_sprint
WHERE pms_project_id = #{pmProjectId} AND status = 2
) AS `closed_sprint_count`
</select>
</mapper>

View File

@ -50,6 +50,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{pmsProjectTestSheetIds}
</foreach>
</select>
<select id="selectCountBySprintId" resultType="java.lang.Integer">
select count(*) from pms_project_testsheet where project_sprint_id = #{sprintId}
</select>
<insert id="insertPmsProjectTestsheet" parameterType="PmsProjectTestsheet" useGeneratedKeys="true" keyProperty="id">
insert into pms_project_testsheet