forked from all_user/stat_center
Initial commit
This commit is contained in:
@@ -0,0 +1,717 @@
|
||||
package statSer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"stat/api/proto"
|
||||
"stat/common/log"
|
||||
"stat/common/stdLog"
|
||||
"stat/common/utils"
|
||||
"stat/models/channelCodeBlocStatMod"
|
||||
"stat/models/channelmod"
|
||||
"time"
|
||||
|
||||
"github.com/360EntSecGroup-Skylar/excelize"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
// // 获取渠道码统计信息列表
|
||||
// func ListChannelCodeStat(ctx context.Context, param proto.ListChannelCodeStatReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
// resp := proto.ListChannelCodeStatRes{
|
||||
// Total: 0,
|
||||
// List: make([]proto.ChannelCodeStatInfo, 0),
|
||||
// }
|
||||
|
||||
// // 获取需要过滤的渠道信息
|
||||
// channels1 := make([]string, 0)
|
||||
// if param.Channel != nil {
|
||||
// // 获取渠道信息
|
||||
// channelInfo, err := channelmod.GetChannelInfoByChannel(ctx, *param.Channel)
|
||||
// if err != nil {
|
||||
// code = stdLog.ChannelNotExists
|
||||
// return code, data, err
|
||||
// }
|
||||
|
||||
// if channelInfo.Channel == "" {
|
||||
// code = stdLog.Success
|
||||
// return code, resp, nil
|
||||
// }
|
||||
|
||||
// // 获取子渠道
|
||||
// if channelInfo.ParentChannel == "" {
|
||||
// chList, err := channelmod.GetAllChildChannel(ctx, channelInfo.Channel)
|
||||
// if err != nil {
|
||||
// code = stdLog.Failure
|
||||
// return code, data, err
|
||||
// }
|
||||
|
||||
// for _, v := range chList {
|
||||
// channels1 = append(channels1, v.Channel)
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// channels1 = append(channels1, channelInfo.Channel)
|
||||
// }
|
||||
|
||||
// channels2 := make([]string, 0)
|
||||
// // 根据渠道备注,获取渠道信息
|
||||
// if param.ChannelRemark != nil {
|
||||
// // 获取渠道
|
||||
// chList, err := channelmod.GetChannelByRemark(ctx, *param.ChannelRemark)
|
||||
// if err != nil {
|
||||
// code = stdLog.Failure
|
||||
// return code, data, err
|
||||
// }
|
||||
|
||||
// if len(chList) == 0 {
|
||||
// code = stdLog.Success
|
||||
// return code, resp, nil
|
||||
// }
|
||||
|
||||
// for _, v1 := range chList {
|
||||
// // 获取子渠道
|
||||
// if v1.ParentChannel == "" && len(v1.Channel) > 0 {
|
||||
// chList, err := channelmod.GetAllChildChannel(ctx, v1.Channel)
|
||||
// if err != nil {
|
||||
// code = stdLog.Failure
|
||||
// return code, data, err
|
||||
// }
|
||||
|
||||
// for _, v2 := range chList {
|
||||
// channels2 = append(channels2, v2.Channel)
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// channels2 = append(channels2, v1.Channel)
|
||||
// }
|
||||
// }
|
||||
|
||||
// channels := make([]string, 0)
|
||||
// // 合并
|
||||
// if param.Channel != nil && param.ChannelRemark != nil {
|
||||
// for _, ch1 := range channels1 {
|
||||
// for _, ch2 := range channels2 {
|
||||
// if ch1 == ch2 {
|
||||
// channels = append(channels, ch1)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// } else if param.Channel != nil && param.ChannelRemark == nil {
|
||||
// channels = channels1
|
||||
// } else if param.Channel == nil && param.ChannelRemark != nil {
|
||||
// channels = channels2
|
||||
// }
|
||||
|
||||
// codes1 := make([]string, 0)
|
||||
// // 获取渠道的渠道码
|
||||
// if len(channels) > 0 {
|
||||
// codeList, err := channelCodeMod.GetChannelCodesByChannels(ctx, channels)
|
||||
// if err != nil {
|
||||
// code = stdLog.Failure
|
||||
// return code, data, err
|
||||
// }
|
||||
// for _, v := range codeList {
|
||||
// codes1 = append(codes1, v.ChannelCode)
|
||||
// }
|
||||
// }
|
||||
|
||||
// codes := make([]string, 0)
|
||||
// // 只搜索渠道码
|
||||
// if param.ChannelCode != nil && param.Channel == nil && param.ChannelRemark == nil {
|
||||
// codes = append(codes, *param.ChannelCode)
|
||||
// } else if param.ChannelCode != nil && (param.Channel != nil || param.ChannelRemark != nil) {
|
||||
// codes2 := make([]string, 0)
|
||||
// for _, v := range codes1 {
|
||||
// if v == *param.ChannelCode {
|
||||
// codes2 = []string{*param.ChannelCode}
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
|
||||
// if len(codes2) == 0 {
|
||||
// code = stdLog.Success
|
||||
// return code, resp, nil
|
||||
// }
|
||||
// codes = codes2
|
||||
// } else {
|
||||
// codes = codes1
|
||||
// }
|
||||
|
||||
// skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
// total, statList, err := channelCodeStatMod.GetChannelCodeStatList(ctx, codes, param.AppId, param.StartTime, param.EndTime, skip, limit)
|
||||
// if err != nil {
|
||||
// code = stdLog.Failure
|
||||
// return
|
||||
// }
|
||||
|
||||
// appIds := make([]int32, 0)
|
||||
// for _, v := range statList {
|
||||
// appIds = append(appIds, v.AppId)
|
||||
// }
|
||||
|
||||
// appInfoMap, err := channelSer.MakeAppInfosMapByIds(ctx, appIds)
|
||||
// if err != nil {
|
||||
// code = stdLog.Failure
|
||||
// return
|
||||
// }
|
||||
|
||||
// codeList, err := channelCodeMod.GetChannelCodesByIds(ctx, appIds)
|
||||
// if err != nil {
|
||||
// code = stdLog.Failure
|
||||
// return
|
||||
// }
|
||||
|
||||
// appInfoCodeMap := make(map[string]*channelCodeMod.ChannelCode)
|
||||
// for _, v := range codeList {
|
||||
// _v := v
|
||||
// appInfoCodeMap[v.ChannelCode+fmt.Sprintf("%d", v.AppId)] = &_v
|
||||
// }
|
||||
|
||||
// for _, v := range statList {
|
||||
// appName := ""
|
||||
// if appInfo, ok := appInfoMap[v.AppId]; ok {
|
||||
// appName = appInfo.Name
|
||||
// }
|
||||
|
||||
// channel := ""
|
||||
// settlement := channelmod.SettlementCPA
|
||||
// rate := float64(0.8)
|
||||
// if channelCodeInfo, ok := appInfoCodeMap[v.ChannelCode+fmt.Sprintf("%d", v.AppId)]; ok {
|
||||
// channel = channelCodeInfo.Channel
|
||||
// channelInfo, _ := channelmod.GetChannelInfoByChannel(ctx, channel)
|
||||
// if channelInfo.Channel == channel {
|
||||
// settlement = channelCodeInfo.Settlement
|
||||
// if settlement == channelmod.SettlementCPS {
|
||||
// rate = float64(channelInfo.CPSRate) / 100
|
||||
// } else {
|
||||
// rate = float64(channelInfo.CPAPrice)
|
||||
// }
|
||||
// }
|
||||
// } else { // 官方活没收益
|
||||
// rate = float64(200)
|
||||
// }
|
||||
|
||||
// tmp := proto.ChannelCodeStatInfo{
|
||||
// SumDate: v.SumDate,
|
||||
// ChannelCode: v.ChannelCode,
|
||||
// AppId: v.AppId,
|
||||
// AppName: appName,
|
||||
// Channel: channel,
|
||||
// Settlement: settlement,
|
||||
// NewDirectCount: v.NewDirectCount,
|
||||
// NewFissionCount: v.NewFissionCount,
|
||||
// NewDeductionCount: v.NewDeductionCount,
|
||||
// DirectVisitCount: v.DirectVisitCount,
|
||||
// FissionVisitCount: v.FissionVisitCount,
|
||||
// Day1RetainRate: v.Day1RetainRate,
|
||||
// Day3RetainRate: v.Day3RetainRate,
|
||||
// Day7RetainRate: v.Day7RetainRate,
|
||||
// Recharge: v.DirectAmount,
|
||||
// FissionAmount: v.FissionAmount,
|
||||
// DeductionAmount: v.DeductionAmount,
|
||||
// NewRechargeCount: v.NewRechargeCount,
|
||||
// NewRechargeAmount: v.NewRechargeAmount,
|
||||
// LandPageVisitCount: v.LandPageVisitCount,
|
||||
// TotalAmount: v.DirectAmount + v.FissionAmount + v.DeductionAmount,
|
||||
// TotalNewCount: v.NewDirectCount + v.NewFissionCount + v.NewDeductionCount,
|
||||
// IncomeRate: float64(0.0),
|
||||
// UpdatedAt: v.UpdatedAt,
|
||||
// }
|
||||
|
||||
// if settlement == channelmod.SettlementCPS {
|
||||
// tmp.CPSRate = rate
|
||||
// channelIncome := float64(v.DirectAmount) * rate
|
||||
// if channelIncome > 0 {
|
||||
// tmp.IncomeRate, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", (float64(tmp.Recharge+tmp.DeductionAmount+tmp.FissionAmount))/channelIncome), 64)
|
||||
|
||||
// }
|
||||
// } else {
|
||||
// tmp.CPAPrice = rate / 100
|
||||
// channelIncome := float64(v.NewDirectCount) * rate
|
||||
// if channelIncome > 0 {
|
||||
// tmp.IncomeRate, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", (float64(tmp.Recharge+tmp.DeductionAmount+tmp.FissionAmount))/channelIncome), 64)
|
||||
// }
|
||||
// }
|
||||
// resp.List = append(resp.List, tmp)
|
||||
// }
|
||||
|
||||
// resp.Total = total
|
||||
|
||||
// // 总量
|
||||
|
||||
// TotalList, err := channelCodeStatMod.GetChannelCodeStatListTotal(ctx, codes, param.AppId, param.StartTime, param.EndTime)
|
||||
// if err != nil {
|
||||
// log.Error("GetChannelCodeStatListTotal", log.E(err))
|
||||
// code = stdLog.Failure
|
||||
// return
|
||||
// }
|
||||
// toatlSum := proto.ChannelCodeStatInfo{
|
||||
// IncomeRate: float64(0.0),
|
||||
// }
|
||||
// for _, valueInfo := range TotalList {
|
||||
// toatlSum.NewDirectCount += valueInfo.NewDirectCount
|
||||
// toatlSum.NewFissionCount += valueInfo.NewFissionCount
|
||||
// toatlSum.NewDeductionCount += valueInfo.NewDeductionCount
|
||||
// toatlSum.DirectVisitCount += valueInfo.DirectVisitCount
|
||||
// toatlSum.FissionVisitCount += valueInfo.FissionVisitCount
|
||||
// toatlSum.Day1RetainRate += valueInfo.Day1RetainRate
|
||||
// toatlSum.Day3RetainRate += valueInfo.Day3RetainRate
|
||||
// toatlSum.Day7RetainRate += valueInfo.Day7RetainRate
|
||||
// toatlSum.Recharge += valueInfo.DirectAmount
|
||||
// toatlSum.FissionAmount += valueInfo.FissionAmount
|
||||
// toatlSum.DeductionAmount += valueInfo.DeductionAmount
|
||||
// toatlSum.NewRechargeCount += valueInfo.NewRechargeCount
|
||||
// toatlSum.NewRechargeAmount += valueInfo.NewRechargeAmount
|
||||
// toatlSum.LandPageVisitCount += valueInfo.LandPageVisitCount
|
||||
// toatlSum.TotalAmount += (valueInfo.DirectAmount + valueInfo.FissionAmount + valueInfo.DeductionAmount)
|
||||
// toatlSum.TotalNewCount += (valueInfo.NewDirectCount + valueInfo.NewFissionCount + valueInfo.NewDeductionCount)
|
||||
// }
|
||||
|
||||
// resp.TotalInfo = toatlSum
|
||||
// data = resp
|
||||
// code = stdLog.Success
|
||||
// return
|
||||
// }
|
||||
|
||||
// // 代理商获取渠道码统计信息列表
|
||||
// func ListChannelCodeStatAgent(ctx context.Context, account string, param proto.ListChannelCodeStatAgentReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
// resp := proto.ListChannelCodeStatAgentRes{
|
||||
// Total: 0,
|
||||
// List: make([]proto.ChannelCodeStatAgentInfo, 0),
|
||||
// }
|
||||
|
||||
// // 获取渠道信息
|
||||
// channelInfo, err := channelmod.GetChannelInfoByAccount(ctx, account)
|
||||
// if err != nil || channelInfo.Channel == "" {
|
||||
// code = stdLog.AgentAccountNotExists
|
||||
// return
|
||||
// }
|
||||
|
||||
// // 获取子渠道
|
||||
// childChannels, err := channelmod.GetAllChildChannel(ctx, channelInfo.Channel)
|
||||
// if err != nil || channelInfo.Channel == "" {
|
||||
// code = stdLog.Failure
|
||||
// return
|
||||
// }
|
||||
// channels := make([]string, 0)
|
||||
// for _, v := range childChannels {
|
||||
// channels = append(channels, v.Channel)
|
||||
// }
|
||||
// channels = append(channels, channelInfo.Channel)
|
||||
|
||||
// // 获取渠道的渠道码
|
||||
// codeList, err := channelCodeMod.GetChannelCodesByChannels(ctx, channels)
|
||||
// if err != nil {
|
||||
// code = stdLog.Failure
|
||||
// return
|
||||
// }
|
||||
// codes := make([]string, 0)
|
||||
// channelCodeMap := make(map[string]string)
|
||||
|
||||
// if param.ChannelCode != nil {
|
||||
// codes = append(codes, *param.ChannelCode)
|
||||
// for _, v := range codeList {
|
||||
// channelCodeMap[v.ChannelCode+fmt.Sprintf("%d", v.AppId)] = v.Channel
|
||||
// }
|
||||
// } else {
|
||||
// for _, v := range codeList {
|
||||
// codes = append(codes, v.ChannelCode)
|
||||
// channelCodeMap[v.ChannelCode+fmt.Sprintf("%d", v.AppId)] = v.Channel
|
||||
// }
|
||||
// }
|
||||
|
||||
// skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
// total, statList, err := channelCodeStatMod.GetChannelCodeStatAgentList(ctx, codes, *param.AppId, param.StartTime, param.EndTime, skip, limit)
|
||||
// if err != nil {
|
||||
// code = stdLog.Failure
|
||||
// return
|
||||
// }
|
||||
|
||||
// for _, v := range statList {
|
||||
// channelName, ok := channelCodeMap[v.ChannelCode+fmt.Sprintf("%d", v.AppId)]
|
||||
// if !ok { // 只能查询渠道下面的渠道码
|
||||
// continue
|
||||
// }
|
||||
|
||||
// tmp := proto.ChannelCodeStatAgentInfo{
|
||||
// SumDate: v.SumDate,
|
||||
// ChannelCode: v.ChannelCode,
|
||||
// Channel: channelName,
|
||||
// NewDirectCount: v.NewDirectCount,
|
||||
// Recharge: v.DirectAmount,
|
||||
// }
|
||||
|
||||
// // CPA子渠道不显示充值金额
|
||||
// if channelInfo.ParentChannel != "" && channelInfo.Settlement == channelmod.SettlementCPA {
|
||||
// tmp.Recharge = 0
|
||||
// }
|
||||
|
||||
// resp.List = append(resp.List, tmp)
|
||||
// }
|
||||
|
||||
// totalStatList, err := channelCodeStatMod.GetChannelCodeStatAgentListTotal(ctx, codes, *param.AppId, param.StartTime, param.EndTime)
|
||||
// if err != nil {
|
||||
// code = stdLog.Failure
|
||||
// return
|
||||
// }
|
||||
// totalCount := int64(0)
|
||||
// totalAmount := int64(0)
|
||||
|
||||
// for _, v := range totalStatList {
|
||||
// _, ok := channelCodeMap[v.ChannelCode+fmt.Sprintf("%d", v.AppId)]
|
||||
// if !ok { // 只能查询渠道下面的渠道码
|
||||
// continue
|
||||
// }
|
||||
// // CPA子渠道不显示充值金额
|
||||
// if channelInfo.ParentChannel != "" && channelInfo.Settlement == channelmod.SettlementCPA {
|
||||
// totalAmount = 0
|
||||
// } else {
|
||||
// totalAmount += v.DirectAmount
|
||||
// }
|
||||
|
||||
// totalCount += v.NewDirectCount
|
||||
// }
|
||||
|
||||
// resp.Total = total
|
||||
// resp.TotalAmount = totalAmount
|
||||
// resp.TotalCount = totalCount
|
||||
|
||||
// data = resp
|
||||
// code = stdLog.Success
|
||||
// return
|
||||
// }
|
||||
|
||||
func CacheKey(channel *string, appId *int32, start, end *time.Time) string {
|
||||
key := ""
|
||||
if channel != nil {
|
||||
key += fmt.Sprintf("channel:%s;", *channel)
|
||||
} else {
|
||||
key += "channel:<nil>;"
|
||||
}
|
||||
if appId != nil {
|
||||
key += fmt.Sprintf("appId:%d;", *appId)
|
||||
} else {
|
||||
key += "appId:<nil>;"
|
||||
}
|
||||
if start != nil {
|
||||
key += fmt.Sprintf("start:%v;", *start)
|
||||
} else {
|
||||
key += "start:<nil>;"
|
||||
}
|
||||
if end != nil {
|
||||
key += fmt.Sprintf("end:%v;", *end)
|
||||
} else {
|
||||
key += "end:<nil>;"
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
// 获取渠道码统计信息列表(集团)
|
||||
func ListBlocChannelCodeStat(ctx context.Context, param *proto.BlocListChannelCodeStatReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
resp := proto.BlocListChannelCodeStatRes{
|
||||
Total: 0,
|
||||
List: make([]proto.BlocChannelCodeStatInfo, 0),
|
||||
}
|
||||
if param.Channel != nil && *param.Channel == channelmod.OfficialChannelDisplayName {
|
||||
tmp := channelmod.OfficialChannelName
|
||||
param.Channel = &tmp
|
||||
}
|
||||
|
||||
// 获取渠道的渠道码
|
||||
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
total, statList, err := channelCodeBlocStatMod.GetBlocChannelCodeBlocStatList(ctx, param.Channel, param.AppId, param.StartTime, param.EndTime, skip, limit)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
appIds := make([]int32, 0)
|
||||
for _, v := range statList {
|
||||
appIds = append(appIds, v.AppId)
|
||||
}
|
||||
|
||||
appInfoMap, err := MakeAppInfosMapByIds(ctx, appIds)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
childstatList := make([]*channelCodeBlocStatMod.ChannelCodeBlocStat, 0)
|
||||
|
||||
if param.WithChild != nil && param.Channel != nil && len(*param.Channel) > 0 {
|
||||
childChannelList, _ := channelmod.FindManyChannelInfo(ctx, bson.M{channelmod.FN.ChannelInfo.ParentChannel: *param.Channel})
|
||||
if len(childChannelList) > 0 {
|
||||
channelArray := make([]string, 0)
|
||||
for _, v := range childChannelList {
|
||||
channelArray = append(channelArray, v.Channel)
|
||||
}
|
||||
_, childstatList, _ = channelCodeBlocStatMod.GetBlocChannelCodeStatTotal(ctx, channelArray, param.AppId, param.StartTime, param.EndTime)
|
||||
}
|
||||
|
||||
// 汇总排序 (存在一级没有 二级存在的情况)
|
||||
for _, childinfo := range childstatList {
|
||||
find := false
|
||||
for _, v := range statList {
|
||||
if v.SumDate.Equal(childinfo.SumDate) {
|
||||
find = true
|
||||
}
|
||||
}
|
||||
if !find {
|
||||
childinfo.ChannelCode = *param.Channel
|
||||
statList = append(statList, childinfo)
|
||||
}
|
||||
}
|
||||
sort.Sort(statList)
|
||||
}
|
||||
// get channels
|
||||
channels := make([]string, 0, len(statList))
|
||||
for _, item := range statList {
|
||||
channels = append(channels, item.ChannelCode)
|
||||
}
|
||||
ruleMap, err := MakeRuleMap(ctx, channels)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
//组装 按照时间排序
|
||||
for _, v := range statList {
|
||||
appName := ""
|
||||
if appInfo, ok := appInfoMap[v.AppId]; ok {
|
||||
appName = appInfo.Name
|
||||
}
|
||||
|
||||
for _, childinfo := range childstatList {
|
||||
if v.SumDate.Equal(childinfo.SumDate) {
|
||||
v.NewDirectCount += childinfo.NewDirectCount
|
||||
v.NewFissionCount += childinfo.NewFissionCount
|
||||
v.NewDeductionCount += childinfo.NewDeductionCount
|
||||
v.DirectVisitCount += childinfo.DirectVisitCount
|
||||
v.FissionVisitCount += childinfo.FissionVisitCount
|
||||
v.DeductionAmount += childinfo.DeductionAmount
|
||||
v.DirectAmount += childinfo.DirectAmount
|
||||
v.FissionAmount += childinfo.FissionAmount
|
||||
}
|
||||
}
|
||||
|
||||
tmp := proto.BlocChannelCodeStatInfo{
|
||||
SumDate: v.SumDate,
|
||||
ChannelCode: channelmod.ChannelDisplayName(v.ChannelCode),
|
||||
AppId: v.AppId,
|
||||
AppName: appName,
|
||||
Channel: v.Channel,
|
||||
NewDirectCount: v.NewDirectCount,
|
||||
NewFissionCount: v.NewFissionCount,
|
||||
NewDeductionCount: v.NewDeductionCount,
|
||||
DirectVisitCount: v.DirectVisitCount,
|
||||
FissionVisitCount: v.FissionVisitCount,
|
||||
DeductionAmount: v.DeductionAmount,
|
||||
RechargeAmount: v.DirectAmount,
|
||||
FissionAmount: v.FissionAmount,
|
||||
UpdatedAt: v.UpdatedAt,
|
||||
}
|
||||
ruleinfo := ruleMap.GetRule(v.ChannelCode, v.AppId)
|
||||
if ruleinfo != nil {
|
||||
if ruleinfo.Settlement == channelmod.SettlementCPA {
|
||||
tmp.Settlement = fmt.Sprintf("CPA_%.2f", float64(ruleinfo.CPAPrice)/100)
|
||||
tmp.TodayIncome = tmp.NewDirectCount * ruleinfo.CPAPrice
|
||||
} else if ruleinfo.Settlement == channelmod.SettlementCPS {
|
||||
tmp.Settlement = fmt.Sprintf("CPS_%.2f", float64(ruleinfo.CPSRate)/100)
|
||||
tmp.TodayIncome = tmp.RechargeAmount * ruleinfo.CPSRate / 100
|
||||
} else if ruleinfo.Settlement == channelmod.SettlementCPT {
|
||||
tmp.Settlement = "CPT"
|
||||
} else if ruleinfo.Settlement == channelmod.SettlementCPC {
|
||||
tmp.Settlement = "CPC"
|
||||
}
|
||||
}
|
||||
|
||||
resp.List = append(resp.List, tmp)
|
||||
}
|
||||
|
||||
resp.Total = total
|
||||
|
||||
// 查询条件不为空时统计总量
|
||||
if param.Channel != nil || param.AppId != nil || (param.StartTime != nil && param.EndTime != nil) {
|
||||
// 总量
|
||||
TotalList, err := channelCodeBlocStatMod.GetBlocChannelCodeBlocStatListTotal(ctx, param.Channel, param.AppId, param.StartTime, param.EndTime)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return code, nil, err
|
||||
}
|
||||
// get channels
|
||||
channels = make([]string, 0, len(TotalList))
|
||||
for _, item := range TotalList {
|
||||
channels = append(channels, item.ChannelCode)
|
||||
}
|
||||
ruleMap, err = MakeRuleMap(ctx, channels)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return code, nil, err
|
||||
}
|
||||
toatlSum := &proto.BlocChannelCodeStatInfo{}
|
||||
for _, valueInfo := range TotalList {
|
||||
toatlSum.NewDirectCount += valueInfo.NewDirectCount
|
||||
toatlSum.NewFissionCount += valueInfo.NewFissionCount
|
||||
toatlSum.DirectVisitCount += valueInfo.DirectVisitCount
|
||||
toatlSum.FissionVisitCount += valueInfo.FissionVisitCount
|
||||
toatlSum.RechargeAmount += valueInfo.DirectAmount
|
||||
toatlSum.DeductionAmount += valueInfo.DeductionAmount
|
||||
toatlSum.NewDeductionCount += valueInfo.NewDeductionCount
|
||||
ruleinfo := ruleMap.GetRule(valueInfo.ChannelCode, valueInfo.AppId)
|
||||
if ruleinfo != nil {
|
||||
if ruleinfo.Settlement == channelmod.SettlementCPA {
|
||||
toatlSum.TodayIncome += valueInfo.NewDirectCount * ruleinfo.CPAPrice
|
||||
} else if ruleinfo.Settlement == channelmod.SettlementCPS {
|
||||
toatlSum.TodayIncome += valueInfo.DirectAmount * ruleinfo.CPSRate / 100
|
||||
}
|
||||
}
|
||||
}
|
||||
resp.TotalInfo = *toatlSum
|
||||
}
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
|
||||
func ListBlocChannelExport(ctx context.Context, param *proto.BlocListChannelCodeStatReq) (string, error) {
|
||||
if param.Channel != nil && *param.Channel == channelmod.OfficialChannelDisplayName {
|
||||
tmp := channelmod.OfficialChannelName
|
||||
param.Channel = &tmp
|
||||
}
|
||||
// 获取渠道的渠道码
|
||||
statList, err := channelCodeBlocStatMod.GetBlocChannelCodeBlocStatListTotal(ctx, param.Channel, param.AppId, param.StartTime, param.EndTime)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
appIds := make([]int32, 0)
|
||||
for _, v := range statList {
|
||||
appIds = append(appIds, v.AppId)
|
||||
}
|
||||
|
||||
appInfoMap, err := MakeAppInfosMapByIds(ctx, appIds)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// get channels
|
||||
channels := make([]string, 0, len(statList))
|
||||
for _, item := range statList {
|
||||
channels = append(channels, item.ChannelCode)
|
||||
}
|
||||
ruleMap, err := MakeRuleMap(ctx, channels)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
result := make([]*proto.BlocChannelCodeStatInfo, 0)
|
||||
for _, v := range statList {
|
||||
appName := ""
|
||||
if appInfo, ok := appInfoMap[v.AppId]; ok {
|
||||
appName = appInfo.Name
|
||||
}
|
||||
|
||||
tmp := &proto.BlocChannelCodeStatInfo{
|
||||
SumDate: v.SumDate,
|
||||
ChannelCode: channelmod.ChannelDisplayName(v.ChannelCode),
|
||||
AppId: v.AppId,
|
||||
AppName: appName,
|
||||
Channel: v.Channel,
|
||||
NewDirectCount: v.NewDirectCount,
|
||||
NewFissionCount: v.NewFissionCount,
|
||||
DirectVisitCount: v.DirectVisitCount,
|
||||
NewDeductionCount: v.NewDeductionCount,
|
||||
FissionVisitCount: v.FissionVisitCount,
|
||||
DeductionAmount: v.DeductionAmount,
|
||||
RechargeAmount: v.DirectAmount,
|
||||
FissionAmount: v.FissionAmount,
|
||||
UpdatedAt: v.UpdatedAt,
|
||||
}
|
||||
ruleinfo := ruleMap.GetRule(v.ChannelCode, v.AppId)
|
||||
if ruleinfo != nil {
|
||||
if ruleinfo.Settlement == channelmod.SettlementCPA {
|
||||
tmp.Settlement = fmt.Sprintf("CPA_%.2f", float64(ruleinfo.CPAPrice)/100)
|
||||
tmp.TodayIncome = tmp.NewDirectCount * ruleinfo.CPAPrice
|
||||
} else if ruleinfo.Settlement == channelmod.SettlementCPS {
|
||||
tmp.Settlement = fmt.Sprintf("CPS_%.2f", float64(ruleinfo.CPSRate)/100)
|
||||
tmp.TodayIncome = tmp.RechargeAmount * ruleinfo.CPSRate / 100
|
||||
} else if ruleinfo.Settlement == channelmod.SettlementCPT {
|
||||
tmp.Settlement = "CPT"
|
||||
} else if ruleinfo.Settlement == channelmod.SettlementCPC {
|
||||
tmp.Settlement = "CPC"
|
||||
}
|
||||
}
|
||||
result = append(result, tmp)
|
||||
}
|
||||
|
||||
filePath := fmt.Sprintf("./tmp/渠道列表-%s.xlsx", time.Now().Format("2006-01-02 15:04:05"))
|
||||
|
||||
if err := export(ctx, filePath, result); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return filePath, nil
|
||||
}
|
||||
|
||||
func export(ctx context.Context, rPath string, channelStatList []*proto.BlocChannelCodeStatInfo) error {
|
||||
f := excelize.NewFile()
|
||||
sheetName := "Sheet1"
|
||||
idx := f.NewSheet(sheetName)
|
||||
|
||||
var exportTransWaterTitle = map[string]string{}
|
||||
|
||||
exportTransWaterTitle = map[string]string{
|
||||
"A1": "日期",
|
||||
"B1": "渠道",
|
||||
"C1": "结算方式",
|
||||
"D1": "当日支出",
|
||||
"E1": "新增(直推)",
|
||||
"F1": "新增(裂变)",
|
||||
"G1": "新增(扣量)",
|
||||
"H1": "访问量",
|
||||
"I1": "直推充值金额",
|
||||
"J1": "裂变充值金额",
|
||||
}
|
||||
|
||||
for k, v := range exportTransWaterTitle {
|
||||
f.SetCellValue(sheetName, k, v)
|
||||
}
|
||||
|
||||
for k, v := range channelStatList {
|
||||
i := 'A' // i 不能超过Z,即列输不能超过26列,超出将出现bug
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.SumDate)
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.ChannelCode)
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.Settlement)
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), float64(v.TodayIncome)/100)
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.NewDirectCount)
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.NewFissionCount)
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.NewDeductionCount)
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.DirectVisitCount+v.FissionVisitCount)
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), float64(v.DeductionAmount)/100)
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), float64(v.FissionAmount)/100)
|
||||
}
|
||||
f.SetActiveSheet(idx)
|
||||
p, _ := os.Getwd()
|
||||
fileName := path.Join(p, rPath)
|
||||
|
||||
if err := f.SaveAs(fileName); err != nil {
|
||||
log.Error("srv_vipcode:export save file to disk failed",
|
||||
log.Any("fileName", fileName),
|
||||
log.E(err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,957 @@
|
||||
package statSer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"stat/api/proto"
|
||||
"stat/common/log"
|
||||
"stat/common/stdLog"
|
||||
"stat/common/utils"
|
||||
"stat/models/appInfoMod"
|
||||
"stat/models/blocDailystatmod"
|
||||
"stat/models/botdailyhourstat"
|
||||
"stat/models/channelmod"
|
||||
"stat/models/dailyhourstatmod"
|
||||
"stat/models/dailystatmod"
|
||||
"stat/models/minutestatmod"
|
||||
"stat/models/rechargemod"
|
||||
"stat/models/registermod"
|
||||
"stat/models/withdrawUserOrdermod"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/360EntSecGroup-Skylar/excelize"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// 获取日常统计信息列表
|
||||
func ListDailyStat(ctx context.Context, param proto.ListDailyStatReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
resp := &proto.ListDailyStatRes{
|
||||
Total: 0,
|
||||
TotalInfo: &proto.DailyStatInfo{},
|
||||
List: make([]*proto.DailyStatInfo, 0),
|
||||
}
|
||||
|
||||
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
total, statList, err := dailystatmod.GetDailyStatList(ctx, param.AppId, param.StartTime, param.EndTime, skip, limit)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
appIds := make([]int32, 0)
|
||||
for _, v := range statList {
|
||||
appIds = append(appIds, v.AppId)
|
||||
}
|
||||
|
||||
appInfoMap, err := MakeAppInfosMapByIds(ctx, appIds)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range statList {
|
||||
appName := ""
|
||||
if appInfo, ok := appInfoMap[v.AppId]; ok {
|
||||
appName = appInfo.Name
|
||||
}
|
||||
tmp := DailyStatToInfo(v)
|
||||
tmp.AppName = appName
|
||||
resp.List = append(resp.List, tmp)
|
||||
}
|
||||
|
||||
if param.AppId != nil || param.StartTime != nil || param.EndTime != nil {
|
||||
var count int
|
||||
err := dailystatmod.GetDailyStatTotalListShard(ctx, param.AppId, param.StartTime, param.EndTime, utils.GlobalShardMonth, func(item *dailystatmod.DailyStatMod) {
|
||||
count++
|
||||
tmp := DailyStatToInfo(item)
|
||||
DailyStatInfoAccumulate(resp.TotalInfo, tmp)
|
||||
})
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return code, nil, err
|
||||
}
|
||||
// 计算留存率平均值
|
||||
if count > 0 {
|
||||
resp.TotalInfo.Day1RetainRate = resp.TotalInfo.Day1RetainRate / float64(count)
|
||||
resp.TotalInfo.Day3RetainRate = resp.TotalInfo.Day3RetainRate / float64(count)
|
||||
resp.TotalInfo.Day7RetainRate = resp.TotalInfo.Day7RetainRate / float64(count)
|
||||
}
|
||||
}
|
||||
resp.Total = total
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
|
||||
// 获取日常统计信息列表
|
||||
func ListDailyStatExport(ctx context.Context, param proto.ListDailyStatReq) (string, error) {
|
||||
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
_, statList, err := dailystatmod.GetDailyStatList(ctx, param.AppId, param.StartTime, param.EndTime, skip, limit)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
filePath := fmt.Sprintf("./tmp/日常统计信息列表-%s.xlsx", time.Now().Format("2006-01-02 15:04:05"))
|
||||
if sErr := dailyStatexport(filePath, statList); sErr != nil {
|
||||
return "", sErr
|
||||
}
|
||||
return filePath, nil
|
||||
}
|
||||
|
||||
func dailyStatexport(rPath string, transInfos []*dailystatmod.DailyStatMod) error {
|
||||
f := excelize.NewFile()
|
||||
sheetName := "Sheet1"
|
||||
// 设置列宽
|
||||
f.SetColWidth("Sheet1", "A", "O", 20)
|
||||
// 设置表头行高
|
||||
f.SetRowHeight("Sheet1", 1, 30)
|
||||
// 设置表头样式
|
||||
headStyleID, _ := f.NewStyle(`{
|
||||
"font":{
|
||||
"color":"#333333",
|
||||
"bold":true,
|
||||
"size":16,
|
||||
"family":"arial"
|
||||
},
|
||||
"alignment":{
|
||||
"vertical":"center",
|
||||
"horizontal":"center"
|
||||
}
|
||||
}`)
|
||||
f.SetCellStyle("Sheet1", "A1", "O1", headStyleID)
|
||||
|
||||
idx := f.NewSheet(sheetName)
|
||||
var exportTransWaterTitle = map[string]string{
|
||||
"A1": "日期",
|
||||
"B1": "总日活",
|
||||
"C1": "android日活",
|
||||
"D1": "ios日活",
|
||||
"E1": "总新增",
|
||||
"F1": "android新增",
|
||||
"G1": "ios新增",
|
||||
"H1": "总充值",
|
||||
"I1": "android充值",
|
||||
"J1": "ios充值",
|
||||
"K1": "总新增H5",
|
||||
"L1": "渠道新增",
|
||||
"M1": "渠道总充值",
|
||||
"N1": "老用户总充值",
|
||||
"O1": "新用户总充值",
|
||||
"P1": "复充总金额",
|
||||
"Q1": "重充VIP总金额",
|
||||
"R1": "拉起订单数",
|
||||
"S1": "成功订单数",
|
||||
}
|
||||
for k, v := range exportTransWaterTitle {
|
||||
f.SetCellValue(sheetName, k, v)
|
||||
}
|
||||
for k, v := range transInfos {
|
||||
i := 'A' // i 不能超过Z,即列输不能超过26列,超出将出现bug
|
||||
date := v.SumDate.Local().Format("2006-01-02")
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), date) //日期
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.TotalVisitCount) //总日活
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.TotalVisitCount-(v.LightVisitCount+v.TodayH5VisitCount)) //android日活
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.LightVisitCount+v.TodayH5VisitCount) //ios日活
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.NewTotalCount) //总新增
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.NewTotalCount-(v.LightAddCount+v.H5AddCount)) //android总新增
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.LightAddCount+v.H5AddCount) //Ios总新增
|
||||
i++
|
||||
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), float64(v.TotalAmount)/100) //总充值
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), float64(v.TodayAndroidRecharge)/100) //android充值
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), float64(v.TotalAmount)/100-float64(v.TodayAndroidRecharge)/100) //ios充值
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.H5AddCount) //总新增H5
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.NewDistrictCount) //渠道新增
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), float64(v.TodayDistrictRecharge)/100) //渠道总充值
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), float64(v.TotalAmount-v.NewRechargeAmount)/100) //老用户总充值
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), float64(v.NewRechargeAmount)/100) //新用户总充值
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), float64(v.RepeatAmount)/100) //复充总金额
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), float64(v.RepeatVipMoney)/100) //重充VIP总金额
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.TotalRechargeOrder) //拉起订单数
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.SuccessRechargeOrder) //成功订单数
|
||||
}
|
||||
|
||||
f.SetActiveSheet(idx)
|
||||
p, _ := os.Getwd()
|
||||
fileName := path.Join(p, rPath)
|
||||
if err := f.SaveAs(fileName); err != nil {
|
||||
log.Error("SettlementInfo:export save file to disk failed",
|
||||
log.Any("fileName", fileName),
|
||||
log.E(err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取日常统计信息列表
|
||||
func BlocListDailyStat(ctx context.Context, param proto.ListBlocDailyStatReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
resp := proto.ListBlocDailyStatRes{
|
||||
Total: 0,
|
||||
List: make([]proto.BlocDailyStatInfo, 0),
|
||||
}
|
||||
|
||||
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
|
||||
total, statList, err := blocDailystatmod.GetBlocDailyStatList(ctx, param.AppId, param.StartTime, param.EndTime, skip, limit)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
appIds := make([]int32, 0)
|
||||
for _, v := range statList {
|
||||
appIds = append(appIds, v.AppId)
|
||||
}
|
||||
|
||||
appInfoMap, err := MakeAppInfosMapByIds(ctx, appIds)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return code, nil, err
|
||||
}
|
||||
|
||||
for _, v := range statList {
|
||||
appName := ""
|
||||
if appInfo, ok := appInfoMap[v.AppId]; ok {
|
||||
appName = appInfo.Name
|
||||
}
|
||||
|
||||
tmp := proto.BlocDailyStatInfo{
|
||||
SumDate: v.SumDate,
|
||||
AppId: v.AppId,
|
||||
AppName: appName,
|
||||
NewDirectCount: v.NewDirectCount,
|
||||
NewFissionCount: v.NewFissionCount,
|
||||
DirectVisitCount: v.DirectVisitCount,
|
||||
FissionVisitCount: v.FissionVisitCount,
|
||||
Day1RetainRate: v.Day1RetainRate,
|
||||
Day3RetainRate: v.Day3RetainRate,
|
||||
Day7RetainRate: v.Day7RetainRate,
|
||||
DirectAmount: v.DirectAmount,
|
||||
FissionAmount: v.FissionAmount,
|
||||
NewRechargeCount: v.NewRechargeCount,
|
||||
NewRechargeAmount: v.NewRechargeAmount,
|
||||
DaichongAmout: v.DaichongAmout,
|
||||
OnlineAmount: v.OnlineAmount,
|
||||
UserWithDrawAmount: v.UserWithDrawAmount,
|
||||
UserWithDrawPaymoneyAmount: v.UserWithDrawPaymoneyAmount,
|
||||
GameRechageAmount: v.GameRechageAmount,
|
||||
GameWithdrawAmount: v.GameWithdrawAmount,
|
||||
TotalRechargeCount: v.TotalRechargeCount,
|
||||
UpdatedAt: v.UpdatedAt,
|
||||
}
|
||||
|
||||
tmp.TotalVisitCount = v.DirectVisitCount + v.FissionVisitCount // 日活
|
||||
tmp.TotalAmount = v.DirectAmount + v.FissionAmount // 总充值
|
||||
tmp.TotalNewCount = v.NewDirectCount + v.NewFissionCount // 新增
|
||||
tmp.OldRechargeAmount = tmp.TotalAmount - tmp.NewRechargeAmount // 老用户充值
|
||||
total := v.DeductionAmountCount + v.DirectAmountCount + v.FissionAmountCount // 充值人数
|
||||
|
||||
if tmp.TotalAmount-tmp.DaichongAmout > 0 {
|
||||
tmp.OnlineAmount = tmp.TotalAmount - tmp.DaichongAmout
|
||||
}
|
||||
|
||||
if tmp.TotalNewCount != 0 {
|
||||
tmp.NewRechargeRate, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", (float64(v.NewRechargeCount)/float64(tmp.TotalNewCount))*100), 64)
|
||||
}
|
||||
|
||||
if tmp.TotalVisitCount != 0 {
|
||||
tmp.VisitRechargeRate, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", (float64(total)/float64(tmp.TotalVisitCount))*100), 64)
|
||||
}
|
||||
|
||||
if total != 0 {
|
||||
tmp.ARPPU = (tmp.DirectAmount + tmp.FissionAmount) / total // 金额
|
||||
}
|
||||
if tmp.TotalVisitCount != 0 {
|
||||
tmp.ARPU = tmp.TotalAmount / tmp.TotalVisitCount // 金额
|
||||
}
|
||||
|
||||
resp.List = append(resp.List, tmp)
|
||||
}
|
||||
|
||||
if param.AppId != nil || param.StartTime != nil || param.EndTime != nil {
|
||||
// 过滤条件至少有一个,不然不统计总数
|
||||
totalList, err := blocDailystatmod.GetBlocDailyStatListTotal(ctx, param.AppId, param.StartTime, param.EndTime)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return code, nil, err
|
||||
}
|
||||
for _, v := range totalList {
|
||||
resp.TotalInfo.NewDirectCount += v.NewDirectCount
|
||||
resp.TotalInfo.NewFissionCount += v.NewFissionCount
|
||||
resp.TotalInfo.DirectVisitCount += v.DirectVisitCount
|
||||
resp.TotalInfo.FissionVisitCount += v.FissionVisitCount
|
||||
resp.TotalInfo.DirectAmount += v.DirectAmount
|
||||
resp.TotalInfo.FissionAmount += v.FissionAmount
|
||||
resp.TotalInfo.NewRechargeCount += v.NewRechargeCount
|
||||
resp.TotalInfo.NewRechargeAmount += v.NewRechargeAmount
|
||||
resp.TotalInfo.DaichongAmout += v.DaichongAmout
|
||||
resp.TotalInfo.UserWithDrawAmount += v.UserWithDrawAmount
|
||||
resp.TotalInfo.UserWithDrawPaymoneyAmount += v.UserWithDrawPaymoneyAmount
|
||||
resp.TotalInfo.GameRechageAmount += v.GameRechageAmount
|
||||
resp.TotalInfo.GameWithdrawAmount += v.GameWithdrawAmount
|
||||
resp.TotalInfo.TotalRechargeCount += v.TotalRechargeCount
|
||||
}
|
||||
resp.TotalInfo.TotalVisitCount = resp.TotalInfo.DirectVisitCount + resp.TotalInfo.FissionVisitCount // 日活
|
||||
resp.TotalInfo.TotalAmount = resp.TotalInfo.DirectAmount + resp.TotalInfo.FissionAmount // 总充值
|
||||
resp.TotalInfo.TotalNewCount = resp.TotalInfo.NewDirectCount + resp.TotalInfo.NewFissionCount // 新增
|
||||
resp.TotalInfo.OldRechargeAmount = resp.TotalInfo.TotalAmount - resp.TotalInfo.NewRechargeAmount // 老用户充值
|
||||
if resp.TotalInfo.TotalAmount-resp.TotalInfo.DaichongAmout > 0 {
|
||||
resp.TotalInfo.OnlineAmount = resp.TotalInfo.TotalAmount - resp.TotalInfo.DaichongAmout
|
||||
}
|
||||
}
|
||||
resp.Total = total
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
|
||||
// 获取充值明细(集团)
|
||||
func BlocListRechargeDetailsInfo(ctx context.Context, param proto.ListBlocRechargeDetailsReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
resp := proto.ListBlocRechargeDetailsRes{
|
||||
Total: 0,
|
||||
List: make([]proto.BlocRechargeDetailsInfo, 0),
|
||||
}
|
||||
|
||||
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
total, RechagerList, err := rechargemod.GetBlocRechargeDetailsList(ctx, param.AppId, param.StartTime, param.EndTime, skip, limit)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
appIds := make([]int32, 0)
|
||||
appMap := make(map[int32]int32)
|
||||
for _, v := range RechagerList {
|
||||
if _, ok := appMap[v.AppId]; !ok {
|
||||
appMap[v.AppId] = v.AppId
|
||||
appIds = append(appIds, v.AppId)
|
||||
}
|
||||
}
|
||||
//fmt.Println(appIds)
|
||||
appInfoMap, err := MakeAppInfosMapByIds(ctx, appIds)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range RechagerList {
|
||||
appName := ""
|
||||
if appInfo, ok := appInfoMap[v.AppId]; ok {
|
||||
appName = appInfo.Name
|
||||
}
|
||||
|
||||
tmp := proto.BlocRechargeDetailsInfo{
|
||||
UserId: v.PromCode,
|
||||
AppName: appName,
|
||||
SysType: v.SysType,
|
||||
DevType: v.DevType,
|
||||
ChannelName: v.ChannelName,
|
||||
CID: v.CID,
|
||||
Type: v.Type,
|
||||
OrderId: v.OrderId,
|
||||
Money: v.Money,
|
||||
PayMoney: v.PayMoney,
|
||||
Status: 3,
|
||||
SuccessAt: v.SuccessAt,
|
||||
}
|
||||
resp.List = append(resp.List, tmp)
|
||||
}
|
||||
|
||||
resp.Total = total
|
||||
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
|
||||
// 获取日常统计信息列表
|
||||
func BlocListDailyTotalStat(ctx context.Context, param proto.ListBlocDailyStatTotalReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
resp := proto.ListBlocDailyStatTotalRes{
|
||||
Total: 0,
|
||||
List: make([]proto.BlocDailyStatTotalInfo, 0),
|
||||
}
|
||||
|
||||
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
|
||||
statList, err := blocDailystatmod.GetBlocDailyStatTotalList(ctx, param.StartTime, param.EndTime)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
count := int64(0)
|
||||
for _, v := range statList {
|
||||
if count >= skip && count <= skip+limit {
|
||||
tmp := proto.BlocDailyStatTotalInfo{
|
||||
SumDate: v.SumDate,
|
||||
NewDirectCount: v.NewDirectCount,
|
||||
NewFissionCount: v.NewFissionCount,
|
||||
DirectVisitCount: v.DirectVisitCount,
|
||||
FissionVisitCount: v.FissionVisitCount,
|
||||
DirectAmount: v.DirectAmount,
|
||||
FissionAmount: v.FissionAmount,
|
||||
NewRechargeCount: v.NewRechargeCount,
|
||||
NewRechargeAmount: v.NewRechargeAmount,
|
||||
DaichongAmout: v.DaichongAmout,
|
||||
OnlineAmount: v.OnlineAmount,
|
||||
UserWithDrawAmount: v.UserWithDrawAmount,
|
||||
UserWithDrawPaymoneyAmount: v.UserWithDrawPaymoneyAmount,
|
||||
GameRechageAmount: v.GameRechageAmount,
|
||||
GameWithdrawAmount: v.GameWithdrawAmount,
|
||||
TotalRechargeCount: v.TotalRechargeCount,
|
||||
}
|
||||
|
||||
tmp.TotalVisitCount = v.DirectVisitCount + v.FissionVisitCount // 日活
|
||||
tmp.TotalAmount = v.DirectAmount + v.FissionAmount // 总充值
|
||||
tmp.TotalNewCount = v.NewDirectCount + v.NewFissionCount // 新增
|
||||
tmp.OldRechargeAmount = tmp.TotalAmount - tmp.NewRechargeAmount // 老用户充值
|
||||
|
||||
if tmp.TotalAmount-tmp.DaichongAmout > 0 {
|
||||
tmp.OnlineAmount = tmp.TotalAmount - tmp.DaichongAmout
|
||||
}
|
||||
|
||||
resp.List = append(resp.List, tmp)
|
||||
}
|
||||
count += 1
|
||||
}
|
||||
|
||||
resp.Total = count
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
|
||||
// 获取充值明细(集团)
|
||||
func BlocListRegisterDetailsInfo(ctx context.Context, param proto.ListBlocRegisterDetailsReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
resp := proto.ListBlocRegisterDetailsRes{
|
||||
Total: 0,
|
||||
List: make([]proto.BlocRegisterDetailsInfo, 0),
|
||||
}
|
||||
|
||||
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
total, RechagerList, err := registermod.GetBlocRegisterDetailsList(ctx, param.AppId, param.StartTime, param.EndTime, skip, limit)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
appIds := make([]int32, 0)
|
||||
appMap := make(map[int32]int32)
|
||||
for _, v := range RechagerList {
|
||||
if _, ok := appMap[v.AppId]; !ok {
|
||||
appMap[v.AppId] = v.AppId
|
||||
appIds = append(appIds, v.AppId)
|
||||
}
|
||||
}
|
||||
|
||||
appInfoMap, err := MakeAppInfosMapByIds(ctx, appIds)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range RechagerList {
|
||||
appName := ""
|
||||
if appInfo, ok := appInfoMap[v.AppId]; ok {
|
||||
appName = appInfo.Name
|
||||
}
|
||||
|
||||
tmp := proto.BlocRegisterDetailsInfo{
|
||||
UserId: v.PromCode,
|
||||
AppName: appName,
|
||||
SysType: v.SysType,
|
||||
DevType: v.DevType,
|
||||
Mobile: v.Mobile,
|
||||
IP: v.IP,
|
||||
Name: v.Name,
|
||||
IsDirect: v.IsDirect,
|
||||
RegisterTime: v.RegisterTime,
|
||||
}
|
||||
resp.List = append(resp.List, tmp)
|
||||
}
|
||||
|
||||
resp.Total = total
|
||||
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
|
||||
// 获取提现明细(集团)
|
||||
func BlocListWithdrawDetailsInfo(ctx context.Context, param proto.ListBlocWithdrawDetailsReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
resp := proto.ListBlocWithdrawDetailsRes{
|
||||
Total: 0,
|
||||
List: make([]proto.ListBlocWithdrawDetailsInfo, 0),
|
||||
}
|
||||
|
||||
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
total, RechagerList, err := withdrawUserOrdermod.GetBlocUserWithdrawOrderList(ctx, param.AppId, param.StartTime, param.EndTime, skip, limit)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
appIds := make([]int32, 0)
|
||||
appMap := make(map[int32]int32)
|
||||
for _, v := range RechagerList {
|
||||
if _, ok := appMap[v.AppId]; !ok {
|
||||
appMap[v.AppId] = v.AppId
|
||||
appIds = append(appIds, v.AppId)
|
||||
}
|
||||
}
|
||||
//fmt.Println(appIds)
|
||||
appInfoMap, err := MakeAppInfosMapByIds(ctx, appIds)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range RechagerList {
|
||||
appName := ""
|
||||
if appInfo, ok := appInfoMap[v.AppId]; ok {
|
||||
appName = appInfo.Name
|
||||
}
|
||||
|
||||
tmp := proto.ListBlocWithdrawDetailsInfo{
|
||||
UID: v.PromCode,
|
||||
AppName: appName,
|
||||
Name: v.Name,
|
||||
Amount: v.Amount,
|
||||
Money: v.Money,
|
||||
PayMoney: v.PayMoney,
|
||||
PayType: v.PayType,
|
||||
OID: v.OID,
|
||||
ActName: v.ActName,
|
||||
Act: v.Act,
|
||||
UserIP: v.UserIP,
|
||||
DeviceType: v.DeviceType,
|
||||
DevID: v.DevID,
|
||||
Status: v.Status,
|
||||
StatusDesc: v.StatusDesc,
|
||||
SuccessAt: v.SuccessAt,
|
||||
ReceivedAt: v.ReceivedAt,
|
||||
}
|
||||
resp.List = append(resp.List, tmp)
|
||||
}
|
||||
|
||||
resp.Total = total
|
||||
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
|
||||
// 获取提现明细(集团)
|
||||
func ListBlocRechargeChannelInfo(ctx context.Context, param proto.ListBlocRechargeChannelReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
resp := proto.ListBlocRechargeChannelRes{
|
||||
Total: 0,
|
||||
List: make([]proto.ListBlocRechargeChannelInfo, 0),
|
||||
}
|
||||
|
||||
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
|
||||
statList, err := blocDailystatmod.GetBlocDailyStatTotalList(ctx, param.StartTime, param.EndTime)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
count := int64(0)
|
||||
for _, v := range statList {
|
||||
if count >= skip && count <= skip+limit {
|
||||
tmp := proto.ListBlocRechargeChannelInfo{
|
||||
SumDate: v.SumDate,
|
||||
ChannelName: "大白鲨",
|
||||
BlocOrderMoney: v.DirectAmount + v.FissionAmount,
|
||||
BlocChannelRate: 12,
|
||||
}
|
||||
|
||||
resp.List = append(resp.List, tmp)
|
||||
}
|
||||
count += 1
|
||||
}
|
||||
|
||||
resp.Total = count
|
||||
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
|
||||
func ListMinuteStat(ctx context.Context, param proto.ListMinuteStatReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
resp := proto.ListMinuteStatRes{
|
||||
TodayGraphList: make([]proto.MinuteStatInfo, 0),
|
||||
}
|
||||
|
||||
// 获取app信息
|
||||
appInfo, err := appInfoMod.GetAppInfoById(ctx, *param.AppId)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
resp.AppInfo = proto.AppInfoRes{
|
||||
AppId: appInfo.AppId,
|
||||
Name: appInfo.Name,
|
||||
LandPages: appInfo.LandPages,
|
||||
IconImg: appInfo.IconImg,
|
||||
CreatedAt: appInfo.CreatedAt,
|
||||
UpdatedAt: appInfo.UpdatedAt,
|
||||
}
|
||||
|
||||
start := *param.SumDate
|
||||
end := start.AddDate(0, 0, 1)
|
||||
|
||||
todayStatList, err := minutestatmod.GetMinuteStatList(ctx, start, end, *param.AppId)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range todayStatList {
|
||||
tmp := proto.MinuteStatInfo{
|
||||
SumDate: v.SumDate,
|
||||
NewCount: v.NewCount,
|
||||
AndroidAddCount: v.AndroidAddCount,
|
||||
IosAddCount: v.IosAddCount,
|
||||
H5AddCount: v.H5AddCount,
|
||||
RechargetCount: v.RechargetCount,
|
||||
RechargetMoney: v.RechargetMoney,
|
||||
AccessCount: v.AccessCount,
|
||||
AndroidAccessCount: v.AndroidAccessCount,
|
||||
IosAccessCount: v.IosAccessCount + v.H5AccessCount,
|
||||
LandpageAndroidClick: v.LandpageAndroidClick,
|
||||
LandpageIosAppstoreClick: v.LandpageIosAppstoreClick,
|
||||
LandpageIosAthorClick: v.LandpageIosAthorClick,
|
||||
LandpageIosH5Click: v.LandpageIosH5Click,
|
||||
LightGuestAddCount: v.LightGuestAddCount,
|
||||
}
|
||||
|
||||
resp.TodayGraphList = append(resp.TodayGraphList, tmp)
|
||||
}
|
||||
|
||||
compareTime := start.AddDate(0, 0, -1)
|
||||
if param.CompareTime != nil {
|
||||
compareTime = *param.CompareTime
|
||||
}
|
||||
compareTimeEnd := compareTime.AddDate(0, 0, 1)
|
||||
yesterdayStatList, err := minutestatmod.GetMinuteStatList(ctx, compareTime, compareTimeEnd, *param.AppId)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range yesterdayStatList {
|
||||
tmp := proto.MinuteStatInfo{
|
||||
SumDate: v.SumDate,
|
||||
NewCount: v.NewCount,
|
||||
AndroidAddCount: v.AndroidAddCount,
|
||||
IosAddCount: v.IosAddCount,
|
||||
H5AddCount: v.H5AddCount,
|
||||
RechargetCount: v.RechargetCount,
|
||||
RechargetMoney: v.RechargetMoney,
|
||||
AccessCount: v.AccessCount,
|
||||
AndroidAccessCount: v.AndroidAccessCount,
|
||||
IosAccessCount: v.IosAccessCount + v.H5AccessCount,
|
||||
LandpageAndroidClick: v.LandpageAndroidClick,
|
||||
LandpageIosAppstoreClick: v.LandpageIosAppstoreClick,
|
||||
LandpageIosAthorClick: v.LandpageIosAthorClick,
|
||||
LandpageIosH5Click: v.LandpageIosH5Click,
|
||||
LightGuestAddCount: v.LightGuestAddCount,
|
||||
}
|
||||
|
||||
resp.YesterdayGraphList = append(resp.YesterdayGraphList, tmp)
|
||||
}
|
||||
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
|
||||
// 获取日常统计信息列表
|
||||
func ListDailyHourStat(ctx context.Context, param *proto.ListDailyHourStatReq) (code stdLog.CodeType, data *proto.ListDailyHourStatRes, err error) {
|
||||
resp := &proto.ListDailyHourStatRes{
|
||||
Total: 0,
|
||||
List: make([]*proto.DailyHourStatInfo, 0),
|
||||
}
|
||||
filter := bson.M{}
|
||||
opt := &options.FindOptions{}
|
||||
opt.SetSort(bson.M{dailyhourstatmod.FN.DailyHourStat.SumDate: -1})
|
||||
opt.SetSkip((param.PageNum - 1) * param.PageSize)
|
||||
opt.SetLimit(param.PageSize)
|
||||
|
||||
if param.AppId != nil {
|
||||
filter[dailyhourstatmod.FN.DailyHourStat.AppId] = *param.AppId
|
||||
}
|
||||
if param.StartTime != nil && param.EndTime != nil {
|
||||
filter[dailyhourstatmod.FN.DailyHourStat.SumDate] = bson.M{"$gte": *param.StartTime, "$lt": *param.EndTime}
|
||||
}
|
||||
if param.SumHour != nil {
|
||||
filter[dailyhourstatmod.FN.DailyHourStat.SumHour] = *¶m.SumHour
|
||||
}
|
||||
|
||||
total, _ := dailyhourstatmod.CountDailyHourStats(ctx, filter)
|
||||
|
||||
statList, err := dailyhourstatmod.FindManyDailyHourStat(ctx, filter, opt)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
appIds := make([]int32, 0)
|
||||
for _, v := range statList {
|
||||
appIds = append(appIds, v.AppId)
|
||||
}
|
||||
|
||||
appInfoMap, err := MakeAppInfosMapByIds(ctx, appIds)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range statList {
|
||||
appName := ""
|
||||
if appInfo, ok := appInfoMap[v.AppId]; ok {
|
||||
appName = appInfo.Name
|
||||
}
|
||||
tmp := DailyHourStatToInfo(v)
|
||||
tmp.AppName = appName
|
||||
resp.List = append(resp.List, tmp)
|
||||
}
|
||||
resp.Total = total
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
|
||||
// 获取日常统计信息列表
|
||||
func ListDailyHourStatExport(ctx context.Context, param *proto.ListDailyHourStatReq) (*bytes.Buffer, error) {
|
||||
_, data, err := ListDailyHourStat(ctx, param)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ExportDailyHourStat(data.List)
|
||||
}
|
||||
|
||||
func ListHourStatLine(ctx context.Context, param proto.ListHourStatLineReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
resp := proto.ListHourStatLineResp{
|
||||
TodayGraphList: make([]proto.ListHourStatLineInfo, 0),
|
||||
YesterdayGraphList: make([]proto.ListHourStatLineInfo, 0),
|
||||
}
|
||||
|
||||
// 获取app信息
|
||||
appInfo, err := appInfoMod.GetAppInfoById(ctx, *param.AppId)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
resp.AppInfo = proto.AppInfoRes{
|
||||
AppId: appInfo.AppId,
|
||||
Name: appInfo.Name,
|
||||
LandPages: appInfo.LandPages,
|
||||
IconImg: appInfo.IconImg,
|
||||
CreatedAt: appInfo.CreatedAt,
|
||||
UpdatedAt: appInfo.UpdatedAt,
|
||||
}
|
||||
|
||||
start := *param.SumDate
|
||||
end := start.AddDate(0, 0, 1)
|
||||
|
||||
todayFilter := bson.M{
|
||||
"sumDate": bson.M{"$gte": start, "$lte": end},
|
||||
"appId": *param.AppId,
|
||||
}
|
||||
|
||||
todayStatList, err := botdailyhourstat.FindManyBotHourStat(ctx, todayFilter)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range todayStatList {
|
||||
tmp := proto.ListHourStatLineInfo{
|
||||
SumDate: v.SumDate,
|
||||
HourNewDistrict: v.HourStat.Register.Total.District.Count,
|
||||
HourNewWeb: v.HourStat.Register.Total.Web.Count,
|
||||
HourNewNormal: v.HourStat.Register.Total.Normal.Count,
|
||||
HourNew: v.HourStat.Register.Count(),
|
||||
HourAndroidNew: v.HourStat.Register.Android.Count(),
|
||||
HourIosNew: v.HourStat.Register.Ios.Count(),
|
||||
HourDistrictRecharge: v.HourStat.Recharge.Total.District.Value,
|
||||
HourWebRecharge: v.HourStat.Recharge.Total.Web.Value,
|
||||
HourNormalRecharge: v.HourStat.Recharge.Total.Normal.Value,
|
||||
HourAndroidRecharge: v.HourStat.Recharge.Android.Value(),
|
||||
HourIosRecharge: v.HourStat.Recharge.Ios.Value(),
|
||||
HourVipRecharge: v.HourStat.RechargeVip.Value(),
|
||||
HourDistrictVip: v.HourStat.RechargeVip.Total.District.Value,
|
||||
HourWebVip: v.HourStat.RechargeVip.Total.Web.Value,
|
||||
HourNormalVip: v.HourStat.RechargeVip.Total.Normal.Value,
|
||||
}
|
||||
|
||||
resp.TodayGraphList = append(resp.TodayGraphList, tmp)
|
||||
}
|
||||
|
||||
compareTime := start.AddDate(0, 0, -1)
|
||||
if param.CompareTime != nil {
|
||||
compareTime = *param.CompareTime
|
||||
}
|
||||
compareTimeEnd := compareTime.AddDate(0, 0, 1)
|
||||
yestodayFilter := bson.M{
|
||||
"sumDate": bson.M{"$gte": compareTime, "$lte": compareTimeEnd},
|
||||
"appId": *param.AppId,
|
||||
}
|
||||
|
||||
yesterdayStatList, err := botdailyhourstat.FindManyBotHourStat(ctx, yestodayFilter)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range yesterdayStatList {
|
||||
tmp := proto.ListHourStatLineInfo{
|
||||
SumDate: v.SumDate,
|
||||
HourNewDistrict: v.HourStat.Register.Total.District.Count,
|
||||
HourNewWeb: v.HourStat.Register.Total.Web.Count,
|
||||
HourNewNormal: v.HourStat.Register.Total.Normal.Count,
|
||||
HourNew: v.HourStat.Register.Count(),
|
||||
HourAndroidNew: v.HourStat.Register.Android.Count(),
|
||||
HourIosNew: v.HourStat.Register.Ios.Count(),
|
||||
HourDistrictRecharge: v.HourStat.Recharge.Total.District.Value,
|
||||
HourWebRecharge: v.HourStat.Recharge.Total.Web.Value,
|
||||
HourNormalRecharge: v.HourStat.Recharge.Total.Normal.Value,
|
||||
HourAndroidRecharge: v.HourStat.Recharge.Android.Value(),
|
||||
HourIosRecharge: v.HourStat.Recharge.Ios.Value(),
|
||||
HourVipRecharge: v.HourStat.RechargeVip.Value(),
|
||||
HourDistrictVip: v.HourStat.RechargeVip.Total.District.Value,
|
||||
HourWebVip: v.HourStat.RechargeVip.Total.Web.Value,
|
||||
HourNormalVip: v.HourStat.RechargeVip.Total.Normal.Value,
|
||||
}
|
||||
|
||||
resp.YesterdayGraphList = append(resp.YesterdayGraphList, tmp)
|
||||
}
|
||||
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
|
||||
// 获取日常统计信息列表
|
||||
func ChannelStatExport(ctx context.Context, param proto.ChannelStatExportReq) (string, error) {
|
||||
statfilter := bson.M{}
|
||||
opt := &options.FindOptions{}
|
||||
opt.SetSort(bson.M{channelmod.FN.ChannelStat.SumDate: -1})
|
||||
opt.SetLimit(5000)
|
||||
|
||||
if param.AppId != nil && len(*param.AppId) > 0 {
|
||||
statfilter[channelmod.FN.ChannelStat.AppId] = bson.M{"$in": *param.AppId}
|
||||
}
|
||||
|
||||
if param.Channel != nil {
|
||||
statfilter[channelmod.FN.ChannelStat.Channel] = *param.Channel
|
||||
}
|
||||
if param.StartTime != nil && param.EndTime != nil {
|
||||
statfilter[channelmod.FN.ChannelStat.SumDate] = bson.M{"$gte": *param.StartTime, "$lte": *param.EndTime}
|
||||
}
|
||||
|
||||
statList, err := channelmod.FindManyChannelStat(ctx, statfilter, opt)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
filePath := fmt.Sprintf("./tmp/渠道统计信息列表-%s.xlsx", time.Now().Format("2006-01-02 15:04:05"))
|
||||
if sErr := channelStatexport(filePath, statList); sErr != nil {
|
||||
return "", sErr
|
||||
}
|
||||
return filePath, nil
|
||||
}
|
||||
|
||||
func channelStatexport(rPath string, statInfos channelmod.ChannelStatList) error {
|
||||
f := excelize.NewFile()
|
||||
sheetName := "Sheet1"
|
||||
// 设置列宽
|
||||
f.SetColWidth("Sheet1", "A", "O", 20)
|
||||
// 设置表头行高
|
||||
f.SetRowHeight("Sheet1", 1, 30)
|
||||
// 设置表头样式
|
||||
headStyleID, _ := f.NewStyle(`{
|
||||
"font":{
|
||||
"color":"#333333",
|
||||
"bold":true,
|
||||
"size":16,
|
||||
"family":"arial"
|
||||
},
|
||||
"alignment":{
|
||||
"vertical":"center",
|
||||
"horizontal":"center"
|
||||
}
|
||||
}`)
|
||||
f.SetCellStyle("Sheet1", "A1", "O1", headStyleID)
|
||||
// 统计时间 app名称 所属渠道 总新增 总充值
|
||||
idx := f.NewSheet(sheetName)
|
||||
var exportTransWaterTitle = map[string]string{
|
||||
"A1": "日期",
|
||||
"B1": "APP名称",
|
||||
"C1": "渠道码",
|
||||
"D1": "总新增",
|
||||
"E1": "总充值",
|
||||
}
|
||||
for k, v := range exportTransWaterTitle {
|
||||
f.SetCellValue(sheetName, k, v)
|
||||
}
|
||||
appInfos, _ := appInfoMod.GetAllAppInfo(context.Background())
|
||||
|
||||
for k, v := range statInfos {
|
||||
i := 'A' // i 不能超过Z,即列输不能超过26列,超出将出现bug
|
||||
date := v.SumDate.Local().Format("2006-01-02")
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), date) //日期
|
||||
i++
|
||||
appName := ""
|
||||
for _, appInfo := range appInfos {
|
||||
if appInfo.AppId == v.AppId {
|
||||
appName = appInfo.Name
|
||||
}
|
||||
}
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), appName) //APP名称
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.Channel) //渠道吗
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), v.NewTotalCount) //总新增
|
||||
i++
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("%s%d", string(i), k+2), float64(v.TotalAmount)/100) //总充值
|
||||
}
|
||||
|
||||
f.SetActiveSheet(idx)
|
||||
p, _ := os.Getwd()
|
||||
fileName := path.Join(p, rPath)
|
||||
if err := f.SaveAs(fileName); err != nil {
|
||||
log.Error("SettlementInfo:export save file to disk failed",
|
||||
log.Any("fileName", fileName),
|
||||
log.E(err))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
package statSer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"stat/api/proto"
|
||||
"stat/common/stdLog"
|
||||
"stat/common/utils"
|
||||
"stat/models/rechargegamemod"
|
||||
"stat/models/withdrawGameOrdermod"
|
||||
)
|
||||
|
||||
// 获取充值明细(集团)
|
||||
func GameRechargeList(ctx context.Context, param proto.ListBlocRechargeDetailsReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
resp := proto.ListBlocRechargeDetailsRes{
|
||||
Total: 0,
|
||||
List: make([]proto.BlocRechargeDetailsInfo, 0),
|
||||
}
|
||||
|
||||
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
total, RechagerList, err := rechargegamemod.GetBlocRechargeDetailsList(ctx, param.AppId, param.StartTime, param.EndTime, skip, limit)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
appIds := make([]int32, 0)
|
||||
appMap := make(map[int32]int32)
|
||||
for _, v := range RechagerList {
|
||||
if _, ok := appMap[v.AppId]; !ok {
|
||||
appMap[v.AppId] = v.AppId
|
||||
appIds = append(appIds, v.AppId)
|
||||
}
|
||||
}
|
||||
//fmt.Println(appIds)
|
||||
appInfoMap, err := MakeAppInfosMapByIds(ctx, appIds)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range RechagerList {
|
||||
appName := ""
|
||||
if appInfo, ok := appInfoMap[v.AppId]; ok {
|
||||
appName = appInfo.Name
|
||||
}
|
||||
|
||||
tmp := proto.BlocRechargeDetailsInfo{
|
||||
UserId: v.PromCode,
|
||||
AppName: appName,
|
||||
SysType: v.SysType,
|
||||
DevType: v.DevType,
|
||||
ChannelName: v.ChannelName,
|
||||
CID: v.CID,
|
||||
Type: v.Type,
|
||||
OrderId: v.OrderId,
|
||||
Money: v.Money,
|
||||
PayMoney: v.PayMoney,
|
||||
Status: 3,
|
||||
SuccessAt: v.SuccessAt,
|
||||
}
|
||||
resp.List = append(resp.List, tmp)
|
||||
}
|
||||
|
||||
resp.Total = total
|
||||
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
|
||||
// 获取提现明细(集团)
|
||||
func GameWithdrawList(ctx context.Context, param proto.ListBlocWithdrawDetailsReq) (code stdLog.CodeType, data interface{}, err error) {
|
||||
resp := proto.ListBlocWithdrawDetailsRes{
|
||||
Total: 0,
|
||||
List: make([]proto.ListBlocWithdrawDetailsInfo, 0),
|
||||
}
|
||||
|
||||
skip, limit := utils.ToDBPage(param.PageNum, param.PageSize)
|
||||
total, RechagerList, err := withdrawGameOrdermod.GetBlocGameWithdrawOrderList(ctx, param.AppId, param.StartTime, param.EndTime, skip, limit)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
appIds := make([]int32, 0)
|
||||
appMap := make(map[int32]int32)
|
||||
for _, v := range RechagerList {
|
||||
if _, ok := appMap[v.AppId]; !ok {
|
||||
appMap[v.AppId] = v.AppId
|
||||
appIds = append(appIds, v.AppId)
|
||||
}
|
||||
}
|
||||
//fmt.Println(appIds)
|
||||
appInfoMap, err := MakeAppInfosMapByIds(ctx, appIds)
|
||||
if err != nil {
|
||||
code = stdLog.Failure
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range RechagerList {
|
||||
appName := ""
|
||||
if appInfo, ok := appInfoMap[v.AppId]; ok {
|
||||
appName = appInfo.Name
|
||||
}
|
||||
|
||||
tmp := proto.ListBlocWithdrawDetailsInfo{
|
||||
UID: v.PromCode,
|
||||
AppName: appName,
|
||||
Name: v.Name,
|
||||
Amount: v.Amount,
|
||||
Money: v.Money,
|
||||
PayMoney: v.PayMoney,
|
||||
PayType: v.PayType,
|
||||
OID: v.OID,
|
||||
ActName: v.ActName,
|
||||
Act: v.Act,
|
||||
UserIP: v.UserIP,
|
||||
DeviceType: v.DeviceType,
|
||||
DevID: v.DevID,
|
||||
Status: v.Status,
|
||||
StatusDesc: v.StatusDesc,
|
||||
SuccessAt: v.SuccessAt,
|
||||
ReceivedAt: v.ReceivedAt,
|
||||
}
|
||||
resp.List = append(resp.List, tmp)
|
||||
}
|
||||
|
||||
resp.Total = total
|
||||
|
||||
data = resp
|
||||
code = stdLog.Success
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,617 @@
|
||||
package statSer
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"stat/api/proto"
|
||||
"stat/models/appInfoMod"
|
||||
"stat/models/channelmod"
|
||||
"stat/models/dailyhourstatmod"
|
||||
"stat/models/dailystatmod"
|
||||
"strconv"
|
||||
|
||||
"github.com/360EntSecGroup-Skylar/excelize"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
type RuleMap map[string]*channelmod.ChannelDeductionRule
|
||||
|
||||
func (c RuleMap) GetRule(channel string, appId int32) *channelmod.ChannelDeductionRule {
|
||||
key := fmt.Sprintf("%s %d", channel, appId)
|
||||
return c[key]
|
||||
}
|
||||
|
||||
func (c RuleMap) SetRule(rule *channelmod.ChannelDeductionRule) {
|
||||
key := fmt.Sprintf("%s %d", rule.Channel, rule.AppId)
|
||||
c[key] = rule
|
||||
}
|
||||
|
||||
func MakeRuleMap(ctx context.Context, channels []string) (RuleMap, error) {
|
||||
ruleMap := make(RuleMap)
|
||||
m := make(map[string]struct{})
|
||||
for _, s := range channels {
|
||||
m[s] = struct{}{}
|
||||
}
|
||||
channels = make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
channels = append(channels, k)
|
||||
}
|
||||
rules, err := channelmod.FindManyChannelDeductionRule(ctx, bson.M{channelmod.FN.ChannelDeductionRule.Channel: bson.M{"$in": channels}})
|
||||
if err != nil {
|
||||
return ruleMap, err
|
||||
}
|
||||
for _, item := range rules {
|
||||
ruleMap.SetRule(item)
|
||||
}
|
||||
return ruleMap, nil
|
||||
}
|
||||
|
||||
func MakeAppInfosMapByIds(ctx context.Context, appIds []int32) (map[int32]*appInfoMod.AppInfo, error) {
|
||||
r := make(map[int32]*appInfoMod.AppInfo)
|
||||
|
||||
if len(appIds) == 0 {
|
||||
return r, nil
|
||||
}
|
||||
|
||||
appList, err := appInfoMod.GetAppInfosByAppIds(ctx, appIds)
|
||||
if err != nil {
|
||||
return r, err
|
||||
}
|
||||
|
||||
for _, v := range appList {
|
||||
_v := v
|
||||
r[v.AppId] = &_v
|
||||
}
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func ExportDailyHourStat(transInfos []*proto.DailyHourStatInfo) (*bytes.Buffer, error) {
|
||||
f := excelize.NewFile()
|
||||
cell := func(row, col int) string { // row start form 0, col start form 0
|
||||
return fmt.Sprintf("%s%d", excelize.ToAlphaString(col), row+1)
|
||||
}
|
||||
sheetName := "Sheet1"
|
||||
row0 := []string{0: "记录时间", 1: "APP名称", 2: "总充值", 3: "总新增", 4: "新增", 11: "充值", 19: "访问数", 21: "VIP", 24: "订单", 27: "落地页", 29: ""}
|
||||
row1 := []string{4: "直推", 5: "裂变", 6: "安卓", 7: "IOS", 8: "自然", 9: "H5", 10: "扣量", 11: "直推", 12: "裂变", 13: "自然",
|
||||
14: "新增", 15: "老用户", 16: "复充", 17: "游戏充值", 18: "游戏提现", 19: "直推", 20: "裂变", 21: "余额", 22: "人民币", 23: "复充",
|
||||
24: "成功", 25: "拉起", 26: "成功率", 27: "安卓", 28: "商店包", 29: "企业签"}
|
||||
// 设置列宽
|
||||
f.SetColWidth("Sheet1", excelize.ToAlphaString(0), excelize.ToAlphaString(1), 16)
|
||||
f.SetColWidth("Sheet1", excelize.ToAlphaString(2), excelize.ToAlphaString(3), 10)
|
||||
f.SetColWidth("Sheet1", excelize.ToAlphaString(4), excelize.ToAlphaString(len(row0)-1), 8)
|
||||
// 设置表头行高
|
||||
f.SetRowHeight("Sheet1", 1, 30)
|
||||
// 设置表头样式
|
||||
headStyleID, _ := f.NewStyle(`{
|
||||
"font":{
|
||||
"color":"#333333",
|
||||
"bold":true,
|
||||
"size":16,
|
||||
"family":"arial"
|
||||
},
|
||||
"alignment":{
|
||||
"vertical":"center",
|
||||
"horizontal":"center"
|
||||
}
|
||||
}`)
|
||||
|
||||
f.SetCellStyle("Sheet1", cell(0, 0), cell(0, len(row0)-1), headStyleID)
|
||||
idx := f.NewSheet(sheetName)
|
||||
// set main title
|
||||
for col, name := range row0 {
|
||||
f.SetCellValue(sheetName, cell(0, col), name)
|
||||
}
|
||||
// merge some title
|
||||
var mergeCells = map[string]string{
|
||||
cell(0, 4): cell(0, 10),
|
||||
cell(0, 11): cell(0, 18),
|
||||
cell(0, 19): cell(0, 20),
|
||||
cell(0, 21): cell(0, 23),
|
||||
cell(0, 24): cell(0, 26),
|
||||
cell(0, 27): cell(0, 29),
|
||||
}
|
||||
for hcell, vcell := range mergeCells {
|
||||
f.MergeCell(sheetName, hcell, vcell)
|
||||
}
|
||||
// set sub title
|
||||
for col, name := range row1 {
|
||||
f.SetCellValue(sheetName, cell(1, col), name)
|
||||
}
|
||||
// set cell data
|
||||
for k, v := range transInfos {
|
||||
col := 0
|
||||
row := k + 2
|
||||
axis := func() string {
|
||||
ret := cell(row, col)
|
||||
col++
|
||||
return ret
|
||||
}
|
||||
fmtW := func(v int64) string {
|
||||
return fmt.Sprintf("%.4f", float64(v)/float64(10000))
|
||||
}
|
||||
f.SetCellValue(sheetName, axis(), v.SumDate.Local().Format("2006-01-02 15:04:05")) //记录时间
|
||||
f.SetCellValue(sheetName, axis(), v.AppName) //APP名称
|
||||
f.SetCellValue(sheetName, axis(), fmtW(v.DirectAmount+v.FissionAmount)) //总充值
|
||||
f.SetCellValue(sheetName, axis(), v.NewDirectCount+v.NewFissionCount) //总新增
|
||||
// Group 1 : E1-K1 = 7
|
||||
f.SetCellValue(sheetName, axis(), v.NewDirectCount) //新增-直推
|
||||
f.SetCellValue(sheetName, axis(), v.NewFissionCount) //新增-裂变
|
||||
f.SetCellValue(sheetName, axis(), v.NewAndroidCount) //新增-安卓
|
||||
f.SetCellValue(sheetName, axis(), v.NewIosCount) //新增-IOS
|
||||
f.SetCellValue(sheetName, axis(), v.NewNaturalCount) //新增-自然
|
||||
f.SetCellValue(sheetName, axis(), v.NewH5Count) //新增-H5
|
||||
f.SetCellValue(sheetName, axis(), v.NewDeductionCount) //新增-扣量
|
||||
//Group 2 : L1-S1 = 8
|
||||
f.SetCellValue(sheetName, axis(), fmtW(v.DirectAmount)) //充值-直推
|
||||
f.SetCellValue(sheetName, axis(), fmtW(v.FissionAmount)) //充值-裂变
|
||||
f.SetCellValue(sheetName, axis(), fmtW(v.NaturalAmount)) //充值-自然
|
||||
f.SetCellValue(sheetName, axis(), fmtW(v.NewRechargeAmount)) //充值-新增
|
||||
f.SetCellValue(sheetName, axis(), fmtW(v.DirectAmount+v.FissionAmount-v.NewRechargeAmount)) //充值-老用户
|
||||
f.SetCellValue(sheetName, axis(), fmtW(v.RepeatAmount)) //充值-复充
|
||||
f.SetCellValue(sheetName, axis(), fmtW(v.GameRechageAmount)) //充值-游戏充值
|
||||
f.SetCellValue(sheetName, axis(), fmtW(v.GameWithdrawAmount)) //充值-游戏提现
|
||||
//Group 3 : T1-U1 = 2
|
||||
f.SetCellValue(sheetName, axis(), v.DirectVisitCount) //访问数-直推
|
||||
f.SetCellValue(sheetName, axis(), v.FissionVisitCount) //访问数-裂变
|
||||
//Group 4 : V1-X1 = 3
|
||||
f.SetCellValue(sheetName, axis(), fmtW(v.VipPayByAmount)) //VIP-余额
|
||||
f.SetCellValue(sheetName, axis(), fmtW(v.VipPayByMoney)) //VIP-人民币
|
||||
f.SetCellValue(sheetName, axis(), fmtW(v.VipRepeatAmount)) //VIP-复充
|
||||
//Group 5 : Y1-AA1 = 3
|
||||
f.SetCellValue(sheetName, axis(), v.SuccessRechargeOrder) //订单-成功
|
||||
f.SetCellValue(sheetName, axis(), v.TotalRechargeOrder) //订单-拉起
|
||||
f.SetCellValue(sheetName, axis(), v.RechargeSuccessRate) //订单-成功率
|
||||
//Group 6 : AB1-AD1 = 3
|
||||
f.SetCellValue(sheetName, axis(), v.LandpageAndroidClick) //落地页-安卓
|
||||
f.SetCellValue(sheetName, axis(), v.LandpageIosAppstoreClick) //落地页-商店包
|
||||
f.SetCellValue(sheetName, axis(), v.LandpageIosAthorClick) //落地页-企业签
|
||||
}
|
||||
f.SetActiveSheet(idx)
|
||||
buf := new(bytes.Buffer)
|
||||
if err := f.Write(buf); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func DailyStatInfoAccumulate(base, value *proto.DailyStatInfo) {
|
||||
base.TotalNewCount += value.TotalNewCount
|
||||
base.NewDirectCount += value.NewDirectCount
|
||||
base.NewFissionCount += value.NewFissionCount
|
||||
base.NewDeductionCount += value.NewDeductionCount
|
||||
base.NewNaturalCount += value.NewNaturalCount
|
||||
base.NewWebCount += value.NewWebCount
|
||||
base.NewDistrictCount += value.NewDistrictCount
|
||||
base.NewNormalCount += value.NewNormalCount
|
||||
base.AndroidAddCount += value.AndroidAddCount
|
||||
base.IosAddCount += value.IosAddCount
|
||||
base.H5FormalCount += value.H5FormalCount
|
||||
base.H5AddCount += value.H5AddCount
|
||||
base.H5PcAddCount += value.H5PcAddCount
|
||||
base.H5IosAddCount += value.H5IosAddCount
|
||||
base.H5AndroidAddCount += value.H5AndroidAddCount
|
||||
base.TotalVisitCount += value.TotalVisitCount
|
||||
base.DirectVisitCount += value.DirectVisitCount
|
||||
base.FissionVisitCount += value.FissionVisitCount
|
||||
base.NaturalVisitCount += value.NaturalVisitCount
|
||||
base.TodayDistrictVisitCount += value.TodayDistrictVisitCount
|
||||
base.TodayWebVisitCount += value.TodayWebVisitCount
|
||||
base.TodayNormalVisitCount += value.TodayNormalVisitCount
|
||||
base.TodayIosVisitCount += value.TodayIosVisitCount
|
||||
base.TodayAndroidVisitCount += value.TodayAndroidVisitCount
|
||||
base.TodayH5VisitCount += value.TodayH5VisitCount
|
||||
base.TodayH5PcVisitCount += value.TodayH5PcVisitCount
|
||||
base.TodayH5IosVisitCount += value.TodayH5IosVisitCount
|
||||
base.TodayH5AndroidVisitCount += value.TodayH5AndroidVisitCount
|
||||
|
||||
base.LightVisitCount += value.LightVisitCount
|
||||
base.LightDirectVisitCount += value.LightDirectVisitCount
|
||||
base.LightFissionVisitCount += value.LightFissionVisitCount
|
||||
base.LightDeductionVisitCount += value.LightDeductionVisitCount
|
||||
base.LightNaturalVisitCount += value.LightNaturalVisitCount
|
||||
base.LightWebVisitCount += value.LightWebVisitCount
|
||||
base.LightDistrictVisitCount += value.LightDistrictVisitCount
|
||||
base.LightNormalVisitCount += value.LightNormalVisitCount
|
||||
|
||||
base.LightAddCount += value.LightAddCount
|
||||
base.LightGuestAddCount += value.LightGuestAddCount
|
||||
base.LightFormalAddCount += value.LightFormalAddCount
|
||||
base.LightDirectCount += value.LightDirectCount
|
||||
base.LightFissionCount += value.LightFissionCount
|
||||
base.LightDeductionCount += value.LightDeductionCount
|
||||
base.LightNaturalCount += value.LightNaturalCount
|
||||
base.LightWebCount += value.LightWebCount
|
||||
base.LightDistrictCount += value.LightDistrictCount
|
||||
base.LightNormalCount += value.LightNormalCount
|
||||
|
||||
base.TotalAmount += value.TotalAmount
|
||||
base.DirectAmount += value.DirectAmount
|
||||
base.FissionAmount += value.FissionAmount
|
||||
base.DeductionAmount += value.DeductionAmount
|
||||
base.NaturalAmount += value.NaturalAmount
|
||||
base.TodayDistrictRecharge += value.TodayDistrictRecharge
|
||||
base.TodayWebRecharge += value.TodayWebRecharge
|
||||
base.TodayNormalRecharge += value.TodayNormalRecharge
|
||||
base.TodayAndroidRecharge += value.TodayAndroidRecharge
|
||||
base.TodayIosRecharge += value.TodayIosRecharge
|
||||
base.LightRechargeCount += value.LightRechargeCount
|
||||
base.LightDirectRechargeCount += value.LightDirectRechargeCount
|
||||
base.LightFissionRechargeCount += value.LightFissionRechargeCount
|
||||
base.LightDeductionRechargeCount += value.LightDeductionRechargeCount
|
||||
base.LightNaturalRechargeCount += value.LightNaturalRechargeCount
|
||||
base.LightWebRechargeCount += value.LightWebRechargeCount
|
||||
base.LightDistrictRechargeCount += value.LightDistrictRechargeCount
|
||||
base.LightNormalRechargeCount += value.LightNormalRechargeCount
|
||||
base.LightRechargeAmount += value.LightRechargeAmount
|
||||
base.LightDirectRechargeAmount += value.LightDirectRechargeAmount
|
||||
base.LightFissionRechargeAmount += value.LightFissionRechargeAmount
|
||||
base.LightDeductionRechargeAmount += value.LightDeductionRechargeAmount
|
||||
base.LightNaturalRechargeAmount += value.LightNaturalRechargeAmount
|
||||
base.LightWebRechargeAmount += value.LightWebRechargeAmount
|
||||
base.LightDistrictRechargeAmount += value.LightDistrictRechargeAmount
|
||||
base.LightNormalRechargeAmount += value.LightNormalRechargeAmount
|
||||
base.TodayH5Recharge += value.TodayH5Recharge
|
||||
base.TodayH5FormalRecharge += value.TodayH5FormalRecharge
|
||||
base.TodayH5PcRecharge += value.TodayH5PcRecharge
|
||||
base.TodayH5IosRecharge += value.TodayH5IosRecharge
|
||||
base.TodayH5AndroidRecharge += value.TodayH5AndroidRecharge
|
||||
base.VipPayByMoney += value.VipPayByMoney
|
||||
base.PayForAthor += value.TotalAmount - value.VipPayByMoney
|
||||
base.RepeatAmount += value.RepeatAmount
|
||||
base.RepeatVipMoney += value.RepeatVipMoney
|
||||
base.GameRechageAmount += value.GameRechageAmount
|
||||
base.GameWithdrawAmount += value.GameWithdrawAmount
|
||||
base.OldRechargeAmount += value.OldRechargeAmount
|
||||
base.OldVipRecharge += value.OldVipRecharge
|
||||
base.OldCoinRecharge += value.OldCoinRecharge
|
||||
base.NewRechargeCount += value.NewRechargeCount
|
||||
base.NewRechargeAmount += value.NewRechargeAmount
|
||||
base.NewVipRecharge += value.NewVipRecharge
|
||||
base.NewCoinRecharge += value.NewCoinRecharge
|
||||
base.SuccessRechargeOrder += value.SuccessRechargeOrder
|
||||
base.TotalRechargeOrder += value.TotalRechargeOrder
|
||||
base.Day1RetainRate += value.Day1RetainRate
|
||||
base.Day3RetainRate += value.Day3RetainRate
|
||||
base.Day7RetainRate += value.Day7RetainRate
|
||||
base.LandpageAndroidClick += value.LandpageAndroidClick
|
||||
base.LandpageIosAppstoreClick += value.LandpageIosAppstoreClick
|
||||
base.LandpageIosAthorClick += value.LandpageIosAthorClick
|
||||
base.LandpageIosH5Click += value.LandpageIosH5Click
|
||||
if base.NewCoinRecharge < 0 {
|
||||
base.NewCoinRecharge = 0
|
||||
}
|
||||
if base.OldVipRecharge < 0 {
|
||||
base.OldVipRecharge = 0
|
||||
}
|
||||
if base.OldCoinRecharge < 0 {
|
||||
base.OldCoinRecharge = 0
|
||||
}
|
||||
|
||||
if base.TotalRechargeOrder > 0 {
|
||||
base.RechargeSuccessRate = fmt.Sprintf("%.3f", float64(base.SuccessRechargeOrder)/float64(base.TotalRechargeOrder))
|
||||
}
|
||||
if base.TotalNewCount != 0 {
|
||||
base.NewRechargeRate, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", (float64(base.NewRechargeCount)/float64(base.TotalNewCount))*100), 64)
|
||||
}
|
||||
if base.TotalVisitCount != 0 {
|
||||
base.VisitRechargeRate, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", (float64(base.SuccessRechargeOrder)/float64(base.TotalVisitCount))*100), 64)
|
||||
}
|
||||
if base.SuccessRechargeOrder != 0 {
|
||||
base.ARPPU = base.TotalAmount / base.SuccessRechargeOrder // 金额
|
||||
}
|
||||
if base.TotalNewCount != 0 {
|
||||
base.ARPU = base.TotalAmount / base.TotalNewCount // 金额
|
||||
}
|
||||
}
|
||||
|
||||
func DailyStatToInfo(src *dailystatmod.DailyStatMod) *proto.DailyStatInfo {
|
||||
src.CorrectValidData()
|
||||
ret := &proto.DailyStatInfo{
|
||||
SumDate: src.SumDate,
|
||||
AppId: src.AppId,
|
||||
AppName: "", // 外面赋值
|
||||
TotalNewCount: src.NewTotalCount,
|
||||
NewDirectCount: src.NewDirectCount,
|
||||
NewFissionCount: src.NewFissionCount,
|
||||
NewDeductionCount: src.NewDeductionCount,
|
||||
NewNaturalCount: src.NewNaturalCount,
|
||||
NewWebCount: src.NewWebCount,
|
||||
NewDistrictCount: src.NewDistrictCount,
|
||||
NewNormalCount: src.NewNormalCount,
|
||||
LightAddCount: src.LightAddCount,
|
||||
LightGuestAddCount: src.LightGuestAddCount,
|
||||
LightFormalAddCount: src.LightFormalAddCount,
|
||||
LightDirectCount: src.LightDirectCount,
|
||||
LightFissionCount: src.LightFissionCount,
|
||||
LightDeductionCount: src.LightDeductionCount,
|
||||
LightNaturalCount: src.LightNaturalCount,
|
||||
LightWebCount: src.LightWebCount,
|
||||
LightDistrictCount: src.LightDistrictCount,
|
||||
LightNormalCount: src.LightNormalCount,
|
||||
AndroidAddCount: src.AndroidAddCount,
|
||||
IosAddCount: src.IosAddCount,
|
||||
H5FormalCount: src.H5FormalCount,
|
||||
H5AddCount: src.H5AddCount,
|
||||
H5PcAddCount: src.H5PcAddCount,
|
||||
H5IosAddCount: src.H5IosAddCount,
|
||||
H5AndroidAddCount: src.H5AndroidAddCount,
|
||||
TotalVisitCount: src.TotalVisitCount,
|
||||
DirectVisitCount: src.DirectVisitCount,
|
||||
FissionVisitCount: src.FissionVisitCount,
|
||||
NaturalVisitCount: src.NaturalVisitCount,
|
||||
TodayDistrictVisitCount: src.TodayDistrictVisitCount,
|
||||
TodayWebVisitCount: src.TodayWebVisitCount,
|
||||
TodayNormalVisitCount: src.TodayNormalVisitCount,
|
||||
TodayIosVisitCount: src.TodayIosVisitCount,
|
||||
TodayAndroidVisitCount: src.TodayAndroidVisitCount,
|
||||
LightVisitCount: src.LightVisitCount,
|
||||
LightDirectVisitCount: src.LightDirectVisitCount,
|
||||
LightFissionVisitCount: src.LightFissionVisitCount,
|
||||
LightDeductionVisitCount: src.LightDeductionVisitCount,
|
||||
LightNaturalVisitCount: src.LightNaturalVisitCount,
|
||||
LightWebVisitCount: src.LightWebVisitCount,
|
||||
LightDistrictVisitCount: src.LightDistrictVisitCount,
|
||||
LightNormalVisitCount: src.LightNormalVisitCount,
|
||||
TodayH5VisitCount: src.TodayH5VisitCount,
|
||||
TodayH5PcVisitCount: src.TodayH5PcVisitCount,
|
||||
TodayH5IosVisitCount: src.TodayH5IosVisitCount,
|
||||
TodayH5AndroidVisitCount: src.TodayH5AndroidVisitCount,
|
||||
TotalAmount: src.TotalAmount,
|
||||
DirectAmount: src.DirectAmount,
|
||||
FissionAmount: src.FissionAmount,
|
||||
DeductionAmount: src.DeductionAmount,
|
||||
NaturalAmount: src.NaturalAmount,
|
||||
TodayDistrictRecharge: src.TodayDistrictRecharge,
|
||||
TodayWebRecharge: src.TodayWebRecharge,
|
||||
TodayNormalRecharge: src.TodayNormalRecharge,
|
||||
TodayAndroidRecharge: src.TodayAndroidRecharge,
|
||||
TodayIosRecharge: src.TodayIosRecharge,
|
||||
LightRechargeCount: src.LightRechargeCount,
|
||||
LightDirectRechargeCount: src.LightDirectRechargeCount,
|
||||
LightFissionRechargeCount: src.LightFissionRechargeCount,
|
||||
LightDeductionRechargeCount: src.LightDeductionRechargeCount,
|
||||
LightNaturalRechargeCount: src.LightNaturalRechargeCount,
|
||||
LightWebRechargeCount: src.LightWebRechargeCount,
|
||||
LightDistrictRechargeCount: src.LightDistrictRechargeCount,
|
||||
LightNormalRechargeCount: src.LightNormalRechargeCount,
|
||||
LightRechargeAmount: src.LightRechargeAmount,
|
||||
LightDirectRechargeAmount: src.LightDirectRechargeAmount,
|
||||
LightFissionRechargeAmount: src.LightFissionRechargeAmount,
|
||||
LightDeductionRechargeAmount: src.LightDeductionRechargeAmount,
|
||||
LightNaturalRechargeAmount: src.LightNaturalRechargeAmount,
|
||||
LightWebRechargeAmount: src.LightWebRechargeAmount,
|
||||
LightDistrictRechargeAmount: src.LightDistrictRechargeAmount,
|
||||
LightNormalRechargeAmount: src.LightNormalRechargeAmount,
|
||||
TodayH5Recharge: src.TodayH5Recharge,
|
||||
TodayH5FormalRecharge: src.TodayH5FormalRecharge,
|
||||
TodayH5PcRecharge: src.TodayH5PcRecharge,
|
||||
TodayH5IosRecharge: src.TodayH5IosRecharge,
|
||||
TodayH5AndroidRecharge: src.TodayH5AndroidRecharge,
|
||||
ARPU: 0, // 下面赋值
|
||||
ARPPU: 0, // 下面赋值
|
||||
VipPayByMoney: src.VipPayByMoney,
|
||||
PayForAthor: 0, // 下面赋值
|
||||
RepeatAmount: src.RepeatAmount,
|
||||
RepeatVipMoney: src.RepeatVipMoney,
|
||||
GameRechageAmount: src.GameRechageAmount,
|
||||
GameWithdrawAmount: src.GameWithdrawAmount,
|
||||
OldRechargeAmount: 0, // 下面赋值
|
||||
OldVipRecharge: 0, // 下面赋值
|
||||
OldCoinRecharge: 0, // 下面赋值
|
||||
NewRechargeCount: src.NewRechargeCount,
|
||||
NewRechargeAmount: src.NewRechargeAmount,
|
||||
NewVipRecharge: src.NewVipPayMoney,
|
||||
NewCoinRecharge: 0, // 下面赋值
|
||||
NewRechargeRate: 0, // 下面赋值
|
||||
VisitRechargeRate: 0, // 下面赋值
|
||||
SuccessRechargeOrder: src.SuccessRechargeOrder,
|
||||
TotalRechargeOrder: src.TotalRechargeOrder,
|
||||
RechargeSuccessRate: "", //下面赋值
|
||||
Day1RetainRate: src.Day1RetainRate,
|
||||
Day3RetainRate: src.Day3RetainRate,
|
||||
Day7RetainRate: src.Day7RetainRate,
|
||||
LandpageAndroidClick: src.LandpageAndroidClick,
|
||||
LandpageIosAppstoreClick: src.LandpageIosAppstoreClick,
|
||||
LandpageIosAthorClick: src.LandpageIosAthorClick,
|
||||
LandpageIosH5Click: src.LandpageIosH5Click,
|
||||
UpdatedAt: src.UpdatedAt,
|
||||
}
|
||||
if ret.TotalNewCount == 0 {
|
||||
ret.TotalNewCount = ret.NewDirectCount + ret.NewFissionCount + ret.NewDeductionCount
|
||||
}
|
||||
if ret.TotalVisitCount == 0 {
|
||||
ret.TotalVisitCount = ret.DirectVisitCount + ret.FissionVisitCount + ret.DeductionVisitCount
|
||||
}
|
||||
if ret.TotalAmount == 0 {
|
||||
ret.TotalAmount = ret.DirectAmount + ret.FissionAmount + ret.DeductionAmount
|
||||
}
|
||||
|
||||
ret.PayForAthor = ret.TotalAmount - ret.VipPayByMoney
|
||||
ret.OldRechargeAmount = ret.TotalAmount - ret.NewRechargeAmount
|
||||
ret.OldVipRecharge = ret.VipPayByMoney - ret.NewVipRecharge
|
||||
ret.OldCoinRecharge = ret.OldRechargeAmount - ret.OldVipRecharge
|
||||
ret.NewCoinRecharge = ret.NewRechargeAmount - ret.NewVipRecharge
|
||||
|
||||
if ret.NewCoinRecharge < 0 {
|
||||
ret.NewCoinRecharge = 0
|
||||
}
|
||||
if ret.OldVipRecharge < 0 {
|
||||
ret.OldVipRecharge = 0
|
||||
}
|
||||
if ret.OldCoinRecharge < 0 {
|
||||
ret.OldCoinRecharge = 0
|
||||
}
|
||||
|
||||
if ret.TotalRechargeOrder > 0 {
|
||||
ret.RechargeSuccessRate = fmt.Sprintf("%.3f", float64(ret.SuccessRechargeOrder)/float64(ret.TotalRechargeOrder))
|
||||
}
|
||||
if ret.TotalNewCount != 0 {
|
||||
ret.ARPU = ret.TotalAmount / ret.TotalNewCount // 金额
|
||||
ret.NewRechargeRate, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", (float64(ret.NewRechargeCount)/float64(ret.TotalNewCount))*100), 64)
|
||||
}
|
||||
if ret.TotalVisitCount != 0 {
|
||||
ret.VisitRechargeRate, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", (float64(ret.SuccessRechargeOrder)/float64(ret.TotalVisitCount))*100), 64)
|
||||
}
|
||||
if ret.SuccessRechargeOrder != 0 {
|
||||
ret.ARPPU = ret.TotalAmount / ret.SuccessRechargeOrder // 金额
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func DailyHourStatToInfo(src *dailyhourstatmod.DailyHourStat) *proto.DailyHourStatInfo {
|
||||
src.CorrectValidData()
|
||||
ret := &proto.DailyHourStatInfo{
|
||||
SumDate: src.SumDate,
|
||||
AppId: src.AppId,
|
||||
SumHour: src.SumHour,
|
||||
AppName: "",
|
||||
NewTotalCount: src.NewTotalCount,
|
||||
NewDirectCount: src.NewDirectCount,
|
||||
NewFissionCount: src.NewFissionCount,
|
||||
NewDeductionCount: src.NewDeductionCount,
|
||||
NewNaturalCount: src.NewNaturalCount,
|
||||
NewWebCount: src.NewWebCount,
|
||||
NewNormalCount: src.NewNormalCount,
|
||||
NewDistrictCount: src.NewDistrictCount,
|
||||
NewAndroidCount: src.NewAndroidCount,
|
||||
NewIosCount: src.NewIosCount,
|
||||
NewLightCount: src.NewLightCount,
|
||||
NewLightGuestCount: src.NewLightGuestCount,
|
||||
NewLightFormalCount: src.NewLightFormalCount,
|
||||
NewLightDirectCount: src.NewLightDirectCount,
|
||||
NewLightFissionCount: src.NewLightFissionCount,
|
||||
NewLightDeductionCount: src.NewLightDeductionCount,
|
||||
NewLightNaturalCount: src.NewLightNaturalCount,
|
||||
NewLightWebCount: src.NewLightWebCount,
|
||||
NewLightNormalCount: src.NewLightNormalCount,
|
||||
NewLightDistrictCount: src.NewLightDistrictCount,
|
||||
NewH5Count: src.NewH5Count,
|
||||
NewH5FormalCount: src.NewH5FormalCount,
|
||||
NewH5PcCount: src.NewH5PcCount,
|
||||
NewH5IosCount: src.NewH5IosCount,
|
||||
NewH5AndroidCount: src.NewH5AndroidCount,
|
||||
TotalVisitCount: src.TotalVisitCount,
|
||||
DirectVisitCount: src.DirectVisitCount,
|
||||
FissionVisitCount: src.FissionVisitCount,
|
||||
NaturalVisitCount: src.NaturalVisitCount,
|
||||
WebVisitCount: src.WebVisitCount,
|
||||
NormalVisitCount: src.NormalVisitCount,
|
||||
DistrictVisitCount: src.DistrictVisitCount,
|
||||
IosVisitCount: src.IosVisitCount,
|
||||
AndroidVisitCount: src.AndroidVisitCount,
|
||||
LightVisitCount: src.LightVisitCount,
|
||||
LightVisitDirectCount: src.LightVisitDirectCount,
|
||||
LightVisitFissionCount: src.LightVisitFissionCount,
|
||||
LightVisitDeductionCount: src.LightVisitDeductionCount,
|
||||
LightVisitNaturalCount: src.LightVisitNaturalCount,
|
||||
LightVisitWebCount: src.LightVisitWebCount,
|
||||
LightVisitNormalCount: src.LightVisitNormalCount,
|
||||
LightVisitDistrictCount: src.LightVisitDistrictCount,
|
||||
H5VisitCount: src.H5VisitCount,
|
||||
H5PcVisitCount: src.H5PcVisitCount,
|
||||
H5IosVisitCount: src.H5IosVisitCount,
|
||||
H5AndroidVisitCount: src.H5AndroidVisitCount,
|
||||
TotalAmount: src.TotalAmount,
|
||||
SuccessRechargeOrder: src.SuccessRechargeOrder,
|
||||
DirectAmount: src.DirectAmount,
|
||||
DirectAmountCount: src.DirectAmountCount,
|
||||
FissionAmount: src.FissionAmount,
|
||||
FissionAmountCount: src.FissionAmountCount,
|
||||
NaturalAmount: src.NaturalAmount,
|
||||
NaturalAmountCount: src.NaturalAmountCount,
|
||||
DeductionAmount: src.DeductionAmount,
|
||||
DeductionAmountCount: src.DeductionAmountCount,
|
||||
WebAmount: src.WebAmount,
|
||||
WebAmountCount: src.WebAmountCount,
|
||||
NormalAmount: src.NormalAmount,
|
||||
NormalAmountCount: src.NormalAmountCount,
|
||||
DistrictAmount: src.DistrictAmount,
|
||||
DistrictAmountCount: src.DistrictAmountCount,
|
||||
AndroidAmount: src.AndroidAmount,
|
||||
AndroidAmountCount: src.AndroidAmountCount,
|
||||
IosAmount: src.IosAmount,
|
||||
IosAmountCount: src.IosAmountCount,
|
||||
LightAmount: src.LightAmount,
|
||||
LightAmountCount: src.LightAmountCount,
|
||||
LightDirectAmount: src.LightDirectAmount,
|
||||
LightDirectAmountCount: src.LightDirectAmountCount,
|
||||
LightFissionAmount: src.LightFissionAmount,
|
||||
LightFissionAmountCount: src.LightFissionAmountCount,
|
||||
LightDeductionAmount: src.LightDeductionAmount,
|
||||
LightDeductionAmountCount: src.LightDeductionAmountCount,
|
||||
LightNaturalAmount: src.LightNaturalAmount,
|
||||
LightNaturalAmountCount: src.LightNaturalAmountCount,
|
||||
LightWebAmount: src.LightWebAmount,
|
||||
LightWebAmountCount: src.LightWebAmountCount,
|
||||
LightNormalAmount: src.LightNormalAmount,
|
||||
LightNormalAmountCount: src.LightNormalAmountCount,
|
||||
LightDistrictAmount: src.LightDistrictAmount,
|
||||
LightDistrictAmountCount: src.LightDistrictAmountCount,
|
||||
H5Amount: src.H5Amount,
|
||||
H5AmountCount: src.H5AmountCount,
|
||||
H5FormalAmount: src.H5FormalAmount,
|
||||
H5FormalAmountCount: src.H5FormalAmountCount,
|
||||
H5PcAmount: src.H5PcAmount,
|
||||
H5PcAmountCount: src.H5PcAmountCount,
|
||||
H5IosAmount: src.H5IosAmount,
|
||||
H5IosAmountCount: src.H5IosAmountCount,
|
||||
H5AndroidAmount: src.H5AndroidAmount,
|
||||
H5AndroidAmountCount: src.H5AndroidAmountCount,
|
||||
RepeatAmount: src.RepeatAmount,
|
||||
RepeatAmountCount: src.RepeatAmountCount,
|
||||
NewRechargeAmount: src.NewRechargeAmount,
|
||||
NewRechargeCount: src.NewRechargeCount,
|
||||
NewCoinRecharge: 0,
|
||||
NewVipRecharge: 0,
|
||||
OldCoinRecharge: 0,
|
||||
OldVipRecharge: 0,
|
||||
OldRechargeAmount: 0,
|
||||
VipPayByMoney: src.VipPayByMoney,
|
||||
VipPayByAmount: src.VipPayByAmount,
|
||||
VipRepeatAmount: src.VipRepeatAmount,
|
||||
TotalRechargeOrder: src.TotalRechargeOrder,
|
||||
RechargeSuccessRate: "",
|
||||
GameRechageAmount: src.GameRechageAmount,
|
||||
GameWithdrawAmount: src.GameWithdrawAmount,
|
||||
LandpageAndroidClick: src.LandpageAndroidClick,
|
||||
LandpageIosAppstoreClick: src.LandpageIosAppstoreClick,
|
||||
LandpageIosAthorClick: src.LandpageIosAthorClick,
|
||||
LandpageIosH5Click: src.LandpageIosH5Click,
|
||||
UpdatedAt: src.UpdatedAt,
|
||||
}
|
||||
|
||||
if ret.NewTotalCount == 0 {
|
||||
ret.NewTotalCount = ret.NewDirectCount + ret.NewFissionCount + ret.NewDeductionCount
|
||||
}
|
||||
if ret.TotalVisitCount == 0 {
|
||||
ret.TotalVisitCount = ret.DirectVisitCount + ret.FissionVisitCount
|
||||
}
|
||||
if ret.TotalAmount == 0 {
|
||||
ret.TotalAmount = ret.DirectAmount + ret.FissionAmount + ret.DeductionAmount
|
||||
}
|
||||
|
||||
ret.VipPayByAmount = ret.TotalAmount - ret.VipPayByMoney
|
||||
ret.OldRechargeAmount = ret.TotalAmount - ret.NewRechargeAmount
|
||||
ret.OldVipRecharge = ret.VipPayByMoney - ret.NewVipRecharge
|
||||
ret.OldCoinRecharge = ret.OldRechargeAmount - ret.OldVipRecharge
|
||||
ret.NewCoinRecharge = ret.NewRechargeAmount - ret.NewVipRecharge
|
||||
|
||||
if ret.NewCoinRecharge < 0 {
|
||||
ret.NewCoinRecharge = 0
|
||||
}
|
||||
if ret.OldVipRecharge < 0 {
|
||||
ret.OldVipRecharge = 0
|
||||
}
|
||||
if ret.OldCoinRecharge < 0 {
|
||||
ret.OldCoinRecharge = 0
|
||||
}
|
||||
|
||||
if ret.TotalRechargeOrder > 0 {
|
||||
ret.RechargeSuccessRate = fmt.Sprintf("%.3f", float64(ret.SuccessRechargeOrder)/float64(ret.TotalRechargeOrder))
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
Reference in New Issue
Block a user