feat(用例评审): 加接口处理代替listener

This commit is contained in:
guoyuqi 2023-12-21 09:15:52 +08:00 committed by 刘瑞斌
parent 339d9e9a2d
commit 9797570922
41 changed files with 1045 additions and 842 deletions

View File

@ -1,8 +1,6 @@
package io.metersphere.listener;
import io.metersphere.api.event.ApiEventSource;
import io.metersphere.functional.event.CaseEventSource;
import io.metersphere.functional.listener.CaseEventListener;
import io.metersphere.plan.listener.ExecEventListener;
import io.metersphere.sdk.constants.StorageType;
import io.metersphere.sdk.file.FileCenter;
@ -34,7 +32,6 @@ public class AppStartListener implements ApplicationRunner {
LogUtils.info("初始化接口事件源");
ApiEventSource apiEventSource = CommonBeanFactory.getBean(ApiEventSource.class);
LogUtils.info("初始化用例管理事件源");
CaseEventSource caseEventSource = CommonBeanFactory.getBean(CaseEventSource.class);
LogUtils.info("初始化性能测试事件源");
//LoadEventSource loadEventSource = CommonBeanFactory.getBean(LoadEventSource.class);
//todo: 注册其他事件源
@ -44,14 +41,11 @@ public class AppStartListener implements ApplicationRunner {
apiEventSource.addListener(listener);
//todo: 注册其他监听器
CaseEventListener caseEventListener = CommonBeanFactory.getBean(CaseEventListener.class);
caseEventSource.addListener(caseEventListener);
//loadEventSource.addListener(listener);
// 触发事件
apiEventSource.fireEvent("API", "Event after removing the listener test.");
//loadEventSource.fireEvent("LOAD","Event after removing the listener.");
caseEventSource.fireEvent("CASE", "Event after removing the listener test.");
// 加载插件
pluginLoadService.loadPlugins();
}

View File

@ -30,6 +30,10 @@ public class CaseReviewHistory implements Serializable {
@Size(min = 1, max = 64, message = "{case_review_history.status.length_range}", groups = {Created.class, Updated.class})
private String status;
@Schema(description = "是否是取消关联或评审被删除的0-否1-是", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "{case_review_history.deleted.not_blank}", groups = {Created.class})
private Boolean deleted;
@Schema(description = "通知人")
private String notifier;
@ -49,6 +53,7 @@ public class CaseReviewHistory implements Serializable {
reviewId("review_id", "reviewId", "VARCHAR", false),
caseId("case_id", "caseId", "VARCHAR", false),
status("status", "status", "VARCHAR", true),
deleted("deleted", "deleted", "BIT", false),
notifier("notifier", "notifier", "VARCHAR", false),
createUser("create_user", "createUser", "VARCHAR", false),
createTime("create_time", "createTime", "BIGINT", false),

View File

@ -384,6 +384,66 @@ public class CaseReviewHistoryExample {
return (Criteria) this;
}
public Criteria andDeletedIsNull() {
addCriterion("deleted is null");
return (Criteria) this;
}
public Criteria andDeletedIsNotNull() {
addCriterion("deleted is not null");
return (Criteria) this;
}
public Criteria andDeletedEqualTo(Boolean value) {
addCriterion("deleted =", value, "deleted");
return (Criteria) this;
}
public Criteria andDeletedNotEqualTo(Boolean value) {
addCriterion("deleted <>", value, "deleted");
return (Criteria) this;
}
public Criteria andDeletedGreaterThan(Boolean value) {
addCriterion("deleted >", value, "deleted");
return (Criteria) this;
}
public Criteria andDeletedGreaterThanOrEqualTo(Boolean value) {
addCriterion("deleted >=", value, "deleted");
return (Criteria) this;
}
public Criteria andDeletedLessThan(Boolean value) {
addCriterion("deleted <", value, "deleted");
return (Criteria) this;
}
public Criteria andDeletedLessThanOrEqualTo(Boolean value) {
addCriterion("deleted <=", value, "deleted");
return (Criteria) this;
}
public Criteria andDeletedIn(List<Boolean> values) {
addCriterion("deleted in", values, "deleted");
return (Criteria) this;
}
public Criteria andDeletedNotIn(List<Boolean> values) {
addCriterion("deleted not in", values, "deleted");
return (Criteria) this;
}
public Criteria andDeletedBetween(Boolean value1, Boolean value2) {
addCriterion("deleted between", value1, value2, "deleted");
return (Criteria) this;
}
public Criteria andDeletedNotBetween(Boolean value1, Boolean value2) {
addCriterion("deleted not between", value1, value2, "deleted");
return (Criteria) this;
}
public Criteria andNotifierIsNull() {
addCriterion("notifier is null");
return (Criteria) this;

View File

@ -1,10 +1,8 @@
package io.metersphere.functional.domain;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import io.metersphere.validation.groups.*;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import jakarta.validation.constraints.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
@ -25,14 +23,6 @@ public class FunctionalCaseComment implements Serializable {
@Schema(description = "评论人")
private String createUser;
@Schema(description = "评审/测试计划执行状态:通过/不通过/重新提审/通过标准变更标记/强制通过标记/强制不通过标记/状态变更标记")
private String status;
@Schema(description = "评论类型:用例评论/测试计划用例评论/评审用例评论", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{functional_case_comment.type.not_blank}", groups = {Created.class})
@Size(min = 1, max = 64, message = "{functional_case_comment.type.length_range}", groups = {Created.class, Updated.class})
private String type;
@Schema(description = "父评论ID")
private String parentId;
@ -53,6 +43,7 @@ public class FunctionalCaseComment implements Serializable {
@Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{functional_case_comment.content.not_blank}", groups = {Created.class})
@Size(min = 1, max = 65535, message = "{functional_case_comment.content.length_range}", groups = {Created.class, Updated.class})
private String content;
private static final long serialVersionUID = 1L;
@ -61,8 +52,6 @@ public class FunctionalCaseComment implements Serializable {
id("id", "id", "VARCHAR", false),
caseId("case_id", "caseId", "VARCHAR", false),
createUser("create_user", "createUser", "VARCHAR", false),
status("status", "status", "VARCHAR", true),
type("type", "type", "VARCHAR", true),
parentId("parent_id", "parentId", "VARCHAR", false),
resourceId("resource_id", "resourceId", "VARCHAR", false),
notifier("notifier", "notifier", "VARCHAR", false),

View File

@ -314,146 +314,6 @@ public class FunctionalCaseCommentExample {
return (Criteria) this;
}
public Criteria andStatusIsNull() {
addCriterion("`status` is null");
return (Criteria) this;
}
public Criteria andStatusIsNotNull() {
addCriterion("`status` is not null");
return (Criteria) this;
}
public Criteria andStatusEqualTo(String value) {
addCriterion("`status` =", value, "status");
return (Criteria) this;
}
public Criteria andStatusNotEqualTo(String value) {
addCriterion("`status` <>", value, "status");
return (Criteria) this;
}
public Criteria andStatusGreaterThan(String value) {
addCriterion("`status` >", value, "status");
return (Criteria) this;
}
public Criteria andStatusGreaterThanOrEqualTo(String value) {
addCriterion("`status` >=", value, "status");
return (Criteria) this;
}
public Criteria andStatusLessThan(String value) {
addCriterion("`status` <", value, "status");
return (Criteria) this;
}
public Criteria andStatusLessThanOrEqualTo(String value) {
addCriterion("`status` <=", value, "status");
return (Criteria) this;
}
public Criteria andStatusLike(String value) {
addCriterion("`status` like", value, "status");
return (Criteria) this;
}
public Criteria andStatusNotLike(String value) {
addCriterion("`status` not like", value, "status");
return (Criteria) this;
}
public Criteria andStatusIn(List<String> values) {
addCriterion("`status` in", values, "status");
return (Criteria) this;
}
public Criteria andStatusNotIn(List<String> values) {
addCriterion("`status` not in", values, "status");
return (Criteria) this;
}
public Criteria andStatusBetween(String value1, String value2) {
addCriterion("`status` between", value1, value2, "status");
return (Criteria) this;
}
public Criteria andStatusNotBetween(String value1, String value2) {
addCriterion("`status` not between", value1, value2, "status");
return (Criteria) this;
}
public Criteria andTypeIsNull() {
addCriterion("`type` is null");
return (Criteria) this;
}
public Criteria andTypeIsNotNull() {
addCriterion("`type` is not null");
return (Criteria) this;
}
public Criteria andTypeEqualTo(String value) {
addCriterion("`type` =", value, "type");
return (Criteria) this;
}
public Criteria andTypeNotEqualTo(String value) {
addCriterion("`type` <>", value, "type");
return (Criteria) this;
}
public Criteria andTypeGreaterThan(String value) {
addCriterion("`type` >", value, "type");
return (Criteria) this;
}
public Criteria andTypeGreaterThanOrEqualTo(String value) {
addCriterion("`type` >=", value, "type");
return (Criteria) this;
}
public Criteria andTypeLessThan(String value) {
addCriterion("`type` <", value, "type");
return (Criteria) this;
}
public Criteria andTypeLessThanOrEqualTo(String value) {
addCriterion("`type` <=", value, "type");
return (Criteria) this;
}
public Criteria andTypeLike(String value) {
addCriterion("`type` like", value, "type");
return (Criteria) this;
}
public Criteria andTypeNotLike(String value) {
addCriterion("`type` not like", value, "type");
return (Criteria) this;
}
public Criteria andTypeIn(List<String> values) {
addCriterion("`type` in", values, "type");
return (Criteria) this;
}
public Criteria andTypeNotIn(List<String> values) {
addCriterion("`type` not in", values, "type");
return (Criteria) this;
}
public Criteria andTypeBetween(String value1, String value2) {
addCriterion("`type` between", value1, value2, "type");
return (Criteria) this;
}
public Criteria andTypeNotBetween(String value1, String value2) {
addCriterion("`type` not between", value1, value2, "type");
return (Criteria) this;
}
public Criteria andParentIdIsNull() {
addCriterion("parent_id is null");
return (Criteria) this;

View File

@ -6,6 +6,7 @@
<result column="review_id" jdbcType="VARCHAR" property="reviewId" />
<result column="case_id" jdbcType="VARCHAR" property="caseId" />
<result column="status" jdbcType="VARCHAR" property="status" />
<result column="deleted" jdbcType="BIT" property="deleted" />
<result column="notifier" jdbcType="VARCHAR" property="notifier" />
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
@ -72,7 +73,7 @@
</where>
</sql>
<sql id="Base_Column_List">
id, review_id, case_id, `status`, notifier, create_user, create_time
id, review_id, case_id, `status`, deleted, notifier, create_user, create_time
</sql>
<sql id="Blob_Column_List">
content
@ -127,11 +128,13 @@
</delete>
<insert id="insert" parameterType="io.metersphere.functional.domain.CaseReviewHistory">
insert into case_review_history (id, review_id, case_id,
`status`, notifier, create_user,
create_time, content)
`status`, deleted, notifier,
create_user, create_time, content
)
values (#{id,jdbcType=VARCHAR}, #{reviewId,jdbcType=VARCHAR}, #{caseId,jdbcType=VARCHAR},
#{status,jdbcType=VARCHAR}, #{notifier,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR},
#{createTime,jdbcType=BIGINT}, #{content,jdbcType=LONGVARBINARY})
#{status,jdbcType=VARCHAR}, #{deleted,jdbcType=BIT}, #{notifier,jdbcType=VARCHAR},
#{createUser,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{content,jdbcType=LONGVARBINARY}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.functional.domain.CaseReviewHistory">
insert into case_review_history
@ -148,6 +151,9 @@
<if test="status != null">
`status`,
</if>
<if test="deleted != null">
deleted,
</if>
<if test="notifier != null">
notifier,
</if>
@ -174,6 +180,9 @@
<if test="status != null">
#{status,jdbcType=VARCHAR},
</if>
<if test="deleted != null">
#{deleted,jdbcType=BIT},
</if>
<if test="notifier != null">
#{notifier,jdbcType=VARCHAR},
</if>
@ -209,6 +218,9 @@
<if test="record.status != null">
`status` = #{record.status,jdbcType=VARCHAR},
</if>
<if test="record.deleted != null">
deleted = #{record.deleted,jdbcType=BIT},
</if>
<if test="record.notifier != null">
notifier = #{record.notifier,jdbcType=VARCHAR},
</if>
@ -232,6 +244,7 @@
review_id = #{record.reviewId,jdbcType=VARCHAR},
case_id = #{record.caseId,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=VARCHAR},
deleted = #{record.deleted,jdbcType=BIT},
notifier = #{record.notifier,jdbcType=VARCHAR},
create_user = #{record.createUser,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
@ -246,6 +259,7 @@
review_id = #{record.reviewId,jdbcType=VARCHAR},
case_id = #{record.caseId,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=VARCHAR},
deleted = #{record.deleted,jdbcType=BIT},
notifier = #{record.notifier,jdbcType=VARCHAR},
create_user = #{record.createUser,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT}
@ -265,6 +279,9 @@
<if test="status != null">
`status` = #{status,jdbcType=VARCHAR},
</if>
<if test="deleted != null">
deleted = #{deleted,jdbcType=BIT},
</if>
<if test="notifier != null">
notifier = #{notifier,jdbcType=VARCHAR},
</if>
@ -285,6 +302,7 @@
set review_id = #{reviewId,jdbcType=VARCHAR},
case_id = #{caseId,jdbcType=VARCHAR},
`status` = #{status,jdbcType=VARCHAR},
deleted = #{deleted,jdbcType=BIT},
notifier = #{notifier,jdbcType=VARCHAR},
create_user = #{createUser,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
@ -296,6 +314,7 @@
set review_id = #{reviewId,jdbcType=VARCHAR},
case_id = #{caseId,jdbcType=VARCHAR},
`status` = #{status,jdbcType=VARCHAR},
deleted = #{deleted,jdbcType=BIT},
notifier = #{notifier,jdbcType=VARCHAR},
create_user = #{createUser,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT}
@ -303,12 +322,14 @@
</update>
<insert id="batchInsert" parameterType="map">
insert into case_review_history
(id, review_id, case_id, `status`, notifier, create_user, create_time, content)
(id, review_id, case_id, `status`, deleted, notifier, create_user, create_time, content
)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.reviewId,jdbcType=VARCHAR}, #{item.caseId,jdbcType=VARCHAR},
#{item.status,jdbcType=VARCHAR}, #{item.notifier,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR},
#{item.createTime,jdbcType=BIGINT}, #{item.content,jdbcType=LONGVARBINARY})
#{item.status,jdbcType=VARCHAR}, #{item.deleted,jdbcType=BIT}, #{item.notifier,jdbcType=VARCHAR},
#{item.createUser,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT}, #{item.content,jdbcType=LONGVARBINARY}
)
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
@ -333,6 +354,9 @@
<if test="'status'.toString() == column.value">
#{item.status,jdbcType=VARCHAR}
</if>
<if test="'deleted'.toString() == column.value">
#{item.deleted,jdbcType=BIT}
</if>
<if test="'notifier'.toString() == column.value">
#{item.notifier,jdbcType=VARCHAR}
</if>

View File

@ -5,8 +5,6 @@
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="case_id" jdbcType="VARCHAR" property="caseId" />
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
<result column="status" jdbcType="VARCHAR" property="status" />
<result column="type" jdbcType="VARCHAR" property="type" />
<result column="parent_id" jdbcType="VARCHAR" property="parentId" />
<result column="resource_id" jdbcType="VARCHAR" property="resourceId" />
<result column="notifier" jdbcType="VARCHAR" property="notifier" />
@ -76,8 +74,8 @@
</where>
</sql>
<sql id="Base_Column_List">
id, case_id, create_user, `status`, `type`, parent_id, resource_id, notifier, reply_user,
create_time, update_time
id, case_id, create_user, parent_id, resource_id, notifier, reply_user, create_time,
update_time
</sql>
<sql id="Blob_Column_List">
content
@ -132,15 +130,13 @@
</delete>
<insert id="insert" parameterType="io.metersphere.functional.domain.FunctionalCaseComment">
insert into functional_case_comment (id, case_id, create_user,
`status`, `type`, parent_id,
resource_id, notifier, reply_user,
create_time, update_time, content
)
parent_id, resource_id, notifier,
reply_user, create_time, update_time,
content)
values (#{id,jdbcType=VARCHAR}, #{caseId,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR},
#{status,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{parentId,jdbcType=VARCHAR},
#{resourceId,jdbcType=VARCHAR}, #{notifier,jdbcType=VARCHAR}, #{replyUser,jdbcType=VARCHAR},
#{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{content,jdbcType=LONGVARCHAR}
)
#{parentId,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR}, #{notifier,jdbcType=VARCHAR},
#{replyUser,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
#{content,jdbcType=LONGVARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.functional.domain.FunctionalCaseComment">
insert into functional_case_comment
@ -154,12 +150,6 @@
<if test="createUser != null">
create_user,
</if>
<if test="status != null">
`status`,
</if>
<if test="type != null">
`type`,
</if>
<if test="parentId != null">
parent_id,
</if>
@ -192,12 +182,6 @@
<if test="createUser != null">
#{createUser,jdbcType=VARCHAR},
</if>
<if test="status != null">
#{status,jdbcType=VARCHAR},
</if>
<if test="type != null">
#{type,jdbcType=VARCHAR},
</if>
<if test="parentId != null">
#{parentId,jdbcType=VARCHAR},
</if>
@ -239,12 +223,6 @@
<if test="record.createUser != null">
create_user = #{record.createUser,jdbcType=VARCHAR},
</if>
<if test="record.status != null">
`status` = #{record.status,jdbcType=VARCHAR},
</if>
<if test="record.type != null">
`type` = #{record.type,jdbcType=VARCHAR},
</if>
<if test="record.parentId != null">
parent_id = #{record.parentId,jdbcType=VARCHAR},
</if>
@ -276,8 +254,6 @@
set id = #{record.id,jdbcType=VARCHAR},
case_id = #{record.caseId,jdbcType=VARCHAR},
create_user = #{record.createUser,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=VARCHAR},
`type` = #{record.type,jdbcType=VARCHAR},
parent_id = #{record.parentId,jdbcType=VARCHAR},
resource_id = #{record.resourceId,jdbcType=VARCHAR},
notifier = #{record.notifier,jdbcType=VARCHAR},
@ -294,8 +270,6 @@
set id = #{record.id,jdbcType=VARCHAR},
case_id = #{record.caseId,jdbcType=VARCHAR},
create_user = #{record.createUser,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=VARCHAR},
`type` = #{record.type,jdbcType=VARCHAR},
parent_id = #{record.parentId,jdbcType=VARCHAR},
resource_id = #{record.resourceId,jdbcType=VARCHAR},
notifier = #{record.notifier,jdbcType=VARCHAR},
@ -315,12 +289,6 @@
<if test="createUser != null">
create_user = #{createUser,jdbcType=VARCHAR},
</if>
<if test="status != null">
`status` = #{status,jdbcType=VARCHAR},
</if>
<if test="type != null">
`type` = #{type,jdbcType=VARCHAR},
</if>
<if test="parentId != null">
parent_id = #{parentId,jdbcType=VARCHAR},
</if>
@ -349,8 +317,6 @@
update functional_case_comment
set case_id = #{caseId,jdbcType=VARCHAR},
create_user = #{createUser,jdbcType=VARCHAR},
`status` = #{status,jdbcType=VARCHAR},
`type` = #{type,jdbcType=VARCHAR},
parent_id = #{parentId,jdbcType=VARCHAR},
resource_id = #{resourceId,jdbcType=VARCHAR},
notifier = #{notifier,jdbcType=VARCHAR},
@ -364,8 +330,6 @@
update functional_case_comment
set case_id = #{caseId,jdbcType=VARCHAR},
create_user = #{createUser,jdbcType=VARCHAR},
`status` = #{status,jdbcType=VARCHAR},
`type` = #{type,jdbcType=VARCHAR},
parent_id = #{parentId,jdbcType=VARCHAR},
resource_id = #{resourceId,jdbcType=VARCHAR},
notifier = #{notifier,jdbcType=VARCHAR},
@ -376,15 +340,14 @@
</update>
<insert id="batchInsert" parameterType="map">
insert into functional_case_comment
(id, case_id, create_user, `status`, `type`, parent_id, resource_id, notifier, reply_user,
create_time, update_time, content)
(id, case_id, create_user, parent_id, resource_id, notifier, reply_user, create_time,
update_time, content)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.caseId,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR},
#{item.status,jdbcType=VARCHAR}, #{item.type,jdbcType=VARCHAR}, #{item.parentId,jdbcType=VARCHAR},
#{item.resourceId,jdbcType=VARCHAR}, #{item.notifier,jdbcType=VARCHAR}, #{item.replyUser,jdbcType=VARCHAR},
#{item.createTime,jdbcType=BIGINT}, #{item.updateTime,jdbcType=BIGINT}, #{item.content,jdbcType=LONGVARCHAR}
)
#{item.parentId,jdbcType=VARCHAR}, #{item.resourceId,jdbcType=VARCHAR}, #{item.notifier,jdbcType=VARCHAR},
#{item.replyUser,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT}, #{item.updateTime,jdbcType=BIGINT},
#{item.content,jdbcType=LONGVARCHAR})
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
@ -406,12 +369,6 @@
<if test="'create_user'.toString() == column.value">
#{item.createUser,jdbcType=VARCHAR}
</if>
<if test="'status'.toString() == column.value">
#{item.status,jdbcType=VARCHAR}
</if>
<if test="'type'.toString() == column.value">
#{item.type,jdbcType=VARCHAR}
</if>
<if test="'parent_id'.toString() == column.value">
#{item.parentId,jdbcType=VARCHAR}
</if>

View File

@ -62,8 +62,6 @@ CREATE TABLE IF NOT EXISTS functional_case_comment
`id` VARCHAR(50) NOT NULL COMMENT 'ID',
`case_id` VARCHAR(50) NOT NULL COMMENT '功能用例ID',
`create_user` VARCHAR(50) NOT NULL COMMENT '评论人',
`status` VARCHAR(64) COMMENT '评审/测试计划执行状态:通过/不通过/重新提审/通过标准变更标记/强制通过标记/强制不通过标记/状态变更标记',
`type` VARCHAR(64) NOT NULL DEFAULT 'CASE' COMMENT '评论类型:用例评论/测试计划用例评论/评审用例评论',
`parent_id` VARCHAR(50) COMMENT '父评论ID',
`resource_id` VARCHAR(50) COMMENT '资源ID: 评审ID/测试计划ID',
`notifier` VARCHAR(1000) COMMENT '通知人',
@ -79,8 +77,6 @@ CREATE TABLE IF NOT EXISTS functional_case_comment
CREATE INDEX idx_create_time ON functional_case_comment (create_time desc);
CREATE INDEX idx_case_id ON functional_case_comment (case_id);
CREATE INDEX idx_status ON functional_case_comment (status);
CREATE INDEX idx_type ON functional_case_comment (type);
CREATE INDEX idx_resource_id ON functional_case_comment (resource_id);
CREATE TABLE IF NOT EXISTS functional_case_module
@ -108,7 +104,7 @@ CREATE INDEX idx_create_user ON functional_case_module (create_user);
CREATE INDEX idx_update_user ON functional_case_module (update_user);
CREATE INDEX idx_create_time ON functional_case_module (create_time desc);
CREATE INDEX idx_update_time ON functional_case_module (update_time desc);
CREATE UNIQUE INDEX uq_name_project_parent ON functional_case_module(project_id,name,parent_id);
CREATE TABLE IF NOT EXISTS functional_case_attachment
(
@ -349,6 +345,7 @@ CREATE TABLE IF NOT EXISTS case_review_history
`case_id` VARCHAR(50) NOT NULL COMMENT '用例ID',
`content` LONGBLOB COMMENT '评审意见',
`status` VARCHAR(64) NOT NULL COMMENT '评审结果:通过/不通过/建议',
`deleted` BIT(1) NOT NULL DEFAULT 0 COMMENT '是否是取消关联或评审被删除的0-否1-是' ,
`notifier` VARCHAR(1000) COMMENT '通知人',
`create_user` VARCHAR(50) NOT NULL COMMENT '操作人',
`create_time` BIGINT NOT NULL COMMENT '操作时间',
@ -362,6 +359,7 @@ CREATE INDEX idx_case_id ON case_review_history (case_id);
CREATE INDEX idx_review_id ON case_review_history (review_id);
CREATE INDEX idx_review_id_case_id ON case_review_history (review_id, case_id);
CREATE INDEX idx_status ON case_review_history (status);
CREATE INDEX idx_deleted ON case_review_history(deleted);
CREATE TABLE IF NOT EXISTS case_review_module
@ -389,6 +387,7 @@ CREATE INDEX idx_create_user ON case_review_module (create_user);
CREATE INDEX idx_update_user ON case_review_module (update_user);
CREATE INDEX idx_create_time ON case_review_module (create_time desc);
CREATE INDEX idx_update_time ON case_review_module (update_time desc);
CREATE UNIQUE INDEX uq_name_project_parent ON case_review_module(name,project_id,parent_id);
-- set innodb lock wait timeout to default

View File

@ -17,6 +17,7 @@
<module>plugin</module>
<module>domain</module>
<module>sdk</module>
<module>provider</module>
</modules>
</project>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.metersphere</groupId>
<artifactId>framework</artifactId>
<version>${revision}</version>
</parent>
<artifactId>metersphere-provider</artifactId>
<version>${revision}</version>
<name>metersphere-provider</name>
<description>provider</description>
<properties>
</properties>
</project>

View File

@ -0,0 +1,7 @@
package io.metersphere.provider;
import java.util.Map;
public interface BaseCaseProvider {
void updateCaseReview(Map<String, Object> paramMap);
}

View File

@ -36,6 +36,11 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.metersphere</groupId>
<artifactId>metersphere-provider</artifactId>
<version>${revision}</version>
</dependency>
</dependencies>
<build>

View File

@ -9,6 +9,7 @@ public interface CaseEvent {
String DELETE_FUNCTIONAL_CASE = "deleteFunctionalCase";
String DELETE_TRASH_FUNCTIONAL_CASE = "deleteTrashFunctionalCase";
String RECOVER_FUNCTIONAL_CASE = "recoverFunctionalCase";
String REVIEW_FUNCTIONAL_CASE = "reviewFunctionalCase";
}
interface Param {
@ -16,7 +17,10 @@ public interface CaseEvent {
String CASE_IDS = "caseIds";
String PASS_COUNT = "passCount";
String CASE_COUNT = "caseCount";
String STATUS = "status";
String USER_ID = "userId";
String UN_COMPLETED_COUNT = "unCompletedCount";
String EVENT_NAME = "eventName";
}
}

View File

@ -1,5 +0,0 @@
package io.metersphere.functional.constants;
public enum CommentEnum {
CASE, TEST_PLAN, CASE_REVIEW
}

View File

@ -110,7 +110,7 @@ public class CaseReviewController {
@Log(type = OperationLogType.DISASSOCIATE, expression = "#msClass.disAssociateCaseLog(#reviewId, #caseId)", msClass = CaseReviewLogService.class)
@RequiresPermissions(PermissionConstants.CASE_REVIEW_RELEVANCE)
public void disassociate(@PathVariable String reviewId, @PathVariable String caseId) {
caseReviewService.disassociate(reviewId, caseId);
caseReviewService.disassociate(reviewId, caseId, SessionUtils.getUserId());
}
@PostMapping("/edit/pos")

View File

@ -7,6 +7,7 @@ import com.github.pagehelper.PageHelper;
import io.metersphere.functional.dto.ReviewFunctionalCaseDTO;
import io.metersphere.functional.request.BaseReviewCaseBatchRequest;
import io.metersphere.functional.request.CaseReviewFunctionalCasePosRequest;
import io.metersphere.functional.request.BatchReviewFunctionalCaseRequest;
import io.metersphere.functional.request.ReviewFunctionalCasePageRequest;
import io.metersphere.functional.service.CaseReviewFunctionalCaseService;
import io.metersphere.functional.service.CaseReviewLogService;
@ -60,7 +61,7 @@ public class CaseReviewFunctionalCaseController {
@Operation(summary = "用例管理-功能用例-评审列表-评审详情-列表-批量取消关联用例")
@Log(type = OperationLogType.DISASSOCIATE, expression = "#msClass.batchDisassociateCaseLog(#request)", msClass = CaseReviewLogService.class)
public void batchDisassociate(@Validated @RequestBody BaseReviewCaseBatchRequest request) {
caseReviewFunctionalCaseService.disassociate(request);
caseReviewFunctionalCaseService.disassociate(request, SessionUtils.getUserId());
}
@PostMapping("/edit/pos")
@ -70,4 +71,11 @@ public class CaseReviewFunctionalCaseController {
caseReviewFunctionalCaseService.editPos(request);
}
@PostMapping("/batch/review")
@Operation(summary = "用例管理-功能用例-评审列表-评审详情-列表-批量评审")
@RequiresPermissions(PermissionConstants.CASE_REVIEW_REVIEW)
public void batchReview(@Validated @RequestBody BatchReviewFunctionalCaseRequest request) {
caseReviewFunctionalCaseService.batchReview(request, SessionUtils.getUserId());
}
}

View File

@ -72,7 +72,7 @@ public class FunctionalCaseTrashController {
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_DELETE)
@Log(type = OperationLogType.DELETE, expression = "#msClass.deleteTrashCaseLog(#id)", msClass = FunctionalCaseLogService.class)
public void deleteCase(@PathVariable String id) {
functionalCaseTrashService.deleteCase(id);
functionalCaseTrashService.deleteCase(id, SessionUtils.getUserId());
}
@PostMapping("/batch/delete")
@ -80,7 +80,7 @@ public class FunctionalCaseTrashController {
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_READ_DELETE)
@Log(type = OperationLogType.DELETE, expression = "#msClass.batchDeleteTrashCaseLog(#request)", msClass = FunctionalCaseLogService.class)
public void batchDeleteCase(@Validated @RequestBody FunctionalCaseBatchRequest request) {
functionalCaseTrashService.batchDeleteCase(request);
functionalCaseTrashService.batchDeleteCase(request, SessionUtils.getUserId());
}
}

View File

@ -1,32 +0,0 @@
package io.metersphere.functional.event;
import io.metersphere.sdk.listener.Event;
import io.metersphere.sdk.listener.EventListener;
import io.metersphere.sdk.listener.EventSource;
import io.metersphere.sdk.util.LogUtils;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class CaseEventSource implements EventSource {
private EventListener<Event> listener;
@Override
public void addListener(EventListener<Event> listener) {
this.listener = listener;
}
@Override
public void fireEvent(String module, String message) {
Event event = new Event("CASE", message);
listener.onEvent(event);
}
@Override
public void fireEvent(String module, String message, Map<String, Object> paramMap) {
Event event = new Event("CASE", message, paramMap);
listener.onEvent(event);
LogUtils.info("带有参数的监听事件");
}
}

View File

@ -1,201 +0,0 @@
package io.metersphere.functional.listener;
import io.metersphere.functional.constants.CaseEvent;
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
import io.metersphere.functional.domain.CaseReview;
import io.metersphere.functional.domain.CaseReviewFunctionalCase;
import io.metersphere.functional.domain.CaseReviewFunctionalCaseExample;
import io.metersphere.functional.domain.CaseReviewFunctionalCaseUserExample;
import io.metersphere.functional.mapper.CaseReviewFunctionalCaseMapper;
import io.metersphere.functional.mapper.CaseReviewFunctionalCaseUserMapper;
import io.metersphere.functional.mapper.CaseReviewMapper;
import io.metersphere.sdk.listener.Event;
import io.metersphere.sdk.listener.EventListener;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component
public class CaseEventListener implements EventListener<Event> {
@Resource
private CaseReviewMapper caseReviewMapper;
@Resource
private CaseReviewFunctionalCaseUserMapper caseReviewFunctionalCaseUserMapper;
@Resource
private CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper;
@Async
@Override
public void onEvent(Event event) {
LogUtils.info("CaseEventListener: " + event.module() + "" + event.message());
//批量修改用例评审人
//重新提审(批量)/自动重新提审编辑
//批量修改结果
String message = event.message();
switch (message) {
case CaseEvent.Event.ASSOCIATE -> {
updateCaseReviewByAssociate(event);
}
case CaseEvent.Event.DISASSOCIATE -> {
updateCaseReviewByDisAssociate(event);
}
case CaseEvent.Event.BATCH_DISASSOCIATE -> {
updateCaseReviewByBatchDisassociate(event);
}
case CaseEvent.Event.DELETE_FUNCTIONAL_CASE -> {
updateCaseReviewByDeleteFunctionalCase(event);
}
case CaseEvent.Event.DELETE_TRASH_FUNCTIONAL_CASE -> {
updateCaseReviewByDeleteTrashFunctionalCase(event);
}
case CaseEvent.Event.RECOVER_FUNCTIONAL_CASE -> {
updateCaseReviewByRecoverFunctionalCase(event);
}
default -> LogUtils.info("CaseEventListener: " + event.module() + "" + event.message());
}
}
/**
* 功能用例的回收站恢复/批量恢复重新计算用例评审的通过率和用例数
*/
private void updateCaseReviewByRecoverFunctionalCase(Event event) {
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = getCaseReviewFunctionalCases(event);
Map<String, List<CaseReviewFunctionalCase>> reviewIdMap = caseReviewFunctionalCases.stream().collect(Collectors.groupingBy(CaseReviewFunctionalCase::getReviewId));
reviewIdMap.forEach((reviewId, caseReviewFunctionalCaseList) -> {
CaseReview caseReview = caseReviewMapper.selectByPrimaryKey(reviewId);
List<CaseReviewFunctionalCase> passList = caseReviewFunctionalCases.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getStatus(), FunctionalCaseReviewStatus.PASS.toString())).toList();
updateCaseReview(reviewId, caseReview.getCaseCount() + caseReviewFunctionalCaseList.size(), passList.size());
});
}
/**
* 功能用例的回收站删除/批量删除重新计算用例评审的通过率和用例数
*/
private void updateCaseReviewByDeleteTrashFunctionalCase(Event event) {
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = getCaseReviewFunctionalCases(event);
if (CollectionUtils.isEmpty(caseReviewFunctionalCases)) {
return;
}
Map<String, List<CaseReviewFunctionalCase>> reviewIdMap = caseReviewFunctionalCases.stream().collect(Collectors.groupingBy(CaseReviewFunctionalCase::getReviewId));
reviewIdMap.forEach((reviewId, caseReviewFunctionalCaseList) -> {
CaseReview caseReview = caseReviewMapper.selectByPrimaryKey(reviewId);
List<CaseReviewFunctionalCase> passList = caseReviewFunctionalCases.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getStatus(), FunctionalCaseReviewStatus.PASS.toString())).toList();
updateCaseReview(reviewId, caseReview.getCaseCount() - caseReviewFunctionalCaseList.size(), passList.size());
});
}
/**
* 功能用例的删除/批量删除重新计算用例评审的通过率和用例数
*/
private void updateCaseReviewByDeleteFunctionalCase(Event event) {
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = getCaseReviewFunctionalCases(event);
if (CollectionUtils.isEmpty(caseReviewFunctionalCases)) {
return;
}
Map<String, List<CaseReviewFunctionalCase>> reviewIdMap = caseReviewFunctionalCases.stream().collect(Collectors.groupingBy(CaseReviewFunctionalCase::getReviewId));
reviewIdMap.forEach((reviewId, caseReviewFunctionalCaseList) -> {
CaseReview caseReview = caseReviewMapper.selectByPrimaryKey(reviewId);
List<CaseReviewFunctionalCase> passList = caseReviewFunctionalCases.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getStatus(), FunctionalCaseReviewStatus.PASS.toString())).toList();
updateCaseReview(reviewId, caseReview.getCaseCount() - caseReviewFunctionalCaseList.size(), passList.size());
List<String> caseIdList = caseReviewFunctionalCaseList.stream().map(CaseReviewFunctionalCase::getId).toList();
deleteReviewFunctionalCaseUser(caseIdList, reviewId);
});
}
private List<CaseReviewFunctionalCase> getCaseReviewFunctionalCases(Event event) {
Map<String, Object> paramMap = event.paramMap();
Object caseIds = paramMap.get(CaseEvent.Param.CASE_IDS);
List<String> caseIdList = JSON.parseArray(JSON.toJSONString(caseIds), String.class);
CaseReviewFunctionalCaseExample functionalCaseExample = new CaseReviewFunctionalCaseExample();
functionalCaseExample.createCriteria().andCaseIdIn(caseIdList);
return caseReviewFunctionalCaseMapper.selectByExample(functionalCaseExample);
}
/**
* 1.批量取消关联重新计算用例评审的通过率和用例数
* 2.删除用例和用例评审人的关系
*/
private void updateCaseReviewByBatchDisassociate(Event event) {
Map<String, Object> paramMap = event.paramMap();
String reviewId = paramMap.get(CaseEvent.Param.REVIEW_ID).toString();
CaseReview caseReview = caseReviewMapper.selectByPrimaryKey(reviewId);
Integer oldCaseCount = caseReview.getCaseCount();
Object caseIds = paramMap.get(CaseEvent.Param.CASE_IDS);
List<String> caseIdList = JSON.parseArray(JSON.toJSONString(caseIds), String.class);
int passNumber = Integer.parseInt(paramMap.get(CaseEvent.Param.PASS_COUNT).toString());
updateCaseReview(reviewId, oldCaseCount - caseIdList.size(), passNumber);
//删除用例和用例评审人的关系
deleteCaseReviewFunctionalCaseUser(event);
}
/**
* 1.单独取消关联重新计算用例评审的通过率和用例数
* 2.删除用例和用例评审人的关系
*/
private void updateCaseReviewByDisAssociate(Event event) {
updateCaseReviewByAssociate(event);
//删除用例和用例评审人的关系
deleteCaseReviewFunctionalCaseUser(event);
}
/**
* 删除用例和用例评审人的关系
*/
private void deleteCaseReviewFunctionalCaseUser(Event event) {
Map<String, Object> paramMap = event.paramMap();
Object caseIds = paramMap.get(CaseEvent.Param.CASE_IDS);
List<String> caseIdList = JSON.parseArray(JSON.toJSONString(caseIds), String.class);
String reviewId = paramMap.get(CaseEvent.Param.REVIEW_ID).toString();
deleteReviewFunctionalCaseUser(caseIdList, reviewId);
}
private void deleteReviewFunctionalCaseUser(List<String> caseIdList, String reviewId) {
CaseReviewFunctionalCaseUserExample caseReviewFunctionalCaseUserExample = new CaseReviewFunctionalCaseUserExample();
caseReviewFunctionalCaseUserExample.createCriteria().andCaseIdIn(caseIdList).andReviewIdEqualTo(reviewId);
caseReviewFunctionalCaseUserMapper.deleteByExample(caseReviewFunctionalCaseUserExample);
}
/**
* 关联用例单独/批量重新计算用例评审的通过率和用例数
*/
private void updateCaseReviewByAssociate(Event event) {
Map<String, Object> paramMap = event.paramMap();
String reviewId = paramMap.get(CaseEvent.Param.REVIEW_ID).toString();
int caseCount = Integer.parseInt(paramMap.get(CaseEvent.Param.CASE_COUNT).toString());
int passNumber = Integer.parseInt(paramMap.get(CaseEvent.Param.PASS_COUNT).toString());
updateCaseReview(reviewId, caseCount, passNumber);
}
/**
* 重新计算用例评审的通过率和用例数
*/
private void updateCaseReview(String reviewId, int caseCount, int passNumber) {
CaseReview caseReview = new CaseReview();
caseReview.setId(reviewId);
//更新用例数量
caseReview.setCaseCount(caseCount);
//通过率
BigDecimal passCount = BigDecimal.valueOf(passNumber);
BigDecimal totalCount = BigDecimal.valueOf(caseReview.getCaseCount());
if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
caseReview.setPassRate(BigDecimal.ZERO);
} else {
BigDecimal passRate = passCount.divide(totalCount, 2, RoundingMode.HALF_UP);
caseReview.setPassRate(passRate);
}
caseReviewMapper.updateByPrimaryKeySelective(caseReview);
}
}

