Moved to biz for working time calculations. Moved to new sla model.
This commit is contained in:
parent
049833fc02
commit
a9e65611fe
15 changed files with 459 additions and 1185 deletions
2
Gemfile
2
Gemfile
|
@ -36,6 +36,8 @@ gem 'mail', '~> 2.5.0'
|
|||
|
||||
gem 'mime-types'
|
||||
|
||||
gem 'biz'
|
||||
|
||||
gem 'delayed_job_active_record'
|
||||
gem 'daemons'
|
||||
|
||||
|
|
10
Gemfile.lock
10
Gemfile.lock
|
@ -1,6 +1,7 @@
|
|||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
abstract_type (0.0.7)
|
||||
actionmailer (4.1.13)
|
||||
actionpack (= 4.1.13)
|
||||
actionview (= 4.1.13)
|
||||
|
@ -39,11 +40,19 @@ GEM
|
|||
autoprefixer-rails (6.0.2)
|
||||
execjs
|
||||
json
|
||||
biz (1.3.0)
|
||||
abstract_type (~> 0.0.0)
|
||||
clavius (~> 1.0)
|
||||
equalizer (~> 0.0.0)
|
||||
memoizable (~> 0.4.0)
|
||||
tzinfo
|
||||
browser (1.0.1)
|
||||
buftok (0.2.0)
|
||||
builder (3.2.2)
|
||||
childprocess (0.5.6)
|
||||
ffi (~> 1.0, >= 1.0.11)
|
||||
clavius (1.0.1)
|
||||
memoizable (~> 0.4.0)
|
||||
coderay (1.1.0)
|
||||
coffee-rails (4.1.0)
|
||||
coffee-script (>= 2.2.0)
|
||||
|
@ -262,6 +271,7 @@ PLATFORMS
|
|||
DEPENDENCIES
|
||||
activerecord-session_store
|
||||
autoprefixer-rails (>= 5.2)
|
||||
biz
|
||||
browser
|
||||
coffee-rails
|
||||
coffee-script-source
|
||||
|
|
|
@ -2,3 +2,6 @@ class App.Calendar extends App.Model
|
|||
@configure 'Calendar', 'name', 'timezone', 'default', 'business_hours', 'ical_url', 'public_holidays'
|
||||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/calendars'
|
||||
|
||||
displayName: ->
|
||||
"#{@name} - #{@timezone}"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
class App.Sla extends App.Model
|
||||
@configure 'Sla', 'name', 'first_response_time', 'update_time', 'close_time', 'condition', 'timezone', 'data', 'active', 'updated_at'
|
||||
@configure 'Sla', 'name', 'first_response_time', 'update_time', 'close_time', 'condition', 'calendar_id'
|
||||
@extend Spine.Model.Ajax
|
||||
@url: @apiPath + '/slas'
|
||||
@configure_attributes = [
|
||||
|
@ -7,31 +7,8 @@ class App.Sla extends App.Model
|
|||
{ name: 'first_response_time', display: 'First Response Time', tag: 'input', type: 'text', limit: 100, null: true, note: 'In minutes, only business times are counted.' },
|
||||
{ name: 'update_time', display: 'Update Time', tag: 'input', type: 'text', limit: 100, null: true, note: 'In minutes, only business times are counted.' },
|
||||
{ name: 'close_time', display: 'Solution Time', tag: 'input', type: 'text', limit: 100, null: true, note: 'In minutes, only business times are counted.' },
|
||||
{ name: 'calendar_id', display: 'Calendar', tag: 'select', relation: 'Calendar', null: false },
|
||||
{ name: 'condition', display: 'Conditions where SLA is used', tag: 'ticket_attribute_selection', null: true },
|
||||
{ name: 'timezone', display: 'Timezone', tag: 'timezone', null: true },
|
||||
{
|
||||
name: 'data'
|
||||
display: 'Business Times'
|
||||
tag: 'working_hour'
|
||||
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
|
||||
options:
|
||||
customer: 'Customer'
|
||||
state: 'State'
|
||||
priority: 'Priority'
|
||||
group: 'Group'
|
||||
owner: 'Owner'
|
||||
},
|
||||
{ name: 'active', display: 'Active', tag: 'active', default: true },
|
||||
{ name: 'created_by_id', display: 'Created by', relation: 'User', readonly: 1 },
|
||||
{ name: 'created_at', display: 'Created', tag: 'datetime', readonly: 1 },
|
||||
{ name: 'updated_by_id', display: 'Updated by', relation: 'User', readonly: 1 },
|
||||
|
|
|
@ -4,6 +4,10 @@ class Calendar < ApplicationModel
|
|||
store :business_hours
|
||||
store :public_holidays
|
||||
|
||||
after_create :sync_default, :min_one_check
|
||||
after_update :sync_default, :min_one_check
|
||||
after_destroy :min_one_check
|
||||
|
||||
=begin
|
||||
|
||||
get default calendar
|
||||
|
@ -100,11 +104,6 @@ returns
|
|||
def self.timezones
|
||||
list = {}
|
||||
TZInfo::Timezone.all_country_zone_identifiers.each { |timezone|
|
||||
|
||||
# ignore the following time zones
|
||||
#next if t.name =~ /^GMT/
|
||||
#next if t.name =~ /^Etc/
|
||||
#next if t.name !~ /\//
|
||||
t = TZInfo::Timezone.get(timezone)
|
||||
diff = t.current_period.utc_total_offset / 60 / 60
|
||||
list[ timezone ] = diff
|
||||
|
@ -194,4 +193,27 @@ returns
|
|||
}
|
||||
events.sort.to_h
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# if changed calendar is default, set all others default to false
|
||||
def sync_default
|
||||
return if !default
|
||||
Calendar.all.each {|calendar|
|
||||
next if calendar.id == id
|
||||
next if !calendar.default
|
||||
calendar.default = false
|
||||
calendar.save
|
||||
}
|
||||
end
|
||||
|
||||
# check if min one is set to default true
|
||||
def min_one_check
|
||||
Calendar.all.each {|calendar|
|
||||
return if calendar.default
|
||||
}
|
||||
first = Calendar.first
|
||||
first.default = true
|
||||
first.save
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,6 +5,8 @@ class Sla < ApplicationModel
|
|||
store :data
|
||||
validates :name, presence: true
|
||||
|
||||
belongs_to :calendar
|
||||
|
||||
after_create :escalation_calculation_rebuild
|
||||
after_update :escalation_calculation_rebuild
|
||||
after_destroy :escalation_calculation_rebuild
|
||||
|
|
|
@ -14,9 +14,9 @@ returns
|
|||
=end
|
||||
|
||||
def self.rebuild_all
|
||||
state_list_open = Ticket::State.by_category( 'open' )
|
||||
state_list_open = Ticket::State.by_category('open')
|
||||
|
||||
tickets = Ticket.where( state_id: state_list_open )
|
||||
tickets = Ticket.where(state_id: state_list_open)
|
||||
tickets.each(&:escalation_calculation)
|
||||
end
|
||||
|
||||
|
@ -37,117 +37,119 @@ returns
|
|||
|
||||
# set escalation off if ticket is already closed
|
||||
state = Ticket::State.lookup( id: state_id )
|
||||
escalation_disabled = false
|
||||
if state.ignore_escalation?
|
||||
|
||||
# nothing to change
|
||||
return true if !escalation_time
|
||||
|
||||
self.escalation_time = nil
|
||||
# self.first_response_escal_date = nil
|
||||
# self.close_time_escal_date = nil
|
||||
self.callback_loop = true
|
||||
save
|
||||
return true
|
||||
escalation_disabled = true
|
||||
end
|
||||
|
||||
# get sla for ticket
|
||||
sla_selected = escalation_calculation_get_sla
|
||||
calendar = nil
|
||||
sla = escalation_calculation_get_sla
|
||||
if sla
|
||||
calendar = sla.calendar
|
||||
end
|
||||
|
||||
# reset escalation if no sla is set
|
||||
if !sla_selected
|
||||
# if no escalation is enabled
|
||||
if !sla
|
||||
|
||||
# nothing to change
|
||||
return true if !escalation_time
|
||||
|
||||
self.escalation_time = nil
|
||||
# self.first_response_escal_date = nil
|
||||
# self.close_time_escal_date = nil
|
||||
self.callback_loop = true
|
||||
self.escalation_time = nil
|
||||
self.callback_loop = true
|
||||
save
|
||||
return true
|
||||
end
|
||||
|
||||
# puts sla_selected.inspect
|
||||
# puts days.inspect
|
||||
self.escalation_time = nil
|
||||
self.first_response_escal_date = nil
|
||||
self.update_time_escal_date = nil
|
||||
self.close_time_escal_date = nil
|
||||
# reset escalation attributes
|
||||
self.escalation_time = nil
|
||||
self.first_response_escal_date = nil
|
||||
self.update_time_escal_date = nil
|
||||
self.close_time_escal_date = nil
|
||||
|
||||
# first response
|
||||
if sla_selected.first_response_time
|
||||
|
||||
# get escalation date without pending time
|
||||
self.first_response_escal_date = TimeCalculation.dest_time( 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( created_at, first_response_escal_date, 'relative', sla_selected, sla_selected.first_response_time )
|
||||
|
||||
# get new escalation time (original escal_date + time_in_pending)
|
||||
self.first_response_escal_date = TimeCalculation.dest_time( first_response_escal_date, time_in_pending.to_i, sla_selected.data, sla_selected.timezone )
|
||||
|
||||
# set ticket escalation
|
||||
self.escalation_time = calculation_higher_time( escalation_time, first_response_escal_date, first_response )
|
||||
biz = Biz::Schedule.new do |config|
|
||||
config.hours = calendar.business_hours.symbolize_keys
|
||||
#config.holidays = [Date.new(2014, 1, 1), Date.new(2014, 12, 25)]
|
||||
config.time_zone = calendar.timezone
|
||||
end
|
||||
|
||||
# fist response
|
||||
# calculate first response escalation
|
||||
if sla.first_response_time
|
||||
self.first_response_escal_date = biz.time(sla.first_response_time, :minutes).after(created_at)
|
||||
pending_time = pending_minutes(created_at, first_response_escal_date, biz)
|
||||
if pending_time && pending_time > 0
|
||||
self.first_response_escal_date = biz.time(pending_time, :minutes).after(first_response_escal_date)
|
||||
end
|
||||
end
|
||||
|
||||
# get response time in min
|
||||
if first_response
|
||||
|
||||
# get response time in min between created and first response
|
||||
self.first_response_in_min = escalation_suspend( created_at, first_response, 'real', sla_selected )
|
||||
|
||||
self.first_response_in_min = pending_minutes(created_at, first_response, biz, 'business_minutes')
|
||||
else
|
||||
self.escalation_time = first_response_escal_date
|
||||
end
|
||||
|
||||
# set time to show if sla is raised ot in
|
||||
if sla_selected.first_response_time && first_response_in_min
|
||||
self.first_response_diff_in_min = sla_selected.first_response_time - first_response_in_min
|
||||
# set time to show if sla is raised or not
|
||||
if sla.first_response_time && first_response_in_min
|
||||
self.first_response_diff_in_min = sla.first_response_time - first_response_in_min
|
||||
end
|
||||
|
||||
# update time
|
||||
# calculate escalation
|
||||
last_update = last_contact_agent
|
||||
if !last_update
|
||||
last_update = created_at
|
||||
end
|
||||
if sla_selected.update_time
|
||||
self.update_time_escal_date = TimeCalculation.dest_time( last_update, sla_selected.update_time, sla_selected.data, sla_selected.timezone )
|
||||
|
||||
# get pending time between created and update escal. time
|
||||
time_in_pending = escalation_suspend( last_update, update_time_escal_date, 'relative', sla_selected, sla_selected.update_time )
|
||||
|
||||
# get new escalation time (original escal_date + time_in_pending)
|
||||
self.update_time_escal_date = TimeCalculation.dest_time( update_time_escal_date, time_in_pending.to_i, sla_selected.data, sla_selected.timezone )
|
||||
|
||||
# set ticket escalation
|
||||
self.escalation_time = calculation_higher_time( escalation_time, update_time_escal_date, false )
|
||||
if sla.update_time
|
||||
self.update_time_escal_date = biz.time(sla.update_time, :minutes).after(last_update)
|
||||
pending_time = pending_minutes(last_update, update_time_escal_date, biz)
|
||||
if pending_time && pending_time > 0
|
||||
self.update_time_escal_date = biz.time(pending_time, :minutes).after(update_time_escal_date)
|
||||
end
|
||||
end
|
||||
if (!self.escalation_time && self.update_time_escal_date) || self.update_time_escal_date < self.escalation_time
|
||||
self.escalation_time = self.update_time_escal_date
|
||||
end
|
||||
|
||||
# get update time in min
|
||||
if last_contact_agent
|
||||
self.update_time_in_min = TimeCalculation.business_time_diff( created_at, last_contact_agent, sla_selected.data, sla_selected.timezone )
|
||||
self.update_time_in_min = pending_minutes(created_at, last_contact_agent, biz, 'business_minutes')
|
||||
end
|
||||
|
||||
# set sla time
|
||||
if sla_selected.update_time && update_time_in_min
|
||||
self.update_time_diff_in_min = sla_selected.update_time - update_time_in_min
|
||||
if sla.update_time && update_time_in_min
|
||||
self.update_time_diff_in_min = sla.update_time - update_time_in_min
|
||||
end
|
||||
|
||||
# close time
|
||||
if sla_selected.close_time
|
||||
|
||||
# get escalation date without pending time
|
||||
self.close_time_escal_date = TimeCalculation.dest_time( 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( created_at, close_time_escal_date, 'relative', sla_selected, sla_selected.close_time )
|
||||
|
||||
# get new escalation time (original escal_date + time_in_pending)
|
||||
self.close_time_escal_date = TimeCalculation.dest_time( close_time_escal_date, extended_escalation.to_i, sla_selected.data, sla_selected.timezone )
|
||||
|
||||
# set ticket escalation
|
||||
self.escalation_time = calculation_higher_time( escalation_time, close_time_escal_date, close_time )
|
||||
# calculate close time escalation
|
||||
if sla.close_time
|
||||
self.close_time_escal_date = biz.time(sla.close_time, :minutes).after(created_at)
|
||||
pending_time = pending_minutes(created_at, first_response_escal_date, biz)
|
||||
if pending_time && pending_time > 0
|
||||
self.close_time_escal_date = biz.time(pending_time, :minutes).after(close_time_escal_date)
|
||||
end
|
||||
end
|
||||
if close_time # && !self.close_time_in_min
|
||||
self.close_time_in_min = escalation_suspend( created_at, close_time, 'real', sla_selected )
|
||||
|
||||
# get close time in min
|
||||
if close_time
|
||||
self.close_time_in_min = pending_minutes(created_at, close_time, biz, 'business_minutes')
|
||||
else
|
||||
if (!self.escalation_time && self.close_time_escal_date) || self.close_time_escal_date < self.escalation_time
|
||||
if !escalation_disabled
|
||||
self.escalation_time = self.close_time_escal_date
|
||||
end
|
||||
end
|
||||
end
|
||||
# set sla time
|
||||
if sla_selected.close_time && close_time_in_min
|
||||
self.close_time_diff_in_min = sla_selected.close_time - close_time_in_min
|
||||
|
||||
# set time to show if sla is raised or not
|
||||
if sla.close_time && close_time_in_min
|
||||
self.close_time_diff_in_min = sla.close_time - close_time_in_min
|
||||
end
|
||||
|
||||
if escalation_disabled
|
||||
self.escalation_time = nil
|
||||
end
|
||||
|
||||
return if !self.changed?
|
||||
|
@ -173,7 +175,7 @@ returns
|
|||
sla_selected = nil
|
||||
sla_list = Cache.get( 'SLA::List::Active' )
|
||||
if sla_list.nil?
|
||||
sla_list = Sla.where( active: true )
|
||||
sla_list = Sla.all
|
||||
Cache.write( 'SLA::List::Active', sla_list, { expires_in: 1.hour } )
|
||||
end
|
||||
sla_list.each {|sla|
|
||||
|
@ -208,24 +210,18 @@ returns
|
|||
|
||||
private
|
||||
|
||||
#type could be:
|
||||
# real - time without supsend state
|
||||
# relative - only suspend time
|
||||
# get business minutes of pending time
|
||||
# type = business_minutes (pending time in business minutes)
|
||||
# type = non_business_minutes (pending time in non business minutes)
|
||||
def pending_minutes(start_time, end_time, biz, type = 'non_business_minutes')
|
||||
|
||||
def escalation_suspend (start_time, end_time, type, sla_selected, sla_time = 0)
|
||||
if type == 'relative'
|
||||
end_time += sla_time * 60
|
||||
end
|
||||
total_time_without_pending = 0
|
||||
total_time = 0
|
||||
#get history for ticket
|
||||
history_list = history_get
|
||||
|
||||
#loop through hist. changes and get time
|
||||
last_state = nil
|
||||
last_state_change = nil
|
||||
working_time_in_min = 0
|
||||
total_time_in_min = 0
|
||||
last_state = nil
|
||||
last_state_change = nil
|
||||
last_state_is_pending = false
|
||||
history_list.each { |history_item|
|
||||
pending_minutes = 0
|
||||
history_get.each { |history_item|
|
||||
|
||||
# ignore if it isn't a state change
|
||||
next if !history_item['attribute']
|
||||
|
@ -256,14 +252,14 @@ returns
|
|||
counted = false
|
||||
end
|
||||
|
||||
diff = escalation_time_diff( last_state_change, history_item['created_at'], sla_selected )
|
||||
diff = biz.within(last_state_change, history_item['created_at']).in_minutes
|
||||
if counted
|
||||
# puts "Diff count #{history_item['value_from']} -> #{history_item['value_to']} / #{last_state_change} -> #{history_item['created_at']}"
|
||||
total_time_without_pending = total_time_without_pending + diff
|
||||
working_time_in_min = working_time_in_min + diff
|
||||
# else
|
||||
# puts "Diff not count #{history_item['value_from']} -> #{history_item['value_to']} / #{last_state_change} -> #{history_item['created_at']}"
|
||||
end
|
||||
total_time = total_time + diff
|
||||
total_time_in_min = total_time_in_min + diff
|
||||
|
||||
if history_item['value_to'] == 'pending reminder'
|
||||
last_state_is_pending = true
|
||||
|
@ -278,45 +274,23 @@ returns
|
|||
|
||||
# if last state isnt pending, count rest
|
||||
if !last_state_is_pending && last_state_change && last_state_change < end_time
|
||||
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
|
||||
diff = biz.within(last_state_change, end_time).in_minutes
|
||||
working_time_in_min = working_time_in_min + diff
|
||||
total_time_in_min = total_time_in_min + diff
|
||||
end
|
||||
|
||||
# if we have not had any state change
|
||||
if !last_state_change
|
||||
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
|
||||
diff = biz.within(start_time, end_time).in_minutes
|
||||
working_time_in_min = working_time_in_min + diff
|
||||
total_time_in_min = total_time_in_min + diff
|
||||
end
|
||||
|
||||
#return sum
|
||||
if type == 'real'
|
||||
return total_time_without_pending
|
||||
elsif type == 'relative'
|
||||
relative = total_time - total_time_without_pending
|
||||
return relative
|
||||
else
|
||||
fail "ERROR: Unknown type #{type}"
|
||||
#puts "#{type}:working_time_in_min:#{working_time_in_min}|free_time:#{total_time_in_min - working_time_in_min}"
|
||||
if type == 'non_business_minutes'
|
||||
return total_time_in_min - working_time_in_min
|
||||
end
|
||||
working_time_in_min
|
||||
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
|
||||
|
||||
def calculation_higher_time(escalation_time, check_time, done_time)
|
||||
return escalation_time if done_time
|
||||
return check_time if !escalation_time
|
||||
return escalation_time if !check_time
|
||||
return check_time if escalation_time > check_time
|
||||
escalation_time
|
||||
end
|
||||
end
|
||||
|
|
|
@ -50,7 +50,7 @@ returns:
|
|||
|
||||
check if state is ignored for escalation
|
||||
|
||||
state = Ticket::State.lookup( :name => 'state name' )
|
||||
state = Ticket::State.lookup(name: 'state name')
|
||||
|
||||
result = state.ignore_escalation?
|
||||
|
||||
|
@ -61,8 +61,7 @@ returns:
|
|||
=end
|
||||
|
||||
def ignore_escalation?
|
||||
ignore_escalation = %w(removed closed merged)
|
||||
return true if ignore_escalation.include?( name )
|
||||
return true if ignore_escalation
|
||||
false
|
||||
end
|
||||
end
|
||||
|
|
8
db/migrate/20150969000001_update_sla.rb
Normal file
8
db/migrate/20150969000001_update_sla.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
class UpdateSla < ActiveRecord::Migration
|
||||
def up
|
||||
add_column :slas, :calendar_id, :integer, null: false
|
||||
remove_column :slas, :timezone
|
||||
remove_column :slas, :data
|
||||
remove_column :slas, :active
|
||||
end
|
||||
end
|
12
db/migrate/20150970000001_update_ticket_state.rb
Normal file
12
db/migrate/20150970000001_update_ticket_state.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
class UpdateTicketState < ActiveRecord::Migration
|
||||
def up
|
||||
add_column :ticket_states, :ignore_escalation, :boolean, null: false, default: false
|
||||
|
||||
Ticket::State.create_or_update( id: 3, name: 'pending reminder', state_type_id: Ticket::StateType.find_by(name: 'pending reminder').id, ignore_escalation: true )
|
||||
Ticket::State.create_or_update( id: 4, name: 'closed', state_type_id: Ticket::StateType.find_by(name: 'closed').id, ignore_escalation: true )
|
||||
Ticket::State.create_or_update( id: 5, name: 'merged', state_type_id: Ticket::StateType.find_by(name: 'merged').id, ignore_escalation: true )
|
||||
Ticket::State.create_or_update( id: 6, name: 'removed', state_type_id: Ticket::StateType.find_by(name: 'removed').id, active: false, ignore_escalation: true )
|
||||
Ticket::State.create_or_update( id: 7, name: 'pending close', state_type_id: Ticket::StateType.find_by(name: 'pending action').id, next_state_id: 4, ignore_escalation: true )
|
||||
|
||||
end
|
||||
end
|
14
db/seeds.rb
14
db/seeds.rb
|
@ -1527,13 +1527,13 @@ Ticket::StateType.create_if_not_exists( id: 5, name: 'closed' )
|
|||
Ticket::StateType.create_if_not_exists( id: 6, name: 'merged' )
|
||||
Ticket::StateType.create_if_not_exists( id: 7, name: 'removed' )
|
||||
|
||||
Ticket::State.create_if_not_exists( id: 1, name: 'new', state_type_id: Ticket::StateType.where(name: 'new').first.id )
|
||||
Ticket::State.create_if_not_exists( id: 2, name: 'open', state_type_id: Ticket::StateType.where(name: 'open').first.id )
|
||||
Ticket::State.create_if_not_exists( id: 3, name: 'pending reminder', state_type_id: Ticket::StateType.where(name: 'pending reminder').first.id )
|
||||
Ticket::State.create_if_not_exists( id: 4, name: 'closed', state_type_id: Ticket::StateType.where(name: 'closed').first.id )
|
||||
Ticket::State.create_if_not_exists( id: 5, name: 'merged', state_type_id: Ticket::StateType.where(name: 'merged').first.id )
|
||||
Ticket::State.create_if_not_exists( id: 6, name: 'removed', state_type_id: Ticket::StateType.where(name: 'removed').first.id, active: false )
|
||||
Ticket::State.create_if_not_exists( id: 7, name: 'pending close', state_type_id: Ticket::StateType.where(name: 'pending action').first.id, next_state_id: 4 )
|
||||
Ticket::State.create_if_not_exists( id: 1, name: 'new', state_type_id: Ticket::StateType.find_by(name: 'new').id, )
|
||||
Ticket::State.create_if_not_exists( id: 2, name: 'open', state_type_id: Ticket::StateType.find_by(name: 'open').id )
|
||||
Ticket::State.create_if_not_exists( id: 3, name: 'pending reminder', state_type_id: Ticket::StateType.find_by(name: 'pending reminder').id, ignore_escalation: true )
|
||||
Ticket::State.create_if_not_exists( id: 4, name: 'closed', state_type_id: Ticket::StateType.find_by(name: 'closed').id, ignore_escalation: true )
|
||||
Ticket::State.create_if_not_exists( id: 5, name: 'merged', state_type_id: Ticket::StateType.find_by(name: 'merged').id, ignore_escalation: true )
|
||||
Ticket::State.create_if_not_exists( id: 6, name: 'removed', state_type_id: Ticket::StateType.find_by(name: 'removed').id, active: false, ignore_escalation: true )
|
||||
Ticket::State.create_if_not_exists( id: 7, name: 'pending close', state_type_id: Ticket::StateType.find_by(name: 'pending action').id, next_state_id: 4, ignore_escalation: true )
|
||||
|
||||
Ticket::Priority.create_if_not_exists( id: 1, name: '1 low' )
|
||||
Ticket::Priority.create_if_not_exists( id: 2, name: '2 normal' )
|
||||
|
|
|
@ -1,361 +0,0 @@
|
|||
module TimeCalculation
|
||||
|
||||
=begin
|
||||
|
||||
put working hours matrix and timezone in function, returns UTC working hours matrix
|
||||
|
||||
working_hours_martix = TimeCalculation.working_hours('2013-10-27 20:00:15', working_hours_matrix, 'Europe/Berlin')
|
||||
|
||||
working_hours_martix = {
|
||||
:Mon => [nil,nil,nil,nil,nil,nil,nil,nil,true,true,true,true,true,true,true,true,true,true,true,nil,nil,nil,nil,nil],
|
||||
:Tue => [nil,nil,nil,nil,nil,nil,nil,nil,true,true,true,true,true,true,true,true,true,true,true,nil,nil,nil,nil,nil],
|
||||
:Wed => [nil,nil,nil,nil,nil,nil,nil,nil,true,true,true,true,true,true,true,true,true,true,true,nil,nil,nil,nil,nil],
|
||||
:Thu => [nil,nil,nil,nil,nil,nil,nil,nil,true,true,true,true,true,true,true,true,true,true,true,nil,nil,nil,nil,nil],
|
||||
:Fri => [nil,nil,nil,nil,nil,nil,nil,nil,true,true,true,true,true,true,true,true,true,true,true,nil,nil,nil,nil,nil],
|
||||
:Sat => [],
|
||||
:Sun => [],
|
||||
}
|
||||
|
||||
=end
|
||||
|
||||
def self.working_hours(start_time, config, timezone)
|
||||
time_diff = 0
|
||||
if timezone
|
||||
begin
|
||||
time_diff = Time.zone.parse(start_time.to_s).in_time_zone(timezone).utc_offset
|
||||
rescue => e
|
||||
Rails.logger.error "Can't fine tomezone #{timezone}"
|
||||
Rails.logger.error e.inspect
|
||||
Rails.logger.error e.backtrace
|
||||
end
|
||||
end
|
||||
beginning_of_workday = Time.zone.parse("1977-10-27 #{config['beginning_of_workday']}")
|
||||
end_of_workday = Time.zone.parse("1977-10-27 #{config['end_of_workday']}") - 3600
|
||||
config_ok = false
|
||||
working_hours = {}
|
||||
[:Mon, :Tue, :Wed, :Thu, :Fri, :Sat, :Sun].each {|day|
|
||||
working_hours[day] = []
|
||||
|
||||
next if !config[day.to_s]
|
||||
if config[day.to_s] != true && config[day.to_s] != day.to_s
|
||||
next
|
||||
end
|
||||
|
||||
config_ok = true
|
||||
(0..23).each {|hour|
|
||||
time = Time.zone.parse("1977-10-27 #{hour}:00:00")
|
||||
if time >= beginning_of_workday && time <= end_of_workday
|
||||
working_hours[day].push true
|
||||
else
|
||||
working_hours[day].push nil
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
if !config_ok
|
||||
fail 'sla config is invalid! ' + config.inspect
|
||||
end
|
||||
|
||||
# shift working hours / if needed
|
||||
if time_diff && time_diff != 0
|
||||
|
||||
hours_to_shift = (time_diff / 3600 ).round
|
||||
move_items = {
|
||||
Mon: [],
|
||||
Tue: [],
|
||||
Wed: [],
|
||||
Thu: [],
|
||||
Fri: [],
|
||||
Sat: [],
|
||||
Sun: [],
|
||||
}
|
||||
(1..hours_to_shift).each {
|
||||
working_hours.each {|day, value|
|
||||
|
||||
next if !value
|
||||
|
||||
to_move = working_hours[day].shift
|
||||
if day == :Mon
|
||||
move_items[:Tue].push to_move
|
||||
elsif day == :Tue
|
||||
move_items[:Wed].push to_move
|
||||
elsif day == :Wed
|
||||
move_items[:Thu].push to_move
|
||||
elsif day == :Thu
|
||||
move_items[:Fri].push to_move
|
||||
elsif day == :Fri
|
||||
move_items[:Sat].push to_move
|
||||
elsif day == :Sat
|
||||
move_items[:Sun].push to_move
|
||||
elsif day == :Sun
|
||||
move_items[:Mon].push to_move
|
||||
end
|
||||
}
|
||||
}
|
||||
move_items.each {|day, value|
|
||||
value.each {|item|
|
||||
working_hours[day].push item
|
||||
}
|
||||
}
|
||||
end
|
||||
working_hours
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
returns business hours in minutes between to dates
|
||||
|
||||
business_hours_in_min = Time.Calculation.business_time_diff(
|
||||
'2013-10-27 14:00:15',
|
||||
'2013-10-27 18:10:15',
|
||||
working_hours_martix,
|
||||
'Europe/Berlin',
|
||||
)
|
||||
|
||||
=end
|
||||
|
||||
def self.business_time_diff(start_time, end_time, config = nil, timezone = '')
|
||||
if start_time.class == String
|
||||
start_time = Time.zone.parse( start_time.to_s + 'UTC' )
|
||||
end
|
||||
if end_time.class == String
|
||||
end_time = Time.zone.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 = {
|
||||
1 => :Mon,
|
||||
2 => :Tue,
|
||||
3 => :Wed,
|
||||
4 => :Thu,
|
||||
5 => :Fri,
|
||||
6 => :Sat,
|
||||
0 => :Sun,
|
||||
}
|
||||
|
||||
count = 0
|
||||
calculation = true
|
||||
first_loop = true
|
||||
while calculation
|
||||
week_day = start_time.wday
|
||||
day = start_time.day
|
||||
month = start_time.month
|
||||
year = start_time.year
|
||||
hour = start_time.hour
|
||||
|
||||
# check if it's vacation day
|
||||
if config
|
||||
if config['holidays']
|
||||
if config['holidays'].include?("#{year}-#{month}-#{day}")
|
||||
|
||||
# jump to next day
|
||||
start_time = start_time.beginning_of_day + 86_400
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# check if it's countable day
|
||||
if working_hours[ week_day_map[week_day] ].empty?
|
||||
|
||||
# jump to next day
|
||||
start_time = start_time.beginning_of_day + 86_400
|
||||
next
|
||||
end
|
||||
|
||||
# fillup to first full hour
|
||||
if first_loop
|
||||
diff = end_time - start_time
|
||||
|
||||
if diff > 59 * 60
|
||||
diff = start_time - start_time.beginning_of_hour
|
||||
end
|
||||
start_time += diff
|
||||
|
||||
# check if it's countable hour
|
||||
if working_hours[ week_day_map[week_day] ][ hour ]
|
||||
count += diff
|
||||
end
|
||||
end
|
||||
first_loop = false
|
||||
|
||||
# loop to next hour
|
||||
(hour..23).each { |next_hour|
|
||||
|
||||
# check if end time is lower
|
||||
if start_time >= end_time
|
||||
calculation = false
|
||||
break
|
||||
end
|
||||
|
||||
# check if end_time is within this hour
|
||||
diff = end_time - start_time
|
||||
if diff > 59 * 60
|
||||
diff = 3600
|
||||
end
|
||||
|
||||
# keep it in current day
|
||||
if next_hour == 23
|
||||
start_time += diff - 1
|
||||
else
|
||||
start_time += diff
|
||||
end
|
||||
|
||||
# check if it's business hour and count
|
||||
if working_hours[ week_day_map[week_day] ][ next_hour ]
|
||||
count += diff
|
||||
end
|
||||
}
|
||||
|
||||
# loop to next day
|
||||
start_time = start_time.beginning_of_day + 86_400
|
||||
end
|
||||
|
||||
diff = count / 60
|
||||
diff.round
|
||||
end
|
||||
|
||||
=begin
|
||||
|
||||
returns destination date of start time plus X minutes
|
||||
|
||||
dest_time = Time.Calculation.dest_time(
|
||||
'2013-10-27 14:00:15',
|
||||
120,
|
||||
working_hours_martix,
|
||||
'Europe/Berlin',
|
||||
)
|
||||
|
||||
=end
|
||||
|
||||
def self.dest_time(start_time, diff_in_min, config = nil, timezone = '')
|
||||
if start_time.class == String
|
||||
start_time = Time.zone.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)
|
||||
end
|
||||
|
||||
# loop
|
||||
working_hours = self.working_hours(start_time, config, timezone)
|
||||
|
||||
week_day_map = {
|
||||
1 => :Mon,
|
||||
2 => :Tue,
|
||||
3 => :Wed,
|
||||
4 => :Thu,
|
||||
5 => :Fri,
|
||||
6 => :Sat,
|
||||
0 => :Sun,
|
||||
}
|
||||
|
||||
count = diff_in_min * 60
|
||||
calculation = true
|
||||
first_loop = true
|
||||
while calculation
|
||||
week_day = start_time.wday
|
||||
day = start_time.day
|
||||
month = start_time.month
|
||||
year = start_time.year
|
||||
hour = start_time.hour
|
||||
#puts "start outer loop #{start_time}-#{week_day}-#{year}-#{month}-#{day}-#{hour}|c#{count}"
|
||||
|
||||
# check if it's vacation day
|
||||
if config
|
||||
if config['holidays']
|
||||
if config['holidays'].include?("#{year}-#{month}-#{day}")
|
||||
|
||||
# jump to next day
|
||||
start_time = start_time.beginning_of_day + 86_400
|
||||
next
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# check if it's countable day
|
||||
if working_hours[ week_day_map[week_day] ].empty?
|
||||
|
||||
# jump to next day
|
||||
start_time = start_time.beginning_of_day + 86_400
|
||||
next
|
||||
end
|
||||
|
||||
# fillup to first full hour
|
||||
if first_loop
|
||||
|
||||
# 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
|
||||
if working_hours[ week_day_map[week_day] ][ hour ]
|
||||
count -= diff
|
||||
end
|
||||
|
||||
# start on next hour of we moved to next
|
||||
if diff != 0
|
||||
hour += 1
|
||||
end
|
||||
end
|
||||
|
||||
first_loop = false
|
||||
|
||||
# loop to next hour
|
||||
(hour..23).each { |next_hour|
|
||||
|
||||
diff = 3600
|
||||
|
||||
# check if count positiv
|
||||
if count <= 0
|
||||
calculation = false
|
||||
break
|
||||
end
|
||||
|
||||
# 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
|
||||
else
|
||||
diff = count
|
||||
end
|
||||
count -= diff
|
||||
end
|
||||
|
||||
# keep it in current day
|
||||
if next_hour == 23
|
||||
start_time += diff - 1
|
||||
else
|
||||
start_time += diff
|
||||
end
|
||||
}
|
||||
|
||||
# check if count positiv
|
||||
if count <= 0
|
||||
calculation = false
|
||||
break
|
||||
end
|
||||
|
||||
# loop to next day
|
||||
start_time = start_time.beginning_of_day + 86_400
|
||||
end
|
||||
|
||||
start_time
|
||||
end
|
||||
|
||||
end
|
93
test/unit/calendar_test.rb
Normal file
93
test/unit/calendar_test.rb
Normal file
|
@ -0,0 +1,93 @@
|
|||
# encoding: utf-8
|
||||
require 'test_helper'
|
||||
|
||||
class CalendarTest < ActiveSupport::TestCase
|
||||
test 'default test' do
|
||||
|
||||
calendar1 = Calendar.create_or_update(
|
||||
name: 'US 1',
|
||||
timezone: 'America/Los_Angeles',
|
||||
business_hours: {
|
||||
mon: { '09:00' => '17:00' },
|
||||
tue: { '09:00' => '17:00' },
|
||||
wed: { '09:00' => '17:00' },
|
||||
thu: { '09:00' => '17:00' },
|
||||
fri: { '09:00' => '17:00' }
|
||||
},
|
||||
default: true,
|
||||
ical_url: nil,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
calendar2 = Calendar.create_or_update(
|
||||
name: 'US 2',
|
||||
timezone: 'America/Los_Angeles',
|
||||
business_hours: {
|
||||
mon: { '09:00' => '17:00' },
|
||||
tue: { '09:00' => '17:00' },
|
||||
wed: { '09:00' => '17:00' },
|
||||
thu: { '09:00' => '17:00' },
|
||||
fri: { '09:00' => '17:00' }
|
||||
},
|
||||
default: false,
|
||||
ical_url: nil,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
calendar3 = Calendar.create_or_update(
|
||||
name: 'US 3',
|
||||
timezone: 'America/Los_Angeles',
|
||||
business_hours: {
|
||||
mon: { '09:00' => '17:00' },
|
||||
tue: { '09:00' => '17:00' },
|
||||
wed: { '09:00' => '17:00' },
|
||||
thu: { '09:00' => '17:00' },
|
||||
fri: { '09:00' => '17:00' }
|
||||
},
|
||||
default: true,
|
||||
ical_url: nil,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
calendar1 = Calendar.find_by(name: 'US 1')
|
||||
calendar2 = Calendar.find_by(name: 'US 2')
|
||||
calendar3 = Calendar.find_by(name: 'US 3')
|
||||
|
||||
assert_equal(false, calendar1.default)
|
||||
assert_equal(false, calendar2.default)
|
||||
assert_equal(true, calendar3.default)
|
||||
|
||||
calendar2.default = true
|
||||
calendar2.save
|
||||
|
||||
calendar1 = Calendar.find_by(name: 'US 1')
|
||||
calendar2 = Calendar.find_by(name: 'US 2')
|
||||
calendar3 = Calendar.find_by(name: 'US 3')
|
||||
|
||||
assert_equal(false, calendar1.default)
|
||||
assert_equal(true, calendar2.default)
|
||||
assert_equal(false, calendar3.default)
|
||||
|
||||
calendar2.default = false
|
||||
calendar2.save
|
||||
|
||||
calendar1 = Calendar.find_by(name: 'US 1')
|
||||
calendar2 = Calendar.find_by(name: 'US 2')
|
||||
calendar3 = Calendar.find_by(name: 'US 3')
|
||||
|
||||
assert_equal(true, calendar1.default)
|
||||
assert_equal(false, calendar2.default)
|
||||
assert_equal(false, calendar3.default)
|
||||
|
||||
calendar1.destroy
|
||||
calendar2 = Calendar.find_by(name: 'US 2')
|
||||
calendar3 = Calendar.find_by(name: 'US 3')
|
||||
|
||||
assert_equal(true, calendar2.default)
|
||||
assert_equal(false, calendar3.default)
|
||||
end
|
||||
|
||||
end
|
|
@ -2,6 +2,7 @@
|
|||
require 'test_helper'
|
||||
|
||||
class TicketSlaTest < ActiveSupport::TestCase
|
||||
|
||||
test 'ticket sla' do
|
||||
|
||||
# cleanup
|
||||
|
@ -24,18 +25,29 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
assert( ticket, 'ticket created' )
|
||||
assert_equal( ticket.escalation_time, nil, 'ticket.escalation_time verify' )
|
||||
|
||||
sla = Sla.create(
|
||||
calendar1 = Calendar.create_or_update(
|
||||
name: 'EU 1',
|
||||
timezone: 'Europe/Berlin',
|
||||
business_hours: {
|
||||
mon: { '09:00' => '17:00' },
|
||||
tue: { '09:00' => '17:00' },
|
||||
wed: { '09:00' => '17:00' },
|
||||
thu: { '09:00' => '17:00' },
|
||||
fri: { '09:00' => '17:00' }
|
||||
},
|
||||
default: true,
|
||||
ical_url: nil,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
sla = Sla.create_or_update(
|
||||
name: 'test sla 1',
|
||||
condition: {},
|
||||
data: {
|
||||
'Mon' => 'Mon', 'Tue' => 'Tue', 'Wed' => 'Wed', 'Thu' => 'Thu', 'Fri' => 'Fri', 'Sat' => 'Sat', 'Sun' => 'Sun',
|
||||
'beginning_of_workday' => '8:00',
|
||||
'end_of_workday' => '18:00',
|
||||
},
|
||||
first_response_time: 120,
|
||||
update_time: 180,
|
||||
close_time: 240,
|
||||
active: true,
|
||||
calendar_id: calendar1.id,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
@ -47,18 +59,30 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
delete = sla.destroy
|
||||
assert( delete, 'sla destroy 1' )
|
||||
|
||||
sla = Sla.create(
|
||||
calendar2 = Calendar.create_or_update(
|
||||
name: 'EU 2',
|
||||
timezone: 'Europe/Berlin',
|
||||
business_hours: {
|
||||
mon: { '08:00' => '18:00' },
|
||||
tue: { '08:00' => '18:00' },
|
||||
wed: { '08:00' => '18:00' },
|
||||
thu: { '08:00' => '18:00' },
|
||||
fri: { '08:00' => '18:00' },
|
||||
sat: { '08:00' => '18:00' },
|
||||
sun: { '08:00' => '18:00' },
|
||||
},
|
||||
default: true,
|
||||
ical_url: nil,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
sla = Sla.create_or_update(
|
||||
name: 'test sla 2',
|
||||
condition: { 'tickets.priority_id' => %w(1 2 3) },
|
||||
data: {
|
||||
'Mon' => 'Mon', 'Tue' => 'Tue', 'Wed' => 'Wed', 'Thu' => 'Thu', 'Fri' => 'Fri', 'Sat' => 'Sat', 'Sun' => 'Sun',
|
||||
'beginning_of_workday' => '8:00',
|
||||
'end_of_workday' => '18:00',
|
||||
},
|
||||
calendar_id: calendar2.id,
|
||||
first_response_time: 60,
|
||||
update_time: 120,
|
||||
close_time: 180,
|
||||
active: true,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
@ -81,7 +105,6 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
ticket.update_attributes(
|
||||
first_response: '2013-03-21 10:00:00 UTC',
|
||||
)
|
||||
puts ticket.inspect
|
||||
|
||||
assert_equal( ticket.escalation_time.gmtime.to_s, '2013-03-21 11:30:00 UTC', 'ticket.escalation_time verify 3' )
|
||||
assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-03-21 10:30:00 UTC', 'ticket.first_response_escal_date verify 3' )
|
||||
|
@ -101,7 +124,6 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
ticket.update_attributes(
|
||||
first_response: '2013-03-21 14:00:00 UTC',
|
||||
)
|
||||
puts ticket.inspect
|
||||
|
||||
assert_equal( ticket.escalation_time.gmtime.to_s, '2013-03-21 11:30:00 UTC', 'ticket.escalation_time verify 4' )
|
||||
assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-03-21 10:30:00 UTC', 'ticket.first_response_escal_date verify 4' )
|
||||
|
@ -269,8 +291,8 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
type: Ticket::Article::Type.where(name: 'email').first,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
created_at: '2013-03-29 08:00:03 UTC',
|
||||
updated_at: '2013-03-29 08:00:03 UTC',
|
||||
created_at: '2013-03-29 07:00:03 UTC',
|
||||
updated_at: '2013-03-29 07:00:03 UTC',
|
||||
)
|
||||
|
||||
ticket = Ticket.find(ticket.id)
|
||||
|
@ -355,20 +377,31 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
assert( ticket, 'ticket created' )
|
||||
assert_equal( ticket.escalation_time, nil, 'ticket.escalation_time verify' )
|
||||
|
||||
# set sla's for timezone "Europe/Berlin" wintertime (+1), so UTC times are 8:00-17: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',
|
||||
},
|
||||
# set sla's for timezone "Europe/Berlin" wintertime (+1), so UTC times are 7:00-16:00
|
||||
calendar = Calendar.create_or_update(
|
||||
name: 'EU 3',
|
||||
timezone: 'Europe/Berlin',
|
||||
business_hours: {
|
||||
mon: { '08:00' => '17:00' },
|
||||
tue: { '08:00' => '17:00' },
|
||||
wed: { '08:00' => '17:00' },
|
||||
thu: { '08:00' => '17:00' },
|
||||
fri: { '08:00' => '17:00' },
|
||||
sat: { '08:00' => '17:00' },
|
||||
sun: { '08:00' => '17:00' },
|
||||
},
|
||||
default: true,
|
||||
ical_url: nil,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
sla = Sla.create_or_update(
|
||||
name: 'test sla 3',
|
||||
condition: {},
|
||||
calendar_id: calendar.id,
|
||||
first_response_time: 120,
|
||||
update_time: 180,
|
||||
close_time: 240,
|
||||
active: true,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
@ -397,23 +430,35 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
assert( ticket, 'ticket created' )
|
||||
assert_equal( ticket.escalation_time, nil, 'ticket.escalation_time verify' )
|
||||
|
||||
# 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',
|
||||
},
|
||||
# set sla's for timezone "Europe/Berlin" summertime (+2), so UTC times are 6:00-15:00
|
||||
calendar = Calendar.create_or_update(
|
||||
name: 'EU 4',
|
||||
timezone: 'Europe/Berlin',
|
||||
first_response_time: 120,
|
||||
update_time: 180,
|
||||
close_time: 240,
|
||||
active: true,
|
||||
business_hours: {
|
||||
mon: { '08:00' => '17:00' },
|
||||
tue: { '08:00' => '17:00' },
|
||||
wed: { '08:00' => '17:00' },
|
||||
thu: { '08:00' => '17:00' },
|
||||
fri: { '08:00' => '17:00' },
|
||||
sat: { '08:00' => '17:00' },
|
||||
sun: { '08:00' => '17:00' },
|
||||
},
|
||||
default: true,
|
||||
ical_url: nil,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
sla = Sla.create_or_update(
|
||||
name: 'test sla 4',
|
||||
condition: {},
|
||||
calendar_id: calendar.id,
|
||||
first_response_time: 120,
|
||||
update_time: 180,
|
||||
close_time: 240,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket = Ticket.find(ticket.id)
|
||||
assert_equal( ticket.escalation_time.gmtime.to_s, '2013-10-21 11:30:00 UTC', 'ticket.escalation_time verify 1' )
|
||||
assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-10-21 11:30:00 UTC', 'ticket.first_response_escal_date verify 1' )
|
||||
|
@ -432,36 +477,30 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
customer_id: 2,
|
||||
state: Ticket::State.lookup( name: 'new' ),
|
||||
priority: Ticket::Priority.lookup( name: '2 normal' ),
|
||||
created_at: '2013-10-21 06:30:00 UTC',
|
||||
updated_at: '2013-10-21 06:30:00 UTC',
|
||||
created_at: '2013-10-21 05:30:00 UTC',
|
||||
updated_at: '2013-10-21 05:30:00 UTC',
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
assert( ticket, 'ticket created' )
|
||||
assert_equal( ticket.escalation_time, nil, 'ticket.escalation_time verify' )
|
||||
|
||||
# set sla's for timezone "Europe/Berlin" summertime (+2), so UTC times are 7:00-16:00
|
||||
sla = Sla.create(
|
||||
name: 'test sla 1',
|
||||
# set sla's for timezone "Europe/Berlin" summertime (+2), so UTC times are 6:00-15:00
|
||||
sla = Sla.create_or_update(
|
||||
name: 'test sla 5',
|
||||
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',
|
||||
calendar_id: calendar.id,
|
||||
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-10-21 09:00:00 UTC', 'ticket.escalation_time verify 1' )
|
||||
assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-10-21 09:00:00 UTC', 'ticket.first_response_escal_date verify 1' )
|
||||
assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-10-21 10:00:00 UTC', 'ticket.update_time_escal_date verify 1' )
|
||||
assert_equal( ticket.close_time_escal_date.gmtime.to_s, '2013-10-21 11:00:00 UTC', 'ticket.close_time_escal_date verify 1' )
|
||||
assert_equal( ticket.escalation_time.gmtime.to_s, '2013-10-21 08:00:00 UTC', 'ticket.escalation_time verify 1' )
|
||||
assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-10-21 08:00:00 UTC', 'ticket.first_response_escal_date verify 1' )
|
||||
assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-10-21 09:00:00 UTC', 'ticket.update_time_escal_date verify 1' )
|
||||
assert_equal( ticket.close_time_escal_date.gmtime.to_s, '2013-10-21 10:00:00 UTC', 'ticket.close_time_escal_date verify 1' )
|
||||
|
||||
delete = sla.destroy
|
||||
assert( delete, 'sla destroy' )
|
||||
|
@ -545,22 +584,34 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
)
|
||||
|
||||
# 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',
|
||||
},
|
||||
calendar = Calendar.create_or_update(
|
||||
name: 'EU 5',
|
||||
timezone: 'Europe/Berlin',
|
||||
first_response_time: 120,
|
||||
update_time: 180,
|
||||
close_time: 250,
|
||||
active: true,
|
||||
business_hours: {
|
||||
mon: { '09:00' => '18:00' },
|
||||
tue: { '09:00' => '18:00' },
|
||||
wed: { '09:00' => '18:00' },
|
||||
thu: { '09:00' => '18:00' },
|
||||
fri: { '09:00' => '18:00' },
|
||||
sat: { '09:00' => '18:00' },
|
||||
sun: { '09:00' => '18:00' },
|
||||
},
|
||||
default: true,
|
||||
ical_url: nil,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
sla = Sla.create_or_update(
|
||||
name: 'test sla 5',
|
||||
condition: {},
|
||||
calendar_id: calendar.id,
|
||||
first_response_time: 120,
|
||||
update_time: 180,
|
||||
close_time: 250,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
|
||||
ticket = Ticket.find(ticket.id)
|
||||
assert_equal( ticket.escalation_time.gmtime.to_s, '2013-06-04 13:30:00 UTC', 'ticket.escalation_time verify 1' )
|
||||
assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-06-04 11:30:00 UTC', 'ticket.first_response_escal_date verify 1' )
|
||||
|
@ -608,25 +659,37 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
close_time: '2013-06-04 12:00:00 UTC',
|
||||
)
|
||||
|
||||
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',
|
||||
calendar = Calendar.create_or_update(
|
||||
name: 'EU 5',
|
||||
timezone: 'Europe/Berlin',
|
||||
business_hours: {
|
||||
mon: { '09:00' => '18:00' },
|
||||
tue: { '09:00' => '18:00' },
|
||||
wed: { '09:00' => '18:00' },
|
||||
thu: { '09:00' => '18:00' },
|
||||
fri: { '09:00' => '18:00' },
|
||||
sat: { '09:00' => '18:00' },
|
||||
sun: { '09:00' => '18:00' },
|
||||
},
|
||||
default: true,
|
||||
ical_url: nil,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
sla = Sla.create_or_update(
|
||||
name: 'test sla 5',
|
||||
condition: {},
|
||||
calendar_id: calendar.id,
|
||||
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 14:00:00 UTC', 'ticket.escalation_time verify 1' )
|
||||
assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-06-04 14:00:00 UTC', 'ticket.first_response_escal_date verify 1' )
|
||||
assert_equal( ticket.escalation_time, nil, 'ticket.escalation_time verify 1' )
|
||||
assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-06-04 13:00:00 UTC', 'ticket.first_response_escal_date verify 1' )
|
||||
assert_equal( ticket.first_response_in_min, nil, 'ticket.first_response_in_min verify 3' )
|
||||
assert_equal( ticket.first_response_diff_in_min, nil, 'ticket.first_response_diff_in_min verify 3' )
|
||||
assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-06-04 15:00:00 UTC', 'ticket.update_time_escal_date verify 1' )
|
||||
|
@ -702,25 +765,37 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
close_time: '2013-06-04 12:00:00 UTC',
|
||||
)
|
||||
|
||||
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',
|
||||
calendar = Calendar.create_or_update(
|
||||
name: 'EU 5',
|
||||
timezone: 'Europe/Berlin',
|
||||
business_hours: {
|
||||
mon: { '09:00' => '18:00' },
|
||||
tue: { '09:00' => '18:00' },
|
||||
wed: { '09:00' => '18:00' },
|
||||
thu: { '09:00' => '18:00' },
|
||||
fri: { '09:00' => '18:00' },
|
||||
sat: { '09:00' => '18:00' },
|
||||
sun: { '09:00' => '18:00' },
|
||||
},
|
||||
default: true,
|
||||
ical_url: nil,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
sla = Sla.create_or_update(
|
||||
name: 'test sla 5',
|
||||
condition: {},
|
||||
calendar_id: calendar.id,
|
||||
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 13:30:00 UTC', 'ticket.escalation_time verify 1' )
|
||||
assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-06-04 13:30:00 UTC', 'ticket.first_response_escal_date verify 1' )
|
||||
assert_equal( ticket.escalation_time, nil, 'ticket.escalation_time verify 1' )
|
||||
assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-06-04 12:30:00 UTC', 'ticket.first_response_escal_date verify 1' )
|
||||
assert_equal( ticket.first_response_in_min, nil, 'ticket.first_response_in_min verify 3' )
|
||||
assert_equal( ticket.first_response_diff_in_min, nil, 'ticket.first_response_diff_in_min verify 3' )
|
||||
assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-06-04 14:30:00 UTC', 'ticket.update_time_escal_date verify 1' )
|
||||
|
@ -812,25 +887,37 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
close_time: '2013-06-04 12:00:00 UTC',
|
||||
)
|
||||
|
||||
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',
|
||||
calendar = Calendar.create_or_update(
|
||||
name: 'EU 5',
|
||||
timezone: 'Europe/Berlin',
|
||||
business_hours: {
|
||||
mon: { '09:00' => '18:00' },
|
||||
tue: { '09:00' => '18:00' },
|
||||
wed: { '09:00' => '18:00' },
|
||||
thu: { '09:00' => '18:00' },
|
||||
fri: { '09:00' => '18:00' },
|
||||
sat: { '09:00' => '18:00' },
|
||||
sun: { '09:00' => '18:00' },
|
||||
},
|
||||
default: true,
|
||||
ical_url: nil,
|
||||
updated_by_id: 1,
|
||||
created_by_id: 1,
|
||||
)
|
||||
sla = Sla.create_or_update(
|
||||
name: 'test sla 5',
|
||||
condition: {},
|
||||
calendar_id: calendar.id,
|
||||
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 13:00:00 UTC', 'ticket.escalation_time verify 1' )
|
||||
assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-06-04 13:00:00 UTC', 'ticket.first_response_escal_date verify 1' )
|
||||
assert_equal( ticket.escalation_time, nil, 'ticket.escalation_time verify 1' )
|
||||
assert_equal( ticket.first_response_escal_date.gmtime.to_s, '2013-06-04 12:30:00 UTC', 'ticket.first_response_escal_date verify 1' )
|
||||
assert_equal( ticket.first_response_in_min, nil, 'ticket.first_response_in_min verify 3' )
|
||||
assert_equal( ticket.first_response_diff_in_min, nil, 'ticket.first_response_diff_in_min verify 3' )
|
||||
assert_equal( ticket.update_time_escal_date.gmtime.to_s, '2013-06-04 14:00:00 UTC', 'ticket.update_time_escal_date verify 1' )
|
||||
|
@ -845,4 +932,5 @@ class TicketSlaTest < ActiveSupport::TestCase
|
|||
assert( delete, 'ticket destroy' )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,555 +0,0 @@
|
|||
# encoding: utf-8
|
||||
require 'test_helper'
|
||||
require 'time_calculation'
|
||||
|
||||
class WorkingTimeTest < ActiveSupport::TestCase
|
||||
test 'working time' do
|
||||
tests = [
|
||||
|
||||
# test 1
|
||||
{
|
||||
start: '2012-12-17 08:00:00',
|
||||
end: '2012-12-18 08:00:00',
|
||||
diff: 600,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 2
|
||||
{
|
||||
start: '2012-12-17 08:00:00',
|
||||
end: '2012-12-17 09:00:00',
|
||||
diff: 60,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 3
|
||||
{
|
||||
start: '2012-12-17 08:00:00',
|
||||
end: '2012-12-17 08:15:00',
|
||||
diff: 15,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 4
|
||||
{
|
||||
start: '2012-12-23 08:00:00',
|
||||
end: '2012-12-27 10:30:42',
|
||||
diff: 151,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
'holidays' => [
|
||||
'2012-12-24', '2012-12-25', '2012-12-26'
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
# test 5
|
||||
{
|
||||
start: '2013-02-28 17:00:00',
|
||||
end: '2013-02-28 23:59:59',
|
||||
diff: 60,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 6
|
||||
{
|
||||
start: '2013-02-28 17:00:00',
|
||||
end: '2013-03-08 23:59:59',
|
||||
diff: 3660,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 7
|
||||
{
|
||||
start: '2012-02-28 17:00:00',
|
||||
end: '2013-03-08 23:59:59',
|
||||
diff: 160_860,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 8
|
||||
{
|
||||
start: '2013-02-28 17:01:00',
|
||||
end: '2013-02-28 18:10:59',
|
||||
diff: 61,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 9
|
||||
{
|
||||
start: '2013-02-28 18:01:00',
|
||||
end: '2013-02-28 18:10:59',
|
||||
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 10 / summertime
|
||||
{
|
||||
start: '2013-02-28 18:01:00',
|
||||
end: '2013-02-28 18:10:59',
|
||||
diff: 0,
|
||||
timezone: 'Europe/Berlin',
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 11 / summertime
|
||||
{
|
||||
start: '2013-02-28 17:01:00',
|
||||
end: '2013-02-28 17:10:59',
|
||||
diff: 0,
|
||||
timezone: 'Europe/Berlin',
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 12 / wintertime
|
||||
{
|
||||
start: '2013-08-29 17:01:00',
|
||||
end: '2013-08-29 17:10:59',
|
||||
diff: 0,
|
||||
timezone: 'Europe/Berlin',
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 13 / summertime
|
||||
{
|
||||
start: '2013-02-28 16:01:00',
|
||||
end: '2013-02-28 16:10:59',
|
||||
diff: 10,
|
||||
timezone: 'Europe/Berlin',
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 14 / wintertime
|
||||
{
|
||||
start: '2013-08-29 16:01:00',
|
||||
end: '2013-08-29 16:10:59',
|
||||
diff: 0,
|
||||
timezone: 'Europe/Berlin',
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'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] )
|
||||
assert_equal( diff, test[:diff], 'diff' )
|
||||
}
|
||||
end
|
||||
|
||||
test 'dest time' do
|
||||
tests = [
|
||||
|
||||
# test 1
|
||||
{
|
||||
start: '2012-12-17 08:00:00',
|
||||
dest_time: '2012-12-17 18:00:00',
|
||||
diff: 600,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 2
|
||||
{
|
||||
start: '2012-12-17 08:00:00',
|
||||
dest_time: '2012-12-18 08:30:00',
|
||||
diff: 630,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 3
|
||||
{
|
||||
start: '2012-12-17 08:00:00',
|
||||
dest_time: '2012-12-18 18:00:00',
|
||||
diff: 1200,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 4
|
||||
{
|
||||
start: '2012-12-17 08:00:00',
|
||||
dest_time: '2012-12-19 08:30:00',
|
||||
diff: 1230,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 5
|
||||
{
|
||||
start: '2012-12-17 08:00:00',
|
||||
dest_time: '2012-12-21 18:00:00',
|
||||
diff: 3000,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 6
|
||||
{
|
||||
start: '2012-12-17 08:00:00',
|
||||
dest_time: '2012-12-24 08:05:00',
|
||||
diff: 3005,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 7
|
||||
{
|
||||
start: '2012-12-17 08:00:00',
|
||||
dest_time: '2012-12-31 08:05:00',
|
||||
diff: 6005,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 8
|
||||
{
|
||||
start: '2012-12-17 08:00:00',
|
||||
dest_time: '2012-12-31 13:30:00',
|
||||
diff: 6330,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 9
|
||||
{
|
||||
start: '2013-04-12 21:20:15',
|
||||
dest_time: '2013-04-15 10:00:00',
|
||||
diff: 120,
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 11 / summertime 7am-5pm
|
||||
{
|
||||
start: '2013-03-08 21:20:15',
|
||||
dest_time: '2013-03-11 09:00:00',
|
||||
diff: 120,
|
||||
timezone: 'Europe/Berlin',
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 12 / wintertime 6am-4pm
|
||||
{
|
||||
start: '2013-09-06 21:20:15',
|
||||
dest_time: '2013-09-09 08:00:00',
|
||||
diff: 120,
|
||||
timezone: 'Europe/Berlin',
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '8:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 13 / wintertime - 7am-4pm
|
||||
{
|
||||
start: '2013-10-21 06:30:00',
|
||||
dest_time: '2013-10-21 09:00:00',
|
||||
diff: 120,
|
||||
timezone: 'Europe/Berlin',
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '9:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 14 / wintertime - 7am-4pm
|
||||
{
|
||||
start: '2013-10-21 04:34:15',
|
||||
dest_time: '2013-10-21 09:00:00',
|
||||
diff: 120,
|
||||
timezone: 'Europe/Berlin',
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '9:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 15 / wintertime - 7am-4pm
|
||||
{
|
||||
start: '2013-10-20 22:34:15',
|
||||
dest_time: '2013-10-21 09:00:00',
|
||||
diff: 120,
|
||||
timezone: 'Europe/Berlin',
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '9:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 16 / wintertime - 7am-4pm
|
||||
{
|
||||
start: '2013-10-21 07:00:15',
|
||||
dest_time: '2013-10-21 09:00:15',
|
||||
diff: 120,
|
||||
timezone: 'Europe/Berlin',
|
||||
config: {
|
||||
'Mon' => true,
|
||||
'Tue' => true,
|
||||
'Wed' => true,
|
||||
'Thu' => true,
|
||||
'Fri' => true,
|
||||
'beginning_of_workday' => '9:00 am',
|
||||
'end_of_workday' => '6:00 pm',
|
||||
},
|
||||
},
|
||||
|
||||
# test 17
|
||||
{
|
||||
start: '2013-10-21 04:01:00',
|
||||
dest_time: '2013-10-21 06:00:00',
|
||||
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] )
|
||||
assert_equal( dest_time.gmtime, Time.zone.parse( test[:dest_time] + ' UTC' ), "dest time - #{test[:dest_time]}" )
|
||||
}
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in a new issue