Skip to content
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

PROD Release #2329

Closed
wants to merge 35 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
09e4651
Add endpoint for goods descriptions
kevincarrogan Nov 25, 2024
f7082be
Add an assessments table
kevincarrogan Nov 11, 2024
cbc2fd1
Add bdd tests for goods ratings endpoint
saruniitr Nov 25, 2024
f16a45d
Merge branch 'dev' into LTD-5673-goods-ratings-endpoint
saruniitr Nov 26, 2024
4a0fe69
Merge branch 'dev' into LTD-5673-goods-ratings-endpoint
saruniitr Nov 26, 2024
e8492c8
Add footnotes table
kevincarrogan Nov 18, 2024
26ade23
Add bdd tests for footnotes endpoint
saruniitr Nov 27, 2024
288b355
Add unit viewset
kevincarrogan Nov 19, 2024
574744b
Add proper 404 for unfound unit
kevincarrogan Nov 19, 2024
923291e
Add bdd tests for units endpoint
saruniitr Nov 27, 2024
78f96e3
Order goods_rating table by the rating
saruniitr Nov 28, 2024
78f88f3
Merge branch 'dev' into LTD-5673-goods-ratings-endpoint
saruniitr Nov 28, 2024
fb4ef21
Add goods on licences endpoint initial commit
hnryjmes Nov 25, 2024
47924e0
Add table_name
hnryjmes Nov 25, 2024
2170459
Add test for issuing a licence
hnryjmes Nov 26, 2024
cb1c1e2
Add test for NLR goods not appearing in goods on licences table
hnryjmes Nov 28, 2024
807d0a0
Add test for draft licences and draft applications
hnryjmes Nov 28, 2024
415390d
Update units endpoint to return the response similar to other endpoints
saruniitr Nov 28, 2024
5d9e50e
Remove unused imports
saruniitr Nov 29, 2024
63c3b5a
Merge pull request #2307 from uktrade/LTD-5674_Productionise_goods_on…
hnryjmes Nov 29, 2024
666e139
Merge branch 'dev' into LTD-5673-goods-ratings-endpoint
saruniitr Nov 29, 2024
6a2824f
Merge pull request #2311 from uktrade/LTD-5673-goods-ratings-endpoint
saruniitr Nov 29, 2024
b59e46f
Merge branch 'dev' into LTD-5688-productionise-footnotes-endpoint
saruniitr Nov 29, 2024
3c0e805
Merge pull request #2318 from uktrade/LTD-5688-productionise-footnote…
saruniitr Nov 29, 2024
a76bd0c
Merge branch 'dev' into LTD-productionise-units-endpoint
saruniitr Nov 29, 2024
96f21b6
Merge pull request #2319 from uktrade/LTD-productionise-units-endpoint
saruniitr Nov 29, 2024
f80613b
Add denial reasons to licence decision
kevincarrogan Nov 25, 2024
d952e00
Stop passing through request to case model in finalise
kevincarrogan Nov 25, 2024
9b4a537
Remove merge migration
kevincarrogan Nov 28, 2024
a6e2788
Merge pull request #2308 from uktrade/LTD-5682-attach-refusal-reasons…
kevincarrogan Nov 29, 2024
18ec33a
Add licence refusal criteria endpoint
kevincarrogan Nov 25, 2024
b5224e1
fixup
kevincarrogan Dec 2, 2024
fabe60d
fixup
kevincarrogan Dec 2, 2024
8accc65
Merge pull request #2310 from uktrade/LTD-5680-productionise-licence-…
kevincarrogan Dec 3, 2024
7c297a4
Merge pull request #2326 from uktrade/dev
kevincarrogan Dec 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions api/cases/migrations/0073_licencedecision_denial_reasons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 4.2.16 on 2024-11-28 11:07

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("denial_reasons", "0006_populate_uuid_field"),
("cases", "0072_alter_decision_populate_issued_on_appeal"),
]

operations = [
migrations.AddField(
model_name="licencedecision",
name="denial_reasons",
field=models.ManyToManyField(to="denial_reasons.denialreason"),
),
]
24 changes: 18 additions & 6 deletions api/cases/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def no_licence_required(self):
notify_exporter_no_licence_required(self)

@transaction.atomic
def finalise(self, request, decisions):
def finalise(self, user, decisions, note):
from api.audit_trail import service as audit_trail_service
from api.cases.libraries.finalise import remove_flags_on_finalisation, remove_flags_from_audit_trail
from api.licences.models import Licence
Expand All @@ -361,7 +361,7 @@ def finalise(self, request, decisions):

