feat(功能用例): 新增用例创建评论功能
This commit is contained in:
parent
34f970fdb2
commit
683d4fb729
|
@ -1,81 +1,90 @@
|
|||
package io.metersphere.project.domain;
|
||||
|
||||
import io.metersphere.validation.groups.*;
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.metersphere.validation.groups.Updated;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class Notification implements Serializable {
|
||||
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{notification.id.not_blank}", groups = {Updated.class})
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "通知类型", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "通知类型", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{notification.type.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 30, message = "{notification.type.length_range}", groups = {Created.class, Updated.class})
|
||||
private String type;
|
||||
|
||||
@Schema(description = "接收人", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "接收人", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{notification.receiver.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{notification.receiver.length_range}", groups = {Created.class, Updated.class})
|
||||
private String receiver;
|
||||
|
||||
@Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{notification.title.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 255, message = "{notification.title.length_range}", groups = {Created.class, Updated.class})
|
||||
private String title;
|
||||
@Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{notification.subject.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 255, message = "{notification.subject.length_range}", groups = {Created.class, Updated.class})
|
||||
private String subject;
|
||||
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{notification.status.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 30, message = "{notification.status.length_range}", groups = {Created.class, Updated.class})
|
||||
private String status;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@Schema(description = "创建时间")
|
||||
private Long createTime;
|
||||
|
||||
@Schema(description = "操作人", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "操作人", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{notification.operator.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{notification.operator.length_range}", groups = {Created.class, Updated.class})
|
||||
private String operator;
|
||||
|
||||
@Schema(description = "操作", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "操作", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{notification.operation.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{notification.operation.length_range}", groups = {Created.class, Updated.class})
|
||||
private String operation;
|
||||
|
||||
@Schema(description = "资源ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "资源ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{notification.resource_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{notification.resource_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String resourceId;
|
||||
|
||||
@Schema(description = "资源类型", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "资源类型", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{notification.resource_type.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{notification.resource_type.length_range}", groups = {Created.class, Updated.class})
|
||||
private String resourceType;
|
||||
|
||||
@Schema(description = "资源名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "资源名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{notification.resource_name.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 255, message = "{notification.resource_name.length_range}", groups = {Created.class, Updated.class})
|
||||
private String resourceName;
|
||||
|
||||
@Schema(description = "通知内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{notification.content.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 65535, message = "{notification.content.length_range}", groups = {Created.class, Updated.class})
|
||||
private String content;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public enum Column {
|
||||
id("id", "id", "BIGINT", false),
|
||||
type("type", "type", "VARCHAR", true),
|
||||
receiver("receiver", "receiver", "VARCHAR", false),
|
||||
title("title", "title", "VARCHAR", false),
|
||||
subject("subject", "subject", "VARCHAR", false),
|
||||
status("status", "status", "VARCHAR", true),
|
||||
createTime("create_time", "createTime", "BIGINT", false),
|
||||
operator("operator", "operator", "VARCHAR", true),
|
||||
operation("operation", "operation", "VARCHAR", true),
|
||||
resourceId("resource_id", "resourceId", "VARCHAR", false),
|
||||
resourceType("resource_type", "resourceType", "VARCHAR", false),
|
||||
resourceName("resource_name", "resourceName", "VARCHAR", false);
|
||||
resourceName("resource_name", "resourceName", "VARCHAR", false),
|
||||
content("content", "content", "LONGVARCHAR", false);
|
||||
|
||||
private static final String BEGINNING_DELIMITER = "`";
|
||||
|
||||
|
|
|
@ -304,73 +304,73 @@ public class NotificationExample {
|
|||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleIsNull() {
|
||||
addCriterion("title is null");
|
||||
public Criteria andSubjectIsNull() {
|
||||
addCriterion("subject is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleIsNotNull() {
|
||||
addCriterion("title is not null");
|
||||
public Criteria andSubjectIsNotNull() {
|
||||
addCriterion("subject is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleEqualTo(String value) {
|
||||
addCriterion("title =", value, "title");
|
||||
public Criteria andSubjectEqualTo(String value) {
|
||||
addCriterion("subject =", value, "subject");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleNotEqualTo(String value) {
|
||||
addCriterion("title <>", value, "title");
|
||||
public Criteria andSubjectNotEqualTo(String value) {
|
||||
addCriterion("subject <>", value, "subject");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleGreaterThan(String value) {
|
||||
addCriterion("title >", value, "title");
|
||||
public Criteria andSubjectGreaterThan(String value) {
|
||||
addCriterion("subject >", value, "subject");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("title >=", value, "title");
|
||||
public Criteria andSubjectGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("subject >=", value, "subject");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleLessThan(String value) {
|
||||
addCriterion("title <", value, "title");
|
||||
public Criteria andSubjectLessThan(String value) {
|
||||
addCriterion("subject <", value, "subject");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleLessThanOrEqualTo(String value) {
|
||||
addCriterion("title <=", value, "title");
|
||||
public Criteria andSubjectLessThanOrEqualTo(String value) {
|
||||
addCriterion("subject <=", value, "subject");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleLike(String value) {
|
||||
addCriterion("title like", value, "title");
|
||||
public Criteria andSubjectLike(String value) {
|
||||
addCriterion("subject like", value, "subject");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleNotLike(String value) {
|
||||
addCriterion("title not like", value, "title");
|
||||
public Criteria andSubjectNotLike(String value) {
|
||||
addCriterion("subject not like", value, "subject");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleIn(List<String> values) {
|
||||
addCriterion("title in", values, "title");
|
||||
public Criteria andSubjectIn(List<String> values) {
|
||||
addCriterion("subject in", values, "subject");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleNotIn(List<String> values) {
|
||||
addCriterion("title not in", values, "title");
|
||||
public Criteria andSubjectNotIn(List<String> values) {
|
||||
addCriterion("subject not in", values, "subject");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleBetween(String value1, String value2) {
|
||||
addCriterion("title between", value1, value2, "title");
|
||||
public Criteria andSubjectBetween(String value1, String value2) {
|
||||
addCriterion("subject between", value1, value2, "subject");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andTitleNotBetween(String value1, String value2) {
|
||||
addCriterion("title not between", value1, value2, "title");
|
||||
public Criteria andSubjectNotBetween(String value1, String value2) {
|
||||
addCriterion("subject not between", value1, value2, "subject");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,16 +16,22 @@ public interface NotificationMapper {
|
|||
|
||||
int insertSelective(Notification record);
|
||||
|
||||
List<Notification> selectByExampleWithBLOBs(NotificationExample example);
|
||||
|
||||
List<Notification> selectByExample(NotificationExample example);
|
||||
|
||||
Notification selectByPrimaryKey(Long id);
|
||||
|
||||
int updateByExampleSelective(@Param("record") Notification record, @Param("example") NotificationExample example);
|
||||
|
||||
int updateByExampleWithBLOBs(@Param("record") Notification record, @Param("example") NotificationExample example);
|
||||
|
||||
int updateByExample(@Param("record") Notification record, @Param("example") NotificationExample example);
|
||||
|
||||
int updateByPrimaryKeySelective(Notification record);
|
||||
|
||||
int updateByPrimaryKeyWithBLOBs(Notification record);
|
||||
|
||||
int updateByPrimaryKey(Notification record);
|
||||
|
||||
int batchInsert(@Param("list") List<Notification> list);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<id column="id" jdbcType="BIGINT" property="id" />
|
||||
<result column="type" jdbcType="VARCHAR" property="type" />
|
||||
<result column="receiver" jdbcType="VARCHAR" property="receiver" />
|
||||
<result column="title" jdbcType="VARCHAR" property="title" />
|
||||
<result column="subject" jdbcType="VARCHAR" property="subject" />
|
||||
<result column="status" jdbcType="VARCHAR" property="status" />
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||
<result column="operator" jdbcType="VARCHAR" property="operator" />
|
||||
|
@ -14,6 +14,9 @@
|
|||
<result column="resource_type" jdbcType="VARCHAR" property="resourceType" />
|
||||
<result column="resource_name" jdbcType="VARCHAR" property="resourceName" />
|
||||
</resultMap>
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.project.domain.Notification">
|
||||
<result column="content" jdbcType="LONGVARCHAR" property="content" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="oredCriteria" item="criteria" separator="or">
|
||||
|
@ -73,9 +76,28 @@
|
|||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, `type`, receiver, title, `status`, create_time, `operator`, `operation`, resource_id,
|
||||
id, `type`, receiver, subject, `status`, create_time, `operator`, `operation`, resource_id,
|
||||
resource_type, resource_name
|
||||
</sql>
|
||||
<sql id="Blob_Column_List">
|
||||
content
|
||||
</sql>
|
||||
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.project.domain.NotificationExample" resultMap="ResultMapWithBLOBs">
|
||||
select
|
||||
<if test="distinct">
|
||||
distinct
|
||||
</if>
|
||||
<include refid="Base_Column_List" />
|
||||
,
|
||||
<include refid="Blob_Column_List" />
|
||||
from notification
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
<if test="orderByClause != null">
|
||||
order by ${orderByClause}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByExample" parameterType="io.metersphere.project.domain.NotificationExample" resultMap="BaseResultMap">
|
||||
select
|
||||
<if test="distinct">
|
||||
|
@ -90,9 +112,11 @@
|
|||
order by ${orderByClause}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
|
||||
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="ResultMapWithBLOBs">
|
||||
select
|
||||
<include refid="Base_Column_List" />
|
||||
,
|
||||
<include refid="Blob_Column_List" />
|
||||
from notification
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</select>
|
||||
|
@ -108,13 +132,15 @@
|
|||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.project.domain.Notification">
|
||||
insert into notification (id, `type`, receiver,
|
||||
title, `status`, create_time,
|
||||
subject, `status`, create_time,
|
||||
`operator`, `operation`, resource_id,
|
||||
resource_type, resource_name)
|
||||
resource_type, resource_name, content
|
||||
)
|
||||
values (#{id,jdbcType=BIGINT}, #{type,jdbcType=VARCHAR}, #{receiver,jdbcType=VARCHAR},
|
||||
#{title,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
|
||||
#{subject,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
|
||||
#{operator,jdbcType=VARCHAR}, #{operation,jdbcType=VARCHAR}, #{resourceId,jdbcType=VARCHAR},
|
||||
#{resourceType,jdbcType=VARCHAR}, #{resourceName,jdbcType=VARCHAR})
|
||||
#{resourceType,jdbcType=VARCHAR}, #{resourceName,jdbcType=VARCHAR}, #{content,jdbcType=LONGVARCHAR}
|
||||
)
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.project.domain.Notification">
|
||||
insert into notification
|
||||
|
@ -128,8 +154,8 @@
|
|||
<if test="receiver != null">
|
||||
receiver,
|
||||
</if>
|
||||
<if test="title != null">
|
||||
title,
|
||||
<if test="subject != null">
|
||||
subject,
|
||||
</if>
|
||||
<if test="status != null">
|
||||
`status`,
|
||||
|
@ -152,6 +178,9 @@
|
|||
<if test="resourceName != null">
|
||||
resource_name,
|
||||
</if>
|
||||
<if test="content != null">
|
||||
content,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -163,8 +192,8 @@
|
|||
<if test="receiver != null">
|
||||
#{receiver,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="title != null">
|
||||
#{title,jdbcType=VARCHAR},
|
||||
<if test="subject != null">
|
||||
#{subject,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="status != null">
|
||||
#{status,jdbcType=VARCHAR},
|
||||
|
@ -187,6 +216,9 @@
|
|||
<if test="resourceName != null">
|
||||
#{resourceName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="content != null">
|
||||
#{content,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.project.domain.NotificationExample" resultType="java.lang.Long">
|
||||
|
@ -207,8 +239,8 @@
|
|||
<if test="record.receiver != null">
|
||||
receiver = #{record.receiver,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.title != null">
|
||||
title = #{record.title,jdbcType=VARCHAR},
|
||||
<if test="record.subject != null">
|
||||
subject = #{record.subject,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.status != null">
|
||||
`status` = #{record.status,jdbcType=VARCHAR},
|
||||
|
@ -231,17 +263,38 @@
|
|||
<if test="record.resourceName != null">
|
||||
resource_name = #{record.resourceName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.content != null">
|
||||
content = #{record.content,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByExampleWithBLOBs" parameterType="map">
|
||||
update notification
|
||||
set id = #{record.id,jdbcType=BIGINT},
|
||||
`type` = #{record.type,jdbcType=VARCHAR},
|
||||
receiver = #{record.receiver,jdbcType=VARCHAR},
|
||||
subject = #{record.subject,jdbcType=VARCHAR},
|
||||
`status` = #{record.status,jdbcType=VARCHAR},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
`operator` = #{record.operator,jdbcType=VARCHAR},
|
||||
`operation` = #{record.operation,jdbcType=VARCHAR},
|
||||
resource_id = #{record.resourceId,jdbcType=VARCHAR},
|
||||
resource_type = #{record.resourceType,jdbcType=VARCHAR},
|
||||
resource_name = #{record.resourceName,jdbcType=VARCHAR},
|
||||
content = #{record.content,jdbcType=LONGVARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByExample" parameterType="map">
|
||||
update notification
|
||||
set id = #{record.id,jdbcType=BIGINT},
|
||||
`type` = #{record.type,jdbcType=VARCHAR},
|
||||
receiver = #{record.receiver,jdbcType=VARCHAR},
|
||||
title = #{record.title,jdbcType=VARCHAR},
|
||||
subject = #{record.subject,jdbcType=VARCHAR},
|
||||
`status` = #{record.status,jdbcType=VARCHAR},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
`operator` = #{record.operator,jdbcType=VARCHAR},
|
||||
|
@ -262,8 +315,8 @@
|
|||
<if test="receiver != null">
|
||||
receiver = #{receiver,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="title != null">
|
||||
title = #{title,jdbcType=VARCHAR},
|
||||
<if test="subject != null">
|
||||
subject = #{subject,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="status != null">
|
||||
`status` = #{status,jdbcType=VARCHAR},
|
||||
|
@ -286,14 +339,32 @@
|
|||
<if test="resourceName != null">
|
||||
resource_name = #{resourceName,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="content != null">
|
||||
content = #{content,jdbcType=LONGVARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</update>
|
||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.project.domain.Notification">
|
||||
update notification
|
||||
set `type` = #{type,jdbcType=VARCHAR},
|
||||
receiver = #{receiver,jdbcType=VARCHAR},
|
||||
subject = #{subject,jdbcType=VARCHAR},
|
||||
`status` = #{status,jdbcType=VARCHAR},
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
`operator` = #{operator,jdbcType=VARCHAR},
|
||||
`operation` = #{operation,jdbcType=VARCHAR},
|
||||
resource_id = #{resourceId,jdbcType=VARCHAR},
|
||||
resource_type = #{resourceType,jdbcType=VARCHAR},
|
||||
resource_name = #{resourceName,jdbcType=VARCHAR},
|
||||
content = #{content,jdbcType=LONGVARCHAR}
|
||||
where id = #{id,jdbcType=BIGINT}
|
||||
</update>
|
||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.project.domain.Notification">
|
||||
update notification
|
||||
set `type` = #{type,jdbcType=VARCHAR},
|
||||
receiver = #{receiver,jdbcType=VARCHAR},
|
||||
title = #{title,jdbcType=VARCHAR},
|
||||
subject = #{subject,jdbcType=VARCHAR},
|
||||
`status` = #{status,jdbcType=VARCHAR},
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
`operator` = #{operator,jdbcType=VARCHAR},
|
||||
|
@ -305,14 +376,15 @@
|
|||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into notification
|
||||
(id, `type`, receiver, title, `status`, create_time, `operator`, `operation`, resource_id,
|
||||
resource_type, resource_name)
|
||||
(id, `type`, receiver, subject, `status`, create_time, `operator`, `operation`, resource_id,
|
||||
resource_type, resource_name, content)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.id,jdbcType=BIGINT}, #{item.type,jdbcType=VARCHAR}, #{item.receiver,jdbcType=VARCHAR},
|
||||
#{item.title,jdbcType=VARCHAR}, #{item.status,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT},
|
||||
#{item.subject,jdbcType=VARCHAR}, #{item.status,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT},
|
||||
#{item.operator,jdbcType=VARCHAR}, #{item.operation,jdbcType=VARCHAR}, #{item.resourceId,jdbcType=VARCHAR},
|
||||
#{item.resourceType,jdbcType=VARCHAR}, #{item.resourceName,jdbcType=VARCHAR})
|
||||
#{item.resourceType,jdbcType=VARCHAR}, #{item.resourceName,jdbcType=VARCHAR}, #{item.content,jdbcType=LONGVARCHAR}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
<insert id="batchInsertSelective" parameterType="map">
|
||||
|
@ -334,8 +406,8 @@
|
|||
<if test="'receiver'.toString() == column.value">
|
||||
#{item.receiver,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'title'.toString() == column.value">
|
||||
#{item.title,jdbcType=VARCHAR}
|
||||
<if test="'subject'.toString() == column.value">
|
||||
#{item.subject,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'status'.toString() == column.value">
|
||||
#{item.status,jdbcType=VARCHAR}
|
||||
|
@ -358,6 +430,9 @@
|
|||
<if test="'resource_name'.toString() == column.value">
|
||||
#{item.resourceName,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'content'.toString() == column.value">
|
||||
#{item.content,jdbcType=LONGVARCHAR}
|
||||
</if>
|
||||
</foreach>
|
||||
)
|
||||
</foreach>
|
||||
|
|
|
@ -271,29 +271,32 @@ CREATE TABLE IF NOT EXISTS message_task_blob
|
|||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT = '消息通知任务大字段';
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS notification
|
||||
(
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'ID',
|
||||
`type` VARCHAR(30) NOT NULL COMMENT '通知类型',
|
||||
`receiver` VARCHAR(50) NOT NULL COMMENT '接收人',
|
||||
`title` VARCHAR(255) NOT NULL COMMENT '标题',
|
||||
`status` VARCHAR(30) NOT NULL COMMENT '状态',
|
||||
`create_time` BIGINT NOT NULL COMMENT '创建时间',
|
||||
`operator` VARCHAR(50) NOT NULL COMMENT '操作人',
|
||||
`operation` VARCHAR(50) NOT NULL COMMENT '操作',
|
||||
`resource_id` VARCHAR(50) NOT NULL COMMENT '资源ID',
|
||||
`resource_type` VARCHAR(50) NOT NULL COMMENT '资源类型',
|
||||
`resource_name` VARCHAR(255) NOT NULL COMMENT '资源名称',
|
||||
PRIMARY KEY (id)
|
||||
CREATE TABLE IF NOT EXISTS notification(
|
||||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'ID' ,
|
||||
`type` VARCHAR(30) NOT NULL COMMENT '通知类型' ,
|
||||
`receiver` VARCHAR(50) NOT NULL COMMENT '接收人' ,
|
||||
`subject` VARCHAR(255) NOT NULL COMMENT '标题' ,
|
||||
`status` VARCHAR(30) NOT NULL COMMENT '状态' ,
|
||||
`create_time` BIGINT NOT NULL COMMENT '创建时间' ,
|
||||
`operator` VARCHAR(50) NOT NULL COMMENT '操作人' ,
|
||||
`operation` VARCHAR(50) NOT NULL COMMENT '操作' ,
|
||||
`resource_id` VARCHAR(50) NOT NULL COMMENT '资源ID' ,
|
||||
`resource_type` VARCHAR(50) NOT NULL COMMENT '资源类型' ,
|
||||
`resource_name` VARCHAR(255) NOT NULL COMMENT '资源名称' ,
|
||||
`content` TEXT NOT NULL COMMENT '通知内容' ,
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT = '消息通知';
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci
|
||||
COMMENT = '消息通知';
|
||||
|
||||
|
||||
CREATE INDEX idx_receiver ON notification (`receiver`);
|
||||
CREATE INDEX idx_receiver_type ON notification (`receiver`, `type`);
|
||||
CREATE INDEX idx_notification_create_time ON notification (`create_time`);
|
||||
CREATE INDEX idx_receiver ON notification(receiver);
|
||||
CREATE INDEX idx_create_time ON notification(create_time);
|
||||
CREATE INDEX idx_subject ON notification(subject);
|
||||
CREATE INDEX idx_resource_id ON notification(resource_id);
|
||||
CREATE INDEX idx_resource_type ON notification(resource_type);
|
||||
CREATE INDEX idx_operator ON notification(operator);
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project_robot(
|
||||
|
|
|
@ -586,6 +586,38 @@ Insert into message_task(id, event, receiver, project_robot_id, task_type, test_
|
|||
VALUES (@schedule_close_id, 'CLOSE', 'CREATE_USER', @robot_in_site_id, 'SCHEDULE_TASK', 'NONE', '100001100001', false, 'admin', unix_timestamp() * 1000, 'admin', unix_timestamp() * 1000, true, true, 'message.title.schedule_task_close');
|
||||
INSERT INTO message_task_blob(id, template) VALUES (@schedule_close_id, 'message.schedule_task_close');
|
||||
|
||||
-- 初始化内部at 消息通知
|
||||
SET @case_comment_at_id = UUID_SHORT();
|
||||
Insert into message_task(id, event, receiver, project_robot_id, task_type, test_id, project_id, enable, create_user, create_time, update_user, update_time, use_default_template, use_default_subject, subject)
|
||||
VALUES (@case_comment_at_id, 'AT', 'NONE', @robot_in_site_id, 'FUNCTIONAL_CASE_TASK', 'NONE', '100001100001', true, 'admin', unix_timestamp() * 1000, 'admin', unix_timestamp() * 1000, true, true, 'message.title.functional_case_task_comment');
|
||||
INSERT INTO message_task_blob(id, template) VALUES (@case_comment_at_id, 'message.functional_case_task_at_comment');
|
||||
|
||||
SET @case_comment_reply_id = UUID_SHORT();
|
||||
Insert into message_task(id, event, receiver, project_robot_id, task_type, test_id, project_id, enable, create_user, create_time, update_user, update_time, use_default_template, use_default_subject, subject)
|
||||
VALUES (@case_comment_reply_id, 'REPLY', 'NONE', @robot_in_site_id, 'FUNCTIONAL_CASE_TASK', 'NONE', '100001100001', true, 'admin', unix_timestamp() * 1000, 'admin', unix_timestamp() * 1000, true, true, 'message.title.functional_case_task_comment');
|
||||
INSERT INTO message_task_blob(id, template) VALUES (@case_comment_reply_id, 'message.functional_case_task_reply_comment');
|
||||
|
||||
SET @case_review_at_id = UUID_SHORT();
|
||||
Insert into message_task(id, event, receiver, project_robot_id, task_type, test_id, project_id, enable, create_user, create_time, update_user, update_time, use_default_template, use_default_subject, subject)
|
||||
VALUES (@case_review_at_id, 'REVIEW_AT', 'NONE', @robot_in_site_id, 'FUNCTIONAL_CASE_TASK', 'NONE', '100001100001', true, 'admin', unix_timestamp() * 1000, 'admin', unix_timestamp() * 1000, true, true, 'message.title.functional_case_task_review_at');
|
||||
INSERT INTO message_task_blob(id, template) VALUES (@case_review_at_id, 'message.functional_case_task_review_at');
|
||||
|
||||
SET @case_plan_at_id = UUID_SHORT();
|
||||
Insert into message_task(id, event, receiver, project_robot_id, task_type, test_id, project_id, enable, create_user, create_time, update_user, update_time, use_default_template, use_default_subject, subject)
|
||||
VALUES (@case_plan_at_id, 'EXECUTE_AT', 'NONE', @robot_in_site_id, 'FUNCTIONAL_CASE_TASK', 'NONE', '100001100001', true, 'admin', unix_timestamp() * 1000, 'admin', unix_timestamp() * 1000, true, true, 'message.title.functional_case_task_execute_at');
|
||||
INSERT INTO message_task_blob(id, template) VALUES (@case_plan_at_id, 'message.functional_case_task_plan_at');
|
||||
|
||||
SET @bug_comment_at_id = UUID_SHORT();
|
||||
Insert into message_task(id, event, receiver, project_robot_id, task_type, test_id, project_id, enable, create_user, create_time, update_user, update_time, use_default_template, use_default_subject, subject)
|
||||
VALUES (@bug_comment_at_id, 'AT', 'NONE', @robot_in_site_id, 'BUG_TASK', 'NONE', '100001100001', true, 'admin', unix_timestamp() * 1000, 'admin', unix_timestamp() * 1000, true, true, 'message.title.bug_task_comment');
|
||||
INSERT INTO message_task_blob(id, template) VALUES (@bug_comment_at_id, 'message.bug_task_at_comment');
|
||||
|
||||
SET @bug_comment_reply_id = UUID_SHORT();
|
||||
Insert into message_task(id, event, receiver, project_robot_id, task_type, test_id, project_id, enable, create_user, create_time, update_user, update_time, use_default_template, use_default_subject, subject)
|
||||
VALUES (@bug_comment_reply_id, 'REPLY', 'NONE', @robot_in_site_id, 'BUG_TASK', 'NONE', '100001100001', true, 'admin', unix_timestamp() * 1000, 'admin', unix_timestamp() * 1000, true, true, 'message.title.bug_task_comment');
|
||||
INSERT INTO message_task_blob(id, template) VALUES (@bug_comment_reply_id, 'message.bug_task_reply_comment');
|
||||
|
||||
|
||||
|
||||
-- 初始化定时任务数据
|
||||
INSERT INTO schedule(`id`, `key`, `type`, `value`, `job`, `enable`, `resource_id`, `create_user`, `create_time`, `update_time`, `project_id`, `name`, `config`)
|
||||
|
|
|
@ -212,5 +212,7 @@ public class PermissionConstants {
|
|||
|
||||
/*------ start: FUNCTIONAL_CASE ------*/
|
||||
public static final String FUNCTIONAL_CASE_READ_ADD = "FUNCTIONAL_CASE:READ+ADD";
|
||||
public static final String FUNCTIONAL_CASE_COMMENT_READ_ADD = "FUNCTIONAL_CASE_COMMENT:READ+ADD";
|
||||
|
||||
/*------ end: FUNCTIONAL_CASE ------*/
|
||||
}
|
||||
|
|
|
@ -118,4 +118,6 @@ case_review_follow.review_id.not_blank=评审ID不能为空
|
|||
case_review_follow.follow_id.not_blank=关注人不能为空
|
||||
#module:CustomFieldTestCase
|
||||
custom_field_test_case.resource_id.not_blank=资源ID不能为空
|
||||
custom_field_test_case.field_id.not_blank=字段ID不能为空
|
||||
custom_field_test_case.field_id.not_blank=字段ID不能为空
|
||||
#comment
|
||||
case_comment.case_is_null=功能用例不存在
|
|
@ -135,4 +135,6 @@ case_review_follow.follow_id.not_blank=follower cannot be empty
|
|||
#module:CustomFieldTestCase
|
||||
custom_field_test_case.resource_id.not_blank=Resource ID cannot be empty
|
||||
custom_field_test_case.field_id.not_blank=Field ID cannot be empty
|
||||
default_template_not_found=Default template not found
|
||||
default_template_not_found=Default template not found
|
||||
#comment
|
||||
case_comment.case_is_null=Function use case does not exist
|
|
@ -135,4 +135,6 @@ case_review_follow.follow_id.not_blank=关注人不能为空
|
|||
#module:CustomFieldTestCase
|
||||
custom_field_test_case.resource_id.not_blank=资源ID不能为空
|
||||
custom_field_test_case.field_id.not_blank=字段ID不能为空
|
||||
default_template_not_found=默认模板不存在
|
||||
default_template_not_found=默认模板不存在
|
||||
#comment
|
||||
case_comment.case_is_null=功能用例不存在
|
|
@ -135,4 +135,6 @@ case_review_follow.follow_id.not_blank=關注人不能為空
|
|||
#module:CustomFieldTestCase
|
||||
custom_field_test_case.resource_id.not_blank=資源ID不能為空
|
||||
custom_field_test_case.field_id.not_blank=字段ID不能為空
|
||||
default_template_not_found=默認模板不存在
|
||||
default_template_not_found=默認模板不存在
|
||||
#comment
|
||||
case_comment.case_is_null=功能用例不存在
|
|
@ -0,0 +1,37 @@
|
|||
package io.metersphere.functional.controller;
|
||||
|
||||
import io.metersphere.functional.domain.FunctionalCaseComment;
|
||||
import io.metersphere.functional.request.FunctionalCaseCommentRequest;
|
||||
import io.metersphere.functional.service.FunctionalCaseCommentService;
|
||||
import io.metersphere.functional.service.FunctionalCaseNoticeService;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.system.notice.annotation.SendNotice;
|
||||
import io.metersphere.system.notice.constants.NoticeConstants;
|
||||
import io.metersphere.system.utils.SessionUtils;
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Tag(name = "用例管理-功能用例-用例评论")
|
||||
@RestController
|
||||
@RequestMapping("/functional/case/comment")
|
||||
public class FunctionalCaseCommentController {
|
||||
|
||||
@Resource
|
||||
private FunctionalCaseCommentService functionalCaseCommentService;
|
||||
|
||||
@PostMapping("/save")
|
||||
@Operation(summary = "用例管理-功能用例-用例评论-创建评论")
|
||||
@RequiresPermissions(PermissionConstants.FUNCTIONAL_CASE_COMMENT_READ_ADD)
|
||||
@SendNotice(taskType = NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK, event = NoticeConstants.Event.AT, target = "#targetClass.getRelatedUsers(#functionalCaseCommentRequest)", targetClass = FunctionalCaseNoticeService.class)
|
||||
public FunctionalCaseComment saveComment(@Validated({Created.class}) @RequestBody FunctionalCaseCommentRequest functionalCaseCommentRequest) {
|
||||
return functionalCaseCommentService.saveComment(functionalCaseCommentRequest, SessionUtils.getUserId());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package io.metersphere.functional.dto;
|
||||
|
||||
public enum CommentEnum {
|
||||
CASE, TEST_PLAN, CASE_REVIEW
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package io.metersphere.functional.dto;
|
||||
|
||||
import io.metersphere.functional.domain.FunctionalCase;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FunctionalCaseDTO extends FunctionalCase {
|
||||
|
||||
@Schema(description = "评论@的人, 多个以';'隔开")
|
||||
private String relatedUsers;
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package io.metersphere.functional.request;
|
||||
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class FunctionalCaseCommentRequest {
|
||||
|
||||
@Schema(description = "功能用例ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{functional_case_comment.case_id.not_blank}", groups = {Created.class})
|
||||
private String caseId;
|
||||
|
||||
@Schema(description = "评论@的人, 多个以';'隔开")
|
||||
private String notifier;
|
||||
|
||||
@Schema(description = "回复人")
|
||||
private String replyUser;
|
||||
|
||||
@Schema(description = "父评论ID")
|
||||
private String parentId;
|
||||
|
||||
@Schema(description = "内容", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{functional_case_comment.content.not_blank}", groups = {Created.class})
|
||||
private String content;
|
||||
|
||||
}
|
|
@ -1,7 +1,61 @@
|
|||
package io.metersphere.functional.service;
|
||||
|
||||
import io.metersphere.functional.domain.FunctionalCase;
|
||||
import io.metersphere.functional.domain.FunctionalCaseComment;
|
||||
import io.metersphere.functional.dto.CommentEnum;
|
||||
import io.metersphere.functional.mapper.FunctionalCaseCommentMapper;
|
||||
import io.metersphere.functional.mapper.FunctionalCaseMapper;
|
||||
import io.metersphere.functional.request.FunctionalCaseCommentRequest;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author guoyuqi
|
||||
*/
|
||||
|
||||
@Service
|
||||
public class FunctionalCaseCommentService {
|
||||
|
||||
@Resource
|
||||
private FunctionalCaseCommentMapper functionalCaseCommentMapper;
|
||||
|
||||
@Resource
|
||||
private FunctionalCaseMapper functionalCaseMapper;
|
||||
|
||||
/**
|
||||
* 新增评论
|
||||
* @param functionalCaseCommentRequest functionalCaseCommentDTO
|
||||
* @param userId 当前操作用户
|
||||
* @return FunctionalCaseComment
|
||||
*/
|
||||
public FunctionalCaseComment saveComment(FunctionalCaseCommentRequest functionalCaseCommentRequest, String userId) {
|
||||
checkCase(functionalCaseCommentRequest);
|
||||
FunctionalCaseComment functionalCaseComment = new FunctionalCaseComment();
|
||||
functionalCaseComment.setId(IDGenerator.nextStr());
|
||||
functionalCaseComment.setCaseId(functionalCaseCommentRequest.getCaseId());
|
||||
functionalCaseComment.setContent(functionalCaseCommentRequest.getContent());
|
||||
functionalCaseComment.setCreateUser(userId);
|
||||
functionalCaseComment.setCreateTime(System.currentTimeMillis());
|
||||
functionalCaseComment.setUpdateTime(System.currentTimeMillis());
|
||||
functionalCaseComment.setType(CommentEnum.CASE.toString());
|
||||
if (StringUtils.isNotBlank(functionalCaseCommentRequest.getNotifier())) {
|
||||
functionalCaseComment.setNotifier(functionalCaseCommentRequest.getNotifier());
|
||||
}
|
||||
if (StringUtils.isNotBlank(functionalCaseCommentRequest.getParentId())) {
|
||||
functionalCaseComment.setParentId(functionalCaseCommentRequest.getParentId());
|
||||
}
|
||||
functionalCaseCommentMapper.insert(functionalCaseComment);
|
||||
return functionalCaseComment;
|
||||
}
|
||||
|
||||
private void checkCase(FunctionalCaseCommentRequest functionalCaseCommentRequest) {
|
||||
FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(functionalCaseCommentRequest.getCaseId());
|
||||
if (functionalCase ==null) {
|
||||
throw new MSException(Translator.get("case_comment.case_is_null"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package io.metersphere.functional.service;
|
||||
|
||||
import io.metersphere.functional.domain.FunctionalCase;
|
||||
import io.metersphere.functional.dto.FunctionalCaseDTO;
|
||||
import io.metersphere.functional.mapper.FunctionalCaseMapper;
|
||||
import io.metersphere.functional.request.FunctionalCaseCommentRequest;
|
||||
import io.metersphere.sdk.util.BeanUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class FunctionalCaseNoticeService {
|
||||
|
||||
@Resource
|
||||
private FunctionalCaseMapper functionalCaseMapper;
|
||||
|
||||
public FunctionalCaseDTO getRelatedUsers(FunctionalCaseCommentRequest functionalCaseCommentRequest){
|
||||
FunctionalCase functionalCase = functionalCaseMapper.selectByPrimaryKey(functionalCaseCommentRequest.getCaseId());
|
||||
FunctionalCaseDTO functionalCaseDTO = new FunctionalCaseDTO();
|
||||
if (functionalCase!=null) {
|
||||
BeanUtils.copyBean(functionalCaseDTO,functionalCase);
|
||||
}
|
||||
functionalCaseDTO.setRelatedUsers(functionalCaseCommentRequest.getNotifier());
|
||||
return functionalCaseDTO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package io.metersphere.functional.controller;
|
||||
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
import io.metersphere.functional.domain.FunctionalCaseComment;
|
||||
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.SessionConstants;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.controller.handler.ResultHolder;
|
||||
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.junit.jupiter.api.*;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.jdbc.Sql;
|
||||
import org.springframework.test.context.jdbc.SqlConfig;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@AutoConfigureMockMvc
|
||||
public class FunctionalCaseCommentControllerTests {
|
||||
@Resource
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Resource
|
||||
private NotificationMapper notificationMapper;
|
||||
|
||||
public static final String SAVE_URL = "/functional/case/comment/save";
|
||||
|
||||
private static String sessionId;
|
||||
private static String csrfToken;
|
||||
private static String projectId = "100001100001";
|
||||
|
||||
@Test
|
||||
@Order(0)
|
||||
@Sql(scripts = {"/dml/init_case_comment.sql"}, config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED))
|
||||
public void login() throws Exception {
|
||||
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post("/login")
|
||||
.content("{\"username\":\"default-project-member-user-guo\",\"password\":\"metersphere\"}")
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
.andReturn();
|
||||
sessionId = JsonPath.read(mvcResult.getResponse().getContentAsString(), "$.data.sessionId");
|
||||
csrfToken = JsonPath.read(mvcResult.getResponse().getContentAsString(), "$.data.csrfToken");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
public void saveCommentSuccess() throws Exception {
|
||||
FunctionalCaseCommentRequest functionalCaseCommentRequest = new FunctionalCaseCommentRequest();
|
||||
functionalCaseCommentRequest.setCaseId("xiaomeinvGTest");
|
||||
functionalCaseCommentRequest.setNotifier("default-project-member-user-guo-1");
|
||||
functionalCaseCommentRequest.setContent("评论你好");
|
||||
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post(SAVE_URL).header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||
.header(SessionConstants.CSRF_TOKEN, csrfToken)
|
||||
.header(SessionConstants.CURRENT_PROJECT, projectId)
|
||||
.content(JSON.toJSONString(functionalCaseCommentRequest))
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn();
|
||||
String contentAsString = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(contentAsString, ResultHolder.class);
|
||||
FunctionalCaseComment functionalCaseComment = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), FunctionalCaseComment.class);
|
||||
NotificationExample notificationExample = new NotificationExample();
|
||||
notificationExample.createCriteria().andResourceIdEqualTo("xiaomeinvGTest").andResourceTypeEqualTo(NoticeConstants.TaskType.FUNCTIONAL_CASE_TASK);
|
||||
List<Notification> notifications = notificationMapper.selectByExampleWithBLOBs(notificationExample);
|
||||
Assertions.assertTrue(notifications.size() > 0);
|
||||
Assertions.assertTrue(StringUtils.equals(notifications.get(0).getReceiver(), "default-project-member-user-guo-1"));
|
||||
System.out.println(notifications.get(0).getContent());
|
||||
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getCaseId(), "xiaomeinvGTest"));
|
||||
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getNotifier(), "default-project-member-user-guo-1"));
|
||||
Assertions.assertTrue(StringUtils.equals(functionalCaseComment.getContent(), "评论你好"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
public void saveCommentFalse() throws Exception {
|
||||
FunctionalCaseCommentRequest functionalCaseCommentRequest = new FunctionalCaseCommentRequest();
|
||||
functionalCaseCommentRequest.setCaseId("xiaomeinvGTestNo");
|
||||
functionalCaseCommentRequest.setNotifier("default-project-member-user-guo-1");
|
||||
functionalCaseCommentRequest.setContent("评论你好");
|
||||
mockMvc.perform(MockMvcRequestBuilders.post(SAVE_URL).header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||
.header(SessionConstants.CSRF_TOKEN, csrfToken)
|
||||
.header(SessionConstants.CURRENT_PROJECT, projectId)
|
||||
.content(JSON.toJSONString(functionalCaseCommentRequest))
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().is5xxServerError())
|
||||
.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));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
public void saveCommentExcludeSelfSuccess() throws Exception {
|
||||
FunctionalCaseCommentRequest functionalCaseCommentRequest = new FunctionalCaseCommentRequest();
|
||||
functionalCaseCommentRequest.setCaseId("xiaomeinvGTest");
|
||||
functionalCaseCommentRequest.setNotifier("default-project-member-user-guo");
|
||||
functionalCaseCommentRequest.setContent("这个好");
|
||||
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.post(SAVE_URL).header(SessionConstants.HEADER_TOKEN, sessionId)
|
||||
.header(SessionConstants.CSRF_TOKEN, csrfToken)
|
||||
.header(SessionConstants.CURRENT_PROJECT, projectId)
|
||||
.content(JSON.toJSONString(functionalCaseCommentRequest))
|
||||
.contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON)).andReturn();
|
||||
String contentAsString = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(contentAsString, ResultHolder.class);
|
||||
FunctionalCaseComment functionalCaseComment = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), FunctionalCaseComment.class);
|
||||
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(), "这个好"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
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 ('xiaomeinvGTest', 1000001, 'test_guo', '100001100001', 'test_guo', '郭雨琦测试', 'UN_REVIEWED', null, 'text',
|
||||
10001, '111', 'xiaomeinvGTest', 'success', false, false, true, 'gyq', 'gyq', null, 1698058347559, 1698058347559,
|
||||
null);
|
||||
|
||||
|
||||
|
||||
INSERT INTO user(id, name, email, password, create_time, update_time, language, last_organization_id, phone, source,
|
||||
last_project_id, create_user, update_user, deleted)
|
||||
VALUES ('default-project-member-user-guo', 'default-project-member-user1', 'project-member-guo1@metersphere.io',
|
||||
MD5('metersphere'), UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin',
|
||||
'admin', 0),
|
||||
('default-project-member-user-guo-1', 'default-project-member-user2', 'project-member-guo2@metersphere.io',
|
||||
MD5('metersphere'), UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, NULL, NUll, '', 'LOCAL', NULL, 'admin',
|
||||
'admin', 0),
|
||||
('default-project-member-user-guo-del', 'default-project-member-userDel',
|
||||
'project-member-guo-del@metersphere.io', MD5('metersphere'), UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000,
|
||||
NULL, NUll, '', 'LOCAL', NULL, 'admin', 'admin', 1);
|
||||
|
||||
INSERT INTO user_role_relation (id, user_id, role_id, source_id, organization_id, create_time, create_user)
|
||||
VALUES (UUID(), 'default-project-member-user-guo', 'org_member', '100001', '100001', UNIX_TIMESTAMP() * 1000, 'admin'),
|
||||
(UUID(), 'default-project-member-user-guo-1', 'org_member', '100001', '100001', UNIX_TIMESTAMP() * 1000,
|
||||
'admin'),
|
||||
(UUID(), 'default-project-member-user-guo-del', 'org_member', '100001', '100001', UNIX_TIMESTAMP() * 1000,
|
||||
'admin');
|
||||
|
||||
INSERT INTO user_role_relation (id, user_id, role_id, source_id, organization_id, create_time, create_user)
|
||||
VALUES (UUID(), 'default-project-member-user-guo', 'project_admin', '100001100001', '100001', UNIX_TIMESTAMP() * 1000,
|
||||
'admin'),
|
||||
(UUID(), 'default-project-member-user-guo-1', 'project_admin', '100001100001', '100001', UNIX_TIMESTAMP() * 1000,
|
||||
'admin'),
|
||||
(UUID(), 'default-project-member-user-guo-del', 'project_admin', '100001100001', '100001',
|
||||
UNIX_TIMESTAMP() * 1000, 'admin');
|
||||
|
||||
INSERT INTO user_role_permission(id, role_id, permission_id)
|
||||
VALUES ('user_role_guo_permission1', 'project_admin', 'FUNCTIONAL_CASE_COMMENT:READ+ADD'),
|
||||
('user_role_guo_permission2', 'project_admin', 'FUNCTIONAL_CASE:READ+ADD');
|
||||
|
||||
|
|
@ -34,7 +34,4 @@ public @interface SendNotice {
|
|||
*/
|
||||
String context() default "";
|
||||
|
||||
String successContext() default "";
|
||||
|
||||
String failedContext() default "";
|
||||
}
|
||||
|
|
|
@ -137,19 +137,22 @@ public abstract class AbstractNoticeSender implements NoticeSender {
|
|||
default -> toUsers.add(new Receiver(userId, NotificationConstants.Type.MENTIONED_ME.name()));
|
||||
}
|
||||
//TODO:接口同步时通知的接收人特殊处理(v2接口同步的通知,v3这里待讨论)
|
||||
//处理评论人
|
||||
if (messageDetail.getTaskType().contains("AT_COMMENT")) {
|
||||
if (CollectionUtils.isNotEmpty(noticeModel.getRelatedUsers())) {
|
||||
for (String relatedUser : noticeModel.getRelatedUsers()) {
|
||||
toUsers.add(new Receiver(relatedUser, NotificationConstants.Type.MENTIONED_ME.name()));
|
||||
}
|
||||
|
||||
}
|
||||
//处理评论人
|
||||
if (event.contains(NoticeConstants.Event.AT) || event.contains(NoticeConstants.Event.REPLAY)) {
|
||||
if (CollectionUtils.isNotEmpty(noticeModel.getRelatedUsers())) {
|
||||
for (String relatedUser : noticeModel.getRelatedUsers()) {
|
||||
toUsers.add(new Receiver(relatedUser, NotificationConstants.Type.MENTIONED_ME.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 去重复
|
||||
return toUsers.stream()
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
List<String> userIds = toUsers.stream().map(Receiver::getUserId).distinct().toList();
|
||||
List<User> users = getUsers(userIds);
|
||||
List<String> realUserIds = users.stream().map(User::getId).toList();
|
||||
return toUsers.stream().filter(t -> realUserIds.contains(t.getUserId())).toList();
|
||||
}
|
||||
|
||||
private List<Receiver> handleFollows(MessageDetail messageDetail, NoticeModel noticeModel) {
|
||||
|
|
|
@ -3,8 +3,8 @@ package io.metersphere.system.notice.sender;
|
|||
|
||||
import io.metersphere.sdk.dto.BaseSystemConfigDTO;
|
||||
import io.metersphere.sdk.dto.SessionUser;
|
||||
import io.metersphere.system.notice.annotation.SendNotice;
|
||||
import io.metersphere.system.notice.NoticeModel;
|
||||
import io.metersphere.system.notice.annotation.SendNotice;
|
||||
import io.metersphere.system.notice.constants.NoticeConstants;
|
||||
import io.metersphere.system.notice.utils.MessageTemplateUtils;
|
||||
import io.metersphere.system.service.NoticeSendService;
|
||||
|
@ -14,9 +14,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
public class AfterReturningNoticeSendService {
|
||||
|
@ -45,6 +43,8 @@ public class AfterReturningNoticeSendService {
|
|||
|
||||
String subject = getSubject(sendNotice);
|
||||
|
||||
List<String> relatedUsers = getRelatedUsers(resource.get("relatedUsers"));
|
||||
|
||||
NoticeModel noticeModel = NoticeModel.builder()
|
||||
.operator(sessionUser.getId())
|
||||
.context(context)
|
||||
|
@ -53,16 +53,27 @@ public class AfterReturningNoticeSendService {
|
|||
.event(sendNotice.event())
|
||||
.status((String) paramMap.get("status"))
|
||||
.excludeSelf(true)
|
||||
.relatedUsers(relatedUsers)
|
||||
.build();
|
||||
noticeSendService.send(sendNotice.taskType(), noticeModel);
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getRelatedUsers(Object relatedUsers) {
|
||||
String relatedUser = (String) relatedUsers;
|
||||
List<String> relatedUserList = new ArrayList<>();
|
||||
if (StringUtils.isNotBlank(relatedUser)) {
|
||||
relatedUserList = Arrays.asList(relatedUser.split(","));
|
||||
}
|
||||
return relatedUserList;
|
||||
}
|
||||
|
||||
private String getSubject(SendNotice sendNotice) {
|
||||
Map<String, String> defaultTemplateTitleMap = MessageTemplateUtils.getDefaultTemplateSubjectMap();
|
||||
return defaultTemplateTitleMap.get(sendNotice.taskType() + "_" + sendNotice.event());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 有些默认的值,避免通知里出现 ${key}
|
||||
*/
|
||||
|
|
|
@ -9,11 +9,13 @@ import io.metersphere.system.notice.Receiver;
|
|||
import io.metersphere.system.notice.sender.AbstractNoticeSender;
|
||||
import io.metersphere.system.service.NotificationService;
|
||||
import io.metersphere.sdk.util.LogUtils;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -26,19 +28,25 @@ public class InSiteNoticeSender extends AbstractNoticeSender {
|
|||
public void sendAnnouncement(MessageDetail messageDetail, NoticeModel noticeModel, String context) {
|
||||
List<Receiver> receivers = noticeModel.getReceivers();
|
||||
// 排除自己
|
||||
if (noticeModel.isExcludeSelf()) {
|
||||
receivers.removeIf(u -> StringUtils.equals(u.getUserId(), noticeModel.getOperator()));
|
||||
List<Receiver> realReceivers = new ArrayList<>();
|
||||
for (Receiver receiver : receivers) {
|
||||
if (!StringUtils.equals(receiver.getUserId(), noticeModel.getOperator())) {
|
||||
realReceivers.add(receiver);
|
||||
}
|
||||
}
|
||||
if (CollectionUtils.isEmpty(receivers)) {
|
||||
|
||||
if (CollectionUtils.isEmpty(realReceivers)) {
|
||||
LogUtils.info("发送人是自己不发");
|
||||
return;
|
||||
}
|
||||
|
||||
LogUtils.info("发送站内通知: {}", receivers);
|
||||
receivers.forEach(receiver -> {
|
||||
LogUtils.info("发送站内通知: {}", realReceivers);
|
||||
realReceivers.forEach(receiver -> {
|
||||
|
||||
Map<String, Object> paramMap = noticeModel.getParamMap();
|
||||
Notification notification = new Notification();
|
||||
notification.setTitle(noticeModel.getSubject());
|
||||
notification.setId(IDGenerator.nextNum());
|
||||
notification.setSubject(noticeModel.getSubject());
|
||||
notification.setOperator(noticeModel.getOperator());
|
||||
notification.setOperation(noticeModel.getEvent());
|
||||
notification.setResourceId((String) paramMap.get("id"));
|
||||
|
@ -53,6 +61,7 @@ public class InSiteNoticeSender extends AbstractNoticeSender {
|
|||
notification.setStatus(NotificationConstants.Status.UNREAD.name());
|
||||
notification.setCreateTime(System.currentTimeMillis());
|
||||
notification.setReceiver(receiver.getUserId());
|
||||
notification.setContent(context);
|
||||
notificationService.sendAnnouncement(notification);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import io.metersphere.system.notice.MessageDetail;
|
|||
import io.metersphere.sdk.util.LogUtils;
|
||||
import io.metersphere.system.notice.utils.MessageTemplateUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -54,6 +55,9 @@ public class MessageDetailService {
|
|||
.andProjectIdEqualTo(projectId).andEnableEqualTo(true);
|
||||
example.setOrderByClause("create_time asc");
|
||||
List<MessageTask> messageTaskLists = messageTaskMapper.selectByExample(example);
|
||||
if (CollectionUtils.isEmpty(messageTaskLists)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
getMessageDetails(messageDetails, messageTaskLists);
|
||||
return messageDetails.stream()
|
||||
.sorted(Comparator.comparing(MessageDetail::getCreateTime, Comparator.nullsLast(Long::compareTo)).reversed())
|
||||
|
@ -93,7 +97,9 @@ public class MessageDetailService {
|
|||
return;
|
||||
}
|
||||
messageDetail.setType(projectRobot.getPlatform());
|
||||
messageDetail.setWebhook(projectRobot.getWebhook());
|
||||
if (StringUtils.isNotBlank(projectRobot.getWebhook())) {
|
||||
messageDetail.setWebhook(projectRobot.getWebhook());
|
||||
}
|
||||
if (StringUtils.isNotBlank(messageTask.getTestId())) {
|
||||
messageDetail.setTestId(messageTask.getTestId());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue