package reward import ( "context" "fmt" "github.com/gogf/gf/v2/os/gtime" "server/internal/consts" "server/internal/dao" "server/internal/model" "server/internal/model/do" "server/internal/service" "server/utility/ecode" "github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/errors/gerror" ) type sReward struct{} func New() service.IReward { return &sReward{} } func init() { service.RegisterReward(New()) } // CreateSystemReward 创建系统奖励 func (s *sReward) CreateSystemReward(ctx context.Context, in *model.RewardCreateIn) (out *model.CreateOut, err error) { if in.Name == "" { return nil, gerror.New("奖励名称不能为空") } 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("奖励类型不存在") } // TODO 生成奖励唯一 code // 插入数据 id, err := dao.Rewards.Ctx(ctx).Data(do.Rewards{ RewardTypeId: in.RewardTypeID, RewardScope: consts.SystemReward, // 系统奖励 Name: in.Name, Code: "xmax", Description: in.Description, Status: in.Status, Stock: in.Stock, StartAt: in.StartAt, ExpireAt: in.ExpireAt, }).OmitEmptyData().InsertAndGetId() if err != nil { return nil, ecode.Fail.Sub("创建奖励失败") } return &model.CreateOut{ Id: id, }, nil } // CreateStoreReward 创建门店奖励 func (s *sReward) CreateStoreReward(ctx context.Context, in *model.RewardCreateIn) (out *model.CreateOut, err error) { if in.OperatorRole != consts.MerchantRoleCode && in.OperatorRole != consts.StoreRoleCode { return nil, ecode.Params.Sub("只有管理员和商户才能创建门店奖励") } // 验证 OperatorId 对 门店 id 是否存在权限 if in.OperatorRole == consts.MerchantRoleCode { count, 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), ).Where(dao.Stores.Columns().Id, in.StoreIDs).WherePri(in.OperatorId).Count() if err != nil { return nil, gerror.Wrap(err, "检查商户权限失败") } if count != len(in.StoreIDs) { return nil, ecode.Params.Sub("商户权限不足") } } else { count, err := dao.StoreAdmins.Ctx(ctx). LeftJoin( dao.Stores.Table(), fmt.Sprintf("%s.%s=%s.%s", dao.Stores.Table(), dao.Stores.Columns().Id, dao.StoreAdmins.Table(), dao.StoreAdmins.Columns().StoreId), ).WherePri(in.OperatorId).WhereIn(dao.Stores.Columns().Id, in.StoreIDs).Count() if err != nil { return nil, gerror.Wrap(err, "检查门店权限失败") } if count != len(in.StoreIDs) { return nil, ecode.Params.Sub("门店权限不足") } } if in.Name == "" { return nil, gerror.New("奖励名称不能为空") } 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("奖励类型不存在") } if err = dao.Rewards.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { // TODO 生成奖励唯一 code // 首先插入奖励 id, err := dao.Rewards.Ctx(ctx).Data(do.Rewards{ RewardTypeId: in.RewardTypeID, RewardScope: consts.StoreReward, // 门店奖励 Name: in.Name, Code: "", Description: in.Description, Status: in.Status, Stock: in.Stock, StartAt: in.StartAt, ExpireAt: in.ExpireAt, }).OmitEmptyData().InsertAndGetId() // 忽略空值插入 if err != nil { return ecode.Fail.Sub("创建门店奖励失败") } insertDatas := make([]do.StoreRewards, 0, len(in.StoreIDs)) // 插入门店奖励关系表 for _, d := range in.StoreIDs { insertDatas = append(insertDatas, do.StoreRewards{ RewardId: id, StoreId: d, }) } if _, err := dao.StoreRewards.Ctx(ctx).Data(insertDatas).Insert(); err != nil { return ecode.Fail.Sub("创建门店奖励关联失败") } return nil }); err != nil { return nil, err } return } // ListSystemReward 查询系统奖励列表 func (s *sReward) ListSystemReward(ctx context.Context, in *model.RewardListIn) (out *model.RewardListOut, err error) { m := dao.Rewards.Ctx(ctx) // 构建查询条件 if in.Name != "" { m = m.WhereLike(dao.Rewards.Columns().Name, "%"+in.Name+"%") } if in.RewardTypeID != 0 { m = m.Where(do.Rewards{RewardTypeId: in.RewardTypeID}) } list := make([]model.Reward, 0) var total int err = m.Page(in.Page, in.Size).Where(do.Rewards{RewardScope: 1, Status: in.Status}).OrderDesc(dao.Rewards.Columns().CreatedAt).OrderDesc(dao.Rewards.Columns().Id).ScanAndCount(&list, &total, false) if err != nil { return nil, ecode.Fail.Sub("查询系统奖励失败") } return &model.RewardListOut{ List: list, Total: total, }, nil } // ListStoreReward 查询门店奖励列表 func (s *sReward) ListStoreReward(ctx context.Context, in *model.RewardListIn) (out *model.RewardListOut, err error) { // 商户可以查询下属门店的所有商品信息,商户只能查询自己的门店商品信息 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 更新系统奖励 func (s *sReward) UpdateSystemReward(ctx context.Context, in *model.RewardUpdateIn) (out *model.UpdateOut, err error) { exist, err := dao.Rewards.Ctx(ctx).Where(do.Rewards{Id: in.ID}).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, RewardScope: 1}).Update(do.Rewards{ RewardTypeId: in.RewardTypeID, Name: in.Name, Description: in.Description, Status: in.Status, Stock: in.Stock, StartAt: in.StartAt, ExpireAt: in.ExpireAt, }) if err != nil { return nil, ecode.Fail.Sub("更新奖励失败") } return &model.UpdateOut{Success: true}, nil } // UpdateStoreReward 更新门店奖励 func (s *sReward) UpdateStoreReward(ctx context.Context, in *model.RewardUpdateIn) (out *model.UpdateOut, err error) { 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 删除系统奖励 func (s *sReward) DeleteSystemReward(ctx context.Context, in *model.RewardDeleteIn) (out *model.DeleteOut, err error) { exist, err := dao.Rewards.Ctx(ctx).Where(do.Rewards{Id: in.ID}).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.DeleteOut{Success: true}, nil } // DeleteStoreReward 删除门店奖励 func (s *sReward) DeleteStoreReward(ctx context.Context, in *model.RewardDeleteIn) (out *model.DeleteOut, err error) { // 验证操作者角色 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) { return }