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)