ordermonitor.go 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. package task
  2. import (
  3. "app.yhyue.com/moapp/jybase/common"
  4. "app.yhyue.com/moapp/jybase/date"
  5. "app.yhyue.com/moapp/jybase/go-logger/logger"
  6. "app.yhyue.com/moapp/message/config"
  7. "app.yhyue.com/moapp/message/db"
  8. "app.yhyue.com/moapp/message/handler/activity"
  9. "context"
  10. "encoding/json"
  11. "fmt"
  12. "github.com/gogf/gf/v2/os/gcfg"
  13. "github.com/gogf/gf/v2/os/gcron"
  14. "github.com/gogf/gf/v2/os/gctx"
  15. "github.com/gogf/gf/v2/os/gtime"
  16. "strings"
  17. "time"
  18. )
  19. const (
  20. TableWinnerInfo2210 = "winner_info_22_10"
  21. Mold1 = "1" // 中奖类型 1:小米智能音响
  22. Mold2 = "2" // 中奖类型 2:ipad
  23. ActivityMode1 = 1 // 双十一
  24. ActivityMode2 = 2 // 双十二
  25. )
  26. var (
  27. flag = false // 是否已经查询到
  28. monitorConfig config.OrderMonitorConfig
  29. ruleWinNumFlag = []map[int]struct{}{}
  30. )
  31. func init() {
  32. // 获取配置信息
  33. monitorConfig = config.OrderMonitorConfig{
  34. DateSpecial: date.FormatDate(&gtime.NewFromStrLayout(gcfg.Instance().MustGet(gctx.New(), "orderMonitor.dateSpecial").String(), "2006-01-02T15:04:05Z").Time, date.Date_Short_Layout),
  35. OpenCron: gcfg.Instance().MustGet(gctx.New(), "orderMonitor.openCron").String(),
  36. SelectCron: gcfg.Instance().MustGet(gctx.New(), "orderMonitor.selectCron").String(),
  37. WinNumberDaily: gcfg.Instance().MustGet(gctx.New(), "orderMonitor.winNumberDaily").Int(),
  38. WinNumbersSpecial: gcfg.Instance().MustGet(gctx.New(), "orderMonitor.winNumbersSpecial").Int(),
  39. Switch: gcfg.Instance().MustGet(gctx.New(), "orderMonitor.switch").Bool(),
  40. ActivityMode: gcfg.Instance().MustGet(gctx.New(), "orderMonitor.activityMode").Int(),
  41. }
  42. rules, _ := gcfg.Instance().MustGet(gctx.New(), "orderMonitor.rules").MarshalJSON()
  43. err := json.Unmarshal(rules, &monitorConfig.Rules)
  44. if err != nil {
  45. panic("加载活动规则配置失败")
  46. }
  47. }
  48. // SelectOrderTask 订单监控
  49. func SelectOrderTask() {
  50. // 活动已结束 不再启动定时任务
  51. if time.Now().After(activity.MembershipDay.Ed) {
  52. return
  53. }
  54. var (
  55. err error
  56. ctx = gctx.New()
  57. )
  58. // 订单查询任务
  59. switch monitorConfig.ActivityMode {
  60. case ActivityMode1: // 双十一活动的模式 每天的第多少名
  61. _, err = gcron.Add(ctx, monitorConfig.SelectCron, monitor, "selectJob")
  62. case ActivityMode2: // 活动期间的第多少名
  63. // 初始化
  64. for i := 0; i < len(monitorConfig.Rules); i++ {
  65. rule := monitorConfig.Rules[i]
  66. tmp := map[int]struct{}{}
  67. for j := 0; j < len(rule.WinNum); j++ {
  68. tmp[rule.WinNum[j]] = struct{}{}
  69. }
  70. ruleWinNumFlag = append(ruleWinNumFlag, tmp)
  71. }
  72. _, err = gcron.Add(ctx, monitorConfig.SelectCron, monitorMode2, "selectJob")
  73. }
  74. if err != nil {
  75. logger.Error("定时任务selectJob添加失败", err)
  76. }
  77. if time.Now().Before(activity.MembershipDay.T2) { // 活动未开始
  78. gcron.Stop("selectJob") // 停掉订单查询任务 等后边的定时任务开启
  79. logger.Info("selectJob stop")
  80. }
  81. // 开启定时任务
  82. _, err = gcron.Add(ctx, monitorConfig.OpenCron, func(ctx context.Context) {
  83. now := time.Now()
  84. if now.After(activity.MembershipDay.Ed) { // 活动已结束 移除掉任务
  85. logger.Info("活动结束,移除任务")
  86. gcron.Remove("openCronJob")
  87. gcron.Remove("selectJob")
  88. return
  89. }
  90. // 活动时间范围内 开启订单查询的定时任务
  91. _, inTime, _ := activity.MembershipDay.InActivity()
  92. if inTime {
  93. if gcron.Search("selectJob").Status() != gcron.StatusRunning {
  94. flag = false // 重置
  95. gcron.Start("selectJob")
  96. logger.Info("开启 selectJob 任务")
  97. }
  98. }
  99. }, "openCronJob")
  100. if err != nil {
  101. logger.Error("定时任务openCronJob失败", err)
  102. }
  103. logger.Info("openCronJob 启动成功")
  104. }
  105. // 订单监控 双十一 查询活动期间的每天的第多少名
  106. func monitor(ctx context.Context) {
  107. logger.Info("开始本轮订单查询")
  108. _, inTime, _ := activity.MembershipDay.InActivity()
  109. if inTime {
  110. // 如果需要查第111个 日期范围内 特殊日期
  111. if date.NowFormat(date.Date_Short_Layout) == monitorConfig.DateSpecial {
  112. logger.Info(fmt.Sprintf("开始查询第%v个人员", monitorConfig.WinNumbersSpecial))
  113. rs111 := selectOrder(monitorConfig.WinNumbersSpecial)
  114. if rs111 != nil {
  115. logger.Info(fmt.Sprintf("查询到第%v个人员", monitorConfig.WinNumbersSpecial))
  116. saveData := map[string]interface{}{
  117. "phone": rs111["user_phone"],
  118. "userid": rs111["user_id"],
  119. "winnerdate": rs111["pay_time"],
  120. "mold": Mold2,
  121. "createdate": date.NowFormat(date.Date_Full_Layout),
  122. }
  123. if existWinnerInfo() {
  124. logger.Info("当日已存在中奖信息")
  125. flag = true
  126. } else {
  127. if saveWinnerInfo(saveData) {
  128. flag = true
  129. logger.Info("中奖信息保存成功:", saveData)
  130. } else {
  131. logger.Error("中奖信息保存失败:", saveData)
  132. }
  133. }
  134. }
  135. } else {
  136. rs := selectOrder(monitorConfig.WinNumberDaily)
  137. if rs != nil { // 查到了
  138. logger.Info(fmt.Sprintf("查询到第%d个人员", monitorConfig.WinNumberDaily))
  139. data := map[string]interface{}{
  140. "phone": rs["user_phone"],
  141. "userid": rs["user_id"],
  142. "winnerdate": rs["pay_time"],
  143. "mold": Mold1,
  144. "createdate": date.NowFormat(date.Date_Full_Layout),
  145. }
  146. if existWinnerInfo() {
  147. logger.Info("当日已存在中奖信息")
  148. flag = true
  149. } else {
  150. if saveWinnerInfo(data) {
  151. flag = true
  152. logger.Info("中奖信息保存成功:", data)
  153. } else {
  154. logger.Error("中奖信息保存失败:", data)
  155. }
  156. }
  157. }
  158. }
  159. if flag {
  160. logger.Info("今日已查询到 暂停任务")
  161. gcron.Stop("selectJob")
  162. logger.Info("selectJob stop")
  163. }
  164. }
  165. }
  166. // 双十二活动 查询活动期间的第多少名
  167. func monitorMode2(ctx context.Context) {
  168. logger.Info("开始本轮订单查询")
  169. _, inTime, _ := activity.MembershipDay.InActivity()
  170. if inTime {
  171. needSelect := false
  172. // 遍历活动抽奖规则
  173. for i := 0; i < len(monitorConfig.Rules); i++ {
  174. rules := monitorConfig.Rules[i]
  175. if len(ruleWinNumFlag[i]) == 0 {
  176. continue
  177. }
  178. // 遍历中奖顺序
  179. for _, num := range rules.WinNum {
  180. if _, ok := ruleWinNumFlag[i][num]; !ok {
  181. continue
  182. }
  183. rs := selectOrder2(num, rules.Products, rules.PriceLimit, rules.PriceStart, rules.PriceEnd, date.FormatDate(&activity.MembershipDay.T2, date.Date_Short_Layout), date.FormatDate(&activity.MembershipDay.Ed, date.Date_Short_Layout))
  184. if len(rs) == 0 {
  185. logger.Info(num, "未查到")
  186. continue
  187. //break // 如果没有查询到 等待下一轮任务再查询
  188. }
  189. logger.Info(num, "查到")
  190. data := map[string]interface{}{
  191. "phone": rs["user_phone"],
  192. "userid": rs["user_id"],
  193. "winnerdate": rs["pay_time"],
  194. "mold": rules.Mold,
  195. "createdate": date.NowFormat(date.Date_Full_Layout),
  196. "ordercode": rs["order_code"],
  197. }
  198. if existOrderWinnerInfo(common.ObjToString(rs["order_code"])) {
  199. // 删除查找的key
  200. delete(ruleWinNumFlag[i], num)
  201. logger.Info("该订单中奖信息重复保存", data)
  202. } else {
  203. // 存库
  204. if saveWinnerInfo(data) {
  205. logger.Info("保存成功", data)
  206. // 删除查找的key
  207. delete(ruleWinNumFlag[i], num)
  208. } else {
  209. logger.Info("保存失败", data)
  210. }
  211. }
  212. }
  213. if len(ruleWinNumFlag[i]) > 0 {
  214. // 存在未查询到的
  215. logger.Info(ruleWinNumFlag[i])
  216. needSelect = true
  217. }
  218. }
  219. if !needSelect {
  220. // 不用再找了 结束任务
  221. gcron.Remove("selectJob")
  222. gcron.Remove("openCronJob")
  223. logger.Info("结束了")
  224. }
  225. }
  226. }
  227. // 查订单表
  228. func selectOrder(num int) map[string]interface{} {
  229. sql := `SELECT
  230. order_code,
  231. user_phone,
  232. user_id,
  233. pay_time
  234. FROM
  235. dataexport_order
  236. WHERE order_status = 1 and
  237. product_type IN (
  238. "VIP订阅",
  239. "大会员",
  240. "数据流量包"
  241. )
  242. AND is_backstage_order = 0
  243. AND TO_DAYS(pay_time) = to_days(now())
  244. ORDER BY
  245. pay_time
  246. LIMIT ?,1
  247. `
  248. rs := db.Mysql.SelectBySql(sql, num-1)
  249. if rs != nil && len(*rs) == 1 {
  250. return (*rs)[0]
  251. }
  252. logger.Info("未查到", rs)
  253. return nil
  254. }
  255. // 查询活动期间指定支付顺序的订单
  256. func selectOrder2(num int, productType []string, priceLimit bool, priceStart, priceEnd int, startTime, endTime string) map[string]interface{} {
  257. var products []string
  258. var values []interface{}
  259. productTypeStr := "" // 产品类型
  260. priceLimitStr := "" // 价格限制
  261. values = append(values, startTime, endTime)
  262. // 拼接产品类型
  263. if len(productType) > 0 {
  264. for i := 0; i < len(productType); i++ {
  265. products = append(products, "?")
  266. values = append(values, productType[i])
  267. }
  268. productTypeStr = fmt.Sprintf(" and product_type IN (%s) ", strings.Join(products, ","))
  269. }
  270. // 拼接价格限制
  271. if priceLimit {
  272. if priceStart != 0 {
  273. priceLimitStr = " and pay_money>=? "
  274. values = append(values, priceStart)
  275. }
  276. if priceEnd != 0 {
  277. priceLimitStr += " and pay_money<=? "
  278. values = append(values, priceEnd)
  279. }
  280. }
  281. values = append(values, num-1)
  282. sql := `SELECT
  283. order_code,
  284. user_phone,
  285. user_id,
  286. pay_time
  287. FROM
  288. dataexport_order
  289. WHERE order_status = 1 and create_time >=? and create_time<?` + productTypeStr +
  290. priceLimitStr + ` AND is_backstage_order = 0
  291. ORDER BY pay_time LIMIT ?,1`
  292. rs := db.Mysql.SelectBySql(sql, values...)
  293. if rs != nil && len(*rs) == 1 {
  294. return (*rs)[0]
  295. }
  296. logger.Info("未查到", rs)
  297. return nil
  298. }
  299. // 保存中奖人员信息
  300. func saveWinnerInfo(data map[string]interface{}) bool {
  301. logger.Info("save winner info ")
  302. return db.Mysql.Insert(TableWinnerInfo2210, data) > 0
  303. }
  304. // 当天是否已经保存过中奖信息
  305. func existWinnerInfo() bool {
  306. logger.Info("select winner info ")
  307. return db.Mysql.CountBySql("SELECT count(id) as count FROM jianyu.winner_info_22_10 where TO_DAYS(createdate) = TO_DAYS(NOW());") > 0
  308. }
  309. // 中奖订单号是否已经保存过
  310. func existOrderWinnerInfo(orderCode string) bool {
  311. logger.Info("select order winner info ")
  312. return db.Mysql.CountBySql("SELECT count(id) as count FROM jianyu.winner_info_22_10 where ordercode = ?", orderCode) > 0
  313. }