From 56695b30cabe8858abd7c58ae8cc47938dedfb6e Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Mon, 3 Mar 2025 14:09:46 +0100 Subject: [PATCH] [#212] Expand BetrokkeneSerializer with digitale_adressen --- .../api/filterset/klantcontacten.py | 6 ++ .../api/serializers/klantcontacten.py | 4 ++ .../api/tests/test_filters.py | 27 ++++++++ .../api/tests/test_klantcontacten.py | 24 ++++++- .../api/viewsets/klantcontacten.py | 13 +++- .../components/klantinteracties/openapi.yaml | 69 ++++++++++++++++++- 6 files changed, 137 insertions(+), 6 deletions(-) diff --git a/src/openklant/components/klantinteracties/api/filterset/klantcontacten.py b/src/openklant/components/klantinteracties/api/filterset/klantcontacten.py index 9ed5e3e7..93b6b570 100644 --- a/src/openklant/components/klantinteracties/api/filterset/klantcontacten.py +++ b/src/openklant/components/klantinteracties/api/filterset/klantcontacten.py @@ -3,6 +3,7 @@ from django_filters.rest_framework import FilterSet, filters from openklant.components.klantinteracties.api.serializers.klantcontacten import ( + BetrokkeneSerializer, KlantcontactSerializer, ) from openklant.components.klantinteracties.models.actoren import ActorKlantcontact @@ -84,6 +85,10 @@ class Meta: ) +class BetrokkeneDetailFilterSet(FilterSet): + expand = ExpandFilter(serializer_class=BetrokkeneSerializer) + + class BetrokkeneFilterSet(FilterSet): had_klantcontact__nummer = filters.CharFilter( help_text=_("Zoek betrokkene object op basis van het klantcontact nummer"), @@ -122,6 +127,7 @@ class BetrokkeneFilterSet(FilterSet): help_text=_("Zoek betrokkene object op basis van het partij uuid"), field_name="partij__uuid", ) + expand = ExpandFilter(serializer_class=BetrokkeneSerializer) class Meta: model = Betrokkene diff --git a/src/openklant/components/klantinteracties/api/serializers/klantcontacten.py b/src/openklant/components/klantinteracties/api/serializers/klantcontacten.py index 5605fba0..2d111f4b 100644 --- a/src/openklant/components/klantinteracties/api/serializers/klantcontacten.py +++ b/src/openklant/components/klantinteracties/api/serializers/klantcontacten.py @@ -184,6 +184,10 @@ class BetrokkeneSerializer( help_text="De voledige naam van de betrokkene.", ) + inclusion_serializers = { + "digitale_adressen": f"{SERIALIZER_PATH}.digitaal_adres.DigitaalAdresSerializer", + } + class Meta: model = Betrokkene fields = ( diff --git a/src/openklant/components/klantinteracties/api/tests/test_filters.py b/src/openklant/components/klantinteracties/api/tests/test_filters.py index 2a9d3c80..21766a23 100644 --- a/src/openklant/components/klantinteracties/api/tests/test_filters.py +++ b/src/openklant/components/klantinteracties/api/tests/test_filters.py @@ -630,6 +630,33 @@ def test_filter_was_partij_nummer(self): self.assertEqual(response.json()["count"], 0) + def test_digitale_adressen_inclusion_param(self): + betrokkene = BetrokkeneFactory.create() + response = self.client.get(self.url, data={"expand": "digitaleAdressen"}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + results = response.json()["results"] + self.assertEqual(len(results), 1) + self.assertEqual(results[0]["_expand"], {"digitaleAdressen": []}) + + digitaal_adres = DigitaalAdresFactory( + betrokkene=betrokkene, + adres="test", + soort_digitaal_adres="email", + ) + + response = self.client.get(self.url, data={"expand": "digitaleAdressen"}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + results = response.json()["results"] + self.assertEqual(len(results), 1) + digitaal_adressen = results[0]["_expand"]["digitaleAdressen"] + self.assertEqual(len(digitaal_adressen), 1) + self.assertEqual(digitaal_adressen[0]["uuid"], str(digitaal_adres.uuid)) + self.assertEqual( + digitaal_adressen[0]["verstrektDoorBetrokkene"]["uuid"], + str(betrokkene.uuid), + ) + class PartijFilterSetTests(APITestCase): url = reverse("klantinteracties:partij-list") diff --git a/src/openklant/components/klantinteracties/api/tests/test_klantcontacten.py b/src/openklant/components/klantinteracties/api/tests/test_klantcontacten.py index 282756bc..36a634f6 100644 --- a/src/openklant/components/klantinteracties/api/tests/test_klantcontacten.py +++ b/src/openklant/components/klantinteracties/api/tests/test_klantcontacten.py @@ -13,6 +13,9 @@ ActorKlantcontactFactory, MedewerkerFactory, ) +from openklant.components.klantinteracties.models.tests.factories.digitaal_adres import ( + DigitaalAdresFactory, +) from openklant.components.klantinteracties.models.tests.factories.klantcontacten import ( BetrokkeneFactory, BijlageFactory, @@ -390,10 +393,10 @@ def test_list_betrokkene(self): self.assertEqual(len(data["results"]), 2) def test_read_betrokkene(self): - klantcontact = BetrokkeneFactory.create() + betrokkene = BetrokkeneFactory.create() detail_url = reverse( "klantinteracties:betrokkene-detail", - kwargs={"uuid": str(klantcontact.uuid)}, + kwargs={"uuid": str(betrokkene.uuid)}, ) response = self.client.get(detail_url) @@ -402,6 +405,23 @@ def test_read_betrokkene(self): data = response.json() self.assertEqual(data["url"], "http://testserver" + detail_url) + with self.subTest("test_expand_digitale_adressen"): + digitaal_adres = DigitaalAdresFactory( + betrokkene=betrokkene, + adres="test", + soort_digitaal_adres="email", + ) + response = self.client.get(detail_url, data={"expand": "digitaleAdressen"}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + data = response.json() + digitaal_adressen = data["_expand"]["digitaleAdressen"] + self.assertEqual(len(digitaal_adressen), 1) + self.assertEqual(digitaal_adressen[0]["uuid"], str(digitaal_adres.uuid)) + self.assertEqual( + digitaal_adressen[0]["verstrektDoorBetrokkene"]["uuid"], + str(betrokkene.uuid), + ) + def test_create_betrokkene_with_partij(self): klantcontact = KlantcontactFactory.create() partij = PartijFactory.create() diff --git a/src/openklant/components/klantinteracties/api/viewsets/klantcontacten.py b/src/openklant/components/klantinteracties/api/viewsets/klantcontacten.py index 16e239d4..f4a03b00 100644 --- a/src/openklant/components/klantinteracties/api/viewsets/klantcontacten.py +++ b/src/openklant/components/klantinteracties/api/viewsets/klantcontacten.py @@ -5,6 +5,7 @@ from openklant.components.klantinteracties.api.filterset.klantcontacten import ( ActorKlantcontactFilterSet, + BetrokkeneDetailFilterSet, BetrokkeneFilterSet, KlantcontactDetailFilterSet, KlantcontactFilterSet, @@ -110,7 +111,7 @@ def filterset_class(self): description="Verwijder een betrokkene.", ), ) -class BetrokkeneViewSet(viewsets.ModelViewSet): +class BetrokkeneViewSet(ExpandMixin, viewsets.ModelViewSet): """ Ofwel betrokkenheid van een partij bij een klantcontact, eventueel aangevuld met specifiek voor opvolging van dat klantcontact te gebruiken contactgegevens, ofwel @@ -129,10 +130,18 @@ class BetrokkeneViewSet(viewsets.ModelViewSet): serializer_class = BetrokkeneSerializer lookup_field = "uuid" pagination_class = DynamicPageSizePagination - filterset_class = BetrokkeneFilterSet authentication_classes = (TokenAuthentication,) permission_classes = (TokenPermissions,) + @property + def filterset_class(self): + """ + support expand in the detail endpoint + """ + if self.detail: + return BetrokkeneDetailFilterSet + return BetrokkeneFilterSet + @extend_schema(tags=["onderwerpobjecten"]) @extend_schema_view( diff --git a/src/openklant/components/klantinteracties/openapi.yaml b/src/openklant/components/klantinteracties/openapi.yaml index c081ca45..6d2ab627 100644 --- a/src/openklant/components/klantinteracties/openapi.yaml +++ b/src/openklant/components/klantinteracties/openapi.yaml @@ -391,6 +391,19 @@ paths: name: contactnaamVoorvoegselAchternaam schema: type: string + - in: query + name: expand + schema: + type: array + items: + type: string + enum: + - digitaleAdressen + description: |+ + Sluit de gespecifieerde gerelateerde resources in in het antwoord. + + explode: false + style: form - in: query name: hadKlantcontact__nummer schema: @@ -467,7 +480,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/PaginatedBetrokkeneList' + $ref: '#/components/schemas/PaginatedExpandBetrokkeneList' description: '' post: operationId: betrokkenenCreate @@ -496,6 +509,19 @@ paths: description: Een specifiek betrokkene opvragen. summary: Een specifiek betrokkene opvragen. parameters: + - in: query + name: expand + schema: + type: array + items: + type: string + enum: + - digitaleAdressen + description: |+ + Sluit de gespecifieerde gerelateerde resources in in het antwoord. + + explode: false + style: form - in: path name: uuid schema: @@ -513,7 +539,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/Betrokkene' + $ref: '#/components/schemas/ExpandBetrokkene' description: '' put: operationId: betrokkenenUpdate @@ -3791,6 +3817,22 @@ components: required: - url - uuid + ExpandBetrokkene: + allOf: + - $ref: '#/components/schemas/Betrokkene' + - type: object + properties: + _expand: + type: object + description: Display details of the linked resources requested in the + `expand` parameter + properties: + digitale_adressen: + type: array + items: + $ref: '#/components/schemas/DigitaalAdres' + readOnly: true + description: Digitale adressen van de betrokkene bij klantcontact. ExpandDigitaalAdres: allOf: - $ref: '#/components/schemas/DigitaalAdres' @@ -4437,6 +4479,29 @@ components: type: array items: $ref: '#/components/schemas/DigitaalAdres' + PaginatedExpandBetrokkeneList: + type: object + required: + - count + - results + properties: + count: + type: integer + example: 123 + next: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?page=4 + previous: + type: string + nullable: true + format: uri + example: http://api.example.org/accounts/?page=2 + results: + type: array + items: + $ref: '#/components/schemas/ExpandBetrokkene' PaginatedExpandDigitaalAdresList: type: object required: