@@ -0,0 +1,602 @@
|
||||
package payvidlgmod
|
||||
|
||||
import (
|
||||
"91porn-server/models/commod"
|
||||
"fmt"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"91porn-server/common/db"
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/common/pageopt"
|
||||
"91porn-server/common/timeutil"
|
||||
"91porn-server/models"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
var mdb *db.MongoDB
|
||||
|
||||
const table = models.PayVideoLog
|
||||
|
||||
// initIndex 初始化索引
|
||||
func initIndex() {
|
||||
many := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{{Key: "uid", Value: 1}, {Key: "videoID", Value: 1}},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{{Key: "createdAt", Value: -1}},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{{Key: "uniq", Value: 1}},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{{Key: "deductType", Value: 1}, {Key: "createdAt", Value: -1}},
|
||||
Options: options.Index().SetSparse(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{{Key: "videoID", Value: 1}},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{{Key: "publisherID", Value: 1}},
|
||||
},
|
||||
}
|
||||
if _, err := coll(nil).CreateIndex(many); err != nil {
|
||||
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
|
||||
}
|
||||
}
|
||||
|
||||
func coll(t *db.MongoTool) *db.MongoTool {
|
||||
if t == nil {
|
||||
return mdb.Coll(table)
|
||||
}
|
||||
return t.Coll(table)
|
||||
}
|
||||
|
||||
// InsertVideoPayRecord 插入一条购买记录
|
||||
func InsertVideoPayRecord(t *db.MongoTool, p Pay4VidLog) error {
|
||||
p.Uniq = Unique(p.UID, p.VideoID)
|
||||
p.CreatedAt = time.Now()
|
||||
res, err := coll(t).InsertOne(&p)
|
||||
if err != nil {
|
||||
log.Error("InsertVideoPayRecord error", log.Any("p", p), log.E(err))
|
||||
return err
|
||||
}
|
||||
p.ID = res.InsertedID.(ObjectID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsPay4Video 用户是否购买了视频
|
||||
func IsPay4Video(uid uint64, videoID ObjectID) (bool, error) {
|
||||
cnt, err := coll(nil).Count(bson.M{"uid": uid, "videoID": videoID})
|
||||
if err != nil {
|
||||
log.Error("IsPay4Video error", log.Any("uid", uid), log.Any("videoID", videoID), log.E(err))
|
||||
return false, err
|
||||
}
|
||||
return cnt != 0, nil
|
||||
}
|
||||
|
||||
func FindManyPay4VidLogByUID(uid uint64, newsType string) ([]*Pay4VidLog, error) {
|
||||
vl := make([]*Pay4VidLog, 0)
|
||||
err := coll(nil).Find(&vl, bson.M{"uid": uid, "newsType": newsType})
|
||||
if err != nil {
|
||||
log.Error("FindManyPay4VidLogByUID error", log.Any("uid", uid), log.Any("err", err.Error()))
|
||||
return nil, err
|
||||
}
|
||||
return vl, nil
|
||||
}
|
||||
|
||||
// IsPay4Videos 用户是否购买了视频
|
||||
func IsPay4Videos(uid uint64, videoIDs []ObjectID) (map[ObjectID]bool, error) {
|
||||
if videoIDs == nil {
|
||||
videoIDs = []ObjectID{}
|
||||
}
|
||||
m := make(map[ObjectID]bool)
|
||||
var infos []Pay4VidLog
|
||||
query := bson.M{"uid": uid, "videoID": bson.M{"$in": videoIDs}}
|
||||
if err := coll(nil).Find(&infos, query); err != nil {
|
||||
log.Error("IsPay4Videos error", log.Any("uid", uid), log.Any("videoIDs", videoIDs), log.E(err))
|
||||
return m, err
|
||||
}
|
||||
for _, i := range infos {
|
||||
m[i.VideoID] = true
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// 判断当前视频是否有人购买过
|
||||
func IsVidIfBePay(id primitive.ObjectID) bool {
|
||||
var pay *Pay4VidLog
|
||||
if err := coll(nil).FindOne(&pay, bson.M{"videoID": id}); err != nil {
|
||||
log.Error("IsVidIfBePay error", log.Any("videoID", id), log.E(err))
|
||||
return false
|
||||
}
|
||||
return pay != nil
|
||||
}
|
||||
|
||||
// DelVideoPayRecord 删除一条购买记录
|
||||
func DelVideoPayRecord(videoID primitive.ObjectID, uid uint64) error {
|
||||
if _, err := coll(nil).DeleteOne(bson.M{"videoID": videoID, "uid": uid}); err != nil {
|
||||
log.Error("DelVideoPayRecord DeleteOne error", log.Any("videoID", videoID), log.Any("uid", uid))
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 从给定的hash列表中获取购买状态映射:uniq->Statue
|
||||
// uniq通过Unique()获取
|
||||
func PayStatueMap(uniqList []string) (map[string]bool, error) {
|
||||
filter := bson.M{
|
||||
"uniq": bson.M{"$in": uniqList},
|
||||
}
|
||||
payLogList := make([]Pay4VidLog, 0, len(uniqList))
|
||||
if err := coll(nil).Find(&payLogList, filter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[string]bool, len(payLogList))
|
||||
//初始化
|
||||
for _, uniq := range uniqList {
|
||||
m[uniq] = false
|
||||
}
|
||||
//已经收藏的
|
||||
for _, v := range payLogList {
|
||||
uniq := v.Uniq
|
||||
m[uniq] = true
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func GetUIDListByPayTime(start time.Time, end time.Time) ([]uint64, error) {
|
||||
filter := bson.M{
|
||||
"createdAt": bson.M{
|
||||
"$gte": start,
|
||||
"$lt": end,
|
||||
},
|
||||
}
|
||||
list := make([]struct {
|
||||
UID uint64 `bson:"uid"`
|
||||
}, 0)
|
||||
if err := coll(nil).Find(&list, filter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uidList := make([]uint64, len(list))
|
||||
for i, v := range list {
|
||||
uidList[i] = v.UID
|
||||
}
|
||||
return uidList, nil
|
||||
}
|
||||
|
||||
func GetPayMoneyByTime(start time.Time, end time.Time) (int64, error) {
|
||||
filter := bson.M{
|
||||
"createdAt": bson.M{
|
||||
"$gte": start,
|
||||
"$lt": end,
|
||||
},
|
||||
}
|
||||
logs := make([]Pay4VidLog, 0)
|
||||
if err := coll(nil).Find(&logs, filter); err != nil {
|
||||
return 0, fmt.Errorf("table:%s GetPayMoneyByTime err: %s", table, err.Error())
|
||||
}
|
||||
total := int64(0)
|
||||
for _, v := range logs {
|
||||
total += v.PayMoney
|
||||
}
|
||||
return total, nil
|
||||
}
|
||||
|
||||
// FindManyVideoPayRecord 查询所有
|
||||
func FindThreeMonthVideoPayRecord(publisherID uint64, pageNumber, pageSize uint64) (total int64, totalAmount int64, data []*Pay4VidLog, hasNext bool, err error) {
|
||||
data = make([]*Pay4VidLog, 0)
|
||||
startTime := timeutil.NearMonth(time.Now(), 2)
|
||||
f := bson.M{"publisherID": publisherID, "createdAt": bson.M{"$gte": startTime}}
|
||||
skip := int64(pageSize * (pageNumber - 1))
|
||||
limit := int64(pageSize + 1)
|
||||
opts := options.FindOptions{
|
||||
Skip: &skip,
|
||||
Limit: &limit,
|
||||
Sort: bson.D{{Key: "createdAt", Value: -1}},
|
||||
}
|
||||
if err = coll(nil).Find(&data, f, &opts); err != nil {
|
||||
log.Error("FindManyVideoPayRecord error", log.Any("filter", f), log.E(err))
|
||||
}
|
||||
type Res struct {
|
||||
TotalAmount float64 `json:"totalAmount" bson:"totalAmount"`
|
||||
}
|
||||
totalIncome := []bson.M{
|
||||
{"$match": f},
|
||||
{
|
||||
"$group": bson.M{
|
||||
"_id": nil,
|
||||
"totalAmount": bson.M{
|
||||
"$sum": "$publisherIncome",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
ress := make([]Res, 0)
|
||||
if err = coll(nil).Aggregate(&ress, totalIncome); err != nil {
|
||||
log.Error("FindManyVideoPayRecord error", log.Any("filter", f), log.E(err))
|
||||
}
|
||||
if len(ress) > 0 {
|
||||
totalAmount = int64(math.Floor(ress[0].TotalAmount))
|
||||
}
|
||||
total, err = coll(nil).Count(f)
|
||||
if err != nil {
|
||||
log.Error("FindManyVideoPayRecord Count error", log.Any("filter", f), log.E(err))
|
||||
}
|
||||
if len(data) > int(pageSize) {
|
||||
hasNext = true
|
||||
data = data[:pageSize]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetWorksIncomeList 查询收益列表
|
||||
func GetWorksIncomeList(publisherID uint64, page commod.Page) (data []*Pay4VidLog, hasNext bool, err error) {
|
||||
data = make([]*Pay4VidLog, 0)
|
||||
opt := options.Find().
|
||||
SetLimit(page.Limit64() + 1).
|
||||
SetSkip(page.Skip64()).
|
||||
SetSort(bson.D{{"createdAt", -1}})
|
||||
|
||||
filter := bson.M{
|
||||
"publisherID": publisherID,
|
||||
}
|
||||
|
||||
if err = coll(nil).Find(&data, filter, opt); err != nil {
|
||||
log.Error("FindManyVideoPayRecord error", log.Any("filter", filter), log.E(err))
|
||||
return nil, false, err
|
||||
}
|
||||
hasNext = len(data) > int(page.Limit64())
|
||||
if hasNext {
|
||||
data = data[:page.Limit64()]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// PayCoinByCreatedTime 金币
|
||||
func PayCoinByCreatedTime(start time.Time, end time.Time) (int64, error) {
|
||||
pipeline := []bson.M{
|
||||
{
|
||||
"$match": bson.M{
|
||||
// createdAt ∈ [startTime, endTime)
|
||||
"createdAt": bson.M{
|
||||
"$gte": start,
|
||||
"$lt": end,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"$group": bson.M{
|
||||
"_id": nil,
|
||||
"totalAmount": bson.M{"$sum": "$payMoney"},
|
||||
},
|
||||
},
|
||||
}
|
||||
var ret struct {
|
||||
TotalAmount int64 `bson:"totalAmount"`
|
||||
}
|
||||
if err := coll(nil).AggregateDecode(&ret, pipeline); err != nil {
|
||||
return 0, fmt.Errorf("table:%s PayCoinByCreatedTime err: %s", table, err.Error())
|
||||
}
|
||||
return ret.TotalAmount, nil
|
||||
}
|
||||
|
||||
// PayCoinMapByTime vid->金币 map
|
||||
func PayCoinMapByTime(start time.Time, end time.Time) (map[ObjectID]int64, error) {
|
||||
pipeline := []bson.M{
|
||||
{
|
||||
"$match": bson.M{
|
||||
"createdAt": bson.M{
|
||||
"$gte": start,
|
||||
"$lt": end,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"$group": bson.M{
|
||||
"_id": "$videoID",
|
||||
"income": bson.M{
|
||||
"$sum": "$payMoney",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
var docList []struct {
|
||||
VID ObjectID `bson:"_id"`
|
||||
Income int64 `bson:"income"`
|
||||
}
|
||||
if err := coll(nil).Aggregate(&docList, pipeline); err != nil {
|
||||
return nil, fmt.Errorf("table:%s PayCoinMapByTime err: %s", table, err.Error())
|
||||
}
|
||||
ret := make(map[ObjectID]int64)
|
||||
for _, doc := range docList {
|
||||
ret[doc.VID] = doc.Income
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func VideoCoinIncomeGross(start, end time.Time) (int64, error) {
|
||||
matchStage := bson.M{
|
||||
"$match": bson.M{
|
||||
"createdAt": bson.M{
|
||||
"$gte": start,
|
||||
"$lt": end,
|
||||
},
|
||||
},
|
||||
}
|
||||
groupStage := bson.M{
|
||||
"$group": bson.M{
|
||||
"_id": nil,
|
||||
"gross": bson.M{
|
||||
"$sum": "$payMoney",
|
||||
},
|
||||
},
|
||||
}
|
||||
var gross struct {
|
||||
Gross int64 `bson:"gross"`
|
||||
}
|
||||
pipeline := []bson.M{matchStage, groupStage}
|
||||
// opts := options.Aggregate()
|
||||
if err := coll(nil).AggregateDecode(&gross, pipeline); err != nil {
|
||||
log.Error("VideoCoinIncomeGross err: " + err.Error())
|
||||
return 0, errors.Wrapf(err, "table:%s VideoCoinIncomeGross", table)
|
||||
}
|
||||
return gross.Gross, nil
|
||||
}
|
||||
|
||||
// VideoCoinIncomeAggregateByVideoIDs 根据视频ID统计视频的售卖总数以及总金币数
|
||||
func VideoCoinIncomeAggregateByVideoIDs(ids []primitive.ObjectID) (list []VideoCoinIncome, err error) {
|
||||
if len(ids) == 0 {
|
||||
return
|
||||
}
|
||||
matchStage := bson.M{
|
||||
"$match": bson.M{
|
||||
"videoID": bson.M{"$in": ids},
|
||||
},
|
||||
}
|
||||
groupStage := bson.M{
|
||||
"$group": bson.M{
|
||||
"_id": "$videoID",
|
||||
"total": bson.M{
|
||||
"$sum": "$payMoney",
|
||||
},
|
||||
"count": bson.M{
|
||||
"$sum": 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
pipeline := []bson.M{matchStage, groupStage}
|
||||
opts := options.Aggregate().SetMaxTime(10 * time.Second)
|
||||
if err := coll(nil).Aggregate(&list, pipeline, opts); err != nil {
|
||||
return nil, errors.Wrapf(err, "table:%s VideoCoinIncomeAggregateByVideoIDs", table)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// VideoCoinIncomeAggregate 聚合统计在给定时间段内视频收入排名前N的视频
|
||||
func VideoCoinIncomeAggregateTopN(topN int, start, end time.Time) (list []VideoCoinIncome, err error) {
|
||||
matchStage := bson.M{
|
||||
"$match": bson.M{
|
||||
"createdAt": bson.M{
|
||||
"$gte": start,
|
||||
"$lt": end,
|
||||
},
|
||||
},
|
||||
}
|
||||
groupStage := bson.M{
|
||||
"$group": bson.M{
|
||||
"_id": "$videoID",
|
||||
"total": bson.M{
|
||||
"$sum": "$payMoney",
|
||||
},
|
||||
"count": bson.M{
|
||||
"$sum": 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
sortStage := bson.M{
|
||||
"$sort": bson.M{
|
||||
"total": -1,
|
||||
"count": -1,
|
||||
},
|
||||
}
|
||||
limitStage := bson.M{
|
||||
"$limit": topN,
|
||||
}
|
||||
pipeline := []bson.M{matchStage, groupStage, sortStage, limitStage}
|
||||
opts := options.Aggregate().SetMaxTime(10 * time.Second)
|
||||
if err := coll(nil).Aggregate(&list, pipeline, opts); err != nil {
|
||||
return nil, errors.Wrapf(err, "table:%s VideoCoinIncomeAggregateTopN", table)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// PayCountMapByTime vid->金币 map
|
||||
func PayCountMapByTime(start time.Time, end time.Time) (map[ObjectID]int64, error) {
|
||||
pipeline := []bson.M{
|
||||
{
|
||||
"$match": bson.M{
|
||||
"createdAt": bson.M{
|
||||
"$gte": start,
|
||||
"$lt": end,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"$group": bson.M{
|
||||
"_id": "$videoID",
|
||||
"count": bson.M{
|
||||
"$sum": 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
var docList []struct {
|
||||
VID ObjectID `bson:"_id"`
|
||||
Count int64 `bson:"count"`
|
||||
}
|
||||
if err := coll(nil).Aggregate(&docList, pipeline); err != nil {
|
||||
return nil, fmt.Errorf("table:%s PayCoinMapByTime err: %s", table, err.Error())
|
||||
}
|
||||
ret := make(map[ObjectID]int64)
|
||||
for _, doc := range docList {
|
||||
ret[doc.VID] = doc.Count
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// TaxAmountMapByTime vid->TaxAmount map
|
||||
func TaxAmountMapByTime(start time.Time, end time.Time) (map[ObjectID]float64, error) {
|
||||
pipeline := []bson.M{
|
||||
{
|
||||
"$match": bson.M{
|
||||
"createdAt": bson.M{
|
||||
"$gte": start,
|
||||
"$lt": end,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"$group": bson.M{
|
||||
"_id": "$videoID",
|
||||
"taxAmount": bson.M{
|
||||
"$sum": "$taxAmount",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
var docList []struct {
|
||||
VID ObjectID `bson:"_id"`
|
||||
TaxAmount float64 `bson:"taxAmount"`
|
||||
}
|
||||
if err := coll(nil).Aggregate(&docList, pipeline); err != nil {
|
||||
return nil, fmt.Errorf("table:%s PayCoinMapByTime err: %s", table, err.Error())
|
||||
}
|
||||
ret := make(map[ObjectID]float64)
|
||||
for _, doc := range docList {
|
||||
ret[doc.VID] += doc.TaxAmount
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func PublisherIncomeMapByTime(start time.Time, end time.Time) (map[uint64]int64, error) {
|
||||
pipeline := []bson.M{
|
||||
{
|
||||
"$match": bson.M{
|
||||
"createdAt": bson.M{
|
||||
"$gte": start,
|
||||
"$lt": end,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"$group": bson.M{
|
||||
"_id": "$publisherID",
|
||||
"income": bson.M{
|
||||
"$sum": "$payMoney",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
var docList []struct {
|
||||
PublisherID uint64 `bson:"_id"`
|
||||
Income int64 `bson:"income"`
|
||||
}
|
||||
if err := coll(nil).Aggregate(&docList, pipeline); err != nil {
|
||||
return nil, fmt.Errorf("table:%s PublisherIncomeMapByTime err: %s", table, err.Error())
|
||||
}
|
||||
ret := make(map[uint64]int64)
|
||||
for _, doc := range docList {
|
||||
ret[doc.PublisherID] = doc.Income
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// TaxAmountByTime
|
||||
func TaxAmountByTime(start, end time.Time, mats ...Matcher) (float64, error) {
|
||||
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
|
||||
filter := pageopt.MergeM(mats)
|
||||
var list []struct {
|
||||
TaxAmount float64 `bson:"taxAmount"` //税额
|
||||
}
|
||||
opt := (&options.FindOptions{}).SetProjection(M{
|
||||
"taxAmount": 1,
|
||||
})
|
||||
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var taxAmount float64
|
||||
for _, v := range list {
|
||||
taxAmount += v.TaxAmount
|
||||
}
|
||||
return taxAmount, nil
|
||||
}
|
||||
|
||||
func FindByUID(uid uint64, newsType string, pageNumber int64, pageSize int64) (data []*Pay4VidLog, hasNext bool, err error) {
|
||||
data = make([]*Pay4VidLog, 0)
|
||||
opt := options.Find().
|
||||
SetLimit(pageSize + 1).
|
||||
SetSkip((pageNumber - 1) * pageSize).
|
||||
SetSort(bson.D{{"createdAt", -1}})
|
||||
|
||||
filter := bson.M{
|
||||
"uid": uid,
|
||||
"newsType": newsType,
|
||||
}
|
||||
err = coll(nil).Find(&data, filter, opt)
|
||||
if err != nil {
|
||||
log.Error("FindByUID error", log.Any("uid", uid), log.Any("err", err.Error()))
|
||||
return nil, false, err
|
||||
}
|
||||
if len(data) > int(pageSize) {
|
||||
hasNext = true
|
||||
data = data[:pageSize]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func PublisherVideoDeductionRange(uid uint64, start, end time.Time) ([]PublisherDeductionStat, error) {
|
||||
pipeline := []bson.M{
|
||||
{
|
||||
"$match": bson.M{
|
||||
// createdAt ∈ [startTime, endTime)
|
||||
"createdAt": bson.M{
|
||||
"$gte": start,
|
||||
"$lt": end,
|
||||
},
|
||||
"publisherID": uid,
|
||||
},
|
||||
},
|
||||
{
|
||||
"$group": bson.M{
|
||||
"_id": "$isVideoDeduction",
|
||||
"totalAmount": bson.M{"$sum": "$coins"},
|
||||
"videoCount": bson.M{"$sum": 1},
|
||||
},
|
||||
},
|
||||
}
|
||||
docList := []PublisherDeductionStat{}
|
||||
return docList, coll(nil).Aggregate(&docList, pipeline)
|
||||
}
|
||||
|
||||
func GetPayVidLogsByTime(start time.Time, end time.Time) ([]Pay4VidLogShort, error) {
|
||||
filter := bson.M{
|
||||
"createdAt": bson.M{
|
||||
"$gte": start,
|
||||
"$lt": end,
|
||||
},
|
||||
}
|
||||
logs := make([]Pay4VidLogShort, 0)
|
||||
if err := coll(nil).Find(&logs, filter); err != nil {
|
||||
return logs, fmt.Errorf("table:%s GetPayMoneyByTime err: %s", table, err.Error())
|
||||
}
|
||||
return logs, nil
|
||||
}
|
||||
Reference in New Issue
Block a user