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)
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)
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)
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={}, )
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, )
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)
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"]}, )
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)
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
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)
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, }, )
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 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)
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)
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))
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)
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 )
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)
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)
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)
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)
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)
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)
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)
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, )
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)
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"] = [
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)
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)
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)