forked from all_user/stat_center
Initial commit
This commit is contained in:
@@ -0,0 +1,655 @@
|
||||
package agentSer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"stat/api/proto"
|
||||
"stat/common"
|
||||
"stat/common/log"
|
||||
"stat/common/stdLog"
|
||||
"stat/common/utils"
|
||||
"stat/middleware/define"
|
||||
"stat/models/channelmod"
|
||||
"stat/statg"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
func GetChannelInfoWithLockStatus(ctx context.Context, channel string) (*channelmod.ChannelInfo, stdLog.CodeType, error) {
|
||||
channelFilter := bson.M{channelmod.FN.ChannelInfo.Channel: channel}
|
||||
channelInfo, err := channelmod.FindOneChannelInfo(ctx, channelFilter)
|
||||
if err != nil || channelInfo.Channel == "" {
|
||||
return nil, stdLog.AgentAccountNotExists, fmt.Errorf("代理账号 %s 不存在", channel)
|
||||
}
|
||||
if channelInfo.Type.IsChild() {
|
||||
channelMap, _, err := MakeChannelAndRuleMap(ctx, channelInfo)
|
||||
if err != nil {
|
||||
return nil, stdLog.QueryDataError, err
|
||||
}
|
||||
lock, status, showDivide := channelMap.GetLockStatusAndShowDivide(channelInfo)
|
||||
channelInfo.Lock = lock
|
||||
channelInfo.Status = status
|
||||
channelInfo.ChildShowDivideRate = showDivide
|
||||
}
|
||||
return channelInfo, stdLog.Success, nil
|
||||
}
|
||||
|
||||
func CheckToken(ctx context.Context, channel string, token string) error {
|
||||
channelFilter := bson.M{channelmod.FN.ChannelInfo.Channel: channel}
|
||||
channelInfo, err := channelmod.FindOneChannelInfo(ctx, channelFilter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if channelInfo.Channel == "" {
|
||||
return fmt.Errorf("代理账号 %s 不存在", channel)
|
||||
}
|
||||
if channelInfo.Lock || !channelInfo.Status {
|
||||
return fmt.Errorf("代理账号 %s 被禁止", channel)
|
||||
}
|
||||
if channelInfo.Token != token {
|
||||
return fmt.Errorf("登陆信息已过期,请重新登陆")
|
||||
}
|
||||
if time.Since(channelInfo.CheckTokenTime) > 6*time.Hour {
|
||||
doc := bson.M{"$set": bson.M{
|
||||
channelmod.FN.ChannelInfo.CheckTokenTime: time.Now(),
|
||||
}}
|
||||
if err = channelmod.UpdateOneChannelInfo(ctx, bson.M{channelmod.FN.ChannelInfo.Channel: channelInfo.Channel}, doc); err != nil {
|
||||
return err
|
||||
}
|
||||
channelInfoWithLock, _, err := GetChannelInfoWithLockStatus(ctx, channel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if channelInfoWithLock.Lock || !channelInfoWithLock.Status {
|
||||
doc := bson.M{"$set": bson.M{
|
||||
channelmod.FN.ChannelInfo.Token: "", // 清空token
|
||||
}}
|
||||
if err = channelmod.UpdateOneChannelInfo(ctx, bson.M{channelmod.FN.ChannelInfo.Channel: channelInfo.Channel}, doc); err != nil {
|
||||
return err
|
||||
}
|
||||
return fmt.Errorf("本账号的上级代理账号 %s 被禁止", channel)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 代理商账号登陆
|
||||
func AgentLogin(ctx context.Context, ip string, param proto.AgentLoginReq) (code stdLog.CodeType, channelInfo *channelmod.ChannelInfo) {
|
||||
var err error
|
||||
channelInfo, code, err = GetChannelInfoWithLockStatus(ctx, *param.Account)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 禁止登陆
|
||||
if channelInfo.Lock || !channelInfo.Status {
|
||||
code = stdLog.AgentHasLocked
|
||||
return
|
||||
}
|
||||
|
||||
if *param.Password != channelInfo.Password {
|
||||
code = stdLog.AdminPasswordError
|
||||
return
|
||||
}
|
||||
|
||||
if len(param.ImgCode) != 4 {
|
||||
code = stdLog.VerifySmsCodeFailed
|
||||
return
|
||||
}
|
||||
|
||||
imgs := make([]byte, 4)
|
||||
for i := range param.ImgCode {
|
||||
pi, err := strconv.Atoi(string(param.ImgCode[i]))
|
||||
if err != nil {
|
||||
code = stdLog.VerifySmsCodeFailed
|
||||
return
|
||||
}
|
||||
imgs[i] = byte(pi)
|
||||
}
|
||||
|
||||
imgCodeByte := statg.VerifyIMGStore.Get(param.ImgID, true)
|
||||
if bytes.Equal(imgCodeByte, imgs) {
|
||||
channelInfo.ShowMagic += 1
|
||||
doc := bson.M{"$set": bson.M{channelmod.FN.ChannelInfo.ShowMagic: channelInfo.ShowMagic}}
|
||||
if err = channelmod.UpdateOneChannelInfo(ctx, bson.M{}, doc); err != nil {
|
||||
code = stdLog.Failure
|
||||
return code, channelInfo
|
||||
}
|
||||
code = stdLog.VerifySmsCodeFailed
|
||||
return
|
||||
} else if bytes.Equal(imgCodeByte, common.ArrayReverseByte(imgs)) {
|
||||
channelInfo.ShowMagic = 1
|
||||
} else {
|
||||
code = stdLog.VerifySmsCodeFailed
|
||||
return
|
||||
}
|
||||
|
||||
// 生成token
|
||||
claims := define.Claims{
|
||||
Type: define.Channel,
|
||||
Name: *param.Account,
|
||||
ShowMagic: strconv.Itoa(int(channelInfo.ShowMagic)),
|
||||
}
|
||||
//fmt.Println("claims", claims)
|
||||
if channelInfo.ShowMagic >= 3 {
|
||||
statg.Bot.SendMonitorMessage("渠道" + channelInfo.Channel + "风险登陆多次已禁止登陆.")
|
||||
}
|
||||
|
||||
newToken, err := define.GenToken(&claims)
|
||||
if err != nil {
|
||||
log.Error("GenerateUserToken failed", log.E(err))
|
||||
code = stdLog.Failure
|
||||
return code, channelInfo
|
||||
}
|
||||
channelInfo.Token = newToken
|
||||
|
||||
// 刷新token
|
||||
doc := bson.M{"$set": bson.M{
|
||||
channelmod.FN.ChannelInfo.Token: newToken,
|
||||
channelmod.FN.ChannelInfo.ShowMagic: channelInfo.ShowMagic,
|
||||
channelmod.FN.ChannelInfo.IP: ip,
|
||||
}}
|
||||
if err = channelmod.UpdateOneChannelInfo(ctx, bson.M{channelmod.FN.ChannelInfo.Channel: channelInfo.Channel}, doc); err != nil {
|
||||
code = stdLog.Failure
|
||||
return code, channelInfo
|
||||
}
|
||||
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
func AgentChannelAppInfo(ctx context.Context, req proto.ChannelAppInfoReq) (*proto.ChannelAppInfoResp, error) {
|
||||
checkFilter := bson.M{
|
||||
channelmod.FN.ChannelInfo.Channel: req.Channel,
|
||||
}
|
||||
channelInfo, err := channelmod.FindOneChannelInfo(ctx, checkFilter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if channelInfo.Channel != req.Channel {
|
||||
return nil, fmt.Errorf("channel not found. %s", req.Channel)
|
||||
}
|
||||
filter := bson.M{}
|
||||
if channelInfo.Type == channelmod.ChannelTypeParent {
|
||||
filter[channelmod.FN.ChannelInfo.Channel] = channelInfo.Channel
|
||||
} else {
|
||||
filter[channelmod.FN.ChannelInfo.Channel] = channelInfo.ParentChannel
|
||||
}
|
||||
ruleList, err := channelmod.FindManyChannelDeductionRule(ctx, filter)
|
||||
if err != nil {
|
||||
log.Error("AgentChannelAppInfo FindManyChannelDeductionRule", log.Any("channel", req.Channel), log.E(err))
|
||||
return nil, err
|
||||
}
|
||||
resp := &proto.ChannelAppInfoResp{
|
||||
List: make([]proto.ChannelAppInfo, 0),
|
||||
}
|
||||
for _, ruleInfo := range ruleList {
|
||||
temp := proto.ChannelAppInfo{
|
||||
AppId: ruleInfo.AppId,
|
||||
AppName: ruleInfo.AppName,
|
||||
LandingPage: ruleInfo.LandingPage + fmt.Sprintf("?dc=%s", req.Channel),
|
||||
}
|
||||
resp.List = append(resp.List, temp)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// AgentChannelListInfo 查询渠道列表
|
||||
func AgentChannelListInfo(ctx context.Context, channel string, req *proto.AgentChannelInfoSearch) (
|
||||
*proto.AgentChannelInfoSearchResp, error) {
|
||||
|
||||
filter := bson.M{"$or": bson.A{
|
||||
bson.M{channelmod.FN.ChannelInfo.Channel: channel},
|
||||
bson.M{channelmod.FN.ChannelInfo.ParentAgent: channel},
|
||||
}}
|
||||
|
||||
opt := &options.FindOptions{}
|
||||
opt.SetSort(bson.M{channelmod.FN.ChannelInfo.CreatedAt: -1})
|
||||
opt.SetSkip((req.PageNum - 1) * req.PageSize)
|
||||
opt.SetLimit(req.PageSize)
|
||||
|
||||
resp := &proto.AgentChannelInfoSearchResp{}
|
||||
|
||||
if req.AppId != nil {
|
||||
filter[channelmod.FN.ChannelInfo.AppIds] = bson.M{"$in": []int32{*req.AppId}}
|
||||
}
|
||||
if req.Type != nil {
|
||||
filter[channelmod.FN.ChannelInfo.Type] = *req.Type
|
||||
}
|
||||
|
||||
total, serr := channelmod.CountChannelInfos(ctx, filter)
|
||||
if serr != nil {
|
||||
return nil, serr
|
||||
}
|
||||
if total == 0 {
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
channelInfoList, err := channelmod.FindManyChannelInfo(ctx, filter, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.List = make([]proto.ChannelAgentInfo, 0)
|
||||
|
||||
for _, channchannelInfo := range channelInfoList {
|
||||
tmp := proto.ChannelAgentInfo{
|
||||
Channel: channchannelInfo.Channel,
|
||||
AppIds: channchannelInfo.AppIds,
|
||||
UserName: channchannelInfo.UserName,
|
||||
ParentAgent: channchannelInfo.ParentAgent,
|
||||
ChildCount: channchannelInfo.ChildCount,
|
||||
Status: channchannelInfo.Status,
|
||||
Mobile: channchannelInfo.Mobile,
|
||||
Type: channchannelInfo.Type,
|
||||
Remark: channchannelInfo.Remark,
|
||||
Lock: channchannelInfo.Lock,
|
||||
Wallet: channchannelInfo.Wallet,
|
||||
CreatedAt: channchannelInfo.CreatedAt,
|
||||
UpdatedAt: channchannelInfo.UpdatedAt,
|
||||
}
|
||||
|
||||
ruleFilter := bson.M{
|
||||
channelmod.FN.ChannelDeductionRule.Channel: channchannelInfo.Channel,
|
||||
}
|
||||
ruleInfoList, _ := channelmod.FindManyChannelDeductionRule(ctx, ruleFilter)
|
||||
for _, ruleInfo := range ruleInfoList {
|
||||
tmp.Settlement = ruleInfo.Settlement
|
||||
tmp.CPAPrice = ruleInfo.CPAPrice
|
||||
tmp.CPSRate = ruleInfo.CPSRate
|
||||
tmp.DivideRate = ruleInfo.DivideRate
|
||||
tmp.AppType = ruleInfo.AppType
|
||||
tmp.PromoteMode = ruleInfo.PromoteMode
|
||||
tmp.AppIds = []int32{int32(ruleInfo.AppId)}
|
||||
if tmp.DivideRate == 0 {
|
||||
tmp.DivideRate = 100
|
||||
}
|
||||
if tmp.Channel == channel {
|
||||
tmp.DivideRate = 100
|
||||
}
|
||||
|
||||
resp.List = append(resp.List, tmp)
|
||||
}
|
||||
}
|
||||
resp.Total = total
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// AgentChannelRuleUpdate 更新渠道信息
|
||||
func AgentChannelRuleUpdate(ctx context.Context, channel string, req *proto.AgentChannelRuleUpdate) error {
|
||||
// 查找要修改规则的子代理
|
||||
channelFilter := bson.M{
|
||||
channelmod.FN.ChannelInfo.Channel: req.Channel,
|
||||
channelmod.FN.ChannelInfo.ParentAgent: channel,
|
||||
}
|
||||
channelInfo, err := channelmod.FindOneChannelInfo(ctx, channelFilter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if channelInfo.Channel != req.Channel {
|
||||
return fmt.Errorf("channel not found %s", req.Channel)
|
||||
}
|
||||
if req.CPSRate == nil && req.CPAPrice == nil && req.DivideRate == nil && req.ChildShowDivideRate == nil {
|
||||
return nil
|
||||
}
|
||||
if req.CPSRate != nil && !InRangeInt64(*req.CPSRate, 0, 100) {
|
||||
return fmt.Errorf("CPS比例 (%d) 必须在 0-100 之间", *req.CPSRate)
|
||||
}
|
||||
if req.DivideRate != nil && !InRangeInt64(*req.DivideRate, 0, 100) {
|
||||
return fmt.Errorf("分成比例 (%d) 必须在 0-100 之间", *req.CPSRate)
|
||||
}
|
||||
// 规则检查
|
||||
parentRules, err := channelmod.FindManyChannelDeductionRule(ctx, bson.M{channelmod.FN.ChannelDeductionRule.Channel: channelInfo.ParentAgent})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if req.CPAPrice != nil {
|
||||
parentCPA := int64(0)
|
||||
for _, rule := range parentRules {
|
||||
if rule.CPAPrice > 0 {
|
||||
if parentCPA <= 0 {
|
||||
parentCPA = rule.CPAPrice
|
||||
} else {
|
||||
if rule.CPAPrice < parentCPA {
|
||||
parentCPA = rule.CPAPrice
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if *req.CPAPrice > parentCPA || *req.CPAPrice < 0 {
|
||||
return fmt.Errorf("下级CPA价格 (%d) 必须在范围 0-%d 之间,不能大于你自己的CPA价格", *req.CPAPrice/100, parentCPA/100)
|
||||
}
|
||||
}
|
||||
if req.CPSRate != nil {
|
||||
parentCPSRate := int64(0)
|
||||
for _, rule := range parentRules {
|
||||
if rule.CPSRate > 0 {
|
||||
if parentCPSRate <= 0 {
|
||||
parentCPSRate = rule.CPSRate
|
||||
} else {
|
||||
if rule.CPSRate < parentCPSRate {
|
||||
parentCPSRate = rule.CPSRate
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if *req.CPSRate > parentCPSRate || *req.CPSRate < 0 {
|
||||
return fmt.Errorf("下级CPS比例 (%d) 必须在范围 0-%d 之间, 不能大于你自己的CPS比例", *req.CPSRate, parentCPSRate)
|
||||
}
|
||||
}
|
||||
|
||||
// 更新规则
|
||||
setdoc := bson.M{}
|
||||
if req.CPAPrice != nil {
|
||||
setdoc[channelmod.FN.ChannelDeductionRule.CPAPrice] = *req.CPAPrice
|
||||
}
|
||||
if req.CPSRate != nil {
|
||||
setdoc[channelmod.FN.ChannelDeductionRule.CPSRate] = *req.CPSRate
|
||||
}
|
||||
if req.DivideRate != nil {
|
||||
setdoc[channelmod.FN.ChannelDeductionRule.DivideRate] = *req.DivideRate
|
||||
}
|
||||
if err := channelmod.UpdateManyChannelDeductionRule(ctx,
|
||||
bson.M{channelmod.FN.ChannelDeductionRule.Channel: req.Channel},
|
||||
bson.M{"$set": setdoc},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 更新子代理是否显示分成比例
|
||||
if req.ChildShowDivideRate != nil || req.Remark != nil {
|
||||
doc := bson.M{}
|
||||
if req.ChildShowDivideRate != nil {
|
||||
doc[channelmod.FN.ChannelInfo.ChildShowDivideRate] = *req.ChildShowDivideRate
|
||||
}
|
||||
if req.Remark != nil {
|
||||
doc[channelmod.FN.ChannelInfo.Remark] = *req.Remark
|
||||
}
|
||||
if err = channelmod.UpdateOneChannelInfo(ctx, channelFilter, bson.M{"$set": doc}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
// AgentChannelInfoUpdate 更新渠道信息
|
||||
func AgentChannelInfoUpdate(ctx context.Context, channel string, req *proto.AgentChannelInfoUpdate) error {
|
||||
checkFilter := bson.M{
|
||||
channelmod.FN.ChannelInfo.Channel: req.Channel,
|
||||
}
|
||||
channelInfo, err := channelmod.FindOneChannelInfo(ctx, checkFilter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if channelInfo.Channel != req.Channel {
|
||||
return fmt.Errorf("channel not found. %s", req.Channel)
|
||||
}
|
||||
if req.WalletAddr1 != nil || req.WalletAddr2 != nil {
|
||||
if channelInfo.Channel == channel {
|
||||
return fmt.Errorf("您不可以修改自己的钱包地址,请联系您的上级代理协助修改")
|
||||
}
|
||||
}
|
||||
if !(channelInfo.Channel == channel || channelInfo.ParentAgent == channel) {
|
||||
return fmt.Errorf("channel not found! %s", req.Channel)
|
||||
}
|
||||
setdoc := bson.M{
|
||||
channelmod.FN.ChannelInfo.UpdatedAt: time.Now(),
|
||||
}
|
||||
if req.Status != nil {
|
||||
setdoc[channelmod.FN.ChannelInfo.Status] = *req.Status
|
||||
}
|
||||
if req.Mobile != nil {
|
||||
setdoc[channelmod.FN.ChannelInfo.Mobile] = *req.Mobile
|
||||
}
|
||||
if req.WalletAddr1 != nil {
|
||||
setdoc[channelmod.FN.ChannelInfo.Wallet.Addr1] = *req.WalletAddr1
|
||||
}
|
||||
if req.WalletAddr2 != nil {
|
||||
setdoc[channelmod.FN.ChannelInfo.Wallet.Addr2] = *req.WalletAddr2
|
||||
}
|
||||
return channelmod.UpdateOneChannelInfo(ctx,
|
||||
bson.M{channelmod.FN.ChannelInfo.Channel: req.Channel},
|
||||
bson.M{"$set": setdoc},
|
||||
)
|
||||
}
|
||||
|
||||
// AgentChannelPasswordReset 子渠道密码重置
|
||||
func AgentChannelPasswordReset(ctx context.Context, channel string, req *proto.AgentChannelPasswordReset) error {
|
||||
checkFilter := bson.M{
|
||||
channelmod.FN.ChannelInfo.Channel: req.Channel,
|
||||
}
|
||||
channelInfo, err := channelmod.FindOneChannelInfo(ctx, checkFilter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if channelInfo.Channel != req.Channel {
|
||||
return fmt.Errorf("代理没找到. %s", req.Channel)
|
||||
}
|
||||
if channelInfo.ParentAgent != channel {
|
||||
return errors.New("只能重置直接下级代理的密码! ")
|
||||
}
|
||||
if req.Password == "" {
|
||||
return errors.New("新密码不能为空! ")
|
||||
}
|
||||
setdoc := bson.M{
|
||||
channelmod.FN.ChannelInfo.UpdatedAt: time.Now(),
|
||||
channelmod.FN.ChannelInfo.Password: req.Password,
|
||||
}
|
||||
return channelmod.UpdateOneChannelInfo(ctx,
|
||||
bson.M{channelmod.FN.ChannelInfo.Channel: req.Channel},
|
||||
bson.M{"$set": setdoc},
|
||||
)
|
||||
}
|
||||
|
||||
// AgentChannelPasswordUpdate 更新渠道密码
|
||||
func AgentChannelPasswordUpdate(ctx context.Context, channel string, req *proto.AgentChannelPasswordUpdate) error {
|
||||
checkFilter := bson.M{
|
||||
channelmod.FN.ChannelInfo.Channel: channel,
|
||||
}
|
||||
channelInfo, err := channelmod.FindOneChannelInfo(ctx, checkFilter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if channelInfo.Channel != channel {
|
||||
return fmt.Errorf("channel not found. %s", channel)
|
||||
}
|
||||
if channelInfo.Password != req.OldPassword {
|
||||
return errors.New("旧密码输入错误")
|
||||
}
|
||||
if req.NewPassword == "" {
|
||||
return errors.New("新密码不能为空! ")
|
||||
}
|
||||
setdoc := bson.M{
|
||||
channelmod.FN.ChannelInfo.UpdatedAt: time.Now(),
|
||||
channelmod.FN.ChannelInfo.Password: req.NewPassword,
|
||||
}
|
||||
return channelmod.UpdateOneChannelInfo(ctx,
|
||||
bson.M{channelmod.FN.ChannelInfo.Channel: channel},
|
||||
bson.M{"$set": setdoc},
|
||||
)
|
||||
}
|
||||
|
||||
func GetChildNewChannelNameAndRootChannelName(ctx context.Context, channelParent *channelmod.ChannelInfo) (string, string, error) {
|
||||
maxid := 0
|
||||
filter := bson.M{}
|
||||
if channelParent.Type == channelmod.ChannelTypeParent {
|
||||
filter[channelmod.FN.ChannelInfo.ParentChannel] = channelParent.Channel
|
||||
} else {
|
||||
filter[channelmod.FN.ChannelInfo.ParentAgent] = channelParent.Channel
|
||||
}
|
||||
channlList, err := channelmod.FindManyChannelInfo(ctx, filter)
|
||||
if err != nil {
|
||||
log.Error("AddAgentChannelInfo CountChannelInfos", log.Any("channel", channelParent.Channel), log.E(err))
|
||||
return "", "", err
|
||||
}
|
||||
for _, v := range channlList {
|
||||
id, err := strconv.Atoi(string(strings.Replace(v.Channel, channelParent.Channel, "", -1)))
|
||||
if err == nil && id > maxid {
|
||||
maxid = id
|
||||
}
|
||||
}
|
||||
maxid = maxid + 1
|
||||
childChannelName := channelParent.Channel + fmt.Sprintf("%.2d", maxid)
|
||||
rootChannelName := ""
|
||||
if channelParent.Type == channelmod.ChannelTypeParent { // 一级代理
|
||||
rootChannelName = channelParent.Channel
|
||||
} else {
|
||||
if channelParent.ParentChannel == "" { // 如果子级代理的父代理为空
|
||||
//rootChannelName = channelParent.Channel
|
||||
return "", "", fmt.Errorf("子级代理【%s】的顶级代理空时不能添加子代理!", channelParent.Channel)
|
||||
} else {
|
||||
rootChannelName = channelParent.ParentChannel
|
||||
}
|
||||
}
|
||||
return childChannelName, rootChannelName, nil
|
||||
}
|
||||
|
||||
// AddAgentChannelInfo 渠道添加一个子渠道
|
||||
func AddAgentChannelInfo(ctx context.Context, channel string, req *proto.AgentChannelInfoAdd) error {
|
||||
channelInfo, _, err := GetChannelInfoWithLockStatus(ctx, channel)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if channelInfo.Lock || !channelInfo.Status {
|
||||
|
||||
return fmt.Errorf("您的代理或上级代理已被禁止")
|
||||
}
|
||||
|
||||
childChannelName, rootChannelName, err := GetChildNewChannelNameAndRootChannelName(ctx, channelInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
childChannelType := channelInfo.Type.Child()
|
||||
if childChannelType.IsNone() {
|
||||
return errors.New("您的代理等级无法添加子渠道")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
newChannelInfo := channelmod.ChannelInfo{
|
||||
Channel: childChannelName,
|
||||
UserName: channelInfo.UserName,
|
||||
AppIds: channelInfo.AppIds,
|
||||
ParentChannel: rootChannelName,
|
||||
ParentAgent: channel,
|
||||
Password: req.Password,
|
||||
Status: true,
|
||||
Mobile: req.Mobile,
|
||||
Type: childChannelType,
|
||||
Remark: req.Remark,
|
||||
Wallet: channelmod.Wallet{
|
||||
Addr1: req.WalletAddr1,
|
||||
Addr2: req.WalletAddr2,
|
||||
},
|
||||
Lock: false,
|
||||
ShowMagic: 0,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
err = channelmod.InsertOneChannelInfo(ctx, &newChannelInfo)
|
||||
if err != nil {
|
||||
log.Error("AddChannelInfo InsertOneChannelInfo", log.Any("channel", newChannelInfo.ParentChannel), log.E(err))
|
||||
return err
|
||||
}
|
||||
|
||||
// 增加子渠道数量
|
||||
setdoc := bson.M{"$inc": bson.M{channelmod.FN.ChannelInfo.ChildCount: 1}}
|
||||
err = channelmod.UpdateOneChannelInfo(ctx, bson.M{channelmod.FN.ChannelInfo.Channel: channel}, setdoc)
|
||||
if err != nil {
|
||||
log.Error("AddChannelInfo InsertOneChannelInfo", log.Any("channel", newChannelInfo.ParentChannel), log.E(err))
|
||||
return err
|
||||
}
|
||||
|
||||
for _, appid := range channelInfo.AppIds {
|
||||
checkFilter := bson.M{channelmod.FN.ChannelDeductionRule.Channel: channel, channelmod.FN.ChannelDeductionRule.AppId: appid}
|
||||
ChannelDeductionRule, err := channelmod.FindOneChannelDeductionRule(ctx, checkFilter)
|
||||
if err != nil || ChannelDeductionRule.Channel != channel {
|
||||
log.Error("AddAgentChannelInfo FindOneChannelDeductionRule", log.Any("channel", channel), log.Any("appid", appid), log.E(err))
|
||||
continue
|
||||
}
|
||||
newChannelRule := &channelmod.ChannelDeductionRule{
|
||||
Channel: newChannelInfo.Channel,
|
||||
AppId: ChannelDeductionRule.AppId,
|
||||
AppName: ChannelDeductionRule.AppName,
|
||||
AppType: ChannelDeductionRule.AppType,
|
||||
PromoteMode: ChannelDeductionRule.PromoteMode,
|
||||
Settlement: ChannelDeductionRule.Settlement,
|
||||
First: ChannelDeductionRule.First,
|
||||
Second: ChannelDeductionRule.Second,
|
||||
Third: ChannelDeductionRule.Third,
|
||||
Fourth: ChannelDeductionRule.Fourth,
|
||||
Fifth: ChannelDeductionRule.Fifth,
|
||||
CPAPrice: ChannelDeductionRule.CPAPrice,
|
||||
CPSRate: ChannelDeductionRule.CPSRate,
|
||||
CPSBegin: ChannelDeductionRule.CPSBegin,
|
||||
CPSDeductionRate: ChannelDeductionRule.CPSDeductionRate,
|
||||
BeginTime: ChannelDeductionRule.BeginTime,
|
||||
SettlementTime: now,
|
||||
TodayTime: utils.BeginOfToday(),
|
||||
TodayDeduction: 0,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
err = channelmod.InsertOneChannelDeductionRule(ctx, newChannelRule)
|
||||
if err != nil {
|
||||
log.Error("AddAgentChannelInfo InsertOneChannelDeductionRule", log.Any("channel", channel), log.Any("appid", appid), log.E(err))
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAgentSummaryStatChild 查询渠道扣量规则信息
|
||||
func GetAgentSummaryStatChild(ctx context.Context, channel string, req *proto.AgentSummaryStatChildSearch) (*proto.AgentSummaryStatChildResp, error) {
|
||||
resp := &proto.AgentSummaryStatChildResp{
|
||||
List: make(proto.AgentSummaryStatChildList, 0),
|
||||
}
|
||||
summary, err := GetAgentSummary(ctx, channel, nil, nil, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
total, list := summary.GetAgentSummaryStats(OutputStatListTypeChild, req.PageNum, req.PageSize)
|
||||
resp.Total = total
|
||||
for _, item := range list {
|
||||
resp.List = append(resp.List, item.ToAgentSummaryStatChild())
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetAgentSummaryStatHome 查询渠道扣量规则信息
|
||||
func GetAgentSummaryStatHome(ctx context.Context, channel string, req *proto.AgentSummaryStatHomeSearch) (*proto.AgentSummaryStatHomeResp, error) {
|
||||
resp := &proto.AgentSummaryStatHomeResp{
|
||||
List: make(proto.AgentSummaryStatHomeList, 0),
|
||||
}
|
||||
summary, err := GetAgentSummary(ctx, channel, nil, nil, nil, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
total, list := summary.GetAgentSummaryStats(OutputStatListTypeSelf, req.PageNum, req.PageSize)
|
||||
resp.Total = total
|
||||
resp.List = list
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetAgentChannelStat 查询渠道扣量规则信息
|
||||
func GetAgentChannelStat(ctx context.Context, channel string, req *proto.AgentChannelStatSearch) (*proto.AgentChannelStatResp, error) {
|
||||
resp := &proto.AgentChannelStatResp{
|
||||
List: make([]*proto.AgentDeductedStat, 0),
|
||||
}
|
||||
summary, err := GetAgentSummary(ctx, channel, req.Channel, req.AppId, req.Start, req.End)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
total, list := summary.GetAgentStats(OutputStatListTypeAll, req.PageNum, req.PageSize)
|
||||
resp.Total = total
|
||||
resp.List = list
|
||||
resp.TotalInfo = *summary.StatTotal
|
||||
return resp, nil
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package agentSer
|
||||
|
||||
import (
|
||||
"stat/api/proto"
|
||||
"stat/models/appInfoMod"
|
||||
"stat/models/channelmod"
|
||||
)
|
||||
|
||||
const (
|
||||
CPA_SHOW_MONEY = false
|
||||
CPS_SHOW_COUNT = true
|
||||
)
|
||||
|
||||
type ChannelMap map[string]*channelmod.ChannelInfo
|
||||
type AppMap map[int32]*appInfoMod.AppInfo
|
||||
type SourceAgentStatMap map[channelmod.ChannelType]map[string]ChannelAgentStatList
|
||||
type OutputStatListType int32
|
||||
|
||||
type AgentDeductedStatList []*proto.AgentDeductedStat
|
||||
|
||||
func (a AgentDeductedStatList) Len() int { return len(a) }
|
||||
func (a AgentDeductedStatList) Less(i, j int) bool { return a[i].SumDate.After(a[j].SumDate) }
|
||||
func (a AgentDeductedStatList) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
const (
|
||||
OutputStatListTypeAll OutputStatListType = 0 // 输出当前渠道和直接下级渠道的stat列表
|
||||
OutputStatListTypeSelf OutputStatListType = 1 // 输出当前渠道自身的stat列表
|
||||
OutputStatListTypeChild OutputStatListType = 2 // 输出直接下级渠道的stat列表
|
||||
)
|
||||
|
||||
type AgentChannelSummaryMode int32
|
||||
|
||||
const (
|
||||
AgentChannelSummaryModeFollowRule AgentChannelSummaryMode = 0 // 按渠道规则,忽略记录中的规则和价格
|
||||
AgentChannelSummaryModeFollowRecord AgentChannelSummaryMode = 1 // 按记录中的规则和价格,覆盖渠道规则
|
||||
)
|
||||
|
||||
var (
|
||||
GlobalAgentChannelSummaryMode = AgentChannelSummaryModeFollowRule
|
||||
)
|
||||
|
||||
type AgentChannelStat struct {
|
||||
channelmod.ChannelStat
|
||||
ChildValidDirectCount int64
|
||||
ChildValidPayMoney int64
|
||||
ChildChannelStats []*AgentChannelStat
|
||||
DeductedStat *proto.AgentDeductedStat
|
||||
DivideRate int64
|
||||
}
|
||||
type ChannelAgentStatList []*AgentChannelStat
|
||||
@@ -0,0 +1,199 @@
|
||||
package agentSer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"stat/api/proto"
|
||||
"stat/models/appInfoMod"
|
||||
"stat/models/channelmod"
|
||||
)
|
||||
|
||||
func EnsureRangeInt64(value, min, max int64) int64 {
|
||||
if value < min {
|
||||
value = min
|
||||
}
|
||||
if value > max {
|
||||
value = max
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func InRangeInt64(value, min, max int64) bool {
|
||||
if value < min {
|
||||
return false
|
||||
}
|
||||
if value > max {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func MinInt64(x, y int64) int64 {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func MaxInt64(x, y int64) int64 {
|
||||
if x > y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
func GetPageRange(totalLen, pageNum, pageSize int) (start, end int) {
|
||||
if pageNum < 1 {
|
||||
pageNum = 1
|
||||
}
|
||||
if pageSize < 1 {
|
||||
pageSize = 10
|
||||
}
|
||||
start = (pageNum - 1) * pageSize
|
||||
if start > totalLen {
|
||||
start = totalLen
|
||||
}
|
||||
end = start + pageSize
|
||||
if end > totalLen {
|
||||
end = totalLen
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c ChannelMap) GetChannelNames() []string {
|
||||
lst := make([]string, 0)
|
||||
for _, v := range c {
|
||||
lst = append(lst, v.Channel)
|
||||
}
|
||||
return lst
|
||||
}
|
||||
|
||||
func (c ChannelMap) GetChildChannels(channel string) []*channelmod.ChannelInfo {
|
||||
lst := make([]*channelmod.ChannelInfo, 0)
|
||||
for _, v := range c {
|
||||
if v.ParentAgent == channel {
|
||||
lst = append(lst, v)
|
||||
}
|
||||
}
|
||||
return lst
|
||||
}
|
||||
|
||||
func (c ChannelMap) GetParentChannels(channel string) []*channelmod.ChannelInfo {
|
||||
lst := make([]*channelmod.ChannelInfo, 0)
|
||||
self := c[channel]
|
||||
if self == nil {
|
||||
return lst
|
||||
}
|
||||
parent := c[self.ParentAgent]
|
||||
for parent != nil {
|
||||
lst = append(lst, parent)
|
||||
parent = c[parent.ParentAgent]
|
||||
}
|
||||
return lst
|
||||
}
|
||||
|
||||
func (c ChannelMap) GetLockStatusAndShowDivide(channelInfo *channelmod.ChannelInfo) (bool, bool, bool) {
|
||||
parents := c.GetParentChannels(channelInfo.Channel)
|
||||
parentShowDivide := true
|
||||
status := channelInfo.Status
|
||||
lock := channelInfo.Lock
|
||||
for _, parent := range parents {
|
||||
parentShowDivide = parentShowDivide && parent.ChildShowDivideRate
|
||||
status = status && parent.Status
|
||||
if parent.Lock {
|
||||
lock = true
|
||||
}
|
||||
}
|
||||
return lock, status, parentShowDivide && channelInfo.ChildShowDivideRate
|
||||
}
|
||||
|
||||
func (c ChannelMap) GetAncestorAndOffspringChannels(channel string) []*channelmod.ChannelInfo {
|
||||
out := make([]*channelmod.ChannelInfo, 0)
|
||||
cInfo := c[channel]
|
||||
if cInfo == nil {
|
||||
return out
|
||||
}
|
||||
children := c.GetChildChannels(cInfo.Channel)
|
||||
for len(children) > 0 {
|
||||
tmp := make([]*channelmod.ChannelInfo, 0)
|
||||
for _, child := range children {
|
||||
out = append(out, child)
|
||||
tmp = append(tmp, c.GetChildChannels(child.Channel)...)
|
||||
}
|
||||
children = tmp
|
||||
}
|
||||
for cInfo != nil {
|
||||
out = append(out, cInfo)
|
||||
if cInfo.ParentAgent != "" {
|
||||
cInfo = c[cInfo.ParentAgent]
|
||||
} else {
|
||||
cInfo = nil
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func GetAppMap(ctx context.Context) (AppMap, error) {
|
||||
appList, err := appInfoMod.GetAllAppInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appMap := make(AppMap)
|
||||
for _, app := range appList {
|
||||
tmp := app
|
||||
appMap[app.AppId] = &tmp
|
||||
}
|
||||
return appMap, nil
|
||||
}
|
||||
|
||||
func (m AppMap) GetAppName(id int32) string {
|
||||
if app, ok := m[id]; ok {
|
||||
return app.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func AccumulateAgentChannelStat(base, stat *AgentChannelStat, ruleData bool) {
|
||||
channelmod.ChannelStatSummation(&base.ChannelStat, &stat.ChannelStat)
|
||||
base.Settlement = stat.Settlement
|
||||
base.ChildValidPayMoney += stat.ChildValidPayMoney
|
||||
base.ChildValidDirectCount += stat.ChildValidDirectCount
|
||||
AccumulateDeductedStat(base.DeductedStat, stat.DeductedStat, ruleData)
|
||||
for _, child := range stat.ChildChannelStats {
|
||||
base.DeductedStat.ChildRebate += child.DeductedStat.Income
|
||||
}
|
||||
}
|
||||
|
||||
func AccumulateDeductedStat(base, stat *proto.AgentDeductedStat, ruleData bool) {
|
||||
base.VisitCount += stat.VisitCount
|
||||
if !ruleData || (ruleData && stat.Settlement == channelmod.SettlementCPA) || (stat.Settlement == channelmod.SettlementCPS && CPS_SHOW_COUNT) {
|
||||
base.DirectCount += stat.DirectCount
|
||||
base.DirectCountChild += stat.DirectCountChild
|
||||
base.DirectCountSelf += stat.DirectCountSelf
|
||||
}
|
||||
if !ruleData || (ruleData && stat.Settlement == channelmod.SettlementCPS) || (stat.Settlement == channelmod.SettlementCPA && CPA_SHOW_MONEY) {
|
||||
base.Recharge += stat.Recharge
|
||||
base.RechargeChild += stat.RechargeChild
|
||||
base.RechargeSelf += stat.RechargeSelf
|
||||
}
|
||||
base.Income += stat.Income
|
||||
base.IncomeChild += stat.IncomeChild
|
||||
base.IncomeSelf += stat.IncomeSelf
|
||||
}
|
||||
|
||||
func AccumulateStatData(base *proto.StatDataDetail, stat *proto.AgentDeductedStat, ruleData bool) {
|
||||
base.ChildRebate += stat.ChildRebate
|
||||
base.VisitCount += stat.VisitCount
|
||||
if !ruleData || (ruleData && stat.Settlement == channelmod.SettlementCPA) || (stat.Settlement == channelmod.SettlementCPS && CPS_SHOW_COUNT) {
|
||||
base.DirectCount += stat.DirectCount
|
||||
base.DirectCountSelf += stat.DirectCountSelf
|
||||
base.DirectCountChild += stat.DirectCountChild
|
||||
}
|
||||
if !ruleData || (ruleData && stat.Settlement == channelmod.SettlementCPS) || (stat.Settlement == channelmod.SettlementCPA && CPA_SHOW_MONEY) {
|
||||
base.Recharge += stat.Recharge
|
||||
base.RechargeSelf += stat.RechargeSelf
|
||||
base.RechargeChild += stat.RechargeChild
|
||||
}
|
||||
base.Income += stat.Income
|
||||
base.IncomeSelf += stat.IncomeSelf
|
||||
base.IncomeChild += stat.IncomeChild
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
package agentSer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"stat/api/proto"
|
||||
"stat/models/channelmod"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
type AgentNode struct {
|
||||
Ctx context.Context
|
||||
ChannelInfo *channelmod.ChannelInfo
|
||||
Stats ChannelAgentStatList
|
||||
Parent *AgentNode
|
||||
Children []*AgentNode
|
||||
Accumulate bool //是否已累计子层
|
||||
AddedChild bool //是否已添加子层
|
||||
Deducted bool //是否已计算扣量
|
||||
}
|
||||
|
||||
func NewAgentNode(ctx context.Context, channel *channelmod.ChannelInfo, parent *AgentNode, stats ...*AgentChannelStat) *AgentNode {
|
||||
ret := &AgentNode{
|
||||
Ctx: ctx,
|
||||
ChannelInfo: channel,
|
||||
Stats: make([]*AgentChannelStat, 0),
|
||||
Parent: parent,
|
||||
Children: make([]*AgentNode, 0),
|
||||
Accumulate: false,
|
||||
}
|
||||
ret.Stats = append(ret.Stats, stats...)
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetRootAgentNode(ctx context.Context, selfChannel *channelmod.ChannelInfo, reqChannel *string, statDict SourceAgentStatMap) (*AgentNode, error) {
|
||||
var rootAgent *AgentNode
|
||||
if reqChannel != nil && *reqChannel != selfChannel.Channel {
|
||||
cInfo, err := channelmod.FindOneChannelInfoEx(ctx, bson.M{channelmod.FN.ChannelInfo.Channel: *reqChannel})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cInfo.ParentAgent != selfChannel.Channel {
|
||||
return nil, fmt.Errorf("查找渠道失败,只能查看自己或自己的直接下级!")
|
||||
}
|
||||
stats := statDict[cInfo.Type][cInfo.Channel]
|
||||
rootAgent = NewAgentNode(ctx, cInfo, nil, stats...)
|
||||
} else {
|
||||
stats := statDict[selfChannel.Type][selfChannel.Channel]
|
||||
rootAgent = NewAgentNode(ctx, selfChannel, nil, stats...)
|
||||
}
|
||||
return rootAgent, nil
|
||||
}
|
||||
|
||||
func nodeFind(node *AgentNode, find func(node *AgentNode) bool) *AgentNode {
|
||||
var stack = []*AgentNode{node}
|
||||
for len(stack) > 0 {
|
||||
node = stack[len(stack)-1]
|
||||
stack = stack[:len(stack)-1]
|
||||
if node != nil {
|
||||
found := find(node)
|
||||
if found {
|
||||
return node
|
||||
}
|
||||
stack = append(stack, node.Children...)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func traverse(node *AgentNode, accumulate func(node *AgentNode)) {
|
||||
// first child
|
||||
for _, child := range node.Children {
|
||||
traverse(child, accumulate)
|
||||
}
|
||||
// last self
|
||||
accumulate(node)
|
||||
}
|
||||
|
||||
func (s *AgentNode) AddChildNodes(srcDict SourceAgentStatMap, channelMap ChannelMap) error {
|
||||
findNotAddChildNodeFn := func(node *AgentNode) bool {
|
||||
if !node.AddedChild {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
for found := nodeFind(s, findNotAddChildNodeFn); found != nil; found = nodeFind(s, findNotAddChildNodeFn) {
|
||||
childChannels := channelMap.GetChildChannels(found.ChannelInfo.Channel)
|
||||
for _, channel := range childChannels {
|
||||
stats := srcDict[channel.Type][channel.Channel]
|
||||
agent := NewAgentNode(s.Ctx, channel, found, stats...)
|
||||
found.Children = append(found.Children, agent)
|
||||
}
|
||||
found.AddedChild = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *AgentNode) AccumulateChildNodes(ruleMap RuleMap) error {
|
||||
accumulate := func(found *AgentNode) {
|
||||
if found.Accumulate {
|
||||
panic(errors.New("AccumulateChildNodes found node can not be accumulate"))
|
||||
}
|
||||
for _, childAgent := range found.Children {
|
||||
if !childAgent.Accumulate {
|
||||
panic(errors.New("AccumulateChildNodes child node can not be not accumulated"))
|
||||
}
|
||||
for _, childStat := range childAgent.Stats {
|
||||
hit := false
|
||||
for _, parentStat := range found.Stats {
|
||||
if parentStat.SumDate.Equal(childStat.SumDate) {
|
||||
hit = true
|
||||
AccumulateChildAgentChannelStatToParent(parentStat, childStat)
|
||||
}
|
||||
}
|
||||
if !hit {
|
||||
lostStat := &AgentChannelStat{
|
||||
ChannelStat: channelmod.ChannelStat{
|
||||
Channel: childAgent.ChannelInfo.ParentAgent,
|
||||
SumDate: childStat.SumDate,
|
||||
AppId: childStat.AppId,
|
||||
Type: childStat.Type - 1,
|
||||
Settlement: childStat.Settlement,
|
||||
UserName: childStat.UserName,
|
||||
ParentChannel: childStat.ParentChannel,
|
||||
},
|
||||
}
|
||||
if rule := ruleMap.GetRule(childAgent.ChannelInfo.ParentAgent, childStat.AppId); rule != nil {
|
||||
lostStat.CPSRate = rule.CPSRate
|
||||
lostStat.CPAPrice = rule.CPAPrice
|
||||
lostStat.Settlement = rule.Settlement
|
||||
lostStat.DivideRate = rule.DivideRate
|
||||
lostStat.AppType = rule.AppType
|
||||
lostStat.PromoteMode = rule.PromoteMode
|
||||
}
|
||||
AccumulateChildAgentChannelStatToParent(lostStat, childStat)
|
||||
found.Stats = append(found.Stats, lostStat)
|
||||
log.Println(lostStat)
|
||||
}
|
||||
}
|
||||
}
|
||||
found.Accumulate = true
|
||||
}
|
||||
traverse(s, accumulate)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *AgentNode) CalculateDeduction(channelMap ChannelMap, ruleMap RuleMap) error {
|
||||
deduction := func(found *AgentNode) {
|
||||
if found.Deducted {
|
||||
panic(errors.New("CalculateDeduction found node, can not be deducted"))
|
||||
}
|
||||
for _, stat := range found.Stats {
|
||||
pRule := GetMergedRule(channelMap, ruleMap, found.ChannelInfo.ParentAgent, stat.AppId)
|
||||
sRule := ruleMap.GetRule(stat.Channel, stat.AppId)
|
||||
stat.DeductedStat = DeductionChannelStat(stat, pRule, sRule)
|
||||
}
|
||||
found.Deducted = true
|
||||
}
|
||||
traverse(s, deduction)
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeductionChannelStat(stat *AgentChannelStat, parentRule, selfRule *AgentChannelRule) *proto.AgentDeductedStat {
|
||||
proxyDeductionTime, _ := time.ParseInLocation("2006-01-02", "2021-10-28", time.Local)
|
||||
base := &proto.AgentDeductedStat{
|
||||
Channel: stat.Channel,
|
||||
AppId: stat.AppId,
|
||||
SumDate: stat.SumDate,
|
||||
DirectCount: stat.ValidDirectCount,
|
||||
DirectCountChild: stat.ChildValidDirectCount,
|
||||
DirectCountSelf: stat.ValidDirectCount - stat.ChildValidDirectCount,
|
||||
Recharge: stat.ValidPayMoney,
|
||||
RechargeChild: stat.ChildValidPayMoney,
|
||||
RechargeSelf: stat.ValidPayMoney - stat.ChildValidPayMoney,
|
||||
Settlement: stat.Settlement,
|
||||
CPSRate: stat.CPSRate,
|
||||
CPAPrice: stat.CPAPrice,
|
||||
DivideRate: stat.DivideRate,
|
||||
UpdatedAt: stat.UpdatedAt,
|
||||
}
|
||||
if selfRule == nil {
|
||||
if base.DivideRate == 0 {
|
||||
base.DivideRate = 100
|
||||
}
|
||||
return base
|
||||
}
|
||||
rule := MergedRule(parentRule, selfRule)
|
||||
if GlobalAgentChannelSummaryMode == AgentChannelSummaryModeFollowRecord {
|
||||
rule.CPSRate = stat.CPSRate
|
||||
rule.CPAPrice = stat.CPAPrice
|
||||
if base.Settlement == "" {
|
||||
base.Settlement = rule.Settlement
|
||||
}
|
||||
} else {
|
||||
base.CPSRate = rule.CPSRate
|
||||
base.CPAPrice = rule.CPAPrice
|
||||
base.Settlement = rule.Settlement
|
||||
}
|
||||
base.DivideRate = selfRule.DivideRate
|
||||
if base.DivideRate == 0 {
|
||||
base.DivideRate = 100
|
||||
}
|
||||
// 首先进行根代理扣量
|
||||
if rule.ProxyDeduction > 0 && rule.ProxyDeduction < 100 && base.SumDate.After(proxyDeductionTime) {
|
||||
base.DirectCount = base.DirectCount * rule.ProxyDeduction / 100
|
||||
base.DirectCountChild = base.DirectCountChild * rule.ProxyDeduction / 100
|
||||
base.Recharge = base.Recharge*rule.ProxyDeduction/100 - (base.Recharge*rule.ProxyDeduction/100)%1000
|
||||
base.RechargeChild = base.RechargeChild*rule.ProxyDeduction/100 - (base.RechargeChild*rule.ProxyDeduction/100)%1000
|
||||
}
|
||||
// 按上级代理对该代理设置的分成比例进行扣量
|
||||
if rule.DivideRateBP > 0 && rule.DivideRateBP < 10000 {
|
||||
base.DirectCount = base.DirectCount * rule.DivideRateBP / 10000
|
||||
base.DirectCountChild = base.DirectCountChild * rule.DivideRateBP / 10000
|
||||
base.Recharge = base.Recharge * rule.DivideRateBP / 10000
|
||||
base.RechargeChild = base.RechargeChild * rule.DivideRateBP / 10000
|
||||
}
|
||||
// 再计算收益
|
||||
if rule.Settlement == channelmod.SettlementCPA {
|
||||
base.Income = base.DirectCount * rule.CPAPrice
|
||||
base.IncomeChild = base.DirectCountChild * rule.CPAPrice
|
||||
} else if rule.Settlement == channelmod.SettlementCPS {
|
||||
base.Income = (base.Recharge * rule.CPSRate) / 100
|
||||
base.IncomeChild = (base.RechargeChild * rule.CPSRate) / 100
|
||||
} else if rule.Settlement == channelmod.SettlementCPT {
|
||||
base.Income = base.DirectCount * rule.CPAPrice
|
||||
base.IncomeChild = base.DirectCountChild * rule.CPAPrice
|
||||
}
|
||||
// 统计子代理数据
|
||||
base.IncomeSelf = base.Income - base.IncomeChild
|
||||
base.DirectCountSelf = base.DirectCount - base.DirectCountChild
|
||||
base.RechargeSelf = base.Recharge - base.RechargeChild
|
||||
for _, child := range stat.ChildChannelStats {
|
||||
base.ChildRebate += child.DeductedStat.Income
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
||||
func AccumulateChildAgentChannelStatToParent(parent, child *AgentChannelStat) {
|
||||
channelmod.ChannelStatSummation(&parent.ChannelStat, &child.ChannelStat)
|
||||
// 子渠道累计
|
||||
parent.ChildValidPayMoney += child.VipPayMoney
|
||||
parent.ChildValidDirectCount += child.NewDirectCount
|
||||
parent.ChildChannelStats = append(parent.ChildChannelStats, child)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package agentSer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"stat/common/log"
|
||||
"stat/common/utils"
|
||||
"stat/models/channelmod"
|
||||
)
|
||||
|
||||
func RepairData() {
|
||||
wg := utils.NewWaitGroup()
|
||||
wg.Add(func() {
|
||||
ctx := context.Background()
|
||||
if err := FixChannelSecondParentAgent(ctx); err != nil {
|
||||
log.Error("fix data err", log.E(err))
|
||||
}
|
||||
})
|
||||
go wg.RunWaits()
|
||||
}
|
||||
|
||||
func FixChannelSecondParentAgent(ctx context.Context) error {
|
||||
filter := bson.M{
|
||||
channelmod.FN.ChannelInfo.Type: channelmod.ChannelTypeSecond,
|
||||
"$or": bson.A{
|
||||
bson.M{channelmod.FN.ChannelInfo.ParentAgent: bson.M{"$eq": nil}},
|
||||
bson.M{channelmod.FN.ChannelInfo.ParentAgent: bson.M{"$exists": false}},
|
||||
bson.M{channelmod.FN.ChannelInfo.ParentAgent: bson.M{"$eq": ""}},
|
||||
},
|
||||
channelmod.FN.ChannelInfo.ParentChannel: bson.M{"$gt": ""},
|
||||
}
|
||||
count, err := channelmod.CountChannelInfos(ctx, filter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if count == 0 {
|
||||
return nil
|
||||
}
|
||||
// 修复
|
||||
channels, err := channelmod.FindManyChannelInfo(ctx, filter)
|
||||
for _, channel := range channels {
|
||||
filter := bson.M{channelmod.FN.ChannelInfo.Channel: channel.Channel}
|
||||
update := bson.M{"$set": bson.M{
|
||||
channelmod.FN.ChannelInfo.ParentAgent: channel.ParentChannel,
|
||||
}}
|
||||
if err = channelmod.UpdateOneChannelInfo(ctx, filter, update); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package agentSer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"stat/models/channelmod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
type RuleMap map[string]*AgentChannelRule
|
||||
|
||||
type AgentChannelRule struct {
|
||||
channelmod.ChannelDeductionRule
|
||||
DivideRateBP int64 // 分成比列(万分比)
|
||||
}
|
||||
|
||||
func (c RuleMap) GetRule(channel string, appId int32) *AgentChannelRule {
|
||||
key := fmt.Sprintf("%s %d", channel, appId)
|
||||
return c[key]
|
||||
}
|
||||
|
||||
func (c RuleMap) SetRule(rule *AgentChannelRule) {
|
||||
key := fmt.Sprintf("%s %d", rule.Channel, rule.AppId)
|
||||
c[key] = rule
|
||||
}
|
||||
|
||||
func GetMergedRule(channelMap ChannelMap, ruleMap RuleMap, channel string, appId int32) *AgentChannelRule {
|
||||
rules := make([]*AgentChannelRule, 0)
|
||||
cInfo := channelMap[channel]
|
||||
for cInfo != nil {
|
||||
rule := ruleMap.GetRule(cInfo.Channel, appId)
|
||||
if rule != nil {
|
||||
rules = append(rules, rule)
|
||||
}
|
||||
if cInfo.ParentAgent != "" {
|
||||
cInfo = channelMap[cInfo.ParentAgent]
|
||||
} else {
|
||||
cInfo = nil
|
||||
}
|
||||
}
|
||||
if len(rules) == 0 {
|
||||
return nil
|
||||
}
|
||||
for i, j := 0, len(rules)-1; i < j; i, j = i+1, j-1 {
|
||||
rules[i], rules[j] = rules[j], rules[i]
|
||||
}
|
||||
base := *rules[0] // 沿用父渠道代理扣量规则
|
||||
rules = rules[1:]
|
||||
|
||||
for _, rule := range rules {
|
||||
base.AppType = rule.AppType
|
||||
base.PromoteMode = rule.PromoteMode
|
||||
base.CPSRate = rule.CPSRate
|
||||
base.CPAPrice = MinInt64(base.CPAPrice, rule.CPAPrice) // 取最小的CPA价格
|
||||
base.DivideRate = base.DivideRate * rule.DivideRate / 100
|
||||
base.DivideRateBP = (base.DivideRateBP * rule.DivideRateBP) / 10000
|
||||
}
|
||||
return &base
|
||||
}
|
||||
|
||||
func MergedRule(parent, self *AgentChannelRule) *AgentChannelRule {
|
||||
if parent != nil && self != nil {
|
||||
rule := *self
|
||||
//rule.CPSRate //CPSRate not change
|
||||
rule.AppType = parent.AppType
|
||||
rule.PromoteMode = parent.PromoteMode
|
||||
rule.CPAPrice = MinInt64(rule.CPAPrice, parent.CPAPrice) // 取最小的CPA价格
|
||||
rule.DivideRate = rule.DivideRate * parent.DivideRate / 100
|
||||
rule.DivideRateBP = (rule.DivideRateBP * parent.DivideRateBP) / 10000
|
||||
rule.ProxyDeduction = parent.ProxyDeduction // 传递父渠道代理扣量到子渠道
|
||||
return &rule
|
||||
} else if parent != nil && self == nil {
|
||||
rule := *parent
|
||||
return &rule
|
||||
} else if parent == nil && self != nil {
|
||||
rule := *self
|
||||
return &rule
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func MakeChannelAndRuleMap(ctx context.Context, channelInfo *channelmod.ChannelInfo) (ChannelMap, RuleMap, error) {
|
||||
var err error
|
||||
ruleMap := make(RuleMap)
|
||||
channelMap := make(ChannelMap)
|
||||
var channelTop string
|
||||
if channelInfo.Type.IsTop() {
|
||||
channelTop = channelInfo.Channel
|
||||
} else {
|
||||
channelTop = channelInfo.ParentChannel
|
||||
}
|
||||
filter := bson.M{
|
||||
"$or": bson.A{
|
||||
bson.M{channelmod.FN.ChannelInfo.Channel: channelTop},
|
||||
bson.M{channelmod.FN.ChannelInfo.ParentChannel: channelTop},
|
||||
},
|
||||
}
|
||||
channelList, err := channelmod.FindManyChannelInfo(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
for _, c := range channelList {
|
||||
channelMap[c.Channel] = c
|
||||
}
|
||||
channels := make([]string, 0)
|
||||
channelInfos := channelMap.GetAncestorAndOffspringChannels(channelInfo.Channel)
|
||||
for _, info := range channelInfos {
|
||||
channels = append(channels, info.Channel)
|
||||
}
|
||||
rules, err := channelmod.FindManyChannelDeductionRule(ctx, bson.M{channelmod.FN.ChannelDeductionRule.Channel: bson.M{"$in": channels}})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
for _, item := range rules {
|
||||
item.CPAPrice = EnsureRangeInt64(item.CPAPrice, 0, 10000)
|
||||
item.CPSRate = EnsureRangeInt64(item.CPSRate, 0, 100)
|
||||
item.DivideRate = EnsureRangeInt64(item.DivideRate, 0, 100)
|
||||
if item.DivideRate == 0 {
|
||||
item.DivideRate = 100
|
||||
}
|
||||
rule := &AgentChannelRule{
|
||||
ChannelDeductionRule: *item,
|
||||
DivideRateBP: EnsureRangeInt64(item.DivideRate, 0, 100) * 100,
|
||||
}
|
||||
ruleMap.SetRule(rule)
|
||||
}
|
||||
return channelMap, ruleMap, nil
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
package agentSer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sort"
|
||||
"stat/api/proto"
|
||||
"stat/models/channelmod"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/now"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
type AgentSummary struct {
|
||||
StartTime *time.Time
|
||||
EndTime *time.Time
|
||||
AppId *int32
|
||||
FilterChannel *string
|
||||
ChannelInfo *channelmod.ChannelInfo
|
||||
ChannelMap ChannelMap
|
||||
RuleMap RuleMap
|
||||
AppMap AppMap
|
||||
StatMap SourceAgentStatMap
|
||||
SelfAgent *AgentNode
|
||||
SelfStats []*proto.AgentDeductedStat
|
||||
ChildStats []*proto.AgentDeductedStat
|
||||
StatTotal *proto.AgentDeductedStat
|
||||
}
|
||||
|
||||
func GetAgentSummary(ctx context.Context, selfChannel string, childChannel *string, appId *int32, start, end *time.Time) (*AgentSummary, error) {
|
||||
summary := AgentSummary{
|
||||
AppId: appId,
|
||||
StartTime: start,
|
||||
EndTime: end,
|
||||
FilterChannel: childChannel,
|
||||
SelfStats: make([]*proto.AgentDeductedStat, 0),
|
||||
ChildStats: make([]*proto.AgentDeductedStat, 0),
|
||||
AppMap: make(AppMap),
|
||||
}
|
||||
// 获取app信息字典
|
||||
appMap, err := GetAppMap(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
summary.AppMap = appMap
|
||||
// 获取渠道信息和统计信息
|
||||
channelInfo, statDict, err := GetAllAgentStatDict(ctx, selfChannel, appId, start, end)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
summary.ChannelInfo = channelInfo
|
||||
summary.StatMap = statDict
|
||||
// 获取顶层节点
|
||||
rootAgent, err := GetRootAgentNode(ctx, channelInfo, childChannel, statDict)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
summary.SelfAgent = rootAgent
|
||||
// 获取渠道列表扣量规则字典
|
||||
channelMap, ruleMap, err := MakeChannelAndRuleMap(ctx, channelInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
summary.ChannelMap = channelMap
|
||||
summary.RuleMap = ruleMap
|
||||
// 添加子渠道节点
|
||||
if err := rootAgent.AddChildNodes(statDict, channelMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 累计子渠道到上级渠道
|
||||
if err := rootAgent.AccumulateChildNodes(ruleMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 计算扣量
|
||||
if err := rootAgent.CalculateDeduction(channelMap, ruleMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, stat := range rootAgent.Stats {
|
||||
summary.SelfStats = append(summary.SelfStats, stat.DeductedStat)
|
||||
}
|
||||
for _, agent := range rootAgent.Children {
|
||||
for _, stat := range agent.Stats {
|
||||
summary.ChildStats = append(summary.ChildStats, stat.DeductedStat)
|
||||
}
|
||||
}
|
||||
// 统计总量
|
||||
base := &AgentChannelStat{
|
||||
DeductedStat: &proto.AgentDeductedStat{},
|
||||
}
|
||||
for _, item := range rootAgent.Stats {
|
||||
AccumulateAgentChannelStat(base, item, true)
|
||||
}
|
||||
summary.StatTotal = base.DeductedStat
|
||||
return &summary, nil
|
||||
}
|
||||
|
||||
func (a *AgentSummary) GetAgentStats(outType OutputStatListType, pageNum int64, pageSize int64) (int64, []*proto.AgentDeductedStat) {
|
||||
totalAgentStatList := make(AgentDeductedStatList, 0)
|
||||
switch outType {
|
||||
case OutputStatListTypeSelf:
|
||||
totalAgentStatList = append(totalAgentStatList, a.SelfStats...)
|
||||
case OutputStatListTypeChild:
|
||||
totalAgentStatList = append(totalAgentStatList, a.ChildStats...)
|
||||
default:
|
||||
totalAgentStatList = append(totalAgentStatList, a.SelfStats...)
|
||||
totalAgentStatList = append(totalAgentStatList, a.ChildStats...)
|
||||
}
|
||||
childChannel := a.FilterChannel
|
||||
if childChannel != nil { // 如果存在渠道过滤
|
||||
outAgentStatList := make([]*proto.AgentDeductedStat, 0)
|
||||
for _, item := range totalAgentStatList {
|
||||
if item.Channel == *childChannel {
|
||||
outAgentStatList = append(outAgentStatList, item)
|
||||
}
|
||||
}
|
||||
totalAgentStatList = outAgentStatList
|
||||
}
|
||||
// 处理排序
|
||||
sort.Sort(totalAgentStatList)
|
||||
// 处理分页输出
|
||||
list := GetAgentChannelStatListPageData(totalAgentStatList, pageNum, pageSize)
|
||||
// 添加app名字
|
||||
for _, item := range list {
|
||||
item.AppName = a.AppMap.GetAppName(item.AppId)
|
||||
if item.Channel == a.ChannelInfo.Channel {
|
||||
item.DivideRate = 100
|
||||
}
|
||||
if item.Settlement == channelmod.SettlementCPA && !CPA_SHOW_MONEY {
|
||||
item.Recharge = 0
|
||||
item.RechargeSelf = 0
|
||||
item.RechargeChild = 0
|
||||
}
|
||||
if item.Settlement == channelmod.SettlementCPS && !CPS_SHOW_COUNT {
|
||||
item.DirectCount = 0
|
||||
item.DirectCountSelf = 0
|
||||
item.DirectCountChild = 0
|
||||
}
|
||||
}
|
||||
return int64(len(totalAgentStatList)), list
|
||||
}
|
||||
|
||||
func (a *AgentSummary) GetAgentSummaryStats(outType OutputStatListType, pageNum int64, pageSize int64) (int64, proto.AgentSummaryStatHomeList) {
|
||||
totalAgentStatList := make(AgentDeductedStatList, 0)
|
||||
channelList := make([]*channelmod.ChannelInfo, 0)
|
||||
switch outType {
|
||||
case OutputStatListTypeSelf:
|
||||
channelList = append(channelList, a.SelfAgent.ChannelInfo)
|
||||
totalAgentStatList = append(totalAgentStatList, a.SelfStats...)
|
||||
case OutputStatListTypeChild:
|
||||
for _, node := range a.SelfAgent.Children {
|
||||
channelList = append(channelList, node.ChannelInfo)
|
||||
}
|
||||
totalAgentStatList = append(totalAgentStatList, a.ChildStats...)
|
||||
default:
|
||||
channelList = append(channelList, a.SelfAgent.ChannelInfo)
|
||||
for _, node := range a.SelfAgent.Children {
|
||||
channelList = append(channelList, node.ChannelInfo)
|
||||
}
|
||||
totalAgentStatList = append(totalAgentStatList, a.SelfStats...)
|
||||
totalAgentStatList = append(totalAgentStatList, a.ChildStats...)
|
||||
}
|
||||
// 按渠道进行汇总
|
||||
summaryList := make(proto.AgentSummaryStatHomeList, 0)
|
||||
for _, channel := range channelList {
|
||||
summary := &proto.AgentSummaryStatHome{
|
||||
Channel: channel.Channel,
|
||||
ParentAgent: channel.ParentAgent,
|
||||
ChildCount: channel.ChildCount,
|
||||
TotalStat: &proto.StatDataDetail{},
|
||||
TodayStat: &proto.StatDataDetail{},
|
||||
WeekStat: &proto.StatDataDetail{},
|
||||
MonthStat: &proto.StatDataDetail{},
|
||||
YearStat: &proto.StatDataDetail{},
|
||||
}
|
||||
summaryList = append(summaryList, summary)
|
||||
}
|
||||
// 统计日周月年数据
|
||||
nowTime := time.Now()
|
||||
for _, summary := range summaryList {
|
||||
for _, stat := range totalAgentStatList {
|
||||
if summary.Channel == stat.Channel {
|
||||
AccumulateSummaryStat(summary, stat, nowTime, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 处理排序,收益多的靠前
|
||||
sort.Sort(summaryList)
|
||||
// 处理分页输出
|
||||
list := GetAgentSummaryStatListPageData(summaryList, pageNum, pageSize)
|
||||
// 添加app名字,CAP屏蔽充值,CPS屏蔽新增
|
||||
for _, item := range list {
|
||||
item.AppName = a.AppMap.GetAppName(item.AppId)
|
||||
if item.Channel == a.ChannelInfo.Channel {
|
||||
item.DivideRate = 100
|
||||
}
|
||||
}
|
||||
return int64(len(summaryList)), list
|
||||
}
|
||||
|
||||
func AccumulateSummaryStat(base *proto.AgentSummaryStatHome, stat *proto.AgentDeductedStat, today time.Time, ruleData bool) {
|
||||
// 时间范围
|
||||
now.WeekStartDay = time.Monday
|
||||
Now := now.With(today.In(time.Local))
|
||||
todayBegin := Now.BeginningOfDay()
|
||||
todayEnd := Now.EndOfDay()
|
||||
weekBegin := Now.BeginningOfWeek()
|
||||
monthBegin := Now.BeginningOfMonth()
|
||||
yearBegin := Now.BeginningOfYear()
|
||||
// 复制信息
|
||||
base.AppId = stat.AppId
|
||||
base.AppName = stat.AppName
|
||||
base.Settlement = stat.Settlement
|
||||
base.CPAPrice = stat.CPAPrice
|
||||
base.CPSRate = stat.CPSRate
|
||||
base.DivideRate = stat.DivideRate
|
||||
// 全部数据累加
|
||||
AccumulateStatData(base.TotalStat, stat, ruleData)
|
||||
if (stat.SumDate.Equal(todayBegin) || stat.SumDate.After(todayBegin)) && (stat.SumDate.Equal(todayEnd) || stat.SumDate.Before(todayEnd)) {
|
||||
AccumulateStatData(base.TodayStat, stat, ruleData)
|
||||
}
|
||||
if (stat.SumDate.Equal(weekBegin) || stat.SumDate.After(weekBegin)) && (stat.SumDate.Equal(todayEnd) || stat.SumDate.Before(todayEnd)) {
|
||||
AccumulateStatData(base.WeekStat, stat, ruleData)
|
||||
}
|
||||
if (stat.SumDate.Equal(monthBegin) || stat.SumDate.After(monthBegin)) && (stat.SumDate.Equal(todayEnd) || stat.SumDate.Before(todayEnd)) {
|
||||
AccumulateStatData(base.MonthStat, stat, ruleData)
|
||||
}
|
||||
if (stat.SumDate.Equal(yearBegin) || stat.SumDate.After(yearBegin)) && (stat.SumDate.Equal(todayEnd) || stat.SumDate.Before(todayEnd)) {
|
||||
AccumulateStatData(base.YearStat, stat, ruleData)
|
||||
}
|
||||
}
|
||||
|
||||
func GetAgentChannelStatListPageData(list []*proto.AgentDeductedStat, pageNum int64, pageSize int64) []*proto.AgentDeductedStat {
|
||||
start, end := GetPageRange(len(list), int(pageNum), int(pageSize))
|
||||
return list[start:end]
|
||||
}
|
||||
|
||||
func GetAgentSummaryStatListPageData(list proto.AgentSummaryStatHomeList, pageNum int64, pageSize int64) proto.AgentSummaryStatHomeList {
|
||||
start, end := GetPageRange(len(list), int(pageNum), int(pageSize))
|
||||
return list[start:end]
|
||||
}
|
||||
|
||||
func GetAllAgentStatDict(ctx context.Context, channel string, appId *int32, startTime, endTime *time.Time) (*channelmod.ChannelInfo, SourceAgentStatMap, error) {
|
||||
// 获取渠道信息
|
||||
checkFilter := bson.M{channelmod.FN.ChannelInfo.Channel: channel}
|
||||
channelInfo, err := channelmod.FindOneChannelInfo(ctx, checkFilter)
|
||||
if err != nil || channelInfo.Channel != channel {
|
||||
return nil, nil, err
|
||||
}
|
||||
// 获取一级渠道的所有子孙数据
|
||||
var channelTop string
|
||||
if channelInfo.Type.IsTop() {
|
||||
channelTop = channelInfo.Channel
|
||||
} else {
|
||||
channelTop = channelInfo.ParentChannel
|
||||
}
|
||||
srcfilter := bson.M{
|
||||
channelmod.FN.ChannelStat.Type: bson.M{"$gte": channelInfo.Type},
|
||||
"$or": bson.A{
|
||||
bson.M{channelmod.FN.ChannelStat.Channel: channelTop},
|
||||
bson.M{channelmod.FN.ChannelStat.ParentChannel: channelTop},
|
||||
}}
|
||||
if appId != nil {
|
||||
srcfilter[channelmod.FN.ChannelStat.AppId] = *appId
|
||||
}
|
||||
if startTime != nil && endTime != nil {
|
||||
srcfilter[channelmod.FN.ChannelStat.SumDate] = bson.M{"$gte": *startTime, "$lte": *endTime}
|
||||
}
|
||||
srcList, err := channelmod.FindManyChannelStat(ctx, srcfilter)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
srcDict := make(SourceAgentStatMap)
|
||||
types := channelmod.GetAllChannelTypes()
|
||||
for _, t := range types {
|
||||
srcDict[t] = make(map[string]ChannelAgentStatList)
|
||||
}
|
||||
for _, stat := range srcList {
|
||||
stat.CorrectValidData()
|
||||
stat.CalcIncomeRate()
|
||||
aStat := &AgentChannelStat{
|
||||
ChannelStat: *stat,
|
||||
ChildValidDirectCount: 0,
|
||||
ChildValidPayMoney: 0,
|
||||
ChildChannelStats: make([]*AgentChannelStat, 0),
|
||||
}
|
||||
srcDict[stat.Type][stat.Channel] = append(srcDict[stat.Type][stat.Channel], aStat)
|
||||
}
|
||||
|
||||
return channelInfo, srcDict, nil
|
||||
}
|
||||
Reference in New Issue
Block a user