This is an automated email from the ASF dual-hosted git repository.

robin0716 pushed a commit to branch develop/robin
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git

commit 45799d1623c1e6a660fc0f09a589ed0f0d8e3e17
Author: LinkinStars <linkins...@foxmail.com>
AuthorDate: Wed Aug 14 12:31:03 2024 +0800

    fix(badge): fix badge init data
---
 internal/entity/badge_entity.go            |   8 +-
 internal/migrations/init.go                |  20 +++
 internal/migrations/init_data.go           | 156 +++++++++++++++++
 internal/migrations/v22.go                 | 268 +++--------------------------
 internal/repo/badge/badge_event_rule.go    | 155 ++++++++---------
 internal/service/content/answer_service.go |   6 +-
 6 files changed, 285 insertions(+), 328 deletions(-)

diff --git a/internal/entity/badge_entity.go b/internal/entity/badge_entity.go
index 5177c93c..a370e275 100644
--- a/internal/entity/badge_entity.go
+++ b/internal/entity/badge_entity.go
@@ -47,14 +47,14 @@ type Badge struct {
        Name         string     `xorm:"not null default '' VARCHAR(256) name"`
        Icon         string     `xorm:"not null default '' VARCHAR(1024) icon"`
        AwardCount   int        `xorm:"not null default 0 INT(11) award_count"`
-       Description  string     `xorm:"not null default '' MEDIUMTEXT 
description"`
+       Description  string     `xorm:"not null MEDIUMTEXT description"`
        Status       int8       `xorm:"not null default 1 INT(11) status"`
        BadgeGroupID int64      `xorm:"not null default 0 BIGINT(20) 
badge_group_id"`
        Level        BadgeLevel `xorm:"not null default 1 TINYINT(4) level"`
        Single       int8       `xorm:"not null default 1 TINYINT(4) single"`
-       Collect      string     `xorm:"not null default '' VARCHAR(64) collect"`
-       Handler      string     `xorm:"not null default '' VARCHAR(64) handler"`
-       Param        string     `xorm:"not null default '' TEXT param"`
+       Collect      string     `xorm:"not null default '' VARCHAR(128) 
collect"`
+       Handler      string     `xorm:"not null default '' VARCHAR(128) 
handler"`
+       Param        string     `xorm:"not null TEXT param"`
 }
 
 // TableName badge table name
diff --git a/internal/migrations/init.go b/internal/migrations/init.go
index 0b4d1ce3..b74e3688 100644
--- a/internal/migrations/init.go
+++ b/internal/migrations/init.go
@@ -80,6 +80,7 @@ func (m *Mentor) InitDB() error {
        m.do("init site info privilege rank", m.initSiteInfoPrivilegeRank)
        m.do("init site info write", m.initSiteInfoWrite)
        m.do("init default content", m.initDefaultContent)
+       m.do("init default badges", m.initDefaultBadges)
        return m.err
 }
 
@@ -432,3 +433,22 @@ func (m *Mentor) initDefaultContent() {
                return
        }
 }
+
+func (m *Mentor) initDefaultBadges() {
+       uniqueIDRepo := unique.NewUniqueIDRepo(&data.Data{DB: m.engine})
+
+       _, m.err = m.engine.Context(m.ctx).Insert(defaultBadgeGroupTable)
+       if m.err != nil {
+               return
+       }
+       for _, badge := range defaultBadgeTable {
+               badge.ID, m.err = uniqueIDRepo.GenUniqueIDStr(m.ctx, 
new(entity.Badge).TableName())
+               if m.err != nil {
+                       return
+               }
+               if _, m.err = m.engine.Context(m.ctx).Insert(badge); m.err != 
nil {
+                       return
+               }
+       }
+       return
+}
diff --git a/internal/migrations/init_data.go b/internal/migrations/init_data.go
index f9a09f52..50a5651b 100644
--- a/internal/migrations/init_data.go
+++ b/internal/migrations/init_data.go
@@ -347,4 +347,160 @@ var (
                {ID: 129, Key: "rank.question.undeleted", Value: `-1`},
                {ID: 130, Key: "rank.tag.undeleted", Value: `-1`},
        }
