|
|
package validevents
|
|
|
|
|
|
import (
|
|
|
"joybuywork/internal/app"
|
|
|
"joybuywork/internal/consts/ckey"
|
|
|
"joybuywork/internal/repository/cache"
|
|
|
"joybuywork/internal/repository/model"
|
|
|
"joybuywork/internal/repository/mtype"
|
|
|
"joybuywork/internal/service/cmm"
|
|
|
"joybuywork/internal/service/provider"
|
|
|
"joybuywork/internal/service/provider/award"
|
|
|
"joybuywork/internal/service/provider/stocks"
|
|
|
"joybuywork/internal/utils/lockdo"
|
|
|
"time"
|
|
|
|
|
|
"gits.branchcn.com/backend/microcode/plugins/derivative/lock"
|
|
|
"gorm.io/gen/field"
|
|
|
)
|
|
|
|
|
|
type win struct {
|
|
|
base
|
|
|
}
|
|
|
|
|
|
func (s *win) Event(user *model.FissionUser) (targetNum int32, setHelp bool, err error) {
|
|
|
fc := cmm.NewFirstCreate(s.Ctx, s.GetDao())
|
|
|
player, err := fc.FissionWin(user)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
defer func() {
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s._newcomerReward(user, player.ID, setHelp)
|
|
|
}()
|
|
|
|
|
|
data, err := s._event(user)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
targetNum = data.targetNum
|
|
|
|
|
|
if data.targetNum == 0 || user.IsHelp == mtype.Yes {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
ticket, err := cache.NewCampaignTicket(s.Ctx).FindByMark(user.CampaignID, mtype.FissionCampaignTicketCustom)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var preOk = true
|
|
|
switch ticket.PreEvent {
|
|
|
case mtype.FissionCampaignTicketPreEventInstall:
|
|
|
preOk = player.BindInstall == mtype.Yes
|
|
|
case mtype.FissionCampaignTicketPreEventRegister:
|
|
|
preOk = player.BindRegister == mtype.Yes
|
|
|
}
|
|
|
|
|
|
if !preOk {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
setHelp = true
|
|
|
|
|
|
err = s._eventHelp(user)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *win) Register(helper, beHelper *model.FissionUser) (setHelp bool, err error) {
|
|
|
player, err := cmm.NewFirstCreate(s.Ctx, s.GetDao()).FissionWin(helper)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
defer func() {
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s._newcomerReward(helper, player.ID, setHelp)
|
|
|
}()
|
|
|
|
|
|
if player.BindRegister == mtype.Yes {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionWin
|
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(player.ID)).UpdateSimple(m.BindRegister.Value(mtype.Yes))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
tasks, setHelp, err := s._getRegisterTasks(helper.CampaignID)
|
|
|
if err != nil || len(tasks) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s._fixTaskDo(beHelper, tasks)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *win) Install(helper, beHelper *model.FissionUser) (setHelp bool, err error) {
|
|
|
player, err := cmm.NewFirstCreate(s.Ctx, s.GetDao()).FissionWin(helper)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
defer func() {
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s._newcomerReward(helper, player.ID, setHelp)
|
|
|
}()
|
|
|
|
|
|
if player.BindInstall == mtype.Yes {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionWin
|
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(player.ID)).UpdateSimple(m.BindInstall.Value(mtype.Yes))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
tasks, setHelp, err := s._getInstallTasks(helper.CampaignID)
|
|
|
if err != nil || len(tasks) == 0 {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s._fixTaskDo(beHelper, tasks)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 一起赢发放新人奖
|
|
|
func (s *win) _newcomerReward(user *model.FissionUser, playerId int64, setHelp bool) (err error) {
|
|
|
conf, err := cache.NewCampaignWin(s.Ctx).FindByCampaignId(user.CampaignID)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
switch conf.NewcomerCond {
|
|
|
case mtype.FissionNewcomerCondInstall:
|
|
|
|
|
|
if user.Source != mtype.FissionUserSourceInstall || !s.Req.NewUser {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
case mtype.FissionNewcomerCondHelp:
|
|
|
|
|
|
if user.IsHelp == mtype.Yes || !setHelp {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
case mtype.FissionNewcomerCondInstallAndHelp:
|
|
|
|
|
|
if user.Source != mtype.FissionUserSourceInstall || user.IsHelp == mtype.Yes || !setHelp {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if !app.NewRedisLock(s.Ctx, ckey.FissionWinNewcomerOnce(user.ID)).SoftLock() {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
rewardM := s.GetDao().FissionCampaignReward
|
|
|
rl, err := rewardM.WithContext(s.Ctx).Where(
|
|
|
rewardM.CampaignID.Eq(user.CampaignID),
|
|
|
rewardM.RewardType.Eq(mtype.FissionCampaignRewardTypeNewcomer),
|
|
|
rewardM.IsDel.Eq(mtype.No),
|
|
|
).Find()
|
|
|
if err != nil {
|
|
|
return s.BE().MysqlError(err)
|
|
|
}
|
|
|
|
|
|
var randMap = make(map[int64]*model.FissionCampaignReward)
|
|
|
for _, v := range rl {
|
|
|
randMap[v.ID] = v
|
|
|
}
|
|
|
|
|
|
var reward *model.FissionCampaignReward
|
|
|
for _, v := range randMap {
|
|
|
reward = v
|
|
|
break
|
|
|
}
|
|
|
|
|
|
record, _, async, err := award.NewAwardReward(s.Ctx, s.GetDao(), s.cpn.ProjectID, user).One(reward, false)
|
|
|
if err != nil || record == nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
provider.NewFissionClue(s.Ctx, user.ID).AddNewcomerReward(record.ID)
|
|
|
|
|
|
s.MP().InApp(user).Newcomer(record.CreatedAt, record.RewardID, record.ID)
|
|
|
|
|
|
playerM := s.GetDao().FissionWin
|
|
|
_, err = playerM.WithContext(s.Ctx).Where(playerM.ID.Eq(playerId)).UpdateSimple(playerM.IsNewcomer.Value(mtype.Yes))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 如果为没有用户id,就不用通知客户
|
|
|
if user.SubUserID == "" {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
s.AddAfterRun(func() (err error) {
|
|
|
// 执行异步任务
|
|
|
for _, do := range async {
|
|
|
do()
|
|
|
}
|
|
|
return
|
|
|
})
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
type winStepDo func(player *model.FissionWin, conf *model.FissionCampaignWin, reward, nextReward *model.FissionCampaignReward, allInviteNum int32) (err error)
|
|
|
type winCycleDo func(player *model.FissionWin, conf *model.FissionCampaignWin, reward *model.FissionCampaignReward) (err error)
|
|
|
|
|
|
type winDo struct {
|
|
|
step winStepDo
|
|
|
cycle winCycleDo
|
|
|
}
|
|
|
|
|
|
func (s *win) _do(user *model.FissionUser, do winDo) (err error) {
|
|
|
//防止同一个人并发发礼物超发
|
|
|
lc := app.NewRedisLock(s.Ctx, ckey.FissionParentInviteOnce(user.ID), lock.SetExpire(10*time.Second)).Lock()
|
|
|
defer lc.Release()
|
|
|
if lc.Error() != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
fc := cmm.NewFirstCreate(s.Ctx, s.GetDao())
|
|
|
player, err := fc.FissionWin(user)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 被限制了
|
|
|
if player.LimitStatus != mtype.FissionReferralLimitStatusNone {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
conf, err := cache.NewCampaignWin(s.Ctx).FindByCampaignId(player.CampaignID)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
m := s.GetDao().FissionCampaignReward
|
|
|
rewards, err := cmm.NewCMM(s.Ctx, s.GetDao()).UserAppReward(user, m.Step)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if conf.RewardRule == mtype.FissionReferralRewardRuleStep {
|
|
|
var allInviteNum int32
|
|
|
for _, campaignReward := range rewards {
|
|
|
if campaignReward.InviteNum > allInviteNum {
|
|
|
allInviteNum = campaignReward.InviteNum
|
|
|
}
|
|
|
}
|
|
|
rewardL := len(rewards)
|
|
|
var reward, nextReward *model.FissionCampaignReward
|
|
|
for i, campaignReward := range rewards {
|
|
|
if campaignReward.Step == player.NextStep {
|
|
|
reward = campaignReward
|
|
|
|
|
|
if i < rewardL-1 {
|
|
|
nextReward = rewards[i+1]
|
|
|
}
|
|
|
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if nextReward == nil && conf.StepLoop == mtype.Yes {
|
|
|
nextReward = rewards[0]
|
|
|
}
|
|
|
|
|
|
return do.step(player, conf, reward, nextReward, allInviteNum)
|
|
|
} else if conf.RewardRule == mtype.FissionReferralRewardRuleCycle {
|
|
|
|
|
|
return do.cycle(player, conf, rewards[0])
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|
|
|
|
|
|
func (s *win) _eventHelp(helper *model.FissionUser) (err error) {
|
|
|
// 找被助力的人
|
|
|
user, err := cache.NewFissionUser(s.Ctx, helper.CampaignID).FindById(helper.ParentID)
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if user == nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
effectNum, err := s._statDirectNum(user.CampaignID, user.ID)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
do := winDo{
|
|
|
step: func(player *model.FissionWin, conf *model.FissionCampaignWin, reward, nextReward *model.FissionCampaignReward, allInviteNum int32) (err error) {
|
|
|
return s._step(user, effectNum, player, conf, reward, nextReward, allInviteNum)
|
|
|
},
|
|
|
cycle: func(player *model.FissionWin, conf *model.FissionCampaignWin, reward *model.FissionCampaignReward) (err error) {
|
|
|
err = s._cycle(user, effectNum, player, conf, reward)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return s._extra(user, player, effectNum)
|
|
|
},
|
|
|
}
|
|
|
|
|
|
return s._do(user, do)
|
|
|
}
|
|
|
|
|
|
// 用户固定事件任务
|
|
|
func (s *win) _fixTaskDo(user *model.FissionUser, tasks []*model.FissionCampaignTask) (err error) {
|
|
|
do := winDo{
|
|
|
step: func(player *model.FissionWin, conf *model.FissionCampaignWin, reward, nextReward *model.FissionCampaignReward, allInviteNum int32) (err error) {
|
|
|
for _, task := range tasks {
|
|
|
switch task.PropMark {
|
|
|
case mtype.FissionCampaignTaskPropMarkChance:
|
|
|
err = s._taskEffectDo(user, task, func() (err error) {
|
|
|
return s._step(user, s.effectNum, player, conf, reward, nextReward, allInviteNum)
|
|
|
})
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return
|
|
|
},
|
|
|
cycle: func(player *model.FissionWin, conf *model.FissionCampaignWin, reward *model.FissionCampaignReward) (err error) {
|
|
|
for _, task := range tasks {
|
|
|
switch task.PropMark {
|
|
|
case mtype.FissionCampaignTaskPropMarkChance:
|
|
|
err = s._taskEffectDo(user, task, func() (err error) {
|
|
|
err = s._cycle(user, s.effectNum, player, conf, reward)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return s._extra(user, player, s.effectNum)
|
|
|
})
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return
|
|
|
},
|
|
|
}
|
|
|
|
|
|
return s._do(user, do)
|
|
|
}
|
|
|
|
|
|
// 增加抽奖次数
|
|
|
func (s *win) _step(user *model.FissionUser, effectNum int64, player *model.FissionWin, conf *model.FissionCampaignWin, reward, nextReward *model.FissionCampaignReward, allInviteNum int32) (err error) {
|
|
|
|
|
|
var limitStatus int8
|
|
|
defer func() {
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s._limitStatus(player.ID, limitStatus)
|
|
|
}()
|
|
|
|
|
|
if conf.StepLoop == mtype.Yes && effectNum > int64(conf.InviteLimit) {
|
|
|
limitStatus = mtype.FissionReferralLimitStatusInvite
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//没有下一级任务
|
|
|
if reward == nil {
|
|
|
limitStatus = mtype.FissionReferralLimitStatusFinish
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var inviteNum = effectNum - int64(player.LoopInvite*allInviteNum)
|
|
|
|
|
|
//没有完成
|
|
|
if int64(reward.InviteNum) > inviteNum {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var decr = int64(reward.RewardNum)
|
|
|
|
|
|
//扣除总预算是否成功
|
|
|
var stock *stocks.Campaign
|
|
|
stock, err = stocks.NewCampaign(s.Ctx, player.CampaignID)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
ok, _ := stock.DecrPoolAndAdd(player.CampaignID, decr)
|
|
|
if !ok {
|
|
|
limitStatus = mtype.FissionReferralLimitStatusBudget
|
|
|
return
|
|
|
}
|
|
|
|
|
|
_, _, _, err = award.NewAwardReward(s.Ctx, s.GetDao(), s.cpn.ProjectID, user).One(reward, true)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if nextReward == nil {
|
|
|
limitStatus = mtype.FissionReferralLimitStatusFinish
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 初始化奖品的东西
|
|
|
playerM := s.GetDao().FissionWin
|
|
|
var up []field.AssignExpr
|
|
|
up = append(up, playerM.NextStep.Value(nextReward.Step))
|
|
|
if nextReward.Step <= reward.Step {
|
|
|
up = append(up, playerM.LoopInvite.Add(1))
|
|
|
}
|
|
|
|
|
|
_, err = playerM.WithContext(s.Ctx).Where(playerM.ID.Eq(player.ID)).UpdateSimple(up...)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
// 增加抽奖次数
|
|
|
func (s *win) _cycle(user *model.FissionUser, effectNum int64, player *model.FissionWin, conf *model.FissionCampaignWin, reward *model.FissionCampaignReward) (err error) {
|
|
|
|
|
|
var limitStatus int8
|
|
|
defer func() {
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
err = s._limitStatus(player.ID, limitStatus)
|
|
|
}()
|
|
|
|
|
|
if effectNum > int64(conf.InviteLimit) {
|
|
|
limitStatus = mtype.FissionReferralLimitStatusInvite
|
|
|
return
|
|
|
}
|
|
|
|
|
|
key := ckey.FissionUserGetRewardNum(user.ID)
|
|
|
num, err := lockdo.Int64(s.Ctx, key, func() (num int64, err error) {
|
|
|
m := s.GetDao().FissionRewardRecord.SubTable(user.CampaignID)
|
|
|
return m.WithContext(s.Ctx).Where(
|
|
|
m.UserID.Eq(user.ID),
|
|
|
m.RewardType.Eq(mtype.FissionCampaignRewardTypeApp),
|
|
|
).Count()
|
|
|
})
|
|
|
|
|
|
if err != nil {
|
|
|
err = s.BE().CacheError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var needInvite = int64(reward.InviteNum) //完成任务需要邀请的人数
|
|
|
var decr = int64(reward.RewardNum) //奖品数据
|
|
|
cn := effectNum - (num * needInvite) //总邀请人数 -(完成任务数 * 完成任务需要邀请的人数)= 计算完成任务的邀请人数
|
|
|
|
|
|
//邀请的人不足以获取到奖品
|
|
|
if cn < needInvite {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//扣除总预算是否成功
|
|
|
var stock *stocks.Campaign
|
|
|
stock, err = stocks.NewCampaign(s.Ctx, player.CampaignID)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
ok, _ := stock.DecrPoolAndAdd(player.CampaignID, decr)
|
|
|
if !ok {
|
|
|
limitStatus = mtype.FissionReferralLimitStatusBudget
|
|
|
return
|
|
|
}
|
|
|
|
|
|
_, _, _, err = award.NewAwardReward(s.Ctx, s.GetDao(), s.cpn.ProjectID, user).One(reward, true)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 领奖数+1
|
|
|
app.Redis.Cache.Incr(s.Ctx, key)
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
func (s *win) _limitStatus(playerId int64, ls int8) (err error) {
|
|
|
if ls == mtype.FissionReferralLimitStatusNone {
|
|
|
return
|
|
|
}
|
|
|
m := s.GetDao().FissionWin
|
|
|
var up = []field.AssignExpr{
|
|
|
m.LimitStatus.Value(ls),
|
|
|
}
|
|
|
|
|
|
if ls == mtype.FissionReferralLimitStatusFinish {
|
|
|
up = append(up, m.NextStep.Value(0))
|
|
|
}
|
|
|
|
|
|
_, err = m.WithContext(s.Ctx).Where(m.ID.Eq(playerId)).UpdateSimple(up...)
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 额外
|
|
|
func (s *win) _extra(user *model.FissionUser, player *model.FissionWin, effectNum int64) (err error) {
|
|
|
m := s.GetDao().FissionCampaignReward
|
|
|
var extras []*model.FissionCampaignReward
|
|
|
var extraReward, nextExtraReward *model.FissionCampaignReward
|
|
|
extras, err = m.WithContext(s.Ctx).Where(
|
|
|
m.CampaignID.Eq(user.CampaignID),
|
|
|
m.RewardType.Eq(mtype.FissionCampaignRewardTypeExtra),
|
|
|
m.IsDel.Eq(mtype.No),
|
|
|
).Find()
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
rewardL := len(extras)
|
|
|
for i, extra := range extras {
|
|
|
if extra.Step == player.NextStep {
|
|
|
extraReward = extra
|
|
|
|
|
|
if i < rewardL-1 {
|
|
|
nextExtraReward = extras[i+1]
|
|
|
}
|
|
|
|
|
|
break
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if extraReward == nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//没有达标任务
|
|
|
if int64(extraReward.InviteNum) > effectNum {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
// 额外奖品
|
|
|
_, _, _, err = award.NewAwardReward(s.Ctx, s.GetDao(), s.cpn.ProjectID, user).One(extraReward, true)
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var nextStep int32
|
|
|
if nextExtraReward != nil {
|
|
|
nextStep = nextExtraReward.Step
|
|
|
}
|
|
|
|
|
|
// 下次的额外奖
|
|
|
playerM := s.GetDao().FissionWin
|
|
|
_, err = playerM.WithContext(s.Ctx).Where(playerM.ID.Eq(player.ID)).UpdateSimple(playerM.NextStep.Value(nextStep))
|
|
|
if err != nil {
|
|
|
err = s.BE().MysqlError(err)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
return
|
|
|
}
|