Jelajahi Sumber

增加sop任务发布、启动、暂停接口

boweniac 9 bulan lalu
induk
melakukan
bbcab6b1d8

+ 8 - 0
desc/wechat/sop_task.api

@@ -72,4 +72,12 @@ service Wechat {
     // Publish sop task | 发布 SopTask
     @handler publishSopTask
     post /sop_task/publish (IDReq) returns (BaseMsgResp)
+
+    // task start | SopTask 开始
+    @handler sopTaskStart
+    post /sop_task/start (IDReq) returns (BaseMsgResp)
+
+    // task stop | SopTask 停止
+    @handler sopTaskStop
+    post /sop_task/stop (IDReq) returns (BaseMsgResp)
 }

+ 10 - 0
internal/handler/routes.go

@@ -335,6 +335,16 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
 					Path:    "/sop_task/publish",
 					Handler: sop_task.PublishSopTaskHandler(serverCtx),
 				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/sop_task/start",
+					Handler: sop_task.SopTaskStartHandler(serverCtx),
+				},
+				{
+					Method:  http.MethodPost,
+					Path:    "/sop_task/stop",
+					Handler: sop_task.SopTaskStopHandler(serverCtx),
+				},
 			}...,
 		),
 		rest.WithJwt(serverCtx.Config.Auth.AccessSecret),

+ 44 - 0
internal/handler/sop_task/sop_task_start_handler.go

@@ -0,0 +1,44 @@
+package sop_task
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/sop_task"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /sop_task/start sop_task SopTaskStart
+//
+// task start | SopTask 开始
+//
+// task start | SopTask 开始
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func SopTaskStartHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.IDReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := sop_task.NewSopTaskStartLogic(r.Context(), svcCtx)
+		resp, err := l.SopTaskStart(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 44 - 0
internal/handler/sop_task/sop_task_stop_handler.go

@@ -0,0 +1,44 @@
+package sop_task
+
+import (
+	"net/http"
+
+	"github.com/zeromicro/go-zero/rest/httpx"
+
+	"wechat-api/internal/logic/sop_task"
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+)
+
+// swagger:route post /sop_task/stop sop_task SopTaskStop
+//
+// task stop | SopTask 停止
+//
+// task stop | SopTask 停止
+//
+// Parameters:
+//  + name: body
+//    require: true
+//    in: body
+//    type: IDReq
+//
+// Responses:
+//  200: BaseMsgResp
+
+func SopTaskStopHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		var req types.IDReq
+		if err := httpx.Parse(r, &req, true); err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+			return
+		}
+
+		l := sop_task.NewSopTaskStopLogic(r.Context(), svcCtx)
+		resp, err := l.SopTaskStop(&req)
+		if err != nil {
+			httpx.ErrorCtx(r.Context(), w, err)
+		} else {
+			httpx.OkJsonCtx(r.Context(), w, resp)
+		}
+	}
+}

+ 19 - 12
internal/logic/label/create_label_logic.go

@@ -7,7 +7,7 @@ import (
 	"wechat-api/internal/types"
 	"wechat-api/internal/utils/dberrorhandler"
 
-    "github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
 
 	"github.com/zeromicro/go-zero/core/logx"
 )
