def send_product_alerts(product): """ 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. """ if not product.has_stockrecord: return num_in_stock = product.stockrecord.num_in_stock if num_in_stock == 0: return logger.info("Sending alerts for '%s'", product) alerts = ProductAlert.objects.filter( product=product, status=ProductAlert.ACTIVE, ) hurry_mode = alerts.count() < product.stockrecord.num_in_stock # Load templates message_tpl = loader.get_template('customer/alerts/message.html') email_subject_tpl = loader.get_template( 'customer/alerts/emails/alert_subject.txt') email_body_tpl = loader.get_template( 'customer/alerts/emails/alert_body.txt') emails = [] num_notifications = 0 for alert in alerts: ctx = Context({ 'alert': alert, 'site': Site.objects.get_current(), 'hurry': hurry_mode, }) if alert.user: # Send a site notification num_notifications += 1 services.notify_user(alert.user, message_tpl.render(ctx)) # Build email and add to list emails.append( mail.EmailMessage( email_subject_tpl.render(ctx).strip(), email_body_tpl.render(ctx), settings.OSCAR_FROM_EMAIL, [alert.get_email_address()], )) alert.close() # Send all emails in one go to prevent multiple SMTP # connections to be opened connection = mail.get_connection() connection.open() connection.send_messages(emails) connection.close() logger.info("Sent %d notifications and %d emails", num_notifications, len(emails))
def test_notify_a_single_user(self): user = UserFactory() subj = "Hello you!" body = "This is the notification body." services.notify_user(user, subj, body=body) user_notification = Notification.objects.get(recipient=user) self.assertEqual(user_notification.subject, subj) self.assertEqual(user_notification.body, body)
def send_product_alerts(product): """ 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. """ if not product.has_stockrecord: return num_in_stock = product.stockrecord.num_in_stock if num_in_stock == 0: return logger.info(u"Sending alerts for '%s'", product) alerts = ProductAlert.objects.filter( product=product, status=ProductAlert.ACTIVE, ) hurry_mode = alerts.count() < product.stockrecord.num_in_stock # Load templates message_tpl = loader.get_template('customer/alerts/message.html') email_subject_tpl = loader.get_template('customer/alerts/emails/alert_subject.txt') email_body_tpl = loader.get_template('customer/alerts/emails/alert_body.txt') emails = [] num_notifications = 0 for alert in alerts: ctx = Context({ 'alert': alert, 'site': Site.objects.get_current(), 'hurry': hurry_mode, }) if alert.user: # Send a site notification num_notifications += 1 services.notify_user(alert.user, message_tpl.render(ctx)) # Build email and add to list emails.append( mail.EmailMessage( email_subject_tpl.render(ctx).strip(), email_body_tpl.render(ctx), settings.OSCAR_FROM_EMAIL, [alert.get_email_address()], ) ) alert.close() # Send all emails in one go to prevent multiple SMTP # connections to be opened if emails: connection = mail.get_connection() connection.open() connection.send_messages(emails) connection.close() logger.info(u"Sent %d notifications and %d emails", num_notifications, len(emails))
def send_product_alerts(product): # noqa C901 too complex C901太复杂了 """ 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 # 如果num_in_stock为None,则hurry_mode为false hurry_mode = num_in_stock is not None and alerts.count() > num_in_stock code = 'PRODUCT_ALERT' try: event_type = CommunicationEventType.objects.get(code=code) except CommunicationEventType.DoesNotExist: event_type = CommunicationEventType.objects.model(code=code) 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 # 构建消息并添加到列表中 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 # 使用一个SMTP连接发送所有邮件,以避免打开大量邮件 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 test_notify_a_single_user(self): user = G(User) services.notify_user(user, "Hello you!") self.assertEqual(1, Notification.objects.filter(recipient=user).count())
def send_product_alerts(product): """ 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=product, status=ProductAlert.ACTIVE, ) # Determine 'hurry mode' num_alerts = alerts.count() if num_stockrecords == 1: num_in_stock = stockrecords[0].num_in_stock hurry_mode = num_alerts < num_in_stock else: result = stockrecords.aggregate(max_in_stock=Max('num_in_stock')) hurry_mode = num_alerts < result['max_in_stock'] # Load templates message_tpl = loader.get_template('customer/alerts/message.html') email_subject_tpl = loader.get_template('customer/alerts/emails/alert_subject.txt') email_body_tpl = loader.get_template('customer/alerts/emails/alert_body.txt') emails = [] 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(product) if not data.availability.is_available_to_buy: continue ctx = Context({ 'alert': alert, 'site': Site.objects.get_current(), 'hurry': hurry_mode, }) if alert.user: # Send a site notification num_notifications += 1 services.notify_user(alert.user, message_tpl.render(ctx)) # Build email and add to list emails.append( mail.EmailMessage( email_subject_tpl.render(ctx).strip(), email_body_tpl.render(ctx), settings.OSCAR_FROM_EMAIL, [alert.get_email_address()], ) ) alert.close() # Send all emails in one go to prevent multiple SMTP # connections to be opened if emails: connection = mail.get_connection() connection.open() connection.send_messages(emails) connection.close() logger.info("Sent %d notifications and %d emails", num_notifications, len(emails))
def setUp(self): self.user = UserFactory() services.notify_user(self.user, "Test message")
def setUp(self): self.user = UserFactory() services.notify_user(self.user, "Test message")
def setUp(self): self.user = G(User) services.notify_user(self.user, "Test message")
def setUp(self): self.user = UserFactory() services.notify_user(self.user, TEST_MSG_TEXT)
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 test_notify_a_single_user(self): user = G(User) services.notify_user(user, "Hello you!") self.assertEqual(1, Notification.objects.filter( recipient=user).count())
def send_product_alerts(product): """ 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' num_alerts = alerts.count() if num_stockrecords == 1: num_in_stock = stockrecords[0].num_in_stock # hurry_mode is false if num_in_stock is None hurry_mode = num_in_stock is not None and num_alerts < num_in_stock else: result = stockrecords.aggregate(max_in_stock=Max('num_in_stock')) hurry_mode = result['max_in_stock'] is not None and \ num_alerts < result['max_in_stock'] # Load templates message_tpl = loader.get_template('customer/alerts/message.html') # Find or create the event type instance outside the loop message_code = 'PRODUCT_ALERT' try: event_type = CommunicationEventType.objects.get(code=message_code) except CommunicationEventType.DoesNotExist: event_type = CommunicationEventType.objects.model(code=message_code) num_emails = 0 num_notifications = 0 selector = Selector() emails_to_send = [] 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 = Context({ 'alert': alert, 'site': Site.objects.get_current(), 'hurry': hurry_mode, }) if alert.user: # Send a site notification num_notifications += 1 services.notify_user(alert.user, message_tpl.render(ctx)) messages = event_type.get_messages(ctx) if messages and messages['body']: num_emails += 1 emails_to_send.append( (alert.get_email_address(), messages) ) # Deactivate the alert for the current user alert.close() if emails_to_send: # Open a persistent SMTP connection connection = mail.get_connection() connection.open() # Remember to close after the loop for message in emails_to_send: Dispatcher().dispatch_direct_messages(*message, email_connection=connection) connection.close() logger.info("Sent %d notifications and %d emails", num_notifications, num_emails)
def setUp(self): self.user = G(User) services.notify_user(self.user, "Test message")
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): """ 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' num_alerts = alerts.count() if num_stockrecords == 1: num_in_stock = stockrecords[0].num_in_stock # hurry_mode is false if num_in_stock is None hurry_mode = num_in_stock is not None and num_alerts < num_in_stock else: result = stockrecords.aggregate(max_in_stock=Max('num_in_stock')) hurry_mode = result['max_in_stock'] is not None and \ num_alerts < result['max_in_stock'] # Load templates message_tpl = loader.get_template('customer/alerts/message.html') email_subject_tpl = loader.get_template('customer/alerts/emails/' 'alert_subject.txt') email_body_tpl = loader.get_template('customer/alerts/emails/' 'alert_body.txt') emails = [] 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 services.notify_user(alert.user, message_tpl.render(ctx)) # Build email and add to list emails.append( mail.EmailMessage( email_subject_tpl.render(ctx).strip(), email_body_tpl.render(ctx), settings.OSCAR_FROM_EMAIL, [alert.get_email_address()], )) alert.close() # Send all emails in one go to prevent multiple SMTP # connections to be opened if emails: connection = mail.get_connection() connection.open() connection.send_messages(emails) connection.close() logger.info("Sent %d notifications and %d emails", num_notifications, len(emails))
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 code = 'PRODUCT_ALERT' try: event_type = CommunicationEventType.objects.get(code=code) except CommunicationEventType.DoesNotExist: event_type = CommunicationEventType.objects.model(code=code) 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('oscar/customer/alerts/message_subject.html') message_tpl = loader.get_template('oscar/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 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))