Рефакторинг: вынос логики онбординга тенанта в сервисный слой

Создан TenantOnboardingService как единый источник истины для:
- Активации заявки на регистрацию тенанта
- Создания Client, Domain, Subscription
- Инициализации системных данных (Customer, статусы, способы оплаты, склад, витрина)

Новые сервисы:
- TenantOnboardingService (tenants/services/onboarding.py)
- WarehouseService (inventory/services/warehouse_service.py)
- ShowcaseService (inventory/services/showcase_service.py)
- PaymentMethodService (orders/services/payment_method_service.py)

Рефакторинг:
- admin.py: 220 строк → 5 строк (делегирование сервису)
- init_tenant_data.py: 259 строк → 68 строк
- activate_registration.py: использует сервис
- Тесты обновлены для вызова сервиса напрямую

При создании тенанта автоматически создаются склад и витрина по умолчанию.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-30 14:52:55 +03:00
parent 658cd59511
commit b59ad725cb
13 changed files with 679 additions and 477 deletions

View File

@@ -0,0 +1,90 @@
# -*- coding: utf-8 -*-
"""
Сервис для работы со способами оплаты.
"""
from orders.models import PaymentMethod
class PaymentMethodService:
"""Сервис управления способами оплаты"""
# Системные способы оплаты
DEFAULT_METHODS = [
{
'code': 'account_balance',
'name': 'С баланса счёта',
'description': 'Оплата из кошелька клиента',
'is_system': True,
'order': 0
},
{
'code': 'cash',
'name': 'Наличными',
'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
},
]
@classmethod
def get_by_code(cls, code: str) -> PaymentMethod | None:
"""
Получить способ оплаты по коду.
Args:
code: Код способа оплаты
Returns:
PaymentMethod или None
"""
return PaymentMethod.objects.filter(code=code).first()
@classmethod
def create_default_methods(cls) -> list[tuple[PaymentMethod, bool]]:
"""
Создать системные способы оплаты.
Returns:
Список кортежей (PaymentMethod, created)
"""
results = []
for method_data in cls.DEFAULT_METHODS:
method, created = PaymentMethod.objects.get_or_create(
code=method_data['code'],
defaults=method_data
)
results.append((method, created))
return results
@classmethod
def reset_default_methods(cls) -> list[PaymentMethod]:
"""
Удалить и пересоздать системные способы оплаты.
Returns:
Список созданных PaymentMethod
"""
PaymentMethod.objects.filter(is_system=True).delete()
results = cls.create_default_methods()
return [method for method, _ in results]