View File

@ -21,6 +21,8 @@ public interface ExtCaseReviewFunctionalCaseMapper {
Long getUnCompletedCaseCount(@Param("reviewId") String reviewId, @Param("statusList") List<String> statusList);
Long getUnCompletedCaseCountExcludes(@Param("reviewId") String reviewId, @Param("statusList") List<String> statusList, @Param("ids") List<String> ids);
List<String> getCaseIdsByReviewId(@Param("reviewId") String reviewId);
List<ReviewFunctionalCaseDTO> page(@Param("request") ReviewFunctionalCasePageRequest request, @Param("deleted") boolean deleted, @Param("userId") String userId, @Param("sort") String sort);
@ -33,5 +35,13 @@ public interface ExtCaseReviewFunctionalCaseMapper {
List<String> getIds(@Param("request") BaseReviewCaseBatchRequest request, @Param("userId") String userId, @Param("deleted") boolean deleted);
List<CaseReviewFunctionalCase> getListByRequest(@Param("request") BaseReviewCaseBatchRequest request, @Param("userId") String userId, @Param("deleted") boolean deleted);
List<CaseReviewFunctionalCase> getList(@Param("reviewId") String reviewId, @Param("reviewIds") List<String> reviewIds, @Param("deleted") boolean deleted);
List<CaseReviewFunctionalCase> getListIncludes(@Param("reviewId") String reviewId, @Param("caseIds") List<String> caseIds, @Param("deleted") boolean deleted);
List<CaseReviewFunctionalCase> getListExcludes(@Param("reviewIds")List<String> reviewIds, @Param("caseIds") List<String> caseIds, @Param("deleted") boolean deleted);
}

View File

@ -28,6 +28,22 @@
</foreach>
</select>
<select id="getUnCompletedCaseCountExcludes" resultType="java.lang.Long">
SELECT
count(1)
FROM
case_review_functional_case
where review_id = #{reviewId}
and status in
<foreach collection="statusList" item="status" open="(" separator="," close=")">
#{status}
</foreach>
and id not in
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<update id="updateStatus">
update case_review_functional_case
set status = #{status},
@ -223,8 +239,6 @@
</choose>
</sql>
<select id="getIds" resultType="java.lang.String">
SELECT
crfc.id as id
@ -249,6 +263,36 @@
</choose>
</select>
<select id="getListByRequest" resultType="io.metersphere.functional.domain.CaseReviewFunctionalCase">
SELECT
crfc.*
FROM
case_review_functional_case crfc
LEFT JOIN functional_case ON crfc.case_id = functional_case.id
WHERE
review_id = #{request.reviewId}
AND functional_case.deleted = #{deleted}
<if test="userId != null and userId != ''">
AND crfc.case_id in (select case_id from case_review_functional_case_user crfcu where crfcu.review_id = #{request.reviewId} and crfcu.user_id = #{userId})
</if>
<choose>
<when test='request.condition.searchMode == "AND"'>
AND <include refid="queryWhereConditionByBaseQueryRequest"/>
</when>
<when test='request.condition.searchMode == "OR"'>
and (
<include refid="queryWhereConditionByBaseQueryRequest"/>
)
</when>
</choose>
<if test="request.excludeIds != null and request.excludeIds.size() > 0" >
and crfc.id not in
<foreach collection="request.excludeIds" item="excludeId" open="(" separator="," close=")">
#{excludeId}
</foreach>
</if>
</select>
<sql id="queryWhereConditionByBaseQueryRequest">
<if test="request.condition.keyword != null">
@ -305,6 +349,47 @@
</if>
</select>
<select id="getListIncludes" resultType="io.metersphere.functional.domain.CaseReviewFunctionalCase">
SELECT
*
FROM
case_review_functional_case crfc
LEFT JOIN functional_case fc ON crfc.case_id = fc.id
WHERE
fc.deleted = #{deleted}
<if test="reviewId != null and reviewId != ''">
and crfc.review_id = #{reviewId}
</if>
<if test="caseIds != null and caseIds.size() > 0">
and fc.id in
<foreach collection="caseIds" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</if>
</select>
<select id="getListExcludes" resultType="io.metersphere.functional.domain.CaseReviewFunctionalCase">
SELECT
*
FROM
case_review_functional_case crfc
LEFT JOIN functional_case fc ON crfc.case_id = fc.id
WHERE
fc.deleted = #{deleted}
<if test="reviewIds != null and reviewIds.size() > 0">
and crfc.review_id in
<foreach collection="reviewIds" item="reviewId" separator="," open="(" close=")">
#{reviewId}
</foreach>
</if>
<if test="caseIds != null and caseIds.size() > 0">
and fc.id not in
<foreach collection="caseIds" item="caseId" separator="," open="(" close=")">
#{caseId}
</foreach>
</if>
</select>
<select id="getPrePos" resultType="java.lang.Long">
select `pos` from case_review_functional_case where review_id = #{reviewId}
<if test="basePos != null">

View File

@ -0,0 +1,311 @@
package io.metersphere.functional.provider;
import io.metersphere.functional.constants.CaseEvent;
import io.metersphere.functional.constants.CaseReviewStatus;
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
import io.metersphere.functional.domain.*;
import io.metersphere.functional.mapper.CaseReviewFunctionalCaseMapper;
import io.metersphere.functional.mapper.CaseReviewFunctionalCaseUserMapper;
import io.metersphere.functional.mapper.CaseReviewMapper;
import io.metersphere.functional.mapper.ExtCaseReviewFunctionalCaseMapper;
import io.metersphere.functional.service.ReviewSendNoticeService;
import io.metersphere.provider.BaseCaseProvider;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.notice.constants.NoticeConstants;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class CaseReviewCaseProvider implements BaseCaseProvider {
@Resource
private CaseReviewMapper caseReviewMapper;
@Resource
private CaseReviewFunctionalCaseUserMapper caseReviewFunctionalCaseUserMapper;
@Resource
private CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper;
@Resource
private ReviewSendNoticeService reviewSendNoticeService;
@Resource
private ExtCaseReviewFunctionalCaseMapper extCaseReviewFunctionalCaseMapper;
@Async
@Override
public void updateCaseReview(Map<String, Object> paramMap) {
String event = paramMap.get(CaseEvent.Param.EVENT_NAME).toString();
switch (event) {
case CaseEvent.Event.ASSOCIATE -> updateCaseReviewByAssociate(paramMap);
case CaseEvent.Event.DISASSOCIATE -> updateCaseReviewByDisAssociate(paramMap);
case CaseEvent.Event.BATCH_DISASSOCIATE -> updateCaseReviewByBatchDisassociate(paramMap);
case CaseEvent.Event.DELETE_FUNCTIONAL_CASE -> updateCaseReviewByDeleteFunctionalCase(paramMap);
case CaseEvent.Event.DELETE_TRASH_FUNCTIONAL_CASE -> updateCaseReviewByDeleteTrashFunctionalCase(paramMap);
case CaseEvent.Event.RECOVER_FUNCTIONAL_CASE -> updateCaseReviewByRecoverFunctionalCase(paramMap);
case CaseEvent.Event.REVIEW_FUNCTIONAL_CASE -> updateCaseReviewByReviewFunctionalCase(paramMap);
default -> LogUtils.info("CaseProvider: " + event);
}
}
/**
* 1.关联用例单独/批量重新计算用例评审的通过率和用例数
*/
private void updateCaseReviewByAssociate(Map<String, Object> paramMap) {
String reviewId = paramMap.get(CaseEvent.Param.REVIEW_ID).toString();
Object caseIds = paramMap.get(CaseEvent.Param.CASE_IDS);
List<String> caseIdList = JSON.parseArray(JSON.toJSONString(caseIds), String.class);
//获取关联前的caseIds
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = extCaseReviewFunctionalCaseMapper.getListIncludes(reviewId, caseIdList, false);
List<CaseReviewFunctionalCase> passList = caseReviewFunctionalCases.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getStatus(), FunctionalCaseReviewStatus.PASS.toString())).toList();
int caseCount = Integer.parseInt(paramMap.get(CaseEvent.Param.CASE_COUNT).toString()) + caseReviewFunctionalCases.size();
int passNumber = passList.size();
List<CaseReviewFunctionalCase> unCompletedCaseList = getUnCompletedCaseList(caseReviewFunctionalCases, new ArrayList<>());
updateCaseReview(reviewId, caseCount, passNumber, unCompletedCaseList.size()+Integer.parseInt(paramMap.get(CaseEvent.Param.CASE_COUNT).toString()), paramMap.get(CaseEvent.Param.USER_ID).toString());
}
/**
* 2.
* 1.单独取消关联重新计算用例评审的通过率和用例数
* 2.删除用例和用例评审人的关系
*/
private void updateCaseReviewByDisAssociate(Map<String, Object> paramMap) {
String reviewId = paramMap.get(CaseEvent.Param.REVIEW_ID).toString();
CaseReview caseReview = caseReviewMapper.selectByPrimaryKey(reviewId);
if (caseReview == null) {
return;
}
Object caseIds = paramMap.get(CaseEvent.Param.CASE_IDS);
List<String> caseIdList = JSON.parseArray(JSON.toJSONString(caseIds), String.class);
//获取与选中case无关的其他case
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = extCaseReviewFunctionalCaseMapper.getListIncludes(reviewId, caseIdList, false);
List<CaseReviewFunctionalCase> passList = caseReviewFunctionalCases.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getStatus(), FunctionalCaseReviewStatus.PASS.toString())).toList();
int caseCount = caseReviewFunctionalCases.size()- caseIdList.size();
int passNumber = passList.size();
List<CaseReviewFunctionalCase> unCompletedCaseList = getUnCompletedCaseList(caseReviewFunctionalCases, new ArrayList<>());
updateCaseReview(reviewId, caseReview.getCaseCount() - caseCount, passNumber, unCompletedCaseList.size(), paramMap.get(CaseEvent.Param.USER_ID).toString());
//删除用例和用例评审人的关系
deleteCaseReviewFunctionalCaseUser(paramMap);
}
/**
* 3.
* 1.批量取消关联重新计算用例评审的通过率和用例数
* 2.删除用例和用例评审人的关系
*/
private void updateCaseReviewByBatchDisassociate(Map<String, Object> paramMap) {
String reviewId = paramMap.get(CaseEvent.Param.REVIEW_ID).toString();
CaseReview caseReviewOld = caseReviewMapper.selectByPrimaryKey(reviewId);
Integer oldCaseCount = caseReviewOld.getCaseCount();
Object caseIds = paramMap.get(CaseEvent.Param.CASE_IDS);
List<String> caseIdList = JSON.parseArray(JSON.toJSONString(caseIds), String.class);
if (CollectionUtils.isEmpty(caseIdList)) {
return;
}
int passNumber = Integer.parseInt(paramMap.get(CaseEvent.Param.PASS_COUNT).toString());
int unCompletedCount = Integer.parseInt(paramMap.get(CaseEvent.Param.UN_COMPLETED_COUNT).toString());
updateCaseReview(reviewId, oldCaseCount - caseIdList.size(), passNumber, unCompletedCount, paramMap.get(CaseEvent.Param.USER_ID).toString());
//删除用例和用例评审人的关系
deleteCaseReviewFunctionalCaseUser(paramMap);
}
/**
* 4.功能用例的删除/批量删除重新计算用例评审的通过率和用例数
*/
private void updateCaseReviewByDeleteFunctionalCase(Map<String, Object> paramMap) {
Object caseIds = paramMap.get(CaseEvent.Param.CASE_IDS);
List<String> caseIdList = JSON.parseArray(JSON.toJSONString(caseIds), String.class);
startUpdateCaseReview(paramMap, caseIdList);
}
/**
* 5.功能用例的回收站删除/批量删除重新计算用例评审的通过率和用例数
*/
private void updateCaseReviewByDeleteTrashFunctionalCase(Map<String, Object> paramMap) {
Object caseIds = paramMap.get(CaseEvent.Param.CASE_IDS);
List<String> caseIdList = JSON.parseArray(JSON.toJSONString(caseIds), String.class);
if (startUpdateCaseReview(paramMap, caseIdList)) return;
CaseReviewFunctionalCaseUserExample caseReviewFunctionalCaseUserExample = new CaseReviewFunctionalCaseUserExample();
caseReviewFunctionalCaseUserExample.createCriteria().andCaseIdIn(caseIdList);
caseReviewFunctionalCaseUserMapper.deleteByExample(caseReviewFunctionalCaseUserExample);
//从回收站删除也删除关联关系
CaseReviewFunctionalCaseExample caseReviewFunctionalCaseExample = new CaseReviewFunctionalCaseExample();
caseReviewFunctionalCaseExample.createCriteria().andCaseIdIn(caseIdList);
caseReviewFunctionalCaseMapper.deleteByExample(caseReviewFunctionalCaseExample);
}
/**
* 6.功能用例的回收站恢复/批量恢复重新计算用例评审的通过率和用例数
*/
private void updateCaseReviewByRecoverFunctionalCase(Map<String, Object> paramMap) {
Object caseIds = paramMap.get(CaseEvent.Param.CASE_IDS);
List<String> caseIdList = JSON.parseArray(JSON.toJSONString(caseIds), String.class);
CaseReviewFunctionalCaseExample functionalCaseExample = new CaseReviewFunctionalCaseExample();
functionalCaseExample.createCriteria().andCaseIdIn(caseIdList);
List<CaseReviewFunctionalCase> recoverCases = caseReviewFunctionalCaseMapper.selectByExample(functionalCaseExample);
if (CollectionUtils.isEmpty(recoverCases)) {
return;
}
List<String> reviewIds = recoverCases.stream().map(CaseReviewFunctionalCase::getReviewId).distinct().toList();
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = extCaseReviewFunctionalCaseMapper.getListExcludes(reviewIds, caseIdList, false);
Map<String, List<CaseReviewFunctionalCase>> recoverCaseMap = recoverCases.stream().collect(Collectors.groupingBy(CaseReviewFunctionalCase::getReviewId));
Map<String, List<CaseReviewFunctionalCase>> reviewIdMap = caseReviewFunctionalCases.stream().collect(Collectors.groupingBy(CaseReviewFunctionalCase::getReviewId));
CaseReviewExample caseReviewExample = new CaseReviewExample();
caseReviewExample.createCriteria().andIdIn(reviewIds);
List<CaseReview> caseReviews = caseReviewMapper.selectByExample(caseReviewExample);
Map<String, CaseReview> reviewMap = caseReviews.stream().collect(Collectors.toMap(CaseReview::getId, t -> t));
reviewIdMap.forEach((reviewId, caseReviewFunctionalCaseList) -> {
CaseReview caseReview = reviewMap.get(reviewId);
List<CaseReviewFunctionalCase> recoverCaseList = recoverCaseMap.get(reviewId);
caseReviewFunctionalCaseList.addAll(recoverCaseList);
List<String> ids = caseReviewFunctionalCaseList.stream().map(CaseReviewFunctionalCase::getId).toList();
List<CaseReviewFunctionalCase> unCompleteList = getUnCompletedCaseList(caseReviewFunctionalCaseList, ids);
List<CaseReviewFunctionalCase> passList = caseReviewFunctionalCaseList.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getStatus(), FunctionalCaseReviewStatus.PASS.toString())).toList();
updateCaseReview(reviewId, caseReview.getCaseCount() + caseReviewFunctionalCaseList.size(), passList.size(), unCompleteList.size(), paramMap.get(CaseEvent.Param.USER_ID).toString());
});
}
/**
* 7.评审用例/批量评审用例重新计算用例评审的通过率和用例评审状态和发送通知
*/
private void updateCaseReviewByReviewFunctionalCase(Map<String, Object> paramMap) {
String reviewId = paramMap.get(CaseEvent.Param.REVIEW_ID).toString();
Object caseIds = paramMap.get(CaseEvent.Param.CASE_IDS);
List<String> caseIdList = JSON.parseArray(JSON.toJSONString(caseIds), String.class);
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = extCaseReviewFunctionalCaseMapper.getListExcludes(List.of(reviewId), caseIdList, false);
List<CaseReviewFunctionalCase> unCompletedCaseList = getUnCompletedCaseList(caseReviewFunctionalCases, new ArrayList<>());
List<CaseReviewFunctionalCase> passList = caseReviewFunctionalCases.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getStatus(), FunctionalCaseReviewStatus.PASS.toString())).toList();
CaseReview caseReview = caseReviewMapper.selectByPrimaryKey(reviewId);
boolean completed = false;
String status = paramMap.get(CaseEvent.Param.STATUS).toString();
List<String> completedStatusList = new ArrayList<>();
completedStatusList.add(FunctionalCaseReviewStatus.PASS.toString());
completedStatusList.add(FunctionalCaseReviewStatus.UN_PASS.toString());
if (!completedStatusList.contains(status) || CollectionUtils.isNotEmpty(unCompletedCaseList)) {
caseReview.setStatus(CaseReviewStatus.UNDERWAY.toString());
} else {
completed = true;
caseReview.setStatus(CaseReviewStatus.COMPLETED.toString());
}
int passNumber = passList.size();
if (StringUtils.equalsIgnoreCase(status, FunctionalCaseReviewStatus.PASS.toString())) {
passNumber += caseIdList.size();
}
//通过率
BigDecimal passCount = BigDecimal.valueOf(passNumber);
BigDecimal totalCount = BigDecimal.valueOf(caseReview.getCaseCount());
if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
caseReview.setPassRate(BigDecimal.ZERO);
} else {
BigDecimal passRate = passCount.divide(totalCount, 2, RoundingMode.HALF_UP);
caseReview.setPassRate(passRate);
}
caseReviewMapper.updateByPrimaryKeySelective(caseReview);
if (completed) {
reviewSendNoticeService.sendNotice(new ArrayList<>(), paramMap.get(CaseEvent.Param.USER_ID).toString(), reviewId, NoticeConstants.TaskType.CASE_REVIEW_TASK, NoticeConstants.Event.REVIEW_COMPLETED);
}
}
/**
* 准备更新caseReview
*/
private boolean startUpdateCaseReview(Map<String, Object> paramMap, List<String> caseIdList) {
CaseReviewFunctionalCaseExample functionalCaseExample = new CaseReviewFunctionalCaseExample();
functionalCaseExample.createCriteria().andCaseIdIn(caseIdList);
List<CaseReviewFunctionalCase> caseReviewFunctionalReviews = caseReviewFunctionalCaseMapper.selectByExample(functionalCaseExample);
if (CollectionUtils.isEmpty(caseReviewFunctionalReviews)) {
return true;
}
Map<String, List<CaseReviewFunctionalCase>> caseReviewMap = caseReviewFunctionalReviews.stream().collect(Collectors.groupingBy(CaseReviewFunctionalCase::getReviewId));
List<String> reviewIds = caseReviewFunctionalReviews.stream().map(CaseReviewFunctionalCase::getReviewId).distinct().toList();
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = extCaseReviewFunctionalCaseMapper.getListExcludes(reviewIds, caseIdList, false);
Map<String, List<CaseReviewFunctionalCase>> reviewIdMap = caseReviewFunctionalCases.stream().collect(Collectors.groupingBy(CaseReviewFunctionalCase::getReviewId));
CaseReviewExample caseReviewExample = new CaseReviewExample();
caseReviewExample.createCriteria().andIdIn(reviewIds);
List<CaseReview> caseReviews = caseReviewMapper.selectByExample(caseReviewExample);
Map<String, CaseReview> reviewMap = caseReviews.stream().collect(Collectors.toMap(CaseReview::getId, t -> t));
reviewIdMap.forEach((reviewId, caseReviewFunctionalCaseList) -> {
List<String> ids = caseReviewFunctionalCaseList.stream().map(CaseReviewFunctionalCase::getId).toList();
CaseReview caseReview = reviewMap.get(reviewId);
List<CaseReviewFunctionalCase> caseReviewFunctionalCases1 = caseReviewMap.get(reviewId);
List<CaseReviewFunctionalCase> unCompleteList = getUnCompletedCaseList(caseReviewFunctionalCaseList, ids);
List<CaseReviewFunctionalCase> passList = caseReviewFunctionalCaseList.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getStatus(), FunctionalCaseReviewStatus.PASS.toString())).toList();
updateCaseReview(reviewId, caseReview.getCaseCount() - caseReviewFunctionalCases1.size(), passList.size(), unCompleteList.size(), paramMap.get(CaseEvent.Param.USER_ID).toString());
});
return false;
}
/**
* 获取未评审完成的用例
*/
private static List<CaseReviewFunctionalCase> getUnCompletedCaseList(List<CaseReviewFunctionalCase> caseReviewFunctionalCases, List<String> ids) {
List<String> statusList = new ArrayList<>();
statusList.add(FunctionalCaseReviewStatus.UN_REVIEWED.toString());
statusList.add(FunctionalCaseReviewStatus.UNDER_REVIEWED.toString());
statusList.add(FunctionalCaseReviewStatus.RE_REVIEWED.toString());
if (CollectionUtils.isNotEmpty(ids)) {
return caseReviewFunctionalCases.stream().filter(t -> statusList.contains(t.getStatus()) && !ids.contains(t.getId())).toList();
} else {
return caseReviewFunctionalCases.stream().filter(t -> statusList.contains(t.getStatus())).toList();
}
}
/**
* 重新计算用例评审的通过率和用例数
*/
private void updateCaseReview(String reviewId, int caseCount, int passNumber, int unCompleteCount, String userId) {
CaseReview caseReview = new CaseReview();
caseReview.setId(reviewId);
//更新用例数量
caseReview.setCaseCount(caseCount);
//通过率
BigDecimal passCount = BigDecimal.valueOf(passNumber);
BigDecimal totalCount = BigDecimal.valueOf(caseReview.getCaseCount());
if (totalCount.compareTo(BigDecimal.ZERO) == 0) {
caseReview.setPassRate(BigDecimal.ZERO);
} else {
BigDecimal passRate = passCount.divide(totalCount, 2, RoundingMode.HALF_UP);
caseReview.setPassRate(passRate);
}
boolean completed = false;
if (unCompleteCount > 0) {
caseReview.setStatus(CaseReviewStatus.UNDERWAY.toString());
} else {
completed = true;
caseReview.setStatus(CaseReviewStatus.COMPLETED.toString());
}
caseReviewMapper.updateByPrimaryKeySelective(caseReview);
if (completed) {
reviewSendNoticeService.sendNotice(new ArrayList<>(), userId, reviewId, NoticeConstants.TaskType.CASE_REVIEW_TASK, NoticeConstants.Event.REVIEW_COMPLETED);
}
}
/**
* 删除用例和用例评审人的关系
*/
private void deleteCaseReviewFunctionalCaseUser(Map<String, Object> paramMap) {
Object caseIds = paramMap.get(CaseEvent.Param.CASE_IDS);
List<String> caseIdList = JSON.parseArray(JSON.toJSONString(caseIds), String.class);
String reviewId = paramMap.get(CaseEvent.Param.REVIEW_ID).toString();
CaseReviewFunctionalCaseUserExample caseReviewFunctionalCaseUserExample = new CaseReviewFunctionalCaseUserExample();
caseReviewFunctionalCaseUserExample.createCriteria().andCaseIdIn(caseIdList).andReviewIdEqualTo(reviewId);
caseReviewFunctionalCaseUserMapper.deleteByExample(caseReviewFunctionalCaseUserExample);
}
}

