Skip to content

Commit

Permalink
Endpoint that allows you to create, update and destroy a ticketer (#155)
Browse files Browse the repository at this point in the history
* feat: Endpoint that allows you to create, update and destroy a ticketer

* Add endpoint that allows managing ticketer queues (#159)

* feat: Add new model named TicketerQueue

* feat: Add endpoint that allows managing ticketer queues

* fix: Adjust Ticketer query to filter from sector uuid
  • Loading branch information
Sandro-Meireles authored Oct 7, 2022
1 parent 0905bfa commit 0aea283
Show file tree
Hide file tree
Showing 14 changed files with 331 additions and 18 deletions.
62 changes: 44 additions & 18 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ django-templates-macros = "^0.2"
django-csp = "^3.7"
pre-commit = "^2.20.0"
weni-protobuffers = "1.2.17"
drf-nested-routers = "^0.93.4"

[tool.poetry.dev-dependencies]
grpcio-tools = "^1.39.0"
Expand Down
27 changes: 27 additions & 0 deletions weni/internal/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 3.2.9 on 2022-09-23 18:58

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
('tickets', '0025_remove_ticket_subject'),
]

operations = [
migrations.CreateModel(
name='TicketerQueue',
fields=[
('topic', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='queue', serialize=False, to='tickets.topic')),
('ticketer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='queues', to='tickets.ticketer')),
],
options={
'db_table': 'internal_tickets_ticketerqueue',
},
bases=('tickets.topic',),
),
]
Empty file.
14 changes: 14 additions & 0 deletions weni/internal/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django.db import models

from temba.tickets.models import Ticketer, Topic


class TicketerQueue(Topic):
topic = models.OneToOneField(Topic, on_delete=models.CASCADE, parent_link=True, related_name="queue")
ticketer = models.ForeignKey(Ticketer, on_delete=models.CASCADE, related_name="queues")

class Meta:
db_table = "internal_tickets_ticketerqueue"

def __str__(self):
return f"Queue[uuid={self.uuid}, name={self.name}]"
Empty file added weni/internal/tests/__init__.py
Empty file.
36 changes: 36 additions & 0 deletions weni/internal/tests/test_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from uuid import uuid4

from temba.tests import TembaTest
from temba.tickets.models import Ticketer, Topic
from temba.tickets.types.rocketchat import RocketChatType
from weni.internal.models import TicketerQueue


class TicketerQueueTestCase(TembaTest):
def setUp(self):
self.fake_chats_uuid = uuid4()

super().setUp()
self.ticketer = Ticketer.create(self.org, self.user, RocketChatType.slug, "Email (bob@acme.com)", {})
self.queue = TicketerQueue.objects.create(
created_by=self.user,
modified_by=self.user,
org=self.org,
name="Fake Name",
uuid=self.fake_chats_uuid,
ticketer=self.ticketer,
)

def test_when_creating_queue_a_topic_is_created(self):
self.assertTrue(Topic.objects.filter(queue=self.queue).exists())

def test_if_topic_name_is_the_same_as_queue(self):
topic = Topic.objects.get(queue=self.queue)
self.assertEquals(topic.name, self.queue.name)

def test_changing_queue_name_also_changes_the_topic_name(self):
self.queue.name = "Fake Name 2"
self.queue.save()

topic = Topic.objects.get(queue=self.queue)
self.assertEquals(topic.name, self.queue.name)
Empty file.
42 changes: 42 additions & 0 deletions weni/internal/tickets/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from rest_framework import serializers
from django.contrib.auth import get_user_model

from temba.tickets.models import Ticketer
from weni import serializers as weni_serializers
from weni.internal.models import TicketerQueue


User = get_user_model()


class TicketerConfigSerializer(serializers.Serializer):
project_auth = serializers.CharField(required=True)
sector_uuid = serializers.CharField(required=True)


class TicketerSerializer(serializers.ModelSerializer):

org = weni_serializers.OrgUUIDRelatedField(required=True)
config = TicketerConfigSerializer(required=True)

class Meta:
model = Ticketer
fields = ("uuid", "org", "ticketer_type", "name", "config")
read_only_fields = ("uuid",)

def create(self, validated_data):
user = self.context["request"].user

validated_data["created_by"] = user
validated_data["modified_by"] = user

return super().create(validated_data)


class TicketerQueueSerializer(serializers.ModelSerializer):

uuid = serializers.UUIDField(required=True)

class Meta:
model = TicketerQueue
fields = ("uuid", "name")
Empty file.
100 changes: 100 additions & 0 deletions weni/internal/tickets/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import json
from uuid import uuid4

from django.urls import reverse
from django.db import transaction
from rest_framework.test import APIRequestFactory, force_authenticate
from rest_framework.permissions import AllowAny
from rest_framework import status

from temba.tests import TembaTest
from temba.tickets.models import Ticketer
from temba.tickets.types.rocketchat import RocketChatType
from weni.internal.tickets import views
from weni.internal.models import TicketerQueue


class TicketerQueueViewTestMixin(object):

action: dict

def setUp(self):
self.fake_chats_uuid = uuid4()
self.factory = APIRequestFactory()
self.view = views.TicketerQueueViewSet
self.view.permission_classes = [AllowAny]

super().setUp()

self.ticketer = Ticketer.create(self.org, self.user, RocketChatType.slug, "Email (bob@acme.com)", {})
self.queue = TicketerQueue.objects.create(
created_by=self.user,
modified_by=self.user,
org=self.org,
name="Fake Name",
uuid=self.fake_chats_uuid,
ticketer=self.ticketer,
)

def _get_response(self, request, **kwargs):
response = self.view.as_view(self.action)(request, **kwargs)
setattr(response, "json", json.loads(json.dumps(response.data)))
return response

def request(self, method: str, *args, data: dict = None, **kwargs):
request = getattr(self.factory, method)(*args, data=data)
force_authenticate(request, self.user)

return self._get_response(request, **kwargs)


class CreateTicketerQueueViewTestCase(TicketerQueueViewTestMixin, TembaTest):

action = dict(post="create")

def test_create_queue(self):
uuid = str(uuid4())
kwargs = dict(ticketer_uuid=str(self.ticketer.uuid))

url = reverse("ticketer-queues-list", kwargs=kwargs)
self.request("post", url, data={"uuid": uuid, "name": "123"}, **kwargs)
self.assertTrue(self.ticketer.queues.filter(uuid=uuid).exists())


class UpdateTicketerQueueViewTestCase(TicketerQueueViewTestMixin, TembaTest):

action = dict(patch="partial_update")

def test_update_queue(self):
kwargs = dict(ticketer_uuid=str(self.ticketer.uuid), uuid=str(self.queue.uuid))
url = reverse("ticketer-queues-detail", kwargs=kwargs)

old_name = self.queue.name
new_name = "Fake Name 2"

self.request("patch", url, data={"name": new_name}, **kwargs)
self.queue.refresh_from_db()

self.assertEqual(self.queue.name, new_name)
self.assertNotEqual(self.queue.name, old_name)


class DestroyTicketerQueueViewTestCase(TicketerQueueViewTestMixin, TembaTest):

action = dict(delete="destroy")

def test_destroy_queue(self):
kwargs = dict(ticketer_uuid=str(self.ticketer.uuid), uuid=str(self.queue.uuid))

url = reverse("ticketer-queues-detail", kwargs=kwargs)

response = self.request("delete", url, **kwargs)
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

def test_destroy_non_existing_queue(self):
kwargs = dict(ticketer_uuid=str(self.ticketer.uuid), uuid=str(uuid4()))

url = reverse("ticketer-queues-detail", kwargs=kwargs)

response = self.request("delete", url, **kwargs)
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
Loading

0 comments on commit 0aea283

Please sign in to comment.