def get(self, request, pk): good = get_good(pk) if hasattr(request.user, "exporteruser"): if good.organisation.id != get_request_user_organisation_id( request): raise PermissionDenied() if str_to_bool(request.GET.get("full_detail")): serializer = GoodSerializerExporterFullDetail( good, context={ "exporter_user": request.user.exporteruser, "organisation_id": get_request_user_organisation_id(request), }, ) else: serializer = GoodSerializerExporter(good) # If there's a query with this good, update the notifications on it query = GoodsQuery.objects.filter(good=good) if query: delete_exporter_notifications( user=request.user.exporteruser, organisation_id=get_request_user_organisation_id(request), objects=query, ) else: serializer = GoodSerializerInternal(good) return JsonResponse(data={"good": serializer.data}, status=status.HTTP_200_OK)
def put(self, request, pk): """ Edit details of a good. This includes description, control codes and PV grading. """ good = get_good(pk) if good.organisation.id != get_request_user_organisation_id(request): raise PermissionDenied() if good.status == GoodStatus.SUBMITTED: return JsonResponse(data={ "errors": "This good is already on a submitted application" }, status=status.HTTP_400_BAD_REQUEST) data = request.data.copy() if data.get("is_good_controlled") is None or data.get( "is_pv_graded") == GoodPvGraded.GRADING_REQUIRED: for good_on_application in GoodOnApplication.objects.filter( good=good): good_on_application.delete() data["organisation"] = get_request_user_organisation_id(request) serializer = GoodCreateSerializer(instance=good, data=data, partial=True) return create_or_update_good(serializer, data.get("validate_only"), is_created=False)
def get_serializer_context(self): context = super().get_serializer_context() organisation_id = get_request_user_organisation_id(self.request) context["organisation_id"] = organisation_id return context
def delete(self, request, pk, doc_pk): """ Deletes good document """ good = get_good(pk) if good.organisation.id != get_request_user_organisation_id(request): raise PermissionDenied() if good.status != GoodStatus.DRAFT: return JsonResponse(data={ "errors": "This good is already on a submitted application" }, status=status.HTTP_400_BAD_REQUEST) good_document = Document.objects.get(id=doc_pk) document = get_good_document(good, good_document.id) document.delete_s3() good_document.delete() if GoodDocument.objects.filter(good=good).count() == 0: for good_on_application in GoodOnApplication.objects.filter( good=good): good_on_application.delete() return JsonResponse({"document": "deleted success"})
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 get_queryset(self): name = self.request.GET.get("name", "") description = self.request.GET.get("description", "") part_number = self.request.GET.get("part_number", "") control_list_entry = self.request.GET.get("control_list_entry") for_application = self.request.GET.get("for_application") organisation = get_request_user_organisation_id(self.request) queryset = Good.objects.filter( organisation_id=organisation, name__icontains=name, description__icontains=description, part_number__icontains=part_number, ) if control_list_entry: queryset = queryset.filter( control_list_entries__rating__icontains=control_list_entry ).distinct() if for_application: good_document_ids = GoodDocument.objects.filter( organisation__id=organisation).values_list("good", flat=True) queryset = queryset.filter( Q(id__in=good_document_ids) | Q(missing_document_reason__isnull=False)) queryset = queryset.prefetch_related("control_list_entries") return queryset.order_by("-updated_at")
def get_paginated_response(self, data): # Get the goods queries for the goods and format in a dict ids = [item["id"] for item in data] goods_queries = GoodsQuery.objects.filter(good_id__in=ids).values( "id", "good_id") goods_queries = { str(query["id"]): { "good_id": str(query["good_id"]) } for query in goods_queries } goods_query_notifications = (ExporterNotification.objects.filter( user_id=self.request.user.pk, organisation_id=get_request_user_organisation_id(self.request), case_id__in=goods_queries.keys(), ).values("case_id").annotate(count=Count("case_id"))) # Map goods_query_notifications to goods goods_notifications = {} for notification in goods_query_notifications: case_id = str(notification["case_id"]) good_id = goods_queries[case_id]["good_id"] goods_query_notification_count = notification["count"] goods_notifications[good_id] = goods_query_notification_count # Set notification counts on each good for item in data: item["exporter_user_notification_count"] = goods_notifications.get( item["id"], 0) return super().get_paginated_response(data)
class ExporterCaseDocumentDownload(APIView): authentication_classes = (ExporterAuthentication, ) def get(self, request, case_pk, document_pk): case = get_case(case_pk) if case.organisation.id != get_request_user_organisation_id(request): raise PermissionDenied()
def authenticate(self, request): """ When given an exporter user token and an HMRC organisation id, validate that the user belongs to the organisation and that they're allowed to access that organisation """ from api.organisations.libraries.get_organisation import get_request_user_organisation_id hawk_receiver = _authenticate(request, _lookup_credentials) if request.META.get(EXPORTER_USER_TOKEN_HEADER): exporter_user_token = request.META.get(EXPORTER_USER_TOKEN_HEADER) user_id = token_to_user_pk(exporter_user_token) organisation_id = get_request_user_organisation_id(request) else: raise PermissionDeniedError(MISSING_TOKEN_ERROR) try: exporter_user = ExporterUser.objects.get(pk=user_id) except ExporterUser.DoesNotExist: raise PermissionDeniedError(USER_NOT_FOUND_ERROR) if not Organisation.objects.filter( id=organisation_id, status=OrganisationStatus.ACTIVE, type=OrganisationType.HMRC).exists(): raise PermissionDeniedError(ORGANISATION_DEACTIVATED_ERROR) if not UserOrganisationRelationship.objects.filter( user_id=user_id, organisation_id=organisation_id, status=UserStatuses.ACTIVE).exists(): raise PermissionDeniedError(USER_DEACTIVATED_ERROR) return exporter_user.baseuser_ptr, hawk_receiver
def post(self, request): """ Create a new End User Advisory Enquiry query case instance """ data = JSONParser().parse(request) if not data.get("end_user"): data["end_user"] = {} organisation_id = get_request_user_organisation_id(request) data["organisation"] = organisation_id data["end_user"]["organisation"] = organisation_id data["end_user"]["type"] = PartyType.END_USER data["submitted_by"] = request.user serializer = EndUserAdvisoryViewSerializer(data=data) try: if serializer.is_valid(): if "validate_only" not in data or data["validate_only"] == "False": eua = serializer.save() audit_trail_service.create( actor=request.user, verb=AuditType.CREATED, action_object=eua.get_case(), payload={"status": {"new": eua.status.status}}, ) apply_flagging_rules_to_case(eua) return JsonResponse(data={"end_user_advisory": serializer.data}, status=status.HTTP_201_CREATED) else: return JsonResponse(data={}, status=status.HTTP_200_OK) return JsonResponse(data={"errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST) except serializers.ValidationError as e: return JsonResponse(data={"errors": e}, status=status.HTTP_400_BAD_REQUEST)
def post(self, request, pk): application = get_application(pk) sites = Site.objects.filter( organisation_id=get_request_user_organisation_id(request), id__in=request.data.get("sites", [])) add_sites_to_application(request.user, sites, application) return JsonResponse(data={"sites": {}}, status=status.HTTP_201_CREATED)
def get(self, request): """ Return list of all permissions """ permissions = request.user.exporteruser.get_role( get_request_user_organisation_id(request)).permissions.values() serializer = PermissionSerializer(permissions, many=True) return JsonResponse(data={"permissions": serializer.data})
def post(self, request, pk): """ Adds a document to the specified good """ good = get_good(pk) good_id = str(good.id) data = request.data if good.organisation.id != get_request_user_organisation_id(request): delete_documents_on_bad_request(data) raise PermissionDenied() if good.status != GoodStatus.DRAFT: delete_documents_on_bad_request(data) return JsonResponse(data={ "errors": "This good is already on a submitted application" }, status=status.HTTP_400_BAD_REQUEST) for document in data: document["good"] = good_id document["user"] = request.user.pk document["organisation"] = get_request_user_organisation_id( request) serializer = GoodDocumentCreateSerializer(data=data, many=True) if serializer.is_valid(): try: serializer.save() except Exception as e: # noqa return JsonResponse( {"errors": { "file": strings.Documents.UPLOAD_FAILURE }}, status=status.HTTP_400_BAD_REQUEST) # Delete missing document reason as a document has now been uploaded good.missing_document_reason = None good.save() return JsonResponse({"documents": serializer.data}, status=status.HTTP_201_CREATED) delete_documents_on_bad_request(data) return JsonResponse({"errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
def get_queryset(self): # Get params licence_type = self.request.GET.get("licence_type") reference = self.request.GET.get("reference") clc = self.request.GET.get("clc") country = self.request.GET.get("country") end_user = self.request.GET.get("end_user") active_only = self.request.GET.get("active_only") == "True" # OGL's are always hidden as we don't treat them as a licence # and they shouldn't be viewed from this endpoint licences = Licence.objects.filter( case__organisation_id=get_request_user_organisation_id( self.request), ).exclude( Q(case__case_type__id__in=CaseTypeEnum.OPEN_GENERAL_LICENCE_IDS) | Q(status=LicenceStatus.DRAFT)) # Apply filters if licence_type in [LicenceType.LICENCE, LicenceType.CLEARANCE]: licences = licences.filter( case__case_type__in=LicenceType.ids[licence_type]) if reference: licences = licences.filter( Q(case__baseapplication__name__icontains=reference) | Q(case__reference_code__icontains=reference)) if clc: licences = licences.filter( Q(case__baseapplication__goods__good__control_list_entries__rating =clc) | Q(case__baseapplication__goods_type__control_list_entries__rating =clc)).distinct() if country: licences = licences.filter( Q( case__baseapplication__parties__party__country_id=country, case__baseapplication__parties__party__type=PartyType. END_USER, ) | Q(case__id__in=CountryOnApplication.objects.filter( country_id=country).values_list("application", flat=True))) if end_user: licences = licences.filter( case__baseapplication__parties__party__name__icontains=end_user, case__baseapplication__parties__party__type=PartyType.END_USER, ) if active_only: licences = licences.exclude( case__status__in=self.non_active_states) return licences.order_by("created_at").reverse()
def has_object_permission(self, request, view, obj): if hasattr(request.user, "govuser"): return True elif hasattr(request.user, "exporteruser"): # assume exporters will only be retrieving casedocuments if not obj.casedocument.visible_to_exporter: return False return obj.casedocument.case.organisation_id == get_request_user_organisation_id( request) raise NotImplementedError()
def get_queryset(self): name = self.request.GET.get("name") queryset = EndUserAdvisoryQuery.objects.filter( organisation_id=get_request_user_organisation_id(self.request) ).select_related("end_user", "end_user__country") if name: queryset = queryset.filter(end_user__name__icontains=name) return queryset
def get(self, request, pk): good = get_good(pk) if hasattr(request.user, "exporteruser"): if good.organisation.id != get_request_user_organisation_id( request): raise PermissionDenied() else: serializer = TinyGoodDetailsSerializer(good) return JsonResponse(data={"good": serializer.data}, status=status.HTTP_200_OK)
def post(self, request, pk): data = request.data data["application"] = pk if "validate_only" in data and not isinstance(data["validate_only"], bool): return JsonResponse( data={"error": strings.Goods.VALIDATE_ONLY_ERROR}, status=status.HTTP_400_BAD_REQUEST, ) if "validate_only" in data and data["validate_only"] is True: # validate the value, quantity, and units relating to a good on an application. # note: Goods attached to applications also need documents. This is validated at a later stage. serializer = GoodOnApplicationCreateSerializer(data=data, partial=True) if serializer.is_valid(): return JsonResponse(status=status.HTTP_200_OK, data={}) else: if "good_id" not in data: return JsonResponse( data={"error": strings.Goods.GOOD_ID_ERROR}, status=status.HTTP_400_BAD_REQUEST, ) data["good"] = data["good_id"] good = get_good_with_organisation( data.get("good"), get_request_user_organisation_id(request)) if not good.missing_document_reason and GoodDocument.objects.filter( good=good).count() == 0: return JsonResponse( data={"error": strings.Goods.DOCUMENT_ERROR}, status=status.HTTP_400_BAD_REQUEST, ) serializer = GoodOnApplicationCreateSerializer(data=data) if serializer.is_valid(): serializer.save() audit_trail_service.create( actor=request.user, verb=AuditType.ADD_GOOD_TO_APPLICATION, action_object=good, target=Case.objects.get(id=pk), payload={"good_name": good.description}, ) return JsonResponse(data={"good": serializer.data}, status=status.HTTP_201_CREATED) return JsonResponse(data={"errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
def post(self, request): """ Create a new GoodsQuery case instance """ data = request.data good = get_good(data["good_id"]) data["organisation"] = get_request_user_organisation_id(request) is_clc_required = good.is_good_controlled is None is_pv_grading_required = good.is_pv_graded == GoodPvGraded.GRADING_REQUIRED errors = self._check_request_for_errors(good, is_clc_required, is_pv_grading_required) if errors: return JsonResponse(data={"errors": errors}, status=status.HTTP_400_BAD_REQUEST) good.status = GoodStatus.QUERY goods_query = GoodsQuery.objects.create( clc_control_list_entry=data.get("clc_control_list_entry"), clc_raised_reasons=data.get("clc_raised_reasons"), pv_grading_raised_reasons=data.get("pv_grading_raised_reasons"), good=good, organisation_id=data["organisation"], case_type_id=CaseTypeEnum.GOODS.id, status=get_starting_status(is_clc_required), submitted_at=django.utils.timezone.now(), submitted_by=request.user.exporteruser, ) # attach flags based on what's required if is_clc_required: flag = Flag.objects.get(id=SystemFlags.GOOD_CLC_QUERY_ID) goods_query.flags.add(flag) goods_query.clc_responded = False if is_pv_grading_required: flag = Flag.objects.get(id=SystemFlags.GOOD_PV_GRADING_QUERY_ID) goods_query.flags.add(flag) goods_query.pv_grading_responded = False good.save() goods_query.save() audit_trail_service.create( actor=request.user, verb=AuditType.CREATED, action_object=goods_query.get_case(), payload={"status": {"new": goods_query.status.status}}, ) apply_flagging_rules_to_case(goods_query) return JsonResponse(data={"id": goods_query.id}, status=status.HTTP_201_CREATED)
def get_compliance_site_case_notifications(data, request): """ returns the count of notification for a compliance site case and all visit cases under it. """ ids = [item["id"] for item in data] notifications = ( ExporterNotification.objects.filter( user_id=request.user.pk, organisation_id=get_request_user_organisation_id(request), case_id__in=ids ) .values("case") .annotate(count=Count("case")) ) cases_with_notifications = {str(notification["case"]): notification["count"] for notification in notifications} visit_notifications = list( ExporterNotification.objects.filter( user_id=request.user.pk, organisation_id=get_request_user_organisation_id(request), case__compliancevisitcase__site_case__id__in=ids, ) .values("case__compliancevisitcase__site_case_id") .annotate(count=Count("case__compliancevisitcase__site_case_id")) ) visit_cases_with_notifications = { str(notification["case__compliancevisitcase__site_case_id"]): notification["count"] for notification in visit_notifications } for item in data: if item["id"] in cases_with_notifications: item["exporter_user_notification_count"] = cases_with_notifications[item["id"]] else: item["exporter_user_notification_count"] = 0 if item["id"] in visit_cases_with_notifications: item["exporter_user_notification_count"] += visit_cases_with_notifications[item["id"]] return data
def get(self, request, pk): """ Gets all case notes. """ is_user_exporter = hasattr(request.user, "exporteruser") case_notes = get_case_notes_from_case(pk, only_show_notes_visible_to_exporter=is_user_exporter) if is_user_exporter: delete_exporter_notifications( user=request.user.exporteruser, organisation_id=get_request_user_organisation_id(request), objects=case_notes, ) serializer = self.serializer(case_notes, many=True) return JsonResponse(data={"case_notes": serializer.data})
def get_queryset(self): pk = self.kwargs["pk"] user = self.request.user if hasattr(user, "exporteruser"): documents = GeneratedCaseDocument.objects.filter(case_id=pk, visible_to_exporter=True) delete_exporter_notifications( user=user.exporteruser, organisation_id=get_request_user_organisation_id(self.request), objects=documents, ) else: documents = GeneratedCaseDocument.objects.filter(case_id=pk) return documents
def get(self, request, pk): """ View a single end user advisory's details """ end_user_advisory = get_end_user_advisory_by_pk(pk) case_id = end_user_advisory.id serializer = EndUserAdvisoryViewSerializer( end_user_advisory, context={ "exporter_user": request.user.exporteruser, "organisation_id": get_request_user_organisation_id(request), }, ) return JsonResponse(data={"end_user_advisory": serializer.data, "case_id": case_id}, status=status.HTTP_200_OK)
def put(self, request, pk): """ Update Exporter user """ user = get_user_by_pk(pk) data = request.data data["organisation"] = get_request_user_organisation_id(request) serializer = ExporterUserCreateUpdateSerializer(user, data=data, partial=True) if serializer.is_valid(): serializer.save() return JsonResponse(data={"user": serializer.data}, status=status.HTTP_200_OK) return JsonResponse(data={"errors": serializer.errors}, status=400)
def post(self, request): """ Create Exporter within the same organisation that current user is logged into """ data = request.data data["organisation"] = get_request_user_organisation_id(request) data["role"] = UUID(data["role"]) serializer = ExporterUserCreateUpdateSerializer(data=data) if serializer.is_valid(): serializer.save() return JsonResponse(data={"user": serializer.data}, status=status.HTTP_201_CREATED) return JsonResponse(data={"errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk): good = get_good(pk) if good.organisation.id != get_request_user_organisation_id(request): raise PermissionDenied() if good.status != GoodStatus.DRAFT: return JsonResponse( data={"errors": "Good is already on a submitted application"}, status=status.HTTP_400_BAD_REQUEST) for document in GoodDocument.objects.filter(good=good): document.delete_s3() good.delete() return JsonResponse(data={"status": "Good Deleted"}, status=status.HTTP_200_OK)
def get_case_notifications(data, request): ids = [item["id"] for item in data] notifications = ( ExporterNotification.objects.filter( user_id=request.user.pk, organisation_id=get_request_user_organisation_id(request), case__id__in=ids ) .values("case") .annotate(count=Count("case")) ) cases_with_notifications = {str(notification["case"]): notification["count"] for notification in notifications} for item in data: if item["id"] in cases_with_notifications: item["exporter_user_notification_count"] = cases_with_notifications[item["id"]] else: item["exporter_user_notification_count"] = 0 return data
def inner(request, *args, **kwargs): base_user = request.request.user user = base_user if hasattr(base_user, "govuser"): user = base_user.govuser elif hasattr(base_user, "exporteruser"): user = base_user.exporteruser if not isinstance(user, user_type): return JsonResponse( data={"errors": ["You are not authorised to perform this operation"]}, status=status.HTTP_403_FORBIDDEN, ) if user.type != UserType.INTERNAL and user.type != UserType.EXPORTER: return JsonResponse( data={"errors": ["You are not authorised to perform this operation"]}, status=status.HTTP_403_FORBIDDEN, ) if user.type == UserType.EXPORTER: pk = _get_application_id(request, kwargs) organisation_id = get_request_user_organisation_id(request.request) required_application_details = _get_application(request, kwargs).values( "case_type__sub_type", "organisation_id" )[0] if required_application_details["case_type__sub_type"] == CaseTypeSubTypeEnum.HMRC: has_access = HmrcQuery.objects.filter(pk=pk, hmrc_organisation=organisation_id).exists() else: has_access = required_application_details["organisation_id"] == organisation_id if not has_access: return JsonResponse( data={ "errors": [ "You can only perform this operation on an application " "that has been opened within your organisation" ] }, status=status.HTTP_403_FORBIDDEN, ) return func(request, *args, **kwargs)
def delete(self, request, obj_pk): good_on_application = self.get_object() application = good_on_application.application if application.status.status in get_case_statuses(read_only=True): return JsonResponse( data={"errors": [strings.Applications.Generic.READ_ONLY]}, status=status.HTTP_400_BAD_REQUEST, ) if good_on_application.application.organisation.id != get_request_user_organisation_id( request): return JsonResponse( data={ "errors": strings.Applications.Generic.INVALID_ORGANISATION }, status=status.HTTP_403_FORBIDDEN, ) if (good_on_application.good.status == GoodStatus.SUBMITTED and GoodOnApplication.objects.filter( good=good_on_application.good).count() == 1): good_on_application.good.status = GoodStatus.DRAFT good_on_application.good.save() good_on_application.delete() # if the application no longer has goods with firearm details, remove the flag if (not application.goods.filter( good__firearm_details__isnull=False).exists() and application.flags.filter(id=SystemFlags.FIREARMS_ID).exists()): application.flags.remove(SystemFlags.FIREARMS_ID) audit_trail_service.create( actor=request.user, verb=AuditType.REMOVE_GOOD_FROM_APPLICATION, action_object=good_on_application.good, target=application.get_case(), payload={"good_name": good_on_application.good.description}, ) return JsonResponse(data={"status": "success"}, status=status.HTTP_200_OK)
def get(self, request, pk, doc_pk): """ Returns a list of documents on the specified good """ good = get_good(pk) if good.organisation.id != get_request_user_organisation_id(request): raise PermissionDenied() if good.status != GoodStatus.DRAFT: return JsonResponse(data={ "errors": "This good is already on a submitted application" }, status=status.HTTP_400_BAD_REQUEST) good_document = get_good_document(good, doc_pk) serializer = GoodDocumentViewSerializer(good_document) return JsonResponse({"document": serializer.data})