Files
2024-11-27 13:18:16 +01:00

160 lines
5.7 KiB
Python
Executable File

from typing import TYPE_CHECKING
from rest_framework import serializers
from rest_framework.exceptions import PermissionDenied
from outbo.apps.photobriefing.enums import ChoiceRole
from outbo.apps.photobriefing.models import Brief, BriefItemChoice
from outbo.apps.photobriefing.rules import can_complete_brief, can_publish_brief
from outbo.apps.photobriefing.serializers import (
BriefItemSerializer,
BriefItemChoiceSerializer,
)
if TYPE_CHECKING:
from outbo.apps.authentication.models import User
class BaseBriefSerializer(serializers.ModelSerializer):
class Meta:
model = Brief
def get_editable(self, instance: Brief):
current_user = self.context["request"].user
return instance.editable_for_user(user=current_user)
def get_acceptable(self, instance: Brief):
current_user = self.context["request"].user
return instance.acceptable_for_user(user=current_user)
def get_publishable(self, instance: Brief):
current_user = self.context["request"].user
return instance.publishable_for_user(user=current_user)
def get_completable(self, instance: Brief):
current_user = self.context["request"].user
return instance.completable_for_user(user=current_user)
class BriefSerializer:
class Retrieve(BaseBriefSerializer):
items = BriefItemSerializer.List(many=True)
choices = BriefItemChoiceSerializer.List(many=True)
editable = serializers.SerializerMethodField()
acceptable = serializers.SerializerMethodField()
publishable = serializers.SerializerMethodField()
completable = serializers.SerializerMethodField()
class Meta(BaseBriefSerializer.Meta):
fields = [
"stage",
"session_date",
"concept_description",
"items",
"choices",
"created_at",
"updated_at",
"editable",
"acceptable",
"publishable",
"completable",
]
class Update(BaseBriefSerializer):
publish = serializers.BooleanField()
complete = serializers.BooleanField()
choice = BriefItemChoiceSerializer.Update(partial=False)
items = BriefItemSerializer.Create(many=True)
class Meta(BaseBriefSerializer.Meta):
fields = [
"session_date",
"concept_description",
"items",
"choice",
"publish",
"complete",
]
def update(self, instance, validated_data):
if validated_data.get("choice", None) is not None:
serializer = BriefSerializer.ChoiceUpdate(context=self.context)
return serializer.update(instance, {"choice": validated_data["choice"]})
if validated_data.get("publish", None) is not None:
serializer = BriefSerializer.Publish(context=self.context)
return serializer.update(
instance, {"publish": validated_data["publish"]}
)
if validated_data.get("complete", None) is not None:
serializer = BriefSerializer.Complete(context=self.context)
return serializer.update(
instance, {"complete": validated_data["complete"]}
)
items = validated_data.pop("items", None)
if items:
for item in items:
item["brief"] = instance
BriefItemSerializer.Create(context=self.context).create(item)
return super().update(instance=instance, validated_data=validated_data)
class Publish(BaseBriefSerializer):
publish = serializers.BooleanField()
class Meta(BaseBriefSerializer.Meta):
fields = ["publish"]
def update(self, instance, validated_data):
publish = validated_data["publish"]
current_user = self.context["request"].user
if not can_publish_brief.test(current_user, instance):
raise PermissionDenied()
if publish:
instance.publish_as_user(user=current_user)
instance.save()
return instance
class Complete(BaseBriefSerializer):
complete = serializers.BooleanField()
class Meta(BaseBriefSerializer.Meta):
fields = ["complete"]
def update(self, instance: Brief, validated_data):
complete = validated_data["complete"]
current_user = self.context["request"].user
if not can_complete_brief.test(current_user, instance):
raise PermissionDenied()
if complete:
instance.complete_as_user(user=current_user)
instance.save()
return instance
class ChoiceUpdate(BaseBriefSerializer):
choice = BriefItemChoiceSerializer.Update()
class Meta(BaseBriefSerializer.Meta):
fields = ["choice"]
def update(self, instance, validated_data):
choice = validated_data["choice"]
current_user: "User" = self.context["request"].user
if current_user.is_supplier:
role = ChoiceRole.SUPPLIER
elif current_user.is_client:
role = ChoiceRole.CLIENT
else:
raise NotImplemented
current_choice, _ = BriefItemChoice.objects.get_or_create(
defaults={"item": choice["item"]},
brief=instance,
category=choice["category"],
role=role,
)
if current_choice.item != choice["item"]:
current_choice.item = choice["item"]
current_choice.save()
return instance