Fixed issue #2292 - CTI Log: duration_talking_time is incorrect and after update initialized_at is a string (not timestamp)
This commit is contained in:
parent
fb24de11cc
commit
86c2df69ad
6 changed files with 174 additions and 34 deletions
|
@ -121,20 +121,6 @@ class App.CTI extends App.Controller
|
|||
@renderCallerLog()
|
||||
|
||||
renderCallerLog: ->
|
||||
format = (time) ->
|
||||
|
||||
# Hours, minutes and seconds
|
||||
hrs = ~~parseInt((time / 3600))
|
||||
mins = ~~parseInt(((time % 3600) / 60))
|
||||
secs = parseInt(time % 60)
|
||||
|
||||
# Output like "1:01" or "4:03:59" or "123:03:59"
|
||||
mins = "0#{mins}" if mins < 10
|
||||
secs = "0#{secs}" if secs < 10
|
||||
if hrs > 0
|
||||
return "#{hrs}:#{mins}:#{secs}"
|
||||
"#{mins}:#{secs}"
|
||||
|
||||
for item in @list
|
||||
item.status_class = ''
|
||||
item.disabled = true
|
||||
|
@ -157,15 +143,12 @@ class App.CTI extends App.Controller
|
|||
if item.comment
|
||||
item.state_human += ", #{item.comment}"
|
||||
|
||||
if item.start_at && item.end_at
|
||||
item.duration = format((Date.parse(item.end_at) - Date.parse(item.start_at))/1000)
|
||||
|
||||
diff_in_min = ((Date.now() - Date.parse(item.created_at)) / 1000) / 60
|
||||
if diff_in_min > 1
|
||||
item.disabled = false
|
||||
|
||||
@removePopovers()
|
||||
@callerLog.html( App.view('cti/caller_log')(list: @list))
|
||||
@callerLog.html(App.view('cti/caller_log')(list: @list))
|
||||
@renderPopovers()
|
||||
|
||||
@updateNavMenu()
|
||||
|
|
|
@ -43,6 +43,23 @@ class App extends Spine.Controller
|
|||
decimal: (data, positions = 2) ->
|
||||
App.Utils.decimal(data, positions)
|
||||
|
||||
# define time_duration / mm:ss / hh:mm:ss format helper
|
||||
time_duration: (time) ->
|
||||
return '' if !time
|
||||
return '' if isNaN(parseInt(time))
|
||||
|
||||
# Hours, minutes and seconds
|
||||
hrs = ~~parseInt((time / 3600))
|
||||
mins = ~~parseInt(((time % 3600) / 60))
|
||||
secs = parseInt(time % 60)
|
||||
|
||||
# Output like "1:01" or "4:03:59" or "123:03:59"
|
||||
mins = "0#{mins}" if mins < 10
|
||||
secs = "0#{secs}" if secs < 10
|
||||
if hrs > 0
|
||||
return "#{hrs}:#{mins}:#{secs}"
|
||||
"#{mins}:#{secs}"
|
||||
|
||||
# define mask helper
|
||||
# mask an value like 'a***********yz'
|
||||
M: (item, start = 1, end = 2) ->
|
||||
|
|
|
@ -4,8 +4,10 @@
|
|||
<th style="width: 40px;"></th>
|
||||
<th><%- @T('From') %></th>
|
||||
<th><%- @T('To') %></th>
|
||||
<!--<th style="width: 100px;"><%- @T('Queue') %></th>-->
|
||||
<th style="width: 130px;"><%- @T('Status') %></th>
|
||||
<th style="width: 100px;"><%- @T('Duration') %></th>
|
||||
<th style="width: 80px;"><%- @T('Waiting') %></th>
|
||||
<th style="width: 80px;"><%- @T('Duration') %></th>
|
||||
<th style="width: 170px;"><%- @T('Time') %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@ -83,12 +85,14 @@
|
|||
<% end %>
|
||||
<% end %>
|
||||
</td>
|
||||
<!--<td style="vertical-align: middle"><%= item.queue %></td>-->
|
||||
<td style="vertical-align: middle">
|
||||
<% if item.state_human: %>
|
||||
<%- @Icon('status', "#{item.status_class} inline") %> <%- @T(item.state_human) %>
|
||||
<% end %>
|
||||
</td>
|
||||
<td style="vertical-align: middle"><%= item.duration %></td>
|
||||
<td style="vertical-align: middle"><%= @time_duration(item.duration_waiting_time) %></td>
|
||||
<td style="vertical-align: middle"><%= @time_duration(item.duration_talking_time) %></td>
|
||||
<td style="vertical-align: middle"><%- @humanTime(item.created_at) %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
|
|
|
@ -68,7 +68,8 @@ example data, can be used for demo
|
|||
user_id: 2,
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
created_at: Time.zone.now,
|
||||
)
|
||||
|
||||
Cti::Log.create!(
|
||||
|
@ -91,7 +92,8 @@ example data, can be used for demo
|
|||
user_id: 2,
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
created_at: Time.zone.now - 20.seconds,
|
||||
)
|
||||
|
||||
Cti::Log.create!(
|
||||
|
@ -114,7 +116,11 @@ example data, can be used for demo
|
|||
user_id: 2,
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
initialized_at: Time.zone.now - 20.seconds,
|
||||
start_at: Time.zone.now - 30.seconds,
|
||||
duration_waiting_time: 20,
|
||||
created_at: Time.zone.now - 20.seconds,
|
||||
)
|
||||
|
||||
Cti::Log.create!(
|
||||
|
@ -139,7 +145,13 @@ example data, can be used for demo
|
|||
user_id: 2,
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
initialized_at: Time.zone.now - 80.seconds,
|
||||
start_at: Time.zone.now - 45.seconds,
|
||||
end_at: Time.zone.now,
|
||||
duration_waiting_time: 35,
|
||||
duration_talking_time: 45,
|
||||
created_at: Time.zone.now - 80.seconds,
|
||||
)
|
||||
|
||||
Cti::Log.create!(
|
||||
|
@ -164,7 +176,13 @@ example data, can be used for demo
|
|||
user_id: 2,
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
initialized_at: Time.zone.now - 5.minutes,
|
||||
start_at: Time.zone.now - 3.minutes,
|
||||
end_at: Time.zone.now - 20.seconds,
|
||||
duration_waiting_time: 120,
|
||||
duration_talking_time: 160,
|
||||
created_at: Time.zone.now - 5.minutes,
|
||||
)
|
||||
|
||||
Cti::Log.create!(
|
||||
|
@ -189,7 +207,13 @@ example data, can be used for demo
|
|||
user_id: 2,
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
initialized_at: Time.zone.now - 60.minutes,
|
||||
start_at: Time.zone.now - 59.minutes,
|
||||
end_at: Time.zone.now - 2.minutes,
|
||||
duration_waiting_time: 60,
|
||||
duration_talking_time: 3420,
|
||||
created_at: Time.zone.now - 60.minutes,
|
||||
)
|
||||
|
||||
Cti::Log.create!(
|
||||
|
@ -214,7 +238,13 @@ example data, can be used for demo
|
|||
user_id: 2,
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
initialized_at: Time.zone.now - 240.minutes,
|
||||
start_at: Time.zone.now - 235.minutes,
|
||||
end_at: Time.zone.now - 222.minutes,
|
||||
duration_waiting_time: 300,
|
||||
duration_talking_time: 1080,
|
||||
created_at: Time.zone.now - 240.minutes,
|
||||
)
|
||||
|
||||
Cti::Log.create!(
|
||||
|
@ -226,7 +256,13 @@ example data, can be used for demo
|
|||
state: 'hangup',
|
||||
start_at: Time.zone.now - 20.seconds,
|
||||
end_at: Time.zone.now,
|
||||
preferences: {}
|
||||
preferences: {},
|
||||
initialized_at: Time.zone.now - 1440.minutes,
|
||||
start_at: Time.zone.now - 1430.minutes,
|
||||
end_at: Time.zone.now - 1429.minutes,
|
||||
duration_waiting_time: 600,
|
||||
duration_talking_time: 660,
|
||||
created_at: Time.zone.now - 1440.minutes,
|
||||
)
|
||||
|
||||
=end
|
||||
|
@ -307,7 +343,11 @@ Cti::Log.process(
|
|||
preferences = nil
|
||||
done = true
|
||||
if params['direction'] == 'in'
|
||||
to_comment = user
|
||||
if user.present?
|
||||
to_comment = user
|
||||
elsif queue.present?
|
||||
to_comment = queue
|
||||
end
|
||||
from_comment, preferences = CallerId.get_comment_preferences(params['from'], 'from')
|
||||
else
|
||||
from_comment = user
|
||||
|
@ -367,7 +407,7 @@ Cti::Log.process(
|
|||
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
|
||||
log.duration_talking_time = log.end_at.to_i - log.start_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
|
||||
|
|
39
db/migrate/20181017000001_cti_generic_api2.rb
Normal file
39
db/migrate/20181017000001_cti_generic_api2.rb
Normal file
|
@ -0,0 +1,39 @@
|
|||
class CtiGenericApi2 < ActiveRecord::Migration[5.1]
|
||||
def up
|
||||
|
||||
# return if it's a new setup
|
||||
return if !Setting.find_by(name: 'system_init_done')
|
||||
return if !column_exists?(:cti_logs, :initialized_at)
|
||||
return if !column_exists?(:cti_logs, :initialized_at_cleanup)
|
||||
|
||||
add_column :cti_logs, :initialized_at_cleanup, :timestamp, limit: 3, null: true
|
||||
Cti::Log.connection.schema_cache.clear!
|
||||
Cti::Log.reset_column_information
|
||||
|
||||
# clenaup table records
|
||||
Cti::Log.order(created_at: :desc).limit(2000).each do |log|
|
||||
if log.initialized_at
|
||||
begin
|
||||
initialized_at = Time.zone.parse(log.initialized_at)
|
||||
log.update_column(:initialized_at_cleanup, initialized_at) # rubocop:disable Rails/SkipsModelValidations
|
||||
if initialized_at && log.start_at
|
||||
log.update_column(:duration_waiting_time, log.start_at.to_i - initialized_at.to_i) # rubocop:disable Rails/SkipsModelValidations
|
||||
end
|
||||
rescue => e
|
||||
logger.error e
|
||||
end
|
||||
end
|
||||
if log.end_at && log.start_at
|
||||
log.update_column(:duration_talking_time, log.end_at.to_i - log.start_at.to_i) # rubocop:disable Rails/SkipsModelValidations
|
||||
end
|
||||
end
|
||||
|
||||
remove_column(:cti_logs, :initialized_at)
|
||||
Cti::Log.connection.schema_cache.clear!
|
||||
Cti::Log.reset_column_information
|
||||
|
||||
rename_column :cti_logs, :initialized_at_cleanup, :initialized_at
|
||||
Cti::Log.connection.schema_cache.clear!
|
||||
Cti::Log.reset_column_information
|
||||
end
|
||||
end
|
|
@ -162,6 +162,8 @@ RSpec.describe 'Integration CTI', type: :request do
|
|||
expect(log.duration_waiting_time).to be_nil
|
||||
expect(log.duration_talking_time).to be_nil
|
||||
|
||||
travel 2.seconds
|
||||
|
||||
# outbound - I - hangup by agent
|
||||
params = 'event=hangup&direction=out&call_id=1234567890-1&cause=cancel'
|
||||
post "/api/v1/cti/#{token}", params: params
|
||||
|
@ -180,7 +182,7 @@ RSpec.describe 'Integration CTI', type: :request do
|
|||
expect(log.initialized_at).to be_truthy
|
||||
expect(log.start_at).to be_nil
|
||||
expect(log.end_at).to be_truthy
|
||||
expect(log.duration_waiting_time).to be_truthy
|
||||
expect(log.duration_waiting_time).to eq(2)
|
||||
expect(log.duration_talking_time).to be_nil
|
||||
|
||||
# outbound - II - new call
|
||||
|
@ -204,6 +206,8 @@ RSpec.describe 'Integration CTI', type: :request do
|
|||
expect(log.duration_waiting_time).to be_nil
|
||||
expect(log.duration_talking_time).to be_nil
|
||||
|
||||
travel 2.seconds
|
||||
|
||||
# outbound - II - answer by customer
|
||||
params = 'event=answer&direction=out&call_id=1234567890-2&from=4930600000000&to=4912347114711'
|
||||
post "/api/v1/cti/#{token}", params: params
|
||||
|
@ -222,9 +226,11 @@ RSpec.describe 'Integration CTI', type: :request do
|
|||
expect(log.initialized_at).to be_truthy
|
||||
expect(log.start_at).to be_truthy
|
||||
expect(log.end_at).to be_nil
|
||||
expect(log.duration_waiting_time).to be_truthy
|
||||
expect(log.duration_waiting_time).to eq(2)
|
||||
expect(log.duration_talking_time).to be_nil
|
||||
|
||||
travel 2.seconds
|
||||
|
||||
# outbound - II - hangup by customer
|
||||
params = 'event=hangup&direction=out&call_id=1234567890-2&cause=normalClearing&from=4930600000000&to=4912347114711'
|
||||
post "/api/v1/cti/#{token}", params: params
|
||||
|
@ -243,8 +249,8 @@ RSpec.describe 'Integration CTI', type: :request do
|
|||
expect(log.initialized_at).to be_truthy
|
||||
expect(log.start_at).to be_truthy
|
||||
expect(log.end_at).to be_truthy
|
||||
expect(log.duration_waiting_time).to be_truthy
|
||||
expect(log.duration_talking_time).to be_truthy
|
||||
expect(log.duration_waiting_time).to eq(2)
|
||||
expect(log.duration_talking_time).to eq(2)
|
||||
|
||||
# inbound - I - new call
|
||||
params = 'event=newCall&direction=in&to=4930600000000&from=4912347114711&call_id=1234567890-3&user%5B%5D=user+1'
|
||||
|
@ -488,5 +494,56 @@ RSpec.describe 'Integration CTI', type: :request do
|
|||
expect(json_response['list'][5]['state']).to eq('hangup')
|
||||
expect(json_response['list'][6]['call_id']).to eq('1234567890-1')
|
||||
end
|
||||
|
||||
it 'does queue param tests' do
|
||||
token = Setting.get('cti_token')
|
||||
|
||||
# inbound - queue & user
|
||||
params = 'event=newCall&direction=in&to=4930600000000&from=anonymous&call_id=1234567890-1&user%5B%5D=user+1,user+2&queue=some_queue_name'
|
||||
post "/api/v1/cti/#{token}", params: params
|
||||
expect(response).to have_http_status(200)
|
||||
log = Cti::Log.find_by(call_id: '1234567890-1')
|
||||
expect(log).to be_truthy
|
||||
expect(log.to).to eq('4930600000000')
|
||||
expect(log.from).to eq('anonymous')
|
||||
expect(log.direction).to eq('in')
|
||||
expect(log.to_comment).to eq('user 1,user 2')
|
||||
expect(log.from_comment).to be_nil
|
||||
expect(log.preferences['to']).to be_falsey
|
||||
expect(log.preferences['from']).to be_falsey
|
||||
expect(log.comment).to be_nil
|
||||
expect(log.queue).to eq('some_queue_name')
|
||||
expect(log.state).to eq('newCall')
|
||||
expect(log.done).to eq(false)
|
||||
expect(log.initialized_at).to be_truthy
|
||||
expect(log.start_at).to be_nil
|
||||
expect(log.end_at).to be_nil
|
||||
expect(log.duration_waiting_time).to be_nil
|
||||
expect(log.duration_talking_time).to be_nil
|
||||
|
||||
# inbound - queue & no user
|
||||
params = 'event=newCall&direction=in&to=4930600000000&from=anonymous&call_id=1234567890-2&user%5B%5D=&queue=some_queue_name'
|
||||
post "/api/v1/cti/#{token}", params: params
|
||||
expect(response).to have_http_status(200)
|
||||
log = Cti::Log.find_by(call_id: '1234567890-2')
|
||||
expect(log).to be_truthy
|
||||
expect(log.to).to eq('4930600000000')
|
||||
expect(log.from).to eq('anonymous')
|
||||
expect(log.direction).to eq('in')
|
||||
expect(log.to_comment).to eq('some_queue_name')
|
||||
expect(log.from_comment).to be_nil
|
||||
expect(log.preferences['to']).to be_falsey
|
||||
expect(log.preferences['from']).to be_falsey
|
||||
expect(log.comment).to be_nil
|
||||
expect(log.queue).to eq('some_queue_name')
|
||||
expect(log.state).to eq('newCall')
|
||||
expect(log.done).to eq(false)
|
||||
expect(log.initialized_at).to be_truthy
|
||||
expect(log.start_at).to be_nil
|
||||
expect(log.end_at).to be_nil
|
||||
expect(log.duration_waiting_time).to be_nil
|
||||
expect(log.duration_talking_time).to be_nil
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue