def test_state_after_first_review(self):
        record_manager = UserFactory(
            role__can_start_destruction=True, role__type=RoleTypeChoices.record_manager
        )
        process_owner = UserFactory(
            role__can_review_destruction=True, role__type=RoleTypeChoices.process_owner
        )
        archivist = UserFactory(
            role__can_review_destruction=True, role__type=RoleTypeChoices.archivist
        )

        destruction_list = DestructionListFactory.create(author=record_manager)

        DestructionListAssigneeFactory.create(
            assignee=process_owner, destruction_list=destruction_list, order=1
        )
        assignee = DestructionListAssigneeFactory.create(
            assignee=archivist, destruction_list=destruction_list, order=2
        )

        DestructionListReviewFactory.create(
            author=process_owner,
            status=ReviewStatus.approved,
            destruction_list=destruction_list,
        )

        destruction_list.assignee = assignee.assignee
        destruction_list.save()

        list_state = destruction_list.list_state()

        self.assertEqual("in_progress", list_state.value)
        self.assertEqual(2, destruction_list.total_reviewers())
        self.assertEqual(1, destruction_list.completed_reviewers())
    def test_retrieve_missing_zaak(self, m):
        self._set_up_services()
        self._set_up_mocks(m)

        user = UserFactory.create(
            username="******",
            password="******",
            email="*****@*****.**",
            role__can_start_destruction=True,
            role__can_review_destruction=True,
        )

        destruction_list = DestructionListFactory.create(author=user,
                                                         assignee=user)
        missing_zaak_url = f"{ZAKEN_ROOT}zaken/uuid-3"
        DestructionListItemFactory.create(destruction_list=destruction_list,
                                          zaak=missing_zaak_url)
        m.get(missing_zaak_url, status_code=404)

        url = reverse("destruction:fetch-list-items",
                      args=[destruction_list.id])

        self.client.force_login(user)
        response = self.client.get(url)

        self.assertEqual(200, response.status_code)
        self.assertIn("error", response.json())
    def setUpTestData(cls):
        AutomaticEmailFactory.create(
            type=EmailTypeChoices.review_required,
            body="Review is required!",
            subject="Review",
        )
        AutomaticEmailFactory.create(
            type=EmailTypeChoices.changes_required,
            body="Changes are required!",
            subject="Changes",
        )

        record_manager = RoleFactory.create(record_manager=True)
        process_owner = RoleFactory.create(process_owner=True)

        user_author = UserFactory.create(
            role=record_manager, email="*****@*****.**"
        )
        user_reviewer = UserFactory.create(
            role=process_owner, email="*****@*****.**"
        )

        destruction_list = DestructionListFactory.create(author=user_author)
        DestructionListAssigneeFactory.create(
            destruction_list=destruction_list, assignee=user_reviewer
        )

        cls.destruction_list = destruction_list
        cls.user_author = user_author
        cls.user_reviewer = user_reviewer
예제 #4
0
    def setUpTestData(cls):
        cls.record_manager = UserFactory(
            role__can_start_destruction=True, role__type=RoleTypeChoices.record_manager
        )
        cls.process_owner = UserFactory(
            role__can_review_destruction=True, role__type=RoleTypeChoices.process_owner
        )

        # List 1: In progress
        cls.dl_in_progress = DestructionListFactory.create(author=cls.record_manager)
        assignee = DestructionListAssigneeFactory.create(
            assignee=cls.process_owner, destruction_list=cls.dl_in_progress, order=1
        )
        cls.dl_in_progress.assignee = assignee.assignee
        cls.dl_in_progress.save()

        # List 2: Changes requested
        cls.dl_changes_required = DestructionListFactory.create(
            author=cls.record_manager
        )
        assignee = DestructionListAssigneeFactory.create(
            assignee=cls.record_manager, destruction_list=cls.dl_changes_required
        )
        cls.dl_changes_required.assignee = assignee.assignee
        cls.dl_changes_required.save()

        # List 3: Rejected
        cls.dl_rejected = DestructionListFactory.create(author=cls.record_manager)
        assignee = DestructionListAssigneeFactory.create(
            assignee=cls.record_manager, destruction_list=cls.dl_rejected
        )
        cls.dl_rejected.assignee = assignee.assignee
        cls.dl_rejected.save()

        # List 4: Approved
        cls.dl_approved = DestructionListFactory.create(author=cls.record_manager)
        cls.dl_approved.assignee = None
        cls.dl_approved.save()

        # List 5: Complete
        cls.dl_complete = DestructionListFactory.create(author=cls.record_manager)
        cls.dl_complete.process()
        cls.dl_complete.save()
        cls.dl_complete.complete()
        cls.dl_complete.save()
    def test_user_unauthenticated_cant_access(self, m):
        destruction_list = DestructionListFactory.create()
        url = reverse("destruction:fetch-list-items",
                      args=[destruction_list.id])

        response = self.client.get(url)

        self.assertEqual(302, response.status_code)
        self.assertEqual(f"/admin/login/?next={url}", response.url)
    def test_logs_from_right_list_are_shown(self):
        record_manager = UserFactory.create(
            role__type=RoleTypeChoices.record_manager)
        archivaris = UserFactory.create(role__type=RoleTypeChoices.archivist)

        destruction_list_1 = DestructionListFactory.create(
            author=record_manager, name="Incredible list 1")
        review_1 = DestructionListReviewFactory.create(
            destruction_list=destruction_list_1, author=archivaris)
        destruction_list_2 = DestructionListFactory.create(
            author=record_manager, name="Incredible list 2")
        review_2 = DestructionListReviewFactory.create(
            destruction_list=destruction_list_2, author=archivaris)

        TimelineLog.objects.create(
            content_object=destruction_list_1,
            template="destruction/logs/created.html",
            extra_data={"n_items": 3},
            user=record_manager,
        )
        TimelineLog.objects.create(
            content_object=review_1,
            template="destruction/logs/review_created.html",
            user=archivaris,
        )
        # These should not appear in the audit trail report, because they are not related to the right list
        TimelineLog.objects.create(
            content_object=destruction_list_2,
            template="destruction/logs/created.html",
            extra_data={"n_items": 3},
            user=record_manager,
        )
        TimelineLog.objects.create(
            content_object=review_2,
            template="destruction/logs/review_created.html",
            user=archivaris,
        )

        report = create_audittrail_report(destruction_list_1)
        html_report = document_fromstring(report)

        self.assertEqual(2, len(html_report.find_class("log-item")))
        self.assertIn("Incredible list 1", report)
        self.assertNotIn("Incredible list 2", report)
