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

Remove open licence references #2345

Open
wants to merge 11 commits into
base: dev
Choose a base branch
from
14 changes: 5 additions & 9 deletions api/applications/creators.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django.db.models import Q

from api.applications.enums import ApplicationExportType, GoodsTypeCategory
from api.applications.enums import ApplicationExportType
from api.applications.models import (
ApplicationDocument,
GoodOnApplication,
Expand All @@ -21,7 +21,6 @@ def _validate_siel_locations(application, errors):
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 = (
Expand Down Expand Up @@ -175,13 +174,13 @@ def _validate_ultimate_end_users(draft, errors, is_mandatory):


def _validate_end_use_details(draft, errors, application_type):
if application_type in [CaseTypeSubTypeEnum.STANDARD, CaseTypeSubTypeEnum.OPEN]:
if application_type in [CaseTypeSubTypeEnum.STANDARD]:
if (
draft.is_military_end_use_controls is None
or draft.is_informed_wmd is None
or draft.is_suspected_wmd is None
or not draft.intended_end_use
) and not getattr(draft, "goodstype_category", None) == GoodsTypeCategory.CRYPTOGRAPHIC:
):
errors["end_use_details"] = [strings.Applications.Generic.NO_END_USE_DETAILS]

if application_type == CaseTypeSubTypeEnum.STANDARD:
Expand Down Expand Up @@ -217,7 +216,7 @@ def _validate_agree_to_declaration(request, errors):

def _validate_temporary_export_details(draft, errors):
if (
draft.case_type.sub_type in [CaseTypeSubTypeEnum.STANDARD, CaseTypeSubTypeEnum.OPEN]
draft.case_type.sub_type in [CaseTypeSubTypeEnum.STANDARD]
and draft.export_type == ApplicationExportType.TEMPORARY
):
if not draft.temp_export_details or draft.is_temp_direct_control is None or draft.proposed_return_date is None:
Expand Down Expand Up @@ -277,10 +276,7 @@ def _validate_standard_licence(draft, errors):


def _validate_route_of_goods(draft, errors):
if (
draft.is_shipped_waybill_or_lading is None
and not getattr(draft, "goodstype_category", None) == GoodsTypeCategory.CRYPTOGRAPHIC
):
if draft.is_shipped_waybill_or_lading is None:
errors["route_of_goods"] = [strings.Applications.Generic.NO_ROUTE_OF_GOODS]
return errors

Expand Down
26 changes: 0 additions & 26 deletions api/applications/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,32 +41,6 @@ class GoodsRecipients:
]


class GoodsTypeCategory:
MILITARY = "military"
CRYPTOGRAPHIC = "cryptographic"
MEDIA = "media"
UK_CONTINENTAL_SHELF = "uk_continental_shelf"
DEALER = "dealer"

choices = [
(MILITARY, "Military or dual use"),
(CRYPTOGRAPHIC, "Cryptographic"),
(MEDIA, "Media"),
(UK_CONTINENTAL_SHELF, "UK continental shelf"),
(DEALER, "Dealer"),
]

# For use in the serialiser
@classmethod
def get_text(cls, choice):
for key, value in cls.choices:
if key == choice:
return value

IMMUTABLE_GOODS = [CRYPTOGRAPHIC, MEDIA, DEALER]
IMMUTABLE_DESTINATIONS = [CRYPTOGRAPHIC, MEDIA, DEALER, UK_CONTINENTAL_SHELF]


class ApplicationExportLicenceOfficialType:
YES = "yes"
NO = "no"
Expand Down
3 changes: 0 additions & 3 deletions api/applications/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from api.applications.models import BaseApplication, GoodOnApplication
from api.applications.serializers.end_use_details import (
F680EndUseDetailsUpdateSerializer,
OpenEndUseDetailsUpdateSerializer,
StandardEndUseDetailsUpdateSerializer,
)
from api.applications.serializers.standard_application import (
Expand Down Expand Up @@ -67,8 +66,6 @@ def get_application_update_serializer(application: BaseApplication):
def get_application_end_use_details_update_serializer(application: BaseApplication):
if application.case_type.sub_type == CaseTypeSubTypeEnum.STANDARD:
return StandardEndUseDetailsUpdateSerializer
elif application.case_type.sub_type == CaseTypeSubTypeEnum.OPEN:
return OpenEndUseDetailsUpdateSerializer
elif application.case_type.sub_type == CaseTypeSubTypeEnum.F680:
return F680EndUseDetailsUpdateSerializer
else:
Expand Down
38 changes: 0 additions & 38 deletions api/applications/libraries/document_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
from api.applications.serializers.good import DocumentOnOrganisationSerializer
from api.audit_trail import service as audit_trail_service
from api.audit_trail.enums import AuditType
from api.goodstype.document.models import GoodsTypeDocument
from api.goodstype.document.serializers import GoodsTypeDocumentSerializer
from api.parties.enums import PartyDocumentType, PartyType
from api.parties.models import PartyDocument
from api.parties.serializers import PartyDocumentSerializer
Expand Down Expand Up @@ -142,39 +140,3 @@ def delete_party_document(party, application, user):
)

