Skip to content

Commit

Permalink
[#11] add eigenschappen
Browse files Browse the repository at this point in the history
  • Loading branch information
Floris272 committed Mar 7, 2025
1 parent f6156c1 commit cd6c607
Show file tree
Hide file tree
Showing 25 changed files with 964 additions and 48 deletions.
2 changes: 2 additions & 0 deletions src/open_producten/producten/admin/product.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from django.utils.translation import gettext_lazy as _

from open_producten.logging.service import AdminAuditLogMixin, get_logs_link
from open_producten.producten.admin.product_eigenschap import ProductEigenschapInline
from open_producten.producten.models import Product
from open_producten.producten.models.product import (
validate_eind_datum,
Expand Down Expand Up @@ -104,6 +105,7 @@ class ProductAdmin(AdminAuditLogMixin, admin.ModelAdmin):
autocomplete_fields = ("product_type",)
search_fields = ("product_type__translations__naam",)
form = ProductAdminForm
inlines = [ProductEigenschapInline]

@admin.display(description="Product Type")
def product_type_name(self, obj):
Expand Down
11 changes: 11 additions & 0 deletions src/open_producten/producten/admin/product_eigenschap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.contrib import admin

from open_producten.logging.admin_tools import AuditLogInlineformset
from open_producten.producten.models import ProductEigenschap


class ProductEigenschapInline(admin.TabularInline):
formset = AuditLogInlineformset
model = ProductEigenschap
extra = 1
ordering = ("pk",)
67 changes: 67 additions & 0 deletions src/open_producten/producten/migrations/0005_producteigenschap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Generated by Django 4.2.17 on 2025-03-06 15:38

import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import uuid


class Migration(migrations.Migration):

dependencies = [
("producttypen", "0010_eigenschap"),
("producten", "0004_product_frequentie_product_prijs"),
]

operations = [
migrations.CreateModel(
name="ProductEigenschap",
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
(
"waarde",
models.CharField(
help_text="De waarde van de eigenschap.",
max_length=255,
validators=[
django.core.validators.RegexValidator("^[^:\\[\\]]+$")
],
verbose_name="waarde",
),
),
(
"eigenschap",
models.ForeignKey(
help_text="Het eigenschap waarbij deze waarde hoort.",
on_delete=django.db.models.deletion.CASCADE,
related_name="waardes",
to="producttypen.eigenschap",
verbose_name="producttype",
),
),
(
"product",
models.ForeignKey(
help_text="Het product waarbij deze eigenschap hoort.",
on_delete=django.db.models.deletion.CASCADE,
related_name="eigenschappen",
to="producten.product",
verbose_name="producttype",
),
),
],
options={
"verbose_name": "product eigenschap",
"verbose_name_plural": "product eigenschappen",
"unique_together": {("product", "eigenschap")},
},
),
]
3 changes: 2 additions & 1 deletion src/open_producten/producten/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .product import Product
from .product_eigenschap import ProductEigenschap

__all__ = ["Product"]
__all__ = ["Product", "ProductEigenschap"]
62 changes: 62 additions & 0 deletions src/open_producten/producten/models/product_eigenschap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator
from django.db import models
from django.utils.translation import gettext_lazy as _

from open_producten.producten.models import Product
from open_producten.producttypen.models import Eigenschap
from open_producten.utils.models import BaseModel


class ProductEigenschap(BaseModel):

waarde = models.CharField(
verbose_name=_("waarde"),
max_length=255,
help_text=_("De waarde van de eigenschap."),
validators=[RegexValidator(r"^[^:\[\]]+$")],
)

eigenschap = models.ForeignKey(
Eigenschap,
verbose_name=_("producttype"),
on_delete=models.CASCADE,
related_name="waardes",
help_text=_("Het eigenschap waarbij deze waarde hoort."),
)

product = models.ForeignKey(
Product,
verbose_name=_("producttype"),
on_delete=models.CASCADE,
related_name="eigenschappen",
help_text=_("Het product waarbij deze eigenschap hoort."),
)

@property
def naam(self):
return self.eigenschap.naam

class Meta:
verbose_name = _("product eigenschap")
verbose_name_plural = _("product eigenschappen")
unique_together = (("product", "eigenschap"),)

def clean(self):
validate_eigenschap_part_of_producttype(
self.eigenschap, self.waarde, self.product
)

def __str__(self):
return f"{self.eigenschap.naam} {self.waarde} {self.product.naam}"


def validate_eigenschap_part_of_producttype(eigenschap, waarde, product):
if eigenschap.product_type != product.product_type:
raise ValidationError(
{
"eigenschap": _(
"eigenschap {}: {} is niet onderdeel van het producttype {}"
).format(eigenschap.naam, waarde, product.product_type.naam)
}
)
79 changes: 78 additions & 1 deletion src/open_producten/producten/serializers/product.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
from django.db import transaction
from django.utils.translation import gettext_lazy as _

from rest_framework import serializers
from rest_framework.exceptions import NotFound

from open_producten.producten.models import Product
from open_producten.producten.serializers.product_eigenschap import (
NestedProductEigenschapSerializer,
ProductEigenschapSerializer,
)
from open_producten.producten.serializers.validators import (
BsnOrKvkValidator,
DateValidator,
StatusValidator,
)
from open_producten.producttypen.models import ProductType
from open_producten.producttypen.models import Eigenschap, ProductType
from open_producten.producttypen.serializers.thema import NestedProductTypeSerializer
from open_producten.utils.serializers import (
set_nested_serializer,
validate_key_value_model_keys,
)


class ProductSerializer(serializers.ModelSerializer):
Expand All @@ -16,7 +28,72 @@ class ProductSerializer(serializers.ModelSerializer):
write_only=True, queryset=ProductType.objects.all(), source="product_type"
)

