forked from all_user/stat_center
958 lines
30 KiB
Go
958 lines
30 KiB
Go
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
|
|
}
|