776 lines
24 KiB
Go
776 lines
24 KiB
Go
/*
|
|
* @Description: 账户充值流水
|
|
* @Author: your name
|
|
* @Date: 2019-08-29 20:45:27
|
|
* @LastEditTime: 2019-08-30 13:44:36
|
|
* @LastEditors: Please set LastEditors
|
|
*/
|
|
package rchgordmod
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"91porn-server/common/db"
|
|
"91porn-server/common/log"
|
|
"91porn-server/common/pageopt"
|
|
"91porn-server/common/timeutil"
|
|
"91porn-server/common/timeutil/timerange"
|
|
"91porn-server/models"
|
|
"91porn-server/models/v/usermod"
|
|
|
|
"github.com/shopspring/decimal"
|
|
"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"
|
|
)
|
|
|
|
const table = models.RechargeOrder
|
|
|
|
func coll(t *db.MongoTool) *db.MongoTool {
|
|
if t == nil {
|
|
return mdb.Coll(table)
|
|
}
|
|
return t.Coll(table)
|
|
}
|
|
|
|
// InitARDIndex 设置账户充值流水表索引
|
|
func initIndex() {
|
|
many := []mongo.IndexModel{ //batch set indexes //value is the type 1 or -1
|
|
{
|
|
Keys: bson.D{{Key: "oid", Value: 1}},
|
|
// Options: options.Index().SetUnique(true).SetPartialFilterExpression(bson.M{"oid": bson.M{"$gt": ""}}),
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "channel", Value: 1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "createdAt", Value: 1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "updatedAt", Value: 1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "progressAt", Value: 1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "paymentAt", Value: 1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "failureAt", Value: 1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "successAt", Value: 1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "districtCode", Value: 1}, {Key: "createdAt", Value: -1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "isDirect", Value: 1}, {Key: "createdAt", Value: -1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "uid", Value: 1}, {Key: "createdAt", Value: -1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "traderId", Value: 1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "rechargeType", Value: 1}, {Key: "createdAt", Value: -1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "status", Value: 1}, {Key: "createdAt", Value: -1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "devType", Value: 1}, {Key: "createdAt", Value: -1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "uid", Value: 1}, {Key: "productType", Value: 1}, {Key: "status", Value: 1}},
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "deductType", Value: 1}, {Key: "createdAt", Value: -1}},
|
|
Options: options.Index().SetSparse(true),
|
|
},
|
|
{
|
|
Keys: bson.D{
|
|
{Key: "experimentId", Value: 1},
|
|
{Key: "experimentVariant", Value: 1},
|
|
{Key: "productID", Value: 1},
|
|
{Key: "status", Value: 1},
|
|
},
|
|
Options: options.Index().
|
|
SetName("vip_experiment_order_statistics").
|
|
SetPartialFilterExpression(bson.M{"experimentId": bson.M{"$gt": ""}}),
|
|
},
|
|
{
|
|
Keys: bson.D{{Key: "sourcePage", Value: 1}, {Key: "createdAt", Value: -1}},
|
|
Options: options.Index().
|
|
SetName("order_source_created_at").
|
|
SetPartialFilterExpression(bson.M{"sourcePage": bson.M{"$gt": ""}}),
|
|
},
|
|
}
|
|
if _, err := coll(nil).CreateIndex(many); err != nil {
|
|
panic(fmt.Sprintf("RechageOrderIndex err+%v", err))
|
|
}
|
|
}
|
|
|
|
// InsertRechargeOrder 插入一条充值订单
|
|
func InsertRechargeOrder(a *RechargeOrder) (err error) {
|
|
a.CreatedAt = time.Now()
|
|
a.UpdatedAt = a.CreatedAt
|
|
res, err := coll(nil).InsertOne(a)
|
|
if err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertRechargeOrder", table, "InsertOne", err))
|
|
return
|
|
}
|
|
a.ID = res.InsertedID.(primitive.ObjectID)
|
|
return
|
|
}
|
|
|
|
// FindRechargesOrders 查询充值订单
|
|
func FindRechargesOrders(cond bson.M, opts *options.FindOptions) (total int64, data []*RechargeOrder, err error) {
|
|
data = make([]*RechargeOrder, 0)
|
|
if err = coll(nil).Find(&data, cond, opts); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindRechargesOrders", table, "Find", err),
|
|
log.Any("cond", cond),
|
|
)
|
|
return
|
|
}
|
|
total, err = coll(nil).Count(cond)
|
|
if err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindRechargesOrders", table, "Count", err),
|
|
log.Any("cond", cond),
|
|
)
|
|
return
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func FindOne(t *db.MongoTool, cond bson.M, opts ...*options.FindOneOptions) (data *RechargeOrder, err error) {
|
|
if err = coll(nil).FindOne(&data, cond, opts...); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindOne", table, "FindOne", err),
|
|
log.Any("cond", cond),
|
|
)
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// FindRechargesOrders 查询充值订单
|
|
func FindMyOrders(uid, pgSz, pgCt uint64) (total int64, data []*RechargeOrder, hasNext bool, err error) {
|
|
data = make([]*RechargeOrder, 0)
|
|
opts := options.FindOptions{}
|
|
skip := int64((pgCt - 1) * pgSz)
|
|
limit := int64(pgSz + 1)
|
|
opts.Skip = &skip
|
|
opts.Limit = &limit
|
|
opts.SetSort(bson.D{{Key: "createdAt", Value: -1}})
|
|
startTime := timeutil.BeforeMinute(20)
|
|
cond := bson.M{
|
|
"$or": []bson.M{
|
|
{"uid": uid, "status": bson.M{"$gt": Processing}},
|
|
{"uid": uid, "status": bson.M{"$lte": Processing}, "createdAt": bson.M{"$gte": startTime}},
|
|
},
|
|
}
|
|
if err = coll(nil).Find(&data, cond, &opts); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindMyOrders", table, "Find", err),
|
|
log.Any("uid", uid),
|
|
log.Any("pgSz", pgSz),
|
|
log.Any("pgCt", pgCt),
|
|
)
|
|
return
|
|
}
|
|
total, err = coll(nil).Count(cond)
|
|
if err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindMyOrders", table, "Count", err),
|
|
log.Any("uid", uid),
|
|
log.Any("pgSz", pgSz),
|
|
log.Any("pgCt", pgCt),
|
|
)
|
|
}
|
|
if len(data) > int(pgSz) {
|
|
hasNext = true
|
|
data = data[:pgSz]
|
|
}
|
|
return
|
|
}
|
|
|
|
// Update 修改订单
|
|
func UpdateRechargeOrder(id string, set RechargeUpdateReq) error {
|
|
set.UpdatedAt = time.Now()
|
|
objID, err := primitive.ObjectIDFromHex(id)
|
|
if err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpdateRechargeOrder", table, "ObjectIDFromHex", err),
|
|
log.Any("id", id),
|
|
log.Any("set", set),
|
|
)
|
|
return err
|
|
}
|
|
if _, err = coll(nil).UpdateOne(bson.M{"_id": objID}, bson.M{"$set": set}); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpdateRechargeOrder", table, "UpdateOne", err),
|
|
log.Any("id", id),
|
|
log.Any("set", set),
|
|
)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CallBackModifyWithProcessing 回调修改订单
|
|
func CallBackModifyWithProcessing(ctx context.Context, t *db.MongoTool, id primitive.ObjectID, set EditSelector) error {
|
|
set.UpdatedAt = time.Now()
|
|
if _, err := coll(t).UpdateOne(bson.M{"_id": id, "status": Processing}, bson.M{"$set": set}); err != nil {
|
|
log.WarnX(ctx, fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Update", table, "UpdateOne", err),
|
|
log.Any("id", id),
|
|
log.Any("set", set),
|
|
)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Update 修改订单
|
|
func Update(t *db.MongoTool, id primitive.ObjectID, set EditSelector) error {
|
|
set.UpdatedAt = time.Now()
|
|
if _, err := coll(t).UpdateOne(bson.M{"_id": id}, bson.M{"$set": set}); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Update", table, "UpdateOne", err),
|
|
log.Any("id", id),
|
|
log.Any("set", set),
|
|
)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 根据第三方订单号修改
|
|
func UpdateBaseOnOidAndStatus(t *db.MongoTool, oid string, status int, set ReplaceEditSelector) error {
|
|
set.UpdatedAt = time.Now()
|
|
if _, err := coll(t).UpdateOne(bson.M{"oid": oid, "status": status}, bson.M{"$set": set}); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpdateBaseOnOid", table, "UpdateOne", err),
|
|
log.Any("id", oid),
|
|
log.Any("set", set),
|
|
)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func UpdateBaseOnOid(t *db.MongoTool, oid string, set ReplaceEditSelector) error {
|
|
set.UpdatedAt = time.Now()
|
|
if _, err := coll(t).UpdateOne(bson.M{"oid": oid}, bson.M{"$set": set}); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpdateBaseOnOid", table, "UpdateOne", err),
|
|
log.Any("id", oid),
|
|
log.Any("set", set),
|
|
)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Upsert 新增或修改订单
|
|
func Upsert(t *db.MongoTool, oid string, upsert UpserSelector) (id primitive.ObjectID, err error) {
|
|
updatedAt := time.Now()
|
|
upsert.UpdatedAt = &updatedAt
|
|
upertRest, err := coll(t).UpsertOne(bson.M{"oid": oid}, bson.M{"$setOnInsert": bson.M{"createdAt": time.Now()}, "$set": upsert})
|
|
if err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Upsert", table, "UpsertOne", err),
|
|
log.Any("oid", oid),
|
|
log.Any("upsert", upsert),
|
|
)
|
|
}
|
|
if tid, ok := upertRest.UpsertedID.(primitive.ObjectID); ok {
|
|
id = tid
|
|
}
|
|
return
|
|
}
|
|
|
|
// FindRechargeByID 根据订单号查询订单
|
|
func FindRechargeOrderByID(id string) (r RechargeOrder, err error) {
|
|
objID, err := primitive.ObjectIDFromHex(id)
|
|
if err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindRechargeOrderByID", table, "ObjectIDFromHex", err),
|
|
log.Any("id", id),
|
|
)
|
|
return
|
|
}
|
|
if err = coll(nil).FindOne(&r, bson.M{"_id": objID}); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindRechargeOrderByID", table, "FindOne", err),
|
|
log.Any("objID", objID),
|
|
)
|
|
}
|
|
return
|
|
}
|
|
|
|
// FindRechargeByID 根据第三方订单号查询订单
|
|
func FindRechargeOrderByThirdOrderId(oid string) (r RechargeOrder, err error) {
|
|
if err = coll(nil).FindOne(&r, bson.M{"oid": oid}); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindRechargeOrderByID", table, "FindOne", err),
|
|
log.Any("objID", oid),
|
|
)
|
|
}
|
|
return
|
|
}
|
|
|
|
// FindRechargeByIDForApp 根据第三方订单号查询订单ForApp
|
|
func FindRechargeOrderByThirdOrderIdForApp(oid string) (r *RechargeOrderAppRes, err error) {
|
|
if err = coll(nil).FindOne(&r, bson.M{"oid": oid}); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindRechargeOrderByThirdOrderIdForApp", table, "FindOne", err),
|
|
log.Any("objID", oid),
|
|
)
|
|
}
|
|
return
|
|
}
|
|
|
|
// TotalMoney 统计总订单金额
|
|
func TotalMoney(matchers ...Matcher) (int64, error) {
|
|
var ret struct {
|
|
Money int64 `bson:"money"` //充值金额 订单金额 李秋山确认
|
|
}
|
|
filter := []bson.M{
|
|
{
|
|
"$match": pageopt.MergeM(matchers),
|
|
},
|
|
{
|
|
"$group": bson.M{
|
|
"_id": nil,
|
|
"money": bson.M{"$sum": "$money"},
|
|
},
|
|
},
|
|
}
|
|
if err := coll(nil).AggregateDecode(&ret, filter); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UsersTotalRecharge", table, "Aggregate", err),
|
|
log.Any("matchers", matchers),
|
|
)
|
|
return 0, err
|
|
}
|
|
return ret.Money, nil
|
|
}
|
|
|
|
// GetSuccessOrderUIDListByTime
|
|
func GetSuccessOrderUIDListByTime(start time.Time, end time.Time) ([]uint64, error) {
|
|
filter := (&SuccessAtGTEAndLTMatch{&start, &end}).New().Filter()
|
|
list := make([]struct {
|
|
UID uint64 `bson:"uid"`
|
|
}, 0)
|
|
if err := coll(nil).Find(&list, filter); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetSuccessOrderUIDListByTime", table, "Find", err),
|
|
log.Any("start", start),
|
|
log.Any("end", end),
|
|
)
|
|
return nil, err
|
|
}
|
|
uidList := make([]uint64, len(list))
|
|
for i, v := range list {
|
|
uidList[i] = v.UID
|
|
}
|
|
return uidList, nil
|
|
}
|
|
|
|
// 根据uid获取用户的成功订单
|
|
func GetSuccessOrderUidList(uid, pageSize, pageNum uint64) (total int64, data []RechargeOrder, hasNext bool, err error) {
|
|
filter := bson.M{"uid": uid}
|
|
skip := int64((pageNum - 1) * pageSize)
|
|
limit := int64(pageSize)
|
|
opts := options.FindOptions{
|
|
Skip: &skip,
|
|
Limit: &limit,
|
|
Sort: bson.D{{Key: "createdAt", Value: -1}},
|
|
}
|
|
if err = coll(nil).Find(&data, filter, &opts); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindMyOrders", table, "Find", err),
|
|
log.Any("uid", uid),
|
|
log.Any("pgSz", pageSize),
|
|
log.Any("pgCt", pageNum),
|
|
)
|
|
return
|
|
}
|
|
total, err = coll(nil).Count(filter)
|
|
if err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindMyOrders", table, "Count", err),
|
|
log.Any("uid", uid),
|
|
log.Any("pgSz", pageSize),
|
|
log.Any("pgCt", pageNum),
|
|
)
|
|
}
|
|
return
|
|
}
|
|
|
|
// GetNewAndRechargeUIDSByTime 新增并充值uid List
|
|
func GetNewAndRechargeUIDSByTime(createStart, createEnd, recStart, recEnd time.Time) ([]uint64, error) {
|
|
createUIDList, err := usermod.UIDListByCreateTime(createStart, createEnd)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
filter := (&SuccessAtGTEAndLTMatch{&recStart, &recEnd}).New().Filter()
|
|
recList := make([]struct {
|
|
UID uint64 `bson:"uid"`
|
|
}, 0)
|
|
if err = coll(nil).Find(&recList, filter); err != nil {
|
|
return nil, err
|
|
}
|
|
//充值用户 Map
|
|
recUserMap := make(map[uint64]byte, len(recList))
|
|
for _, rec := range recList {
|
|
recUserMap[rec.UID] = 1
|
|
}
|
|
uidList := make([]uint64, 0, len(recUserMap))
|
|
for _, uid := range createUIDList {
|
|
if _, ok := recUserMap[uid]; ok {
|
|
uidList = append(uidList, uid)
|
|
}
|
|
}
|
|
return uidList, nil
|
|
}
|
|
|
|
// GetChannelNewAndRechargeUIDSMapByTime 渠道新增并充值用户映射
|
|
func GetChannelNewAndRechargeUIDSMapByTime(start time.Time, end time.Time) (map[string][]uint64, error) {
|
|
creatUserStartTime := timerange.LocDayRange(start).Head
|
|
creatUserEndTime := timerange.LocDayRange(end).Tail
|
|
chMap, err := usermod.ChannelMapByCreateTime(creatUserStartTime, creatUserEndTime)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
filter := (&SuccessAtGTEAndLTMatch{&start, &end}).New().Filter()
|
|
list := make([]struct {
|
|
UID uint64 `bson:"uid"`
|
|
}, 0)
|
|
if err = coll(nil).Find(&list, filter); err != nil {
|
|
return nil, err
|
|
}
|
|
recUIDMap := make(map[uint64]byte, len(list))
|
|
for _, v := range list {
|
|
recUIDMap[v.UID] = 1
|
|
}
|
|
ret := make(map[string][]uint64)
|
|
for uid, channel := range chMap {
|
|
if _, ok := recUIDMap[uid]; ok {
|
|
ret[channel] = append(ret[channel], uid)
|
|
}
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
// GetChannelNewAndRechargeAmountMapByTime 渠道新增并充值金额映射
|
|
func GetChannelNewAndRechargeAmountMapByTime(start time.Time, end time.Time) (map[string]int64, error) {
|
|
creatUserStartTime := timerange.LocDayRange(start).Head
|
|
creatUserEndTime := timerange.LocDayRange(end).Tail
|
|
chMap, err := usermod.ChannelMapByCreateTime(creatUserStartTime, creatUserEndTime)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
filter := (&SuccessAtGTEAndLTMatch{GTE: &start, LT: &end}).New().Filter()
|
|
list := make([]struct {
|
|
UID uint64 `bson:"uid"`
|
|
Money int64 `bson:"money"`
|
|
}, 0)
|
|
if err = coll(nil).Find(&list, filter); err != nil {
|
|
return nil, err
|
|
}
|
|
moneyMap := make(map[uint64]int64, len(list))
|
|
for _, v := range list {
|
|
moneyMap[v.UID] += v.Money
|
|
}
|
|
ret := make(map[string]int64)
|
|
for uid, channel := range chMap {
|
|
money := moneyMap[uid]
|
|
ret[channel] += money
|
|
}
|
|
return ret, nil
|
|
}
|
|
|
|
// OnlineRechargeAmount OnlineRechargeAmount
|
|
func RechargeAmount(start time.Time, end time.Time, mats ...Matcher) (int64, error) {
|
|
mats = append(mats, (&SuccessAtGTEAndLTMatch{&start, &end}).New())
|
|
filter := pageopt.MergeM(mats)
|
|
list := make([]struct {
|
|
Money int64 `bson:"money"`
|
|
}, 0)
|
|
if err := coll(nil).Find(&list, filter); err != nil {
|
|
return 0, err
|
|
}
|
|
var totalMoney int64
|
|
for _, v := range list {
|
|
totalMoney += v.Money
|
|
}
|
|
return totalMoney, nil
|
|
}
|
|
|
|
// ChannelOrderCountMap channel->订单数 map
|
|
func ChannelOrderCountMap(start, end time.Time) (map[string]int64, error) {
|
|
filter := (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New().Filter()
|
|
var list []struct {
|
|
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` //流水id
|
|
Channel string `json:"channel" bson:"channel"` //渠道类型 鲨鱼 金鱼
|
|
}
|
|
if err := coll(nil).Find(&list, filter); err != nil {
|
|
return nil, err
|
|
}
|
|
m := make(map[string]int64, len(list))
|
|
for _, v := range list {
|
|
m[v.Channel] += 1
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
// ChannelCompleteOrderCountMap channel->完成订单数 map
|
|
func ChannelCompleteOrderCountMap(start, end time.Time) (map[string]int64, error) {
|
|
filter := (&SuccessAtGTEAndLTMatch{&start, &end}).New().Filter()
|
|
var list []struct {
|
|
ID primitive.ObjectID `bson:"_id,omitempty"` //流水id
|
|
Channel string `bson:"channel"` //渠道类型 鲨鱼 金鱼
|
|
}
|
|
if err := coll(nil).Find(&list, filter); err != nil {
|
|
return nil, err
|
|
}
|
|
m := make(map[string]int64, len(list))
|
|
for _, v := range list {
|
|
m[v.Channel] += 1
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
// ChannelOrderMoneyMap channel->订单金额 map
|
|
func ChannelOrderMoneyMap(start, end time.Time) (map[string]int64, error) {
|
|
filter := (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New().Filter()
|
|
var list []struct {
|
|
Channel string `bson:"channel"` //渠道类型 鲨鱼 金鱼
|
|
Money int64 `bson:"money"` //充值金额 订单金额 李秋山确认
|
|
}
|
|
if err := coll(nil).Find(&list, filter); err != nil {
|
|
return nil, err
|
|
}
|
|
m := make(map[string]int64, len(list))
|
|
for _, v := range list {
|
|
m[v.Channel] += v.Money
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
// ChannelCompleteOrderPayMoneyMap channel->完成订单的用户实际支付金额 map
|
|
func ChannelCompleteOrderPayMoneyMap(start, end time.Time) (map[string]int64, error) {
|
|
filter := (&SuccessAtGTEAndLTMatch{&start, &end}).New().Filter()
|
|
var list []struct {
|
|
Channel string `bson:"channel"` //渠道类型 鲨鱼 金鱼
|
|
PayMoney int64 `bson:"payMoney"` //实际到账金额 实际支付金额 李秋山确认
|
|
}
|
|
if err := coll(nil).Find(&list, filter); err != nil {
|
|
return nil, err
|
|
}
|
|
m := make(map[string]int64, len(list))
|
|
for _, v := range list {
|
|
m[v.Channel] += v.PayMoney
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
var ChannelPaymentOrderCountMap = ChannelCompleteOrderCountMap
|
|
|
|
var ChannelPaymentMoneyMap = ChannelCompleteOrderPayMoneyMap
|
|
|
|
// SuccessRateMap 每小时成功率
|
|
func SuccessRateMap(channel string, start, end time.Time, scaleMinute int64) (map[int64]float64, error) {
|
|
var list []struct {
|
|
CreatedAt time.Time `bson:"createdAt"` //创建时间
|
|
Status int `bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
|
|
}
|
|
matList := []pageopt.Matcher{
|
|
(&ChannelMatch{&channel}).New(),
|
|
(&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New(),
|
|
}
|
|
filter := pageopt.MergeM(matList)
|
|
opt := (&options.FindOptions{}).SetProjection(M{
|
|
"createdAt": 1,
|
|
"status": 1,
|
|
})
|
|
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
|
return nil, err
|
|
}
|
|
sucOrdCountMap := make(map[int64]int64)
|
|
orderCountMap := make(map[int64]int64)
|
|
successRateMap := make(map[int64]float64)
|
|
tempTime := start
|
|
for end.After(tempTime) {
|
|
tim := timerange.RecentMinute(tempTime, scaleMinute)
|
|
p := tim.Unix()
|
|
sucOrdCountMap[p] = 0
|
|
orderCountMap[p] = 0
|
|
successRateMap[p] = 0.0
|
|
tempTime = tempTime.Add(time.Duration(scaleMinute) * time.Minute)
|
|
}
|
|
for _, v := range list {
|
|
tim := timerange.RecentMinute(v.CreatedAt, scaleMinute)
|
|
p := tim.Unix()
|
|
if v.Status == SUCCESS {
|
|
sucOrdCountMap[p] += 1
|
|
}
|
|
orderCountMap[p] += 1
|
|
}
|
|
lastTime := end
|
|
if len(list) > 0 {
|
|
lastTime = list[len(list)-1].CreatedAt
|
|
}
|
|
tempTime = start
|
|
for lastTime.After(tempTime) {
|
|
tim := timerange.RecentMinute(tempTime, scaleMinute)
|
|
p := tim.Unix()
|
|
if orderCountMap[p] != 0 {
|
|
successRateMap[p] = float64(int(float64(sucOrdCountMap[p])/float64(orderCountMap[p])*1000)) / 10
|
|
}
|
|
tempTime = tempTime.Add(time.Duration(scaleMinute) * time.Minute)
|
|
}
|
|
return successRateMap, nil
|
|
}
|
|
|
|
func GetSuccessRechargeCountMapByHour(discCode string, start, end time.Time, mats ...Matcher) ([]int, map[int]int64, int64, error) {
|
|
mats = append(mats,
|
|
(&DistrictCodeMatch{&discCode}).New(),
|
|
(&SuccessAtGTEAndLTMatch{&start, &end}).New())
|
|
filter := pageopt.MergeM(mats)
|
|
opt := (&options.FindOptions{}).SetProjection(M{
|
|
"successAt": 1,
|
|
})
|
|
var list []struct {
|
|
SuccessAt time.Time `bson:"successAt"` //创建时间
|
|
}
|
|
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
|
log.Error("rchgordmod GetRechargeCountMapByHour error", log.E(err))
|
|
return nil, nil, 0, err
|
|
}
|
|
hs := []int{}
|
|
m := make(map[int]int64)
|
|
startH := start.Hour()
|
|
lastH := end.Hour() + (end.Day()-start.Day())*24
|
|
for i := startH; i <= lastH; i++ {
|
|
hs = append(hs, i)
|
|
m[i] = 0
|
|
}
|
|
var total int64
|
|
for _, v := range list {
|
|
hour := v.SuccessAt.Hour() + (v.SuccessAt.Day()-start.Day())*24
|
|
m[hour] += 1
|
|
total++
|
|
}
|
|
return hs, m, total, nil
|
|
}
|
|
|
|
func UpRechOrder(mt *db.MongoTool, tradeNo string, oid string, amount int64, progressAt time.Time) error {
|
|
id, _ := primitive.ObjectIDFromHex(tradeNo)
|
|
c, err := coll(nil).Count(bson.M{"_id": id})
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
if c <= 0 {
|
|
return errors.New("tradeNo不存在")
|
|
}
|
|
tStr := time.Now().Local()
|
|
filter := bson.M{"_id": id, "status": Processing}
|
|
mur, err := coll(mt).UpdateOne(filter,
|
|
bson.M{"$set": bson.M{
|
|
"status": SUCCESS,
|
|
"statusDesc": "success",
|
|
"oid": oid,
|
|
"payMoney": amount,
|
|
"updatedAt": tStr,
|
|
"progressAt": progressAt,
|
|
"successAt": progressAt,
|
|
"paymentAt": progressAt,
|
|
/*"finishedAt": tStr*/}})
|
|
if err != nil {
|
|
log.Warn("transplat:UpRechOrder rchgOderColl.UpdateOne failed", log.E(err), log.Any("filter", filter))
|
|
return err
|
|
}
|
|
if mur.ModifiedCount != 1 {
|
|
return errors.New("UpdateErr")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// 获取用户昨日棋牌充值金额
|
|
func GetUserChessSuccessOrderAmout(uid uint64, now time.Time) (int64, error) {
|
|
/** TODO: 统计用户昨日棋牌充值总金额
|
|
查询条件
|
|
1.指定用户
|
|
2.棋牌充值
|
|
3.成功订单
|
|
4.订单时间(大于等于昨日凌晨时间;小于今日凌晨时间)
|
|
*/
|
|
match := bson.M{"uid": uid,
|
|
"productType": 1,
|
|
"status": 3,
|
|
"paymentAt": bson.M{"$gte": timeutil.BeginningOfDay(now.AddDate(0, 0, -1)), "$lt": timeutil.BeginningOfDay(now)},
|
|
}
|
|
pipelines := []bson.M{
|
|
{"$match": match},
|
|
{"$group": bson.M{"_id": nil, "totalAmount": bson.M{"$sum": "$payMoney"}}},
|
|
{"$project": bson.M{"totalAmount": 1}},
|
|
}
|
|
var res struct {
|
|
TotalAmount int64 `bson:"totalAmount"`
|
|
}
|
|
if err := coll(nil).AggregateDecode(&res, pipelines); err != nil {
|
|
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetUserChessSuccessOrderAmout", table, "AggregateDecode", err), log.Any("uid", uid))
|
|
return 0, err
|
|
}
|
|
return decimal.NewFromInt(res.TotalAmount).Div(decimal.NewFromInt(100)).IntPart(), nil
|
|
}
|
|
|
|
// 首冲判定
|
|
func IsFirstRecharge(uid uint64) (bool, error) {
|
|
filter := bson.M{"uid": uid, "productType": 1, "status": SUCCESS}
|
|
count, err := coll(nil).Count(filter)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return count == 0, nil
|
|
}
|
|
|
|
func StatCenterSyncRecharge(start time.Time, size int64) ([]RechargeOrder, error) {
|
|
end := time.Now().Add(-time.Second * 240) //等用户注册信息先同步
|
|
opt := (&options.FindOptions{})
|
|
opt.SetLimit(size)
|
|
opt.SetSort(bson.M{"successAt": 1})
|
|
filter := bson.M{"status": 3, "successAt": bson.M{"$gt": start, "$lte": end}}
|
|
data := make([]RechargeOrder, 0)
|
|
return data, coll(nil).Find(&data, filter, opt)
|
|
}
|
|
|
|
func StatCenterSyncOrder(start time.Time, size int64) ([]RechargeOrder, error) {
|
|
end := time.Now().Add(-time.Second * 240) //等用户注册信息先同步
|
|
opt := (&options.FindOptions{})
|
|
opt.SetLimit(size)
|
|
opt.SetSort(bson.M{"createdAt": 1})
|
|
filter := bson.M{"createdAt": bson.M{"$gt": start, "$lte": end}}
|
|
data := make([]RechargeOrder, 0)
|
|
return data, coll(nil).Find(&data, filter, opt)
|
|
}
|
|
|
|
func GetOrderByTime(start, end time.Time) ([]RechargeStat, error) {
|
|
filter := bson.M{"status": 3, "productType": bson.M{"$ne": 1}, "successAt": bson.M{"$gt": start, "$lte": end}}
|
|
data := make([]RechargeStat, 0)
|
|
return data, coll(nil).Find(&data, filter)
|
|
}
|
|
|
|
func NewStatCenterSyncRecharge(id string, size int64) ([]RechargeOrder, error) {
|
|
_id, _ := primitive.ObjectIDFromHex(id)
|
|
opt := (&options.FindOptions{}).SetLimit(size).SetSort(bson.M{"_id": 1})
|
|
filter := bson.M{"_id": bson.M{"$gt": _id}}
|
|
data := make([]RechargeOrder, 0)
|
|
return data, coll(nil).Find(&data, filter, opt)
|
|
}
|
|
|
|
// RefundCallBackModify 退款回调修改订单
|
|
func RefundCallBackModify(ctx context.Context, t *db.MongoTool, id primitive.ObjectID, set EditSelector) error {
|
|
set.UpdatedAt = time.Now()
|
|
if _, err := coll(t).UpdateOne(bson.M{"_id": id}, bson.M{"$set": set}); err != nil {
|
|
log.WarnX(ctx, fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Update", table, "UpdateOne", err),
|
|
log.Any("id", id),
|
|
log.Any("set", set),
|
|
)
|
|
return err
|
|
}
|
|
return nil
|
|
}
|