# -*- coding: utf-8 -*- """ Management команда для ручной активации заявки на регистрацию тенанта. Использование: python manage.py activate_registration Пример: 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_name = f"{registration.schema_name}.localhost" 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")}' )) # Обновляем заявку 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', 'да']