Skip to content

Commit

Permalink
Merge branch 'main' of github.com:weni-ai/chats-engine into feature/n…
Browse files Browse the repository at this point in the history
…ew-publisher-for-rooms
  • Loading branch information
ericosta-dev committed Jan 27, 2025
2 parents 7ebc992 + 9339a33 commit 1cb8582
Show file tree
Hide file tree
Showing 31 changed files with 1,896 additions and 372 deletions.
56 changes: 56 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,59 @@
# 3.13.7
## Add
- user info (email and name) to RoomInfoSerializer

# 3.13.6
## Add
- reintroduce created_on in MsgFlowSerializer

# 3.13.5
## Fix
- remove completely created_on from MsgFlowSerializer

# 3.13.4
## Fix
- remove created_on from MsgFlowSerializer's validate method

# 3.13.3
## Add
- new endpoint for rooms' user assignment information
- flows API call to update the ticket info about the user assignment
## Fix
- new messages from flows timestamps

# 3.13.2
## Add
- new endpoint to list human service rooms.
## Fix
- order by name in project permission endpoint
- passing project uuid to flows when deleting a queue.

# 3.13.1
## Add
- is_active field to ListRoomSerializer
## Fix
- new message timestamp

# 3.13.0
## Add
- ticket_uuid field in Room

# 3.12.1
## Fix
- check if room is active before returning redirection link

# 3.12.0
## Add
- chat redirect link to the room data returned via the rooms list internal endpoint

# 3.11.3
## Add
- last name to dashboard agent returned data

# 3.11.2
## Add
- ordering tags by name

# 3.11.1
## Add
- new filters in discussion
Expand Down
1 change: 1 addition & 0 deletions chats/apps/api/v1/dashboard/dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@dataclass
class Agent:
first_name: str = None
last_name: str = None
email: str = None
agent_status: str = None
closed_rooms: int = None
Expand Down
8 changes: 7 additions & 1 deletion chats/apps/api/v1/dashboard/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,19 @@ def get_agents_data(self, filters: Filters, project) -> List[Agent]:
opened_rooms=Count("rooms", filter=Q(**opened_rooms, **rooms_filter)),
)
.values(
"first_name", "email", "agent_status", "closed_rooms", "opened_rooms"
"first_name",
"last_name",
"email",
"agent_status",
"closed_rooms",
"opened_rooms",
)
)

user_agents = [
Agent(
first_name=user_agent["first_name"],
last_name=user_agent["last_name"],
email=user_agent["email"],
agent_status=user_agent["agent_status"],
closed_rooms=user_agent["closed_rooms"],
Expand Down
1 change: 1 addition & 0 deletions chats/apps/api/v1/dashboard/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def dashboard_general_data(context: dict, project):

class DashboardAgentsSerializer(serializers.Serializer):
first_name = serializers.CharField(allow_null=True, required=False)
last_name = serializers.CharField(allow_null=True, required=False)
email = serializers.EmailField(allow_null=True, required=False)
agent_status = serializers.CharField(allow_null=True, required=False)
closed_rooms = serializers.IntegerField(allow_null=True, required=False)
Expand Down
11 changes: 9 additions & 2 deletions chats/apps/api/v1/external/msgs/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class MsgFlowSerializer(serializers.ModelSerializer):
media = MessageMediaSerializer(required=False, many=True, read_only=True)
contact = ContactRelationsSerializer(many=False, required=False, read_only=True)
user = UserSerializer(many=False, required=False, read_only=True)
created_on = serializers.DateTimeField(required=False, allow_null=True)

class Meta:
model = Message
Expand All @@ -43,9 +44,9 @@ class Meta:
# Write
"room",
"text",
"created_on",
"direction",
"attachments",
"created_on",
# Read
"user",
"contact",
Expand All @@ -55,11 +56,17 @@ class Meta:
read_only_fields = [
"uuid",
"user",
"created_on",
"contact",
"media",
]

def validate(self, attrs: dict):
if "created_on" in attrs and attrs["created_on"] is None:
# defaults to current time and date
attrs.pop("created_on")

return super().validate(attrs)

def create(self, validated_data):
direction = validated_data.pop("direction")
medias = validated_data.pop("attachments")
Expand Down
2 changes: 2 additions & 0 deletions chats/apps/api/v1/external/rooms/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ class RoomFlowSerializer(serializers.ModelSerializer):
contact = ContactRelationsSerializer(many=False, required=False, read_only=False)
flow_uuid = serializers.CharField(required=False, write_only=True, allow_null=True)
is_anon = serializers.BooleanField(write_only=True, required=False, default=False)
ticket_uuid = serializers.UUIDField(required=False)

class Meta:
model = Room
Expand All @@ -144,6 +145,7 @@ class Meta:
"transfer_history",
# Writable Fields
"sector_uuid",
"ticket_uuid",
"queue_uuid",
"user_email",
"contact",
Expand Down
8 changes: 5 additions & 3 deletions chats/apps/api/v1/external/rooms/viewsets.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.db import IntegrityError
from django.db.models import Q
from django.utils import timezone
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters, status, viewsets
Expand Down Expand Up @@ -150,9 +151,9 @@ def partial_update(self, request, pk=None):
project = request_permission.project
room = (
Room.objects.filter(
callback_url__endswith=pk,
project_uuid=project,
is_active=True,
(Q(ticket_uuid=pk) | Q(callback_url__endswith=pk))
& Q(project_uuid=project)
& Q(is_active=True)
)
.select_related("user", "queue__sector__project")
.first()
Expand Down Expand Up @@ -205,6 +206,7 @@ def partial_update(self, request, pk=None):

room.notify_user("update", user=None)
room.notify_queue("update")
room.update_ticket()

create_room_feedback_message(room, feedback, method="rt")

Expand Down
29 changes: 28 additions & 1 deletion chats/apps/api/v1/internal/rest_clients/flows_rest_client.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import json
import logging
from typing import Callable

import requests
from django.conf import settings
from django.core.serializers.json import DjangoJSONEncoder
from rest_framework import status

from chats.apps.api.v1.internal.rest_clients.internal_authorization import (
InternalAuthentication,
)
from chats.core.requests import get_request_session_with_retries

LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -83,9 +86,10 @@ def update_queue(self, uuid: str, name: str, sector_uuid: str):
)
return response

def destroy_queue(self, uuid: str, sector_uuid: str):
def destroy_queue(self, uuid: str, sector_uuid: str, project_uuid: str):
response = requests.delete(
url=f"{self.base_url}/api/v2/internals/ticketers/{sector_uuid}/queues/{uuid}/",
json={"project_uuid": project_uuid},
headers=self.headers,
)

Expand Down Expand Up @@ -237,3 +241,26 @@ def start_flow(self, project, data):
headers=self.project_headers(project.flows_authorization),
)
return response.json()

def update_ticket_assignee(self, ticket_uuid: str, user_email: str):
url = f"{self.base_url}/api/v2/internals/ticket_assignee"

data = {
"uuid": ticket_uuid,
"email": user_email,
}

request_session = get_request_session_with_retries(
status_forcelist=[429, 500, 502, 503, 504], method_whitelist=["POST"]
)

request_session.post(
url,
data=json.dumps(
data,
sort_keys=True,
indent=1,
cls=DjangoJSONEncoder,
),
headers=self.headers,
)
12 changes: 12 additions & 0 deletions chats/apps/api/v1/internal/rooms/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class RoomInternalListSerializer(serializers.ModelSerializer):
tags = TagSimpleSerializer(many=True, required=False)
sector = serializers.CharField(source="queue.sector.name")
queue = serializers.CharField(source="queue.name")
link = serializers.SerializerMethodField()

class Meta:
model = Room
Expand All @@ -24,10 +25,21 @@ class Meta:
"queue",
"created_on",
"tags",
"link",
]

