from rest_framework import serializers from api.v1.employees.serializers import EmployeeBriefSerializer from tasks.automation.schema import ( AutomationSchemaError, validate_automation_payload, ) from tasks.models import ( TaskAutomation, TaskAutomationKind, TaskAutomationRun, TaskBoard, ) class TaskAutomationRunSerializer(serializers.ModelSerializer): automation_name = serializers.CharField(source="automation.name", read_only=True) task_title = serializers.CharField(source="task.title", read_only=True) actor = EmployeeBriefSerializer(read_only=True) class Meta: model = TaskAutomationRun fields = [ "id", "automation", "automation_name", "task", "task_title", "trigger_activity", "actor", "source", "status", "context", "actions_log", "error", "started_at", "finished_at", ] read_only_fields = fields class TaskAutomationSerializer(serializers.ModelSerializer): """Validate shared automation rules exposed to authenticated task users. ``can_manage`` intentionally mirrors the temporary broad API permission. It should use the dedicated automation permission once that role is introduced. """ created_by = EmployeeBriefSerializer(read_only=True) boards = serializers.PrimaryKeyRelatedField( queryset=TaskBoard.objects.filter(is_archived=False), many=True, required=False, ) runs_count = serializers.IntegerField(read_only=True, default=0) can_manage = serializers.SerializerMethodField() class Meta: model = TaskAutomation fields = [ "id", "name", "description", "kind", "trigger", "conditions", "actions", "schedule_config", "applies_to_all_boards", "boards", "is_active", "stop_on_error", "position", "created_by", "last_run_at", "runs_count", "can_manage", "created_at", "updated_at", ] read_only_fields = [ "id", "created_by", "last_run_at", "runs_count", "can_manage", "created_at", "updated_at", ] def get_can_manage(self, obj) -> bool: user = getattr(self.context.get("request"), "user", None) return bool(user and user.is_authenticated) def validate_name(self, value): name = value.strip() if not name: raise serializers.ValidationError("Введите название автоматизации.") return name def validate(self, attrs): attrs = super().validate(attrs) instance = self.instance kind = attrs.get("kind", getattr(instance, "kind", TaskAutomationKind.EVENT)) trigger = attrs.get("trigger", getattr(instance, "trigger", "task_updated")) conditions = attrs.get("conditions", getattr(instance, "conditions", {})) actions = attrs.get("actions", getattr(instance, "actions", [])) schedule_config = attrs.get( "schedule_config", getattr(instance, "schedule_config", {}), ) try: normalized = validate_automation_payload( kind=kind, trigger=trigger, conditions=conditions, actions=actions, schedule_config=schedule_config, ) except AutomationSchemaError as error: raise serializers.ValidationError({"detail": str(error)}) from error attrs.update(normalized) applies_to_all = attrs.get( "applies_to_all_boards", getattr(instance, "applies_to_all_boards", True), ) boards = attrs.get("boards") if not applies_to_all and boards is not None and not boards: raise serializers.ValidationError( {"boards": "Выберите хотя бы одну доску или включите все доски."} ) if applies_to_all: attrs["boards"] = [] return attrs