Files
stat_center/skd/job/statminute/method.go
T
2026-11-05 12:11:56 +08:00

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
}