From 2ecb2ca0f007ff01fbef3b966c4c9737289f9204 Mon Sep 17 00:00:00 2001
From: Sojan Jose
Date: Tue, 16 Aug 2022 16:58:23 +0530
Subject: [PATCH] feat: Enable Capacity Config UI (#5164)
- Enables Capacity Config in UI
- Rewrite auto assignment Logic to consider only online agents
fixes: #4990
---
.../inbox/settingsPage/CollaboratorsPage.vue | 3 +-
app/models/concerns/assignment_handler.rb | 4 +-
..._handler.rb => auto_assignment_handler.rb} | 12 +--
app/models/conversation.rb | 2 +-
app/models/inbox.rb | 2 +-
app/models/inbox_member.rb | 4 +-
.../agent_assignment_service.rb | 38 +++++++++
.../inbox_round_robin_service.rb | 62 ++++++++++++++
.../round_robin/assignment_service.rb | 28 ------
app/services/round_robin/manage_service.rb | 85 -------------------
lib/online_status_tracker.rb | 2 +-
.../assignments_controller_spec.rb | 2 +-
.../accounts/conversations_controller_spec.rb | 2 +-
spec/factories/users.rb | 6 +-
.../concerns/assignment_handler_shared.rb | 2 +-
...d.rb => auto_assignment_handler_shared.rb} | 11 +--
spec/models/conversation_spec.rb | 4 +-
.../agent_assignment_service_spec.rb | 38 +++++++++
.../inbox_round_robin_service_spec.rb | 59 +++++++++++++
.../round_robin/manage_service_spec.rb | 75 ----------------
20 files changed, 225 insertions(+), 216 deletions(-)
rename app/models/concerns/{round_robin_handler.rb => auto_assignment_handler.rb} (59%)
create mode 100644 app/services/auto_assignment/agent_assignment_service.rb
create mode 100644 app/services/auto_assignment/inbox_round_robin_service.rb
delete mode 100644 app/services/round_robin/assignment_service.rb
delete mode 100644 app/services/round_robin/manage_service.rb
rename spec/models/concerns/{round_robin_handler_shared.rb => auto_assignment_handler_shared.rb} (91%)
create mode 100644 spec/services/auto_assignment/agent_assignment_service_spec.rb
create mode 100644 spec/services/auto_assignment/inbox_round_robin_service_spec.rb
delete mode 100644 spec/services/round_robin/manage_service_spec.rb
diff --git a/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/CollaboratorsPage.vue b/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/CollaboratorsPage.vue
index 68f5bc5e3..e830bd640 100644
--- a/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/CollaboratorsPage.vue
+++ b/app/javascript/dashboard/routes/dashboard/settings/inbox/settingsPage/CollaboratorsPage.vue
@@ -49,9 +49,8 @@
-
'busy',
+ inbox_members[1].user_id.to_s => 'busy',
+ inbox_members[2].user_id.to_s => 'busy',
+ inbox_members[3].user_id.to_s => 'online',
+ inbox_members[4].user_id.to_s => 'online'
+ }
+ end
+
+ before do
+ allow(::OnlineStatusTracker).to receive(:get_available_users).and_return(online_users)
+ end
+
+ describe '#perform' do
+ it 'will assign an online agent to the conversation' do
+ expect(conversation.reload.assignee).to be_nil
+ described_class.new(conversation: conversation, allowed_agent_ids: inbox_members.map(&:user_id).map(&:to_s)).perform
+ expect(conversation.reload.assignee).not_to be_nil
+ end
+ end
+
+ describe '#find_assignee' do
+ it 'will return an online agent from the allowed agent ids in roud robin' do
+ expect(described_class.new(conversation: conversation,
+ allowed_agent_ids: inbox_members.map(&:user_id).map(&:to_s)).find_assignee).to eq(inbox_members[3].user)
+ expect(described_class.new(conversation: conversation,
+ allowed_agent_ids: inbox_members.map(&:user_id).map(&:to_s)).find_assignee).to eq(inbox_members[4].user)
+ end
+ end
+end
diff --git a/spec/services/auto_assignment/inbox_round_robin_service_spec.rb b/spec/services/auto_assignment/inbox_round_robin_service_spec.rb
new file mode 100644
index 000000000..1c78a2785
--- /dev/null
+++ b/spec/services/auto_assignment/inbox_round_robin_service_spec.rb
@@ -0,0 +1,59 @@
+require 'rails_helper'
+
+describe AutoAssignment::InboxRoundRobinService do
+ subject(:inbox_round_robin_service) { described_class.new(inbox: inbox) }
+
+ let!(:account) { create(:account) }
+ let!(:inbox) { create(:inbox, account: account) }
+ let!(:inbox_members) { create_list(:inbox_member, 5, inbox: inbox) }
+
+ describe '#available_agent' do
+ it 'returns nil if allowed_agent_ids is not passed or empty' do
+ expect(described_class.new(inbox: inbox).available_agent).to be_nil
+ end
+
+ it 'gets the first available agent in allowed_agent_ids and move agent to end of the list' do
+ expected_queue = [inbox_members[0].user_id, inbox_members[4].user_id, inbox_members[3].user_id, inbox_members[2].user_id,
+ inbox_members[1].user_id].map(&:to_s)
+ described_class.new(inbox: inbox).available_agent(allowed_agent_ids: [inbox_members[0].user_id, inbox_members[4].user_id].map(&:to_s))
+ expect(inbox_round_robin_service.send(:queue)).to eq(expected_queue)
+ end
+
+ it 'constructs round_robin_queue if queue is not present' do
+ inbox_round_robin_service.clear_queue
+ expect(inbox_round_robin_service.send(:queue)).to eq([])
+ inbox_round_robin_service.available_agent
+ # the service constructed the redis queue before performing
+ expect(inbox_round_robin_service.send(:queue).sort.map(&:to_i)).to eq(inbox_members.map(&:user_id).sort)
+ end
+
+ it 'validates the queue and correct it before performing round robin' do
+ # adding some invalid ids to queue
+ inbox_round_robin_service.add_agent_to_queue([2, 3, 5, 9])
+ expect(inbox_round_robin_service.send(:queue).sort.map(&:to_i)).not_to eq(inbox_members.map(&:user_id).sort)
+ inbox_round_robin_service.available_agent
+ # the service have refreshed the redis queue before performing
+ expect(inbox_round_robin_service.send(:queue).sort.map(&:to_i)).to eq(inbox_members.map(&:user_id).sort)
+ end
+
+ context 'when allowed_agent_ids is passed' do
+ it 'will get the first allowed member and move it to the end of the queue' do
+ expected_queue = [inbox_members[3].user_id, inbox_members[2].user_id, inbox_members[4].user_id, inbox_members[1].user_id,
+ inbox_members[0].user_id].map(&:to_s)
+ expect(described_class.new(inbox: inbox).available_agent(
+ allowed_agent_ids: [
+ inbox_members[3].user_id,
+ inbox_members[2].user_id
+ ].map(&:to_s)
+ )).to eq inbox_members[2].user
+ expect(described_class.new(inbox: inbox).available_agent(
+ allowed_agent_ids: [
+ inbox_members[3].user_id,
+ inbox_members[2].user_id
+ ].map(&:to_s)
+ )).to eq inbox_members[3].user
+ expect(inbox_round_robin_service.send(:queue)).to eq(expected_queue)
+ end
+ end
+ end
+end
diff --git a/spec/services/round_robin/manage_service_spec.rb b/spec/services/round_robin/manage_service_spec.rb
deleted file mode 100644
index fafbfb6d4..000000000
--- a/spec/services/round_robin/manage_service_spec.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-require 'rails_helper'
-
-describe RoundRobin::ManageService do
- subject(:round_robin_manage_service) { described_class.new(inbox: inbox) }
-
- let!(:account) { create(:account) }
- let!(:inbox) { create(:inbox, account: account) }
- let!(:inbox_members) { create_list(:inbox_member, 5, inbox: inbox) }
-
- describe '#available_agent' do
- it 'returns nil if allowed_member_ids is empty' do
- expect(described_class.new(inbox: inbox, allowed_member_ids: []).available_agent).to be_nil
- end
-
- it 'gets the first available agent in allowed_member_ids and move agent to end of the list' do
- expected_queue = [inbox_members[0].user_id, inbox_members[4].user_id, inbox_members[3].user_id, inbox_members[2].user_id,
- inbox_members[1].user_id].map(&:to_s)
- described_class.new(inbox: inbox, allowed_member_ids: [inbox_members[0].user_id, inbox_members[4].user_id]).available_agent
- expect(round_robin_manage_service.send(:queue)).to eq(expected_queue)
- end
-
- it 'gets intersection of priority list and agent queue. get and move agent to the end of the list' do
- expected_queue = [inbox_members[2].user_id, inbox_members[4].user_id, inbox_members[3].user_id, inbox_members[1].user_id,
- inbox_members[0].user_id].map(&:to_s)
- # prority list will be ids in string, since thats what redis supplies to us
- expect(described_class.new(inbox: inbox, allowed_member_ids: [inbox_members[2].user_id])
- .available_agent(priority_list: [inbox_members[3].user_id.to_s, inbox_members[2].user_id.to_s])).to eq inbox_members[2].user
- expect(round_robin_manage_service.send(:queue)).to eq(expected_queue)
- end
-
- it 'constructs round_robin_queue if queue is not present' do
- round_robin_manage_service.clear_queue
- expect(round_robin_manage_service.send(:queue)).to eq([])
- round_robin_manage_service.available_agent
- # the service constructed the redis queue before performing
- expect(round_robin_manage_service.send(:queue).sort.map(&:to_i)).to eq(inbox_members.map(&:user_id).sort)
- end
-
- it 'validates the queue and correct it before performing round robin' do
- # adding some invalid ids to queue
- round_robin_manage_service.add_agent_to_queue([2, 3, 5, 9])
- expect(round_robin_manage_service.send(:queue).sort.map(&:to_i)).not_to eq(inbox_members.map(&:user_id).sort)
- round_robin_manage_service.available_agent
- # the service have refreshed the redis queue before performing
- expect(round_robin_manage_service.send(:queue).sort.map(&:to_i)).to eq(inbox_members.map(&:user_id).sort)
- end
-
- context 'when allowed_member_ids is passed' do
- it 'will get the first allowed member and move it to the end of the queue' do
- expected_queue = [inbox_members[3].user_id, inbox_members[2].user_id, inbox_members[4].user_id, inbox_members[1].user_id,
- inbox_members[0].user_id].map(&:to_s)
- expect(described_class.new(inbox: inbox,
- allowed_member_ids: [inbox_members[3].user_id,
- inbox_members[2].user_id]).available_agent).to eq inbox_members[2].user
- expect(described_class.new(inbox: inbox,
- allowed_member_ids: [inbox_members[3].user_id,
- inbox_members[2].user_id]).available_agent).to eq inbox_members[3].user
- expect(round_robin_manage_service.send(:queue)).to eq(expected_queue)
- end
-
- it 'will get union of priority list and allowed_member_ids and move it to the end of the queue' do
- expected_queue = [inbox_members[3].user_id, inbox_members[4].user_id, inbox_members[2].user_id, inbox_members[1].user_id,
- inbox_members[0].user_id].map(&:to_s)
- # prority list will be ids in string, since thats what redis supplies to us
- expect(described_class.new(inbox: inbox,
- allowed_member_ids: [inbox_members[3].user_id,
- inbox_members[2].user_id])
- .available_agent(
- priority_list: [inbox_members[3].user_id.to_s]
- )).to eq inbox_members[3].user
- expect(round_robin_manage_service.send(:queue)).to eq(expected_queue)
- end
- end
- end
-end