- Добавлена специальная обработка витринных комплектов в сигнале update_reservation_on_item_change: * При создании OrderItem с витринным комплектом привязываются существующие витринные резервы компонентов * Не создаются новые резервы на уровне комплекта - Исправлена логика создания Sale для комплектов в сигнале create_sale_on_order_completion: * Для комплектов (витринных и обычных) создаются Sale для каждого компонента через резервы * Используется FIFO-списание для компонентов * Предотвращена ошибка передачи ProductKit в поле Reservation.product Fixes: Cannot assign ProductKit to Reservation.product field Fixes: Не удалось создать Sale для заказа с витринным комплектом
105 lines
5.2 KiB
Python
105 lines
5.2 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""
|
||
Сервисы для работы с тенантами
|
||
"""
|
||
import uuid
|
||
from django.utils import timezone
|
||
from django.conf import settings
|
||
|
||
|
||
def send_password_setup_email(registration):
|
||
"""
|
||
Отправить email с ссылкой для установки пароля одобренному владельцу тенанта.
|
||
|
||
Args:
|
||
registration: экземпляр TenantRegistration
|
||
|
||
Returns:
|
||
bool: True если письмо успешно "отправлено" (выведено в консоль)
|
||
"""
|
||
# Генерировать токен
|
||
registration.password_setup_token = uuid.uuid4()
|
||
registration.password_setup_token_created_at = timezone.now()
|
||
|
||
# Построить URL динамически в зависимости от окружения
|
||
# Локально: http://localhost:8000
|
||
# Продакшен: https://mix.smaa.by
|
||
protocol = 'https' if settings.USE_HTTPS else 'http'
|
||
domain_base = settings.TENANT_DOMAIN_BASE # localhost:8000 или mix.smaa.by
|
||
|
||
# URL для установки пароля (главный домен)
|
||
setup_url = f"{protocol}://{domain_base}/accounts/setup-password/{registration.password_setup_token}/"
|
||
|
||
# URL тенанта (поддомен)
|
||
tenant_url = f"{protocol}://{registration.schema_name}.{domain_base}/"
|
||
|
||
# Составить письмо
|
||
subject = f"Ваш магазин {registration.shop_name} активирован!"
|
||
|
||
message = f"""
|
||
╔══════════════════════════════════════════════════════════════════╗
|
||
║ ВАША ЗАЯВКА НА РЕГИСТРАЦИЮ МАГАЗИНА ОДОБРЕНА! ║
|
||
╚══════════════════════════════════════════════════════════════════╝
|
||
|
||
Здравствуйте, {registration.owner_name}!
|
||
|
||
Отличные новости! Ваша заявка на регистрацию магазина "{registration.shop_name}"
|
||
была одобрена администратором.
|
||
|
||
╔══════════════════════════════════════════════════════════════════╗
|
||
║ ДАННЫЕ ДЛЯ ВХОДА ║
|
||
╚══════════════════════════════════════════════════════════════════╝
|
||
|
||
📧 Email для входа: {registration.owner_email}
|
||
🏪 Ваш магазин доступен по адресу: {tenant_url}
|
||
|
||
╔══════════════════════════════════════════════════════════════════╗
|
||
║ УСТАНОВИТЕ ПАРОЛЬ (действительна 7 дней) ║
|
||
╚══════════════════════════════════════════════════════════════════╝
|
||
|
||
Для завершения настройки аккаунта, пожалуйста, установите пароль,
|
||
перейдя по следующей ссылке:
|
||
|
||
{setup_url}
|
||
|
||
⏰ Ссылка действительна в течение 7 дней.
|
||
|
||
╔══════════════════════════════════════════════════════════════════╗
|
||
║ ЧТО ДЕЛАТЬ ДАЛЬШЕ? ║
|
||
╚══════════════════════════════════════════════════════════════════╝
|
||
|
||
1. Нажмите на ссылку выше
|
||
2. Придумайте надежный пароль
|
||
3. Войдите в свой магазин и начните работу!
|
||
|
||
Если у вас возникли вопросы, свяжитесь с нами:
|
||
📧 support@inventory.by
|
||
📞 +375 29 123-45-67
|
||
|
||
С уважением,
|
||
Команда Inventory System
|
||
|
||
---
|
||
Если вы не подавали заявку на регистрацию, проигнорируйте это письмо.
|
||
"""
|
||
|
||
from_email = settings.DEFAULT_FROM_EMAIL
|
||
recipient_list = [registration.owner_email]
|
||
|
||
# Вывести в консоль с красивым форматированием
|
||
print("\n" + "="*70)
|
||
print("📧 ОТПРАВКА EMAIL (Console Backend)")
|
||
print("="*70)
|
||
print(f"Тема: {subject}")
|
||
print(f"От: {from_email}")
|
||
print(f"Кому: {recipient_list[0]}")
|
||
print("-"*70)
|
||
print(message)
|
||
print("="*70 + "\n")
|
||
|
||
# Обновить registration
|
||
registration.owner_notified_at = timezone.now()
|
||
registration.save()
|
||
|
||
return True
|