participateStatistics.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. package service
  2. import (
  3. "app.yhyue.com/moapp/jybase/common"
  4. "app.yhyue.com/moapp/jybase/encrypt"
  5. "app.yhyue.com/moapp/jybase/redis"
  6. "encoding/json"
  7. "fmt"
  8. "jyBXCore/rpc/bxcore"
  9. IC "jyBXCore/rpc/init"
  10. "jyBXCore/rpc/model/es"
  11. "log"
  12. "strconv"
  13. "strings"
  14. "time"
  15. )
  16. const (
  17. //角色
  18. Role_admin_system = 1 //系统管理员
  19. Role_admin_department = 2 //部门管理员
  20. )
  21. type ParticipateStatistics struct {
  22. PositionId int64
  23. EntId int64
  24. DeptId int64
  25. EntUserId int64
  26. }
  27. func (in *ParticipateStatistics) PushStatistics(entUserIdArr []string, startTime, endTime int64, source []int64) (result []*bxcore.PushStatisticsData) {
  28. //判断是企业、部门还是个人
  29. isAdmin, personArrStr, users := in.PersonHandle(entUserIdArr)
  30. //时间处理
  31. query := QueryHandle(isAdmin, startTime, endTime, personArrStr, source, -1)
  32. //推送数据查询
  33. dataList := IC.BaseMysql.SelectBySql(fmt.Sprintf("select * from participate_push_statistics where %s order by ymd", strings.Join(query, " and ")))
  34. if users != nil && len(*users) > 0 {
  35. result = PushHandle(dataList, users, isAdmin)
  36. }
  37. return
  38. }
  39. func (in *ParticipateStatistics) ProjectStatistics(entUserIdArr []string, startTime, endTime, bidWay int64) (result []*bxcore.ProjectStatisticsData) {
  40. //判断是企业、部门还是个人
  41. isAdmin, personArrStr, users := in.PersonHandle(entUserIdArr)
  42. query := QueryHandle(isAdmin, startTime, endTime, personArrStr, []int64{}, bidWay)
  43. //订阅推送数处理
  44. //推送数据查询
  45. // 调整为时间倒序 处理投标阶段的时候 只取最新的一条的数据
  46. dataList := IC.BaseMysql.SelectBySql(fmt.Sprintf("select * from participate_project_statistics where %s order by ymd desc ", strings.Join(query, "and ")))
  47. if users != nil && len(*users) > 0 {
  48. result = ProjectHandle(dataList, users, isAdmin)
  49. }
  50. return
  51. }
  52. var (
  53. SelectItemMap = map[int]string{
  54. 1: "个人订阅",
  55. 2: "企业自动分发",
  56. 3: "企业手动分发",
  57. }
  58. )
  59. // GetSourceItem 获取标讯项目来源筛选项
  60. func (in *ParticipateStatistics) GetSourceItem(entId, positionId int) (result []*bxcore.SourceItem) {
  61. redisKey := "sourceItem%s_%s"
  62. query := "select distinct `source` from participate_push_statistics where "
  63. // 个人用户
  64. if entId == 0 {
  65. // 查职位id
  66. query += fmt.Sprintf(" position_id =%d", positionId)
  67. redisKey = fmt.Sprintf(redisKey, "personal", positionId)
  68. } else {
  69. // 企业用户 用企业id查
  70. query += fmt.Sprintf(" end =%d", entId)
  71. redisKey = fmt.Sprintf(redisKey, "ent", entId)
  72. }
  73. if data, err := redis.GetBytes("other", redisKey); err == nil && data != nil {
  74. err := json.Unmarshal(*data, &result)
  75. if err == nil {
  76. return result
  77. } else {
  78. log.Println("序列化失败", redisKey, err)
  79. }
  80. }
  81. //
  82. rs := IC.BaseMysql.SelectBySql(query)
  83. if rs == nil || len(*rs) == 0 {
  84. return
  85. }
  86. for i := 0; i < len(*rs); i++ {
  87. value := common.ObjToString((*rs)[i]["source"])
  88. if value == "" {
  89. continue
  90. }
  91. splitSource := strings.Split(value, ",")
  92. for j := 0; j < len(splitSource); j++ {
  93. sourceValue, err := strconv.Atoi(splitSource[j])
  94. if err != nil {
  95. log.Println("类型转换错误:", err, splitSource[j])
  96. continue
  97. }
  98. if name, ok := SelectItemMap[sourceValue]; ok {
  99. result = append(result, &bxcore.SourceItem{
  100. Name: name,
  101. Value: int64(sourceValue),
  102. })
  103. }
  104. }
  105. }
  106. if len(result) > 0 {
  107. // 存缓存
  108. rsByte, _ := json.Marshal(result)
  109. redis.PutBytes("other", redisKey, &rsByte, 60*60*2)
  110. }
  111. return
  112. }
  113. func (in *ParticipateStatistics) PersonHandle(entUserIdArr []string) (isAdmin bool, idStr string, users *[]map[string]interface{}) {
  114. userEnt := EntInfo(common.IntAll(in.EntId), common.IntAll(in.EntUserId))
  115. if len(entUserIdArr) > 0 {
  116. //查询所选人的部门以及人员信息
  117. users = GetUser(entUserIdArr)
  118. //返回所选人的信息
  119. isAdmin = true
  120. idStr = strings.Join(entUserIdArr, ",")
  121. } else {
  122. if userEnt.Role_admin_department || userEnt.Role_admin_system { //
  123. // 部门管理员 获取所有部门和子部门员工
  124. users = GetDisUsers(common.IntAll(in.EntId), userEnt.Dept.Id)
  125. var staffs []string
  126. if users != nil && len(*users) > 0 {
  127. for _, v := range *users {
  128. staffs = append(staffs, common.InterfaceToStr(v["id"]))
  129. }
  130. }
  131. isAdmin = true
  132. idStr = strings.Join(staffs, ",")
  133. } else {
  134. if userEnt.Dept.Id != 0 {
  135. entUserIdArr = append(entUserIdArr, common.InterfaceToStr(in.EntUserId))
  136. users = GetUser(entUserIdArr)
  137. //返回所选人的信息
  138. isAdmin = true
  139. idStr = strings.Join(entUserIdArr, ",")
  140. } else {
  141. isAdmin = false
  142. idStr = common.InterfaceToStr(in.PositionId)
  143. users = &[]map[string]interface{}{
  144. map[string]interface{}{
  145. "id": in.PositionId,
  146. "name": "个人",
  147. },
  148. }
  149. }
  150. }
  151. }
  152. return
  153. }
  154. type PushData struct {
  155. PersonName string
  156. entUserId string
  157. DepartmentName string
  158. PushNumb map[string]interface{}
  159. ParticipateNumb map[string]interface{}
  160. BidNumb map[string]interface{}
  161. WinNumb map[string]interface{}
  162. BrowseNumb map[string]interface{}
  163. }
  164. type ProjectData struct {
  165. PersonName string
  166. DepartmentName string
  167. entUserId string
  168. BidNumb map[string]interface{} //投标数量
  169. DirectBidNumb map[string]interface{} //直接投标数
  170. ChannelBidNumb map[string]interface{} //渠道投标数
  171. WinNumb map[string]interface{}
  172. DirectWinNumb map[string]interface{} //直接中标数
  173. ChannelWinNumb map[string]interface{} //渠道中标数
  174. NotBidNumber map[string]interface{} //未中标数量
  175. EndNumb map[string]interface{} //终止数量
  176. participateProjectNumb map[string]interface{} // 参标数量
  177. Stage map[string]map[string]interface{}
  178. }
  179. func PushHandle(data *[]map[string]interface{}, users *[]map[string]interface{}, isAdmin bool) []*bxcore.PushStatisticsData {
  180. result := &map[int64]*PushData{}
  181. for k, v := range *users {
  182. (*result)[common.Int64All(v["id"])] = &PushData{
  183. PersonName: fmt.Sprintf("%s_%d", common.InterfaceToStr(v["name"]), k),
  184. DepartmentName: common.InterfaceToStr(v["dept_name"]),
  185. entUserId: common.InterfaceToStr(v["id"]),
  186. }
  187. }
  188. if data != nil && len(*data) > 0 {
  189. for _, v := range *data {
  190. userId := int64(0)
  191. if isAdmin {
  192. userId = common.Int64All(v["ent_user_id"])
  193. } else {
  194. userId = common.Int64All(v["position_id"])
  195. }
  196. if (*result)[userId] != nil {
  197. //浏览总数处理处理
  198. project_id := common.InterfaceToStr(common.InterfaceToStr(v["project_id"]))
  199. if common.Int64All(v["isvisit"]) > 0 {
  200. (*result)[userId].BrowseNumb = DataHanle((*result)[userId].BrowseNumb, project_id)
  201. }
  202. //推送总数处理
  203. (*result)[userId].PushNumb = DataHanle((*result)[userId].PushNumb, project_id)
  204. //参标总数处理
  205. if common.Int64All(v["isparticipate"]) > 0 {
  206. (*result)[userId].ParticipateNumb = DataHanle((*result)[userId].ParticipateNumb, project_id)
  207. }
  208. //投标总数处理
  209. if common.Int64All(v["isbid"]) > 0 {
  210. (*result)[userId].BidNumb = DataHanle((*result)[userId].BidNumb, project_id)
  211. }
  212. //中标总数处理
  213. if common.Int64All(v["win_status"]) != 0 {
  214. win_status := common.Int64All(v["win_status"])
  215. if win_status == 1 {
  216. (*result)[userId].WinNumb = DataHanle((*result)[userId].WinNumb, project_id)
  217. } else {
  218. delete((*result)[userId].WinNumb, project_id)
  219. }
  220. }
  221. }
  222. }
  223. }
  224. pushStatisticsList := make([]*bxcore.PushStatisticsData, len(*result))
  225. for _, v := range *result {
  226. personName := strings.Split(v.PersonName, "_")[0]
  227. k := common.Int64All(strings.Split(v.PersonName, "_")[1])
  228. pushStatisticsList[k] = &bxcore.PushStatisticsData{
  229. PersonName: personName,
  230. DepartmentName: v.DepartmentName,
  231. EntUserId: encrypt.SE.Encode2Hex(v.entUserId),
  232. PushNumb: common.Int64All(len(v.PushNumb)),
  233. ParticipateNumb: common.Int64All(len(v.ParticipateNumb)),
  234. BidNumb: common.Int64All(len(v.BidNumb)),
  235. WinNumb: common.Int64All(len(v.WinNumb)),
  236. BrowseNumb: common.Int64All(len(v.BrowseNumb)),
  237. }
  238. }
  239. return pushStatisticsList
  240. }
  241. func ProjectHandle(data *[]map[string]interface{}, users *[]map[string]interface{}, isAdmin bool) []*bxcore.ProjectStatisticsData {
  242. result := &map[int64]*ProjectData{}
  243. for k, v := range *users {
  244. (*result)[common.Int64All(v["id"])] = &ProjectData{
  245. PersonName: fmt.Sprintf("%s_%d", common.InterfaceToStr(v["name"]), k),
  246. DepartmentName: common.InterfaceToStr(v["dept_name"]),
  247. entUserId: common.InterfaceToStr(v["id"]),
  248. }
  249. }
  250. if data != nil && len(*data) > 0 {
  251. // existProject 已经存在的项目 项目id_用户id
  252. existProject := map[string]struct{}{}
  253. for _, v := range *data {
  254. userId := int64(0)
  255. if isAdmin {
  256. userId = common.Int64All(v["ent_user_id"])
  257. } else {
  258. userId = common.Int64All(v["position_id"])
  259. }
  260. project_id := common.InterfaceToStr(common.InterfaceToStr(v["project_id"]))
  261. if (*result)[userId] != nil {
  262. // 参标数量
  263. (*result)[userId].participateProjectNumb = DataHanle((*result)[userId].participateProjectNumb, project_id)
  264. //投标数量
  265. if common.Int64All(v["isbid"]) > 0 {
  266. (*result)[userId].BidNumb = DataHanle((*result)[userId].BidNumb, project_id)
  267. }
  268. //终止参保统计
  269. if common.Int64All(v["isend"]) != 0 {
  270. (*result)[userId].EndNumb = DataHanle((*result)[userId].EndNumb, project_id)
  271. }
  272. /* p408 调整:
  273. 这里是因为participate_project_statistics 表的数据是多条的
  274. 统计各阶段数据的时候和中标总数的时候只以最新的为准
  275. 但是统计各阶段勾选数量时 重复统计后续删除不好处理 所以这里调整为
  276. 查询的时候根据时间倒序,同一个项目只统计第一条就可以了 每个项目第一条就是当前阶段内最新的
  277. 其他的直接跳过 不用重复统计后续再删除
  278. */
  279. existKey := fmt.Sprintf("%d_%s", userId, project_id)
  280. if _, ok := existProject[existKey]; !ok {
  281. existProject[existKey] = struct{}{}
  282. } else {
  283. continue
  284. }
  285. //直接投标数
  286. if common.Int64All(v["bid_way"]) > 0 {
  287. if common.Int64All(v["bid_way"]) == 2 {
  288. (*result)[userId].ChannelBidNumb = DataHanle((*result)[userId].ChannelBidNumb, project_id)
  289. delete((*result)[userId].DirectBidNumb, project_id)
  290. } else {
  291. (*result)[userId].DirectBidNumb = DataHanle((*result)[userId].DirectBidNumb, project_id)
  292. delete((*result)[userId].ChannelBidNumb, project_id)
  293. }
  294. }
  295. //中标总数处理
  296. if common.Int64All(v["win_status"]) != 0 {
  297. if common.Int64All(v["win_status"]) > 0 {
  298. //中标数量
  299. (*result)[userId].WinNumb = DataHanle((*result)[userId].WinNumb, project_id)
  300. delete((*result)[userId].NotBidNumber, project_id)
  301. } else {
  302. //未中标数量
  303. (*result)[userId].NotBidNumber = DataHanle((*result)[userId].NotBidNumber, project_id)
  304. delete((*result)[userId].WinNumb, project_id)
  305. }
  306. }
  307. //中标方式处理
  308. if common.Int64All(v["win_bidway"]) != 0 {
  309. if common.Int64All(v["win_bidway"]) == 1 {
  310. //直接投标数量
  311. (*result)[userId].DirectWinNumb = DataHanle((*result)[userId].DirectWinNumb, project_id)
  312. delete((*result)[userId].ChannelWinNumb, project_id)
  313. } else {
  314. //渠道投标数量
  315. (*result)[userId].ChannelWinNumb = DataHanle((*result)[userId].ChannelWinNumb, project_id)
  316. delete((*result)[userId].DirectWinNumb, project_id)
  317. }
  318. }
  319. // 阶段勾选数量统计 只统计第一条
  320. stage := common.ObjToString(v["bid_stage"])
  321. if stage != "" {
  322. stageSplit := strings.Split(stage, ",")
  323. if (*result)[userId].Stage == nil {
  324. (*result)[userId].Stage = map[string]map[string]interface{}{}
  325. }
  326. for i := 0; i < len(stageSplit); i++ {
  327. stageK := stageSplit[i]
  328. (*result)[userId].Stage[stageK] = DataHanle((*result)[userId].Stage[stageSplit[i]], project_id)
  329. }
  330. }
  331. }
  332. }
  333. }
  334. projectStatisticsList := make([]*bxcore.ProjectStatisticsData, len(*result))
  335. for _, v := range *result {
  336. personName := strings.Split(v.PersonName, "_")[0]
  337. k := common.Int64All(strings.Split(v.PersonName, "_")[1])
  338. tmpStage := map[string]int64{}
  339. for stageK, stageV := range v.Stage {
  340. tmpStage[stageK] = int64(len(stageV))
  341. }
  342. projectStatisticsList[k] = &bxcore.ProjectStatisticsData{
  343. PersonName: personName,
  344. DepartmentName: v.DepartmentName,
  345. EntUserId: encrypt.SE.Encode2Hex(v.entUserId),
  346. BidNumb: common.Int64All(len(v.BidNumb)),
  347. DirectBidNumb: common.Int64All(len(v.DirectBidNumb)),
  348. ChannelBidNumb: common.Int64All(len(v.ChannelBidNumb)),
  349. WinNumb: common.Int64All(len(v.WinNumb)),
  350. DirectWinNumb: common.Int64All(len(v.DirectWinNumb)),
  351. ChannelWinNumb: common.Int64All(len(v.ChannelWinNumb)),
  352. NotBidNumber: common.Int64All(len(v.NotBidNumber)),
  353. EndNumb: common.Int64All(len(v.EndNumb)),
  354. ParticipateProjectNumb: common.Int64All(len(v.participateProjectNumb)),
  355. Stage: tmpStage,
  356. }
  357. }
  358. return projectStatisticsList
  359. }
  360. func EntInfo(entId, entUserId int) *CurrentUser {
  361. currentUser := &CurrentUser{
  362. Dept: &Department{},
  363. }
  364. user := IC.MainMysql.SelectBySql(`SELECT a.name as user_name from entniche_user a INNER JOIN entniche_user_role b on (a.id=b.user_id) where a.id=? and b.role_id=? limit 1`, entUserId, Role_admin_system)
  365. if user != nil && len(*user) > 0 {
  366. currentUser.Role_admin_system = true
  367. currentUser.User_name, _ = (*user)[0]["user_name"].(string)
  368. currentUser.User_power = 1
  369. r := IC.MainMysql.SelectBySql(`SELECT id,name,subdis,nodiff from entniche_department where ent_id=? and pid=0 limit 1`, entId)
  370. if r != nil && len(*r) == 1 {
  371. department := JsonUnmarshal((*r)[0], &Department{}).(*Department)
  372. if department != nil {
  373. department.Pid = department.Id
  374. currentUser.Dept = department
  375. }
  376. }
  377. } else {
  378. //角色、权限
  379. r := IC.MainMysql.SelectBySql(`SELECT a.name as user_name,a.power as user_power,b.role_id,d.id as dept_id,d.name as dept_name,d.subdis as dept_subdis,d.nodiff as dept_nodiff,e.id as dept_pid from entniche_user a
  380. LEFT JOIN entniche_user_role b on (b.user_id=?)
  381. INNER JOIN entniche_department_user c on (a.id=? and a.id=c.user_id)
  382. INNER JOIN entniche_department d on (c.dept_id=d.id)
  383. INNER JOIN entniche_department e on (e.ent_id=? and e.pid=0)
  384. order by a.id desc limit 1`, entUserId, entUserId, entId)
  385. if r != nil && len(*r) == 1 {
  386. currentUser.User_name, _ = (*r)[0]["user_name"].(string)
  387. currentUser.User_power = common.IntAll((*r)[0]["user_power"])
  388. if common.IntAll((*r)[0]["role_id"]) == Role_admin_department {
  389. currentUser.Role_admin_department = true
  390. }
  391. currentUser.Dept.Id = common.IntAll((*r)[0]["dept_id"])
  392. currentUser.Dept.Pid = common.IntAll((*r)[0]["dept_pid"])
  393. currentUser.Dept.Name = common.ObjToString((*r)[0]["dept_name"])
  394. currentUser.Dept.Subdis = common.IntAll((*r)[0]["dept_subdis"])
  395. currentUser.Dept.Nodiff = common.IntAll((*r)[0]["dept_nodiff"])
  396. }
  397. }
  398. return currentUser
  399. }
  400. // map转结构体
  401. func JsonUnmarshal(m interface{}, s interface{}) interface{} {
  402. var b []byte
  403. if v, ok := m.(string); ok {
  404. b = []byte(v)
  405. } else if v, ok := m.([]byte); ok {
  406. b = v
  407. } else {
  408. b, _ = json.Marshal(m)
  409. }
  410. json.Unmarshal(b, &s)
  411. return s
  412. }
  413. // 获取部门下可以进行分发的人员(不包含部门名称和部门id)
  414. func GetDisUsers(entId, deptId int) *[]map[string]interface{} {
  415. r := IC.MainMysql.SelectBySql(`select DISTINCT c.id,c.name,c.phone,c.power,b.dept_id,d.name as dept_name
  416. from entniche_department_parent a
  417. INNER JOIN entniche_department_user b on (b.dept_id=? or (a.pid=? and a.id=b.dept_id))
  418. INNER JOIN entniche_user c on (c.ent_id=? and b.user_id=c.id)
  419. INNER JOIN entniche_department d on d.id=b.dept_id
  420. order by b.dept_id , convert(c.name using gbk) COLLATE gbk_chinese_ci asc`, deptId, deptId, entId)
  421. return r
  422. }
  423. func GetUser(entUserIdArr []string) *[]map[string]interface{} {
  424. r := IC.MainMysql.SelectBySql("SELECT DISTINCT a.id, a.name, a.phone, d.id AS dept_id, d.NAME AS dept_name " +
  425. "FROM entniche_user a " +
  426. " INNER JOIN entniche_department_user b ON FIND_IN_SET(a.id,'" + strings.Join(entUserIdArr, ",") +
  427. "') and b.user_id = a.id " +
  428. " INNER JOIN entniche_department d ON d.id = b.dept_id " +
  429. " ORDER BY d.id, CONVERT ( a.NAME USING gbk ) COLLATE gbk_chinese_ci ASC",
  430. )
  431. return r
  432. }
  433. type User struct {
  434. Id int
  435. Name string //员工姓名
  436. Mail string //邮箱
  437. Phone string //手机号
  438. Dept_id int //部门id
  439. Dept_name string //部门名称
  440. //Role string //角色
  441. Power int //权限
  442. }
  443. type CurrentUser struct {
  444. Role_admin_department bool //是否是部门管理员
  445. Role_admin_system bool //是否是系统管理员
  446. Dept *Department //部门信息
  447. BondPhone string //手机号
  448. NickName string //昵称
  449. HeadImageUrl string //头像
  450. PersonalAuth int //个人认证
  451. PersonalAuthReason string //个人认证不通过原因
  452. User_power int //是否分配权限
  453. User_name string //用户姓名
  454. }
  455. type Department struct {
  456. Id int
  457. Name string //部门名
  458. Pid int //上级部门id
  459. Pname string //上级部门名称
  460. Nodiff int //全员无差别接收 0:关闭 1:打开
  461. Subdis int //订阅分发 0:关闭 1:打开
  462. Aid int //管理员id
  463. Aname string //管理员姓名
  464. Rname string //角色名
  465. User_count int //该部门下员工的总数
  466. Dept_count int //该部门下子部门总数
  467. Ent_id int //公司id
  468. }
  469. func DataHanle(data map[string]interface{}, project_id string) map[string]interface{} {
  470. if data == nil {
  471. data = map[string]interface{}{project_id: 1}
  472. } else {
  473. data[project_id] = 1
  474. }
  475. return data
  476. }
  477. func QueryHandle(isAdmin bool, startTime, endTime int64, personArrStr string, source []int64, bidWay int64) []string {
  478. //时间处理
  479. query := []string{}
  480. if isAdmin {
  481. //是管理员
  482. query = append(query, fmt.Sprintf(" ent_user_id in (%s) ", personArrStr))
  483. } else {
  484. //不是管理员
  485. query = append(query, fmt.Sprintf(" position_id = %s ", personArrStr))
  486. }
  487. if startTime == 0 && endTime == 0 {
  488. //没有传时间,默认时间处理
  489. var start = time.Now().AddDate(0, 0, -30)
  490. query = append(query, fmt.Sprintf(" ymd >= %s ", start.Format("20060102")))
  491. }
  492. if startTime != 0 {
  493. query = append(query, fmt.Sprintf(" ymd >= %d ", startTime))
  494. }
  495. if endTime != 0 {
  496. query = append(query, fmt.Sprintf(" ymd <= %d ", endTime))
  497. }
  498. if len(source) > 0 {
  499. sourceValue := ""
  500. for i := 0; i < len(source); i++ {
  501. sourceValue += fmt.Sprint(source[i]) + ","
  502. }
  503. sourceValue = sourceValue[:len(sourceValue)-1]
  504. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', a.source)", sourceValue))
  505. }
  506. if bidWay != 0 {
  507. query = append(query, fmt.Sprintf("bid_way = %d", bidWay))
  508. }
  509. return query
  510. }
  511. func (in *ParticipateStatistics) ProjectDetails(entUserIdArr []string, detailReq *bxcore.ProjectDetailsReq) (result bxcore.DetailData) {
  512. //判断是企业、部门还是个人
  513. isAdmin, personArrStr, _ := in.PersonHandle(entUserIdArr)
  514. queryType := GetQueryType(detailReq)
  515. query, countQuery := GetDetailQuery(isAdmin, personArrStr, detailReq, queryType)
  516. totalCount := IC.BaseMysql.CountBySql(countQuery)
  517. if totalCount == 0 {
  518. return
  519. }
  520. // 处理数据 这里只是筛选出项目id和阶段信息
  521. dataList := IC.BaseMysql.SelectBySql(query)
  522. if dataList == nil && len(*dataList) == 0 {
  523. return
  524. }
  525. // 处理数据 补充项目名称、推送表字段 、格式化数据
  526. rs := ProjectDetailHandle(*dataList, in.EntId)
  527. result = bxcore.DetailData{
  528. List: rs,
  529. Total: totalCount,
  530. }
  531. // 处理数据
  532. return
  533. }
  534. // todo 查询条件待验证
  535. //
  536. // 这个查询只用查出符合筛选条件的项目id 以及该项目对应的stage
  537. // 查询类型 0空搜索 全连接 1查左边 连右表查stage 2只查右表 3内连接
  538. func GetDetailQuery(isAdmin bool, personArrStr string, req *bxcore.ProjectDetailsReq, queryType int) (string, string) {
  539. if queryType == 0 {
  540. // 空搜索调整
  541. query1, query2, query3 := []string{}, []string{}, []string{}
  542. //没有传时间,默认时间处理
  543. var start = time.Now().AddDate(0, 0, -30)
  544. query1 = append(query1, fmt.Sprintf(" a.ymd >= %s ", start.Format("20060102")))
  545. query2 = append(query2, fmt.Sprintf(" b.update_date >= %s ", start.Format("20060102")))
  546. if isAdmin {
  547. //是管理员
  548. query1 = append(query1, fmt.Sprintf(" a.ent_user_id in (%s) ", personArrStr))
  549. query2 = append(query2, fmt.Sprintf(" FIND_IN_SET('%s', b.ent_user_id) ", personArrStr))
  550. query3 = append(query3, fmt.Sprintf(" FIND_IN_SET('%s', b.ent_user_id) ", personArrStr))
  551. } else {
  552. //不是管理员
  553. query1 = append(query1, fmt.Sprintf(" a.position_id = %s ", personArrStr))
  554. query2 = append(query2, fmt.Sprintf(" FIND_IN_SET('%s', b.position_id) ", personArrStr))
  555. query3 = append(query3, fmt.Sprintf(" FIND_IN_SET('%s', b.position_id) ", personArrStr))
  556. }
  557. q := `SELECT A.project_id, B.stage
  558. FROM
  559. (SELECT DISTINCT(project_id)
  560. FROM
  561. (SELECT project_id FROM participate_push_statistics
  562. WHERE %s UNION
  563. SELECT project_id
  564. FROM participate_stage_statistics
  565. WHERE %s)
  566. LIMIT %d , %d) A
  567. LEFT JOIN
  568. participate_stage_statistics B ON A.project_id = B.project_id where %s`
  569. q2 := "select distinct(position_id) from participate_push_statistics where %s union select project_id from participate_stage_statistics where %s "
  570. q1Str := strings.Join(query1, " and ")
  571. q2Str := strings.Join(query2, " and ")
  572. q3Str := strings.Join(query3, " and ")
  573. return fmt.Sprintf(q, q1Str, q2Str, q3Str), fmt.Sprintf(q2, q1Str, q2Str)
  574. }
  575. var q, qCount string
  576. query := []string{}
  577. if queryType == 1 {
  578. if isAdmin {
  579. //是管理员
  580. query = append(query, fmt.Sprintf(" a.ent_user_id in (%s) ", personArrStr))
  581. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', b.ent_user_id)", personArrStr))
  582. } else {
  583. //不是管理员
  584. query = append(query, fmt.Sprintf(" a.position_id = %s ", personArrStr))
  585. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', b.position_id)", personArrStr))
  586. }
  587. if req.StartTime == 0 && req.EndTime == 0 {
  588. //没有传时间,默认时间处理
  589. var start = time.Now().AddDate(0, 0, -30)
  590. query = append(query, fmt.Sprintf(" a.ymd >= %s ", start.Format("20060102")))
  591. }
  592. if req.StartTime != 0 {
  593. query = append(query, fmt.Sprintf(" a.ymd >= %d ", req.StartTime))
  594. }
  595. if req.EndTime != 0 {
  596. query = append(query, fmt.Sprintf(" a.ymd <= %d ", req.EndTime))
  597. }
  598. // 标讯/项目来源
  599. if len(req.Source) > 0 {
  600. sourceValue := ""
  601. for i := 0; i < len(req.Source); i++ {
  602. sourceValue += fmt.Sprint(req.Source[i]) + ","
  603. }
  604. sourceValue = sourceValue[:len(sourceValue)-1]
  605. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', a.source)", sourceValue))
  606. }
  607. // 投标类型 投标方式;1:直接投标 2:渠道投标',
  608. if req.BidWay != 0 {
  609. query = append(query, fmt.Sprintf("a.bid_way = %d", req.BidWay))
  610. }
  611. //参标状态:-1全部,0未参标、1已参标
  612. if req.IsParticipate != -1 {
  613. query = append(query, fmt.Sprintf("a.isparticipate = %d", req.IsParticipate))
  614. }
  615. q = "select distinct(a.project_id),b.stage from participate_push_statistics a left join participate_stage_statistics b on(b.project_id=a.project_id ) %s"
  616. qCount = "select count(distinct(a.project_id),b.stage) from participate_push_statistics a left join participate_stage_statistics b on(b.project_id=a.project_id ) %s"
  617. } else if queryType == 2 {
  618. if isAdmin {
  619. //是管理员
  620. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', b.ent_user_id) ", personArrStr))
  621. } else {
  622. //不是管理员
  623. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', b.position_id)", personArrStr))
  624. }
  625. // 参标状态更新时间
  626. if req.BidUpdateStartTime != "" {
  627. query = append(query, fmt.Sprintf("b.update_date > %s", req.BidUpdateStartTime))
  628. }
  629. if req.BidUpdateEndTime != "" {
  630. query = append(query, fmt.Sprintf("b.update_date > %s", req.BidUpdateStartTime))
  631. }
  632. if req.BidWay != 0 {
  633. query = append(query, fmt.Sprintf("b.bid_way = %d", req.BidWay))
  634. }
  635. //参标状态:-1全部,0未参标、1已参标
  636. if req.IsParticipate == 1 {
  637. query = append(query, fmt.Sprintf("b.isparticipate = %d", req.IsParticipate))
  638. }
  639. q = "select distinct(b.project_id),b.stage from participate_stage_statistics b %s"
  640. qCount = "select count(distinct(b.project_id),b.stage) from participate_stage_statistics b %s"
  641. } else {
  642. if isAdmin {
  643. //是管理员
  644. query = append(query, fmt.Sprintf(" a.ent_user_id in (%s) ", personArrStr))
  645. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', b.ent_user_id) ", personArrStr))
  646. } else {
  647. //不是管理员
  648. query = append(query, fmt.Sprintf(" a.position_id = %s ", personArrStr))
  649. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', b.position_id)", personArrStr))
  650. }
  651. if req.StartTime != 0 {
  652. query = append(query, fmt.Sprintf(" a.ymd >= %d ", req.StartTime))
  653. }
  654. if req.EndTime != 0 {
  655. query = append(query, fmt.Sprintf(" a.ymd <= %d ", req.EndTime))
  656. }
  657. // 标讯/项目来源
  658. if len(req.Source) > 0 {
  659. sourceValue := ""
  660. for i := 0; i < len(req.Source); i++ {
  661. sourceValue += fmt.Sprint(req.Source[i]) + ","
  662. }
  663. sourceValue = sourceValue[:len(sourceValue)-1]
  664. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', a.source)", sourceValue))
  665. }
  666. //参标状态:-1全部,0未参标、1已参标
  667. if req.IsParticipate != -1 {
  668. query = append(query, fmt.Sprintf("a.isparticipate = %d", req.IsParticipate))
  669. }
  670. // 投标类型 投标方式;1:直接投标 2:渠道投标',
  671. if req.BidWay != 0 {
  672. query = append(query, fmt.Sprintf("a.bid_way = %d", req.BidWay))
  673. }
  674. // 参标状态更新时间
  675. if req.BidUpdateStartTime != "" {
  676. query = append(query, fmt.Sprintf("b.update_date > %s", req.BidUpdateStartTime))
  677. }
  678. if req.BidUpdateEndTime != "" {
  679. query = append(query, fmt.Sprintf("b.update_date > %s", req.BidUpdateStartTime))
  680. }
  681. q = "select distinct(a.project_id),b.stage from participate_push_statistics a inner join participate_stage_statistics b on(b.project_id=a.project_id ) %s"
  682. qCount = "select count(distinct(a.project_id),b.stage) from participate_push_statistics a inner join participate_stage_statistics b on(b.project_id=a.project_id ) %s"
  683. }
  684. if len(query) > 0 {
  685. q = fmt.Sprintf(q, strings.Join(query, " and "))
  686. qCount = fmt.Sprintf(qCount, strings.Join(query, " and "))
  687. }
  688. // 处理分页
  689. if req.PageNum == 0 && req.PageSize == 0 {
  690. req.PageNum = 1
  691. req.PageNum = 50
  692. }
  693. q = fmt.Sprintf("%s limit %d,%d", q, (req.PageNum-1)*req.PageSize, req.PageSize)
  694. return q, qCount
  695. }
  696. type PushInfoStruct struct {
  697. Source string
  698. VisitDate string
  699. DisDate string
  700. IsDistribute int
  701. }
  702. func ProjectDetailHandle(dataList []map[string]interface{}, entId int64) []*bxcore.ProjectDetailData {
  703. //dataList 里面包含 项目id、各阶段信息
  704. // 处理项目名称
  705. projectIdList := []string{}
  706. for i := 0; i < len(dataList); i++ {
  707. projectIdList = append(projectIdList, common.ObjToString(dataList[i]["project_id"]))
  708. }
  709. // 项目名称处理成map用于后续使用
  710. projectNameMap := map[string]string{}
  711. projectNameRs := es.GetProjectNameByProjectId(projectIdList)
  712. if projectNameRs != nil && len(*projectNameRs) > 0 {
  713. for i := 0; i < len(*projectNameRs); i++ {
  714. projectId_ := common.ObjToString((*projectNameRs)[i]["_id"])
  715. projectName_ := (*projectNameRs)[i]["projectname"]
  716. projectNameMap[projectId_] = common.ObjToString(projectName_)
  717. }
  718. }
  719. // 获取推送最新状态
  720. newPushInfo := getNewPushInfo(projectIdList, int(entId))
  721. newPushInfoMap := map[string]PushInfoStruct{}
  722. // 处理推送最新状态
  723. if newPushInfo != nil && len(*newPushInfo) > 0 {
  724. for i := 0; i < len(*newPushInfo); i++ {
  725. project_ := common.ObjToString((*newPushInfo)[i]["project_id"])
  726. info := PushInfoStruct{
  727. Source: common.ObjToString((*newPushInfo)[i]["source"]),
  728. VisitDate: common.ObjToString((*newPushInfo)[i]["visit_date"]),
  729. DisDate: common.ObjToString((*newPushInfo)[i]["dis_date"]),
  730. IsDistribute: common.IntAll((*newPushInfo)[i]["is_distribute"]),
  731. }
  732. newPushInfoMap[project_] = info
  733. }
  734. }
  735. results := []*bxcore.ProjectDetailData{}
  736. // 处理成最后的数据
  737. for i := 0; i < len(dataList); i++ {
  738. projectId := common.ObjToString(dataList[i]["project_id"])
  739. tmp := bxcore.ProjectDetailData{
  740. ProjectName: projectNameMap[projectId],
  741. }
  742. // 处理推送表相关字段
  743. if pushInfo_, ok := newPushInfoMap[projectId]; ok {
  744. tmp.Source = pushInfo_.Source // todo 处理成中文
  745. tmp.ViewDate = pushInfo_.VisitDate
  746. tmp.IsDistribute = int64(pushInfo_.IsDistribute)
  747. tmp.DisDate = pushInfo_.DisDate
  748. } //
  749. // 处理阶段勾选信息和参标、终止参标信息
  750. if dataList[i]["stage"] != nil {
  751. if stage_, err := json.Marshal(dataList[i]["stage"]); err == nil {
  752. err := json.Unmarshal(stage_, &tmp.Stage)
  753. if err != nil {
  754. log.Println("stage 反序列失败", err)
  755. }
  756. }
  757. }
  758. results = append(results, &tmp)
  759. }
  760. return results
  761. }
  762. // 获取项目的最新推送状态信息
  763. func getNewPushInfo(projectIds []string, entId int) *[]map[string]interface{} {
  764. sql := `select project_id,source,visit_date,dis_date,is_distribute from participate_push_statistics where id in (SELECT max(id) from participate_push_statistics where ent_id=%d and project_id in ( "` + strings.Join(projectIds, "\",\"") + `" ) group by project_id); `
  765. query := fmt.Sprintf(sql, entId)
  766. return IC.BaseMysql.SelectBySql(query)
  767. }
  768. // GetQueryType 查询类型 0空搜索 全连接 1查左边 连右表查stage 2只查右表 3内连接
  769. func GetQueryType(in *bxcore.ProjectDetailsReq) int {
  770. // TODO 调整
  771. if in.BidUpdateStartTime == "" && in.BidUpdateEndTime == "" && in.StartTime == 0 && in.EndTime == 0 && in.IsParticipate == -1 && in.BidWay == 0 && len(in.Source) == 0 {
  772. return 0
  773. }
  774. if in.IsParticipate == 0 {
  775. // 未参标只筛选推送表 右表条件无效
  776. return 1
  777. }
  778. if (in.StartTime != 0 || in.EndTime != 0 || len(in.Source) > 0) && (in.BidUpdateStartTime == "" && in.BidUpdateEndTime == "" && in.IsParticipate != 1) {
  779. return 1
  780. }
  781. if (in.StartTime == 0 && in.EndTime == 0 && len(in.Source) == 0) && (in.BidUpdateStartTime != "" || in.BidUpdateEndTime == "" || in.IsParticipate == 1 || in.BidWay != 0) {
  782. return 2
  783. }
  784. return 3
  785. }