Files
novatask/internal/logic/stakepoint/stake_point_logic.go
2025-04-03 16:17:20 +08:00

238 lines
8.9 KiB
Go

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()
}