from background_task import background from django.conf import settings from celery import shared_task from django.core.mail import send_mail from django.template.loader import render_to_string from django.utils.html import strip_tags from django.contrib.auth import get_user_model import logging logger = logging.getLogger(__name__) User = get_user_model() @background(schedule=0) def send_order_notification_background(order_id): """Асинхронная отправка уведомлений о заказе через background-tasks.""" from .utils.email_notifications import send_order_notification from products.models import Order try: order = Order.objects.select_related('product', 'configuration').get(id=order_id) success = send_order_notification(order) if success: order.notification_sent = True order.save(update_fields=['notification_sent']) return success except Order.DoesNotExist: logger.error(f"Order #{order_id} not found") return False @background(schedule=0) def send_multiple_order_notifications_background(order_ids): """Отправка уведомлений для нескольких заказов.""" from .utils.email_notifications import send_multiple_order_notifications from products.models import Order orders = Order.objects.filter(id__in=order_ids) return send_multiple_order_notifications(orders) try: from celery import shared_task except ImportError: shared_task = None if shared_task is not None: @shared_task def send_order_notification_celery(order_id): from .utils.email_notifications import send_order_notification from products.models import Order try: order = Order.objects.select_related('product', 'configuration').get(id=order_id) success = send_order_notification(order) if success: order.notification_sent = True order.save(update_fields=['notification_sent']) return success except Order.DoesNotExist: return False @shared_task def send_multiple_order_notifications_celery(order_ids): from .utils.email_notifications import send_multiple_order_notifications from products.models import Order orders = Order.objects.filter(id__in=order_ids) return send_multiple_order_notifications(orders) @shared_task def send_new_article_notification(article_id): """Отправка уведомлений подписчикам о новой статье.""" from blog.models import Article from programmer.models import Profile try: article = Article.objects.select_related('category', 'author').get(id=article_id, is_published=True) except Article.DoesNotExist: logger.error(f"Article #{article_id} not found or not published") return # Получаем email-адреса пользователей, подписанных на новые статьи profiles = Profile.objects.filter(notify_new_articles=True, user__is_active=True) emails = [p.user.email for p in profiles if p.user.email] if not emails: logger.info(f"No subscribers for new articles, skipping notification for article #{article_id}") return subject = f'📰 Новая статья: {article.title}' context = { 'article': article, 'site_url': settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else 'localhost', 'site_name': 'С.Н.А. Технологии', } html_message = render_to_string('emails/new_article_notification.html', context) plain_message = strip_tags(html_message) try: send_mail( subject=subject, message=plain_message, from_email=settings.DEFAULT_FROM_EMAIL, recipient_list=emails, html_message=html_message, fail_silently=False, ) logger.info(f"New article notification sent to {len(emails)} subscribers for article #{article_id}") except Exception as e: logger.error(f"Failed to send new article notification for article #{article_id}: {e}") @shared_task def send_new_product_notification(product_id): """Отправка уведомлений подписчикам о новом продукте.""" from products.models import Product from programmer.models import Profile try: product = Product.objects.select_related('category').get(id=product_id, is_published=True) except Product.DoesNotExist: logger.error(f"Product #{product_id} not found or not published") return profiles = Profile.objects.filter(notify_new_products=True, user__is_active=True) emails = [p.user.email for p in profiles if p.user.email] if not emails: logger.info(f"No subscribers for new products, skipping notification for product #{product_id}") return subject = f'🛒 Новый продукт: {product.title}' context = { 'product': product, 'site_url': settings.ALLOWED_HOSTS[0] if settings.ALLOWED_HOSTS else 'localhost', 'site_name': 'С.Н.А. Технологии', } html_message = render_to_string('emails/new_product_notification.html', context) plain_message = strip_tags(html_message) try: send_mail( subject=subject, message=plain_message, from_email=settings.DEFAULT_FROM_EMAIL, recipient_list=emails, html_message=html_message, fail_silently=False, ) logger.info(f"New product notification sent to {len(emails)} subscribers for product #{product_id}") except Exception as e: logger.error(f"Failed to send new product notification for product #{product_id}: {e}")