예제 #7
0
    def test_relation_between_report_and_destructionlist(
            self, m_vcs, m_zaaktype):
        destruction_list = DestructionListFactory.create(name="Winter cases")
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-1",
                "omschrijving": "Een zaak",
                "toelichting": "Bah",
                "startdatum": "2020-01-01",
                "einddatum": "2021-01-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-1",
                "verantwoordelijke_organisatie": "Nice organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nice result type",
                        "archiefactietermijn": "20 days",
                    }
                },
                "relevante_andere_zaken": [],
            },
        )
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-2",
                "omschrijving": "Een andere zaak",
                "toelichting": "Boh",
                "startdatum": "2020-02-01",
                "einddatum": "2021-03-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-2",
                "verantwoordelijke_organisatie": "Nice organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nice result type",
                        "archiefactietermijn": "20 days",
                    }
                },
                "relevante_andere_zaken": [],
            },
        )
        DestructionListReviewFactory.create(
            destruction_list=destruction_list,
            status=ReviewStatus.approved,
            text="What a magnificent list!",
        )

        report = create_destruction_report(destruction_list)

        # can't use refresh_from_db() because of django-fsm
        destruction_list = DestructionList.objects.get(id=destruction_list.id)

        self.assertEqual(1, destruction_list.destructionreport_set.count())
        self.assertEqual(report, destruction_list.destructionreport_set.get())
    def test_only_comments_from_archivaris_returned(self):
        archivaris = UserFactory.create(
            role__type=RoleTypeChoices.archivist,
            role__can_start_destruction=False,
            role__can_review_destruction=True,
            role__can_view_case_details=False,
        )
        process_owner = UserFactory.create(
            role__type=RoleTypeChoices.process_owner,
            role__can_start_destruction=False,
            role__can_review_destruction=True,
            role__can_view_case_details=True,
        )
        destruction_list = DestructionListFactory.create(
            status=ListStatus.processing)
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.failed,
            extra_zaak_data={
                "identificatie": "ZAAK-1",
                "omschrijving": "Een zaak",
                "toelichting": "Bah",
                "startdatum": "2020-01-01",
                "einddatum": "2021-01-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-1",
            },
        )
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-2",
                "omschrijving": "Een andere zaak",
                "toelichting": "",
                "startdatum": "2020-02-01",
                "einddatum": "2021-03-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-2",
            },
        )
        DestructionListReviewFactory.create(
            destruction_list=destruction_list,
            status=ReviewStatus.approved,
            author=archivaris,
            text="What a magnificent list!",
        )
        DestructionListReviewFactory.create(
            destruction_list=destruction_list,
            status=ReviewStatus.approved,
            author=process_owner,
            text="I am happy with this list!",
        )

        comment = get_destruction_list_archivaris_comments(destruction_list)

        self.assertEqual("What a magnificent list!", comment)
    def test_assignee_is_no_reviewer(self):
        role = RoleFactory.create(can_review_destruction=False)
        destruction_list = DestructionListFactory.create()
        reviewer = DestructionListAssigneeFactory.create(
            destruction_list=destruction_list, assignee__role=role)
        destruction_list.assignee = reviewer.assignee
        destruction_list.save()
        reviewer.assigned_on = timezone.make_aware(datetime(2021, 11, 12))
        reviewer.save()

        self.assertFalse(destruction_list.is_review_overdue)
    def test_failed_destruction_not_in_report_content(self, m_vcs, m_zaaktype):
        destruction_list = DestructionListFactory.create(
            status=ListStatus.processing,
            contains_sensitive_info=False,
        )
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.failed,
            extra_zaak_data={
                "identificatie": "ZAAK-1",
                "omschrijving": "Een zaak",
                "toelichting": "Bah",
                "startdatum": "2020-01-01",
                "einddatum": "2021-01-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-1",
                "verantwoordelijke_organisatie": "Nicer organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nicer result type",
                        "archiefactietermijn": "40 days",
                    }
                },
                "relevante_andere_zaken": [{
                    "url": "http://some.zaak"
                }],
            },
        )
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-2",
                "omschrijving": "Een andere zaak",
                "toelichting": "",
                "startdatum": "2020-02-01",
                "einddatum": "2021-03-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-2",
                "verantwoordelijke_organisatie": "Nice organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nice result type",
                        "archiefactietermijn": "20 days",
                    }
                },
                "relevante_andere_zaken": [],
            },
        )

        report_data = get_destruction_report_data(destruction_list)

        self.assertEqual(1, len(report_data))

        self.assertEqual("ZAAK-2", report_data[0]["identificatie"])
    def test_state_after_last_review(self):
        record_manager = UserFactory(
            role__can_start_destruction=True, role__type=RoleTypeChoices.record_manager
        )
        destruction_list = DestructionListFactory.create(author=record_manager)

        destruction_list.assignee = None
        destruction_list.save()

        list_state = destruction_list.list_state()

        self.assertEqual("approved", list_state.value)
    def test_returns_list_items_and_zaak_data(self, m):
        self._set_up_services()

        user = UserFactory.create(
            username="******",
            password="******",
            email="*****@*****.**",
            role__can_start_destruction=True,
            role__can_review_destruction=True,
        )

        destruction_list = DestructionListFactory.create(author=user,
                                                         assignee=user)
        DestructionListItemFactory.create(destruction_list=destruction_list,
                                          zaak=ZAAK_1["url"])
        DestructionListItemFactory.create(destruction_list=destruction_list,
                                          zaak=ZAAK_2["url"])

        self._set_up_mocks(m)

        url = reverse("destruction:fetch-list-items",
                      args=[destruction_list.id])

        self.client.force_login(user)
        response = self.client.get(url)

        self.assertEqual(200, response.status_code)

        response_data = response.json()

        self.assertIn("items", response_data)
        self.assertEqual(2, len(response_data["items"]))

        # Test first item (No related zaken, no process type)
        zaak_1_data = response_data["items"][0]["zaak"]
        self.assertEqual(f"{ZAKEN_ROOT}zaken/uuid-1", zaak_1_data["url"])
        self.assertEqual([], zaak_1_data["relevanteAndereZaken"])
        self.assertNotIn("processtype", zaak_1_data["zaaktype"])
        self.assertEqual("10 days", zaak_1_data["looptijd"])

        # Test second item (related zaken and process type)
        zaak_2_data = response_data["items"][1]["zaak"]
        self.assertEqual(f"{ZAKEN_ROOT}zaken/uuid-2", zaak_2_data["url"])
        self.assertEqual(
            zaak_2_data["relevanteAndereZaken"],
            [{
                "url": f"{ZAKEN_ROOT}zaken/uuid-3",
                "aardRelatie": "vervolg"
            }],
        )
        self.assertIn("processtype", zaak_2_data["zaaktype"])
    def test_zaakafhandelcomponent_link(self, m):
        self._set_up_services()

        config = ArchiveConfig.get_solo()
        config.link_to_zac = (
            "http://example.nl/{{ bronorganisatie }}/{{ identificatie }}/{{ uuid }}"
        )
        config.save()

        user = UserFactory.create(
            username="******",
            password="******",
            email="*****@*****.**",
            role__can_start_destruction=True,
            role__can_review_destruction=True,
        )

        destruction_list = DestructionListFactory.create(author=user,
                                                         assignee=user)
        DestructionListItemFactory.create(destruction_list=destruction_list,
                                          zaak=ZAAK_1["url"])
        DestructionListItemFactory.create(destruction_list=destruction_list,
                                          zaak=ZAAK_2["url"])

        self._set_up_mocks(m)

        url = reverse("destruction:fetch-list-items",
                      args=[destruction_list.id])

        self.client.force_login(user)
        response = self.client.get(url)

        self.assertEqual(200, response.status_code)

        response_data = response.json()

        self.assertIn("items", response_data)
        self.assertEqual(2, len(response_data["items"]))

        zaak_1_data = response_data["items"][0]["zaak"]
        self.assertIn("zac_link", zaak_1_data)
        self.assertEqual("http://example.nl/123456789/ZAAK-001/uuid-1",
                         zaak_1_data["zac_link"])

        zaak_2_data = response_data["items"][1]["zaak"]
        self.assertIn("zac_link", zaak_2_data)
        self.assertEqual("http://example.nl/987654321/ZAAK-002/uuid-2",
                         zaak_2_data["zac_link"])
    def test_destruction_report_data_with_sensitive_info(self):
        destruction_list = DestructionListFactory.create(
            name="Winter cases",
            contains_sensitive_info=True,
        )
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-1",
                "omschrijving": "Een zaak",
                "toelichting": "Bah",
                "startdatum": "2020-01-01",
                "einddatum": "2021-01-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-1",
                "verantwoordelijke_organisatie": "Nicer organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nicer result type",
                        "archiefactietermijn": "40 days",
                    }
                },
                "relevante_andere_zaken": [{
                    "url": "http://some.zaak"
                }],
            },
        )
        archivaris = UserFactory.create(
            role__type=RoleTypeChoices.archivist,
            role__can_start_destruction=False,
            role__can_review_destruction=True,
            role__can_view_case_details=False,
        )
        DestructionListReviewFactory.create(
            destruction_list=destruction_list,
            status=ReviewStatus.approved,
            author=archivaris,
            text="What a magnificent list!",
        )

        report_data = get_destruction_report_data(destruction_list)

        self.assertEqual(1, len(report_data))

        zaak_data = report_data[0]

        self.assertNotIn("omschrijving", zaak_data)
        self.assertNotIn("opmerkingen", zaak_data)
    def test_destruction_report_content_generation_without_toelichting(
            self, m_vcs, m_zaaktype):
        destruction_list = DestructionListFactory.create(
            contains_sensitive_info=False)
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-1",
                "omschrijving": "Een zaak",
                "startdatum": "2020-01-01",
                "einddatum": "2021-01-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-1",
                "verantwoordelijke_organisatie": "Nicer organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nicer result type",
                        "archiefactietermijn": "40 days",
                    }
                },
                "relevante_andere_zaken": [{
                    "url": "http://some.zaak"
                }],
            },
        )

        report_data = get_destruction_report_data(destruction_list)

        self.assertEqual(1, len(report_data))

        # Test sensitive info
        self.assertIn("omschrijving", report_data[0])
        self.assertIn("opmerkingen", report_data[0])

        # Test remaining info
        self.assertEqual("ZAAK-1", report_data[0]["identificatie"])
        self.assertEqual("Een zaak", report_data[0]["omschrijving"])
        self.assertEqual("366 days", report_data[0]["looptijd"])
        self.assertEqual("1", report_data[0]["vernietigings_categorie"])
        self.assertNotIn("toelichting", report_data[0])
        self.assertEqual("", report_data[0]["opmerkingen"])
        self.assertEqual("", report_data[0]["reactie_zorgdrager"])
        self.assertEqual("This is a zaaktype", report_data[0]["zaaktype"])
        self.assertEqual("40 days", report_data[0]["archiefactietermijn"])
        self.assertEqual("Nicer result type", report_data[0]["resultaattype"])
        self.assertEqual("Nicer organisation",
                         report_data[0]["verantwoordelijke_organisatie"])
        self.assertEqual("Yes", report_data[0]["relaties"])
    def test_logs_are_in_correct_order(self):
        record_manager = UserFactory.create(
            role__type=RoleTypeChoices.record_manager)
        archivaris = UserFactory.create(role__type=RoleTypeChoices.archivist)

        destruction_list = DestructionListFactory.create(author=record_manager)
        review = DestructionListReviewFactory.create(
            destruction_list=destruction_list, author=archivaris)

        with freeze_time("2012-01-14 12:00"):
            TimelineLog.objects.create(
                content_object=destruction_list,
                template="destruction/logs/created.html",
                extra_data={"n_items": 3},
                user=record_manager,
            )
        with freeze_time("2012-01-14 12:05"):
            TimelineLog.objects.create(
                content_object=review,
                template="destruction/logs/review_created.html",
                user=archivaris,
            )
        with freeze_time("2012-01-14 12:10"):
            TimelineLog.objects.create(
                content_object=destruction_list,
                template="destruction/logs/updated.html",
                extra_data={"n_items": 1},
                user=record_manager,
            )
        with freeze_time("2012-01-14 12:15"):
            TimelineLog.objects.create(
                content_object=destruction_list,
                template="destruction/logs/aborted.html",
                extra_data={"n_items": 3},
                user=record_manager,
            )

        report = create_audittrail_report(destruction_list)
        html_report = document_fromstring(report)

        self.assertEqual(4, len(html_report.find_class("log-item")))

        titles = html_report.find_class("log-item__title")
        times = [title.text_content() for title in titles]
        sorted_times = sorted(times)

        self.assertEqual(times, sorted_times)
    def test_no_sensitive_data_for_archivist(self, m):
        self._set_up_services()

        record_manager = UserFactory.create(
            role__can_start_destruction=True,
            role__type=RoleTypeChoices.record_manager,
        )
        archivist = UserFactory.create(
            role__can_review_destruction=True,
            role__type=RoleTypeChoices.archivist,
        )

        destruction_list = DestructionListFactory.create(
            author=record_manager,
            assignee=archivist,
            contains_sensitive_info=False,
        )
        DestructionListItemFactory.create(destruction_list=destruction_list,
                                          zaak=ZAAK_1["url"])
        DestructionListItemFactory.create(destruction_list=destruction_list,
                                          zaak=ZAAK_2["url"])

        DestructionListAssigneeFactory.create(
            destruction_list=destruction_list, assignee=archivist)

        self._set_up_mocks(m)

        url = reverse("destruction:fetch-list-items",
                      args=[destruction_list.id])

        self.client.force_login(archivist)
        response = self.client.get(url)

        self.assertEqual(200, response.status_code)

        response_data = response.json()

        self.assertIn("items", response_data)
        self.assertEqual(2, len(response_data["items"]))

        # Since the list does NOT contain sensitive data, the archivist can see it
        zaak_1_data = response_data["items"][0]["zaak"]
        self.assertIn("omschrijving", zaak_1_data)

        zaak_2_data = response_data["items"][1]["zaak"]
        self.assertIn("omschrijving", zaak_2_data)
    def test_sensitive_data_for_process_owner(self, m):
        self._set_up_services()

        record_manager = UserFactory.create(
            role__can_start_destruction=True,
            role__type=RoleTypeChoices.record_manager,
        )
        process_owner = UserFactory.create(
            role__can_review_destruction=True,
            role__type=RoleTypeChoices.process_owner,
        )

        destruction_list = DestructionListFactory.create(
            author=record_manager,
            assignee=process_owner,
            contains_sensitive_info=True,
        )
        DestructionListItemFactory.create(destruction_list=destruction_list,
                                          zaak=ZAAK_1["url"])
        DestructionListItemFactory.create(destruction_list=destruction_list,
                                          zaak=ZAAK_2["url"])

        DestructionListAssigneeFactory.create(
            destruction_list=destruction_list, assignee=process_owner)

        self._set_up_mocks(m)

        url = reverse("destruction:fetch-list-items",
                      args=[destruction_list.id])

        self.client.force_login(process_owner)
        response = self.client.get(url)

        self.assertEqual(200, response.status_code)

        response_data = response.json()

        self.assertIn("items", response_data)
        self.assertEqual(2, len(response_data["items"]))

        # Even if the list contains sensitive data, the process owner should be able to see it
        zaak_1_data = response_data["items"][0]["zaak"]
        self.assertIn("omschrijving", zaak_1_data)

        zaak_2_data = response_data["items"][1]["zaak"]
        self.assertIn("omschrijving", zaak_2_data)
