Skip to content

Commit

Permalink
[#46] refactor prijs serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
Floris272 committed Mar 6, 2025
1 parent fc82519 commit f5e8e17
Show file tree
Hide file tree
Showing 5 changed files with 13 additions and 77 deletions.
17 changes: 0 additions & 17 deletions src/open_producten/producten/serializers/product.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,27 +57,10 @@ def update(self, instance, validated_data):
else:
existing_eigenaar = Eigenaar.objects.get(id=eigenaar_id)
EigenaarSerializer().update(existing_eigenaar, eigenaar)

# serializer = EigenaarSerializer(existing_eigenaar, data=eigenaar, partial=self.partial)
# serializer.is_valid(raise_exception=True)
# serializer.save()

seen_eigenaren_ids.add(eigenaar_id)

product.eigenaren.filter(
id__in=(current_eigenaren_ids - seen_eigenaren_ids)
).delete()

return product


# def update_nested_object(object_list: list[dict], child_serializer: Serializer):
# ids = [obj["id"] for obj in object_list]
# product.eigenaren.exclude(id__in=ids).delete()
#
# for obj in object_list:
# if obj_id := obj.pop("id", None):
# existing_eigenaar = Eigenaar.objects.get(id=obj_id)
# child_serializer().update(existing_eigenaar, obj)
# else:
# child_serializer().create(obj | {"product": product})
15 changes: 8 additions & 7 deletions src/open_producten/producttypen/serializers/prijs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

from rest_framework import serializers

from ...utils.drf_validators import NestedObjectsValidator
from ..models import Prijs, PrijsOptie, ProductType
from .validators import PrijsOptieValidator


class PrijsOptieSerializer(serializers.ModelSerializer):
Expand All @@ -24,7 +24,7 @@ class PrijsSerializer(serializers.ModelSerializer):
class Meta:
model = Prijs
fields = ("id", "product_type_id", "prijsopties", "actief_vanaf")
validators = [PrijsOptieValidator()]
validators = [NestedObjectsValidator("prijsopties", PrijsOptie)]

def validate_prijsopties(self, opties: list[PrijsOptie]) -> list[PrijsOptie]:
if len(opties) == 0:
Expand All @@ -39,7 +39,7 @@ def create(self, validated_data):
prijs = Prijs.objects.create(**validated_data, product_type=product_type)

for optie in prijsopties:
PrijsOptie.objects.create(prijs=prijs, **optie)
PrijsOptieSerializer().create(optie | {"prijs": prijs})

return prijs

Expand All @@ -57,13 +57,14 @@ def update(self, instance, validated_data):
for optie in opties:
optie_id = optie.pop("id", None)
if optie_id is None:
PrijsOptie.objects.create(prijs=prijs, **optie)
PrijsOptieSerializer().create(optie | {"prijs": prijs})

else:
existing_optie = PrijsOptie.objects.get(id=optie_id)
existing_optie.bedrag = optie["bedrag"]
existing_optie.beschrijving = optie["beschrijving"]
existing_optie.save()
PrijsOptieSerializer(partial=self.partial).update(
existing_optie, optie
)
seen_optie_ids.add(optie_id)

PrijsOptie.objects.filter(
id__in=(current_optie_ids - seen_optie_ids)
Expand Down
50 changes: 0 additions & 50 deletions src/open_producten/producttypen/serializers/validators.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _

from rest_framework import serializers

from ...utils.serializers import get_from_serializer_data_or_instance
from ..models import PrijsOptie
from ..models.thema import disallow_self_reference, validate_gepubliceerd_state


Expand Down Expand Up @@ -39,51 +37,3 @@ def __call__(self, value, serializer):
disallow_self_reference(thema, hoofd_thema)
except ValidationError as e:
raise serializers.ValidationError({"hoofd_thema": e.message})


class PrijsOptieValidator:
requires_context = True

def __call__(self, value, serializer):
prijs_instance = serializer.instance
if not prijs_instance or not value.get("prijsopties"):
return

optie_errors = []

current_optie_ids = set(
prijs_instance.prijsopties.values_list("id", flat=True).distinct()
)
seen_optie_ids = set()

for idx, optie in enumerate(value["prijsopties"]):
optie_id = optie.pop("id", None)

if not optie_id:
continue

if optie_id in current_optie_ids:

if optie_id in seen_optie_ids:
optie_errors.append(
_("Dubbel id: {} op index {}.").format(optie_id, idx)
)
seen_optie_ids.add(optie_id)

else:
try:
PrijsOptie.objects.get(id=optie_id)
optie_errors.append(
_(
"Prijs optie id {} op index {} is niet onderdeel van het prijs object."
).format(optie_id, idx)
)
except PrijsOptie.DoesNotExist:
optie_errors.append(
_("Prijs optie id {} op index {} bestaat niet.").format(
optie_id, idx
)
)

if optie_errors:
raise serializers.ValidationError({"prijsopties": optie_errors})
6 changes: 4 additions & 2 deletions src/open_producten/producttypen/tests/api/test_prijs.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ def test_update_prijs_updating_and_removing_opties(self):
self.assertEqual(Prijs.objects.count(), 1)
self.assertEqual(PrijsOptie.objects.count(), 1)
self.assertEqual(PrijsOptie.objects.first().bedrag, Decimal("20"))
self.assertEqual(PrijsOptie.objects.first().id, optie_to_be_updated.id)

def test_update_prijs_creating_and_deleting_opties(self):

Expand Down Expand Up @@ -195,7 +196,7 @@ def test_update_prijs_with_optie_not_part_of_prijs_returns_error(self):
"prijsopties": [
ErrorDetail(
string=_(
"Prijs optie id {} op index 0 is niet onderdeel van het prijs object."
"Prijs optie id {} op index 0 is niet onderdeel van het Prijs object."
).format(optie.id),
code="invalid",
)
Expand Down Expand Up @@ -298,6 +299,7 @@ def test_partial_update_prijs_updating_and_removing_opties(self):
self.assertEqual(Prijs.objects.count(), 1)
self.assertEqual(PrijsOptie.objects.count(), 1)
self.assertEqual(PrijsOptie.objects.first().bedrag, Decimal("20"))
self.assertEqual(PrijsOptie.objects.first().id, optie_to_be_updated.id)

def test_partial_update_prijs_creating_and_deleting_opties(self):

Expand Down Expand Up @@ -351,7 +353,7 @@ def test_partial_update_with_multiple_errors(self):
),
ErrorDetail(
string=_(
"Prijs optie id {} op index 2 is niet onderdeel van het prijs object."
"Prijs optie id {} op index 2 is niet onderdeel van het Prijs object."
).format(optie_of_other_prijs.id),
code="invalid",
),
Expand Down
2 changes: 1 addition & 1 deletion src/open_producten/producttypen/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

class UniformeProductNaamFactory(factory.django.DjangoModelFactory):
naam = factory.Sequence(lambda n: f"upn {n}")
uri = factory.Faker("url")
uri = factory.Sequence(lambda n: f"{fake.url()}/{n}")

class Meta:
model = UniformeProductNaam
Expand Down

0 comments on commit f5e8e17

Please sign in to comment.