Corp/backend/api/v1/schedule/serializers.py
igor_nadein d94e82d313 feat: add django-scheduler API v1 endpoints
New clean API alongside old calendar_app:

API endpoints:
- /api/v1/schedule/calendars/ - Calendar CRUD
- /api/v1/schedule/events/ - Event CRUD (with timezone)
- /api/v1/schedule/rules/ - rrule RFC 5545 rules
- /api/v1/schedule/occurrences/ - materialized recurrences
- /api/v1/schedule/relations/ - meeting attendees

Features:
- Timezone support (pytz)
- RFC 5545 rrule for recurring events
- EventRelation for meeting participants
- Clean, tested code (django-scheduler)
- Parallel work with old /api/v1/calendar/

Old API untouched, works as before.
Gradual migration approach (Strangler Fig Pattern).
2026-02-24 17:35:30 +03:00

141 lines
4.1 KiB
Python

# backend/api/v1/schedule/serializers.py
"""
Serializers для django-scheduler.
Чистые, проверенные временем модели.
"""
from rest_framework import serializers
from schedule.models import Calendar, Event, Rule, Occurrence, EventRelation
import pytz
class CalendarSerializer(serializers.ModelSerializer):
"""Сериализатор для Calendar (django-scheduler)."""
events_count = serializers.SerializerMethodField()
class Meta:
model = Calendar
fields = ['id', 'name', 'slug', 'events_count']
read_only_fields = ['id']
def get_events_count(self, obj):
"""Количество событий в календаре."""
return obj.event_set.count()
class RuleSerializer(serializers.ModelSerializer):
"""Сериализатор для Rule (rrule RFC 5545)."""
class Meta:
model = Rule
fields = ['id', 'name', 'description', 'frequency', 'params']
read_only_fields = ['id']
class EventSerializer(serializers.ModelSerializer):
"""Сериализатор для Event (django-scheduler)."""
calendar_name = serializers.CharField(source='calendar.name', read_only=True)
rule_description = serializers.CharField(source='rule.description', read_only=True, allow_null=True)
class Meta:
model = Event
fields = [
'id',
'title',
'description',
'start',
'end',
'calendar',
'calendar_name',
'rule',
'rule_description',
'end_recurring_period',
'color_event',
'creator',
'created_on',
'updated_on',
]
read_only_fields = ['id', 'created_on', 'updated_on']
def validate(self, attrs):
"""Валидация start/end."""
start = attrs.get('start')
end = attrs.get('end')
if end and start and end < start:
raise serializers.ValidationError({
'end': 'Дата окончания не может быть раньше даты начала.'
})
return attrs
class EventListSerializer(EventSerializer):
"""Упрощённый сериализатор для списка событий."""
class Meta(EventSerializer.Meta):
fields = [
'id',
'title',
'start',
'end',
'calendar',
'calendar_name',
'color_event',
]
class OccurrenceSerializer(serializers.ModelSerializer):
"""Сериализатор для Occurrence (материализованные вхождения)."""
event_title = serializers.CharField(source='event.title', read_only=True)
event_id = serializers.IntegerField(source='event.id', read_only=True)
class Meta:
model = Occurrence
fields = [
'id',
'event',
'event_id',
'event_title',
'title',
'description',
'start',
'end',
'cancelled',
'original_start',
'original_end',
'created_on',
'updated_on',
]
read_only_fields = ['id', 'created_on', 'updated_on']
class EventRelationSerializer(serializers.ModelSerializer):
"""Сериализатор для EventRelation (участники встреч)."""
event_title = serializers.CharField(source='event.title', read_only=True)
user_name = serializers.SerializerMethodField()
class Meta:
model = EventRelation
fields = [
'id',
'event',
'event_title',
'content_type',
'object_id',
'content_object',
'user_name',
'distinction',
'created_on',
]
read_only_fields = ['id', 'created_on']
def get_user_name(self, obj):
"""Имя связанного объекта."""
if obj.content_object:
return str(obj.content_object)
return None