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

linkinstar pushed a commit to branch feat/1.4.0/badge
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git


The following commit(s) were added to refs/heads/feat/1.4.0/badge by this push:
     new bede0adb feat(badge): award badge for user
bede0adb is described below

commit bede0adbf783a840fdeefec8afeb61e1e71cb864
Author: LinkinStars <[email protected]>
AuthorDate: Wed Aug 14 10:37:37 2024 +0800

    feat(badge): award badge for user
---
 cmd/wire_gen.go                               |  4 +-
 docs/docs.go                                  | 19 ++++++
 internal/entity/badge_award_entity.go         | 16 ++---
 internal/repo/badge/badge_event_rule.go       |  2 +-
 internal/repo/badge_award/badge_award_repo.go | 88 +++++++++++++++++++--------
 internal/service/badge/badge_award_service.go | 47 +++++---------
 internal/service/badge/badge_event_handler.go | 34 ++++++-----
 7 files changed, 129 insertions(+), 81 deletions(-)

diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go
index d4034b6b..9acd76ee 100644
--- a/cmd/wire_gen.go
+++ b/cmd/wire_gen.go
@@ -263,9 +263,9 @@ func initApplication(debug bool, serverConf *conf.Server, 
dbConf *data.Database,
        badgeGroupRepo := badge_group.NewBadgeGroupRepo(dataData, uniqueIDRepo)
        badgeAwardRepo := badge_award.NewBadgeAwardRepo(dataData, uniqueIDRepo)
        eventRuleRepo := badge.NewEventRuleRepo(dataData)
-       badgeEventService := badge2.NewBadgeEventService(dataData, 
eventQueueService, badgeRepo, eventRuleRepo)
-       badgeService := badge2.NewBadgeService(badgeRepo, badgeGroupRepo, 
badgeAwardRepo, badgeEventService)
        badgeAwardService := badge2.NewBadgeAwardService(badgeAwardRepo, 
badgeRepo, userCommon, objService)
+       badgeEventService := badge2.NewBadgeEventService(dataData, 
eventQueueService, badgeRepo, eventRuleRepo, badgeAwardService)
+       badgeService := badge2.NewBadgeService(badgeRepo, badgeGroupRepo, 
badgeAwardRepo, badgeEventService)
        badgeController := controller.NewBadgeController(badgeService, 
badgeAwardService)
        controller_adminBadgeController := 
controller_admin.NewBadgeController(badgeService)
        answerAPIRouter := router.NewAnswerAPIRouter(langController, 
userController, commentController, reportController, voteController, 
tagController, followController, collectionController, questionController, 
answerController, searchController, revisionController, rankController, 
userAdminController, reasonController, themeController, siteInfoController, 
controllerSiteInfoController, notificationController, dashboardController, 
uploadController, activityController, roleController, pluginCon [...]
diff --git a/docs/docs.go b/docs/docs.go
index 7fef400f..cfefe0ed 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -1,3 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
 // Package docs Code generated by swaggo/swag. DO NOT EDIT
 package docs
 
diff --git a/internal/entity/badge_award_entity.go 
b/internal/entity/badge_award_entity.go
index 0eb30227..5ba475cd 100644
--- a/internal/entity/badge_award_entity.go
+++ b/internal/entity/badge_award_entity.go
@@ -24,18 +24,20 @@ import "time"
 const (
        IsBadgeNotDeleted = 0
        IsBadgeDeleted    = 1
+
+       BadgeOnceAwardKey = "0"
 )
 
 // BadgeAward badge_award
 type BadgeAward struct {
        ID             string    `xorm:"not null pk BIGINT(20) id"`
-       CreatedAt      time.Time `json:"created_at" xorm:"created not null 
default CURRENT_TIMESTAMP TIMESTAMP created_at"`
-       UpdatedAt      time.Time `json:"updated_at" xorm:"updated not null 
default CURRENT_TIMESTAMP TIMESTAMP updated_at"`
-       UserID         string    `json:"user_id" xorm:"not null index 
BIGINT(20) user_id"`
-       BadgeID        string    `json:"badge_id" xorm:"not null index 
BIGINT(20) badge_id"`
-       AwardKey       string    `json:"award_key" xorm:"not null index 
VARCHAR(64) award_key"`
-       BadgeGroupID   int64     `json:"badge_group_id" xorm:"not null index 
BIGINT(20) badge_group_id"`
-       IsBadgeDeleted int8      `json:"is_badge_deleted" xorm:"not null index 
TINYINT(1) is_badge_deleted"`
+       CreatedAt      time.Time `xorm:"created not null default 
CURRENT_TIMESTAMP TIMESTAMP created_at"`
+       UpdatedAt      time.Time `xorm:"updated not null default 
CURRENT_TIMESTAMP TIMESTAMP updated_at"`
+       UserID         string    `xorm:"not null index BIGINT(20) user_id"`
+       BadgeID        string    `xorm:"not null index BIGINT(20) badge_id"`
+       AwardKey       string    `xorm:"not null index VARCHAR(64) award_key"`
+       BadgeGroupID   int64     `xorm:"not null index BIGINT(20) 
badge_group_id"`
+       IsBadgeDeleted int8      `xorm:"not null TINYINT(1) is_badge_deleted"`
 }
 
 // TableName badge_award table name
diff --git a/internal/repo/badge/badge_event_rule.go 
b/internal/repo/badge/badge_event_rule.go
index 41d56686..f912c2bb 100644
--- a/internal/repo/badge/badge_event_rule.go
+++ b/internal/repo/badge/badge_event_rule.go
@@ -99,7 +99,7 @@ func (br *eventRuleRepo) FirstUpdateUserProfile(ctx 
context.Context,
                return nil, nil
        }
        if len(bean.Bio) > 0 {
-               return append(awards, br.createBadgeAward(event.UserID, b.ID, 
"")), nil
+               return append(awards, br.createBadgeAward(event.UserID, b.ID, 
entity.BadgeOnceAwardKey)), nil
        }
        return nil, nil
 }
diff --git a/internal/repo/badge_award/badge_award_repo.go 
b/internal/repo/badge_award/badge_award_repo.go
index 5a5d56cd..058fa864 100644
--- a/internal/repo/badge_award/badge_award_repo.go
+++ b/internal/repo/badge_award/badge_award_repo.go
@@ -21,6 +21,7 @@ package badge_award
 
 import (
        "context"
+       "fmt"
        "github.com/apache/incubator-answer/internal/base/data"
        "github.com/apache/incubator-answer/internal/base/pager"
        "github.com/apache/incubator-answer/internal/base/reason"
@@ -28,6 +29,7 @@ import (
        "github.com/apache/incubator-answer/internal/service/badge"
        "github.com/apache/incubator-answer/internal/service/unique"
        "github.com/segmentfault/pacman/errors"
+       "xorm.io/xorm"
 )
 
 type badgeAwardRepo struct {
@@ -42,38 +44,62 @@ func NewBadgeAwardRepo(data *data.Data, uniqueIDRepo 
unique.UniqueIDRepo) badge.
        }
 }
 
-func (r *badgeAwardRepo) Add(ctx context.Context, badgeAward 
*entity.BadgeAward) (err error) {
+// AwardBadgeForUser award badge for user
+func (r *badgeAwardRepo) AwardBadgeForUser(ctx context.Context, badgeAward 
*entity.BadgeAward) (err error) {
        badgeAward.ID, err = r.uniqueIDRepo.GenUniqueIDStr(ctx, 
entity.BadgeAward{}.TableName())
        if err != nil {
-               return
+               return err
        }
-       _, err = r.data.DB.Context(ctx).Insert(badgeAward)
-       return
-}
-func (r *badgeAwardRepo) CheckIsAward(ctx context.Context, badgeID string, 
userID string, awardKey string, singleOrMulti int8) (isAward bool) {
-       isAward = false
-       if singleOrMulti == entity.BadgeSingleAward {
-               _, exists, err := r.GetByUserIdAndBadgeId(ctx, userID, badgeID)
+
+       _, err = r.data.DB.Transaction(func(session *xorm.Session) (result any, 
err error) {
+               session = session.Context(ctx)
+
+               badgeInfo := &entity.Badge{}
+               exist, err := 
session.ID(badgeAward.BadgeID).ForUpdate().Get(badgeInfo)
                if err != nil {
-                       err = 
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
-                       return
+                       return nil, err
                }
-               if exists {
-                       return true
+               if !exist {
+                       return nil, fmt.Errorf("badge not exist")
                }
-       } else {
-               _, exists, err := r.GetByUserIdAndBadgeIdAndObjectId(ctx, 
userID, badgeID, awardKey)
+
+               old := &entity.BadgeAward{}
+               exist, err = session.Where("user_id = ? AND badge_id = ? AND 
award_key = ? AND is_badge_deleted = 0",
+                       badgeAward.UserID, badgeAward.BadgeID, 
badgeAward.AwardKey).Get(old)
                if err != nil {
-                       err = 
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
-                       return
+                       return nil, err
                }
-               if exists {
-                       return true
+               if exist {
+                       return nil, fmt.Errorf("badge already awarded")
                }
+
+               _, err = session.Insert(badgeAward)
+               if err != nil {
+                       return nil, err
+               }
+
+               return session.ID(badgeInfo.ID).Incr("award_count", 
1).Update(&entity.Badge{})
+       })
+       if err != nil {
+               return 
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
        }
+       return nil
+}
 
-       return
+// CheckIsAward check this badge is awarded for this user or not
+func (r *badgeAwardRepo) CheckIsAward(ctx context.Context, badgeID, userID, 
awardKey string, singleOrMulti int8) (
+       isAward bool, err error) {
+       if singleOrMulti == entity.BadgeSingleAward {
+               _, isAward, err = r.GetByUserIdAndBadgeId(ctx, userID, badgeID)
+       } else {
+               _, isAward, err = r.GetByUserIdAndBadgeIdAndAwardKey(ctx, 
userID, badgeID, awardKey)
+       }
+       if err != nil {
+               err = 
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+       }
+       return isAward, err
 }
+
 func (r *badgeAwardRepo) CountByUserIdAndBadgeLevel(ctx context.Context, 
userID string, badgeLevel entity.BadgeLevel) (awardCount int64) {
        return
 }
@@ -161,13 +187,25 @@ func (r *badgeAwardRepo) ListNewestByUserIdAndLevel(ctx 
context.Context, userID
 }
 
 // GetByUserIdAndBadgeId get badge award by user id and badge id
-func (r *badgeAwardRepo) GetByUserIdAndBadgeId(ctx context.Context, userID 
string, badgeID string) (badgeAward *entity.BadgeAward, exists bool, err error) 
{
-       exists, err = r.data.DB.Context(ctx).Where("user_id = ? AND badge_id = 
? AND is_badge_deleted = 0", userID, badgeID).Get(&badgeAward)
+func (r *badgeAwardRepo) GetByUserIdAndBadgeId(ctx context.Context, userID 
string, badgeID string) (
+       badgeAward *entity.BadgeAward, exists bool, err error) {
+       badgeAward = &entity.BadgeAward{}
+       exists, err = r.data.DB.Context(ctx).
+               Where("user_id = ? AND badge_id = ? AND is_badge_deleted = 0", 
userID, badgeID).Get(badgeAward)
+       if err != nil {
+               err = 
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+       }
        return
 }
 
-// GetByUserIdAndBadgeIdAndObjectId get badge award by user id, badge id and 
object id
-func (r *badgeAwardRepo) GetByUserIdAndBadgeIdAndObjectId(ctx context.Context, 
userID string, badgeID string, awardKey string) (badgeAward *entity.BadgeAward, 
exists bool, err error) {
-       exists, err = r.data.DB.Context(ctx).Where("user_id = ? AND badge_id = 
? AND award_key = ? AND is_badge_deleted = 0", userID, badgeID, 
awardKey).Get(&badgeAward)
+// GetByUserIdAndBadgeIdAndAwardKey get badge award by user id and badge id 
and award key
+func (r *badgeAwardRepo) GetByUserIdAndBadgeIdAndAwardKey(ctx context.Context, 
userID string, badgeID string, awardKey string) (
+       badgeAward *entity.BadgeAward, exists bool, err error) {
+       badgeAward = &entity.BadgeAward{}
+       exists, err = r.data.DB.Context(ctx).
+               Where("user_id = ? AND badge_id = ? AND award_key = ? AND 
is_badge_deleted = 0", userID, badgeID, awardKey).Get(badgeAward)
+       if err != nil {
+               err = 
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
+       }
        return
 }
diff --git a/internal/service/badge/badge_award_service.go 
b/internal/service/badge/badge_award_service.go
index 96a9743f..3883de61 100644
--- a/internal/service/badge/badge_award_service.go
+++ b/internal/service/badge/badge_award_service.go
@@ -33,12 +33,11 @@ import (
        "github.com/jinzhu/copier"
        "github.com/segmentfault/pacman/errors"
        "github.com/segmentfault/pacman/log"
-       "time"
 )
 
 type BadgeAwardRepo interface {
-       Add(ctx context.Context, badgeAward *entity.BadgeAward) (err error)
-       CheckIsAward(ctx context.Context, badgeID string, userID string, 
awardKey string, singleOrMulti int8) bool
+       CheckIsAward(ctx context.Context, badgeID string, userID string, 
awardKey string, singleOrMulti int8) (isAward bool, err error)
+       AwardBadgeForUser(ctx context.Context, badgeAward *entity.BadgeAward) 
(err error)
 
        CountByUserIdAndBadgeLevel(ctx context.Context, userID string, 
badgeLevel entity.BadgeLevel) (awardCount int64)
        CountByUserId(ctx context.Context, userID string) (awardCount int64)
@@ -62,7 +61,7 @@ type BadgeAwardRepo interface {
        ListNewestByUserIdAndLevel(ctx context.Context, userID string, level 
int, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, 
err error)
 
        GetByUserIdAndBadgeId(ctx context.Context, userID string, badgeID 
string) (badgeAward *entity.BadgeAward, exists bool, err error)
-       GetByUserIdAndBadgeIdAndObjectId(ctx context.Context, userID string, 
badgeID string, awardKey string) (badgeAward *entity.BadgeAward, exists bool, 
err error)
+       GetByUserIdAndBadgeIdAndAwardKey(ctx context.Context, userID string, 
badgeID string, awardKey string) (badgeAward *entity.BadgeAward, exists bool, 
err error)
 }
 
 type BadgeAwardService struct {
@@ -151,48 +150,32 @@ func (b *BadgeAwardService) GetBadgeAwardList(
 }
 
 // Award award badge
-func (b *BadgeAwardService) Award(ctx context.Context, badgeID string, userID 
string, awardKey string, force bool, createdAt time.Time) (err error) {
-       var (
-               badgeData       *entity.Badge
-               exists, awarded bool
-       )
-
-       badgeData, exists, err = b.badgeRepo.GetByID(ctx, badgeID)
+func (b *BadgeAwardService) Award(ctx context.Context, badgeID string, userID 
string, awardKey string) (err error) {
+       badgeData, exists, err := b.badgeRepo.GetByID(ctx, badgeID)
        if err != nil {
-               return
+               return err
        }
 
        if !exists || badgeData.Status == entity.BadgeStatusInactive {
-               err = errors.BadRequest(reason.BadgeObjectNotFound)
-               return
+               return errors.BadRequest(reason.BadgeObjectNotFound)
        }
 
-       awarded = b.badgeAwardRepo.CheckIsAward(ctx, badgeID, userID, awardKey, 
badgeData.Single)
-       if !force && awarded {
-               return
+       alreadyAwarded, err := b.badgeAwardRepo.CheckIsAward(ctx, badgeID, 
userID, awardKey, badgeData.Single)
+       if err != nil {
+               return err
        }
-
-       if createdAt.IsZero() {
-               createdAt = time.Now()
+       if alreadyAwarded {
+               return nil
        }
 
-       err = b.badgeAwardRepo.Add(ctx, &entity.BadgeAward{
-               CreatedAt:      createdAt,
-               UpdatedAt:      createdAt,
+       badgeAward := &entity.BadgeAward{
                UserID:         userID,
                BadgeID:        badgeID,
                AwardKey:       awardKey,
                BadgeGroupID:   badgeData.BadgeGroupID,
-               IsBadgeDeleted: 0,
-       })
-       if err != nil {
-               return
+               IsBadgeDeleted: entity.IsBadgeNotDeleted,
        }
-
-       // increment badge award count
-       err = b.badgeRepo.UpdateAwardCount(ctx, badgeID, 1)
-
-       return
+       return b.badgeAwardRepo.AwardBadgeForUser(ctx, badgeAward)
 }
 
 // GetUserBadgeAwardList get user badge award list
diff --git a/internal/service/badge/badge_event_handler.go 
b/internal/service/badge/badge_event_handler.go
index 09331197..f990260b 100644
--- a/internal/service/badge/badge_event_handler.go
+++ b/internal/service/badge/badge_event_handler.go
@@ -21,12 +21,11 @@ package badge
 
 import (
        "context"
+       "github.com/apache/incubator-answer/internal/base/data"
        "github.com/apache/incubator-answer/internal/entity"
+       "github.com/apache/incubator-answer/internal/schema"
        "github.com/apache/incubator-answer/internal/service/event_queue"
        "github.com/segmentfault/pacman/log"
-
-       "github.com/apache/incubator-answer/internal/base/data"
-       "github.com/apache/incubator-answer/internal/schema"
 )
 
 type BadgeEventService struct {
@@ -35,6 +34,7 @@ type BadgeEventService struct {
        badgeAwardRepo    BadgeAwardRepo
        badgeRepo         BadgeRepo
        eventRuleRepo     EventRuleRepo
+       badgeAwardService *BadgeAwardService
 }
 
 type EventRuleHandler func(ctx context.Context, event *schema.EventMsg) 
(awards []*entity.BadgeAward, err error)
@@ -48,12 +48,14 @@ func NewBadgeEventService(
        eventQueueService event_queue.EventQueueService,
        badgeRepo BadgeRepo,
        eventRuleRepo EventRuleRepo,
+       badgeAwardService *BadgeAwardService,
 ) *BadgeEventService {
        n := &BadgeEventService{
                data:              data,
                eventQueueService: eventQueueService,
                badgeRepo:         badgeRepo,
                eventRuleRepo:     eventRuleRepo,
+               badgeAwardService: badgeAwardService,
        }
        eventQueueService.RegisterHandler(n.Handler)
        return n
@@ -65,18 +67,22 @@ func (ns *BadgeEventService) Handler(ctx context.Context, 
msg *schema.EventMsg)
                return nil
        }
 
-       badgeIDs := make([]string, 0)
-       for _, award := range awards {
-               badgeIDs = append(badgeIDs, award.BadgeID)
-       }
+       //badgeIDs := make([]string, 0)
+       //for _, award := range awards {
+       //      badgeIDs = append(badgeIDs, award.BadgeID)
+       //}
+       //
+       //badges, err := ns.badgeRepo.GetByIDs(ctx, badgeIDs)
+       //if err != nil {
+       //      log.Errorf("error getting badges %+v: %v", badgeIDs, err)
+       //      return err
+       //}
 
-       badges, err := ns.badgeRepo.GetByIDs(ctx, badgeIDs)
-       if err != nil {
-               log.Errorf("error getting badges %+v: %v", badgeIDs, err)
-               return err
+       for _, award := range awards {
+               err := ns.badgeAwardService.Award(ctx, award.BadgeID, 
award.UserID, award.AwardKey)
+               if err != nil {
+                       log.Debugf("error awarding badge %s: %v", 
award.BadgeID, err)
+               }
        }
-
-       // TODO: award badges to user
-       log.Debugf("awarding badges %+v to user", badges)
        return nil
 }

Reply via email to