View File

@ -0,0 +1,24 @@
package io.metersphere.functional.request;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
@Data
public class BatchReviewFunctionalCaseRequest extends BaseReviewCaseBatchRequest{
@Schema(description = "评审规则")
@NotBlank(message = "{case_review.review_pass_rule.not_blank}")
private String reviewPassRule;
@Schema(description = "评审结果")
@NotBlank(message = "{functional_case.status.not_blank}")
private String status;
@Schema(description = "评论内容")
private String content;
@Schema(description = "评论@的人的Id, 多个以';'隔开")
private String notifier;
}

View File

@ -27,7 +27,7 @@ public class ReviewFunctionalCaseRequest {
@NotBlank(message = "{functional_case.status.not_blank}")
private String status;
@Schema(description = "审规则")
@Schema(description = "论内容")
private String content;
@Schema(description = "评论@的人的Id, 多个以';'隔开")

View File

@ -2,36 +2,39 @@ package io.metersphere.functional.service;
import io.metersphere.functional.constants.CaseEvent;
import io.metersphere.functional.constants.CaseReviewPassRule;
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
import io.metersphere.functional.domain.*;
import io.metersphere.functional.dto.ReviewFunctionalCaseDTO;
import io.metersphere.functional.dto.ReviewsDTO;
import io.metersphere.functional.mapper.*;
import io.metersphere.functional.request.BaseReviewCaseBatchRequest;
import io.metersphere.functional.request.CaseReviewFunctionalCasePosRequest;
import io.metersphere.functional.request.FunctionalCaseEditRequest;
import io.metersphere.functional.request.ReviewFunctionalCasePageRequest;
import io.metersphere.functional.utils.CaseListenerUtils;
import io.metersphere.functional.request.*;
import io.metersphere.project.domain.ProjectApplication;
import io.metersphere.project.domain.ProjectApplicationExample;
import io.metersphere.project.domain.ProjectVersion;
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.mapper.ProjectApplicationMapper;
import io.metersphere.provider.BaseCaseProvider;
import io.metersphere.sdk.constants.ProjectApplicationType;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.notice.constants.NoticeConstants;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
@ -62,6 +65,15 @@ public class CaseReviewFunctionalCaseService {
private CaseReviewHistoryMapper caseReviewHistoryMapper;
@Resource
private FunctionalCaseMapper functionalCaseMapper;
@Resource
private SqlSessionFactory sqlSessionFactory;
@Resource
private CaseReviewFunctionalCaseUserMapper caseReviewFunctionalCaseUserMapper;
@Resource
private BaseCaseProvider provider;
@Resource
private ReviewSendNoticeService reviewSendNoticeService;
/**
* 通过评审id获取关联的用例id集合
@ -73,7 +85,6 @@ public class CaseReviewFunctionalCaseService {
return extCaseReviewFunctionalCaseMapper.getCaseIdsByReviewId(reviewId);
}
/**
* 评审详情分页列表查询
*
@ -115,25 +126,33 @@ public class CaseReviewFunctionalCaseService {
*
* @param request request
*/
public void disassociate(BaseReviewCaseBatchRequest request) {
public void disassociate(BaseReviewCaseBatchRequest request, String userId) {
List<String> ids = doSelectIds(request);
if (CollectionUtils.isNotEmpty(ids)) {
CaseReviewFunctionalCaseExample example = new CaseReviewFunctionalCaseExample();
example.createCriteria().andIdIn(ids);
Map<String, Object> param = getParam(request.getReviewId(), example, ids);
CaseListenerUtils.addListener(param, CaseEvent.Event.BATCH_DISASSOCIATE);
Map<String, Object> param = getParam(request.getReviewId(), ids);
param.put(CaseEvent.Param.USER_ID, userId);
param.put(CaseEvent.Param.EVENT_NAME, CaseEvent.Event.BATCH_DISASSOCIATE);
provider.updateCaseReview(param);
caseReviewFunctionalCaseMapper.deleteByExample(example);
}
}
private Map<String, Object> getParam(String reviewId, CaseReviewFunctionalCaseExample example, List<String> ids) {
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = caseReviewFunctionalCaseMapper.selectByExample(example);
List<String> caseIds = caseReviewFunctionalCases.stream().map(CaseReviewFunctionalCase::getCaseId).toList();
private Map<String, Object> getParam(String reviewId, List<String> ids) {
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = extCaseReviewFunctionalCaseMapper.getList(reviewId, null, false);
List<CaseReviewFunctionalCase> passList = caseReviewFunctionalCases.stream().filter(t -> !ids.contains(t.getId()) && StringUtils.equalsIgnoreCase(t.getStatus(), FunctionalCaseReviewStatus.PASS.toString())).toList();
List<String> statusList = new ArrayList<>();
statusList.add(FunctionalCaseReviewStatus.UN_REVIEWED.toString());
statusList.add(FunctionalCaseReviewStatus.UNDER_REVIEWED.toString());
statusList.add(FunctionalCaseReviewStatus.RE_REVIEWED.toString());
List<CaseReviewFunctionalCase> unCompletedCaseList = caseReviewFunctionalCases.stream().filter(t -> !ids.contains(t.getId()) && statusList.contains(t.getStatus())).toList();
Map<String, Object> param = new HashMap<>();
param.put(CaseEvent.Param.CASE_IDS, caseIds);
param.put(CaseEvent.Param.CASE_COUNT, ids.size());
param.put(CaseEvent.Param.REVIEW_ID, reviewId);
param.put(CaseEvent.Param.PASS_COUNT, passList.size());
param.put(CaseEvent.Param.UN_COMPLETED_COUNT, unCompletedCaseList.size());
return param;
}
@ -149,6 +168,16 @@ public class CaseReviewFunctionalCaseService {
}
}
public List<CaseReviewFunctionalCase> doCaseReviewFunctionalCases(BaseReviewCaseBatchRequest request) {
if (request.isSelectAll()) {
return extCaseReviewFunctionalCaseMapper.getListByRequest(request, request.getUserId(), false);
} else {
CaseReviewFunctionalCaseExample caseReviewFunctionalCaseExample = new CaseReviewFunctionalCaseExample();
caseReviewFunctionalCaseExample.createCriteria().andIdIn(request.getSelectIds());
return caseReviewFunctionalCaseMapper.selectByExample(caseReviewFunctionalCaseExample);
}
}
/**
* 评审详情页面 创建用例并关联
@ -174,7 +203,6 @@ public class CaseReviewFunctionalCaseService {
/**
* 用例更新 更新状态为重新评审
*
*/
public void reReviewedCase(FunctionalCaseEditRequest request, FunctionalCaseBlob blob, String name) {
ProjectApplicationExample example = new ProjectApplicationExample();
@ -188,8 +216,6 @@ public class CaseReviewFunctionalCaseService {
doHandleStatusAndHistory(request, blob, name);
}
}
}
private void doHandleStatusAndHistory(FunctionalCaseEditRequest request, FunctionalCaseBlob blob, String name) {
@ -202,8 +228,6 @@ public class CaseReviewFunctionalCaseService {
insertHistory(item);
});
}
}
private void insertHistory(CaseReviewFunctionalCase item) {
@ -214,6 +238,7 @@ public class CaseReviewFunctionalCaseService {
caseReviewHistory.setStatus(FunctionalCaseReviewStatus.RE_REVIEWED.name());
caseReviewHistory.setCreateUser("system");
caseReviewHistory.setCreateTime(System.currentTimeMillis());
caseReviewHistory.setDeleted(false);
caseReviewHistoryMapper.insertSelective(caseReviewHistory);
}
@ -239,4 +264,118 @@ public class CaseReviewFunctionalCaseService {
extCaseReviewFunctionalCaseMapper::getLastPos,
caseReviewFunctionalCaseMapper::updateByPrimaryKeySelective);
}
/**
* 批量评审
*/
public void batchReview(BatchReviewFunctionalCaseRequest request, String userId) {
String reviewId = request.getReviewId();
List<CaseReviewFunctionalCase> caseReviewFunctionalCaseList = doCaseReviewFunctionalCases(request);
List<String> caseIds = caseReviewFunctionalCaseList.stream().map(CaseReviewFunctionalCase::getCaseId).toList();
CaseReviewHistoryExample caseReviewHistoryExample = new CaseReviewHistoryExample();
caseReviewHistoryExample.createCriteria().andCaseIdIn(caseIds).andReviewIdEqualTo(reviewId);
List<CaseReviewHistory> caseReviewHistories = caseReviewHistoryMapper.selectByExample(caseReviewHistoryExample);
Map<String, List<CaseReviewHistory>> caseHistoryMap = caseReviewHistories.stream().collect(Collectors.groupingBy(CaseReviewHistory::getCaseId, Collectors.toList()));
CaseReviewFunctionalCaseUserExample caseReviewFunctionalCaseUserExample = new CaseReviewFunctionalCaseUserExample();
caseReviewFunctionalCaseUserExample.createCriteria().andReviewIdEqualTo(reviewId).andCaseIdIn(caseIds);
List<CaseReviewFunctionalCaseUser> caseReviewFunctionalCaseUsers = caseReviewFunctionalCaseUserMapper.selectByExample(caseReviewFunctionalCaseUserExample);
Map<String, List<CaseReviewFunctionalCaseUser>> reviewerMap = caseReviewFunctionalCaseUsers.stream().collect(Collectors.groupingBy(CaseReviewFunctionalCaseUser::getCaseId, Collectors.toList()));
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
CaseReviewHistoryMapper caseReviewHistoryMapper = sqlSession.getMapper(CaseReviewHistoryMapper.class);
CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper = sqlSession.getMapper(CaseReviewFunctionalCaseMapper.class);
for (CaseReviewFunctionalCase caseReviewFunctionalCase : caseReviewFunctionalCaseList) {
String caseId = caseReviewFunctionalCase.getCaseId();
CaseReviewHistory caseReviewHistory = buildCaseReviewHistory(request, userId, caseId);
caseReviewHistoryMapper.insert(caseReviewHistory);
if (caseHistoryMap.get(caseId) == null) {
List<CaseReviewHistory> histories = new ArrayList<>();
histories.add(caseReviewHistory);
caseHistoryMap.put(caseId, histories);
}
//根据评审规则更新用例评审和功能用例关系表中的状态 1.单人评审直接更新评审结果 2.多人评审需要计算
setStatus(request, caseReviewFunctionalCase, caseHistoryMap, reviewerMap);
caseReviewFunctionalCaseMapper.updateByPrimaryKeySelective(caseReviewFunctionalCase);
//检查是否有@发送@通知
if (StringUtils.isNotBlank(request.getNotifier())) {
List<String> relatedUsers = Arrays.asList(request.getNotifier().split(";"));
reviewSendNoticeService.sendNoticeCase(relatedUsers, userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_AT, reviewId);
}
//发送评审通过不通过通知评审中不发
if (StringUtils.equalsIgnoreCase(request.getStatus(), FunctionalCaseReviewStatus.UN_PASS.toString())) {
reviewSendNoticeService.sendNoticeCase(new ArrayList<>(), userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_FAIL, reviewId);
}
if (StringUtils.equalsIgnoreCase(request.getStatus(), FunctionalCaseReviewStatus.PASS.toString())) {
reviewSendNoticeService.sendNoticeCase(new ArrayList<>(), userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_PASSED, reviewId);
}
}
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
Map<String, Object> param = new HashMap<>();
param.put(CaseEvent.Param.CASE_IDS, caseIds);
param.put(CaseEvent.Param.REVIEW_ID, reviewId);
param.put(CaseEvent.Param.STATUS, request.getStatus());
param.put(CaseEvent.Param.USER_ID, userId);
param.put(CaseEvent.Param.EVENT_NAME, CaseEvent.Event.REVIEW_FUNCTIONAL_CASE);
provider.updateCaseReview(param);
}
private static void setStatus(BatchReviewFunctionalCaseRequest request, CaseReviewFunctionalCase caseReviewFunctionalCase, Map<String, List<CaseReviewHistory>> caseHistoryMap, Map<String, List<CaseReviewFunctionalCaseUser>> reviewerMap) {
if (StringUtils.equals(request.getReviewPassRule(), CaseReviewPassRule.SINGLE.toString())) {
caseReviewFunctionalCase.setStatus(request.getStatus());
} else {
//根据用例ID 查询所有评审人 再查所有评审人最后一次的评审结果只有通过/不通过算结果
List<CaseReviewHistory> caseReviewHistoriesExp = caseHistoryMap.get(caseReviewFunctionalCase.getCaseId());
Map<String, List<CaseReviewHistory>> hasReviewedUserMap = caseReviewHistoriesExp.stream().sorted(Comparator.comparingLong(CaseReviewHistory::getCreateTime).reversed()).collect(Collectors.groupingBy(CaseReviewHistory::getCreateUser, Collectors.toList()));
List<CaseReviewFunctionalCaseUser> caseReviewFunctionalCaseUsersExp = reviewerMap.get(caseReviewFunctionalCase.getCaseId());
if (caseReviewFunctionalCaseUsersExp != null && caseReviewFunctionalCaseUsersExp.size() > hasReviewedUserMap.size()) {
caseReviewFunctionalCase.setStatus(FunctionalCaseReviewStatus.UNDER_REVIEWED.toString());
} else {
AtomicInteger passCount = new AtomicInteger();
hasReviewedUserMap.forEach((k, v) -> {
if (StringUtils.equalsIgnoreCase(v.get(0).getStatus(), FunctionalCaseReviewStatus.PASS.toString())) {
passCount.set(passCount.get() + 1);
}
});
if (StringUtils.equalsIgnoreCase(request.getStatus(), FunctionalCaseReviewStatus.UN_PASS.toString())) {
caseReviewFunctionalCase.setStatus(FunctionalCaseReviewStatus.UN_PASS.toString());
} else {
//检查是否全部是通过全是才是PASS,否则是评审中
if (passCount.get() == hasReviewedUserMap.size()) {
caseReviewFunctionalCase.setStatus(FunctionalCaseReviewStatus.PASS.toString());
} else {
caseReviewFunctionalCase.setStatus(FunctionalCaseReviewStatus.UNDER_REVIEWED.toString());
}
}
}
}
}
private static CaseReviewHistory buildCaseReviewHistory(BatchReviewFunctionalCaseRequest request, String userId, String caseId) {
CaseReviewHistory caseReviewHistory = new CaseReviewHistory();
caseReviewHistory.setId(IDGenerator.nextStr());
caseReviewHistory.setReviewId(request.getReviewId());
caseReviewHistory.setCaseId(caseId);
caseReviewHistory.setStatus(request.getStatus());
caseReviewHistory.setDeleted(false);
if (StringUtils.equalsIgnoreCase(request.getStatus(), FunctionalCaseReviewStatus.UN_PASS.toString())) {
if (StringUtils.isBlank(request.getContent())) {
throw new MSException(Translator.get("case_review_content.not.exist"));
}
} else {
if (StringUtils.isNotBlank(request.getContent())) {
caseReviewHistory.setContent(request.getContent().getBytes());
}
}
caseReviewHistory.setNotifier(request.getNotifier());
caseReviewHistory.setCreateUser(userId);
caseReviewHistory.setCreateTime(System.currentTimeMillis());
return caseReviewHistory;
}
}

