Skip to content

Commit

Permalink
Merge pull request #891 from uktrade/revert-885-LTD-1372-locations
Browse files Browse the repository at this point in the history
Revert "Backwards compatible SIEL location flow updates"
  • Loading branch information
alixedi authored Jan 6, 2022
2 parents 7f77b5d + 9f4f8a3 commit dd6f61e
Show file tree
Hide file tree
Showing 12 changed files with 44 additions and 203 deletions.
47 changes: 10 additions & 37 deletions api/applications/creators.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
GoodOnApplication,
SiteOnApplication,
ExternalLocationOnApplication,
StandardApplication,
)
from api.cases.enums import CaseTypeSubTypeEnum
from api.core.helpers import str_to_bool
Expand All @@ -33,27 +32,6 @@ def _validate_locations(application, errors):
return errors


def _validate_siel_locations(application, errors):
old_locations_invalid = (
not SiteOnApplication.objects.filter(application=application).exists()
and not ExternalLocationOnApplication.objects.filter(application=application).exists()
and not getattr(application, "have_goods_departed", False)
and not getattr(application, "goodstype_category", None) == GoodsTypeCategory.CRYPTOGRAPHIC
)

new_locations_invalid = (
not getattr(application, "export_type", False)
and not getattr(application, "goods_recipients", False)
and not getattr(application, "goods_starting_point", False)
and getattr(application, "is_shipped_waybill_or_lading") is None
)

if old_locations_invalid and new_locations_invalid:
errors["location"] = [strings.Applications.Generic.NO_LOCATION_SET]

return errors


def _get_document_errors(documents, processing_error, virus_error):
document_statuses = documents.values_list("safe", flat=True)

Expand Down Expand Up @@ -130,21 +108,16 @@ def _validate_end_user(draft, errors, is_mandatory, open_application=False):


def _validate_consignee(draft, errors, is_mandatory):
"""
Checks there is an consignee if goods_recipients is set to VIA_CONSIGNEE or VIA_CONSIGNEE_AND_THIRD_PARTIES
(with a document if is_document_mandatory)
"""
""" Checks there is an consignee (with a document if is_document_mandatory) """

# This logic includes old style applications where the goods_recipients field will be ""
if draft.goods_recipients != StandardApplication.DIRECT_TO_END_USER:
consignee_errors = check_party_error(
draft.consignee.party if draft.consignee else None,
object_not_found_error=strings.Applications.Standard.NO_CONSIGNEE_SET,
is_mandatory=is_mandatory,
is_document_mandatory=False,
)
if consignee_errors:
errors["consignee"] = [consignee_errors]
consignee_errors = check_party_error(
draft.consignee.party if draft.consignee else None,
object_not_found_error=strings.Applications.Standard.NO_CONSIGNEE_SET,
is_mandatory=is_mandatory,
is_document_mandatory=False,
)
if consignee_errors:
errors["consignee"] = [consignee_errors]

return errors

Expand Down Expand Up @@ -351,7 +324,7 @@ def _validate_exhibition_details(draft, errors):
def _validate_standard_licence(draft, errors):
""" Checks that a standard licence has all party types & goods """

errors = _validate_siel_locations(draft, errors)
errors = _validate_locations(draft, errors)
errors = _validate_end_user(draft, errors, is_mandatory=True)
errors = _validate_consignee(draft, errors, is_mandatory=True)
errors = _validate_third_parties(draft, errors, is_mandatory=False)
Expand Down
11 changes: 11 additions & 0 deletions api/applications/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from elasticsearch_dsl import Search, Q
from elasticsearch.exceptions import NotFoundError

