Fixes issue #2441 - Zammad ignores disabled Chat-Topics for agents.
This commit is contained in:
parent
d24a7c5584
commit
8a5552c9f8
8 changed files with 544 additions and 64 deletions
|
@ -832,6 +832,10 @@ class Setting extends App.ControllerModal
|
||||||
# update runtime
|
# update runtime
|
||||||
@windowSpace.maxChatWindows = params.chat.max_windows
|
@windowSpace.maxChatWindows = params.chat.max_windows
|
||||||
|
|
||||||
|
# disable chat if we have no active chat selected
|
||||||
|
if params.chat && ( _.isEmpty(params.chat.active) || !_.includes(_.values(params.chat.active), 'on') )
|
||||||
|
@active = false
|
||||||
|
|
||||||
# update user preferences
|
# update user preferences
|
||||||
@ajax(
|
@ajax(
|
||||||
id: 'preferences'
|
id: 'preferences'
|
||||||
|
|
|
@ -4,6 +4,60 @@ class Chat < ApplicationModel
|
||||||
validates :name, presence: true
|
validates :name, presence: true
|
||||||
store :preferences
|
store :preferences
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get the customer state of a chat
|
||||||
|
|
||||||
|
chat = Chat.find(123)
|
||||||
|
chat.customer_state(session_id = nil)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
chat_disabled - chat is disabled
|
||||||
|
|
||||||
|
{
|
||||||
|
state: 'chat_disabled'
|
||||||
|
}
|
||||||
|
|
||||||
|
returns (without session_id)
|
||||||
|
|
||||||
|
offline - no agent is online
|
||||||
|
|
||||||
|
{
|
||||||
|
state: 'offline'
|
||||||
|
}
|
||||||
|
|
||||||
|
no_seats_available - no agent is available (all slots are used, max_queue is full)
|
||||||
|
|
||||||
|
{
|
||||||
|
state: 'no_seats_available'
|
||||||
|
}
|
||||||
|
|
||||||
|
online - ready for chats
|
||||||
|
|
||||||
|
{
|
||||||
|
state: 'online'
|
||||||
|
}
|
||||||
|
|
||||||
|
returns (session_id)
|
||||||
|
|
||||||
|
reconnect - position of waiting list for new chat
|
||||||
|
|
||||||
|
{
|
||||||
|
state: 'reconnect',
|
||||||
|
position: chat_session.position,
|
||||||
|
}
|
||||||
|
|
||||||
|
reconnect - chat session already exists, serve agent and session chat messages (to redraw chat history)
|
||||||
|
|
||||||
|
{
|
||||||
|
state: 'reconnect',
|
||||||
|
session: session,
|
||||||
|
agent: user,
|
||||||
|
}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
def customer_state(session_id = nil)
|
def customer_state(session_id = nil)
|
||||||
return { state: 'chat_disabled' } if !Setting.get('chat')
|
return { state: 'chat_disabled' } if !Setting.get('chat')
|
||||||
|
|
||||||
|
@ -45,16 +99,16 @@ class Chat < ApplicationModel
|
||||||
end
|
end
|
||||||
|
|
||||||
# check if agents are available
|
# check if agents are available
|
||||||
available_agents = Chat::Agent.where(active: true).where('updated_at > ?', Time.zone.now - 2.minutes).count
|
if Chat.active_agent_count([id]).zero?
|
||||||
if available_agents.zero?
|
|
||||||
return { state: 'offline' }
|
return { state: 'offline' }
|
||||||
end
|
end
|
||||||
|
|
||||||
# if all seads are used
|
# if all seads are used
|
||||||
if Chat.waiting_chat_count >= max_queue
|
waiting_count = Chat.waiting_chat_count(id)
|
||||||
|
if waiting_count >= max_queue
|
||||||
return {
|
return {
|
||||||
state: 'no_seats_available',
|
state: 'no_seats_available',
|
||||||
queue: Chat.waiting_chat_count,
|
queue: waiting_count,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -62,20 +116,101 @@ class Chat < ApplicationModel
|
||||||
{ state: 'online' }
|
{ state: 'online' }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get available chat_ids for agent
|
||||||
|
|
||||||
|
chat_ids = Chat.agent_active_chat_ids(User.find(123))
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
[1, 2, 3]
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.agent_active_chat_ids(user)
|
||||||
|
return [] if user.preferences[:chat].blank?
|
||||||
|
return [] if user.preferences[:chat][:active].blank?
|
||||||
|
|
||||||
|
chat_ids = []
|
||||||
|
user.preferences[:chat][:active].each do |chat_id, state|
|
||||||
|
next if state != 'on'
|
||||||
|
|
||||||
|
chat_ids.push chat_id.to_i
|
||||||
|
end
|
||||||
|
return [] if chat_ids.blank?
|
||||||
|
|
||||||
|
chat_ids
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
get current agent state
|
||||||
|
|
||||||
|
Chat.agent_state(123)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
{
|
||||||
|
state: 'chat_disabled'
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
waiting_chat_count: 1,
|
||||||
|
waiting_chat_session_list: [
|
||||||
|
{
|
||||||
|
id: 17,
|
||||||
|
chat_id: 1,
|
||||||
|
session_id: "81e58184385aabe92508eb9233200b5e",
|
||||||
|
name: "",
|
||||||
|
state: "waiting",
|
||||||
|
user_id: nil,
|
||||||
|
preferences: {
|
||||||
|
"url: "http://localhost:3000/chat.html",
|
||||||
|
"participants: ["70332537618180"],
|
||||||
|
"remote_ip: nil,
|
||||||
|
"geo_ip: nil,
|
||||||
|
"dns_name: nil,
|
||||||
|
},
|
||||||
|
updated_by_id: nil,
|
||||||
|
created_by_id: nil,
|
||||||
|
created_at: Thu, 02 May 2019 10:10:45 UTC +00:00,
|
||||||
|
updated_at: Thu, 02 May 2019 10:10:45 UTC +00:00},
|
||||||
|
}
|
||||||
|
],
|
||||||
|
running_chat_count: 0,
|
||||||
|
running_chat_session_list: [],
|
||||||
|
active_agent_count: 2,
|
||||||
|
active_agent_ids: [1, 2],
|
||||||
|
seads_available: 5,
|
||||||
|
seads_total: 15,
|
||||||
|
active: true, # agent is available for chats
|
||||||
|
assets: { ...related assets... },
|
||||||
|
}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
def self.agent_state(user_id)
|
def self.agent_state(user_id)
|
||||||
return { state: 'chat_disabled' } if !Setting.get('chat')
|
return { state: 'chat_disabled' } if !Setting.get('chat')
|
||||||
|
|
||||||
|
current_user = User.lookup(id: user_id)
|
||||||
|
return { error: "No such user with id: #{user_id}" } if !current_user
|
||||||
|
|
||||||
|
chat_ids = agent_active_chat_ids(current_user)
|
||||||
|
|
||||||
assets = {}
|
assets = {}
|
||||||
Chat.where(active: true).each do |chat|
|
Chat.where(active: true).each do |chat|
|
||||||
assets = chat.assets(assets)
|
assets = chat.assets(assets)
|
||||||
end
|
end
|
||||||
|
|
||||||
active_agent_ids = []
|
active_agent_ids = []
|
||||||
active_agents.each do |user|
|
active_agents(chat_ids).each do |user|
|
||||||
active_agent_ids.push user.id
|
active_agent_ids.push user.id
|
||||||
assets = user.assets(assets)
|
assets = user.assets(assets)
|
||||||
end
|
end
|
||||||
runningchat_session_list_local = running_chat_session_list
|
|
||||||
runningchat_session_list_local.each do |session|
|
running_chat_session_list_local = running_chat_session_list(chat_ids)
|
||||||
|
running_chat_session_list_local.each do |session|
|
||||||
next if !session['user_id']
|
next if !session['user_id']
|
||||||
|
|
||||||
user = User.lookup(id: session['user_id'])
|
user = User.lookup(id: session['user_id'])
|
||||||
|
@ -83,20 +218,78 @@ class Chat < ApplicationModel
|
||||||
|
|
||||||
assets = user.assets(assets)
|
assets = user.assets(assets)
|
||||||
end
|
end
|
||||||
|
|
||||||
{
|
{
|
||||||
waiting_chat_count: waiting_chat_count,
|
waiting_chat_count: waiting_chat_count(chat_ids),
|
||||||
waiting_chat_session_list: waiting_chat_session_list,
|
waiting_chat_session_list: waiting_chat_session_list(chat_ids),
|
||||||
running_chat_count: running_chat_count,
|
running_chat_count: running_chat_count(chat_ids),
|
||||||
running_chat_session_list: runningchat_session_list_local,
|
running_chat_session_list: running_chat_session_list_local,
|
||||||
active_agent_count: active_agent_count,
|
active_agent_count: active_agent_count(chat_ids),
|
||||||
active_agent_ids: active_agent_ids,
|
active_agent_ids: active_agent_ids,
|
||||||
seads_available: seads_available,
|
seads_available: seads_available(chat_ids),
|
||||||
seads_total: seads_total,
|
seads_total: seads_total(chat_ids),
|
||||||
active: Chat::Agent.state(user_id),
|
active: Chat::Agent.state(user_id),
|
||||||
assets: assets,
|
assets: assets,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
check if agent is available for chat_ids
|
||||||
|
|
||||||
|
chat_ids = Chat.agent_active_chat?(User.find(123), [1, 2])
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
true|false
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.agent_active_chat?(user, chat_ids)
|
||||||
|
return true if user.preferences[:chat].blank?
|
||||||
|
return true if user.preferences[:chat][:active].blank?
|
||||||
|
|
||||||
|
chat_ids.each do |chat_id|
|
||||||
|
return true if user.preferences[:chat][:active][chat_id] == 'on' || user.preferences[:chat][:active][chat_id.to_s] == 'on'
|
||||||
|
end
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
=begin
|
||||||
|
|
||||||
|
list all active sessins by user_id
|
||||||
|
|
||||||
|
Chat.agent_state_with_sessions(123)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
the same as Chat.agent_state(123) but with the following addition
|
||||||
|
|
||||||
|
active_sessions: [
|
||||||
|
{
|
||||||
|
id: 19,
|
||||||
|
chat_id: 1,
|
||||||
|
session_id: "f28b2704e381c668c9b59215e9481310",
|
||||||
|
name: "",
|
||||||
|
state: "running",
|
||||||
|
user_id: 3,
|
||||||
|
preferences: {
|
||||||
|
url: "http://localhost/chat.html",
|
||||||
|
participants: ["70332475730240", "70332481108980"],
|
||||||
|
remote_ip: nil,
|
||||||
|
geo_ip: nil,
|
||||||
|
dns_name: nil
|
||||||
|
},
|
||||||
|
updated_by_id: nil,
|
||||||
|
created_by_id: nil,
|
||||||
|
created_at: Thu, 02 May 2019 11:48:25 UTC +00:00,
|
||||||
|
updated_at: Thu, 02 May 2019 11:48:29 UTC +00:00,
|
||||||
|
messages: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
def self.agent_state_with_sessions(user_id)
|
def self.agent_state_with_sessions(user_id)
|
||||||
return { state: 'chat_disabled' } if !Setting.get('chat')
|
return { state: 'chat_disabled' } if !Setting.get('chat')
|
||||||
|
|
||||||
|
@ -105,87 +298,204 @@ class Chat < ApplicationModel
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.waiting_chat_count
|
=begin
|
||||||
Chat::Session.where(state: ['waiting']).count
|
|
||||||
|
get count if waiting sessions in given chats
|
||||||
|
|
||||||
|
Chat.waiting_chat_count(chat_ids)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
123
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.waiting_chat_count(chat_ids)
|
||||||
|
Chat::Session.where(state: ['waiting'], chat_id: chat_ids).count
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.waiting_chat_session_list
|
def self.waiting_chat_session_list(chat_ids)
|
||||||
sessions = []
|
sessions = []
|
||||||
Chat::Session.where(state: ['waiting']).each do |session|
|
Chat::Session.where(state: ['waiting'], chat_id: chat_ids).each do |session|
|
||||||
sessions.push session.attributes
|
sessions.push session.attributes
|
||||||
end
|
end
|
||||||
sessions
|
sessions
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.running_chat_count
|
=begin
|
||||||
Chat::Session.where(state: ['running']).count
|
|
||||||
|
get count running sessions in given chats
|
||||||
|
|
||||||
|
Chat.running_chat_count(chat_ids)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
123
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.running_chat_count(chat_ids)
|
||||||
|
Chat::Session.where(state: ['running'], chat_id: chat_ids).count
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.running_chat_session_list
|
def self.running_chat_session_list(chat_ids)
|
||||||
sessions = []
|
sessions = []
|
||||||
Chat::Session.where(state: ['running']).each do |session|
|
Chat::Session.where(state: ['running'], chat_id: chat_ids).each do |session|
|
||||||
sessions.push session.attributes
|
sessions.push session.attributes
|
||||||
end
|
end
|
||||||
sessions
|
sessions
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.active_chat_count
|
=begin
|
||||||
Chat::Session.where(state: %w[waiting running]).count
|
|
||||||
|
get count of active sessions in given chats
|
||||||
|
|
||||||
|
Chat.active_chat_count(chat_ids)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
123
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.active_chat_count(chat_ids)
|
||||||
|
Chat::Session.where(state: %w[waiting running], chat_id: chat_ids).count
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.available_agents(diff = 2.minutes)
|
=begin
|
||||||
|
|
||||||
|
get user agents with concurrent
|
||||||
|
|
||||||
|
Chat.available_agents_with_concurrent(chat_ids)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
{
|
||||||
|
123: 5,
|
||||||
|
124: 1,
|
||||||
|
125: 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.available_agents_with_concurrent(chat_ids, diff = 2.minutes)
|
||||||
agents = {}
|
agents = {}
|
||||||
Chat::Agent.where(active: true).where('updated_at > ?', Time.zone.now - diff).each do |record|
|
Chat::Agent.where(active: true).where('updated_at > ?', Time.zone.now - diff).each do |record|
|
||||||
|
user = User.lookup(id: record.updated_by_id)
|
||||||
|
next if !user
|
||||||
|
next if !agent_active_chat?(user, chat_ids)
|
||||||
|
|
||||||
agents[record.updated_by_id] = record.concurrent
|
agents[record.updated_by_id] = record.concurrent
|
||||||
end
|
end
|
||||||
agents
|
agents
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.active_agent_count(diff = 2.minutes)
|
=begin
|
||||||
Chat::Agent.where(active: true).where('updated_at > ?', Time.zone.now - diff).count
|
|
||||||
|
get count of active agents in given chats
|
||||||
|
|
||||||
|
Chat.active_agent_count(chat_ids)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
123
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.active_agent_count(chat_ids, diff = 2.minutes)
|
||||||
|
count = 0
|
||||||
|
Chat::Agent.where(active: true).where('updated_at > ?', Time.zone.now - diff).each do |record|
|
||||||
|
user = User.lookup(id: record.updated_by_id)
|
||||||
|
next if !user
|
||||||
|
next if !agent_active_chat?(user, chat_ids)
|
||||||
|
|
||||||
|
count += 1
|
||||||
|
end
|
||||||
|
count
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.active_agents(diff = 2.minutes)
|
=begin
|
||||||
|
|
||||||
|
get active agents in given chats
|
||||||
|
|
||||||
|
Chat.active_agent_count(chat_ids)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
[User.find(123), User.find(345)]
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.active_agents(chat_ids, diff = 2.minutes)
|
||||||
users = []
|
users = []
|
||||||
Chat::Agent.where(active: true).where('updated_at > ?', Time.zone.now - diff).each do |record|
|
Chat::Agent.where(active: true).where('updated_at > ?', Time.zone.now - diff).each do |record|
|
||||||
user = User.lookup(id: record.updated_by_id)
|
user = User.lookup(id: record.updated_by_id)
|
||||||
next if !user
|
next if !user
|
||||||
|
next if !agent_active_chat?(user, chat_ids)
|
||||||
|
|
||||||
users.push user
|
users.push user
|
||||||
end
|
end
|
||||||
users
|
users
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.seads_total(diff = 2.minutes)
|
=begin
|
||||||
|
|
||||||
|
get count all possible seads (possible chat sessions) in given chats
|
||||||
|
|
||||||
|
Chat.seads_total(chat_ids)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
123
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.seads_total(chat_ids, diff = 2.minutes)
|
||||||
total = 0
|
total = 0
|
||||||
available_agents(diff).each_value do |concurrent|
|
available_agents_with_concurrent(chat_ids, diff).each_value do |concurrent|
|
||||||
total += concurrent
|
total += concurrent
|
||||||
end
|
end
|
||||||
total
|
total
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.seads_available(diff = 2.minutes)
|
=begin
|
||||||
seads_total(diff) - active_chat_count
|
|
||||||
|
get count all available seads (available chat sessions) in given chats
|
||||||
|
|
||||||
|
Chat.seads_available(chat_ids)
|
||||||
|
|
||||||
|
returns
|
||||||
|
|
||||||
|
123
|
||||||
|
|
||||||
|
=end
|
||||||
|
|
||||||
|
def self.seads_available(chat_ids, diff = 2.minutes)
|
||||||
|
seads_total(chat_ids, diff) - active_chat_count(chat_ids)
|
||||||
end
|
end
|
||||||
|
|
||||||
=begin
|
=begin
|
||||||
|
|
||||||
broadcast new agent status to all agents
|
broadcast new agent status to all agents
|
||||||
|
|
||||||
Chat.broadcast_agent_state_update
|
Chat.broadcast_agent_state_update(chat_ids)
|
||||||
|
|
||||||
optional you can ignore it for dedicated user
|
optional you can ignore it for dedicated user
|
||||||
|
|
||||||
Chat.broadcast_agent_state_update(ignore_user_id)
|
Chat.broadcast_agent_state_update(chat_ids, ignore_user_id)
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def self.broadcast_agent_state_update(ignore_user_id = nil)
|
def self.broadcast_agent_state_update(chat_ids, ignore_user_id = nil)
|
||||||
|
|
||||||
# send broadcast to agents
|
# send broadcast to agents
|
||||||
Chat::Agent.where('active = ? OR updated_at > ?', true, Time.zone.now - 8.hours).each do |item|
|
Chat::Agent.where('active = ? OR updated_at > ?', true, Time.zone.now - 8.hours).each do |item|
|
||||||
next if item.updated_by_id == ignore_user_id
|
next if item.updated_by_id == ignore_user_id
|
||||||
|
|
||||||
|
user = User.lookup(id: item.updated_by_id)
|
||||||
|
next if !user
|
||||||
|
next if !agent_active_chat?(user, chat_ids)
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
event: 'chat_status_agent',
|
event: 'chat_status_agent',
|
||||||
data: Chat.agent_state(item.updated_by_id),
|
data: Chat.agent_state(item.updated_by_id),
|
||||||
|
@ -198,15 +508,15 @@ optional you can ignore it for dedicated user
|
||||||
|
|
||||||
broadcast new customer queue position to all waiting customers
|
broadcast new customer queue position to all waiting customers
|
||||||
|
|
||||||
Chat.broadcast_customer_state_update
|
Chat.broadcast_customer_state_update(chat_id)
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def self.broadcast_customer_state_update
|
def self.broadcast_customer_state_update(chat_id)
|
||||||
|
|
||||||
# send position update to other waiting sessions
|
# send position update to other waiting sessions
|
||||||
position = 0
|
position = 0
|
||||||
Chat::Session.where(state: 'waiting').order(created_at: :asc).each do |local_chat_session|
|
Chat::Session.where(state: 'waiting', chat_id: chat_id).order(created_at: :asc).each do |local_chat_session|
|
||||||
position += 1
|
position += 1
|
||||||
data = {
|
data = {
|
||||||
event: 'chat_session_queue',
|
event: 'chat_session_queue',
|
||||||
|
@ -228,11 +538,11 @@ cleanup old chat messages
|
||||||
|
|
||||||
optional you can put the max oldest chat entries
|
optional you can put the max oldest chat entries
|
||||||
|
|
||||||
Chat.cleanup(3.months)
|
Chat.cleanup(12.months)
|
||||||
|
|
||||||
=end
|
=end
|
||||||
|
|
||||||
def self.cleanup(diff = 3.months)
|
def self.cleanup(diff = 12.months)
|
||||||
Chat::Session.where(state: 'closed').where('updated_at < ?', Time.zone.now - diff).each do |chat_session|
|
Chat::Session.where(state: 'closed').where('updated_at < ?', Time.zone.now - diff).each do |chat_session|
|
||||||
Chat::Message.where(chat_session_id: chat_session.id).delete_all
|
Chat::Message.where(chat_session_id: chat_session.id).delete_all
|
||||||
chat_session.destroy
|
chat_session.destroy
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Observer::Chat::Leave::BackgroundJob
|
||||||
}
|
}
|
||||||
chat_session.send_to_recipients(message, @client_id)
|
chat_session.send_to_recipients(message, @client_id)
|
||||||
|
|
||||||
Chat.broadcast_agent_state_update
|
Chat.broadcast_agent_state_update([chat_session.chat_id])
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,10 +6,14 @@ class Sessions::Event::ChatAgentState < Sessions::Event::ChatBase
|
||||||
# check if user has permissions
|
# check if user has permissions
|
||||||
return if !permission_check('chat.agent', 'chat')
|
return if !permission_check('chat.agent', 'chat')
|
||||||
|
|
||||||
|
chat_user = User.lookup(id: @session['id'])
|
||||||
|
|
||||||
Chat::Agent.state(@session['id'], @payload['data']['active'])
|
Chat::Agent.state(@session['id'], @payload['data']['active'])
|
||||||
|
|
||||||
|
chat_ids = Chat.agent_active_chat_ids(chat_user)
|
||||||
|
|
||||||
# broadcast new state to agents
|
# broadcast new state to agents
|
||||||
Chat.broadcast_agent_state_update(@session['id'])
|
Chat.broadcast_agent_state_update(chat_ids, @session['id'])
|
||||||
|
|
||||||
{
|
{
|
||||||
event: 'chat_agent_state',
|
event: 'chat_agent_state',
|
||||||
|
|
|
@ -32,10 +32,10 @@ class Sessions::Event::ChatSessionClose < Sessions::Event::ChatBase
|
||||||
chat_session.save
|
chat_session.save
|
||||||
|
|
||||||
# set state update to all agents
|
# set state update to all agents
|
||||||
Chat.broadcast_agent_state_update
|
Chat.broadcast_agent_state_update([chat_session.chat_id])
|
||||||
|
|
||||||
# send position update to other waiting sessions
|
# send position update to other waiting sessions
|
||||||
Chat.broadcast_customer_state_update
|
Chat.broadcast_customer_state_update(chat_session.chat_id)
|
||||||
|
|
||||||
# notify about "leaving"
|
# notify about "leaving"
|
||||||
else
|
else
|
||||||
|
|
|
@ -40,14 +40,14 @@ class Sessions::Event::ChatSessionInit < Sessions::Event::ChatBase
|
||||||
)
|
)
|
||||||
|
|
||||||
# send broadcast to agents
|
# send broadcast to agents
|
||||||
Chat.broadcast_agent_state_update
|
Chat.broadcast_agent_state_update([chat_session.chat_id])
|
||||||
|
|
||||||
# return new session
|
# return new session
|
||||||
{
|
{
|
||||||
event: 'chat_session_queue',
|
event: 'chat_session_queue',
|
||||||
data: {
|
data: {
|
||||||
state: 'queue',
|
state: 'queue',
|
||||||
position: Chat.waiting_chat_count,
|
position: Chat.waiting_chat_count([chat_session.chat_id]),
|
||||||
session_id: chat_session.session_id,
|
session_id: chat_session.session_id,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@ class Sessions::Event::ChatSessionStart < Sessions::Event::ChatBase
|
||||||
return if !permission_check('chat.agent', 'chat')
|
return if !permission_check('chat.agent', 'chat')
|
||||||
|
|
||||||
# find first in waiting list
|
# find first in waiting list
|
||||||
chat_session = Chat::Session.where(state: 'waiting').order(created_at: :asc).first
|
chat_user = User.lookup(id: @session['id'])
|
||||||
|
chat_ids = Chat.agent_active_chat_ids(chat_user)
|
||||||
|
chat_session = Chat::Session.where(state: 'waiting', chat_id: chat_ids).order(created_at: :asc).first
|
||||||
if !chat_session
|
if !chat_session
|
||||||
return {
|
return {
|
||||||
event: 'chat_session_start',
|
event: 'chat_session_start',
|
||||||
|
@ -15,13 +17,12 @@ class Sessions::Event::ChatSessionStart < Sessions::Event::ChatBase
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
chat_session.user_id = @session['id']
|
chat_session.user_id = chat_user.id
|
||||||
chat_session.state = 'running'
|
chat_session.state = 'running'
|
||||||
chat_session.preferences[:participants] = chat_session.add_recipient(@client_id)
|
chat_session.preferences[:participants] = chat_session.add_recipient(@client_id)
|
||||||
chat_session.save
|
chat_session.save
|
||||||
|
|
||||||
# send chat_session_init to client
|
# send chat_session_init to client
|
||||||
chat_user = User.lookup(id: chat_session.user_id)
|
|
||||||
url = nil
|
url = nil
|
||||||
if chat_user.image && chat_user.image != 'none'
|
if chat_user.image && chat_user.image != 'none'
|
||||||
url = "#{Setting.get('http_type')}://#{Setting.get('fqdn')}/api/v1/users/image/#{chat_user.image}"
|
url = "#{Setting.get('http_type')}://#{Setting.get('fqdn')}/api/v1/users/image/#{chat_user.image}"
|
||||||
|
@ -52,10 +53,10 @@ class Sessions::Event::ChatSessionStart < Sessions::Event::ChatBase
|
||||||
Sessions.send(@client_id, data)
|
Sessions.send(@client_id, data)
|
||||||
|
|
||||||
# send state update with sessions to agents
|
# send state update with sessions to agents
|
||||||
Chat.broadcast_agent_state_update
|
Chat.broadcast_agent_state_update([chat_session.chat_id])
|
||||||
|
|
||||||
# send position update to other waiting sessions
|
# send position update to other waiting sessions
|
||||||
Chat.broadcast_customer_state_update
|
Chat.broadcast_customer_state_update(chat_session.chat_id)
|
||||||
|
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@ class ChatTest < ActiveSupport::TestCase
|
||||||
setup do
|
setup do
|
||||||
groups = Group.all
|
groups = Group.all
|
||||||
roles = Role.where(name: %w[Agent])
|
roles = Role.where(name: %w[Agent])
|
||||||
@agent1 = User.create_or_update(
|
@agent1 = User.create!(
|
||||||
login: 'ticket-chat-agent1@example.com',
|
login: 'ticket-chat-agent1@example.com',
|
||||||
firstname: 'Notification',
|
firstname: 'Notification',
|
||||||
lastname: 'Agent1',
|
lastname: 'Agent1',
|
||||||
|
@ -18,7 +18,7 @@ class ChatTest < ActiveSupport::TestCase
|
||||||
updated_by_id: 1,
|
updated_by_id: 1,
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
)
|
)
|
||||||
@agent2 = User.create_or_update(
|
@agent2 = User.create!(
|
||||||
login: 'ticket-chat-agent2@example.com',
|
login: 'ticket-chat-agent2@example.com',
|
||||||
firstname: 'Notification',
|
firstname: 'Notification',
|
||||||
lastname: 'Agent2',
|
lastname: 'Agent2',
|
||||||
|
@ -130,8 +130,7 @@ class ChatTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
test 'default test' do
|
test 'default test' do
|
||||||
|
chat = Chat.create!(
|
||||||
chat = Chat.create_or_update(
|
|
||||||
name: 'default',
|
name: 'default',
|
||||||
max_queue: 5,
|
max_queue: 5,
|
||||||
note: '',
|
note: '',
|
||||||
|
@ -140,6 +139,19 @@ class ChatTest < ActiveSupport::TestCase
|
||||||
created_by_id: 1,
|
created_by_id: 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@agent1.preferences[:chat] = {
|
||||||
|
active: {
|
||||||
|
chat.id => 'on',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@agent1.save!
|
||||||
|
@agent2.preferences[:chat] = {
|
||||||
|
active: {
|
||||||
|
chat.id => 'on',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@agent2.save!
|
||||||
|
|
||||||
# check if feature is disabled
|
# check if feature is disabled
|
||||||
assert_equal('chat_disabled', chat.customer_state[:state])
|
assert_equal('chat_disabled', chat.customer_state[:state])
|
||||||
assert_equal('chat_disabled', Chat.agent_state(@agent1.id)[:state])
|
assert_equal('chat_disabled', Chat.agent_state(@agent1.id)[:state])
|
||||||
|
@ -178,7 +190,7 @@ class ChatTest < ActiveSupport::TestCase
|
||||||
assert_equal(true, agent_state[:active])
|
assert_equal(true, agent_state[:active])
|
||||||
|
|
||||||
# start session
|
# start session
|
||||||
chat_session1 = Chat::Session.create(
|
chat_session1 = Chat::Session.create!(
|
||||||
chat_id: chat.id,
|
chat_id: chat.id,
|
||||||
user_id: @agent1.id,
|
user_id: @agent1.id,
|
||||||
)
|
)
|
||||||
|
@ -197,7 +209,7 @@ class ChatTest < ActiveSupport::TestCase
|
||||||
assert_equal(true, agent_state[:active])
|
assert_equal(true, agent_state[:active])
|
||||||
|
|
||||||
# activate second agent
|
# activate second agent
|
||||||
chat_agent2 = Chat::Agent.create_or_update(
|
chat_agent2 = Chat::Agent.create!(
|
||||||
active: true,
|
active: true,
|
||||||
concurrent: 2,
|
concurrent: 2,
|
||||||
updated_by_id: @agent2.id,
|
updated_by_id: @agent2.id,
|
||||||
|
@ -255,13 +267,13 @@ class ChatTest < ActiveSupport::TestCase
|
||||||
Chat::Session.create(
|
Chat::Session.create(
|
||||||
chat_id: chat.id,
|
chat_id: chat.id,
|
||||||
)
|
)
|
||||||
chat_session4 = Chat::Session.create(
|
chat_session4 = Chat::Session.create!(
|
||||||
chat_id: chat.id,
|
chat_id: chat.id,
|
||||||
)
|
)
|
||||||
chat_session5 = Chat::Session.create(
|
chat_session5 = Chat::Session.create!(
|
||||||
chat_id: chat.id,
|
chat_id: chat.id,
|
||||||
)
|
)
|
||||||
chat_session6 = Chat::Session.create(
|
chat_session6 = Chat::Session.create!(
|
||||||
chat_id: chat.id,
|
chat_id: chat.id,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -290,25 +302,25 @@ class ChatTest < ActiveSupport::TestCase
|
||||||
chat_session6.state = 'running'
|
chat_session6.state = 'running'
|
||||||
chat_session6.save
|
chat_session6.save
|
||||||
|
|
||||||
Chat::Message.create(
|
Chat::Message.create!(
|
||||||
chat_session_id: chat_session6.id,
|
chat_session_id: chat_session6.id,
|
||||||
content: 'message 1',
|
content: 'message 1',
|
||||||
created_by_id: @agent1.id,
|
created_by_id: @agent1.id,
|
||||||
)
|
)
|
||||||
travel 1.second
|
travel 1.second
|
||||||
Chat::Message.create(
|
Chat::Message.create!(
|
||||||
chat_session_id: chat_session6.id,
|
chat_session_id: chat_session6.id,
|
||||||
content: 'message 2',
|
content: 'message 2',
|
||||||
created_by_id: @agent1.id,
|
created_by_id: @agent1.id,
|
||||||
)
|
)
|
||||||
travel 1.second
|
travel 1.second
|
||||||
Chat::Message.create(
|
Chat::Message.create!(
|
||||||
chat_session_id: chat_session6.id,
|
chat_session_id: chat_session6.id,
|
||||||
content: 'message 3',
|
content: 'message 3',
|
||||||
created_by_id: @agent1.id,
|
created_by_id: @agent1.id,
|
||||||
)
|
)
|
||||||
travel 1.second
|
travel 1.second
|
||||||
Chat::Message.create(
|
Chat::Message.create!(
|
||||||
chat_session_id: chat_session6.id,
|
chat_session_id: chat_session6.id,
|
||||||
content: 'message 4',
|
content: 'message 4',
|
||||||
created_by_id: nil,
|
created_by_id: nil,
|
||||||
|
@ -441,6 +453,155 @@ class ChatTest < ActiveSupport::TestCase
|
||||||
travel_back
|
travel_back
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test 'check if agent_state_with_sessions works correctly with 2 chats' do
|
||||||
|
chat1 = Chat.create!(
|
||||||
|
name: 'topic 1',
|
||||||
|
max_queue: 5,
|
||||||
|
note: '',
|
||||||
|
active: true,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
chat2 = Chat.create!(
|
||||||
|
name: 'topic 2',
|
||||||
|
max_queue: 5,
|
||||||
|
note: '',
|
||||||
|
active: true,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
@agent1.preferences[:chat] = {
|
||||||
|
active: {
|
||||||
|
chat1.id.to_s => 'on',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@agent1.save!
|
||||||
|
@agent2.preferences[:chat] = {
|
||||||
|
active: {
|
||||||
|
chat2.id.to_s => 'on',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@agent2.save!
|
||||||
|
|
||||||
|
Setting.set('chat', true)
|
||||||
|
|
||||||
|
# check customer state
|
||||||
|
assert_equal('offline', chat1.customer_state[:state])
|
||||||
|
assert_equal('offline', chat2.customer_state[:state])
|
||||||
|
|
||||||
|
# check agent state
|
||||||
|
agent_state = Chat.agent_state_with_sessions(@agent1.id)
|
||||||
|
assert_equal(0, agent_state[:waiting_chat_count])
|
||||||
|
assert_equal(0, agent_state[:running_chat_count])
|
||||||
|
assert_equal([], agent_state[:active_sessions])
|
||||||
|
assert_equal(0, agent_state[:seads_available])
|
||||||
|
assert_equal(0, agent_state[:seads_total])
|
||||||
|
assert_equal(false, agent_state[:active])
|
||||||
|
|
||||||
|
# set agent 1 to active
|
||||||
|
Chat::Agent.create!(
|
||||||
|
active: true,
|
||||||
|
concurrent: 4,
|
||||||
|
updated_by_id: @agent1.id,
|
||||||
|
created_by_id: @agent1.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
# check customer state
|
||||||
|
assert_equal('online', chat1.customer_state[:state])
|
||||||
|
assert_equal('offline', chat2.customer_state[:state])
|
||||||
|
|
||||||
|
# check agent state
|
||||||
|
agent_state = Chat.agent_state_with_sessions(@agent2.id)
|
||||||
|
assert_equal(0, agent_state[:waiting_chat_count])
|
||||||
|
assert_equal(0, agent_state[:running_chat_count])
|
||||||
|
assert_equal([], agent_state[:active_sessions])
|
||||||
|
assert_equal(0, agent_state[:seads_available])
|
||||||
|
assert_equal(0, agent_state[:seads_total])
|
||||||
|
assert_equal(false, agent_state[:active])
|
||||||
|
|
||||||
|
# set agent 2 to active
|
||||||
|
Chat::Agent.create!(
|
||||||
|
active: true,
|
||||||
|
concurrent: 2,
|
||||||
|
updated_by_id: @agent2.id,
|
||||||
|
created_by_id: @agent2.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
# check customer state
|
||||||
|
assert_equal('online', chat1.customer_state[:state])
|
||||||
|
assert_equal('online', chat2.customer_state[:state])
|
||||||
|
|
||||||
|
# start session
|
||||||
|
chat_session1 = Chat::Session.create!(
|
||||||
|
chat_id: chat1.id,
|
||||||
|
user_id: @agent1.id,
|
||||||
|
)
|
||||||
|
assert(chat_session1.session_id)
|
||||||
|
|
||||||
|
# check agent1 state
|
||||||
|
agent_state = Chat.agent_state_with_sessions(@agent1.id)
|
||||||
|
assert_equal(1, agent_state[:waiting_chat_count])
|
||||||
|
assert_equal(0, agent_state[:running_chat_count])
|
||||||
|
assert_equal([], agent_state[:active_sessions])
|
||||||
|
assert_equal(3, agent_state[:seads_available])
|
||||||
|
assert_equal(4, agent_state[:seads_total])
|
||||||
|
assert_equal(true, agent_state[:active])
|
||||||
|
|
||||||
|
# check agent2 state
|
||||||
|
agent_state = Chat.agent_state_with_sessions(@agent2.id)
|
||||||
|
assert_equal(0, agent_state[:waiting_chat_count])
|
||||||
|
assert_equal(0, agent_state[:running_chat_count])
|
||||||
|
assert_equal([], agent_state[:active_sessions])
|
||||||
|
assert_equal(2, agent_state[:seads_available])
|
||||||
|
assert_equal(2, agent_state[:seads_total])
|
||||||
|
assert_equal(true, agent_state[:active])
|
||||||
|
end
|
||||||
|
|
||||||
|
test 'if agent_active_chat_ids works correctly' do
|
||||||
|
chat1 = Chat.create!(
|
||||||
|
name: 'topic 1',
|
||||||
|
max_queue: 5,
|
||||||
|
note: '',
|
||||||
|
active: true,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
chat2 = Chat.create!(
|
||||||
|
name: 'topic 2',
|
||||||
|
max_queue: 5,
|
||||||
|
note: '',
|
||||||
|
active: true,
|
||||||
|
updated_by_id: 1,
|
||||||
|
created_by_id: 1,
|
||||||
|
)
|
||||||
|
assert_equal([], Chat.agent_active_chat_ids(@agent1))
|
||||||
|
assert_equal([], Chat.agent_active_chat_ids(@agent2))
|
||||||
|
|
||||||
|
@agent1.preferences[:chat] = {
|
||||||
|
active: {
|
||||||
|
chat1.id.to_s => 'on',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@agent1.save!
|
||||||
|
@agent2.preferences[:chat] = {
|
||||||
|
active: {
|
||||||
|
chat2.id => 'on',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@agent2.save!
|
||||||
|
assert_equal([chat1.id], Chat.agent_active_chat_ids(@agent1))
|
||||||
|
assert_equal([chat2.id], Chat.agent_active_chat_ids(@agent2))
|
||||||
|
|
||||||
|
@agent2.preferences[:chat] = {
|
||||||
|
active: {
|
||||||
|
chat2.id => 'off',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@agent2.save!
|
||||||
|
assert_equal([chat1.id], Chat.agent_active_chat_ids(@agent1))
|
||||||
|
assert_equal([], Chat.agent_active_chat_ids(@agent2))
|
||||||
|
end
|
||||||
|
|
||||||
test 'blocked ip test' do
|
test 'blocked ip test' do
|
||||||
chat = Chat.create!(
|
chat = Chat.create!(
|
||||||
name: 'ip test',
|
name: 'ip test',
|
||||||
|
|
Loading…
Reference in a new issue