if Licence.objects.filter(case=self).count() > 1:
audit_trail_service.create(
actor=request.user,
actor=user,
verb=AuditType.REINSTATED_APPLICATION,
target=self,
payload={
Expand All @@ -376,12 +376,12 @@ def finalise(self, request, decisions):
self.save()

audit_trail_service.create(
actor=request.user,
actor=user,
verb=AuditType.UPDATED_STATUS,
target=self,
payload={
"status": {"new": self.status.status, "old": old_status},
"additional_text": request.data.get("note"),
"additional_text": note,
},
)
logging.info("Case is now finalised")
Expand Down Expand Up @@ -410,16 +410,27 @@ def finalise(self, request, decisions):
if previous_licence_decision.decision == current_decision:
previous_decision = previous_licence_decision

LicenceDecision.objects.create(
licence_decision = LicenceDecision.objects.create(
case=self,
decision=current_decision,
licence=licence,
previous_decision=previous_decision,
)
if advice_type == AdviceType.REFUSE:
denial_reasons = (
self.advice.filter(
level=AdviceLevel.FINAL,
type=AdviceType.REFUSE,
)
.only("denial_reasons__id")
.distinct()
.values_list("denial_reasons__id", flat=True)
)
licence_decision.denial_reasons.set(denial_reasons)

licence_reference = licence.reference_code if licence and advice_type == AdviceType.APPROVE else ""
audit_trail_service.create(
actor=request.user,
actor=user,
verb=AuditType.CREATED_FINAL_RECOMMENDATION,
target=self,
payload={
Expand Down Expand Up @@ -846,6 +857,7 @@ class LicenceDecision(TimestampableModel):
licence = models.ForeignKey(
"licences.Licence", on_delete=models.DO_NOTHING, related_name="licence_decisions", null=True, blank=True
)
denial_reasons = models.ManyToManyField(DenialReason)
excluded_from_statistics_reason = models.TextField(default=None, blank=True, null=True)
previous_decision = models.ForeignKey(
"self", related_name="previous_decisions", default=None, null=True, on_delete=models.DO_NOTHING
Expand Down
23 changes: 19 additions & 4 deletions api/cases/tests/test_finalise_advice.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@
from api.audit_trail.enums import AuditType
from api.audit_trail.models import Audit
from api.audit_trail import service as audit_trail_service
from api.cases.enums import AdviceType, CaseTypeEnum, LicenceDecisionType
from api.cases.models import LicenceDecision
from api.cases.enums import (
AdviceLevel,
AdviceType,
CaseTypeEnum,
LicenceDecisionType,
)
from api.cases.tests.factories import FinalAdviceFactory
from api.cases.libraries.get_case import get_case
from api.cases.generated_documents.models import GeneratedCaseDocument
Expand Down Expand Up @@ -65,8 +69,19 @@ def test_refuse_standard_application_success(self, send_exporter_notifications_f
payload__decision=AdviceType.REFUSE,
).exists()
)
self.assertTrue(
LicenceDecision.objects.filter(case=self.application, decision=LicenceDecisionType.REFUSED).exists()

licence_decision = case.licence_decisions.get(decision=LicenceDecisionType.REFUSED)

advice = case.advice.get(
level=AdviceLevel.FINAL,
type=AdviceType.REFUSE,
)

self.assertTrue(licence_decision.denial_reasons.exists())

self.assertQuerySetEqual(
licence_decision.denial_reasons.all(),
advice.denial_reasons.all(),
)

@mock.patch("api.cases.notify.notify_exporter_licence_refused")
Expand Down
2 changes: 1 addition & 1 deletion api/cases/views/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@ def put(self, request, pk):
)

# finalises case, grants licence and publishes decision documents
licence_id = case.finalise(request, required_decisions)
licence_id = case.finalise(request.user, required_decisions, request.data.get("note"))

return JsonResponse({"case": pk, "licence": licence_id}, status=status.HTTP_201_CREATED)

Expand Down
44 changes: 44 additions & 0 deletions api/data_workspace/v2/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
)
from api.cases.enums import LicenceDecisionType
from api.cases.models import LicenceDecision
from api.licences.models import GoodOnLicence
from api.staticdata.control_list_entries.models import ControlListEntry
from api.staticdata.countries.models import Country
from api.staticdata.denial_reasons.models import DenialReason
from api.staticdata.report_summaries.models import ReportSummary


Expand Down Expand Up @@ -96,6 +99,15 @@ class Meta:
)


class GoodOnLicenceSerializer(serializers.ModelSerializer):
good_id = serializers.UUIDField()
licence_id = serializers.UUIDField()

class Meta:
model = GoodOnLicence
fields = ("good_id", "licence_id")


class ApplicationSerializer(serializers.ModelSerializer):
licence_type = serializers.CharField(source="case_type.reference")
status = serializers.CharField(source="status.status")
Expand Down Expand Up @@ -129,3 +141,35 @@ def get_first_closed_at(self, application) -> typing.Optional[datetime.datetime]
return application.baseapplication_ptr.case_ptr.closed_status_updates[0].created_at

return None


class UnitSerializer(serializers.Serializer):
code = serializers.CharField()
description = serializers.CharField()


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()

class Meta:
model = ControlListEntry
fields = (
"good_id",
"rating",
)


class LicenceRefusalCriteriaSerializer(serializers.ModelSerializer):
criteria = serializers.CharField(source="display_value")
licence_decision_id = serializers.UUIDField()

class Meta:
model = DenialReason
fields = ("criteria", "licence_decision_id")
Loading
Loading