diff --git a/openedx/core/djangoapps/schedules/management/commands/tests/test_send_upgrade_reminder.py b/openedx/core/djangoapps/schedules/management/commands/tests/test_send_upgrade_reminder.py index 13a214acab..67a8967d46 100644 --- a/openedx/core/djangoapps/schedules/management/commands/tests/test_send_upgrade_reminder.py +++ b/openedx/core/djangoapps/schedules/management/commands/tests/test_send_upgrade_reminder.py @@ -34,8 +34,9 @@ NUM_QUERIES_NO_MATCHING_SCHEDULES = 2 NUM_QUERIES_WITH_MATCHES = NUM_QUERIES_NO_MATCHING_SCHEDULES + 1 # 1) Global dynamic deadline switch +# 2) Course dynamic deadline switch # 2) E-commerce configuration -NUM_QUERIES_WITH_DEADLINE = 2 +NUM_QUERIES_WITH_DEADLINE = 3 NUM_COURSE_MODES_QUERIES = 1 @@ -233,7 +234,7 @@ class TestUpgradeReminder(FilteredQueryCountMixin, CacheIsolationTestCase): bin_num=user.id % tasks.UPGRADE_REMINDER_NUM_BINS, org_list=[schedules[0].enrollment.course.org], ) - self.assertEqual(mock_schedule_send.apply_async.call_count, 3) + self.assertEqual(mock_schedule_send.apply_async.call_count, 1) self.assertFalse(mock_ace.send.called) @ddt.data(*itertools.product((1, 10, 100), (2, 10))) @@ -281,7 +282,7 @@ class TestUpgradeReminder(FilteredQueryCountMixin, CacheIsolationTestCase): # we execute one query per course to see if it's opted out of dynamic upgrade deadlines, however, # since we create a new course for each schedule in this test, we expect there to be one per message - num_expected_queries = NUM_QUERIES_WITH_MATCHES + NUM_QUERIES_WITH_DEADLINE + message_count + num_expected_queries = NUM_QUERIES_WITH_MATCHES + NUM_QUERIES_WITH_DEADLINE with self.assertNumQueries(num_expected_queries, table_blacklist=WAFFLE_TABLES): tasks.upgrade_reminder_schedule_bin( self.site_config.site.id, target_day_str=test_datetime_str, day_offset=day, @@ -289,15 +290,15 @@ class TestUpgradeReminder(FilteredQueryCountMixin, CacheIsolationTestCase): org_list=[schedules[0].enrollment.course.org], ) - self.assertEqual(len(sent_messages), message_count) + self.assertEqual(len(sent_messages), 1) # Load the site (which we query per message sent) # Check the schedule config - with self.assertNumQueries(1 + message_count): + with self.assertNumQueries(2): for args in sent_messages: tasks._upgrade_reminder_schedule_send(*args) - self.assertEqual(mock_channel.deliver.call_count, message_count) + self.assertEqual(mock_channel.deliver.call_count, 1) for (_name, (_msg, email), _kwargs) in mock_channel.deliver.mock_calls: for template in attr.astuple(email): self.assertNotIn("TEMPLATE WARNING", template) diff --git a/openedx/core/djangoapps/schedules/tasks.py b/openedx/core/djangoapps/schedules/tasks.py index 0a4478936f..d878a3454d 100644 --- a/openedx/core/djangoapps/schedules/tasks.py +++ b/openedx/core/djangoapps/schedules/tasks.py @@ -222,26 +222,28 @@ def _upgrade_reminder_schedules_for_bin(site, current_datetime, target_datetime, 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 + 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, '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)])), + 'course_links': [ + { + 'url': absolute_url(site, reverse('course_root', args=[str(s.enrollment.course_id)])), + 'name': s.enrollment.course.display_name + } for s in user_schedules + ], + + 'first_course_name': first_schedule.enrollment.course.display_name, # 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')), }) diff --git a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html index 5c21e314e8..12e039b78c 100644 --- a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html +++ b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/body.html @@ -3,11 +3,24 @@ {% load static %} {% block preview_text %} - {% blocktrans trimmed %} - We hope you are enjoying learning with us so far in {{ course_name }}! A verified certificate - will allow you to highlight your new knowledge and skills. It's official, and easily shareable. + {% if course_ids|length > 1 %} + {% blocktrans trimmed %} + We hope you are enjoying learning with us so far on {{ platform_name }}! A verified certificate allows you to + highlight your new knowledge and skills. An {{ platform_name }} certificate is official and easily + shareable. - Upgrade by {{ user_schedule_upgrade_deadline_time }}. + Upgrade by {{ user_schedule_upgrade_deadline_time }}. + {% endblocktrans %} + {% else %} + {% blocktrans trimmed %} + We hope you are enjoying learning with us so far in {{ first_course_name }}! A verified certificate allows + you to highlight your new knowledge and skills. An {{ platform_name }} certificate is official and easily + shareable. + + Upgrade by {{ user_schedule_upgrade_deadline_time }}. + {% endblocktrans %} + {% endif %} + {% blocktrans trimmed %} {% endblocktrans %} {% endblock %} @@ -18,11 +31,19 @@

