183 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from tasks.models import (
TaskColumn,
TaskColumnRow,
TaskLabel,
)
from .common import validate_board_access
class TaskLabelSerializer(serializers.ModelSerializer):
class Meta:
model = TaskLabel
fields = ["id", "name", "color"]
read_only_fields = ["id"]
def validate_name(self, value):
name = value.strip()
duplicate = TaskLabel.objects.only("id", "name")
if self.instance:
duplicate = duplicate.exclude(pk=self.instance.pk)
normalized_name = name.casefold()
if any(label.name.casefold() == normalized_name for label in duplicate):
raise serializers.ValidationError("Метка с таким названием уже существует.")
return name
class TaskColumnSerializer(serializers.ModelSerializer):
tasks_count = serializers.IntegerField(read_only=True, default=0)
subcolumns_count = serializers.SerializerMethodField()
class Meta:
model = TaskColumn
validators = []
fields = [
"id",
"board",
"parent",
"name",
"position",
"color",
"is_done",
"is_archived",
"tasks_count",
"subcolumns_count",
"created_at",
"updated_at",
]
read_only_fields = [
"id",
"created_at",
"updated_at",
"tasks_count",
"subcolumns_count",
]
def validate_board(self, board):
return validate_board_access(self, board)
@extend_schema_field(serializers.IntegerField())
def get_subcolumns_count(self, obj):
annotated_count = getattr(obj, "subcolumns_count", None)
if annotated_count is not None:
return annotated_count
return obj.subcolumns.filter(is_archived=False).count()
def validate(self, attrs):
board = attrs.get("board") or getattr(self.instance, "board", None)
parent = attrs.get("parent", getattr(self.instance, "parent", None))
if self.instance and board and self.instance.board_id != board.id:
raise serializers.ValidationError(
{"board": "Доску существующей колонки изменить нельзя."}
)
if self.instance and "parent" in attrs:
current_parent_id = self.instance.parent_id
requested_parent_id = parent.id if parent else None
if current_parent_id != requested_parent_id:
raise serializers.ValidationError(
{"parent": "Родителя существующей колонки изменить нельзя."}
)
if parent:
if board and parent.board_id != board.id:
raise serializers.ValidationError(
{"parent": "Подколонка должна принадлежать той же доске."}
)
if parent.parent_id:
raise serializers.ValidationError(
{"parent": "Допускается только один уровень подколонок."}
)
if parent.is_archived:
raise serializers.ValidationError(
{"parent": "Нельзя добавить подколонку в архивную колонку."}
)
attrs["is_done"] = parent.is_done
if (
self.instance
and attrs.get("is_archived") is True
and self.instance.subcolumns.exists()
):
raise serializers.ValidationError(
{"is_archived": "Сначала удалите подколонки."}
)
name = attrs.get("name", getattr(self.instance, "name", ""))
if board and name:
duplicate_columns = TaskColumn.objects.filter(name=name)
if parent:
duplicate_columns = duplicate_columns.filter(parent=parent)
else:
duplicate_columns = duplicate_columns.filter(
board=board,
parent__isnull=True,
)
if self.instance:
duplicate_columns = duplicate_columns.exclude(pk=self.instance.pk)
if duplicate_columns.exists():
raise serializers.ValidationError(
{"name": "Колонка с таким названием уже существует здесь."}
)
return attrs
def create(self, validated_data):
parent = validated_data.get("parent")
if parent:
validated_data.setdefault("color", parent.color)
validated_data.setdefault("is_done", parent.is_done)
return super().create(validated_data)
class TaskColumnRowSerializer(serializers.ModelSerializer):
tasks_count = serializers.IntegerField(read_only=True, default=0)
class Meta:
model = TaskColumnRow
fields = [
"id",
"column",
"name",
"position",
"color",
"tasks_count",
"created_at",
"updated_at",
]
read_only_fields = ["id", "tasks_count", "created_at", "updated_at"]
def validate_column(self, column):
validate_board_access(self, column.board)
if column.parent_id:
raise serializers.ValidationError(
"Дорожки можно создавать только в основной колонке."
)
if column.is_archived:
raise serializers.ValidationError(
"Нельзя создать дорожку в архивной колонке."
)
return column
def validate(self, attrs):
column = attrs.get("column") or getattr(self.instance, "column", None)
if self.instance and column and self.instance.column_id != column.id:
raise serializers.ValidationError(
{"column": "Основную колонку дорожки изменить нельзя."}
)
name = attrs.get("name", getattr(self.instance, "name", "")).strip()
if not name:
raise serializers.ValidationError({"name": "Укажите название дорожки."})
duplicate = TaskColumnRow.objects.filter(column=column, name__iexact=name)
if self.instance:
duplicate = duplicate.exclude(pk=self.instance.pk)
if duplicate.exists():
raise serializers.ValidationError(
{"name": "Дорожка с таким названием уже существует в колонке."}
)
attrs["name"] = name
return attrs