From 4a57f04cf4bac26976fd47703c123d71906e5086 Mon Sep 17 00:00:00 2001 From: Leufolium Date: Fri, 7 Jun 2024 16:45:01 +0800 Subject: [PATCH] by Robin at 20240607; refund rate --- app/mix/dao/mongo.go | 44 +++++++++++++++++ app/mix/dao/mysql.go | 18 +++++++ app/mix/service/logic/streamer_score.go | 30 ++++++++++++ app/mix/service/logic/vas.go | 4 ++ app/mix/service/service.go | 4 +- app/mix/service/streamer_recomm_service.go | 56 +++++++++++++++++++--- dbstruct/streamer_score.go | 14 ++++++ dbstruct/vas_mysql.go | 20 ++++++++ 8 files changed, 182 insertions(+), 8 deletions(-) create mode 100644 app/mix/service/logic/streamer_score.go create mode 100644 dbstruct/streamer_score.go diff --git a/app/mix/dao/mongo.go b/app/mix/dao/mongo.go index c8c65540..3fd64a9a 100644 --- a/app/mix/dao/mongo.go +++ b/app/mix/dao/mongo.go @@ -210,6 +210,9 @@ const ( DBVideoModeration = "video_moderation" COLVideoModeration = "video_moderation" COLVideoModerationTask = "video_moderation_task" + + DBStreamerScore = "streamer_score" + COLStreamerScore = "streamer_score" ) // 商品表 @@ -531,6 +534,11 @@ func (m *Mongo) getColDailyStatementZoneInfo() *qmgo.Collection { return m.clientMix.Database(DBDailyStatement).Collection(COLDailyStatementZoneInfo) } +// 每小时临时统计主播得分表 +func (m *Mongo) getColStreamerScore() *qmgo.Collection { + return m.clientMix.Database(DBStreamerScore).Collection(COLStreamerScore) +} + // 商品相关 func (m *Mongo) CreateProduct(ctx *gin.Context, product *dbstruct.Product) error { col := m.getColProduct() @@ -5173,3 +5181,39 @@ func (m *Mongo) CreateBatchDailyStatementZoneInfo(ctx *gin.Context, dlyStmtZoneI _, err := col.InsertMany(ctx, dlyStmtZoneInfos) return err } + +func (m *Mongo) SetStreamerScore(ctx *gin.Context, list []*dbstruct.StreamerScore) error { + col := m.getColStreamerScore() + + // 再写 + bulk := col.Bulk() + timeNow := time.Now().Unix() + for _, item := range list { + query := qmgo.M{ + "_id": item.Id, + } + update := qmgo.M{ + "$setOnInsert": bson.M{ + "ct": timeNow, + }, + "$set": bson.M{ + "zone_moment_count_in_three_days": item.ZoneMomentCountInThreeDays, + "zone_moment_count_in_a_month": item.ZoneMomentCountInAMonth, + "income_in_a_week": item.IncomeInAWeek, + "new_zone_member_count_in_three_days": item.NewZoneMemberCountInThreeDays, + "new_zone_member_count_in_a_month": item.NewZoneMemberCountInAMonth, + "moment_count_in_three_days": item.MomentCountInThreeDays, + "refund_rate": item.RefundRate, + "score": item.Score, + "ut": timeNow, + }, + } + bulk.UpsertOne(query, update) + } + _, err := bulk.Run(ctx) + if err != nil { + logger.Error("bulk Run fail, err: %v", err) + return err + } + return err +} diff --git a/app/mix/dao/mysql.go b/app/mix/dao/mysql.go index 1807a688..e065611d 100644 --- a/app/mix/dao/mysql.go +++ b/app/mix/dao/mysql.go @@ -1244,3 +1244,21 @@ func (m *Mysql) GetIncomeByTimeSpanGroupByMid(ctx *gin.Context, tx *sqlx.Tx, st, } return list, nil } + +// 统计退款率 +func (m *Mysql) GetRefundRateGroupByMid(ctx *gin.Context, tx *sqlx.Tx) ([]*dbstruct.RefundRate, error) { + var sql strings.Builder + var err error + sql.WriteString(fmt.Sprintf("select rc/ac as refund_rate, t1.uid as mid from (SELECT count(*) as ac, uid FROM %s where uid != 0 group by uid) t1 left join (SELECT count(*) as rc, uid FROM %s where uid != 0 and order_status = 3 group by uid) t2 on t1.uid = t2.uid", TableOrder, TableOrder)) + list := make([]*dbstruct.RefundRate, 0) + if tx != nil { + err = tx.SelectContext(ctx, &list, sql.String()) + } else { + db := m.getDBVas() + err = db.SelectContext(ctx, &list, sql.String()) + } + if err != nil { + return make([]*dbstruct.RefundRate, 0), err + } + return list, nil +} diff --git a/app/mix/service/logic/streamer_score.go b/app/mix/service/logic/streamer_score.go new file mode 100644 index 00000000..47fd75c4 --- /dev/null +++ b/app/mix/service/logic/streamer_score.go @@ -0,0 +1,30 @@ +package logic + +import ( + "service/app/mix/dao" + "service/bizcommon/util" + "service/dbstruct" + "service/library/logger" + + "github.com/gin-gonic/gin" +) + +type StreamerScore struct { + store *dao.Store +} + +func NewStreamerScore(store *dao.Store) (a *StreamerScore) { + a = &StreamerScore{ + store: store, + } + return +} + +func (p *StreamerScore) OpSetStreamerScore(ctx *gin.Context, list []*dbstruct.StreamerScore) error { + err := p.store.SetStreamerScore(ctx, list) + if err != nil { + logger.Error("SetStreamerScore fail, list: %v, err: %v", util.ToJson(list), err) + return err + } + return nil +} diff --git a/app/mix/service/logic/vas.go b/app/mix/service/logic/vas.go index 8fa8253b..b4bfb3fe 100644 --- a/app/mix/service/logic/vas.go +++ b/app/mix/service/logic/vas.go @@ -3587,3 +3587,7 @@ func (v *Vas) GetTotalFinishIncome(ctx *gin.Context, tx *sqlx.Tx, mid int64, ord func (v *Vas) GetIncomeByTimeSpanGroupByMid(ctx *gin.Context, tx *sqlx.Tx, st, et int64) ([]*dbstruct.StreamerProfit, error) { return v.store.GetIncomeByTimeSpanGroupByMid(ctx, tx, st, et) } + +func (v *Vas) GetRefundRateGroupByMid(ctx *gin.Context, tx *sqlx.Tx) ([]*dbstruct.RefundRate, error) { + return v.store.GetRefundRateGroupByMid(ctx, tx) +} diff --git a/app/mix/service/service.go b/app/mix/service/service.go index ad18c695..f853d2e9 100644 --- a/app/mix/service/service.go +++ b/app/mix/service/service.go @@ -128,6 +128,7 @@ var ( _DefaultDailyStatementZoneInfo *logic.DailyStatementZoneInfo _DefaultStreamerAcct *logic.StreamerAcct _DefaultContentAuditRTI *logic.ContentAuditRTI + _DefaultStreamerScore *logic.StreamerScore ) type Service struct { @@ -218,6 +219,7 @@ func (s *Service) Init(c any) (err error) { _DefaultVideoModerationTask = logic.NewVideoModerationTask(store) _DefaultDailyStatementZoneInfo = logic.NewDailyStatementZoneInfo(store) _DefaultContentAuditRTI = logic.NewContentAuditRTI(store) + _DefaultStreamerScore = logic.NewStreamerScore(store) _DefaultVas = logic.NewVas(store, _DefaultStreamer, _DefaultAccount, _DefaultZone, _DefaultZoneThirdPartner, _DefaultZoneCollaborator) _DefaultStreamerAcct = logic.NewStreamerAcct(store) @@ -262,7 +264,7 @@ func (s *Service) ConnectToVideoModeration() { // 推荐服务数据库接口 func (s *Service) ConnectToStreamerRecommService(r *StreamerRecommService) { - r.SetStreamerRecommDbService(_DefaultMoment, _DefaultZoneMoment, _DefaultVas, _DefaultStreamer) + r.SetStreamerRecommDbService(_DefaultMoment, _DefaultZoneMoment, _DefaultVas, _DefaultStreamer, _DefaultStreamerScore) r.SetOut(func(mids []int64) error { err := redis.GetRedisClient().Set(consts.RedisStreamerPrefix+"recomm_list", mids, 0) if err != nil { diff --git a/app/mix/service/streamer_recomm_service.go b/app/mix/service/streamer_recomm_service.go index fec7f94f..4b4bf758 100644 --- a/app/mix/service/streamer_recomm_service.go +++ b/app/mix/service/streamer_recomm_service.go @@ -6,6 +6,7 @@ import ( "service/api/consts" "service/apollostruct" "service/app/mix/service/logic" + "service/dbstruct" "service/library/apollo" "service/library/logger" "sort" @@ -20,11 +21,12 @@ var ( ) type StreamerRecommService struct { - momentService *logic.Moment - zoneMomentService *logic.ZoneMoment - vasService *logic.Vas - streamerService *logic.Streamer - out func([]int64) error + momentService *logic.Moment + zoneMomentService *logic.ZoneMoment + vasService *logic.Vas + streamerService *logic.Streamer + streamerScoreService *logic.StreamerScore + out func([]int64) error formula *apollostruct.StreamerScoreFormulaCfg @@ -36,11 +38,12 @@ func NewStreamerRecommService() *StreamerRecommService { return new(StreamerRecommService) } -func (s *StreamerRecommService) SetStreamerRecommDbService(moment *logic.Moment, zonemoment *logic.ZoneMoment, vas *logic.Vas, streamer *logic.Streamer) { +func (s *StreamerRecommService) SetStreamerRecommDbService(moment *logic.Moment, zonemoment *logic.ZoneMoment, vas *logic.Vas, streamer *logic.Streamer, streamerScore *logic.StreamerScore) { s.momentService = moment s.zoneMomentService = zonemoment s.vasService = vas s.streamerService = streamer + s.streamerScoreService = streamerScore } func (s *StreamerRecommService) SetOut(out func([]int64) error) { @@ -177,6 +180,13 @@ func (s *StreamerRecommService) recvMsg(ctx *gin.Context, nt int64) (err error) return } + // 退款率 + err = s.recvRefundRate(ctx) + if err != nil { + logger.Error("recvRefundRate fail, err: %v", err) + return + } + return } @@ -202,10 +212,26 @@ func (s *StreamerRecommService) save() { // 推送 func (s *StreamerRecommService) push() error { list := make([]int64, 0) + l := make([]*dbstruct.StreamerScore, 0) for i := len(s.scorelist) - 1; i >= 0; i-- { v := s.scorelist[i] - //logger.Info("%v得分:%v %v %v %v %v %v %v", v.Mid, v.Score, v.ZoneMomentCountInThreeDays, v.ZoneMomentCountInAMonth, v.IncomeInAWeek, v.NewZoneMemberCountInThreeDays, v.NewZoneMemberCountInAMonth, v.MomentCountInThreeDays) list = append(list, v.Mid) + l = append(l, &dbstruct.StreamerScore{ + Id: v.Mid, + Mid: v.Mid, + ZoneMomentCountInThreeDays: v.ZoneMomentCountInThreeDays, + ZoneMomentCountInAMonth: v.ZoneMomentCountInAMonth, + IncomeInAWeek: v.IncomeInAWeek, + NewZoneMemberCountInThreeDays: v.NewZoneMemberCountInThreeDays, + NewZoneMemberCountInAMonth: v.NewZoneMemberCountInAMonth, + MomentCountInThreeDays: v.MomentCountInThreeDays, + RefundRate: v.RefundRate, + Score: v.Score, + }) + } + err := _DefaultStreamerScore.OpSetStreamerScore(&gin.Context{}, l) + if err != nil { + logger.Error("OpSetStreamerScore fail, err: %v", err) } return s.out(list) @@ -308,6 +334,22 @@ func (s *StreamerRecommService) recvMomentStatInfoInThreeDays(ctx *gin.Context, return } +func (s *StreamerRecommService) recvRefundRate(ctx *gin.Context) (err error) { + + refundRateList, err := s.vasService.GetRefundRateGroupByMid(ctx, nil) + if err != nil { + logger.Error("GetRefundRateGroupByMid in three days fail, err: %v", err) + return + } + + for _, rr := range refundRateList { + if _, ok := s.scores[rr.GetMid()]; ok { + s.scores[rr.GetMid()].RefundRate = rr.GetRefundRate() + } + } + return +} + /* *@author Robin *@class 主播打分 diff --git a/dbstruct/streamer_score.go b/dbstruct/streamer_score.go new file mode 100644 index 00000000..36f2e732 --- /dev/null +++ b/dbstruct/streamer_score.go @@ -0,0 +1,14 @@ +package dbstruct + +type StreamerScore struct { + Id int64 `json:"id" bson:"_id"` + Mid int64 `json:"mid" bson:"mid"` + ZoneMomentCountInThreeDays int64 `json:"zone_moment_count_in_three_days" bson:"zone_moment_count_in_three_days"` + ZoneMomentCountInAMonth int64 `json:"zone_moment_count_in_a_month" bson:"zone_moment_count_in_a_month"` + IncomeInAWeek int64 `json:"income_in_a_week" bson:"income_in_a_week"` + NewZoneMemberCountInThreeDays int64 `json:"new_zone_member_count_in_three_days" bson:"new_zone_member_count_in_three_days"` + NewZoneMemberCountInAMonth int64 `json:"new_zone_member_count_in_a_month" bson:"new_zone_member_count_in_a_month"` + MomentCountInThreeDays int64 `json:"moment_count_in_three_days" bson:"moment_count_in_three_days"` + RefundRate float64 `json:"refund_rate" bson:"refund_rate"` + Score float64 `json:"score" bson:"score"` +} diff --git a/dbstruct/vas_mysql.go b/dbstruct/vas_mysql.go index 9c8877a2..96338fee 100644 --- a/dbstruct/vas_mysql.go +++ b/dbstruct/vas_mysql.go @@ -1462,3 +1462,23 @@ func (p *ZoneAdmissionInfo) GetNum() int64 { } return 0 } + +// 退款率 +type RefundRate struct { + Mid *int64 `json:"mid" db:"mid"` // 用户id + RefundRate *float64 `json:"refund_rate" db:"refund_rate"` // 退款率 +} + +func (p *RefundRate) GetMid() int64 { + if p != nil && p.Mid != nil { + return *p.Mid + } + return 0 +} + +func (p *RefundRate) GetRefundRate() float64 { + if p != nil && p.RefundRate != nil { + return *p.RefundRate + } + return 0 +}