""" Административная панель для пользователей. """ from django import forms from django.contrib import admin from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from django.contrib.auth.forms import UserChangeForm as BaseUserChangeForm, UserCreationForm as BaseUserCreationForm from django.utils.translation import gettext_lazy as _ from .models import User, Client, Parent, Mentor, MentorStudentConnection from .utils import normalize_phone class UserChangeForm(BaseUserChangeForm): class Meta(BaseUserChangeForm.Meta): model = User def clean_phone(self): value = self.cleaned_data.get('phone', '') or '' return normalize_phone(value) if value else '' class UserCreationForm(BaseUserCreationForm): class Meta(BaseUserCreationForm.Meta): model = User def clean_phone(self): value = self.cleaned_data.get('phone', '') or '' return normalize_phone(value) if value else '' class ClientMentorInline(admin.TabularInline): """Инлайн для связи ментор — студент (на странице ментора).""" model = Client.mentors.through fk_name = 'user' extra = 0 verbose_name = _('Студент') verbose_name_plural = _('Связь ментор — студент') autocomplete_fields = ['client'] @admin.register(User) class UserAdmin(BaseUserAdmin): """Административная панель для модели User.""" form = UserChangeForm add_form = UserCreationForm list_display = [ 'email', 'first_name', 'last_name', 'role', 'is_active', 'email_verified', 'created_at' ] list_filter = [ 'role', 'is_active', 'is_staff', 'is_superuser', 'email_verified', 'created_at' ] search_fields = ['email', 'first_name', 'last_name', 'phone', 'telegram_username'] ordering = ['-created_at'] fieldsets = ( (None, { 'fields': ('email', 'password') }), (_('Персональная информация'), { 'fields': ( 'first_name', 'last_name', 'birth_date', 'avatar', 'bio', 'phone' ) }), (_('Роль и права'), { 'fields': ( 'role', 'is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions' ) }), (_('Telegram'), { 'fields': ('telegram_id', 'telegram_username') }), (_('Верификация'), { 'fields': ('email_verified', 'email_verification_token') }), (_('Настройки'), { 'fields': ( 'timezone', 'language', 'notifications_enabled', 'email_notifications', 'telegram_notifications' ) }), (_('Блокировка'), { 'fields': ('is_blocked', 'blocked_reason', 'blocked_at'), 'classes': ('collapse',) }), (_('Важные даты'), { 'fields': ('last_login', 'last_activity', 'date_joined', 'created_at', 'updated_at'), 'classes': ('collapse',) }), ) add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ( 'email', 'password1', 'password2', 'first_name', 'last_name', 'role', 'is_staff', 'is_active' ), }), ) readonly_fields = ['created_at', 'updated_at', 'last_login', 'date_joined'] def get_readonly_fields(self, request, obj=None): """Сделать некоторые поля только для чтения после создания.""" # Email теперь можно редактировать в админке return self.readonly_fields @admin.register(Mentor) class MentorAdmin(BaseUserAdmin): """Отдельная админка только для менторов.""" form = UserChangeForm add_form = UserCreationForm list_display = [ 'email', 'first_name', 'last_name', 'clients_display', 'is_active', 'universal_code', 'created_at' ] list_filter = ['is_active', 'email_verified', 'created_at'] search_fields = ['email', 'first_name', 'last_name', 'phone', 'universal_code'] ordering = ['-created_at'] inlines = [ClientMentorInline] fieldsets = ( (None, {'fields': ('email', 'password')}), (_('Персональная информация'), { 'fields': ('first_name', 'last_name', 'birth_date', 'avatar', 'bio', 'phone') }), (_('Роль и права'), { 'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions') }), (_('Telegram'), {'fields': ('telegram_id', 'telegram_username')}), (_('Верификация'), {'fields': ('email_verified', 'email_verification_token')}), (_('Настройки'), { 'fields': ('timezone', 'language', 'universal_code', 'notifications_enabled', 'email_notifications', 'telegram_notifications', 'ai_trust_draft', 'ai_trust_publish') }), (_('Важные даты'), { 'fields': ('last_login', 'last_activity', 'date_joined', 'created_at', 'updated_at'), 'classes': ('collapse',) }), ) add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('email', 'password1', 'password2', 'first_name', 'last_name', 'is_staff', 'is_active'), }), ) readonly_fields = ['universal_code', 'created_at', 'updated_at', 'last_login', 'date_joined'] @admin.display(description=_('Студенты')) def clients_display(self, obj): clients = obj.clients.all()[:5] if not clients: return '—' names = [c.user.get_full_name() or c.user.email for c in clients] extra = obj.clients.count() - 5 if extra > 0: names.append(f'+{extra}') return ', '.join(names) def save_model(self, request, obj, form, change): obj.role = 'mentor' super().save_model(request, obj, form, change) @admin.register(Client) class ClientAdmin(admin.ModelAdmin): """Административная панель для модели Client.""" list_display = [ 'user', 'mentors_display', 'grade', 'school', 'total_lessons', 'completed_lessons', 'enrollment_date' ] list_filter = ['enrollment_date', 'created_at'] search_fields = [ 'user__email', 'user__first_name', 'user__last_name', 'school', 'grade' ] filter_horizontal = ['mentors'] readonly_fields = ['enrollment_date', 'created_at', 'updated_at'] fieldsets = ( (_('Пользователь'), { 'fields': ('user',) }), (_('Учебная информация'), { 'fields': ('grade', 'school', 'learning_goals') }), (_('Менторы'), { 'fields': ('mentors',) }), (_('Статистика'), { 'fields': ('total_lessons', 'completed_lessons') }), (_('Даты'), { 'fields': ('enrollment_date', 'created_at', 'updated_at'), 'classes': ('collapse',) }), ) @admin.display(description=_('Менторы')) def mentors_display(self, obj): mentors = obj.mentors.all()[:5] if not mentors: return '—' names = [m.get_full_name() or m.email for m in mentors] extra = obj.mentors.count() - 5 if extra > 0: names.append(f'+{extra}') return ', '.join(names) @admin.register(Parent) class ParentAdmin(admin.ModelAdmin): """Административная панель для модели Parent.""" list_display = [ 'user', 'relation_type', 'can_view_progress', 'can_view_schedule', 'created_at' ] list_filter = [ 'relation_type', 'can_view_progress', 'can_view_schedule', 'can_receive_reports', 'created_at' ] search_fields = [ 'user__email', 'user__first_name', 'user__last_name' ] filter_horizontal = ['children'] readonly_fields = ['created_at', 'updated_at'] fieldsets = ( (_('Пользователь'), { 'fields': ('user',) }), (_('Информация о родителе'), { 'fields': ('relation_type',) }), (_('Дети'), { 'fields': ('children',) }), (_('Права доступа'), { 'fields': ( 'can_view_progress', 'can_view_schedule', 'can_receive_reports' ) }), (_('Даты'), { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) @admin.register(MentorStudentConnection) class MentorStudentConnectionAdmin(admin.ModelAdmin): list_display = ['mentor', 'student', 'status', 'initiator', 'created_at'] list_filter = ['status', 'initiator', 'created_at'] search_fields = ['mentor__email', 'student__email', 'mentor__first_name', 'student__first_name'] readonly_fields = ['confirm_token', 'student_confirmed_at', 'parent_confirmed_at', 'created_at', 'updated_at']