from django.contrib import admin from django.utils.html import format_html from django.shortcuts import render from django_ckeditor_5.widgets import CKEditor5Widget from .models import ProductCategory, Configuration, Product, Order from programmer.utils.email_notifications import send_multiple_order_notifications, send_multiple_order_notifications_async from django.urls import reverse from programmer.tasks import send_new_product_notification from django.contrib import messages @admin.register(ProductCategory) class ProductCategoryAdmin(admin.ModelAdmin): list_display = ('name', 'slug', 'description') prepopulated_fields = {'slug': ('name',)} search_fields = ('name',) @admin.register(Configuration) class ConfigurationAdmin(admin.ModelAdmin): list_display = ('name', 'slug', 'description') prepopulated_fields = {'slug': ('name',)} search_fields = ('name',) @admin.register(Product) class ProductAdmin(admin.ModelAdmin): def get_form(self, request, obj=None, **kwargs): form = super().get_form(request, obj, **kwargs) form.base_fields['content'].widget = CKEditor5Widget(config_name='default') return form list_display = ('title', 'category', 'price', 'is_published', 'time_create', 'configurations_list') list_filter = ('is_published', 'category', 'configurations', 'time_create') search_fields = ('title', 'short_description', 'content') prepopulated_fields = {'slug': ('title',)} filter_horizontal = ('configurations',) date_hierarchy = 'time_create' actions = ['make_published', 'make_unpublished', 'send_notification'] fieldsets = ( (None, { 'fields': ('title', 'slug', 'category', 'price', 'is_published') }), ('Описания', { 'fields': ('short_description', 'content', 'image'), 'description': 'Краткое – обычный текст для карточки; полное – HTML-редактор для детальной страницы.' }), ('Совместимость', { 'fields': ('configurations',), }), ('SEO', { 'fields': ('meta_description',), 'classes': ('collapse',), }), ) def configurations_list(self, obj): return ", ".join(c.name for c in obj.configurations.all()) configurations_list.short_description = "Конфигурации" def view_on_site(self, obj): if obj.is_published: return obj.get_absolute_url() # Для неопубликованных — ссылка на предпросмотр return reverse('products:product_draft_preview', args=[obj.slug]) def make_published(self, request, queryset): queryset.update(is_published=True) make_published.short_description = "Опубликовать выбранные продукты" def make_unpublished(self, request, queryset): queryset.update(is_published=False) make_unpublished.short_description = "Снять с публикации" def send_notification(self, request, queryset): """Отправить уведомления подписчикам для выбранных продуктов.""" published = queryset.filter(is_published=True) count = published.count() if count == 0: self.message_user(request, "Нет опубликованных продуктов для отправки уведомлений.", level=messages.WARNING) return for product in published: send_new_product_notification.delay(product.id) self.message_user(request, f"Уведомления отправлены для {count} продуктов.") send_notification.short_description = "Отправить уведомление подписчикам о новых продуктах" @admin.register(Order) class OrderAdmin(admin.ModelAdmin): list_display = ('id', 'product', 'name', 'phone', 'created_at', 'is_processed', 'notification_sent') list_filter = ('is_processed', 'product', 'configuration', 'notification_sent') search_fields = ('name', 'phone', 'email') list_editable = ('is_processed',) readonly_fields = ('created_at',) actions = ['resend_order_notification'] # добавляем действие в выпадающий список def notification_badge(self, obj): # Если в модели Order добавите поле notification_sent, можно показывать иконку # Пока просто заглушка – всегда зелёная галочка (уведомление считается отправленным при создании) return format_html('') notification_badge.short_description = 'Уведомление' def resend_order_notification(self, request, queryset): """ Переотправляет уведомления для выбранных заказов. """ # count = send_multiple_order_notifications(queryset) count = send_multiple_order_notifications_async(queryset) self.message_user(request, f'Уведомления отправлены для {count} заказов.') resend_order_notification.short_description = 'Переотправить email уведомления' # Опционально: добавить кастомную кнопку на страницу списка def get_urls(self): from django.urls import path from django.shortcuts import render from django.contrib import messages urls = super().get_urls() custom_urls = [ path( 'order-stats/', self.admin_site.admin_view(self.order_stats_view), name='order_stats', ), ] return custom_urls + urls def notification_badge(self, obj): if obj.notification_sent: return format_html('') return format_html('') def order_stats_view(self, request): from .models import Order from django.utils import timezone today = timezone.now().date() week_ago = today - timezone.timedelta(days=7) stats = { 'total': Order.objects.count(), 'today': Order.objects.filter(created_at__date=today).count(), 'week': Order.objects.filter(created_at__date__gte=week_ago).count(), 'unprocessed': Order.objects.filter(is_processed=False).count(), } context = { **self.admin_site.each_context(request), 'title': 'Статистика заказов', 'stats': stats, } return render(request, 'admin/order_stats.html', context)