Skip to content

Commit

Permalink
Merge pull request #826 from uktrade/LTD-1239-departments-endpoint
Browse files Browse the repository at this point in the history
Add Departments and DepartmentsSLA endpoints
  • Loading branch information
Manos authored Sep 30, 2021
2 parents 61403a2 + e7a8470 commit f6a8b99
Show file tree
Hide file tree
Showing 12 changed files with 121 additions and 24 deletions.
10 changes: 9 additions & 1 deletion api/cases/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,21 @@ class Meta:
db_table = "cases_case_queues"


class CaseAssignmentSla(models.Model):
class CaseAssignmentSLA(models.Model):
"""
Keeps track of days passed since case assigned to a team
"""

sla_days = models.IntegerField()
queue = models.ForeignKey(Queue, related_name="slas", on_delete=models.CASCADE)
case = models.ForeignKey(Case, related_name="slas", on_delete=models.CASCADE)


class DepartmentSLA(models.Model):
"""
Keeps track of days passed since application received in department
"""

sla_days = models.IntegerField()
department = models.ForeignKey(Department, on_delete=models.CASCADE, related_name="department_slas")
case = models.ForeignKey(Case, on_delete=models.CASCADE, related_name="department_slas")
Expand Down
6 changes: 3 additions & 3 deletions api/cases/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
Case,
CaseNote,
CaseAssignment,
CaseAssignmentSla,
CaseAssignmentSLA,
CaseDocument,
CaseQueue,
EcjuQuery,
Expand Down Expand Up @@ -81,9 +81,9 @@ class Meta:
)


class CaseAssignmentSlaSerializer(serializers.ModelSerializer):
class CaseAssignmentSLASerializer(serializers.ModelSerializer):
class Meta:
model = CaseAssignmentSla
model = CaseAssignmentSLA
fields = "__all__"


Expand Down
8 changes: 4 additions & 4 deletions api/cases/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from pytz import timezone as tz

from api.cases.enums import CaseTypeSubTypeEnum
from api.cases.models import Case, CaseAssignmentSla, CaseQueue, DepartmentSLA
from api.cases.models import Case, CaseAssignmentSLA, CaseQueue, DepartmentSLA
from api.cases.models import EcjuQuery
from api.common.dates import is_weekend, is_bank_holiday
from api.staticdata.statuses.enums import CaseStatusEnum
Expand Down Expand Up @@ -108,11 +108,11 @@ def update_cases_sla():
for assignment in CaseQueue.objects.filter(case__in=cases):
# Update team SLAs
try:
assignment_sla = CaseAssignmentSla.objects.get(queue=assignment.queue, case=assignment.case)
assignment_sla = CaseAssignmentSLA.objects.get(queue=assignment.queue, case=assignment.case)
assignment_sla.sla_days += 1
assignment_sla.save()
except CaseAssignmentSla.DoesNotExist:
CaseAssignmentSla.objects.create(queue=assignment.queue, case=assignment.case, sla_days=1)
except CaseAssignmentSLA.DoesNotExist:
CaseAssignmentSLA.objects.create(queue=assignment.queue, case=assignment.case, sla_days=1)
# Update department SLAs
department = assignment.queue.team.department
if department is not None:
Expand Down
12 changes: 11 additions & 1 deletion api/cases/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
CaseType,
EcjuQuery,
GoodCountryDecision,
DepartmentSLA,
)
from api.queues.tests.factories import QueueFactory
from api.organisations.tests.factories import OrganisationFactory
from api.goodstype.tests.factories import GoodsTypeFactory
from api.staticdata.countries.factories import CountryFactory
from api.teams.tests.factories import TeamFactory
from api.teams.tests.factories import TeamFactory, DepartmentFactory
from api.users.tests.factories import GovUserFactory


Expand Down Expand Up @@ -66,6 +67,15 @@ class Meta:
model = Case


class DepartmentSLAFactory(factory.django.DjangoModelFactory):
sla_days = factory.Faker("pyint", min_value=0, max_value=30)
case = factory.SubFactory(CaseFactory)
department = factory.SubFactory(DepartmentFactory)

class Meta:
model = DepartmentSLA


class CaseAssignmentFactory(factory.django.DjangoModelFactory):

case = factory.SubFactory(CaseFactory)
Expand Down
8 changes: 4 additions & 4 deletions api/cases/tests/test_sla.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
SLA_UPDATE_CUTOFF_TIME,
HMRC_QUERY_TARGET_DAYS,
)
from api.cases.models import CaseAssignmentSla, CaseQueue, DepartmentSLA
from api.cases.models import CaseAssignmentSLA, CaseQueue, DepartmentSLA
from api.staticdata.statuses.enums import CaseStatusEnum
from api.staticdata.statuses.libraries.get_case_status import get_case_status_by_status
from api.teams.models import Department
Expand Down Expand Up @@ -138,7 +138,7 @@ def test_sla_update_exhibition_mod(
case=application.case_ptr, queue=self.queue,
)
results = update_cases_sla.now()
sla = CaseAssignmentSla.objects.get()
sla = CaseAssignmentSLA.objects.get()
case.refresh_from_db()

