435 lines
13 KiB
Go
435 lines
13 KiB
Go
package service
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"sort"
|
|
"strconv"
|
|
"time"
|
|
|
|
"go-common/app/admin/main/growup/model"
|
|
"go-common/library/database/sql"
|
|
"go-common/library/log"
|
|
xtime "go-common/library/time"
|
|
)
|
|
|
|
const (
|
|
_activityNotStart = iota
|
|
_activityStart
|
|
_activityEnd
|
|
)
|
|
|
|
// AddActivity add creative activity
|
|
func (s *Service) AddActivity(c context.Context, ac *model.CActivity, creator string) (err error) {
|
|
ac.Creator = creator
|
|
_, err = s.dao.GetActivityByName(c, ac.Name)
|
|
if err == sql.ErrNoRows {
|
|
err = s.insertActivity(c, ac, "", true)
|
|
return
|
|
}
|
|
if err != nil {
|
|
log.Error("s.dao.GetActivityByName error(%v)", err)
|
|
return
|
|
}
|
|
err = fmt.Errorf("activity has exist")
|
|
return
|
|
}
|
|
|
|
func actQueyStmt(name, sort string) string {
|
|
query := ""
|
|
if name != "" {
|
|
query = fmt.Sprintf("WHERE name = '%s'", name)
|
|
}
|
|
if sort != "" {
|
|
query += " ORDER BY "
|
|
query += sort
|
|
}
|
|
return query
|
|
}
|
|
|
|
// ListActivity list activity by query
|
|
func (s *Service) ListActivity(c context.Context, name string, from, limit int, sort string) (acs []*model.CActivity, total int, err error) {
|
|
query := actQueyStmt(name, sort)
|
|
total, err = s.dao.ActivityCount(c, query)
|
|
if err != nil {
|
|
log.Error("s.dao.ActivityCount error(%v)", err)
|
|
return
|
|
}
|
|
acs, err = s.dao.GetActivities(c, query, from, limit)
|
|
if err != nil {
|
|
log.Error("s.dao.GetActivities error(%v)", err)
|
|
return
|
|
}
|
|
if len(acs) == 0 {
|
|
return
|
|
}
|
|
ids := make([]int64, len(acs))
|
|
for i := 0; i < len(acs); i++ {
|
|
ids[i] = acs[i].ID
|
|
}
|
|
bonus, err := s.getActivityBonus(c, ids)
|
|
if err != nil {
|
|
log.Error("s.getActivityBonus error(%v)", err)
|
|
return
|
|
}
|
|
|
|
now := xtime.Time(time.Now().Unix())
|
|
for _, ac := range acs {
|
|
if now < ac.SignUpStart {
|
|
ac.State = _activityNotStart
|
|
} else if now >= ac.SignUpStart && now <= ac.BonusTime {
|
|
ac.State = _activityStart
|
|
} else if now > ac.BonusTime {
|
|
ac.State = _activityEnd
|
|
}
|
|
ac.BonusMoney = bonus[ac.ID]
|
|
ac.Enrolment, err = s.dao.UpActivityStateCount(c, ac.ID, []int64{1, 2, 3})
|
|
if err != nil {
|
|
log.Error("s.dao.UpActivityStateCount error(%v)", err)
|
|
return
|
|
}
|
|
ac.WinNum, err = s.dao.UpActivityStateCount(c, ac.ID, []int64{2, 3})
|
|
if err != nil {
|
|
log.Error("s.dao.UpActivityStateCount error(%v)", err)
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func checkSignUp(oldAc, newAc *model.CActivity) bool {
|
|
if oldAc.SignedStart != newAc.SignedStart ||
|
|
oldAc.SignedEnd != newAc.SignedEnd ||
|
|
oldAc.SignUp != newAc.SignUp ||
|
|
oldAc.SignUpStart != newAc.SignUpStart {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func checkWin(oldAc, newAc *model.CActivity) bool {
|
|
if oldAc.Object != newAc.Object ||
|
|
oldAc.UploadStart != newAc.UploadStart ||
|
|
oldAc.UploadEnd != newAc.UploadEnd ||
|
|
oldAc.WinType != newAc.WinType ||
|
|
oldAc.RequireItems != newAc.RequireItems ||
|
|
oldAc.RequireValue != newAc.RequireValue ||
|
|
oldAc.StatisticsStart != newAc.StatisticsStart {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func checkBonus(oldAc, newAc *model.CActivity) bool {
|
|
if oldAc.BonusType != newAc.BonusType ||
|
|
oldAc.BonusTime != newAc.BonusTime {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func checkProgress(oldAc, newAc *model.CActivity) bool {
|
|
if oldAc.ProgressFrequency != newAc.ProgressFrequency ||
|
|
oldAc.UpdatePage != newAc.UpdatePage ||
|
|
oldAc.ProgressStart != newAc.ProgressStart ||
|
|
oldAc.ProgressSync != newAc.ProgressSync {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func checkOpenBonus(oldAc, newAc *model.CActivity) bool {
|
|
if oldAc.BonusQuery != newAc.BonusQuery ||
|
|
oldAc.BonusQuerStart != newAc.BonusQuerStart {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
// UpdateActivity update creative activity
|
|
func (s *Service) UpdateActivity(c context.Context, newAc *model.CActivity) (err error) {
|
|
acs, _, err := s.ListActivity(c, newAc.Name, 0, 1, "")
|
|
if err != nil {
|
|
log.Error("s.ListActivity error(%v)", err)
|
|
return
|
|
}
|
|
if len(acs) == 0 {
|
|
err = fmt.Errorf("activity(%s) not exist", newAc.Name)
|
|
return
|
|
}
|
|
old := acs[0]
|
|
// 报名标准
|
|
signUpStr := "signed_start=VALUES(signed_start),signed_end=VALUES(signed_end),sign_up=VALUES(sign_up),sign_up_start=VALUES(sign_up_start)"
|
|
// 中奖标准
|
|
winStr := "object=VALUES(object),upload_start=VALUES(upload_start),upload_end=VALUES(upload_end),win_type=VALUES(win_type),require_items=VALUES(require_items),require_value=VALUES(require_value),statistics_start=VALUES(statistics_start),statistics_end=VALUES(statistics_end)"
|
|
// 奖金设置
|
|
bonusStr := "bonus_type=VALUES(bonus_type),bonus_time=VALUES(bonus_time)"
|
|
// 进展同步
|
|
progressStr := "progress_frequency=VALUES(progress_frequency),update_page=VALUES(update_page),progress_start=VALUES(progress_start),progress_end=VALUES(progress_end),progress_sync=VALUES(progress_sync)"
|
|
// 开奖查询
|
|
openBonusStr := "bonus_query=VALUES(bonus_query),bonus_query_start=VALUES(bonus_query_start),bonus_query_end=VALUES(bonus_query_end)"
|
|
// others
|
|
otherStr := "background=VALUES(background),win_desc=VALUES(win_desc),unwin_desc=VALUES(unwin_desc),details=VALUES(details)"
|
|
|
|
var (
|
|
update = ""
|
|
updateBonus = false
|
|
now = xtime.Time(time.Now().Unix())
|
|
)
|
|
switch {
|
|
case now < old.SignUpStart:
|
|
// 报名未时间开始
|
|
update = fmt.Sprintf("%s,%s,%s,%s,%s,%s,sign_up_end=VALUES(sign_up_end)", signUpStr, winStr, bonusStr, progressStr, openBonusStr, otherStr)
|
|
updateBonus = true
|
|
case now >= old.SignUpStart && now <= old.SignUpEnd && now < old.ProgressStart:
|
|
// 报名已开始未结束,进展同步未开始
|
|
if !checkSignUp(old, newAc) || !checkWin(old, newAc) || !checkBonus(old, newAc) {
|
|
err = fmt.Errorf("报名已开始,无法修改报名、中奖、奖金相关内容,请检查修改项")
|
|
return
|
|
}
|
|
update = fmt.Sprintf("sign_up_end=VALUES(sign_up_end),%s,%s,%s", progressStr, openBonusStr, otherStr)
|
|
case now > old.SignUpEnd && now >= old.ProgressStart && now <= old.ProgressEnd:
|
|
// 报名已结束,进展同步开始未结束
|
|
if !checkSignUp(old, newAc) || !checkWin(old, newAc) || !checkBonus(old, newAc) || !checkProgress(old, newAc) {
|
|
err = fmt.Errorf("报名已结束,进展同步开始未结束,无法修改报名、中奖、奖金、进展相关内容,请检查修改项")
|
|
return
|
|
}
|
|
update = fmt.Sprintf("progress_end=VALUES(progress_end),%s,%s", openBonusStr, otherStr)
|
|
case now > old.ProgressEnd && now < old.BonusQueryEnd:
|
|
// 进展同步已结束,开奖查询未结束
|
|
if !checkSignUp(old, newAc) || !checkWin(old, newAc) || !checkBonus(old, newAc) || !checkProgress(old, newAc) || !checkOpenBonus(old, newAc) || old.ProgressEnd != newAc.ProgressEnd {
|
|
err = fmt.Errorf("进展同步已结束,开奖查询未结束,无法修改报名、中奖、奖金、进展、开奖相关内容,请检查修改项")
|
|
return
|
|
}
|
|
update = fmt.Sprintf("bonus_query_end=VALUES(bonus_query_end),%s", otherStr)
|
|
default:
|
|
err = fmt.Errorf("不符合任何修改时间段,没有任何修改")
|
|
return
|
|
}
|
|
update = fmt.Sprintf("ON DUPLICATE KEY UPDATE %s", update)
|
|
err = s.insertActivity(c, newAc, update, updateBonus)
|
|
return
|
|
}
|
|
|
|
func (s *Service) getActivityBonus(c context.Context, ids []int64) (bm map[int64][]int64, err error) {
|
|
bm = make(map[int64][]int64)
|
|
bonus, err := s.dao.GetActivityBonus(c, ids)
|
|
if err != nil {
|
|
return
|
|
}
|
|
sort.Slice(bonus, func(i, j int) bool {
|
|
return bonus[i].Rank < bonus[j].Rank
|
|
})
|
|
for i := 0; i < len(bonus); i++ {
|
|
id := bonus[i].ID
|
|
if _, ok := bm[id]; !ok {
|
|
bm[id] = make([]int64, 0)
|
|
}
|
|
bm[id] = append(bm[id], bonus[i].Money)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) insertActivity(c context.Context, ac *model.CActivity, updateVal string, updateBonus bool) (err error) {
|
|
tx, err := s.dao.BeginTran(c)
|
|
if err != nil {
|
|
log.Error("s.dao.BeginTran error(%v)", err)
|
|
return
|
|
}
|
|
// insert activity
|
|
if _, err = s.dao.TxInsertActivity(tx, ac, updateVal); err != nil {
|
|
log.Error("s.dao.TxInsertActivity error(%v)", err)
|
|
return
|
|
}
|
|
id, err := s.dao.TxGetActivityByName(tx, ac.Name)
|
|
if err != nil {
|
|
log.Error("s.dao.GetActivityByName error(%v)", err)
|
|
return
|
|
}
|
|
|
|
// is update bonus
|
|
if updateBonus && len(ac.BonusMoney) > 0 {
|
|
bonus := make([]*model.BonusRank, 0)
|
|
if ac.WinType == 1 {
|
|
bonus = append(bonus, &model.BonusRank{ID: id, Rank: 0, Money: ac.BonusMoney[0]})
|
|
} else if ac.WinType == 2 {
|
|
for i := 0; i < len(ac.BonusMoney); i++ {
|
|
bonus = append(bonus, &model.BonusRank{ID: id, Rank: i + 1, Money: ac.BonusMoney[i]})
|
|
}
|
|
}
|
|
// insert bonus money
|
|
if err = s.txInsertActivityBonus(tx, bonus); err != nil {
|
|
log.Error("s.TxInsertBonusRank error(%v)", err)
|
|
return
|
|
}
|
|
}
|
|
if err = tx.Commit(); err != nil {
|
|
log.Error("tx.Commit error")
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) txInsertActivityBonus(tx *sql.Tx, bonus []*model.BonusRank) (err error) {
|
|
var buf bytes.Buffer
|
|
for _, row := range bonus {
|
|
buf.WriteString("(")
|
|
buf.WriteString(strconv.FormatInt(row.ID, 10))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.Itoa(row.Rank))
|
|
buf.WriteByte(',')
|
|
buf.WriteString(strconv.FormatInt(row.Money, 10))
|
|
buf.WriteString(")")
|
|
buf.WriteByte(',')
|
|
}
|
|
if buf.Len() > 0 {
|
|
buf.Truncate(buf.Len() - 1)
|
|
}
|
|
vals := buf.String()
|
|
buf.Reset()
|
|
_, err = s.dao.TxInsertActivityBonusBatch(tx, vals)
|
|
return
|
|
}
|
|
|
|
// ListActivitySignUp list activity who sign up
|
|
func (s *Service) ListActivitySignUp(c context.Context, activityID int64, from, limit int) (ups []*model.UpActivity, total int, err error) {
|
|
total, err = s.dao.UpActivityStateCount(c, activityID, []int64{1, 2, 3})
|
|
if err != nil {
|
|
log.Error("s.dao.UpActivityStateCount error(%v)", err)
|
|
return
|
|
}
|
|
ups, err = s.dao.ListUpActivity(c, activityID, from, limit)
|
|
if err != nil {
|
|
log.Error("s.dao.ListUpActivity error(%v)", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
// ListActivityWinners list activity winners
|
|
func (s *Service) ListActivityWinners(c context.Context, activityID, mid int64, from, limit int) (ups []*model.UpActivity, total int, err error) {
|
|
total, err = s.dao.UpActivityStateCount(c, activityID, []int64{2, 3})
|
|
if err != nil {
|
|
log.Error("s.dao.UpActivityStateCount error(%v)", err)
|
|
return
|
|
}
|
|
ups, err = s.dao.ListUpActivitySuccess(c, activityID, mid, from, limit)
|
|
if err != nil {
|
|
log.Error("s.dao.ListUpActivity error(%v)", err)
|
|
return
|
|
}
|
|
if mid != 0 {
|
|
total = len(ups)
|
|
}
|
|
return
|
|
}
|
|
|
|
// ActivityAward activity award
|
|
func (s *Service) ActivityAward(c context.Context, activityID int64, activityName string, date, statisticsEnd xtime.Time, creator string) (err error) {
|
|
if xtime.Time(time.Now().Unix()) <= statisticsEnd {
|
|
err = fmt.Errorf("统计阶段未结束,不能发奖")
|
|
return
|
|
}
|
|
ups, err := s.listUpActivity(c, activityID)
|
|
if err != nil {
|
|
log.Error("s.listUpActivity error(%v)", err)
|
|
return
|
|
}
|
|
if len(ups) == 0 {
|
|
return
|
|
}
|
|
rankMID := make(map[int][]int64)
|
|
rankMoney := make(map[int]int64)
|
|
for _, up := range ups {
|
|
if up.State != 2 {
|
|
continue
|
|
}
|
|
rank := up.Rank
|
|
rankMoney[rank] = up.Bonus
|
|
if _, ok := rankMID[rank]; !ok {
|
|
rankMID[rank] = make([]int64, 0)
|
|
}
|
|
rankMID[rank] = append(rankMID[rank], up.MID)
|
|
}
|
|
|
|
// insert to tag
|
|
tx, err := s.dao.BeginTran(c)
|
|
if err != nil {
|
|
log.Error("s.dao.BeginTran error(%v)", err)
|
|
return
|
|
}
|
|
for rank, money := range rankMoney {
|
|
mids, ok := rankMID[rank]
|
|
if !ok || len(mids) == 0 {
|
|
continue
|
|
}
|
|
tagName := fmt.Sprintf("act-%s-%d", activityName, rank)
|
|
err = s.addActivityUpTag(tx, money, creator, tagName, mids, date)
|
|
if err != nil {
|
|
log.Error("s.addActivityUpTag error(%v)", err)
|
|
return
|
|
}
|
|
// update mids state
|
|
if _, err = s.dao.TxUpdateUpActivityState(tx, activityID, mids, 2, 3); err != nil {
|
|
tx.Rollback()
|
|
log.Error("s.dao.TxUpdateUpActivityState error(%v)", err)
|
|
return
|
|
}
|
|
}
|
|
if err = tx.Commit(); err != nil {
|
|
log.Error("tx.Commit error(%v)", err)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) addActivityUpTag(tx *sql.Tx, money int64, creator, tagName string, mids []int64, date xtime.Time) (err error) {
|
|
tag := &model.TagInfo{
|
|
Tag: tagName,
|
|
Creator: creator,
|
|
Dimension: 1,
|
|
StartTime: date,
|
|
EndTime: date,
|
|
AdjustType: 1,
|
|
Ratio: int(money),
|
|
UploadStartTime: date,
|
|
UploadEndTime: date,
|
|
}
|
|
if _, err = s.dao.TxInsertTag(tx, tag); err != nil {
|
|
tx.Rollback()
|
|
log.Error("s.dao.TxInsertTag error(%v)", err)
|
|
return
|
|
}
|
|
tagID, err := s.dao.TxGetTagInfoByName(tx, tagName, 1, 0, 0)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
log.Error("s.dao.TxGetTagInfoByName error(%v)", err)
|
|
return
|
|
}
|
|
for _, mid := range mids {
|
|
_, err = s.dao.TxInsertTagUpInfo(tx, tagID, mid, 0)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
log.Error("s.dao.TxInsertTagUpInfo error(%v)", err)
|
|
return
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (s *Service) listUpActivity(c context.Context, activityID int64) (ups []*model.UpActivity, err error) {
|
|
from, limit := 0, 2000
|
|
ups = make([]*model.UpActivity, 0)
|
|
for {
|
|
var up []*model.UpActivity
|
|
up, err = s.dao.ListUpActivity(c, activityID, from, limit)
|
|
if err != nil {
|
|
return
|
|
}
|
|
ups = append(ups, up...)
|
|
if len(up) < limit {
|
|
break
|
|
}
|
|
from += limit
|
|
}
|
|
return
|
|
}
|