Fixed issue #2255 - CTI: Limit used caller log states and prevent race conditions (if callback comes later).
This commit is contained in:
parent
cff3dba0a8
commit
ce9ebe828f
2 changed files with 233 additions and 29 deletions
|
@ -4,6 +4,8 @@ module Cti
|
||||||
|
|
||||||
store :preferences
|
store :preferences
|
||||||
|
|
||||||
|
validates :state, format: { with: /\A(newCall|answer|hangup)\z/, message: 'newCall|answer|hangup is allowed' }
|
||||||
|
|
||||||
after_commit :push_incoming_call, :push_caller_list_update
|
after_commit :push_incoming_call, :push_caller_list_update
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
@ -288,7 +290,7 @@ Cti::Log.process(
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def self.process(params)
|
def self.process(params)
|
||||||
comment = params['cause']
|
cause = params['cause']
|
||||||
event = params['event']
|
event = params['event']
|
||||||
user = params['user']
|
user = params['user']
|
||||||
call_id = params['callId'] || params['call_id']
|
call_id = params['callId'] || params['call_id']
|
||||||
|
@ -308,11 +310,14 @@ Cti::Log.process(
|
||||||
to_comment, preferences = CallerId.get_comment_preferences(params['to'], 'to')
|
to_comment, preferences = CallerId.get_comment_preferences(params['to'], 'to')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
log = find_by(call_id: call_id)
|
||||||
|
|
||||||
case event
|
case event
|
||||||
when 'newCall'
|
when 'newCall'
|
||||||
if params['direction'] == 'in'
|
if params['direction'] == 'in'
|
||||||
done = false
|
done = false
|
||||||
end
|
end
|
||||||
|
raise "call_id #{call_id} already exists!" if log
|
||||||
create(
|
create(
|
||||||
direction: params['direction'],
|
direction: params['direction'],
|
||||||
from: params['from'],
|
from: params['from'],
|
||||||
|
@ -320,44 +325,47 @@ Cti::Log.process(
|
||||||
to: params['to'],
|
to: params['to'],
|
||||||
to_comment: to_comment,
|
to_comment: to_comment,
|
||||||
call_id: call_id,
|
call_id: call_id,
|
||||||
comment: comment,
|
comment: cause,
|
||||||
state: event,
|
state: event,
|
||||||
initialized_at: Time.zone.now,
|
initialized_at: Time.zone.now,
|
||||||
preferences: preferences,
|
preferences: preferences,
|
||||||
done: done,
|
done: done,
|
||||||
)
|
)
|
||||||
when 'answer'
|
when 'answer'
|
||||||
log = find_by(call_id: call_id)
|
|
||||||
raise "No such call_id #{call_id}" if !log
|
raise "No such call_id #{call_id}" if !log
|
||||||
log.state = 'answer'
|
return if log.state == 'hangup' # call is already hangup, ignore answer
|
||||||
log.start_at = Time.zone.now
|
log.with_lock do
|
||||||
log.duration_waiting_time = log.start_at.to_i - log.initialized_at.to_i
|
log.state = 'answer'
|
||||||
if user
|
log.start_at = Time.zone.now
|
||||||
log.to_comment = user
|
log.duration_waiting_time = log.start_at.to_i - log.initialized_at.to_i
|
||||||
end
|
if user
|
||||||
log.done = true
|
log.to_comment = user
|
||||||
log.comment = comment
|
|
||||||
log.save
|
|
||||||
when 'hangup'
|
|
||||||
log = find_by(call_id: call_id)
|
|
||||||
raise "No such call_id #{call_id}" if !log
|
|
||||||
log.done = done
|
|
||||||
if params['direction'] == 'in'
|
|
||||||
if log.state == 'newCall'
|
|
||||||
log.done = false
|
|
||||||
elsif log.to_comment == 'voicemail'
|
|
||||||
log.done = false
|
|
||||||
end
|
end
|
||||||
|
log.done = true
|
||||||
|
log.comment = cause
|
||||||
|
log.save
|
||||||
end
|
end
|
||||||
log.state = 'hangup'
|
when 'hangup'
|
||||||
log.end_at = Time.zone.now
|
raise "No such call_id #{call_id}" if !log
|
||||||
if log.start_at
|
log.with_lock do
|
||||||
log.duration_talking_time = log.start_at.to_i - log.end_at.to_i
|
log.done = done
|
||||||
elsif !log.duration_waiting_time && log.initialized_at
|
if params['direction'] == 'in'
|
||||||
log.duration_waiting_time = log.end_at.to_i - log.initialized_at.to_i
|
if log.state == 'newCall' && cause != 'forwarded'
|
||||||
|
log.done = false
|
||||||
|
elsif log.to_comment == 'voicemail'
|
||||||
|
log.done = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
log.state = 'hangup'
|
||||||
|
log.end_at = Time.zone.now
|
||||||
|
if log.start_at
|
||||||
|
log.duration_talking_time = log.start_at.to_i - log.end_at.to_i
|
||||||
|
elsif !log.duration_waiting_time && log.initialized_at
|
||||||
|
log.duration_waiting_time = log.end_at.to_i - log.initialized_at.to_i
|
||||||
|
end
|
||||||
|
log.comment = cause
|
||||||
|
log.save
|
||||||
end
|
end
|
||||||
log.comment = comment
|
|
||||||
log.save
|
|
||||||
else
|
else
|
||||||
raise ArgumentError, "Unknown event #{event.inspect}"
|
raise ArgumentError, "Unknown event #{event.inspect}"
|
||||||
end
|
end
|
||||||
|
|
|
@ -547,4 +547,200 @@ Mob: +49 333 8362222",
|
||||||
assert_equal(0, Cti::CallerId.where(user_id: @agent2.id).count)
|
assert_equal(0, Cti::CallerId.where(user_id: @agent2.id).count)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'order of events' do
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => '',
|
||||||
|
'event' => 'newCall',
|
||||||
|
'user' => 'user 1',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
|
||||||
|
last = Cti::Log.last
|
||||||
|
assert_equal(last.state, 'newCall')
|
||||||
|
assert_equal(last.done, false)
|
||||||
|
|
||||||
|
travel 2.seconds
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => '',
|
||||||
|
'event' => 'hangup',
|
||||||
|
'user' => 'user 1',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
last.reload
|
||||||
|
assert_equal(last.state, 'hangup')
|
||||||
|
assert_equal(last.done, false)
|
||||||
|
|
||||||
|
travel 2.seconds
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => '',
|
||||||
|
'event' => 'answer',
|
||||||
|
'user' => 'user 1',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
last.reload
|
||||||
|
assert_equal(last.state, 'hangup')
|
||||||
|
assert_equal(last.done, false)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'not answered should be not marked as done' do
|
||||||
|
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => '',
|
||||||
|
'event' => 'newCall',
|
||||||
|
'user' => 'user 1',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
|
||||||
|
last = Cti::Log.last
|
||||||
|
assert_equal(last.state, 'newCall')
|
||||||
|
assert_equal(last.done, false)
|
||||||
|
|
||||||
|
travel 2.seconds
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => '',
|
||||||
|
'event' => 'hangup',
|
||||||
|
'user' => 'user 1',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
last.reload
|
||||||
|
assert_equal(last.state, 'hangup')
|
||||||
|
assert_equal(last.done, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'answered should be marked as done' do
|
||||||
|
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => '',
|
||||||
|
'event' => 'newCall',
|
||||||
|
'user' => 'user 1',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
|
||||||
|
last = Cti::Log.last
|
||||||
|
assert_equal(last.state, 'newCall')
|
||||||
|
assert_equal(last.done, false)
|
||||||
|
|
||||||
|
travel 2.seconds
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => '',
|
||||||
|
'event' => 'answer',
|
||||||
|
'user' => 'user 1',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
last = Cti::Log.last
|
||||||
|
assert_equal(last.state, 'answer')
|
||||||
|
assert_equal(last.done, true)
|
||||||
|
|
||||||
|
travel 2.seconds
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => '',
|
||||||
|
'event' => 'hangup',
|
||||||
|
'user' => 'user 1',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
last.reload
|
||||||
|
assert_equal(last.state, 'hangup')
|
||||||
|
assert_equal(last.done, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'voicemail should not be marked as done' do
|
||||||
|
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => '',
|
||||||
|
'event' => 'newCall',
|
||||||
|
'user' => 'user 1',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
|
||||||
|
last = Cti::Log.last
|
||||||
|
assert_equal(last.state, 'newCall')
|
||||||
|
assert_equal(last.done, false)
|
||||||
|
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => '',
|
||||||
|
'event' => 'answer',
|
||||||
|
'user' => 'voicemail',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
last = Cti::Log.last
|
||||||
|
assert_equal(last.state, 'answer')
|
||||||
|
assert_equal(last.done, true)
|
||||||
|
|
||||||
|
travel 2.seconds
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => '',
|
||||||
|
'event' => 'hangup',
|
||||||
|
'user' => 'user 1',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
last.reload
|
||||||
|
assert_equal(last.state, 'hangup')
|
||||||
|
assert_equal(last.done, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'forwarded should be marked as done' do
|
||||||
|
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => '',
|
||||||
|
'event' => 'newCall',
|
||||||
|
'user' => 'user 1',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
|
||||||
|
last = Cti::Log.last
|
||||||
|
assert_equal(last.state, 'newCall')
|
||||||
|
assert_equal(last.done, false)
|
||||||
|
|
||||||
|
travel 2.seconds
|
||||||
|
Cti::Log.process(
|
||||||
|
'cause' => 'forwarded',
|
||||||
|
'event' => 'hangup',
|
||||||
|
'user' => 'user 1',
|
||||||
|
'from' => '491111222222',
|
||||||
|
'to' => '4930600000000',
|
||||||
|
'callId' => 'touch-loop-1',
|
||||||
|
'direction' => 'in',
|
||||||
|
)
|
||||||
|
last.reload
|
||||||
|
assert_equal(last.state, 'hangup')
|
||||||
|
assert_equal(last.done, true)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue