feat(badge): badge award

This commit is contained in:
kumfo
2024-08-09 10:33:03 +08:00
parent 122ac657f1
commit 203062dd98
7 changed files with 127 additions and 44 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ type BadgeAward struct {
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 int8 `json:"badge_group_id" xorm:"not null index BIGINT(20) badge_group_id"`
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) s_badge_deleted"`
}
+1 -1
View File
@@ -46,7 +46,7 @@ type Badge struct {
AwardCount int `json:"award_count" xorm:"not null default 0 INT(11) award_count"`
Description string `json:"description" xorm:"not null default '' MEDIUMTEXT description"`
Status int8 `json:"status" xorm:"not null default 1 INT(11) status"`
BadgeGroupId int64 `json:"badge_group_id" xorm:"not null default 0 BIGINT(20) badge_group_id"`
BadgeGroupID int64 `json:"badge_group_id" xorm:"not null default 0 BIGINT(20) badge_group_id"`
Level BadgeLevel `json:"level" xorm:"not null default 1 TINYINT(4) level"`
Single int8 `json:"single" xorm:"not null default 1 TINYINT(4) single"`
Collect string `json:"collect" xorm:"not null default '' VARCHAR(64) collect"`
+14 -14
View File
@@ -44,7 +44,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.autobiographer.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 1,
BadgeGroupID: 1,
Level: entity.BadgeLevelBronze,
Single: entity.BadgeSingleAward,
Collect: "",
@@ -59,7 +59,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.editor.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 1,
BadgeGroupID: 1,
Level: entity.BadgeLevelBronze,
Single: entity.BadgeSingleAward,
Collect: "question",
@@ -74,7 +74,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.first_flag.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 1,
BadgeGroupID: 1,
Level: entity.BadgeLevelBronze,
Single: entity.BadgeSingleAward,
Collect: "",
@@ -89,7 +89,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.first_upvote.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 1,
BadgeGroupID: 1,
Level: entity.BadgeLevelBronze,
Single: entity.BadgeSingleAward,
Collect: "",
@@ -104,7 +104,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.first_reaction.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 1,
BadgeGroupID: 1,
Level: entity.BadgeLevelBronze,
Single: entity.BadgeSingleAward,
Collect: "",
@@ -119,7 +119,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.first_share.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 1,
BadgeGroupID: 1,
Level: entity.BadgeLevelBronze,
Single: entity.BadgeSingleAward,
Collect: "",
@@ -134,7 +134,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.scholar.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 1,
BadgeGroupID: 1,
Level: entity.BadgeLevelBronze,
Single: entity.BadgeSingleAward,
Collect: "",
@@ -149,7 +149,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.solved.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 2,
BadgeGroupID: 2,
Level: entity.BadgeLevelBronze,
Single: entity.BadgeSingleAward,
Collect: "",
@@ -164,7 +164,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.nice_answer.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 3,
BadgeGroupID: 3,
Level: entity.BadgeLevelBronze,
Single: entity.BadgeMultiAward,
Collect: "",
@@ -179,7 +179,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.good_answer.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 3,
BadgeGroupID: 3,
Level: entity.BadgeLevelSilver,
Single: entity.BadgeMultiAward,
Collect: "",
@@ -194,7 +194,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.great_answer.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 3,
BadgeGroupID: 3,
Level: entity.BadgeLevelGold,
Single: entity.BadgeMultiAward,
Collect: "",
@@ -209,7 +209,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.nice_question.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 3,
BadgeGroupID: 3,
Level: entity.BadgeLevelBronze,
Single: entity.BadgeMultiAward,
Collect: "",
@@ -224,7 +224,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.good_question.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 3,
BadgeGroupID: 3,
Level: entity.BadgeLevelSilver,
Single: entity.BadgeSingleAward,
Collect: "",
@@ -239,7 +239,7 @@ var (
AwardCount: 0,
Description: "badge.default_badges.great_question.desc",
Status: entity.BadgeStatusActive,
BadgeGroupId: 3,
BadgeGroupID: 3,
Level: entity.BadgeLevelGold,
Single: entity.BadgeMultiAward,
Collect: "",
+6
View File
@@ -109,3 +109,9 @@ func (r *badgeRepo) ListInactivated(ctx context.Context) (badges []*entity.Badge
}
return
}
// UpdateAwardCount updates the award count of a badge
func (r *badgeRepo) UpdateAwardCount(ctx context.Context, id string, count int64) (err error) {
_, err = r.data.DB.Context(ctx).Where("id = ?", id).Incr("award_count", count).Update(&entity.Badge{})
return
}
+41 -10
View File
@@ -28,7 +28,6 @@ import (
"github.com/apache/incubator-answer/internal/service/badge_award"
"github.com/apache/incubator-answer/internal/service/unique"
"github.com/segmentfault/pacman/errors"
"time"
)
type badgeAwardRepo struct {
@@ -43,10 +42,36 @@ func NewBadgeAwardRepo(data *data.Data, uniqueIDRepo unique.UniqueIDRepo) badge_
}
}
func (r *badgeAwardRepo) Award(ctx context.Context, badgeID string, userID string, awardKey string, force bool, createdAt time.Time) {
func (r *badgeAwardRepo) Add(ctx context.Context, badgeAward *entity.BadgeAward) (err error) {
badgeAward.ID, err = r.uniqueIDRepo.GenUniqueIDStr(ctx, entity.BadgeAward{}.TableName())
if err != nil {
return
}
_, err = r.data.DB.Context(ctx).Insert(badgeAward)
return
}
func (r *badgeAwardRepo) CheckIsAward(ctx context.Context, badgeID string, userID string, awardKey string) (isAward bool) {
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)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
return
}
if exists {
return true
}
} else {
_, exists, err := r.GetByUserIdAndBadgeIdAndObjectId(ctx, userID, badgeID, awardKey)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
return
}
if exists {
return true
}
}
return
}
func (r *badgeAwardRepo) CountByUserIdAndBadgeLevel(ctx context.Context, userID string, badgeLevel entity.BadgeLevel) (awardCount int64) {
@@ -62,13 +87,13 @@ func (r *badgeAwardRepo) CountByUserIdAndBadgeId(ctx context.Context, userID str
}
return
}
func (r *badgeAwardRepo) CountByObjectId(ctx context.Context, objectID string) (awardCount int64) {
func (r *badgeAwardRepo) CountByObjectId(ctx context.Context, awardKey string) (awardCount int64) {
return
}
func (r *badgeAwardRepo) CountByObjectIdAndBadgeId(ctx context.Context, objectID string, badgeID string) (awardCount int64) {
func (r *badgeAwardRepo) CountByObjectIdAndBadgeId(ctx context.Context, awardKey string, badgeID string) (awardCount int64) {
return
}
func (r *badgeAwardRepo) CountBadgesByUserIdAndObjectId(ctx context.Context, userID string, objectID string, badgeID string) (awardCount int64) {
func (r *badgeAwardRepo) CountBadgesByUserIdAndObjectId(ctx context.Context, userID string, awardKey string, badgeID string) (awardCount int64) {
return
}
func (r *badgeAwardRepo) SumUserEarnedGroupByBadgeID(ctx context.Context, userID string) (earnedCounts []*entity.BadgeEarnedCount, err error) {
@@ -92,10 +117,10 @@ func (r *badgeAwardRepo) ListPagedByBadgeId(ctx context.Context, badgeID string,
func (r *badgeAwardRepo) ListPagedByBadgeIdAndUserId(ctx context.Context, badgeID string, userID string, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error) {
return
}
func (r *badgeAwardRepo) ListPagedByObjectId(ctx context.Context, badgeID string, objectID string, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error) {
func (r *badgeAwardRepo) ListPagedByObjectId(ctx context.Context, badgeID string, awardKey string, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error) {
return
}
func (r *badgeAwardRepo) ListPagedByObjectIdAndUserId(ctx context.Context, badgeID string, objectID string, userID string, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error) {
func (r *badgeAwardRepo) ListPagedByObjectIdAndUserId(ctx context.Context, badgeID string, awardKey string, userID string, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error) {
return
}
func (r *badgeAwardRepo) ListTagPagedByBadgeId(ctx context.Context, badgeIDs []string, page int, pageSize int, filterUserID string) (badgeAwards []*entity.BadgeAward, total int64, err error) {
@@ -113,9 +138,15 @@ func (r *badgeAwardRepo) ListNewestEarnedByLevel(ctx context.Context, userID str
func (r *badgeAwardRepo) ListNewestByUserIdAndLevel(ctx context.Context, userID string, level int, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error) {
return
}
func (r *badgeAwardRepo) GetByUserIdAndBadgeId(ctx context.Context, userID string, badgeID string) (badgeAward *entity.BadgeAward) {
// 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)
return
}
func (r *badgeAwardRepo) GetByUserIdAndBadgeIdAndObjectId(ctx context.Context, userID string, badgeID string, objectID string) (badgeAward *entity.BadgeAward) {
// 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)
return
}
+4 -1
View File
@@ -37,11 +37,14 @@ import (
type BadgeRepo interface {
GetByID(ctx context.Context, id string) (badge *entity.Badge, exists bool, err error)
GetByIDs(ctx context.Context, ids []string) (badges []*entity.Badge, err error)
ListByLevel(ctx context.Context, level entity.BadgeLevel) ([]*entity.Badge, error)
ListByGroup(ctx context.Context, groupID int64) ([]*entity.Badge, error)
ListByLevelAndGroup(ctx context.Context, level entity.BadgeLevel, groupID int64) ([]*entity.Badge, error)
ListActivated(ctx context.Context) ([]*entity.Badge, error)
ListInactivated(ctx context.Context) ([]*entity.Badge, error)
UpdateAwardCount(ctx context.Context, id string, count int64) error
}
type BadgeService struct {
@@ -109,7 +112,7 @@ func (b *BadgeService) ListByGroup(ctx context.Context, userID string) (resp []*
}
}
badgesMap[badge.BadgeGroupId] = append(badgesMap[badge.BadgeGroupId], &schema.BadgeListInfo{
badgesMap[badge.BadgeGroupID] = append(badgesMap[badge.BadgeGroupID], &schema.BadgeListInfo{
ID: uid.EnShortID(badge.ID),
Name: translator.Tr(handler.GetLangByCtx(ctx), badge.Name),
Icon: badge.Icon,
@@ -21,66 +21,64 @@ package badge_award
import (
"context"
"github.com/apache/incubator-answer/internal/base/reason"
"github.com/apache/incubator-answer/internal/entity"
"github.com/apache/incubator-answer/internal/schema"
answercommon "github.com/apache/incubator-answer/internal/service/answer_common"
"github.com/apache/incubator-answer/internal/service/badge"
"github.com/apache/incubator-answer/internal/service/object_info"
questioncommon "github.com/apache/incubator-answer/internal/service/question_common"
usercommon "github.com/apache/incubator-answer/internal/service/user_common"
"github.com/jinzhu/copier"
"github.com/segmentfault/pacman/errors"
"github.com/segmentfault/pacman/log"
"time"
)
type BadgeAwardRepo interface {
Award(ctx context.Context, badgeID string, userID string, awardKey string, force bool, createdAt time.Time)
CheckIsAward(ctx context.Context, badgeID string, userID string, awardKey string) bool
Add(ctx context.Context, badgeAward *entity.BadgeAward) (err error)
CheckIsAward(ctx context.Context, badgeID string, userID string, awardKey string, singleOrMulti int8) bool
CountByUserIdAndBadgeLevel(ctx context.Context, userID string, badgeLevel entity.BadgeLevel) (awardCount int64)
CountByUserId(ctx context.Context, userID string) (awardCount int64)
CountByUserIdAndBadgeId(ctx context.Context, userID string, badgeID string) (awardCount int64)
CountByObjectId(ctx context.Context, objectID string) (awardCount int64)
CountByObjectIdAndBadgeId(ctx context.Context, objectID string, badgeID string) (awardCount int64)
CountBadgesByUserIdAndObjectId(ctx context.Context, userID string, objectID string, badgeID string) (awardCount int64)
CountByObjectId(ctx context.Context, awardKey string) (awardCount int64)
CountByObjectIdAndBadgeId(ctx context.Context, awardKey string, badgeID string) (awardCount int64)
CountBadgesByUserIdAndObjectId(ctx context.Context, userID string, awardKey string, badgeID string) (awardCount int64)
SumUserEarnedGroupByBadgeID(ctx context.Context, userID string) (earnedCounts []*entity.BadgeEarnedCount, err error)
ListAllByUserId(ctx context.Context, userID string) (badgeAwards []*entity.BadgeAward)
ListPagedByBadgeId(ctx context.Context, badgeID string, page int, pageSize int) (badgeAwardList []*entity.BadgeAward, total int64, err error)
ListPagedByBadgeIdAndUserId(ctx context.Context, badgeID string, userID string, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error)
ListPagedByObjectId(ctx context.Context, badgeID string, objectID string, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error)
ListPagedByObjectIdAndUserId(ctx context.Context, badgeID string, objectID string, userID string, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error)
ListPagedByObjectId(ctx context.Context, badgeID string, awardKey string, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error)
ListPagedByObjectIdAndUserId(ctx context.Context, badgeID string, awardKey string, userID string, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error)
ListTagPagedByBadgeId(ctx context.Context, badgeIDs []string, page int, pageSize int, filterUserID string) (badgeAwards []*entity.BadgeAward, total int64, err error)
ListTagPagedByBadgeIdAndUserId(ctx context.Context, badgeIDs []string, userID string, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error)
ListPagedLatest(ctx context.Context, page int, pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error)
ListNewestEarnedByLevel(ctx context.Context, userID string, level entity.BadgeLevel, num int) (badgeAwards []*entity.BadgeAward, total int64, err error)
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)
GetByUserIdAndBadgeIdAndObjectId(ctx context.Context, userID string, badgeID string, objectID string) (badgeAward *entity.BadgeAward)
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)
}
type BadgeAwardService struct {
badgeAwardRepo BadgeAwardRepo
badgeRepo badge.BadgeRepo
userCommon *usercommon.UserCommon
objectInfoService *object_info.ObjService
questionRepo questioncommon.QuestionRepo
answerRepo answercommon.AnswerRepo
}
func NewBadgeAwardService(
badgeAwardRepo BadgeAwardRepo,
badgeRepo badge.BadgeRepo,
userCommon *usercommon.UserCommon,
objectInfoService *object_info.ObjService,
questionRepo questioncommon.QuestionRepo,
answerRepo answercommon.AnswerRepo,
) *BadgeAwardService {
return &BadgeAwardService{
badgeAwardRepo: badgeAwardRepo,
badgeRepo: badgeRepo,
userCommon: userCommon,
objectInfoService: objectInfoService,
questionRepo: questionRepo,
answerRepo: answerRepo,
}
}
@@ -140,3 +138,48 @@ func (b *BadgeAwardService) GetBadgeAwardList(
return
}
// 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)
if err != nil {
return
}
if !exists || badgeData.Status == entity.BadgeStatusInactive {
err = errors.BadRequest(reason.BadgeObjectNotFound)
return
}
awarded = b.badgeAwardRepo.CheckIsAward(ctx, badgeID, userID, awardKey, badgeData.Single)
if !force && awarded {
return
}
if createdAt.IsZero() {
createdAt = time.Now()
}
err = b.badgeAwardRepo.Add(ctx, &entity.BadgeAward{
CreatedAt: createdAt,
UpdatedAt: createdAt,
UserID: userID,
BadgeID: badgeID,
AwardKey: awardKey,
BadgeGroupID: badgeData.BadgeGroupID,
IsBadgeDeleted: 0,
})
if err != nil {
return
}
// increment badge award count
err = b.badgeRepo.UpdateAwardCount(ctx, badgeID, 1)
return
}