participateStatistics.go 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  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, 0)
  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. // 这是因为数据库中 0是未参标 1是已参标, 接收参数时和其他默认参数保持一致 0-全部 1 是未参标 2 是已参标
  540. req.IsParticipate -= 1
  541. if queryType == 0 {
  542. // 空搜索调整
  543. query1, query2, query3 := []string{}, []string{}, []string{}
  544. //没有传时间,默认时间处理
  545. var start = time.Now().AddDate(0, 0, -30)
  546. query1 = append(query1, fmt.Sprintf(" a.ymd >= %s ", start.Format("20060102")))
  547. query2 = append(query2, fmt.Sprintf(" b.update_date >= %s ", start.Format("20060102")))
  548. if isAdmin {
  549. //是管理员
  550. query1 = append(query1, fmt.Sprintf(" a.ent_user_id in (%s) ", personArrStr))
  551. query2 = append(query2, fmt.Sprintf(" FIND_IN_SET('%s', b.ent_user_ids) ", personArrStr))
  552. query3 = append(query3, fmt.Sprintf(" FIND_IN_SET('%s', b.ent_user_ids) ", personArrStr))
  553. } else {
  554. //不是管理员
  555. query1 = append(query1, fmt.Sprintf(" a.position_id = %s ", personArrStr))
  556. query2 = append(query2, fmt.Sprintf(" FIND_IN_SET('%s', b.position_ids) ", personArrStr))
  557. query3 = append(query3, fmt.Sprintf(" FIND_IN_SET('%s', b.position_ids) ", personArrStr))
  558. }
  559. q := `SELECT A.project_id, B.stage
  560. FROM
  561. (SELECT DISTINCT(project_id)
  562. FROM
  563. (SELECT project_id FROM participate_push_statistics
  564. WHERE %s UNION
  565. SELECT project_id
  566. FROM participate_stage_statistics
  567. WHERE %s)
  568. LIMIT %d , %d) A
  569. LEFT JOIN
  570. participate_stage_statistics B ON A.project_id = B.project_id where %s`
  571. q2 := "select distinct(position_id) from participate_push_statistics where %s union select project_id from participate_stage_statistics where %s "
  572. q1Str := strings.Join(query1, " and ")
  573. q2Str := strings.Join(query2, " and ")
  574. q3Str := strings.Join(query3, " and ")
  575. return fmt.Sprintf(q, q1Str, q2Str, q3Str), fmt.Sprintf(q2, q1Str, q2Str)
  576. }
  577. var q, qCount string
  578. query := []string{}
  579. joinStr := ""
  580. if queryType == 1 {
  581. if isAdmin {
  582. //是管理员
  583. query = append(query, fmt.Sprintf(" a.ent_user_id in (%s) ", personArrStr))
  584. joinStr = "and a.ent_id = b.ent_id"
  585. } else {
  586. query = append(query, fmt.Sprintf(" a.position_id = %s ", personArrStr))
  587. //不是管理员
  588. // 个人版
  589. if req.PositionType == 0 {
  590. joinStr = "and a.position_id = b.position_ids"
  591. } else {
  592. // 企业版 个人 因为是查项目的最新状态信息 所以 用ent_id 和项目id连表
  593. joinStr = "and a.ent_id = b.ent_id"
  594. }
  595. }
  596. if req.StartTime == 0 && req.EndTime == 0 {
  597. //没有传时间,默认时间处理
  598. var start = time.Now().AddDate(0, 0, -30)
  599. query = append(query, fmt.Sprintf(" a.ymd >= %s ", start.Format("20060102")))
  600. }
  601. if req.StartTime != 0 {
  602. query = append(query, fmt.Sprintf(" a.ymd >= %d ", req.StartTime))
  603. }
  604. if req.EndTime != 0 {
  605. query = append(query, fmt.Sprintf(" a.ymd <= %d ", req.EndTime))
  606. }
  607. // 标讯/项目来源
  608. if len(req.Source) > 0 {
  609. sourceValue := ""
  610. for i := 0; i < len(req.Source); i++ {
  611. sourceValue += fmt.Sprint(req.Source[i]) + ","
  612. }
  613. sourceValue = sourceValue[:len(sourceValue)-1]
  614. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', a.source)", sourceValue))
  615. }
  616. // 投标类型 投标方式;1:直接投标 2:渠道投标',
  617. if req.BidWay != 0 {
  618. query = append(query, fmt.Sprintf("a.bid_way = %d", req.BidWay))
  619. }
  620. //参标状态:-1全部,0未参标、1已参标
  621. if req.IsParticipate != -1 {
  622. query = append(query, fmt.Sprintf("a.isparticipate = %d", req.IsParticipate))
  623. }
  624. q = "select distinct(a.project_id),b.stage,a.id,b.id from participate_push_statistics a left join participate_stage_statistics b on(a.project_id=b.project_id %s ) where %s order by a.id desc,b.id desc"
  625. qCount = "select count(distinct(a.project_id)) from participate_push_statistics a left join participate_stage_statistics b on(a.project_id=b.project_id %s) where %s"
  626. } else if queryType == 2 {
  627. if isAdmin {
  628. //是管理员
  629. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', b.ent_user_ids) ", personArrStr))
  630. } else {
  631. //不是管理员
  632. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', b.position_ids)", personArrStr))
  633. }
  634. // 参标状态更新时间
  635. if req.BidUpdateStartTime != "" {
  636. query = append(query, fmt.Sprintf("b.update_date > %s", req.BidUpdateStartTime))
  637. }
  638. if req.BidUpdateEndTime != "" {
  639. query = append(query, fmt.Sprintf("b.update_date > %s", req.BidUpdateStartTime))
  640. }
  641. if req.BidWay != 0 {
  642. query = append(query, fmt.Sprintf("b.bid_way = %d", req.BidWay))
  643. }
  644. //参标状态:-1全部,0未参标、1已参标
  645. if req.IsParticipate == 1 {
  646. query = append(query, fmt.Sprintf("b.isparticipate = %d", req.IsParticipate))
  647. }
  648. q = "select distinct(b.project_id),b.stage,a.id,b.id from participate_stage_statistics b where %s %s order by b.id desc"
  649. qCount = "select count(b.project_id) from participate_stage_statistics b where %s %s"
  650. } else {
  651. if isAdmin {
  652. //是管理员
  653. query = append(query, fmt.Sprintf(" a.ent_user_id in (%s) ", personArrStr))
  654. joinStr = "and a.ent_id = b.ent_id"
  655. } else {
  656. query = append(query, fmt.Sprintf(" a.position_id = %s ", personArrStr))
  657. //不是管理员
  658. // 个人版
  659. if req.PositionType == 0 {
  660. joinStr = "and a.position_id = b.position_ids"
  661. } else {
  662. // 企业版 个人 因为是查项目的最新状态信息 所以 用ent_id 和项目id连表
  663. joinStr = "and a.ent_id = b.ent_id"
  664. }
  665. }
  666. if req.StartTime != 0 {
  667. query = append(query, fmt.Sprintf(" a.ymd >= %d ", req.StartTime))
  668. }
  669. if req.EndTime != 0 {
  670. query = append(query, fmt.Sprintf(" a.ymd <= %d ", req.EndTime))
  671. }
  672. // 标讯/项目来源
  673. if len(req.Source) > 0 {
  674. sourceValue := ""
  675. for i := 0; i < len(req.Source); i++ {
  676. sourceValue += fmt.Sprint(req.Source[i]) + ","
  677. }
  678. sourceValue = sourceValue[:len(sourceValue)-1]
  679. query = append(query, fmt.Sprintf(" FIND_IN_SET('%s', a.source)", sourceValue))
  680. }
  681. //参标状态:-1全部,0未参标、1已参标
  682. if req.IsParticipate != -1 {
  683. query = append(query, fmt.Sprintf("a.isparticipate = %d", req.IsParticipate))
  684. }
  685. // 投标类型 投标方式;1:直接投标 2:渠道投标',
  686. if req.BidWay != 0 {
  687. query = append(query, fmt.Sprintf("a.bid_way = %d", req.BidWay))
  688. }
  689. // 参标状态更新时间
  690. if req.BidUpdateStartTime != "" {
  691. query = append(query, fmt.Sprintf("b.update_date > %s", req.BidUpdateStartTime))
  692. }
  693. if req.BidUpdateEndTime != "" {
  694. query = append(query, fmt.Sprintf("b.update_date > %s", req.BidUpdateStartTime))
  695. }
  696. q = "select distinct(a.project_id),b.stage,a.id,b.id from participate_push_statistics a inner join participate_stage_statistics b on(b.project_id=a.project_id %s) where %s order by a.id desc,b.id desc"
  697. qCount = "select count(distinct(a.project_id)) from participate_push_statistics a inner join participate_stage_statistics b on(b.project_id=a.project_id %s) where %s"
  698. }
  699. if len(query) > 0 {
  700. q = fmt.Sprintf(q, joinStr, strings.Join(query, " and "))
  701. qCount = fmt.Sprintf(qCount, joinStr, strings.Join(query, " and "))
  702. }
  703. // 处理分页
  704. if req.PageNum == 0 && req.PageSize == 0 {
  705. req.PageNum = 1
  706. req.PageSize = 50
  707. }
  708. q = fmt.Sprintf("%s limit %d,%d", q, (req.PageNum-1)*req.PageSize, req.PageSize)
  709. return q, qCount
  710. }
  711. type PushInfoStruct struct {
  712. Source string
  713. VisitDate string
  714. DisDate string
  715. IsDistribute int
  716. }
  717. func ProjectDetailHandle(dataList []map[string]interface{}, entId int64) []*bxcore.ProjectDetailData {
  718. //dataList 里面包含 项目id、各阶段信息
  719. // 处理项目名称
  720. projectIdList := []string{}
  721. for i := 0; i < len(dataList); i++ {
  722. projectIdList = append(projectIdList, common.ObjToString(dataList[i]["project_id"]))
  723. }
  724. // 项目名称处理成map用于后续使用
  725. projectNameMap := map[string]string{}
  726. projectNameRs := es.GetProjectNameByProjectId(projectIdList)
  727. if projectNameRs != nil && len(*projectNameRs) > 0 {
  728. for i := 0; i < len(*projectNameRs); i++ {
  729. projectId_ := common.ObjToString((*projectNameRs)[i]["_id"])
  730. projectName_ := (*projectNameRs)[i]["projectname"]
  731. projectNameMap[projectId_] = common.ObjToString(projectName_)
  732. }
  733. }
  734. // 获取推送最新状态
  735. newPushInfo := getNewPushInfo(projectIdList, int(entId))
  736. newPushInfoMap := map[string]PushInfoStruct{}
  737. // 处理推送最新状态
  738. if newPushInfo != nil && len(*newPushInfo) > 0 {
  739. for i := 0; i < len(*newPushInfo); i++ {
  740. project_ := common.ObjToString((*newPushInfo)[i]["project_id"])
  741. info := PushInfoStruct{
  742. Source: common.ObjToString((*newPushInfo)[i]["source"]),
  743. VisitDate: common.ObjToString((*newPushInfo)[i]["visit_date"]),
  744. DisDate: common.ObjToString((*newPushInfo)[i]["dis_date"]),
  745. IsDistribute: common.IntAll((*newPushInfo)[i]["is_distribute"]),
  746. }
  747. newPushInfoMap[project_] = info
  748. }
  749. }
  750. results := []*bxcore.ProjectDetailData{}
  751. // 处理成最后的数据
  752. for i := 0; i < len(dataList); i++ {
  753. projectId := common.ObjToString(dataList[i]["project_id"])
  754. tmp := bxcore.ProjectDetailData{
  755. ProjectName: projectNameMap[projectId],
  756. }
  757. // 处理推送表相关字段
  758. if pushInfo_, ok := newPushInfoMap[projectId]; ok {
  759. tmp.Source = pushInfo_.Source // todo 处理成中文
  760. tmp.ViewDate = pushInfo_.VisitDate
  761. tmp.IsDistribute = int64(pushInfo_.IsDistribute)
  762. tmp.DisDate = pushInfo_.DisDate
  763. } //
  764. // 处理阶段勾选信息和参标、终止参标信息
  765. if dataList[i]["stage"] != nil {
  766. if stage_, err := json.Marshal(dataList[i]["stage"]); err == nil {
  767. err := json.Unmarshal(stage_, &tmp.Stage)
  768. if err != nil {
  769. log.Println("stage 反序列失败", err)
  770. }
  771. }
  772. }
  773. results = append(results, &tmp)
  774. }
  775. return results
  776. }
  777. // 获取项目的最新推送状态信息
  778. func getNewPushInfo(projectIds []string, entId int) *[]map[string]interface{} {
  779. 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); `
  780. query := fmt.Sprintf(sql, entId)
  781. return IC.BaseMysql.SelectBySql(query)
  782. }
  783. // GetQueryType 查询类型 0空搜索 全连接 1查左边 连右表查stage 2只查右表 3内连接
  784. // IsParticipate 接收参数时 0 全部 1 未参标 2已参标 数据库中 未参标是0
  785. func GetQueryType(in *bxcore.ProjectDetailsReq) int {
  786. // TODO 调整
  787. if in.BidUpdateStartTime == "" && in.BidUpdateEndTime == "" && in.StartTime == 0 && in.EndTime == 0 && in.IsParticipate == -1 && in.BidWay == 0 && len(in.Source) == 0 {
  788. return 0
  789. }
  790. if in.IsParticipate == 1 {
  791. // 未参标只筛选推送表 右表条件无效
  792. return 1
  793. }
  794. if (in.StartTime != 0 || in.EndTime != 0 || len(in.Source) > 0) && (in.BidUpdateStartTime == "" && in.BidUpdateEndTime == "" && in.IsParticipate != 2) {
  795. return 1
  796. }
  797. if (in.StartTime == 0 && in.EndTime == 0 && len(in.Source) == 0) && (in.BidUpdateStartTime != "" || in.BidUpdateEndTime == "" || in.IsParticipate == 2 || in.BidWay != 0) {
  798. return 2
  799. }
  800. return 3
  801. }