222 lines
6.3 KiB
Go
222 lines
6.3 KiB
Go
package service
|
||
|
||
import (
|
||
"cid/dao"
|
||
"cid/model/dto"
|
||
"cid/model/entity"
|
||
"context"
|
||
"encoding/json"
|
||
"strconv"
|
||
|
||
"github.com/gogf/gf/v2/errors/gerror"
|
||
"github.com/gogf/gf/v2/frame/g"
|
||
)
|
||
|
||
var (
|
||
Strategy = strategyService{}
|
||
)
|
||
|
||
type strategyService struct{}
|
||
|
||
// CreateStrategy 创建策略
|
||
func (s *strategyService) CreateStrategy(ctx context.Context, req *dto.CreateStrategyReq) (id int64, err error) {
|
||
// 检查策略名称是否已存在
|
||
existingStrategy, err := dao.Strategy.GetByName(ctx, req.Name)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
if existingStrategy != nil {
|
||
return 0, gerror.New("策略名称已存在")
|
||
}
|
||
|
||
// 验证转化率范围
|
||
if req.MaxConversion <= req.MinConversion {
|
||
return 0, gerror.New("最高转化率必须大于最低转化率")
|
||
}
|
||
|
||
// 序列化权重配置
|
||
weightsJson, err := json.Marshal(req.SourceWeights)
|
||
if err != nil {
|
||
return 0, gerror.Wrap(err, "权重配置序列化失败")
|
||
}
|
||
|
||
strategy := &entity.Strategy{
|
||
Name: req.Name,
|
||
Description: req.Description,
|
||
MinConversion: req.MinConversion,
|
||
MaxConversion: req.MaxConversion,
|
||
SourceWeights: string(weightsJson),
|
||
MaxAdsPerReq: req.MaxAdsPerReq,
|
||
Priority: req.Priority,
|
||
Status: req.Status,
|
||
}
|
||
|
||
_, err = dao.Strategy.Create(ctx, strategy)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
|
||
// MongoDB使用ObjectId,创建成功后返回成功状态
|
||
return 1, nil
|
||
}
|
||
|
||
// UpdateStrategy 更新策略
|
||
func (s *strategyService) UpdateStrategy(ctx context.Context, req *dto.UpdateStrategyReq) (affected int64, err error) {
|
||
// 检查策略是否存在
|
||
existingStrategy, err := dao.Strategy.GetByID(ctx, strconv.FormatInt(req.Id, 10))
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
if existingStrategy == nil {
|
||
return 0, gerror.New("策略不存在")
|
||
}
|
||
|
||
// 如果更新名称,检查是否与其他策略冲突
|
||
if req.Name != "" && req.Name != existingStrategy.Name {
|
||
conflictStrategy, err := dao.Strategy.GetByName(ctx, req.Name)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
if conflictStrategy != nil {
|
||
return 0, gerror.New("策略名称已存在")
|
||
}
|
||
}
|
||
|
||
// 验证转化率范围
|
||
if req.MaxConversion <= req.MinConversion {
|
||
return 0, gerror.New("最高转化率必须大于最低转化率")
|
||
}
|
||
|
||
// 序列化权重配置
|
||
weightsJson, err := json.Marshal(req.SourceWeights)
|
||
if err != nil {
|
||
return 0, gerror.Wrap(err, "权重配置序列化失败")
|
||
}
|
||
|
||
strategy := &entity.Strategy{
|
||
Name: req.Name,
|
||
Description: req.Description,
|
||
MinConversion: req.MinConversion,
|
||
MaxConversion: req.MaxConversion,
|
||
SourceWeights: string(weightsJson),
|
||
MaxAdsPerReq: req.MaxAdsPerReq,
|
||
Priority: req.Priority,
|
||
Status: req.Status,
|
||
}
|
||
|
||
return dao.Strategy.Update(ctx, strategy)
|
||
}
|
||
|
||
// DeleteStrategy 删除策略
|
||
func (s *strategyService) DeleteStrategy(ctx context.Context, id int64) (affected int64, err error) {
|
||
// 检查策略是否存在
|
||
existingStrategy, err := dao.Strategy.GetByID(ctx, strconv.FormatInt(id, 10))
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
if existingStrategy == nil {
|
||
return 0, gerror.New("策略不存在")
|
||
}
|
||
|
||
return dao.Strategy.Delete(ctx, strconv.FormatInt(id, 10))
|
||
}
|
||
|
||
// GetStrategyByID 根据ID获取策略
|
||
func (s *strategyService) GetStrategyByID(ctx context.Context, id int64) (strategy *dto.StrategyRes, err error) {
|
||
entity, err := dao.Strategy.GetByID(ctx, strconv.FormatInt(id, 10))
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if entity == nil {
|
||
return nil, gerror.New("策略不存在")
|
||
}
|
||
|
||
// 反序列化权重配置
|
||
var weights map[string]int
|
||
if entity.SourceWeights != "" {
|
||
err = json.Unmarshal([]byte(entity.SourceWeights), &weights)
|
||
if err != nil {
|
||
return nil, gerror.Wrap(err, "权重配置反序列化失败")
|
||
}
|
||
}
|
||
|
||
// 将ObjectId的十六进制字符串转换为int64,如果失败则使用0
|
||
var idInt64 int64
|
||
if id, err := strconv.ParseInt(entity.Id.Hex(), 16, 64); err == nil {
|
||
idInt64 = id
|
||
}
|
||
|
||
return &dto.StrategyRes{
|
||
Id: idInt64,
|
||
Name: entity.Name,
|
||
Description: entity.Description,
|
||
TenantLevel: "", // Strategy实体中没有TenantLevel字段,暂时设为空字符串
|
||
MinConversion: entity.MinConversion,
|
||
MaxConversion: entity.MaxConversion,
|
||
SourceWeights: weights,
|
||
MaxAdsPerReq: entity.MaxAdsPerReq,
|
||
Priority: entity.Priority,
|
||
Status: entity.Status,
|
||
CreatedAt: entity.CreatedAt.String(),
|
||
UpdatedAt: entity.UpdatedAt.String(),
|
||
CreatedBy: 0, // 这些字段在MongoBaseDO中不存在,暂时设为0
|
||
UpdatedBy: 0,
|
||
}, nil
|
||
}
|
||
|
||
// GetStrategyList 获取策略列表
|
||
func (s *strategyService) GetStrategyList(ctx context.Context, req *dto.GetStrategyListReq) (res *dto.GetStrategyListRes, err error) {
|
||
list, total, err := dao.Strategy.GetList(ctx, req.Page, req.Size, req.TenantLevel, req.Status)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
var strategyList []*dto.StrategyRes
|
||
for _, entity := range list {
|
||
// 反序列化权重配置
|
||
var weights map[string]int
|
||
if entity.SourceWeights != "" {
|
||
err = json.Unmarshal([]byte(entity.SourceWeights), &weights)
|
||
if err != nil {
|
||
g.Log().Warningf(ctx, "策略 %d 权重配置反序列化失败: %v", entity.Id, err)
|
||
weights = make(map[string]int)
|
||
}
|
||
}
|
||
|
||
// 将ObjectId的十六进制字符串转换为int64,如果失败则使用0
|
||
var idInt64 int64
|
||
if id, err := strconv.ParseInt(entity.Id.Hex(), 16, 64); err == nil {
|
||
idInt64 = id
|
||
}
|
||
|
||
strategyList = append(strategyList, &dto.StrategyRes{
|
||
Id: idInt64,
|
||
Name: entity.Name,
|
||
Description: entity.Description,
|
||
TenantLevel: "", // Strategy实体中没有TenantLevel字段,暂时设为空字符串
|
||
MinConversion: entity.MinConversion,
|
||
MaxConversion: entity.MaxConversion,
|
||
SourceWeights: weights,
|
||
MaxAdsPerReq: entity.MaxAdsPerReq,
|
||
Priority: entity.Priority,
|
||
Status: entity.Status,
|
||
CreatedAt: entity.CreatedAt.String(),
|
||
UpdatedAt: entity.UpdatedAt.String(),
|
||
CreatedBy: 0, // 这些字段在MongoBaseDO中不存在,暂时设为0
|
||
UpdatedBy: 0,
|
||
})
|
||
}
|
||
|
||
return &dto.GetStrategyListRes{
|
||
List: strategyList,
|
||
Total: total,
|
||
Page: req.Page,
|
||
Size: req.Size,
|
||
}, nil
|
||
}
|
||
|
||
// GetStrategyByTenantLevel 根据租户级别获取策略
|
||
func (s *strategyService) GetStrategyByTenantLevel(ctx context.Context, tenantLevel string) (strategy *entity.Strategy, err error) {
|
||
return dao.Strategy.GetByTenantLevel(ctx, tenantLevel)
|
||
}
|