Files
arenax-server/internal/logic/reward/reward.go
2025-06-25 10:35:06 +08:00

508 lines
15 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package reward
import (
"context"
"encoding/json"
"fmt"
"server/internal/consts"
"server/internal/dao"
"server/internal/model"
"server/internal/model/do"
"server/internal/service"
"server/utility/ecode"
"server/utility/gamelife"
)
type sReward struct{}
func init() {
service.RegisterReward(New())
}
func New() service.IReward {
return &sReward{}
}
// Create 创建奖励
func (s *sReward) Create(ctx context.Context, in *model.RewardCreateIn) (out *model.RewardCreateOut, err error) {
// 仅管理员能创建系统奖励source=1
if in.Source == 1 && in.OperatorRole != consts.AdminRoleCode {
return nil, ecode.Params.Sub("只有管理员可以创建系统奖励")
}
// 权限验证
switch in.OperatorRole {
case consts.MerchantRoleCode:
// 检查商户管理员是否有该门店权限
exist, err := dao.MerchantAdmins.Ctx(ctx).LeftJoin(
dao.Stores.Table(),
fmt.Sprintf("%s.%s = %s.%s",
dao.MerchantAdmins.Table(), dao.MerchantAdmins.Columns().MerchantId,
dao.Stores.Table(), dao.Stores.Columns().MerchantId,
),
).Where(
fmt.Sprintf("%s.%s = ?", dao.Stores.Table(), dao.Stores.Columns().Id), in.StoreId,
).Where(
do.MerchantAdmins{Id: in.OperatorId},
).Exist()
if err != nil {
return nil, ecode.Fail.Sub("检查商户权限失败")
}
if !exist {
return nil, ecode.Params.Sub("无门店权限")
}
case consts.StoreRoleCode:
// 检查门店管理员是否有该门店权限
exist, err := dao.StoreAdmins.Ctx(ctx).LeftJoin(
dao.Stores.Table(),
fmt.Sprintf("%s.%s = %s.%s",
dao.StoreAdmins.Table(), dao.StoreAdmins.Columns().StoreId,
dao.Stores.Table(), dao.Stores.Columns().Id,
),
).Where(
fmt.Sprintf("%s.%s = ?", dao.Stores.Table(), dao.Stores.Columns().Id), in.StoreId,
).Where(
do.StoreAdmins{Id: in.OperatorId},
).Exist()
if err != nil {
return nil, ecode.Fail.Sub("检查门店权限失败")
}
if !exist {
return nil, ecode.Params.Sub("无门店权限")
}
}
// 创建奖励
_, err = dao.Rewards.Ctx(ctx).Data(do.Rewards{
StoreId: in.StoreId,
Name: in.Name,
RewardTypeId: in.RewardTypeId,
ImageUrl: in.Img,
QqGoodsId: in.QQGoodsId,
QqGoodsIdStr: in.QQGoodsIdStr,
Status: in.Status,
ValidFrom: in.ValidFrom,
ValidTo: in.ValidTo,
ExpireType: in.ExpireType,
ExpireDays: in.ExpireDays,
DailyTotalLimit: in.DailyTotalLimit,
TotalLimit: in.TotalLimit,
GameId: in.GameId,
UserDailyLimit: in.UserDailyLimit,
UserTotalLimit: in.UserTotalLimit,
}).OmitEmptyData().Insert()
if err != nil {
return nil, err
}
return &model.RewardCreateOut{Success: true}, nil
}
// Update 更新奖励
func (s *sReward) Update(ctx context.Context, in *model.RewardUpdateIn) (out *model.RewardUpdateOut, err error) {
// 查询原始记录,确保存在,并获取 source 与 store_id 用于权限校验
data, err := dao.Rewards.Ctx(ctx).
Fields(dao.Rewards.Columns().Id, dao.Rewards.Columns().StoreId).
Where(do.Rewards{Id: in.Id}).One()
if err != nil {
return nil, ecode.Fail.Sub("查询奖励失败")
}
if data.IsEmpty() {
return nil, ecode.Params.Sub("奖励不存在")
}
// 系统奖励source=1只能由管理员修改
if in.Source == 1 && in.OperatorRole != consts.AdminRoleCode {
return nil, ecode.Params.Sub("只有管理员可以修改系统奖励")
}
storeId := data[dao.Rewards.Columns().StoreId].Int64()
// 权限校验(管理员跳过)
switch in.OperatorRole {
case consts.MerchantRoleCode:
// 商户管理员权限校验:是否管理该门店
exist, err := dao.MerchantAdmins.Ctx(ctx).LeftJoin(
dao.Stores.Table(),
fmt.Sprintf("%s.%s = %s.%s",
dao.MerchantAdmins.Table(), dao.MerchantAdmins.Columns().MerchantId,
dao.Stores.Table(), dao.Stores.Columns().MerchantId,
),
).Where(
fmt.Sprintf("%s.%s = ?", dao.Stores.Table(), dao.Stores.Columns().Id), storeId,
).Where(
do.MerchantAdmins{Id: in.OperatorId},
).Exist()
if err != nil {
return nil, ecode.Fail.Sub("检查操作者权限异常")
}
if !exist {
return nil, ecode.Params.Sub("无门店权限")
}
case consts.StoreRoleCode:
// 门店管理员权限校验:是否管理该门店
exist, err := dao.StoreAdmins.Ctx(ctx).LeftJoin(
dao.Stores.Table(),
fmt.Sprintf("%s.%s = %s.%s",
dao.StoreAdmins.Table(), dao.StoreAdmins.Columns().StoreId,
dao.Stores.Table(), dao.Stores.Columns().Id,
),
).Where(
fmt.Sprintf("%s.%s = ?", dao.Stores.Table(), dao.Stores.Columns().Id), storeId,
).Where(
do.StoreAdmins{Id: in.OperatorId},
).Exist()
if err != nil {
return nil, ecode.Fail.Sub("检查操作者权限异常")
}
if !exist {
return nil, ecode.Params.Sub("无门店权限")
}
}
// 执行更新(不允许更新 store_id 和 source
_, err = dao.Rewards.Ctx(ctx).
Where(do.Rewards{Id: in.Id}).
Data(do.Rewards{
Name: in.Name,
RewardTypeId: in.RewardTypeId,
GameId: in.GameId,
ImageUrl: in.Img,
QqGoodsId: in.QQGoodsId,
QqGoodsIdStr: in.QQGoodsIdStr,
Status: in.Status,
ValidFrom: in.ValidFrom,
ValidTo: in.ValidTo,
ExpireType: in.ExpireType,
ExpireDays: in.ExpireDays,
DailyTotalLimit: in.DailyTotalLimit,
TotalLimit: in.TotalLimit,
UserDailyLimit: in.UserDailyLimit,
UserTotalLimit: in.UserTotalLimit,
GrantQuantity: in.GrantQuantity,
}).OmitEmptyData().Update()
if err != nil {
return nil, ecode.Fail.Sub("更新奖励失败")
}
// 判断过期类型
if in.ExpireType == 1 {
in.ExpireDays = 0
_, err = dao.Rewards.Ctx(ctx).Where(do.Rewards{Id: in.Id}).Update("expire_days = null")
if err != nil {
return nil, err
}
} else {
_, err = dao.Rewards.Ctx(ctx).Where(do.Rewards{Id: in.Id}).Update("valid_from = null,valid_to = null")
if err != nil {
return nil, err
}
}
return &model.RewardUpdateOut{Success: true}, nil
}
// Delete 删除奖励
func (s *sReward) Delete(ctx context.Context, in *model.RewardDeleteIn) (out *model.RewardDeleteOut, err error) {
data, err := dao.Rewards.Ctx(ctx).
Fields("id", "store_id").
Where(do.Rewards{Id: in.Id}).One()
if err != nil {
return nil, ecode.Fail.Sub("查询奖励失败")
}
if data.IsEmpty() {
return nil, ecode.Params.Sub("奖励不存在")
}
if in.Source == 1 && in.OperatorRole != consts.AdminRoleCode {
return nil, ecode.Params.Sub("只有管理员可以删除系统奖励")
}
storeId := data["store_id"].Int64()
switch in.OperatorRole {
case consts.MerchantRoleCode:
exist, err := dao.MerchantAdmins.Ctx(ctx).LeftJoin(
dao.Stores.Table(),
fmt.Sprintf("%s.%s = %s.%s",
dao.MerchantAdmins.Table(), dao.MerchantAdmins.Columns().MerchantId,
dao.Stores.Table(), dao.Stores.Columns().MerchantId),
).Where(fmt.Sprintf("%s.%s = ?", dao.Stores.Table(), dao.Stores.Columns().Id), storeId).
Where(do.MerchantAdmins{Id: in.OperatorId}).Exist()
if err != nil {
return nil, ecode.Fail.Sub("权限校验失败")
}
if !exist {
return nil, ecode.Params.Sub("无门店权限")
}
case consts.StoreRoleCode:
exist, err := dao.StoreAdmins.Ctx(ctx).Where(do.StoreAdmins{Id: in.OperatorId, StoreId: storeId}).Exist()
if err != nil {
return nil, ecode.Fail.Sub("权限校验失败")
}
if !exist {
return nil, ecode.Params.Sub("无门店权限")
}
}
_, err = dao.Rewards.Ctx(ctx).Where(do.Rewards{Id: in.Id}).Delete()
if err != nil {
return nil, ecode.Fail.Sub("删除失败")
}
return &model.RewardDeleteOut{Success: true}, nil
}
// List 奖励列表
func (s *sReward) List(ctx context.Context, in *model.RewardListIn) (out *model.RewardListOut, err error) {
rewardCols := dao.Rewards.Columns()
rewardTypeCols := dao.RewardTypes.Columns()
rewardTypeIds := make([]int64, 0)
// ==== 权限校验 ====
switch in.OperatorRole {
case consts.AdminRoleCode:
// 系统管理员只能查询 source = 1 的奖励
array, err := dao.RewardTypes.Ctx(ctx).Where(do.RewardTypes{Source: 1}).Fields(rewardTypeCols.Id).Array()
if err != nil {
return nil, ecode.Fail.Sub("获取奖励类型列表失败")
}
for _, value := range array {
rewardTypeIds = append(rewardTypeIds, value.Int64())
}
case consts.MerchantRoleCode, consts.StoreRoleCode:
// 合并商户和门店角色权限校验
var exist bool
if in.OperatorRole == consts.MerchantRoleCode {
exist, err = dao.MerchantAdmins.Ctx(ctx).
Where(do.MerchantAdmins{Id: in.OperatorId}).
LeftJoin(
dao.Stores.Table(),
fmt.Sprintf("%s.%s = %s.%s",
dao.MerchantAdmins.Table(), dao.MerchantAdmins.Columns().MerchantId,
dao.Stores.Table(), dao.Stores.Columns().MerchantId,
),
).
Where(fmt.Sprintf("%s.%s = ?", dao.Stores.Table(), dao.Stores.Columns().Id), in.StoreId).
Exist()
} else {
exist, err = dao.StoreAdmins.Ctx(ctx).
Where(do.StoreAdmins{Id: in.OperatorId}).
LeftJoin(
dao.Stores.Table(),
fmt.Sprintf("%s.%s = %s.%s",
dao.StoreAdmins.Table(), dao.StoreAdmins.Columns().StoreId,
dao.Stores.Table(), dao.Stores.Columns().Id,
),
).
Where(fmt.Sprintf("%s.%s = ?", dao.Stores.Table(), dao.Stores.Columns().Id), in.StoreId).
Exist()
}
if err != nil {
return nil, ecode.Fail.Sub("检查操作者权限异常")
}
if !exist {
return nil, ecode.Params.Sub("无门店权限")
}
//
array, err := dao.RewardTypes.Ctx(ctx).Where(do.RewardTypes{Source: 2, StoreId: in.StoreId}).Fields(rewardTypeCols.Id).Array()
if err != nil {
return nil, ecode.Fail.Sub("获取奖励类型列表失败")
}
for _, value := range array {
rewardTypeIds = append(rewardTypeIds, value.Int64())
}
default:
return nil, ecode.Params.Sub("无效的角色")
}
orm := dao.Rewards.Ctx(ctx).LeftJoin(
dao.RewardTypes.Table(),
fmt.Sprintf(
"%s.%s = %s.%s",
dao.Rewards.Table(), dao.Rewards.Columns().RewardTypeId,
dao.RewardTypes.Table(), dao.RewardTypes.Columns().Id,
),
).Fields(fmt.Sprintf("%s.*,%s.name as reward_type_name", dao.Rewards.Table(), dao.RewardTypes.Table())).
WhereIn(dao.Rewards.Columns().RewardTypeId, rewardTypeIds)
// ==== 其他查询条件 ====
if in.Status != 0 {
orm = orm.Where(fmt.Sprintf("%s.%s = ?", dao.Rewards.Table(), rewardCols.Status), in.Status)
}
if in.RewardTypeId != 0 {
// 确保 reward_type_id 过滤独立应用
orm = orm.Where(fmt.Sprintf("%s.%s = ?", dao.Rewards.Table(), rewardCols.RewardTypeId), in.RewardTypeId)
}
if in.Name != "" {
orm = orm.WhereLike(rewardCols.Name, "%"+in.Name+"%")
}
// ==== 总数统计 ====
list := make([]model.Reward, 0)
var total int
err = orm.ScanAndCount(&list, &total, false)
if err != nil {
return nil, err
}
return &model.RewardListOut{
List: list,
Total: total,
}, nil
}
// GetLift 领取奖励
func (s *sReward) GetLift(ctx context.Context, in *model.GetRewardIn) (out *model.GetRewardOut, err error) {
// 遍历奖励类型列表
//for _, v := range in.RewradTypeId {
// if v > 0 {
// // 发背包+兑换
//
// }
// if v > 0 {
// // 直接发背包
// }
//}
activity, err := gamelife.GetGamelifeClient(ctx).RequestActivity(ctx, &model.QQNetbarActivityIn{PopenId: in.PopenId, ServiceName: consts.GetGift, GiftParam: model.GiftParam{
TaskId: in.TaskId,
AreaId: in.AreaId,
Gid: in.GameId,
RoleIdx: in.RoleIdx,
}})
if err != nil {
return nil, err
}
result, ok := activity.(*model.GiftResponse)
if !ok {
return nil, ecode.Fail.Sub("数据类型转换失败")
}
// 存储数据库记录
for _, item := range result.GiftItem {
marshal, err := json.Marshal(item.Water)
if err != nil {
return nil, ecode.Fail.Sub("序列化 json 数据出现异常")
}
_, err = dao.RewardWaters.Ctx(ctx).Insert(model.RewardWaters{
OrderId: item.Water.OrderId,
Status: int64(item.Water.Status),
Uid: item.Water.Uid,
TaskId: "BZD",
Water: string(marshal),
})
if err != nil {
return nil, ecode.Fail.Sub("添加奖励领取记录异常")
}
}
return nil, err
}
// GetGoodsList 调用外部获取物品列表
func (s *sReward) GetGoodsList(ctx context.Context, in *model.GetGoodsListIn) (out *model.GetGoodsListOut, err error) {
var user model.User
// 查询用户信息
//err = dao.Users.Ctx(ctx).Where(do.Users{Id: in.UserId}).Scan(&user)
err = dao.Users.Ctx(ctx).Where(do.Users{Id: 19}).Scan(&user)
if err != nil {
return nil, ecode.Fail.Sub("查询用户失败")
}
var pOpenId string
// 判断绑定类型 QQ还是WX
if in.BindType == 1 {
pOpenId = user.QQPopenId
} else {
pOpenId = user.WXPopenId
}
// 调用 tencent
result, err := gamelife.GetGamelifeClient(ctx).RequestActivity(ctx, &model.QQNetbarActivityIn{ServiceName: consts.QueryUserGoodsList, BindType: in.BindType,
GoodsParam: model.GoodsParam{AppFilter: in.Appfilter, BigTime: in.BigTime, GoodsStatus: int(in.Goodsstatus), Num: int(in.Num), OrderByDesc: true, OrderType: in.OrderType, Pageidx: in.Pageidx, Gid: 26},
PopenId: pOpenId, NickName: user.Nickname})
if err != nil {
return nil, ecode.Fail.Sub("请求失败")
}
response, ok := result.(*model.GoodsResponse)
if !ok {
return nil, ecode.Fail.Sub("类型断言失败")
}
return &model.GetGoodsListOut{
List: response.Waters,
Pageidx: response.PageIdx,
Total: response.Total,
}, nil
}
// GetGoods 物品兑换
func (s *sReward) GetGoods(ctx context.Context, in *model.GetGoodsGetIn) (out *model.GoodsGetOut, err error) {
return nil, err
}
// GetGoodsDetails 物品详情
func (s *sReward) GetGoodsDetails(ctx context.Context, in *model.GetGoodsDetailsIn) (out *model.QueryUserGoodsDetailResponse, err error) {
//
activity, err := gamelife.GetGamelifeClient(ctx).RequestActivity(ctx, &model.QQNetbarActivityIn{PopenId: in.PopenId, ServiceName: consts.QueryUserGoodsDetail, QueryUserGoodsDetailParam: model.QueryUserGoodsDetailParam{
Gid: in.Gid,
WinningTime: in.WinningTime,
OrderId: in.OrderId,
IsActInfo: in.IsActInfo,
IsDocument: in.IsDocument,
IsDetail: in.IsDetail,
}})
if err != nil {
return nil, err
}
result, ok := activity.(*model.QueryUserGoodsDetailResponse)
if !ok {
return nil, ecode.Fail.Sub("数据类型转换失败")
}
return &model.QueryUserGoodsDetailResponse{
Water: result.Water,
}, nil
}
func (s *sReward) OperateTaskReward(ctx context.Context, in *model.OperateTaskRewardIn) (out *model.OperateTaskRewardOut, err error) {
// 如果是系统管理员给任务添加奖励,需要校验奖励的来源
exist, err := dao.Tasks.Ctx(ctx).Where(do.Tasks{Id: in.TaskId}).Exist()
if err != nil {
return nil, ecode.Fail.Sub("任务不存在")
}
if !exist {
return nil, ecode.Params.Sub("任务不存在")
}
exist, err = dao.Rewards.Ctx(ctx).Where(do.Rewards{Id: in.RewardId}).Exist()
if err != nil {
return nil, ecode.Fail.Sub("奖励不存在")
}
if !exist {
return nil, ecode.Params.Sub("奖励不存在")
}
opiton := dao.TaskRewards.Ctx(ctx).Data(do.TaskRewards{TaskId: in.TaskId, RewardId: in.RewardId})
if in.Type == 1 {
_, err := opiton.Insert()
return &model.OperateTaskRewardOut{Success: true}, err
} else {
_, err := opiton.Delete()
return &model.OperateTaskRewardOut{Success: true}, err
}
}