-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ [#182] changed internetaken actor field to actoren #218
Changes from all commits
4537ab1
b9e4b58
bdf63f9
fe4001d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
from django.db import transaction | ||
from django.utils.translation import gettext_lazy as _ | ||
|
||
from drf_spectacular.utils import extend_schema_serializer | ||
from glom import PathAccessError, glom | ||
from rest_framework import serializers | ||
|
||
from openklant.components.klantinteracties.api.serializers.actoren import ( | ||
|
@@ -33,12 +35,21 @@ class Meta: | |
} | ||
|
||
|
||
@extend_schema_serializer(deprecate_fields=["toegewezen_aan_actor"]) | ||
class InterneTaakSerializer(serializers.HyperlinkedModelSerializer): | ||
toegewezen_aan_actor = ActorForeignKeySerializer( | ||
required=True, | ||
required=False, | ||
allow_null=False, | ||
help_text=_("Actor die een interne taak toegewezen kreeg."), | ||
source="actor", | ||
help_text=_("Eerste actor die een interne taak toegewezen kreeg."), | ||
source="actoren.first", | ||
many=False, | ||
) | ||
toegewezen_aan_actoren = ActorForeignKeySerializer( | ||
required=False, | ||
allow_null=False, | ||
help_text=_("Actoren die een interne taak toegewezen kreeg."), | ||
source="actoren", | ||
many=True, | ||
) | ||
aanleidinggevend_klantcontact = KlantcontactForeignKeySerializer( | ||
required=True, | ||
|
@@ -56,6 +67,7 @@ class Meta: | |
"gevraagde_handeling", | ||
"aanleidinggevend_klantcontact", | ||
"toegewezen_aan_actor", | ||
"toegewezen_aan_actoren", | ||
"toelichting", | ||
"status", | ||
"toegewezen_op", | ||
|
@@ -70,7 +82,52 @@ class Meta: | |
}, | ||
} | ||
|
||
def to_representation(self, instance): | ||
response = super().to_representation(instance) | ||
response["toegewezen_aan_actor"] = ActorForeignKeySerializer( | ||
instance.actoren.order_by("internetakenactorenthoughmodel__pk").first(), | ||
context={**self.context}, | ||
).data | ||
|
||
response["toegewezen_aan_actoren"] = ActorForeignKeySerializer( | ||
instance.actoren.all().order_by("internetakenactorenthoughmodel__pk"), | ||
context={**self.context}, | ||
many=True, | ||
).data | ||
return response | ||
|
||
# TODO: remove when depricated actoren field gets removed | ||
def _validate_actoren(self): | ||
toegewezen_aan_actor = "toegewezen_aan_actor" in self.initial_data | ||
toegewezen_aan_actoren = "toegewezen_aan_actoren" in self.initial_data | ||
|
||
if toegewezen_aan_actor == toegewezen_aan_actoren: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible? They should have different types since one is iterable and another one is not There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am basically checking here if the fields got send by the user. This way I can validate if only one of the two fields got used. If both are False then neither were send, and if both are True then both got send. |
||
if toegewezen_aan_actor: | ||
message = _( | ||
"`toegewezen_aan_actor` en `toegewezen_aan_actoren` mag niet beiden gebruikt worden." | ||
) | ||
else: | ||
message = _( | ||
"`toegewezen_aan_actor` of `toegewezen_aan_actoren` is required (mag niet beiden gebruiken)." | ||
) | ||
|
||
# If patch don't raise required error | ||
if self.context.get("request").method == "PATCH": | ||
return | ||
|
||
raise serializers.ValidationError(message) | ||
|
||
# TODO: remove when depricated actoren field gets removed | ||
def _get_actoren(self, actoren): | ||
if isinstance(actoren, list): | ||
actor_uuids = [str(actor.get("uuid")) for actor in actoren] | ||
else: | ||
actor_uuids = [glom(actoren, "first.uuid", skip_exc=PathAccessError)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't quite understand this line. Could you please provide an example when it happens? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The structure of both actor fields are different. The single object returns a validated data of {"first": {"uuid": "..."}} This is just a temporary function to fetch the data I need to update and create the objects. |
||
|
||
return [Actor.objects.get(uuid=uuid) for uuid in actor_uuids] | ||
|
||
def validate(self, attrs): | ||
self._validate_actoren() | ||
status = attrs.get("status", None) | ||
if status is None and self.instance is not None: | ||
status = self.instance.status | ||
|
@@ -89,21 +146,27 @@ def validate(self, attrs): | |
|
||
@transaction.atomic | ||
def create(self, validated_data): | ||
actor_uuid = str(validated_data.pop("actor").get("uuid")) | ||
actoren = validated_data.pop("actoren", None) | ||
klantcontact_uuid = str(validated_data.pop("klantcontact").get("uuid")) | ||
|
||
validated_data["actor"] = Actor.objects.get(uuid=actor_uuid) | ||
validated_data["klantcontact"] = Klantcontact.objects.get( | ||
uuid=klantcontact_uuid | ||
) | ||
|
||
return super().create(validated_data) | ||
internetaak = super().create(validated_data) | ||
if actoren: | ||
for actor in self._get_actoren(actoren): | ||
internetaak.actoren.add(actor) | ||
|
||
return internetaak | ||
|
||
@transaction.atomic | ||
def update(self, instance, validated_data): | ||
if "actor" in validated_data: | ||
if actor := validated_data.pop("actor", None): | ||
validated_data["actor"] = Actor.objects.get(uuid=str(actor.get("uuid"))) | ||
if "actoren" in validated_data: | ||
actoren = validated_data.pop("actoren") | ||
instance.actoren.clear() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Always delete and create relations seems unnecessary. I think it's better to compare first that old and new actors are not the same There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be done in the future but because we currently are bound to a temporary ordering model. I think it is not worth the time and resources to create the functionality of comparing the data between the existing data and the user submitted data and compare the order of both. Deleting the relations and creating them afterwards will guarantee that the order will always be correct. So I think that for now this is a fine solution. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, let's keep it until we get rid of the deprecated field and OrderedModel There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to modify it now? |
||
for actor in self._get_actoren(actoren): | ||
instance.actoren.add(actor) | ||
|
||
if "klantcontact" in validated_data: | ||
if klantcontact := validated_data.pop("klantcontact", None): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now it's possible that a task doesn't have any actor, isn't it?
Is this change intended? Can it affect a process in some way?
Nvm, I saw a validation that it can't be possible
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is indeed not intended for a
IntereTaak
to not have anActor
.But because we now have 2 (1 temporary)
Actor
fields we can't have them set as required.So I moved the "required" clause to the validation function within the serializer.