jobutil.go 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019
  1. package main
  2. import (
  3. "app.yhyue.com/moapp/jybase/redis"
  4. "fmt"
  5. "log"
  6. "strings"
  7. "time"
  8. "github.com/gogf/gf/v2/util/gconv"
  9. "app.yhyue.com/moapp/jybase/common"
  10. "app.yhyue.com/moapp/jybase/date"
  11. "app.yhyue.com/moapp/jybase/mongodb"
  12. )
  13. // 电销工单生成
  14. func rderAcceptance() {
  15. sql := fmt.Sprintf(`select * from order_acceptance where is_clue=2 and is_delete=1 order by propose_time `)
  16. data := WorkOrder.SelectBySql(sql)
  17. if data != nil && len(*data) > 0 {
  18. for _, v := range *data {
  19. acceptance_no := gconv.String(v["acceptance_no"])
  20. childrenArr := WorkOrder.Find("order_acceptance_children", map[string]interface{}{
  21. "acceptance_no": acceptance_no,
  22. }, "", "", -1, -1)
  23. if childrenArr != nil && len(*childrenArr) > 0 {
  24. company := ""
  25. phone := ""
  26. demand := ""
  27. name := ""
  28. product := ""
  29. for _, v1 := range *childrenArr {
  30. if gconv.String(v1["field_name"]) == "公司名称" {
  31. company = gconv.String(v1["field_value"])
  32. }
  33. if gconv.String(v1["field_name"]) == "联系方式num" {
  34. phone = gconv.String(v1["field_value"])
  35. }
  36. if gconv.String(v1["field_name"]) == "客户姓名" {
  37. name = gconv.String(v1["field_value"])
  38. }
  39. if gconv.String(v1["field_name"]) == "客户需求" {
  40. demand = gconv.String(v1["field_value"])
  41. }
  42. if gconv.String(v1["field_name"]) == "咨询产品" {
  43. product = gconv.String(v1["field_value"])
  44. }
  45. }
  46. WorkDataHandle(company, phone, demand, name, product, v)
  47. }
  48. }
  49. }
  50. }
  51. func WorkDataHandle(company, phone, demand, name, product string, acceptanceData map[string]interface{}) bool {
  52. uId := ""
  53. query := map[string]interface{}{}
  54. contactsData := TiDb.SelectBySql("select * from dwd_f_userbase_contacts where phone = ? and is_delete = 1", phone)
  55. if contactsData != nil && len(*contactsData) > 0 {
  56. if common.ObjToString((*contactsData)[0]["baseinfo_id"]) != "" {
  57. uId = common.ObjToString((*contactsData)[0]["baseinfo_id"])
  58. query["uid"] = uId
  59. }
  60. }
  61. if uId == "" {
  62. return false
  63. }
  64. cluename := company
  65. if cluename == "" {
  66. cluename = phone //没有线索名,手机号代替
  67. }
  68. ok, data, saleData := false, map[string]interface{}{}, []map[string]interface{}{}
  69. isGroup, isCommerce := GetCompanyType(cluename)
  70. uCount, _ := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"uid": uId}, "", ""), true //查当前线索是否已存在
  71. if uCount != nil && len(*uCount) > 0 {
  72. clueId := gconv.Int64((*uCount)["id"])
  73. positionId := gconv.Int64((*uCount)["position_id"])
  74. if positionId == 0 {
  75. //线索变更
  76. ok, data, saleData = FindPosition(positionId, "", false)
  77. if !ok {
  78. return false
  79. }
  80. UpdateClue(*uCount, saleData, "", "", uId, "", "", "", "", company, name, gconv.String(data["name"]), phone, "", "", "", "", "", "", gconv.String(data["seat_number"]), "", gconv.Int64(data["position_id"]), "", "", "", []string{}, "", isGroup, isCommerce, true, demand)
  81. } else {
  82. trailstatusl := gconv.String((*uCount)["trailstatusl"])
  83. if trailstatusl == "01" || trailstatusl == "03" || trailstatusl == "04" {
  84. //变更销售员
  85. ok, data, saleData = FindPosition(positionId, "", false)
  86. if !ok {
  87. return false
  88. }
  89. UpdateClue(*uCount, saleData, "", "", uId, "", "", "", "", company, name, gconv.String(data["name"]), phone, "", "", "", "", "", "", gconv.String(data["seat_number"]), "", gconv.Int64(data["position_id"]), "", "", "", []string{}, "", isGroup, isCommerce, true, demand)
  90. } else if trailstatusl == "08" {
  91. //客成
  92. //查找客成人员标识
  93. customerMap := TiDb.FindOne("dwd_f_csm_customer_info", map[string]interface{}{
  94. "clue_id": clueId,
  95. }, "position_id", "")
  96. if customerMap != nil && len(*customerMap) > 0 {
  97. UpdateClue(*uCount, saleData, "", "", uId, "", "", "", "", company, name, gconv.String((*uCount)["name"]), phone, "", "", "", "", "", "", gconv.String((*uCount)["seat_number"]), "", gconv.Int64((*uCount)["position_id"]), "", "", "", []string{}, "", isGroup, isCommerce, true, demand)
  98. data = map[string]interface{}{
  99. "type": "kc",
  100. "position_id": (*customerMap)["position_id"],
  101. "name": (*customerMap)["name"],
  102. }
  103. }
  104. } else {
  105. //线索变更
  106. ok, data, saleData = FindPosition(positionId, trailstatusl, false)
  107. if !ok {
  108. return false
  109. }
  110. UpdateClue(*uCount, saleData, "", "", uId, "", "", "", "", company, name, gconv.String(data["name"]), phone, "", "", "", "", "", "", gconv.String(data["seat_number"]), "", gconv.Int64(data["position_id"]), "", "", "", []string{}, "", isGroup, isCommerce, true, demand)
  111. }
  112. }
  113. } else {
  114. //新增线索
  115. ok, data, _ = FindPosition(0, "", false)
  116. if !ok {
  117. return false
  118. }
  119. SaveClue("", "", uId, "", "", "", "", cluename, name, gconv.String(data["name"]), phone, "", "", "", "", "", "", gconv.String(data["seat_number"]), gconv.Int64(data["position_id"]), "", "", "", []string{}, "", isGroup, isCommerce, false, demand)
  120. }
  121. //工单生成
  122. AddOrderWork(acceptanceData, data, product, phone, company)
  123. return true
  124. }
  125. func AddOrderWork(acceptanceData map[string]interface{}, userData map[string]interface{}, product, phone, company string) bool {
  126. nowTime := time.Now().Format(date.Date_Full_Layout)
  127. work_order_no := fmt.Sprintf("GD%s%s", time.Now().Format(date.Date_Short_Layout), FindNumber("gd"))
  128. productArr := []string{}
  129. for _, v := range strings.Split(product, ",") {
  130. switch ProductMap[v] {
  131. case "dk":
  132. continue
  133. default:
  134. productArr = append(productArr, v)
  135. }
  136. }
  137. orderWorkMap := map[string]interface{}{
  138. "work_order_no": work_order_no,
  139. "acceptance_no": gconv.String(acceptanceData["acceptance_no"]),
  140. "type": strings.Join(productArr, ","),
  141. "status": common.If(gconv.Int64(userData["orderStatus"]) == 0, 1, 2),
  142. "initiator_name": gconv.String(acceptanceData["creator_name"]),
  143. "initiator_position_id": gconv.String(acceptanceData["initiator_position_id"]),
  144. "current_name": userData["name"],
  145. "current_position_id": userData["position_id"],
  146. "is_delete": 1,
  147. "creator_name": gconv.String(acceptanceData["creator_name"]),
  148. "creator_position_id": gconv.String(acceptanceData["creator_position_id"]),
  149. "creator_time": nowTime,
  150. "two_type": "dx",
  151. "department_no": gconv.String(acceptanceData["department_no"]),
  152. "department_name": gconv.String(acceptanceData["department_name"]),
  153. }
  154. ok3 := WorkOrder.Insert("order_work", orderWorkMap)
  155. if ok3 > 0 {
  156. WorkOrder.Update("order_acceptance", map[string]interface{}{
  157. "id": acceptanceData["id"],
  158. }, map[string]interface{}{
  159. "is_clue": 3,
  160. })
  161. //发送邮件
  162. personMap := GetPerson(gconv.String(userData["position_id"]))
  163. if personMap == nil || len(personMap) == 0 {
  164. return false
  165. }
  166. WorkMail(personMap,
  167. strings.Join(productArr, ","),
  168. gconv.Int64(common.If(gconv.Int64(userData["orderStatus"]) == 0, 1, 2)),
  169. gconv.String(personMap["name"]),
  170. gconv.String(acceptanceData["creator_name"]),
  171. nowTime,
  172. gconv.String(acceptanceData["acceptance_no"]),
  173. phone,
  174. company)
  175. return true
  176. }
  177. return false
  178. }
  179. // 本级以及上级管理员查询
  180. func GetPerson(positionId string) map[string]interface{} {
  181. person := map[string]interface{}{}
  182. positionArrMap := Base.SelectBySql(fmt.Sprintf(`select a.phone,b.id,b.ent_id from
  183. base_user a
  184. INNER JOIN base_position b
  185. on b.id=%s and b.user_id=a.id and b.type=1`,
  186. positionId))
  187. if positionArrMap == nil || len(*positionArrMap) == 0 {
  188. return map[string]interface{}{}
  189. }
  190. phone := gconv.String((*positionArrMap)[0]["phone"])
  191. entId := gconv.String((*positionArrMap)[0]["ent_id"])
  192. entUserArrMap := Mysql.SelectBySql(fmt.Sprintf(`SELECT
  193. a.name as name,a.mail as mail,b.dept_id as deptId,a.phone
  194. FROM
  195. entniche_user a
  196. INNER JOIN entniche_department_user b ON a.ent_id =%s
  197. AND a.phone IN %s
  198. and a.id=b.user_id`, entId, fmt.Sprintf("(%s)", phone)))
  199. //商机管理员
  200. if entUserArrMap == nil || len(*entUserArrMap) == 0 {
  201. return map[string]interface{}{}
  202. }
  203. deptId := gconv.Int64((*entUserArrMap)[0]["deptId"])
  204. person = map[string]interface{}{
  205. "name": gconv.String((*entUserArrMap)[0]["name"]),
  206. "mail": gconv.String((*entUserArrMap)[0]["mail"]),
  207. "phone": gconv.String((*entUserArrMap)[0]["phone"]),
  208. }
  209. //本部门管理员查询
  210. depthMap := Mysql.SelectBySql(`SELECT
  211. c.name as name,c.mail as mail
  212. FROM
  213. entniche_department_user a
  214. INNER JOIN entniche_user_role b ON a.dept_id = ?
  215. AND a.user_id = b.user_id
  216. AND b.role_id =2
  217. INNER JOIN entniche_user c ON a.user_id = c.id`, deptId)
  218. if depthMap != nil && len(*depthMap) > 0 {
  219. person["deptPersonName"] = gconv.String((*depthMap)[0]["name"])
  220. person["deptPersonMail"] = gconv.String((*depthMap)[0]["mail"])
  221. }
  222. //商机管理员查询
  223. superiorDepthMap := Mysql.SelectBySql(`SELECT
  224. c.*
  225. FROM
  226. entniche_department d
  227. INNER JOIN entniche_department_user a ON d.id = ?
  228. AND d.pid = a.dept_id
  229. INNER JOIN entniche_user_role b ON a.user_id = b.user_id
  230. AND b.role_id = 1
  231. INNER JOIN entniche_user c ON a.user_id = c.id`, deptId)
  232. if superiorDepthMap != nil && len(*superiorDepthMap) > 0 {
  233. person["superiorDepthPersonName"] = gconv.String((*superiorDepthMap)[0]["name"])
  234. person["superiorDepthPersonMail"] = gconv.String((*superiorDepthMap)[0]["mail"])
  235. }
  236. return person
  237. }
  238. // 编号查询
  239. func FindNumber(moudle string) string {
  240. today := time.Now().Format("2006-01-02")
  241. yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02")
  242. key := fmt.Sprintf("%s_%s", today, moudle)
  243. yesterdayKey := fmt.Sprintf("%s_%s", yesterday, moudle)
  244. if ok, _ := redis.Exists("newother", yesterdayKey); ok {
  245. //删除之前数据
  246. redis.Del("newother", yesterdayKey)
  247. }
  248. count := redis.Incr("newother", key)
  249. return fmt.Sprintf("%04d", count)
  250. }
  251. // 人员查询
  252. func FindPosition(positionId int64, trailstatusl string, full bool) (bool, map[string]interface{}, []map[string]interface{}) {
  253. allData := []map[string]interface{}{}
  254. //查询是否满了
  255. if positionId != 0 {
  256. if FindUpperLimit(gconv.String(positionId), "", false) {
  257. full = true
  258. }
  259. }
  260. //查询两个部门高级管理员
  261. //查询两个部门所有人员标识
  262. //电销三部
  263. userData1 := TiDb.SelectBySql(`SELECT
  264. a.position_id,
  265. a.name,
  266. b.seat_number
  267. FROM
  268. dwd_d_crm_department_level_succbi a
  269. INNER JOIN dwd_f_crm_personnel_management b ON a.resign = 0
  270. AND a.ent_id = 25917
  271. AND a.resign = 0
  272. AND a.dept_name LIKE "%销售一部/电销部%"
  273. AND a.position_id = b.position_id`)
  274. userData3 := TiDb.SelectBySql(`SELECT
  275. a.position_id,
  276. a.name,
  277. b.seat_number
  278. FROM
  279. dwd_d_crm_department_level_succbi a
  280. INNER JOIN dwd_f_crm_personnel_management b ON a.resign = 0
  281. AND a.ent_id = 25917
  282. AND a.resign = 0
  283. AND a.dept_name LIKE "%销售三部"
  284. AND a.position_id = b.position_id`)
  285. if userData3 == nil || len(*userData3) == 0 || userData1 == nil || len(*userData1) == 0 {
  286. return false, map[string]interface{}{}, allData
  287. }
  288. //一部管理员信息
  289. administrators1 := map[string]interface{}{}
  290. //三部管理员信息
  291. administrators3 := map[string]interface{}{}
  292. //返回当前人信息
  293. administrators := map[string]interface{}{}
  294. //电销一部
  295. positionIdArr1 := []string{}
  296. positionIdArr3 := []string{}
  297. proportion1 := float64(0)
  298. proportion3 := float64(0)
  299. for _, v := range *userData3 {
  300. v["type"] = 3
  301. personName := gconv.String(v["name"])
  302. id := gconv.Int64(v["position_id"])
  303. if id == positionId && !full {
  304. if personName == "孙鹏" {
  305. v["orderStatus"] = 2
  306. }
  307. administrators = v
  308. }
  309. if personName == "孙鹏" {
  310. v["orderStatus"] = 2
  311. administrators3 = v
  312. proportion3 += 0.5
  313. } else {
  314. proportion3 += 1
  315. }
  316. positionIdArr3 = append(positionIdArr3, gconv.String(id))
  317. allData = append(allData, v)
  318. }
  319. for _, v := range *userData1 {
  320. v["type"] = 1
  321. personName := gconv.String(v["name"])
  322. id := gconv.Int64(v["position_id"])
  323. if id == positionId && !full {
  324. if personName == "沈炳毅" {
  325. v["orderStatus"] = 2
  326. }
  327. administrators = v
  328. }
  329. if personName == "沈炳毅" {
  330. v["orderStatus"] = 2
  331. administrators1 = v
  332. proportion1 += 0.5
  333. } else {
  334. proportion1 += 1
  335. }
  336. positionIdArr1 = append(positionIdArr1, gconv.String(id))
  337. allData = append(allData, v)
  338. }
  339. if positionId != 0 {
  340. if administrators == nil || len(administrators) == 0 {
  341. return false, map[string]interface{}{}, allData
  342. }
  343. positiontype := gconv.Int64(administrators["type"])
  344. if full {
  345. switch positiontype {
  346. case 1:
  347. if trailstatusl == "01" || trailstatusl == "03" || trailstatusl == "04" {
  348. //找他上级
  349. positionId1 := gconv.String(administrators1["position_id"])
  350. administrators = administrators1
  351. if FindUpperLimit(positionId1, "", false) {
  352. return false, map[string]interface{}{}, allData
  353. }
  354. }
  355. case 3:
  356. if trailstatusl == "01" || trailstatusl == "03" || trailstatusl == "04" {
  357. //找他上级
  358. positionId1 := gconv.String(administrators3["position_id"])
  359. administrators = administrators3
  360. if FindUpperLimit(positionId1, "", false) {
  361. return false, map[string]interface{}{}, allData
  362. }
  363. }
  364. }
  365. } else {
  366. return true, administrators, allData
  367. }
  368. }
  369. //按照比例分配选择一部还是三部
  370. //一部查询
  371. deptCount1 := CalculateProportion(strings.Join(positionIdArr1, ","))
  372. //三部查询
  373. deptCount3 := CalculateProportion(strings.Join(positionIdArr3, ","))
  374. if deptCount1 == 0 {
  375. return true, administrators1, allData
  376. }
  377. if deptCount3 == 0 {
  378. return true, administrators3, allData
  379. }
  380. if deptCount1/deptCount3 > proportion1/proportion3 {
  381. return true, administrators3, allData
  382. } else {
  383. return true, administrators1, allData
  384. }
  385. return false, map[string]interface{}{}, allData
  386. }
  387. func CalculateProportion(positionIsStr string) float64 {
  388. createtime := time.Time{}
  389. now := time.Now()
  390. weekday := int(now.Weekday())
  391. if weekday == 0 { // 如果是周日,则将其视为本周的最后一天
  392. weekday = 7
  393. }
  394. switch cfg.LoopType {
  395. case 1: //周
  396. createtime = now.AddDate(0, 0, -weekday+1)
  397. case 2: //月
  398. createtime = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.Local)
  399. }
  400. count := float64(0)
  401. sql := `SELECT
  402. sum(1) as count
  403. FROM
  404. order_work
  405. WHERE
  406. FIND_IN_SET(current_position_id ,?)
  407. AND is_delete=1
  408. and creator_time>?`
  409. data := WorkOrder.SelectBySql(sql, positionIsStr, createtime.Format("2006-01-02"))
  410. if data != nil && len(*data) > 0 {
  411. count = gconv.Float64((*data)[0]["count"])
  412. }
  413. return count
  414. }
  415. // 未支付订单 30分钟一次
  416. func orders() {
  417. //一个小时未支付进入线索 A
  418. log.Println("未支付订单定时任务开始")
  419. lastOrderId := cfg.LastOrderId
  420. selectTimeStart := time.Unix(time.Now().Unix()-7200, 0).Format(date.Date_Full_Layout)
  421. selectTimeEnd := time.Unix(time.Now().Unix()-3600, 0).Format(date.Date_Full_Layout)
  422. sql := fmt.Sprintf(`select * from dataexport_order where create_time <= "%s" and create_time >= "%s" and id > %s`, selectTimeEnd, selectTimeStart, fmt.Sprint(lastOrderId))
  423. data := Mysql.SelectBySql(sql)
  424. if data != nil && *data != nil && len(*data) > 0 {
  425. for _, v := range *data {
  426. order_status := common.IntAll(v["order_status"])
  427. is_backstage_order := common.IntAll(v["is_backstage_order"])
  428. product_type_str1 := `"大会员","VIP订阅","数据流量包","历史数据"`
  429. product_type := common.ObjToString(v["product_type"])
  430. if order_status == 0 && is_backstage_order == 0 && strings.Contains(product_type_str1, product_type) {
  431. ok1, ok2 := FormatData(v, "orders")
  432. if !ok1 {
  433. common.WriteSysConfig(&cfg)
  434. log.Println("线索卡点", "orders", v, selectTimeEnd, selectTimeStart)
  435. break
  436. } else {
  437. if !ok2 {
  438. log.Println("用户分配已达上限", "orders", v, selectTimeEnd, selectTimeStart)
  439. common.WriteSysConfig(&cfg)
  440. break
  441. }
  442. }
  443. }
  444. cfg.LastOrderId = common.IntAll(v["id"])
  445. }
  446. }
  447. common.WriteSysConfig(&cfg)
  448. log.Println("未支付订单定时任务结束")
  449. }
  450. func readClue() {
  451. log.Println("读表进线索定时任务开始")
  452. lastReadClueTime := cfg.LastReadClueTime
  453. sql := fmt.Sprintf(`select * from clue_info where updatetime > "%s" order by updatetime asc`, fmt.Sprint(lastReadClueTime))
  454. data := TiDb.SelectBySql(sql)
  455. if data != nil && *data != nil && len(*data) > 0 {
  456. for _, v := range *data {
  457. ok1, ok2 := FormatData(v, "readClue")
  458. if !ok1 {
  459. common.WriteSysConfig(&cfg)
  460. log.Println("线索卡点", "readClue", v, lastReadClueTime)
  461. break
  462. } else {
  463. if !ok2 {
  464. log.Println("用户分配已达上限", "readClue", v, lastReadClueTime)
  465. common.WriteSysConfig(&cfg)
  466. break
  467. }
  468. }
  469. cfg.LastReadClueTime = common.ObjToString(v["updatetime"])
  470. }
  471. }
  472. common.WriteSysConfig(&cfg)
  473. log.Println("读表进线索定时任务结束")
  474. }
  475. // 新注册用户 5分钟一次
  476. func users() {
  477. //判断节假日
  478. runOk := getRunOk()
  479. if !runOk {
  480. log.Println("不是工作日,任务暂停")
  481. return
  482. }
  483. //新用户注册后5分钟内进入线索 C
  484. log.Println("新注册用户定时任务开始")
  485. selectTimeEnd := cfg.LastUserId
  486. sql := fmt.Sprintf(`select * from dwd_f_userbase_baseinfo where createtime > "%s" and source = "0101" and status != 2`, selectTimeEnd)
  487. data := TiDb.SelectBySql(sql)
  488. if data != nil && *data != nil && len(*data) > 0 {
  489. for k, v := range *data {
  490. createtime := common.ObjToString(v["createtime"])
  491. ok1, ok2 := FormatData(v, "users")
  492. if !ok1 {
  493. common.WriteSysConfig(&cfg)
  494. log.Println("线索卡点", "users", v, selectTimeEnd)
  495. break
  496. } else {
  497. if !ok2 {
  498. log.Println("用户分配已达上限", "users", v, selectTimeEnd)
  499. common.WriteSysConfig(&cfg)
  500. break
  501. }
  502. }
  503. if k == len(*data)-1 {
  504. cfg.LastUserId = createtime
  505. }
  506. }
  507. }
  508. common.WriteSysConfig(&cfg)
  509. log.Println("新注册用户定时任务结束")
  510. }
  511. // 留资 5分钟一次
  512. func saleLeads() {
  513. //判断节假日
  514. runOk := getRunOk()
  515. if !runOk {
  516. log.Println("不是工作日,任务暂停")
  517. return
  518. }
  519. //留资后5分钟内进入线索
  520. //分为免费留资和付费留资 付费B 免费C
  521. log.Println("用户留资定时任务开始")
  522. session := Mgo.GetMgoConn()
  523. lastId := cfg.LastId
  524. defer func() {
  525. Mgo.DestoryMongoConn(session)
  526. }()
  527. query := map[string]interface{}{}
  528. if lastId != "" {
  529. query["_id"] = map[string]interface{}{"$gt": mongodb.StringTOBsonId(lastId)}
  530. }
  531. log.Println("query :", query)
  532. iter := session.DB(cfg.Mgo.DbName).C("saleLeads").Find(&query).Sort("_id").Iter()
  533. thisData := map[string]interface{}{}
  534. for {
  535. if !iter.Next(&thisData) {
  536. break
  537. }
  538. ok1, ok2 := FormatData(thisData, "saleLeads")
  539. if !ok1 {
  540. common.WriteSysConfig(&cfg)
  541. log.Println("线索卡点", "saleLeads", thisData, lastId)
  542. break
  543. } else {
  544. if !ok2 {
  545. log.Println("用户分配已达上限", "saleLeads", thisData, lastId)
  546. common.WriteSysConfig(&cfg)
  547. break
  548. }
  549. }
  550. cfg.LastId = mongodb.BsonIdToSId(thisData["_id"])
  551. }
  552. common.WriteSysConfig(&cfg)
  553. log.Println("用户留资定时任务结束")
  554. }
  555. func userbase() {
  556. log.Println("userbase定时任务开始")
  557. selectTimeEnd := time.Unix(time.Now().Unix()-1800, 0).Format("2006-01-02 15:04:05")
  558. 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)
  559. //sql := fmt.Sprintf(`select * from dwd_f_userbase_baseinfo where id='11927183'`)
  560. data := TiDb.SelectBySql(sql)
  561. if data != nil && *data != nil && len(*data) > 0 {
  562. for _, v := range *data {
  563. phone := common.ObjToString(v["phone"])
  564. uId := common.ObjToString(v["uid"])
  565. userId := common.ObjToString(v["userid"])
  566. registedate := common.ObjToString(v["l_registedate"])
  567. name := common.ObjToString(v["name"])
  568. nowTime := time.Now().Format(date.Date_Full_Layout)
  569. source := common.ObjToString(v["source"])
  570. if phone != "" {
  571. contactsData := TiDb.SelectBySql("select * from dwd_f_userbase_contacts where phone = ? and is_delete = 1", phone)
  572. if contactsData == nil || len(*contactsData) == 0 {
  573. contactsData2 := TiDb.SelectBySql("select * from dwd_f_userbase_contacts where baseinfo_id = ? and is_delete = 1", uId)
  574. if contactsData2 != nil && len(*contactsData2) > 0 {
  575. log.Println("userbase uid不为空 新增通讯录", uId)
  576. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  577. "status": 1,
  578. "is_delete": 1,
  579. "createtime": nowTime,
  580. "updatetime": nowTime,
  581. "phone": phone,
  582. "baseinfo_id": uId,
  583. "SOURCE": source,
  584. })
  585. } else {
  586. registedates, _ := time.Parse(date.Date_Full_Layout, registedate)
  587. count := TiDb.CountBySql("select count(1) as count from dwd_f_crm_clue_info where uid = ?", uId)
  588. log.Println("userbase uid 线索数量 ", count)
  589. log.Println("userbase uid 注册时间 ", registedates)
  590. if time.Now().Unix()-registedates.Unix() > int64(cfg.RegTimes)*86400 {
  591. if count == 0 {
  592. // TiDb.Insert("dwd_f_crm_open_sea", map[string]interface{}{
  593. // "clue_id": clueId,
  594. // "comeintime": nowTime,
  595. // "comeinsource": 2,
  596. // })
  597. clueId := TiDb.Insert("dwd_f_crm_clue_info", map[string]interface{}{
  598. "userid": userId,
  599. "uid": uId,
  600. "is_assign": 0,
  601. "comeintime": nowTime,
  602. "createtime": nowTime,
  603. "updatetime": nowTime,
  604. "cluename": phone,
  605. "top_cluetype": "532",
  606. "sub_cluetype": "475",
  607. "trailstatus": "01",
  608. "name": name,
  609. "phone": phone,
  610. "comeintime_open": nowTime,
  611. "comeinsource_open": 1,
  612. "FREEZE_TIME": nowTime,
  613. })
  614. if clueId > 0 {
  615. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  616. "status": 1,
  617. "is_delete": 1,
  618. "createtime": nowTime,
  619. "updatetime": nowTime,
  620. "phone": phone,
  621. "baseinfo_id": uId,
  622. "SOURCE": source,
  623. })
  624. TiDb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  625. "clue_id": clueId,
  626. "position_id": -1,
  627. "change_type": "创建线索",
  628. "new_value": "系统自动创建",
  629. "createtime": nowTime,
  630. "BCPCID": common.GetRandom(32),
  631. "operator_id": -1,
  632. })
  633. }
  634. } else {
  635. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  636. "status": 1,
  637. "is_delete": 1,
  638. "createtime": nowTime,
  639. "updatetime": nowTime,
  640. "phone": phone,
  641. "baseinfo_id": uId,
  642. "SOURCE": source,
  643. })
  644. }
  645. } else {
  646. if count == 0 {
  647. ok1, ok2 := FormatData(v, "users")
  648. if !ok1 {
  649. common.WriteSysConfig(&cfg)
  650. log.Println("线索卡点", "userbase uid", v, uId)
  651. break
  652. } else {
  653. if !ok2 {
  654. log.Println("用户分配已达上限", "userbase uid", v, uId)
  655. common.WriteSysConfig(&cfg)
  656. break
  657. }
  658. }
  659. } else {
  660. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  661. "status": 1,
  662. "is_delete": 1,
  663. "createtime": nowTime,
  664. "updatetime": nowTime,
  665. "phone": phone,
  666. "baseinfo_id": uId,
  667. "SOURCE": source,
  668. })
  669. }
  670. }
  671. }
  672. }
  673. }
  674. }
  675. }
  676. log.Println("userbase定时任务结束")
  677. }
  678. func getRunOk() bool {
  679. currentTime, runOk := time.Now(), false
  680. if currentTime.Weekday() == time.Sunday {
  681. isok := false
  682. for k, v := range DateMap {
  683. if currentTime.Format(date.Date_Short_Layout) == k && v == 2 {
  684. isok = true
  685. }
  686. }
  687. if isok {
  688. runOk = true
  689. }
  690. } else {
  691. isok := true
  692. for k, v := range DateMap {
  693. if currentTime.Format(date.Date_Short_Layout) == k && v == 1 {
  694. isok = false
  695. }
  696. }
  697. if isok {
  698. runOk = true
  699. }
  700. }
  701. return runOk
  702. }
  703. func getAreaCode(userId string) (code string) {
  704. followData := Base.Find("follow_project_monitor", map[string]interface{}{"s_userid": userId}, "", "", -1, -1)
  705. sidArr := []string{}
  706. if followData != nil && len(*followData) > 0 {
  707. for _, v := range *followData {
  708. infoId := common.ObjToString(v["s_id"])
  709. sidArr = append(sidArr, infoId)
  710. }
  711. }
  712. if len(sidArr) > 0 {
  713. query := `{"query": {"bool": {"must": [{"terms": {"_id": ["%s"]}}],"must_not": [],"should": []}}}`
  714. query = fmt.Sprintf(query, strings.Join(sidArr, `","`))
  715. biddingData := Es.Get("bidding", "bidding", query)
  716. if biddingData != nil && len(*biddingData) > 0 {
  717. codeMap := map[string]string{}
  718. codeArr := []string{}
  719. for _, v := range *biddingData {
  720. area := common.ObjToString(v["area"])
  721. address := common.ObjToString(v["city"])
  722. if address == "" {
  723. address = area
  724. }
  725. codeMap[address] = AreaCode[address]
  726. }
  727. if len(codeMap) > 0 {
  728. for _, v := range codeMap {
  729. codeArr = append(codeArr, v)
  730. }
  731. }
  732. if len(codeArr) > 0 {
  733. code = strings.Join(codeArr, ",")
  734. }
  735. }
  736. }
  737. log.Println("code ", code)
  738. return
  739. }
  740. func getClueType(item string, data map[string]interface{}, sourceCode string, sourceId int64) (pcode, code, level, topname, subname string) {
  741. if item == "orders" {
  742. productType := common.ObjToString(data["product_type"])
  743. pcode = "1"
  744. level = "A"
  745. topname = "提交订单未支付"
  746. if productType == "VIP订阅" {
  747. code = "6"
  748. subname = "超级订阅"
  749. } else if productType == "大会员" {
  750. code = "7"
  751. subname = "大会员"
  752. } else if productType == "数据流量包" {
  753. code = "8"
  754. subname = "数据流量包"
  755. } else if productType == "历史数据" {
  756. code = "9"
  757. subname = "数据自助导出"
  758. }
  759. } else if item == "users" {
  760. pcode = "4"
  761. code = "154"
  762. level = "C"
  763. topname = "新增注册"
  764. subname = "新增注册用户"
  765. } else if item == "message" {
  766. pcode = "532"
  767. code = "477"
  768. level = "B"
  769. topname = "其他"
  770. subname = "机器人客服主动咨询"
  771. } else if item == "readClue" {
  772. level = "A"
  773. topname = "超级订阅临期用户"
  774. pcode = "614"
  775. if sourceId == 1 {
  776. code = "615"
  777. subname = "60天后到期"
  778. } else if sourceId == 2 {
  779. code = "616"
  780. subname = "45天后到期"
  781. } else if sourceId == 3 {
  782. code = "617"
  783. subname = "15天后到期"
  784. } else {
  785. code = "618"
  786. subname = "7天后到期"
  787. }
  788. } else {
  789. if sourceCode != "" {
  790. codeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"source": sourceCode}, "", "")
  791. if codeData != nil && len(*codeData) > 0 {
  792. pcode = common.ObjToString((*codeData)["pcode"])
  793. code = common.ObjToString((*codeData)["code"])
  794. level = common.ObjToString((*codeData)["clue_level"])
  795. subname = common.ObjToString((*codeData)["name"])
  796. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  797. if pcodeData != nil && len(*pcodeData) > 0 {
  798. topname = common.ObjToString((*pcodeData)["name"])
  799. }
  800. }
  801. }
  802. }
  803. return
  804. }
  805. // 获取自动分配的人
  806. func autoDraw(mode, cluename, phone string, isGroup, isCommerce int) (positionId int64, seatNumber, saleName string, saleData []map[string]interface{}, isOk, isFreeze bool, noticePositionId int64) {
  807. isOk = false
  808. isFreeze = false
  809. if TiDb.Count("dwd_f_crm_clue_info", map[string]interface{}{"phone": phone, "is_assign": 1}) == 0 { //线索没销售进入,有销售走分配次数最少的逻辑
  810. if isGroup == 0 && isCommerce == 1 && cluename != "" { //非集团在工商库线索名不为空
  811. cdata := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"cluename": cluename, "is_assign": 1}, "", "")
  812. if cdata != nil && len(*cdata) > 0 { //找到了公司有人在跟进
  813. isOk = true
  814. positionId = common.Int64All((*cdata)["position_id"])
  815. noticePositionId = positionId
  816. seatNumber = common.ObjToString((*cdata)["seatNumber"])
  817. log.Println("positionId seatNumber ", positionId, seatNumber)
  818. if positionId > 0 {
  819. pdata := TiDb.SelectBySql(`select * from dwd_f_crm_personnel_management where seat_number is not null and seat_number != ""`)
  820. if pdata != nil {
  821. saleData = *pdata
  822. for _, v := range *pdata {
  823. resign := common.IntAll(v["resign"])
  824. if positionId == common.Int64All(v["position_id"]) {
  825. if resign == 1 { //离职分配,找到的销售离职了,分给组员,没离职就给他
  826. 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)
  827. if sdata != nil && len(*sdata) > 0 {
  828. for _, m := range *sdata {
  829. if !FindUpperLimit(gconv.String(positionId), mode, true) {
  830. positionId = common.Int64All(m["position_id"])
  831. noticePositionId = positionId
  832. seatNumber = common.ObjToString(m["seat_number"])
  833. saleName = common.ObjToString(m["name"])
  834. return
  835. }
  836. }
  837. isFreeze = true
  838. positionId = 0
  839. seatNumber = ""
  840. saleName = ""
  841. return
  842. }
  843. } else {
  844. if FindUpperLimit(gconv.String(positionId), mode, true) {
  845. isFreeze = true
  846. }
  847. saleName = common.ObjToString(v["name"])
  848. }
  849. }
  850. }
  851. }
  852. if isFreeze {
  853. positionId = 0
  854. seatNumber = ""
  855. saleName = ""
  856. }
  857. return
  858. }
  859. }
  860. }
  861. }
  862. query := `select * from dwd_f_crm_personnel_management where assign_type = 1 and`
  863. if mode == "A" {
  864. query += ` assign_level like "%A%"`
  865. } else if mode == "B" {
  866. query += ` assign_level like "%B%"`
  867. } else {
  868. query += ` assign_level like "%C%"`
  869. }
  870. data := TiDb.SelectBySql(query)
  871. if data != nil && len(*data) > 0 {
  872. saleData = *data
  873. sql := "select * from dwd_f_crm_clue_autodraw_record where clue_level = ?"
  874. countData := TiDb.SelectBySql(sql, mode)
  875. if countData != nil && len(*countData) > 0 {
  876. for _, v := range *data {
  877. isOk := false //判断是否有新员工
  878. for _, vv := range *countData {
  879. if common.Int64All(v["position_id"]) == common.Int64All(vv["position_id"]) {
  880. if common.IntAll(v["resign"]) == 0 {
  881. vv["status"] = 1
  882. } else {
  883. vv["status"] = 2
  884. }
  885. isOk = true
  886. }
  887. }
  888. if !isOk { //有新员工直接分给新员工
  889. positionId = common.Int64All(v["position_id"])
  890. saleName = common.ObjToString(v["name"])
  891. log.Println("新员工, ", positionId, saleName)
  892. rData := TiDb.FindOne("dwd_f_crm_clue_autodraw_record", map[string]interface{}{"clue_level": mode}, "", "count desc")
  893. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  894. "position_id": positionId,
  895. "clue_level": mode,
  896. "count": common.Int64All((*rData)["count"]),
  897. })
  898. break
  899. }
  900. }
  901. if positionId == 0 {
  902. res := int64(0)
  903. countres := 0
  904. for _, v := range *countData {
  905. if common.IntAll(v["status"]) == 1 {
  906. if FindUpperLimit(gconv.String(v["position_id"]), mode, false) {
  907. continue
  908. }
  909. if countres == 0 {
  910. res = common.Int64All(v["count"])
  911. positionId = common.Int64All(v["position_id"])
  912. } else {
  913. if common.Int64All(v["count"]) <= res {
  914. res = common.Int64All(v["count"])
  915. positionId = common.Int64All(v["position_id"])
  916. }
  917. }
  918. countres++
  919. }
  920. }
  921. log.Println(444, res)
  922. }
  923. } else {
  924. for _, kv := range *data {
  925. positionId1 := gconv.String(kv["position_id"])
  926. if !FindUpperLimit(positionId1, "", false) {
  927. positionId = common.Int64All(kv["position_id"])
  928. saleName = common.ObjToString(kv["name"])
  929. rData := TiDb.FindOne("dwd_f_crm_clue_autodraw_record", map[string]interface{}{"clue_level": mode}, "", "count desc")
  930. if rData != nil && len(*rData) > 0 {
  931. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  932. "position_id": positionId,
  933. "clue_level": mode,
  934. "count": common.Int64All((*rData)["count"]),
  935. })
  936. } else {
  937. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  938. "position_id": positionId,
  939. "clue_level": mode,
  940. "count": 0,
  941. })
  942. }
  943. break
  944. }
  945. }
  946. }
  947. for _, v := range *data {
  948. if positionId == common.Int64All(v["position_id"]) {
  949. seatNumber = common.ObjToString(v["seat_number"])
  950. saleName = common.ObjToString(v["name"])
  951. }
  952. }
  953. }
  954. return
  955. }
  956. func getPositionId(phone string) (positionId int64) {
  957. userData, ok := Mgo.FindOne("user", map[string]interface{}{"s_phone": phone})
  958. if ok && userData != nil && len(*userData) > 0 {
  959. userId := common.Int64All((*userData)["base_user_id"])
  960. positionData := Base.FindOne("base_position", map[string]interface{}{"type": 1, "ent_id": 25917, "user_id": userId}, "", "") //TODO ent_id
  961. if positionData != nil && len(*positionData) > 0 {
  962. positionId = common.Int64All((*positionData)["id"])
  963. }
  964. }
  965. return
  966. }
  967. func GetCompanyType(companyName string) (int, int) {
  968. //是否是集团
  969. isGroup, isCommerce := 0, 0
  970. if c := TiDb.CountBySql(`select count(1) from group_company_name where company_name=?`, companyName); c > 0 {
  971. isGroup = 1
  972. }
  973. //是否在工商库
  974. if c := MgoQyxy.Count("qyxy_std", map[string]interface{}{"company_name": companyName, "company_type": map[string]interface{}{"$ne": "个体工商户"}}); c > 0 {
  975. isCommerce = 1
  976. }
  977. return isGroup, isCommerce
  978. }
  979. // 查询是否达上限
  980. func FindUpperLimit(positionId string, level string, isAdd bool) bool {
  981. if positionId == "" {
  982. return false
  983. }
  984. isFull := false
  985. isFull = TiDb.CountBySql(`select count(1) from dwd_f_crm_clue_info where position_id=? and is_assign=1 and trailstatus != '08' `, positionId) >= cfg.AllocationCap
  986. if isFull && isAdd && level != "" {
  987. TiDb.UpdateOrDeleteBySql(`update dwd_f_crm_clue_autodraw_record set count = count + 1 where position_id = ? and clue_level = ?`, positionId, level)
  988. }
  989. return isFull
  990. }
  991. func getSeatNumberPositionId(seatNumber string) (positionId int64) {
  992. saleData := TiDb.FindOne("dwd_f_crm_personnel_management", map[string]interface{}{"seat_number": seatNumber}, "", "")
  993. if saleData != nil && len(*saleData) > 0 {
  994. positionId = common.Int64All((*saleData)["position_id"])
  995. }
  996. return
  997. }