diff --git a/internal/logic/reward/reward.go b/internal/logic/reward/reward.go index 4dfed28..3a35ef1 100644 --- a/internal/logic/reward/reward.go +++ b/internal/logic/reward/reward.go @@ -3,6 +3,7 @@ package reward import ( "context" "fmt" + "github.com/gogf/gf/v2/os/gtime" "server/internal/consts" "server/internal/dao" "server/internal/model" @@ -61,7 +62,7 @@ func (s *sReward) CreateSystemReward(ctx context.Context, in *model.RewardCreate // CreateStoreReward 创建门店奖励 func (s *sReward) CreateStoreReward(ctx context.Context, in *model.RewardCreateIn) (out *model.CreateOut, err error) { - if in.OperatorRole != consts.MerchantRoleCode && in.OperatorRole != consts.AdminRoleCode { + if in.OperatorRole != consts.MerchantRoleCode && in.OperatorRole != consts.StoreRoleCode { return nil, ecode.Params.Sub("只有管理员和商户才能创建门店奖励") } // 验证 OperatorId 对 门店 id 是否存在权限 @@ -143,7 +144,59 @@ func (s *sReward) ListSystemReward(ctx context.Context, in *model.RewardListIn) // ListStoreReward 查询门店奖励列表 func (s *sReward) ListStoreReward(ctx context.Context, in *model.RewardListIn) (out *model.RewardListOut, err error) { - return + // 商户可以查询下属门店的所有商品信息,商户只能查询自己的门店商品信息 + if in.OperatorRole != consts.MerchantRoleCode && in.OperatorRole != consts.StoreRoleCode { + return nil, ecode.Params.Sub("只有管理员和商户才能查询门店奖励") + } + if in.OperatorRole == consts.MerchantRoleCode { + // 获取商户管理员所属商户 id,根据 商户 id 和门店 id 查询记录是否 + exist, err := dao.MerchantAdmins.Ctx(ctx).LeftJoin( + dao.Stores.Table(), + fmt.Sprintf("%s.%s=%s.%s", dao.Stores.Table(), dao.Stores.Columns().MerchantId, dao.MerchantAdmins.Table(), dao.MerchantAdmins.Columns().MerchantId), + ).WherePri(in.StoreID).Exist() + if err != nil { + return nil, gerror.Wrap(err, "检查商户权限失败") + } + if !exist { + return nil, ecode.Params.Sub("商户权限不足") + } + } + + // 构建查询 + query := dao.Rewards.Ctx(ctx).LeftJoin( + dao.StoreRewards.Table(), + fmt.Sprintf("%s.%s=%s.%s", dao.Rewards.Table(), dao.Rewards.Columns().Id, dao.StoreRewards.Table(), dao.StoreRewards.Columns().RewardId), + ).Where(dao.Rewards.Columns().RewardScope, consts.StoreReward) + + // 应用过滤条件 + if in.StoreID != nil && *in.StoreID > 0 { + query = query.Where(dao.StoreRewards.Columns().StoreId, *in.StoreID) + } + if in.RewardTypeID > 0 { + query = query.Where(dao.Rewards.Columns().RewardTypeId, in.RewardTypeID) + } + if in.Name != "" { + query = query.WhereLike(dao.Rewards.Columns().Name, "%"+in.Name+"%") + } + if in.Status > 0 { + query = query.Where(dao.Rewards.Columns().Status, in.Status) + } + if in.RewardScope > 0 { + query = query.Where(dao.Rewards.Columns().RewardScope, in.RewardScope) + } + + // 查询奖励列表 + list := make([]model.Reward, 0) + var total int + err = query.Fields(dao.Rewards.Columns()).Page(in.Page, in.Size).ScanAndCount(&list, &total, false) + if err != nil { + return nil, ecode.Fail.Sub("查询奖励列表失败") + } + + return &model.RewardListOut{ + List: list, + Total: total, + }, nil } // UpdateSystemReward 更新系统奖励 @@ -153,7 +206,91 @@ func (s *sReward) UpdateSystemReward(ctx context.Context, in *model.RewardUpdate // UpdateStoreReward 更新门店奖励 func (s *sReward) UpdateStoreReward(ctx context.Context, in *model.RewardUpdateIn) (out *model.UpdateOut, err error) { - return + if in.OperatorRole != consts.MerchantRoleCode && in.OperatorRole != consts.StoreRoleCode { + return nil, ecode.Params.Sub("只有管理员和商户才能更新门店奖励") + } + // 1. 如果是门店管理员,只需要更新奖励信息即可 + // 2. 如果是商户管理员,更新奖励信息,同时将 StoreIds 中id 不在门店关系表的数据删除 + + // 验证奖励是否存在且为门店奖励 + exist, err := dao.Rewards.Ctx(ctx).Where("id = ? AND reward_scope = ? AND deleted_at IS NULL", in.ID, consts.StoreReward).Exist() + if err != nil { + return nil, ecode.Fail.Sub("检查奖励是否存在失败") + } + if !exist { + return nil, ecode.Params.Sub("门店奖励不存在或已删除") + } + + if in.Name == "" { + return nil, ecode.Params.Sub("奖励名称不能为空") + } + exist, err = dao.RewardTypes.Ctx(ctx).WherePri(in.RewardTypeID).Exist() + if err != nil { + return nil, ecode.Fail.Sub("检查奖励类型失败") + } + if !exist { + return nil, ecode.Params.Sub("奖励类型不存在") + } + + // 使用事务确保数据一致性 + err = dao.Rewards.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { + // 更新 rewards 表 + _, err := tx.Model(dao.Rewards).Data(do.Rewards{ + RewardTypeId: in.RewardTypeID, + Name: in.Name, + Description: in.Description, + Status: in.Status, + Stock: in.Stock, + StartAt: in.StartAt, + ExpireAt: in.ExpireAt, + UpdatedAt: gtime.Now(), + }).Where("id = ?", in.ID).OmitEmptyData().Update() + if err != nil { + return ecode.Fail.Sub("更新奖励信息失败") + } + + // 门店管理员不修改门店关联 + if in.OperatorRole == consts.MerchantRoleCode { + return nil + } + + // 验证 StoreIDs 是否存在 + count, err := dao.Stores.Ctx(ctx).WhereIn("id", in.StoreIDs).Count() + if err != nil { + return ecode.Fail.Sub("检查门店ID失败") + } + if count != len(in.StoreIDs) { + return ecode.Params.Sub("存在无效的门店ID") + } + + // 删除旧的门店关联 + _, err = tx.Model(dao.StoreRewards).Where(do.StoreRewards{RewardId: in.ID}).Delete() + if err != nil { + return ecode.Fail.Sub("删除旧门店关联失败") + } + + // 插入新的门店关联 + storeRewardData := make([]do.StoreRewards, len(in.StoreIDs)) + for i, storeID := range in.StoreIDs { + storeRewardData[i] = do.StoreRewards{ + StoreId: storeID, + RewardId: in.ID, + } + } + _, err = tx.Model(dao.StoreRewards).Data(storeRewardData).Insert() + if err != nil { + return ecode.Fail.Sub("关联门店失败") + } + + return nil + }) + if err != nil { + return nil, err + } + + return &model.UpdateOut{ + Success: true, + }, nil } // DeleteSystemReward 删除系统奖励 @@ -163,7 +300,55 @@ func (s *sReward) DeleteSystemReward(ctx context.Context, in *model.RewardDelete // DeleteStoreReward 删除门店奖励 func (s *sReward) DeleteStoreReward(ctx context.Context, in *model.RewardDeleteIn) (out *model.DeleteOut, err error) { - return + + // 验证操作者角色 + if in.OperatorRole != consts.MerchantRoleCode && in.OperatorRole != consts.StoreRoleCode { + return nil, ecode.Params.Sub("只有管理员和商户才能删除门店奖励") + } + + // 验证奖励是否存在且为门店奖励 + exist, err := dao.Rewards.Ctx(ctx).WherePri(in.ID).Where(do.Rewards{RewardScope: consts.StoreReward}).Exist() + if err != nil { + return nil, ecode.Fail.Sub("检查奖励是否存在失败") + } + if !exist { + return nil, ecode.Params.Sub("门店奖励不存在或已删除") + } + + storeIds := make([]int64, 0) + if in.OperatorRole == consts.MerchantRoleCode { + array, 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(do.MerchantAdmins{Id: in.OperatorId}).Fields(dao.Stores.Columns().Id).Array() + if err != nil { + return nil, ecode.Fail.Sub("查询商户门店失败") + } + for _, value := range array { + storeIds = append(storeIds, value.Int64()) + } + } else { + value, err := dao.StoreAdmins.Ctx(ctx).LeftJoin().WherePri(in.OperatorId).Fields(dao.StoreRewards.Columns().StoreId).Value() + if err != nil { + return nil, ecode.Fail.Sub("查询门店失败") + } + storeIds = append(storeIds, value.Int64()) + } + if err = dao.Rewards.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { + if _, err := dao.Rewards.Ctx(ctx).WherePri(in.ID).Delete(); err != nil { + return ecode.Fail.Sub("删除奖励失败") + } + if _, err := dao.StoreRewards.Ctx(ctx).Where(do.StoreRewards{RewardId: in.ID}).WhereIn(dao.StoreRewards.Columns().StoreId, storeIds).Delete(); err != nil { + return ecode.Fail.Sub("删除门店奖励关联失败") + } + return nil + }); err != nil { + return nil, err + } + + return &model.DeleteOut{ + Success: true, + }, nil } func (s *sReward) Detail(ctx context.Context, in *model.RewardDetailIn) (out *model.RewardDetailOut, err error) { diff --git a/internal/model/reward.go b/internal/model/reward.go index aabee64..b0aad00 100644 --- a/internal/model/reward.go +++ b/internal/model/reward.go @@ -1,11 +1,13 @@ package model import ( + "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" ) // Reward 奖励信息 type Reward struct { + g.Meta `orm:"table:rewards"` ID int64 `json:"id" orm:"id,primary"` // 奖励ID RewardTypeID int64 `json:"rewardTypeId" orm:"reward_type_id,not null"` // 奖励类型ID RewardScope int `json:"rewardScope" orm:"reward_scope,not null,default:2"` // 奖励范围:1=系统奖励,2=门店奖励 @@ -34,6 +36,8 @@ type RewardCreateIn struct { type RewardUpdateIn struct { ID int64 // 奖励ID + OperatorId int64 // 操作人ID + OperatorRole string // 操作人角色 RewardTypeID int64 // 奖励类型ID RewardScope int // 奖励范围:1=系统奖励,2=门店奖励 Name string // 奖励名称 @@ -46,6 +50,8 @@ type RewardUpdateIn struct { } type RewardListIn struct { + OperatorId int64 // 操作人ID + OperatorRole string // 操作人角色 Page int // 页码 Size int // 每页数量 StoreID *int64 // 门店ID(用于过滤门店可见的奖励) @@ -61,7 +67,9 @@ type RewardListOut struct { } type RewardDeleteIn struct { - ID int64 // 奖励ID + ID int64 // 奖励ID + OperatorId int64 // 操作人ID + OperatorRole string // 操作人角色 } type RewardDetailIn struct {