/
ilnar_g
/
111
Обзор
Документация
Войти
/
ilnar_g
/
111
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
admin.py
217 строк
9 KB
ilnar_g
upload files
26 сен 2025, 01:46
26 сен 2025, 01:46
3fd377a
Код
Авторство
О чём код?
from django.contrib import admin from django.utils.safestring import mark_safe # Добавьте этот импорт from django.urls import reverse from .models import Counterparty, Contract, Payment, Order, OrderSlot, Community, CommunityTariff from django import forms class CounterpartyAdminForm(forms.ModelForm): password_input = forms.CharField( required=False, widget=forms.PasswordInput(attrs={'placeholder': 'Введите пароль'}), label='Пароль', help_text='Оставьте пустым, чтобы не менять пароль' ) class Meta: model = Counterparty fields = '__all__' class CommunityTariffInline(admin.TabularInline): model = CommunityTariff extra = 6 min_num = 0 max_num = 6 fields = ['date_from', 'time_slot', 'single_post_price', 'min_3_posts_price', 'min_10_posts_price', 'min_25_posts_price', 'min_50_posts_price', 'min_100_posts_price', 'is_active'] class OrderSlotInline(admin.TabularInline): model = OrderSlot extra = 1 # Разрешаем добавлять новые слоты fields = ['community', 'date', 'time_slot', 'price', 'is_confirmed'] readonly_fields = ['created_at'] # Только дата создания только для чтения can_delete = True # Разрешаем удаление @admin.register(Counterparty) class CounterpartyAdmin(admin.ModelAdmin): form = CounterpartyAdminForm list_display = ['registration_number', 'name', 'inn', 'type', 'has_password', 'has_api_token', 'created_at'] fieldsets = ( (None, { 'fields': ('type', 'name', 'inn', 'registration_number') }), ('Контактная информация', { 'fields': ('contact_info',), 'classes': ('collapse',) }), ('Доступ в личный кабинет', { 'fields': ('password_input', 'api_token'), 'classes': ('collapse',), 'description': 'Пароль для входа в личный кабинет и API токен' }), ) readonly_fields = ['api_token'] def save_model(self, request, obj, form, change): # Обрабатываем установку пароля new_password = form.cleaned_data.get('password_input') if new_password: obj.set_password(new_password) super().save_model(request, obj, form, change) def has_api_token(self, obj): return bool(obj.api_token) has_api_token.boolean = True has_api_token.short_description = 'API Токен' def has_password(self, obj): return obj.has_usable_password() has_password.boolean = True has_password.short_description = 'Есть пароль' @admin.register(OrderSlot) class OrderSlotAdmin(admin.ModelAdmin): list_display = ['order', 'community', 'date', 'time_slot', 'price', 'is_confirmed'] list_filter = ['date', 'community', 'is_confirmed', 'time_slot'] search_fields = ['order__counterparty__name', 'community__name'] readonly_fields = ['created_at'] list_select_related = ['order', 'community', 'community_tariff'] class Meta: verbose_name = '5. Выход рекламы' verbose_name_plural = '5. Выходы рекламы' def get_queryset(self, request): return super().get_queryset(request).select_related('order__counterparty', 'community') @admin.register(Contract) class ContractAdmin(admin.ModelAdmin): list_display = ['get_contract_number', 'counterparty', 'amount', 'get_paid_amount', 'get_balance', 'conclusion_date', 'add_payment_button'] list_filter = ['conclusion_date'] search_fields = ['counterparty__name'] # Добавляем метод для кнопки "Внести платеж" def add_payment_button(self, obj): url = reverse('admin:counterparties_payment_add') + f'?contract={obj.id}' return mark_safe(f'<a href="{url}" class="button" style="padding: 5px 10px; background: #417690; color: white; text-decoration: none; border-radius: 3px;">Внести платеж</a>') add_payment_button.short_description = 'Действия' add_payment_button.allow_tags = True # Метод для отображения оплаченной суммы (зеленый цвет) def get_paid_amount(self, obj): paid = obj.get_total_payments() return mark_safe(f'<span style="color: green; font-weight: bold;">{paid} руб.</span>') get_paid_amount.short_description = 'Оплачено' get_paid_amount.admin_order_field = 'payments__amount' # Метод для отображения остатка (красный если есть долг, зеленый если оплачено) def get_balance(self, obj): balance = obj.get_balance() if balance > 0: return mark_safe(f'<span style="color: red; font-weight: bold;">{balance} руб.</span>') else: return mark_safe(f'<span style="color: green; font-weight: bold;">{balance} руб.</span>') get_balance.short_description = 'Остаток' def get_contract_number(self, obj): return obj.get_contract_number() get_contract_number.short_description = 'Номер договора' class Meta: verbose_name = '6. Договор' verbose_name_plural = '6. Договоры' @admin.register(Payment) class PaymentAdmin(admin.ModelAdmin): list_display = ['contract', 'get_counterparty', 'get_inn', 'amount', 'payment_date', 'method', 'commission', 'receipt_fee'] list_filter = ['method', 'payment_date'] search_fields = ['contract__counterparty__name', 'contract__counterparty__inn'] # Добавляем метод для отображения контрагента def get_counterparty(self, obj): return obj.contract.counterparty get_counterparty.short_description = 'Контрагент' get_counterparty.admin_order_field = 'contract__counterparty__name' # Добавляем метод для отображения ИНН def get_inn(self, obj): return obj.contract.counterparty.inn get_inn.short_description = 'ИНН' get_inn.admin_order_field = 'contract__counterparty__inn' # Добавляем предзаполнение договора из параметра URL def get_changeform_initial_data(self, request): initial = super().get_changeform_initial_data(request) contract_id = request.GET.get('contract') if contract_id: try: contract = Contract.objects.get(id=contract_id) initial['contract'] = contract except Contract.DoesNotExist: pass return initial class Meta: verbose_name = '7. Платёж' verbose_name_plural = '7. Платежи' @admin.register(Order) class OrderAdmin(admin.ModelAdmin): list_display = ['order_number', 'counterparty', 'get_inn', 'total_amount', 'slots_count', 'created_at'] list_filter = ['created_at', 'counterparty'] search_fields = ['counterparty__name', 'counterparty__inn', 'order_number'] readonly_fields = ['order_number', 'created_at'] inlines = [OrderSlotInline] # Добавляем метод для отображения ИНН def get_inn(self, obj): return obj.counterparty.inn get_inn.short_description = 'ИНН' # Название столбца get_inn.admin_order_field = 'counterparty__inn' # Возможность сортировки по ИНН fieldsets = ( (None, { 'fields': ('order_number', 'counterparty', 'contract', 'total_amount', 'slots_count') }), ('Системная информация', { 'fields': ('created_at',), 'classes': ('collapse',) }), ) class Meta: verbose_name = '4. Заказ' verbose_name_plural = '4. Заказы' @admin.register(Community) class CommunityAdmin(admin.ModelAdmin): list_display = ['name', 'link', 'is_active', 'created_at'] list_filter = ['is_active', 'created_at'] search_fields = ['name', 'link'] list_editable = ['is_active'] ordering = ['name'] inlines = [CommunityTariffInline] class Meta: verbose_name = '1. Сообщество' verbose_name_plural = '1. Сообщества' @admin.register(CommunityTariff) class CommunityTariffAdmin(admin.ModelAdmin): list_display = ['community', 'time_slot', 'date_from', 'is_active', 'single_post_price', 'min_3_posts_price', 'min_10_posts_price', 'min_25_posts_price', 'min_50_posts_price', 'min_100_posts_price'] list_filter = ['community', 'time_slot', 'is_active', 'date_from'] # Убираем tariff_version search_fields = ['community__name'] list_editable = ['is_active', 'single_post_price', 'min_3_posts_price', 'min_10_posts_price', 'min_25_posts_price', 'min_50_posts_price', 'min_100_posts_price'] ordering = ['community', 'time_slot'] # Убираем сортировку по версии class Meta: verbose_name = '2. Тариф' verbose_name_plural = '2. Тарифы' def get_queryset(self, request): return super().get_queryset(request).select_related('community')