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
|
||||
|
||||
gem 'business_time'
|
||||
gem 'thin'
|
||||
|
|
|
@ -421,6 +421,8 @@ class App.ControllerForm extends App.Controller
|
|||
|
||||
# radio
|
||||
else if attribute.tag is 'working_hour'
|
||||
if !attribute.value
|
||||
attribute.value = {}
|
||||
item = $( App.view('generic/working_hour')( attribute: attribute ) )
|
||||
|
||||
# ticket attribute selection
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
$ = jQuery.sub()
|
||||
|
||||
class Index extends App.Controller
|
||||
constructor: ->
|
||||
super
|
||||
|
|
|
@ -1,18 +1,26 @@
|
|||
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
|
||||
@url: 'api/slas'
|
||||
@configure_attributes = [
|
||||
{ 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: '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: 'condition', display: 'Conditions where SLA is used', tag: 'ticket_attribute_selection', 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: 'working_hour'
|
||||
name: 'data'
|
||||
display: 'Working Hours'
|
||||
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
|
||||
nulloption: true
|
||||
translate: true
|
||||
|
|
|
@ -1,19 +1,24 @@
|
|||
<table>
|
||||
<label><%- @T('Days') %></label>
|
||||
<table style="width:70%">
|
||||
<thead>
|
||||
<tr>
|
||||
<% for hour in [ 0 .. 23 ]: %>
|
||||
<th><%- hour %></th>
|
||||
<% for day in ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']: %>
|
||||
<td><%- @T(day) %></td>
|
||||
<% end %>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% for day in ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']: %>
|
||||
<tr>
|
||||
<td><%- @T(day) %></td>
|
||||
<% for hour in [ 0 .. 23 ]: %>
|
||||
<td><input type="checkbox" value="1" name="<%- day %>-<%- hour %>"></td>
|
||||
<% for day in ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']: %>
|
||||
<td style="padding:2px"><input type="checkbox" name="<%= @attribute.name %>::<%- day %>" value="<%- day %>" <% if @attribute.value[day]: %>checked<% end %> /></td>
|
||||
<% end %>
|
||||
</tr>
|
||||
<% end %>
|
||||
</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
|
||||
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
|
||||
|
||||
def number_generate
|
||||
|
|
|
@ -40,7 +40,8 @@ module Zammad
|
|||
'observer::_ticket::_article::_communicate_twitter',
|
||||
'observer::_ticket::_notification',
|
||||
'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.
|
||||
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
class CreateSla < ActiveRecord::Migration
|
||||
def up
|
||||
create_table :slas do |t|
|
||||
t.column :name, :string, :limit => 150, :null => true
|
||||
t.column :condition, :string, :limit => 5000, :null => true
|
||||
t.column :data, :string, :limit => 5000, :null => true
|
||||
t.column :active, :boolean, :null => false, :default => true
|
||||
t.column :updated_by_id, :integer, :null => false
|
||||
t.column :created_by_id, :integer, :null => false
|
||||
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 :data, :string, :limit => 5000, :null => true
|
||||
t.column :active, :boolean, :null => false, :default => true
|
||||
t.column :updated_by_id, :integer, :null => false
|
||||
t.column :created_by_id, :integer, :null => false
|
||||
t.timestamps
|
||||
end
|
||||
add_index :slas, [:name], :unique => 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