def _dispatch_order_messages(self, order_number, order, email=None): et = CommunicationEventType.objects.create(code="ORDER_PLACED", name="Order Placed", category=CommunicationEventType.ORDER_RELATED) messages = et.get_messages({ 'order': order, 'lines': order.lines.all() }) self.assertIn(order_number, messages['body']) self.assertIn(order_number, messages['html']) dispatcher = Dispatcher() dispatcher.dispatch_order_messages(order, messages, et) self.assertEqual(CommunicationEvent.objects.filter(order=order, event_type=et).count(), 1) self.assertEqual(len(mail.outbox), 1) message = mail.outbox[0] self.assertIn(order_number, message.body) # test sending messages to emails without account and text body messages['body'] = '' dispatcher.dispatch_direct_messages(email, messages) self.assertEqual(len(mail.outbox), 2)
def test_sending_a_order_related_messages(self): email = '*****@*****.**' user = User.objects.create_user('testuser', email, 'somesimplepassword') order_number = '12345' order = create_order(number=order_number, user=user) et = CommunicationEventType.objects.create(code="ORDER_PLACED", name="Order Placed", category="Order related") messages = et.get_messages({ 'order': order, 'lines': order.lines.all() }) self.assertIn(order_number, messages['body']) self.assertIn(order_number, messages['html']) dispatcher = Dispatcher() dispatcher.dispatch_order_messages(order, messages, et) self.assertEqual(len(mail.outbox), 1) message = mail.outbox[0] self.assertIn(order_number, message.body) # test sending messages to emails without account and text body messages['body'] = '' dispatcher.dispatch_direct_messages(email, messages) self.assertEqual(len(mail.outbox), 2)
def test_dispatcher_uses_email_connection(self): connection = mail.get_connection() disp = Dispatcher(mail_connection=connection) disp.dispatch_direct_messages('*****@*****.**', { 'subject': 'Test', 'body': 'This is a test.', 'html': '', }) self.assertEqual(len(mail.outbox), 1)
def send_product_alerts(product): # noqa C901 too complex """ Check for notifications for this product and send email to users if the product is back in stock. Add a little 'hurry' note if the amount of in-stock items is less then the number of notifications. """ stockrecords = product.stockrecords.all() num_stockrecords = len(stockrecords) if not num_stockrecords: return logger.info("Sending alerts for '%s'", product) alerts = ProductAlert.objects.filter( product_id__in=(product.id, product.parent_id), status=ProductAlert.ACTIVE, ) # Determine 'hurry mode' if num_stockrecords == 1: num_in_stock = stockrecords[0].num_in_stock else: result = stockrecords.aggregate(max_in_stock=Max('num_in_stock')) num_in_stock = result['max_in_stock'] # hurry_mode is false if num_in_stock is None hurry_mode = num_in_stock is not None and alerts.count() > num_in_stock # For backwards compability, we check if the old (non-communication-event) # templates exist, and use them if they do. # This will be removed in Oscar 2.0 try: email_subject_tpl = loader.get_template('customer/alerts/emails/' 'alert_subject.txt') email_body_tpl = loader.get_template('customer/alerts/emails/' 'alert_body.txt') use_deprecated_templates = True warnings.warn( "Product alert notifications now use the CommunicationEvent. " "Move '{}' to '{}', and '{}' to '{}'".format( 'customer/alerts/emails/alert_subject.txt', 'customer/emails/commtype_product_alert_subject.txt', 'customer/alerts/emails/alert_body.txt', 'customer/emails/commtype_product_alert_body.txt', ), category=RemovedInOscar20Warning, stacklevel=2) except TemplateDoesNotExist: code = 'PRODUCT_ALERT' try: event_type = CommunicationEventType.objects.get(code=code) except CommunicationEventType.DoesNotExist: event_type = CommunicationEventType.objects.model(code=code) use_deprecated_templates = False messages_to_send = [] user_messages_to_send = [] num_notifications = 0 selector = Selector() for alert in alerts: # Check if the product is available to this user strategy = selector.strategy(user=alert.user) data = strategy.fetch_for_product(product) if not data.availability.is_available_to_buy: continue ctx = { 'alert': alert, 'site': Site.objects.get_current(), 'hurry': hurry_mode, } if alert.user: # Send a site notification num_notifications += 1 subj_tpl = loader.get_template( 'customer/alerts/message_subject.html') message_tpl = loader.get_template('customer/alerts/message.html') services.notify_user(alert.user, subj_tpl.render(ctx).strip(), body=message_tpl.render(ctx).strip()) # Build message and add to list if use_deprecated_templates: messages = { 'subject': email_subject_tpl.render(ctx).strip(), 'body': email_body_tpl.render(ctx), 'html': '', 'sms': '', } else: messages = event_type.get_messages(ctx) if messages and messages['body']: if alert.user: user_messages_to_send.append((alert.user, messages)) else: messages_to_send.append((alert.get_email_address(), messages)) alert.close() # Send all messages using one SMTP connection to avoid opening lots of them if messages_to_send or user_messages_to_send: connection = mail.get_connection() connection.open() disp = Dispatcher(mail_connection=connection) for message in messages_to_send: disp.dispatch_direct_messages(*message) for message in user_messages_to_send: disp.dispatch_user_messages(*message) connection.close() logger.info("Sent %d notifications and %d messages", num_notifications, len(messages_to_send) + len(user_messages_to_send))
def send_product_alerts(product): # noqa C901 too complex """ Check for notifications for this product and send email to users if the product is back in stock. Add a little 'hurry' note if the amount of in-stock items is less then the number of notifications. """ stockrecords = product.stockrecords.all() num_stockrecords = len(stockrecords) if not num_stockrecords: return logger.info("Sending alerts for '%s'", product) alerts = ProductAlert.objects.filter( product_id__in=(product.id, product.parent_id), status=ProductAlert.ACTIVE, ) # Determine 'hurry mode' if num_stockrecords == 1: num_in_stock = stockrecords[0].num_in_stock else: result = stockrecords.aggregate(max_in_stock=Max('num_in_stock')) num_in_stock = result['max_in_stock'] # hurry_mode is false if num_in_stock is None hurry_mode = num_in_stock is not None and alerts.count() > num_in_stock # For backwards compability, we check if the old (non-communication-event) # templates exist, and use them if they do. # This will be removed in Oscar 2.0 try: email_subject_tpl = loader.get_template('customer/alerts/emails/' 'alert_subject.txt') email_body_tpl = loader.get_template('customer/alerts/emails/' 'alert_body.txt') use_deprecated_templates = True warnings.warn( "Product alert notifications now use the CommunicationEvent. " "Move '{}' to '{}', and '{}' to '{}'".format( 'customer/alerts/emails/alert_subject.txt', 'customer/emails/commtype_product_alert_subject.txt', 'customer/alerts/emails/alert_body.txt', 'customer/emails/commtype_product_alert_body.txt', ), category=RemovedInOscar20Warning, stacklevel=2 ) except TemplateDoesNotExist: code = 'PRODUCT_ALERT' try: event_type = CommunicationEventType.objects.get(code=code) except CommunicationEventType.DoesNotExist: event_type = CommunicationEventType.objects.model(code=code) use_deprecated_templates = False messages_to_send = [] user_messages_to_send = [] num_notifications = 0 selector = Selector() for alert in alerts: # Check if the product is available to this user strategy = selector.strategy(user=alert.user) data = strategy.fetch_for_product(product) if not data.availability.is_available_to_buy: continue ctx = { 'alert': alert, 'site': Site.objects.get_current(), 'hurry': hurry_mode, } if alert.user: # Send a site notification num_notifications += 1 subj_tpl = loader.get_template('customer/alerts/message_subject.html') message_tpl = loader.get_template('customer/alerts/message.html') services.notify_user( alert.user, subj_tpl.render(ctx).strip(), body=message_tpl.render(ctx).strip() ) # Build message and add to list if use_deprecated_templates: messages = { 'subject': email_subject_tpl.render(ctx).strip(), 'body': email_body_tpl.render(ctx), 'html': '', 'sms': '', } else: messages = event_type.get_messages(ctx) if messages and messages['body']: if alert.user: user_messages_to_send.append( (alert.user, messages) ) else: messages_to_send.append( (alert.get_email_address(), messages) ) alert.close() # Send all messages using one SMTP connection to avoid opening lots of them if messages_to_send or user_messages_to_send: connection = mail.get_connection() connection.open() disp = Dispatcher(mail_connection=connection) for message in messages_to_send: disp.dispatch_direct_messages(*message) for message in user_messages_to_send: disp.dispatch_user_messages(*message) connection.close() logger.info("Sent %d notifications and %d messages", num_notifications, len(messages_to_send) + len(user_messages_to_send))