@@ -27,18 +27,25 @@ func NewCreateLabelLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Creat
 }
 
 func (l *CreateLabelLogic) CreateLabel(req *types.LabelInfo) (*types.BaseMsgResp, error) {
-    _, err := l.svcCtx.DB.Label.Create().
-			SetNotNilStatus(req.Status).
-			SetNotNilType(req.Type).
-			SetNotNilName(req.Name).
-			SetNotNilFrom(req.From).
-			SetNotNilMode(req.Mode).
-			SetNotNilConditions(req.Conditions).
-			Save(l.ctx)
-
-    if err != nil {
+	l.Logger.Infof("CreateLabel req: %v", req)
+	var conditions = "{}"
+	//if *req.Conditions == "" {
+	//	conditions = "{}"
+	//} else {
+	//	conditions = *req.Conditions
+	//}
+	_, err := l.svcCtx.DB.Label.Create().
+		SetNotNilStatus(req.Status).
+		SetNotNilType(req.Type).
+		SetNotNilName(req.Name).
+		SetNotNilFrom(req.From).
+		SetNotNilMode(req.Mode).
+		SetNotNilConditions(&conditions).
+		Save(l.ctx)
+
+	if err != nil {
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
-    return &types.BaseMsgResp{Msg: errormsg.CreateSuccess}, nil
+	return &types.BaseMsgResp{Msg: errormsg.CreateSuccess}, nil
 }

+ 37 - 10
internal/logic/label_relationship/update_label_relationships_logic.go

@@ -30,11 +30,18 @@ func NewUpdateLabelRelationshipsLogic(ctx context.Context, svcCtx *svc.ServiceCo
 }
 
 func (l *UpdateLabelRelationshipsLogic) UpdateLabelRelationships(req *types.LabelRelationshipsInfo) (resp *types.BaseMsgResp, err error) {
+	// 开始事务
+	tx, err := l.svcCtx.DB.Tx(context.Background())
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
 	// 获取联系人信息
-	c, err := l.svcCtx.DB.Contact.Query().Where(contact.ID(*req.ContactId)).Only(l.ctx)
+	c, err := tx.Contact.Query().Where(contact.ID(*req.ContactId)).Only(l.ctx)
 	// 获取联系人当前已关联的标签
-	currentLabelRelationships, err := l.svcCtx.DB.LabelRelationship.Query().Where(labelrelationship.ContactID(*req.ContactId)).All(l.ctx)
+	currentLabelRelationships, err := tx.LabelRelationship.Query().Where(labelrelationship.ContactID(*req.ContactId)).All(l.ctx)
 	if err != nil {
+		_ = tx.Rollback()
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
@@ -51,7 +58,7 @@ func (l *UpdateLabelRelationshipsLogic) UpdateLabelRelationships(req *types.Labe
 	if req.UpdateType == nil || *req.UpdateType == "all" {
 		// 删除需要移除的标签关系
 		for _, id := range removeLabelIds {
-			_, err := l.svcCtx.DB.LabelRelationship.
+			_, err := tx.LabelRelationship.
 				Delete().
 				Where(
 					labelrelationship.ContactID(*req.ContactId),
@@ -59,6 +66,7 @@ func (l *UpdateLabelRelationshipsLogic) UpdateLabelRelationships(req *types.Labe
 				).
 				Exec(l.ctx)
 			if err != nil {
+				_ = tx.Rollback()
 				return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 			}
 		}
@@ -66,7 +74,7 @@ func (l *UpdateLabelRelationshipsLogic) UpdateLabelRelationships(req *types.Labe
 
 	// 创建需要新增的标签关系
 	for _, id := range addLabelIds {
-		_, _ = l.svcCtx.DB.LabelRelationship.Create().
+		_, _ = tx.LabelRelationship.Create().
 			SetLabelID(id).
 			SetContactID(*req.ContactId).
 			Save(l.ctx)
@@ -78,8 +86,10 @@ func (l *UpdateLabelRelationshipsLogic) UpdateLabelRelationships(req *types.Labe
 	currentLabelIds = req.LabelIds
 
 	// 获取所有 status 为 3 且 bot_wxid_list 包含 c.wx_wxid 的 sop_task
-	sopTasks, err := l.svcCtx.DB.SopTask.Query().Where(soptask.Status(3)).All(l.ctx)
+	sopTasks, err := tx.SopTask.Query().Where(soptask.Status(3)).All(l.ctx)
+	l.Logger.Info("UpdateLabelRelationships sopTasks:", sopTasks)
 	if err != nil {
+		_ = tx.Rollback()
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
@@ -98,6 +108,7 @@ func (l *UpdateLabelRelationshipsLogic) UpdateLabelRelationships(req *types.Labe
 	for _, task := range filteredSopTasks {
 		stages, err := task.QueryTaskStages().All(l.ctx)
 		if err != nil {
+			_ = tx.Rollback()
 			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 		}
 		sopStages = append(sopStages, stages...)
@@ -105,8 +116,14 @@ func (l *UpdateLabelRelationshipsLogic) UpdateLabelRelationships(req *types.Labe
 
 	err = l.AddLabelRelationships(sopStages, *c, currentLabelIds)
 	if err != nil {
+		_ = tx.Rollback()
 		return nil, err
 	}
+	// 所有操作成功,提交事务
+	err = tx.Commit()
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
 
 	return &types.BaseMsgResp{
 		Code: 0,
@@ -115,12 +132,16 @@ func (l *UpdateLabelRelationshipsLogic) UpdateLabelRelationships(req *types.Labe
 }
 
 func (l *UpdateLabelRelationshipsLogic) AddLabelRelationships(sopStages []*ent.SopStage, contact ent.Contact, currentLabelIds []uint64) (err error) {
-
+	// 开始事务
+	tx, err := l.svcCtx.DB.Tx(context.Background())
+	if err != nil {
+		return dberrorhandler.DefaultEntError(l.Logger, err, nil)
+	}
 	// 遍历 sop_stages,找出满足条件的 stage
 	for _, stage := range sopStages {
 		if stage.ConditionType == 1 && isLabelIdListMatchFilter(currentLabelIds, stage.ConditionOperator, stage.ConditionList) {
 			// 判断是否有 contact_wxid、source_type、source_id、sub_source_id 相同的记录
-			_, err = l.svcCtx.DB.MessageRecords.Query().
+			_, err = tx.MessageRecords.Query().
 				Where(
 					messagerecords.ContactWxid(contact.Wxid),
 					messagerecords.SourceType(3),
@@ -135,7 +156,7 @@ func (l *UpdateLabelRelationshipsLogic) AddLabelRelationships(sopStages []*ent.S
 			sourceType := 3
 			if stage.ActionMessage != nil {
 				for _, message := range stage.ActionMessage {
-					_, _ = l.svcCtx.DB.MessageRecords.Create().
+					_, _ = tx.MessageRecords.Create().
 						SetNotNilBotWxid(&contact.WxWxid).
 						SetNotNilContactID(&contact.ID).
 						SetNotNilContactType(&contact.Type).
@@ -173,7 +194,7 @@ func (l *UpdateLabelRelationshipsLogic) AddLabelRelationships(sopStages []*ent.S
 
 				// 创建需要新增的标签关系
 				for _, id := range newLabelIds {
-					_, err = l.svcCtx.DB.LabelRelationship.Create().
+					_, err = tx.LabelRelationship.Create().
 						SetLabelID(id).
 						SetContactID(contact.ID).
 						Save(l.ctx)
@@ -187,12 +208,18 @@ func (l *UpdateLabelRelationshipsLogic) AddLabelRelationships(sopStages []*ent.S
 				// 递归调用 AddLabelRelationships
 				err = l.AddLabelRelationships(sopStages, contact, currentLabelIds)
 				if err != nil {
+					_ = tx.Rollback()
 					return err
 				}
 			}
 		}
-
 	}
+	// 所有操作成功,提交事务
+	err = tx.Commit()
+	if err != nil {
+		return dberrorhandler.DefaultEntError(l.Logger, err, nil)
+	}
+
 	return nil
 }
 

+ 59 - 11
internal/logic/sop_task/publish_sop_task_logic.go

@@ -33,23 +33,44 @@ func NewPublishSopTaskLogic(ctx context.Context, svcCtx *svc.ServiceContext) *Pu
 }
 
 func (l *PublishSopTaskLogic) PublishSopTask(req *types.IDReq) (resp *types.BaseMsgResp, err error) {
+	// 开始事务
+	tx, err := l.svcCtx.DB.Tx(context.Background())
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
 	// 根据 id 查询 sop_task
-	sopTask, err := l.svcCtx.DB.SopTask.Query().
+	sopTask, err := tx.SopTask.Query().
 		Where(
 			soptask.ID(req.Id),
-			soptask.Status(3),
+			soptask.Status(1),
 		).
 		WithTaskStages().
 		Only(l.ctx)
 	if err != nil {
+		_ = tx.Rollback()
 		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 	}
 
 	// 判断 sop_task 是否存在
 	if sopTask != nil {
+		if sopTask.BotWxidList == nil {
+			return nil, errors.New(errormsg.ValidationError)
+		}
+
 		// 查询任务的所有 sop_stages
-		sopStages, err := l.svcCtx.DB.SopStage.Query().All(l.ctx)
+		err = tx.SopTask.UpdateOneID(req.Id).
+			SetStatus(3).
+			Exec(l.ctx)
+
+		if err != nil {
+			_ = tx.Rollback()
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+		}
+
+		sopStages, err := tx.SopStage.Query().All(l.ctx)
 		if err != nil {
+			_ = tx.Rollback()
 			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 		}
 
@@ -72,12 +93,13 @@ func (l *PublishSopTaskLogic) PublishSopTask(req *types.IDReq) (resp *types.Base
 				var err error
 				sourceType := 3
 				if stage.ConditionOperator == 1 {
-					contacts, err = l.svcCtx.DB.Contact.Query().Where(contact.And(predicates...)).All(l.ctx)
+					contacts, err = tx.Contact.Query().Where(contact.And(predicates...)).All(l.ctx)
 				} else {
-					contacts, err = l.svcCtx.DB.Contact.Query().Where(contact.Or(predicates...)).All(l.ctx)
+					contacts, err = tx.Contact.Query().Where(contact.Or(predicates...)).All(l.ctx)
 				}
 
 				if err != nil {
+					_ = tx.Rollback()
 					return nil, err
 				}
 
@@ -86,7 +108,7 @@ func (l *PublishSopTaskLogic) PublishSopTask(req *types.IDReq) (resp *types.Base
 					// 判断联系人所属微信是否包含在任务当中
 					if sopTask.BotWxidList == nil || (sopTask.BotWxidList != nil && valueInArray(c.WxWxid, sopTask.BotWxidList)) {
 						for _, message := range stage.ActionMessage {
-							_, _ = l.svcCtx.DB.MessageRecords.Create().
+							_, _ = tx.MessageRecords.Create().
 								SetNotNilBotWxid(&c.WxWxid).
 								SetNotNilContactID(&c.ID).
 								SetNotNilContactType(&c.Type).
@@ -103,8 +125,9 @@ func (l *PublishSopTaskLogic) PublishSopTask(req *types.IDReq) (resp *types.Base
 						}
 
 						// 查询当前联系人的标签关系
-						currentLabelRelationships, err := l.svcCtx.DB.LabelRelationship.Query().Where(labelrelationship.ContactID(c.ID)).All(l.ctx)
+						currentLabelRelationships, err := tx.LabelRelationship.Query().Where(labelrelationship.ContactID(c.ID)).All(l.ctx)
 						if err != nil {
+							_ = tx.Rollback()
 							return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
 						}
 
@@ -118,6 +141,7 @@ func (l *PublishSopTaskLogic) PublishSopTask(req *types.IDReq) (resp *types.Base
 							// 递归调用 AddLabelRelationships
 							err = l.AddLabelRelationships(sopStages, *c, currentLabelIds, stage.ActionLabel)
 							if err != nil {
+								_ = tx.Rollback()
 								return nil, err
 							}
 						}
@@ -125,14 +149,30 @@ func (l *PublishSopTaskLogic) PublishSopTask(req *types.IDReq) (resp *types.Base
 				}
 			}
 		}
+		// 所有操作成功,提交事务
+		err = tx.Commit()
+		if err != nil {
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+		}
 		return &types.BaseMsgResp{Msg: errormsg.Success}, nil
 	} else {
+		// 所有操作成功,提交事务
+		err = tx.Commit()
+		if err != nil {
+			return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+		}
 		// 返回错误信息:任务不存在
 		return nil, errors.New(errormsg.TargetNotFound)
 	}
 }
 
 func (l *PublishSopTaskLogic) AddLabelRelationships(sopStages []*ent.SopStage, contact ent.Contact, currentLabelIds []uint64, addLabelIds []uint64) (err error) {
+	// 开始事务
+	tx, err := l.svcCtx.DB.Tx(context.Background())
+	if err != nil {
+		return dberrorhandler.DefaultEntError(l.Logger, err, nil)
+	}
+
 	// 获取 addLabelIds 中不在 currentLabelIds 中的标签ID
 	var newLabelIds []uint64
 	// 创建一个映射,用于快速查找 currentLabelIds 中的元素
@@ -154,11 +194,12 @@ func (l *PublishSopTaskLogic) AddLabelRelationships(sopStages []*ent.SopStage, c
 
 	// 创建需要新增的标签关系
 	for _, id := range newLabelIds {
-		_, err = l.svcCtx.DB.LabelRelationship.Create().
+		_, err = tx.LabelRelationship.Create().
 			SetLabelID(id).
 			SetContactID(contact.ID).
 			Save(l.ctx)
 		if err != nil {
+			_ = tx.Rollback()
 			return dberrorhandler.DefaultEntError(l.Logger, err, nil)
 		}
 	}
@@ -170,7 +211,7 @@ func (l *PublishSopTaskLogic) AddLabelRelationships(sopStages []*ent.SopStage, c
 	for _, stage := range sopStages {
 		if stage.ConditionType == 1 && isLabelIdListMatchFilter(currentLabelIds, stage.ConditionOperator, stage.ConditionList) {
 			// 判断是否有 contact_wxid、source_type、source_id、sub_source_id 相同的记录
-			_, err = l.svcCtx.DB.MessageRecords.Query().
+			_, err := tx.MessageRecords.Query().
 				Where(
 					messagerecords.ContactWxid(contact.Wxid),
 					messagerecords.SourceType(3),
@@ -178,14 +219,14 @@ func (l *PublishSopTaskLogic) AddLabelRelationships(sopStages []*ent.SopStage, c
 					messagerecords.SubSourceID(0),
 				).
 				Only(l.ctx)
-			if err == nil {
+			if err != nil {
 				continue
 			}
 			// 判断ActionMessage是否为空
 			sourceType := 3
 			if stage.ActionMessage != nil {
 				for _, message := range stage.ActionMessage {
-					_, _ = l.svcCtx.DB.MessageRecords.Create().
+					_, _ = tx.MessageRecords.Create().
 						SetNotNilBotWxid(&contact.WxWxid).
 						SetNotNilContactID(&contact.ID).
 						SetNotNilContactType(&contact.Type).
@@ -205,12 +246,19 @@ func (l *PublishSopTaskLogic) AddLabelRelationships(sopStages []*ent.SopStage, c
 				// 递归调用 AddLabelRelationships
 				err = l.AddLabelRelationships(sopStages, contact, currentLabelIds, stage.ActionLabel)
 				if err != nil {
+					_ = tx.Rollback()
 					return err
 				}
 			}
 		}
 
 	}
+
+	// 所有操作成功,提交事务
+	err = tx.Commit()
+	if err != nil {
+		return dberrorhandler.DefaultEntError(l.Logger, err, nil)
+	}
 	return nil
 }
 

+ 68 - 0
internal/logic/sop_task/sop_task_start_logic.go

@@ -0,0 +1,68 @@
+package sop_task
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent/messagerecords"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type SopTaskStartLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewSopTaskStartLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SopTaskStartLogic {
+	return &SopTaskStartLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *SopTaskStartLogic) SopTaskStart(req *types.IDReq) (resp *types.BaseMsgResp, err error) {
+	// 开始事务
+	tx, err := l.svcCtx.DB.Tx(context.Background())
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 根据 id 查询 task 信息,如果 Status 的值不为 1,则不允许修改
+	task, err := tx.SopTask.Get(l.ctx, req.Id)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	if task.Status != 2 && task.Status != 4 {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	err = l.svcCtx.DB.SopTask.UpdateOneID(req.Id).
+		SetStatus(3).
+		Exec(l.ctx)
+
+	if err != nil {
+		_ = tx.Rollback()
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 查询task的所有sop_stages
+	for _, stage := range task.Edges.TaskStages {
+		// 更新最旧的 p.Number 条 status 值为 1 或 4 的 message_records 记录的 status 为 2
+		messages, _ := tx.MessageRecords.Query().
+			Where(messagerecords.Status(5), messagerecords.SourceType(3), messagerecords.SourceID(stage.ID)).
+			All(l.ctx)
+		for _, m := range messages {
+			_, err := tx.MessageRecords.UpdateOneID(m.ID).SetStatus(1).Save(l.ctx)
+			if err != nil {
+				_ = tx.Rollback()
+			}
+		}
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
+}

+ 68 - 0
internal/logic/sop_task/sop_task_stop_logic.go

@@ -0,0 +1,68 @@
+package sop_task
+
+import (
+	"context"
+	"github.com/suyuan32/simple-admin-common/msg/errormsg"
+	"wechat-api/ent/messagerecords"
+	"wechat-api/internal/utils/dberrorhandler"
+
+	"wechat-api/internal/svc"
+	"wechat-api/internal/types"
+
+	"github.com/zeromicro/go-zero/core/logx"
+)
+
+type SopTaskStopLogic struct {
+	logx.Logger
+	ctx    context.Context
+	svcCtx *svc.ServiceContext
+}
+
+func NewSopTaskStopLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SopTaskStopLogic {
+	return &SopTaskStopLogic{
+		Logger: logx.WithContext(ctx),
+		ctx:    ctx,
+		svcCtx: svcCtx}
+}
+
+func (l *SopTaskStopLogic) SopTaskStop(req *types.IDReq) (resp *types.BaseMsgResp, err error) {
+	// 开始事务
+	tx, err := l.svcCtx.DB.Tx(context.Background())
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 根据 id 查询 task 信息,如果 Status 的值不为 1,则不允许修改
+	task, err := tx.SopTask.Get(l.ctx, req.Id)
+	if err != nil {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+	if task.Status != 3 {
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	err = l.svcCtx.DB.SopTask.UpdateOneID(req.Id).
+		SetStatus(2).
+		Exec(l.ctx)
+
+	if err != nil {
+		_ = tx.Rollback()
+		return nil, dberrorhandler.DefaultEntError(l.Logger, err, req)
+	}
+
+	// 查询task的所有sop_stages
+	for _, stage := range task.Edges.TaskStages {
+		// 更新最旧的 p.Number 条 status 值为 1 或 4 的 message_records 记录的 status 为 2
+		messages, _ := tx.MessageRecords.Query().
+			Where(messagerecords.StatusIn(1, 2, 4), messagerecords.SourceType(3), messagerecords.SourceID(stage.ID)).
+			All(l.ctx)
+		for _, m := range messages {
+			_, err := tx.MessageRecords.UpdateOneID(m.ID).SetStatus(5).Save(l.ctx)
+			if err != nil {
+				_ = tx.Rollback()
+			}
+		}
+	}
+
+	return &types.BaseMsgResp{Msg: errormsg.UpdateSuccess}, nil
+}