jobutil.go 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935
  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) (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. pcode = "4"
  1017. code = "154"
  1018. level = "C"
  1019. topname = "新增注册"
  1020. subname = "新增注册用户"
  1021. } else if item == "users" && (sourceCode == "bidCreditReportPreview" || sourceCode == "bidCreditReportFile") {
  1022. pcode = "4"
  1023. code = "767"
  1024. level = "B"
  1025. topname = "新增注册"
  1026. subname = "信用报告引流用户"
  1027. } else if item == "message" {
  1028. pcode = "532"
  1029. code = "477"
  1030. level = "B"
  1031. topname = "其他"
  1032. subname = "机器人客服主动咨询"
  1033. } else if item == "readClue" {
  1034. level = "A"
  1035. topname = "超级订阅临期用户"
  1036. pcode = "614"
  1037. if sourceId == 1 {
  1038. code = "615"
  1039. subname = "60天后到期"
  1040. } else if sourceId == 2 {
  1041. code = "616"
  1042. subname = "45天后到期"
  1043. } else if sourceId == 3 {
  1044. code = "617"
  1045. subname = "15天后到期"
  1046. } else {
  1047. code = "618"
  1048. subname = "7天后到期"
  1049. }
  1050. } else if item == "allocation" {
  1051. pcode = "532"
  1052. code = "671"
  1053. level = "D"
  1054. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  1055. if pcodeData != nil && len(*pcodeData) > 0 {
  1056. topname = common.ObjToString((*pcodeData)["name"])
  1057. }
  1058. pcodeData = TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": code}, "", "")
  1059. if pcodeData != nil && len(*pcodeData) > 0 {
  1060. subname = common.ObjToString((*pcodeData)["name"])
  1061. }
  1062. } else if item == "rebind" {
  1063. pcode = "532"
  1064. code = "670"
  1065. level = "D"
  1066. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  1067. if pcodeData != nil && len(*pcodeData) > 0 {
  1068. topname = common.ObjToString((*pcodeData)["name"])
  1069. }
  1070. pcodeData = TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": code}, "", "")
  1071. if pcodeData != nil && len(*pcodeData) > 0 {
  1072. subname = common.ObjToString((*pcodeData)["name"])
  1073. }
  1074. } else if item == "invite" {
  1075. codeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": sourceCode}, "", "")
  1076. if codeData != nil && len(*codeData) > 0 {
  1077. pcode = common.ObjToString((*codeData)["pcode"])
  1078. code = common.ObjToString((*codeData)["code"])
  1079. level = common.ObjToString((*codeData)["clue_level"])
  1080. subname = common.ObjToString((*codeData)["name"])
  1081. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  1082. if pcodeData != nil && len(*pcodeData) > 0 {
  1083. topname = common.ObjToString((*pcodeData)["name"])
  1084. }
  1085. }
  1086. } else if item == "tag" {
  1087. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"name": gconv.String(data["topName"]), "level": 1}, "", "")
  1088. if pcodeData != nil && len(*pcodeData) > 0 {
  1089. pcode = common.ObjToString((*pcodeData)["code"])
  1090. topname = common.ObjToString((*pcodeData)["name"])
  1091. codeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"name": gconv.String(data["subName"]), "level": 2}, "", "")
  1092. if codeData != nil && len(*codeData) > 0 {
  1093. subname = common.ObjToString((*codeData)["name"])
  1094. level = common.ObjToString((*codeData)["clue_level"])
  1095. code = common.ObjToString((*codeData)["code"])
  1096. }
  1097. }
  1098. } else {
  1099. if sourceCode != "" {
  1100. codeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"source": sourceCode}, "", "")
  1101. if codeData != nil && len(*codeData) > 0 {
  1102. pcode = common.ObjToString((*codeData)["pcode"])
  1103. code = common.ObjToString((*codeData)["code"])
  1104. level = common.ObjToString((*codeData)["clue_level"])
  1105. subname = common.ObjToString((*codeData)["name"])
  1106. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  1107. if pcodeData != nil && len(*pcodeData) > 0 {
  1108. topname = common.ObjToString((*pcodeData)["name"])
  1109. }
  1110. }
  1111. }
  1112. }
  1113. return
  1114. }
  1115. // 获取自动分配的人
  1116. func autoDraw(userId, mode, cluename, phone string, isGroup, isCommerce int) (positionId int64, seatNumber, saleName string, saleData []map[string]interface{}, isOk, isFreeze bool, noticePositionId int64) {
  1117. isOk = false
  1118. isFreeze = false
  1119. pdata := TiDb.SelectBySql(`select * from dwd_f_crm_personnel_management where seat_number is not null and seat_number != ""`)
  1120. if userId != "" {
  1121. saleData = *pdata
  1122. //查一下之前有没有设置的人
  1123. data := TiDb.FindOne("temporary_assignment", map[string]interface{}{
  1124. "userId": userId,
  1125. "status": 0,
  1126. }, "", "")
  1127. if data != nil && len(*data) > 0 {
  1128. positionId, seatNumber, saleName, isOk = gconv.Int64((*data)["positionId"]), gconv.String((*data)["seatNumber"]), gconv.String((*data)["saleName"]), true
  1129. isFreeze = FindUpperLimit(gconv.String(positionId), mode, true)
  1130. TiDb.Update("temporary_assignment", map[string]interface{}{
  1131. "userId": userId,
  1132. }, map[string]interface{}{
  1133. "status": 1,
  1134. })
  1135. return
  1136. }
  1137. }
  1138. if phone != "" && TiDb.Count("dwd_f_crm_clue_info", map[string]interface{}{"phone": phone, "is_assign": 1}) == 0 { //线索没销售进入,有销售走分配次数最少的逻辑
  1139. if isGroup == 0 && isCommerce == 1 && cluename != "" { //非集团在工商库线索名不为空
  1140. //cdata := TiDb.Find("dwd_f_crm_clue_info", map[string]interface{}{"cluename": cluename, "is_assign": 1}, "", "", -1, -1)
  1141. 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)
  1142. if cdata != nil && len(*cdata) > 0 { //找到了公司有人在跟进
  1143. isOk = true
  1144. pdata := TiDb.SelectBySql(`select * from dwd_f_crm_personnel_management where seat_number is not null and seat_number != ""`)
  1145. if pdata == nil {
  1146. positionId = 0
  1147. seatNumber = ""
  1148. saleName = ""
  1149. return
  1150. }
  1151. saleData = *pdata
  1152. cdataNew := []map[string]interface{}{}
  1153. if len(*cdata) > 1 {
  1154. //可能有多个人跟进
  1155. personMap := map[int64]bool{}
  1156. upperLimitPersonMap := map[int64]bool{}
  1157. upperLimitCdataNew := []map[string]interface{}{}
  1158. upperLimitCount := 0
  1159. isFull := false
  1160. for _, m := range *cdata {
  1161. positionid1 := gconv.Int64(m["position_id"])
  1162. for _, v := range *pdata {
  1163. resign := common.IntAll(v["resign"])
  1164. assign_type := common.IntAll(v["assign_type"])
  1165. role_id := common.IntAll(v["role_id"])
  1166. if positionid1 == common.Int64All(v["position_id"]) {
  1167. if resign == 0 && (assign_type == 1 || role_id == 8) {
  1168. if !FindUpperLimit(gconv.String(positionid1), mode, true) {
  1169. personMap[positionid1] = true
  1170. m["saleName"] = common.ObjToString(v["name"])
  1171. cdataNew = append(cdataNew, m)
  1172. } else {
  1173. upperLimitCount++
  1174. upperLimitPersonMap[positionid1] = true
  1175. m["saleName"] = common.ObjToString(v["name"])
  1176. upperLimitCdataNew = append(upperLimitCdataNew, m)
  1177. }
  1178. }
  1179. }
  1180. }
  1181. }
  1182. if len(cdataNew) == 0 && len(upperLimitCdataNew) > 0 {
  1183. //没有达上限的人数为0 全部都是达上限的
  1184. personMap = upperLimitPersonMap
  1185. cdataNew = upperLimitCdataNew
  1186. isFull = true
  1187. }
  1188. //查询是否都有没有离职
  1189. if len(personMap) != 0 && len(cdataNew) > 0 {
  1190. layout := "2006-01-02 15:04:05"
  1191. //有人没有离职
  1192. data := map[string]interface{}{}
  1193. trailTime := int64(0)
  1194. for _, m := range cdataNew {
  1195. currentTime := int64(0)
  1196. if gconv.String(m["trail_time"]) == "" {
  1197. continue
  1198. }
  1199. t, _ := time.Parse(layout, gconv.String(m["trail_time"]))
  1200. currentTime = t.Unix()
  1201. if currentTime > trailTime {
  1202. trailTime = currentTime
  1203. data = m
  1204. }
  1205. }
  1206. if trailTime == 0 {
  1207. //需要查看通话记录
  1208. lastRingTime := int64(0)
  1209. for _, m := range cdataNew {
  1210. currentTime := int64(0)
  1211. if gconv.String(m["last_ring_time"]) == "" {
  1212. continue
  1213. }
  1214. t, _ := time.Parse(layout, gconv.String(m["last_ring_time"]))
  1215. currentTime = t.Unix()
  1216. if currentTime > lastRingTime {
  1217. lastRingTime = currentTime
  1218. data = m
  1219. }
  1220. }
  1221. if lastRingTime != 0 {
  1222. positionId = common.Int64All(data["position_id"])
  1223. noticePositionId = positionId
  1224. seatNumber = common.ObjToString(data["seatNumber"])
  1225. saleName = common.ObjToString(data["saleName"])
  1226. if isFull {
  1227. isFreeze = true
  1228. noticePositionId = positionId
  1229. positionId = 0
  1230. seatNumber = ""
  1231. saleName = ""
  1232. }
  1233. return
  1234. } else {
  1235. count := 0
  1236. //线索数量判断
  1237. for i, v := range cdataNew {
  1238. if i == 0 {
  1239. count = gconv.Int(v["count"])
  1240. data = v
  1241. } else {
  1242. if count < gconv.Int(v["count"]) {
  1243. count = gconv.Int(v["count"])
  1244. data = v
  1245. }
  1246. }
  1247. }
  1248. positionId = common.Int64All(data["position_id"])
  1249. noticePositionId = positionId
  1250. saleName = common.ObjToString(data["saleName"])
  1251. seatNumber = common.ObjToString(data["seatNumber"])
  1252. if isFull {
  1253. isFreeze = true
  1254. noticePositionId = positionId
  1255. positionId = 0
  1256. seatNumber = ""
  1257. saleName = ""
  1258. }
  1259. return
  1260. }
  1261. } else {
  1262. positionId = common.Int64All(data["position_id"])
  1263. noticePositionId = positionId
  1264. seatNumber = common.ObjToString(data["seatNumber"])
  1265. saleName = common.ObjToString(data["saleName"])
  1266. if isFull {
  1267. isFreeze = true
  1268. noticePositionId = positionId
  1269. positionId = 0
  1270. seatNumber = ""
  1271. saleName = ""
  1272. }
  1273. return
  1274. }
  1275. }
  1276. } else {
  1277. //只有一人跟进
  1278. //(1)该销售人员未离职,则继续分配给该销售人员(保持现状);
  1279. //该销售人员已离职,则随机分配
  1280. positionId = common.Int64All((*cdata)[0]["position_id"])
  1281. noticePositionId = positionId
  1282. seatNumber = common.ObjToString((*cdata)[0]["seatNumber"])
  1283. for _, v := range *pdata {
  1284. resign := common.IntAll(v["resign"])
  1285. assign_type := common.IntAll(v["assign_type"])
  1286. role_id := common.IntAll(v["role_id"])
  1287. if positionId == common.Int64All(v["position_id"]) {
  1288. if resign == 0 && (assign_type == 1 || role_id == 8) {
  1289. if FindUpperLimit(gconv.String(positionId), mode, true) {
  1290. isFreeze = true
  1291. positionId = 0
  1292. seatNumber = ""
  1293. saleName = ""
  1294. break
  1295. } else {
  1296. saleName = common.ObjToString(v["name"])
  1297. return
  1298. }
  1299. }
  1300. }
  1301. }
  1302. }
  1303. }
  1304. }
  1305. }
  1306. positionId = 0
  1307. seatNumber = ""
  1308. saleName = ""
  1309. query := `select * from dwd_f_crm_personnel_management where assign_type = 1 and`
  1310. if mode == "A" {
  1311. query += ` assign_level like "%A%"`
  1312. } else if mode == "B" {
  1313. query += ` assign_level like "%B%"`
  1314. } else if mode == "D" {
  1315. query += ` assign_level like "%D%"`
  1316. } else if mode == "C" {
  1317. query += ` assign_level like "%C%"`
  1318. } else if mode == "S" {
  1319. query += ` assign_level like "%S%"`
  1320. } else if mode == "E" {
  1321. query += ` assign_level like "%E%"`
  1322. }
  1323. data := TiDb.SelectBySql(query)
  1324. if data != nil && len(*data) > 0 {
  1325. saleData = *data
  1326. sql := "select * from dwd_f_crm_clue_autodraw_record where clue_level = ?"
  1327. countData := TiDb.SelectBySql(sql, mode)
  1328. if countData != nil && len(*countData) > 0 {
  1329. for _, v := range *data {
  1330. isOk := false //判断是否有新员工
  1331. for _, vv := range *countData {
  1332. if common.Int64All(v["position_id"]) == common.Int64All(vv["position_id"]) {
  1333. if common.IntAll(v["resign"]) == 0 {
  1334. vv["status"] = 1
  1335. } else {
  1336. vv["status"] = 2
  1337. }
  1338. isOk = true
  1339. }
  1340. }
  1341. if !isOk { //有新员工直接分给新员工
  1342. positionId = common.Int64All(v["position_id"])
  1343. saleName = common.ObjToString(v["name"])
  1344. log.Println("新员工, ", positionId, saleName)
  1345. rData := TiDb.FindOne("dwd_f_crm_clue_autodraw_record", map[string]interface{}{"clue_level": mode}, "", "count desc")
  1346. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  1347. "position_id": positionId,
  1348. "clue_level": mode,
  1349. "count": common.Int64All((*rData)["count"]),
  1350. })
  1351. break
  1352. }
  1353. }
  1354. if positionId == 0 {
  1355. res := int64(0)
  1356. countres := 0
  1357. for _, v := range *countData {
  1358. if common.IntAll(v["status"]) == 1 {
  1359. if FindUpperLimit(gconv.String(v["position_id"]), mode, false) {
  1360. continue
  1361. }
  1362. if countres == 0 {
  1363. res = common.Int64All(v["count"])
  1364. positionId = common.Int64All(v["position_id"])
  1365. } else {
  1366. if common.Int64All(v["count"]) <= res {
  1367. res = common.Int64All(v["count"])
  1368. positionId = common.Int64All(v["position_id"])
  1369. }
  1370. }
  1371. countres++
  1372. }
  1373. }
  1374. log.Println(444, res)
  1375. }
  1376. } else {
  1377. for _, kv := range *data {
  1378. positionId1 := gconv.String(kv["position_id"])
  1379. if !FindUpperLimit(positionId1, "", false) {
  1380. positionId = common.Int64All(kv["position_id"])
  1381. saleName = common.ObjToString(kv["name"])
  1382. rData := TiDb.FindOne("dwd_f_crm_clue_autodraw_record", map[string]interface{}{"clue_level": mode}, "", "count desc")
  1383. if rData != nil && len(*rData) > 0 {
  1384. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  1385. "position_id": positionId,
  1386. "clue_level": mode,
  1387. "count": common.Int64All((*rData)["count"]),
  1388. })
  1389. } else {
  1390. TiDb.Insert("dwd_f_crm_clue_autodraw_record", map[string]interface{}{
  1391. "position_id": positionId,
  1392. "clue_level": mode,
  1393. "count": 0,
  1394. })
  1395. }
  1396. break
  1397. }
  1398. }
  1399. }
  1400. for _, v := range *data {
  1401. if positionId == common.Int64All(v["position_id"]) {
  1402. seatNumber = common.ObjToString(v["seat_number"])
  1403. saleName = common.ObjToString(v["name"])
  1404. }
  1405. }
  1406. }
  1407. return
  1408. }
  1409. func getPositionId(phone string) (positionId int64) {
  1410. userData, ok := Mgo.FindOne("user", map[string]interface{}{"s_phone": phone})
  1411. if ok && userData != nil && len(*userData) > 0 {
  1412. userId := common.Int64All((*userData)["base_user_id"])
  1413. positionData := Base.FindOne("base_position", map[string]interface{}{"type": 1, "ent_id": db.EntId, "user_id": userId}, "", "") //TODO ent_id
  1414. if positionData != nil && len(*positionData) > 0 {
  1415. positionId = common.Int64All((*positionData)["id"])
  1416. }
  1417. }
  1418. return
  1419. }
  1420. func GetCompanyType(companyName string, uId string) (int, int) {
  1421. isGroup, isCommerce := 0, 0
  1422. uCount := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"uid": uId}, "", "")
  1423. if uCount != nil && len(*uCount) > 0 {
  1424. isUpdate := gconv.Int64((*uCount)["is_artificially_modified"])
  1425. if isUpdate == 1 {
  1426. companyName = gconv.String((*uCount)["cluename"])
  1427. }
  1428. if companyName == "" {
  1429. companyName = gconv.String((*uCount)["cluename"])
  1430. }
  1431. }
  1432. if companyName == "" {
  1433. return isGroup, isCommerce
  1434. }
  1435. //是否是集团
  1436. if c := TiDb.CountBySql(`select count(1) from group_company_name where company_name=?`, companyName); c > 0 {
  1437. isGroup = 1
  1438. }
  1439. //是否在工商库
  1440. if companyName != "" {
  1441. if c := MgoQyxy.Count("qyxy_std", map[string]interface{}{"company_name": companyName, "company_type": map[string]interface{}{"$ne": "个体工商户"}}); c > 0 {
  1442. isCommerce = 1
  1443. }
  1444. }
  1445. return isGroup, isCommerce
  1446. }
  1447. // 查询是否达上限
  1448. func FindUpperLimit(positionId string, level string, isAdd bool) bool {
  1449. if positionId == "" {
  1450. return false
  1451. }
  1452. 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
  1453. if isFull && isAdd && level != "" {
  1454. TiDb.UpdateOrDeleteBySql(`update dwd_f_crm_clue_autodraw_record set count = count + 1 where position_id = ? and clue_level = ?`, positionId, level)
  1455. }
  1456. return isFull
  1457. }
  1458. func getSeatNumberPositionId(seatNumber string) (positionId int64) {
  1459. saleData := TiDb.FindOne("dwd_f_crm_personnel_management", map[string]interface{}{"seat_number": seatNumber}, "", "")
  1460. if saleData != nil && len(*saleData) > 0 {
  1461. positionId = common.Int64All((*saleData)["position_id"])
  1462. }
  1463. return
  1464. }
  1465. // 重新关注用户处理
  1466. func rebind() {
  1467. log.Println("重新关注用户处理开始")
  1468. //判断节假日
  1469. runOk := getRunOk()
  1470. if !runOk {
  1471. log.Println("不是工作日,任务暂停")
  1472. return
  1473. }
  1474. rebindTimeEnd := cfg.RebindTime
  1475. sql := fmt.Sprintf(`select * from freeClubSign where sub_again_date > "%s" order by sub_again_date asc`, rebindTimeEnd)
  1476. data := BiService.SelectBySql(sql)
  1477. if data != nil && *data != nil && len(*data) > 0 {
  1478. for _, v := range *data {
  1479. rebindTimeEnd = common.ObjToString(v["sub_again_date"])
  1480. registedates, _ := time.Parse(date.Date_Full_Layout, gconv.String(v["register_time"]))
  1481. if time.Now().Unix()-registedates.Unix() > int64(db.RegTimes)*86400 {
  1482. ok1, ok2, _ := FormatData(v, "rebind")
  1483. if !ok1 {
  1484. log.Println("线索卡点", "allocation", v, rebindTimeEnd)
  1485. } else {
  1486. if !ok2 {
  1487. log.Println("用户分配已达上限", "allocation", v, rebindTimeEnd)
  1488. }
  1489. }
  1490. }
  1491. }
  1492. cfg.RebindTime = rebindTimeEnd
  1493. common.WriteSysConfig(&cfg)
  1494. }
  1495. log.Println("重新关注用户处理结束")
  1496. }
  1497. // 活跃用户处理
  1498. func activeUsers() {
  1499. log.Println("活跃用户处理开始")
  1500. //判断节假日
  1501. runOk := getRunOk()
  1502. if !runOk {
  1503. log.Println("不是工作日,任务暂停")
  1504. return
  1505. }
  1506. //活跃用户查询
  1507. activeTimeEnd := cfg.ActiveTime
  1508. sql := fmt.Sprintf(`select * from freeClubSign where act_again_date > "%s" order by act_again_date asc`, activeTimeEnd)
  1509. data := BiService.SelectBySql(sql)
  1510. if data != nil && *data != nil && len(*data) > 0 {
  1511. for _, v := range *data {
  1512. activeTimeEnd = common.ObjToString(v["act_again_date"])
  1513. ok1, ok2, _ := FormatData(v, "allocation")
  1514. log.Println(v, "allocation", ok1, ok2)
  1515. if !ok1 {
  1516. log.Println("线索卡点", "allocation", v, activeTimeEnd)
  1517. } else {
  1518. if !ok2 {
  1519. log.Println("用户分配已达上限", "allocation", v, activeTimeEnd)
  1520. }
  1521. }
  1522. }
  1523. cfg.ActiveTime = activeTimeEnd
  1524. common.WriteSysConfig(&cfg)
  1525. }
  1526. log.Println("活跃用户处理结束")
  1527. }
  1528. // 安博会邮件
  1529. /*func ABHEmail(source string, data []map[string]interface{}) {
  1530. fileName, detailName, email, dir := "", "", "", ""
  1531. var err error
  1532. switch source {
  1533. case "user":
  1534. xlsxArr := []string{"姓名", "联系方式", "邮箱", "公司名称", "咨询需求", "销售线索来源", "具体来源", "留资时间"}
  1535. batch := FindBatch("abh")
  1536. fileName, detailName = "安博会用户注册销售线索 "+time.Now().Format(date.Date_Short_Layout)+"-"+batch, ""
  1537. xf := xlsx.NewFile()
  1538. style := xlsx.NewStyle()
  1539. style.Font.Size = 12
  1540. style.Font.Bold = true
  1541. style.Alignment.Vertical = "center"
  1542. style.Alignment.Horizontal = "center"
  1543. detailName = "今日新增安博会销售线索,请查收附件,及时跟进。"
  1544. sh, _ := xf.AddSheet("线索数据")
  1545. row1 := sh.AddRow()
  1546. for _, x := range xlsxArr {
  1547. cell := row1.AddCell()
  1548. cell.SetString(x)
  1549. cell.SetStyle(style)
  1550. }
  1551. for _, v := range data {
  1552. row := sh.AddRow()
  1553. row.AddCell().SetString(common.ObjToString(v["name"]))
  1554. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1555. row.AddCell().SetString(common.ObjToString(v["email"]))
  1556. row.AddCell().SetString(common.ObjToString(v["company_name"]))
  1557. row.AddCell().SetString("")
  1558. row.AddCell().SetString("")
  1559. row.AddCell().SetString("安博会用户注册")
  1560. row.AddCell().SetString(gconv.Time(gconv.Int64(v["createtime"])).Format(date.Date_Full_Layout))
  1561. //增加客户需求
  1562. }
  1563. dir = "./xlsx/abh/" + fileName + ".xlsx"
  1564. err = xf.Save(dir)
  1565. case "saleLeads":
  1566. xlsxArr := []string{"用户昵称", "姓名", "公司名称", "职位", "联系人电话", "购买条数", "用户邮箱", "已支付订单信息", "未支付订单类型", "销售线索来源", "具体来源", "数据需求"}
  1567. batch := FindBatch("abh")
  1568. fileName, detailName = time.Now().Format(date.Date_Short_Layout)+"-"+batch+"安博会电销销售线索", ""
  1569. xf := xlsx.NewFile()
  1570. style := xlsx.NewStyle()
  1571. style.Font.Size = 12
  1572. style.Font.Bold = true
  1573. style.Alignment.Vertical = "center"
  1574. style.Alignment.Horizontal = "center"
  1575. detailName = "今日新增安博会销售线索,请查收附件,及时跟进。"
  1576. sh, _ := xf.AddSheet("线索数据")
  1577. row1 := sh.AddRow()
  1578. for _, x := range xlsxArr {
  1579. cell := row1.AddCell()
  1580. cell.SetString(x)
  1581. cell.SetStyle(style)
  1582. }
  1583. filterArr := []string{"-pc", "-app", "-wx", "-h5"}
  1584. sourceMap := map[string]string{} //根据留资维表:tidb/Jianyu_subjectdb/d_saleleads_code
  1585. saleSource := TiDb.SelectBySql(`SELECT source,name FROM d_saleleads_code WHERE is_delete = 1`)
  1586. if saleSource != nil && len(*saleSource) > 0 {
  1587. for _, v := range *saleSource {
  1588. source := common.ObjToString(v["source"])
  1589. name := common.ObjToString(v["name"])
  1590. for _, s := range filterArr {
  1591. name = strings.ReplaceAll(name, s, "")
  1592. }
  1593. sourceMap[source] = name
  1594. }
  1595. }
  1596. for _, v := range data {
  1597. sources := common.ObjToString(v["source"])
  1598. interest := common.ObjToString(v["interest"])
  1599. row := sh.AddRow()
  1600. row.AddCell().SetString(common.ObjToString(v["usernickname"]))
  1601. row.AddCell().SetString(common.ObjToString(v["name"]))
  1602. row.AddCell().SetString(common.ObjToString(v["company"]))
  1603. row.AddCell().SetString(common.ObjToString(v["position"]))
  1604. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1605. row.AddCell().SetValue(0)
  1606. row.AddCell().SetString(common.ObjToString(v["email"]))
  1607. row.AddCell().SetString("")
  1608. row.AddCell().SetString("")
  1609. row.AddCell().SetString(sourceMap[sources])
  1610. row.AddCell().SetString(interest)
  1611. row.AddCell().SetString(common.ObjToString(v["data_requirement"]))
  1612. //增加客户需求
  1613. }
  1614. dir = "./xlsx/abh/" + fileName + ".xlsx"
  1615. err = xf.Save(dir)
  1616. case "big":
  1617. xlsxArr := []string{"用户昵称", "姓名", "公司名称", "职位", "联系人电话", "购买条数", "用户邮箱", "已支付订单信息", "未支付订单类型", "销售线索来源", "具体来源", "数据需求"}
  1618. batch := FindBatch("abh")
  1619. fileName, detailName = time.Now().Format(date.Date_Short_Layout)+"-"+batch+"安博会大客户销售线索", ""
  1620. xf := xlsx.NewFile()
  1621. style := xlsx.NewStyle()
  1622. style.Font.Size = 12
  1623. style.Font.Bold = true
  1624. style.Alignment.Vertical = "center"
  1625. style.Alignment.Horizontal = "center"
  1626. detailName = "今日新增安博会销售线索,请查收附件,及时跟进。"
  1627. sh, _ := xf.AddSheet("线索数据")
  1628. row1 := sh.AddRow()
  1629. for _, x := range xlsxArr {
  1630. cell := row1.AddCell()
  1631. cell.SetString(x)
  1632. cell.SetStyle(style)
  1633. }
  1634. for _, v := range data {
  1635. row := sh.AddRow()
  1636. row.AddCell().SetString(common.ObjToString(v["usernickname"]))
  1637. row.AddCell().SetString(common.ObjToString(v["username"]))
  1638. row.AddCell().SetString(common.ObjToString(v["company"]))
  1639. row.AddCell().SetString(common.ObjToString(v["job"]))
  1640. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1641. row.AddCell().SetValue(common.IntAll(v["data_count"]))
  1642. row.AddCell().SetString(common.ObjToString(v["email"]))
  1643. row.AddCell().SetString(common.ObjToString(v["payorderinfo"]))
  1644. row.AddCell().SetString(common.ObjToString(v["unpayorderinfo"]))
  1645. row.AddCell().SetString(common.ObjToString(v["source"]))
  1646. row.AddCell().SetString(common.ObjToString(v["interest"]))
  1647. row.AddCell().SetString(common.ObjToString(v["data_requirement"]))
  1648. //增加客户需求
  1649. }
  1650. dir = "./xlsx/abh/" + fileName + ".xlsx"
  1651. err = xf.Save(dir)
  1652. case "advisory":
  1653. xlsxArr := []string{"姓名", "联系方式", "邮箱", "公司名称", "咨询需求", "销售线索来源", "具体来源", "留资时间"}
  1654. //排序:首先按照“联系方式”排序,即同1个用户的留资放在一起,其次按照留资时间正序排序。
  1655. batch := FindBatch("abh")
  1656. fileName, detailName = "安博会咨询服务销售线索 "+time.Now().Format(date.Date_Short_Layout)+"-"+batch, ""
  1657. xf := xlsx.NewFile()
  1658. style := xlsx.NewStyle()
  1659. style.Font.Size = 12
  1660. style.Font.Bold = true
  1661. style.Alignment.Vertical = "center"
  1662. style.Alignment.Horizontal = "center"
  1663. detailName = "今日新增安博会销售线索,请查收附件,及时跟进。"
  1664. sh, _ := xf.AddSheet("线索数据")
  1665. row1 := sh.AddRow()
  1666. for _, x := range xlsxArr {
  1667. cell := row1.AddCell()
  1668. cell.SetString(x)
  1669. cell.SetStyle(style)
  1670. }
  1671. for _, v := range data {
  1672. row := sh.AddRow()
  1673. row.AddCell().SetString(common.ObjToString(v["username"]))
  1674. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1675. row.AddCell().SetString(common.ObjToString(v["email"]))
  1676. row.AddCell().SetString(common.ObjToString(v["company"]))
  1677. row.AddCell().SetString(common.ObjToString(v["data_requirement"]))
  1678. row.AddCell().SetString(common.ObjToString(v["source"]))
  1679. row.AddCell().SetString(common.ObjToString(v["interest"]))
  1680. row.AddCell().SetString(gconv.Time(gconv.Int64(v["createtime"])).Format(date.Date_Full_Layout))
  1681. }
  1682. dir = "./xlsx/abh/" + fileName + ".xlsx"
  1683. err = xf.Save(dir)
  1684. case "market":
  1685. xlsxArr := []string{"姓名", "联系人电话", "公司名称", "职位", "部门", "销售线索来源", "留资时间"}
  1686. batch := FindBatch("abh")
  1687. fileName, detailName = "安博会商务合作销售线索 "+time.Now().Format(date.Date_Short_Layout)+"-"+batch, ""
  1688. xf := xlsx.NewFile()
  1689. style := xlsx.NewStyle()
  1690. style.Font.Size = 12
  1691. style.Font.Bold = true
  1692. style.Alignment.Vertical = "center"
  1693. style.Alignment.Horizontal = "center"
  1694. detailName = "今日新增安博会销售线索,请查收附件,及时跟进。"
  1695. sh, _ := xf.AddSheet("线索数据")
  1696. row1 := sh.AddRow()
  1697. for _, x := range xlsxArr {
  1698. cell := row1.AddCell()
  1699. cell.SetString(x)
  1700. cell.SetStyle(style)
  1701. }
  1702. for _, v := range data {
  1703. row := sh.AddRow()
  1704. row.AddCell().SetString(common.ObjToString(v["username"]))
  1705. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1706. row.AddCell().SetString(common.ObjToString(v["company"]))
  1707. row.AddCell().SetString(common.ObjToString(v["job"]))
  1708. row.AddCell().SetString(common.ObjToString(v["branch"]))
  1709. row.AddCell().SetString(common.ObjToString(v["source"]))
  1710. row.AddCell().SetString(gconv.Time(gconv.Int64(v["createtime"])).Format(date.Date_Full_Layout))
  1711. //增加客户需求
  1712. }
  1713. dir = "./xlsx/abh/" + fileName + ".xlsx"
  1714. err = xf.Save(dir)
  1715. }
  1716. email = db.AbhEmail
  1717. if err != nil {
  1718. log.Println("xls error", err, dir)
  1719. } else {
  1720. gmail := &mail.GmailAuth{
  1721. SmtpHost: "smtp.exmail.qq.com",
  1722. SmtpPort: 465,
  1723. User: "public03@topnet.net.cn",
  1724. Pwd: "ue9Rg9Sf4CVtdm5a",
  1725. }
  1726. status := mail.GSendMail_q("剑鱼标讯", email, "", "", fileName, detailName, dir, fileName+".xlsx", gmail)
  1727. if status {
  1728. log.Println("send mail success", fileName, email)
  1729. }
  1730. }
  1731. }*/
  1732. // 安防邮件
  1733. func AFEmail(data []map[string]interface{}) {
  1734. xlsxArr := []string{"姓名", "联系方式", "邮箱", "公司名称", "咨询需求", "销售线索来源", "具体来源", "留资时间"}
  1735. batch := FindBatch("af")
  1736. fileName, detailName := "安防销售线索 "+time.Now().Format(date.Date_Short_Layout)+"-"+batch, ""
  1737. xf := xlsx.NewFile()
  1738. style := xlsx.NewStyle()
  1739. style.Font.Size = 12
  1740. style.Font.Bold = true
  1741. style.Alignment.Vertical = "center"
  1742. style.Alignment.Horizontal = "center"
  1743. detailName = "今日新增安防销售线索,请查收附件,及时跟进。"
  1744. sh, _ := xf.AddSheet("线索数据")
  1745. row1 := sh.AddRow()
  1746. for _, x := range xlsxArr {
  1747. cell := row1.AddCell()
  1748. cell.SetString(x)
  1749. cell.SetStyle(style)
  1750. }
  1751. for _, v := range data {
  1752. row := sh.AddRow()
  1753. row.AddCell().SetString(common.ObjToString(v["name"]))
  1754. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1755. row.AddCell().SetString(common.ObjToString(v["email"]))
  1756. row.AddCell().SetString(common.ObjToString(v["company_name"]))
  1757. row.AddCell().SetString("")
  1758. row.AddCell().SetString("")
  1759. row.AddCell().SetString("首次使用安防新注册")
  1760. row.AddCell().SetString(gconv.String(v["time"]))
  1761. //增加客户需求
  1762. }
  1763. email := db.AfEmail
  1764. dir := "./xlsx/af/" + fileName + ".xlsx"
  1765. err := xf.Save(dir)
  1766. if err != nil {
  1767. log.Println("xls error", err, dir)
  1768. } else {
  1769. gmail := &mail.GmailAuth{
  1770. SmtpHost: db.Mail.SmtpHost,
  1771. SmtpPort: db.Mail.SmtpPort,
  1772. User: db.Mail.User,
  1773. Pwd: db.Mail.Pwd,
  1774. }
  1775. status := mail.GSendMail_q("剑鱼标讯", email, "", "", fileName, detailName, dir, "", gmail)
  1776. if status {
  1777. log.Println("send mail success", fileName, email)
  1778. }
  1779. }
  1780. }
  1781. func populateAdvisoryData(sh *xlsx.Sheet, data []map[string]interface{}) error {
  1782. for _, v := range data {
  1783. row := sh.AddRow()
  1784. row.AddCell().SetString(common.ObjToString(v["username"]))
  1785. row.AddCell().SetString(common.ObjToString(v["phone"]))
  1786. row.AddCell().SetString(common.ObjToString(v["email"]))
  1787. row.AddCell().SetString(common.ObjToString(v["company"]))
  1788. row.AddCell().SetString(common.ObjToString(v["data_requirement"]))
  1789. row.AddCell().SetString(common.ObjToString(v["source"]))
  1790. row.AddCell().SetString(common.ObjToString(v["interest"]))
  1791. row.AddCell().SetString(gconv.Time(gconv.Int64(v["createtime"])).Format(date.Date_Full_Layout))
  1792. }
  1793. return nil
  1794. }
  1795. // 邀请用户处理
  1796. func inviteUser() {
  1797. log.Println("邀请用户处理开始")
  1798. //判断节假日
  1799. runOk := getRunOk()
  1800. if !runOk {
  1801. log.Println("不是工作日,任务暂停")
  1802. return
  1803. }
  1804. rebindTimeEnd := cfg.InviteTime
  1805. sql := fmt.Sprintf(`select * from user_statistics where createTime > "%s" order by createTime asc`, rebindTimeEnd)
  1806. //sql := fmt.Sprintf(`select * from user_statistics where createTime = "%s" order by createTime asc`, rebindTimeEnd)
  1807. data := BiService.SelectBySql(sql)
  1808. if data != nil && *data != nil && len(*data) > 0 {
  1809. for _, v := range *data {
  1810. rebindTimeEnd = common.ObjToString(v["createTime"])
  1811. event := gconv.Int64(v["event"])
  1812. switch event {
  1813. case 1:
  1814. v["sourceCode"] = "736"
  1815. case 2:
  1816. v["sourceCode"] = "737"
  1817. case 3:
  1818. v["sourceCode"] = "738"
  1819. }
  1820. v["user_id"] = gconv.String(v["userId"])
  1821. ok1, ok2, _ := FormatData(v, "invite")
  1822. if !ok1 {
  1823. log.Println("线索卡点", "invite", v, rebindTimeEnd)
  1824. } else {
  1825. if !ok2 {
  1826. log.Println("用户分配已达上限", "invite", v, rebindTimeEnd)
  1827. }
  1828. }
  1829. }
  1830. cfg.InviteTime = rebindTimeEnd
  1831. common.WriteSysConfig(&cfg)
  1832. }
  1833. log.Println("邀请用户处理结束")
  1834. }
  1835. // 开年活动
  1836. func nextYearActivity() {
  1837. log.Println("开年活动处理开始")
  1838. //判断节假日
  1839. runOk := getRunOk()
  1840. if !runOk {
  1841. log.Println("不是工作日,任务暂停")
  1842. return
  1843. }
  1844. activityTimeEnd := cfg.ActivityTime
  1845. sql := fmt.Sprintf(`SELECT
  1846. a.*
  1847. FROM
  1848. jyactivities.lottery_user_account a
  1849. INNER JOIN jyactivities.lottery_prize_info b on a.create_time > "%s" and a.prize_id=b.id
  1850. INNER JOIN jyactivities.prize_base_info c on c.name like "%s" and b.pb_id=c.id
  1851. ORDER BY
  1852. a.create_time ASC
  1853. `, activityTimeEnd, "%超级订阅%")
  1854. data := Mysql.SelectBySql(sql)
  1855. if data != nil && *data != nil && len(*data) > 0 {
  1856. for _, v := range *data {
  1857. activityTimeEnd = common.ObjToString(v["create_time"])
  1858. v["sourceCode"] = gconv.Int64(v["active_id"])
  1859. v["user_id"] = gconv.String(v["mgo_user_id"])
  1860. ok1, ok2, _ := FormatData(v, "activity")
  1861. if !ok1 {
  1862. log.Println("线索卡点", "activity", v, activityTimeEnd)
  1863. } else {
  1864. if !ok2 {
  1865. log.Println("开年活动分配已达上限", "activity", v, activityTimeEnd)
  1866. }
  1867. }
  1868. }
  1869. cfg.ActivityTime = activityTimeEnd
  1870. common.WriteSysConfig(&cfg)
  1871. }
  1872. log.Println("开年活动处理结束")
  1873. }
  1874. // 获取用户渠道信息
  1875. func GetUserChannel(userId string) string {
  1876. if userId == "" {
  1877. return ""
  1878. }
  1879. codeArr := []string{}
  1880. if len(UserChannel) > 0 {
  1881. for i := range UserChannel {
  1882. codeArr = append(codeArr, fmt.Sprintf(`"%s"`, i))
  1883. }
  1884. }
  1885. //查找注册日志表
  1886. 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, ","))
  1887. courceData := ThirdParty.SelectBySql(sql)
  1888. if courceData != nil && len(*courceData) > 0 {
  1889. channelCode := gconv.String((*courceData)[0]["channel_code"])
  1890. data, exit := UserChannel[channelCode]
  1891. if exit {
  1892. return gconv.String(data["clueCode"])
  1893. }
  1894. }
  1895. return ""
  1896. }