def delete(self, request, pk, ext_loc_pk): application = get_application(pk) if not is_case_status_draft( application.status.status ) and application.status.status in get_case_statuses(read_only=True): return JsonResponse( data={ "error": f"Application status {application.status.status} is read-only." }, status=status.HTTP_400_BAD_REQUEST, ) if (not is_case_status_draft(application.status.status) and application.status.status != CaseStatusEnum.APPLICANT_EDITING): if ExternalLocationOnApplication.objects.filter( application=application).count() == 1: return JsonResponse( data={ "errors": { "external_locations": [ "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, ) removed_locations = ExternalLocationOnApplication.objects.filter( application=application, external_location__pk=ext_loc_pk) if removed_locations: audit_trail_service.create( actor=request.user, verb=AuditType.REMOVED_EXTERNAL_LOCATIONS_FROM_APPLICATION, target=application.get_case(), payload={ "locations": [ location.external_location.name + " " + location.external_location.country.name if location.external_location.country else location.external_location.name for location in removed_locations ] }, ) removed_locations.delete() return HttpResponse(status=status.HTTP_204_NO_CONTENT)
def create(self, *args, **kwargs): """ Create an audit entry for a model target: the target object (such as a case) actor: the object causing the audit entry (such as a user) send_notification: certain scenarios alert internal users, default is True ignore_case_status: draft cases become audited, default is False """ # TODO: decouple notifications and audit (signals?) from api.cases.models import Case target = kwargs.get("target") actor = kwargs.get("actor") send_notification = kwargs.pop("send_notification", True) ignore_case_status = kwargs.pop("ignore_case_status", False) if isinstance(target, Case): # Only audit cases if their status is not draft if not is_case_status_draft( target.status.status) or ignore_case_status: audit = super(AuditManager, self).create(*args, **kwargs) # Notify gov users when an exporter updates a case if isinstance(actor, ExporterUser) and send_notification: for gov_user in GovUser.objects.all(): gov_user.send_notification(content_object=audit, case=target) return audit return None return super(AuditManager, self).create(*args, **kwargs)
def _get_new_locations(self, application, user_organisation, location_ids, previous_locations, previous_location_ids): new_locations = [] if (is_case_status_draft(application.status.status) or application.status.status == CaseStatusEnum.APPLICANT_EDITING): new_locations = [ get_location(location_id, user_organisation) for location_id in location_ids if location_id not in previous_location_ids ] else: if has_previous_sites(application): return ( None, { "external_locations": [ "Go back and change your answer from ‘Change a site, or delete a good, third party or " "country’ to ’Change something else’." ] }, ) previous_location_countries = list( previous_locations.values_list( "external_location__country__id", flat=True)) for location_id in location_ids: new_location = get_location(location_id, user_organisation) if (new_location.country and (previous_location_countries and new_location.country.id not in previous_location_countries) or (str(new_location.id) not in previous_location_ids and new_location.location_type == LocationType.SEA_BASED)): return ( None, { "external_locations": [ "Go back and change your answer from ‘Change a site, or delete a good, " "third party or country’ to ’Change something else’." ] }, ) elif str(new_location.id) not in previous_location_ids: new_locations.append(new_location) return new_locations, None
def delete(self, request, pk): """ Deleting an application should only be allowed for draft applications """ application = get_application(pk) if not is_case_status_draft(application.status.status): return JsonResponse( data={ "errors": strings.Applications.Generic. DELETE_SUBMITTED_APPLICATION_ERROR }, status=status.HTTP_400_BAD_REQUEST, ) application.delete() return JsonResponse(data={ "status": strings.Applications.Generic.DELETE_DRAFT_APPLICATION }, status=status.HTTP_200_OK)
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)
def is_major_editable(self): return self.status.status == CaseStatusEnum.APPLICANT_EDITING or is_case_status_draft( self.status.status)