Browse Source

Fixes issue #2441 - Zammad ignores disabled Chat-Topics for agents.

Martin Edenhofer 5 years ago
parent
commit
8a5552c9f8

+ 4 - 0
app/assets/javascripts/app/controllers/chat.coffee

@@ -832,6 +832,10 @@ class Setting extends App.ControllerModal
     # update runtime
     @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
     @ajax(
       id:          'preferences'

+ 350 - 40
app/models/chat.rb

@@ -4,6 +4,60 @@ class Chat < ApplicationModel
   validates :name, presence: true
   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)
     return { state: 'chat_disabled' } if !Setting.get('chat')
 
@@ -45,16 +99,16 @@ class Chat < ApplicationModel
     end
 
     # check if agents are available
-    available_agents = Chat::Agent.where(active: true).where('updated_at > ?', Time.zone.now - 2.minutes).count
-    if available_agents.zero?
+    if Chat.active_agent_count([id]).zero?
       return { state: 'offline' }
     end
 
     # 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 {
         state: 'no_seats_available',
-        queue: Chat.waiting_chat_count,
+        queue: waiting_count,
       }
     end
 
@@ -62,20 +116,101 @@ class Chat < ApplicationModel
     { state: 'online' }
   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)
     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 = {}
     Chat.where(active: true).each do |chat|
       assets = chat.assets(assets)
     end
+
     active_agent_ids = []
-    active_agents.each do |user|
+    active_agents(chat_ids).each do |user|
       active_agent_ids.push user.id
       assets = user.assets(assets)
     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']
 
       user = User.lookup(id: session['user_id'])
@@ -83,20 +218,78 @@ class Chat < ApplicationModel
 
       assets = user.assets(assets)
     end
+
     {
-      waiting_chat_count:        waiting_chat_count,
-      waiting_chat_session_list: waiting_chat_session_list,
-      running_chat_count:        running_chat_count,
-      running_chat_session_list: runningchat_session_list_local,
-      active_agent_count:        active_agent_count,
+      waiting_chat_count:        waiting_chat_count(chat_ids),
+      waiting_chat_session_list: waiting_chat_session_list(chat_ids),
+      running_chat_count:        running_chat_count(chat_ids),
+      running_chat_session_list: running_chat_session_list_local,
+      active_agent_count:        active_agent_count(chat_ids),
       active_agent_ids:          active_agent_ids,
-      seads_available:           seads_available,
-      seads_total:               seads_total,
+      seads_available:           seads_available(chat_ids),
+      seads_total:               seads_total(chat_ids),
       active:                    Chat::Agent.state(user_id),
       assets:                    assets,
     }
   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)
     return { state: 'chat_disabled' } if !Setting.get('chat')
 
@@ -105,87 +298,204 @@ class Chat < ApplicationModel
     result
   end
 
-  def self.waiting_chat_count
-    Chat::Session.where(state: ['waiting']).count
+=begin
+
+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
 
-  def self.waiting_chat_session_list
+  def self.waiting_chat_session_list(chat_ids)
     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
     end
     sessions
   end
 
-  def self.running_chat_count
-    Chat::Session.where(state: ['running']).count
+=begin
+
+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
 
-  def self.running_chat_session_list
+  def self.running_chat_session_list(chat_ids)
     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
     end
     sessions
   end
 
-  def self.active_chat_count
-    Chat::Session.where(state: %w[waiting running]).count
+=begin
+
+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
 
-  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 = {}
     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
     end
     agents
   end
 
-  def self.active_agent_count(diff = 2.minutes)
-    Chat::Agent.where(active: true).where('updated_at > ?', Time.zone.now - diff).count
+=begin
+
+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
 
-  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 = []
     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)
 
       users.push user
     end
     users
   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
-    available_agents(diff).each_value do |concurrent|
+    available_agents_with_concurrent(chat_ids, diff).each_value do |concurrent|
       total += concurrent
     end
     total
   end
 
-  def self.seads_available(diff = 2.minutes)
-    seads_total(diff) - active_chat_count
+=begin
+
+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
 
 =begin
 
 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
 
-  Chat.broadcast_agent_state_update(ignore_user_id)
+  Chat.broadcast_agent_state_update(chat_ids, ignore_user_id)
 
 =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
     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
 
+      user = User.lookup(id: item.updated_by_id)
+      next if !user
+      next if !agent_active_chat?(user, chat_ids)
+
       data = {
         event: 'chat_status_agent',
         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
 
-  Chat.broadcast_customer_state_update
+  Chat.broadcast_customer_state_update(chat_id)
 
 =end
 
-  def self.broadcast_customer_state_update
+  def self.broadcast_customer_state_update(chat_id)
 
     # send position update to other waiting sessions
     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
       data = {
         event: 'chat_session_queue',
@@ -228,11 +538,11 @@ cleanup old chat messages
 
 optional you can put the max oldest chat entries
 
-  Chat.cleanup(3.months)
+  Chat.cleanup(12.months)
 
 =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::Message.where(chat_session_id: chat_session.id).delete_all
       chat_session.destroy

+ 1 - 1
app/models/observer/chat/leave/background_job.rb

@@ -30,7 +30,7 @@ class Observer::Chat::Leave::BackgroundJob
     }
     chat_session.send_to_recipients(message, @client_id)
 
-    Chat.broadcast_agent_state_update
+    Chat.broadcast_agent_state_update([chat_session.chat_id])
   end
 
 end

+ 5 - 1
lib/sessions/event/chat_agent_state.rb

@@ -6,10 +6,14 @@ class Sessions::Event::ChatAgentState < Sessions::Event::ChatBase
     # check if user has permissions
     return if !permission_check('chat.agent', 'chat')
 
+    chat_user = User.lookup(id: @session['id'])
+
     Chat::Agent.state(@session['id'], @payload['data']['active'])
 
+    chat_ids = Chat.agent_active_chat_ids(chat_user)
+
     # 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',

+ 2 - 2
lib/sessions/event/chat_session_close.rb

@@ -32,10 +32,10 @@ class Sessions::Event::ChatSessionClose < Sessions::Event::ChatBase
       chat_session.save
 
       # 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
-      Chat.broadcast_customer_state_update
+      Chat.broadcast_customer_state_update(chat_session.chat_id)
 
     # notify about "leaving"
     else

+ 2 - 2
lib/sessions/event/chat_session_init.rb

@@ -40,14 +40,14 @@ class Sessions::Event::ChatSessionInit < Sessions::Event::ChatBase
     )
 
     # send broadcast to agents
