Files
arenax-server/internal/logic/reward/reward.go

414 lines
13 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"
"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
}