Skip to content

Commit

Permalink
feat: add IncreaseViewCount, IncreaseLikeCount, FindNextItems API
Browse files Browse the repository at this point in the history
  • Loading branch information
slowhigh committed Jul 4, 2024
1 parent b673fb5 commit b18660d
Show file tree
Hide file tree
Showing 9 changed files with 342 additions and 5 deletions.
98 changes: 98 additions & 0 deletions infra/database/repository/item_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,104 @@ func (ir *ItemRepo) FindAllView(company *string, companySizes *[]entity.CompanyS
return items, err
}

// Update implements entity.ItemRepo.
func (ir *ItemRepo) Update(id int64, newItem entity.Item) (entity.Item, error) {
var (
item entity.Item
)

err := ir.db.First(&item, id).Error
if err != nil {
return entity.Item{}, err
}

item = newItem
item.ID = uint(id)
err = ir.db.Save(&item).Error
if err != nil {
return entity.Item{}, err
}

return item, nil
}

// Exist implements entity.ItemRepo.
func (ir *ItemRepo) Exist(id int64) (bool, error) {
err := ir.db.Select("id").Take(&entity.Item{}, id).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return false, nil
} else if err != nil {
return false, err
}

return true, nil
}

// IncreaseViewCount implements entity.ItemRepo.
func (ir *ItemRepo) IncreaseViewCount(id int64) (int64, error) {
var (
item entity.Item
)

if err := ir.db.Select("id", "views").Take(&item, id).Error; err != nil {
return -1, err
}

result := ir.db.Model(&item).Updates(entity.Item{Views: item.Views + 1})
if result.Error != nil {
return -1, result.Error
}

if result.RowsAffected < 1 {
return -1, errors.New("0 Row Affected")
}

return int64(item.Views), nil
}

// IncreaseLikeCount implements entity.ItemRepo.
func (ir *ItemRepo) IncreaseLikeCount(id int64) (int64, error) {
var (
item entity.Item
)

if err := ir.db.Select("id", "likes").Take(&item, id).Error; err != nil {
return -1, err
}

result := ir.db.Model(&item).Updates(entity.Item{Likes: item.Likes + 1})
if result.Error != nil {
return -1, result.Error
}

if result.RowsAffected < 1 {
return -1, errors.New("0 Row Affected")
}

return int64(item.Likes), nil
}

// FindAllViewByExcludedIds implements entity.ItemRepo.
func (ir *ItemRepo) FindAllViewByExcludedIds(ids []int64, perPage int32) ([]entity.ItemView, error) {
var (
items []entity.ItemView
where = make([]string, 0)
param = make([]interface{}, 0)
)

if len(ids) > 0 {
where = append(where, "item_id NOT IN ?")
param = append(param, ids)
}

err := ir.db.
Where(strings.Join(where, " AND "), param...).
Limit(int(perPage)).
Find(&items).Error

return items, err
}

