Skip to content

Commit

Permalink
Merge pull request #2318 from uktrade/LTD-5688-productionise-footnote…
Browse files Browse the repository at this point in the history
…s-endpoint

LTD-5688: Productionise footnotes endpoint
  • Loading branch information
saruniitr authored Nov 29, 2024
2 parents 6a2824f + b59e46f commit 3c0e805
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 20 deletions.
7 changes: 7 additions & 0 deletions api/data_workspace/v2/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,13 @@ def get_first_closed_at(self, application) -> typing.Optional[datetime.datetime]
return None


class FootnoteSerializer(serializers.Serializer):
footnote = serializers.CharField()
team_name = serializers.CharField(source="team__name")
application_id = serializers.CharField(source="case__pk")
type = serializers.CharField()


class AssessmentSerializer(serializers.ModelSerializer):
good_id = serializers.UUIDField()

Expand Down
36 changes: 36 additions & 0 deletions api/data_workspace/v2/tests/bdd/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,18 @@ def gov_user_permissions():
Permission.objects.get_or_create(id=permission.name, name=permission.value, type=UserType.INTERNAL.value)


@pytest.fixture()
def ogd_advisor(gov_user, gov_user_permissions):
gov_user.role = RoleFactory(name="OGD Advisor", type=UserType.INTERNAL)
gov_user.role.permissions.set(
[
GovPermissions.MAINTAIN_FOOTNOTES.name,
]
)
gov_user.save()
return gov_user


@pytest.fixture()
def lu_case_officer(gov_user, gov_user_permissions):
gov_user.role = RoleFactory(name="Case officer", type=UserType.INTERNAL)
Expand Down Expand Up @@ -170,6 +182,11 @@ def gov_headers(gov_user):
return {"HTTP_GOV_USER_TOKEN": user_to_token(gov_user.baseuser_ptr)}


@pytest.fixture()
def ogd_advisor_headers(ogd_advisor):
return {"HTTP_GOV_USER_TOKEN": user_to_token(ogd_advisor.baseuser_ptr)}


@pytest.fixture()
def lu_case_officer_headers(lu_case_officer):
return {"HTTP_GOV_USER_TOKEN": user_to_token(lu_case_officer.baseuser_ptr)}
Expand Down Expand Up @@ -453,6 +470,25 @@ def _parse_attributes(attributes):
return _parse_attributes


@given(
parsers.parse("a draft standard application with attributes:{attributes}"),
target_fixture="draft_standard_application",
)
def given_a_draft_standard_application_with_attributes(organisation, parse_attributes, attributes):
application = DraftStandardApplicationFactory(
organisation=organisation,
**parse_attributes(attributes),
)

PartyDocumentFactory(
party=application.end_user.party,
s3_key="party-document",
safe=True,
)

return application


@pytest.fixture()
def issue_licence(api_client, lu_case_officer, gov_headers, siel_template):
def _issue_licence(application):
Expand Down
33 changes: 33 additions & 0 deletions api/data_workspace/v2/tests/bdd/scenarios/footnotes.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@db
Feature: applications Table

Scenario: Draft application
Given a draft standard application
Then the `footnotes` table is empty

Scenario: Submit an application
Given a draft standard application
When the application is submitted
Then the `footnotes` table is empty

Scenario: Approving an application with footnotes
Given a draft standard application with attributes:
| name | value |
| id | 03fb08eb-1564-4b68-9336-3ca8906543f9 |
When the application is submitted
And a recommendation is added with footnotes:
| team | footnotes |
| FCDO | Commercial end user |
Then the `footnotes` table has the following rows:
| application_id | team_name | type | footnote |
| 03fb08eb-1564-4b68-9336-3ca8906543f9 | FCDO | approve | Commercial end user |

Scenario: Approving an application with no footnotes
Given a draft standard application with attributes:
| name | value |
| id | 03fb08eb-1564-4b68-9336-3ca8906543f9 |
When the application is submitted
And a recommendation is added with footnotes:
| team | footnotes |
| FCDO | |
Then the `footnotes` table is empty
19 changes: 0 additions & 19 deletions api/data_workspace/v2/tests/bdd/test_applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,25 +130,6 @@ def given_draft_standard_application(organisation):
return application


