Files
octopus/myproject/TENANT_REGISTRATION_GUIDE.md
Andrey Smakotin 097d4ea304 feat: Добавить систему мультитенантности с регистрацией магазинов
Реализована полноценная система мультитенантности на базе django-tenants.
Каждый магазин получает изолированную схему БД и поддомен.

Основные компоненты:

Django-tenants интеграция:
- Модели Client (тенант) и Domain в приложении tenants/
- Разделение на SHARED_APPS и TENANT_APPS
- Public schema для общей админки
- Tenant schemas для изолированных данных магазинов

Система регистрации магазинов:
- Публичная форма регистрации на /register/
- Модель TenantRegistration для заявок со статусами (pending/approved/rejected)
- Валидация schema_name (латиница, 3-63 символа, уникальность)
- Проверка на зарезервированные имена (admin, api, www и т.д.)
- Админ-панель для модерации заявок с кнопками активации/отклонения

Система подписок:
- Модель Subscription с планами (триал 90 дней, месяц, квартал, год)
- Автоматическое создание триальной подписки при активации
- Методы is_expired() и days_left() для проверки статуса
- Цветовая индикация в админке (зеленый/оранжевый/красный)

Приложения:
- tenants/ - управление тенантами, регистрация, подписки
- shops/ - точки магазинов/самовывоза (tenant app)
- Обновлены миграции для всех приложений

Утилиты:
- switch_to_tenant.py - переключение между схемами тенантов
- Обновлены image_processor и image_service

Конфигурация:
- urls_public.py - роуты для public schema (админка + регистрация)
- urls.py - роуты для tenant schemas (магазины)
- requirements.txt - добавлены django-tenants, django-environ, phonenumber-field

Документация:
- DJANGO_TENANTS_SETUP.md - настройка мультитенантности
- TENANT_REGISTRATION_GUIDE.md - руководство по регистрации
- QUICK_START.md - быстрый старт
- START_HERE.md - общая документация

Использование:
1. Пользователь: http://localhost:8000/register/ → заполняет форму
2. Админ: http://localhost:8000/admin/ → активирует заявку
3. Результат: http://{schema_name}.localhost:8000/ - готовый магазин

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-27 19:13:10 +03:00

12 KiB
Raw Blame History

Руководство по системе регистрации тенантов

Что реализовано

Создана полноценная система регистрации новых магазинов (тенантов) с ручной модерацией администратором.

1. Модели данных (tenants/models.py)

Client (обновлена)

  • Добавлен db_index для поля name (ускорение поиска)
  • Изменено поле phone на PhoneNumberField (поддержка РБ/РФ форматов)
  • Обновлен help_text для owner_email (один email может быть у нескольких магазинов для супер-админа)

TenantRegistration (новая)

Модель заявки на регистрацию:

  • shop_name - название магазина
  • schema_name - желаемый поддомен (с валидацией regex)
  • owner_email, owner_name, phone - контактные данные
  • status - статус заявки: pending/approved/rejected
  • processed_at, processed_by - данные обработки
  • tenant - ссылка на созданный тенант после активации

Subscription (новая)

Модель подписки:

  • plan - тип плана (триал 90 дней, месяц, квартал, год)
  • started_at, expires_at - период действия
  • is_active, auto_renew - статус и автопродление
  • Методы: is_expired(), days_left(), create_trial(client)

RESERVED_SCHEMA_NAMES

Список зарезервированных поддоменов (admin, api, www, и т.д.)


2. Админ-панель (tenants/admin.py)

ClientAdmin (обновлена)

  • Добавлена колонка subscription_status с цветовой индикацией
  • Разрешено редактирование schema_name при создании нового тенанта
  • Запрещено удаление тенантов через админку (для безопасности)

TenantRegistrationAdmin (новая)

Функции:

  • Список заявок с фильтрами по статусу и дате
  • Кнопки "Активировать" / "Отклонить" для каждой заявки
  • Массовые действия для обработки нескольких заявок
  • При активации:
    • Создается тенант (Client)
    • Создается домен (например: myshop.localhost)
    • Создается триальная подписка на 90 дней
    • Заявка помечается как "Одобрено"

SubscriptionAdmin (новая)

  • Просмотр и управление подписками
  • Цветовая индикация истекающих подписок (красный < 0 дней, оранжевый < 7 дней)

3. Публичная форма регистрации

tenants/forms.py - TenantRegistrationForm

Валидация:

  • schema_name: приведение к lowercase, проверка длины (3-63 символа), проверка на зарезервированные имена, проверка уникальности
  • owner_email: проверка на дубликаты pending заявок

tenants/views.py

  • TenantRegistrationView - форма регистрации
  • RegistrationSuccessView - страница благодарности

HTML шаблоны


Как использовать

Для пользователей (владельцев будущих магазинов)

  1. Откройте публичную форму регистрации:

    http://localhost:8000/register/
    
  2. Заполните форму:

    • Название магазина
    • Желаемый поддомен (только латиница, цифры, дефис)
    • Ваше имя
    • Email
    • Телефон
  3. После отправки увидите страницу благодарности

  4. Ожидайте активации администратором (в течение 24 часов)


