@@ -0,0 +1,6 @@
|
||||
package payvidlgmod
|
||||
|
||||
// Pay4VidLogQueryReq Pay4VidLogQueryReq
|
||||
type Pay4VidLogQueryReq struct {
|
||||
PublisherID *uint64 `json:"publisherID,omitempty" bson:"publisherID"` //上传者ID
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package payvidlgmod
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/common/pageopt"
|
||||
"91porn-server/common/ysinterface/disc"
|
||||
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type DistrictStatKey struct {
|
||||
DiscSeqe `bson:",inline"` //商区码
|
||||
SysType string `bson:"sysType"` //系统类型 iOS Android
|
||||
}
|
||||
|
||||
func (d DistrictStatKey) GetDiscCode() string {
|
||||
return d.DistrictCode
|
||||
}
|
||||
|
||||
func (d DistrictStatKey) GetPromSeqe() string {
|
||||
return d.PromSeqe
|
||||
}
|
||||
|
||||
func (d DistrictStatKey) GetSysType() string {
|
||||
return d.SysType
|
||||
}
|
||||
|
||||
func (d DistrictStatKey) String() string {
|
||||
if d.DiscSeqe.String() == "" {
|
||||
return ""
|
||||
}
|
||||
return strings.ToUpper(strings.Join([]string{d.DiscSeqe.String(), d.SysType}, "-"))
|
||||
}
|
||||
|
||||
type DistrictStater = disc.DistrictStater
|
||||
|
||||
// DiscSeqeTransCount
|
||||
func DiscSeqeBuyVidCount(start, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
|
||||
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
|
||||
filter := pageopt.MergeM(mats)
|
||||
list := []DistrictStatKey{}
|
||||
opt := (&options.FindOptions{}).SetProjection(M{
|
||||
"districtCode": 1,
|
||||
"promSeqe": 1,
|
||||
"sysType": 1,
|
||||
})
|
||||
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DiscSeqeTransCount", table, "Find", err))
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater]int64)
|
||||
for _, v := range list {
|
||||
if v.String() != "" {
|
||||
m[v] += 1
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// DiscSeqeBuyVidCoins
|
||||
func DiscSeqeBuyVidCoins(start, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
|
||||
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
|
||||
filter := pageopt.MergeM(mats)
|
||||
list := []struct {
|
||||
DistrictStatKey `bson:",inline"` //商区码
|
||||
Coins int64 `bson:"coins"`
|
||||
}{}
|
||||
opt := (&options.FindOptions{}).SetProjection(M{
|
||||
"districtCode": 1,
|
||||
"promSeqe": 1,
|
||||
"sysType": 1,
|
||||
"coins": 1,
|
||||
})
|
||||
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater]int64, len(list))
|
||||
for _, v := range list {
|
||||
if v.String() != "" {
|
||||
m[v.DistrictStatKey] += v.Coins
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// DiscSeqeTaxAmount
|
||||
func DiscSeqeTaxAmount(start, end time.Time, mats ...Matcher) (map[DistrictStater]float64, error) {
|
||||
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
|
||||
filter := pageopt.MergeM(mats)
|
||||
list := []struct {
|
||||
DistrictStatKey `bson:",inline"` //商区码
|
||||
TaxAmount float64 `bson:"taxAmount"` //税额
|
||||
}{}
|
||||
opt := (&options.FindOptions{}).SetProjection(M{
|
||||
"districtCode": 1,
|
||||
"promSeqe": 1,
|
||||
"sysType": 1,
|
||||
"taxAmount": 1,
|
||||
})
|
||||
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater]float64, len(list))
|
||||
for _, v := range list {
|
||||
if v.String() != "" {
|
||||
m[v.DistrictStatKey] += v.TaxAmount
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package payvidlgmod
|
||||
|
||||
import (
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/common/pageopt"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type Matcher = pageopt.Matcher
|
||||
|
||||
// DistrictCodeMatch
|
||||
type DistrictCodeMatch struct {
|
||||
DistrictCode *string
|
||||
}
|
||||
|
||||
func (s *DistrictCodeMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("districtCode", s.DistrictCode)
|
||||
}
|
||||
|
||||
// IsDirectMatch
|
||||
type IsDirectMatch struct {
|
||||
IsDirect *bool
|
||||
}
|
||||
|
||||
func (b *IsDirectMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("isDirect", b.IsDirect)
|
||||
}
|
||||
|
||||
// PromSeqeMatch
|
||||
type PromSeqeMatch struct {
|
||||
Seqe *string
|
||||
}
|
||||
|
||||
func (d *PromSeqeMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("promSeqe", d.Seqe)
|
||||
}
|
||||
|
||||
// SysTypeMatch
|
||||
type SysTypeMatch struct {
|
||||
SysType *string
|
||||
}
|
||||
|
||||
func (d *SysTypeMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("sysType", d.SysType)
|
||||
}
|
||||
|
||||
// CreatedAtGTEAndLTMatch
|
||||
type CreatedAtGTEAndLTMatch = pageopt.CreatedAtGTEAndLTMatch
|
||||
|
||||
type Sort = bson.D
|
||||
|
||||
var Sort_CreatedAt_n1 = Sort{{Key: "createdAt", Value: -1}}
|
||||
|
||||
func List(sort Sort, skip, limit *int64, matchers ...Matcher) ([]Pay4VidLog, error) {
|
||||
filter := pageopt.MergeM(matchers)
|
||||
opt := (&options.FindOptions{})
|
||||
if len(sort) != 0 {
|
||||
opt.SetSort(sort)
|
||||
}
|
||||
if skip != nil {
|
||||
opt.SetSkip(*skip)
|
||||
}
|
||||
if limit != nil {
|
||||
opt.SetLimit(*limit)
|
||||
}
|
||||
list := []Pay4VidLog{}
|
||||
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
||||
log.Error("payvidlgmod List error", log.E(err))
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func Count(matchers ...Matcher) (int64, error) {
|
||||
filter := pageopt.MergeM(matchers)
|
||||
count, err := coll(nil).Count(filter)
|
||||
if err != nil {
|
||||
log.Error("payvidlgmod Count error", log.E(err))
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package payvidlgmod
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"91porn-server/common/db"
|
||||
"91porn-server/models/commod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type (
|
||||
ObjectID = primitive.ObjectID
|
||||
|
||||
M = bson.M
|
||||
|
||||
DiscSeqe = commod.DiscSeqe
|
||||
|
||||
DiscDoc = commod.DiscDoc
|
||||
)
|
||||
|
||||
// Pay4VidLog 购买影片记录
|
||||
type Pay4VidLog struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` // ID
|
||||
UID uint64 `json:"uid" bson:"uid"` // 用户ID
|
||||
Title string `json:"title" bson:"title,required"` // 视频标题
|
||||
NewsType string `json:"newsType" bson:"newsType"` // 类型
|
||||
VideoID primitive.ObjectID `json:"videoID" bson:"videoID"` // 视频id
|
||||
PlayTime uint `json:"playTime" bson:"playTime"` // 影片长度
|
||||
Coins int64 `json:"coins" bson:"coins"` // 定价
|
||||
Tax int64 `json:"tax" bson:"tax"` // 税率
|
||||
TaxAmount float64 `json:"taxAmount" bson:"taxAmount"` // 系统收取的税额 税率*定价
|
||||
PayMoney int64 `json:"payMoney" bson:"payMoney"` // 金币
|
||||
PublisherIncome float64 `json:"publisherIncome" bson:"publisherIncome"` // 上传者实际收益 定价-系统收取的税额
|
||||
PublisherID uint64 `json:"publisherID" bson:"publisherID"` // 上传者ID
|
||||
Uniq string `json:"uniq" bson:"uniq"` // UID.VideoID
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
|
||||
SysType string `json:"sysType" bson:"sysType"` // 系统类型
|
||||
IsVideoDeduction bool `json:"isVideoDeduction" bson:"isVideoDeduction"` // 是否扣量
|
||||
DiscDoc `bson:",inline"`
|
||||
}
|
||||
|
||||
func Init() {
|
||||
mdb = db.Init(table)
|
||||
initIndex()
|
||||
}
|
||||
|
||||
func Unique(uid uint64, videoID primitive.ObjectID) string {
|
||||
list := []string{
|
||||
strconv.FormatInt(int64(uid), 10),
|
||||
videoID.Hex(),
|
||||
}
|
||||
s := strings.Join(list, ".")
|
||||
return s
|
||||
}
|
||||
|
||||
type VideoCoinIncome struct {
|
||||
VID ObjectID `bson:"_id" json:"videoID"` //video id
|
||||
Total int64 `bson:"total" json:"total"` //视频总金币
|
||||
Count int64 `bson:"count" json:"count"` //视频购买总次数
|
||||
}
|
||||
|
||||
type PublisherDeductionStat struct {
|
||||
IsVideoDeduction bool `bson:"_id"` // 是否扣量
|
||||
TotalAmount int64 `bson:"totalAmount"` // 视频总售卖(金币)
|
||||
VideoCount int64 `bson:"videoCount"` // 总计视频数
|
||||
}
|
||||
|
||||
// Pay4VidLogShort 购买影片短结构
|
||||
type Pay4VidLogShort struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
||||
VideoID primitive.ObjectID `json:"videoID" bson:"videoID"`
|
||||
PayMoney int64 `json:"payMoney" bson:"payMoney"` //金币
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
|
||||
}
|
||||
Reference in New Issue
Block a user