+
+       defaultBadgeGroupTable = []*entity.BadgeGroup{
+               {ID: "1", Name: 
"badge.default_badge_groups.getting_started.name"},
+               {ID: "2", Name: "badge.default_badge_groups.community.name"},
+               {ID: "3", Name: "badge.default_badge_groups.posting.name"},
+       }
+
+       defaultBadgeTable = []*entity.Badge{
+               {
+                       Name:         
"badge.default_badges.autobiographer.name",
+                       Icon:         "person-badge-fill",
+                       Description:  
"badge.default_badges.autobiographer.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 1,
+                       Level:        entity.BadgeLevelBronze,
+                       Single:       entity.BadgeSingleAward,
+                       Handler:      "FirstUpdateUserProfile",
+               },
+               {
+                       Name:         "badge.default_badges.editor.name",
+                       Icon:         "pencil-fill",
+                       Description:  "badge.default_badges.editor.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 1,
+                       Level:        entity.BadgeLevelBronze,
+                       Single:       entity.BadgeSingleAward,
+                       Handler:      "FirstPostEdit",
+               },
+               {
+                       Name:         "badge.default_badges.first_flag.name",
+                       Icon:         "flag-fill",
+                       Description:  "badge.default_badges.first_flag.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 1,
+                       Level:        entity.BadgeLevelBronze,
+                       Single:       entity.BadgeSingleAward,
+                       Handler:      "FirstFlaggedPost",
+               },
+               {
+                       Name:         "badge.default_badges.first_upvote.name",
+                       Icon:         "hand-thumbs-up-fill",
+                       Description:  "badge.default_badges.first_upvote.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 1,
+                       Level:        entity.BadgeLevelBronze,
+                       Single:       entity.BadgeSingleAward,
+                       Handler:      "FirstVotedPost",
+               },
+               {
+                       Name:         
"badge.default_badges.first_reaction.name",
+                       Icon:         "emoji-smile-fill",
+                       Description:  
"badge.default_badges.first_reaction.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 1,
+                       Level:        entity.BadgeLevelBronze,
+                       Single:       entity.BadgeSingleAward,
+                       Handler:      "FirstReactedPost",
+               },
+               {
+                       Name:         "badge.default_badges.first_share.name",
+                       Icon:         "share-fill",
+                       Description:  "badge.default_badges.first_share.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 1,
+                       Level:        entity.BadgeLevelBronze,
+                       Single:       entity.BadgeSingleAward,
+                       Handler:      "FirstSharedPost",
+               },
+               {
+                       Name:         "badge.default_badges.scholar.name",
+                       Icon:         "check-circle-fill",
+                       Description:  "badge.default_badges.scholar.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 1,
+                       Level:        entity.BadgeLevelBronze,
+                       Single:       entity.BadgeSingleAward,
+                       Handler:      "FirstAcceptAnswer",
+               },
+               {
+                       Name:         "badge.default_badges.solved.name",
+                       Icon:         "check-square-fill",
+                       Description:  "badge.default_badges.solved.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 2,
+                       Level:        entity.BadgeLevelBronze,
+                       Single:       entity.BadgeSingleAward,
+                       Handler:      "ReachAnswerAcceptedAmount",
+                       Param:        `{"amount":"1"}`,
+               },
+               {
+                       Name:         "badge.default_badges.nice_answer.name",
+                       Icon:         "chat-square-text-fill",
+                       Description:  "badge.default_badges.nice_answer.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 3,
+                       Level:        entity.BadgeLevelBronze,
+                       Single:       entity.BadgeMultiAward,
+                       Handler:      "ReachAnswerVote",
+                       Param:        `{"amount":"10"}`,
+               },
+               {
+                       Name:         "badge.default_badges.good_answer.name",
+                       Icon:         "chat-square-text-fill",
+                       Description:  "badge.default_badges.good_answer.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 3,
+                       Level:        entity.BadgeLevelSilver,
+                       Single:       entity.BadgeMultiAward,
+                       Handler:      "ReachAnswerVote",
+                       Param:        `{"amount":"25"}`,
+               },
+               {
+                       Name:         "badge.default_badges.great_answer.name",
+                       Icon:         "chat-square-text-fill",
+                       Description:  "badge.default_badges.great_answer.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 3,
+                       Level:        entity.BadgeLevelGold,
+                       Single:       entity.BadgeMultiAward,
+                       Handler:      "ReachAnswerVote",
+                       Param:        `{"amount":"50"}`,
+               },
+               {
+                       Name:         "badge.default_badges.nice_question.name",
+                       Icon:         "question-circle-fill",
+                       Description:  "badge.default_badges.nice_question.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 3,
+                       Level:        entity.BadgeLevelBronze,
+                       Single:       entity.BadgeMultiAward,
+                       Handler:      "ReachQuestionVote",
+                       Param:        `{"amount":"10"}`,
+               },
+               {
+                       Name:         "badge.default_badges.good_question.name",
+                       Icon:         "question-circle-fill",
+                       Description:  "badge.default_badges.good_question.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 3,
+                       Level:        entity.BadgeLevelSilver,
+                       Single:       entity.BadgeMultiAward,
+                       Handler:      "ReachQuestionVote",
+                       Param:        `{"amount":"25"}`,
+               },
+               {
+                       Name:         
"badge.default_badges.great_question.name",
+                       Icon:         "question-circle-fill",
+                       Description:  
"badge.default_badges.great_question.desc",
+                       Status:       entity.BadgeStatusActive,
+                       BadgeGroupID: 3,
+                       Level:        entity.BadgeLevelGold,
+                       Single:       entity.BadgeMultiAward,
+                       Handler:      "ReachQuestionVote",
+                       Param:        `{"amount":"50"}`,
+               },
+       }
 )
