reports_controller.rb 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. # Copyright (C) 2012-2014 Zammad Foundation, http://zammad-foundation.org/
  2. require 'tempfile'
  3. class ReportsController < ApplicationController
  4. before_action :authentication_check
  5. # GET /api/reports/config
  6. def reporting_config
  7. return if deny_if_not_role('Report')
  8. render json: {
  9. config: Report.config,
  10. profiles: Report::Profile.list,
  11. }
  12. end
  13. # GET /api/reports/generate
  14. def generate
  15. return if deny_if_not_role('Report')
  16. get_params = params_all
  17. return if !get_params
  18. result = {}
  19. get_params[:metric][:backend].each {|backend|
  20. condition = get_params[:profile].condition
  21. if backend[:condition]
  22. backend[:condition].merge(condition)
  23. else
  24. backend[:condition] = condition
  25. end
  26. next if !backend[:adapter]
  27. result[backend[:name]] = backend[:adapter].aggs(
  28. range_start: get_params[:start],
  29. range_end: get_params[:stop],
  30. interval: get_params[:range],
  31. selector: backend[:condition],
  32. params: backend[:params],
  33. )
  34. }
  35. #created = aggs(start, stop, range, 'created_at', profile.condition)
  36. #closed = aggs(start, stop, range, 'close_time', profile.condition)
  37. #first_solution =
  38. #reopend = backend(start, stop, range, Report::TicketReopened, profile.condition)
  39. # add backlog
  40. #backlogs = []
  41. #position = -1
  42. #created.each {|_not_used|
  43. # position += 1
  44. # diff = created[position][1] - closed[position][1]
  45. # backlog = [position+1, diff]
  46. # backlogs.push backlog
  47. #}
  48. render json: {
  49. data: result
  50. }
  51. end
  52. # GET /api/reports/sets
  53. def sets
  54. return if deny_if_not_role('Report')
  55. get_params = params_all
  56. return if !get_params
  57. if !params[:downloadBackendSelected]
  58. render json: {
  59. error: 'No such downloadBackendSelected param',
  60. }, status: :unprocessable_entity
  61. return
  62. end
  63. # get data
  64. result = {}
  65. get_params[:metric][:backend].each {|backend|
  66. next if params[:downloadBackendSelected] != backend[:name]
  67. condition = get_params[:profile].condition
  68. if backend[:condition]
  69. backend[:condition].merge(condition)
  70. else
  71. backend[:condition] = condition
  72. end
  73. next if !backend[:adapter]
  74. result = backend[:adapter].items(
  75. range_start: get_params[:start],
  76. range_end: get_params[:stop],
  77. interval: get_params[:range],
  78. selector: backend[:condition],
  79. params: backend[:params],
  80. sheet: params[:sheet],
  81. )
  82. # generate sheet
  83. next if !params[:sheet]
  84. content = sheet(get_params[:profile], backend[:display], result)
  85. send_data(
  86. content,
  87. filename: "tickets-#{get_params[:profile].name}-#{backend[:display]}.xls",
  88. type: 'application/vnd.ms-excel',
  89. disposition: 'attachment'
  90. )
  91. }
  92. return if params[:sheet]
  93. render json: result
  94. end
  95. def params_all
  96. profile = nil
  97. if !params[:profiles] && !params[:profile_id]
  98. render json: {
  99. error: 'No such profiles param',
  100. }, status: :unprocessable_entity
  101. return
  102. end
  103. if params[:profile_id]
  104. profile = Report::Profile.find(params[:profile_id])
  105. else
  106. params[:profiles].each {|profile_id, active|
  107. next if !active
  108. profile = Report::Profile.find(profile_id)
  109. }
  110. end
  111. if !profile
  112. render json: {
  113. error: 'No such active profile',
  114. }, status: :unprocessable_entity
  115. return
  116. end
  117. local_config = Report.config
  118. if !local_config || !local_config[:metric] || !local_config[:metric][params[:metric].to_sym]
  119. render json: {
  120. error: "No such metric #{params[:metric]}"
  121. }, status: :unprocessable_entity
  122. return
  123. end
  124. metric = local_config[:metric][params[:metric].to_sym]
  125. #{"metric"=>"count", "year"=>2015, "month"=>10, "week"=>43, "day"=>20, "timeSlot"=>"year", "report"=>{"metric"=>"count", "year"=>2015, "month"=>10, "week"=>43, "day"=>20, "timeSlot"=>"year"}}
  126. if params[:timeRange] == 'realtime'
  127. start = (Time.zone.now - 60.minutes).iso8601
  128. stop = Time.zone.now.iso8601
  129. range = 'minute'
  130. elsif params[:timeRange] == 'day'
  131. date = Date.parse("#{params[:year]}-#{params[:month]}-#{params[:day]}").to_s
  132. start = "#{date}T00:00:00Z"
  133. stop = "#{date}T23:59:59Z"
  134. range = 'hour'
  135. elsif params[:timeRange] == 'week'
  136. start = Date.commercial(params[:year], params[:week]).iso8601
  137. stop = Date.parse(start).end_of_week
  138. range = 'week'
  139. elsif params[:timeRange] == 'month'
  140. start = Date.parse("#{params[:year]}-#{params[:month]}-01}").iso8601
  141. stop = Date.parse(start).end_of_month
  142. range = 'day'
  143. else
  144. start = "#{params[:year]}-01-01"
  145. stop_date = Date.parse(start).end_of_month
  146. stop = "#{stop_date.year}-#{stop_date.month}-#{stop_date.day}"
  147. range = 'month'
  148. end
  149. {
  150. profile: profile,
  151. metric: metric,
  152. config: local_config,
  153. start: start,
  154. stop: stop,
  155. range: range,
  156. }
  157. end
  158. def sheet(profile, title, result)
  159. # Create a new Excel workbook
  160. temp_file = Tempfile.new('time_tracking.xls')
  161. workbook = WriteExcel.new(temp_file)
  162. # Add a worksheet
  163. worksheet = workbook.add_worksheet
  164. worksheet.set_column(0, 0, 10)
  165. worksheet.set_column(1, 1, 34)
  166. worksheet.set_column(2, 2, 10)
  167. worksheet.set_column(3, 3, 10)
  168. worksheet.set_column(4, 7, 20)
  169. # Add and define a format
  170. format = workbook.add_format # Add a format
  171. format.set_bold
  172. format.set_size(14)
  173. format.set_color('black')
  174. worksheet.set_row(0, 0, 6)
  175. # Write a formatted and unformatted string, row and column notation.
  176. worksheet.write(0, 0, "Tickets: #{profile.name} (#{title})", format)
  177. format_header = workbook.add_format # Add a format
  178. format_header.set_italic
  179. format_header.set_bg_color('gray')
  180. format_header.set_color('white')
  181. worksheet.write(2, 0, '#', format_header )
  182. worksheet.write(2, 1, 'Title', format_header )
  183. worksheet.write(2, 2, 'State', format_header )
  184. worksheet.write(2, 3, 'Priority', format_header )
  185. worksheet.write(2, 4, 'Customer', format_header )
  186. worksheet.write(2, 5, 'Created at', format_header )
  187. worksheet.write(2, 6, 'Updated at', format_header )
  188. worksheet.write(2, 7, 'Closed at', format_header )
  189. row = 2
  190. result[:ticket_ids].each {|ticket_id|
  191. ticket = Ticket.lookup(id: ticket_id)
  192. row += 1
  193. worksheet.write(row, 0, ticket.number )
  194. worksheet.write(row, 1, ticket.title)
  195. worksheet.write(row, 2, ticket.state.name)
  196. worksheet.write(row, 3, ticket.priority.name)
  197. worksheet.write(row, 4, ticket.customer.fullname)
  198. worksheet.write(row, 5, ticket.created_at)
  199. worksheet.write(row, 6, ticket.updated_at)
  200. worksheet.write(row, 7, ticket.close_time)
  201. }
  202. workbook.close
  203. # read file again
  204. file = File.new(temp_file, 'r')
  205. contents = file.read
  206. file.close
  207. contents
  208. end
  209. end