From 4e9893186b51ece16a00c5e36c737e247d2f11d9 Mon Sep 17 00:00:00 2001 From: Paul Schilling Date: Thu, 21 Dec 2023 10:19:40 +0100 Subject: [PATCH] [#1963] Sort documents in case detail view --- src/open_inwoner/cms/cases/tests/test_htmx.py | 11 +- src/open_inwoner/cms/cases/views/status.py | 15 +- .../openzaak/tests/test_case_detail.py | 163 +++++++++++++++++- 3 files changed, 174 insertions(+), 15 deletions(-) diff --git a/src/open_inwoner/cms/cases/tests/test_htmx.py b/src/open_inwoner/cms/cases/tests/test_htmx.py index ec641c37ab..a5199229fc 100644 --- a/src/open_inwoner/cms/cases/tests/test_htmx.py +++ b/src/open_inwoner/cms/cases/tests/test_htmx.py @@ -202,6 +202,7 @@ def setUp(self) -> None: url=f"{ZAKEN_ROOT}zaakinformatieobjecten/e55153aa-ad2c-4a07-ae75-15add57d6", informatieobject=f"{DOCUMENTEN_ROOT}enkelvoudiginformatieobjecten/014c38fe-b010-4412-881c-3000032fb812", zaak=self.zaak["url"], + registratiedatum="2021-01-12", ) self.informatie_object_type = generate_oas_component( "ztc", @@ -243,6 +244,7 @@ def setUp(self) -> None: url=f"{ZAKEN_ROOT}zaakinformatieobjecten/48599f76-b524-48e8-be5a-6fc47288c9bf", informatieobject=f"{DOCUMENTEN_ROOT}enkelvoudiginformatieobjecten/48599f76-b524-48e8-be5a-6fc47288c9bf", zaak=self.zaak["url"], + registratiedatum="2022-01-12", ) self.uploaded_zaak_informatie_object_content = "test56789".encode("utf8") self.uploaded_informatie_object = generate_oas_component( @@ -433,7 +435,9 @@ def test_cases(self, m): ) # check case is visible - expect(page.get_by_text(self.zaak["identificatie"])).to_be_visible() + expect(page.get_by_text(self.zaak["identificatie"])).to_be_visible( + timeout=100_000 + ) # check documents show documents = page.locator(".file-list").get_by_role("listitem") @@ -466,7 +470,7 @@ def test_cases(self, m): # check for new file expect(documents).to_have_count(2) - uploaded_doc = documents.nth(1) + uploaded_doc = documents.nth(0) expect(uploaded_doc).to_contain_text("uploaded_test_file") expect(uploaded_doc).to_contain_text("(txt, 9 bytes)") @@ -523,6 +527,7 @@ def mock_list(request, context): url=f"{ZAKEN_ROOT}zaakinformatieobjecten/e55153aa-ad2c-4a07-ae75-15add57d6", informatieobject=upload["url"], zaak=self.zaak["url"], + registratiedatum="2021-01-12", ) for upload in uploads ] @@ -616,8 +621,8 @@ def mock_upload(request, context): # Check that the case does now have two uploaded documents. expect(notification_list_items).to_have_count(2) - expect(notification_list_items.first).to_contain_text("document_1.txt") expect(notification_list_items.last).to_contain_text("document_two.pdf") + expect(notification_list_items.first).to_contain_text("document_1.txt") expect(file_list_items).to_have_count(2) expect(file_list_items.first).to_contain_text("document_1") expect(file_list_items.first).to_contain_text("(txt, 9 bytes)") diff --git a/src/open_inwoner/cms/cases/views/status.py b/src/open_inwoner/cms/cases/views/status.py index 328fc9f90c..f858c27eff 100644 --- a/src/open_inwoner/cms/cases/views/status.py +++ b/src/open_inwoner/cms/cases/views/status.py @@ -442,7 +442,7 @@ def get_case_document_files(case: Zaak) -> List[SimpleFile]: # restructure into something understood by the FileList template tag documents.append( SimpleFile( - name=info_obj.titel, + name=getattr(info_obj, "titel", None), size=info_obj.bestandsomvang, url=reverse( "cases:document_download", @@ -451,11 +451,20 @@ def get_case_document_files(case: Zaak) -> List[SimpleFile]: "info_id": info_obj.uuid, }, ), - created=case_info_obj.registratiedatum, + created=getattr(case_info_obj, "registratiedatum", None), ) ) - return documents + # `registratiedatum` and `titel` should be present, but not guaranteed by schema + try: + return sorted(documents, key=lambda doc: doc.created, reverse=True) + except TypeError: + try: + return sorted( + documents, key=lambda doc: doc.name + ) # order ascending b/c alphabetical + except TypeError: + return documents def get_form_kwargs(self): kwargs = super().get_form_kwargs() diff --git a/src/open_inwoner/openzaak/tests/test_case_detail.py b/src/open_inwoner/openzaak/tests/test_case_detail.py index a5e4a0c415..213989cb6e 100644 --- a/src/open_inwoner/openzaak/tests/test_case_detail.py +++ b/src/open_inwoner/openzaak/tests/test_case_detail.py @@ -293,10 +293,32 @@ def setUpTestData(cls): informatieobject=f"{DOCUMENTEN_ROOT}enkelvoudiginformatieobjecten/014c38fe-b010-4412-881c-3000032fb812", zaak=cls.zaak["url"], aardRelatieWeergave="some content", - titel="", + titel="info object 1", beschrijving="", registratiedatum="2021-01-12", ) + cls.zaak_informatie_object_2 = generate_oas_component( + "zrc", + "schemas/ZaakInformatieObject", + url=f"{ZAKEN_ROOT}zaakinformatieobjecten/e55153aa-ad2c-4a07-ae75-15add57d7", + informatieobject=f"{DOCUMENTEN_ROOT}enkelvoudiginformatieobjecten/015c38fe-b010-4412-881c-3000032fb812", + zaak=cls.zaak["url"], + aardRelatieWeergave="some content", + titel="info object 2", + beschrijving="", + registratiedatum="2021-02-12", + ) + # informatie_object without registratiedatum + cls.zaak_informatie_object_no_date = generate_oas_component( + "zrc", + "schemas/ZaakInformatieObject", + url=f"{ZAKEN_ROOT}zaakinformatieobjecten/e55153aa-ad2c-4a07-ae75-15add57d7", + informatieobject=f"{DOCUMENTEN_ROOT}enkelvoudiginformatieobjecten/016c38fe-b010-4412-881c-3000032fb812", + zaak=cls.zaak["url"], + aardRelatieWeergave="some content", + titel="info object 3", + beschrijving="", + ) cls.informatie_object_type = generate_oas_component( "ztc", "schemas/InformatieObjectType", @@ -329,6 +351,32 @@ def setUpTestData(cls): titel="uploaded_document_title.txt", bestandsomvang=123, ) + cls.informatie_object_2 = generate_oas_component( + "drc", + "schemas/EnkelvoudigInformatieObject", + uuid="015c38fe-b010-4412-881c-3000032fb812", + url=cls.zaak_informatie_object_2["informatieobject"], + inhoud=f"{DOCUMENTEN_ROOT}enkelvoudiginformatieobjecten/015c38fe-b010-4412-881c-3000032fb812/download", + informatieobjecttype=cls.informatie_object_type["url"], + status="definitief", + vertrouwelijkheidaanduiding=VertrouwelijkheidsAanduidingen.openbaar, + bestandsnaam="uploaded_document.txt", + titel="another_document_title.txt", + bestandsomvang=123, + ) + cls.informatie_object_no_date = generate_oas_component( + "drc", + "schemas/EnkelvoudigInformatieObject", + uuid="015c38fe-b010-4412-881c-3000032fb812", + url=cls.zaak_informatie_object_no_date["informatieobject"], + inhoud=f"{DOCUMENTEN_ROOT}enkelvoudiginformatieobjecten/016c38fe-b010-4412-881c-3000032fb812/download", + informatieobjecttype=cls.informatie_object_type["url"], + status="definitief", + vertrouwelijkheidaanduiding=VertrouwelijkheidsAanduidingen.openbaar, + bestandsnaam="uploaded_document.txt", + titel="yet_another_document_title.txt", + bestandsomvang=123, + ) cls.uploaded_informatie_object = generate_oas_component( "drc", "schemas/EnkelvoudigInformatieObject", @@ -379,6 +427,29 @@ def setUpTestData(cls): ), created=datetime.datetime(2021, 1, 12, 0, 0, 0), ) + cls.informatie_object_file_2 = SimpleFile( + name="another_document_title.txt", + size=123, + url=reverse( + "cases:document_download", + kwargs={ + "object_id": cls.zaak["uuid"], + "info_id": cls.informatie_object_2["uuid"], + }, + ), + created=datetime.datetime(2021, 2, 12, 0, 0, 0), + ) + cls.informatie_object_file_no_date = SimpleFile( + name="yet_another_document_title.txt", + size=123, + url=reverse( + "cases:document_download", + kwargs={ + "object_id": cls.zaak["uuid"], + "info_id": cls.informatie_object_no_date["uuid"], + }, + ), + ) def _setUpOASMocks(self, m): mock_service_oas_get(m, ZAKEN_ROOT, "zrc") @@ -400,6 +471,7 @@ def _setUpMocks(self, m, use_eindstatus=True): self.zaaktype, self.informatie_object_type, self.informatie_object, + self.informatie_object_2, self.informatie_object_invisible, self.zaaktype_informatie_object_type, self.status_type_new, @@ -411,11 +483,18 @@ def _setUpMocks(self, m, use_eindstatus=True): m.post( f"{ZAKEN_ROOT}zaakinformatieobjecten", status_code=201, - json=self.zaak_informatie_object, + json=[ + self.zaak_informatie_object, + self.zaak_informatie_object_2, + ], ) m.get( f"{ZAKEN_ROOT}zaakinformatieobjecten?zaak={self.zaak['url']}", - json=[self.zaak_informatie_object, self.zaak_informatie_object_invisible], + json=[ + self.zaak_informatie_object, + self.zaak_informatie_object_2, + self.zaak_informatie_object_invisible, + ], ) m.get( f"{ZAKEN_ROOT}zaakinformatieobjecten?zaak={self.zaak_eherkenning['url']}", @@ -534,8 +613,11 @@ def test_status_is_retrieved_when_user_logged_in_via_digid(self, m): ], "second_status_preview": None, "end_statustype_data": None, - # only one visible information object - "documents": [self.informatie_object_file], + # only two visible information objects + "documents": [ + self.informatie_object_file_2, + self.informatie_object_file, + ], "initiator": "Foo Bar van der Bazz", "result": "resultaat toelichting", "result_description": "", @@ -611,7 +693,10 @@ def test_pass_endstatus_type_data_if_endstatus_not_reached(self, m): "call_to_action_text": "Click me", }, # only one visible information object - "documents": [self.informatie_object_file], + "documents": [ + self.informatie_object_file_2, + self.informatie_object_file, + ], "initiator": "Foo Bar van der Bazz", "result": "resultaat toelichting", "result_description": "", @@ -680,6 +765,66 @@ def test_second_status_preview(self, m): res = detail_view.get_second_status_preview(status_types) self.assertEqual(res, result) + def test_document_ordering_by_name(self, m): + """ + Assert that case documents are sorted by name/title if sorting by date does not work + """ + self.maxDiff = None + self._setUpMocks(m) + + ZaakTypeStatusTypeConfigFactory.create( + statustype_url=self.status_type_new["url"], + status_indicator=StatusIndicators.warning, + status_indicator_text="foo", + ) + ZaakTypeStatusTypeConfigFactory.create( + statustype_url=self.status_type_finish["url"], + status_indicator=StatusIndicators.success, + status_indicator_text="bar", + call_to_action_url="https://www.example.com", + call_to_action_text="Click me", + ) + + # install mocks with additional case documents + m.get(self.informatie_object["url"], json=self.informatie_object) + m.get(self.informatie_object_2["url"], json=self.informatie_object_2) + m.get( + self.informatie_object_no_date["url"], json=self.informatie_object_no_date + ) + + m.post( + f"{ZAKEN_ROOT}zaakinformatieobjecten", + status_code=201, + json=[ + self.zaak_informatie_object, + self.zaak_informatie_object_2, + self.zaak_informatie_object_no_date, + ], + ) + m.get( + f"{ZAKEN_ROOT}zaakinformatieobjecten?zaak={self.zaak['url']}", + json=[ + self.zaak_informatie_object, + self.zaak_informatie_object_2, + self.zaak_informatie_object_no_date, + self.zaak_informatie_object_invisible, + ], + ) + + status_new_obj, status_finish_obj = factory( + Status, [self.status_new, self.status_finish] + ) + status_new_obj.statustype = factory(StatusType, self.status_type_new) + status_finish_obj.statustype = factory(StatusType, self.status_type_finish) + + response = self.app.get(self.case_detail_url, user=self.user) + + documents = response.context.get("case")["documents"] + + self.assertEqual(documents[0].name, "another_document_title.txt") + self.assertEqual(documents[1].name, "uploaded_document_title.txt") + self.assertEqual(documents[2].name, "yet_another_document_title.txt") + @freeze_time("2021-01-12 17:00:00") def test_new_docs(self, m): self._setUpMocks(m) @@ -761,11 +906,11 @@ def test_case_io_objects_are_retrieved_when_user_logged_in_via_digid(self, m): response = self.app.get(self.case_detail_url, user=self.user) documents = response.context.get("case", {}).get("documents") - self.assertEquals(len(documents), 1) + self.assertEquals(len(documents), 2) self.assertEquals( documents, - # only one visible information object - [self.informatie_object_file], + # only two visible information objects, newest first + [self.informatie_object_file_2, self.informatie_object_file], ) def test_user_is_redirected_to_root_when_not_logged_in_via_digid(self, m):