def put(self, request, pk): """ Edit the TAU details of a good. This includes military use, component and information security use. """ good = get_good(pk) data = request.data.copy() # return bad request if trying to edit software_or_technology details outside of category group 3 if good.item_category in ItemCategory.group_one and "software_or_technology_details" in data: raise BadRequestError( {"non_field_errors": [strings.Goods.CANNOT_SET_DETAILS_ERROR]}) # return bad request if trying to edit component and component details outside of category group 1 if good.item_category in ItemCategory.group_three and data.get( "is_component_step"): raise BadRequestError( {"non_field_errors": [strings.Goods.CANNOT_SET_DETAILS_ERROR]}) # return bad request if editing any of the firearm details on a good that is not in group 2 firearms if good.item_category not in ItemCategory.group_two and data.get( "firearm_details"): check_if_firearm_details_edited_on_unsupported_good(data) if good.status == GoodStatus.SUBMITTED: raise BadRequestError( {"non_field_errors": [strings.Goods.CANNOT_EDIT_GOOD]}) serializer = GoodCreateSerializer(instance=good, data=data, partial=True) return create_or_update_good(serializer, data.get("validate_only"), is_created=False)
def post(self, request, *args, **kwargs): """ Add a good to to an organisation. """ data = request.data data["organisation"] = get_request_user_organisation_id(request) data["status"] = GoodStatus.DRAFT if isinstance(data.get("control_list_entries"), str): data["control_list_entries"] = data["control_list_entries"].split( " ") item_category = data.get("item_category") if item_category: # return bad request if trying to edit software_or_technology details outside of category group 3 if (item_category in ItemCategory.group_one ) and data.get("software_or_technology_details"): raise BadRequestError({ "non_field_errors": [strings.Goods.CANNOT_SET_DETAILS_ERROR] }) # return bad request if adding any of the firearm details on a good that is not in group 2 firearms if data.get("firearm_details" ) and item_category not in ItemCategory.group_two: check_if_firearm_details_edited_on_unsupported_good(data) serializer = GoodCreateSerializer(data=data) return create_or_update_good(serializer, data.get("validate_only"), is_created=True)
def put(self, request, pk): application = get_application(pk) if application.goodstype_category in GoodsTypeCategory.IMMUTABLE_GOODS: raise BadRequestError( detail= "You cannot do this action for this type of open application") data = request.data serialized_data, errors = self.validate_data(data) if errors: return JsonResponse(data={"errors": errors}, status=status.HTTP_400_BAD_REQUEST) countries = data.get("countries") serialized_contract_types = serialized_data.get("contract_types") contract_types = [",".join(serialized_contract_types)] qs = CountryOnApplication.objects.filter(country__in=countries, application=application) qs.update(contract_types=contract_types, other_contract_type_text=serialized_data.get( "other_contract_type_text")) [ Flag.objects.get(name=ContractType.get_flag_name( contract_type)).countries_on_applications.set(qs) for contract_type in serialized_contract_types ] return JsonResponse(data={"countries_set": "success"}, status=status.HTTP_200_OK)
def delete(self, request, pk, goodstype_pk): """ Deletes a goodstype """ application = get_application(pk) if (hasattr(application, "goodstype_category") and application.goodstype_category in GoodsTypeCategory.IMMUTABLE_GOODS): raise BadRequestError( detail= "You cannot do this action for this type of open application") goods_type = get_goods_type(goodstype_pk) if application.case_type.sub_type == CaseTypeSubTypeEnum.HMRC: delete_goods_type_document_if_exists(goods_type) goods_type.delete() audit_trail_service.create( actor=request.user, verb=AuditType.REMOVE_GOOD_TYPE_FROM_APPLICATION, action_object=goods_type, target=Case.objects.get(id=application.id), payload={"good_type_name": goods_type.description}, ) return JsonResponse(data={}, status=status.HTTP_200_OK)
def post(self, request, pk): """ Post a goodstype """ application = get_application(pk) if (hasattr(application, "goodstype_category") and application.goodstype_category in GoodsTypeCategory.IMMUTABLE_GOODS): raise BadRequestError( detail= "You cannot do this action for this type of open application") request.data["application"] = application serializer = GoodsTypeSerializer(data=request.data) if serializer.is_valid(raise_exception=True): serializer.save() audit_trail_service.create( actor=request.user, verb=AuditType.ADD_GOOD_TYPE_TO_APPLICATION, action_object=serializer.instance, target=application.get_case(), payload={"good_type_name": serializer.instance.description}, ) return JsonResponse(data={"good": serializer.data}, status=status.HTTP_201_CREATED)
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 put(self, request, pk): application = get_application(pk) if application.goodstype_category in GoodsTypeCategory.IMMUTABLE_DESTINATIONS: raise BadRequestError( detail= "You cannot do this action for this type of open application") data = request.data for good, countries in data.items(): good = get_goods_type(good) # Validate that at least one country has been selected per good if not countries: return JsonResponse( {"errors": "Select at least one country for each good"}, status=status.HTTP_400_BAD_REQUEST) # Validate that the countries given are valid countries if not Country.objects.filter( pk__in=countries).count() == len(countries): return HttpResponse(status=status.HTTP_404_NOT_FOUND) initial_countries = list(good.countries.all()) good.countries.set(countries) removed_countries = [ country.name for country in initial_countries if country not in good.countries.all() ] added_countries = [ country.name for country in good.countries.all() if country not in initial_countries ] if removed_countries: audit_trail_service.create( actor=request.user, verb=AuditType.REMOVED_COUNTRIES_FROM_GOOD, action_object=good, target=Case.objects.get(id=application.id), payload={ "good_type_name": good.description, "countries": ", ".join(removed_countries), }, ) if added_countries: audit_trail_service.create( actor=request.user, verb=AuditType.ASSIGNED_COUNTRIES_TO_GOOD, action_object=good, target=Case.objects.get(id=application.id), payload={ "good_type_name": good.description, "countries": ", ".join(added_countries), }, ) return JsonResponse(data=data, status=status.HTTP_200_OK)
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: raise BadRequestError({ f"get_application_end_use_details_update_serializer does " f"not support this application type: {application.case_type.sub_type}" })
def check_if_firearm_details_edited_on_unsupported_good(data): """ Return bad request if editing any of the firearm details on a good that is not in group 2 firearms """ firearm_good_specific_details = [ "type", "year_of_manufacture", "calibre", "is_covered_by_firearm_act_section_one_two_or_five", "section_certificate_number", "section_certificate_date_of_expiry", "has_identification_markings", "identification_markings_details", "no_identification_markings_details", ] if any(detail in data["firearm_details"] for detail in firearm_good_specific_details): raise BadRequestError({"non_field_errors": [strings.Goods.CANNOT_SET_DETAILS_ERROR]})
def get_application_update_serializer(application: BaseApplication): if application.case_type.sub_type == CaseTypeSubTypeEnum.STANDARD: return StandardApplicationUpdateSerializer elif application.case_type.sub_type == CaseTypeSubTypeEnum.OPEN: return OpenApplicationUpdateSerializer elif application.case_type.sub_type == CaseTypeSubTypeEnum.HMRC: return HmrcQueryUpdateSerializer elif application.case_type.sub_type == CaseTypeSubTypeEnum.EXHIBITION: return ExhibitionClearanceUpdateSerializer elif application.case_type.sub_type == CaseTypeSubTypeEnum.GIFTING: return GiftingClearanceUpdateSerializer elif application.case_type.sub_type == CaseTypeSubTypeEnum.F680: return F680ClearanceUpdateSerializer else: raise BadRequestError({ f"get_application_update_serializer does " f"not support this application type: {application.case_type.sub_type}" })
def get_application_create_serializer(case_type): sub_type = CaseTypeEnum.reference_to_class(case_type).sub_type if sub_type == CaseTypeSubTypeEnum.STANDARD: return StandardApplicationCreateSerializer elif sub_type == CaseTypeSubTypeEnum.OPEN: return OpenApplicationCreateSerializer elif sub_type == CaseTypeSubTypeEnum.HMRC: return HmrcQueryCreateSerializer elif sub_type == CaseTypeSubTypeEnum.EXHIBITION: return ExhibitionClearanceCreateSerializer elif sub_type == CaseTypeSubTypeEnum.GIFTING: return GiftingClearanceCreateSerializer elif sub_type == CaseTypeSubTypeEnum.F680: return F680ClearanceCreateSerializer else: raise BadRequestError({ "application_type": [strings.Applications.Generic.SELECT_A_LICENCE_TYPE] })
def check_if_unsupported_fields_edited_on_firearm_good(data): """ Return bad request if trying to edit any details that are NOT applicable to category 2 firearm goods. This includes all military use/component/information security fields only relevant to category 1 along with the software or technology details for category 3 """ sections = [ "is_military_use", "modified_military_use_details", "is_component", "designed_details", "modified_details", "general_details", "uses_information_security", "information_security_details", "software_or_technology_details", ] # The parent field values don't get sent if not explicitly selected on the form, so we check the presence of details fields as well if any(section in data for section in sections): raise BadRequestError({"non_field_errors": [strings.Goods.CANNOT_SET_DETAILS_ERROR]})
def post(self, request, pk): """ Add countries to an open licence application. """ application = get_application(pk) if application.goodstype_category in GoodsTypeCategory.IMMUTABLE_DESTINATIONS: raise BadRequestError( detail= "You cannot do this action for this type of open application") data = request.data country_ids = data.get("countries") # Validate that there are countries if not country_ids: return JsonResponse( data={ "errors": { "countries": ["You have to pick at least one country"] } }, status=status.HTTP_400_BAD_REQUEST, ) if not is_case_status_draft( application.status.status ) and application.status.status in get_case_statuses(read_only=True): return JsonResponse( data={ "errors": { "external_locations": [ f"Application status {application.status.status} is read-only." ] } }, status=status.HTTP_400_BAD_REQUEST, ) else: previous_countries = CountryOnApplication.objects.filter( application=application) previous_country_ids = [ str(previous_country_id) for previous_country_id in previous_countries.values_list("country__id", flat=True) ] new_countries = [] if (is_case_status_draft(application.status.status) or application.status.status == CaseStatusEnum.APPLICANT_EDITING): new_countries = [ get_country(country_id) for country_id in country_ids if country_id not in previous_country_ids ] else: for country_id in country_ids: if previous_country_ids and country_id not in previous_country_ids: return JsonResponse( data={ "errors": { "countries": [ "Go back and change your answer from ‘Change a site, or delete " "a good, third party or country’ to ’Change something else’." ] } }, status=status.HTTP_400_BAD_REQUEST, ) # Get countries to be removed removed_country_ids = list( set(previous_country_ids) - set(country_ids)) removed_countries = previous_countries.filter( country__id__in=removed_country_ids) # Append new Countries to application (only in unsubmitted/applicant editing statuses) CountryOnApplication.objects.bulk_create([ CountryOnApplication(country=country, application=application) for country in new_countries ]) countries_data = CountrySerializer(new_countries, many=True).data case = Case.objects.get(id=application.id) if new_countries: audit_trail_service.create( actor=request.user, verb=AuditType.ADD_COUNTRIES_TO_APPLICATION, target=case, payload={ "countries": [country.name for country in new_countries] }, ) if removed_countries: audit_trail_service.create( actor=request.user, verb=AuditType.REMOVED_COUNTRIES_FROM_APPLICATION, target=case, payload={ "countries": [ country.country.name for country in removed_countries ] }, ) removed_countries.delete() return JsonResponse(data={"countries": countries_data}, status=status.HTTP_201_CREATED)