예제 #19
0
    def test_report_creation_without_process_owner(self, m_vcs, m_zaaktype):
        destruction_list = DestructionListFactory.create(name="Winter cases")
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-1",
                "omschrijving": "Een zaak",
                "toelichting": "Bah",
                "startdatum": "2020-01-01",
                "einddatum": "2021-01-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-1",
                "verantwoordelijke_organisatie": "Nice organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nice result type",
                        "archiefactietermijn": "20 days",
                    }
                },
                "relevante_andere_zaken": [],
            },
        )
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-2",
                "omschrijving": "Een andere zaak",
                "toelichting": "",
                "startdatum": "2020-02-01",
                "einddatum": "2021-03-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-2",
                "verantwoordelijke_organisatie": "Nice organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nice result type",
                        "archiefactietermijn": "20 days",
                    }
                },
                "relevante_andere_zaken": [],
            },
        )

        report = create_destruction_report(destruction_list)

        self.assertEqual(None, report.process_owner)
    def test_state_after_destruction(self):
        process_owner = UserFactory.create(
            role__type=RoleTypeChoices.process_owner,
            role__can_review_destruction=True,
            role__can_view_case_details=True,
        )
        destruction_list = DestructionListFactory.create(name="Summer List",)
        DestructionListReviewFactory.create(
            author=process_owner,
            status=ReviewStatus.approved,
            destruction_list=destruction_list,
        )

        destruction_list.process()
        destruction_list.complete()
        destruction_list.save()

        list_state = destruction_list.list_state()

        self.assertEqual("finished", list_state.value)
    def test_state_after_rejection(self):
        record_manager = UserFactory(
            role__can_start_destruction=True, role__type=RoleTypeChoices.record_manager
        )
        archivist = UserFactory(
            role__can_review_destruction=True, role__type=RoleTypeChoices.archivist
        )

        destruction_list = DestructionListFactory.create(author=record_manager)

        DestructionListReviewFactory.create(
            author=archivist,
            status=ReviewStatus.rejected,
            destruction_list=destruction_list,
        )
        destruction_list.assignee = record_manager
        destruction_list.save()

        list_state = destruction_list.list_state()

        self.assertEqual("rejected", list_state.value)
    def test_state_after_creation(self):
        record_manager = UserFactory(
            role__can_start_destruction=True, role__type=RoleTypeChoices.record_manager
        )
        process_owner = UserFactory(
            role__can_review_destruction=True, role__type=RoleTypeChoices.process_owner
        )

        destruction_list = DestructionListFactory.create(author=record_manager)

        assignee = DestructionListAssigneeFactory.create(
            assignee=process_owner, destruction_list=destruction_list, order=1
        )
        destruction_list.assignee = assignee.assignee
        destruction_list.save()

        list_state = destruction_list.list_state()

        self.assertEqual("in_progress", list_state.value)
        self.assertEqual(1, destruction_list.total_reviewers())
        self.assertEqual(0, destruction_list.completed_reviewers())
    def test_destruction_report_data_without_sensitive_info(
            self, m_vcs, m_zaaktype):
        destruction_list = DestructionListFactory.create(
            name="Winter cases",
            contains_sensitive_info=False,
        )
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-1",
                "omschrijving": "Een zaak",
                "toelichting": "Bah",
                "startdatum": "2020-01-01",
                "einddatum": "2021-01-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-1",
                "verantwoordelijke_organisatie": "Nicer organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nicer result type",
                        "archiefactietermijn": "40 days",
                    }
                },
                "relevante_andere_zaken": [{
                    "url": "http://some.zaak"
                }],
            },
        )
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-2",
                "omschrijving": "Een andere zaak",
                "toelichting": "Boh",
                "startdatum": "2020-02-01",
                "einddatum": "2021-03-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-2",
                "verantwoordelijke_organisatie": "Nice organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nice result type",
                        "archiefactietermijn": "20 days",
                    }
                },
                "relevante_andere_zaken": [],
            },
        )
        archivaris = UserFactory.create(
            role__type=RoleTypeChoices.archivist,
            role__can_start_destruction=False,
            role__can_review_destruction=True,
            role__can_view_case_details=False,
        )
        DestructionListReviewFactory.create(
            destruction_list=destruction_list,
            status=ReviewStatus.approved,
            author=archivaris,
            text="What a magnificent list!",
        )

        report_data = get_destruction_report_data(destruction_list)

        self.assertEqual(2, len(report_data))

        # Test sensitive info
        self.assertIn("omschrijving", report_data[0])
        self.assertIn("opmerkingen", report_data[0])
        self.assertIn("omschrijving", report_data[1])
        self.assertIn("opmerkingen", report_data[1])

        # Test remaining info
        self.assertEqual("ZAAK-1", report_data[0]["identificatie"])
        self.assertEqual("Een zaak", report_data[0]["omschrijving"])
        self.assertEqual("366 days", report_data[0]["looptijd"])
        self.assertEqual("1", report_data[0]["vernietigings_categorie"])
        self.assertEqual("Bah", report_data[0]["toelichting"])
        self.assertEqual("What a magnificent list!",
                         report_data[0]["opmerkingen"])
        self.assertEqual("", report_data[0]["reactie_zorgdrager"])
        self.assertEqual("This is a zaaktype", report_data[0]["zaaktype"])
        self.assertEqual("40 days", report_data[0]["archiefactietermijn"])
        self.assertEqual("Nicer result type", report_data[0]["resultaattype"])
        self.assertEqual("Nicer organisation",
                         report_data[0]["verantwoordelijke_organisatie"])
        self.assertEqual("Yes", report_data[0]["relaties"])

        # Test remaining info
        self.assertEqual("ZAAK-2", report_data[1]["identificatie"])
        self.assertEqual("Een andere zaak", report_data[1]["omschrijving"])
        self.assertEqual("394 days", report_data[1]["looptijd"])
        self.assertEqual("1", report_data[1]["vernietigings_categorie"])
        self.assertEqual("Boh", report_data[1]["toelichting"])
        self.assertEqual("What a magnificent list!",
                         report_data[1]["opmerkingen"])
        self.assertEqual("", report_data[1]["reactie_zorgdrager"])
        self.assertEqual("This is a zaaktype", report_data[1]["zaaktype"])
        self.assertEqual("20 days", report_data[1]["archiefactietermijn"])
        self.assertEqual("Nice result type", report_data[1]["resultaattype"])
        self.assertEqual("Nice organisation",
                         report_data[1]["verantwoordelijke_organisatie"])
        self.assertEqual("No", report_data[1]["relaties"])
    def test_no_reviewer_assigned(self):
        destruction_list = DestructionListFactory.create()
        destruction_list.assignee = None
        destruction_list.save()

        self.assertFalse(destruction_list.is_review_overdue)
