Files
octopus/myproject/tenants/management/commands/activate_registration.py

153 lines
7.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
Management команда для ручной активации заявки на регистрацию тенанта.
Использование:
python manage.py activate_registration <schema_name>
Пример:
python manage.py activate_registration mixflowers
"""
from django.core.management.base import BaseCommand, CommandError
from django.db import transaction
from django.utils import timezone
from tenants.models import TenantRegistration, Client, Domain, Subscription
class Command(BaseCommand):
help = 'Активировать заявку на регистрацию тенанта вручную'
def add_arguments(self, parser):
parser.add_argument(
'schema_name',
type=str,
help='Schema name заявки для активации'
)
parser.add_argument(
'--force',
action='store_true',
help='Принудительная активация (пересоздать тенант если уже существует)'
)
def handle(self, *args, **options):
schema_name = options['schema_name']
force = options.get('force', False)
try:
# Ищем заявку
registration = TenantRegistration.objects.get(schema_name=schema_name)
except TenantRegistration.DoesNotExist:
raise CommandError(f'Заявка с schema_name "{schema_name}" не найдена')
self.stdout.write(f'Найдена заявка: {registration.shop_name} ({registration.schema_name})')
self.stdout.write(f'Статус: {registration.get_status_display()}')
self.stdout.write(f'Email: {registration.owner_email}')
self.stdout.write('')
# Проверяем статус
if registration.status == TenantRegistration.STATUS_APPROVED and not force:
self.stdout.write(self.style.WARNING('Эта заявка уже была одобрена!'))
if registration.tenant:
self.stdout.write(f'Связанный тенант: {registration.tenant.name} (ID: {registration.tenant.id})')
else:
self.stdout.write(self.style.WARNING('Но тенант не был создан. Используйте --force для пересоздания'))
if not self._confirm('Продолжить с --force?'):
return
force = True
# Проверяем существование тенанта
existing_client = Client.objects.filter(schema_name=schema_name).first()
if existing_client and not force:
raise CommandError(
f'Тенант с schema_name "{schema_name}" уже существует (ID: {existing_client.id}). '
'Используйте --force для пересоздания (ОПАСНО: удалит все данные!)'
)
# Активируем
self.stdout.write('')
self.stdout.write(self.style.WARNING('НАЧИНАЮ АКТИВАЦИЮ...'))
self.stdout.write('')
try:
with transaction.atomic():
# Если force - удаляем старый тенант
if force and existing_client:
self.stdout.write(self.style.WARNING(f'Удаление существующего тенанта {existing_client.id}...'))
# Удаляем подписку
try:
existing_client.subscription.delete()
except:
pass
# Удаляем домены
Domain.objects.filter(tenant=existing_client).delete()
# Удаляем тенант (это также удалит схему из PostgreSQL)
existing_client.delete()
self.stdout.write(self.style.SUCCESS('Старый тенант удален'))
# Создаем тенант
self.stdout.write(f'Создание тенанта: {registration.schema_name}')
client = Client.objects.create(
schema_name=registration.schema_name,
name=registration.shop_name,
owner_email=registration.owner_email,
owner_name=registration.owner_name,
phone=registration.phone,
is_active=True
)
self.stdout.write(self.style.SUCCESS(f'✓ Тенант создан (ID: {client.id})'))
# Создаем домен
domain_base = getattr(settings, 'TENANT_DOMAIN_BASE', 'localhost')
domain_name = f"{registration.schema_name}.{domain_base}"
self.stdout.write(f'Создание домена: {domain_name}')
domain = Domain.objects.create(
domain=domain_name,
tenant=client,
is_primary=True
)
self.stdout.write(self.style.SUCCESS(f'✓ Домен создан (ID: {domain.id})'))
# Создаем триальную подписку
self.stdout.write('Создание триальной подписки на 90 дней')
subscription = Subscription.create_trial(client)
self.stdout.write(self.style.SUCCESS(
f'✓ Подписка создана (ID: {subscription.id}), '
f'истекает: {subscription.expires_at.strftime("%Y-%m-%d")}'
))
# Инициализация системных данных
self.stdout.write('Инициализация системных данных...')
from django.core.management import call_command
call_command('init_tenant_data', schema=client.schema_name)
self.stdout.write(self.style.SUCCESS('✓ Системные данные созданы'))
# Обновляем заявку
registration.status = TenantRegistration.STATUS_APPROVED
registration.processed_at = timezone.now()
registration.processed_by = None # Активировано через команду
registration.tenant = client
registration.save()
self.stdout.write(self.style.SUCCESS('✓ Заявка обновлена'))
self.stdout.write('')
self.stdout.write(self.style.SUCCESS('=' * 60))
self.stdout.write(self.style.SUCCESS('АКТИВАЦИЯ ЗАВЕРШЕНА УСПЕШНО!'))
self.stdout.write(self.style.SUCCESS('=' * 60))
self.stdout.write('')
self.stdout.write(f'Магазин: {client.name}')
self.stdout.write(f'Schema: {client.schema_name}')
self.stdout.write(f'Домен: http://{domain_name}:8000/')
self.stdout.write(f'Подписка до: {subscription.expires_at.strftime("%Y-%m-%d")} ({subscription.days_left()} дней)')
self.stdout.write('')
except Exception as e:
self.stdout.write(self.style.ERROR(f'ОШИБКА: {str(e)}'))
import traceback
self.stdout.write(traceback.format_exc())
raise CommandError('Активация не удалась')
def _confirm(self, question):
"""Запрос подтверждения у пользователя"""
answer = input(f'{question} (yes/no): ')
return answer.lower() in ['yes', 'y', 'да']