示例#1
0
    def put(self, request, pk):
        """
        Assigns a gov user to be the case officer for a case
        """
        case = get_case(pk)
        gov_user_pk = request.data.get("gov_user_pk")

        if not gov_user_pk:
            return JsonResponse(
                data={"errors": {
                    "user": [Cases.CaseOfficerPage.NONE]
                }},
                status=status.HTTP_400_BAD_REQUEST)

        data = {"case_officer": gov_user_pk}
        serializer = CaseOfficerUpdateSerializer(instance=case, data=data)

        if serializer.is_valid(raise_exception=True):
            user = get_user_by_pk(gov_user_pk)
            serializer.save()

            audit_trail_service.create(
                actor=request.user,
                verb=AuditType.ADD_CASE_OFFICER_TO_CASE,
                target=case,
                payload={
                    "case_officer":
                    user.email if not user.first_name else
                    f"{user.first_name} {user.last_name}"
                },
            )

            return JsonResponse(data={}, status=status.HTTP_200_OK)
示例#2
0
    def delete(self, request, pk):
        """
        Removes the case officer currently assigned to a case off of it.
        """
        case = get_case(pk)

        if not case.case_officer:
            return HttpResponse(status=status.HTTP_400_BAD_REQUEST)

        data = {"case_officer": None}

        serializer = CaseOfficerUpdateSerializer(instance=case, data=data)

        if serializer.is_valid(raise_exception=True):
            user = case.case_officer

            serializer.save()
            audit_trail_service.create(
                actor=request.user,
                verb=AuditType.REMOVE_CASE_OFFICER_FROM_CASE,
                target=case,
                payload={
                    "case_officer":
                    user.email if not user.first_name else
                    f"{user.first_name} {user.last_name}"
                },
            )

            return JsonResponse(data={}, status=status.HTTP_200_OK)
示例#3
0
 def get(self, request, pk, s3_key):
     """
     Returns a list of documents on the specified case
     """
     case = get_case(pk)
     case_document = get_case_document(case, s3_key)
     serializer = CaseDocumentViewSerializer(case_document)
     return JsonResponse(data={"document": serializer.data},
                         status=status.HTTP_200_OK)
示例#4
0
 def perform_destroy(self, instance):
     instance.delete()
     case = get_case(instance.visit_case_id)
     audit_trail_service.create(
         actor=self.request.user,
         verb=AuditType.COMPLIANCE_PEOPLE_PRESENT_DELETED,
         action_object=case,
         payload={},
     )
示例#5
0
    def post(self, request, pk):
        """ Create a case note on a case. """
        case = get_case(pk, hasattr(request.user, "exporteruser"))

        if CaseStatusEnum.is_terminal(case.status.status) and hasattr(request.user, "exporteruser"):
            return JsonResponse(
                data={"errors": {"text": [strings.Applications.Generic.TERMINAL_CASE_CANNOT_PERFORM_OPERATION_ERROR]}},
                status=status.HTTP_400_BAD_REQUEST,
            )
示例#6
0
 def patch(self, request, pk):
     """
     Change case status
     """
     case = get_case(pk)
     case.change_status(
         request.user,
         get_case_status_by_status(request.data.get("status")),
         request.data.get("note"))
     return JsonResponse(data={}, status=status.HTTP_200_OK)
示例#7
0
 def perform_create(self, serializer):
     party = serializer.save()
     case = get_case(self.kwargs["pk"])
     case.additional_contacts.add(party)
     audit_trail_service.create(
         actor=self.request.user,
         verb=AuditType.ADD_ADDITIONAL_CONTACT_TO_CASE,
         target=case,
         payload={"contact": serializer.data["name"]},
     )
示例#8
0
    def put(self, request, pk):
        """
        Finalise & grant a Licence
        """
        case = get_case(pk)

        # Check Permissions
        if CaseTypeSubTypeEnum.is_mod_clearance(case.case_type.sub_type):
            assert_user_has_permission(
                request.user.govuser,
                GovPermissions.MANAGE_CLEARANCE_FINAL_ADVICE)
示例#9
0
    def get(self, request, pk):
        """
        Retrieve a case instance
        """
        gov_user = request.user.govuser
        case = get_case(pk)
        data = CaseDetailSerializer(case, user=gov_user,
                                    team=gov_user.team).data

        if case.case_type.sub_type == CaseTypeSubTypeEnum.OPEN:
            data["data"]["destinations"] = get_destinations(case.id)  # noqa
