Init version of SLA calculation.
This commit is contained in:
parent
77a4167b72
commit
f7f55c52f0
10 changed files with 152 additions and 23 deletions
1
Gemfile
1
Gemfile
|
@ -76,4 +76,5 @@ group :development, :test do
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
gem 'business_time'
|
||||||
gem 'thin'
|
gem 'thin'
|
||||||
|
|
|
@ -421,6 +421,8 @@ class App.ControllerForm extends App.Controller
|
||||||
|
|
||||||
# radio
|
# radio
|
||||||
else if attribute.tag is 'working_hour'
|
else if attribute.tag is 'working_hour'
|
||||||
|
if !attribute.value
|
||||||
|
attribute.value = {}
|
||||||
item = $( App.view('generic/working_hour')( attribute: attribute ) )
|
item = $( App.view('generic/working_hour')( attribute: attribute ) )
|
||||||
|
|
||||||
# ticket attribute selection
|
# ticket attribute selection
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
$ = jQuery.sub()
|
|
||||||
|
|
||||||
class Index extends App.Controller
|
class Index extends App.Controller
|
||||||
constructor: ->
|
constructor: ->
|
||||||
super
|
super
|
||||||
|
|
|
@ -1,18 +1,26 @@
|
||||||
class App.Sla extends Spine.Model
|
class App.Sla extends Spine.Model
|
||||||
@configure 'Sla', 'name', 'condition', 'data', 'active'
|
@configure 'Sla', 'name', 'first_response_time', 'update_time', 'close_time', 'condition', 'data', 'active'
|
||||||
@extend Spine.Model.Ajax
|
@extend Spine.Model.Ajax
|
||||||
@url: 'api/slas'
|
@url: 'api/slas'
|
||||||
@configure_attributes = [
|
@configure_attributes = [
|
||||||
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false, 'class': 'span4' },
|
{ name: 'name', display: 'Name', tag: 'input', type: 'text', limit: 100, null: false, 'class': 'span4' },
|
||||||
{ name: 'first_response_time', display: 'First Resposne Time', tag: 'input', type: 'text', limit: 100, null: true, 'class': 'span4' },
|
{ name: 'first_response_time', display: 'First Resposne Time', tag: 'input', type: 'text', limit: 100, null: true, 'class': 'span4' },
|
||||||
{ name: 'update_time', display: 'Update Time', tag: 'input', type: 'text', limit: 100, null: true, 'class': 'span4' },
|
{ name: 'update_time', display: 'Update Time', tag: 'input', type: 'text', limit: 100, null: true, 'class': 'span4' },
|
||||||
{ name: 'solution_time', display: 'Solution Time', tag: 'input', type: 'text', limit: 100, null: true, 'class': 'span4' },
|
{ name: 'close_time', display: 'Solution Time', tag: 'input', type: 'text', limit: 100, null: true, 'class': 'span4' },
|
||||||
{ name: 'condition', display: 'Conditions where SLA is used', tag: 'ticket_attribute_selection', null: true, class: 'span4' },
|
{ name: 'condition', display: 'Conditions where SLA is used', tag: 'ticket_attribute_selection', null: true, class: 'span4' },
|
||||||
{
|
{
|
||||||
name: 'working_hour'
|
name: 'data'
|
||||||
display: 'Working Hours'
|
display: 'Working Hours'
|
||||||
tag: 'working_hour'
|
tag: 'working_hour'
|
||||||
default: ''
|
default: {
|
||||||
|
Mon: true
|
||||||
|
Tue: true
|
||||||
|
Wed: true
|
||||||
|
Thu: true
|
||||||
|
Fri: true
|
||||||
|
beginning_of_workday: '8:00'
|
||||||
|
end_of_workday: '18:00'
|
||||||
|
}
|
||||||
null: true
|
null: true
|
||||||
nulloption: true
|
nulloption: true
|
||||||
translate: true
|
translate: true
|
||||||
|
|
|
@ -1,19 +1,24 @@
|
||||||
<table>
|
<label><%- @T('Days') %></label>
|
||||||
|
<table style="width:70%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<% for hour in [ 0 .. 23 ]: %>
|
<% for day in ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']: %>
|
||||||
<th><%- hour %></th>
|
<td><%- @T(day) %></td>
|
||||||
<% end %>
|
<% end %>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<% for day in ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']: %>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><%- @T(day) %></td>
|
<% for day in ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']: %>
|
||||||
<% for hour in [ 0 .. 23 ]: %>
|
<td style="padding:2px"><input type="checkbox" name="<%= @attribute.name %>::<%- day %>" value="<%- day %>" <% if @attribute.value[day]: %>checked<% end %> /></td>
|
||||||
<td><input type="checkbox" value="1" name="<%- day %>-<%- hour %>"></td>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
</tr>
|
</tr>
|
||||||
<% end %>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<div class="">
|
||||||
|
<label><%- @T('Hours') %></label>
|
||||||
|
<input type="text" class="span2" name="<%= @attribute.name %>::beginning_of_workday" value="<%= @attribute.value['beginning_of_workday'] %>"/>
|
||||||
|
-
|
||||||
|
<input type="text" class="span2" name="<%= @attribute.name %>::end_of_workday" value="<%= @attribute.value['end_of_workday'] %>"/>
|
||||||
|
</div>
|
26
app/models/observer/ticket/escalation_calculation.rb
Normal file
26
app/models/observer/ticket/escalation_calculation.rb
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
class Observer::Ticket::EscalationCalculation < ActiveRecord::Observer
|
||||||
|
observe 'ticket', 'ticket::_article'
|
||||||
|
|
||||||
|
def after_create(record)
|
||||||
|
end
|
||||||
|
|
||||||
|
def after_update(record)
|
||||||
|
|
||||||
|
# return if we run import mode
|
||||||
|
return if Setting.get('import_mode')
|
||||||
|
|
||||||
|
# prevent loops
|
||||||
|
return if record[:escalation_calc]
|
||||||
|
record[:escalation_calc] = true
|
||||||
|
|
||||||
|
# do not recalculation if first respons is already out
|
||||||
|
if record.class.name == 'Ticket::Article'
|
||||||
|
return true if record.ticket.first_response
|
||||||
|
record.ticket.escalation_calculation
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
# update escalation
|
||||||
|
record.escalation_calculation
|
||||||
|
end
|
||||||
|
end
|
|
@ -403,6 +403,81 @@ class Ticket < ApplicationModel
|
||||||
return adapter
|
return adapter
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def escalation_calculation
|
||||||
|
|
||||||
|
# get sla
|
||||||
|
sla_selected = nil
|
||||||
|
Sla.where( :active => true ).each {|sla|
|
||||||
|
if sla.condition
|
||||||
|
puts sla.condition.inspect
|
||||||
|
hit = false
|
||||||
|
if sla.condition['tickets.ticket_priority_id']
|
||||||
|
if sla.condition['tickets.ticket_priority_id'].class == String
|
||||||
|
sla.condition['tickets.ticket_priority_id'] = [ sla.condition['tickets.ticket_priority_id'].to_i ]
|
||||||
|
end
|
||||||
|
if sla.condition['tickets.ticket_priority_id'].include?( self.ticket_priority_id )
|
||||||
|
hit = true
|
||||||
|
else
|
||||||
|
hit = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if hit
|
||||||
|
sla_selected = sla
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
return if !sla_selected
|
||||||
|
|
||||||
|
# get calendar settings
|
||||||
|
BusinessTime::Config.beginning_of_workday = sla_selected.data['beginning_of_workday']
|
||||||
|
BusinessTime::Config.end_of_workday = sla_selected.data['end_of_workday']
|
||||||
|
days = []
|
||||||
|
['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'].each {|day|
|
||||||
|
if sla_selected.data[day]
|
||||||
|
days.push day.downcase.to_sym
|
||||||
|
end
|
||||||
|
}
|
||||||
|
BusinessTime::Config.work_week = days
|
||||||
|
# puts sla_selected.inspect
|
||||||
|
# puts days.inspect
|
||||||
|
|
||||||
|
# first response
|
||||||
|
if sla_selected.first_response_time
|
||||||
|
created_at = Time.parse(self.created_at.to_s)
|
||||||
|
self.first_response_escal_date = (sla_selected.first_response_time / 60).round.business_hour.after( created_at )
|
||||||
|
# self.first_response_sla_time =
|
||||||
|
#!self.first_response &&
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.first_response && !self.first_response_in_min
|
||||||
|
created_at = Time.parse(self.created_at.to_s)
|
||||||
|
first_response_at = Time.parse(self.first_response.to_s)
|
||||||
|
diff = created_at.business_time_until(first_response_at) / 60
|
||||||
|
self.first_response_in_min = diff.round
|
||||||
|
end
|
||||||
|
|
||||||
|
# # update time
|
||||||
|
# if sla_selected.close_time
|
||||||
|
# created_at = Time.parse(self.created_at.to_s)
|
||||||
|
# self.close_time_escal_date = (sla_selected.close_time / 60).round.business_hour.after( created_at )
|
||||||
|
# end
|
||||||
|
|
||||||
|
# close time
|
||||||
|
if sla_selected.close_time
|
||||||
|
created_at = Time.parse(self.created_at.to_s)
|
||||||
|
self.close_time_escal_date = (sla_selected.close_time / 60).round.business_hour.after( created_at )
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.close_time && !self.close_time_in_min
|
||||||
|
created_at = Time.parse(self.created_at.to_s)
|
||||||
|
closed_at = Time.parse(self.close_time.to_s)
|
||||||
|
diff = created_at.business_time_until(closed_at) / 60
|
||||||
|
self.close_time_in_min = diff.round
|
||||||
|
end
|
||||||
|
|
||||||
|
self.save
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def number_generate
|
def number_generate
|
||||||
|
|
|
@ -40,7 +40,8 @@ module Zammad
|
||||||
'observer::_ticket::_article::_communicate_twitter',
|
'observer::_ticket::_article::_communicate_twitter',
|
||||||
'observer::_ticket::_notification',
|
'observer::_ticket::_notification',
|
||||||
'observer::_tag::_ticket_history',
|
'observer::_tag::_ticket_history',
|
||||||
'observer::_ticket::_reset_new_state'
|
'observer::_ticket::_reset_new_state',
|
||||||
|
'observer::_ticket::_escalation_calculation'
|
||||||
|
|
||||||
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
||||||
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
||||||
|
|
|
@ -2,6 +2,9 @@ class CreateSla < ActiveRecord::Migration
|
||||||
def up
|
def up
|
||||||
create_table :slas do |t|
|
create_table :slas do |t|
|
||||||
t.column :name, :string, :limit => 150, :null => true
|
t.column :name, :string, :limit => 150, :null => true
|
||||||
|
# t.column :first_response_time, :integer, :null => true
|
||||||
|
# t.column :update_time, :integer, :null => true
|
||||||
|
# t.column :close_time, :integer, :null => true
|
||||||
t.column :condition, :string, :limit => 5000, :null => true
|
t.column :condition, :string, :limit => 5000, :null => true
|
||||||
t.column :data, :string, :limit => 5000, :null => true
|
t.column :data, :string, :limit => 5000, :null => true
|
||||||
t.column :active, :boolean, :null => false, :default => true
|
t.column :active, :boolean, :null => false, :default => true
|
||||||
|
|
10
db/migrate/20130305111945_update_sla.rb
Normal file
10
db/migrate/20130305111945_update_sla.rb
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
class UpdateSla < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
add_column :slas, :first_response_time, :integer, :null => true
|
||||||
|
add_column :slas, :update_time, :integer, :null => true
|
||||||
|
add_column :slas, :close_time, :integer, :null => true
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue