Added expiration_datetime field to CourseModes
Added an expiration_datetime field to CourseModes, intended to eventually replace expiration_date. Included relevant schema and data migration file. LMS-1454
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
# Adding field 'CourseMode.expiration_datetime'
|
||||
db.add_column('course_modes_coursemode', 'expiration_datetime',
|
||||
self.gf('django.db.models.fields.DateTimeField')(default=None, null=True, blank=True),
|
||||
keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting field 'CourseMode.expiration_datetime'
|
||||
db.delete_column('course_modes_coursemode', 'expiration_datetime')
|
||||
|
||||
|
||||
models = {
|
||||
'course_modes.coursemode': {
|
||||
'Meta': {'unique_together': "(('course_id', 'mode_slug', 'currency'),)", 'object_name': 'CourseMode'},
|
||||
'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'expiration_date': ('django.db.models.fields.DateField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
|
||||
'expiration_datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'min_price': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'mode_display_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'mode_slug': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'suggested_prices': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'default': "''", 'max_length': '255', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['course_modes']
|
||||
@@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import DataMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(DataMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
from datetime import datetime
|
||||
for course_mode in orm.CourseMode.objects.all():
|
||||
if course_mode.expiration_date is None:
|
||||
course_mode.expiration_datetime = None
|
||||
course_mode.save()
|
||||
else:
|
||||
course_mode.expiration_datetime = datetime.combine(course_mode.expiration_date, datetime.min.time())
|
||||
course_mode.save()
|
||||
|
||||
def backwards(self, orm):
|
||||
for course_mode in orm.CourseMode.objects.all():
|
||||
course_mode.expiration_datetime = None
|
||||
course_mode.save()
|
||||
|
||||
models = {
|
||||
'course_modes.coursemode': {
|
||||
'Meta': {'unique_together': "(('course_id', 'mode_slug', 'currency'),)", 'object_name': 'CourseMode'},
|
||||
'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'currency': ('django.db.models.fields.CharField', [], {'default': "'usd'", 'max_length': '8'}),
|
||||
'expiration_date': ('django.db.models.fields.DateField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
|
||||
'expiration_datetime': ('django.db.models.fields.DateTimeField', [], {'default': 'None', 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'min_price': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
|
||||
'mode_display_name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'mode_slug': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'suggested_prices': ('django.db.models.fields.CommaSeparatedIntegerField', [], {'default': "''", 'max_length': '255', 'blank': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['course_modes']
|
||||
symmetrical = True
|
||||
@@ -9,7 +9,7 @@ from collections import namedtuple
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.db.models import Q
|
||||
|
||||
Mode = namedtuple('Mode', ['slug', 'name', 'min_price', 'suggested_prices', 'currency', 'expiration_date'])
|
||||
Mode = namedtuple('Mode', ['slug', 'name', 'min_price', 'suggested_prices', 'currency', 'expiration_datetime'])
|
||||
|
||||
class CourseMode(models.Model):
|
||||
"""
|
||||
@@ -38,6 +38,8 @@ class CourseMode(models.Model):
|
||||
# turn this mode off after the given expiration date
|
||||
expiration_date = models.DateField(default=None, null=True, blank=True)
|
||||
|
||||
expiration_datetime = models.DateTimeField(default=None, null=True, blank=True)
|
||||
|
||||
DEFAULT_MODE = Mode('honor', _('Honor Code Certificate'), 0, '', 'usd', None)
|
||||
DEFAULT_MODE_SLUG = 'honor'
|
||||
|
||||
@@ -54,15 +56,15 @@ class CourseMode(models.Model):
|
||||
"""
|
||||
now = datetime.now(pytz.UTC)
|
||||
found_course_modes = cls.objects.filter(Q(course_id=course_id) &
|
||||
(Q(expiration_date__isnull=True) |
|
||||
Q(expiration_date__gte=now)))
|
||||
(Q(expiration_datetime__isnull=True) |
|
||||
Q(expiration_datetime__gte=now)))
|
||||
modes = ([Mode(
|
||||
mode.mode_slug,
|
||||
mode.mode_display_name,
|
||||
mode.min_price,
|
||||
mode.suggested_prices,
|
||||
mode.currency,
|
||||
mode.expiration_date
|
||||
mode.expiration_datetime
|
||||
) for mode in found_course_modes])
|
||||
if not modes:
|
||||
modes = [cls.DEFAULT_MODE]
|
||||
|
||||
@@ -11,4 +11,4 @@ class CourseModeFactory(DjangoModelFactory):
|
||||
mode_display_name = 'audit course'
|
||||
min_price = 0
|
||||
currency = 'usd'
|
||||
expiration_date = None
|
||||
expiration_datetime = None
|
||||
|
||||
@@ -93,7 +93,7 @@ class CourseModeModelTest(TestCase):
|
||||
|
||||
def test_modes_for_course_expired(self):
|
||||
expired_mode, _status = self.create_mode('verified', 'Verified Certificate')
|
||||
expired_mode.expiration_date = datetime.now(pytz.UTC) + timedelta(days=-1)
|
||||
expired_mode.expiration_datetime = datetime.now(pytz.UTC) + timedelta(days=-1)
|
||||
expired_mode.save()
|
||||
modes = CourseMode.modes_for_course(self.course_id)
|
||||
self.assertEqual([CourseMode.DEFAULT_MODE], modes)
|
||||
@@ -103,10 +103,10 @@ class CourseModeModelTest(TestCase):
|
||||
modes = CourseMode.modes_for_course(self.course_id)
|
||||
self.assertEqual([mode1], modes)
|
||||
|
||||
expiration_date = datetime.now(pytz.UTC) + timedelta(days=1)
|
||||
expired_mode.expiration_date = expiration_date
|
||||
expiration_datetime = datetime.now(pytz.UTC) + timedelta(days=1)
|
||||
expired_mode.expiration_datetime = expiration_datetime
|
||||
expired_mode.save()
|
||||
expired_mode_value = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', expiration_date.date())
|
||||
expired_mode_value = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', expiration_datetime)
|
||||
modes = CourseMode.modes_for_course(self.course_id)
|
||||
self.assertEqual([expired_mode_value, mode1], modes)
|
||||
|
||||
|
||||
@@ -243,14 +243,14 @@ class DashboardTest(TestCase):
|
||||
course_id=self.course.id,
|
||||
mode_slug='verified',
|
||||
mode_display_name='Verified',
|
||||
expiration_date=(datetime.now(pytz.UTC) + timedelta(days=1)).date()
|
||||
expiration_datetime=datetime.now(pytz.UTC) + timedelta(days=1)
|
||||
)
|
||||
enrollment = CourseEnrollment.enroll(self.user, self.course.id)
|
||||
course_mode_info = complete_course_mode_info(self.course.id, enrollment)
|
||||
self.assertTrue(course_mode_info['show_upsell'])
|
||||
self.assertEquals(course_mode_info['days_for_upsell'], 1)
|
||||
|
||||
verified_mode.expiration_date = datetime.now(pytz.UTC) + timedelta(days=-1)
|
||||
verified_mode.expiration_datetime = datetime.now(pytz.UTC) + timedelta(days=-1)
|
||||
verified_mode.save()
|
||||
course_mode_info = complete_course_mode_info(self.course.id, enrollment)
|
||||
self.assertFalse(course_mode_info['show_upsell'])
|
||||
@@ -261,13 +261,13 @@ class DashboardTest(TestCase):
|
||||
course_id=self.course.id,
|
||||
mode_slug='verified',
|
||||
mode_display_name='Verified',
|
||||
expiration_date=(datetime.now(pytz.UTC) + timedelta(days=1)).date()
|
||||
expiration_datetime=datetime.now(pytz.UTC) + timedelta(days=1)
|
||||
)
|
||||
enrollment = CourseEnrollment.enroll(self.user, self.course.id, mode='verified')
|
||||
|
||||
self.assertTrue(enrollment.refundable())
|
||||
|
||||
verified_mode.expiration_date = (datetime.now(pytz.UTC) - timedelta(days=1)).date()
|
||||
verified_mode.expiration_datetime = datetime.now(pytz.UTC) - timedelta(days=1)
|
||||
verified_mode.save()
|
||||
self.assertFalse(enrollment.refundable())
|
||||
|
||||
|
||||
@@ -284,9 +284,9 @@ def complete_course_mode_info(course_id, enrollment):
|
||||
if 'verified' in modes and enrollment.mode != 'verified':
|
||||
mode_info['show_upsell'] = True
|
||||
# if there is an expiration date, find out how long from now it is
|
||||
if modes['verified'].expiration_date:
|
||||
if modes['verified'].expiration_datetime:
|
||||
today = datetime.datetime.now(UTC).date()
|
||||
mode_info['days_for_upsell'] = (modes['verified'].expiration_date - today).days
|
||||
mode_info['days_for_upsell'] = (modes['verified'].expiration_datetime.date() - today).days
|
||||
|
||||
return mode_info
|
||||
|
||||
|
||||
@@ -384,7 +384,7 @@ class CertificateItemTest(ModuleStoreTestCase):
|
||||
mode_slug="verified",
|
||||
mode_display_name="verified cert",
|
||||
min_price=self.cost,
|
||||
expiration_date=(datetime.datetime.now(pytz.utc).date() + many_days))
|
||||
expiration_datetime=(datetime.datetime.now(pytz.utc) + many_days))
|
||||
course_mode.save()
|
||||
|
||||
CourseEnrollment.enroll(self.user, course_id, 'verified')
|
||||
@@ -407,7 +407,7 @@ class CertificateItemTest(ModuleStoreTestCase):
|
||||
mode_slug="verified",
|
||||
mode_display_name="verified cert",
|
||||
min_price=self.cost,
|
||||
expiration_date=(datetime.datetime.now(pytz.utc).date() + many_days))
|
||||
expiration_datetime=datetime.datetime.now(pytz.utc) + many_days)
|
||||
course_mode.save()
|
||||
|
||||
CourseEnrollment.enroll(self.user, course_id, 'verified')
|
||||
@@ -436,7 +436,7 @@ class CertificateItemTest(ModuleStoreTestCase):
|
||||
CertificateItem.add_to_order(cart, course_id, self.cost, 'verified')
|
||||
cart.purchase()
|
||||
|
||||
course_mode.expiration_date = (datetime.datetime.now(pytz.utc).date() - many_days)
|
||||
course_mode.expiration_datetime = (datetime.datetime.now(pytz.utc) - many_days)
|
||||
course_mode.save()
|
||||
|
||||
CourseEnrollment.unenroll(self.user, course_id)
|
||||
|
||||
Reference in New Issue
Block a user