From 9bbcafdbd9052ba9ed04bd127f3a66fc0423b2df Mon Sep 17 00:00:00 2001
From: Daniel Mursa <daniel@maykinmedia.nl>
Date: Wed, 12 Feb 2025 16:18:26 +0100
Subject: [PATCH 1/4] [#240] Make nullable fields non-required in creation
 endpoints

---
 .../api/serializers/digitaal_adres.py         | 11 +++-
 .../api/serializers/klantcontacten.py         | 27 +++++++--
 .../api/serializers/partijen.py               | 55 +++++++++++++++----
 .../api/serializers/rekeningnummers.py        |  8 ++-
 .../api/tests/test_partijen.py                | 21 +------
 5 files changed, 85 insertions(+), 37 deletions(-)

diff --git a/src/openklant/components/klantinteracties/api/serializers/digitaal_adres.py b/src/openklant/components/klantinteracties/api/serializers/digitaal_adres.py
index 1fc7a3cd..c8410394 100644
--- a/src/openklant/components/klantinteracties/api/serializers/digitaal_adres.py
+++ b/src/openklant/components/klantinteracties/api/serializers/digitaal_adres.py
@@ -42,7 +42,7 @@ class DigitaalAdresSerializer(serializers.HyperlinkedModelSerializer):
     )
 
     verstrekt_door_partij = PartijForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_(
             "Digitaal adres dat een partij verstrekte voor gebruik bij "
@@ -51,7 +51,7 @@ class DigitaalAdresSerializer(serializers.HyperlinkedModelSerializer):
         source="partij",
     )
     verstrekt_door_betrokkene = BetrokkeneForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_(
             "Digitaal adres dat een betrokkene bij klantcontact verstrekte voor gebruik bij "
@@ -70,6 +70,13 @@ class DigitaalAdresSerializer(serializers.HyperlinkedModelSerializer):
         ".internetaken.InterneTaakSerializer",
     }
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        request = self.context.get("request")
+        if request and request.method in ["PUT", "PATCH"]:
+            self.fields["verstrekt_door_partij"].required = True
+            self.fields["verstrekt_door_betrokkene"].required = True
+
     class Meta:
         model = DigitaalAdres
         fields = (
diff --git a/src/openklant/components/klantinteracties/api/serializers/klantcontacten.py b/src/openklant/components/klantinteracties/api/serializers/klantcontacten.py
index 5605fba0..393e3b1b 100644
--- a/src/openklant/components/klantinteracties/api/serializers/klantcontacten.py
+++ b/src/openklant/components/klantinteracties/api/serializers/klantcontacten.py
@@ -134,7 +134,7 @@ class BetrokkeneSerializer(
     )
 
     was_partij = PartijForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         source="partij",
         help_text=_("Betrokkene bij klantcontact die een partij was."),
@@ -184,6 +184,12 @@ class BetrokkeneSerializer(
         help_text="De voledige naam van de betrokkene.",
     )
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        request = self.context.get("request")
+        if request and request.method in ["PUT", "PATCH"]:
+            self.fields["was_partij"].required = True
+
     class Meta:
         model = Betrokkene
         fields = (
@@ -336,12 +342,12 @@ class OnderwerpobjectSerializer(
     NestedGegevensGroepMixin, serializers.HyperlinkedModelSerializer
 ):
     klantcontact = KlantcontactForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_("'Klantcontact' ging over 'Onderwerpobject'"),
     )
     was_klantcontact = KlantcontactForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_("'Onderwerpobject' was 'Klantcontact'"),
     )
