""" Административная панель для расписания. """ from django.contrib import admin from django.utils.html import format_html from django.utils.translation import gettext_lazy as _ from .models import Lesson, LessonTemplate, TimeSlot, Availability, Subject, MentorSubject @admin.register(Lesson) class LessonAdmin(admin.ModelAdmin): """Административная панель для занятий.""" list_display = [ 'title', 'mentor', 'client', 'start_time', 'duration', 'status_badge', 'created_at' ] list_filter = [ 'status', 'start_time', 'mentor', 'subject', 'mentor_subject', 'created_at' ] search_fields = [ 'title', 'description', 'subject__name', 'mentor_subject__name', 'subject_name', 'mentor__email', 'mentor__first_name', 'mentor__last_name', 'client__user__email', 'client__user__first_name', 'client__user__last_name' ] date_hierarchy = 'start_time' readonly_fields = [ 'end_time', 'created_at', 'updated_at', 'cancelled_at' ] fieldsets = ( (_('Участники'), { 'fields': ('mentor', 'client') }), (_('Время'), { 'fields': ('start_time', 'duration', 'end_time') }), (_('Информация'), { 'fields': ('title', 'description', 'subject', 'mentor_subject', 'subject_name', 'template') }), (_('Статус'), { 'fields': ('status',) }), (_('Отмена'), { 'fields': ( 'cancelled_by', 'cancellation_reason', 'cancelled_at' ), 'classes': ('collapse',) }), (_('Перенос'), { 'fields': ('rescheduled_from',), 'classes': ('collapse',) }), (_('Дополнительно'), { 'fields': ( 'meeting_url', 'mentor_notes', 'reminder_sent' ), 'classes': ('collapse',) }), (_('Даты'), { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) def status_badge(self, obj): """Отображение статуса с цветом.""" colors = { 'scheduled': '#3B82F6', # синий 'in_progress': '#10B981', # зеленый 'completed': '#6B7280', # серый 'cancelled': '#EF4444', # красный 'rescheduled': '#F59E0B', # оранжевый } color = colors.get(obj.status, '#6B7280') return format_html( '{}', color, obj.get_status_display() ) status_badge.short_description = 'Статус' def get_queryset(self, request): """Оптимизация запросов.""" return super().get_queryset(request).select_related( 'mentor', 'client', 'client__user', 'template', 'cancelled_by', 'rescheduled_from', 'subject', 'mentor_subject' ) @admin.register(LessonTemplate) class LessonTemplateAdmin(admin.ModelAdmin): """Административная панель для шаблонов занятий.""" list_display = [ 'title', 'mentor', 'subject', 'duration', 'is_active', 'lessons_count', 'created_at' ] list_filter = ['is_active', 'subject', 'mentor_subject', 'created_at'] search_fields = [ 'title', 'description', 'subject__name', 'mentor_subject__name', 'subject_name', 'mentor__email', 'mentor__first_name', 'mentor__last_name' ] readonly_fields = ['created_at', 'updated_at'] fieldsets = ( (_('Владелец'), { 'fields': ('mentor',) }), (_('Информация'), { 'fields': ('title', 'description', 'subject', 'mentor_subject', 'subject_name', 'duration') }), (_('Настройки'), { 'fields': ('is_active', 'meeting_url', 'color') }), (_('Даты'), { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) def lessons_count(self, obj): """Количество занятий созданных из шаблона.""" return obj.lessons.count() lessons_count.short_description = 'Занятий создано' def get_queryset(self, request): """Оптимизация запросов.""" return super().get_queryset(request).select_related('mentor', 'subject', 'mentor_subject') @admin.register(TimeSlot) class TimeSlotAdmin(admin.ModelAdmin): """Административная панель для временных слотов.""" list_display = [ 'mentor', 'start_time', 'end_time', 'availability_badge', 'is_recurring', 'created_at' ] list_filter = [ 'is_available', 'is_booked', 'is_recurring', 'start_time', 'created_at' ] search_fields = [ 'mentor__email', 'mentor__first_name', 'mentor__last_name' ] date_hierarchy = 'start_time' readonly_fields = ['created_at', 'updated_at'] fieldsets = ( (_('Ментор'), { 'fields': ('mentor',) }), (_('Время'), { 'fields': ('start_time', 'end_time') }), (_('Статус'), { 'fields': ('is_available', 'is_booked', 'lesson') }), (_('Повторение'), { 'fields': ('is_recurring', 'recurring_day') }), (_('Даты'), { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) def availability_badge(self, obj): """Отображение доступности.""" if obj.is_booked: return format_html( 'Забронирован' ) elif obj.is_available: return format_html( 'Доступен' ) else: return format_html( 'Недоступен' ) availability_badge.short_description = 'Доступность' def get_queryset(self, request): """Оптимизация запросов.""" return super().get_queryset(request).select_related('mentor', 'lesson') @admin.register(Availability) class AvailabilityAdmin(admin.ModelAdmin): """Административная панель для доступности.""" list_display = [ 'mentor', 'day_display', 'time_range', 'is_recurring', 'is_active', 'created_at' ] list_filter = [ 'is_active', 'is_recurring', 'day_of_week', 'created_at' ] search_fields = [ 'mentor__email', 'mentor__first_name', 'mentor__last_name', 'notes' ] readonly_fields = ['created_at', 'updated_at'] fieldsets = ( (_('Ментор'), { 'fields': ('mentor',) }), (_('Время'), { 'fields': ('day_of_week', 'specific_date', 'start_time', 'end_time') }), (_('Тип'), { 'fields': ('is_recurring', 'is_active') }), (_('Исключения'), { 'fields': ('exception_dates', 'notes'), 'classes': ('collapse',) }), (_('Даты'), { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) def day_display(self, obj): """Отображение дня.""" if obj.is_recurring and obj.day_of_week is not None: return obj.get_day_of_week_display() elif obj.specific_date: return obj.specific_date.strftime('%d.%m.%Y') return '-' day_display.short_description = 'День' def time_range(self, obj): """Отображение временного диапазона.""" return f"{obj.start_time.strftime('%H:%M')} - {obj.end_time.strftime('%H:%M')}" time_range.short_description = 'Время' def get_queryset(self, request): """Оптимизация запросов.""" return super().get_queryset(request).select_related('mentor') @admin.register(Subject) class SubjectAdmin(admin.ModelAdmin): """Административная панель для предметов.""" list_display = ['name', 'is_active', 'lessons_count', 'created_at'] list_filter = ['is_active', 'created_at'] search_fields = ['name'] readonly_fields = ['created_at', 'updated_at'] fieldsets = ( (_('Информация'), { 'fields': ('name', 'is_active') }), (_('Даты'), { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) def lessons_count(self, obj): """Количество занятий с этим предметом.""" return obj.lessons.count() lessons_count.short_description = 'Занятий' @admin.register(MentorSubject) class MentorSubjectAdmin(admin.ModelAdmin): """Административная панель для кастомных предметов менторов.""" list_display = ['name', 'mentor', 'usage_count', 'created_at'] list_filter = ['created_at'] search_fields = ['name', 'mentor__email', 'mentor__first_name', 'mentor__last_name'] readonly_fields = ['created_at', 'updated_at'] fieldsets = ( (_('Информация'), { 'fields': ('mentor', 'name', 'usage_count') }), (_('Даты'), { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) def get_queryset(self, request): """Оптимизация запросов.""" return super().get_queryset(request).select_related('mentor')