From 38b20d7601dca800158d70481b0f17281b2728c8 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/viewsets/klantcontacten.py | 13 +++- .../components/klantinteracties/openapi.yaml | 69 ++++++++++++++++++- 5 files changed, 115 insertions(+), 4 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/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 c36eaa53..f5ef26a6 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 @@ -3737,6 +3763,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' @@ -4383,6 +4425,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: