EmployService.go 14 KB

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