report.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. package service
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "strconv"
  7. "time"
  8. "go-common/app/admin/main/aegis/model"
  9. "go-common/library/ecode"
  10. "go-common/library/log"
  11. )
  12. //ReportTaskflow .
  13. func (s *Service) ReportTaskflow(c context.Context, opt *model.OptReport) (res map[string][]*model.ReportFlowItem, form map[string][24]*model.ReportFlowItem, err error) {
  14. // TODO 从redis 补充实时增量
  15. var (
  16. mnames map[int64]string
  17. metas []*model.ReportMeta
  18. )
  19. // 取出统计元数据
  20. mnames, metas, err = s.reportMeta(c, opt)
  21. if err != nil {
  22. return
  23. }
  24. tempres := model.Gentempres(opt, mnames, metas)
  25. res = model.Genres(opt, tempres, mnames)
  26. form = model.Genform(res)
  27. return
  28. }
  29. //MemberStats . 统计个人24h 处理量 处理率 通过率 平均耗时
  30. func (s *Service) MemberStats(c context.Context, bizid, flowid int64, uids []int64) (res map[int64][]interface{}, err error) {
  31. var (
  32. metas []*model.ReportMeta
  33. opt = &model.OptReport{
  34. BizID: bizid,
  35. FlowID: flowid,
  36. Type: model.TypeMeta,
  37. }
  38. passState = s.passState(bizid, flowid)
  39. )
  40. if _, metas, err = s.reportMeta(c, opt); err != nil {
  41. return
  42. }
  43. return model.GenMemberStat(metas, passState)
  44. }
  45. //MemberStats . 统计个人24h 处理量 处理率 通过率 平均耗时
  46. func (s *Service) parseOption(c context.Context, opt *model.OptReport) (uids []int64, mnames map[int64]string, err error) {
  47. var muids map[string]int64
  48. mnames = make(map[int64]string)
  49. bTime, _ := time.ParseInLocation("2006-01-02", opt.Bt, time.Local)
  50. eTime, _ := time.ParseInLocation("2006-01-02", opt.Et, time.Local)
  51. switch {
  52. case bTime.IsZero() && eTime.IsZero():
  53. bTime = time.Now().Add(-24 * time.Hour)
  54. eTime = time.Now()
  55. case bTime.IsZero() && !eTime.IsZero():
  56. bTime = eTime.Add(-24 * time.Hour)
  57. case !bTime.IsZero() && eTime.IsZero():
  58. eTime = bTime.Add(24 * time.Hour)
  59. }
  60. eTime = eTime.Add(+1 * time.Hour)
  61. opt.Btime, opt.Etime = bTime, eTime
  62. opt.Bt, opt.Et = bTime.Format("2006-01-02 15"), eTime.Format("2006-01-02 15")
  63. if bTime.After(eTime) {
  64. err = ecode.RequestErr
  65. return
  66. }
  67. if len(opt.UName) > 0 {
  68. if muids, err = s.http.GetUIDs(c, opt.UName); err != nil {
  69. return
  70. }
  71. for name, uid := range muids {
  72. uids = append(uids, uid)
  73. mnames[uid] = name
  74. }
  75. }
  76. return
  77. }
  78. func (s *Service) reportMeta(c context.Context, opt *model.OptReport) (mnames map[int64]string, metas []*model.ReportMeta, err error) {
  79. // TODO 从redis 补充实时增量
  80. var (
  81. uids []int64
  82. )
  83. uids, mnames, err = s.parseOption(c, opt)
  84. if err != nil {
  85. return
  86. }
  87. // 取出统计元数据
  88. metas, missuids, err := s.gorm.ReportTaskMetas(c, opt.Bt, opt.Et, opt.BizID, opt.FlowID, uids, mnames, opt.Type)
  89. if err != nil {
  90. return
  91. }
  92. if len(missuids) > 0 && opt.Type == model.TypeMeta {
  93. var tunames map[int64]string
  94. if tunames, err = s.http.GetUnames(c, missuids); err != nil {
  95. return
  96. }
  97. for uid, uname := range tunames {
  98. mnames[uid] = uname
  99. }
  100. }
  101. return
  102. }
  103. //TODO 根据业务配置,获取通过状态号
  104. func (s *Service) passState(bizid, flowid int64) int64 {
  105. return 1
  106. }
  107. //ReportTaskSubmit 业务节点下的任务提交统计信息, 按天分页
  108. func (s *Service) ReportTaskSubmit(c context.Context, pm *model.OptReportSubmit) (res *model.ReportSubmitRes, err error) {
  109. var (
  110. datas []*model.TaskReport
  111. states map[string]string
  112. unames map[int64]string
  113. uids = []int64{}
  114. dayUID = int64(-1)
  115. dayUname = "ALL"
  116. groups = [][]*model.ReportSubmitItem{} //{stat_date:[]obj}
  117. creates = map[string]string{} //{bizid_flowid_statdate:cnt}
  118. stateOrderUnique = map[string]string{}
  119. )
  120. res = &model.ReportSubmitRes{}
  121. //取出元数据: 状态名 + 操作提交数据
  122. if datas, err = s.gorm.TaskReports(c, pm.BizID, pm.FlowID,
  123. []int8{model.TypeCreate, model.TypeDaySubmit, model.TypeDayUserSubmit},
  124. pm.Bt, pm.Et); err != nil || len(datas) == 0 {
  125. return
  126. }
  127. if states, err = s.TokenByName(c, pm.BizID, "state"); err != nil {
  128. return
  129. }
  130. prevDate := ""
  131. groupItems := []*model.ReportSubmitItem{}
  132. for _, item := range datas {
  133. statdate := item.StatDate.Format("2006-01-02")
  134. //每日任务增量
  135. if item.Type == model.TypeCreate {
  136. creates[fmt.Sprintf("%d_%s", item.FlowID, statdate)] = item.Content
  137. continue
  138. }
  139. //每日uid维度的提交数据
  140. if item.Type == model.TypeDaySubmit {
  141. item.UID = dayUID
  142. } else {
  143. uids = append(uids, item.UID)
  144. }
  145. content := &model.ReportSubmitContent{}
  146. if err = json.Unmarshal([]byte(item.Content), content); err != nil {
  147. log.Error("ReportTaskSubmit json.Unmarshal(%s) error(%v), for id(%d)", item.Content, err, item.ID)
  148. continue
  149. }
  150. submitCnt := int64(0)
  151. statecnt := map[string]*model.ReportSubmitState{}
  152. for state, cnt := range content.RscStates {
  153. submitCnt = submitCnt + cnt
  154. statecnt[state] = &model.ReportSubmitState{
  155. Cnt: cnt,
  156. }
  157. if _, exist := stateOrderUnique[state]; !exist {
  158. stateOrderUnique[state] = states[state]
  159. }
  160. }
  161. //各状态的提交量所占比率
  162. for _, one := range statecnt {
  163. one.Ratio = fmt.Sprintf("%.2f", float64(one.Cnt)/float64(submitCnt))
  164. }
  165. if prevDate == "" {
  166. prevDate = statdate
  167. }
  168. if prevDate != statdate {
  169. groups = append(groups, groupItems)
  170. groupItems = []*model.ReportSubmitItem{}
  171. prevDate = statdate
  172. }
  173. groupItems = append(groupItems, &model.ReportSubmitItem{
  174. StatDate: statdate,
  175. UID: item.UID,
  176. AvgDur: time.Unix(content.AvgDur, 0).In(time.UTC).Format("15:04:05"),
  177. AvgUtime: time.Unix(content.AvgUtime, 0).In(time.UTC).Format("15:04:05"),
  178. FlowID: item.FlowID,
  179. SubmitCnt: submitCnt,
  180. StateCnt: statecnt,
  181. })
  182. }
  183. if len(groupItems) > 0 {
  184. groups = append(groups, groupItems)
  185. }
  186. //get usernames
  187. unames, _ = s.http.GetUnames(c, uids)
  188. res.Order = []string{
  189. "state_date",
  190. "create_cnt",
  191. "username",
  192. "avg_dur",
  193. "avg_utime",
  194. "submit_cnt",
  195. }
  196. res.Header = map[string]string{
  197. "state_date": "日期",
  198. "create_cnt": "新增量",
  199. "username": "操作人",
  200. "avg_dur": "平均耗时",
  201. "avg_utime": "平均停留时间",
  202. "submit_cnt": "操作总量",
  203. }
  204. res.Rows = make([][]map[string]string, len(groups))
  205. for state, name := range stateOrderUnique {
  206. cnt := fmt.Sprintf("state_%s_cnt", state)
  207. ratio := fmt.Sprintf("state_%s_ratio", state)
  208. res.Header[cnt] = fmt.Sprintf("%s量", name)
  209. res.Header[ratio] = fmt.Sprintf("%s率", name)
  210. res.Order = append(res.Order, cnt, ratio)
  211. }
  212. for i, list := range groups {
  213. res.Rows[i] = make([]map[string]string, len(list))
  214. for j, item := range list {
  215. uname := strconv.FormatInt(item.UID, 10)
  216. create := "0"
  217. if item.UID == dayUID {
  218. create = creates[fmt.Sprintf("%d_%s", item.FlowID, item.StatDate)]
  219. uname = dayUname
  220. } else if v, exist := unames[item.UID]; exist {
  221. uname = v
  222. }
  223. one := map[string]string{
  224. "state_date": item.StatDate,
  225. "create_cnt": create,
  226. "username": uname,
  227. "avg_dur": item.AvgDur,
  228. "avg_utime": item.AvgUtime,
  229. "submit_cnt": strconv.FormatInt(item.SubmitCnt, 10),
  230. }
  231. for state := range stateOrderUnique {
  232. cnt := "0"
  233. ration := "0.00"
  234. if v, exist := item.StateCnt[state]; exist {
  235. cnt = strconv.FormatInt(v.Cnt, 10)
  236. ration = v.Ratio
  237. }
  238. one[fmt.Sprintf("state_%s_cnt", state)] = cnt
  239. one[fmt.Sprintf("state_%s_ratio", state)] = ration
  240. }
  241. res.Rows[i][j] = one
  242. }
  243. }
  244. return
  245. }