# -*- coding: utf-8 -*- from django.contrib import admin from django.utils.html import format_html from .models import Order, OrderItem, Payment, PaymentMethod, Address, OrderStatus class PaymentInline(admin.TabularInline): """ Inline для управления платежами по заказу. """ model = Payment extra = 1 fields = ['amount', 'payment_method', 'payment_date', 'created_by', 'notes'] readonly_fields = ['payment_date'] class OrderItemInline(admin.TabularInline): """ Inline для управления позициями заказа прямо в форме заказа. """ model = OrderItem extra = 1 fields = ['product', 'product_kit', 'quantity', 'price'] readonly_fields = [] def get_readonly_fields(self, request, obj=None): """Делаем цену readonly для существующих позиций""" if obj and obj.pk: return ['price'] return [] @admin.register(Order) class OrderAdmin(admin.ModelAdmin): """ Админ-панель для управления заказами. """ list_display = [ 'order_number', 'customer', 'is_delivery', 'delivery_date', 'status', 'total_amount', 'payment_status', 'amount_paid', 'created_at', ] list_filter = [ 'status', 'is_delivery', 'payment_status', 'delivery_date', 'created_at', ] search_fields = [ 'order_number', 'customer__name', 'customer__phone', 'customer__email', 'delivery_address__recipient_name', 'delivery_address__street', ] readonly_fields = [ 'order_number', 'created_at', 'updated_at', 'delivery_info', 'delivery_time_window', 'amount_due', 'payment_status', ] fieldsets = ( ('Основная информация', { 'fields': ('order_number', 'customer', 'status') }), ('Доставка', { 'fields': ( 'is_delivery', 'customer_is_recipient', 'delivery_address', 'pickup_warehouse', 'delivery_date', 'delivery_time_start', 'delivery_time_end', 'delivery_cost', 'delivery_info', 'delivery_time_window', ) }), ('Оплата', { 'fields': ( 'total_amount', 'discount_amount', 'amount_paid', 'amount_due', 'payment_status', ) }), ('Дополнительно', { 'fields': ('is_anonymous', 'special_instructions'), 'classes': ('collapse',) }), ('Системная информация', { 'fields': ('created_at', 'updated_at', 'modified_by'), 'classes': ('collapse',) }), ) inlines = [OrderItemInline, PaymentInline] actions = [ 'mark_as_confirmed', 'mark_as_in_assembly', 'mark_as_in_delivery', 'mark_as_delivered', 'mark_as_paid', ] def mark_as_confirmed(self, request, queryset): """Отметить заказы как подтвержденные""" updated = queryset.update(status='confirmed') self.message_user(request, f'{updated} заказ(ов) отмечено как подтвержденные') mark_as_confirmed.short_description = 'Отметить как подтвержденные' def mark_as_in_assembly(self, request, queryset): """Отметить заказы как в сборке""" updated = queryset.update(status='in_assembly') self.message_user(request, f'{updated} заказ(ов) отмечено как в сборке') mark_as_in_assembly.short_description = 'Отметить как в сборке' def mark_as_in_delivery(self, request, queryset): """Отметить заказы как в доставке""" updated = queryset.update(status='in_delivery') self.message_user(request, f'{updated} заказ(ов) отмечено как в доставке') mark_as_in_delivery.short_description = 'Отметить как в доставке' def mark_as_delivered(self, request, queryset): """Отметить заказы как доставленные""" updated = queryset.update(status='delivered') self.message_user(request, f'{updated} заказ(ов) отмечено как доставленные') mark_as_delivered.short_description = 'Отметить как доставленные' def mark_as_paid(self, request, queryset): """Отметить заказы как оплаченные""" updated = queryset.update(is_paid=True) self.message_user(request, f'{updated} заказ(ов) отмечено как оплаченные') mark_as_paid.short_description = 'Отметить как оплаченные' @admin.register(Payment) class PaymentAdmin(admin.ModelAdmin): """ Админ-панель для управления платежами. """ list_display = [ 'order', 'amount', 'payment_method', 'payment_date', 'created_by', ] list_filter = [ 'payment_method', 'payment_date', ] search_fields = [ 'order__order_number', 'notes', ] readonly_fields = ['payment_date'] fieldsets = ( ('Информация о платеже', { 'fields': ('order', 'amount', 'payment_method', 'payment_date') }), ('Дополнительно', { 'fields': ('created_by', 'notes') }), ) @admin.register(OrderItem) class OrderItemAdmin(admin.ModelAdmin): """ Админ-панель для управления позициями заказов. """ list_display = [ 'order', 'item_name', 'quantity', 'price', 'get_total_price', ] list_filter = [ 'order__status', 'order__created_at', ] search_fields = [ 'order__order_number', 'product__name', 'product_kit__name', ] readonly_fields = ['created_at', 'get_total_price'] fieldsets = ( ('Заказ', { 'fields': ('order',) }), ('Товар/Комплект', { 'fields': ('product', 'product_kit') }), ('Информация', { 'fields': ('quantity', 'price', 'get_total_price') }), ('Системная информация', { 'fields': ('created_at',), 'classes': ('collapse',) }), ) @admin.register(Address) class AddressAdmin(admin.ModelAdmin): """ Админ-панель для управления адресами доставки заказов. """ list_display = [ 'recipient_name', 'recipient_phone', 'full_address', 'entrance', 'floor', 'confirm_address_with_recipient', 'created_at', ] list_filter = [ 'confirm_address_with_recipient', 'created_at', ] search_fields = [ 'recipient_name', 'street', 'building_number', ] readonly_fields = ['created_at', 'updated_at'] fieldsets = ( ('Информация о получателе', { 'fields': ('recipient_name', 'recipient_phone') }), ('Адрес доставки', { 'fields': ('street', 'building_number', 'apartment_number', 'entrance', 'floor') }), ('Доступ в здание', { 'fields': ('intercom_code',), 'classes': ('collapse',) }), ('Дополнительная информация', { 'fields': ('delivery_instructions', 'confirm_address_with_recipient'), 'classes': ('collapse',) }), ('Даты', { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), ) @admin.register(OrderStatus) class OrderStatusAdmin(admin.ModelAdmin): """ Админ-панель для управления статусами заказов. """ list_display = [ 'order_display', 'name', 'code', 'color_preview', 'is_system', 'is_positive_end', 'is_negative_end', 'orders_count', ] list_filter = [ 'is_system', 'is_positive_end', 'is_negative_end', ] search_fields = [ 'name', 'code', 'label', ] readonly_fields = ['created_at', 'updated_at', 'created_by', 'updated_by'] fieldsets = ( ('Основная информация', { 'fields': ('code', 'name', 'label', 'order') }), ('Визуальное оформление', { 'fields': ('color',) }), ('Тип статуса', { 'fields': ('is_system', 'is_positive_end', 'is_negative_end') }), ('Дополнительно', { 'fields': ('description',), 'classes': ('collapse',) }), ('Системная информация', { 'fields': ('created_at', 'updated_at', 'created_by', 'updated_by', 'get_orders_count'), 'classes': ('collapse',) }), ) ordering = ['order', 'name'] def get_readonly_fields(self, request, obj=None): """Делаем код readonly для системных статусов""" readonly = list(self.readonly_fields) readonly.append('get_orders_count') if obj and obj.is_system: readonly.append('code') return readonly def color_preview(self, obj): """Превью цвета статуса""" return format_html( '
', obj.color ) color_preview.short_description = 'Цвет' def order_display(self, obj): """Отображение порядкового номера с бейджем""" return format_html( '{}', obj.order ) order_display.short_description = 'Порядок' def orders_count(self, obj): """Количество заказов в этом статусе""" count = obj.orders_count if count == 0: return format_html('{}', count) return format_html('{}', count) orders_count.short_description = 'Заказов' def get_orders_count(self, obj): """Количество заказов для readonly поля""" return obj.orders_count if obj else 0 get_orders_count.short_description = 'Количество заказов' def has_delete_permission(self, request, obj=None): """Запрещаем удаление системных статусов и статусов с заказами""" if obj: if obj.is_system or obj.orders_count > 0: return False return super().has_delete_permission(request, obj) @admin.register(PaymentMethod) class PaymentMethodAdmin(admin.ModelAdmin): """ Админ-панель для управления способами оплаты. """ list_display = [ 'order_display', 'name', 'code', 'description', 'is_active', 'is_system', 'payments_count', ] list_filter = [ 'is_active', 'is_system', ] search_fields = [ 'name', 'code', 'description', ] readonly_fields = ['created_at', 'updated_at', 'created_by'] fieldsets = ( ('Основная информация', { 'fields': ('code', 'name', 'description', 'order') }), ('Настройки', { 'fields': ('is_active', 'is_system') }), ('Системная информация', { 'fields': ('created_at', 'updated_at', 'created_by'), 'classes': ('collapse',) }), ) ordering = ['order', 'name'] def get_readonly_fields(self, request, obj=None): """Делаем код readonly для системных способов оплаты""" readonly = list(self.readonly_fields) if obj and obj.is_system: readonly.append('code') return readonly def order_display(self, obj): """Отображение порядкового номера с бейджем""" return format_html( '{}', obj.order ) order_display.short_description = 'Порядок' def payments_count(self, obj): """Количество платежей этим способом""" count = obj.payments.count() if count == 0: return format_html('{}', count) return format_html('{}', count) payments_count.short_description = 'Платежей' def has_delete_permission(self, request, obj=None): """Запрещаем удаление используемых способов оплаты""" if obj: # Разрешаем удаление только если нет связанных платежей if obj.payments.exists(): return False return super().has_delete_permission(request, obj)