jobutil.go 37 KB

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