def get_agent(self, obj):
try:
return obj.user.full_name
except AttributeError:
return ""

def get_link(self, obj: Room) -> dict:
return {
"url": (
f"chats:dashboard/view-mode/{obj.user.email}/?room_uuid={obj.uuid}"
if obj.user and obj.is_active
else None
),
"type": "internal",
}
2 changes: 1 addition & 1 deletion chats/apps/api/v1/internal/sectors/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def perform_destroy(self, instance):


class SectorTagsViewset(viewsets.ModelViewSet):
queryset = SectorTag.objects.all()
queryset = SectorTag.objects.all().order_by("name")
serializer_class = SectorTagSerializer
permission_classes = [IsAuthenticated, ModuleHasPermission]
filter_backends = [DjangoFilterBackend]
Expand Down
13 changes: 10 additions & 3 deletions chats/apps/api/v1/projects/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -460,10 +460,17 @@ def partial_update(self, request, uuid=None):


class ProjectPermissionViewset(viewsets.ReadOnlyModelViewSet):
queryset = ProjectPermission.objects.all().annotate(
full_name=Concat(
"user__first_name", Value(" "), "user__last_name", output_field=CharField()
queryset = (
ProjectPermission.objects.all()
.annotate(
full_name=Concat(
"user__first_name",
Value(" "),
"user__last_name",
output_field=CharField(),
)
)
.order_by("full_name")
)
serializer_class = ProjectPermissionReadSerializer
permission_classes = []
Expand Down
1 change: 1 addition & 0 deletions chats/apps/api/v1/queues/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def perform_destroy(self, instance):
content = {
"uuid": str(instance.uuid),
"sector_uuid": str(instance.sector.uuid),
"project_uuid": str(instance.sector.project.uuid),
}

if not settings.USE_WENI_FLOWS:
Expand Down
37 changes: 37 additions & 0 deletions chats/apps/api/v1/rooms/serializers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from datetime import datetime
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from rest_framework import serializers

Expand Down Expand Up @@ -100,6 +101,7 @@ class ListRoomSerializer(serializers.ModelSerializer):

last_interaction = serializers.DateTimeField(read_only=True)
can_edit_custom_fields = serializers.SerializerMethodField()
is_active = serializers.BooleanField(default=True)

class Meta:
model = Room
Expand All @@ -119,6 +121,7 @@ class Meta:
"transfer_history",
"protocol",
"service_chat",
"is_active",
]

def get_user(self, room: Room):
Expand Down Expand Up @@ -231,3 +234,37 @@ def get_linked_user(self, room: Room):

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


class RoomInfoSerializer(serializers.ModelSerializer):
first_user_message_sent_at = serializers.SerializerMethodField()
user = serializers.SerializerMethodField()

class Meta:
model = Room
fields = [
"uuid",
"user",
"first_user_message_sent_at",
"user_assigned_at",
]

def get_user(self, room: Room) -> dict:
user: User = room.user

if not user:
return None

name = f"{user.first_name} {user.last_name}".strip()

return {"email": user.email, "name": name}

def get_first_user_message_sent_at(self, room: Room) -> datetime:
if (
first_user_message := room.messages.filter(user__isnull=False)
.order_by("created_on")
.first()
):
return first_user_message.created_on

return None
Loading

0 comments on commit 1cb8582

Please sign in to comment.