def schedules_for_bin(self): schedules = self.get_schedules_with_target_date_by_bin_and_orgs() template_context = get_base_template_context(self.site) for (user, user_schedules) in groupby(schedules, lambda s: s.enrollment.user): user_schedules = list(user_schedules) course_id_strs = [ str(schedule.enrollment.course_id) for schedule in user_schedules ] # This is used by the bulk email optout policy template_context['course_ids'] = course_id_strs first_schedule = user_schedules[0] try: template_context.update( self.get_template_context(user, user_schedules)) except InvalidContextError: continue yield (user, first_schedule.enrollment.course.closest_released_language, template_context)
def schedules_for_bin(self): week_num = abs(self.day_offset) / 7 schedules = self.get_schedules_with_target_date_by_bin_and_orgs( order_by='enrollment__course', ) template_context = get_base_template_context(self.site) for schedule in schedules: enrollment = schedule.enrollment try: week_highlights = get_week_highlights(enrollment.course_id, week_num) except CourseUpdateDoesNotExist: continue user = enrollment.user course_id_str = str(enrollment.course_id) template_context.update({ 'course_name': schedule.enrollment.course.display_name, 'course_url': absolute_url(self.site, reverse('course_root', args=[course_id_str])), 'week_num': week_num, 'week_highlights': week_highlights, # This is used by the bulk email optout policy 'course_ids': [course_id_str], }) template_context.update( _get_upsell_information_for_schedule(user, schedule)) yield (user, schedule.enrollment.course.language, template_context)
def _build_message_context(context): message_context = get_base_template_context( Site.objects.get(id=context['site_id'])) message_context.update(_deserialize_context_dates(context)) message_context['post_link'] = _get_thread_url(context) message_context['ga_tracking_pixel_url'] = _generate_ga_pixel_url(context) return message_context
def schedules_for_bin(self): week_num = abs(self.day_offset) / 7 schedules = self.get_schedules_with_target_date_by_bin_and_orgs( order_by='enrollment__course', ) template_context = get_base_template_context(self.site) for schedule in schedules: enrollment = schedule.enrollment try: week_highlights = get_week_highlights(enrollment.course_id, week_num) except CourseUpdateDoesNotExist: continue user = enrollment.user course_id_str = str(enrollment.course_id) template_context.update({ 'course_name': schedule.enrollment.course.display_name, 'course_url': absolute_url( self.site, reverse('course_root', args=[course_id_str]) ), 'week_num': week_num, 'week_highlights': week_highlights, # This is used by the bulk email optout policy 'course_ids': [course_id_str], }) template_context.update(_get_upsell_information_for_schedule(user, schedule)) yield (user, schedule.enrollment.course.language, template_context)
def _recurring_nudge_schedules_for_bin(site, target_day, bin_num, org_list, exclude_orgs=False): beginning_of_day = target_day.replace(hour=0, minute=0, second=0) schedules = get_schedules_with_target_date_by_bin_and_orgs( schedule_date_field='start', target_date=beginning_of_day, bin_num=bin_num, num_bins=RECURRING_NUDGE_NUM_BINS, org_list=org_list, exclude_orgs=exclude_orgs, ) LOG.debug('Recurring Nudge: Query = %r', schedules.query.sql_with_params()) for (user, user_schedules) in groupby(schedules, lambda s: s.enrollment.user): user_schedules = list(user_schedules) course_id_strs = [str(schedule.enrollment.course_id) for schedule in user_schedules] first_schedule = user_schedules[0] template_context = get_base_template_context(site) template_context.update({ 'student_name': user.profile.name, 'course_name': first_schedule.enrollment.course.display_name, 'course_url': absolute_url(site, reverse('course_root', args=[str(first_schedule.enrollment.course_id)])), # This is used by the bulk email optout policy 'course_ids': course_id_strs, }) # Information for including upsell messaging in template. _add_upsell_button_information_to_template_context(user, first_schedule, template_context) yield (user, first_schedule.enrollment.course.language, template_context)
def _recurring_nudge_schedules_for_bin(site, current_datetime, target_datetime, bin_num, org_list, exclude_orgs=False): schedules = get_schedules_with_target_date_by_bin_and_orgs( schedule_date_field='start', current_datetime=current_datetime, target_datetime=target_datetime, bin_num=bin_num, num_bins=RECURRING_NUDGE_NUM_BINS, org_list=org_list, exclude_orgs=exclude_orgs, ) LOG.debug('Recurring Nudge: Query = %r', schedules.query.sql_with_params()) for (user, user_schedules) in groupby(schedules, lambda s: s.enrollment.user): user_schedules = list(user_schedules) course_id_strs = [str(schedule.enrollment.course_id) for schedule in user_schedules] first_schedule = user_schedules[0] template_context = get_base_template_context(site) template_context.update({ 'student_name': user.profile.name, 'course_name': first_schedule.enrollment.course.display_name, 'course_url': absolute_url(site, reverse('course_root', args=[str(first_schedule.enrollment.course_id)])), # This is used by the bulk email optout policy 'course_ids': course_id_strs, }) # Information for including upsell messaging in template. _add_upsell_button_information_to_template_context(user, first_schedule, template_context) yield (user, first_schedule.enrollment.course.language, template_context)
def _upgrade_reminder_schedules_for_bin(site, current_datetime, target_datetime, bin_num, org_list, exclude_orgs=False): schedules = get_schedules_with_target_date_by_bin_and_orgs( schedule_date_field='upgrade_deadline', current_datetime=current_datetime, target_datetime=target_datetime, bin_num=bin_num, num_bins=RECURRING_NUDGE_NUM_BINS, org_list=org_list, exclude_orgs=exclude_orgs, ) for schedule in schedules: enrollment = schedule.enrollment user = enrollment.user course_id_str = str(enrollment.course_id) # TODO: group by schedule and user like recurring nudge course_id_strs = [course_id_str] first_schedule = schedule template_context = get_base_template_context(site) template_context.update({ 'student_name': user.profile.name, 'user_personal_address': user.profile.name if user.profile.name else user.username, 'course_name': first_schedule.enrollment.course.display_name, 'course_url': absolute_url( site, reverse('course_root', args=[str(first_schedule.enrollment.course_id)])), # This is used by the bulk email optout policy 'course_ids': course_id_strs, 'cert_image': absolute_url(site, static('course_experience/images/verified-cert.png')), }) _add_upsell_button_information_to_template_context( user, first_schedule, template_context) yield (user, first_schedule.enrollment.course.language, template_context)
def _course_update_schedules_for_bin(site, current_datetime, target_datetime, day_offset, bin_num, org_list, exclude_orgs=False): week_num = abs(day_offset) / 7 schedules = get_schedules_with_target_date_by_bin_and_orgs( schedule_date_field='start', current_datetime=current_datetime, target_datetime=target_datetime, bin_num=bin_num, num_bins=COURSE_UPDATE_NUM_BINS, org_list=org_list, exclude_orgs=exclude_orgs, order_by='enrollment__course', ) for schedule in schedules: enrollment = schedule.enrollment try: week_summary = get_course_week_summary(enrollment.course_id, week_num) except CourseUpdateDoesNotExist: continue user = enrollment.user course_id_str = str(enrollment.course_id) template_context = get_base_template_context(site) template_context.update({ 'student_name': user.profile.name, 'user_personal_address': user.profile.name if user.profile.name else user.username, 'course_name': schedule.enrollment.course.display_name, 'course_url': absolute_url( site, reverse('course_root', args=[str(schedule.enrollment.course_id)])), 'week_num': week_num, 'week_summary': week_summary, # This is used by the bulk email optout policy 'course_ids': [course_id_str], }) yield (user, schedule.enrollment.course.language, template_context)
def test_send_discussion_email_notification(self, user_subscribed): if user_subscribed: non_matching_id = 'not-a-match' # with per_page left with a default value of 1, this ensures # that we test a multiple page result when calling # comment_client.User.subscribed_threads() subscribed_thread_ids = [non_matching_id, self.discussion_id] else: subscribed_thread_ids = [] self.mock_request.side_effect = make_mock_responder( subscribed_thread_ids=subscribed_thread_ids, comment_data=self.comment, thread_data=self.thread, ) user = mock.Mock() comment = cc.Comment.find(id=self.comment['id']).retrieve() site = Site.objects.get_current() site_config = SiteConfigurationFactory.create(site=site) site_config.values[ENABLE_FORUM_NOTIFICATIONS_FOR_SITE_KEY] = True site_config.save() with waffle().override(FORUM_RESPONSE_NOTIFICATIONS): with mock.patch('lms.djangoapps.discussion.signals.handlers.get_current_site', return_value=site): comment_created.send(sender=None, user=user, post=comment) if user_subscribed: expected_message_context = get_base_template_context(site) expected_message_context.update({ 'comment_author_id': self.comment_author.id, 'comment_body': self.comment['body'], 'comment_created_at': ONE_HOUR_AGO, 'comment_id': self.comment['id'], 'comment_username': self.comment_author.username, 'course_id': self.course.id, 'thread_author_id': self.thread_author.id, 'thread_created_at': TWO_HOURS_AGO, 'thread_id': self.discussion_id, 'thread_title': 'thread-title', 'thread_username': self.thread_author.username, 'thread_commentable_id': self.thread['commentable_id'], 'post_link': self.mock_permalink.return_value, 'site': site, 'site_id': site.id }) expected_recipient = Recipient(self.thread_author.username, self.thread_author.email) actual_message = self.mock_ace_send.call_args_list[0][0][0] self.assertEqual(expected_message_context, actual_message.context) self.assertEqual(expected_recipient, actual_message.recipient) self.assertEqual(self.course.language, actual_message.language) self._assert_rendered_email(actual_message) else: self.assertFalse(self.mock_ace_send.called)
def _build_message_context(context): message_context = get_base_template_context(context['site']) message_context.update(context) thread_author = User.objects.get(id=context['thread_author_id']) comment_author = User.objects.get(id=context['comment_author_id']) message_context.update({ 'thread_username': thread_author.username, 'comment_username': comment_author.username, 'post_link': _get_thread_url(context), 'comment_created_at': date.deserialize(context['comment_created_at']), 'thread_created_at': date.deserialize(context['thread_created_at']) }) return message_context
def _upgrade_reminder_schedules_for_bin(site, target_day, bin_num, org_list, exclude_orgs=False): beginning_of_day = target_day.replace(hour=0, minute=0, second=0) schedules = get_schedules_with_target_date_by_bin_and_orgs( schedule_date_field='upgrade_deadline', target_date=beginning_of_day, bin_num=bin_num, num_bins=RECURRING_NUDGE_NUM_BINS, org_list=org_list, exclude_orgs=exclude_orgs, ) LOG.debug('Upgrade Reminder: Query = %r', schedules.query.sql_with_params()) for schedule in schedules: enrollment = schedule.enrollment user = enrollment.user course_id_str = str(enrollment.course_id) # TODO: group by schedule and user like recurring nudge course_id_strs = [course_id_str] first_schedule = schedule template_context = get_base_template_context(site) template_context.update({ 'student_name': user.profile.name, 'user_personal_address': user.profile.name if user.profile.name else user.username, 'user_schedule_upgrade_deadline_time': dateformat.format( schedule.upgrade_deadline, get_format( 'DATE_FORMAT', lang=first_schedule.enrollment.course.language, use_l10n=True ) ), 'course_name': first_schedule.enrollment.course.display_name, 'course_url': absolute_url(site, reverse('course_root', args=[str(first_schedule.enrollment.course_id)])), # This is used by the bulk email optout policy 'course_ids': course_id_strs, 'cert_image': absolute_url(site, static('course_experience/images/verified-cert.png')), }) yield (user, first_schedule.enrollment.course.language, template_context)
def schedules_for_bin(self): schedules = self.get_schedules_with_target_date_by_bin_and_orgs() template_context = get_base_template_context(self.site) for (user, user_schedules) in groupby(schedules, lambda s: s.enrollment.user): user_schedules = list(user_schedules) course_id_strs = [str(schedule.enrollment.course_id) for schedule in user_schedules] # This is used by the bulk email optout policy template_context['course_ids'] = course_id_strs first_schedule = user_schedules[0] try: template_context.update(self.get_template_context(user, user_schedules)) except InvalidContextError: continue yield (user, first_schedule.enrollment.course.language, template_context)
def _course_update_schedules_for_bin(site, current_datetime, target_datetime, day_offset, bin_num, org_list, exclude_orgs=False): week_num = abs(day_offset) / 7 schedules = get_schedules_with_target_date_by_bin_and_orgs( schedule_date_field='start', current_datetime=current_datetime, target_datetime=target_datetime, bin_num=bin_num, num_bins=COURSE_UPDATE_NUM_BINS, org_list=org_list, exclude_orgs=exclude_orgs, order_by='enrollment__course', ) LOG.debug('Course Update: Query = %r', schedules.query.sql_with_params()) for schedule in schedules: enrollment = schedule.enrollment try: week_summary = get_course_week_summary(enrollment.course_id, week_num) except CourseUpdateDoesNotExist: continue user = enrollment.user course_id_str = str(enrollment.course_id) template_context = get_base_template_context(site) template_context.update({ 'student_name': user.profile.name, 'user_personal_address': user.profile.name if user.profile.name else user.username, 'course_name': schedule.enrollment.course.display_name, 'course_url': absolute_url(site, reverse('course_root', args=[str(schedule.enrollment.course_id)])), 'week_num': week_num, 'week_summary': week_summary, # This is used by the bulk email optout policy 'course_ids': [course_id_str], }) yield (user, schedule.enrollment.course.language, template_context)
def _upgrade_reminder_schedules_for_bin(site, current_datetime, target_datetime, bin_num, org_list, exclude_orgs=False): schedules = get_schedules_with_target_date_by_bin_and_orgs( schedule_date_field='upgrade_deadline', current_datetime=current_datetime, target_datetime=target_datetime, bin_num=bin_num, num_bins=RECURRING_NUDGE_NUM_BINS, org_list=org_list, exclude_orgs=exclude_orgs, ) LOG.debug('Upgrade Reminder: Query = %r', schedules.query.sql_with_params()) for schedule in schedules: enrollment = schedule.enrollment user = enrollment.user course_id_str = str(enrollment.course_id) # TODO: group by schedule and user like recurring nudge course_id_strs = [course_id_str] first_schedule = schedule template_context = get_base_template_context(site) template_context.update({ 'student_name': user.profile.name, 'user_personal_address': user.profile.name if user.profile.name else user.username, 'course_name': first_schedule.enrollment.course.display_name, 'course_url': absolute_url(site, reverse('course_root', args=[str(first_schedule.enrollment.course_id)])), # This is used by the bulk email optout policy 'course_ids': course_id_strs, 'cert_image': absolute_url(site, static('course_experience/images/verified-cert.png')), }) _add_upsell_button_information_to_template_context(user, first_schedule, template_context) yield (user, first_schedule.enrollment.course.language, template_context)
def schedules_for_bin(self): week_num = abs(self.day_offset) / 7 schedules = self.get_schedules_with_target_date_by_bin_and_orgs( order_by='enrollment__course', ) template_context = get_base_template_context(self.site) for schedule in schedules: enrollment = schedule.enrollment user = enrollment.user try: week_highlights = get_week_highlights(user, enrollment.course_id, week_num) except CourseUpdateDoesNotExist: LOG.exception( 'Weekly highlights for user {} in week {} of course {} does not exist or is disabled' .format(user, week_num, enrollment.course_id)) template_context.update({ 'course_name': schedule.enrollment.course.display_name, 'course_url': _get_trackable_course_home_url(enrollment.course_id), 'week_num': week_num, 'week_highlights': week_highlights, # This is used by the bulk email optout policy 'course_ids': [str(enrollment.course_id)], }) template_context.update( _get_upsell_information_for_schedule(user, schedule)) yield (user, schedule.enrollment.course.closest_released_language, template_context)
def test_send_discussion_email_notification(self, user_subscribed): with mock_the_things() as mocked_items: mock_request, mock_ace_send, mock_permalink = mocked_items if user_subscribed: non_matching_id = 'not-a-match' # with per_page left with a default value of 1, this ensures # that we test a multiple page result when calling # comment_client.User.subscribed_threads() mock_request.side_effect = make_mock_responder([non_matching_id, self.discussion_id]) else: mock_request.side_effect = make_mock_responder([]) now = datetime.utcnow() one_hour_ago = now - timedelta(hours=1) thread = mock.Mock( id=self.discussion_id, course_id=self.course.id, created_at=one_hour_ago, title='thread-title', user_id=self.thread_author.id, username=self.thread_author.username, commentable_id='thread-commentable-id' ) comment = mock.Mock( id='comment-id', body='comment-body', created_at=now, thread=thread, user_id=self.comment_author.id, username=self.comment_author.username ) user = mock.Mock() with waffle().override(FORUM_RESPONSE_NOTIFICATIONS): comment_created.send(sender=None, user=user, post=comment) if user_subscribed: expected_message_context = get_base_template_context(Site.objects.get_current()) expected_message_context.update({ 'comment_author_id': self.comment_author.id, 'comment_body': 'comment-body', 'comment_created_at': now, 'comment_id': 'comment-id', 'comment_username': self.comment_author.username, 'course_id': self.course.id, 'thread_author_id': self.thread_author.id, 'thread_created_at': one_hour_ago, 'thread_id': self.discussion_id, 'thread_title': 'thread-title', 'thread_username': self.thread_author.username, 'thread_commentable_id': 'thread-commentable-id', 'post_link': urljoin(Site.objects.get_current().domain, mock_permalink.return_value), 'site': Site.objects.get_current(), 'site_id': Site.objects.get_current().id, }) ga_tracking_pixel_url = _generate_ga_pixel_url(expected_message_context) expected_message_context.update({'ga_tracking_pixel_url': ga_tracking_pixel_url}) expected_recipient = Recipient(self.thread_author.username, self.thread_author.email) actual_message = mock_ace_send.call_args_list[0][0][0] self.assertEqual(expected_message_context, actual_message.context) self.assertEqual(expected_recipient, actual_message.recipient) self.assertEqual(self.course.language, actual_message.language) else: self.assertFalse(mock_ace_send.called)
def _build_message_context(context): message_context = get_base_template_context(context['site']) message_context.update(context) message_context['post_link'] = _get_thread_url(context) message_context['ga_tracking_pixel_url'] = _generate_ga_pixel_url(context) return message_context