@@ -354,6 +360,13 @@ class OnderwerpobjectSerializer(
         ),
     )
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        request = self.context.get("request")
+        if request and request.method in ["PUT", "PATCH"]:
+            self.fields["klantcontact"].required = True
+            self.fields["was_klantcontact"].required = True
+
     class Meta:
         model = Onderwerpobject
         fields = (
@@ -419,7 +432,7 @@ class BijlageSerializer(
     NestedGegevensGroepMixin, serializers.HyperlinkedModelSerializer
 ):
     was_bijlage_van_klantcontact = KlantcontactForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_("'Klantcontact' ging over 'Onderwerpobject'"),
         source="klantcontact",
@@ -433,6 +446,12 @@ class BijlageSerializer(
         ),
     )
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        request = self.context.get("request")
+        if request and request.method in ["PUT", "PATCH"]:
+            self.fields["was_bijlage_van_klantcontact"].required = True
+
     class Meta:
         model = Bijlage
         fields = (
diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py
index 5894696b..ca5d1453 100644
--- a/src/openklant/components/klantinteracties/api/serializers/partijen.py
+++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py
@@ -198,12 +198,12 @@ class CategorieRelatieSerializer(serializers.HyperlinkedModelSerializer):
     """Let op: Dit endpoint is EXPERIMENTEEL."""
 
     partij = PartijForeignkeyBaseSerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_("De partij waar de categorie relatie aan gelinkt is."),
     )
     categorie = CategorieForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_(
             "De categorie waar de categorie relatie aan gelinkt is: Let op: Dit attribuut is EXPERIMENTEEL."
@@ -218,6 +218,13 @@ class CategorieRelatieSerializer(serializers.HyperlinkedModelSerializer):
         ),
     )
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        request = self.context.get("request")
+        if request and request.method in ["PUT", "PATCH"]:
+            self.fields["partij"].required = True
+            self.fields["categorie"].required = True
+
     class Meta:
         model = CategorieRelatie
         fields = (
@@ -286,7 +293,7 @@ class Meta:
 
 class PersoonSerializer(NestedGegevensGroepMixin, serializers.ModelSerializer):
     contactnaam = PersoonContactSerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_(
             "Naam die een persoon wil gebruiken tijdens contact met de gemeente. "
@@ -298,6 +305,12 @@ class PersoonSerializer(NestedGegevensGroepMixin, serializers.ModelSerializer):
         help_text="De voledige naam van het persoon.",
     )
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        request = self.context.get("request")
+        if request and request.method in ["PUT", "PATCH"]:
+            self.fields["contactnaam"].required = True
+
     class Meta:
         model = Persoon
         fields = (
@@ -311,7 +324,7 @@ def get_volledige_naam(self, obj) -> str:
 
 class ContactpersoonSerializer(NestedGegevensGroepMixin, serializers.ModelSerializer):
     werkte_voor_partij = PartijPolymorphicSerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_("Organisatie waarvoor een contactpersoon werkte."),
     )
@@ -328,6 +341,12 @@ class ContactpersoonSerializer(NestedGegevensGroepMixin, serializers.ModelSerial
         help_text="De voledige naam van het constact persoon.",
     )
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        request = self.context.get("request")
+        if request and request.method in ["PUT", "PATCH"]:
+            self.fields["werkte_voor_partij"].required = True
+
     class Meta:
         model = Contactpersoon
         fields = (
@@ -370,13 +389,13 @@ class PartijIdentificatorSerializer(
     NestedGegevensGroepMixin, serializers.HyperlinkedModelSerializer
 ):
     identificeerde_partij = PartijForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_("Partij-identificator die hoorde bij een partij."),
         source="partij",
     )
     partij_identificator = PartijIdentificatorGroepTypeSerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_(
             "Gegevens die een partij in een basisregistratie "
@@ -384,6 +403,13 @@ class PartijIdentificatorSerializer(
         ),
     )
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        request = self.context.get("request")
+        if request and request.method in ["PUT", "PATCH"]:
+            self.fields["identificeerde_partij"].required = True
+            self.fields["partij_identificator"].required = True
+
     class Meta:
         model = PartijIdentificator
         fields = (
@@ -461,7 +487,7 @@ class PartijSerializer(NestedGegevensGroepMixin, PolymorphicSerializer):
         source="categorierelatie_set",
     )
     digitale_adressen = DigitaalAdresForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_(
             "Digitaal adresen dat een partij verstrekte voor gebruik bij "
@@ -471,21 +497,21 @@ class PartijSerializer(NestedGegevensGroepMixin, PolymorphicSerializer):
         many=True,
     )
     voorkeurs_digitaal_adres = DigitaalAdresForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_(
             "Digitaal adres waarop een partij bij voorkeur door de gemeente benaderd wordt."
         ),
     )
     rekeningnummers = RekeningnummerForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_("Rekeningnummers van een partij"),
         source="rekeningnummer_set",
         many=True,
     )
     voorkeurs_rekeningnummer = RekeningnummerForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_("Rekeningsnummer die een partij bij voorkeur gebruikt."),
     )
@@ -526,6 +552,15 @@ class PartijSerializer(NestedGegevensGroepMixin, PolymorphicSerializer):
         "betrokkenen.had_klantcontact": f"{SERIALIZER_PATH}.klantcontacten.KlantcontactSerializer",
     }
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        request = self.context.get("request")
+        if request and request.method in ["PUT", "PATCH"]:
+            self.fields["digitale_adressen"].required = True
+            self.fields["voorkeurs_digitaal_adres"].required = True
+            self.fields["rekeningnummers"].required = True
+            self.fields["voorkeurs_rekeningnummer"].required = True
+
     class Meta:
         model = Partij
         fields = (
diff --git a/src/openklant/components/klantinteracties/api/serializers/rekeningnummers.py b/src/openklant/components/klantinteracties/api/serializers/rekeningnummers.py
index 43d4b500..79a47d7f 100644
--- a/src/openklant/components/klantinteracties/api/serializers/rekeningnummers.py
+++ b/src/openklant/components/klantinteracties/api/serializers/rekeningnummers.py
@@ -33,11 +33,17 @@ class RekeningnummerSerializer(serializers.HyperlinkedModelSerializer):
     )
 
     partij = PartijForeignKeySerializer(
-        required=True,
+        required=False,
         allow_null=True,
         help_text=_("Rekeningnummer van een partij"),
     )
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        request = self.context.get("request")
+        if request and request.method in ["PUT", "PATCH"]:
+            self.fields["partij"].required = True
+
     class Meta:
         model = Rekeningnummer
         fields = ("uuid", "url", "partij", "iban", "bic")
