123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 |
- 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
- }
|