From 55cd9c4c4d7adac947f7f7132942e808d348967a Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Mon, 13 May 2024 16:28:28 +0200 Subject: [PATCH 1/6] :sparkles: [#15] Expand info of zaaktype and resultaat --- ..._alter_zaak_resultaat_and_zaak_zaaktype.py | 31 +++++++++++++++++++ backend/src/openarchiefbeheer/zaken/models.py | 4 +-- backend/src/openarchiefbeheer/zaken/tasks.py | 6 ++-- backend/src/openarchiefbeheer/zaken/utils.py | 23 ++++++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 backend/src/openarchiefbeheer/zaken/migrations/0002_alter_zaak_resultaat_and_zaak_zaaktype.py diff --git a/backend/src/openarchiefbeheer/zaken/migrations/0002_alter_zaak_resultaat_and_zaak_zaaktype.py b/backend/src/openarchiefbeheer/zaken/migrations/0002_alter_zaak_resultaat_and_zaak_zaaktype.py new file mode 100644 index 00000000..8145ed24 --- /dev/null +++ b/backend/src/openarchiefbeheer/zaken/migrations/0002_alter_zaak_resultaat_and_zaak_zaaktype.py @@ -0,0 +1,31 @@ +# Generated by Django 4.2.11 on 2024-05-13 14:11 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("zaken", "0001_initial"), + ] + + operations = [ + migrations.RemoveField( + model_name="zaak", + name="resultaat", + ), + migrations.RemoveField( + model_name="zaak", + name="zaaktype", + ), + migrations.AddField( + model_name="zaak", + name="resultaat", + field=models.JSONField(blank=True, null=True, verbose_name="resultaat"), + ), + migrations.AddField( + model_name="zaak", + name="zaaktype", + field=models.JSONField(blank=True, null=True, verbose_name="zaaktype"), + ), + ] diff --git a/backend/src/openarchiefbeheer/zaken/models.py b/backend/src/openarchiefbeheer/zaken/models.py index 1822edaa..c6a26375 100644 --- a/backend/src/openarchiefbeheer/zaken/models.py +++ b/backend/src/openarchiefbeheer/zaken/models.py @@ -10,7 +10,7 @@ class Zaak(models.Model): models.URLField("rollen", max_length=1000, blank=True), null=True, blank=True ) status = models.URLField("status", max_length=1000, blank=True, null=True) - zaaktype = models.URLField("zaaktype", max_length=1000) + zaaktype = models.JSONField("zaaktype", blank=True, null=True) deelzaken = ArrayField( models.URLField("deelzaken", max_length=1000, blank=True), null=True, @@ -19,7 +19,7 @@ class Zaak(models.Model): einddatum = models.DateField("einddatum", blank=True, null=True) hoofdzaak = models.URLField("hoofdzaak", max_length=1000, blank=True, null=True) kenmerken = models.JSONField("kenmerken", blank=True, null=True) - resultaat = models.URLField("resultaat", max_length=1000, blank=True, null=True) + resultaat = models.JSONField("resultaat", blank=True, null=True) startdatum = models.DateField("startdatum") verlenging = models.JSONField("verlenging", blank=True, null=True) opschorting = models.JSONField("opschorting", blank=True, null=True) diff --git a/backend/src/openarchiefbeheer/zaken/tasks.py b/backend/src/openarchiefbeheer/zaken/tasks.py index 3b158720..19f665d0 100644 --- a/backend/src/openarchiefbeheer/zaken/tasks.py +++ b/backend/src/openarchiefbeheer/zaken/tasks.py @@ -8,7 +8,7 @@ from .api.serializers import ZaakSerializer from .models import Zaak -from .utils import pagination_helper +from .utils import pagination_helper, process_expanded_data @app.task @@ -20,6 +20,7 @@ def retrieve_and_cache_zaken_from_openzaak() -> None: response = zrc_client.get( "zaken", headers={"Accept-Crs": "EPSG:4326"}, + params={"expand": "resultaat,resultaat.resultaattype,zaaktype"}, ) response.raise_for_status() @@ -30,6 +31,7 @@ def retrieve_and_cache_zaken_from_openzaak() -> None: Zaak.objects.all().delete() for data in data_iterator: - serializer = ZaakSerializer(data=data["results"], many=True) + zaken = process_expanded_data(data["results"]) + serializer = ZaakSerializer(data=zaken, many=True) serializer.is_valid(raise_exception=True) serializer.save() diff --git a/backend/src/openarchiefbeheer/zaken/utils.py b/backend/src/openarchiefbeheer/zaken/utils.py index 15496a00..63d95a21 100644 --- a/backend/src/openarchiefbeheer/zaken/utils.py +++ b/backend/src/openarchiefbeheer/zaken/utils.py @@ -3,6 +3,7 @@ from ape_pie import APIClient from djangorestframework_camel_case.parser import CamelCaseJSONParser from djangorestframework_camel_case.util import underscoreize +from zgw_consumers.concurrent import parallel from zgw_consumers.utils import PaginatedResponseData @@ -22,3 +23,25 @@ def _iter( yield from _iter(data) return _iter(paginated_response) + + +def process_expanded_data(zaken: list[dict]) -> list[dict]: + def _format_expanded_data(zaak: dict) -> dict: + if "_expand" not in zaak: + return zaak + + extra_data = zaak["_expand"] + + zaak["zaaktype"] = extra_data["zaaktype"] + if "resultaat" in extra_data: + resultaat = extra_data["resultaat"] + resultaat_extra_data = resultaat.pop("_expand") + resultaat["resultaattype"] = resultaat_extra_data["resultaattype"] + zaak["resultaat"] = resultaat + + return zaak + + with parallel() as executor: + zaken_with_expanded_info = list(executor.map(_format_expanded_data, zaken)) + + return zaken_with_expanded_info From 5623c22a0aace84eb06c73202409b88ead2d0368 Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Mon, 13 May 2024 16:29:22 +0200 Subject: [PATCH 2/6] :white_check_mark: Test expanding zaaktype/resultaat --- .../zaken/tests/test_tasks.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/backend/src/openarchiefbeheer/zaken/tests/test_tasks.py b/backend/src/openarchiefbeheer/zaken/tests/test_tasks.py index ac5ac228..cd2b9f33 100644 --- a/backend/src/openarchiefbeheer/zaken/tests/test_tasks.py +++ b/backend/src/openarchiefbeheer/zaken/tests/test_tasks.py @@ -14,10 +14,26 @@ "identificatie": "ZAAK-01", "url": "http://zaken-api.nl/zaken/api/v1/zaken/75f4c682-1e16-45ea-8f78-99b4474986ac", "uuid": "75f4c682-1e16-45ea-8f78-99b4474986ac", + "resultaat": "http://zaken-api.nl/zaken/api/v1/resultaten/ffaa6410-0319-4a6b-b65a-fb209798e81c", "startdatum": "2020-02-01", "zaaktype": "http://catalogue-api.nl/zaaktypen/111-111-111", "bronorganisatie": "000000000", "verantwoordelijkeOrganisatie": "000000000", + "_expand": { + "zaaktype": { + "url": "http://catalogue-api.nl/zaaktypen/111-111-111", + }, + "resultaat": { + "url": "http://zaken-api.nl/zaken/api/v1/resultaten/ffaa6410-0319-4a6b-b65a-fb209798e81c", + "resultaattype": "http://catalogue-api.nl/catalogi/api/v1/resultaattypen/bd84c463-fa65-46ef-8a9e-dd887e005aea", + "toelichting": "Test result", + "_expand": { + "resultaattype": { + "url": "http://catalogue-api.nl/catalogi/api/v1/resultaattypen/bd84c463-fa65-46ef-8a9e-dd887e005aea", + }, + }, + }, + }, }, { "identificatie": "ZAAK-02", @@ -27,6 +43,11 @@ "zaaktype": "http://catalogue-api.nl/zaaktypen/111-111-111", "bronorganisatie": "000000000", "verantwoordelijkeOrganisatie": "000000000", + "_expand": { + "zaaktype": { + "url": "http://catalogue-api.nl/zaaktypen/111-111-111", + }, + }, }, ], "count": 2, @@ -44,6 +65,11 @@ "zaaktype": "http://catalogue-api.nl/zaaktypen/111-111-111", "bronorganisatie": "000000000", "verantwoordelijkeOrganisatie": "000000000", + "_expand": { + "zaaktype": { + "url": "http://catalogue-api.nl/zaaktypen/111-111-111", + }, + }, }, { "identificatie": "ZAAK-04", @@ -53,6 +79,11 @@ "zaaktype": "http://catalogue-api.nl/zaaktypen/111-111-111", "bronorganisatie": "000000000", "verantwoordelijkeOrganisatie": "000000000", + "_expand": { + "zaaktype": { + "url": "http://catalogue-api.nl/zaaktypen/111-111-111", + }, + }, }, ], "count": 2, @@ -86,3 +117,23 @@ def test_retrieve_and_cache_zaken(self, m): zaken = Zaak.objects.all() self.assertEqual(zaken.count(), 4) + + def test_expanded_correctly(self, m): + m.get("http://zaken-api.nl/zaken/api/v1/zaken", json=PAGE_1) + m.get("http://zaken-api.nl/zaken/api/v1/zaken/?page=2", json=PAGE_2) + + retrieve_and_cache_zaken_from_openzaak() + + zaak_with_resultaat = Zaak.objects.get(identificatie="ZAAK-01") + + self.assertEqual(zaak_with_resultaat.resultaat["toelichting"], "Test result") + self.assertEqual( + zaak_with_resultaat.resultaat["resultaattype"], + { + "url": "http://catalogue-api.nl/catalogi/api/v1/resultaattypen/bd84c463-fa65-46ef-8a9e-dd887e005aea", + }, + ) + self.assertEqual( + zaak_with_resultaat.zaaktype["url"], + "http://catalogue-api.nl/zaaktypen/111-111-111", + ) From b45382b7c0de1a125008fb6c0c64ebfbfb1db734 Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Mon, 13 May 2024 17:53:47 +0200 Subject: [PATCH 3/6] :sparkles: [#15] Expand procestype --- backend/src/openarchiefbeheer/zaken/utils.py | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/backend/src/openarchiefbeheer/zaken/utils.py b/backend/src/openarchiefbeheer/zaken/utils.py index 63d95a21..5078321c 100644 --- a/backend/src/openarchiefbeheer/zaken/utils.py +++ b/backend/src/openarchiefbeheer/zaken/utils.py @@ -1,9 +1,12 @@ +from functools import lru_cache from typing import Generator from ape_pie import APIClient from djangorestframework_camel_case.parser import CamelCaseJSONParser from djangorestframework_camel_case.util import underscoreize +from zgw_consumers.client import build_client from zgw_consumers.concurrent import parallel +from zgw_consumers.models import Service from zgw_consumers.utils import PaginatedResponseData @@ -25,6 +28,21 @@ def _iter( return _iter(paginated_response) +@lru_cache +def get_procestype(url: str) -> dict | None: + service = Service.get_service(url) + if not service: + return + + client = build_client(service) + with client: + response = client.get(url) + response.raise_for_status() + data = response.json() + + return data + + def process_expanded_data(zaken: list[dict]) -> list[dict]: def _format_expanded_data(zaak: dict) -> dict: if "_expand" not in zaak: @@ -33,6 +51,11 @@ def _format_expanded_data(zaak: dict) -> dict: extra_data = zaak["_expand"] zaak["zaaktype"] = extra_data["zaaktype"] + if procestype_url := zaak["zaaktype"].get("selectielijst_procestype"): + expanded_procestype = get_procestype(procestype_url) + if expanded_procestype is not None: + zaak["zaaktype"]["selectielijst_procestype"] = expanded_procestype + if "resultaat" in extra_data: resultaat = extra_data["resultaat"] resultaat_extra_data = resultaat.pop("_expand") From 89e79d85aab54f7bd7340b53170a63ea24331511 Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Mon, 13 May 2024 17:54:12 +0200 Subject: [PATCH 4/6] :white_check_mark: [#15] Test expanding procestype --- .../zaken/tests/test_tasks.py | 178 ++++++++++++++---- 1 file changed, 144 insertions(+), 34 deletions(-) diff --git a/backend/src/openarchiefbeheer/zaken/tests/test_tasks.py b/backend/src/openarchiefbeheer/zaken/tests/test_tasks.py index cd2b9f33..1248d709 100644 --- a/backend/src/openarchiefbeheer/zaken/tests/test_tasks.py +++ b/backend/src/openarchiefbeheer/zaken/tests/test_tasks.py @@ -1,4 +1,4 @@ -from django.test import TestCase +from django.test import TestCase, TransactionTestCase from requests_mock import Mocker from zgw_consumers.constants import APITypes @@ -6,6 +6,7 @@ from ..models import Zaak from ..tasks import retrieve_and_cache_zaken_from_openzaak +from ..utils import get_procestype from .factories import ZaakFactory PAGE_1 = { @@ -19,21 +20,6 @@ "zaaktype": "http://catalogue-api.nl/zaaktypen/111-111-111", "bronorganisatie": "000000000", "verantwoordelijkeOrganisatie": "000000000", - "_expand": { - "zaaktype": { - "url": "http://catalogue-api.nl/zaaktypen/111-111-111", - }, - "resultaat": { - "url": "http://zaken-api.nl/zaken/api/v1/resultaten/ffaa6410-0319-4a6b-b65a-fb209798e81c", - "resultaattype": "http://catalogue-api.nl/catalogi/api/v1/resultaattypen/bd84c463-fa65-46ef-8a9e-dd887e005aea", - "toelichting": "Test result", - "_expand": { - "resultaattype": { - "url": "http://catalogue-api.nl/catalogi/api/v1/resultaattypen/bd84c463-fa65-46ef-8a9e-dd887e005aea", - }, - }, - }, - }, }, { "identificatie": "ZAAK-02", @@ -43,11 +29,6 @@ "zaaktype": "http://catalogue-api.nl/zaaktypen/111-111-111", "bronorganisatie": "000000000", "verantwoordelijkeOrganisatie": "000000000", - "_expand": { - "zaaktype": { - "url": "http://catalogue-api.nl/zaaktypen/111-111-111", - }, - }, }, ], "count": 2, @@ -65,11 +46,6 @@ "zaaktype": "http://catalogue-api.nl/zaaktypen/111-111-111", "bronorganisatie": "000000000", "verantwoordelijkeOrganisatie": "000000000", - "_expand": { - "zaaktype": { - "url": "http://catalogue-api.nl/zaaktypen/111-111-111", - }, - }, }, { "identificatie": "ZAAK-04", @@ -79,11 +55,6 @@ "zaaktype": "http://catalogue-api.nl/zaaktypen/111-111-111", "bronorganisatie": "000000000", "verantwoordelijkeOrganisatie": "000000000", - "_expand": { - "zaaktype": { - "url": "http://catalogue-api.nl/zaaktypen/111-111-111", - }, - }, }, ], "count": 2, @@ -93,7 +64,7 @@ @Mocker() -class TasksTest(TestCase): +class RetrieveCachedZakenTest(TestCase): @classmethod def setUpTestData(cls): super().setUpTestData() @@ -118,9 +89,91 @@ def test_retrieve_and_cache_zaken(self, m): self.assertEqual(zaken.count(), 4) + +PAGE_WITH_EXPAND = { + "results": [ + { + "identificatie": "ZAAK-01", + "url": "http://zaken-api.nl/zaken/api/v1/zaken/75f4c682-1e16-45ea-8f78-99b4474986ac", + "uuid": "75f4c682-1e16-45ea-8f78-99b4474986ac", + "resultaat": "http://zaken-api.nl/zaken/api/v1/resultaten/ffaa6410-0319-4a6b-b65a-fb209798e81c", + "startdatum": "2020-02-01", + "zaaktype": "http://catalogue-api.nl/zaaktypen/111-111-111", + "bronorganisatie": "000000000", + "verantwoordelijkeOrganisatie": "000000000", + "_expand": { + "zaaktype": { + "url": "http://catalogue-api.nl/zaaktypen/111-111-111", + "selectielijstProcestype": "https://selectielijst.openzaak.nl/api/v1/procestypen/e1b73b12-b2f6-4c4e-8929-94f84dd2a57d", + }, + "resultaat": { + "url": "http://zaken-api.nl/zaken/api/v1/resultaten/ffaa6410-0319-4a6b-b65a-fb209798e81c", + "resultaattype": "http://catalogue-api.nl/catalogi/api/v1/resultaattypen/bd84c463-fa65-46ef-8a9e-dd887e005aea", + "toelichting": "Test result", + "_expand": { + "resultaattype": { + "url": "http://catalogue-api.nl/catalogi/api/v1/resultaattypen/bd84c463-fa65-46ef-8a9e-dd887e005aea", + }, + }, + }, + }, + }, + { + "identificatie": "ZAAK-02", + "url": "http://zaken-api.nl/zaken/api/v1/zaken/79dbdbb6-b903-4655-84de-d0b9e106b781", + "uuid": "79dbdbb6-b903-4655-84de-d0b9e106b781", + "startdatum": "2020-02-01", + "zaaktype": "http://catalogue-api.nl/zaaktypen/111-111-111", + "bronorganisatie": "000000000", + "verantwoordelijkeOrganisatie": "000000000", + "resultaat": "http://zaken-api.nl/zaken/api/v1/resultaten/ffaa6410-0319-4a6b-b65a-fb209798e81c", + "_expand": { + "zaaktype": { + "url": "http://catalogue-api.nl/zaaktypen/111-111-111", + }, + }, + }, + { + "identificatie": "ZAAK-03", + "url": "http://zaken-api.nl/zaken/api/v1/zaken/89dbdbb6-b903-4655-84de-d0b9e106b781", + "uuid": "89dbdbb6-b903-4655-84de-d0b9e106b781", + "startdatum": "2020-02-01", + "zaaktype": "http://catalogue-api.nl/zaaktypen/111-111-111", + "bronorganisatie": "000000000", + "verantwoordelijkeOrganisatie": "000000000", + }, + ], + "count": 3, + "previous": None, + "next": None, +} + + +@Mocker() +class RetrieveCachedZakenWithProcestypeTest(TransactionTestCase): + def setUp(self): + super().setUp() + + self.addCleanup(get_procestype.cache_clear) + def test_expanded_correctly(self, m): - m.get("http://zaken-api.nl/zaken/api/v1/zaken", json=PAGE_1) - m.get("http://zaken-api.nl/zaken/api/v1/zaken/?page=2", json=PAGE_2) + ServiceFactory.create( + api_type=APITypes.zrc, + api_root="http://zaken-api.nl/zaken/api/v1", + ) + ServiceFactory.create( + api_type=APITypes.orc, + api_root="https://selectielijst.openzaak.nl/api/v1/", + ) + + m.get("http://zaken-api.nl/zaken/api/v1/zaken", json=PAGE_WITH_EXPAND) + m.get( + "https://selectielijst.openzaak.nl/api/v1/procestypen/e1b73b12-b2f6-4c4e-8929-94f84dd2a57d", + json={ + "url": "https://selectielijst.openzaak.nl/api/v1/procestypen/e1b73b12-b2f6-4c4e-8929-94f84dd2a57d", + "nummer": 1, + }, + ) retrieve_and_cache_zaken_from_openzaak() @@ -137,3 +190,60 @@ def test_expanded_correctly(self, m): zaak_with_resultaat.zaaktype["url"], "http://catalogue-api.nl/zaaktypen/111-111-111", ) + self.assertEqual( + zaak_with_resultaat.zaaktype["selectielijst_procestype"]["nummer"], + 1, + ) + + zaak_without_expanded_resultaat = Zaak.objects.get(identificatie="ZAAK-02") + + self.assertEqual( + zaak_without_expanded_resultaat.resultaat, + "http://zaken-api.nl/zaken/api/v1/resultaten/ffaa6410-0319-4a6b-b65a-fb209798e81c", + ) + + zaak_without_expand = Zaak.objects.get(identificatie="ZAAK-03") + + self.assertEqual( + zaak_without_expand.zaaktype, + "http://catalogue-api.nl/zaaktypen/111-111-111", + ) + + def test_expand_no_selectielijst_service(self, m): + ServiceFactory.create( + api_type=APITypes.zrc, + api_root="http://zaken-api.nl/zaken/api/v1", + ) + + m.get( + "http://zaken-api.nl/zaken/api/v1/zaken", + json={ + "results": [ + { + "identificatie": "ZAAK-01", + "url": "http://zaken-api.nl/zaken/api/v1/zaken/75f4c682-1e16-45ea-8f78-99b4474986ac", + "uuid": "75f4c682-1e16-45ea-8f78-99b4474986ac", + "resultaat": "http://zaken-api.nl/zaken/api/v1/resultaten/ffaa6410-0319-4a6b-b65a-fb209798e81c", + "startdatum": "2020-02-01", + "zaaktype": "http://catalogue-api.nl/zaaktypen/111-111-111", + "bronorganisatie": "000000000", + "verantwoordelijkeOrganisatie": "000000000", + "_expand": { + "zaaktype": { + "url": "http://catalogue-api.nl/zaaktypen/111-111-111", + "selectielijstProcestype": "https://selectielijst.openzaak.nl/api/v1/procestypen/e1b73b12-b2f6-4c4e-8929-94f84dd2a57d", + }, + }, + } + ] + }, + ) + + retrieve_and_cache_zaken_from_openzaak() + + zaak = Zaak.objects.get(identificatie="ZAAK-01") + + self.assertEqual( + zaak.zaaktype["selectielijst_procestype"], + "https://selectielijst.openzaak.nl/api/v1/procestypen/e1b73b12-b2f6-4c4e-8929-94f84dd2a57d", + ) From 712d04ac8ce467ff1982ae71f2a08f9f0ed9b878 Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Tue, 14 May 2024 10:58:35 +0200 Subject: [PATCH 5/6] :sparkles: [#15] Enable filtering on expanded fields --- .../openarchiefbeheer/zaken/api/filtersets.py | 64 +++++++++++++++++-- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/backend/src/openarchiefbeheer/zaken/api/filtersets.py b/backend/src/openarchiefbeheer/zaken/api/filtersets.py index 8ab9bc67..8060eae6 100644 --- a/backend/src/openarchiefbeheer/zaken/api/filtersets.py +++ b/backend/src/openarchiefbeheer/zaken/api/filtersets.py @@ -1,7 +1,9 @@ -from django.db.models import Q, QuerySet, Subquery +from decimal import Decimal + +from django.db.models import Func, IntegerField, Q, QuerySet, Subquery from django.utils.translation import gettext_lazy as _ -from django_filters import BooleanFilter, FilterSet +from django_filters import BooleanFilter, CharFilter, FilterSet, NumberFilter from openarchiefbeheer.destruction.constants import ListItemStatus from openarchiefbeheer.destruction.models import DestructionListItem @@ -17,6 +19,35 @@ class ZaakFilter(FilterSet): "If True, only cases not already included in a destruction list are returned." ), ) + resultaat__resultaattype__url = CharFilter( + help_text=_("Filter on the exact URL of resultaattype."), + ) + bewaartermijn = CharFilter( + field_name="bewaartermijn", + method="filter_bewaartermijn", + help_text=_( + "Filter on bewaartermijn. " + "This corresponds to the property 'resultaat.resultaattype.archiefactietermijn'. " + "This field is expressed in Open Zaak as a ISO8601 duration." + ), + ) + vcs = NumberFilter( + field_name="vcs", + method="filter_vcs", + help_text=_( + "Filter on VCS. This stands for 'Vernietigings-Categorie Selectielijst'. " + "It is obtained through 'zaak.zaaktype.procestype.nummer'." + ), + decimal_places=0, + ) + heeft_relaties = BooleanFilter( + field_name="heeft_relaties", + method="filter_heeft_relaties", + help_text=_( + "Filter on whether this case has other related cases. " + "This is done by looking at the property 'zaak.relevanteAndereZaken'." + ), + ) class Meta: model = Zaak @@ -24,10 +55,8 @@ class Meta: "uuid": ["exact"], "url": ["exact"], "status": ["exact"], - "zaaktype": ["exact", "in"], "einddatum": ["exact", "gt", "lt", "isnull"], "hoofdzaak": ["exact"], - "resultaat": ["exact"], "startdatum": ["exact", "gt", "lt", "gte", "lte"], "toelichting": ["exact"], "omschrijving": ["exact"], @@ -63,7 +92,6 @@ class Meta: # "verlenging": ["exact"], # "opschorting": ["exact"], # "processobject": ["exact"], - # "relevante_andere_zaken": ["exact"], # # Geometry Field # "zaakgeometrie": ["exact"], } @@ -79,3 +107,29 @@ def filter_not_in_destruction_list( ).values_list("zaak", flat=True) return queryset.exclude(url__in=Subquery(zaken_to_exclude)) + + def filter_bewaartermijn( + self, queryset: QuerySet[Zaak], name: str, value: str + ) -> QuerySet[Zaak]: + # TODO it would be nice to do comparisons for periods such as gt/lt + return queryset.filter(resultaat__resultaattype__archiefactietermijn=value) + + def filter_vcs( + self, queryset: QuerySet[Zaak], name: str, value: Decimal + ) -> QuerySet[Zaak]: + return queryset.filter(zaaktype__selectielijst_procestype__nummer=int(value)) + + def filter_heeft_relaties( + self, queryset: QuerySet[Zaak], name: str, value: bool + ) -> QuerySet[Zaak]: + annotated_zaken = queryset.annotate( + number_relations=Func( + "relevante_andere_zaken", + function="jsonb_array_length", + output_field=IntegerField(), + ) + ) + if value: + return annotated_zaken.filter(number_relations__gt=0) + + return annotated_zaken.filter(number_relations=0) From c71d1d601722e3eca093e4fae9f9250fc48b6c27 Mon Sep 17 00:00:00 2001 From: SilviaAmAm Date: Tue, 14 May 2024 10:58:55 +0200 Subject: [PATCH 6/6] :white_check_mark: [#15] Test new filters --- .../zaken/tests/test_viewsets.py | 125 ++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/backend/src/openarchiefbeheer/zaken/tests/test_viewsets.py b/backend/src/openarchiefbeheer/zaken/tests/test_viewsets.py index 4c9e3585..59f373fb 100644 --- a/backend/src/openarchiefbeheer/zaken/tests/test_viewsets.py +++ b/backend/src/openarchiefbeheer/zaken/tests/test_viewsets.py @@ -91,3 +91,128 @@ def test_using_query_params_to_filter(self): self.assertIn(recent_zaken[0].url, urls_zaken) self.assertIn(recent_zaken[1].url, urls_zaken) + + def test_filter_resultaattype(self): + zaak_1 = ZaakFactory.create( + resultaat={ + "resultaattype": { + "url": "http://catalogue-api.nl/catalogi/api/v1/resultaattypen/111-111-111" + } + } + ) + ZaakFactory.create( + resultaat="http://zaken-api.nl/zaken/api/v1/resultaten/111-111-111" + ) # Not expanded + ZaakFactory.create_batch( + 2, + resultaat={ + "resultaattype": { + "url": "http://catalogue-api.nl/catalogi/api/v1/resultaattypen/222-222-222" + } + }, + ) + + user = UserFactory(username="record_manager", role__can_start_destruction=True) + + endpoint = furl(reverse("api:zaken-list")) + endpoint.args["resultaat__resultaattype__url"] = ( + "http://catalogue-api.nl/catalogi/api/v1/resultaattypen/111-111-111" + ) + + self.client.force_authenticate(user) + response = self.client.get(endpoint.url) + data = response.json() + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(data["count"], 1) + self.assertEqual(data["results"][0]["uuid"], str(zaak_1.uuid)) + + def test_filter_bewaartermijn(self): + zaak_1 = ZaakFactory.create( + resultaat={"resultaattype": {"archiefactietermijn": "P1D"}} + ) + ZaakFactory.create( + resultaat="http://zaken-api.nl/zaken/api/v1/resultaten/111-111-111" + ) # Not expanded + ZaakFactory.create_batch( + 2, resultaat={"resultaattype": {"archiefactietermijn": "P2D"}} + ) + + user = UserFactory(username="record_manager", role__can_start_destruction=True) + + endpoint = furl(reverse("api:zaken-list")) + endpoint.args["bewaartermijn"] = "P1D" + + self.client.force_authenticate(user) + response = self.client.get(endpoint.url) + data = response.json() + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(data["count"], 1) + self.assertEqual(data["results"][0]["uuid"], str(zaak_1.uuid)) + + def test_filter_vcs(self): + zaak_1 = ZaakFactory.create( + zaaktype={"selectielijst_procestype": {"nummer": 1}} + ) + ZaakFactory.create( + zaaktype="http://catalogue-api.nl/zaaktypen/111-111-111", + ) # Not expanded + ZaakFactory.create_batch( + 2, zaaktype={"selectielijst_procestype": {"nummer": 2}} + ) + + user = UserFactory(username="record_manager", role__can_start_destruction=True) + + endpoint = furl(reverse("api:zaken-list")) + endpoint.args["vcs"] = 1 + + self.client.force_authenticate(user) + response = self.client.get(endpoint.url) + data = response.json() + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(data["count"], 1) + self.assertEqual(data["results"][0]["uuid"], str(zaak_1.uuid)) + + def test_filter_heeft_relaties(self): + zaak_1 = ZaakFactory.create( + relevante_andere_zaken=[ + "http://zaken-api.nl/zaken/api/v1/zaken/111-111-111" + ] + ) + zaak_2 = ZaakFactory.create( + relevante_andere_zaken=[ + "http://zaken-api.nl/zaken/api/v1/zaken/111-111-111", + "http://zaken-api.nl/zaken/api/v1/zaken/222-222-222", + ] + ) + no_relations_zaken = ZaakFactory.create_batch(2, relevante_andere_zaken=[]) + + user = UserFactory(username="record_manager", role__can_start_destruction=True) + + endpoint = furl(reverse("api:zaken-list")) + endpoint.args["heeft_relaties"] = True + + self.client.force_authenticate(user) + response = self.client.get(endpoint.url) + data = response.json() + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(data["count"], 2) + + uuids = [zaak["uuid"] for zaak in data["results"]] + + self.assertIn(str(zaak_1.uuid), uuids) + self.assertIn(str(zaak_2.uuid), uuids) + + # If the filter is false, we only want zaken without relations + endpoint.args["heeft_relaties"] = False + response = self.client.get(endpoint.url) + data = response.json() + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(data["count"], 2) + + uuids = [zaak["uuid"] for zaak in data["results"]] + + self.assertIn(str(no_relations_zaken[0].uuid), uuids) + self.assertIn(str(no_relations_zaken[1].uuid), uuids)