@@ -0,0 +1,103 @@
|
||||
package rchgordmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type UpserSelector struct {
|
||||
UID *uint64 `json:"uid,omitempty" bson:"uid,omitempty"` //用户id
|
||||
OID *string `json:"oid,omitempty" bson:"oid,omitempty"` //支付平台订单号
|
||||
TraderId *string `json:"traderId,omitempty" bson:"traderId,omitempty"` //商户ID
|
||||
UserIP *string `json:"userIp,omitempty" bson:"userIp,omitempty"` //用户IP
|
||||
DevID *string `json:"devID,omitempty" bson:"devID,omitempty"` //设备id
|
||||
Name *string `json:"name,omitempty" bson:"name,omitempty"` //用户名称
|
||||
Tel *string `json:"tel,omitempty" bson:"tel,omitempty"` //用户手机号
|
||||
DevType *string `json:"devType,omitempty" bson:"devType,omitempty"` //设备系统类型 ios pc android
|
||||
Amount int64 `json:"amount" bson:"amount"` //金币数量
|
||||
Money *int64 `json:"money,omitempty" bson:"money,omitempty"` //充值金额 单位角
|
||||
PayMoney *int64 `json:"payMoney,omitempty" bson:"payMoney,omitempty"` //实际到账金额
|
||||
RechargeType *string `json:"rechargeType,omitempty" bson:"rechargeType,omitempty"` //充值类型
|
||||
Channel *string `json:"channel,omitempty" bson:"channel,omitempty"` //渠道类型 鲨鱼 金鱼 代充
|
||||
Status *int `json:"status" bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
|
||||
StatusDesc *string `json:"statusDesc,omitempty" bson:"statusDesc,omitempty"` //状态描述
|
||||
NotifyTime *int64 `json:"notifyTime,omitempty" bson:"notifyTime,omitempty"` //第三方回调的时间
|
||||
NotifyStatus *int `json:"notifyStatus,omitempty" bson:"notifyStatus,omitempty"` //通知第三方上分情况状态
|
||||
LockStatus *int `json:"lockStatus,omitempty" bson:"lockStatus,omitempty"` //订单操作锁定状态 用户订单更新操作
|
||||
FailureAt *time.Time `json:"failureAt,omitempty" bson:"failureAt,omitempty"` //回调失败时间
|
||||
SuccessAt *time.Time `json:"successAt,omitempty" bson:"successAt,omitempty"` //回调成功时间
|
||||
PaymentAt *time.Time `json:"paymentAt,omitempty" bson:"paymentAt,omitempty"` //支付时间
|
||||
UpdatedAt *time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` //刷新时间
|
||||
ProductType *int `json:"productType,omitempty" bson:"productType,omitempty"` //0站群 1棋牌
|
||||
ChanShareMod *int `json:"chanShareMod,omitempty" bson:"chanShareMod,omitempty"` //渠道分成类型 0 不分成 (默认) 1 金币充值分成 2正常vip消费分成
|
||||
DiscDoc DiscDoc `bson:",inline"`
|
||||
}
|
||||
|
||||
type ReplaceEditSelector struct {
|
||||
OID *string `json:"oid,omitempty" bson:"oid,omitempty"` //支付平台订单号
|
||||
PayMoney *int64 `json:"payMoney,omitempty" bson:"payMoney,omitempty"` //实际到账金额
|
||||
Status *int `json:"status" bson:"status,omitempty"` //1进行中 2付款失败 3付款成功 4已经退款
|
||||
StatusDesc *string `json:"statusDesc,omitempty" bson:"statusDesc,omitempty"` //状态描述
|
||||
LockStatus *int `json:"lockStatus,omitempty" bson:"lockStatus,omitempty"` //订单操作锁定状态 用户订单更新操作
|
||||
NotifyStatus *int `json:"notifyStatus,omitempty" bson:"notifyStatus,omitempty"` //通知第三方上分情况状态
|
||||
Remark *string `json:"remark,omitempty" bson:"remark,omitempty"` //备注
|
||||
VipID primitive.ObjectID `json:"vipID,omitempty" bson:"vipID,omitempty"` //是否是vip冲 hi
|
||||
ChanShareMod *int `json:"chanShareMod,omitempty" bson:"chanShareMod,omitempty"` //渠道分成类型 0 不分成 (默认) 1 金币充值分成 2正常vip消费分成
|
||||
ProgressAt *time.Time `json:"progressAt,omitempty" bson:"progressAt,omitempty"` //第三方下单成功时间
|
||||
FailureAt *time.Time `json:"failureAt,omitempty" bson:"failureAt,omitempty"` //回调失败时间
|
||||
SuccessAt *time.Time `json:"successAt,omitempty" bson:"successAt,omitempty"` //回调成功时间
|
||||
PaymentAt *time.Time `json:"paymentAt,omitempty" bson:"paymentAt,omitempty"` //支付时间
|
||||
UpdatedAt time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` //刷新时间
|
||||
ProductChildType *ChildType `json:"productChildType" bson:"productChildType"` //产品子类型
|
||||
ServiceID primitive.ObjectID `json:"serviceId" bson:"serviceId"` //裸聊服务ID
|
||||
ProductID primitive.ObjectID `json:"productID" bson:"productID"` //产品ID
|
||||
}
|
||||
|
||||
type EditSelector struct {
|
||||
OID *string `json:"oid,omitempty" bson:"oid,omitempty"` //支付平台订单号
|
||||
PayMoney *int64 `json:"payMoney,omitempty" bson:"payMoney,omitempty"` //实际到账金额
|
||||
Status int `json:"status" bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
|
||||
StatusDesc *string `json:"statusDesc,omitempty" bson:"statusDesc,omitempty"` //状态描述
|
||||
NotifyStatus *int `json:"notifyStatus,omitempty" bson:"notifyStatus,omitempty"` //通知第三方上分情况状态
|
||||
ProgressAt *time.Time `json:"progressAt,omitempty" bson:"progressAt,omitempty"` //第三方下单成功时间
|
||||
FailureAt *time.Time `json:"failureAt,omitempty" bson:"failureAt,omitempty"` //回调失败时间
|
||||
SuccessAt *time.Time `json:"successAt,omitempty" bson:"successAt,omitempty"` //回调成功时间
|
||||
PaymentAt *time.Time `json:"paymentAt,omitempty" bson:"paymentAt,omitempty"` //支付时间
|
||||
RefundAt *time.Time `json:"refundAt,omitempty" bson:"refundAt,omitempty"` //退款时间
|
||||
UpdatedAt time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` //刷新时间
|
||||
Mode *string `json:"mode,omitempty" bson:"mode,omitempty"` //支付模式
|
||||
Channel *string `json:"channel,omitempty" bson:"channel,omitempty"` //渠道类型 鲨鱼 金鱼 代充
|
||||
Rate *string `json:"rate,omitempty" bson:"rate,omitempty"` //渠道费率
|
||||
ProductType *int `json:"productType,omitempty" bson:"productType,omitempty"` //支付产品类型 0 站群 1 棋牌
|
||||
ChanShareMod *int `json:"chanShareMod,omitempty" bson:"chanShareMod,omitempty"` //渠道分成类型
|
||||
Remark *string `json:"remark,omitempty" bson:"remark,omitempty"` //备注
|
||||
|
||||
}
|
||||
|
||||
type RechargToPayP struct {
|
||||
RechargeType string `json:"rechargeType" binding:"required"` //充值类型
|
||||
ProductID primitive.ObjectID `json:"productID"` //充值金币类型id
|
||||
VipID primitive.ObjectID `json:"vipID"` //是否是vip冲 hi
|
||||
ProductType int `json:"productType"` //充值产品 0 站群 1 棋牌
|
||||
Money int64 `json:"money"` //金额
|
||||
ProductChildType ChildType `json:"productChildType"` //产品子类型
|
||||
ServiceID primitive.ObjectID `json:"serviceId"` //裸聊服务ID
|
||||
}
|
||||
|
||||
// RechargeOrder 账户充值流水 App返回给前端
|
||||
type RechargeOrderAppRes struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` //流水id
|
||||
OID string `json:"oid" bson:"oid"` //支付平台订单号
|
||||
UID uint64 `json:"uid" bson:"uid"` //用户id
|
||||
Name string `json:"name" bson:"name"` //用户名称
|
||||
Tel string `json:"tel" bson:"tel"` //用户手机号
|
||||
Money int64 `json:"money" bson:"money"` //充值金额 订单金额 李秋山确认
|
||||
PayMoney int64 `json:"payMoney" bson:"payMoney"` //实际到账金额 用户实际支付金额 李秋山确认
|
||||
Status int `json:"status" bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
|
||||
StatusDesc string `json:"statusDesc" bson:"statusDesc"` //状态描述
|
||||
Remark string `json:"remark" bson:"remark"` //备注
|
||||
FailureAt time.Time `json:"failureAt" bson:"failureAt"` //回调失败时间
|
||||
SuccessAt time.Time `json:"successAt" bson:"successAt"` //回调成功时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
package rchgordmod
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"91porn-server/common/pageopt"
|
||||
"91porn-server/common/ysinterface/disc"
|
||||
)
|
||||
|
||||
type DistrictStatKey struct {
|
||||
DiscSeqe `bson:",inline"` //商区码
|
||||
DevType string `bson:"devType"` //系统类型 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.DevType
|
||||
}
|
||||
|
||||
func (d DistrictStatKey) String() string {
|
||||
if d.DiscSeqe.String() == "" {
|
||||
return ""
|
||||
}
|
||||
return strings.ToUpper(strings.Join([]string{d.DiscSeqe.String(), d.DevType}, "-"))
|
||||
}
|
||||
|
||||
type DistrictStater = disc.DistrictStater
|
||||
|
||||
// DistrictOrderCountMap districtCode->订单数 map
|
||||
func DistrictOrderCountMap(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{}
|
||||
if err := coll(nil).Find(&list, filter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater]int64, len(list))
|
||||
for _, v := range list {
|
||||
if v.String() != "" {
|
||||
m[v] += 1
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// DistrictOrderMoneyMap districtCode->完成订单数 map
|
||||
func DistrictOrderMoneyMap(start, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
|
||||
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
|
||||
filter := pageopt.MergeM(mats)
|
||||
var list []struct {
|
||||
DistrictStatKey `bson:",inline"` //商区码
|
||||
Money int64 `bson:"money"` //充值金额 订单金额 李秋山确认
|
||||
}
|
||||
if err := coll(nil).Find(&list, filter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater]int64, len(list))
|
||||
for _, v := range list {
|
||||
if v.String() != "" {
|
||||
m[v.DistrictStatKey] += v.Money
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// DistrictCompleteOrderCountMap districtCode->订单金额 map
|
||||
func DistrictCompleteOrderCountMap(start, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
|
||||
mats = append(mats, (&SuccessAtGTEAndLTMatch{&start, &end}).New())
|
||||
filter := pageopt.MergeM(mats)
|
||||
list := []DistrictStatKey{}
|
||||
if err := coll(nil).Find(&list, filter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater]int64, len(list))
|
||||
for _, v := range list {
|
||||
if v.String() != "" {
|
||||
m[v] += 1
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// DistrictCompleteOrderPayMoneyMap districtCode->完成订单的用户实际支付金额 map
|
||||
func DistrictCompleteOrderPayMoneyMap(start, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
|
||||
mats = append(mats, (&SuccessAtGTEAndLTMatch{&start, &end}).New())
|
||||
filter := pageopt.MergeM(mats)
|
||||
var list []struct {
|
||||
DistrictStatKey `bson:",inline"` //商区码
|
||||
PayMoney int64 `bson:"payMoney"` //实际到账金额 实际支付金额 李秋山确认
|
||||
}
|
||||
if err := coll(nil).Find(&list, filter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater]int64, len(list))
|
||||
for _, v := range list {
|
||||
if v.String() != "" {
|
||||
m[v.DistrictStatKey] += v.PayMoney
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// DiscCompleteOrderUIDSMap districtCode->完成订单的用户列表 map key:District
|
||||
func DiscCompleteOrderUIDSMap(start, end time.Time, mats ...Matcher) (map[DistrictStater][]uint64, error) {
|
||||
mats = append(mats, (&SuccessAtGTEAndLTMatch{&start, &end}).New())
|
||||
filter := pageopt.MergeM(mats)
|
||||
var list []struct {
|
||||
DistrictCode string `json:"districtCode" bson:"districtCode"` //商区码
|
||||
UID uint64 `bson:"uid"` //uid
|
||||
}
|
||||
if err := coll(nil).Find(&list, filter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater][]uint64, len(list))
|
||||
for _, v := range list {
|
||||
key := DistrictStatKey{
|
||||
DiscSeqe: DiscSeqe{DistrictCode: v.DistrictCode},
|
||||
}
|
||||
if key.String() != "" {
|
||||
m[key] = append(m[key], v.UID)
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// DistrictCompleteOrderUIDSMap districtCode->完成订单的用户列表 map key:DiscSeqeSystem
|
||||
func DistrictCompleteOrderUIDSMap(start, end time.Time, mats ...Matcher) (map[DistrictStater][]uint64, error) {
|
||||
mats = append(mats, (&SuccessAtGTEAndLTMatch{&start, &end}).New())
|
||||
filter := pageopt.MergeM(mats)
|
||||
var list []struct {
|
||||
DistrictStatKey `bson:",inline"` //商区码
|
||||
UID uint64 `bson:"uid"` //uid
|
||||
}
|
||||
if err := coll(nil).Find(&list, filter); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater][]uint64, len(list))
|
||||
for _, v := range list {
|
||||
if v.String() != "" {
|
||||
m[v.DistrictStatKey] = append(m[v.DistrictStatKey], v.UID)
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// 时间内购买VIP次数
|
||||
func CompleteOrderCountByDiscCode(start, end time.Time, discCode string) (int64, error) {
|
||||
mats := []Matcher{
|
||||
(&SuccessAtGTEAndLTMatch{GTE: &start, LT: &end}).New(),
|
||||
(&DistrictCodeMatch{DistrictCode: &discCode}).New(),
|
||||
}
|
||||
filter := pageopt.MergeM(mats)
|
||||
return coll(nil).Count(filter)
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
package rchgordmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/common/pageopt"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type Matcher = pageopt.Matcher
|
||||
|
||||
// ChannelMatch
|
||||
type ChannelMatch struct {
|
||||
Channel *string
|
||||
}
|
||||
|
||||
func (c *ChannelMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("channel", c.Channel)
|
||||
}
|
||||
|
||||
// StatusMatch
|
||||
type StatusMatch struct {
|
||||
Status *int
|
||||
}
|
||||
|
||||
func (s *StatusMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("status", s.Status)
|
||||
}
|
||||
|
||||
// IDMatch
|
||||
type IDMatch = pageopt.IDMatch
|
||||
|
||||
// UIDMatch
|
||||
type UIDMatch = pageopt.UIDMatch
|
||||
|
||||
// UIDInMatch
|
||||
type UIDInMatch = pageopt.UIDInMatch
|
||||
|
||||
// RechargeTypeMatch
|
||||
type RechargeTypeMatch struct {
|
||||
RechargeType *string
|
||||
}
|
||||
|
||||
func (s *RechargeTypeMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("rechargeType", s.RechargeType)
|
||||
}
|
||||
|
||||
// RechargeTypeINMatch
|
||||
type RechargeTypeINMatch struct {
|
||||
RechargeTypes []RechType
|
||||
}
|
||||
|
||||
func (s *RechargeTypeINMatch) New() Matcher {
|
||||
return pageopt.NewInMatch("rechargeType", s.RechargeTypes)
|
||||
}
|
||||
|
||||
// DistrictCodeMatch
|
||||
type DistrictCodeMatch struct {
|
||||
DistrictCode *string
|
||||
}
|
||||
|
||||
func (s *DistrictCodeMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("districtCode", s.DistrictCode)
|
||||
}
|
||||
|
||||
// PromSeqeMatch
|
||||
type PromSeqeMatch struct {
|
||||
PromSeqe *string
|
||||
}
|
||||
|
||||
func (s *PromSeqeMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("promSeqe", s.PromSeqe)
|
||||
}
|
||||
|
||||
// IsDirectMatch
|
||||
type IsDirectMatch struct {
|
||||
IsDirect *bool
|
||||
}
|
||||
|
||||
func (b *IsDirectMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("isDirect", b.IsDirect)
|
||||
}
|
||||
|
||||
type DevTypeMatch struct {
|
||||
DevType *string
|
||||
}
|
||||
|
||||
func (d *DevTypeMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("devType", d.DevType)
|
||||
}
|
||||
|
||||
// StatusInMatch
|
||||
type StatusInMatch struct {
|
||||
Status []int
|
||||
}
|
||||
|
||||
func (d *StatusInMatch) New() Matcher {
|
||||
return pageopt.NewInMatch("status", d.Status)
|
||||
}
|
||||
|
||||
// NotifyStatusMatch
|
||||
type NotifyStatusMatch struct {
|
||||
NotifyStatus []int
|
||||
}
|
||||
|
||||
func (d *NotifyStatusMatch) New() Matcher {
|
||||
return pageopt.NewInMatch("notifyStatus", d.NotifyStatus)
|
||||
}
|
||||
|
||||
// ProgressAtGTEAndLTMatch
|
||||
type ProgressAtGTEAndLTMatch struct {
|
||||
GTE *time.Time
|
||||
LT *time.Time
|
||||
}
|
||||
|
||||
func (s *ProgressAtGTEAndLTMatch) New() Matcher {
|
||||
return pageopt.NewGTEAndLTMatch("progressAt", s.GTE, s.LT)
|
||||
}
|
||||
|
||||
// FailureAtGTEAndLTMatch
|
||||
type FailureAtGTEAndLTMatch struct {
|
||||
GTE *time.Time
|
||||
LT *time.Time
|
||||
}
|
||||
|
||||
func (s *FailureAtGTEAndLTMatch) New() Matcher {
|
||||
return pageopt.NewGTEAndLTMatch("failureAt", s.GTE, s.LT)
|
||||
}
|
||||
|
||||
// SuccessAtGTEAndLTMatch
|
||||
type SuccessAtGTEAndLTMatch struct {
|
||||
GTE *time.Time
|
||||
LT *time.Time
|
||||
}
|
||||
|
||||
func (s *SuccessAtGTEAndLTMatch) New() Matcher {
|
||||
return pageopt.NewGTEAndLTMatch("successAt", s.GTE, s.LT)
|
||||
}
|
||||
|
||||
//PaymentAtGTEAndLTMatch
|
||||
//type PaymentAtGTEAndLTMatch struct {
|
||||
// GTE *time.Time
|
||||
// LT *time.Time
|
||||
//}
|
||||
//
|
||||
//func (s *PaymentAtGTEAndLTMatch) New() Matcher {
|
||||
// return pageopt.NewGTEAndLTMatch("paymentAt", s.GTE, s.LT)
|
||||
//}
|
||||
|
||||
// CreatedAtGTEAndLTMatch
|
||||
type CreatedAtGTEAndLTMatch = pageopt.CreatedAtGTEAndLTMatch
|
||||
|
||||
// CreatedAtLTMatch
|
||||
type CreatedAtLTMatch = pageopt.CreatedAtLTMatch
|
||||
|
||||
type Sort = bson.D
|
||||
|
||||
type M = bson.M
|
||||
|
||||
var Sort_CreatedAt_n1 = Sort{{Key: "createdAt", Value: -1}}
|
||||
|
||||
type RechargeOrderSlice []*RechargeOrder
|
||||
|
||||
func (this RechargeOrderSlice) Map() map[primitive.ObjectID]*RechargeOrder {
|
||||
m := map[primitive.ObjectID]*RechargeOrder{}
|
||||
for _, v := range this {
|
||||
m[v.ID] = v
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func List(sort Sort, skip, limit *int64, matchers ...Matcher) (RechargeOrderSlice, 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 := RechargeOrderSlice{}
|
||||
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
||||
log.Error("rchgordmod 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("rchgordmod Count error", log.E(err))
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
@@ -0,0 +1,775 @@
|
||||
/*
|
||||
* @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
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package rchgordmod
|
||||
|
||||
import (
|
||||
"91porn-server/middleware/ua"
|
||||
"time"
|
||||
|
||||
"91porn-server/common/db"
|
||||
"91porn-server/models/commod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
const (
|
||||
DEFAULT = iota //默认
|
||||
Processing //1进行中
|
||||
FAILURE //2失败
|
||||
SUCCESS //3成功
|
||||
REFUND //4退款
|
||||
)
|
||||
|
||||
const (
|
||||
UnLock = iota //0锁定 订单操作锁 解锁
|
||||
Lock //1锁定 订单操作锁 加锁 目前在代充中用到
|
||||
)
|
||||
|
||||
// 通知第三方上分结果
|
||||
const (
|
||||
Notify_DEFAULT = iota //默认
|
||||
Notify_SUCCESS //1 成功通知第三方
|
||||
Notify_FAILURE //2 通知第三方失败
|
||||
)
|
||||
|
||||
type Status int
|
||||
|
||||
var status = map[Status]string{
|
||||
Processing: "processing",
|
||||
FAILURE: "failure",
|
||||
SUCCESS: "success",
|
||||
REFUND: "refund",
|
||||
}
|
||||
|
||||
func (s Status) Desc() string {
|
||||
if desc, ok := status[s]; ok {
|
||||
return desc
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 支付类型
|
||||
type RechType string
|
||||
|
||||
const (
|
||||
Rech_WeChat RechType = "wechat" //微信
|
||||
Rech_AliPay RechType = "alipay" //支付宝
|
||||
Rech_Union RechType = "union" //支付宝
|
||||
Rech_DaiChong RechType = "daichong" //代充
|
||||
)
|
||||
|
||||
type ChildType int
|
||||
|
||||
const (
|
||||
Gold ChildType = iota + 1 // 购买金币
|
||||
VIP // 购买会员卡
|
||||
FruitCoin // 购买果币
|
||||
NudeChatService // 购买裸聊服务
|
||||
)
|
||||
|
||||
const (
|
||||
GoldFish = "jinyu"
|
||||
Shark = "shayu"
|
||||
DaBaiSha = "dabaisha"
|
||||
Lucky = "lezhifu"
|
||||
Rongyi = "rongyi"
|
||||
GoldfishPlus = "dajinyu"
|
||||
IZhiFu = "izhifu"
|
||||
DXZhiFu = "dxzhifu"
|
||||
LeiHuo = "leihuo"
|
||||
ZhongFu = "zhongfu"
|
||||
YiLianFu = "yilianfu"
|
||||
YinSe = "yinse"
|
||||
)
|
||||
const (
|
||||
ChanShareNO = iota //不分成
|
||||
ChanShareCoin //金币分成
|
||||
ChanShareModVIP //vip分成
|
||||
)
|
||||
|
||||
var mdb *db.MongoDB
|
||||
|
||||
type DiscSeqe = commod.DiscSeqe
|
||||
|
||||
type DiscDoc = commod.DiscDoc
|
||||
|
||||
// RechargeOrder 账户充值流水
|
||||
type RechargeOrder struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` //流水id
|
||||
UID uint64 `json:"uid" bson:"uid"` //用户id
|
||||
DevID string `json:"devID" bson:"devID"` //设备id
|
||||
OID string `json:"oid" bson:"oid"` //支付平台订单号
|
||||
TraderId string `json:"traderId" bson:"traderId"` //商户ID
|
||||
UserIP string `json:"userIP" bson:"userIP"` //用户ip
|
||||
Name string `json:"name" bson:"name"` //用户名称
|
||||
Tel string `json:"tel" bson:"tel"` //用户手机号
|
||||
PayAct string `json:"payAct" bson:"payAct"` //支付账号
|
||||
DevType string `json:"devType" bson:"devType"` //设备系统类型 ios pc android
|
||||
Amount int64 `json:"amount" bson:"amount"` //虚拟币数量(金币/果币)
|
||||
Money int64 `json:"money" bson:"money"` //充值金额 订单金额 李秋山确认
|
||||
PayMoney int64 `json:"payMoney" bson:"payMoney"` //实际到账金额 用户实际支付金额 李秋山确认
|
||||
RechargeType string `json:"rechargeType" bson:"rechargeType"` //充值类型(支付类型)
|
||||
ProductID primitive.ObjectID `json:"productID" bson:"productID"` //充值金币类型id
|
||||
ProductName string `json:"productName" bson:"productName"` //充值产品名
|
||||
VipID primitive.ObjectID `json:"vipID" bson:"vipID"` //是否是vip冲 hi
|
||||
Channel string `json:"channel" bson:"channel"` //渠道类型 鲨鱼 金鱼
|
||||
Proof string `json:"proof" bson:"proof"` //代充平台 支付凭证
|
||||
Status int `json:"status" bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
|
||||
StatusDesc string `json:"statusDesc" bson:"statusDesc"` //状态描述
|
||||
LockStatus int `json:"lockStatus" bson:"lockStatus"` //订单操作锁定状态 用户订单更新操作 0-未锁定 可用于编辑订单 1-已锁定 不可编辑
|
||||
NotifyTime int64 `json:"notifyTime" bson:"notifyTime"` //第三方回调本地订单的时间
|
||||
NotifyStatus int `json:"notifyStatus" bson:"notifyStatus"` //通知第三方上分情况状态 1-成功 2-失败
|
||||
Remark string `json:"remark" bson:"remark"` //备注
|
||||
ProgressAt time.Time `json:"progressAt" bson:"progressAt"` //第三方下单成功时间
|
||||
RefundAt time.Time `json:"refundAt" bson:"refundAt"` // 退款失败时间
|
||||
FailureAt time.Time `json:"failureAt" bson:"failureAt"` //回调失败时间
|
||||
SuccessAt time.Time `json:"successAt" bson:"successAt"` //回调成功时间
|
||||
PaymentAt time.Time `json:"paymentAt" bson:"paymentAt"` //支付时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` //刷新时间
|
||||
Rate string `json:"rate" bson:"rate"` //渠道费率
|
||||
ProductType int `json:"productType" bson:"productType"` //支付产品类型 0 站群 1 棋牌
|
||||
BuyType commod.BuyType `json:"buyType" bson:"buyType"` //充值购买类型
|
||||
ServiceID primitive.ObjectID `json:"serviceId" bson:"serviceId"` //裸聊服务ID
|
||||
DiscDoc `bson:",inline"` //商区
|
||||
ChanShareMod int `json:"chanShareMod" bson:"chanShareMod"` //渠道分成类型
|
||||
Category int `json:"category" bson:"category"` //充值类别 0金币 1会员
|
||||
GoldExtraID *primitive.ObjectID `json:"goldExtraID" bson:"goldExtraID,omitempty"` // 金币加购券
|
||||
Ua ua.UA `json:"ua" bson:"ua"`
|
||||
SourcePage string `json:"sourcePage,omitempty" bson:"sourcePage,omitempty"` // 下单来源页面
|
||||
SourceRef string `json:"sourceRef,omitempty" bson:"sourceRef,omitempty"` // 来源业务对象
|
||||
VideoID string `json:"videoId,omitempty" bson:"videoId,omitempty"` // 来源视频ID
|
||||
ActivityID string `json:"activityId,omitempty" bson:"activityId,omitempty"` // 来源活动ID
|
||||
ExperimentID string `json:"experimentId,omitempty" bson:"experimentId,omitempty"` // A/B实验ID
|
||||
ExperimentVariant string `json:"experimentVariant,omitempty" bson:"experimentVariant,omitempty"` // A/B实验分组
|
||||
SessionID string `json:"sessionId,omitempty" bson:"sessionId,omitempty"` // 前端会话ID
|
||||
MediaID primitive.ObjectID `json:"mediaId,omitempty" bson:"mediaId,omitempty"` // 短剧ID
|
||||
ContentID primitive.ObjectID `json:"contentId,omitempty" bson:"contentId,omitempty"` // 短剧单集ID
|
||||
CheckoutContextID string `json:"checkoutContextId,omitempty" bson:"checkoutContextId,omitempty"` // 短剧付费墙上下文
|
||||
CouponID string `json:"couponId,omitempty" bson:"couponId,omitempty"` // 会员抵扣券ID(活动服券号,不透明串,支付结果回调时原样回传)
|
||||
DeductAmount int64 `json:"deductAmount,omitempty" bson:"deductAmount,omitempty"` // 抵扣金额(分),已按上限封顶后的实际抵扣额
|
||||
}
|
||||
|
||||
func Init() {
|
||||
mdb = db.Init(table)
|
||||
initIndex()
|
||||
}
|
||||
|
||||
type RechargeStat struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` //流水id
|
||||
UID uint64 `json:"uid" bson:"uid"` //用户id
|
||||
DevID string `json:"devID" bson:"devID"` //设备id
|
||||
OID string `json:"oid" bson:"oid"` //支付平台订单号
|
||||
TraderId string `json:"traderId" bson:"traderId"` //商户ID
|
||||
UserIP string `json:"userIP" bson:"userIP"` //用户ip
|
||||
Name string `json:"name" bson:"name"` //用户名称
|
||||
Tel string `json:"tel" bson:"tel"` //用户手机号
|
||||
PayAct string `json:"payAct" bson:"payAct"` //支付账号
|
||||
DevType string `json:"devType" bson:"devType"` //设备系统类型 ios pc android
|
||||
Amount int64 `json:"amount" bson:"amount"` //虚拟币数量(金币/果币)
|
||||
Money int64 `json:"money" bson:"money"` //充值金额 订单金额 李秋山确认
|
||||
PayMoney int64 `json:"payMoney" bson:"payMoney"` //实际到账金额 用户实际支付金额 李秋山确认
|
||||
RechargeType string `json:"rechargeType" bson:"rechargeType"` //充值类型(支付类型)
|
||||
ProductID primitive.ObjectID `json:"productID" bson:"productID"` //充值金币类型id
|
||||
VipID primitive.ObjectID `json:"vipID" bson:"vipID"` //是否是vip冲 hi
|
||||
Channel string `json:"channel" bson:"channel"` //渠道类型 鲨鱼 金鱼
|
||||
Proof string `json:"proof" bson:"proof"` //代充平台 支付凭证
|
||||
Status int `json:"status" bson:"status"` //1进行中 2付款失败 3付款成功 4已经退款
|
||||
StatusDesc string `json:"statusDesc" bson:"statusDesc"` //状态描述
|
||||
LockStatus int `json:"lockStatus" bson:"lockStatus"` //订单操作锁定状态 用户订单更新操作 0-未锁定 可用于编辑订单 1-已锁定 不可编辑
|
||||
NotifyTime int64 `json:"notifyTime" bson:"notifyTime"` //第三方回调本地订单的时间
|
||||
NotifyStatus int `json:"notifyStatus" bson:"notifyStatus"` //通知第三方上分情况状态 1-成功 2-失败
|
||||
Remark string `json:"remark" bson:"remark"` //备注
|
||||
ProgressAt time.Time `json:"progressAt" bson:"progressAt"` //第三方下单成功时间
|
||||
FailureAt time.Time `json:"failureAt" bson:"failureAt"` //回调失败时间
|
||||
SuccessAt time.Time `json:"successAt" bson:"successAt"` //回调成功时间
|
||||
PaymentAt time.Time `json:"paymentAt" bson:"paymentAt"` //支付时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` //刷新时间
|
||||
Rate string `json:"rate" bson:"rate"` //渠道费率
|
||||
ProductType int `json:"productType" bson:"productType"` //支付产品类型 0 站群 1 棋牌
|
||||
BuyType commod.BuyType `json:"buyType" bson:"buyType"` //充值购买类型
|
||||
ServiceID primitive.ObjectID `json:"serviceId" bson:"serviceId"` //裸聊服务ID
|
||||
DiscDoc `bson:",inline"` //商区
|
||||
ChanShareMod int `json:"chanShareMod" bson:"chanShareMod"` //渠道分成类型
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package rchgordmod
|
||||
|
||||
import (
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type VIPExperimentOrderStat struct {
|
||||
Variant string `json:"variant" bson:"variant"`
|
||||
ProductID primitive.ObjectID `json:"productId" bson:"productId"`
|
||||
CreatedOrders int `json:"createdOrders" bson:"createdOrders"`
|
||||
PaidOrders int `json:"paidOrders" bson:"paidOrders"`
|
||||
RefundedOrders int `json:"refundedOrders" bson:"refundedOrders"`
|
||||
OrderAmount int64 `json:"orderAmount" bson:"orderAmount"`
|
||||
PaidAmount int64 `json:"paidAmount" bson:"paidAmount"`
|
||||
GoldPaidOrders int `json:"goldPaidOrders" bson:"goldPaidOrders"`
|
||||
GoldPaidAmount int64 `json:"goldPaidAmount" bson:"goldPaidAmount"`
|
||||
}
|
||||
|
||||
func VIPExperimentOrderStatistics(experimentID string) ([]VIPExperimentOrderStat, error) {
|
||||
var raw []struct {
|
||||
ID struct {
|
||||
Variant string `bson:"variant"`
|
||||
ProductID primitive.ObjectID `bson:"productId"`
|
||||
} `bson:"_id"`
|
||||
CreatedOrders int `bson:"createdOrders"`
|
||||
PaidOrders int `bson:"paidOrders"`
|
||||
RefundedOrders int `bson:"refundedOrders"`
|
||||
OrderAmount int64 `bson:"orderAmount"`
|
||||
PaidAmount int64 `bson:"paidAmount"`
|
||||
}
|
||||
err := coll(nil).Aggregate(&raw, []bson.M{
|
||||
{"$match": bson.M{"experimentId": experimentID}},
|
||||
{"$group": bson.M{
|
||||
"_id": bson.M{
|
||||
"variant": "$experimentVariant",
|
||||
"productId": "$productID",
|
||||
},
|
||||
"createdOrders": bson.M{"$sum": 1},
|
||||
"paidOrders": bson.M{"$sum": bson.M{"$cond": bson.A{
|
||||
bson.M{"$eq": bson.A{"$status", SUCCESS}}, 1, 0,
|
||||
}}},
|
||||
"refundedOrders": bson.M{"$sum": bson.M{"$cond": bson.A{
|
||||
bson.M{"$eq": bson.A{"$status", REFUND}}, 1, 0,
|
||||
}}},
|
||||
"orderAmount": bson.M{"$sum": "$money"},
|
||||
"paidAmount": bson.M{"$sum": bson.M{"$cond": bson.A{
|
||||
bson.M{"$eq": bson.A{"$status", SUCCESS}}, "$payMoney", 0,
|
||||
}}},
|
||||
}},
|
||||
{"$sort": bson.D{{Key: "_id.variant", Value: 1}, {Key: "createdOrders", Value: -1}}},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]VIPExperimentOrderStat, 0, len(raw))
|
||||
for _, item := range raw {
|
||||
result = append(result, VIPExperimentOrderStat{
|
||||
Variant: item.ID.Variant,
|
||||
ProductID: item.ID.ProductID,
|
||||
CreatedOrders: item.CreatedOrders,
|
||||
PaidOrders: item.PaidOrders,
|
||||
RefundedOrders: item.RefundedOrders,
|
||||
OrderAmount: item.OrderAmount,
|
||||
PaidAmount: item.PaidAmount,
|
||||
})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package rchgordmod
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
// RechargeUpdateReq 修改参数
|
||||
type RechargeUpdateReq struct {
|
||||
StatusDesc *string `json:"statusDesc" bson:"statusDesc"` // 状态描述
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` //更新时间
|
||||
}
|
||||
|
||||
type RchgQueryReq struct {
|
||||
ID *string `form:"id" json:"_id,omitempty" bson:"_id"` //流水id
|
||||
UID *uint64 `form:"uid" json:"uid,omitempty" bson:"uid"` //用户id
|
||||
DevID *string `form:"devID" json:"devID,omitempty" bson:"devID"` //设备id
|
||||
OID *string `form:"oid" json:"oid,omitempty" bson:"oid"` //支付平台订单号
|
||||
TraderId *string `form:"traderId" json:"traderId,omitempty" bson:"traderId"` //商户ID
|
||||
UserIP *string `form:"userIP" json:"userIP,omitempty" bson:"userIP"` //用户ip
|
||||
Name *string `form:"name" json:"name,omitempty" bson:"name"` //用户名称
|
||||
Tel *string `form:"tel" json:"tel,omitempty" bson:"tel"` //用户手机号
|
||||
PayAct *string `form:"payAct" json:"payAct,omitempty" bson:"payAct"` //支付账号
|
||||
DevType *string `form:"devType" json:"devType,omitempty" bson:"devType"` //设备系统类型 ios pc android
|
||||
Amount *int64 `form:"amount" json:"amount,omitempty" bson:"amount"` //蝴蝶币数量
|
||||
Money *int64 `form:"money" json:"money,omitempty" bson:"money"` //充值金额
|
||||
PayMoney *int64 `form:"payMoney" json:"payMoney,omitempty" bson:"payMoney"` //实际到账金额
|
||||
RechargeType *string `form:"rechargeType" json:"rechargeType,omitempty" bson:"rechargeType"` //充值类型
|
||||
Channel *string `form:"channel" json:"channel,omitempty" bson:"channel"` //渠道类型 鲨鱼 金鱼
|
||||
Account *string `form:"bankAccount" json:"bankAccount,omitempty" bson:"bankAccount"` //银行账户,支付宝或微信账户
|
||||
BackName *string `form:"backName" json:"backName,omitempty" bson:"backName"` //银行名称,如果是银行类型提现,必填
|
||||
TranOrder *string `form:"tranOrder" json:"tranOrder,omitempty" bson:"tranOrder"` //交易充值的订单号
|
||||
Status *int `form:"status" json:"status,omitempty" bson:"status"` //0代表进行中 1付款成功,可退款 2付款失败 3付款成功 4已经退款
|
||||
ProductType *int `form:"productType" json:"productType,omitempty" bson:"productType"` //产品类型 0站群 1棋牌
|
||||
SourcePage *string `form:"sourcePage" json:"sourcePage,omitempty" bson:"sourcePage"`
|
||||
SourceRef *string `form:"sourceRef" json:"sourceRef,omitempty" bson:"sourceRef"`
|
||||
VideoID *string `form:"videoId" json:"videoId,omitempty" bson:"videoId"`
|
||||
ActivityID *string `form:"activityId" json:"activityId,omitempty" bson:"activityId"`
|
||||
ExperimentID *string `form:"experimentId" json:"experimentId,omitempty" bson:"experimentId"`
|
||||
ExperimentVariant *string `form:"experimentVariant" json:"experimentVariant,omitempty" bson:"experimentVariant"`
|
||||
SessionID *string `form:"sessionId" json:"sessionId,omitempty" bson:"sessionId"`
|
||||
}
|
||||
|
||||
type RchargeOrderExport struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` //流水id
|
||||
UID uint64 `json:"uid" bson:"uid"` //用户id
|
||||
DevID string `json:"devID" bson:"devID" ` //设备id
|
||||
OID string `json:"oid" bson:"oid"` //支付平台订单号
|
||||
TraderId string `json:"traderId,omitempty" bson:"traderId,omitempty"` //商户ID
|
||||
UserIP string `json:"userIP" bson:"userIP"` //用户ip
|
||||
Name string `json:"name" bson:"name" ` //用户名称
|
||||
Tel string `json:"tel" bson:"tel" ` //用户手机号
|
||||
PayAct string `json:"payAct" bson:"payAct" ` //支付账号
|
||||
DevType string `json:"devType" bson:"devType"` //设备系统类型 ios pc android
|
||||
Amount string `json:"amount" bson:"amount" ` //蝴蝶币数量
|
||||
Money string `json:"money" bson:"money"` //充值金额 订单金额 李秋山确认
|
||||
PayMoney string `json:"payMoney" bson:"payMoney"` //实际到账金额 用户实际支付金额 李秋山确认
|
||||
RechargeType string `json:"rechargeType" bson:"rechargeType"` //充值类型
|
||||
ProductID primitive.ObjectID `json:"productID" bson:"productID"` //充值金币类型id
|
||||
VipID primitive.ObjectID `json:"vipID" bson:"vipID"` //是否是vip冲 hi
|
||||
Channel string `json:"channel" bson:"channel"` //渠道类型 鲨鱼 金鱼
|
||||
Status int `json:"status" bson:"status" ` // 1进行中 2付款失败 3付款成功 4已经退款
|
||||
StatusDesc string `json:"statusDesc" bson:"statusDesc"` // 状态描述
|
||||
ProgressAt time.Time `json:"progressAt" bson:"progressAt"` //第三方下单成功时间
|
||||
FailureAt time.Time `json:"failureAt" bson:"failureAt"` //回调失败时间
|
||||
SuccessAt time.Time `json:"successAt" bson:"successAt"` //回调成功时间
|
||||
PaymentAt time.Time `json:"paymentAt" bson:"paymentAt"` //支付时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` //刷新时间
|
||||
SourcePage string `json:"sourcePage" bson:"sourcePage"`
|
||||
SourceRef string `json:"sourceRef" bson:"sourceRef"`
|
||||
VideoID string `json:"videoId" bson:"videoId"`
|
||||
ActivityID string `json:"activityId" bson:"activityId"`
|
||||
ExperimentID string `json:"experimentId" bson:"experimentId"`
|
||||
ExperimentVariant string `json:"experimentVariant" bson:"experimentVariant"`
|
||||
SessionID string `json:"sessionId" bson:"sessionId"`
|
||||
}
|
||||
Reference in New Issue
Block a user