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/refactor room list #266

Closed
wants to merge 7 commits into from
Closed
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
10 changes: 10 additions & 0 deletions chats/apps/api/v1/accounts/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,13 @@ class Meta:
"last_name",
"email",
]


class UserSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = [
"first_name",
"last_name",
"email",
]
4 changes: 2 additions & 2 deletions chats/apps/api/v1/contacts/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ class Meta:
fields = "__all__"


class ContactSimpleSerializer(ContactSerializer):
class ContactSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Contact
fields = [
"uuid",
"name",
"external_id",
"name",
]
5 changes: 2 additions & 3 deletions chats/apps/api/v1/external/msgs/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,14 @@ def create(self, validated_data):
if direction == "incoming":
validated_data["contact"] = room.contact

is_waiting = room.get_is_waiting()
was_24h_valid = room.is_24h_valid
was_24h_valid = room.validate_24h
msg = super().create(validated_data)
media_list = [MessageMedia(**media_data, message=msg) for media_data in medias]
medias = MessageMedia.objects.bulk_create(media_list)

if direction == "incoming":
validated_data["contact"] = room.contact
if is_waiting:
if room.is_waiting:
room.is_waiting = False
room.save()
room.notify_room("update")
Expand Down
9 changes: 7 additions & 2 deletions chats/apps/api/v1/projects/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,7 @@ def start_flow(self, request, *args, **kwargs):
{"Detail": "There already is an active flow start for this room"},
status.HTTP_400_BAD_REQUEST,
)

if not room.is_24h_valid:
if not room.validate_24h:
flow_start_data["room"] = room
room.request_callback(room.serialized_ws_data)
except (ObjectDoesNotExist, ValidationError):
Expand All @@ -293,8 +292,14 @@ def start_flow(self, request, *args, **kwargs):
chats_flow_start.name = flow_start.get("flow").get("name")
chats_flow_start.save()
feedback = {"name": chats_flow_start.name}

room.is_waiting = True
room.save()

if chats_flow_start.room:
create_room_feedback_message(room, feedback, method="fs")
room.is_waiting = True
room.save()
room.notify_room("update")
return Response(flow_start, status.HTTP_200_OK)

Expand Down
7 changes: 6 additions & 1 deletion chats/apps/api/v1/queues/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@


class QueueSerializer(serializers.ModelSerializer):

sector_name = serializers.CharField(source="sector.name", read_only=True)

class Meta:
Expand Down Expand Up @@ -99,3 +98,9 @@ class Meta:

def get_user(self, auth):
return UserSerializer(auth.permission.user).data


class QueueSimpleSerializer(serializers.ModelSerializer):
class Meta:
model = Queue
fields = ["uuid", "name"]
37 changes: 12 additions & 25 deletions chats/apps/api/v1/rooms/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
from rest_framework import serializers

from chats.apps.accounts.models import User
from chats.apps.api.v1.accounts.serializers import UserSerializer
from chats.apps.api.v1.contacts.serializers import ContactRelationsSerializer
from chats.apps.api.v1.queues.serializers import QueueSerializer
from chats.apps.api.v1.accounts.serializers import UserSerializer, UserSimpleSerializer
from chats.apps.api.v1.contacts.serializers import (
ContactRelationsSerializer,
ContactSimpleSerializer,
)
from chats.apps.api.v1.queues.serializers import QueueSerializer, QueueSimpleSerializer
from chats.apps.api.v1.sectors.serializers import DetailSectorTagSerializer
from chats.apps.queues.models import Queue
from chats.apps.rooms.models import Room
Expand All @@ -21,15 +24,14 @@ class RoomMessageStatusSerializer(serializers.Serializer):


class RoomSerializer(serializers.ModelSerializer):
user = UserSerializer(many=False, read_only=True)
contact = ContactRelationsSerializer(many=False, read_only=True)
queue = QueueSerializer(many=False, read_only=True)
user = UserSimpleSerializer(many=False, read_only=True)
contact = ContactSimpleSerializer(many=False, read_only=True)
queue = QueueSimpleSerializer(many=False, read_only=True)
tags = DetailSectorTagSerializer(many=True, read_only=True)
unread_msgs = serializers.SerializerMethodField()
unread_msgs = serializers.IntegerField(required=False, default=0)
linked_user = serializers.CharField(read_only=True)
is_24h_valid = serializers.BooleanField(default=True)
last_message = serializers.SerializerMethodField()
is_waiting = serializers.SerializerMethodField()
linked_user = serializers.SerializerMethodField()
is_24h_valid = serializers.SerializerMethodField()
flowstart_data = serializers.SerializerMethodField()
last_interaction = serializers.DateTimeField(read_only=True)
can_edit_custom_fields = serializers.SerializerMethodField()
Expand All @@ -48,9 +50,6 @@ class Meta:
"can_edit_custom_fields",
]

