-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Endpoint that allows you to create, update and destroy a ticketer (#155)
* 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
1 parent
0905bfa
commit 0aea283
Showing
14 changed files
with
331 additions
and
18 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
Oops, something went wrong.