from api.applications.enums import ApplicationExportType
from api.applications.models import BaseApplication, GoodOnApplication
from api.applications.serializers.end_use_details import (
F680EndUseDetailsUpdateSerializer,
Expand Down Expand Up @@ -40,6 +41,7 @@
StandardApplicationViewSerializer,
)
from api.applications.serializers.good import GoodOnStandardLicenceSerializer
from api.applications.serializers.temporary_export_details import TemporaryExportDetailsUpdateSerializer
from api.cases.enums import CaseTypeSubTypeEnum, CaseTypeEnum, AdviceType, AdviceLevel
from api.core.exceptions import BadRequestError
from api.documents.models import Document
Expand Down Expand Up @@ -128,6 +130,15 @@ def get_application_end_use_details_update_serializer(application: BaseApplicati
)


def get_temp_export_details_update_serializer(export_type):
if export_type == ApplicationExportType.TEMPORARY:
return TemporaryExportDetailsUpdateSerializer
else:
raise BadRequestError(
{f"get_temp_export_details_update_serializer does " f"not support this export type: {export_type}"}
)


def validate_and_create_goods_on_licence(application_id, licence_id, data):
errors = {}
good_on_applications = (
Expand Down
28 changes: 0 additions & 28 deletions api/applications/migrations/0050_auto_20211210_1618.py

This file was deleted.

20 changes: 1 addition & 19 deletions api/applications/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,23 +179,7 @@ class Meta:

# Licence Applications
class StandardApplication(BaseApplication):
GB = "GB"
NI = "NI"
GOODS_STARTING_POINT_CHOICES = [
(GB, "Great Britain"),
(NI, "Northern Ireland"),
]
DIRECT_TO_END_USER = "direct_to_end_user"
VIA_CONSIGNEE = "via_consignee"
VIA_CONSIGNEE_AND_THIRD_PARTIES = "via_consignee_and_third_parties"

GOODS_RECIPIENTS_CHOICES = [
(DIRECT_TO_END_USER, "Directly to the end-user"),
(VIA_CONSIGNEE, "To an end-user via a consignee"),
(VIA_CONSIGNEE_AND_THIRD_PARTIES, "To an end-user via a consignee, with additional third parties"),
]

export_type = models.TextField(choices=ApplicationExportType.choices, blank=True, default="")
export_type = models.CharField(choices=ApplicationExportType.choices, default=None, max_length=50)
reference_number_on_information_form = models.CharField(blank=True, null=True, max_length=255)
have_you_been_informed = models.CharField(
choices=ApplicationExportLicenceOfficialType.choices, blank=True, null=True, default=None, max_length=50,
Expand All @@ -213,8 +197,6 @@ class StandardApplication(BaseApplication):
trade_control_product_categories = SeparatedValuesField(
choices=TradeControlProductCategory.choices, blank=False, null=True, max_length=50
)
goods_recipients = models.TextField(choices=GOODS_RECIPIENTS_CHOICES, default="")
goods_starting_point = models.TextField(choices=GOODS_STARTING_POINT_CHOICES, default="")


class OpenApplication(BaseApplication):
Expand Down
14 changes: 3 additions & 11 deletions api/applications/serializers/standard_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ class StandardApplicationViewSerializer(PartiesSerializerMixin, GenericApplicati
trade_control_product_categories = serializers.SerializerMethodField()
sanction_matches = serializers.SerializerMethodField()
is_amended = serializers.SerializerMethodField()
goods_starting_point = serializers.CharField()
goods_recipients = serializers.CharField()

class Meta:
model = StandardApplication
Expand Down Expand Up @@ -77,8 +75,6 @@ class Meta:
"trade_control_product_categories",
"sanction_matches",
"is_amended",
"goods_starting_point",
"goods_recipients",
)
)

Expand Down Expand Up @@ -137,7 +133,9 @@ def get_is_amended(self, instance):


class StandardApplicationCreateSerializer(GenericApplicationCreateSerializer):
export_type = KeyValueChoiceField(choices=ApplicationExportType.choices, required=False)
export_type = KeyValueChoiceField(
choices=ApplicationExportType.choices, error_messages={"required": strings.Applications.Generic.NO_EXPORT_TYPE},
)
have_you_been_informed = KeyValueChoiceField(
choices=ApplicationExportLicenceOfficialType.choices, error_messages={"required": strings.Goods.INFORMED},
)
Expand Down Expand Up @@ -194,21 +192,15 @@ def create(self, validated_data):


class StandardApplicationUpdateSerializer(GenericApplicationUpdateSerializer):
export_type = KeyValueChoiceField(choices=ApplicationExportType.choices, required=False)
goods_starting_point = serializers.CharField()
goods_recipients = serializers.CharField()
reference_number_on_information_form = CharField(max_length=100, required=False, allow_blank=True, allow_null=True)

class Meta:
model = StandardApplication
fields = GenericApplicationUpdateSerializer.Meta.fields + (
"export_type",
"have_you_been_informed",
"reference_number_on_information_form",
"is_shipped_waybill_or_lading",
"non_waybill_or_lading_route_details",
"goods_starting_point",
"goods_recipients",
)

def __init__(self, *args, **kwargs):
Expand Down
23 changes: 2 additions & 21 deletions api/applications/tests/test_create_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,6 @@ def test_create_draft_standard_individual_export_application_successful(self):
self.assertEqual(response_data["id"], str(standard_application.id))
self.assertEqual(StandardApplication.objects.count(), 1)

def test_create_draft_standard_individual_export_application_empty_export_type_successful(self):
"""
Ensure we can create a new standard individual export application draft without the export_type field populated
"""
data = {
"name": "Test",
"application_type": CaseTypeReferenceEnum.SIEL,
"have_you_been_informed": ApplicationExportLicenceOfficialType.YES,
"reference_number_on_information_form": "123",
}

response = self.client.post(self.url, data, **self.exporter_headers)
response_data = response.json()
standard_application = StandardApplication.objects.get()

self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response_data["id"], str(standard_application.id))
self.assertEqual(StandardApplication.objects.count(), 1)

