Exemple #1
0
    def test_F680_application(self):
        application = self.create_mod_clearance_application(self.organisation, CaseTypeEnum.F680)

        case_flag = self.create_flag("case flag", FlagLevels.CASE, self.team)
        self.create_flagging_rule(
            FlagLevels.CASE, self.team, flag=case_flag, matching_values=[application.case_type.reference]
        )

        good = GoodOnApplication.objects.filter(application_id=application.id).first().good
        good_flag = self.create_flag("good flag", FlagLevels.GOOD, self.team)
        self.create_flagging_rule(
            FlagLevels.GOOD, self.team, flag=good_flag, matching_values=[good.control_list_entries.first().rating]
        )

        party = PartyOnApplication.objects.filter(application_id=application.id).first().party
        destination_flag = self.create_flag("dest flag", FlagLevels.DESTINATION, self.team)
        self.create_flagging_rule(
            FlagLevels.DESTINATION, self.team, flag=destination_flag, matching_values=[party.country_id]
        )

        self.submit_application(application)
        apply_flagging_rules_to_case(application)

        application.refresh_from_db()
        good.refresh_from_db()
        party.refresh_from_db()

        self.assertIn(case_flag, application.flags.all())
        self.assertIn(good_flag, good.flags.all())
        self.assertIn(destination_flag, party.flags.all())
Exemple #2
0
    def test_open_application_automation(self):
        application = self.create_draft_open_application(self.organisation)

        case_flag = self.create_flag("case flag", FlagLevels.CASE, self.team)
        self.create_flagging_rule(
            FlagLevels.CASE, self.team, flag=case_flag, matching_values=[application.case_type.reference]
        )

        goods_type = GoodsType.objects.filter(application_id=application.id).first()
        good_flag = self.create_flag("good flag", FlagLevels.GOOD, self.team)
        self.create_flagging_rule(
            FlagLevels.GOOD,
            self.team,
            flag=good_flag,
            matching_values=[goods_type.control_list_entries.first().rating],
            is_for_verified_goods_only=False,
        )

        country = CountryOnApplication.objects.filter(application_id=application.id).first().country
        destination_flag = self.create_flag("dest flag", FlagLevels.DESTINATION, self.team)
        dest_flagging_rule = self.create_flagging_rule(
            FlagLevels.DESTINATION, self.team, flag=destination_flag, matching_values=[country.id]
        )
        apply_flagging_rule_to_all_open_cases(dest_flagging_rule)

        self.submit_application(application)
        apply_flagging_rules_to_case(application)

        application.refresh_from_db()
        goods_type.refresh_from_db()
        country.refresh_from_db()

        self.assertIn(case_flag, application.flags.all())
        self.assertIn(good_flag, goods_type.flags.all())
        self.assertIn(destination_flag, country.flags.all())
Exemple #3
0
    def test_hmrc_application(self):
        application = self.create_hmrc_query(self.organisation)

        case_flag = self.create_flag("case flag", FlagLevels.CASE, self.team)
        self.create_flagging_rule(
            FlagLevels.CASE, self.team, flag=case_flag, matching_values=[application.case_type.reference]
        )

        goods_type = GoodsType.objects.filter(application_id=application.id).first()
        good_flag = self.create_flag("good flag", FlagLevels.GOOD, self.team)

        goods_type.control_list_entries.set([get_control_list_entry("ML1a")])
        self.create_flagging_rule(
            FlagLevels.GOOD, self.team, flag=good_flag, matching_values=[goods_type.control_list_entries.first().rating]
        )

        party = PartyOnApplication.objects.filter(application_id=application.id).first().party
        destination_flag = self.create_flag("dest flag", FlagLevels.DESTINATION, self.team)
        self.create_flagging_rule(
            FlagLevels.DESTINATION, self.team, flag=destination_flag, matching_values=[party.country_id]
        )

        self.submit_application(application)
        apply_flagging_rules_to_case(application)

        application.refresh_from_db()
        goods_type.refresh_from_db()
        party.refresh_from_db()

        self.assertIn(case_flag, application.flags.all())
        self.assertIn(good_flag, goods_type.flags.all())
        self.assertIn(destination_flag, party.flags.all())
