diff --git a/src/openklant/components/klantinteracties/api/serializers/partijen.py b/src/openklant/components/klantinteracties/api/serializers/partijen.py index f12797a5..6fce8f87 100644 --- a/src/openklant/components/klantinteracties/api/serializers/partijen.py +++ b/src/openklant/components/klantinteracties/api/serializers/partijen.py @@ -444,7 +444,7 @@ def validate(self, attrs): return super().validate(attrs) - def assert_partij(self, partij): + def validate_partij(self, partij): if not partij: raise serializers.ValidationError( {"identificeerdePartij": _("Dit veld is vereist.")}, @@ -454,13 +454,13 @@ def assert_partij(self, partij): @handle_db_exceptions @transaction.atomic def update(self, instance, validated_data): - self.assert_partij(validated_data["partij"]) + self.validate_partij(validated_data["partij"]) return super().update(instance, validated_data) @handle_db_exceptions @transaction.atomic def create(self, validated_data): - self.assert_partij(validated_data["partij"]) + self.validate_partij(validated_data["partij"]) return super().create(validated_data) @@ -634,6 +634,11 @@ def validate_partij_identificatoren(self, attrs): return attrs def update_or_create_partij_identificator(self, partij_identificator): + sub_identificator_van = partij_identificator["sub_identificator_van"] + if isinstance(sub_identificator_van, PartijIdentificator): + partij_identificator["sub_identificator_van"] = { + "uuid": sub_identificator_van.uuid + } partij_identificator_serializer = PartijIdentificatorSerializer( data=partij_identificator ) diff --git a/src/openklant/components/klantinteracties/api/tests/test_partijen.py b/src/openklant/components/klantinteracties/api/tests/test_partijen.py index 37f87b1e..3bb5340e 100644 --- a/src/openklant/components/klantinteracties/api/tests/test_partijen.py +++ b/src/openklant/components/klantinteracties/api/tests/test_partijen.py @@ -2503,6 +2503,260 @@ def test_invalid_create_where_partij_is_selected(self): self.assertEqual(Partij.objects.all().count(), 1) + def test_partially_update_with_null_values(self): + partij = PartijFactory.create( + nummer="1298329191", + interne_notitie="interneNotitie", + voorkeurs_digitaal_adres=None, + voorkeurs_rekeningnummer=None, + indicatie_geheimhouding=True, + voorkeurstaal="ndl", + indicatie_actief=True, + soort_partij="persoon", + ) + + detail_url = reverse( + "klantinteracties:partij-detail", kwargs={"uuid": str(partij.uuid)} + ) + + with self.subTest("partij_identificatoren_not_specified"): + data = {"soortPartij": "organisatie"} + self.assertEqual(partij.soort_partij, "persoon") + self.assertEqual(partij.partijidentificator_set.count(), 0) + response = self.client.patch(detail_url, data) + response_data = response.json() + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response_data["partijIdentificatoren"], []) + self.assertEqual(response_data["soortPartij"], "organisatie") + self.assertEqual(partij.partijidentificator_set.count(), 0) + + BsnPartijIdentificatorFactory.create( + partij=partij, partij_identificator_object_id="296648875" + ) + # Resend update request + # No changes to the partij_identificator because the value wasn't specified in PATCH + self.assertEqual(partij.partijidentificator_set.count(), 1) + response = self.client.patch(detail_url, data) + response_data = response.json() + self.assertEqual(response.status_code, status.HTTP_200_OK) + + partij = Partij.objects.get(uuid=partij.uuid) + self.assertEqual(partij.partijidentificator_set.count(), 1) + self.assertEqual(len(response_data["partijIdentificatoren"]), 1) + self.assertEqual(response_data["soortPartij"], "organisatie") + self.assertEqual(partij.soort_partij, "organisatie") + + with self.subTest("partij_identificatoren_null_value"): + data = { + "soortPartij": "persoon", + "partijIdentificatoren": None, + } + self.assertEqual(partij.soort_partij, "organisatie") + self.assertEqual(partij.partijidentificator_set.count(), 1) + + # No changes to the partij_identificator because the value was None in PATCH + self.assertEqual(partij.partijidentificator_set.count(), 1) + response = self.client.patch(detail_url, data) + response_data = response.json() + self.assertEqual(response.status_code, status.HTTP_200_OK) + + partij = Partij.objects.get(uuid=partij.uuid) + self.assertEqual(partij.partijidentificator_set.count(), 1) + self.assertEqual(len(response_data["partijIdentificatoren"]), 1) + self.assertEqual(response_data["soortPartij"], "persoon") + self.assertEqual(partij.soort_partij, "persoon") + + with self.subTest("partij_identificatoren_empty_list_value"): + data = { + "soortPartij": "organisatie", + "partijIdentificatoren": [], + } + self.assertEqual(partij.soort_partij, "persoon") + self.assertEqual(partij.partijidentificator_set.count(), 1) + + # Delete all partij_identificatoren because the value was [] in PATCH + response = self.client.patch(detail_url, data) + response_data = response.json() + self.assertEqual(response.status_code, status.HTTP_200_OK) + partij = Partij.objects.get(uuid=partij.uuid) + self.assertEqual(partij.partijidentificator_set.count(), 0) + self.assertEqual(len(response_data["partijIdentificatoren"]), 0) + self.assertEqual(response_data["soortPartij"], "organisatie") + self.assertEqual(partij.soort_partij, "organisatie") + + def test_partially_update_where_all_partij_identificatoren_have_uuid(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, + ) + detail_url = reverse( + "klantinteracties:partij-detail", kwargs={"uuid": str(partij.uuid)} + ) + bsn = BsnPartijIdentificatorFactory.create( + partij=partij, partij_identificator_object_id="296648875" + ) + kvk_nummer = KvkNummerPartijIdentificatorFactory.create( + partij=partij, partij_identificator_object_id="12345678" + ) + vestigingsnummer = VestigingsnummerPartijIdentificatorFactory.create( + partij=partij, partij_identificator_object_id="111122223333" + ) + + # changes are only for objectId + data = { + "soortPartij": "organisatie", + "partijIdentificatoren": [ + { + "uuid": str(bsn.uuid), + "partijIdentificator": { + "codeObjecttype": "natuurlijk_persoon", + "codeSoortObjectId": "bsn", + "objectId": "123456782", + "codeRegister": "brp", + }, + }, + { + "uuid": str(kvk_nummer.uuid), + "partijIdentificator": { + "codeObjecttype": "niet_natuurlijk_persoon", + "codeSoortObjectId": "kvk_nummer", + "objectId": "11112222", + "codeRegister": "hr", + }, + }, + { + "uuid": str(vestigingsnummer.uuid), + "sub_identificator_van": {"uuid": str(kvk_nummer.uuid)}, + "partijIdentificator": { + "codeObjecttype": "vestiging", + "codeSoortObjectId": "vestigingsnummer", + "objectId": "444455556666", + "codeRegister": "hr", + }, + }, + ], + } + response = self.client.patch(detail_url, data) + response_data = response.json() + + self.assertEqual(response.status_code, status.HTTP_200_OK) + partij = Partij.objects.get(pk=partij.pk) + + self.assertEqual(len(response_data["partijIdentificatoren"]), 3) + self.assertEqual(response_data["soortPartij"], "organisatie") + self.assertEqual(partij.soort_partij, "organisatie") + new_bsn = partij.partijidentificator_set.get( + partij_identificator_code_soort_object_id="bsn" + ) + new_kvk_nummer = partij.partijidentificator_set.get( + partij_identificator_code_soort_object_id="kvk_nummer" + ) + new_vestigingsnummer = partij.partijidentificator_set.get( + partij_identificator_code_soort_object_id="vestigingsnummer" + ) + # assert that they are the same objects + self.assertEqual(new_bsn.uuid, bsn.uuid) + self.assertEqual(new_kvk_nummer.uuid, kvk_nummer.uuid) + self.assertEqual(new_vestigingsnummer.uuid, vestigingsnummer.uuid) + # assert that the object_ids have been updated + self.assertEqual(new_bsn.partij_identificator_object_id, "123456782") + self.assertEqual(new_kvk_nummer.partij_identificator_object_id, "11112222") + self.assertEqual( + new_vestigingsnummer.partij_identificator_object_id, "444455556666" + ) + + def test_partially_update_where_not_all_partij_identificatoren_have_uuid(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, + ) + detail_url = reverse( + "klantinteracties:partij-detail", kwargs={"uuid": str(partij.uuid)} + ) + bsn = BsnPartijIdentificatorFactory.create( + partij=partij, partij_identificator_object_id="296648875" + ) + kvk_nummer = KvkNummerPartijIdentificatorFactory.create( + partij=partij, partij_identificator_object_id="12345678" + ) + vestigingsnummer = VestigingsnummerPartijIdentificatorFactory.create( + partij=partij, partij_identificator_object_id="111122223333" + ) + + # changes are only for objectId + data = { + "soortPartij": "organisatie", + "partijIdentificatoren": [ + { + "partijIdentificator": { + "codeObjecttype": "natuurlijk_persoon", + "codeSoortObjectId": "bsn", + "objectId": "123456782", + "codeRegister": "brp", + }, + }, + { + "uuid": str(kvk_nummer.uuid), + "partijIdentificator": { + "codeObjecttype": "niet_natuurlijk_persoon", + "codeSoortObjectId": "kvk_nummer", + "objectId": "11112222", + "codeRegister": "hr", + }, + }, + { + "uuid": str(vestigingsnummer.uuid), + "sub_identificator_van": {"uuid": str(kvk_nummer.uuid)}, + "partijIdentificator": { + "codeObjecttype": "vestiging", + "codeSoortObjectId": "vestigingsnummer", + "objectId": "444455556666", + "codeRegister": "hr", + }, + }, + ], + } + response = self.client.patch(detail_url, data) + response_data = response.json() + + self.assertEqual(response.status_code, status.HTTP_200_OK) + partij = Partij.objects.get(pk=partij.pk) + self.assertEqual(len(response_data["partijIdentificatoren"]), 3) + self.assertEqual(response_data["soortPartij"], "organisatie") + self.assertEqual(partij.soort_partij, "organisatie") + new_bsn = partij.partijidentificator_set.get( + partij_identificator_code_soort_object_id="bsn" + ) + new_kvk_nummer = partij.partijidentificator_set.get( + partij_identificator_code_soort_object_id="kvk_nummer" + ) + new_vestigingsnummer = partij.partijidentificator_set.get( + partij_identificator_code_soort_object_id="vestigingsnummer" + ) + # assert bsn was deleted and then created again with new values + self.assertNotEqual(new_bsn.uuid, bsn.uuid) + # assert that they are the same objects + self.assertEqual(new_kvk_nummer.uuid, kvk_nummer.uuid) + self.assertEqual(new_vestigingsnummer.uuid, vestigingsnummer.uuid) + # assert that the object_ids have been updated + self.assertEqual(new_bsn.partij_identificator_object_id, "123456782") + self.assertEqual(new_kvk_nummer.partij_identificator_object_id, "11112222") + self.assertEqual( + new_vestigingsnummer.partij_identificator_object_id, "444455556666" + ) + class PartijIdentificatorTests(APITestCase): def test_list_partij_identificator(self): @@ -2576,6 +2830,7 @@ def test_update_partij_identificator(self): partij, partij2 = PartijFactory.create_batch(2) partij_identificator = BsnPartijIdentificatorFactory.create( partij=partij, + andere_partij_identificator="anderePartijIdentificator", partij_identificator_object_id="296648875", ) @@ -2916,7 +3171,7 @@ def test_invalid_create_partij_required(self): def test_invalid_create_duplicate_code_soort_object_id_for_partij(self): BsnPartijIdentificatorFactory.create( partij=self.partij, - partij_identificator_object_id="296648875", + partij_identificator_object_id="123456782", ) data = { diff --git a/src/openklant/components/klantinteracties/openapi.yaml b/src/openklant/components/klantinteracties/openapi.yaml index c081ca45..56aa7ff3 100644 --- a/src/openklant/components/klantinteracties/openapi.yaml +++ b/src/openklant/components/klantinteracties/openapi.yaml @@ -3065,8 +3065,8 @@ components: partijIdentificatoren: type: array items: - $ref: '#/components/schemas/PartijIdentificatorForeignkey' - readOnly: true + $ref: '#/components/schemas/PartijIdentificator' + nullable: true description: Partij-identificatoren die hoorde bij deze partij. soortPartij: allOf: @@ -3107,7 +3107,6 @@ components: - categorieRelaties - digitaleAdressen - indicatieActief - - partijIdentificatoren - rekeningnummers - soortPartij - url @@ -4836,7 +4835,6 @@ components: uuid: type: string format: uuid - readOnly: true description: Unieke (technische) identificatiecode van de partij-identificator. url: type: string @@ -4871,10 +4869,8 @@ components: the child identificator could specify a vestigingsnummer that is unique for the KVK number). required: - - identificeerdePartij - partijIdentificator - url - - uuid PartijIdentificatorForeignkey: type: object properties: @@ -5391,7 +5387,6 @@ components: uuid: type: string format: uuid - readOnly: true description: Unieke (technische) identificatiecode van de partij-identificator. url: type: string