diff --git a/api/reward/reward.go b/api/reward/reward.go new file mode 100644 index 0000000..3742e68 --- /dev/null +++ b/api/reward/reward.go @@ -0,0 +1,18 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package reward + +import ( + "context" + + "server/api/reward/v1" +) + +type IRewardV1 interface { + List(ctx context.Context, req *v1.ListReq) (res *v1.ListRes, err error) + Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) + Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) + Delete(ctx context.Context, req *v1.DeleteReq) (res *v1.DeleteRes, err error) +} diff --git a/api/reward/v1/reward.go b/api/reward/v1/reward.go new file mode 100644 index 0000000..3f49952 --- /dev/null +++ b/api/reward/v1/reward.go @@ -0,0 +1,63 @@ +package v1 + +import "github.com/gogf/gf/v2/frame/g" + +type ListReq struct { + g.Meta `path:"/reward" method:"get" tags:"Reward" summary:"(系统、商户、门店后台)获取奖励列表"` + Name string `json:"name" dc:"名称"` + Page int `json:"page" dc:"页数"` + Size int `json:"size" dc:"每页数量"` + Status int `json:"status" dc:"状态"` + StoreId int64 `json:"storeId" dc:"门店ID"` + OperatorRole int `json:"operatorRole" dc:"操作者角色"` + OperatorId int64 `json:"operatorId" dc:"操作者ID"` +} + +type ListRes struct { + List interface{} `json:"list" dc:"奖励列表"` + Total int `json:"total" dc:"总数"` +} + +type CreateReq struct { + g.Meta `path:"/reward" method:"post" tags:"Reward" summary:"(系统、商户、门店后台)创建奖励"` + Name string `json:"name" v:"required#名称不能为空" dc:"名称"` + Description string `json:"description" v:"required#描述不能为空" dc:"描述"` + Value int64 `json:"value" v:"required#数值不能为空" dc:"奖励值"` + Status int `json:"status" dc:"状态" d:"1"` + StoreId int64 `json:"storeId" dc:"门店ID"` + RewardTypeId int64 `json:"rewardTypeId" v:"required#奖励类型ID不能为空" dc:"奖励类型ID"` + Source int `json:"source" v:"in:1,2#来源只能为1或2" dc:"来源"` + OperatorRole int `json:"operatorRole" dc:"操作者角色"` + OperatorId int64 `json:"operatorId" dc:"操作者ID"` +} + +type CreateRes struct { + Id int64 `json:"id" dc:"奖励ID"` +} + +type UpdateReq struct { + g.Meta `path:"/reward" method:"put" tags:"Reward" summary:"(系统、商户、门店后台)更新奖励"` + Id int64 `json:"id" v:"required#ID不能为空" dc:"ID"` + Name string `json:"name" v:"required#名称不能为空" dc:"名称"` + Description string `json:"description" v:"required#描述不能为空" dc:"描述"` + Value int64 `json:"value" v:"required#数值不能为空" dc:"奖励值"` + Status int `json:"status" dc:"状态" d:"1"` + StoreId int64 `json:"storeId" dc:"门店ID"` + OperatorRole int `json:"operatorRole" dc:"操作者角色"` + OperatorId int64 `json:"operatorId" dc:"操作者ID"` +} + +type UpdateRes struct { + Success bool `json:"success" dc:"是否成功"` +} + +type DeleteReq struct { + g.Meta `path:"/reward/{id}" method:"delete" tags:"Reward" summary:"(系统、商户、门店后台)删除奖励"` + Id int64 `in:"path" json:"id" v:"required#ID不能为空" dc:"ID"` + OperatorRole int `json:"operatorRole" dc:"操作者角色"` + OperatorId int64 `json:"operatorId" dc:"操作者ID"` +} + +type DeleteRes struct { + Success bool `json:"success" dc:"是否成功"` +} diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 34096bc..5fb107d 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -11,6 +11,7 @@ import ( "server/internal/controller/game" "server/internal/controller/merchant" "server/internal/controller/merchantAdmin" + "server/internal/controller/reward" "server/internal/controller/rewardType" "server/internal/controller/role" "server/internal/controller/store" @@ -54,6 +55,7 @@ var ( task.NewV1(), game.NewV1(), rewardType.NewV1(), + reward.NewV1(), ) }) }) diff --git a/internal/controller/reward/reward.go b/internal/controller/reward/reward.go new file mode 100644 index 0000000..5627599 --- /dev/null +++ b/internal/controller/reward/reward.go @@ -0,0 +1,5 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package reward diff --git a/internal/controller/reward/reward_new.go b/internal/controller/reward/reward_new.go new file mode 100644 index 0000000..94c347d --- /dev/null +++ b/internal/controller/reward/reward_new.go @@ -0,0 +1,15 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package reward + +import ( + "server/api/reward" +) + +type ControllerV1 struct{} + +func NewV1() reward.IRewardV1 { + return &ControllerV1{} +} diff --git a/internal/controller/reward/reward_v1_create.go b/internal/controller/reward/reward_v1_create.go new file mode 100644 index 0000000..fbf4c5b --- /dev/null +++ b/internal/controller/reward/reward_v1_create.go @@ -0,0 +1,31 @@ +package reward + +import ( + "context" + "github.com/gogf/gf/v2/frame/g" + "server/internal/model" + "server/internal/service" + + "server/api/reward/v1" +) + +func (c *ControllerV1) Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) { + fromCtx := g.RequestFromCtx(ctx) + operatorId := fromCtx.GetCtxVar("id").Int64() + operatorRole := fromCtx.GetCtxVar("role").String() + out, err := service.Reward().Create(ctx, &model.RewardCreateIn{ + Name: req.Name, + Description: req.Description, + Value: req.Value, + Status: req.Status, + OperatorId: operatorId, + OperatorRole: operatorRole, + StoreId: req.StoreId, + RewardTypeId: req.RewardTypeId, + Source: req.Source, + }) + if err != nil { + return nil, err + } + return &v1.CreateRes{Id: out.Id}, nil +} diff --git a/internal/controller/reward/reward_v1_delete.go b/internal/controller/reward/reward_v1_delete.go new file mode 100644 index 0000000..839c314 --- /dev/null +++ b/internal/controller/reward/reward_v1_delete.go @@ -0,0 +1,21 @@ +package reward + +import ( + "context" + "github.com/gogf/gf/v2/frame/g" + "server/internal/model" + "server/internal/service" + + "server/api/reward/v1" +) + +func (c *ControllerV1) Delete(ctx context.Context, req *v1.DeleteReq) (res *v1.DeleteRes, err error) { + fromCtx := g.RequestFromCtx(ctx) + operatorId := fromCtx.GetCtxVar("id").Int64() + operatorRole := fromCtx.GetCtxVar("role").String() + out, err := service.Reward().Delete(ctx, &model.RewardDeleteIn{Id: req.Id, OperatorId: operatorId, OperatorRole: operatorRole}) + if err != nil { + return nil, err + } + return &v1.DeleteRes{Success: out.Success}, nil +} diff --git a/internal/controller/reward/reward_v1_list.go b/internal/controller/reward/reward_v1_list.go new file mode 100644 index 0000000..142cf11 --- /dev/null +++ b/internal/controller/reward/reward_v1_list.go @@ -0,0 +1,24 @@ +package reward + +import ( + "context" + "github.com/gogf/gf/v2/frame/g" + "server/internal/model" + "server/internal/service" + + "server/api/reward/v1" +) + +func (c *ControllerV1) List(ctx context.Context, req *v1.ListReq) (res *v1.ListRes, err error) { + fromCtx := g.RequestFromCtx(ctx) + operatorId := fromCtx.GetCtxVar("id").Int64() + operatorRole := fromCtx.GetCtxVar("role").String() + out, err := service.Reward().List(ctx, &model.RewardListIn{Page: req.Page, Size: req.Size, OperatorId: operatorId, OperatorRole: operatorRole, StoreId: req.StoreId}) + if err != nil { + return nil, err + } + return &v1.ListRes{ + List: out.List, + Total: out.Total, + }, nil +} diff --git a/internal/controller/reward/reward_v1_update.go b/internal/controller/reward/reward_v1_update.go new file mode 100644 index 0000000..95fee2b --- /dev/null +++ b/internal/controller/reward/reward_v1_update.go @@ -0,0 +1,30 @@ +package reward + +import ( + "context" + "github.com/gogf/gf/v2/frame/g" + "server/internal/model" + "server/internal/service" + + "server/api/reward/v1" +) + +func (c *ControllerV1) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) { + fromCtx := g.RequestFromCtx(ctx) + operatorId := fromCtx.GetCtxVar("id").Int64() + operatorRole := fromCtx.GetCtxVar("role").String() + out, err := service.Reward().Update(ctx, &model.RewardUpdateIn{ + Id: req.Id, + Name: req.Name, + Description: req.Description, + Value: req.Value, + OperatorId: operatorId, + OperatorRole: operatorRole, + StoreId: req.StoreId, + Status: req.Status, + }) + if err != nil { + return nil, err + } + return &v1.UpdateRes{Success: out.Success}, nil +} diff --git a/internal/dao/internal/reward_types.go b/internal/dao/internal/reward_types.go index d90b693..9d2a944 100644 --- a/internal/dao/internal/reward_types.go +++ b/internal/dao/internal/reward_types.go @@ -25,7 +25,7 @@ type RewardTypesColumns struct { Description string // 奖励类型描述 Source string // 来源:1=系统默认,2=门店自定义 StoreId string // 门店ID,系统默认类型为NULL - Status string // 状态:1=正常,0=禁用 + Status string // 状态:1=正常,2=禁用 CreatedAt string // 创建时间 UpdatedAt string // 更新时间 DeletedAt string // 软删除时间戳 diff --git a/internal/dao/internal/rewards.go b/internal/dao/internal/rewards.go index 3cbe55f..797b726 100644 --- a/internal/dao/internal/rewards.go +++ b/internal/dao/internal/rewards.go @@ -27,7 +27,7 @@ type RewardsColumns struct { Source string // 来源:1=系统内置,2=门店自定义 StoreId string // 门店ID,系统内置奖励为NULL Value string // 奖励值(如积分数额、优惠金额) - Status string // 状态:1=正常,0=禁用 + Status string // 状态:1=正常,2=禁用 CreatedAt string // 创建时间 UpdatedAt string // 更新时间 DeletedAt string // 软删除时间戳 diff --git a/internal/dao/internal/user_tasks.go b/internal/dao/internal/user_tasks.go index a3ec699..095425b 100644 --- a/internal/dao/internal/user_tasks.go +++ b/internal/dao/internal/user_tasks.go @@ -23,7 +23,7 @@ type UserTasksColumns struct { Id string // 用户任务唯一标识符 UserId string // 用户ID TaskId string // 任务ID - Status string // 任务状态:1=已领取,2=进行中,3=已完成,4=已取消 + Status string // 任务状态:1=进行中,2=已完成中,3=未完成 SerialNumber string // 流水号,确保用户任务唯一性 CreatedAt string // 创建时间 UpdatedAt string // 更新时间 diff --git a/internal/logic/reward/reward.go b/internal/logic/reward/reward.go index 7ec94a6..7d605b6 100644 --- a/internal/logic/reward/reward.go +++ b/internal/logic/reward/reward.go @@ -2,12 +2,16 @@ package reward import ( "context" + "fmt" + "server/internal/consts" + "server/internal/dao" "server/internal/model" + "server/internal/model/do" "server/internal/service" + "server/utility/ecode" ) -type sReward struct { -} +type sReward struct{} func init() { service.RegisterReward(New()) @@ -17,7 +21,297 @@ func New() service.IReward { return &sReward{} } -func (s *sReward) List(ctx context.Context, in *model.RewardListIn) (out *model.RewardListOut, err error) { - return +// 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("无门店权限") + } + } + + // 创建奖励 + id, err := dao.Rewards.Ctx(ctx).Data(do.Rewards{ + RewardTypeId: in.RewardTypeId, + Name: in.Name, + Description: in.Description, + Source: in.Source, + StoreId: in.StoreId, + Value: in.Value, + Status: in.Status, + }).InsertAndGetId() + if err != nil { + return nil, err + } + + return &model.RewardCreateOut{Id: id}, nil +} + +// Update 更新奖励 +// 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().Source, 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 data[dao.Rewards.Columns().Source].Int() == 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, + Description: in.Description, + Value: in.Value, + Status: in.Status, + }).OmitEmptyData().Update() + if err != nil { + return nil, ecode.Fail.Sub("更新奖励失败") + } + + 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", "source", "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 data["source"].Int() == 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) { + var list []model.Reward + orm := dao.Rewards.Ctx(ctx) + + // 根据角色和权限构建查询条件 + switch in.OperatorRole { + case 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() + if err != nil { + return nil, ecode.Fail.Sub("检查操作者权限出现异常") + } + if !exist { + return nil, ecode.Params.Sub("无门店权限") + } + orm = orm.Where( + fmt.Sprintf("%s.%s = ?", dao.Rewards.Table(), dao.Rewards.Columns().Source), + 1, + ).WhereOr( + fmt.Sprintf("%s.%s = ?", dao.Rewards.Table(), dao.Rewards.Columns().StoreId), + in.StoreId, + ) + + case consts.StoreRoleCode: + // 检查门店是否有权限 + 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("无门店权限") + } + orm = orm.Where( + fmt.Sprintf("%s.%s = ?", dao.Rewards.Table(), dao.Rewards.Columns().Source), + 1, + ).WhereOr( + fmt.Sprintf("%s.%s = ?", dao.Rewards.Table(), dao.Rewards.Columns().StoreId), + in.StoreId, + ) + } + + if in.Status != 0 { + orm = orm.Where(do.Rewards{Status: in.Status}) + } + if in.StoreId != 0 { + orm = orm.Where(do.Rewards{StoreId: in.StoreId}) + } + if in.RewardTypeId != 0 { + orm = orm.Where(do.Rewards{RewardTypeId: in.RewardTypeId}) + } + if in.Name != "" { + orm = orm.WhereLike(dao.Rewards.Columns().Name, "%"+in.Name+"%") + } + + total, err := orm.Count() + if err != nil { + return nil, err + } + err = orm.Page(in.Page, in.Size).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.%s %s", dao.Rewards.Table(), dao.RewardTypes.Table(), dao.RewardTypes.Columns().Name, "reward_type_name")).Scan(&list) + if err != nil { + return nil, err + } + return &model.RewardListOut{ + List: list, + Total: total, + }, nil } diff --git a/internal/logic/rewardType/rewardType.go b/internal/logic/rewardType/rewardType.go index 5e9d975..196f826 100644 --- a/internal/logic/rewardType/rewardType.go +++ b/internal/logic/rewardType/rewardType.go @@ -3,6 +3,7 @@ package reward import ( "context" "fmt" + "github.com/gogf/gf/v2/frame/g" "server/internal/consts" "server/internal/dao" "server/internal/model" @@ -89,7 +90,6 @@ func (s *sRewardType) Create(ctx context.Context, in *model.RewardTypeCreateIn) }, nil } -// Update 更新奖励类型 // Update 更新奖励类型 func (s *sRewardType) Update(ctx context.Context, in *model.RewardTypeUpdateIn) (out *model.RewardTypeUpdateOut, err error) { // 查询原始记录,确保存在,并获取 store_id 和 source 字段用于权限判断 @@ -257,15 +257,27 @@ func (s *sRewardType) List(ctx context.Context, in *model.RewardTypeListIn) (out 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() - + ).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("无门店权限") } - case consts.StoreRoleCode: // 门店 + + // 追加限制:source = 1 或 store_id = 当前门店 + orm = orm.Where( + fmt.Sprintf("%s.%s = ?", dao.RewardTypes.Table(), dao.RewardTypes.Columns().Source), + 1, + ).WhereOr( + fmt.Sprintf("%s.%s IN (?)", dao.RewardTypes.Table(), dao.RewardTypes.Columns().StoreId), + g.Slice{in.StoreId}, + ) + + case consts.StoreRoleCode: // 检查门店是否有权限 exist, err := dao.StoreAdmins.Ctx(ctx). Where(do.StoreAdmins{Id: in.OperatorId}). @@ -285,21 +297,41 @@ func (s *sRewardType) List(ctx context.Context, in *model.RewardTypeListIn) (out if !exist { return nil, ecode.Params.Sub("无门店权限") } + + // 追加限制:source = 1 或 store_id = 当前门店 + orm = orm.Where( + fmt.Sprintf("%s.%s = ?", dao.RewardTypes.Table(), dao.RewardTypes.Columns().Source), + 1, + ).WhereOr( + fmt.Sprintf("%s.%s IN (?)", dao.RewardTypes.Table(), dao.RewardTypes.Columns().StoreId), + g.Slice{in.StoreId}, + ) } + + // 其他筛选 if in.Status != 0 { - orm = orm.Where(do.RewardTypes{Status: in.Status}) + orm = orm.Where( + fmt.Sprintf("%s.%s = ?", dao.RewardTypes.Table(), dao.RewardTypes.Columns().Status), + in.Status, + ) } if in.Name != "" { - orm = orm.WhereLike(dao.RewardTypes.Columns().Name, "%"+in.Name+"%") + orm = orm.WhereLike( + fmt.Sprintf("%s.%s", dao.RewardTypes.Table(), dao.RewardTypes.Columns().Name), + "%"+in.Name+"%", + ) } + // 查询总数 count, err := orm.Count() if err != nil { return nil, err } - // 查询结果 - err = orm.Page(in.Page, in.Size).OrderAsc(dao.RewardTypes.Columns().Source).Scan(&list) + // 查询分页数据 + err = orm.Page(in.Page, in.Size). + OrderAsc(fmt.Sprintf("%s.%s", dao.RewardTypes.Table(), dao.RewardTypes.Columns().Source)). + Scan(&list) if err != nil { return nil, err } diff --git a/internal/model/do/reward_types.go b/internal/model/do/reward_types.go index d7dea96..e65bfc0 100644 --- a/internal/model/do/reward_types.go +++ b/internal/model/do/reward_types.go @@ -17,7 +17,7 @@ type RewardTypes struct { Description interface{} // 奖励类型描述 Source interface{} // 来源:1=系统默认,2=门店自定义 StoreId interface{} // 门店ID,系统默认类型为NULL - Status interface{} // 状态:1=正常,0=禁用 + Status interface{} // 状态:1=正常,2=禁用 CreatedAt *gtime.Time // 创建时间 UpdatedAt *gtime.Time // 更新时间 DeletedAt *gtime.Time // 软删除时间戳 diff --git a/internal/model/do/rewards.go b/internal/model/do/rewards.go index a2250c2..2c1ac2c 100644 --- a/internal/model/do/rewards.go +++ b/internal/model/do/rewards.go @@ -19,7 +19,7 @@ type Rewards struct { Source interface{} // 来源:1=系统内置,2=门店自定义 StoreId interface{} // 门店ID,系统内置奖励为NULL Value interface{} // 奖励值(如积分数额、优惠金额) - Status interface{} // 状态:1=正常,0=禁用 + Status interface{} // 状态:1=正常,2=禁用 CreatedAt *gtime.Time // 创建时间 UpdatedAt *gtime.Time // 更新时间 DeletedAt *gtime.Time // 软删除时间戳 diff --git a/internal/model/do/user_tasks.go b/internal/model/do/user_tasks.go index 3c9a229..4967147 100644 --- a/internal/model/do/user_tasks.go +++ b/internal/model/do/user_tasks.go @@ -15,7 +15,7 @@ type UserTasks struct { Id interface{} // 用户任务唯一标识符 UserId interface{} // 用户ID TaskId interface{} // 任务ID - Status interface{} // 任务状态:1=已领取,2=进行中,3=已完成,4=已取消 + Status interface{} // 任务状态:1=进行中,2=已完成中,3=未完成 SerialNumber interface{} // 流水号,确保用户任务唯一性 CreatedAt *gtime.Time // 创建时间 UpdatedAt *gtime.Time // 更新时间 diff --git a/internal/model/entity/reward_types.go b/internal/model/entity/reward_types.go index 1422c56..54960f8 100644 --- a/internal/model/entity/reward_types.go +++ b/internal/model/entity/reward_types.go @@ -15,7 +15,7 @@ type RewardTypes struct { Description string `json:"description" orm:"description" description:"奖励类型描述"` // 奖励类型描述 Source int `json:"source" orm:"source" description:"来源:1=系统默认,2=门店自定义"` // 来源:1=系统默认,2=门店自定义 StoreId int64 `json:"storeId" orm:"store_id" description:"门店ID,系统默认类型为NULL"` // 门店ID,系统默认类型为NULL - Status int `json:"status" orm:"status" description:"状态:1=正常,0=禁用"` // 状态:1=正常,0=禁用 + Status int `json:"status" orm:"status" description:"状态:1=正常,2=禁用"` // 状态:1=正常,2=禁用 CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 diff --git a/internal/model/entity/rewards.go b/internal/model/entity/rewards.go index f0897ea..fb52c8a 100644 --- a/internal/model/entity/rewards.go +++ b/internal/model/entity/rewards.go @@ -16,8 +16,8 @@ type Rewards struct { Description string `json:"description" orm:"description" description:"奖励描述"` // 奖励描述 Source int `json:"source" orm:"source" description:"来源:1=系统内置,2=门店自定义"` // 来源:1=系统内置,2=门店自定义 StoreId int64 `json:"storeId" orm:"store_id" description:"门店ID,系统内置奖励为NULL"` // 门店ID,系统内置奖励为NULL - Value float64 `json:"value" orm:"value" description:"奖励值(如积分数额、优惠金额)"` // 奖励值(如积分数额、优惠金额) - Status int `json:"status" orm:"status" description:"状态:1=正常,0=禁用"` // 状态:1=正常,0=禁用 + Value uint64 `json:"value" orm:"value" description:"奖励值(如积分数额、优惠金额)"` // 奖励值(如积分数额、优惠金额) + Status int `json:"status" orm:"status" description:"状态:1=正常,2=禁用"` // 状态:1=正常,2=禁用 CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 diff --git a/internal/model/entity/user_tasks.go b/internal/model/entity/user_tasks.go index 8173ea6..f6fd34e 100644 --- a/internal/model/entity/user_tasks.go +++ b/internal/model/entity/user_tasks.go @@ -10,14 +10,14 @@ import ( // UserTasks is the golang structure for table user_tasks. type UserTasks struct { - Id int64 `json:"id" orm:"id" description:"用户任务唯一标识符"` // 用户任务唯一标识符 - UserId int64 `json:"userId" orm:"user_id" description:"用户ID"` // 用户ID - TaskId int64 `json:"taskId" orm:"task_id" description:"任务ID"` // 任务ID - Status int `json:"status" orm:"status" description:"任务状态:1=已领取,2=进行中,3=已完成,4=已取消"` // 任务状态:1=已领取,2=进行中,3=已完成,4=已取消 - SerialNumber string `json:"serialNumber" orm:"serial_number" description:"流水号,确保用户任务唯一性"` // 流水号,确保用户任务唯一性 - CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 - UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 - CompletedAt *gtime.Time `json:"completedAt" orm:"completed_at" description:"任务完成时间"` // 任务完成时间 - DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 - StoreId int64 `json:"storeId" orm:"store_id" description:"门店 id"` // 门店 id + Id int64 `json:"id" orm:"id" description:"用户任务唯一标识符"` // 用户任务唯一标识符 + UserId int64 `json:"userId" orm:"user_id" description:"用户ID"` // 用户ID + TaskId int64 `json:"taskId" orm:"task_id" description:"任务ID"` // 任务ID + Status int `json:"status" orm:"status" description:"任务状态:1=进行中,2=已完成中,3=未完成"` // 任务状态:1=进行中,2=已完成中,3=未完成 + SerialNumber string `json:"serialNumber" orm:"serial_number" description:"流水号,确保用户任务唯一性"` // 流水号,确保用户任务唯一性 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 + CompletedAt *gtime.Time `json:"completedAt" orm:"completed_at" description:"任务完成时间"` // 任务完成时间 + DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间戳"` // 软删除时间戳 + StoreId int64 `json:"storeId" orm:"store_id" description:"门店 id"` // 门店 id } diff --git a/internal/model/reward.go b/internal/model/reward.go index 53025ab..0b0a889 100644 --- a/internal/model/reward.go +++ b/internal/model/reward.go @@ -1,10 +1,87 @@ package model +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// Reward 奖励表 type Reward struct { + Id int64 `json:"id" dc:"奖励ID" orm:"id,primary"` + RewardTypeId int64 `json:"rewardTypeId" dc:"奖励类型ID" orm:"reward_type_id"` + RewardTypeName string `json:"rewardTypeName" dc:"奖励类型名称" orm:"reward_type_name"` + Name string `json:"name" dc:"奖励名称(如100积分、5元优惠券)" orm:"name"` + Description string `json:"description" dc:"奖励描述" orm:"description"` + Source int `json:"source" dc:"来源:1=系统内置,2=门店自定义" orm:"source"` + StoreId int64 `json:"storeId" dc:"门店ID,系统内置奖励为NULL" orm:"store_id"` + Value int64 `json:"value" dc:"奖励值(如积分数额、优惠金额)" orm:"value"` + Status int `json:"status" dc:"状态:1=正常,0=禁用" orm:"status"` + CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间" orm:"created_at"` + UpdatedAt *gtime.Time `json:"updatedAt" dc:"更新时间" orm:"updated_at"` + DeletedAt *gtime.Time `json:"deletedAt" dc:"软删除时间戳" orm:"deleted_at"` } -type RewardListIn struct { +// RewardCreateIn 创建奖励入参 +type RewardCreateIn struct { + OperatorId int64 + OperatorRole string + RewardTypeId int64 + Name string + Description string + Source int + StoreId int64 + Value int64 + Status int } + +// RewardCreateOut 创建奖励出参 +type RewardCreateOut struct { + Id int64 +} + +// RewardUpdateIn 更新奖励入参 +type RewardUpdateIn struct { + OperatorId int64 + OperatorRole string + Id int64 + RewardTypeId int64 + Name string + Description string + StoreId int64 + Value int64 + Status int +} + +// RewardUpdateOut 更新奖励出参 +type RewardUpdateOut struct { + Success bool +} + +// RewardDeleteIn 删除奖励入参 +type RewardDeleteIn struct { + Id int64 + OperatorId int64 + OperatorRole string +} + +// RewardDeleteOut 删除奖励出参 +type RewardDeleteOut struct { + Success bool +} + +// RewardListIn 奖励列表查询入参 +type RewardListIn struct { + OperatorId int64 + OperatorRole string + Page int + Size int + Name string + StoreId int64 + RewardTypeId int64 + Status int + Source int +} + +// RewardListOut 奖励列表查询出参 type RewardListOut struct { List []Reward Total int diff --git a/internal/service/reward.go b/internal/service/reward.go index 8e1f233..d73dc96 100644 --- a/internal/service/reward.go +++ b/internal/service/reward.go @@ -12,6 +12,14 @@ import ( type ( IReward interface { + // Create 创建奖励 + Create(ctx context.Context, in *model.RewardCreateIn) (out *model.RewardCreateOut, err error) + // Update 更新奖励 + // Update 更新奖励 + Update(ctx context.Context, in *model.RewardUpdateIn) (out *model.RewardUpdateOut, err error) + // Delete 删除奖励 + Delete(ctx context.Context, in *model.RewardDeleteIn) (out *model.RewardDeleteOut, err error) + // List 奖励列表 List(ctx context.Context, in *model.RewardListIn) (out *model.RewardListOut, err error) } ) diff --git a/utility/myCasbin/casbin.go b/utility/myCasbin/casbin.go index 0bb93cf..7177977 100644 --- a/utility/myCasbin/casbin.go +++ b/utility/myCasbin/casbin.go @@ -88,7 +88,10 @@ func init() { enforcer.AddPolicy("store", "/x/rewardType", "PUT", "更新奖励类型") enforcer.AddPolicy("store", "/x/rewardType/*", "DELETE", "删除奖励类型") - enforcer.AddPolicy("store", "/x/reward/store", "GET", "获取门店奖励列表") + enforcer.AddPolicy("store", "/x/reward", "GET", "获取奖励列表") + enforcer.AddPolicy("store", "/x/reward", "POST", "添加奖励") + enforcer.AddPolicy("store", "/x/reward", "PUT", "更新奖励") + enforcer.AddPolicy("store", "/x/reward/*", "DELETE", "删除奖励") // 门店角色 enforcer.AddPolicy("store", "/x/store/role", "GET", "获取门店角色列表") @@ -128,15 +131,9 @@ func init() { enforcer.AddPolicy("admin", "/x/merchant", "GET", "管理员获取商户列表") enforcer.AddPolicy("admin", "/x/merchant/audit", "POST", "管理员审核商户申请") - // 奖励 - enforcer.AddPolicy("admin", "/x/reward/system", "POST", "管理员创建系统奖励") - enforcer.AddPolicy("admin", "/x/reward/system", "GET", "管理员获取系统奖励列表") - enforcer.AddPolicy("admin", "/x/reward/system/*", "DELETE", "管理员删除系统单个奖励") - enforcer.AddPolicy("admin", "/x/reward/system", "PUT", "管理员修改单个系统奖励") - - enforcer.AddPolicy("admin", "/x/game", "POST", "管理员创建门店奖励") - enforcer.AddPolicy("admin", "/x/game/*", "DELETE", "管理员删除门店单个奖励") - enforcer.AddPolicy("admin", "/x/game", "PUT", "管理员修改单个门店奖励") + enforcer.AddPolicy("admin", "/x/game", "POST", "管理员添加游戏") + enforcer.AddPolicy("admin", "/x/game/*", "DELETE", "管理员删除游戏") + enforcer.AddPolicy("admin", "/x/game", "PUT", "管理员更新游戏") // 任务 enforcer.AddPolicy("admin", "/x/task/selector", "GET", "管理员获取任务列表二级选择器")