예제 #25
0
    def test_create_csv_content_without_sensitive_info(self, m_vcs,
                                                       m_zaaktype):
        destruction_list = DestructionListFactory.create(
            name="Winter cases",
            contains_sensitive_info=False,
        )
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-1",
                "omschrijving": "Een zaak",
                "toelichting": "Bah",
                "startdatum": "2020-01-01",
                "einddatum": "2021-01-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-1",
                "verantwoordelijke_organisatie": "Nicer organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nicer result type",
                        "archiefactietermijn": "40 days",
                    }
                },
                "relevante_andere_zaken": [{
                    "url": "http://some.zaak"
                }],
            },
        )
        archivaris = UserFactory.create(
            role__type=RoleTypeChoices.archivist,
            role__can_start_destruction=False,
            role__can_review_destruction=True,
            role__can_view_case_details=False,
        )
        DestructionListReviewFactory.create(
            destruction_list=destruction_list,
            status=ReviewStatus.approved,
            author=archivaris,
            text="What a magnificent list!",
        )

        zaken_data = get_destruction_report_data(destruction_list)
        html_content = create_csv_report_content(
            zaken_data, destruction_list.contains_sensitive_info)

        html_content.seek(0)

        lines = [line for line in html_content.readlines()]

        expected_header_row = [
            "Unique ID",
            "Description",
            "Duration",
            "Destruction category Selectielijst",
            "Explanation",
            "Remarks SAD",
            "Reaction caretaker",
            "Case type",
            "Archive action period",
            "Result type",
            "Organisation responsible",
            "Relations",
        ]
        expected_zaak_row = [
            "ZAAK-1",
            "Een zaak",
            "366 days",
            "1",
            "Bah",
            "What a magnificent list!",
            "",
            "This is a zaaktype",
            "40 days",
            "Nicer result type",
            "Nicer organisation",
            "Yes",
        ]

        self.assertEqual(2, len(lines))
        for header in expected_header_row:
            self.assertIn(header, lines[0])

        for zaak in expected_zaak_row:
            self.assertIn(zaak, lines[1])
