jobutil.go 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025
  1. package main
  2. import (
  3. "app.yhyue.com/moapp/jybase/mail"
  4. "app.yhyue.com/moapp/jybase/redis"
  5. "fmt"
  6. "github.com/tealeg/xlsx"
  7. "log"
  8. "math"
  9. "strings"
  10. "time"
  11. "github.com/gogf/gf/v2/util/gconv"
  12. "app.yhyue.com/moapp/jybase/common"
  13. "app.yhyue.com/moapp/jybase/date"
  14. "app.yhyue.com/moapp/jybase/mongodb"
  15. )
  16. // 电销工单生成
  17. func rderAcceptance() {
  18. sql := fmt.Sprintf(`select * from order_acceptance where is_clue=2 and is_delete=1 order by propose_time `)
  19. //sql := fmt.Sprintf(`select * from order_acceptance where is_clue=2 and is_delete=1 and id = 333 order by propose_time `)
  20. data := WorkOrder.SelectBySql(sql)
  21. if data != nil && len(*data) > 0 {
  22. for _, v := range *data {
  23. acceptance_no := gconv.String(v["acceptance_no"])
  24. childrenArr := WorkOrder.Find("order_acceptance_children", map[string]interface{}{
  25. "acceptance_no": acceptance_no,
  26. }, "", "", -1, -1)
  27. if childrenArr != nil && len(*childrenArr) > 0 {
  28. company := ""
  29. phone := ""
  30. demand := ""
  31. name := ""
  32. product := ""
  33. for _, v1 := range *childrenArr {
  34. if gconv.String(v1["field_name"]) == "公司名称" {
  35. company = gconv.String(v1["field_value"])
  36. }
  37. if gconv.String(v1["field_name"]) == "联系方式num" {
  38. phone = gconv.String(v1["field_value"])
  39. }
  40. if gconv.String(v1["field_name"]) == "客户姓名" {
  41. name = gconv.String(v1["field_value"])
  42. }
  43. if gconv.String(v1["field_name"]) == "客户需求" {
  44. demand = gconv.String(v1["field_value"])
  45. }
  46. if gconv.String(v1["field_name"]) == "咨询产品" {
  47. product = gconv.String(v1["field_value"])
  48. }
  49. }
  50. if !WorkDataHandle(company, phone, demand, name, product, v) {
  51. log.Println("工单创建失败")
  52. }
  53. }
  54. }
  55. }
  56. }
  57. func WorkDataHandle(company, phone, demand, name, product string, acceptanceData map[string]interface{}) bool {
  58. uId := ""
  59. query := map[string]interface{}{}
  60. contactsData := TiDb.SelectBySql("select * from dwd_f_userbase_contacts where phone = ? and is_delete = 1", phone)
  61. if contactsData != nil && len(*contactsData) > 0 {
  62. if common.ObjToString((*contactsData)[0]["baseinfo_id"]) != "" {
  63. uId = common.ObjToString((*contactsData)[0]["baseinfo_id"])
  64. query["uid"] = uId
  65. }
  66. }
  67. if uId == "" {
  68. log.Println("用户信息不存在")
  69. return false
  70. }
  71. cluename := company
  72. if cluename == "" {
  73. cluename = phone //没有线索名,手机号代替
  74. }
  75. ok, data, saleData, isNewScore := false, map[string]interface{}{}, []map[string]interface{}{}, false
  76. isGroup, isCommerce := GetCompanyType(cluename, uId)
  77. uCount, _ := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"uid": uId}, "", ""), true //查当前线索是否已存在
  78. inData := Clue{
  79. UId: uId,
  80. TopCluetype: "5",
  81. SubCluetype: "169",
  82. Topname: "新增线索",
  83. Subname: "主动咨询客服留资客户",
  84. Cluename: cluename,
  85. Name: name,
  86. Phone: phone,
  87. IsGroup: isGroup,
  88. IsCommerce: isCommerce,
  89. PIsOk: false,
  90. Demand: demand,
  91. }
  92. if uCount != nil && len(*uCount) > 0 {
  93. inData.SaleName = gconv.String((*uCount)["name"])
  94. inData.SeatNumber = gconv.String((*uCount)["seat_number"])
  95. inData.PositionId = gconv.Int64((*uCount)["position_id"])
  96. isUpdate := gconv.Int64((*uCount)["is_artificially_modified"])
  97. if isUpdate == 1 {
  98. cluename = ""
  99. }
  100. clueId := gconv.Int64((*uCount)["id"])
  101. positionId := gconv.Int64((*uCount)["position_id"])
  102. trailstatus := gconv.String((*uCount)["trailstatus"])
  103. IS_TRANSFER := gconv.Int64((*uCount)["IS_TRANSFER"])
  104. if IS_TRANSFER == 1 {
  105. //客成处理
  106. //客成
  107. //生成客成数据
  108. customerMap := TiDb.FindOne("dwd_f_csm_customer_info", map[string]interface{}{
  109. "clue_id": clueId,
  110. }, "position_id,name", "")
  111. if customerMap != nil && len(*customerMap) > 0 {
  112. //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)
  113. WorkUpdateClue(*uCount, saleData, inData)
  114. data = map[string]interface{}{
  115. "type": "kc",
  116. "position_id": (*customerMap)["position_id"],
  117. "name": (*customerMap)["name"],
  118. }
  119. } else {
  120. log.Println("查询不到客成数据", clueId, uId)
  121. return false
  122. }
  123. TiDb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  124. "clue_id": clueId,
  125. "position_id": (*customerMap)["position_id"],
  126. "change_type": "加入任务车",
  127. "new_value": "咨询客服转客成",
  128. "createtime": time.Now().Format(date.Date_Full_Layout),
  129. "BCPCID": common.GetRandom(32),
  130. "operator_id": -1,
  131. })
  132. } else {
  133. log.Println("工单分配程序:", positionId)
  134. if positionId == 0 {
  135. //线索变更
  136. isNewScore = true
  137. ok, data, saleData = FindPosition(phone, 0, "", gconv.String(acceptanceData["creator_time"]))
  138. if !ok {
  139. log.Println(positionId, "用户查询失败")
  140. return false
  141. }
  142. inData.PIsOk = true
  143. log.Println("按照比例抽取人数:", gconv.Int64(data["position_id"]), gconv.String(data["name"]))
  144. inData.SaleName = gconv.String(data["name"])
  145. inData.SeatNumber = gconv.String(data["seat_number"])
  146. inData.PositionId = gconv.Int64(data["position_id"])
  147. WorkUpdateClue(*uCount, saleData, inData)
  148. } else {
  149. ok, data, saleData = FindPosition(phone, positionId, trailstatus, gconv.String(acceptanceData["creator_time"]))
  150. if !ok {
  151. log.Println(positionId, "用户查询失败")
  152. return false
  153. }
  154. inData.SaleName = gconv.String(data["name"])
  155. inData.SeatNumber = gconv.String(data["seat_number"])
  156. inData.PositionId = gconv.Int64(data["position_id"])
  157. if gconv.Int64(data["position_id"]) == positionId {
  158. WorkUpdateClue(*uCount, saleData, inData)
  159. } else {
  160. inData.PIsOk = true
  161. WorkUpdateClue(*uCount, saleData, inData)
  162. }
  163. }
  164. }
  165. } else {
  166. //新增线索
  167. ok, data, _ = FindPosition(phone, 0, "", gconv.String(acceptanceData["creator_time"]))
  168. if !ok {
  169. return false
  170. }
  171. isNewScore = false
  172. inData.SaleName = gconv.String(data["name"])
  173. inData.SeatNumber = gconv.String(data["seat_number"])
  174. inData.PositionId = gconv.Int64(data["position_id"])
  175. SaveClue(inData)
  176. }
  177. //工单生成
  178. ok1 := AddOrderWork(acceptanceData, data, product, phone, company, isNewScore)
  179. log.Println("工单创建", ok1, gconv.String(acceptanceData["acceptance_no"]))
  180. return true
  181. }
  182. func AddOrderWork(acceptanceData map[string]interface{}, userData map[string]interface{}, product, phone, company string, isNewScore bool) bool {
  183. time.Sleep(time.Second * 1)
  184. nowTime := time.Now().Format(date.Date_Full_Layout)
  185. work_order_no := fmt.Sprintf("GD%s%s", time.Now().Format(date.Date_yyyyMMdd), FindNumber("gd"))
  186. productArr := []string{}
  187. for _, v := range strings.Split(product, ",") {
  188. switch ProductMap[v] {
  189. case "dk":
  190. continue
  191. default:
  192. productArr = append(productArr, v)
  193. }
  194. }
  195. two_type := "dx"
  196. if gconv.String(userData["type"]) == "kc" {
  197. two_type = "kc"
  198. }
  199. personMap := GetPerson(gconv.String(userData["position_id"]))
  200. if personMap == nil || len(personMap) == 0 {
  201. return false
  202. }
  203. orderWorkMap := map[string]interface{}{
  204. "work_order_no": work_order_no,
  205. "acceptance_no": gconv.String(acceptanceData["acceptance_no"]),
  206. "type": strings.Join(productArr, ","),
  207. "status": common.If(gconv.Int64(userData["orderStatus"]) == 0, 2, 1),
  208. "initiator_name": gconv.String(acceptanceData["creator_name"]),
  209. "initiator_position_id": gconv.String(acceptanceData["initiator_position_id"]),
  210. "current_name": common.If(gconv.Int64(userData["orderStatus"]) == 0, nil, userData["name"]),
  211. "current_position_id": common.If(gconv.Int64(userData["orderStatus"]) == 0, nil, userData["position_id"]),
  212. "history_name": common.If(gconv.Int64(userData["orderStatus"]) == 0, userData["name"], nil),
  213. "history_postion_id": common.If(gconv.Int64(userData["orderStatus"]) == 0, userData["position_id"], nil),
  214. "is_delete": 1,
  215. "creator_name": gconv.String(acceptanceData["creator_name"]),
  216. "creator_position_id": gconv.String(acceptanceData["creator_position_id"]),
  217. "creator_time": nowTime,
  218. "two_type": two_type,
  219. "department_no": gconv.String(personMap["deptId"]),
  220. "department_name": gconv.String(personMap["deptName"]),
  221. "update_time": common.If(gconv.Int64(userData["orderStatus"]) == 0, nowTime, nil),
  222. }
  223. ok3 := WorkOrder.Insert("order_work", orderWorkMap)
  224. if ok3 > 0 {
  225. status := 2
  226. if WorkOrder.Count("order_work", map[string]interface{}{
  227. "status": 1,
  228. "acceptance_no": gconv.String(acceptanceData["acceptance_no"]),
  229. }) > 0 {
  230. status = 1
  231. }
  232. WorkOrder.Update("order_acceptance", map[string]interface{}{
  233. "id": acceptanceData["id"],
  234. }, map[string]interface{}{
  235. "is_clue": 3,
  236. "status": status,
  237. "over_time": common.If(status == 1, nil, nowTime),
  238. })
  239. //日志添加
  240. approvalRecordMap := map[string]interface{}{
  241. "work_order_no": work_order_no,
  242. "status": common.If(gconv.Int64(userData["orderStatus"]) == 0, 3, 1),
  243. "new_status": common.If(gconv.Int64(userData["orderStatus"]) == 0, 2, nil),
  244. "handle_name": userData["name"],
  245. "handle_position_id": userData["position_id"],
  246. "handle_dept_id": gconv.String(personMap["deptId"]),
  247. "handle_dept_name": gconv.String(personMap["deptName"]),
  248. "creator_name": gconv.String(acceptanceData["creator_name"]),
  249. "creator_position_id": gconv.String(acceptanceData["initiator_position_id"]),
  250. "is_delete": 1,
  251. "creator_time": nowTime,
  252. "handle_time": common.If(gconv.Int64(userData["orderStatus"]) == 0, nowTime, nil),
  253. "update_name": common.If(gconv.Int64(userData["orderStatus"]) == 0, userData["name"], nil),
  254. "update_position_id": common.If(gconv.Int64(userData["orderStatus"]) == 0, userData["position_id"], nil),
  255. "update_time": common.If(gconv.Int64(userData["orderStatus"]) == 0, nowTime, nil),
  256. }
  257. WorkOrder.Insert("approval_record", approvalRecordMap)
  258. //工单分配记录添加
  259. if isNewScore {
  260. orderWorkAllocationRecord := map[string]interface{}{
  261. "person_name": userData["name"],
  262. "position_id": userData["position_id"],
  263. "dept_name": personMap["deptName"],
  264. "dept_id": personMap["deptId"],
  265. "work_order_no": work_order_no,
  266. "create_time": nowTime,
  267. "company_dept_numb": common.If(gconv.String(personMap["deptName"]) == "销售三部", 3, 1),
  268. "whee_time": cfg.AllocationTime,
  269. }
  270. WorkOrder.Insert("order_work_allocation_record", orderWorkAllocationRecord)
  271. }
  272. WorkMail(personMap,
  273. strings.Join(productArr, ","),
  274. gconv.Int64(common.If(gconv.Int64(userData["orderStatus"]) == 0, 2, 1)),
  275. gconv.String(personMap["name"]),
  276. gconv.String(acceptanceData["creator_name"]),
  277. nowTime,
  278. work_order_no,
  279. phone,
  280. company)
  281. return true
  282. }
  283. return false
  284. }
  285. // 本级以及上级管理员查询
  286. func GetPerson(positionId string) map[string]interface{} {
  287. person := map[string]interface{}{}
  288. positionArrMap := Base.SelectBySql(fmt.Sprintf(`select a.phone,b.id,b.ent_id from
  289. base_user a
  290. INNER JOIN base_position b
  291. on b.id= %s and b.user_id=a.id and b.type=1`,
  292. positionId))
  293. if positionArrMap == nil || len(*positionArrMap) == 0 {
  294. return map[string]interface{}{}
  295. }
  296. phone := gconv.String((*positionArrMap)[0]["phone"])
  297. entId := gconv.String((*positionArrMap)[0]["ent_id"])
  298. entUserArrMap := Mysql.SelectBySql(fmt.Sprintf(`SELECT
  299. a.name as name,a.mail as mail,b.dept_id as deptId,a.phone ,c.name as deptName
  300. FROM
  301. entniche_user a
  302. INNER JOIN entniche_department_user b ON a.ent_id =%s
  303. AND a.phone IN %s
  304. and a.id=b.user_id
  305. inner join entniche_department c on b.dept_id=c.id
  306. `, entId, fmt.Sprintf("(%s)", phone)))
  307. //商机管理员
  308. if entUserArrMap == nil || len(*entUserArrMap) == 0 {
  309. return map[string]interface{}{}
  310. }
  311. deptId := gconv.Int64((*entUserArrMap)[0]["deptId"])
  312. person = map[string]interface{}{
  313. "name": gconv.String((*entUserArrMap)[0]["name"]),
  314. "mail": gconv.String((*entUserArrMap)[0]["mail"]),
  315. "phone": gconv.String((*entUserArrMap)[0]["phone"]),
  316. "deptId": gconv.String((*entUserArrMap)[0]["deptId"]),
  317. "deptName": gconv.String((*entUserArrMap)[0]["deptName"]),
  318. }
  319. //本部门管理员查询
  320. depthMap := Mysql.SelectBySql(`SELECT
  321. c.name as name,c.mail as mail
  322. FROM
  323. entniche_department_user a
  324. INNER JOIN entniche_user_role b ON a.dept_id = ?
  325. AND a.user_id = b.user_id
  326. AND b.role_id !=""
  327. INNER JOIN entniche_user c ON a.user_id = c.id`, deptId)
  328. if depthMap != nil && len(*depthMap) > 0 {
  329. person["deptPersonName"] = gconv.String((*depthMap)[0]["name"])
  330. person["deptPersonMail"] = gconv.String((*depthMap)[0]["mail"])
  331. }
  332. //商机管理员查询
  333. superiorDepthMap := Mysql.SelectBySql(`SELECT
  334. c.*
  335. FROM
  336. entniche_department d
  337. INNER JOIN entniche_department_user a ON d.id = ?
  338. AND d.pid = a.dept_id
  339. INNER JOIN entniche_user_role b ON a.user_id = b.user_id
  340. AND b.role_id !=""
  341. INNER JOIN entniche_user c ON a.user_id = c.id`, deptId)
  342. if superiorDepthMap != nil && len(*superiorDepthMap) > 0 {
  343. person["superiorDepthPersonName"] = gconv.String((*superiorDepthMap)[0]["name"])
  344. person["superiorDepthPersonMail"] = gconv.String((*superiorDepthMap)[0]["mail"])
  345. }
  346. return person
  347. }
  348. // 编号查询
  349. func FindNumber(moudle string) string {
  350. today := time.Now().Format("2006-01-02")
  351. yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02")
  352. key := fmt.Sprintf("%s_%s", today, moudle)
  353. yesterdayKey := fmt.Sprintf("%s_%s", yesterday, moudle)
  354. if ok, _ := redis.Exists("newother", yesterdayKey); ok {
  355. //删除之前数据
  356. redis.Del("newother", yesterdayKey)
  357. }
  358. count := redis.Incr("newother", key)
  359. log.Println("编号获取", moudle, fmt.Sprintf("%04d", count))
  360. return fmt.Sprintf("%04d", count)
  361. }
  362. // 人员查询
  363. func GetAllocation(proportion1, proportion3 float64, deptCount1, deptCount3 int64, administrators1, administrators3 map[string]interface{}) map[string]interface{} {
  364. log.Println("分配比例查询", cfg.AllocationTime, cfg.AllocationRatio, proportion1, proportion3, deptCount1, deptCount3)
  365. if deptCount1 == 0 {
  366. return administrators1
  367. }
  368. if deptCount3 == 0 {
  369. return administrators3
  370. }
  371. nowAllocationRatio := math.Round(gconv.Float64(deptCount1 / deptCount3))
  372. log.Println("分配比例查询", proportion1, proportion3, deptCount1, deptCount3, nowAllocationRatio, cfg.AllocationRatio)
  373. if cfg.AllocationRatio == 0 {
  374. //重新计算
  375. cfg.AllocationRatio = math.Round(proportion1 / proportion3)
  376. cfg.AllocationTime = time.Now().Format(date.Date_Full_Layout)
  377. common.WriteSysConfig(&cfg)
  378. log.Println("新增计算比例", cfg.AllocationRatio)
  379. return administrators1
  380. } else {
  381. if nowAllocationRatio == cfg.AllocationRatio {
  382. //重新计算
  383. cfg.AllocationRatio = math.Round(proportion1 / proportion3)
  384. cfg.AllocationTime = time.Now().Format(date.Date_Full_Layout)
  385. common.WriteSysConfig(&cfg)
  386. return administrators1
  387. }
  388. }
  389. if nowAllocationRatio > cfg.AllocationRatio {
  390. return administrators3
  391. } else {
  392. return administrators1
  393. }
  394. //达到比例也重新计算
  395. }
  396. func FindPosition(phone string, positionId int64, trailstatus, creatorTime string) (bool, map[string]interface{}, []map[string]interface{}) {
  397. //查询预分配人员
  398. assignmentData := TiDb.FindOne("temporary_assignment", map[string]interface{}{
  399. "status": 0,
  400. "phone": phone,
  401. }, "", "")
  402. if assignmentData != nil && len(*assignmentData) > 0 {
  403. data := map[string]interface{}{
  404. "name": gconv.String((*assignmentData)["saleName"]),
  405. "seat_number": gconv.String((*assignmentData)["seatNumber"]),
  406. "position_id": gconv.Int64((*assignmentData)["positionId"]),
  407. }
  408. userData := TiDb.SelectBySql(`SELECT
  409. a.position_id,
  410. a.name,
  411. b.seat_number,
  412. b.role_id,
  413. a.bi_pcode,
  414. a.dept_name
  415. FROM
  416. dwd_d_crm_department_level_succbi a
  417. INNER JOIN dwd_f_crm_personnel_management b ON a.resign = 0 and b.resign = 0
  418. AND a.position_id = b.position_id`)
  419. TiDb.Update("temporary_assignment", map[string]interface{}{
  420. "id": (*assignmentData)["id"],
  421. }, map[string]interface{}{
  422. "status": 1,
  423. })
  424. return true, data, *userData
  425. }
  426. allData := []map[string]interface{}{}
  427. //查询两个部门高级管理员
  428. //查询两个部门所有人员标识
  429. //电销三部
  430. userData1 := TiDb.SelectBySql(`SELECT
  431. a.position_id,
  432. a.name,
  433. b.seat_number,
  434. b.role_id,
  435. a.bi_pcode,
  436. a.dept_name
  437. FROM
  438. dwd_d_crm_department_level_succbi a
  439. INNER JOIN dwd_f_crm_personnel_management b ON a.resign = 0 and b.resign = 0
  440. AND a.dept_name LIKE "销售一部%"
  441. AND a.position_id = b.position_id`)
  442. userData3 := TiDb.SelectBySql(`SELECT
  443. a.position_id,
  444. a.name,
  445. b.seat_number,
  446. b.role_id,
  447. a.bi_pcode,
  448. a.dept_name
  449. FROM
  450. dwd_d_crm_department_level_succbi a
  451. INNER JOIN dwd_f_crm_personnel_management b ON a.resign = 0 and b.resign = 0
  452. AND a.resign = 0
  453. AND a.dept_name LIKE "%销售三部"
  454. AND a.position_id = b.position_id`)
  455. if userData3 == nil || len(*userData3) == 0 || userData1 == nil || len(*userData1) == 0 {
  456. return false, map[string]interface{}{}, allData
  457. }
  458. //一部管理员信息
  459. administrators1 := map[string]interface{}{}
  460. //三部管理员信息
  461. administrators3 := map[string]interface{}{}
  462. //返回当前人信息
  463. administrators := map[string]interface{}{}
  464. //电销一部
  465. deptNameMap1 := map[string]interface{}{}
  466. deptNameMap3 := map[string]interface{}{}
  467. proportion1 := float64(0)
  468. proportion3 := float64(0)
  469. for _, v := range *userData3 {
  470. v["type"] = 3
  471. id := gconv.Int64(v["position_id"])
  472. roleId := gconv.Int64(v["role_id"])
  473. if id == positionId {
  474. administrators = v
  475. }
  476. if roleId == 8 {
  477. v["orderStatus"] = 2
  478. administrators3 = v
  479. } else if roleId == 3 {
  480. proportion3 += 0.5
  481. } else {
  482. proportion3 += 1
  483. }
  484. deptNameMap3[gconv.String(v["bi_pcode"])] = true
  485. allData = append(allData, v)
  486. }
  487. for _, v := range *userData1 {
  488. v["type"] = 1
  489. id := gconv.Int64(v["position_id"])
  490. roleId := gconv.Int64(v["role_id"])
  491. if id == positionId {
  492. administrators = v
  493. }
  494. if roleId == 8 {
  495. v["orderStatus"] = 2
  496. administrators1 = v
  497. } else if roleId == 3 {
  498. proportion1 += 0.5
  499. } else {
  500. proportion1 += 1
  501. }
  502. deptNameMap1[gconv.String(v["bi_pcode"])] = true
  503. allData = append(allData, v)
  504. }
  505. if positionId != 0 {
  506. if administrators == nil || len(administrators) == 0 {
  507. return false, map[string]interface{}{}, allData
  508. }
  509. positiontype := gconv.Int64(administrators["type"])
  510. if trailstatus == "01" {
  511. switch positiontype {
  512. case 1:
  513. //找他上级
  514. administrators = administrators1
  515. case 3:
  516. //找他上级
  517. administrators = administrators3
  518. }
  519. return true, administrators, allData
  520. } else {
  521. return true, administrators, allData
  522. }
  523. }
  524. //按照比例分配选择一部还是三部
  525. //一部查询
  526. deptCount1 := CalculateProportion(1)
  527. //三部查询
  528. deptCount3 := CalculateProportion(3)
  529. return true, GetAllocation(proportion1, proportion3, deptCount1, deptCount3, administrators1, administrators3), allData
  530. }
  531. func CalculateProportion(deptNumb int64) int64 {
  532. data := WorkOrder.SelectBySql(`SELECT
  533. sum(1) as count
  534. FROM
  535. order_work_allocation_record where create_time >? and company_dept_numb=? `, cfg.AllocationTime, deptNumb)
  536. count := int64(0)
  537. if data != nil && len(*data) > 0 {
  538. count = gconv.Int64((*data)[0]["count"])
  539. }
  540. return count
  541. }
  542. // 未支付订单 30分钟一次
  543. func orders() {
  544. //一个小时未支付进入线索 A
  545. log.Println("未支付订单定时任务开始")
  546. lastOrderId := cfg.LastOrderId
  547. selectTimeStart := time.Unix(time.Now().Unix()-7200, 0).Format(date.Date_Full_Layout)
  548. selectTimeEnd := time.Unix(time.Now().Unix()-3600, 0).Format(date.Date_Full_Layout)
  549. product_type_str1 := `"大会员","VIP订阅","数据流量包","历史数据"`
  550. DataSql := fmt.Sprintf(`select a.*,b.product_type as productType ,b.service_starttime,b.service_endtime,b.filter AS productFilter from dataexport_order a
  551. INNER JOIN jy_order_detail b on a.order_code=b.order_code
  552. and a.create_time<="%s" and a.create_time>="%s" and b.product_type in (%s)
  553. and a.order_status = 0 and a.is_backstage_order = 0 and a.id> %s order by b.id asc`,
  554. selectTimeEnd, selectTimeStart, product_type_str1, gconv.String(lastOrderId))
  555. data, _ := getOrderData(DataSql)
  556. if data != nil && data != nil && len(data) > 0 {
  557. for _, v := range data {
  558. ok1, ok2, _ := FormatData(v, "orders")
  559. if !ok1 {
  560. common.WriteSysConfig(&cfg)
  561. log.Println("线索卡点", "orders", v, selectTimeEnd, selectTimeStart)
  562. } else {
  563. if !ok2 {
  564. log.Println("用户分配已达上限", "orders", v, selectTimeEnd, selectTimeStart)
  565. common.WriteSysConfig(&cfg)
  566. }
  567. }
  568. cfg.LastOrderId = common.IntAll(v["id"])
  569. }
  570. }
  571. common.WriteSysConfig(&cfg)
  572. log.Println("未支付订单定时任务结束")
  573. }
  574. func readClue() {
  575. log.Println("读表进线索定时任务开始")
  576. lastReadClueTime := cfg.LastReadClueTime
  577. sql := fmt.Sprintf(`select * from clue_info where updatetime > "%s" order by updatetime asc`, fmt.Sprint(lastReadClueTime))
  578. data := TiDb.SelectBySql(sql)
  579. if data != nil && *data != nil && len(*data) > 0 {
  580. for _, v := range *data {
  581. ok1, ok2, _ := FormatData(v, "readClue")
  582. if !ok1 {
  583. common.WriteSysConfig(&cfg)
  584. log.Println("线索卡点", "readClue", v, lastReadClueTime)
  585. } else {
  586. if !ok2 {
  587. log.Println("用户分配已达上限", "readClue", v, lastReadClueTime)
  588. common.WriteSysConfig(&cfg)
  589. }
  590. }
  591. cfg.LastReadClueTime = common.ObjToString(v["updatetime"])
  592. }
  593. }
  594. common.WriteSysConfig(&cfg)
  595. log.Println("读表进线索定时任务结束")
  596. }
  597. // 新注册用户 5分钟一次
  598. func users() {
  599. //判断节假日
  600. runOk := getRunOk()
  601. if !runOk {
  602. log.Println("不是工作日,任务暂停")
  603. return
  604. }
  605. //新用户注册后5分钟内进入线索 C
  606. log.Println("新注册用户定时任务开始", cfg.LastUserId)
  607. selectTimeEnd := cfg.LastUserId
  608. sql := fmt.Sprintf(`select * from dwd_f_userbase_baseinfo where createtime > "%s" and (s_platform != 'xcx' or s_sourceid='jyzbw' or s_platform is NULL) and source = "0101" and status != 2 order by createtime asc`, selectTimeEnd)
  609. data := TiDb.SelectBySql(sql)
  610. if data != nil && *data != nil && len(*data) > 0 {
  611. for _, v := range *data {
  612. //判断用户是否有小程序切使用过剑鱼其他产品
  613. createtime := common.ObjToString(v["createtime"])
  614. changeCode := GetUserChannel(gconv.String(v["userid"]))
  615. if changeCode != "" {
  616. TiDb.Update("dwd_f_userbase_baseinfo", map[string]interface{}{
  617. "userid": gconv.String(v["userid"]),
  618. }, map[string]interface{}{
  619. "belong_to": changeCode,
  620. })
  621. }
  622. //判断一下用户是否进线索
  623. uid := gconv.String(v["uid"])
  624. if TiDb.Count("dwd_f_crm_clue_info", map[string]interface{}{
  625. "uid": uid,
  626. }) > 0 {
  627. cfg.LastUserId = createtime
  628. continue
  629. }
  630. ok1, ok2, _ := FormatData(v, "users")
  631. if !ok1 {
  632. log.Println("线索卡点", "users", v, selectTimeEnd)
  633. } else {
  634. if !ok2 {
  635. log.Println("用户分配已达上限", "users", v, selectTimeEnd)
  636. }
  637. }
  638. cfg.LastUserId = createtime
  639. }
  640. }
  641. common.WriteSysConfig(&cfg)
  642. log.Println("新注册用户定时任务结束", cfg.LastUserId)
  643. log.Println("小程序新注册用户定时任务结束", cfg.LastXcxUserId)
  644. selectXcxTimeEnd := cfg.LastXcxUserId
  645. xcxSql := fmt.Sprintf(`SELECT DISTINCT
  646. aa.mgo_id as userId,
  647. cc.code as industry ,
  648. aa.phone,
  649. IF
  650. ( aa.phone_time IS NULL, aa.create_time, aa.phone_time ) as time
  651. FROM
  652. debris_product.miniprogram_user aa
  653. INNER JOIN debris_product.miniprogram bb ON (
  654. aa.phone <> ''
  655. AND
  656. IF
  657. ( aa.phone_time IS NULL, aa.create_time, aa.phone_time ) > '%s'
  658. AND aa.miniprogram_code = bb.CODE
  659. )
  660. INNER JOIN debris_product.industry cc ON ( bb.industry_code = cc.CODE )
  661. WHERE
  662. NOT EXISTS (
  663. SELECT
  664. 1
  665. FROM
  666. debris_product.miniprogram_user a
  667. INNER JOIN debris_product.miniprogram b ON (
  668. aa.unionid = a.unionid
  669. AND aa.miniprogram_code = a.miniprogram_code
  670. AND aa.id != a.id
  671. AND
  672. IF
  673. ( a.phone_time IS NULL, a.create_time, a.phone_time ) <= '%s'
  674. AND a.miniprogram_code = b.CODE
  675. )
  676. INNER JOIN debris_product.miniprogram_user c ON ( a.unionid = c.unionid AND b.CODE = c.miniprogram_code ))
  677. ORDER BY time
  678. `, selectXcxTimeEnd, selectXcxTimeEnd)
  679. xcxData := debrisProductMysql.SelectBySql(xcxSql)
  680. log.Println("11122", selectXcxTimeEnd, xcxData)
  681. if xcxData != nil && *xcxData != nil && len(*xcxData) > 0 {
  682. afList := []map[string]interface{}{}
  683. for _, v := range *xcxData {
  684. //判断用户是否有小程序切使用过剑鱼其他产品
  685. //判断uid
  686. uId := ""
  687. changeCode := GetUserChannel(gconv.String(v["userId"]))
  688. if changeCode != "" {
  689. TiDb.Update("dwd_f_userbase_baseinfo", map[string]interface{}{
  690. "userid": gconv.String(v["userId"]),
  691. }, map[string]interface{}{
  692. "belong_to": changeCode,
  693. })
  694. }
  695. for i := 0; i < 10; i++ {
  696. phone := common.ObjToString(v["phone"])
  697. contactsData := TiDb.SelectBySql("select * from dwd_f_userbase_contacts where phone = ? and is_delete = 1", phone)
  698. if contactsData != nil && len(*contactsData) > 0 {
  699. if common.ObjToString((*contactsData)[0]["baseinfo_id"]) != "" {
  700. uId = common.ObjToString((*contactsData)[0]["baseinfo_id"])
  701. }
  702. }
  703. if uId == "" {
  704. time.Sleep(1 * time.Minute)
  705. } else {
  706. break
  707. }
  708. }
  709. updatetime := common.ObjToString(v["time"])
  710. if uId == "" {
  711. cfg.LastXcxUserId = updatetime
  712. continue
  713. }
  714. ok1, ok2, _ := FormatData(v, "xcxusers")
  715. /*if !ok3 {
  716. //首次使用"安防"小程序新注册用户
  717. afList = append(afList, v)
  718. cfg.LastXcxUserId = updatetime
  719. continue
  720. }*/
  721. if !ok1 {
  722. common.WriteSysConfig(&cfg)
  723. log.Println("小程序用户分配线索卡点", "xcxusers", v, selectXcxTimeEnd)
  724. } else {
  725. if !ok2 {
  726. log.Println("小程序用户分配已达上限", "xcxusers", v, selectXcxTimeEnd)
  727. common.WriteSysConfig(&cfg)
  728. }
  729. }
  730. cfg.LastXcxUserId = updatetime
  731. }
  732. if len(afList) > 0 {
  733. //发邮件给张文福
  734. AFEmail(afList)
  735. }
  736. }
  737. common.WriteSysConfig(&cfg)
  738. log.Println("小程序新注册用户定时任务结束", cfg.LastXcxUserId)
  739. }
  740. // 留资 5分钟一次
  741. func saleLeads() {
  742. //判断节假日
  743. runOk := getRunOk()
  744. if !runOk {
  745. log.Println("不是工作日,任务暂停")
  746. return
  747. }
  748. //留资后5分钟内进入线索
  749. //分为免费留资和付费留资 付费B 免费C
  750. log.Println("用户留资定时任务开始")
  751. session := Mgo.GetMgoConn()
  752. lastId := cfg.LastId
  753. defer func() {
  754. Mgo.DestoryMongoConn(session)
  755. }()
  756. query := map[string]interface{}{}
  757. if lastId != "" {
  758. query["_id"] = map[string]interface{}{"$gt": mongodb.StringTOBsonId(lastId)}
  759. }
  760. log.Println("query :", query)
  761. iter := session.DB(db.Mgo.DbName).C("saleLeads").Find(&query).Sort("_id").Iter()
  762. thisData := map[string]interface{}{}
  763. filterArr := []string{"-pc", "-app", "-wx", "-h5"}
  764. sourceMap := map[string]string{}
  765. saleLeadsConfig := TiDb.Find("saleLeads_config", map[string]interface{}{
  766. "status": 0,
  767. }, "groupName", "", -1, -1)
  768. if saleLeadsConfig == nil || len(*saleLeadsConfig) == 0 {
  769. log.Println("线索卡点", "缺少留资分类名称", "saleLeads", thisData, lastId)
  770. return
  771. }
  772. sourceArr := []string{}
  773. for _, v := range *saleLeadsConfig {
  774. sourceArr = append(sourceArr, fmt.Sprintf(`department LIKE '%%%s%%'`, gconv.String(v["groupName"])))
  775. }
  776. sql := fmt.Sprintf(`SELECT source,name FROM d_saleleads_code WHERE ( %s) AND is_delete = 1`, strings.Join(sourceArr, " or "))
  777. saleSource := TiDb.SelectBySql(sql)
  778. if saleSource != nil && len(*saleSource) > 0 {
  779. for _, v := range *saleSource {
  780. source := common.ObjToString(v["source"])
  781. name := common.ObjToString(v["name"])
  782. for _, s := range filterArr {
  783. name = strings.ReplaceAll(name, s, "")
  784. }
  785. sourceMap[source] = name
  786. }
  787. }
  788. for {
  789. if !iter.Next(&thisData) {
  790. break
  791. }
  792. sourceCode := common.ObjToString(thisData["source"])
  793. if sourceCode == "" {
  794. log.Println("留资没有source", thisData)
  795. continue
  796. }
  797. //
  798. if sourceMap[sourceCode] != "" {
  799. continue
  800. }
  801. ok1, ok2, _ := FormatData(thisData, "saleLeads")
  802. if !ok1 {
  803. log.Println("线索卡点", "saleLeads", thisData, lastId)
  804. } else {
  805. if !ok2 {
  806. log.Println("用户分配已达上限", "saleLeads", thisData, lastId)
  807. }
  808. }
  809. cfg.LastId = mongodb.BsonIdToSId(thisData["_id"])
  810. }
  811. common.WriteSysConfig(&cfg)
  812. log.Println("用户留资定时任务结束")
  813. }
  814. func userbase() {
  815. log.Println("userbase定时任务开始")
  816. timeUnix := time.Now().Unix()
  817. selectTimeStart := cfg.LastUserBindingTime
  818. selectTimeEnd := time.Unix(timeUnix, 0).Format("2006-01-02 15:04:05")
  819. sql := fmt.Sprintf(`SELECT
  820. a.phone,b.uid,a.baseinfo_id,b.l_registedate,a.createtime,b.id,b.userid,b.rsource
  821. FROM
  822. dwd_f_userbase_contacts a
  823. INNER JOIN dwd_f_userbase_baseinfo b ON
  824. b.status= 1
  825. and (b.s_platform != 'xcx' or b.s_sourceid='jyzbw' or b.s_platform is NULL)
  826. AND a.phone = b.phone and a.baseinfo_id= b.uid and b.source ="0101"
  827. and a.phone is not NULL
  828. and a.createtime >"%s"
  829. and a.is_delete=1
  830. ORDER BY a.createtime `, selectTimeStart)
  831. data := TiDb.SelectBySql(sql)
  832. if data != nil && *data != nil && len(*data) > 0 {
  833. for _, v := range *data {
  834. phone := common.ObjToString(v["phone"])
  835. uId := common.ObjToString(v["uid"])
  836. userId := common.ObjToString(v["userid"])
  837. changeCode := GetUserChannel(userId)
  838. if changeCode != "" {
  839. TiDb.Update("", map[string]interface{}{
  840. "userid": userId,
  841. }, map[string]interface{}{
  842. "belong_to": changeCode,
  843. })
  844. }
  845. registedate := common.ObjToString(v["l_registedate"])
  846. name := common.ObjToString(v["name"])
  847. nowTime := time.Now().Format(date.Date_Full_Layout)
  848. layout := "2006-01-02 15:04:05"
  849. createtime := gconv.String(v["createtime"])
  850. cfg.LastUserBindingTime = createtime
  851. createtimeInt64, _ := time.Parse(layout, createtime)
  852. registedateInt64, _ := time.Parse(layout, registedate)
  853. count := TiDb.CountBySql("select count(1) as count from dwd_f_crm_clue_info where uid = ?", uId)
  854. if createtimeInt64.Unix()-registedateInt64.Unix() < int64(db.RegTimes)*86400 {
  855. if count == 0 {
  856. //注册少于7天、走新增
  857. data := TiDb.FindOne("dwd_f_userbase_baseinfo", map[string]interface{}{
  858. "id": gconv.Int64(v["id"]),
  859. }, "", "")
  860. if data != nil && len(*data) > 0 {
  861. ok1, ok2, _ := FormatData(v, "users")
  862. if !ok1 {
  863. log.Println("线索卡点", "userbase uid", v, uId)
  864. } else {
  865. if !ok2 {
  866. log.Println("用户分配已达上限", "userbase uid", v, uId)
  867. }
  868. }
  869. }
  870. }
  871. continue
  872. }
  873. registedates, _ := time.Parse(date.Date_Full_Layout, registedate)
  874. log.Println("userbase uid 线索数量 ", count)
  875. log.Println("userbase uid 注册时间 ", registedates)
  876. if count == 0 {
  877. clueId := int64(0)
  878. sql := fmt.Sprintf(`select * from freeClubSign where mogUserId="%s" and sub_again_date > "%s" `, userId, selectTimeEnd)
  879. data := BiService.SelectBySql(sql)
  880. if len(*data) > 0 && userId != "" {
  881. clueId = TiDb.Insert("dwd_f_crm_clue_info", map[string]interface{}{
  882. "userid": userId,
  883. "uid": uId,
  884. "is_assign": 0,
  885. "comeintime": nowTime,
  886. "createtime": nowTime,
  887. "updatetime": nowTime,
  888. "cluename": phone,
  889. "top_cluetype": "532",
  890. "sub_cluetype": "670",
  891. "trailstatus": "01",
  892. "name": name,
  893. "phone": phone,
  894. "comeintime_open": nowTime,
  895. "comeinsource_open": 1,
  896. "FREEZE_TIME": nowTime,
  897. })
  898. } else {
  899. clueId = TiDb.Insert("dwd_f_crm_clue_info", map[string]interface{}{
  900. "userid": userId,
  901. "uid": uId,
  902. "is_assign": 0,
  903. "comeintime": nowTime,
  904. "createtime": nowTime,
  905. "updatetime": nowTime,
  906. "cluename": phone,
  907. "top_cluetype": "532",
  908. "sub_cluetype": "475",
  909. "trailstatus": "01",
  910. "name": name,
  911. "phone": phone,
  912. "comeintime_open": nowTime,
  913. "comeinsource_open": 1,
  914. "FREEZE_TIME": nowTime,
  915. })
  916. }
  917. if clueId > 0 {
  918. TiDb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  919. "clue_id": clueId,
  920. "position_id": -1,
  921. "change_type": "创建线索",
  922. "new_value": "系统自动创建",
  923. "createtime": nowTime,
  924. "BCPCID": common.GetRandom(32),
  925. "operator_id": -1,
  926. })
  927. }
  928. }
  929. }
  930. }
  931. common.WriteSysConfig(&cfg)
  932. log.Println("userbase定时任务结束")
  933. }
  934. func getRunOk() bool {
  935. currentTime, runOk := time.Now(), false
  936. if currentTime.Weekday() == time.Sunday {
  937. isok := false
  938. for k, v := range DateMap {
  939. if currentTime.Format(date.Date_Short_Layout) == k && v == 2 {
  940. isok = true
  941. }
  942. }
  943. if isok {
  944. runOk = true
  945. }
  946. } else {
  947. isok := true
  948. for k, v := range DateMap {
  949. if currentTime.Format(date.Date_Short_Layout) == k && v == 1 {
  950. isok = false
  951. }
  952. }
  953. if isok {
  954. runOk = true
  955. }
  956. }
  957. return runOk
  958. }
  959. func getAreaCode(userId string) (code string) {
  960. followData := Base.Find("follow_project_monitor", map[string]interface{}{"s_userid": userId}, "", "", -1, -1)
  961. sidArr := []string{}
  962. if followData != nil && len(*followData) > 0 {
  963. for _, v := range *followData {
  964. infoId := common.ObjToString(v["s_id"])
  965. sidArr = append(sidArr, infoId)
  966. }
  967. }
  968. if len(sidArr) > 0 {
  969. query := `{"query": {"bool": {"must": [{"terms": {"_id": ["%s"]}}],"must_not": [],"should": []}}}`
  970. query = fmt.Sprintf(query, strings.Join(sidArr, `","`))
  971. biddingData := Es.Get("bidding", "bidding", query)
  972. if biddingData != nil && len(*biddingData) > 0 {
  973. codeMap := map[string]string{}
  974. codeArr := []string{}
  975. for _, v := range *biddingData {
  976. area := common.ObjToString(v["area"])
  977. address := common.ObjToString(v["city"])
  978. if address == "" {
  979. address = area
  980. }
  981. codeMap[address] = AreaCode[address]
  982. }
  983. if len(codeMap) > 0 {
  984. for _, v := range codeMap {
  985. codeArr = append(codeArr, v)
  986. }
  987. }
  988. if len(codeArr) > 0 {
  989. code = strings.Join(codeArr, ",")
  990. }
  991. }
  992. }
  993. log.Println("code ", code)
  994. return
  995. }
  996. func getClueType(item string, data map[string]interface{}, sourceCode string, sourceId int64, isSub bool) (pcode, code, level, topname, subname string) {
  997. if item == "orders" {
  998. productType := common.ObjToString(data["product_type"])
  999. pcode = "1"
  1000. level = "A"
  1001. topname = "提交订单未支付"
  1002. if productType == "VIP订阅" {
  1003. code = "6"
  1004. subname = "超级订阅"
  1005. } else if productType == "大会员" {
  1006. code = "7"
  1007. subname = "大会员"
  1008. } else if productType == "数据流量包" {
  1009. code = "8"
  1010. subname = "数据流量包"
  1011. } else if productType == "历史数据" {
  1012. code = "9"
  1013. subname = "数据自助导出"
  1014. }
  1015. } else if item == "users" && sourceCode != "bidCreditReportPreview" && sourceCode != "bidCreditReportFile" {
  1016. if isSub {
  1017. pcode = "532"
  1018. code = "947"
  1019. level = "C"
  1020. topname = "其他"
  1021. subname = "被分配大会员子账号权限"
  1022. } else {
  1023. pcode = "4"
  1024. code = "154"
  1025. level = "C"
  1026. topname = "新增注册"
  1027. subname = "新增注册用户"
  1028. }
  1029. } else if item == "users" && (sourceCode == "bidCreditReportPreview" || sourceCode == "bidCreditReportFile") {
  1030. pcode = "4"
  1031. code = "767"
  1032. level = "B"
  1033. topname = "新增注册"
  1034. subname = "信用报告引流用户"
  1035. } else if item == "message" {
  1036. pcode = "532"
  1037. code = "477"
  1038. level = "B"
  1039. topname = "其他"
  1040. subname = "机器人客服主动咨询"
  1041. } else if item == "readClue" {
  1042. level = "A"
  1043. topname = "超级订阅临期用户"
  1044. pcode = "614"
  1045. if sourceId == 1 {
  1046. code = "615"
  1047. subname = "60天后到期"
  1048. } else if sourceId == 2 {
  1049. code = "616"
  1050. subname = "45天后到期"
  1051. } else if sourceId == 3 {
  1052. code = "617"
  1053. subname = "15天后到期"
  1054. } else {
  1055. code = "618"
  1056. subname = "7天后到期"
  1057. }
  1058. } else if item == "allocation" {
  1059. pcode = "532"
  1060. code = "671"
  1061. level = "D"
  1062. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  1063. if pcodeData != nil && len(*pcodeData) > 0 {
  1064. topname = common.ObjToString((*pcodeData)["name"])
  1065. }
  1066. pcodeData = TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": code}, "", "")
  1067. if pcodeData != nil && len(*pcodeData) > 0 {
  1068. subname = common.ObjToString((*pcodeData)["name"])
  1069. }
  1070. } else if item == "rebind" {
  1071. pcode = "532"
  1072. code = "670"
  1073. level = "D"
  1074. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  1075. if pcodeData != nil && len(*pcodeData) > 0 {
  1076. topname = common.ObjToString((*pcodeData)["name"])
  1077. }
  1078. pcodeData = TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": code}, "", "")
  1079. if pcodeData != nil && len(*pcodeData) > 0 {
  1080. subname = common.ObjToString((*pcodeData)["name"])
  1081. }
  1082. } else if item == "invite" {
  1083. codeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": sourceCode}, "", "")
  1084. if codeData != nil && len(*codeData) > 0 {
  1085. pcode = common.ObjToString((*codeData)["pcode"])
  1086. code = common.ObjToString((*codeData)["code"])
  1087. level = common.ObjToString((*codeData)["clue_level"])
  1088. subname = common.ObjToString((*codeData)["name"])
  1089. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  1090. if pcodeData != nil && len(*pcodeData) > 0 {
  1091. topname = common.ObjToString((*pcodeData)["name"])
  1092. }
  1093. }
  1094. } else if item == "tag" {
  1095. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"name": gconv.String(data["topName"]), "level": 1}, "", "")
  1096. if pcodeData != nil && len(*pcodeData) > 0 {
  1097. pcode = common.ObjToString((*pcodeData)["code"])
  1098. topname = common.ObjToString((*pcodeData)["name"])
  1099. codeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"name": gconv.String(data["subName"]), "level": 2}, "", "")
  1100. if codeData != nil && len(*codeData) > 0 {
  1101. subname = common.ObjToString((*codeData)["name"])
  1102. level = common.ObjToString((*codeData)["clue_level"])
  1103. code = common.ObjToString((*codeData)["code"])
  1104. }
  1105. }
  1106. } else if item == "powerdDele" {
  1107. pcode = "532"
  1108. code = "949"
  1109. level = "C"
  1110. topname = "其他"
  1111. subname = "产品权限被企业删除"
  1112. } else {
  1113. if sourceCode != "" {
  1114. codeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"source": sourceCode}, "", "")
  1115. if codeData != nil && len(*codeData) > 0 {
  1116. pcode = common.ObjToString((*codeData)["pcode"])
  1117. code = common.ObjToString((*codeData)["code"])
  1118. level = common.ObjToString((*codeData)["clue_level"])
  1119. subname = common.ObjToString((*codeData)["name"])
  1120. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  1121. if pcodeData != nil && len(*pcodeData) > 0 {
  1122. topname = common.ObjToString((*pcodeData)["name"])
  1123. }
  1124. }
  1125. }
  1126. }
  1127. return
  1128. }
  1129. // 获取自动分配的人
  1130. func autoDraw(userId, mode, cluename, phone string, isGroup, isCommerce int) (positionId int64, seatNumber, saleName string, saleData []map[string]interface{}, isOk, isFreeze bool, noticePositionId int64) {
  1131. isOk = false
  1132. isFreeze = false
  1133. pdata := TiDb.SelectBySql(`select * from dwd_f_crm_personnel_management where seat_number is not null and seat_number != ""`)
  1134. if userId != "" {
  1135. saleData = *pdata
  1136. //查一下之前有没有设置的人
  1137. data := TiDb.FindOne("temporary_assignment", map[string]interface{}{
  1138. "userId": userId,
  1139. "status": 0,
  1140. }, "", "")
  1141. if data != nil && len(*data) > 0 {
  1142. positionId, seatNumber, saleName, isOk = gconv.Int64((*data)["positionId"]), gconv.String((*data)["seatNumber"]), gconv.String((*data)["saleName"]), true
  1143. isFreeze = FindUpperLimit(gconv.String(positionId), mode, true)
  1144. TiDb.Update("temporary_assignment", map[string]interface{}{
  1145. "userId": userId,
  1146. }, map[string]interface{}{
  1147. "status": 1,
  1148. })
  1149. return
  1150. }
  1151. }
  1152. if phone != "" && TiDb.Count("dwd_f_crm_clue_info", map[string]interface{}{"phone": phone, "is_assign": 1}) == 0 { //线索没销售进入,有销售走分配次数最少的逻辑
  1153. if isGroup == 0 && isCommerce == 1 && cluename != "" { //非集团在工商库线索名不为空
  1154. //cdata := TiDb.Find("dwd_f_crm_clue_info", map[string]interface{}{"cluename": cluename, "is_assign": 1}, "", "", -1, -1)
  1155. 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)
  1156. if cdata != nil && len(*cdata) > 0 { //找到了公司有人在跟进
  1157. isOk = true
  1158. pdata := TiDb.SelectBySql(`select * from dwd_f_crm_personnel_management where seat_number is not null and seat_number != ""`)
  1159. if pdata == nil {
  1160. positionId = 0
  1161. seatNumber = ""
  1162. saleName = ""
  1163. return
  1164. }
  1165. saleData = *pdata
  1166. cdataNew := []map[string]interface{}{}
  1167. if len(*cdata) > 1 {
  1168. //可能有多个人跟进
  1169. personMap := map[int64]bool{}
  1170. upperLimitPersonMap := map[int64]bool{}
  1171. upperLimitCdataNew := []map[string]interface{}{}
  1172. upperLimitCount := 0
  1173. isFull := false
  1174. for _, m := range *cdata {
  1175. positionid1 := gconv.Int64(m["position_id"])
  1176. for _, v := range *pdata {
  1177. resign := common.IntAll(v["resign"])
  1178. assign_type := common.IntAll(v["assign_type"])
  1179. role_id := common.IntAll(v["role_id"])
  1180. if positionid1 == common.Int64All(v["position_id"]) {
  1181. if resign == 0 && (assign_type == 1 || role_id == 8) {
  1182. if !FindUpperLimit(gconv.String(positionid1), mode, true) {
  1183. personMap[positionid1] = true
  1184. m["saleName"] = common.ObjToString(v["name"])
  1185. cdataNew = append(cdataNew, m)
  1186. } else {
  1187. upperLimitCount++
  1188. upperLimitPersonMap[positionid1] = true
  1189. m["saleName"] = common.ObjToString(v["name"])
  1190. upperLimitCdataNew = append(upperLimitCdataNew, m)
  1191. }
  1192. }
  1193. }
  1194. }
  1195. }
  1196. if len(cdataNew) == 0 && len(upperLimitCdataNew) > 0 {
  1197. //没有达上限的人数为0 全部都是达上限的
  1198. personMap = upperLimitPersonMap
  1199. cdataNew = upperLimitCdataNew
  1200. isFull = true
  1201. }
  1202. //查询是否都有没有离职
  1203. if len(personMap) != 0 && len(cdataNew) > 0 {
  1204. layout := "2006-01-02 15:04:05"
  1205. //有人没有离职
  1206. data := map[string]interface{}{}
  1207. trailTime := int64(0)
  1208. for _, m := range cdataNew {
  1209. currentTime := int64(0)
  1210. if gconv.String(m["trail_time"]) == "" {
  1211. continue
  1212. }
  1213. t, _ := time.Parse(layout, gconv.String(m["trail_time"]))
  1214. currentTime = t.Unix()
  1215. if currentTime > trailTime {
  1216. trailTime = currentTime
  1217. data = m
  1218. }
  1219. }
  1220. if trailTime == 0 {
  1221. //需要查看通话记录
  1222. lastRingTime := int64(0)
  1223. for _, m := range cdataNew {
  1224. currentTime := int64(0)
  1225. if gconv.String(m["last_ring_time"]) == "" {
  1226. continue
  1227. }
  1228. t, _ := time.Parse(layout, gconv.String(m["last_ring_time"]))
  1229. currentTime = t.Unix()
  1230. if currentTime > lastRingTime {
  1231. lastRingTime = currentTime
  1232. data = m
  1233. }
  1234. }
  1235. if lastRingTime != 0 {
  1236. positionId = common.Int64All(data["position_id"])
  1237. noticePositionId = positionId
  1238. seatNumber = common.ObjToString(data["seatNumber"])
  1239. saleName = common.ObjToString(data["saleName"])
  1240. if isFull {
  1241. isFreeze = true
  1242. noticePositionId = positionId
  1243. positionId = 0
  1244. seatNumber = ""
  1245. saleName = ""
  1246. }
  1247. return
  1248. } else {
  1249. count := 0
  1250. //线索数量判断
  1251. for i, v := range cdataNew {
  1252. if i == 0 {
  1253. count = gconv.Int(v["count"])
  1254. data = v
  1255. } else {
  1256. if count < gconv.Int(v["count"]) {
  1257. count = gconv.Int(v["count"])
  1258. data = v
  1259. }
  1260. }
  1261. }
  1262. positionId = common.Int64All(data["position_id"])
  1263. noticePositionId = positionId
  1264. saleName = common.ObjToString(data["saleName"])
  1265. seatNumber = common.ObjToString(data["seatNumber"])
  1266. if isFull {
  1267. isFreeze = true
  1268. noticePositionId = positionId
  1269. positionId = 0
  1270. seatNumber = ""
  1271. saleName = ""
  1272. }
  1273. return
  1274. }
  1275. } else {
  1276. positionId = common.Int64All(data["position_id"])
  1277. noticePositionId = positionId
  1278. seatNumber = common.ObjToString(data["seatNumber"])
  1279. saleName = common.ObjToString(data["saleName"])
  1280. if isFull {
  1281. isFreeze = true
  1282. noticePositionId = positionId
  1283. positionId = 0
  1284. seatNumber = ""
  1285. saleName = ""
  1286. }
  1287. return
  1288. }
  1289. }
  1290. } else {
  1291. //只有一人跟进
  1292. //(1)该销售人员未离职,则继续分配给该销售人员(保持现状);
  1293. //该销售人员已离职,则随机分配
  1294. positionId = common.Int64All((*cdata)[0]["position_id"])
  1295. noticePositionId = positionId
  1296. seatNumber = common.ObjToString((*cdata)[0]["seatNumber"])
  1297. for _, v := range *pdata {
  1298. resign := common.IntAll(v["resign"])
  1299. assign_type := common.IntAll(v["assign_type"])
  1300. role_id := common.IntAll(v["role_id"])
  1301. if positionId == common.Int64All(v["position_id"]) {
  1302. if resign == 0 && (assign_type == 1 || role_id == 8) {
  1303. if FindUpperLimit(gconv.String(positionId), mode, true) {
  1304. isFreeze = true
  1305. positionId = 0
  1306. seatNumber = ""
  1307. saleName = ""
  1308. break
  1309. } else {
  1310. saleName = common.ObjToString(v["name"])
  1311. return
  1312. }
  1313. }
  1314. }
  1315. }
  1316. }
  1317. }
  1318. }
  1319. }
  1320. positionId = 0
  1321. seatNumber = ""
  1322. saleName = ""
  1323. query := `select * from dwd_f_crm_personnel_management where assign_type = 1 and`
  1324. if mode == "A" {
  1325. query += ` assign_level like "%A%"`
  1326. } else if mode == "B" {
  1327. query += ` assign_level like "%B%"`
  1328. } else if mode == "D" {
  1329. query += ` assign_level like "%D%"`
  1330. } else if mode == "C" {
  1331. query += ` assign_level like "%C%"`
  1332. } else if mode == "S" {
  1333. query += ` assign_level like "%S%"`
  1334. } else if mode == "E" {
  1335. query += ` assign_level like "%E%"`
  1336. }
  1337. data := TiDb.SelectBySql(query)
  1338. if data != nil && len(*data) > 0 {
  1339. saleData = *data
  1340. sql := "select * from dwd_f_crm_clue_autodraw_record where clue_level = ?"
  1341. countData := TiDb.SelectBySql(sql, mode)
  1342. if countData != nil && len(*countData) > 0 {
  1343. for _, v := range *data {
  1344. isOk := false //判断是否有新员工
  1345. for _, vv := range *countData {
  1346. if common.Int64All(v["position_id"]) == common.Int64All(vv["position_id"]) {
  1347. if common.IntAll(v["resign"]) == 0 {
  1348. vv["status"] = 1
  1349. } else {
  1350. vv["status"] = 2
  1351. }
  1352. isOk = true
  1353. }
  1354. }
  1355. if !isOk { //有新员工直接分给新员工
  1356. positionId = common.Int64All(v["position_id"])
  1357. saleName = common.ObjToString(v["name"])
  1358. log.Println("新员工, ", positionId, saleName)
  1359. rData := TiDb.FindOne("dwd_f_crm_clue_autodraw_record", map[string]interface{}{"clue_level": mode}, "", "count desc")
  1360. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  1361. "position_id": positionId,
  1362. "clue_level": mode,
  1363. "count": common.Int64All((*rData)["count"]),
  1364. })
  1365. break
  1366. }
  1367. }
  1368. if positionId == 0 {
  1369. res := int64(0)
  1370. countres := 0
  1371. for _, v := range *countData {
  1372. if common.IntAll(v["status"]) == 1 {
  1373. if FindUpperLimit(gconv.String(v["position_id"]), mode, false) {
  1374. continue
  1375. }
  1376. if countres == 0 {
  1377. res = common.Int64All(v["count"])
  1378. positionId = common.Int64All(v["position_id"])
  1379. } else {
  1380. if common.Int64All(v["count"]) <= res {
  1381. res = common.Int64All(v["count"])
  1382. positionId = common.Int64All(v["position_id"])
  1383. }
  1384. }
  1385. countres++
  1386. }
  1387. }
  1388. log.Println(444, res)
  1389. }
  1390. } else {
  1391. for _, kv := range *data {
  1392. positionId1 := gconv.String(kv["position_id"])
  1393. if !FindUpperLimit(positionId1, "", false) {
  1394. positionId = common.Int64All(kv["position_id"])
  1395. saleName = common.ObjToString(kv["name"])
  1396. rData := TiDb.FindOne("dwd_f_crm_clue_autodraw_record", map[string]interface{}{"clue_level": mode}, "", "count desc")
  1397. if rData != nil && len(*rData) > 0 {
  1398. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  1399. "position_id": positionId,
  1400. "clue_level": mode,
  1401. "count": common.Int64All((*rData)["count"]),
  1402. })
  1403. } else {
  1404. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  1405. "position_id": positionId,
  1406. "clue_level": mode,
  1407. "count": 0,
  1408. })
  1409. }
  1410. break
  1411. }
  1412. }
  1413. }
  1414. for _, v := range *data {
  1415. if positionId == common.Int64All(v["position_id"]) {
  1416. seatNumber = common.ObjToString(v["seat_number"])
  1417. saleName = common.ObjToString(v["name"])
  1418. }
  1419. }
  1420. }
  1421. return
  1422. }
  1423. // 通过管理后台添加的子账号 获取自动分配的人
  1424. func subAutoDraw(mode, cluename, phone string, isGroup, isCommerce int, positionId int64, seatNumber, saleName string) (newPositionId int64, newSeatNumber, newSaleName string, saleData []map[string]interface{}, isOk, isFreeze bool, noticePositionId int64) {
  1425. isOk = false
  1426. isFreeze = false
  1427. newPositionId = positionId
  1428. newSeatNumber = seatNumber
  1429. newSaleName = saleName
  1430. if TiDb.Count("dwd_f_crm_clue_info", map[string]interface{}{"phone": phone, "is_assign": 1}) == 0 { //线索没销售进入,有销售走分配次数最少的逻辑
  1431. if isGroup == 0 && isCommerce == 1 && cluename != "" { //非集团在工商库线索名不为空
  1432. isOk = true
  1433. pdata := TiDb.SelectBySql(`select * from dwd_f_crm_personnel_management where seat_number is not null and seat_number != ""`)
  1434. if pdata == nil {
  1435. newPositionId = 0
  1436. newSeatNumber = ""
  1437. newSaleName = ""
  1438. return
  1439. }
  1440. saleData = *pdata
  1441. //(1)该销售人员未离职,则继续分配给该销售人员(保持现状);
  1442. //该销售人员已离职,则随机分配
  1443. noticePositionId = positionId
  1444. for _, v := range saleData {
  1445. resign := common.IntAll(v["resign"])
  1446. assign_type := common.IntAll(v["assign_type"])
  1447. role_id := common.IntAll(v["role_id"])
  1448. if positionId == common.Int64All(v["position_id"]) {
  1449. if resign == 0 && (assign_type == 1 || role_id == 8) {
  1450. if FindUpperLimit(gconv.String(positionId), mode, true) {
  1451. isFreeze = true
  1452. newPositionId = 0
  1453. newSeatNumber = ""
  1454. newSaleName = ""
  1455. break
  1456. } else {
  1457. newSaleName = common.ObjToString(v["name"])
  1458. return
  1459. }
  1460. }
  1461. }
  1462. }
  1463. }
  1464. }
  1465. return
  1466. }
  1467. func getPositionId(phone string) (positionId int64) {
  1468. userData, ok := Mgo.FindOne("user", map[string]interface{}{"s_phone": phone})
  1469. if ok && userData != nil && len(*userData) > 0 {
  1470. userId := common.Int64All((*userData)["base_user_id"])
  1471. positionData := Base.FindOne("base_position", map[string]interface{}{"type": 1, "ent_id": db.EntId, "user_id": userId}, "", "") //TODO ent_id
  1472. if positionData != nil && len(*positionData) > 0 {
  1473. positionId = common.Int64All((*positionData)["id"])
  1474. }
  1475. }
  1476. return
  1477. }
  1478. func GetCompanyType(companyName string, uId string) (int, int) {
  1479. isGroup, isCommerce := 0, 0
  1480. uCount := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"uid": uId}, "is_artificially_modified,cluename", "")
  1481. if uCount != nil && len(*uCount) > 0 {
  1482. isUpdate := gconv.Int64((*uCount)["is_artificially_modified"])
  1483. if isUpdate == 1 {
  1484. companyName = gconv.String((*uCount)["cluename"])
  1485. }
  1486. if companyName == "" {
  1487. companyName = gconv.String((*uCount)["cluename"])
  1488. }
  1489. }
  1490. if companyName == "" {
  1491. return isGroup, isCommerce
  1492. }
  1493. //是否是集团
  1494. if c := TiDb.CountBySql(`select count(1) from group_company_name where company_name=?`, companyName); c > 0 {
  1495. isGroup = 1
  1496. }
  1497. //是否在工商库
  1498. if companyName != "" {
  1499. if c := MgoQyxy.Count("qyxy_std", map[string]interface{}{"company_name": companyName, "company_type": map[string]interface{}{"$ne": "个体工商户"}}); c > 0 {
  1500. isCommerce = 1
  1501. }
  1502. }
  1503. return isGroup, isCommerce
  1504. }
  1505. func GetCompanyTypeByClueId(companyName string, clueId int64) (int, int) {
  1506. isGroup, isCommerce := 0, 0
  1507. uCount := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"id": clueId}, "is_artificially_modified,cluename", "")
  1508. if uCount != nil && len(*uCount) > 0 {
  1509. isUpdate := gconv.Int64((*uCount)["is_artificially_modified"])
  1510. if isUpdate == 1 {
  1511. companyName = gconv.String((*uCount)["cluename"])
  1512. }
  1513. if companyName == "" {
  1514. companyName = gconv.String((*uCount)["cluename"])
  1515. }
  1516. }
  1517. if companyName == "" {
  1518. return isGroup, isCommerce
  1519. }
  1520. //是否是集团
  1521. if c := TiDb.CountBySql(`select count(1) from group_company_name where company_name=?`, companyName); c > 0 {
  1522. isGroup = 1
  1523. }
  1524. //是否在工商库
  1525. if companyName != "" {
  1526. if c := MgoQyxy.Count("qyxy_std", map[string]interface{}{"company_name": companyName, "company_type": map[string]interface{}{"$ne": "个体工商户"}}); c > 0 {
  1527. isCommerce = 1
  1528. }
  1529. }
  1530. return isGroup, isCommerce
  1531. }
  1532. // 查询是否达上限
  1533. func FindUpperLimit(positionId string, level string, isAdd bool) bool {
  1534. if positionId == "" {
  1535. return false
  1536. }
  1537. 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
  1538. if isFull && isAdd && level != "" {
  1539. TiDb.UpdateOrDeleteBySql(`update dwd_f_crm_clue_autodraw_record set count = count + 1 where position_id = ? and clue_level = ?`, positionId, level)
  1540. }
  1541. return isFull
  1542. }
  1543. func getSeatNumberPositionId(seatNumber string) (positionId int64) {
  1544. saleData := TiDb.FindOne("dwd_f_crm_personnel_management", map[string]interface{}{"seat_number": seatNumber}, "", "")
  1545. if saleData != nil && len(*saleData) > 0 {
  1546. positionId = common.Int64All((*saleData)["position_id"])
  1547. }
  1548. return
  1549. }
  1550. // 重新关注用户处理
  1551. func rebind() {
  1552. log.Println("重新关注用户处理开始")
  1553. //判断节假日
  1554. runOk := getRunOk()
  1555. if !runOk {
  1556. log.Println("不是工作日,任务暂停")
  1557. return
  1558. }
  1559. rebindTimeEnd := cfg.RebindTime
  1560. sql := fmt.Sprintf(`select * from freeClubSign where sub_again_date > "%s" order by sub_again_date asc`, rebindTimeEnd)
  1561. data := BiService.SelectBySql(sql)
  1562. if data != nil && *data != nil && len(*data) > 0 {
  1563. for _, v := range *data {
  1564. rebindTimeEnd = common.ObjToString(v["sub_again_date"])
  1565. registedates, _ := time.Parse(date.Date_Full_Layout, gconv.String(v["register_time"]))
  1566. if time.Now().Unix()-registedates.Unix() > int64(db.RegTimes)*86400 {
  1567. ok1, ok2, _ := FormatData(v, "rebind")
  1568. if !ok1 {
  1569. log.Println("线索卡点", "allocation", v, rebindTimeEnd)
  1570. } else {
  1571. if !ok2 {
  1572. log.Println("用户分配已达上限", "allocation", v, rebindTimeEnd)
  1573. }
  1574. }
  1575. }
  1576. }
  1577. cfg.RebindTime = rebindTimeEnd
  1578. common.WriteSysConfig(&cfg)
  1579. }
  1580. log.Println("重新关注用户处理结束")
  1581. }
  1582. // 活跃用户处理
  1583. func activeUsers() {
  1584. log.Println("活跃用户处理开始")
  1585. //判断节假日
  1586. runOk := getRunOk()
  1587. if !runOk {
  1588. log.Println("不是工作日,任务暂停")
  1589. return
  1590. }
  1591. //活跃用户查询
  1592. activeTimeEnd := cfg.ActiveTime
  1593. sql := fmt.Sprintf(`select * from freeClubSign where act_again_date > "%s" order by act_again_date asc`, activeTimeEnd)
  1594. data := BiService.SelectBySql(sql)
  1595. if data != nil && *data != nil && len(*data) > 0 {
  1596. for _, v := range *data {
  1597. activeTimeEnd = common.ObjToString(v["act_again_date"])
  1598. ok1, ok2, _ := FormatData(v, "allocation")
  1599. log.Println(v, "allocation", ok1, ok2)
  1600. if !ok1 {
  1601. log.Println("线索卡点", "allocation", v, activeTimeEnd)
  1602. } else {
  1603. if !ok2 {
  1604. log.Println("用户分配已达上限", "allocation", v, activeTimeEnd)
  1605. }
  1606. }
  1607. }
  1608. cfg.ActiveTime = activeTimeEnd
  1609. common.WriteSysConfig(&cfg)
  1610. }
  1611. log.Println("活跃用户处理结束")
  1612. }
  1613. // 安博会邮件
  1614. /*func ABHEmail(source string, data []map[string]interface{}) {
  1615. fileName, detailName, email, dir := "", "", "", ""
  1616. var err error
  1617. switch source {
  1618. case "user":
  1619. xlsxArr := []string{"姓名", "联系方式", "邮箱", "公司名称", "咨询需求", "销售线索来源", "具体来源", "留资时间"}
  1620. batch := FindBatch("abh")
  1621. fileName, detailName = "安博会用户注册销售线索 "+time.Now().Format(date.Date_Short_Layout)+"-"+batch, ""
  1622. xf := xlsx.NewFile()
  1623. style := xlsx.NewStyle()
  1624. style.Font.Size = 12
  1625. style.Font.Bold = true
  1626. style.Alignment.Vertical = "center"
  1627. style.Alignment.Horizontal = "center"
  1628. detailName = "今日新增安博会销售线索,请查收附件,及时跟进。"
  1629. sh, _ := xf.AddSheet("线索数据")
  1630. row1 := sh.AddRow()
  1631. for _, x := range xlsxArr {
  1632. cell := row1.AddCell()
  1633. cell.SetString(x)
  1634. cell.SetStyle(style)
  1635. }
  1636. for _, v := range data {
  1637. row := sh.AddRow()
  1638. row.AddCell().SetString(common.ObjToString(v["name"]))
  1639. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1640. row.AddCell().SetString(common.ObjToString(v["email"]))
  1641. row.AddCell().SetString(common.ObjToString(v["company_name"]))
  1642. row.AddCell().SetString("")
  1643. row.AddCell().SetString("")
  1644. row.AddCell().SetString("安博会用户注册")
  1645. row.AddCell().SetString(gconv.Time(gconv.Int64(v["createtime"])).Format(date.Date_Full_Layout))
  1646. //增加客户需求
  1647. }
  1648. dir = "./xlsx/abh/" + fileName + ".xlsx"
  1649. err = xf.Save(dir)
  1650. case "saleLeads":
  1651. xlsxArr := []string{"用户昵称", "姓名", "公司名称", "职位", "联系人电话", "购买条数", "用户邮箱", "已支付订单信息", "未支付订单类型", "销售线索来源", "具体来源", "数据需求"}
  1652. batch := FindBatch("abh")
  1653. fileName, detailName = time.Now().Format(date.Date_Short_Layout)+"-"+batch+"安博会电销销售线索", ""
  1654. xf := xlsx.NewFile()
  1655. style := xlsx.NewStyle()
  1656. style.Font.Size = 12
  1657. style.Font.Bold = true
  1658. style.Alignment.Vertical = "center"
  1659. style.Alignment.Horizontal = "center"
  1660. detailName = "今日新增安博会销售线索,请查收附件,及时跟进。"
  1661. sh, _ := xf.AddSheet("线索数据")
  1662. row1 := sh.AddRow()
  1663. for _, x := range xlsxArr {
  1664. cell := row1.AddCell()
  1665. cell.SetString(x)
  1666. cell.SetStyle(style)
  1667. }
  1668. filterArr := []string{"-pc", "-app", "-wx", "-h5"}
  1669. sourceMap := map[string]string{} //根据留资维表:tidb/Jianyu_subjectdb/d_saleleads_code
  1670. saleSource := TiDb.SelectBySql(`SELECT source,name FROM d_saleleads_code WHERE is_delete = 1`)
  1671. if saleSource != nil && len(*saleSource) > 0 {
  1672. for _, v := range *saleSource {
  1673. source := common.ObjToString(v["source"])
  1674. name := common.ObjToString(v["name"])
  1675. for _, s := range filterArr {
  1676. name = strings.ReplaceAll(name, s, "")
  1677. }
  1678. sourceMap[source] = name
  1679. }
  1680. }
  1681. for _, v := range data {
  1682. sources := common.ObjToString(v["source"])
  1683. interest := common.ObjToString(v["interest"])
  1684. row := sh.AddRow()
  1685. row.AddCell().SetString(common.ObjToString(v["usernickname"]))
  1686. row.AddCell().SetString(common.ObjToString(v["name"]))
  1687. row.AddCell().SetString(common.ObjToString(v["company"]))
  1688. row.AddCell().SetString(common.ObjToString(v["position"]))
  1689. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1690. row.AddCell().SetValue(0)
  1691. row.AddCell().SetString(common.ObjToString(v["email"]))
  1692. row.AddCell().SetString("")
  1693. row.AddCell().SetString("")
  1694. row.AddCell().SetString(sourceMap[sources])
  1695. row.AddCell().SetString(interest)
  1696. row.AddCell().SetString(common.ObjToString(v["data_requirement"]))
  1697. //增加客户需求
  1698. }
  1699. dir = "./xlsx/abh/" + fileName + ".xlsx"
  1700. err = xf.Save(dir)
  1701. case "big":
  1702. xlsxArr := []string{"用户昵称", "姓名", "公司名称", "职位", "联系人电话", "购买条数", "用户邮箱", "已支付订单信息", "未支付订单类型", "销售线索来源", "具体来源", "数据需求"}
  1703. batch := FindBatch("abh")
  1704. fileName, detailName = time.Now().Format(date.Date_Short_Layout)+"-"+batch+"安博会大客户销售线索", ""
  1705. xf := xlsx.NewFile()
  1706. style := xlsx.NewStyle()
  1707. style.Font.Size = 12
  1708. style.Font.Bold = true
  1709. style.Alignment.Vertical = "center"
  1710. style.Alignment.Horizontal = "center"
  1711. detailName = "今日新增安博会销售线索,请查收附件,及时跟进。"
  1712. sh, _ := xf.AddSheet("线索数据")
  1713. row1 := sh.AddRow()
  1714. for _, x := range xlsxArr {
  1715. cell := row1.AddCell()
  1716. cell.SetString(x)
  1717. cell.SetStyle(style)
  1718. }
  1719. for _, v := range data {
  1720. row := sh.AddRow()
  1721. row.AddCell().SetString(common.ObjToString(v["usernickname"]))
  1722. row.AddCell().SetString(common.ObjToString(v["username"]))
  1723. row.AddCell().SetString(common.ObjToString(v["company"]))
  1724. row.AddCell().SetString(common.ObjToString(v["job"]))
  1725. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1726. row.AddCell().SetValue(common.IntAll(v["data_count"]))
  1727. row.AddCell().SetString(common.ObjToString(v["email"]))
  1728. row.AddCell().SetString(common.ObjToString(v["payorderinfo"]))
  1729. row.AddCell().SetString(common.ObjToString(v["unpayorderinfo"]))
  1730. row.AddCell().SetString(common.ObjToString(v["source"]))
  1731. row.AddCell().SetString(common.ObjToString(v["interest"]))
  1732. row.AddCell().SetString(common.ObjToString(v["data_requirement"]))
  1733. //增加客户需求
  1734. }
  1735. dir = "./xlsx/abh/" + fileName + ".xlsx"
  1736. err = xf.Save(dir)
  1737. case "advisory":
  1738. xlsxArr := []string{"姓名", "联系方式", "邮箱", "公司名称", "咨询需求", "销售线索来源", "具体来源", "留资时间"}
  1739. //排序:首先按照“联系方式”排序,即同1个用户的留资放在一起,其次按照留资时间正序排序。
  1740. batch := FindBatch("abh")
  1741. fileName, detailName = "安博会咨询服务销售线索 "+time.Now().Format(date.Date_Short_Layout)+"-"+batch, ""
  1742. xf := xlsx.NewFile()
  1743. style := xlsx.NewStyle()
  1744. style.Font.Size = 12
  1745. style.Font.Bold = true
  1746. style.Alignment.Vertical = "center"
  1747. style.Alignment.Horizontal = "center"
  1748. detailName = "今日新增安博会销售线索,请查收附件,及时跟进。"
  1749. sh, _ := xf.AddSheet("线索数据")
  1750. row1 := sh.AddRow()
  1751. for _, x := range xlsxArr {
  1752. cell := row1.AddCell()
  1753. cell.SetString(x)
  1754. cell.SetStyle(style)
  1755. }
  1756. for _, v := range data {
  1757. row := sh.AddRow()
  1758. row.AddCell().SetString(common.ObjToString(v["username"]))
  1759. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1760. row.AddCell().SetString(common.ObjToString(v["email"]))
  1761. row.AddCell().SetString(common.ObjToString(v["company"]))
  1762. row.AddCell().SetString(common.ObjToString(v["data_requirement"]))
  1763. row.AddCell().SetString(common.ObjToString(v["source"]))
  1764. row.AddCell().SetString(common.ObjToString(v["interest"]))
  1765. row.AddCell().SetString(gconv.Time(gconv.Int64(v["createtime"])).Format(date.Date_Full_Layout))
  1766. }
  1767. dir = "./xlsx/abh/" + fileName + ".xlsx"
  1768. err = xf.Save(dir)
  1769. case "market":
  1770. xlsxArr := []string{"姓名", "联系人电话", "公司名称", "职位", "部门", "销售线索来源", "留资时间"}
  1771. batch := FindBatch("abh")
  1772. fileName, detailName = "安博会商务合作销售线索 "+time.Now().Format(date.Date_Short_Layout)+"-"+batch, ""
  1773. xf := xlsx.NewFile()
  1774. style := xlsx.NewStyle()
  1775. style.Font.Size = 12
  1776. style.Font.Bold = true
  1777. style.Alignment.Vertical = "center"
  1778. style.Alignment.Horizontal = "center"
  1779. detailName = "今日新增安博会销售线索,请查收附件,及时跟进。"
  1780. sh, _ := xf.AddSheet("线索数据")
  1781. row1 := sh.AddRow()
  1782. for _, x := range xlsxArr {
  1783. cell := row1.AddCell()
  1784. cell.SetString(x)
  1785. cell.SetStyle(style)
  1786. }
  1787. for _, v := range data {
  1788. row := sh.AddRow()
  1789. row.AddCell().SetString(common.ObjToString(v["username"]))
  1790. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1791. row.AddCell().SetString(common.ObjToString(v["company"]))
  1792. row.AddCell().SetString(common.ObjToString(v["job"]))
  1793. row.AddCell().SetString(common.ObjToString(v["branch"]))
  1794. row.AddCell().SetString(common.ObjToString(v["source"]))
  1795. row.AddCell().SetString(gconv.Time(gconv.Int64(v["createtime"])).Format(date.Date_Full_Layout))
  1796. //增加客户需求
  1797. }
  1798. dir = "./xlsx/abh/" + fileName + ".xlsx"
  1799. err = xf.Save(dir)
  1800. }
  1801. email = db.AbhEmail
  1802. if err != nil {
  1803. log.Println("xls error", err, dir)
  1804. } else {
  1805. gmail := &mail.GmailAuth{
  1806. SmtpHost: "smtp.exmail.qq.com",
  1807. SmtpPort: 465,
  1808. User: "public03@topnet.net.cn",
  1809. Pwd: "ue9Rg9Sf4CVtdm5a",
  1810. }
  1811. status := mail.GSendMail_q("剑鱼标讯", email, "", "", fileName, detailName, dir, fileName+".xlsx", gmail)
  1812. if status {
  1813. log.Println("send mail success", fileName, email)
  1814. }
  1815. }
  1816. }*/
  1817. // 安防邮件
  1818. func AFEmail(data []map[string]interface{}) {
  1819. xlsxArr := []string{"姓名", "联系方式", "邮箱", "公司名称", "咨询需求", "销售线索来源", "具体来源", "留资时间"}
  1820. batch := FindBatch("af")
  1821. fileName, detailName := "安防销售线索 "+time.Now().Format(date.Date_Short_Layout)+"-"+batch, ""
  1822. xf := xlsx.NewFile()
  1823. style := xlsx.NewStyle()
  1824. style.Font.Size = 12
  1825. style.Font.Bold = true
  1826. style.Alignment.Vertical = "center"
  1827. style.Alignment.Horizontal = "center"
  1828. detailName = "今日新增安防销售线索,请查收附件,及时跟进。"
  1829. sh, _ := xf.AddSheet("线索数据")
  1830. row1 := sh.AddRow()
  1831. for _, x := range xlsxArr {
  1832. cell := row1.AddCell()
  1833. cell.SetString(x)
  1834. cell.SetStyle(style)
  1835. }
  1836. for _, v := range data {
  1837. row := sh.AddRow()
  1838. row.AddCell().SetString(common.ObjToString(v["name"]))
  1839. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1840. row.AddCell().SetString(common.ObjToString(v["email"]))
  1841. row.AddCell().SetString(common.ObjToString(v["company_name"]))
  1842. row.AddCell().SetString("")
  1843. row.AddCell().SetString("")
  1844. row.AddCell().SetString("首次使用安防新注册")
  1845. row.AddCell().SetString(gconv.String(v["time"]))
  1846. //增加客户需求
  1847. }
  1848. email := db.AfEmail
  1849. dir := "./xlsx/af/" + fileName + ".xlsx"
  1850. err := xf.Save(dir)
  1851. if err != nil {
  1852. log.Println("xls error", err, dir)
  1853. } else {
  1854. gmail := &mail.GmailAuth{
  1855. SmtpHost: db.Mail.SmtpHost,
  1856. SmtpPort: db.Mail.SmtpPort,
  1857. User: db.Mail.User,
  1858. Pwd: db.Mail.Pwd,
  1859. }
  1860. status := mail.GSendMail_q("剑鱼标讯", email, "", "", fileName, detailName, dir, "", gmail)
  1861. if status {
  1862. log.Println("send mail success", fileName, email)
  1863. }
  1864. }
  1865. }
  1866. func populateAdvisoryData(sh *xlsx.Sheet, data []map[string]interface{}) error {
  1867. for _, v := range data {
  1868. row := sh.AddRow()
  1869. row.AddCell().SetString(common.ObjToString(v["username"]))
  1870. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1871. row.AddCell().SetString(common.ObjToString(v["email"]))
  1872. row.AddCell().SetString(common.ObjToString(v["company"]))
  1873. row.AddCell().SetString(common.ObjToString(v["data_requirement"]))
  1874. row.AddCell().SetString(common.ObjToString(v["source"]))
  1875. row.AddCell().SetString(common.ObjToString(v["interest"]))
  1876. row.AddCell().SetString(gconv.Time(gconv.Int64(v["createtime"])).Format(date.Date_Full_Layout))
  1877. }
  1878. return nil
  1879. }
  1880. // 邀请用户处理
  1881. func inviteUser() {
  1882. log.Println("邀请用户处理开始")
  1883. //判断节假日
  1884. runOk := getRunOk()
  1885. if !runOk {
  1886. log.Println("不是工作日,任务暂停")
  1887. return
  1888. }
  1889. rebindTimeEnd := cfg.InviteTime
  1890. sql := fmt.Sprintf(`select * from user_statistics where createTime > "%s" order by createTime asc`, rebindTimeEnd)
  1891. //sql := fmt.Sprintf(`select * from user_statistics where createTime = "%s" order by createTime asc`, rebindTimeEnd)
  1892. data := BiService.SelectBySql(sql)
  1893. if data != nil && *data != nil && len(*data) > 0 {
  1894. for _, v := range *data {
  1895. rebindTimeEnd = common.ObjToString(v["createTime"])
  1896. event := gconv.Int64(v["event"])
  1897. switch event {
  1898. case 1:
  1899. v["sourceCode"] = "736"
  1900. case 2:
  1901. v["sourceCode"] = "737"
  1902. case 3:
  1903. v["sourceCode"] = "738"
  1904. }
  1905. v["user_id"] = gconv.String(v["userId"])
  1906. ok1, ok2, _ := FormatData(v, "invite")
  1907. if !ok1 {
  1908. log.Println("线索卡点", "invite", v, rebindTimeEnd)
  1909. } else {
  1910. if !ok2 {
  1911. log.Println("用户分配已达上限", "invite", v, rebindTimeEnd)
  1912. }
  1913. }
  1914. }
  1915. cfg.InviteTime = rebindTimeEnd
  1916. common.WriteSysConfig(&cfg)
  1917. }
  1918. log.Println("邀请用户处理结束")
  1919. }
  1920. // 开年活动
  1921. func nextYearActivity() {
  1922. log.Println("开年活动处理开始")
  1923. //判断节假日
  1924. runOk := getRunOk()
  1925. if !runOk {
  1926. log.Println("不是工作日,任务暂停")
  1927. return
  1928. }
  1929. activityTimeEnd := cfg.ActivityTime
  1930. sql := fmt.Sprintf(`SELECT
  1931. a.*
  1932. FROM
  1933. jyactivities.lottery_user_account a
  1934. INNER JOIN jyactivities.lottery_prize_info b on a.create_time > "%s" and a.prize_id=b.id
  1935. INNER JOIN jyactivities.prize_base_info c on c.name like "%s" and b.pb_id=c.id
  1936. ORDER BY
  1937. a.create_time ASC
  1938. `, activityTimeEnd, "%超级订阅%")
  1939. data := Mysql.SelectBySql(sql)
  1940. if data != nil && *data != nil && len(*data) > 0 {
  1941. for _, v := range *data {
  1942. activityTimeEnd = common.ObjToString(v["create_time"])
  1943. v["sourceCode"] = gconv.Int64(v["active_id"])
  1944. v["user_id"] = gconv.String(v["mgo_user_id"])
  1945. ok1, ok2, _ := FormatData(v, "activity")
  1946. if !ok1 {
  1947. log.Println("线索卡点", "activity", v, activityTimeEnd)
  1948. } else {
  1949. if !ok2 {
  1950. log.Println("开年活动分配已达上限", "activity", v, activityTimeEnd)
  1951. }
  1952. }
  1953. }
  1954. cfg.ActivityTime = activityTimeEnd
  1955. common.WriteSysConfig(&cfg)
  1956. }
  1957. log.Println("开年活动处理结束")
  1958. }
  1959. // 获取用户渠道信息
  1960. func GetUserChannel(userId string) string {
  1961. if userId == "" {
  1962. return ""
  1963. }
  1964. codeArr := []string{}
  1965. if len(UserChannel) > 0 {
  1966. for i := range UserChannel {
  1967. codeArr = append(codeArr, fmt.Sprintf(`"%s"`, i))
  1968. }
  1969. }
  1970. //查找注册日志表
  1971. sql := fmt.Sprintf(`select channel_code from user_source where user_id ="%s" and channel_code in (%s) ORDER BY create_time desc limit 1 `, userId, strings.Join(codeArr, ","))
  1972. courceData := ThirdParty.SelectBySql(sql)
  1973. if courceData != nil && len(*courceData) > 0 {
  1974. channelCode := gconv.String((*courceData)[0]["channel_code"])
  1975. data, exit := UserChannel[channelCode]
  1976. if exit {
  1977. return gconv.String(data["clueCode"])
  1978. }
  1979. }
  1980. return ""
  1981. }