diff --git a/internal/migrations/v22.go b/internal/migrations/v22.go
index d3d81d84..ab7185e3 100644
--- a/internal/migrations/v22.go
+++ b/internal/migrations/v22.go
@@ -21,265 +21,51 @@ package migrations
 
 import (
        "context"
+       "fmt"
        "github.com/apache/incubator-answer/internal/base/data"
        "github.com/apache/incubator-answer/internal/entity"
        "github.com/apache/incubator-answer/internal/repo/unique"
-       "time"
        "xorm.io/xorm"
 )
 
-var (
-       defaultBadgeGroupTable = []*entity.BadgeGroup{
-               {ID: "1", Name: 
"badge.default_badge_groups.getting_started.name"},
-               {ID: "2", Name: "badge.default_badge_groups.community.name"},
-               {ID: "3", Name: "badge.default_badge_groups.posting.name"},
-       }
-
-       defaultBadgeTable = []*entity.Badge{
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         
"badge.default_badges.autobiographer.name",
-                       Icon:         "person-badge-fill",
-                       AwardCount:   0,
-                       Description:  
"badge.default_badges.autobiographer.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 1,
-                       Level:        entity.BadgeLevelBronze,
-                       Single:       entity.BadgeSingleAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         "badge.default_badges.editor.name",
-                       Icon:         "pencil-fill",
-                       AwardCount:   0,
-                       Description:  "badge.default_badges.editor.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 1,
-                       Level:        entity.BadgeLevelBronze,
-                       Single:       entity.BadgeSingleAward,
-                       Collect:      "question",
-                       Handler:      "FirstQuestion",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         "badge.default_badges.first_flag.name",
-                       Icon:         "flag-fill",
-                       AwardCount:   0,
-                       Description:  "badge.default_badges.first_flag.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 1,
-                       Level:        entity.BadgeLevelBronze,
-                       Single:       entity.BadgeSingleAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         "badge.default_badges.first_upvote.name",
-                       Icon:         "hand-thumbs-up-fill",
-                       AwardCount:   0,
-                       Description:  "badge.default_badges.first_upvote.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 1,
-                       Level:        entity.BadgeLevelBronze,
-                       Single:       entity.BadgeSingleAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         
"badge.default_badges.first_reaction.name",
-                       Icon:         "emoji-smile-fill",
-                       AwardCount:   0,
-                       Description:  
"badge.default_badges.first_reaction.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 1,
-                       Level:        entity.BadgeLevelBronze,
-                       Single:       entity.BadgeSingleAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         "badge.default_badges.first_share.name",
-                       Icon:         "share-fill",
-                       AwardCount:   0,
-                       Description:  "badge.default_badges.first_share.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 1,
-                       Level:        entity.BadgeLevelBronze,
-                       Single:       entity.BadgeSingleAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         "badge.default_badges.scholar.name",
-                       Icon:         "check-circle-fill",
-                       AwardCount:   0,
-                       Description:  "badge.default_badges.scholar.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 1,
-                       Level:        entity.BadgeLevelBronze,
-                       Single:       entity.BadgeSingleAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         "badge.default_badges.solved.name",
-                       Icon:         "check-square-fill",
-                       AwardCount:   0,
-                       Description:  "badge.default_badges.solved.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 2,
-                       Level:        entity.BadgeLevelBronze,
-                       Single:       entity.BadgeSingleAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         "badge.default_badges.nice_answer.name",
-                       Icon:         "chat-square-text-fill",
-                       AwardCount:   0,
-                       Description:  "badge.default_badges.nice_answer.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 3,
-                       Level:        entity.BadgeLevelBronze,
-                       Single:       entity.BadgeMultiAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         "badge.default_badges.good_answer.name",
-                       Icon:         "chat-square-text-fill",
-                       AwardCount:   0,
-                       Description:  "badge.default_badges.good_answer.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 3,
-                       Level:        entity.BadgeLevelSilver,
-                       Single:       entity.BadgeMultiAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         "badge.default_badges.great_answer.name",
-                       Icon:         "chat-square-text-fill",
-                       AwardCount:   0,
-                       Description:  "badge.default_badges.great_answer.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 3,
-                       Level:        entity.BadgeLevelGold,
-                       Single:       entity.BadgeMultiAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         "badge.default_badges.nice_question.name",
-                       Icon:         "question-circle-fill",
-                       AwardCount:   0,
-                       Description:  "badge.default_badges.nice_question.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 3,
-                       Level:        entity.BadgeLevelBronze,
-                       Single:       entity.BadgeMultiAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         "badge.default_badges.good_question.name",
-                       Icon:         "question-circle-fill",
-                       AwardCount:   0,
-                       Description:  "badge.default_badges.good_question.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 3,
-                       Level:        entity.BadgeLevelSilver,
-                       Single:       entity.BadgeSingleAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-               {
-                       CreatedAt:    time.Now(),
-                       UpdatedAt:    time.Now(),
-                       Name:         
"badge.default_badges.great_question.name",
-                       Icon:         "question-circle-fill",
-                       AwardCount:   0,
-                       Description:  
"badge.default_badges.great_question.desc",
-                       Status:       entity.BadgeStatusActive,
-                       BadgeGroupID: 3,
-                       Level:        entity.BadgeLevelGold,
-                       Single:       entity.BadgeMultiAward,
-                       Collect:      "",
-                       Handler:      "",
-                       Param:        "",
-               },
-       }
-)
-
 func addBadges(ctx context.Context, x *xorm.Engine) (err error) {
        uniqueIDRepo := unique.NewUniqueIDRepo(&data.Data{DB: x})
-       // create table
-       err = x.Context(ctx).Sync(new(entity.Badge))
-       if err != nil {
-               return
-       }
 
-       err = x.Context(ctx).Sync(new(entity.BadgeGroup))
+       err = x.Context(ctx).Sync(new(entity.Badge), new(entity.BadgeGroup), 
new(entity.BadgeAward))
        if err != nil {
-               return
+               return fmt.Errorf("sync table failed: %w", err)
        }
 
-       err = x.Context(ctx).Sync(new(entity.BadgeAward))
-       if err != nil {
-               return
+       for _, badgeGroup := range defaultBadgeGroupTable {
+               exist, err := x.Context(ctx).Get(&entity.BadgeGroup{ID: 
badgeGroup.ID})
+               if err != nil {
+                       return err
+               }
+               if exist {
+                       _, err = 
x.Context(ctx).ID(badgeGroup.ID).Update(badgeGroup)
+               } else {
+                       _, err = x.Context(ctx).Insert(badgeGroup)
+               }
+               if err != nil {
+                       return fmt.Errorf("insert badge group failed: %w", err)
+               }
        }
 
-       // insert default data
-       _, err = x.Context(ctx).Insert(defaultBadgeGroupTable)
-       if err != nil {
-               return
-       }
        for _, badge := range defaultBadgeTable {
-               badge.ID, err = uniqueIDRepo.GenUniqueIDStr(ctx, 
new(entity.Badge).TableName())
+               exist, err := x.Context(ctx).Get(&entity.Badge{Name: 
badge.Name})
                if err != nil {
-                       return
+                       return err
+               }
+               if exist {
+                       continue
                }
-               _, err = x.Context(ctx).Insert(badge)
+               badge.ID, err = uniqueIDRepo.GenUniqueIDStr(ctx, 
new(entity.Badge).TableName())
                if err != nil {
-                       return
+                       return err
+               }
+
+               if _, err := x.Context(ctx).Insert(badge); err != nil {
+                       return err
                }
        }
        return
diff --git a/internal/repo/badge/badge_event_rule.go 
b/internal/repo/badge/badge_event_rule.go
index f912c2bb..f107203e 100644
--- a/internal/repo/badge/badge_event_rule.go
+++ b/internal/repo/badge/badge_event_rule.go
@@ -86,91 +86,87 @@ func (br *eventRuleRepo) HandleEventWithRule(ctx 
context.Context, msg *schema.Ev
 // FirstUpdateUserProfile first update user profile
 func (br *eventRuleRepo) FirstUpdateUserProfile(ctx context.Context,
        event *schema.EventMsg) (awards []*entity.BadgeAward, err error) {
-       b := br.getBadgeByHandler(ctx, "FirstUpdateUserProfile")
-       if b == nil {
-               return nil, nil
-       }
-       bean := &entity.User{ID: event.UserID}
-       exist, err := br.data.DB.Context(ctx).Get(bean)
-       if err != nil {
-               return nil, 
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
-       }
-       if !exist {
-               return nil, nil
-       }
-       if len(bean.Bio) > 0 {
-               return append(awards, br.createBadgeAward(event.UserID, b.ID, 
entity.BadgeOnceAwardKey)), nil
+       badges := br.getBadgesByHandler(ctx, "FirstUpdateUserProfile")
+       for _, b := range badges {
+               bean := &entity.User{ID: event.UserID}
+               exist, err := br.data.DB.Context(ctx).Get(bean)
+               if err != nil {
+                       return nil, 
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+               }
+               if !exist {
+                       continue
+               }
+               if len(bean.Bio) > 0 {
+                       awards = append(awards, 
br.createBadgeAward(event.UserID, "", b))
+               }
        }
-       return nil, nil
+       return awards, nil
 }
 
 // FirstPostEdit first post edit
 func (br *eventRuleRepo) FirstPostEdit(ctx context.Context,
        event *schema.EventMsg) (awards []*entity.BadgeAward, err error) {
-       b := br.getBadgeByHandler(ctx, "FirstPostEdit")
-       if b == nil {
-               return nil, nil
+       badges := br.getBadgesByHandler(ctx, "FirstPostEdit")
+       for _, b := range badges {
+               awards = append(awards, br.createBadgeAward(event.UserID, 
event.GetObjectID(), b))
        }
-       return append(awards, br.createBadgeAward(event.UserID, b.ID, 
event.GetObjectID())), nil
+       return awards, nil
 }
 
 // FirstFlaggedPost first flagged post.
 func (br *eventRuleRepo) FirstFlaggedPost(ctx context.Context,
        event *schema.EventMsg) (awards []*entity.BadgeAward, err error) {
-       b := br.getBadgeByHandler(ctx, "FirstFlaggedPost")
-       if b == nil {
-               return nil, nil
+       badges := br.getBadgesByHandler(ctx, "FirstFlaggedPost")
+       for _, b := range badges {
+               awards = append(awards, br.createBadgeAward(event.UserID, 
event.GetObjectID(), b))
        }
-       return append(awards, br.createBadgeAward(event.UserID, b.ID, 
event.GetObjectID())), nil
+       return awards, nil
 }
 
 // FirstVotedPost first voted post
 func (br *eventRuleRepo) FirstVotedPost(ctx context.Context,
        event *schema.EventMsg) (awards []*entity.BadgeAward, err error) {
-       b := br.getBadgeByHandler(ctx, "FirstVotedPost")
-       if b == nil {
-               return nil, nil
+       badges := br.getBadgesByHandler(ctx, "FirstVotedPost")
+       for _, b := range badges {
+               awards = append(awards, br.createBadgeAward(event.UserID, 
event.GetObjectID(), b))
        }
-       return append(awards, br.createBadgeAward(event.UserID, b.ID, 
event.GetObjectID())), nil
+       return awards, nil
 }
 
 // FirstReactedPost first reacted post
 func (br *eventRuleRepo) FirstReactedPost(ctx context.Context,
        event *schema.EventMsg) (awards []*entity.BadgeAward, err error) {
-       b := br.getBadgeByHandler(ctx, "FirstReactedPost")
-       if b == nil {
-               return nil, nil
+       badges := br.getBadgesByHandler(ctx, "FirstReactedPost")
+       for _, b := range badges {
+               awards = append(awards, br.createBadgeAward(event.UserID, 
event.GetObjectID(), b))
        }
-       return append(awards, br.createBadgeAward(event.UserID, b.ID, 
event.GetObjectID())), nil
+       return awards, nil
 }
 
 // FirstSharedPost first shared post
 func (br *eventRuleRepo) FirstSharedPost(ctx context.Context,
        event *schema.EventMsg) (awards []*entity.BadgeAward, err error) {
-       b := br.getBadgeByHandler(ctx, "FirstSharedPost")
-       if b == nil {
-               return nil, nil
+       badges := br.getBadgesByHandler(ctx, "FirstSharedPost")
+       for _, b := range badges {
+               awards = append(awards, br.createBadgeAward(event.UserID, 
event.GetObjectID(), b))
        }
-       return append(awards, br.createBadgeAward(event.UserID, b.ID, 
event.GetObjectID())), nil
+       return awards, nil
 }
 
 // FirstAcceptAnswer user first accept answer
 func (br *eventRuleRepo) FirstAcceptAnswer(ctx context.Context,
        event *schema.EventMsg) (awards []*entity.BadgeAward, err error) {
-       b := br.getBadgeByHandler(ctx, "FirstAcceptAnswer")
-       if b == nil {
-               return nil, nil
+       badges := br.getBadgesByHandler(ctx, "FirstAcceptAnswer")
+       for _, b := range badges {
+               awards = append(awards, br.createBadgeAward(event.UserID, 
event.GetObjectID(), b))
        }
-       return append(awards, br.createBadgeAward(event.UserID, b.ID, 
event.GetObjectID())), nil
+       return awards, nil
 }
 
 // ReachAnswerAcceptedAmount reach answer accepted amount
 func (br *eventRuleRepo) ReachAnswerAcceptedAmount(ctx context.Context,
        event *schema.EventMsg) (awards []*entity.BadgeAward, err error) {
-       b := br.getBadgeByHandler(ctx, "ReachAnswerAcceptedAmount")
-       if b == nil {
-               return nil, nil
-       }
+       badges := br.getBadgesByHandler(ctx, "ReachAnswerAcceptedAmount")
        if len(event.AnswerUserID) == 0 {
                return nil, nil
        }
@@ -185,79 +181,76 @@ func (br *eventRuleRepo) ReachAnswerAcceptedAmount(ctx 
context.Context,
                return nil, 
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
        }
 
-       // get badge requirement
-       requirement := b.GetIntParam("amount")
-       if requirement == 0 || amount < requirement {
-               return nil, nil
+       for _, b := range badges {
+               // get badge requirement
+               requirement := b.GetIntParam("amount")
+               if requirement == 0 || amount < requirement {
+                       continue
+               }
+               awards = append(awards, br.createBadgeAward(event.AnswerUserID, 
event.AnswerID, b))
        }
-
-       return append(awards, br.createBadgeAward(event.UserID, b.ID, 
event.GetObjectID())), nil
+       return awards, nil
 }
 
 // ReachAnswerVote reach answer vote
 func (br *eventRuleRepo) ReachAnswerVote(ctx context.Context,
        event *schema.EventMsg) (awards []*entity.BadgeAward, err error) {
-       b := br.getBadgeByHandler(ctx, "ReachAnswerVote")
-       if b == nil {
-               return nil, nil
-       }
-
+       badges := br.getBadgesByHandler(ctx, "ReachAnswerVote")
        // get vote amount
        amount, _ := strconv.Atoi(event.GetExtra("vote_up_amount"))
        if amount == 0 {
                return nil, nil
        }
 
-       // get badge requirement
-       requirement := b.GetIntParam("amount")
-       if requirement == 0 || int64(amount) < requirement {
-               return nil, nil
+       for _, b := range badges {
+               // get badge requirement
+               requirement := b.GetIntParam("amount")
+               if requirement == 0 || int64(amount) < requirement {
+                       continue
+               }
+               awards = append(awards, br.createBadgeAward(event.AnswerUserID, 
event.AnswerID, b))
        }
-
-       return append(awards, br.createBadgeAward(event.AnswerUserID, b.ID, 
event.AnswerID)), nil
+       return awards, nil
 }
 
 // ReachQuestionVote reach question vote
 func (br *eventRuleRepo) ReachQuestionVote(ctx context.Context,
        event *schema.EventMsg) (awards []*entity.BadgeAward, err error) {
-       b := br.getBadgeByHandler(ctx, "ReachQuestionVote")
-       if b == nil {
-               return nil, nil
-       }
-
+       badges := br.getBadgesByHandler(ctx, "ReachQuestionVote")
        // get vote amount
        amount, _ := strconv.Atoi(event.GetExtra("vote_up_amount"))
        if amount == 0 {
                return nil, nil
        }
 
-       // get badge requirement
-       requirement := b.GetIntParam("amount")
-       if requirement == 0 || int64(amount) < requirement {
-               return nil, nil
+       for _, b := range badges {
+               // get badge requirement
+               requirement := b.GetIntParam("amount")
+               if requirement == 0 || int64(amount) < requirement {
+                       continue
+               }
+               awards = append(awards, 
br.createBadgeAward(event.QuestionUserID, event.QuestionID, b))
        }
-
-       return append(awards, br.createBadgeAward(event.QuestionUserID, b.ID, 
event.QuestionID)), nil
+       return awards, nil
 }
 
-func (br *eventRuleRepo) getBadgeByHandler(ctx context.Context, handler 
string) (b *entity.Badge) {
-       b = &entity.Badge{Handler: handler}
-       exist, err := br.data.DB.Context(ctx).Get(b)
+func (br *eventRuleRepo) getBadgesByHandler(ctx context.Context, handler 
string) (badges []*entity.Badge) {
+       badges = make([]*entity.Badge, 0)
+       err := br.data.DB.Context(ctx).Where("handler = ?", 
handler).Find(&badges)
        if err != nil {
                log.Errorf("error getting badge by handler %s: %v", handler, 
err)
                return nil
        }
-       if !exist {
-               log.Errorf("badge not found by handler %s", handler)
-               return nil
-       }
-       return b
+       return badges
 }
 
-func (br *eventRuleRepo) createBadgeAward(userID, badgeID, awardKey string) 
(awards *entity.BadgeAward) {
+func (br *eventRuleRepo) createBadgeAward(userID, awardKey string, badge 
*entity.Badge) (awards *entity.BadgeAward) {
+       if badge.Single == entity.BadgeSingleAward {
+               awardKey = entity.BadgeOnceAwardKey
+       }
        return &entity.BadgeAward{
                UserID:   userID,
-               BadgeID:  badgeID,
+               BadgeID:  badge.ID,
                AwardKey: awardKey,
        }
 }
diff --git a/internal/service/content/answer_service.go 
b/internal/service/content/answer_service.go
index 5674a79b..496f7546 100644
--- a/internal/service/content/answer_service.go
+++ b/internal/service/content/answer_service.go
@@ -446,8 +446,10 @@ func (as *AnswerService) AcceptAnswer(ctx context.Context, 
req *schema.AcceptAns
                oldAnswerInfo.ID = uid.DeShortID(oldAnswerInfo.ID)
        }
 
-       as.eventQueueService.Send(ctx, 
schema.NewEvent(constant.EventQuestionAccept, req.UserID).
-               QID(questionInfo.ID, questionInfo.UserID).AID(req.AnswerID, 
req.UserID))
+       if acceptedAnswerInfo != nil {
+               as.eventQueueService.Send(ctx, 
schema.NewEvent(constant.EventQuestionAccept, req.UserID).
+                       QID(questionInfo.ID, 
questionInfo.UserID).AID(acceptedAnswerInfo.ID, acceptedAnswerInfo.UserID))
+       }
 
        as.updateAnswerRank(ctx, req.UserID, questionInfo, acceptedAnswerInfo, 
oldAnswerInfo)
        return nil

Reply via email to