160 lines
6.4 KiB
Python
160 lines
6.4 KiB
Python
"""
|
||
Сервис для экспорта данных расписания в различные форматы.
|
||
"""
|
||
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
|
||
}
|
||
|