jobutil.go 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439
  1. package main
  2. import (
  3. "app.yhyue.com/moapp/jybase/redis"
  4. "fmt"
  5. "log"
  6. "math"
  7. "strings"
  8. "time"
  9. "github.com/gogf/gf/v2/util/gconv"
  10. "app.yhyue.com/moapp/jybase/common"
  11. "app.yhyue.com/moapp/jybase/date"
  12. "app.yhyue.com/moapp/jybase/mongodb"
  13. )
  14. // 电销工单生成
  15. func rderAcceptance() {
  16. sql := fmt.Sprintf(`select * from order_acceptance where is_clue=2 and is_delete=1 order by propose_time `)
  17. //sql := fmt.Sprintf(`select * from order_acceptance where is_clue=2 and is_delete=1 and id = 333 order by propose_time `)
  18. data := WorkOrder.SelectBySql(sql)
  19. if data != nil && len(*data) > 0 {
  20. for _, v := range *data {
  21. acceptance_no := gconv.String(v["acceptance_no"])
  22. childrenArr := WorkOrder.Find("order_acceptance_children", map[string]interface{}{
  23. "acceptance_no": acceptance_no,
  24. }, "", "", -1, -1)
  25. if childrenArr != nil && len(*childrenArr) > 0 {
  26. company := ""
  27. phone := ""
  28. demand := ""
  29. name := ""
  30. product := ""
  31. for _, v1 := range *childrenArr {
  32. if gconv.String(v1["field_name"]) == "公司名称" {
  33. company = gconv.String(v1["field_value"])
  34. }
  35. if gconv.String(v1["field_name"]) == "联系方式num" {
  36. phone = gconv.String(v1["field_value"])
  37. }
  38. if gconv.String(v1["field_name"]) == "客户姓名" {
  39. name = gconv.String(v1["field_value"])
  40. }
  41. if gconv.String(v1["field_name"]) == "客户需求" {
  42. demand = gconv.String(v1["field_value"])
  43. }
  44. if gconv.String(v1["field_name"]) == "咨询产品" {
  45. product = gconv.String(v1["field_value"])
  46. }
  47. }
  48. if !WorkDataHandle(company, phone, demand, name, product, v) {
  49. log.Println("工单创建失败")
  50. }
  51. }
  52. }
  53. }
  54. }
  55. func WorkDataHandle(company, phone, demand, name, product string, acceptanceData map[string]interface{}) bool {
  56. uId := ""
  57. query := map[string]interface{}{}
  58. contactsData := TiDb.SelectBySql("select * from dwd_f_userbase_contacts where phone = ? and is_delete = 1", phone)
  59. if contactsData != nil && len(*contactsData) > 0 {
  60. if common.ObjToString((*contactsData)[0]["baseinfo_id"]) != "" {
  61. uId = common.ObjToString((*contactsData)[0]["baseinfo_id"])
  62. query["uid"] = uId
  63. }
  64. }
  65. if uId == "" {
  66. log.Println("用户信息不存在")
  67. return false
  68. }
  69. cluename := company
  70. if cluename == "" {
  71. cluename = phone //没有线索名,手机号代替
  72. }
  73. ok, data, saleData := false, map[string]interface{}{}, []map[string]interface{}{}
  74. isGroup, isCommerce := GetCompanyType(cluename)
  75. uCount, _ := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"uid": uId}, "", ""), true //查当前线索是否已存在
  76. if uCount != nil && len(*uCount) > 0 {
  77. isUpdate := gconv.Int64((*uCount)["is_artificially_modified"])
  78. if isUpdate == 1 {
  79. cluename = ""
  80. }
  81. clueId := gconv.Int64((*uCount)["id"])
  82. positionId := gconv.Int64((*uCount)["position_id"])
  83. trailstatus := gconv.String((*uCount)["trailstatus"])
  84. IS_TRANSFER := gconv.Int64((*uCount)["IS_TRANSFER"])
  85. if IS_TRANSFER == 1 {
  86. //客成处理
  87. //客成
  88. //生成客成数据
  89. customerMap := TiDb.FindOne("dwd_f_csm_customer_info", map[string]interface{}{
  90. "clue_id": clueId,
  91. }, "position_id,name", "")
  92. if customerMap != nil && len(*customerMap) > 0 {
  93. //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)
  94. WorkUpdateClue(*uCount, saleData, "", "", uId, "5", "169", "新增线索", "主动咨询客服留资客户", cluename, name, gconv.String((*uCount)["name"]), phone, "", "", "", "", "", "", gconv.String((*uCount)["seat_number"]), "", gconv.Int64((*uCount)["position_id"]), "", "", "", []string{}, "", isGroup, isCommerce, false, demand)
  95. data = map[string]interface{}{
  96. "type": "kc",
  97. "position_id": (*customerMap)["position_id"],
  98. "name": (*customerMap)["name"],
  99. }
  100. } else {
  101. log.Println("查询不到客成数据", clueId, uId)
  102. return false
  103. }
  104. TiDb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  105. "clue_id": clueId,
  106. "position_id": (*customerMap)["position_id"],
  107. "change_type": "加入任务车",
  108. "new_value": "咨询客服转客成",
  109. "createtime": time.Now().Format(date.Date_Full_Layout),
  110. "BCPCID": common.GetRandom(32),
  111. "operator_id": -1,
  112. })
  113. } else {
  114. if positionId == 0 {
  115. //线索变更
  116. ok, data, saleData = FindPosition(0, "", gconv.String(acceptanceData["creator_time"]))
  117. if !ok {
  118. log.Println(positionId, "用户查询失败")
  119. return false
  120. }
  121. WorkUpdateClue(*uCount, saleData, "", "", uId, "5", "169", "新增线索", "主动咨询客服留资客户", cluename, name, gconv.String(data["name"]), phone, "", "", "", "", "", "", gconv.String(data["seat_number"]), "", gconv.Int64(data["position_id"]), "", "", "", []string{}, "", isGroup, isCommerce, true, demand)
  122. } else {
  123. ok, data, saleData = FindPosition(positionId, trailstatus, gconv.String(acceptanceData["creator_time"]))
  124. if !ok {
  125. log.Println(positionId, "用户查询失败")
  126. return false
  127. }
  128. if gconv.Int64(data["position_id"]) == positionId {
  129. WorkUpdateClue(*uCount, saleData, "", "", 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)
  130. } else {
  131. WorkUpdateClue(*uCount, saleData, "", "", uId, "5", "169", "新增线索", "主动咨询客服留资客户", cluename, name, gconv.String(data["name"]), phone, "", "", "", "", "", "", gconv.String(data["seat_number"]), "", gconv.Int64(data["position_id"]), "", "", "", []string{}, "", isGroup, isCommerce, true, demand)
  132. }
  133. }
  134. }
  135. } else {
  136. //新增线索
  137. ok, data, _ = FindPosition(0, "", gconv.String(acceptanceData["creator_time"]))
  138. if !ok {
  139. return false
  140. }
  141. 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)
  142. }
  143. //工单生成
  144. ok1 := AddOrderWork(acceptanceData, data, product, phone, company)
  145. log.Println("工单创建", ok1, gconv.String(acceptanceData["acceptance_no"]))
  146. return true
  147. }
  148. func AddOrderWork(acceptanceData map[string]interface{}, userData map[string]interface{}, product, phone, company string) bool {
  149. nowTime := time.Now().Format(date.Date_Full_Layout)
  150. work_order_no := fmt.Sprintf("GD%s%s", time.Now().Format(date.Date_yyyyMMdd), FindNumber("gd"))
  151. productArr := []string{}
  152. for _, v := range strings.Split(product, ",") {
  153. switch ProductMap[v] {
  154. case "dk":
  155. continue
  156. default:
  157. productArr = append(productArr, v)
  158. }
  159. }
  160. two_type := "dx"
  161. if gconv.String(userData["type"]) == "kc" {
  162. two_type = "kc"
  163. }
  164. personMap := GetPerson(gconv.String(userData["position_id"]))
  165. if personMap == nil || len(personMap) == 0 {
  166. return false
  167. }
  168. orderWorkMap := map[string]interface{}{
  169. "work_order_no": work_order_no,
  170. "acceptance_no": gconv.String(acceptanceData["acceptance_no"]),
  171. "type": strings.Join(productArr, ","),
  172. "status": common.If(gconv.Int64(userData["orderStatus"]) == 0, 2, 1),
  173. "initiator_name": gconv.String(acceptanceData["creator_name"]),
  174. "initiator_position_id": gconv.String(acceptanceData["initiator_position_id"]),
  175. "current_name": common.If(gconv.Int64(userData["orderStatus"]) == 0, nil, userData["name"]),
  176. "current_position_id": common.If(gconv.Int64(userData["orderStatus"]) == 0, nil, userData["position_id"]),
  177. "history_name": common.If(gconv.Int64(userData["orderStatus"]) == 0, userData["name"], nil),
  178. "history_postion_id": common.If(gconv.Int64(userData["orderStatus"]) == 0, userData["position_id"], nil),
  179. "is_delete": 1,
  180. "creator_name": gconv.String(acceptanceData["creator_name"]),
  181. "creator_position_id": gconv.String(acceptanceData["creator_position_id"]),
  182. "creator_time": nowTime,
  183. "two_type": two_type,
  184. "department_no": gconv.String(personMap["deptId"]),
  185. "department_name": gconv.String(personMap["deptName"]),
  186. "update_time": common.If(gconv.Int64(userData["orderStatus"]) == 0, nowTime, nil),
  187. }
  188. ok3 := WorkOrder.Insert("order_work", orderWorkMap)
  189. if ok3 > 0 {
  190. status := 2
  191. if WorkOrder.Count("order_work", map[string]interface{}{
  192. "status": 1,
  193. "acceptance_no": gconv.String(acceptanceData["acceptance_no"]),
  194. }) > 0 {
  195. status = 1
  196. }
  197. WorkOrder.Update("order_acceptance", map[string]interface{}{
  198. "id": acceptanceData["id"],
  199. }, map[string]interface{}{
  200. "is_clue": 3,
  201. "status": status,
  202. "over_time": common.If(status == 1, nil, nowTime),
  203. })
  204. //日志添加
  205. approvalRecordMap := map[string]interface{}{
  206. "work_order_no": work_order_no,
  207. "status": common.If(gconv.Int64(userData["orderStatus"]) == 0, 3, 1),
  208. "new_status": common.If(gconv.Int64(userData["orderStatus"]) == 0, 2, nil),
  209. "handle_name": userData["name"],
  210. "handle_position_id": userData["position_id"],
  211. "handle_dept_id": gconv.String(personMap["deptId"]),
  212. "handle_dept_name": gconv.String(personMap["deptName"]),
  213. "creator_name": gconv.String(acceptanceData["creator_name"]),
  214. "creator_position_id": gconv.String(acceptanceData["initiator_position_id"]),
  215. "is_delete": 1,
  216. "creator_time": nowTime,
  217. "handle_time": common.If(gconv.Int64(userData["orderStatus"]) == 0, nowTime, nil),
  218. "update_name": common.If(gconv.Int64(userData["orderStatus"]) == 0, userData["name"], nil),
  219. "update_position_id": common.If(gconv.Int64(userData["orderStatus"]) == 0, userData["position_id"], nil),
  220. "update_time": common.If(gconv.Int64(userData["orderStatus"]) == 0, nowTime, nil),
  221. }
  222. WorkOrder.Insert("approval_record", approvalRecordMap)
  223. WorkMail(personMap,
  224. strings.Join(productArr, ","),
  225. gconv.Int64(common.If(gconv.Int64(userData["orderStatus"]) == 0, 2, 1)),
  226. gconv.String(personMap["name"]),
  227. gconv.String(acceptanceData["creator_name"]),
  228. nowTime,
  229. work_order_no,
  230. phone,
  231. company)
  232. return true
  233. }
  234. return false
  235. }
  236. // 本级以及上级管理员查询
  237. func GetPerson(positionId string) map[string]interface{} {
  238. person := map[string]interface{}{}
  239. positionArrMap := Base.SelectBySql(fmt.Sprintf(`select a.phone,b.id,b.ent_id from
  240. base_user a
  241. INNER JOIN base_position b
  242. on b.id=%s and b.user_id=a.id and b.type=1`,
  243. positionId))
  244. if positionArrMap == nil || len(*positionArrMap) == 0 {
  245. return map[string]interface{}{}
  246. }
  247. phone := gconv.String((*positionArrMap)[0]["phone"])
  248. entId := gconv.String((*positionArrMap)[0]["ent_id"])
  249. entUserArrMap := Mysql.SelectBySql(fmt.Sprintf(`SELECT
  250. a.name as name,a.mail as mail,b.dept_id as deptId,a.phone ,c.name as deptName
  251. FROM
  252. entniche_user a
  253. INNER JOIN entniche_department_user b ON a.ent_id =%s
  254. AND a.phone IN %s
  255. and a.id=b.user_id
  256. inner join entniche_department c on b.dept_id=c.id
  257. `, entId, fmt.Sprintf("(%s)", phone)))
  258. //商机管理员
  259. if entUserArrMap == nil || len(*entUserArrMap) == 0 {
  260. return map[string]interface{}{}
  261. }
  262. deptId := gconv.Int64((*entUserArrMap)[0]["deptId"])
  263. person = map[string]interface{}{
  264. "name": gconv.String((*entUserArrMap)[0]["name"]),
  265. "mail": gconv.String((*entUserArrMap)[0]["mail"]),
  266. "phone": gconv.String((*entUserArrMap)[0]["phone"]),
  267. "deptId": gconv.String((*entUserArrMap)[0]["deptId"]),
  268. "deptName": gconv.String((*entUserArrMap)[0]["deptName"]),
  269. }
  270. //本部门管理员查询
  271. depthMap := Mysql.SelectBySql(`SELECT
  272. c.name as name,c.mail as mail
  273. FROM
  274. entniche_department_user a
  275. INNER JOIN entniche_user_role b ON a.dept_id = ?
  276. AND a.user_id = b.user_id
  277. AND b.role_id !=""
  278. INNER JOIN entniche_user c ON a.user_id = c.id`, deptId)
  279. if depthMap != nil && len(*depthMap) > 0 {
  280. person["deptPersonName"] = gconv.String((*depthMap)[0]["name"])
  281. person["deptPersonMail"] = gconv.String((*depthMap)[0]["mail"])
  282. }
  283. //商机管理员查询
  284. superiorDepthMap := Mysql.SelectBySql(`SELECT
  285. c.*
  286. FROM
  287. entniche_department d
  288. INNER JOIN entniche_department_user a ON d.id = ?
  289. AND d.pid = a.dept_id
  290. INNER JOIN entniche_user_role b ON a.user_id = b.user_id
  291. AND b.role_id !=""
  292. INNER JOIN entniche_user c ON a.user_id = c.id`, deptId)
  293. if superiorDepthMap != nil && len(*superiorDepthMap) > 0 {
  294. person["superiorDepthPersonName"] = gconv.String((*superiorDepthMap)[0]["name"])
  295. person["superiorDepthPersonMail"] = gconv.String((*superiorDepthMap)[0]["mail"])
  296. }
  297. return person
  298. }
  299. // 编号查询
  300. func FindNumber(moudle string) string {
  301. today := time.Now().Format("2006-01-02")
  302. yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02")
  303. key := fmt.Sprintf("%s_%s", today, moudle)
  304. yesterdayKey := fmt.Sprintf("%s_%s", yesterday, moudle)
  305. if ok, _ := redis.Exists("newother", yesterdayKey); ok {
  306. //删除之前数据
  307. redis.Del("newother", yesterdayKey)
  308. }
  309. count := redis.Incr("newother", key)
  310. log.Println("编号获取", moudle, fmt.Sprintf("%04d", count))
  311. return fmt.Sprintf("%04d", count)
  312. }
  313. // 人员查询
  314. func GetAllocation(proportion1, proportion3 float64, deptCount1, deptCount3 int64, administrators1, administrators3 map[string]interface{}, creatorTime string) map[string]interface{} {
  315. log.Println("分配比例查询", proportion1, proportion3, deptCount1, deptCount3)
  316. if deptCount1 == 0 {
  317. return administrators1
  318. }
  319. if deptCount3 == 0 {
  320. return administrators3
  321. }
  322. nowAllocationRatio := math.Round(gconv.Float64(deptCount1 / deptCount3))
  323. if cfg.AllocationRatio == 0 {
  324. //重新计算
  325. cfg.AllocationRatio = math.Round(proportion1 / proportion3)
  326. cfg.AllocationTime = creatorTime
  327. common.WriteSysConfig(&cfg)
  328. log.Println("新增计算比例", cfg.AllocationRatio)
  329. return administrators1
  330. } else {
  331. if nowAllocationRatio == cfg.AllocationRatio {
  332. //重新计算
  333. cfg.AllocationRatio = math.Round(proportion1 / proportion3)
  334. cfg.AllocationTime = creatorTime
  335. common.WriteSysConfig(&cfg)
  336. return administrators1
  337. }
  338. }
  339. if nowAllocationRatio > cfg.AllocationRatio {
  340. return administrators3
  341. } else {
  342. return administrators1
  343. }
  344. //达到比例也重新计算
  345. }
  346. func FindPosition(positionId int64, trailstatus, creatorTime string) (bool, map[string]interface{}, []map[string]interface{}) {
  347. allData := []map[string]interface{}{}
  348. //查询两个部门高级管理员
  349. //查询两个部门所有人员标识
  350. //电销三部
  351. userData1 := TiDb.SelectBySql(`SELECT
  352. a.position_id,
  353. a.name,
  354. b.seat_number,
  355. b.role_id,
  356. a.bi_pcode,
  357. a.dept_name
  358. FROM
  359. dwd_d_crm_department_level_succbi a
  360. INNER JOIN dwd_f_crm_personnel_management b ON a.resign = 0 and b.resign = 0
  361. AND a.dept_name LIKE "%电销部%"
  362. AND a.position_id = b.position_id`)
  363. userData3 := TiDb.SelectBySql(`SELECT
  364. a.position_id,
  365. a.name,
  366. b.seat_number,
  367. b.role_id,
  368. a.bi_pcode,
  369. a.dept_name
  370. FROM
  371. dwd_d_crm_department_level_succbi a
  372. INNER JOIN dwd_f_crm_personnel_management b ON a.resign = 0 and b.resign = 0
  373. AND a.resign = 0
  374. AND a.dept_name LIKE "%销售三部"
  375. AND a.position_id = b.position_id`)
  376. if userData3 == nil || len(*userData3) == 0 || userData1 == nil || len(*userData1) == 0 {
  377. return false, map[string]interface{}{}, allData
  378. }
  379. //一部管理员信息
  380. administrators1 := map[string]interface{}{}
  381. //三部管理员信息
  382. administrators3 := map[string]interface{}{}
  383. //返回当前人信息
  384. administrators := map[string]interface{}{}
  385. //电销一部
  386. deptNameMap1 := map[string]interface{}{}
  387. deptNameMap3 := map[string]interface{}{}
  388. proportion1 := float64(0)
  389. proportion3 := float64(0)
  390. for _, v := range *userData3 {
  391. v["type"] = 3
  392. id := gconv.Int64(v["position_id"])
  393. roleId := gconv.Int64(v["role_id"])
  394. if id == positionId {
  395. administrators = v
  396. }
  397. if roleId == 8 {
  398. v["orderStatus"] = 2
  399. administrators3 = v
  400. } else if roleId == 3 {
  401. proportion3 += 0.5
  402. } else {
  403. proportion3 += 1
  404. }
  405. deptNameMap3[gconv.String(v["bi_pcode"])] = true
  406. allData = append(allData, v)
  407. }
  408. for _, v := range *userData1 {
  409. v["type"] = 1
  410. id := gconv.Int64(v["position_id"])
  411. roleId := gconv.Int64(v["role_id"])
  412. if id == positionId {
  413. administrators = v
  414. }
  415. if roleId == 8 {
  416. v["orderStatus"] = 2
  417. administrators1 = v
  418. } else if roleId == 3 {
  419. proportion1 += 0.5
  420. } else {
  421. proportion1 += 1
  422. }
  423. deptNameMap1[gconv.String(v["bi_pcode"])] = true
  424. allData = append(allData, v)
  425. }
  426. if positionId != 0 {
  427. if administrators == nil || len(administrators) == 0 {
  428. return false, map[string]interface{}{}, allData
  429. }
  430. positiontype := gconv.Int64(administrators["type"])
  431. if trailstatus == "01" {
  432. switch positiontype {
  433. case 1:
  434. //找他上级
  435. administrators = administrators1
  436. case 3:
  437. //找他上级
  438. administrators = administrators3
  439. }
  440. return true, administrators, allData
  441. } else {
  442. return true, administrators, allData
  443. }
  444. }
  445. //按照比例分配选择一部还是三部
  446. //一部查询
  447. deptCount1 := CalculateProportion(deptNameMap1)
  448. //三部查询
  449. deptCount3 := CalculateProportion(deptNameMap3)
  450. return true, GetAllocation(proportion1, proportion3, deptCount1, deptCount3, administrators1, administrators3, creatorTime), allData
  451. log.Println("电销信息获取失败", positionId)
  452. return false, map[string]interface{}{}, allData
  453. }
  454. func CalculateProportion(deptNameMap map[string]interface{}) int64 {
  455. deptNameStr := ""
  456. for k := range deptNameMap {
  457. if deptNameStr == "" {
  458. deptNameStr = k
  459. } else {
  460. deptNameStr = fmt.Sprintf("%s,%s", deptNameStr, k)
  461. }
  462. }
  463. if deptNameStr == "" {
  464. return int64(0)
  465. }
  466. count := int64(0)
  467. sql := fmt.Sprintf(`SELECT
  468. sum(1) as count
  469. FROM
  470. order_work a
  471. INNER JOIN approval_record b ON a.creator_time >= "%s"
  472. AND FIND_IN_SET( a.department_no , "%s")
  473. AND a.work_order_no = b.work_order_no
  474. and (b.new_status!= 1 or b.new_status is null )
  475. `, cfg.AllocationTime, deptNameStr)
  476. data := WorkOrder.SelectBySql(sql)
  477. if data != nil && len(*data) > 0 {
  478. count = gconv.Int64((*data)[0]["count"])
  479. }
  480. return count
  481. }
  482. // 未支付订单 30分钟一次
  483. func orders() {
  484. //一个小时未支付进入线索 A
  485. log.Println("未支付订单定时任务开始")
  486. lastOrderId := cfg.LastOrderId
  487. selectTimeStart := time.Unix(time.Now().Unix()-7200, 0).Format(date.Date_Full_Layout)
  488. selectTimeEnd := time.Unix(time.Now().Unix()-3600, 0).Format(date.Date_Full_Layout)
  489. sql := fmt.Sprintf(`select * from dataexport_order where create_time <= "%s" and create_time >= "%s" and id > %s`, selectTimeEnd, selectTimeStart, fmt.Sprint(lastOrderId))
  490. data := Mysql.SelectBySql(sql)
  491. if data != nil && *data != nil && len(*data) > 0 {
  492. for _, v := range *data {
  493. order_status := common.IntAll(v["order_status"])
  494. is_backstage_order := common.IntAll(v["is_backstage_order"])
  495. product_type_str1 := `"大会员","VIP订阅","数据流量包","历史数据"`
  496. product_type := common.ObjToString(v["product_type"])
  497. if order_status == 0 && is_backstage_order == 0 && strings.Contains(product_type_str1, product_type) {
  498. ok1, ok2 := FormatData(v, "orders")
  499. if !ok1 {
  500. common.WriteSysConfig(&cfg)
  501. log.Println("线索卡点", "orders", v, selectTimeEnd, selectTimeStart)
  502. } else {
  503. if !ok2 {
  504. log.Println("用户分配已达上限", "orders", v, selectTimeEnd, selectTimeStart)
  505. common.WriteSysConfig(&cfg)
  506. }
  507. }
  508. }
  509. cfg.LastOrderId = common.IntAll(v["id"])
  510. }
  511. }
  512. common.WriteSysConfig(&cfg)
  513. log.Println("未支付订单定时任务结束")
  514. }
  515. func readClue() {
  516. log.Println("读表进线索定时任务开始")
  517. lastReadClueTime := cfg.LastReadClueTime
  518. sql := fmt.Sprintf(`select * from clue_info where updatetime > "%s" order by updatetime asc`, fmt.Sprint(lastReadClueTime))
  519. data := TiDb.SelectBySql(sql)
  520. if data != nil && *data != nil && len(*data) > 0 {
  521. for _, v := range *data {
  522. ok1, ok2 := FormatData(v, "readClue")
  523. if !ok1 {
  524. common.WriteSysConfig(&cfg)
  525. log.Println("线索卡点", "readClue", v, lastReadClueTime)
  526. } else {
  527. if !ok2 {
  528. log.Println("用户分配已达上限", "readClue", v, lastReadClueTime)
  529. common.WriteSysConfig(&cfg)
  530. }
  531. }
  532. cfg.LastReadClueTime = common.ObjToString(v["updatetime"])
  533. }
  534. }
  535. common.WriteSysConfig(&cfg)
  536. log.Println("读表进线索定时任务结束")
  537. }
  538. // 新注册用户 5分钟一次
  539. func users() {
  540. //判断节假日
  541. runOk := getRunOk()
  542. if !runOk {
  543. log.Println("不是工作日,任务暂停")
  544. return
  545. }
  546. //新用户注册后5分钟内进入线索 C
  547. log.Println("新注册用户定时任务开始")
  548. selectTimeEnd := cfg.LastUserId
  549. sql := fmt.Sprintf(`select * from dwd_f_userbase_baseinfo where createtime > "%s" and (s_platform != 'xcx' or s_platform is NULL) and source = "0101" and status != 2 order by createtime asc`, selectTimeEnd)
  550. data := TiDb.SelectBySql(sql)
  551. if data != nil && *data != nil && len(*data) > 0 {
  552. for k, v := range *data {
  553. //判断用户是否有小程序切使用过剑鱼其他产品
  554. createtime := common.ObjToString(v["createtime"])
  555. ok1, ok2 := FormatData(v, "users")
  556. if !ok1 {
  557. log.Println("线索卡点", "users", v, selectTimeEnd)
  558. } else {
  559. if !ok2 {
  560. log.Println("用户分配已达上限", "users", v, selectTimeEnd)
  561. }
  562. }
  563. if k == len(*data)-1 {
  564. cfg.LastUserId = createtime
  565. }
  566. }
  567. }
  568. common.WriteSysConfig(&cfg)
  569. selectXcxTimeEnd := cfg.LastXcxUserId
  570. xcxSql := fmt.Sprintf(`SELECT DISTINCT
  571. aa.mgo_id as userId,
  572. cc.NAME as industry ,
  573. aa.phone,
  574. IF
  575. ( aa.phone_time IS NULL, aa.create_time, aa.phone_time ) as time
  576. FROM
  577. debris_product.miniprogram_user aa
  578. INNER JOIN debris_product.miniprogram bb ON (
  579. aa.phone <> ''
  580. AND
  581. IF
  582. ( aa.phone_time IS NULL, aa.create_time, aa.phone_time ) > '%s'
  583. AND aa.miniprogram_code = bb.CODE
  584. )
  585. INNER JOIN debris_product.industry cc ON ( bb.industry_code = cc.CODE )
  586. WHERE
  587. NOT EXISTS (
  588. SELECT
  589. 1
  590. FROM
  591. debris_product.miniprogram_user a
  592. INNER JOIN debris_product.miniprogram b ON (
  593. aa.unionid = a.unionid
  594. AND aa.miniprogram_code = a.miniprogram_code
  595. AND aa.id != a.id
  596. AND
  597. IF
  598. ( a.phone_time IS NULL, a.create_time, a.phone_time ) <= '%s'
  599. AND a.miniprogram_code = b.CODE
  600. )
  601. INNER JOIN debris_product.miniprogram_user c ON ( a.unionid = c.unionid AND b.CODE = c.miniprogram_code ))
  602. ORDER BY time
  603. `, selectXcxTimeEnd, selectXcxTimeEnd)
  604. xcxData := debrisProductMysql.SelectBySql(xcxSql)
  605. if xcxData != nil && *xcxData != nil && len(*xcxData) > 0 {
  606. for k, v := range *xcxData {
  607. //判断用户是否有小程序切使用过剑鱼其他产品
  608. //判断uid
  609. uId := ""
  610. for i := 0; i < 10; i++ {
  611. phone := common.ObjToString(v["phone"])
  612. contactsData := TiDb.SelectBySql("select * from dwd_f_userbase_contacts where phone = ? and is_delete = 1", phone)
  613. if contactsData != nil && len(*contactsData) > 0 {
  614. if common.ObjToString((*contactsData)[0]["baseinfo_id"]) != "" {
  615. uId = common.ObjToString((*contactsData)[0]["baseinfo_id"])
  616. }
  617. }
  618. if uId == "" {
  619. time.Sleep(1 * time.Minute)
  620. } else {
  621. break
  622. }
  623. }
  624. updatetime := common.ObjToString(v["time"])
  625. if uId == "" {
  626. cfg.LastXcxUserId = updatetime
  627. continue
  628. }
  629. ok1, ok2 := FormatData(v, "xcxusers")
  630. if !ok1 {
  631. common.WriteSysConfig(&cfg)
  632. log.Println("小程序用户分配线索卡点", "xcxusers", v, selectXcxTimeEnd)
  633. } else {
  634. if !ok2 {
  635. log.Println("小程序用户分配已达上限", "xcxusers", v, selectXcxTimeEnd)
  636. common.WriteSysConfig(&cfg)
  637. }
  638. }
  639. if k == len(*xcxData)-1 {
  640. cfg.LastXcxUserId = updatetime
  641. }
  642. }
  643. }
  644. common.WriteSysConfig(&cfg)
  645. log.Println("新注册用户定时任务结束")
  646. }
  647. // 留资 5分钟一次
  648. func saleLeads() {
  649. //判断节假日
  650. runOk := getRunOk()
  651. if !runOk {
  652. log.Println("不是工作日,任务暂停")
  653. return
  654. }
  655. //留资后5分钟内进入线索
  656. //分为免费留资和付费留资 付费B 免费C
  657. log.Println("用户留资定时任务开始")
  658. session := Mgo.GetMgoConn()
  659. lastId := cfg.LastId
  660. defer func() {
  661. Mgo.DestoryMongoConn(session)
  662. }()
  663. query := map[string]interface{}{}
  664. if lastId != "" {
  665. query["_id"] = map[string]interface{}{"$gt": mongodb.StringTOBsonId(lastId)}
  666. }
  667. log.Println("query :", query)
  668. iter := session.DB(db.Mgo.DbName).C("saleLeads").Find(&query).Sort("_id").Iter()
  669. thisData := map[string]interface{}{}
  670. for {
  671. if !iter.Next(&thisData) {
  672. break
  673. }
  674. sourceCode := common.ObjToString(thisData["source"])
  675. if sourceCode == "" {
  676. log.Println("留资没有source", thisData)
  677. continue
  678. }
  679. //
  680. filterArr := []string{"-pc", "-app", "-wx", "-h5"}
  681. sourceMap := map[string]string{}
  682. saleSource := TiDb.SelectBySql(`SELECT source,name FROM d_saleleads_code WHERE (department LIKE '%大客户%' or department LIKE '%市场组%' or department LIKE '%咨询组%') AND is_delete = 1`)
  683. if saleSource != nil && len(*saleSource) > 0 {
  684. for _, v := range *saleSource {
  685. source := common.ObjToString(v["source"])
  686. name := common.ObjToString(v["name"])
  687. for _, s := range filterArr {
  688. name = strings.ReplaceAll(name, s, "")
  689. }
  690. sourceMap[source] = name
  691. }
  692. }
  693. if sourceMap[sourceCode] != "" {
  694. continue
  695. }
  696. ok1, ok2 := FormatData(thisData, "saleLeads")
  697. if !ok1 {
  698. log.Println("线索卡点", "saleLeads", thisData, lastId)
  699. } else {
  700. if !ok2 {
  701. log.Println("用户分配已达上限", "saleLeads", thisData, lastId)
  702. }
  703. }
  704. cfg.LastId = mongodb.BsonIdToSId(thisData["_id"])
  705. }
  706. common.WriteSysConfig(&cfg)
  707. log.Println("用户留资定时任务结束")
  708. }
  709. func userbase() {
  710. log.Println("userbase定时任务开始")
  711. selectTimeEnd := time.Unix(time.Now().Unix()-1800, 0).Format("2006-01-02 15:04:05")
  712. 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)
  713. data := TiDb.SelectBySql(sql)
  714. if data != nil && *data != nil && len(*data) > 0 {
  715. for _, v := range *data {
  716. phone := common.ObjToString(v["phone"])
  717. uId := common.ObjToString(v["uid"])
  718. userId := common.ObjToString(v["userid"])
  719. //判断用户是否有小程序切使用过剑鱼其他产品
  720. s_platform := gconv.String(v["s_platform"])
  721. login_positionid := gconv.Int64(v["login_positionid"])
  722. if s_platform == "xcx" && login_positionid == 0 {
  723. log.Println(phone, uId, userId, "用户是否有小程序且未使用过剑鱼其他产品")
  724. continue
  725. }
  726. registedate := common.ObjToString(v["l_registedate"])
  727. name := common.ObjToString(v["name"])
  728. nowTime := time.Now().Format(date.Date_Full_Layout)
  729. source := common.ObjToString(v["source"])
  730. if phone != "" {
  731. contactsData := TiDb.SelectBySql("select * from dwd_f_userbase_contacts where phone = ? and is_delete = 1", phone)
  732. if contactsData == nil || len(*contactsData) == 0 {
  733. contactsData2 := TiDb.SelectBySql("select * from dwd_f_userbase_contacts where baseinfo_id = ? and is_delete = 1", uId)
  734. if contactsData2 != nil && len(*contactsData2) > 0 {
  735. log.Println("userbase uid不为空 新增通讯录", uId)
  736. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  737. "status": 1,
  738. "is_delete": 1,
  739. "createtime": nowTime,
  740. "updatetime": nowTime,
  741. "phone": phone,
  742. "baseinfo_id": uId,
  743. "SOURCE": source,
  744. })
  745. } else {
  746. registedates, _ := time.Parse(date.Date_Full_Layout, registedate)
  747. count := TiDb.CountBySql("select count(1) as count from dwd_f_crm_clue_info where uid = ?", uId)
  748. log.Println("userbase uid 线索数量 ", count)
  749. log.Println("userbase uid 注册时间 ", registedates)
  750. if time.Now().Unix()-registedates.Unix() > int64(db.RegTimes)*86400 {
  751. if count == 0 {
  752. clueId := int64(0)
  753. sql := fmt.Sprintf(`select * from freeClubSign where mogUserId="%s" and sub_again_date > "%s" `, userId, selectTimeEnd)
  754. data := BiService.SelectBySql(sql)
  755. if len(*data) > 0 && userId != "" {
  756. clueId = TiDb.Insert("dwd_f_crm_clue_info", map[string]interface{}{
  757. "userid": userId,
  758. "uid": uId,
  759. "is_assign": 0,
  760. "comeintime": nowTime,
  761. "createtime": nowTime,
  762. "updatetime": nowTime,
  763. "cluename": phone,
  764. "top_cluetype": "532",
  765. "sub_cluetype": "670",
  766. "trailstatus": "01",
  767. "name": name,
  768. "phone": phone,
  769. "comeintime_open": nowTime,
  770. "comeinsource_open": 1,
  771. "FREEZE_TIME": nowTime,
  772. })
  773. } else {
  774. clueId = TiDb.Insert("dwd_f_crm_clue_info", map[string]interface{}{
  775. "userid": userId,
  776. "uid": uId,
  777. "is_assign": 0,
  778. "comeintime": nowTime,
  779. "createtime": nowTime,
  780. "updatetime": nowTime,
  781. "cluename": phone,
  782. "top_cluetype": "532",
  783. "sub_cluetype": "475",
  784. "trailstatus": "01",
  785. "name": name,
  786. "phone": phone,
  787. "comeintime_open": nowTime,
  788. "comeinsource_open": 1,
  789. "FREEZE_TIME": nowTime,
  790. })
  791. }
  792. if clueId > 0 {
  793. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  794. "status": 1,
  795. "is_delete": 1,
  796. "createtime": nowTime,
  797. "updatetime": nowTime,
  798. "phone": phone,
  799. "baseinfo_id": uId,
  800. "SOURCE": source,
  801. })
  802. TiDb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  803. "clue_id": clueId,
  804. "position_id": -1,
  805. "change_type": "创建线索",
  806. "new_value": "系统自动创建",
  807. "createtime": nowTime,
  808. "BCPCID": common.GetRandom(32),
  809. "operator_id": -1,
  810. })
  811. }
  812. } else {
  813. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  814. "status": 1,
  815. "is_delete": 1,
  816. "createtime": nowTime,
  817. "updatetime": nowTime,
  818. "phone": phone,
  819. "baseinfo_id": uId,
  820. "SOURCE": source,
  821. })
  822. }
  823. } else {
  824. if count == 0 {
  825. ok1, ok2 := FormatData(v, "users")
  826. if !ok1 {
  827. common.WriteSysConfig(&cfg)
  828. log.Println("线索卡点", "userbase uid", v, uId)
  829. } else {
  830. if !ok2 {
  831. log.Println("用户分配已达上限", "userbase uid", v, uId)
  832. common.WriteSysConfig(&cfg)
  833. }
  834. }
  835. } else {
  836. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  837. "status": 1,
  838. "is_delete": 1,
  839. "createtime": nowTime,
  840. "updatetime": nowTime,
  841. "phone": phone,
  842. "baseinfo_id": uId,
  843. "SOURCE": source,
  844. })
  845. }
  846. }
  847. }
  848. }
  849. }
  850. }
  851. }
  852. log.Println("userbase定时任务结束")
  853. }
  854. func getRunOk() bool {
  855. currentTime, runOk := time.Now(), false
  856. if currentTime.Weekday() == time.Sunday {
  857. isok := false
  858. for k, v := range DateMap {
  859. if currentTime.Format(date.Date_Short_Layout) == k && v == 2 {
  860. isok = true
  861. }
  862. }
  863. if isok {
  864. runOk = true
  865. }
  866. } else {
  867. isok := true
  868. for k, v := range DateMap {
  869. if currentTime.Format(date.Date_Short_Layout) == k && v == 1 {
  870. isok = false
  871. }
  872. }
  873. if isok {
  874. runOk = true
  875. }
  876. }
  877. return runOk
  878. }
  879. func getAreaCode(userId string) (code string) {
  880. followData := Base.Find("follow_project_monitor", map[string]interface{}{"s_userid": userId}, "", "", -1, -1)
  881. sidArr := []string{}
  882. if followData != nil && len(*followData) > 0 {
  883. for _, v := range *followData {
  884. infoId := common.ObjToString(v["s_id"])
  885. sidArr = append(sidArr, infoId)
  886. }
  887. }
  888. if len(sidArr) > 0 {
  889. query := `{"query": {"bool": {"must": [{"terms": {"_id": ["%s"]}}],"must_not": [],"should": []}}}`
  890. query = fmt.Sprintf(query, strings.Join(sidArr, `","`))
  891. biddingData := Es.Get("bidding", "bidding", query)
  892. if biddingData != nil && len(*biddingData) > 0 {
  893. codeMap := map[string]string{}
  894. codeArr := []string{}
  895. for _, v := range *biddingData {
  896. area := common.ObjToString(v["area"])
  897. address := common.ObjToString(v["city"])
  898. if address == "" {
  899. address = area
  900. }
  901. codeMap[address] = AreaCode[address]
  902. }
  903. if len(codeMap) > 0 {
  904. for _, v := range codeMap {
  905. codeArr = append(codeArr, v)
  906. }
  907. }
  908. if len(codeArr) > 0 {
  909. code = strings.Join(codeArr, ",")
  910. }
  911. }
  912. }
  913. log.Println("code ", code)
  914. return
  915. }
  916. func getClueType(item string, data map[string]interface{}, sourceCode string, sourceId int64) (pcode, code, level, topname, subname string) {
  917. if item == "orders" {
  918. productType := common.ObjToString(data["product_type"])
  919. pcode = "1"
  920. level = "A"
  921. topname = "提交订单未支付"
  922. if productType == "VIP订阅" {
  923. code = "6"
  924. subname = "超级订阅"
  925. } else if productType == "大会员" {
  926. code = "7"
  927. subname = "大会员"
  928. } else if productType == "数据流量包" {
  929. code = "8"
  930. subname = "数据流量包"
  931. } else if productType == "历史数据" {
  932. code = "9"
  933. subname = "数据自助导出"
  934. }
  935. } else if item == "users" {
  936. pcode = "4"
  937. code = "154"
  938. level = "C"
  939. topname = "新增注册"
  940. subname = "新增注册用户"
  941. } else if item == "message" {
  942. pcode = "532"
  943. code = "477"
  944. level = "B"
  945. topname = "其他"
  946. subname = "机器人客服主动咨询"
  947. } else if item == "readClue" {
  948. level = "A"
  949. topname = "超级订阅临期用户"
  950. pcode = "614"
  951. if sourceId == 1 {
  952. code = "615"
  953. subname = "60天后到期"
  954. } else if sourceId == 2 {
  955. code = "616"
  956. subname = "45天后到期"
  957. } else if sourceId == 3 {
  958. code = "617"
  959. subname = "15天后到期"
  960. } else {
  961. code = "618"
  962. subname = "7天后到期"
  963. }
  964. } else if item == "xcxusers" {
  965. level = "S"
  966. pcode = "532"
  967. code = "477"
  968. topname = "其他"
  969. switch sourceCode {
  970. case "环境采购":
  971. pcode = "532"
  972. code = "696"
  973. subname = `首次使用“环境”小程序`
  974. case "物业":
  975. pcode = "532"
  976. code = "693"
  977. subname = `首次使用“物业”小程序`
  978. case "印务商机":
  979. pcode = "532"
  980. code = "697"
  981. subname = `首次使用“印务”小程序`
  982. case "家具":
  983. pcode = "532"
  984. code = "695"
  985. subname = `首次使用“家具”小程序`
  986. case "车辆租赁":
  987. pcode = "532"
  988. code = "694"
  989. subname = `首次使用“车辆”小程序`
  990. }
  991. } else if item == "allocation" {
  992. pcode = "532"
  993. code = "671"
  994. level = "D"
  995. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  996. if pcodeData != nil && len(*pcodeData) > 0 {
  997. topname = common.ObjToString((*pcodeData)["name"])
  998. }
  999. pcodeData = TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": code}, "", "")
  1000. if pcodeData != nil && len(*pcodeData) > 0 {
  1001. subname = common.ObjToString((*pcodeData)["name"])
  1002. }
  1003. } else if item == "rebind" {
  1004. pcode = "532"
  1005. code = "670"
  1006. level = "D"
  1007. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  1008. if pcodeData != nil && len(*pcodeData) > 0 {
  1009. topname = common.ObjToString((*pcodeData)["name"])
  1010. }
  1011. pcodeData = TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": code}, "", "")
  1012. if pcodeData != nil && len(*pcodeData) > 0 {
  1013. subname = common.ObjToString((*pcodeData)["name"])
  1014. }
  1015. } else {
  1016. if sourceCode != "" {
  1017. codeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"source": sourceCode}, "", "")
  1018. if codeData != nil && len(*codeData) > 0 {
  1019. pcode = common.ObjToString((*codeData)["pcode"])
  1020. code = common.ObjToString((*codeData)["code"])
  1021. level = common.ObjToString((*codeData)["clue_level"])
  1022. subname = common.ObjToString((*codeData)["name"])
  1023. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  1024. if pcodeData != nil && len(*pcodeData) > 0 {
  1025. topname = common.ObjToString((*pcodeData)["name"])
  1026. }
  1027. }
  1028. }
  1029. }
  1030. return
  1031. }
  1032. // 获取自动分配的人
  1033. func autoDraw(mode, cluename, phone string, isGroup, isCommerce int) (positionId int64, seatNumber, saleName string, saleData []map[string]interface{}, isOk, isFreeze bool, noticePositionId int64) {
  1034. isOk = false
  1035. isFreeze = false
  1036. if TiDb.Count("dwd_f_crm_clue_info", map[string]interface{}{"phone": phone, "is_assign": 1}) == 0 { //线索没销售进入,有销售走分配次数最少的逻辑
  1037. if isGroup == 0 && isCommerce == 1 && cluename != "" { //非集团在工商库线索名不为空
  1038. //cdata := TiDb.Find("dwd_f_crm_clue_info", map[string]interface{}{"cluename": cluename, "is_assign": 1}, "", "", -1, -1)
  1039. cdata := TiDb.SelectBySql(`select position_id,MAX(trail_time) as trail_time,max(last_ring_time) as last_ring_time,seatNumber,count(id) as count from dwd_f_crm_clue_info where cluename=? and is_assign =1 GROUP BY position_id `, cluename)
  1040. if cdata != nil && len(*cdata) > 0 { //找到了公司有人在跟进
  1041. isOk = true
  1042. pdata := TiDb.SelectBySql(`select * from dwd_f_crm_personnel_management where seat_number is not null and seat_number != ""`)
  1043. if pdata == nil {
  1044. positionId = 0
  1045. seatNumber = ""
  1046. saleName = ""
  1047. return
  1048. }
  1049. saleData = *pdata
  1050. cdataNew := []map[string]interface{}{}
  1051. if len(*cdata) > 1 {
  1052. //可能有多个人跟进
  1053. personMap := map[int64]bool{}
  1054. upperLimitPersonMap := map[int64]bool{}
  1055. upperLimitCdataNew := []map[string]interface{}{}
  1056. upperLimitCount := 0
  1057. isFull := false
  1058. for _, m := range *cdata {
  1059. positionid1 := gconv.Int64(m["position_id"])
  1060. for _, v := range *pdata {
  1061. resign := common.IntAll(v["resign"])
  1062. assign_type := common.IntAll(v["assign_type"])
  1063. role_id := common.IntAll(v["role_id"])
  1064. if positionid1 == common.Int64All(v["position_id"]) {
  1065. if resign == 0 && (assign_type == 1 || role_id == 8) {
  1066. if !FindUpperLimit(gconv.String(positionid1), mode, true) {
  1067. personMap[positionid1] = true
  1068. m["saleName"] = common.ObjToString(v["name"])
  1069. cdataNew = append(cdataNew, m)
  1070. } else {
  1071. upperLimitCount++
  1072. upperLimitPersonMap[positionid1] = true
  1073. m["saleName"] = common.ObjToString(v["name"])
  1074. upperLimitCdataNew = append(upperLimitCdataNew, m)
  1075. }
  1076. }
  1077. }
  1078. }
  1079. }
  1080. if len(cdataNew) == 0 && len(upperLimitCdataNew) > 0 {
  1081. //没有达上限的人数为0 全部都是达上限的
  1082. personMap = upperLimitPersonMap
  1083. cdataNew = upperLimitCdataNew
  1084. isFull = true
  1085. }
  1086. //查询是否都有没有离职
  1087. if len(personMap) != 0 && len(cdataNew) > 0 {
  1088. layout := "2006-01-02 15:04:05"
  1089. //有人没有离职
  1090. data := map[string]interface{}{}
  1091. trailTime := int64(0)
  1092. for _, m := range cdataNew {
  1093. currentTime := int64(0)
  1094. if gconv.String(m["trail_time"]) == "" {
  1095. continue
  1096. }
  1097. t, _ := time.Parse(layout, gconv.String(m["trail_time"]))
  1098. currentTime = t.Unix()
  1099. if currentTime > trailTime {
  1100. trailTime = currentTime
  1101. data = m
  1102. }
  1103. }
  1104. if trailTime == 0 {
  1105. //需要查看通话记录
  1106. lastRingTime := int64(0)
  1107. for _, m := range cdataNew {
  1108. currentTime := int64(0)
  1109. if gconv.String(m["last_ring_time"]) == "" {
  1110. continue
  1111. }
  1112. t, _ := time.Parse(layout, gconv.String(m["last_ring_time"]))
  1113. currentTime = t.Unix()
  1114. if currentTime > lastRingTime {
  1115. lastRingTime = currentTime
  1116. data = m
  1117. }
  1118. }
  1119. if lastRingTime != 0 {
  1120. positionId = common.Int64All(data["position_id"])
  1121. noticePositionId = positionId
  1122. seatNumber = common.ObjToString(data["seatNumber"])
  1123. saleName = common.ObjToString(data["saleName"])
  1124. if isFull {
  1125. isFreeze = true
  1126. noticePositionId = positionId
  1127. positionId = 0
  1128. seatNumber = ""
  1129. saleName = ""
  1130. }
  1131. return
  1132. } else {
  1133. count := 0
  1134. //线索数量判断
  1135. for i, v := range cdataNew {
  1136. if i == 0 {
  1137. count = gconv.Int(v["count"])
  1138. data = v
  1139. } else {
  1140. if count < gconv.Int(v["count"]) {
  1141. count = gconv.Int(v["count"])
  1142. data = v
  1143. }
  1144. }
  1145. }
  1146. positionId = common.Int64All(data["position_id"])
  1147. noticePositionId = positionId
  1148. saleName = common.ObjToString(data["saleName"])
  1149. seatNumber = common.ObjToString(data["seatNumber"])
  1150. if isFull {
  1151. isFreeze = true
  1152. noticePositionId = positionId
  1153. positionId = 0
  1154. seatNumber = ""
  1155. saleName = ""
  1156. }
  1157. return
  1158. }
  1159. } else {
  1160. positionId = common.Int64All(data["position_id"])
  1161. noticePositionId = positionId
  1162. seatNumber = common.ObjToString(data["seatNumber"])
  1163. saleName = common.ObjToString(data["saleName"])
  1164. if isFull {
  1165. isFreeze = true
  1166. noticePositionId = positionId
  1167. positionId = 0
  1168. seatNumber = ""
  1169. saleName = ""
  1170. }
  1171. return
  1172. }
  1173. }
  1174. } else {
  1175. //只有一人跟进
  1176. //(1)该销售人员未离职,则继续分配给该销售人员(保持现状);
  1177. //该销售人员已离职,则随机分配
  1178. positionId = common.Int64All((*cdata)[0]["position_id"])
  1179. noticePositionId = positionId
  1180. seatNumber = common.ObjToString((*cdata)[0]["seatNumber"])
  1181. for _, v := range *pdata {
  1182. resign := common.IntAll(v["resign"])
  1183. assign_type := common.IntAll(v["assign_type"])
  1184. role_id := common.IntAll(v["role_id"])
  1185. if positionId == common.Int64All(v["position_id"]) {
  1186. if resign == 0 && (assign_type == 1 || role_id == 8) {
  1187. if FindUpperLimit(gconv.String(positionId), mode, true) {
  1188. isFreeze = true
  1189. positionId = 0
  1190. seatNumber = ""
  1191. saleName = ""
  1192. break
  1193. } else {
  1194. saleName = common.ObjToString(v["name"])
  1195. return
  1196. }
  1197. }
  1198. }
  1199. }
  1200. }
  1201. }
  1202. }
  1203. }
  1204. positionId = 0
  1205. seatNumber = ""
  1206. saleName = ""
  1207. query := `select * from dwd_f_crm_personnel_management where assign_type = 1 and`
  1208. if mode == "A" {
  1209. query += ` assign_level like "%A%"`
  1210. } else if mode == "B" {
  1211. query += ` assign_level like "%B%"`
  1212. } else if mode == "D" {
  1213. query += ` assign_level like "%D%"`
  1214. } else if mode == "C" {
  1215. query += ` assign_level like "%C%"`
  1216. } else if mode == "S" {
  1217. query += ` assign_level like "%S%"`
  1218. }
  1219. data := TiDb.SelectBySql(query)
  1220. if data != nil && len(*data) > 0 {
  1221. saleData = *data
  1222. sql := "select * from dwd_f_crm_clue_autodraw_record where clue_level = ?"
  1223. countData := TiDb.SelectBySql(sql, mode)
  1224. if countData != nil && len(*countData) > 0 {
  1225. for _, v := range *data {
  1226. isOk := false //判断是否有新员工
  1227. for _, vv := range *countData {
  1228. if common.Int64All(v["position_id"]) == common.Int64All(vv["position_id"]) {
  1229. if common.IntAll(v["resign"]) == 0 {
  1230. vv["status"] = 1
  1231. } else {
  1232. vv["status"] = 2
  1233. }
  1234. isOk = true
  1235. }
  1236. }
  1237. if !isOk { //有新员工直接分给新员工
  1238. positionId = common.Int64All(v["position_id"])
  1239. saleName = common.ObjToString(v["name"])
  1240. log.Println("新员工, ", positionId, saleName)
  1241. rData := TiDb.FindOne("dwd_f_crm_clue_autodraw_record", map[string]interface{}{"clue_level": mode}, "", "count desc")
  1242. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  1243. "position_id": positionId,
  1244. "clue_level": mode,
  1245. "count": common.Int64All((*rData)["count"]),
  1246. })
  1247. break
  1248. }
  1249. }
  1250. if positionId == 0 {
  1251. res := int64(0)
  1252. countres := 0
  1253. for _, v := range *countData {
  1254. if common.IntAll(v["status"]) == 1 {
  1255. if FindUpperLimit(gconv.String(v["position_id"]), mode, false) {
  1256. continue
  1257. }
  1258. if countres == 0 {
  1259. res = common.Int64All(v["count"])
  1260. positionId = common.Int64All(v["position_id"])
  1261. } else {
  1262. if common.Int64All(v["count"]) <= res {
  1263. res = common.Int64All(v["count"])
  1264. positionId = common.Int64All(v["position_id"])
  1265. }
  1266. }
  1267. countres++
  1268. }
  1269. }
  1270. log.Println(444, res)
  1271. }
  1272. } else {
  1273. for _, kv := range *data {
  1274. positionId1 := gconv.String(kv["position_id"])
  1275. if !FindUpperLimit(positionId1, "", false) {
  1276. positionId = common.Int64All(kv["position_id"])
  1277. saleName = common.ObjToString(kv["name"])
  1278. rData := TiDb.FindOne("dwd_f_crm_clue_autodraw_record", map[string]interface{}{"clue_level": mode}, "", "count desc")
  1279. if rData != nil && len(*rData) > 0 {
  1280. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  1281. "position_id": positionId,
  1282. "clue_level": mode,
  1283. "count": common.Int64All((*rData)["count"]),
  1284. })
  1285. } else {
  1286. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  1287. "position_id": positionId,
  1288. "clue_level": mode,
  1289. "count": 0,
  1290. })
  1291. }
  1292. break
  1293. }
  1294. }
  1295. }
  1296. for _, v := range *data {
  1297. if positionId == common.Int64All(v["position_id"]) {
  1298. seatNumber = common.ObjToString(v["seat_number"])
  1299. saleName = common.ObjToString(v["name"])
  1300. }
  1301. }
  1302. }
  1303. return
  1304. }
  1305. func getPositionId(phone string) (positionId int64) {
  1306. userData, ok := Mgo.FindOne("user", map[string]interface{}{"s_phone": phone})
  1307. if ok && userData != nil && len(*userData) > 0 {
  1308. userId := common.Int64All((*userData)["base_user_id"])
  1309. positionData := Base.FindOne("base_position", map[string]interface{}{"type": 1, "ent_id": 25917, "user_id": userId}, "", "") //TODO ent_id
  1310. if positionData != nil && len(*positionData) > 0 {
  1311. positionId = common.Int64All((*positionData)["id"])
  1312. }
  1313. }
  1314. return
  1315. }
  1316. func GetCompanyType(companyName string) (int, int) {
  1317. //是否是集团
  1318. isGroup, isCommerce := 0, 0
  1319. if c := TiDb.CountBySql(`select count(1) from group_company_name where company_name=?`, companyName); c > 0 {
  1320. isGroup = 1
  1321. }
  1322. //是否在工商库
  1323. if c := MgoQyxy.Count("qyxy_std", map[string]interface{}{"company_name": companyName, "company_type": map[string]interface{}{"$ne": "个体工商户"}}); c > 0 {
  1324. isCommerce = 1
  1325. }
  1326. return isGroup, isCommerce
  1327. }
  1328. // 查询是否达上限
  1329. func FindUpperLimit(positionId string, level string, isAdd bool) bool {
  1330. if positionId == "" {
  1331. return false
  1332. }
  1333. isFull := TiDb.CountBySql(`select count(1) from dwd_f_crm_clue_info where position_id=? and is_assign=1 and is_transfer != 1 `, positionId) >= db.AllocationCap
  1334. if isFull && isAdd && level != "" {
  1335. TiDb.UpdateOrDeleteBySql(`update dwd_f_crm_clue_autodraw_record set count = count + 1 where position_id = ? and clue_level = ?`, positionId, level)
  1336. }
  1337. return isFull
  1338. }
  1339. func getSeatNumberPositionId(seatNumber string) (positionId int64) {
  1340. saleData := TiDb.FindOne("dwd_f_crm_personnel_management", map[string]interface{}{"seat_number": seatNumber}, "", "")
  1341. if saleData != nil && len(*saleData) > 0 {
  1342. positionId = common.Int64All((*saleData)["position_id"])
  1343. }
  1344. return
  1345. }
  1346. // 重新关注用户处理
  1347. func rebind() {
  1348. log.Println("重新关注用户处理开始")
  1349. //判断节假日
  1350. runOk := getRunOk()
  1351. if !runOk {
  1352. log.Println("不是工作日,任务暂停")
  1353. return
  1354. }
  1355. rebindTimeEnd := cfg.RebindTime
  1356. sql := fmt.Sprintf(`select * from freeClubSign where sub_again_date > "%s" order by sub_again_date asc`, rebindTimeEnd)
  1357. data := BiService.SelectBySql(sql)
  1358. if data != nil && *data != nil && len(*data) > 0 {
  1359. for _, v := range *data {
  1360. rebindTimeEnd = common.ObjToString(v["sub_again_date"])
  1361. registedates, _ := time.Parse(date.Date_Full_Layout, gconv.String(v["register_time"]))
  1362. if time.Now().Unix()-registedates.Unix() > int64(db.RegTimes)*86400 {
  1363. ok1, ok2 := FormatData(v, "rebind")
  1364. if !ok1 {
  1365. log.Println("线索卡点", "allocation", v, rebindTimeEnd)
  1366. } else {
  1367. if !ok2 {
  1368. log.Println("用户分配已达上限", "allocation", v, rebindTimeEnd)
  1369. }
  1370. }
  1371. }
  1372. }
  1373. cfg.RebindTime = rebindTimeEnd
  1374. common.WriteSysConfig(&cfg)
  1375. }
  1376. log.Println("重新关注用户处理结束")
  1377. }
  1378. // 活跃用户处理
  1379. func activeUsers() {
  1380. log.Println("活跃用户处理开始")
  1381. //判断节假日
  1382. runOk := getRunOk()
  1383. if !runOk {
  1384. log.Println("不是工作日,任务暂停")
  1385. return
  1386. }
  1387. //活跃用户查询
  1388. activeTimeEnd := cfg.ActiveTime
  1389. sql := fmt.Sprintf(`select * from freeClubSign where act_again_date > "%s" order by act_again_date asc`, activeTimeEnd)
  1390. data := BiService.SelectBySql(sql)
  1391. if data != nil && *data != nil && len(*data) > 0 {
  1392. for _, v := range *data {
  1393. activeTimeEnd = common.ObjToString(v["act_again_date"])
  1394. ok1, ok2 := FormatData(v, "allocation")
  1395. log.Println(v, "allocation", ok1, ok2)
  1396. if !ok1 {
  1397. log.Println("线索卡点", "allocation", v, activeTimeEnd)
  1398. } else {
  1399. if !ok2 {
  1400. log.Println("用户分配已达上限", "allocation", v, activeTimeEnd)
  1401. }
  1402. }
  1403. }
  1404. cfg.ActiveTime = activeTimeEnd
  1405. common.WriteSysConfig(&cfg)
  1406. }
  1407. log.Println("活跃用户处理结束")
  1408. }