ticket_generic_time.rb 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. class Report::TicketGenericTime
  3. =begin
  4. result = Report::TicketGenericTime.aggs(
  5. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  6. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  7. interval: 'month', # year, quarter, month, week, day, hour, minute, second
  8. selector: selector, # ticket selector to get only a collection of tickets
  9. params: { field: 'created_at', selector: selector_sub },
  10. timezone: 'Europe/Berlin',
  11. )
  12. returns
  13. [4,5,1,5,0,51,5,56,7,4]
  14. =end
  15. def self.aggs(params_origin)
  16. params = params_origin.dup
  17. interval_es = params[:interval]
  18. if params[:interval] == 'week'
  19. interval_es = 'day'
  20. end
  21. aggs_interval = {
  22. from: params[:range_start].iso8601,
  23. to: params[:range_end].iso8601,
  24. interval: interval_es, # year, quarter, month, week, day, hour, minute, second
  25. field: params[:params][:field],
  26. timezone: params[:timezone],
  27. }
  28. without_merged_tickets = {
  29. 'state.name' => {
  30. 'operator' => 'is not',
  31. 'value' => 'merged'
  32. }
  33. }
  34. selector = params[:selector].clone
  35. if params[:params].present? && params[:params][:selector].present?
  36. selector = selector.merge(params[:params][:selector])
  37. end
  38. selector.merge!(without_merged_tickets) # do not show merged tickets in reports
  39. result_es = SearchIndexBackend.selectors('Ticket', selector, { current_user: params[:current_user] }, aggs_interval)
  40. case params[:interval]
  41. when 'month'
  42. stop_interval = 12
  43. when 'week'
  44. stop_interval = 7
  45. when 'day'
  46. stop_interval = ((params[:range_end] - params[:range_start]) / 86_400).to_i + 1
  47. when 'hour'
  48. stop_interval = 24
  49. when 'minute'
  50. stop_interval = 60
  51. end
  52. result = []
  53. (1..stop_interval).each do |_counter|
  54. match = false
  55. if !result_es
  56. raise "Invalid es result #{result_es.inspect}"
  57. end
  58. if !result_es['aggregations']
  59. raise "Invalid es result, no aggregations #{result_es.inspect}"
  60. end
  61. if !result_es['aggregations']['time_buckets']
  62. raise "Invalid es result, no time_buckets #{result_es.inspect}"
  63. end
  64. if !result_es['aggregations']['time_buckets']['buckets']
  65. raise "Invalid es result, no buckets #{result_es.inspect}"
  66. end
  67. result_es['aggregations']['time_buckets']['buckets'].each do |item|
  68. key_as_string = Time.zone.parse(item['key_as_string'])
  69. next if !item['doc_count']
  70. next if item['doc_count'].zero?
  71. # only compare date - in certain cases elasticsearch timezone offset will not match
  72. replace = ':\d\dZ$'
  73. case params[:interval]
  74. when 'month'
  75. replace = '\d\dT\d\d:\d\d:\d\dZ$'
  76. when 'day', 'week'
  77. replace = '\d\d:\d\d:\d\dZ$'
  78. end
  79. next if key_as_string.iso8601.sub(%r{#{replace}}, '') != params[:range_start].iso8601.sub(%r{#{replace}}, '')
  80. next if match
  81. match = true
  82. result.push item['doc_count']
  83. case params[:interval]
  84. when 'month'
  85. params[:range_start] = params[:range_start].next_month
  86. when 'week', 'day'
  87. params[:range_start] = params[:range_start].next_day
  88. when 'hour'
  89. params[:range_start] = params[:range_start] + 1.hour
  90. when 'minute'
  91. params[:range_start] = params[:range_start] + 1.minute
  92. end
  93. end
  94. next if match
  95. result.push 0
  96. case params[:interval]
  97. when 'month'
  98. params[:range_start] = params[:range_start].next_month
  99. when 'week'
  100. params[:range_start] = params[:range_start].next_day
  101. when 'day'
  102. params[:range_start] = params[:range_start] + 1.day
  103. when 'hour'
  104. params[:range_start] = params[:range_start] + 1.hour
  105. when 'minute'
  106. params[:range_start] = params[:range_start] + 1.minute
  107. end
  108. end
  109. result
  110. end
  111. =begin
  112. result = Report::TicketGenericTime.items(
  113. range_start: Time.zone.parse('2015-01-01T00:00:00Z'),
  114. range_end: Time.zone.parse('2015-12-31T23:59:59Z'),
  115. selector: selector, # ticket selector to get only a collection of tickets
  116. params: { field: 'created_at' },
  117. )
  118. returns
  119. {
  120. count: 123,
  121. ticket_ids: [4,5,1,5,0,51,5,56,7,4],
  122. assets: assets,
  123. }
  124. =end
  125. def self.items(params)
  126. aggs_interval = {
  127. from: params[:range_start].iso8601,
  128. to: params[:range_end].iso8601,
  129. field: params[:params][:field],
  130. }
  131. limit = 6000
  132. if params[:sheet].blank?
  133. limit = 100
  134. end
  135. without_merged_tickets = {
  136. 'state.name' => {
  137. 'operator' => 'is not',
  138. 'value' => 'merged'
  139. }
  140. }
  141. selector = params[:selector].clone
  142. if params[:params] && params[:params][:selector]
  143. selector = selector.merge(params[:params][:selector])
  144. end
  145. selector.merge!(without_merged_tickets) # do not show merged tickets in reports
  146. result = SearchIndexBackend.selectors('Ticket', selector, { current_user: params[:current_user], limit: limit }, aggs_interval)
  147. return result if params[:sheet].present?
  148. assets = {}
  149. result[:ticket_ids].each do |ticket_id|
  150. suppress(ActiveRecord::RecordNotFound) do
  151. ticket_full = Ticket.find(ticket_id)
  152. assets = ticket_full.assets(assets)
  153. end
  154. end
  155. result[:assets] = assets
  156. result
  157. end
  158. end