-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LTD: Add endpoint for licences list #2235
Draft
saruniitr
wants to merge
24
commits into
dev
Choose a base branch
from
LTD-stats-init
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
5d58f86
Add DRF csv renderer
kevincarrogan 684aac7
Add endpoint for licence statuses
kevincarrogan 6cb8532
Add endpoint for retrieving SIEL licences list
saruniitr f86d6f3
Address review comments
saruniitr d90ca37
Update url name and fix fixture
saruniitr 545f1cd
Add licence issue date to licences list
saruniitr e73df0f
Update Licences list view to excludes licences with no goods
saruniitr 95963ba
Only consider licences for finalised Cases
saruniitr 0ae5925
Ignore cancelled licences
saruniitr 2786805
Rename status to decision as that is what it is
saruniitr 673b60c
Add more common fixtures
saruniitr 7927d70
Seed letter layouts and templates
saruniitr 4553cb0
Update licence test to include steps for generating documents
saruniitr c0760ef
Use Case as base object the get licences list
saruniitr 060f962
Update licence list API view to be called licence decision
kevincarrogan c10f0e9
Allow pagination to be disabled for licence decisions
kevincarrogan 7b06322
Include refused cases in the extract
saruniitr 84c0b2f
Simplify query for getting cases with case documents
kevincarrogan 0600888
Determine issued and refused in queryset
kevincarrogan ce5f7ff
Condense down logic for finding decision made at
kevincarrogan 35f1450
Temporarily skip hawk authentication
kevincarrogan 91b3d21
Fix DW authentication
kevincarrogan df81a44
Add revoked as a licence decision
kevincarrogan 55c8493
Move into queryset
kevincarrogan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Large diffs are not rendered by default.
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
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,64 @@ | ||
from enum import Enum | ||
|
||
from rest_framework import serializers | ||
|
||
from api.audit_trail.enums import AuditType | ||
from api.audit_trail.models import Audit | ||
from api.cases.models import Case | ||
from api.licences.enums import LicenceStatus | ||
|
||
SIEL_TEMPLATE_ID = "d159b195-9256-4a00-9bc8-1eb2cebfa1d2" | ||
SIEL_REFUSAL_TEMPLATE_ID = "074d8a54-ee10-4dca-82ba-650460650342" | ||
|
||
|
||
class LicenceDecisionType(str, Enum): | ||
ISSUED = "issued" | ||
REFUSED = "refused" | ||
|
||
@classmethod | ||
def templates(cls): | ||
return { | ||
cls.ISSUED: SIEL_TEMPLATE_ID, | ||
cls.REFUSED: SIEL_REFUSAL_TEMPLATE_ID, | ||
} | ||
|
||
@classmethod | ||
def get_template(cls, decision): | ||
return cls.templates()[cls(decision)] | ||
|
||
|
||
class LicenceDecisionSerializer(serializers.ModelSerializer): | ||
decision = serializers.SerializerMethodField() | ||
decision_made_at = serializers.SerializerMethodField() | ||
|
||
class Meta: | ||
model = Case | ||
fields = ( | ||
"id", | ||
"reference_code", | ||
"decision", | ||
"decision_made_at", | ||
) | ||
|
||
def get_decision(self, case): | ||
return case.decision | ||
|
||
def get_decision_made_at(self, case): | ||
if case.decision in list(LicenceDecisionType): | ||
documents = case.casedocument_set.filter( | ||
generatedcasedocument__template_id=LicenceDecisionType.get_template(case.decision), | ||
safe=True, | ||
visible_to_exporter=True, | ||
) | ||
return documents.earliest("created_at").created_at | ||
|
||
if case.decision == "revoked": | ||
audits = Audit.objects.filter( | ||
target_object_id=case.pk, | ||
payload__status=LicenceStatus.REVOKED, | ||
verb=AuditType.LICENCE_UPDATED_STATUS, | ||
) | ||
|
||
return audits.earliest("created_at").created_at | ||
|
||
raise ValueError(f"Unknown decision type `{case.decision}`") |
Empty file.
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,95 @@ | ||
import json | ||
import pytest | ||
|
||
from rest_framework import status | ||
|
||
from api.cases.enums import CaseTypeEnum | ||
from api.cases.models import CaseType | ||
from api.core.constants import GovPermissions | ||
from api.letter_templates.models import LetterTemplate | ||
from api.staticdata.letter_layouts.models import LetterLayout | ||
from api.users.libraries.user_to_token import user_to_token | ||
from api.users.enums import SystemUser, UserType | ||
from api.users.models import BaseUser, Permission | ||
from api.users.tests.factories import BaseUserFactory, GovUserFactory, RoleFactory | ||
|
||
|
||
def load_json(filename): | ||
with open(filename) as f: | ||
return json.load(f) | ||
|
||
|
||
@pytest.fixture() | ||
def seed_layouts(): | ||
layouts = load_json("api/data_workspace/v2/tests/bdd/initial_data/letter_layouts.json") | ||
for layout in layouts: | ||
LetterLayout.objects.get_or_create(**layout) | ||
|
||
|
||
@pytest.fixture() | ||
def seed_templates(seed_layouts): | ||
templates = load_json("api/data_workspace/v2/tests/bdd/initial_data/letter_templates.json") | ||
for template in templates: | ||
template_instance, _ = LetterTemplate.objects.get_or_create(**template) | ||
template_instance.case_types.add(CaseType.objects.get(id=CaseTypeEnum.SIEL.id)) | ||
|
||
|
||
@pytest.fixture() | ||
def siel_template(seed_templates): | ||
return LetterTemplate.objects.get(layout_id="00000000-0000-0000-0000-000000000001") | ||
|
||
|
||
@pytest.fixture() | ||
def siel_refusal_template(seed_templates): | ||
return LetterTemplate.objects.get(layout_id="00000000-0000-0000-0000-000000000006") | ||
|
||
|
||
@pytest.fixture(autouse=True) | ||
def system_user(db): | ||
if BaseUser.objects.filter(id=SystemUser.id).exists(): | ||
return BaseUser.objects.get(id=SystemUser.id) | ||
else: | ||
return BaseUserFactory(id=SystemUser.id) | ||
|
||
|
||
@pytest.fixture() | ||
def gov_user(): | ||
return GovUserFactory() | ||
|
||
|
||
@pytest.fixture() | ||
def gov_user_permissions(): | ||
for permission in GovPermissions: | ||
Permission.objects.get_or_create(id=permission.name, name=permission.name, type=UserType.INTERNAL) | ||
|
||
|
||
@pytest.fixture() | ||
def lu_case_officer(gov_user, gov_user_permissions): | ||
gov_user.role = RoleFactory(name="Case officer", type=UserType.INTERNAL) | ||
gov_user.role.permissions.set( | ||
[GovPermissions.MANAGE_LICENCE_FINAL_ADVICE.name, GovPermissions.MANAGE_LICENCE_DURATION.name] | ||
) | ||
gov_user.save() | ||
return gov_user | ||
|
||
|
||
@pytest.fixture() | ||
def gov_headers(gov_user): | ||
return {"HTTP_GOV_USER_TOKEN": user_to_token(gov_user.baseuser_ptr)} | ||
|
||
|
||
@pytest.fixture() | ||
def unpage_data(client): | ||
def _unpage_data(url): | ||
unpaged_results = [] | ||
while True: | ||
response = client.get(url) | ||
assert response.status_code == status.HTTP_200_OK | ||
unpaged_results += response.data["results"] | ||
if not response.data["next"]: | ||
break | ||
url = response.data["next"] | ||
|
||
return unpaged_results | ||
|
||
return _unpage_data |
17 changes: 17 additions & 0 deletions
17
api/data_workspace/v2/tests/bdd/initial_data/letter_layouts.json
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,17 @@ | ||
[ | ||
{ | ||
"id": "00000000-0000-0000-0000-000000000001", | ||
"name": "SIEL", | ||
"filename": "siel" | ||
}, | ||
{ | ||
"id": "00000000-0000-0000-0000-000000000003", | ||
"name": "No Licence Required Letter", | ||
"filename": "nlr" | ||
}, | ||
{ | ||
"id": "00000000-0000-0000-0000-000000000006", | ||
"name": "Refusal Letter", | ||
"filename": "refusal" | ||
} | ||
] |
23 changes: 23 additions & 0 deletions
23
api/data_workspace/v2/tests/bdd/initial_data/letter_templates.json
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,23 @@ | ||
[ | ||
{ | ||
"id": "d159b195-9256-4a00-9bc8-1eb2cebfa1d2", | ||
"name": "SIEL template", | ||
"layout_id": "00000000-0000-0000-0000-000000000001", | ||
"visible_to_exporter": true, | ||
"include_digital_signature": true | ||
}, | ||
{ | ||
"id": "074d8a54-ee10-4dca-82ba-650460650342", | ||
"name": "Refusal letter template", | ||
"layout_id": "00000000-0000-0000-0000-000000000006", | ||
"visible_to_exporter": true, | ||
"include_digital_signature": true | ||
}, | ||
{ | ||
"id": "d71c3cfc-a127-46b6-96c0-a435cdd63cdb", | ||
"name": "No licence required letter template", | ||
"layout_id": "00000000-0000-0000-0000-000000000003", | ||
"visible_to_exporter": true, | ||
"include_digital_signature": true | ||
} | ||
] |
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,73 @@ | ||
import pytest | ||
|
||
from api.applications.tests.factories import GoodOnApplicationFactory, StandardApplicationFactory | ||
from api.cases.enums import AdviceType | ||
from api.cases.tests.factories import FinalAdviceFactory | ||
from api.goods.tests.factories import GoodFactory | ||
from api.licences.enums import LicenceStatus | ||
from api.licences.tests.factories import GoodOnLicenceFactory, StandardLicenceFactory | ||
from api.staticdata.statuses.enums import CaseStatusEnum | ||
from api.staticdata.statuses.models import CaseStatus | ||
from api.staticdata.units.enums import Units | ||
|
||
|
||
@pytest.fixture() | ||
def standard_draft_licence(): | ||
application = StandardApplicationFactory( | ||
status=CaseStatus.objects.get(status=CaseStatusEnum.FINALISED), | ||
) | ||
good = GoodFactory(organisation=application.organisation) | ||
good_on_application = GoodOnApplicationFactory( | ||
application=application, good=good, quantity=100.0, value=1500, unit=Units.NAR | ||
) | ||
licence = StandardLicenceFactory(case=application, status=LicenceStatus.DRAFT) | ||
GoodOnLicenceFactory( | ||
good=good_on_application, | ||
quantity=good_on_application.quantity, | ||
usage=0.0, | ||
value=good_on_application.value, | ||
licence=licence, | ||
) | ||
return licence | ||
|
||
|
||
@pytest.fixture() | ||
def standard_licence(): | ||
application = StandardApplicationFactory( | ||
status=CaseStatus.objects.get(status=CaseStatusEnum.FINALISED), | ||
) | ||
good = GoodFactory(organisation=application.organisation) | ||
good_on_application = GoodOnApplicationFactory( | ||
application=application, good=good, quantity=100.0, value=1500, unit=Units.NAR | ||
) | ||
licence = StandardLicenceFactory(case=application, status=LicenceStatus.DRAFT) | ||
GoodOnLicenceFactory( | ||
good=good_on_application, | ||
quantity=good_on_application.quantity, | ||
usage=0.0, | ||
value=good_on_application.value, | ||
licence=licence, | ||
) | ||
licence.status = LicenceStatus.ISSUED | ||
licence.save() | ||
return licence | ||
|
||
|
||
@pytest.fixture() | ||
def standard_case_with_final_advice(lu_case_officer): | ||
case = StandardApplicationFactory( | ||
status=CaseStatus.objects.get(status=CaseStatusEnum.UNDER_FINAL_REVIEW), | ||
) | ||
good = GoodFactory(organisation=case.organisation) | ||
good_on_application = GoodOnApplicationFactory( | ||
application=case, good=good, quantity=100.0, value=1500, unit=Units.NAR | ||
) | ||
FinalAdviceFactory(user=lu_case_officer, case=case, good=good_on_application.good) | ||
return case | ||
|
||
|
||
|
||
@pytest.fixture() | ||
def standard_case_with_refused_advice(lu_case_officer, standard_case_with_final_advice): | ||
standard_case_with_final_advice.advice.update(type=AdviceType.REFUSE) | ||
return standard_case_with_final_advice |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this works fine and looks great, although I am surprised there's not a way of doing this using the existing libraries we have