kc.go 88 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361
  1. package main
  2. import (
  3. "app.yhyue.com/moapp/jybase/mail"
  4. "app.yhyue.com/moapp/jybase/redis"
  5. "database/sql"
  6. "fmt"
  7. "log"
  8. "strings"
  9. "time"
  10. "github.com/gogf/gf/v2/util/gconv"
  11. "app.yhyue.com/moapp/jybase/common"
  12. "app.yhyue.com/moapp/jybase/date"
  13. "app.yhyue.com/moapp/jybase/mongodb"
  14. )
  15. func kcSync() {
  16. log.Println("客户成功系统移交定时任务开始")
  17. //商品查询
  18. productArr, _ := KcProduct()
  19. if len(productArr) == 0 {
  20. log.Println("查询不到进客成商品类型")
  21. return
  22. }
  23. sql := `SELECT
  24. a.*,b.product_type,b.service_starttime,b.service_endtime,b.service_type,b.filter as productFilter,TIMESTAMPDIFF(DAY, b.service_starttime, b.service_endtime) as difference,b.update_time
  25. FROM
  26. dataexport_order a
  27. INNER JOIN jy_order_detail b ON a.order_code = b.order_code
  28. and b.product_type in (%s)
  29. AND (
  30. a.pay_money > 0
  31. OR (
  32. a.pay_money = 0
  33. AND ( a.zero_type = "分期付款权益补充" OR a.zero_type = "原订单不支持开通多项权益" OR a.zero_type = "权益码兑换" )))
  34. AND a.user_phone NOT LIKE "%s"
  35. and a.user_id !=""
  36. AND a.order_status = 1
  37. AND ( a.refund_status != 1 OR a.refund_status IS NULL )
  38. AND b.service_starttime < "2099-01-01" AND b.service_endtime > now()
  39. AND b.update_time > "%s"
  40. ORDER BY
  41. b.update_time asc ,
  42. a.order_code ASC,
  43. difference desc ,
  44. b.final_price DESC `
  45. sql = fmt.Sprintf(sql, strings.Join(productArr, ","), "9%", cfg.LastkcTime)
  46. //sql = fmt.Sprintf(sql, strings.Join(productArr, ","), "9%", "2025-01-02", "140500841645")
  47. data := Mysql.SelectBySql(sql)
  48. fmt.Println("客成查询到的数量:", len(*data))
  49. customList := gconv.Strings(redis.Get("newother", "customList"))
  50. if data != nil && *data != nil && len(*data) > 0 {
  51. orderMap := map[string]map[string]interface{}{}
  52. for _, v := range *data {
  53. orderCode := gconv.String(v["order_code"])
  54. productType := gconv.String(v["product_type"])
  55. vipStarttime := gconv.String(v["service_starttime"])
  56. vipEndtime := gconv.String(v["service_endtime"])
  57. service_type := gconv.Int64(v["service_type"])
  58. difference := gconv.Int(v["difference"])
  59. if (service_type != 4) || (service_type == 4 && difference > 95) {
  60. isExit := false
  61. /*for _, v := range customList {
  62. if v == orderCode {
  63. isExit = true
  64. continue
  65. }
  66. }*/
  67. if isExit {
  68. continue
  69. }
  70. //判断一下服务周期
  71. _, productInt64, _ := GetOrderProduct(productType, gconv.String(v["productFilter"]))
  72. productInt64 = 2
  73. if productInt64 == 0 {
  74. continue
  75. }
  76. if _, exists := orderMap[orderCode]; exists {
  77. //判断服务周期
  78. data := orderMap[orderCode]
  79. //商品类型获取
  80. oldDifference := gconv.Int(data["difference"])
  81. if oldDifference < difference {
  82. //需要更换
  83. v["difference"] = difference
  84. v["product"] = productInt64
  85. v["service_endtime"] = vipEndtime
  86. v["service_starttime"] = vipStarttime
  87. orderMap[orderCode] = v
  88. }
  89. } else {
  90. v["difference"] = difference
  91. v["product"] = productInt64
  92. orderMap[orderCode] = v
  93. }
  94. }
  95. }
  96. for _, v := range *data {
  97. orderCode := gconv.String(v["order_code"])
  98. if _, exists := orderMap[orderCode]; exists {
  99. status := kcJob(orderMap[orderCode])
  100. log.Println("订单进客成打印", orderCode, status)
  101. if status == 0 {
  102. break
  103. }
  104. cfg.LastkcTime = gconv.String(v["update_time"])
  105. customList = append(customList, orderCode)
  106. delete(orderMap, orderCode)
  107. }
  108. }
  109. }
  110. redis.Put("newother", "customList", customList, 0)
  111. common.WriteSysConfig(&cfg)
  112. log.Println("客户成功系统移交定时任务结束")
  113. }
  114. // 进客成处理
  115. func kcJob(data map[string]interface{}) int {
  116. nowTime := time.Now().Format(date.Date_Full_Layout)
  117. uId, entId, clueId, saveMap, status := "", gconv.String(data["ent_id"]), int64(0), map[string]interface{}{}, 1
  118. userId, cluename, phone := "", "", ""
  119. phone = gconv.String(data["user_phone"])
  120. productName := gconv.String(data["product_type"])
  121. uId, userId = GetUidToUserId(gconv.String(data["user_id"]), "")
  122. log.Println("用户信息获取", data["user_id"], uId, userId)
  123. if uId == "" {
  124. log.Println("移交客成缺少基本信息,缺少用户信息", uId)
  125. return 0
  126. }
  127. buy_subject := common.Int64All(data["buy_subject"])
  128. if buy_subject == 1 || buy_subject == 0 {
  129. entId = gconv.String(data["user_id"])
  130. }
  131. clueData := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"uid": uId}, "", "")
  132. orderCode := gconv.String(data["order_code"])
  133. saleDep, orderPositionId, salesperson := FindSaleRecord(orderCode)
  134. log.Println(data["order_code"], saleDep, orderPositionId, salesperson)
  135. cluename = gconv.String(data["company_name"])
  136. if cluename == "" {
  137. cluename = phone
  138. }
  139. if clueData == nil || len(*clueData) == 0 {
  140. if saleDep == "销售部" || saleDep == "市场部" {
  141. log.Println("移交客成缺少基本信息", uId)
  142. return 0
  143. }
  144. //原始订单获取
  145. position_id := int64(0)
  146. seatNumber := ""
  147. if saleDep == "客户成功部" {
  148. //新增线索
  149. position_id = 0
  150. } else {
  151. position_id = orderPositionId
  152. //其他信息
  153. seatNumber = "0000"
  154. }
  155. trailstatus := "08"
  156. isGroup, isCommerce := GetCompanyType(cluename, uId) //判断是否集团公司、工商库
  157. clueId = TiDb.Insert("dwd_f_crm_clue_info", map[string]interface{}{
  158. "userid": userId,
  159. "uid": uId,
  160. "is_assign": common.If(position_id > 0, 1, 0),
  161. "createtime": nowTime,
  162. "updatetime": nowTime,
  163. "cluename": cluename,
  164. "seatNumber": seatNumber,
  165. "position_id": position_id,
  166. "top_cluetype": "4",
  167. "sub_cluetype": "154",
  168. "trailstatus": trailstatus,
  169. "name": phone,
  170. "phone": phone,
  171. "is_task": 0,
  172. "taskstatus": 0,
  173. "company_nature": isGroup,
  174. "company_verification": isCommerce,
  175. "FREEZE_TIME": nowTime,
  176. "label": common.If(position_id > 0, 1, nil),
  177. })
  178. if clueId > 0 {
  179. AddClueChange(clueId, gconv.Int64(common.If(position_id > 0, position_id, -1)), "", "创建线索", "", "系统自动创建", nowTime, common.GetRandom(32), "", "")
  180. clueData = TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"uid": uId}, "", "")
  181. if clueData == nil || len(*clueData) == 0 {
  182. return 0
  183. }
  184. } else {
  185. return 0
  186. }
  187. }
  188. isTransfer := gconv.Int64((*clueData)["is_transfer"])
  189. //cluename = gconv.String((*clueData)["cluename"])
  190. clueId = common.Int64All((*clueData)["id"])
  191. starttime := gconv.String(data["service_starttime"])
  192. endtime := gconv.String(data["service_endtime"])
  193. //product_type := gconv.String(data["product_type"])
  194. product, company_name := gconv.Int64(data["product"]), gconv.String(data["company_name"])
  195. //同一公司名称(以客户详情-组织机构-公司名称)下的线索需分配给同1人
  196. saveMap = map[string]interface{}{
  197. "clue_id": clueId,
  198. "transfertime": nowTime,
  199. "service_starttime": starttime,
  200. "service_endtime": endtime,
  201. "ent_id": entId,
  202. "is_task": 1,
  203. "tasktime": nowTime,
  204. "taskstatus": 0,
  205. "tasksource": "1",
  206. "is_admin": 1,
  207. "product_access": product,
  208. "buy_subject": buy_subject,
  209. "relationship_building_way": 1,
  210. "inventory_way": 1,
  211. "training_way": 1,
  212. "is_pre_sales_training": 0,
  213. "service_stage": 1,
  214. "account_type": 1,
  215. "company_name": company_name,
  216. }
  217. k := KcTransferRequest{
  218. KcEntId: entId,
  219. HostUID: uId,
  220. HostClueId: clueId,
  221. KcBuySubject: buy_subject,
  222. KcCompanyName: company_name,
  223. KcStartTime: starttime,
  224. KcEndTime: endtime,
  225. NowTime: nowTime,
  226. KcProduct: product,
  227. KcProductName: productName,
  228. HostClueName: cluename,
  229. }
  230. if TiDb.Count("dwd_f_csm_customer_info", map[string]interface{}{"clue_id": clueId}) > 0 {
  231. customData := TiDb.FindOne("dwd_f_csm_customer_info", map[string]interface{}{"clue_id": clueId}, "", "")
  232. if customData != nil && len(*customData) > 0 {
  233. isUpdate := true
  234. // 获取客户数据
  235. customId := gconv.Int64((*customData)["id"])
  236. // 自动分配客户给销售或部门
  237. customerPositionId, customerName := cAutoDraw(gconv.Int(entId), orderPositionId, salesperson, saleDep, customData, company_name)
  238. log.Println("移交客户positionId", customerPositionId, customerName, saleDep, orderPositionId, salesperson, true)
  239. // 创建客户转移请求结构体
  240. k.KcID = customId
  241. k.KcName = customerName
  242. k.KcPositionId = customerPositionId
  243. if isTransfer == 0 {
  244. // 非转移客户,直接更新账号信息
  245. isUpdate = false
  246. k.KcAccountNumberUpdate(customData, clueData, orderCode, false, isUpdate, isTransfer)
  247. } else {
  248. // 转移客户处理
  249. if clueData == nil || len(*clueData) == 0 {
  250. // 之前没有线索的情况(理论上不应出现)
  251. } else {
  252. // 检查原线索名称是否是手机号
  253. if ValidatePhone(cluename) {
  254. // 原线索是手机号
  255. if gconv.Int64(entId) > 0 {
  256. // 新客户是企业,需要将线索名称替换为企业名称
  257. isUpdate = true
  258. k.KcAccountNumberUpdate(customData, clueData, orderCode, false, isUpdate, isTransfer)
  259. } else {
  260. // 新客户是个人,保持原样
  261. isUpdate = false
  262. k.KcAccountNumberUpdate(customData, clueData, orderCode, false, isUpdate, isTransfer)
  263. }
  264. }
  265. }
  266. }
  267. }
  268. } else {
  269. customerPositionId, customerName := cAutoDraw(gconv.Int(entId), orderPositionId, salesperson, saleDep, nil, company_name)
  270. log.Println("移交客成positionId", customerPositionId, customerName, saleDep, orderPositionId, salesperson, false)
  271. customId := TiDb.Insert("dwd_f_csm_customer_info", saveMap)
  272. if customId > 0 {
  273. k.KcID = customId
  274. k.KcName = customerName
  275. k.KcPositionId = customerPositionId
  276. k.KcAccountNumberUpdate(&saveMap, clueData, orderCode, true, false, isTransfer)
  277. }
  278. }
  279. return status
  280. }
  281. // 客成人员查询
  282. func cAutoDraw(entId int, orderPositionId int64, salesperson, saleDep string, customData *map[string]interface{}, company_name string) (positionId int64, name string) {
  283. if customData != nil {
  284. //查看一下之前有没有人
  285. positionId = common.Int64All((*customData)["position_id"])
  286. if positionId != 0 {
  287. name = gconv.String((*customData)["name"])
  288. return
  289. }
  290. }
  291. query := `SELECT name,position_id FROM dwd_d_crm_department_level_succbi WHERE bi_pcode = (SELECT bi_code FROM dwd_d_crm_department_level_succbi WHERE name = "客户成功部" and resign=0 and ent_id=?) and resign = 0 and position_id is not null `
  292. data := TiDb.SelectBySql(query, db.EntId)
  293. if data == nil || len(*data) == 0 {
  294. return
  295. }
  296. //个人的话随机分
  297. if entId == 0 {
  298. positionId, name = getKCperson(data)
  299. return
  300. }
  301. //看其他公司上边有没有客成人员 有的话新分给这个人
  302. customerData := TiDb.Find("dwd_f_csm_customer_info", map[string]interface{}{"company_name": company_name}, "", "", -1, -1)
  303. if customerData != nil && len(*customerData) > 0 {
  304. for _, v := range *customerData {
  305. positionid := common.Int64All(v["position_id"])
  306. if positionid != 0 {
  307. name = gconv.String(v["name"])
  308. return
  309. }
  310. }
  311. }
  312. //没有的话看下业绩归属
  313. if saleDep == "客户成功部" {
  314. positionId = orderPositionId
  315. name = salesperson
  316. return
  317. }
  318. //随机分配
  319. positionId, name = getKCperson(data)
  320. return
  321. }
  322. // 获取客成里边最少的一个人
  323. func getKCperson(data *[]map[string]interface{}) (positionId int64, name string) {
  324. if data != nil && len(*data) > 0 {
  325. sql := `select a.name,a.count,b.position_id from dwd_f_csm_customer_autodraw_record a INNER JOIN dwd_d_crm_department_level_succbi b on b.ent_id=? and (a.name = b.name) and b.resign = 0`
  326. countData := TiDb.SelectBySql(sql, db.EntId)
  327. if countData != nil && len(*countData) > 0 {
  328. for _, v := range *countData {
  329. //判断是否有新员工
  330. isOk := false
  331. for _, vv := range *data {
  332. if gconv.String(v["name"]) == gconv.String(vv["name"]) {
  333. isOk = true
  334. }
  335. }
  336. //有新员工直接分给新员工
  337. if !isOk {
  338. name = gconv.String(v["name"])
  339. rData := TiDb.FindOne("dwd_f_csm_customer_autodraw_record", map[string]interface{}{
  340. "name": name,
  341. }, "", "count desc")
  342. TiDb.Insert("dwd_f_csm_customer_autodraw_record", map[string]interface{}{
  343. "name": name,
  344. "count": common.Int64All((*rData)["count"]),
  345. })
  346. break
  347. }
  348. }
  349. res := int64(0)
  350. countres := 0
  351. for _, v := range *countData {
  352. if countres == 0 {
  353. res = common.Int64All(v["count"])
  354. name = gconv.String(v["name"])
  355. positionId = gconv.Int64(v["position_id"])
  356. } else {
  357. if common.Int64All(v["count"]) <= res {
  358. res = common.Int64All(v["count"])
  359. name = gconv.String(v["name"])
  360. positionId = gconv.Int64(v["position_id"])
  361. }
  362. }
  363. countres++
  364. }
  365. }
  366. }
  367. return
  368. }
  369. // 客成自动加入任务车
  370. func kcAuto() {
  371. log.Println("客户成功系统自动进入任务车定时任务开始")
  372. nowTime := time.Now().Format(date.Date_Full_Layout)
  373. sql := `select * from dwd_f_csm_customer_info where ((relationship_building_way != 1 and inventory_way = 1) or (inventory_way != 1 and training_way = 1)) and is_task = 0`
  374. data := TiDb.SelectBySql(sql)
  375. if data != nil && *data != nil && len(*data) > 0 {
  376. for _, v := range *data {
  377. relationship_building_way := common.IntAll(v["relationship_building_way"])
  378. inventory_way := common.IntAll(v["inventory_way"])
  379. training_way := common.IntAll(v["training_way"])
  380. positionId := common.Int64All(v["position_id"])
  381. clueId := common.Int64All(v["clue_id"])
  382. tasksource, tasksources := gconv.String(v["tasksource"]), ""
  383. taskstatus := common.IntAll(v["taskstatus"])
  384. if relationship_building_way != 1 && inventory_way == 1 {
  385. tasksources = "2"
  386. //新增任务车
  387. AddClueChange(clueId, positionId, "", "加入任务车", "", "未盘点", nowTime, common.GetRandom(32), "", "")
  388. } else if inventory_way != 1 && training_way == 1 {
  389. tasksources = "3"
  390. //新增任务车
  391. AddClueChange(clueId, positionId, "", "加入任务车", "", "未培训", nowTime, common.GetRandom(32), "", "")
  392. }
  393. if taskstatus == 1 {
  394. tasksource = tasksources
  395. } else {
  396. if tasksource != "" {
  397. if !strings.Contains(tasksource, tasksources) {
  398. tasksource += "," + tasksources
  399. }
  400. } else {
  401. tasksource = tasksources
  402. }
  403. }
  404. TiDb.Update("dwd_f_csm_customer_info", map[string]interface{}{"clue_id": clueId}, map[string]interface{}{
  405. "tasksource": tasksource,
  406. "tasktime": nowTime,
  407. "is_task": 1,
  408. "taskstatus": 0,
  409. })
  410. }
  411. }
  412. log.Println("客户成功系统进入任务车定时任务结束")
  413. }
  414. func ordersClue() {
  415. log.Println("后台订单线索定时任务开始")
  416. lastOrderClueId := cfg.LastOrderClueId
  417. nowTime := time.Now().Format(date.Date_Full_Layout)
  418. product_type_str2 := `"大会员","企业商机管理","VIP订阅"`
  419. sql := fmt.Sprintf(`select a.*,b.product_type as productType ,b.service_starttime,b.service_endtime,b.filter AS productFilter,b.update_time,a.personPhone,a.personName,a.ent_id from dataexport_order a
  420. INNER JOIN jy_order_detail b on a.order_code=b.order_code
  421. and b.update_time>="%s" AND a.user_phone NOT LIKE "%s" and a.user_id !=""
  422. and b.product_type in (%s) and a.order_status = 1 and a.is_backstage_order = 1 order by b.update_time asc`, lastOrderClueId, "9%", product_type_str2)
  423. log.Println("后台订单线索定时任务", sql)
  424. //sql := "select a.*,b.product_type as productType ,b.service_starttime,b.service_endtime,b.filter AS productFilter,b.update_time,a.personPhone,a.personName,a.ent_id from dataexport_order a INNER JOIN jy_order_detail b on a.order_code=b.order_code where a.order_code = '115223989825'"
  425. data := Mysql.SelectBySql(sql)
  426. log.Println("后台订单线索定时任务", len(*data))
  427. if data != nil && *data != nil && len(*data) > 0 {
  428. for _, v := range *data {
  429. user_id := gconv.String(v["user_id"])
  430. payMoney := common.IntAll(v["pay_money"])
  431. orderCode := gconv.String(v["order_code"])
  432. saleDep, _, salesperson := FindSaleRecord(orderCode)
  433. userPhone := gconv.String(v["user_phone"]) //开通权益手机号
  434. createperson := gconv.String(v["create_person"])
  435. personPhone := gconv.String(v["personPhone"]) //联系人手机号
  436. personName := gconv.String(v["personName"])
  437. entId := gconv.Int64(v["ent_id"])
  438. addUser := []map[string]string{}
  439. if user_id == "" {
  440. userData := Base.SelectBySql("SELECT b.id FROM base_user a LEFT JOIN base_position b ON a.id= b.user_id WHERE a.phone = ? AND b.ent_id = ?", userPhone, entId)
  441. if userData == nil || len(*userData) == 0 {
  442. log.Printf("未查询用户positionId,订单编号:%s,手机号:%s", orderCode, userPhone)
  443. continue
  444. }
  445. user_id = gconv.String((*userData)[0]["id"])
  446. }
  447. if userPhone == personPhone {
  448. addUser = append(addUser, map[string]string{"phone": userPhone, "name": userPhone, "type": "采购人", "user_id": user_id})
  449. } else {
  450. //查询联系人user_id
  451. personPositionId := int64(0)
  452. ssql := fmt.Sprintf("SELECT b.id FROM base_user a LEFT JOIN base_position b ON a.id= b.user_id WHERE a.phone = '%s' AND b.ent_id = %d", personPhone, entId)
  453. log.Println("查询订单联系人职位id sql", ssql)
  454. personData := Base.SelectBySql(ssql)
  455. if personData != nil && len(*personData) > 0 {
  456. personPositionId = gconv.Int64((*personData)[0]["id"])
  457. addUser = append(addUser, map[string]string{"phone": personPhone, "name": personName, "type": "采购人", "user_id": gconv.String(personPositionId)})
  458. }
  459. addUser = append(addUser, map[string]string{"phone": userPhone, "name": userPhone, "type": "使用人", "user_id": user_id})
  460. }
  461. //撞单
  462. log.Println("销售部订单", saleDep)
  463. if strings.Contains(salesperson, ",") {
  464. log.Println("销售部撞单 ", salesperson)
  465. if salesperson == "" {
  466. salesperson = createperson
  467. }
  468. }
  469. log.Println("销售部订单salesperson", salesperson)
  470. seatNumber, positionId := "", int64(0)
  471. saleData := TiDb.FindOne("dwd_f_crm_personnel_management", map[string]interface{}{"name": salesperson}, "", "")
  472. if saleData != nil {
  473. seatNumber = gconv.String((*saleData)["seat_number"])
  474. positionId = common.Int64All((*saleData)["position_id"])
  475. }
  476. for _, vv := range addUser {
  477. userId, uId, cluename, trailstatus, clueId, phone := gconv.String(vv["user_id"]), "", "", "", int64(0), ""
  478. if saleDep != "" {
  479. //销售部
  480. phone = vv["phone"]
  481. query := map[string]interface{}{}
  482. source := ""
  483. if !mongodb.IsObjectIdHex(userId) {
  484. userMapping := TiDb.FindOne("data_service.user_system", map[string]interface{}{"position_id": userId}, "", "")
  485. if userMapping != nil && len(*userMapping) > 0 {
  486. userId = gconv.String((*userMapping)["userid"])
  487. } else {
  488. log.Println("后台订单--未查询到 ", phone)
  489. break
  490. }
  491. }
  492. query["userid"] = userId
  493. userInfo := TiDb.FindOne("dwd_f_userbase_baseinfo", query, "", "")
  494. if userInfo != nil && len(*userInfo) > 0 {
  495. uId = gconv.String((*userInfo)["uid"])
  496. source = gconv.String((*userInfo)["source"])
  497. } else {
  498. log.Println("后台订单--未查询到 ", query, phone)
  499. break
  500. }
  501. is_assign := 1
  502. mailContent := ""
  503. cluename = gconv.String(v["company_name"])
  504. mailContent = fmt.Sprintf("%s(%s)", cluename, phone)
  505. if cluename == "" {
  506. cluename = phone
  507. mailContent = phone
  508. }
  509. if payMoney > 0 {
  510. trailstatus = "08"
  511. } else {
  512. trailstatus = "01"
  513. }
  514. isGroup, isCommerce := GetCompanyType(cluename, uId) //判断是否集团公司、工商库
  515. if IsFreeze(source, payMoney, gconv.String(positionId), trailstatus) {
  516. //线索需要冻结
  517. is_assign = -3
  518. }
  519. clueData := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"uid": uId}, "", "")
  520. if clueData == nil || len(*clueData) == 0 {
  521. log.Println("saleDep", saleDep)
  522. if saleDep == "销售部" {
  523. clueId = TiDb.Insert("dwd_f_crm_clue_info", map[string]interface{}{
  524. "userid": userId,
  525. "uid": uId,
  526. "seatNumber": seatNumber,
  527. "position_id": positionId,
  528. "is_assign": is_assign,
  529. "comeintime": nowTime,
  530. "createtime": nowTime,
  531. "updatetime": nowTime,
  532. "cluename": cluename,
  533. "top_cluetype": "4",
  534. "sub_cluetype": "154",
  535. "trailstatus": trailstatus,
  536. "name": phone,
  537. "phone": phone,
  538. "comeinsource_private": 2,
  539. "is_task": 0,
  540. "taskstatus": 0,
  541. "company_nature": isGroup,
  542. "company_verification": isCommerce,
  543. "FREEZE_TIME": nowTime,
  544. "contact_type": vv["type"],
  545. })
  546. } else if saleDep == "市场部" {
  547. log.Println("市场部订单", saleDep)
  548. clueId = TiDb.Insert("dwd_f_crm_clue_info", map[string]interface{}{
  549. "userid": userId,
  550. "uid": uId,
  551. "is_assign": -2,
  552. "createtime": nowTime,
  553. "updatetime": nowTime,
  554. "cluename": cluename,
  555. "top_cluetype": "4",
  556. "sub_cluetype": "154",
  557. "trailstatus": trailstatus,
  558. "name": phone,
  559. "phone": phone,
  560. "is_task": 0,
  561. "taskstatus": 0,
  562. "company_nature": isGroup,
  563. "company_verification": isCommerce,
  564. "FREEZE_TIME": nowTime,
  565. "contact_type": vv["type"],
  566. })
  567. }
  568. if clueId > 0 {
  569. AddClueChange(clueId, gconv.Int64(common.If(positionId > 0, positionId, -1)), "", "创建线索", "", "系统自动创建", nowTime, common.GetRandom(32), "", "")
  570. if is_assign == -3 {
  571. //新增冻结记录
  572. AddClueChange(clueId, positionId, "", "线索冻结", "", "销售人员私海已达上限", nowTime, common.GetRandom(32), "", "")
  573. //移交失败发送消息
  574. if IsFreeze(source, payMoney, gconv.String(positionId), trailstatus) {
  575. //发送邮件信息
  576. OrderCreateFail(positionId, mailContent)
  577. }
  578. }
  579. }
  580. }
  581. }
  582. }
  583. cfg.LastOrderClueId = gconv.String(v["update_time"])
  584. }
  585. }
  586. common.WriteSysConfig(&cfg)
  587. log.Println("后台订单线索定时任务结束")
  588. }
  589. func refundAuto() {
  590. log.Println("自动移交销售定时任务开始")
  591. findNowTime := time.Now().AddDate(0, 0, -db.ExpirationPeriod).Format(date.Date_Full_Layout)
  592. nowTime := time.Now().Format(date.Date_Full_Layout)
  593. mailData := map[string][]map[string]interface{}{}
  594. salesEmailData := map[int64][]map[string]interface{}{}
  595. TiDb.SelectByBath(100, func(l *[]map[string]interface{}) bool {
  596. for _, v := range *l {
  597. cluename, company_nature, company_verification, uid, phone, userName, oldSaleId, oldsaleName := "", 0, 0, "", "", "", int64(0), ""
  598. saleId, newSeatNumber, newPerson := int64(0), "", ""
  599. clueId := common.Int64All(v["clue_id"])
  600. company_name := gconv.String(v["company_name"])
  601. name := gconv.String(v["name"])
  602. kcposition_id := common.Int64All(v["position_id"])
  603. isRenewalProtection := common.IntAll(v["is_renewal_protection"])
  604. clueData := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"id": clueId}, "name,phone,company_nature,company_verification,cluename,userid,position_id,uid", "")
  605. if clueData != nil && len(*clueData) > 0 {
  606. uid = gconv.String((*clueData)["uid"])
  607. saleId, newPerson, newSeatNumber = FindPositionIdClueId(uid)
  608. oldSaleId = common.Int64All((*clueData)["position_id"])
  609. oldPersonData := FindPersonOne(oldSaleId)
  610. if oldSaleId != 0 {
  611. oldsaleName = gconv.String(oldPersonData["name"])
  612. }
  613. cluename = gconv.String((*clueData)["cluename"])
  614. userName = gconv.String((*clueData)["name"])
  615. company_nature = common.IntAll((*clueData)["company_nature"])
  616. company_verification = common.IntAll((*clueData)["company_verification"])
  617. phone = gconv.String((*clueData)["phone"])
  618. }
  619. personArr := getUserIdToUid(uid)
  620. productArr, _ := KcProduct()
  621. if len(productArr) == 0 || len(personArr) == 0 {
  622. log.Println("查询不到进客成商品类型或查询不到用户信息")
  623. continue
  624. }
  625. //查询即将到期数据
  626. if isRenewalProtection == 0 {
  627. sqlStr := fmt.Sprintf(`select a.*,b.product_type as productType,b.service_starttime,b.service_endtime,b.filter AS productFilter from dataexport_order a INNER JOIN jy_order_detail b on a.order_code=b.order_code and a.user_id in (%s) and b.product_type in (%s) ORDER BY b.service_endtime desc `, strings.Join(personArr, ","), strings.Join(productArr, ","))
  628. _, vipEndDateStr := getOrderData(sqlStr)
  629. if vipEndDateStr != "" {
  630. endDate := time.Now().AddDate(0, 0, -db.ExpirationPeriod+3).Unix()
  631. startDate := time.Now().AddDate(0, 0, -db.ExpirationPeriod+2).Unix()
  632. vipEndDate, _ := time.ParseInLocation(time.DateTime, vipEndDateStr, time.Local)
  633. log.Println(vipEndDate.Unix() > startDate, vipEndDate.Unix() < endDate)
  634. log.Println(vipEndDate.Unix(), startDate, endDate)
  635. if vipEndDate.Unix() > startDate && vipEndDate.Unix() < endDate {
  636. //即将到期
  637. mailData[name] = append(mailData[name], map[string]interface{}{
  638. "company_name": company_name,
  639. "phone": phone,
  640. "userName": userName,
  641. "remrk": "3天后即将移交",
  642. "reason": "成交客户续费失败",
  643. })
  644. continue
  645. }
  646. }
  647. }
  648. isFull := false
  649. isAllRefund := false
  650. orderSql := fmt.Sprintf(` select a.*,b.product_type as productType,b.service_starttime,b.service_endtime,b.filter AS productFilter from dataexport_order a INNER JOIN jy_order_detail b on a.order_code=b.order_code and a.user_id in (%s) and b.product_type in (%s) and order_status = 1 ORDER BY b.service_endtime desc `, strings.Join(personArr, ","), strings.Join(productArr, ","))
  651. myOrders, _ := getOrderData(orderSql)
  652. if myOrders != nil || len(myOrders) > 0 {
  653. refundCount := 0
  654. for _, v := range myOrders {
  655. if common.IntAll(v["refund_status"]) == 1 {
  656. refundCount++
  657. }
  658. }
  659. if len(myOrders) > 0 && len(myOrders) == refundCount {
  660. isAllRefund = true
  661. }
  662. }
  663. if isAllRefund {
  664. mainUserPower, _ := GetPersonIdentityPower(uid, common.IntAll(v["account_type"]), common.Int64All(v["ent_id"]), "")
  665. if mainUserPower == nil { //移出客成
  666. //全退款了
  667. TiDb.UpdateOrDeleteBySql(`UPDATE dwd_f_crm_clue_info SET is_unfollow=0,is_assign=0,trailstatus="01",position_id=null,seatNumber=null,updatetime=?,comeintime_open=?,comeinsource_open=1,level_open=3,next_trail_time=null,is_task=null,tasktime=null,taskstatus=null,comeinsource_private=null,tasksource=null,is_transfer=0 WHERE id = ?`, nowTime, nowTime, clueId)
  668. //新增变更记录
  669. AddClueChange(clueId, gconv.Int64(common.If(kcposition_id > 0, kcposition_id, -1)), "", "退回公海", "", "成交客户申请退款", nowTime, common.GetRandom(32), "", "")
  670. //新增变更记录
  671. AddClueChange(clueId, gconv.Int64(common.If(kcposition_id > 0, kcposition_id, -1)), "trailstatus", "基本信息变更", "成交客户", "商机线索", nowTime, common.GetRandom(32), "", "")
  672. //新增变更记录
  673. AddClueChange(clueId, gconv.Int64(common.If(kcposition_id > 0, kcposition_id, -1)), "position_id", "客户成功经理", name, "/", nowTime, common.GetRandom(32), "", "")
  674. //新增变更记录y
  675. AddClueChange(clueId, gconv.Int64(common.If(kcposition_id > 0, kcposition_id, -1)), "", "移交销售", "", "成交客户申请退款", nowTime, common.GetRandom(32), "", "")
  676. TiDb.UpdateOrDeleteBySql(`UPDATE dwd_f_csm_customer_info SET is_transfer=1,account_type = NULL WHERE clue_id = ?`, clueId)
  677. } else { //主账号在其他身份下存在子账号或移交客成的免费账号
  678. entId := common.Int64All(mainUserPower["entId"])
  679. mainCusData := common.ObjToMap(mainUserPower["customer"])
  680. mainCompanyName := common.InterfaceToStr((*mainCusData)["company_name"])
  681. isGroup, isCommerce := GetCompanyTypeByClueId(mainCompanyName, common.Int64All((*mainCusData)["clue_id"]))
  682. SubAndFreeAccountUpdate(*mainCusData, entId, clueId, common.IntAll(mainUserPower["newAccountType"]), isGroup, isCommerce, common.InterfaceToStr(v["name"]))
  683. }
  684. //处理子账号及免费账号
  685. SubAndFreeAccountToDx(gconv.Int64(v["id"]), 2)
  686. mailData[name] = append(mailData[name], map[string]interface{}{
  687. "company_name": company_name,
  688. "phone": phone,
  689. "userName": userName,
  690. "remrk": "已移交",
  691. "reason": "成交客户申请退款",
  692. })
  693. } else {
  694. log.Println("客成到期处理")
  695. order1Sql := fmt.Sprintf(`select a.id from dataexport_order a INNER JOIN jy_order_detail b on a.order_code=b.order_code and a.user_id in (%s) and b.product_type in (%s) and order_status = 1 and b.service_endtime>"%s" ORDER BY b.service_endtime desc `, strings.Join(personArr, ","), strings.Join(productArr, ","), findNowTime)
  696. log.Println("有效订单查询", order1Sql)
  697. order1 := Mysql.SelectBySql(order1Sql)
  698. if order1 == nil || len(*order1) == 0 {
  699. isOk := false
  700. order3Sql := fmt.Sprintf(`select a.* , b.product_type AS productType,b.service_starttime,b.service_endtime ,b.filter AS productFilter
  701. from dataexport_order a INNER JOIN jy_order_detail b
  702. on a.order_code=b.order_code and a.user_id in (%s) and b.product_type in (%s)
  703. and order_status = 1 and b.service_endtime<"%s" ORDER BY b.service_endtime desc `,
  704. strings.Join(personArr, ","), strings.Join(productArr, ","), findNowTime)
  705. log.Println("有效订单查询1", order3Sql)
  706. _, vip_endtime := getOrderData(order3Sql)
  707. if vip_endtime != "" {
  708. //获取最后一个订单信息
  709. if isRenewalProtection == 1 {
  710. vip_endtimes, _ := time.ParseInLocation(date.Date_Full_Layout, vip_endtime, time.Local)
  711. //查询申请保护时间
  712. renewalTime := time.Now()
  713. timeData := TiDb.SelectBySql(`select max(createtime) as createtime from dwd_f_crm_clue_change_record where clue_id = ? and change_type="申请续费保护"`, clueId)
  714. if timeData != nil && len(*timeData) > 0 {
  715. if gconv.String(gconv.String((*timeData)[0]["createtime"])) != "" {
  716. renewalTime, _ = time.ParseInLocation(date.Date_Full_Layout, gconv.String((*timeData)[0]["createtime"]), time.Local)
  717. }
  718. }
  719. renewalInt := renewalTime.Unix()
  720. log.Println("申请保护期时间", clueId, renewalInt)
  721. log.Println("申请保护期时间222", time.Now().Unix()-vip_endtimes.Unix(), (db.HandoverCycle-1)*86400, (db.HandoverCycle)*86400)
  722. //查看服务到期时间
  723. if renewalInt != 0 && renewalInt < db.CustomerTime {
  724. //三个月
  725. if time.Now().Unix()-vip_endtimes.Unix() < 3*30*86400 {
  726. isOk = true
  727. }
  728. } else if (db.HandoverCycle-5)*86400 < time.Now().Unix()-vip_endtimes.Unix() && time.Now().Unix()-vip_endtimes.Unix() < (db.HandoverCycle-4)*86400 {
  729. //提前一天提示
  730. mailData[name] = append(mailData[name], map[string]interface{}{
  731. "company_name": company_name,
  732. "phone": phone,
  733. "userName": userName,
  734. "remrk": "3天后即将移交",
  735. "reason": "成交客户续费失败",
  736. })
  737. isOk = true
  738. } else if time.Now().Unix()-vip_endtimes.Unix() < db.HandoverCycle*86400 {
  739. isOk = true
  740. }
  741. }
  742. }
  743. if !isOk {
  744. //全到期了
  745. if saleId > 0 {
  746. saleData := TiDb.FindOne("dwd_f_crm_personnel_management", map[string]interface{}{"position_id": saleId, "resign": 0}, "", "")
  747. if saleData != nil && len(*saleData) > 0 {
  748. //该销售人没有变更
  749. } else {
  750. if company_nature == 0 && company_verification == 1 && cluename != "" {
  751. adata := TiDb.Find("dwd_f_crm_clue_info", map[string]interface{}{"cluename": cluename, "is_assign": 1}, "seatNumber,position_id", "", -1, -1)
  752. if adata != nil && len(*adata) > 0 {
  753. isOks := false
  754. for _, vv := range *adata {
  755. position_ids := common.Int64All(vv["position_id"])
  756. newSeatNumber = gconv.String(vv["seatNumber"])
  757. saleDatas := TiDb.FindOne("dwd_f_crm_personnel_management", map[string]interface{}{"position_id": position_ids, "resign": 0}, "", "")
  758. if saleDatas != nil && len(*saleDatas) > 0 {
  759. saleId = position_ids
  760. newPerson = gconv.String((*saleDatas)["name"])
  761. isOks = true
  762. break
  763. }
  764. }
  765. if !isOks {
  766. sdata := TiDb.SelectBySql(`SELECT b.name,b.position_id,b.seat_number from dwd_d_crm_department_level_succbi a INNER JOIN dwd_f_crm_personnel_management b on a.position_id = b.position_id where a.bi_pcode = (SELECT bi_pcode from dwd_d_crm_department_level_succbi where position_id = ?) and b.role_id = 3`, saleId)
  767. if len(*sdata) == 0 {
  768. sdata = TiDb.SelectBySql(`SELECT b.name,b.position_id,b.seat_number from dwd_d_crm_department_level_succbi a INNER JOIN dwd_f_crm_personnel_management b on a.position_id = b.position_id where a.bi_pcode = (SELECT bi_pcode from dwd_d_crm_department_level_succbi where position_id = ?) and b.role_id = 8`, saleId)
  769. }
  770. if sdata != nil && len(*sdata) > 0 {
  771. saleId = common.Int64All((*sdata)[0]["position_id"])
  772. newSeatNumber = gconv.String((*sdata)[0]["seat_number"])
  773. newPerson = gconv.String((*sdata)[0]["name"])
  774. }
  775. }
  776. }
  777. } else {
  778. sdata := &[]map[string]interface{}{}
  779. //查看当前是否属于一部三部
  780. userData := FindPersonOne(saleId)
  781. if userData != nil {
  782. deptName := gconv.String(userData["dept_name"])
  783. if strings.Contains(deptName, "一部") {
  784. sdata = TiDb.SelectBySql(`SELECT b.name,b.position_id,b.seat_number from dwd_d_crm_department_level_succbi a INNER JOIN dwd_f_crm_personnel_management b on a.position_id = b.position_id where a.bi_pcode = (SELECT bi_pcode from dwd_d_crm_department_level_succbi where position_id = ?) and b.role_id = 3`, saleId)
  785. if len(*sdata) == 0 {
  786. sdata = TiDb.SelectBySql(`SELECT b.name,b.position_id,b.seat_number from dwd_d_crm_department_level_succbi a INNER JOIN dwd_f_crm_personnel_management b on a.position_id = b.position_id where a.bi_pcode = (SELECT bi_pcode from dwd_d_crm_department_level_succbi where position_id = ?) and b.role_id = 8`, saleId)
  787. }
  788. } else if strings.Contains(deptName, "三部") {
  789. sdata = TiDb.SelectBySql(`SELECT b.name,b.position_id,b.seat_number from dwd_d_crm_department_level_succbi a INNER JOIN dwd_f_crm_personnel_management b on a.position_id = b.position_id where a.bi_pcode = (SELECT bi_pcode from dwd_d_crm_department_level_succbi where position_id = ?) and b.role_id = 8`, saleId)
  790. }
  791. }
  792. if sdata != nil && len(*sdata) > 0 {
  793. saleId = common.Int64All((*sdata)[0]["position_id"])
  794. newSeatNumber = gconv.String((*sdata)[0]["seat_number"])
  795. newPerson = gconv.String((*sdata)[0]["name"])
  796. }
  797. }
  798. }
  799. }
  800. if kcposition_id > 0 {
  801. mailData[name] = append(mailData[name], map[string]interface{}{
  802. "company_name": company_name,
  803. "phone": phone,
  804. "userName": userName,
  805. "remrk": "已移交",
  806. "reason": "成交客户续费失败",
  807. })
  808. }
  809. isFull = FindUpperLimit(gconv.String(saleId), "", false)
  810. //查询主账号下是否存在其他身份的会员权益 755非集团公司
  811. mainUserPower, _ := GetPersonIdentityPower(uid, common.IntAll(v["account_type"]), common.Int64All(v["ent_id"]), "")
  812. if mainUserPower == nil { //err == nil || err !=nil 移交电销
  813. if saleId > 0 {
  814. salesEmailData[saleId] = append(salesEmailData[saleId], map[string]interface{}{
  815. "company_name": company_name,
  816. "phone": phone,
  817. "userName": userName,
  818. "remrk": "已移交",
  819. "reason": "成交客户续费失败",
  820. "cluename": cluename,
  821. })
  822. if saleId != oldSaleId {
  823. //新增个人员变更
  824. //新增变更记录
  825. AddClueChange(clueId, saleId, "position_id", "所属人变更", gconv.String(common.If(oldsaleName != "", oldsaleName, "/")), gconv.String(common.If(newPerson != "", newPerson, "/")), nowTime, common.GetRandom(32), "", "")
  826. if isFull {
  827. TiDb.UpdateOrDeleteBySql(`UPDATE dwd_f_crm_clue_info SET is_unfollow=0,updatetime=?,trailstatus="01",position_id=?,seatNumber=?,is_task=1,tasktime=?,top_cluetype="532",sub_cluetype="537",taskstatus=0,tasksource="其他-成交客户续约失败",is_transfer=0,is_assign=-3,FREEZE_TIME=? WHERE id = ?`, nowTime, saleId, newSeatNumber, nowTime, nowTime, clueId)
  828. } else {
  829. TiDb.UpdateOrDeleteBySql(`UPDATE dwd_f_crm_clue_info SET is_unfollow=0,updatetime=?,trailstatus="01",position_id=?,seatNumber=?,is_task=1,tasktime=?,top_cluetype="532",sub_cluetype="537",taskstatus=0,tasksource="其他-成交客户续约失败",is_transfer=0,is_assign=1 WHERE id = ?`, nowTime, saleId, newSeatNumber, nowTime, clueId)
  830. }
  831. } else {
  832. if isFull {
  833. TiDb.UpdateOrDeleteBySql(`UPDATE dwd_f_crm_clue_info SET is_unfollow=0,updatetime=?,trailstatus="01",top_cluetype="532",sub_cluetype="537",is_transfer=0,is_assign=-3,FREEZE_TIME=? WHERE id = ?`, nowTime, nowTime, clueId)
  834. } else {
  835. TiDb.UpdateOrDeleteBySql(`UPDATE dwd_f_crm_clue_info SET is_unfollow=0,updatetime=?,trailstatus="01",top_cluetype="532",sub_cluetype="537",is_transfer=0,is_assign=1 WHERE id = ?`, nowTime, clueId)
  836. }
  837. }
  838. } else if saleId == 0 {
  839. //找不到人
  840. TiDb.UpdateOrDeleteBySql(`UPDATE dwd_f_crm_clue_info SET is_unfollow=0,updatetime=?,trailstatus="01",position_id=0,seatNumber="",is_task=1,tasktime=?,top_cluetype="532",sub_cluetype="537",taskstatus=0,tasksource="其他-成交客户续约失败",is_transfer=0,is_assign=0 WHERE id = ?`, nowTime, nowTime, clueId)
  841. if oldSaleId != 0 {
  842. //新增变更记录
  843. AddClueChange(clueId, saleId, "position_id", "所属人变更", gconv.String(common.If(oldsaleName != "", oldsaleName, "/")), gconv.String(common.If(newPerson != "", newPerson, "/")), nowTime, common.GetRandom(32), "", "")
  844. }
  845. }
  846. //新增变更记录
  847. AddClueChange(clueId, gconv.Int64(common.If(kcposition_id > 0, kcposition_id, -1)), "trailstatus", "基本信息变更", "成交客户", "商机线索", nowTime, common.GetRandom(32), "", "")
  848. if saleId > 0 {
  849. //新增任务车
  850. AddClueChange(clueId, saleId, "", "加入任务车", "", "线索自动分配-其他-成交客户续约失败", nowTime, common.GetRandom(32), "", "")
  851. }
  852. AddClueChange(clueId, gconv.Int64(common.If(kcposition_id > 0, kcposition_id, -1)), "position_id", "客户成功经理", name, "/", nowTime, common.GetRandom(32), "", "")
  853. AddClueChange(clueId, saleId, "", "移交销售", "", "成交客户续费失败,到期自动移交", nowTime, common.GetRandom(32), "", "")
  854. TiDb.UpdateOrDeleteBySql(`UPDATE dwd_f_csm_customer_info SET is_transfer=1 WHERE clue_id = ?`, clueId)
  855. if isFull {
  856. //新增冻结记录
  857. AddClueChange(clueId, saleId, "", "线索冻结", "", "销售人员私海已达上限", nowTime, common.GetRandom(32), "", "")
  858. //发送邮件
  859. mailContent := ""
  860. if cluename != "" {
  861. if phone != "" {
  862. if cluename == phone {
  863. mailContent = phone
  864. } else {
  865. mailContent = fmt.Sprintf("%s(%s)", cluename, phone)
  866. }
  867. } else {
  868. mailContent = cluename
  869. }
  870. } else {
  871. mailContent = phone
  872. }
  873. HandOverFail(saleId, mailContent)
  874. }
  875. } else { //主账号在其他身份下有会员权益, 更新客成企业信息、更新线索名称
  876. entId := common.Int64All(mainUserPower["entId"])
  877. mainCusData := common.ObjToMap(mainUserPower["customer"])
  878. //cusId := common.Int64All((*mainCusData)["id"])
  879. mainCompanyName := common.InterfaceToStr((*mainCusData)["company_name"])
  880. isGroup, isCommerce := GetCompanyTypeByClueId(mainCompanyName, common.Int64All((*mainCusData)["clue_id"]))
  881. SubAndFreeAccountUpdate(*mainCusData, entId, clueId, common.IntAll(mainUserPower["newAccountType"]), isGroup, isCommerce, common.InterfaceToStr(v["name"]))
  882. }
  883. //处理子账号、免费账号
  884. SubAndFreeAccountToDx(common.Int64All(v["id"]), 1)
  885. }
  886. }
  887. }
  888. }
  889. return true
  890. }, `select id,ent_id,clue_id,position_id,name,is_renewal_protection,company_name,account_type from dwd_f_csm_customer_info where is_transfer = 0 and account_type = 1`)
  891. //}, `select id,ent_id,clue_id,position_id,name,is_renewal_protection,company_name,account_type from dwd_f_csm_customer_info where clue_id =1893222`)
  892. //移交电销提醒
  893. for i, v := range mailData {
  894. ExitKcSend(i, v)
  895. }
  896. //移交电销销售提醒
  897. for i, v := range salesEmailData {
  898. ExitKcSaleSend(i, v)
  899. }
  900. log.Println("自动移交销售定时任务结束")
  901. }
  902. // 查找一部三部人员信息 返回人员信息 以及管理员信息
  903. func FindDeptAdmin(positionId int64) (map[string]interface{}, map[string]interface{}, map[string]interface{}) {
  904. //先判断那个部门的
  905. userData1 := TiDb.SelectBySql(`SELECT
  906. a.position_id,
  907. a.name,
  908. b.seat_number,
  909. b.role_id,
  910. a.bi_pcode,
  911. a.dept_name,
  912. a.resign
  913. FROM
  914. (SELECT *
  915. FROM dwd_d_crm_department_level_succbi u1
  916. WHERE id = (
  917. SELECT MAX(id)
  918. FROM dwd_d_crm_department_level_succbi u2
  919. WHERE u1.position_id = u2.position_id
  920. )
  921. ORDER BY id desc) a
  922. INNER JOIN (SELECT *
  923. FROM dwd_f_crm_personnel_management u1
  924. WHERE id = (
  925. SELECT MAX(id)
  926. FROM dwd_f_crm_personnel_management u2
  927. WHERE u1.position_id = u2.position_id
  928. )
  929. ORDER BY id desc) b ON a.dept_name LIKE "%销售一部%"
  930. AND a.position_id = b.position_id`)
  931. userData3 := TiDb.SelectBySql(`SELECT
  932. a.position_id,
  933. a.name,
  934. b.seat_number,
  935. b.role_id,
  936. a.bi_pcode,
  937. a.dept_name,
  938. a.resign
  939. FROM
  940. (SELECT *
  941. FROM dwd_d_crm_department_level_succbi u1
  942. WHERE id = (
  943. SELECT MAX(id)
  944. FROM dwd_d_crm_department_level_succbi u2
  945. WHERE u1.position_id = u2.position_id
  946. )
  947. ORDER BY id desc) a
  948. INNER JOIN (SELECT *
  949. FROM dwd_f_crm_personnel_management u1
  950. WHERE id = (
  951. SELECT MAX(id)
  952. FROM dwd_f_crm_personnel_management u2
  953. WHERE u1.position_id = u2.position_id
  954. )
  955. ORDER BY id desc) b ON
  956. a.dept_name LIKE "%销售三部"
  957. AND a.position_id = b.position_id`)
  958. if userData3 == nil || len(*userData3) == 0 || userData1 == nil || len(*userData1) == 0 {
  959. log.Println("找不到一部三部员工信息")
  960. return nil, nil, nil
  961. }
  962. //一部高级管理员信息
  963. seniorAdmin1 := map[string]interface{}{}
  964. //三部高级管理员信息
  965. seniorAdmin3 := map[string]interface{}{}
  966. //一部管理员信息
  967. admin1 := map[string]map[string]interface{}{}
  968. //返回当前人信息
  969. admin := map[string]interface{}{}
  970. for _, v := range *userData3 {
  971. v["type"] = 3
  972. id := gconv.Int64(v["position_id"])
  973. roleId := gconv.Int64(v["role_id"])
  974. resign := gconv.Int64(v["resign"])
  975. if id == positionId && resign == 0 {
  976. admin = v
  977. }
  978. if roleId == 8 {
  979. v["orderStatus"] = 2
  980. seniorAdmin3 = v
  981. }
  982. }
  983. for _, v := range *userData1 {
  984. v["type"] = 1
  985. id := gconv.Int64(v["position_id"])
  986. roleId := gconv.Int64(v["role_id"])
  987. dept_name := gconv.String(v["dept_name"])
  988. resign := gconv.Int64(v["resign"])
  989. if id == positionId && resign == 0 {
  990. admin = v
  991. }
  992. if roleId == 8 {
  993. v["orderStatus"] = 2
  994. seniorAdmin1 = v
  995. } else if roleId == 3 {
  996. admin1[dept_name] = v
  997. }
  998. }
  999. //查看当前人属于哪个部门
  1000. if admin == nil {
  1001. //当前人不属于电销部的
  1002. admin = *(TiDb.FindOne("dwd_f_crm_personnel_management", map[string]interface{}{
  1003. "position_id": positionId,
  1004. "resign": 1,
  1005. }, "name", ""))
  1006. }
  1007. positiontype := gconv.Int64(admin["type"])
  1008. deptName := gconv.String(admin["dept_name"])
  1009. switch positiontype {
  1010. case 1:
  1011. roleId := gconv.Int64(admin["role_id"])
  1012. if roleId == 3 {
  1013. return admin, nil, seniorAdmin1
  1014. }
  1015. return admin, admin1[deptName], seniorAdmin1
  1016. case 3:
  1017. return admin, nil, seniorAdmin3
  1018. default:
  1019. return admin, nil, nil
  1020. }
  1021. }
  1022. // 客成人员变更基本信息获取
  1023. func CustomerChangeHandle(data map[string]interface{}) map[string]interface{} {
  1024. clueId := gconv.Int64(data["clue_id"])
  1025. oldPerson := gconv.String(data["old_value"])
  1026. newPerson := gconv.String(data["new_value"])
  1027. operatorId := gconv.Int64(data["operator_id"])
  1028. companyName := ""
  1029. phone := ""
  1030. userName := ""
  1031. clueName := ""
  1032. clueData := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{
  1033. "id": clueId,
  1034. }, "", "")
  1035. if clueData == nil || len(*clueData) == 0 {
  1036. return nil
  1037. }
  1038. uid := gconv.String((*clueData)["uid"])
  1039. phone = gconv.String((*clueData)["phone"])
  1040. userName = gconv.String((*clueData)["name"])
  1041. //positionId := gconv.Int64((*clueData)["position_id"])
  1042. positionId, _, _ := FindPositionIdClueId(uid)
  1043. clueName = gconv.String((*clueData)["cluename"])
  1044. customData := TiDb.FindOne("dwd_f_csm_customer_info", map[string]interface{}{
  1045. "clue_id": clueId,
  1046. }, "", "")
  1047. if customData != nil || len(*customData) != 0 {
  1048. companyName = gconv.String((*customData)["company_name"])
  1049. }
  1050. return map[string]interface{}{
  1051. "oldPerson": oldPerson,
  1052. "newPerson": newPerson,
  1053. "operatorId": operatorId,
  1054. "phone": phone,
  1055. "userName": userName,
  1056. "positionId": positionId,
  1057. "clueName": clueName,
  1058. "companyName": companyName,
  1059. }
  1060. }
  1061. // 查找订单实际业绩归属
  1062. func FindPositionIdClueId(uid string) (int64, string, string) {
  1063. personArr := getUserIdToUid(uid)
  1064. productArr, _ := KcProduct()
  1065. querySql := fmt.Sprintf(` SELECT
  1066. d.saler_name as salesperson ,c.position_id,f.dept_name,c.seat_number,b.product_type as productType,b.filter
  1067. FROM
  1068. jianyu.dataexport_order a INNER JOIN jianyu.jy_order_detail b on
  1069. a.order_code=b.order_code and a.user_id in (%s)
  1070. AND (
  1071. b.final_price > 0
  1072. OR (
  1073. b.final_price = 0
  1074. AND ( a.zero_type= "分期付款权益补充" OR a.zero_type= "原订单不支持开通多项权益" OR a.zero_type= "权益码兑换" )))
  1075. AND a.order_status = 1 and a.user_phone not like "%s"
  1076. AND ( a.refund_status != 1 OR a.refund_status IS NULL )
  1077. AND b.service_starttime < "2099-01-01"
  1078. AND b.product_type IN (%s )
  1079. AND ( b.service_type != 4 or b.service_type is NULL OR ( b.service_type = 4 AND TIMESTAMPDIFF(DAY, b.service_starttime, b.service_endtime )> 90 ) )
  1080. inner JOIN jianyu.order_sale_record d on b.order_code=d.ordercode and d.state=1
  1081. INNER JOIN jianyu.entniche_user e on d.ent_userId = e.id
  1082. INNER JOIN dwd_f_crm_personnel_management c on c.ent_id =? and e.name=c.name
  1083. inner join dwd_d_crm_department_level_succbi f on c.position_id=f.position_id
  1084. ORDER BY
  1085. b.service_endtime desc ,b.final_price DESC `, strings.Join(personArr, ","), "9%", strings.Join(productArr, ","))
  1086. log.Println("业绩归属查询:", querySql)
  1087. clueData := TiDb.SelectBySql(querySql, db.EntId)
  1088. if clueData == nil || len(*clueData) == 0 {
  1089. return 0, "", ""
  1090. }
  1091. for _, m := range *clueData {
  1092. productType := gconv.String(m["productType"])
  1093. if productType == "大会员" {
  1094. level := gconv.Int(m["service_type"])
  1095. if level == 4 {
  1096. continue
  1097. }
  1098. }
  1099. deptName := gconv.String(m["dept_name"])
  1100. if strings.Contains(deptName, "一部") || strings.Contains(deptName, "三部") {
  1101. return gconv.Int64(m["position_id"]), gconv.String(m["salesperson"]), gconv.String(m["seat_number"])
  1102. }
  1103. }
  1104. return 0, "", ""
  1105. }
  1106. func refundAutoHistory() {
  1107. data := TiDb.Find("dwd_f_crm_clue_autodraw_record", nil, "", "", -1, -1)
  1108. if data != nil {
  1109. for _, v := range *data {
  1110. seatNumber := gconv.String(v["seatNumber"])
  1111. adata := TiDb.Find("dwd_f_crm_personnel_management", map[string]interface{}{"seat_number": seatNumber}, "", "", -1, -1)
  1112. if adata != nil {
  1113. for _, vv := range *adata {
  1114. if common.IntAll(vv["resign"]) == 0 {
  1115. position_id := common.Int64All(vv["position_id"])
  1116. TiDb.Update("dwd_f_crm_clue_autodraw_record", map[string]interface{}{"seatNumber": seatNumber}, map[string]interface{}{"position_id": position_id})
  1117. break
  1118. }
  1119. }
  1120. }
  1121. }
  1122. }
  1123. }
  1124. func IsFreeze(source string, pay_money int, positionId, trailstatus string) bool {
  1125. log.Println(source, pay_money == 0, FindUpperLimit(gconv.String(
  1126. positionId), "", false), trailstatus)
  1127. if source == "0104" && pay_money == 0 && FindUpperLimit(gconv.String(
  1128. positionId), "", false) {
  1129. return true
  1130. } else if source == "0104" && pay_money > 0 && trailstatus == "08" && FindUpperLimit(gconv.String(
  1131. positionId), "", false) {
  1132. return true
  1133. }
  1134. return false
  1135. }
  1136. // 业绩归属查询
  1137. func FindSaleRecord(orderCode string) (dept string, positionId int64, position string) {
  1138. recordList := Mysql.SelectBySql(`
  1139. SELECT DISTINCT
  1140. a.saler_dept,
  1141. a.saler_name,
  1142. b.phone
  1143. FROM
  1144. order_sale_record a
  1145. INNER JOIN entniche_user b
  1146. on
  1147. a.ordercode = ? and a.ent_userId = b.id
  1148. ORDER BY
  1149. a.state,
  1150. a.money desc
  1151. `, orderCode)
  1152. if recordList != nil && len(*recordList) > 0 {
  1153. saler_dept := gconv.String((*recordList)[0]["saler_dept"])
  1154. if strings.Contains(saler_dept, "销售") {
  1155. saler_dept = "销售部"
  1156. } else if strings.Contains(saler_dept, "市场") {
  1157. saler_dept = "市场部"
  1158. } else if strings.Contains(saler_dept, "客户成功") && !strings.Contains(saler_dept, "客服") {
  1159. saler_dept = "客户成功部"
  1160. } else {
  1161. saler_dept = ""
  1162. }
  1163. positionid := PhoneToPositionId(gconv.String((*recordList)[0]["phone"]))
  1164. if positionid > 0 {
  1165. return saler_dept, positionid, gconv.String((*recordList)[0]["saler_name"])
  1166. }
  1167. }
  1168. return "", int64(0), ""
  1169. }
  1170. func PhoneToPositionId(phone string) int64 {
  1171. positionId := int64(0)
  1172. data := Base.SelectBySql(`SELECT
  1173. b.id
  1174. FROM
  1175. base_user a
  1176. INNER JOIN base_position b ON a.phone = ?
  1177. AND a.id = b.user_id
  1178. AND b.ent_id = 25917`, phone)
  1179. if data != nil && len(*data) > 0 {
  1180. positionId = gconv.Int64((*data)[0]["id"])
  1181. }
  1182. return positionId
  1183. }
  1184. func kcClue(userId, uId, seatNumber, cluename, top_cluetype, sub_cluetype,
  1185. name, phone, position, sourceCode, industry, follow_project_area,
  1186. role, item, subname, topname, remark, demand, department, departments, saleName, source string, positionId int64, isGroup, isCommerce int, keywords []string) bool {
  1187. clueId, updateId1, updateId2, updateId3, updateId4, updateId5 := int64(0), int64(0), int64(0), int64(0), int64(0), int64(0)
  1188. nowTime := time.Now().Format("2006-01-02 15:04:05")
  1189. nowTimes := time.Unix(time.Now().Unix()+3600*12, 0).Format("2006-01-02 15:04:05")
  1190. if TiDb.ExecTx("保存线索", func(tx *sql.Tx) bool {
  1191. clueId = TiDb.InsertByTx(tx, "dwd_f_crm_clue_info", map[string]interface{}{
  1192. "userid": userId,
  1193. "uid": uId,
  1194. "seatNumber": seatNumber,
  1195. "position_id": positionId,
  1196. "is_assign": common.If(positionId > 0, 1, 0),
  1197. "comeintime": nowTime,
  1198. "createtime": nowTime,
  1199. "updatetime": nowTime,
  1200. "cluename": cluename,
  1201. "top_cluetype": top_cluetype,
  1202. "sub_cluetype": sub_cluetype,
  1203. "trailstatus": "01",
  1204. "name": name,
  1205. "phone": phone,
  1206. "position": position,
  1207. "department": common.If(sourceCode == "app_xzcyh", departments, department),
  1208. "industry": industry,
  1209. "follow_project_area": follow_project_area,
  1210. "role": role,
  1211. "comeinsource_private": 2,
  1212. "is_task": 1,
  1213. "task_time": nowTime,
  1214. "tasktime": common.If(item == "users", nowTimes, nowTime),
  1215. "taskstatus": 0,
  1216. "tasksource": "线索自动分配" + "-" + topname + "-" + subname,
  1217. "business_scope": common.If(sourceCode == "app_xzcyh", keywords, nil),
  1218. "company_nature": isGroup,
  1219. "company_verification": isCommerce,
  1220. "remark": remark,
  1221. "customer_demand": demand,
  1222. "FREEZE_TIME": nowTime,
  1223. "label": 1,
  1224. "labelChangeTime": time.Now().Format("2006-01-02"),
  1225. })
  1226. updateId1 = AddClueChange(clueId, positionId, "", "创建线索", "", "系统自动创建", nowTime, common.GetRandom(32), "", "")
  1227. updateId2 = AddClueChange(clueId, positionId, "position_id", "所属人变更", "", saleName, nowTime, common.GetRandom(32), "", "")
  1228. updateId3 = AddClueChange(clueId, positionId, "trailstatus", "基本信息变更", "商机线索", "新增", nowTime, common.GetRandom(32), "", "")
  1229. updateId4 = AddClueChange(clueId, positionId, "top_cluetype", "基本信息变更", "/", topname, nowTime, common.GetRandom(32), "", "")
  1230. updateId5 = AddClueChange(clueId, positionId, "sub_cluetype", "基本信息变更", "/", subname, nowTime, common.GetRandom(32), "", "")
  1231. return clueId > -1 && updateId1 > -1 && updateId2 > -1 && updateId3 > -1 && updateId4 > -1 && updateId5 > -1
  1232. }) {
  1233. log.Println("线索分配成功")
  1234. if TiDb.Count("dwd_f_userbase_contacts", map[string]interface{}{"phone": phone}) == 0 {
  1235. TiDb.Insert("dwd_f_userbase_contacts", map[string]interface{}{
  1236. "status": 1,
  1237. "is_delete": 1,
  1238. "createtime": nowTime,
  1239. "updatetime": nowTime,
  1240. "phone": phone,
  1241. "baseinfo_id": uId,
  1242. "SOURCE": source,
  1243. })
  1244. }
  1245. return true
  1246. }
  1247. return false
  1248. }
  1249. type OrderInfo struct {
  1250. Id int64
  1251. UserId string
  1252. CompanyName string
  1253. ProductType string
  1254. OrderCode string
  1255. PayMoney float64
  1256. ReturnMoney float64
  1257. UserPhone string
  1258. StartEnd string
  1259. DisKcName string
  1260. UserName string
  1261. SeriveList []string
  1262. SaleName string
  1263. }
  1264. // 客成发送邮箱
  1265. func KcSend(orderCode, personName string) {
  1266. log.Println("客成发邮件", orderCode)
  1267. orderInfo := KcOrderFormat(orderCode)
  1268. if orderInfo != nil {
  1269. tableAppend := ""
  1270. if len(orderInfo.SeriveList) > 0 {
  1271. tableAppend = fmt.Sprintf(db.KeCheng.Mail.ServiceList, strings.Join(orderInfo.SeriveList, ","))
  1272. }
  1273. if orderInfo.ReturnMoney > 0 {
  1274. tableAppend += fmt.Sprintf(db.KeCheng.Mail.ReturnMoney, orderInfo.ReturnMoney)
  1275. }
  1276. table := ""
  1277. orderInfo.DisKcName = personName
  1278. deptData := Mysql.SelectBySql("select b.mail from jianyu.entniche_department_user a inner join jianyu.entniche_user b on a.dept_id=? and a.user_id=b.id and b.name=? ", db.KeCheng.DeptId, personName)
  1279. adminData := Mysql.SelectBySql(` select c.mail from entniche_department_user a INNER JOIN entniche_user_role b on a.dept_id=59005 and a.user_id = b.user_id and b.role_id=2 INNER JOIN entniche_user c on a.user_id=c.id`)
  1280. table += fmt.Sprintf(db.KeCheng.Mail.Table, orderInfo.ProductType, orderInfo.CompanyName, orderInfo.UserPhone, orderInfo.UserName, orderInfo.OrderCode, orderInfo.PayMoney, orderInfo.StartEnd, orderInfo.DisKcName, orderInfo.SaleName, tableAppend)
  1281. adminMailStr := ""
  1282. if adminData != nil && len(*adminData) > 0 {
  1283. adminMailStr = gconv.String((*adminData)[0]["mail"])
  1284. }
  1285. //发送邮件
  1286. if personName == "" {
  1287. if adminData != nil && len(*adminData) > 0 {
  1288. //发送给管理员
  1289. if adminMailStr != "" {
  1290. gmail := &mail.GmailAuth{
  1291. SmtpHost: db.Mail.SmtpHost,
  1292. SmtpPort: db.Mail.SmtpPort,
  1293. User: db.Mail.User,
  1294. Pwd: db.Mail.Pwd,
  1295. }
  1296. status := mail.GSendMail_q("剑鱼标讯", adminMailStr, "", "", db.KeCheng.Title, fmt.Sprintf(db.KeCheng.Mail.Content, table), "", "", gmail)
  1297. if status {
  1298. log.Println("客成发邮件 send mail success", table, adminMailStr)
  1299. }
  1300. }
  1301. }
  1302. return
  1303. }
  1304. //当事人 管理员发送
  1305. if deptData != nil && len(*deptData) > 0 {
  1306. mailStr := gconv.String((*deptData)[0]["mail"])
  1307. if mailStr != "" || adminMailStr != "" {
  1308. if mailStr == adminMailStr {
  1309. adminMailStr = ""
  1310. }
  1311. gmail := &mail.GmailAuth{
  1312. SmtpHost: db.Mail.SmtpHost,
  1313. SmtpPort: db.Mail.SmtpPort,
  1314. User: db.Mail.User,
  1315. Pwd: db.Mail.Pwd,
  1316. }
  1317. status := true
  1318. if mailStr == "" {
  1319. status = mail.GSendMail_q("剑鱼标讯", adminMailStr, "", "", db.KeCheng.Title, fmt.Sprintf(db.KeCheng.Mail.Content, table), "", "", gmail)
  1320. } else {
  1321. status = mail.GSendMail_q("剑鱼标讯", mailStr, adminMailStr, "", db.KeCheng.Title, fmt.Sprintf(db.KeCheng.Mail.Content, table), "", "", gmail)
  1322. }
  1323. if status {
  1324. log.Println("客成发邮件 send mail success", table, mailStr, adminMailStr)
  1325. }
  1326. }
  1327. }
  1328. }
  1329. }
  1330. func FindPersonOne(positionId int64) map[string]interface{} {
  1331. personData := TiDb.SelectBySql(`SELECT
  1332. b.name,
  1333. b.position_id,
  1334. b.seat_number,
  1335. b.role_id,
  1336. a.dept_name
  1337. FROM
  1338. dwd_d_crm_department_level_succbi a
  1339. INNER JOIN dwd_f_crm_personnel_management b ON a.position_id = ?
  1340. AND a.position_id = b.position_id`, positionId)
  1341. if personData == nil || len(*personData) == 0 {
  1342. return nil
  1343. }
  1344. return (*personData)[0]
  1345. }
  1346. // 进客成商品查询
  1347. func KcProduct() ([]string, map[string]bool) {
  1348. var strArr []string
  1349. strMap := map[string]bool{}
  1350. productData := Mysql.SelectBySql(`SELECT id ,
  1351. CONCAT( '"', class_name,'"' ) as product
  1352. FROM
  1353. jy_product_class
  1354. WHERE
  1355. s_service = 1`)
  1356. if productData == nil && len(*productData) == 0 {
  1357. return strArr, strMap
  1358. }
  1359. for _, m := range *productData {
  1360. strMap[gconv.String(m["product"])] = true
  1361. strArr = append(strArr, gconv.String(m["product"]))
  1362. }
  1363. return strArr, strMap
  1364. }
  1365. func GetOrderProduct(productType string, file string) (string, int64, int64) {
  1366. fileJson := gconv.Map(file)
  1367. if fileJson == nil || len(fileJson) == 0 {
  1368. return "", 0, 0
  1369. }
  1370. productName := ""
  1371. level := int64(0)
  1372. switch productType {
  1373. case "大会员":
  1374. level = gconv.Int64(fileJson["comboId"])
  1375. if level == 0 {
  1376. level = gconv.Int64(fileJson["level"])
  1377. }
  1378. switch level {
  1379. case 0:
  1380. productName = "大会员自定义"
  1381. case 30190:
  1382. productName = "大会员商机版2.0(单省版)"
  1383. case 6:
  1384. productName = "大会员商机版2.0"
  1385. case 7:
  1386. productName = "大会员专家版2.0"
  1387. }
  1388. default:
  1389. productName = productType
  1390. }
  1391. productData := TiDb.FindOne("dwd_d_csm_product_access_code", map[string]interface{}{
  1392. "name": productName,
  1393. }, "", "")
  1394. if productData == nil || len(*productData) == 0 {
  1395. return productName, 0, level
  1396. }
  1397. return productName, gconv.Int64((*productData)["code"]), level
  1398. }
  1399. func GetTimeDifference(timeStr1, timeStr2 string) int {
  1400. // 解析时间字符串
  1401. t1, err1 := time.Parse(time.DateTime, timeStr1)
  1402. t2, err2 := time.Parse(time.DateTime, timeStr2)
  1403. if err1 != nil || err2 != nil {
  1404. fmt.Println("时间格式错误:", err1, err2)
  1405. return 0
  1406. }
  1407. // 计算时间差
  1408. daysDiff := gconv.Int(t2.Sub(t1).Hours() / 24)
  1409. fmt.Printf("两个时间相差 %.0f 天\n", daysDiff)
  1410. return daysDiff
  1411. }
  1412. func getOrderData(sql string) (map[string]map[string]interface{}, string) {
  1413. data := Mysql.SelectBySql(sql)
  1414. orderMap := map[string]map[string]interface{}{}
  1415. lastEndTime := ""
  1416. for _, v := range *data {
  1417. orderCode := gconv.String(v["order_code"])
  1418. product_type := gconv.String(v["productType"])
  1419. vip_starttime := gconv.String(v["service_starttime"])
  1420. vip_endtime := gconv.String(v["service_endtime"])
  1421. //判断一下服务周期
  1422. difference := GetTimeDifference(vip_starttime, vip_endtime)
  1423. _, productInt64, _ := GetOrderProduct(product_type, gconv.String(v["productFilter"]))
  1424. if productInt64 == 0 {
  1425. continue
  1426. }
  1427. t1, _ := time.Parse(time.DateTime, lastEndTime)
  1428. t2, _ := time.Parse(time.DateTime, vip_endtime)
  1429. //判断服务周期
  1430. if t2.Unix() > t1.Unix() {
  1431. lastEndTime = vip_endtime
  1432. }
  1433. if _, exists := orderMap[orderCode]; exists {
  1434. data := orderMap[orderCode]
  1435. //商品类型获取
  1436. oldDifference := gconv.Int(data["difference"])
  1437. if difference >= oldDifference {
  1438. //需要更换
  1439. v["difference"] = difference
  1440. v["product"] = productInt64
  1441. v["service_endtime"] = vip_endtime
  1442. v["service_starttime"] = vip_starttime
  1443. v["product_type"] = product_type
  1444. orderMap[orderCode] = v
  1445. }
  1446. } else {
  1447. v["difference"] = difference
  1448. v["product"] = productInt64
  1449. v["product_type"] = product_type
  1450. orderMap[orderCode] = v
  1451. }
  1452. }
  1453. return orderMap, lastEndTime
  1454. }
  1455. type KcTransferRequest struct {
  1456. //主账号信息
  1457. HostClueName string
  1458. HostClueId int64
  1459. HostUID string // 用户唯一标识
  1460. // 基础信息
  1461. ClueType int64 // 线索类型(1:个人,2:企业,3:子账号等)
  1462. UserList []interface{} // 用户列表(使用具体类型替代interface{})
  1463. NowTime string
  1464. SendUserMailMap map[string]map[string]interface{}
  1465. LogPrefix string
  1466. IsDelete bool
  1467. //主账号下边人信息
  1468. SecondaryAccountType int64
  1469. SecondaryPersonUid string
  1470. SecondaryUserName string
  1471. SecondaryUserPhone string
  1472. SecondaryClueId int64
  1473. SecondaryClueName string
  1474. //客成信息
  1475. KcID int64 // 自定义业务ID
  1476. KcBuySubject int64 // 购买主体
  1477. KcName string // 新客成经理姓名
  1478. KcOldName string //老客成经理姓名
  1479. KcCompanyName string // 公司名称
  1480. KcStartTime string
  1481. KcEndTime string
  1482. KcProduct int64
  1483. KcProductName string
  1484. KcEntId interface{}
  1485. KcPositionId int64 // 职位ID
  1486. }
  1487. // OtherKcTransfer 处理客成移交逻辑
  1488. func (k *KcTransferRequest) OtherKcTransfer() {
  1489. // 初始化日志前缀
  1490. k.LogPrefix = fmt.Sprintf("[客成移交] uid:%s, kcName:%s, company:%s", k.HostUID, k.KcName, k.KcCompanyName)
  1491. if gconv.Int64(k.KcEntId) == 0 {
  1492. k.handlePersonalAccount()
  1493. } else {
  1494. k.handleEnterpriseAccount()
  1495. }
  1496. if !isGroupCompany(k.KcCompanyName) {
  1497. if gconv.Int64(k.KcEntId) > 0 && k.KcCompanyName != "" {
  1498. k.handleOtherClues()
  1499. }
  1500. }
  1501. //发邮件处理
  1502. userMailList := []map[string]interface{}{}
  1503. for _, v := range k.SendUserMailMap {
  1504. userMailList = append(userMailList, v)
  1505. }
  1506. if len(userMailList) > 0 {
  1507. data := map[int64][]map[string]interface{}{}
  1508. data[k.KcPositionId] = userMailList
  1509. log.Println("需要发送邮件的人")
  1510. log.Println(data)
  1511. //KcClueTransfer(data)
  1512. }
  1513. }
  1514. // handlePersonalAccount 处理个人账号移交
  1515. func (k *KcTransferRequest) handlePersonalAccount() {
  1516. userData := TiDb.FindOne("data_service.user_system", map[string]interface{}{
  1517. "status": 1,
  1518. "uid": k.HostUID,
  1519. }, "", "createtime DESC")
  1520. if userData == nil || len(*userData) == 0 {
  1521. log.Printf("%s - 查询不到用户信息\n", k.LogPrefix)
  1522. return
  1523. }
  1524. mongoId := gconv.String((*userData)["userid"])
  1525. childAccount, _ := Mgo.Find("user", map[string]interface{}{"s_member_mainid": mongoId, "i_member_sub_status": 1, "i_member_status": map[string]interface{}{"$gt": 0}}, "", `"_id":1`, false, -1, -1)
  1526. if childAccount == nil || len(*childAccount) == 0 {
  1527. log.Printf("%s - 子账号查询不到, mongoId:%s\n", k.LogPrefix, mongoId)
  1528. return
  1529. }
  1530. log.Printf("%s - 找到子账号, 数量:%v\n", k.LogPrefix, len(*childAccount))
  1531. childIds := make([]interface{}, 0, len(*childAccount))
  1532. for _, v := range *childAccount {
  1533. childIds = append(childIds, mongodb.BsonIdToSId(v["_id"]))
  1534. }
  1535. k.ClueType = 21
  1536. k.UserList = childIds
  1537. k.addKcClue()
  1538. }
  1539. // handleEnterpriseAccount
  1540. func (k *KcTransferRequest) handleEnterpriseAccount() {
  1541. log.Println("处理企业账号移交:", k.LogPrefix)
  1542. entData := Mysql.Find("entniche_user", map[string]interface{}{"ent_id": k.KcEntId}, "", "", -1, -1)
  1543. if entData == nil || len(*entData) == 0 {
  1544. log.Printf("%s - 企业账号不存在, entId:%v\n", k.LogPrefix, k.KcEntId)
  1545. return
  1546. }
  1547. entMap := make(map[int64]map[string]interface{})
  1548. for _, v := range *entData {
  1549. id := gconv.Int64(v["id"])
  1550. entMap[id] = v
  1551. }
  1552. noPowerList := []interface{}{}
  1553. powerList := k.classifyEnterpriseUsers(entMap)
  1554. if len(powerList) > 0 {
  1555. k.ClueType = 22
  1556. k.UserList = powerList
  1557. k.addKcClue()
  1558. }
  1559. if len(entMap) > 0 {
  1560. for k := range entMap {
  1561. noPowerList = append(noPowerList, k)
  1562. }
  1563. k.ClueType = 3
  1564. k.UserList = noPowerList
  1565. k.addKcClue()
  1566. }
  1567. }
  1568. // classifyEnterpriseUsers 分类企业用户权限
  1569. func (k *KcTransferRequest) classifyEnterpriseUsers(entMap map[int64]map[string]interface{}) []interface{} {
  1570. log.Println("分类企业用户权限:", k.LogPrefix)
  1571. powerList := make([]interface{}, 0)
  1572. switch k.KcProductName {
  1573. case "商机管理":
  1574. sql := fmt.Sprintf(`SELECT b.* FROM entniche_info a
  1575. INNER JOIN entniche_user b ON a.id=%v AND a.id = b.ent_id
  1576. AND a.status = 1 AND a.enddate > UNIX_TIMESTAMP() AND b.power =1`, k.KcEntId)
  1577. powerData := Mysql.SelectBySql(sql)
  1578. if powerData != nil && len(*powerData) > 0 {
  1579. for _, v := range *powerData {
  1580. entUserId := gconv.Int64(v["id"])
  1581. if _, exists := entMap[entUserId]; exists {
  1582. powerList = append(powerList, entUserId)
  1583. delete(entMap, entUserId)
  1584. }
  1585. }
  1586. }
  1587. case "大会员":
  1588. powerData, _ := Mgo.Find("ent_user", map[string]interface{}{
  1589. "i_member_status": map[string]interface{}{"$gt": 0},
  1590. }, "", "", false, -1, -1)
  1591. if powerData != nil && len(*powerData) > 0 {
  1592. for _, v := range *powerData {
  1593. entUserId := gconv.Int64(v["i_userid"])
  1594. if _, exists := entMap[entUserId]; exists {
  1595. powerList = append(powerList, entUserId)
  1596. delete(entMap, entUserId)
  1597. }
  1598. }
  1599. }
  1600. }
  1601. return powerList
  1602. }
  1603. // isGroupCompany 检查是否为集团公司
  1604. func isGroupCompany(companyName string) bool {
  1605. count := TiDb.CountBySql(`SELECT count(1) FROM group_company_name WHERE company_name=?`, companyName)
  1606. return count > 0
  1607. }
  1608. // handleOtherClues 处理其他相关线索
  1609. func (k *KcTransferRequest) handleOtherClues() {
  1610. sql := fmt.Sprintf(`SELECT c.* FROM dwd_f_crm_clue_info c
  1611. INNER JOIN data_service.user_system d ON c.cluename = "%s" AND c.is_transfer=0
  1612. AND c.uid = d.uid AND d.STATUS = 1
  1613. WHERE NOT EXISTS (
  1614. SELECT 1 FROM data_service.user_system b
  1615. WHERE b.uid = c.uid %s AND b.STATUS = 1
  1616. )`, k.KcCompanyName, common.If(gconv.Int64(k.KcEntId) == 0, "", fmt.Sprintf(` AND b.ent_id = %v`, gconv.Int64(k.KcEntId))))
  1617. otherData := TiDb.SelectBySql(sql)
  1618. if otherData == nil || len(*otherData) == 0 {
  1619. return
  1620. }
  1621. otherList := make([]interface{}, 0, len(*otherData))
  1622. for _, v := range *otherData {
  1623. otherList = append(otherList, gconv.Int64(v["id"]))
  1624. }
  1625. k.ClueType = 4
  1626. k.UserList = otherList
  1627. k.addKcClue()
  1628. }
  1629. // addKcClue 添加客成线索
  1630. func (k *KcTransferRequest) addKcClue() {
  1631. for _, userId := range k.UserList {
  1632. uid, err := getUserIdByClueType(k.ClueType, userId, k.KcEntId)
  1633. if err != nil {
  1634. log.Printf("获取用户ID失败: %v, clueType:%d, userId:%v\n", err, k.ClueType, userId)
  1635. continue
  1636. }
  1637. if uid == k.HostUID {
  1638. continue
  1639. }
  1640. clueData, err := getClueData(k.ClueType, uid, userId)
  1641. if err != nil {
  1642. log.Printf("获取线索数据失败: %v\n", err)
  1643. continue
  1644. }
  1645. k.SecondaryUserName = gconv.String((*clueData)["name"])
  1646. k.SecondaryUserPhone = gconv.String((*clueData)["phone"])
  1647. k.SecondaryClueId = gconv.Int64((*clueData)["id"])
  1648. k.HostUID = gconv.String((*clueData)["uid"])
  1649. k.SecondaryClueName = gconv.String((*clueData)["cluename"])
  1650. // 处理客户数据
  1651. k.handleCustomerData()
  1652. }
  1653. }
  1654. // getUserIdByClueType 根据线索类型获取用户ID
  1655. func getUserIdByClueType(clueType int64, userId interface{}, entId interface{}) (string, error) {
  1656. switch clueType {
  1657. case 21: // 子账号
  1658. userData := TiDb.FindOne("data_service.user_system", map[string]interface{}{
  1659. "uid": userId,
  1660. "status": 1,
  1661. "type": 0,
  1662. }, "", "")
  1663. if userData == nil || len(*userData) == 0 {
  1664. return "", fmt.Errorf("个人用户不存在: %v", userId)
  1665. }
  1666. return gconv.String((*userData)["uid"]), nil
  1667. case 3, 22: // 企业账号
  1668. userData := TiDb.FindOne("data_service.user_system", map[string]interface{}{
  1669. "ent_user_id": userId,
  1670. "status": 1,
  1671. "ent_id": entId,
  1672. }, "", "")
  1673. if userData == nil || len(*userData) == 0 {
  1674. return "", fmt.Errorf("企业用户不存在: %v", userId)
  1675. }
  1676. return gconv.String((*userData)["uid"]), nil
  1677. default:
  1678. return "", nil
  1679. }
  1680. }
  1681. // getClueData 获取线索数据
  1682. func getClueData(clueType int64, uid string, userId interface{}) (*map[string]interface{}, error) {
  1683. var query map[string]interface{}
  1684. if clueType == 21 || clueType == 22 || clueType == 3 {
  1685. query = map[string]interface{}{"uid": uid}
  1686. } else {
  1687. query = map[string]interface{}{"id": userId}
  1688. }
  1689. clueData := TiDb.FindOne("dwd_f_crm_clue_info", query, "", "")
  1690. if clueData == nil || len(*clueData) == 0 {
  1691. return nil, fmt.Errorf("线索不存在, clueType:%d, uid:%s, userId:%v", clueType, uid, userId)
  1692. }
  1693. return clueData, nil
  1694. }
  1695. func GetClueTypeName(clueType int64) (reason string) {
  1696. switch clueType {
  1697. case 21, 22:
  1698. reason = "子账号移交"
  1699. case 3:
  1700. reason = "企业组织架构免费账户"
  1701. case 4:
  1702. reason = "非集团公司成交客户关联线索"
  1703. }
  1704. return
  1705. }
  1706. // handleCustomerData 处理客户数据
  1707. func (k *KcTransferRequest) handleCustomerData() {
  1708. customData := TiDb.FindOne("dwd_f_csm_customer_info", map[string]interface{}{"clue_id": k.SecondaryClueId}, "", "")
  1709. var oldKcName string
  1710. if customData == nil || len(*customData) == 0 {
  1711. var accountType int64
  1712. // 新增客户
  1713. switch k.ClueType {
  1714. case 21, 22, 2:
  1715. accountType = 2
  1716. case 3:
  1717. accountType = 3
  1718. case 4:
  1719. accountType = 4
  1720. }
  1721. reason := GetClueTypeName(accountType)
  1722. k.saveCustomerInfo(accountType)
  1723. if k.SendUserMailMap == nil {
  1724. k.SendUserMailMap = map[string]map[string]interface{}{}
  1725. }
  1726. k.SendUserMailMap[k.SecondaryPersonUid] = map[string]interface{}{
  1727. "clueName": k.HostClueName,
  1728. "userName": k.SecondaryUserPhone,
  1729. "phone": k.SecondaryUserPhone,
  1730. "reason": reason,
  1731. }
  1732. // 添加变更记录
  1733. k.addChangeRecords(accountType)
  1734. } else {
  1735. // 更新客户信息
  1736. oldKcName = gconv.String((*customData)["name"])
  1737. oldClueType := gconv.Int64((*customData)["account_type"])
  1738. k.KcOldName = oldKcName
  1739. isTransfer := gconv.Int64((*customData)["is_transfer"])
  1740. // 检查是否需要跳过更新
  1741. isUpdate, newAccountType := shouldSkipUpdate(k.ClueType, isTransfer, oldClueType, k.IsDelete)
  1742. if isUpdate {
  1743. return
  1744. }
  1745. reason := GetClueTypeName(newAccountType)
  1746. if k.SendUserMailMap == nil {
  1747. k.SendUserMailMap = make(map[string]map[string]interface{}) // 如果 nil,则初始化
  1748. }
  1749. k.SendUserMailMap[k.SecondaryPersonUid] = map[string]interface{}{
  1750. "clueName": k.HostClueName,
  1751. "userName": k.SecondaryUserName,
  1752. "phone": k.SecondaryUserPhone,
  1753. "reason": reason,
  1754. }
  1755. k.updateCustomerInfo(newAccountType)
  1756. // 添加变更记录
  1757. k.addChangeRecords(newAccountType)
  1758. }
  1759. }
  1760. // saveCustomerInfo 保存客户信息
  1761. func (k *KcTransferRequest) saveCustomerInfo(accountType int64) {
  1762. saveMap := map[string]interface{}{
  1763. "clue_id": k.SecondaryClueId,
  1764. "transfertime": k.NowTime,
  1765. "service_starttime": k.KcStartTime,
  1766. "service_endtime": k.KcEndTime,
  1767. "ent_id": k.KcEntId,
  1768. "is_task": 0,
  1769. "tasktime": k.NowTime,
  1770. "taskstatus": 0,
  1771. "tasksource": "1",
  1772. "is_admin": 0,
  1773. "product_access": k.KcProduct,
  1774. "buy_subject": k.KcBuySubject,
  1775. "relationship_building_way": 1,
  1776. "inventory_way": 1,
  1777. "training_way": 1,
  1778. "is_pre_sales_training": 0,
  1779. "service_stage": 1,
  1780. "company_name": k.KcCompanyName,
  1781. "position_id": k.KcPositionId,
  1782. "name": k.KcName,
  1783. "is_transfer": 0,
  1784. "account_type": accountType,
  1785. "primary_id": k.KcID,
  1786. }
  1787. if id := TiDb.Insert("dwd_f_csm_customer_info", saveMap); id < 0 {
  1788. log.Printf("保存客户信息失败: %v, clueId:%s\n")
  1789. return
  1790. }
  1791. }
  1792. // updateCustomerInfo 更新客户信息
  1793. func (k *KcTransferRequest) updateCustomerInfo(newAccountType int64) {
  1794. updateMap := map[string]interface{}{
  1795. "is_transfer": 0,
  1796. "is_renewal_protection": 0,
  1797. "product_access": k.KcProduct,
  1798. "buy_subject": k.KcBuySubject,
  1799. "transfertime": k.NowTime,
  1800. "service_starttime": k.KcStartTime,
  1801. "service_endtime": k.KcEndTime,
  1802. "ent_id": k.KcEntId,
  1803. "company_name": k.KcCompanyName,
  1804. "name": k.KcName,
  1805. "position_id": k.KcPositionId,
  1806. "primary_id": k.KcID,
  1807. "account_type": newAccountType,
  1808. "relationship_building_way": 1,
  1809. "tasksource": 0,
  1810. "inventory_way": 1,
  1811. "training_way": 1,
  1812. "is_pre_sales_training": 0,
  1813. "service_stage": 1,
  1814. "is_task": 0,
  1815. }
  1816. if ok := TiDb.Update("dwd_f_csm_customer_info", map[string]interface{}{"clue_id": k.SecondaryClueId}, updateMap); !ok {
  1817. log.Printf("更新客户信息失败: %v, clueId:%s\n", k.SecondaryClueId)
  1818. }
  1819. }
  1820. // shouldSkipUpdate 判断是否需要跳过更新
  1821. func shouldSkipUpdate(clueType, isTransfer, oldClueType int64, IsDelete bool) (bool, int64) {
  1822. newAccountType := int64(0)
  1823. if isTransfer == 0 {
  1824. //当前值 已经在客成了
  1825. if IsDelete {
  1826. return false, clueType
  1827. } else {
  1828. switch oldClueType {
  1829. case 1, 2:
  1830. return true, 0
  1831. case 3:
  1832. if clueType == 21 || clueType == 22 || clueType == 2 {
  1833. return false, 2
  1834. } else {
  1835. return true, 0
  1836. }
  1837. case 4:
  1838. if clueType == 21 || clueType == 22 || clueType == 2 {
  1839. return false, 2
  1840. } else if clueType == 3 {
  1841. return false, 3
  1842. }
  1843. }
  1844. }
  1845. return true, 0
  1846. } else {
  1847. switch clueType {
  1848. case 21, 22, 2:
  1849. newAccountType = 2
  1850. case 3:
  1851. newAccountType = 3
  1852. case 4:
  1853. newAccountType = 4
  1854. }
  1855. return false, newAccountType
  1856. }
  1857. }
  1858. // addChangeRecords 添加变更记录
  1859. func (k *KcTransferRequest) addChangeRecords(accountType int64) {
  1860. // 修改线索名称
  1861. if k.SecondaryClueName != k.KcCompanyName {
  1862. updateClueName(k.SecondaryClueId, k.KcCompanyName, k.NowTime, k.SecondaryPersonUid)
  1863. addClueNameChangeRecord(k.ClueType, k.SecondaryClueId, k.KcCompanyName, k.KcCompanyName, k.KcPositionId, k.NowTime)
  1864. }
  1865. //线索移交客成变更
  1866. //线索移交
  1867. updateClueTransfer(k.SecondaryClueId, k.NowTime)
  1868. // 添加移交记录
  1869. description := ""
  1870. switch accountType {
  1871. case 2:
  1872. description = "子账号"
  1873. case 3:
  1874. description = "企业下免费用户"
  1875. case 4:
  1876. description = "关联线索"
  1877. }
  1878. AddClueChange(k.SecondaryClueId, k.KcPositionId, "", "成交客户移交", "", "移交至客户成功组", k.NowTime, common.GetRandom(32), description, "")
  1879. if k.KcOldName != k.KcName {
  1880. // 添加客户成功经理变更记录
  1881. AddClueChange(k.SecondaryClueId, k.KcPositionId, "position_id", "客户成功经理", gconv.String(common.If(k.KcOldName == "", "/", k.KcOldName)), k.KcName, k.NowTime, common.GetRandom(32), "", "")
  1882. }
  1883. }
  1884. // updateClueName 更新线索名称
  1885. func updateClueName(clueId int64, companyName, nowTime, uid string) {
  1886. isGroup, isCommerce := GetCompanyType(companyName, uid)
  1887. //线索名称、移交状态、
  1888. TiDb.Update("dwd_f_crm_clue_info", map[string]interface{}{"id": clueId}, map[string]interface{}{
  1889. "cluename": companyName,
  1890. "updatetime": nowTime,
  1891. "company_nature": isGroup,
  1892. "company_verification": isCommerce,
  1893. })
  1894. }
  1895. // addClueNameChangeRecord 添加线索名称变更记录
  1896. func addClueNameChangeRecord(clueType, clueId int64, oldName, newName string, kcPositionId int64, nowTime string) {
  1897. description := ""
  1898. switch clueType {
  1899. case 21, 22:
  1900. description = "与订单公司名称保持一致"
  1901. case 3:
  1902. description = "与主账号线索名称保持一致"
  1903. case 51:
  1904. description = "主账号公司信息变更"
  1905. case 5:
  1906. description = "订单公司信息变更"
  1907. }
  1908. //新增变更记录
  1909. AddClueChange(clueId, kcPositionId, "cluename", "基本信息变更", oldName, newName, nowTime, common.GetRandom(32), "", description)
  1910. }
  1911. func updateClueTransfer(clueId int64, nowTime string) {
  1912. TiDb.Update("dwd_f_crm_clue_info", map[string]interface{}{"id": clueId}, map[string]interface{}{
  1913. "is_transfer": 1,
  1914. "updatetime": nowTime,
  1915. })
  1916. }
  1917. // 客成新增变更记录
  1918. func AddClueChange(clueId, positionId int64, changeField, changeType, old_value, new_value, nowTime, BCPCID, description, change_reason string) int64 {
  1919. return TiDb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  1920. "clue_id": clueId,
  1921. "position_id": positionId,
  1922. "change_field": changeField,
  1923. "change_type": changeType,
  1924. "old_value": old_value,
  1925. "new_value": new_value,
  1926. "createtime": nowTime,
  1927. "BCPCID": BCPCID,
  1928. "operator_id": -1,
  1929. "SHUOMING": description,
  1930. "change_reason": change_reason,
  1931. })
  1932. }
  1933. // 主账号信息修改
  1934. func (k *KcTransferRequest) KcAccountNumberUpdate(customData, clueData *map[string]interface{}, orderCode string, isNew, isUpdate bool, is_transfer int64) {
  1935. //需要进客成
  1936. if !isNew {
  1937. updateMap := map[string]interface{}{
  1938. "is_transfer": 0,
  1939. "is_renewal_protection": 0,
  1940. "product_access": k.KcProduct,
  1941. "buy_subject": k.KcBuySubject,
  1942. "transfertime": k.NowTime,
  1943. "service_starttime": k.KcStartTime,
  1944. "service_endtime": k.KcEndTime,
  1945. "ent_id": k.KcEntId,
  1946. "company_name": k.KcCompanyName,
  1947. "name": k.KcName,
  1948. "position_id": k.KcPositionId,
  1949. "account_type": 1,
  1950. "primary_id": nil,
  1951. }
  1952. if is_transfer == 1 || k.KcPositionId != gconv.Int64((*customData)["position_id"]) {
  1953. //重新进去
  1954. updateMap["relationship_building_way"] = 1
  1955. updateMap["tasksource"] = "1"
  1956. updateMap["inventory_way"] = 1
  1957. updateMap["training_way"] = 1
  1958. updateMap["is_pre_sales_training"] = 0
  1959. updateMap["service_stage"] = 1
  1960. updateMap["is_task"] = 1
  1961. }
  1962. TiDb.Update("dwd_f_csm_customer_info", map[string]interface{}{"clue_id": k.HostClueId}, updateMap)
  1963. //判断是否需要做线索名称变成
  1964. TiDb.Update("dwd_f_crm_clue_info", map[string]interface{}{"id": k.HostClueId}, map[string]interface{}{"is_transfer": 1, "updatetime": k.NowTime, "cluename": k.KcCompanyName})
  1965. oldClueName := gconv.String((*clueData)["cluename"])
  1966. if oldClueName != k.KcCompanyName && k.KcCompanyName != "" {
  1967. //线索名称修改
  1968. updateClueName(k.HostClueId, k.KcCompanyName, k.NowTime, gconv.String((*clueData)["uid"]))
  1969. addClueNameChangeRecord(5, k.HostClueId, oldClueName, k.KcCompanyName, k.KcPositionId, k.NowTime)
  1970. }
  1971. }
  1972. if k.KcPositionId > 0 {
  1973. // 添加移交记录
  1974. AddClueChange(k.HostClueId, k.KcPositionId, "", "成交客户移交", "", "移交至客户成功组", k.NowTime, common.GetRandom(32), "主账号", "")
  1975. if is_transfer == 1 || k.KcPositionId != gconv.Int64((*customData)["position_id"]) {
  1976. // 添加客户成功经理变更记录
  1977. AddClueChange(k.HostClueId, k.KcPositionId, "position_id", "客户成功经理", gconv.String(common.If(k.KcOldName == "", "/", k.KcOldName)), k.KcName, k.NowTime, common.GetRandom(32), "", "")
  1978. //新增任务车
  1979. AddClueChange(k.HostClueId, k.KcPositionId, "", "加入任务车", "", "未建联", k.NowTime, common.GetRandom(32), "", "")
  1980. }
  1981. if k.KcPositionId != gconv.Int64((*customData)["position_id"]) {
  1982. if k.KcName == db.KeCheng.Admin {
  1983. TiDb.UpdateOrDeleteBySql(`update dwd_f_csm_customer_autodraw_record set count = count + 2 where name = ?`, k.KcName)
  1984. } else {
  1985. TiDb.UpdateOrDeleteBySql(`update dwd_f_csm_customer_autodraw_record set count = count + 1 where name = ?`, k.KcName)
  1986. }
  1987. }
  1988. }
  1989. KcSend(orderCode, k.KcName)
  1990. TiDb.Update("dwd_f_crm_clue_info",
  1991. map[string]interface{}{"id": k.HostClueId}, map[string]interface{}{"is_transfer": 1, "updatetime": k.NowTime})
  1992. k.OtherKcTransfer()
  1993. if isUpdate {
  1994. //需要替换
  1995. customList := TiDb.SelectBySql(`select * from dwd_f_csm_customer_info where primary_id = ? and account_type in (2,3,4)`, k.KcID)
  1996. for _, v := range *customList {
  1997. clueId := gconv.Int64(v["clue_id"])
  1998. clueData := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{
  1999. "id": clueId,
  2000. }, "", "")
  2001. if clueData == nil || len(*clueData) == 0 {
  2002. continue
  2003. }
  2004. cluename := gconv.String((*clueData)["cluename"])
  2005. //查看名称是否需要修改
  2006. if cluename == k.HostClueName {
  2007. continue
  2008. }
  2009. //线索名称修改
  2010. updateClueName(clueId, k.KcCompanyName, k.NowTime, gconv.String((*clueData)["uid"]))
  2011. addClueNameChangeRecord(51, clueId, cluename, k.KcCompanyName, k.KcPositionId, k.NowTime)
  2012. }
  2013. }
  2014. }
  2015. // 企业操作客成处理
  2016. func EntOperateHandle() {
  2017. nowTime := time.Now().Format(date.Date_Full_Layout)
  2018. Mysql.SelectByBath(100, func(l *[]map[string]interface{}) bool {
  2019. for _, v := range *l {
  2020. userData := &map[string]interface{}{}
  2021. entId := gconv.Int64(v["entId"])
  2022. entUserId := gconv.String(v["entUserId"])
  2023. operate := gconv.Int(v["operate"])
  2024. number := gconv.Int64(v["number"])
  2025. number++
  2026. if number == 80 {
  2027. Mysql.Update("ent_operate_record", map[string]interface{}{
  2028. "entUserId": entUserId,
  2029. "isUse": 0,
  2030. }, map[string]interface{}{
  2031. "isUse": 1,
  2032. })
  2033. continue
  2034. }
  2035. if entId != 0 {
  2036. userData = TiDb.FindOne("data_service.user_system", map[string]interface{}{
  2037. "ent_user_id": entUserId,
  2038. "ent_id": entId,
  2039. "status": 1,
  2040. }, "", "")
  2041. } else {
  2042. userData = TiDb.FindOne("data_service.user_system", map[string]interface{}{
  2043. "userid": entUserId,
  2044. "status": 1,
  2045. }, "", "")
  2046. }
  2047. if userData == nil || len(*userData) == 0 {
  2048. log.Println("用户信息查询不到:", entId, entUserId)
  2049. //没有归集需要等一等
  2050. Mysql.Update("ent_operate_record", map[string]interface{}{
  2051. "entUserId": entUserId,
  2052. "isUse": 0,
  2053. }, map[string]interface{}{
  2054. "number": number,
  2055. })
  2056. continue
  2057. }
  2058. uid := gconv.String((*userData)["uid"])
  2059. //客成信息查询
  2060. clueData := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{
  2061. "uid": uid,
  2062. }, "", "")
  2063. if clueData == nil || len(*clueData) == 0 {
  2064. log.Println("企业操作线索不存在:", uid)
  2065. Mysql.Update("ent_operate_record", map[string]interface{}{
  2066. "entUserId": entUserId,
  2067. "isUse": 0,
  2068. }, map[string]interface{}{
  2069. "number": number,
  2070. })
  2071. continue
  2072. }
  2073. clueId := gconv.Int64((*clueData)["id"])
  2074. customData := TiDb.FindOne("dwd_f_csm_customer_info", map[string]interface{}{
  2075. "clue_id": clueId,
  2076. }, "", "")
  2077. isCreate := false
  2078. isTransfer := false
  2079. oldClueType := int64(0)
  2080. minEntry, _ := GetPersonIdentityPower(uid, gconv.Int(common.If(operate > 0, 51, 52)), entId, gconv.String((*clueData)["cluename"]))
  2081. //minEntry, _ := GetPersonIdentityPower(uid, gconv.Int(common.If(operate > 0, 51, 52)), entId, "2222")
  2082. newClueType := int64(0)
  2083. if minEntry != nil {
  2084. newClueType = gconv.Int64(minEntry["newAccountType"])
  2085. }
  2086. if customData != nil && len(*customData) > 0 {
  2087. isCreate = true
  2088. oldClueType = gconv.Int64((*customData)["account_type"])
  2089. if gconv.Int64((*customData)["is_transfer"]) == 0 {
  2090. isTransfer = true
  2091. }
  2092. }
  2093. if !isTransfer && minEntry == nil {
  2094. //之前不在客成 没有权限 不需要处理
  2095. Mysql.Update("ent_operate_record", map[string]interface{}{
  2096. "entUserId": entUserId,
  2097. "isUse": 0,
  2098. }, map[string]interface{}{
  2099. "isUse": 1,
  2100. })
  2101. continue
  2102. }
  2103. custom := gconv.Map(minEntry["customer"])
  2104. k := KcTransferRequest{
  2105. ClueType: newClueType,
  2106. KcEntId: common.If(entId == 0, entUserId, entId),
  2107. UserList: []interface{}{entUserId},
  2108. NowTime: nowTime,
  2109. LogPrefix: fmt.Sprintf("[企业操作客成移交] uid:%s, kcName:%s, company:%s", uid, gconv.String(custom["name"]), gconv.String(custom["company_name"])),
  2110. SecondaryClueId: clueId,
  2111. SecondaryPersonUid: uid,
  2112. SecondaryUserName: gconv.String((*clueData)["name"]),
  2113. SecondaryUserPhone: gconv.String((*clueData)["phone"]),
  2114. SendUserMailMap: nil,
  2115. SecondaryClueName: gconv.String((*clueData)["cluename"]),
  2116. }
  2117. if customData != nil && len(*customData) > 0 {
  2118. k.KcOldName = gconv.String((*customData)["name"])
  2119. //k.SecondaryAccountType = gconv.Int64((*customData)["account_type"])
  2120. }
  2121. if minEntry != nil {
  2122. k.KcName = gconv.String(custom["name"])
  2123. k.KcID = gconv.Int64(custom["id"])
  2124. k.KcBuySubject = gconv.Int64(custom["buy_subject"])
  2125. k.KcCompanyName = gconv.String(custom["company_name"])
  2126. k.KcPositionId = gconv.Int64(custom["position_id"])
  2127. k.KcStartTime = gconv.String(custom["service_starttime"])
  2128. k.KcEndTime = gconv.String(custom["service_endtime"])
  2129. k.KcProduct = gconv.Int64(custom["product_access"])
  2130. }
  2131. switch operate {
  2132. case 2, 1, 3:
  2133. if minEntry == nil {
  2134. Mysql.Update("ent_operate_record", map[string]interface{}{
  2135. "entUserId": entUserId,
  2136. "isUse": 0,
  2137. }, map[string]interface{}{
  2138. "isUse": 1,
  2139. })
  2140. continue
  2141. }
  2142. //查看是否创建
  2143. if isCreate {
  2144. if isTransfer {
  2145. //在客成
  2146. if newClueType < oldClueType {
  2147. //做修改
  2148. k.ClueType = newClueType
  2149. k.handleCustomerData()
  2150. }
  2151. } else {
  2152. //不在客成
  2153. //做新增
  2154. k.ClueType = newClueType
  2155. k.handleCustomerData()
  2156. }
  2157. } else {
  2158. //走新增
  2159. k.ClueType = newClueType
  2160. k.handleCustomerData()
  2161. }
  2162. case -1, -2, -3:
  2163. isPower := false
  2164. if operate == -1 {
  2165. //企业删人
  2166. //看看之前有没有权限
  2167. if Mgo.Count("ent_user", map[string]interface{}{
  2168. "i_member_status": map[string]interface{}{"$gt": 0},
  2169. "i_entid": entId,
  2170. "i_userid": gconv.Int64(entUserId),
  2171. }) > 0 {
  2172. isPower = true
  2173. }
  2174. }
  2175. //删除权限
  2176. if isCreate && isTransfer {
  2177. if newClueType == 0 {
  2178. //查询不到其他权限
  2179. //走退出
  2180. productName := GetProductName(gconv.Int64((*customData)["product_access"]))
  2181. changeReason := ""
  2182. switch operate {
  2183. case -1:
  2184. if isPower {
  2185. changeReason = fmt.Sprintf("%s权限被企业删除", productName)
  2186. } else {
  2187. changeReason = "被企业移出组织架构(集团公司客户),关联线索移交销售"
  2188. }
  2189. case -2:
  2190. productName := GetProductName(gconv.Int64((*customData)["product_access"]))
  2191. changeReason = fmt.Sprintf("%s权限被企业删除", productName)
  2192. case -3:
  2193. productName, _ := GetSubAccountProduct(entUserId)
  2194. changeReason = fmt.Sprintf("%s权限被企业删除", productName)
  2195. }
  2196. kcToOpenSeaUpdate(clueId, gconv.Int64((*customData)["position_id"]), oldClueType, changeReason)
  2197. if isPower {
  2198. //需要重新进课程
  2199. FormatData(map[string]interface{}{
  2200. "belong_to": "0100",
  2201. "source": "0101",
  2202. "uid": uid,
  2203. "phone": "phone",
  2204. }, "powerdDele")
  2205. }
  2206. } else {
  2207. //已创建 在客成可继续处理 其他不需要操作
  2208. if newClueType >= oldClueType {
  2209. //需要更换一个客成信息 或级别下降
  2210. k.ClueType = newClueType
  2211. k.IsDelete = true
  2212. k.handleCustomerData()
  2213. }
  2214. }
  2215. } else {
  2216. Mysql.Update("ent_operate_record", map[string]interface{}{
  2217. "entUserId": entUserId,
  2218. "isUse": 0,
  2219. }, map[string]interface{}{
  2220. "isUse": 1,
  2221. })
  2222. }
  2223. }
  2224. Mysql.Update("ent_operate_record", map[string]interface{}{
  2225. "entUserId": entUserId,
  2226. "isUse": 0,
  2227. }, map[string]interface{}{
  2228. "isUse": 1,
  2229. })
  2230. }
  2231. return true
  2232. }, `SELECT e.*
  2233. FROM ent_operate_record e
  2234. INNER JOIN (
  2235. SELECT entUserId, MAX(createTime) as max_createTime
  2236. FROM ent_operate_record
  2237. WHERE isUse = 0 AND number < 80
  2238. GROUP BY entUserId
  2239. ) latest ON e.entUserId = latest.entUserId AND e.createTime = latest.max_createTime
  2240. WHERE e.isUse = 0 AND e.number < 80
  2241. ORDER BY e.createTime DESC`)
  2242. }
  2243. // 获取商品名称
  2244. func GetProductName(product int64) string {
  2245. productMap := TiDb.FindOne("dwd_d_csm_product_access_code", map[string]interface{}{
  2246. "code": product,
  2247. }, "", "")
  2248. if productMap == nil || len(*productMap) == 0 {
  2249. return ""
  2250. }
  2251. productName := gconv.String((*productMap)["name"])
  2252. return productName
  2253. }
  2254. var level_map = map[int]string{
  2255. 1: "专家版",
  2256. 2: "智慧版",
  2257. 3: "商机版",
  2258. 4: "试用版",
  2259. 5: "自定义",
  2260. 6: "商机版2.0",
  2261. 7: "专家版2.0",
  2262. }
  2263. // 获取子账号商品信息
  2264. func GetSubAccountProduct(userId string) (string, int) {
  2265. rMap, _ := Mgo.FindById("user", userId, `{"s_phone":1,"s_m_phone":1}`)
  2266. if rMap == nil || len(*rMap) == 0 {
  2267. return "", 0
  2268. }
  2269. combo := gconv.Int((*rMap)["i_member_status"])
  2270. if combo < 0 {
  2271. combo = -combo
  2272. }
  2273. return level_map[combo], combo
  2274. }