reports_controller.rb 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. # Copyright (C) 2012-2016 Zammad Foundation, http://zammad-foundation.org/
  2. class ReportsController < ApplicationController
  3. prepend_before_action { authentication_check && authorize! }
  4. # GET /api/reports/config
  5. def reporting_config
  6. if !Report.enabled?
  7. render json: {
  8. error: 'Elasticsearch need to be configured!',
  9. }
  10. return
  11. end
  12. render json: {
  13. config: Report.config,
  14. profiles: Report::Profile.list,
  15. }
  16. end
  17. # GET /api/reports/generate
  18. def generate
  19. get_params = params_all
  20. return if !get_params
  21. result = {}
  22. get_params[:metric][:backend].each do |backend|
  23. condition = get_params[:profile].condition
  24. if backend[:condition]
  25. backend[:condition].merge(condition)
  26. else
  27. backend[:condition] = condition
  28. end
  29. next if !backend[:adapter]
  30. result[backend[:name]] = backend[:adapter].aggs(
  31. range_start: get_params[:start],
  32. range_end: get_params[:stop],
  33. interval: get_params[:range],
  34. selector: backend[:condition],
  35. params: backend[:params],
  36. timezone: get_params[:timezone],
  37. timezone_offset: get_params[:timezone_offset],
  38. )
  39. end
  40. render json: {
  41. data: result
  42. }
  43. end
  44. # GET /api/reports/sets
  45. def sets
  46. get_params = params_all
  47. return if !get_params
  48. if !params[:downloadBackendSelected]
  49. render json: {
  50. error: 'No such downloadBackendSelected param',
  51. }, status: :unprocessable_entity
  52. return
  53. end
  54. # get data
  55. result = {}
  56. excel = nil
  57. filename = nil
  58. get_params[:metric][:backend].each do |backend|
  59. next if params[:downloadBackendSelected] != backend[:name]
  60. condition = get_params[:profile].condition
  61. if backend[:condition]
  62. backend[:condition].merge(condition)
  63. else
  64. backend[:condition] = condition
  65. end
  66. next if !backend[:adapter]
  67. result = backend[:adapter].items(
  68. range_start: get_params[:start],
  69. range_end: get_params[:stop],
  70. interval: get_params[:range],
  71. selector: backend[:condition],
  72. params: backend[:params],
  73. sheet: params[:sheet],
  74. timezone: get_params[:timezone],
  75. timezone_offset: get_params[:timezone_offset],
  76. )
  77. result = { count: 0, ticket_ids: [] } if result.nil?
  78. # generate sheet
  79. if params[:sheet]
  80. excel = ExcelSheet::Ticket.new(
  81. title: "#{get_params[:profile].name} (#{backend[:display]})",
  82. ticket_ids: result[:ticket_ids],
  83. timezone: params[:timezone],
  84. locale: current_user.locale,
  85. )
  86. filename = "tickets-#{get_params[:profile].name}-#{backend[:display]}.xls"
  87. end
  88. break
  89. end
  90. if excel
  91. send_data(
  92. excel.content,
  93. filename: filename,
  94. type: 'application/vnd.ms-excel',
  95. disposition: 'attachment'
  96. )
  97. return
  98. end
  99. render json: result
  100. end
  101. def params_all
  102. profile = nil
  103. if !params[:profiles] && !params[:profile_id]
  104. raise Exceptions::UnprocessableEntity, 'No such profiles param'
  105. end
  106. if params[:profile_id]
  107. profile = Report::Profile.find(params[:profile_id])
  108. else
  109. params[:profiles].each do |profile_id, active|
  110. next if !active
  111. profile = Report::Profile.find(profile_id)
  112. end
  113. end
  114. if !profile
  115. raise Exceptions::UnprocessableEntity, 'No such active profile'
  116. end
  117. local_config = Report.config
  118. if !local_config || !local_config[:metric] || !local_config[:metric][params[:metric].to_sym]
  119. raise Exceptions::UnprocessableEntity, "No such metric #{params[:metric]}"
  120. end
  121. metric = local_config[:metric][params[:metric].to_sym]
  122. case params[:timeRange]
  123. when 'realtime'
  124. start_at = (Time.zone.now - 60.minutes)
  125. stop_at = Time.zone.now
  126. range = 'minute'
  127. when 'day'
  128. date = Date.parse("#{params[:year]}-#{params[:month]}-#{params[:day]}").to_s
  129. start_at = Time.zone.parse("#{date}T00:00:00Z")
  130. stop_at = Time.zone.parse("#{date}T23:59:59Z")
  131. range = 'hour'
  132. when 'week'
  133. start_week_at = Date.commercial(params[:year].to_i, params[:week].to_i)
  134. stop_week_at = start_week_at.end_of_week
  135. start_at = Time.zone.parse("#{start_week_at.year}-#{start_week_at.month}-#{start_week_at.day}T00:00:00Z")
  136. stop_at = Time.zone.parse("#{stop_week_at.year}-#{stop_week_at.month}-#{stop_week_at.day}T23:59:59Z")
  137. range = 'week'
  138. when 'month'
  139. start_at = Time.zone.parse("#{params[:year]}-#{params[:month]}-01T00:00:00Z")
  140. stop_at = Time.zone.parse("#{params[:year]}-#{params[:month]}-#{start_at.end_of_month.day}T23:59:59Z")
  141. range = 'day'
  142. else
  143. start_at = Time.zone.parse("#{params[:year]}-01-01T00:00:00Z")
  144. stop_at = Time.zone.parse("#{params[:year]}-12-31T23:59:59Z")
  145. range = 'month'
  146. end
  147. params[:timezone] ||= Setting.get('timezone_default')
  148. if params[:timezone].present? && params[:timeRange] != 'realtime'
  149. offset = stop_at.in_time_zone(params[:timezone]).utc_offset
  150. start_at -= offset
  151. stop_at -= offset
  152. end
  153. {
  154. profile: profile,
  155. metric: metric,
  156. config: local_config,
  157. start: start_at,
  158. stop: stop_at,
  159. range: range,
  160. timezone: params[:timezone],
  161. timezone_offset: offset,
  162. }
  163. end
  164. end