Switch ContentTypeGatingConfig.enabled_as_of and CourseDurationLimitConfig.enabled_as_of to datetimes
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.16 on 2018-11-28 19:07
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('course_duration_limits', '0002_auto_20181119_0959'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='coursedurationlimitconfig',
|
||||
name='enabled_as_of',
|
||||
field=models.DateTimeField(blank=True, default=None, help_text='If the configuration is Enabled, then all enrollments created after this date (UTC) will be affected.', null=True, verbose_name='Enabled As Of'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.16 on 2018-11-28 20:21
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('course_duration_limits', '0003_auto_20181128_1407'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='coursedurationlimitconfig',
|
||||
name='enabled_as_of',
|
||||
field=models.DateTimeField(blank=True, default=None, help_text='If the configuration is Enabled, then all enrollments created after this date and time (UTC) will be affected.', null=True, verbose_name='Enabled As Of'),
|
||||
),
|
||||
]
|
||||
@@ -5,11 +5,11 @@ Course Duration Limit Configuration Models
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from datetime import datetime
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.utils.encoding import python_2_unicode_compatible
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils import timezone
|
||||
|
||||
from experiments.models import ExperimentData
|
||||
from student.models import CourseEnrollment
|
||||
@@ -29,14 +29,14 @@ class CourseDurationLimitConfig(StackedConfigurationModel):
|
||||
|
||||
STACKABLE_FIELDS = ('enabled', 'enabled_as_of')
|
||||
|
||||
enabled_as_of = models.DateField(
|
||||
enabled_as_of = models.DateTimeField(
|
||||
default=None,
|
||||
null=True,
|
||||
verbose_name=_('Enabled As Of'),
|
||||
blank=True,
|
||||
help_text=_(
|
||||
'If the configuration is Enabled, then all enrollments '
|
||||
'created after this date (UTC) will be affected.'
|
||||
'created after this date and time (UTC) will be affected.'
|
||||
)
|
||||
)
|
||||
|
||||
@@ -78,7 +78,7 @@ class CourseDurationLimitConfig(StackedConfigurationModel):
|
||||
# enrollment might be None if the user isn't enrolled. In that case,
|
||||
# return enablement as if the user enrolled today
|
||||
if enrollment is None:
|
||||
return cls.enabled_for_course(course_key=course_key, target_date=datetime.utcnow().date())
|
||||
return cls.enabled_for_course(course_key=course_key, target_datetime=timezone.now())
|
||||
else:
|
||||
# TODO: clean up as part of REV-100
|
||||
experiment_data_holdback_key = EXPERIMENT_DATA_HOLDBACK_KEY.format(user)
|
||||
@@ -95,48 +95,48 @@ class CourseDurationLimitConfig(StackedConfigurationModel):
|
||||
if is_in_holdback:
|
||||
return False
|
||||
current_config = cls.current(course_key=enrollment.course_id)
|
||||
return current_config.enabled_as_of_date(target_date=enrollment.created.date())
|
||||
return current_config.enabled_as_of_datetime(target_datetime=enrollment.created)
|
||||
|
||||
@classmethod
|
||||
def enabled_for_course(cls, course_key, target_date=None):
|
||||
def enabled_for_course(cls, course_key, target_datetime=None):
|
||||
"""
|
||||
Return whether Course Duration Limits are enabled for this course as of a particular date.
|
||||
|
||||
Course Duration Limits are enabled for a course on a date if they are enabled either specifically,
|
||||
or via a containing context, such as the org, site, or globally, and if the configuration
|
||||
is specified to be ``enabled_as_of`` before ``target_date``.
|
||||
is specified to be ``enabled_as_of`` before ``target_datetime``.
|
||||
|
||||
Only one of enrollment and (user, course_key) may be specified at a time.
|
||||
|
||||
Arguments:
|
||||
course_key: The CourseKey of the course being queried.
|
||||
target_date: The date to checked enablement as of. Defaults to the current date.
|
||||
target_datetime: The datetime to checked enablement as of. Defaults to the current date and time.
|
||||
"""
|
||||
if CONTENT_TYPE_GATING_FLAG.is_enabled():
|
||||
return True
|
||||
|
||||
if target_date is None:
|
||||
target_date = datetime.utcnow().date()
|
||||
if target_datetime is None:
|
||||
target_datetime = timezone.now()
|
||||
|
||||
current_config = cls.current(course_key=course_key)
|
||||
return current_config.enabled_as_of_date(target_date=target_date)
|
||||
return current_config.enabled_as_of_datetime(target_datetime=target_datetime)
|
||||
|
||||
def clean(self):
|
||||
if self.enabled and self.enabled_as_of is None:
|
||||
raise ValidationError({'enabled_as_of': _('enabled_as_of must be set when enabled is True')})
|
||||
|
||||
def enabled_as_of_date(self, target_date):
|
||||
def enabled_as_of_datetime(self, target_datetime):
|
||||
"""
|
||||
Return whether this Course Duration Limit configuration context is enabled as of a date.
|
||||
Return whether this Course Duration Limit configuration context is enabled as of a date and time.
|
||||
|
||||
Arguments:
|
||||
target_date (:class:`datetime.date`): The date that ``enabled_as_of`` must be equal to or before
|
||||
target_datetime (:class:`datetime.datetime`): The datetime that ``enabled_as_of`` must be equal to or before
|
||||
"""
|
||||
if CONTENT_TYPE_GATING_FLAG.is_enabled():
|
||||
return True
|
||||
|
||||
# Explicitly cast this to bool, so that when self.enabled is None the method doesn't return None
|
||||
return bool(self.enabled and self.enabled_as_of <= target_date)
|
||||
return bool(self.enabled and self.enabled_as_of <= target_datetime)
|
||||
|
||||
def __str__(self):
|
||||
return "CourseDurationLimits(enabled={!r}, enabled_as_of={!r})".format(
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
Tests of CourseDurationLimitConfig.
|
||||
"""
|
||||
|
||||
from datetime import timedelta, date
|
||||
from datetime import timedelta, datetime
|
||||
import itertools
|
||||
|
||||
import ddt
|
||||
from django.utils import timezone
|
||||
from mock import Mock
|
||||
|
||||
from openedx.core.djangoapps.site_configuration.tests.factories import SiteConfigurationFactory
|
||||
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
|
||||
from openedx.core.djangoapps.waffle_utils.testutils import override_waffle_flag
|
||||
@@ -46,12 +46,12 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
enrolled_before_enabled,
|
||||
):
|
||||
|
||||
# Tweak the day to enable the config so that it is either before
|
||||
# or after today (which is when the enrollment will be created)
|
||||
# Tweak the datetime to enable the config so that it is either before
|
||||
# or after now (which is when the enrollment will be created)
|
||||
if enrolled_before_enabled:
|
||||
enabled_as_of = date.today() + timedelta(days=1)
|
||||
enabled_as_of = timezone.now() + timedelta(days=1)
|
||||
else:
|
||||
enabled_as_of = date.today() - timedelta(days=1)
|
||||
enabled_as_of = timezone.now() - timedelta(days=1)
|
||||
|
||||
CourseDurationLimitConfig.objects.create(
|
||||
enabled=True,
|
||||
@@ -130,15 +130,15 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
config = CourseDurationLimitConfig.objects.create(
|
||||
enabled=True,
|
||||
course=self.course_overview,
|
||||
enabled_as_of=date.today(),
|
||||
enabled_as_of=timezone.now(),
|
||||
)
|
||||
|
||||
# Tweak the day to check for course enablement so it is either
|
||||
# Tweak the datetime to check for course enablement so it is either
|
||||
# before or after when the configuration was enabled
|
||||
if before_enabled:
|
||||
target_date = config.enabled_as_of - timedelta(days=1)
|
||||
target_datetime = config.enabled_as_of - timedelta(days=1)
|
||||
else:
|
||||
target_date = config.enabled_as_of + timedelta(days=1)
|
||||
target_datetime = config.enabled_as_of + timedelta(days=1)
|
||||
|
||||
course_key = self.course_overview.id
|
||||
|
||||
@@ -146,7 +146,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
not before_enabled,
|
||||
CourseDurationLimitConfig.enabled_for_course(
|
||||
course_key=course_key,
|
||||
target_date=target_date,
|
||||
target_datetime=target_datetime,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -200,7 +200,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
self.assertEqual(expected_course_setting, CourseDurationLimitConfig.current(course_key=test_course.id).enabled)
|
||||
|
||||
def test_caching_global(self):
|
||||
global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=date(2018, 1, 1))
|
||||
global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1))
|
||||
global_config.save()
|
||||
|
||||
# Check that the global value is not retrieved from cache after save
|
||||
@@ -220,7 +220,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
|
||||
def test_caching_site(self):
|
||||
site_cfg = SiteConfigurationFactory()
|
||||
site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=date(2018, 1, 1))
|
||||
site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1))
|
||||
site_config.save()
|
||||
|
||||
# Check that the site value is not retrieved from cache after save
|
||||
@@ -238,7 +238,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
with self.assertNumQueries(1):
|
||||
self.assertFalse(CourseDurationLimitConfig.current(site=site_cfg.site).enabled)
|
||||
|
||||
global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=date(2018, 1, 1))
|
||||
global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1))
|
||||
global_config.save()
|
||||
|
||||
# Check that the site value is not updated in cache by changing the global value
|
||||
@@ -248,7 +248,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
def test_caching_org(self):
|
||||
course = CourseOverviewFactory.create(org='test-org')
|
||||
site_cfg = SiteConfigurationFactory.create(values={'course_org_filter': course.org})
|
||||
org_config = CourseDurationLimitConfig(org=course.org, enabled=True, enabled_as_of=date(2018, 1, 1))
|
||||
org_config = CourseDurationLimitConfig(org=course.org, enabled=True, enabled_as_of=datetime(2018, 1, 1))
|
||||
org_config.save()
|
||||
|
||||
# Check that the org value is not retrieved from cache after save
|
||||
@@ -266,14 +266,14 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
with self.assertNumQueries(2):
|
||||
self.assertFalse(CourseDurationLimitConfig.current(org=course.org).enabled)
|
||||
|
||||
global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=date(2018, 1, 1))
|
||||
global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1))
|
||||
global_config.save()
|
||||
|
||||
# Check that the org value is not updated in cache by changing the global value
|
||||
with self.assertNumQueries(0):
|
||||
self.assertFalse(CourseDurationLimitConfig.current(org=course.org).enabled)
|
||||
|
||||
site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=date(2018, 1, 1))
|
||||
site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1))
|
||||
site_config.save()
|
||||
|
||||
# Check that the org value is not updated in cache by changing the site value
|
||||
@@ -283,7 +283,7 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
def test_caching_course(self):
|
||||
course = CourseOverviewFactory.create(org='test-org')
|
||||
site_cfg = SiteConfigurationFactory.create(values={'course_org_filter': course.org})
|
||||
course_config = CourseDurationLimitConfig(course=course, enabled=True, enabled_as_of=date(2018, 1, 1))
|
||||
course_config = CourseDurationLimitConfig(course=course, enabled=True, enabled_as_of=datetime(2018, 1, 1))
|
||||
course_config.save()
|
||||
|
||||
# Check that the org value is not retrieved from cache after save
|
||||
@@ -301,21 +301,21 @@ class TestCourseDurationLimitConfig(CacheIsolationTestCase):
|
||||
with self.assertNumQueries(2):
|
||||
self.assertFalse(CourseDurationLimitConfig.current(course_key=course.id).enabled)
|
||||
|
||||
global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=date(2018, 1, 1))
|
||||
global_config = CourseDurationLimitConfig(enabled=True, enabled_as_of=datetime(2018, 1, 1))
|
||||
global_config.save()
|
||||
|
||||
# Check that the org value is not updated in cache by changing the global value
|
||||
with self.assertNumQueries(0):
|
||||
self.assertFalse(CourseDurationLimitConfig.current(course_key=course.id).enabled)
|
||||
|
||||
site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=date(2018, 1, 1))
|
||||
site_config = CourseDurationLimitConfig(site=site_cfg.site, enabled=True, enabled_as_of=datetime(2018, 1, 1))
|
||||
site_config.save()
|
||||
|
||||
# Check that the org value is not updated in cache by changing the site value
|
||||
with self.assertNumQueries(0):
|
||||
self.assertFalse(CourseDurationLimitConfig.current(course_key=course.id).enabled)
|
||||
|
||||
org_config = CourseDurationLimitConfig(org=course.org, enabled=True, enabled_as_of=date(2018, 1, 1))
|
||||
org_config = CourseDurationLimitConfig(org=course.org, enabled=True, enabled_as_of=datetime(2018, 1, 1))
|
||||
org_config.save()
|
||||
|
||||
# Check that the org value is not updated in cache by changing the site value
|
||||
|
||||
Reference in New Issue
Block a user