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 3ed0e59c48ed5cdd41435faccc85fdaea85c6690
Author: kumfo <ku...@sifou.com>
AuthorDate: Mon Aug 12 15:33:04 2024 +0800

    feat(badge): fixed user's badge award list and add recent user badges
---
 docs/docs.go                                  | 103 +++++++++++++++++++++++--
 docs/swagger.json                             | 103 +++++++++++++++++++++++--
 docs/swagger.yaml                             |  70 +++++++++++++++--
 internal/controller/badge_controller.go       |  35 ++++++++-
 internal/entity/badge_award_entity.go         |  21 ++++-
 internal/repo/badge_award/badge_award_repo.go |  25 +++++-
 internal/router/answer_api_router.go          |   3 +-
 internal/schema/badge_schema.go               |  95 +++++++++++++++--------
 internal/service/badge/badge_award_service.go | 107 ++++++++++++++++++++++----
 9 files changed, 489 insertions(+), 73 deletions(-)

diff --git a/docs/docs.go b/docs/docs.go
index 79e23a85..ecc62169 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -2326,6 +2326,12 @@ const docTemplate = `{
                         "name": "badge_id",
                         "in": "query",
                         "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "only list the award by username",
+                        "name": "username",
+                        "in": "query"
                     }
                 ],
                 "responses": {
@@ -2370,9 +2376,61 @@ const docTemplate = `{
                 "summary": "get user badge award list",
                 "parameters": [
                     {
-                        "type": "integer",
-                        "description": "user id",
-                        "name": "user_id",
+                        "type": "string",
+                        "description": "user name",
+                        "name": "username",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/handler.RespBody"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "type": "array",
+                                            "items": {
+                                                "$ref": 
"#/definitions/schema.GetUserBadgeAwardListResp"
+                                            }
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/answer/api/v1/badge/user/awards/recent": {
+            "get": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "description": "get user badge award list",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "api-badge"
+                ],
+                "summary": "get user badge award list",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "user name",
+                        "name": "username",
                         "in": "query",
                         "required": true
                     }
@@ -7565,21 +7623,31 @@ const docTemplate = `{
             "type": "object",
             "properties": {
                 "award_count": {
+                    "description": "badge award count",
                     "type": "integer"
                 },
                 "earned": {
+                    "description": "badge earned count",
                     "type": "boolean"
                 },
                 "icon": {
+                    "description": "badge icon",
                     "type": "string"
                 },
                 "id": {
+                    "description": "badge id",
                     "type": "string"
                 },
                 "level": {
-                    "$ref": "#/definitions/entity.BadgeLevel"
+                    "description": "badge level",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/entity.BadgeLevel"
+                        }
+                    ]
                 },
                 "name": {
+                    "description": "badge name",
                     "type": "string"
                 }
             }
@@ -7839,27 +7907,39 @@ const docTemplate = `{
             "type": "object",
             "properties": {
                 "award_count": {
+                    "description": "badge award count",
                     "type": "integer"
                 },
                 "description": {
+                    "description": "badge description",
                     "type": "string"
                 },
                 "earned_count": {
+                    "description": "badge earned count",
                     "type": "integer"
                 },
                 "icon": {
+                    "description": "badge icon",
                     "type": "string"
                 },
                 "id": {
+                    "description": "badge id",
                     "type": "string"
                 },
                 "is_single": {
+                    "description": "badge is single or multiple",
                     "type": "boolean"
                 },
                 "level": {
-                    "$ref": "#/definitions/entity.BadgeLevel"
+                    "description": "badge level",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/entity.BadgeLevel"
+                        }
+                    ]
                 },
                 "name": {
+                    "description": "badge name",
                     "type": "string"
                 }
             }
