Skip to content

Commit

Permalink
✨ [#147] Convenience endpoint for Klantcontact/Betrokkene/Onderwerpob…
Browse files Browse the repository at this point in the history
…ject

to allow creation of these three resources in a single API call
  • Loading branch information
stevenbal committed Oct 3, 2024
1 parent 2886954 commit d812844
Show file tree
Hide file tree
Showing 4 changed files with 235 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -537,3 +537,55 @@ def create(self, validated_data):
)

return super().create(validated_data)


class BetrokkeneConvenienceSerializer(BetrokkeneSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

self.fields["had_klantcontact"].read_only = True


class OnderwerpobjectConvenienceSerializer(OnderwerpobjectSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

self.fields["klantcontact"].read_only = True


class KlantContactBetrokkeneOnderwerpObjectSerializer(serializers.Serializer):
klantcontact = KlantcontactSerializer()
betrokkene = BetrokkeneConvenienceSerializer()
onderwerpobject = OnderwerpobjectConvenienceSerializer()

@transaction.atomic
def create(self, validated_data):
"""
Create the objects and use the original serializers to ensure all the correct
fields show up in the response
"""
klantcontact_data = validated_data["klantcontact"]
klantcontact = Klantcontact.objects.create(**klantcontact_data)

betrokkene_data = validated_data["betrokkene"]
betrokkene_data["had_klantcontact"] = {"uuid": str(klantcontact.uuid)}
# TODO for some reason `was_partij` is converted to `partij` by the serializer
betrokkene_data.setdefault("was_partij", betrokkene_data.get("partij", None))
betrokkene_serializer = BetrokkeneSerializer(data=betrokkene_data)
betrokkene_serializer.is_valid()
betrokkene = betrokkene_serializer.save()

onderwerpobject_data = validated_data["onderwerpobject"]
onderwerpobject_data["klantcontact"] = {"uuid": str(klantcontact.uuid)}
onderwerpobject_data.setdefault("was_klantcontact", None)
onderwerpobject_serializer = OnderwerpobjectSerializer(
data=onderwerpobject_data
)
onderwerpobject_serializer.is_valid()
onderwerpobject = onderwerpobject_serializer.save()

return {
"klantcontact": klantcontact,
"betrokkene": betrokkene,
"onderwerpobject": onderwerpobject,
}
6 changes: 6 additions & 0 deletions src/openklant/components/klantinteracties/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
ActorKlantcontactViewSet,
BetrokkeneViewSet,
BijlageViewSet,
KlantContactBetrokkeneOnderwerpObjectViewSet,
KlantcontactViewSet,
OnderwerpobjectViewSet,
)
Expand Down Expand Up @@ -48,6 +49,11 @@
router.register("betrokkenen", BetrokkeneViewSet)
router.register("onderwerpobjecten", OnderwerpobjectViewSet)
router.register("bijlagen", BijlageViewSet)
router.register(
"klantcontact-convenience",
KlantContactBetrokkeneOnderwerpObjectViewSet,
basename="klantcontact-convenience",
)

router.register("internetaken", InterneTaakViewSet)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.utils import extend_schema, extend_schema_view
from rest_framework import viewsets
from rest_framework import mixins, viewsets
from vng_api_common.pagination import DynamicPageSizePagination

from openklant.components.klantinteracties.api.filterset.klantcontacten import (
Expand All @@ -13,6 +13,7 @@
ActorKlantcontactSerializer,
BetrokkeneSerializer,
BijlageSerializer,
KlantContactBetrokkeneOnderwerpObjectSerializer,
KlantcontactSerializer,
OnderwerpobjectSerializer,
)
Expand Down Expand Up @@ -262,3 +263,23 @@ class ActorKlantcontactViewSet(viewsets.ModelViewSet):
filterset_class = ActorKlantcontactFilterSet
authentication_classes = (TokenAuthentication,)
permission_classes = (TokenPermissions,)


@extend_schema(tags=["klantcontact-convenience"])
@extend_schema_view(
create=extend_schema(
summary="Maak een KlantContact, Betrokkene en een OnderwerpObject aan.",
description="Maak een KlantContact, Betrokkene en een OnderwerpObject aan.",
),
)
class KlantContactBetrokkeneOnderwerpObjectViewSet(
mixins.CreateModelMixin, viewsets.GenericViewSet
):
"""
Convenience endpoint om in één request een Betrokkene, KlantContact en een OnderwerpObject
aan te maken. De aangemaakte objecten worden automatisch aan elkaar gekoppeld.
"""

serializer_class = KlantContactBetrokkeneOnderwerpObjectSerializer
authentication_classes = (TokenAuthentication,)
permission_classes = (TokenPermissions,)
155 changes: 155 additions & 0 deletions src/openklant/components/klantinteracties/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1547,6 +1547,28 @@ paths:
responses:
'204':
description: No response body
/klantcontact-convenience:
post:
operationId: klantcontactConvenienceCreate
description: Maak een KlantContact, Betrokkene en een OnderwerpObject aan.
summary: Maak een KlantContact, Betrokkene en een OnderwerpObject aan.
tags:
- klantcontact-convenience
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/KlantContactBetrokkeneOnderwerpObject'
required: true
security:
- tokenAuth: []
responses:
'201':
content:
application/json:
schema:
$ref: '#/components/schemas/KlantContactBetrokkeneOnderwerpObject'
description: ''
/klantcontacten:
get:
operationId: klantcontactenList
Expand Down Expand Up @@ -2986,6 +3008,87 @@ components:
- uuid
- volledigeNaam
- wasPartij
BetrokkeneConvenience:
type: object
description: |-
Set gegevensgroepdata from validated nested data.
Usage: include the mixin on the ModelSerializer that has gegevensgroepen.
properties:
uuid:
type: string
format: uuid
readOnly: true
description: Unieke (technische) identificatiecode van de betrokkene bij
klantcontact.
url:
type: string
format: uri
readOnly: true
description: De unieke URL van deze betrokkene binnen deze API.
wasPartij:
allOf:
- $ref: '#/components/schemas/PartijForeignKey'
nullable: true
description: Betrokkene bij klantcontact die een partij was.
hadKlantcontact:
allOf:
- $ref: '#/components/schemas/KlantcontactForeignKey'
readOnly: true
description: Het klantcontact waar deze persoon of organisatie bij betrokken
was.
digitaleAdressen:
type: array
items:
$ref: '#/components/schemas/DigitaalAdresForeignKey'
readOnly: true
description: Digitale adressen van de betrokkene bij klantcontact.
bezoekadres:
allOf:
- $ref: '#/components/schemas/Bezoekadres'
nullable: true
description: Adres waarop de betrokkene bij klantcontact in naar aanleiding
van dat contact af te leggen bezoeken wil ontvangen. Dit mag afwijken
van voor de verstrekker eventueel in een basisregistratie bekende adressen.
correspondentieadres:
allOf:
- $ref: '#/components/schemas/BetrokkeneCorrespondentieadres'
nullable: true
description: Adres waarop de betrokkene bij klantcontact naar aanleiding
van dat contact te versturen post wil ontvangen. Dit mag afwijken van
voor de verstrekker eventueel in een basisregistratie bekende adressen.
contactnaam:
allOf:
- $ref: '#/components/schemas/Contactnaam'
nullable: true
description: Naam die de betrokkene bij klantcontact tijdens vervolghandelingen
naar aanleiding van dat contact wil gebruiken. Deze mag afwijken van eventueel
in de Basisregistratie Personen (BRP) bekende naam van de betrokkene.
volledigeNaam:
type: string
readOnly: true
description: De voledige naam van de betrokkene.
rol:
allOf:
- $ref: '#/components/schemas/RolEnum'
description: Rol die de betrokkene bij klantcontact tijdens dat contact
vervulde.
organisatienaam:
type: string
description: Naam van de organisatie waarmee de betrokkene bij klantcontact
een relatie had.
maxLength: 200
initiator:
type: boolean
required:
- digitaleAdressen
- hadKlantcontact
- initiator
- rol
- url
- uuid
- volledigeNaam
- wasPartij
BetrokkeneCorrespondentieadres:
type: object
description: |-
Expand Down Expand Up @@ -3549,6 +3652,19 @@ components:
required:
- url
- uuid
KlantContactBetrokkeneOnderwerpObject:
type: object
properties:
klantcontact:
$ref: '#/components/schemas/Klantcontact'
betrokkene:
$ref: '#/components/schemas/BetrokkeneConvenience'
onderwerpobject:
$ref: '#/components/schemas/OnderwerpobjectConvenience'
required:
- betrokkene
- klantcontact
- onderwerpobject
Klantcontact:
type: object
properties:
Expand Down Expand Up @@ -3699,6 +3815,45 @@ components:
- url
- uuid
- wasKlantcontact
OnderwerpobjectConvenience:
type: object
description: |-
Set gegevensgroepdata from validated nested data.
Usage: include the mixin on the ModelSerializer that has gegevensgroepen.
properties:
uuid:
type: string
format: uuid
readOnly: true
description: Unieke (technische) identificatiecode van het onderwerpdeel.
url:
type: string
format: uri
readOnly: true
description: De unieke URL van dit klantcontact binnen deze API.
klantcontact:
allOf:
- $ref: '#/components/schemas/KlantcontactForeignKey'
readOnly: true
nullable: true
description: '''Klantcontact'' ging over ''Onderwerpobject'''
wasKlantcontact:
allOf:
- $ref: '#/components/schemas/KlantcontactForeignKey'
nullable: true
description: '''Onderwerpobject'' was ''Klantcontact'''
onderwerpobjectidentificator:
allOf:
- $ref: '#/components/schemas/Onderwerpobjectidentificator'
nullable: true
description: Gegevens die een onderwerpobject in een extern register uniek
identificeren.
required:
- klantcontact
- url
- uuid
- wasKlantcontact
OnderwerpobjectForeignKey:
type: object
properties:
Expand Down

0 comments on commit d812844

Please sign in to comment.