CoopHistoryService.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. package service
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "strings"
  7. "time"
  8. "app.yhyue.com/moapp/jybase/common"
  9. "app.yhyue.com/moapp/jybase/encrypt"
  10. "app.yhyue.com/moapp/jybase/redis"
  11. T "bp.jydev.jianyu360.cn/CRM/networkManage/api/common"
  12. "bp.jydev.jianyu360.cn/CRM/networkManage/api/internal/types"
  13. "github.com/ClickHouse/clickhouse-go/v2/lib/driver"
  14. "github.com/shopspring/decimal"
  15. "github.com/zeromicro/go-zero/core/logx"
  16. )
  17. const (
  18. NetworkManageCoopHistory = "networkManage_coopHistory_%d_%s"
  19. )
  20. var (
  21. INDEX_1 = "transaction_info_all"
  22. sql_2_0 = `SELECT buyer_id FROM information.transaction_info_all prewhere project_id = ?`
  23. sql_2_2 = `select id as buyer_id from ent_info prewhere company_name=? order by id desc limit 1`
  24. sql_2_1 = `SELECT project_id, project_name, zbtime FROM information.transaction_info_all prewhere buyer_id = ? AND has(winner, ?) ORDER BY zbtime DESC`
  25. sql_2_1_1 = `SELECT project_id, project_name, zbtime FROM information.transaction_info_all prewhere buyer_id = ? AND agency = ? ORDER BY zbtime DESC`
  26. )
  27. type ResultData struct {
  28. SourceType string `json:"SourceType"`
  29. EntName string `json:"EntName"`
  30. EntId string `json:"EntId"`
  31. EntPerson string `json:"EntPerson"`
  32. Middleman string `json:"Middleman"`
  33. ProjectNum int `json:"ProjectNum"`
  34. TotalAmount float64 `json:"TotalAmount"`
  35. RecentTime int64 `json:"RecentTime"`
  36. NearlyYears bool `json:"NearlyYears"`
  37. SupEnt string `json:"SupEnt"` // 上级
  38. NextEnt string `json:"NextEnt"` // 下级
  39. Relationship string `json:"Relationship"` // 关系
  40. BuyerId string `json:"BuyerId"`
  41. IsIgnore bool `json:"isIgnore"`
  42. }
  43. type ResultDatas []*ResultData
  44. func (n *ResultDatas) Len() int {
  45. return len(*n)
  46. }
  47. func (n *ResultDatas) Less(i, j int) bool {
  48. if (*n)[i].RecentTime == (*n)[j].RecentTime {
  49. return (*n)[i].EntName < (*n)[j].EntName
  50. }
  51. return (*n)[i].RecentTime > (*n)[j].RecentTime
  52. }
  53. func (n *ResultDatas) Swap(i, j int) {
  54. (*n)[i], (*n)[j] = (*n)[j], (*n)[i]
  55. }
  56. type ProjectTmp struct {
  57. BuyerId string `ch:"buyer_id"`
  58. }
  59. type Cooperate struct {
  60. Near bool
  61. ZbTime int64
  62. }
  63. type AggStruct struct {
  64. Id string `ch:"id"`
  65. Name string `ch:"name"`
  66. Sum uint64 `ch:"sum"`
  67. ProjectMoney decimal.Decimal `ch:"project_money"`
  68. Zbtime int64 `ch:"zbtime"`
  69. }
  70. type PrListRes struct {
  71. Result []*ResultData
  72. Size_1 int64
  73. Size_2 int64
  74. Size_3 int64
  75. Size_4 int64
  76. }
  77. func GetPrList(req *types.CoopHistoryReq) *PrListRes {
  78. redisFlag := ""
  79. if req.Buyer != "" {
  80. redisFlag = req.Buyer
  81. } else if req.Pid != "" {
  82. redisFlag = req.Pid
  83. }
  84. redisKey := fmt.Sprintf(NetworkManageCoopHistory, req.PositionId, req.ChannelType+"_"+redisFlag)
  85. prListRes := &PrListRes{}
  86. if rBt, rErr := redis.GetNewBytes("newother", redisKey); rErr == nil && rBt != nil {
  87. json.Unmarshal(*rBt, &prListRes)
  88. return prListRes
  89. }
  90. pTmp := ProjectTmp{}
  91. var err error
  92. if req.Buyer != "" {
  93. err = T.ClickhouseConn.QueryRow(context.TODO(), sql_2_2, req.Buyer).ScanStruct(&pTmp)
  94. } else if req.Pid != "" {
  95. err = T.ClickhouseConn.QueryRow(context.TODO(), sql_2_0, req.Pid).ScanStruct(&pTmp)
  96. } else {
  97. return prListRes
  98. }
  99. if err != nil || pTmp.BuyerId == "" {
  100. return prListRes
  101. }
  102. // firstparty:甲方 supplier:供应商 adiffb:同甲异业 middleman:中间人 agency:招标代理机构 sup_sub: 上下级
  103. // 1、同甲异业数据/ 3、招标代理机构渠道
  104. // 中间人可介绍业主
  105. var r3 []map[string]interface{}
  106. FindMiddleman(req.PositionId, []string{pTmp.BuyerId}, r3)
  107. prListRes.Size_4 = int64(len(r3))
  108. if req.ChannelType == "0" || req.ChannelType == "4" {
  109. for _, m := range r3 {
  110. tmp := ResultData{
  111. SourceType: "middleman",
  112. EntName: common.ObjToString(m["b_name"]),
  113. EntId: common.ObjToString(m["b_id"]),
  114. Relationship: "业主的关系人",
  115. BuyerId: pTmp.BuyerId,
  116. }
  117. prListRes.Result = append(prListRes.Result, &tmp)
  118. }
  119. }
  120. // 关联单位
  121. var r4 []map[string]interface{}
  122. Findfirstparty(req.PositionId, []string{pTmp.BuyerId}, r4)
  123. prListRes.Size_2 = int64(len(r4))
  124. if req.ChannelType == "0" || req.ChannelType == "2" {
  125. for _, m := range r4 {
  126. tmp := ResultData{
  127. SourceType: "sup_sub",
  128. EntName: common.ObjToString(m["b_name"]),
  129. EntId: common.ObjToString(m["b_id"]),
  130. Relationship: common.ObjToString(m["relationship"]),
  131. BuyerId: pTmp.BuyerId,
  132. }
  133. prListRes.Result = append(prListRes.Result, &tmp)
  134. }
  135. }
  136. scopeClass := FindBusiness(req.EntId, req.EntUserId)
  137. r1 := GetWinnerData(scopeClass, pTmp.BuyerId)
  138. prListRes.Size_1 = int64(len(r1))
  139. if req.ChannelType == "0" || req.ChannelType == "1" {
  140. for _, m := range r1 {
  141. tmp := ResultData{
  142. SourceType: "adiffb",
  143. EntName: m.Name,
  144. ProjectNum: int(m.Sum),
  145. BuyerId: pTmp.BuyerId,
  146. RecentTime: m.Zbtime,
  147. }
  148. tmp.TotalAmount, _ = m.ProjectMoney.Float64()
  149. if time.Now().AddDate(-3, 0, 0).Unix() <= tmp.RecentTime {
  150. tmp.NearlyYears = true
  151. }
  152. prListRes.Result = append(prListRes.Result, &tmp)
  153. }
  154. }
  155. r2 := GetAgencyData(pTmp.BuyerId)
  156. prListRes.Size_3 = int64(len(r2))
  157. if req.ChannelType == "0" || req.ChannelType == "3" {
  158. for _, m := range r2 {
  159. tmp := ResultData{
  160. SourceType: "agency",
  161. EntName: m.Name,
  162. ProjectNum: int(m.Sum),
  163. BuyerId: pTmp.BuyerId,
  164. RecentTime: m.Zbtime,
  165. }
  166. tmp.TotalAmount, _ = m.ProjectMoney.Float64()
  167. if time.Now().AddDate(-3, 0, 0).Unix() <= tmp.RecentTime {
  168. tmp.NearlyYears = true
  169. }
  170. prListRes.Result = append(prListRes.Result, &tmp)
  171. }
  172. }
  173. redis.Put("newother", redisKey, prListRes, T.NetworkCom.CacheTimeout())
  174. return prListRes
  175. }
  176. func GetWinnerData(scopeClass string, bid string) []AggStruct {
  177. ass := []AggStruct{}
  178. if scopeClass == "" {
  179. return ass
  180. }
  181. args := []interface{}{bid, bid}
  182. wh, newArgs := common.WhArgs(strings.Split(scopeClass, ","))
  183. args = append(args, newArgs...)
  184. rows, err1 := T.ClickhouseConn.Query(context.TODO(), `select distinct wr as name,wr_id as id from information.transaction_info_all ARRAY JOIN winner_id as wr_id,winner as wr
  185. prewhere buyer_id IN (SELECT buyer_id from information.transaction_info_all prewhere has(winner_id,?) and buyer_id<>'') and wr_id<>? and LENGTH(winner)=LENGTH(winner_id) AND hasAny(topscopeclass,[`+wh+`])=0`, args...)
  186. if err1 != nil {
  187. logx.Error(err1)
  188. return ass
  189. }
  190. winnerIds := []string{}
  191. for rows.Next() {
  192. as := AggStruct{}
  193. if err := rows.ScanStruct(&as); err != nil {
  194. logx.Error(err)
  195. continue
  196. }
  197. winnerIds = append(winnerIds, as.Id)
  198. ass = append(ass, as)
  199. }
  200. rows.Close()
  201. if err := rows.Err(); err != nil {
  202. logx.Error(err)
  203. }
  204. hz := GetWinnerDataHz(bid, winnerIds)
  205. for _, v := range ass {
  206. if _, ok := hz[v.Id]; !ok {
  207. continue
  208. }
  209. v.ProjectMoney = hz[v.Id].ProjectMoney
  210. v.Sum = hz[v.Id].Sum
  211. v.Zbtime = hz[v.Id].Zbtime
  212. }
  213. return ass
  214. }
  215. //
  216. func GetWinnerDataHz(buyerId string, winnerIds []string) map[string]AggStruct {
  217. res := map[string]AggStruct{}
  218. if len(winnerIds) == 0 {
  219. return res
  220. }
  221. args := []interface{}{buyerId}
  222. wh, newArgs := common.WhArgs(winnerIds)
  223. args = append(args, newArgs...)
  224. rows, err1 := T.ClickhouseConn.Query(context.TODO(), `select winner_id as id,sum(1) as sum,sum(project_money) as project_money,max(zbtime) as zbtime from information.transaction_info_all ARRAY JOIN winner_id
  225. prewhere winner_id in(`+wh+`) and buyer_id=? group by winner_id`, args...)
  226. if err1 != nil {
  227. logx.Error(err1)
  228. return res
  229. }
  230. for rows.Next() {
  231. as := AggStruct{}
  232. if err := rows.ScanStruct(&as); err != nil {
  233. logx.Error(err)
  234. continue
  235. }
  236. res[as.Id] = as
  237. }
  238. rows.Close()
  239. if err := rows.Err(); err != nil {
  240. logx.Error(err)
  241. }
  242. return res
  243. }
  244. //代理机构
  245. func GetAgencyData(bid string) []AggStruct {
  246. ass := []AggStruct{}
  247. rows, err1 := T.ClickhouseConn.Query(context.TODO(), `select agency as name,agency_id as id,sum(1) as sum,sum(project_money) as project_money,max(zbtime) as zbtime from information.transaction_info_all prewhere buyer_id=? and agency<>'' and agency_id<>'' GROUP by agency,agency_id`, bid)
  248. if err1 != nil {
  249. logx.Error(err1)
  250. return ass
  251. }
  252. for rows.Next() {
  253. as := AggStruct{}
  254. if err := rows.ScanStruct(&as); err != nil {
  255. logx.Error(err)
  256. continue
  257. }
  258. ass = append(ass, as)
  259. }
  260. rows.Close()
  261. if err := rows.Err(); err != nil {
  262. logx.Error(err)
  263. }
  264. return ass
  265. }
  266. type P_History struct {
  267. ProjectId string `ch:"project_id"`
  268. ProjectName string `ch:"project_name"`
  269. ZbTime int64 `ch:"zbtime"`
  270. Href string `ch:"href"`
  271. }
  272. // @Author jianghan
  273. // @Description 合作历史
  274. // @Date 2024/4/20
  275. func GetData3(source string, buyerId, winnerId string) (result []*P_History) {
  276. var rows driver.Rows
  277. if source == "1" {
  278. rows, _ = T.ClickhouseConn.Query(context.TODO(), sql_2_1_1, buyerId, winnerId)
  279. } else if source == "2" {
  280. rows, _ = T.ClickhouseConn.Query(context.TODO(), sql_2_1, buyerId, winnerId)
  281. }
  282. for rows.Next() {
  283. pHis := P_History{}
  284. _ = rows.ScanStruct(&pHis)
  285. pHis.Href = fmt.Sprintf("/article/content/%s.html", encrypt.CommonEncodeArticle("content", pHis.ProjectId))
  286. result = append(result, &pHis)
  287. }
  288. return
  289. }
  290. // @Author jianghan
  291. // @Description 上次合作时间
  292. // @Date 2024/4/24
  293. func LastTimeCoop(buyerId, ent, stype string) (bool, int64) {
  294. zbtime := int64(0)
  295. near := false
  296. if stype == "adiffb" {
  297. sql := `SELECT zbtime FROM information.transaction_info_all prewhere buyer_id = ? AND has(winner, ?) ORDER BY zbtime DESC LIMIT 1`
  298. _ = T.ClickhouseConn.QueryRow(context.TODO(), sql, buyerId, ent).Scan(&zbtime)
  299. } else if stype == "agency" {
  300. sql := `SELECT zbtime FROM information.transaction_info_all prewhere buyer_id = ? AND agency = ? ORDER BY zbtime DESC LIMIT 1`
  301. _ = T.ClickhouseConn.QueryRow(context.TODO(), sql, buyerId, ent).Scan(&zbtime)
  302. }
  303. timestamp := time.Now().AddDate(-3, 0, 0).Unix()
  304. if timestamp <= zbtime {
  305. near = true
  306. }
  307. return near, zbtime
  308. }
  309. func LastTimeCoopBath(positionId int64, buyerId string, winners, agencys []string) (map[string]*Cooperate, map[string]*Cooperate) {
  310. adiffb, agency := map[string]*Cooperate{}, map[string]*Cooperate{}
  311. if buyerId == "" {
  312. return adiffb, agency
  313. }
  314. var toSearch = func(tp int, query string, ws []string) {
  315. logx.Info("LastTimeCoopBath once start ", positionId)
  316. defer logx.Info("LastTimeCoopBath once over ", positionId)
  317. wh, newArgs := common.WhArgs(ws)
  318. query = fmt.Sprintf(query, wh)
  319. args := []interface{}{buyerId}
  320. args = append(args, newArgs...)
  321. rows, err := T.ClickhouseConn.Query(context.Background(), query, args...)
  322. if err != nil {
  323. logx.Error(err)
  324. return
  325. }
  326. for rows.Next() {
  327. var (
  328. one string
  329. zbtime int64
  330. )
  331. if err := rows.Scan(&one, &zbtime); err != nil {
  332. logx.Error(err)
  333. continue
  334. }
  335. c := &Cooperate{
  336. ZbTime: zbtime,
  337. }
  338. timestamp := time.Now().AddDate(-3, 0, 0).Unix()
  339. if timestamp <= c.ZbTime {
  340. c.Near = true
  341. }
  342. if tp == 1 {
  343. adiffb[one] = c
  344. } else {
  345. agency[one] = c
  346. }
  347. }
  348. rows.Close()
  349. if err := rows.Err(); err != nil {
  350. logx.Error(err)
  351. }
  352. }
  353. if len(winners) > 0 {
  354. key := fmt.Sprintf("networkManage_lastTimeCoop_winner_%s", common.GetMd5String(buyerId+"_"+strings.Join(winners, ",")))
  355. wb, err := redis.GetBytes("newother", key)
  356. if err == nil {
  357. json.Unmarshal(*wb, &adiffb)
  358. } else {
  359. sql := `SELECT winner_one,max(zbtime) FROM information.transaction_info_all ARRAY JOIN winner AS winner_one prewhere buyer_id=? AND hasAny(winner,[%s])) group by winner_one`
  360. wns := []string{}
  361. for _, v := range winners {
  362. wns = append(wns, v)
  363. if len(wns) == 50 {
  364. toSearch(1, sql, wns)
  365. wns = []string{}
  366. }
  367. }
  368. if len(wns) > 0 {
  369. toSearch(1, sql, wns)
  370. }
  371. redis.Put("newother", key, adiffb, T.NetworkCom.CacheTimeout())
  372. }
  373. }
  374. if len(agencys) > 0 {
  375. key := fmt.Sprintf("networkManage_lastTimeCoop_agency_%s", common.GetMd5String(buyerId+"_"+strings.Join(agencys, ",")))
  376. wb, err := redis.GetBytes("newother", key)
  377. if err == nil {
  378. json.Unmarshal(*wb, &agency)
  379. } else {
  380. sql := `SELECT agency,max(zbtime) FROM information.transaction_info_all prewhere buyer_id=? AND agency in (%s) group by agency`
  381. acs := []string{}
  382. for _, v := range agencys {
  383. acs = append(acs, v)
  384. if len(acs) == 50 {
  385. toSearch(2, sql, acs)
  386. acs = []string{}
  387. }
  388. }
  389. if len(acs) > 0 {
  390. toSearch(2, sql, acs)
  391. }
  392. redis.Put("newother", key, agency, T.NetworkCom.CacheTimeout())
  393. }
  394. }
  395. return adiffb, agency
  396. }