refactor(answer): refactor accept answer activity

This commit is contained in:
LinkinStars 2023-07-03 14:11:48 +08:00
parent 47661dc8a3
commit 7f58fbdad1
7 changed files with 414 additions and 213 deletions

View File

@ -45,7 +45,6 @@ import (
"github.com/answerdev/answer/internal/service"
"github.com/answerdev/answer/internal/service/action"
activity2 "github.com/answerdev/answer/internal/service/activity"
activity_common2 "github.com/answerdev/answer/internal/service/activity_common"
"github.com/answerdev/answer/internal/service/activity_queue"
"github.com/answerdev/answer/internal/service/answer_common"
auth2 "github.com/answerdev/answer/internal/service/auth"
@ -172,7 +171,7 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
collectionService := service.NewCollectionService(collectionRepo, collectionGroupRepo, questionCommon)
collectionController := controller.NewCollectionController(collectionService)
answerActivityRepo := activity.NewAnswerActivityRepo(dataData, activityRepo, userRankRepo, notificationQueueService)
answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo)
answerActivityService := activity2.NewAnswerActivityService(answerActivityRepo, configService)
questionService := service.NewQuestionService(questionRepo, tagCommonService, questionCommon, userCommon, userRepo, revisionService, metaService, collectionCommon, answerActivityService, emailService, notificationQueueService, activityQueueService, siteInfoCommonService)
answerService := service.NewAnswerService(answerRepo, questionRepo, questionCommon, userCommon, collectionCommon, userRepo, revisionService, answerActivityService, answerCommon, voteRepo, emailService, userRoleRelService, notificationQueueService, activityQueueService)
questionController := controller.NewQuestionController(questionService, answerService, rankService, siteInfoCommonService)
@ -205,11 +204,10 @@ func initApplication(debug bool, serverConf *conf.Server, dbConf *data.Database,
dashboardController := controller.NewDashboardController(dashboardService)
uploaderService := uploader.NewUploaderService(serviceConf, siteInfoCommonService)
uploadController := controller.NewUploadController(uploaderService)
activityCommon := activity_common2.NewActivityCommon(activityRepo, activityQueueService)
activityActivityRepo := activity.NewActivityRepo(dataData, configService)
commentCommonService := comment_common.NewCommentCommonService(commentCommonRepo)
activityService := activity2.NewActivityService(activityActivityRepo, userCommon, activityCommon, tagCommonService, objService, commentCommonService, revisionService, metaService, configService)
activityController := controller.NewActivityController(activityCommon, activityService)
activityService := activity2.NewActivityService(activityActivityRepo, userCommon, tagCommonService, objService, commentCommonService, revisionService, metaService, configService)
activityController := controller.NewActivityController(activityService)
roleController := controller_admin.NewRoleController(roleService)
pluginConfigRepo := plugin_config.NewPluginConfigRepo(dataData)
pluginCommonService := plugin_common.NewPluginCommonService(pluginConfigRepo, configService)

View File

@ -5,22 +5,19 @@ import (
"github.com/answerdev/answer/internal/base/middleware"
"github.com/answerdev/answer/internal/schema"
"github.com/answerdev/answer/internal/service/activity"
"github.com/answerdev/answer/internal/service/activity_common"
"github.com/answerdev/answer/internal/service/role"
"github.com/answerdev/answer/pkg/uid"
"github.com/gin-gonic/gin"
)
type ActivityController struct {
activityCommonService *activity_common.ActivityCommon
activityService *activity.ActivityService
activityService *activity.ActivityService
}
// NewActivityController new activity controller.
func NewActivityController(
activityCommonService *activity_common.ActivityCommon,
activityService *activity.ActivityService) *ActivityController {
return &ActivityController{activityCommonService: activityCommonService, activityService: activityService}
return &ActivityController{activityService: activityService}
}
// GetObjectTimeline get object timeline

View File

@ -2,7 +2,10 @@ package activity
import (
"context"
"fmt"
"github.com/segmentfault/pacman/log"
"time"
"xorm.io/builder"
"github.com/answerdev/answer/internal/base/constant"
"github.com/answerdev/answer/internal/base/data"
@ -18,10 +21,6 @@ import (
"xorm.io/xorm"
)
var (
acceptActionList = []string{constant.ActAccept, constant.ActAccepted}
)
// AnswerActivityRepo answer accepted
type AnswerActivityRepo struct {
data *data.Data
@ -45,91 +44,273 @@ func NewAnswerActivityRepo(
}
}
// AcceptAnswer accept other answer
func (ar *AnswerActivityRepo) AcceptAnswer(ctx context.Context,
answerObjID, questionObjID, questionUserID, answerUserID string, isSelf bool,
) (err error) {
addActivityList := make([]*entity.Activity, 0)
for _, action := range acceptActionList {
// get accept answer need add rank amount
activityType, deltaRank, hasRank, e := ar.activityRepo.GetActivityTypeByObjID(ctx, answerObjID, action)
if e != nil {
return errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
}
addActivity := &entity.Activity{
ObjectID: answerObjID,
OriginalObjectID: questionObjID,
ActivityType: activityType,
Rank: deltaRank,
HasRank: hasRank,
}
if action == constant.ActAccept {
addActivity.UserID = questionUserID
addActivity.TriggerUserID = converter.StringToInt64(answerUserID)
addActivity.OriginalObjectID = questionObjID // if activity is 'accept' means this question is accept the answer.
} else {
addActivity.UserID = answerUserID
addActivity.TriggerUserID = converter.StringToInt64(answerUserID)
addActivity.OriginalObjectID = answerObjID // if activity is 'accepted' means this answer was accepted.
}
if isSelf {
addActivity.Rank = 0
addActivity.HasRank = 0
}
addActivityList = append(addActivityList, addActivity)
func (ar *AnswerActivityRepo) SaveAcceptAnswerActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (
err error) {
// pre check
noNeedToDo, err := ar.activityPreCheck(ctx, op)
if err != nil {
return err
}
if noNeedToDo {
return nil
}
// save activity
_, err = ar.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
session = session.Context(ctx)
for _, addActivity := range addActivityList {
existsActivity, exists, e := ar.activityRepo.GetActivity(
ctx, session, answerObjID, addActivity.UserID, addActivity.ActivityType)
if e != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
}
if exists && existsActivity.Cancelled == entity.ActivityAvailable {
continue
}
// trigger user rank and send notification
if addActivity.Rank != 0 {
reachStandard, e := ar.userRankRepo.TriggerUserRank(
ctx, session, addActivity.UserID, addActivity.Rank, addActivity.ActivityType)
if e != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
}
if reachStandard {
addActivity.Rank = 0
}
}
userInfoMapping, err := ar.acquireUserInfo(session, op.GetUserIDs())
if err != nil {
return nil, err
}
if exists {
if _, e = session.Where("id = ?", existsActivity.ID).Cols("`cancelled`").
Update(&entity.Activity{Cancelled: entity.ActivityAvailable}); e != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
}
} else {
if _, e = session.Insert(addActivity); e != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
}
}
err = ar.saveActivitiesAvailable(session, op)
if err != nil {
return nil, err
}
err = ar.changeUserRank(ctx, session, op, userInfoMapping)
if err != nil {
return nil, err
}
return nil, nil
})
if err != nil {
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
// notification
ar.sendAcceptAnswerNotification(ctx, op)
return nil
}
func (ar *AnswerActivityRepo) SaveCancelAcceptAnswerActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (
err error) {
// pre check
activities, err := ar.getExistActivity(ctx, op)
if err != nil {
return err
}
for _, act := range addActivityList {
var userIDs []string
for _, act := range activities {
if act.Cancelled == entity.ActivityCancelled {
continue
}
userIDs = append(userIDs, act.UserID)
}
if len(userIDs) == 0 {
return nil
}
// save activity
_, err = ar.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
session = session.Context(ctx)
userInfoMapping, err := ar.acquireUserInfo(session, userIDs)
if err != nil {
return nil, err
}
err = ar.cancelActivities(session, activities)
if err != nil {
return nil, err
}
err = ar.rollbackUserRank(ctx, session, activities, userInfoMapping)
if err != nil {
return nil, err
}
return nil, nil
})
if err != nil {
return errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
// notification
ar.sendCancelAcceptAnswerNotification(ctx, op)
return nil
}
func (ar *AnswerActivityRepo) activityPreCheck(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (
noNeedToDo bool, err error) {
activities, err := ar.getExistActivity(ctx, op)
if err != nil {
return false, err
}
done := 0
for _, act := range activities {
if act.Cancelled == entity.ActivityAvailable {
done++
}
}
return done == len(op.Activities), nil
}
func (ar *AnswerActivityRepo) acquireUserInfo(session *xorm.Session, userIDs []string) (map[string]*entity.User, error) {
us := make([]*entity.User, 0)
err := session.In("id", userIDs).ForUpdate().Find(&us)
if err != nil {
log.Error(err)
return nil, err
}
users := make(map[string]*entity.User, 0)
for _, u := range us {
users[u.ID] = u
}
return users, nil
}
// saveActivitiesAvailable save activities
// If activity not exist it will be created or else will be updated
// If this activity is already exist, set activity rank to 0
// So after this function, the activity rank will be correct for update user rank
func (ar *AnswerActivityRepo) saveActivitiesAvailable(session *xorm.Session, op *schema.AcceptAnswerOperationInfo) (
err error) {
for _, act := range op.Activities {
existsActivity := &entity.Activity{}
exist, err := session.
Where(builder.Eq{"object_id": op.AnswerObjectID}).
And(builder.Eq{"user_id": act.ActivityUserID}).
And(builder.Eq{"trigger_user_id": act.TriggerUserID}).
And(builder.Eq{"activity_type": act.ActivityType}).
Get(existsActivity)
if err != nil {
return err
}
if exist && existsActivity.Cancelled == entity.ActivityAvailable {
act.Rank = 0
continue
}
if exist {
if _, err = session.Where("id = ?", existsActivity.ID).Cols("`cancelled`").
Update(&entity.Activity{Cancelled: entity.ActivityAvailable}); err != nil {
return err
}
} else {
insertActivity := entity.Activity{
ObjectID: op.AnswerObjectID,
OriginalObjectID: act.OriginalObjectID,
UserID: act.ActivityUserID,
TriggerUserID: converter.StringToInt64(act.TriggerUserID),
ActivityType: act.ActivityType,
Rank: act.Rank,
HasRank: act.HasRank(),
Cancelled: entity.ActivityAvailable,
}
_, err = session.Insert(&insertActivity)
if err != nil {
return err
}
}
}
return nil
}
// cancelActivities cancel activities
// If this activity is already cancelled, set activity rank to 0
// So after this function, the activity rank will be correct for update user rank
func (ar *AnswerActivityRepo) cancelActivities(session *xorm.Session, activities []*entity.Activity) (err error) {
for _, act := range activities {
t := &entity.Activity{}
exist, err := session.ID(act.ID).Get(t)
if err != nil {
log.Error(err)
return err
}
if !exist {
log.Error(fmt.Errorf("%s activity not exist", act.ID))
return fmt.Errorf("%s activity not exist", act.ID)
}
// If this activity is already cancelled, set activity rank to 0
if t.Cancelled == entity.ActivityCancelled {
act.Rank = 0
}
if _, err = session.ID(act.ID).Cols("cancelled", "cancelled_at").
Update(&entity.Activity{
Cancelled: entity.ActivityCancelled,
CancelledAt: time.Now(),
}); err != nil {
log.Error(err)
return err
}
}
return nil
}
func (ar *AnswerActivityRepo) changeUserRank(ctx context.Context, session *xorm.Session,
op *schema.AcceptAnswerOperationInfo,
userInfoMapping map[string]*entity.User) (err error) {
for _, act := range op.Activities {
if act.Rank == 0 {
continue
}
user := userInfoMapping[act.ActivityUserID]
if user == nil {
continue
}
if err = ar.userRankRepo.ChangeUserRank(ctx, session,
act.ActivityUserID, user.Rank, act.Rank); err != nil {
log.Error(err)
return err
}
}
return nil
}
func (ar *AnswerActivityRepo) rollbackUserRank(ctx context.Context, session *xorm.Session,
activities []*entity.Activity,
userInfoMapping map[string]*entity.User) (err error) {
for _, act := range activities {
if act.Rank == 0 {
continue
}
user := userInfoMapping[act.UserID]
if user == nil {
continue
}
if err = ar.userRankRepo.ChangeUserRank(ctx, session,
act.UserID, user.Rank, -act.Rank); err != nil {
log.Error(err)
return err
}
}
return nil
}
func (ar *AnswerActivityRepo) getExistActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) ([]*entity.Activity, error) {
var activities []*entity.Activity
for _, action := range op.Activities {
t := &entity.Activity{}
exist, err := ar.data.DB.Context(ctx).
Where(builder.Eq{"user_id": action.ActivityUserID}).
And(builder.Eq{"trigger_user_id": action.TriggerUserID}).
And(builder.Eq{"activity_type": action.ActivityType}).
And(builder.Eq{"object_id": op.AnswerObjectID}).
Get(t)
if err != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
if exist {
activities = append(activities, t)
}
}
return activities, nil
}
func (ar *AnswerActivityRepo) sendAcceptAnswerNotification(
ctx context.Context, op *schema.AcceptAnswerOperationInfo) {
for _, act := range op.Activities {
msg := &schema.NotificationMsg{
Type: schema.NotificationTypeAchievement,
ObjectID: act.ObjectID,
ReceiverUserID: act.UserID,
ObjectID: op.AnswerObjectID,
ReceiverUserID: act.ActivityUserID,
}
if act.UserID == questionUserID {
msg.TriggerUserID = answerUserID
if act.ActivityUserID == op.QuestionUserID {
msg.TriggerUserID = op.AnswerUserID
msg.ObjectType = constant.AnswerObjectType
} else {
msg.TriggerUserID = questionUserID
msg.TriggerUserID = op.QuestionUserID
msg.ObjectType = constant.AnswerObjectType
}
if msg.TriggerUserID != msg.ReceiverUserID {
@ -137,98 +318,38 @@ func (ar *AnswerActivityRepo) AcceptAnswer(ctx context.Context,
}
}
for _, act := range addActivityList {
for _, act := range op.Activities {
msg := &schema.NotificationMsg{
ReceiverUserID: act.UserID,
ReceiverUserID: act.ActivityUserID,
Type: schema.NotificationTypeInbox,
ObjectID: act.ObjectID,
ObjectID: op.AnswerObjectID,
}
if act.UserID != questionUserID {
msg.TriggerUserID = questionUserID
if act.ActivityUserID != op.QuestionUserID {
msg.TriggerUserID = op.QuestionUserID
msg.ObjectType = constant.AnswerObjectType
msg.NotificationAction = constant.NotificationAcceptAnswer
ar.notificationQueueService.Send(ctx, msg)
}
}
return err
}
// CancelAcceptAnswer accept other answer
func (ar *AnswerActivityRepo) CancelAcceptAnswer(ctx context.Context,
answerObjID, questionObjID, questionUserID, answerUserID string,
) (err error) {
addActivityList := make([]*entity.Activity, 0)
for _, action := range acceptActionList {
// get accept answer need add rank amount
activityType, deltaRank, hasRank, e := ar.activityRepo.GetActivityTypeByObjID(ctx, answerObjID, action)
if e != nil {
return errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
}
addActivity := &entity.Activity{
ObjectID: answerObjID,
ActivityType: activityType,
Rank: -deltaRank,
HasRank: hasRank,
}
if action == constant.ActAccept {
addActivity.UserID = questionUserID
addActivity.OriginalObjectID = questionObjID
} else {
addActivity.UserID = answerUserID
addActivity.OriginalObjectID = answerObjID
}
addActivityList = append(addActivityList, addActivity)
}
_, err = ar.data.DB.Transaction(func(session *xorm.Session) (result any, err error) {
session = session.Context(ctx)
for _, addActivity := range addActivityList {
existsActivity, exists, e := ar.activityRepo.GetActivity(
ctx, session, answerObjID, addActivity.UserID, addActivity.ActivityType)
if e != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
}
if exists && existsActivity.Cancelled == entity.ActivityCancelled {
continue
}
if !exists {
continue
}
if existsActivity.Rank != 0 {
_, e = ar.userRankRepo.TriggerUserRank(
ctx, session, addActivity.UserID, addActivity.Rank, addActivity.ActivityType)
if e != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
}
}
if _, e := session.Where("id = ?", existsActivity.ID).Cols("cancelled", "cancelled_at").
Update(&entity.Activity{Cancelled: entity.ActivityCancelled, CancelledAt: time.Now()}); e != nil {
return nil, errors.InternalServer(reason.DatabaseError).WithError(e).WithStack()
}
}
return nil, nil
})
if err != nil {
return err
}
for _, act := range addActivityList {
func (ar *AnswerActivityRepo) sendCancelAcceptAnswerNotification(
ctx context.Context, op *schema.AcceptAnswerOperationInfo) {
for _, act := range op.Activities {
msg := &schema.NotificationMsg{
ReceiverUserID: act.UserID,
ReceiverUserID: act.ActivityUserID,
Type: schema.NotificationTypeAchievement,
ObjectID: act.ObjectID,
ObjectID: op.AnswerObjectID,
}
if act.UserID == questionUserID {
msg.TriggerUserID = answerUserID
if act.ActivityUserID == op.QuestionObjectID {
msg.TriggerUserID = op.AnswerObjectID
msg.ObjectType = constant.QuestionObjectType
} else {
msg.TriggerUserID = questionUserID
msg.TriggerUserID = op.QuestionObjectID
msg.ObjectType = constant.AnswerObjectType
}
if msg.TriggerUserID != msg.ReceiverUserID {
ar.notificationQueueService.Send(ctx, msg)
}
}
return err
}

View File

@ -0,0 +1,35 @@
package schema
// AcceptAnswerOperationInfo accept answer operation info
type AcceptAnswerOperationInfo struct {
QuestionObjectID string
QuestionUserID string
AnswerObjectID string
AnswerUserID string
// vote activity info
Activities []*AcceptAnswerActivity
}
// AcceptAnswerActivity accept answer activity
type AcceptAnswerActivity struct {
ActivityType int
ActivityUserID string
TriggerUserID string
OriginalObjectID string
Rank int
}
func (v *AcceptAnswerActivity) HasRank() int {
if v.Rank != 0 {
return 1
}
return 0
}
func (a *AcceptAnswerOperationInfo) GetUserIDs() (userIDs []string) {
for _, act := range a.Activities {
userIDs = append(userIDs, act.ActivityUserID)
}
return userIDs
}

View File

@ -10,7 +10,6 @@ import (
"github.com/answerdev/answer/internal/base/handler"
"github.com/answerdev/answer/internal/entity"
"github.com/answerdev/answer/internal/schema"
"github.com/answerdev/answer/internal/service/activity_common"
"github.com/answerdev/answer/internal/service/comment_common"
"github.com/answerdev/answer/internal/service/config"
"github.com/answerdev/answer/internal/service/meta"
@ -31,22 +30,20 @@ type ActivityRepo interface {
// ActivityService activity service
type ActivityService struct {
activityRepo ActivityRepo
userCommon *usercommon.UserCommon
activityCommonService *activity_common.ActivityCommon
tagCommonService *tag_common.TagCommonService
objectInfoService *object_info.ObjService
commentCommonService *comment_common.CommentCommonService
revisionService *revision_common.RevisionService
metaService *meta.MetaService
configService *config.ConfigService
activityRepo ActivityRepo
userCommon *usercommon.UserCommon
tagCommonService *tag_common.TagCommonService
objectInfoService *object_info.ObjService
commentCommonService *comment_common.CommentCommonService
revisionService *revision_common.RevisionService
metaService *meta.MetaService
configService *config.ConfigService
}
// NewActivityService new activity service
func NewActivityService(
activityRepo ActivityRepo,
userCommon *usercommon.UserCommon,
activityCommonService *activity_common.ActivityCommon,
tagCommonService *tag_common.TagCommonService,
objectInfoService *object_info.ObjService,
commentCommonService *comment_common.CommentCommonService,
@ -55,15 +52,14 @@ func NewActivityService(
configService *config.ConfigService,
) *ActivityService {
return &ActivityService{
objectInfoService: objectInfoService,
activityRepo: activityRepo,
userCommon: userCommon,
activityCommonService: activityCommonService,
tagCommonService: tagCommonService,
commentCommonService: commentCommonService,
revisionService: revisionService,
metaService: metaService,
configService: configService,
objectInfoService: objectInfoService,
activityRepo: activityRepo,
userCommon: userCommon,
tagCommonService: tagCommonService,
commentCommonService: commentCommonService,
revisionService: revisionService,
metaService: metaService,
configService: configService,
}
}

View File

@ -1,38 +0,0 @@
package activity
import (
"context"
)
// AnswerActivityRepo answer activity
type AnswerActivityRepo interface {
AcceptAnswer(ctx context.Context,
answerObjID, questionObjID, questionUserID, answerUserID string, isSelf bool) (err error)
CancelAcceptAnswer(ctx context.Context,
answerObjID, questionObjID, questionUserID, answerUserID string) (err error)
}
// AnswerActivityService user service
type AnswerActivityService struct {
answerActivityRepo AnswerActivityRepo
}
// NewAnswerActivityService new comment service
func NewAnswerActivityService(
answerActivityRepo AnswerActivityRepo) *AnswerActivityService {
return &AnswerActivityService{
answerActivityRepo: answerActivityRepo,
}
}
// AcceptAnswer accept answer change activity
func (as *AnswerActivityService) AcceptAnswer(ctx context.Context,
answerObjID, questionObjID, questionUserID, answerUserID string, isSelf bool) (err error) {
return as.answerActivityRepo.AcceptAnswer(ctx, answerObjID, questionObjID, questionUserID, answerUserID, isSelf)
}
// CancelAcceptAnswer cancel accept answer change activity
func (as *AnswerActivityService) CancelAcceptAnswer(ctx context.Context,
answerObjID, questionObjID, questionUserID, answerUserID string) (err error) {
return as.answerActivityRepo.CancelAcceptAnswer(ctx, answerObjID, questionObjID, questionUserID, answerUserID)
}

View File

@ -0,0 +1,92 @@
package activity
import (
"context"
"github.com/answerdev/answer/internal/schema"
"github.com/answerdev/answer/internal/service/activity_type"
"github.com/answerdev/answer/internal/service/config"
"github.com/segmentfault/pacman/log"
)
// AnswerActivityRepo answer activity
type AnswerActivityRepo interface {
SaveAcceptAnswerActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (err error)
SaveCancelAcceptAnswerActivity(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (err error)
}
// AnswerActivityService answer activity service
type AnswerActivityService struct {
answerActivityRepo AnswerActivityRepo
configService *config.ConfigService
}
// NewAnswerActivityService new comment service
func NewAnswerActivityService(
answerActivityRepo AnswerActivityRepo,
configService *config.ConfigService,
) *AnswerActivityService {
return &AnswerActivityService{
answerActivityRepo: answerActivityRepo,
configService: configService,
}
}
// AcceptAnswer accept answer change activity
func (as *AnswerActivityService) AcceptAnswer(ctx context.Context,
answerObjID, questionObjID, questionUserID, answerUserID string, isSelf bool) (err error) {
operationInfo := as.createAcceptAnswerOperationInfo(ctx,
answerObjID, questionObjID, questionUserID, answerUserID, isSelf)
return as.answerActivityRepo.SaveAcceptAnswerActivity(ctx, operationInfo)
}
// CancelAcceptAnswer cancel accept answer change activity
func (as *AnswerActivityService) CancelAcceptAnswer(ctx context.Context,
answerObjID, questionObjID, questionUserID, answerUserID string) (err error) {
operationInfo := as.createAcceptAnswerOperationInfo(ctx,
answerObjID, questionObjID, questionUserID, answerUserID, false)
return as.answerActivityRepo.SaveCancelAcceptAnswerActivity(ctx, operationInfo)
}
func (as *AnswerActivityService) createAcceptAnswerOperationInfo(ctx context.Context,
answerObjID, questionObjID, questionUserID, answerUserID string, isSelf bool) *schema.AcceptAnswerOperationInfo {
operationInfo := &schema.AcceptAnswerOperationInfo{
QuestionObjectID: questionObjID,
QuestionUserID: questionUserID,
AnswerObjectID: answerObjID,
AnswerUserID: answerUserID,
}
operationInfo.Activities = as.getActivities(ctx, operationInfo)
if isSelf {
for _, activity := range operationInfo.Activities {
activity.Rank = 0
}
}
return operationInfo
}
func (as *AnswerActivityService) getActivities(ctx context.Context, op *schema.AcceptAnswerOperationInfo) (
activities []*schema.AcceptAnswerActivity) {
activities = make([]*schema.AcceptAnswerActivity, 0)
for _, action := range []string{activity_type.AnswerAccept, activity_type.AnswerAccepted} {
t := &schema.AcceptAnswerActivity{}
cfg, err := as.configService.GetConfigByKey(ctx, action)
if err != nil {
log.Warnf("get config by key error: %v", err)
continue
}
t.ActivityType, t.Rank = cfg.ID, cfg.GetIntValue()
if action == activity_type.AnswerAccept {
t.ActivityUserID = op.QuestionUserID
t.TriggerUserID = op.AnswerUserID
t.OriginalObjectID = op.QuestionObjectID // if activity is 'accept' means this question is accept the answer.
} else {
t.ActivityUserID = op.AnswerUserID
t.TriggerUserID = op.AnswerUserID
t.OriginalObjectID = op.AnswerObjectID // if activity is 'accepted' means this answer was accepted.
}
activities = append(activities, t)
}
return activities
}