diff --git a/src/openklant/components/klantinteracties/api/tests/test_partijen.py b/src/openklant/components/klantinteracties/api/tests/test_partijen.py
index 5f36e120..c8e3dccf 100644
--- a/src/openklant/components/klantinteracties/api/tests/test_partijen.py
+++ b/src/openklant/components/klantinteracties/api/tests/test_partijen.py
@@ -331,26 +331,6 @@ def test_create_partij_only_required(self):
         self.assertEqual(
             response_data["invalidParams"],
             [
-                {
-                    "name": "digitaleAdressen",
-                    "code": "required",
-                    "reason": _("This field is required."),
-                },
-                {
-                    "name": "voorkeursDigitaalAdres",
-                    "code": "required",
-                    "reason": _("This field is required."),
-                },
-                {
-                    "name": "rekeningnummers",
-                    "code": "required",
-                    "reason": _("This field is required."),
-                },
-                {
-                    "name": "voorkeursRekeningnummer",
-                    "code": "required",
-                    "reason": _("This field is required."),
-                },
                 {
                     "name": "soortPartij",
                     "code": "required",
@@ -843,6 +823,7 @@ def test_update_partij(self):
         with self.subTest(
             "test_voorkeurs_digitaal_adres_must_be_part_of_digitale_adressen"
         ):
+
             data["voorkeursDigitaalAdres"] = {"uuid": str(digitaal_adres.uuid)}
             response = self.client.put(detail_url, data)
             self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)

From 85b206d50c4202da1ed56a04d85c53b522f0caf5 Mon Sep 17 00:00:00 2001
From: Daniel Mursa <daniel@maykinmedia.nl>
Date: Wed, 12 Feb 2025 16:40:22 +0100
Subject: [PATCH 2/4] [#240] Fix tests and update schema

---
 .../api/serializers/partijen.py               |  4 +--
 .../api/tests/test_partijen.py                | 21 +++++++++++-----
 .../components/klantinteracties/openapi.yaml  | 25 -------------------
 3 files changed, 17 insertions(+), 33 deletions(-)

diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py
index ca5d1453..9261bdc5 100644
--- a/src/openklant/components/klantinteracties/api/serializers/partijen.py
+++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py
@@ -770,8 +770,8 @@ def update(self, instance, validated_data):
     @transaction.atomic
     def create(self, validated_data):
         partij_identificatie = validated_data.pop("partij_identificatie", None)
-        digitale_adressen = validated_data.pop("digitaaladres_set")
-        rekeningnummers = validated_data.pop("rekeningnummer_set")
+        digitale_adressen = validated_data.pop("digitaaladres_set", [])
+        rekeningnummers = validated_data.pop("rekeningnummer_set", [])
 
         if voorkeurs_digitaal_adres := validated_data.pop(
             "voorkeurs_digitaal_adres", None
diff --git a/src/openklant/components/klantinteracties/api/tests/test_partijen.py b/src/openklant/components/klantinteracties/api/tests/test_partijen.py
index c8e3dccf..7beb5f89 100644
--- a/src/openklant/components/klantinteracties/api/tests/test_partijen.py
+++ b/src/openklant/components/klantinteracties/api/tests/test_partijen.py
@@ -344,19 +344,28 @@ def test_create_partij_only_required(self):
             ],
         )
 
-        digitaal_adres = DigitaalAdresFactory()
-
         data = {
-            "digitaleAdressen": [{"uuid": str(digitaal_adres.uuid)}],
-            "voorkeursDigitaalAdres": {"uuid": str(digitaal_adres.uuid)},
-            "rekeningnummers": [],
-            "voorkeursRekeningnummer": None,
             "soortPartij": "persoon",
             "indicatieActief": True,
         }
 
         response = self.client.post(list_url, data)
         self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+        response_data = response.json()
+
+        self.assertEqual(response_data["betrokkenen"], [])
+        self.assertEqual(response_data["categorieRelaties"], [])
+        self.assertEqual(response_data["digitaleAdressen"], [])
+        self.assertEqual(response_data["voorkeursDigitaalAdres"], None)
+        self.assertEqual(response_data["vertegenwoordigden"], [])
+        self.assertEqual(response_data["rekeningnummers"], [])
+        self.assertEqual(response_data["voorkeursRekeningnummer"], None)
+        self.assertEqual(response_data["partijIdentificatoren"], [])
+        self.assertEqual(response_data["soortPartij"], "persoon")
+        self.assertEqual(response_data["indicatieGeheimhouding"], None)
+        self.assertEqual(response_data["voorkeurstaal"], "")
+        self.assertEqual(response_data["indicatieActief"], True)
+        self.assertEqual(response_data["partijIdentificatie"], None)
 
     def test_create_persoon(self):
         list_url = reverse("klantinteracties:partij-list")
diff --git a/src/openklant/components/klantinteracties/openapi.yaml b/src/openklant/components/klantinteracties/openapi.yaml
index fb0120e5..281b522f 100644
--- a/src/openklant/components/klantinteracties/openapi.yaml
+++ b/src/openklant/components/klantinteracties/openapi.yaml
@@ -650,7 +650,6 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/Bijlage'
-        required: true
       security:
       - tokenAuth: []
       responses:
@@ -703,7 +702,6 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/Bijlage'
-        required: true
       security:
       - tokenAuth: []
       responses:
@@ -1939,7 +1937,6 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/Onderwerpobject'
-        required: true
       security:
       - tokenAuth: []
       responses:
@@ -1992,7 +1989,6 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/Onderwerpobject'
-        required: true
       security:
       - tokenAuth: []
       responses:
@@ -2136,7 +2132,6 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/PartijIdentificator'
-        required: true
       security:
       - tokenAuth: []
       responses:
@@ -2189,7 +2184,6 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/PartijIdentificator'
-        required: true
       security:
       - tokenAuth: []
       responses:
@@ -3105,16 +3099,12 @@ components:
       required:
       - betrokkenen
       - categorieRelaties
-      - digitaleAdressen
       - indicatieActief
       - partijIdentificatoren
-      - rekeningnummers
       - soortPartij
       - url
       - uuid
       - vertegenwoordigden
-      - voorkeursDigitaalAdres
-      - voorkeursRekeningnummer
     Betrokkene:
       type: object
       description: |-
@@ -3196,7 +3186,6 @@ components:
       - url
       - uuid
       - volledigeNaam
-      - wasPartij
     BetrokkeneCorrespondentieadres:
       type: object
       properties:
@@ -3327,7 +3316,6 @@ components:
       - url
       - uuid
       - volledigeNaam
-      - wasPartij
     Bezoekadres:
       type: object
       properties:
@@ -3391,7 +3379,6 @@ components:
       required:
       - url
       - uuid
-      - wasBijlageVanKlantcontact
     BijlageForeignKey:
       type: object
       properties:
@@ -3524,8 +3511,6 @@ components:
             Een voorbeeld: 2022-02-21'
       required:
       - beginDatum
-      - categorie
-      - partij
       - url
       - uuid
     CategorieRelatieForeignKey:
@@ -3640,7 +3625,6 @@ components:
           description: De voledige naam van het constact persoon.
       required:
       - volledigeNaam
-      - werkteVoorPartij
     ContactpersoonPersoon:
       type: object
       properties:
@@ -3718,8 +3702,6 @@ components:
       - soortDigitaalAdres
       - url
       - uuid
-      - verstrektDoorBetrokkene
-      - verstrektDoorPartij
     DigitaalAdresForeignKey:
       type: object
       properties:
@@ -4105,10 +4087,8 @@ components:
           description: Gegevens die een onderwerpobject in een extern register uniek
             identificeren.
       required:
-      - klantcontact
       - url
       - uuid
-      - wasKlantcontact
     OnderwerpobjectForeignKey:
       type: object
       properties:
@@ -4166,7 +4146,6 @@ components:
       - klantcontact
       - url
       - uuid
-      - wasKlantcontact
     Onderwerpobjectidentificator:
       type: object
       properties:
@@ -4755,8 +4734,6 @@ components:
           description: Gegevens die een partij in een basisregistratie of ander extern
             register uniek identificeren.
       required:
-      - identificeerdePartij
-      - partijIdentificator
       - url
       - uuid
     PartijIdentificatorForeignkey:
@@ -5373,7 +5350,6 @@ components:
           readOnly: true
           description: De voledige naam van het persoon.
       required:
-      - contactnaam
       - volledigeNaam
     PersoonContact:
       type: object
@@ -5436,7 +5412,6 @@ components:
           minLength: 8
       required:
       - iban
-      - partij
       - url
       - uuid
     RekeningnummerForeignKey:

From 55d18c971edc49277e3224760bdbed0f641daee0 Mon Sep 17 00:00:00 2001
From: Daniel Mursa <daniel@maykinmedia.nl>
Date: Thu, 13 Feb 2025 11:39:02 +0100
Subject: [PATCH 3/4] [#240] Revers logic

---
 .../api/serializers/digitaal_adres.py         | 15 ++-
 .../api/serializers/klantcontacten.py         | 28 +++---
 .../api/serializers/partijen.py               | 98 +++++++++----------
 .../api/serializers/rekeningnummers.py        |  8 +-
 .../components/klantinteracties/openapi.yaml  | 25 +++++
 5 files changed, 97 insertions(+), 77 deletions(-)

diff --git a/src/openklant/components/klantinteracties/api/serializers/digitaal_adres.py b/src/openklant/components/klantinteracties/api/serializers/digitaal_adres.py
index c8410394..1c2c131d 100644
--- a/src/openklant/components/klantinteracties/api/serializers/digitaal_adres.py
+++ b/src/openklant/components/klantinteracties/api/serializers/digitaal_adres.py
@@ -42,7 +42,7 @@ class DigitaalAdresSerializer(serializers.HyperlinkedModelSerializer):
     )
 
     verstrekt_door_partij = PartijForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_(
             "Digitaal adres dat een partij verstrekte voor gebruik bij "
@@ -51,7 +51,7 @@ class DigitaalAdresSerializer(serializers.HyperlinkedModelSerializer):
         source="partij",
     )
     verstrekt_door_betrokkene = BetrokkeneForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_(
             "Digitaal adres dat een betrokkene bij klantcontact verstrekte voor gebruik bij "
@@ -70,13 +70,6 @@ class DigitaalAdresSerializer(serializers.HyperlinkedModelSerializer):
         ".internetaken.InterneTaakSerializer",
     }
 
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        request = self.context.get("request")
-        if request and request.method in ["PUT", "PATCH"]:
-            self.fields["verstrekt_door_partij"].required = True
-            self.fields["verstrekt_door_betrokkene"].required = True
-
     class Meta:
         model = DigitaalAdres
         fields = (
@@ -110,6 +103,10 @@ class Meta:
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
+        request = self.context.get("request", None)
+        if request and request.method == "POST":
+            self.fields["verstrekt_door_partij"].required = False
+            self.fields["verstrekt_door_betrokkene"].required = False
 
         if "soort_digitaal_adres" in self.fields:
             # Avoid validating the UniqueConstraint for `soort_digitaal_adres` with
diff --git a/src/openklant/components/klantinteracties/api/serializers/klantcontacten.py b/src/openklant/components/klantinteracties/api/serializers/klantcontacten.py
index 393e3b1b..929ded0b 100644
--- a/src/openklant/components/klantinteracties/api/serializers/klantcontacten.py
+++ b/src/openklant/components/klantinteracties/api/serializers/klantcontacten.py
@@ -134,7 +134,7 @@ class BetrokkeneSerializer(
     )
 
     was_partij = PartijForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         source="partij",
         help_text=_("Betrokkene bij klantcontact die een partij was."),
@@ -186,9 +186,9 @@ class BetrokkeneSerializer(
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        request = self.context.get("request")
-        if request and request.method in ["PUT", "PATCH"]:
-            self.fields["was_partij"].required = True
+        request = self.context.get("request", None)
+        if request and request.method == "POST":
+            self.fields["was_partij"].required = False
 
     class Meta:
         model = Betrokkene
@@ -342,12 +342,12 @@ class OnderwerpobjectSerializer(
     NestedGegevensGroepMixin, serializers.HyperlinkedModelSerializer
 ):
     klantcontact = KlantcontactForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_("'Klantcontact' ging over 'Onderwerpobject'"),
     )
     was_klantcontact = KlantcontactForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_("'Onderwerpobject' was 'Klantcontact'"),
     )
@@ -362,10 +362,10 @@ class OnderwerpobjectSerializer(
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        request = self.context.get("request")
-        if request and request.method in ["PUT", "PATCH"]:
-            self.fields["klantcontact"].required = True
-            self.fields["was_klantcontact"].required = True
+        request = self.context.get("request", None)
+        if request and request.method == "POST":
+            self.fields["klantcontact"].required = False
+            self.fields["was_klantcontact"].required = False
 
     class Meta:
         model = Onderwerpobject
@@ -432,7 +432,7 @@ class BijlageSerializer(
     NestedGegevensGroepMixin, serializers.HyperlinkedModelSerializer
 ):
     was_bijlage_van_klantcontact = KlantcontactForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_("'Klantcontact' ging over 'Onderwerpobject'"),
         source="klantcontact",
@@ -448,9 +448,9 @@ class BijlageSerializer(
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        request = self.context.get("request")
-        if request and request.method in ["PUT", "PATCH"]:
-            self.fields["was_bijlage_van_klantcontact"].required = True
+        request = self.context.get("request", None)
+        if request and request.method == "POST":
+            self.fields["was_bijlage_van_klantcontact"].required = False
 
     class Meta:
         model = Bijlage
diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py
index 9261bdc5..701d12b0 100644
--- a/src/openklant/components/klantinteracties/api/serializers/partijen.py
+++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py
@@ -198,18 +198,19 @@ class CategorieRelatieSerializer(serializers.HyperlinkedModelSerializer):
     """Let op: Dit endpoint is EXPERIMENTEEL."""
 
     partij = PartijForeignkeyBaseSerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_("De partij waar de categorie relatie aan gelinkt is."),
     )
     categorie = CategorieForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_(
             "De categorie waar de categorie relatie aan gelinkt is: Let op: Dit attribuut is EXPERIMENTEEL."
         ),
     )
     begin_datum = serializers.DateField(
+        required=True,
         allow_null=True,
         help_text=_(
             "Aanduiding van datum volgens de NEN-ISO 8601:2019-standaard. "
@@ -220,10 +221,11 @@ class CategorieRelatieSerializer(serializers.HyperlinkedModelSerializer):
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        request = self.context.get("request")
-        if request and request.method in ["PUT", "PATCH"]:
-            self.fields["partij"].required = True
-            self.fields["categorie"].required = True
+        request = self.context.get("request", None)
+        if request and request.method == "POST":
+            self.fields["begin_datum"].required = False
+            self.fields["partij"].required = False
+            self.fields["categorie"].required = False
 
     class Meta:
         model = CategorieRelatie
@@ -246,35 +248,31 @@ class Meta:
 
     @transaction.atomic
     def update(self, instance, validated_data):
-        if "partij" in validated_data:
-            if partij := validated_data.pop("partij", None):
-                partij = Partij.objects.get(uuid=str(partij.get("uuid")))
+        if partij := validated_data.pop("partij", None):
+            validated_data["partij"] = Partij.objects.get(uuid=str(partij.get("uuid")))
 
-            validated_data["partij"] = partij
-
-        if "categorie" in validated_data:
-            if categorie := validated_data.pop("categorie", None):
-                categorie = Categorie.objects.get(uuid=str(categorie.get("uuid")))
-
-            validated_data["categorie"] = categorie
+        if categorie := validated_data.pop("categorie", None):
+            validated_data["categorie"] = Categorie.objects.get(
+                uuid=str(categorie.get("uuid"))
+            )
 
         return super().update(instance, validated_data)
 
     @transaction.atomic
     def create(self, validated_data):
-        if not validated_data.get("begin_datum"):
-            validated_data["begin_datum"] = datetime.datetime.today().strftime(
-                "%Y-%m-%d"
-            )
+        begin_datum = validated_data.get(
+            "begin_datum", datetime.datetime.today().strftime("%Y-%m-%d")
+        )
 
-        if partij := validated_data.pop("partij"):
-            partij = Partij.objects.get(uuid=str(partij.get("uuid")))
+        validated_data["begin_datum"] = begin_datum
 
-        if categorie := validated_data.pop("categorie"):
-            categorie = Categorie.objects.get(uuid=str(categorie.get("uuid")))
+        if partij := validated_data.pop("partij", None):
+            validated_data["partij"] = Partij.objects.get(uuid=str(partij.get("uuid")))
 
-        validated_data["partij"] = partij
-        validated_data["categorie"] = categorie
+        if categorie := validated_data.pop("categorie", None):
+            validated_data["categorie"] = Categorie.objects.get(
+                uuid=str(categorie.get("uuid"))
+            )
 
         return super().create(validated_data)
 
@@ -293,7 +291,7 @@ class Meta:
 
 class PersoonSerializer(NestedGegevensGroepMixin, serializers.ModelSerializer):
     contactnaam = PersoonContactSerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_(
             "Naam die een persoon wil gebruiken tijdens contact met de gemeente. "
@@ -307,9 +305,9 @@ class PersoonSerializer(NestedGegevensGroepMixin, serializers.ModelSerializer):
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        request = self.context.get("request")
-        if request and request.method in ["PUT", "PATCH"]:
-            self.fields["contactnaam"].required = True
+        request = self.context.get("request", None)
+        if request and request.method == "POST":
+            self.fields["contactnaam"].required = False
 
     class Meta:
         model = Persoon
@@ -324,7 +322,7 @@ def get_volledige_naam(self, obj) -> str:
 
 class ContactpersoonSerializer(NestedGegevensGroepMixin, serializers.ModelSerializer):
     werkte_voor_partij = PartijPolymorphicSerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_("Organisatie waarvoor een contactpersoon werkte."),
     )
@@ -343,9 +341,9 @@ class ContactpersoonSerializer(NestedGegevensGroepMixin, serializers.ModelSerial
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        request = self.context.get("request")
-        if request and request.method in ["PUT", "PATCH"]:
-            self.fields["werkte_voor_partij"].required = True
+        request = self.context.get("request", None)
+        if request and request.method == "POST":
+            self.fields["werkte_voor_partij"].required = False
 
     class Meta:
         model = Contactpersoon
@@ -389,13 +387,13 @@ class PartijIdentificatorSerializer(
     NestedGegevensGroepMixin, serializers.HyperlinkedModelSerializer
 ):
     identificeerde_partij = PartijForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_("Partij-identificator die hoorde bij een partij."),
         source="partij",
     )
     partij_identificator = PartijIdentificatorGroepTypeSerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_(
             "Gegevens die een partij in een basisregistratie "
@@ -405,10 +403,10 @@ class PartijIdentificatorSerializer(
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        request = self.context.get("request")
-        if request and request.method in ["PUT", "PATCH"]:
-            self.fields["identificeerde_partij"].required = True
-            self.fields["partij_identificator"].required = True
+        request = self.context.get("request", None)
+        if request and request.method == "POST":
+            self.fields["identificeerde_partij"].required = False
+            self.fields["partij_identificator"].required = False
 
     class Meta:
         model = PartijIdentificator
@@ -487,7 +485,7 @@ class PartijSerializer(NestedGegevensGroepMixin, PolymorphicSerializer):
         source="categorierelatie_set",
     )
     digitale_adressen = DigitaalAdresForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_(
             "Digitaal adresen dat een partij verstrekte voor gebruik bij "
@@ -497,21 +495,21 @@ class PartijSerializer(NestedGegevensGroepMixin, PolymorphicSerializer):
         many=True,
     )
     voorkeurs_digitaal_adres = DigitaalAdresForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_(
             "Digitaal adres waarop een partij bij voorkeur door de gemeente benaderd wordt."
         ),
     )
     rekeningnummers = RekeningnummerForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_("Rekeningnummers van een partij"),
         source="rekeningnummer_set",
         many=True,
     )
     voorkeurs_rekeningnummer = RekeningnummerForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_("Rekeningsnummer die een partij bij voorkeur gebruikt."),
     )
@@ -554,12 +552,12 @@ class PartijSerializer(NestedGegevensGroepMixin, PolymorphicSerializer):
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        request = self.context.get("request")
-        if request and request.method in ["PUT", "PATCH"]:
-            self.fields["digitale_adressen"].required = True
-            self.fields["voorkeurs_digitaal_adres"].required = True
-            self.fields["rekeningnummers"].required = True
-            self.fields["voorkeurs_rekeningnummer"].required = True
+        request = self.context.get("request", None)
+        if request and request.method == "POST":
+            self.fields["digitale_adressen"].required = False
+            self.fields["voorkeurs_digitaal_adres"].required = False
+            self.fields["rekeningnummers"].required = False
+            self.fields["voorkeurs_rekeningnummer"].required = False
 
     class Meta:
         model = Partij
diff --git a/src/openklant/components/klantinteracties/api/serializers/rekeningnummers.py b/src/openklant/components/klantinteracties/api/serializers/rekeningnummers.py
index 79a47d7f..a2b507d5 100644
--- a/src/openklant/components/klantinteracties/api/serializers/rekeningnummers.py
+++ b/src/openklant/components/klantinteracties/api/serializers/rekeningnummers.py
@@ -33,16 +33,16 @@ class RekeningnummerSerializer(serializers.HyperlinkedModelSerializer):
     )
 
     partij = PartijForeignKeySerializer(
-        required=False,
+        required=True,
         allow_null=True,
         help_text=_("Rekeningnummer van een partij"),
     )
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        request = self.context.get("request")
-        if request and request.method in ["PUT", "PATCH"]:
-            self.fields["partij"].required = True
+        request = self.context.get("request", None)
+        if request and request.method == "POST":
+            self.fields["partij"].required = False
 
     class Meta:
         model = Rekeningnummer
diff --git a/src/openklant/components/klantinteracties/openapi.yaml b/src/openklant/components/klantinteracties/openapi.yaml
index 281b522f..fb0120e5 100644
--- a/src/openklant/components/klantinteracties/openapi.yaml
+++ b/src/openklant/components/klantinteracties/openapi.yaml
@@ -650,6 +650,7 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/Bijlage'
+        required: true
       security:
       - tokenAuth: []
       responses:
@@ -702,6 +703,7 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/Bijlage'
+        required: true
       security:
       - tokenAuth: []
       responses:
@@ -1937,6 +1939,7 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/Onderwerpobject'
+        required: true
       security:
       - tokenAuth: []
       responses:
@@ -1989,6 +1992,7 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/Onderwerpobject'
+        required: true
       security:
       - tokenAuth: []
       responses:
@@ -2132,6 +2136,7 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/PartijIdentificator'
+        required: true
       security:
       - tokenAuth: []
       responses:
@@ -2184,6 +2189,7 @@ paths:
           application/json:
             schema:
               $ref: '#/components/schemas/PartijIdentificator'
+        required: true
       security:
       - tokenAuth: []
       responses:
@@ -3099,12 +3105,16 @@ components:
       required:
       - betrokkenen
       - categorieRelaties
+      - digitaleAdressen
       - indicatieActief
       - partijIdentificatoren
+      - rekeningnummers
       - soortPartij
       - url
       - uuid
       - vertegenwoordigden
+      - voorkeursDigitaalAdres
+      - voorkeursRekeningnummer
     Betrokkene:
       type: object
       description: |-
@@ -3186,6 +3196,7 @@ components:
       - url
       - uuid
       - volledigeNaam
+      - wasPartij
     BetrokkeneCorrespondentieadres:
       type: object
       properties:
@@ -3316,6 +3327,7 @@ components:
       - url
       - uuid
       - volledigeNaam
+      - wasPartij
     Bezoekadres:
       type: object
       properties:
@@ -3379,6 +3391,7 @@ components:
       required:
       - url
       - uuid
+      - wasBijlageVanKlantcontact
     BijlageForeignKey:
       type: object
       properties:
@@ -3511,6 +3524,8 @@ components:
             Een voorbeeld: 2022-02-21'
       required:
       - beginDatum
+      - categorie
+      - partij
       - url
       - uuid
     CategorieRelatieForeignKey:
@@ -3625,6 +3640,7 @@ components:
           description: De voledige naam van het constact persoon.
       required:
       - volledigeNaam
+      - werkteVoorPartij
     ContactpersoonPersoon:
       type: object
       properties:
@@ -3702,6 +3718,8 @@ components:
       - soortDigitaalAdres
       - url
       - uuid
+      - verstrektDoorBetrokkene
+      - verstrektDoorPartij
     DigitaalAdresForeignKey:
       type: object
       properties:
@@ -4087,8 +4105,10 @@ components:
           description: Gegevens die een onderwerpobject in een extern register uniek
             identificeren.
       required:
+      - klantcontact
       - url
       - uuid
+      - wasKlantcontact
     OnderwerpobjectForeignKey:
       type: object
       properties:
@@ -4146,6 +4166,7 @@ components:
       - klantcontact
       - url
       - uuid
+      - wasKlantcontact
     Onderwerpobjectidentificator:
       type: object
       properties:
@@ -4734,6 +4755,8 @@ components:
           description: Gegevens die een partij in een basisregistratie of ander extern
             register uniek identificeren.
       required:
+      - identificeerdePartij
+      - partijIdentificator
       - url
       - uuid
     PartijIdentificatorForeignkey:
@@ -5350,6 +5373,7 @@ components:
           readOnly: true
           description: De voledige naam van het persoon.
       required:
+      - contactnaam
       - volledigeNaam
     PersoonContact:
       type: object
@@ -5412,6 +5436,7 @@ components:
           minLength: 8
       required:
       - iban
+      - partij
       - url
       - uuid
     RekeningnummerForeignKey:

From 164fabda1424963f4ca63be2624e77e783c518d6 Mon Sep 17 00:00:00 2001
From: Daniel Mursa <daniel@maykinmedia.nl>
Date: Thu, 13 Feb 2025 12:33:43 +0100
Subject: [PATCH 4/4] Fix test

---
 .../api/serializers/partijen.py               | 33 +++++++++++--------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py
index 701d12b0..93eab953 100644
--- a/src/openklant/components/klantinteracties/api/serializers/partijen.py
+++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py
@@ -248,30 +248,37 @@ class Meta:
 
     @transaction.atomic
     def update(self, instance, validated_data):
-        if partij := validated_data.pop("partij", None):
-            validated_data["partij"] = Partij.objects.get(uuid=str(partij.get("uuid")))
 
-        if categorie := validated_data.pop("categorie", None):
+        if "partij" in validated_data:
+            validated_data["partij"] = Partij.objects.get(
+                uuid=str(validated_data["partij"].get("uuid"))
+            )
+
+        if "categorie" in validated_data:
             validated_data["categorie"] = Categorie.objects.get(
-                uuid=str(categorie.get("uuid"))
+                uuid=str(validated_data["categorie"].get("uuid"))
             )
 
         return super().update(instance, validated_data)
 
     @transaction.atomic
     def create(self, validated_data):
-        begin_datum = validated_data.get(
-            "begin_datum", datetime.datetime.today().strftime("%Y-%m-%d")
-        )
-
-        validated_data["begin_datum"] = begin_datum
+        if "begin_datum" in validated_data:
+            begin_datum = validated_data["begin_datum"]
+            validated_data["begin_datum"] = (
+                begin_datum
+                if begin_datum
+                else datetime.datetime.today().strftime("%Y-%m-%d")
+            )
 
-        if partij := validated_data.pop("partij", None):
-            validated_data["partij"] = Partij.objects.get(uuid=str(partij.get("uuid")))
+        if "partij" in validated_data:
+            validated_data["partij"] = Partij.objects.get(
+                uuid=str(validated_data["partij"].get("uuid"))
+            )
 
-        if categorie := validated_data.pop("categorie", None):
+        if "categorie" in validated_data:
             validated_data["categorie"] = Categorie.objects.get(
-                uuid=str(categorie.get("uuid"))
+                uuid=str(validated_data["categorie"].get("uuid"))
             )
 
         return super().create(validated_data)