refactor(测试跟踪): 评审用例批量修改评审人支持多选

--bug=1024499 --user=陈建星 【测试跟踪】用例评审-批量操作-变更评审人,可以同时选择多人 https://www.tapd.cn/55049933/s/1351129
--bug=1024522 --user=陈建星 【测试跟踪】用例评审评审人显示异常 https://www.tapd.cn/55049933/s/1351479
This commit is contained in:
chenjianxing 2023-03-16 15:12:57 +08:00 committed by jianxing
parent d0ae74322b
commit 5022f61ede
4 changed files with 81 additions and 49 deletions

View File

@ -11,8 +11,9 @@ import java.util.List;
@Setter @Setter
public class TestReviewCaseBatchRequest extends TestCaseReviewTestCase { public class TestReviewCaseBatchRequest extends TestCaseReviewTestCase {
private String reviewId; private String reviewId;
private List<String> reviewerIds;
private List<String> ids; private List<String> ids;
private QueryCaseReviewCondition condition; private QueryCaseReviewCondition condition;
private Boolean appendTag; private Boolean appendTag = false;
private String description; private String description;
} }

View File

@ -7,10 +7,7 @@ import io.metersphere.base.mapper.ext.ExtTestReviewCaseMapper;
import io.metersphere.commons.constants.TestCaseReviewStatus; import io.metersphere.commons.constants.TestCaseReviewStatus;
import io.metersphere.commons.constants.TestPlanStatus; import io.metersphere.commons.constants.TestPlanStatus;
import io.metersphere.commons.exception.MSException; import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils; import io.metersphere.commons.utils.*;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.constants.TestCaseCommentType; import io.metersphere.constants.TestCaseCommentType;
import io.metersphere.constants.TestCaseReviewCommentStatus; import io.metersphere.constants.TestCaseReviewCommentStatus;
import io.metersphere.constants.TestCaseReviewPassRule; import io.metersphere.constants.TestCaseReviewPassRule;
@ -23,7 +20,6 @@ import io.metersphere.log.vo.OperatingLogDetails;
import io.metersphere.log.vo.StatusReference; import io.metersphere.log.vo.StatusReference;
import io.metersphere.request.OrderRequest; import io.metersphere.request.OrderRequest;
import io.metersphere.request.ResetOrderRequest; import io.metersphere.request.ResetOrderRequest;
import io.metersphere.request.member.QueryMemberRequest;
import io.metersphere.request.testplancase.TestReviewCaseBatchRequest; import io.metersphere.request.testplancase.TestReviewCaseBatchRequest;
import io.metersphere.request.testreview.DeleteRelevanceRequest; import io.metersphere.request.testreview.DeleteRelevanceRequest;
import io.metersphere.request.testreview.QueryCaseReviewRequest; import io.metersphere.request.testreview.QueryCaseReviewRequest;
@ -33,6 +29,7 @@ import io.metersphere.xpack.version.service.ProjectVersionService;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -91,7 +88,15 @@ public class TestReviewTestCaseService {
.collect(Collectors.toList()); .collect(Collectors.toList());
// 查询评审人 // 查询评审人
userIds.addAll(getReviewUserIds(request.getReviewId(), caseIds)); List<TestCaseReviewTestCaseUsers> testCaseReviewTestCaseUsers =
getTestCaseReviewTestCaseUsers(request.getReviewId(), caseIds);
userIds.addAll(testCaseReviewTestCaseUsers.stream()
.map(TestCaseReviewTestCaseUsers::getUserId)
.collect(Collectors.toList())
);
Map<String, List<TestCaseReviewTestCaseUsers>> caseReviewerMap = testCaseReviewTestCaseUsers.stream()
.collect(Collectors.groupingBy(TestCaseReviewTestCaseUsers::getCaseId));
Map<String, String> userNameMap = ServiceUtils.getUserNameMap(userIds); Map<String, String> userNameMap = ServiceUtils.getUserNameMap(userIds);
@ -107,20 +112,22 @@ public class TestReviewTestCaseService {
list.forEach(item -> { list.forEach(item -> {
// 设置责任人和评审人名称 // 设置责任人和评审人名称
item.setReviewerName(getReviewName(userIds, userNameMap)); List<TestCaseReviewTestCaseUsers> caseReviewers = caseReviewerMap.get(item.getCaseId());
if (CollectionUtils.isNotEmpty(caseReviewers)) {
List<String> reviewerIds = caseReviewerMap.get(item.getCaseId()).stream()
.map(TestCaseReviewTestCaseUsers::getUserId)
.collect(Collectors.toList());
item.setReviewerName(getReviewName(reviewerIds, userNameMap));
}
item.setMaintainerName(userNameMap.get(item.getMaintainer())); item.setMaintainerName(userNameMap.get(item.getMaintainer()));
}); });
return list; return list;
} }
private List<String> getReviewUserIds(String reviewId) {
TestCaseReviewUsersExample testCaseReviewUsersExample = new TestCaseReviewUsersExample();
testCaseReviewUsersExample.createCriteria().andReviewIdEqualTo(reviewId);
List<TestCaseReviewUsers> testCaseReviewUsers = testCaseReviewUsersMapper.selectByExample(testCaseReviewUsersExample);
return testCaseReviewUsers.stream().map(TestCaseReviewUsers::getUserId).collect(Collectors.toList());
}
private String getReviewName(List<String> userIds, Map<String, String> userMap) { private String getReviewName(List<String> userIds, Map<String, String> userMap) {
if (CollectionUtils.isEmpty(userIds)) {
return StringUtils.EMPTY;
}
List<String> userNames = new ArrayList<>(); List<String> userNames = new ArrayList<>();
if (userIds.size() > 0) { if (userIds.size() > 0) {
for (String id : userIds) { for (String id : userIds) {
@ -473,37 +480,69 @@ public class TestReviewTestCaseService {
ServiceUtils.getSelectAllIds(request, request.getCondition(), ServiceUtils.getSelectAllIds(request, request.getCondition(),
(query) -> extTestReviewCaseMapper.selectTestCaseIds((QueryCaseReviewRequest) query)); (query) -> extTestReviewCaseMapper.selectTestCaseIds((QueryCaseReviewRequest) query));
List<String> ids = request.getIds(); List<String> ids = request.getIds();
if (CollectionUtils.isEmpty(ids)) { if (CollectionUtils.isEmpty(ids) || CollectionUtils.isEmpty(request.getReviewerIds())) {
return; return;
} }
if (StringUtils.isNotBlank(request.getReviewer())) {
// 分批处理
SubListUtil.dealForSubList(ids, 500, (subList) -> {
SqlSession batchSqlSession = ServiceUtils.getBatchSqlSession();
TestCaseReviewTestCaseUsersMapper batchMapper = batchSqlSession.getMapper(TestCaseReviewTestCaseUsersMapper.class);
TestCaseReviewTestCaseUsersExample example = new TestCaseReviewTestCaseUsersExample();
if (!request.getAppendTag()) { if (!request.getAppendTag()) {
TestCaseReviewTestCaseUsersExample example = new TestCaseReviewTestCaseUsersExample(); // 如果不是追加则先删除然后批量新增
example.createCriteria().andCaseIdIn(request.getIds()); example.createCriteria().andCaseIdIn(subList);
testCaseReviewTestCaseUsersMapper.deleteByExample(example); testCaseReviewTestCaseUsersMapper.deleteByExample(example);
}
for (int i = 0; i < ids.size(); i++) { subList.forEach(caseId ->
TestCaseReviewTestCaseUsersExample example = new TestCaseReviewTestCaseUsersExample(); request.getReviewerIds().forEach(reviewerId -> {
example.createCriteria().andReviewIdEqualTo(request.getReviewId()).andCaseIdEqualTo(ids.get(i)).andUserIdEqualTo(request.getReviewer()); addTestCaseReviewTestCaseUser(reviewerId, batchMapper, (String) caseId, request.getReviewId());
}));
} else {
example.createCriteria()
.andReviewIdEqualTo(request.getReviewId())
.andCaseIdIn(subList)
.andUserIdIn(request.getReviewerIds());
// 查询用例已有的评审人
List<TestCaseReviewTestCaseUsers> testCaseReviewTestCaseUsers = testCaseReviewTestCaseUsersMapper.selectByExample(example); List<TestCaseReviewTestCaseUsers> testCaseReviewTestCaseUsers = testCaseReviewTestCaseUsersMapper.selectByExample(example);
if (CollectionUtils.isEmpty(testCaseReviewTestCaseUsers)) {
TestCaseReviewTestCaseUsers insertData = new TestCaseReviewTestCaseUsers(); Set<String> caseUserSet = testCaseReviewTestCaseUsers.stream()
insertData.setCaseId(ids.get(i)); .map(item -> item.getCaseId() + item.getUserId())
insertData.setReviewId(request.getReviewId()); .collect(Collectors.toSet());
insertData.setUserId(request.getReviewer());
testCaseReviewTestCaseUsersMapper.insert(insertData); subList.forEach(caseId ->
} request.getReviewerIds().forEach(reviewerId -> {
// 如果该用例没有当前的评审人就添加评审人
if (!caseUserSet.contains(caseId + reviewerId)) {
addTestCaseReviewTestCaseUser(reviewerId, batchMapper, (String) caseId, request.getReviewId());
}
}));
} }
batchSqlSession.flushStatements();
batchSqlSession.close();
});
// 修改评审人后重新计算用例的评审状态 // 修改评审人后重新计算用例的评审状态
TestCaseReview testReview = testCaseReviewService.getTestReview(request.getReviewId()); TestCaseReview testReview = testCaseReviewService.getTestReview(request.getReviewId());
List<TestCaseReviewTestCase> testCaseReviewTestCases = selectForReviewChange(request.getReviewId()); List<TestCaseReviewTestCase> testCaseReviewTestCases = selectForReviewChange(request.getReviewId());
for (TestCaseReviewTestCase reviewTestCase : testCaseReviewTestCases) { for (TestCaseReviewTestCase reviewTestCase : testCaseReviewTestCases) {
// 重新计算评审状态 // 重新计算评审状态
reCalcReviewCaseStatus(testReview.getReviewPassRule(), reviewTestCase); reCalcReviewCaseStatus(testReview.getReviewPassRule(), reviewTestCase);
}
} }
}
private void addTestCaseReviewTestCaseUser(String reviewer, TestCaseReviewTestCaseUsersMapper batchMapper,
String caseId, String reviewerId) {
TestCaseReviewTestCaseUsers insertData = new TestCaseReviewTestCaseUsers();
insertData.setCaseId(caseId);
insertData.setReviewId(reviewerId);
insertData.setUserId(reviewer);
batchMapper.insert(insertData);
} }
private void checkReviewCase(String reviewId) { private void checkReviewCase(String reviewId) {
@ -679,21 +718,13 @@ public class TestReviewTestCaseService {
return updateIsDel(ids, false); return updateIsDel(ids, false);
} }
private List<String> getReviewUserIds(String reviewId, String caseId) { private List<TestCaseReviewTestCaseUsers> getTestCaseReviewTestCaseUsers(String reviewId, List<String> caseIds) {
TestCaseReviewTestCaseUsersExample testCaseReviewTestCaseUsersExample = new TestCaseReviewTestCaseUsersExample();
testCaseReviewTestCaseUsersExample.createCriteria().andReviewIdEqualTo(reviewId).andCaseIdEqualTo(caseId);
List<TestCaseReviewTestCaseUsers> testCaseReviewUsers = testCaseReviewTestCaseUsersMapper.selectByExample(testCaseReviewTestCaseUsersExample);
return testCaseReviewUsers.stream().map(TestCaseReviewTestCaseUsers::getUserId).collect(Collectors.toList());
}
private List<String> getReviewUserIds(String reviewId, List<String> caseIds) {
if (CollectionUtils.isEmpty(caseIds)) { if (CollectionUtils.isEmpty(caseIds)) {
return new ArrayList<>(); return new ArrayList<>();
} }
TestCaseReviewTestCaseUsersExample testCaseReviewTestCaseUsersExample = new TestCaseReviewTestCaseUsersExample(); TestCaseReviewTestCaseUsersExample testCaseReviewTestCaseUsersExample = new TestCaseReviewTestCaseUsersExample();
testCaseReviewTestCaseUsersExample.createCriteria().andReviewIdEqualTo(reviewId).andCaseIdIn(caseIds); testCaseReviewTestCaseUsersExample.createCriteria().andReviewIdEqualTo(reviewId).andCaseIdIn(caseIds);
List<TestCaseReviewTestCaseUsers> testCaseReviewUsers = testCaseReviewTestCaseUsersMapper.selectByExample(testCaseReviewTestCaseUsersExample); return testCaseReviewTestCaseUsersMapper.selectByExample(testCaseReviewTestCaseUsersExample);
return testCaseReviewUsers.stream().map(TestCaseReviewTestCaseUsers::getUserId).collect(Collectors.toList());
} }
public List<TestCaseReviewTestCase> getCaseStatusByReviewIds(List<String> reviewIds) { public List<TestCaseReviewTestCase> getCaseStatusByReviewIds(List<String> reviewIds) {

View File

@ -44,7 +44,7 @@
</el-form-item> </el-form-item>
<el-form-item v-else-if="form.type === 'reviewers'" :label="$t('test_track.case.batch_update_to')" prop="value"> <el-form-item v-else-if="form.type === 'reviewers'" :label="$t('test_track.case.batch_update_to')" prop="value">
<el-select v-model="form.value" style="width: 100%" :filterable="filterable" :disabled="!form.type"> <el-select multiple v-model="form.value" style="width: 100%" :filterable="filterable" :disabled="!form.type">
<el-option v-for="(option, index) in options" :key="index" :value="option.id" :label="option.name"> <el-option v-for="(option, index) in options" :key="index" :value="option.id" :label="option.name">
<div v-if="option.email"> <div v-if="option.email">
<span>{{ option.id }}({{ option.name }})</span> <span>{{ option.id }}({{ option.name }})</span>

View File

@ -553,7 +553,7 @@ export default {
param.reviewId = reviewId; param.reviewId = reviewId;
param.description = form.description; param.description = form.description;
if (form.type === 'reviewers') { if (form.type === 'reviewers') {
param.reviewer = form.value; param.reviewerIds = form.value;
param.appendTag = form.appendTag; param.appendTag = form.appendTag;
batchEditTestReviewCaseReviewer(param) batchEditTestReviewCaseReviewer(param)
.then(() => { .then(() => {