Exemple #4
0
    def submit_application(application: BaseApplication,
                           user: ExporterUser = None):
        if not user:
            user = UserOrganisationRelationship.objects.filter(
                organisation_id=application.organisation_id).first().user

        application.submitted_at = timezone.localtime()
        application.sla_remaining_days = get_application_target_sla(
            application.case_type.sub_type)
        application.status = get_case_status_by_status(
            CaseStatusEnum.SUBMITTED)
        application.save()

        if application.case_type.sub_type in [
                CaseTypeSubTypeEnum.STANDARD, CaseTypeSubTypeEnum.OPEN
        ]:
            set_case_flags_on_submitted_standard_or_open_application(
                application)

        add_goods_flags_to_submitted_application(application)
        apply_flagging_rules_to_case(application)

        audit_trail_service.create(
            actor=user.baseuser_ptr,
            verb=AuditType.UPDATED_STATUS,
            target=application.get_case(),
            payload={
                "status": {
                    "new": CaseStatusEnum.get_text(CaseStatusEnum.SUBMITTED),
                    "old": CaseStatusEnum.get_text(CaseStatusEnum.DRAFT),
                }
            },
        )

        return application
Exemple #5
0
    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)
Exemple #6
0
    def change_status(self,
                      user,
                      status: CaseStatus,
                      note: Optional[str] = ""):
        """
        Sets the status for the case, runs validation on various parameters,
        creates audit entries and also runs flagging and automation rules
        """
        from api.cases.helpers import can_set_status
        from api.audit_trail import service as audit_trail_service
        from api.applications.libraries.application_helpers import can_status_be_set_by_gov_user
        from api.workflow.automation import run_routing_rules
        from api.workflow.flagging_rules_automation import apply_flagging_rules_to_case
        from api.licences.helpers import update_licence_status

        old_status = self.status.status

        # Only allow the final decision if the user has the MANAGE_FINAL_ADVICE permission
        if status.status == CaseStatusEnum.FINALISED:
            assert_user_has_permission(
                user.govuser, GovPermissions.MANAGE_LICENCE_FINAL_ADVICE)

        if not can_set_status(self, status.status):
            raise ValidationError({"status": [strings.Statuses.BAD_STATUS]})

        if not can_status_be_set_by_gov_user(
                user.govuser, old_status, status.status, is_mod=False):
            raise ValidationError({"status": ["Status cannot be set by user"]})

        self.status = status
        self.save()

        # Update licence status if applicable case status change
        update_licence_status(self, status.status)

        if CaseStatusEnum.is_terminal(
                old_status) and not CaseStatusEnum.is_terminal(
                    self.status.status):
            apply_flagging_rules_to_case(self)

        audit_trail_service.create(
            actor=user,
            verb=AuditType.UPDATED_STATUS,
            target=self,
            payload={
                "status": {
                    "new": CaseStatusEnum.get_text(self.status.status),
                    "old": old_status
                },
                "additional_text": note,
            },
        )

        if old_status != self.status.status:
            run_routing_rules(case=self, keep_status=True)
Exemple #7
0
    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 reopen_closed_cases_for_organisation(organisation):
        """
        Set the case status to 'Reopened due to org changes' for any cases in the organisation that have
        been granted a licence.
        """
        reopened_due_to_org_changes_status = CaseStatus.objects.get(
            status="reopened_due_to_org_changes")

        applications = BaseApplication.objects.filter(
            organisation=organisation,
            status=get_case_status_by_status(CaseStatusEnum.FINALISED))
        applications.update(status_id=reopened_due_to_org_changes_status)

        for application in applications:
            apply_flagging_rules_to_case(application)
Exemple #9
0
    def test_end_user_advisory_application(self):
        query = self.create_end_user_advisory("a", "v", self.organisation)

        case_flag = self.create_flag("case flag", FlagLevels.CASE, self.team)
        self.create_flagging_rule(
            FlagLevels.CASE, self.team, flag=case_flag, matching_values=[query.case_type.reference]
        )

        party = query.end_user
        destination_flag = self.create_flag("dest flag", FlagLevels.DESTINATION, self.team)
        self.create_flagging_rule(
            FlagLevels.DESTINATION, self.team, flag=destination_flag, matching_values=[party.country_id]
        )

        apply_flagging_rules_to_case(query)

        query.refresh_from_db()
        party.refresh_from_db()

        self.assertIn(case_flag, query.flags.all())
        self.assertIn(destination_flag, party.flags.all())
Exemple #10
0
    def test_goods_query_application(self):
        query = self.create_clc_query("query", self.organisation)

        case_flag = self.create_flag("case flag", FlagLevels.CASE, self.team)
        self.create_flagging_rule(
            FlagLevels.CASE, self.team, flag=case_flag, matching_values=[query.case_type.reference]
        )

        good = query.good
        good.control_list_entries.set([get_control_list_entry("ML1a")])
        good_flag = self.create_flag("good flag", FlagLevels.GOOD, self.team)
        self.create_flagging_rule(
            FlagLevels.GOOD, self.team, flag=good_flag, matching_values=[good.control_list_entries.first().rating]
        )

        apply_flagging_rules_to_case(query)

        query.refresh_from_db()
        good.refresh_from_db()

        self.assertIn(case_flag, query.flags.all())
        self.assertIn(good_flag, good.flags.all())
Exemple #11
0
    def test_exhibition_application(self):
        application = self.create_mod_clearance_application(self.organisation, CaseTypeEnum.EXHIBITION)
        self.submit_application(application)

        case_flag = self.create_flag("case flag", FlagLevels.CASE, self.team)
        self.create_flagging_rule(
            FlagLevels.CASE, self.team, flag=case_flag, matching_values=[application.case_type.reference]
        )

        good = GoodOnApplication.objects.filter(application_id=application.id).first().good
        good_flag = self.create_flag("good flag", FlagLevels.GOOD, self.team)
        self.create_flagging_rule(
            FlagLevels.GOOD, self.team, flag=good_flag, matching_values=[good.control_list_entries.first().rating]
        )

        self.submit_application(application)
        apply_flagging_rules_to_case(application)

        application.refresh_from_db()
        good.refresh_from_db()

        self.assertIn(case_flag, application.flags.all())
        self.assertIn(good_flag, good.flags.all())
Exemple #12
0
    def put(self, request, pk):
        """ Respond to a control list classification."""
        assert_user_has_permission(request.user.govuser, constants.GovPermissions.REVIEW_GOODS)

        query = get_exporter_query(pk)
        if CaseStatusEnum.is_terminal(query.status.status):
            return JsonResponse(
                data={"errors": [strings.Applications.Generic.TERMINAL_CASE_CANNOT_PERFORM_OPERATION_ERROR]},
                status=status.HTTP_400_BAD_REQUEST,
            )

        data = request.data

        clc_good_serializer = ClcControlGoodSerializer(query.good, data=data)

        if clc_good_serializer.is_valid():
            if not str_to_bool(data.get("validate_only")):
                previous_control_list_entries = list(
                    query.good.control_list_entries.values_list("rating", flat=True)
                ) or [strings.Goods.GOOD_NO_CONTROL_CODE]

                clc_good_serializer.save()
                query.clc_responded = True
                query.save()

                if clc_good_serializer.validated_data.get("control_list_entries"):
                    values = clc_good_serializer.validated_data["control_list_entries"]
                    new_control_list_entries = [clc.rating for clc in values]
                else:
                    new_control_list_entries = [strings.Goods.GOOD_NO_CONTROL_CODE]

                if new_control_list_entries != previous_control_list_entries:
                    audit_trail_service.create(
                        actor=request.user,
                        verb=AuditType.GOOD_REVIEWED,
                        action_object=query.good,
                        target=query.get_case(),
                        payload={
                            "good_name": query.good.description,
                            "old_control_list_entry": previous_control_list_entries,
                            "new_control_list_entry": new_control_list_entries,
                        },
                    )

                flag = Flag.objects.get(id=SystemFlags.GOOD_CLC_QUERY_ID)
                query.good.flags.remove(flag)
                query.good.status = GoodStatus.VERIFIED
                query.good.save()
                apply_flagging_rules_to_case(query)

                audit_trail_service.create(
                    actor=request.user, verb=AuditType.CLC_RESPONSE, action_object=query.good, target=query.get_case(),
                )

                # Send a notification to the user
                for user_relationship in UserOrganisationRelationship.objects.filter(organisation=query.organisation):
                    user_relationship.send_notification(content_object=query, case=query)

                return JsonResponse(
                    data={"control_list_classification_query": clc_good_serializer.data}, status=status.HTTP_200_OK
                )

            return JsonResponse(data={"control_list_classification_query": data}, status=status.HTTP_200_OK)

        return JsonResponse(data={"errors": clc_good_serializer.errors}, status=status.HTTP_400_BAD_REQUEST)
    def put(self, request, pk):
        application = get_application(pk)
        is_licence_application = application.case_type.sub_type != CaseTypeSubTypeEnum.EXHIBITION

        data = deepcopy(request.data)

        if data["status"] == CaseStatusEnum.FINALISED:
            return JsonResponse(
                data={
                    "errors": [
                        strings.Applications.Generic.Finalise.Error.
                        SET_FINALISED
                    ]
                },
                status=status.HTTP_400_BAD_REQUEST,
            )

        if not can_set_status(application, data["status"]):
            raise ValidationError({"status": [strings.Statuses.BAD_STATUS]})

        if hasattr(request.user, "exporteruser"):
            if get_request_user_organisation_id(
                    request) != application.organisation.id:
                raise PermissionDenied()

            if not can_status_be_set_by_exporter_user(
                    application.status.status, data["status"]):
                return JsonResponse(
                    data={
                        "errors": [
                            strings.Applications.Generic.Finalise.Error.
                            EXPORTER_SET_STATUS
                        ]
                    },
                    status=status.HTTP_400_BAD_REQUEST,
                )
        else:
            if not can_status_be_set_by_gov_user(
                    request.user.govuser, application.status.status,
                    data["status"], is_licence_application):
                return JsonResponse(
                    data={
                        "errors": [
                            strings.Applications.Generic.Finalise.Error.
                            GOV_SET_STATUS
                        ]
                    },
                    status=status.HTTP_400_BAD_REQUEST,
                )

        update_licence_status(application, data["status"])

        case_status = get_case_status_by_status(data["status"])
        data["status"] = str(case_status.pk)
        old_status = application.status

        serializer = get_application_update_serializer(application)
        serializer = serializer(application, data=data, partial=True)

        if not serializer.is_valid():
            return JsonResponse(data={"errors": serializer.errors},
                                status=status.HTTP_400_BAD_REQUEST)

        application = serializer.save()

        if CaseStatusEnum.is_terminal(
                old_status.status) and not CaseStatusEnum.is_terminal(
                    application.status.status):
            # we reapply flagging rules if the status is reopened from a terminal state
            apply_flagging_rules_to_case(application)

        audit_trail_service.create(
            actor=request.user,
            verb=AuditType.UPDATED_STATUS,
            target=application.get_case(),
            payload={
                "status": {
                    "new": CaseStatusEnum.get_text(case_status.status),
                    "old": CaseStatusEnum.get_text(old_status.status),
                },
                "additional_text": data.get("note"),
            },
        )

        # Case routing rules
        if old_status != application.status:
            run_routing_rules(case=application, keep_status=True)

        if CaseStatusEnum.is_terminal(application.status.status):
            gov_notify_service.send_email(
                email_address=application.submitted_by.email,
                template_type=TemplateType.APPLICATION_STATUS,
                data=ApplicationStatusEmailData(
                    case_reference=application.reference_code,
                    application_reference=application.name,
                    link=
                    f"{settings.EXPORTER_BASE_URL}/applications/{application.id}",
                ),
            )

        data = get_application_view_serializer(application)(
            application, context={
                "user_type": request.user.type
            }).data

        if application.case_type.sub_type == CaseTypeSubTypeEnum.OPEN:
            data["destinations"] = get_destinations(
                application.id, user_type=request.user.type)

        return JsonResponse(
            data={"data": data},
            status=status.HTTP_200_OK,
        )
    def put(self, request, pk):
        """
        Submit a draft application which will set its submitted_at datetime and status before creating a case
        Depending on the application subtype, this will also submit the declaration of the licence
        """
        application = get_application(pk)
        old_status = application.status.status

        if application.case_type.sub_type != CaseTypeSubTypeEnum.HMRC:
            assert_user_has_permission(
                request.user.exporteruser,
                ExporterPermissions.SUBMIT_LICENCE_APPLICATION,
                application.organisation)

        errors = validate_application_ready_for_submission(application)
        if errors:
            return JsonResponse(data={"errors": errors},
                                status=status.HTTP_400_BAD_REQUEST)

        # Queries are completed directly when submit is clicked on the task list
        # HMRC are completed when submit is clicked on the summary page (page after task list)
        # Applications are completed when submit is clicked on the declaration page (page after summary page)

        if application.case_type.sub_type in [
                CaseTypeSubTypeEnum.EUA, CaseTypeSubTypeEnum.GOODS
        ] or (CaseTypeSubTypeEnum.HMRC and request.data.get("submit_hmrc")):
            application.submitted_by = request.user.exporteruser
            create_submitted_audit(request, application, old_status)
            submit_application(application)
            if request.data.get("submit_hmrc"):
                auto_generate_case_document(
                    "application_form", application,
                    AutoGeneratedDocuments.APPLICATION_FORM)

        elif application.case_type.sub_type in [
                CaseTypeSubTypeEnum.STANDARD,
                CaseTypeSubTypeEnum.OPEN,
                CaseTypeSubTypeEnum.F680,
                CaseTypeSubTypeEnum.GIFTING,
                CaseTypeSubTypeEnum.EXHIBITION,
        ]:
            if request.data.get("submit_declaration"):
                errors = _validate_agree_to_declaration(request, errors)
                if errors:
                    return JsonResponse(data={"errors": errors},
                                        status=status.HTTP_400_BAD_REQUEST)

                # If a valid declaration is provided, save the application
                application.submitted_by = request.user.exporteruser
                application.agreed_to_foi = request.data.get("agreed_to_foi")
                application.foi_reason = request.data.get("foi_reason", "")
                submit_application(application)

                if application.case_type.sub_type in [
                        CaseTypeSubTypeEnum.STANDARD, CaseTypeSubTypeEnum.OPEN
                ]:
                    set_case_flags_on_submitted_standard_or_open_application(
                        application)

                add_goods_flags_to_submitted_application(application)
                apply_flagging_rules_to_case(application)
                create_submitted_audit(request, application, old_status)
                auto_generate_case_document(
                    "application_form", application,
                    AutoGeneratedDocuments.APPLICATION_FORM)
                run_routing_rules(application)

                # Set the sites on this application as used so their name/site records located at are no longer editable
                sites_on_application = SiteOnApplication.objects.filter(
                    application=application)
                Site.objects.filter(id__in=sites_on_application.values_list(
                    "site_id", flat=True)).update(is_used_on_application=True)

        if application.case_type.sub_type in [
                CaseTypeSubTypeEnum.STANDARD,
                CaseTypeSubTypeEnum.OPEN,
                CaseTypeSubTypeEnum.HMRC,
        ]:
            if UUID(SystemFlags.ENFORCEMENT_CHECK_REQUIRED
                    ) not in application.flags.values_list("id", flat=True):
                application.flags.add(SystemFlags.ENFORCEMENT_CHECK_REQUIRED)

        # If the user hasn't visited the optional goods to country mapping page, then no goods to country mappings will
        # have been saved before this point. So save mappings for all goods to all countries, which is the default
        if (application.case_type.sub_type == CaseTypeSubTypeEnum.OPEN
                and GoodsType.objects.filter(application=application,
                                             countries__isnull=True).exists()):
            countries_on_application = CountryOnApplication.objects.filter(
                application=application).values_list("country", flat=True)

            for goods_type in GoodsType.objects.filter(application=application,
                                                       countries__isnull=True):
                goods_type.countries.set(countries_on_application)

        # Serialize for the response message
        serializer = get_application_view_serializer(application)
        serializer = serializer(application,
                                context={"user_type": request.user.type})

        application_data = serializer.data

        if application.case_type.sub_type == CaseTypeSubTypeEnum.OPEN:
            application_data["destinations"] = get_destinations(
                application.id, user_type=request.user.type)

        data = {
            "application": {
                "reference_code": application.reference_code,
                **application_data
            }
        }

        if application.reference_code:
            data["reference_code"] = application.reference_code

        return JsonResponse(data=data, status=status.HTTP_200_OK)