employService.go 15 KB

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