def test_create_draft_exhibition_clearance_application_successful(self):
"""
Ensure we can create a new Exhibition Clearance draft object
Expand All @@ -82,7 +63,7 @@ def test_create_draft_exhibition_clearance_application_successful(self):

def test_create_draft_gifting_clearance_application_successful(self):
"""
Ensure we can create a new Gifting Clearance draft object
Ensure we can create a new Exhibition Clearance draft object
"""
self.assertEqual(GiftingClearanceApplication.objects.count(), 0)

Expand All @@ -101,7 +82,7 @@ def test_create_draft_gifting_clearance_application_successful(self):

def test_create_draft_f680_clearance_application_successful(self):
"""
Ensure we can create a new F680 Clearance draft object
Ensure we can create a new Exhibition Clearance draft object
"""
self.assertEqual(F680ClearanceApplication.objects.count(), 0)

Expand Down
40 changes: 0 additions & 40 deletions api/applications/tests/test_edit_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,46 +38,6 @@ def test_edit_unsubmitted_application_name_success(self):
# Unsubmitted (draft) applications should not create audit entries when edited
self.assertEqual(Audit.objects.count(), 0)

def test_edit_unsubmitted_application_export_type_success(self):
""" Test edit the application export_type of an unsubmitted application. An unsubmitted application
has the 'draft' status.
"""
application = self.create_draft_standard_application(self.organisation)
# export_type is set to permanent in create_draft_standard_application

url = reverse("applications:application", kwargs={"pk": application.id})
updated_at = application.updated_at

response = self.client.put(url, {"export_type": "temporary"}, **self.exporter_headers)

application.refresh_from_db()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(application.export_type, "temporary")
self.assertGreater(application.updated_at, updated_at)
# Unsubmitted (draft) applications should not create audit entries when edited
self.assertEqual(Audit.objects.count(), 0)

def test_edit_unsubmitted_application_locations_success(self):
application = self.create_draft_standard_application(self.organisation)

url = reverse("applications:application", kwargs={"pk": application.id})
updated_at = application.updated_at

data = {
"goods_starting_point": "GB",
"goods_recipients": "via_consignee",
}

response = self.client.put(url, data, **self.exporter_headers)

application.refresh_from_db()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(application.goods_starting_point, "GB")
self.assertEqual(application.goods_recipients, "via_consignee")
self.assertGreater(application.updated_at, updated_at)
# Unsubmitted (draft) applications should not create audit entries when edited
self.assertEqual(Audit.objects.count(), 0)

@parameterized.expand(get_case_statuses(read_only=False))
def test_edit_application_name_in_editable_status_success(self, editable_status):
old_name = "Old Name"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def test_perform_action_on_non_temporary_export_type_standard_applications_failu
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(
response.json()["errors"],
{"temp_export_details": ["Cannot update temporary export details for a permanent export type"]},
["{'get_temp_export_details_update_serializer does not support this export type: permanent'}"],
)

def test_perform_action_on_non_open_or_standard_applications_failure(self):
Expand Down
38 changes: 7 additions & 31 deletions api/applications/tests/test_standard_application_submit.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from uuid import UUID

from api.applications.enums import ApplicationExportType
from api.applications.models import SiteOnApplication, GoodOnApplication, PartyOnApplication, StandardApplication
from api.applications.models import SiteOnApplication, GoodOnApplication, PartyOnApplication
from api.audit_trail.enums import AuditType
from api.audit_trail.models import Audit
from api.cases.enums import CaseTypeEnum, CaseDocumentState
Expand Down Expand Up @@ -60,35 +60,12 @@ def test_submit_standard_application_with_invalid_id_failure(self):

self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

def test_submit_standard_application_old_location_info_success(self):
SiteOnApplication(site=self.organisation.primary_site, application=self.draft).save()
def test_submit_standard_application_without_site_or_external_location_failure(self):
SiteOnApplication.objects.get(application=self.draft).delete()
url = reverse("applications:application_submit", kwargs={"pk": self.draft.id})

response = self.client.put(url, **self.exporter_headers)

self.assertEqual(response.status_code, status.HTTP_200_OK)

def test_submit_standard_application_with_new_location_info_success(self):
url = reverse("applications:application_submit", kwargs={"pk": self.draft.id})
SiteOnApplication.objects.filter(application_id=self.draft.id).delete()
self.draft.goods_recipients = StandardApplication.DIRECT_TO_END_USER
self.draft.goods_starting_point = StandardApplication.GB

response = self.client.put(url, **self.exporter_headers)

self.assertEqual(response.status_code, status.HTTP_200_OK)

def test_submit_standard_application_with_no_new_or_old_location_info_failure(self):
url = reverse("applications:application_submit", kwargs={"pk": self.draft.id})
SiteOnApplication.objects.filter(application_id=self.draft.id).delete()
self.draft.export_type = ""
self.draft.goods_recipients = ""
self.draft.goods_starting_point = ""
self.draft.is_shipped_waybill_or_lading = None
self.draft.save()

response = self.client.put(url, **self.exporter_headers)

self.assertContains(
response, text=strings.Applications.Generic.NO_LOCATION_SET, status_code=status.HTTP_400_BAD_REQUEST,
)
Expand Down Expand Up @@ -117,17 +94,16 @@ def test_submit_standard_application_without_end_user_document_failure(self):
status_code=status.HTTP_400_BAD_REQUEST,
)

def test_submit_standard_application_without_consignee_success(self):
# Consignee is optional if goods_recipients is DIRECT_TO_END_USER
def test_submit_standard_application_without_consignee_failure(self):
self.draft.delete_party(self.draft.consignee)
self.draft.goods_recipients = StandardApplication.DIRECT_TO_END_USER
self.draft.save()

url = reverse("applications:application_submit", kwargs={"pk": self.draft.id})

response = self.client.put(url, **self.exporter_headers)

self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertContains(
response, text=strings.Applications.Standard.NO_CONSIGNEE_SET, status_code=status.HTTP_400_BAD_REQUEST,
)

def test_submit_standard_application_without_consignee_document_success(self):
# Consignee document is optional
Expand Down
Loading

0 comments on commit dd6f61e

Please sign in to comment.