477 lines
15 KiB
Go
477 lines
15 KiB
Go
package proxyser
|
|
|
|
import (
|
|
"91porn-server/app/service/taskser"
|
|
"91porn-server/common/timeutil"
|
|
"91porn-server/models/v/dailytaskmod"
|
|
"91porn-server/models/v/rchgordmod"
|
|
"91porn-server/models/v/taskmod"
|
|
"errors"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"91porn-server/app/appg"
|
|
"91porn-server/common"
|
|
"91porn-server/common/constant"
|
|
"91porn-server/common/db"
|
|
"91porn-server/common/log"
|
|
"91porn-server/common/stderr"
|
|
"91porn-server/models/v/prdcthsomod"
|
|
"91porn-server/models/v/proxymod"
|
|
"91porn-server/models/v/proxyrecordmod"
|
|
"91porn-server/models/v/sourcemod"
|
|
"91porn-server/models/v/txnmod"
|
|
"91porn-server/models/v/usermod"
|
|
"91porn-server/models/v/walletmod"
|
|
|
|
"github.com/shopspring/decimal"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
)
|
|
|
|
var PerformanceConvRat = []int64{100, 25, 15, 10}
|
|
|
|
// 推广
|
|
func Invite(inv *proxyrecordmod.InvitationRecord) (err error) {
|
|
u, err := usermod.FindUserByUID(inv.UID)
|
|
if err != nil || u == nil {
|
|
return
|
|
}
|
|
p := sourcemod.GetRandomPromotionURL()
|
|
inv.PromotionCode = u.PromCode
|
|
inv.URL = common.BindUrl(p, constant.PromotionField+u.PromCode)
|
|
if err = proxyrecordmod.InsertInvitationRecord(inv); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
|
|
// InviteLog 推广绑定记录
|
|
func InviteLog(uid uint64, pageNumber int, pageSize int) (res []*proxymod.InvitationRes, hasNext bool, err error) {
|
|
data, hasNext, err := proxymod.GetInvitationByUID(uid, int64(pageNumber), int64(pageSize))
|
|
if err != nil {
|
|
return
|
|
}
|
|
if len(data) <= 0 {
|
|
res = make([]*proxymod.InvitationRes, 0)
|
|
return
|
|
}
|
|
res = make([]*proxymod.InvitationRes, len(data))
|
|
for idx, v := range data {
|
|
i := proxymod.InvitationRes{}
|
|
i.Invitation = *v
|
|
i.IsBoughtVIP, err = prdcthsomod.IsBoughtVIP(v.Invitee)
|
|
if err != nil {
|
|
return
|
|
}
|
|
res[idx] = &i
|
|
}
|
|
return
|
|
}
|
|
|
|
type Invitation = proxymod.Invitation
|
|
|
|
// InviteBind 推广绑定
|
|
func InviteBind(uid uint64, parentdisc string, isBind bool) stderr.Code {
|
|
now := time.Now()
|
|
//查询推广用户
|
|
user, err := usermod.FindUserByUID(uid)
|
|
if err != nil {
|
|
log.Warn("InviteBind FindUserByUID error", log.E(err), log.Any("uid", uid))
|
|
return stderr.Failure
|
|
}
|
|
if user == nil {
|
|
return stderr.ErrParamError
|
|
}
|
|
// 通过推广str查询父级用户
|
|
parent, err := findUserByPromotionStr(parentdisc)
|
|
if err != nil {
|
|
switch err.(type) {
|
|
case PromStrInvalidError:
|
|
return stderr.InvalidPromotionCode
|
|
default:
|
|
return stderr.ErrDbQueryError
|
|
}
|
|
}
|
|
// 判断推广是否合法
|
|
if err = canInvite(user, parent); err != nil {
|
|
switch err.(type) {
|
|
case SelfInvError:
|
|
return stderr.SelfPromotionCode
|
|
case proxymod.LoopInviteError:
|
|
return stderr.PromoteHasBind
|
|
default:
|
|
return stderr.NotInvitedUsers
|
|
}
|
|
}
|
|
i := Invitation{
|
|
UID: parent.UID,
|
|
Invitee: uid,
|
|
InviteePortrait: user.Portrait,
|
|
InviteCode: parentdisc,
|
|
CreatedAt: now,
|
|
InviteeName: user.Name,
|
|
IsRecharge: false,
|
|
}
|
|
if isBind {
|
|
i.InviteTime = now
|
|
}
|
|
//invitation表插入记录
|
|
if err := proxymod.InsertOne(i); err != nil {
|
|
switch err.(type) {
|
|
case proxymod.LoopInviteError:
|
|
return stderr.PromoteHasBind
|
|
default:
|
|
return stderr.ErrDbInsertError
|
|
}
|
|
}
|
|
|
|
common.Go(func() {
|
|
// 限制同ip注册不增加vip时间
|
|
if user.RegisterIP != parent.RegisterIP {
|
|
// 同一用户, 一天最多增加3个人的分享vip天数
|
|
startTime, endTime := timeutil.EarlyLastDay(time.Now())
|
|
maxCount, _ := proxymod.GetInviteesCount([]uint64{parent.UID}, startTime, endTime)
|
|
if maxCount < 3 {
|
|
_ = addFreeTime(*parent, 1*24*60*60)
|
|
}
|
|
log.Info("InviteBind addFreeTime", log.Any("uid", uid), log.Any("parentUid", parent.UID), log.Any("maxCount", maxCount), log.Any("startTime", startTime), log.Any("endTime", endTime))
|
|
}
|
|
})
|
|
go func() {
|
|
_ = taskser.CompleteDailyTask(nil, parent.UID, dailytaskmod.DailyTaskTypeUserInvite)
|
|
maxCount, _ := proxymod.CountByUID(parent.UID)
|
|
taskser.CompleteGrowthTask(parent.UID, taskmod.GrowthBuyInviteUser, maxCount)
|
|
_ = taskser.ReSignCallBack(parent.UID)
|
|
}()
|
|
return stderr.Success
|
|
}
|
|
|
|
// addFreeTime 增加Vip FreeTime
|
|
func addFreeTime(user usermod.User, freeSecond int64) error {
|
|
freeTime := time.Unix(time.Now().Unix()+freeSecond, 0)
|
|
if user.VipExpireDate.After(time.Now()) {
|
|
freeTime = time.Unix(user.VipExpireDate.Unix()+freeSecond, 0)
|
|
}
|
|
upd := usermod.UserSelector{VipExpireDate: &freeTime}
|
|
if user.VipLevel == 0 {
|
|
l := 1
|
|
upd.VipLevel = &l
|
|
}
|
|
_, err := usermod.Update(user.UID, upd)
|
|
return err
|
|
}
|
|
|
|
func canInvite(user, parent *usermod.User) error {
|
|
if user == nil || parent == nil {
|
|
return errors.New("user is nil!")
|
|
}
|
|
//不能自我推广
|
|
if user.UID == parent.UID {
|
|
return SelfInvError{user.UID}
|
|
}
|
|
if user.CreatedAt.AddDate(0, 0, 1).Before(time.Now()) {
|
|
return errors.New("time is expire")
|
|
}
|
|
if user.CreatedAt.Before(parent.CreatedAt) {
|
|
return errors.New("invaild invite")
|
|
}
|
|
// 推广用户只能是离散节点,不允许闭环推广
|
|
count, err := proxymod.CountByUID(user.UID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if count != 0 {
|
|
return proxymod.LoopInviteError{Parent: parent.UID, UID: user.UID}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func GetInv(uid uint64) (uint64, error) {
|
|
return proxymod.GetInvrLv1(uid)
|
|
}
|
|
|
|
func findUserByPromotionStr(promoCode string) (*usermod.User, error) {
|
|
parent, err := usermod.FindUserPromotionCode(promoCode)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if parent == nil {
|
|
log.Warn("userser InviteBind fail: invalid promotion code", log.Any("promoCode", promoCode))
|
|
return nil, PromStrInvalidError{promoCode}
|
|
}
|
|
return parent, nil
|
|
}
|
|
|
|
// GetInveUsers 获取下级代理
|
|
func GetInveUsers(uid uint64) (invMap map[string][]*usermod.User, err error) {
|
|
invMap = make(map[string][]*usermod.User, 0)
|
|
var MaxLv = 4
|
|
var flag = 0
|
|
ids := []uint64{uid}
|
|
usersChan := make(chan map[string][]*usermod.User, MaxLv)
|
|
for i := 1; i <= MaxLv; i++ {
|
|
flag += 1
|
|
uids, _, err := proxymod.GetInveNext(ids)
|
|
if err != nil || len(ids) <= 0 {
|
|
break
|
|
}
|
|
go func(ids []uint64, lv int, datachan chan map[string][]*usermod.User) {
|
|
var users []*usermod.User
|
|
m := make(map[string][]*usermod.User)
|
|
users, _ = usermod.FindUsersByUID(ids)
|
|
m["lv"+strconv.Itoa(lv)] = users
|
|
datachan <- m
|
|
}(uids, i, usersChan)
|
|
ids = uids
|
|
}
|
|
for i := 0; i < flag; i++ {
|
|
um, ok := <-usersChan
|
|
if !ok {
|
|
break
|
|
}
|
|
for k, v := range um {
|
|
invMap[k] = v
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func StatCenterIncPerformance(t *db.MongoTool, uid uint64, proxyUserId uint64, incomeAmount int64, orderId string) error {
|
|
u, err := usermod.FindUserByUID(uid)
|
|
if err != nil {
|
|
if err.Error() == "empty user" {
|
|
return nil
|
|
}
|
|
return errors.New("invalid user")
|
|
}
|
|
if u == nil {
|
|
return nil
|
|
}
|
|
orderIdV1 := strings.Replace(orderId, "CZ-DSP-", "", -1)
|
|
objId, err := primitive.ObjectIDFromHex(orderIdV1)
|
|
if err != nil {
|
|
log.Error("StatCenterIncPerformance ObjectIDFromHex err", log.E(err))
|
|
return err
|
|
}
|
|
income := incomeAmount // 金币
|
|
pIncome := income
|
|
creditPlan := walletmod.CreditPlan{
|
|
Income: &income,
|
|
ProxyIncome: &pIncome,
|
|
}
|
|
wallet, err := walletmod.Credit(t, creditPlan, uid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
desc := "推广用户充值返现"
|
|
transacton := txnmod.TransactionLog{
|
|
UID: uid,
|
|
TransNo: objId,
|
|
Amount: income,
|
|
ActualAmount: float64(income),
|
|
TranType: txnmod.ProxyIncome.Key(),
|
|
TranTypeInt: int64(txnmod.ProxyIncome),
|
|
Desc: desc,
|
|
RechargeId: proxyUserId,
|
|
RealAmount: walletmod.GetRealAmount(wallet),
|
|
}
|
|
return txnmod.InsertTransactionLog(t, &transacton)
|
|
}
|
|
|
|
type WaLiPromoteSettleSyncDataReq struct {
|
|
Size int `json:"size"`
|
|
ID []primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
|
SetDate []time.Time `json:"setDate" bson:"setDate"` //结算日期
|
|
Money []decimal.Decimal `json:"money" bson:"money"` //收益金额 元
|
|
AppId []int `json:"appId" bson:"appId"` //appid
|
|
UID []uint64 `json:"uid" bson:"uid"` //用户id
|
|
NoticeStatus []int `json:"noticeStatus" bson:"noticeStatus"` //通知状态
|
|
}
|
|
|
|
type WaLiPromoteSettleSyncDataRes struct {
|
|
ID []primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
|
}
|
|
|
|
func StatCenterIncPerformanceWaLi(req WaLiPromoteSettleSyncDataReq) (res WaLiPromoteSettleSyncDataRes) {
|
|
successIDSlice := make([]primitive.ObjectID, 0)
|
|
for i := 0; i < req.Size; i++ {
|
|
income := req.Money[i].Shift(1).IntPart() // 金币
|
|
pIncome := float64(income) //金币
|
|
cp := walletmod.CreditPlan{
|
|
Income: &income,
|
|
WaLiProxyIncome: &pIncome,
|
|
}
|
|
flag := 1
|
|
_ = appg.VideoDB.Trans(func(t *db.MongoTool) error {
|
|
wallet, err := walletmod.Credit(t, cp, req.UID[i])
|
|
if err != nil {
|
|
flag = 2
|
|
return err
|
|
}
|
|
transacton := txnmod.TransactionLog{
|
|
UID: req.UID[i],
|
|
UniqueOrder: req.ID[i].Hex(),
|
|
Amount: income,
|
|
ActualAmount: float64(income),
|
|
TranType: txnmod.WaLiProxyIncome.Key(),
|
|
TranTypeInt: int64(txnmod.WaLiProxyIncome),
|
|
Desc: "游戏推广用户充值返现",
|
|
RealAmount: walletmod.GetRealAmount(wallet),
|
|
}
|
|
if err = txnmod.InsertTransactionLog(t, &transacton); err != nil {
|
|
if stderr.IsEqual(err, stderr.InsertExistError) {
|
|
return err
|
|
}
|
|
flag = 2
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
if flag == 2 {
|
|
continue
|
|
}
|
|
successIDSlice = append(successIDSlice, req.ID[i])
|
|
}
|
|
res.ID = successIDSlice
|
|
return
|
|
}
|
|
|
|
// GetInveUserList 获取下级代理列表
|
|
func GetInveUserList(uid, pageNumber, pageSize uint64) (list []*proxymod.Invitation, total int64, err error) {
|
|
//查询用户推广列表
|
|
total, list, err = proxymod.FindManyByApp(uid, pageNumber, pageSize)
|
|
if err != nil {
|
|
log.Error("HandelProxyRechargeCommission proxymod.FindManyByApp err", log.E(err), log.Any("uid", uid))
|
|
return list, 0, nil
|
|
}
|
|
if len(list) == 0 {
|
|
log.Warn("HandelProxyRechargeCommission len(list) == 0", log.Any("uid", uid))
|
|
return list, 0, nil
|
|
}
|
|
return list, total, nil
|
|
}
|
|
|
|
// HandelProxyRechargeCommission 处理代理充值分成
|
|
func HandelProxyRechargeCommission(t *db.MongoTool, orderId string, payMoney int64) {
|
|
//return
|
|
// 充值订单用户id
|
|
var uid uint64 = 0
|
|
// 截取订单号
|
|
orderIdV1 := strings.Replace(orderId, "CZ-91PO-", "", -1)
|
|
// 验证充值订单
|
|
order, err := rchgordmod.FindRechargeOrderByID(orderIdV1)
|
|
if err != nil {
|
|
log.Error("HandelProxyRechargeCommission rchgordmod.FindRechargeOrderByID err", log.E(err), log.Any("orderId", orderId))
|
|
return
|
|
}
|
|
uid = order.UID
|
|
if order.Status != rchgordmod.SUCCESS {
|
|
log.Warn("HandelProxyRechargeCommission order.Status != rchgordmod.SUCCESS", log.Any("uid", uid), log.Any("orderId", orderId))
|
|
return
|
|
}
|
|
// 棋牌订单不参与分成
|
|
if order.ProductType == 1 {
|
|
log.Info("HandelProxyRechargeCommission order.ProductType == 1", log.Any("uid", uid), log.Any("orderId", orderId))
|
|
return
|
|
}
|
|
// 金币订单不参与分成
|
|
if order.Category == 0 {
|
|
log.Info("HandelProxyRechargeCommission order.Category == 0", log.Any("uid", uid), log.Any("orderId", orderId))
|
|
return
|
|
}
|
|
// 查询用户上级id
|
|
proxyUserId, err := proxymod.GetInvrLv1(uid)
|
|
if err != nil {
|
|
log.Error("HandelProxyRechargeCommission proxymod.GetInvrLv1 err", log.E(err), log.Any("uid", uid), log.Any("proxyUserId", proxyUserId), log.Any("orderId", orderId))
|
|
return
|
|
}
|
|
if proxyUserId == 0 {
|
|
log.Warn("HandelProxyRechargeCommission proxyUserId == 0", log.E(err), log.Any("uid", uid), log.Any("proxyUserId", proxyUserId), log.Any("orderId", orderId))
|
|
return
|
|
}
|
|
// 查询当前订单是否已经分成
|
|
if txnmod.IsProxyExist(proxyUserId, order.ID) {
|
|
log.Warn("HandelProxyRechargeCommission txnmod.IsProxyExist == true", log.Any("uid", uid), log.Any("proxyUserId", proxyUserId), log.Any("orderId", orderId))
|
|
return
|
|
}
|
|
// 查询用户信息
|
|
u, err := usermod.FindUserByUID(proxyUserId)
|
|
if err != nil {
|
|
log.Error("HandelProxyRechargeCommission usermod.FindUserByUID err", log.E(err), log.Any("uid", uid), log.Any("proxyUserId", proxyUserId), log.Any("orderId", orderId))
|
|
return
|
|
}
|
|
if u == nil {
|
|
log.Warn("HandelProxyRechargeCommission u == nil", log.Any("uid", uid), log.Any("proxyUserId", proxyUserId), log.Any("orderId", orderId))
|
|
return
|
|
}
|
|
// 查询代理用户钱包
|
|
proxyUserWallet, err := walletmod.GetWallet(proxyUserId)
|
|
if err != nil {
|
|
log.Error("HandelProxyRechargeCommission walletmod.GetWallet err", log.E(err), log.Any("uid", uid), log.Any("proxyUserId", proxyUserId), log.Any("orderId", orderId))
|
|
return
|
|
}
|
|
if proxyUserWallet == nil {
|
|
log.Warn("HandelProxyRechargeCommission proxyUserWallet == nil", log.Any("uid", uid), log.Any("proxyUserId", proxyUserId), log.Any("orderId", orderId))
|
|
return
|
|
}
|
|
//分成收益计算,单位:金币个数
|
|
var incomeAmount int64 = 0
|
|
//代理推广用户累计充值
|
|
var proxyConsumption int64 = (proxyUserWallet.ProxyConsumption + payMoney) / 100
|
|
var money int64 = payMoney / 100
|
|
if proxyConsumption < 2000 {
|
|
//充值2000元以内, 返利50%
|
|
incomeAmount = money * 50 / 10
|
|
} else if proxyConsumption > 2000 && proxyConsumption < 10000 {
|
|
//充值2000—10000元以内, 返利60%
|
|
incomeAmount = money * 60 / 10
|
|
} else if proxyConsumption > 10000 && proxyConsumption < 30000 {
|
|
//充值10000—30000元以内, 返利65%
|
|
incomeAmount = money * 65 / 10
|
|
} else if proxyConsumption > 30000 {
|
|
//充值大于30000元, 返利70%
|
|
incomeAmount = money * 70 / 10
|
|
}
|
|
|
|
// 事务处理, 增加流水日志、代理收益
|
|
_ = appg.VideoDB.Trans(func(t *db.MongoTool) error {
|
|
//增加收益余额
|
|
pIncome := incomeAmount
|
|
creditPlan := walletmod.CreditPlan{
|
|
Income: &incomeAmount,
|
|
ProxyIncome: &pIncome,
|
|
ProxyConsumption: &payMoney,
|
|
}
|
|
wallet, err := walletmod.Credit(t, creditPlan, proxyUserId)
|
|
if err != nil {
|
|
log.Warn("HandelProxyRechargeCommission walletmod.Credit err", log.E(err), log.Any("uid", uid), log.Any("proxyUserId", proxyUserId), log.Any("orderId", orderId))
|
|
return err
|
|
}
|
|
//新增流水日志
|
|
transacton := txnmod.TransactionLog{
|
|
UID: proxyUserId,
|
|
TransNo: order.ID,
|
|
Amount: incomeAmount,
|
|
ActualAmount: float64(incomeAmount),
|
|
TranType: txnmod.ProxyIncome.Key(),
|
|
TranTypeInt: int64(txnmod.ProxyIncome),
|
|
Desc: "推广用户充值返现",
|
|
RechargeId: uid,
|
|
RealAmount: walletmod.GetRealAmount(wallet),
|
|
}
|
|
err = txnmod.InsertTransactionLog(t, &transacton)
|
|
if err != nil {
|
|
log.Warn("HandelProxyRechargeCommission txnmod.InsertTransactionLog err", log.E(err), log.Any("uid", uid), log.Any("proxyUserId", proxyUserId), log.Any("orderId", orderId))
|
|
return err
|
|
}
|
|
err = proxymod.UpdateByUid(t, uid, proxyUserId)
|
|
if err != nil {
|
|
log.Warn("HandelProxyRechargeCommission proxymod.UpdateByUid err", log.E(err), log.Any("uid", uid), log.Any("proxyUserId", proxyUserId), log.Any("orderId", orderId))
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
return
|
|
}
|