uchill/backend/apps/schedule/export_service.py

160 lines
6.4 KiB
Python
Raw Permalink 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.

"""
Сервис для экспорта данных расписания в различные форматы.
"""
import logging
from datetime import datetime, timedelta
from typing import List, Dict
from django.utils import timezone
from django.http import HttpResponse
logger = logging.getLogger(__name__)
try:
from icalendar import Calendar, Event
ICALENDAR_AVAILABLE = True
except ImportError:
ICALENDAR_AVAILABLE = False
logger.warning("icalendar не установлен. Экспорт в iCal недоступен.")
class ScheduleExportService:
"""Сервис для экспорта расписания."""
@staticmethod
def export_to_ical(lessons, user=None) -> HttpResponse:
"""
Экспорт занятий в формат iCal.
Args:
lessons: QuerySet или список объектов Lesson
user: Пользователь (опционально, для персонализации)
Returns:
HttpResponse с файлом .ics
"""
if not ICALENDAR_AVAILABLE:
return HttpResponse(
'Экспорт в iCal недоступен. Установите icalendar: pip install icalendar',
status=500,
content_type='text/plain'
)
cal = Calendar()
cal.add('prodid', '-//Platform//Schedule Export//RU')
cal.add('version', '2.0')
cal.add('X-WR-CALNAME', 'Расписание занятий')
cal.add('X-WR-TIMEZONE', 'Europe/Moscow')
for lesson in lessons:
event = Event()
# Основная информация
event.add('summary', lesson.title or f"Занятие с {lesson.mentor.get_full_name()}")
event.add('dtstart', lesson.start_time)
event.add('dtend', lesson.end_time)
event.add('dtstamp', timezone.now())
# Описание
description_parts = []
if lesson.mentor:
description_parts.append(f"Ментор: {lesson.mentor.get_full_name()}")
if lesson.client:
description_parts.append(f"Клиент: {lesson.client.get_full_name()}")
if lesson.subject:
description_parts.append(f"Предмет: {lesson.subject.name}")
if lesson.description:
description_parts.append(f"\n{lesson.description}")
if lesson.location:
description_parts.append(f"\nМесто: {lesson.location}")
event.add('description', '\n'.join(description_parts))
# Местоположение
if lesson.location:
event.add('location', lesson.location)
# URL видеоконференции
if lesson.video_room and lesson.video_room.join_url:
event.add('url', lesson.video_room.join_url)
# Статус
if lesson.status == 'completed':
event.add('status', 'CONFIRMED')
elif lesson.status == 'cancelled':
event.add('status', 'CANCELLED')
else:
event.add('status', 'TENTATIVE')
# Уникальный ID
event.add('uid', f"lesson-{lesson.id}@platform")
# Напоминание за 1 час
alarm = Event()
alarm.add('action', 'DISPLAY')
alarm.add('description', f"Напоминание: {event.get('summary')}")
alarm.add('trigger', timedelta(hours=-1))
event.add_component(alarm)
cal.add_component(event)
# Формируем HTTP ответ
response = HttpResponse(cal.to_ical(), content_type='text/calendar; charset=utf-8')
filename = f"schedule_{datetime.now().strftime('%Y%m%d')}.ics"
response['Content-Disposition'] = f'attachment; filename="{filename}"'
return response
@staticmethod
def export_to_json(lessons, user=None) -> Dict:
"""
Экспорт занятий в JSON формат.
Args:
lessons: QuerySet или список объектов Lesson
user: Пользователь (опционально)
Returns:
dict: Данные в формате JSON
"""
lessons_data = []
for lesson in lessons:
lesson_data = {
'id': lesson.id,
'title': lesson.title,
'start_time': lesson.start_time.isoformat() if lesson.start_time else None,
'end_time': lesson.end_time.isoformat() if lesson.end_time else None,
'status': lesson.status,
'mentor': {
'id': lesson.mentor.id,
'name': lesson.mentor.get_full_name(),
'email': lesson.mentor.email
} if lesson.mentor else None,
'client': {
'id': lesson.client.id,
'name': lesson.client.get_full_name(),
'email': lesson.client.email
} if lesson.client else None,
'subject': {
'id': lesson.subject.id,
'name': lesson.subject.name
} if lesson.subject else None,
'description': lesson.description,
'location': lesson.location,
'video_room': {
'id': lesson.video_room.id,
'join_url': lesson.video_room.join_url
} if lesson.video_room and lesson.video_room.join_url else None,
'price': float(lesson.price) if lesson.price else None,
'created_at': lesson.created_at.isoformat() if lesson.created_at else None,
'updated_at': lesson.updated_at.isoformat() if lesson.updated_at else None
}
lessons_data.append(lesson_data)
return {
'export_date': timezone.now().isoformat(),
'total_lessons': len(lessons_data),
'lessons': lessons_data
}