return HttpResponse(status=status.HTTP_204_NO_CONTENT)


def get_goods_type_document(goods_type):
if not goods_type:
return JsonResponse(data={"error": "No such goods type"}, status=status.HTTP_400_BAD_REQUEST)

documents = GoodsTypeDocument.objects.filter(goods_type=goods_type)
return _get_document(documents)


def upload_goods_type_document(goods_type, data):
if not goods_type:
return JsonResponse(data={"error": "No such goods type"}, status=status.HTTP_400_BAD_REQUEST)

documents = GoodsTypeDocument.objects.filter(goods_type=goods_type)
if documents.exists():
return JsonResponse(data={"error": "Document already exists"}, status=status.HTTP_400_BAD_REQUEST)

data["goods_type"] = goods_type.id
serializer = GoodsTypeDocumentSerializer(data=data)

if not serializer.is_valid():
return JsonResponse({"errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)

serializer.save()

return JsonResponse({"document": serializer.data}, status=status.HTTP_201_CREATED)


def delete_goods_type_document(goods_type):
documents = GoodsTypeDocument.objects.filter(goods_type=goods_type)
for document in documents:
document.delete_s3()
document.delete()

return HttpResponse(status=status.HTTP_204_NO_CONTENT)
6 changes: 1 addition & 5 deletions api/applications/libraries/goods_on_applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
from api.cases.enums import CaseTypeSubTypeEnum
from api.flags.enums import SystemFlags
from api.goods.enums import GoodStatus
from api.goodstype.models import GoodsType


def add_goods_flags_to_submitted_application(application: BaseApplication):
"""
When an application is submitted;
The 'not yet verified' system flag must be added to its Goods or GoodsTypes
The 'not yet verified' system flag must be added to its Goods
A Good's status must also be updated to 'SUBMITTED'
"""
if application.case_type.sub_type == CaseTypeSubTypeEnum.STANDARD:
Expand All @@ -17,9 +16,6 @@ def add_goods_flags_to_submitted_application(application: BaseApplication):
good_on_application.good.status = GoodStatus.SUBMITTED
good_on_application.good.save()
_add_good_not_yet_verified_system_flag_to_good(good_on_application.good)
elif application.case_type.sub_type == CaseTypeSubTypeEnum.OPEN:
for goods_type_on_application in GoodsType.objects.filter(application=application):
_add_good_not_yet_verified_system_flag_to_good(goods_type_on_application)


def _add_good_not_yet_verified_system_flag_to_good(good):
Expand Down
3 changes: 0 additions & 3 deletions api/applications/serializers/advice.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
from api.flags.enums import FlagStatuses
from api.goods.models import Good
from api.applications.models import GoodOnApplication
from api.goodstype.models import GoodsType
from api.gov_users.serializers import (
GovUserListSerializer,
GovUserSimpleSerializer,
Expand Down Expand Up @@ -59,7 +58,6 @@ class AdviceViewSerializer(serializers.Serializer):
team = TeamReadOnlySerializer()

good = GoodField()
goods_type = serializers.UUIDField(source="goods_type_id")
country = serializers.UUIDField(source="country_id")
end_user = serializers.UUIDField(source="end_user_id")
ultimate_end_user = serializers.UUIDField(source="ultimate_end_user_id")
Expand Down Expand Up @@ -111,7 +109,6 @@ class AdviceCreateSerializer(serializers.ModelSerializer):
)

good = GoodField(required=False)
goods_type = serializers.PrimaryKeyRelatedField(queryset=GoodsType.objects.all(), required=False)
country = serializers.PrimaryKeyRelatedField(queryset=Country.objects.all(), required=False)
end_user = serializers.PrimaryKeyRelatedField(
queryset=Party.objects.filter(type=PartyType.END_USER), required=False
Expand Down
38 changes: 0 additions & 38 deletions api/applications/serializers/end_use_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,44 +64,6 @@ def update(self, instance, validated_data):
return super().update(instance, validated_data)


class OpenEndUseDetailsUpdateSerializer(serializers.ModelSerializer):
military_end_use_controls_ref = serializers.CharField(
required=False, allow_blank=True, allow_null=True, max_length=225
)
informed_wmd_ref = serializers.CharField(required=False, allow_blank=True, allow_null=True, max_length=225)
suspected_wmd_ref = serializers.CharField(required=False, allow_blank=True, allow_null=True, max_length=2200)
intended_end_use = serializers.CharField(required=False, allow_blank=True, allow_null=True, max_length=2200)

class Meta:
model = BaseApplication
fields = (
"is_military_end_use_controls",
"military_end_use_controls_ref",
"is_informed_wmd",
"informed_wmd_ref",
"is_suspected_wmd",
"suspected_wmd_ref",
"intended_end_use",
)

def validate(self, data):
_validate_linked_fields(
data, "military_end_use_controls", strings.Generic.EndUseDetails.Error.INFORMED_TO_APPLY
)
_validate_linked_fields(data, "informed_wmd", strings.Generic.EndUseDetails.Error.INFORMED_WMD)
_validate_linked_fields(data, "suspected_wmd", strings.Generic.EndUseDetails.Error.SUSPECTED_WMD)
validate_field(data, "intended_end_use", strings.Generic.EndUseDetails.Error.INTENDED_END_USE)

return super().validate(data)

def update(self, instance, validated_data):
_update_reference_field(instance, "military_end_use_controls", validated_data)
_update_reference_field(instance, "informed_wmd", validated_data)
_update_reference_field(instance, "suspected_wmd", validated_data)

return super().update(instance, validated_data)


def _validate_linked_fields(data, linked_field, error):
linked_boolean_field_name = "is_" + linked_field
linked_boolean_field = validate_field(data, linked_boolean_field_name, error)
Expand Down
3 changes: 1 addition & 2 deletions api/applications/tests/test_copy_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ def _validate_reset_data(self):
def _validate_end_use_details(self, application_type=None):
if application_type == CaseTypeSubTypeEnum.F680:
self.assertIsNone(self.copied_application.intended_end_use)
elif application_type in [CaseTypeSubTypeEnum.STANDARD, CaseTypeSubTypeEnum.OPEN]:
elif application_type in [CaseTypeSubTypeEnum.STANDARD]:
self.assertIsNone(self.copied_application.intended_end_use)
self.assertIsNone(self.copied_application.is_informed_wmd)
self.assertIsNone(self.copied_application.is_suspected_wmd)
Expand Down Expand Up @@ -256,7 +256,6 @@ def _validate_third_party(self):
def _validate_case_data(self):
self.assertEqual(list(self.copied_application.case_ecju_query.all()), [])
self.assertEqual(list(self.copied_application.case_notes.all()), [])
self.assertEqual(list(self.copied_application.goodcountrydecision_set.all()), [])
self.assertEqual(list(self.copied_application.get_case().advice.all()), [])
self.assertEqual(list(self.copied_application.applicationdocument_set.all()), [])
self.assertEqual(list(self.copied_application.casedocument_set.all()), [])
Expand Down
24 changes: 0 additions & 24 deletions api/applications/tests/test_endpoints_response_applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,30 +48,6 @@ def test_application_goods(self):
self.url + self.get_standard_application()["id"] + "/goods/",
)

def test_applications_goodstype_list(self):
self.call_endpoint(
self.get_exporter_headers(),
self.url + self.get_open_application()["id"] + "/goodstypes/",
)

def test_applications_goodstype_detail(self):
application = self.get_open_application()
application_id = application["id"]
goods_type = self.get_application_goodstype_id()
url = f"{self.url}{application_id}/goodstype/{goods_type}"
exporter_user = self.get_exporter_headers()
self.call_endpoint(exporter_user, url)

def test_applications_goodstype_documents(self):
self.call_endpoint(
self.get_exporter_headers(),
self.url
+ self.get_open_application()["id"]
+ "/goodstype/"
+ self.get_application_goodstype_id()
+ "/document/",
)

def test_application_parties_list(self):
self.call_endpoint(
self.get_exporter_headers(),
Expand Down
6 changes: 0 additions & 6 deletions api/applications/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,6 @@
goods.ApplicationGoodOnApplicationUpdateSerialNumbers.as_view(),
name="good_on_application_update_serial_numbers",
),
# Goods types
path(
"<uuid:pk>/goodstype/<uuid:goods_type_pk>/document/",
documents.GoodsTypeDocumentView.as_view(),
name="goods_type_document",
),
# Parties
path("<uuid:pk>/parties/", parties.ApplicationPartyView.as_view(), name="parties"),
path("<uuid:pk>/parties/<uuid:party_pk>/", parties.ApplicationPartyView.as_view(), name="party"),
Expand Down
30 changes: 2 additions & 28 deletions api/applications/views/applications.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@
from api.flags.enums import FlagStatuses, SystemFlags
from api.goods.serializers import GoodCreateSerializer
from api.goods.models import FirearmGoodDetails
from api.goodstype.models import GoodsType
from api.licences.enums import LicenceStatus
from api.licences.helpers import get_licence_reference_code
from api.licences.models import Licence
Expand Down Expand Up @@ -316,7 +315,6 @@ def put(self, request, pk):

elif application.case_type.sub_type in [
CaseTypeSubTypeEnum.STANDARD,
CaseTypeSubTypeEnum.OPEN,
CaseTypeSubTypeEnum.F680,
CaseTypeSubTypeEnum.GIFTING,
CaseTypeSubTypeEnum.EXHIBITION,
Expand Down Expand Up @@ -354,13 +352,12 @@ def put(self, request, pk):

if application.case_type.sub_type in [
CaseTypeSubTypeEnum.STANDARD,
CaseTypeSubTypeEnum.OPEN,
CaseTypeSubTypeEnum.HMRC,
]:
if UUID(SystemFlags.ENFORCEMENT_CHECK_REQUIRED) not in application.flags.values_list("id", flat=True):
application.flags.add(SystemFlags.ENFORCEMENT_CHECK_REQUIRED)

if application.case_type.sub_type in [CaseTypeSubTypeEnum.STANDARD, CaseTypeSubTypeEnum.OPEN]:
if application.case_type.sub_type in [CaseTypeSubTypeEnum.STANDARD]:
auto_match_sanctions(application)

# Serialize for the response message
Expand Down Expand Up @@ -638,14 +635,10 @@ def post(self, request, pk):

# Create new foreign key connection using data from old application (this is for tables pointing to the case)
self.create_foreign_relations_for_new_application()
self.duplicate_goodstypes_for_new_application()

# Get all parties connected to the application and produce a copy (and replace reference for each one)
self.duplicate_parties_on_new_application()

# Remove usage & licenced quantity/ value
self.new_application.goods_type.update(usage=0)

# Save
self.new_application.created_at = now()
self.new_application.save()
Expand Down Expand Up @@ -743,32 +736,13 @@ def create_foreign_relations_for_new_application(self):
result.created_at = now()
result.save()

def duplicate_goodstypes_for_new_application(self):
"""
Creates a duplicate GoodsType and attaches it to the new application if applicable.
"""
# GoodsType has more logic than in "create_foreign_relations_for_new_application",
# such as listing the countries on the goodstype, and flags as such it is seperated.
for good in GoodsType.objects.filter(application_id=self.old_application_id).all():
old_good_countries = list(good.countries.all())
old_good_flags = list(good.flags.all())
old_good_control_list_entries = list(good.control_list_entries.all())
good.pk = None
good.id = None
good.application = self.new_application
good.created_at = now()
good.save()
good.countries.set(old_good_countries)
good.flags.set(old_good_flags)
good.control_list_entries.set(old_good_control_list_entries)


class ApplicationRouteOfGoods(UpdateAPIView):
authentication_classes = (ExporterAuthentication,)

@authorised_to_view_application(ExporterUser)
@application_is_major_editable
@allowed_application_types([CaseTypeSubTypeEnum.OPEN, CaseTypeSubTypeEnum.STANDARD])
@allowed_application_types([CaseTypeSubTypeEnum.STANDARD])
def put(self, request, pk):
"""Update an application instance with route of goods data."""

Expand Down
Loading
Loading