offlineactivity.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. package dao
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/jinzhu/gorm"
  6. "go-common/app/admin/main/growup/dao/shell"
  7. "go-common/app/admin/main/growup/model/offlineactivity"
  8. "go-common/app/admin/main/up/util"
  9. "go-common/library/log"
  10. "strconv"
  11. "strings"
  12. )
  13. func generateDelimiter(delimiter string) func(r rune) bool {
  14. return func(r rune) bool {
  15. for _, v := range delimiter {
  16. if v == r {
  17. return true
  18. }
  19. }
  20. return false
  21. }
  22. }
  23. const (
  24. trimSet = "\r\n "
  25. )
  26. func strlistToInt64List(list []string, trimSet string) (result []int64) {
  27. for _, v := range list {
  28. mid, e := strconv.ParseInt(strings.Trim(v, trimSet), 10, 64)
  29. if e != nil {
  30. continue
  31. }
  32. result = append(result, mid)
  33. }
  34. return
  35. }
  36. func trimString(strlist []string, trimset string) (result []string) {
  37. for _, v := range strlist {
  38. var trimed = strings.Trim(v, trimSet)
  39. if trimed == "" {
  40. continue
  41. }
  42. result = append(result, trimed)
  43. }
  44. return
  45. }
  46. //ParseMidsFromString parse []int64 from string
  47. func ParseMidsFromString(str string) (result []int64) {
  48. var midstrlist = trimString(strings.FieldsFunc(str, generateDelimiter(",\r\n")), trimSet)
  49. result = util.Unique(strlistToInt64List(midstrlist, trimSet))
  50. return
  51. }
  52. //OfflineActivityAddActivity add acitvity
  53. func (d *Dao) OfflineActivityAddActivity(ctx context.Context, arg *offlineactivity.AddActivityArg) (err error) {
  54. var activityInfo = offlineactivity.OfflineActivityInfo{
  55. Title: arg.Title,
  56. Link: arg.Link,
  57. BonusType: arg.BonusType,
  58. Memo: arg.Memo,
  59. State: int8(offlineactivity.ActivityStateInit),
  60. Creator: arg.Creator,
  61. }
  62. var bonusList = arg.BonusList
  63. var hasBonus = false
  64. for _, bonus := range bonusList {
  65. if bonus.TotalMoney <= 0 {
  66. err = fmt.Errorf("bonus money < 0, money=%f", bonus.TotalMoney)
  67. log.Error(err.Error())
  68. return
  69. }
  70. bonus.MidList = ParseMidsFromString(bonus.Mids)
  71. bonus.MemberCount = int64(len(bonus.MidList))
  72. if bonus.MemberCount == 0 {
  73. log.Warn("no mid for this bonus, bonus:money=%.2f", bonus.TotalMoney)
  74. continue
  75. }
  76. hasBonus = true
  77. log.Info("bonus info:money=%.2f, membercount=%d", bonus.TotalMoney/1000, bonus.MemberCount)
  78. }
  79. // 如果一个bonus都没有,则什么也不做
  80. if !hasBonus {
  81. log.Error("no bonus")
  82. err = fmt.Errorf("no bonus info")
  83. return
  84. }
  85. if err = d.db.Create(&activityInfo).Error; err != nil {
  86. log.Error("err insert offline activity, err=%s", err)
  87. return
  88. }
  89. var tx = d.db.Begin()
  90. defer func() {
  91. if r := recover(); r != nil || err != nil {
  92. tx.Rollback()
  93. activityInfo.State = int8(offlineactivity.ActivityStateCreateFail)
  94. if err = d.db.Select("state").Save(&activityInfo).Error; err != nil {
  95. log.Error("err update offline activity, err=%s", err)
  96. return
  97. }
  98. }
  99. }()
  100. // create
  101. for _, bonus := range bonusList {
  102. if bonus.MemberCount <= 0 {
  103. continue
  104. }
  105. // 插入OfflineActivityBonus
  106. //if activityInfo.BonusType == offlineactivity.BonusTypeMoney {
  107. bonusMoney := offlineactivity.GetMoneyForDb(bonus.TotalMoney)
  108. //}
  109. var bonusInfo = offlineactivity.OfflineActivityBonus{
  110. TotalMoney: bonusMoney,
  111. MemberCount: uint32(bonus.MemberCount),
  112. State: int8(offlineactivity.BonusStateInit),
  113. ActivityID: activityInfo.ID,
  114. }
  115. if err = tx.Create(&bonusInfo).Error; err != nil {
  116. log.Error("err insert offline activity bonus, err=%s", err)
  117. return
  118. }
  119. // 插入OfflineActivityResult
  120. var insertSchema []string
  121. var vals []interface{}
  122. var dbmoney = bonusInfo.TotalMoney / int64(bonusInfo.MemberCount)
  123. for _, mid := range bonus.MidList {
  124. insertSchema = append(insertSchema, "(?,?,?,?,?)")
  125. vals = append(vals, activityInfo.ID, bonusInfo.ID, activityInfo.BonusType, mid, dbmoney)
  126. }
  127. var insertPre = "insert into offline_activity_result (activity_id, bonus_id, bonus_type, mid, bonus_money) values "
  128. var insertSQL = insertPre + strings.Join(insertSchema, ",")
  129. if err = tx.Table(offlineactivity.TableOfflineActivityResult).Exec(insertSQL, vals...).Error; err != nil {
  130. log.Error("err insert offline activity result, err=%s", err)
  131. return
  132. }
  133. }
  134. activityInfo.State = int8(offlineactivity.ActivityStateSending)
  135. if arg.BonusType == int8(offlineactivity.BonusTypeThing) {
  136. activityInfo.State = int8(offlineactivity.ActivityStateSucess)
  137. }
  138. if err = tx.Select("state").Save(&activityInfo).Error; err != nil {
  139. log.Error("err update offline activity, err=%s", err)
  140. return
  141. }
  142. return tx.Commit().Error
  143. }
  144. //ShellCallbackUpdate shell callback
  145. func (d *Dao) ShellCallbackUpdate(ctx context.Context, result *shell.OrderCallbackJSON, msgid string) (orderInfo offlineactivity.OfflineActivityShellOrder, err error) {
  146. // 找到order info, 写入结果
  147. var stateResult = offlineactivity.ActivityStateWaitResult
  148. if result.IsSuccess() {
  149. stateResult = offlineactivity.ActivityStateSucess
  150. } else if result.IsFail() {
  151. stateResult = offlineactivity.ActivityStateFail
  152. }
  153. if err = d.db.Where("order_id=?", result.ThirdOrderNo).Find(&orderInfo).Error; err != nil {
  154. log.Error("order id=%s, find order id fail, err=%s", result.ThirdOrderNo, err)
  155. return
  156. }
  157. var tx = d.db.Begin()
  158. defer func() {
  159. if r := recover(); r != nil || err != nil {
  160. tx.Rollback()
  161. }
  162. }()
  163. if err = tx.Table(offlineactivity.TableOfflineActivityShellOrder).
  164. Where("id=?", orderInfo.ID).
  165. Update("order_status", result.Status).
  166. Error; err != nil {
  167. log.Error("order id=%s, update order fail, err=%s", result.ThirdOrderNo, err)
  168. return
  169. }
  170. if err = tx.Table(offlineactivity.TableOfflineActivityResult).
  171. Where("id=?", orderInfo.ResultID).
  172. Update("state", stateResult).
  173. Error; err != nil {
  174. log.Error("order id=%s, update result fail, err=%s", result.ThirdOrderNo, err)
  175. return
  176. }
  177. log.Info("order id=%s, shell callback, success, mid=%s, status=%s", result.ThirdOrderNo, result.Mid, result.Status)
  178. err = tx.Commit().Error
  179. return
  180. }
  181. //OfflineActivityGetUpBonusResult Up主所有Activity一起统计
  182. func (d *Dao) OfflineActivityGetUpBonusResult(ctx context.Context, needCount bool, limit, offset int, query string, args ...interface{}) (upResult []*offlineactivity.OfflineActivityResult, totalCount int, err error) {
  183. // 查询所有的 result for mid
  184. // 区分已结算、未结算
  185. // 已结算= 成功, 未结算= 初始、发送、等待
  186. if needCount {
  187. if err = d.db.Table(offlineactivity.TableOfflineActivityResult).Where(query, args...).Count(&totalCount).Error; err != nil {
  188. log.Error("fail to get from db, err=%s", err)
  189. return
  190. }
  191. }
  192. if err = d.db.Where(query, args...).Limit(limit).Offset(offset).Find(&upResult).Error; err != nil {
  193. log.Error("fail to get from db, err=%s", err)
  194. return
  195. }
  196. return
  197. }
  198. //OfflineActivityGetUpBonusResultSelect select by selection
  199. func (d *Dao) OfflineActivityGetUpBonusResultSelect(ctx context.Context, selectQuery string, query string, args ...interface{}) (upResult []*offlineactivity.OfflineActivityResult, err error) {
  200. if err = d.db.Where(query, args...).Select(selectQuery).Find(&upResult).Error; err != nil {
  201. log.Error("fail to get from db, err=%s", err)
  202. return
  203. }
  204. return
  205. }
  206. //OfflineActivityGetUpBonusByActivityResult 根据Activity来分别统计
  207. func (d *Dao) OfflineActivityGetUpBonusByActivityResult(ctx context.Context, limit, offset int, mid int64) (upResult []*offlineactivity.OfflineActivityResult, totalCount int, err error) {
  208. // 查询所有的 result for mid
  209. // 区分已结算、未结算
  210. // 已结算= 成功, 未结算= 初始、发送、等待
  211. var actividyIds []struct {
  212. ActivityID int64 `gorm:"column:activity_id"`
  213. }
  214. if err = d.db.Table(offlineactivity.TableOfflineActivityResult).Select("count(distinct(activity_id))").Where("mid=?", mid).Count(&totalCount).Error; err != nil {
  215. log.Error("fail to get from db, err=%s", err)
  216. return
  217. }
  218. if err = d.db.Table(offlineactivity.TableOfflineActivityResult).Select("distinct(activity_id)").Where("mid=?", mid).Offset(offset).Limit(limit).Find(&actividyIds).Error; err != nil {
  219. log.Error("fail to get from db, err=%s", err)
  220. return
  221. }
  222. //totalCount = len(actividyIds)
  223. var ids []int64
  224. for i := 0; i < len(actividyIds); i++ {
  225. ids = append(ids, actividyIds[i].ActivityID)
  226. }
  227. if err = d.db.Where("mid=? and activity_id in(?)", mid, ids).Find(&upResult).Error; err != nil {
  228. log.Error("fail to get from db, err=%s", err)
  229. return
  230. }
  231. return
  232. }
  233. //OfflineActivityGetDB get gorm db
  234. func (d *Dao) OfflineActivityGetDB() *gorm.DB {
  235. return d.db
  236. }
  237. //UpdateActivityState 更新Activity的状态,根据每一个付款记录的状态
  238. func (d *Dao) UpdateActivityState(ctx context.Context, activityID int64) (affectedRow int64, err error) {
  239. // 找到所有result中,state最小的一个
  240. // 更新到activity的状态
  241. var record offlineactivity.OfflineActivityResult
  242. if err = d.db.Model(&record).Select("min(state) as state").Where("activity_id=?", activityID).Find(&record).Error; err != nil {
  243. log.Error("fail to get from db, err=%s", err)
  244. return
  245. }
  246. var db = d.db.Table(offlineactivity.TableOfflineActivityInfo).
  247. Where("id=? and state<10 and state<?", activityID, record.State).
  248. Update("state", record.State)
  249. if err = db.Error; err != nil {
  250. log.Error("fail to get from db, err=%s", err)
  251. return
  252. }
  253. affectedRow = db.RowsAffected
  254. if affectedRow > 0 {
  255. log.Info("update activity state, id=%d, newstate=%d", activityID, record.State)
  256. } else {
  257. log.Info("no need to update activity, id=%d, newstate=%d", activityID, record.State)
  258. }
  259. return
  260. }