internal/repo/badge_award/badge_award_repo.go (149 lines of code) (raw):
/*
* 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 badge_award
import (
"context"
"fmt"
"github.com/apache/answer/internal/base/data"
"github.com/apache/answer/internal/base/pager"
"github.com/apache/answer/internal/base/reason"
"github.com/apache/answer/internal/entity"
"github.com/apache/answer/internal/service/badge"
"github.com/apache/answer/internal/service/unique"
"github.com/segmentfault/pacman/errors"
"xorm.io/xorm"
)
type badgeAwardRepo struct {
data *data.Data
uniqueIDRepo unique.UniqueIDRepo
}
func NewBadgeAwardRepo(data *data.Data, uniqueIDRepo unique.UniqueIDRepo) badge.BadgeAwardRepo {
return &badgeAwardRepo{
data: data,
uniqueIDRepo: uniqueIDRepo,
}
}
// 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 err
}
_, 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 {
return nil, err
}
if !exist {
return nil, fmt.Errorf("badge not exist")
}
old := &entity.BadgeAward{
UserID: badgeAward.UserID,
BadgeID: badgeAward.BadgeID,
IsBadgeDeleted: entity.IsBadgeNotDeleted,
}
if badgeInfo.Single != entity.BadgeSingleAward {
old.AwardKey = badgeAward.AwardKey
}
exist, err = session.Get(old)
if err != nil {
return nil, err
}
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
}
// 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) CountByUserIdAndBadgeId(ctx context.Context, userID string, badgeID string) (awardCount int64) {
awardCount, err := r.data.DB.Context(ctx).Where("user_id = ? AND badge_id = ?", userID, badgeID).Count(&entity.BadgeAward{})
if err != nil {
return 0
}
return
}
func (r *badgeAwardRepo) CountByBadgeID(ctx context.Context, badgeID string) (awardCount int64, err error) {
awardCount, err = r.data.DB.Context(ctx).Count(&entity.BadgeAward{BadgeID: badgeID})
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return
}
func (r *badgeAwardRepo) SumUserEarnedGroupByBadgeID(ctx context.Context, userID string) (earnedCounts []*entity.BadgeEarnedCount, err error) {
err = r.data.DB.Context(ctx).Select("badge_id, count(`id`) AS earned_count").Where("user_id = ?", userID).GroupBy("badge_id").Find(&earnedCounts)
return
}
// ListPagedByBadgeId list badge awards by badge id
func (r *badgeAwardRepo) ListPagedByBadgeId(ctx context.Context, badgeID string, page int, pageSize int) (badgeAwardList []*entity.BadgeAward, total int64, err error) {
session := r.data.DB.Context(ctx)
session.Where("badge_id = ?", badgeID)
total, err = pager.Help(page, pageSize, &badgeAwardList, &entity.BadgeAward{}, session)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return
}
// ListPagedByBadgeIdAndUserId list badge awards by badge id and user id
func (r *badgeAwardRepo) ListPagedByBadgeIdAndUserId(ctx context.Context, badgeID string, userID string, page int, pageSize int) (badgeAwardList []*entity.BadgeAward, total int64, err error) {
session := r.data.DB.Context(ctx)
session.Where("badge_id = ? AND user_id = ?", badgeID, userID)
total, err = pager.Help(page, pageSize, &badgeAwardList, &entity.Question{}, session)
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return
}
// ListNewestEarned list newest earned badge awards
func (r *badgeAwardRepo) ListNewestEarned(ctx context.Context, userID string, limit int) (badgeAwards []*entity.BadgeAwardRecent, err error) {
badgeAwards = make([]*entity.BadgeAwardRecent, 0)
err = r.data.DB.Context(ctx).
Select("badge_id, max(created_at) created,count(*) earned_count").
Where("user_id = ? AND is_badge_deleted = ? ", userID, entity.IsBadgeNotDeleted).
GroupBy("badge_id").
OrderBy("created desc").
Limit(limit).Find(&badgeAwards)
return
}
// 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) {
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
}
// 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
}
// DeleteUserBadgeAward delete user badge award
func (r *badgeAwardRepo) DeleteUserBadgeAward(ctx context.Context, userID string) (err error) {
_, err = r.data.DB.Context(ctx).Where("user_id = ?", userID).Delete(&entity.BadgeAward{})
if err != nil {
err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
}
return
}