@@ -7868,12 +7948,14 @@ const docTemplate = `{
             "type": "object",
             "properties": {
                 "badges": {
+                    "description": "badge list info",
                     "type": "array",
                     "items": {
                         "$ref": "#/definitions/schema.BadgeListInfo"
                     }
                 },
                 "group_name": {
+                    "description": "badge group name",
                     "type": "string"
                 }
             }
@@ -8790,18 +8872,27 @@ const docTemplate = `{
             "type": "object",
             "properties": {
                 "earned_count": {
+                    "description": "badge award count",
                     "type": "integer"
                 },
                 "icon": {
+                    "description": "badge icon",
                     "type": "string"
                 },
                 "id": {
+                    "description": "badge id",
                     "type": "string"
                 },
                 "level": {
-                    "$ref": "#/definitions/entity.BadgeLevel"
+                    "description": "badge level",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/entity.BadgeLevel"
+                        }
+                    ]
                 },
                 "name": {
+                    "description": "badge name",
                     "type": "string"
                 }
             }
diff --git a/docs/swagger.json b/docs/swagger.json
index 07aabfea..1412f179 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -2296,6 +2296,12 @@
                         "name": "badge_id",
                         "in": "query",
                         "required": true
+                    },
+                    {
+                        "type": "string",
+                        "description": "only list the award by username",
+                        "name": "username",
+                        "in": "query"
                     }
                 ],
                 "responses": {
@@ -2340,9 +2346,61 @@
                 "summary": "get user badge award list",
                 "parameters": [
                     {
-                        "type": "integer",
-                        "description": "user id",
-                        "name": "user_id",
+                        "type": "string",
+                        "description": "user name",
+                        "name": "username",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "allOf": [
+                                {
+                                    "$ref": "#/definitions/handler.RespBody"
+                                },
+                                {
+                                    "type": "object",
+                                    "properties": {
+                                        "data": {
+                                            "type": "array",
+                                            "items": {
+                                                "$ref": 
"#/definitions/schema.GetUserBadgeAwardListResp"
+                                            }
+                                        }
+                                    }
+                                }
+                            ]
+                        }
+                    }
+                }
+            }
+        },
+        "/answer/api/v1/badge/user/awards/recent": {
+            "get": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "description": "get user badge award list",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "api-badge"
+                ],
+                "summary": "get user badge award list",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "user name",
+                        "name": "username",
                         "in": "query",
                         "required": true
                     }
@@ -7535,21 +7593,31 @@
             "type": "object",
             "properties": {
                 "award_count": {
+                    "description": "badge award count",
                     "type": "integer"
                 },
                 "earned": {
+                    "description": "badge earned count",
                     "type": "boolean"
                 },
                 "icon": {
+                    "description": "badge icon",
                     "type": "string"
                 },
                 "id": {
+                    "description": "badge id",
                     "type": "string"
                 },
                 "level": {
-                    "$ref": "#/definitions/entity.BadgeLevel"
+                    "description": "badge level",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/entity.BadgeLevel"
+                        }
+                    ]
                 },
                 "name": {
+                    "description": "badge name",
                     "type": "string"
                 }
             }
@@ -7809,27 +7877,39 @@
             "type": "object",
             "properties": {
                 "award_count": {
+                    "description": "badge award count",
                     "type": "integer"
                 },
                 "description": {
+                    "description": "badge description",
                     "type": "string"
                 },
                 "earned_count": {
+                    "description": "badge earned count",
                     "type": "integer"
                 },
                 "icon": {
+                    "description": "badge icon",
                     "type": "string"
                 },
                 "id": {
+                    "description": "badge id",
                     "type": "string"
                 },
                 "is_single": {
+                    "description": "badge is single or multiple",
                     "type": "boolean"
                 },
                 "level": {
-                    "$ref": "#/definitions/entity.BadgeLevel"
+                    "description": "badge level",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/entity.BadgeLevel"
+                        }
+                    ]
                 },
                 "name": {
+                    "description": "badge name",
                     "type": "string"
                 }
             }
