From f7f55c52f0ef760ed3ea4ff426c9e955b856bce8 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Tue, 5 Mar 2013 13:31:23 +0100 Subject: [PATCH] Init version of SLA calculation. --- Gemfile | 1 + .../_application_controller_form.js.coffee | 2 + .../javascripts/app/controllers/sla.js.coffee | 2 - .../javascripts/app/models/sla.js.coffee | 18 +++-- .../app/views/generic/working_hour.jst.eco | 23 +++--- .../observer/ticket/escalation_calculation.rb | 26 +++++++ app/models/ticket.rb | 75 +++++++++++++++++++ config/application.rb | 3 +- db/migrate/20130201071513_create_sla.rb | 15 ++-- db/migrate/20130305111945_update_sla.rb | 10 +++ 10 files changed, 152 insertions(+), 23 deletions(-) create mode 100644 app/models/observer/ticket/escalation_calculation.rb create mode 100644 db/migrate/20130305111945_update_sla.rb diff --git a/Gemfile b/Gemfile index 85c4b0639..06ad6d70a 100644 --- a/Gemfile +++ b/Gemfile @@ -76,4 +76,5 @@ group :development, :test do end +gem 'business_time' gem 'thin' diff --git a/app/assets/javascripts/app/controllers/_application_controller_form.js.coffee b/app/assets/javascripts/app/controllers/_application_controller_form.js.coffee index 1eb8526fc..b2d9829f6 100644 --- a/app/assets/javascripts/app/controllers/_application_controller_form.js.coffee +++ b/app/assets/javascripts/app/controllers/_application_controller_form.js.coffee @@ -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 diff --git a/app/assets/javascripts/app/controllers/sla.js.coffee b/app/assets/javascripts/app/controllers/sla.js.coffee index 8336004c5..acefecbdf 100644 --- a/app/assets/javascripts/app/controllers/sla.js.coffee +++ b/app/assets/javascripts/app/controllers/sla.js.coffee @@ -1,5 +1,3 @@ -$ = jQuery.sub() - class Index extends App.Controller constructor: -> super diff --git a/app/assets/javascripts/app/models/sla.js.coffee b/app/assets/javascripts/app/models/sla.js.coffee index 9e0e5c4eb..83236547b 100644 --- a/app/assets/javascripts/app/models/sla.js.coffee +++ b/app/assets/javascripts/app/models/sla.js.coffee @@ -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 diff --git a/app/assets/javascripts/app/views/generic/working_hour.jst.eco b/app/assets/javascripts/app/views/generic/working_hour.jst.eco index 4e24b22a2..0ac121c0e 100644 --- a/app/assets/javascripts/app/views/generic/working_hour.jst.eco +++ b/app/assets/javascripts/app/views/generic/working_hour.jst.eco @@ -1,19 +1,24 @@ - + +
-<% for hour in [ 0 .. 23 ]: %> - +<% for day in ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']: %> + <% end %> -<% for day in ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']: %> - -<% for hour in [ 0 .. 23 ]: %> - +<% for day in ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']: %> + <% end %> -<% end %> -
<%- hour %><%- @T(day) %>
<%- @T(day) %>checked<% end %> />
\ No newline at end of file + + +
+ + +- + +
\ No newline at end of file diff --git a/app/models/observer/ticket/escalation_calculation.rb b/app/models/observer/ticket/escalation_calculation.rb new file mode 100644 index 000000000..62bf1ff56 --- /dev/null +++ b/app/models/observer/ticket/escalation_calculation.rb @@ -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 \ No newline at end of file diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 976ee3adf..ce98e2e6e 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -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 diff --git a/config/application.rb b/config/application.rb index 7a156ec7c..cd341ba18 100644 --- a/config/application.rb +++ b/config/application.rb @@ -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. diff --git a/db/migrate/20130201071513_create_sla.rb b/db/migrate/20130201071513_create_sla.rb index 5dc95e6c4..e70b50af4 100644 --- a/db/migrate/20130201071513_create_sla.rb +++ b/db/migrate/20130201071513_create_sla.rb @@ -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 diff --git a/db/migrate/20130305111945_update_sla.rb b/db/migrate/20130305111945_update_sla.rb new file mode 100644 index 000000000..bba8b93ea --- /dev/null +++ b/db/migrate/20130305111945_update_sla.rb @@ -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