Skip to content

Commit

Permalink
Fixed issue zammad#2292 - CTI Log: duration_talking_time is incorrect…
Browse files Browse the repository at this point in the history
… and after update initialized_at is a string (not timestamp)
  • Loading branch information
znuny-robo committed Oct 18, 2018
1 parent fb24de1 commit 86c2df6
Show file tree
Hide file tree
Showing 6 changed files with 174 additions and 34 deletions.
19 changes: 1 addition & 18 deletions app/assets/javascripts/app/controllers/cti.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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()
Expand Down
17 changes: 17 additions & 0 deletions app/assets/javascripts/app/index.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -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) ->
Expand Down
8 changes: 6 additions & 2 deletions app/assets/javascripts/app/views/cti/caller_log.jst.eco
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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 %>
Expand Down
60 changes: 50 additions & 10 deletions app/models/cti/log.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ class Log < ApplicationModel
user_id: 2,
}
]
}
},
created_at: Time.zone.now,
)
Cti::Log.create!(
Expand All @@ -91,7 +92,8 @@ class Log < ApplicationModel
user_id: 2,
}
]
}
},
created_at: Time.zone.now - 20.seconds,
)
Cti::Log.create!(
Expand All @@ -114,7 +116,11 @@ class Log < ApplicationModel
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!(
Expand All @@ -139,7 +145,13 @@ class Log < ApplicationModel
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!(
Expand All @@ -164,7 +176,13 @@ class Log < ApplicationModel
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!(
Expand All @@ -189,7 +207,13 @@ class Log < ApplicationModel
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!(
Expand All @@ -214,7 +238,13 @@ class Log < ApplicationModel
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!(
Expand All @@ -226,7 +256,13 @@ class Log < ApplicationModel
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
Expand Down Expand Up @@ -307,7 +343,11 @@ def self.process(params)
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
Expand Down Expand Up @@ -367,7 +407,7 @@ def self.process(params)
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
Expand Down
39 changes: 39 additions & 0 deletions db/migrate/20181017000001_cti_generic_api2.rb
Original file line number Diff line number Diff line change
@@ -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
65 changes: 61 additions & 4 deletions spec/requests/integration/cti_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@
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
Expand All @@ -180,7 +182,7 @@
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
Expand All @@ -204,6 +206,8 @@
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
Expand All @@ -222,9 +226,11 @@
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
Expand All @@ -243,8 +249,8 @@
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'
Expand Down Expand Up @@ -488,5 +494,56 @@
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

0 comments on commit 86c2df6

Please sign in to comment.