From cde9054eab244be80aa39671b3ada895bdb697f3 Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Tue, 21 Jan 2025 12:11:15 +0100 Subject: [PATCH 01/11] [#239] Fix createPartij endpoint --- .../api/serializers/partijen.py | 15 ++++++++--- .../api/tests/test_partijen.py | 25 ++++++++++++------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py index 5894696b..0fe352ff 100644 --- a/src/openklant/components/klantinteracties/api/serializers/partijen.py +++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py @@ -370,7 +370,7 @@ 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", @@ -492,8 +492,7 @@ class PartijSerializer(NestedGegevensGroepMixin, PolymorphicSerializer): vertegenwoordigden = serializers.SerializerMethodField( help_text=_("Partijen die een andere partijen vertegenwoordigden."), ) - partij_identificatoren = PartijIdentificatorForeignkeySerializer( - read_only=True, + partij_identificatoren = PartijIdentificatorSerializer( many=True, source="partijidentificator_set", help_text=_("Partij-identificatoren die hoorde bij deze partij."), @@ -737,6 +736,7 @@ 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") + partij_identificatoren = validated_data.pop("partijidentificator_set", []) if voorkeurs_digitaal_adres := validated_data.pop( "voorkeurs_digitaal_adres", None @@ -814,6 +814,15 @@ def create(self, validated_data): rekeningnummer.partij = partij rekeningnummer.save() + if partij_identificatoren: + for partij_identificator in partij_identificatoren: + partij_identificator["partij"] = {"uuid": str(partij.uuid)} + partij_identificator_serializer = PartijIdentificatorSerializer( + data=partij_identificator + ) + partij_identificator_serializer.is_valid(raise_exception=True) + partij_identificator_serializer.create(partij_identificator) + return partij diff --git a/src/openklant/components/klantinteracties/api/tests/test_partijen.py b/src/openklant/components/klantinteracties/api/tests/test_partijen.py index fa925abd..d4ea1f26 100644 --- a/src/openklant/components/klantinteracties/api/tests/test_partijen.py +++ b/src/openklant/components/klantinteracties/api/tests/test_partijen.py @@ -131,6 +131,17 @@ def test_create_partij(self): "achternaam": "Bozeman", } }, + "partijIdentificatoren": [ + { + "anderePartijIdentificator": "string", + "partijIdentificator": { + "codeObjecttype": "natuurlijk_persoon", + "codeSoortObjectId": "bsn", + "objectId": "296648875", + "codeRegister": "brp", + }, + } + ], } response = self.client.post(list_url, data) @@ -174,18 +185,14 @@ def test_create_partij(self): }, ) self.assertEqual( - data["partijIdentificatie"], + data["partijIdentificatoren"][0]["partijIdentificator"], { - "volledigeNaam": "Phil Bozeman", - "contactnaam": { - "voorletters": "P", - "voornaam": "Phil", - "voorvoegselAchternaam": "", - "achternaam": "Bozeman", - }, + "codeObjecttype": "natuurlijk_persoon", + "codeSoortObjectId": "bsn", + "objectId": "296648875", + "codeRegister": "brp", }, ) - with self.subTest("create_partij_without_foreignkey_relations"): data["nummer"] = "1298329192" data["digitaleAdressen"] = [] From a7f4a61916c13a7df353917ca85702916c3cda97 Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Tue, 21 Jan 2025 12:15:31 +0100 Subject: [PATCH 02/11] [#239] Add required=False --- .../components/klantinteracties/api/serializers/partijen.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py index 0fe352ff..53b98177 100644 --- a/src/openklant/components/klantinteracties/api/serializers/partijen.py +++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py @@ -494,6 +494,7 @@ class PartijSerializer(NestedGegevensGroepMixin, PolymorphicSerializer): ) partij_identificatoren = PartijIdentificatorSerializer( many=True, + required=False, source="partijidentificator_set", help_text=_("Partij-identificatoren die hoorde bij deze partij."), ) From 80e01386ea5ea35c313161d751b4d12c29e0199f Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Wed, 22 Jan 2025 09:42:40 +0100 Subject: [PATCH 03/11] [#239] Fix updatePartij --- .../api/serializers/partijen.py | 12 ++++++ .../api/tests/test_partijen.py | 39 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py index 53b98177..b08b3a37 100644 --- a/src/openklant/components/klantinteracties/api/serializers/partijen.py +++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py @@ -571,6 +571,7 @@ def get_vertegenwoordigden(self, obj): def update(self, instance, validated_data): method = self.context.get("request").method partij_identificatie = validated_data.pop("partij_identificatie", None) + partij_identificatoren = validated_data.pop("partijidentificator_set", []) if "digitaaladres_set" in validated_data: existing_digitale_adressen = instance.digitaaladres_set.all() @@ -717,6 +718,17 @@ def update(self, instance, validated_data): partij = super().update(instance, validated_data) + if partij_identificatoren: + partij.partijidentificator_set.all().delete() + for partij_identificator in partij_identificatoren: + partij_identificator["partij"] = {"uuid": str(partij.uuid)} + partij_identificator_serializer = PartijIdentificatorSerializer( + data=partij_identificator + ) + partij_identificator_serializer.is_valid(raise_exception=True) + partij_identificator_serializer.create(partij_identificator) + + if partij_identificatie: serializer_class = self.discriminator.mapping[ validated_data.get("soort_partij") diff --git a/src/openklant/components/klantinteracties/api/tests/test_partijen.py b/src/openklant/components/klantinteracties/api/tests/test_partijen.py index d4ea1f26..c898377d 100644 --- a/src/openklant/components/klantinteracties/api/tests/test_partijen.py +++ b/src/openklant/components/klantinteracties/api/tests/test_partijen.py @@ -680,6 +680,14 @@ def test_update_partij(self): rekeningnummer = RekeningnummerFactory.create(partij=partij) rekeningnummer2 = RekeningnummerFactory.create() + partij_identificator = PartijIdentificatorFactory.create( + partij=partij, + partij_identificator_code_objecttype="natuurlijk_persoon", + partij_identificator_code_soort_object_id="bsn", + partij_identificator_object_id="296648875", + partij_identificator_code_register="brp", + ) + detail_url = reverse( "klantinteracties:partij-detail", kwargs={"uuid": str(partij.uuid)} ) @@ -745,6 +753,16 @@ def test_update_partij(self): }, ) + self.assertEqual( + data["partijIdentificatoren"][0]["partijIdentificator"], + { + "codeObjecttype": partij_identificator.partij_identificator_code_objecttype, + "codeSoortObjectId": partij_identificator.partij_identificator_code_soort_object_id, + "objectId": partij_identificator.partij_identificator_object_id, + "codeRegister": partij_identificator.partij_identificator_code_register, + }, + ) + data = { "nummer": "6427834668", "interneNotitie": "changed", @@ -778,6 +796,17 @@ def test_update_partij(self): "achternaam": "Bennette", } }, + "partijIdentificatoren": [ + { + "anderePartijIdentificator": "string", + "partijIdentificator": { + "codeObjecttype": "niet_natuurlijk_persoon", + "codeSoortObjectId": "rsin", + "objectId": "296648875", + "codeRegister": "hr", + }, + } + ], } response = self.client.put(detail_url, data) @@ -846,6 +875,16 @@ def test_update_partij(self): }, }, ) + self.assertEqual(len(data["partijIdentificatoren"]), 1) + self.assertEqual( + data["partijIdentificatoren"][0]["partijIdentificator"], + { + "codeObjecttype": "niet_natuurlijk_persoon", + "codeSoortObjectId": "rsin", + "objectId": "296648875", + "codeRegister": "hr", + }, + ) with self.subTest( "test_voorkeurs_digitaal_adres_must_be_part_of_digitale_adressen" From 8f46653bfa07c91da744704c1972c5801b123a0b Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Wed, 22 Jan 2025 09:48:12 +0100 Subject: [PATCH 04/11] [#239] Formatting --- .../components/klantinteracties/api/serializers/partijen.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py index b08b3a37..b0176ea3 100644 --- a/src/openklant/components/klantinteracties/api/serializers/partijen.py +++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py @@ -728,7 +728,6 @@ def update(self, instance, validated_data): partij_identificator_serializer.is_valid(raise_exception=True) partij_identificator_serializer.create(partij_identificator) - if partij_identificatie: serializer_class = self.discriminator.mapping[ validated_data.get("soort_partij") From 14f0ae5b1265272bf0064ccd3129fc4412300edc Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Wed, 22 Jan 2025 10:54:07 +0100 Subject: [PATCH 05/11] [#239] Fix case create without partij --- .../api/serializers/partijen.py | 25 ++++++++++++++----- .../api/tests/test_partijen.py | 24 ++++++++++++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py index b0176ea3..8e21979c 100644 --- a/src/openklant/components/klantinteracties/api/serializers/partijen.py +++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py @@ -425,9 +425,14 @@ def update(self, instance, validated_data): @transaction.atomic def create(self, validated_data): - partij_uuid = str(validated_data.pop("partij").get("uuid")) - validated_data["partij"] = Partij.objects.get(uuid=partij_uuid) + partij = validated_data.pop("partij", None) + if not partij: + raise serializers.ValidationError( + {"identificeerde_partij": _("Dit veld is vereist.")}, + code="required", + ) + validated_data["partij"] = Partij.objects.get(uuid=str(partij.get("uuid"))) return super().create(validated_data) @@ -721,12 +726,16 @@ def update(self, instance, validated_data): if partij_identificatoren: partij.partijidentificator_set.all().delete() for partij_identificator in partij_identificatoren: - partij_identificator["partij"] = {"uuid": str(partij.uuid)} + partij_identificator["identificeerde_partij"] = { + "uuid": str(partij.uuid) + } partij_identificator_serializer = PartijIdentificatorSerializer( data=partij_identificator ) partij_identificator_serializer.is_valid(raise_exception=True) - partij_identificator_serializer.create(partij_identificator) + partij_identificator_serializer.create( + partij_identificator_serializer.validated_data + ) if partij_identificatie: serializer_class = self.discriminator.mapping[ @@ -828,12 +837,16 @@ def create(self, validated_data): if partij_identificatoren: for partij_identificator in partij_identificatoren: - partij_identificator["partij"] = {"uuid": str(partij.uuid)} + partij_identificator["identificeerde_partij"] = { + "uuid": str(partij.uuid) + } partij_identificator_serializer = PartijIdentificatorSerializer( data=partij_identificator ) partij_identificator_serializer.is_valid(raise_exception=True) - partij_identificator_serializer.create(partij_identificator) + partij_identificator_serializer.create( + partij_identificator_serializer.validated_data + ) return partij diff --git a/src/openklant/components/klantinteracties/api/tests/test_partijen.py b/src/openklant/components/klantinteracties/api/tests/test_partijen.py index c898377d..3d3bfed4 100644 --- a/src/openklant/components/klantinteracties/api/tests/test_partijen.py +++ b/src/openklant/components/klantinteracties/api/tests/test_partijen.py @@ -1946,6 +1946,30 @@ def test_create_partij_indetificator(self): }, ) + def test_create_partij_indetificator_invalid_without_identificeerdePartij(self): + list_url = reverse("klantinteracties:partijidentificator-list") + data = { + "anderePartijIdentificator": "anderePartijIdentificator", + "partijIdentificator": { + "codeObjecttype": "natuurlijk_persoon", + "codeSoortObjectId": "bsn", + "objectId": "296648875", + "codeRegister": "brp", + }, + } + + response = self.client.post(list_url, data) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertEqual(response.data["code"], "invalid") + self.assertEqual(response.data["title"], "Invalid input.") + self.assertEqual( + response.data["invalid_params"][0]["name"], "identificeerdePartij" + ) + self.assertEqual(response.data["invalid_params"][0]["code"], "required") + self.assertEqual( + response.data["invalid_params"][0]["reason"], "Dit veld is vereist." + ) + def test_update_partij_indetificator(self): partij, partij2 = PartijFactory.create_batch(2) partij_identificator = PartijIdentificatorFactory.create( From 9ca5e79e9295495d5c00284af41940a08c4d86ab Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Wed, 22 Jan 2025 10:58:02 +0100 Subject: [PATCH 06/11] [#239] bin/generate_schema_for_component.sh --- .../components/klantinteracties/openapi.yaml | 22 +------------------ 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/openklant/components/klantinteracties/openapi.yaml b/src/openklant/components/klantinteracties/openapi.yaml index 415c1319..ac5381af 100644 --- a/src/openklant/components/klantinteracties/openapi.yaml +++ b/src/openklant/components/klantinteracties/openapi.yaml @@ -3065,8 +3065,7 @@ components: partijIdentificatoren: type: array items: - $ref: '#/components/schemas/PartijIdentificatorForeignkey' - readOnly: true + $ref: '#/components/schemas/PartijIdentificator' description: Partij-identificatoren die hoorde bij deze partij. soortPartij: allOf: @@ -3107,7 +3106,6 @@ components: - categorieRelaties - digitaleAdressen - indicatieActief - - partijIdentificatoren - rekeningnummers - soortPartij - url @@ -4751,27 +4749,9 @@ components: description: Gegevens die een partij in een basisregistratie of ander extern register uniek identificeren. required: - - identificeerdePartij - partijIdentificator - url - uuid - PartijIdentificatorForeignkey: - type: object - properties: - uuid: - type: string - format: uuid - description: Unieke (technische) identificatiecode van de partij-identificator. - url: - type: string - format: uri - readOnly: true - description: De unieke URL van deze partij indentificator binnen deze API. - minLength: 1 - maxLength: 1000 - required: - - url - - uuid PartijIdentificatorGroepType: type: object properties: From e64b9018925a7336115bd995c76b85d3227ffca2 Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Wed, 22 Jan 2025 11:35:46 +0100 Subject: [PATCH 07/11] [#239] Fix test empty_list for partijidentificatoren --- .../api/serializers/partijen.py | 8 +- .../api/tests/test_partijen.py | 99 +++++++++++++++++++ 2 files changed, 103 insertions(+), 4 deletions(-) diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py index 8e21979c..3ff9e42f 100644 --- a/src/openklant/components/klantinteracties/api/serializers/partijen.py +++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py @@ -576,7 +576,7 @@ def get_vertegenwoordigden(self, obj): def update(self, instance, validated_data): method = self.context.get("request").method partij_identificatie = validated_data.pop("partij_identificatie", None) - partij_identificatoren = validated_data.pop("partijidentificator_set", []) + partij_identificatoren = validated_data.pop("partijidentificator_set", None) if "digitaaladres_set" in validated_data: existing_digitale_adressen = instance.digitaaladres_set.all() @@ -723,7 +723,7 @@ def update(self, instance, validated_data): partij = super().update(instance, validated_data) - if partij_identificatoren: + if partij_identificatoren is not None: partij.partijidentificator_set.all().delete() for partij_identificator in partij_identificatoren: partij_identificator["identificeerde_partij"] = { @@ -757,7 +757,7 @@ 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") - partij_identificatoren = validated_data.pop("partijidentificator_set", []) + partij_identificatoren = validated_data.pop("partijidentificator_set", None) if voorkeurs_digitaal_adres := validated_data.pop( "voorkeurs_digitaal_adres", None @@ -835,7 +835,7 @@ def create(self, validated_data): rekeningnummer.partij = partij rekeningnummer.save() - if partij_identificatoren: + if partij_identificatoren is not None: for partij_identificator in partij_identificatoren: partij_identificator["identificeerde_partij"] = { "uuid": str(partij.uuid) diff --git a/src/openklant/components/klantinteracties/api/tests/test_partijen.py b/src/openklant/components/klantinteracties/api/tests/test_partijen.py index 3d3bfed4..42558a01 100644 --- a/src/openklant/components/klantinteracties/api/tests/test_partijen.py +++ b/src/openklant/components/klantinteracties/api/tests/test_partijen.py @@ -1024,6 +1024,105 @@ def test_update_partij(self): }, ) + def test_update_partij_partijidentificator_empty_list(self): + partij = PartijFactory.create( + nummer="1298329191", + interne_notitie="interneNotitie", + voorkeurs_digitaal_adres=None, + voorkeurs_rekeningnummer=None, + soort_partij="persoon", + indicatie_geheimhouding=True, + voorkeurstaal="ndl", + indicatie_actief=True, + bezoekadres_nummeraanduiding_id="095be615-a8ad-4c33-8e9c-c7612fbf6c9f", + bezoekadres_adresregel1="adres1", + bezoekadres_adresregel2="adres2", + bezoekadres_adresregel3="adres3", + bezoekadres_land="6030", + correspondentieadres_nummeraanduiding_id="095be615-a8ad-4c33-8e9c-c7612fbf6c9f", + correspondentieadres_adresregel1="adres1", + correspondentieadres_adresregel2="adres2", + correspondentieadres_adresregel3="adres3", + correspondentieadres_land="6030", + ) + PersoonFactory.create( + partij=partij, + contactnaam_voorletters="P", + contactnaam_voornaam="Phil", + contactnaam_voorvoegsel_achternaam="", + contactnaam_achternaam="Bozeman", + ) + + digitaal_adres2 = DigitaalAdresFactory.create() + rekeningnummer2 = RekeningnummerFactory.create() + + partij_identificator = PartijIdentificatorFactory.create( + partij=partij, + partij_identificator_code_objecttype="natuurlijk_persoon", + partij_identificator_code_soort_object_id="bsn", + partij_identificator_object_id="296648875", + partij_identificator_code_register="brp", + ) + + detail_url = reverse( + "klantinteracties:partij-detail", kwargs={"uuid": str(partij.uuid)} + ) + response = self.client.get(detail_url) + data = response.json() + self.assertEqual(partij.partijidentificator_set.all().count(), 1) + self.assertEqual( + data["partijIdentificatoren"][0]["partijIdentificator"], + { + "codeObjecttype": partij_identificator.partij_identificator_code_objecttype, + "codeSoortObjectId": partij_identificator.partij_identificator_code_soort_object_id, + "objectId": partij_identificator.partij_identificator_object_id, + "codeRegister": partij_identificator.partij_identificator_code_register, + }, + ) + + data = { + "nummer": "6427834668", + "interneNotitie": "changed", + "digitaleAdressen": [{"uuid": str(digitaal_adres2.uuid)}], + "voorkeursDigitaalAdres": {"uuid": str(digitaal_adres2.uuid)}, + "rekeningnummers": [{"uuid": str(rekeningnummer2.uuid)}], + "voorkeursRekeningnummer": {"uuid": str(rekeningnummer2.uuid)}, + "soortPartij": "persoon", + "indicatieGeheimhouding": None, + "voorkeurstaal": "ger", + "indicatieActief": False, + "bezoekadres": { + "nummeraanduidingId": "f78sd8f-uh45-34km-2o3n-aasdasdasc9g", + "adresregel1": "changed", + "adresregel2": "changed", + "adresregel3": "changed", + "land": "3060", + }, + "correspondentieadres": { + "nummeraanduidingId": "sd76f7sd-j4nr-a9s8-83ec-sad89f79a7sd", + "adresregel1": "changed", + "adresregel2": "changed", + "adresregel3": "changed", + "land": "3060", + }, + "partijIdentificatie": { + "contactnaam": { + "voorletters": "V", + "voornaam": "Vincent", + "voorvoegselAchternaam": "", + "achternaam": "Bennette", + } + }, + "partijIdentificatoren": [], + } + + response = self.client.put(detail_url, data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + data = response.json() + + self.assertEqual(len(data["partijIdentificatoren"]), 0) + self.assertEqual(partij.partijidentificator_set.all().count(), 0) + def test_update_partij_persoon(self): partij = PartijFactory.create( nummer="1298329191", From 7c301777e49a2d8505ebde2482e1c84992d096eb Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Thu, 23 Jan 2025 12:00:34 +0100 Subject: [PATCH 08/11] [#239] Fix test naming --- .../components/klantinteracties/api/tests/test_partijen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/openklant/components/klantinteracties/api/tests/test_partijen.py b/src/openklant/components/klantinteracties/api/tests/test_partijen.py index 42558a01..499ca11a 100644 --- a/src/openklant/components/klantinteracties/api/tests/test_partijen.py +++ b/src/openklant/components/klantinteracties/api/tests/test_partijen.py @@ -2045,7 +2045,7 @@ def test_create_partij_indetificator(self): }, ) - def test_create_partij_indetificator_invalid_without_identificeerdePartij(self): + def test_create_partij_indentificator_invalid_without_identificeerdePartij(self): list_url = reverse("klantinteracties:partijidentificator-list") data = { "anderePartijIdentificator": "anderePartijIdentificator", From 91edb968a5d4649f7fae2fd18fff2899485a43b6 Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Fri, 24 Jan 2025 11:41:35 +0100 Subject: [PATCH 09/11] [#239] Add uuid as an allowed parameter --- .../api/serializers/partijen.py | 53 ++++++--- .../api/tests/test_partijen.py | 106 +++++++++++++++++- 2 files changed, 139 insertions(+), 20 deletions(-) diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py index 3ff9e42f..c65cefd5 100644 --- a/src/openklant/components/klantinteracties/api/serializers/partijen.py +++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py @@ -376,7 +376,7 @@ class PartijIdentificatorSerializer( source="partij", ) partij_identificator = PartijIdentificatorGroepTypeSerializer( - required=True, + required=False, allow_null=True, help_text=_( "Gegevens die een partij in een basisregistratie " @@ -395,7 +395,7 @@ class Meta: ) extra_kwargs = { - "uuid": {"read_only": True}, + "uuid": {"required": False, "validators": [partij_identificator_exists]}, "url": { "view_name": "klantinteracties:partijidentificator-detail", "lookup_field": "uuid", @@ -403,15 +403,17 @@ class Meta: }, } - def validate(self, attrs): - partij_identificator = get_field_value(self, attrs, "partij_identificator") - PartijIdentificatorValidator( - code_register=partij_identificator["code_register"], - code_objecttype=partij_identificator["code_objecttype"], - code_soort_object_id=partij_identificator["code_soort_object_id"], - object_id=partij_identificator["object_id"], - ).validate() - return super().validate(attrs) + def validate_partij_identificator(self, value): + if value: + PartijIdentificatorValidator( + code_register=get_field_value(self, value, "code_register"), + code_objecttype=get_field_value(self, value, "code_objecttype"), + code_soort_object_id=get_field_value( + self, value, "code_soort_object_id" + ), + object_id=get_field_value(self, value, "object_id"), + ).validate() + return value @transaction.atomic def update(self, instance, validated_data): @@ -500,6 +502,7 @@ class PartijSerializer(NestedGegevensGroepMixin, PolymorphicSerializer): partij_identificatoren = PartijIdentificatorSerializer( many=True, required=False, + allow_null=True, source="partijidentificator_set", help_text=_("Partij-identificatoren die hoorde bij deze partij."), ) @@ -572,12 +575,27 @@ def get_vertegenwoordigden(self, obj): if vertegenwoordigende ] + def validate_partij_identificatoren(self, value): + if not value: + return value + + for identificator in value: + if {"uuid", "partij_identificator"} <= identificator.keys(): + raise serializers.ValidationError( + { + "partij_identificatoren": _( + "Slechts één van deze twee sleutels `uuid` of `partij_identificator` is toegestaan." + ) + } + ) + return value + @transaction.atomic def update(self, instance, validated_data): + method = self.context.get("request").method partij_identificatie = validated_data.pop("partij_identificatie", None) partij_identificatoren = validated_data.pop("partijidentificator_set", None) - if "digitaaladres_set" in validated_data: existing_digitale_adressen = instance.digitaaladres_set.all() digitaal_adres_uuids = [ @@ -844,9 +862,14 @@ def create(self, validated_data): data=partij_identificator ) partij_identificator_serializer.is_valid(raise_exception=True) - partij_identificator_serializer.create( - partij_identificator_serializer.validated_data - ) + if "uuid" in partij_identificator: + PartijIdentificator.objects.filter( + uuid=partij_identificator["uuid"] + ).update(partij=partij) + else: + partij_identificator_serializer.create( + partij_identificator_serializer.validated_data + ) return partij diff --git a/src/openklant/components/klantinteracties/api/tests/test_partijen.py b/src/openklant/components/klantinteracties/api/tests/test_partijen.py index 499ca11a..fda1ffb8 100644 --- a/src/openklant/components/klantinteracties/api/tests/test_partijen.py +++ b/src/openklant/components/klantinteracties/api/tests/test_partijen.py @@ -98,6 +98,14 @@ def test_read_partij(self): def test_create_partij(self): digitaal_adres, digitaal_adres2 = DigitaalAdresFactory.create_batch(2) rekeningnummer, rekeningnummer2 = RekeningnummerFactory.create_batch(2) + + partij_identificator = PartijIdentificatorFactory.create( + partij_identificator_code_objecttype="natuurlijk_persoon", + partij_identificator_code_soort_object_id="bsn", + partij_identificator_object_id="296648875", + partij_identificator_code_register="brp", + ) + list_url = reverse("klantinteracties:partij-list") data = { "nummer": "1298329191", @@ -140,7 +148,10 @@ def test_create_partij(self): "objectId": "296648875", "codeRegister": "brp", }, - } + }, + { + "uuid": str(partij_identificator.uuid), + }, ], } @@ -184,6 +195,14 @@ def test_create_partij(self): "land": "6030", }, ) + self.assertEqual(len(data["partijIdentificatoren"]), 2) + self.assertTrue( + str(partij_identificator.uuid) + in [ + identificator["uuid"] for identificator in data["partijIdentificatoren"] + ] + ) + self.assertEqual( data["partijIdentificatoren"][0]["partijIdentificator"], { @@ -193,6 +212,9 @@ def test_create_partij(self): "codeRegister": "brp", }, ) + + data["partijIdentificatoren"] = None + with self.subTest("create_partij_without_foreignkey_relations"): data["nummer"] = "1298329192" data["digitaleAdressen"] = [] @@ -886,6 +908,8 @@ def test_update_partij(self): }, ) + data["partijIdentificatoren"] = None + with self.subTest( "test_voorkeurs_digitaal_adres_must_be_part_of_digitale_adressen" ): @@ -2290,7 +2314,7 @@ def test_invalid_validation_partij_identificator_code_objecttype(self): self.assertEqual(response.data["title"], "Invalid input.") self.assertEqual( response.data["invalid_params"][0]["name"], - "partijIdentificatorCodeObjecttype", + "partijIdentificator.partijIdentificatorCodeObjecttype", ) self.assertEqual(response.data["invalid_params"][0]["code"], "invalid") self.assertEqual( @@ -2318,7 +2342,7 @@ def test_invalid_validation_partij_identificator_code_soort_object_id(self): self.assertEqual(response.data["title"], "Invalid input.") self.assertEqual( response.data["invalid_params"][0]["name"], - "partijIdentificatorCodeSoortObjectId", + "partijIdentificator.partijIdentificatorCodeSoortObjectId", ) self.assertEqual(response.data["invalid_params"][0]["code"], "invalid") self.assertEqual( @@ -2346,7 +2370,7 @@ def test_invalid_validation_partij_identificator_object_id(self): self.assertEqual(response.data["title"], "Invalid input.") self.assertEqual( response.data["invalid_params"][0]["name"], - "partijIdentificatorObjectId", + "partijIdentificator.partijIdentificatorObjectId", ) self.assertEqual(response.data["invalid_params"][0]["code"], "invalid") self.assertEqual( @@ -2374,7 +2398,7 @@ def test_invalid_overig_code_objecttype_validation_partij_identificator(self): self.assertEqual(response.data["title"], "Invalid input.") self.assertEqual( response.data["invalid_params"][0]["name"], - "partijIdentificatorCodeObjecttype", + "partijIdentificator.partijIdentificatorCodeObjecttype", ) self.assertEqual(response.data["invalid_params"][0]["code"], "invalid") self.assertEqual( @@ -2446,6 +2470,78 @@ def test_valid_overig_code_register_validation_partij_identificator(self): "overig", ) + def test_valid_empty_partij_identificator(self): + url = reverse("klantinteracties:partijidentificator-list") + partij = PartijFactory.create() + data = { + "identificeerdePartij": {"uuid": str(partij.uuid)}, + "anderePartijIdentificator": "anderePartijIdentificator", + "partijIdentificator": {}, + } + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual( + response.data["partij_identificator"], + { + "code_objecttype": "", + "code_soort_object_id": "", + "object_id": "", + "code_register": "", + }, + ) + + data = { + "identificeerdePartij": {"uuid": str(partij.uuid)}, + "anderePartijIdentificator": "anderePartijIdentificator", + "partijIdentificator": None, + } + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual( + response.data["partij_identificator"], + { + "code_objecttype": "", + "code_soort_object_id": "", + "object_id": "", + "code_register": "", + }, + ) + + data = { + "identificeerdePartij": {"uuid": str(partij.uuid)}, + "anderePartijIdentificator": "anderePartijIdentificator", + } + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual( + response.data["partij_identificator"], + { + "code_objecttype": "", + "code_soort_object_id": "", + "object_id": "", + "code_register": "", + }, + ) + + data = { + "identificeerdePartij": {"uuid": str(partij.uuid)}, + "anderePartijIdentificator": "anderePartijIdentificator", + "partijIdentificator": { + "code_register": "brp", + }, + } + response = self.client.post(url, data) + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual( + response.data["partij_identificator"], + { + "code_objecttype": "", + "code_soort_object_id": "", + "object_id": "", + "code_register": "brp", + }, + ) + class CategorieRelatieTests(APITestCase): def test_list_categorie_relatie(self): From 8d4b20f54f31d76eba194849e5a3f22d90425e88 Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Fri, 24 Jan 2025 12:11:48 +0100 Subject: [PATCH 10/11] [#239] Fix updatePartij and create tests --- .../api/serializers/partijen.py | 11 +- .../api/tests/test_partijen.py | 217 +++++++++++++----- 2 files changed, 168 insertions(+), 60 deletions(-) diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py index c65cefd5..53611cb3 100644 --- a/src/openklant/components/klantinteracties/api/serializers/partijen.py +++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py @@ -751,9 +751,14 @@ def update(self, instance, validated_data): data=partij_identificator ) partij_identificator_serializer.is_valid(raise_exception=True) - partij_identificator_serializer.create( - partij_identificator_serializer.validated_data - ) + if "uuid" in partij_identificator: + PartijIdentificator.objects.filter( + uuid=partij_identificator["uuid"] + ).update(partij=partij) + else: + partij_identificator_serializer.create( + partij_identificator_serializer.validated_data + ) if partij_identificatie: serializer_class = self.discriminator.mapping[ diff --git a/src/openklant/components/klantinteracties/api/tests/test_partijen.py b/src/openklant/components/klantinteracties/api/tests/test_partijen.py index fda1ffb8..6b03d409 100644 --- a/src/openklant/components/klantinteracties/api/tests/test_partijen.py +++ b/src/openklant/components/klantinteracties/api/tests/test_partijen.py @@ -1048,38 +1048,166 @@ def test_update_partij(self): }, ) - def test_update_partij_partijidentificator_empty_list(self): - partij = PartijFactory.create( - nummer="1298329191", - interne_notitie="interneNotitie", - voorkeurs_digitaal_adres=None, - voorkeurs_rekeningnummer=None, - soort_partij="persoon", - indicatie_geheimhouding=True, - voorkeurstaal="ndl", - indicatie_actief=True, - bezoekadres_nummeraanduiding_id="095be615-a8ad-4c33-8e9c-c7612fbf6c9f", - bezoekadres_adresregel1="adres1", - bezoekadres_adresregel2="adres2", - bezoekadres_adresregel3="adres3", - bezoekadres_land="6030", - correspondentieadres_nummeraanduiding_id="095be615-a8ad-4c33-8e9c-c7612fbf6c9f", - correspondentieadres_adresregel1="adres1", - correspondentieadres_adresregel2="adres2", - correspondentieadres_adresregel3="adres3", - correspondentieadres_land="6030", + def test_update_partij_partijidentificator(self): + partij = PartijFactory.create() + digitaal_adres2 = DigitaalAdresFactory.create() + partij_identificator = PartijIdentificatorFactory.create( + partij_identificator_code_objecttype="natuurlijk_persoon", + partij_identificator_code_soort_object_id="bsn", + partij_identificator_object_id="296648875", + partij_identificator_code_register="brp", ) - PersoonFactory.create( - partij=partij, - contactnaam_voorletters="P", - contactnaam_voornaam="Phil", - contactnaam_voorvoegsel_achternaam="", - contactnaam_achternaam="Bozeman", + detail_url = reverse( + "klantinteracties:partij-detail", kwargs={"uuid": str(partij.uuid)} ) + response = self.client.get(detail_url) + data = response.json() + self.assertEqual(partij.partijidentificator_set.all().count(), 0) + data = { + "digitaleAdressen": [{"uuid": str(digitaal_adres2.uuid)}], + "voorkeursDigitaalAdres": {"uuid": str(digitaal_adres2.uuid)}, + "rekeningnummers": [], + "voorkeursRekeningnummer": None, + "soortPartij": "persoon", + "indicatieActief": True, + "partijIdentificatoren": [ + { + "uuid": str(partij_identificator.uuid), + }, + ], + } + + response = self.client.put(detail_url, data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json() + self.assertEqual(len(data["partijIdentificatoren"]), 1) + self.assertEqual(partij.partijidentificator_set.all().count(), 1) + + self.assertEqual( + data["partijIdentificatoren"][0]["partijIdentificator"], + { + "codeObjecttype": partij_identificator.partij_identificator_code_objecttype, + "codeSoortObjectId": partij_identificator.partij_identificator_code_soort_object_id, + "objectId": partij_identificator.partij_identificator_object_id, + "codeRegister": partij_identificator.partij_identificator_code_register, + }, + ) + + def test_update_replace_partij_partijidentificator(self): + partij = PartijFactory.create() digitaal_adres2 = DigitaalAdresFactory.create() - rekeningnummer2 = RekeningnummerFactory.create() + partij_identificator_1 = PartijIdentificatorFactory.create( + partij=partij, + partij_identificator_code_objecttype="natuurlijk_persoon", + partij_identificator_code_soort_object_id="bsn", + partij_identificator_object_id="296648875", + partij_identificator_code_register="brp", + ) + partij_identificator_2 = PartijIdentificatorFactory.create( + partij_identificator_code_objecttype="niet_natuurlijk_persoon", + partij_identificator_code_soort_object_id="rsin", + partij_identificator_object_id="296648875", + partij_identificator_code_register="hr", + ) + detail_url = reverse( + "klantinteracties:partij-detail", kwargs={"uuid": str(partij.uuid)} + ) + response = self.client.get(detail_url) + data = response.json() + self.assertEqual(len(data["partijIdentificatoren"]), 1) + self.assertEqual(partij.partijidentificator_set.all().count(), 1) + + # Check simple GET + self.assertEqual( + data["partijIdentificatoren"][0]["partijIdentificator"], + { + "codeObjecttype": partij_identificator_1.partij_identificator_code_objecttype, + "codeSoortObjectId": partij_identificator_1.partij_identificator_code_soort_object_id, + "objectId": partij_identificator_1.partij_identificator_object_id, + "codeRegister": partij_identificator_1.partij_identificator_code_register, + }, + ) + # Update with specific partij_identificator (UUID) + data = { + "digitaleAdressen": [{"uuid": str(digitaal_adres2.uuid)}], + "voorkeursDigitaalAdres": {"uuid": str(digitaal_adres2.uuid)}, + "rekeningnummers": [], + "voorkeursRekeningnummer": None, + "soortPartij": "persoon", + "indicatieActief": True, + "partijIdentificatoren": [ + { + "uuid": str(partij_identificator_2.uuid), + }, + ], + } + + response = self.client.put(detail_url, data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json() + self.assertEqual(len(data["partijIdentificatoren"]), 1) + self.assertEqual(partij.partijidentificator_set.all().count(), 1) + + # Check new values + self.assertEqual( + data["partijIdentificatoren"][0]["partijIdentificator"], + { + "codeObjecttype": partij_identificator_2.partij_identificator_code_objecttype, + "codeSoortObjectId": partij_identificator_2.partij_identificator_code_soort_object_id, + "objectId": partij_identificator_2.partij_identificator_object_id, + "codeRegister": partij_identificator_2.partij_identificator_code_register, + }, + ) + partij_identificator_3 = PartijIdentificatorFactory.create( + partij_identificator_code_objecttype="niet_natuurlijk_persoon", + partij_identificator_code_soort_object_id="rsin", + partij_identificator_object_id="296648875", + partij_identificator_code_register="hr", + ) + # Update with new partij_identificator and specific partij_identificator (UUID) + data = { + "digitaleAdressen": [{"uuid": str(digitaal_adres2.uuid)}], + "voorkeursDigitaalAdres": {"uuid": str(digitaal_adres2.uuid)}, + "rekeningnummers": [], + "voorkeursRekeningnummer": None, + "soortPartij": "persoon", + "indicatieActief": True, + "partijIdentificatoren": [ + { + "anderePartijIdentificator": "string", + "partijIdentificator": { + "codeObjecttype": "natuurlijk_persoon", + "codeSoortObjectId": "bsn", + "objectId": "296648875", + "codeRegister": "brp", + }, + }, + { + "uuid": str(partij_identificator_3.uuid), + }, + ], + } + + response = self.client.put(detail_url, data) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + data = response.json() + self.assertEqual(len(data["partijIdentificatoren"]), 2) + self.assertEqual(partij.partijidentificator_set.all().count(), 2) + self.assertTrue( + str(partij_identificator_3.uuid) + in [ + identificator["uuid"] for identificator in data["partijIdentificatoren"] + ] + ) + + def test_update_partij_partijidentificator_empty_list(self): + partij = PartijFactory.create() + digitaal_adres2 = DigitaalAdresFactory.create() partij_identificator = PartijIdentificatorFactory.create( partij=partij, partij_identificator_code_objecttype="natuurlijk_persoon", @@ -1091,6 +1219,7 @@ def test_update_partij_partijidentificator_empty_list(self): detail_url = reverse( "klantinteracties:partij-detail", kwargs={"uuid": str(partij.uuid)} ) + response = self.client.get(detail_url) data = response.json() self.assertEqual(partij.partijidentificator_set.all().count(), 1) @@ -1105,45 +1234,19 @@ def test_update_partij_partijidentificator_empty_list(self): ) data = { - "nummer": "6427834668", - "interneNotitie": "changed", "digitaleAdressen": [{"uuid": str(digitaal_adres2.uuid)}], "voorkeursDigitaalAdres": {"uuid": str(digitaal_adres2.uuid)}, - "rekeningnummers": [{"uuid": str(rekeningnummer2.uuid)}], - "voorkeursRekeningnummer": {"uuid": str(rekeningnummer2.uuid)}, + "rekeningnummers": [], + "voorkeursRekeningnummer": None, "soortPartij": "persoon", - "indicatieGeheimhouding": None, - "voorkeurstaal": "ger", - "indicatieActief": False, - "bezoekadres": { - "nummeraanduidingId": "f78sd8f-uh45-34km-2o3n-aasdasdasc9g", - "adresregel1": "changed", - "adresregel2": "changed", - "adresregel3": "changed", - "land": "3060", - }, - "correspondentieadres": { - "nummeraanduidingId": "sd76f7sd-j4nr-a9s8-83ec-sad89f79a7sd", - "adresregel1": "changed", - "adresregel2": "changed", - "adresregel3": "changed", - "land": "3060", - }, - "partijIdentificatie": { - "contactnaam": { - "voorletters": "V", - "voornaam": "Vincent", - "voorvoegselAchternaam": "", - "achternaam": "Bennette", - } - }, + "indicatieActief": True, "partijIdentificatoren": [], } response = self.client.put(detail_url, data) self.assertEqual(response.status_code, status.HTTP_200_OK) - data = response.json() + data = response.json() self.assertEqual(len(data["partijIdentificatoren"]), 0) self.assertEqual(partij.partijidentificator_set.all().count(), 0) From a28f3d226420dd3d82c97d94094eecc48c23a933 Mon Sep 17 00:00:00 2001 From: Daniel Mursa Date: Fri, 24 Jan 2025 12:38:38 +0100 Subject: [PATCH 11/11] [#239] Update schema --- src/openklant/components/klantinteracties/openapi.yaml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/openklant/components/klantinteracties/openapi.yaml b/src/openklant/components/klantinteracties/openapi.yaml index ac5381af..e10ddb19 100644 --- a/src/openklant/components/klantinteracties/openapi.yaml +++ b/src/openklant/components/klantinteracties/openapi.yaml @@ -2136,7 +2136,6 @@ paths: application/json: schema: $ref: '#/components/schemas/PartijIdentificator' - required: true security: - tokenAuth: [] responses: @@ -2189,7 +2188,6 @@ paths: application/json: schema: $ref: '#/components/schemas/PartijIdentificator' - required: true security: - tokenAuth: [] responses: @@ -3066,6 +3064,7 @@ components: type: array items: $ref: '#/components/schemas/PartijIdentificator' + nullable: true description: Partij-identificatoren die hoorde bij deze partij. soortPartij: allOf: @@ -4722,7 +4721,6 @@ components: uuid: type: string format: uuid - readOnly: true description: Unieke (technische) identificatiecode van de partij-identificator. url: type: string @@ -4749,9 +4747,7 @@ components: description: Gegevens die een partij in een basisregistratie of ander extern register uniek identificeren. required: - - partijIdentificator - url - - uuid PartijIdentificatorGroepType: type: object properties: @@ -5246,7 +5242,6 @@ components: uuid: type: string format: uuid - readOnly: true description: Unieke (technische) identificatiecode van de partij-identificator. url: type: string