619 lines
22 KiB
Go
619 lines
22 KiB
Go
package statminute
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"math/rand"
|
|
"stat/common/log"
|
|
"stat/common/statutils"
|
|
"stat/common/topicmessage"
|
|
"stat/common/utils"
|
|
"stat/models/accessmod"
|
|
"stat/models/channelmod"
|
|
"stat/models/downloadinfo"
|
|
"stat/models/rechargegamemod"
|
|
"stat/models/rechargemod"
|
|
"stat/models/registermod"
|
|
"stat/models/syncvip"
|
|
"stat/models/versionMod"
|
|
"stat/models/withdrawGameOrdermod"
|
|
"strings"
|
|
"time"
|
|
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
)
|
|
|
|
const (
|
|
ChannelStat string = "visitInfo" // 渠道统计
|
|
)
|
|
|
|
func defaultTimeMap(defaultStatDate time.Time) map[string]time.Time {
|
|
return map[string]time.Time{
|
|
ChannelStat: defaultStatDate, // 渠道统计
|
|
}
|
|
}
|
|
|
|
// 获取统计方法
|
|
type StatMethod = func(ctx context.Context, start time.Time, end time.Time, appIds []int32) error
|
|
|
|
// 统计方法汇总
|
|
var statMethodMap = map[string]StatMethod{
|
|
ChannelStat: ChannelSettlementMethod, // 渠道统计
|
|
}
|
|
|
|
func canUserDeduction(ruleInfo *channelmod.ChannelDeductionRule, index int, incomeRate float64, isDirect bool) bool {
|
|
rate := int32(0) // 扣量比例
|
|
if ruleInfo.Settlement == channelmod.SettlementCPA || ruleInfo.Settlement == channelmod.SettlementCPS {
|
|
//自动扣量
|
|
if ruleInfo.Settlement == channelmod.SettlementCPA && ruleInfo.AutoDeduction && incomeRate > 0.0 && ruleInfo.LessIncomeRate > incomeRate {
|
|
rate = 80
|
|
} else {
|
|
if index < 1 { // 一阶
|
|
rate = ruleInfo.First
|
|
} else if index <= 3 { // 二阶
|
|
rate = ruleInfo.Second
|
|
} else if index <= 6 { // 三阶
|
|
rate = ruleInfo.Third
|
|
} else if index <= 10 { // 四阶
|
|
rate = ruleInfo.Fourth
|
|
} else {
|
|
rate = ruleInfo.Fifth
|
|
}
|
|
}
|
|
if isDirect && int32(rand.Intn(100)) < rate { // rate扣量比例
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func deductionCountMethod(ctx context.Context, ruleInfo *channelmod.ChannelDeductionRule, settlement *channelmod.ChannelSettlement, registerList []*registermod.RegisterMod, incomeRate float64) error {
|
|
deductionUserIds := make([]int64, 0)
|
|
// 先计算扣量
|
|
for index, item := range registerList {
|
|
item.IsDeduction = false
|
|
if canUserDeduction(ruleInfo, index, incomeRate, item.IsDirect) {
|
|
item.IsDeduction = true
|
|
deductionUserIds = append(deductionUserIds, int64(item.UserId))
|
|
}
|
|
}
|
|
// 统计IP
|
|
ipDict := make(map[string]int64)
|
|
for _, item := range registerList {
|
|
if item.IP != "" {
|
|
ipDict[item.IP]++
|
|
}
|
|
}
|
|
// 1.统计这段时间内的注册用户
|
|
stat := &statutils.Stat{}
|
|
uniqueStat := &statutils.Stat{}
|
|
for _, item := range registerList {
|
|
client := statutils.GetClientInfo(item.SysType, item.DevType, item.DistrictCode, item.IsDirect, item.IsDeduction, item.IsFormal)
|
|
stat.Add(1, client)
|
|
if _, exists := ipDict[item.IP]; exists {
|
|
uniqueStat.Add(1, client)
|
|
}
|
|
}
|
|
settlement.NewTotalIpCount += uniqueStat.Count()
|
|
settlement.NewTotalCount += stat.Total.Count()
|
|
settlement.NewDirectCount += stat.Total.Direct.Count()
|
|
settlement.NewFissionCount += stat.Total.Fission.Count
|
|
settlement.NewDeductionCount += stat.Total.Deduction.Count
|
|
settlement.NewLightCount += stat.Light.Count()
|
|
settlement.NewLightDirectCount += stat.Light.Total.Direct.Count()
|
|
settlement.NewLightFissionCount += stat.Light.Total.Fission.Count
|
|
settlement.NewLightDeductionCount += stat.Light.Total.Deduction.Count
|
|
settlement.NewLightNaturalCount += stat.Light.Total.Direct.Natural.Count
|
|
settlement.NewLightGuestCount += stat.Light.Guest.Count()
|
|
settlement.NewLightGuestDirectCount += stat.Light.Guest.Direct.Count()
|
|
settlement.NewLightGuestFissionCount += stat.Light.Guest.Fission.Count
|
|
settlement.NewLightGuestDeductionCount += stat.Light.Guest.Deduction.Count
|
|
settlement.NewLightFormalCount += stat.Light.Formal.Count()
|
|
settlement.NewLightFormalDirectCount += stat.Light.Formal.Direct.Count()
|
|
settlement.NewLightFormalFissionCount += stat.Light.Formal.Fission.Count
|
|
settlement.NewLightFormalDeductionCount += stat.Light.Formal.Deduction.Count
|
|
settlement.NewAndroidCount += stat.Android.Count()
|
|
settlement.NewAndroidDirectCount += stat.Android.Direct.Count()
|
|
settlement.NewAndroidFissionCount += stat.Android.Fission.Count
|
|
settlement.NewAndroidDeductionCount += stat.Android.Deduction.Count
|
|
settlement.NewIosCount += stat.Ios.Count()
|
|
settlement.NewIosDirectCount += stat.Ios.Direct.Count()
|
|
settlement.NewIosFissionCount += stat.Ios.Fission.Count
|
|
settlement.NewIosDeductionCount += stat.Ios.Deduction.Count
|
|
settlement.NewH5Count += stat.H5.Count()
|
|
settlement.NewH5DirectCount += stat.H5.Total.Direct.Count()
|
|
settlement.NewH5FissionCount += stat.H5.Total.Fission.Count
|
|
settlement.NewH5DeductionCount += stat.H5.Total.Deduction.Count
|
|
settlement.NewH5AndroidCount += stat.H5.Android.Count()
|
|
settlement.NewH5IosCount += stat.H5.Ios.Count()
|
|
settlement.NewH5PcCount += stat.H5.Pc.Count()
|
|
settlement.NewH5FormalCount += stat.H5.Formal.Count()
|
|
settlement.NewH5FormalDirectCount += stat.H5.Formal.Direct.Count()
|
|
settlement.NewH5FormalFissionCount += stat.H5.Formal.Fission.Count
|
|
settlement.NewH5FormalDeductionCount += stat.H5.Formal.Deduction.Count
|
|
|
|
// 5 更新扣量用户
|
|
if len(deductionUserIds) > 0 {
|
|
setdoc := bson.M{"$set": bson.M{"isDeduction": true}}
|
|
filter := bson.M{
|
|
"appId": ruleInfo.AppId,
|
|
"userId": bson.M{"$in": deductionUserIds},
|
|
}
|
|
err := registermod.UpdateManyRegister(ctx, filter, setdoc)
|
|
if err != nil {
|
|
log.Error("NewCountMethod UpdateManyRegister ", log.E(err))
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func channelChannelStatMethod(ctx context.Context, ruleInfo *channelmod.ChannelDeductionRule, settlement *channelmod.ChannelSettlement, visitList accessmod.VisitInfoList,
|
|
start, end time.Time, appid int32) error {
|
|
|
|
stat := &statutils.Stat{}
|
|
for _, item := range visitList {
|
|
client := statutils.GetClientInfo(item.SysType, item.DevType, item.DistrictCode, item.IsDirect, false, item.IsFormalUser)
|
|
stat.Add(1, client)
|
|
}
|
|
settlement.TotalVisitCount = stat.Count()
|
|
settlement.DirectVisitCount = stat.Total.Direct.Count()
|
|
settlement.FissionVisitCount = stat.Total.Fission.Count
|
|
settlement.AndroidVisitCount = stat.Android.Count()
|
|
settlement.IosVisitCount = stat.Ios.Count()
|
|
settlement.LightVisitCount = stat.Light.Count()
|
|
settlement.LightVisitDirectCount = stat.Light.Total.Direct.Count()
|
|
settlement.LightVisitFissionCount = stat.Light.Total.Fission.Count
|
|
settlement.LightVisitDeductionCount = stat.Light.Total.Deduction.Count
|
|
settlement.LightVisitNaturalCount = stat.Light.Total.Direct.Natural.Count
|
|
settlement.H5VisitCount = stat.H5.Count()
|
|
settlement.H5AndroidVisitCount = stat.H5.Android.Count()
|
|
settlement.H5IosVisitCount = stat.H5.Ios.Count()
|
|
settlement.H5PcVisitCount = stat.H5.Pc.Count()
|
|
|
|
return nil
|
|
}
|
|
|
|
func channelVipMethod(ctx context.Context, ruleInfo *channelmod.ChannelDeductionRule, settlement *channelmod.ChannelSettlement, VipList syncvip.SyncVipList,
|
|
start, end time.Time, appid int32) error {
|
|
deductionVipOrderIds := make([]primitive.ObjectID, 0)
|
|
for _, buyInfo := range VipList {
|
|
// 统计渠道信息
|
|
if buyInfo.IsDirect && buyInfo.BuyVIPType == topicmessage.BuyVIPTypeMoney {
|
|
if ruleInfo.Settlement == channelmod.SettlementCPS {
|
|
if ruleInfo.TodayTime != utils.BeginWithTime(start) {
|
|
ruleInfo.TodayDeduction = 0
|
|
ruleInfo.TodayTime = utils.BeginWithTime(start)
|
|
}
|
|
ruleInfo.TodayDeduction += buyInfo.Money
|
|
if ruleInfo.CPSBegin < ruleInfo.TodayDeduction {
|
|
if int32(rand.Intn(100)) < int32(ruleInfo.CPSDeductionRate) {
|
|
deductionVipOrderIds = append(deductionVipOrderIds, buyInfo.ID)
|
|
settlement.VipPayDeduction += buyInfo.Money
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// 统计信息
|
|
if buyInfo.IsDirect {
|
|
if buyInfo.BuyVIPType == topicmessage.BuyVIPTypeMoney {
|
|
settlement.VipPayMoney += buyInfo.Money
|
|
} else {
|
|
settlement.VipPayCoin += buyInfo.Amount
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(deductionVipOrderIds) > 0 {
|
|
settlement.VipPayMoney = settlement.VipPayMoney - settlement.VipPayDeduction
|
|
|
|
setdoc := bson.M{"$set": bson.M{syncvip.FN.SyncVip.IsDeduction: true}}
|
|
filter := bson.M{
|
|
syncvip.FN.SyncVip.ID: bson.M{"$in": deductionVipOrderIds},
|
|
syncvip.FN.SyncVip.AppId: ruleInfo.AppId,
|
|
}
|
|
err := syncvip.UpdateOneSyncVip(ctx, filter, setdoc)
|
|
if err != nil {
|
|
log.Error("channelRechargeCountMethod UpdateManyRecharge ", log.E(err))
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func channelRechargeCountMethod(ctx context.Context, ruleInfo *channelmod.ChannelDeductionRule, settlement *channelmod.ChannelSettlement, rechargeList rechargemod.RechargeInfoList,
|
|
start, end time.Time, appid int32) error {
|
|
|
|
stat := &statutils.Stat{}
|
|
statNew := statutils.Stat{}
|
|
for _, item := range rechargeList {
|
|
client := statutils.GetClientInfo(item.SysType, item.DevType, item.DistrictCode, item.IsDirect, false, item.IsFormalUser)
|
|
stat.Add(item.Money, client)
|
|
if item.RegisterTime.After(item.SuccessAt.AddDate(0, 0, -1)) {
|
|
statNew.Add(item.Money, client)
|
|
}
|
|
}
|
|
settlement.TotalAmount = stat.Value()
|
|
settlement.DirectAmount = stat.Total.Direct.Value()
|
|
settlement.DirectAmountCount = stat.Total.Direct.Count()
|
|
settlement.FissionAmount = stat.Total.Fission.Value
|
|
settlement.FissionAmountCount = stat.Total.Fission.Count
|
|
settlement.NaturalAmount = stat.Total.Direct.Natural.Value
|
|
settlement.NaturalAmountCount = stat.Total.Direct.Natural.Count
|
|
settlement.DeductionAmount = stat.Total.Deduction.Value
|
|
settlement.DeductionAmountCount = stat.Total.Deduction.Count
|
|
settlement.AndroidAmount = stat.Android.Value()
|
|
settlement.AndroidAmountCount = stat.Android.Count()
|
|
settlement.IosAmount = stat.Ios.Value()
|
|
settlement.IosAmountCount = stat.Ios.Count()
|
|
settlement.H5Amount = stat.H5.Value()
|
|
settlement.H5AmountCount = stat.H5.Count()
|
|
settlement.LightAmount = stat.Light.Value()
|
|
settlement.LightAmountCount = stat.Light.Count()
|
|
settlement.LightDirectAmount = stat.Light.Total.Direct.Value()
|
|
settlement.LightDirectAmountCount = stat.Light.Total.Direct.Count()
|
|
settlement.LightFissionAmount = stat.Light.Total.Fission.Value
|
|
settlement.LightFissionAmountCount = stat.Light.Total.Fission.Count
|
|
settlement.LightDeductionAmount = stat.Light.Total.Deduction.Value
|
|
settlement.LightDeductionAmountCount = stat.Light.Total.Deduction.Count
|
|
settlement.LightNaturalAmount = stat.Light.Total.Direct.Natural.Value
|
|
settlement.LightNaturalAmountCount = stat.Light.Total.Direct.Natural.Count
|
|
settlement.NewRechargeAmount = statNew.Value()
|
|
return nil
|
|
}
|
|
|
|
// GameRechargeMethod 游戏充值
|
|
func channelGameRechargeMethod(ctx context.Context, ruleInfo *channelmod.ChannelDeductionRule,
|
|
rechageList rechargegamemod.GameRechargeInfoList, withdrawList []withdrawGameOrdermod.GameWithdrawOrder,
|
|
settlement *channelmod.ChannelSettlement,
|
|
start, end time.Time, appid int32) error {
|
|
|
|
for _, withdrawInfo := range withdrawList {
|
|
if ruleInfo.Channel == withdrawInfo.DistrictCode {
|
|
settlement.GameWithdrawAmount += withdrawInfo.Money
|
|
}
|
|
}
|
|
|
|
for _, rechageInfo := range rechageList {
|
|
if ruleInfo.Channel == rechageInfo.DistrictCode {
|
|
settlement.GameRechageAmount += rechageInfo.Money
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// channelLandPageMethod 落地页访问
|
|
func channelLandPageMethod(ctx context.Context, settlement *channelmod.ChannelSettlement, start, end time.Time, appid int32) error {
|
|
itemList, err := downloadinfo.GetChannelDownloadPageListByTime(ctx, settlement.Channel, appid, start, end)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
androidClick := int64(0)
|
|
appstoreClick := int64(0)
|
|
iosAtherClick := int64(0)
|
|
lightClick := int64(0)
|
|
|
|
for _, downloadInfo := range itemList {
|
|
if downloadInfo.SysType == "android" {
|
|
androidClick += 1
|
|
} else if strings.Contains(downloadInfo.SysType, "ios") || strings.Contains(downloadInfo.SysType, "light") {
|
|
if downloadInfo.PackageType == versionMod.Shop {
|
|
appstoreClick += 1
|
|
} else if downloadInfo.PackageType == versionMod.Enterprise {
|
|
iosAtherClick += 1
|
|
} else if downloadInfo.PackageType == versionMod.Light {
|
|
lightClick += 1
|
|
}
|
|
}
|
|
}
|
|
|
|
settlement.LandPageVisitCount = int64(len(itemList))
|
|
settlement.LandpageAndroidClick = androidClick
|
|
settlement.LandpageIosAppstoreClick = appstoreClick
|
|
settlement.LandpageIosAthorClick = iosAtherClick
|
|
settlement.LandpageIosH5Click = lightClick
|
|
|
|
return nil
|
|
}
|
|
|
|
// ChannelSettlementMethod 渠道计算
|
|
func ChannelSettlementMethod(ctx context.Context, start time.Time, end time.Time, appIds []int32) error {
|
|
for _, appid := range appIds {
|
|
channelDeductionRules, err := channelmod.FindManyChannelDeductionRule(ctx, bson.M{channelmod.FN.ChannelDeductionRule.AppId: appid})
|
|
if err != nil {
|
|
log.Error("ChannelSettlementMethod FindManyChannelDeductionRule", log.E(err))
|
|
return err
|
|
}
|
|
|
|
channnels := make([]string, 0)
|
|
for _, channnelInfo := range channelDeductionRules {
|
|
channnels = append(channnels, channnelInfo.Channel)
|
|
}
|
|
channelInfolist, err := channelmod.FindManyChannelInfo(ctx, bson.M{channelmod.FN.ChannelInfo.Channel: bson.M{"$in": channnels}})
|
|
if err != nil {
|
|
log.Error("ChannelSettlementMethod FindManyChannelInfo", log.E(err))
|
|
return err
|
|
}
|
|
registerList, err := registermod.RegisterUsersInfoByTime(ctx, appid, start, end)
|
|
if err != nil {
|
|
log.Error("NewCountMethod RegisterUsersInfoByDistrict ", log.E(err))
|
|
return err
|
|
}
|
|
|
|
registerFormalList, err := registermod.RegisterFormalsInfoByTime(ctx, appid, start, end)
|
|
if err != nil {
|
|
log.Error("NewCountMethod RegisterUsersInfoByDistrict ", log.E(err))
|
|
return err
|
|
}
|
|
|
|
vipfilter := bson.M{
|
|
syncvip.FN.SyncVip.AppId: appid,
|
|
syncvip.FN.SyncVip.SuccessAt: bson.M{"$gte": start, "$lt": end},
|
|
}
|
|
|
|
VipList, err := syncvip.FindManySyncVip(ctx, vipfilter)
|
|
if err != nil {
|
|
log.Error("ChannelChannelStatMethod FindManyVisitInfo ", log.E(err))
|
|
return err
|
|
}
|
|
|
|
visitFilter := bson.M{"appId": appid, "visitAt": bson.M{"$gte": start, "$lt": end}}
|
|
visitList, _ := accessmod.FindManyVisitInfo(ctx, visitFilter)
|
|
|
|
rechargeFilter := bson.M{"appId": appid, "successAt": bson.M{"$gte": start, "$lt": end}}
|
|
rechargeList, _ := rechargemod.FindManyRechargeInfo(ctx, rechargeFilter)
|
|
|
|
for _, ruleInfo := range channelDeductionRules {
|
|
if ruleInfo.CreatedAt.After(start) {
|
|
continue
|
|
}
|
|
//fmt.Println("channelDeductionRules", ruleInfo.Channel)
|
|
settlement := &channelmod.ChannelSettlement{
|
|
SumDate: start,
|
|
AppId: appid,
|
|
AppType: ruleInfo.AppType,
|
|
PromoteMode: ruleInfo.PromoteMode,
|
|
Channel: ruleInfo.Channel,
|
|
}
|
|
for _, channelInfo := range channelInfolist {
|
|
if channelInfo.Channel == ruleInfo.Channel {
|
|
settlement.Type = channelInfo.Type
|
|
settlement.ParentChannel = channelInfo.ParentChannel
|
|
settlement.UserName = channelInfo.UserName
|
|
}
|
|
}
|
|
if ruleInfo.SettlementTime == start {
|
|
// 已经结算
|
|
continue
|
|
}
|
|
|
|
statFilter := bson.M{
|
|
channelmod.FN.ChannelStat.Channel: ruleInfo.Channel,
|
|
channelmod.FN.ChannelStat.SumDate: utils.BeginWithTime(start),
|
|
channelmod.FN.ChannelStat.AppId: appid,
|
|
}
|
|
|
|
channelStatInfo, err := channelmod.FindOneChannelStat(ctx, statFilter)
|
|
if err != nil {
|
|
log.Error("ChannelSettlementMethod CountChannelStats", log.E(err))
|
|
return err
|
|
}
|
|
|
|
// 统计新增情况
|
|
userDict := make(map[uint64]bool)
|
|
channelRegisterList := make([]*registermod.RegisterMod, 0)
|
|
for _, v := range registerFormalList {
|
|
if v.IsFormal && statutils.IsClientH5OrLight(v.SysType, v.DevType) {
|
|
if v.DistrictCode == ruleInfo.Channel {
|
|
userDict[v.UserId] = true
|
|
channelRegisterList = append(channelRegisterList, v)
|
|
}
|
|
}
|
|
}
|
|
for _, v := range registerList {
|
|
if v.DistrictCode == ruleInfo.Channel {
|
|
if _, exists := userDict[v.UserId]; !exists {
|
|
userDict[v.UserId] = true
|
|
channelRegisterList = append(channelRegisterList, v)
|
|
}
|
|
}
|
|
}
|
|
oldIncomeRate := float64(0)
|
|
if channelStatInfo != nil {
|
|
oldIncomeRate = channelStatInfo.IncomeRate
|
|
}
|
|
deductionCountMethod(ctx, ruleInfo, settlement, channelRegisterList, oldIncomeRate)
|
|
|
|
// 统计访问量
|
|
channelAccessList := make(accessmod.VisitInfoList, 0)
|
|
for _, v := range visitList {
|
|
if v.DistrictCode == ruleInfo.Channel {
|
|
channelAccessList = append(channelAccessList, v)
|
|
}
|
|
}
|
|
channelChannelStatMethod(ctx, ruleInfo, settlement, channelAccessList, start, end, appid)
|
|
|
|
// 统计充值数据
|
|
channelRechargeList := make(rechargemod.RechargeInfoList, 0)
|
|
for _, v := range rechargeList {
|
|
if v.DistrictCode == ruleInfo.Channel {
|
|
channelRechargeList = append(channelRechargeList, v)
|
|
}
|
|
}
|
|
channelRechargeCountMethod(ctx, ruleInfo, settlement, channelRechargeList, start, end, appid)
|
|
|
|
// 统计VIP购买
|
|
channelVipList := make(syncvip.SyncVipList, 0)
|
|
for _, v := range VipList {
|
|
if v.DistrictCode == ruleInfo.Channel {
|
|
channelVipList = append(channelVipList, v)
|
|
}
|
|
}
|
|
channelVipMethod(ctx, ruleInfo, settlement, channelVipList, start, end, appid)
|
|
|
|
channelLandPageMethod(ctx, settlement, start, end, appid)
|
|
|
|
// 更新渠道信息
|
|
ruleFilter := bson.M{channelmod.FN.ChannelDeductionRule.ID: ruleInfo.ID}
|
|
ruleSet := bson.M{"$set": bson.M{
|
|
channelmod.FN.ChannelDeductionRule.SettlementTime: start,
|
|
channelmod.FN.ChannelDeductionRule.TodayTime: ruleInfo.TodayTime,
|
|
channelmod.FN.ChannelDeductionRule.TodayDeduction: ruleInfo.TodayDeduction,
|
|
}}
|
|
|
|
err = channelmod.UpdateManyChannelDeductionRule(ctx, ruleFilter, ruleSet)
|
|
if err != nil {
|
|
log.Error("ChannelSettlementMethod UpdateManyChannelDeductionRule", log.E(err))
|
|
return err
|
|
}
|
|
|
|
settlement.CorrectValidData()
|
|
|
|
//插入数据
|
|
err = channelmod.InsertOneChannelSettlement(ctx, settlement)
|
|
if err != nil {
|
|
log.Error("ChannelSettlementMethod InsertOneChannelSettlement", log.E(err))
|
|
return err
|
|
}
|
|
|
|
if channelStatInfo.Channel != ruleInfo.Channel {
|
|
channelStatInfo.Channel = ruleInfo.Channel
|
|
channelStatInfo.SumDate = utils.BeginWithTime(start)
|
|
channelStatInfo.AppId = appid
|
|
channelStatInfo.Type = settlement.Type
|
|
channelStatInfo.UserName = settlement.UserName
|
|
channelStatInfo.Settlement = ruleInfo.Settlement
|
|
channelStatInfo.CPAPrice = ruleInfo.CPAPrice
|
|
channelStatInfo.CPSRate = ruleInfo.CPSRate
|
|
channelStatInfo.AppType = ruleInfo.AppType
|
|
channelStatInfo.PromoteMode = ruleInfo.PromoteMode
|
|
channelStatInfo.ParentChannel = settlement.ParentChannel
|
|
channelStatInfo.IsPay = false
|
|
// 数据赋值
|
|
settlement.AssignmentTo(channelStatInfo)
|
|
// 插入记录
|
|
err = channelmod.InsertOneChannelStat(ctx, channelStatInfo)
|
|
if err != nil {
|
|
log.Error("ChannelSettlementMethod InsertOneChannelStat", log.E(err))
|
|
return err
|
|
}
|
|
} else {
|
|
// 数据累加
|
|
settlement.AccumulateTo(channelStatInfo)
|
|
// 更新记录
|
|
setdoc := bson.M{"$set": channelStatInfo}
|
|
err = channelmod.UpdateOneChannelStat(ctx, statFilter, setdoc)
|
|
if err != nil {
|
|
log.Error("ChannelSettlementMethod UpdateOneChannelStat", log.E(err))
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 更新渠道数据
|
|
func ChannelSettlementUpdateByHour() error {
|
|
ctx := context.Background()
|
|
nowHour := utils.BeginOfHour()
|
|
|
|
statFilter := bson.M{
|
|
channelmod.FN.ChannelStat.SumDate: utils.BeginWithTime(nowHour.Add(-30 * time.Minute)), // 确保:0点是获取上一天数据
|
|
"$or": bson.A{
|
|
bson.M{channelmod.FN.ChannelStat.NewDirectCount: bson.M{"$gt": 0}},
|
|
bson.M{channelmod.FN.ChannelStat.DirectAmount: bson.M{"$gt": 0}},
|
|
},
|
|
}
|
|
statList, err := channelmod.FindManyChannelStat(ctx, statFilter)
|
|
if err != nil {
|
|
log.Error("ChannelSettlementUpdateByHour FindManyChannelStat", log.E(err))
|
|
return err
|
|
}
|
|
|
|
yesterdayFilter := bson.M{
|
|
channelmod.FN.ChannelStatYestoday.SumDate: nowHour.AddDate(0, 0, -1),
|
|
}
|
|
|
|
statYesterdayList, _ := channelmod.FindManyChannelStatYestoday(ctx, yesterdayFilter)
|
|
|
|
var succeed, failed int
|
|
for _, channelStatInfo := range statList {
|
|
channelStatInfoYesterday := &channelmod.ChannelStatYesterday{
|
|
// base
|
|
Channel: channelStatInfo.Channel,
|
|
SumDate: nowHour,
|
|
AppId: channelStatInfo.AppId,
|
|
ParentChannel: channelStatInfo.ParentChannel,
|
|
Settlement: channelStatInfo.Settlement,
|
|
UpdatedAt: time.Now(),
|
|
CreatedAt: time.Now(),
|
|
// new
|
|
NewCount: channelStatInfo.NewTotalCount,
|
|
NewDirectCount: channelStatInfo.NewDirectCount,
|
|
NewFissionCount: channelStatInfo.NewFissionCount,
|
|
NewAndroidCount: channelStatInfo.NewAndroidCount,
|
|
NewIosCount: channelStatInfo.NewIosCount,
|
|
NewH5Count: channelStatInfo.NewH5Count,
|
|
NewH5FormalCount: channelStatInfo.NewH5FormalCount,
|
|
NewLightGuestCount: channelStatInfo.NewLightGuestCount,
|
|
NewLightFormalCount: channelStatInfo.NewLightFormalCount,
|
|
// recharge
|
|
RechargeAmount: channelStatInfo.TotalAmount,
|
|
DirectAmount: channelStatInfo.DirectAmount,
|
|
FissionAmount: channelStatInfo.FissionAmount,
|
|
AndroidRechargeAmount: channelStatInfo.AndroidAmount,
|
|
IosRechargeAmount: channelStatInfo.IosAmount,
|
|
LightRechargeAmount: channelStatInfo.LightAmount,
|
|
H5RechargeAmount: channelStatInfo.H5Amount,
|
|
// other
|
|
VipPayCoin: channelStatInfo.VipPayCoin,
|
|
VipPayMoney: channelStatInfo.VipPayMoney,
|
|
VipPayDeduction: channelStatInfo.VipPayDeduction,
|
|
}
|
|
|
|
for _, yesterdayStatInfo := range statYesterdayList {
|
|
// 获取昨天数据
|
|
if yesterdayStatInfo.Channel == channelStatInfo.Channel && yesterdayStatInfo.AppId == channelStatInfo.AppId {
|
|
newYesterday := yesterdayStatInfo.NewCount
|
|
newToday := channelStatInfo.NewTotalCount
|
|
channelStatInfoYesterday.NewIncreaseCount = newToday - newYesterday
|
|
if newYesterday != 0 {
|
|
channelStatInfoYesterday.NewIncreaseRate = fmt.Sprintf("%.2f", float64(newToday-newYesterday)*100/float64(newYesterday)) + "%"
|
|
}
|
|
rechargeYesterday := yesterdayStatInfo.RechargeAmount
|
|
rechargeToday := channelStatInfo.TotalAmount
|
|
channelStatInfoYesterday.RechargeIncreaseAmount = rechargeToday - rechargeYesterday
|
|
if rechargeYesterday != 0 {
|
|
channelStatInfoYesterday.RechargeIncreaseRate = fmt.Sprintf("%.2f", float64(rechargeToday-rechargeYesterday)*100/float64(rechargeYesterday)) + "%"
|
|
}
|
|
}
|
|
}
|
|
|
|
// 单条失败只记录并继续,不能因为一个渠道写失败就丢掉后面所有渠道
|
|
if err := channelmod.UpsertOneChannelStatYestoday(ctx, channelStatInfoYesterday); err != nil {
|
|
failed++
|
|
log.Error("ChannelSettlementUpdateByHour UpsertOneChannelStatYestoday",
|
|
log.E(err),
|
|
log.Any("channel", channelStatInfoYesterday.Channel),
|
|
log.Any("appId", channelStatInfoYesterday.AppId),
|
|
log.Any("sumDate", channelStatInfoYesterday.SumDate))
|
|
continue
|
|
}
|
|
succeed++
|
|
}
|
|
|
|
log.Info("ChannelSettlementUpdateByHour done",
|
|
log.Any("sumDate", nowHour),
|
|
log.Any("total", len(statList)),
|
|
log.Any("succeed", succeed),
|
|
log.Any("failed", failed))
|
|
|
|
if failed > 0 {
|
|
return fmt.Errorf("渠道同时段对比数据写入失败 %d 条(成功 %d 条)", failed, succeed)
|
|
}
|
|
return nil
|
|
}
|