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