clue.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. package service
  2. import (
  3. "database/sql"
  4. "log"
  5. "math"
  6. "sync"
  7. "time"
  8. "app.yhyue.com/moapp/jybase/date"
  9. common "app.yhyue.com/moapp/jybase/common"
  10. . "bp.jydev.jianyu360.cn/BaseService/biService/entity"
  11. "bp.jydev.jianyu360.cn/BaseService/biService/rpc/biservice"
  12. )
  13. func DistributeClue(this *biservice.DistributeClueReq) *biservice.AddProjectResp {
  14. count, status := DistributeClueSync(this)
  15. log.Println("分配数量 ", count)
  16. return &biservice.AddProjectResp{
  17. ErrorCode: 0,
  18. Data: &biservice.AddProject{
  19. Status: int64(status),
  20. Count: int64(count),
  21. },
  22. }
  23. }
  24. func DistributeClueSync(this *biservice.DistributeClueReq) (int, int) {
  25. if DistributeLock.TryLock() {
  26. defer DistributeLock.Unlock()
  27. saleMap, count := map[string]map[string]interface{}{}, 0
  28. saleData := JyBiTidb.SelectBySql("select * from jy_salesperson_info where is_complete = 1 or is_complete = 0")
  29. if saleData != nil && len(*saleData) > 0 {
  30. for _, v := range *saleData {
  31. name := common.ObjToString(v["name"])
  32. saleMap[name] = v
  33. }
  34. }
  35. for _, data := range this.Datas {
  36. seatNumber := common.ObjToString(saleMap[data.Name]["seatNumber"])
  37. distributedCount := int(data.DistributedCount)
  38. if distributedCount > 0 {
  39. distributedArr := this.ClueIdList[count : count+distributedCount]
  40. count += distributedCount
  41. DistributeClueMore(saleMap, distributedArr, seatNumber, data.Name, data.PositionId, this.PositionId)
  42. }
  43. }
  44. return count, 1
  45. } else {
  46. return 0, 2
  47. }
  48. }
  49. func DistributeClueMore(saleMap map[string]map[string]interface{}, distributedArr []int64, seatNumber, name string, positionId, thispositionId int64) {
  50. wg := new(sync.WaitGroup)
  51. ch := make(chan bool, 20)
  52. for _, v := range distributedArr {
  53. wg.Add(1)
  54. ch <- true
  55. go func(v int64) {
  56. defer func() {
  57. wg.Done()
  58. <-ch
  59. }()
  60. clueData := JyBiTidb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"id": v}, "", "")
  61. nowTime := time.Now().Format(date.Date_Full_Layout)
  62. if clueData != nil && len(*clueData) > 0 {
  63. isAssign := common.IntAll((*clueData)["is_assign"])
  64. clueSeatNumber := common.ObjToString((*clueData)["seatNumber"])
  65. oldName := ""
  66. trailstatus := common.ObjToString((*clueData)["trailstatus"])
  67. if clueSeatNumber != "" {
  68. for _, s := range saleMap {
  69. if common.ObjToString(s["seatNumber"]) == clueSeatNumber {
  70. oldName = common.ObjToString(s["name"])
  71. }
  72. }
  73. }
  74. if isAssign == 1 {
  75. oldpositionId := common.Int64All((*clueData)["position_id"])
  76. updateClue := map[string]interface{}{
  77. "position_id": positionId,
  78. "seatNumber": seatNumber,
  79. "is_assign": 1,
  80. "updatetime": nowTime,
  81. "comeintime": nowTime,
  82. "comeinsource_private": 4,
  83. "level_open": nil,
  84. "clue_level": nil,
  85. "out_task_time": nil,
  86. "out_task_status": nil,
  87. "trail_time": nil,
  88. // "comeinsource_open": nil,
  89. }
  90. ok := JyBiTidb.Update("dwd_f_crm_clue_info", map[string]interface{}{"id": v}, updateClue)
  91. // ok := JyBiTidb.Update("dwd_f_crm_private_sea", map[string]interface{}{"clue_id": v}, map[string]interface{}{
  92. // "position_id": positionId,
  93. // "seatNumber": seatNumber,
  94. // "comeinsource": 4,
  95. // "comeintime": nowTime,
  96. // })
  97. if ok {
  98. JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  99. "clue_id": v,
  100. "position_id": positionId,
  101. "change_field": "position_id",
  102. "change_type": "所属人变更",
  103. "old_value": oldName,
  104. "new_value": name,
  105. "createtime": nowTime,
  106. "BCPCID": common.GetRandom(32),
  107. "operator_id": thispositionId,
  108. })
  109. JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  110. "clue_id": v,
  111. "position_id": oldpositionId,
  112. "change_field": "trailstatus",
  113. "change_type": "基本信息变更",
  114. "old_value": CodeTrail[trailstatus],
  115. "new_value": "流失",
  116. "createtime": nowTime,
  117. "BCPCID": common.GetRandom(32),
  118. "operator_id": thispositionId,
  119. })
  120. JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  121. "clue_id": v,
  122. "position_id": positionId,
  123. "change_field": "trailstatus",
  124. "change_type": "基本信息变更",
  125. "old_value": CodeTrail[trailstatus],
  126. "new_value": "新增",
  127. "createtime": nowTime,
  128. "BCPCID": common.GetRandom(32),
  129. "operator_id": thispositionId,
  130. })
  131. } else {
  132. log.Println("私海修改失败 ", v, positionId, seatNumber)
  133. }
  134. } else {
  135. updateClue := map[string]interface{}{
  136. "position_id": positionId,
  137. "seatNumber": seatNumber,
  138. "is_assign": 1,
  139. "updatetime": nowTime,
  140. "comeintime": nowTime,
  141. "comeinsource_private": 4,
  142. "is_task": 0,
  143. "taskstatus": 0,
  144. "level_open": nil,
  145. "clue_level": nil,
  146. "out_task_time": nil,
  147. "out_task_status": nil,
  148. "trail_time": nil,
  149. "next_trail_time": nil,
  150. // "comeinsource_open": nil,
  151. }
  152. if trailstatus != "08" {
  153. updateClue["trailstatus"] = "01"
  154. }
  155. ok := JyBiTidb.Update("dwd_f_crm_clue_info", map[string]interface{}{"id": v}, updateClue)
  156. // seaId := JyBiTidb.Insert("dwd_f_crm_private_sea", map[string]interface{}{
  157. // "clue_id": v,
  158. // "position_id": positionId,
  159. // "seatNumber": seatNumber,
  160. // "comeinsource": 4,
  161. // "comeintime": nowTime,
  162. // "is_task": 0,
  163. // // "task_time": nowTime,
  164. // // "tasktime": nowTime,
  165. // "taskstatus": 0,
  166. // // "tasksource": "线索批量分配",
  167. // })
  168. if ok {
  169. // JyBiTidb.Delete("dwd_f_crm_open_sea", map[string]interface{}{"clue_id": v})
  170. JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  171. "clue_id": v,
  172. "position_id": positionId,
  173. "change_field": "position_id",
  174. "change_type": "所属人变更",
  175. "old_value": "/",
  176. "new_value": name,
  177. "createtime": nowTime,
  178. "BCPCID": common.GetRandom(32),
  179. "operator_id": thispositionId,
  180. })
  181. if trailstatus != "08" {
  182. JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  183. "clue_id": v,
  184. "position_id": positionId,
  185. "change_field": "trailstatus",
  186. "change_type": "基本信息变更",
  187. "old_value": "商机线索",
  188. "new_value": "新增",
  189. "createtime": nowTime,
  190. "BCPCID": common.GetRandom(32),
  191. "operator_id": thispositionId,
  192. })
  193. JyBiTidb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  194. "clue_id": v,
  195. "position_id": positionId,
  196. "change_field": "trailstatus",
  197. "change_type": "基本信息变更",
  198. "old_value": CodeTrail[trailstatus],
  199. "new_value": "商机线索",
  200. "createtime": nowTime,
  201. "BCPCID": common.GetRandom(32),
  202. "operator_id": thispositionId,
  203. })
  204. }
  205. } else {
  206. log.Println("私海插入失败 ", v, positionId, seatNumber)
  207. }
  208. }
  209. }
  210. }(v)
  211. }
  212. wg.Wait()
  213. }
  214. func DrawClue(this *biservice.DrawClueReq) *biservice.AddProjectResp {
  215. count, status := DrawClueSync(this)
  216. log.Println("领取数量 ", count)
  217. return &biservice.AddProjectResp{
  218. ErrorCode: 0,
  219. Data: &biservice.AddProject{
  220. Status: int64(status),
  221. Count: int64(count),
  222. },
  223. }
  224. }
  225. func DrawClueSync(this *biservice.DrawClueReq) (int, int) {
  226. if DataLock.TryLock() {
  227. defer DataLock.Unlock()
  228. count1 := JyBiTidb.Count("dwd_f_crm_clue_info", map[string]interface{}{"level_open": 1, "is_assign": 0})
  229. count2 := JyBiTidb.Count("dwd_f_crm_clue_info", map[string]interface{}{"level_open": 2, "is_assign": 0})
  230. counts1, counts2, counts3 := int64(0), int64(0), int64(0)
  231. counts1 = int64(math.Ceil(float64(this.Count) / float64(10) * 5))
  232. if this.Count-counts1 == 0 {
  233. counts2 = 0
  234. counts3 = 0
  235. } else {
  236. counts2 = int64(math.Ceil(float64(this.Count) / float64(10) * 4))
  237. if this.Count-counts1-counts2 == 0 {
  238. counts3 = 0
  239. } else {
  240. counts3 = this.Count - counts1 - counts2
  241. }
  242. }
  243. if counts1 > count1 {
  244. counts2 += counts1 - count1
  245. counts1 = count1
  246. }
  247. if counts2 > count2 {
  248. counts3 += counts2 - count2
  249. counts2 = count2
  250. }
  251. log.Println(count1, count2)
  252. log.Println(counts1, counts2, counts3)
  253. return DrawClues(this.PositionId, counts1, counts2, counts3), 1
  254. } else {
  255. return 0, 2
  256. }
  257. }
  258. func DrawClues(positionId, count1, count2, count3 int64) int {
  259. data1, data2, data3, drawCount := &[]map[string]interface{}{}, &[]map[string]interface{}{}, &[]map[string]interface{}{}, 0
  260. if count1 > 0 {
  261. // data1 = JyBiTidb.Find("dwd_f_crm_clue_info", map[string]interface{}{"level_open": 1, "is_assign": 0}, "", "", 0, int(count1))
  262. data1 = JyBiTidb.SelectBySql(`SELECT max(c.createTime) as ctime,a.id,a.trailstatus FROM dwd_f_crm_clue_info a
  263. LEFT JOIN Call_Accounting.voice_record c ON c.CalledNo = a.phone
  264. WHERE a.level_open = ? AND a.is_assign = 0 AND a.uid !="" GROUP BY a.id ORDER BY ctime asc limit ?`, 1, count1)
  265. }
  266. if count2 > 0 {
  267. // data2 = JyBiTidb.Find("dwd_f_crm_clue_info", map[string]interface{}{"level_open": 2, "is_assign": 0}, "", "", 0, int(count2))
  268. data2 = JyBiTidb.SelectBySql(`SELECT max(c.createTime) as ctime,a.id,a.trailstatus FROM dwd_f_crm_clue_info a
  269. LEFT JOIN Call_Accounting.voice_record c ON c.CalledNo = a.phone
  270. WHERE a.level_open = ? AND a.is_assign = 0 AND a.uid !="" GROUP BY a.id ORDER BY ctime asc limit ?`, 2, count2)
  271. }
  272. if count3 > 0 {
  273. // data3 = JyBiTidb.Find("dwd_f_crm_clue_info", map[string]interface{}{"level_open": 3, "is_assign": 0}, "", "", 0, int(count3))
  274. data3 = JyBiTidb.SelectBySql(`SELECT max(c.createTime) as ctime,a.id,a.trailstatus FROM dwd_f_crm_clue_info a
  275. LEFT JOIN Call_Accounting.voice_record c ON c.CalledNo = a.phone
  276. WHERE a.level_open = ? AND a.is_assign = 0 AND a.uid !="" GROUP BY a.id ORDER BY ctime asc limit ?`, 3, count3)
  277. }
  278. nowTime := time.Now().Format("2006-01-02 15:04:05")
  279. seatNumber, name := getSeatNumber(positionId)
  280. if data1 != nil && len(*data1) > 0 {
  281. batchDraw(*data1, nowTime, seatNumber, name, positionId)
  282. drawCount += len(*data1)
  283. }
  284. if data2 != nil && len(*data2) > 0 {
  285. batchDraw(*data2, nowTime, seatNumber, name, positionId)
  286. drawCount += len(*data2)
  287. }
  288. if data3 != nil && len(*data3) > 0 {
  289. batchDraw(*data3, nowTime, seatNumber, name, positionId)
  290. drawCount += len(*data3)
  291. }
  292. return drawCount
  293. }
  294. func batchDraw(data []map[string]interface{}, nowTime, seatNumber, name string, positionId int64) {
  295. wg := new(sync.WaitGroup)
  296. ch := make(chan bool, 20)
  297. for _, v := range data {
  298. wg.Add(1)
  299. ch <- true
  300. go func(v map[string]interface{}) {
  301. defer func() {
  302. wg.Done()
  303. <-ch
  304. }()
  305. clueId := common.Int64All(v["id"])
  306. trailstatus := common.ObjToString(v["trailstatus"])
  307. if JyBiMysql.ExecTx("领取线索等", func(tx *sql.Tx) bool {
  308. updateClue := map[string]interface{}{
  309. "position_id": positionId,
  310. "seatNumber": seatNumber,
  311. "is_assign": 1,
  312. "updatetime": nowTime,
  313. "comeintime": nowTime,
  314. "comeinsource_private": 3,
  315. "is_task": 1,
  316. "task_time": nowTime,
  317. "tasktime": nowTime,
  318. "taskstatus": 0,
  319. "tasksource": "领取公海线索",
  320. "level_open": nil,
  321. "clue_level": nil,
  322. // "comeinsource_open": nil,
  323. }
  324. if trailstatus != "08" {
  325. updateClue["trailstatus"] = "01"
  326. }
  327. ok1 := JyBiTidb.UpdateByTx(tx, "dwd_f_crm_clue_info", map[string]interface{}{"id": clueId}, updateClue)
  328. // ok2 := JyBiTidb.DeleteByTx(tx, "dwd_f_crm_open_sea", map[string]interface{}{"clue_id": clueId})
  329. // seaId := JyBiTidb.InsertByTx(tx, "dwd_f_crm_private_sea", map[string]interface{}{
  330. // "clue_id": clueId,
  331. // "seatNumber": seatNumber,
  332. // "position_id": positionId,
  333. // "comeintime": nowTime,
  334. // "comeinsource": 3,
  335. // "is_task": 1,
  336. // "task_time": nowTime,
  337. // "tasktime": nowTime,
  338. // "taskstatus": 0,
  339. // "tasksource": "领取公海线索",
  340. // })
  341. recordId := JyBiTidb.InsertByTx(tx, "dwd_f_crm_clue_change_record", map[string]interface{}{
  342. "clue_id": clueId,
  343. "position_id": positionId,
  344. "change_field": "position_id",
  345. "change_type": "所属人变更",
  346. "old_value": "/",
  347. "new_value": name,
  348. "createtime": nowTime,
  349. "BCPCID": common.GetRandom(32),
  350. "operator_id": positionId,
  351. })
  352. recordId1 := JyBiTidb.InsertByTx(tx, "dwd_f_crm_clue_change_record", map[string]interface{}{
  353. "clue_id": clueId,
  354. "position_id": positionId,
  355. "change_type": "领取公海线索",
  356. "createtime": nowTime,
  357. "BCPCID": common.GetRandom(32),
  358. "operator_id": positionId,
  359. })
  360. recordId2 := JyBiTidb.InsertByTx(tx, "dwd_f_crm_clue_change_record", map[string]interface{}{
  361. "clue_id": clueId,
  362. "position_id": positionId,
  363. "change_type": "加入任务车",
  364. "new_value": "领取公海线索",
  365. "createtime": nowTime,
  366. "BCPCID": common.GetRandom(32),
  367. "operator_id": positionId,
  368. })
  369. recordId3, recordId4 := int64(0), int64(0)
  370. if trailstatus != "08" {
  371. recordId3 = JyBiTidb.InsertByTx(tx, "dwd_f_crm_clue_change_record", map[string]interface{}{
  372. "clue_id": clueId,
  373. "position_id": positionId,
  374. "change_field": "trailstatus",
  375. "change_type": "基本信息变更",
  376. "old_value": "商机线索",
  377. "new_value": "新增",
  378. "createtime": nowTime,
  379. "BCPCID": common.GetRandom(32),
  380. "operator_id": positionId,
  381. })
  382. recordId4 = JyBiTidb.InsertByTx(tx, "dwd_f_crm_clue_change_record", map[string]interface{}{
  383. "clue_id": clueId,
  384. "position_id": positionId,
  385. "change_field": "trailstatus",
  386. "change_type": "基本信息变更",
  387. "old_value": CodeTrail[trailstatus],
  388. "new_value": "商机线索",
  389. "createtime": nowTime,
  390. "BCPCID": common.GetRandom(32),
  391. "operator_id": positionId,
  392. })
  393. }
  394. return ok1 && recordId > 0 && recordId1 > 0 && recordId2 > 0 && recordId3 > -1 && recordId4 > -1
  395. }) {
  396. log.Println("领取线索成功")
  397. } else {
  398. log.Println("领取线索失败")
  399. }
  400. }(v)
  401. }
  402. wg.Wait()
  403. }
  404. func getSeatNumber(positionId int64) (seatNumber, name string) {
  405. positionData := JyTidb.FindOne("base_position", map[string]interface{}{"id": positionId}, "", "")
  406. if positionData != nil && len(*positionData) > 0 {
  407. userId := common.Int64All((*positionData)["user_id"])
  408. if userId > 0 {
  409. userData, ok := Mgo.FindOne("user", map[string]interface{}{"base_user_id": userId})
  410. if ok && userData != nil && len(*userData) > 0 {
  411. s_phone := common.ObjToString((*userData)["s_phone"])
  412. if s_phone == "" {
  413. s_phone = common.ObjToString((*userData)["s_m_phone"])
  414. }
  415. saleData := JyBiTidb.FindOne("jy_salesperson_info", map[string]interface{}{"phone": s_phone}, "", "")
  416. if saleData != nil && len(*saleData) > 0 {
  417. seatNumber = common.ObjToString((*saleData)["seatNumber"])
  418. name = common.ObjToString((*saleData)["name"])
  419. }
  420. }
  421. }
  422. }
  423. return
  424. }