participateStatistics.go 35 KB

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