def get_is_24h_valid(self, room: Room) -> bool:
return room.is_24h_valid

def get_flowstart_data(self, room: Room) -> bool:
try:
flowstart = room.flowstarts.get(is_deleted=False)
Expand All @@ -62,18 +61,6 @@ def get_flowstart_data(self, room: Room) -> bool:
"created_on": flowstart.created_on,
}

def get_linked_user(self, room: Room):
try:
return room.contact.get_linked_user(room.queue.sector.project).full_name
except AttributeError:
return ""

def get_is_waiting(self, room: Room):
return room.get_is_waiting()

def get_unread_msgs(self, room: Room):
return room.messages.filter(seen=False).count()

def get_last_message(self, room: Room):
last_message = (
room.messages.order_by("-created_on")
Expand Down
50 changes: 48 additions & 2 deletions chats/apps/api/v1/rooms/viewsets.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
import json
from datetime import timedelta

from django.conf import settings
from django.db.models import Max
from django.db.models import (
BooleanField,
Case,
CharField,
Count,
F,
Max,
Q,
Value,
When,
)
from django.db.models.functions import Concat
from django.utils import timezone
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters, mixins, permissions, status
from rest_framework.decorators import action
from rest_framework.filters import OrderingFilter
from rest_framework.pagination import CursorPagination
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet

Expand Down Expand Up @@ -46,6 +61,8 @@ class RoomViewset(
search_fields = ["contact__name", "urn", "protocol"]
ordering_fields = "__all__"
ordering = ["user", "-last_interaction"]
pagination_class = CursorPagination
pagination_class.page_size_query_param = "limit"

def get_permissions(self):
permission_classes = [permissions.IsAuthenticated]
Expand All @@ -60,7 +77,36 @@ def get_queryset(self):
if self.action != "list":
self.filterset_class = None
qs = super().get_queryset()
return qs.annotate(last_interaction=Max("messages__created_on"))

last_24h = timezone.now() - timedelta(days=1)

qs = qs.annotate(
last_interaction=Max("messages__created_on"),
unread_msgs=Count("messages", filter=Q(messages__seen=False)),
linked_user=Concat(
"contact__linked_users__user__first_name",
Value(" "),
"contact__linked_users__user__last_name",
filter=Q(contact__linked_users__project=F("queue__sector__project")),
output_field=CharField(),
),
last_contact_interaction=Max(
"messages__created_on", filter=Q(messages__contact__isnull=False)
),
is_24h_valid=Case(
When(
Q(
urn__startswith="whatsapp",
last_contact_interaction__lt=last_24h,
),
then=False,
),
default=True,
output_field=BooleanField(),
),
)

return qs

def get_serializer_class(self):
if "update" in self.action:
Expand Down
2 changes: 1 addition & 1 deletion chats/apps/msgs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class Meta:
def save(self, *args, **kwargs) -> None:
if self.room.is_active is False:
raise ValidationError({"detail": _("Closed rooms cannot receive messages")})
if self.room.is_24h_valid is False and self.user is not None:
if self.room.validate_24h is False and self.user is not None:
raise ValidationError(
{
"detail": _(
Expand Down
2 changes: 1 addition & 1 deletion chats/apps/rooms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def trigger_default_message(self):
sent_message.notify_room("create", True)

@property
def is_24h_valid(self) -> bool:
def validate_24h(self) -> bool:
"""Validates is the last contact message was sent more than a day ago"""
if not self.urn.startswith("whatsapp"):
return True
Expand Down
4 changes: 2 additions & 2 deletions chats/apps/rooms/tests/test_viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,14 +113,14 @@ def _ok_list_rooms(self, token, rooms: list, data: dict):
response, results = self._request_list_rooms(token, data)
self.assertEqual(response.status_code, status.HTTP_200_OK)

self.assertEqual(response.json().get("count"), len(rooms))
self.assertEqual(len(response.json().get("results")), len(rooms))
for result in results:
self.assertIn(result.get("uuid"), rooms)

def _not_ok_list_rooms(self, token, data: dict):
response, _ = self._request_list_rooms(token, data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.json().get("count"), 0)
self.assertEqual(len(response.json().get("results")), 0)

def test_list_rooms_given_agents(self):
self._ok_list_rooms(
Expand Down
Loading