From c239d32f1cd6510d026d5cd47843522cd4803fbb Mon Sep 17 00:00:00 2001 From: Johannes Nickel Date: Tue, 11 Jun 2013 14:53:15 +0200 Subject: [PATCH 01/10] browser check --- .../app/lib/app_post/browser_check.js.coffee | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 app/assets/javascripts/app/lib/app_post/browser_check.js.coffee diff --git a/app/assets/javascripts/app/lib/app_post/browser_check.js.coffee b/app/assets/javascripts/app/lib/app_post/browser_check.js.coffee new file mode 100644 index 000000000..e0e7beb24 --- /dev/null +++ b/app/assets/javascripts/app/lib/app_post/browser_check.js.coffee @@ -0,0 +1,99 @@ +class App.browser extends App.Contoller + constructor: -> + + + init: -> + @browser = @searchString(@dataBrowser) or "An unknown browser" + @version = @searchVersion(navigator.userAgent) or @searchVersion(navigator.appVersion) or "an unknown version" + @OS = @searchString(@dataOS) or "an unknown OS" + + searchString: (data) -> + i = 0 + + while i < data.length + dataString = data[i].string + dataProp = data[i].prop + @versionSearchString = data[i].versionSearch or data[i].identity + if dataString + return data[i].identity unless dataString.indexOf(data[i].subString) is -1 + else return data[i].identity if dataProp + i++ + + searchVersion: (dataString) -> + index = dataString.indexOf(@versionSearchString) + return if index is -1 + parseFloat dataString.substring(index + @versionSearchString.length + 1) + + dataBrowser: [ + string: navigator.userAgent + subString: "Chrome" + identity: "Chrome" + , + string: navigator.userAgent + subString: "OmniWeb" + versionSearch: "OmniWeb/" + identity: "OmniWeb" + , + string: navigator.vendor + subString: "Apple" + identity: "Safari" + versionSearch: "Version" + , + prop: window.opera + identity: "Opera" + versionSearch: "Version" + , + string: navigator.vendor + subString: "iCab" + identity: "iCab" + , + string: navigator.vendor + subString: "KDE" + identity: "Konqueror" + , + string: navigator.userAgent + subString: "Firefox" + identity: "Firefox" + , + string: navigator.vendor + subString: "Camino" + identity: "Camino" + , + # for newer Netscapes (6+) + string: navigator.userAgent + subString: "Netscape" + identity: "Netscape" + , + string: navigator.userAgent + subString: "MSIE" + identity: "Explorer" + versionSearch: "MSIE" + , + string: navigator.userAgent + subString: "Gecko" + identity: "Mozilla" + versionSearch: "rv" + , + # for older Netscapes (4-) + string: navigator.userAgent + subString: "Mozilla" + identity: "Netscape" + versionSearch: "Mozilla" + ] + dataOS: [ + string: navigator.platform + subString: "Win" + identity: "Windows" + , + string: navigator.platform + subString: "Mac" + identity: "Mac" + , + string: navigator.userAgent + subString: "iPhone" + identity: "iPhone/iPod" + , + string: navigator.platform + subString: "Linux" + identity: "Linux" + ] From 26445e01e3a6bc8b198c83e10385660ce65e9a4f Mon Sep 17 00:00:00 2001 From: Johannes Nickel Date: Wed, 12 Jun 2013 16:57:29 +0200 Subject: [PATCH 02/10] 'alten' stand wieder hergestellt --- app/models/ticket.rb | 93 +++++++++++++++++++++++++++++++- test/unit/ticket_test.rb | 114 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+), 1 deletion(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index b35b545da..143ac55c0 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -610,7 +610,9 @@ class Ticket < ApplicationModel # first response if sla_selected.first_response_time self.first_response_escal_date = TimeCalculation.dest_time( created_at, sla_selected.first_response_time, sla_selected.data, sla_selected.timezone ) - + extended_escalation = escalation_suspend( self.first_response_escal_date, 'relative', sla_selected.timezone) + self.first_response_escal_date = TimeCalculation.dest_time( self.first_response_escal_date, extended_escalation.to_i, sla_selected.timezone) + # set ticket escalation self.escalation_time = self._escalation_calculation_higher_time( self.escalation_time, self.first_response_escal_date, self.first_response ) end @@ -700,6 +702,95 @@ class Ticket < ApplicationModel # delete articles self.articles.destroy_all end + #type could be: + # real - time without supsend state + # relative - only suspend time + + def escalation_suspend (end_time, type, sla_timezone) + sum_temp = 0 + total_time = 0 + #get history for ticket + history_list = History.history_list( 'Ticket', self.id, 'Ticket' ) + + #loop through hist. changes and get time + last_state = nil + last_state_change = nil + last_state_is_pending = false + history_list.each { |history_item| + + # ignore if it isn't a state change + next if history_item['history_attribute'] != 'ticket_state' + + # ignore all older state changes after first_response + next if last_state_change && last_state_change > self.first_response + + # if created_at is later then first_response, use first_response as last time + if history_item['created_at'] > self.first_response + history_item['created_at'] = self.first_response + end + + # get initial state and time + if !last_state + last_state = history_item['value_from'] + last_state_change = self.created_at + end + + # use time if ticket got from e. g. open to pending + if history_item['value_from'] != 'pending' && history_item['value_to'] == 'pending' + diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_timezone) + puts 'Diff count !=pending -> ==pending ' + diff.to_s + sum_temp = sum_temp + diff + total_time = total_time + diff + last_state_is_pending = true + + # use time if ticket got from e. g. open to open + elsif history_item['value_from'] != 'pending' && history_item['value_to'] != 'pending' + diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_timezone) + puts 'Diff count !=pending -> !=pending ' + diff.to_s + sum_temp = sum_temp + diff + total_time = total_time + diff + last_state_is_pending = false + elsif history_item['value_from'] == 'pending' && history_item['value_to'] != 'pending' + diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_timezone) + puts 'Diff count !=pending -> !=pending ' + diff.to_s + total_time = total_time + diff + last_state_is_pending = false + # no pending state, do not count + else + puts "Diff do not count #{history_item['value_from']}->#{history_item['value_to']} -> #{history_item['created_at']}" + last_state_is_pending = false + end + + # remember for next loop last state + last_state = history_item['value_to'] + last_state_change = history_item['created_at'] + } + + # if last state isnt pending, count rest + if !last_state_is_pending && last_state_change && last_state_change < end_time + diff = TimeCalculation.business_time_diff( last_state_change, end_time, sla_timezone) + sum_temp = sum_temp + diff + total_time = total_time + diff + end + + # if we have not had any state change + if !last_state_change + puts self.created_at.to_s + ' ' + end_time.to_s + ' ' + sla_timezone.to_s + diff = TimeCalculation.business_time_diff( self.created_at, end_time, sla_timezone) + sum_temp = sum_temp + diff + total_time = total_time + diff + end + puts total_time + #return sum + if (type == 'real') + return sum_temp + elsif (type == 'relative') + return total_time - sum_temp + else + return nil + end + + end class Number end diff --git a/test/unit/ticket_test.rb b/test/unit/ticket_test.rb index 6f00d1d2f..5c3f6ca53 100644 --- a/test/unit/ticket_test.rb +++ b/test/unit/ticket_test.rb @@ -569,6 +569,120 @@ class TicketTest < ActiveSupport::TestCase delete = ticket.destroy assert( delete, "ticket destroy" ) + + ticket = Ticket.create( + :title => 'some title äöüß3', + :group => Group.lookup( :name => 'Users'), + :customer_id => 2, + :ticket_state => Ticket::State.lookup( :name => 'new' ), + :ticket_priority => Ticket::Priority.lookup( :name => '2 normal' ), + :created_at => '2013-06-04 09:00:00 UTC', + :updated_at => '2013-06-04 09:00:00 UTC', + :updated_by_id => 1, + :created_by_id => 1, + ) + assert( ticket, 'ticket created' ) + + # set ticket at 10:00 to pending + History.history_create( + :history_type => 'updated', + :history_object => 'Ticket', + :history_attribute => 'ticket_state', + :o_id => ticket.id, + :id_to => 3, + :id_from => 2, + :value_from => 'open', + :value_to => 'pending', + :created_by_id => 1, + :created_at => '2013-06-04 10:00:00', + :updated_at => '2013-06-04 10:00:00' + ) + + # set ticket at 10:30 to open + History.history_create( + :history_type => 'updated', + :history_object => 'Ticket', + :history_attribute => 'ticket_state', + :o_id => ticket.id, + :id_to => 2, + :id_from => 3, + :value_from => 'pending', + :value_to => 'open', + :created_by_id => 1, + :created_at => '2013-06-04 10:30:00', + :updated_at => '2013-06-04 10:30:00' + ) + + # set ticket from 11:00 to pending + History.history_create( + :history_type => 'updated', + :history_object => 'Ticket', + :history_attribute => 'ticket_state', + :o_id => ticket.id, + :id_to => 3, + :id_from => 2, + :value_from => 'open', + :value_to => 'pending', + :created_by_id => 1, + :created_at => '2013-06-04 11:00:00', + :updated_at => '2013-06-04 11:00:00' + ) + + # set first response in time + ticket.update_attributes( + :first_response => '2013-06-04 10:45:00 UTC', + ) + # set ticket from 11:30 to closed + History.history_create( + :history_type => 'updated', + :history_object => 'Ticket', + :history_attribute => 'ticket_state', + :o_id => ticket.id, + :id_to => 3, + :id_from => 2, + :value_from => 'pending', + :value_to => 'closed', + :created_by_id => 1, + :created_at => '2013-06-04 12:00:00', + :updated_at => '2013-06-04 12:00:00' + ) + + ticket.update_attributes( + :close_time => '2013-06-04 12:00:00 UTC', + ) + + # set sla's for timezone "Europe/Berlin" summertime (+2), so UTC times are 7:00-16:00 + sla = Sla.create( + :name => 'test sla 1', + :condition => {}, + :data => { + "Mon"=>"Mon", "Tue"=>"Tue", "Wed"=>"Wed", "Thu"=>"Thu", "Fri"=>"Fri", "Sat"=>"Sat", "Sun"=>"Sun", + "beginning_of_workday" => "9:00", + "end_of_workday" => "18:00", + }, + :timezone => 'Europe/Berlin', + :first_response_time => 120, + :update_time => 180, + :close_time => 240, + :active => true, + :updated_by_id => 1, + :created_by_id => 1, + ) + ticket = Ticket.find(ticket.id) + assert_equal( ticket.escalation_time.gmtime.to_s, '2013-06-04 12:00:00 UTC', 'ticket.escalation_time verify 1' ) #check escal. time because first resp. is already done + assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-06-04 11:30:00 UTC', 'ticket.first_response_escal_date verify 1' ) + #assert_equal( ticket.first_response_in_min, 75, 'ticket.first_response_in_min verify 3' ) + #assert_equal( ticket.first_response_diff_in_min, 45, 'ticket.first_response_diff_in_min verify 3' ) + #assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-06-04 12:30:00 UTC', 'ticket.update_time_escal_date verify 1' ) + #assert_equal( ticket.close_time_escal_date.gmtime.to_s, '2013-06-04 13:30:00 UTC', 'ticket.close_time_escal_date verify 1' ) + #assert_equal( ticket.close_time_in_min, 90, 'ticket.first_response_in_min verify 3' ) + #assert_equal( ticket.close_time_diff_in_min, 150, 'ticket.first_response_diff_in_min verify 3' ) + delete = sla.destroy + assert( delete, "sla destroy" ) + + delete = ticket.destroy + assert( delete, "ticket destroy" ) + end end From e127028f1d043da0da71d3f74e72250c9bbac8b8 Mon Sep 17 00:00:00 2001 From: Johannes Nickel Date: Thu, 13 Jun 2013 09:21:35 +0200 Subject: [PATCH 03/10] transfer --- app/models/ticket.rb | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 143ac55c0..7f6beee4e 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -706,7 +706,7 @@ class Ticket < ApplicationModel # real - time without supsend state # relative - only suspend time - def escalation_suspend (end_time, type, sla_timezone) +def escalation_suspend (end_time, type, sla_selected) sum_temp = 0 total_time = 0 #get history for ticket @@ -737,7 +737,7 @@ class Ticket < ApplicationModel # use time if ticket got from e. g. open to pending if history_item['value_from'] != 'pending' && history_item['value_to'] == 'pending' - diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_timezone) + diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'],sla_selected.data, sla_selected.timezone) puts 'Diff count !=pending -> ==pending ' + diff.to_s sum_temp = sum_temp + diff total_time = total_time + diff @@ -745,13 +745,13 @@ class Ticket < ApplicationModel # use time if ticket got from e. g. open to open elsif history_item['value_from'] != 'pending' && history_item['value_to'] != 'pending' - diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_timezone) + diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_selected.data, sla_selected.timezone) puts 'Diff count !=pending -> !=pending ' + diff.to_s sum_temp = sum_temp + diff total_time = total_time + diff last_state_is_pending = false elsif history_item['value_from'] == 'pending' && history_item['value_to'] != 'pending' - diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_timezone) + diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_selected.data, sla_selected.timezone) puts 'Diff count !=pending -> !=pending ' + diff.to_s total_time = total_time + diff last_state_is_pending = false @@ -768,15 +768,14 @@ class Ticket < ApplicationModel # if last state isnt pending, count rest if !last_state_is_pending && last_state_change && last_state_change < end_time - diff = TimeCalculation.business_time_diff( last_state_change, end_time, sla_timezone) + diff = TimeCalculation.business_time_diff( last_state_change, end_time, sla_selected.data, sla_selected.timezone) sum_temp = sum_temp + diff total_time = total_time + diff end # if we have not had any state change if !last_state_change - puts self.created_at.to_s + ' ' + end_time.to_s + ' ' + sla_timezone.to_s - diff = TimeCalculation.business_time_diff( self.created_at, end_time, sla_timezone) + diff = TimeCalculation.business_time_diff( self.created_at, end_time, sla_selected.data, sla_selected.timezone) sum_temp = sum_temp + diff total_time = total_time + diff end From c6e32501f62849c9f414c4a1425e1b49a54b9cfa Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 13 Jun 2013 12:00:03 +0200 Subject: [PATCH 04/10] Added some fixes to support TimeCalculation without config and timezone. --- app/models/ticket.rb | 39 +++++++++++++++++++++++++--------- lib/time_calculation.rb | 15 +++++++++++-- test/unit/ticket_test.rb | 4 ++++ test/unit/working_time_test.rb | 14 ++++++++++++ 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 7f6beee4e..b8fb5bd17 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -610,9 +610,9 @@ class Ticket < ApplicationModel # first response if sla_selected.first_response_time self.first_response_escal_date = TimeCalculation.dest_time( created_at, sla_selected.first_response_time, sla_selected.data, sla_selected.timezone ) - extended_escalation = escalation_suspend( self.first_response_escal_date, 'relative', sla_selected.timezone) - self.first_response_escal_date = TimeCalculation.dest_time( self.first_response_escal_date, extended_escalation.to_i, sla_selected.timezone) - + extended_escalation = escalation_suspend( self.first_response_escal_date, 'relative', sla_selected ) + self.first_response_escal_date = TimeCalculation.dest_time( self.first_response_escal_date, extended_escalation.to_i, sla_selected.data, sla_selected.timezone ) + # set ticket escalation self.escalation_time = self._escalation_calculation_higher_time( self.escalation_time, self.first_response_escal_date, self.first_response ) end @@ -704,7 +704,7 @@ class Ticket < ApplicationModel end #type could be: # real - time without supsend state - # relative - only suspend time + # relative - only suspend time def escalation_suspend (end_time, type, sla_selected) sum_temp = 0 @@ -737,7 +737,11 @@ def escalation_suspend (end_time, type, sla_selected) # use time if ticket got from e. g. open to pending if history_item['value_from'] != 'pending' && history_item['value_to'] == 'pending' - diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'],sla_selected.data, sla_selected.timezone) + if sla_selected + diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'],sla_selected.data, sla_selected.timezone) + else + diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'] ) + end puts 'Diff count !=pending -> ==pending ' + diff.to_s sum_temp = sum_temp + diff total_time = total_time + diff @@ -745,13 +749,21 @@ def escalation_suspend (end_time, type, sla_selected) # use time if ticket got from e. g. open to open elsif history_item['value_from'] != 'pending' && history_item['value_to'] != 'pending' - diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_selected.data, sla_selected.timezone) + if sla_selected + diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_selected.data, sla_selected.timezone) + else + diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'] ) + end puts 'Diff count !=pending -> !=pending ' + diff.to_s sum_temp = sum_temp + diff total_time = total_time + diff last_state_is_pending = false elsif history_item['value_from'] == 'pending' && history_item['value_to'] != 'pending' - diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_selected.data, sla_selected.timezone) + if sla_selected + diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_selected.data, sla_selected.timezone) + else + diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'] ) + end puts 'Diff count !=pending -> !=pending ' + diff.to_s total_time = total_time + diff last_state_is_pending = false @@ -768,14 +780,22 @@ def escalation_suspend (end_time, type, sla_selected) # if last state isnt pending, count rest if !last_state_is_pending && last_state_change && last_state_change < end_time - diff = TimeCalculation.business_time_diff( last_state_change, end_time, sla_selected.data, sla_selected.timezone) + if sla_selected + diff = TimeCalculation.business_time_diff( last_state_change, end_time, sla_selected.data, sla_selected.timezone) + else + diff = TimeCalculation.business_time_diff( last_state_change, end_time ) + end sum_temp = sum_temp + diff total_time = total_time + diff end # if we have not had any state change if !last_state_change - diff = TimeCalculation.business_time_diff( self.created_at, end_time, sla_selected.data, sla_selected.timezone) + if sla_selected + diff = TimeCalculation.business_time_diff( self.created_at, end_time, sla_selected.data, sla_selected.timezone) + else + diff = TimeCalculation.business_time_diff( self.created_at, end_time ) + end sum_temp = sum_temp + diff total_time = total_time + diff end @@ -788,7 +808,6 @@ def escalation_suspend (end_time, type, sla_selected) else return nil end - end class Number diff --git a/lib/time_calculation.rb b/lib/time_calculation.rb index c09e0c9f4..6d995735f 100644 --- a/lib/time_calculation.rb +++ b/lib/time_calculation.rb @@ -109,7 +109,7 @@ put working hours matrix and timezone in function, returns UTC working hours mat =end - def self.business_time_diff(start_time, end_time, config, timezone = '') + def self.business_time_diff(start_time, end_time, config = nil, timezone = '') if start_time.class == String start_time = Time.parse( start_time.to_s + 'UTC' ) end @@ -117,6 +117,12 @@ put working hours matrix and timezone in function, returns UTC working hours mat end_time = Time.parse( end_time.to_s + 'UTC' ) end + # if no config is given, just return calculation directly + if !config + return ((end_time - start_time) / 60 ).round + end + + working_hours = self.working_hours(start_time, config, timezone) week_day_map = { @@ -225,11 +231,16 @@ put working hours matrix and timezone in function, returns UTC working hours mat =end - def self.dest_time(start_time, diff_in_min, config, timezone = '') + def self.dest_time(start_time, diff_in_min, config = nil, timezone = '') if start_time.class == String start_time = Time.parse( start_time.to_s + ' UTC' ) end + # if no config is given, just return calculation directly + if !config + return start_time + (diff_in_min * 60) + end + # loop working_hours = self.working_hours(start_time, config, timezone) diff --git a/test/unit/ticket_test.rb b/test/unit/ticket_test.rb index 5c3f6ca53..496e36509 100644 --- a/test/unit/ticket_test.rb +++ b/test/unit/ticket_test.rb @@ -569,6 +569,10 @@ class TicketTest < ActiveSupport::TestCase delete = ticket.destroy assert( delete, "ticket destroy" ) + end + + test 'ticket escalation suspend' do + ticket = Ticket.create( :title => 'some title äöüß3', diff --git a/test/unit/working_time_test.rb b/test/unit/working_time_test.rb index a7c01b512..1fda76c88 100644 --- a/test/unit/working_time_test.rb +++ b/test/unit/working_time_test.rb @@ -238,6 +238,13 @@ class WorkingTimeTest < ActiveSupport::TestCase 'end_of_workday' => '6:00 pm', }, }, + + # test 15 + { + :start => '2013-08-29 16:01:00', + :end => '2013-08-29 16:10:59', + :diff => 10, + }, ] tests.each { |test| diff = TimeCalculation.business_time_diff( test[:start], test[:end], test[:config], test[:timezone] ) @@ -495,6 +502,13 @@ class WorkingTimeTest < ActiveSupport::TestCase }, }, + # test 17 + { + :start => '2013-10-21 04:01:00', + :dest_time => '2013-10-21 06:00:00', + :diff => 119, + }, + ] tests.each { |test| dest_time = TimeCalculation.dest_time( test[:start] + ' UTC', test[:diff], test[:config], test[:timezone] ) From dfcfc7ab28b54900006b6f14e4d229af792e6e33 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 13 Jun 2013 13:25:28 +0200 Subject: [PATCH 05/10] Improved TimeCalculation, added unit tests. --- lib/time_calculation.rb | 11 ++++++++-- test/unit/working_time_test.rb | 38 ++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/lib/time_calculation.rb b/lib/time_calculation.rb index 6d995735f..290f0aad4 100644 --- a/lib/time_calculation.rb +++ b/lib/time_calculation.rb @@ -236,6 +236,8 @@ put working hours matrix and timezone in function, returns UTC working hours mat start_time = Time.parse( start_time.to_s + ' UTC' ) end + return start_time if diff_in_min == 0 + # if no config is given, just return calculation directly if !config return start_time + (diff_in_min * 60) @@ -288,8 +290,12 @@ put working hours matrix and timezone in function, returns UTC working hours mat # fillup to first full hour if first_loop - # get rest of this hour - diff = 3600 - (start_time - start_time.beginning_of_hour) + # get rest of this hour if diff_in_min in lower the one hour + diff_to_count = 3600 + if diff_to_count > (diff_in_min * 60) + diff_to_count = diff_in_min * 60 + end + diff = diff_to_count - (start_time - start_time.beginning_of_hour) start_time += diff # check if it's countable hour @@ -318,6 +324,7 @@ put working hours matrix and timezone in function, returns UTC working hours mat # check if it's business hour and count if working_hours[ week_day_map[week_day] ][ next_hour ] + # check if count is within this hour if count > 59 * 60 diff = 3600 diff --git a/test/unit/working_time_test.rb b/test/unit/working_time_test.rb index 1fda76c88..f1d6fb1a5 100644 --- a/test/unit/working_time_test.rb +++ b/test/unit/working_time_test.rb @@ -509,6 +509,44 @@ class WorkingTimeTest < ActiveSupport::TestCase :diff => 119, }, + # test 18 + { + :start => '2013-10-21 04:01:00', + :dest_time => '2013-10-21 04:01:00', + :diff => 0, + }, + + # test 19 + { + :start => '2013-04-12 21:20:15', + :dest_time => '2013-04-12 21:20:15', + :diff => 0, + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, + + # test 20 + { + :start => '2013-04-12 11:20:15', + :dest_time => '2013-04-12 11:21:15', + :diff => 1, + :config => { + 'Mon' => true, + 'Tue' => true, + 'Wed' => true, + 'Thu' => true, + 'Fri' => true, + 'beginning_of_workday' => '8:00 am', + 'end_of_workday' => '6:00 pm', + }, + }, ] tests.each { |test| dest_time = TimeCalculation.dest_time( test[:start] + ' UTC', test[:diff], test[:config], test[:timezone] ) From 02c271385627421d90eb0daeaf5b8713abdd1165 Mon Sep 17 00:00:00 2001 From: Johannes Nickel Date: Thu, 13 Jun 2013 15:19:50 +0200 Subject: [PATCH 06/10] fest zum test --- app/models/ticket.rb | 7 +++++++ test/unit/ticket_test.rb | 36 ++++++++++++++++++------------------ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index b8fb5bd17..17ab6a5d3 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -618,6 +618,9 @@ class Ticket < ApplicationModel end if self.first_response# && !self.first_response_in_min self.first_response_in_min = TimeCalculation.business_time_diff( self.created_at, self.first_response, sla_selected.data, sla_selected.timezone ) + self.first_response_in_min = escalation_suspend( self.first_response, 'real', sla_selected ) + + #self.first_response_in_min = TimeCalculation.business_time_diff( self.first_response_in_min, extended_escalation.to_i, sla_selected.data, sla_selected.timezone ) end # set sla time if sla_selected.first_response_time && self.first_response_in_min @@ -655,9 +658,13 @@ class Ticket < ApplicationModel end if self.close_time# && !self.close_time_in_min self.close_time_in_min = TimeCalculation.business_time_diff( self.created_at, self.close_time, sla_selected.data, sla_selected.timezone ) + puts '#### 1 ' + self.close_time_in_min.to_s + self.close_time_in_min == escalation_suspend( self.close_time, 'real', sla_selected ) + puts '#### 2 ' + self.close_time_in_min.to_s end # set sla time if sla_selected.close_time && self.close_time_in_min + puts '#### 3 ' + sla_selected.close_time.to_s + ' - ' + self.close_time_in_min.to_s self.close_time_diff_in_min = sla_selected.close_time - self.close_time_in_min end self.callback_loop = true diff --git a/test/unit/ticket_test.rb b/test/unit/ticket_test.rb index 496e36509..7d34240aa 100644 --- a/test/unit/ticket_test.rb +++ b/test/unit/ticket_test.rb @@ -618,19 +618,19 @@ class TicketTest < ActiveSupport::TestCase ) # set ticket from 11:00 to pending - History.history_create( - :history_type => 'updated', - :history_object => 'Ticket', - :history_attribute => 'ticket_state', - :o_id => ticket.id, - :id_to => 3, - :id_from => 2, - :value_from => 'open', - :value_to => 'pending', - :created_by_id => 1, - :created_at => '2013-06-04 11:00:00', - :updated_at => '2013-06-04 11:00:00' - ) + #History.history_create( + # :history_type => 'updated', + # :history_object => 'Ticket', + # :history_attribute => 'ticket_state', + # :o_id => ticket.id, + # :id_to => 3, + # :id_from => 2, + # :value_from => 'open', + # :value_to => 'pending', + # :created_by_id => 1, + # :created_at => '2013-06-04 11:00:00', + # :updated_at => '2013-06-04 11:00:00' + #) # set first response in time ticket.update_attributes( @@ -644,7 +644,7 @@ class TicketTest < ActiveSupport::TestCase :o_id => ticket.id, :id_to => 3, :id_from => 2, - :value_from => 'pending', + :value_from => 'open', :value_to => 'closed', :created_by_id => 1, :created_at => '2013-06-04 12:00:00', @@ -675,12 +675,12 @@ class TicketTest < ActiveSupport::TestCase ticket = Ticket.find(ticket.id) assert_equal( ticket.escalation_time.gmtime.to_s, '2013-06-04 12:00:00 UTC', 'ticket.escalation_time verify 1' ) #check escal. time because first resp. is already done assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-06-04 11:30:00 UTC', 'ticket.first_response_escal_date verify 1' ) - #assert_equal( ticket.first_response_in_min, 75, 'ticket.first_response_in_min verify 3' ) - #assert_equal( ticket.first_response_diff_in_min, 45, 'ticket.first_response_diff_in_min verify 3' ) + assert_equal( ticket.first_response_in_min, 75, 'ticket.first_response_in_min verify 3' ) + assert_equal( ticket.first_response_diff_in_min, 45, 'ticket.first_response_diff_in_min verify 3' ) #assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-06-04 12:30:00 UTC', 'ticket.update_time_escal_date verify 1' ) #assert_equal( ticket.close_time_escal_date.gmtime.to_s, '2013-06-04 13:30:00 UTC', 'ticket.close_time_escal_date verify 1' ) - #assert_equal( ticket.close_time_in_min, 90, 'ticket.first_response_in_min verify 3' ) - #assert_equal( ticket.close_time_diff_in_min, 150, 'ticket.first_response_diff_in_min verify 3' ) + assert_equal( ticket.close_time_in_min, 150, 'ticket.close_time_in_min verify 3' ) + assert_equal( ticket.close_time_diff_in_min, 150, 'ticket.close_time_diff_in_min# verify 3' ) delete = sla.destroy assert( delete, "sla destroy" ) From d313170d876178b9beebd25b03bb08bc52613d07 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 13 Jun 2013 17:03:08 +0200 Subject: [PATCH 07/10] Fixed "self.close_time_in_min == escalation_suspend(" issue. --- app/models/ticket.rb | 78 +++++++++++++++++++++++----------------- test/unit/ticket_test.rb | 2 +- 2 files changed, 47 insertions(+), 33 deletions(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 17ab6a5d3..088b1928f 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -609,20 +609,27 @@ class Ticket < ApplicationModel # first response if sla_selected.first_response_time - self.first_response_escal_date = TimeCalculation.dest_time( created_at, sla_selected.first_response_time, sla_selected.data, sla_selected.timezone ) - extended_escalation = escalation_suspend( self.first_response_escal_date, 'relative', sla_selected ) - self.first_response_escal_date = TimeCalculation.dest_time( self.first_response_escal_date, extended_escalation.to_i, sla_selected.data, sla_selected.timezone ) + + # get escalation date without pending time + self.first_response_escal_date = TimeCalculation.dest_time( self.created_at, sla_selected.first_response_time, sla_selected.data, sla_selected.timezone ) + + # get pending time between created and first response escal. time + time_in_pending = escalation_suspend( self.created_at, self.first_response_escal_date, 'relative', sla_selected ) + + # get new escalation time (original escal_date + time_in_pending) + self.first_response_escal_date = TimeCalculation.dest_time( self.first_response_escal_date, time_in_pending.to_i, sla_selected.data, sla_selected.timezone ) # set ticket escalation self.escalation_time = self._escalation_calculation_higher_time( self.escalation_time, self.first_response_escal_date, self.first_response ) end if self.first_response# && !self.first_response_in_min - self.first_response_in_min = TimeCalculation.business_time_diff( self.created_at, self.first_response, sla_selected.data, sla_selected.timezone ) - self.first_response_in_min = escalation_suspend( self.first_response, 'real', sla_selected ) - - #self.first_response_in_min = TimeCalculation.business_time_diff( self.first_response_in_min, extended_escalation.to_i, sla_selected.data, sla_selected.timezone ) + + # get response time in min between created and first response + self.first_response_in_min = escalation_suspend( self.created_at, self.first_response, 'real', sla_selected ) + end - # set sla time + + # set time to show if sla is raised ot in if sla_selected.first_response_time && self.first_response_in_min self.first_response_diff_in_min = sla_selected.first_response_time - self.first_response_in_min end @@ -651,20 +658,24 @@ class Ticket < ApplicationModel # close time if sla_selected.close_time + + # get escalation date without pending time self.close_time_escal_date = TimeCalculation.dest_time( self.created_at, sla_selected.close_time, sla_selected.data, sla_selected.timezone ) + # get pending time between created and close escal. time + extended_escalation = escalation_suspend( self.created_at, self.close_time_escal_date, 'relative', sla_selected ) + + # get new escalation time (original escal_date + time_in_pending) + self.close_time_escal_date = TimeCalculation.dest_time( self.close_time_escal_date, extended_escalation.to_i, sla_selected.data, sla_selected.timezone ) + # set ticket escalation self.escalation_time = self._escalation_calculation_higher_time( self.escalation_time, self.close_time_escal_date, self.close_time ) end - if self.close_time# && !self.close_time_in_min - self.close_time_in_min = TimeCalculation.business_time_diff( self.created_at, self.close_time, sla_selected.data, sla_selected.timezone ) - puts '#### 1 ' + self.close_time_in_min.to_s - self.close_time_in_min == escalation_suspend( self.close_time, 'real', sla_selected ) - puts '#### 2 ' + self.close_time_in_min.to_s + if self.close_time # && !self.close_time_in_min + self.close_time_in_min = escalation_suspend( self.created_at, self.close_time, 'real', sla_selected ) end # set sla time if sla_selected.close_time && self.close_time_in_min - puts '#### 3 ' + sla_selected.close_time.to_s + ' - ' + self.close_time_in_min.to_s self.close_time_diff_in_min = sla_selected.close_time - self.close_time_in_min end self.callback_loop = true @@ -713,8 +724,8 @@ class Ticket < ApplicationModel # real - time without supsend state # relative - only suspend time -def escalation_suspend (end_time, type, sla_selected) - sum_temp = 0 + def escalation_suspend (start_time, end_time, type, sla_selected) + total_time_without_pending = 0 total_time = 0 #get history for ticket history_list = History.history_list( 'Ticket', self.id, 'Ticket' ) @@ -728,12 +739,12 @@ def escalation_suspend (end_time, type, sla_selected) # ignore if it isn't a state change next if history_item['history_attribute'] != 'ticket_state' - # ignore all older state changes after first_response - next if last_state_change && last_state_change > self.first_response + # ignore all older state changes after end_time + next if last_state_change && last_state_change > end_time - # if created_at is later then first_response, use first_response as last time - if history_item['created_at'] > self.first_response - history_item['created_at'] = self.first_response + # if created_at is later then end_time, use end_time as last time + if history_item['created_at'] > end_time + history_item['created_at'] = end_time end # get initial state and time @@ -749,8 +760,8 @@ def escalation_suspend (end_time, type, sla_selected) else diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'] ) end - puts 'Diff count !=pending -> ==pending ' + diff.to_s - sum_temp = sum_temp + diff + puts "Diff count !=pending -> ==pending #{diff.to_s} - #{last_state_change} - #{history_item['created_at']}" + total_time_without_pending = total_time_without_pending + diff total_time = total_time + diff last_state_is_pending = true @@ -761,8 +772,8 @@ def escalation_suspend (end_time, type, sla_selected) else diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'] ) end - puts 'Diff count !=pending -> !=pending ' + diff.to_s - sum_temp = sum_temp + diff + puts "Diff count !=pending -> !=pending #{diff.to_s} - #{last_state_change} - #{history_item['created_at']}" + total_time_without_pending = total_time_without_pending + diff total_time = total_time + diff last_state_is_pending = false elsif history_item['value_from'] == 'pending' && history_item['value_to'] != 'pending' @@ -771,7 +782,7 @@ def escalation_suspend (end_time, type, sla_selected) else diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'] ) end - puts 'Diff count !=pending -> !=pending ' + diff.to_s + puts "Diff not count ==pending -> !=pending #{diff.to_s} - #{last_state_change} - #{history_item['created_at']}" total_time = total_time + diff last_state_is_pending = false # no pending state, do not count @@ -792,7 +803,8 @@ def escalation_suspend (end_time, type, sla_selected) else diff = TimeCalculation.business_time_diff( last_state_change, end_time ) end - sum_temp = sum_temp + diff + puts "Diff count last state was not pending #{diff.to_s} - #{last_state_change} - #{end_time}" + total_time_without_pending = total_time_without_pending + diff total_time = total_time + diff end @@ -803,17 +815,19 @@ def escalation_suspend (end_time, type, sla_selected) else diff = TimeCalculation.business_time_diff( self.created_at, end_time ) end - sum_temp = sum_temp + diff + puts 'Diff state has not changed ' + diff.to_s + total_time_without_pending = total_time_without_pending + diff total_time = total_time + diff end - puts total_time + #return sum if (type == 'real') - return sum_temp + return total_time_without_pending elsif (type == 'relative') - return total_time - sum_temp + relative = total_time - total_time_without_pending + return relative else - return nil + raise "ERROR: Unknown type #{type}" end end diff --git a/test/unit/ticket_test.rb b/test/unit/ticket_test.rb index 7d34240aa..fdea49fba 100644 --- a/test/unit/ticket_test.rb +++ b/test/unit/ticket_test.rb @@ -680,7 +680,7 @@ class TicketTest < ActiveSupport::TestCase #assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-06-04 12:30:00 UTC', 'ticket.update_time_escal_date verify 1' ) #assert_equal( ticket.close_time_escal_date.gmtime.to_s, '2013-06-04 13:30:00 UTC', 'ticket.close_time_escal_date verify 1' ) assert_equal( ticket.close_time_in_min, 150, 'ticket.close_time_in_min verify 3' ) - assert_equal( ticket.close_time_diff_in_min, 150, 'ticket.close_time_diff_in_min# verify 3' ) + assert_equal( ticket.close_time_diff_in_min, 90, 'ticket.close_time_diff_in_min# verify 3' ) delete = sla.destroy assert( delete, "sla destroy" ) From 710773255ee3fe02e5d9df415c3d9cd1d822f24b Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 13 Jun 2013 17:05:31 +0200 Subject: [PATCH 08/10] Fixed from global start time to local start time. --- app/models/ticket.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 088b1928f..bbf211a10 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -750,7 +750,7 @@ class Ticket < ApplicationModel # get initial state and time if !last_state last_state = history_item['value_from'] - last_state_change = self.created_at + last_state_change = start_time end # use time if ticket got from e. g. open to pending @@ -811,9 +811,9 @@ class Ticket < ApplicationModel # if we have not had any state change if !last_state_change if sla_selected - diff = TimeCalculation.business_time_diff( self.created_at, end_time, sla_selected.data, sla_selected.timezone) + diff = TimeCalculation.business_time_diff( start_time, end_time, sla_selected.data, sla_selected.timezone) else - diff = TimeCalculation.business_time_diff( self.created_at, end_time ) + diff = TimeCalculation.business_time_diff( start_time, end_time ) end puts 'Diff state has not changed ' + diff.to_s total_time_without_pending = total_time_without_pending + diff From a2aaa8c2cec9a2b0c0ff4c2050c8cfe2cf685a8f Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 13 Jun 2013 17:39:22 +0200 Subject: [PATCH 09/10] Small improvement to make escalation_calculation() smaller. --- app/models/ticket.rb | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index bbf211a10..f1c99eaa5 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -755,11 +755,7 @@ class Ticket < ApplicationModel # use time if ticket got from e. g. open to pending if history_item['value_from'] != 'pending' && history_item['value_to'] == 'pending' - if sla_selected - diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'],sla_selected.data, sla_selected.timezone) - else - diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'] ) - end + diff = self.escalation_time_diff( last_state_change, history_item['created_at'], sla_selected ) puts "Diff count !=pending -> ==pending #{diff.to_s} - #{last_state_change} - #{history_item['created_at']}" total_time_without_pending = total_time_without_pending + diff total_time = total_time + diff @@ -767,21 +763,13 @@ class Ticket < ApplicationModel # use time if ticket got from e. g. open to open elsif history_item['value_from'] != 'pending' && history_item['value_to'] != 'pending' - if sla_selected - diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_selected.data, sla_selected.timezone) - else - diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'] ) - end + diff = self.escalation_time_diff( last_state_change, history_item['created_at'], sla_selected ) puts "Diff count !=pending -> !=pending #{diff.to_s} - #{last_state_change} - #{history_item['created_at']}" total_time_without_pending = total_time_without_pending + diff total_time = total_time + diff last_state_is_pending = false elsif history_item['value_from'] == 'pending' && history_item['value_to'] != 'pending' - if sla_selected - diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'], sla_selected.data, sla_selected.timezone) - else - diff = TimeCalculation.business_time_diff( last_state_change, history_item['created_at'] ) - end + diff = self.escalation_time_diff( last_state_change, history_item['created_at'], sla_selected ) puts "Diff not count ==pending -> !=pending #{diff.to_s} - #{last_state_change} - #{history_item['created_at']}" total_time = total_time + diff last_state_is_pending = false @@ -798,11 +786,7 @@ class Ticket < ApplicationModel # if last state isnt pending, count rest if !last_state_is_pending && last_state_change && last_state_change < end_time - if sla_selected - diff = TimeCalculation.business_time_diff( last_state_change, end_time, sla_selected.data, sla_selected.timezone) - else - diff = TimeCalculation.business_time_diff( last_state_change, end_time ) - end + diff = self.escalation_time_diff( last_state_change, end_time, sla_selected ) puts "Diff count last state was not pending #{diff.to_s} - #{last_state_change} - #{end_time}" total_time_without_pending = total_time_without_pending + diff total_time = total_time + diff @@ -810,11 +794,7 @@ class Ticket < ApplicationModel # if we have not had any state change if !last_state_change - if sla_selected - diff = TimeCalculation.business_time_diff( start_time, end_time, sla_selected.data, sla_selected.timezone) - else - diff = TimeCalculation.business_time_diff( start_time, end_time ) - end + diff = self.escalation_time_diff( start_time, end_time, sla_selected ) puts 'Diff state has not changed ' + diff.to_s total_time_without_pending = total_time_without_pending + diff total_time = total_time + diff @@ -831,6 +811,15 @@ class Ticket < ApplicationModel end end + def escalation_time_diff( start_time, end_time, sla_selected ) + if sla_selected + diff = TimeCalculation.business_time_diff( start_time, end_time, sla_selected.data, sla_selected.timezone) + else + diff = TimeCalculation.business_time_diff( start_time, end_time ) + end + diff + end + class Number end From a8dd0cd3ee6bee4d2290225761dbde0f2568f51b Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Thu, 13 Jun 2013 20:38:05 +0200 Subject: [PATCH 10/10] Call private method without self.methode. --- app/models/ticket.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index f1c99eaa5..06f5a726f 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -755,7 +755,7 @@ class Ticket < ApplicationModel # use time if ticket got from e. g. open to pending if history_item['value_from'] != 'pending' && history_item['value_to'] == 'pending' - diff = self.escalation_time_diff( last_state_change, history_item['created_at'], sla_selected ) + diff = escalation_time_diff( last_state_change, history_item['created_at'], sla_selected ) puts "Diff count !=pending -> ==pending #{diff.to_s} - #{last_state_change} - #{history_item['created_at']}" total_time_without_pending = total_time_without_pending + diff total_time = total_time + diff @@ -763,13 +763,13 @@ class Ticket < ApplicationModel # use time if ticket got from e. g. open to open elsif history_item['value_from'] != 'pending' && history_item['value_to'] != 'pending' - diff = self.escalation_time_diff( last_state_change, history_item['created_at'], sla_selected ) + diff = escalation_time_diff( last_state_change, history_item['created_at'], sla_selected ) puts "Diff count !=pending -> !=pending #{diff.to_s} - #{last_state_change} - #{history_item['created_at']}" total_time_without_pending = total_time_without_pending + diff total_time = total_time + diff last_state_is_pending = false elsif history_item['value_from'] == 'pending' && history_item['value_to'] != 'pending' - diff = self.escalation_time_diff( last_state_change, history_item['created_at'], sla_selected ) + diff = escalation_time_diff( last_state_change, history_item['created_at'], sla_selected ) puts "Diff not count ==pending -> !=pending #{diff.to_s} - #{last_state_change} - #{history_item['created_at']}" total_time = total_time + diff last_state_is_pending = false @@ -786,7 +786,7 @@ class Ticket < ApplicationModel # if last state isnt pending, count rest if !last_state_is_pending && last_state_change && last_state_change < end_time - diff = self.escalation_time_diff( last_state_change, end_time, sla_selected ) + diff = escalation_time_diff( last_state_change, end_time, sla_selected ) puts "Diff count last state was not pending #{diff.to_s} - #{last_state_change} - #{end_time}" total_time_without_pending = total_time_without_pending + diff total_time = total_time + diff @@ -794,7 +794,7 @@ class Ticket < ApplicationModel # if we have not had any state change if !last_state_change - diff = self.escalation_time_diff( start_time, end_time, sla_selected ) + diff = escalation_time_diff( start_time, end_time, sla_selected ) puts 'Diff state has not changed ' + diff.to_s total_time_without_pending = total_time_without_pending + diff total_time = total_time + diff