from rest_framework import serializers from rest_framework.reverse import reverse_lazy from outbo.apps.projects.models import Project, Member from outbo.apps.projects.models.member import MembershipType class _BaseProjectSerializer(serializers.ModelSerializer): class Meta: model = Project fields = ["name"] class BaseMemberSerializer(serializers.ModelSerializer): class Meta: model = Member class MemberSerializer: class Create(BaseMemberSerializer): class Meta(BaseMemberSerializer.Meta): fields = ["user"] class AfterCreate(BaseMemberSerializer): role = serializers.SerializerMethodField() class Meta(BaseMemberSerializer.Meta): fields = ["id", "user", "role"] def get_role(self, instance): t, val = str(instance.role).split(".", 1) return MembershipType[val].value class List(BaseMemberSerializer): role = serializers.SerializerMethodField() class Meta(BaseMemberSerializer.Meta): fields = ["id", "user", "role"] def get_role(self, instance): t, val = str(instance.role).split(".", 1) return MembershipType[val].value class ProjectSerializer: class Retrieve(_BaseProjectSerializer): products = serializers.SerializerMethodField() publishable = serializers.SerializerMethodField() products_amount = serializers.SerializerMethodField() max_product_stage = serializers.ReadOnlyField() members = MemberSerializer.List(many=True) class Meta(_BaseProjectSerializer.Meta): fields = [ "slug", *_BaseProjectSerializer.Meta.fields, "description", "category", "members", "brand", "products_amount", "products", "printing_files_date", "promo_date", "max_product_stage", "published", "publishable", "created_at", "updated_at", ] def get_publishable(self, project: "Project"): current_user = self.context["request"].user return project.publishable_for_user(user=current_user) def get_products(self, project: "Project"): url = reverse_lazy("products:product-list") return f"{url}?project={project.pk}" def get_products_amount(self, project: "Project"): return project.products.count() class AfterCreate(_BaseProjectSerializer): products = serializers.SerializerMethodField() publishable = serializers.SerializerMethodField() products_amount = serializers.SerializerMethodField() max_product_stage = serializers.ReadOnlyField() members = MemberSerializer.List(many=True) class Meta(_BaseProjectSerializer.Meta): fields = [ "id", "slug", *_BaseProjectSerializer.Meta.fields, "description", "category", "brand", "products_amount", "products", "printing_files_date", "promo_date", "members", # Computed "max_product_stage", "published", "publishable", "created_at", "updated_at", ] def get_publishable(self, project: "Project"): current_user = self.context["request"].user return project.publishable_for_user(user=current_user) def get_products(self, project: "Project"): # TODO: Hyperlink? url = reverse_lazy("products:product-list") return f"{url}?project={project.pk}" def get_products_amount(self, project: "Project"): return project.products.count() class List(_BaseProjectSerializer): products = serializers.SerializerMethodField() max_product_stage = serializers.ReadOnlyField() members = MemberSerializer.List(many=True) class Meta(_BaseProjectSerializer.Meta): fields = [ "id", "slug", *_BaseProjectSerializer.Meta.fields, "members", "products", "printing_files_date", "category", "brand", # Computed "max_product_stage", "published", "created_at", "updated_at", ] def get_products(self, instance): # TODO: refactor, maybe custom serializerfield url = reverse_lazy("products:product-list") return f"{url}?project={instance.pk}" class Create(_BaseProjectSerializer): products_amount = serializers.IntegerField(min_value=1, write_only=True) class Meta(_BaseProjectSerializer.Meta): fields = [ *_BaseProjectSerializer.Meta.fields, "description", "category", "brand", "products_amount", "printing_files_date", "promo_date", "created_at", "updated_at", ] # NOTE: business logic? def create(self, validated_data): products_amount = validated_data.pop("products_amount") project = super().create(validated_data) project.add_products(products_amount=products_amount) membership = Member.objects.create( user=self.context["request"].user, role=MembershipType.SUPPLIER, project=project, ) project.members.add(membership) return project class Update(serializers.Serializer): publish = serializers.BooleanField(default=False) def update(self, instance: Project, validated_data): current_user = self.context["request"].user if validated_data["publish"] is True: instance.publish_as_user(user=current_user) return instance