示例#10
0
    def get(self, request, pk):
        """
        Returns a list of documents on the specified case
        """
        case = get_case(pk)
        case_documents = CaseDocument.objects.filter(
            case=case).order_by("-created_at")
        serializer = CaseDocumentViewSerializer(case_documents, many=True)

        return JsonResponse(data={"documents": serializer.data},
                            status=status.HTTP_200_OK)
示例#11
0
    def perform_update(self, serializer):
        person = serializer.save()

        case = get_case(person.visit_case_id)

        audit_trail_service.create(
            actor=self.request.user,
            verb=AuditType.COMPLIANCE_PEOPLE_PRESENT_UPDATED,
            action_object=case,
            payload={
                "name": person.name,
                "job_title": person.job_title,
            },
        )
示例#12
0
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()
示例#13
0
    def post(self, request, pk):
        """
        Adds a document to the specified case
        """
        data = request.data

        for document in data:
            document["case"] = pk
            document["user"] = request.user.pk
            document["visible_to_exporter"] = False

        serializer = CaseDocumentCreateSerializer(data=data, many=True)
        if serializer.is_valid():
            serializer.save()

            for document in serializer.data:
                audit_trail_service.create(
                    actor=request.user,
                    verb=AuditType.UPLOAD_CASE_DOCUMENT,
                    target=get_case(pk),
                    payload={"file_name": document["name"]},
                )

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

        delete_documents_on_bad_request(data)
        return JsonResponse(data={"errors": serializer.errors},
                            status=status.HTTP_400_BAD_REQUEST)
示例#14
0
    def dispatch(self, request, *args, **kwargs):
        self.case = get_case(kwargs["pk"])
        self.team_advice = Advice.objects.get_team_advice(case=self.case)
        self.final_advice = Advice.objects.get_final_advice(
            case=self.case).order_by("created_at")

        return super(FinalAdvice, self).dispatch(request, *args, **kwargs)
示例#15
0
class LetterTemplatesList(generics.ListCreateAPIView):
    """
    Returns list of all letter templates or creates a letter template
    """

    authentication_classes = (GovAuthentication, )

    def get_serializer_class(self):
        if self.request.method == "GET":
            return LetterTemplateListSerializer
        else:
            return LetterTemplateSerializer

    def get_queryset(self):
        case = self.request.GET.get("case")
        name = self.request.GET.get("name")
        decision = self.request.GET.get("decision")
        queryset = LetterTemplate.objects.all().prefetch_related(
            "layout", "case_types")

        if decision:
            case = get_case(pk=case)
            decision = Decision.objects.get(name=decision)
            return queryset.filter(
                Q(case_types=case.case_type, decisions=decision)
                | Q(case_types=case.case_type, decisions__isnull=True))
示例#16
0
    def put(self, request, pk):
        """
        Reruns routing rules against a given case, in turn removing all existing queues, and user assignments,
            and starting again from scratch on the given status
        Audits who requests the rules to be rerun
        """
        case = get_case(pk)

        audit_trail_service.create(
            actor=request.user,
            verb=AuditType.RERUN_ROUTING_RULES,
            target=case,
        )

        run_routing_rules(case)

        return JsonResponse(data={}, status=status.HTTP_200_OK)
示例#17
0
class ActivityView(APIView):
    authentication_classes = (ExporterAuthentication,)

    def get(self, request, pk):
        case = get_case(pk)
        audit_trail_qs = audit_trail_service.get_activity_for_user_and_model(user=request.user, object_type=case)

        return JsonResponse(
            data={"activity": AuditSerializer(audit_trail_qs, many=True).data}, status=status.HTTP_200_OK
        )
