2022-01-01 13:38:12 +00:00
|
|
|
# Copyright (C) 2012-2022 Zammad Foundation, https://zammad-foundation.org/
|
2021-06-01 12:20:20 +00:00
|
|
|
|
2015-10-20 08:48:43 +00:00
|
|
|
class ReportsController < ApplicationController
|
2020-03-19 09:39:51 +00:00
|
|
|
prepend_before_action { authentication_check && authorize! }
|
2015-10-20 08:48:43 +00:00
|
|
|
|
|
|
|
# GET /api/reports/config
|
2015-10-29 15:19:31 +00:00
|
|
|
def reporting_config
|
2016-11-09 14:05:18 +00:00
|
|
|
if !Report.enabled?
|
|
|
|
render json: {
|
2021-12-07 09:55:00 +00:00
|
|
|
error: __('Elasticsearch needs to be configured!'),
|
2016-11-09 14:05:18 +00:00
|
|
|
}
|
|
|
|
return
|
|
|
|
end
|
2015-10-20 08:48:43 +00:00
|
|
|
render json: {
|
2018-12-19 17:31:51 +00:00
|
|
|
config: Report.config,
|
2015-10-20 08:48:43 +00:00
|
|
|
profiles: Report::Profile.list,
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
# GET /api/reports/generate
|
|
|
|
def generate
|
2015-10-29 02:33:36 +00:00
|
|
|
get_params = params_all
|
|
|
|
return if !get_params
|
|
|
|
|
2021-11-29 14:21:47 +00:00
|
|
|
begin
|
|
|
|
result = {}
|
|
|
|
get_params[:metric][:backend].each do |backend|
|
|
|
|
condition = get_params[:profile].condition
|
|
|
|
if backend[:condition]
|
|
|
|
backend[:condition].merge(condition)
|
|
|
|
else
|
|
|
|
backend[:condition] = condition
|
|
|
|
end
|
|
|
|
next if !backend[:adapter]
|
|
|
|
|
|
|
|
result[backend[:name]] = backend[:adapter].aggs(
|
|
|
|
range_start: get_params[:start],
|
|
|
|
range_end: get_params[:stop],
|
|
|
|
interval: get_params[:range],
|
|
|
|
selector: backend[:condition],
|
|
|
|
params: backend[:params],
|
|
|
|
timezone: get_params[:timezone],
|
|
|
|
timezone_offset: get_params[:timezone_offset],
|
|
|
|
current_user: current_user
|
|
|
|
)
|
|
|
|
end
|
|
|
|
rescue => e
|
|
|
|
if e.message.include? 'Conflicting date range'
|
|
|
|
raise Exceptions::UnprocessableEntity, __('Conflicting date ranges. Please check your selected report profile.')
|
2015-10-29 02:33:36 +00:00
|
|
|
end
|
2021-11-29 14:21:47 +00:00
|
|
|
|
|
|
|
raise e
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2015-10-29 02:33:36 +00:00
|
|
|
|
2015-10-20 08:48:43 +00:00
|
|
|
render json: {
|
2015-10-29 02:33:36 +00:00
|
|
|
data: result
|
2015-10-20 08:48:43 +00:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
# GET /api/reports/sets
|
|
|
|
def sets
|
2015-10-29 02:33:36 +00:00
|
|
|
get_params = params_all
|
|
|
|
return if !get_params
|
|
|
|
|
|
|
|
if !params[:downloadBackendSelected]
|
|
|
|
render json: {
|
2021-11-15 15:58:19 +00:00
|
|
|
error: __('No such downloadBackendSelected param'),
|
2015-10-29 02:33:36 +00:00
|
|
|
}, status: :unprocessable_entity
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
# get data
|
|
|
|
result = {}
|
2019-09-16 20:36:03 +00:00
|
|
|
excel = nil
|
2019-06-24 07:28:34 +00:00
|
|
|
filename = nil
|
2017-10-01 12:25:52 +00:00
|
|
|
get_params[:metric][:backend].each do |backend|
|
2015-10-29 02:33:36 +00:00
|
|
|
next if params[:downloadBackendSelected] != backend[:name]
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2015-10-29 02:33:36 +00:00
|
|
|
condition = get_params[:profile].condition
|
|
|
|
if backend[:condition]
|
|
|
|
backend[:condition].merge(condition)
|
|
|
|
else
|
|
|
|
backend[:condition] = condition
|
|
|
|
end
|
|
|
|
next if !backend[:adapter]
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2015-10-29 02:33:36 +00:00
|
|
|
result = backend[:adapter].items(
|
2019-03-26 00:17:17 +00:00
|
|
|
range_start: get_params[:start],
|
|
|
|
range_end: get_params[:stop],
|
|
|
|
interval: get_params[:range],
|
|
|
|
selector: backend[:condition],
|
|
|
|
params: backend[:params],
|
|
|
|
sheet: params[:sheet],
|
|
|
|
timezone: get_params[:timezone],
|
|
|
|
timezone_offset: get_params[:timezone_offset],
|
2020-10-07 14:53:52 +00:00
|
|
|
current_user: current_user
|
2015-10-29 02:33:36 +00:00
|
|
|
)
|
2015-10-29 15:19:31 +00:00
|
|
|
|
2018-04-27 13:35:20 +00:00
|
|
|
result = { count: 0, ticket_ids: [] } if result.nil?
|
|
|
|
|
2015-10-29 15:19:31 +00:00
|
|
|
# generate sheet
|
2019-06-24 07:28:34 +00:00
|
|
|
if params[:sheet]
|
2019-09-16 20:36:03 +00:00
|
|
|
excel = ExcelSheet::Ticket.new(
|
|
|
|
title: "#{get_params[:profile].name} (#{backend[:display]})",
|
|
|
|
ticket_ids: result[:ticket_ids],
|
|
|
|
timezone: params[:timezone],
|
|
|
|
locale: current_user.locale,
|
|
|
|
)
|
2019-06-24 07:28:34 +00:00
|
|
|
filename = "tickets-#{get_params[:profile].name}-#{backend[:display]}.xls"
|
|
|
|
end
|
|
|
|
break
|
|
|
|
end
|
2019-09-16 20:36:03 +00:00
|
|
|
if excel
|
2015-10-29 15:19:31 +00:00
|
|
|
send_data(
|
2019-09-16 20:36:03 +00:00
|
|
|
excel.content,
|
2019-06-24 07:28:34 +00:00
|
|
|
filename: filename,
|
2018-12-19 17:31:51 +00:00
|
|
|
type: 'application/vnd.ms-excel',
|
2015-10-29 15:19:31 +00:00
|
|
|
disposition: 'attachment'
|
|
|
|
)
|
2019-06-24 07:28:34 +00:00
|
|
|
return
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2015-10-29 15:19:31 +00:00
|
|
|
|
2015-10-29 02:33:36 +00:00
|
|
|
render json: result
|
|
|
|
end
|
|
|
|
|
|
|
|
def params_all
|
|
|
|
profile = nil
|
2015-10-29 15:19:31 +00:00
|
|
|
if !params[:profiles] && !params[:profile_id]
|
2021-11-15 15:58:19 +00:00
|
|
|
raise Exceptions::UnprocessableEntity, __('No such profiles param')
|
2015-10-29 02:33:36 +00:00
|
|
|
end
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2015-10-29 15:19:31 +00:00
|
|
|
if params[:profile_id]
|
|
|
|
profile = Report::Profile.find(params[:profile_id])
|
|
|
|
else
|
2017-10-01 12:25:52 +00:00
|
|
|
params[:profiles].each do |profile_id, active|
|
2015-10-29 15:19:31 +00:00
|
|
|
next if !active
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2015-10-29 15:19:31 +00:00
|
|
|
profile = Report::Profile.find(profile_id)
|
2017-10-01 12:25:52 +00:00
|
|
|
end
|
2015-10-29 15:19:31 +00:00
|
|
|
end
|
2015-10-29 02:33:36 +00:00
|
|
|
if !profile
|
2021-11-15 15:58:19 +00:00
|
|
|
raise Exceptions::UnprocessableEntity, __('No such active profile')
|
2015-10-29 02:33:36 +00:00
|
|
|
end
|
|
|
|
|
2015-10-29 15:19:31 +00:00
|
|
|
local_config = Report.config
|
|
|
|
if !local_config || !local_config[:metric] || !local_config[:metric][params[:metric].to_sym]
|
2016-06-30 08:24:03 +00:00
|
|
|
raise Exceptions::UnprocessableEntity, "No such metric #{params[:metric]}"
|
2015-10-29 02:33:36 +00:00
|
|
|
end
|
2018-10-09 06:17:41 +00:00
|
|
|
|
2015-10-29 15:19:31 +00:00
|
|
|
metric = local_config[:metric][params[:metric].to_sym]
|
2015-10-29 02:33:36 +00:00
|
|
|
|
2020-07-13 12:46:08 +00:00
|
|
|
case params[:timeRange]
|
|
|
|
when 'realtime'
|
2019-03-26 00:17:17 +00:00
|
|
|
start_at = (Time.zone.now - 60.minutes)
|
|
|
|
stop_at = Time.zone.now
|
2015-10-29 02:33:36 +00:00
|
|
|
range = 'minute'
|
2020-07-13 12:46:08 +00:00
|
|
|
when 'day'
|
2015-10-20 09:31:08 +00:00
|
|
|
date = Date.parse("#{params[:year]}-#{params[:month]}-#{params[:day]}").to_s
|
2019-03-26 00:17:17 +00:00
|
|
|
start_at = Time.zone.parse("#{date}T00:00:00Z")
|
|
|
|
stop_at = Time.zone.parse("#{date}T23:59:59Z")
|
2015-10-29 02:33:36 +00:00
|
|
|
range = 'hour'
|
2020-07-13 12:46:08 +00:00
|
|
|
when 'week'
|
2019-03-26 00:17:17 +00:00
|
|
|
start_week_at = Date.commercial(params[:year].to_i, params[:week].to_i)
|
|
|
|
stop_week_at = start_week_at.end_of_week
|
|
|
|
start_at = Time.zone.parse("#{start_week_at.year}-#{start_week_at.month}-#{start_week_at.day}T00:00:00Z")
|
|
|
|
stop_at = Time.zone.parse("#{stop_week_at.year}-#{stop_week_at.month}-#{stop_week_at.day}T23:59:59Z")
|
2015-10-29 02:33:36 +00:00
|
|
|
range = 'week'
|
2020-07-13 12:46:08 +00:00
|
|
|
when 'month'
|
2019-03-26 00:17:17 +00:00
|
|
|
start_at = Time.zone.parse("#{params[:year]}-#{params[:month]}-01T00:00:00Z")
|
|
|
|
stop_at = Time.zone.parse("#{params[:year]}-#{params[:month]}-#{start_at.end_of_month.day}T23:59:59Z")
|
2015-10-29 02:33:36 +00:00
|
|
|
range = 'day'
|
2015-10-20 08:48:43 +00:00
|
|
|
else
|
2019-03-26 00:17:17 +00:00
|
|
|
start_at = Time.zone.parse("#{params[:year]}-01-01T00:00:00Z")
|
|
|
|
stop_at = Time.zone.parse("#{params[:year]}-12-31T23:59:59Z")
|
2016-11-09 14:05:18 +00:00
|
|
|
range = 'month'
|
2015-10-20 08:48:43 +00:00
|
|
|
end
|
2019-03-26 00:17:17 +00:00
|
|
|
params[:timezone] ||= Setting.get('timezone_default')
|
|
|
|
if params[:timezone].present? && params[:timeRange] != 'realtime'
|
|
|
|
offset = stop_at.in_time_zone(params[:timezone]).utc_offset
|
|
|
|
start_at -= offset
|
|
|
|
stop_at -= offset
|
|
|
|
end
|
|
|
|
|
2015-10-29 02:33:36 +00:00
|
|
|
{
|
2019-03-26 00:17:17 +00:00
|
|
|
profile: profile,
|
|
|
|
metric: metric,
|
|
|
|
config: local_config,
|
|
|
|
start: start_at,
|
|
|
|
stop: stop_at,
|
|
|
|
range: range,
|
|
|
|
timezone: params[:timezone],
|
|
|
|
timezone_offset: offset,
|
2015-10-20 08:48:43 +00:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|