feat: 积分质押功能
This commit is contained in:
27
internal/logic/admin/game_action_logic.go
Normal file
27
internal/logic/admin/game_action_logic.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"nova_task/internal/svc"
|
||||
"nova_task/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GameActionLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGameActionLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GameActionLogic {
|
||||
return &GameActionLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GameActionLogic) GameAction(req *types.GameActionReq) (any, error) {
|
||||
return l.svcCtx.GameAction(l.ctx, req.RoleId, req.Action, nil)
|
||||
}
|
||||
147
internal/logic/stakepoint/get_stake_level_list_logic.go
Normal file
147
internal/logic/stakepoint/get_stake_level_list_logic.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package stakepoint
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/shopspring/decimal"
|
||||
"github.com/spf13/cast"
|
||||
"nova_task/internal/consts"
|
||||
"nova_task/internal/model"
|
||||
"nova_task/internal/pkg/errs"
|
||||
"time"
|
||||
|
||||
"nova_task/internal/svc"
|
||||
"nova_task/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type GetStakeLevelListLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
func NewGetStakeLevelListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetStakeLevelListLogic {
|
||||
return &GetStakeLevelListLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *GetStakeLevelListLogic) GetStakeLevelList(req *types.GetStakeLevelListReq) (*types.GetStakeLevelListResp, error) {
|
||||
resp, err := l.svcCtx.GameAction(l.ctx, req.RoleID, consts.GameActionGetHomePointsState, nil)
|
||||
if err != nil {
|
||||
l.Errorw("GetStakeLevelList", logx.Field("err", err))
|
||||
return nil, errs.New(errs.GameServerError, err)
|
||||
}
|
||||
if !cast.ToBool(resp.(map[string]any)["data"]) {
|
||||
l.Debugw("getStakeHomePointsState", logx.Field("role", req.RoleID), logx.Field("resp", resp))
|
||||
return &types.GetStakeLevelListResp{
|
||||
State: 0,
|
||||
}, nil
|
||||
}
|
||||
lvs, err := l.svcCtx.StakePointConfigModel.All(l.ctx)
|
||||
if err != nil {
|
||||
l.Errorw("GetStakeLevelList", logx.Field("err", err))
|
||||
return nil, errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
var ls []types.PointStakeLevel
|
||||
for _, lv := range lvs {
|
||||
ls = append(ls, types.PointStakeLevel{
|
||||
Id: int(lv.Id),
|
||||
Title: lv.Title,
|
||||
Level: int(lv.Level),
|
||||
Points: int(lv.Points),
|
||||
Days: lv.Days.InexactFloat64(),
|
||||
RenewDays: lv.RenewDays.InexactFloat64(),
|
||||
})
|
||||
}
|
||||
stake, err := l.svcCtx.StakePointsModel.FindCurrentLevel(l.ctx, req.RoleID)
|
||||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||
l.Errorw("GetStakeLevelList", logx.Field("err", err), logx.Field("role_id", req.RoleID))
|
||||
return nil, errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
var staking *types.StakeLevel
|
||||
var hasRenew bool
|
||||
if stake != nil {
|
||||
var (
|
||||
title string
|
||||
level int
|
||||
points int
|
||||
days float64
|
||||
renewDays float64
|
||||
canRenew bool
|
||||
)
|
||||
for _, lv := range lvs {
|
||||
if lv.Id == stake.LevelId {
|
||||
title = lv.Title
|
||||
level = int(lv.Level)
|
||||
points = int(lv.Points)
|
||||
days = lv.Days.InexactFloat64()
|
||||
renewDays = lv.RenewDays.InexactFloat64()
|
||||
canRenew = stake.EndTime.Sub(time.Now()) <= time.Duration(lv.RenewDays.Mul(decimal.NewFromInt(int64(time.Hour*24))).IntPart()) && stake.Status == model.PointsStakeStatusStaking
|
||||
break
|
||||
}
|
||||
}
|
||||
hasRenew = stake.Status == model.PointsStakeStatusRenew
|
||||
|
||||
staking = &types.StakeLevel{
|
||||
Id: int(stake.LevelId),
|
||||
Title: title,
|
||||
Level: level,
|
||||
Points: points,
|
||||
Days: days,
|
||||
RenewDays: renewDays,
|
||||
StartTime: stake.StartTime.Format(time.DateTime),
|
||||
EndTime: stake.EndTime.Format(time.DateTime),
|
||||
CanRenew: canRenew,
|
||||
}
|
||||
}
|
||||
var renewLevel *types.StakeLevel
|
||||
if hasRenew {
|
||||
stk, err := l.svcCtx.StakePointsModel.FindRenewLevel(l.ctx, req.RoleID)
|
||||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||
l.Errorw("GetStakeLevelList", logx.Field("err", err), logx.Field("role_id", req.RoleID))
|
||||
return nil, errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
|
||||
if stk != nil {
|
||||
var (
|
||||
title string
|
||||
level int
|
||||
points int
|
||||
days float64
|
||||
renewDays float64
|
||||
)
|
||||
for _, lv := range lvs {
|
||||
if lv.Id == stk.LevelId {
|
||||
title = lv.Title
|
||||
level = int(lv.Level)
|
||||
points = int(lv.Points)
|
||||
days = lv.Days.InexactFloat64()
|
||||
renewDays = lv.RenewDays.InexactFloat64()
|
||||
break
|
||||
}
|
||||
}
|
||||
renewLevel = &types.StakeLevel{
|
||||
Id: int(stk.LevelId),
|
||||
Title: title,
|
||||
Level: level,
|
||||
Points: points,
|
||||
Days: days,
|
||||
RenewDays: renewDays,
|
||||
StartTime: stk.StartTime.Format(time.DateTime),
|
||||
EndTime: stk.EndTime.Format(time.DateTime),
|
||||
CanRenew: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
return &types.GetStakeLevelListResp{
|
||||
State: 1,
|
||||
Staking: staking,
|
||||
RenewLevel: renewLevel,
|
||||
Levels: ls,
|
||||
}, nil
|
||||
}
|
||||
237
internal/logic/stakepoint/stake_point_logic.go
Normal file
237
internal/logic/stakepoint/stake_point_logic.go
Normal file
@@ -0,0 +1,237 @@
|
||||
package stakepoint
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/shopspring/decimal"
|
||||
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
||||
"nova_task/internal/consts"
|
||||
"nova_task/internal/model"
|
||||
"nova_task/internal/pkg/errs"
|
||||
"nova_task/internal/pkg/utils"
|
||||
"time"
|
||||
|
||||
"nova_task/internal/svc"
|
||||
"nova_task/internal/types"
|
||||
|
||||
"github.com/zeromicro/go-zero/core/logx"
|
||||
)
|
||||
|
||||
type StakePointLogic struct {
|
||||
logx.Logger
|
||||
ctx context.Context
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
// 质押积分操作
|
||||
func NewStakePointLogic(ctx context.Context, svcCtx *svc.ServiceContext) *StakePointLogic {
|
||||
return &StakePointLogic{
|
||||
Logger: logx.WithContext(ctx),
|
||||
ctx: ctx,
|
||||
svcCtx: svcCtx,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *StakePointLogic) StakePoint(req *types.StakePointReq) error {
|
||||
uid := utils.GetUid(l.ctx)
|
||||
r, err := l.svcCtx.RoleModel.FindOneByRoleId(l.ctx, req.RoleID)
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
return errs.New(errs.ErrRoleNotFound, "role not exist")
|
||||
}
|
||||
l.Errorw("find role error", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid), logx.Field("level_id", req.LevelId), logx.Field("action", req.Action))
|
||||
return errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
u, err := l.svcCtx.UserModel.FindOneByEmail(l.ctx, r.Account)
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
return errs.New(errs.ErrUserNotFound, "user not found")
|
||||
}
|
||||
l.Errorw("find user error", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid), logx.Field("level_id", req.LevelId), logx.Field("action", req.Action))
|
||||
return errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
if u.Id != uint(uid) {
|
||||
return errs.New(errs.ErrRoleNotFound, "role not exist")
|
||||
}
|
||||
lv, err := l.svcCtx.StakePointConfigModel.FindOne(l.ctx, uint(req.LevelId))
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
return errs.New(errs.ErrPointLevelConfigNotFound, "stake point level config not found")
|
||||
}
|
||||
return errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
clv, err := l.svcCtx.StakePointsModel.FindCurrentLevel(l.ctx, req.RoleID)
|
||||
if err != nil && !errors.Is(err, model.ErrNotFound) {
|
||||
l.Errorw("find current level error", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid), logx.Field("level_id", req.LevelId), logx.Field("action", req.Action))
|
||||
return errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
start := time.Now()
|
||||
end := start.Add(time.Duration(lv.Days.Mul(decimal.NewFromInt(int64(time.Hour * 24))).IntPart()))
|
||||
switch req.Action {
|
||||
case 1:
|
||||
if err == nil {
|
||||
return errs.New(errs.ErrPointsStakeExist, "stake points exist")
|
||||
}
|
||||
err = l.svcCtx.DBConn.TransactCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||
err = l.svcCtx.AddUserAssetWithSession(ctx, session, uint(uid), req.RoleID, consts.AssetType_Points, "", decimal.NewFromInt(int64(-lv.Points)), "stake points", 0, 0, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = l.svcCtx.StakePointsModel.WithSession(session).Insert(l.ctx, &model.NhStakePoints{
|
||||
Uid: uint(uid),
|
||||
RoleId: uint64(req.RoleID),
|
||||
LevelId: lv.Id,
|
||||
Level: lv.Level,
|
||||
Points: lv.Points,
|
||||
StartTime: start,
|
||||
EndTime: end,
|
||||
Status: model.PointsStakeStatusStaking,
|
||||
})
|
||||
if err != nil {
|
||||
return errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
_, err := l.svcCtx.GameAction(ctx, req.RoleID, consts.GameActionStakePoints, map[string]any{
|
||||
"level": lv.Level,
|
||||
"operation": req.Action,
|
||||
"start_time": start.Unix(),
|
||||
"end_time": end.Unix(),
|
||||
"renew_times": 0,
|
||||
})
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("积分质押", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid), logx.Field("level_id", req.LevelId), logx.Field("action", req.Action))
|
||||
return errs.New(errs.ErrInternalServer, err)
|
||||
}
|
||||
|
||||
case 2:
|
||||
if err != nil {
|
||||
l.Errorw("用户在未质押的情况下进行升级", logx.Field("uid", uid), logx.Field("role_id", req.RoleID))
|
||||
return errs.New(errs.ErrPointStakeNotExist, "stake points not exist")
|
||||
}
|
||||
clvConfig, err := l.svcCtx.StakePointConfigModel.FindOne(l.ctx, clv.LevelId)
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
return errs.New(errs.ErrPointLevelConfigNotFound, "current stake point level config not found")
|
||||
}
|
||||
return errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
if lv.Level <= clvConfig.Level {
|
||||
return errs.New(errs.ErrPointsStakeLevelNotAllow, "Upgraded pledge credit bracket must be higher than current bracket")
|
||||
}
|
||||
// 已续约,不可升级
|
||||
if clv.Status != model.PointsStakeStatusStaking {
|
||||
return errs.New(errs.ErrPointsStakeHasRenew, "Current stake has renew")
|
||||
}
|
||||
err = l.svcCtx.DBConn.TransactCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||
points := lv.Points - clvConfig.Points
|
||||
err = l.svcCtx.AddUserAssetWithSession(ctx, session, uint(uid), req.RoleID, consts.AssetType_Points, "", decimal.NewFromInt(int64(-points)), "stake points", 0, 0, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
clv.Status = model.PointsStakeStatusUpgraded
|
||||
clv.EndTime = start
|
||||
spm := l.svcCtx.StakePointsModel.WithSession(session)
|
||||
err := spm.Update(ctx, clv)
|
||||
if err != nil {
|
||||
return errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
end = start.Add(time.Duration(lv.Days.Mul(decimal.NewFromInt(int64(time.Hour*24))).IntPart()) - start.Sub(clv.StartTime))
|
||||
_, err = spm.Insert(l.ctx, &model.NhStakePoints{
|
||||
Uid: uint(uid),
|
||||
RoleId: uint64(req.RoleID),
|
||||
LevelId: lv.Id,
|
||||
Level: lv.Level,
|
||||
Points: lv.Points,
|
||||
StartTime: start,
|
||||
EndTime: end,
|
||||
Status: model.PointsStakeStatusStaking,
|
||||
})
|
||||
if err != nil {
|
||||
return errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
_, err = l.svcCtx.GameAction(ctx, req.RoleID, consts.GameActionStakePoints, map[string]any{
|
||||
"level": lv.Level,
|
||||
"operation": req.Action,
|
||||
"start_time": start.Unix(),
|
||||
"end_time": end.Unix(),
|
||||
"renew_times": 0,
|
||||
})
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("积分质押升级失败", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid), logx.Field("level_id", req.LevelId), logx.Field("action", req.Action))
|
||||
return errs.New(errs.ErrInternalServer, err)
|
||||
}
|
||||
case 3:
|
||||
if err != nil {
|
||||
l.Errorw("用户在未质押的情况下进行续约", logx.Field("uid", uid), logx.Field("role_id", req.RoleID))
|
||||
return errs.New(errs.ErrPointStakeNotExist, "stake points not exist")
|
||||
}
|
||||
clvConfig, err := l.svcCtx.StakePointConfigModel.FindOne(l.ctx, clv.LevelId)
|
||||
if err != nil {
|
||||
if errors.Is(err, model.ErrNotFound) {
|
||||
return errs.New(errs.ErrPointLevelConfigNotFound, "current stake point level config not found")
|
||||
}
|
||||
return errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
// 续约等级不能小于当前等级
|
||||
if lv.Level < clvConfig.Level {
|
||||
return errs.New(errs.ErrPointsStakeLevelNotAllow, "Renewal level cannot be lower than current level")
|
||||
}
|
||||
// 已续约,不可重复续约
|
||||
if clv.Status != model.PointsStakeStatusStaking {
|
||||
return errs.New(errs.ErrPointsStakeHasRenew, "Current stake has renew")
|
||||
}
|
||||
// 判断是否在可续约时间范围内
|
||||
if clv.EndTime.Sub(time.Now()) > time.Duration(clvConfig.RenewDays.Mul(decimal.NewFromInt(int64(time.Hour*24))).IntPart()) {
|
||||
return errs.New(errs.ErrPointsStakeNotInRenewTime, "Not within the renewal time frame")
|
||||
}
|
||||
// 判断是否属于续约期内
|
||||
err = l.svcCtx.DBConn.TransactCtx(l.ctx, func(ctx context.Context, session sqlx.Session) error {
|
||||
points := lv.Points - clvConfig.Points
|
||||
if points > 0 {
|
||||
err = l.svcCtx.AddUserAssetWithSession(ctx, session, uint(uid), req.RoleID, consts.AssetType_Points, "", decimal.NewFromInt(int64(-points)), "stake points", 0, 0, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
clv.Status = model.PointsStakeStatusRenew
|
||||
spm := l.svcCtx.StakePointsModel.WithSession(session)
|
||||
err := spm.Update(ctx, clv)
|
||||
if err != nil {
|
||||
return errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
end = clv.EndTime.Add(time.Duration(lv.Days.Mul(decimal.NewFromInt(int64(time.Hour * 24))).IntPart()))
|
||||
_, err = spm.Insert(l.ctx, &model.NhStakePoints{
|
||||
Uid: uint(uid),
|
||||
RoleId: uint64(req.RoleID),
|
||||
LevelId: lv.Id,
|
||||
Level: lv.Level,
|
||||
Points: lv.Points,
|
||||
StartTime: clv.EndTime,
|
||||
EndTime: end,
|
||||
Status: model.PointsStakeStatusStaking,
|
||||
})
|
||||
if err != nil {
|
||||
return errs.New(errs.ErrDatabaseOperate, err)
|
||||
}
|
||||
_, err = l.svcCtx.GameAction(ctx, req.RoleID, consts.GameActionStakePoints, map[string]any{
|
||||
"level": lv.Level,
|
||||
"operation": req.Action,
|
||||
"start_time": start.Unix(),
|
||||
"end_time": end.Unix(),
|
||||
"renew_times": 0,
|
||||
})
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
l.Errorw("积分质押续期失败", logx.Field("err", err), logx.Field("role_id", req.RoleID), logx.Field("uid", uid), logx.Field("level_id", req.LevelId), logx.Field("action", req.Action))
|
||||
return errs.New(errs.ErrInternalServer, err)
|
||||
}
|
||||
default:
|
||||
return errs.New(errs.ErrInvalidParam, "Invalid action")
|
||||
}
|
||||
return errs.Success()
|
||||
}
|
||||
Reference in New Issue
Block a user