Skip to content

Commit

Permalink
feat(controller, poll): cancel poll
Browse files Browse the repository at this point in the history
  • Loading branch information
greenhat616 committed Aug 9, 2023
1 parent 89b7594 commit c213445
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 11 deletions.
6 changes: 1 addition & 5 deletions api/poll/v1/cancel.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@ package v1

import (
"github.com/gogf/gf/v2/frame/g"
"github.com/hitokoto-osc/reviewer/internal/model"
)

type CancelPollReq struct {
g.Meta `path:"/poll/:id/cancel" tags:"Poll" method:"delete" summary:"取消投票"`
ID int `json:"id" dc:"投票 ID" v:"required|min:1#请输入投票 ID"`
}

type CancelPollRes struct {
model.PollElement
PollData model.PolledData `json:"poll_data" dc:"投票数据"`
}
type CancelPollRes struct{}
4 changes: 2 additions & 2 deletions api/poll/v1/poll.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ type PollReq struct {
Comment string `json:"comment" dc:"理由" v:"length:1,255"`
}

// PollRes 成功返回句子的投票记录
type PollRes = GetPollDetailRes
// PollRes 成功返回空结构
type PollRes struct{}
47 changes: 46 additions & 1 deletion internal/controller/poll/poll_v1_cancel_poll.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,57 @@ package poll
import (
"context"

"github.com/hitokoto-osc/reviewer/internal/consts"
"github.com/hitokoto-osc/reviewer/internal/model"
"github.com/hitokoto-osc/reviewer/internal/model/entity"
"github.com/hitokoto-osc/reviewer/internal/service"
"golang.org/x/sync/errgroup"

"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"

v1 "github.com/hitokoto-osc/reviewer/api/poll/v1"
)

// CancelPoll 目前只用于撤回普通的投票
func (c *ControllerV1) CancelPoll(ctx context.Context, req *v1.CancelPollReq) (res *v1.CancelPollRes, err error) {
return nil, gerror.NewCode(gcode.CodeNotImplemented)
var (
user = service.BizCtx().GetUser(ctx)
poll *entity.Poll
polledData *model.PolledData
)
eg, egCtx := errgroup.WithContext(ctx)
// 获取投票信息
eg.Go(func() (e error) {
poll, e = service.Poll().GetPollByID(egCtx, req.ID)
return e
})
// 获取已投票信息
eg.Go(func() (e error) {
polledData, e = service.User().GetUserPolledDataWithPollID(egCtx, user.Id, uint(req.ID))
return e
})
err = eg.Wait()
if err != nil {
return nil, gerror.WrapCode(gcode.CodeInternalError, err, "无法获取投票信息:")
}
if polledData == nil {
return nil, gerror.NewCode(gcode.CodeInvalidOperation, "您尚未对此投票,无需撤回!")
}
if poll == nil {
return nil, gerror.NewCode(gcode.CodeInvalidOperation, "投票不存在。可能是系統問題,建議聯係管理員。")
}
if poll.Status != int(consts.PollStatusOpen) {
return nil, gerror.NewCode(gcode.CodeInvalidOperation, "此投票已結束投票階段,無法撤回投票。")
}
err = service.Poll().CancelPollByID(ctx, &model.CancelPollInput{
PollID: uint(req.ID),
UserID: user.Id,
SentenceUUID: poll.SentenceUuid,
PolledData: polledData,
})
if err != nil {
return nil, gerror.WrapCode(gcode.CodeOperationFailed, err, "撤回投票失败:")
}
return nil, nil
}
2 changes: 1 addition & 1 deletion internal/logic/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (s *sCache) RemovePrefixes(ctx context.Context, prefixes []string) error {
return err
}