@@ -7838,12 +7918,14 @@
             "type": "object",
             "properties": {
                 "badges": {
+                    "description": "badge list info",
                     "type": "array",
                     "items": {
                         "$ref": "#/definitions/schema.BadgeListInfo"
                     }
                 },
                 "group_name": {
+                    "description": "badge group name",
                     "type": "string"
                 }
             }
@@ -8760,18 +8842,27 @@
             "type": "object",
             "properties": {
                 "earned_count": {
+                    "description": "badge award count",
                     "type": "integer"
                 },
                 "icon": {
+                    "description": "badge icon",
                     "type": "string"
                 },
                 "id": {
+                    "description": "badge id",
                     "type": "string"
                 },
                 "level": {
-                    "$ref": "#/definitions/entity.BadgeLevel"
+                    "description": "badge level",
+                    "allOf": [
+                        {
+                            "$ref": "#/definitions/entity.BadgeLevel"
+                        }
+                    ]
                 },
                 "name": {
+                    "description": "badge name",
                     "type": "string"
                 }
             }
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index c8c5a560..e2fc6682 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -355,16 +355,23 @@ definitions:
   schema.BadgeListInfo:
     properties:
       award_count:
+        description: badge award count
         type: integer
       earned:
+        description: badge earned count
         type: boolean
       icon:
+        description: badge icon
         type: string
       id:
+        description: badge id
         type: string
       level:
-        $ref: '#/definitions/entity.BadgeLevel'
+        allOf:
+        - $ref: '#/definitions/entity.BadgeLevel'
+        description: badge level
       name:
+        description: badge name
         type: string
     type: object
   schema.CloseQuestionReq:
@@ -541,29 +548,40 @@ definitions:
   schema.GetBadgeInfoResp:
     properties:
       award_count:
+        description: badge award count
         type: integer
       description:
+        description: badge description
         type: string
       earned_count:
+        description: badge earned count
         type: integer
       icon:
+        description: badge icon
         type: string
       id:
+        description: badge id
         type: string
       is_single:
+        description: badge is single or multiple
         type: boolean
       level:
-        $ref: '#/definitions/entity.BadgeLevel'
+        allOf:
+        - $ref: '#/definitions/entity.BadgeLevel'
+        description: badge level
       name:
+        description: badge name
         type: string
     type: object
   schema.GetBadgeListResp:
     properties:
       badges:
+        description: badge list info
         items:
           $ref: '#/definitions/schema.BadgeListInfo'
         type: array
       group_name:
+        description: badge group name
         type: string
     type: object
   schema.GetCommentPersonalWithPageResp:
@@ -1206,14 +1224,20 @@ definitions:
   schema.GetUserBadgeAwardListResp:
     properties:
       earned_count:
+        description: badge award count
         type: integer
       icon:
+        description: badge icon
         type: string
       id:
+        description: badge id
         type: string
       level:
-        $ref: '#/definitions/entity.BadgeLevel'
+        allOf:
+        - $ref: '#/definitions/entity.BadgeLevel'
+        description: badge level
       name:
+        description: badge name
         type: string
     type: object
   schema.GetUserNotificationConfigResp:
@@ -4197,6 +4221,10 @@ paths:
         name: badge_id
         required: true
         type: string
+      - description: only list the award by username
+        in: query
+        name: username
+        type: string
       produces:
       - application/json
       responses:
@@ -4220,11 +4248,41 @@ paths:
       - application/json
       description: get user badge award list
       parameters:
-      - description: user id
+      - description: user name
         in: query
-        name: user_id
+        name: username
         required: true
-        type: integer
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            allOf:
+            - $ref: '#/definitions/handler.RespBody'
+            - properties:
+                data:
+                  items:
+                    $ref: '#/definitions/schema.GetUserBadgeAwardListResp'
+                  type: array
+              type: object
+      security:
+      - ApiKeyAuth: []
+      summary: get user badge award list
+      tags:
+      - api-badge
+  /answer/api/v1/badge/user/awards/recent:
+    get:
+      consumes:
+      - application/json
+      description: get user badge award list
+      parameters:
+      - description: user name
+        in: query
+        name: username
+        required: true
+        type: string
       produces:
       - application/json
       responses:
