You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

utils.py 3.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import logging
  2. from django.core import mail
  3. from django.conf import settings
  4. from django.template import loader, Context
  5. from django.contrib.sites.models import Site
  6. from django.db.models import get_model, Max
  7. from oscar.apps.customer.notifications import services
  8. from oscar.core.loading import get_class
  9. ProductAlert = get_model('customer', 'ProductAlert')
  10. Product = get_model('catalogue', 'Product')
  11. Selector = get_class('partner.strategy', 'Selector')
  12. logger = logging.getLogger(__file__)
  13. def send_alerts():
  14. """
  15. Send out product alerts
  16. """
  17. products = Product.objects.filter(
  18. productalert__status=ProductAlert.ACTIVE
  19. ).distinct()
  20. logger.info("Found %d products with active alerts", products.count())
  21. for product in products:
  22. send_product_alerts(product)
  23. def send_alert_confirmation(alert):
  24. """
  25. Send an alert confirmation email.
  26. """
  27. ctx = Context({
  28. 'alert': alert,
  29. 'site': Site.objects.get_current(),
  30. })
  31. subject_tpl = loader.get_template('customer/alerts/emails/confirmation_subject.txt')
  32. body_tpl = loader.get_template('customer/alerts/emails/confirmation_body.txt')
  33. mail.send_mail(
  34. subject_tpl.render(ctx).strip(),
  35. body_tpl.render(ctx),
  36. settings.OSCAR_FROM_EMAIL,
  37. [alert.email],
  38. )
  39. def send_product_alerts(product):
  40. """
  41. Check for notifications for this product and send email to users
  42. if the product is back in stock. Add a little 'hurry' note if the
  43. amount of in-stock items is less then the number of notifications.
  44. """
  45. stockrecords = product.stockrecords.all()
  46. num_stockrecords = len(stockrecords)
  47. if not num_stockrecords:
  48. return
  49. logger.info("Sending alerts for '%s'", product)
  50. alerts = ProductAlert.objects.filter(
  51. product=product,
  52. status=ProductAlert.ACTIVE,
  53. )
  54. # Determine 'hurry mode'
  55. num_alerts = alerts.count()
  56. if num_stockrecords == 1:
  57. num_in_stock = stockrecords[0].num_in_stock
  58. hurry_mode = num_alerts < num_in_stock
  59. else:
  60. result = stockrecords.aggregate(max_in_stock=Max('num_in_stock'))
  61. hurry_mode = num_alerts < result['max_in_stock']
  62. # Load templates
  63. message_tpl = loader.get_template('customer/alerts/message.html')
  64. email_subject_tpl = loader.get_template('customer/alerts/emails/alert_subject.txt')
  65. email_body_tpl = loader.get_template('customer/alerts/emails/alert_body.txt')
  66. emails = []
  67. num_notifications = 0
  68. selector = Selector()
  69. for alert in alerts:
  70. # Check if the product is available to this user
  71. strategy = selector.strategy(user=alert.user)
  72. data = strategy.fetch(product)
  73. if not data.availability.is_available_to_buy:
  74. continue
  75. ctx = Context({
  76. 'alert': alert,
  77. 'site': Site.objects.get_current(),
  78. 'hurry': hurry_mode,
  79. })
  80. if alert.user:
  81. # Send a site notification
  82. num_notifications += 1
  83. services.notify_user(alert.user, message_tpl.render(ctx))
  84. # Build email and add to list
  85. emails.append(
  86. mail.EmailMessage(
  87. email_subject_tpl.render(ctx).strip(),
  88. email_body_tpl.render(ctx),
  89. settings.OSCAR_FROM_EMAIL,
  90. [alert.get_email_address()],
  91. )
  92. )
  93. alert.close()
  94. # Send all emails in one go to prevent multiple SMTP
  95. # connections to be opened
  96. if emails:
  97. connection = mail.get_connection()
  98. connection.open()
  99. connection.send_messages(emails)
  100. connection.close()
  101. logger.info("Sent %d notifications and %d emails", num_notifications, len(emails))