jobutil.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "strings"
  6. "time"
  7. "app.yhyue.com/moapp/jybase/common"
  8. "app.yhyue.com/moapp/jybase/date"
  9. "app.yhyue.com/moapp/jybase/mongodb"
  10. )
  11. // 未支付订单 30分钟一次
  12. func orders() {
  13. //一个小时未支付进入线索 A
  14. log.Println("未支付订单定时任务开始")
  15. lastOrderId := cfg.LastOrderId
  16. selectTimeStart := time.Unix(time.Now().Unix()-7200, 0).Format(date.Date_Full_Layout)
  17. selectTimeEnd := time.Unix(time.Now().Unix()-3600, 0).Format(date.Date_Full_Layout)
  18. sql := fmt.Sprintf(`select * from dataexport_order where create_time <= "%s" and create_time >= "%s" and id > %s`, selectTimeEnd, selectTimeStart, fmt.Sprint(lastOrderId))
  19. data := Mysql.SelectBySql(sql)
  20. if data != nil && *data != nil && len(*data) > 0 {
  21. for _, v := range *data {
  22. order_status := common.IntAll(v["order_status"])
  23. is_backstage_order := common.IntAll(v["is_backstage_order"])
  24. product_type_str1 := `"大会员","VIP订阅","数据流量包","历史数据"`
  25. product_type := common.ObjToString(v["product_type"])
  26. if order_status == 0 && is_backstage_order == 0 && strings.Contains(product_type_str1, product_type) {
  27. ok1, _ := FormatData(v, "orders")
  28. if !ok1 {
  29. common.WriteSysConfig(&cfg)
  30. break
  31. }
  32. }
  33. cfg.LastOrderId = common.IntAll(v["id"])
  34. }
  35. }
  36. common.WriteSysConfig(&cfg)
  37. log.Println("未支付订单定时任务结束")
  38. }
  39. func readClue() {
  40. log.Println("读表进线索定时任务开始")
  41. lastReadClueTime := cfg.LastReadClueTime
  42. sql := fmt.Sprintf(`select * from clue_info where updatetime > "%s" order by updatetime asc`, fmt.Sprint(lastReadClueTime))
  43. data := TiDb.SelectBySql(sql)
  44. if data != nil && *data != nil && len(*data) > 0 {
  45. for _, v := range *data {
  46. ok1, _ := FormatData(v, "readClue")
  47. if !ok1 {
  48. common.WriteSysConfig(&cfg)
  49. break
  50. }
  51. cfg.LastReadClueTime = common.ObjToString(v["updatetime"])
  52. }
  53. }
  54. common.WriteSysConfig(&cfg)
  55. log.Println("读表进线索定时任务结束")
  56. }
  57. // 新注册用户 5分钟一次
  58. func users() {
  59. //判断节假日
  60. runOk := getRunOk()
  61. if !runOk {
  62. log.Println("不是工作日,任务暂停")
  63. return
  64. }
  65. //新用户注册后5分钟内进入线索 C
  66. log.Println("新注册用户定时任务开始")
  67. selectTimeEnd := cfg.LastUserId
  68. sql := fmt.Sprintf(`select * from dwd_f_userbase_baseinfo where createtime > "%s" and source = "0101" and status != 2`, selectTimeEnd)
  69. data := TiDb.SelectBySql(sql)
  70. if data != nil && *data != nil && len(*data) > 0 {
  71. for k, v := range *data {
  72. createtime := common.ObjToString(v["createtime"])
  73. FormatData(v, "users")
  74. if k == len(*data)-1 {
  75. cfg.LastUserId = createtime
  76. }
  77. }
  78. }
  79. common.WriteSysConfig(&cfg)
  80. log.Println("新注册用户定时任务结束")
  81. }
  82. // 留资 5分钟一次
  83. func saleLeads() {
  84. //判断节假日
  85. runOk := getRunOk()
  86. if !runOk {
  87. log.Println("不是工作日,任务暂停")
  88. return
  89. }
  90. //留资后5分钟内进入线索
  91. //分为免费留资和付费留资 付费B 免费C
  92. log.Println("用户留资定时任务开始")
  93. session := Mgo.GetMgoConn()
  94. lastId := cfg.LastId
  95. defer func() {
  96. Mgo.DestoryMongoConn(session)
  97. }()
  98. query := map[string]interface{}{}
  99. if lastId != "" {
  100. query["_id"] = map[string]interface{}{"$gt": mongodb.StringTOBsonId(lastId)}
  101. }
  102. log.Println("query :", query)
  103. iter := session.DB(cfg.Mgo.DbName).C("saleLeads").Find(&query).Sort("_id").Iter()
  104. thisData := map[string]interface{}{}
  105. for {
  106. if !iter.Next(&thisData) {
  107. break
  108. }
  109. ok1, _ := FormatData(thisData, "saleLeads")
  110. if !ok1 {
  111. common.WriteSysConfig(&cfg)
  112. break
  113. }
  114. cfg.LastId = mongodb.BsonIdToSId(thisData["_id"])
  115. }
  116. common.WriteSysConfig(&cfg)
  117. log.Println("用户留资定时任务结束")
  118. }
  119. func userbase() {
  120. log.Println("userbase定时任务开始")
  121. selectTimeEnd := time.Unix(time.Now().Unix()-1800, 0).Format("2006-01-02 15:04:05")
  122. sql := fmt.Sprintf(`select * from dwd_f_userbase_baseinfo where updatetime > "%s" and source != "0105" and source != "0104" and source != "0103" and source != "0102"`, selectTimeEnd)
  123. data := TiDb.SelectBySql(sql)
  124. if data != nil && *data != nil && len(*data) > 0 {
  125. for _, v := range *data {
  126. phone := common.ObjToString(v["phone"])
  127. uId := common.ObjToString(v["uid"])
  128. userId := common.ObjToString(v["userid"])
  129. registedate := common.ObjToString(v["l_registedate"])
  130. name := common.ObjToString(v["name"])
  131. nowTime := time.Now().Format(date.Date_Full_Layout)
  132. source := common.ObjToString(v["source"])
  133. if phone != "" {
  134. contactsData := TiDb.SelectBySql("select * from dwd_f_userbase_contacts where phone = ? and is_delete = 1", phone)
  135. if contactsData == nil || len(*contactsData) == 0 {
  136. contactsData2 := TiDb.SelectBySql("select * from dwd_f_userbase_contacts where baseinfo_id = ? and is_delete = 1", uId)
  137. if contactsData2 != nil && len(*contactsData2) > 0 {
  138. log.Println("userbase uid不为空 新增通讯录", uId)
  139. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  140. "status": 1,
  141. "is_delete": 1,
  142. "createtime": nowTime,
  143. "updatetime": nowTime,
  144. "phone": phone,
  145. "baseinfo_id": uId,
  146. "SOURCE": source,
  147. })
  148. } else {
  149. registedates, _ := time.Parse(date.Date_Full_Layout, registedate)
  150. count := TiDb.CountBySql("select count(1) as count from dwd_f_crm_clue_info where uid = ?", uId)
  151. log.Println("userbase uid 线索数量 ", count)
  152. log.Println("userbase uid 注册时间 ", registedates)
  153. if time.Now().Unix()-registedates.Unix() > int64(cfg.RegTimes)*86400 {
  154. if count == 0 {
  155. // TiDb.Insert("dwd_f_crm_open_sea", map[string]interface{}{
  156. // "clue_id": clueId,
  157. // "comeintime": nowTime,
  158. // "comeinsource": 2,
  159. // })
  160. clueId := TiDb.Insert("dwd_f_crm_clue_info", map[string]interface{}{
  161. "userid": userId,
  162. "uid": uId,
  163. "is_assign": 0,
  164. "comeintime": nowTime,
  165. "createtime": nowTime,
  166. "updatetime": nowTime,
  167. "cluename": phone,
  168. "top_cluetype": "532",
  169. "sub_cluetype": "475",
  170. "trailstatus": "01",
  171. "name": name,
  172. "phone": phone,
  173. "comeintime_open": nowTime,
  174. "comeinsource_open": 1,
  175. })
  176. if clueId > 0 {
  177. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  178. "status": 1,
  179. "is_delete": 1,
  180. "createtime": nowTime,
  181. "updatetime": nowTime,
  182. "phone": phone,
  183. "baseinfo_id": uId,
  184. "SOURCE": source,
  185. })
  186. TiDb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  187. "clue_id": clueId,
  188. "position_id": -1,
  189. "change_type": "创建线索",
  190. "new_value": "系统自动创建",
  191. "createtime": nowTime,
  192. "BCPCID": common.GetRandom(32),
  193. "operator_id": -1,
  194. })
  195. }
  196. } else {
  197. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  198. "status": 1,
  199. "is_delete": 1,
  200. "createtime": nowTime,
  201. "updatetime": nowTime,
  202. "phone": phone,
  203. "baseinfo_id": uId,
  204. "SOURCE": source,
  205. })
  206. }
  207. } else {
  208. if count == 0 {
  209. FormatData(v, "users")
  210. } else {
  211. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  212. "status": 1,
  213. "is_delete": 1,
  214. "createtime": nowTime,
  215. "updatetime": nowTime,
  216. "phone": phone,
  217. "baseinfo_id": uId,
  218. "SOURCE": source,
  219. })
  220. }
  221. }
  222. }
  223. }
  224. }
  225. }
  226. }
  227. log.Println("userbase定时任务结束")
  228. }
  229. func getRunOk() bool {
  230. currentTime, runOk := time.Now(), false
  231. if currentTime.Weekday() == time.Sunday {
  232. isok := false
  233. for k, v := range DateMap {
  234. if currentTime.Format(date.Date_Short_Layout) == k && v == 2 {
  235. isok = true
  236. }
  237. }
  238. if isok {
  239. runOk = true
  240. }
  241. } else {
  242. isok := true
  243. for k, v := range DateMap {
  244. if currentTime.Format(date.Date_Short_Layout) == k && v == 1 {
  245. isok = false
  246. }
  247. }
  248. if isok {
  249. runOk = true
  250. }
  251. }
  252. return runOk
  253. }
  254. func getAreaCode(userId string) (code string) {
  255. followData := Base.Find("follow_project_monitor", map[string]interface{}{"s_userid": userId}, "", "", -1, -1)
  256. sidArr := []string{}
  257. if followData != nil && len(*followData) > 0 {
  258. for _, v := range *followData {
  259. infoId := common.ObjToString(v["s_id"])
  260. sidArr = append(sidArr, infoId)
  261. }
  262. }
  263. if len(sidArr) > 0 {
  264. query := `{"query": {"bool": {"must": [{"terms": {"_id": ["%s"]}}],"must_not": [],"should": []}}}`
  265. query = fmt.Sprintf(query, strings.Join(sidArr, `","`))
  266. biddingData := Es.Get("bidding", "bidding", query)
  267. if biddingData != nil && len(*biddingData) > 0 {
  268. codeMap := map[string]string{}
  269. codeArr := []string{}
  270. for _, v := range *biddingData {
  271. area := common.ObjToString(v["area"])
  272. address := common.ObjToString(v["city"])
  273. if address == "" {
  274. address = area
  275. }
  276. codeMap[address] = AreaCode[address]
  277. }
  278. if len(codeMap) > 0 {
  279. for _, v := range codeMap {
  280. codeArr = append(codeArr, v)
  281. }
  282. }
  283. if len(codeArr) > 0 {
  284. code = strings.Join(codeArr, ",")
  285. }
  286. }
  287. }
  288. log.Println("code ", code)
  289. return
  290. }
  291. func getClueType(item string, data map[string]interface{}, sourceCode string, sourceId int64) (pcode, code, level, topname, subname string) {
  292. if item == "orders" {
  293. productType := common.ObjToString(data["product_type"])
  294. pcode = "1"
  295. level = "A"
  296. topname = "提交订单未支付"
  297. if productType == "VIP订阅" {
  298. code = "6"
  299. subname = "超级订阅"
  300. } else if productType == "大会员" {
  301. code = "7"
  302. subname = "大会员"
  303. } else if productType == "数据流量包" {
  304. code = "8"
  305. subname = "数据流量包"
  306. } else if productType == "历史数据" {
  307. code = "9"
  308. subname = "数据自助导出"
  309. }
  310. } else if item == "users" {
  311. pcode = "4"
  312. code = "154"
  313. level = "C"
  314. topname = "新增注册"
  315. subname = "新增注册用户"
  316. } else if item == "message" {
  317. pcode = "532"
  318. code = "477"
  319. level = "B"
  320. topname = "其他"
  321. subname = "机器人客服主动咨询"
  322. } else if item == "readClue" {
  323. level = "A"
  324. topname = "超级订阅临期用户"
  325. pcode = "614"
  326. if sourceId == 1 {
  327. code = "615"
  328. subname = "60天后到期"
  329. } else if sourceId == 2 {
  330. code = "616"
  331. subname = "45天后到期"
  332. } else if sourceId == 3 {
  333. code = "617"
  334. subname = "15天后到期"
  335. } else {
  336. code = "618"
  337. subname = "7天后到期"
  338. }
  339. } else {
  340. if sourceCode != "" {
  341. codeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"source": sourceCode}, "", "")
  342. if codeData != nil && len(*codeData) > 0 {
  343. pcode = common.ObjToString((*codeData)["pcode"])
  344. code = common.ObjToString((*codeData)["code"])
  345. level = common.ObjToString((*codeData)["clue_level"])
  346. subname = common.ObjToString((*codeData)["name"])
  347. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  348. if pcodeData != nil && len(*pcodeData) > 0 {
  349. topname = common.ObjToString((*pcodeData)["name"])
  350. }
  351. }
  352. }
  353. }
  354. return
  355. }
  356. // 获取自动分配的人
  357. func autoDraw(mode, cluename, phone string, isGroup, isCommerce int) (positionId int64, seatNumber, saleName string, saleData []map[string]interface{}, isOk bool) {
  358. isOk = false
  359. if TiDb.Count("dwd_f_crm_clue_info", map[string]interface{}{"phone": phone, "is_assign": 1}) == 0 { //线索没销售进入,有销售走分配次数最少的逻辑
  360. if isGroup == 0 && isCommerce == 1 && cluename != "" { //非集团在工商库线索名不为空
  361. cdata := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"cluename": cluename, "is_assign": 1}, "", "")
  362. if cdata != nil && len(*cdata) > 0 { //找到了公司有人在跟进
  363. isOk = true
  364. positionId = common.Int64All((*cdata)["position_id"])
  365. seatNumber = common.ObjToString((*cdata)["seatNumber"])
  366. log.Println("positionId seatNumber ", positionId, seatNumber)
  367. if positionId > 0 {
  368. pdata := TiDb.SelectBySql(`select * from dwd_f_crm_personnel_management where seat_number is not null and seat_number != ""`)
  369. if pdata != nil {
  370. saleData = *pdata
  371. for _, v := range *pdata {
  372. resign := common.IntAll(v["resign"])
  373. if positionId == common.Int64All(v["position_id"]) {
  374. if resign == 1 { //离职分配,找到的销售离职了,分给组员,没离职就给他
  375. sdata := TiDb.SelectBySql(`SELECT b.name,b.position_id,b.seat_number from dwd_d_crm_department_level_succbi a INNER JOIN dwd_f_crm_personnel_management b on a.position_id = b.position_id where a.bi_pcode = (SELECT bi_pcode from dwd_d_crm_department_level_succbi where position_id = ?) and b.role_id = 3`, positionId)
  376. if sdata != nil && len(*sdata) > 0 {
  377. positionId = common.Int64All((*sdata)[0]["position_id"])
  378. seatNumber = common.ObjToString((*sdata)[0]["seat_number"])
  379. saleName = common.ObjToString((*sdata)[0]["name"])
  380. }
  381. } else {
  382. saleName = common.ObjToString(v["name"])
  383. }
  384. }
  385. }
  386. }
  387. return
  388. }
  389. }
  390. }
  391. }
  392. query := `select * from dwd_f_crm_personnel_management where assign_type = 1 and`
  393. if mode == "A" {
  394. query += ` assign_level like "%A%"`
  395. } else if mode == "B" {
  396. query += ` assign_level like "%B%"`
  397. } else {
  398. query += ` assign_level like "%C%"`
  399. }
  400. data := TiDb.SelectBySql(query)
  401. if data != nil && len(*data) > 0 {
  402. saleData = *data
  403. sql := "select * from dwd_f_crm_clue_autodraw_record where clue_level = ?"
  404. countData := TiDb.SelectBySql(sql, mode)
  405. if countData != nil && len(*countData) > 0 {
  406. for _, v := range *data {
  407. isOk := false //判断是否有新员工
  408. for _, vv := range *countData {
  409. if common.Int64All(v["position_id"]) == common.Int64All(vv["position_id"]) {
  410. if common.IntAll(v["resign"]) == 0 {
  411. vv["status"] = 1
  412. } else {
  413. vv["status"] = 2
  414. }
  415. isOk = true
  416. }
  417. }
  418. if !isOk { //有新员工直接分给新员工
  419. positionId = common.Int64All(v["position_id"])
  420. saleName = common.ObjToString(v["name"])
  421. log.Println("新员工, ", positionId, saleName)
  422. rData := TiDb.FindOne("dwd_f_crm_clue_autodraw_record", map[string]interface{}{"clue_level": mode}, "", "count desc")
  423. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  424. "position_id": positionId,
  425. "clue_level": mode,
  426. "count": common.Int64All((*rData)["count"]),
  427. })
  428. break
  429. }
  430. }
  431. if positionId == 0 {
  432. res := int64(0)
  433. countres := 0
  434. for _, v := range *countData {
  435. if common.IntAll(v["status"]) == 1 {
  436. if countres == 0 {
  437. res = common.Int64All(v["count"])
  438. positionId = common.Int64All(v["position_id"])
  439. } else {
  440. if common.Int64All(v["count"]) <= res {
  441. res = common.Int64All(v["count"])
  442. positionId = common.Int64All(v["position_id"])
  443. }
  444. }
  445. countres++
  446. }
  447. }
  448. }
  449. } else {
  450. positionId = common.Int64All((*data)[0]["position_id"])
  451. saleName = common.ObjToString((*data)[0]["name"])
  452. rData := TiDb.FindOne("dwd_f_crm_clue_autodraw_record", map[string]interface{}{"clue_level": mode}, "", "count desc")
  453. if rData != nil && len(*rData) > 0 {
  454. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  455. "position_id": positionId,
  456. "clue_level": mode,
  457. "count": common.Int64All((*rData)["count"]),
  458. })
  459. } else {
  460. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  461. "position_id": positionId,
  462. "clue_level": mode,
  463. "count": 0,
  464. })
  465. }
  466. }
  467. for _, v := range *data {
  468. if positionId == common.Int64All(v["position_id"]) {
  469. seatNumber = common.ObjToString(v["seat_number"])
  470. saleName = common.ObjToString(v["name"])
  471. }
  472. }
  473. }
  474. return
  475. }
  476. func getPositionId(phone string) (positionId int64) {
  477. userData, ok := Mgo.FindOne("user", map[string]interface{}{"s_phone": phone})
  478. if ok && userData != nil && len(*userData) > 0 {
  479. userId := common.Int64All((*userData)["base_user_id"])
  480. positionData := Base.FindOne("base_position", map[string]interface{}{"type": 1, "ent_id": 25917, "user_id": userId}, "", "") //TODO ent_id
  481. if positionData != nil && len(*positionData) > 0 {
  482. positionId = common.Int64All((*positionData)["id"])
  483. }
  484. }
  485. return
  486. }
  487. func GetCompanyType(companyName string) (int, int) {
  488. //是否是集团
  489. isGroup, isCommerce := 0, 0
  490. if c := TiDb.CountBySql(`select count(1) from group_company_name where company_name=?`, companyName); c > 0 {
  491. isGroup = 1
  492. }
  493. //是否在工商库
  494. if c := MgoQyxy.Count("qyxy_std", map[string]interface{}{"company_name": companyName, "company_type": map[string]interface{}{"$ne": "个体工商户"}}); c > 0 {
  495. isCommerce = 1
  496. }
  497. return isGroup, isCommerce
  498. }
  499. func getSeatNumberPositionId(seatNumber string) (positionId int64) {
  500. saleData := TiDb.FindOne("dwd_f_crm_personnel_management", map[string]interface{}{"seat_number": seatNumber}, "", "")
  501. if saleData != nil && len(*saleData) > 0 {
  502. positionId = common.Int64All((*saleData)["position_id"])
  503. }
  504. return
  505. }