Unverified Commit e5c8acb6 by Tyler Hallada Committed by Gabe Mulley

Allow communication experiences to be customized per-learner

parent 908d5f91
...@@ -4,12 +4,17 @@ from django.utils.translation import ugettext_lazy as _ ...@@ -4,12 +4,17 @@ from django.utils.translation import ugettext_lazy as _
from . import models from . import models
class ScheduleExperienceAdminInline(admin.StackedInline):
model = models.ScheduleExperience
@admin.register(models.Schedule) @admin.register(models.Schedule)
class ScheduleAdmin(admin.ModelAdmin): class ScheduleAdmin(admin.ModelAdmin):
list_display = ('username', 'course_id', 'active', 'start', 'upgrade_deadline') list_display = ('username', 'course_id', 'active', 'start', 'upgrade_deadline')
raw_id_fields = ('enrollment',) raw_id_fields = ('enrollment',)
readonly_fields = ('modified',) readonly_fields = ('modified',)
search_fields = ('enrollment__user__username', 'enrollment__course_id',) search_fields = ('enrollment__user__username', 'enrollment__course_id',)
inlines = (ScheduleExperienceAdminInline,)
def username(self, obj): def username(self, obj):
return obj.enrollment.user.username return obj.enrollment.user.username
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('schedules', '0005_auto_20171010_1722'),
]
operations = [
migrations.CreateModel(
name='ScheduleExperience',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('experience_type', models.IntegerField(default=0, choices=[(0, b'Recurring Nudge and Upgrade Reminder'), (1, b'Course Updates')])),
('schedule', models.OneToOneField(related_name='experience', to='schedules.Schedule')),
],
),
]
...@@ -6,6 +6,13 @@ from model_utils.models import TimeStampedModel ...@@ -6,6 +6,13 @@ from model_utils.models import TimeStampedModel
from config_models.models import ConfigurationModel from config_models.models import ConfigurationModel
EXPERIENCE_TYPES = (
(0, 'Recurring Nudge and Upgrade Reminder'),
(1, 'Course Updates'),
)
DEFAULT_EXPERIENCE_TYPE = EXPERIENCE_TYPES[0][0]
class Schedule(TimeStampedModel): class Schedule(TimeStampedModel):
enrollment = models.OneToOneField('student.CourseEnrollment', null=False) enrollment = models.OneToOneField('student.CourseEnrollment', null=False)
active = models.BooleanField( active = models.BooleanField(
...@@ -23,6 +30,12 @@ class Schedule(TimeStampedModel): ...@@ -23,6 +30,12 @@ class Schedule(TimeStampedModel):
help_text=_('Deadline by which the learner must upgrade to a verified seat') help_text=_('Deadline by which the learner must upgrade to a verified seat')
) )
def get_experience_type(self):
if (hasattr(self, 'experience')):
return self.experience.experience_type
else:
return DEFAULT_EXPERIENCE_TYPE
class Meta(object): class Meta(object):
verbose_name = _('Schedule') verbose_name = _('Schedule')
verbose_name_plural = _('Schedules') verbose_name_plural = _('Schedules')
...@@ -39,3 +52,8 @@ class ScheduleConfig(ConfigurationModel): ...@@ -39,3 +52,8 @@ class ScheduleConfig(ConfigurationModel):
deliver_upgrade_reminder = models.BooleanField(default=False) deliver_upgrade_reminder = models.BooleanField(default=False)
enqueue_course_update = models.BooleanField(default=False) enqueue_course_update = models.BooleanField(default=False)
deliver_course_update = models.BooleanField(default=False) deliver_course_update = models.BooleanField(default=False)
class ScheduleExperience(models.Model):
schedule = models.OneToOneField(Schedule, related_name='experience')
experience_type = models.IntegerField(choices=EXPERIENCE_TYPES, default=DEFAULT_EXPERIENCE_TYPE)
...@@ -18,7 +18,7 @@ from courseware.date_summary import verified_upgrade_deadline_link, verified_upg ...@@ -18,7 +18,7 @@ from courseware.date_summary import verified_upgrade_deadline_link, verified_upg
from openedx.core.djangoapps.monitoring_utils import function_trace, set_custom_metric from openedx.core.djangoapps.monitoring_utils import function_trace, set_custom_metric
from openedx.core.djangoapps.schedules.config import COURSE_UPDATE_WAFFLE_FLAG from openedx.core.djangoapps.schedules.config import COURSE_UPDATE_WAFFLE_FLAG
from openedx.core.djangoapps.schedules.exceptions import CourseUpdateDoesNotExist from openedx.core.djangoapps.schedules.exceptions import CourseUpdateDoesNotExist
from openedx.core.djangoapps.schedules.models import Schedule from openedx.core.djangoapps.schedules.models import DEFAULT_EXPERIENCE_TYPE, EXPERIENCE_TYPES, Schedule
from openedx.core.djangoapps.schedules.utils import PrefixedDebugLoggerMixin from openedx.core.djangoapps.schedules.utils import PrefixedDebugLoggerMixin
from openedx.core.djangoapps.schedules.template_context import ( from openedx.core.djangoapps.schedules.template_context import (
absolute_url, absolute_url,
...@@ -64,6 +64,7 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver): ...@@ -64,6 +64,7 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
relative to. For example, if this resolver finds schedules that started 7 days ago relative to. For example, if this resolver finds schedules that started 7 days ago
this variable should be set to "start". this variable should be set to "start".
num_bins -- the int number of bins to split the users into num_bins -- the int number of bins to split the users into
experience_type -- the string name for the experience type that users will be filtered to
""" """
async_send_task = attr.ib() async_send_task = attr.ib()
site = attr.ib() site = attr.ib()
...@@ -74,6 +75,7 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver): ...@@ -74,6 +75,7 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
schedule_date_field = None schedule_date_field = None
num_bins = DEFAULT_NUM_BINS num_bins = DEFAULT_NUM_BINS
experience_type = DEFAULT_EXPERIENCE_TYPE
def __attrs_post_init__(self): def __attrs_post_init__(self):
# TODO: in the next refactor of this task, pass in current_datetime instead of reproducing it here # TODO: in the next refactor of this task, pass in current_datetime instead of reproducing it here
...@@ -123,10 +125,14 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver): ...@@ -123,10 +125,14 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
'enrollment__user__profile', 'enrollment__user__profile',
'enrollment__course', 'enrollment__course',
).prefetch_related( ).prefetch_related(
'enrollment__course__modes' 'enrollment__course__modes',
'experience',
).filter( ).filter(
Q(enrollment__course__end__isnull=True) | Q( Q(enrollment__course__end__isnull=True) | Q(
enrollment__course__end__gte=self.current_datetime), enrollment__course__end__gte=self.current_datetime),
Q(experience__isnull=True) | Q(experience__experience_type=self.experience_type)
if self.experience_type == DEFAULT_EXPERIENCE_TYPE else
Q(experience__isnull=False) & Q(experience__experience_type=self.experience_type),
enrollment__user__in=users, enrollment__user__in=users,
enrollment__is_active=True, enrollment__is_active=True,
**schedule_day_equals_target_day_filter **schedule_day_equals_target_day_filter
...@@ -333,6 +339,7 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver): ...@@ -333,6 +339,7 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
log_prefix = 'Course Update' log_prefix = 'Course Update'
schedule_date_field = 'start' schedule_date_field = 'start'
num_bins = COURSE_UPDATE_NUM_BINS num_bins = COURSE_UPDATE_NUM_BINS
experience_type = EXPERIENCE_TYPES[1][0]
def schedules_for_bin(self): def schedules_for_bin(self):
week_num = abs(self.day_offset) / 7 week_num = abs(self.day_offset) / 7
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment