コード例 #1
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
コード例 #2
0
    def test_standard_application_declaration_submit_success(self, upload_bytes_file_func, html_to_pdf_func):
        upload_bytes_file_func.return_value = None
        html_to_pdf_func.return_value = None

        self.draft.agreed_to_foi = True
        self.draft.save()
        self.assertEqual(self.draft.status.status, CaseStatusEnum.DRAFT)

        data = {
            "submit_declaration": "True",
            "agreed_to_declaration": "True",
            "agreed_to_foi": "False",
            "foi_reason": "Lorem ipsum",
        }

        url = reverse("applications:application_submit", kwargs={"pk": self.draft.id})
        response = self.client.put(url, data, **self.exporter_headers)

        self.assertEqual(response.status_code, status.HTTP_200_OK)

        case = Case.objects.get(id=self.draft.id)
        self.assertIsNotNone(case.submitted_at)
        self.assertNotEqual(case.status.status, CaseStatusEnum.DRAFT)
        self.assertFalse(case.status.is_terminal)
        self.assertEqual(case.baseapplication.agreed_to_foi, False)
        self.assertEqual(case.baseapplication.foi_reason, "Lorem ipsum")
        self.assertEqual(case.submitted_by, self.exporter_user)
        self.assertTrue(UUID(SystemFlags.ENFORCEMENT_CHECK_REQUIRED) in case.flags.values_list("id", flat=True))

        for good_on_application in GoodOnApplication.objects.filter(application=case):
            self.assertEqual(good_on_application.good.status, GoodStatus.SUBMITTED)

        case_status_audits = Audit.objects.filter(target_object_id=case.id, verb=AuditType.UPDATED_STATUS).values_list(
            "payload", flat=True
        )
        self.assertIn(
            {
                "status": {
                    "new": CaseStatusEnum.get_text(CaseStatusEnum.SUBMITTED),
                    "old": CaseStatusEnum.get_text(CaseStatusEnum.DRAFT),
                }
            },
            case_status_audits,
        )
        # Asserting that the 'Application Form' has been autogenerated on submission of the application
        html_to_pdf_func.assert_called_once()
        upload_bytes_file_func.assert_called_once()
        self.assertEqual(
            CaseDocument.objects.filter(
                name__contains=AutoGeneratedDocuments.APPLICATION_FORM,
                type=CaseDocumentState.AUTO_GENERATED,
                safe=True,
                case=case,
                visible_to_exporter=False,
            ).count(),
            1,
        )
コード例 #3
0
def create_submitted_audit(request: Request, application: HmrcQuery,
                           old_status: str) -> None:
    audit_trail_service.create(
        actor=request.user,
        verb=AuditType.UPDATED_STATUS,
        target=application.get_case(),
        payload={
            "status": {
                "new": CaseStatusEnum.get_text(CaseStatusEnum.SUBMITTED),
                "old": CaseStatusEnum.get_text(old_status),
            }
        },
        ignore_case_status=True,
        send_notification=False,
    )
コード例 #4
0
    def test_exporter_set_application_status_surrendered_success(self, mock_notify_client):
        self.standard_application.status = get_case_status_by_status(CaseStatusEnum.FINALISED)
        self.standard_application.save()
        self.create_licence(self.standard_application, status=LicenceStatus.ISSUED)
        surrendered_status = get_case_status_by_status("surrendered")

        data = {"status": CaseStatusEnum.SURRENDERED}
        response = self.client.put(self.url, data=data, **self.exporter_headers)
        response_data = response.json()["data"]

        self.standard_application.refresh_from_db()

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(
            response_data["status"],
            {"key": surrendered_status.status, "value": CaseStatusEnum.get_text(surrendered_status.status)},
        )
        self.assertEqual(self.standard_application.status, get_case_status_by_status(CaseStatusEnum.SURRENDERED))
        mock_notify_client.send_email.assert_called_with(
            email_address=self.standard_application.submitted_by.email,
            template_id=TemplateType.APPLICATION_STATUS.template_id,
            data={
                "case_reference": self.standard_application.reference_code,
                "application_reference": self.standard_application.name,
                "link": f"{settings.EXPORTER_BASE_URL}/applications/{self.standard_application.pk}",
            },
        )
コード例 #5
0
    def test_rules_rerun_when_no_rules_are_applied_then_case_status_is_changed_and_audited(
            self):
        self.routing_rule_1.delete()
        self.case.queues.set([self.other_queue.id])

        response = self.client.put(self.url, {}, **self.gov_headers)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.case.refresh_from_db()

        # Case has been removed from queues
        self.assertEqual(self.case.queues.count(), 0)

        # Assert case status changed to all applicable statuses in correct order (ignoring initial submission status)
        exclude_payload = {
            "status": {
                "new": CaseStatusEnum.get_text(CaseStatusEnum.SUBMITTED),
                "old": CaseStatusEnum.get_text(CaseStatusEnum.DRAFT),
            }
        }

        actual_status_changes = (Audit.objects.filter(
            target_object_id=self.case.id,
            verb=AuditType.UPDATED_STATUS).exclude(
                payload=exclude_payload).order_by("created_at"))

        applicable_status_changes = CaseStatus.objects.filter(
            workflow_sequence__isnull=False,
            workflow_sequence__gt=CaseStatus.objects.get(
                status=CaseStatusEnum.SUBMITTED).workflow_sequence,
            workflow_sequence__lte=CaseStatus.objects.get(
                status=CaseStatusEnum.UNDER_FINAL_REVIEW).workflow_sequence,
        ).order_by("workflow_sequence")

        self.assertEqual(actual_status_changes.count(),
                         applicable_status_changes.count())

        for index in range(len(applicable_status_changes)):
            self.assertEqual(
                actual_status_changes[index].payload["status"]["new"],
                CaseStatusEnum.get_text(
                    applicable_status_changes[index].status),
            )

        # Assert the case status was finally set to Under Final Review (the last applicable status)
        self.assertEqual(self.case.status.status,
                         CaseStatusEnum.UNDER_FINAL_REVIEW)
コード例 #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)
コード例 #7
0
    def test_exp_set_application_status_to_submitted_when_previously_applicant_editing_success(
        self, upload_bytes_file_func, html_to_pdf_func
    ):
        upload_bytes_file_func.return_value = None
        html_to_pdf_func.return_value = None

        standard_application = self.create_draft_standard_application(self.organisation)
        self.submit_application(standard_application)
        standard_application.status = get_case_status_by_status(CaseStatusEnum.APPLICANT_EDITING)
        standard_application.save()
        previous_submitted_at = standard_application.submitted_at

        data = {"submit_declaration": True, "agreed_to_declaration": True, "agreed_to_foi": True, "foi_reason": ""}

        url = reverse("applications:application_submit", kwargs={"pk": standard_application.id})

        response = self.client.put(url, data, **self.exporter_headers)

        standard_application.refresh_from_db()
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertNotEqual(
            standard_application.status.status, CaseStatusEnum.APPLICANT_EDITING,
        )
        self.assertFalse(standard_application.status.is_terminal)
        self.assertNotEqual(standard_application.submitted_at, previous_submitted_at)
        self.assertEqual(standard_application.agreed_to_foi, True)

        case_status_audits = Audit.objects.filter(
            target_object_id=standard_application.id, verb=AuditType.UPDATED_STATUS
        ).values_list("payload", flat=True)
        self.assertIn(
            {
                "status": {
                    "new": CaseStatusEnum.get_text(CaseStatusEnum.SUBMITTED),
                    "old": CaseStatusEnum.get_text(CaseStatusEnum.APPLICANT_EDITING),
                }
            },
            case_status_audits,
        )
        html_to_pdf_func.assert_called_once()
        upload_bytes_file_func.assert_called_once()
コード例 #8
0
    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,
        )
コード例 #9
0
ファイル: automation.py プロジェクト: django-doctor/lite-api
                                    case=case).exists():
                                CaseAssignment(
                                    user=rule.user,
                                    queue=rule.queue,
                                    case=case).save(audit_user=system_user)
                        team_rule_tier = rule.tier
                        rules_have_been_applied = True
                        break

        # If no rules have been applied, we wish to either move to the next status, or break loop if keep_status is True
        #   or the next status is terminal
        if not rules_have_been_applied:
            next_status = get_next_status_in_workflow_sequence(case)
            if next_status and not next_status.is_terminal and not keep_status:
                old_status = case.status
                case.status = next_status
                case.save()
                audit_trail_service.create(
                    actor=system_user,
                    verb=AuditType.UPDATED_STATUS,
                    target=case,
                    payload={
                        "status": {
                            "new": CaseStatusEnum.get_text(next_status.status),
                            "old": CaseStatusEnum.get_text(old_status.status),
                        }
                    },
                )
            else:
                rules_have_been_applied = True
コード例 #10
0
ファイル: serializers.py プロジェクト: django-doctor/lite-api
 def get_status(self, instance):
     return {
         "key": instance.status.status,
         "value": CaseStatusEnum.get_text(instance.status.status)
     }