self.assertEqual(sla.sla_days, 1)
Expand All @@ -163,7 +163,7 @@ def test_sla_update_F680_mod(
CaseQueue.objects.create(
queue=self.queue, case=application.case_ptr,
)
sla = CaseAssignmentSla.objects.create(sla_days=4, queue=self.queue, case=application.case_ptr,)
sla = CaseAssignmentSLA.objects.create(sla_days=4, queue=self.queue, case=application.case_ptr,)
results = update_cases_sla.now()

case.refresh_from_db()
Expand Down Expand Up @@ -574,7 +574,7 @@ def test_sla_not_update_for_terminal(
self.assertEqual(case.sla_remaining_days, STANDARD_APPLICATION_TARGET_DAYS - 1)


class DepartmentSlaTests(DataTestClient):
class DepartmentSLATests(DataTestClient):
@mock.patch("api.cases.tasks.is_weekend")
@mock.patch("api.cases.tasks.is_bank_holiday")
def test_department_sla_updated(
Expand Down
18 changes: 13 additions & 5 deletions api/data_workspace/case_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@
from rest_framework.pagination import LimitOffsetPagination

from api.core.authentication import DataWorkspaceOnlyAuthentication
from api.cases.models import CaseAssignment, CaseAssignmentSla, CaseType, CaseQueue, EcjuQuery
from api.cases.models import CaseAssignment, CaseAssignmentSLA, CaseType, CaseQueue, EcjuQuery, DepartmentSLA
from api.cases.serializers import (
CaseAssignmentSlaSerializer,
CaseAssignmentSLASerializer,
CaseTypeSerializer,
CaseQueueSerializer,
)
from api.data_workspace.serializers import (
EcjuQuerySerializer,
CaseAssignmentSerializer,
DepartmentSLASerializer,
)


Expand All @@ -21,11 +22,11 @@ class CaseAssignmentList(viewsets.ReadOnlyModelViewSet):
queryset = CaseAssignment.objects.all().order_by("id")


class CaseAssignmentSlaList(viewsets.ReadOnlyModelViewSet):
class CaseAssignmentSLAList(viewsets.ReadOnlyModelViewSet):
authentication_classes = (DataWorkspaceOnlyAuthentication,)
serializer_class = CaseAssignmentSlaSerializer
serializer_class = CaseAssignmentSLASerializer
pagination_class = LimitOffsetPagination
queryset = CaseAssignmentSla.objects.all()
queryset = CaseAssignmentSLA.objects.all()


class CaseTypeList(viewsets.ReadOnlyModelViewSet):
Expand All @@ -42,6 +43,13 @@ class CaseQueueList(viewsets.ReadOnlyModelViewSet):
queryset = CaseQueue.objects.all()


class CaseDepartmentList(viewsets.ReadOnlyModelViewSet):
authentication_classes = (DataWorkspaceOnlyAuthentication,)
serializer_class = DepartmentSLASerializer
pagination_class = LimitOffsetPagination
queryset = DepartmentSLA.objects.all()


class EcjuQueryList(viewsets.ReadOnlyModelViewSet):
authentication_classes = (DataWorkspaceOnlyAuthentication,)
serializer_class = EcjuQuerySerializer
Expand Down
15 changes: 14 additions & 1 deletion api/data_workspace/serializers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from api.audit_trail.models import Audit
from api.cases.models import CaseAssignment, EcjuQuery
from api.teams.models import Department
from api.cases.models import CaseAssignment, EcjuQuery, DepartmentSLA
from api.queues.models import Queue

from rest_framework import serializers
Expand All @@ -19,6 +20,18 @@ class Meta:
fields = "__all__"


class DepartmentSerializer(serializers.ModelSerializer):
class Meta:
model = Department
fields = "__all__"


class DepartmentSLASerializer(serializers.ModelSerializer):
class Meta:
model = DepartmentSLA
fields = "__all__"


class AuditMoveCaseSerializer(serializers.ModelSerializer):
"""Serializer for serializing 'move case' audit events."""

Expand Down
4 changes: 2 additions & 2 deletions api/data_workspace/tests/test_case_views.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.urls import reverse
from rest_framework import status

from api.cases.models import CaseAssignmentSla, CaseAssignment
from api.cases.models import CaseAssignmentSLA, CaseAssignment
from test_helpers.clients import DataTestClient
from test_helpers.assertions import is_uuid_as_string
from api.users.tests.factories import GovUserFactory
Expand All @@ -13,7 +13,7 @@ def setUp(self):
super().setUp()
self.case = self.create_standard_application_case(self.organisation, "Example Application")
self.queue.cases.add(self.case)
CaseAssignmentSla.objects.create(sla_days=4, queue=self.queue, case=self.case)
CaseAssignmentSLA.objects.create(sla_days=4, queue=self.queue, case=self.case)

# Create CaseAssignment
user = GovUserFactory(
Expand Down
35 changes: 35 additions & 0 deletions api/data_workspace/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

from api.parties.enums import PartyType
from test_helpers.clients import DataTestClient
from api.teams.tests.factories import TeamFactory
from api.cases.tests.factories import DepartmentSLAFactory
from api.teams.models import Department


class DataWorkspaceTests(DataTestClient):
Expand Down Expand Up @@ -103,3 +106,35 @@ def test_teams(self):
self.assertEqual(response.status_code, status.HTTP_200_OK)
options = response.json()["actions"]["OPTIONS"]
self.assertEqual(tuple(options.keys()), expected_fields)

def test_departments(self):
team = TeamFactory()
url = reverse("data_workspace:dw-departments-list")
response = self.client.get(url)
payload = response.json()

# Ensure we get departments and not sth else
deps_ids = [d["id"] for d in payload["results"]]
assert str(team.department.id) in deps_ids
assert not str(team.id) in deps_ids
assert len(deps_ids) == Department.objects.count()

# Ensure we get some expected fields
expected_fields = {"id", "name"}
assert set(payload["results"][0].keys()) == expected_fields

def test_case_department_slas(self):
department_sla = DepartmentSLAFactory()
url = reverse("data_workspace:dw-case-department-sla-list")
response = self.client.get(url)
payload = response.json()
last_result = payload["results"][-1]

# Ensure we get some expected fields
expected_fields = {"id", "sla_days", "department", "case"}
assert set(last_result.keys()) == expected_fields

# Ensure values are correct
assert last_result["sla_days"] == department_sla.sla_days
assert last_result["case"] == str(department_sla.case.id)
assert last_result["department"] == str(department_sla.department.id)
4 changes: 3 additions & 1 deletion api/data_workspace/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,12 @@
router_v1.register("parties", views.PartyListView, basename="dw-parties")
router_v1.register("queues", views.QueueListView, basename="dw-queues")
router_v1.register("teams", views.TeamListView, basename="dw-teams")
router_v1.register("departments", views.DepartmentListView, basename="dw-departments")
router_v1.register("case-assignment", case_views.CaseAssignmentList, basename="dw-case-assignment")
router_v1.register("case-assignment-slas", case_views.CaseAssignmentSlaList, basename="dw-case-assignment-sla")
router_v1.register("case-assignment-slas", case_views.CaseAssignmentSLAList, basename="dw-case-assignment-sla")
router_v1.register("case-types", case_views.CaseTypeList, basename="dw-case-type")
router_v1.register("case-queues", case_views.CaseQueueList, basename="dw-case-queue")
router_v1.register("case-department-slas", case_views.CaseDepartmentList, basename="dw-case-department-sla")
router_v1.register("ecju-queries", case_views.EcjuQueryList, basename="dw-ecju-query")
router_v1.register(
"external-data-denials", external_data_views.ExternalDataDenialView, basename="dw-external-data-denial"
Expand Down
10 changes: 9 additions & 1 deletion api/data_workspace/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
from api.parties.serializers import PartyViewSerializer
from api.queues.models import Queue
from api.queues.serializers import QueueListSerializer
from api.teams.models import Team
from api.teams.models import Team, Department
from api.teams.serializers import TeamReadOnlySerializer
from api.data_workspace.serializers import DepartmentSerializer


class OrganisationListView(viewsets.ReadOnlyModelViewSet):
Expand Down Expand Up @@ -38,3 +39,10 @@ class TeamListView(viewsets.ReadOnlyModelViewSet):
serializer_class = TeamReadOnlySerializer
pagination_class = LimitOffsetPagination
queryset = Team.objects.all()


class DepartmentListView(viewsets.ReadOnlyModelViewSet):
authentication_classes = (DataWorkspaceOnlyAuthentication,)
serializer_class = DepartmentSerializer
pagination_class = LimitOffsetPagination
queryset = Department.objects.all()
15 changes: 14 additions & 1 deletion api/teams/tests/factories.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
import factory
from api.teams.models import Team
from api.teams.models import Team, Department


class DepartmentFactory(factory.django.DjangoModelFactory):
name = factory.Iterator(["HMRC", "MOD", "BEIS", "DIT", "NCSC"])
# Commented out since probably we want to manually add this.
# team = factory.RelatedFactory(
# TeamFactory,
# factory_related_name='department',
# )

class Meta:
model = Department


class TeamFactory(factory.django.DjangoModelFactory):
name = factory.Faker("word")
department = factory.SubFactory(DepartmentFactory)

class Meta:
model = Team

0 comments on commit f6a8b99

Please sign in to comment.