Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/routing options #320

Merged
merged 5 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions chats/apps/projects/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ class Meta:
def __str__(self):
return self.name

@property
def routing_option(self):
"""
OPTIONS>
"general": will consider closed rooms on the day. e.g.: a agent has 3 open rooms and 1 closed,
the limit for the sector is 4, new rooms will go to other agents or stay in the queue.
None: Will only consider open rooms, does not matter when the room was created.
"""
try:
return self.config.get("routing_option", None)
except AttributeError:
return None

@property
def history_contacts_blocklist(self):
try:
Expand Down
36 changes: 29 additions & 7 deletions chats/apps/queues/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.contrib.auth import get_user_model
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from chats.core.models import BaseConfigurableModel, BaseModel, BaseSoftDeleteModel
Expand Down Expand Up @@ -64,17 +65,38 @@ def online_agents(self):

@property
def available_agents(self):
routing_option = self.project.routing_option
rooms_active_filter = models.Q(rooms__is_active=True)
rooms_sector_filter = models.Q(rooms__queue__sector=self.sector)

rooms_count_filter = models.Q(rooms_active_filter & rooms_sector_filter)
online_agents = self.online_agents.annotate(
active_rooms_count=models.Count(
"rooms",
filter=models.Q(
rooms__is_active=True, rooms__queue__sector=self.sector
),
filter=rooms_count_filter,
)
)
return online_agents.filter(active_rooms_count__lt=self.limit).order_by(
"active_rooms_count"
)
).filter(active_rooms_count__lt=self.limit)

if routing_option == "general":
rooms_day_closed_filter = models.Q(
rooms__ended_at__date__gte=timezone.now().date()
)
rooms_active_or_day_closed_filter = (
rooms_active_filter | rooms_day_closed_filter
)
rooms_sector_and_active_or_day_closed_filter = (
rooms_sector_filter & rooms_active_or_day_closed_filter
)

online_agents = online_agents.annotate(
active_and_day_closed_rooms=models.Count(
"rooms", filter=rooms_sector_and_active_or_day_closed_filter
)
)

return online_agents.order_by("active_and_day_closed_rooms")

return online_agents.order_by("active_rooms_count")

def is_agent(self, user):
return self.authorizations.filter(permission__user=user).exists()
Expand Down
53 changes: 52 additions & 1 deletion chats/apps/queues/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def setUp(self):
)


class QueueAvailableAgentsTestCase(QueueSetUpMixin, TestCase):
class QueueAvailableAgentsDefaultTestCase(QueueSetUpMixin, TestCase):
def test_available_agents_returns_online_agents(self):
self.agent_permission.status = "ONLINE"
self.agent_permission.save()
Expand Down Expand Up @@ -144,6 +144,57 @@ def tests_if_when_there_are_2_agents_it_returns_sorted_by_active_rooms_count(sel
self.assertEqual(self.agent_2, self.queue.available_agents.first())


class QueueAvailableAgentsGaneralTestCase(TestCase):
fixtures = ["chats/fixtures/fixture_app.json", "chats/fixtures/fixture_room.json"]

def setUp(self):
self.queue = Queue.objects.get(pk="f2519480-7e58-4fc4-9894-9ab1769e29cf")
self.project = Project.objects.get(pk="34a93b52-231e-11ed-861d-0242ac120002")
self.project.config = {"routing_option": "general"}
self.project.save()
self.sector = self.queue.sector
self.sector.rooms_limit = 4
self.sector.save()

def test_1_online_user_with_3_active_1_closed(self):
user = User.objects.get(email="[email protected]")
Room.objects.update(user=user)
Room.objects.first().close()
self.project.permissions.filter(user=user).update(status="ONLINE")

available_agents = self.queue.available_agents

self.assertEqual(available_agents.count(), 1)

def test_1_online_user_with_2_active_1_closed(self):
user = User.objects.get(email="[email protected]")
user.rooms.first().close()
self.project.permissions.filter(user=user).update(status="ONLINE")

available_agents = self.queue.available_agents

self.assertEqual(available_agents.count(), 1)
self.assertEqual(available_agents.first().active_and_day_closed_rooms, 3)
self.assertEqual(available_agents.first().active_rooms_count, 2)

def test_2_online_users_with_2_active_1_closed_second_agent_empty(self):
"""
Verify if the first in queue will be the agent with the least rooms
"""
user = User.objects.get(email="[email protected]")
user.rooms.first().close()
self.project.permissions.filter(user=user).update(status="ONLINE")
self.project.permissions.filter(user__email="[email protected]").update(
status="ONLINE"
)

available_agents = self.queue.available_agents

self.assertEqual(available_agents.count(), 2)
self.assertEqual(available_agents.first().active_rooms_count, 0)
self.assertEqual(available_agents.first().email, "[email protected]")


class PropertyTests(QueueSetUpMixin, APITestCase):
def test_name_property(self):
"""
Expand Down
74 changes: 74 additions & 0 deletions chats/fixtures/fixture_project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
[
{
"model": "projects.project",
"pk": "c599ecd2-8536-49f5-93f9-3c4fa09c22f9",
"fields": {
"created_on": "2022-08-24T19:22:15.781Z",
"modified_on": "2022-08-24T19:22:15.781Z",
"name": "General routing",
"timezone": "America/Sao_Paulo",
"date_format": "D",
"config": {
"routing_option": "general"
}
}
},
{
"model": "projects.projectpermission",
"pk": "6ea2e553-a7c1-428d-ab8e-45cbd99c309d",
"fields": {
"created_on": "2022-08-24T20:27:42.814Z",
"modified_on": "2022-08-24T20:27:42.815Z",
"project": "c599ecd2-8536-49f5-93f9-3c4fa09c22f9",
"user": "[email protected]",
"role": 1
}
},
{
"model": "projects.projectpermission",
"pk": "334549ea-3c8e-4a23-94cb-3cb0a28cbb28",
"fields": {
"created_on": "2022-08-24T20:25:54.375Z",
"modified_on": "2022-08-24T20:25:54.375Z",
"project": "c599ecd2-8536-49f5-93f9-3c4fa09c22f9",
"user": "[email protected]",
"role": 2
}
},
{
"model": "projects.projectpermission",
"pk": "e1d1cdb4-2a54-4bc8-8d63-6c680ffe589e",
"fields": {
"created_on": "2022-08-24T20:25:36.278Z",
"modified_on": "2022-08-24T20:25:36.278Z",
"project": "c599ecd2-8536-49f5-93f9-3c4fa09c22f9",
"user": "[email protected]",
"role": 2
}
},
{
"model": "sectors.sector",
"pk": "86792083-021d-4e89-b91f-b367d2948aa1",
"fields": {
"created_on": "2022-08-24T20:59:49.115Z",
"modified_on": "2022-08-24T20:59:49.115Z",
"name": "Limited sector",
"project": "c599ecd2-8536-49f5-93f9-3c4fa09c22f9",
"rooms_limit": 3,
"open_offline": false,
"work_start": "08:00:00",
"work_end": "17:00:00",
"is_deleted": false
}
},
{
"model": "queues.queue",
"pk": "30a237dd-bbff-42ea-ae4a-78675da12529",
"fields": {
"created_on": "2022-08-24T21:40:15.274Z",
"modified_on": "2022-08-24T21:40:15.274Z",
"sector": "86792083-021d-4e89-b91f-b367d2948aa1",
"name": "New routing queue"
}
}
]
Loading