diff --git a/internal/controller/badge_controller.go 
b/internal/controller/badge_controller.go
index 7eb42da0..65b59407 100644
--- a/internal/controller/badge_controller.go
+++ b/internal/controller/badge_controller.go
@@ -87,6 +87,7 @@ func (b *BadgeController) GetBadgeInfo(ctx *gin.Context) {
 // @Param page query int false "page"
 // @Param page_size query int false "page size"
 // @Param badge_id query string true "badge id"
+// @Param username query string false "only list the award by username"
 // @Success 200 {object} handler.RespBody{data=schema.GetBadgeInfoResp}
 // @Router /answer/api/v1/badge/awards/page [get]
 func (b *BadgeController) GetBadgeAwardList(ctx *gin.Context) {
@@ -95,7 +96,6 @@ func (b *BadgeController) GetBadgeAwardList(ctx *gin.Context) 
{
                return
        }
        req.BadgeID = uid.DeShortID(req.BadgeID)
-       req.UserID = middleware.GetLoginUserIDFromContext(ctx)
 
        resp, total, err := b.badgeAwardService.GetBadgeAwardList(ctx, req)
        if err != nil {
@@ -105,17 +105,17 @@ func (b *BadgeController) GetBadgeAwardList(ctx 
*gin.Context) {
        handler.HandleResponse(ctx, nil, pager.NewPageModel(total, resp))
 }
 
-// GetBadgeAwardListByUsername get user badge award list
+// GetAllBadgeAwardListByUsername get user badge award list
 // @Summary get user badge award list
 // @Description get user badge award list
 // @Tags api-badge
 // @Accept json
 // @Produce json
 // @Security ApiKeyAuth
-// @Param user_id query int true "user id"
+// @Param username query string true "user name"
 // @Success 200 {object} 
handler.RespBody{data=[]schema.GetUserBadgeAwardListResp}
 // @Router /answer/api/v1/badge/user/awards [get]
-func (b *BadgeController) GetBadgeAwardListByUsername(ctx *gin.Context) {
+func (b *BadgeController) GetAllBadgeAwardListByUsername(ctx *gin.Context) {
        req := &schema.GetUserBadgeAwardListReq{}
        if handler.BindAndCheck(ctx, req) {
                return
@@ -129,3 +129,30 @@ func (b *BadgeController) GetBadgeAwardListByUsername(ctx 
*gin.Context) {
 
        handler.HandleResponse(ctx, nil, pager.NewPageModel(total, resp))
 }
+
+// GetRecentBadgeAwardListByUsername get user badge award list
+// @Summary get user badge award list
+// @Description get user badge award list
+// @Tags api-badge
+// @Accept json
+// @Produce json
+// @Security ApiKeyAuth
+// @Param username query string true "user name"
+// @Success 200 {object} 
handler.RespBody{data=[]schema.GetUserBadgeAwardListResp}
+// @Router /answer/api/v1/badge/user/awards/recent [get]
+func (b *BadgeController) GetRecentBadgeAwardListByUsername(ctx *gin.Context) {
+       req := &schema.GetUserBadgeAwardListReq{}
+       if handler.BindAndCheck(ctx, req) {
+               return
+       }
+
+       req.Limit = 10
+
+       resp, total, err := 
b.badgeAwardService.GetUserRecentBadgeAwardList(ctx, req)
+       if err != nil {
+               handler.HandleResponse(ctx, err, nil)
+               return
+       }
+
+       handler.HandleResponse(ctx, nil, pager.NewPageModel(total, resp))
+}
diff --git a/internal/entity/badge_award_entity.go 
b/internal/entity/badge_award_entity.go
index 17649734..1d421623 100644
--- a/internal/entity/badge_award_entity.go
+++ b/internal/entity/badge_award_entity.go
@@ -21,6 +21,11 @@ package entity
 
 import "time"
 
+const (
+       IsBadgeNotDeleted = 0
+       IsBadgeDeleted    = 1
+)
+
 // BadgeAward badge_award
 type BadgeAward struct {
        ID             string    `json:"id" xorm:"id"`
@@ -30,7 +35,7 @@ type BadgeAward struct {
        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) s_badge_deleted"`
+       IsBadgeDeleted int8      `json:"is_badge_deleted" xorm:"not null index 
TINYINT(1) is_badge_deleted"`
 }
 
 // TableName badge_award table name
@@ -47,3 +52,17 @@ type BadgeEarnedCount struct {
 func (BadgeEarnedCount) TableName() string {
        return "badge_award"
 }
+
+type BadgeAwardRecent struct {
+       Created        time.Time `xorm:"created"`
+       UserID         string    `xorm:"user_id"`
+       BadgeID        string    `xorm:"badge_id"`
+       AwardKey       string    `xorm:"award_key"`
+       EarnedCount    int64     `xorm:"earned_count"`
+       IsBadgeDeleted int8      `xorm:"is_badge_deleted"`
+}
+
+// TableName badge_award table name
+func (BadgeAwardRecent) TableName() string {
+       return "badge_award"
+}
diff --git a/internal/repo/badge_award/badge_award_repo.go 
b/internal/repo/badge_award/badge_award_repo.go
index 8860a5b1..5a5d56cd 100644
--- a/internal/repo/badge_award/badge_award_repo.go
+++ b/internal/repo/badge_award/badge_award_repo.go
@@ -108,13 +108,21 @@ func (r *badgeAwardRepo) ListAllByUserId(ctx 
context.Context, userID string) (ba
 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.Question{}, session)
+       total, err = pager.Help(page, pageSize, &badgeAwardList, 
&entity.BadgeAward{}, session)
        if err != nil {
                err = 
errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
        }
        return
 }
-func (r *badgeAwardRepo) ListPagedByBadgeIdAndUserId(ctx context.Context, 
badgeID string, userID string, page int, pageSize int) (badgeAwards 
[]*entity.BadgeAward, total int64, err error) {
+
+// 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
 }
 func (r *badgeAwardRepo) ListPagedByObjectId(ctx context.Context, badgeID 
string, awardKey string, page int, pageSize int) (badgeAwards 
[]*entity.BadgeAward, total int64, err error) {
@@ -132,6 +140,19 @@ func (r *badgeAwardRepo) 
ListTagPagedByBadgeIdAndUserId(ctx context.Context, bad
 func (r *badgeAwardRepo) ListPagedLatest(ctx context.Context, page int, 
pageSize int) (badgeAwards []*entity.BadgeAward, total int64, err error) {
        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("user_id, 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
+}
+
 func (r *badgeAwardRepo) ListNewestEarnedByLevel(ctx context.Context, userID 
string, level entity.BadgeLevel, num int) (badgeAwards []*entity.BadgeAward, 
total int64, err error) {
        return
 }
diff --git a/internal/router/answer_api_router.go 
b/internal/router/answer_api_router.go
index 63dec5fa..f343d7d1 100644
--- a/internal/router/answer_api_router.go
+++ b/internal/router/answer_api_router.go
@@ -194,7 +194,8 @@ func (a *AnswerAPIRouter) RegisterUnAuthAnswerAPIRouter(r 
*gin.RouterGroup) {
        // badges
        r.GET("/badge", a.badgeController.GetBadgeInfo)
        r.GET("/badge/awards/page", a.badgeController.GetBadgeAwardList)
-       r.GET("/badge/user/awards", 
a.badgeController.GetBadgeAwardListByUsername)
+       r.GET("/badge/user/awards/recent", 
a.badgeController.GetRecentBadgeAwardListByUsername)
+       r.GET("/badge/user/awards", 
a.badgeController.GetAllBadgeAwardListByUsername)
        r.GET("/badges", a.badgeController.GetBadgeList)
 }
 
diff --git a/internal/schema/badge_schema.go b/internal/schema/badge_schema.go
index 0555a99b..cae2aa66 100644
--- a/internal/schema/badge_schema.go
+++ b/internal/schema/badge_schema.go
@@ -23,28 +23,44 @@ import "github.com/apache/incubator-answer/internal/entity"
 
 // BadgeListInfo get badge list response
 type BadgeListInfo struct {
-       ID         string            `json:"id" `
-       Name       string            `json:"name" `
-       Icon       string            `json:"icon" `
-       AwardCount int               `json:"award_count" `
-       Earned     bool              `json:"earned" `
-       Level      entity.BadgeLevel `json:"level" `
+       // badge id
+       ID string `json:"id" `
+       // badge name
+       Name string `json:"name" `
+       // badge icon
+       Icon string `json:"icon" `
+       // badge award count
+       AwardCount int `json:"award_count" `
+       // badge earned count
+       Earned bool `json:"earned" `
+       // badge level
+       Level entity.BadgeLevel `json:"level" `
 }
 
 type GetBadgeListResp struct {
-       Badges    []*BadgeListInfo `json:"badges" `
-       GroupName string           `json:"group_name" `
+       // badge list info
+       Badges []*BadgeListInfo `json:"badges" `
+       // badge group name
+       GroupName string `json:"group_name" `
 }
 
 type GetBadgeInfoResp struct {
-       ID          string            `json:"id" `
-       Name        string            `json:"name" `
-       Description string            `json:"description" `
-       Icon        string            `json:"icon" `
-       AwardCount  int               `json:"award_count" `
-       EarnedCount int64             `json:"earned_count" `
-       IsSingle    bool              `json:"is_single" `
-       Level       entity.BadgeLevel `json:"level" `
+       // badge id
+       ID string `json:"id" `
+       // badge name
+       Name string `json:"name" `
+       // badge description
+       Description string `json:"description" `
+       // badge icon
+       Icon string `json:"icon" `
+       // badge award count
+       AwardCount int `json:"award_count" `
+       // badge earned count
+       EarnedCount int64 `json:"earned_count" `
+       // badge is single or multiple
+       IsSingle bool `json:"is_single" `
+       // badge level
+       Level entity.BadgeLevel `json:"level" `
 }
 
 type GetBadgeAwardWithPageReq struct {
@@ -54,29 +70,48 @@ type GetBadgeAwardWithPageReq struct {
        PageSize int `validate:"omitempty,min=1" form:"page_size"`
        // badge id
        BadgeID string `validate:"required" form:"badge_id"`
+       // username
+       Username string `validate:"omitempty,gt=0,lte=100" form:"username"`
        // user id
        UserID string `json:"-"`
 }
 
 type GetBadgeAwardWithPageResp struct {
-       CreatedAt      int64         `json:"created_at"`
-       ObjectID       string        `json:"object_id"`
-       QuestionID     string        `json:"question_id"`
-       AnswerID       string        `json:"answer_id"`
-       CommentID      string        `json:"comment_id"`
-       ObjectType     string        `json:"object_type" 
enums:"question,answer,comment"`
-       UrlTitle       string        `json:"url_title"`
+       // created time
+       CreatedAt int64 `json:"created_at"`
+       // object id
+       ObjectID string `json:"object_id"`
+       // question id
+       QuestionID string `json:"question_id"`
+       // answer id
+       AnswerID string `json:"answer_id"`
+       // comment id
+       CommentID string `json:"comment_id"`
+       // object type
+       ObjectType string `json:"object_type" enums:"question,answer,comment"`
+       // url title
+       UrlTitle string `json:"url_title"`
+       // author user info
        AuthorUserInfo UserBasicInfo `json:"author_user_info"`
 }
 
 type GetUserBadgeAwardListReq struct {
-       Username string `validate:"omitempty,gt=0,lte=100" form:"username"`
-       UserID   string `json:"-"`
+       // username
+       Username string `validate:"required,gt=0,lte=100" form:"username"`
+       // user id
+       UserID string `json:"-"`
+       Limit  int    `json:"-"`
 }
+
 type GetUserBadgeAwardListResp struct {
-       ID          string            `json:"id" `
-       Name        string            `json:"name" `
-       Icon        string            `json:"icon" `
-       EarnedCount int64             `json:"earned_count" `
-       Level       entity.BadgeLevel `json:"level" `
+       // badge id
+       ID string `json:"id" `
+       // badge name
+       Name string `json:"name" `
+       // badge icon
+       Icon string `json:"icon" `
+       // badge award count
+       EarnedCount int64 `json:"earned_count" `
+       // badge level
+       Level entity.BadgeLevel `json:"level" `
 }
diff --git a/internal/service/badge/badge_award_service.go 
b/internal/service/badge/badge_award_service.go
index c13c5658..0ad299ba 100644
--- a/internal/service/badge/badge_award_service.go
+++ b/internal/service/badge/badge_award_service.go
@@ -28,6 +28,7 @@ import (
        "github.com/apache/incubator-answer/internal/schema"
        "github.com/apache/incubator-answer/internal/service/object_info"
        usercommon 
"github.com/apache/incubator-answer/internal/service/user_common"
+       "github.com/apache/incubator-answer/pkg/uid"
        "github.com/gin-gonic/gin"
        "github.com/jinzhu/copier"
        "github.com/segmentfault/pacman/errors"
@@ -56,6 +57,7 @@ type BadgeAwardRepo interface {
        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)
+       ListNewestEarned(ctx context.Context, userID string, limit int) 
(badgeAwards []*entity.BadgeAwardRecent, 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)
 
@@ -86,13 +88,20 @@ func NewBadgeAwardService(
 
 // GetBadgeAwardList get badge award list
 func (b *BadgeAwardService) GetBadgeAwardList(
-       ctx context.Context, req *schema.GetBadgeAwardWithPageReq,
+       ctx context.Context,
+       req *schema.GetBadgeAwardWithPageReq,
 ) (resp []*schema.GetBadgeAwardWithPageResp, total int64, err error) {
        var (
                badgeAwardList []*entity.BadgeAward
        )
 
-       badgeAwardList, total, err = b.badgeAwardRepo.ListPagedByBadgeId(ctx, 
req.BadgeID, req.Page, req.PageSize)
+       req.UserID, err = b.validateUserByUsername(ctx, req.Username)
+       if err != nil {
+               badgeAwardList, total, err = 
b.badgeAwardRepo.ListPagedByBadgeId(ctx, req.BadgeID, req.Page, req.PageSize)
+       } else {
+               badgeAwardList, total, err = 
b.badgeAwardRepo.ListPagedByBadgeIdAndUserId(ctx, req.BadgeID, req.UserID, 
req.Page, req.PageSize)
+       }
+
        if err != nil {
                return
        }
@@ -197,33 +206,66 @@ func (b *BadgeAwardService) GetUserBadgeAwardList(
 ) {
        var (
                earnedCounts []*entity.BadgeEarnedCount
-               userInfo     *schema.UserBasicInfo
-               exist        bool
        )
 
-       // validate user exists or not
-       if len(req.Username) > 0 {
-               userInfo, exist, err = 
b.userCommon.GetUserBasicInfoByUserName(ctx, req.Username)
-               if err != nil {
+       req.UserID, err = b.validateUserByUsername(ctx, req.Username)
+       if err != nil {
+               return
+       }
+
+       earnedCounts, err = b.badgeAwardRepo.SumUserEarnedGroupByBadgeID(ctx, 
req.UserID)
+       if err != nil {
+               return
+       }
+       total = int64(len(earnedCounts))
+       resp = make([]*schema.GetUserBadgeAwardListResp, total)
+
+       for i, earnedCount := range earnedCounts {
+               badge, exists, e := b.badgeRepo.GetByID(ctx, 
earnedCount.BadgeID)
+               if e != nil {
+                       err = e
                        return
                }
-               if !exist {
-                       err = errors.BadRequest(reason.UserNotFound)
-                       return
+               if !exists {
+                       continue
+               }
+               resp[i] = &schema.GetUserBadgeAwardListResp{
+                       ID:          uid.EnShortID(badge.ID),
+                       Name:        translator.Tr(handler.GetLangByCtx(ctx), 
badge.Name),
+                       Icon:        badge.Icon,
+                       EarnedCount: earnedCount.EarnedCount,
+                       Level:       badge.Level,
                }
-               req.UserID = userInfo.ID
        }
-       if len(req.UserID) == 0 {
-               err = errors.BadRequest(reason.UserNotFound)
+
+       return
+}
+
+// GetUserRecentBadgeAwardList get user badge award list
+func (b *BadgeAwardService) GetUserRecentBadgeAwardList(
+       ctx *gin.Context,
+       req *schema.GetUserBadgeAwardListReq,
+) (
+       resp []*schema.GetUserBadgeAwardListResp,
+       total int64,
+       err error,
+) {
+       var (
+               earnedCounts []*entity.BadgeAwardRecent
+       )
+
+       req.UserID, err = b.validateUserByUsername(ctx, req.Username)
+       if err != nil {
                return
        }
 
-       earnedCounts, err = b.badgeAwardRepo.SumUserEarnedGroupByBadgeID(ctx, 
req.UserID)
+       earnedCounts, err = b.badgeAwardRepo.ListNewestEarned(ctx, req.UserID, 
req.Limit)
        if err != nil {
                return
        }
+
        total = int64(len(earnedCounts))
-       resp = make([]*schema.GetUserBadgeAwardListResp, 0, total)
+       resp = make([]*schema.GetUserBadgeAwardListResp, total)
 
        for i, earnedCount := range earnedCounts {
                badge, exists, e := b.badgeRepo.GetByID(ctx, 
earnedCount.BadgeID)
@@ -235,7 +277,7 @@ func (b *BadgeAwardService) GetUserBadgeAwardList(
                        continue
                }
                resp[i] = &schema.GetUserBadgeAwardListResp{
-                       ID:          badge.ID,
+                       ID:          uid.EnShortID(badge.ID),
                        Name:        translator.Tr(handler.GetLangByCtx(ctx), 
badge.Name),
                        Icon:        badge.Icon,
                        EarnedCount: earnedCount.EarnedCount,
@@ -245,3 +287,34 @@ func (b *BadgeAwardService) GetUserBadgeAwardList(
 
        return
 }
+
+// validate user
+
+type userReq struct {
+       UserID   string
+       Username string
+}
+
+func (b *BadgeAwardService) validateUserByUsername(ctx context.Context, 
userName string) (userID string, err error) {
+       var (
+               userInfo *schema.UserBasicInfo
+               exist    bool
+       )
+       // validate user exists or not
+       if len(userName) > 0 {
+               userInfo, exist, err = 
b.userCommon.GetUserBasicInfoByUserName(ctx, userName)
+               if err != nil {
+                       return
+               }
+               if !exist {
+                       err = errors.BadRequest(reason.UserNotFound)
+                       return
+               }
+               userID = userInfo.ID
+       }
+       if len(userID) == 0 {
+               err = errors.BadRequest(reason.UserNotFound)
+               return
+       }
+       return
+}


Reply via email to