Allow communication experiences to be customized per-learner
This commit is contained in:
committed by
Gabe Mulley
parent
908d5f91a5
commit
e5c8acb609
@@ -4,12 +4,17 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from . import models
|
||||
|
||||
|
||||
class ScheduleExperienceAdminInline(admin.StackedInline):
|
||||
model = models.ScheduleExperience
|
||||
|
||||
|
||||
@admin.register(models.Schedule)
|
||||
class ScheduleAdmin(admin.ModelAdmin):
|
||||
list_display = ('username', 'course_id', 'active', 'start', 'upgrade_deadline')
|
||||
raw_id_fields = ('enrollment',)
|
||||
readonly_fields = ('modified',)
|
||||
search_fields = ('enrollment__user__username', 'enrollment__course_id',)
|
||||
inlines = (ScheduleExperienceAdminInline,)
|
||||
|
||||
def username(self, obj):
|
||||
return obj.enrollment.user.username
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# -*- 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
|
||||
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):
|
||||
enrollment = models.OneToOneField('student.CourseEnrollment', null=False)
|
||||
active = models.BooleanField(
|
||||
@@ -23,6 +30,12 @@ class Schedule(TimeStampedModel):
|
||||
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):
|
||||
verbose_name = _('Schedule')
|
||||
verbose_name_plural = _('Schedules')
|
||||
@@ -39,3 +52,8 @@ class ScheduleConfig(ConfigurationModel):
|
||||
deliver_upgrade_reminder = models.BooleanField(default=False)
|
||||
enqueue_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
|
||||
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.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.template_context import (
|
||||
absolute_url,
|
||||
@@ -64,6 +64,7 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
|
||||
relative to. For example, if this resolver finds schedules that started 7 days ago
|
||||
this variable should be set to "start".
|
||||
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()
|
||||
site = attr.ib()
|
||||
@@ -74,6 +75,7 @@ class BinnedSchedulesBaseResolver(PrefixedDebugLoggerMixin, RecipientResolver):
|
||||
|
||||
schedule_date_field = None
|
||||
num_bins = DEFAULT_NUM_BINS
|
||||
experience_type = DEFAULT_EXPERIENCE_TYPE
|
||||
|
||||
def __attrs_post_init__(self):
|
||||
# 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):
|
||||
'enrollment__user__profile',
|
||||
'enrollment__course',
|
||||
).prefetch_related(
|
||||
'enrollment__course__modes'
|
||||
'enrollment__course__modes',
|
||||
'experience',
|
||||
).filter(
|
||||
Q(enrollment__course__end__isnull=True) | Q(
|
||||
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__is_active=True,
|
||||
**schedule_day_equals_target_day_filter
|
||||
@@ -333,6 +339,7 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver):
|
||||
log_prefix = 'Course Update'
|
||||
schedule_date_field = 'start'
|
||||
num_bins = COURSE_UPDATE_NUM_BINS
|
||||
experience_type = EXPERIENCE_TYPES[1][0]
|
||||
|
||||
def schedules_for_bin(self):
|
||||
week_num = abs(self.day_offset) / 7
|
||||
|
||||
Reference in New Issue
Block a user