diff --git a/chats/apps/api/v1/external/rooms/viewsets.py b/chats/apps/api/v1/external/rooms/viewsets.py index d52967b2..b60f6872 100644 --- a/chats/apps/api/v1/external/rooms/viewsets.py +++ b/chats/apps/api/v1/external/rooms/viewsets.py @@ -12,9 +12,13 @@ ) from chats.apps.api.v1.external.permissions import IsAdminPermission from chats.apps.api.v1.external.rooms.serializers import RoomFlowSerializer -from chats.apps.api.v1.internal.rest_clients.flows_rest_client import FlowRESTClient from chats.apps.dashboard.models import RoomMetrics from chats.apps.rooms.models import Room +from chats.apps.rooms.views import ( + get_editable_custom_fields_room, + update_custom_fields, + update_flows_custom_fields, +) def add_user_or_queue_to_room(instance, request): @@ -200,34 +204,27 @@ def partial_update(self, request, pk=None): return Response( {"Detail": "No contact id on the request"}, status.HTTP_400_BAD_REQUEST ) + elif not custom_fields_update: + return Response( + {"Detail": "No custom fields the request"}, status.HTTP_400_BAD_REQUEST + ) request_permission = self.request.auth project = request_permission.project - response = FlowRESTClient().create_contact( - project=project, data=data, contact_id=pk + room = get_editable_custom_fields_room( + { + "contact__external_id": pk, + "queue__sector__project": project, + "is_active": "True", + } + ) + update_flows_custom_fields( + project=room.queue.sector.project, + data=data, + contact_id=room.contact.external_id, ) - if response.status_code not in [status.HTTP_200_OK]: - return Response( - { - "Detail": f"[{response.status_code}]\n" - + f"Error updating custom fields on flows. Exception: {response.content}" - }, - status.HTTP_404_NOT_FOUND, - ) - - room = Room.objects.filter( - contact__external_id=pk, - queue__sector__project=project, - is_active=True, - ).update(custom_fields=custom_fields_update) - if not room: - return Response( - { - "Detail": "Contact with the given id was not found, it does not exist or it is deleted" - }, - status.HTTP_404_NOT_FOUND, - ) + update_custom_fields(room, custom_fields_update) return Response( {"Detail": "Custom Field edited with success"}, diff --git a/chats/apps/api/v1/rooms/serializers.py b/chats/apps/api/v1/rooms/serializers.py index 1066d62f..2e6476d6 100644 --- a/chats/apps/api/v1/rooms/serializers.py +++ b/chats/apps/api/v1/rooms/serializers.py @@ -32,6 +32,7 @@ class RoomSerializer(serializers.ModelSerializer): is_24h_valid = serializers.SerializerMethodField() flowstart_data = serializers.SerializerMethodField() last_interaction = serializers.DateTimeField(read_only=True) + can_edit_custom_fields = serializers.SerializerMethodField() class Meta: model = Room @@ -44,6 +45,7 @@ class Meta: "linked_user", "is_24h_valid", "last_interaction", + "can_edit_custom_fields", ] def get_is_24h_valid(self, room: Room) -> bool: @@ -80,6 +82,9 @@ def get_last_message(self, room: Room): ) return "" if last_message is None else last_message.text + def get_can_edit_custom_fields(self, room: Room): + return room.queue.sector.can_edit_custom_fields + class TransferRoomSerializer(serializers.ModelSerializer): user = UserSerializer(many=False, required=False, read_only=True) diff --git a/chats/apps/api/v1/rooms/viewsets.py b/chats/apps/api/v1/rooms/viewsets.py index 5889e196..4cd3b9a5 100644 --- a/chats/apps/api/v1/rooms/viewsets.py +++ b/chats/apps/api/v1/rooms/viewsets.py @@ -20,6 +20,11 @@ from chats.apps.dashboard.models import RoomMetrics from chats.apps.msgs.models import Message from chats.apps.rooms.models import Room +from chats.apps.rooms.views import ( + get_editable_custom_fields_room, + update_custom_fields, + update_flows_custom_fields, +) class RoomViewset( @@ -47,12 +52,6 @@ def get_permissions(self): permissions.IsAuthenticated, api_permissions.IsQueueAgent, ) - elif self.action == "list" and self.request.query_params.get("email"): - permission_classes = ( - permissions.IsAuthenticated, - api_permissions.AnySectorManagerPermission, - ) - return [permission() for permission in permission_classes] def get_queryset(self): @@ -214,16 +213,47 @@ def perform_update(self, serializer): msg.notify_room("create") if old_user is None and user: # queued > agent - instance.notify_queue("update", transferred_by=self.request.user.email) + instance.notify_queue("update") elif old_user is not None: - instance.notify_user( - "update", user=old_user, transferred_by=self.request.user.email - ) + instance.notify_user("update", user=old_user) if queue: # agent > queue - instance.notify_queue("update", transferred_by=self.request.user.email) + instance.notify_queue("update") else: # agent > agent - instance.notify_user("update", transferred_by=self.request.user.email) + instance.notify_user("update") def perform_destroy(self, instance): instance.notify_room("destroy", callback=True) super().perform_destroy(instance) + + @action( + detail=True, + methods=["PATCH"], + ) + def update_custom_fields(self, request, pk=None): + custom_fields_update = request.data + data = {"fields": custom_fields_update} + + if pk is None: + return Response( + {"Detail": "No room on the request"}, status.HTTP_400_BAD_REQUEST + ) + elif not custom_fields_update: + return Response( + {"Detail": "No custom fields on the request"}, + status.HTTP_400_BAD_REQUEST, + ) + + room = get_editable_custom_fields_room({"uuid": pk, "is_active": "True"}) + + update_flows_custom_fields( + project=room.queue.sector.project, + data=data, + contact_id=room.contact.external_id, + ) + + update_custom_fields(room, custom_fields_update) + + return Response( + {"Detail": "Custom Field edited with success"}, + status.HTTP_200_OK, + ) diff --git a/chats/apps/api/v1/sectors/serializers.py b/chats/apps/api/v1/sectors/serializers.py index bfd0ccc0..a1122baf 100644 --- a/chats/apps/api/v1/sectors/serializers.py +++ b/chats/apps/api/v1/sectors/serializers.py @@ -41,6 +41,7 @@ class Meta: "is_deleted", "can_trigger_flows", "sign_messages", + "can_edit_custom_fields", ] extra_kwargs = {field: {"required": False} for field in fields} @@ -78,6 +79,7 @@ class Meta: "rooms_limit", "can_trigger_flows", "sign_messages", + "can_edit_custom_fields", ] diff --git a/chats/apps/rooms/views.py b/chats/apps/rooms/views.py new file mode 100644 index 00000000..8c8902ce --- /dev/null +++ b/chats/apps/rooms/views.py @@ -0,0 +1,39 @@ +from rest_framework import status +from rest_framework.exceptions import APIException + +from chats.apps.api.v1.internal.rest_clients.flows_rest_client import FlowRESTClient +from chats.apps.rooms.models import Room + + +def update_custom_fields(room: Room, custom_fields_update: dict): + room.custom_fields.update(custom_fields_update) + room.save() + + +def update_flows_custom_fields(project, data, contact_id): + response = FlowRESTClient().create_contact( + project=project, + data=data, + contact_id=contact_id, + ) + if response.status_code not in [status.HTTP_200_OK]: + raise APIException( + { + "Detail": f"[{response.status_code}]\n" + + f"Error updating custom fields on flows. Exception: {response.content}" + }, + ) + + +def get_editable_custom_fields_room(room_filter: dict) -> Room: + try: + room = Room.objects.get(**room_filter) + except Room.DoesNotExist: + raise APIException(detail="Active room not found.") + + if not room.queue.sector.can_edit_custom_fields: + raise APIException( + detail="Access denied! You can't edit custom fields in this sector." + ) + + return room diff --git a/chats/apps/sectors/migrations/0008_sector_can_edit_custom_fields.py b/chats/apps/sectors/migrations/0008_sector_can_edit_custom_fields.py new file mode 100644 index 00000000..2e8e561d --- /dev/null +++ b/chats/apps/sectors/migrations/0008_sector_can_edit_custom_fields.py @@ -0,0 +1,20 @@ +# Generated by Django 4.1.2 on 2023-07-25 20:15 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("sectors", "0007_sector_sign_messages"), + ] + + operations = [ + migrations.AddField( + model_name="sector", + name="can_edit_custom_fields", + field=models.BooleanField( + default=False, verbose_name="Can edit custom fields?" + ), + ), + ] diff --git a/chats/apps/sectors/models.py b/chats/apps/sectors/models.py index 77de3f52..9be79ac5 100644 --- a/chats/apps/sectors/models.py +++ b/chats/apps/sectors/models.py @@ -35,6 +35,9 @@ class Sector(BaseSoftDeleteModel, BaseModel): open_offline = models.BooleanField( _("Open room when all agents are offline?"), default=True ) + can_edit_custom_fields = models.BooleanField( + _("Can edit custom fields?"), default=False + ) class Meta: verbose_name = _("Sector")