employService.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. package service
  2. import (
  3. "app.yhyue.com/moapp/jybase/common"
  4. "app.yhyue.com/moapp/jybase/date"
  5. elastic "app.yhyue.com/moapp/jybase/es"
  6. "app.yhyue.com/moapp/jypkg/ent/util"
  7. "app.yhyue.com/moapp/jypkg/public"
  8. MC "bp.jydev.jianyu360.cn/CRM/application/api/common"
  9. "bp.jydev.jianyu360.cn/CRM/application/api/internal/types"
  10. "bp.jydev.jianyu360.cn/CRM/application/entity"
  11. "database/sql"
  12. "fmt"
  13. "github.com/RoaringBitmap/roaring"
  14. "go.mongodb.org/mongo-driver/bson"
  15. "log"
  16. "regexp"
  17. "strconv"
  18. "strings"
  19. "time"
  20. )
  21. const (
  22. BuyerIndex = "buyer" // 采购单位index
  23. BuyerType = "buyer"
  24. )
  25. type EmPloyService struct{}
  26. // InfoEmployinfo 收录情况查询
  27. func (e *EmPloyService) InfoEmployinfo(in *types.InfoEmployinfoReq) []map[string]interface{} {
  28. var data []map[string]interface{}
  29. for _, v := range strings.Split(in.IdArr, ",") {
  30. table, findKey, employKey, source := EmployKeyFormat(in.EmployType)
  31. id := ""
  32. id = IdFormat(v, in.EmployType)
  33. if id == "" {
  34. log.Println(v, in.EmployType, "该信息查询不到数据")
  35. break
  36. }
  37. valueMap := map[string]interface{}{
  38. "id": v,
  39. }
  40. //有收录情况
  41. //summaryMap := SummaryFormat(in.PositionId)
  42. //vint = mongodb.StringTOBsonId(id).Timestamp().Unix()
  43. //vint = extractNumbers(id)
  44. //valueMap["isEmploy"] = summaryMap[in.EmployType].Contains(uint32(vint))
  45. employData := MC.CrmMysql.FindOne(table, map[string]interface{}{
  46. employKey: id,
  47. "position_id": in.PositionId,
  48. "source": source,
  49. }, "is_ignore,status,id", "")
  50. employId := int64(0)
  51. if employData != nil && len(*employData) > 0 {
  52. valueMap["isIgnore"] = common.If(common.Int64All((*employData)["is_ignore"]) == 1, true, false)
  53. valueMap["isEmploy"] = common.If(common.Int64All((*employData)["status"]) == 1, true, false)
  54. employId = common.Int64All((*employData)["id"])
  55. valueMap["employId"] = employId
  56. } else {
  57. valueMap["isIgnore"] = false
  58. valueMap["isEmploy"] = false
  59. }
  60. if len(strings.Split(in.IdArr, ",")) == 1 && employId > 0 {
  61. //列表查询
  62. //是否忽略处理
  63. //客户数量
  64. customCount := MC.CrmMysql.Count(entity.CUSTOM, map[string]interface{}{
  65. findKey: employId,
  66. "position_id": in.PositionId,
  67. })
  68. valueMap["customCount"] = customCount
  69. if in.EmployType == 1 || in.EmployType == 4 {
  70. //销售线索数量
  71. clueCount := MC.CrmMysql.Count(entity.SALE_CLUE, map[string]interface{}{
  72. "employ_info_id": employId,
  73. "position_id": in.PositionId,
  74. })
  75. valueMap["clueCount"] = clueCount
  76. //销售机会数量
  77. chanceCount := MC.CrmMysql.Count(entity.SALE_CHANCE, map[string]interface{}{
  78. "employ_info_id": id,
  79. "position_id": in.PositionId,
  80. })
  81. valueMap["chanceCount"] = chanceCount
  82. }
  83. } else {
  84. valueMap["chanceCount"] = 0
  85. valueMap["clueCount"] = 0
  86. valueMap["isIgnore"] = false
  87. valueMap["customCount"] = 0
  88. }
  89. data = append(data, valueMap)
  90. }
  91. return data
  92. }
  93. // EmployOperate 收录操作
  94. func (e *EmPloyService) EmployOperate(in *types.EmployOperateReq) bool {
  95. //收录汇总表
  96. table, _, employKey, source := EmployKeyFormat(in.EmployType)
  97. //summaryMap := SummaryFormat(in.PositionId)
  98. return MC.CrmMysql.ExecTx("收录操作", func(tx *sql.Tx) bool {
  99. for _, v1 := range strings.Split(in.IdArr, ",") {
  100. //id转中文
  101. id := ""
  102. findMap := map[string]interface{}{}
  103. findMap["position_id"] = in.PositionId
  104. id = IdFormat(v1, in.EmployType)
  105. findMap[employKey] = id
  106. if id == "" {
  107. log.Println(v1, in.EmployType, "该信息查询不到数据")
  108. break
  109. }
  110. if in.IsEmploy {
  111. if MC.CrmMysql.Count(table, findMap) > 0 {
  112. MC.CrmMysql.UpdateByTx(tx, table, findMap, map[string]interface{}{
  113. "status": 1,
  114. })
  115. } else {
  116. //收录新增
  117. data := map[string]interface{}{}
  118. if in.EmployType == 1 || in.EmployType == 4 {
  119. data = InfoFind(id, in.EmployType)
  120. data["employ_way"] = 1
  121. data["jybx_url"] = "/article/content/" + v1 + ".html"
  122. } else if in.EmployType == 2 {
  123. data = CustomFind(id, in.EmployType)
  124. data["jybx_url"] = "/swordfish/page_big_pc/svip/ent_ser_portrait/" + v1
  125. } else if in.EmployType == 3 {
  126. data = CustomFind(id, in.EmployType)
  127. data["jybx_url"] = "/swordfish/page_big_pc/unit_portrayal/" + v1
  128. }
  129. data["position_id"] = in.PositionId
  130. data["ent_id"] = in.EntId
  131. data["source"] = source
  132. ok := MC.CrmMysql.InsertByTx(tx, table, data)
  133. if ok <= 0 {
  134. log.Println(v1, id, in.EmployType, "收录失败")
  135. break
  136. }
  137. }
  138. } else {
  139. //取消收录
  140. ok := MC.CrmMysql.UpdateByTx(tx, table, findMap, map[string]interface{}{
  141. "status": -1,
  142. })
  143. if !ok {
  144. log.Println(v1, id, in.EmployType, "取消收录失败")
  145. }
  146. }
  147. /*//收录汇总表处理
  148. vint := extractNumbers(id)
  149. if in.IsEmploy {
  150. summaryMap[in.EmployType].Add(uint32(vint))
  151. } else {
  152. summaryMap[in.EmployType].Remove(uint32(vint))
  153. }*/
  154. //fool = true
  155. }
  156. /*if fool {
  157. return SummarySave(tx, in.PositionId, summaryMap)
  158. } else {
  159. return false
  160. }*/
  161. return true
  162. })
  163. }
  164. // CustomFind 企业信息查询
  165. func CustomFind(id string, employType int64) map[string]interface{} {
  166. data := map[string]interface{}{}
  167. //company_id 企业id name户名称 address 地址 industry 行业
  168. if employType == 2 {
  169. //企业详情
  170. entinfo, _ := MC.MgoEnt.FindOneByField("qyxy_std", map[string]interface{}{"_id": id}, map[string]interface{}{
  171. "company_address": 1, //注册地
  172. "company_name": 1,
  173. })
  174. if entinfo != nil && len(*entinfo) > 0 {
  175. data["name"] = (*entinfo)["company_name"]
  176. data["address"] = (*entinfo)["company_address"]
  177. data["company_id"] = id
  178. }
  179. } else {
  180. //采购单位详情
  181. rs := elastic.Get(BuyerIndex, BuyerType, fmt.Sprintf(`{"query":{"bool":{"must":[{"terms":{"_id":["%s"]}}]}},"size":1,"_source":["buyer_name","city"]}`, id))
  182. if rs != nil && len(*rs) > 0 {
  183. data["name"] = (*rs)[0]["buyer_name"]
  184. data["address"] = (*rs)[0]["city"]
  185. data["company_id"] = id
  186. }
  187. }
  188. data["status"] = 1
  189. data["create_time"] = time.Now().Format(date.Date_Full_Layout)
  190. return data
  191. }
  192. // InfoFind 标讯信息查询
  193. func InfoFind(id string, employType int64) map[string]interface{} {
  194. data := map[string]interface{}{}
  195. //source_id 信息id、项目id- title 标题-area 省 -city 市 -subtype 信息类型二级分类
  196. //buyerclass 采购单位行业 -budget 预算 -bidamount 中标金额 buyer采购单位 annex有无附件 publishtime发布时间 projectname 项目时间
  197. //ownerclass 业主类型(拟在建搜索) expurasing_time 预计采购时间 jybx_url 标讯详情页
  198. if employType == 1 {
  199. //标讯信息
  200. obj := map[string]interface{}{}
  201. brobj, ok := MC.Mgo.Find("bidding_rec", bson.M{"s_id": id}, `{"l_recoverydate":-1}`, public.MgoBiddingFields, false, 0, 1)
  202. if ok && (*brobj) != nil && len(*brobj) == 1 && (*brobj)[0] != nil {
  203. obj = (*brobj)[0]
  204. } else {
  205. aobj, ok := MC.MgoBidding.FindById("bidding", id, public.MgoBiddingFields)
  206. if ok && (aobj == nil || *aobj == nil || len(*aobj) == 0) {
  207. aobj, ok = MC.MgoBidding.FindById("bidding_back", id, public.MgoBiddingFields)
  208. }
  209. obj = *aobj
  210. }
  211. if ok && obj != nil && len(obj) > 0 {
  212. toptype := common.InterfaceToStr(obj["toptype"])
  213. subtype := common.InterfaceToStr(obj["subtype"])
  214. data["title"] = common.ObjToString(obj["title"])
  215. data["city"] = obj["city"]
  216. data["area"] = obj["area"]
  217. data["subtype"] = obj["subtype"]
  218. data["buyerclass"] = obj["buyerclass"]
  219. data["budget"] = obj["budget"]
  220. data["bidamount"] = obj["bidamount"]
  221. data["annex"] = 0
  222. data["buyer"] = obj["buyer"]
  223. data["winner"] = obj["s_winner"]
  224. //类型处理
  225. /*if subtype == "拟建" {
  226. data["type"] = 1
  227. data["type"] = 2
  228. } else */
  229. if toptype == "采购意向" || toptype == "预告" || toptype == "招标" {
  230. data["type"] = 2
  231. } else {
  232. if subtype == "废标" || subtype == "流标" || subtype == "其它" {
  233. data["type"] = 2
  234. } else if subtype == "成交" || subtype == "中标" || subtype == "合同" || subtype == "验收" || subtype == "违规" {
  235. data["type"] = 3
  236. } else {
  237. data["type"] = 1
  238. }
  239. }
  240. if common.InterfaceToStr(obj["subtype"]) == "拟建" {
  241. } else {
  242. }
  243. //data["type"] = in.SourceType
  244. if obj["projectinfo"] != nil {
  245. projectinfo := common.ObjToMap(obj["projectinfo"])
  246. if (*projectinfo)["attachments"] != nil {
  247. data["annex"] = 1
  248. }
  249. }
  250. data["publishtime"] = time.Unix(common.Int64All(obj["publishtime"]), 0).Format(date.Date_Full_Layout)
  251. data["show_time"] = time.Unix(common.Int64All(obj["publishtime"]), 0).Format(date.Date_Full_Layout)
  252. data["projectname"] = obj["projectname"]
  253. procurementlist, _ := obj["procurementlist"].([]interface{})
  254. for _, vs := range procurementlist { //1.采购意向清单数据集打码处理
  255. vsMap, _ := vs.(map[string]interface{})
  256. if vsMap["expurasingtime"] != nil {
  257. data["expurasing_time"] = vsMap["expurasingtime"]
  258. break
  259. }
  260. }
  261. }
  262. }
  263. data["status"] = 1
  264. data["employ_way"] = 1
  265. data["source_id"] = id
  266. data["create_time"] = time.Now().Format(date.Date_Full_Layout)
  267. return data
  268. }
  269. // GetBuyerIdByName 通过采购单位名称获取id
  270. func GetBuyerIdByName(buyerName string) (buyerId string) {
  271. r := elastic.Get(BuyerIndex, BuyerType, fmt.Sprintf(`{"query":{"bool":{"must":[{"term":{"buyer_name":"%s"}}]}},"size":1,"_source":["city","id"]}`, buyerName))
  272. if r == nil || len(*r) == 0 {
  273. return
  274. }
  275. buyerId, _ = (*r)[0]["_id"].(string)
  276. return
  277. }
  278. // IdFormat id解密
  279. func IdFormat(encryptionId string, employType int64) string {
  280. decryptId := ""
  281. switch employType {
  282. case 1, 2:
  283. decryptId = util.DecodeId(encryptionId)
  284. case 3:
  285. if len(encryptionId) > 0 && len([]rune(encryptionId)) == len(encryptionId) {
  286. //此数据是id
  287. //获取中文名字
  288. decryptId = util.DecodeId(encryptionId)
  289. } else {
  290. //次数据传的名字
  291. decryptId = GetBuyerIdByName(encryptionId)
  292. }
  293. }
  294. return decryptId
  295. }
  296. // SummaryFormat 汇总表处理
  297. func SummaryFormat(positionId int64) map[int64]*roaring.Bitmap {
  298. var byte1 []byte
  299. var byte2 []byte
  300. var byte3 []byte
  301. var byte4 []byte
  302. err := MC.CrmMysql.DB.QueryRow("select search_tencent, search_buyer, search_ent, search_nzj from employ_summary where position_id=?", positionId).Scan(&byte1, &byte3, &byte2, &byte4)
  303. if err != nil {
  304. return nil
  305. }
  306. rb1 := roaring.NewBitmap()
  307. rb2 := roaring.NewBitmap()
  308. rb3 := roaring.NewBitmap()
  309. rb4 := roaring.NewBitmap()
  310. data := map[int64]*roaring.Bitmap{}
  311. if byte1 != nil && len(byte1) > 0 {
  312. rb1.UnmarshalBinary(byte1)
  313. }
  314. if byte2 != nil && len(byte2) > 0 {
  315. rb2.UnmarshalBinary(byte2)
  316. }
  317. if byte3 != nil && len(byte3) > 0 {
  318. rb3.UnmarshalBinary(byte3)
  319. }
  320. if byte4 != nil && len(byte4) > 0 {
  321. rb4.UnmarshalBinary(byte4)
  322. }
  323. data[1] = rb1
  324. data[2] = rb2
  325. data[3] = rb3
  326. data[4] = rb4
  327. return data
  328. }
  329. // SummarySave 汇总表保存
  330. func SummarySave(tx *sql.Tx, positionId int64, data map[int64]*roaring.Bitmap) bool {
  331. employSummaryData := MC.CrmMysql.FindOne(entity.EMPLOY_SUMMARY, map[string]interface{}{
  332. "position_id": positionId,
  333. }, "", "")
  334. if employSummaryData != nil && len(*employSummaryData) > 0 {
  335. //修改
  336. updateData := map[string]interface{}{}
  337. updateData["search_tencent"], _ = data[1].ToBytes()
  338. updateData["search_buyer"], _ = data[3].ToBytes()
  339. updateData["search_ent"], _ = data[2].ToBytes()
  340. updateData["search_nzj"], _ = data[4].ToBytes()
  341. ok := MC.CrmMysql.UpdateByTx(tx, entity.EMPLOY_SUMMARY, map[string]interface{}{
  342. "position_id": positionId,
  343. }, updateData)
  344. return ok
  345. } else {
  346. //新增
  347. insertData := map[string]interface{}{}
  348. insertData["position_id"] = positionId
  349. insertData["search_tencent"], _ = data[1].ToBytes()
  350. insertData["search_buyer"], _ = data[3].ToBytes()
  351. insertData["search_ent"], _ = data[2].ToBytes()
  352. insertData["search_nzj"], _ = data[4].ToBytes()
  353. ok := MC.CrmMysql.InsertByTx(tx, entity.EMPLOY_SUMMARY, insertData)
  354. return ok > 0
  355. }
  356. }
  357. // EmployKeyFormat 根据收录类型 字段处理 table,findKey,employKey,source
  358. func EmployKeyFormat(employType int64) (string, string, string, int64) {
  359. table := ""
  360. employKey := "company_id"
  361. findKey := "employ_custom_id"
  362. source := int64(0)
  363. switch employType {
  364. case 1:
  365. table = entity.EMPLOY_INFO
  366. employKey = "source_id"
  367. findKey = "employ_info_id"
  368. source = 1
  369. case 2:
  370. table = entity.EMPLOY_CUSTOM
  371. source = 1
  372. case 3:
  373. table = entity.EMPLOY_CUSTOM
  374. source = 2
  375. case 4:
  376. table = entity.EMPLOY_INFO
  377. source = 2
  378. employKey = "source_id"
  379. findKey = "employ_info_id"
  380. }
  381. return table, findKey, employKey, source
  382. }
  383. // IgnoreOperate 忽略操作
  384. func (e *EmPloyService) IgnoreOperate(in *types.IgnoreOperateReq) {
  385. //
  386. table := ""
  387. switch in.EmployType {
  388. case 1, 4:
  389. table = entity.EMPLOY_INFO
  390. case 2, 3:
  391. table = entity.EMPLOY_CUSTOM
  392. }
  393. for _, v := range strings.Split(in.IdArr, ",") {
  394. id := IdFormat(v, in.EmployType)
  395. if id == "" {
  396. log.Println(v, id, in.EmployType, "忽略处理,id解析失败")
  397. break
  398. }
  399. findMap := map[string]interface{}{
  400. "position_id": in.PositionId,
  401. }
  402. if in.EmployType == 3 || in.EmployType == 2 {
  403. findMap["company_id"] = id
  404. } else {
  405. findMap["source_id"] = id
  406. }
  407. if MC.CrmMysql.Count(table, findMap) == 0 {
  408. log.Println(v, id, in.EmployType, "忽略处理,id所对应数据不存在")
  409. break
  410. }
  411. if in.IsIgnore {
  412. MC.CrmMysql.Update(table, findMap, map[string]interface{}{
  413. "is_ignore": 1,
  414. "is_handle": 1,
  415. })
  416. } else {
  417. MC.CrmMysql.Update(table, findMap, map[string]interface{}{
  418. "is_ignore": 0,
  419. "is_handle": 1,
  420. })
  421. }
  422. }
  423. }
  424. type PersonSmmary struct {
  425. EntUserId int64
  426. Summary map[int64]*roaring.Bitmap
  427. }
  428. // DistributePerson 分发操作
  429. func (e *EmPloyService) DistributePerson(in *types.EmployDistributeReq) bool {
  430. return MC.CrmMysql.ExecTx("收录操作", func(tx *sql.Tx) bool {
  431. personMap := map[int64]PersonSmmary{}
  432. //汇总表查询
  433. for _, person := range in.Person {
  434. personMap[person.PositionId] = PersonSmmary{
  435. EntUserId: person.EntUserId,
  436. }
  437. }
  438. //分发数据处理
  439. infoMap := map[string]map[string]interface{}{}
  440. onlyMap := map[string]interface{}{}
  441. for _, v := range strings.Split(in.EmployIdArr, ",") {
  442. if onlyMap[v] == nil {
  443. //查询信息
  444. infoDataList := MC.CrmMysql.SelectBySqlByTx(tx, "SELECT * FROM employ_info WHERE id=?", v)
  445. if infoDataList != nil && len(*infoDataList) > 0 {
  446. source_id := common.InterfaceToStr((*infoDataList)[0]["source_id"])
  447. if onlyMap[source_id] == nil {
  448. (*infoDataList)[0]["dis_id"] = v
  449. (*infoDataList)[0]["is_handle"] = 0
  450. (*infoDataList)[0]["is_ignore"] = 0
  451. (*infoDataList)[0]["is_dis"] = 0
  452. (*infoDataList)[0]["is_create_clue"] = 0
  453. (*infoDataList)[0]["is_create_chance"] = 0
  454. (*infoDataList)[0]["is_create_custom"] = 0
  455. (*infoDataList)[0]["create_time"] = time.Now().Format(date.Date_Full_Layout)
  456. delete((*infoDataList)[0], "id")
  457. if common.IntAll((*infoDataList)[0]["is_dis"]) != 1 {
  458. MC.CrmMysql.UpdateByTx(tx, entity.EMPLOY_INFO, map[string]interface{}{
  459. "id": v,
  460. }, map[string]interface{}{
  461. "is_dis": 1,
  462. })
  463. }
  464. infoMap[source_id] = (*infoDataList)[0]
  465. onlyMap[source_id] = v
  466. } else {
  467. log.Println(v, "查询不到改收录信息")
  468. continue
  469. }
  470. }
  471. }
  472. }
  473. for positionId, personSmmary := range personMap {
  474. for _, v := range infoMap {
  475. //查询时候收录过
  476. findMap := map[string]interface{}{
  477. "position_id": positionId,
  478. "source_id": v["source_id"],
  479. }
  480. if MC.CrmMysql.Count(entity.EMPLOY_INFO, findMap) == 0 {
  481. //新增
  482. v["ent_user_id"] = personSmmary.EntUserId
  483. v["position_id"] = positionId
  484. MC.CrmMysql.InsertByTx(tx, entity.EMPLOY_INFO, v)
  485. }
  486. }
  487. }
  488. return true
  489. })
  490. }
  491. // 提取字符串中的数字
  492. func ExtractNumbers(str string) int64 {
  493. re := regexp.MustCompile(`\d+`)
  494. matches := re.FindAllString(str, -1)
  495. numbers := make([]int, len(matches))
  496. for i, match := range matches {
  497. number, err := strconv.Atoi(match)
  498. if err == nil {
  499. numbers[i] = number
  500. }
  501. }
  502. result := 0
  503. for _, number := range numbers {
  504. result = result*10 + number
  505. }
  506. return int64(result)
  507. }