示例#18
0
class SetQueues(APIView):
    authentication_classes = (GovAuthentication, )

    @transaction.atomic
    def put(self, request, pk):
        case = get_case(pk)
        request_queues = set(request.data.get("queues", []))
        queues = Queue.objects.filter(id__in=request_queues)
        note = request.data.get("note")

        if len(request_queues) > len(queues):
            queues_not_found = list(request_queues - set(
                str(id) for id in queues.values_list("id", flat=True)))
            return JsonResponse(
                data={
                    "errors": {
                        "queues":
                        [Cases.Queue.NOT_FOUND + str(queues_not_found)]
                    }
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        initial_queues = set(case.queues.all())
        queues = set(queues)
        case.queues.set(request_queues)

        removed_queues = initial_queues - queues
        new_queues = queues - initial_queues
        if removed_queues:
            # Remove case assignments when the case is remove from the queue
            CaseAssignment.objects.filter(case=case,
                                          queue__in=removed_queues).delete()
            audit_trail_service.create(
                actor=request.user,
                verb=AuditType.REMOVE_CASE,
                target=case,
                payload={
                    "queues": sorted([queue.name for queue in removed_queues]),
                    "additional_text": note
                },
            )
        if new_queues:
            audit_trail_service.create(
                actor=request.user,
                verb=AuditType.MOVE_CASE,
                target=case,
                payload={
                    "queues": sorted([queue.name for queue in new_queues]),
                    "additional_text": note
                },
            )
        return JsonResponse(data={"queues": list(request_queues)},
                            status=status.HTTP_200_OK)
示例#19
0
    def post(self, request, pk):
        assert_user_has_permission(
            request.user.govuser,
            constants.GovPermissions.MANAGE_LICENCE_FINAL_ADVICE)

        data = {k: v for k, v in request.data.items() if v is not None}

        # Get list of all required item id's
        required_decisions = get_required_good_type_to_country_combinations(pk)
        required_decision_ids = set()
        for goods_type, country_list in required_decisions.items():
            for country in country_list:
                required_decision_ids.add(f"{goods_type}.{country}")

        if not required_decision_ids.issubset(data):
            missing_ids = required_decision_ids.difference(request.data)
            raise ParseError({
                missing_id: [Cases.GoodCountryMatrix.MISSING_ITEM]
                for missing_id in missing_ids
            })

        # Delete existing decision documents if decision changes
        existing_decisions = get_existing_good_type_to_country_decisions(pk)
        for decision_id in required_decision_ids:
            if (data.get(decision_id) !=
                    AdviceType.REFUSE) != existing_decisions.get(decision_id):
                # Proviso N/A as there is no proviso document type
                GeneratedCaseDocument.objects.filter(
                    case_id=pk,
                    advice_type__in=[AdviceType.APPROVE, AdviceType.REFUSE],
                    visible_to_exporter=False).delete()
                break

        # Update or create GoodCountryDecisions
        for id in required_decision_ids:
            goods_type_id, country_id = id.split(".")
            value = data[id] == AdviceType.APPROVE
            GoodCountryDecision.objects.update_or_create(
                case_id=pk,
                goods_type_id=goods_type_id,
                country_id=country_id,
                defaults={"approve": value})

        audit_trail_service.create(
            actor=request.user,
            verb=AuditType.UPDATED_GOOD_ON_DESTINATION_MATRIX,
            target=get_case(pk),
        )

        return JsonResponse(
            data={"good_country_decisions": list(required_decision_ids)},
            status=status.HTTP_201_CREATED)
示例#20
0
def get_object_of_level(level, pk):
    if level == "good":
        try:
            good = Good.objects.get(pk=pk)
        except Good.DoesNotExist:
            good = get_goods_type(pk)
        return good
    elif level == "case":
        return get_case(pk)
    elif level == "organisation":
        return get_organisation_by_pk(pk)
    elif level == "destination":
        return get_destination(pk)
示例#21
0
def get_generated_document_data(request_params, pk):
    template_id = request_params.get("template")
    if not template_id:
        raise AttributeError(strings.Cases.GeneratedDocuments.MISSING_TEMPLATE)

    text = request_params.get("text", "")
    additional_contact = request_params.get("addressee")
    if additional_contact:
        try:
            additional_contact = Party.objects.get(
                type=PartyType.ADDITIONAL_CONTACT, id=additional_contact)
        except Party.DoesNotExist:
            raise AttributeError(
                strings.Cases.GeneratedDocuments.INVALID_ADDRESSEE)

    case = get_case(pk)
    try:
        template = LetterTemplate.objects.get(pk=template_id,
                                              case_types=case.case_type)
    except LetterTemplate.DoesNotExist:
        raise NotFoundError({
            "letter_template":
            strings.Cases.GeneratedDocuments.LETTER_TEMPLATE_NOT_FOUND
        })
    document_html = generate_preview(
        layout=template.layout.filename,
        text=text,
        case=case,
        additional_contact=additional_contact,
        include_digital_signature=template.include_digital_signature,
    )

    if "error" in document_html:
        raise AttributeError(document_html["error"])

    return GeneratedDocumentPayload(case=case,
                                    template=template,
                                    document_html=document_html,
                                    text=text)
示例#22
0
    def put(self, request, pk):
        """
        Assign users to cases on that queue
        """
        queue = get_queue(pk)
        data = request.data

        for assignment in data.get("case_assignments"):
            case = get_case(assignment["case_id"])
            users = [get_user_by_pk(i) for i in assignment["users"]]

            if str_to_bool(data.get("remove_existing_assignments")):
                CaseAssignment.objects.filter(case=case, queue=queue).delete()

            # Create a new case assignment object between that case and those users
            for user in users:
                try:
                    CaseAssignment.objects.get(case=case, queue=queue, user=user)
                except CaseAssignment.DoesNotExist:
                    case_assignment = CaseAssignment(case=case, queue=queue, user=user)
                    case_assignment.save(audit_user=request.user, user=user, audit_note=data.get("note"))

            # Add to queue
            case.queues.add(queue)
示例#23
0
    def get(self, request, pk):
        """
        Gets all advice types and any documents generated for those types of advice.
        """
        # Get all advice
        advice_values = AdviceType.as_dict()

        final_advice = get_required_decision_document_types(get_case(pk))
        if not final_advice:
            return JsonResponse(data={"documents": {}},
                                status=status.HTTP_200_OK)

        advice_documents = {
            advice_type: {
                "value": advice_values[advice_type]
            }
            for advice_type in final_advice
        }

        if AdviceType.APPROVE in final_advice:
            # Get Licence document (Approve)
            licence = Licence.objects.get_draft_or_active_licence(pk)
            # Only cases with Approve/Proviso advice have a Licence
            if licence:
                try:
                    licence_document = GeneratedCaseDocument.objects.get(
                        advice_type=AdviceType.APPROVE, licence=licence)
                    advice_documents[AdviceType.APPROVE][
                        "document"] = AdviceDocumentGovSerializer(
                            licence_document).data
                except GeneratedCaseDocument.DoesNotExist:
                    pass
            # Remove Approve for looking up other decision documents below
            final_advice.remove(AdviceType.APPROVE)

        # Get other decision documents
        generated_advice_documents = GeneratedCaseDocument.objects.filter(
            advice_type__in=final_advice, case__id=pk)
        generated_advice_documents = AdviceDocumentGovSerializer(
            generated_advice_documents,
            many=True,
        ).data
        for document in generated_advice_documents:
            advice_documents[document["advice_type"]
                             ["key"]]["document"] = document

        return JsonResponse(data={"documents": advice_documents},
                            status=status.HTTP_200_OK)
示例#24
0
    def get_paginated_response(self, data):
        current_date = timezone.now().date()

        # We take an OLR as outstanding if it hasn't been added by the end of January, meaning if the
        # month is currently January we only go back 1 year
        olr_year = current_date.year - 2 if current_date.month == 1 else current_date.year - 1

        org_id = get_case(self.kwargs["pk"]).organisation_id
        licences_with_olr = set(
            OpenLicenceReturns.objects.filter(
                year=olr_year,
                organisation_id=org_id).values_list("licences__case",
                                                    flat=True))

        for licence in data:
            licence["has_open_licence_returns"] = UUID(
                licence["id"]) in licences_with_olr

        return super().get_paginated_response(data)
示例#25
0
class CaseApplicant(APIView):
    authentication_classes = (GovAuthentication, )

    def get(self, request, pk):
        case = get_case(pk)
        applicant = case.submitted_by
        # compliance cases do not contain a person who submit them, as such we return empty details
        if not applicant:
            return JsonResponse({
                "name": "",
                "email": ""
            },
                                status=status.HTTP_200_OK)
        return JsonResponse(
            {
                "name": applicant.first_name + " " + applicant.last_name,
                "email": applicant.email
            },
            status=status.HTTP_200_OK,
        )
示例#26
0
class ComplianceCaseId(APIView):
    """
    This endpoint is currently only used for testing purposes.
    It gives us back the compliance case ids for the given case.
    """

    authentication_classes = (GovAuthentication, )

    def get(self, request, pk, *args, **kwargs):
        case = get_case(pk)
        # Get record holding sites for the case
        record_holding_sites_id = get_record_holding_sites_for_case(case)

        # Get list of record holding sites that do not have a compliance case
        existing_compliance_cases = Case.objects.filter(
            compliancesitecase__site_id__in=record_holding_sites_id).distinct(
            )

        return JsonResponse(data={
            "ids":
            list(existing_compliance_cases.values_list("id", flat=True))
        },
                            status=status.HTTP_200_OK)
示例#27
0
    def get_queryset(self):
        case = self.request.GET.get("case")
        name = self.request.GET.get("name")
        decision = self.request.GET.get("decision")
        queryset = LetterTemplate.objects.all().prefetch_related(
            "layout", "case_types")

        if decision:
            case = get_case(pk=case)
            decision = Decision.objects.get(name=decision)
            return queryset.filter(
                Q(case_types=case.case_type, decisions=decision)
                | Q(case_types=case.case_type, decisions__isnull=True))
        elif case:
            case = get_case(pk=case)
            return queryset.filter(case_types=case.case_type,
                                   decisions__isnull=True)

        if name:
            queryset = queryset.filter(name__icontains=name)

        return queryset

    def post(self, request, *args, **kwargs):
        assert_user_has_permission(
            request.user.govuser, constants.GovPermissions.CONFIGURE_TEMPLATES)
        data = request.data
        data["case_types"] = CaseTypeEnum.references_to_ids(
            data.get("case_types"))
        data["decisions"] = [
示例#28
0
            GeneratedCaseDocument.objects.filter(
                case_id=case.id, advice_type__isnull=False, visible_to_exporter=False
            ).delete()
        return JsonResponse({"advice": serializer.data}, status=status.HTTP_201_CREATED)

    errors = {}
    if serializer.errors:
        errors.update(serializer.errors[0])

    if refusal_error:
        errors.update(refusal_error)
    return JsonResponse({"errors": errors}, status=status.HTTP_400_BAD_REQUEST)


def case_advice_contains_refusal(case_id):
    case = get_case(case_id)
    team_advice = Advice.objects.filter(case=case)
    flag = Flag.objects.get(id=SystemFlags.REFUSAL_FLAG_ID)

    refuse_advice_found = False

    for advice in team_advice:
        if advice.type.lower() == "refuse":
            refuse_advice_found = True
            if flag not in case.flags.all():
                case.flags.add(flag)
                break

    if not refuse_advice_found:
        if flag in case.flags.all():
            case.flags.remove(flag)
示例#29
0
    def post(self, request, case_pk):
        if CaseStatusEnum.is_terminal(self.application.status.status):
            return JsonResponse(
                data={
                    "errors": {
                        "error": [
                            strings.Applications.Generic.
                            TERMINAL_CASE_CANNOT_PERFORM_OPERATION_ERROR
                        ]
                    }
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        case = get_case(case_pk)

        for good in self.get_queryset():
            serializer = self.get_serializer(good)
            serializer.is_valid(raise_exception=True)
            old_control_list_entries = list(
                good.control_list_entries.values_list("rating", flat=True))
            old_is_controlled = good.is_good_controlled
            serializer.save()
            if "control_list_entries" in serializer.data or "is_good_controlled" in serializer.data:
                new_control_list_entries = [
                    item.rating for item in
                    serializer.validated_data["control_list_entries"]
                ]
                new_is_controlled = serializer.validated_data[
                    "is_good_controlled"]
                if new_control_list_entries != old_control_list_entries or new_is_controlled != old_is_controlled:
                    if isinstance(good, GoodsType):
                        good.flags.clear()
                    else:
                        good.good.flags.clear()
                    default_control = [strings.Goods.GOOD_NO_CONTROL_CODE]
                    audit_trail_service.create(
                        actor=request.user,
                        verb=AuditType.GOOD_REVIEWED,
                        action_object=good,
                        target=case,
                        payload={
                            "good_name":
                            good.description,
                            "new_control_list_entry":
                            new_control_list_entries or default_control,
                            "old_control_list_entry":
                            old_control_list_entries or default_control,
                            "old_is_good_controlled":
                            "Yes" if old_is_controlled else "No",
                            "new_is_good_controlled":
                            "Yes" if new_is_controlled else "No",
                            "additional_text":
                            serializer.validated_data["comment"],
                            "is_precedent":
                            serializer.validated_data.get(
                                "is_precedent", False),
                        },
                    )
        apply_good_flagging_rules_for_case(case)
        return JsonResponse(data={}, status=status.HTTP_200_OK)
示例#30
0
    def dispatch(self, request, *args, **kwargs):
        self.case = get_case(kwargs["pk"])
        self.advice = Advice.objects.filter(case=self.case)
        self.team_advice = Advice.objects.get_team_advice(self.case)

        return super(TeamAdviceView, self).dispatch(request, *args, **kwargs)