func (s *sCache) RemoveCacheAfterPollUpdated(ctx context.Context, userID, pollID uint, sentenceUUID string) {
func (s *sCache) ClearCacheAfterPollUpdated(ctx context.Context, userID, pollID uint, sentenceUUID string) {
if e := service.Cache().RemovePrefixes(ctx, []string{
"poll:list",
"poll_logs:uid:" + gconv.String(userID),
Expand Down
78 changes: 77 additions & 1 deletion internal/logic/poll/poll.go
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,82 @@ func (s *sPoll) Poll(ctx context.Context, in *model.PollInput) error {
return gerror.Wrap(err, "poll failed")
}
// Remove caches
go service.Cache().RemoveCacheAfterPollUpdated(ctx, in.UserID, in.PollID, in.SentenceUUID)
go service.Cache().ClearCacheAfterPollUpdated(ctx, in.UserID, in.PollID, in.SentenceUUID)
return nil
}

func (s *sPoll) CancelPollByID(ctx context.Context, in *model.CancelPollInput) error {
if in == nil {
return gerror.New("input is empty")
}
err := g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
eg, egCtx := errgroup.WithContext(ctx)
// 更新投票信息
eg.Go(func() error {
affectedRows, e := dao.Poll.Ctx(egCtx).TX(tx).Where(dao.Poll.Columns().Id, in.PollID).
Data(g.Map{
translatePollMethodToField(in.PolledData.Method): gdb.Raw(
fmt.Sprintf("%s-%d",
translatePollMethodToField(in.PolledData.Method),
in.PolledData.Point,
),
),
}).
UpdateAndGetAffected()
if e != nil {
return e
} else if affectedRows == 0 {
return gerror.New("failed to update poll because poll not found")
}
return nil
})
// 更新用户投票信息
if in.PolledData.Method != consts.PollMethodNeedCommonUserPoll {
eg.Go(func() error {
affectedRows, e := dao.PollUsers.Ctx(egCtx).TX(tx).Where(dao.PollUsers.Columns().Id, in.UserID).
Data(g.Map{
dao.PollUsers.Columns().Points: gdb.Raw(
fmt.Sprintf("%s-%d",
dao.PollUsers.Columns().Points,
in.PolledData.Point,
),
),
translatePollMethodToField(in.PolledData.Method): gdb.Raw(
fmt.Sprintf("%s-%d",
translatePollMethodToField(in.PolledData.Method),
in.PolledData.Point,
),
),
}).
UpdateAndGetAffected()
if e != nil {
return e
} else if affectedRows == 0 {
return gerror.New("failed to update poll because poll not found")
}
return nil
})
}
// 删除投票标记
eg.Go(func() error {
_, e := dao.PollMarkRelation.Ctx(egCtx).TX(tx).Where(dao.PollMarkRelation.Columns().UserId, in.UserID).
Where(dao.PollMarkRelation.Columns().PollId, in.PollID).
Delete()
return e
})
// 删除投票日记
eg.Go(func() error {
_, e := dao.PollLog.Ctx(egCtx).TX(tx).Where(dao.PollLog.Columns().UserId, in.UserID).
Where(dao.PollLog.Columns().PollId, in.PollID).
Where(dao.PollLog.Columns().Type, in.PolledData.Method).
Delete()
return e
})
return eg.Wait()
})
if err != nil {
return gerror.Wrap(err, "cancel poll failed")
}
go service.Cache().ClearCacheAfterPollUpdated(ctx, in.UserID, in.PollID, in.SentenceUUID)
return nil
}
1 change: 1 addition & 0 deletions internal/logic/user/poll_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ func (s *sUser) GetUserPolledDataWithPollID(ctx context.Context, userID, pid uin
err := dao.PollLog.Ctx(ctx).
Where(dao.PollLog.Columns().PollId, pid).
Where(dao.PollLog.Columns().UserId, userID).
WhereNot(dao.PollLog.Columns().Type, consts.PollMethodNeedCommonUserPoll). // 排除需要普通用户投票的记录
Scan(&pollLog)
if err != nil {
return nil, err
Expand Down
7 changes: 7 additions & 0 deletions internal/model/poll.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,10 @@ type PollInput struct {
IsAdmin bool `json:"is_admin" dc:"是否为管理员"`
Marks []int `json:"marks" dc:"标记"`
}

type CancelPollInput struct {
PollID uint `json:"poll_id" dc:"投票 ID"`
UserID uint `json:"user_id" dc:"用户 ID"`
SentenceUUID string `json:"sentence_uuid" dc:"句子 UUID"`
PolledData *PolledData `json:"polled_data" dc:"投票数据"`
}
2 changes: 1 addition & 1 deletion internal/service/cache.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions internal/service/poll.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c213445

Please sign in to comment.