Единый источник истины для способов оплаты

Проблема #1: Дублирование кода способов оплаты
- В tenants/admin.py был полный список способов оплаты (45 строк)
- В orders/management/commands/create_payment_methods.py был другой список
- При создании тенанта отсутствовал способ 'account_balance'
- Нарушение DRY принципа

Решение: Single Source of Truth
- Единственный источник истины: команда create_payment_methods
- В tenants/admin.py заменено дублирование на call_command()
- Удалено 45 строк дублирующего кода
- Теперь все тенанты получают одинаковый полный список

Проблема #2: AttributeError в админке PaymentMethod
- obj.payments.count() вызывал ошибку
- В модели Transaction связь называется 'transactions', а не 'payments'

Решение: Исправлено в orders/admin.py
- obj.payments → obj.transactions (2 места)
- Админка PaymentMethod теперь работает корректно

Для тенанта buba:
- Создан скрипт add_payment_methods_to_buba.py
- Добавлен недостающий способ оплаты 'С баланса счёта'

Изменённые файлы:
- myproject/tenants/admin.py - вызов команды вместо дублирования
- myproject/orders/admin.py - исправлено на transactions
- add_payment_methods_to_buba.py - скрипт для существующих тенантов
This commit is contained in:
2025-12-01 01:22:40 +03:00
parent 293e8640ef
commit 7188b11f65
3 changed files with 48 additions and 46 deletions

View File

@@ -0,0 +1,40 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Скрипт для добавления способов оплаты в тенант buba
"""
import os
import sys
import django
# Добавляем путь к проекту
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'myproject'))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
django.setup()
from django_tenants.utils import schema_context
from django.core.management import call_command
print("=" * 70)
print("Добавление способов оплаты в тенант 'buba'")
print("=" * 70)
# Переключаемся на схему buba и создаём способы оплаты
with schema_context('buba'):
print("\n1. Создание способов оплаты...")
call_command('create_payment_methods')
# Проверяем что создалось
from orders.models import PaymentMethod
methods = PaymentMethod.objects.all().order_by('order')
print(f"\n2. Проверка созданных способов оплаты:")
print(f" Всего: {methods.count()}")
for method in methods:
status = "" if method.is_active else ""
print(f" {status} [{method.order}] {method.name} ({method.code})")
print("\n" + "=" * 70)
print("✓ Готово!")
print("=" * 70)

View File

@@ -441,7 +441,7 @@ class PaymentMethodAdmin(admin.ModelAdmin):
def payments_count(self, obj): def payments_count(self, obj):
"""Количество платежей этим способом""" """Количество платежей этим способом"""
count = obj.payments.count() count = obj.transactions.count()
if count == 0: if count == 0:
return format_html('<span style="color: #999;">{}</span>', count) return format_html('<span style="color: #999;">{}</span>', count)
return format_html('<span style="font-weight: bold;">{}</span>', count) return format_html('<span style="font-weight: bold;">{}</span>', count)
@@ -450,7 +450,7 @@ class PaymentMethodAdmin(admin.ModelAdmin):
def has_delete_permission(self, request, obj=None): def has_delete_permission(self, request, obj=None):
"""Запрещаем удаление используемых способов оплаты""" """Запрещаем удаление используемых способов оплаты"""
if obj: if obj:
# Разрешаем удаление только если нет связанных платежей # Разрешаем удаление только если нет связанных транзакций
if obj.payments.exists(): if obj.transactions.exists():
return False return False
return super().has_delete_permission(request, obj) return super().has_delete_permission(request, obj)

View File

@@ -312,51 +312,13 @@ class TenantRegistrationAdmin(admin.ModelAdmin):
# Создаем системные способы оплаты # Создаем системные способы оплаты
logger.info(f"Создание системных способов оплаты для тенанта: {client.id}") logger.info(f"Создание системных способов оплаты для тенанта: {client.id}")
from orders.models import PaymentMethod from django.core.management import call_command
try: try:
payment_methods = [ # Вызываем команду создания способов оплаты
{ # Это единственный источник истины для списка способов оплаты
'code': 'cash', call_command('create_payment_methods')
'name': 'Наличными', logger.info("Системные способы оплаты успешно созданы")
'description': 'Оплата наличными деньгами',
'is_system': True,
'order': 1
},
{
'code': 'card',
'name': 'Картой',
'description': 'Оплата банковской картой',
'is_system': True,
'order': 2
},
{
'code': 'online',
'name': 'Онлайн',
'description': 'Онлайн оплата через платежную систему',
'is_system': True,
'order': 3
},
{
'code': 'legal_entity',
'name': 'Безнал от ЮРЛИЦ',
'description': 'Безналичный расчёт от юридических лиц',
'is_system': True,
'order': 4
},
]
created_count = 0
for method_data in payment_methods:
method, created = PaymentMethod.objects.get_or_create(
code=method_data['code'],
defaults=method_data
)
if created:
created_count += 1
logger.info(f"Создан способ оплаты: {method.name}")
logger.info(f"Системные способы оплаты успешно созданы: {created_count} новых")
except Exception as e: except Exception as e:
logger.error(f"Ошибка при создании способов оплаты: {e}", exc_info=True) logger.error(f"Ошибка при создании способов оплаты: {e}", exc_info=True)
# Не прерываем процесс, т.к. это не критично # Не прерываем процесс, т.к. это не критично