예제 #26
0
    def test_invalid_report_type(self, m_vcs, m_zaaktype):
        process_owner = UserFactory.create(
            role__type=RoleTypeChoices.process_owner,
            role__can_start_destruction=False,
            role__can_review_destruction=True,
            role__can_view_case_details=True,
        )
        destruction_list = DestructionListFactory.create(
            name="Winter cases", contains_sensitive_info=False)
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-1",
                "omschrijving": "Een zaak",
                "toelichting": "Bah",
                "startdatum": "2020-01-01",
                "einddatum": "2021-01-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-1",
                "verantwoordelijke_organisatie": "Nice organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nice result type",
                        "archiefactietermijn": "20 days",
                    }
                },
                "relevante_andere_zaken": [],
            },
        )
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-2",
                "omschrijving": "Een andere zaak",
                "toelichting": "Boh",
                "startdatum": "2020-02-01",
                "einddatum": "2021-03-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-2",
                "verantwoordelijke_organisatie": "Nice organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nice result type",
                        "archiefactietermijn": "20 days",
                    }
                },
                "relevante_andere_zaken": [],
            },
        )
        DestructionListReviewFactory.create(
            destruction_list=destruction_list,
            status=ReviewStatus.approved,
            author=process_owner,
            text="What a magnificent list!",
        )

        report = create_destruction_report(destruction_list)

        self.assertEqual(process_owner, report.process_owner)
        self.assertEqual(
            "Declaration of destruction - Winter cases (2021-05-05)",
            report.title)

        self.client.force_login(process_owner)
        response = self.client.get(reverse("report:download-report",
                                           args=[report.pk]),
                                   data={"type": "GNE"})

        self.assertEqual(400, response.status_code)