@given(
parsers.parse("a draft standard application with attributes:{attributes}"),
target_fixture="draft_standard_application",
)
def given_a_draft_standard_application_with_attributes(organisation, parse_attributes, attributes):
application = DraftStandardApplicationFactory(
organisation=organisation,
**parse_attributes(attributes),
)

PartyDocumentFactory(
party=application.end_user.party,
s3_key="party-document",
safe=True,
)

return application


@given(
parsers.parse("a draft temporary standard application with attributes:{attributes}"),
target_fixture="draft_standard_application",
Expand Down
61 changes: 61 additions & 0 deletions api/data_workspace/v2/tests/bdd/test_footnotes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import pytest

from pytest_bdd import (
parsers,
scenarios,
when,
)

from django.urls import reverse

from api.staticdata.statuses.enums import CaseStatusEnum
from api.teams.models import Team


scenarios("./scenarios/footnotes.feature")


@pytest.fixture()
def add_recommendation(
api_client,
ogd_advisor,
ogd_advisor_headers,
):
def _add_recommendation(application, footnotes_data):

url = reverse("caseworker_applications:change_status", kwargs={"pk": str(application.pk)})
response = api_client.post(url, data={"status": CaseStatusEnum.OGD_ADVICE}, **ogd_advisor_headers)
assert response.status_code == 200

ogd_advisor.team = Team.objects.get(name=footnotes_data[0]["team"])
ogd_advisor.save()

subjects = [("good_id", good_on_application.good.id) for good_on_application in application.goods.all()] + [
(poa.party.type, poa.party.id) for poa in application.parties.all()
]

data = [
{
"type": "approve",
"text": "Recommend issuing licence",
"proviso": "",
"footnote_required": True,
"footnote": footnotes_data[0]["footnotes"],
subject_name: str(subject_id),
"denial_reasons": [],
}
for subject_name, subject_id in subjects
]
url = reverse("cases:user_advice", kwargs={"pk": str(application.pk)})
response = api_client.post(url, data=data, **ogd_advisor_headers)
assert response.status_code == 201

return _add_recommendation


@when(parsers.parse("a recommendation is added with footnotes:{footnotes}"))
def when_a_recommendation_is_added_with_footnotes(
submitted_standard_application, add_recommendation, parse_table, footnotes
):
footnotes_data = [{"team": team, "footnotes": text} for team, text in parse_table(footnotes)[1:]]
add_recommendation(submitted_standard_application, footnotes_data)
1 change: 1 addition & 0 deletions api/data_workspace/v2/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@
router_v2.register(views.GoodDescriptionViewSet)
router_v2.register(views.GoodOnLicenceViewSet)
router_v2.register(views.ApplicationViewSet)
router_v2.register(views.FootnoteViewSet)
router_v2.register(views.AssessmentViewSet)
16 changes: 15 additions & 1 deletion api/data_workspace/v2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@
)
from api.audit_trail.enums import AuditType
from api.audit_trail.models import Audit
from api.cases.models import LicenceDecision
from api.cases.models import Advice, LicenceDecision
from api.core.authentication import DataWorkspaceOnlyAuthentication
from api.core.helpers import str_to_bool
from api.data_workspace.v2.serializers import (
ApplicationSerializer,
AssessmentSerializer,
CountrySerializer,
DestinationSerializer,
FootnoteSerializer,
GoodDescriptionSerializer,
GoodSerializer,
LicenceDecisionSerializer,
Expand Down Expand Up @@ -159,6 +160,19 @@ class DataWorkspace:
table_name = "applications"


class FootnoteViewSet(BaseViewSet):
serializer_class = FootnoteSerializer
queryset = (
Advice.objects.exclude(Q(footnote="") | Q(footnote__isnull=True))
.values("footnote", "team__name", "case__pk", "type")
.order_by("case__pk")
.distinct()
)

class DataWorkspace:
table_name = "footnotes"


class AssessmentViewSet(BaseViewSet):
serializer_class = AssessmentSerializer

Expand Down

0 comments on commit 3c0e805

Please sign in to comment.