manualOperation.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. package main
  2. import (
  3. "app.yhyue.com/moapp/jybase/common"
  4. "app.yhyue.com/moapp/jybase/mongodb"
  5. "fmt"
  6. "github.com/gin-gonic/gin"
  7. "github.com/gogf/gf/v2/util/gconv"
  8. "log"
  9. "net/http"
  10. "strings"
  11. "time"
  12. )
  13. func setupRouter() *gin.Engine {
  14. r := gin.Default()
  15. // 添加中间件(如认证、日志等)
  16. r.Use(gin.Logger())
  17. r.Use(gin.Recovery())
  18. api := r.Group("/clue")
  19. {
  20. api.POST("/ClueBefore", clueBefore)
  21. api.POST("/GetClueState", getClueState)
  22. }
  23. return r
  24. }
  25. type FetchDeptAdminRequest struct {
  26. PositionId string `json:"position_id"`
  27. SourceDesc string `json:"source_desc"`
  28. Action string `json:"action"`
  29. }
  30. type FetchDeptAdminResponse struct {
  31. Name string `json:"name"`
  32. Wxer string `json:"wxer"`
  33. Phone string `json:"phone"`
  34. }
  35. // 留资以前处理
  36. func clueBefore(c *gin.Context) {
  37. var req FetchDeptAdminRequest
  38. var returnData FetchDeptAdminResponse
  39. if err := c.ShouldBindJSON(&req); err != nil {
  40. log.Println(err)
  41. c.JSON(http.StatusBadRequest, gin.H{"error": "无效的请求参数"})
  42. return
  43. }
  44. log.Println("clueBefore", req)
  45. if req.Action == "" {
  46. req.Action = "saleLeads"
  47. }
  48. kcPositionId, positionId, is_transfer, belong_to := int64(0), int64(0), int64(0), ""
  49. nowTime := time.Now().Format("2006-01-02 15:04:05")
  50. //人员信息查询
  51. uId, userId, source, belong_to, phone, cluename := processUserInfo(req)
  52. if cluename == "" {
  53. cluename = phone
  54. }
  55. clueData := &map[string]interface{}{}
  56. isGroup, isCommerce := 0, 0
  57. if uId != "" {
  58. isGroup, isCommerce, kcPositionId, is_transfer, clueData = processClueInfo(uId, cluename)
  59. if clueData != nil {
  60. positionId = gconv.Int64((*clueData)["position_id"])
  61. }
  62. } else {
  63. if uId == "" || phone == "" {
  64. data := TiDb.FindOne("temporary_assignment", map[string]interface{}{
  65. "userId": userId,
  66. "status": 0,
  67. }, "", "")
  68. if data != nil && len(*data) > 0 {
  69. positionId = gconv.Int64((*data)["positionId"])
  70. returnData.Phone, returnData.Wxer, returnData.Name = GetPersonSubsidiary(positionId)
  71. log.Println(returnData)
  72. c.JSON(http.StatusOK, returnData)
  73. return
  74. }
  75. }
  76. belong_to = GetUserChannel(userId)
  77. }
  78. if source == "0104" || strings.HasPrefix(belong_to, "02") || source == "0102" || source == "0103" || phone == "" || strings.HasPrefix(belong_to, "03") {
  79. c.JSON(http.StatusOK, returnData)
  80. return
  81. }
  82. top_cluetype, sub_cluetype, level, topname, subname := getCodeId(req.Action, req.SourceDesc)
  83. seatNumber, saleName, saleData, pIsOk, isFreeze, noticePositionId := "", "", []map[string]interface{}{}, true, true, int64(0)
  84. if positionId != 0 {
  85. //线索上边已经有人了
  86. personnel := TiDb.FindOne("dwd_f_crm_personnel_management", map[string]interface{}{
  87. "position_id": positionId,
  88. "resign": 0,
  89. "ent_Id": db.EntId,
  90. }, "", "")
  91. if personnel != nil && len(*personnel) > 0 {
  92. seatNumber = gconv.String((*personnel)["seat_number"])
  93. saleName = gconv.String((*personnel)["name"])
  94. saleData = *(TiDb.SelectBySql(`select * from dwd_f_crm_personnel_management where seat_number is not null and seat_number != ""`))
  95. }
  96. } else {
  97. //需要查找一个人
  98. positionId, seatNumber, saleName, saleData, pIsOk, isFreeze, noticePositionId = autoDraw(userId, level, cluename, phone, isGroup, isCommerce)
  99. }
  100. //用户没有创建 //用户创建没有手机号
  101. if uId == "" || phone == "" {
  102. //加一条记录分配
  103. TiDb.Insert("temporary_assignment", map[string]interface{}{
  104. "userId": userId,
  105. "positionId": positionId,
  106. "seatNumber": seatNumber,
  107. "saleName": saleName,
  108. "status": 0,
  109. })
  110. returnData.Phone, returnData.Wxer, returnData.Name = GetPersonSubsidiary(positionId)
  111. log.Println(returnData)
  112. c.JSON(http.StatusOK, returnData)
  113. return
  114. }
  115. log.Println("data -------", positionId, seatNumber, saleName, pIsOk, isFreeze, noticePositionId)
  116. inData := Clue{
  117. Item: req.Action,
  118. UserId: userId,
  119. UId: uId,
  120. TopCluetype: top_cluetype,
  121. SubCluetype: sub_cluetype,
  122. Topname: topname,
  123. Subname: subname,
  124. Cluename: cluename,
  125. SaleName: saleName,
  126. Phone: phone,
  127. SeatNumber: seatNumber,
  128. Level: level,
  129. PositionId: positionId,
  130. Source: "",
  131. SourceCode: "",
  132. BelongTo: belong_to,
  133. IsGroup: isGroup,
  134. IsCommerce: isCommerce,
  135. PIsOk: pIsOk,
  136. Demand: "",
  137. IsFreeze: isFreeze,
  138. }
  139. if positionId > 0 {
  140. //找到分配人了
  141. oks := true
  142. if clueData != nil && len(*clueData) > 0 {
  143. isUpdate := gconv.Int64((*clueData)["is_artificially_modified"])
  144. if isUpdate == 1 {
  145. cluename = ""
  146. }
  147. oks = UpdateClue(*clueData, saleData, inData)
  148. } else { //不存在走新增
  149. oks = SaveClue(inData)
  150. if oks { //新增成功,销售分配次数+1
  151. TiDb.UpdateOrDeleteBySql(`update dwd_f_crm_clue_autodraw_record set count = count + 1 where position_id = ? and clue_level = ?`, positionId, level)
  152. }
  153. }
  154. if is_transfer == 1 {
  155. returnData.Phone, returnData.Wxer, returnData.Name = GetPersonSubsidiary(kcPositionId)
  156. } else {
  157. returnData.Phone, returnData.Wxer, returnData.Name = GetPersonSubsidiary(positionId)
  158. }
  159. } else {
  160. if isFreeze {
  161. //达上限放公海处理
  162. uCount, oks := TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{"uid": uId}, "", ""), true //查当前线索是否已存在
  163. if uCount == nil || len(*uCount) == 0 {
  164. oks = SaveClue0(inData)
  165. log.Println(oks)
  166. } else {
  167. //留资线索更新
  168. if req.Action != "orders" && req.Action != "users" { //新用户和订单之外的替换一下新的留资信息
  169. BCPCID := common.GetRandom(32)
  170. clueId := common.Int64All((*uCount)["id"])
  171. old_cluename := gconv.String((*uCount)["cluename"])
  172. old_top_cluetype := gconv.String((*uCount)["top_cluetype"])
  173. old_sub_cluetype := gconv.String((*uCount)["sub_cluetype"])
  174. label := gconv.Int64((*uCount)["label"])
  175. trailstatusCode := gconv.String((*uCount)["trailstatus"])
  176. clueUpdateData := map[string]interface{}{}
  177. e_label := gconv.String((*uCount)["e_label"])
  178. Ehandle(clueId, uId, userId, cluename, trailstatusCode, e_label)
  179. if old_cluename != cluename && cluename != "" {
  180. clueUpdateData["cluename"] = cluename //新的线索名不为空才替换
  181. TiDb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  182. "clue_id": clueId,
  183. "change_field": "cluename",
  184. "change_type": "基本信息变更",
  185. "old_value": common.If(old_cluename != "", old_cluename, "/"),
  186. "new_value": common.If(cluename != "", cluename, "/"),
  187. "createtime": nowTime,
  188. "BCPCID": BCPCID,
  189. "position_id": noticePositionId,
  190. "operator_id": -1})
  191. }
  192. old_topname := ""
  193. old_subname := ""
  194. if old_top_cluetype != "" {
  195. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": old_top_cluetype}, "", "")
  196. if pcodeData != nil && len(*pcodeData) > 0 {
  197. old_topname = gconv.String((*pcodeData)["name"])
  198. }
  199. }
  200. if old_sub_cluetype != "" {
  201. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": old_sub_cluetype}, "", "")
  202. if pcodeData != nil && len(*pcodeData) > 0 {
  203. old_subname = gconv.String((*pcodeData)["name"])
  204. }
  205. }
  206. if old_top_cluetype != top_cluetype && top_cluetype != "" {
  207. clueUpdateData["top_cluetype"] = top_cluetype //新的线索名不为空才替换
  208. TiDb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  209. "clue_id": clueId,
  210. "change_field": "top_cluetype",
  211. "position_id": noticePositionId,
  212. "change_type": "基本信息变更",
  213. "old_value": common.If(old_topname != "", old_topname, "/"),
  214. "new_value": common.If(topname != "", topname, "/"),
  215. "createtime": nowTime,
  216. "BCPCID": BCPCID,
  217. "operator_id": -1})
  218. }
  219. if old_sub_cluetype != sub_cluetype && sub_cluetype != "" {
  220. clueUpdateData["sub_cluetype"] = sub_cluetype //新的线索名不为空才替换
  221. TiDb.Insert("dwd_f_crm_clue_change_record", map[string]interface{}{
  222. "clue_id": clueId,
  223. "change_field": "sub_cluetype", //111
  224. "position_id": noticePositionId,
  225. "change_type": "基本信息变更",
  226. "old_value": common.If(old_subname != "", old_subname, "/"),
  227. "new_value": common.If(subname != "", subname, "/"),
  228. "createtime": nowTime,
  229. "BCPCID": BCPCID,
  230. "operator_id": -1})
  231. //标签处理
  232. LabelHandel(nil, label, 2, uId, level, trailstatusCode, gconv.String(clueUpdateData["trailstatus"]), 1)
  233. }
  234. clueUpdateData["company_nature"] = isGroup
  235. clueUpdateData["company_verification"] = isCommerce
  236. TiDb.Update("dwd_f_crm_clue_info", map[string]interface{}{"uid": uId}, clueUpdateData)
  237. }
  238. }
  239. //某人已经满了处理
  240. AssFail(noticePositionId, cluename, phone)
  241. //查找人
  242. }
  243. if is_transfer == 1 {
  244. returnData.Phone, returnData.Wxer, returnData.Name = GetPersonSubsidiary(kcPositionId)
  245. } else {
  246. returnData.Phone, returnData.Wxer, returnData.Name = GetPersonSubsidiary(positionId)
  247. }
  248. }
  249. log.Println(returnData)
  250. c.JSON(http.StatusOK, returnData)
  251. return
  252. }
  253. // 来源获取
  254. func getCodeId(item, name string) (pcode, code, level, topname, subname string) {
  255. switch item {
  256. case "user":
  257. pcode = "4"
  258. code = "154"
  259. level = "C"
  260. topname = "新增注册"
  261. subname = "新增注册用户"
  262. default:
  263. codeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"name": name}, "", "")
  264. if codeData != nil && len(*codeData) > 0 {
  265. pcode = common.ObjToString((*codeData)["pcode"])
  266. code = common.ObjToString((*codeData)["code"])
  267. level = common.ObjToString((*codeData)["clue_level"])
  268. subname = name
  269. pcodeData := TiDb.FindOne("dwd_d_crm_cluetype_code", map[string]interface{}{"code": pcode}, "", "")
  270. if pcodeData != nil && len(*pcodeData) > 0 {
  271. topname = common.ObjToString((*pcodeData)["name"])
  272. }
  273. }
  274. }
  275. return
  276. }
  277. // 查找人员附属信息(工作手机号,二维码)
  278. func GetPersonSubsidiary(positionId int64) (string, string, string) {
  279. //手机号获取
  280. phone, qrCode, name := "", "", ""
  281. personnel := TiDb.FindOne("dwd_f_crm_personnel_management", map[string]interface{}{
  282. "position_id": positionId,
  283. "resign": 0,
  284. "ent_Id": db.EntId,
  285. }, "", "")
  286. if personnel != nil && len(*personnel) > 0 {
  287. phone = gconv.String((*personnel)["phone"])
  288. name = gconv.String((*personnel)["name"])
  289. }
  290. //二维码获取
  291. if name != "" {
  292. qrData := Mysql.SelectBySql(`SELECT
  293. b.qr_code
  294. FROM
  295. wx_qy_user a
  296. INNER JOIN wx_qy_code b ON a.user_name like ?
  297. AND a.config_id = b.config_id
  298. AND b.is_del = 0
  299. ORDER BY
  300. b.create_date DESC`, fmt.Sprintf("%%%s%%", name))
  301. if qrData != nil && len(*qrData) > 0 {
  302. qrCode = gconv.String((*qrData)[0]["qr_code"])
  303. }
  304. }
  305. return phone, qrCode, name
  306. }
  307. // 处理用户信息查询
  308. func processUserInfo(in FetchDeptAdminRequest) (uId, userId, source, belong_to, phone, companyName string) {
  309. userMap := &map[string]interface{}{}
  310. if mongodb.IsObjectIdHex(in.PositionId) {
  311. //个人 select * from data_service.user_system where userid=? limit 0,1 [65378f1f060d58518d50fb85]
  312. userMap = TiDb.FindOne("data_service.user_system", map[string]interface{}{
  313. "userid": in.PositionId,
  314. "status": 1,
  315. }, "", "")
  316. } else {
  317. //企业
  318. userMap = TiDb.FindOne("data_service.user_system", map[string]interface{}{
  319. "position_id": in.PositionId,
  320. "status": 1,
  321. }, "", "")
  322. }
  323. if userMap == nil || len(*userMap) == 0 {
  324. //查询用户原始表
  325. userData := &[]map[string]interface{}{}
  326. if mongodb.IsObjectIdHex(in.PositionId) {
  327. userData, _ = Mgo.Find("user", map[string]interface{}{"_id": mongodb.StringTOBsonId(in.PositionId)}, ``, `{"_id":1,"s_phone":1,"s_m_phone":1}`, false, -1, -1)
  328. } else {
  329. sql := `select b.id from base_position a INNER JOIN base_user b on a.id =? and a.user_id=b.id`
  330. baseData := Base.SelectBySql(sql, in.PositionId)
  331. if baseData == nil || len(*baseData) == 0 {
  332. return
  333. }
  334. userData, _ = Mgo.Find("user", map[string]interface{}{"base_user_id": gconv.Int64((*baseData)[0]["id"])}, ``, `{"_id":1,"s_phone":1,"s_m_phone":1}`, false, -1, -1)
  335. }
  336. if userData == nil || len(*userData) == 0 {
  337. return
  338. }
  339. userId = mongodb.BsonIdToSId((*userData)[0]["_id"])
  340. phone = gconv.String((*userData)[0]["s_phone"])
  341. if phone == "" {
  342. phone = gconv.String((*userData)[0]["s_m_phone"])
  343. }
  344. return
  345. } else {
  346. uId = gconv.String((*userMap)["uid"])
  347. userId = gconv.String((*userMap)["userid"])
  348. userBaseData := TiDb.FindOne("dwd_f_userbase_baseinfo", map[string]interface{}{
  349. "uid": uId,
  350. "status": 1,
  351. }, "", "")
  352. if userBaseData != nil && len(*userBaseData) > 0 {
  353. source = gconv.String((*userBaseData)["source"])
  354. belong_to = gconv.String((*userBaseData)["belong_to"])
  355. phone = gconv.String((*userBaseData)["phone"])
  356. companyName = gconv.String((*userBaseData)["company_name"])
  357. }
  358. }
  359. return
  360. }
  361. // 处理线索信息
  362. func processClueInfo(uId, cluename string) (isGroup, isCommerce int, kcPositionId, is_transfer int64, clueData *map[string]interface{}) {
  363. isGroup, isCommerce = GetCompanyType(cluename, uId)
  364. //查询一下是否在客成
  365. clueData = TiDb.FindOne("dwd_f_crm_clue_info", map[string]interface{}{
  366. "uid": uId,
  367. }, "", "")
  368. if clueData != nil && len(*clueData) > 0 {
  369. clueId := gconv.Int64((*clueData)["id"])
  370. is_transfer = gconv.Int64((*clueData)["is_transfer"])
  371. if is_transfer == 1 {
  372. //在客成
  373. customData := TiDb.FindOne("dwd_f_csm_customer_info", map[string]interface{}{
  374. "clue_id": clueId,
  375. }, "", "")
  376. if customData != nil && len(*customData) > 0 {
  377. kcPositionId = gconv.Int64((*customData)["position_id"])
  378. }
  379. }
  380. }
  381. return
  382. }
  383. // 线索状态查询
  384. func getClueState(c *gin.Context) {
  385. // 1. 参数绑定和验证
  386. positionId := int64(0)
  387. var req FetchDeptAdminRequest
  388. response := FetchDeptAdminResponse{}
  389. if err := c.ShouldBindJSON(&req); err != nil {
  390. log.Println(err)
  391. c.JSON(http.StatusBadRequest, gin.H{"error": "无效的请求参数"})
  392. return
  393. }
  394. log.Println("getClueState", req)
  395. // 2. 处理用户信息
  396. uId, userId, source, belong_to, _, _ := processUserInfo(req)
  397. if source == "0104" || strings.HasPrefix(belong_to, "02") || source == "0102" || source == "0103" || strings.HasPrefix(belong_to, "03") {
  398. c.JSON(http.StatusOK, response)
  399. return
  400. }
  401. if uId == "" {
  402. data := TiDb.FindOne("temporary_assignment", map[string]interface{}{
  403. "userId": userId,
  404. "status": 0,
  405. }, "", "")
  406. if data != nil && len(*data) > 0 {
  407. positionId = gconv.Int64((*data)["positionId"])
  408. response.Phone, response.Wxer, response.Name = GetPersonSubsidiary(positionId)
  409. log.Println(response)
  410. c.JSON(http.StatusOK, response)
  411. return
  412. }
  413. }
  414. // 3. 处理线索信息
  415. _, _, kcPositionId, isTransfer, clueData := processClueInfo(uId, "")
  416. // 4. 根据是否转移获取不同数据
  417. if clueData != nil {
  418. positionId = gconv.Int64((*clueData)["position_id"])
  419. } else {
  420. data := TiDb.FindOne("temporary_assignment", map[string]interface{}{
  421. "userId": userId,
  422. "status": 0,
  423. }, "", "")
  424. if data != nil {
  425. positionId = gconv.Int64((*data)["positionId"])
  426. }
  427. }
  428. if isTransfer == 1 {
  429. response.Phone, response.Wxer, response.Name = GetPersonSubsidiary(kcPositionId)
  430. } else {
  431. response.Phone, response.Wxer, response.Name = GetPersonSubsidiary(positionId)
  432. }
  433. // 5. 返回响应
  434. log.Println(response)
  435. c.JSON(http.StatusOK, response)
  436. }