예제 #27
0
    def test_private_media_is_not_accessible(self, m_vcs, m_zaaktype):
        process_owner = UserFactory.create(
            role__type=RoleTypeChoices.process_owner,
            role__can_start_destruction=False,
            role__can_review_destruction=True,
            role__can_view_case_details=True,
        )
        destruction_list = DestructionListFactory.create(name="Winter cases")
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-1",
                "omschrijving": "Een zaak",
                "toelichting": "Bah",
                "startdatum": "2020-01-01",
                "einddatum": "2021-01-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-1",
                "verantwoordelijke_organisatie": "Nice organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nice result type",
                        "archiefactietermijn": "20 days",
                    }
                },
                "relevante_andere_zaken": [],
            },
        )
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-2",
                "omschrijving": "Een andere zaak",
                "toelichting": "",
                "startdatum": "2020-02-01",
                "einddatum": "2021-03-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-2",
                "verantwoordelijke_organisatie": "Nice organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nice result type",
                        "archiefactietermijn": "20 days",
                    }
                },
                "relevante_andere_zaken": [],
            },
        )
        DestructionListReviewFactory.create(
            destruction_list=destruction_list,
            status=ReviewStatus.approved,
            author=process_owner,
            text="What a magnificent list!",
        )

        report = create_destruction_report(destruction_list)

        response_csv = self.client.get(report.content_csv.url)

        self.assertEqual(404, response_csv.status_code)

        response_pdf = self.client.get(report.content_pdf.url)

        self.assertEqual(404, response_pdf.status_code)