{% trans "Upgrade now" %}

- {% blocktrans trimmed %} - We hope you are enjoying learning with us so far in {{ course_name }}! A - verified certificate will allow you to highlight your new knowledge and skills. It's official, - and easily shareable. - {% endblocktrans %} + {% if course_ids|length > 1 %} + {% blocktrans trimmed %} + We hope you are enjoying learning with us so far on {{ platform_name }}! A + verified certificate allows you to highlight your new knowledge and skills. An {{ platform_name + }} certificate is official and easily shareable. + {% endblocktrans %} + {% else %} + {% blocktrans trimmed %} + We hope you are enjoying learning with us so far in {{ first_course_name }}! A + verified certificate allows you to highlight your new knowledge and skills. An {{ platform_name + }} certificate is official and easily shareable. + {% endblocktrans %} + {% endif %}

{% blocktrans trimmed %} @@ -30,27 +51,42 @@ {% endblocktrans %}

- - {% trans 'Example print-out of a verified certificate' %} - + {% if course_ids|length > 1 and course_ids|length < 10 %} +

+ {% trans "You are eligible to upgrade in these courses:" %} +

+ + {% endif %} + + {% trans 'Example print-out of a verified certificate' %}

{# email client support for style sheets is pretty spotty, so we have to inline all of these styles #} +{% else %} +{% blocktrans trimmed %} +We hope you are enjoying learning with us so far in {{ first_course_name }}! A verified certificate +allows you to highlight your new knowledge and skills. An {{ platform_name }} certificate is +official and easily shareable. Upgrade by {{ user_schedule_upgrade_deadline_time }}. {% endblocktrans %} {% trans "Upgrade now at" %} <{{ upsell_link }}> +{% endif %} diff --git a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/from_name.txt b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/from_name.txt index 08e86bddd0..9a58dc516b 100644 --- a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/from_name.txt +++ b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/from_name.txt @@ -1 +1,5 @@ -{{ course_name }} +{% if course_ids|length > 1 %} +{{ platform_name }} +{% else %} +{{ first_course_name }} +{% endif %} diff --git a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/subject.txt b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/subject.txt index 7daea3543a..585253a0d1 100644 --- a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/subject.txt +++ b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/upgradereminder/email/subject.txt @@ -1,3 +1,7 @@ {% load i18n %} -{% blocktrans %}Upgrade to earn a verified certificate in {{ course_name }}{% endblocktrans %} +{% if course_ids|length > 1 %} +{% blocktrans %}Upgrade to earn a verified certificate on {{ platform_name }}{% endblocktrans %} +{% else %} +{% blocktrans %}Upgrade to earn a verified certificate in {{ first_course_name }}{% endblocktrans %} +{% endif %}