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.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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
  7. from oscar.apps.customer.notifications import services
  8. ProductAlert = get_model('customer', 'ProductAlert')
  9. Product = get_model('catalogue', 'Product')
  10. logger = logging.getLogger(__file__)
  11. def send_alerts():
  12. """
  13. Send out product alerts
  14. """
  15. products = Product.objects.filter(
  16. productalert__status=ProductAlert.ACTIVE
  17. ).distinct()
  18. logger.info("Found %d products with active alerts", products.count())
  19. for product in products:
  20. if product.is_available_to_buy:
  21. send_product_alerts(product)
  22. def send_alert_confirmation(alert):
  23. """
  24. Send an alert confirmation email.
  25. """
  26. ctx = Context({
  27. 'alert': alert,
  28. 'site': Site.objects.get_current(),
  29. })
  30. subject_tpl = loader.get_template('customer/alerts/emails/confirmation_subject.txt')
  31. body_tpl = loader.get_template('customer/alerts/emails/confirmation_body.txt')
  32. mail.send_mail(
  33. subject_tpl.render(ctx).strip(),
  34. body_tpl.render(ctx),
  35. settings.OSCAR_FROM_EMAIL,
  36. [alert.email],
  37. )
  38. def send_product_alerts(product):
  39. """
  40. Check for notifications for this product and send email to users
  41. if the product is back in stock. Add a little 'hurry' note if the
  42. amount of in-stock items is less then the number of notifications.
  43. """
  44. if not product.has_stockrecord:
  45. return
  46. num_in_stock = product.stockrecord.num_in_stock
  47. if num_in_stock == 0:
  48. return
  49. logger.info("Sending alerts for '%s'", product)
  50. alerts = ProductAlert.objects.filter(
  51. product=product,
  52. status=ProductAlert.ACTIVE,
  53. )
  54. hurry_mode = alerts.count() < product.stockrecord.num_in_stock
  55. # Load templates
  56. message_tpl = loader.get_template('customer/alerts/message.html')
  57. email_subject_tpl = loader.get_template('customer/alerts/emails/alert_subject.txt')
  58. email_body_tpl = loader.get_template('customer/alerts/emails/alert_body.txt')
  59. emails = []
  60. num_notifications = 0
  61. for alert in alerts:
  62. ctx = Context({
  63. 'alert': alert,
  64. 'site': Site.objects.get_current(),
  65. 'hurry': hurry_mode,
  66. })
  67. if alert.user:
  68. # Send a site notification
  69. num_notifications += 1
  70. services.notify_user(alert.user, message_tpl.render(ctx))
  71. # Build email and add to list
  72. emails.append(
  73. mail.EmailMessage(
  74. email_subject_tpl.render(ctx).strip(),
  75. email_body_tpl.render(ctx),
  76. settings.OSCAR_FROM_EMAIL,
  77. [alert.get_email_address()],
  78. )
  79. )
  80. alert.close()
  81. # Send all emails in one go to prevent multiple SMTP
  82. # connections to be opened
  83. connection = mail.get_connection()
  84. connection.send_messages(emails)
  85. connection.close()
  86. logger.info("Sent %d notifications and %d emails", num_notifications, len(emails))