-    Chat.broadcast_agent_state_update
+    Chat.broadcast_agent_state_update([chat_session.chat_id])
 
     # return new session
     {
       event: 'chat_session_queue',
       data:  {
         state:      'queue',
-        position:   Chat.waiting_chat_count,
+        position:   Chat.waiting_chat_count([chat_session.chat_id]),
         session_id: chat_session.session_id,
       },
     }

+ 6 - 5
lib/sessions/event/chat_session_start.rb

@@ -5,7 +5,9 @@ class Sessions::Event::ChatSessionStart < Sessions::Event::ChatBase
     return if !permission_check('chat.agent', 'chat')
 
     # 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
       return {
         event: 'chat_session_start',
@@ -15,13 +17,12 @@ class Sessions::Event::ChatSessionStart < Sessions::Event::ChatBase
         },
       }
     end
-    chat_session.user_id = @session['id']
+    chat_session.user_id = chat_user.id
     chat_session.state = 'running'
     chat_session.preferences[:participants] = chat_session.add_recipient(@client_id)
     chat_session.save
 
     # send chat_session_init to client
-    chat_user = User.lookup(id: chat_session.user_id)
     url = nil
     if chat_user.image && chat_user.image != 'none'
       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)
 
     # 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
-    Chat.broadcast_customer_state_update
+    Chat.broadcast_customer_state_update(chat_session.chat_id)
 
     nil
   end

+ 174 - 13
test/unit/chat_test.rb

@@ -5,7 +5,7 @@ class ChatTest < ActiveSupport::TestCase
   setup do
     groups = Group.all
     roles  = Role.where(name: %w[Agent])
-    @agent1 = User.create_or_update(
+    @agent1 = User.create!(
       login:         'ticket-chat-agent1@example.com',
       firstname:     'Notification',
       lastname:      'Agent1',
@@ -18,7 +18,7 @@ class ChatTest < ActiveSupport::TestCase
       updated_by_id: 1,
       created_by_id: 1,
     )
-    @agent2 = User.create_or_update(
+    @agent2 = User.create!(
       login:         'ticket-chat-agent2@example.com',
       firstname:     'Notification',
       lastname:      'Agent2',
@@ -130,8 +130,7 @@ class ChatTest < ActiveSupport::TestCase
   end
 
   test 'default test' do
-
-    chat = Chat.create_or_update(
+    chat = Chat.create!(
       name:          'default',
       max_queue:     5,
       note:          '',
@@ -140,6 +139,19 @@ class ChatTest < ActiveSupport::TestCase
       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
     assert_equal('chat_disabled', chat.customer_state[: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])
 
     # start session
-    chat_session1 = Chat::Session.create(
+    chat_session1 = Chat::Session.create!(
       chat_id: chat.id,
       user_id: @agent1.id,
     )
@@ -197,7 +209,7 @@ class ChatTest < ActiveSupport::TestCase
     assert_equal(true, agent_state[:active])
 
     # activate second agent
-    chat_agent2 = Chat::Agent.create_or_update(
+    chat_agent2 = Chat::Agent.create!(
       active:        true,
       concurrent:    2,
       updated_by_id: @agent2.id,
@@ -255,13 +267,13 @@ class ChatTest < ActiveSupport::TestCase
     Chat::Session.create(
       chat_id: chat.id,
     )
-    chat_session4 = Chat::Session.create(
+    chat_session4 = Chat::Session.create!(
       chat_id: chat.id,
     )
-    chat_session5 = Chat::Session.create(
+    chat_session5 = Chat::Session.create!(
       chat_id: chat.id,
     )
-    chat_session6 = Chat::Session.create(
+    chat_session6 = Chat::Session.create!(
       chat_id: chat.id,
     )
 
@@ -290,25 +302,25 @@ class ChatTest < ActiveSupport::TestCase
     chat_session6.state = 'running'
     chat_session6.save
 
-    Chat::Message.create(
+    Chat::Message.create!(
       chat_session_id: chat_session6.id,
       content:         'message 1',
       created_by_id:   @agent1.id,
     )
     travel 1.second
-    Chat::Message.create(
+    Chat::Message.create!(
       chat_session_id: chat_session6.id,
       content:         'message 2',
       created_by_id:   @agent1.id,
     )
     travel 1.second
-    Chat::Message.create(
+    Chat::Message.create!(
       chat_session_id: chat_session6.id,
       content:         'message 3',
       created_by_id:   @agent1.id,
     )
     travel 1.second
-    Chat::Message.create(
+    Chat::Message.create!(
       chat_session_id: chat_session6.id,
       content:         'message 4',
       created_by_id:   nil,
@@ -441,6 +453,155 @@ class ChatTest < ActiveSupport::TestCase
     travel_back
   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
     chat = Chat.create!(
       name:          'ip test',