lotteryDrawTask.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. package activity
  2. import (
  3. "app.yhyue.com/moapp/jybase/common"
  4. "app.yhyue.com/moapp/jybase/date"
  5. "app.yhyue.com/moapp/jybase/encrypt"
  6. "app.yhyue.com/moapp/jybase/go-logger/logger"
  7. "app.yhyue.com/moapp/jybase/redis"
  8. "app.yhyue.com/moapp/message/db"
  9. "app.yhyue.com/moapp/message/model"
  10. "app.yhyue.com/moapp/message/util"
  11. "encoding/json"
  12. "fmt"
  13. "github.com/gogf/gf/v2/frame/g"
  14. "github.com/gogf/gf/v2/os/gctx"
  15. "regexp"
  16. "strconv"
  17. "time"
  18. )
  19. const (
  20. //表
  21. tableTaskInfo = "jyactivities.lottery_task_info"
  22. tableTaskUser = "jyactivities.lottery_task_user"
  23. tableActivityInfo = "jyactivities.activity_info"
  24. )
  25. // 任务信息
  26. type TaskInfo struct {
  27. Id int64 `json:"id"`
  28. Name string `json:"name"`
  29. ActiveId int64 `json:"active_id"` //活动id
  30. Qualification int `json:"qualification"` //获取抽奖资格次数;
  31. CycleNum int `json:"cycle_num"` //任务周期(每天/每周/每月/活动周期) 可执行任务次数:n次;-1:不限制
  32. CycleUnit int `json:"cycle_unit"` //默认0:当天;;1:当周;2:当月;3:活动周期
  33. ActivityStartTime string `json:"start_time"` //活动开始时间
  34. ActivityEndTime string `json:"end_time"` //活动结束时间
  35. ActivityName string `json:"activity_name"` //活动名称
  36. }
  37. // 信息主题
  38. type MsgBody struct {
  39. Phone string `json:"phone"`
  40. UserId string `json:"userId"`
  41. MgoUserId string `json:"mgoUserId"`
  42. PositionId int64 `json:"positionId"`
  43. ActiveId int64 `json:"activeId"`
  44. TaskInfoId int64 `json:"taskInfoId"`
  45. OrderCode string `json:"orderCode"`
  46. NickName string `json:"nickName"`
  47. State int `json:"state"` //购买超级订阅和大会员 0:购买;1:续费;2:升级
  48. }
  49. // LotteryDrawTask 抽奖任务
  50. func LotteryDrawTask(msg *model.Message) {
  51. var msgBody MsgBody
  52. if msg.E_body != nil {
  53. b, err := json.Marshal(msg.E_body)
  54. if err == nil {
  55. err = json.Unmarshal(b, &msgBody)
  56. }
  57. if err != nil {
  58. logger.Info(fmt.Sprintf("任务完成参数信息有误:%s,err:%s", msg.E_userId, err.Error()))
  59. return
  60. }
  61. }
  62. if msgBody.MgoUserId == "" {
  63. logger.Info(fmt.Sprintf("用户mgo user id 参数信息有误:%v ,userId:%s", msgBody, msg.E_userId))
  64. return
  65. }
  66. //判断用户是否存在
  67. data, ok := db.Mgo.FindById("user", msgBody.MgoUserId, `{"l_registedate":1,"s_phone":1,"s_m_phone":1}`)
  68. if data == nil || len(*data) == 0 || !ok {
  69. logger.Info(fmt.Sprintf("未找到用户:%s, 任务id:%d。", msg.E_userId, msgBody.TaskInfoId))
  70. return
  71. }
  72. //任务信息
  73. taskInfos := db.Mysql.SelectBySql(fmt.Sprintf("SELECT lti.*,ai.start_time,ai.end_time,ai.name AS activity_name FROM %s lti LEFT JOIN %s ai ON lti.active_id = ai.id WHERE lti.active_id = ? AND lti.id = ? AND ai.start_time < NOW() AND ai.end_time >= NOW() ORDER BY lti.create_date DESC", tableTaskInfo, tableActivityInfo), msgBody.ActiveId, msgBody.TaskInfoId)
  74. if taskInfos == nil || len(*taskInfos) == 0 {
  75. logger.Info(fmt.Sprintf("没有当前需要完成的任务信息:%v", msgBody))
  76. return
  77. }
  78. //任务信息
  79. var taskInfo TaskInfo
  80. b, err := json.Marshal((*taskInfos)[0])
  81. if err == nil {
  82. err = json.Unmarshal(b, &taskInfo)
  83. }
  84. if err != nil {
  85. logger.Info(fmt.Sprintf("任务信息异常:%v,err:%s", msgBody, err.Error()))
  86. return
  87. }
  88. var (
  89. now = time.Now()
  90. timeRange = util.TimeRange{}
  91. emdTime, _ = time.ParseInLocation(date.Date_Full_Layout, taskInfo.ActivityEndTime, time.Local)
  92. startTime, _ = time.ParseInLocation(date.Date_Full_Layout, taskInfo.ActivityStartTime, time.Local)
  93. )
  94. //判断任务有效期内,此次任务是否已完成
  95. switch taskInfo.CycleUnit {
  96. case 1: //当周
  97. timeRange = util.GetWeekRange(now)
  98. case 2: //当月
  99. timeRange = util.GetMonthRange(now)
  100. case 3: //活动周期
  101. timeRange = util.TimeRange{
  102. StartTime: startTime,
  103. EndTime: emdTime,
  104. StartUnix: startTime.Unix(),
  105. EndUnix: emdTime.Unix(),
  106. }
  107. default: //当天
  108. timeRange = util.GetDayRange(now)
  109. }
  110. //当前周期内 是否已完成任务
  111. if taskInfo.CycleNum > 0 {
  112. tasks := db.Mysql.SelectBySql(fmt.Sprintf(`SELECT ltu.create_date FROM %s ltu WHERE ltu.active_id = ? AND ltu.task_id = ? AND ltu.position_id = ? AND ltu.create_date < ? AND ltu.create_date > ? `, tableTaskUser), msgBody.ActiveId, taskInfo.Id, msgBody.PositionId, timeRange.EndTime.Format(date.Date_Full_Layout), timeRange.StartTime.Format(date.Date_Full_Layout))
  113. if tasks != nil && taskInfo.CycleNum <= len(*tasks) {
  114. createDate := common.InterfaceToStr((*tasks)[0]["create_date"])
  115. logger.Info(fmt.Sprintf("用户:%s ,此任务:%s ,在 %s 已完成", msgBody.Phone, taskInfo.Name, createDate))
  116. return
  117. }
  118. } else if msgBody.OrderCode != "" {
  119. //活动期间创建订单并且活动期间全部回款的才算
  120. orderInfo := db.Mysql.CountBySql(`SELECT COUNT(do.id) FROM jianyu.dataexport_order do WHERE do.order_code = ? AND do.create_time > ? AND ((is_backstage_order = 1 AND return_status = 1) OR (is_backstage_order != 1 AND order_status = 1))`, msgBody.OrderCode, taskInfo.ActivityStartTime)
  121. if orderInfo == 0 {
  122. logger.Info(fmt.Sprintf("用户:%s ,此订单:%s ,未在活动期间内创建", msgBody.Phone, msgBody.OrderCode))
  123. return
  124. }
  125. tasks := db.Mysql.SelectBySql(fmt.Sprintf(`SELECT ltu.create_date FROM %s ltu WHERE ltu.active_id = ? AND ltu.position_id = ? AND ltu.order_code = ?`, tableTaskUser), taskInfo.ActiveId, msgBody.PositionId, msgBody.OrderCode)
  126. //TODO 判重 担心订单有更新
  127. if tasks != nil && len(*tasks) > 0 {
  128. createDate := common.InterfaceToStr((*tasks)[0]["create_date"])
  129. logger.Info(fmt.Sprintf("用户:%s ,此订单:%s ,在 %s 已新增抽奖机会", msgBody.Phone, msgBody.OrderCode, createDate))
  130. return
  131. }
  132. }
  133. //二次验证
  134. switch taskInfo.Id {
  135. case 1: //签到赠送剑鱼币任务
  136. case 2: //设置关键词任务
  137. var hasKeys bool
  138. //查看当前用户是否有订阅词
  139. res := db.Compatible.Select(msgBody.UserId, `{"o_vipjy":1,"i_vip_status":1,"o_member_jy":1,"i_member_status":1,"o_jy":"1"}`)
  140. if res != nil && len(*res) > 0 {
  141. vipStatus := common.IntAll((*res)["i_vip_status"])
  142. memberStatus := common.IntAll((*res)["i_member_status"])
  143. if vipStatus > 0 || memberStatus > 0 {
  144. if vipStatus > 0 {
  145. obj, _ := (*res)["o_vipjy"].(map[string]interface{})
  146. if obj != nil {
  147. itmes, _ := obj["a_items"].([]interface{})
  148. for _, v := range itmes {
  149. item, _ := v.(map[string]interface{})
  150. keys, _ := item["a_key"].([]interface{})
  151. if len(keys) > 0 {
  152. hasKeys = true
  153. break
  154. }
  155. }
  156. }
  157. }
  158. if memberStatus > 0 && !hasKeys {
  159. obj, _ := (*res)["o_member_jy"].(map[string]interface{})
  160. if obj != nil {
  161. itmes, _ := obj["a_items"].([]interface{})
  162. for _, v := range itmes {
  163. item, _ := v.(map[string]interface{})
  164. keys, _ := item["a_key"].([]interface{})
  165. if len(keys) > 0 {
  166. hasKeys = true
  167. break
  168. }
  169. }
  170. }
  171. }
  172. } else {
  173. obj, _ := (*res)["o_jy"].(map[string]interface{})
  174. aKey, _ := obj["a_key"].([]interface{})
  175. if len(aKey) > 0 {
  176. hasKeys = true
  177. }
  178. }
  179. }
  180. //没有设置关键词
  181. if !hasKeys {
  182. logger.Info(fmt.Sprintf("当前用户:%s,手机号: %s 没有设置订阅词", msgBody.UserId, msgBody.Phone))
  183. return
  184. }
  185. case 3: //招标采购搜索任务
  186. case 4: //购买/续费/升级超级订阅会员
  187. cacheKey := fmt.Sprintf(model.PayCacheKey, msgBody.ActiveId, msgBody.UserId, "v", strconv.Itoa(msgBody.State))
  188. if cacheBool := redis.Put(PowerCacheDb, cacheKey, msgBody.Phone, int(emdTime.Unix()-time.Now().Unix())); !cacheBool {
  189. logger.Info(fmt.Sprintf("当前用户:%s,手机号: %s 超级订阅订单信息 %d redis存储失败,keys:%s", msgBody.UserId, msgBody.Phone, msgBody.State, cacheKey))
  190. }
  191. case 5: //购买/续费/升级大会员
  192. // TODO 完成任务 赠送两次 抽奖机会
  193. cacheKey := fmt.Sprintf(model.PayCacheKey, msgBody.ActiveId, msgBody.UserId, "m", strconv.Itoa(msgBody.State))
  194. if cacheBool := redis.Put(PowerCacheDb, cacheKey, msgBody.Phone, int(emdTime.Unix()-time.Now().Unix())); !cacheBool {
  195. logger.Info(fmt.Sprintf("当前用户:%s,手机号: %s 大会员订单信息 %d redis存储失败,keys:%s", msgBody.UserId, msgBody.Phone, msgBody.State, cacheKey))
  196. }
  197. case 6: //给朋友分享活动
  198. }
  199. insertMap := map[string]interface{}{
  200. "active_id": msgBody.ActiveId,
  201. "task_id": msgBody.TaskInfoId,
  202. "phone": msgBody.Phone,
  203. "user_id": msgBody.UserId,
  204. "position_id": msgBody.PositionId,
  205. "mgo_user_id": msgBody.MgoUserId,
  206. "order_code": msgBody.OrderCode,
  207. "state": 0,
  208. "end_date": timeRange.EndTime.Format(date.Date_Full_Layout),
  209. "update_date": time.Now().Format(date.Date_Full_Layout),
  210. "create_date": time.Now().Format(date.Date_Full_Layout),
  211. }
  212. var tf bool
  213. for i := 0; i < taskInfo.Qualification; i++ {
  214. if id := db.Mysql.Insert(tableTaskUser, insertMap); id < 0 {
  215. logger.Info(fmt.Sprintf("保存任务记录异常:%v", msgBody))
  216. // TODO 保存任务记录异常 告警
  217. if webhookURL := g.Cfg().MustGet(gctx.New(), "webhookURL").Strings(); len(webhookURL) > 0 {
  218. content := fmt.Sprintf(`保存任务记录异常:\n活动名称:%s \n手机号:%s \n职位id:%d \n任务id:%d \n任务名称:%s`,
  219. taskInfo.ActivityName, msgBody.Phone, msgBody.PositionId, msgBody.TaskInfoId, taskInfo.Name)
  220. util.SendMsgByWXURL(content, webhookURL)
  221. }
  222. } else {
  223. tf = true
  224. }
  225. }
  226. if tf {
  227. logger.Info(" sse 任务信息通知:", msg)
  228. var userName = msgBody.NickName
  229. if msgBody.Phone != "" {
  230. var PhoneReg = regexp.MustCompile(`^(100\d{8}|1[3-9]\d{9})$`)
  231. if PhoneReg.MatchString(msgBody.Phone) {
  232. phone := []rune(msgBody.Phone)
  233. userName = string(phone[0:3]) + "****" + string(phone[(len(phone)-4):])
  234. }
  235. }
  236. if sendData := util.GetSseRedisCache(msgBody.UserId); len(sendData) > 0 {
  237. for _, sv := range sendData {
  238. util.SendNotification(sv, model.SseMessage{
  239. //util.SendNotificationToAll(model.SseMessage{
  240. Name: taskInfo.Name,
  241. User: encrypt.SE.EncodeString(msgBody.UserId),
  242. State: model.TaskTarget,
  243. Time: time.Now().Format(date.Date_Full_Layout),
  244. Remark: fmt.Sprintf("%s 完成 %s 任务。", userName, taskInfo.Name),
  245. ActiveId: encrypt.SE.EncodeString(strconv.FormatInt(msgBody.ActiveId, 10)),
  246. })
  247. }
  248. }
  249. }
  250. }
  251. type lotteryBody struct {
  252. NickName string `json:"nick_name"`
  253. Phone string `json:"phone"`
  254. MgoUserId string `json:"mgo_user_id"`
  255. PositionId int64 `json:"position_id"`
  256. ActiveId int64 `json:"active_id"`
  257. ActiveName string `json:"active_name"`
  258. PrizeId int64 `json:"prize_id"`
  259. PrizeName string `json:"prize_name"`
  260. }
  261. // LotteryWinning 中奖信息
  262. func LotteryWinning(msg *model.Message) {
  263. //TODO sse 通知用户 中奖信息
  264. var lb lotteryBody
  265. if msg.E_body != nil {
  266. b, err := json.Marshal(msg.E_body)
  267. if err == nil {
  268. err = json.Unmarshal(b, &lb)
  269. }
  270. if err != nil {
  271. logger.Info(fmt.Sprintf("中奖参数信息有误:%s", msg.E_userId))
  272. return
  273. }
  274. }
  275. var userName = lb.NickName
  276. if lb.Phone != "" {
  277. var PhoneReg = regexp.MustCompile(`^(100\d{8}|1[3-9]\d{9})$`)
  278. if PhoneReg.MatchString(lb.Phone) {
  279. phone := []rune(lb.Phone)
  280. userName = string(phone[0:3]) + "****" + string(phone[(len(phone)-4):])
  281. }
  282. }
  283. logger.Info(" sse 中奖信息通知:", msg)
  284. util.SendNotificationToAll(model.SseMessage{
  285. Name: lb.PrizeName,
  286. User: userName,
  287. State: model.WinningTarget,
  288. Time: time.Now().Format(date.Date_Full_Layout),
  289. Remark: fmt.Sprintf("恭喜 %s 抽中 %s ", userName, lb.PrizeName),
  290. ActiveId: encrypt.SE.EncodeString(strconv.FormatInt(lb.ActiveId, 10)),
  291. })
  292. }