Next features for mini reporting.
This commit is contained in:
parent
eaa266ec50
commit
b9a5de081e
14 changed files with 2042 additions and 233 deletions
|
@ -87,8 +87,6 @@ class Graph extends App.ControllerContent
|
|||
constructor: ->
|
||||
super
|
||||
|
||||
return
|
||||
|
||||
# rerender view
|
||||
@bind 'ui:report:rerender', =>
|
||||
@render()
|
||||
|
@ -98,7 +96,14 @@ class Graph extends App.ControllerContent
|
|||
render: =>
|
||||
|
||||
update = (data) =>
|
||||
@draw(data.data)
|
||||
|
||||
# show only selected lines
|
||||
dataNew = {}
|
||||
for key, value of data.data
|
||||
if @params.backendSelected[key] is true
|
||||
dataNew[key] = value
|
||||
|
||||
@draw(dataNew)
|
||||
t = new Date
|
||||
@el.find('#download-chart').html(t.toString())
|
||||
new Download(
|
||||
|
@ -109,19 +114,20 @@ class Graph extends App.ControllerContent
|
|||
)
|
||||
|
||||
url = @apiPath + '/reports/generate'
|
||||
interval = 60000
|
||||
interval = 5 * 60000
|
||||
if @params.timeRange is 'year'
|
||||
interval = 30000
|
||||
interval = 5 * 60000
|
||||
if @params.timeRange is 'month'
|
||||
interval = 20000
|
||||
interval = 60000
|
||||
if @params.timeRange is 'week'
|
||||
interval = 20000
|
||||
interval = 40000
|
||||
if @params.timeRange is 'day'
|
||||
interval = 20000
|
||||
if @params.timeRange is 'realtime'
|
||||
interval = 10000
|
||||
|
||||
@ajax(
|
||||
id: 'report_graph'
|
||||
type: 'POST'
|
||||
url: url
|
||||
data: JSON.stringify(
|
||||
|
@ -137,7 +143,7 @@ class Graph extends App.ControllerContent
|
|||
processData: true
|
||||
success: (data) =>
|
||||
update(data)
|
||||
@delay( @render, interval, 'report-update', 'page' )
|
||||
@delay(@render, interval, 'report-update', 'page')
|
||||
)
|
||||
|
||||
draw: (data) =>
|
||||
|
@ -162,10 +168,22 @@ class Graph extends App.ControllerContent
|
|||
|
||||
dataPlot = []
|
||||
for key, value of data
|
||||
realname = key
|
||||
if @config.metric[@params.metric]
|
||||
for backend in @config.metric[@params.metric].backend
|
||||
if backend.name is key
|
||||
realname = backend.display
|
||||
content = []
|
||||
count = 0
|
||||
for i in xaxis
|
||||
content.push [count, value[count]]
|
||||
count += 1
|
||||
|
||||
dataPlot.push {
|
||||
data: value
|
||||
label: key
|
||||
data: content
|
||||
label: App.i18n.translateInline(realname)
|
||||
}
|
||||
|
||||
# plot
|
||||
$.plot( $('#placeholder'), dataPlot, {
|
||||
yaxis: { min: 0 },
|
||||
|
@ -190,12 +208,10 @@ class Download extends App.Controller
|
|||
reports = []
|
||||
|
||||
# select first backend, if no backend is selected
|
||||
@backendSelected = undefined
|
||||
if @config.metric[@params.metric]
|
||||
for backend in @config.metric[@params.metric].backend
|
||||
console.log('bac', backend)
|
||||
if backend.dataDownload && !@backendSelected
|
||||
@backendSelected = backend.name
|
||||
if backend.dataDownload && !@params.downloadBackendSelected
|
||||
@params.downloadBackendSelected = backend.name
|
||||
|
||||
# get used profiles
|
||||
profiles = []
|
||||
|
@ -206,10 +222,10 @@ class Download extends App.Controller
|
|||
profiles.push App.ReportProfile.find(key)
|
||||
|
||||
@html App.view('report/download_header')(
|
||||
reports: reports
|
||||
profiles: profiles
|
||||
backendSelected: @backendSelected
|
||||
metric: @config.metric[@params.metric]
|
||||
reports: reports
|
||||
profiles: profiles
|
||||
downloadBackendSelected: @params.downloadBackendSelected
|
||||
metric: @config.metric[@params.metric]
|
||||
)
|
||||
|
||||
@tableUpdate()
|
||||
|
@ -219,8 +235,8 @@ class Download extends App.Controller
|
|||
e.preventDefault()
|
||||
@el.find('.js-dataDownloadBackendSelector').parent().removeClass('active')
|
||||
$(e.target).parent().addClass('active')
|
||||
@profileSelectedId = $(e.target).data('profile-id')
|
||||
@backendSelected = $(e.target).data('backend')
|
||||
@profileSelectedId = $(e.target).data('profile-id')
|
||||
@params.downloadBackendSelected = $(e.target).data('backend')
|
||||
|
||||
table = (tickets, count) =>
|
||||
url = '#ticket/zoom/'
|
||||
|
@ -239,17 +255,19 @@ class Download extends App.Controller
|
|||
|
||||
@startLoading()
|
||||
@ajax(
|
||||
id: 'report_download'
|
||||
type: 'POST'
|
||||
url: @apiPath + '/reports/sets'
|
||||
data: JSON.stringify(
|
||||
metric: @params.metric
|
||||
year: @params.year
|
||||
month: @params.month
|
||||
week: @params.week
|
||||
day: @params.day
|
||||
timeRange: @params.timeRange
|
||||
profile_id: @profileSelectedId
|
||||
backend: @backendSelected
|
||||
metric: @params.metric
|
||||
year: @params.year
|
||||
month: @params.month
|
||||
week: @params.week
|
||||
day: @params.day
|
||||
timeRange: @params.timeRange
|
||||
profiles: @params.profileSelected
|
||||
backends: @params.backendSelected
|
||||
downloadBackendSelected: @params.downloadBackendSelected
|
||||
)
|
||||
processData: true
|
||||
success: (data) =>
|
||||
|
@ -433,7 +451,7 @@ class Sidebar extends App.Controller
|
|||
events:
|
||||
'click .js-profileSelector': 'selectProfile'
|
||||
'click .js-backendSelector': 'selectBackend'
|
||||
'click .panel-heading': 'selectMetric'
|
||||
'click .panel-heading': 'selectMetric'
|
||||
|
||||
constructor: ->
|
||||
super
|
||||
|
@ -459,11 +477,10 @@ class Sidebar extends App.Controller
|
|||
|
||||
selectProfile: (e) =>
|
||||
profile_id = $(e.target).val()
|
||||
active = $(e.target).prop('checked')
|
||||
if active
|
||||
@params.profileSelected[profile_id] = true
|
||||
else
|
||||
delete @params.profileSelected[profile_id]
|
||||
console.log('llll', profile_id)
|
||||
for key, value of @params.profileSelected
|
||||
delete @params.profileSelected[key]
|
||||
@params.profileSelected[profile_id] = true
|
||||
App.Event.trigger( 'ui:report:rerender' )
|
||||
|
||||
selectBackend: (e) =>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<% for profile in @profiles: %>
|
||||
<% for backend in @metric.backend: %>
|
||||
<% if backend.dataDownload: %>
|
||||
<li <% if backend.name is @backendSelected: %>class="is-active active"<% end %>><a href="#" class="js-dataDownloadBackendSelector" data-toggle="tab" data-profile-id="<%= profile.id %>" data-backend="<%= backend.name %>"><%= @T(backend.display) %></a></li>
|
||||
<li <% if backend.name is @downloadBackendSelected: %>class="is-active active"<% end %>><a href="#" class="js-dataDownloadBackendSelector" data-toggle="tab" data-profile-id="<%= profile.id %>" data-backend="<%= backend.name %>"><%= @T(backend.display) %></a></li>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<i><%- @T('%s records', @count) %></i>
|
||||
<a href="<%- @download %>" target="_blank" data-type="attachment" id="downloadsetascsv"><%- @Icon('download') %></a>
|
||||
<a href="<%- @download %>" target="_blank" data-type="attachment"><%- @Icon('download') %></a>
|
||||
<table class="table table-striped table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="main flex">
|
||||
|
||||
<div class="page-header page-header--center">
|
||||
<div class="page-header">
|
||||
<div class="page-header-title">
|
||||
<h1><%- @T( 'Reporting' ) %> <small></small></h1>
|
||||
</div>
|
||||
|
@ -12,17 +12,9 @@
|
|||
<div class="page-main">
|
||||
<div class="js-timeRangePicker"></div>
|
||||
<div class="page-content">
|
||||
|
||||
|
||||
<div id="placeholder" class="" style="height:350px;"></div>
|
||||
<span class=" muted" id="download-chart" style="font-size: 8px;"></span>
|
||||
<!--
|
||||
<a href="<%-@download%>" target="_blank" data-type="attachment" class="pull-right" id="download-chart">
|
||||
<i class="icon-download" title="<%- @Ti('Download') %>"></i>
|
||||
</a>
|
||||
-->
|
||||
<!--
|
||||
<div id="overview" style="margin-left:50px;margin-top:20px;width:400px;height:50px"></div>
|
||||
-->
|
||||
|
||||
<div class="js-timePicker"></div>
|
||||
<div class="js-dataDownload"></div>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<% for profile in @profiles: %>
|
||||
<li>
|
||||
<label class="inline-label radio-replacement">
|
||||
<input class="js-profileSelector" type="radio" value="<%= profile.id %>"<%- ' checked' if @params.profileSelected[profile.id] %>>
|
||||
<input class="js-profileSelector" type="radio" name="profile_id" value="<%= profile.id %>"<%- ' checked' if @params.profileSelected[profile.id] %>>
|
||||
<%- @Icon('radio', 'icon-unchecked') %>
|
||||
<%- @Icon('radio-checked', 'icon-checked') %>
|
||||
<span class="label-text"><%= profile.name %></span>
|
||||
|
|
|
@ -16,39 +16,44 @@ class ReportsController < ApplicationController
|
|||
def generate
|
||||
return if deny_if_not_role('Report')
|
||||
|
||||
#{"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"}}
|
||||
if params[:timeRange] == 'realtime'
|
||||
start = (Time.zone.now - 60.minutes).iso8601
|
||||
stop = Time.zone.now.iso8601
|
||||
created = aggs(start, stop, 'minute', 'created_at')
|
||||
closed = aggs(start, stop, 'minute', 'close_time')
|
||||
elsif params[:timeRange] == 'day'
|
||||
date = Date.parse("#{params[:year]}-#{params[:month]}-#{params[:day]}").to_s
|
||||
start = "#{date}T00:00:00Z"
|
||||
stop = "#{date}T23:59:59Z"
|
||||
created = aggs(start, stop, 'hour', 'created_at')
|
||||
closed = aggs(start, stop, 'hour', 'close_time')
|
||||
elsif params[:timeRange] == 'week'
|
||||
start = Date.commercial(params[:year], params[:week]).iso8601
|
||||
stop = Date.parse(start).end_of_week
|
||||
created = aggs(start, stop, 'week', 'created_at')
|
||||
closed = aggs(start, stop, 'week', 'close_time')
|
||||
elsif params[:timeRange] == 'month'
|
||||
start = Date.parse("#{params[:year]}-#{params[:month]}-01}").iso8601
|
||||
stop = Date.parse(start).end_of_month
|
||||
created = aggs(start, stop, 'day', 'created_at')
|
||||
closed = aggs(start, stop, 'day', 'close_time')
|
||||
else
|
||||
start = "#{params[:year]}-01-01"
|
||||
stop = "#{params[:year]}-12-31"
|
||||
created = aggs(start, stop, 'month', 'created_at')
|
||||
closed = aggs(start, stop, 'month', 'close_time')
|
||||
end
|
||||
get_params = params_all
|
||||
return if !get_params
|
||||
|
||||
result = {}
|
||||
get_params[:metric][:backend].each {|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],
|
||||
)
|
||||
}
|
||||
|
||||
#created = aggs(start, stop, range, 'created_at', profile.condition)
|
||||
#closed = aggs(start, stop, range, 'close_time', profile.condition)
|
||||
#first_solution =
|
||||
#reopend = backend(start, stop, range, Report::TicketReopened, profile.condition)
|
||||
|
||||
# add backlog
|
||||
#backlogs = []
|
||||
#position = -1
|
||||
#created.each {|_not_used|
|
||||
# position += 1
|
||||
# diff = created[position][1] - closed[position][1]
|
||||
# backlog = [position+1, diff]
|
||||
# backlogs.push backlog
|
||||
#}
|
||||
|
||||
render json: {
|
||||
data: {
|
||||
created: created,
|
||||
closed: closed,
|
||||
}
|
||||
data: result
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -56,109 +61,97 @@ class ReportsController < ApplicationController
|
|||
def sets
|
||||
return if deny_if_not_role('Report')
|
||||
|
||||
get_params = params_all
|
||||
return if !get_params
|
||||
|
||||
if !params[:downloadBackendSelected]
|
||||
render json: {
|
||||
error: 'No such downloadBackendSelected param',
|
||||
}, status: :unprocessable_entity
|
||||
return
|
||||
end
|
||||
|
||||
# get data
|
||||
result = {}
|
||||
get_params[:metric][:backend].each {|backend|
|
||||
next if params[:downloadBackendSelected] != backend[:name]
|
||||
condition = get_params[:profile].condition
|
||||
if backend[:condition]
|
||||
backend[:condition].merge(condition)
|
||||
else
|
||||
backend[:condition] = condition
|
||||
end
|
||||
next if !backend[:adapter]
|
||||
result = backend[:adapter].items(
|
||||
range_start: get_params[:start],
|
||||
range_end: get_params[:stop],
|
||||
interval: get_params[:range],
|
||||
selector: backend[:condition],
|
||||
params: backend[:params],
|
||||
)
|
||||
}
|
||||
render json: result
|
||||
end
|
||||
|
||||
def params_all
|
||||
profile = nil
|
||||
if !params[:profiles]
|
||||
render json: {
|
||||
error: 'No such profiles param',
|
||||
}, status: :unprocessable_entity
|
||||
return
|
||||
end
|
||||
params[:profiles].each {|profile_id, active|
|
||||
next if !active
|
||||
profile = Report::Profile.find(profile_id)
|
||||
}
|
||||
if !profile
|
||||
render json: {
|
||||
error: 'No such active profile',
|
||||
}, status: :unprocessable_entity
|
||||
return
|
||||
end
|
||||
|
||||
config = Report.config
|
||||
if !config || !config[:metric] || !config[:metric][params[:metric].to_sym]
|
||||
render json: {
|
||||
error: "No such metric #{params[:metric]}"
|
||||
}, status: :unprocessable_entity
|
||||
return
|
||||
end
|
||||
metric = config[:metric][params[:metric].to_sym]
|
||||
|
||||
#{"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"}}
|
||||
if params[:timeRange] == 'realtime'
|
||||
start = (Time.zone.now - 60.minutes).iso8601
|
||||
stop = Time.zone.now.iso8601
|
||||
range = 'minute'
|
||||
elsif params[:timeRange] == 'day'
|
||||
date = Date.parse("#{params[:year]}-#{params[:month]}-#{params[:day]}").to_s
|
||||
start = "#{date}T00:00:00Z"
|
||||
stop = "#{date}T23:59:59Z"
|
||||
range = 'hour'
|
||||
elsif params[:timeRange] == 'week'
|
||||
start = Date.commercial(params[:year], params[:week]).iso8601
|
||||
stop = Date.parse(start).end_of_week
|
||||
range = 'week'
|
||||
elsif params[:timeRange] == 'month'
|
||||
start = Date.parse("#{params[:year]}-#{params[:month]}-01}").iso8601
|
||||
stop = Date.parse(start).end_of_month
|
||||
range = 'day'
|
||||
else
|
||||
start = "#{params[:year]}-01-01"
|
||||
stop = "#{params[:year]}-12-31"
|
||||
range = 'month'
|
||||
end
|
||||
|
||||
# get data
|
||||
ticket_ids = []
|
||||
assets = {}
|
||||
Ticket.select('id').all.each {|ticket_part|
|
||||
ticket = Ticket.lookup(id: ticket_part.id)
|
||||
assets = ticket.assets(assets)
|
||||
ticket_ids.push ticket_part.id
|
||||
}
|
||||
count = Ticket.count
|
||||
render json: {
|
||||
ticket_ids: ticket_ids,
|
||||
assets: assets,
|
||||
count: count,
|
||||
{
|
||||
profile: profile,
|
||||
metric: metric,
|
||||
config: config,
|
||||
start: start,
|
||||
stop: stop,
|
||||
range: range,
|
||||
}
|
||||
end
|
||||
|
||||
def aggs(range_start, range_end, interval, field)
|
||||
interval_es = interval
|
||||
if interval == 'week'
|
||||
interval_es = 'day'
|
||||
end
|
||||
result = SearchIndexBackend.aggs(
|
||||
{
|
||||
},
|
||||
[range_start, range_end, field, interval_es],
|
||||
['Ticket'],
|
||||
)
|
||||
data = []
|
||||
if interval == 'month'
|
||||
start = Date.parse(range_start)
|
||||
stop_interval = 12
|
||||
elsif interval == 'week'
|
||||
start = Date.parse(range_start)
|
||||
stop_interval = 7
|
||||
elsif interval == 'day'
|
||||
start = Date.parse(range_start)
|
||||
stop_interval = 31
|
||||
elsif interval == 'hour'
|
||||
start = Time.zone.parse(range_start)
|
||||
stop_interval = 24
|
||||
elsif interval == 'minute'
|
||||
start = Time.zone.parse(range_start)
|
||||
stop_interval = 60
|
||||
end
|
||||
(1..stop_interval).each {|counter|
|
||||
match = false
|
||||
result['aggregations']['time_buckets']['buckets'].each {|item|
|
||||
if interval == 'minute'
|
||||
item['key_as_string'] = item['key_as_string'].sub(/:\d\d.\d\d\dZ$/, '')
|
||||
start_string = start.iso8601.sub(/:\d\dZ$/, '')
|
||||
else
|
||||
start_string = start.iso8601.sub(/:\d\d:\d\d.+?$/, '')
|
||||
end
|
||||
next if !item['doc_count']
|
||||
next if item['key_as_string'] !~ /#{start_string}/
|
||||
next if match
|
||||
match = true
|
||||
data.push [counter, item['doc_count']]
|
||||
if interval == 'month'
|
||||
start = start.next_month
|
||||
elsif interval == 'week'
|
||||
start = start.next_day
|
||||
elsif interval == 'day'
|
||||
start = start.next_day
|
||||
elsif interval == 'hour'
|
||||
start = start + 1.hour
|
||||
elsif interval == 'minute'
|
||||
start = start + 1.minute
|
||||
end
|
||||
}
|
||||
next if match
|
||||
data.push [counter, 0]
|
||||
if interval == 'month'
|
||||
start = start.next_month
|
||||
elsif interval == 'week'
|
||||
start = start.next_day
|
||||
elsif interval == 'day'
|
||||
start = start + 1.day
|
||||
elsif interval == 'hour'
|
||||
start = start + 1.hour
|
||||
elsif interval == 'minute'
|
||||
start = start + 1.minute
|
||||
end
|
||||
}
|
||||
data
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,12 +16,16 @@ class Report
|
|||
display: 'Created',
|
||||
selected: true,
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketGenericTime,
|
||||
params: { field: 'created_at' },
|
||||
},
|
||||
{
|
||||
name: 'closed',
|
||||
display: 'Closed',
|
||||
selected: true,
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketGenericTime,
|
||||
params: { field: 'close_time' },
|
||||
},
|
||||
{
|
||||
name: 'backlog',
|
||||
|
@ -32,39 +36,45 @@ class Report
|
|||
{
|
||||
name: 'first_solution',
|
||||
display: 'First Solution',
|
||||
selected: true,
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketFirstSolution,
|
||||
},
|
||||
{
|
||||
name: 'reopen',
|
||||
name: 'reopened',
|
||||
display: 'Re-Open',
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketReopened,
|
||||
},
|
||||
{
|
||||
name: 'movedin',
|
||||
display: 'Moved in',
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketMoved,
|
||||
params: { type: 'in' },
|
||||
},
|
||||
{
|
||||
name: 'movedout',
|
||||
display: 'Moved out',
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketMoved,
|
||||
params: { type: 'out' },
|
||||
},
|
||||
{
|
||||
name: 'sla_in',
|
||||
display: 'SLA in',
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
},
|
||||
{
|
||||
name: 'sla_out',
|
||||
display: 'SLA out',
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
},
|
||||
#{
|
||||
# name: 'sla_in',
|
||||
# display: 'SLA in',
|
||||
# selected: false,
|
||||
# dataDownload: true,
|
||||
#},
|
||||
#{
|
||||
# name: 'sla_out',
|
||||
# display: 'SLA out',
|
||||
# selected: false,
|
||||
# dataDownload: true,
|
||||
#},
|
||||
]
|
||||
config[:metric][:count][:backend] = backend
|
||||
|
||||
|
@ -79,24 +89,80 @@ class Report
|
|||
display: 'Phone (in)',
|
||||
selected: true,
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketGenericTime,
|
||||
params: {
|
||||
field: 'created_at',
|
||||
selector: {
|
||||
'create_article_type_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::Article::Type.lookup(name: 'phone').id,
|
||||
},
|
||||
'create_article_sender_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::Article::Sender.lookup(name: 'Customer').id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'phone_out',
|
||||
display: 'Phone (out)',
|
||||
selected: true,
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketGenericTime,
|
||||
params: {
|
||||
field: 'created_at',
|
||||
selector: {
|
||||
'create_article_type_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::Article::Type.lookup(name: 'phone').id,
|
||||
},
|
||||
'create_article_sender_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::Article::Sender.lookup(name: 'Agent').id,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'email_in',
|
||||
display: 'Email (in)',
|
||||
selected: true,
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketGenericTime,
|
||||
params: {
|
||||
field: 'created_at',
|
||||
selector: {
|
||||
'create_article_type_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::Article::Type.lookup(name: 'email').id,
|
||||
},
|
||||
'create_article_sender_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::Article::Sender.lookup(name: 'Customer').id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'email_out',
|
||||
display: 'Email (out)',
|
||||
selected: true,
|
||||
dataDownload: true,
|
||||
adapter: Report::TicketGenericTime,
|
||||
params: {
|
||||
field: 'created_at',
|
||||
selector: {
|
||||
'create_article_type_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::Article::Type.lookup(name: 'email').id,
|
||||
},
|
||||
'create_article_sender_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => Ticket::Article::Sender.lookup(name: 'Agent').id,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'web_in',
|
||||
|
@ -218,19 +284,19 @@ class Report
|
|||
{
|
||||
name: 'sla_out_1',
|
||||
display: 'SLA (out) - <1h',
|
||||
selected: true,
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
},
|
||||
{
|
||||
name: 'sla_out_2',
|
||||
display: 'SLA (out) - <2h',
|
||||
selected: true,
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
},
|
||||
{
|
||||
name: 'sla_out_4',
|
||||
display: 'SLA (out) - <4h',
|
||||
selected: true,
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
},
|
||||
{
|
||||
|
@ -248,19 +314,19 @@ class Report
|
|||
{
|
||||
name: 'sla_in_2',
|
||||
display: 'SLA (in) - <2h',
|
||||
selected: true,
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
},
|
||||
{
|
||||
name: 'sla_in_4',
|
||||
display: 'SLA (in) - <4h',
|
||||
selected: true,
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
},
|
||||
{
|
||||
name: 'sla_in_8',
|
||||
display: 'SLA (in) - <8h',
|
||||
selected: true,
|
||||
selected: false,
|
||||
dataDownload: true,
|
||||
},
|
||||
]
|
||||
|
|
389
lib/report/base.rb
Normal file
389
lib/report/base.rb
Normal file
|
@ -0,0 +1,389 @@
|
|||
class Report::Base
|
||||
|
||||
# :object
|
||||
# :type created|updated
|
||||
# :attribute
|
||||
# :value_from
|
||||
# :value_to
|
||||
# :start
|
||||
# :end
|
||||
# :selector
|
||||
def self.history_count(params)
|
||||
|
||||
history_object = History::Object.lookup( name: params[:object] )
|
||||
|
||||
query, bind_params, tables = Ticket.selector2sql(params[:selector])
|
||||
|
||||
count = 0
|
||||
ticket_ids = []
|
||||
|
||||
# created
|
||||
if params[:type] == 'created'
|
||||
history_type = History::Type.lookup( name: 'created' )
|
||||
return History.select('histories.o_id').joins('INNER JOIN tickets ON tickets.id = histories.o_id')
|
||||
.where(
|
||||
'histories.created_at >= ? AND histories.created_at <= ? AND histories.history_object_id = ? AND histories.history_type_id = ?', params[:start], params[:end], history_object.id, history_type.id
|
||||
)
|
||||
.where(query, *bind_params).joins(tables).count
|
||||
end
|
||||
|
||||
# updated
|
||||
if params[:type] == 'updated'
|
||||
history_type = History::Type.lookup( name: 'updated' )
|
||||
history_attribute = History::Attribute.lookup( name: params[:attribute] )
|
||||
if !history_attribute || !history_type
|
||||
count = 0
|
||||
else
|
||||
if params[:id_not_from] && params[:id_to]
|
||||
return History.select('histories.o_id').joins('INNER JOIN tickets ON tickets.id = histories.o_id')
|
||||
.where(query, *bind_params).joins(tables)
|
||||
.where(
|
||||
'histories.created_at >= ? AND histories.created_at <= ? AND histories.history_object_id = ? AND histories.history_type_id = ? AND histories.history_attribute_id IN (?) AND histories.id_from NOT IN (?) AND histories.id_to IN (?)',
|
||||
params[:start],
|
||||
params[:end],
|
||||
history_object.id,
|
||||
history_type.id,
|
||||
history_attribute.id,
|
||||
params[:id_not_from],
|
||||
params[:id_to],
|
||||
).count
|
||||
elsif params[:id_from] && params[:id_not_to]
|
||||
return History.select('histories.o_id').joins('INNER JOIN tickets ON tickets.id = histories.o_id')
|
||||
.where(query, *bind_params).joins(tables)
|
||||
.where(
|
||||
'histories.created_at >= ? AND histories.created_at <= ? AND histories.history_object_id = ? AND histories.history_type_id = ? AND histories.history_attribute_id IN (?) AND histories.id_from IN (?) AND histories.id_to NOT IN (?)',
|
||||
params[:start],
|
||||
params[:end],
|
||||
history_object.id,
|
||||
history_type.id,
|
||||
history_attribute.id,
|
||||
params[:id_from],
|
||||
params[:id_not_to],
|
||||
).count
|
||||
elsif params[:value_from] && params[:value_not_to]
|
||||
return History.joins('INNER JOIN tickets ON tickets.id = histories.o_id')
|
||||
.where(query, *bind_params).joins(tables)
|
||||
.where(
|
||||
'histories.created_at >= ? AND histories.created_at <= ? AND histories.history_object_id = ? AND histories.history_type_id = ? AND histories.history_attribute_id IN (?) AND histories.value_from IN (?) AND histories.value_to NOT IN (?)',
|
||||
params[:start],
|
||||
params[:end],
|
||||
history_object.id,
|
||||
history_type.id,
|
||||
history_attribute.id,
|
||||
params[:value_from],
|
||||
params[:value_not_to],
|
||||
).count
|
||||
elsif params[:value_to]
|
||||
return History.select('histories.o_id').joins('INNER JOIN tickets ON tickets.id = histories.o_id')
|
||||
.where(query, *bind_params).joins(tables)
|
||||
.where(
|
||||
'histories.created_at >= ? AND histories.created_at <= ? AND histories.history_object_id = ? AND histories.history_type_id = ? AND histories.history_attribute_id IN (?) AND histories.value_to IN (?)',
|
||||
params[:start],
|
||||
params[:end],
|
||||
history_object.id,
|
||||
history_type.id,
|
||||
history_attribute.id,
|
||||
params[:value_to],
|
||||
).count
|
||||
elsif params[:id_to]
|
||||
return History.select('histories.o_id').joins('INNER JOIN tickets ON tickets.id = histories.o_id')
|
||||
.where(query, *bind_params).joins(tables)
|
||||
.where(
|
||||
'histories.created_at >= ? AND histories.created_at <= ? AND histories.history_object_id = ? AND histories.history_type_id = ? AND histories.history_attribute_id IN (?) AND histories.id_to IN (?)',
|
||||
params[:start],
|
||||
params[:end],
|
||||
history_object.id,
|
||||
history_type.id,
|
||||
history_attribute.id,
|
||||
params[:id_to],
|
||||
).count
|
||||
else
|
||||
fail "UNKOWN params (#{params.inspect})!"
|
||||
end
|
||||
end
|
||||
end
|
||||
fail "UNKOWN :type (#{params[:type]})!"
|
||||
end
|
||||
|
||||
# :object
|
||||
# :type created|updated
|
||||
# :attribute
|
||||
# :value_from
|
||||
# :value_to
|
||||
# :start
|
||||
# :end
|
||||
# :condition
|
||||
def self.history(data)
|
||||
|
||||
history_object = History::Object.lookup( name: data[:object] )
|
||||
|
||||
query, bind_params, tables = Ticket.selector2sql(data[:selector])
|
||||
|
||||
count = 0
|
||||
ticket_ids = []
|
||||
|
||||
# created
|
||||
if data[:type] == 'created'
|
||||
history_type = History::Type.lookup( name: 'created' )
|
||||
histories = History.select('histories.o_id').joins('INNER JOIN tickets ON tickets.id = histories.o_id')
|
||||
.where(
|
||||
'histories.created_at >= ? AND histories.created_at <= ? AND histories.history_object_id = ? AND histories.history_type_id = ?', data[:start], data[:end], history_object.id, history_type.id
|
||||
)
|
||||
.where(query, *bind_params).joins(tables)
|
||||
histories.each {|history|
|
||||
count += 1
|
||||
ticket_ids.push history.o_id
|
||||
}
|
||||
return {
|
||||
count: count,
|
||||
ticket_ids: ticket_ids,
|
||||
}
|
||||
end
|
||||
|
||||
# updated
|
||||
if data[:type] == 'updated'
|
||||
history_type = History::Type.lookup( name: 'updated' )
|
||||
history_attribute = History::Attribute.lookup( name: data[:attribute] )
|
||||
if !history_attribute || !history_type
|
||||
count = 0
|
||||
else
|
||||
if data[:id_not_from] && data[:id_to]
|
||||
histories = History.select('histories.o_id').joins('INNER JOIN tickets ON tickets.id = histories.o_id')
|
||||
.where(query, *bind_params).joins(tables)
|
||||
.where(
|
||||
'histories.created_at >= ? AND histories.created_at <= ? AND histories.history_object_id = ? AND histories.history_type_id = ? AND histories.history_attribute_id IN (?) AND histories.id_from NOT IN (?) AND histories.id_to IN (?)',
|
||||
data[:start],
|
||||
data[:end],
|
||||
history_object.id,
|
||||
history_type.id,
|
||||
history_attribute.id,
|
||||
data[:id_not_from],
|
||||
data[:id_to],
|
||||
)
|
||||
elsif data[:id_from] && data[:id_not_to]
|
||||
histories = History.select('histories.o_id').joins('INNER JOIN tickets ON tickets.id = histories.o_id')
|
||||
.where(query, *bind_params).joins(tables)
|
||||
.where(
|
||||
'histories.created_at >= ? AND histories.created_at <= ? AND histories.history_object_id = ? AND histories.history_type_id = ? AND histories.history_attribute_id IN (?) AND histories.id_from IN (?) AND histories.id_to NOT IN (?)',
|
||||
data[:start],
|
||||
data[:end],
|
||||
history_object.id,
|
||||
history_type.id,
|
||||
history_attribute.id,
|
||||
data[:id_from],
|
||||
data[:id_not_to],
|
||||
)
|
||||
elsif data[:value_from] && data[:value_not_to]
|
||||
histories = History.joins('INNER JOIN tickets ON tickets.id = histories.o_id')
|
||||
.where(query, *bind_params).joins(tables)
|
||||
.where(
|
||||
'histories.created_at >= ? AND histories.created_at <= ? AND histories.history_object_id = ? AND histories.history_type_id = ? AND histories.history_attribute_id IN (?) AND histories.value_from IN (?) AND histories.value_to NOT IN (?)',
|
||||
data[:start],
|
||||
data[:end],
|
||||
history_object.id,
|
||||
history_type.id,
|
||||
history_attribute.id,
|
||||
data[:value_from],
|
||||
data[:value_not_to],
|
||||
)
|
||||
elsif data[:value_to]
|
||||
histories = History.select('histories.o_id').joins('INNER JOIN tickets ON tickets.id = histories.o_id')
|
||||
.where(query, *bind_params).joins(tables)
|
||||
.where(
|
||||
'histories.created_at >= ? AND histories.created_at <= ? AND histories.history_object_id = ? AND histories.history_type_id = ? AND histories.history_attribute_id IN (?) AND histories.value_to IN (?)',
|
||||
data[:start],
|
||||
data[:end],
|
||||
history_object.id,
|
||||
history_type.id,
|
||||
history_attribute.id,
|
||||
data[:value_to],
|
||||
)
|
||||
elsif data[:id_to]
|
||||
histories = History.select('histories.o_id').joins('INNER JOIN tickets ON tickets.id = histories.o_id')
|
||||
.where(query, *bind_params).joins(tables)
|
||||
.where(
|
||||
'histories.created_at >= ? AND histories.created_at <= ? AND histories.history_object_id = ? AND histories.history_type_id = ? AND histories.history_attribute_id IN (?) AND histories.id_to IN (?)',
|
||||
data[:start],
|
||||
data[:end],
|
||||
history_object.id,
|
||||
history_type.id,
|
||||
history_attribute.id,
|
||||
data[:id_to],
|
||||
)
|
||||
end
|
||||
histories.each {|history|
|
||||
count += 1
|
||||
ticket_ids.push history.o_id
|
||||
}
|
||||
end
|
||||
return {
|
||||
count: count,
|
||||
ticket_ids: ticket_ids,
|
||||
}
|
||||
end
|
||||
fail "UNKOWN :type (#{data[:type]})!"
|
||||
end
|
||||
|
||||
# :sender
|
||||
# :type
|
||||
# :start
|
||||
# :end
|
||||
# :condition
|
||||
def self.article_type_and_sender(data)
|
||||
query, bind_params, tables = Ticket.selector2sql(data[:condition])
|
||||
sender = Ticket::Article::Sender.lookup( name: data[:sender] )
|
||||
type = Ticket::Article::Type.lookup( name: data[:type] )
|
||||
articles = Ticket::Article.joins('INNER JOIN tickets ON tickets.id = ticket_articles.ticket_id')
|
||||
.where(query, *bind_params).joins(tables)
|
||||
.where(
|
||||
'ticket_articles.created_at >= ? AND ticket_articles.created_at <= ? AND ticket_articles.type_id = ? AND ticket_articles.sender_id = ?',
|
||||
data[:start],
|
||||
data[:end],
|
||||
type.id,
|
||||
sender.id,
|
||||
).count
|
||||
{
|
||||
count: articles,
|
||||
}
|
||||
end
|
||||
|
||||
# :type
|
||||
# :start
|
||||
# :end
|
||||
# :condition
|
||||
def self.create_channel(data)
|
||||
query, bind_params, tables = Ticket.selector2sql(data[:condition])
|
||||
article_type = Ticket::Article::Type.lookup( name: data[:type] )
|
||||
tickets = Ticket.select('tickets.id')
|
||||
.where( 'tickets.created_at >= ? AND tickets.created_at <= ? AND tickets.create_article_type_id = ?', data[:start], data[:end], article_type.id )
|
||||
.where(query, *bind_params).joins(tables)
|
||||
count = 0
|
||||
ticket_ids = []
|
||||
tickets.each {|ticket|
|
||||
count += 1
|
||||
ticket_ids.push ticket.id
|
||||
}
|
||||
{
|
||||
count: count,
|
||||
ticket_ids: ticket_ids,
|
||||
}
|
||||
end
|
||||
|
||||
# :type
|
||||
# :start
|
||||
# :end
|
||||
# :condition
|
||||
def self.time_average(data)
|
||||
query, bind_params, tables = Ticket.selector2sql(data[:condition])
|
||||
ticket_list = Ticket.where( 'tickets.created_at >= ? AND tickets.created_at <= ?', data[:start], data[:end] )
|
||||
.where(query, *bind_params).joins(tables)
|
||||
tickets = 0
|
||||
time_total = 0
|
||||
ticket_list.each {|ticket|
|
||||
timestamp = ticket[ data[:type].to_sym ]
|
||||
next if !timestamp
|
||||
# puts 'FR:' + first_response.to_s
|
||||
# puts 'CT:' + ticket.created_at.to_s
|
||||
diff = timestamp - ticket.created_at
|
||||
#puts 'DIFF:' + diff.to_s
|
||||
time_total = time_total + diff
|
||||
tickets += 1
|
||||
}
|
||||
if time_total == 0 || tickets == 0
|
||||
tickets = -0.001
|
||||
else
|
||||
tickets = time_total / tickets / 60
|
||||
tickets = tickets.to_i
|
||||
end
|
||||
{
|
||||
count: tickets,
|
||||
}
|
||||
end
|
||||
|
||||
# :type
|
||||
# :start
|
||||
# :end
|
||||
# :condition
|
||||
def self.time_min(data)
|
||||
query, bind_params, tables = Ticket.selector2sql(data[:condition])
|
||||
ticket_list = Ticket.where( 'tickets.created_at >= ? AND tickets.created_at <= ?', data[:start], data[:end] )
|
||||
.where(query, *bind_params).joins(tables)
|
||||
tickets = 0
|
||||
time_min = 0
|
||||
ticket_ids = []
|
||||
ticket_list.each {|ticket|
|
||||
timestamp = ticket[ data[:type].to_sym ]
|
||||
next if !timestamp
|
||||
ticket_ids.push ticket.id
|
||||
# puts 'FR:' + first_response.to_s
|
||||
# puts 'CT:' + ticket.created_at.to_s
|
||||
diff = timestamp - ticket.created_at
|
||||
#puts 'DIFF:' + diff.to_s
|
||||
if !time_min
|
||||
time_min = diff
|
||||
end
|
||||
if diff < time_min
|
||||
time_min = diff
|
||||
end
|
||||
}
|
||||
if time_min == 0
|
||||
tickets = -0.001
|
||||
else
|
||||
tickets = (time_min / 60).to_i
|
||||
end
|
||||
{
|
||||
count: tickets,
|
||||
ticket_ids: ticket_ids,
|
||||
}
|
||||
end
|
||||
|
||||
# :type
|
||||
# :start
|
||||
# :end
|
||||
# :condition
|
||||
def self.time_max(data)
|
||||
query, bind_params, tables = Ticket.selector2sql(data[:condition])
|
||||
ticket_list = Ticket.where( 'tickets.created_at >= ? AND tickets.created_at <= ?', data[:start], data[:end] )
|
||||
.where(query, *bind_params).joins(tables)
|
||||
tickets = 0
|
||||
time_max = 0
|
||||
ticket_ids = []
|
||||
ticket_list.each {|ticket|
|
||||
timestamp = ticket[ data[:type].to_sym ]
|
||||
next if !timestamp
|
||||
ticket_ids.push ticket.id
|
||||
# puts "#{data[:type].to_s} - #{timestamp} - #{ticket.inspect}"
|
||||
# puts 'FR:' + ticket.first_response.to_s
|
||||
# puts 'CT:' + ticket.created_at.to_s
|
||||
diff = timestamp - ticket.created_at
|
||||
#puts 'DIFF:' + diff.to_s
|
||||
if !time_max
|
||||
time_max = diff
|
||||
end
|
||||
if diff > time_max
|
||||
time_max = diff
|
||||
end
|
||||
}
|
||||
if time_max == 0
|
||||
tickets = -0.001
|
||||
else
|
||||
tickets = (time_max / 60).to_i
|
||||
end
|
||||
{
|
||||
count: tickets,
|
||||
ticket_ids: ticket_ids,
|
||||
}
|
||||
end
|
||||
|
||||
def self.ticket_condition(ticket_id, condition)
|
||||
ticket = Ticket.lookup( id: ticket_id )
|
||||
match = true
|
||||
condition.each {|key, value|
|
||||
if ticket[key.to_sym] != value
|
||||
return false
|
||||
end
|
||||
}
|
||||
true
|
||||
end
|
||||
|
||||
end
|
118
lib/report/ticket_first_solution.rb
Normal file
118
lib/report/ticket_first_solution.rb
Normal file
|
@ -0,0 +1,118 @@
|
|||
class Report::TicketFirstSolution
|
||||
|
||||
=begin
|
||||
|
||||
result = Report::TicketFirstSolution.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # quarter, month, week, day, hour, minute, second
|
||||
selector: selector, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
|
||||
returns
|
||||
|
||||
[4,5,1,5,0,51,5,56,7,4]
|
||||
|
||||
=end
|
||||
|
||||
def self.aggs(params)
|
||||
interval = params[:interval]
|
||||
if params[:interval] == 'week'
|
||||
interval = 'day'
|
||||
end
|
||||
|
||||
result = []
|
||||
if params[:interval] == 'month'
|
||||
start = Date.parse(params[:range_start])
|
||||
stop_interval = 12
|
||||
elsif params[:interval] == 'week'
|
||||
start = Date.parse(params[:range_start])
|
||||
stop_interval = 7
|
||||
elsif params[:interval] == 'day'
|
||||
start = Date.parse(params[:range_start])
|
||||
stop_interval = 31
|
||||
elsif params[:interval] == 'hour'
|
||||
start = Time.zone.parse(params[:range_start])
|
||||
stop_interval = 24
|
||||
elsif params[:interval] == 'minute'
|
||||
start = Time.zone.parse(params[:range_start])
|
||||
stop_interval = 60
|
||||
end
|
||||
(1..stop_interval).each {|_counter|
|
||||
if params[:interval] == 'month'
|
||||
stop = start.next_month
|
||||
elsif params[:interval] == 'week'
|
||||
stop = start.next_day
|
||||
elsif params[:interval] == 'day'
|
||||
stop = start.next_day
|
||||
elsif params[:interval] == 'hour'
|
||||
stop = start + 1.hour
|
||||
elsif params[:interval] == 'minute'
|
||||
stop = start + 1.minute
|
||||
end
|
||||
query, bind_params, tables = Ticket.selector2sql(params[:selector])
|
||||
ticket_list = Ticket.select('tickets.id, tickets.close_time, tickets.created_at').where(
|
||||
'tickets.close_time IS NOT NULL AND tickets.close_time >= ? AND tickets.close_time < ?',
|
||||
start,
|
||||
stop,
|
||||
).where(query, *bind_params).joins(tables)
|
||||
count = 0
|
||||
ticket_list.each {|ticket|
|
||||
closed_at = ticket.close_time
|
||||
created_at = ticket.created_at
|
||||
if (closed_at - (60 * 15) ) < created_at
|
||||
count += 1
|
||||
end
|
||||
}
|
||||
result.push count
|
||||
start = stop
|
||||
}
|
||||
result
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
result = Report::TicketFirstSolution.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: selector, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
|
||||
returns
|
||||
|
||||
{
|
||||
count: 123,
|
||||
ticket_ids: [4,5,1,5,0,51,5,56,7,4],
|
||||
assets: assets,
|
||||
}
|
||||
|
||||
=end
|
||||
|
||||
def self.items(params)
|
||||
query, bind_params, tables = Ticket.selector2sql(params[:selector])
|
||||
ticket_list = Ticket.select('tickets.id, tickets.close_time, tickets.created_at').where(
|
||||
'tickets.close_time IS NOT NULL AND tickets.close_time >= ? AND tickets.close_time < ?',
|
||||
params[:range_start],
|
||||
params[:range_end],
|
||||
).where(query, *bind_params).joins(tables)
|
||||
count = 0
|
||||
assets = {}
|
||||
ticket_ids = []
|
||||
ticket_list.each {|ticket|
|
||||
closed_at = ticket.close_time
|
||||
created_at = ticket.created_at
|
||||
if (closed_at - (60 * 15) ) < created_at
|
||||
count += 1
|
||||
ticket_ids.push ticket.id
|
||||
end
|
||||
ticket_full = Ticket.find(ticket.id)
|
||||
assets = ticket_full.assets(assets)
|
||||
}
|
||||
{
|
||||
count: count,
|
||||
ticket_ids: ticket_ids,
|
||||
assets: assets,
|
||||
}
|
||||
end
|
||||
|
||||
end
|
131
lib/report/ticket_generic_time.rb
Normal file
131
lib/report/ticket_generic_time.rb
Normal file
|
@ -0,0 +1,131 @@
|
|||
class Report::TicketGenericTime
|
||||
|
||||
=begin
|
||||
selector = {}
|
||||
result = Report::TicketGenericTime.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: selector, # ticket selector to get only a collection of tickets
|
||||
params: { field: 'created_at' },
|
||||
)
|
||||
|
||||
returns
|
||||
|
||||
[4,5,1,5,0,51,5,56,7,4]
|
||||
|
||||
=end
|
||||
|
||||
def self.aggs(params)
|
||||
interval_es = params[:interval]
|
||||
if params[:interval] == 'week'
|
||||
interval_es = 'day'
|
||||
end
|
||||
|
||||
aggs_interval = {
|
||||
from: params[:range_start],
|
||||
to: params[:range_end],
|
||||
interval: interval_es, # year, quarter, month, week, day, hour, minute, second
|
||||
field: params[:params][:field],
|
||||
}
|
||||
|
||||
result_es = SearchIndexBackend.selectors(['Ticket'], params[:selector], nil, nil, aggs_interval)
|
||||
|
||||
if params[:interval] == 'month'
|
||||
start = Date.parse(params[:range_start])
|
||||
stop_interval = 12
|
||||
elsif params[:interval] == 'week'
|
||||
start = Date.parse(params[:range_start])
|
||||
stop_interval = 7
|
||||
elsif params[:interval] == 'day'
|
||||
start = Date.parse(params[:range_start])
|
||||
stop_interval = 31
|
||||
elsif params[:interval] == 'hour'
|
||||
start = Time.zone.parse(params[:range_start])
|
||||
stop_interval = 24
|
||||
elsif params[:interval] == 'minute'
|
||||
start = Time.zone.parse(params[:range_start])
|
||||
stop_interval = 60
|
||||
end
|
||||
result = []
|
||||
(1..stop_interval).each {|_counter|
|
||||
match = false
|
||||
result_es['aggregations']['time_buckets']['buckets'].each {|item|
|
||||
if params[:interval] == 'minute'
|
||||
item['key_as_string'] = item['key_as_string'].sub(/:\d\d.\d\d\dZ$/, '')
|
||||
start_string = start.iso8601.sub(/:\d\dZ$/, '')
|
||||
else
|
||||
start_string = start.iso8601.sub(/:\d\d:\d\d.+?$/, '')
|
||||
end
|
||||
next if !item['doc_count']
|
||||
next if item['key_as_string'] !~ /#{start_string}/
|
||||
next if match
|
||||
match = true
|
||||
result.push item['doc_count']
|
||||
if params[:interval] == 'month'
|
||||
start = start.next_month
|
||||
elsif params[:interval] == 'week'
|
||||
start = start.next_day
|
||||
elsif params[:interval] == 'day'
|
||||
start = start.next_day
|
||||
elsif params[:interval] == 'hour'
|
||||
start = start + 1.hour
|
||||
elsif params[:interval] == 'minute'
|
||||
start = start + 1.minute
|
||||
end
|
||||
}
|
||||
next if match
|
||||
result.push 0
|
||||
if params[:interval] == 'month'
|
||||
start = start.next_month
|
||||
elsif params[:interval] == 'week'
|
||||
start = start.next_day
|
||||
elsif params[:interval] == 'day'
|
||||
start = start + 1.day
|
||||
elsif params[:interval] == 'hour'
|
||||
start = start + 1.hour
|
||||
elsif params[:interval] == 'minute'
|
||||
start = start + 1.minute
|
||||
end
|
||||
}
|
||||
result
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
result = Report::TicketGenericTime.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: selector, # ticket selector to get only a collection of tickets
|
||||
params: { field: 'created_at' },
|
||||
)
|
||||
|
||||
returns
|
||||
|
||||
{
|
||||
count: 123,
|
||||
ticket_ids: [4,5,1,5,0,51,5,56,7,4],
|
||||
assets: assets,
|
||||
}
|
||||
|
||||
=end
|
||||
|
||||
def self.items(params)
|
||||
|
||||
aggs_interval = {
|
||||
from: params[:range_start],
|
||||
to: params[:range_end],
|
||||
field: params[:params][:field],
|
||||
}
|
||||
|
||||
result = SearchIndexBackend.selectors(['Ticket'], params[:selector], nil, nil, aggs_interval)
|
||||
assets = {}
|
||||
result[:ticket_ids].each {|ticket_id|
|
||||
ticket_full = Ticket.find(ticket_id)
|
||||
assets = ticket_full.assets(assets)
|
||||
}
|
||||
result[:assets] = assets
|
||||
result
|
||||
end
|
||||
|
||||
end
|
165
lib/report/ticket_moved.rb
Normal file
165
lib/report/ticket_moved.rb
Normal file
|
@ -0,0 +1,165 @@
|
|||
class Report::TicketMoved < Report::Base
|
||||
|
||||
=begin
|
||||
|
||||
result = Report::TicketMoved.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # quarter, month, week, day, hour, minute, second
|
||||
selector: selector, # ticket selector to get only a collection of tickets
|
||||
params: { type: 'in' }, # in|out
|
||||
)
|
||||
|
||||
returns
|
||||
|
||||
[4,5,1,5,0,51,5,56,7,4]
|
||||
|
||||
=end
|
||||
|
||||
def self.aggs(params)
|
||||
|
||||
selector = params[:selector]['ticket.group_id']
|
||||
|
||||
if !selector
|
||||
return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
end
|
||||
|
||||
interval = params[:interval]
|
||||
if params[:interval] == 'week'
|
||||
interval = 'day'
|
||||
end
|
||||
|
||||
result = []
|
||||
if params[:interval] == 'month'
|
||||
start = Date.parse(params[:range_start])
|
||||
stop_interval = 12
|
||||
elsif params[:interval] == 'week'
|
||||
start = Date.parse(params[:range_start])
|
||||
stop_interval = 7
|
||||
elsif params[:interval] == 'day'
|
||||
start = Date.parse(params[:range_start])
|
||||
stop_interval = 31
|
||||
elsif params[:interval] == 'hour'
|
||||
start = Time.zone.parse(params[:range_start])
|
||||
stop_interval = 24
|
||||
elsif params[:interval] == 'minute'
|
||||
start = Time.zone.parse(params[:range_start])
|
||||
stop_interval = 60
|
||||
end
|
||||
(1..stop_interval).each {|_counter|
|
||||
if params[:interval] == 'month'
|
||||
stop = start.next_month
|
||||
elsif params[:interval] == 'week'
|
||||
stop = start.next_day
|
||||
elsif params[:interval] == 'day'
|
||||
stop = start.next_day
|
||||
elsif params[:interval] == 'hour'
|
||||
stop = start + 1.hour
|
||||
elsif params[:interval] == 'minute'
|
||||
stop = start + 1.minute
|
||||
end
|
||||
local_params = group_attributes(selector, params)
|
||||
local_selector = params[:selector].clone
|
||||
if params[:params][:type] == 'out'
|
||||
local_selector.delete('ticket.group_id')
|
||||
end
|
||||
defaults = {
|
||||
object: 'Ticket',
|
||||
type: 'updated',
|
||||
attribute: 'group',
|
||||
start: start,
|
||||
end: stop,
|
||||
selector: local_selector
|
||||
}
|
||||
local_params = defaults.merge(local_params)
|
||||
count = history_count(local_params)
|
||||
result.push count
|
||||
start = stop
|
||||
}
|
||||
result
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
result = Report::TicketMoved.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: selector, # ticket selector to get only a collection of tickets
|
||||
params: { type: 'in' }, # in|out
|
||||
)
|
||||
|
||||
returns
|
||||
|
||||
{
|
||||
count: 123,
|
||||
ticket_ids: [4,5,1,5,0,51,5,56,7,4],
|
||||
assets: assets,
|
||||
}
|
||||
|
||||
=end
|
||||
|
||||
def self.items(params)
|
||||
|
||||
selector = params[:selector]['ticket.group_id']
|
||||
|
||||
if !selector
|
||||
return {
|
||||
count: 0,
|
||||
ticket_ids: [],
|
||||
}
|
||||
end
|
||||
local_params = group_attributes(selector, params)
|
||||
local_selector = params[:selector].clone
|
||||
if params[:params][:type] == 'out'
|
||||
local_selector.delete('ticket.group_id')
|
||||
end
|
||||
defaults = {
|
||||
object: 'Ticket',
|
||||
type: 'updated',
|
||||
attribute: 'group',
|
||||
start: params[:range_start],
|
||||
end: params[:range_end],
|
||||
selector: local_selector
|
||||
}
|
||||
local_params = defaults.merge(local_params)
|
||||
result = history(local_params)
|
||||
assets = {}
|
||||
result[:ticket_ids].each {|ticket_id|
|
||||
ticket_full = Ticket.find(ticket_id)
|
||||
assets = ticket_full.assets(assets)
|
||||
}
|
||||
result[:assets] = assets
|
||||
result
|
||||
end
|
||||
|
||||
def self.group_attributes(selector, params)
|
||||
if selector['operator'] == 'is'
|
||||
group_id = selector['value']
|
||||
if params[:params][:type] == 'in'
|
||||
return {
|
||||
id_not_from: group_id,
|
||||
id_to: group_id,
|
||||
}
|
||||
else
|
||||
return {
|
||||
id_from: group_id,
|
||||
id_not_to: group_id,
|
||||
}
|
||||
end
|
||||
else
|
||||
group_id = selector['value']
|
||||
if params[:params][:type] == 'in'
|
||||
return {
|
||||
id_from: group_id,
|
||||
id_not_to: group_id,
|
||||
}
|
||||
else
|
||||
return {
|
||||
id_not_from: group_id,
|
||||
id_to: group_id,
|
||||
}
|
||||
end
|
||||
end
|
||||
fail "Unknown selector params '#{selector.inspect}'"
|
||||
end
|
||||
end
|
124
lib/report/ticket_reopened.rb
Normal file
124
lib/report/ticket_reopened.rb
Normal file
|
@ -0,0 +1,124 @@
|
|||
class Report::TicketReopened < Report::Base
|
||||
|
||||
=begin
|
||||
|
||||
result = Report::TicketReopened.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # quarter, month, week, day, hour, minute, second
|
||||
selector: selector, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
|
||||
returns
|
||||
|
||||
[4,5,1,5,0,51,5,56,7,4]
|
||||
|
||||
=end
|
||||
|
||||
def self.aggs(params)
|
||||
ticket_state_ids = ticket_ids
|
||||
|
||||
interval = params[:interval]
|
||||
if params[:interval] == 'week'
|
||||
interval = 'day'
|
||||
end
|
||||
|
||||
result = []
|
||||
if params[:interval] == 'month'
|
||||
start = Date.parse(params[:range_start])
|
||||
stop_interval = 12
|
||||
elsif params[:interval] == 'week'
|
||||
start = Date.parse(params[:range_start])
|
||||
stop_interval = 7
|
||||
elsif params[:interval] == 'day'
|
||||
start = Date.parse(params[:range_start])
|
||||
stop_interval = 31
|
||||
elsif params[:interval] == 'hour'
|
||||
start = Time.zone.parse(params[:range_start])
|
||||
stop_interval = 24
|
||||
elsif params[:interval] == 'minute'
|
||||
start = Time.zone.parse(params[:range_start])
|
||||
stop_interval = 60
|
||||
end
|
||||
(1..stop_interval).each {|_counter|
|
||||
if params[:interval] == 'month'
|
||||
stop = start.next_month
|
||||
elsif params[:interval] == 'week'
|
||||
stop = start.next_day
|
||||
elsif params[:interval] == 'day'
|
||||
stop = start.next_day
|
||||
elsif params[:interval] == 'hour'
|
||||
stop = start + 1.hour
|
||||
elsif params[:interval] == 'minute'
|
||||
stop = start + 1.minute
|
||||
end
|
||||
count = history_count(
|
||||
object: 'Ticket',
|
||||
type: 'updated',
|
||||
attribute: 'state',
|
||||
id_from: ticket_state_ids,
|
||||
id_not_to: ticket_state_ids,
|
||||
start: start,
|
||||
end: stop,
|
||||
selector: params[:selector]
|
||||
)
|
||||
result.push count
|
||||
start = stop
|
||||
}
|
||||
result
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
result = Report::TicketReopened.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: selector, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
|
||||
returns
|
||||
|
||||
{
|
||||
count: 123,
|
||||
ticket_ids: [4,5,1,5,0,51,5,56,7,4],
|
||||
assets: assets,
|
||||
}
|
||||
|
||||
=end
|
||||
|
||||
def self.items(params)
|
||||
ticket_state_ids = ticket_ids
|
||||
result = history(
|
||||
object: 'Ticket',
|
||||
type: 'updated',
|
||||
attribute: 'state',
|
||||
id_from: ticket_state_ids,
|
||||
id_not_to: ticket_state_ids,
|
||||
start: params[:range_start],
|
||||
end: params[:range_end],
|
||||
selector: params[:selector]
|
||||
)
|
||||
assets = {}
|
||||
result[:ticket_ids].each {|ticket_id|
|
||||
ticket_full = Ticket.find(ticket_id)
|
||||
assets = ticket_full.assets(assets)
|
||||
}
|
||||
result[:assets] = assets
|
||||
result
|
||||
end
|
||||
|
||||
def self.ticket_ids
|
||||
key = 'Report::TicketReopened::StateList'
|
||||
ticket_state_ids = Cache.get( key )
|
||||
return ticket_state_ids if ticket_state_ids
|
||||
ticket_state_types = Ticket::StateType.where( name: %w(closed merged removed) )
|
||||
ticket_state_ids = []
|
||||
ticket_state_types.each {|ticket_state_type|
|
||||
ticket_state_type.states.each {|ticket_state|
|
||||
ticket_state_ids.push ticket_state.id
|
||||
}
|
||||
}
|
||||
Cache.write( key, ticket_state_ids, { expires_in: 2.days } )
|
||||
ticket_state_ids
|
||||
end
|
||||
end
|
|
@ -232,19 +232,18 @@ return search result
|
|||
|
||||
=begin
|
||||
|
||||
return aggregation result
|
||||
get count of tickets and tickets which match on selector
|
||||
|
||||
result = SearchIndexBackend.aggs(
|
||||
{
|
||||
title: 'test',
|
||||
state_id: 4,
|
||||
},
|
||||
['2014-10-19', '2015-10-19', 'created_at', 'month'],
|
||||
['Ticket'],
|
||||
)
|
||||
aggs_interval = {
|
||||
from: '2015-01-01',
|
||||
to: '2015-12-31',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
field: 'created_at',
|
||||
}
|
||||
|
||||
# year, quarter, month, week, day, hour, minute, second
|
||||
result = SearchIndexBackend.selectors(index, params[:condition], limit, current_user, aggs_interval)
|
||||
|
||||
# for aggregations
|
||||
result = {
|
||||
hits:{
|
||||
total:4819,
|
||||
|
@ -270,7 +269,8 @@ return aggregation result
|
|||
|
||||
=end
|
||||
|
||||
def self.aggs(query, range, index = nil)
|
||||
def self.selectors(index = nil, selectors = nil, _limit = 10, current_user = nil, aggs_interval = nil)
|
||||
fail 'no selectors given' if !selectors
|
||||
|
||||
url = build_url()
|
||||
return if !url
|
||||
|
@ -284,45 +284,7 @@ return aggregation result
|
|||
url += '/_search'
|
||||
end
|
||||
|
||||
and_data = []
|
||||
if query && !query.empty?
|
||||
bool = {
|
||||
bool: {
|
||||
must: {
|
||||
term: query,
|
||||
},
|
||||
},
|
||||
}
|
||||
and_data.push bool
|
||||
end
|
||||
range_data = {}
|
||||
range_data[range[2]] = {
|
||||
from: range[0],
|
||||
to: range[1],
|
||||
}
|
||||
range_data_and = {
|
||||
range: range_data,
|
||||
}
|
||||
and_data.push range_data_and
|
||||
|
||||
data = {
|
||||
query: {
|
||||
filtered: {
|
||||
filter: {
|
||||
and: and_data,
|
||||
}
|
||||
}
|
||||
},
|
||||
size: 0,
|
||||
aggs: {
|
||||
time_buckets: {
|
||||
date_histogram: {
|
||||
field: range[2],
|
||||
interval: range[3],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data = selector2query(selectors, current_user, aggs_interval)
|
||||
|
||||
Rails.logger.info "# curl -X POST \"#{url}\" \\"
|
||||
Rails.logger.debug " -d'#{data.to_json}'"
|
||||
|
@ -345,9 +307,114 @@ return aggregation result
|
|||
return []
|
||||
end
|
||||
Rails.logger.debug response.data.to_json
|
||||
|
||||
if !aggs_interval || !aggs_interval[:interval]
|
||||
ticket_ids = []
|
||||
response.data['hits']['hits'].each {|item|
|
||||
ticket_ids.push item['_id']
|
||||
}
|
||||
return {
|
||||
count: response.data['hits']['total'],
|
||||
ticket_ids: ticket_ids,
|
||||
}
|
||||
end
|
||||
response.data
|
||||
end
|
||||
|
||||
def self.selector2query(selector, _current_user, aggs_interval)
|
||||
filter_must = []
|
||||
filter_must_not = []
|
||||
query_must = []
|
||||
query_must_not = []
|
||||
if selector && !selector.empty?
|
||||
selector.each {|key, data|
|
||||
key_tmp = key.sub(/^.+?\./, '')
|
||||
t = {}
|
||||
if data['value'].class == Array
|
||||
t[:terms] = {}
|
||||
t[:terms][key_tmp] = data['value']
|
||||
else
|
||||
t[:term] = {}
|
||||
t[:term][key_tmp] = data['value']
|
||||
end
|
||||
if data['operator'] == 'is'
|
||||
filter_must.push t
|
||||
elsif data['operator'] == 'is not'
|
||||
filter_must_not.push t
|
||||
elsif data['operator'] == 'contains'
|
||||
query_must.push t
|
||||
elsif data['operator'] == 'contains not'
|
||||
query_must_not.push t
|
||||
else
|
||||
fail "unknown operator '#{data['operator']}'"
|
||||
end
|
||||
}
|
||||
end
|
||||
data = {
|
||||
query: {}
|
||||
}
|
||||
|
||||
# add aggs to filter
|
||||
if aggs_interval
|
||||
if aggs_interval[:interval]
|
||||
data[:size] = 0
|
||||
data[:aggs] = {
|
||||
time_buckets: {
|
||||
date_histogram: {
|
||||
field: aggs_interval[:field],
|
||||
interval: aggs_interval[:interval],
|
||||
}
|
||||
}
|
||||
}
|
||||
end
|
||||
r = {}
|
||||
r[:range] = {}
|
||||
r[:range][aggs_interval[:field]] = {
|
||||
from: aggs_interval[:from],
|
||||
to: aggs_interval[:to],
|
||||
}
|
||||
filter_must.push r
|
||||
end
|
||||
|
||||
if !query_must.empty? || !query_must_not.empty?
|
||||
if !data[:query][:filtered]
|
||||
data[:query][:filtered] = {}
|
||||
end
|
||||
if !data[:query][:filtered][:query]
|
||||
data[:query][:filtered][:query] = {}
|
||||
end
|
||||
if !data[:query][:filtered][:query][:bool]
|
||||
data[:query][:filtered][:query][:bool] = {}
|
||||
end
|
||||
end
|
||||
if !query_must.empty?
|
||||
data[:query][:filtered][:query][:bool][:must] = query_must
|
||||
end
|
||||
if !query_must_not.empty?
|
||||
data[:query][:filtered][:query][:bool][:must_not] = query_must_not
|
||||
end
|
||||
|
||||
if !filter_must.empty? || !filter_must.empty?
|
||||
if !data[:query][:filtered]
|
||||
data[:query][:filtered] = {}
|
||||
end
|
||||
if !data[:query][:filtered][:filter]
|
||||
data[:query][:filtered][:filter] = {}
|
||||
end
|
||||
if !data[:query][:filtered][:filter][:bool]
|
||||
data[:query][:filtered][:filter][:bool] = {}
|
||||
end
|
||||
end
|
||||
if !filter_must.empty?
|
||||
data[:query][:filtered][:filter][:bool][:must] = filter_must
|
||||
end
|
||||
if !filter_must_not.empty?
|
||||
data[:query][:filtered][:filter][:bool][:must_not] = filter_must_not
|
||||
end
|
||||
|
||||
data
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
return true if backend is configured
|
||||
|
|
747
test/integration/report_test.rb
Normal file
747
test/integration/report_test.rb
Normal file
|
@ -0,0 +1,747 @@
|
|||
# encoding: utf-8
|
||||
require 'integration_test_helper'
|
||||
|
||||
class ReportTest < ActiveSupport::TestCase
|
||||
|
||||
# set config
|
||||
if !ENV['ES_URL']
|
||||
fail "ERROR: Need ES_URL - hint ES_URL='http://172.0.0.1:9200'"
|
||||
end
|
||||
Setting.set('es_url', ENV['ES_URL'])
|
||||
if !ENV['ES_INDEX']
|
||||
fail "ERROR: Need ES_INDEX - hint ES_INDEX='estest.local_zammad'"
|
||||
end
|
||||
Setting.set('es_index', ENV['ES_INDEX'])
|
||||
|
||||
# Setting.set('es_url', 'http://172.0.0.1:9200')
|
||||
# Setting.set('es_index', 'estest.local_zammad')
|
||||
# Setting.set('es_user', 'elasticsearch')
|
||||
# Setting.set('es_password', 'zammad')
|
||||
# Setting.set('es_attachment_max_size_in_mb', 1 )
|
||||
|
||||
Ticket.destroy_all
|
||||
|
||||
# drop/create indexes
|
||||
#Rake::Task["searchindex:drop"].execute
|
||||
#Rake::Task["searchindex:create"].execute
|
||||
#system('rake searchindex:rebuild')
|
||||
|
||||
Group.create_if_not_exists(
|
||||
name: 'Report Test',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1
|
||||
)
|
||||
ticket1 = Ticket.create(
|
||||
title: 'test 1',
|
||||
group: Group.lookup(name: 'Report Test'),
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'new'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
created_at: '2015-10-28 09:30:00 UTC',
|
||||
updated_at: '2015-10-28 09:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
article1 = Ticket::Article.create(
|
||||
ticket_id: ticket1.id,
|
||||
from: 'some_sender@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message article_inbound',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.where(name: 'Customer').first,
|
||||
type: Ticket::Article::Type.where(name: 'email').first,
|
||||
created_at: '2015-10-28 09:30:00 UTC',
|
||||
updated_at: '2015-10-28 09:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
ticket1.update_attributes(
|
||||
group: Group.lookup(name: 'Users'),
|
||||
updated_at: '2015-10-28 14:30:00 UTC',
|
||||
)
|
||||
|
||||
ticket2 = Ticket.create(
|
||||
title: 'test 2',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'new'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
created_at: '2015-10-28 09:30:00 UTC',
|
||||
updated_at: '2015-10-28 09:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
article2 = Ticket::Article.create(
|
||||
ticket_id: ticket2.id,
|
||||
from: 'some_sender@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message article_inbound',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.where(name: 'Customer').first,
|
||||
type: Ticket::Article::Type.where(name: 'email').first,
|
||||
created_at: '2015-10-28 09:30:00 UTC',
|
||||
updated_at: '2015-10-28 09:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
ticket2.update_attributes(
|
||||
group_id: Group.lookup(name: 'Report Test').id,
|
||||
updated_at: '2015-10-28 14:30:00 UTC',
|
||||
)
|
||||
|
||||
ticket3 = Ticket.create(
|
||||
title: 'test 3',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'open'),
|
||||
priority: Ticket::Priority.lookup(name: '3 high'),
|
||||
created_at: '2015-10-28 10:30:00 UTC',
|
||||
updated_at: '2015-10-28 10:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
article3 = Ticket::Article.create(
|
||||
ticket_id: ticket3.id,
|
||||
from: 'some_sender@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message article_inbound',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.where(name: 'Customer').first,
|
||||
type: Ticket::Article::Type.where(name: 'email').first,
|
||||
created_at: '2015-10-28 10:30:00 UTC',
|
||||
updated_at: '2015-10-28 10:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket4 = Ticket.create(
|
||||
title: 'test 4',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'closed'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
close_time: '2015-10-28 11:30:00 UTC',
|
||||
created_at: '2015-10-28 10:30:00 UTC',
|
||||
updated_at: '2015-10-28 10:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
article4 = Ticket::Article.create(
|
||||
ticket_id: ticket4.id,
|
||||
from: 'some_sender@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message article_inbound',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.where(name: 'Customer').first,
|
||||
type: Ticket::Article::Type.where(name: 'email').first,
|
||||
created_at: '2015-10-28 10:30:00 UTC',
|
||||
updated_at: '2015-10-28 10:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket5 = Ticket.create(
|
||||
title: 'test 5',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'closed'),
|
||||
priority: Ticket::Priority.lookup(name: '3 high'),
|
||||
close_time: '2015-10-28 11:40:00 UTC',
|
||||
created_at: '2015-10-28 11:30:00 UTC',
|
||||
updated_at: '2015-10-28 11:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
article5 = Ticket::Article.create(
|
||||
ticket_id: ticket5.id,
|
||||
from: 'some_sender@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message article_outbound',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.where(name: 'Agent').first,
|
||||
type: Ticket::Article::Type.where(name: 'email').first,
|
||||
created_at: '2015-10-28 11:30:00 UTC',
|
||||
updated_at: '2015-10-28 11:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
ticket5.update_attributes(
|
||||
state: Ticket::State.lookup(name: 'open'),
|
||||
updated_at: '2015-10-28 14:30:00 UTC',
|
||||
)
|
||||
|
||||
ticket6 = Ticket.create(
|
||||
title: 'test 6',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'closed'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
close_time: '2015-10-31 12:35:00 UTC',
|
||||
created_at: '2015-10-31 12:30:00 UTC',
|
||||
updated_at: '2015-10-31 12:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
article6 = Ticket::Article.create(
|
||||
ticket_id: ticket6.id,
|
||||
from: 'some_sender@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message article_outbound',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.where(name: 'Agent').first,
|
||||
type: Ticket::Article::Type.where(name: 'email').first,
|
||||
created_at: '2015-10-31 12:30:00 UTC',
|
||||
updated_at: '2015-10-31 12:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket7 = Ticket.create(
|
||||
title: 'test 7',
|
||||
group: Group.lookup(name: 'Users'),
|
||||
customer_id: 2,
|
||||
state: Ticket::State.lookup(name: 'closed'),
|
||||
priority: Ticket::Priority.lookup(name: '2 normal'),
|
||||
close_time: '2015-11-01 12:30:00 UTC',
|
||||
created_at: '2015-11-01 12:30:00 UTC',
|
||||
updated_at: '2015-11-01 12:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
article7 = Ticket::Article.create(
|
||||
ticket_id: ticket7.id,
|
||||
from: 'some_sender@example.com',
|
||||
to: 'some_recipient@example.com',
|
||||
subject: 'some subject',
|
||||
message_id: 'some@id',
|
||||
body: 'some message article_outbound',
|
||||
internal: false,
|
||||
sender: Ticket::Article::Sender.where(name: 'Agent').first,
|
||||
type: Ticket::Article::Type.where(name: 'email').first,
|
||||
created_at: '2015-11-01 12:30:00 UTC',
|
||||
updated_at: '2015-11-01 12:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
# execute background jobs
|
||||
#puts Delayed::Job.all.inspect
|
||||
Delayed::Worker.new.work_off
|
||||
|
||||
sleep 6
|
||||
|
||||
test 'first solution' do
|
||||
|
||||
# month
|
||||
result = Report::TicketFirstSolution.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(2, result[9])
|
||||
assert_equal(1, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_equal(nil, result[12])
|
||||
|
||||
result = Report::TicketFirstSolution.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(ticket5.id, result[:ticket_ids][0])
|
||||
assert_equal(ticket6.id, result[:ticket_ids][1])
|
||||
assert_equal(ticket7.id, result[:ticket_ids][2])
|
||||
assert_equal(nil, result[:ticket_ids][3])
|
||||
|
||||
# month - with selector #1
|
||||
result = Report::TicketFirstSolution.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {
|
||||
'ticket.priority_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => [Ticket::Priority.lookup(name: '3 high').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(1, result[9])
|
||||
assert_equal(0, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_equal(nil, result[12])
|
||||
|
||||
result = Report::TicketFirstSolution.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {
|
||||
'ticket.priority_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => [Ticket::Priority.lookup(name: '3 high').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(ticket5.id, result[:ticket_ids][0])
|
||||
assert_equal(nil, result[:ticket_ids][1])
|
||||
|
||||
# month - with selector #2
|
||||
result = Report::TicketFirstSolution.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {
|
||||
'ticket.priority_id' => {
|
||||
'operator' => 'is not',
|
||||
'value' => [Ticket::Priority.lookup(name: '3 high').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(1, result[9])
|
||||
assert_equal(1, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_equal(nil, result[12])
|
||||
|
||||
result = Report::TicketFirstSolution.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {
|
||||
'ticket.priority_id' => {
|
||||
'operator' => 'is not',
|
||||
'value' => [Ticket::Priority.lookup(name: '3 high').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(ticket6.id, result[:ticket_ids][0])
|
||||
assert_equal(ticket7.id, result[:ticket_ids][1])
|
||||
assert_equal(nil, result[:ticket_ids][2])
|
||||
|
||||
# week
|
||||
result = Report::TicketFirstSolution.aggs(
|
||||
range_start: '2015-10-26T00:00:00Z',
|
||||
range_end: '2015-10-31T23:59:59Z',
|
||||
interval: 'week', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(1, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(1, result[5])
|
||||
assert_equal(1, result[6])
|
||||
assert_equal(nil, result[7])
|
||||
|
||||
result = Report::TicketFirstSolution.items(
|
||||
range_start: '2015-10-26T00:00:00Z',
|
||||
range_end: '2015-11-01T23:59:59Z',
|
||||
interval: 'week', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(ticket5.id, result[:ticket_ids][0])
|
||||
assert_equal(ticket6.id, result[:ticket_ids][1])
|
||||
assert_equal(ticket7.id, result[:ticket_ids][2])
|
||||
assert_equal(nil, result[:ticket_ids][3])
|
||||
|
||||
# day
|
||||
result = Report::TicketFirstSolution.aggs(
|
||||
range_start: '2015-10-01T00:00:00Z',
|
||||
range_end: '2015-11-01T23:59:59Z',
|
||||
interval: 'day', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(0, result[9])
|
||||
assert_equal(0, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_equal(0, result[12])
|
||||
assert_equal(0, result[13])
|
||||
assert_equal(0, result[14])
|
||||
assert_equal(0, result[15])
|
||||
assert_equal(0, result[16])
|
||||
assert_equal(0, result[17])
|
||||
assert_equal(0, result[18])
|
||||
assert_equal(0, result[19])
|
||||
assert_equal(0, result[20])
|
||||
assert_equal(0, result[21])
|
||||
assert_equal(0, result[22])
|
||||
assert_equal(0, result[23])
|
||||
assert_equal(0, result[24])
|
||||
assert_equal(0, result[25])
|
||||
assert_equal(0, result[26])
|
||||
assert_equal(1, result[27])
|
||||
assert_equal(0, result[28])
|
||||
assert_equal(0, result[29])
|
||||
assert_equal(1, result[30])
|
||||
assert_equal(nil, result[31])
|
||||
|
||||
result = Report::TicketFirstSolution.items(
|
||||
range_start: '2015-10-01T00:00:00Z',
|
||||
range_end: '2015-10-31T23:59:59Z',
|
||||
interval: 'day', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(ticket5.id, result[:ticket_ids][0])
|
||||
assert_equal(ticket6.id, result[:ticket_ids][1])
|
||||
assert_equal(nil, result[:ticket_ids][2])
|
||||
|
||||
# hour
|
||||
result = Report::TicketFirstSolution.aggs(
|
||||
range_start: '2015-10-28T00:00:00Z',
|
||||
range_end: '2015-10-28T23:59:59Z',
|
||||
interval: 'hour', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(0, result[9])
|
||||
assert_equal(0, result[10])
|
||||
assert_equal(1, result[11])
|
||||
assert_equal(0, result[12])
|
||||
assert_equal(0, result[13])
|
||||
assert_equal(0, result[14])
|
||||
assert_equal(0, result[15])
|
||||
assert_equal(0, result[16])
|
||||
assert_equal(0, result[17])
|
||||
assert_equal(0, result[18])
|
||||
assert_equal(0, result[19])
|
||||
assert_equal(0, result[20])
|
||||
assert_equal(0, result[21])
|
||||
assert_equal(0, result[22])
|
||||
assert_equal(0, result[23])
|
||||
assert_equal(nil, result[24])
|
||||
|
||||
result = Report::TicketFirstSolution.items(
|
||||
range_start: '2015-10-28T00:00:00Z',
|
||||
range_end: '2015-10-28T23:59:59Z',
|
||||
interval: 'hour', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(ticket5.id, result[:ticket_ids][0])
|
||||
assert_equal(nil, result[:ticket_ids][1])
|
||||
|
||||
# created by channel and direction
|
||||
end
|
||||
|
||||
test 'reopen' do
|
||||
|
||||
# month
|
||||
result = Report::TicketReopened.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(1, result[9])
|
||||
assert_equal(0, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_equal(nil, result[12])
|
||||
|
||||
result = Report::TicketReopened.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(ticket5.id, result[:ticket_ids][0])
|
||||
assert_equal(nil, result[:ticket_ids][1])
|
||||
|
||||
# month - with selector #1
|
||||
result = Report::TicketReopened.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {
|
||||
'ticket.priority_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => [Ticket::Priority.lookup(name: '3 high').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(1, result[9])
|
||||
assert_equal(0, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_equal(nil, result[12])
|
||||
|
||||
result = Report::TicketReopened.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {
|
||||
'ticket.priority_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => [Ticket::Priority.lookup(name: '3 high').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(ticket5.id, result[:ticket_ids][0])
|
||||
assert_equal(nil, result[:ticket_ids][1])
|
||||
|
||||
# month - with selector #2
|
||||
result = Report::TicketReopened.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {
|
||||
'ticket.priority_id' => {
|
||||
'operator' => 'is not',
|
||||
'value' => [Ticket::Priority.lookup(name: '3 high').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(0, result[9])
|
||||
assert_equal(0, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_equal(nil, result[12])
|
||||
|
||||
result = Report::TicketReopened.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {
|
||||
'ticket.priority_id' => {
|
||||
'operator' => 'is not',
|
||||
'value' => [Ticket::Priority.lookup(name: '3 high').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(nil, result[:ticket_ids][0])
|
||||
|
||||
end
|
||||
|
||||
test 'move in/out' do
|
||||
|
||||
# month
|
||||
result = Report::TicketMoved.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {
|
||||
'ticket.group_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => [Group.lookup(name: 'Users').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
params: {
|
||||
type: 'in',
|
||||
},
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(1, result[9])
|
||||
assert_equal(0, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_equal(nil, result[12])
|
||||
|
||||
result = Report::TicketMoved.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {
|
||||
'ticket.group_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => [Group.lookup(name: 'Users').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
params: {
|
||||
type: 'in',
|
||||
},
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(ticket1.id, result[:ticket_ids][0])
|
||||
assert_equal(nil, result[:ticket_ids][1])
|
||||
|
||||
# out
|
||||
result = Report::TicketMoved.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {
|
||||
'ticket.group_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => [Group.lookup(name: 'Users').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
params: {
|
||||
type: 'out',
|
||||
},
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(1, result[9])
|
||||
assert_equal(0, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_equal(nil, result[12])
|
||||
|
||||
result = Report::TicketMoved.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {
|
||||
'ticket.group_id' => {
|
||||
'operator' => 'is',
|
||||
'value' => [Group.lookup(name: 'Users').id],
|
||||
}
|
||||
}, # ticket selector to get only a collection of tickets
|
||||
params: {
|
||||
type: 'out',
|
||||
},
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(ticket2.id, result[:ticket_ids][0])
|
||||
assert_equal(nil, result[:ticket_ids][1])
|
||||
|
||||
end
|
||||
|
||||
test 'created at' do
|
||||
|
||||
# month
|
||||
result = Report::TicketGenericTime.aggs(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
interval: 'month', # year, quarter, month, week, day, hour, minute, second
|
||||
selector: {}, # ticket selector to get only a collection of tickets
|
||||
params: { field: 'created_at' },
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(0, result[0])
|
||||
assert_equal(0, result[1])
|
||||
assert_equal(0, result[2])
|
||||
assert_equal(0, result[3])
|
||||
assert_equal(0, result[4])
|
||||
assert_equal(0, result[5])
|
||||
assert_equal(0, result[6])
|
||||
assert_equal(0, result[7])
|
||||
assert_equal(0, result[8])
|
||||
assert_equal(6, result[9])
|
||||
assert_equal(1, result[10])
|
||||
assert_equal(0, result[11])
|
||||
assert_equal(nil, result[12])
|
||||
|
||||
result = Report::TicketGenericTime.items(
|
||||
range_start: '2015-01-01T00:00:00Z',
|
||||
range_end: '2015-12-31T23:59:59Z',
|
||||
selector: {}, # ticket selector to get only a collection of tickets
|
||||
params: { field: 'created_at' },
|
||||
)
|
||||
assert(result)
|
||||
assert_equal(ticket1.id, result[:ticket_ids][0])
|
||||
assert_equal(ticket2.id, result[:ticket_ids][1])
|
||||
assert_equal(ticket3.id, result[:ticket_ids][2])
|
||||
assert_equal(ticket4.id, result[:ticket_ids][3])
|
||||
assert_equal(ticket5.id, result[:ticket_ids][4])
|
||||
assert_equal(ticket6.id, result[:ticket_ids][5])
|
||||
assert_equal(ticket7.id, result[:ticket_ids][6])
|
||||
assert_equal(nil, result[:ticket_ids][7])
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in a new issue