Для администратора

  1. Войдите в админ-панель:

    http://localhost:8000/admin/
    
  2. Перейдите в раздел "Заявки на регистрацию"

  3. Увидите список заявок со статусом "Ожидает проверки"

  4. Для активации заявки:

    • Кликните на кнопку "Активировать" справа от заявки
    • ИЛИ выберите несколько заявок и используйте массовое действие
  5. Что происходит при активации:

    • Создается новый тенант (Client) с указанным schema_name
    • Создается домен {schema_name}.localhost
    • Создается триальная подписка на 90 дней
    • Заявка помечается как "Одобрено"
    • В поле "Созданный тенант" появляется ссылка на тенант
  6. Для отклонения:

    • Кликните "Отклонить"
    • Заявка помечается как "Отклонено"

Доступ к магазинам

После активации магазин доступен по адресу:

http://{schema_name}.localhost:8000/

Например, для магазина с schema_name=myshop:

http://myshop.localhost:8000/

Управление подписками

Просмотр подписок

  1. Админ-панель → "Подписки"
  2. Видны все подписки с информацией:
    • Тип плана
    • Дата начала/окончания
    • Осталось дней
    • Истекла или нет

Продление подписки

  1. Откройте подписку тенанта
  2. Измените:
    • expires_at - новую дату окончания
    • plan - новый тип плана (если меняется)
  3. Сохраните

Типы планов

  • Триальный (90 дней) - автоматически при создании
  • Месячный - 30 дней
  • Квартальный - 90 дней
  • Годовой - 365 дней

Технические детали

Валидация schema_name

Regex: ^[a-z0-9](?:[a-z0-9\-]{0,61}[a-z0-9])?$

Правила:

  • Только латинские буквы в нижнем регистре
  • Цифры и дефис разрешены
  • Длина 3-63 символа
  • Не может начинаться или заканчиваться дефисом
  • Не совпадает с зарезервированными именами

Зарезервированные имена

RESERVED_SCHEMA_NAMES = [
    'public', 'admin', 'api', 'www', 'mail', 'ftp', 'smtp',
    'static', 'media', 'assets', 'cdn', 'app', 'web',
    'billing', 'register', 'login', 'logout', 'dashboard',
    'test', 'dev', 'staging', 'production', 'demo'
]

Email для супер-админа

Один email может использоваться для нескольких магазинов (полезно для вас как супер-админа для входа в разные тенанты).

Для обычных пользователей форма проверяет наличие pending заявок с таким же email.


Что дальше (рекомендации)

1. Email-уведомления

Добавить отправку писем:

  • Пользователю при активации заявки
  • Пользователю при истечении подписки (за 7 дней, за 1 день)
  • Админу при новой заявке

2. Биллинг

Создать страницу /billing/ где владелец магазина может:

  • Посмотреть текущую подписку
  • Продлить подписку
  • Оплатить через платежную систему

3. Middleware для is_active

Если нужна жесткая блокировка доступа к деактивированным магазинам, создать middleware:

# tenants/middleware.py
class TenantStatusMiddleware:
    def __call__(self, request):
        if hasattr(request, 'tenant'):
            if not request.tenant.is_active:
                # Показать страницу "Магазин заблокирован"
                pass

            sub = request.tenant.subscription
            if sub.is_expired():
                # Редирект на /billing/renew/
                pass

        return self.get_response(request)

4. Автоматическая очистка

Создать команду для удаления старых отклоненных заявок:

python manage.py cleanup_old_registrations --days=30

Структура файлов

myproject/tenants/
├── models.py                   # Модели Client, TenantRegistration, Subscription
├── admin.py                    # Админ-панель с функционалом активации
├── forms.py                    # Форма регистрации с валидацией
├── views.py                    # Views для публичной регистрации
├── urls.py                     # Роуты /register/ и /register/success/
└── templates/tenants/
    ├── base.html              # Базовый шаблон
    ├── registration_form.html # Форма регистрации
    └── registration_success.html # Страница благодарности

Тестирование

1. Регистрация магазина

# Запустите сервер
python manage.py runserver

# Откройте браузер
http://localhost:8000/register/

# Заполните форму:
Название: Тестовый магазин
Поддомен: testshop
Имя: Иван Иванов
Email: test@example.com
Телефон: +375291234567

# Отправьте заявку

2. Активация через админку

# Войдите в админку
http://localhost:8000/admin/

# Логин/пароль супер-админа
# Перейдите в "Заявки на регистрацию"
# Нажмите "Активировать" напротив заявки

3. Проверка созданного магазина

# Откройте браузер
http://testshop.localhost:8000/

# Должна открыться страница магазина

Поддержка

При возникновении проблем проверьте:

  1. Миграции применены: python manage.py migrate_schemas --shared
  2. В settings.py приложение tenants в SHARED_APPS
  3. В urls_public.py подключены роуты tenants
  4. Виртуальное окружение активировано
  5. phonenumber_field установлен

Система готова к использованию!

Теперь вы можете:

  • Принимать заявки на регистрацию
  • Модерировать их через админку
  • Управлять подписками
  • Контролировать доступ к магазинам