예제 #28
0
    def test_create_html_content_without_sensitive_info(
            self, m_vcs, m_zaaktype):
        destruction_list = DestructionListFactory.create(
            name="Winter cases",
            contains_sensitive_info=False,
        )
        DestructionListItemFactory.create(
            destruction_list=destruction_list,
            status=ListItemStatus.destroyed,
            extra_zaak_data={
                "identificatie": "ZAAK-1",
                "omschrijving": "Een zaak",
                "toelichting": "Bah",
                "startdatum": "2020-01-01",
                "einddatum": "2021-01-01",
                "zaaktype": "https://oz.nl/catalogi/api/v1/zaaktypen/uuid-1",
                "verantwoordelijke_organisatie": "Nicer organisation",
                "resultaat": {
                    "resultaattype": {
                        "omschrijving": "Nicer result type",
                        "archiefactietermijn": "40 days",
                    }
                },
                "relevante_andere_zaken": [{
                    "url": "http://some.zaak"
                }],
            },
        )
        archivaris = UserFactory.create(
            role__type=RoleTypeChoices.archivist,
            role__can_start_destruction=False,
            role__can_review_destruction=True,
            role__can_view_case_details=False,
        )
        DestructionListReviewFactory.create(
            destruction_list=destruction_list,
            status=ReviewStatus.approved,
            author=archivaris,
            text="What a magnificent list!",
        )

        zaken_data = get_destruction_report_data(destruction_list)
        html_content = create_html_report_content(
            zaken_data, destruction_list.contains_sensitive_info)

        expected_html_nodes = [
            "<th>Unique ID</th>",
            "<th>Description</th>",
            "<th>Duration</th>",
            "<th>Destruction category Selectielijst</th>",
            "<th>Explanation</th>",
            "<th>Reaction caretaker</th>",
            "<th>Remarks SAD</th>",
            "<th>Case type</th>",
            "<th>Archive action period</th>",
            "<th>Result type</th>",
            "<th>Organisation responsible</th>",
            "<th>Relations</th>",
            "<td>Een zaak</td>",
            "<td>ZAAK-1</td>",
            "<td>What a magnificent list!</td>",
            "<td>366 days</td>",
            "<td>1</td>",
            "<td>Bah</td>",
            "<td></td>",
            "<td>This is a zaaktype</td>",
            "<td>40 days</td>",
            "<td>Nicer result type</td>",
            "<td>Nicer organisation</td>",
            "<td>Yes</td>",
        ]

        for node in expected_html_nodes:
            self.assertIn(node, html_content)
    def test_logs_contain_comments(self):
        record_manager = UserFactory.create(
            role__type=RoleTypeChoices.record_manager)
        archivaris = UserFactory.create(role__type=RoleTypeChoices.archivist)

        destruction_list = DestructionListFactory.create(author=record_manager)
        review_1 = DestructionListReviewFactory.create(
            destruction_list=destruction_list,
            author=archivaris,
            text="This is a comment for the author.",
        )
        author_comment = DestructionListReviewComment.objects.create(
            text="This is a comment for the reviewer.", review=review_1)

        review_2 = DestructionListReviewFactory.create(
            destruction_list=destruction_list, author=archivaris, text="")

        TimelineLog.objects.create(
            content_object=destruction_list,
            template="destruction/logs/created.html",
            extra_data={"n_items": 3},
            user=record_manager,
        )
        TimelineLog.objects.create(
            content_object=review_1,
            template="destruction/logs/review_created.html",
            user=archivaris,
            extra_data={
                "n_items": 1,
                "text": review_1.text
            },
        )
        TimelineLog.objects.create(
            content_object=destruction_list,
            template="destruction/logs/updated.html",
            user=record_manager,
            extra_data={
                "n_items": 1,
                "text": author_comment.text
            },
        )
        TimelineLog.objects.create(
            content_object=review_2,
            template="destruction/logs/review_created.html",
            user=archivaris,
            extra_data={
                "n_items": 1,
                "text": review_2.text
            },
        )

        report = create_audittrail_report(destruction_list)
        html_report = document_fromstring(report)

        self.assertEqual(4, len(html_report.find_class("log-item")))

        # The second review should not have this tag, because the review text was empty
        self.assertEqual(1,
                         len(html_report.find_class("log-item__review-text")))
        self.assertIn("This is a comment for the author.", report)
        self.assertEqual(
            1, len(html_report.find_class("log-item__author-comment")))
        self.assertIn("This is a comment for the reviewer.", report)