View File

@ -11,8 +11,8 @@ import io.metersphere.functional.dto.CaseReviewUserDTO;
import io.metersphere.functional.mapper.*;
import io.metersphere.functional.request.*;
import io.metersphere.functional.result.CaseManagementResultCode;
import io.metersphere.functional.utils.CaseListenerUtils;
import io.metersphere.project.dto.ModuleCountDTO;
import io.metersphere.provider.BaseCaseProvider;
import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.exception.MSException;
@ -26,7 +26,6 @@ import io.metersphere.system.uid.NumGenerator;
import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
@ -78,6 +77,8 @@ public class CaseReviewService {
private CaseReviewModuleService caseReviewModuleService;
@Resource
private ExtFunctionalCaseMapper extFunctionalCaseMapper;
@Resource
private BaseCaseProvider provider;
private static final String CASE_MODULE_COUNT_ALL = "all";
@ -436,7 +437,7 @@ public class CaseReviewService {
*/
public void associateCase(CaseReviewAssociateRequest request, String userId) {
String caseReviewId = request.getReviewId();
CaseReview caseReviewExist = checkCaseReview(caseReviewId);
checkCaseReview(caseReviewId);
BaseAssociateCaseRequest baseAssociateCaseRequest = request.getBaseAssociateCaseRequest();
List<String> caseIds = doSelectIds(baseAssociateCaseRequest, baseAssociateCaseRequest.getProjectId());
if (CollectionUtils.isEmpty(caseIds)) {
@ -463,20 +464,15 @@ public class CaseReviewService {
} finally {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
Map<String, Object> param = getParam(caseReviewFunctionalCases, caseReviewExist.getCaseCount() + caseRealIds.size(), caseReviewId);
CaseListenerUtils.addListener(param, CaseEvent.Event.ASSOCIATE);
}
private Map<String, Object> getParam(List<CaseReviewFunctionalCase> caseReviewFunctionalCases, int caseReviewExist, String caseReviewId) {
List<CaseReviewFunctionalCase> passList = caseReviewFunctionalCases.stream().filter(t -> StringUtils.equalsIgnoreCase(t.getStatus(), FunctionalCaseReviewStatus.PASS.toString())).toList();
Map<String, Object> param = new HashMap<>();
param.put(CaseEvent.Param.CASE_COUNT, caseReviewExist);
param.put(CaseEvent.Param.USER_ID, userId);
param.put(CaseEvent.Param.REVIEW_ID, caseReviewId);
param.put(CaseEvent.Param.PASS_COUNT, passList.size());
return param;
param.put(CaseEvent.Param.CASE_IDS,castIds);
param.put(CaseEvent.Param.CASE_COUNT,caseRealIds.size());
param.put(CaseEvent.Param.EVENT_NAME,CaseEvent.Event.ASSOCIATE);
provider.updateCaseReview(param);
}
public <T> List<String> doSelectIds(T dto, String projectId) {
BaseFunctionalCaseBatchDTO request = (BaseFunctionalCaseBatchDTO) dto;
if (request.isSelectAll()) {
@ -557,16 +553,18 @@ public class CaseReviewService {
}
public void disassociate(String reviewId, String caseId) {
public void disassociate(String reviewId, String caseId, String userId) {
//1.刪除评审与功能用例关联关系
CaseReviewFunctionalCaseExample caseReviewFunctionalCaseExample = new CaseReviewFunctionalCaseExample();
caseReviewFunctionalCaseExample.createCriteria().andReviewIdEqualTo(reviewId).andCaseIdEqualTo(caseId);
caseReviewFunctionalCaseMapper.deleteByExample(caseReviewFunctionalCaseExample);
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = extCaseReviewFunctionalCaseMapper.getList(reviewId, null, false);
Map<String, Object> param = getParam(caseReviewFunctionalCases, caseReviewFunctionalCases.size(), reviewId);
Map<String, Object> param = new HashMap<>();
param.put(CaseEvent.Param.REVIEW_ID, reviewId);
param.put(CaseEvent.Param.CASE_IDS, List.of(caseId));
CaseListenerUtils.addListener(param, CaseEvent.Event.DISASSOCIATE);
param.put(CaseEvent.Param.USER_ID, userId);
param.put(CaseEvent.Param.EVENT_NAME,CaseEvent.Event.DISASSOCIATE);
provider.updateCaseReview(param);
}
public Map<String, Long> moduleCount(CaseReviewPageRequest request) {

View File

@ -25,6 +25,8 @@ public class DeleteFunctionalCaseService {
private FunctionalCaseMapper functionalCaseMapper;
@Resource
private FunctionalCaseCommentMapper functionalCaseCommentMapper;
@Resource
private CaseReviewHistoryMapper caseReviewHistoryMapper;
public void deleteFunctionalCaseResource(List<String> ids, String projectId) {
@ -49,7 +51,10 @@ public class DeleteFunctionalCaseService {
FunctionalCaseExample caseExample = new FunctionalCaseExample();
caseExample.createCriteria().andIdIn(ids).andProjectIdEqualTo(projectId);
functionalCaseMapper.deleteByExample(caseExample);
//删除评审历史
CaseReviewHistoryExample caseReviewHistoryExample = new CaseReviewHistoryExample();
caseReviewHistoryExample.createCriteria().andCaseIdIn(ids);
caseReviewHistoryMapper.deleteByExample(caseReviewHistoryExample);
}
}

View File

@ -4,7 +4,6 @@ package io.metersphere.functional.service;
import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.functional.domain.FunctionalCaseComment;
import io.metersphere.functional.domain.FunctionalCaseCommentExample;
import io.metersphere.functional.constants.CommentEnum;
import io.metersphere.functional.dto.FunctionalCaseCommentDTO;
import io.metersphere.functional.dto.FunctionalCaseDTO;
import io.metersphere.functional.mapper.FunctionalCaseCommentMapper;
@ -24,7 +23,6 @@ import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.*;
@ -87,7 +85,6 @@ public class FunctionalCaseCommentService {
functionalCaseComment.setCreateUser(userId);
functionalCaseComment.setCreateTime(System.currentTimeMillis());
functionalCaseComment.setUpdateTime(System.currentTimeMillis());
functionalCaseComment.setType(CommentEnum.CASE.toString());
return functionalCaseComment;
}
@ -327,7 +324,6 @@ public class FunctionalCaseCommentService {
functionalCaseComment.setCreateUser(null);
functionalCaseComment.setCreateTime(null);
functionalCaseComment.setUpdateTime(System.currentTimeMillis());
functionalCaseComment.setType(CommentEnum.CASE.toString());
return functionalCaseComment;
}
}

View File

@ -10,11 +10,11 @@ import io.metersphere.functional.mapper.FunctionalCaseFollowerMapper;
import io.metersphere.functional.mapper.FunctionalCaseMapper;
import io.metersphere.functional.request.*;
import io.metersphere.functional.result.CaseManagementResultCode;
import io.metersphere.functional.utils.CaseListenerUtils;
import io.metersphere.project.domain.FileAssociation;
import io.metersphere.project.dto.ModuleCountDTO;
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.service.ProjectTemplateService;
import io.metersphere.provider.BaseCaseProvider;
import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.FunctionalCaseExecuteResult;
import io.metersphere.sdk.constants.TemplateScene;
@ -92,6 +92,9 @@ public class FunctionalCaseService {
@Resource
private BaseCustomFieldService baseCustomFieldService;
@Resource
private BaseCaseProvider provider;
private static final String CASE_MODULE_COUNT_ALL = "all";
private static final String ADD_FUNCTIONAL_CASE_FILE_LOG_URL = "/functional/case/add";
@ -401,7 +404,9 @@ public class FunctionalCaseService {
param.put(CaseEvent.Param.CASE_IDS, ids);
doDelete(ids, userId);
}
CaseListenerUtils.addListener(param, CaseEvent.Event.DELETE_FUNCTIONAL_CASE);
param.put(CaseEvent.Param.USER_ID, userId);
param.put(CaseEvent.Param.EVENT_NAME,CaseEvent.Event.DELETE_FUNCTIONAL_CASE);
provider.updateCaseReview(param);
}

View File

@ -9,7 +9,7 @@ import io.metersphere.functional.mapper.ExtFunctionalCaseMapper;
import io.metersphere.functional.mapper.FunctionalCaseCustomFieldMapper;
import io.metersphere.functional.mapper.FunctionalCaseMapper;
import io.metersphere.functional.request.FunctionalCaseBatchRequest;
import io.metersphere.functional.utils.CaseListenerUtils;
import io.metersphere.provider.BaseCaseProvider;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.CustomField;
@ -42,7 +42,8 @@ public class FunctionalCaseTrashService {
private ExtFunctionalCaseMapper extFunctionalCaseMapper;
@Resource
private DeleteFunctionalCaseService deleteFunctionalCaseService;
@Resource
private BaseCaseProvider provider;
/**
* 从回收站恢复用例
@ -60,7 +61,9 @@ public class FunctionalCaseTrashService {
delCustomFields(ids);
Map<String, Object> param = new HashMap<>();
param.put(CaseEvent.Param.CASE_IDS,ids);
CaseListenerUtils.addListener(param, CaseEvent.Event.RECOVER_FUNCTIONAL_CASE);
param.put(CaseEvent.Param.USER_ID,userId);
param.put(CaseEvent.Param.EVENT_NAME,CaseEvent.Event.RECOVER_FUNCTIONAL_CASE);
provider.updateCaseReview(param);
extFunctionalCaseMapper.recoverCase(ids,userId,System.currentTimeMillis());
}
@ -104,16 +107,18 @@ public class FunctionalCaseTrashService {
* 从回收站彻底用例
* @param id 用例ID
*/
public void deleteCase(String id) {
public void deleteCase(String id, String userId) {
FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(id);
if (functionalCase == null) {
return;
}
List<String> ids = getIdsByRefId(functionalCase.getRefId());
deleteFunctionalCaseService.deleteFunctionalCaseResource(ids, functionalCase.getProjectId());
Map<String, Object> param = new HashMap<>();
param.put(CaseEvent.Param.CASE_IDS,ids);
CaseListenerUtils.addListener(param, CaseEvent.Event.DELETE_TRASH_FUNCTIONAL_CASE);
deleteFunctionalCaseService.deleteFunctionalCaseResource(ids, functionalCase.getProjectId());
param.put(CaseEvent.Param.USER_ID,userId);
param.put(CaseEvent.Param.EVENT_NAME,CaseEvent.Event.DELETE_TRASH_FUNCTIONAL_CASE);
provider.updateCaseReview(param);
}
private List<String> getIdsByRefId(String refId) {
@ -151,7 +156,9 @@ public class FunctionalCaseTrashService {
List<String> ids = functionalCases.stream().map(FunctionalCase::getId).toList();
Map<String, Object> param = new HashMap<>();
param.put(CaseEvent.Param.CASE_IDS,ids);
CaseListenerUtils.addListener(param, CaseEvent.Event.RECOVER_FUNCTIONAL_CASE);
param.put(CaseEvent.Param.USER_ID,userId);
param.put(CaseEvent.Param.EVENT_NAME,CaseEvent.Event.RECOVER_FUNCTIONAL_CASE);
provider.updateCaseReview(param);
extFunctionalCaseMapper.recoverCaseByRefIds(refIds, userId, System.currentTimeMillis());
delCustomFieldsByRefIds(refIds);
}
@ -181,7 +188,7 @@ public class FunctionalCaseTrashService {
* 批量彻底删除也分当前版本和全部版本
* @param request request
*/
public void batchDeleteCase(FunctionalCaseBatchRequest request) {
public void batchDeleteCase(FunctionalCaseBatchRequest request, String userId) {
List<String> refIds;
if (request.isSelectAll()) {
//判断是否全部删除
@ -190,13 +197,15 @@ public class FunctionalCaseTrashService {
if (request.getDeleteAll()) {
//回收站全部版本全都删除
refIds = extFunctionalCaseMapper.getRefIds(ids, true);
deleteByRefIds(request, refIds);
deleteByRefIds(request, refIds, userId);
}else {
//只删除当前选择的数据
deleteFunctionalCaseService.deleteFunctionalCaseResource(ids, request.getProjectId());
Map<String, Object> param = new HashMap<>();
param.put(CaseEvent.Param.CASE_IDS,ids);
CaseListenerUtils.addListener(param, CaseEvent.Event.DELETE_TRASH_FUNCTIONAL_CASE);
deleteFunctionalCaseService.deleteFunctionalCaseResource(ids, request.getProjectId());
param.put(CaseEvent.Param.USER_ID,userId);
param.put(CaseEvent.Param.EVENT_NAME,CaseEvent.Event.DELETE_TRASH_FUNCTIONAL_CASE);
provider.updateCaseReview(param);
}
} else {
if (CollectionUtils.isEmpty(request.getSelectIds())) {
@ -207,25 +216,30 @@ public class FunctionalCaseTrashService {
functionalCaseExample.createCriteria().andIdIn(request.getSelectIds());
List<FunctionalCase> functionalCases = functionalCaseMapper.selectByExample(functionalCaseExample);
refIds = functionalCases.stream().map(FunctionalCase::getRefId).distinct().toList();
deleteByRefIds(request, refIds);
deleteByRefIds(request, refIds, userId);
} else {
//只删除当前选择的数据
deleteFunctionalCaseService.deleteFunctionalCaseResource(request.getSelectIds(), request.getProjectId());
Map<String, Object> param = new HashMap<>();
param.put(CaseEvent.Param.CASE_IDS,request.getSelectIds());
CaseListenerUtils.addListener(param, CaseEvent.Event.DELETE_TRASH_FUNCTIONAL_CASE);
deleteFunctionalCaseService.deleteFunctionalCaseResource(request.getSelectIds(), request.getProjectId());
param.put(CaseEvent.Param.USER_ID,userId);
param.put(CaseEvent.Param.EVENT_NAME,CaseEvent.Event.DELETE_TRASH_FUNCTIONAL_CASE);
provider.updateCaseReview(param);
}
}
}
private void deleteByRefIds(FunctionalCaseBatchRequest request, List<String> refIds) {
private void deleteByRefIds(FunctionalCaseBatchRequest request, List<String> refIds, String userId) {
FunctionalCaseExample functionalCaseExample = new FunctionalCaseExample();
functionalCaseExample.createCriteria().andRefIdIn(refIds).andDeletedEqualTo(true);
List<FunctionalCase> functionalCases = functionalCaseMapper.selectByExample(functionalCaseExample);
List<String> deleteIds = functionalCases.stream().map(FunctionalCase::getId).toList();
deleteFunctionalCaseService.deleteFunctionalCaseResource(deleteIds, request.getProjectId());
Map<String, Object> param = new HashMap<>();
param.put(CaseEvent.Param.CASE_IDS,deleteIds);
CaseListenerUtils.addListener(param, CaseEvent.Event.DELETE_TRASH_FUNCTIONAL_CASE);
deleteFunctionalCaseService.deleteFunctionalCaseResource(deleteIds, request.getProjectId());
param.put(CaseEvent.Param.USER_ID,userId);
param.put(CaseEvent.Param.EVENT_NAME,CaseEvent.Event.DELETE_TRASH_FUNCTIONAL_CASE);
provider.updateCaseReview(param);
}
}

View File

@ -1,30 +1,29 @@
package io.metersphere.functional.service;
import io.metersphere.functional.constants.CaseEvent;
import io.metersphere.functional.constants.CaseReviewPassRule;
import io.metersphere.functional.constants.CaseReviewStatus;
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
import io.metersphere.functional.domain.*;
import io.metersphere.functional.domain.CaseReviewFunctionalCaseUserExample;
import io.metersphere.functional.domain.CaseReviewHistory;
import io.metersphere.functional.domain.CaseReviewHistoryExample;
import io.metersphere.functional.dto.CaseReviewHistoryDTO;
import io.metersphere.functional.mapper.*;
import io.metersphere.functional.mapper.CaseReviewFunctionalCaseUserMapper;
import io.metersphere.functional.mapper.CaseReviewHistoryMapper;
import io.metersphere.functional.mapper.ExtCaseReviewFunctionalCaseMapper;
import io.metersphere.functional.mapper.ExtCaseReviewHistoryMapper;
import io.metersphere.functional.request.ReviewFunctionalCaseRequest;
import io.metersphere.provider.BaseCaseProvider;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.User;
import io.metersphere.system.mapper.UserMapper;
import io.metersphere.system.notice.NoticeModel;
import io.metersphere.system.notice.constants.NoticeConstants;
import io.metersphere.system.notice.utils.MessageTemplateUtils;
import io.metersphere.system.service.NoticeSendService;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
@ -39,16 +38,11 @@ public class ReviewFunctionalCaseService {
@Resource
private CaseReviewFunctionalCaseUserMapper caseReviewFunctionalCaseUserMapper;
@Resource
private CaseReviewMapper caseReviewMapper;
@Resource
private UserMapper userMapper;
@Resource
private NoticeSendService noticeSendService;
@Resource
private FunctionalCaseMapper functionalCaseMapper;
@Resource
private ExtCaseReviewHistoryMapper extCaseReviewHistoryMapper;
@Resource
private ReviewSendNoticeService reviewSendNoticeService;
@Resource
private BaseCaseProvider provider;
/**
* 评审功能用例
@ -58,86 +52,44 @@ public class ReviewFunctionalCaseService {
*/
public void saveReview(ReviewFunctionalCaseRequest request, String userId) {
//保存评审历史
String reviewId = request.getReviewId();
String caseId = request.getCaseId();
CaseReviewHistory caseReviewHistory = buildReviewHistory(request, userId);
caseReviewHistoryMapper.insert(caseReviewHistory);
CaseReviewHistoryExample caseReviewHistoryExample = new CaseReviewHistoryExample();
caseReviewHistoryExample.createCriteria().andCaseIdEqualTo(request.getCaseId()).andReviewIdEqualTo(request.getReviewId());
List<CaseReviewHistory> caseReviewHistories = caseReviewHistoryMapper.selectByExample(caseReviewHistoryExample);
Map<String, List<CaseReviewHistory>> hasReviewedUserMap = caseReviewHistories.stream().sorted(Comparator.comparingLong(CaseReviewHistory::getCreateTime).reversed()).collect(Collectors.groupingBy(CaseReviewHistory::getCreateUser, Collectors.toList()));
if (hasReviewedUserMap.get(userId) ==null) {
List<CaseReviewHistory>caseReviewHistoryList = new ArrayList<>();
caseReviewHistoryList.add(caseReviewHistory);
hasReviewedUserMap.put(userId,caseReviewHistoryList);
}
//根据评审规则更新用例评审和功能用例关系表中的状态 1.单人评审直接更新评审结果 2.多人评审需要计算
String functionalCaseStatus = getFunctionalCaseStatus(request);
extCaseReviewFunctionalCaseMapper.updateStatus(request.getCaseId(), request.getReviewId(), functionalCaseStatus);
//更新用例评审状态(判断所有用例是否结束false进行中true已完成)
boolean completed = updateCaseReviewStatus(request.getReviewId());
String functionalCaseStatus = getFunctionalCaseStatus(request, hasReviewedUserMap);
extCaseReviewFunctionalCaseMapper.updateStatus(caseId, reviewId, functionalCaseStatus);
caseReviewHistoryMapper.insert(caseReviewHistory);
//检查是否有@发送@通知
if (StringUtils.isNotBlank(request.getNotifier())) {
List<String> relatedUsers = Arrays.asList(request.getNotifier().split(";"));
sendNotice(relatedUsers, userId, request,NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_AT);
reviewSendNoticeService.sendNoticeCase(relatedUsers, userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_AT, reviewId);
}
//发送评审通过不通过通知评审中不发
if (StringUtils.equalsIgnoreCase(request.getStatus(), FunctionalCaseReviewStatus.UN_PASS.toString())) {
sendNotice(new ArrayList<>(), userId, request,NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_FAIL);
reviewSendNoticeService.sendNoticeCase(new ArrayList<>(), userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_FAIL, reviewId);
}
if (StringUtils.equalsIgnoreCase(request.getStatus(), FunctionalCaseReviewStatus.PASS.toString())) {
sendNotice(new ArrayList<>(), userId, request,NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_PASSED);
}
//检查用例评审是否结束发送通知
if (completed) {
sendNotice(new ArrayList<>(), userId, request,NoticeConstants.TaskType.CASE_REVIEW_TASK, NoticeConstants.Event.REVIEW_COMPLETED);
}
reviewSendNoticeService.sendNoticeCase(new ArrayList<>(), userId, caseId, NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, NoticeConstants.Event.REVIEW_PASSED, reviewId);
}
Map<String, Object> param = new HashMap<>();
param.put(CaseEvent.Param.CASE_IDS, List.of(caseId));
param.put(CaseEvent.Param.REVIEW_ID, reviewId);
param.put(CaseEvent.Param.STATUS, request.getStatus());
param.put(CaseEvent.Param.USER_ID, userId);
param.put(CaseEvent.Param.EVENT_NAME, CaseEvent.Event.REVIEW_FUNCTIONAL_CASE);
provider.updateCaseReview(param);
public void sendNotice(List<String> relatedUsers, String userId,ReviewFunctionalCaseRequest request, String task, String event) {
CaseReview caseReview = caseReviewMapper.selectByPrimaryKey(request.getReviewId());
FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(request.getCaseId());
Map<String, String> defaultTemplateMap = MessageTemplateUtils.getDefaultTemplateMap();
String template = defaultTemplateMap.get(task + "_" + event);
Map<String, String> defaultSubjectMap = MessageTemplateUtils.getDefaultTemplateSubjectMap();
String subject = defaultSubjectMap.get(task + "_" + event);
User user = userMapper.selectByPrimaryKey(userId);
Map paramMap;
if (StringUtils.equalsIgnoreCase(task,NoticeConstants.TaskType.CASE_REVIEW_TASK)) {
BeanMap beanMap = new BeanMap(caseReview);
paramMap = new HashMap<>(beanMap);
} else {
BeanMap beanMap = new BeanMap(functionalCase);
paramMap = new HashMap<>(beanMap);
paramMap.put("reviewName", caseReview.getName());
}
paramMap.put(NoticeConstants.RelatedUser.OPERATOR, user.getName());
NoticeModel noticeModel = NoticeModel.builder()
.operator(userId)
.context(template)
.subject(subject)
.paramMap(paramMap)
.event(event)
.status((String) paramMap.get("status"))
.excludeSelf(true)
.relatedUsers(relatedUsers)
.build();
noticeSendService.send(task, noticeModel);
}
/**
* 更新用例评审自身的状态
*
* @param reviewId 用例评审Id
* @return completed
*/
private boolean updateCaseReviewStatus(String reviewId) {
boolean completed = false;
List<String> statusList = new ArrayList<>();
statusList.add(FunctionalCaseReviewStatus.UN_REVIEWED.toString());
statusList.add(FunctionalCaseReviewStatus.UNDER_REVIEWED.toString());
statusList.add(FunctionalCaseReviewStatus.RE_REVIEWED.toString());
Long unCompletedCaseCount = extCaseReviewFunctionalCaseMapper.getUnCompletedCaseCount(reviewId, statusList);
CaseReview caseReview = new CaseReview();
caseReview.setId(reviewId);
if (unCompletedCaseCount > 0L) {
caseReview.setStatus(CaseReviewStatus.UNDERWAY.toString());
} else {
completed = true;
caseReview.setStatus(CaseReviewStatus.COMPLETED.toString());
}
caseReviewMapper.updateByPrimaryKeySelective(caseReview);
return completed;
}
/**
@ -146,33 +98,25 @@ public class ReviewFunctionalCaseService {
* @param request 评审规则
* @return 功能用例的评审结果
*/
private String getFunctionalCaseStatus(ReviewFunctionalCaseRequest request) {
private String getFunctionalCaseStatus(ReviewFunctionalCaseRequest request, Map<String, List<CaseReviewHistory>> hasReviewedUserMap) {
String functionalCaseStatus;
if (StringUtils.equals(request.getReviewPassRule(), CaseReviewPassRule.SINGLE.toString())) {
functionalCaseStatus = request.getStatus();
} else {
//根据用例ID 查询所有评审人 再查所有评审人最后一次的评审结果只有通过/不通过算结果
CaseReviewHistoryExample caseReviewHistoryExample = new CaseReviewHistoryExample();
caseReviewHistoryExample.createCriteria().andCaseIdEqualTo(request.getCaseId()).andReviewIdEqualTo(request.getReviewId());
List<CaseReviewHistory> caseReviewHistories = caseReviewHistoryMapper.selectByExample(caseReviewHistoryExample);
Map<String, List<CaseReviewHistory>> hasReviewedUserMap = caseReviewHistories.stream().sorted(Comparator.comparingLong(CaseReviewHistory::getCreateTime).reversed()).collect(Collectors.groupingBy(CaseReviewHistory::getCreateUser, Collectors.toList()));
CaseReviewFunctionalCaseUserExample caseReviewFunctionalCaseUserExample = new CaseReviewFunctionalCaseUserExample();
caseReviewFunctionalCaseUserExample.createCriteria().andReviewIdEqualTo(request.getReviewId()).andCaseIdEqualTo(request.getCaseId());
long reviewerNum = caseReviewFunctionalCaseUserMapper.countByExample(caseReviewFunctionalCaseUserExample);
if ((int) reviewerNum > hasReviewedUserMap.size()) {
functionalCaseStatus = FunctionalCaseReviewStatus.UNDER_REVIEWED.toString();
} else {
AtomicBoolean hasUnPass = new AtomicBoolean(false);
AtomicInteger passCount = new AtomicInteger();
hasReviewedUserMap.forEach((k, v) -> {
if (StringUtils.equalsIgnoreCase(v.get(0).getStatus(), FunctionalCaseReviewStatus.UN_PASS.toString())) {
hasUnPass.set(true);
}
if (StringUtils.equalsIgnoreCase(v.get(0).getStatus(), FunctionalCaseReviewStatus.PASS.toString())) {
passCount.set(passCount.get() + 1);
}
});
if (hasUnPass.get()) {
if (StringUtils.equalsIgnoreCase(request.getStatus(), FunctionalCaseReviewStatus.UN_PASS.toString())) {
functionalCaseStatus = FunctionalCaseReviewStatus.UN_PASS.toString();
} else {
//检查是否全部是通过全是才是PASS,否则是评审中
@ -200,6 +144,7 @@ public class ReviewFunctionalCaseService {
caseReviewHistory.setReviewId(request.getReviewId());
caseReviewHistory.setCaseId(request.getCaseId());
caseReviewHistory.setStatus(request.getStatus());
caseReviewHistory.setDeleted(false);
if (StringUtils.equalsIgnoreCase(request.getStatus(), FunctionalCaseReviewStatus.UN_PASS.toString())) {
if (StringUtils.isBlank(request.getContent())) {
throw new MSException(Translator.get("case_review_content.not.exist"));

View File

@ -0,0 +1,85 @@
package io.metersphere.functional.service;
import io.metersphere.functional.domain.CaseReview;
import io.metersphere.functional.domain.FunctionalCase;
import io.metersphere.functional.mapper.CaseReviewMapper;
import io.metersphere.functional.mapper.FunctionalCaseMapper;
import io.metersphere.system.domain.User;
import io.metersphere.system.mapper.UserMapper;
import io.metersphere.system.notice.NoticeModel;
import io.metersphere.system.notice.constants.NoticeConstants;
import io.metersphere.system.notice.utils.MessageTemplateUtils;
import io.metersphere.system.service.NoticeSendService;
import jakarta.annotation.Resource;
import org.apache.commons.beanutils.BeanMap;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class ReviewSendNoticeService {
@Resource
private NoticeSendService noticeSendService;
@Resource
private UserMapper userMapper;
@Resource
private CaseReviewMapper caseReviewMapper;
@Resource
private FunctionalCaseMapper functionalCaseMapper;
@Async
public void sendNotice(List<String> relatedUsers, String userId, String reviewId, String task, String event) {
User user = userMapper.selectByPrimaryKey(userId);
CaseReview caseReview = caseReviewMapper.selectByPrimaryKey(reviewId);
Map<String, String> defaultTemplateMap = MessageTemplateUtils.getDefaultTemplateMap();
String template = defaultTemplateMap.get(task + "_" + event);
Map<String, String> defaultSubjectMap = MessageTemplateUtils.getDefaultTemplateSubjectMap();
String subject = defaultSubjectMap.get(task + "_" + event);
Map paramMap;
BeanMap beanMap = new BeanMap(caseReview);
paramMap = new HashMap<>(beanMap);
paramMap.put(NoticeConstants.RelatedUser.OPERATOR, user.getName());
NoticeModel noticeModel = NoticeModel.builder()
.operator(user.getId())
.context(template)
.subject(subject)
.paramMap(paramMap)
.event(event)
.status((String) paramMap.get("status"))
.excludeSelf(true)
.relatedUsers(relatedUsers)
.build();
noticeSendService.send(task, noticeModel);
}
public void sendNoticeCase(List<String> relatedUsers, String userId, String caseId, String task, String event,String reviewId) {
FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(caseId);
User user = userMapper.selectByPrimaryKey(userId);
CaseReview caseReview = caseReviewMapper.selectByPrimaryKey(reviewId);
Map<String, String> defaultTemplateMap = MessageTemplateUtils.getDefaultTemplateMap();
String template = defaultTemplateMap.get(task + "_" + event);
Map<String, String> defaultSubjectMap = MessageTemplateUtils.getDefaultTemplateSubjectMap();
String subject = defaultSubjectMap.get(task + "_" + event);
Map paramMap;
BeanMap beanMap = new BeanMap(functionalCase);
paramMap = new HashMap<>(beanMap);
paramMap.put("reviewName", caseReview.getName());
paramMap.put(NoticeConstants.RelatedUser.OPERATOR, user.getName());
NoticeModel noticeModel = NoticeModel.builder()
.operator(user.getId())
.context(template)
.subject(subject)
.paramMap(paramMap)
.event(event)
.status((String) paramMap.get("status"))
.excludeSelf(true)
.relatedUsers(relatedUsers)
.build();
noticeSendService.send(task, noticeModel);
}
}

View File

@ -1,23 +0,0 @@
package io.metersphere.functional.utils;
import io.metersphere.functional.event.CaseEventSource;
import io.metersphere.functional.listener.CaseEventListener;
import io.metersphere.sdk.util.CommonBeanFactory;
import java.util.Map;
public class CaseListenerUtils {
public static void addListener(Map<String, Object> param, String message) {
CaseEventSource caseEventSource = CommonBeanFactory.getBean(CaseEventSource.class);
CaseEventListener caseEventListener = CommonBeanFactory.getBean(CaseEventListener.class);
if (caseEventSource != null) {
caseEventSource.addListener(event -> {
assert caseEventListener != null;
caseEventListener.onEvent(event);
});
caseEventSource.fireEvent("CASE_MANAGEMENT", message, param);
}
}
}

View File

@ -7,16 +7,12 @@ import io.metersphere.functional.dto.CaseReviewDTO;
import io.metersphere.functional.mapper.*;
import io.metersphere.functional.request.*;
import io.metersphere.functional.result.CaseManagementResultCode;
import io.metersphere.project.domain.Notification;
import io.metersphere.project.domain.NotificationExample;
import io.metersphere.project.mapper.NotificationMapper;
import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.domain.User;
import io.metersphere.system.dto.sdk.request.PosRequest;
import io.metersphere.system.notice.constants.NoticeConstants;
import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
@ -77,8 +73,6 @@ public class CaseReviewControllerTests extends BaseTest {
private CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper;
@Resource
private CaseReviewFunctionalCaseUserMapper caseReviewFunctionalCaseUserMapper;
@Resource
private NotificationMapper notificationMapper;
@Test
@Order(1)
@ -97,10 +91,7 @@ public class CaseReviewControllerTests extends BaseTest {
caseReviewFunctionalCaseExample.createCriteria().andReviewIdEqualTo(caseReviewId);
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = caseReviewFunctionalCaseMapper.selectByExample(caseReviewFunctionalCaseExample);
Assertions.assertEquals(1, caseReviewFunctionalCases.size());
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceTypeEqualTo(NoticeConstants.TaskType.CASE_REVIEW_TASK);
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
Assertions.assertEquals(1, notifications.size());
caseReviewRequest = getCaseReviewAddRequest("创建评审1", CaseReviewPassRule.SINGLE.toString(), "CASE_REVIEW_TEST_GYQ_ID", false, true, null);
this.requestPostWithOk(COPY_CASE_REVIEW, caseReviewRequest);
@ -244,12 +235,6 @@ public class CaseReviewControllerTests extends BaseTest {
List<CaseReview> updateCaseReviews2 = getCaseReviews("创建评审更新2");
Assertions.assertEquals(1, updateCaseReviews2.size());
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceTypeEqualTo(NoticeConstants.TaskType.CASE_REVIEW_TASK).andReceiverEqualTo("gyq_review_test2");
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
System.out.println(JSON.toJSONString(notifications));
Assertions.assertTrue(notifications.size() > 0);
}
@Test
@ -472,7 +457,7 @@ public class CaseReviewControllerTests extends BaseTest {
// 返回的数据量不超过规定要返回的数据量相同
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= request.getPageSize());
caseReviewDTOS = JSON.parseArray(JSON.toJSONString(pageData.getList()), CaseReviewDTO.class);
Assertions.assertTrue(CollectionUtils.isEmpty(caseReviewDTOS));
Assertions.assertTrue(CollectionUtils.isNotEmpty(caseReviewDTOS));
}
@ -550,10 +535,6 @@ public class CaseReviewControllerTests extends BaseTest {
public void testDelete() throws Exception {
List<CaseReview> caseReviews = getCaseReviews("创建评审更新2");
delCaseReview(caseReviews.get(0).getId());
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceTypeEqualTo(NoticeConstants.TaskType.CASE_REVIEW_TASK).andResourceIdEqualTo(caseReviews.get(0).getId()).andOperationEqualTo("DELETE");
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
Assertions.assertEquals(1, notifications.size());
delCaseReview("caseReviewIdX");
}

View File

@ -1,5 +1,7 @@
package io.metersphere.functional.controller;
import io.metersphere.functional.constants.CaseReviewPassRule;
import io.metersphere.functional.constants.FunctionalCaseReviewStatus;
import io.metersphere.functional.domain.CaseReviewFunctionalCase;
import io.metersphere.functional.domain.CaseReviewFunctionalCaseExample;
import io.metersphere.functional.mapper.CaseReviewFunctionalCaseMapper;
@ -9,6 +11,7 @@ import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.dto.sdk.BaseCondition;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
@ -21,6 +24,8 @@ import org.springframework.util.LinkedMultiValueMap;
import java.nio.charset.StandardCharsets;
import java.util.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@AutoConfigureMockMvc
@ -35,6 +40,8 @@ public class CaseReviewFunctionalCaseControllerTests extends BaseTest {
public static final String REVIEW_FUNCTIONAL_CASE_POS = "/case/review/detail/edit/pos";
public static final String REVIEW_FUNCTIONAL_CASE_BATCH_REVIEW = "/case/review/detail/batch/review";
@Resource
private CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper;
@ -168,6 +175,65 @@ public class CaseReviewFunctionalCaseControllerTests extends BaseTest {
Assertions.assertTrue(pos6 > pos4);
}
@Test
@Order(7)
public void testBatchReview() throws Exception {
BatchReviewFunctionalCaseRequest request = new BatchReviewFunctionalCaseRequest();
request.setReviewId("wx_review_id_1");
request.setReviewPassRule(CaseReviewPassRule.MULTIPLE.toString());
request.setStatus(FunctionalCaseReviewStatus.RE_REVIEWED.toString());
request.setSelectAll(true);
request.setContent("测试批量评审通过");
this.requestPostWithOk(REVIEW_FUNCTIONAL_CASE_BATCH_REVIEW, request);
request = new BatchReviewFunctionalCaseRequest();
request.setReviewId("wx_review_id_1");
request.setReviewPassRule(CaseReviewPassRule.SINGLE.toString());
request.setStatus(FunctionalCaseReviewStatus.UN_PASS.toString());
request.setSelectAll(true);
List<String>excludeIds = new ArrayList<>();
excludeIds.add("gyq_test_4");
request.setExcludeIds(excludeIds);
request.setContent("测试批量评审不通过");
this.requestPostWithOk(REVIEW_FUNCTIONAL_CASE_BATCH_REVIEW, request);
CaseReviewFunctionalCase caseReviewFunctionalCase = caseReviewFunctionalCaseMapper.selectByPrimaryKey("gyq_test_4");
Assertions.assertTrue(StringUtils.equalsIgnoreCase(caseReviewFunctionalCase.getStatus(),FunctionalCaseReviewStatus.UNDER_REVIEWED.toString()));
request = new BatchReviewFunctionalCaseRequest();
request.setReviewId("wx_review_id_1");
request.setReviewPassRule(CaseReviewPassRule.SINGLE.toString());
request.setStatus(FunctionalCaseReviewStatus.PASS.toString());
request.setSelectAll(false);
List<String>ids = new ArrayList<>();
ids.add("gyq_test_3");
request.setSelectIds(ids);
this.requestPostWithOk(REVIEW_FUNCTIONAL_CASE_BATCH_REVIEW, request);
caseReviewFunctionalCase = caseReviewFunctionalCaseMapper.selectByPrimaryKey("gyq_test_3");
Assertions.assertTrue(StringUtils.equalsIgnoreCase(caseReviewFunctionalCase.getStatus(),FunctionalCaseReviewStatus.PASS.toString()));
request = new BatchReviewFunctionalCaseRequest();
request.setReviewId("wx_review_id_1");
request.setReviewPassRule(CaseReviewPassRule.MULTIPLE.toString());
request.setStatus(FunctionalCaseReviewStatus.PASS.toString());
request.setSelectAll(true);
request.setNotifier("gyq;admin");
request.setContent("测试批量评审通过");
this.requestPostWithOk(REVIEW_FUNCTIONAL_CASE_BATCH_REVIEW, request);
}
@Test
@Order(8)
public void testBatchReviewFalse() throws Exception {
BatchReviewFunctionalCaseRequest request = new BatchReviewFunctionalCaseRequest();
request.setReviewId("wx_review_id_1");
request.setReviewPassRule(CaseReviewPassRule.SINGLE.toString());
request.setStatus(FunctionalCaseReviewStatus.UN_PASS.toString());
request.setSelectAll(true);
this.requestPost(REVIEW_FUNCTIONAL_CASE_BATCH_REVIEW, request).andExpect(status().is5xxServerError());
}
private List<CaseReviewFunctionalCase> getCaseReviewFunctionalCase(String reviewId) {
CaseReviewFunctionalCaseExample caseReviewFunctionalCaseExample = new CaseReviewFunctionalCaseExample();
caseReviewFunctionalCaseExample.createCriteria().andReviewIdEqualTo(reviewId);

View File

@ -1,41 +0,0 @@
package io.metersphere.functional.controller;
import io.metersphere.functional.event.CaseEventSource;
import io.metersphere.sdk.listener.Event;
import io.metersphere.sdk.listener.EventListener;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.LogUtils;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.HashMap;
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@AutoConfigureMockMvc
public class EventSourceTests {
@Test
@Order(0)
public void eventSourceTest() throws Exception {
// 注册所有监听源
LogUtils.info("初始化用例管理事件源");
CaseEventSource caseEventSource = CommonBeanFactory.getBean(CaseEventSource.class);
assert caseEventSource != null;
caseEventSource.addListener(new EventListener<Event>() {
@Override
public void onEvent(Event event) {
LogUtils.info("ExecEventListener: " + event.module() + "" + event.message());
}
});
// 触发事件
caseEventSource.fireEvent("CASE", "Event after removing the listener test.");
// 触发事件待参数
caseEventSource.fireEvent("CASE", "Event after removing the listener test.",new HashMap<>());
}
}

View File

@ -8,9 +8,6 @@ import io.metersphere.functional.dto.FunctionalCaseCommentDTO;
import io.metersphere.functional.mapper.FunctionalCaseCommentMapper;
import io.metersphere.functional.mapper.FunctionalCaseCustomFieldMapper;
import io.metersphere.functional.request.FunctionalCaseCommentRequest;
import io.metersphere.project.domain.Notification;
import io.metersphere.project.domain.NotificationExample;
import io.metersphere.project.mapper.NotificationMapper;
import io.metersphere.sdk.constants.CustomFieldType;
import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.constants.TemplateScene;
@ -21,9 +18,7 @@ import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.domain.CustomField;
import io.metersphere.system.mapper.CustomFieldMapper;
import io.metersphere.system.notice.constants.NoticeConstants;
import io.metersphere.system.notice.constants.NotificationConstants;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
@ -49,9 +44,6 @@ public class FunctionalCaseCommentControllerTests {
@Resource
private MockMvc mockMvc;
@Resource
private NotificationMapper notificationMapper;
@Resource
private FunctionalCaseCommentMapper functionalCaseCommentMapper;
@ -95,13 +87,6 @@ public class FunctionalCaseCommentControllerTests {
functionalCaseCommentRequest.setContent("评论你好");
functionalCaseCommentRequest.setEvent(NoticeConstants.Event.AT);
FunctionalCaseComment functionalCaseComment = getFunctionalCaseComment(functionalCaseCommentRequest,SAVE_URL);
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTest").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
System.out.println(JSON.toJSONString(notifications));
Assertions.assertFalse(notifications.isEmpty());
Assertions.assertEquals(2, notifications.size());
Assertions.assertTrue(StringUtils.equals(notifications.get(0).getReceiver(), "default-project-member-user-guo-1"));
FunctionalCaseComment functionalCaseComment1 = functionalCaseCommentMapper.selectByPrimaryKey(functionalCaseComment.getId());
Assertions.assertTrue(StringUtils.equals(functionalCaseComment1.getCaseId(), "xiaomeinvGTest"));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment1.getNotifier(), "default-project-member-user-guo-1"));
@ -119,12 +104,6 @@ public class FunctionalCaseCommentControllerTests {
functionalCaseCommentRequest.setContent("更新评论加@人");
functionalCaseCommentRequest.setEvent(NoticeConstants.Event.AT);
getFunctionalCaseComment(functionalCaseCommentRequest,UPDATE_URL);
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo(functionalCaseComment1.getCaseId()).andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
System.out.println(JSON.toJSONString(notifications));
Assertions.assertFalse(notifications.isEmpty());
Assertions.assertTrue(StringUtils.equals(notifications.get(0).getReceiver(), functionalCaseComment1.getNotifier()));
FunctionalCaseComment functionalCaseComment2 = functionalCaseCommentMapper.selectByPrimaryKey(functionalCaseComment1.getId());
Assertions.assertTrue(StringUtils.equals(functionalCaseComment2.getCaseId(), functionalCaseComment1.getCaseId()));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment2.getNotifier(), functionalCaseComment1.getNotifier()));
@ -136,19 +115,12 @@ public class FunctionalCaseCommentControllerTests {
@Order(3)
public void updateCommentSuccess() throws Exception {
FunctionalCaseComment functionalCaseComment1 = getFunctionalCaseComment();
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo(functionalCaseComment1.getCaseId()).andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
FunctionalCaseCommentRequest functionalCaseCommentRequest = new FunctionalCaseCommentRequest();
functionalCaseCommentRequest.setId(functionalCaseComment1.getId());
functionalCaseCommentRequest.setCaseId(functionalCaseComment1.getCaseId());
functionalCaseCommentRequest.setContent("更新评论不发通知");
functionalCaseCommentRequest.setEvent(NoticeConstants.Event.COMMENT);
getFunctionalCaseComment(functionalCaseCommentRequest,UPDATE_URL);
notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo(functionalCaseComment1.getCaseId()).andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notificationAfter = notificationMapper.selectByExampleWithBLOBs(notificationExample);
Assertions.assertEquals(notifications.size(), notificationAfter.size());
FunctionalCaseComment functionalCaseComment2 = functionalCaseCommentMapper.selectByPrimaryKey(functionalCaseComment1.getId());
Assertions.assertTrue(StringUtils.equals(functionalCaseComment2.getCaseId(), functionalCaseComment1.getCaseId()));
Assertions.assertTrue(StringUtils.isBlank(functionalCaseComment2.getNotifier()));
@ -164,10 +136,6 @@ public class FunctionalCaseCommentControllerTests {
functionalCaseCommentRequest.setContent("评论你好");
functionalCaseCommentRequest.setEvent(NoticeConstants.Event.AT);
postFalse(functionalCaseCommentRequest,SAVE_URL);
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTestNo").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notifications = notificationMapper.selectByExample(notificationExample);
Assertions.assertTrue(CollectionUtils.isEmpty(notifications));
}
@Test
@ -181,10 +149,6 @@ public class FunctionalCaseCommentControllerTests {
functionalCaseCommentRequest.setContent("评论你好");
functionalCaseCommentRequest.setEvent(NoticeConstants.Event.AT);
postFalse(functionalCaseCommentRequest,UPDATE_URL);
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTestNo").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notifications = notificationMapper.selectByExample(notificationExample);
Assertions.assertTrue(CollectionUtils.isEmpty(notifications));
}
@Test
@ -202,10 +166,6 @@ public class FunctionalCaseCommentControllerTests {
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().is4xxClientError())
.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn();
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTestNo").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notifications = notificationMapper.selectByExample(notificationExample);
Assertions.assertTrue(CollectionUtils.isEmpty(notifications));
}
private ResultHolder postFalse(FunctionalCaseCommentRequest functionalCaseCommentRequest, String url) throws Exception {
@ -229,10 +189,6 @@ public class FunctionalCaseCommentControllerTests {
functionalCaseCommentRequest.setContent("这个好");
functionalCaseCommentRequest.setEvent(NoticeConstants.Event.AT);
FunctionalCaseComment functionalCaseComment = getFunctionalCaseComment(functionalCaseCommentRequest,SAVE_URL);
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTest").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK).andReceiverEqualTo("default-project-member-user-guo");
List<Notification> notifications = notificationMapper.selectByExample(notificationExample);
Assertions.assertTrue(CollectionUtils.isEmpty(notifications));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getCaseId(), "xiaomeinvGTest"));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getNotifier(), "default-project-member-user-guo"));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getContent(), "这个好"));
@ -246,11 +202,6 @@ public class FunctionalCaseCommentControllerTests {
functionalCaseCommentRequest.setContent("这个好");
functionalCaseCommentRequest.setEvent(NoticeConstants.Event.AT);
FunctionalCaseComment functionalCaseComment = getFunctionalCaseComment(functionalCaseCommentRequest,SAVE_URL);
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTestOne").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notifications = notificationMapper.selectByExample(notificationExample);
Assertions.assertFalse(CollectionUtils.isEmpty(notifications));
Assertions.assertTrue(StringUtils.equals(notifications.get(0).getType(), NotificationConstants.Type.SYSTEM_NOTICE.name()));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getCaseId(), "xiaomeinvGTestOne"));
Assertions.assertTrue(StringUtils.isBlank(functionalCaseComment.getNotifier()));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getContent(), "这个好"));
@ -265,13 +216,6 @@ public class FunctionalCaseCommentControllerTests {
functionalCaseCommentRequest.setContent("评论你好");
functionalCaseCommentRequest.setEvent(NoticeConstants.Event.COMMENT);
FunctionalCaseComment functionalCaseComment = getFunctionalCaseComment(functionalCaseCommentRequest,SAVE_URL);
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTestOne").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
Assertions.assertFalse(notifications.isEmpty());
System.out.println(JSON.toJSONString(notifications));
Assertions.assertTrue(StringUtils.equals(notifications.get(0).getReceiver(), "gyq"));
System.out.println(notifications.get(0).getContent());
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getCaseId(), "xiaomeinvGTestOne"));
Assertions.assertTrue(StringUtils.isBlank(functionalCaseComment.getNotifier()));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getContent(), "评论你好"));
@ -288,13 +232,6 @@ public class FunctionalCaseCommentControllerTests {
functionalCaseCommentRequest.setParentId(functionalCaseComment1.getId());
functionalCaseCommentRequest.setEvent(NoticeConstants.Event.REPLY);
FunctionalCaseComment functionalCaseComment = getFunctionalCaseComment(functionalCaseCommentRequest,SAVE_URL);
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTestOne").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
Assertions.assertFalse(notifications.isEmpty());
System.out.println(JSON.toJSONString(notifications));
Assertions.assertTrue(StringUtils.equals(notifications.get(0).getReceiver(), "gyq"));
System.out.println(notifications.get(0).getContent());
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getCaseId(), "xiaomeinvGTestOne"));
Assertions.assertTrue(StringUtils.isBlank(functionalCaseComment.getNotifier()));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getContent(), "评论你好"));
@ -309,10 +246,6 @@ public class FunctionalCaseCommentControllerTests {
FunctionalCaseComment functionalCaseComment3 = getFunctionalCaseComment(functionalCaseCommentRequestUpdate,UPDATE_URL);
FunctionalCaseComment functionalCaseComment4 = functionalCaseCommentMapper.selectByPrimaryKey(functionalCaseComment3.getId());
Assertions.assertTrue(StringUtils.equals(functionalCaseComment4.getContent(), "更新回复评论你好"));
notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTestOne").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notificationUpdate = notificationMapper.selectByExampleWithBLOBs(notificationExample);
Assertions.assertEquals(notifications.size(), notificationUpdate.size());
FunctionalCaseCommentRequest functionalCaseCommentRequestUpdate2 = new FunctionalCaseCommentRequest();
functionalCaseCommentRequestUpdate2.setId(functionalCaseComment2.getId());
functionalCaseCommentRequestUpdate2.setCaseId(functionalCaseComment2.getCaseId());
@ -324,11 +257,6 @@ public class FunctionalCaseCommentControllerTests {
FunctionalCaseComment functionalCaseComment5 = getFunctionalCaseComment(functionalCaseCommentRequestUpdate2,UPDATE_URL);
FunctionalCaseComment functionalCaseComment6 = functionalCaseCommentMapper.selectByPrimaryKey(functionalCaseComment5.getId());
Assertions.assertTrue(StringUtils.equals(functionalCaseComment6.getContent(), "更新回复评论你好@"));
notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTestOne").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notificationUpdate2 = notificationMapper.selectByExampleWithBLOBs(notificationExample);
System.out.println(JSON.toJSONString(notificationUpdate2));
Assertions.assertTrue(notifications.size()<notificationUpdate2.size());
}
@Test
@ -371,14 +299,6 @@ public class FunctionalCaseCommentControllerTests {
functionalCaseCommentRequest.setParentId(functionalCaseComment1.getId());
functionalCaseCommentRequest.setEvent(NoticeConstants.Event.REPLY);
FunctionalCaseComment functionalCaseComment = getFunctionalCaseComment(functionalCaseCommentRequest,SAVE_URL);
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTest").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK).andReceiverEqualTo("default-project-member-user-guo-2");
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
System.out.println(JSON.toJSONString(notifications));
Assertions.assertFalse(notifications.isEmpty());
System.out.println(JSON.toJSONString(notifications));
Assertions.assertTrue(StringUtils.equals(notifications.get(0).getReceiver(), "default-project-member-user-guo-2"));
System.out.println(notifications.get(0).getContent());
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getCaseId(), "xiaomeinvGTest"));
Assertions.assertTrue(StringUtils.isNotBlank(functionalCaseComment.getNotifier()));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getContent(), "评论你好"));
@ -441,12 +361,6 @@ public class FunctionalCaseCommentControllerTests {
functionalCaseCommentRequest.setReplyUser("default-project-member-user-guo");
functionalCaseCommentRequest.setParentId(functionalCaseComment1.getId());
FunctionalCaseComment functionalCaseComment = getFunctionalCaseComment(functionalCaseCommentRequest,SAVE_URL);
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTest").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
Assertions.assertFalse(notifications.isEmpty());
// Assertions.assertTrue(StringUtils.equals(notifications.get(0).getReceiver(), "default-project-member-user-guo-1"));
System.out.println(JSON.toJSONString(notifications));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getCaseId(), "xiaomeinvGTest"));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getNotifier(), "default-project-member-user-guo-3;default-project-member-user-guo-4;"));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getContent(), "评论你好"));
@ -464,12 +378,6 @@ public class FunctionalCaseCommentControllerTests {
functionalCaseCommentRequest.setReplyUser("default-project-member-user-guo");
functionalCaseCommentRequest.setParentId(functionalCaseComment1.getId());
FunctionalCaseComment functionalCaseComment = getFunctionalCaseComment(functionalCaseCommentRequest,SAVE_URL);
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTest").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
Assertions.assertFalse(notifications.isEmpty());
// Assertions.assertTrue(StringUtils.equals(notifications.get(0).getReceiver(), "default-project-member-user-guo-1"));
System.out.println(JSON.toJSONString(notifications));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getCaseId(), "xiaomeinvGTest"));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getNotifier(), "default-project-member-user-guo;default-project-member-user-guo-4;"));
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getContent(), "评论你好哇"));

View File

@ -11,14 +11,10 @@ import io.metersphere.functional.mapper.CaseReviewMapper;
import io.metersphere.functional.request.BaseAssociateCaseRequest;
import io.metersphere.functional.request.CaseReviewRequest;
import io.metersphere.functional.request.ReviewFunctionalCaseRequest;
import io.metersphere.project.domain.Notification;
import io.metersphere.project.domain.NotificationExample;
import io.metersphere.project.mapper.NotificationMapper;
import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.notice.constants.NoticeConstants;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.junit.jupiter.api.*;
@ -53,8 +49,6 @@ public class ReviewFunctionalCaseControllerTests extends BaseTest {
@Resource
private CaseReviewHistoryMapper caseReviewHistoryMapper;
@Resource
private NotificationMapper notificationMapper;
@Resource
private CaseReviewFunctionalCaseMapper caseReviewFunctionalCaseMapper;
@ -110,14 +104,7 @@ public class ReviewFunctionalCaseControllerTests extends BaseTest {
Assertions.assertTrue(StringUtils.equalsIgnoreCase(caseReviewFunctionalCases.get(0).getStatus(),FunctionalCaseReviewStatus.UN_PASS.toString()));
caseReviews1 = getCaseReviews("创建用例评审1");
Assertions.assertTrue(StringUtils.equals(caseReviews1.get(0).getStatus(), CaseReviewStatus.COMPLETED.toString()));
NotificationExample notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceTypeEqualTo(NoticeConstants.TaskType.CASE_REVIEW_TASK);
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
Assertions.assertFalse(notifications.isEmpty());
notificationExample = new NotificationExample();
notificationExample.createCriteria().andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
Assertions.assertFalse(notifications.isEmpty());
}
@Test
@ -149,7 +136,7 @@ public class ReviewFunctionalCaseControllerTests extends BaseTest {
List<CaseReviewFunctionalCase> caseReviewFunctionalCases = caseReviewFunctionalCaseMapper.selectByExample(caseReviewFunctionalCaseExample);
Assertions.assertTrue(StringUtils.equalsIgnoreCase(caseReviewFunctionalCases.get(0).getStatus(),FunctionalCaseReviewStatus.UNDER_REVIEWED.toString()));
List<CaseReview> caseReviews1 = getCaseReviews("创建用例评审2");
Assertions.assertTrue(StringUtils.equals(caseReviews1.get(0).getStatus(), CaseReviewStatus.UNDERWAY.toString()));
Assertions.assertTrue(StringUtils.equals(caseReviews1.get(0).getStatus(), CaseReviewStatus.COMPLETED.toString()));
}
@Test

View File

@ -41,7 +41,7 @@ INSERT INTO functional_case_module(id, project_id, name, parent_id, pos, create_
INSERT INTO case_review_module(id, project_id, name, parent_id, pos, create_time, update_time, create_user, update_user)
VALUES ('CASE_REVIEW_REAL_MODULE_ID', 'project-gyq-case-review-test', '用例评审所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin'),
('CASE_REVIEW_REAL_MODULE_ID2', 'project-gyq-case-review-test', '用例评审所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin');
('CASE_REVIEW_REAL_MODULE_ID2', 'project-gyq-case-review-test', '用例评审所属模块1', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin');
INSERT INTO user(id, name, email, password, create_time, update_time, language, last_organization_id, phone, source,

View File

@ -85,7 +85,7 @@ VALUES('gyq_custom_id1', 'functional_priority', 'FUNCTIONAL', 'SELECT', '', 1, '
INSERT INTO custom_field(id, name, scene, `type`, remark, internal, scope_type, create_time, update_time, create_user, scope_id)
VALUES('gyq_custom_id2', 'level', 'FUNCTIONAL', 'SELECT', '', 1, 'ORGANIZATION', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'test_template_case_trash_id');
INSERT INTO functional_case_comment(id, case_id, create_user, status, parent_id, resource_id, notifier, content, reply_user, create_time, update_time)
VALUES ('trash_comment_id', 'Trash_TEST_FUNCTIONAL_CASE_ID', 'gyq', null, null, null, 'gyq','你好', null, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000);
INSERT INTO functional_case_comment(id, case_id, create_user, parent_id, resource_id, notifier, content, reply_user, create_time, update_time)
VALUES ('trash_comment_id', 'Trash_TEST_FUNCTIONAL_CASE_ID', 'gyq', null, null, 'gyq','你好', null, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000);
INSERT INTO functional_case_module(id, project_id, name, parent_id, pos, create_time, update_time, create_user, update_user) VALUES ('Trash_TEST_MOUDLE_ID', '100001100001', '测试回收站所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin');

View File

@ -7,9 +7,13 @@ VALUES ('wx_case_id_2', 101, 'TEST_MODULE_ID', 'wx_test_project', '100001', '测
INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time)
VALUES ('gyq_case_id_3', 102, 'TEST_MODULE_ID', 'wx_test_project', '100001', '测试多版本', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'TEST_REF_ID', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL);
INSERT INTO functional_case(id, num, module_id, project_id, template_id, name, review_status, tags, case_edit_type, pos, version_id, ref_id, last_execute_result, deleted, public_case, latest, create_user, update_user, delete_user, create_time, update_time, delete_time)
VALUES ('gyq_case_id_4', 102, 'TEST_MODULE_ID', 'wx_test_project', '100001', '测试多版本', 'UN_REVIEWED', '["测试标签_1"]', 'STEP', 0, 'v1.0.0', 'gyq_case_id_4', 'UN_EXECUTED', b'0', b'0', b'1', 'admin', 'admin', '', 1698058347559, 1698058347559, NULL);
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('wx_case_id_1', 'STEP', '1111', '', '', 'TEST');
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('wx_case_id_2', 'STEP', '1111', '', '', '1111');
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('gyq_case_id_3', 'STEP', '1111', '', '', '1111');
INSERT INTO functional_case_blob(id, steps, text_description, expected_result, prerequisite, description) VALUES ('gyq_case_id_4', 'STEP', '1111', '', '', '1111');
@ -26,7 +30,15 @@ VALUES ('wx_review_id_1',10001,'wx1', 'wx_module_1', 'wx_test_project', 'COMPLET
INSERT INTO case_review_functional_case(id, review_id, case_id, status, create_time, create_user, update_time, pos)
VALUES ('wx_test_1', 'wx_review_id_1', 'wx_case_id_1', 'PASS', 1698058347559,'admin',1698058347559, 1000),
('gyq_test_3', 'wx_review_id_1', 'gyq_case_id_3', 'PASS', 1698058347559,'admin',1698058347559, 1500),
('gyq_test_4', 'wx_review_id_1', 'gyq_case_id_4', 'PASS', 1698058347559,'admin',1698058347559, 2000),
('wx_test_2', 'wx_review_id_2', 'wx_case_id_2', 'PASS', 1698058347559,'admin',1698058347559, 3000);
INSERT INTO case_review_functional_case_user(case_id, review_id, user_id)
VALUES ('wx_case_id_1', 'wx_review_id_1', 'admin'),
('wx_case_id_1', 'wx_review_id_1', 'gyq'),
('gyq_case_id_3', 'wx_review_id_1', 'gyq'),
('gyq_case_id_4', 'wx_review_id_1', 'gyq');
INSERT INTO functional_case_module(id, project_id, name, parent_id, pos, create_time, update_time, create_user, update_user) VALUES ('wx_module_1', 'wx_test_project', '测试所属模块', 'NONE', 0, 1669174143999, 1669174143999, 'admin', 'admin');