eigenschappen = NestedProductEigenschapSerializer(many=True, required=False)

def validate_eigenschappen(self, parameters: list[dict]):
return validate_key_value_model_keys(
parameters,
"naam",
_("Er bestaat al een eigenschap met de naam {} voor dit Product."),
)

class Meta:
model = Product
fields = "__all__"
validators = [BsnOrKvkValidator(), DateValidator(), StatusValidator()]

@transaction.atomic()
def create(self, validated_data):
eigenschappen = validated_data.pop("eigenschappen", [])

product = super().create(validated_data)

set_nested_serializer(
[
product_eigenschap
| {
"product": product.id,
"eigenschap": self._get_eigenschap(
product_eigenschap.pop("naam"), product.product_type
).id,
}
for product_eigenschap in eigenschappen
],
ProductEigenschapSerializer,
)

return product

def _get_eigenschap(self, naam, product_type):
try:
return product_type.eigenschappen.get(naam=naam)
except Eigenschap.DoesNotExist:
raise NotFound(
_("Producttype {} heeft geen eigenschap `{}`").format(
product_type.id, naam
)
)

@transaction.atomic()
def update(self, instance, validated_data):
eigenschappen = validated_data.pop("eigenschappen", None)

instance = super().update(instance, validated_data)

if eigenschappen is not None:
instance.eigenschappen.all().delete()
set_nested_serializer(
[
product_eigenschap
| {
"product": instance.id,
"eigenschap": self._get_eigenschap(
product_eigenschap.pop("naam"), instance.product_type
).id,
}
for product_eigenschap in eigenschappen
],
ProductEigenschapSerializer,
)

return instance
20 changes: 20 additions & 0 deletions src/open_producten/producten/serializers/product_eigenschap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from rest_framework import serializers

from open_producten.producten.models import ProductEigenschap
from open_producten.producten.serializers.validators import ProductEigenschapValidator


class NestedProductEigenschapSerializer(serializers.ModelSerializer):
naam = serializers.CharField()

class Meta:
model = ProductEigenschap
fields = ["waarde", "naam"]


class ProductEigenschapSerializer(serializers.ModelSerializer):

class Meta:
model = ProductEigenschap
fields = ["eigenschap", "product", "waarde"]
validators = [ProductEigenschapValidator()]
18 changes: 18 additions & 0 deletions src/open_producten/producten/serializers/validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
validate_start_datum,
validate_status,
)
from open_producten.producten.models.product_eigenschap import (
validate_eigenschap_part_of_producttype,
)
from open_producten.utils.serializers import get_from_serializer_data_or_instance


Expand Down Expand Up @@ -83,3 +86,18 @@ def __call__(self, value, serializer):
validate_dates(start_datum, eind_datum)
except ValidationError as e:
raise serializers.ValidationError(e.message_dict)


class ProductEigenschapValidator:
requires_context = True

def __call__(self, value, serializer):
eigenschap = get_from_serializer_data_or_instance(
"eigenschap", value, serializer
)
waarde = get_from_serializer_data_or_instance("waarde", value, serializer)
product = get_from_serializer_data_or_instance("product", value, serializer)
try:
validate_eigenschap_part_of_producttype(eigenschap, waarde, product)
except ValidationError as e:
raise serializers.ValidationError(e.message_dict)
Loading

0 comments on commit cd6c607

Please sign in to comment.