func getArrToString(arr []int64) string {
strArr := make([]string, len(arr))
for i, v := range arr {
Expand Down
90 changes: 89 additions & 1 deletion infra/router/handler/item_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,93 @@ func ListItems(c iris.Context, ctrl rest.ItemController) {
return
}

c.JSON(http.StatusOK, res)
c.JSON(res)
}

// IncreaseViewCount
//
// @Summary Increase View Count
// @Description increase item's view count
// @Tags item
// @Schemes http
// @Accept json
// @Produce json
// @Param request body item_dto.IncreaseViewCountReq true "조회 수 증가 요청 내용"
// @Success 200 {object} item_dto.IncreaseViewCountRes
// @Failure 400 {object} util.HTTPError
// @Failure 500 {object} util.HTTPError
// @Router /v1/item/view_increase [post]
func IncreaseViewCount(c iris.Context, ctrl rest.ItemController) {
req, err := util.ValidateBody[item_dto.IncreaseViewCountReq](c)
if err != nil {
util.NewError(c, http.StatusBadRequest, err)
return
}

res, ok := ctrl.IncreaseViewCount(*req)
if !ok {
util.NewError(c, http.StatusInternalServerError)
return
}

c.JSON(res)
}

// IncreaseLikeCount
//
// @Summary Increase Like Count
// @Description increase item's like count
// @Tags item
// @Schemes http
// @Accept json
// @Produce json
// @Param request body item_dto.IncreaseLikeCountReq true "좋아요 수 증가 요청 내용"
// @Success 200 {object} item_dto.IncreaseLikeCountRes
// @Failure 400 {object} util.HTTPError
// @Failure 500 {object} util.HTTPError
// @Router /v1/item/like_increase [post]
func IncreaseLikeCount(c iris.Context, ctrl rest.ItemController) {
req, err := util.ValidateBody[item_dto.IncreaseLikeCountReq](c)
if err != nil {
util.NewError(c, http.StatusBadRequest, err)
return
}

res, ok := ctrl.IncreaseLikeCount(*req)
if !ok {
util.NewError(c, http.StatusInternalServerError)
return
}

c.JSON(res)
}

// FindNextItems
//
// @Summary Find Next Items
// @Description find next items
// @Tags item
// @Schemes http
// @Accept json
// @Produce json
// @Param excluded_ids query []int64 false "제외할 글 ID 목록"
// @Param limit query int32 true "글 목록 개수 제한"
// @Success 200 {object} []item_dto.FindNextRes
// @Failure 400 {object} util.HTTPError
// @Failure 500 {object} util.HTTPError
// @Router /v1/item/next [get]
func FindNextItems(c iris.Context, ctrl rest.ItemController) {
req, err := util.ValidateQuery[item_dto.FindNextReq](c)
if err != nil {
util.NewError(c, http.StatusBadRequest, err)
return
}

res, ok := ctrl.FindNextItems(*req)
if !ok {
util.NewError(c, http.StatusInternalServerError)
return
}

c.JSON(res)
}
8 changes: 7 additions & 1 deletion internal/controller/rest/dto/item_dto/find_all_dto.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ type FindAllItemRes struct {
ItemDescription string `json:"item_description"` // 글 설명
ItemLink string `json:"item_link"` // 글 URL
ItemThumbnail *string `json:"item_thumbnail"` // 글 썸네일
ItemPublished time.Time `json:"item_published"` // 개시 시간
ItemPublished time.Time `json:"item_published"` // 글 개시 시간
ItemSummary *string `json:"item_summary"` // 글 요약 내용
ItemViews uint `json:"item_views"` // 조회 수
ItemLikes uint `json:"item_likes"` // 좋아요 수
FeedName string `json:"feed_name"` // 회사 이름
FeedTitle string `json:"feed_title"` // 회사 Feed 제목
FeedLink string `json:"feed_link"` // 회사 URL
Expand All @@ -37,6 +40,9 @@ func NewFindAllItemRes(itemView entity.ItemView) FindAllItemRes {
ItemLink: itemView.ItemLink,
ItemThumbnail: itemView.ItemThumbnail,
ItemPublished: itemView.ItemPublished,
ItemSummary: itemView.ItemSummary,
ItemViews: itemView.ItemViews,
ItemLikes: itemView.ItemLikes,
FeedName: itemView.FeedName,
FeedTitle: itemView.FeedTitle,
FeedLink: itemView.FeedLink,
Expand Down
56 changes: 56 additions & 0 deletions internal/controller/rest/dto/item_dto/find_next_dto.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package item_dto

import (
"time"

"github.com/team-nerd-planet/api-server/internal/entity"
)

type FindNextReq struct {
ExcludedIds []int64 `url:"excluded_ids"` // 제외할 글 ID 목록
Limit int32 `url:"limit" validate:"required"` // 글 목록 개수 제한
}

type FindNextRes struct {
ItemID uint `json:"item_id"` // 글 DB ID
ItemTitle string `json:"item_title"` // 글 제목
ItemDescription string `json:"item_description"` // 글 설명
ItemLink string `json:"item_link"` // 글 URL
ItemThumbnail *string `json:"item_thumbnail"` // 글 썸네일
ItemPublished time.Time `json:"item_published"` // 글 개시 시간
ItemSummary *string `json:"item_summary"` // 글 요약 내용
ItemViews uint `json:"item_views"` // 조회 수
ItemLikes uint `json:"item_likes"` // 좋아요 수
FeedName string `json:"feed_name"` // 회사 이름
FeedTitle string `json:"feed_title"` // 회사 Feed 제목
FeedLink string `json:"feed_link"` // 회사 URL
CompanySize entity.CompanySizeType `json:"company_size"` // 회사 규모
JobTagIDArr []int64 `json:"job_tags_id_arr"` // 관련 직무 DB ID 배열
SkillTagIDArr []int64 `json:"skill_tags_id_arr"` // 관련 스킬 DB ID 배열
}

func NewFindNextRes(itemViews []entity.ItemView) []FindNextRes {
res := make([]FindNextRes, len(itemViews))

for i, itemView := range itemViews {
res[i] = FindNextRes{
ItemID: itemView.ItemID,
ItemTitle: itemView.ItemTitle,
ItemDescription: itemView.ItemDescription,
ItemLink: itemView.ItemLink,
ItemThumbnail: itemView.ItemThumbnail,
ItemPublished: itemView.ItemPublished,
ItemSummary: itemView.ItemSummary,
ItemViews: itemView.ItemViews,
ItemLikes: itemView.ItemLikes,
FeedName: itemView.FeedName,
FeedTitle: itemView.FeedTitle,
FeedLink: itemView.FeedLink,
CompanySize: itemView.CompanySize,
JobTagIDArr: itemView.JobTagIDArr,
SkillTagIDArr: itemView.SkillTagIDArr,
}
}

return res
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package item_dto

type IncreaseLikeCountReq struct {
Id int64 `json:"item_id" binding:"required"` // 좋아요 수를 증가시킬 글의 ID
}

type IncreaseLikeCountRes struct {
ItemLikeCount int64 `json:"item_like_count"` // 증가된 글의 종아요 수
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package item_dto

type IncreaseViewCountReq struct {
Id int64 `json:"item_id" binding:"required"` // 조회 수를 증가시킬 글의 ID
}

type IncreaseViewCountRes struct {
ItemViewCount int64 `json:"item_view_count"` // 증가된 글의 조회 수
}
31 changes: 31 additions & 0 deletions internal/controller/rest/item_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,34 @@ func (ic ItemController) FindAllItem(req item_dto.FindAllItemReq) (dto.Paginated
data = dto.NewPaginatedRes(itemRes, *req.Page, perPage, *totalCount)
return data, true
}

func (ic ItemController) IncreaseViewCount(req item_dto.IncreaseViewCountReq) (*item_dto.IncreaseViewCountRes, bool) {
count, ok := ic.itemUcase.IncreaseViewCount(req.Id)
if !ok {
return nil, false
}

return &item_dto.IncreaseViewCountRes{
ItemViewCount: count,
}, true
}

func (ic ItemController) IncreaseLikeCount(req item_dto.IncreaseLikeCountReq) (*item_dto.IncreaseLikeCountRes, bool) {
count, ok := ic.itemUcase.IncreaseLikeCount(req.Id)
if !ok {
return nil, false
}

return &item_dto.IncreaseLikeCountRes{
ItemLikeCount: count,
}, true
}

func (ic ItemController) FindNextItems(req item_dto.FindNextReq) ([]item_dto.FindNextRes, bool) {
items, ok := ic.itemUcase.FindNextViewItem(req.ExcludedIds, req.Limit)
if !ok {
return []item_dto.FindNextRes{}, false
}

return item_dto.NewFindNextRes(*items), true
}
12 changes: 11 additions & 1 deletion internal/entity/item.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ type Item struct {
Thumbnail *string `gorm:"column:thumbnail;type:varchar"`
Published time.Time `gorm:"column:published;type:timestamp;not null"`
GUID string `gorm:"column:guid;type:varchar;not null"`
Summary string `gorm:"column:summary;type:varchar"`
Views uint `gorm:"column:views;type:int8;not null;default:0"`
Likes uint `gorm:"column:likes;type:int8;not null;default:0"`
FeedID uint `gorm:"column:feed_id;type:int8;not null"`
JobTags []JobTag `gorm:"many2many:item_job_tags;"`
SkillTags []SkillTag `gorm:"many2many:item_skill_tags;"`
Expand All @@ -26,6 +29,9 @@ type ItemView struct {
ItemLink string `gorm:"column:item_link;type:varchar"`
ItemThumbnail *string `gorm:"column:item_thumbnail;type:varchar"`
ItemPublished time.Time `gorm:"column:item_published;type:timestamp"`
ItemSummary *string `gorm:"column:item_summary;type:varchar"`
ItemViews uint `gorm:"column:item_views;type:int8"`
ItemLikes uint `gorm:"column:item_likes;type:int8"`
FeedName string `gorm:"column:feed_name;type:varchar"`
FeedTitle string `gorm:"column:feed_title;type:varchar"`
FeedLink string `gorm:"column:feed_link;type:varchar"`
Expand All @@ -40,5 +46,9 @@ func (ItemView) TableName() string {

type ItemRepo interface {
CountView(company *string, companySizes *[]CompanySizeType, jobTags, skillTags *[]int64) (int64, error)
FindAllView(company *string, companySizes *[]CompanySizeType, jobTags, skillTags *[]int64, perPage int, page int) ([]ItemView, error)
FindAllView(company *string, companySizes *[]CompanySizeType, jobTags, skillTags *[]int64, perPage, page int) ([]ItemView, error)
Exist(id int64) (bool, error)
IncreaseViewCount(id int64) (int64, error)
IncreaseLikeCount(id int64) (int64, error)
FindAllViewByExcludedIds(ids []int64, perPage int32) ([]ItemView, error)
}
Loading

0 comments on commit b18660d

Please sign in to comment.