from django.contrib import admin
from django.db import models
from django.utils.html import format_html
from .models import Customer, WalletTransaction, ContactChannel
class IsSystemCustomerFilter(admin.SimpleListFilter):
title = 'Системный клиент'
parameter_name = 'is_system_customer'
def lookups(self, request, model_admin):
return (
('yes', 'Системный'),
('no', 'Обычный'),
)
def queryset(self, request, queryset):
if self.value() == 'yes':
return queryset.filter(is_system_customer=True)
if self.value() == 'no':
return queryset.filter(is_system_customer=False)
return queryset
@admin.register(Customer)
class CustomerAdmin(admin.ModelAdmin):
"""Административный интерфейс для управления клиентами цветочного магазина"""
list_display = (
'full_name',
'email',
'phone',
'wallet_balance_display',
'is_system_customer',
'created_at'
)
list_filter = (
IsSystemCustomerFilter,
'created_at'
)
search_fields = (
'name',
'email',
'phone'
)
date_hierarchy = 'created_at'
ordering = ('-created_at',)
readonly_fields = ('created_at', 'updated_at', 'is_system_customer', 'wallet_balance_display')
fieldsets = (
('Основная информация', {
'fields': ('name', 'email', 'phone', 'is_system_customer')
}),
('Кошелёк', {
'fields': ('wallet_balance_display',),
}),
('Заметки', {
'fields': ('notes',)
}),
('Даты', {
'fields': ('created_at', 'updated_at'),
'classes': ('collapse',)
}),
)
def wallet_balance_display(self, obj):
"""Отображение баланса кошелька с цветом"""
balance = obj.wallet_balance
if balance > 0:
return format_html(
'{} руб.',
balance
)
return f'{balance} руб.'
wallet_balance_display.short_description = 'Баланс кошелька'
def get_readonly_fields(self, request, obj=None):
"""Делаем все поля read-only для системного клиента"""
if obj and obj.is_system_customer:
# Для системного клиента все поля только для чтения
return ['name', 'email', 'phone', 'is_system_customer', 'wallet_balance_display', 'notes', 'created_at', 'updated_at']
return self.readonly_fields
def has_delete_permission(self, request, obj=None):
"""Запрет на удаление системного клиента"""
if obj and obj.is_system_customer:
return False
return super().has_delete_permission(request, obj)
def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
"""Добавляем предупреждение для системного клиента"""
extra_context = extra_context or {}
if object_id:
obj = self.get_object(request, object_id)
if obj and obj.is_system_customer:
extra_context['readonly'] = True
from django.contrib import messages
messages.warning(request, 'Это системный клиент. Редактирование запрещено для обеспечения корректной работы системы.')
return super().changeform_view(request, object_id, form_url, extra_context)
class ContactChannelInline(admin.TabularInline):
"""Inline для управления каналами связи клиента"""
model = ContactChannel
extra = 1
fields = ('channel_type', 'value', 'is_primary', 'notes')
class WalletTransactionInline(admin.TabularInline):
"""Inline для отображения транзакций кошелька"""
model = WalletTransaction
extra = 0
can_delete = False
readonly_fields = ('created_at', 'transaction_type', 'signed_amount', 'balance_after', 'order', 'description', 'created_by')
fields = ('created_at', 'transaction_type', 'signed_amount', 'balance_after', 'order', 'description', 'created_by')
ordering = ('-created_at',)
def has_add_permission(self, request, obj=None):
"""Запрещаем ручное создание транзакций - только через сервис"""
return False
# Добавляем inline в CustomerAdmin
CustomerAdmin.inlines = [ContactChannelInline, WalletTransactionInline]
@admin.register(WalletTransaction)
class WalletTransactionAdmin(admin.ModelAdmin):
"""Админка для просмотра всех транзакций кошелька"""
list_display = ('created_at', 'customer', 'transaction_type', 'amount_display', 'balance_after', 'order', 'created_by')
list_filter = ('transaction_type', 'balance_category', 'created_at')
search_fields = ('customer__name', 'customer__email', 'customer__phone', 'description')
readonly_fields = ('customer', 'transaction_type', 'signed_amount', 'balance_category', 'balance_after', 'order', 'description', 'created_at', 'created_by')
date_hierarchy = 'created_at'
ordering = ('-created_at',)
def amount_display(self, obj):
"""Отображение суммы с цветом"""
amount = obj.signed_amount
if amount > 0:
return format_html(
'+{} руб.',
amount
)
elif amount < 0:
return format_html(
'{} руб.',
amount
)
return f'{amount} руб.'
amount_display.short_description = 'Сумма'
def has_add_permission(self, request):
"""Запрещаем ручное создание - только через сервис"""
return False
def has_delete_permission(self, request, obj=None):
"""Запрещаем удаление - аудит должен быть неизменяем"""
return False