from django.contrib import admin from django.utils import timezone from django.utils.html import format_html from django.urls import path from django.shortcuts import render from django.contrib import messages from .models import Home, Solution, Competence, Recall, CallbackRequest, PageView # ===== BASE ADMIN CLASSES ===== class BaseContentAdmin(admin.ModelAdmin): """Общий базовый класс для контентных моделей.""" list_display_links = ('id', 'title') list_editable = ('is_published',) list_filter = ('time_create', 'is_published') search_fields = ('title',) # ===== MODEL ADMINS ===== @admin.register(Home) class HomeAdmin(BaseContentAdmin): list_display = ('id', 'title', 'time_create', 'is_published') search_fields = ('title', 'content') @admin.register(Solution) class SolutionAdmin(BaseContentAdmin): list_display = ('id', 'title', 'time_create', 'is_published') search_fields = ('title', 'description', 'implementation') @admin.register(Competence) class CompetenceAdmin(BaseContentAdmin): list_display = ('id', 'title', 'time_create', 'is_published') search_fields = ('title', 'content') @admin.register(Recall) class RecallAdmin(BaseContentAdmin): list_display = ('id', 'title', 'time_create', 'scan', 'is_published') search_fields = ('title', 'content') @admin.register(CallbackRequest) class CallbackAdmin(admin.ModelAdmin): list_display = ('name', 'phone', 'email', 'time_create', 'is_processed', 'is_read', 'new_badge') list_display_links = ('name', 'phone') list_editable = ('is_processed', 'is_read') list_filter = ('time_create', 'is_processed', 'is_read') search_fields = ('name', 'phone', 'email') readonly_fields = ('time_create',) actions = ['mark_as_read', 'mark_as_unread', 'mark_as_processed', 'resend_notification'] # ── badge helper ────────────────────────────────────────────────────────── def new_badge(self, obj): if not obj.is_read: return format_html('🆕 НОВАЯ') return '' new_badge.short_description = 'Статус' # ── bulk actions ────────────────────────────────────────────────────────── def mark_as_read(self, request, queryset): updated = queryset.update(is_read=True) self.message_user(request, f'{updated} заявок отмечены как прочитанные') mark_as_read.short_description = 'Отметить как прочитанные' def mark_as_unread(self, request, queryset): updated = queryset.update(is_read=False) self.message_user(request, f'{updated} заявок отмечены как непрочитанные') mark_as_unread.short_description = 'Отметить как непрочитанные' def mark_as_processed(self, request, queryset): updated = queryset.update(is_processed=True) self.message_user(request, f'{updated} заявок отмечены как обработанные') mark_as_processed.short_description = 'Отметить как обработанные' def resend_notification(self, request, queryset): from .utils.email_notifications import send_multiple_callback_notifications count = send_multiple_callback_notifications(queryset) self.message_user(request, f'Уведомления отправлены для {count} заявок') resend_notification.short_description = 'Переотправить email уведомления' # ── custom URL + view for stats ─────────────────────────────────────────── def get_urls(self): urls = super().get_urls() custom_urls = [ path( 'callback-stats/', self.admin_site.admin_view(self.callback_stats_view), name='callback_stats', ), ] return custom_urls + urls def callback_stats_view(self, request): today = timezone.now().date() week_ago = today - timezone.timedelta(days=7) stats = { 'total': CallbackRequest.objects.count(), 'today': CallbackRequest.objects.filter(time_create__date=today).count(), 'week': CallbackRequest.objects.filter(time_create__date__gte=week_ago).count(), 'unread': CallbackRequest.objects.filter(is_read=False).count(), 'unprocessed': CallbackRequest.objects.filter(is_processed=False).count(), } context = { **self.admin_site.each_context(request), 'title': 'Статистика заявок', 'stats': stats, } return render(request, 'admin/callback_stats.html', context) # ── FIX: removed get_queryset message_user spam ─────────────────────────── # Previously, a warning banner was shown on EVERY request to the changelist, # including background requests. Removed entirely — the new_badge column # and base_site.html header notification already surface unread counts. @admin.register(PageView) class PageViewAdmin(admin.ModelAdmin): list_display = ('url', 'timestamp', 'ip_address') list_filter = ('timestamp', 'url') search_fields = ('url', 'ip_address') date_hierarchy = 'timestamp' readonly_fields = ('url', 'timestamp', 'ip_address') def get_queryset(self, request): return super().get_queryset(request).order_by('-timestamp') # PageViews should never be created or edited manually def has_add_permission(self, request): return False def has_change_permission(self, request, obj=None): return False